bochs-2.6/0000755000175000017500000000000012077504621012341 5ustar guillemguillembochs-2.6/COPYING0000644000175000017500000006347412020641507013403 0ustar guillemguillem GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! bochs-2.6/.conf.everything0000644000175000017500000000171312020641507015445 0ustar guillemguillem# This script tries to turn on nearly every configure option. # It is useful for finding compile problems, but it may turn on # more things than you actually want. ./configure \ --enable-smp \ --enable-x86-64 \ --enable-all-optimizations \ --enable-long-phy-address \ --enable-configurable-msrs \ --enable-debugger \ --enable-disasm \ --enable-debugger-gui \ --enable-fpu \ --enable-misaligned-sse \ --enable-alignment-check \ --enable-3dnow \ --enable-monitor-mwait \ --enable-svm \ --enable-vmx \ --enable-avx \ --enable-x86-debugger \ --enable-a20-pin \ --enable-instrumentation=instrument/example1 \ --enable-ne2000 \ --enable-e1000 \ --enable-pci \ --enable-clgd54xx \ --enable-usb \ --enable-usb-ohci \ --enable-usb-xhci \ --enable-cdrom \ --enable-sb16 \ --enable-es1370 \ --enable-gameport \ --enable-iodebug \ --enable-large-ramfile \ --enable-gdb-stub \ --enable-show-ips \ --with-all-libs bochs-2.6/cpudb.h0000644000175000017500000000353312020641507013604 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cpudb.h 11196 2012-05-26 19:40:18Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// bx_define_cpudb(bx_generic) #if BX_CPU_LEVEL == 5 bx_define_cpudb(pentium_mmx) bx_define_cpudb(amd_k6_2_chomper) #elif BX_CPU_LEVEL >= 6 bx_define_cpudb(p2_klamath) bx_define_cpudb(p3_katmai) bx_define_cpudb(p4_willamette) bx_define_cpudb(core_duo_t2400_yonah) bx_define_cpudb(atom_n270) #if BX_SUPPORT_X86_64 bx_define_cpudb(p4_prescott_celeron_336) bx_define_cpudb(athlon64_clawhammer) bx_define_cpudb(athlon64_venice) bx_define_cpudb(turion64_tyler) bx_define_cpudb(phenom_8650_toliman) bx_define_cpudb(core2_penryn_t9600) bx_define_cpudb(corei5_lynnfield_750) bx_define_cpudb(corei5_arrandale_m520) #if BX_SUPPORT_AVX bx_define_cpudb(corei7_sandy_bridge_2600k) bx_define_cpudb(corei7_ivy_bridge_3770k) #endif #endif #endif bochs-2.6/.conf.amigaos0000755000175000017500000000017212020641507014702 0ustar guillemguillem#!/bin/sh # # These options should work on Amiga/MorphOS # ./configure --with-amigaos --disable-shared ${CONFIGURE_ARGS} bochs-2.6/README0000644000175000017500000000733612020641507013223 0ustar guillemguillemBochs - The cross platform IA-32 (x86) emulator Updated: Sun Sep 2 13:10:00 CEST 2012 Version: 2.6 WHAT IS BOCHS? Bochs is a highly portable open source IA-32 (x86) PC emulator written in C++, that runs on most popular platforms. It includes emulation of the Intel x86 CPU, common I/O devices, and a custom BIOS. Bochs can be compiled to emulate many different x86 CPUs, from early 386 to the most recent x86-64 Intel and AMD processors which may even not reached the market yet. Bochs is capable of running most Operating Systems inside the emulation, for example DOS, Linux or Windows. Bochs was written by Kevin Lawton and is currently maintained by the Bochs project at "http://bochs.sourceforge.net". Bochs can be compiled and used in a variety of modes, some which are still in development. The 'typical' use of bochs is to provide complete x86 PC emulation, including the x86 processor, hardware devices, and memory. This allows you to run OS's and software within the emulator on your workstation, much like you have a machine inside of a machine. Bochs will allow you to run Windows applications on a Solaris machine with X11, for example. Bochs is distributed under the GNU LGPL. See LICENSE and COPYING for details. GETTING CURRENT SOURCE CODE Source code for Bochs is available from the Bochs home page at http://bochs.sourceforge.net. You can download the most recent release, use SVN to get the latest sources, or grab a SVN snapshot which is updated frequently. The releases contain the most stable code, but if you want the very newest features try the SVN version instead. WHERE ARE THE DOCS? The Bochs documentation is written in Docbook. Docbook is a text format that can be rendered to many popular browser formats such as HTML, PDF, and Postscript. Each binary release contains the HTML rendering of the documentation. Also, you can view the latest documentation on the web at http://bochs.sf.net/doc/docbook/index.html Some information has not yet been transferred from the older HTML docs. These can be found at http://bochs.sf.net/docs-html WHERE CAN I GET MORE INFORMATION? HOW DO I REPORT PROBLEMS? Both the documentation and the Bochs website have instructions on how to join the bochs-developers mailing list, which is the primary forum for discussion of Bochs. The main page of the website also has links to bug reports and feature requests. You can browse and add to the content in these areas even if you do not have a (free) SourceForge account. We need your feedback so that we know what parts of Bochs to improve. There is a patches section on the web site too, if you have made some changes to Bochs that you want to share. HOW CAN I HELP? If you would like contribute to the Bochs project, a good first step is to join the bochs-developers mailing list, and read the archive of recent messages to see what's going on. If you are a technical person (can follow hardware specs, can write C/C++) take a look at the list of open bug reports and feature requests to see if you are interested in working on any of the problems that are mentioned in them. If you check out the SVN sources, make some changes, and create a patch, one of the developers will be very happy to apply it for you. Developers who frequently submit patches, or who embark on major changes in the source can get write access to SVN. Be sure to communicate with the bochs-developers list to avoid several people working on the same thing without realizing it. If you are a Bochs user, not a hardware/C++ guru, there are still many ways you could help out. For example: - write instructions on how to install a particular operating system - writing/cleaning up documentation - testing out Bochs on every imaginable operating system and reporting how it goes. bochs-2.6/config.guess0000755000175000017500000012765512020641507014672 0ustar guillemguillem#! /bin/sh # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 # Free Software Foundation, Inc. timestamp='2010-04-03' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA # 02110-1301, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Per Bothner. Please send patches (context # diff format) to and include a ChangeLog # entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' HUP INT TERM # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" HUP INT PIPE TERM ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE="alpha" ;; "EV4.5 (21064)") UNAME_MACHINE="alpha" ;; "LCA4 (21066/21068)") UNAME_MACHINE="alpha" ;; "EV5 (21164)") UNAME_MACHINE="alphaev5" ;; "EV5.6 (21164A)") UNAME_MACHINE="alphaev56" ;; "EV5.6 (21164PC)") UNAME_MACHINE="alphapca56" ;; "EV5.7 (21164PC)") UNAME_MACHINE="alphapca57" ;; "EV6 (21264)") UNAME_MACHINE="alphaev6" ;; "EV6.7 (21264A)") UNAME_MACHINE="alphaev67" ;; "EV6.8CB (21264C)") UNAME_MACHINE="alphaev68" ;; "EV6.8AL (21264B)") UNAME_MACHINE="alphaev68" ;; "EV6.8CX (21264D)") UNAME_MACHINE="alphaev68" ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE="alphaev69" ;; "EV7 (21364)") UNAME_MACHINE="alphaev7" ;; "EV7.9 (21364A)") UNAME_MACHINE="alphaev79" ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` exit ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm:riscos:*:*|arm:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH="i386" # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH="x86_64" fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[456]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH="hppa2.0n" ;; 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = "hppa2.0w" ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH="hppa2.0w" else HP_ARCH="hppa64" fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) case ${UNAME_MACHINE} in pc98) echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-gnu else echo ${UNAME_MACHINE}-unknown-linux-gnueabi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; cris:Linux:*:*) echo cris-axis-linux-gnu exit ;; crisv32:Linux:*:*) echo crisv32-axis-linux-gnu exit ;; frv:Linux:*:*) echo frv-unknown-linux-gnu exit ;; i*86:Linux:*:*) LIBC=gnu eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __dietlibc__ LIBC=dietlibc #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` echo "${UNAME_MACHINE}-pc-linux-${LIBC}" exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } ;; or32:Linux:*:*) echo or32-unknown-linux-gnu exit ;; padre:Linux:*:*) echo sparc-unknown-linux-gnu exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-gnu exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-gnu ;; PA8*) echo hppa2.0-unknown-linux-gnu ;; *) echo hppa-unknown-linux-gnu ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-gnu exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) echo x86_64-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configury will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown case $UNAME_PROCESSOR in i386) eval $set_cc_for_build if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then UNAME_PROCESSOR="x86_64" fi fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = "x86"; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = "386"; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 eval $set_cc_for_build cat >$dummy.c < # include #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (__arm) && defined (__acorn) && defined (__unix) printf ("arm-acorn-riscix\n"); exit (0); #endif #if defined (hp300) && !defined (hpux) printf ("m68k-hp-bsd\n"); exit (0); #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) # if !defined (ultrix) # include # if defined (BSD) # if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); # else # if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); # else printf ("vax-dec-bsd\n"); exit (0); # endif # endif # else printf ("vax-dec-bsd\n"); exit (0); # endif # else printf ("vax-dec-ultrix\n"); exit (0); # endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } # Convex versions that predate uname can use getsysinfo(1) if [ -x /usr/convex/getsysinfo ] then case `getsysinfo -f cpu_type` in c1*) echo c1-convex-bsd exit ;; c2*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; c34*) echo c34-convex-bsd exit ;; c38*) echo c38-convex-bsd exit ;; c4*) echo c4-convex-bsd exit ;; esac fi cat >&2 < in order to provide the needed information to handle your system. config.guess timestamp = $timestamp uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: bochs-2.6/ltdl.c0000644000175000017500000025327212020641507013450 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ltdl.c 10209 2011-02-24 22:05:47Z sshwarts $ // // NOTE: The ltdl library comes from the Libtool package. Bochs uses // ltdl and libtool to build and load plugins. The libtool // documentation describes how to copy ltdl.c and ltdl.h into your // distribution, so it is clearly legal to do so. ///////////////////////////////////////////////////////////////////////// /* ltdl.c -- system independent dlopen wrapper Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. Originally by Thomas Tanner This file is part of GNU Libtool. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. As a special exception to the GNU Lesser General Public License, if you distribute this file as part of a program or library that is built using GNU libtool, you may include it under the same distribution terms that you use for the rest of that program. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // ltdlconf.h added for Bochs #include "ltdlconf.h" #if HAVE_CONFIG_H # include #endif #if HAVE_UNISTD_H # include #endif #if HAVE_STDIO_H # include #endif #if HAVE_STDLIB_H # include #endif #if HAVE_STRING_H # include #else # if HAVE_STRINGS_H # include # endif #endif #if HAVE_CTYPE_H # include #endif #if HAVE_MALLOC_H # include #endif #if HAVE_MEMORY_H # include #endif #if HAVE_ERRNO_H # include #endif #if HAVE_DIRENT_H # include # define LT_D_NAMLEN(dirent) (strlen((dirent)->d_name)) #else # define dirent direct # define LT_D_NAMLEN(dirent) ((dirent)->d_namlen) # if HAVE_SYS_NDIR_H # include # endif # if HAVE_SYS_DIR_H # include # endif # if HAVE_NDIR_H # include # endif #endif #if HAVE_ARGZ_H # include #endif #if HAVE_ASSERT_H # include #else # ifdef __GNUC__ # warning using my own assert # endif # define assert(cond) while (!(cond)) { fprintf (stderr, "Assert failed at %s:%d: '%s'\n", __FILE__, __LINE__, #cond); abort(); } #endif #define LTDEBUG_PRINTF(x) /* debug output disabled */ //#define LTDEBUG_PRINTF(x) do{ printf("LT_DEBUG: "); printf x; } while (0) #include "ltdl.h" /* --- WINDOWS SUPPORT --- */ #ifdef DLL_EXPORT # define LT_GLOBAL_DATA __declspec(dllexport) #else # define LT_GLOBAL_DATA #endif /* fopen() mode flags for reading a text file */ #undef LT_READTEXT_MODE #ifdef __WINDOWS__ # define LT_READTEXT_MODE "rt" #else # define LT_READTEXT_MODE "r" #endif /* --- MANIFEST CONSTANTS --- */ /* Standard libltdl search path environment variable name */ #undef LTDL_SEARCHPATH_VAR #define LTDL_SEARCHPATH_VAR "LTDL_LIBRARY_PATH" /* Standard libtool archive file extension. */ #undef LTDL_ARCHIVE_EXT #define LTDL_ARCHIVE_EXT ".la" /* max. filename length */ #ifndef LT_FILENAME_MAX # define LT_FILENAME_MAX 1024 #endif /* This is the maximum symbol size that won't require malloc/free */ #undef LT_SYMBOL_LENGTH #define LT_SYMBOL_LENGTH 128 /* This accounts for the _LTX_ separator */ #undef LT_SYMBOL_OVERHEAD #define LT_SYMBOL_OVERHEAD 5 /* --- MEMORY HANDLING --- */ /* These are the functions used internally. In addition to making use of the associated function pointers above, they also perform error handling. */ static char *lt_estrdup LT_PARAMS((const char *str)); static lt_ptr lt_emalloc LT_PARAMS((size_t size)); static lt_ptr lt_erealloc LT_PARAMS((lt_ptr addr, size_t size)); static lt_ptr rpl_realloc LT_PARAMS((lt_ptr ptr, size_t size)); /* These are the pointers that can be changed by the caller: */ LT_GLOBAL_DATA lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)) = (lt_ptr (*) LT_PARAMS((size_t))) malloc; LT_GLOBAL_DATA lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)) = (lt_ptr (*) LT_PARAMS((lt_ptr, size_t))) rpl_realloc; LT_GLOBAL_DATA void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)) = (void (*) LT_PARAMS((lt_ptr))) free; /* The following macros reduce the amount of typing needed to cast assigned memory. */ #define LT_DLMALLOC(tp, n) ((tp *) lt_dlmalloc ((n) * sizeof(tp))) #define LT_DLREALLOC(tp, p, n) ((tp *) rpl_realloc ((p), (n) * sizeof(tp))) #define LT_DLFREE(p) \ LT_STMT_START { if (p) (p) = (lt_dlfree (p), (lt_ptr) 0); } LT_STMT_END #define LT_EMALLOC(tp, n) ((tp *) lt_emalloc ((n) * sizeof(tp))) #define LT_EREALLOC(tp, p, n) ((tp *) lt_erealloc ((p), (n) * sizeof(tp))) #define LT_DLMEM_REASSIGN(p, q) LT_STMT_START { \ if ((p) != (q)) { lt_dlfree (p); (p) = (q); (q) = 0; } \ } LT_STMT_END /* --- REPLACEMENT FUNCTIONS --- */ #undef strdup #define strdup rpl_strdup static char *strdup LT_PARAMS((const char *str)); char * strdup(str) const char *str; { char *tmp = 0; if (str) { tmp = LT_DLMALLOC (char, 1+ strlen (str)); if (tmp) { strcpy(tmp, str); } } return tmp; } #if ! HAVE_STRCMP #undef strcmp #define strcmp rpl_strcmp static int strcmp LT_PARAMS((const char *str1, const char *str2)); int strcmp (str1, str2) const char *str1; const char *str2; { if (str1 == str2) return 0; if (str1 == 0) return -1; if (str2 == 0) return 1; for (;*str1 && *str2; ++str1, ++str2) { if (*str1 != *str2) break; } return (int)(*str1 - *str2); } #endif #if ! HAVE_STRCHR # if HAVE_INDEX # define strchr index # else # define strchr rpl_strchr static const char *strchr LT_PARAMS((const char *str, int ch)); const char* strchr(str, ch) const char *str; int ch; { const char *p; for (p = str; *p != (char)ch && *p != LT_EOS_CHAR; ++p) /*NOWORK*/; return (*p == (char)ch) ? p : 0; } # endif #endif /* !HAVE_STRCHR */ #if ! HAVE_STRRCHR # if HAVE_RINDEX # define strrchr rindex # else # define strrchr rpl_strrchr static const char *strrchr LT_PARAMS((const char *str, int ch)); const char* strrchr(str, ch) const char *str; int ch; { const char *p, *q = 0; for (p = str; *p != LT_EOS_CHAR; ++p) { if (*p == (char) ch) { q = p; } } return q; } # endif #endif /* NOTE: Neither bcopy nor the memcpy implementation below can reliably handle copying in overlapping areas of memory. Use memmove (for which there is a fallback implmentation below) if you need that behaviour. */ #if ! HAVE_MEMCPY # if HAVE_BCOPY # define memcpy(dest, src, size) bcopy (src, dest, size) # else # define memcpy rpl_memcpy static lt_ptr memcpy LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); lt_ptr memcpy (dest, src, size) lt_ptr dest; const lt_ptr src; size_t size; { size_t i = 0; for (i = 0; i < size; ++i) { dest[i] = src[i]; } return dest; } # endif /* !HAVE_BCOPY */ #endif /* !HAVE_MEMCPY */ #if ! HAVE_MEMMOVE # define memmove rpl_memmove static lt_ptr memmove LT_PARAMS((lt_ptr dest, const lt_ptr src, size_t size)); lt_ptr memmove (dest, src, size) lt_ptr dest; const lt_ptr src; size_t size; { size_t i; if (dest < src) for (i = 0; i < size; ++i) { dest[i] = src[i]; } else if (dest > src) for (i = size -1; i >= 0; --i) { dest[i] = src[i]; } return dest; } #endif /* !HAVE_MEMMOVE */ /* According to Alexandre Oliva , ``realloc is not entirely portable'' In any case we want to use the allocator supplied by the user without burdening them with an lt_dlrealloc function pointer to maintain. Instead implement our own version (with known boundary conditions) using lt_dlmalloc and lt_dlfree. */ #undef realloc #define realloc rpl_realloc lt_ptr realloc (ptr, size) lt_ptr ptr; size_t size; { if (size <= 0) { /* For zero or less bytes, free the original memory */ if (ptr != 0) { lt_dlfree (ptr); } return (lt_ptr) 0; } else if (ptr == 0) { /* Allow reallocation of a NULL pointer. */ return lt_dlmalloc (size); } else { /* Allocate a new block, copy and free the old block. */ lt_ptr mem = lt_dlmalloc (size); if (mem) { memcpy (mem, ptr, size); lt_dlfree (ptr); } /* Note that the contents of PTR are not damaged if there is insufficient memory to realloc. */ return mem; } } #if ! HAVE_ARGZ_APPEND # define argz_append rpl_argz_append static error_t argz_append LT_PARAMS((char **pargz, size_t *pargz_len, const char *buf, size_t buf_len)); error_t argz_append (pargz, pargz_len, buf, buf_len) char **pargz; size_t *pargz_len; const char *buf; size_t buf_len; { size_t argz_len; char *argz; assert (pargz); assert (pargz_len); assert ((*pargz && *pargz_len) || (!*pargz && !*pargz_len)); /* If nothing needs to be appended, no more work is required. */ if (buf_len == 0) return 0; /* Ensure there is enough room to append BUF_LEN. */ argz_len = *pargz_len + buf_len; argz = LT_DLREALLOC (char, *pargz, argz_len); if (!argz) return ENOMEM; /* Copy characters from BUF after terminating '\0' in ARGZ. */ memcpy (argz + *pargz_len, buf, buf_len); /* Assign new values. */ *pargz = argz; *pargz_len = argz_len; return 0; } #endif /* !HAVE_ARGZ_APPEND */ #if ! HAVE_ARGZ_CREATE_SEP # define argz_create_sep rpl_argz_create_sep static error_t argz_create_sep LT_PARAMS((const char *str, int delim, char **pargz, size_t *pargz_len)); error_t argz_create_sep (str, delim, pargz, pargz_len) const char *str; int delim; char **pargz; size_t *pargz_len; { size_t argz_len; char *argz = 0; assert (str); assert (pargz); assert (pargz_len); /* Make a copy of STR, but replacing each occurence of DELIM with '\0'. */ argz_len = 1+ LT_STRLEN (str); if (argz_len) { const char *p; char *q; argz = LT_DLMALLOC (char, argz_len); if (!argz) return ENOMEM; for (p = str, q = argz; *p != LT_EOS_CHAR; ++p) { if (*p == delim) { /* Ignore leading delimiters, and fold consecutive delimiters in STR into a single '\0' in ARGZ. */ if ((q > argz) && (q[-1] != LT_EOS_CHAR)) *q++ = LT_EOS_CHAR; else --argz_len; } else *q++ = *p; } /* Copy terminating LT_EOS_CHAR. */ *q = *p; } /* If ARGZ_LEN has shrunk to nothing, release ARGZ's memory. */ if (!argz_len) LT_DLFREE (argz); /* Assign new values. */ *pargz = argz; *pargz_len = argz_len; return 0; } #endif /* !HAVE_ARGZ_CREATE_SEP */ #if ! HAVE_ARGZ_INSERT # define argz_insert rpl_argz_insert static error_t argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, char *before, const char *entry)); error_t argz_insert (pargz, pargz_len, before, entry) char **pargz; size_t *pargz_len; char *before; const char *entry; { assert (pargz); assert (pargz_len); assert (entry && *entry); /* Either PARGZ/PARGZ_LEN is empty and BEFORE is NULL, or BEFORE points into an address within the ARGZ vector. */ assert ((!*pargz && !*pargz_len && !before) || ((*pargz <= before) && (before < (*pargz + *pargz_len)))); /* No BEFORE address indicates ENTRY should be inserted after the current last element. */ if (!before) return argz_append (pargz, pargz_len, entry, 1+ LT_STRLEN (entry)); /* This probably indicates a programmer error, but to preserve semantics, scan back to the start of an entry if BEFORE points into the middle of it. */ while ((before >= *pargz) && (before[-1] != LT_EOS_CHAR)) --before; { size_t entry_len = 1+ LT_STRLEN (entry); size_t argz_len = *pargz_len + entry_len; size_t offset = before - *pargz; char *argz = LT_DLREALLOC (char, *pargz, argz_len); if (!argz) return ENOMEM; /* Make BEFORE point to the equivalent offset in ARGZ that it used to have in *PARGZ incase realloc() moved the block. */ before = argz + offset; /* Move the ARGZ entries starting at BEFORE up into the new space at the end -- making room to copy ENTRY into the resulting gap. */ memmove (before + entry_len, before, *pargz_len - offset); memcpy (before, entry, entry_len); /* Assign new values. */ *pargz = argz; *pargz_len = argz_len; } return 0; } #endif /* !HAVE_ARGZ_INSERT */ #if ! HAVE_ARGZ_NEXT # define argz_next rpl_argz_next static char *argz_next LT_PARAMS((char *argz, size_t argz_len, const char *entry)); char * argz_next (argz, argz_len, entry) char *argz; size_t argz_len; const char *entry; { assert ((argz && argz_len) || (!argz && !argz_len)); if (entry) { /* Either ARGZ/ARGZ_LEN is empty, or ENTRY points into an address within the ARGZ vector. */ assert ((!argz && !argz_len) || ((argz <= entry) && (entry < (argz + argz_len)))); /* Move to the char immediately after the terminating '\0' of ENTRY. */ entry = 1+ strchr (entry, LT_EOS_CHAR); /* Return either the new ENTRY, or else NULL if ARGZ is exhausted. */ return (entry >= argz + argz_len) ? 0 : (char *) entry; } else { /* This should probably be flagged as a programmer error, since starting an argz_next loop with the iterator set to ARGZ is safer. To preserve semantics, handle the NULL case by returning the start of ARGZ (if any). */ if (argz_len > 0) return argz; else return 0; } } #endif /* !HAVE_ARGZ_NEXT */ #if ! HAVE_ARGZ_STRINGIFY # define argz_stringify rpl_argz_stringify static void argz_stringify LT_PARAMS((char *argz, size_t argz_len, int sep)); void argz_stringify (argz, argz_len, sep) char *argz; size_t argz_len; int sep; { assert ((argz && argz_len) || (!argz && !argz_len)); if (sep) { --argz_len; /* don't stringify the terminating EOS */ while (--argz_len > 0) { if (argz[argz_len] == LT_EOS_CHAR) argz[argz_len] = sep; } } } #endif /* !HAVE_ARGZ_STRINGIFY */ /* --- TYPE DEFINITIONS -- */ /* This type is used for the array of caller data sets in each handler. */ typedef struct { lt_dlcaller_id key; lt_ptr data; } lt_caller_data; /* --- OPAQUE STRUCTURES DECLARED IN LTDL.H --- */ /* Extract the diagnostic strings from the error table macro in the same order as the enumerated indices in ltdl.h. */ static const char *lt_dlerror_strings[] = { lt_dlerror_names_list 0 }; /* This structure is used for the list of registered loaders. */ struct lt_dlloader { struct lt_dlloader *next; const char *loader_name; /* identifying name for each loader */ const char *sym_prefix; /* prefix for symbols */ lt_module_open *module_open; lt_module_close *module_close; lt_find_sym *find_sym; lt_dlloader_exit *dlloader_exit; lt_user_data dlloader_data; }; struct lt_dlhandle_struct { struct lt_dlhandle_struct *next; lt_dlloader *loader; /* dlopening interface */ lt_dlinfo info; int depcount; /* number of dependencies */ lt_dlhandle *deplibs; /* dependencies */ lt_module module; /* system module handle */ lt_ptr system; /* system specific data */ lt_caller_data *caller_data; /* per caller associated data */ int flags; /* various boolean stats */ }; /* Various boolean flags can be stored in the flags field of an lt_dlhandle_struct... */ #define LT_DLGET_FLAG(handle, flag) (((handle)->flags & (flag)) == (flag)) #define LT_DLSET_FLAG(handle, flag) ((handle)->flags |= (flag)) #define LT_DLRESIDENT_FLAG (0x01 << 0) /* ...add more flags here... */ #define LT_DLIS_RESIDENT(handle) LT_DLGET_FLAG(handle, LT_DLRESIDENT_FLAG) #define LT_DLSTRERROR(name) lt_dlerror_strings[LT_CONC(LT_ERROR_,name)] static const char objdir[] = LTDL_OBJDIR; static const char archive_ext[] = LTDL_ARCHIVE_EXT; #ifdef LTDL_SHLIB_EXT static const char shlib_ext[] = LTDL_SHLIB_EXT; #endif #ifdef LTDL_SYSSEARCHPATH static const char sys_search_path[] = LTDL_SYSSEARCHPATH; #endif /* --- MUTEX LOCKING --- */ /* Macros to make it easier to run the lock functions only if they have been registered. The reason for the complicated lock macro is to ensure that the stored error message from the last error is not accidentally erased if the current function doesn't generate an error of its own. */ #define LT_DLMUTEX_LOCK() LT_STMT_START { \ if (lt_dlmutex_lock_func) (*lt_dlmutex_lock_func)(); \ } LT_STMT_END #define LT_DLMUTEX_UNLOCK() LT_STMT_START { \ if (lt_dlmutex_unlock_func) (*lt_dlmutex_unlock_func)();\ } LT_STMT_END #define LT_DLMUTEX_SETERROR(errormsg) LT_STMT_START { \ if (lt_dlmutex_seterror_func) \ (*lt_dlmutex_seterror_func) (errormsg); \ else lt_dllast_error = (errormsg); } LT_STMT_END #define LT_DLMUTEX_GETERROR(errormsg) LT_STMT_START { \ if (lt_dlmutex_seterror_func) \ (errormsg) = (*lt_dlmutex_geterror_func) (); \ else (errormsg) = lt_dllast_error; } LT_STMT_END /* The mutex functions stored here are global, and are necessarily the same for all threads that wish to share access to libltdl. */ static lt_dlmutex_lock *lt_dlmutex_lock_func = 0; static lt_dlmutex_unlock *lt_dlmutex_unlock_func = 0; static lt_dlmutex_seterror *lt_dlmutex_seterror_func = 0; static lt_dlmutex_geterror *lt_dlmutex_geterror_func = 0; static const char *lt_dllast_error = 0; /* Either set or reset the mutex functions. Either all the arguments must be valid functions, or else all can be NULL to turn off locking entirely. The registered functions should be manipulating a static global lock from the lock() and unlock() callbacks, which needs to be reentrant. */ int lt_dlmutex_register (lock, unlock, seterror, geterror) lt_dlmutex_lock *lock; lt_dlmutex_unlock *unlock; lt_dlmutex_seterror *seterror; lt_dlmutex_geterror *geterror; { lt_dlmutex_unlock *old_unlock = unlock; int errors = 0; /* Lock using the old lock() callback, if any. */ LT_DLMUTEX_LOCK (); if ((lock && unlock && seterror && geterror) || !(lock || unlock || seterror || geterror)) { lt_dlmutex_lock_func = lock; lt_dlmutex_unlock_func = unlock; lt_dlmutex_geterror_func = geterror; } else { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_MUTEX_ARGS)); ++errors; } /* Use the old unlock() callback we saved earlier, if any. Otherwise record any errors using internal storage. */ if (old_unlock) (*old_unlock) (); /* Return the number of errors encountered during the execution of this function. */ return errors; } /* --- ERROR HANDLING --- */ static const char **user_error_strings = 0; static int errorcount = LT_ERROR_MAX; int lt_dladderror (diagnostic) const char *diagnostic; { int errindex = 0; int result = -1; const char **temp = (const char **) 0; assert (diagnostic); LT_DLMUTEX_LOCK (); errindex = errorcount - LT_ERROR_MAX; temp = LT_EREALLOC (const char *, user_error_strings, 1 + errindex); if (temp) { user_error_strings = temp; user_error_strings[errindex] = diagnostic; result = errorcount++; } LT_DLMUTEX_UNLOCK (); return result; } int lt_dlseterror (errindex) int errindex; { int errors = 0; LT_DLMUTEX_LOCK (); if (errindex >= errorcount || errindex < 0) { /* Ack! Error setting the error message! */ LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_ERRORCODE)); ++errors; } else if (errindex < LT_ERROR_MAX) { /* No error setting the error message! */ LT_DLMUTEX_SETERROR (lt_dlerror_strings[errindex]); } else { /* No error setting the error message! */ LT_DLMUTEX_SETERROR (user_error_strings[errindex - LT_ERROR_MAX]); } LT_DLMUTEX_UNLOCK (); return errors; } lt_ptr lt_emalloc (size) size_t size; { lt_ptr mem = lt_dlmalloc (size); if (size && !mem) LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); return mem; } lt_ptr lt_erealloc (addr, size) lt_ptr addr; size_t size; { lt_ptr mem = realloc (addr, size); if (size && !mem) LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); return mem; } char * lt_estrdup (str) const char *str; { char *dup = strdup (str); if (LT_STRLEN (str) && !dup) LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); return dup; } /* --- DLOPEN() INTERFACE LOADER --- */ /* The Cygwin dlopen implementation prints a spurious error message to stderr if its call to LoadLibrary() fails for any reason. We can mitigate this by not using the Cygwin implementation, and falling back to our own LoadLibrary() wrapper. */ #if HAVE_LIBDL && !defined(__CYGWIN__) /* dynamic linking with dlopen/dlsym */ #if HAVE_DLFCN_H # include #endif #if HAVE_SYS_DL_H # include #endif #ifdef RTLD_GLOBAL # define LT_GLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_GLOBAL DL_GLOBAL # endif #endif /* !RTLD_GLOBAL */ #ifndef LT_GLOBAL # define LT_GLOBAL 0 #endif /* !LT_GLOBAL */ /* We may have to define LT_LAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_LAZY_OR_NOW # ifdef RTLD_LAZY # define LT_LAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_LAZY_OR_NOW DL_LAZY # endif # endif /* !RTLD_LAZY */ #endif #ifndef LT_LAZY_OR_NOW # ifdef RTLD_NOW # define LT_LAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_LAZY_OR_NOW DL_NOW # endif # endif /* !RTLD_NOW */ #endif #ifndef LT_LAZY_OR_NOW # define LT_LAZY_OR_NOW 0 #endif /* !LT_LAZY_OR_NOW */ #if HAVE_DLERROR # define DLERROR(arg) dlerror () #else # define DLERROR(arg) LT_DLSTRERROR (arg) #endif static lt_module sys_dl_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_module module = dlopen (filename, LT_GLOBAL | LT_LAZY_OR_NOW); if (!module) { LT_DLMUTEX_SETERROR (DLERROR (CANNOT_OPEN)); } return module; } static int sys_dl_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (dlclose (module) != 0) { LT_DLMUTEX_SETERROR (DLERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_dl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = dlsym (module, symbol); if (!address) { LT_DLMUTEX_SETERROR (DLERROR (SYMBOL_NOT_FOUND)); } return address; } static struct lt_user_dlloader sys_dl = { # ifdef NEED_USCORE "_", # else 0, # endif sys_dl_open, sys_dl_close, sys_dl_sym, 0, 0 }; #endif /* HAVE_LIBDL */ /* --- SHL_LOAD() INTERFACE LOADER --- */ #if HAVE_SHL_LOAD /* dynamic linking with shl_load (HP-UX) (comments from gmodule) */ #ifdef HAVE_DL_H # include #endif /* some flags are missing on some systems, so we provide * harmless defaults. * * Mandatory: * BIND_IMMEDIATE - Resolve symbol references when the library is loaded. * BIND_DEFERRED - Delay code symbol resolution until actual reference. * * Optionally: * BIND_FIRST - Place the library at the head of the symbol search * order. * BIND_NONFATAL - The default BIND_IMMEDIATE behavior is to treat all * unsatisfied symbols as fatal. This flag allows * binding of unsatisfied code symbols to be deferred * until use. * [Perl: For certain libraries, like DCE, deferred * binding often causes run time problems. Adding * BIND_NONFATAL to BIND_IMMEDIATE still allows * unresolved references in situations like this.] * BIND_NOSTART - Do not call the initializer for the shared library * when the library is loaded, nor on a future call to * shl_unload(). * BIND_VERBOSE - Print verbose messages concerning possible * unsatisfied symbols. * * hp9000s700/hp9000s800: * BIND_RESTRICTED - Restrict symbols visible by the library to those * present at library load time. * DYNAMIC_PATH - Allow the loader to dynamically search for the * library specified by the path argument. */ #ifndef DYNAMIC_PATH # define DYNAMIC_PATH 0 #endif #ifndef BIND_RESTRICTED # define BIND_RESTRICTED 0 #endif #define LT_BIND_FLAGS (BIND_IMMEDIATE | BIND_NONFATAL | DYNAMIC_PATH) static lt_module sys_shl_open (loader_data, filename) lt_user_data loader_data; const char *filename; { static shl_t self = (shl_t) 0; lt_module module = shl_load (filename, LT_BIND_FLAGS, 0L); /* Since searching for a symbol against a NULL module handle will also look in everything else that was already loaded and exported with the -E compiler flag, we always cache a handle saved before any modules are loaded. */ if (!self) { lt_ptr address; shl_findsym (&self, "main", TYPE_UNDEFINED, &address); } if (!filename) { module = self; } else { module = shl_load (filename, LT_BIND_FLAGS, 0L); if (!module) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); } } return module; } static int sys_shl_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (module && (shl_unload ((shl_t) (module)) != 0)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_shl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = 0; /* sys_shl_open should never return a NULL module handle */ if (module == (lt_module) 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); } else if (!shl_findsym((shl_t*) &module, symbol, TYPE_UNDEFINED, &address)) { if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } } return address; } static struct lt_user_dlloader sys_shl = { 0, sys_shl_open, sys_shl_close, sys_shl_sym, 0, 0 }; #endif /* HAVE_SHL_LOAD */ /* --- LOADLIBRARY() INTERFACE LOADER --- */ #ifdef __WINDOWS__ /* dynamic linking for Win32 */ #include void win32_print_last_error (char *fmtstring) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL ); printf (fmtstring, (char*)lpMsgBuf); LocalFree (lpMsgBuf); } /* Forward declaration; required to implement handle search below. */ static lt_dlhandle handles; static lt_module sys_wll_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_dlhandle cur; lt_module module = 0; const char *errormsg = 0; char *searchname = 0; char *ext; char self_name_buf[MAX_PATH]; if (!filename) { /* Get the name of main module */ *self_name_buf = 0; GetModuleFileName (NULL, self_name_buf, sizeof (self_name_buf)); filename = ext = self_name_buf; } else { ext = strrchr (filename, '.'); } if (ext) { /* FILENAME already has an extension. */ searchname = lt_estrdup (filename); } else { /* Append a `.' to stop Windows from adding an implicit `.dll' extension. */ searchname = LT_EMALLOC (char, 2+ LT_STRLEN (filename)); if (searchname) sprintf (searchname, "%s.", filename); } if (!searchname) return 0; #if __CYGWIN__ { char wpath[MAX_PATH]; cygwin_conv_to_full_win32_path(searchname, wpath); module = LoadLibrary(wpath); } #else module = LoadLibrary (searchname); if (!module) { win32_print_last_error ("LoadLibrary failed: %s\n"); } #endif LT_DLFREE (searchname); /* libltdl expects this function to fail if it is unable to physically load the library. Sadly, LoadLibrary will search the loaded libraries for a match and return one of them if the path search load fails. We check whether LoadLibrary is returning a handle to an already loaded module, and simulate failure if we find one. */ LT_DLMUTEX_LOCK (); cur = handles; while (cur) { if (!cur->module) { cur = 0; break; } if (cur->module == module) { break; } cur = cur->next; } LT_DLMUTEX_UNLOCK (); if (cur || !module) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); module = 0; } return module; } static int sys_wll_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (FreeLibrary(module) == 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_wll_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = GetProcAddress (module, symbol); if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } return address; } static struct lt_user_dlloader sys_wll = { 0, sys_wll_open, sys_wll_close, sys_wll_sym, 0, 0 }; #endif /* __WINDOWS__ */ /* --- LOAD_ADD_ON() INTERFACE LOADER --- */ #ifdef __BEOS__ /* dynamic linking for BeOS */ #include static lt_module sys_bedl_open (loader_data, filename) lt_user_data loader_data; const char *filename; { image_id image = 0; if (filename) { image = load_add_on (filename); } else { image_info info; int32 cookie = 0; if (get_next_image_info (0, &cookie, &info) == B_OK) image = load_add_on (info.name); } if (image <= 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); image = 0; } return (lt_module) image; } static int sys_bedl_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (unload_add_on ((image_id) module) != B_OK) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } return errors; } static lt_ptr sys_bedl_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = 0; image_id image = (image_id) module; if (get_image_symbol (image, symbol, B_SYMBOL_TYPE_ANY, address) != B_OK) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); address = 0; } return address; } static struct lt_user_dlloader sys_bedl = { 0, sys_bedl_open, sys_bedl_close, sys_bedl_sym, 0, 0 }; #endif /* __BEOS__ */ /* --- DLD_LINK() INTERFACE LOADER --- */ #if HAVE_DLD /* dynamic linking with dld */ #if HAVE_DLD_H #include #endif static lt_module sys_dld_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_module module = strdup (filename); if (dld_link (filename) != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_OPEN)); LT_DLFREE (module); module = 0; } return module; } static int sys_dld_close (loader_data, module) lt_user_data loader_data; lt_module module; { int errors = 0; if (dld_unlink_by_file ((char*)(module), 1) != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CANNOT_CLOSE)); ++errors; } else { LT_DLFREE (module); } return errors; } static lt_ptr sys_dld_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_ptr address = dld_get_func (symbol); if (!address) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); } return address; } static struct lt_user_dlloader sys_dld = { 0, sys_dld_open, sys_dld_close, sys_dld_sym, 0, 0 }; #endif /* HAVE_DLD */ /* --- DLPREOPEN() INTERFACE LOADER --- */ /* emulate dynamic linking using preloaded_symbols */ typedef struct lt_dlsymlists_t { struct lt_dlsymlists_t *next; const lt_dlsymlist *syms; } lt_dlsymlists_t; static const lt_dlsymlist *default_preloaded_symbols = 0; static lt_dlsymlists_t *preloaded_symbols = 0; static int presym_init (loader_data) lt_user_data loader_data; { int errors = 0; LT_DLMUTEX_LOCK (); preloaded_symbols = 0; if (default_preloaded_symbols) { errors = lt_dlpreload (default_preloaded_symbols); } LT_DLMUTEX_UNLOCK (); return errors; } static int presym_free_symlists () { lt_dlsymlists_t *lists; LT_DLMUTEX_LOCK (); lists = preloaded_symbols; while (lists) { lt_dlsymlists_t *tmp = lists; lists = lists->next; LT_DLFREE (tmp); } preloaded_symbols = 0; LT_DLMUTEX_UNLOCK (); return 0; } static int presym_exit (loader_data) lt_user_data loader_data; { presym_free_symlists (); return 0; } static int presym_add_symlist (preloaded) const lt_dlsymlist *preloaded; { lt_dlsymlists_t *tmp; lt_dlsymlists_t *lists; int errors = 0; LT_DLMUTEX_LOCK (); lists = preloaded_symbols; while (lists) { if (lists->syms == preloaded) { goto done; } lists = lists->next; } tmp = LT_EMALLOC (lt_dlsymlists_t, 1); if (tmp) { memset (tmp, 0, sizeof(lt_dlsymlists_t)); tmp->syms = preloaded; tmp->next = preloaded_symbols; preloaded_symbols = tmp; } else { ++errors; } done: LT_DLMUTEX_UNLOCK (); return errors; } static lt_module presym_open (loader_data, filename) lt_user_data loader_data; const char *filename; { lt_dlsymlists_t *lists; lt_module module = (lt_module) 0; LT_DLMUTEX_LOCK (); lists = preloaded_symbols; if (!lists) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_SYMBOLS)); goto done; } /* Can't use NULL as the reflective symbol header, as NULL is used to mark the end of the entire symbol list. Self-dlpreopened symbols follow this magic number, chosen to be an unlikely clash with a real module name. */ if (!filename) { filename = "@PROGRAM@"; } while (lists) { const lt_dlsymlist *syms = lists->syms; while (syms->name) { if (!syms->address && strcmp(syms->name, filename) == 0) { module = (lt_module) syms; goto done; } ++syms; } lists = lists->next; } LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); done: LT_DLMUTEX_UNLOCK (); return module; } static int presym_close (loader_data, module) lt_user_data loader_data; lt_module module; { /* Just to silence gcc -Wall */ module = 0; return 0; } static lt_ptr presym_sym (loader_data, module, symbol) lt_user_data loader_data; lt_module module; const char *symbol; { lt_dlsymlist *syms = (lt_dlsymlist*) module; ++syms; while (syms->address) { if (strcmp(syms->name, symbol) == 0) { return syms->address; } ++syms; } LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); return 0; } static struct lt_user_dlloader presym = { 0, presym_open, presym_close, presym_sym, presym_exit, 0 }; /* --- DYNAMIC MODULE LOADING --- */ /* The type of a function used at each iteration of foreach_dirinpath(). */ typedef int foreach_callback_func LT_PARAMS((char *filename, lt_ptr data1, lt_ptr data2)); static int foreach_dirinpath LT_PARAMS((const char *search_path, const char *base_name, foreach_callback_func *func, lt_ptr data1, lt_ptr data2)); static int find_file_callback LT_PARAMS((char *filename, lt_ptr data, lt_ptr ignored)); static int find_handle_callback LT_PARAMS((char *filename, lt_ptr data, lt_ptr ignored)); static int foreachfile_callback LT_PARAMS((char *filename, lt_ptr data1, lt_ptr data2)); static int canonicalize_path LT_PARAMS((const char *path, char **pcanonical)); static int argzize_path LT_PARAMS((const char *path, char **pargz, size_t *pargz_len)); static FILE *find_file LT_PARAMS((const char *search_path, const char *base_name, char **pdir)); static lt_dlhandle *find_handle LT_PARAMS((const char *search_path, const char *base_name, lt_dlhandle *handle)); static int find_module LT_PARAMS((lt_dlhandle *handle, const char *dir, const char *libdir, const char *dlname, const char *old_name, int installed)); static int free_vars LT_PARAMS((char *dlname, char *oldname, char *libdir, char *deplibs)); static int load_deplibs LT_PARAMS((lt_dlhandle handle, char *deplibs)); static int trim LT_PARAMS((char **dest, const char *str)); static int try_dlopen LT_PARAMS((lt_dlhandle *handle, const char *filename)); static int tryall_dlopen LT_PARAMS((lt_dlhandle *handle, const char *filename)); static int unload_deplibs LT_PARAMS((lt_dlhandle handle)); static int lt_argz_insert LT_PARAMS((char **pargz, size_t *pargz_len, char *before, const char *entry)); static int lt_argz_insertinorder LT_PARAMS((char **pargz, size_t *pargz_len, const char *entry)); static int lt_dlpath_insertdir LT_PARAMS((char **ppath, char *before, const char *dir)); static char *user_search_path= 0; static lt_dlloader *loaders = 0; static lt_dlhandle handles = 0; static int initialized = 0; /* Initialize libltdl. */ int lt_dlinit () { int errors = 0; LT_DLMUTEX_LOCK (); /* Initialize only at first call. */ if (++initialized == 1) { handles = 0; user_search_path = 0; /* empty search path */ #if HAVE_LIBDL && !defined(__CYGWIN__) errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dl, "dlopen"); #endif #if HAVE_SHL_LOAD errors += lt_dlloader_add (lt_dlloader_next (0), &sys_shl, "dlopen"); #endif #ifdef __WINDOWS__ errors += lt_dlloader_add (lt_dlloader_next (0), &sys_wll, "dlopen"); #endif #ifdef __BEOS__ errors += lt_dlloader_add (lt_dlloader_next (0), &sys_bedl, "dlopen"); #endif #if HAVE_DLD errors += lt_dlloader_add (lt_dlloader_next (0), &sys_dld, "dld"); #endif errors += lt_dlloader_add (lt_dlloader_next (0), &presym, "dlpreload"); if (presym_init (presym.dlloader_data)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INIT_LOADER)); ++errors; } else if (errors != 0) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (DLOPEN_NOT_SUPPORTED)); ++errors; } } LT_DLMUTEX_UNLOCK (); return errors; } int lt_dlpreload (preloaded) const lt_dlsymlist *preloaded; { int errors = 0; if (preloaded) { errors = presym_add_symlist (preloaded); } else { presym_free_symlists(); LT_DLMUTEX_LOCK (); if (default_preloaded_symbols) { errors = lt_dlpreload (default_preloaded_symbols); } LT_DLMUTEX_UNLOCK (); } return errors; } int lt_dlpreload_default (preloaded) const lt_dlsymlist *preloaded; { LT_DLMUTEX_LOCK (); default_preloaded_symbols = preloaded; LT_DLMUTEX_UNLOCK (); return 0; } int lt_dlexit () { /* shut down libltdl */ lt_dlloader *loader; int errors = 0; LT_DLMUTEX_LOCK (); loader = loaders; if (!initialized) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SHUTDOWN)); ++errors; goto done; } /* shut down only at last call. */ if (--initialized == 0) { int level; while (handles && LT_DLIS_RESIDENT (handles)) { handles = handles->next; } /* close all modules */ for (level = 1; handles; ++level) { lt_dlhandle cur = handles; int saw_nonresident = 0; while (cur) { lt_dlhandle tmp = cur; cur = cur->next; if (!LT_DLIS_RESIDENT (tmp)) saw_nonresident = 1; if (!LT_DLIS_RESIDENT (tmp) && tmp->info.ref_count <= level) { if (lt_dlclose (tmp)) { ++errors; } } } /* done if only resident modules are left */ if (!saw_nonresident) break; } /* close all loaders */ while (loader) { lt_dlloader *next = loader->next; lt_user_data data = loader->dlloader_data; if (loader->dlloader_exit && loader->dlloader_exit (data)) { ++errors; } LT_DLMEM_REASSIGN (loader, next); } loaders = 0; } done: LT_DLMUTEX_UNLOCK (); return errors; } // returns number of errors, so 0=success // returns handle in *handle, if one is found. static int tryall_dlopen (handle, filename) lt_dlhandle *handle; const char *filename; { lt_dlhandle cur; lt_dlloader *loader; const char *saved_error; int errors = 0; LT_DLMUTEX_GETERROR (saved_error); LT_DLMUTEX_LOCK (); cur = handles; loader = loaders; /* check whether the module was already opened */ while (cur) { /* try to dlopen the program itself? */ if (!cur->info.filename && !filename) { break; } if (cur->info.filename && filename && strcmp (cur->info.filename, filename) == 0) { break; } cur = cur->next; } if (cur) { ++cur->info.ref_count; *handle = cur; goto done; } cur = *handle; if (filename) { cur->info.filename = lt_estrdup (filename); if (!cur->info.filename) { ++errors; goto done; } } else { cur->info.filename = 0; } // Call access() to see if it exists first. If not return FILE_NOT_FOUND // instead of CANNOT_OPEN. if (access (cur->info.filename, R_OK) != 0) { LT_DLFREE (cur->info.filename); LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); ++errors; goto done; } while (loader) { lt_user_data data = loader->dlloader_data; LTDEBUG_PRINTF(("Trying to open '%s' using loader '%s'\n", filename, loader->loader_name)); cur->module = loader->module_open (data, filename); if (cur->module != 0) { LTDEBUG_PRINTF(("Load '%s' succeeded.\n", filename)); break; } loader = loader->next; } if (!loader) { LT_DLFREE (cur->info.filename); ++errors; goto done; } cur->loader = loader; LT_DLMUTEX_SETERROR (saved_error); done: LT_DLMUTEX_UNLOCK (); return errors; } static int tryall_dlopen_module (handle, prefix, dirname, dlname) lt_dlhandle *handle; const char *prefix; const char *dirname; const char *dlname; { int error = 0; char *filename = 0; size_t filename_len = 0; #ifdef __GNUC__ #warning dirname could be null #endif size_t dirname_len = LT_STRLEN (dirname); if (dirname == NULL) { LTDEBUG_PRINTF(("leaving tryall_dlopen_module early because dirname is NULL\n")); return 1; } assert (handle); assert (dirname); assert (dlname); #ifdef LT_DIRSEP_CHAR /* Only canonicalized names (i.e. with DIRSEP chars already converted) should make it into this function: */ assert (strchr (dirname, LT_DIRSEP_CHAR) == 0); #endif if (dirname[dirname_len -1] == '/') --dirname_len; filename_len = dirname_len + 1 + LT_STRLEN (dlname); /* Allocate memory, and combine DIRNAME and MODULENAME into it. The PREFIX (if any) is handled below. */ filename = LT_EMALLOC (char, dirname_len + 1 + filename_len + 1); if (!filename) return 1; sprintf (filename, "%.*s/%s", (int) dirname_len, dirname, dlname); /* Now that we have combined DIRNAME and MODULENAME, if there is also a PREFIX to contend with, simply recurse with the arguments shuffled. Otherwise, attempt to open FILENAME as a module. */ if (prefix) { error += tryall_dlopen_module (handle, (const char *) 0, prefix, filename); } else if (tryall_dlopen (handle, filename) != 0) { ++error; } LT_DLFREE (filename); return error; } static int find_module (handle, dir, libdir, dlname, old_name, installed) lt_dlhandle *handle; const char *dir; const char *libdir; const char *dlname; const char *old_name; int installed; { /* Try to open the old library first; if it was dlpreopened, we want the preopened version of it, even if a dlopenable module is available. */ if (old_name && tryall_dlopen (handle, old_name) == 0) { return 0; } /* Try to open the dynamic library. */ if (dlname) { /* try to open the installed module */ if (installed && libdir) { if (tryall_dlopen_module (handle, (const char *) 0, libdir, dlname) == 0) return 0; } /* try to open the not-installed module */ if (!installed) { if (tryall_dlopen_module (handle, dir, objdir, dlname) == 0) return 0; } /* maybe it was moved to another directory */ { if (tryall_dlopen_module (handle, (const char *) 0, dir, dlname) == 0) return 0; } } return 1; } static int canonicalize_path (path, pcanonical) const char *path; char **pcanonical; { char *canonical = 0; assert (path && *path); assert (pcanonical); canonical = LT_EMALLOC (char, 1+ LT_STRLEN (path)); if (!canonical) return 1; { size_t dest = 0; size_t src; for (src = 0; path[src] != LT_EOS_CHAR; ++src) { /* Path separators are not copied to the beginning or end of the destination, or if another separator would follow immediately. */ if (path[src] == LT_PATHSEP_CHAR) { if ((dest == 0) || (path[1+ src] == LT_PATHSEP_CHAR) || (path[1+ src] == LT_EOS_CHAR)) continue; } /* Anything other than a directory separator is copied verbatim. */ if ((path[src] != '/') #ifdef LT_DIRSEP_CHAR && (path[src] != LT_DIRSEP_CHAR) #endif ) { canonical[dest++] = path[src]; } /* Directory separators are converted and copied only if they are not at the end of a path -- i.e. before a path separator or NULL terminator. */ else if ((path[1+ src] != LT_PATHSEP_CHAR) && (path[1+ src] != LT_EOS_CHAR) #ifdef LT_DIRSEP_CHAR && (path[1+ src] != LT_DIRSEP_CHAR) #endif && (path[1+ src] != '/')) { canonical[dest++] = '/'; } } /* Add an end-of-string marker at the end. */ canonical[dest] = LT_EOS_CHAR; } /* Assign new value. */ *pcanonical = canonical; return 0; } static int argzize_path (path, pargz, pargz_len) const char *path; char **pargz; size_t *pargz_len; { error_t error; assert (path); assert (pargz); assert (pargz_len); if ((error = argz_create_sep (path, LT_PATHSEP_CHAR, pargz, pargz_len))) { switch (error) { case ENOMEM: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); break; default: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); break; } return 1; } return 0; } /* Repeatedly call FUNC with each LT_PATHSEP_CHAR delimited element of SEARCH_PATH and references to DATA1 and DATA2, until FUNC returns non-zero or all elements are exhausted. If BASE_NAME is non-NULL, it is appended to each SEARCH_PATH element before FUNC is called. */ static int foreach_dirinpath (search_path, base_name, func, data1, data2) const char *search_path; const char *base_name; foreach_callback_func *func; lt_ptr data1; lt_ptr data2; { int result = 0; int filenamesize = 0; int lenbase = LT_STRLEN (base_name); size_t argz_len = 0; char * argz = 0; char * filename = 0; char * canonical = 0; LT_DLMUTEX_LOCK (); if (!search_path || !*search_path) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); goto cleanup; } if (canonicalize_path (search_path, &canonical) != 0) goto cleanup; if (argzize_path (canonical, &argz, &argz_len) != 0) goto cleanup; { char *dir_name = 0; while ((dir_name = argz_next (argz, argz_len, dir_name))) { int lendir = LT_STRLEN (dir_name); if (lendir +1 +lenbase >= filenamesize) { LT_DLFREE (filename); filenamesize = lendir +1 +lenbase +1; /* "/d" + '/' + "f" + '\0' */ filename = LT_EMALLOC (char, filenamesize); if (!filename) goto cleanup; } strncpy (filename, dir_name, lendir); if (base_name && *base_name) { if (filename[lendir -1] != '/') filename[lendir++] = '/'; strcpy (filename +lendir, base_name); } if ((result = (*func) (filename, data1, data2))) { break; } } } cleanup: LT_DLFREE (argz); LT_DLFREE (canonical); LT_DLFREE (filename); LT_DLMUTEX_UNLOCK (); return result; } /* If FILEPATH can be opened, store the name of the directory component in DATA1, and the opened FILE* structure address in DATA2. Otherwise DATA1 is unchanged, but DATA2 is set to a pointer to NULL. */ static int find_file_callback (filename, data1, data2) char *filename; lt_ptr data1; lt_ptr data2; { char **pdir = (char **) data1; FILE **pfile = (FILE **) data2; int is_done = 0; assert (filename && *filename); assert (pdir); assert (pfile); if ((*pfile = fopen (filename, LT_READTEXT_MODE))) { char *dirend = strrchr (filename, '/'); LTDEBUG_PRINTF(("find_file_callback opening file '%s'...ok\n", filename)); if (dirend > filename) *dirend = LT_EOS_CHAR; LT_DLFREE (*pdir); *pdir = lt_estrdup (filename); is_done = (*pdir == 0) ? -1 : 1; } else { LTDEBUG_PRINTF(("find_file_callback opening file '%s'...failed\n", filename)); } return is_done; } static FILE * find_file (search_path, base_name, pdir) const char *search_path; const char *base_name; char **pdir; { FILE *file = 0; foreach_dirinpath (search_path, base_name, find_file_callback, pdir, &file); return file; } static int find_handle_callback (filename, data, ignored) char *filename; lt_ptr data; lt_ptr ignored; { lt_dlhandle *handle = (lt_dlhandle *) data; int found = (0 == access (filename, R_OK)); LTDEBUG_PRINTF(("find_handle_callback searching for '%s'...%s\n", filename, found?"found":"not found")); /* Bail out if file cannot be read... */ if (!found) return 0; /* Try to dlopen the file, but do not continue searching in any case. */ if (tryall_dlopen (handle, filename) != 0) *handle = 0; return 1; } /* If HANDLE was found return it, otherwise return 0. If HANDLE was found but could not be opened, *HANDLE will be set to 0. */ static lt_dlhandle * find_handle (search_path, base_name, handle) const char *search_path; const char *base_name; lt_dlhandle *handle; { if (!search_path) return 0; if (!foreach_dirinpath (search_path, base_name, find_handle_callback, handle, 0)) return 0; return handle; } static int load_deplibs (handle, deplibs) lt_dlhandle handle; char *deplibs; { #if LTDL_DLOPEN_DEPLIBS char *p, *save_search_path = 0; int depcount = 0; int i; char **names = 0; #endif int errors = 0; handle->depcount = 0; #if LTDL_DLOPEN_DEPLIBS if (!deplibs) { return errors; } ++errors; LT_DLMUTEX_LOCK (); if (user_search_path) { save_search_path = lt_estrdup (user_search_path); if (!save_search_path) goto cleanup; } /* extract search paths and count deplibs */ p = deplibs; while (*p) { if (!isspace ((int) *p)) { char *end = p+1; while (*end && !isspace((int) *end)) { ++end; } if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0) { char save = *end; *end = 0; /* set a temporary string terminator */ if (lt_dladdsearchdir(p+2)) { goto cleanup; } *end = save; } else { ++depcount; } p = end; } else { ++p; } } /* restore the old search path */ LT_DLFREE (user_search_path); user_search_path = save_search_path; LT_DLMUTEX_UNLOCK (); if (!depcount) { errors = 0; goto cleanup; } names = LT_EMALLOC (char *, depcount * sizeof (char*)); if (!names) goto cleanup; /* now only extract the actual deplibs */ depcount = 0; p = deplibs; while (*p) { if (isspace ((int) *p)) { ++p; } else { char *end = p+1; while (*end && !isspace ((int) *end)) { ++end; } if (strncmp(p, "-L", 2) != 0 && strncmp(p, "-R", 2) != 0) { char *name; char save = *end; *end = 0; /* set a temporary string terminator */ if (strncmp(p, "-l", 2) == 0) { size_t name_len = 3+ /* "lib" */ LT_STRLEN (p + 2); name = LT_EMALLOC (char, 1+ name_len); if (name) sprintf (name, "lib%s", p+2); } else name = lt_estrdup(p); if (!name) goto cleanup_names; names[depcount++] = name; *end = save; } p = end; } } /* load the deplibs (in reverse order) At this stage, don't worry if the deplibs do not load correctly, they may already be statically linked into the loading application for instance. There will be a more enlightening error message later on if the loaded module cannot resolve all of its symbols. */ if (depcount) { int j = 0; handle->deplibs = (lt_dlhandle*) LT_EMALLOC (lt_dlhandle *, depcount); if (!handle->deplibs) goto cleanup; for (i = 0; i < depcount; ++i) { handle->deplibs[j] = lt_dlopenext(names[depcount-1-i]); if (handle->deplibs[j]) { ++j; } } handle->depcount = j; /* Number of successfully loaded deplibs */ errors = 0; } cleanup_names: for (i = 0; i < depcount; ++i) { LT_DLFREE (names[i]); } cleanup: LT_DLFREE (names); #endif return errors; } static int unload_deplibs (handle) lt_dlhandle handle; { int i; int errors = 0; if (handle->depcount) { for (i = 0; i < handle->depcount; ++i) { if (!LT_DLIS_RESIDENT (handle->deplibs[i])) { errors += lt_dlclose (handle->deplibs[i]); } } } return errors; } static int trim (dest, str) char **dest; const char *str; { /* remove the leading and trailing "'" from str and store the result in dest */ const char *end = strrchr (str, '\''); int len = LT_STRLEN (str); char *tmp; LT_DLFREE (*dest); if (len > 3 && str[0] == '\'') { tmp = LT_EMALLOC (char, end - str); if (!tmp) return 1; strncpy(tmp, &str[1], (end - str) - 1); tmp[len-3] = LT_EOS_CHAR; *dest = tmp; } else { *dest = 0; } return 0; } static int free_vars (dlname, oldname, libdir, deplibs) char *dlname; char *oldname; char *libdir; char *deplibs; { LT_DLFREE (dlname); LT_DLFREE (oldname); LT_DLFREE (libdir); LT_DLFREE (deplibs); return 0; } // returns number of errors, so 0=success. // phandle is a pointer to an lt_dlhandle, which must initially be NULL. // On success (return value=0), *phandle is changed to point to the new // lt_dlhandle. int try_dlopen (phandle, filename) lt_dlhandle *phandle; const char *filename; { const char * ext = 0; const char * saved_error = 0; char * canonical = 0; char * base_name = 0; char * dir = 0; char * name = 0; int errors = 0; lt_dlhandle newhandle; assert (phandle); assert (*phandle == 0); LT_DLMUTEX_GETERROR (saved_error); /* dlopen self? */ if (!filename) { *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); if (*phandle == 0) return 1; memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); newhandle = *phandle; /* lt_dlclose()ing yourself is very bad! Disallow it. */ LT_DLSET_FLAG (*phandle, LT_DLRESIDENT_FLAG); if (tryall_dlopen (&newhandle, 0) != 0) { LT_DLFREE (*phandle); // this sets *phandle=NULL return 1; } goto register_handle; } assert (filename && *filename); /* Doing this immediately allows internal functions to safely assume only canonicalized paths are passed. */ if (canonicalize_path (filename, &canonical) != 0) { ++errors; goto cleanup; } /* If the canonical module name is a path (relative or absolute) then split it into a directory part and a name part. */ base_name = strrchr (canonical, '/'); if (base_name) { size_t dirlen = (1+ base_name) - canonical; dir = LT_EMALLOC (char, 1+ dirlen); if (!dir) { ++errors; goto cleanup; } strncpy (dir, canonical, dirlen); dir[dirlen] = LT_EOS_CHAR; ++base_name; LTDEBUG_PRINTF(("in base_name not NULL section. dir='%s', base_name='%s', canonical='%s'\n", dir, base_name, canonical)); } else { LT_DLMEM_REASSIGN (base_name, canonical); LTDEBUG_PRINTF(("in base_name=NULL section. dir=NULL, base_name='%s', canonical='%s'\n", base_name, canonical)); } assert (base_name && *base_name); /* Check whether we are opening a libtool module (.la extension). */ ext = strrchr (base_name, '.'); if (ext && strcmp (ext, archive_ext) == 0) { /* this seems to be a libtool module */ FILE * file = 0; char * dlname = 0; char * old_name = 0; char * libdir = 0; char * deplibs = 0; char * line = 0; size_t line_len; int i; /* if we can't find the installed flag, it is probably an installed libtool archive, produced with an old version of libtool */ int installed = 1; /* extract the module name from the file name */ name = LT_EMALLOC (char, ext - base_name + 1); if (!name) { ++errors; goto cleanup; } /* canonicalize the module name */ for (i = 0; i < ext - base_name; ++i) { if (isalnum ((int)(base_name[i]))) { name[i] = base_name[i]; } else { name[i] = '_'; } } name[ext - base_name] = LT_EOS_CHAR; /* Now try to open the .la file. If there is no directory name component, try to find it first in user_search_path and then other prescribed paths. Otherwise (or in any case if the module was not yet found) try opening just the module name as passed. */ if (!dir) { const char *search_path; LT_DLMUTEX_LOCK (); search_path = user_search_path; if (search_path) file = find_file (user_search_path, base_name, &dir); LT_DLMUTEX_UNLOCK (); if (!file) { search_path = getenv (LTDL_SEARCHPATH_VAR); if (search_path) file = find_file (search_path, base_name, &dir); } #ifdef LTDL_SHLIBPATH_VAR if (!file) { search_path = getenv (LTDL_SHLIBPATH_VAR); if (search_path) file = find_file (search_path, base_name, &dir); } #endif #ifdef LTDL_SYSSEARCHPATH if (!file && sys_search_path) { file = find_file (sys_search_path, base_name, &dir); } #endif } if (!file) { LTDEBUG_PRINTF(("try_dlopen opening file '%s'\n", filename)); file = fopen (filename, LT_READTEXT_MODE); #ifdef __GNUC__ #warning dir is still NULL #endif } /* If we didn't find the file by now, it really isn't there. Set the status flag, and bail out. */ if (!file) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); ++errors; goto cleanup; } line_len = LT_FILENAME_MAX; line = LT_EMALLOC (char, line_len); if (!line) { fclose (file); ++errors; goto cleanup; } /* read the .la file */ while (!feof (file)) { if (!fgets (line, line_len, file)) { break; } /* Handle the case where we occasionally need to read a line that is longer than the initial buffer size. */ while (line[LT_STRLEN(line) -1] != '\n') { line = LT_DLREALLOC (char, line, line_len *2); if (!fgets (&line[line_len -1], line_len +1, file)) { break; } line_len *= 2; } if (line[0] == '\n' || line[0] == '#') { continue; } #undef STR_DLNAME #define STR_DLNAME "dlname=" if (strncmp (line, STR_DLNAME, sizeof (STR_DLNAME) - 1) == 0) { errors += trim (&dlname, &line[sizeof (STR_DLNAME) - 1]); } #undef STR_OLD_LIBRARY #define STR_OLD_LIBRARY "old_library=" else if (strncmp (line, STR_OLD_LIBRARY, sizeof (STR_OLD_LIBRARY) - 1) == 0) { errors += trim (&old_name, &line[sizeof (STR_OLD_LIBRARY) - 1]); } #undef STR_LIBDIR #define STR_LIBDIR "libdir=" else if (strncmp (line, STR_LIBDIR, sizeof (STR_LIBDIR) - 1) == 0) { errors += trim (&libdir, &line[sizeof(STR_LIBDIR) - 1]); } #undef STR_DL_DEPLIBS #define STR_DL_DEPLIBS "dependency_libs=" else if (strncmp (line, STR_DL_DEPLIBS, sizeof (STR_DL_DEPLIBS) - 1) == 0) { errors += trim (&deplibs, &line[sizeof (STR_DL_DEPLIBS) - 1]); } else if (strcmp (line, "installed=yes\n") == 0) { installed = 1; } else if (strcmp (line, "installed=no\n") == 0) { installed = 0; } #undef STR_LIBRARY_NAMES #define STR_LIBRARY_NAMES "library_names=" else if (! dlname && strncmp (line, STR_LIBRARY_NAMES, sizeof (STR_LIBRARY_NAMES) - 1) == 0) { char *last_libname; errors += trim (&dlname, &line[sizeof (STR_LIBRARY_NAMES) - 1]); if (!errors && dlname && (last_libname = strrchr (dlname, ' ')) != 0) { last_libname = lt_estrdup (last_libname + 1); if (!last_libname) { ++errors; goto cleanup; } LT_DLMEM_REASSIGN (dlname, last_libname); } } if (errors) break; } fclose (file); LT_DLFREE (line); /* allocate the handle */ *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); if (*phandle == 0) ++errors; if (errors) { free_vars (dlname, old_name, libdir, deplibs); LT_DLFREE (*phandle); goto cleanup; } assert (*phandle); memset (*phandle, 0, sizeof(struct lt_dlhandle_struct)); if (load_deplibs (*phandle, deplibs) == 0) { newhandle = *phandle; /* find_module may replace newhandle */ if (find_module (&newhandle, dir, libdir, dlname, old_name, installed)) { unload_deplibs (*phandle); ++errors; } } else { ++errors; } free_vars (dlname, old_name, libdir, deplibs); if (errors) { LT_DLFREE (*phandle); // sets *phandle=NULL goto cleanup; } if (*phandle != newhandle) { unload_deplibs (*phandle); } } else { /* not a libtool module */ *phandle = (lt_dlhandle) LT_EMALLOC (struct lt_dlhandle_struct, 1); if (*phandle == 0) { ++errors; goto cleanup; } memset (*phandle, 0, sizeof (struct lt_dlhandle_struct)); newhandle = *phandle; /* If the module has no directory name component, try to find it first in user_search_path and then other prescribed paths. Otherwise (or in any case if the module was not yet found) try opening just the module name as passed. */ if ((dir || (!find_handle (user_search_path, base_name, &newhandle) && !find_handle (getenv (LTDL_SEARCHPATH_VAR), base_name, &newhandle) #ifdef LTDL_SHLIBPATH_VAR && !find_handle (getenv (LTDL_SHLIBPATH_VAR), base_name, &newhandle) #endif #ifdef LTDL_SYSSEARCHPATH && !find_handle (sys_search_path, base_name, &newhandle) #endif ))) { // Directory component was specified, or all find_handle() calls // failed to find the lib. This is our last try. errors = tryall_dlopen (&newhandle, filename); } if (!newhandle || errors>0) { LT_DLFREE (*phandle); ++errors; goto cleanup; } } register_handle: LT_DLMEM_REASSIGN (*phandle, newhandle); if ((*phandle)->info.ref_count == 0) { (*phandle)->info.ref_count = 1; LT_DLMEM_REASSIGN ((*phandle)->info.name, name); LT_DLMUTEX_LOCK (); (*phandle)->next = handles; handles = *phandle; LT_DLMUTEX_UNLOCK (); } LT_DLMUTEX_SETERROR (saved_error); cleanup: LT_DLFREE (dir); LT_DLFREE (name); LT_DLFREE (canonical); return errors; } lt_dlhandle lt_dlopen (filename) const char *filename; { lt_dlhandle handle = 0; /* Just incase we missed a code path in try_dlopen() that reports an error, but forgets to reset handle... */ if (try_dlopen (&handle, filename) != 0) return 0; // If we're going to return a handle, be sure that has its loader // field filled in. This is in response to some bugs in which dlopen() // would return valid-looking handle with NULL loader, causing crashes // later. if (handle) assert (handle->loader != NULL); return handle; } /* If the last error messge store was `FILE_NOT_FOUND', then return non-zero. */ int file_not_found () { const char *error = 0; LT_DLMUTEX_GETERROR (error); if (error == LT_DLSTRERROR (FILE_NOT_FOUND)) return 1; return 0; } /* If FILENAME has an ARCHIVE_EXT or SHLIB_EXT extension, try to open the FILENAME as passed. Otherwise try appending ARCHIVE_EXT, and if a file is still not found try again with SHLIB_EXT appended instead. */ lt_dlhandle lt_dlopenext (filename) const char *filename; { lt_dlhandle handle = 0; char * tmp = 0; char * ext = 0; int len; int errors = 0; int file_found = 1; /* until proven otherwise */ if (!filename) { return lt_dlopen (filename); } assert (filename); len = LT_STRLEN (filename); ext = strrchr (filename, '.'); /* If FILENAME already bears a suitable extension, there is no need to try appending additional extensions. */ if (ext && ((strcmp (ext, archive_ext) == 0) #ifdef LTDL_SHLIB_EXT || (strcmp (ext, shlib_ext) == 0) #endif )) { return lt_dlopen (filename); } /* First try appending ARCHIVE_EXT. */ tmp = LT_EMALLOC (char, len + LT_STRLEN (archive_ext) + 1); if (!tmp) return 0; strcpy (tmp, filename); strcat (tmp, archive_ext); errors = try_dlopen (&handle, tmp); /* If we found FILENAME, stop searching -- whether we were able to load the file as a module or not. If the file exists but loading failed, it is better to return an error message here than to report FILE_NOT_FOUND when the alternatives (foo.so etc) are not in the module search path. */ if (handle || ((errors > 0) && !file_not_found ())) { LT_DLFREE (tmp); // If we're going to return a handle, be sure that has its loader // field filled in. This is in response to some bugs in which dlopen() // would return valid-looking handle with NULL loader, causing crashes // later. if (handle) assert (handle->loader != NULL); return handle; } #ifdef LTDL_SHLIB_EXT /* Try appending SHLIB_EXT. */ if (LT_STRLEN (shlib_ext) > LT_STRLEN (archive_ext)) { LT_DLFREE (tmp); tmp = LT_EMALLOC (char, len + LT_STRLEN (shlib_ext) + 1); if (!tmp) return 0; strcpy (tmp, filename); } else { tmp[len] = LT_EOS_CHAR; } strcat(tmp, shlib_ext); errors = try_dlopen (&handle, tmp); /* As before, if the file was found but loading failed, return now with the current error message. */ if (handle || ((errors > 0) && !file_not_found ())) { LT_DLFREE (tmp); // If we're going to return a handle, be sure that has its loader // field filled in. This is in response to some bugs in which dlopen() // would return valid-looking handle with NULL loader, causing crashes // later. if (handle) assert (handle->loader != NULL); return handle; } #endif /* Still here? Then we really did fail to locate any of the file names we tried. */ LT_DLMUTEX_SETERROR (LT_DLSTRERROR (FILE_NOT_FOUND)); LT_DLFREE (tmp); return 0; } int lt_argz_insert (pargz, pargz_len, before, entry) char **pargz; size_t *pargz_len; char *before; const char *entry; { error_t error; if ((error = argz_insert (pargz, pargz_len, before, entry))) { switch (error) { case ENOMEM: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (NO_MEMORY)); break; default: LT_DLMUTEX_SETERROR (LT_DLSTRERROR (UNKNOWN)); break; } return 1; } return 0; } int lt_argz_insertinorder (pargz, pargz_len, entry) char **pargz; size_t *pargz_len; const char *entry; { char *before = 0; assert (pargz); assert (pargz_len); assert (entry && *entry); if (*pargz) while ((before = argz_next (*pargz, *pargz_len, before))) { int cmp = strcmp (entry, before); if (cmp < 0) break; if (cmp == 0) return 0; /* No duplicates! */ } return lt_argz_insert (pargz, pargz_len, before, entry); } int lt_argz_insertdir (pargz, pargz_len, dirnam, dp) char **pargz; size_t *pargz_len; const char *dirnam; struct dirent *dp; { char *buf = 0; size_t buf_len = 0; char *end = 0; size_t end_offset = 0; size_t dir_len = 0; int errors = 0; assert (pargz); assert (pargz_len); assert (dp); dir_len = LT_STRLEN (dirnam); end = dp->d_name + LT_D_NAMLEN(dp); /* Ignore version numbers. */ { char *p; for (p = end; p -1 > dp->d_name; --p) if (strchr (".0123456789", p[-1]) == 0) break; if (*p == '.') end = p; } /* Ignore filename extension. */ { char *p; for (p = end -1; p > dp->d_name; --p) if (*p == '.') { end = p; break; } } /* Prepend the directory name. */ end_offset = end - dp->d_name; buf_len = dir_len + 1+ end_offset; buf = LT_EMALLOC (char, 1+ buf_len); if (!buf) return ++errors; assert (buf); strcpy (buf, dirnam); strcat (buf, "/"); strncat (buf, dp->d_name, end_offset); buf[buf_len] = LT_EOS_CHAR; /* Try to insert (in order) into ARGZ/ARGZ_LEN. */ if (lt_argz_insertinorder (pargz, pargz_len, buf) != 0) ++errors; LT_DLFREE (buf); return errors; } int list_files_by_dir (dirnam, pargz, pargz_len) const char *dirnam; char **pargz; size_t *pargz_len; { DIR *dirp = 0; int errors = 0; assert (dirnam && *dirnam); assert (pargz); assert (pargz_len); assert (dirnam[LT_STRLEN(dirnam) -1] != '/'); dirp = opendir (dirnam); if (dirp) { struct dirent *dp = 0; while ((dp = readdir (dirp))) if (dp->d_name[0] != '.') if (lt_argz_insertdir (pargz, pargz_len, dirnam, dp)) { ++errors; break; } closedir (dirp); } else ++errors; return errors; } /* If there are any files in DIRNAME, call the function passed in DATA1 (with the name of each file and DATA2 as arguments). */ static int foreachfile_callback (dirname, data1, data2) char *dirname; lt_ptr data1; lt_ptr data2; { int (*func) LT_PARAMS((const char *filename, lt_ptr data)) = (int (*) LT_PARAMS((const char *filename, lt_ptr data))) data1; int is_done = 0; char *argz = 0; size_t argz_len = 0; if (list_files_by_dir (dirname, &argz, &argz_len) != 0) goto cleanup; if (!argz) goto cleanup; { char *filename = 0; while ((filename = argz_next (argz, argz_len, filename))) if ((is_done = (*func) (filename, data2))) break; } cleanup: LT_DLFREE (argz); return is_done; } /* Call FUNC for each unique extensionless file in SEARCH_PATH, along with DATA. The filenames passed to FUNC would be suitable for passing to lt_dlopenext. The extensions are stripped so that individual modules do not generate several entries (e.g. libfoo.la, libfoo.so, libfoo.so.1, libfoo.so.1.0.0). If SEARCH_PATH is NULL, then the same directories that lt_dlopen would search are examined. */ int lt_dlforeachfile (search_path, func, data) const char *search_path; int (*func) LT_PARAMS ((const char *filename, lt_ptr data)); lt_ptr data; { int is_done = 0; if (search_path) { /* If a specific path was passed, search only the directories listed in it. */ is_done = foreach_dirinpath (search_path, 0, foreachfile_callback, func, data); } else { /* Otherwise search the default paths. */ is_done = foreach_dirinpath (user_search_path, 0, foreachfile_callback, func, data); if (!is_done) { is_done = foreach_dirinpath (getenv("LTDL_LIBRARY_PATH"), 0, foreachfile_callback, func, data); } #ifdef LTDL_SHLIBPATH_VAR if (!is_done) { is_done = foreach_dirinpath (getenv(LTDL_SHLIBPATH_VAR), 0, foreachfile_callback, func, data); } #endif #ifdef LTDL_SYSSEARCHPATH if (!is_done) { is_done = foreach_dirinpath (getenv(LTDL_SYSSEARCHPATH), 0, foreachfile_callback, func, data); } #endif } return is_done; } int lt_dlclose (handle) lt_dlhandle handle; { lt_dlhandle cur, last; int errors = 0; LT_DLMUTEX_LOCK (); /* check whether the handle is valid */ last = cur = handles; while (cur && handle != cur) { last = cur; cur = cur->next; } if (!cur) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); ++errors; goto done; } handle->info.ref_count--; /* Note that even with resident modules, we must track the ref_count correctly incase the user decides to reset the residency flag later (even though the API makes no provision for that at the moment). */ if (handle->info.ref_count <= 0 && !LT_DLIS_RESIDENT (handle)) { lt_user_data data = handle->loader->dlloader_data; if (handle != handles) { last->next = handle->next; } else { handles = handle->next; } errors += handle->loader->module_close (data, handle->module); errors += unload_deplibs(handle); LT_DLFREE (handle->info.filename); LT_DLFREE (handle->info.name); LT_DLFREE (handle); goto done; } if (LT_DLIS_RESIDENT (handle)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (CLOSE_RESIDENT_MODULE)); ++errors; } done: LT_DLMUTEX_UNLOCK (); return errors; } lt_ptr lt_dlsym (handle, symbol) lt_dlhandle handle; const char *symbol; { int lensym; char lsym[LT_SYMBOL_LENGTH]; char *sym; lt_ptr address; lt_user_data data; if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); return 0; } if (!symbol) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (SYMBOL_NOT_FOUND)); return 0; } // Due to bugs in lt_dlopen*, some handles were being returned that have a // NULL loader field. Check for this. assert (handle->loader); lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->loader->sym_prefix) + LT_STRLEN (handle->info.name); if (lensym + LT_SYMBOL_OVERHEAD < LT_SYMBOL_LENGTH) { sym = lsym; } else { sym = LT_EMALLOC (char, lensym + LT_SYMBOL_OVERHEAD + 1); if (!sym) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (BUFFER_OVERFLOW)); return 0; } } data = handle->loader->dlloader_data; if (handle->info.name) { const char *saved_error; LT_DLMUTEX_GETERROR (saved_error); /* this is a libtool module */ if (handle->loader->sym_prefix) { strcpy(sym, handle->loader->sym_prefix); strcat(sym, handle->info.name); } else { strcpy(sym, handle->info.name); } strcat(sym, "_LTX_"); strcat(sym, symbol); /* try "modulename_LTX_symbol" */ LTDEBUG_PRINTF(("dlsym looking for '%s'\n", sym)); address = handle->loader->find_sym (data, handle->module, sym); if (address) { if (sym != lsym) { LT_DLFREE (sym); } return address; } LT_DLMUTEX_SETERROR (saved_error); } /* otherwise try "symbol" */ if (handle->loader->sym_prefix) { strcpy(sym, handle->loader->sym_prefix); strcat(sym, symbol); } else { strcpy(sym, symbol); } LTDEBUG_PRINTF(("dlsym looking for '%s'\n", sym)); address = handle->loader->find_sym (data, handle->module, sym); if (sym != lsym) { LT_DLFREE (sym); } return address; } const char * lt_dlerror () { const char *error; LT_DLMUTEX_GETERROR (error); LT_DLMUTEX_SETERROR (0); return error ? error : LT_DLSTRERROR (UNKNOWN); } int lt_dlpath_insertdir (ppath, before, dir) char **ppath; char *before; const char *dir; { int errors = 0; char *canonical = 0; char *argz = 0; size_t argz_len = 0; assert (ppath); assert (dir && *dir); if (canonicalize_path (dir, &canonical) != 0) { ++errors; goto cleanup; } assert (canonical && *canonical); /* If *PPATH is empty, set it to DIR. */ if (*ppath == 0) { assert (!before); /* BEFORE cannot be set without PPATH. */ assert (dir); /* Without DIR, don't call this function! */ *ppath = lt_estrdup (dir); if (*ppath == 0) ++errors; return errors; } assert (ppath && *ppath); if (argzize_path (*ppath, &argz, &argz_len) != 0) { ++errors; goto cleanup; } /* Convert BEFORE into an equivalent offset into ARGZ. This only works if *PPATH is already canonicalized, and hence does not change length with respect to ARGZ. We canonicalize each entry as it is added to the search path, and don't call this function with (uncanonicalized) user paths, so this is a fair assumption. */ if (before) { assert (*ppath <= before); assert (before - *ppath <= strlen (*ppath)); before = before - *ppath + argz; } if (lt_argz_insert (&argz, &argz_len, before, dir) != 0) { ++errors; goto cleanup; } argz_stringify (argz, argz_len, LT_PATHSEP_CHAR); LT_DLMEM_REASSIGN (*ppath, argz); cleanup: LT_DLFREE (canonical); LT_DLFREE (argz); return errors; } int lt_dladdsearchdir (search_dir) const char *search_dir; { int errors = 0; if (search_dir && *search_dir) { LT_DLMUTEX_LOCK (); if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0) ++errors; LT_DLMUTEX_UNLOCK (); } return errors; } int lt_dlinsertsearchdir (before, search_dir) const char *before; const char *search_dir; { int errors = 0; if (before) { LT_DLMUTEX_LOCK (); if ((before < user_search_path) || (before >= user_search_path + LT_STRLEN (user_search_path))) { LT_DLMUTEX_UNLOCK (); LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_POSITION)); return 1; } LT_DLMUTEX_UNLOCK (); } if (search_dir && *search_dir) { LT_DLMUTEX_LOCK (); if (lt_dlpath_insertdir (&user_search_path, (char *) before, search_dir) != 0) { ++errors; } LT_DLMUTEX_UNLOCK (); } return errors; } int lt_dlsetsearchpath (search_path) const char *search_path; { int errors = 0; LT_DLMUTEX_LOCK (); LT_DLFREE (user_search_path); LT_DLMUTEX_UNLOCK (); if (!search_path || !LT_STRLEN (search_path)) { return errors; } LT_DLMUTEX_LOCK (); if (canonicalize_path (search_path, &user_search_path) != 0) ++errors; LT_DLMUTEX_UNLOCK (); return errors; } const char * lt_dlgetsearchpath () { const char *saved_path; LT_DLMUTEX_LOCK (); saved_path = user_search_path; LT_DLMUTEX_UNLOCK (); return saved_path; } int lt_dlmakeresident (handle) lt_dlhandle handle; { int errors = 0; if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); ++errors; } else { LT_DLSET_FLAG (handle, LT_DLRESIDENT_FLAG); } return errors; } int lt_dlisresident (handle) lt_dlhandle handle; { if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); return -1; } return LT_DLIS_RESIDENT (handle); } /* --- MODULE INFORMATION --- */ const lt_dlinfo * lt_dlgetinfo (handle) lt_dlhandle handle; { if (!handle) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_HANDLE)); return 0; } return &(handle->info); } lt_dlhandle lt_dlhandle_next (place) lt_dlhandle place; { return place ? place->next : handles; } int lt_dlforeach (func, data) int (*func) LT_PARAMS((lt_dlhandle handle, lt_ptr data)); lt_ptr data; { int errors = 0; lt_dlhandle cur; LT_DLMUTEX_LOCK (); cur = handles; while (cur) { lt_dlhandle tmp = cur; cur = cur->next; if ((*func) (tmp, data)) { ++errors; break; } } LT_DLMUTEX_UNLOCK (); return errors; } lt_dlcaller_id lt_dlcaller_register () { static lt_dlcaller_id last_caller_id = 0; int result; LT_DLMUTEX_LOCK (); result = ++last_caller_id; LT_DLMUTEX_UNLOCK (); return result; } lt_ptr lt_dlcaller_set_data (key, handle, data) lt_dlcaller_id key; lt_dlhandle handle; lt_ptr data; { int n_elements = 0; lt_ptr stale = (lt_ptr) 0; int i; /* This needs to be locked so that the caller data can be updated simultaneously by different threads. */ LT_DLMUTEX_LOCK (); if (handle->caller_data) while (handle->caller_data[n_elements].key) ++n_elements; for (i = 0; i < n_elements; ++i) { if (handle->caller_data[i].key == key) { stale = handle->caller_data[i].data; break; } } /* Ensure that there is enough room in this handle's caller_data array to accept a new element (and an empty end marker). */ if (i == n_elements) { lt_caller_data *temp = LT_DLREALLOC (lt_caller_data, handle->caller_data, 2+ n_elements); if (!temp) { stale = 0; goto done; } handle->caller_data = temp; /* We only need this if we needed to allocate a new caller_data. */ handle->caller_data[i].key = key; handle->caller_data[1+ i].key = 0; } handle->caller_data[i].data = data; done: LT_DLMUTEX_UNLOCK (); return stale; } lt_ptr lt_dlcaller_get_data (key, handle) lt_dlcaller_id key; lt_dlhandle handle; { lt_ptr result = (lt_ptr) 0; /* This needs to be locked so that the caller data isn't updated by another thread part way through this function. */ LT_DLMUTEX_LOCK (); /* Locate the index of the element with a matching KEY. */ { int i; for (i = 0; handle->caller_data[i].key; ++i) { if (handle->caller_data[i].key == key) { result = handle->caller_data[i].data; break; } } } LT_DLMUTEX_UNLOCK (); return result; } /* --- USER MODULE LOADER API --- */ int lt_dlloader_add (place, dlloader, loader_name) lt_dlloader *place; const struct lt_user_dlloader *dlloader; const char *loader_name; { int errors = 0; lt_dlloader *node = 0, *ptr = 0; if ((dlloader == 0) /* diagnose null parameters */ || (dlloader->module_open == 0) || (dlloader->module_close == 0) || (dlloader->find_sym == 0)) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); return 1; } /* Create a new dlloader node with copies of the user callbacks. */ node = LT_EMALLOC (lt_dlloader, 1); if (!node) return 1; node->next = 0; node->loader_name = loader_name; node->sym_prefix = dlloader->sym_prefix; node->dlloader_exit = dlloader->dlloader_exit; node->module_open = dlloader->module_open; node->module_close = dlloader->module_close; node->find_sym = dlloader->find_sym; node->dlloader_data = dlloader->dlloader_data; LT_DLMUTEX_LOCK (); if (!loaders) { /* If there are no loaders, NODE becomes the list! */ loaders = node; } else if (!place) { /* If PLACE is not set, add NODE to the end of the LOADERS list. */ for (ptr = loaders; ptr->next; ptr = ptr->next) { /*NOWORK*/; } ptr->next = node; } else if (loaders == place) { /* If PLACE is the first loader, NODE goes first. */ node->next = place; loaders = node; } else { /* Find the node immediately preceding PLACE. */ for (ptr = loaders; ptr->next != place; ptr = ptr->next) { /*NOWORK*/; } if (ptr->next != place) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); ++errors; } else { /* Insert NODE between PTR and PLACE. */ node->next = place; ptr->next = node; } } LT_DLMUTEX_UNLOCK (); return errors; } int lt_dlloader_remove (loader_name) const char *loader_name; { lt_dlloader *place = lt_dlloader_find (loader_name); lt_dlhandle handle; int errors = 0; if (!place) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); return 1; } LT_DLMUTEX_LOCK (); /* Fail if there are any open modules which use this loader. */ for (handle = handles; handle; handle = handle->next) { if (handle->loader == place) { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (REMOVE_LOADER)); ++errors; goto done; } } if (place == loaders) { /* PLACE is the first loader in the list. */ loaders = loaders->next; } else { /* Find the loader before the one being removed. */ lt_dlloader *prev; for (prev = loaders; prev->next; prev = prev->next) { if (!strcmp (prev->next->loader_name, loader_name)) { break; } } place = prev->next; prev->next = prev->next->next; } if (place->dlloader_exit) { errors = place->dlloader_exit (place->dlloader_data); } LT_DLFREE (place); done: LT_DLMUTEX_UNLOCK (); return errors; } lt_dlloader * lt_dlloader_next (place) lt_dlloader *place; { lt_dlloader *next; LT_DLMUTEX_LOCK (); next = place ? place->next : loaders; LT_DLMUTEX_UNLOCK (); return next; } const char * lt_dlloader_name (place) lt_dlloader *place; { const char *name = 0; if (place) { LT_DLMUTEX_LOCK (); name = place ? place->loader_name : 0; LT_DLMUTEX_UNLOCK (); } else { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); } return name; } lt_user_data * lt_dlloader_data (place) lt_dlloader *place; { lt_user_data *data = 0; if (place) { LT_DLMUTEX_LOCK (); data = place ? &(place->dlloader_data) : 0; LT_DLMUTEX_UNLOCK (); } else { LT_DLMUTEX_SETERROR (LT_DLSTRERROR (INVALID_LOADER)); } return data; } lt_dlloader * lt_dlloader_find (loader_name) const char *loader_name; { lt_dlloader *place = 0; LT_DLMUTEX_LOCK (); for (place = loaders; place; place = place->next) { if (strcmp (place->loader_name, loader_name) == 0) { break; } } LT_DLMUTEX_UNLOCK (); return place; } bochs-2.6/configure.in0000644000175000017500000023432012020641507014647 0ustar guillemguillemdnl // Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) AC_INIT(bochs.h) AC_REVISION([[$Id: configure.in 11392 2012-09-02 11:11:00Z vruppert $]]) AC_CONFIG_HEADER(config.h) AC_CONFIG_HEADER(ltdlconf.h) dnl // Put Bochs version information right here so that it gets substituted dnl // into all the right places. VERSION="2.6" VER_STRING="2.6" dnl // WIN_VER_STRING format is "a, b, c, d" dnl // c should be > 90 for pre-release of next version otherwise patch level dnl // d should be 0 for release and 1 for svn version WIN_VER_STRING="2, 6, 0, 0" REL_STRING="Built from SVN snapshot on September 2nd, 2012" changequote(<<, >>) changequote([, ]) dnl Detect host and target AC_CANONICAL_HOST AC_CANONICAL_TARGET AC_MSG_CHECKING(if you are configuring for another platform) if test "$cross_compiling" = yes -o "$target_os" = "windows"; then AC_MSG_RESULT(yes) cross_configure=1 else AC_MSG_RESULT(no) cross_configure=0 fi # this case statement defines the compile flags which are needed to # compile bochs on a platform. Don't put things like optimization settings # into the configure.in file, since people will want to be able to change # those settings by defining CFLAGS and CXXFLAGS before running configure. NO_LT=0 MSVC_TARGET=0 need_dlcompat_for_plugins=0 case "$target" in *-pc-windows* | *-pc-winnt*) DEFAULT_GUI=win32 # default to win32 gui MSVC_TARGET=1 ;; *-pc-cygwin*) NO_LT=1 # do not use libtool at all on cygwin if test "$with_term" = yes; then # ncurses won't compile with -mno-cygwin or -DWIN32 # also, I can't get it to link without this -DBROKEN_LINKER=1 hack. # see /usr/include/curses.h for details. ADD_FLAGS="-DBROKEN_LINKER=1" fi ;; *-mingw32*) NO_LT=1 # do not use libtool at all on cygwin if test "$with_term" = yes; then # ncurses won't compile with -mno-cygwin or -DWIN32 # also, I can't get it to link without this -DBROKEN_LINKER=1 hack. # see /usr/include/curses.h for details. ADD_FLAGS="-DBROKEN_LINKER=1" else # default case ADD_FLAGS="-DWIN32" # required for mingw compile+win32 gui DEFAULT_GUI=win32 # default to win32 gui fi ;; *-macosx* | *-darwin*) ADD_FLAGS="-fpascal-strings -fno-common -Wno-four-char-constants -Wno-unknown-pragmas -Dmacintosh" # required for macosx compile DEFAULT_GUI=carbon # default to carbon need_dlcompat_for_plugins=1 ;; *-macos*) DEFAULT_GUI=macos # macos defaults to macos ;; *-amigaos* | *-morphos*) DEFAULT_GUI=amigaos # amigaos or morphos defaults to amigaos gui ;; *-solaris*) ADD_FLAGS="-D_XOPEN_SOURCE_EXTENDED=1 -D__EXTENSIONS__" # required for correct function prototypes LIBS="$LIBS -lsocket -lnsl" DEFAULT_GUI=x11 ;; *) DEFAULT_GUI=x11 ;; esac if test "${ADD_FLAGS:+set}" = set; then CFLAGS="$CFLAGS $ADD_FLAGS" CXXFLAGS="$CXXFLAGS $ADD_FLAGS" CPPFLAGS="$CPPFLAGS $ADD_FLAGS" fi AC_MSG_CHECKING(for standard CFLAGS on this platform) AC_MSG_RESULT($ADD_FLAGS) dnl // make sure X Windows is default if no other chosen if (test "$with_sdl" != yes) && \ (test "$with_svga" != yes) && \ (test "$with_x11" != yes) && \ (test "$with_win32" != yes) && \ (test "$with_nogui" != yes) && \ (test "$with_term" != yes) && \ (test "$with_rfb" != yes) && \ (test "$with_amigaos" != yes) && \ (test "$with_carbon" != yes) && \ (test "$with_wx" != yes) && \ (test "$with_macos" != yes); then # use DEFAULT_GUI. Set the appropriate variable. # DEFAULT_GUI must be set to one of the names above. Otherwise, no # valid $with_* variable will be set and who knows what will happen? eval "with_${DEFAULT_GUI}=yes" fi AC_PROG_CC AC_PROG_CXX AC_PROG_MAKE_SET if test "$MSVC_TARGET" != 1; then dnl------------ libtool configuration dnl Configure libtool, and default to shared libraries. Libtool will only be dnl used for compiling and linking plugins. AC_DISABLE_STATIC dnl Check for dlopen support AC_LIBTOOL_DLOPEN dnl Configure libtool AC_PROG_LIBTOOL dnl Configure the ltdl library. This must go after AC_PROG_LIBTOOL or dnl else it disables shared libraries somehow. AC_LIB_LTDL fi AC_PATH_PROG(PKGCONFIG, pkg-config, not_found) if test "$PKGCONFIG" = not_found; then AC_PATH_XTRA fi AC_C_BIGENDIAN AC_C_INLINE AC_CHECK_SIZEOF(unsigned char) AC_CHECK_SIZEOF(unsigned short) AC_CHECK_SIZEOF(unsigned int) AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned long long) AC_CHECK_SIZEOF(int *) AC_CHECK_FUNCS(getenv, AC_DEFINE(BX_HAVE_GETENV)) AC_CHECK_FUNCS(setenv, AC_DEFINE(BX_HAVE_SETENV)) AC_CHECK_FUNCS(snprintf, AC_DEFINE(BX_HAVE_SNPRINTF)) AC_CHECK_FUNCS(vsnprintf, AC_DEFINE(BX_HAVE_VSNPRINTF)) if test "$MSVC_TARGET" != 1; then AC_CHECK_FUNCS(select, AC_DEFINE(BX_HAVE_SELECT)) AC_CHECK_TYPE(socklen_t, AC_DEFINE(BX_HAVE_SOCKLEN_T), , [#include #include ]) AC_CHECK_FUNCS(strtoull, AC_DEFINE(BX_HAVE_STRTOULL)) AC_CHECK_FUNCS(strtouq, AC_DEFINE(BX_HAVE_STRTOUQ)) AC_CHECK_FUNCS(strdup, AC_DEFINE(BX_HAVE_STRDUP)) AC_CHECK_FUNCS(strrev, AC_DEFINE(BX_HAVE_STRREV)) AC_CHECK_FUNCS(stricmp, AC_DEFINE(BX_HAVE_STRICMP)) AC_CHECK_FUNCS(strcasecmp, AC_DEFINE(BX_HAVE_STRCASECMP)) AC_CHECK_FUNCS(mkstemp, AC_DEFINE(BX_HAVE_MKSTEMP)) AC_CHECK_HEADER(sys/mman.h, AC_DEFINE(BX_HAVE_SYS_MMAN_H)) AC_CHECK_FUNCS(gettimeofday, AC_DEFINE(BX_HAVE_GETTIMEOFDAY)) AC_CHECK_FUNCS(usleep, AC_DEFINE(BX_HAVE_USLEEP)) AC_MSG_CHECKING(for __builtin_bswap32) AC_TRY_LINK([],[ __builtin_bswap32(0x12345678); ],[ AC_DEFINE(BX_HAVE___BUILTIN_BSWAP32, 1, [Define to 1 if you have the '__builtin_bswap32' function.]) AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) ]) AC_MSG_CHECKING(for __builtin_bswap64) AC_TRY_LINK([],[ __builtin_bswap64(0x12345678); ],[ AC_DEFINE(BX_HAVE___BUILTIN_BSWAP64, 1, [Define to 1 if you have the '__builtin_bswap64' function.]) AC_MSG_RESULT(yes) ],[ AC_MSG_RESULT(no) ]) AC_CHECK_FUNCS(tmpfile64, AC_DEFINE(BX_HAVE_TMPFILE64)) AC_CHECK_FUNCS(fseek64, AC_DEFINE(BX_HAVE_FSEEK64)) AC_CHECK_FUNCS(fseeko64, AC_DEFINE(BX_HAVE_FSEEKO64)) else AC_DEFINE(BX_HAVE_SELECT, 1) AC_DEFINE(BX_HAVE_SOCKLEN_T, 0) AC_DEFINE(BX_HAVE_STRTOULL, 1) AC_DEFINE(BX_HAVE_STRTOUQ, 0) AC_DEFINE(BX_HAVE_STRDUP, 1) AC_DEFINE(BX_HAVE_STRREV, 1) AC_DEFINE(BX_HAVE_STRICMP, 1) AC_DEFINE(BX_HAVE_STRCASECMP, 0) AC_DEFINE(BX_HAVE_MKSTEMP, 0) AC_DEFINE(BX_HAVE_SYS_MMAN_H, 0) AC_DEFINE(BX_HAVE_GETTIMEOFDAY, 0) AC_DEFINE(BX_HAVE_USLEEP, 0) AC_DEFINE(BX_HAVE___BUILTIN_BSWAP32, 0) AC_DEFINE(BX_HAVE___BUILTIN_BSWAP64, 0) AC_DEFINE(BX_HAVE_TMPFILE64, 0) AC_DEFINE(BX_HAVE_FSEEK64, 0) AC_DEFINE(BX_HAVE_FSEEKO64, 0) fi AC_CHECK_FUNCS(sleep, AC_DEFINE(BX_HAVE_SLEEP)) AC_CHECK_FUNCS(nanosleep, AC_DEFINE(BX_HAVE_NANOSLEEP)) AC_CHECK_FUNCS(abort, AC_DEFINE(BX_HAVE_ABORT)) AC_CHECK_MEMBER(struct sockaddr_in.sin_len, AC_DEFINE(BX_HAVE_SOCKADDR_IN_SIN_LEN), , [#include #include ]) AC_CHECK_FUNCS(timelocal, AC_DEFINE(BX_HAVE_TIMELOCAL)) AC_CHECK_FUNCS(gmtime, AC_DEFINE(BX_HAVE_GMTIME)) AC_CHECK_FUNCS(mktime, AC_DEFINE(BX_HAVE_MKTIME)) dnl As of autoconf 2.53, the standard largefile test fails for Linux/gcc. dnl It does not put the largefiles arguments into CFLAGS, even though Linux/gcc dnl does need them. So we do it ourselves. AC_SYS_LARGEFILE dnl we need to define _FILE_OFFSET_BITS or _LARGE_FILES on the compiler command dnl line because otherwise the system headers risk being included before dnl config.h which defines these constants leading to inconsistent dnl sizeof(off_t) in different source files of the same program and linking dnl problems case "x$ac_cv_sys_file_offset_bits" in #( xno | xunknown) ;; *) if test "x$ac_cv_sys_file_offset_bits" = "x64"; then BX_LARGEFILE_FLAGS="-D_FILE_OFFSET_BITS=64 -D_LARGE_FILES" else BX_LARGEFILE_FLAGS="-D_LARGE_FILES" fi CPPFLAGS="$CPPFLAGS $BX_LARGEFILE_FLAGS" CFLAGS="$CFLAGS $BX_LARGEFILE_FLAGS" CXXFLAGS="$CXXFLAGS $BX_LARGEFILE_FLAGS" ;; esac dnl ---end of largefile tests dnl Add the -lm library if math functions cannot be used without it. dnl This check is important on cygwin because of the bizarre way that they dnl have organized functions into libraries. On cygwin, both libc.a and dnl libm.a are symbolic links to a single lib libcygwin.a. This means that dnl 1) linking with -lm is not necessary, and dnl 2) linking with -lm is dangerous if the order of libraries is wrong dnl In particular, if you compile any program with -mno-cygwin and link with dnl -lm, it will crash instantly when it is run. This happens because the dnl linker incorrectly links the Cygwin libm.a (==libcygwin.a), which replaces dnl the ___main function instead of allowing it to be defined by dnl /usr/lib/mingw/libmingw32.a as it should be. dnl dnl On MacOS X, this test will find that -lm is unnecessary and leave it out. dnl dnl Just check a few math functions. If they are all found without dnl -lm, then we must not need -lm. have_cos=0 have_floor=0 AC_CHECK_FUNCS(cos, have_cos=1) AC_CHECK_FUNCS(floor, have_floor=1) AC_MSG_CHECKING(if math functions link without -lm) if test "$have_cos" = 1 -a "$have_floor" = 1; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) LIBS="$LIBS -lm" # use different functions to bypass configure caching have_sin=0 have_ceil=0 AC_CHECK_FUNCS(sin, have_sin=1) AC_CHECK_FUNCS(ceil, have_ceil=1) AC_MSG_CHECKING(if math functions link with -lm) if test "$have_sin" = 1 -a "$have_ceil" = 1; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) # not sure we should warn the user, crash, etc. # expect link failure fi fi AC_MSG_CHECKING(if compiler allows __attribute__) AC_TRY_COMPILE([], [typedef struct { } __attribute__ ((packed)) junk;], AC_MSG_RESULT(yes), [ AC_MSG_RESULT(no) AC_DEFINE(BX_NO_ATTRIBUTES) ]) AC_LANG_SAVE AC_LANG_CPLUSPLUS AC_MSG_CHECKING(for set) AC_TRY_COMPILE([#include ], [], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_HAVE_SET) ], AC_MSG_RESULT(no)) AC_MSG_CHECKING(for set.h) AC_TRY_COMPILE([#include ], [], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_HAVE_SET_H) ], AC_MSG_RESULT(no)) AC_MSG_CHECKING(for map) AC_TRY_COMPILE([#include ], [], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_HAVE_MAP) ], AC_MSG_RESULT(no)) AC_MSG_CHECKING(for map.h) AC_TRY_COMPILE([#include ], [], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_HAVE_MAP_H) ], AC_MSG_RESULT(no)) AC_LANG_RESTORE dnl Implement a check for each gui library to see if has a chance of compiling. if test "$with_all_libs" = yes; then if test "$cross_configure" = 1; then AC_MSG_WARN([[Using --with-all-libs while cross configuring is very unlikely to be what you want. You should specify the --with-* args yourself.]]) fi if test "$with_amigaos" != yes; then can_compile_amigaos=1 AC_CHECK_HEADER([proto/intuition.h], [], [ can_compile_amigaos=0 ]) AC_CHECK_HEADER([intuition/intuitionbase.h], [], [ can_compile_amigaos=0 ]) AC_CHECK_HEADER([cybergraphx/cybergraphics.h], [], [ can_compile_amigaos=0 ]) AC_CHECK_HEADER([devices/trackdisk.h], [], [ can_compile_amigaos=0 ]) if test $can_compile_amigaos = 1; then with_amigaos=yes fi fi if test "$with_macos" != yes; then can_compile_macos=1 AC_CHECK_HEADER([Quickdraw.h], [], [ can_compile_macos=0 ]) AC_CHECK_HEADER([Dialogs.h], [], [ can_compile_macos=0 ]) if test $can_compile_macos = 1; then with_macos=yes fi fi if test "$with_carbon" != yes; then can_compile_carbon=1 AC_CHECK_HEADER([Carbon.h], [], [ can_compile_carbon=0 ]) AC_CHECK_HEADER([ApplicationServices/ApplicationServices.h], [], [ can_compile_carbon=0 ]) if test $can_compile_carbon = 1; then with_carbon=yes fi fi if test "$with_win32" != yes; then can_compile_win32=1 AC_CHECK_HEADER([windows.h], [], [ can_compile_win32=0 ]) AC_CHECK_HEADER([commctrl.h], [], [ can_compile_win32=0 ]) if test $can_compile_win32 = 1; then with_win32=yes fi fi if test "$with_sdl" != yes; then can_compile_sdl=1 AC_CHECK_HEADER([SDL/SDL.h], [], [ can_compile_sdl=0 ]) AC_CHECK_HEADER([SDL/SDL_main.h], [], [ can_compile_sdl=0 ]) if test $can_compile_sdl = 1; then with_sdl=yes fi fi if test "$with_svga" != yes; then can_compile_svga=1 AC_CHECK_HEADER([vga.h], [], [ can_compile_svga=0 ]) AC_CHECK_HEADER([vgagl.h], [], [ can_compile_svga=0 ]) if test $can_compile_svga = 1; then with_svga=yes fi fi if test "$with_x11" != yes; then can_compile_x11=1 AC_CHECK_HEADER([X11/Xlib.h], [], [ can_compile_x11=0 ]) AC_CHECK_HEADER([X11/Xutil.h], [], [ can_compile_x11=0 ]) if test $can_compile_x11 = 1; then with_x11=yes fi fi if test "$with_rfb" != yes; then can_compile_rfb=1 case $target in *-pc-windows* | *-pc-winnt* | *-pc-cygwin* | *-mingw32*) AC_CHECK_HEADER([winsock.h], [], [ can_compile_rfb=0 ]) AC_CHECK_HEADER([process.h], [], [ can_compile_rfb=0 ]) ;; *) AC_CHECK_HEADER([sys/socket.h], [], [ can_compile_rfb=0 ]) AC_CHECK_HEADER([netinet/tcp.h], [], [ can_compile_rfb=0 ]) AC_CHECK_HEADER([pthread.h], [], [ can_compile_rfb=0 ]) ;; esac if test $can_compile_rfb = 1; then with_rfb=yes fi fi if test "$with_term" != yes; then can_compile_term=1 AC_CHECK_HEADER([curses.h], [], [ can_compile_term=0 ]) AC_CHECK_HEADER([signal.h], [], [ can_compile_term=0 ]) if test $can_compile_term = 1; then with_term=yes fi fi if test "$with_nogui" != yes; then with_nogui=yes fi fi # end of if $with_all_libs = yes AC_MSG_CHECKING(for idle hack) AC_ARG_ENABLE(idle-hack, [ --enable-idle-hack use Roland Mainz's idle hack], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_USE_IDLE_HACK, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_USE_IDLE_HACK, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_USE_IDLE_HACK, 0) ] ) AC_SUBST(BX_USE_IDLE_HACK) AC_CHECK_HEADER(dlfcn.h, AC_DEFINE(BX_HAVE_DLFCN_H, 1)) AC_CHECK_HEADER(assert.h, AC_DEFINE(HAVE_ASSERT_H, 1)) AC_MSG_CHECKING(for plugins support) AC_ARG_ENABLE(plugins, [ --enable-plugins enable plugins], [if test "$enableval" = yes; then bx_plugins=1 else bx_plugins=0 fi], [ bx_plugins=0 ] ) if test "$bx_plugins" = 1; then AC_MSG_RESULT(yes) AC_DEFINE(BX_PLUGINS, 1) GUI_NON_PLUGIN_OBJS='$(OBJS_THAT_CANNOT_BE_PLUGINS)' GUI_PLUGIN_OBJS='$(OBJS_THAT_CAN_BE_PLUGINS)' DEFINE_PLUGIN_PATH='-DBX_PLUGIN_PATH="\"${plugdir}\""' # and the $(OBJS_THAT_SUPPORT_OTHER_PLUGINS) will be built and linked # by special link rules for the plugins that they support. LIBS="$LIBS $LIBADD_DL" have_ltdl=0 AC_CHECK_HEADER(ltdl.h, [AC_CHECK_LIB(ltdl, lt_dlinit, [have_ltdl=1]])) if test "$have_ltdl" = 1; then PLUGIN_VAR="-lltdl" AC_DEFINE(BX_HAVE_LTDL,1) else PLUGIN_VAR="ltdl.o" fi PLUGIN_TARGET=bochs_plugins INSTALL_PLUGINS_VAR=install_libtool_plugins NONPLUGIN_GUI_LINK_OPTS='' else AC_MSG_RESULT(no) bx_plugins=0 AC_DEFINE(BX_PLUGINS, 0) GUI_NON_PLUGIN_OBJS='$(OBJS_THAT_CANNOT_BE_PLUGINS) $(OBJS_THAT_CAN_BE_PLUGINS) $(OBJS_THAT_SUPPORT_OTHER_PLUGINS)' GUI_PLUGIN_OBJS='' NONPLUGIN_GUI_LINK_OPTS='$(GUI_LINK_OPTS)' fi AC_SUBST(DEFINE_PLUGIN_PATH) AC_SUBST(NONPLUGIN_GUI_LINK_OPTS) # copy gui variables into iodev variables. Later, we will add to the gui # objs list, according to which display libraries are enabled. IODEV_NON_PLUGIN_OBJS=$GUI_NON_PLUGIN_OBJS IODEV_PLUGIN_OBJS=$GUI_PLUGIN_OBJS IODEV_EXT_NON_PLUGIN_OBJS=$GUI_NON_PLUGIN_OBJS IODEV_EXT_PLUGIN_OBJS=$GUI_PLUGIN_OBJS # on MacOSX if they enabled plugins, make sure that dlopen() was found. # It is provided by a library called dlcompat. if test "$bx_plugins" = 1 -a "$need_dlcompat_for_plugins" = 1; then have_dlopen=0 AC_CHECK_LIB(dl, dlopen, [have_dlopen=1]) AC_MSG_CHECKING(if you have dlcompat, required for MacOSX plugins) if test "$have_dlopen" = 0; then AC_MSG_RESULT(no) AC_MSG_ERROR([To use plugins on MacOSX you must use a library called dlcompat. The configure script was not able to find dlcompat. If it is already installed then you must set up your environment variables to point to it, as is done in .conf.macosx. If you cannot resolve this, you should turn off plugins.]) else AC_MSG_RESULT(yes) fi fi AC_MSG_CHECKING(if compiler allows LL for 64-bit constants) AC_TRY_COMPILE([], [ { 42LL; } ], AC_MSG_RESULT(yes), [ AC_MSG_RESULT(no) AC_DEFINE(BX_64BIT_CONSTANTS_USE_LL, 0) ]) AC_MSG_CHECKING(for A20 support) AC_ARG_ENABLE(a20-pin, [ --enable-a20-pin compile in support for A20 pin], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_A20, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_A20, 0) fi ], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_A20, 1) ] ) use_x86_64=0 AC_MSG_CHECKING(for x86-64 support) AC_ARG_ENABLE(x86-64, [ --enable-x86-64 compile in support for x86-64 instructions], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) OBJS64='$(OBJS64)' AC_DEFINE(BX_SUPPORT_X86_64, 1) use_x86_64=1 else AC_MSG_RESULT(no) OBJS64='' AC_DEFINE(BX_SUPPORT_X86_64, 0) fi ], [ AC_MSG_RESULT(no) OBJS64='' AC_DEFINE(BX_SUPPORT_X86_64, 0) ] ) AC_SUBST(OBJS64) use_smp=0 AC_MSG_CHECKING(for SMP support) AC_ARG_ENABLE(smp, [ --enable-smp compile in support for SMP configurations], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_SMP, 1) AC_DEFINE(BX_USE_CPU_SMF, 0) use_smp=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_SMP, 0) fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_SMP, 0) ] ) AC_MSG_CHECKING(for cpu level) AC_ARG_ENABLE(cpu-level, [ --enable-cpu-level select cpu level (3,4,5,6)], [case "$enableval" in 3) AC_MSG_RESULT(3) AC_DEFINE(BX_CPU_LEVEL, 3) ;; 4) AC_MSG_RESULT(4) AC_DEFINE(BX_CPU_LEVEL, 4) ;; 5) AC_MSG_RESULT(5) AC_DEFINE(BX_CPU_LEVEL, 5) ;; 6) AC_MSG_RESULT(6) AC_DEFINE(BX_CPU_LEVEL, 6) ;; *) echo " " echo "ERROR: you must supply a valid CPU level to --enable-cpu-level" exit 1 ;; esac bx_cpu_level=$enableval if test "$use_smp" = 1 -a "$enableval" -lt 5; then echo "ERROR: with >1 processor, use --enable-cpu-level=5 or more" exit 1 fi if test "$use_x86_64" = 1 -a "$enableval" -lt 6; then echo "ERROR: --enable-cpu-level=6 required for x86-64 emulation" exit 1 fi ], [ AC_MSG_RESULT(6) AC_DEFINE(BX_CPU_LEVEL, 6) bx_cpu_level=6 ] ) AC_MSG_CHECKING(for larger than 32 bit physical address emulation) AC_ARG_ENABLE(long-phy-address, [ --enable-long-phy-address compile in support for physical address larger than 32 bit], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_PHY_ADDRESS_LONG, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_PHY_ADDRESS_LONG, 0) fi ], [ if test "$bx_cpu_level" -ge 5; then AC_MSG_RESULT(yes) AC_DEFINE(BX_PHY_ADDRESS_LONG, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_PHY_ADDRESS_LONG, 0) fi ] ) AC_MSG_CHECKING(for large ramfile support) AC_ARG_ENABLE(large-ramfile, [ --enable-large-ramfile enable large ramfile support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_LARGE_RAMFILE, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_LARGE_RAMFILE, 0) fi], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_LARGE_RAMFILE, 1) ] ) AC_SUBST(BX_LARGE_RAMFILE) networking=no NETDEV_OBJS='' AC_MSG_CHECKING(for NE2000 support) AC_ARG_ENABLE(ne2000, [ --enable-ne2000 enable NE2000 support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_NE2K, 1) NETDEV_OBJS='ne2k.o' networking=yes else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_NE2K, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_NE2K, 0) ] ) AC_MSG_CHECKING(for i440FX PCI support) AC_ARG_ENABLE(pci, [ --enable-pci enable i440FX PCI support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_PCI, 1) pci=1 PCI_OBJ='pci.o pci2isa.o pci_ide.o acpi.o' else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_PCI, 0) pci=0 PCI_OBJ='' fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_PCI, 0) pci=0 PCI_OBJ='' ] ) AC_SUBST(PCI_OBJ) # # PCI host device support # AC_MSG_CHECKING(for PCI host device mapping support) AC_ARG_ENABLE(pcidev, [ --enable-pcidev enable PCI host device mapping support (linux host only)], [ if test "$enableval" = "yes"; then AC_MSG_RESULT(yes) if test "$pci" != "1"; then AC_MSG_ERROR([PCI host device mapping requires PCI support]) fi case "$target" in *-linux*) AC_MSG_NOTICE([Linux detected as host for PCI host device mapping]) linux_version=`uname -r` case "$linux_version" in 2.4*) PCIDEV_MODULE_MAKE_ALL="all-kernel24" KERNEL_MODULE_SUFFIX="o" ;; 2.6*|3.*) PCIDEV_MODULE_MAKE_ALL="all-kernel26" KERNEL_MODULE_SUFFIX="ko" ;; *) AC_MSG_ERROR([Linux kernel 2.4, 2.6 or 3.x is required for PCI host device mapping]) ;; esac KERNELDIR="/lib/modules/$linux_version/build" LSMOD="lsmod" INSMOD="insmod" RMMOD="rmmod" DEPMOD="depmod" CLEAN_PCIDEV_VAR=clean_pcidev AC_SUBST(KERNELDIR) AC_SUBST(LSMOD) AC_SUBST(INSMOD) AC_SUBST(RMMOD) AC_SUBST(DEPMOD) AC_SUBST(PCIDEV_MODULE_MAKE_ALL) AC_SUBST(KERNEL_MODULE_SUFFIX) AC_SUBST(CLEAN_PCIDEV_VAR) ;; *) AC_MSG_ERROR([PCI host device mapping requires Linux as host]) ;; esac AC_DEFINE(BX_SUPPORT_PCIDEV, 1) PCI_OBJ="$PCI_OBJ pcidev.o" else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_PCIDEV, 0) fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_PCIDEV, 0) ] ) use_usb=0 USBHC_OBJS='' AC_MSG_CHECKING(for USB UHCI support) AC_ARG_ENABLE(usb, [ --enable-usb enable USB UHCI support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_USB_UHCI, 1) USBHC_OBJS="usb_uhci.o" use_usb=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_UHCI, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_UHCI, 0) ] ) AC_MSG_CHECKING(for USB OHCI support) AC_ARG_ENABLE(usb-ohci, [ --enable-usb-ohci enable USB OHCI support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_USB_OHCI, 1) USBHC_OBJS="$USBHC_OBJS usb_ohci.o" use_usb=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_OHCI, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_OHCI, 0) ] ) AC_MSG_CHECKING(for experimental USB xHCI support) AC_ARG_ENABLE(usb-xhci, [ --enable-usb-xhci enable experimental USB xHCI support (incomplete)], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_USB_XHCI, 1) USBHC_OBJS="$USBHC_OBJS usb_xhci.o" use_usb=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_XHCI, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_USB_XHCI, 0) ] ) if test "$use_usb" = 1; then USBCORE_OBJ="usb_common.o" USBDEV_OBJS="usb_hid.o usb_hub.o usb_msd.o usb_printer.o" SCSI_OBJS="scsi_device.o" AC_SUBST(USBHC_OBJS) AC_SUBST(USBCORE_OBJ) AC_SUBST(USBDEV_OBJS) AC_SUBST(SCSI_OBJS) if test "$bx_plugins" = 0; then USB_LIB_VAR='iodev/usb/libusb.a' AC_SUBST(USB_LIB_VAR) fi fi AC_MSG_CHECKING(for PCI pseudo NIC support) AC_ARG_ENABLE(pnic, [ --enable-pnic enable PCI pseudo NIC support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_PCIPNIC, 1) NETDEV_OBJS="$NETDEV_OBJS pcipnic.o" networking=yes else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_PCIPNIC, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_PCIPNIC, 0) ] ) AC_MSG_CHECKING(for Intel(R) Gigabit Ethernet support) AC_ARG_ENABLE(e1000, [ --enable-e1000 enable Intel(R) Gigabit Ethernet support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_E1000, 1) NETDEV_OBJS="$NETDEV_OBJS e1000.o" networking=yes else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_E1000, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_E1000, 0) ] ) NETLOW_OBJS='' if test "$networking" = yes; then NETLOW_OBJS='eth_null.o eth_vnet.o' if test "$MSVC_TARGET" != 1; then AC_CHECK_HEADER(net/bpf.h, [ NETLOW_OBJS="$NETLOW_OBJS eth_fbsd.o" AC_DEFINE(BX_NETMOD_FBSD, 1) ]) AC_CHECK_HEADER(netpacket/packet.h, [ NETLOW_OBJS="$NETLOW_OBJS eth_linux.o" AC_DEFINE(BX_NETMOD_LINUX, 1) ]) AC_CHECK_FUNCS(fork, have_fork=1) AC_CHECK_FUNCS(execlp, have_execlp=1) AC_CHECK_FUNCS(socketpair, have_socketpair=1) if test x"$have_fork" = x1 -a x"$have_execlp" = x1 -a x"$have_socketpair" = x1; then NETLOW_OBJS="$NETLOW_OBJS eth_slirp.o" AC_DEFINE(BX_NETMOD_SLIRP, 1) fi fi case "$target" in *-pc-windows* | *-pc-winnt* | *-pc-cygwin* | *-mingw32*) NETLOW_OBJS="$NETLOW_OBJS eth_win32.o" AC_DEFINE(BX_NETMOD_WIN32, 1) ;; *-macosx* | *-darwin*) NETLOW_OBJS="$NETLOW_OBJS eth_tuntap.o" AC_DEFINE(BX_NETMOD_TUNTAP, 1) ;; *) AC_CHECK_HEADER(net/if.h, [ use_ethertap=yes AC_DEFINE(BX_HAVE_NET_IF_H, 1) ], [], [ #include #include ]) AC_CHECK_HEADER(linux/netlink.h, [ use_ethertap=yes ], [], [ #include #include ]) if test "$use_ethertap" = yes; then NETLOW_OBJS="$NETLOW_OBJS eth_tap.o eth_vde.o" AC_DEFINE(BX_NETMOD_TAP, 1) AC_DEFINE(BX_NETMOD_VDE, 1) fi AC_CHECK_HEADER(net/if_tun.h, [ use_tuntap=yes ], [], [ #include #include #include ]) AC_CHECK_HEADER(linux/if_tun.h, [ use_tuntap=yes ], [], [ #include #include ]) if test "$use_tuntap" = yes; then NETLOW_OBJS="$NETLOW_OBJS eth_tuntap.o" AC_DEFINE(BX_NETMOD_TUNTAP, 1) fi ;; esac if test "$bx_plugins" = 0; then NETWORK_LIB_VAR='iodev/network/libnetwork.a' AC_SUBST(NETWORK_LIB_VAR) fi AC_DEFINE(BX_NETWORKING, 1) else AC_DEFINE(BX_NETWORKING, 0) fi AC_SUBST(NETDEV_OBJS) AC_SUBST(NETLOW_OBJS) AC_MSG_CHECKING(for repeated IO and mem copy speedups) AC_ARG_ENABLE(repeat-speedups, [ --enable-repeat-speedups support repeated IO and mem copy speedups], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) speedup_repeat=1 else AC_MSG_RESULT(no) speedup_repeat=0 fi], [ AC_MSG_RESULT(no) speedup_repeat=0 ] ) AC_MSG_CHECKING(for gcc fast function calls optimization) AC_ARG_ENABLE(fast-function-calls, [ --enable-fast-function-calls support for fast function calls (gcc on x86 only)], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) speedup_fastcall=1 else AC_MSG_RESULT(no) speedup_fastcall=0 fi], [ AC_MSG_RESULT(no) speedup_fastcall=0 ] ) AC_MSG_CHECKING(for handlers chaining speedups) AC_ARG_ENABLE(handlers-chaining, [ --enable-handlers-chaining support handlers-chaining emulation speedups], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) speedup_handlers_chaining=1 else AC_MSG_RESULT(no) speedup_handlers_chaining=0 fi], [ AC_MSG_RESULT(no) speedup_handlers_chaining=0 ] ) AC_MSG_CHECKING(support for configurable MSR registers) AC_ARG_ENABLE(configurable-msrs, [ --enable-configurable-msrs support for configurable MSR registers], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_CONFIGURE_MSRS, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_CONFIGURE_MSRS, 0) fi], [ if test "$bx_cpu_level" -ge 5; then AC_MSG_RESULT(yes) AC_DEFINE(BX_CONFIGURE_MSRS, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_CONFIGURE_MSRS, 0) fi ] ) AC_MSG_CHECKING(show IPS) AC_ARG_ENABLE(show-ips, [ --enable-show-ips show IPS in Bochs log file], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SHOW_IPS, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_SHOW_IPS, 0) fi], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_SHOW_IPS, 1) ] ) AC_MSG_CHECKING(for use of .cpp as suffix) AC_ARG_ENABLE(cpp, [ --enable-cpp use .cpp as C++ suffix], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) SUFFIX_LINE='.SUFFIXES: .cpp' CPP_SUFFIX='cpp' else AC_MSG_RESULT(no) SUFFIX_LINE='.SUFFIXES: .cc' CPP_SUFFIX='cc' fi], [ AC_MSG_RESULT(no) SUFFIX_LINE='.SUFFIXES: .cc' CPP_SUFFIX='cc' ] ) AC_SUBST(SUFFIX_LINE) AC_SUBST(CPP_SUFFIX) if test "$enable_cpp" = yes; then echo "moving .cc source files to .cpp" sourcefiles=`find . -name "*.cc" -print` if test "$sourcefiles" != ""; then for ccname in $sourcefiles do cppname=`echo $ccname | sed -e "s/\.cc$/.cpp/"` echo "mv $ccname $cppname" mv $ccname $cppname done else echo "no more .cc source files to rename" fi fi AC_MSG_CHECKING(for Bochs internal debugger support) AC_ARG_ENABLE(debugger, [ --enable-debugger compile in support for Bochs internal debugger], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_DEBUGGER, 1) DEBUGGER_VAR='$(DEBUGGER_LIB)' NO_FLEX_YACC='' AC_PATH_PROG(FLEX, flex, not_found) AC_PATH_PROG(YACC, yacc, not_found) AC_MSG_CHECKING(whether to generate parser / lexer files) if test "$FLEX" = not_found -o "$YACC" = not_found -o "$MSVC_TARGET" = 1; then NO_FLEX_YACC='#' AC_MSG_RESULT(no) else AC_MSG_RESULT(yes) fi AC_SUBST(NO_FLEX_YACC) bx_debugger=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_DEBUGGER, 0) DEBUGGER_VAR='' bx_debugger=0 fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_DEBUGGER, 0) DEBUGGER_VAR='' bx_debugger=0 ] ) AC_SUBST(DEBUGGER_VAR) AC_MSG_CHECKING(for disassembler support) AC_ARG_ENABLE(disasm, [ --enable-disasm compile in support for disassembler], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_DISASM, 1) DISASM_VAR='$(DISASM_LIB)' else AC_MSG_RESULT(no) if test "$bx_debugger" = 1; then echo "ERROR: debugger is enabled, so --enable-disasm is required" exit 1 fi AC_DEFINE(BX_DISASM, 0) DISASM_VAR='' fi], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_DISASM, 1) DISASM_VAR='$(DISASM_LIB)' ]) AC_SUBST(DISASM_VAR) AC_MSG_CHECKING(enable Bochs internal debugger GUI) AC_ARG_ENABLE(debugger-gui, [ --enable-debugger-gui compile in support for Bochs internal debugger GUI], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_DEBUGGER_GUI, 1) gui_debugger=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_DEBUGGER_GUI, 0) gui_debugger=0 fi], [ if test "$bx_debugger" = 1; then AC_MSG_RESULT(yes) AC_DEFINE(BX_DEBUGGER_GUI, 1) gui_debugger=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_DEBUGGER_GUI, 0) gui_debugger=0 fi ] ) bx_gdb_stub=0 AC_MSG_CHECKING(for gdb stub enable) AC_ARG_ENABLE(gdb-stub, [ --enable-gdb-stub enable gdb stub support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_GDBSTUB, 1) GDBSTUB_VAR='$(GDBSTUB_OBJS)' bx_gdb_stub=1 if test "$bx_debugger" = 1; then AC_MSG_ERROR([[--enable-debugger and --enable-gdb-stub are mutually exclusive]]) fi else AC_MSG_RESULT(no) AC_DEFINE(BX_GDBSTUB, 0) GDBSTUB_VAR='' fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_GDBSTUB, 0) GDBSTUB_VAR='' ] ) AC_SUBST(GDBSTUB_VAR) AC_MSG_CHECKING(for I/O Interface to the debugger) IODEBUG_OBJS='' AC_ARG_ENABLE(iodebug, [ --enable-iodebug enable I/O interface to debugger], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_IODEBUG, 1) IODEBUG_OBJS='iodebug.o' else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_IODEBUG, 0) fi ], [ if test "$bx_debugger" = 1; then # enable by default if debugger is on AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_IODEBUG, 1) IODEBUG_OBJS='iodebug.o' else AC_MSG_RESULT(no) fi ] ) AC_SUBST(IODEBUG_OBJS) AC_MSG_CHECKING(for ALL optimizations enabled) AC_ARG_ENABLE(all-optimizations, [ --enable-all-optimizations compile in all possible optimizations], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) speedups_all=1 else AC_MSG_RESULT(no) speedups_all=0 fi ], [ AC_MSG_RESULT(no) speedups_all=0 ] ) # # Optimizations section. Decide what the status of various optimizations # should be based on configure choices and other factors. # if test "$speedups_all" = 1; then # Configure requested to force all options enabled. speedup_repeat=1 speedup_fastcall=1 speedup_handlers_chaining=1 fi if test "$speedup_repeat" = 1; then AC_DEFINE(BX_SUPPORT_REPEAT_SPEEDUPS, 1) else AC_DEFINE(BX_SUPPORT_REPEAT_SPEEDUPS, 0) fi if test "$speedup_fastcall" = 1; then AC_DEFINE(BX_FAST_FUNC_CALL, 1) else AC_DEFINE(BX_FAST_FUNC_CALL, 0) fi if test "$bx_debugger" = 1 -a "$speedup_handlers_chaining" = 1; then speedup_handlers_chaining=0 echo "ERROR: handlers-chaining speedups are not supported with internal debugger or gdbstub yet" fi if test "$bx_gdb_stub" = 1 -a "$speedup_handlers_chaining" = 1; then speedup_handlers_chaining=0 echo "ERROR: handlers-chaining speedups are not supported with internal debugger or gdbstub yet" fi if test "$speedup_handlers_chaining" = 1; then AC_DEFINE(BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS, 1) else AC_DEFINE(BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS, 0) fi READLINE_LIB="" rl_without_curses_ok=no rl_with_curses_ok=no AC_MSG_CHECKING(whether user wants readline) AC_ARG_ENABLE(readline, [ --enable-readline use readline library, if available], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) want_readline=yes else AC_MSG_RESULT(no) want_readline=no fi], [ AC_MSG_RESULT(yes) want_readline=yes ] ) use_readline=0 AC_MSG_CHECKING(whether to use readline) if test "$want_readline" = yes; then if test "$bx_debugger" = 1; then AC_MSG_CHECKING(if readline works without -lcurses) OLD_LIBS=$LIBS LIBS="$LIBS -lreadline" AC_TRY_RUN([ #include #include int main() { rl_initialize(); exit(0); } ], [ AC_MSG_RESULT(yes) rl_without_curses_ok=yes ], [ AC_MSG_RESULT(no) ] ) AC_MSG_CHECKING(if readline works with -lcurses) LIBS="$LIBS -lcurses" AC_TRY_RUN([ #include #include int main() { rl_initialize(); exit(0); } ], [AC_MSG_RESULT(yes) rl_with_curses_ok=yes ], [ AC_MSG_RESULT(no) ] ) LIBS=$OLD_LIBS if test "$rl_without_curses_ok" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_LIBREADLINE, 1) READLINE_LIB="-lreadline" use_readline=1 elif test "$rl_with_curses_ok" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(HAVE_LIBREADLINE, 1) READLINE_LIB="-lreadline -lcurses" use_readline=1 else AC_MSG_RESULT(no) echo WARNING: The readline library was disabled because it was not found. fi else AC_MSG_RESULT(no) fi else AC_MSG_RESULT(no) fi AC_SUBST(READLINE_LIB) AC_CHECK_HEADER(readline/history.h, AC_DEFINE(HAVE_READLINE_HISTORY_H) ) INSTRUMENT_DIR='instrument/stubs' AC_MSG_CHECKING(for instrumentation support) AC_ARG_ENABLE(instrumentation, [ --enable-instrumentation compile in support for instrumentation], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_INSTRUMENTATION, 1) INSTRUMENT_VAR='$(INSTRUMENT_LIB)' elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_INSTRUMENTATION, 0) INSTRUMENT_VAR='' else AC_MSG_RESULT(yes) AC_DEFINE(BX_INSTRUMENTATION, 1) INSTRUMENT_DIR=$enableval INSTRUMENT_VAR='$(INSTRUMENT_LIB)' fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_INSTRUMENTATION, 0) INSTRUMENT_VAR='' ] ) AC_SUBST(INSTRUMENT_DIR) AC_SUBST(INSTRUMENT_VAR) dnl // serial mode 'socket' needs wsock32.dll in non-plugin mode if test "$bx_plugins" = 0; then case $target in *-pc-windows*) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS wsock32.lib" ;; *-cygwin* | *-mingw32*) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lwsock32" ;; esac fi AC_MSG_CHECKING(enable logging) AC_ARG_ENABLE(logging, [ --enable-logging enable logging], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_NO_LOGGING, 0) else AC_MSG_RESULT(no) AC_DEFINE(BX_NO_LOGGING, 1) fi], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_NO_LOGGING, 0) ] ) AC_MSG_CHECKING(enable assert checks) AC_ARG_ENABLE(assert-checks, [ --enable-assert-checks enable BX_ASSERT checks], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_ASSERT_ENABLE, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_ASSERT_ENABLE, 0) fi], [ if test "$bx_debugger" = 1; then AC_MSG_RESULT(yes) AC_DEFINE(BX_ASSERT_ENABLE, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_ASSERT_ENABLE, 0) fi ] ) AC_MSG_CHECKING(for raw serial support) AC_ARG_ENABLE(raw-serial, [ --enable-raw-serial use raw serial port access], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(USE_RAW_SERIAL, 1) else AC_MSG_RESULT(no) AC_DEFINE(USE_RAW_SERIAL, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(USE_RAW_SERIAL, 0) ] ) AC_MSG_CHECKING(for CLGD54XX emulation) AC_ARG_ENABLE(clgd54xx, [ --enable-clgd54xx enable CLGD54XX emulation], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_CLGD54XX, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_CLGD54XX, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_CLGD54XX, 0) ] ) support_fpu=1 AC_MSG_CHECKING(for FPU emulation) FPU_VAR='' AC_ARG_ENABLE(fpu, [ --enable-fpu compile in FPU emulation], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_FPU, 1) FPU_VAR='$(FPU_LIB)' elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_FPU, 0) support_fpu=0 else echo " " echo "ERROR: --enable-fpu does not accept a path" exit 1 fi ], [ AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_FPU, 1) FPU_VAR='$(FPU_LIB)' ] ) AC_SUBST(FPU_VAR) support_vmx=0 AC_MSG_CHECKING(for VMX support) AC_ARG_ENABLE(vmx, [ --enable-vmx VMX (virtualization extensions) emulation (--enable-vmx=[no|1|2])], [case "$enableval" in no | 0) support_vmx=0 AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_VMX, 0) ;; yes | 1) support_vmx=1 AC_MSG_RESULT(1) AC_DEFINE(BX_SUPPORT_VMX, 1) ;; 2) support_vmx=2 AC_MSG_RESULT(2) AC_DEFINE(BX_SUPPORT_VMX, 2) ;; *) echo "ERROR: --enable-vmx=$enableval not understood. Use --enable-vmx=[no|1|2]" exit 1 ;; esac ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_VMX, 0) ] ) if test "$support_vmx" -gt 0 -a "$bx_cpu_level" -lt 6; then AC_MSG_ERROR([for VMX support the CPU level must be set to 6]) fi if test "$support_vmx" -gt 1 -a "$use_x86_64" = 0; then AC_MSG_ERROR([VMXx2 support require x86-64 enabled]) fi support_svm=0 AC_MSG_CHECKING(for SVM support) AC_ARG_ENABLE(svm, [ --enable-svm SVM (AMD: secure virtual machine) emulation], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_SVM, 1) support_svm=1 elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_SVM, 0) fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_SVM, 0) ] ) if test "$support_svm" -gt 0 -a "$bx_cpu_level" -lt 6; then AC_MSG_ERROR([for SVM support the CPU level must be set to 6]) fi if test "$support_svm" -gt 1 -a "$use_x86_64" = 0; then AC_MSG_ERROR([SVM support require x86-64 enabled]) fi AC_MSG_CHECKING(for 3DNow! support) AC_ARG_ENABLE(3dnow, [ --enable-3dnow 3DNow! support (incomplete)], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_3DNOW, 1) elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_3DNOW, 0) fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_3DNOW, 0) ] ) AC_MSG_CHECKING(for alignment check support) AC_ARG_ENABLE(alignment-check, [ --enable-alignment-check alignment check (#AC) support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_ALIGNMENT_CHECK, 1) elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_ALIGNMENT_CHECK, 0) fi ], [ if test "$bx_cpu_level" -gt 3; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_ALIGNMENT_CHECK, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_ALIGNMENT_CHECK, 0) fi ] ) AC_MSG_CHECKING(for misaligned SSE support) AC_ARG_ENABLE(misaligned-sse, [ --enable-misaligned-sse misaligned SSE support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_MISALIGNED_SSE, 1) elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_MISALIGNED_SSE, 0) fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_MISALIGNED_SSE, 0) ] ) AC_MSG_CHECKING(for MONITOR/MWAIT instructions support (experimental)) AC_ARG_ENABLE(monitor_mwait, [ --enable-monitor-mwait support for MONITOR/MWAIT instructions (experimental)], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_MONITOR_MWAIT, 1) elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_MONITOR_MWAIT, 0) fi ], [ if test "$bx_cpu_level" -gt 5; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_MONITOR_MWAIT, 1) else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_MONITOR_MWAIT, 0) fi ] ) support_avx=0 AC_MSG_CHECKING(for AVX instructions support) AC_ARG_ENABLE(avx, [ --enable-avx support for AVX instructions], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_AVX, 1) support_avx=1 elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_AVX, 0) fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_AVX, 0) ] ) if test "$support_avx" -gt 0 -a "$use_x86_64" = 0; then AC_MSG_ERROR([for AVX support x86-64 emulation must be compiled in!]) fi AC_MSG_CHECKING(for x86 debugger support) AC_ARG_ENABLE(x86-debugger, [ --enable-x86-debugger x86 debugger support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_X86_DEBUGGER, 1) elif test "$enableval" = no; then AC_MSG_RESULT(no) AC_DEFINE(BX_X86_DEBUGGER, 0) fi ], [ AC_MSG_RESULT(no) AC_DEFINE(BX_X86_DEBUGGER, 0) ] ) AC_MSG_CHECKING(for CDROM support) AC_ARG_ENABLE(cdrom, [ --enable-cdrom CDROM support], [if test "$enableval" = no; then bx_cdrom=0 else bx_cdrom=1 fi], [ bx_cdrom=1 ] ) if test "$bx_cdrom" = 1; then AC_MSG_RESULT(yes) CDROM_OBJS='cdrom.o' case $target in *-pc-windows* | *-pc-winnt* | *-pc-cygwin* | *-mingw32*) CDROM_OBJS="$CDROM_OBJS cdrom_win32.o" AC_DEFINE(BX_SUPPORT_CDROM, 1) ;; *) AC_CHECK_HEADER(IOKit/storage/IOCDMedia.h, can_use_osx_cdrom=yes ) if test "$with_amigaos" = yes; then # use the amiga cdrom file instead. CDROM_OBJS="$CDROM_OBJS cdrom_amigaos.o" elif test "$can_use_osx_cdrom" = yes; then # use cdrom_osx AC_MSG_RESULT(Using OSX IOKit CD Interface) CDROM_OBJS="$CDROM_OBJS cdrom_osx.o" EXTRA_LINK_OPTS="${EXTRA_LINK_OPTS} -framework IOKit -framework CoreFoundation "'$(GUI_LINK_OPTS)' else CDROM_OBJS="$CDROM_OBJS cdrom_misc.o" fi AC_DEFINE(BX_SUPPORT_CDROM, 1) ;; esac else AC_MSG_RESULT(no) CDROM_OBJS='' AC_DEFINE(BX_SUPPORT_CDROM, 0) fi AC_SUBST(CDROM_OBJS) SOUNDCARD_OBJS='' SOUNDLOW_OBJS='' GAME_OBJS='' soundcard_present=0 gameport_present=0 AC_MSG_CHECKING(for Sound Blaster 16 support) AC_ARG_ENABLE(sb16, [ --enable-sb16 Sound Blaster 16 Support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) SOUNDCARD_OBJS='sb16.o' soundcard_present=1 AC_DEFINE(BX_SUPPORT_SB16, 1) GAME_OBJS='gameport.o' gameport_present=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_SB16, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_SB16, 0) ] ) AC_MSG_CHECKING(for ES1370 soundcard support) AC_ARG_ENABLE(es1370, [ --enable-es1370 enable ES1370 soundcard support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) if test "$pci" != "1"; then AC_MSG_ERROR([ES1370 soundcard requires PCI support]) fi SOUNDCARD_OBJS="$SOUNDCARD_OBJS es1370.o" soundcard_present=1 AC_DEFINE(BX_SUPPORT_ES1370, 1) GAME_OBJS='gameport.o' gameport_present=1 else AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_ES1370, 0) fi], [ AC_MSG_RESULT(no) AC_DEFINE(BX_SUPPORT_ES1370, 0) ] ) if test "$soundcard_present" = 1; then AC_MSG_CHECKING(for sound lowlevel module) AC_DEFINE(BX_SUPPORT_SOUNDLOW, 1) case "$target" in *-linux* | *-freebsd*) SOUNDLOW_OBJS='soundlnx.o' AC_DEFINE(BX_SOUND_LOWLEVEL_C, bx_sound_linux_c) AC_MSG_RESULT(linux) bx_have_alsa=0 AC_CHECK_HEADER([alsa/asoundlib.h], [bx_have_alsa=1]) if test "$bx_have_alsa" = 1; then AC_DEFINE(BX_HAVE_ALSASOUND, 1) if test "$bx_plugins" = 1; then SOUND_LINK_OPTS="$SOUND_LINK_OPTS -lasound" else DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lasound" fi fi ;; *-pc-windows*) SOUNDLOW_OBJS='soundwin.o' AC_DEFINE(BX_SOUND_LOWLEVEL_C, bx_sound_windows_c) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS winmm.lib" AC_MSG_RESULT(win) ;; *-cygwin* | *-mingw32*) SOUNDLOW_OBJS='soundwin.o' AC_DEFINE(BX_SOUND_LOWLEVEL_C, bx_sound_windows_c) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lwinmm" AC_MSG_RESULT(win) ;; *-macosx* | *-macos* | *-apple-darwin*) SOUNDLOW_OBJS='soundosx.o' AC_DEFINE(BX_SOUND_LOWLEVEL_C, bx_sound_osx_c) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -framework CoreServices -framework AudioUnit -framework AudioToolbox" AC_MSG_RESULT(osx) ;; *) SOUNDLOW_OBJS='' AC_DEFINE(BX_SOUND_LOWLEVEL_C, bx_sound_lowlevel_c) AC_MSG_RESULT(dummy) ;; esac AC_MSG_CHECKING(for additional sound lowlevel modules) if test "$with_sdl" = yes; then SOUNDLOW_OBJS="$SOUNDLOW_OBJS soundsdl.o" if test "$bx_plugins" = 1; then SOUND_LINK_OPTS="$SOUND_LINK_OPTS `sdl-config --libs`" fi AC_MSG_RESULT(sdl) else AC_MSG_RESULT(none) fi if test "$bx_plugins" = 0; then SOUND_LIB_VAR='iodev/sound/libsound.a' AC_SUBST(SOUND_LIB_VAR) fi else AC_DEFINE(BX_SUPPORT_SOUNDLOW, 0) fi AC_SUBST(SOUNDCARD_OBJS) AC_SUBST(SOUNDLOW_OBJS) AC_SUBST(SOUND_LINK_OPTS) AC_MSG_CHECKING(for standard PC gameport support) AC_ARG_ENABLE(gameport, [ --enable-gameport enable standard PC gameport support], [if test "$enableval" = yes; then AC_MSG_RESULT(yes) AC_DEFINE(BX_SUPPORT_GAMEPORT, 1) if test "$gameport_present" = 0; then GAME_OBJS='gameport.o' case $target in *-cygwin* | *-mingw32*) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lwinmm" ;; esac fi else AC_MSG_RESULT(no) GAME_OBJS='' AC_DEFINE(BX_SUPPORT_GAMEPORT, 0) fi], [ if test "$gameport_present" = 1; then AC_DEFINE(BX_SUPPORT_GAMEPORT, 1) AC_MSG_RESULT(yes) else AC_DEFINE(BX_SUPPORT_GAMEPORT, 0) AC_MSG_RESULT(no) fi] ) AC_SUBST(GAME_OBJS) AC_PATH_PROG(DOCBOOK2HTML, docbook2html, not_found) AC_MSG_CHECKING(whether to build docbook documentation) build_docbook=0 AC_ARG_ENABLE(docbook, [ --enable-docbook build the Docbook documentation], [ if test "$enableval" = yes; then build_docbook=1; fi ], [ dnl Not specified. If they have docbook2html, then yes. if test "$DOCBOOK2HTML" != not_found; then build_docbook=1; fi ] ) if test $build_docbook = 1; then AC_MSG_RESULT(yes) BUILD_DOCBOOK_VAR=build_docbook INSTALL_DOCBOOK_VAR=install_docbook CLEAN_DOCBOOK_VAR=clean_docbook if test "$DOCBOOK2HTML" = not_found; then echo "ERROR: docbook2html must be installed to build the documentation" exit 1 fi else AC_MSG_RESULT(no) fi AC_SUBST(BUILD_DOCBOOK_VAR) AC_SUBST(INSTALL_DOCBOOK_VAR) AC_SUBST(CLEAN_DOCBOOK_VAR) AC_SUBST(DOCBOOK2HTML) PRIMARY_TARGET='bochs' PLUGIN_LIBNAME_TRANSFORMATION='%.o=libbx_%.la' if test "$bx_plugins" = 0; then HDIMAGE_LIB_VAR='iodev/hdimage/libhdimage.a' AC_SUBST(HDIMAGE_LIB_VAR) fi IODEV_LIB_VAR='iodev/libiodev.a' NONINLINE_VAR='$(NONINLINE_OBJS)' AC_SUBST(IODEV_LIB_VAR) AC_SUBST(EXTRA_BX_OBJS) AC_SUBST(NONINLINE_VAR) AC_SUBST(INLINE_VAR) AC_SUBST(EXTERNAL_DEPENDENCY) AC_SUBST(RC_CMD) AC_ARG_WITH(x11, [ --with-x11 use X11 GUI], ) AC_ARG_WITH(win32, [ --with-win32 use Win32 GUI], ) AC_ARG_WITH(macos, [ --with-macos use Macintosh/CodeWarrior environment], ) AC_ARG_WITH(carbon, [ --with-carbon compile for MacOS X with Carbon GUI], ) AC_ARG_WITH(nogui, [ --with-nogui no native GUI, just use blank stubs], ) AC_ARG_WITH(term, [ --with-term textmode terminal environment], ) AC_ARG_WITH(rfb, [ --with-rfb use RFB protocol, works with VNC viewer], ) AC_ARG_WITH(amigaos, [ --with-amigaos use AmigaOS (or MorphOS) GUI], ) AC_ARG_WITH(sdl, [ --with-sdl use SDL libraries], ) AC_ARG_WITH(svga, [ --with-svga use SVGALib libraries], ) AC_ARG_WITH(wx, [ --with-wx use wxWidgets libraries], ) AC_ARG_WITH(all-libs, [ --with-all-libs compile all guis that Bochs supports], ) dnl // DASH is option prefix for your platform dnl // SLASH is directory for your platform dnl // CXXFP is C++ File Prefix; the flag that tells the compiler dnl // this is a C++ source file dnl // CFP is C File Prefix; the flag that tells the compiler dnl // this is a C source file dnl // OFP is Object File Prefix; the flag that tells the compiler dnl // generate an object file with this name DASH="-" SLASH="/" CXXFP="" CFP="" OFP="-o " MAKELIB="ar rv \$@" RMCOMMAND="rm -f " # first define link variables without libtool LINK="\$(CXX) -o \$@ \$(CXXFLAGS) \$(LDFLAGS)" LINK_CONSOLE="\$(CXX) -o \$@ \$(CXXFLAGS_CONSOLE) \$(LDFLAGS)" # unless NO_LT is set, add libtool to the front of the link command if test "$NO_LT" != 1; then LINK="\$(LIBTOOL) --mode=link --tag CXX $LINK" LINK_CONSOLE="\$(LIBTOOL) --mode=link --tag CXX $LINK_CONSOLE" fi EXE="" COMMAND_SEPARATOR="&& \\" CD_UP_ONE="echo done" CD_UP_TWO="echo done" CD_UP_THREE="echo done" INSTALL_TARGET=install_unix INSTALL_LIST_FOR_PLATFORM= # check for existence of and usable version of wxWidgets. This comes # early so that it could affect which one gets chosen. if test x$WX_CONFIG = x; then AC_CHECK_PROG(WX_CONFIG, [ wx-config --version ], wx-config, not_found) fi AC_MSG_CHECKING(for wxWidgets configuration script) AC_MSG_RESULT($WX_CONFIG) ok_wx_version=0 wx_multi_lib=0 needs_gtk2=0 wx_needs_gdk2=0 AC_MSG_CHECKING(for wxWidgets library version) if test x$WX_CONFIG != xnot_found; then WX_VERSION=`$WX_CONFIG --version` WX_BASENAME=`$WX_CONFIG --basename` [ # test that version >= 2.3.2. Anybody have a better way to do this? Yuck. case x$WX_VERSION in x2.[012]*) ;; # less than version 2.3.x x2.3.[01]) ;; # less than version 2.3.2 x2.3.[2-4]*) ok_wx_version=1 ;; # 2.3.2 or greater x2.[4-5]*) ok_wx_version=1 ;; # version 2.4 / 2.5 x2.[6-9]*) # version 2.6 or greater ok_wx_version=1 wx_multi_lib=1 case x$WX_BASENAME in xwx_gtk2|xwx_gtk2u) wx_needs_gdk2=1 ;; *) ;; esac ;; x[3-9]*) ok_wx_version=1 ;; # version 3 or greater *) ;; # who knows? esac ] fi AC_MSG_RESULT($WX_VERSION) if test "$cross_configure" = 0; then if test "$ok_wx_version" = 1; then # detected a usable version if test "$with_all_libs" = yes; then with_wx=yes fi else if test "$with_wx" = yes; then AC_MSG_WARN([Bochs for wxWidgets cannot be compiled here, disabling it]) fi with_wx=no fi fi AC_MSG_CHECKING(for default gui on this platform) AC_MSG_RESULT($DEFAULT_GUI) display_libs="" # the $with_* variable tells the gui library to use, but does NOT necessarily # indicate the platform. Settings that depend on the platform should be # handled later. XPM_LIB='' if test "$with_x11" = yes; then display_libs="$display_libs X11" if test "$no_x" = yes; then echo ERROR: X windows gui was selected, but X windows libraries were not found. exit 1 fi check_xpm=0 AC_MSG_CHECKING(whether user wants XPM support) AC_ARG_ENABLE(xpm, [ --enable-xpm enable the check for XPM support], [if test "$enableval" = yes; then check_xpm=0 AC_MSG_RESULT(yes) check_xpm=1 else AC_MSG_RESULT(no) check_xpm=0 fi], [ AC_MSG_RESULT(yes) check_xpm=1 ] ) if test $check_xpm = 1; then AC_CHECK_HEADER(X11/xpm.h, [ AC_DEFINE(BX_HAVE_XPM_H) XPM_LIB='-lXpm' ]) fi if test "$PKGCONFIG" != not_found; then X_CFLAGS="`pkg-config --cflags x11`" X_LIBS="`pkg-config --libs x11` $XPM_LIB -lXrandr" else X_LIBS="$X_LIBS -lX11 $XPM_LIB -lXrandr" fi AC_DEFINE(BX_WITH_X11, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_X11)" GUI_CFLAGS="$GUI_CFLAGS \$(X_CFLAGS)" GUI_CXXFLAGS="$GUI_CXXFLAGS \$(X_CFLAGS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_X)" # The enhanced X debugger depends on GTK2 if test "$gui_debugger" = 1; then needs_gtk2=1 fi fi AC_SUBST(X_CFLAGS) AC_SUBST(X_LIBS) if test "$with_sdl" = yes; then display_libs="$display_libs sdl" AC_DEFINE(BX_WITH_SDL, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_SDL)" # GUI_*FLAGS are added to the compilation of every bochs file, not just # the files in gui/*.cc. SDL_CFLAGS=`sdl-config --cflags` GUI_CFLAGS="$GUI_CFLAGS $SDL_CFLAGS" GUI_CXXFLAGS="$GUI_CXXFLAGS $SDL_CFLAGS" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_SDL)" # The enhanced X debugger depends on GTK2 if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then needs_gtk2=1 fi if test "$with_win32" != yes -a "$with_wx" != yes; then case $target in *-pc-windows*) RC_CMD="rc /fo" EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" ;; *-cygwin* | *-mingw32*) RC_CMD="windres -I. -o " EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" ;; esac fi fi if test "$with_svga" = yes; then display_libs="$display_libs svga" AC_DEFINE(BX_WITH_SVGA, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_SVGA)" # GUI_*FLAGS are added to the compilation of every bochs file, not just # the files in gui/*.cc. GUI_CFLAGS="$GUI_CFLAGS" GUI_CXXFLAGS="$GUI_CXXFLAGS" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_SVGA)" fi if test "$with_rfb" = yes; then display_libs="$display_libs rfb" AC_DEFINE(BX_WITH_RFB, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_RFB)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_RFB)" fi if test "$with_amigaos" = yes; then display_libs="$display_libs amigaos" AC_DEFINE(BX_WITH_AMIGAOS, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_AMIGAOS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_AMIGAOS)" fi if test "$with_win32" = yes; then display_libs="$display_libs win32" AC_DEFINE(BX_WITH_WIN32, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_WIN32)" case $target in *-pc-windows*) if test "$with_wx" != yes; then RC_CMD="rc /fo" EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" fi GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_WIN32_VCPP)" ;; *-cygwin* | *-mingw32*) if test "$with_wx" != yes; then RC_CMD="windres -I. -o " EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" fi GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_WIN32)" ;; *) echo Unsupported compile setup: GUI library is win32, but target is neither windows nor cygwin. ;; esac fi if test "$with_macos" = yes; then display_libs="$display_libs macos" AC_DEFINE(BX_WITH_MACOS, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_MACOS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_MACOS)" fi if test "$with_carbon" = yes; then display_libs="$display_libs carbon" AC_DEFINE(BX_WITH_CARBON, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_CARBON)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_CARBON)" if test "$bx_plugins" = 1; then PRIMARY_TARGET=bochs.app/.build_plugins # only for carbon application else PRIMARY_TARGET=bochs.app/.build # only for carbon application fi INSTALL_TARGET='install_macosx' fi if test "$with_term" = yes; then display_libs="$display_libs term" AC_DEFINE(BX_WITH_TERM, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_TERM)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_TERM)" use_curses=yes fi if test "$with_wx" = yes; then display_libs="$display_libs wxWidgets" if test "$cross_configure" = 1; then true # do not insist, if configuring for another machine else if test x$ok_wx_version != x1; then echo ERROR: A usable version of wxWidgets was not found. echo Upgrade the library or choose another gui. exit 1 fi fi AC_DEFINE(BX_WITH_WX, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_WX)" SPECIFIC_GUI_SUPPORT_OBJS="$SPECIFIC_GUI_SUPPORT_OBJS \$(GUI_OBJS_WX_SUPPORT)" WX_CFLAGS="`$WX_CONFIG --cflags`" WX_CXXFLAGS="`$WX_CONFIG --cxxflags`" if test "$wx_needs_gdk2" = 1; then GDK_CFLAGS="`pkg-config --cflags gdk-2.0`" WX_CFLAGS="$WX_CFLAGS $GDK_CFLAGS" WX_CXXFLAGS="$WX_CXXFLAGS $GDK_CFLAGS" fi if test "$wx_multi_lib" = 1; then GUI_LINK_OPTS_WX="`$WX_CONFIG --libs core,base`" else GUI_LINK_OPTS_WX="`$WX_CONFIG --libs`" fi # GUI_C*FLAGS are added to the compilation of every bochs file, not just # the files in gui/*.cc. They are not used when building other things # such as bximage. GUI_CFLAGS="$GUI_CFLAGS $WX_CFLAGS" GUI_CXXFLAGS="$GUI_CXXFLAGS $WX_CXXFLAGS" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_WX)" # using debugger with readline is failing due to thread/signal handler # problems. case $target in *-pc-windows* | *-cygwin* | *-mingw32*) EXTRA_BX_OBJS="$EXTRA_BX_OBJS wxbochs_resources.o" GUI_LINK_OPTS_WX="$GUI_LINK_OPTS_WX --subsystem,windows -mwindows" ;; *) # This is required for XStringToKeysym if test "$with_x11" != yes -a "$bx_plugins" != 1; then GUI_LINK_OPTS="$GUI_LINK_OPTS -lX11" fi ;; esac # The enhanced X debugger depends on GTK2 (unused yet, but fixes link failure) if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then needs_gtk2=1 fi fi if test "$with_nogui" = yes; then display_libs="$display_libs nogui" AC_DEFINE(BX_WITH_NOGUI, 1) SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_NOGUI)" fi AC_MSG_CHECKING(for display libraries) AC_MSG_RESULT($display_libs) if test "$display_libs" = ""; then echo "No display libraries were selected. Use --with-* options to enable" echo "individual display libraries, or --with-all-libs to detect the ones" echo "that Bochs supports." exit 1 fi # some display libraries and the enhanced debugger may depend on the GTK+ software package if test "$needs_gtk2" = 1; then # pkg-config is required to set TOOLKIT_CXXFLAGS and LIBS if test "$PKGCONFIG" != not_found; then TOOLKIT_CXXFLAGS="`pkg-config --cflags gtk+-2.0`" LIBS="$LIBS `pkg-config --libs gtk+-2.0`" else echo "ERROR: pkg-config was not found, or unable to access the gtk+-2.0 package." echo "Install pkg-config and the gtk+ development package," echo "or disable the gui debugger, or the wxWidgets display library (whichever is being used)." exit 1 fi fi dnl To use wxWidgets you must select it as both the configuration interface dnl and the display library. In the simplest case where the user has dnl only configured with --with-wx, set both defaults to wxWidgets. dnl Without this setting, the config interface would default to the text dnl mode config interface, and then the wxWidgets display library would not dnl be usable. if test "$display_libs" = " wxWidgets"; then AC_MSG_CHECKING(for default configuration interface) AC_MSG_RESULT(wxWidgets) AC_MSG_CHECKING(for default display library) AC_MSG_RESULT(wxWidgets) AC_DEFINE(BX_DEFAULT_CONFIG_INTERFACE, "wx") AC_DEFINE(BX_DEFAULT_DISPLAY_LIBRARY, "wx") AC_DEFINE(BX_USE_TEXTCONFIG, 0) else AC_DEFINE(BX_USE_TEXTCONFIG, 1) fi if test "$bx_plugins" = 1; then # every item in this list will be compiled as a plugin. Do not include # support objs; they will be mentioned in plugin-specific makefile rules. GUI_PLUGIN_OBJS="$GUI_PLUGIN_OBJS $SPECIFIC_GUI_OBJS" else # include support objs GUI_NON_PLUGIN_OBJS="$GUI_NON_PLUGIN_OBJS $SPECIFIC_GUI_OBJS $SPECIFIC_GUI_SUPPORT_OBJS" fi AC_SUBST(GUI_CFLAGS) AC_SUBST(GUI_CXXFLAGS) AC_SUBST(WX_CONFIG) AC_SUBST(WX_CFLAGS) AC_SUBST(WX_CXXFLAGS) AC_SUBST(TOOLKIT_CXXFLAGS) AC_CHECK_PROGS(WGET, wget curl fetch, not_found) if test "$WGET" = not_found; then AC_MSG_WARN([cannot find wget (or equivalent) command]) fi # everybody has to re-invent the wheel. differently. test "${WGET}" = "curl" && WGET="curl -O" # modify settings based on target platform case "$target" in *-macosx*) AC_DEFINE(BX_HAVE_STRDUP, 0) ;; *-macos*) AC_DEFINE(BX_HAVE_STRDUP, 0) AC_DEFINE(BX_PLUGINS, 0) AC_DEFINE(BX_HAVE_DLFCN_H, 0) AC_DEFINE(BX_HAVE_SOCKLEN_T, 0) AC_DEFINE(BX_HAVE_SELECT, 0) AC_DEFINE(BX_HAVE_GETTIMEOFDAY, 0) AC_DEFINE(BX_NO_ATTRIBUTES, 1) AC_DEFINE(BX_NETMOD_TUNTAP, 0) AC_DEFINE(BX_NETMOD_TAP, 0) ;; *-pc-windows*) INSTALL_TARGET='install_win32' CC="cl" CXX="$CC" #C_OPT="/Zi" # for debugging C_OPT="/Ox" # optimize for speed if test "$bx_plugins" = 1; then CFLAGS="/nologo /MD /W3 /EHs-c- /DNDEBUG /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS $C_OPT" else CFLAGS="/nologo /MT /W3 /EHs-c- /DNDEBUG /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS $C_OPT" fi CXXFLAGS="$CFLAGS" DASH="/" SLASH="\\" CXXFP="/Tp" CFP="/Tc" OFP="/Fo" MAKE=nmake MAKELIB="lib /nologo /subsystem:console /verbose /out:\$@" RMCOMMAND="-del" RANLIB="echo" #L_OPT="/debug" # for debugging L_OPT="" # no debug info LINK="link $L_OPT /nologo /subsystem:console /incremental:no /out:\$@ " LINK_CONSOLE=$LINK EXE=".exe" PRIMARY_TARGET="bochs.exe" BXIMAGE_LINK_OPTS="user32.lib" # also compile niclist if networking is on if test "$networking" = yes; then PRIMARY_TARGET="$PRIMARY_TARGET niclist.exe" fi COMMAND_SEPARATOR="" CD_UP_ONE="cd .." CD_UP_TWO="cd ..\.." CD_UP_THREE="cd ..\..\.." have_gettimeofday=0 # even though it may exist in build environment AC_DEFINE(BX_64BIT_CONSTANTS_USE_LL, 0) AC_DEFINE(inline, __forceinline) AC_DEFINE(BX_NO_ATTRIBUTES, 1) AC_DEFINE(HAVE_LIBREADLINE, 0) AC_DEFINE(HAVE_READLINE_HISTORY_H, 0) READLINE_LIB=""; AC_DEFINE(BX_HAVE_DLFCN_H, 0) AC_DEFINE(BX_NETMOD_TAP, 0) ;; *-pc-cygwin*) EXE=".exe" PRIMARY_TARGET="bochs.exe" BXIMAGE_LINK_OPTS="-luser32" if test "$networking" = yes; then PRIMARY_TARGET="$PRIMARY_TARGET niclist.exe" fi AC_DEFINE(BX_HAVE_SELECT, 1) ;; *-pc-mingw*) BXIMAGE_LINK_OPTS="-luser32" if test "$networking" = yes; then PRIMARY_TARGET="$PRIMARY_TARGET niclist" fi AC_DEFINE(BX_HAVE_SELECT, 1) ;; esac ENH_DBG_OBJS="" if test "$gui_debugger" = 1; then if test "$needs_gtk2" = 1; then ENH_DBG_OBJS="gtk_enh_dbg_osdep.o" elif test "$DEFAULT_GUI" = win32; then ENH_DBG_OBJS="win32_enh_dbg_osdep.o" fi fi AC_SUBST(ENH_DBG_OBJS) DIALOG_OBJS="" EXPORT_DYNAMIC="-export-dynamic" case $target in *-pc-windows* | *-pc-winnt*) if test "$bx_plugins" = 1; then # set variables for building DLL plugins PLUGIN_VAR="" PLUGIN_LIBNAME_TRANSFORMATION='%.o=bx_%.dll' INSTALL_PLUGINS_VAR=install_dll_plugins LIBS="$LIBS advapi32.lib comctl32.lib comdlg32.lib gdi32.lib shell32.lib user32.lib" else if test "$with_win32" != yes; then LIBS="$LIBS comctl32.lib" fi fi DIALOG_OBJS="win32dialog.o win32paramdlg.o" EXPORT_DYNAMIC="" ;; *-cygwin* | *-mingw*) if test "$bx_plugins" = 1; then AC_CHECK_LIB(mingwex, opendir, LIBS="$LIBS -lmingwex") # set variables for building DLL plugins PRIMARY_TARGET=".win32_dll_plugin_target" PLUGIN_LIBNAME_TRANSFORMATION='%.o=bx_%.dll' INSTALL_PLUGINS_VAR=install_dll_plugins else if test "$with_win32" != yes; then LIBS="$LIBS -lcomctl32" fi fi DIALOG_OBJS="win32dialog.o win32paramdlg.o" EXPORT_DYNAMIC="" ;; esac AC_SUBST(DIALOG_OBJS) AC_SUBST(EXPORT_DYNAMIC) if test "$use_curses" = yes -a "$cross_configure" = 0; then AC_CHECK_LIB(curses, mvaddch, GUI_LINK_OPTS_TERM='-lcurses') AC_CHECK_LIB(ncurses, mvaddch, GUI_LINK_OPTS_TERM='-lncurses') AC_CHECK_LIB(termlib, mvaddch, GUI_LINK_OPTS_TERM='-ltermlib') AC_CHECK_LIB(pdcurses, mvaddch, GUI_LINK_OPTS_TERM='-lpdcurses') if test "$GUI_LINK_OPTS_TERM" = ""; then echo Curses library not found: tried curses, ncurses, termlib and pdcurses. exit 1 fi fi if test "$with_term" = yes; then old_LIBS="$LIBS" LIBS="$LIBS $GUI_LINK_OPTS_TERM" AC_CHECK_FUNCS(color_set, AC_DEFINE(BX_HAVE_COLOR_SET, 1)) AC_CHECK_FUNCS(mvhline, AC_DEFINE(BX_HAVE_MVHLINE, 1)) AC_CHECK_FUNCS(mvvline, AC_DEFINE(BX_HAVE_MVVLINE, 1)) LIBS="$old_LIBS" fi if test "$with_rfb" = yes; then # we need the socket function case $target in *-pc-windows*) # is this okay without a check ? RFB_LIBS="$RFB_LIBS wsock32.lib" have_socket=yes ;; *-pc-winnt* | *-pc-cygwin* | *-mingw32*) # is this okay without a check ? RFB_LIBS="$RFB_LIBS -lwsock32" have_socket=yes ;; *) AC_CHECK_FUNCS(socket, have_socket=yes) if test "$have_socket" != yes; then AC_CHECK_LIB(socket, socket, [ RFB_LIBS="$RFB_LIBS -lsocket" have_socket=yes ]) fi ;; esac if test "$have_socket" != yes; then echo 'ERROR: socket function required for RFB compile' exit 1 fi fi # The ACX_PTHREAD function was written by # Steven G. Johnson and # Alejandro Forero Cuervo # I found it in the ac-archive project on Source Forge. AC_DEFUN([ACX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) acx_pthread_ok=no # First, check if the POSIX threads header, pthread.h, is available. # If it isn't, don't bother looking for the threads libraries. AC_CHECK_HEADER(pthread.h, , acx_pthread_ok=noheader) # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) AC_MSG_RESULT($acx_pthread_ok) if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_TRY_LINK([#include ], [pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], [acx_pthread_ok=yes]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($acx_pthread_ok) if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). AC_MSG_CHECKING([for joinable pthread attribute]) AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_JOINABLE;], ok=PTHREAD_CREATE_JOINABLE, ok=unknown) if test x"$ok" = xunknown; then AC_TRY_LINK([#include ], [int attr=PTHREAD_CREATE_UNDETACHED;], ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, [Define to the necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_RESULT(${ok}) if test x"$ok" = xunknown; then AC_MSG_WARN([we do not know how to create joinable pthreads]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; *solaris* | alpha*-osf*) flag="-D_REENTRANT";; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else acx_pthread_ok=no $2 fi ])dnl ACX_PTHREAD pthread_ok=no ACX_PTHREAD([ pthread_ok=yes #echo Using PTHREAD_LIBS=$PTHREAD_LIBS #echo Using PTHREAD_CFLAGS=$PTHREAD_CFLAGS #echo Using PTHREAD_CC=$PTHREAD_CC ]) # since some features need the pthread library, check that it was found. # But on win32 platforms, the pthread library is not needed. if test "$cross_configure" = 0; then if test "$with_rfb" = yes -o "$soundcard_present" = 1; then if test "$pthread_ok" = yes; then if test "$with_rfb" = yes; then RFB_LIBS="$RFB_LIBS $PTHREAD_LIBS" fi if test "$soundcard_present" = 1; then if test "$bx_plugins" = 1; then SOUND_LINK_OPTS="$SOUND_LINK_OPTS $PTHREAD_LIBS" else DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS $PTHREAD_LIBS" fi fi CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" else case "$target" in *-pc-windows* | *-pc-winnt* | *-cygwin* | *-mingw32*) # pthread not needed for win32 platform ;; *) echo ERROR: the pthread library is required, but could not be found.; exit 1 esac fi fi fi dnl // DEPRECATED configure options - force users to remove them AC_MSG_CHECKING(for APIC support (deprecated)) AC_ARG_ENABLE(apic, [ --enable-apic enable APIC support (deprecated)], [AC_MSG_RESULT($enableval) AC_MSG_ERROR([DEPRECATED - enabled automatically with SMP or when CPU_LEVEL >= 5]) ], [ AC_MSG_RESULT(no) ]) AC_MSG_CHECKING(for X2APIC support (deprecated)) AC_ARG_ENABLE(x2apic, [ --enable-x2apic enable X2APIC support (deprecated)], [AC_MSG_RESULT($enableval) AC_MSG_ERROR([DEPRECATED - moved to .bochsrc options]) ], [ AC_MSG_RESULT(no) ]) AC_MSG_CHECKING(for VESA BIOS extensions (deprecated)) AC_ARG_ENABLE(vbe, [ --enable-vbe use VESA BIOS extensions (deprecated)], [AC_MSG_RESULT($enableval) AC_MSG_ERROR([DEPRECATED - this feature always available with .bochsrc option]) ], [ AC_MSG_RESULT(no) ]) AC_MSG_CHECKING(for ACPI extensions support (deprecated)) AC_ARG_ENABLE(acpi, [ --enable-acpi use ACPI extensions support (deprecated)], [AC_MSG_RESULT($enableval) AC_MSG_ERROR([DEPRECATED - this feature enabled with PCI configure option and could be turned on through .bochsrc option]) ], [ AC_MSG_RESULT(no) ]) AC_MSG_CHECKING(for instruction trace cache support (deprecated)) AC_ARG_ENABLE(trace-cache, [ --enable-trace-cache support instruction trace cache (deprecated)], [AC_MSG_RESULT($enableval) AC_MSG_ERROR([DEPRECATED - this feature will be enabled in all configurations]) ], [ AC_MSG_RESULT(no) ]) # Create some subdirectories for when you run configure from some other # directory. if test ! -d instrument; then mkdir instrument; fi if test ! -d build; then mkdir build; fi if test ! -d build/linux; then mkdir build/linux; fi if test ! -d build/win32; then mkdir build/win32; fi if test ! -d build/win32/nsis; then mkdir build/win32/nsis; fi AC_SUBST(INSTALL_TARGET) AC_SUBST(INSTALL_LIST_FOR_PLATFORM) AC_SUBST(RFB_LIBS) AC_SUBST(GUI_OBJS) AC_SUBST(DEVICE_LINK_OPTS) AC_SUBST(GUI_LINK_OPTS) AC_SUBST(GUI_LINK_OPTS_TERM) AC_SUBST(GUI_LINK_OPTS_WX) AC_SUBST(BXIMAGE_LINK_OPTS) AC_SUBST(DASH) AC_SUBST(SLASH) AC_SUBST(CXXFP) AC_SUBST(CFP) AC_SUBST(OFP) AC_SUBST(MAKELIB) AC_SUBST(RMCOMMAND) AC_SUBST(LINK) AC_SUBST(LINK_CONSOLE) AC_SUBST(EXE) AC_SUBST(PRIMARY_TARGET) AC_SUBST(PLUGIN_LIBNAME_TRANSFORMATION) AC_SUBST(COMMAND_SEPARATOR) AC_SUBST(CD_UP_ONE) AC_SUBST(CD_UP_TWO) AC_SUBST(CD_UP_THREE) AC_SUBST(VERSION) AC_SUBST(VER_STRING) AC_SUBST(WIN_VER_STRING) AC_SUBST(REL_STRING) AC_SUBST(EXTRA_LINK_OPTS) AC_SUBST(GUI_NON_PLUGIN_OBJS) AC_SUBST(GUI_PLUGIN_OBJS) AC_SUBST(IODEV_NON_PLUGIN_OBJS) AC_SUBST(IODEV_PLUGIN_OBJS) AC_SUBST(IODEV_EXT_NON_PLUGIN_OBJS) AC_SUBST(IODEV_EXT_PLUGIN_OBJS) AC_SUBST(PLUGIN_VAR) AC_SUBST(PLUGIN_TARGET) AC_SUBST(INSTALL_PLUGINS_VAR) AC_PATH_PROG(GZIP, gzip) AC_PATH_PROG(TAR, tar) AC_OUTPUT(Makefile iodev/Makefile iodev/hdimage/Makefile iodev/usb/Makefile \ iodev/network/Makefile iodev/sound/Makefile bx_debug/Makefile \ bios/Makefile cpu/Makefile cpu/cpudb/Makefile memory/Makefile \ gui/Makefile disasm/Makefile ${INSTRUMENT_DIR}/Makefile misc/Makefile \ fpu/Makefile doc/docbook/Makefile build/linux/bochs-dlx \ bxversion.h bxversion.rc build/macosx/Info.plist \ build/win32/nsis/Makefile build/win32/nsis/bochs.nsi \ host/linux/pcidev/Makefile) bochs-2.6/crc.cc0000644000175000017500000000437612020641507013422 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: crc.cc 10297 2011-04-03 09:55:17Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // I grabbed these CRC routines from the following source: // http://www.landfield.com/faqs/compression-faq/part1/section-25.html // // These routines are very useful, so I'm including them in bochs. // They are not covered by the license, as they are not my doing. // My gratitude to the author for offering them on the 'net. // // I only changed the u_long to Bit32u, and u_char to Bit8u, and gave // the functions prototypes. // // -Kevin // // ************************************************************************** // The following C code (by Rob Warnock ) does CRC-32 in // BigEndian/BigEndian byte/bit order. That is, the data is sent most // significant byte first, and each of the bits within a byte is sent most // significant bit first, as in FDDI. You will need to twiddle with it to do // Ethernet CRC, i.e., BigEndian/LittleEndian byte/bit order. [Left as an // exercise for the reader.] // // The CRCs this code generates agree with the vendor-supplied Verilog models // of several of the popular FDDI "MAC" chips. // ************************************************************************** #include "config.h" /* Initialized first time "crc32()" is called. If you prefer, you can * statically initialize it at compile time. [Another exercise.] */ static Bit32u crc32_table[256]; /* * Build auxiliary table for parallel byte-at-a-time CRC-32. */ #define CRC32_POLY 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */ static void init_crc32(void) { int i, j; Bit32u c; for (i = 0; i < 256; ++i) { for (c = i << 24, j = 8; j > 0; --j) c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); crc32_table[i] = c; } } Bit32u crc32(const Bit8u *buf, int len) { const Bit8u *p; Bit32u crc; if (!crc32_table[1]) /* if not already done, */ init_crc32(); /* build table */ crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ for (p = buf; len > 0; ++p, --len) crc = (crc << 8) ^ crc32_table[(crc >> 24) ^ *p]; return ~crc; /* transmit complement, per CRC-32 spec */ } bochs-2.6/extplugin.h0000644000175000017500000000276512020641507014534 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: extplugin.h 10966 2012-01-10 17:45:18Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // extplugin.h // // This header file defines the types necessary to make a Bochs plugin, // but without mentioning all the details of Bochs internals (bochs.h). // It is included by the configuration interfaces and possibly other // things which are intentionally isolated from other parts of the program. // // The plugin_t struct comes from the plugin.h file from plex86. // Plex86 is Copyright (C) 1999-2000 The plex86 developers team // ///////////////////////////////////////////////////////////////////////// #ifndef __EXTPLUGIN_H #define __EXTPLUGIN_H #if BX_PLUGINS #if BX_HAVE_LTDL #include #elif !defined(_MSC_VER) #include "ltdl.h" #endif #endif enum plugintype_t { PLUGTYPE_NULL=100, PLUGTYPE_CORE, PLUGTYPE_STANDARD, PLUGTYPE_OPTIONAL, PLUGTYPE_USER }; #define MAX_ARGC 10 typedef int (*plugin_init_t)(struct _plugin_t *plugin, plugintype_t type, int argc, char *argv[]); typedef void (*plugin_fini_t)(void); typedef struct _plugin_t { plugintype_t type; int initialized; #if BX_PLUGINS #if defined(_MSC_VER) HINSTANCE handle; #else lt_dlhandle handle; #endif #endif int argc; char *name, *args, *argv[MAX_ARGC]; plugin_init_t plugin_init; plugin_fini_t plugin_fini; struct _plugin_t *next; } plugin_t; #endif /* __EXTPLUGIN_H */ bochs-2.6/ltmain.sh0000644000175000017500000054142412020641507014164 0ustar guillemguillem# ltmain.sh - Provide generalized library-building support services. # NOTE: Changing this file will not affect anything until you rerun configure. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003 # Free Software Foundation, Inc. # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Check that we have a working $echo. if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then # Yippee, $echo works! : else # Restart under the correct shell, and then maybe $echo will work. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat <&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 fi # Global variables. mode=$default_mode nonopt= prev= prevopt= run= show="$echo" show_help= execute_dlfiles= lo2o="s/\\.lo\$/.${objext}/" o2lo="s/\\.${objext}\$/.lo/" ##################################### # Shell function definitions: # This seems to be the best place for them # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. win32_libid () { win32_libid_type="unknown" win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ grep -E 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then win32_nmres=`eval $NM -f posix -A $1 | \ sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'` if test "X$win32_nmres" = "Ximport" ; then win32_libid_type="x86 archive import" else win32_libid_type="x86 archive static" fi fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $echo $win32_libid_type } # End of Shell function definitions ##################################### # Parse our command line options once, thoroughly. while test "$#" -gt 0 do arg="$1" shift case $arg in -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; *) optarg= ;; esac # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in execute_dlfiles) execute_dlfiles="$execute_dlfiles $arg" ;; tag) tagname="$arg" # Check whether tagname contains only valid characters case $tagname in *[!-_A-Za-z0-9,/]*) $echo "$progname: invalid tag name: $tagname" 1>&2 exit 1 ;; esac case $tagname in CC) # Don't test for the "default" C tag, as we know, it's there, but # not specially marked. ;; *) if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$0" > /dev/null; then taglist="$taglist $tagname" # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $0`" else $echo "$progname: ignoring unknown tag $tagname" 1>&2 fi ;; esac ;; *) eval "$prev=\$arg" ;; esac prev= prevopt= continue fi # Have we seen a non-optional argument yet? case $arg in --help) show_help=yes ;; --version) $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" $echo $echo "Copyright (C) 2003 Free Software Foundation, Inc." $echo "This is free software; see the source for copying conditions. There is NO" $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." exit 0 ;; --config) ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 # Now print the configurations for the tags. for tagname in $taglist; do ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$0" done exit 0 ;; --debug) $echo "$progname: enabling shell trace mode" set -x ;; --dry-run | -n) run=: ;; --features) $echo "host: $host" if test "$build_libtool_libs" = yes; then $echo "enable shared libraries" else $echo "disable shared libraries" fi if test "$build_old_libs" = yes; then $echo "enable static libraries" else $echo "disable static libraries" fi exit 0 ;; --finish) mode="finish" ;; --mode) prevopt="--mode" prev=mode ;; --mode=*) mode="$optarg" ;; --preserve-dup-deps) duplicate_deps="yes" ;; --quiet | --silent) show=: ;; --tag) prevopt="--tag" prev=tag ;; --tag=*) set tag "$optarg" ${1+"$@"} shift prev=tag ;; -dlopen) prevopt="-dlopen" prev=execute_dlfiles ;; -*) $echo "$modename: unrecognized option \`$arg'" 1>&2 $echo "$help" 1>&2 exit 1 ;; *) nonopt="$arg" break ;; esac done if test -n "$prevopt"; then $echo "$modename: option \`$prevopt' requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= if test -z "$show_help"; then # Infer the operation mode. if test -z "$mode"; then $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2 case $nonopt in *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) mode=link for arg do case $arg in -c) mode=compile break ;; esac done ;; *db | *dbx | *strace | *truss) mode=execute ;; *install*|cp|mv) mode=install ;; *rm) mode=uninstall ;; *) # If we have no mode, but dlfiles were specified, then do execute mode. test -n "$execute_dlfiles" && mode=execute # Just use the default operation mode. if test -z "$mode"; then if test -n "$nonopt"; then $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 else $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 fi fi ;; esac fi # Only execute mode is allowed to have -dlopen flags. if test -n "$execute_dlfiles" && test "$mode" != execute; then $echo "$modename: unrecognized option \`-dlopen'" 1>&2 $echo "$help" 1>&2 exit 1 fi # Change the help message to a mode-specific one. generic_help="$help" help="Try \`$modename --help --mode=$mode' for more information." # These modes are in order of execution frequency so that they run quickly. case $mode in # libtool compile mode compile) modename="$modename: compile" # Get the compilation command and the source file. base_compile= srcfile="$nonopt" # always keep a non-empty value in "srcfile" suppress_output= arg_mode=normal libobj= for arg do case "$arg_mode" in arg ) # do not "continue". Instead, add this to base_compile lastarg="$arg" arg_mode=normal ;; target ) libobj="$arg" arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) if test -n "$libobj" ; then $echo "$modename: you cannot specify \`-o' more than once" 1>&2 exit 1 fi arg_mode=target continue ;; -static) build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` lastarg= save_ifs="$IFS"; IFS=',' for arg in $args; do IFS="$save_ifs" # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac lastarg="$lastarg $arg" done IFS="$save_ifs" lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` # Add the arguments to base_compile. base_compile="$base_compile $lastarg" continue ;; * ) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg="$srcfile" srcfile="$arg" ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` case $lastarg in # Double-quote args containing other shell metacharacters. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") lastarg="\"$lastarg\"" ;; esac base_compile="$base_compile $lastarg" done # for arg case $arg_mode in arg) $echo "$modename: you must specify an argument for -Xcompile" exit 1 ;; target) $echo "$modename: you must specify a target with \`-o'" 1>&2 exit 1 ;; *) # Get the name of the library object. [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo xform='[cCFSifmso]' case $libobj in *.ada) xform=ada ;; *.adb) xform=adb ;; *.ads) xform=ads ;; *.asm) xform=asm ;; *.c++) xform=c++ ;; *.cc) xform=cc ;; *.ii) xform=ii ;; *.class) xform=class ;; *.cpp) xform=cpp ;; *.cxx) xform=cxx ;; *.f90) xform=f90 ;; *.for) xform=for ;; *.java) xform=java ;; esac libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` case $libobj in *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; *) $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 exit 1 ;; esac # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. if test -n "$available_tags" && test -z "$tagname"; then case $base_compile in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" case "$base_compile " in "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then $echo "$modename: unable to infer tagged configuration" $echo "$modename: specify a tag with \`--tag'" 1>&2 exit 1 # else # $echo "$modename: using $tagname tagged configuration" fi ;; esac fi objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$obj"; then xdir= else xdir=$xdir/ fi lobj=${xdir}$objdir/$objname if test -z "$base_compile"; then $echo "$modename: you must specify a compilation command" 1>&2 $echo "$help" 1>&2 exit 1 fi # Delete any leftover library objects. if test "$build_old_libs" = yes; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi $run $rm $removelist trap "$run $rm $removelist; exit 1" 1 2 15 # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2*) pic_mode=default ;; esac if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test "$compiler_c_o" = no; then output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} lockfile="$output_obj.lock" removelist="$removelist $output_obj $lockfile" trap "$run $rm $removelist; exit 1" 1 2 15 else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test "$need_locks" = yes; then until $run ln "$0" "$lockfile" 2>/dev/null; do $show "Waiting for $lockfile to be removed" sleep 2 done elif test "$need_locks" = warn; then if test -f "$lockfile"; then $echo "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi $echo $srcfile > "$lockfile" fi if test -n "$fix_srcfile_path"; then eval srcfile=\"$fix_srcfile_path\" fi $run $rm "$libobj" "${libobj}T" # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then $show "$mv $output_obj $lobj" if $run $mv $output_obj $lobj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the PIC object to the libtool object file. test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then $echo "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support \`-c' and \`-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $run $rm $removelist exit 1 fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then $show "$mv $output_obj $obj" if $run $mv $output_obj $obj; then : else error=$? $run $rm $removelist exit $error fi fi # Append the name of the non-PIC object the libtool object file. # Only append if the libtool object file exists. test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi else if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi fi build_libtool_libs=no build_old_libs=yes prefer_static_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg="$1" base_compile="$base_compile $arg" shift case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test ;; *) qarg=$arg ;; esac libtool_args="$libtool_args $qarg" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) compile_command="$compile_command @OUTPUT@" finalize_command="$finalize_command @OUTPUT@" ;; esac case $prev in dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. compile_command="$compile_command @SYMFILE@" finalize_command="$finalize_command @SYMFILE@" preload=yes fi case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test "$dlself" = no; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test "$prev" = dlprefiles; then dlself=yes elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test "$prev" = dlfiles; then dlfiles="$dlfiles $arg" else dlprefiles="$dlprefiles $arg" fi prev= continue ;; esac ;; expsyms) export_symbols="$arg" if test ! -f "$arg"; then $echo "$modename: symbol file \`$arg' does not exist" exit 1 fi prev= continue ;; expsyms_regex) export_symbols_regex="$arg" prev= continue ;; inst_prefix) inst_prefix_dir="$arg" prev= continue ;; release) release="-$arg" prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat $save_arg` do # moreargs="$moreargs $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit 1 fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit 1 else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi done else $echo "$modename: link input file \`$save_arg' does not exist" exit 1 fi arg=$save_arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac if test "$prev" = rpath; then case "$rpath " in *" $arg "*) ;; *) rpath="$rpath $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) xrpath="$xrpath $arg" ;; esac fi prev= continue ;; xcompiler) compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; xlinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $wl$qarg" prev= compile_command="$compile_command $wl$qarg" finalize_command="$finalize_command $wl$qarg" continue ;; xcclinker) linker_flags="$linker_flags $qarg" compiler_flags="$compiler_flags $qarg" prev= compile_command="$compile_command $qarg" finalize_command="$finalize_command $qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg="$arg" case $arg in -all-static) if test -n "$link_static_flag"; then compile_command="$compile_command $link_static_flag" finalize_command="$finalize_command $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 continue ;; -avoid-version) avoid_version=yes continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: more than one -exported-symbols argument is not allowed" exit 1 fi if test "X$arg" = "X-export-symbols"; then prev=expsyms else prev=expsyms_regex fi continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" ;; esac continue ;; -L*) dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 exit 1 fi dir="$absdir" ;; esac case "$deplibs " in *" -L$dir "*) ;; *) deplibs="$deplibs -L$dir" lib_search_path="$lib_search_path $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$dir:"*) ;; *) dllsearchpath="$dllsearchpath:$dir";; esac ;; esac continue ;; -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in *-*-cygwin* | *-*-pw32* | *-*-beos*) # These systems don't actually have a C or math library (as such) continue ;; *-*-mingw* | *-*-os2*) # These systems don't actually have a C library (as such) test "X$arg" = "X-lc" && continue ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework deplibs="$deplibs -framework System" continue esac elif test "X$arg" = "X-lc_r"; then case $host in *-*-openbsd* | *-*-freebsd*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi deplibs="$deplibs $arg" continue ;; -module) module=yes continue ;; # gcc -m* arguments should be passed to the linker via $compiler_flags # in order to pass architecture information to the linker # (e.g. 32 vs 64-bit). This may also be accomplished via -Wl,-mfoo # but this is not reliable with gcc because gcc may use -mfoo to # select a different linker, different libraries, etc, while # -Wl,-mfoo simply passes -mfoo to the linker. -m*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" if test "$with_gcc" = "yes" ; then compiler_flags="$compiler_flags $arg" fi continue ;; -shrext) prev=shrext continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) # The PATH hackery in wrapper scripts is required on Windows # in order for the loader to find any dlls it needs. $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -o) prev=output ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) $echo "$modename: only absolute run-paths are allowed" 1>&2 exit 1 ;; esac case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac continue ;; -static) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -Wc,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Wl,*) args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` arg= save_ifs="$IFS"; IFS=',' for flag in $args; do IFS="$save_ifs" case $flag in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") flag="\"$flag\"" ;; esac arg="$arg $wl$flag" compiler_flags="$compiler_flags $wl$flag" linker_flags="$linker_flags $flag" done IFS="$save_ifs" arg=`$echo "X$arg" | $Xsed -e "s/^ //"` ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # Some other compiler flag. -* | +*) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; *.$objext) # A standard object. objs="$objs $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then pic_object= non_pic_object= # Read the .lo file # If there is no directory component, then add one. case $arg in */* | *\\*) . $arg ;; *) . ./$arg ;; esac if test -z "$pic_object" || \ test -z "$non_pic_object" || test "$pic_object" = none && \ test "$non_pic_object" = none; then $echo "$modename: cannot find name of object for \`$arg'" 1>&2 exit 1 fi # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi if test "$pic_object" != none; then # Prepend the subdirectory the object is found in. pic_object="$xdir$pic_object" if test "$prev" = dlfiles; then if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then dlfiles="$dlfiles $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test "$prev" = dlprefiles; then # Preload the old-style object. dlprefiles="$dlprefiles $pic_object" prev= fi # A PIC object. libobjs="$libobjs $pic_object" arg="$pic_object" fi # Non-PIC object. if test "$non_pic_object" != none; then # Prepend the subdirectory the object is found in. non_pic_object="$xdir$non_pic_object" # A standard non-PIC object non_pic_objects="$non_pic_objects $non_pic_object" if test -z "$pic_object" || test "$pic_object" = none ; then arg="$non_pic_object" fi fi else # Only an error if not doing a dry-run. if test -z "$run"; then $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 exit 1 else # Dry-run case. # Extract subdirectory from the argument. xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` if test "X$xdir" = "X$arg"; then xdir= else xdir="$xdir/" fi pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` libobjs="$libobjs $pic_object" non_pic_objects="$non_pic_objects $non_pic_object" fi fi ;; *.$libext) # An archive. deplibs="$deplibs $arg" old_deplibs="$old_deplibs $arg" continue ;; *.la) # A libtool-controlled library. if test "$prev" = dlfiles; then # This library was specified with -dlopen. dlfiles="$dlfiles $arg" prev= elif test "$prev" = dlprefiles; then # The library was specified with -dlpreopen. dlprefiles="$dlprefiles $arg" prev= else deplibs="$deplibs $arg" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") arg="\"$arg\"" ;; esac ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi done # argument parsing loop if test -n "$prev"; then $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base link # command doesn't match the default compiler. if test -n "$available_tags" && test -z "$tagname"; then case $base_compile in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$0" > /dev/null; then # Evaluate the configuration. eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $0`" case $base_compile in "$CC "* | " $CC "* | "`$echo $CC` "* | " `$echo $CC` "*) # The compiler in $compile_command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then $echo "$modename: unable to infer tagged configuration" $echo "$modename: specify a tag with \`--tag'" 1>&2 exit 1 # else # $echo "$modename: using $tagname tagged configuration" fi ;; esac fi if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" compile_command="$compile_command $arg" finalize_command="$finalize_command $arg" fi oldlibs= # calculate the name of the file, without its directory outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` libobjs_save="$libobjs" if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` if test "X$output_objdir" = "X$output"; then output_objdir="$objdir" else output_objdir="$output_objdir/$objdir" fi # Create the object directory. if test ! -d "$output_objdir"; then $show "$mkdir $output_objdir" $run $mkdir $output_objdir status=$? if test "$status" -ne 0 && test ! -d "$output_objdir"; then exit $status fi fi # Determine the type of output case $output in "") $echo "$modename: you must specify an output file" 1>&2 $echo "$help" 1>&2 exit 1 ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac case $host in *cygwin* | *mingw* | *pw32*) # don't eliminate duplcations in $postdeps and $predeps duplicate_compiler_generated_deps=yes ;; *) duplicate_compiler_generated_deps=$duplicate_deps ;; esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if test "X$duplicate_deps" = "Xyes" ; then case "$libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi libs="$libs $deplib" done if test "$linkmode" = lib; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; esac pre_post_deps="$pre_post_deps $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 exit 1 ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=no newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan"; then libs="$deplibs" deplibs= fi if test "$linkmode" = prog; then case $pass in dlopen) libs="$dlfiles" ;; dlpreopen) libs="$dlprefiles" ;; link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; esac fi if test "$pass" = dlopen; then # Collect dlpreopened libraries save_deplibs="$deplibs" deplibs= fi for deplib in $libs; do lib= found=no case $deplib in -l*) if test "$linkmode" != lib && test "$linkmode" != prog; then $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 continue fi if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do for search_ext in .la $shrext .so .a; do # Search the libtool library lib="$searchdir/lib${name}${search_ext}" if test -f "$lib"; then if test "$search_ext" = ".la"; then found=yes else found=no fi break 2 fi done done if test "$found" != yes; then # deplib doesn't seem to be a libtool library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue else # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $deplib "*) if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then library_names= old_library= case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac for l in $old_library $library_names; do ll="$l" done if test "X$ll" = "X$old_library" ; then # only static version available found=no ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." lib=$ladir/$old_library if test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi fi ;; # -l -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test "$pass" = conv && continue newdependency_libs="$deplib $newdependency_libs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` ;; prog) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi if test "$pass" = scan; then deplibs="$deplib $deplibs" newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi ;; *) $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 ;; esac # linkmode continue ;; # -L -R*) if test "$pass" = link; then dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) xrpath="$xrpath $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) lib="$deplib" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) if test "$deplibs_check_method" != pass_all; then $echo $echo "*** Warning: Trying to link with static lib archive $deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because the file extensions .$libext of this argument makes me believe" $echo "*** that it is just a static archive that I should not used here." else $echo $echo "*** Warning: Linking the shared library $output against the" $echo "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" fi continue ;; prog) if test "$pass" != link; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test "$pass" = conv; then deplibs="$deplib $deplibs" elif test "$linkmode" = prog; then if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlopen support or we're linking statically, # we need to preload. newdlprefiles="$newdlprefiles $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else newdlfiles="$newdlfiles $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=yes continue ;; esac # case $deplib if test "$found" = yes || test -f "$lib"; then : else $echo "$modename: cannot find the library \`$lib'" 1>&2 exit 1 fi # Check to see that this really is a libtool archive. if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` test "X$ladir" = "X$lib" && ladir="." dlname= dlopen= dlpreopen= libdir= library_names= old_library= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no # Read the .la file case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then test -n "$dlopen" && dlfiles="$dlfiles $dlopen" test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" fi if test "$pass" = conv; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # It is a libtool convenience library, so add in its objects. convenience="$convenience $ladir/$objdir/$old_library" old_convenience="$old_convenience $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done elif test "$linkmode" != prog && test "$linkmode" != lib; then $echo "$modename: \`$lib' is not a convenience library" 1>&2 exit 1 fi continue fi # $pass = conv # Get the name of the library we link against. linklib= for l in $old_library $library_names; do linklib="$l" done if test -z "$linklib"; then $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 exit 1 fi # This library was specified with -dlopen. if test "$pass" = dlopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 exit 1 fi if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. dlprefiles="$dlprefiles $lib $dependency_libs" else newdlfiles="$newdlfiles $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 abs_ladir="$ladir" fi ;; esac laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` # Find the relevant object directory and library name. if test "X$installed" = Xyes; then if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then $echo "$modename: warning: library \`$lib' was moved." 1>&2 dir="$ladir" absdir="$abs_ladir" libdir="$abs_ladir" else dir="$libdir" absdir="$libdir" fi else dir="$ladir/$objdir" absdir="$abs_ladir/$objdir" # Remove this search path later notinst_path="$notinst_path $abs_ladir" fi # $installed = yes name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` # This library was specified with -dlpreopen. if test "$pass" = dlpreopen; then if test -z "$libdir"; then $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 exit 1 fi # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then newdlprefiles="$newdlprefiles $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then newdlprefiles="$newdlprefiles $dir/$dlname" else newdlprefiles="$newdlprefiles $dir/$linklib" fi fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test "$linkmode" = lib; then deplibs="$dir/$old_library $deplibs" elif test "$linkmode,$pass" = "prog,link"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test "$linkmode" = prog && test "$pass" != link; then newlib_search_path="$newlib_search_path $ladir" deplibs="$lib $deplibs" linkalldeplibs=no if test "$link_all_deplibs" != no || test -z "$library_names" || test "$build_libtool_libs" = no; then linkalldeplibs=yes fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test esac # Need to link against all dependency_libs? if test "$linkalldeplibs" = yes; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done # for deplib continue fi # $linkmode = prog... if test "$linkmode,$pass" = "prog,link"; then if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var"; then # Make sure the rpath contains only unique directories. case "$temp_rpath " in *" $dir "*) ;; *" $absdir "*) ;; *) temp_rpath="$temp_rpath $dir" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi # $linkmode,$pass = prog,link... if test "$alldeplibs" = yes && { test "$deplibs_check_method" = pass_all || { test "$build_libtool_libs" = yes && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically if test -n "$library_names" && { test "$prefer_static_libs" = no || test -z "$old_library"; }; then if test "$installed" = no; then notinst_deplibs="$notinst_deplibs $lib" need_relink=yes fi # This is a shared library # Warn about portability, can't link against -module's on some systems (darwin) if test "$shouldnotlink" = yes && test "$pass" = link ; then $echo if test "$linkmode" = prog; then $echo "*** Warning: Linking the executable $output against the loadable module" else $echo "*** Warning: Linking the shared library $output against the loadable module" fi $echo "*** $linklib is not portable!" fi if test "$linkmode" = lib && test "$hardcode_into_libs" = yes; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) compile_rpath="$compile_rpath $absdir" esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names realname="$2" shift; shift libname=`eval \\$echo \"$libname_spec\"` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname="$dlname" elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw*) major=`expr $current - $age` versuffix="-$major" ;; esac eval soname=\"$soname_spec\" else soname="$realname" fi # Make a new name for the extract_expsyms_cmds to use soroot="$soname" soname=`$echo $soroot | ${SED} -e 's/^.*\///'` newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else $show "extracting exported symbol list from \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$extract_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else $show "generating import library for \`$soname'" save_ifs="$IFS"; IFS='~' eval cmds=\"$old_archive_from_expsyms_cmds\" for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test "$linkmode" = prog || test "$mode" != relink; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test "$hardcode_direct" = no; then add="$dir/$linklib" case $host in *-*-sco3.2v5* ) add_dir="-L$dir" ;; *-*-darwin* ) # if the lib is a module then we can not link against it, someone # is ignoring the new warnings I added if /usr/bin/file -L $add 2> /dev/null | grep "bundle" >/dev/null ; then $echo "** Warning, lib $linklib is a module, not a shared library" if test -z "$old_library" ; then $echo $echo "** And there doesn't seem to be a static archive available" $echo "** The link will probably fail, sorry" else add="$dir/$old_library" fi fi esac elif test "$hardcode_minus_L" = no; then case $host in *-*-sunos*) add_shlibpath="$dir" ;; esac add_dir="-L$dir" add="-l$name" elif test "$hardcode_shlibpath_var" = no; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; relink) if test "$hardcode_direct" = yes; then add="$dir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$dir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case "$libdir" in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then add_shlibpath="$dir" add="-l$name" else lib_linked=no fi ;; *) lib_linked=no ;; esac if test "$lib_linked" != yes; then $echo "$modename: configuration error: unsupported hardcode properties" exit 1 fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; esac fi if test "$linkmode" = prog; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test "$hardcode_direct" != yes && \ test "$hardcode_minus_L" != yes && \ test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac fi fi fi if test "$linkmode" = prog || test "$mode" = relink; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test "$hardcode_direct" = yes; then add="$libdir/$linklib" elif test "$hardcode_minus_L" = yes; then add_dir="-L$libdir" add="-l$name" elif test "$hardcode_shlibpath_var" = yes; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; esac add="-l$name" elif test "$hardcode_automatic" = yes; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib" ; then add="$inst_prefix_dir$libdir/$linklib" else add="$libdir/$linklib" fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir="-L$libdir" # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case "$libdir" in [\\/]*) add_dir="$add_dir -L$inst_prefix_dir$libdir" ;; esac fi add="-l$name" fi if test "$linkmode" = prog; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test "$linkmode" = prog; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test "$hardcode_direct" != unsupported; then test -n "$old_library" && linklib="$old_library" compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test "$build_libtool_libs" = yes; then # Not a shared library if test "$deplibs_check_method" != pass_all; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. $echo $echo "*** Warning: This system can not link to static lib archive $lib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then $echo "*** But as you try to build a module library, libtool will still create " $echo "*** a static module, that should work as long as the dlopening application" $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else convenience="$convenience $dir/$old_library" old_convenience="$old_convenience $dir/$old_library" deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test "$linkmode" = lib; then if test -n "$dependency_libs" && { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || test "$link_static" = yes; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` case " $xrpath " in *" $temp_xrpath "*) ;; *) xrpath="$xrpath $temp_xrpath";; esac;; *) temp_deplibs="$temp_deplibs $libdir";; esac done dependency_libs="$temp_deplibs" fi newlib_search_path="$newlib_search_path $absdir" # Link against this library test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" if test "X$duplicate_deps" = "Xyes" ; then case "$tmp_libs " in *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; esac fi tmp_libs="$tmp_libs $deplib" done if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do case $deplib in -L*) path="$deplib" ;; *.la) dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$deplib" && dir="." # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 absdir="$dir" fi ;; esac if grep "^installed=no" $deplib > /dev/null; then path="$absdir/$objdir" else eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi if test "$absdir" != "$libdir"; then $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 fi path="$absdir" fi depdepl= case $host in *-*-darwin*) # we do not want to link against static libs, but need to link against shared eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names" ; then for tmp in $deplibrary_names ; do depdepl=$tmp done if test -f "$path/$depdepl" ; then depdepl="$path/$depdepl" fi # do not add paths which are already there case " $newlib_search_path " in *" $path "*) ;; *) newlib_search_path="$newlib_search_path $path";; esac path="" fi ;; *) path="-L$path" ;; esac ;; -l*) case $host in *-*-darwin*) # Again, we only want to link against shared libraries eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` for tmp in $newlib_search_path ; do if test -f "$tmp/lib$tmp_libs.dylib" ; then eval depdepl="$tmp/lib$tmp_libs.dylib" break fi done path="" ;; *) continue ;; esac ;; *) continue ;; esac case " $deplibs " in *" $depdepl "*) ;; *) deplibs="$deplibs $depdepl" ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$deplibs $path" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs dependency_libs="$newdependency_libs" if test "$pass" = dlpreopen; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test "$pass" != dlopen; then if test "$pass" != conv; then # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) lib_search_path="$lib_search_path $dir" ;; esac done newlib_search_path= fi if test "$linkmode,$pass" != "prog,link"; then vars="deplibs" else vars="compile_deplibs finalize_deplibs" fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) tmp_libs="$tmp_libs $deplib" ;; esac ;; *) tmp_libs="$tmp_libs $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Last step: remove runtime libs from dependency_libs (they stay in deplibs) tmp_libs= for i in $dependency_libs ; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i="" ;; esac if test -n "$i" ; then tmp_libs="$tmp_libs $i" fi done dependency_libs=$tmp_libs done # for pass if test "$linkmode" = prog; then dlfiles="$newdlfiles" dlprefiles="$newdlprefiles" fi case $linkmode in oldlib) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 fi if test -n "$export_symbols" || test -n "$export_symbols_regex"; then $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 fi # Now set the variables for building old libraries. build_libtool_libs=no oldlibs="$output" objs="$objs$old_deplibs" ;; lib) # Make sure we only generate libraries of the form `libNAME.la'. case $outputname in lib*) name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` eval shared_ext=\"$shrext\" eval libname=\"$libname_spec\" ;; *) if test "$module" = no; then $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 $echo "$help" 1>&2 exit 1 fi if test "$need_lib_prefix" != no; then # Add the "lib" prefix for modules if required name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` eval shared_ext=\"$shrext\" eval libname=\"$libname_spec\" else libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` fi ;; esac if test -n "$objs"; then if test "$deplibs_check_method" != pass_all; then $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 exit 1 else $echo $echo "*** Warning: Linking the shared library $output against the non-libtool" $echo "*** objects $objs is not portable!" libobjs="$libobjs $objs" fi fi if test "$dlself" != no; then $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 fi set dummy $rpath if test "$#" -gt 2; then $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 fi install_libdir="$2" oldlibs= if test -z "$rpath"; then if test "$build_libtool_libs" = yes; then # Building a libtool convenience library. # Some compilers have problems with a `.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 fi else # Parse the version information argument. save_ifs="$IFS"; IFS=':' set dummy $vinfo 0 0 0 IFS="$save_ifs" if test -n "$8"; then $echo "$modename: too many parameters to \`-version-info'" 1>&2 $echo "$help" 1>&2 exit 1 fi # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major="$2" number_minor="$3" number_revision="$4" # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # which has an extra 1 added just for fun # case $version_type in darwin|linux|osf|windows) current=`expr $number_major + $number_minor` age="$number_minor" revision="$number_revision" ;; freebsd-aout|freebsd-elf|sunos) current="$number_major" revision="$number_minor" age="0" ;; irix|nonstopux) current=`expr $number_major + $number_minor - 1` age="$number_minor" revision="$number_minor" ;; esac ;; no) current="$2" revision="$3" age="$4" ;; esac # Check that each of the things are valid numbers. case $current in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $revision in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac case $age in 0 | [1-9] | [1-9][0-9] | [1-9][0-9][0-9]) ;; *) $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 ;; esac if test "$age" -gt "$current"; then $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 $echo "$modename: \`$vinfo' is not valid version information" 1>&2 exit 1 fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header major=.`expr $current - $age` versuffix="$major.$age.$revision" # Darwin ld doesn't like 0 for these options... minor_current=`expr $current + 1` verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; freebsd-aout) major=".$current" versuffix=".$current.$revision"; ;; freebsd-elf) major=".$current" versuffix=".$current"; ;; irix | nonstopux) major=`expr $current - $age + 1` case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring="$verstring_prefix$major.$revision" # Add in all the interfaces that we are compatible with. loop=$revision while test "$loop" -ne 0; do iface=`expr $revision - $loop` loop=`expr $loop - 1` verstring="$verstring_prefix$major.$iface:$verstring" done # Before this point, $major must not contain `.'. major=.$major versuffix="$major.$revision" ;; linux) major=.`expr $current - $age` versuffix="$major.$age.$revision" ;; osf) major=.`expr $current - $age` versuffix=".$current.$age.$revision" verstring="$current.$age.$revision" # Add in all the interfaces that we are compatible with. loop=$age while test "$loop" -ne 0; do iface=`expr $current - $loop` loop=`expr $loop - 1` verstring="$verstring:${iface}.0" done # Make executables depend on our current version. verstring="$verstring:${current}.0" ;; sunos) major=".$current" versuffix=".$current.$revision" ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 filesystems. major=`expr $current - $age` versuffix="-$major" ;; *) $echo "$modename: unknown library version type \`$version_type'" 1>&2 $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 exit 1 ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring="0.0" ;; esac if test "$need_version" = no; then versuffix= else versuffix=".0.0" fi fi # Remove version info from name if versioning should be avoided if test "$avoid_version" = yes && test "$need_version" = no; then major= versuffix= verstring="" fi # Check to see if the archive will have undefined symbols. if test "$allow_undefined" = yes; then if test "$allow_undefined_flag" = unsupported; then $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 build_libtool_libs=no build_old_libs=yes fi else # Don't allow undefined symbols. allow_undefined_flag="$no_undefined_flag" fi fi if test "$mode" != relink; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$echo "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) removelist="$removelist $p" ;; *) ;; esac done if test -n "$removelist"; then $show "${rm}r $removelist" $run ${rm}r $removelist fi fi # Now set the variables for building old libraries. if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` fi # Eliminate all temporary directories. for path in $notinst_path; do lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'` deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'` dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'` done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do temp_xrpath="$temp_xrpath -R$libdir" case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles="$dlfiles" dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) dlfiles="$dlfiles $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles="$dlprefiles" dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) dlprefiles="$dlprefiles $lib" ;; esac done if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework deplibs="$deplibs -framework System" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd*) # Do not include libc due to us having libc/libc_r. test "X$arg" = "X-lc" && continue ;; *) # Add libc to deplibs on all other systems if necessary. if test "$build_libtool_need_lc" = "yes"; then deplibs="$deplibs -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release="" versuffix="" major="" newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $rm conftest.c cat > conftest.c </dev/null` for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null \ | grep " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib="$potent_lib" while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$file_magic_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for file magic test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a file magic. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` for a_deplib in $deplibs; do name="`expr $a_deplib : '-l\(.*\)'`" # If $name is empty we are operating on a -L argument. if test -n "$name" && test "$name" != "0"; then if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then case " $predeps $postdeps " in *" $a_deplib "*) newdeplibs="$newdeplibs $a_deplib" a_deplib="" ;; esac fi if test -n "$a_deplib" ; then libname=`eval \\$echo \"$libname_spec\"` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test if eval $echo \"$potent_lib\" 2>/dev/null \ | ${SED} 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" break 2 fi done done fi if test -n "$a_deplib" ; then droppeddeps=yes $echo $echo "*** Warning: linker path does not have real file for library $a_deplib." $echo "*** I have the capability to make that library automatically link in when" $echo "*** you link to this library. But I can only do this if you have a" $echo "*** shared version of the library, which you do not appear to have" $echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $echo "*** with $libname but no candidates were found. (...for regex pattern test)" else $echo "*** with $libname and none of the candidates passed a file format test" $echo "*** using a regex pattern. Last file checked: $potlib" fi fi else # Add a -L argument. newdeplibs="$newdeplibs $a_deplib" fi done # Gone through all deplibs. ;; none | unknown | *) newdeplibs="" tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ -e 's/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` done fi if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ | grep . >/dev/null; then $echo if test "X$deplibs_check_method" = "Xnone"; then $echo "*** Warning: inter-library dependencies are not supported in this platform." else $echo "*** Warning: inter-library dependencies are not known to be supported." fi $echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes fi ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then $echo $echo "*** Warning: libtool could not satisfy all declared inter-library" $echo "*** dependencies of module $libname. Therefore, libtool will create" $echo "*** a static module, that should work as long as the dlopening" $echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then $echo $echo "*** However, this would only work if libtool was able to extract symbol" $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" $echo "*** not find such a program. So, this module is probably useless." $echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else $echo "*** The inter-library dependencies that have been dropped here will be" $echo "*** automatically added whenever a program is linked with this library" $echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then $echo $echo "*** Since this library must not contain undefined symbols," $echo "*** because either the platform does not support them or" $echo "*** it was explicitly requested with -no-undefined," $echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test "$build_libtool_libs" = yes; then if test "$hardcode_into_libs" = yes; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath="$finalize_rpath" test "$mode" != relink && rpath="$compile_rpath$rpath" for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" dep_rpath="$dep_rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" if test -n "$hardcode_libdir_flag_spec_ld"; then eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" else eval dep_rpath=\"$hardcode_libdir_flag_spec\" fi fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath="$finalize_shlibpath" test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext\" eval library_names=\"$library_names_spec\" set dummy $library_names realname="$2" shift; shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname="$realname" fi if test -z "$dlname"; then dlname=$soname fi lib="$output_objdir/$realname" for link do linknames="$linknames $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` # Prepare the list of exported symbols if test -z "$export_symbols"; then if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols eval cmds=\"$export_symbols_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" if len=`expr "X$cmd" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then $show "$cmd" $run eval "$cmd" || exit $? skipped_export=false else # The command line is too long to execute in one step. $show "using reloadable object file for export list..." skipped_export=: fi done IFS="$save_ifs" if test -n "$export_symbols_regex"; then $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' $show "$mv \"${export_symbols}T\" \"$export_symbols\"" $run eval '$mv "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) tmp_deplibs="$tmp_deplibs $test_deplib" ;; esac done deplibs="$tmp_deplibs" if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" else gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" status=$? if test "$status" -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "$mkdir $xdir" $run $mkdir "$xdir" status=$? if test "$status" -ne 0 && test ! -d "$xdir"; then exit $status fi # We will extract separately just the conflicting names and we will no # longer touch any unique names. It is faster to leave these extract # automatically by $AR in one run. $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 $AR t "$xabs" | sort | uniq -cd | while read -r count name do i=1 while test "$i" -le "$count" do # Put our $i before any first dot (extension) # Never overwrite any file name_to="$name" while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" do name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` done $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? i=`expr $i + 1` done done fi libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done fi fi if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" linker_flags="$linker_flags $flag" fi # Make a backup of the uninstalled library when relinking if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test "$module" = yes && test -n "$module_cmds" ; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval cmds=\"$module_expsym_cmds\" else eval cmds=\"$module_cmds\" fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi fi if test "X$skipped_export" != "X:" && len=`expr "X$cmds" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise. $echo "creating reloadable object files..." # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= delfiles= last_robj= k=1 output=$output_objdir/$save_output-${k}.$objext # Loop over the list of objects to be linked. for obj in $save_libobjs do eval test_cmds=\"$reload_cmds $objlist $last_robj\" if test "X$objlist" = X || { len=`expr "X$test_cmds" : ".*"` && test "$len" -le "$max_cmd_len"; }; then objlist="$objlist $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. eval concat_cmds=\"$reload_cmds $objlist $last_robj\" else # All subsequent reloadable object files will link in # the last one created. eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" fi last_robj=$output_objdir/$save_output-${k}.$objext k=`expr $k + 1` output=$output_objdir/$save_output-${k}.$objext objlist=$obj len=1 fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" if ${skipped_export-false}; then $show "generating symbol list for \`$libname.la'" export_symbols="$output_objdir/$libname.exp" $run $rm $export_symbols libobjs=$output # Append the command to create the export file. eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" fi # Set up a command to remove the reloadale object files # after they are used. i=0 while test "$i" -lt "$k" do i=`expr $i + 1` delfiles="$delfiles $output_objdir/$save_output-${i}.$objext" done $echo "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs="$IFS"; IFS='~' for cmd in $concat_cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval cmds=\"$archive_expsym_cmds\" else eval cmds=\"$archive_cmds\" fi # Append the command to remove the reloadable object files # to the just-reset $cmds. eval cmds=\"\$cmds~$rm $delfiles\" fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Restore the uninstalled library and exit if test "$mode" = relink; then $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? exit 0 fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? fi done # If -module or -export-dynamic was specified, set the dlname. if test "$module" = yes || test "$export_dynamic" = yes; then # On all known operating systems, these are identical. dlname="$soname" fi fi ;; obj) if test -n "$deplibs"; then $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 fi if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 fi if test -n "$rpath"; then $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 fi if test -n "$xrpath"; then $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 fi if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 fi case $output in *.lo) if test -n "$objs$old_deplibs"; then $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 exit 1 fi libobj="$output" obj=`$echo "X$output" | $Xsed -e "$lo2o"` ;; *) libobj= obj="$output" ;; esac # Delete the old objects. $run $rm $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # reload_cmds runs $LD directly, so let us get rid of # -Wl from whole_archive_flag_spec wl= if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" else gentop="$output_objdir/${obj}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" status=$? if test "$status" -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" for xlib in $convenience; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "$mkdir $xdir" $run $mkdir "$xdir" status=$? if test "$status" -ne 0 && test ! -d "$xdir"; then exit $status fi # We will extract separately just the conflicting names and we will no # longer touch any unique names. It is faster to leave these extract # automatically by $AR in one run. $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 $AR t "$xabs" | sort | uniq -cd | while read -r count name do i=1 while test "$i" -le "$count" do # Put our $i before any first dot (extension) # Never overwrite any file name_to="$name" while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" do name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` done $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? i=`expr $i + 1` done done fi reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` done fi fi # Create the old-style object. reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 fi if test "$build_libtool_libs" != yes; then if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $run eval "echo timestamp > $libobj" || exit $? exit 0 fi if test -n "$pic_flag" || test "$pic_mode" != default; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output="$libobj" eval cmds=\"$reload_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi if test -n "$gentop"; then $show "${rm}r $gentop" $run ${rm}r $gentop fi exit 0 ;; prog) case $host in *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; esac if test -n "$vinfo"; then $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 fi if test -n "$release"; then $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 fi if test "$preload" = yes; then if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && test "$dlopen_self_static" = unknown; then $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." fi fi case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` ;; esac case $host in *darwin*) # Don't allow lazy linking, it breaks C++ global constructors if test "$tagname" = CXX ; then compile_command="$compile_command ${wl}-bind_at_load" finalize_command="$finalize_command ${wl}-bind_at_load" fi ;; esac compile_command="$compile_command $compile_deplibs" finalize_command="$finalize_command $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) finalize_rpath="$finalize_rpath $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) perm_rpath="$perm_rpath $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) case :$dllsearchpath: in *":$libdir:"*) ;; *) dllsearchpath="$dllsearchpath:$libdir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath="$rpath" rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs="$libdir" else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" rpath="$rpath $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir="$hardcode_libdirs" eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath="$rpath" if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` fi dlsyms= if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then if test -n "$NM" && test -n "$global_symbol_pipe"; then dlsyms="${outputname}S.c" else $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 fi fi if test -n "$dlsyms"; then case $dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist="$output_objdir/${outputname}.nm" $show "$rm $nlist ${nlist}S ${nlist}T" $run $rm "$nlist" "${nlist}S" "${nlist}T" # Parse the name list into a source file. $show "creating $output_objdir/$dlsyms" test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ /* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ /* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ #ifdef __cplusplus extern \"C\" { #endif /* Prevent the only kind of declaration conflicts we can make. */ #define lt_preloaded_symbols some_other_symbol /* External symbol declarations for the compiler. */\ " if test "$dlself" = yes; then $show "generating symbol list for \`$output'" test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` for arg in $progfiles; do $show "extracting global C symbols from \`$arg'" $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi if test -n "$export_symbols_regex"; then $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' $run eval '$mv "$nlist"T "$nlist"' fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols="$output_objdir/$output.exp" $run $rm $export_symbols $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' else $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' $run eval 'mv "$nlist"T "$nlist"' fi fi for arg in $dlprefiles; do $show "extracting global C symbols from \`$arg'" name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` $run eval '$echo ": $name " >> "$nlist"' $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" done if test -z "$run"; then # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $mv "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if grep -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else grep -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' else $echo '/* NONE */' >> "$output_objdir/$dlsyms" fi $echo >> "$output_objdir/$dlsyms" "\ #undef lt_preloaded_symbols #if defined (__STDC__) && __STDC__ # define lt_ptr void * #else # define lt_ptr char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr address; } lt_preloaded_symbols[] = {\ " eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" $echo >> "$output_objdir/$dlsyms" "\ {0, (lt_ptr) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " fi pic_flag_for_symtable= case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; esac;; *-*-hpux*) case "$compile_command " in *" -static "*) ;; *) pic_flag_for_symtable=" $pic_flag";; esac esac # Now compile the dynamic symbol file. $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? # Clean up the generated files. $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" # Transform the symbol file into the correct name. compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` ;; *) $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 exit 1 ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` fi if test "$need_relink" = no || test "$build_libtool_libs" != yes; then # Replace the output file specification. compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. $show "$link_command" $run eval "$link_command" status=$? # Delete the generated files. if test -n "$dlsyms"; then $show "$rm $output_objdir/${outputname}S.${objext}" $run $rm "$output_objdir/${outputname}S.${objext}" fi exit $status fi if test -n "$shlibpath_var"; then # We should set the shlibpath_var rpath= for dir in $temp_rpath; do case $dir in [\\/]* | [A-Za-z]:[\\/]*) # Absolute path. rpath="$rpath$dir:" ;; *) # Relative path: add a thisdir entry. rpath="$rpath\$thisdir/$dir:" ;; esac done temp_rpath="$rpath" fi if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do rpath="$rpath$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do rpath="$rpath$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test "$no_install" = yes; then # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $run $rm $output # Link the executable and exit $show "$link_command" $run eval "$link_command" || exit $? exit 0 fi if test "$hardcode_action" = relink; then # Fast installation is not supported link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 $echo "$modename: \`$output' will be relinked during installation" 1>&2 else if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= fi else link_command="$compile_var$compile_command$compile_rpath" relink_command="$finalize_var$finalize_command$finalize_rpath" fi fi # Replace the output file specification. link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname $show "$link_command" $run eval "$link_command" || exit $? # Now create the wrapper script. $show "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` fi # Quote $echo for shipping. if test "X$echo" = "X$SHELL $0 --fallback-echo"; then case $0 in [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; *) qecho="$SHELL `pwd`/$0 --fallback-echo";; esac qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` else qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` fi # Only actually do things if our run command is non-null. if test -z "$run"; then # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) cwrappersource=`$echo ${objdir}/lt-${output}.c` cwrapper=`$echo ${output}.exe` $rm $cwrappersource $cwrapper trap "$rm $cwrappersource $cwrapper; exit 1" 1 2 15 cat > $cwrappersource <> $cwrappersource<<"EOF" #include #include #include #include #include #include #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef DIR_SEPARATOR #define DIR_SEPARATOR '/' #endif #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ defined (__OS2__) #define HAVE_DOS_BASED_FILE_SYSTEM #ifndef DIR_SEPARATOR_2 #define DIR_SEPARATOR_2 '\\' #endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free ((void *) stale); stale = 0; } \ } while (0) const char *program_name = NULL; void * xmalloc (size_t num); char * xstrdup (const char *string); char * basename (const char *name); char * fnqualify(const char *path); char * strendzap(char *str, const char *pat); void lt_fatal (const char *message, ...); int main (int argc, char *argv[]) { char **newargz; int i; program_name = (char *) xstrdup ((char *) basename (argv[0])); newargz = XMALLOC(char *, argc+2); EOF cat >> $cwrappersource <> $cwrappersource <<"EOF" newargz[1] = fnqualify(argv[0]); /* we know the script has the same name, without the .exe */ /* so make sure newargz[1] doesn't end in .exe */ strendzap(newargz[1],".exe"); for (i = 1; i < argc; i++) newargz[i+1] = xstrdup(argv[i]); newargz[argc+1] = NULL; EOF cat >> $cwrappersource <> $cwrappersource <<"EOF" } void * xmalloc (size_t num) { void * p = (void *) malloc (num); if (!p) lt_fatal ("Memory exhausted"); return p; } char * xstrdup (const char *string) { return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL ; } char * basename (const char *name) { const char *base; #if defined (HAVE_DOS_BASED_FILE_SYSTEM) /* Skip over the disk name in MSDOS pathnames. */ if (isalpha (name[0]) && name[1] == ':') name += 2; #endif for (base = name; *name; name++) if (IS_DIR_SEPARATOR (*name)) base = name + 1; return (char *) base; } char * fnqualify(const char *path) { size_t size; char *p; char tmp[LT_PATHMAX + 1]; assert(path != NULL); /* Is it qualified already? */ #if defined (HAVE_DOS_BASED_FILE_SYSTEM) if (isalpha (path[0]) && path[1] == ':') return xstrdup (path); #endif if (IS_DIR_SEPARATOR (path[0])) return xstrdup (path); /* prepend the current directory */ /* doesn't handle '~' */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal ("getcwd failed"); size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */ p = XMALLOC(char, size); sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path); return p; } char * strendzap(char *str, const char *pat) { size_t len, patlen; assert(str != NULL); assert(pat != NULL); len = strlen(str); patlen = strlen(pat); if (patlen <= len) { str += len - patlen; if (strcmp(str, pat) == 0) *str = '\0'; } return str; } static void lt_error_core (int exit_status, const char * mode, const char * message, va_list ap) { fprintf (stderr, "%s: %s: ", program_name, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, "FATAL", message, ap); va_end (ap); } EOF # we should really use a build-platform specific compiler # here, but OTOH, the wrappers (shell script and this C one) # are only useful if you want to execute the "real" binary. # Since the "real" binary is built for $host, then this # wrapper might as well be built for $host, too. $run $LTCC -s -o $cwrapper $cwrappersource ;; esac $rm $output trap "$rm $output; exit 1" 1 2 15 $echo > $output "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variable: notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$echo are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then echo=\"$qecho\" file=\"\$0\" # Make sure echo works. if test \"X\$1\" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then # Yippee, \$echo works! : else # Restart under the correct shell, and then maybe \$echo will work. exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} fi fi\ " $echo >> $output "\ # Find the directory that this script lives in. thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` done # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test "$fast_install" = yes; then $echo >> $output "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || \\ { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $mkdir \"\$progdir\" else $rm \"\$progdir/\$file\" fi" $echo >> $output "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else $echo \"\$relink_command_output\" >&2 $rm \"\$progdir/\$file\" exit 1 fi fi $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $rm \"\$progdir/\$program\"; $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } $rm \"\$progdir/\$file\" fi" else $echo >> $output "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $echo >> $output "\ if test -f \"\$progdir/\$program\"; then" # Export our shlibpath_var if we have one. if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $echo >> $output "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` export $shlibpath_var " fi # fixup the dll searchpath if we need to. if test -n "$dllsearchpath"; then $echo >> $output "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi $echo >> $output "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2*) $echo >> $output "\ exec \$progdir\\\\\$program \${1+\"\$@\"} " ;; *) $echo >> $output "\ exec \$progdir/\$program \${1+\"\$@\"} " ;; esac $echo >> $output "\ \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" exit 1 fi else # The program doesn't exist. \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 \$echo \"This script is just a wrapper for \$program.\" 1>&2 $echo \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " chmod +x $output fi exit 0 ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do if test "$build_libtool_libs" = convenience; then oldobjs="$libobjs_save" addlibs="$convenience" build_libtool_libs=no else if test "$build_libtool_libs" = module; then oldobjs="$libobjs_save" build_libtool_libs=no else oldobjs="$old_deplibs $non_pic_objects" fi addlibs="$old_convenience" fi if test -n "$addlibs"; then gentop="$output_objdir/${outputname}x" $show "${rm}r $gentop" $run ${rm}r "$gentop" $show "$mkdir $gentop" $run $mkdir "$gentop" status=$? if test "$status" -ne 0 && test ! -d "$gentop"; then exit $status fi generated="$generated $gentop" # Add in members from convenience archives. for xlib in $addlibs; do # Extract the objects. case $xlib in [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; *) xabs=`pwd`"/$xlib" ;; esac xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` xdir="$gentop/$xlib" $show "${rm}r $xdir" $run ${rm}r "$xdir" $show "$mkdir $xdir" $run $mkdir "$xdir" status=$? if test "$status" -ne 0 && test ! -d "$xdir"; then exit $status fi # We will extract separately just the conflicting names and we will no # longer touch any unique names. It is faster to leave these extract # automatically by $AR in one run. $show "(cd $xdir && $AR x $xabs)" $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; renaming object files" 1>&2 $echo "$modename: warning: to ensure that they will not overwrite" 1>&2 $AR t "$xabs" | sort | uniq -cd | while read -r count name do i=1 while test "$i" -le "$count" do # Put our $i before any first dot (extension) # Never overwrite any file name_to="$name" while test "X$name_to" = "X$name" || test -f "$xdir/$name_to" do name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"` done $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')" $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $? i=`expr $i + 1` done done fi oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` done fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then eval cmds=\"$old_archive_from_new_cmds\" else eval cmds=\"$old_archive_cmds\" if len=`expr "X$cmds" : ".*"` && test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # the command line is too long to link in one step, link in parts $echo "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs # GNU ar 2.10+ was changed to match POSIX; thus no paths are # encoded into archives. This makes 'ar r' malfunction in # this piecewise linking case whenever conflicting object # names appear in distinct ar calls; check, warn and compensate. if (for obj in $save_oldobjs do $echo "X$obj" | $Xsed -e 's%^.*/%%' done | sort | sort -uc >/dev/null 2>&1); then : else $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2 $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2 AR_FLAGS=cq fi # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done for obj in $save_oldobjs do oldobjs="$objlist $obj" objlist="$objlist $obj" eval test_cmds=\"$old_archive_cmds\" if len=`expr "X$test_cmds" : ".*"` && test "$len" -le "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj" ; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" objlist= fi done RANLIB=$save_RANLIB oldobjs=$objlist if test "X$oldobjs" = "X" ; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~$old_archive_cmds\" fi fi fi save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$generated"; then $show "${rm}r$generated" $run ${rm}r$generated fi # Now create the libtool archive. case $output in *.la) old_library= test "$build_old_libs" = yes && old_library="$libname.$libext" $show "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` relink_command="$var=\"$var_value\"; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi # Only create the output if not a dry run. if test -z "$run"; then for installed in no yes; do if test "$installed" = yes; then if test -z "$install_libdir"; then break fi output="$output_objdir/$outputname"i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit 1 fi newdependency_libs="$newdependency_libs $libdir/$name" ;; *) newdependency_libs="$newdependency_libs $deplib" ;; esac done dependency_libs="$newdependency_libs" newdlfiles= for lib in $dlfiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlfiles="$newdlfiles $libdir/$name" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` if test -z "$libdir"; then $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 exit 1 fi newdlprefiles="$newdlprefiles $libdir/$name" done dlprefiles="$newdlprefiles" else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlfiles="$newdlfiles $abs" done dlfiles="$newdlfiles" newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; *) abs=`pwd`"/$lib" ;; esac newdlprefiles="$newdlprefiles $abs" done dlprefiles="$newdlprefiles" fi $rm $output # place dlname in correct position for cygwin tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; esac $echo > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test "$installed" = no && test "$need_relink" = yes; then $echo >> $output "\ relink_command=\"$relink_command\"" fi done fi # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? ;; esac exit 0 ;; # libtool install mode install) modename="$modename: install" # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || # Allow the use of GNU shtool's install command. $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then # Aesthetically quote it. arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$arg " arg="$1" shift else install_prog= arg="$nonopt" fi # The real first argument should be the name of the installation program. # Aesthetically quote it. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog$arg" # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=no stripme= for arg do if test -n "$dest"; then files="$files $dest" dest="$arg" continue fi case $arg in -d) isdir=yes ;; -f) prev="-f" ;; -g) prev="-g" ;; -m) prev="-m" ;; -o) prev="-o" ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then prev= else dest="$arg" continue fi ;; esac # Aesthetically quote the argument. arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` case $arg in *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) arg="\"$arg\"" ;; esac install_prog="$install_prog $arg" done if test -z "$install_prog"; then $echo "$modename: you must specify an install program" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -n "$prev"; then $echo "$modename: the \`$prev' option requires an argument" 1>&2 $echo "$help" 1>&2 exit 1 fi if test -z "$files"; then if test -z "$dest"; then $echo "$modename: no file or destination specified" 1>&2 else $echo "$modename: you must specify a destination" 1>&2 fi $echo "$help" 1>&2 exit 1 fi # Strip any trailing slash from the destination. dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` # Check to see that the destination is a directory. test -d "$dest" && isdir=yes if test "$isdir" = yes; then destdir="$dest" destname= else destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` test "X$destdir" = "X$dest" && destdir=. destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` # Not a directory, so check to see that there is only one file specified. set dummy $files if test "$#" -gt 2; then $echo "$modename: \`$dest' is not a directory" 1>&2 $echo "$help" 1>&2 exit 1 fi fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. staticlibs="$staticlibs $file" ;; *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi library_names= old_library= relink_command= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) current_libdirs="$current_libdirs $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) future_libdirs="$future_libdirs $libdir" ;; esac fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ test "X$dir" = "X$file/" && dir= dir="$dir$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. if test "$inst_prefix_dir" = "$destdir"; then $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 exit 1 fi if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi $echo "$modename: warning: relinking \`$file'" 1>&2 $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 exit 1 fi fi # See the names of the shared library. set dummy $library_names if test -n "$2"; then realname="$2" shift shift srcname="$realname" test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. $show "$install_prog $dir/$srcname $destdir/$realname" $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$striplib $destdir/$realname" $run eval "$striplib $destdir/$realname" || exit $? fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. for linkname do if test "$linkname" != "$realname"; then $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" fi done fi # Do each command in the postinstall commands. lib="$destdir/$realname" eval cmds=\"$postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" fi # Install the pseudo-library for information purposes. name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` instname="$dir/$name"i $show "$install_prog $instname $destdir/$name" $run eval "$install_prog $instname $destdir/$name" || exit $? # Maybe install the static library, too. test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` ;; *.$objext) staticdest="$destfile" destfile= ;; *) $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac # Install the libtool object if requested. if test -n "$destfile"; then $show "$install_prog $file $destfile" $run eval "$install_prog $file $destfile" || exit $? fi # Install the old object if enabled. if test "$build_old_libs" = yes; then # Deduce the name of the old-style object file. staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` $show "$install_prog $staticobj $staticdest" $run eval "$install_prog \$staticobj \$staticdest" || exit $? fi exit 0 ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile="$destdir/$destname" else destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` destfile="$destdir/$destfile" fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext="" case $file in *.exe) if test ! -f "$file"; then file=`$echo $file|${SED} 's,.exe$,,'` stripped_ext=".exe" fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin*|*mingw*) wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` ;; *) wrapper=$file ;; esac if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then notinst_deplibs= relink_command= # To insure that "foo" is sourced, and not "foo.exe", # finese the cygwin/MSYS system by explicitly sourcing "foo." # which disallows the automatic-append-.exe behavior. case $build in *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; *) wrapperdot=${wrapper} ;; esac # If there is no directory component, then add one. case $file in */* | *\\*) . ${wrapperdot} ;; *) . ./${wrapperdot} ;; esac # Check the variables that should have been set. if test -z "$notinst_deplibs"; then $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 exit 1 fi finalize=yes for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then # If there is no directory component, then add one. case $lib in */* | *\\*) . $lib ;; *) . ./$lib ;; esac fi libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 finalize=no fi done relink_command= # To insure that "foo" is sourced, and not "foo.exe", # finese the cygwin/MSYS system by explicitly sourcing "foo." # which disallows the automatic-append-.exe behavior. case $build in *cygwin* | *mingw*) wrapperdot=${wrapper}. ;; *) wrapperdot=${wrapper} ;; esac # If there is no directory component, then add one. case $file in */* | *\\*) . ${wrapperdot} ;; *) . ./${wrapperdot} ;; esac outputname= if test "$fast_install" = no && test -n "$relink_command"; then if test "$finalize" = yes && test -z "$run"; then tmpdir="/tmp" test -n "$TMPDIR" && tmpdir="$TMPDIR" tmpdir="$tmpdir/libtool-$$" if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : else $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 continue fi file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` outputname="$tmpdir/$file" # Replace the output file specification. relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` $show "$relink_command" if $run eval "$relink_command"; then : else $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 ${rm}r "$tmpdir" continue fi file="$outputname" else $echo "$modename: warning: cannot relink \`$file'" 1>&2 fi else # Install the binary that we compiled earlier. file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyways case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` ;; esac ;; esac $show "$install_prog$stripme $file $destfile" $run eval "$install_prog\$stripme \$file \$destfile" || exit $? test -n "$outputname" && ${rm}r "$tmpdir" ;; esac done for file in $staticlibs; do name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` # Set up the ranlib parameters. oldlib="$destdir/$name" $show "$install_prog $file $oldlib" $run eval "$install_prog \$file \$oldlib" || exit $? if test -n "$stripme" && test -n "$striplib"; then $show "$old_striplib $oldlib" $run eval "$old_striplib $oldlib" || exit $? fi # Do each command in the postinstall commands. eval cmds=\"$old_postinstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || exit $? done IFS="$save_ifs" done if test -n "$future_libdirs"; then $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 fi if test -n "$current_libdirs"; then # Maybe just do a dry run. test -n "$run" && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL $0 --finish$current_libdirs' else exit 0 fi ;; # libtool finish mode finish) modename="$modename: finish" libdirs="$nonopt" admincmds= if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for dir do libdirs="$libdirs $dir" done for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. eval cmds=\"$finish_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" || admincmds="$admincmds $cmd" done IFS="$save_ifs" fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $run eval "$cmds" || admincmds="$admincmds $cmds" fi done fi # Exit here if they wanted silent mode. test "$show" = : && exit 0 $echo "----------------------------------------------------------------------" $echo "Libraries have been installed in:" for libdir in $libdirs; do $echo " $libdir" done $echo $echo "If you ever happen to want to link against installed libraries" $echo "in a given directory, LIBDIR, you must either use libtool, and" $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" $echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" $echo " during execution" fi if test -n "$runpath_var"; then $echo " - add LIBDIR to the \`$runpath_var' environment variable" $echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $echo " - use the \`$flag' linker flag" fi if test -n "$admincmds"; then $echo " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" fi $echo $echo "See any operating system documentation about shared libraries for" $echo "more information, such as the ld(1) and ld.so(8) manual pages." $echo "----------------------------------------------------------------------" exit 0 ;; # libtool execute mode execute) modename="$modename: execute" # The first argument is the command name. cmd="$nonopt" if test -z "$cmd"; then $echo "$modename: you must specify a COMMAND" 1>&2 $echo "$help" exit 1 fi # Handle -dlopen flags immediately. for file in $execute_dlfiles; do if test ! -f "$file"; then $echo "$modename: \`$file' is not a file" 1>&2 $echo "$help" 1>&2 exit 1 fi dir= case $file in *.la) # Check to see that this really is a libtool archive. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : else $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 $echo "$help" 1>&2 exit 1 fi # Read the libtool library. dlname= library_names= # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" continue fi dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. if test -f "$dir/$objdir/$dlname"; then dir="$dir/$objdir" else $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 exit 1 fi ;; *.lo) # Just add the directory containing the .lo file. dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` test "X$dir" = "X$file" && dir=. ;; *) $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir="$absdir" # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic="$magic" # Check if any of the arguments is a wrapper script. args= for file do case $file in -*) ;; *) # Do a test to see if this is really a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # If there is no directory component, then add one. case $file in */* | *\\*) . $file ;; *) . ./$file ;; esac # Transform arg to wrapped name. file="$progdir/$program" fi ;; esac # Quote arguments (to preserve shell metacharacters). file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` args="$args \"$file\"" done if test -z "$run"; then if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables if test "${save_LC_ALL+set}" = set; then LC_ALL="$save_LC_ALL"; export LC_ALL fi if test "${save_LANG+set}" = set; then LANG="$save_LANG"; export LANG fi # Now prepare to actually exec the command. exec_cmd="\$cmd$args" else # Display what would be done. if test -n "$shlibpath_var"; then eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" $echo "export $shlibpath_var" fi $echo "$cmd$args" exit 0 fi ;; # libtool clean and uninstall mode clean | uninstall) modename="$modename: $mode" rm="$nonopt" files= rmforce= exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic="$magic" for arg do case $arg in -f) rm="$rm $arg"; rmforce=yes ;; -*) rm="$rm $arg" ;; *) files="$files $arg" ;; esac done if test -z "$rm"; then $echo "$modename: you must specify an RM program" 1>&2 $echo "$help" 1>&2 exit 1 fi rmdirs= origobjdir="$objdir" for file in $files; do dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` if test "X$dir" = "X$file"; then dir=. objdir="$origobjdir" else objdir="$dir/$origobjdir" fi name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` test "$mode" = uninstall && objdir="$dir" # Remember objdir for removal later, being careful to avoid duplicates if test "$mode" = clean; then case " $rmdirs " in *" $objdir "*) ;; *) rmdirs="$rmdirs $objdir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if (test -L "$file") >/dev/null 2>&1 \ || (test -h "$file") >/dev/null 2>&1 \ || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif test "$rmforce" = yes; then continue fi rmfiles="$file" case $name in *.la) # Possibly a libtool archive, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then . $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do rmfiles="$rmfiles $objdir/$n" done test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" if test "$mode" = uninstall; then if test -n "$library_names"; then # Do each command in the postuninstall commands. eval cmds=\"$postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. eval cmds=\"$old_postuninstall_cmds\" save_ifs="$IFS"; IFS='~' for cmd in $cmds; do IFS="$save_ifs" $show "$cmd" $run eval "$cmd" if test "$?" -ne 0 && test "$rmforce" != yes; then exit_status=1 fi done IFS="$save_ifs" fi # FIXME: should reinstall the best remaining shared library. fi fi ;; *.lo) # Possibly a libtool object, so verify it. if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then # Read the .lo file . $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" \ && test "$pic_object" != none; then rmfiles="$rmfiles $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" \ && test "$non_pic_object" != none; then rmfiles="$rmfiles $dir/$non_pic_object" fi fi ;; *) if test "$mode" = clean ; then noexename=$name case $file in *.exe) file=`$echo $file|${SED} 's,.exe$,,'` noexename=`$echo $name|${SED} 's,.exe$,,'` # $file with .exe has already been added to rmfiles, # add $file without .exe rmfiles="$rmfiles $file" ;; esac # Do a test to see if this is a libtool program. if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then relink_command= . $dir/$noexename # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" if test "$fast_install" = yes && test -n "$relink_command"; then rmfiles="$rmfiles $objdir/lt-$name" fi if test "X$noexename" != "X$name" ; then rmfiles="$rmfiles $objdir/lt-${noexename}.c" fi fi fi ;; esac $show "$rm $rmfiles" $run $rm $rmfiles || exit_status=1 done objdir="$origobjdir" # Try to remove the ${objdir}s in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then $show "rmdir $dir" $run rmdir $dir >/dev/null 2>&1 fi done exit $exit_status ;; "") $echo "$modename: you must specify a MODE" 1>&2 $echo "$generic_help" 1>&2 exit 1 ;; esac if test -z "$exec_cmd"; then $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$generic_help" 1>&2 exit 1 fi fi # test -z "$show_help" if test -n "$exec_cmd"; then eval exec $exec_cmd exit 1 fi # We need to display help for each of the modes. case $mode in "") $echo \ "Usage: $modename [OPTION]... [MODE-ARG]... Provide generalized library-building support services. --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --finish same as \`--mode=finish' --help display this help message and exit --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] --quiet same as \`--silent' --silent don't print informational messages --tag=TAG use configuration variables from tag TAG --version print version information MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for a more detailed description of MODE. Report bugs to ." exit 0 ;; clean) $echo \ "Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $echo \ "Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -prefer-pic try to building PIC objects only -prefer-non-pic try to building non-PIC objects only -static always build a \`.o' file suitable for static linking COMPILE-COMMAND is a command to be used in creating a \`standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix \`.c' with the library object suffix, \`.lo'." ;; execute) $echo \ "Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to \`-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $echo \ "Usage: $modename [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the \`--dry-run' option if you just want to see what would be executed." ;; install) $echo \ "Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the \`install' or \`cp' program. The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $echo \ "Usage: $modename [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE Use a list of object files found in FILE to specify objects -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -static do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] All other options (arguments beginning with \`-') are ignored. Every other argument is treated as a filename. Files ending in \`.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in \`.la', then a libtool library is created, only library objects (\`.lo' files) may be specified, and \`-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created using \`ar' and \`ranlib', or on Windows using \`lib'. If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $echo \ "Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) $echo "$modename: invalid operation mode \`$mode'" 1>&2 $echo "$help" 1>&2 exit 1 ;; esac $echo $echo "Try \`$modename --help' for more information about other modes." exit 0 # The TAGs below are defined such that we never get into a situation # in which we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: bochs-2.6/bxversion.h.in0000644000175000017500000000051712020641507015132 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // This file is checked in as bxversion.h.in. The configure script // substitutes variables and creates bxversion.h. ///////////////////////////////////////////////////////////////////////// #define VER_STRING "@VER_STRING@" #define REL_STRING "@REL_STRING@" bochs-2.6/win32res.rc0000644000175000017500000001150112020641507014332 0ustar guillemguillem#define ISOLATION_AWARE_ENABLED #include #include "gui\win32res.h" ICON_BOCHS ICON build\win32\nsis\bochs.ico ICON_BOCHS2 ICON build\win32\nsis\logo.ico // Manifest for both 32-bit and 64-bit Windows 1 24 build\win32\bochs.manifest ASK_DLG DIALOG 30, 30, 200, 100 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Event" FONT 8, "Helv" BEGIN LTEXT "Device", IDASKTX1, 10, 12, 40, 14 EDITTEXT IDASKDEV, 45, 10, 145, 14, ES_READONLY LTEXT "Message", IDASKTX2, 10, 27, 40, 14 EDITTEXT IDASKMSG, 45, 25, 145, 14, ES_READONLY | ES_AUTOHSCROLL LISTBOX IDASKLIST, 10, 50, 120, 45, WS_VSCROLL | WS_TABSTOP DEFPUSHBUTTON "OK", IDOK, 140, 50, 50, 14 PUSHBUTTON "Cancel", IDCANCEL, 140, 70, 50, 14 END STRING_DLG DIALOG 30, 30, 130, 65 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Param" FONT 8, "Helv" BEGIN EDITTEXT IDSTRING, 15, 15, 100, 14 DEFPUSHBUTTON "OK", IDOK, 10, 40, 50, 14 PUSHBUTTON "Cancel", IDCANCEL, 70, 40, 50, 14 END FLOPPY_DLG DIALOG 30, 30, 240, 130 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Param" FONT 8, "Helv" BEGIN LTEXT "Device Type", IDDEVTX, 5, 12, 45, 14 EDITTEXT IDDEVTYPE, 50, 10, 40, 14, ES_READONLY | NOT WS_TABSTOP LTEXT "Path", IDPATHTX, 5, 32, 40, 14 EDITTEXT IDPATH, 50, 30, 120, 14, ES_AUTOHSCROLL PUSHBUTTON "Browse...", IDBROWSE, 180, 30, 50, 14 LTEXT "Media Type", IDMEDIATX, 5, 52, 45, 14 COMBOBOX IDMEDIATYPE, 50, 50, 40, 14, CBS_DROPDOWNLIST | WS_TABSTOP AUTOCHECKBOX "Inserted", IDSTATUS, 50, 70, 50, 14 AUTOCHECKBOX "Write Protection", IDREADONLY, 116, 70, 70, 14 LTEXT "Clicking OK signals a media change for this drive.", IDCHANGETX, 35, 90, 185, 8 PUSHBUTTON "Create Image", IDCREATE, 35, 105, 50, 14 DEFPUSHBUTTON "OK", IDOK, 95, 105, 50, 14 PUSHBUTTON "Cancel", IDCANCEL, 155, 105, 50, 14 END MAINMENU_DLG DIALOG 30, 30, 275, 130 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Bochs Start Menu" FONT 8, "Helv" BEGIN GROUPBOX "Configuration", IDCONFIG, 10, 10, 70, 97 PUSHBUTTON "L&oad", IDREADRC, 20, 25, 50, 14 PUSHBUTTON "&Save", IDWRITERC, 20, 45, 50, 14 PUSHBUTTON "&Edit", IDEDITCFG, 20, 65, 50, 14 PUSHBUTTON "Rese&t", IDRESETCFG, 20, 85, 50, 14 GROUPBOX "Edit Options", IDEDITGRP, 90, 10, 95, 107 LISTBOX IDEDITBOX, 95, 20, 85, 100, WS_VSCROLL | WS_TABSTOP GROUPBOX "Simulation", IDSIMU, 195, 10, 70, 77 DEFPUSHBUTTON "Sta&rt", IDOK, 205, 25, 50, 14 PUSHBUTTON "Restore St&ate", IDRESTORE, 205, 45, 50, 14 PUSHBUTTON "&Quit", IDQUIT, 205, 65, 50, 14 END LOGOPT_DLG DIALOG 30, 30, 240, 180 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Log Options" FONT 8, "Helv" BEGIN LISTBOX IDDEVLIST, 15, 25, 55, 100, LBS_SORT | WS_VSCROLL | WS_TABSTOP LTEXT "Debug events", IDLOGLBL1, 80, 27, 55, 14 COMBOBOX IDLOGEVT1, 155, 25, 65, 56, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP LTEXT "Info events", IDLOGLBL2, 80, 47, 55, 14 COMBOBOX IDLOGEVT2, 155, 45, 65, 56, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP LTEXT "Error events", IDLOGLBL3, 80, 67, 55, 14 COMBOBOX IDLOGEVT3, 155, 65, 65, 56, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP LTEXT "Panic events", IDLOGLBL4, 80, 87, 55, 14 COMBOBOX IDLOGEVT4, 155, 85, 65, 56, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_VSCROLL | WS_TABSTOP AUTOCHECKBOX "Specify log options per device", IDADVLOGOPT, 50, 135, 112, 14, BS_LEFTTEXT | WS_TABSTOP DEFPUSHBUTTON "OK", IDOK, 35, 155, 50, 14 PUSHBUTTON "Cancel", IDCANCEL, 95, 155, 50, 14 PUSHBUTTON "Apply", IDAPPLY, 155, 155, 50, 14 END PLUGIN_CTRL_DLG DIALOG 100, 120, 180, 135 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Optional Plugin Control" FONT 8, "Helv" BEGIN LISTBOX IDPLUGLIST, 15, 15, 85, 100, WS_VSCROLL | WS_TABSTOP EDITTEXT IDEDIT, 110, 15, 60, 14 PUSHBUTTON "Load", IDLOAD, 110, 35, 50, 14 PUSHBUTTON "Unload", IDUNLOAD, 110, 55, 50, 14 DEFPUSHBUTTON "OK", IDOK, 65, 115, 50, 14 END PARAM_DLG DIALOG 30, 30, 200, 65 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU CAPTION "Param" FONT 8, "Helv" BEGIN DEFPUSHBUTTON "OK", IDOK, 45, 40, 50, 14 PUSHBUTTON "Cancel", IDCANCEL, 105, 40, 50, 14 END #include "bxversion.rc" #include "win32_enh_dbg.rc" bochs-2.6/patches/0000755000175000017500000000000012020641476013766 5ustar guillemguillembochs-2.6/patches/patch.example-user-plugin0000644000175000017500000002613412020641476020720 0ustar guillemguillem---------------------------------------------------------------------- Patch name: patch.example-user-plugin Author: Volker Ruppert Updated: 14 Apr 2012 Status: Demo Detailed description: This sample code can be used as a framework for writing user plugins. It contains enough code for testing the existing user plugin support in Bochs and creates a device that installs a 32-bit r/w register at i/o address 0x1000. This example also shows how to install and handle user-defined config options for bochsrc, command line and the config interface. In this demo it is used to specify the reset value. For user plugin support Bochs must be configured with plugins enabled. Compiling with plugin support is known to work on Linux and Windows (Cygwin or MinGW/MSYS). Bochs supports loading of up to 16 different user plugins when starting up. Loading / removing plugins at runtime is not yet supported. Patch was created with: diff -u Apply patch to what version: svn revision 11138 (April 14, 2012) Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". Regenerate the configure script and compile Bochs as usual cd user-plugin make make install ---------------------------------------------------------------------- diff -urN ../bochs/configure.in ./configure.in --- ../bochs/configure.in 2012-04-11 18:53:04.078087998 +0200 +++ ./configure.in 2012-04-14 16:18:03.046503743 +0200 @@ -2787,4 +2787,4 @@ doc/docbook/Makefile build/linux/bochs-dlx \ bxversion.h bxversion.rc build/macosx/Info.plist \ build/win32/nsis/Makefile build/win32/nsis/bochs.nsi \ - host/linux/pcidev/Makefile) + host/linux/pcidev/Makefile user-plugin/Makefile) diff -urN ../bochs/user-plugin/Makefile.in ./user-plugin/Makefile.in --- ../bochs/user-plugin/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +++ ./user-plugin/Makefile.in 2012-04-14 16:18:03.046503743 +0200 @@ -0,0 +1,108 @@ +# Copyright (C) 2009-2012 Volker Ruppert +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# Makefile for the user plugin example of bochs + + +@SUFFIX_LINE@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +srcdir = @srcdir@ +VPATH = @srcdir@ +bindir = @bindir@ +libdir = @libdir@ +plugdir = @libdir@/bochs/plugins +datarootdir = @datarootdir@ +mandir = @mandir@ +man1dir = $(mandir)/man1 +man5dir = $(mandir)/man5 +docdir = $(datarootdir)/doc/bochs +sharedir = $(datarootdir)/bochs +top_builddir = .. +top_srcdir = @top_srcdir@ + +SHELL = @SHELL@ + +@SET_MAKE@ + +CXX = @CXX@ +CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ + +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +RANLIB = @RANLIB@ +PLUGIN_PATH=@libdir@ +top_builddir = .. +LIBTOOL=@LIBTOOL@ +WIN32_DLL_IMPORT_LIBRARY=../dllexports.a + +BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@ + +PLUGIN_OBJS = testdev.o + +plugins: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@) + +install: @INSTALL_PLUGINS_VAR@ + +install_libtool_plugins:: + list=`echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install $$i $(DESTDIR)$(plugdir); done + $(LIBTOOL) --finish $(DESTDIR)$(plugdir) + +install_dll_plugins:: + list=`echo *.dll`; for i in $$list; do cp $$i $(DESTDIR)$(plugdir); done + +# standard compile rule for C++ files +.@CPP_SUFFIX@.o: + $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@ + +##### building plugins with libtool +%.lo: %.@CPP_SUFFIX@ + $(LIBTOOL) --mode=compile $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@ + +libbx_%.la: %.lo + $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) + +#### building DLLs for win32 (tested on cygwin only) +bx_%.dll: %.o + $(CXX) $(CXXFLAGS) -shared -o $@ $< $(WIN32_DLL_IMPORT_LIBRARY) + +clean: + @RMCOMMAND@ -rf .libs *.lo *.o *.la *.a *.dll + +dist-clean: clean + @RMCOMMAND@ Makefile + +########################################### +# dependencies generated by +# gcc -MM -I.. -I../instrument/stubs *.cc | sed -e 's/\.cc/.@CPP_SUFFIX@/g' +# gcc -MM -I.. -I../instrument/stubs *.cc | \ +# sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g' +# +# This means that every source file is listed twice, once with a .o rule +# and then again with an identical .lo rule. The .lo rules are used when +# building plugins. +########################################### +testdev.o: testdev.@CPP_SUFFIX@ ../iodev/iodev.h ../bochs.h ../config.h ../osdep.h \ + ../bx_debug/debug.h ../config.h ../osdep.h ../bxversion.h \ + ../gui/siminterface.h ../memory/memory.h ../pc_system.h ../plugin.h \ + ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ + ../gui/keymap.h ../instrument/stubs/instrument.h testdev.h +testdev.lo: testdev.@CPP_SUFFIX@ ../iodev/iodev.h ../bochs.h ../config.h ../osdep.h \ + ../bx_debug/debug.h ../config.h ../osdep.h ../bxversion.h \ + ../gui/siminterface.h ../memory/memory.h ../pc_system.h ../plugin.h \ + ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \ + ../gui/keymap.h ../instrument/stubs/instrument.h testdev.h diff -urN ../bochs/user-plugin/testdev.cc ./user-plugin/testdev.cc --- ../bochs/user-plugin/testdev.cc 1970-01-01 01:00:00.000000000 +0100 +++ ./user-plugin/testdev.cc 2012-04-14 16:30:28.849027414 +0200 @@ -0,0 +1,118 @@ +// Copyright (C) 2009-2012 Volker Ruppert +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +// User plugin example (see patch description for details) + +// Define BX_PLUGGABLE in files that can be compiled into plugins. For +// platforms that require a special tag on exported symbols, BX_PLUGGABLE +// is used to know when we are exporting symbols and when we are importing. +#define BX_PLUGGABLE + +#include "iodev.h" +#include "testdev.h" + +#define LOG_THIS theTestDevice-> + +bx_testdev_c *theTestDevice = NULL; + +// builtin configuration handling functions + +Bit32s testdev_options_parser(const char *context, int num_params, char *params[]) +{ + if (!strcmp(params[0], "testdev")) { + if (!strncmp(params[1], "test=", 5)) { + SIM->get_param_num("user.testdev.test")->set(atoi(¶ms[1][5])); + } else { + BX_PANIC(("%s: testdev: unknown parameter '%s'", context, params[1])); + } + } else { + BX_PANIC(("%s: unknown directive '%s'", context, params[0])); + } + return 0; +} + +Bit32s testdev_options_save(FILE *fp) +{ + fprintf(fp, "testdev: test=%d\n", SIM->get_param_num("user.testdev.test")->get()); + return 0; +} + +// device plugin entry points + +int libuser_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) +{ + theTestDevice = new bx_testdev_c(); + BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theTestDevice, "testdev"); + // add new configuration parameter for the config interface + bx_param_c *root_param = SIM->get_param("user"); + bx_list_c *menu = new bx_list_c(root_param, "testdev", "Test Device"); + menu->set_options(bx_list_c::SHOW_PARENT); + new bx_param_num_c(menu, "test", "Test Parameter", "", 0, BX_MAX_BIT32U, 0); + // register user-defined option for bochsrc and command line + SIM->register_addon_option("testdev", testdev_options_parser, testdev_options_save); + return(0); // Success +} + +void libuser_LTX_plugin_fini(void) +{ + SIM->unregister_addon_option("testdev"); + bx_list_c *menu = (bx_list_c*)SIM->get_param("user"); + menu->remove("testdev"); + delete theTestDevice; +} + +// the device object + +bx_testdev_c::bx_testdev_c(void) +{ + put("USER"); +} + +bx_testdev_c::~bx_testdev_c(void) +{ + // nothing here yet +} + +void bx_testdev_c::init(void) +{ + DEV_register_ioread_handler(this, read_handler, 0x1000, "Test Device", 4); + DEV_register_iowrite_handler(this, write_handler, 0x1000, "Test Device", 4); +} + +void bx_testdev_c::reset(unsigned type) +{ + BX_USER_THIS s.reg0 = SIM->get_param_num("user.testdev.test")->get(); +} + +void bx_testdev_c::register_state(void) +{ + bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "testdev", "Test Device"); + BXRS_HEX_PARAM_FIELD(list, reg0, BX_USER_THIS s.reg0); +} + +Bit32u bx_testdev_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) +{ + UNUSED(this_ptr); + + return BX_USER_THIS s.reg0; +} + +void bx_testdev_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) +{ + UNUSED(this_ptr); + + BX_USER_THIS s.reg0 = value; +} diff -urN ../bochs/user-plugin/testdev.h ./user-plugin/testdev.h --- ../bochs/user-plugin/testdev.h 1970-01-01 01:00:00.000000000 +0100 +++ ./user-plugin/testdev.h 2012-04-14 16:19:30.538406315 +0200 @@ -0,0 +1,40 @@ +// Copyright (C) 2009-2012 Volker Ruppert +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef BX_TESTDEV_H +#define BX_TESTDEV_H + +#define BX_USER_THIS theTestDevice-> + +class bx_testdev_c : public bx_devmodel_c { +public: + bx_testdev_c(); + virtual ~bx_testdev_c(); + + virtual void init(void); + virtual void reset(unsigned type); + virtual void register_state(void); + +private: + static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); + static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); + + struct { + Bit32u reg0; + } s; +}; + +#endif bochs-2.6/patches/patch.marklog0000644000175000017500000001410412020641476016443 0ustar guillemguillem---------------------------------------------------------------------- Patch name: patch.marklog Author: Carl Sopchak Date: May, 1st 2002 Detailed description: While working on getting SCO OSR5 installed into bochs, I added this mod to the gui programs. It adds a button (labelled XX LOG; my bitmap artsmanship leaves MUCH to be desired!) to the gui bar that writes a BX_ERROR entry into the log file. The format of the entry is: tttttttttt-x-@eeeeeeee[XGUI ] ================================ Log Marker # nnnn ================================ where nnnn is a sequential number from the beginning of the bochs session. A message is also written to stdout stating that the entry was logged, which also shows the number. This is useful to log demarcation points in the log file (e.g., "skip everything before marker #1"; "stuff between markers 3 & 4 is where the hard disk gets initialized", etc.) Please make this a part of the standard bochs package. Thanks, Carl Patch was created with: cvs diff -u Apply patch to what version: cvs checked out on May, 1st 2002 Instructions: To patch, go to main bochs directory. Type "cd gui" Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- Index: gui.h =================================================================== RCS file: /cvsroot/bochs/bochs/gui/gui.h,v retrieving revision 1.27 diff -u -r1.27 gui.h --- gui.h 20 Apr 2002 07:19:35 -0000 1.27 +++ gui.h 1 May 2002 18:13:03 -0000 @@ -78,6 +78,7 @@ static void cdromD_handler(void); static void reset_handler(void); static void power_handler(void); + static void marklog_handler(void); static void copy_handler(void); static void paste_handler(void); static void snapshot_handler(void); @@ -91,6 +92,7 @@ unsigned floppyA_bmap_id, floppyA_eject_bmap_id, floppyA_hbar_id; unsigned floppyB_bmap_id, floppyB_eject_bmap_id, floppyB_hbar_id; unsigned cdromD_bmap_id, cdromD_eject_bmap_id, cdromD_hbar_id; + unsigned marklog_bmap_id, marklog_hbar_id; unsigned power_bmap_id, power_hbar_id; unsigned reset_bmap_id, reset_hbar_id; unsigned copy_bmap_id, copy_hbar_id; @@ -98,11 +100,13 @@ unsigned snapshot_bmap_id, snapshot_hbar_id; unsigned config_bmap_id, config_hbar_id; unsigned mouse_bmap_id, nomouse_bmap_id, mouse_hbar_id; + + unsigned markercount; }; #define BX_MAX_PIXMAPS 16 -#define BX_MAX_HEADERBAR_ENTRIES 10 +#define BX_MAX_HEADERBAR_ENTRIES 11 #define BX_HEADER_BAR_Y 32 // align pixmaps towards left or right side of header bar Index: gui.cc =================================================================== RCS file: /cvsroot/bochs/bochs/gui/gui.cc,v retrieving revision 1.41 diff -u -r1.41 gui.cc --- gui.cc 18 Apr 2002 00:22:19 -0000 1.41 +++ gui.cc 1 May 2002 18:13:03 -0000 @@ -37,6 +37,7 @@ #include "gui/bitmaps/paste.h" #include "gui/bitmaps/configbutton.h" #include "gui/bitmaps/cdromd.h" +#include "gui/bitmaps/marklog.h" #if BX_WITH_MACOS # include #endif @@ -75,13 +76,15 @@ BX_GUI_THIS nomouse_bmap_id = create_bitmap(bx_nomouse_bmap, BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y); - BX_GUI_THIS power_bmap_id = create_bitmap(bx_power_bmap, BX_POWER_BMAP_X, BX_POWER_BMAP_Y); BX_GUI_THIS reset_bmap_id = create_bitmap(bx_reset_bmap, BX_RESET_BMAP_X, BX_RESET_BMAP_Y); BX_GUI_THIS snapshot_bmap_id = create_bitmap(bx_snapshot_bmap, BX_SNAPSHOT_BMAP_X, BX_SNAPSHOT_BMAP_Y); BX_GUI_THIS copy_bmap_id = create_bitmap(bx_copy_bmap, BX_COPY_BMAP_X, BX_COPY_BMAP_Y); BX_GUI_THIS paste_bmap_id = create_bitmap(bx_paste_bmap, BX_PASTE_BMAP_X, BX_PASTE_BMAP_Y); BX_GUI_THIS config_bmap_id = create_bitmap(bx_config_bmap, BX_CONFIG_BMAP_X, BX_CONFIG_BMAP_Y); + BX_GUI_THIS marklog_bmap_id = create_bitmap(bx_marklog_bmap, BX_MARKLOG_BMAP_X, BX_MARKLOG_BMAP_Y); + + BX_GUI_THIS markercount = 0; // Add the initial bitmaps to the headerbar, and enable callback routine, for use @@ -145,6 +148,9 @@ // Copy button BX_GUI_THIS copy_hbar_id = headerbar_bitmap(BX_GUI_THIS copy_bmap_id, BX_GRAVITY_RIGHT, copy_handler); + // Mark Log button + BX_GUI_THIS marklog_hbar_id = headerbar_bitmap(BX_GUI_THIS marklog_bmap_id, + BX_GRAVITY_RIGHT, marklog_handler); show_headerbar(); } @@ -262,6 +268,15 @@ bx_pc_system.ResetSignal( PCS_SET ); /* XXX is this right? */ for (int i=0; ireset(BX_RESET_HARDWARE); +} + + void +bx_gui_c::marklog_handler(void) +{ + // the user pressed Mark Log button, so write error marker to log file + BX_GUI_THIS markercount += 1; + BX_ERROR (("\n================================\nLog Marker # %d\n================================", BX_GUI_THIS markercount)); + fprintf (stderr, "Marker # %d written to log.\n", BX_GUI_THIS markercount); } void --- /dev/null Thu Aug 30 16:30:55 2001 +++ bitmaps/marklog.h Wed May 1 09:58:00 2002 @@ -0,0 +1,20 @@ +///////////////////////////////////////////////////////////////////////// +// $Id: patch.marklog,v 1.1 2002-05-01 21:07:13 cbothamy Exp $ +///////////////////////////////////////////////////////////////////////// +// +#define BX_MARKLOG_BMAP_X 32 +#define BX_MARKLOG_BMAP_Y 32 + +static const unsigned char bx_marklog_bmap[(BX_MARKLOG_BMAP_X * BX_MARKLOG_BMAP_Y)/8] = { + 0x60, 0x18, 0x86, 0x01, 0xc0, 0x0c, 0xcc, 0x00, 0x80, 0x07, 0x78, 0x00, + 0x00, 0x03, 0x30, 0x00, 0x80, 0x07, 0x78, 0x00, 0xc0, 0x0c, 0xcc, 0x00, + 0x60, 0x18, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x30, 0x18, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00, 0x30, 0x18, 0x00, + 0x00, 0x30, 0x18, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x30, 0x10, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x00, 0x30, 0x1e, 0x00, 0x00, 0x30, 0x18, 0x00, 0x00, 0x30, 0x18, 0x00, + 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00 + }; bochs-2.6/patches/bochs-bios-win32.diff0000644000175000017500000000331712020641476017614 0ustar guillemguillemdiff -Nurd bios-orig/rombios32.ld bios/rombios32.ld --- bios-orig/rombios32.ld Sat Jan 26 09:15:27 2008 +++ bios/rombios32.ld Sat Mar 22 09:29:24 2008 @@ -1,4 +1,3 @@ -OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start); SECTIONS diff -Nurd bios-orig/rombios32start.S bios/rombios32start.S --- bios-orig/rombios32start.S Sat Jan 26 09:15:27 2008 +++ bios/rombios32start.S Sat Mar 22 09:30:49 2008 @@ -21,12 +21,12 @@ #include "rombios.h" .globl _start -.globl smp_ap_boot_code_start -.globl smp_ap_boot_code_end -.global smm_relocation_start -.global smm_relocation_end -.global smm_code_start -.global smm_code_end +.globl _smp_ap_boot_code_start +.globl _smp_ap_boot_code_end +.global _smm_relocation_start +.global _smm_relocation_end +.global _smm_code_start +.global _smm_code_end _start: /* clear bss section */ @@ -36,20 +36,20 @@ sub %edi, %ecx rep stosb - jmp rombios32_init + jmp _rombios32_init .code16 -smp_ap_boot_code_start: +_smp_ap_boot_code_start: xor %ax, %ax mov %ax, %ds incw CPU_COUNT_ADDR 1: hlt jmp 1b -smp_ap_boot_code_end: +_smp_ap_boot_code_end: /* code to relocate SMBASE to 0xa0000 */ -smm_relocation_start: +_smm_relocation_start: mov $0x38000 + 0x7efc, %ebx addr32 mov (%ebx), %al /* revision ID to see if x86_64 or x86 */ cmp $0x64, %al @@ -66,10 +66,10 @@ movw $0xb3, %dx outb %al, %dx rsm -smm_relocation_end: +_smm_relocation_end: /* minimal SMM code to enable or disable ACPI */ -smm_code_start: +_smm_code_start: movw $0xb2, %dx inb %dx, %al cmp $0xf0, %al @@ -95,4 +95,4 @@ 2: rsm -smm_code_end: +_smm_code_end: bochs-2.6/patches/patch.hosttime-port0000644000175000017500000001533612020641476017635 0ustar guillemguillem---------------------------------------------------------------------- Patch name: patch.hosttime-port Author: cbbochs@free.fr Date: July, 31th 2002 Detailed description: This patch enables the guest to read to host time (linux only). Port 0x8901 is used. Two time values can be set and read, along with the difference of the two. This can be useful to do performance tests. port 0x8901 : Writes can be bytes, word, dword Reads must be dword write 0x00 : set both times to 0 write 0x01 : set the first time write 0x02 : set the second time write 0x03 : set the both time write 0x11 : the seconds of the first time will be read from 0x8901 write 0x12 : the microseconds of the first time will be read from 0x8901 write 0x21 : the seconds of the second time will be read from 0x8901 write 0x22 : the microseconds of the second time will be read from 0x8901 write 0x31 : the seconds of the difference will be read from 0x8901 write 0x32 : the microseconds of the difference will be read from 0x8901 Additionnal values have been defined for language that can't do 32bits port access. Please look in the source. Example : Set first time, then second time, and get the difference : outb(0x8901, 0x01); // Set first time outb(0x8901, 0x02); // Set second time outb(0x8901, 0x31); // Read difference : seconds fields sec = inl(0x8901); outb(0x8901, 0x32); // Read difference : microseconds fields usec = inl(0x8901); Patch was created with: cvs diff -u Apply patch to what version: cvs checked out on July, 31th 2002 Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- Index: iodev/unmapped.cc =================================================================== RCS file: /cvsroot/bochs/bochs/iodev/unmapped.cc,v retrieving revision 1.17 diff -u -r1.17 unmapped.cc --- iodev/unmapped.cc 30 Jul 2002 08:48:03 -0000 1.17 +++ iodev/unmapped.cc 31 Jul 2002 09:01:23 -0000 @@ -137,6 +137,40 @@ retval = 0xffffffff; BX_DEBUG(("unsupported IO read from port %04x", address)); break; +#ifdef __linux__ + case 0x8901: // host-time port + struct timeval diff; + retval = 0; + + if (timercmp(& BX_UM_THIS s.hosttime_value1, & BX_UM_THIS s.hosttime_value2, < ) ) + timersub(& BX_UM_THIS s.hosttime_value2, & BX_UM_THIS s.hosttime_value1, &diff); + else + timersub(& BX_UM_THIS s.hosttime_value1, & BX_UM_THIS s.hosttime_value2, &diff); + + switch (BX_UM_THIS s.hosttime_field) { + case 0x11: retval = BX_UM_THIS s.hosttime_value1.tv_sec; break; + case 0x12: retval = BX_UM_THIS s.hosttime_value1.tv_usec; break; + case 0x1C: retval = BX_UM_THIS s.hosttime_value1.tv_sec & 0xffff; break; + case 0x1D: retval = BX_UM_THIS s.hosttime_value1.tv_sec >> 16; break; + case 0x1E: retval = BX_UM_THIS s.hosttime_value1.tv_usec & 0xffff; break; + case 0x1F: retval = BX_UM_THIS s.hosttime_value1.tv_usec >> 16; break; + case 0x21: retval = BX_UM_THIS s.hosttime_value2.tv_sec; break; + case 0x22: retval = BX_UM_THIS s.hosttime_value2.tv_usec; break; + case 0x2C: retval = BX_UM_THIS s.hosttime_value2.tv_sec & 0xffff; break; + case 0x2D: retval = BX_UM_THIS s.hosttime_value2.tv_sec >> 16; break; + case 0x2E: retval = BX_UM_THIS s.hosttime_value2.tv_usec & 0xffff; break; + case 0x2F: retval = BX_UM_THIS s.hosttime_value2.tv_usec >> 16; break; + case 0x31: retval = diff.tv_sec; break; + case 0x32: retval = diff.tv_usec; break; + case 0x3C: retval = diff.tv_sec & 0xffff; break; + case 0x3D: retval = diff.tv_sec >> 16; break; + case 0x3E: retval = diff.tv_usec & 0xffff; break; + case 0x3F: retval = diff.tv_usec >> 16; break; + } + + break; +#endif + default: retval = 0xffffffff; } @@ -256,6 +290,51 @@ BX_CPU(0)->kill_bochs_request = 2; } break; + +#ifdef __linux__ + case 0x8901: // host-time port + switch (value) { + case 0x01: // set first time + gettimeofday(& BX_UM_THIS s.hosttime_value1, NULL); + break; + case 0x02: // set second time + gettimeofday(& BX_UM_THIS s.hosttime_value2, NULL); + break; + case 0x03: // set both times + gettimeofday(& BX_UM_THIS s.hosttime_value1, NULL); + BX_UM_THIS s.hosttime_value2.tv_sec = BX_UM_THIS s.hosttime_value1.tv_sec; + BX_UM_THIS s.hosttime_value2.tv_usec = BX_UM_THIS s.hosttime_value1.tv_usec; + break; + case 0x11: // retrieve sec from first time // 32 bits + case 0x12: // retrieve usec from first time // 32 bits + case 0x1C: // retrieve sec from first time // low 16 bits + case 0x1D: // retrieve sec from first time // high 16 bits + case 0x1E: // retrieve usec from first time // low 16 bits + case 0x1F: // retrieve usec from first time // high 16 bits + case 0x21: // retrieve sec from second time // 32 bits + case 0x22: // retrieve usec from second time // 32 bits + case 0x2C: // retrieve sec from second time // low 16 bits + case 0x2D: // retrieve sec from second time // high 16 bits + case 0x2E: // retrieve usec from second time // low 16 bits + case 0x2F: // retrieve usec from second time // high 16 bits + case 0x31: // retrieve sec from difference // 32 bits + case 0x32: // retrieve usec from difference // 32 bits + case 0x3C: // retrieve sec from difference // low 16 bits + case 0x3D: // retrieve sec from difference // high 16 bits + case 0x3E: // retrieve usec from difference // low 16 bits + case 0x3F: // retrieve usec from difference // high 16 bits + BX_UM_THIS s.hosttime_field = value; + break; + default: + BX_UM_THIS s.hosttime_field = 0; + BX_UM_THIS s.hosttime_value1.tv_sec = 0; + BX_UM_THIS s.hosttime_value1.tv_usec = 0; + BX_UM_THIS s.hosttime_value2.tv_sec = 0; + BX_UM_THIS s.hosttime_value2.tv_usec = 0; + break; + } + break; +#endif case 0xfedc: bx_dbg.debugger = (value > 0); Index: iodev/unmapped.h =================================================================== RCS file: /cvsroot/bochs/bochs/iodev/unmapped.h,v retrieving revision 1.8 diff -u -r1.8 unmapped.h --- iodev/unmapped.h 29 Jul 2002 12:44:47 -0000 1.8 +++ iodev/unmapped.h 31 Jul 2002 09:01:23 -0000 @@ -56,6 +56,11 @@ Bit8u port80; Bit8u port8e; Bit8u shutdown; +#ifdef __linux__ + Bit8u hosttime_field; + struct timeval hosttime_value1; + struct timeval hosttime_value2; +#endif } s; // state information bx_devices_c *devices; bochs-2.6/patches/patch.example-override-ask0000644000175000017500000000773212020641476021044 0ustar guillemguillem---------------------------------------------------------------------- Patch name: patch.example-override-ask Author: Bryce Denney Date: Mon Sep 23 13:00:53 EDT 2002 Status: Demo Detailed description: This patch shows how to create your own siminterface callback function. It is not intended to be checked in anytime, only to serve as an example of how to use the siminterface. Patch updated for current SVN. (Volker Ruppert, Apr 15, 2012) Patch was created with: diff -u Apply patch to what version: svn checked out on DATE Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- diff -urN ../bochs/config.h.in ./config.h.in --- ../bochs/config.h.in 2012-01-26 17:34:41.603286662 +0100 +++ ./config.h.in 2012-04-15 14:29:36.529504219 +0200 @@ -858,6 +858,9 @@ // I/O Interface to debugger #define BX_SUPPORT_IODEBUG 0 +// Override ask dialog (demo) +#define BX_OVERRIDE_ASK_EXAMPLE 1 + #ifdef WIN32 #define BX_FLOPPY0_NAME "Floppy Disk A:" #define BX_FLOPPY1_NAME "Floppy Disk B:" diff -urN ../bochs/gui/textconfig.cc ./gui/textconfig.cc --- ../bochs/gui/textconfig.cc 2012-04-06 15:15:28.094038820 +0200 +++ ./gui/textconfig.cc 2012-04-15 14:31:30.538122593 +0200 @@ -1075,6 +1075,10 @@ { case CI_START: bx_config_interface_init(); +#if BX_OVERRIDE_ASK_EXAMPLE + extern void override_ask_init(); + override_ask_init(); +#endif if (SIM->get_param_enum(BXPN_BOCHS_START)->get() == BX_QUICK_START) bx_config_interface(BX_CI_START_SIMULATION); else { diff -urN ../bochs/Makefile.in ./Makefile.in --- ../bochs/Makefile.in 2012-04-11 18:52:41.715215121 +0200 +++ ./Makefile.in 2012-04-15 14:29:36.530504215 +0200 @@ -141,6 +141,7 @@ osdep.o \ plugin.o \ crc.o \ + overrideask.o \ @EXTRA_BX_OBJS@ EXTERN_ENVIRONMENT_OBJS = \ diff -urN ../bochs/overrideask.cc ./overrideask.cc --- ../bochs/overrideask.cc 1970-01-01 01:00:00.000000000 +0100 +++ ./overrideask.cc 2012-04-15 14:29:36.531504211 +0200 @@ -0,0 +1,52 @@ +#include +#include +#include "config.h" +#include "osdep.h" +#include "gui/siminterface.h" + +bxevent_handler old_callback = NULL; +void *old_callback_arg = NULL; + +BxEvent * +override_ask_callback (void *unused, BxEvent *event) +{ + int n; + int level; + fprintf (stderr, "override_ask_callback\n"); + event->retcode = -1; + switch (event->type) + { + case BX_SYNC_EVT_LOG_ASK: + level = event->u.logmsg.level; + fprintf (stderr, "============ override_ask_callback was called ==========================\n"); + fprintf (stderr, "Event type: %s\n", SIM->get_log_level_name (level)); + fprintf (stderr, "Device: %s\n", event->u.logmsg.prefix); + fprintf (stderr, "Message: %s\n\n", event->u.logmsg.msg); + // note: 4 only available if BX_DEBUGGER=1. ideally, don't show it + fprintf (stderr, "What should I do? (0=continue, 1=alwayscont, 2=die, 3=abort, 4=debug) "); + while (scanf ("%d", &n) != 1 || (n<0 && n>4)) { + fprintf (stderr, "Enter 0-4 only.\n"); + } + event->retcode = n; + fprintf (stderr, "============ override_ask_callback is done =============================\n"); + return event; + case BX_SYNC_EVT_TICK: // called periodically by siminterface. + case BX_SYNC_EVT_ASK_PARAM: // called if simulator needs to know value of a param. + case BX_ASYNC_EVT_REFRESH: // called when some bx_param_c parameters have changed. + // fall into default case + default: + return (*old_callback)(old_callback_arg, event); + } +} + +// called from textconfig.cc +void override_ask_init () +{ + fprintf (stderr, "override_ask_init"); + // this should be called after the configuration interface has had a + // chance to install its own callback. Otherwise, overrideask will not + // override anything. + SIM->get_notify_callback (&old_callback, &old_callback_arg); + assert (old_callback != NULL); + SIM->set_notify_callback (override_ask_callback, NULL); +} bochs-2.6/patches/HEADER0000644000175000017500000000061012020641476014636 0ustar guillemguillem---------------------------------------------------------------------- Patch name: Author: Date: Status: Detailed description: Patch was created with: diff -up VER1 VER2 Apply patch to what version: svn revision [REVISION] Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- bochs-2.6/patches/patch.mingw-resources0000644000175000017500000000320212020641476020135 0ustar guillemguillem---------------------------------------------------------------------- Patch name: patch.mingw-resources Author: Jeroen Janssen Date: 2003-08-19 Status: not applied Detailed description: Changes the .rc (resource) files to use forware (/) style slashes instead of backwards style ones. This allows for crosscompilation from linux using a crosscompiler. Patch was created with: cvs diff -u Apply patch to what version: cvs checked out on DATE, release version VER Instructions: To patch, go to main bochs directory. Type "patch -p0 < THIS_PATCH_FILE". ---------------------------------------------------------------------- Index: win32res.rc =================================================================== RCS file: /cvsroot/bochs/bochs/win32res.rc,v retrieving revision 1.4 diff -u -r1.4 win32res.rc --- win32res.rc 15 Jul 2003 21:02:05 -0000 1.4 +++ win32res.rc 19 Aug 2003 16:40:03 -0000 @@ -1,7 +1,7 @@ #include -#include "gui\win32res.h" +#include "gui/win32res.h" -ICON_BOCHS ICON build\win32\nsis\bochs.ico +ICON_BOCHS ICON build/win32/nsis/bochs.ico ASK_DLG DIALOG 30, 30, 200, 100 STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU Index: wxbochs.rc =================================================================== RCS file: /cvsroot/bochs/bochs/wxbochs.rc,v retrieving revision 1.4 diff -u -r1.4 wxbochs.rc --- wxbochs.rc 13 Jul 2003 23:30:55 -0000 1.4 +++ wxbochs.rc 19 Aug 2003 16:40:03 -0000 @@ -1,5 +1,5 @@ #include "config.h" -icon_bochs ICON build\win32\nsis\bochs.ico +icon_bochs ICON build/win32/nsis/bochs.ico #include "wx/msw/wx.rc" #if BX_WITH_WIN32 #include "win32res.rc"bochs-2.6/patches/NOTES0000644000175000017500000000024012020641476014575 0ustar guillemguillemThis directory contains patches that are under consideration or being tested. The file HEADER is a nice template for the top of a patch. Use it if you want. bochs-2.6/patches/patch.decode-interrupts.gz0000644000175000017500000010552212020641476021073 0ustar guillemguillem‹î0Ü=patch.decode-interrupts´[i{ÚȲþ|ô+:ØCÌ"ð†±É 9æŽm|€l7ÉðÔ€N„Äh±ñÉx~û­ªnm€—‰sy2F´ªÞ®ª®®®êî)~ÆG¹ÖýÑ”ÙúŒ×ØŸ‹9/˜¶Ï]7˜ûžÒü©ãÖØ©{7â¬Åm›ß)-Ý–Ü`WÎ «¨¬|T«Ô*{Lëõá·ZQ”ç>ku´kã÷¯Šræ¸L·ï˜çŒý[Ýå,ê&Ϧºk,·9_ŒøÜ7;ÏNÑÔSFºeyÌŸ"¡ç»ÁŒÛ¾Žl¦\‡~´¯zý.üíkÝî»ë~6Wd »æ:(‹üŠ¿ž.¸¦',ÁtÃðVú@ã‘î+–ã|óX0¨‘ÐðDÂuuk &snm¶¨$Þ[¦çƒ eîB£Ð€9c©UI³'@?ù¯à²,æß͹´Jk7•öÕY§ øíÎU‘^ÍX0ÍZêl[Ù¯À0w.7äsÙî•÷Üõ0İl3×tæw®9™ú°°UË…òÑÑ.»4a}Á¥‹5wÎ.Ì·=¹—°º¦n1XO]gÎ]ÿƒyLÞ€ÈI`s!»7ÀôGc[Q ÞQœÛW*{å½ò²«äã°ÐRXËôµ ­ÿéZcwýëwý"Á² n±[fÙr.‚Ú­¼ªÂ²•j_}ÔËîÅPÕ@©,«ÆPÕƒ@í³ì~µ¯¾Äì‡,{CU^bvp»ƒê@Ý«ü0dcYCU*?uÎ0Œ¡öÔ‡:rô(†š€µ ¬¥'ö¨\TDÌÛ`aS²]¬}Éóƒ¡WzÚ˜£©ÿ 0‡¼v6w\Ì=·0›ÅÜÕôÁ8 JÆ‚JÊ4HüÑ”¾Á[4®î):³ùíJea˜.-òwTö±@B=ÅÁ\w}©šbða0™`o ýÔ+½~ýZèHÊ­îAÿ7Ü‚åÈÀMo,° àÖÑy|WùÛûSvíø ¬cJŸ¦¶c902ËN}^+•noo‹óÄŠ"–“†!…Ôc*Ò@iÅ æ` pX>ÑGwLŸÏ-sDªBùb£Ý¹kGUŸôF~ Â9·’ÏX× u0¡ïИ‰> ~ø—ÂC B…%,¯À1¢^$¤¨¯%1¸Œ e[¤+Ké*Ñc¡ì`p0 Õ«¯0sI‘e3y“ÅC!j c£0¼9³B 4@å;és 9U@7"ÉIÉ3€å£´}¨Ã\nAyÅCZH»JÛCæ¾#€ólâ øLljKv‰©ˆtP»±Œ¡0W٠럷{ƒkÌÓ˜¤eŠÊOÙJ((ʯ«G_×XLE—¢w;_Kµ‰´ λ¨­Ò§@•úË?J·Ù£¨Pc%+×qüYXþ}\‚üâr S78+\ø¢±,é¬à¯t¨Å±xBµUöY<÷X$ö{{µÝ*+`‚ý/DßÙÙy¡,wmA-×à_¥"”ß~c…ý£<¬z;ðuÀ~ûMa7Ž óo1 ÁÜåcs1˜xÙÀö̉ Þ;š9öýþJ¾€¹fT‡kè•Bš# ñ)Ú<‹~‰:ˆ˜—X£}¢Î:½}f¿yvjú僀¼<²ë†Ö^s.p—-à[ÃÁb˜õ.ÆBÝ­¸*ÜèÖ:KŽ`qçO#=4fÿ` J>.FôÓã“”~ÎxìqŽþQ­äwÙÎa5_†ì d¥ÏéÝàÖ5}žM€àw¢‹ÛkÅVÌCžÁ¹£ì”~ÆaÄöY˜X°±ëÌé×¶·´÷ÓzVv¸ÌØw¦ì0Ö=…$i€©å³úÔ™º€yYÎ/à.^’ ²LÐ’ïC‚½e‚pß/$¨.ˆ|7B(« ‚ÆÕ§Áe£÷{ÜÅáx´øç¯à0`Ñ ÓYd¡‘±ɈW]û>Ô¢‘XÖ :3mJ —‚.BE¤HZ“¢l^¼&cÒ Ê¯±gþ ÕqŒuUK;}÷ö-ä†À-ÙWÐq#‹«ká Qk€I6ËærÂUóHB %àÌ Q&Îldz^QBv I>þÀ÷o29ß{Æ-ÈL¿GJ ïÍ1@ƒõ² ÍÉÉ^ŽíH]Ž*`Êg̰³f]=fæ‰T wv"CŸÞùü8jú8¸Ô.³*èe '± ÍøŒeçbq(çÙ/È‘‹Xü³‰cšB;aC½®æØÔÿ½"¤ùûž´[£¾ø¼l:¹÷H­ø6`X“$†I˜pR!s ^9Í„û˜"¹ú@½ÁBFš‰¢ð©|$á˯©øÏKÏg2Â_¢Òa°W!ZÙ/,å2(‰Öø“ˆ$úG8‰8U°Ý›7¬š¤²–¨.‚Á¾gôÝZêÛ ¾'ú6¬%ªTß8³ (dwèC„,ï34ô âRÔí}-zPu¡Q‹/á1dJt¤²ZÙûJMŒ,”RY™MR\3K6uQVkuo öwBß ¹ôiÂÏ#U­Åm OcΆ3°¾‘D]l©•E.AÎÂÿbwÇÔk¯âWžÀ‡8‡ð#Ç f6<¾•¥ñ\ü£jLÙL‡¸áÒö”îËw†FëÁôŸ;ž‰Î½Š£¯Å¡#Ìç°sb÷aqi`B½Ç5—[whU–Ý…–5e,ü«nÕ¶Ý~Ô÷QÐID)U¥,üAnŒ{$’qêyþQÙbü¢Ó!Ô#>ÚR÷5ü#µ2 j1iMB‰qMQWzÞ5„ð´ Âùb¨Ãš8‰¥Ï¸ò±ÄÊ'c¤çë.1 ¶zµÖÇ$ók&…;!pžQÈÅ¥ÂcøÍ¥UXµ ˆGêõí-o;CüŒ_Žãx®§O o(»€ØòPžØK4YÕaù„kI“{¹„ ÙEÇîËçØ~Ff3Ýû–‹’ñôjÿ’Ì‘T±SÚvåXÕ8V¾Ö-Z2 Q†Zi¹'¨ú2“ö¥¹úª¾š\IŠDn•¸Ö°´ÇýBÓÂåɳÉ^~I(\ÁW8äzÁi¡|lm|ÄCD-“˜Ç$†ºÀµ ˆ$¾È¡ä‰vhY‘çþ9}]¬ö…+຾ÂöGú¢q¤|$±ê1Ù¢bBµýEÝ–­ç.äz¡ÇÉ섨s» Å æØaÙÌ–·åÙ–GáÊÏG.W(Ì1…¡q‰–}§ÂÁî‰!„q±±.nXźçÄQÖR|’—²<Ï*äå ÞEÂ-éS š%U#@©jJ½5šý¤-»¤öÚj?Gý„:à¡mïÕ]òŸ¼÷ýœÅŽöÕ³hq‡»dð›®”ÿ*³ÿ*ª Ò`ú'w¢×îc¯â=µ™­æU¶SΗ÷÷p«rgãU)ðÜ,E%:q-ÜBü£›lám| ›¸Å·t ®êù†i‹ksÞL77ÀS öŽ–fxºJ•±“rhâþ <}Âk؂٘Ïþ.¹ ©_ E)~Ö ÿýÊþbÅ5†aoXbcYE}vE,t{¯ÞÞSñ2V|Ÿ¬+hZÐ{M„jîR‚W®+ O¼=<ä‘a]¥#WXIm›[L ¤«pBïL=`á¹]y÷4qýT¡ßaß8ŸRœqÁÐßrFßX07P xåøxÅ3¼ZéÉá±¹€¢yoŠÐ4ä® €%ú@]B›VEq#$q3Ü›ó‘9¾¡¾q.;Ššç; '^ˆOø:¼?#_âÝ ì‹Ô £œRR˜1 H*i‚ ½ËĸòÊ8ÍQ—"‹Ü­—Ÿ§îÆcrˆ\äÜ´F\Ôß\¬á4’ˆ"—‹ð"»Ì椀¸U‚rªàÒ$n §¸èwö]ò.|ÂÛÒË%‚  ÀÝÓ²(® q )pêÛ,/b*v€/ê;ìÖq¿‘|æÝ@ê7tH¤‹™¸NfÚbØqÏÆÖͨ§ïÛ§Û÷X(a¨ÃJ)ùª)^A‰»ü¦%Þ´VyÎÅ›pâ/¿~/^ÓÁaæX ̦i½Ü)«Dö¤×oµ¯ÞÈÜ+}þâ~±¿Bb|VR¥?ÂÕ¹”ÚˆeïCÀ“Ìñ¢…x"ªãZ2Âtßô‹!íØ l#,Í6Å!Òf˜T`Á°I§LéªxClbaz2'"˜¢(NG~ì£\ì”á­-¹Á“P§nú” …âëè§NZÜžøÓìæ«ÃÝPŒèAì»ð–¢k9z«&ªÄØŒOf¹CÍÿdÛ¯¢Î丕㳟õ#  ‹€½9ظ€à|ÚÕ¿odÒ[UkXŸ?j¥Xcö(+ˆÿÛ€äØÀ²•Žöt6æ·Ña”œcy-þÇ•ÄþH2ß߬tÑî¾Û(‰æ¿þJ¼é»°0Ø>ë=ð&[!Ê‹¯›ën§©õz.ƒ¥¬Ó}O«óîôBcÚǦvwá…÷€ 6-IePwS¼²¨éopµÄ°D>‡\áô%Æh*ÓãýqÚÙWaÜ‹(…·lˆíߌð£ZÊkRŠ/¶ðÃäˆúxL‰Î^‰ÅšÍQ¢øuôzŠžõiühEé³êTKtP0ÐÁ”/²á\.iJU䮬”!õZN¦ä,…öÔZñ.Î&™=†ü(öèˆo=‰ÿDOöÁ6[FQS@OöôŒ¾ØÒIõˆ8³Ü§ÏhcÄ´´»t&å/ÖiØÓÍó:ŽXÅŒü[:VDsQG«/ÑX)º•‚©n=aº4GÚ1Wﱟ´%ˆü8Ò\ûÚÑLK«'æ¶È†GSúÈvù/v¸‡/ùR7uþZo¯UÒ‹URk=©¸Õ³L6YŠiÍ•Ÿ¿ˆ9ŽtÚT|Ýè5Ûÿ[J"¨ ý6}}R`ÐMh³5“§ OøW mÓ‡>Ⱦ­V<0I¨hMàYà-ðïaÐ<Å›“Vc‹>)† eѿņ"Šý‘™_"Hz89©âýÍølzYœuq$¹Ž:}½„†DÂ¥w³”ˆr-É.Í™(Ûq M·BÐYŒç€O)¸ååå^ìÃ:æä—:L†â”¶<9 Ï`NäùBïý¿½÷L¡£¸œL@¾|Áìžri—Ï(i°¨Š•ñ~¿géÞ”{ËœàÍ/²ŠÿÝâÏ·ºÄŽeÄZ Öeö?pƒá³Z8ú?ö®ÿ9mdÉÿ+sùá=ç6„°·*•b½I+ ‚·öêJ1"ñ;Ÿ#Ž7{U÷¿ßôŒ$FBÐÂH‚T½ýa°jõéžžþ6Ý=úå(¼\ýÇ¿“KÒÊhBþxô¦¾Ê«×ì§¡:ÿI½‹ôj#9wñ*$Ù.ª ËÎÿGéõ®²^ï÷»mž_ßk]xÓù/"MÄ3Díâ Qœj'É¡6OeaÞZ ¦pœaÁÀÊözeïë•äõJáë¡·•9â~@ÝÆß~qÕî^i¿¼.ðò20~iHà—Â#eï$P½ : ¨ ‰õÓ­éÉØ%±ûN6uˆRÒ7¿ŒCݽ`º ˜náúðXÇuØ/{¹º÷åjòrµðå¼|HjtHœ9õF–ó±>Ÿ!ƒ¤·I!á®ñ RûeÔâïàÔöŠ…Q‰…qàÌì!ñt{,"T:¤Ã—áÑöâÑ<Ú~<¦Í\j“-€k8CZ O^½ËŒ½òáñ’Ç·÷°ÆžîNL¦Ù ¶át& øÞ¸°€èq‡ÿ¿½~›ú{¡õhýb6ub6IYˆE@mŸéÂÑÍuÓ°G(”‡äÿ_üê뽯¾N^}¼šÙ5òÞ öƒV<͸yÙÊôò¢•yÃuü®åa¿rå `1›Â½Héž°©Ãþc¹A‡\¸Æë7И ô<0—”>¹ cýÍ|¬—îêÐáÃò/8þk_Æ'Ⱦ¤¦ÿ¡^$âõžcéL NÝ™šCS0dÄXó2I*Ïwß&Otam;~ Ìw¡ã)-i‹yòi/¶O ¶A²:]>áÄ3™¸Ît:³™äp—…\°ïjÁò(ör(fW}®GýãXs»ÔmÊHX£îeòBÖ„b7gÝø@FúÌ:†#˽X– –a‘-³ b為y³˜ÆÊG‡é8• ×o•ŸêÀmô ÑÚdò¿Ìó™258b²3yÙr„bçr©M=&G’‘˜›L)Á§#XíWzþÕË8sÐË £%ò>Ý=ó‰7«:óR•éÕ^X«Ö(áI_ÌšÒ#,á¶—dÈÆ/Í%b( Ó¼ÿe'žx–I{3˦M‰ÏÓÃä\Ö7«¿×â<²AFŸ£uôC Q"ôáKøp­ s(Zó»èϯ¸a®< N 48 @Q½dD8Ò°7\‡Ë»o`}CôàoŒßCCk·cæóñVìE•³;±¾EÉ*¥zZcÙ‘ˆ€¬ÈÒ‚ëá¸Lõ”V4õR£lS£”§2çFQg›¢N9Š~›Qï&Þ"Ìù›•KÕKMw›šn9j,‡ù#ñ¼ÀsÙ;ê65j9j( %Ó¡Nèt&Ìô¹ÕÛ&ªwQÆø ‰Ò¶‰ÒZ)ÇvŒ‰çL)WygBU›ªþAKåXŽWA{àï4¢«’Øë'lƦÄè¤LN¿*Ú¶EÕ˜E•)bD¼ÿþ  n›KM93¨ ø)ìåü”Å;øéÌ Æ\ ·5hØ;S¨Ûz1Ôª‡šC¢à‹’ X Öå’{2Ì€´¨?ÑÝ#VTÕɂС¸Žoï+æÐtq4’ß4ÞFC 雿WË$‡%9@|µeŽ'q©½v!zÿH饿…°ës…ƒ¹Ê)ñÍI6˜=b^ZGàö¢ç·üä’U GÄwiÉ¢¾j!ê[¶yZÜLçȱƒjó~¢]¼SÚù#Ö¸V8± i–ò‚ûܲ7P+55)˜z1 N@.å[ü ¨dõ Ý~g‹óÔ½ƒcÏef˜ Øâ¼ä]¹”Å œñ8® ¶™ÿwÓX¦ýê¼YJ.þÁÂ(×g¡ókoˆJ £‚4 FG§£Ÿ5oLÃA­þLß^r9ýÙýÓ:œ‹ ùÏ_j&à ' ò$rO.dß÷õIɸÆÉ¸Î‘Q¼ 4J ÌPT/ ®H•œ"•$i¨Y°-О5#Ƶ’Ó>~TíŒ2xýÆãJGéÊ€yÊQ|ÀBËó´LòÐÃÁör}jÀ•¡ÒÏA>±DàÚO¹ŠµyGC&¶¥ásÿ›B‹+9åº-guãpCn˜µ¹½vÉ÷š(Ïn`Ç}ÂñJ —zp#Dñ7—ÌZ@ûÛl:§¤!G¸Éˆ$“1¼ ÿ¦±ù_£h \HG%¹£^‚#•&$j®yPX ‹B_IЃoÑÃgBƒK" à“;ãñþqÝ$r<^X)rurR/XÜD¯:©Æø.iŒBÜÌ‹OêFpYå/ÕKYü§h— X 3šÙFùú³+O€Gv“lMÄ»½¸^ìxÌ®(?…*=‹Ðøà&@ù)LÀ„-@¬sÔæ7_ÊÏa¾¤d÷*0"ødBNGSË€Û.å´¶ #MÆ(<3˜ÿû:rç/I`â¬Vw·wáýý_äWîúî9|ŠþxEFñýBµÂîຳ#éN¾;‹œžb+Ö ôwpÔQÊR „¤ßÇN JŠUj“„àþt§[š-­Ô$%¸vê¨%\=qÕ”_y|\\3 hþ•=r  ýþâóû¾®ÏŸý;=Î5ÖKF×¼Ýv6Á Ä´!q+*aøTÂK ª?-Þ|-.5Ê—-Õ•L”±Ÿ~%S¥ýŸ¾á½5ØV~î¾í5PÓƒ÷}€7„æÞ–.ÎêÓ$× P(Š"žê ‰K‚Jpè8ºpÊ‘ÄÜÉá#èç´”AÈé똭ìW.É'ÄLøæþïÕU»ÝººfÿºÎ¥ºùÇŸªx&—TÝ T©HÄ&ûM"›§]/ðSì¯íó¦¥Ú¢òùê-ßwƒÙø™WpÞèŠ5Pª}˜2„Oß>³ÿü(µ'ºmÐ!Q=˜yW8üô^àC3îÖëï߈õøùî6ÙΦýÛÌôÄHãË„*ƒ•†sP!Í'#Ϧƒj‡ö‰nH}s •Ûs“|Á¬ëzà´u¤•uOß ëât ¤S§ÚvÍ£ÙfCò5„+dAÕµ˜·È‡³uf’H+k¬5dL…GVy¯pÅÜΦ8Öðü«Ïgª»-êHuç±ÁJð™.\>(ûÜ9mðiÏ={¨ýN›ŸuÌÅÌ=s¸"êƒà³€yIFŽgPrÅkà $>U3´bfºÎGÞ‰fûÔ›ŸdN{³L<³àgbŽ'gÈ­Ã:ãàú_Ð*‚¶™/!®ÖJ3Þ̨v‡âå6]Ñ@ßyz¡œ{÷áS´†cÒZ+P°¡Š‹wðÈjQ±78Ùpʼn=—¹ë'wÕKZû§Ê½4œøb*0Æ \±‡·~Т?5? ƒŒ.H3âȹ5“RY!9ÔøÀ@¹É ;¹ñùáôf&äDÙÀ„ÃkOž'W3&˜S×ñ©ð0/ü¯Ñzýqj¡á“ð )ú!DZ0·7Æ—Bn2Óæ8ò‰9ʉÕ)¶Øp<&¶a;WÄ–¬¼áLÐ̘¤9ù©d#­Ç!®/ÂüÔœ&Pç`â³ëä†îäŒW‡¨%ºÎ3¥‚µáÄGÙ)Ò(;_ŸÓ³¼Ì;Nòžq‹¼ë÷Ú¿TPË›ƒ‡¶S–¿Š¶rÄ#î=sQ“Á±n2ûÖ¿± I[b3Wnël¾î(]†›A ¢tµŒneøƒÅ;ø)3Ú!íæ‚.”/šJæwË豆ªÐýª›4ÈTA$+°véê6µH:µ¤Má:+’uV(sZ†'+± ª<0¼¨CÉMoêT2.Šv)Dr×ohZkÇÓßüÄnQ?]­ÌP‡Z›§"¼ñ7’3$Ø ½V+{u"БA‘<~:CÄÀƒaô6õýfd[áj; r|º$@·y]/ttÊQ$|ÛÅefƒ£Ë1¨hG]$w+ær@WØ=rðÈ ›Òü‹L—ùí{Äb"ð?üè鵸·Ç¢ö882‡‘€Ú•l  ÜZsf½øPÛ·’m߆Å>d³SŒ°µ~+Ùúí‚Ú¨ÏÙ•ç¶ÜçÌßwh,r÷ZŽAF·Óo»0ŸË™ã™8L.qßö<+ DT|6®*žDëÛï÷Ñ7(Ú™ ö˯Æ`…ÿxEr·qT}4¬âs9Te?Ò ƒÌ[õ(ñ\°ÚÙÒ°<ßð8Lâ,öK†w3K+žV»ÈÚ¦˜£¼Œrèé!ýW9Vü²UÝÕbΤU„5±v•âų{jo?^ˆ7d¸|p_àÔQÏ â——¨Ú~´®å-p•86­~¿Šßk¢öy¥+`28C‘ÌukV­°âwž¨WûN¹ØWðVÝuÌ’·Å—‰'yÕkDB-†b³èµ Äo:QÃý(Ö‡‘)6¾‚žU+—xNTý„X&f‹#“dH’>¯(žUo÷Õ=c³àìK¥ððŒ£ºDl§)ãƒoVµ;¿DöCé‹5e1Ò:½~ïâ*R‰Ô×¹Í3¸iÏù·Ø¯†¿P{nzŽ=¥vS'9*ž_TE~q7z3Ïæôgƒø|µ1øXÈ¥Štc)øüį1äX¦Šüãnä~,6UU‘c€±l£*²(«k¾*g 7–`TE‚q?£ãþ¤Méž8¾ª9–oTE¾åø Àãù&u•ªEÿû×h=O(¸˜h2/"ýKCÛÏ1©«Tfaç7©LðÌ“ºJÕ`µ/£nfOâé'u•*¿".7«BV¸ê[¥ªo‹½òÁwŽÏ ìBTù­Rå—G×yÆ æU œ±04¨Î[¥:/ †÷ü"üYΘŸÑñ;Q ŽŠóªä‚¥~³S“2” ,ž¼ìȤ ¬w;¶èsçmzïn¢ &è hêæi*ÞÆ Mc^ж0§³éMõÊv ”’³$ „*’##óú0wc2&t8ƒfÉŸ u®ç .[¡Žo8®i4 û±ãHxd— t2‚¢é¼›FT)60Ávg+ªYq=@ %æ•L;¯dŠIYɸž0×—/cǬ’A-Ø `—ÉÀ#i”Ã+K © Ÿ¢§°˜’ã[Å_O/]¶¡c*lªƒS'ˆ HÖ»Ø=9ðÈ“Å$-}{ºí’!›†ØÄpÄUûeò Û-ÿv|ÆgêÍaÆŸÏ#A~ŒÛĬüÒœOJçw =™w» )ïß¿¯:Á‰Ù 0rÉÅè>|".ï€5ž¢õ*¼ø8;׬+ã) «a’ ãûúÛãº^œ¸¾n…Ãô›r“aÈôžñ%|`ì~]X&JZÄÐ]ÑÚ¼mÚ&MÉ“¦”$ªÐ¡yäͼ°3.)EÂ|hŽêÝxˆ¨hâ1C<^‡_¿ÜÝ~‹‡ãñau÷ùû:„1Sì^Ü Vúhfk.ôÛÛè>bÙNFb}k¬ºDÁòs"›Œ’‹§ö¥ŽáMÃ~½±EO2ö™jџÇÛ(n@ö\ê.ôÎ4•¡[â,]2–2 dª©LøÌd•pöVªÇp8T+Ðvµ <²ÃÓ ÏÑ:úÁ>ð¬3ı[Ψ^}Pq®÷ ½G’sͤö´Ê£J\ KTˆ~Š®Æ¶¡¬ˆïà§™Ù±Y¬‘ͽ¶Š…“ðˆÔðÃûm=ð˜{|îw½J«ÇþÁð±¤!uŒ‹t¬·@|?2¹`N'gâÿy÷tû¥é–”á?1~üÀªÇ¬Œ/w_¿‘¿‘ ºýòðxÏLJôMº-£å&ä'ÓmÈ”Ɵð? 9ž“W/\,ôêñƒ¶Rìæ9*ºž3öôé”…º ®††],CÄ7NI<J™ç÷›ÖKTöøÁa©U€ifÆ7â<þß5(Ïý»,Cu§¡ŽÜëuÏ0¢UÄWǾ8º—Lj¬à¶ ¾ b71ZJÔeÔf^ãvẴ]ÐÅ…GõbÇãûë²  ´Ê¹9ø!.Aá. úx÷ðùî!"Ãñ"–º¨=¤Ã8KÑ” …¸ …»d(K‡ÝL}9Ä‹O¸K|²° fÃUÙW¨ác4&(“¼„(É [^)|Ø‚¦dñðFåø˜=p¤+ŒKÇB¶¸Ú{#4|Ò‚ÖÉBŒ{3a2Ä‹yç @Å-hÝíÕMÆU Ÿ£ ©ÛPºñÁ‚9K„OQ¨qÓjØà„Å;xd{a7sJY~>C€)Dxd+™C…Oqд&×2ƒj&J˜ªÔäÆþAḜA2.gx·ŽnŸHZ%• ÿ)|X†ë%¹ŽM_”à‰« â˘Ó+‚×fKï4yš+2 èê<:dÄ4^— ‘[¯°‡è) <Âa ¥0ãºqޝþ‚¶ìc±7<ò+™˜K¿é3| ïÅ×x/¾®ÃåÌUfNêHÃCxk¹zKŽ5¼ZãmÔû Æ£ìÁ'å·‹ÔË»k¼ƒzdq1F­g^ý ñꇉKæL¬Cæë_¦·Ö*£¨&[•×ÓÉI%ŸšÛF¿™Sh'åç•Ín6¼úAËT?`~Öc³c镚Sé~®­ñsí"yñʼnem5~„]„“í9stÓ TT³­äq´;ä!&#‡¡PqéíÕÜmQ‚*¼•<“6OIšFˆëÛ2dù´¡¶u ?wÔVò¼Úb¥ÏFƒâžøÌ¢~ÜX­¼¶’‡Õî.Ý–¶¯o¦?VôñÜB_RÞèÒiî÷¥éü®õzúô 娅x¢–eº>´?êé@˘ŒXƸôžcíäXẬ¦=t>úÝ1‘ƒ…¤í÷¶aýî8ÕŠž¥ìç²”–ã|ƒòÞTš—ïãeûýíLsm§.}|nlÿ*‹‡{›¬r%"9LXî‚aZIÙ?n^·ŽÚlÐb]¼ëó< Ó,ºØ4Jç«ÐYâW¢ÊvšEÝv&Õ8a\Ð*È“nær­Aåå÷/£BÙ¦BÙCE\µXGÝåËðw¶ñwv7lžÿ&ëµ§<[þ“†ãäþAJüëÉi(ªa/CÃøŒh([P††!Üì6…¹cÉßê¨c,AQçe’•ÔÆç@YËþñä•“³ONQ©æœmŠâª–ø²Ÿ,Aɯ§0‰¥šYÊ“cÚÌ©Ö-8˜úÿöÞ¼¹q#Ûü*ÇÄsy\’p÷D½)´H@-Ot€[—®e©®¤*—#Þ‡y2‘ØæIRH°î}ÕØ"‰6~'×ó;ká‘“‹%w6ì%jKë04-Mç¸5GS‹JÇû®þ¸°c¤[je)¦ß˜r+«j.’ZŸëôkªªp§Ül¨“c5æ—éS¿Ì.lÚú›üßœ°nEe"æséSŸË.Äùb9þÌfÑãê“§û¸›¥OÝ,»Pi_…šœBŒÃ.š~ü¢]_`>>ïÀ„üæxˆ Üž2ì•1ÀÆ`›ë+Šý¯q õ¿ÆÔ¹à|Ú<Þ½v웋™•Þz&@øó;Ìï0¿Ãüó[‚‰UƒGXu° þ÷F7y—ªÚÁïè¾£; :´*.<’ÔÌ‹W{FÁaÁ{ðH8åÀð#OïTΩrdŃGö­¶ {vb ©Dèz¾Zd¡ƒGN3«X px¤âе‚,ÔÌôµw‘]â%—Ë´BÿlÓOOÏÅót#2~IÆOQº\w°Í 0[O~ŠÿSûõúƒ)Ÿïob îe_nÉÞxý¸yŒµñý¿ï_ãírj9£yRfõÄyË|²3sÆë¸\"¾Ê†’Q¥~­f¤ØÁŒ% ,i^³°ú‹z‰§1/i³¥ú›g…ðÞ~XÑè…°­…Ÿ6›õâm¸A[ 4:뫚²¢ UH©G™¢×¶æùª»S¬ZhÈŠÆ"T! FŠ)“ðH©žŽédfNÄýåÑU³% ´$Yaw>Aº„D°\šŽËk*¤M§fêKPŒÝFKØFÎ…?†Â'´‘½®y“‰Z y=º}–°}ª D·Í¶M5Âv#Ñ}³„}S°ÓBŒ”Á#;û%é¦FÆà‘<²´ÌHc›mOä!6{Wcë ¾U>õtñðú§Z:_¡É4Ú»]Üõ¶£ÜŽžŽ«|þi8/Ø•…¤ªÅŠž“«|å"VÖÿ°!¨k|=¬÷¯êh_Ì¢À¼vBš™”´|·zzxz†ŒÈ÷dë)]k|a¬÷/Œ|¿Cï…°x¾Â›”]0ëý veå$4½q×ùªÛ»Ð¿…áGïäu>—¹bøsßКXÔР×õ:Ÿ¾¼»þy‘)¢)Èè=¾Î§*ïŽ÷ cÖVx¤2ï c½pÇv@»óeÞ z,°£Ÿž=ªS‘G„GL’0y`µiµŽß¬:r³†4ɗКxù_ˆ¢ƒ#éÔ~ê±®ñ|öu«`bæ°/}òMkv{aÀ?sIxª+ o?¬ màùô¼Þ¿§1â­q#Þ:1âU‚mÔŽ·ÆíxëÄŽW ¶QSÞ7å­©)/·vwpg†=þƒº6¨;ð1åhM }8|:ä`Ê <Î*ݣ몭iuöØ®x )žü¿ÖåN6ŠÃ5gõûÓÖx öºsrxBöšÌ¸»y}~zúòæ]kv¥Ü?ºÞÆèR$TŽÞ~™66#S3Û¬s7XM½Ë›M¦8£¹öûþóý—øuóûiÛÚZ!á®ÜMNù›‡—v`åÆŠýÀsý(c€So¿ü‹0·¸‚²…Â5`ˆÜüûþåu“kÔ­Íî—ÏñóßZÒTÙsíšòŽYŒm¯[)A¿­.1n¬»ž²“CY8Öu(W[¤VDxá“­!»ÞøiéNëÝr0•ftlñr&Û¶ôS8Vr8K‹ŒUiÙÑ ”Ì£}“ª°îqÄ•€mçà%÷foÖQ wÓwjé‚Z‚+$Ûîá ¯î“CY5bî*M¾±'_ ž~µíI-2è2Ú«NÌÅ,ªËÿwÜÝÁ«»ÊÙ¯½³íKŒò3hZN©ZÇ8àX0áMŸÂéë½øq…xKâèéÓõýæ/î"½4ÇÞMÒL¤V4¸. Îå M;ÔSD+>58®¨{ñZÚ ù‹~ÞJmä‡us¶üƒÁÁèðÞ½8tíü_Îþ½yÜ<Ö²ÖÞ ZAïg(oΜ©;‡¨y=ð —”`ÿºp|úÊ™óÖÖ%š}Ü 1ˆ_[†‘SbÚ¶ PG·à+‚ø!~üãÌyÕÂÕófóÈ>“yÊ8Yú®ºHˆ|‚>TÕL6ÌhfºWu·õ:N"cW"C$QE@Þ …Þ$º1ƒÆŠ'¤hïJÑI‘6Zû¶ÄèìŠÑ‰Aû©$kII;•ãÄèîŠÑ•XS¼¨"4Ž#Ûž¡›m4-©·+SOf…}ÓBõw…ê‹„Z¸tµ±mSCyÐZ„ì 1 ñ Š0Üaˆ]+—^teßÑ[enº@ϺUvÕ C¨^Eõ‚·^–mh·£Máo+iSþæñõþóŸU¨æ¦u t‚êš}kÙ¾´b—J¾OëlÓ‰š4Û uÒNx•DžGì¡b‘-WÎD‰ÐFÈè)’\(¥7ÑffižoP­^”ÐþÆ@¹á1ÇdÑZ‘¼ jÅËé× IhæbÚ)$fû`3ÆÕ Fh.b`:)B.¡Ç†:4BS CCnèÉÌóý;‚‡Õ&Õ¢À<”¬ÔùµÇ|hTAÚW”ž k'B;Åñ•Írc´w·Ñ{(üVëü 0 m¿-5]À‰D $’o¦ä 7‘B XaudvP8¯Fß Ì9Ñ$cè[ïo#cÐ{oyîõ{?|o‡cç}h…N­H‡8Rr_šA:ª¹Ò„Iq­¹åoœè²B “ n½ûXhÛb€ã"`zôÎ<ˆMÏ_L‹×Ú¹YŸkÅ'̉bø–E|ìn  0O\†¶}æ^ënæ@˜bh„r ͺA 9Ç×ÞÁ·pžBlqŒN-<]@þ§ðã¼Ñ›à˜5æ.‚äÎÃ3ð¾;ó9aðÜÊû“æÛã½1HŽÍ<ÂYta zàÁöŸž_ãåÃFk“Ͻ>}z¡{ÉZŸ4#kvvL²ªsöq';†K‘ëõN³cZ½|V\²cà« ²Ó*à‘¦1—@ ãLØÒÞ¦¡mÒ•}7ò Ä,÷'EÙ6{ãw’ˆm…k½+Œç ÃÝ¥ñ{Ø‹}ë›´6„(DïyP >q¦ –*£¹‹ùHU“g&ŶJA)̈õñž,•ÿ¡E›ÕÇǧ‡§ßo^´{Ýn»õ#W›|/ŒÊv׋œ‰c) ´á"aû9X$Zþ“ùÍëT'$\I{ = qÉäísÇ­1±Ž!Õ£A;MŤe-¨zIµNúâk²²YØgÍ6£® :)´zwy|¥… RŒhm¼…ƒXŒ ]¿¼Wµâp æ »gzÿ_‚ÍÂÇ ‹Â\k-C(ŒMf{¿,– @Cˆ~îµ<ÿŽõÛãZ8ܤ;üR4”ÐЄdíuWêD&Œ"fȆ9dIñ´ÈƒÃâÉí CÊAâ‡þú;'éhªXÏCüŒêp¨¶¢~¾ uAÕr c| ãV5HÓ­æÓ³ÄÍæLÉ}´,e" R˜ÒÇ@.O>’ÿ@Š;/R«Véx+r¸Aÿgš‰òØšÑ/JºTܤ+|_¯ô‚­†r)~,ŸÑQÅ”&úʔ֤2Çã°´ëR-®<­ò–%%x‘Öj1É©=öÒR: ün+\‡Zå L‰²9§øXQyðBŠ’p¸Ú´ÊÔ¦EQo¢Î@˜mÈ,–c™³Y2ˆíÖ[šÝÖoäŸÃn­¨qUjÕ+Ø^2s³`¼p¿Bî´8\ÅZõ÷Z*’ÝÄt›³¹éœ1#‰×¼Vƒýû&óÇÖxS®|­ˆòõ¸ù+¹ÿWû?ß?}~¡ëqÃg×ò¹2Ýfxµ<éÚ¬’`…ú l\XŒtΩ!mØå.%JAý»µ«ÙâÆ¥ âÈú¬Ö J˜˜Ï@­êuœ}hEþ‡Ø‡àÄÎ{m]šãsûÖ>>IrL…庼OÃ-¬2À@m~)ƒp“Ј“ñzŒœ(ш¨©¼Nt¸‘|µ-£Ûá÷þéòvEå[¤öYüŽã;áÁ‰yú ÝiÆÌÓ×j°Žo?´høB-\åÌ9Î3ÂØ­ÀñÁÈžÄDŽÇÑODO‰Ù6FG¹¢Ö¸+jM]Q•zþNÝâŠ:V,ÆkMß"„sáQÖÖ:ˬ}Ü2ãDÖœ€H7~[D 6þXˆ<ò¶ñO“,ª/yÚàV¶uŲ©ÿÔÃiÿºÝœÜ¯w¦‘ÏË»Ð!|9_‡‚•œHNºwŒóÓ‰y^]õÚjœõC{«oàÎÈýÑŒmæ<ÒÑìCÕF6ÇtÌjÚ5€ÖË w.ÆÿNŠZ¯a¨eóH¢>f¬k†½½m{»·í¯ r@Ø;°]‹ŒœúlA½ô~Ü‹¯ÇóârÁAp‚‘axW5¹¡í¹ÇóÞrHXª R‚GxÝõxr[idÂKg±Ú ub^y=ž4–ÃB«‰€ñÐÒh­70„í™Y“u‰Þ=žƒUF>Z3xWwö%¼âz<£)Š(Rv¶Š4ÇÍ~ååÍ赿´ÍãGíÍßËõ·€›ùÒoÈä2¼’aZf{¼~êîQÁ>rc± %ñk„%®ÉØã5K°l÷Ò$gê87éïÈÌÆ«ÍZûƒLîËçOŸžž_kEqÁÆ/ØXyÌí­/~ ê»Ç`¨ÁÎCˆã†T Õ` |-»kA7Œ3Ê*|E6¹Z°øJ0ö­„SAƃ±»8Øl-@LÿÛðâÉ­p,tÐPÀqü‹æG_¿~Mº½¾#~°¦æû¤ý{¢{žŸŸÿD=œm3À“^ku@TÞÞŽ¿)é'Ñí$‚~ä«_4ëõùÁ|xÕÌ——§Õ=Ñ._  šoΨœÐ*«u¼KB¡@ýÞŽ@ðU¥@×ê*â—oìñòຟ›šÞ2:€ñ,üûqõގΈ×ÒVC¼yMµüß<?Eõß-z¶ôq&ÒçLÄèKR&g]šiÕ–mÞÇ©HŸS‘ J®N<¿Ö Exâö9 É dAjZIFŸœ^ ÊÔšáåÂONRe[‘AÂ'©±J3ZÁÛ0¥“•bÀëö¾~ ±š¸3{¢4žÆÍ¼£9ÐYÝšNà"  µ|Q ‚€è ¦OcëÚ+1¾mc¾miÙ…du2TðM8„Ë!æ{6ÁªÃ!ܰ1ß°¹ñlsvF?[Pž‹ý¤ ;#Æ- 1·$䆩YxB{BÌí ‚Ñ£J•Á2ô˜3tÁè©…'Œ‹y››q«øÁ`™\*ÅØ_R>£ÍÅè\tÎ[%Ã…å‡7êQî¯à‘¢ì”Q†vSèö—µOÑ%Jj'kaÌRâߺm0hû;ΧеËEÁÂæâ!ÕqŽD¸¿ó|Š(®7÷ë§¿^hÝ42±ÖÌ6Àý¯z/¶6N…ÚÒÉË­z¢Â/5CÂ9P»[‚¤ŽµqÔî•ÐLÛf×è›–ÂõŽ‘ ²šú­üýÿû¬˜¸üþ× YuñÃòœŽD»¿ºUŠVß6¬íƒI&:a”ÆùWÚs«}Þþ™æ”R¬æµéÌÆö5ÃJZ()á¾ÚB²ç„pliÍ¿Æá¿Æ·ÿJBþWIœ€¶¥KC‘ƒ»³T½9´0¬ÜË#k³{#̰‘KV¼ëøáD¹=,,ÒùÕØa+41€„‹ ¨‘-µúVÈ8•nÇÈÁœCì¹w}È8én/ ­K9Ìû‘ôöªD~i”˜ÀÆé|{]€ ñ5 İo0âÎüœÜ·7ÅÑ„H 6šiLFxpŽßÞw‘mŽ“M”ÁjM=#Pû©>pÂîœ \§xÑS["E—Yk'»ô„Ý.ØÅáÎ÷ŠâÎÅlÔ8¸M cÍBÛ¾Ú9xèXú^(_0KNg’YÌbpû¡Ón•m?µ‘ÿâhI¦ÔŽÓ;í’h]νq:ß„ ˜5¤C­!óð Äè§jÖÜæd3ïVíðóÅ0äÚn³2>|ÕmuÛy™Fþø*“éÜhiïM~ʤÎf¶;.3ǹAXõêú'êÿIKè1¶­A ›Þñ¬hÆM›IíÇzt{ (ºË;…]ΆE·r§eTÍîü,<÷d¶MøÁu%+¶+O>jä3åO5%X¬#Ðÿ­­7_îW›ô˜Ê· :tm†p (þ4„øÁs ÖÅå½ û[À›t7§Pþæ<¼ƒ.QÁtìäckÇP©\*˜å©Xç©öxÊe.‡]~™“SæÿøÇ©Vºœ4Õ+=,¯t"Ç·€¶j[þ¯ÿšOí0…@fÌ à&Ûò`¨G®iÌÇïæ–l~3bîxDtœ 7æ‚Gö¨N,ïìíiLDÌ9ìÈl8Æ¢—£då%IqP$$«Ä<Ä19f]³B+Aã€c1`VKAsÂÐ.q´ËJ´Ô¥Cô `jÍÌü‹·…€Ëé;­ýݸR)V\ŠÒösíÀ±v5¤òiB¥·È½‚.-ìºïRuë©2èÄy)¬ÛðÕ/%¥Ž À¢r̼)m}qíÍo‹D«EŽå®K)9Ò߆ ½Ý 顲p¿Á)éíNI’D’omRV»¢¬0Q@U`ál3³þp«7æ*%\ïJ¸Æ$´]27´#AšFüØ+EÜ슸ÁD¤‰¶áé×äC|Û:ì·vD€zÊø:侺¿ñ¥Ø×w…Ôe„d¹ÚÖlª ®!˜7¸&°Ù£ Dé!ÍB_禯éGº­D6ŒTÇ­í¼T@7“•².®ËôM–Ц½cº¹\ù·#‘ãæw^Và ätÔß¼„öët ÎÀñÂgÞá…?s²dp6¤5Ããþ:½20ã÷Þ“¿&^`Ù'ý -¼Öé}ª7ã4°Ö`š0<æ«“FK{ßШZÖÕɇuÑÎÚAàZ| ¤DüÆa0¦ÖHÔœÕ)gÙ·¶E—Ôÿ†`ÿ h'C¾\ÔSøîXR¿Ä•Kn¬ìòˆC†<jt’ÿ¸Kpð¸·Îª´ö–åùÐÊ‚I—Ñ·Ær–àáñmu)&D{G^ì´¹v W²ÄìâobàèûTd7Êž@5Ž( ×Ùî „Ê?ÀÝ:@õáëâÑpÝ, "—Š”à"Ç’i ΢’Ï¡ÏSjTpºx\W¯‚:ÝuZ#TÙÛŃæºÅ0ƒ]y~ÿ!¼ ¯Í LÕŽ™CV°7¡ÿ®1'²‹çÒuÛU#Ns5gpVAÍÛü¿ÈË'¾ý6.¡ÆqºåD%©®]\#ïv«†/‰p&û}6†ÚÈÂĵônQKg›’¨Ý´x“2&ÖÅStºýÊ0ÍCmf†Ñ¸M#Ûe ò­)Ö^Œ9v‹I:á©ñbq8ðÏFüÊÓu M³`RVÑCñ‚À"àIÀp3øÐ ¢Vçb,TÙAVñéqr›ÝE>É’^Hdýj¦E¯ÚÆ–/¦èÃ#{0‡§ÂŒERÀ#‚q¦7ð”Æcqðˆ`ë\Bˆ[IºÜJr®§Å?  ùWbÈUbƒ^\‘=­ÑrqÂn Þb>Ò §£nVÚÅ-:Ý4¨#MCOO$JúÔ$:J"³???}ÚÄ|ÝeÅ.¡*q­¥*ÜBÕ ƒš¨}‘=÷½À$ë°©´¶.n¥ê.« B}ªšù(n é® Pcþè¡´¦|VYã‹™IÈ1¸U´DãhÈNC²œÖÛƒ¾µ*A£úèôQ´åÍç­VÉÂùj.´ÉÜ'ÊIp‘0íØüˆ¨&»ní²ìé!‡‡}nßÒ–gYéêÑlGåD¡zíº¤-¿8gSÂÀÝt¾TŠƒ*“kP&k礫U@× € '½ûÓ îÔÊcC ¿ÊÉB5Ò5h¤;B´v eÅMà²ð!:•53‚*^*Å@õÔ5è©Usñ¸yýëéùÔ¼Í|yÐ-iÝ;¯¥~Â~èXX0<‚AO‹†G0è¬ÅDxʼn+ ¢oCez0 †GÒ‘öøPçŒ ¥Ýºg‹*42üwó?6Ü&Yq¸ÌMðéØuëÙÇC¶ÚLI´.iÀxˆr2YЖmL¡:™vp¢*Þ&«¢·Òµ£/¸JòÝÂO:©*v›¬fÞÎj9hT}Ûd%ôvFº™›gƒë^îå¯Ùf@b®`r+8,øè$YUE™â–{.zG@ÑS`»ç(hÊõßÿÛ=ûŸC­­âÌ~ŒèvßîÙîI[ðܨª„‰nøm¡tfqæS­ù%€“-OL¤æ_ÛeÊŒÒrŸä(騶òVé±Öƒ«¤‡‡£ôZ%óTM=Ñd z.D5ÓviA‘@óÍè²Fœx,JO/à\¸ ¨VóºÓ×P·†€â7:ù©Æ@™cÒ3vÌùi„L£l½õð’K½¬äÒ¹ÑÍûng¶=ºK9]‚ߨ$Ìž±‘ňš \ÃD‚³L•ȱ‹¼—Uˆ"Ãü>/ ½òri˜ýÔ^Ì~JÒ·•Þê=¼&T/­½ƒzªu &fÔëäE)v.IM«–xWæ%­GPkRAê¥jq{dzÇ+†6ì:;u‡—%aeWǶÈÝ|^Ëô.µ6™^×À´;xdÇú•H0¶Y€¯ çøÀ†:gD P»³Ã ׃Hvßs›©€+9U‚GÄèk¯SqüT`…và±0*2¸±)ÀŠîÀ#¨ëMë>zºXÀ'<‚±*Ò?³Õ´úz/Ó¬‹UÊc·f€‰‹¼‡oõÖ Ž^9[iºK°£wƒóöO9%©þdÌcä1ÊòGŸ“Ò¯5øt‘ÞÃʘÂ#È¥öªJøO²ÉcÌdàsÁª56âJáºFŒì‡ß˜_­‡§—M©†JzñÎk–Êecfx¤ÀÉó"嬜Íß";¢àºSÜFEQ  ^‚GN  [‚GN WbDHÛcÁ9éRo¯ÑvðÝgzò¨B5᪕’“i¹/¬;³úô² ×J`§-ë”f‡ÄX<‚-—•œez ÿE%hÜR#–’$‘³‰Ûþ˜¨~"@fGUFõxT¿„6.F6¯†¯ïÂGvCvû«—àmScìʆhʬÚè›å*à û\ËÍk à&îYªxÕ/GÕoZ²*SI:8­6A#TæKôñèµ~»<›3jT_n^ÿe}û£´¸Wjm"_ž‚<´Q§ ¦í®ÄºÆ›·hóÖ}"REvnÏóýäMVyaœª·@Á²av¯í÷ºO62a\2o™d«&5ÍÈm¦TÂ90=h@Ûzîß+3Û m. SjÅ_ŒÇ:Š–™jä²]$å@áU9½ýcH6.pLG1¹QÓÂM`¸Æ;ì7 Wn‡+·C\¹fÉrŸ÷‚"»s”~e}%ØR†¸ú;ŒåÐ fQY¸ÊÐnñ ß&É‘_ üõùG;Q2={ÎŨ]ÑÜâs¾VàLu$Ò•Ðàsº›CƒS–í²948WÙ®šCƒ”íº94xšàvÓœXl·u¢I_oÀ›ö¾ÙÐØKi}Lî0àTŒÆÇ$î¥ïn ßÝοÛòÜ(ðfgÖÿkD´¸«£N·ôýáû;Zrt4+ ¿aP§¤!¬L+z‚®A7?»n?íÝæëjóéUû?¿Þ¿Þ?=¾hÿSkóÃʦ}ÞÞ‹‡¼ûÌhuúsícü¼>[ß¿ü‘;UOˆª·ˆ¨S´î1’CS=F ƒÔÂêç) œŠ02ïh?M0Ç÷îðݾ‹é.¢¥}àgLã “·÷ö¡ðíCþöañíhCN2=v ¥ˆS41§–â25 Tu^;Œ(¿öÔq)Ðôœ ß^¯Phrˆ¹k¶ X Ãbî—= ^¨µ´è2ðÓK­ÜR[ —ÚR+v¨¥…áT½ÈÍ!Ë›r’/Çñºôm+áÛVõ‰µ¾h}ô‹²˜–^5úüüøôùUó>¿h_Úç-Þd†¶ãáZÆÁÙGa¡+yÌ¢fVϛͣ}¼ßl!r†Â¢îÒK‡¬\Þòx1™Ø’ÔÄ-µÂ ©çü½ðH‚|ÂjÐâgçá]¨½|þôééùUQÐÏ~Ì_;Ǭ㘉JK-ƒŒØ«+ÑÊQ <ëµ£æQ=ÅRtýëÂVS¤‚ÃÄrøí"|^¦RŽ)O´g%ßYUÈš müRT*½•›^8=ª·e…Ó·ÛT0v =}Ù<¹¬,3ÌuQ‰Wçu\‡.Òfæ@ó=ŠO%qÒqU^ÇUù¼…R%X\g×q½ÔQ9¼ #äqxò–ºÆe\ \‰×q%¾²ø$ìÌ…-–k¯¬2—Wåu\•gµéf3;ø1¤¥²CÕ‹×áu\‡O«+µÜ:®µë¸ÖÎ+I‘V¾(p-]—ÐÒ à;Û .²»gb‚…©vkâ ºŽ+èÜÀ›xŒUâŵqׯ›Š«á:®†§×c¢>)=&p­[ǵîÑ’4'µB \ñ6pÅÎŽz£&¯H×¹ Ãy¹…¥²VÚ6®q¸ÆæKýpëŠR׊¨ßÇ«ÛôØ+6]SÀA`áJ·+ÝÜØàaÛ3SéâÆun×¹áe죰Ö ×Í*ݼ½kÚRìá2põÛ¨R¿‹H™S®¹JÐ|¦q|øªc´ øGþ‡Nµ´ˆŸ¶r gbÂ2UŽ8®oUúv1 a€ö:ª®qUw{ç‡Hgº¤Yèi•ÀqÍÛ¨Ò¼‹ÀßÜþ C‰ëØF•ŽÝÞµ 3¸âØ"ÃÀ•l£JÉÞ\ºÕ-µ¦z׸]»¢™"Ôa¥J E]è­T7pÜØUÀ;ç_wh:ùúÚh/.Öœ=ä¶_JÎwüjñ— Kl!u¡Òhœöè¦þ„ @ É»âÖ+`¼·øšïù _£…>nVøŸóU©‰n–Wãè÷”WËÐûO/¯ xÖJ“êUì÷Ð l[áVãì)¬–IÆ_6‰¡yÝv”³uZ{ rd؃ÍËëÓ3‡•½À®;ª×ör-£[ó­w zííø* Q6äÅZ©0Ë|I® Zs¹ï¨›‡î^î•ÜËiYå?ȹ¡6"Ï#dΛzZ¸ð}/PÙÚÃÝɽ’;y2¯÷Dª?({¸¶WòÁV"&Dߞ͠ì¦9·Õ:z¸÷µWò¾VCV»pGkOÏW/Ž&uM@Bý6„ä9û‰Æ"ª5¶õpk¯äoÝ•"ü.E-R QE¦7lÉŸ(fû„UX²„a ;M7thžÔÑê•,RôšÌcg×dZÿ¯Émõ¨ýÙ"¤È¿ç-Ú¶ü[ ÛÛÚä™×fdÍ üJôº‰+âö‹«¥H¡/~áÏÌ»7äµ(zűü{Ř;¡E®OÓµ½Eȳå®Ðc%Àý@1ø k%õË,X)À6jÌ"†8‡õKë\×5ùìñ£A¢**yää Q¥”HûçœþBqA"µ8`RW{“Šú9ràp£x8÷w%«fy ÅÌeðÈ^¤,4³˜¸ž—²ÿò0•ÞÔqÇÖ>6ürh{±e]*Qðü1 ¿;Úäî(¬Gšo˜ñðr¹òòÇ)Ä=<`»G¶C+pCóÚ8'ôT¹U@Ü™oË;ó9›çùýËËýÓ#7ï7TÚ[a'%ýËpÿ¢qÿ¢K]U켄ÇhþY²?#¾µ'ḷǨ;'·ÇnÑ.n‚[¥­{Ûº×ûJ:&9åå\íFý:æ‡G€æ[XµMÁ.õÍ©Ê< ‚sžÃ#‰0m\ÌÑ,Bн¡,# ‚G*ëÎ==>ü½OµÁ²ñírT¢–ÞÃߦݽËG5ÞŽ·“/åÒ"ü ì@ÁŠçxy¿º¸Ü,Ÿ7ñ‚çø¥Í>É ¯üØèà'_ÇaGŒt6>Êk’l¦vm,[è-¿lq6=“y¶N3í´ØJ†Gö£-äp)J4*AÆC–4d€‡Í·ÏÉóÉfOÍS”úŽù;æï˜OŽ 3‡GJÕë àøãqiÒÍ;ŽÃ¿Â/–½X®§æKüeÁŸÃvÓ£,ÒÓxÞoÞØ™ß8Ñ7 /·F£Ðv§þ)”‡®<¬˜òÀ“ñLwâLÃX{Ú7f *€¶CøªœÁf‡I[ºF©QÑ 7!ÊêKy ˜ÂäP²@Yp/ºö Y ²ÕƇ©çðHð‡¹ã.";Û÷é(ƇÙà‘Ò,7Š«w”Æ–PIªà-T¦‘“wc×%ªÝV؆Õj´†+ÿù©0÷tѵ[R(FN FG8¨ÉfGDå=Ó 5þÙwIï7B0Y±.:@—&aô”<|$0áøt`|’0XÚBã,÷ÒV¦?»Õjÿ_a¥ýÿG®˜@34ú¢1õ|XÈ;ÌÅ,=‡Ù!TÚ²ìP{gOÍ÷×Só'%'üµ»Ù!¨É °CŒ|†rŽÖÇûO/ÚÿТÍêããÓÃÓ¿ï7/Ú½n·Ýú‘­„3–0À¬¨žšŒáïw'äø©ìéåãý2ÖâO¯OŸ^šâRŒû]_)F]€QËú‚(+}œbÝoOH±Èx†Å/<òKÂi®õ–BËWŠs¿]!ÅÙ©}‘¦(Ú³©žMÉ©™ˆg'%=ˆæÖq§Q ¢#Ñ)ƒH¯• „Œ½Ï—%hµ>žõ'µw¾õÏrÀvWOp§èI5Ò:o–]|!¾ÁweßÑ&T=ÈÕ†ÙwQ`ºa¢±0Nˆ¡ëw@ׯõôç§ø?µ…Cô¡sûÙž»o2Í‚„èX³ òH wwÚ†ÂÑî,+°q§“Z¦{FcòÓ—ìÆc&±4’”_[ºèBµ8¸ž"G󟟶Z..~Ð|ª Qrà[‹êƒBîu/¼Ý^WBià( Y”¾:oÏY(±©`[pZHç\ÉHöp =ñH²û…A ±üâZ!öqˆ}ˆ—« ¤¨v]r€Oxz¿Á\›Q8#(ãaFjVé=‚fU"RØïÂŸÈØF—ôZáŠzó&pã£àò8 5°Em9Ø!ì(ºKJAÔ‰K 2\̓'Í•…"Ö9mLÝ"Ðñ J_PjX ôZqãW–.¾²&9à E3T3~éâ ÌšÙfÀñÒ ¹ê —ÞÜN®·ZQ‹*ð&¨;ò¨k-ÒPB*4V0¤]TƒÉUbý°Þ^¦WtD=°sǪ6ƒ"ҵĕ]¬¤uøÏ¼É·øEU+R\CÐÅ­“M/VéH6 ÙH̹›I | 19cÕ'Ì™̹M÷°×ï›5½"…WÑš^‘û®"J¿Ï’&úa®žðÎY IQ/Ye°GÉ33ÃúòÉÒ’H…·ÌZHŒÒ4ÉqBí 9PÔ—µs¨§ðzY ùQ‚“]ãPZ—²~ Â…Ýw£$@¯íÀ™Ü%K“Â%ûÙ"ë„)¼NÌ}×IÓõäê´H^k!¯Ü;n5™ðêX yenWvÜ5²·…ÈZH1¼!;…Ü1µ[²NšÒÄ$ÉgàJÒ˵^æWãä–Õ:ñ ùåZÈ/s ¢9¼KïRŒ7-q Õ±¨[ ¾oˆ²YÐ,ºB_q|ÅNðkK{Þ<<­â×ͼÖc;üõËý毆_ëŒæZÛè´ÍŸŸbê)_==¾>?=hŸžŸþýÿÙ0 /¼0 õòë7ýÞCíñ’X½#¸LÞúí:~\ožãøù•1Ff§ ßÚ>~¾ÑÂа4iÞ”{F-úý>Û½~zÖ*©1øûݸ)|c/| ‹¼iÒq½ß›‚n‹@'µS¡Y;ÍÊkò~Ïn ¹#‚ ·‡ª4®äþ€ñdW’6ÖcuÂÐîÃNÑöDhí±“¬Ã–mõ+Œ9êêì€Õk¿àŽy­Ò î@u\p§z¯0 «k°÷µÏû1¯ÅçýýɆ¤)l—n›ak×>]Ǽö[’¦° £º†­SûtóÚoyHšÂÖbë2lÝÚ§ë˜×65$¸±naëÕ>$Ǽ¶©!é ±õ¶~íCrÌk›aÐ\wÀ° ª‡D3ÎÞϪ_^¶Í<}^>lÆ’!úÕïƾu‡ì½CEBK½¼¬¯$ônl¤ÄK§aHã ?¿nžµésüéãýêEs 0ê6^m´wäÿÇš:rÖîjÑ…^¾nœˆ¾Ç÷æ—z{Ya®aµ-…ï]&Rïaho–Zêíe½³©WÂ÷®©÷ð“7K-õö²úVƒÔká{׉Ô{Ôü7K-õö²TƒÔá{7‰Ô{´å7K-õö²¢SƒÔ[á{·‰Ô{”Î7K-õö².óÆk¤'4æ÷À˜ïÆËåý+­â¡UdI¾9ô,ä%Ú¼×¹ÙUCgêšÑ"8ÔXxòoü¡ü£ÏÛ-ŒK[Õ¸ÈÙ0{:êûèé™ïÃó#gnjzËè@)γðïÇÕ{;:k“_µäÙm^ øß<2¼*sÉSØû)l]¶Eûª0ô Mñ)øý.¼! ºïrµ÷;RðÆÖJèÛ€ÔÞÚkü~—H ¾[ òøvp×ÜÂÞïI±ö¤Â+C¾¿LMм/œºéû3Çb¹*ÇYŠ5˜ÿàð‘÷&ò·ä~ÙDoPƒÖ¦˜Li,H@ïÐ6Zøý‡É”ü×Y¶úï?ИTê\];A´ ¯e ›ÊZ;¤²n%#»•$e±æa^–™7%«)/‹öúWªÉºOEÜUFvWIŠdã"‘GK$¸ÊŒì*“”è—èV¹D‚ûÍÈî·*‰ôs½õ¾(Õ"òàR£RÑJðTZ'áæbî…‘6±©º¬&=JpïÙ½‡OÓÈ£‚@ðE^ª)ù?¹¢íÍ‘šæP©P‚ ÒÈ.H ¡¼[*Ï80o´… Ù76Ê´"Ó*êT’ !¸+ì®”blûÑ%•$¤Ñª ~mäcòü3ŽÞ˜‘ #¸8ì┆MÉ­h—9nššýUÕR†R",¢ÈsÓ}òOï.ŒëJcßÓ(bŒ쯽–JËHb™~)t©,;M¨K~Q§‘qYöWfKeYJÉr9…p&* ¨”wiB(&b¡NDApŠÏäýÜR™V’2xv„¥ÕMhw³æÔwL¤5.ÒZJ$'°fvÅ¡Ì~P+ÄþzÅ©y!&™ ʰ¿xu*Ãv ó–‘Š0sü¹é–|ç1÷… ný3Â)m_­^&èHÈEÒ÷Q›]‘Â+¡LäwØ>DtÅBáGßÇqŠBùºH¨‘©—'8ú>‚S’®û­“é4ŽË“ŒCßR»™tœãèû8NA(oæav‹:óÅŒHc{‹pvwf^›ÎŒ¦°çÔŠ„“}É)‰äßù|ÝÑ¢5òHޝN‘ÛU±48»Ñ÷±›‚4ôªd tb‘¼¹´i%PªÀïæ„DÀÐQÕÂ0 g7ú>v“jl†—Ù>‚OdñPysDyšÝŒz ã\GßÇuÊ"öl¯Tä73ºnJ(œóèû8OA({B7>SMC𣱓@»6g *ûwí­Z‘p¤ïã@%‘à`Gù …u1ƒýšö¡bÅ9n'ªªç§2álHßdž 2‘Ë•\FvIÛö~Ѫ•çAú>T–‚/‘¨ a4Ö|çÖžiÁÂÕX›oÅJN„ô}D¨B(¿J*ß´®ìœ`Šˆ:N„ô}D¨ 9ݲcŽœÕÎÉÎnœéûXQY¢2£È(„íÒþyDUÝ[­@8EÒe(¨Ä'šæ‚f@\C†0…›µ¸äèÅê4u³892dÈQ"TfP<©P8C2dµO¢fO§G† =ߨÅ»‚óã3S>çG† ?7»¼œq¿…ÁÀ©‘!Cì©IçRö ­ŒÉBó‘fZtûGÔF+q‘pbdÈ#{6sü°ÊȘüÒäzÙ‘!ÃŒä»6Ç¢HÌl¢\(œ2ÌÈÌdšXÉ6r.ð5×P(‚"C†M̱í0Ÿü ³q錉ÊÓ€8ÿ1døà&›>“Nউ…rTµ’àÈá@°3RÛ­¸x‚……SC†úhãœ,PQ65'&a;<šB½P8ù1dÈÏdæXcÏå[êhÀW0WŠÀ¹Ž!Ãuí¥mŽ©´Øùæb2c"hð“¢¾f©$8É1dHHRû`±o³|äXsù”ÊÔÆ¹N[†ë€LP[†ÊD‹ÌägG­8³iË0aÇŽã‚©z½ XQ¿f&§5mZA-ùLϤL¾R‹'1mCñ_9̾TÍD ç/mþ2©r–:îu•ÃT¹‘£s™¶ —™Ì<Éô/v÷›äå´ðb7 ÐΩjæÜÆ™L[†ÉLª¼¿³Ô„¸3™¶ “®/éAÀ½qð%k5— õÉÕQ, ç1m3!¼+SÒȇ4¢š³ëªV&œÑ´e 9¢¡ÚaæÔ¶§s Þ¤aMºó›¶ ¿x€X©O‹ ›4LÕÆyN[†ç)F¦{• <¸žšL…úìI|xB­88ÕiËP'‹F ÌQÎ@HV]¨6NpÚ2‡ˆË«b­Á"Kì4ͬ5œñ´eH4K´*\@àa·i£æ§6Î}Ú2܇ʔ¥Ÿ4æ ÉeäZ¶6wÆ®3½T{ upÞÓ‘á= Ohô*GÀª*ö—Ê‚ Ž "ðǦ•m¼—œÕLàQg=ÖC ¬Á]*h¬;Ðõ„'@DÐ_¦JN~u%†Î\l˜»P”fËEÂIPG†)2õš†z$ µ&¾µbà´§#C{@ Êf&]NSáEœötdh‘áÊÎö µ{/Â(ð®_8ÉéÈ|¶ÙùEàê™Ò þD™…M­H8ÉéÈ"ï(m•B” òP¾up–Ó‘d9só6Û9äƒ3_ÌaÇ,æÍj5œçt$y‘ânG$²øš•g9I–S0Pók'g &÷ÍH±½½ƒ“œŽ$É)\¢;\ºapšÓ‘¤94î®tñ²Æì:ÌS+ Nq:’'˜Ž*4N 8!·fTOœÝt$Ù͵cßää±oh=röÜÖfÎÜQ,Kg6]Ifs]Ø6Iœ~Ãû¦‹“›®$¹¹å©É Íß…mCžŒ¨±üJƒ¾OÎrº’,çöŸ^vå\zóÙ+à“NŒ Ï”U+Nwº’tçöŸ‹0ª ¾'§›%ßèhip¦Ó•d:·d*RaÒ®ˆI)ÓwÔŠ‚³®$Û¹«Ü<¹ jhûàt§+IwîòÛ'=šß<8ýéJÒŸ»ÂæIEjpë༧+É{îD['PUs‰ËS® Õ¹\$éb„½ù„¶Ý¹Öeà¹Þ"ÔBoá‚/qn3²gjì]œèteˆäòôø=B©g8]†C‰ôh1)xD#{N´5p[3žM~Ÿ¨VopŽÓ•á8pèü–d‡ˆsˆ_O>""ùw`ÿºp@uÕ×»8×éÊpÇu"^— þv̸«í[ßtDŽ簮•ÐbU­88ÙéÊß99qÒb&ÊåÀYNW†åvþûÿøÇ?´¤N¨3÷gt]Ùcµ=œÝôö±¨(¥==>üÍ÷¦oÝ"=ÈgõEo‘¢<·U$²›Ü =œ£õd8šã†Nbu¢ùš3a¥5ö ®í[òÝìnªX•éá<­'ÃÓÈy=óʾ³¼±M4/ìЇhïôð®z| L8OëÉð4ò@ÞWº Þk®§Ý˜ŽÚÛ¥‡ó³ž ?s\Г½j„Ì#Ìäê6õNÐz2©øwi¹²\4Wƒê'g=rv5‚ÃŒ c»vANg~?ónÎföµ=Ó®Fリ-NÏz2ôìj Ž3T+ l(ſt–é¡ ùgÙah«U¡{8IëÉ´«íŸÄãêËÍŽ}7ò Yr#S„³µž [»Ev2EìúáõJ2Ë:‘‹ÌRs„óµž _›yæ˜k8ð·vú½éS/‹šl€ëôpîÖ“án¹bºü¬;£>©&«³õpâÖ“!nsóÊæ3”Tjå*¨6 ¼9wª¬4ÍEÂi[O†¶Q‘ü  R©bD*6NÚz2¤ „ ‹Â¤à›çn=îFîp#&ÎCË›ûž ^6v4øæÌŽ Fµ©Ö‹ØÇiP_†Ím3\™§jl“["Ô|ð!¦1†jÅÁiP_†ÖF©ÎpªÓ—¢:8ôÇÕëŒH¨˜T÷q~Ó—â7ûÚ «å aRÎ̉ë58¿éKñï:£Òe?{3û§6})jC$áåÖÌ1X=O#Ïg5)V³‹JÃÊbÚc‡ ;»^¤8Êf€3™“F{e€Øè‘i]MåqœÎ d茻˜WwoH~PÞ¼a€ó™ Ÿ‹ 3jxÌùAg„.Ÿî"Zù.1Ú4àà¬f Ãj|QîäóªY"ˆòÎi2œÆ7É#¹ú …‚ Ú]6P%j€š ¡I Ké}à MôÓnô·Z¡pV3a5‰™:`Îf©d\Åç5Nk2´Æ7ÝTŠÄîìÎÔQ|aâÕ …³š «¡ñO…5³ü®!Îa†2†¢¿­‚ÛäÖk@â\f(Ãe èÌO‹5”ךŽÃâ…xH éÔ^÷CœÌ eÈ ˆõº²·fÚV«¹H»!Îh†RŒ†aÍ ãfUˆg1C)C°B&Í %ÁÉËPм¬Þd’÷™%ð©\P˦>ÎCœ½ ¥ØKP>Š“Æ€eã3°³²CŠœ¼ ¥È Èdíê†unÔÞ%µïÔÆvq3”b1‹\Q«Àf•¯k5ÄYÍPŠÕ,¢Ýz„´üC–f%š4µ!Îk†2¼æ×…cçrˆ ÇÛq4ƒ¨Ñl¢!Îq†2§Øla·éq£E †8Ëʰœ,º“ÖŒç@ %¾©øWQ¤–‹qª3”¡:Af,¸;( -Ù Õ „Sž¡ åI&"1äúwÜ.H#“"Q‘>)õE#‡8ãÊ0"Óbn§‡·DM'Æ8û‰eØO`_ïÝäK¢4[G6Æ9P,ÃöÆeykÓã,(–aA¡y½gñŠd5ÕY"ÆÉP,C†BËLÚêÑ¿špâÄ8ý‰eè¹Tª]läo6Óq³Å8ŠeÃLeáùø³;.Ir}6P;Æ)P,CÂ\AßRì}©´¯ê¢—1N€bæ ú†'+èãÜ'–á>DËôsÒðÍß6³spÞËðž0Wý6Ü­~«VœçÄ2<'ÌW‡ sáhê]P1NmbjæŠÂ´TæŠq2Ë™0_–ž\¥z°YPºú;g3± ›!bL®•ŠÄ«Þ{>!l4‰uâñ’—ž¯xžpBËš0_ñ„Ú©t«V œÃÄ2&Ì×"Mri-R›” ²Ä)ÌR†Â„¹J¡=³­BHØ?Y·Zp ³”¡0D w1ß½›ŠßZâ¬e)ÅZrE-ꢖj¥ÀiÊRЦdõ«#€š¹e–8uY"Ôeá.T'/qN²”â$¹*•‰W†ªT‹'!KIr]Xû»•)ÕÊS¥õ¸´“~ô/²„š‹¸\â|c)Å7.½hÓU0 1K5¡4Ö¤k‰ÓŽ¥í •kåäi$²g‰Ó¥ýY’Üå*Yü Yp²”â!D–p¿,a#²àdd)EFÀ‚ä`_ÙILÒÄËš/õõZ–8YJ Ì…ùÓÏ F÷/qö±”bþ¬ºî ýÛël÷Ú aÊvõ±– Å7‚T­L8YËЙëQdíÞ=,Ä¿âR|ûà¤f-Cj@¨2íäBåë7â[[ãüf-Ão®G —,œÛìlK‚bš;Âqr³–!7‰Q-ñzš×öÏ Ö5Ï ¦ªUÃSjEÂ)ÏZ†ò\{ŽÅAC˜¿z£íg8k)†ÈOéñXãìf-Ãn [Ã$ PdesOàXã$g-Cr@Þ˜b2[„—Yz~BÀ<¦<Îg“µ Ù°×A•OŠÇ““ó- LËVßycƒó ß¹¹´sÕšÓ˜Øk´mp’³‘!9·æÌ¿4 u´'aÒÍš\ `Nk¢Ùãg<Æs›HR*'È” ©V$œþldèÏmïÄåI;óZžŒWõ•¹ÁIÏF†ôÜí]pÐk=káçOŸžž_¡[‹<öüC-pÁMÁëÇÏÊRG˜r·8—G —py¶ÇÈã¸4Є%PWŸR9¶¸Û£äHê¬çÐ.ÜD69//RبÐêbÿè·4•üaÁX¿à0œ“Øæì,ræ6kcñº‚Î!èÂrç±æBÈ! ¿·LmtG7@1„P ÅàPô–ÆšL×’AÖÕïm ßÛæïm§ïÕëyoGøÞo'}/\$ôTŸìؾ&tS{ç‡oY]!†.ÇÐM1´©’M:“õܾµlŸîñwf¤Åkíó§· ê Qõ8ª^ŠªCþ ÿ)p\_åíYÚô³™ÙäÆåâ×Íó[Pö…(ûe?EÙÍ­€ñþmswÔûC›ŒÎ˜¶3f½3ùHUŒUÓà|ï†ewÀ1(ﬧ??Åÿ©…³èÂô9Hñ …x†IÞhçá] œ •Âó},}ñVøâ-yñeüð4€£Ýô·]…—~mé-á›ÍË-¢¥D˜ Ÿþüóóãý*~½z|ÑÆÏ÷_6ÏÚã¼ÕMÔ’œR¨Æ„‚ÞO!4ѶÉ#dùŒæÚ «w.LÍ\ÇŸÈ^ÖœGòÏm¼Úhï.Ç´¶;·om5a*G ½VB%_›ÎØ aå)ƺŸÇ¤X IÆŽèF«m£2èC‰ö£¯n´÷óc†‘ZÀMà5º¶à)¼ª CÚiû C H!mHÃgÀ»äpxä$Cœ}ôhiÙ2öx™ >Ý2ËB«–„V+=ÛzZôôyõQ Wϛͣ6Þ|¹'»/‘#qÙû;™¿ªÁe¸ÿžXÈ •ˆ>Þo¶”1Í›õÜÃõÝzÃû…Wóz(õ~ý ï…ï¥Þo¼áýKáû—Rïo¿áý+áûWRïï¼áýBsÕz-õþîÞ¿¾#õþÞÞ/Ô×[©÷÷¥Þ½ðî­Pö-ÈnF·Ѽ/ü°Ûú™¼w½yy}~ú{³Ö–kÏ›×ÏÏÚöùéOíÓóÓëfõJ~øói½9p0¶[Õ€vx D¾u1ñ‰ϲêp0s£*8ß!˜¯Ýƒ#%Þãû U½ðaö6ò.abochs-2.6/ltdlconf.h.in0000644000175000017500000001041612020641507014717 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ltdlconf.h.in,v 1.2 2002-10-24 21:04:38 bdenney Exp $ // // The configure script reads this file and produces ltdlconf.h, which // tells ltdl.c how to compile. It was copied out of the libtool package // but appears to have been generated by autoheader. ///////////////////////////////////////////////////////////////////////// /* config-h.in. Generated automatically from configure.in by autoheader. */ /* Define to empty if the keyword does not work. */ #undef const /* Define as __inline if that's what the C compiler calls it. */ #undef inline /* Define if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define if you have the argz_append function. */ #undef HAVE_ARGZ_APPEND /* Define if you have the argz_create_sep function. */ #undef HAVE_ARGZ_CREATE_SEP /* Define if you have the argz_insert function. */ #undef HAVE_ARGZ_INSERT /* Define if you have the argz_next function. */ #undef HAVE_ARGZ_NEXT /* Define if you have the argz_stringify function. */ #undef HAVE_ARGZ_STRINGIFY /* Define if you have the bcopy function. */ #undef HAVE_BCOPY /* Define if you have the dlerror function. */ #undef HAVE_DLERROR /* Define if you have the index function. */ #undef HAVE_INDEX /* Define if you have the memcpy function. */ #undef HAVE_MEMCPY /* Define if you have the memmove function. */ #undef HAVE_MEMMOVE /* Define if you have the rindex function. */ #undef HAVE_RINDEX /* Define if you have the strchr function. */ #undef HAVE_STRCHR /* Define if you have the strcmp function. */ #undef HAVE_STRCMP /* Define if you have the strrchr function. */ #undef HAVE_STRRCHR /* Define if you have the header file. */ #undef HAVE_ARGZ_H /* Define if you have the header file. */ #undef HAVE_ASSERT_H /* Define if you have the header file. */ #undef HAVE_CTYPE_H /* Define if you have the header file. */ #undef HAVE_DIRENT_H /* Define if you have the header file. */ #undef HAVE_DL_H /* Define if you have the header file. */ #undef HAVE_DLD_H /* Define if you have the header file. */ #undef HAVE_DLFCN_H /* Define if you have the header file. */ #undef HAVE_ERRNO_H /* Define if you have the header file. */ #undef HAVE_MALLOC_H /* Define if you have the header file. */ #undef HAVE_MEMORY_H /* Define if you have the header file. */ #undef HAVE_NDIR_H /* Define if you have the header file. */ #undef HAVE_STDIO_H /* Define if you have the header file. */ #undef HAVE_STDLIB_H /* Define if you have the header file. */ #undef HAVE_STRING_H /* Define if you have the header file. */ #undef HAVE_STRINGS_H /* Define if you have the header file. */ #undef HAVE_SYS_DIR_H /* Define if you have the header file. */ #undef HAVE_SYS_DL_H /* Define if you have the header file. */ #undef HAVE_SYS_NDIR_H /* Define if you have the header file. */ #undef HAVE_UNISTD_H /* Define to the extension used for shared libraries, say, .so. */ #undef LTDL_SHLIB_EXT /* Define to the name of the environment variable that determines the dynamic library search path. */ #undef LTDL_SHLIBPATH_VAR /* Define to the system default library search path. */ #undef LTDL_SYSSEARCHPATH /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LTDL_OBJDIR /* Define if libtool can extract symbol lists from object files. */ #undef HAVE_PRELOADED_SYMBOLS /* Define if you have the libdl library or equivalent. */ #undef HAVE_LIBDL /* Define if you have the libdl library or equivalent. */ #undef HAVE_LIBDL /* Define if you have the libdl library or equivalent. */ #undef HAVE_LIBDL /* Define if you have the shl_load function. */ #undef HAVE_SHL_LOAD /* Define if you have the shl_load function. */ #undef HAVE_SHL_LOAD /* Define if you have the GNU dld library. */ #undef HAVE_DLD /* Define if dlsym() requires a leading underscode in symbol names. */ #undef NEED_USCORE /* Define if the OS needs help to load dependent libraries for dlopen(). */ #undef LTDL_DLOPEN_DEPLIBS /* Define to a type to use for `error_t' if it is not otherwise available. */ #undef error_t bochs-2.6/Makefile.in0000644000175000017500000007166512020641507014416 0ustar guillemguillem# Copyright (C) 2001-2012 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # #################################################### # NOTE: To be compatibile with nmake (microsoft vc++) please follow # the following rules: # use $(VAR) not ${VAR} prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ VPATH = @srcdir@ bindir = @bindir@ libdir = @libdir@ plugdir = @libdir@/bochs/plugins datarootdir = @datarootdir@ mandir = @mandir@ man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 docdir = $(datarootdir)/doc/bochs sharedir = $(datarootdir)/bochs top_builddir = . top_srcdir = $(srcdir) DESTDIR = VERSION=@VERSION@ VER_STRING=@VER_STRING@ REL_STRING=@REL_STRING@ MAN_PAGE_1_LIST=bochs bximage bxcommit bochs-dlx MAN_PAGE_5_LIST=bochsrc INSTALL_LIST_SHARE=bios/BIOS-bochs-* bios/VGABIOS* @INSTALL_LIST_FOR_PLATFORM@ INSTALL_LIST_DOC=CHANGES COPYING LICENSE README TODO INSTALL_LIST_BIN=bochs@EXE@ bximage@EXE@ bxcommit@EXE@ INSTALL_LIST_BIN_OPTIONAL=bochsdbg@EXE@ INSTALL_LIST_WIN32=$(INSTALL_LIST_SHARE) $(INSTALL_LIST_DOC) $(INSTALL_LIST_BIN) $(INSTALL_LIST_BIN_OPTIONAL) niclist@EXE@ INSTALL_LIST_MACOSX=$(INSTALL_LIST_SHARE) $(INSTALL_LIST_DOC) bochs.scpt # for win32 and macosx, these files get renamed to *.txt in install process TEXT_FILE_LIST=README CHANGES COPYING TODO VGABIOS-elpin-LICENSE VGABIOS-lgpl-README CP=cp CAT=cat RM=rm MV=mv LN_S=ln -sf DLXLINUX_TAR=dlxlinux4.tar.gz DLXLINUX_TAR_URL=http://bochs.sourceforge.net/guestos/$(DLXLINUX_TAR) DLXLINUX_ROMFILE=BIOS-bochs-latest GUNZIP=gunzip WGET=@WGET@ SED=sed MKDIR=mkdir RMDIR=rmdir TAR=tar CHMOD=chmod # the GZIP variable is reserved by gzip program GZIP_BIN=gzip -9 GUNZIP=gunzip ZIP=zip UNIX2DOS=unix2dos LIBTOOL=@LIBTOOL@ DLLTOOL=dlltool RC_CMD=@RC_CMD@ @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ SHELL = @SHELL@ @SET_MAKE@ CC = @CC@ CXX = @CXX@ CFLAGS = @CFLAGS@ @GUI_CFLAGS@ $(MCH_CFLAGS) $(FLA_FLAGS) @DEFINE_PLUGIN_PATH@ -DBX_SHARE_PATH='"$(sharedir)"' CXXFLAGS = @CXXFLAGS@ @GUI_CXXFLAGS@ $(MCH_CFLAGS) $(FLA_FLAGS) @DEFINE_PLUGIN_PATH@ -DBX_SHARE_PATH='"$(sharedir)"' LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ # To compile with readline: # linux needs just -lreadline # solaris needs -lreadline -lcurses X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ GUI_LINK_OPTS_X = $(X_LIBS) $(X_PRE_LIBS) GUI_LINK_OPTS_SDL = `sdl-config --cflags --libs` GUI_LINK_OPTS_SVGA = -lvga -lvgagl GUI_LINK_OPTS_RFB = @RFB_LIBS@ GUI_LINK_OPTS_AMIGAOS = GUI_LINK_OPTS_WIN32 = -luser32 -lgdi32 -lcomdlg32 -lcomctl32 -lwsock32 -lshell32 GUI_LINK_OPTS_WIN32_VCPP = user32.lib gdi32.lib winmm.lib \ comdlg32.lib comctl32.lib wsock32.lib advapi32.lib shell32.lib GUI_LINK_OPTS_MACOS = GUI_LINK_OPTS_CARBON = -framework Carbon GUI_LINK_OPTS_NOGUI = GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@ GUI_LINK_OPTS_WX = @GUI_LINK_OPTS_WX@ GUI_LINK_OPTS = @GUI_LINK_OPTS@ @DEVICE_LINK_OPTS@ RANLIB = @RANLIB@ CFLAGS_CONSOLE = @CFLAGS@ $(MCH_CFLAGS) $(FLA_FLAGS) CXXFLAGS_CONSOLE = @CXXFLAGS@ $(MCH_CFLAGS) $(FLA_FLAGS) BXIMAGE_LINK_OPTS = @BXIMAGE_LINK_OPTS@ BX_INCDIRS = -I. -I$(srcdir)/. -I@INSTRUMENT_DIR@ -I$(srcdir)/@INSTRUMENT_DIR@ #SUBDIRS = iodev bx_debug #all install uninstall: config.h# # for subdir in $(SUBDIRS); do # # echo making $@ in $$subdir; # # ($(MAKE) -C $$subdir $(MDEFINES) $@) || exit 1; # # done# # gnu flags for clean up #CFLAGS = -ansi -O -g -Wunused -Wuninitialized NONINLINE_OBJS = \ logio.o \ main.o \ config.o \ load32bitOShack.o \ pc_system.o \ osdep.o \ plugin.o \ crc.o \ @EXTRA_BX_OBJS@ EXTERN_ENVIRONMENT_OBJS = \ main.o \ config.o \ load32bitOShack.o \ pc_system.o DEBUGGER_LIB = bx_debug/libdebug.a DISASM_LIB = disasm/libdisasm.a INSTRUMENT_LIB = @INSTRUMENT_DIR@/libinstrument.a FPU_LIB = fpu/libfpu.a READLINE_LIB = @READLINE_LIB@ EXTRA_LINK_OPTS = @EXTRA_LINK_OPTS@ GDBSTUB_OBJS = gdbstub.o BX_OBJS = @NONINLINE_VAR@ BX_INCLUDES = bochs.h config.h osdep.h .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(BX_INCDIRS) $(CXXFLAGS) @CXXFP@$< @OFP@$@ .c.o: $(CC) @DASH@c $(BX_INCDIRS) $(CFLAGS) $(FPU_FLAGS) $< @OFP@$@ all: @PRIMARY_TARGET@ @PLUGIN_TARGET@ bximage@EXE@ bxcommit@EXE@ @BUILD_DOCBOOK_VAR@ @EXTERNAL_DEPENDENCY@ bochs@EXE@: @IODEV_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ @SOUND_LIB_VAR@ \ @DEBUGGER_VAR@ cpu/libcpu.a cpu/cpudb/libcpudb.a memory/libmemory.a \ gui/libgui.a @DISASM_VAR@ @INSTRUMENT_VAR@ $(BX_OBJS) \ $(SIMX86_OBJS) @FPU_VAR@ @GDBSTUB_VAR@ @PLUGIN_VAR@ @LINK@ @EXPORT_DYNAMIC@ $(BX_OBJS) $(SIMX86_OBJS) \ @IODEV_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ @SOUND_LIB_VAR@ \ @DEBUGGER_VAR@ cpu/libcpu.a cpu/cpudb/libcpudb.a \ memory/libmemory.a gui/libgui.a \ @DISASM_VAR@ @INSTRUMENT_VAR@ @PLUGIN_VAR@ \ @GDBSTUB_VAR@ @FPU_VAR@ \ @NONPLUGIN_GUI_LINK_OPTS@ \ $(MCH_LINK_FLAGS) \ $(SIMX86_LINK_FLAGS) \ $(READLINE_LIB) \ $(EXTRA_LINK_OPTS) \ $(LIBS) # Special make target for cygwin/mingw using dlltool instead of # libtool. This creates a .DEF file, and exports file, an import library, # and then links bochs.exe with the exports file. .win32_dll_plugin_target: @IODEV_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ \ @SOUND_LIB_VAR@ @DEBUGGER_VAR@ cpu/libcpu.a cpu/cpudb/libcpudb.a \ memory/libmemory.a gui/libgui.a @DISASM_VAR@ @INSTRUMENT_VAR@ \ $(BX_OBJS) $(SIMX86_OBJS) @FPU_VAR@ @GDBSTUB_VAR@ @PLUGIN_VAR@ $(DLLTOOL) --export-all-symbols --output-def bochs.def \ $(BX_OBJS) $(SIMX86_OBJS) \ @IODEV_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ @SOUND_LIB_VAR@ \ cpu/libcpu.a cpu/cpudb/libcpudb.a memory/libmemory.a gui/libgui.a \ @DEBUGGER_VAR@ @DISASM_VAR@ @INSTRUMENT_VAR@ @PLUGIN_VAR@ \ @GDBSTUB_VAR@ @FPU_VAR@ $(DLLTOOL) --dllname bochs.exe --def bochs.def --output-lib dllexports.a $(DLLTOOL) --dllname bochs.exe --output-exp bochs.exp --def bochs.def $(CXX) -o bochs.exe $(CXXFLAGS) $(LDFLAGS) -export-dynamic \ $(BX_OBJS) bochs.exp $(SIMX86_OBJS) \ @IODEV_LIB_VAR@ @HDIMAGE_LIB_VAR@ @USB_LIB_VAR@ @NETWORK_LIB_VAR@ @SOUND_LIB_VAR@ \ cpu/libcpu.a cpu/cpudb/libcpudb.a memory/libmemory.a gui/libgui.a \ @DEBUGGER_VAR@ @DISASM_VAR@ @INSTRUMENT_VAR@ @PLUGIN_VAR@ \ @GDBSTUB_VAR@ @FPU_VAR@ \ $(GUI_LINK_OPTS) \ $(MCH_LINK_FLAGS) \ $(SIMX86_LINK_FLAGS) \ $(READLINE_LIB) \ $(EXTRA_LINK_OPTS) \ $(LIBS) touch .win32_dll_plugin_target bochs_plugins: cd gui @COMMAND_SEPARATOR@ $(MAKE) plugins @CD_UP_ONE@ cd iodev @COMMAND_SEPARATOR@ $(MAKE) plugins @CD_UP_ONE@ cd iodev/hdimage @COMMAND_SEPARATOR@ $(MAKE) plugins @CD_UP_TWO@ cd iodev/usb @COMMAND_SEPARATOR@ $(MAKE) plugins @CD_UP_TWO@ cd iodev/network @COMMAND_SEPARATOR@ $(MAKE) plugins @CD_UP_TWO@ cd iodev/sound @COMMAND_SEPARATOR@ $(MAKE) plugins @CD_UP_TWO@ bximage@EXE@: misc/bximage.o @LINK_CONSOLE@ $(BXIMAGE_LINK_OPTS) misc/bximage.o bxcommit@EXE@: misc/bxcommit.o @LINK_CONSOLE@ misc/bxcommit.o niclist@EXE@: misc/niclist.o @LINK_CONSOLE@ misc/niclist.o # compile with console CXXFLAGS, not gui CXXFLAGS misc/bximage.o: $(srcdir)/misc/bximage.c $(srcdir)/misc/bswap.h $(srcdir)/iodev/hdimage/hdimage.h $(CC) @DASH@c $(BX_INCDIRS) $(CFLAGS_CONSOLE) $(srcdir)/misc/bximage.c @OFP@$@ misc/bxcommit.o: $(srcdir)/misc/bxcommit.c $(srcdir)/misc/bswap.h $(srcdir)/iodev/hdimage/hdimage.h $(CC) @DASH@c $(BX_INCDIRS) $(CFLAGS_CONSOLE) $(srcdir)/misc/bxcommit.c @OFP@$@ misc/niclist.o: $(srcdir)/misc/niclist.c $(CC) @DASH@c $(BX_INCDIRS) $(CFLAGS_CONSOLE) $(srcdir)/misc/niclist.c @OFP@$@ $(BX_OBJS): $(BX_INCLUDES) # cannot use -C option to be compatible with Microsoft nmake iodev/libiodev.a:: cd iodev @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libiodev.a @CD_UP_ONE@ iodev/hdimage/libhdimage.a:: cd iodev/hdimage @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libhdimage.a @CD_UP_TWO@ iodev/usb/libusb.a:: cd iodev/usb @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libusb.a @CD_UP_TWO@ iodev/network/libnetwork.a:: cd iodev/network @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libnetwork.a @CD_UP_TWO@ iodev/sound/libsound.a:: cd iodev/sound @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libsound.a @CD_UP_TWO@ bx_debug/libdebug.a:: cd bx_debug @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libdebug.a @CD_UP_ONE@ cpu/libcpu.a:: cd cpu @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libcpu.a @CD_UP_ONE@ cpu/cpudb/libcpudb.a:: cd cpu/cpudb @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libcpudb.a @CD_UP_TWO@ memory/libmemory.a:: cd memory @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libmemory.a @CD_UP_ONE@ gui/libgui.a:: cd gui @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libgui.a @CD_UP_ONE@ disasm/libdisasm.a:: cd disasm @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libdisasm.a @CD_UP_ONE@ @INSTRUMENT_DIR@/libinstrument.a:: cd @INSTRUMENT_DIR@ @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libinstrument.a @CD_UP_TWO@ fpu/libfpu.a:: cd fpu @COMMAND_SEPARATOR@ $(MAKE) $(MDEFINES) libfpu.a @CD_UP_ONE@ libbochs.a: -rm -f libbochs.a ar rv libbochs.a $(EXTERN_ENVIRONMENT_OBJS) $(RANLIB) libbochs.a libbochs_cpu.a: @DEBUGGER_VAR@ $(BX_OBJS) -rm -f libbochs_cpu.a ar rv libbochs_cpu.a $(BX_OBJS) $(RANLIB) libbochs_cpu.a # for wxWidgets port, on win32 platform wxbochs_resources.o: wxbochs.rc windres $(srcdir)/wxbochs.rc -o $@ --include-dir=`@WX_CONFIG@ --prefix`/include # for win32 gui win32res.o: win32res.rc bxversion.rc $(RC_CMD)$@ $(srcdir)/win32res.rc ##################################################################### # Install target for all platforms. ##################################################################### install: all @INSTALL_TARGET@ ##################################################################### # Install target for win32 # # This is intended to be run in cygwin, since it has better scripting # tools. ##################################################################### install_win32: download_dlx @INSTALL_DOCBOOK_VAR@ -mkdir -p $(prefix) cp obj-release/*.exe . for i in $(INSTALL_LIST_WIN32); do if test -f $$i; then cp $$i $(prefix); else cp $(srcdir)/$$i $(prefix); fi; done cp $(srcdir)/misc/sb16/sb16ctrl.example $(prefix)/sb16ctrl.txt cp $(srcdir)/misc/sb16/sb16ctrl.exe $(prefix) #cat $(srcdir)/build/win32/DOC-win32.htm | $(SED) -e 's/@VERSION@/$(VERSION)/g' > $(prefix)/DOC-win32.htm cp $(srcdir)/.bochsrc $(prefix)/bochsrc-sample.txt -mkdir $(prefix)/keymaps cp $(srcdir)/gui/keymaps/*.map $(prefix)/keymaps cat $(DLXLINUX_TAR) | (cd $(prefix) && tar xzvf -) echo '..\bochs' > $(prefix)/dlxlinux/start.bat dlxrc=$(prefix)/dlxlinux/bochsrc.txt; mv $$dlxrc $$dlxrc.orig && sed < $$dlxrc.orig 's/\/usr\/local\/bochs\/latest/../' > $$dlxrc && rm -f $$dlxrc.orig mv $(prefix)/README $(prefix)/README.orig cat $(srcdir)/build/win32/README.win32-binary $(prefix)/README.orig > $(prefix)/README rm -f $(prefix)/README.orig for i in $(TEXT_FILE_LIST); do mv $(prefix)/$$i $(prefix)/$$i.txt; done cd $(prefix); $(UNIX2DOS) *.txt */*.txt cd $(prefix); NAME=`pwd|$(SED) 's/.*\///'`; (cd ..; $(ZIP) $$NAME.zip -r $$NAME); ls -l ../$$NAME.zip ##################################################################### # install target for unix ##################################################################### install_unix: install_bin @INSTALL_PLUGINS_VAR@ install_man install_share install_doc @INSTALL_DOCBOOK_VAR@ install_bin:: for i in $(DESTDIR)$(bindir); do mkdir -p $$i && test -d $$i && test -w $$i; done for i in $(INSTALL_LIST_BIN); do if test -f $$i; then install $$i $(DESTDIR)$(bindir); else install $(srcdir)/$$i $(DESTDIR)$(bindir); fi; done -for i in $(INSTALL_LIST_BIN_OPTIONAL); do if test -f $$i; then install $$i $(DESTDIR)$(bindir); else install $(srcdir)/$$i $(DESTDIR)$(bindir); fi; done install_libtool_plugins:: for i in $(DESTDIR)$(plugdir); do mkdir -p $$i && test -d $$i && test -w $$i; done list=`cd gui && echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install gui/$$i $(DESTDIR)$(plugdir); done list=`cd iodev && echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install iodev/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/hdimage && echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install iodev/hdimage/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/usb && echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install iodev/usb/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/network && echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install iodev/network/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/sound && echo *.la`; for i in $$list; do $(LIBTOOL) --mode=install install iodev/sound/$$i $(DESTDIR)$(plugdir); done $(LIBTOOL) --finish $(DESTDIR)$(plugdir) install_dll_plugins:: for i in $(DESTDIR)$(plugdir); do mkdir -p $$i && test -d $$i && test -w $$i; done list=`cd gui && echo *.dll`; for i in $$list; do cp gui/$$i $(DESTDIR)$(plugdir); done list=`cd iodev && echo *.dll`; for i in $$list; do cp iodev/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/hdimage && echo *.dll`; for i in $$list; do cp iodev/hdimage/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/usb && echo *.dll`; for i in $$list; do cp iodev/usb/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/network && echo *.dll`; for i in $$list; do cp iodev/network/$$i $(DESTDIR)$(plugdir); done list=`cd iodev/sound && echo *.dll`; for i in $$list; do cp iodev/sound/$$i $(DESTDIR)$(plugdir); done install_share:: for i in $(DESTDIR)$(sharedir); do mkdir -p $$i && test -d $$i && test -w $$i; done for i in $(INSTALL_LIST_SHARE); do if test -f $$i; then install -m 644 $$i $(DESTDIR)$(sharedir); else install -m 644 $(srcdir)/$$i $(DESTDIR)$(sharedir); fi; done -mkdir $(DESTDIR)$(sharedir)/keymaps for i in $(srcdir)/gui/keymaps/*.map; do install -m 644 $$i $(DESTDIR)$(sharedir)/keymaps/; done install_doc:: for i in $(DESTDIR)$(docdir); do mkdir -p $$i && test -d $$i && test -w $$i; done for i in $(INSTALL_LIST_DOC); do if test -f $$i; then install -m 644 $$i $(DESTDIR)$(docdir); else install -m 644 $(srcdir)/$$i $(DESTDIR)$(docdir); fi; done $(RM) -f $(DESTDIR)$(docdir)/README $(CAT) $(srcdir)/build/linux/README.linux-binary $(srcdir)/README > $(DESTDIR)$(docdir)/README install -m 644 $(srcdir)/.bochsrc $(DESTDIR)$(docdir)/bochsrc-sample.txt # docbook section: the -C option can be used here build_docbook:: $(MAKE) -C doc/docbook dl_docbook:: $(MAKE) -C doc/docbook dl_docs install_docbook: build_docbook $(MAKE) -C doc/docbook install clean_docbook:: $(MAKE) -C doc/docbook clean install_man:: -mkdir -p $(DESTDIR)$(man1dir) -mkdir -p $(DESTDIR)$(man5dir) for i in $(MAN_PAGE_1_LIST); do cat $(srcdir)/doc/man/$$i.1 | $(SED) 's/@version@/$(VERSION)/g' | $(GZIP_BIN) -c > $(DESTDIR)$(man1dir)/$$i.1.gz; chmod 644 $(DESTDIR)$(man1dir)/$$i.1.gz; done for i in $(MAN_PAGE_5_LIST); do cat $(srcdir)/doc/man/$$i.5 | $(GZIP_BIN) -c > $(DESTDIR)$(man5dir)/$$i.5.gz; chmod 644 $(DESTDIR)$(man5dir)/$$i.5.gz; done download_dlx: $(DLXLINUX_TAR) $(DLXLINUX_TAR): $(RM) -f $(DLXLINUX_TAR) $(WGET) $(DLXLINUX_TAR_URL) test -f $(DLXLINUX_TAR) unpack_dlx: $(DLXLINUX_TAR) rm -rf dlxlinux $(GUNZIP) -c $(DLXLINUX_TAR) | $(TAR) -xvf - test -d dlxlinux (cd dlxlinux; $(MV) bochsrc.txt bochsrc.txt.orig; $(SED) -e "s/1\.1\.2/$(VERSION)/g" -e 's,/usr/local/bochs/latest,$(prefix)/share/bochs,g' < bochsrc.txt.orig > bochsrc.txt; rm -f bochsrc.txt.orig) install_dlx: $(RM) -rf $(DESTDIR)$(sharedir)/dlxlinux cp -r dlxlinux $(DESTDIR)$(sharedir)/dlxlinux $(CHMOD) 755 $(DESTDIR)$(sharedir)/dlxlinux $(GZIP_BIN) $(DESTDIR)$(sharedir)/dlxlinux/hd10meg.img $(CHMOD) 644 $(DESTDIR)$(sharedir)/dlxlinux/* for i in bochs-dlx; do cp $(srcdir)/build/linux/$$i $(DESTDIR)$(bindir)/$$i; $(CHMOD) 755 $(DESTDIR)$(bindir)/$$i; done uninstall:: $(RM) -rf $(DESTDIR)$(sharedir) $(RM) -rf $(DESTDIR)$(docdir) $(RM) -rf $(DESTDIR)$(libdir)/bochs for i in bochs bximage bxcommit bochs-dlx; do rm -f $(DESTDIR)$(bindir)/$$i; done for i in $(MAN_PAGE_1_LIST); do $(RM) -f $(man1dir)/$$i.1.gz; done for i in $(MAN_PAGE_5_LIST); do $(RM) -f $(man5dir)/$$i.5.gz; done VS2008_WORKSPACE_ZIP=build/win32/vs2008ex-workspace.zip VS2008_WORKSPACE_FILES=vs2008/bochs.sln vs2008/*.vcproj vs2008workspace: zip $(VS2008_WORKSPACE_ZIP) $(VS2008_WORKSPACE_FILES) ######## # the win32_snap target is used to create a ZIP of bochs sources configured # for VC++. This ZIP is stuck on the website every once in a while to make # it easier for VC++ users to compile bochs. First, you should # run "sh .conf.win32-vcpp" to configure the source code, then do # "make win32_snap" to unzip the workspace files and create the ZIP. ######## win32_snap: unzip $(VS2008_WORKSPACE_ZIP) $(MAKE) zip tar: NAME=`pwd|$(SED) 's/.*\///'`; (cd ..; $(RM) -f $$NAME.zip; tar cf - $$NAME | $(GZIP_BIN) > $$NAME.tar.gz); ls -l ../$$NAME.tar.gz zip: NAME=`pwd|$(SED) 's/.*\///'`; (cd ..; $(RM) -f $$NAME-msvc-src.zip; $(ZIP) $$NAME-msvc-src.zip -r $$NAME -x \*CVS\* -x \*.cvsignore -x \*.svn\* ); ls -l ../$$NAME-msvc-src.zip clean: @RMCOMMAND@ *.o @RMCOMMAND@ *.a @RMCOMMAND@ bochs @RMCOMMAND@ bochs.exe @RMCOMMAND@ bximage @RMCOMMAND@ bximage.exe @RMCOMMAND@ bxcommit @RMCOMMAND@ bxcommit.exe @RMCOMMAND@ niclist @RMCOMMAND@ niclist.exe @RMCOMMAND@ bochs.out @RMCOMMAND@ bochsout.txt @RMCOMMAND@ bochs.exp @RMCOMMAND@ bochs.def @RMCOMMAND@ bochs.scpt @RMCOMMAND@ -rf bochs.app @RMCOMMAND@ -rf .libs @RMCOMMAND@ .win32_dll_plugin_target local-dist-clean: clean @RMCOMMAND@ config.h config.status config.log config.cache @RMCOMMAND@ .dummy `find . -name '*.dsp' -o -name '*.dsw' -o -name '*.opt' -o -name '.DS_Store'` @RMCOMMAND@ bxversion.h bxversion.rc build/linux/bochs-dlx _rpm_top *.rpm @RMCOMMAND@ build/win32/nsis/Makefile build/win32/nsis/bochs.nsi @RMCOMMAND@ build/macosx/Info.plist build/macosx/script_compiled.rsrc @RMCOMMAND@ libtool @RMCOMMAND@ ltdlconf.h clean_pcidev:: cd host/linux/pcidev @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_THREE@ all-clean: clean @CLEAN_DOCBOOK_VAR@ @CLEAN_PCIDEV_VAR@ cd iodev @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ cd iodev/hdimage @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_TWO@ cd iodev/usb @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_TWO@ cd iodev/network @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_TWO@ cd iodev/sound @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_TWO@ cd bx_debug @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ cd cpu @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ cd cpu/cpudb @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_TWO@ cd memory @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ cd gui @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ cd disasm @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ cd @INSTRUMENT_DIR@ @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_TWO@ cd misc @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ cd fpu @COMMAND_SEPARATOR@ $(MAKE) clean @CD_UP_ONE@ dist-clean: local-dist-clean cd iodev @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd iodev/hdimage @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_TWO@ cd iodev/usb @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_TWO@ cd iodev/network @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_TWO@ cd iodev/sound @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_TWO@ cd bx_debug @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd bios @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd cpu @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd cpu/cpudb @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_TWO@ cd memory @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd gui @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd disasm @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd @INSTRUMENT_DIR@ @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_TWO@ cd misc @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd fpu @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_ONE@ cd doc/docbook @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_TWO@ cd host/linux/pcidev @COMMAND_SEPARATOR@ $(MAKE) dist-clean @CD_UP_THREE@ @RMCOMMAND@ Makefile ########################################### # Build app on MacOS X ########################################### MACOSX_STUFF=build/macosx MACOSX_STUFF_SRCDIR=$(srcdir)/$(MACOSX_STUFF) APP=bochs.app APP_PLATFORM=MacOS SCRIPT_EXEC=bochs.scpt SCRIPT_DATA=$(MACOSX_STUFF_SRCDIR)/script.data SCRIPT_R=$(MACOSX_STUFF_SRCDIR)/script.r SCRIPT_APPLESCRIPT=$(MACOSX_STUFF_SRCDIR)/bochs.applescript SCRIPT_COMPILED_RSRC=$(MACOSX_STUFF)/script_compiled.rsrc REZ=/Developer/Tools/Rez CPMAC=/Developer/Tools/CpMac RINCLUDES=/System/Library/Frameworks/Carbon.framework/Libraries/RIncludes REZ_ARGS=-append -i $RINCLUDES -d SystemSevenOrLater=1 -useDF STANDALONE_LIBDIR=`pwd`/$(APP)/Contents/$(APP_PLATFORM)/lib OSACOMPILE=/usr/bin/osacompile SETFILE=/Developer/Tools/SetFile # On a MacOS X machine, you run rez, osacompile, and setfile to # produce the script executable, which has both a data fork and a # resource fork. Ideally, we would just recompile the whole # executable at build time, but unfortunately this cannot be done on # the SF compile farm through an ssh connection because osacompile # needs to be run locally for some reason. Solution: If the script # sources are changed, rebuild the executable on a MacOSX machine, # split it into its data and resource forks and check them into SVN # as separate files. Then at release time, all that's left to do is # put the data and resource forks back together to make a working script. # (This can be done through ssh.) # # Sources: # 1. script.r: resources for the script # 2. script.data: binary data for the script # 3. bochs.applescript: the source of the script # # NOTE: All of this will fail if you aren't building on an HFS+ # filesystem! On the SF compile farm building in your user directory # will fail, while doing the build in /tmp will work ok. # check if this filesystem supports resource forks at all test_hfsplus: $(RM) -rf test_hfsplus echo data > test_hfsplus # if you get "Not a directory", then this filesystem doesn't support resources echo resource > test_hfsplus/rsrc # test succeeded $(RM) -rf test_hfsplus # Step 1 (must be done locally on MacOSX, only when sources change) # Compile and pull out just the resource fork. The resource fork is # checked into SVN as script_compiled.rsrc. Note that we don't need # to check in the data fork of tmpscript because it is identical to the # script.data input file. $(SCRIPT_COMPILED_RSRC): $(SCRIPT_R) $(SCRIPT_APPLESCRIPT) $(RM) -f tmpscript $(CP) -f $(SCRIPT_DATA) tmpscript $(REZ) -append $(SCRIPT_R) -o tmpscript $(OSACOMPILE) -o tmpscript $(SCRIPT_APPLESCRIPT) $(CP) tmpscript/rsrc $(SCRIPT_COMPILED_RSRC) $(RM) -f tmpscript # Step 2 (can be done locally or remotely on MacOSX) # Combine the data fork and resource fork, and set attributes. $(SCRIPT_EXEC): $(SCRIPT_DATA) $(SCRIPT_COMPILED_RSRC) rm -f $(SCRIPT_EXEC) $(CP) $(SCRIPT_DATA) $(SCRIPT_EXEC) if test ! -f $(SCRIPT_COMPILED_RSRC); then $(CP) $(srcdir)/$(SCRIPT_COMPILED_RSRC) $(SCRIPT_COMPILED_RSRC); fi $(CP) $(SCRIPT_COMPILED_RSRC) $(SCRIPT_EXEC)/rsrc $(SETFILE) -t "APPL" -c "aplt" $(SCRIPT_EXEC) $(APP)/.build: bochs test_hfsplus $(SCRIPT_EXEC) rm -f $(APP)/.build $(MKDIR) -p $(APP) $(MKDIR) -p $(APP)/Contents $(CP) -f $(MACOSX_STUFF)/Info.plist $(APP)/Contents $(CP) -f $(MACOSX_STUFF_SRCDIR)/pbdevelopment.plist $(APP)/Contents echo -n "APPL????" > $(APP)/Contents/PkgInfo $(MKDIR) -p $(APP)/Contents/$(APP_PLATFORM) $(CP) bochs $(APP)/Contents/$(APP_PLATFORM) $(MKDIR) -p $(APP)/Contents/Resources $(REZ) $(REZ_ARGS) $(MACOSX_STUFF_SRCDIR)/bochs.r -o $(APP)/Contents/Resources/bochs.rsrc $(CP) -f $(MACOSX_STUFF_SRCDIR)/bochs-icn.icns $(APP)/Contents/Resources ls -ld $(APP) $(SCRIPT_EXEC) $(SCRIPT_EXEC)/rsrc touch $(APP)/.build $(APP)/.build_plugins: $(APP)/.build bochs_plugins rm -f $(APP)/.build_plugins $(MKDIR) -p $(STANDALONE_LIBDIR); list=`cd gui && echo *.la`; for i in $$list; do $(LIBTOOL) cp gui/$$i $(STANDALONE_LIBDIR); done; list=`cd iodev && echo *.la`; for i in $$list; do $(LIBTOOL) cp iodev/$$i $(STANDALONE_LIBDIR); done; $(LIBTOOL) --finish $(STANDALONE_LIBDIR); touch $(APP)/.build_plugins install_macosx: all download_dlx install_man @INSTALL_DOCBOOK_VAR@ -mkdir -p $(DESTDIR)$(sharedir) for i in $(INSTALL_LIST_MACOSX); do if test -e $$i; then $(CPMAC) -r $$i $(DESTDIR)$(sharedir); else $(CPMAC) -r $(srcdir)/$$i $(DESTDIR)$(sharedir); fi; done $(CPMAC) $(srcdir)/.bochsrc $(DESTDIR)$(sharedir)/bochsrc-sample.txt -mkdir $(DESTDIR)$(sharedir)/keymaps $(CPMAC) $(srcdir)/gui/keymaps/*.map $(DESTDIR)$(sharedir)/keymaps cat $(DLXLINUX_TAR) | (cd $(DESTDIR)$(sharedir) && tar xzvf -) dlxrc=$(DESTDIR)$(sharedir)/dlxlinux/bochsrc.txt; mv "$$dlxrc" "$$dlxrc.orig" && sed < "$$dlxrc.orig" 's/\/usr\/local\/bochs\/latest/../' > "$$dlxrc" && rm -f "$$dlxrc.orig" mv $(srcdir)/README $(srcdir)/README.orig cat $(srcdir)/build/macosx/README.macosx-binary $(srcdir)/README.orig > $(DESTDIR)$(sharedir)/README rm -f $(DESTDIR)$(sharedir)/README.orig $(CPMAC) $(SCRIPT_EXEC) $(DESTDIR)$(sharedir)/dlxlinux # for i in $(TEXT_FILE_LIST); do mv $(srcdir)/$$i $(DESTDIR)$(sharedir)/$$i.txt; done ########################################### # dependencies generated by # gcc -MM -I. -Iinstrument/stubs *.cc | sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's,cpu/,cpu/,g' ########################################### config.o: config.@CPP_SUFFIX@ bochs.h config.h osdep.h bx_debug/debug.h config.h \ osdep.h bxversion.h gui/siminterface.h gui/paramtree.h memory/memory.h \ pc_system.h plugin.h extplugin.h ltdl.h gui/gui.h \ instrument/stubs/instrument.h iodev/iodev.h bochs.h param_names.h \ param_names.h cpudb.h crc.o: crc.@CPP_SUFFIX@ config.h gdbstub.o: gdbstub.@CPP_SUFFIX@ bochs.h config.h osdep.h bx_debug/debug.h config.h \ osdep.h bxversion.h gui/siminterface.h gui/paramtree.h memory/memory.h \ pc_system.h plugin.h extplugin.h ltdl.h gui/gui.h \ instrument/stubs/instrument.h param_names.h cpu/cpu.h \ cpu/cpuid.h cpu/crregs.h cpu/descriptor.h cpu/instr.h \ cpu/ia_opcodes.h cpu/lazy_flags.h cpu/icache.h cpu/apic.h cpu/i387.h \ fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h cpu/xmm.h \ cpu/stack.h iodev/iodev.h bochs.h param_names.h load32bitOShack.o: load32bitOShack.@CPP_SUFFIX@ bochs.h config.h osdep.h \ bx_debug/debug.h config.h osdep.h bxversion.h gui/siminterface.h \ gui/paramtree.h memory/memory.h pc_system.h plugin.h extplugin.h ltdl.h \ gui/gui.h instrument/stubs/instrument.h param_names.h cpu/cpu.h \ cpu/cpuid.h cpu/crregs.h cpu/descriptor.h cpu/instr.h \ cpu/ia_opcodes.h cpu/lazy_flags.h cpu/icache.h cpu/apic.h cpu/i387.h \ fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h cpu/xmm.h \ iodev/iodev.h bochs.h param_names.h logio.o: logio.@CPP_SUFFIX@ bochs.h config.h osdep.h bx_debug/debug.h config.h \ osdep.h bxversion.h gui/siminterface.h gui/paramtree.h memory/memory.h \ pc_system.h plugin.h extplugin.h ltdl.h gui/gui.h \ instrument/stubs/instrument.h cpu/cpu.h cpu/cpuid.h \ cpu/crregs.h cpu/descriptor.h cpu/instr.h cpu/ia_opcodes.h \ cpu/lazy_flags.h cpu/icache.h cpu/apic.h cpu/i387.h fpu/softfloat.h \ fpu/tag_w.h fpu/status_w.h fpu/control_w.h cpu/xmm.h iodev/iodev.h \ bochs.h param_names.h main.o: main.@CPP_SUFFIX@ bochs.h config.h osdep.h bx_debug/debug.h config.h \ osdep.h bxversion.h gui/siminterface.h gui/paramtree.h memory/memory.h \ pc_system.h plugin.h extplugin.h ltdl.h gui/gui.h \ instrument/stubs/instrument.h param_names.h gui/textconfig.h cpu/cpu.h \ cpu/cpuid.h cpu/crregs.h cpu/descriptor.h cpu/instr.h \ cpu/ia_opcodes.h cpu/lazy_flags.h cpu/icache.h cpu/apic.h cpu/i387.h \ fpu/softfloat.h fpu/tag_w.h fpu/status_w.h fpu/control_w.h cpu/xmm.h \ iodev/iodev.h bochs.h param_names.h osdep.o: osdep.@CPP_SUFFIX@ bochs.h config.h osdep.h bx_debug/debug.h config.h \ osdep.h bxversion.h gui/siminterface.h gui/paramtree.h memory/memory.h \ pc_system.h plugin.h extplugin.h ltdl.h gui/gui.h \ instrument/stubs/instrument.h pc_system.o: pc_system.@CPP_SUFFIX@ bochs.h config.h osdep.h bx_debug/debug.h \ config.h osdep.h bxversion.h gui/siminterface.h gui/paramtree.h \ memory/memory.h pc_system.h plugin.h extplugin.h ltdl.h gui/gui.h \ instrument/stubs/instrument.h cpu/cpu.h cpu/cpuid.h \ cpu/crregs.h cpu/descriptor.h cpu/instr.h cpu/ia_opcodes.h \ cpu/lazy_flags.h cpu/icache.h cpu/apic.h cpu/i387.h fpu/softfloat.h \ fpu/tag_w.h fpu/status_w.h fpu/control_w.h cpu/xmm.h iodev/iodev.h \ bochs.h param_names.h plugin.o: plugin.@CPP_SUFFIX@ bochs.h config.h osdep.h bx_debug/debug.h config.h \ osdep.h bxversion.h gui/siminterface.h gui/paramtree.h memory/memory.h \ pc_system.h plugin.h extplugin.h ltdl.h gui/gui.h \ instrument/stubs/instrument.h iodev/iodev.h bochs.h param_names.h bochs-2.6/bxversion.rc.in0000644000175000017500000000053012020641507015302 0ustar guillemguillem1 VERSIONINFO FILEVERSION @WIN_VER_STRING@ { BLOCK "StringFileInfo" { BLOCK "040904E4" { VALUE "FileDescription", "The cross platform IA-32 emulator" VALUE "FileVersion", "@VER_STRING@" VALUE "LegalCopyright", "GNU Lesser General Public License" VALUE "ProductName", "Bochs" VALUE "ProductVersion", "@REL_STRING@" } } } bochs-2.6/msrs.def0000644000175000017500000000274712020641507014010 0ustar guillemguillem# # ---------------------------------- # Bochs CPU MSRs configuration # ---------------------------------- # # LEGEND: # ------ # # MSR ADDRESS - MSR address in hex (supplied in ECX register for RDMSR/WRMSR) # MSR TYPE - MSR type, see below # # The following fields have any meaning for MSRs with no type only: # # RESET_HI - reset value of the MSR (bits 63:32) # RESET_LO - reset value of the MSR (bits 31:00) # # NOTE: the value of the MSR doesn't change on INIT (software reset). # # RSRVD_HI - mask of reserved bits (bits 63:32) # RSRVD_LO - mask of reserved bits (bits 31:00) # # NOTE: #GP fault will be generated when trying to modify any of MSR # reserved bits. # # IGNRD_HI - mask of ignored bits (bits 63:32) # IGNRD_LO - mask of ignored bits (bits 31:00) # # NOTE: Ignored bits will keep their reset value, all writes to these # bits are ignored. # # MSR TYPES: # --------- # # 0 - No type. # 1 - MSR contains linear address, # #GP if writing non-canonical address in 64-bit mode. # 2 - MSR contains physical address, # #GP if writing a value which exceeds emulated physical address size. # # ADDRESS TYPE RESET_HI RESET_LO RSRVD_HI RSRVD_LO IGNRD_HI IGNRD_LO # --------------------------------------------------------------------------------- 0x02c 0 00000000 00000000 00000000 00000000 00000000 00000000 bochs-2.6/osdep.cc0000644000175000017500000002236412020641507013762 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: osdep.cc 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // // osdep.cc // // Provide definition of library functions that are missing on various // systems. The only reason this is a .cc file rather than a .c file // is so that it can include bochs.h. Bochs.h includes all the required // system headers, with appropriate #ifdefs for different compilers and // platforms. // #include "bochs.h" ////////////////////////////////////////////////////////////////////// // Missing library functions. These should work on any platform // that needs them. ////////////////////////////////////////////////////////////////////// #if !BX_HAVE_SNPRINTF /* XXX use real snprintf */ /* if they don't have snprintf, just use sprintf */ int bx_snprintf (char *s, size_t maxlen, const char *format, ...) { va_list arg; int done; va_start (arg, format); done = vsprintf (s, format, arg); va_end (arg); return done; } #endif /* !BX_HAVE_SNPRINTF */ #if !BX_HAVE_VSNPRINTF int bx_vsnprintf (char *s, size_t maxlen, const char *format, va_list arg) { return vsprintf (s, format, arg); } #endif /* !BX_HAVE_VSNPRINTF*/ #if (!BX_HAVE_STRTOULL && !BX_HAVE_STRTOUQ) /* taken from glibc-2.2.2: strtod.c, and stripped down a lot. There are still a few leftover references to decimal points and exponents, but it works for bases 10 and 16 */ #define RETURN(val,end) \ do { if (endptr != NULL) *endptr = (char *) (end); \ return val; } while (0) Bit64u bx_strtoull (const char *nptr, char **endptr, int baseignore) { int negative; /* The sign of the number. */ int exponent; /* Exponent of the number. */ /* Numbers starting `0X' or `0x' have to be processed with base 16. */ int base = 10; /* Number of bits currently in result value. */ int bits; /* Running pointer after the last character processed in the string. */ const char *cp, *tp; /* Start of significant part of the number. */ const char *startp, *start_of_digits; /* Total number of digit and number of digits in integer part. */ int dig_no; /* Contains the last character read. */ char c; Bit64s n = 0; char const *p; /* Prepare number representation. */ exponent = 0; negative = 0; bits = 0; /* Parse string to get maximal legal prefix. We need the number of characters of the integer part, the fractional part and the exponent. */ cp = nptr - 1; /* Ignore leading white space. */ do c = *++cp; while (isspace (c)); /* Get sign of the result. */ if (c == '-') { negative = 1; c = *++cp; } else if (c == '+') c = *++cp; if (c < '0' || c > '9') { /* It is really a text we do not recognize. */ RETURN (0, nptr); } /* First look whether we are faced with a hexadecimal number. */ if (c == '0' && tolower (cp[1]) == 'x') { /* Okay, it is a hexa-decimal number. Remember this and skip the characters. BTW: hexadecimal numbers must not be grouped. */ base = 16; cp += 2; c = *cp; } /* Record the start of the digits, in case we will check their grouping. */ start_of_digits = startp = cp; /* Ignore leading zeroes. This helps us to avoid useless computations. */ while (c == '0') c = *++cp; /* If no other digit but a '0' is found the result is 0.0. Return current read pointer. */ if ((c < '0' || c > '9') && (base == 16 && (c < tolower ('a') || c > tolower ('f'))) && (base == 16 && (cp == start_of_digits || tolower (c) != 'p')) && (base != 16 && tolower (c) != 'e')) { tp = start_of_digits; /* If TP is at the start of the digits, there was no correctly grouped prefix of the string; so no number found. */ RETURN (0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp); } /* Remember first significant digit and read following characters until the decimal point, exponent character or any non-FP number character. */ startp = cp; dig_no = 0; while (1) { if ((c >= '0' && c <= '9') || (base == 16 && tolower (c) >= 'a' && tolower (c) <= 'f')) ++dig_no; else break; c = *++cp; } /* The whole string is parsed. Store the address of the next character. */ if (endptr) *endptr = (char *) cp; if (dig_no == 0) return 0; for (p=start_of_digits; p!=cp; p++) { n = n * (Bit64s)base; c = tolower (*p); c = (c >= 'a') ? (10+c-'a') : c-'0'; n = n + (Bit64s)c; //printf ("after shifting in digit %c, n is %lld\n", *p, n); } return negative? -n : n; } #endif /* !BX_HAVE_STRTOULL */ #if BX_TEST_STRTOULL_MAIN /* test driver for strtoull. Do not compile by default. */ int main (int argc, char **argv) { char buf[256], *endbuf; long l; Bit64s ll; while (1) { printf ("Enter a long int: "); gets (buf); l = strtoul (buf, &endbuf, 10); printf ("As a long, %ld\n", l); printf ("Endbuf is at buf[%d]\n", endbuf-buf); ll = bx_strtoull(buf, &endbuf, 10); printf ("As a long long, %lld\n", ll); printf ("Endbuf is at buf[%d]\n", endbuf-buf); } return 0; } #endif /* BX_TEST_STRTOULL_MAIN */ #if !BX_HAVE_STRDUP /* XXX use real strdup */ char *bx_strdup(const char *str) { char *temp = (char*)malloc(strlen(str)+1); sprintf(temp, "%s", str); return temp; // Well, I'm sure this isn't how strdup is REALLY implemented, // but it works... } #endif /* !BX_HAVE_STRDUP */ #if !BX_HAVE_STRREV char *bx_strrev(char *str) { char *p1, *p2; if (! str || ! *str) return str; for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) { *p1 ^= *p2; *p2 ^= *p1; *p1 ^= *p2; } return str; } #endif /* !BX_HAVE_STRREV */ #if BX_WITH_MACOS namespace std{extern "C" {char *mktemp(char *tpl);}} #endif #if !BX_HAVE_MKSTEMP int bx_mkstemp(char *tpl) { mktemp(tpl); return ::open(tpl, O_RDWR | O_CREAT | O_TRUNC # ifdef O_BINARY | O_BINARY # endif , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP); } #endif // !BX_HAVE_MKSTEMP ////////////////////////////////////////////////////////////////////// // Missing library functions, implemented for MacOS only ////////////////////////////////////////////////////////////////////// #if BX_WITH_MACOS // these functions are part of MacBochs. They are not intended to be // portable! #include #include #include int fd_read(char *buffer, Bit32u offset, Bit32u bytes) { OSErr err; IOParam param; param.ioRefNum=-5; // Refnum of the floppy disk driver param.ioVRefNum=1; param.ioPosMode=fsFromStart; param.ioPosOffset=offset; param.ioBuffer=buffer; param.ioReqCount=bytes; err = PBReadSync((union ParamBlockRec *)(¶m)); return param.ioActCount; } int fd_write(char *buffer, Bit32u offset, Bit32u bytes) { OSErr err; IOParam param; param.ioRefNum=-5; // Refnum of the floppy disk driver param.ioVRefNum=1; param.ioPosMode=fsFromStart; param.ioPosOffset=offset; param.ioBuffer=buffer; param.ioReqCount=bytes; err = PBWriteSync((union ParamBlockRec *)(¶m)); return param.ioActCount; } int fd_stat(struct stat *buf) { OSErr err; DrvSts status; int result = 0; err = DriveStatus(1, &status); if (status.diskInPlace <1 || status.diskInPlace > 2) result = -1; buf->st_mode = S_IFCHR; return result; } #endif /* BX_WITH_MACOS */ ////////////////////////////////////////////////////////////////////// // New functions to replace library functions // with OS-independent versions ////////////////////////////////////////////////////////////////////// #if BX_HAVE_REALTIME_USEC #if defined(WIN32) static Bit64u last_realtime64_top = 0; static Bit64u last_realtime64_bottom = 0; Bit64u bx_get_realtime64_usec(void) { Bit64u new_bottom = ((Bit64u) GetTickCount()) & BX_CONST64(0x0FFFFFFFF); if(new_bottom < last_realtime64_bottom) { last_realtime64_top += BX_CONST64(0x0000000100000000); } last_realtime64_bottom = new_bottom; Bit64u interim_realtime64 = (last_realtime64_top & BX_CONST64(0xFFFFFFFF00000000)) | (new_bottom & BX_CONST64(0x00000000FFFFFFFF)); return interim_realtime64*(BX_CONST64(1000)); } #elif BX_HAVE_GETTIMEOFDAY Bit64u bx_get_realtime64_usec(void) { timeval thetime; gettimeofday(&thetime,0); Bit64u mytime; mytime=(Bit64u)thetime.tv_sec*(Bit64u)1000000+(Bit64u)thetime.tv_usec; return mytime; } #endif #endif bochs-2.6/CHANGES0000644000175000017500000055765612020641507013355 0ustar guillemguillemChanges in 2.6 (September 2, 2012): Brief summary : - More than 10% CPU emulation speedup ! - Support for AMD's SVM hardware emulation (including extended XAPIC support). - Implemented support for new x86 ISA extensions. Bochs is fully aligned with rev043 of Intel(R) Architecture Manual. - Improved emulation accuracy (critical fixes for APIC, VMX and AVX/XOP emulation). - Bochs internal debugger: new command to show state of a device from the debugger. - ROM BIOS: improved PCI boot ROM support (for VGA and other devices) - Networking: - Ported Intel(R) 82540EM Gigabit Ethernet adapter emulation from Qemu. - Added PCI network boot ROM support to all network adapters. - Added TFTP support to the 'slirp' networking module. - Harddrive: added support for VirtualPC disk images, fixed sparse disk images. - Sound: - implemented PC speaker beep using the lowlevel sound interface. - SDL audio output support. - Added ability to set log action per device from .bochsrc. - Moved disk imaging, networking, sound and USB devices to subdirectories in the iodev folder. Detailed change log : - CPU - Implemented EPT A/D extensions support. Bochs is fully aligned with rev043 of the of Intel(R) Architecture Manual. - Implemented ADX (ADCX/ADOX) instructions support, the feature can be enabled using .bochsrc CPUID option. - More than 10% CPU emulation speedup with even more optimal lazy flags handling, stack access optimizations and cross branch trace linking. - Support for AMD's SVM hardware emulation in Bochs CPU, to enable configure with --enable-svm option - Implemented AMD Extended XAPIC support, to enable set .bochsrc CPU APIC option to 'xapic_ext' ! Added Corei5 750 (Lynnfield) configuration to the CPUDB ! Added Turion64 (Tyler) configuration to the CPUDB ! Added AMD Phenom X3 8650 (Toliman) configuration to the CPUDB ! Added Corei7 3770K (Ivy Bridge) configuration to the CPUDB - Bugfixes for CPU emulation correctness and stability (critical fixes for APIC/X2APIC, VMX and AVX/XOP emulation) - Bochs Debugger and Instrumentation - Implemented new debugger command 'info device [string]' that shows the state of the device specified in 'string' - Improved debug dump for ne2k, pci, pic and vga/cirrus devices. Added debug dump for pci2isa, i/o apic, cmos, pit, floppy and dma devices. - Added TLB to CPU param tree - now it can be browsed from Bochs internal debugger and Bochs debugger GUI through param tree interfaces - Implemented 'writemem' debugger command to dump virtual memory block starting from selected linear address into a file - Updated definition of instrumentation callbacks, see description in instrumentation.txt / Fixed instrumentation examples - Configure and compile - Moved disk imaging, networking, sound and USB devices to subdirectories in the iodev folder. - pcidev: enable support for Linux kernel 3.x (Debian patch by Guillem Jover) - debugger: generate parser / lexer files only if all required tools are present - Config interface - Added support for direct device plugin loading with bochsrc directive for devices which have the same name for the plugin and config option. - The bochsrc option 'plugin_ctrl' can now be used to load/unload optional plugins directly when parsing the config file or command line. See the bochsrc sample for supported devices. - Moved bochsrc parsing / writing and config parameter handling for networking, sound and USB devices to the plugin device code. The options are only available when the corresponding plugin device is loaded. - Added ability to set log action per device from .bochsrc. - Added new command line option '-noconsole' to disable the console window on Windows host. - Renamed PCI Pseudo NIC option to "pcipnic" (for direct plugin loading) - Moved several related options to the new "keyboard" bochsrc option. - Added new parameter 'rtc_sync' for the 'clock' option. If this option is enabled together with the realtime synchronization, the RTC runs at realtime speed. - Moved MWAIT_IS_NOP bochsrc option from CPUID to CPU so it can be set even if cpu was configured using pre-defined CPUDB profile. - Allow larger CPU 'quantum' values when emulating SMP systems for speed (quantum values up to 32 are allowed now). - I/O Devices - Networking - Ported Intel(R) 82540EM Gigabit Ethernet adapter emulation from Qemu, to enable configure with option --enable-e1000 - Added PCI network boot ROM support to all network adapters - Added TFTP support to the 'slirp' networking module - PCI - added "auto-assign to PCI slot" feature for PCI-only devices - DMA - Added the capability to transfer more then one byte / word per ISA DMA cycle - VGA - Major rewrite of the vga / cirrus code: - vgacore (shared standard VGA emulation code) - vga (Bochs VBE and PCI VGA) - cirrus (CL-GD 5430 ISA / CL-GD 5446 PCI) - Added VGA graphics blinking support - More accurate vertical and horizontal retrace emulation (based on the DOSBox implementation) - hard drive / hdimage - added new disk image mode 'vpc' for VirtualPC images - undoable mode: added coherency check (flat image size and timestamp) - sparse mode: fixed read support - Sound - implemented PC speaker beep using the lowlevel sound interface - added SDL audio output support - ROM BIOS - improved PCI boot ROM support (for VGA and other devices) - added MADT entry for Interrupt Source Override to ACPI tables - GUI and display libraries - implemented "auto-off" timer for status LEDs indicating a data transfer - Added support for sending absolute mouse position values from the gui if an absolute pointing device (USB tablet) is active (rfb, sdl, win32, wx, x). - Gui debugger now supported when using sdl gui on Windows - Implemented "hideIPS" option in rfb, sdl, win32 and wx libraries - wx: fixed random freezes with wxGTK and "show ips" feature enabled - rfb: the "show ips" feature now works on Windows host - Tools - bxcommit: added support for converting growing to flat mode images - bxcommit: support command line options and non-interactive (quiet) mode - bximage: increased maximum disk size to 8 TB - SF patches applied [3540389] Patch 5 : Change memory reference functions argument order by Yeong-uk Jo [3539254] Patch 4 : Memory reference optimization 2 by Yeong-uk Jo [3539251] Patch 3 : Memory reference optimization by Yeong-uk Jo [3539237] Patch 2 : Some optimization by Yeong-uk Jo [3539228] Patch 1 : ROM BIOS Compatibility patch by Yeong-uk Jo [3505209] Fixed combo box size by Konrad Grochowski [2864391] Gui debugger default regs by Thomas Nilsen [3486555] Fix critical stack leak in Win32 GUI by Carlo Bramini - these S.F. bugs were closed/fixed [625877] wx: power button -> thread deadlock [3534063] Configure does not check for flex presence [3555237] NE2000 doesn't compile on OS/X [3553168] X doesn't build in latest code on OS/X [3550175] Crash when saving snapshot to directory instead of file [3548109] VMX State Not Restored After Entering SMM on 32-bit Systems [3548108] VMEXIT Instruction Length Not Always Getting Updated [3545941] Typo in preprocessor symbol [3538731] Missing CR8 register [3538574] Missing XD flag ( Execute Disable ) when showing PTEs [3537556] Missing initializations [3537309] Unable to use the debug GUI with SDL and plugins [3537473] GUI debugger only shows 32-bit CRx registers in x86-64 mode [3533426] UHCI PCI interrupts [3459359] svga cirrus initialization [3535228] info gdt does not show long mode segments [3531806] Bochs crashes (SIGSEGV) when starting via ssh console [3531807] Various missing initialization values reported by Valgrind [635789] mapping mode 0 not supported [3307201] BOCHS panics when execute HBIOS.COM [3528809] IO APIC index register width [3528516] Missing #if in soundmod.h [3526069] MADT:Interrupt Source Override missed [3518753] update dump after manual chages to memory contents [3516859] bug in svn e1000 module [3516029] stepping not working in debugger GUI in case of smp vm [3510403] closing config dialog box closes entire simulator [3459998] Bochs cannot be compiled outside the source tree [2905969] can't use --enable-gdb-stub on vs2008 [3294001] Bochs GUI doesn't appear properly for 2nd Bochs copy [3493315] Changing VGA 9/8 dot mode causes screen corruption - these S.F. feature requests were closed/implemented [3540441] automatically enable devices in plugin control [1251456] command line method to query bochs for features [3409396] sdl sound [3519794] debugger's ability to save physical/linear memory dumps [1429612] Idea how to speedup simulation - stack direct access [1703452] Other Network Devices? [2919376] Disable show the console window [534271] can't set log action by device (bochsrc) ------------------------------------------------------------------------- Changes in 2.5.1 (January 6, 2012): - CPU / CPUDB ! Added Athlon64 (Venice) configuration to the CPUDB - BMI: fixed EFLAGS after BMI instructions - MSR: access to AMD extended MSR space was impossible due to a bug in RDMSR/WRMSR - VMX: fixed VMFUNC instruction behavior to align with Intel SDM revision 041 - VMX: fixed Bochs PANIC when doing I/O access crossing VMX I/O permission bitmaps - VMX: fixed VirtualBox VMX guest Guru Meditation - FS.BASE got corrupted after saving/restoring unusable FS selector - VMX: fixed VirtualBox failures with VMX+EPT enabled - Better report of supported CPUID features when not using pre-defined CPUID profile - Debugger / Instrumentation - fixed typo - closing SF bug [3461405] step all command fails in SMP mode - instrumentation: added special indication for indirect call/jump - Configure and compile - fixed compilation err in instrumentation call (tasking.cc) - fixed compilation err with x86 hw breakpoint enabled and CPU_LEVEL < 6 - fixed compilation issue under win32 --with-nogui - added missing dependencies for cdrom_osx.o - removed very old deprecated configure options from configure script - I/O Devices - fixed possible failures of PCI DMA transfers - VVFAT: several fixes in the optional write support (passes test with XP) - USB UHCI: some fixes to make it work in XP guest - removed devices 'acpi', 'ioapic' and 'pci_ide' from optional plugin control to avoid trouble - Config interface / GUI and display libraries - added VMX .bochsrc option to control VMX support on runtime - fix for x86-64 .bochsrc option parsing (patch from @SF) - fix for @SF bug: Crash on WIN2K - ID: 3454214 - added 'nokeyrepeat' option for the SDL and win32 gui ------------------------------------------------------------------------- Changes in 2.5 (November 27, 2011): Bochs repository moved to the SVN version control ! Brief summary : ! Fully configurable CPU to emulate with a single .bochsrc option ! - 10% (ST) to 50% (SMP) CPU emulation speedup ! - Implemented support for new x86 ISA extensions, Bochs is aligned with latest published Intel Architecture Manual (rev 040, AVX rev 011): - XSAVEOPT, AVX/AVX2/FMA/F16C, BMI1/BMI2, SMEP, INVPCID, TSC-Deadline - VMX: VMX Preemption Timer, Pause Loop Exiting and VM Functions - Implemented support for AMD SSE4A/XOP/FMA4/TBM instruction sets - Networking: introduced new networking module 'slirp' - Harddrive: fixed buffer overflow causing Bochs crash in LBA48 mode - VGA: Added PCI ROM support to cirrus and pcivga and moved ROM loading for the ISA case to the vga code (SeaBIOS now usable by Bochs) - Sound: ported ES1370 soundcard emulation from Qemu - Continuing configure rework, check for more removed configure and .bochsrc options and their replacements ! - LGPL'd VGABIOS updated to version 0.7a Detailed change log : - CPU - Now you can configure CPU to emulate using a single .bochsrc option ! The option selects CPU configuration to emulate from pre-defined list of supported configurations. When this option is used, Bochs CPU emulation engine is automatically configured to emulate a specific real hardware CPU, including exact CPUID matching reference hardware. Check .bochsrc example or check user manual for list of supported configurations and more details. * It is also possible to choose the CPU to emulate from Bochs command line using command line interface to .bochsrc: "cpu::model " * Query for supported CPU models using command line option: -help cpu. - 10% emulation speedup with handlers chaining optimization implemented. The feature is enabled by default when configure with --enable-all-optimizations option, to disable handlers chaining speedups configure with --disable-handlers-chaining - New way of CPUs scheduling in SMP mode brings up to 50% speedup to the SMP emulation. New implementation uses dynamic CPU quantum value and takes full advantage of the trace cache. Each emulated processor will execute the whole trace before switching to the next processor. * It is also safe to use large (up to 16 instructions) quantum values for the SMP emulation now and improve performance even further. - Implemented Supervisor Mode Execution Protection (SMEP), the feature can be enabled using .bochsrc CPUID option. - Added support for XSAVEOPT instruction, the instruction can be enabled using .bochsrc CPUID option. - Added support for AVX and AVX2 instructions emulation, to enable configure with --enable-avx option. When compiled in, AVX still has to be enabled using .bochsrc CPUID option. - Added emulation of AVX float16 convert instructions, the feature can be enabled using .bochsrc CPUID option. - Added support for AVX2 FMA instructions emulation. The implementation was ported (with few bugfixes) from QEMU patch by Peter Maydell. The FMA instructions support can be enabled using .bochsrc CPUID option. - Added support for Bit Manipulation Instructions (BMI1/BMI2) emulation. The BMI instructions support can be enabled using .bochsrc CPUID option. - Added support for AMD SSE4A/XOP/FMA4/TBM extensions emulation, the instructions can be enabled using .bochsrc CPUID option. - Implemented VMX preemption timer VMEXIT control (patch by Jianan Hao) - Implemented Pause-Loop Exiting Secondary VMEXIT control. - Implemented VM Functions support and EPTP-Switching VM Function. - Added INVPCID instruction emulation support. - Added APIC timer TSC-Deadline mode emulation support. - Now you could disable x86-64 from .bochsrc so it become possible to emulate 32-bit CPUs using Bochs binary compiled with x86-64 support. - Updated/fixed instrumentation callbacks. - Bugfixes for CPU emulation correctness and stability. - Bochs Internal Debugger and Debugger GUI - Bochs disassembler fixes / new instructions support. - Fixed timer breakpoint handling in Bochs internal debugger. - Fixed bug in Bochs internal debugger 'show off' command. - Added Bochs internal debugger command 'vmexitbp' to set breakpoint on VMX guest VMEXIT (patch by Jianan Hao). Type 'vmexitbp' in debugger command window to switch it on/off (similar to modebp). - Fixed linear to physical address translation by Bochs internal debugger for EPT unrestricted guest (VMX guest with paging disabled under EPT) - Fixed bug in GUI debugger SSE registers display. - Correctly display current CPU mode in GUI debugger status bar. - Turn off the mouse capture when the internal debugger or gdbstub enter the input loop. - Memory - Added new configure option which enables RAM file backing for large guest memory with a smaller amount host memory, without causing a panic when host memory is exhausted (patch by Gary Cameron). To enable configure with --enable-large-ramfile option. - Configure and compile - Fixed Bochs manifest for Win64 compilation using Microsoft Visual Studio command line compiler. - Added ability to configure CPUID family through .bochsrc. The default family value determined by configure option --enable-cpu-level. - Added ability to configure CPUID model through .bochsrc. The default model value is 3. - Added ability to configure x2apic support through .bochsrc. The APIC configuration could be selected using new CPUID .bochsrc APIC option. Possible configurations are: "legacy", "xapic" and "x2apic". Configure option --enable-x2apic and Bochs 2.4.6 .bochsrc XAPIC option are deprecated and should not be used anymore. - Configure option --enable-vbe is deprecated and should not be used anymore. The VBE support is always automatically compiled in, in order to enable VBE support the .bochsrc option "vga: extension=" has to be set to "vbe". If PCI is present, the "pcivga" device can be assigned to PCI slot. - Configure option --enable-acpi is deprecated and should not be used anymore. The ACPI support is always automatically compiled in if PCI is compiled in. The ACPI still could be disabled using .bochsrc 'plugin_ctrl' option. - Removed --enable-trace-cache configure option. The option will be always ON for any Bochs configuration. - Compile in MONITOR/MWAIT support by default for all cpu-level=6 configurations. - added support for MSVC DLL plugins with a separate workspace package. VS2008Ex can now create a BOCHS.EXE with a set of plugin DLLs. TODO: nmake still cannot create plugin DLLs. - removed some outdated / unmaintained parts from the Bochs code: BeOS host support, plex86 support, networking module 'arpback', text snapshot check feature. - I/O Devices - Networking - new networking module 'slirp' (user mode networking using Slirp and a builtin DHCP server) - Hard drive / cdrom - fixed buffer overflow causing Bochs crash in LBA48 mode - implemented ATA commands "READ NATIVE MAX ADDRESS" and "READ NATIVE MAX ADDRESS EXT" - Sound - ported ES1370 soundcard emulation from Qemu, to enable configure with the option --enable-es1370 - sound input implemented in the sound lowlevel modules for Windows and Linux (ALSA / OSS) - PCI - added framework for PCI ROM support - new bochsrc option 'pci' replaces the 'i440fxsupport' option. The 'chipset' parameter for now only accepts the value 'i440fx'. - VGA - added PCI ROM support to cirrus and pcivga and moved ROM loading for the ISA case to the vga code (SeaBIOS now usable by Bochs) - log prefix now depends on the selected extension (new prefix BXVGA for Bochs VBE support) - USB - experimental USB xHCI support (written by Ben Lunt) - LGPL'd VGABIOS updated to version 0.7a - implemented vgabios functions with AX=0x112x (patch by Hugo Mercier) - fixed DAC palette in 8 bpp VBE and Cirrus modes (using the same palette as VGA mode 0x13) - VBE: added HDTV resolutions (patch by Tristan Schmelcher) - VBE: added PCI ROM signature and data structure - ROM BIOS - Report memory above 4GB to BIOS (patch by Sebastian Herbszt) - added PCI ROM init code for BIOS-bochs-latest (WARNING: legacy BIOS no longer works with a PCI display adapter) - GUI and display libraries - new parameter 'update_freq' for the 'vga' bochsrc option replaces the 'vga_update_interval' option - vga update frequency now uses host timing if the realtime synchronization is enabled with the "clock" option (FIXME: it should always be used - independent from the "clock" setting) - Implemented graphics mode snapshot for VBE, Cirrus and standard VGA modes. CGA modes are not supported yet. - added 'x' display library option 'nokeyrepeat' to turn off keyboard repeat - Config interface - win32paramdlg: dialog size now adjusted to support larger label text - win32paramdlg: added tooltip support using the parameter description - SF patches applied [3412431] Enabling raw devices as hdimage by affiss [3435049] rombios: fix package size in pointing device flags 2 by Sebastian Herbszt [3426460] [PATCH] PIC: remove never-executed code by Christian Inci [3370604] Ctrl-Break support for the bochs BIOS by Nikolay Nikolov [3302668] VMX preemption timer by Jianan Hao [3327510] Fix wrong address translation in debugger by Jianan Hao [3323758] Ctrl-Break support for the Win32 gui by Nikolay Nikolov [3316785] Ctrl-Break support for the X11 gui by Nikolay Nikolov [3298173] Breakpoint on VMEXIT event by Jianan Hao [3295737] Fix CopyHost*WordLittleEndian macros by Heikki Lindholm [3289448] optimized powerpc byte swapping by Heikki Lindholm [3292581] Core Audio first aid by Heikki Lindholm [3205979] Compilation fixes for OpenBSD by Brad Smith [3290979] acpi/muldiv64 endian bug by Heikki Lindholm [3289459] Mac OS X audio missing framework dependency by Heikki Lindholm [3267459] fix xrandr related crash by Heikki Lindholm [3190995] add eth backend based on Slirp by Heikki Lindholm - these S.F. bugs were closed/fixed [3365456] block device dimensions problem [3441564] interrupts vectors 0x67 should also be NULL ! cf: 2902118 [2829847] Mouse locked during magic-break [3418621] release mouse when debugger breakpoint was hit [1947077] sb command bug [2802677] Unable to install Cirrus SVGA driver in guest Windows ME [3422638] large ramfile support broken on anything but Linux [3312237] stepN command might be not working properly [3392760] Bochs does not compile with linux3.0 [3403746] segfault crash with sparse disk images [3062054] Problems with BIOS pointing device services (int 15h) [3277639] incompatible colours in palette [1788739] Abort on large memory setting [3012207] Int 13h FN 48h incorrect return values [3363289] holding shift key causes capslock hang [1819639] Two incompatible crc32 modules [3324111] configure for VCPP.NET issues [3190970] Installing linux causes a crash in pci_ide [3077616] Fedora 13 installation fails on Bochs 2.4.5 [3294671] ./configure --enable-pci --disable-cdrom [3303818] wrong memory size is reported to GRUB (e820 problem?) [3297475] trace cache disabled mode will miss SMC [3170157] BIOS32 PCI service wrong length [3025030] PIT mistakenly connected to IRQ0 IOAPIC instead of IRQ2 [3266738] GUI debugger does not update CPU mode correctly [3292571] SB16 doesn't reinit correctly [3175168] Cirrus CL-GD5446 emulation incorrect [3260134] Failed to compile when trace cache disabled [3197425] Error compile with vmx in vs2008/2010 and for correct x64 - these S.F. feature requests were closed/implemented [3424738] Legacy BIOS int13 AL=17/18h diskette issue [1197067] Screenshot for graphical [2800839] VMX-preemption timer [1507519] configurable CPUID [579002] Allow user to specify architecture [1228567] CPU option ------------------------------------------------------------------------- Changes in 2.4.6 (February 22, 2011): Brief summary : - Support more host OS to run on: - Include win64 native binary in the release. - Fixed failures on big endian hosts. - BIOS: Support for up to 2M ROM BIOS images. - GUI: select mouse capture toggle method in .bochsrc. - Ported most of Qemu's 'virtual VFAT' block driver (except runtime write support, but plus FAT32 support) - Added write protect option for floppy drives. - Bugfixes / improved internal debugger + instrumentation. Detailed change log : - CPU and internal debugger - Implemented Process Context ID (PCID) feature - Implemented FS/GS BASE access instructions support (according to document from http://software.intel.com/en-us/avx/) - Rewritten from scratch SMC detection algorithm - Implemented fine-grained SMC detection (on 128 byte granularity) - Bugfixes for CPU emulation correctness and stability - Fixed failures on Big Endian hosts ! - Print detailed page walk information and attributes in internal debugger 'page' command - Updated/Fixed instrumentation callbacks - Configure and compile - Bochs now can be compiled as native Windows x86-64 application (tested with Mingw gcc 4.5.1 and Microsoft Visual Studio Express 2010) - Added ability to configure CPUID stepping through .bochsrc. The default stepping value is 3. - Added ability to disable MONITOR/MWAIT support through .bochsrc CPUID option. The option is available only if compiled with --enable-monitor-mwait configure option. - Determine and select max physical address size automatically at configure time: - 32-bit physical address for 386/486 guests - 36-bit physical address for PSE-36 enabled Pentium guest - 40-bit physical address for PAE enabled P6 or later guests - Update config.guess/config.sub scripts to May 2010 revisions. - Update Visual Studio 2008 project files in build/win32/vs2008ex-workspace.zip - Added Bochs compilation timestamp after Bochs version string. - GUI and display libraries (Volker) - Added new .bochsrc option to select mouse capture toggle method. In addition to the default Bochs method using the CTRL key and the middle mouse button there are now the choices: - CTRL+F10 (like DOSBox) - CTRL+ALT (like QEMU) - F12 (replaces win32 'legacyF12' option) - display library 'x' now uses the desktop size for the maximum guest resolution - ROM BIOS - Support for up to 2M ROM BIOS images - I/O Devices - 3 new 'pseudo device' plugins created by plugin separation (see below) - Fixes for emulated DHCP in eth_vnet (patch from @SF tracker) - Added support for VGA graphics mode with 400 lines (partial fix for SF bug #2948724) - NE2K: Fixed "send buffer" command issue on big endian hosts - USB - converted common USB code plus devices to the new 'usb_common' plugin Now the USB device classes no longer exist twice if both HC plugins are loaded. - added 'pseudo device' in common USB code for the device creation. This makes the HCs independent from the device specific code. - USB MSD: added support for disk image modes (like ATA disks) - USB printer: output file creation failure now causes a disconnect - re-implemented "options" parameter for additional options of connected devices (currently only used to set the speed reported by device and to specify an alternative redolog file of USB MSD disk image modes) - hard drive - new disk image mode 'vvfat' - ported the read-only part of Qemu's 'virtual VFAT' block driver - additions: configurable disk geometry, FAT32 support, read MBR and/or boot sector from file, volatile write support using hdimage redolog_t class, optional commit support on Bochs exit, save/restore file attributes, 1.44 MB floppy support, set file modification date/time - converted the complete hdimage stuff to the new 'hdimage' plugin - new hdimage method get_capabilities() that can return special flags - vmware3, vmware4 and vvfat classes now return HDIMAGE_HAS_GEOMETRY flag - other disk image modes by default return HDIMAGE_AUTO_GEOMETRY if cylinder value is set to 0 - multiple sector read/write support for some image modes - new log prefix "IMG" for hdimage messages - floppy - added write protect option for floppy drives (based on @SF patch by Ben Lunt) - vvfat support - bugfix: close images on exit - SB16 - converted the sound output module stuff to the new 'soundmod' plugin - SF patches applied [3164945] hack to compile under WIN64 by Darek Mihocka and Stanislav [3164073] Fine grain SMC invalidation by Stanislav [1539417] write protect for floppy drives by Ben Lunt [2862322] fixes for emulated DHCP in eth_vnet - these S.F. bugs were closed/fixed [2588085] Mouse capture [3140332] typo in mf3/ps2 mapping of BX_KEY_CTRL_R [3111577] No "back" option in log settings [3108422] Timing window in NE2K emulation [3084390] Bochs won't load floppy plugin right on startup [3043174] Docbook use of '_' build failure [3085140] Ia_arpl_Ew_Rw definition of error [3078995] ROL/ROR/SHL/SHR modeling wrong when dest reg is 32 bit [2864794] BX_INSTR_OPCODE in "cpu_loop" causes crash in x86_64 host [2884071] [AIX host] prefetch: EIP [00010000] > CS.limit [0000ffff] [3053542] 64 bit mode: far-jmp instruction is error [3011112] error compile vs2008/2010 with X2APIC [3002017] compile error with vs 2010 [3009767] guest RFLAGS.IF blocks externel interrupt in VMX guest mode [2964655] VMX not enabled in MSR IA32_FEATURE_CONTROL [3005865] IDT show bug [3001637] CMOS MAP register meaning error [2994370] Cannot build with 3DNow support - these S.F. feature requests were closed/implemented [1510142] Native Windows XP x64 Edition binary [1062553] select mouse (de)activation in bochsrc [2930633] legacy mouse capture key : not specific enough [2930679] Let user change mouse capture control key [2803538] Show flags for pages when using "info tab" ------------------------------------------------------------------------- Changes in 2.4.5 (April 25, 2010): Brief summary : - Major configure/cpu rework allowing to enable/disable CPU options at runtime through .bochsrc (Stanislav) - Bugfixes for CPU emulation correctness and stability - Implemented X2APIC extensions (Stanislav) - Implemented Intel VMXx2 extensions (Stanislav) - Extended VMX capability MSRs, APIC Virtualization, X2APIC Virtualization, Extended Page Tables (EPT), VPID, Unrestricted Guests, new VMX controls. - Implemented PCLMULQDQ AES instruction - Extended Bochs internal debugger functionality - USB HP DeskJet 920C printer device emulation (Ben Lunt) Detailed change log : - Configure rework - Deprecate --enable-popcnt configure option. POPCNT instruction will be enabled automatically iff SSE4_2 is supported (like in hardware). - Make --ignore-bad-msrs runtime option in .bochsrc. Old --ignore-bad-msrs configure option is deprecated and should not be used anymore. - Enable changing part of CPU functionality at runtime through .bochsrc. - Now you could enable/disable any of SSEx/AES/MOVBE/SYSENTER_SYSEXIT/XSAVE instruction sets using new CPUID option in .bochsrc. - When x86-64 support is compiled in, you could enable/disable long mode 1G pages support without recompile using new CPUID option in .bochsrc. Configure options: --enable-mmx, --enable-sse, --enable-movbe, --enable-xsave, --enable-sep, --enable-aes, --enable-1g-pages are deprecated and should not be used anymore. - Local APIC configure option --enable-apic is deprecated and should not be used anymore. The LAPIC option now automatically determined from other configure options. XAPIC functionality could be enabled using new CPUID .bochsrc option. - Changed default CPU configuration (generated by configure script with default options) to BX_CPU_LEVEL=6 with SSE2 enabled. - CPU - Implemented PCLMULQDQ AES instruction - Implemented X2APIC extensions / enable extended topology CPUID leaf (0xb), in order to enable X2APIC configure with --enable-x2apic - Implemented Intel VMXx2 extensions: - Enabled extended VMX capability MSRs - Implemented VMX controls for loading/storing of MSR_PAT and MSR_EFER - Enabled/Implemented secondary proc-based vmexec controls: - Implemented APIC virtualization - Implemented Extended Page Tables (EPT) mode - Implemented Descriptor Table Access VMEXIT control - Implemented RDTSCP VMEXIT control - Implemented Virtualize X2APIC mode control - Implemented Virtual Process ID (VPID) - Implemented WBINVD VMEXIT control - Implemented Unrestricted Guest mode In order to enable emulation of VMXx2 extensions configure with --enable-vmx=2 option (x86-64 must be enabled) - Bugfixes for CPU emulation correctness - Fixed Bochs crash when accessing the first byte above emulated memory size - Internal Debugger - Introduced range read/write physical watchpoints - Allow reloading of segment registers from internal debugger - Improved verbose physical memory access tracing - BIOS - Fix MTRR configuration (prevented boot of modern Linux kernels) - Fix interrupt vectors for INT 60h-66h (reserved for user interrupt) by setting them to zero - Fix BIOS INT13 function 08 when the number of cylinders on the disk = 1 - I/O Devices - USB HP DeskJet 920C printer device emulation (Ben Lunt) - Misc - Updated Bochs TESTFORM to version 0.5 - SF patches applied [2864402] outstanding x2apic patches by Stanislav [2960379] Fix build with -Wformat -Werror=format-security by Per Oyvind Karlsen [2938273] allow instrumentation to change execute by Konrad Grochowski [2926072] Indirection operators in expressions by Derek Peschel [2914433] makesym.perl misses symbols by John R. Jackson [2908481] USB Printer by Ben Lunt - these S.F. bugs were closed/fixed [2861662] dbg_xlate_linear2phy needs to be updated [2956217] INT13 AH=8 returns wrong values when cylinders=1 [2981161] Allow DMA transfers to continue when CPU is in HALT state [2795115] NX fault could be missed [2964824] bad newline sequence in aspi-win32.h [913419] configure options and build process needs some work [2938398] gdbstub compile error with x86_64 enabled [2734455] shutdown/reset type 05 should reinit the PICs [1921294] extended memory less than 1M wrong size [1947249] BX_USE_EBDA_TABLES and MP table placement [1933859] BX_USE_EBDA_TABLES and memory overlapping [2923680] "help dregs" is a syntax error [2919661] CPU may fail to do 16bit near call [2790768] Memory corruption with SMP > 32, Panic BIOS Keyboard Error [2902118] interrupts vectors 0x60 to 67 should be NULL ! [2912502] Instruction Pointer behaving erratically [2901047] Bochs crashed, closed by guest os [2905385] Bochs crash [2901481] Instruction SYSRET and SS(PL) [2900632] Broken long mode RETF to outer priviledge with null SS [1429011] Use bx_phyaddr_t for physaddr vars and bx_adress for lin adr - these S.F. feature requests were closed/implemented [2955911] RPM preuninstall scriptlet removes /core [2947863] don't abort on unrecognised options [2878861] numerics in the disassembler output [2900619] make more CPU state changeable ------------------------------------------------------------------------- Changes in 2.4.2 (November 12, 2009): - CPU and internal debugger - VMX: Implemented TPR shadow VMEXIT - Bugfixes for CPU emulation correctness (mostly for VMX support). - Bugfixes and updates for Bochs internal debugger - On SMP system stepN command now affects only current processor - Memory - Bugfixes for > 32-bit physical address space. - Allow to emulate more physical memory than host actually could or would like to allocate. For more details look for new .bochsrc 'memory' option. - Cleanup configure options - All paging related options now will be automatically determined according to --enable-cpu-level option. Related configure options --enable-global-pages, --enable-large-pages, --enable-pae, --enable-mtrr are deprecated now. Only 1G paging option still remaining unchanged. - Deprecate --enable-daz configure option. Denormals-are-zeros MXCSR control will be enabled automatically iff SSE2 is supported (like in hardware). - Deprecate --enable-vme configure option, now it will be supported iff CPU_LEVEL >= 5 (like in hardware). - I/O Devices - Bugfixes for 8254 PIT, VGA, Cirrus-Logic SVGA, USB UCHI - SF patches applied [2817840] Make old_callback static by Mark Marshall [2874004] fix for VMWRITE instruction by Roberto Paleari [2873999] fix CS segment type during fast syscall invocation by Roberto Paleari [2864389] Debugger gui maximize on startup by Thomas Nilsen [2817868] Rework loops in the memory code by Mark Marshall [2812948] PIT bug by Derek - these S.F. bugs were closed/fixed [2833504] GUI debugger bug-about GDT display [2872244] BIOS writes not allowed value to MTRR MSR causing #GP [2885383] SDL GUI memory leak [2872290] compilation in AIX5.3 ML10 failes [2867904] crash with cirrus bx_vga_c::mem_write [2851495] BIOS PCI returns with INT flag = 0 [2860333] vista 64 guest STOP 109 (GDT modification) [2849745] disassembler bug for 3DNow and SSE opcodes [1066748] Wrong registers values after #RESET, #INIT [2836893] Regression: Windows XP installer unable to format harddrive [2812239] VMX: VM-Exit: Incorrect instruction length on software int [2814130] bx_debug lex/yacc files incorrectly generated [2813199] MP Tables Missing From BIOS [2824093] VMX exception bug [2811909] VMX : CS Access-rights Type.Accessed stays 0 [2810571] Compile Errors on OSX [2823749] GCC regression or VM_EXIT RDMSR/WRMSR bug [2815929] Vista/XP64 unnecessary panic [2803519] Wrong example in man page bochsrc - these S.F. feature requests were closed/implemented [422766] Large Memory configurations [1311287] Idea for a better GUI [455971] USB support [615363] debugger shortcut for repeat last cmd ------------------------------------------------------------------------- Changes in 2.4.1 (June 7, 2009): - Fixed bunch of CPUID issues - Bochs is now able to install and boot 64-bit Windows images! (special thanks to Mark Ebersole for his patch) - Several bugfixes in CPU emulation (mostly for x87 instructions) - Fixed two critical deadlock bugs in the Win32 gui (patches from @SF tracker) - Fixes related to the 'show ips' feature - removed conflicting win32-specific alarm() functions ('win32' and 'sdl' gui) - feature now works in wx on win32 - Added support for gdb stub on big endian machine (patch by Godmar Back) - Rewritten obsolete hash_map code in dbg symbols module (patch from @SF) - BIOS: implemented missing INT 15h/89h (patch by Sebastian Herbszt) ------------------------------------------------------------------------- Changes in 2.4 (May 3, 2009): Brief summary : - Added graphical Bochs debugger frontend for most of the supported platforms. - Thanks for Chourdakis Michael and Bruce Ewing. - Many new CPU features in emulation - Support for > 32 bit physical address space and configurable MSRs - VMX, 1G pages in long mode, MOVBE instruction - Bugfixes for CPU emulation correctness, debugger and CPU instrumentation. - New config interface 'win32config' with start and runtime menu - USB: added OHCI support, external hub and cdrom - Added user plugin interface support. Detailed change log : - CPU and internal debugger - Support for VMX hardware emulation in Bochs CPU, to enable configure with --enable-vmx option Nearly complete VMX implementation, with few exceptions: - Dual-monitor treatment of SMIs and SMM not implemented yet - NMI virtualization, APIC virtualization not implemented yet - VMENTER to not-active state not supported yet - No advanced features like Extended Page Tables or VPID - Support for configurable MSR registers emulation, to enable configure with --enable-configurable-msrs option Look for configuration example in .bochsrc and msrs.def - Support new Intel Atom(R) MOVBE instruction, to enable configure with --enable-movbe option - Support for 1G pages in long mode, to enable configure with --enable-1g-pages option - Support for > 32 bit physical address space in CPU. Up to 36 bit could be seen in legacy mode (PAE) and up to 40 bit in x86-64 mode. Still support the same amount of the physical memory in the memory object, so system with > 4Gb of RAM yet cannot be emulated. To enable configure with --enable-long-phy-address option. - Implemented modern BIOSes mode limiting max reported CPUID function to 3 using .bochsrc CPU option. The mode is required in order to correctly install and boot WinNT. - Added ability to configure CPUID vendor/brand strings through .bochsrc (patch from @SF by Doug Reed). - Many bugfixes for CPU emulation correctness (both x86 and x86-64). - Updated CPU instrumentation callbacks. - Fixed Bochs internal debugger breakpoints/watchpoints handling. - Configure and compile - Added ability to choose Bochs log file name and Bochs debugger log file name from Bochs command line (using new -log and -dbglog options) - Removed Peter Tattam's closed source external debugger interface from the code. - Removed --enable-guest2host-tlb configure option. The option is always enabled for any Bochs configuration. - Removed --enable-icache configure option. The option is always enabled for any Bochs configuration. Trace cache support still remains optional and could be configured off. - Added configure option to compile in GUI frontend for Bochs debugger, to enable configure with --enable-debugger-gui option. The GUI debugger frontend is enabled by default with Bochs debugger. - Removed --enable-port-e9-hack configure option. The feature now could be configured at runtime through .bochsrc. - Added configure option to enable/disable A20 pin support. Disabling the A20 pin support slightly speeds up the emulation. - reduced dependencies between source files for faster code generation - BIOS - Added S3 (suspend to RAM) ACPI state to BIOS (patch by Gleb Natapov) - Implemented MTRR support in the bios (patches by Avi Kivity and Alex Williamsion with additions by Sebastian Herbszt) - Bug fixes - I/O Devices - Added user plugin support - remaining devices converted to plugins: pit, ioapic, iodebug - added 'plugin_ctrl' bochsrc option to control the presence of optional device plugins without a separate option. By default all plugins are enabled. - added register mechanism for removable mouse and keyboard devices - Hard drive / cdrom - PACKET-DMA feature now supported by all ATAPI commands - ATAPI command 0x1A added (based on the Qemu implementation) - sb16 - Added ALSA sound support on Linux (PCM/MIDI output) - FM synthesizer now usable with MIDI output (simple piano only) - Fixed OPL frequency to MIDI note translation - Fixed MIDI output command - keyboard - added keyboard controller commands 0xCA and 0xCB - USB - USB code reorganized to support more HC types and devices - added USB OHCI support written by Ben Lunt - added external USB hub support (initial code ported from Qemu) - added USB cdrom support (SCSI layer ported from Qemu) - added status bar indicators to show data transfer - VGA - VBE video memory increased to 16 MB - implemented changeable VBE LFB base address (PCI only, requires latest BIOS and VGABIOS images) - I/O APIC - implemented I/O APIC device hardware reset - Config interface - new config interface 'win32config' with start and runtime menu is now the default on Windows ('textconfig' is still available) - win32 device config dialogs are now created dynamicly from a parameter list (works like the wx ParamDialog) - changes in textcofig and the wx ParamDialog for compatibility with the new win32 dialog behaviour - Bochs param tree index keys are case independent now - some other additions / bugfixes in the simulator interface code - Misc - updated LGPL'd VGABIOS to version 0.6c - Updated Bochs TESTFORM to version 0.4 - SF patches applied [2784858] IO Handler names are not compared properly [2712569] Legacy bios serial data buffer timeout bug by grybranix [2655090] 64 bit BSWAP with REX.W broken by M. Eby [2645919] CR8 bug when reading by M. Eby [1895665] kvm: bios: add support to memory above the pci hole by Izik Eidus [2403372] rombios: check for valid cdrom before using it by Sebastian [2307269] acpi: handle S3 by Sebastian [2354134] TAP networking on Solaris/Sparc repaired [2144692] The scsi device can not complete its writing data command by naiyue [1827082] [PATCH] Configurable CPU vendor by Marcel Sondaar [2217229] Panic on EBDA overflow in rombios32 by Sebastian [2210194] Log pci class code by Sebastian [1984662] red led for disk write and titlebar mod by ggbsf [2142955] Fix for monitor/mwait by Doug Gibson [2137774] Patch to fix bug: cdrom: read_block: lseek returned error by Gabor Olah [2134642] Fix scan_to_scanascii table for F11 and F12 by Ben Guthro & Steve Ofsthun [2123036] sdl fullscreen fix by ggbsf [2073039] Remove CMOS accsess from AML code by Gleb Natapov [2072168] smbios: add L1-L3 cache handle to processor information by Sebastian [2055416] bochsrc cpu options for cpuid vendor and brand string by Doug Reed [2035278] rombios: Fix return from BEV via retf by Sebastian [2035260] rombios: El Torito load segment fix by Sebastian [2031978] Fix VMware backdoor command 0Ah by Jamie Lokier [2015277] Remove obsolete comment about DATA_SEG_DEFS_HERE hack by Sebastian [2011268] Set new default format and unit only if both are supported by Sebastian [2001919] gdbstub: fix qSupported reply by Sebastian [2001912] gdbstub: enclose packet data by apostrophes by Sebastian [1998071] fix missing SIGHUP and SIGQUIT with term ui on mingw by Sebastian [1998063] fix wrong colors with term ui by Sebastian [1995064] Compile fix needed for --enable-debugger and gcc 4.3 by Hans de Goede [1994564] Fix typo in RDMSR BX_MSR_MTRRFIX16K_A0000 by Sebastian [1994396] Change hard_drive_post #if by Sebastian [1993235] TESTFORM email address update by Sebastian [1992322] PATCH: fix compilation of bochs 2.3.7 on bigendian machines by Hans de Goede [1991280] Shutdown status code 0Ch handler by Sebastian [1990108] Shutdown status code 0Bh handler by Sebastian [1988907] Shutdown status code 0Ah handler by Sebastian [1984467] two typos in a release! (2.3.7) [1981505] Init PIIX4 PCI to ISA bridge and IDE by Sebastian - these S.F. bugs were closed/fixed [2784148] an integer overflow BUG of Bochs-2.3.7 source code [2695273] MSVC cpu.dsp failure in 2.3.7.zip [616114] Snapshot/Copy crash on Win2K [2628318] 'VGABIOS-latest' bug [1945055] can't 'make install' lastest bochs on loepard [2031993] Mac OS X Makefile bug [1843199] install error on mac osx [2710931] Problem compiling both instrumentation and debugger [2617003] ExceptionInfo conflicts with OS X api [2609432] stepping causes segfault (CVS) [2605861] compile error with --enable-smp [1757068] current cvs(Jul19, 07) failed to boot smp [2426271] cannot get correct symbol entry [2471982] VGA character height glitches [1659659] wrong behaviour a20 at boot [1998027] minwg + --with-term + --with-out-win32 = link failure [1871936] bochs-2.3.6 make fails on wx.cc [1684666] info idt for long mode [2105989] could not read() hard drive image file at byte 269824 [1173093] Debugger totally not supports x86-64 [1803018] new win32debug dialog problems [2141679] windows vcc build broken [2162824] latest cvs fails to compile [2164506] latest bochs fails to start [2129223] MOV reg16, SS not working in real mode due to dead code [2106514] RIS / startrom.com install ALMOST works [2123358] SMP (HTT): wbinvd executed by CPU1 crashes CPU0 [2002758] Arch Linux: >>PANIC<< ATAPI command with zero byte count [2026501] El Torito incorrect boot segment:offset [2029758] BEV can return via retf instead of int 18h [2010173] x command breaks after one error about x/s or x/i [1830665] harddrv PANIC: ATAPI command with zero byte count [1985387] fail to make using gcc4 with --enable-debugger [1990187] testform feedback [1992138] Misspell in cpu/ia_opcodes.h - these S.F. feature requests were closed/implemented [2175153] Update MSVC project files [658800] front end program and bios [1883370] Make cd and floppy images more usable [422783] change floppy size without restarting [2552685] param tree names should be case insensitive [1214659] PC Speaker emu turnoff. Plugin Controll. [1977045] support 40 bit physical address [1506385] Intel Core Duo VT features [1429015] Support for user plugins [1488136] debugger access to floppy controller [1363136] Full debugger SMP and 64 bit support [2068304] Support for ACPI [431032] debugger "x" command [423420] profiling ideas (SMF) [445342] Add FM support? [928439] alsa ------------------------------------------------------------------------- Changes in 2.3.7 (June 3, 2008): Brief summary : + More optimizations in CPU code - Bochs 2.3.7 is more than 2x faster than Bochs 2.3.5 build ! - Implemented LBA48 support in BIOS - Added memory access tracing for Bochs internal debugger - Implemented Intel(R) XSAVE/XRSTOR and AES instruction set extensions - Many fixes in CPU emulation and internal debugger - MenuetOS64 floppy images booting perfect again ! - updated LGPL'd VGABIOS to version 0.6b Detailed change log : - CPU - Support of XSAVE/XRSTOR CPU extensions, to enable configure with --enable-xsave option - Support of AES CPU extensions, to enable configure with --enable-aes option - Fixed Bochs failure on RISC host machines with BxRepeatSpeedups optimization enabled - Implemented SYSENTER/SYSEXIT instructions in long mode - More than 100 bugfixes for CPU emulation correctness (both x86 and x86-64) - MenuetOS64 floppy images booting perfect again ! - Updated CPU instrumentation callbacks - Bochs Internal Debugger and Disassembler - Added memory access tracing for Bochs internal debugger, enable by typing 'trace-mem on' in debugger command line - Many bug fixes in Bochs internal debugger and disassembler - System BIOS (Volker) - Implemented LBA48 support - Added generation of SSDT ACPI table that contains definitions for available processors - Added RTC device to ACPI DSDT table - Added implementation of SMBIOS - I/O devices (Volker) - VGA - Implemented screen disable bit in sequencer register #1 - Implemented text mode cursor blinking - Serial - new serial modes 'pipe-server' and 'pipe-client' for win32 - new serial mode 'socket-server' - Configure and compile - Fixed configure bug with enabling of POPCNT instruction, POPCNT instruction should be enabled by default when SSE4.2 is enabled. - Removed --enable-magic-breakpoint configure option. The option is automatically enabled if Bochs internal debugger is compiled in. It is still possible to turn on/off the feature through .bochsrc. - Allow boot from network option in .bochsrc - Added Bochs version info for Win32 - Display libraries - implemented text mode character blinking in some guis - improved 'X' gui runtime dialogs - SF patches applied [1980833] Fix shutdown status code 5h handler by Kevin O'Connor [1928848] "pipe" mode for serial port (win32 only) by Eugene Toder [1956843] Set the compatible pci interrupt router back to PIIX by Sebastian [1956366] Do not announce C2 & C3 cpu power state support by Igor Lvovsky [1921733] support for LBA48 by Robert Millan [1938185] Fix link problem with --enable-debugger by Sebastian [1938182] Makefile.in - use @IODEV_LIB_VAR@ by Sebastian [1928945] fix for legacy rombios - e820 map and ACPI_DATA_SIZE by Sebastian [1925578] rombios32.c - fix ram_size in ram_probe for low memory setup by Sebastian [1908921] rombios32.c - move uuid_probe() call by Sebastian [1928902] improvements to load-symbols by Eugene Toder [1925568] PATCH: msvc compilation by Eugene Toder [1913150] rombios.c - e820 cover full size if memory <= 16 mb by Alexander van Heukelum [1919804] rombios.c - fix and add #ifdef comments by Sebastian [1909782] rombios.c - remove segment values from comment by Sebastian [1908918] SMBIOS - BIOS characteristics fix by Sebastian [1901027] BIOS boot menu support (take 3) [1902579] rombios32.c - define pci ids by Sebastian [1859447] Pass segment:offset to put_str and introduce %S by Sebastian [1889057] rombios.c - boot failure message by Sebastian [1891469] rombios.c - print BEV product string by Sebastian [1889851] Win32 version information FILEVERSION for bochs.exe by Sebastian [1889042] rombios.c - fix comment by Sebastian [1881500] bochsrc, allow boot: network by Sebastian [1880755] Win32 version information for bochs.exe by Sebastian [1880471] SMBIOS fix type 0 by Sebastian [1878558] SMBIOS fixes by Sebastian [1864692] SMBIOS support by Filip Navara [1865105] Move bios_table_area_end to 0xcc00 by Sebastian [1875414] Makefile.in - change make use by Sebastian [1874276] Added instrumentation for sysenter/sysexit by Lluis [1873221] TLB page flush: add logical address to instrumentation by Lluis [1830626] lba32 support by Samuel Thibault [1861839] Move option rom scan after floppy and hard drive post by Sebastian [1838283] Early vga bios init by Sebastian [1838272] rom_scan range parameter by Sebastian [1864680] Save CPUID signature by Filip Navara - these S.F. bugs were closed [1976171] Keyboard missing break code for enter (0x9C) [666433] physical read/write breakpoint sometimes fails [1744820] info gdt and info idt shows the entire tables [1755652] graphics: MenuetOS64 shows black screen [1782207] Windows Installer malfunction, Host=Linux, Guest=Win98SE [1697762] OS/2 Warp Install Failed [1952548] String to char * warnings [1940714] SYSENTER/SYSEXIT doesn't work in long mode [1422342] SYSRET errors [1923803] legacy rombios - e820 map and ACPI_DATA_SIZE [1936132] Link problem with --enable-debugger & --enable-disasm [1934477] Linear address wrap is not working [1424984] virtual machine freezes in Bochs 2.2.6 [1902928] with debugger cpu_loop leaves CPU with unstable state [1898929] Bochs VESA BIOS violates specs (banks == 1) [1569256] bug in datasegment change in long mode [1830662] ACPI: no DMI BIOS year, acpi=force is required [1868806] VGA blink enable & screen disable [1875721] Bit "Accessed" in LDT/GDT descriptors & #PF [1874124] bx_Instruction_c::ilen() const [1873488] bochs-2.3.6 make fails on dbg_main.cc - these S.F. feature requests were implemented [1422769] SYSENTER/SYSEXIT support in x86-64 mode [1847955] Version information for bochs(dbg).exe [939797] SMBIOS support ------------------------------------------------------------------------- Changes in 2.3.6 (December 24, 2007): Brief summary : + More than 25% emulation speedup vs Bochs 2.3.5 release! - Thanks to Darek Mihocka (http://www.emulators.com) for providing patches and ideas that made the speedup possible! + Up to 40% speedup vs Bochs 2.3.5 release with trace cache optimization! - Lots of bugfixes in CPU emulation - Bochs benchmarking support - Added emulation of Intel SSE4.2 instruction set Detailed change log : - CPU - Added emulation of SSE4.2 instruction set, to enable use --enable-sse=4 --enable-sse-extension configure options to enable POPCNT instruction only use configure option --enable-popcnt - Implemented MTRR emulation, to enable use --enable-mtrr configure option. MTRRs is enabled by default when cpu-level >= 6. - Implemented experimental MONITOR/MWAIT support including optimized MWAIT CPU state and hardware monitoring of physical address range, to enable use --enable-monitor-mwait configure option. - Removed hostasm optimizations, after Bochs rebenchmarking it was found that the feature bringing no speedup or even sometimes slows down emulation! - Merged trace cache optimization patch, the trace cache optimization is enabled by default when configure with --enable-all-optimizations option, to disable trace cache optimization configure with --disable-trace-cache - Many minor bugfixes in CPU emulation (both ia32 and x86-64) - Updated CPU instrumentation callbacks - Bochs Internal Debugger and Disassembler - Many fixes in Bochs internal debugger and disassembler, some debugger interfaces significantly changed due transition to the param tree architecture - Added support for restoring of the CPU state from external file directly from Bochs debugger - Configure and compile - Renamed configure option --enable-4meg-pages to --enable-large-pages. The option enables page size extensions (PSE) which refers to 2M pages as well. - Removed --enable-save-restore configure option, save/restore feature changed to be one of the basic Bochs features and compiled by default for all configurations. - Added new Bochs benchmark mode. To run Bochs in benchmark mode execute it with new command line option 'bochs -benchmark time'. The emulation will be automatically stopped after 'time' millions of emulation cycles executed. - Another very useful option for benchmarking of Bochs could be enabled using new 'print_timestamps' directive from .bochsrc: print_timestamps: enable=1 - Added --enable-show-ips option to all configuration scripts used to build release binaries, so all future releases will enjoy IPS display. - Enable alignment check in the CPU and #AC exception by default for --cpu-level >= 4 (like in real hardware) - SF patches applied [1491207] Trace Cache Speedup patch by Stanislav [1857149] Define some IPL values by Sebastian [1850183] Get memory access mode in BX_INSTR_LIN_READ by Lluis Vilanova [1841421] pic: keep slave_pic.INT and master_pic.IRQ_in bit 2 in sync by Russ Cox [1841420] give segment numbers in exception logs by Russ Cox [1801696] Allow Intel builds on Mac OS X [1830658] Fix >32GB disk banner by Samuel Thibault [1813314] Move #define IPL_* and typedef ipl_entry by Sebastian [1809001] Save PnP Option ROM Product Name string in IPL Boot Table by Sebastian [1821242] Fix for #1801285, Niclist.exe broken by Sebastian [1819567] Code warning cleanup [1816162] Update comment on bios_printf() by Sebastian [1811139] Trivial Fix when BX_PCIBIOS and BX_ROMBIOS32 not defined by Myles Watson [1811190] Improve HD recognition and CD boot by Myles Watson [1811860] Implement %X in bios_printf by Sebastian [1809649] printf %lx %ld %lu by Myles Watson [1809651] move BX_SUPPORT_FLOPPY by Myles Watson [1809652] dpte and Int13DPT fixes by Myles Watson [1809669] clip cylinders to 16383 in hard drive by Myles Watson [1799903] Build BIOS on amd64 by Robert Millan [1799877] Fix for parallel build (make -j2) by Robert Millan - these S.F. bugs were closed [1837354] website bug: View the Source link broken [1801268] Reset from real mode no longer working [1843250] Using forward slashes gives invalid filename [1823446] BIOS bug, local APIC #0 not detected [1801285] Niclist.exe broken [1364472] breakpoints sometimes don't work [994451] breakpoint bug [1801295] NSIS installer vs Windows Notepad [1715328] Unreal mode quirk [1503972] debugger doesn't debug first instruction on exception [1069071] div al, byte ptr [ds:0x7c18] fails to execute [1800080] Wrong "BX_MAX_SMP_THREADS_SUPPORTED" assertion - these S.F. feature requests were implemented [1662687] Download for Win32-exe with x64 Mode and debugging [604221] Debugger command: query lin->phys mapping ------------------------------------------------------------------------- Changes in 2.3.5 (September 16, 2007): Brief summary : - Critical problems fixed for x86-64 support in CPU and Bochs internal debugger - ACPI support - The release compiled with x86-64 and ACPI - Hard disk emulation supports ATA-6 (LBA48 addressing, UDMA modes) - Added emulation of Intel SSE4.1 instruction set Detailed change log : - CPU - Fixed critical bug with 0x90 opcode (NOP) handling in x86-64 mode - implied stack references where the stack address is not in canonical form should causes a stack exception (#SS) - Added emulation of SSE4.1 instruction set (Stanislav) - Do not save and restore XMM8-XMM15 registers when not in x86-64 mode - Fixed zero upper 32-bit part of GPR in x86-64 mode - CMOV_GdEd should zero upper 32-bit part of GPR register even if the 'cmov' condition was false ! - Implemented CLFLUSH instruction, report non-zero cache size in CPUID - Fixed PUSHA/POPA instructions behavior in real mode - Fixed detection of inexact result by FPU - Fixed denormals-are-zero (DAZ) handling by SSE convert instructions - Implemented Misaligned Exception Mask support for SSE (MXCSR[17]) - Implemented Alignment Check in the CPU and #AC exception, to enable use --enable-alignment-check configure option - General - 2nd simulation support in wxBochs now almost usable (simulation cleanup code added and memory leaks fixed) - Configure and compile - several fixes for MacOSX, OpenBSD and Solaris 10 - enable save/restore feature by default for all configurations - reorganized SSE configure options to match Intel(R) Programming Reference Manual, new option introduced for SSE extensions enabling. To enable Intel Core Duo 2 new instructions use --enable-sse=3 --enable-sse-extension enabling of SSE4.1 (--enable-sse=4) will enable SSE3 extensions as well - removed old PIT, always use new PIT written by Greg Alexander, removed configure option --enable-new-pit - I/O devices (Volker) - Floppy - partial non-DMA mode support (patch by John Comeau) - Hard drive / cdrom - hard disk emulation now supports ATA-6 (LBA48 addressing, UDMA modes) - VMWare version 4 disk image support added (patch by Sharvil Nanavati) - PCI - initial support for the PIIX4 ACPI controller - Serial - added support for 3-button mouse with Mousesystems protocol - USB - experimental USB device change support added - rewrite of the existing USB devices code - new USB devices 'disk' and 'tablet' (ported from the Qemu project) - Bochs internal debugger - fixed broken debugger "rc file" option (execute debugger command from file) - implementation of a gui frontend ("windebug") for win32 started - gdbstub now accepts connection from any host - several documentation updates - a lot of disasm and internal debugger x86_64 support fixes - Configuration interface - fixes and improvements to the save state dialog handling - Display libraries - text mode color handling improved in some guis - win32 fullscreen mode (patch by John Comeau) - System BIOS (Volker) - 32-bit PM BIOS init code for ACPI, PCI, SMP and SMM (initial patches by Fabrice Bellard) - PCI BIOS function "find class code" implemented - SF patches applied [1791000] 15h 8600h is reading the wrong stack frame by Sebastian [1791016] rombios32.c, ram_probe(), BX_INFO missing value by Sebastian [1786429] typo in bochsrc.5 by Sebastian [1785204] Extend acpi_build_table_header to accept a revision number by Sebastian [1766536] Partial Patch for Bug Report 1549873 by Ben Lunt [1763578] ACPI Table Revision 0 -> 1 [1642490] implement alignment check and #AC exception by Stanislav Shwartsman [1695652] [PATCH] .pcap pktlog and vnet PXE boot by Duane Voth [1741153] Add expansion-ROM boot support to the ROMBIOS [1734159] Implemented INT15h, fn 0xC2 (mouse), subfn 3, set resolution [1712970] bios_printf %s fix [1573297] PUSHA/POPA real mode fix by Stanislav Shwartsman [1641816] partial support for non-DMA access to floppy by John Comeau [1624032] shows where write outside of memory occurred by John Comeau [1607793] allow fullscreen when app requests it by John Comeau [1603013] Bugfix for major NOP problem on x64 by mvysin [1600178] Make tap and tuntap compile on OpenBSD by Jonathan Gray [1149659] improve gdbstub network efficiency by Avi Kivity [1554502] Trivial FPU exception handling fix - these S.F. bugs were closed [1316008] Double faults when it shouldn't - gcc 4.0.2 [1787289] broken ABI for redolog class when enable-compressed-hd [1787500] tftp_send_optack not 64bit clean [1264540] Security issue with Bochs website [1767217] Debugger Faults including ud2 [1729822] Various security issues in io device emulation [1675202] mptable hosed (bad entry count in header) [1197141] 'make install' installs to bad location [1157623] x86Solaris10 cannot recoginize ACPI RSD PTR [1768254] large HDD in Bochs/bximage [1496157] Windows Vista Beta2 dosn't boot [1755915] Illegal Hard Disk Signature Output [1717790] info gdt and info idt scrolls away, too long result [1726640] Debugger displays incorrect segment for mov instruction [1719156] Typo in misc_mem.cpp [1715270] Debugger broken in/beyond 2.3 [1689107] v8086 mode priviledge check failed [1704484] A few checks when CPU_LEVEL < 4 [1678395] Problem with zero sector... [876990] SA-RTL OS fails on PIC configuration [1673582] save/restore didn't restore simulation correctly [1586662] EDD int 13h bug, modify eax [666618] POP_A Panic in DOS EMU [1001485] panic: not enough bytes on stack [1667336] delay times an order of magnitude slow [1665601] crash disassembling bootcode [1657065] CVS sources won't compile [1653805] bochs's gdbstub uses incorrect protocol [1640737] ASM sti command frezzes guest OS [1636439] latest CVS sources don't compile under Cygwin [1634357] disasm incorrect (no sign ext) displacement in 64-bit mode [1376453] pcidev segfaults bochs [1180890] IOAPIC in BOCHS - WinXP 64 in MP version [1597528] 2.3 fails to compile on amd64 [1526255] FLD1 broken when compaling with gcc 4.0.x [1597451] eth_fbsd is broken under FreeBSD [1571949] Bochs will not compile under Solaris [1500216] Bochs fails to boot BeOs CD [1458339] bochs-2.2.6 WinXP Binary ACPI error installing FreeBSD 6.0 [1440011] patches needed for FreeBSD 6.0 to compile Bochs [431674] some devices don't have a prefix [458150] QNX demo disk crashes with new pit [818322] Bochs 2.1 cvs: OS/2 - read verify on non disk [906840] KBD: bogus scan codes generated in set 3 [1005053] No keyboard codes translation [1109374] Problem with Scancodeset 2 [1572345] Bochs won't continue [1568153] Bochs looks for (and loads?) unspecified display libraries [1563462] Errors in /iodev/harddrv.h [1562172] TLB_init() fails to initialize priv_check array if USE_TLB 0 [1385303] debugger crashes after panic [1438227] crc.cpp missing in bx_debug version 2.2.6 [1501825] debugger crashes on to high input [1420959] Memory leak + buffer overflow in Bochs debugger [1553289] Error in Dis-assembler [542464] I cannot use FLAT [1548270] Bochs won't die with its pseudo terminal [1545588] roundAndPackFloatx80 does not detect round up correctly ------------------------------------------------------------------------- Changes in 2.3 (August 27, 2006): Brief summary : - limited save/restore support added (config + log options, hardware state) - configuration parameter handling rewritten to a parameter tree - lots of cpu and internal debugger fixes - hard disk geometry autodetection now supported by most of the image types - hard disk emulation now supports ATA-3 (multiple sector transfers) - VBE memory size increased to 8MB and several VGA/VBE fixes - updated LGPL'd VGABIOS to version 0.6a Detailed change log : - CPU and internal debugger fixes - Fixed bug in FSTENV instruction (Stanislav Shwartsman) - Recognize #XF exception (19) when SSE is enabled - Fixed bug in PSRAW/PSRAD MMX and SSE instructions - Save and restore RIP/RSP only for FAULT-type exceptions, not for traps - Correctly decode, disassemble and execute multi-byte NOP '0F F1' opcode - Raise A20 line after system reset (Stanislav Shwartsman) - Implemented SMI and NMI delivery (APIC) and handling in CPU (Stanislav) - Experimental implementation of System Management Mode (Stanislav) - Added emulation of SSE3E instructions (Stanislav Shwarstman) - Save and restore FPU opcode, FIP and FDP in FXSAVE/FRSTOR instructions - Fixed bug in MOVD_EdVd opcode (always generated #UD exception) - Fixed critical issue, Bochs was not supporting > 16 bit LDT.LIMIT values - Many fixes in Bochs internal debugger and disassembler - CPU x86-64 fixes - Fixed SYSRET instruction implementation - Fixed bug in CALL/JMP far through 64-bit callgate in x86-64 mode - Correctly decode, disassemble and execute 'XCHG R8, rAX' instruction - Correctly decode and execute 'BSWAP R8-R15' instructions - Fixed ENTER and LEAVE instructions in x86-64 mode (Stanislav) - Fixed CR4 exception condition (No Name) - Fixed x86 debugger to support x86-64 mode (Stanislav) - APIC and SMP - Support for Dual Core and Intel(R) HyperThreading Technology. Now you could choose amount of cores per processor and amount of HT threads per core from .bochsrc for SMP simulation (Stanislav Shwartsman) - Allow to control SMP quantum value through .bochsrc CPU option parameter. Previous Bochs versions used hardcoded quantum=5 value. - Fixed interrupt priority bug in service_local_apic() - Fixed again reading of APIC IRR/ISR/TMR registers. Finally it becomes fully correct :-) - Configure and compile - Moved configure time --enable-reset-on-triple-fault option to runtime, the 'cpu' option in .bochsrc is extended and the old configure option is deprecated (Stanislav Shwartsman) - Removed --enable-pni configure option, to compile with PNI use --enable-sse=3 instead (Stanislav Shwartsman) - enable SEP (SYSENTER/SYSEXIT) support by default for Penitum II+ processor emulation (i.e. if cpu-level >= 6 and MMX is enabled) - general - Limited save/restore support added. The state of CPU, memory and all devices can be saved now (state of harddisk images not handled yet). - Fixed several memory leaks - configuration interface - Configuration parameter handling rewritten to a parameter tree. This is required for dynamic menus/dialogs, user-defined options and save/restore. - Support for user-defined bochsrc options added - help support at the parameter prompt in textconfig added - I/O devices (Volker) - Floppy - partial sector transfers fixed - Hard drive / cdrom - several fixes to the IDE register behaviour (e.g. in case of a channel with only one drive connected) - fixed data alignment of 'growing' hard drive images (sharing images between Windows and Linux now possible) - disk geometry autodetection now supported by most of the image types (unsupported: external, dll and compressed modes) - multi sector read/write commands implemented - hard disk now reporting ATA-3 supported - ATAPI 'inquiry' now returns a unique device name - Keyboard - reset sent to keyboard has no effect on the 8042 (scancode translation) - PCI - forward PIRQ register changes to the I/O APIC (if present) - attempt to fix and update the emulation part of 'pcidev' (untested) - VGA - VBE memory size increased to 8MB and several VBE fixes - VGA memory read access fixed (bit plane access and read mode) - VGA memory is now a part of the common video memory - System BIOS (Volker) - enable interrupts before executing INT 19h - fixed ATA device detection in case of one drive only connected to controller - improved INT 15h function AX=E820h - real mode PCI BIOS now returns IRQ routing information (function 0Eh) - keyboard LED flags handling fixed and improved - fixed handling of extended keys in INT 09h - Updated LGPL'd VGABIOS to version 0.6a - SF patches applied [1340111] fixes and updates to usb support by Ben Lunt [1539420] minor addition to pci_usb code by Ben Lunt [1455958] call/jmp through call gate in 64-bit mode [1433107] PATCH: fix compile with wxwindows 2.6 (unicode / utf8) by jwrdegoede [1386671] Combined dual core and hyper-threading patch - these S.F. bugs were closed [833927] TTD: System Error TNT.40025: Unexpected processor exception [789230] Sending code that shows lock up when setting idt [909670] Problems with Symantec Ghost [1540241] include missing in osdep.cc [1539373] Incorrect disasm for "mov moffset,bla" in 64bit [1538419] incorrect disassembly of [rip+disp] with rex.b [1535432] shift+cursor key maps to a digit [1504891] Knoopix 5.0.1 error [1424355] bochs-2.2.6 ata failure in windoze 98se [1533979] wrong disassembly of IN instruction [620059] paste won't stop [1164904] status bar doesn't show num/caps/scroll lock status [1061720] ATA Support level for HD [1522196] Broken CHANGES link in main page [1438415] crash if screen scrolled downwards [778441] Shouldn't interrupts be enable after BIOS? [1514949] I got a problem with the 8253 timer [1513544] disasm of 0xec (in AL,DX) returns ilen of 2 instead of 1 [1508947] APIC interrupt priority checking and interrupt delivery [766286] Debugger halts after any GPF exception [639143] va_list is not a pointer on linuxppc [1501815] debugger examines memory over page-boundary wrong [1503978] movsb/w/d doesn't work when direction is stored [1499405] WinPCap has changed URL hosting [1498519] APIC IRR bits not set while interrupts disabled [1498193] Bochs segfaults on LTR instruction [787140] Guest2HostTLB optimization bug [1492070] instrument stop [1487772] No SEP on P4 [1488335] Growing hard disk images severe interoperability errors! [1076312] Shadow RAM and TLB [1282249] The real i440FX chipset Award bios hangs [1479763] mistake "mov ax,[es:di]" for "mov ax,[ds:di]" [1453575] Misconfigured floppy DMA transfers do not terminate. [1460068] Incorrect handling for the Options Menu Item [910203] bochs-2.1.1 wx.lo failed [1438654] PANIC when trying to run install-amd64-minimal-2005.0.iso [1458320] compile hdimage.h fails [1455880] bochs-2.2.6,2: make error on FreeBSD [696890] Network wouldn't run under W2k hosting MSDOS [673391] SMP timer problems [1291059] wxWindows GUI on non-windows/configure issue [1356450] bochs 2.2.1 errors-omittions [1178017] Win98 guest cannot receive network packets from host [1076315] a20_mask after restarting [1436323] real hw does not panic when bad Ib in CMPSS_VssWssIb [1435269] cdrom_amigaos is not compilable [1433314] disasm issues [1170614] relative jumps/calls wrong in debugger [758121] user might get confused when interrupt handler invoked [1170622] You cannot toggle OFF "show" flags [1406387] JMP instruction should display absolute address [1428813] PANIC: ROM address space out of range [1426288] DR-DOSs EMM386 problem [1412036] Bochs cannot recognize PCI NIC correctly [435115] dbg: modebp broken and no docs [1419366] disasm cs:eip does not work anymore [1419393] SSE's #XF exception -> "exception(19): bad vector" [1419429] disassembly of "260f6f00" show DS: instead of ES: prefix [1417583] Interrupt behaviour changed from 2.2.1 to 2.2.5 [1418281] 'push' (6A) incorrectly disassembled [1417791] FLDENV generating exception when real hw does not. [1264583] OS/2 1.1 doesn't run ------------------------------------------------------------------------- Changes in 2.2.6 (January 29, 2006): - First major SMP release ! - several APIC and I/O APIC fixes make SMP Bochs booting Windows NT4.0 or Knoppix 4.0.2 without noapic kernel option in SMP configuration. - critical APIC timer bug fixed - obsolete SMP BIOS images removed (MP tables created dynamicaly) - determine number of processors in SMP configuration through .bochsrc new .bochsrc option 'CPU' allows to choose number of processors to emulate - new configure option --enable-smp to configure Bochs for SMP support, the old --enable-processors=N option is deprecated - CPU and internal debugger fixes - enabled #PCE bit in CR4 register, previosly setting of this bit generated #GP(0) fault - enabled LAHF/SAHF instructions in x86-64 mode - fixed bug in PMULUDQ SSE2 instruction - fixes in Bochs debugger - Configure and compile - enable VME (virtual 8086 mode extensions) by default if cpu-level >= 5 - enable Bochs disassembler by default for all configurations - win32 installer script improvements - ips parameter moved to new 'CPU' option - show IPS value in status bar if BX_SHOW_IPS is enabled - Other - several fixes in the hard drive, keyboard, timer, usb and vga code - new user button shortcut "bksl" (backslash) - updated Bochs instrumentation examples - user and development documentation improved ------------------------------------------------------------------------- Changes in 2.2.5 (December 30, 2005): Brief summary : - added virtual 8086 mode extensions (VME) implementation - several fixes/improvements in x86-64 emulation, debugger and disassembler - new serial mode 'socket' connects a network socket - IDE busmaster DMA feature for harddisks and cdroms completed and enabled - many improvements in Bochs emulated I/O devices (e.g. floppy, cdrom) - Updated LGPL'd VGABIOS to version 0.5d Detailed change log : - CPU - fixed XMM registers restore in FXRSTOR instruction (Andrej Palkovsky) - print registers dump to the log if tripple fault occured - fixed PANIC in LTR instruction (Stanislav) - added virtual 8086 mode extensions (VME) implementation, to enable configure with --enable-vme (Stanislav) - flush caches and TLBs when executing WBINVD and INVD instructions - do not modify segment limit and AR bytes when modifying segment register in real mode (support for unreal mode) - fixed init/reset values for LDTR and TR registers - reimplemented hardware task switching mechanism (Stanislav) - generate #GP(0) when fetching instruction cross segment boundary - CPU (x86-64) (Stanislav Shwartsman) - implemented call_far/ret_far/jmp_far instructions in long mode - fixed IRET operation in long mode - fixed bug prevented setting of NXE/FFXSR bits in MSR.EFER register - implemented RDTSCP instruction - do not check CS.limit when prefetching instructions in long mode - fixed masked write instructions (MASKMOVQ/MASKMOVDQU) in long mode - fetchdecode fixes for x86-64 - APIC - Fixed bug in changing local APIC id (Stanislav) - Fixed reading of IRR/ISR/TMR registers (patch by wmrieker) - Implemented spurious interrupt register (Stanislav, patch by wmrieker) - Fixed interrupt delivery bug (anonymous #SF patch) - Correctly implemented ESR APIC register (Stanislav) - Bochs debugger - Fixed bug in bochs debugger caused breakpoints doesn't fire sometimes (Alexander Krisak) - watchpoints in device memory fixed (Nickolai Zeldovich) - new debug interface to access Bochs CPU general purpose registers with support for x86-64 - Disassembler (Stanislav Shwartsman) - Fixed disassembly for FCOMI/FUCOMI instructions - Full x86-64 support in disassembler. The disassembler module extended to support x86-64 extensions. Still limited by Bochs debugger which is not supporting x86-64 at all ;( - I/O devices (Volker) - general - memory management prepared for large BIOS images (up to 512k) - slowdown timer sleep rate fixed (now using 1 msec on all platforms) - some device specific parameter handlers moved into the device code - serial - new serial mode 'socket' connects a network socket (#SF patch by Andrew Backer) - hard drive / cdrom - assign a unique serial number to each drive (fixes harddrive detection problems with Linux kernels 2.6.x: "ignoring undecoded slave") - geometry autodetection for 'flat' hard disk images added. Works with images created with bximage (heads = 16, sectors per track = 63) - ATAPI command 'read cd' implemented, some other commands improved - cdrom read block function now tries up to 3 times before giving up - emulation of raw cdrom reads added, some other lowlevel cdrom fixes - IDE busmaster DMA feature for harddisks and cdroms completed and enabled - disk image size limit changed from 32 to 127 GB - split ATA/ATAPI emulation code and image handling code - floppy - fixes for OS/2 (patch by Robin Kay) - disk change line behaviour fixed (initial patch by Ben Lunt) - end-of-track (EOT) condition handling implemented - more accurate timing for read/write data and format track commands using a motor speed of 300 RPM - timing of recalibrate and seek commands now depends on the step rate, date rate and the steps to do - floppy controller type changed to 82077AA - cmos - RTC 12-hour and binary mode implemented - number of CMOS registers changed from 64 to 128 - bochsrc option 'cmosimage' improved - save cmos image on exit if enabled - speaker - simple speaker support for OS X added (patch by brianonn@telus.net) - pci - BeOS boot failure fix in the PCI IDE code - don't register i/o and memory regions during PCI probe - vga - memory allocation for vga extensions fixed - usb - some bugfixes by Ben Lunt (mouse and keypad are usable now) - networking modules - VDE networking module now enabled on Linux - display libraries - general - new syntax for the userbutton shortcut string and more keys supported - win32 - fixed keycode generation for right alt/ctrl/shift keys - runtime dialog is now a property sheet - x11 - simple dialog boxes for the "ask" and "user shortcut" feature implemented - Slovenian keymap added (contributed by Mitja Ursic) - configuration interface - ask dialog is now enabled by default for win32, wx and x display libraries - bochsrc option floppy_command_delay is obsolete now (floppy timing now based on hardware specs) - floppy image size detection now available in the whole config interface - some device specific parameter handlers moved into the device code - calculate BIOS ROM start address from image if not specified - System BIOS (Volker) - PCI i/o and memory base address initialization added - several keyboard interrupt handler fixes (e.g. patch by japheth) - several floppy fixes (e.g. OS/2 works with patch by Robin Kay) - some more APM functions added - Updated LGPL'd VGABIOS to version 0.5d - generate SMP specific tables dynamicly by the Bochs memory init code - SF patches applied [1389776] Disk sizes over 64 Gbytes by Andrzej Zaborowski [1359162] disasm support for x86-64 by Stanislav Shwartsman [857235] task priority and other APIC bugs, etc by wmrieker [1359011] build breaks for 386 + debugger + disasm by shirokuma [1352761] Infinite loop when trying to debug a triple exception [1311170] small APIC bug fix (interrupt sent to the wrong CPU) [1309763] Watchpoints don't work in device memory by Nickolai Zeldovich [1294930] change line status on floppy by Ben Lunt [1282033] SSE FXRESTORE not working correctly by Ondrej Palkovsky [816979] wget generalizations by Lyndon Nerenberg [1214886] No more pageWriteStamp / unified icache by H. Johansson [1107945] com->socket redirection support by Andrew Backer - these S.F. bugs were closed [669180] win95 install : unknown SET FEATURES subcommand 0x03 [1346692] bochs 2.2.1 VGA BIOS error [1354963] floppy in KolibriOS [1378204] error: bochs-2.2.1, --enable-sb16, --disable-gameport [1368412] VDE problems in BOCHS [533446] CPU and APIC devices appear twice [1000796] bximage fails to create image of specified size [1170793] Quarterdeck QEMM doesn't work [923704] Multiple opcode prefixes don't reflect Trap 13 [1166392] DocBook/documentation issues [1368239] broken grater than 4GB size of sparse type hd image [1365830] i386 compile breaks on paging [427550] Incomplete IRETD implementation [1215081] MSVC workspace STILL not fixed [736279] Jump to Task [1356488] FD change fail & occur error [957615] [CPU ] prefetch: RIP > CS.limit [1353866] not booting linux-2.6.14 [1351667] load32bitOSImage does not work with --enable-x86-debugger [1217476] Incorrect (?) handling of segment registers in real mode [1184711] OS2 DOS crash [2.2.pre2] [624330] support for disks > 32GiB [1348368] bochs 2.2.1 bximage error [1342081] Configuration Menu option failed [1138616] OS/2 Warp 4 hangs when booting [1049840] mouse and video conflict [1164570] Unable to perform Fedora Core 4 test 1 installation [1183201] Windows 2000 (MSDN build 2150?) does not completely install [1194284] Can't boot from CD-ROM (Windows NT) [962969] Windows NT crashes while trying to intall them. [1054594] WinXP install halts (redo) [1153107] Windows XP fails with BSOD on 'vga' [938518] Win XP installation fails [645420] getHostMemAddr vetoed direct read [1179985] MS XENIX: >>PANIC<< VGABIOS panic at vgabios.c, line 0 [1329600] WBINVD and INVD should flush caches and TLB [638924] eliminate BX_USE_CONFIG_INTERFACE [1048711] Funny behaviour with CTRL [1288450] keyboard BIOS error [1310706] Keyboard - about key SHIFT [1295981] Ubuntu 5.04 Live-CD won't boot in Bochs [879047] APIC timer behavior different before reset and after [1188506] I still can't install the german Windows XP! [1301847] Windows XP dosn't boot - FXRSTOR problem ? [661259] does not boot QNX under WinX [924412] Keyboard lock states all whacked [681127] MIPSpro compiler (IRIX) is allergic to ^M [1285923] BIOS keyboard handler [516639] ATA controller revisited... [657918] does not boot BeOS under WinX [649245] BeOS CD locks halfway on boot [1094385] Attachment for bug 1090339 (beos failure) [1183196] BeOS 4.5 developer CD does not install [1090339] BeOS fails to boot [639484] panics when int 13 is called [711701] divide by zero [704295] ATAPI/BIOS call missing [682856] hard drive problems [627691] Cursor keys problem [588011] keyboard not working [542260] os/2 warp crashes with floppy handling [1273878] SB16 doesn't work in pure DOS [542254] OS/2 FDC driver dies [1099610] Windows 98 SE Does not install [875479] cr3 problem on task switch [731423] NE2000 causing PANIC on Win2K detection [1156155] bochs fails to boot plan9 iso [1251979] --enable-cpu-level=3 should assume --without-fpu [1257538] Interupt 15h 83h - set wait event interval [658396] Panic for DR DOS emm386 [679339] /? doesn't divulge Bochs command-line syntax [1167016] call/jump/return_protected doesn't support x86-64 [1252432] Mac OS X compile bug [881442] Bochs 2.1 PANIC when loading DOS Turbo Pascal protected mode [1249324] Boch2.2.1 Buffer Overfollow in void bx_local_apic_c::init () [1197144] 'make install' has dependency on wget [1079595] LTR:386TSS: loading tr.limit < 103 [1244070] Compilation Error in gui/rfb.cc [761707] CPU error when trying to start Privateer [517281] Crash running Privateer in DOS... ------------------------------------------------------------------------- Changes in 2.2.1 (July 8, 2005): - Fixed several compilation warnings and errors for different platforms (Volker) - Fixed FPU tag word restore in FXRSTOR instruction (Stanislav) - Added missing scancodes for F11 and F12 to BIOS translation table (Volker) - Bochs disassembler bugfixes (h.johansson) - About 5% emulation speed improvement (h.johansson) - Handle writing of zero to APIC timer initial count register (Stanislav) - Enable Idle-Hack for 'TERM' GUI (h.johansson) - Reduced overhead of BX_SHOW_IPS option to minimum. Now every simulation could run with --enable-show-ips without significant performance penalty. (Stanislav) - Fixed pcipnic register access (Volker) - Limited write support for TFTP server in 'vnet' networking module added (Volker) - Changed some timing defaults to more useful values (Volker) - WinXP/2003 style common controls now supported (Vitaly Vorobyov) - Updated LGPL'd VGABIOS to version 0.5c (Volker) - Added new BX_INSTR_HLT callback to instrumentation (Stanislav) ------------------------------------------------------------------------- Changes in 2.2 (May 28, 2005): Brief summary : - New floating point emulator based on SoftFloat floating point emulation library. - improved x86-64 emulation - Cirrus SVGA card emulation added - status bar with indicators for keyboard, floppy, cdrom and disk (gui dependant) - many improvements in Bochs emulated I/O devices (e.g. PCI subsystem) Detailed change log : - CPU - fixes for booting OS/2 by Dmitri Froloff - fixed v8086 priveleged instruction processing bug (was also reported by LightCone Aug 7 2003) - exception process bug (was reported by Diego Henriquez Sat Nov 15 01:16:51 CET 2003) - segment validation with IRET instruction - CS segment not present exception processing with IRET - several fixes by Kevin Lawton - add MSVC host asm instructions (patch by suzu) - fixed bug in HADDPD/HSUBPD (SSE3) instructions - fixed bug in float to integer SSE/SSE2 convert instructions - fixed BCD instructions implementation - execution speed improvements (sshwarts and psychosmur) - fix MSR_APICBASE base address (Kangmo Kim, Christian Neubert) - change BX_PANIC messages to BX_INFO when behaviour exactly matches Intel docs - EIP > CS.limit case should always cause #GP(0), even in real mode. Fixed all jump, call and ret instructions for 16/32 modes - fixed using invalid segment register for MOV instruction (h.johansson) - fixed ET bit mismatch between CR0 and SMSW instruction - fixed possible simulator #DIVZERO fault when executing IDIV instruction - fixed undocumented flags handling for BTS, BTR, SHR, SHLD, MUL and IMUL instructions (Stanislav Shwartsman) - added missed #GP(0) exception when loading incorrect flags combination to CR0 (Stanislav Shwartsman) - in case of --enable-ignore-bad-msr enabled read ignored MSRs as zero - enabled #DE, #TSD and #MCE bits in CR4 register, previosly setting of one of these bits generated #GP(0) (Stanislav, Volker Ruppert) - exceeding the instruction length limit of 15 bytes (this only can occur when redundant prefixes are placed before an instruction) generate #GP(0) (Stanislav Shwartsman) - corrected PAE functionality - CPU (x86-64) - fetchdecode fixes for x86-64 and 3DNow! (Stanislav) - fixed CF flag handling for SHL instruction in x86-64 mode (Stanislav) - implemented CR8 register (aliased to APIC.TPR[7:4]) (Stanislav) - implemented NXE bit (No-Execute page protection) support (Stanislav) - STOSQ instruction emulation fixed (Avi Kivity) - allow null SS selector for MOV SS, POP SS, and LSS instructions in long mode (Avi Kivity) - ignore segment bases for all segments (except FS and GS) in long mode (Avi Kivity) - allow SYSENTER/SYSEXIT instructions together with x86-64 (Stanislav) - canonical address checking for RIP (Stanislav) - FPU (Stanislav Shwartsman) - totally rewritten all FPU code based on softfloat library - significantly improved accuracy of all floating point instructions. - implemented all missed P6 and PNI floating point instructions. - hundreds of bug fixes in FPU code. TODO: ! Unmasked underflow/overflow should correct the result by magic number for all operations, including float32 and float64. - APIC (Zwane Mwaikambo) - APIC arbitration - Processor priority - Various interrupt delivery fixes - Focus processor checking - ExtINT delivery - Disassembler - fixed MOV opcode 0x88, had exchanged the operands (h.johansson) - fixed MOV opcode 0xA3, had wrong operand size (h.johansson) - fixed BOUND opcode 0x62 (Stanislav) - fixed CALLW opcode 0xFF /3 and JMPW opcode 0xFF /5 (Stanislav) - fixed INS opcode 0x6D, had wrong operand size (Stanislav) - fixed disassembly for repeatable instructions (Stanislav) - fixed sign-extended immediate opcodes (Stanislav) - fixed MOVSS/MOVSD instructions opcode names (Stanislav) - fixed NEG instruction opcode name (Stanislav) - fixed CMPXCHG8B instruction, had wrong operand size (Stanislav) - fixed floating point instructions operands (Stanislav) - experimental support of AT&T syntax in disassembler (Stanislav) - I/O devices - general - handle cpu reset through port 0x92 - new memory handler API for PCI i/o and memory handling (Frank Cornelis) - speaker emulation for Linux (David N. Welton) and Win32 (Volker Ruppert) added - pci - PCI slot configuration added for 5 slots (Volker) - PCI irq routing, irq sharing and level sensitive irq mode implemented - ne2k device appears as a Realtec 8029 NIC if connected to a PCI slot - PCI IDE controller dummy device added - PCI host device mapping for Linux (Frank Cornelis) - PCI Pseudo-NIC emulation (Michael Brown) - serial - multiple serial port support added (4 ports now available) - partial raw serial support on win32 (transmit data) - serial port i/o mode option added (modes: null, file, term, raw, mouse) - parallel - multiple parallel port support added (2 ports now available) - mouse - serial mouse support (Volker) - PS/2 and serial wheel mouse support (Ben Lunt) - usb - USB mouse and keypad support (Ben Lunt) - config option to specify devices connected to USB ports - vga - VBE 8 bit DAC support added - VBE memory now registered using DEV_register_memory_handlers() - CL-GD 54xx SVGA emulation added (Makoto Suzuki) - vga extension option added (choices: vbe, cirrus, none) (Volker) - floppy - raw floppy access now works on Win9x host (Ben Lunt) - sb16 - MacOSX sound support (Brian Huffman) - networking modules - new: 'eth_vnet' simulates ARP, DHCP, ICMP-echo and read-only TFTP (m_suzu, easeway) - new: 'eth_vde' for Virtual Distributed Ethernet (Renzo Davoli) - System BIOS - turn floppy motor off 2 seconds after last read/write/recalibrate command (Ben Lunt) - int13_cdrom / 32 bit register update fixes for FreeBSD cdrom boot (Fabrice Bellard) - APM and system shutdown support (Fabrice Bellard) - checksum calculation for expansion ROMs - extended floppy parameter table (Mike Nordell, Derek Favcus) - PCI IRQ initialisation added - boot sequence with up to 3 boot devices added - display libraries - status bar with indicators for cdrom, floppy, harddisk and keyboard added (done in rfb, sdl, win32, wx and x) - 3rd (middle) mouse button now supported (rfb, sdl, win32, wx, x) - mouse wheel support (sdl, win32, x) - CTRL key + middle mouse button now used to toggle the mouse capture mode (sdl, win32, wx, x) - text mode split screen feature added (sdl, win32, wx, x) - new gui function returns the display library capabilities (xres, yres, bpp) for the Bochs VBE support - display library specific options added - currently supported: rfb: timeout (time to wait for client connection) sdl: fullscreen (startup in fullscreen mode) win32: legacyF12 (use F12 to toggle mouse) - new graphics update API added (used by svga_cirrus) (Robin Kay) - configuration interface - win32: gui runtime dialogs replace textconfig runtime dialogs - set default IPS to 10000000 in .bochsrc sample - SB16 options dmatimer and loglevel now available at runtime - configure script / compile - --enable-ignore-bad-msr (ignore bad MSR references) option is enabled by default - --enable-mmx enabled by default only if cpu-level >= 5 - --enable-4meg-pages will be enabled by default if cpu-level >= 5 - fixes for Solaris SunPro (Robin Kay) - --enable-pni option added - --enable-show-ips option added, enable Instruction Per Second counter in log file - autodetection for lowlevel sound support added - documentation - a bunch of updates in user and documentation docs (Alexander Schuch) - SF patches applied [894595] MSR_APICBASE always returns APIC ADDRESS 0 by Kangmo Kim [907163] ctrl_xfer8 clean/speed up [907161] clean/speed up of io.cc [899972] data xfer performance patch V 2.0.4 [904549] imul gives incorrect result in long mode [877510] amd64 fixes... [903465] SEGV in iodev/ne2k.cc line 1211 on Alpha architecture by Christian Lestrade [903332] copy the bximage result to clipboard, etc by Lukewarm [950905] Do not PANIC on rare, bad input from user-mode by h.johansson [924428] ET bit mismatch between CR0 and MSW [869822] a real SVGA implementation by m_suzu [867045] fix for compiler errors on VC++ by m_suzu [838601] support for the over 2GB disk size with MSVC++ [874816] local ARP/ping/DHCP simulator by m_suzu [976066] Keyboard: Get controller version by Ben Lunt [832330] ROMBIOS improvement (reduce stack consumption, etc.) [977900] READ_CDROM_TOC and base address by Ben Lunt [961665] WinXP patch to read physical CDROM's TOC by Ben Lunt [978793] CDROM_SENSE_MODE medium_type by Ben Lunt [615457] gif to png migration [1021767] Portability in sb16ctrl.c by Robert Millan [690400] gzip is confused by GZIP variable in Makefile [567595] guess floppy image size from image file length by Tal Benavidor [888426] bochsrc to make vnet useful by m_suzu [1021758] GNU/k*BSD host support by Robert Millan [969967] int 15/ah=87h clearing cr0 by Ben Lunt [1048327] Russian Keymap by Dmitry Soshnikov [851332] DESTDIR support for install_dlx by Ville Skyttä [970929] gdbstub support for MinGW tool chains by Muranaka Masaki [1021740] Turn gdb stub into a runtime option by Charles Duffy [1063329] RFB key press/release bug fix by Remko van der Vossen [1079240] Wheel Mouse by Ben Lunt [1087537] Fix for Win9x CD boot by lukewarm [1083218] Start of wheel for USB #2 by Ben Lunt [1098480] bochsrc: fixed floppya example by Alexander Schuch (ci-dev) [1094407] configure.in: changed wxWindows to wxWidgets by Alexander Schuch [1092058] serial.cc debug output cleanup by Ben Lunt [1101165] APIC base address by Christian Neubert (flashburn) [1093796] Fix for bug #1093786 (Nigel Horne) [1082584] The start of Bus mice and USB mice by Ben Lunt [1104695] msvc6 compatibility update (Royce Mitchell III) [1059199] VGA text font bug fix (Anonymous) [1108001] Null pointer on bx_atexit() (Ben Lunt) [1112093] Fixed mouse cursor remain area drawing (Anonymous) [1114826] Fix PCIBIOS (Destruction prevention of esi and edi) [1095473] Reading from a CDRW (Fixed) by Ben Lunt [1123895] x86-64 gdb/debugger fixes by Avi Kivity [1145423] stosq simulation bugfix by Avi Kivity [1151012] allow null ss on x86-64 by Avi Kivity [1153327] ignore segment bases in x86-64 by Avi Kivity [1153511] Fixed broken screen update (VBE) [1152808] use 'install' instead of 'cp' during installation by Avi Kivity [1159626] bugfix [1156776] keyboard scanmode fault by Rene Kootstra [843328] PATCH: support for Flat-style ToolBar with Win32GUI [1198308] PATCH: fix incorrect moving mouse cursor when wheel used [1200515] add TFTP server to vnet & ipv4 bug fix by easeway [1203305] tuntap incompatibility by Jan Kratochvil - SF patches partially applied [896733] Lazy flags, for more instructions, only 1 src op [1005422] Improve mouse cursol Grub when 2 buttons-mouse use (WIN32) (TODO: improved japanese keyboard support) - patches applied - patch.rombios.markevich (Start/Stop Wait Timer) (Kory Markevich) - patch.apic-zwane (APIC fixes) (Zwane Mwaikambo) - patch.v8086-exception.lightcone (LightCone) - these S.F. bugs were closed #957660 >>PANIC<< APIC: R(curr timer count): delta < initial #1192654 60 x 90 text not quite right... #1189097 "configure --with-sdl --with-rfb" doesn't compile #1188980 Crash on XP when break into debugger #1186693 Improving quality of ./configure --help #1185245 Errors Making Bochs with Mingw32 #1185289 PSE is not enabled by default on Pentium #1170620 info cpu scrolls away, is too long #1157998 ips shown even when waiting for input #663108 APIC Timer Bug #831750 bochs unlike real PC in paging #1182698 PAE support doesn't work #954400 debugger causes segfaults when gcc 3.4.0 is used #1171312 Possible SMP problem with ICACHE pageWriteStamp #1179964 PANIC: RIP>CS.limit when jumping to longmode #1171067 configure fails to add -lpthread #1171065 Term UI needs -lncurses #1171061 SDL GUI startup failure #1022056 win32 error build debug version..c2146 #957190 error while attempting to compile sb16.cc #804797 Debugger: visualization problem (jmp) #675523 2.0.1 doesn't run on W2K? #1167358 When using 5430PCI in DR-DOS Bochs would panic with a PUSHAD #1164654 Bochs VBE bios causing exception 0B in Windows 95 (SVGA bios) #1162983 conflicts which configure could detect #1164536 Windows 95 B crashes during install #526978 cygwin: in an rxvt, stdout is flaky #542303 >>PANIC<< call_protected: CS selector null #859457 BRICKS game doesn't work #1159639 text modes on address A0000-BFFFF are not handled properly #1164225 define BX_SUPPORT_X86_64 0 #1163720 ROL bug #1156776 keyboard scanmode fault #1162042 Duke Nukem 3D: >>PANIC<< iret: VM set on stack, CPL!=0 #1161945 ctrl_xfer32 compile/make error #1157124 Bochs doesn't run with large amounts of memory in bochsrc #1154266 weird INT handling in V86 mode #1157051 default Bochs CVS doesn't work-out-of-the-box #923954 enter() with level > 0, >>PANIC<< iret: return CS selector #1098476 Privilege Problem after SYSEXIT #1121734 Bochs crashes when shutting down Win95 #1099294 VESA for Win98 bogus #1112836 PGE-Bit crashes Bochs #947586 The specification difference in x86-64 emulation #1117145 Push reset Button, APIC0 Error occur #1123043 fpu stack pointer changed *despite* fault occured (e.g. #pf) #1122066 PANIC: iret: IP > descriptor limit when installing os/2 warp #809574 rm -f segfaults #593952 SuSE rm segfaults #929783 floppy not recogniced since 2.1 #1099298 SB16 for Win98 Bogus #1079483 Reading from a CDRW #549793 flaw in interrupt gate handling(exception.cc) #692055 SMP Error #805479 Booting from disk causes illegal instruction warnings #909677 pc-speaker doesn't work #831751 behaviour unrealistic #661213 CR4.TSD is broken #685508 PANIC: prefetch: RIP > CS.limit #1037923 Non-executable page support missed (NX bit, x86-64) #1106530 wrong disassemble result #1105208 drive order for boot gets saved wrong #661060 Problem with Win98SE #837377 Norton Ghost don't boot #876689 Unknown register 0x17 [CPU] / WIN98SE #947282 Bochs segfault #963317 Persistent Win98SE #1101168 APIC base address change #680737 panic when installing winme #1097187 Install FC3 on bochs-win failed #875461 vgabios-lgpl should be default #594797 Bochs segfaults #602994 bochs breaks boot kernel #571539 FreeBSD Install from CD Fails #774257 Device doesn't work under W98 #759228 Installing Suse 8.2 in Bochs on WinME #792561 cant boot freebsd 5.1 from cdrom #804004 Live cd will halt on boot.. #956173 FreeBSD won't boot iso install images in Bochs v2.1 or 2.2. #864401 >>PANIC<< jmp_ev: IP out of CS limits! #853831 Error on int 15h #1094150 DR-DOS 7.03: panics when using multitasker #655592 win98 hardwaredetection #1093786 Solaris 9 installation CD fails #959585 USB UHCI IO-Device #963314 Redhat Fedora Installer Kernel Panic and Crash #1086920 Bochs (cvs) doesn't compile on FreeBSD 5 #879050 Bochs reports enabled APIC without support #1071199 dBaseII cause prefetch: RIP > CS limit #1070812 typecast error while compiling wx.cc #1068786 FSINCOS Cos value wrong at 90 degrees #675248 Panic: EIP > limit on win98 install #829793 [CPU ] prefetch: RIP > CS.limit #1034059 >>PANIC<< prefetch: running in bogus memory #1067813 pbm fpu_proto.h:144 ebuild gentoo bochs 2.1.1 #922034 bios not aliased at 0xFFFFF000, registers wrong after reset #912666 Configure fails on Yellow Dog Linux 3.0.1 #922038 Unexisting memory should read back as 0xFFFFFFFF #1019723 HD image #1057814 Shadow RAM not aligned #1057240 Invalid IRET32 implementation #809682 >> PANIC << : prefetch: RIP > CS.limit #618680 memory referencing problems #724262 A few things (Windows 2.03, Wolfenstein) #985375 Crash Mandrake 7.1 #913418 compiler errors with --enable-external-debugger option #708847 CR8 access should not panic X86-64 #1039499 Compile error pcipnic.cc (cygwin) #978024 compile against wxGTK-2.5.2 fails #639073 MacOSX: Networking not implemented #639074 MacOSX: Soundblaster not implemented #963264 Latest CVS --enable-pcidev fails to configue on YDL Linux #586282 Mac OS X, will not "make" #699532 CVS (as of 2003/03/07) cannot read disk images #639275 wrong more than 2GB size DVD-ROM #766020 info registers / dump_cpu get old eflags #655920 QuickBasic (qbx.exe) panics #676188 Error BX_MAX_DIRTY_PAGE_TABLE_MEGS #923821 LOCK not generating exceptions properly #1007747 Wrong configure? #1022577 show "call" command crashes bochs every time #681849 SuSE 8.1 Compile problem #660322 Install bochs 2.0 on SuSe 8,0 #1022587 "Unrecognized args" message wrong after invalid show command #833118 TUN/TAP interface bug #1022178 tuntap module mangles incoming broadcast packets #1028682 Report incorrect disk parameters of floppy #1026234 make fails on Cygwin because of missing .exe extension #1026241 --enable-cpp needed for .conf.win32-cygwin #855323 BIOS Panic at rombios.c, line 1563 #762773 ROM checksum is not checked in rom_scan_loop #657604 concat_image_t.lseek to byte -1378816 fa #800140 No AH=83h INT15h implemented #831965 Win32.zip BIOSes in wrong directory #873280 bximage crashes after createing "growing" #892223 bochsrc-sample.txt/vgaromimage option error #1014361 Bximage on WinXP won't create image #651510 bximage won't create larger than 2GB #759206 bximage fails on Win32 for hd images over 2Gb #759210 Bochs fails on image files over 2Gb on Win32 #799785 bximage doesn't work #903345 Problem compiling harddrv.cc #933303 Bochs cannot lseek() HD images > 2GB on W32 platforms #888438 bximage crashes...(hacked fix included) #871720 bximage 2GB file size limit #930368 Can't create big hard drives (>2 GB) #912496 IDIV can cause simulator divide error #522111 Host os SIGILL, booting grub from hd #1005052 DMA Controller Model Problem #552939 Bochs window doesn't resize when win311 #989478 I-Cache and undefined Instructions #661008 make install fails #845691 Workaround: Ne2k and Windows 2000 not working #923662 BIOS diskette motor countdown byte broken #848141 VGA problems running Scitech Display Driver on Win95 #799370 Problem booting ReactOS 0.1.3 #670143 No rule to make config.h #653444 with vbe/lgpl bios, scrn updates broken #655696 quickstart broken? #659350 FDC #620853 Ne2000 ethernet card *NOT* supported #607611 Numlock #543476 Sound card does not work in Windows 95 #529554 unsupported VBE features DISPI update #487316 Access violation on Win32 #576253 RTC too fast #489748 io read from address 000003c0, len=2 #656861 Gentoo Linux panics in VGA code #787184 Video BIOS's don't checksum correctly #988529 textconfig [Save options to] function output obsolete option #987293 Cannot accesss header/toolbar #988246 floppy read error #933199 speedup Bochs compilation 4x -> suggestion #979106 Incorrect disassembly table entry #658374 FPU incorrect emulation #706933 Problem with the F12-Key #477043 math_abort panic in RH 7.1 #634371 Floating point problems #681138 // is not valid in C #643300 cpuid feature flag 15, cmov and fcmov #913697 missing division by 0 exeption in fpu emuation #923682 FSTENV/FINIT problems #923855 FPTAN doesn't work right with full NPX stack #924379 ET bit mismatch between CR0 and MSW #716116 Direct floppy access #962919 Mac: iodev/cdrom.cc disordered #954751 Two FPU.CPP in project #954359 Compile faile is 3dnow support is selected without SSE support #906412 FreeSCO error #942060 FDC Controller not conforming to specifications #938522 Win XP installation fails #923613 BOUND instruction exception handling is broken #923223 memtest86 errors #593342 autoconf script doesn't regenerate clean #616116 Crash on exit... #922042 shutdown through port 92 does not work #891633 02839990390p[CPU0 ] >>PANIC<< RDMSR: Unknown register 0x17 #923653 DAA instruction is broken #911225 obscure AAA / AAS bugs #837206 Problems with numerical keys #658765 BOCHS halts in runtime config #890734 Bochsrc Parser Bug with commas included in strings #877285 MSR_APICBASE zero upon startup #526984 SDL compiled in cygwin just quits #886406 I/O permissions bug #883239 undefined symbols in gui/siminterface.h:1215 #419647 on OSF1, cxx hates C++ inlines #809790 "No rule to make target `devices.cc?..." #873654 How compile without plug-in support ? #837161 Test case for BX_CPU_C::IRET32 #888116 mmx.cc compile error ------------------------------------------------------------------------- Changes in 2.1.1 (February 8, 2004): - fix bug in int15h function 0xe820 (Christian Neubert) - fix vmware3 disk support on big-endian platforms (Christophe Bothamy) - fix conditions for NM exception on FWAIT instruction (Christophe) - fix symbol conflict in rfb and x display libraries (Volker Ruppert) - allow 16 bit writes to ne2k page 0 (Kenneth Stailey) - notify display libraries on change of bpp (Volker) - fix bug in int13h function 0x10 (Volker) - fix floppy dialog error on win2k (Volker) - fix adress check in TSS IO permission bitmap (Christophe) - fix buffer overflow vulnerability pointed out by SeSoX (Christophe) - updates for MacOS compile (Daniel Gimpelevich) ------------------------------------------------------------------------- Changes in 2.1 (January 9, 2004): Brief summary : - New disassembler - 3DNow!/SSE/SSE2/PNI instruction support - Vmware3/Sparse/Undoable/Growing harddisk images support - many VGA emulation improvements (e.g. high/true color VBE modes added) - No more X11 vga font required Detailed change log : - CPU - added emulation of AMD 3DNow! instructions set. (Stanislav Shwartsman) Bochs now could decode all AMD 3DNow! instructions. Most of instructions still not implemented, but the basis already presents. Configure --enable-3dnow to enable 3DNow! support. Notes : - These instructions are not implemented yet: PFPNACC_PqQq, PF2IW_PqQq, PFNACC_PqQq, PFCMPGE_PqQq, PFMIN_PqQq, PFRCP_PqQq, PFRSQRT_PqQq, PFSUB_PqQq, PFADD_PqQq, PFCMPGT_PqQq, PFMAX_PqQq, PFRCPIT1_PqQq, PFRSQIT1_PqQq, PFSUBR_PqQq, PFACC_PqQq, PFCMPEQ_PqQq, PFMUL_PqQq, PFRCPIT2_PqQq - CPUID does not report 3DNow! instruction set. - added emulation of SSE/SSE2 floating point instructions. (Stanislav) All SSE/SSE2 floating point instructions are fully implemented using free softfloat library (including DAZ support and floating point exceptions). Correctness of the emulation checked with heavily random testing. - added emulation of SSE3 (PNI) instructions (Stanislav) Currently only 3 PNI opcodes still not implemented: FISTTP m16int, FISTTP m32int, FISTTP m64int - added P4 CPU support to CPUID instruction. (Stanislav) - fixed implementation of FXSAVE/FXRSTOR instructions. (Stanislav) - bugfix: unallowed lock prefix cases must cause #UD exception. (Stanislav) - fixed fetchdecode bug caused #UD in SYSENTER/SYSEXIT instructions in 32bit mode. (Stanislav) - fixed fetchdecode64 bug caused wrong decoding of opcodes containing BxImmediate_IvIw or BxImmediate_IwIb in x86-64. (Stanislav) - fixed bug in int01 (opcode 0xF1) emulation. (Vitaly Vorobyov) - fixed bug in x86 debugger with dr0-dr3 registers (Vitaly) - fixed bug with mov to/from dr register in v86mode. (now exception is generated (according to Intel documentation) instead of panic) (Vitaly) - fixed stack limit checking, now message is generated as BX_DEBUG, rather then BX_PANIC, and exception code is executed. (Vitaly) - instrumentation code updated. (Stanislav) - fix flaw in IO bitmap permission of TSS (Christophe Bothamy) - cpu resets on triple fault (Christophe) - remove calculation on cr3 in dtranslate_linear to increase emulation speed (Conn Clark) - numerous x86-64 fixes (Peter Tattam) - FPU - hundreds of bugfixes in FPU emulation after checking of the emulation with testfloat (Scott Duplichan). - Fixed cases: - floatx80_to_int32, floatx80_to_float32 - floatx80_to_float64, floatx80_round_to_int - floatx80_add, floatx80_sub, - floatx80_mul, floatx80_div - implemented FCMOVcc instructions (Stanislav) - 64-bit addressing support for x86-64 mode (Peter) - Disassembler - replaced Bochs disassember. New table-based disassembler fully supports all IA-32 instruction sets including all FPU/MMX/SSE/SSE2/SSE3 opcodes. (Stanislav) - I/O devices - general - i/o access mask implemented, unallowed cases are now handled in the devices code and cause a BX_ERROR (Volker Ruppert) - include slowdown timer as a runtime option (Christophe) - netBSD : fix serial, ethernet, cdrom (fredb, uebayasi and David Laight) - VGA - color depth 15, 16, 24 and 32 bpp supported by VBE (Volker and Christopher Nelson for 32 bpp on win32). Supported by sdl, x, win32 and wx. - SVGA mode 0x6A (800x600x4bpp) implemented (Volker) - new CGA graphics modes 640x200x1bpp and 160x100x4bpp (text mode 80x100) (Volker) - raster operations AND, OR and XOR in write mode 2 (based on SF patch #707931) (Volker) - 'split screen' in standard VGA graphics mode implemented (Volker) - 'double scan' and 'double width' now handled in the VGA code (Volker) - more accurate emulation of the horizontal and vertical retrace (Volker) - changeable start address and variable line length supported by all graphics modes (Volker) - VBE: preserve video memory feature implemented (Volker) - additional text mode features prepared (handled in the display library code) (Volker) - PCI - add experimental PCI VGA card (Mike Nordell) - add experimental PCI USB card (Ben Lunt) - Harddisks - per device selectable harddisk modes : - undoable, volatile, growing disks support (Christophe) - sparse disks support (justinSB) - vmware3 disks support (Sharvil Nanavati) - fix non detection of hard drives by minix2 (Christophe) - implement atapi command 0xA8 read (12) (Christophe) - mode sense command updated (Hartmut Birr) - sb16 - opl2 support enhanced (James E. Flemer) - ne2k - tap support for FreeBSD (Ronald Klop and Gen Otsuji) - fix when booting with grub (Keir Fraser) - cmos - date/time change support added (Volker) - UIP bit and divider chain reset implemented (Volker) - initial time can now be set to local time or utc (Christophe, Daniel Gimpelevich) - keyboard - keyboard reset function (0xff) now resets the keyboard (Volker) - gameport - new standard PC gameport device (real joystick connected on Linux and win32 only). Enable it with --enable-gameport or the SB16 emulation (Volker) - serial - FIFO emulation (UART type 16550A) implemented (Volker) - floppies - 160k,180k,320k floppies support (Ben Lunt) - display libraries - X11 - onboard vgacard charmap usage (no need for external X11 vga font any more) (Christophe) - vgacard charmap change support (Christophe) - fix black stripes on partial exposes (Dirk Thierbach) - headerbar redraw optimizations (Dirk Thierbach) - external font files and their installation mechanism removed (Volker) - belgian keymap support (Wouter Verhelst, Eric Brasseur) - win32 + wx + x: new application/window icon (bochs.ico / icon_bochs.xpm) (Volker) - sdl + win32 + wx + x: new textmode features: variable line length, char width switch, horizontal and vertical pel panning (Volker) - win32 + wxMSW: key event handling rewritten (Volker) - win32: status bar at the bottom of the simulation window added (Volker) - wxMSW: resource problems fixed - wx dll plugin works now without errors (Volker) - term: variable line length and cursor enable/disable feature implemented (Volker) - rfb - textmode: charmap change, better cursor emulation, variable line length (Volker) - headerbar works now (power, reset and user button are okay) (Volker) - key event handling rewritten (Volker) - Bochs-RFB waits up to 30 seconds for a client connection. The emulation starts after connecting the client. (Volker) - carbon: Alt/Ctrl/Shift key handling rewritten & SysRq/Ctrl-Break key support added (Daniel) - configuration interface - gui dialogs as an extension of the textconfig interface on win32 added (Volker) * ask dialog * save text snapshot * user button shortcut * floppy image change - wxwindows configuration dialogs improved (Volker, Christophe) - support tools - bximage : added support for - growing disks (Christophe) - sparse disks (justinSB) - created bxcommit tool for undoable disk images (Christophe) - System BIOS : - fixed int15 function e801 (get memory size) (Christophe) - added int75_handler for FPU Dos Exceptions (Christophe) - added int16 function 0a (Get Keyboard ID) (Volker) - added support for ElTorito Harddisk-on-CD emulation (Christophe) - fixed ATA/Serial ioport conflict (Daniel) - VGA BIOS : updated to version 0.4c (Christophe) - configure script/compile/porting to other OSes/installation - fixes for compilation with MSVC (Andrew Zabolotny) - fixes for cross-compilation (Jeroen Janssen) - win32 nsis installer script updates (Volker) - small configure fixes for MacOS (Christophe) - optimizations & compile fixes for MacOS/X (Daniel) - configuration files. The following options have been deprecated : diskc, diskd, cdromd, time0, pit, newharddrivesupport. - documentation - already ported and obsolete parts of the old documentation removed (Volker) - user documentation updated and extended : - improved section "What does Bochs need" (Volker) - command line arguments (Volker) - search order for the configuration file (Volker) - the configuration interface 'textconfig' (Volker) - FreeDOS Beta 8 installation instructions (Volker) - disk modes (Christophe) - LBA translation (Christophe) - cdboot error codes (Christophe) - SCO OpenServer install section (Carl Sopchak) - MacOS-X DMG install guide (Aard Vark) - update Win98 install guide (Dirk Thierbach) - SF patches applied #658950 Bug in FPU (Anonymous) #678117 build fail due to bad SGML punctuation (Anonymous) #671873 minimal USB support (UHCI) (Ben Lunt) #682539 Fix CapsLock and NumLock behavior (rock at gimp.org) #720776 REX MOVB immediate broken for x86_64 (Arnd Bergmann) #729450 new keymap x11-pc-be.map (Wouter Verhelst) #735990 Limited patches for VC++ (Anonymous) #742670 fix library dependencies in GUI plugins (Robert Millan) #742782 LFB bugfix (Jan L. Hauffa) #748414 load32bitOShack bug (kyriazis at nvidia.com) #830079 Fix bochs's application error if unsupported key pressed (Anonymous) #724466 enable building with CC=gcc-3.2 CXX=g++-3.2; dist-clean adds(Leonard Norrgard) #834962 Fixed drawing graphics is broken (Anonymous) #838401 Fixed redrawing of ToolBar on Win32GUI (Anonymous) #850236 Fixed accessing DVD-ROM with direct device access on Win32 (Anonymous) #847822 Bochs crash when exmining memory that crosses page boundary (ortal at jungo.com) - SF patches partially applied #707931 Support EGA/VGA write mode 2 and others (Anonymous) already applied: disable IME, split screen, write mode 2, BIOS INT16h/AH=05h #856506/#856510 Patch to fix compile-time iodev/cd-rom.cc error (alden.dima at nist.gov) Correct patch provided in SF bug report #843433 (birkhofer at users.sourceforge.net) - patches applied - patch.highmem (memory allocation) (Zwane Mwaikambo) - patch.floppy-160k-180k-320k-benlunt (exotic floppies) (Ben Lunt) - patch.perf-regparm-cclark (performance) (Conn Clark) - new patches present in the patches directory : patch.pipelined-asm-cclark patch.mingw-resources patch.v8086-exception.lightcone patch.pit-vitaly-vorobyov patch.rombios-vitaly-vorobyov patch.win32-vitaly-vorobyov patch.win32-new-files-vitaly-vorobyov.tgz patch.rombios.markevich patch.rombios.dirk.thierbach - these S.F. bugs were closed #865354 ">>PANIC<< CRA: divider chain control 0x07" in Linux 1.1 #725796 configure script bug #859768 cpuid #863964 panic in duron 2000 #843433 cdrom.cc on MacOSX: wrong const names #818493 EMU][ (DJGPP app running on FreeDOS) broken #787005 Some MOV instructions are not implemented!!! #840664 2200136693936p[CPU ] >>PANIC<< prefetch: RIP > CS.limit #837416 V2 OS not compatible !? #650917 Serial port broken under win95 #829863 Make bochs 2.0.2 build with gcc3 #816971 main.cc: getcwd() missing argument #813556 Compile error under gcc 3.3.1 #809758 RIGHT ALT does not function properly #809695 CVS complains about unknown files after compilation #628762 Error in Floppy Booting #474526 Crash under win32 (access violation) #687619 test case for BX_CPU_C::IRET32 #664544 Panic in IRET32 - Reporting test case #637822 test case for BX_CPU_C::IRET32 #603410 BX_CP U_C::IRET32 #537047 IRET32 incomplete emulation, panic #805541 Compile fails on i686, gcc 3.3 #798829 Problem booting from ISO image #688163 Panic at rombios.c #688161 rombios.c crashes when boot from a CD. #796339 int 15h, e801h broken? #666946 Slowdown Timer should be a module #783826 the clock is extremely fast #645609 Real Time Clock is too *FAST* #663320 flaw in IO bitmap permission handling #764929 Timing is off. #659510 Bochs timing off by x10 #787138 No ROM BIOS character map #787134 Config options not saved #689201 Disassembler bug #666202 Windows 2000 - random screen blanking with linux DLX demo #629242 reset during Doom -> BIOS panic #695434 minix floppies won't boot. #764473 Freesco Linux crashes on boot #656026 error when trying to run some stuff #614202 HD: non-byte IO read to 01f4 #777357 Strange FPU compiler error #583758 gag bootloader doesn't run #658639 ne2k panics with MS lanman Client/DOS62 #536711 problem running smart bootmanager #741433 Disabling all ata# results in HD error. #753200 lock instruction doesn't do an illegal instruction trap #679389 libbx_wx.so.0: undefined symbol #758936 Problem Installing Bochs #742580 I configured fants but bochs still give me the same error #772242 iodev/vga.cc wrong memory access. #739222 Cannot change resultion #693344 libwx_gtk2.3.so.2 RedHat linux 8.0 #639320 sparc: needs -lm to compile #587422 Windows 95j doesn't boot #547817 sparc: rfb needs -lsocket #480963 RFB: option to wait for client #763893 i've got problems with a "libvga.so.1" and another file #766490 Documentation mistake #766481 Bochs 2.0.2 Fails to compile on YDL3.0 #626144 %lld is not portable #752241 lock prefix erronously allowed for some instructions #743305 fetchdecode.c probs #658707 Automatic exit? #696758 BeOS can't mount image disk, won't complete boot. #737048 Enabling keyboard resets controllers translation mode #717713 Bochs panics on startup on RH 9 #741108 VGA PANIC #730922 seg fault on "bochs boot: cdrom" #658905 VGA read write error #564218 Panic on vga_mem_write #614231 X11 doesn't support charmap change #708311 Missing CGA low-res emulation #720776 REX MOVB immediate broken for x86_64 #643296 lock prefix, unallowed cases #716964 [sb16] OPL.timer_running not initialized #662074 little mistake in the default config example #470701 CD-ROM on Win2K needs FILE_SHARE_READ #706454 bug?? #653861 Win32 build bug #421155 panic on vga read 0x3c7,0x3cb #666434 VGA BIOS: Incompatible mode reporting #681819 Incorrent return value from cdrom reads #648222 Lotus Agenda futuristic dates off #657455 doesn't boot plan9 #658938 SGDT in VM8086 ------------------------------------------------------------------------- Changes in 2.0.2 (January 21, 2003): - fix possible segfault in wxWindows (Volker Ruppert) - fix instrumentation (Stanislav Shwartsman) - fix cdrom read_toc() function for *BSD (Keith Matthew Jones) - fix NetBSD boot from cdrom (Christophe Bothamy) - fix cmos checksum (Volker) - fix "refresh bit" behaviour in pit (Volker) - fix .bochsrc parsing (Volker) - fix vga resize/redraw problems (Volker) - fix compilation issues on Irix and Tru64 (Christophe) - fix MMX/SSE bugs (Stanislav, Peter Tattam) ------------------------------------------------------------------------- Changes in 2.0.1 (January 4, 2003): - fix corrupt saved configuration files (Christophe Bothamy) - fix missing break statements in apic (Shai Fultheim) - fix compiling sb16 under FreeBSD (Volker Ruppert) - updates to the documentation (Volker) - fix text mode colors 8 to 15 (Volker) - fix FPU integer load bug (Volker) - stop pasting on hardware reset (Volker) ------------------------------------------------------------------------- Changes in 2.0 (December 21, 2002): Since the change log is hundreds of lines long, here is a very brief summary. - 2x emulation speedup!!! - added plugin devices and guis. Now you can compile with many more options, and choose between them at runtime. - added emulation of AMD x86-64, MMX, SSE, SSE2 instructions - add wxWindows port (a graphical configuration interface and display lib) and SVGAlib port (full screen display for Linux without X11) - improvements in many I/O devices: for example up to 8 hard disks/cdroms, TUN/TAP network interface, 360k floppies, - improved MacOSX/Carbon interface and updated MacOS9 port - GDB remote stub, allows symbolic debugging with Bochs simulation. - support for up to 32gig hard disk images Detailed change log follows. - documentation - manpages updated (Volker, Christophe) - install HTML rendering of docbook documentation instead of docs-html (Bryce) - doc/docbook/Makefile is now generated by configure script. if configure detects docbook2html on your system, it will turn on --enable-docbook and run make in the doc/docbook directory. Also make install will install documentation into $(docdir). You can use --disable-docbook to turn this off, if necessary. (Bryce) - add "make bochsdoc.tar.gz" target to create a documentation tarball. If you do "make webinst" and you have write access on SF shell server, it updates doc/docbook/* on the website (Bryce) - user documentation additions: - new options (Bryce, Volker, Christophe) - Bios tips section (Christophe) - Tuntap section (Christophe) - Serial Port section (Christophe) - "Will it Work for Me" / "Is Bochs Right for Me" sections (N. David Guarneri) - VESA section (Jeroen Janssen) - several documents, previously existing as separate html files, have been included : - internal debugger section (Christophe) - gdb stub debugger section (Christophe) - WinME, WinNT, WinXP, The Hurd, Japanese Win95 install tips (Christophe) - Win95, Win98 install tips (N. David) - SB16 section (N. David) - configure script/compile/porting to other OSes/installation - added plugin architecture - plugin code written by Bryce, Christophe, Volker based on plex86's plugin code by Kevin. Testing help from Psyon and Br'fin. - Plugins are shared libraries that can be loaded on demand. Example: the serial device is implemented as a plugin. In UNIX, the serial plugin is called libbx_serial.so. When Bochs reads its configuration file, if the serial device is enabled it loads libbx_serial.so. - all display libraries, most I/O devices are converted to plugins now - plugins supported on Linux, Solaris, and MacOS X using libtool, Cygwin using dlltool. On MacOSX, you must have dlcompat installed and in your include/library paths at configure time. (See .conf.macosx for an example.) - we use libtool's LTDL library from libtool 1.4.2, with a number of critical bug fixes (Bryce Denney) - the Linux binary RPMs are built with plugin support - to compile with plugins, configure with --enable-plugins - the LTDL_LIBRARY_PATH variable tells Bochs where its plugins can be found. Bochs has a compile-time default for this variable which is correct if you do a make install. You would only need to set the variable if the default is wrong. - for win32 plugins we added "BOCHSAPI" in front of many classes and methods, to aid in building DLLs. This turns into __declspecs which are used when making an export library for Bochs. - allow many display libraries to be configured and compiled at a time. For example --with-win32 --with-sdl --with-rfb. Also, we added an experimental option --with-all-libs which tries to detect which --with-* options will work. If the autodetection fails, just type the --with-* options explicitly. (Bryce) - add #if's around all files which are conditionally compiled such as cdrom.cc and sb16.cc. This makes it possible to compile every source file all the time, which has the potential to simplify the configure script and makefiles. At present we only take advantage of this capability in the win32 VC++ workspace. (Bryce) - the MacOS9 port has been updated so that it works again. It had not been updated in at least 2 years, maybe more. (Christophe Bothamy) - improve support for FHS standard (Robert Millan, Volker Ruppert) See patches 551811 and 650066. - keep separate CFLAGS and CXXFLAGS for Bochs (usually a graphical program) and console programs such as bximage and niclist. Some sdl and wx compile flags were making bximage and niclist unusable.(Bryce) - add concept of cross-configuring in the configure script. If you use the --target option to generate makefiles to be used on another machine, some detection of compilers and libraries is disabled. (Bryce) - fix term compile on Cygwin, but it has to be done without -mno-cygwin, which means that several win32 features such as networking do not work. - add "-Wno-multichar" on beos - test for largefile support, and add required CFLAGS (Bryce) - add -lm when it's needed, and not when it's not (Bryce) - add configure support for 8 processors. Bochs can support up to 15 with some work on the BIOS. - fix nmake makefile generation (Psyon) - improved pthread detection function from ac-archive project on SF - add installer package for Windows, using Nullsoft (Michael Rich, Bryce) - on MacOSX, add startup script that creates a text console and then runs Bochs. Also add make target to create a DMG disk image (Br'fin) - do not restart the font server on Unix/X11, if vga.pcf was already installed. On several modern machines, if you restart the font server the user has to restart X windows. (Bryce) - update most .conf.* files with modern options such as --enable-all-optimizations. (Bryce) - The MacosX .conf script adds /sw/include and /sw/lib to the compile/link path list because it is a common place to put dlcompat. Dlcompat is required when building with plugins. (Bryce) - rpms can now be built without root privileges (Bryce) - command line - fixed up our command line options (Volker, Bryce, Christophe) Usage: bochs [flags] [bochsrc options] -n no configuration file -f configfile specify configuration file -q quick start (skip configuration interface) --help display this help and exit - configuration file (bochsrc) - There are several new options. See the documentation for more details. - config_interface: select text mode menus or wxWindows for configuration - display_library: select which display lib to use - optromimage: load optional rom images - ataN (N=0,1,2,3): up to 4 ATA controllers for hard disks, cdroms - ataN-master, ataN-slave, N=0,1,2,3: defines a hard disk or cdrom. The "ata*" options replace diskc, diskd, and cdromd, which are now deprecated. - floppy_bootsig_check: control the 0xaa55 signature check on boot floppies - logprefix: lets you change the format of log messages (patch by Carl Sopchak, help from Christophe) - debugger_log: log all output from bochs debugger - user_shortcut: allow you to type key combinations like Ctrl-Alt-Del - pit: control the PIT model, including realtime option to try to keep in sync with real time. - Credits: Christophe added optromimage, everything about ATA, floppy_bootsig_check, debugger_log. Bryce added config_interface and display_library. Volker did the user_shortcut button. Greg Alexander wrote the PIT model and added the realtime option. - since v1.3 we've been able to use environment variables in pathnames in the bochsrc file. Now, a few variables have default values, set at compile time, that are used if the user does not set a value. If Bochs is installed correctly, the defaults will be correct and the user will not need to override them. - $LTDL_LIBRARY_PATH is the path name where the plugins can be found. The default value comes from $(plugdir) in the makefile. This is only important if plugins are enabled. (Bryce) - $BXSHARE is the path where the BIOSes and keymaps are installed. The default value comes from $(sharedir) in the makefile. Disk images on the Bochs website will begin to use BIOS pathnames like $BXSHARE/BIOS-bios-latest. On win32, the $BXSHARE default is set by the NSIS installer and read from the registry. On MacoSX, the $BXSHARE default is set to the path containing bochs.app. (Bryce, Volker, Br'fin) - new option in the configuration interface to reset all bochsrc settings to initial defaults. A reset occurs just before reading a new configuration file, so that leftover parameters from a previous configuration do not affect the new configuration. Also, you can request a reset using the configuration interface. (Volker, Bryce) - ne2k line can now specify a script to set up the interface (Christophe) - on Unix, also search /etc/bochsrc (Bernhard Bablok) - you can use #include in the bochsrc to read configuration from other files (Volker) - CPU - speed optimizations from Kevin Lawton, yielding around 2x speedup - guest2host_tlb : for entries in the paging TLB which point to normal physical memory pages, a pointer to the host address of the emulated physical memory (from malloc()) page is stored in the TLB entry. In many cases, this pointer can be used in memory accesses to directly read/write the guest memory address. In exceptional cases, the physical memory access routines are used. Turn on with --enable-guest2host-tlb. - repeat IO/string : for some variants of repeatable IO and string instructions, the segmentation and paging checks are done in batch along with the data transfers, constrained within page boundaries and the segment limits. Turn on with --enable-repeat-speedups. - icache : The structure holding instruction decode information was reduced to 32 bytes. 24 bytes for the actual decode data, and 4 each for pointers to the address resolution routine (not always needed) and the instruction emulation routine. With a reasonably small per-instruction decode size, an instruction cache (iCache) was created, which is simply a hash table. The main cpu loop looks in the table first; if the instruction has already been decoded, execution can begin immediately without decoding. Turn on with --enable-icache. - host specific asm : when compiling on an x86 platform, use of x86-specific asms can be enabled to accelerate several facets of emulating instructions. For example, the EFLAGS values are much more efficient to calculate when the actual x86 instructions are used to generate the EFLAGS values. Turn on with --enable-host-specific-asms. (Kevin, with help from Jas Sandys-Lumsdaine) - if you want to enable all the speed optimizations that we believe to be stable, use --enable-all-optimizations. The release binaries are built with this option. - add support for AMD's x86-64 instruction set. To enable, configure with --enable-x86-64. The AMD x86-64 support is about 90% complete and is still experimental. We've implemented the core x86-64 instruction set and the changes to the rest of Bochs necessary to operate in long mode, but we've still to implement checking for canonical 64 bit addresses. The code has been tested on a limited number of test programs. It has been able to successfully boot a x86-64 Linux kernel and run a 64 bit userland application. It has also successfully run a DOS based 64 bit protected mode test application. (Peter Tattam, with merge/bugfix help from Kevin Lawton and Bryce Denney) - add MMX support. To enable, configure with --enable-mmx. (Stanislav Shwartsman) - add SSE and SSE2 support. To enable, configure with --enable-sse=1 or --enable-sse=2. (Stanislav) - fixed the behaviour of the bcd instructions AAM, AAD and DAA based on SF patch #537146 (Volker) - stop printing an error for VERR/VERW. According to the i386 opcode description there is no error present. (Volker) - fix bug [ 625878 ] reset doesn't reset something(?). Fix cpu reset when executing a rep instruction (Christophe) - use accessors methods for CFLAGS and several other registers, so that the implementation can be changed transparently later (Bryce, Stanislav) - add support for page size extensions, also known as 4meg pages. Turn on with --enable-4meg-pages. (Kevin Lawton) - add support for page global extensions. Turn on with --enable-global-pages. (Kevin) - add support for physical address extensions. Turn on with --enable-pae. (Peter Tattam) - implement RDMSR and WRMSR. not all MSRs are supported (Zwane Mwaikambo) - new configure option --enable-ignore-bad-msr, which makes unrecognized MSR reads and writes into just a warning - fix PIC/APIC interrupt problem that caused Linux 2.4.19 to hang during boot (Peter) - CMPXCHG8B patch (Michael Hohmuth) - EFLAGS are now stored in the same form as the native EFLAGS on an x86, so that we can use native machine instructions in some cases (Kevin) - instrumentation code updated (Stanislav) - FPU - fixed bug [ 452275 ] fprem emulation bug (Volker) - fixed bug [ 648579 ] Mac OSX >>PANIC<< FPU_printall. There was an endianness issue with the fpu (Christophe) - I/O devices - rewrote pc_system timers (Kevin) - biosdev - this new device handles the panic/error/info/debug messages sent by the Bios and VGABios. It was previously done in the unmapped device. - cdrom - implementation of the function READ TOC for cdrom image files. (Volker) - function capacity() for win32 fixed. Now it returns the number of blocks instead of bytes. (Volker) - added multiple cdrom support for win32 (NT/2000 version untested). The ASPI version uses the cdrom drives in the system's order. Drive letters are not used by ASPI. (Volker) - fix configure script's cdrom detection on BeOS (Bryce) - fix physical CD change at runtime (Bryce) - cmos - fix panic when WinXP read port 70h (Christophe) - add ps/2 style century at index 37 to allow WinXP to boot. (Bryce) - dma - DMA register and unregister functions for DMA channels added and macros for DMA functions defined. The changes are based on the Plex86 functions. (Volker) - implementation of the DMA controller reset (Volker) - the value of the command register must be always 0x00 (BX_ERROR fixed) - floppy (Volker) - implemented Tape Drive Register (Dave Poirier) - added support for 360k floppy images - the skip flag (SK) in command 'read sector' is ignored now - floppy read and write function do not set the 'seek end' bit in status register 0 (fixes SF bug #553377) - the status of the 'disk changed' line depends on the selected drive. The digital input register is now an array (DIR[4]). - apply patch [ 635021 ] floppy cleanup by Alex Thiel - distinguish between floppy drive type and media type - hard drive - add largefiles support, to allow disk images larger than 2gig. (Stu Grossman) - missing conditions for lower_irq() added (Volker) - several noncritical panics replaced with BX_ERRORS and the controller returns an error code until we implement the features (Volker) - applied patch from Carl Sopchak for booting sco openserver - allow disk block access only if concatenated images are not used (Christophe) - fix bug [ 419415 ] netbsd 1.5 rescue disk won't boot (Volker) - multiple drq atapi data transfers corruption fixed (Christophe) - added some commands to the unsupported "Set Feature" commands (Christophe) - speedups in repeated IO transfers (Kevin) - support for Peter Tattam's external disk simulator (Bryce) - 4 channels / 8 devices support (Christophe) - "inquiry" atapi command results corrected (Volker) - check for incomplete devices configuration before starting the simulation (Bryce) - implemented the different bios disk translation schemes (Christophe) - keyboard and mouse - add commands 0xd2, 0xdd and 0xdf (Dave) - fix bug [ 613975 ] wxWindows: params redefined on restart (Bryce) - in function mouse_motion(): added parentheses to fix compilation problems with MSVC. See SF bug #575301. (Volker) - added missing register_irq() for the PS/2 mouse IRQ12 (Volker) - fix "AltGr" key on European keyboards wxWindows/win32, SDL (Volker) - NE2000 - function reset() clears the IRQ line (Volker) - added TUN/TAP interface (Renzo Davoli, Christophe) - fix DOS based packet drivers that use an odd count for the NE2000 DMA (Peter) - changed "TCR write, reserved bits set" panic into an error, fixes networking with debian image (Bryce) - parallel - parport1 enable/disable support added (Volker) - PCI (Volker) - implementation of the PCI device register mechanism - PCI memory handling moved to the memory code - replaced memcpy() in pci_read() by a more portable code. Problems with PCI on big-endian machines are fixed now (SF bug #638481). - implementation of the PCI-to-ISA bridge started (still incomplete) - PIC - fixed detection of single mode and level senistive mode in ICW1 (Volker) - fixed handling of rotate_on_autoeoi for master PIC (Volker) - irq mask is now cleared on initialization (Dave) - fixed lockup during mouse movements during win98 install. (patch from Wilfried Weissmann) - PIT - Added realtime PIT support (Greg) - Sound Blaster 16 - it used to enable itself all the time; now only when you ask - fix memory leaks (Bryce) - serial - don't cause problems when serial device is disabled (Volker) - unmapped - add programmatic shutdown feature at port 0x8900 (Christophe) - vga - VBE fixes (Jeroen, Volker) - CRTC fixes (Volker) - sequencer reset with bits 'reset1' and 'reset2' implemented (Volker) - add charmap change support (used by SDL, win32 and wxWindows gui) (Volker) - screen dimensions / updates for some graphics and text modes fixed (Volker) - use the start address when calculating the byte offset for standard EGA/VGA modes (Volker) - byte offset for modeX fixed (use value of CRT register 0x13) (Volker) - text mode memory mappings 0 and 1 support (Christophe) - fix bug [ 612741 ] VBE mem conflicts w/ local APIC address (Jeroen) - fix bug #635223: VGA tiles array access out of bounds (Bryce) - ROM BIOS - improve compile process. Now bioses for 1, 2, 4 and 8 processors are built at the same time (Bryce) - fixes to be able to compile the bios with gcc2 or gcc3 (Jeroen and Christophe) - changes on boot signature check (Christophe): - never done for cdroms - always done for hard-disks - conditional for floppies - add keyboard int16 functions 0x09 (get keyboard functionality) and 0x0a (get keyboard id) (Christophe) - fix bug [ 629810 ] int 16/ah=01 broken? Enable interrupt on entering int16 handler (Christophe) - new keyboard init in POST (patch from Adam Sulmicki) - flush input and output keyboard buffer before keyboard self test (Volker and Christophe) - fix bug [ 547603 ] kbd up/down arrows in dos install (Christophe) - fix bug [ 549815 ] bios wrongly loads CS,ES. CS and ES are set to 0 before the bootloader code is called. (Christophe) - PCI functions support (Volker) : - BIOS32 service directory - real mode PCI int1a functions - protected mode PCI int1a functions - fix reset for MS-DOS and Win95 (Volker) - 360K floppy support (Volker) - enhanced ata/atapi support (Christophe) : - 4 channels / 8 devices - device auto detection (with help from Adam Sulmicki) - EDD3.0 - 32bits device access - optional disk translation "large", "r-echs" or "lba" (up to 8.4GiB) - re-enable harddisk controller interrupt after reads/writes. Win95 can now use native access to harddisks and cdroms. (Volker) - shutdown status handling (cmos index 0x0f) (Christophe) : - fix bug [ 601166 ] CMOS Problem @ "0x0F Index 0x05 data". After reset execution will resume by a jump to [0x40:0x67] if the shutdown status is 5 - the bios don't panic any more if the shutdown status is 9 - two parallel ports detection in POST (Volker) - two serial ports detection in POST (Volker) - add int15 extended memory function 0xe820 (patch from osmaker) and 0xe801 (patch from Hartmut Birr) - fix return values on some int15 functions (Bryce) - fix int70 handler overlapping int08 handler (Christophe) - simplify 8 processors BIOS for operating systems which don't do paranoia/sanity checks (Zwane) - configuration interface - wxWindows config interface now allows you to change every bochsrc option using menus and dialog boxes. There is also the beginning of a wxWindows graphical debugger, but it needs a lot of work before it will be useful. - renamed control.cc to textconfig.cc. Now we're calling it a text configuration interface, instead of a control panel. - display libraries - Even though we've had them for years, the term "display library" is new in release 2.0. In the gui directory, Bochs has a number of different C++ files which you can select to display the text and graphics on the simulated monitor. Each of these is a display library. The display libraries are: x use X windows interface, cross platform win32 use native win32 libraries carbon use Carbon library (for MacOS X) beos use native BeOS libraries macintosh use MacOS pre-10 amigaos use native AmigaOS libraries sdl use SDL library, cross platform svga use SVGALIB library for Linux, allows graphics without X term text only, uses curses/ncurses library, cross platform rfb provides an interface to AT&T's VNC viewer, cross platform wx use wxWindows library, cross platform nogui no display at all - it is now possible to compile Bochs with support for many different display libraries and select the one to use at runtime (even without plugins). See the display_library directive in .bochsrc. - add new svgalib display library by Igor Popik - fix bug [ 614724 ] SDL can get stuck in full screen mode display libraries such as SDL which have a full screen mode can be dangerous, if Bochs does not switch back to normal display mode at the right time. This is fixed for SDL and the new svga. - keymap support added in SDL interface (Bryce, Volker) - new keymap files: SDL keymaps for US and DE keyboards, X11 keymap for Danish keyboard. - use keyboard mapping for keyup messages too - renamed almost all references to data type "Boolean" to "bx_bool". The Boolean data type was defined in Carbon.h headers, and conflicted with Bochs's definition. See bug [ 618388 ] Unable to boot under MacOS X Exceptions: When talking to the Carbon library, you must use Boolean. Also, siminterface.h uses standard "bool" instead of bx_bool. - "User" button added in toolbar. It can send keyboard shortcuts to the guest OS. (Volker) - snapshot improvement and memory leak fixed (Volker) - testing framework, based on comparing screen content, added (Greg) - term display library: - support for color terminal, function keys, clear screen (Volker) - solaris compilation problem (bug #613393) fixed (Bryce) - win32 display library: - use native win32 toolbar for headerbar, use system palette (Volker) - many Carbon interface improvements: - patch [ 549248 ] Fix Carbon key & menu handling (Chris Thomas) - partial keymap support, copy&paste, menu items fixed, new toolbar behavior, dialog box display for panics (Br'fin) - sdl display library: - keyboard fixes and key mapping added (Bryce) - when captured, the mouse is forced to stay in the window. fix bug [ 619283 ] SDL: os mouse pointer leaves the window (Bryce) - x display library: - bug [ #537593 ] vga font not being found fixed. If vga font not found, search for a font called "-*-vga-*" (Bryce) - keyboard problems fixed (Bryce, Christophe) - beos platform, any display library: add a nice icon to the executable (Bernd Korz) - wxWindows - wxWindows is a cross-platform C++ user interface library which you can download for free at http://wxwindows.org. wxWindows provides C++ classes for all sorts of GUI controls (buttons, menubars, etc.) and implements all of them using the native controls on the platform. - The new wxWindows port of Bochs provides both a graphical configuration interface (for editing bochsrc options) and a display. It was written by Bryce Denney, Don Becker, Dave Poirier, and Volker Ruppert. - In release 2.0, we concentrated on making the wxWindows port as stable and functional as the other interfaces. wxWindows provides a great toolbox that we can use to make Bochs easier to learn and use. - wxWindows supports charmap changes, keyboard mapping, cut and paste, text and graphics modes, text mode cursor size, and mouse (Volker, Bryce) - To compile Bochs with wxWindows, you should install wxWindows 2.3.3 or later. Then configure Bochs with --with-wx. - if you have multiple versions of wxWindows installed (e.g. a debug and a release version), you can set $WX_CONFIG before configuring to select between them. (Bryce) - Bochs debugger - [ 609616 ] remote GDB stub add GDB Stub support from Johan Rydberg, with bug fixes by Stu Grossman - add hooks for external debugger for win32. The external debugger that connects to Bochs is distributed in build/win32/tattam-external-debugger.zip in binary form. Turn on with --enable-external-debugger. (Peter) - add "debugger_log" option to bochsrc, which logs all debug output into a file. feature [ 629068 ] (Christophe) - debugger is now usable in fullscreen SDL and SVGA guis. It will switch back to text mode for each debug prompt (Bryce) - disassembly output cleaned up and improved (Kernel Panic, Peter Tattam, Jonathan Shapiro, Luiz Henrique Shigunov) - fix [ 628806 ] debug: x/c prints unprintable chars (Bryce) - add the beginnings of a wxWindows debugger. Not ready for mainstream use yet. CPU register display is implemented, and you can type any debugger command you want into the Debug Console window. (Bryce) - add help command (Alexander Krisak) - symbol table lookups cleaned up a bit (Bryce) - displays the address of the caught watchpoint, feature #435271 (Dave) - remove obsolete "loader" - utilities - fixed bug [ 487758 ] bximage fails on file creation >2048meg Bximage should now work up to 32gig. (Bryce) - on win32, both bximage and niclist now ask the user to press return before exiting, so that you have time to read the results before the window disappears. (Bryce) ------------------------------------------------------------------------- Changes in 1.4.1 (June 22, 2002): - now cdrom is enabled in configure, unless you specifically disable it with --disable-cdrom. (Christophe) - fix compile error in main.cc when SMP or APIC is enabled (Dave) - the runtime menu now displays 11 (continue) by default (Bryce) - initialize DMA controller before floppy and SB16 - fix DMA panic when installing win95 (Volker) - first character of the vga bitmap is blank on win32 (Volker) Before, it was incorrectly coded as a '@'. - AltGr key on European keyboards works now on win32 (Volker) - fix problem with console/serial port on Bochs exit (Volker) - enable serial port for GNU and GNU/Linux (Volker) - small documentation fixes (Volker) - remove unnecessary include statements for X11 (Volker) - italian keymap added (Emanuele Goldoni) - fix win32 ethernet frames error. It will no longer reject packets that are less than 60 bytes long. (Peter Tattam) - BIOS fixes : - win2k cd-boot (Christophe) - emm386 crash (Dave) - cs=0 at boot time (Christophe) - keyboard failure in scandisk (Dave) - fix bug in forming the 64-bit APIC base address from two 32-bit registers. A compiler warning in cpu/proc_ctrl.cc pointed this out. - fix default choice in the runtime options menu ------------------------------------------------------------------------- Changes in 1.4 (March 27, 2002): - ROM BIOS - Boot from CDROM! Christophe Bothamy added partial El Torito support in rombios.c, which allows Bochs to boot cdroms. Booting from win2k or winXP cdrom is not supported yet. The default BIOS includes El Torito functions. the boot line must say "cdrom". Example: boot: cdrom - implementation of int13 diskette function 5 (format track) (Volker) - initialisation of PIC and DMA-2 added to POST code (Volker) - configure script (Bryce Denney) - the configure script now detects your platform and provides a default GUI and the required compiler flags. All supported platforms should compile with simply "configure" and "make". - default guis by platform: - win32/windows/cygwin: win32 gui - MacOS X: carbon gui - MacOS 9 or earlier: macos gui - BeOS: beos gui - AmigaOS: amigaos gui - all other platforms: X windows gui - compile arguments supplied by configure script - win32: too many to list here; see documentation - cygwin: -mno-cygwin -DWIN32 - MacOS X: -fpascal-strings -fno-common -arch ppc -Wno-four-char-constants -Wno-unknown-pragmas -Dmacintosh - the --with-GUINAME configure option is only needed if you want to override the default GUI. This is the only way to use the Term, RFB, and SDL GUIs. - VGA - added VESA BIOS Extensions code by Jeroen Janssen (banked mode only, LFB support in patches) - vga memory read/write functions in text mode fixed - implementation of CGA mode 320*200*4 (patch from Sebastien Bechet) - VGA BIOS - updated Christophe Bothamy's LGPL VGA BIOS to version 0.3a. This consists of a bug fix for function ah=13 and VBE support by Jeroen Janssen. - networking - chipmem read/write limit fixed (Mike Lerwill) - writing a byte in 16-bit mode now possible (Mike Lerwill) - new ethertap interface for Linux, which allows Bochs to talk to the local machine and the internet (Bryce Denney) - NE2000 is now enabled by default on Win32, Cygwin, and Linux compiles in the .conf.* scripts and release binaries. - fix check for auto transmit disable, which was checking the wrong bit (Peter Tattam) - Win32 only - niclist.exe has been revised to work on more Windows versions, and it suggests a usable ne2k line (Dean Payne) - fix timeout setting so that ne2000 does not slow down the whole simulation (Don Becker) - bug fix: be able to handle multiple packets that arrive at once (Mike Lerwill) - GUI changes - cdrom button: click this to notify Bochs when you changed the CDROM (Volker) - snapshot button: saves the text on the Bochs screen into a file called snapshot.txt (Volker) - copy button: on Win32 and X windows, copy the text on the Bochs screen to the clipboard (Volker) - paste button: on Win32 and X windows, paste the characters on the clipboard into the Bochs window. This requires keyboard_mapping to be enabled. (Bryce Denney) - improved text mode cursor for Win32, X11, and SDL (Volker) - new SDL interface (Dave Poirier, debugging by Christophe, Volker, Bryce) SDL is a graphics library that has works on many platforms. This interface is experimental, and is missing a few features of the standard Bochs interfaces: extended keys (arrows, keypad). - MacOS X: add MacOS X carbonized event handlers by Jeremy Parsons - X windows: when not enough colors can be allocated, force use of private colormap (Bryce Denney) - bug #490570 fixed: OUTB set and command 0xaa encountered (Dave Poirier) - keyboard - completed keyboard emulation with the implementation of the three scancodes sets (mf1, mf2, mf3) with or without translation. This is based on Ludovic Lange's plex86 keyboard patch. (Christophe Bothamy) - added a "keyboard_type" option, that defines the answer to an "identify keybord" request to the keyboard controller. The available values are "xt","at","mf". (Christophe Bothamy) - added an optional keyboard_mapping option that enables to use your country specific keyboard with Bochs. If enabled, the keymap file must be specified in bochsrc. The available keymaps are US, German, Spanish and French for PCs running X11. Contributions are welcomed. (Christophe Bothamy) - added Windows(tm) key definitions (Volker Ruppert) - added paste button, which causes the emulated keyboard to type characters from the system clipboard. This only works when keyboard_mapping is enabled. (Bryce Denney) - cdrom - bug fix: win32 could not read a cdrom image file - eject cd support for linux (patch from Petr Stehlik) - BeOS fixes - changing cdrom media is possible now with CDROM button - sound blaster(tm) emulation (Volker) - you can use --enable-sb16=freebsd now - 16-bit DMA controller added - 16-bit mode of the SB16 implemented (output to file works) - floppy drive (Volker Ruppert) - implementation of the floppy command 'format track' - implementation of read / write operations with MT=0 - behaviour of a few floppy commands fixed - floppy reset behaviour fixed - lots of other fixes - fixed bug [ #468340 ] pic:slave: OCW3 not implemented. Now the slave PIC supports all the modes that the master PIC does, and nobody will see this message again. - serial port (by Volker Ruppert unless noted) - improved IRQ handling - now Windows 95 serial driver works correctly - fixed the return value of the MCR (loopback bit) - interrupt reasons LSR change and MSR change implemented - the number of data bits is considered when sending data - all serial port changes are tested in loopback mode only - serial port emulation fixed for FreeBSD and OpenBSD (Stu Grossman) - fix receiver poll frequency so that it doesn't slow emulation (Stu Grossman) - Bochs debugger - when tracing, print the instruction just before it is executed, instead of just after (Greg Alexander) - after a triple-fault panic, you can now return to the debugger - symmetric multiprocessor (SMP) simulation - no more panic if you read the EOI register - fixed default destination format in local APIC - fix SMP instruction tracing in bochs debugger - fix deadlock when debugger enabled and all processors HLT - MSR support added by Zwane Mwaikambo - simulation of interrupts is more accurate (Volker) - implemented edge triggered interrupt mode - added functions raise_irq() and lower_irq() - programmable interrupt timer (Greg Alexander) - fixed the PIT gate and improved the PIT printing options - experimental real-time PIT - parallel port improvements (Volker Ruppert) - bug fix: hard disk errors caused by overflowing imul in the BIOS code. Sebastian Bechet and Peter Tattam tracked it down and fixed it. - fix some memory leaks (patch from Darko Tominac) - Double-Word IO is supported for ATA devices - fix bash-specific syntax in install-x11-fonts script - print stack_return_from_v86 error only the first 100 times ------------------------------------------------------------------------- Changes in 1.3 (December 10, 2001): - networking works on Windows and Linux platforms - emulated cdrom can now read from ISO image files, on any platform. - new PIT model by Greg Alexander which is much more complete than the old one. The new PIT is used by default, but you can switch back to the old one if you configure with --disable-new-pit. (PIT = 8254 programmable interrupt timer) - new configuration menus by Bryce Denney, which allow you to change any bochsrc option using text menus, then save the configuration into a new bochsrc file for later use. You can disable the new code using configure --disable-control-panel. Also you can use the command line arguments -nocp or -nocontrolpanel. Also, there is a new "Config" button on the GUI that allows limited changes to the configuration at runtime, such as changing the floppy disk. - add docbook documentation directory in the sources under doc/docbook. The transition from HTML to docbook documentation is still in progress. - Add new log action "ask", as shown in these example bochsrc lines: panic: action=ask error: action=ask When an event occurs which is set to "ask", you get a beep and message on the text terminal that asks what you want to do. Choices are: continue, continue and disable future messages from this device, quit immediately, or segfault (where abort() function is available). If compiled with --enable-debugger, you can also choose to enter the debugger. - Parallel port emulation cleaned up by Volker Ruppert. See .bochsrc for syntax of new parport1 line in bochsrc. - PCI support improved by Volker Ruppert, including BIOS changes. Still not complete. - floppy controller returns a proper error response if you try to write a read-only disk image. For systems such as DOS that actually use the BIOS services, it was also necessary to add code in int13_diskette_function to recognize a write-protected error and return the correct error status code (AH=3, Carry Set). - the ROM BIOS now prints panic messages to the console. Thanks to Cliff Hones for his console display code. - the ROM BIOS detects nonbootable disks (Barry Allard), and prints a message on the console. Barry Allard's patch who helped with checking the boot signature. - LBA support added for hard disks. (Not tested very much.) - add dependencies to makefiles - logging code moved into a separate file, logio.cc - new option --enable-slowdown-timer, by Greg Alexander, which kicks in if Bochs simulation time starts to run faster than real time. This helps to keep the Bochs clock in sync with the real clock when the CPU is mostly idle. - new option --enable-iodebug, by Dave Poirier, which creates an I/O interface to the debugger. This lets you write software to be emulated in Bochs which can turn on instruction, register, or memory tracing using I/O accesses. - improved detection of readline in configure script - configure substitutes the version number into many files, instead of using sed in the makefile. There are still a few uses of sed remaining. - you can now use environment variables in bochsrc values. For example, diskd: file="$BOCHS_IMG/diskd.img", cyl=615, heads=6, spt=17 - configure with --prefix=PATH works now - running configure from a different directory works now, thanks to a patch from Edouard G. Parmelan - fix [ #433759 ] virtual address checks can overflow. > Bochs has been crashing in some cases when you try to access data which > overlaps the segment limit, when the segment limit is near the 32-bit > boundary. The example that came up a few times is reading/writing 4 bytes > starting at 0xffffffff when the segment limit was 0xffffffff. The > condition used to compare offset+length-1 with the limit, but > offset+length-1 was overflowing so the comparison went wrong. - cmpxchg8b patch from Michael Hohmuth - apply patch from Thomas Fitzsimmons to fix compile problems when BX_SUPPORT_PAGING and BX_USE_TLB are turned off - fix bug introduced in 1.2.1 which caused spurious exceptions. See patch #439314, Exception 1 (debug) on HALT, from thomas.petazzoni@meridon.com. - add panic in ctrl_xfer32.cc where the IRET32 implementation is broken. This only happens if you are NOT in vm8086 mode or protected mode. The intent is to warn people when they are getting bad emulation, and encourage people to report how they got to that point. - apply patch from Santiago Bazerque. See this bug report: [ #463018 ] retf not removing parameters sometimes - fix bug [ #461730 ] IRETD causes problems if NT-flag is set reported by Peter Lammich. - apply patch [ #455014 ] CR0 bug in 80486, described as: > In the register CR0, when the bit PM is enabled, the bit 4 is 0 > when should be 1. - apply patch from Mike Rieker associated with this bug report: [ #480422 ] gdt 'accessed' bit - in task_switch when it tried to ensure that the old TSS was paged in, it actually used the new TSS address, fixed. - updated the instrumentation code, and added a working example. To try it, configure --enable-instrumentation=instrument/example1. Then when you run bochs, you will get one line for each instruction PC and for each I/O access in a new file called bxevent.txt. - set a bit in the CMOS that says the processor has an FPU. This is from patch [ #455006 ] Device byte is not initialized aptly. Author did not leave their name. - add logging code to the "null ethernet" which does not require host OS support. All this does is print the outgoing packets from the guest OS. - cleanup of log functions (Todd Fries) - add BX_ERROR for every command in ATAPI-6 that bochs does not support. I still need to do add some commands from older specs that are obsolete (and not listed) in ATAPI-6. Commands that aren't in the spec will still panic. - only put 0xf into the 2nd hard disk field when the cdrom is not present. This is a patch from Volker Ruppert , who comments: "The fdisk command reports an unusable second harddisk if the cdrom is enabled. This patch helps, but I don't know if it is the right way." - make hard disk code return error codes when data is not available instead of just panicing. In particular, if the logical sector is out of bounds or the disk image cannot be read/written at the desired offset, we now abort the ATA command and return an error code. Many of the old BX_PANIC messages are turned to BX_ERROR, so they will still appear in the log, but now the device model will try to communicate this fact to the OS instead of simply giving up. - don't blindly reject odd length atapi commands. There are cases when it's really ok according to ATA-4. - for big endian machines, reversed the bit fields in interrupt_reason. This was pointed out by Nicholai Benalal. - extended keyboard improvements by Dave Poirier - major mouse patch from Dave Spring, that implements several missing mouse modes. - commit keyboard patch from David Haslam posted to mailing list, that addresses the problem of each key press printing ^@. See cvs log for details. - mouse performance fixes by Greg Alexander and Robb Main - NE2000 fixes by Frode Vatvedt Fjeld, ecelca@yahoo.com, Greg Alexander, and angelos@openbsd.org. - fix bug [ #468340 ] pic:slave: OCW3 not implemented. Some event handling code appeared in the master pic but not the slave pic. - fix compile problems in SB16 code, related to fpos_t being treated as an integer. - patch from Volker Ruppert to fix midi output file so that winamp can play it. - some cleanup of serial code by Todd Fries and Volker Ruppert, but it doesn't work yet. X Windows specific: - commit patch from David Haslam [ #455763 ] Cursor trail with DOS Edit/Minix vi - error for missing fonts now points to the documentation - new option --enable-idle-hack, by Roland Mainz, which makes Bochs more friendly toward other processes when its CPU is idle. Presently, this option is specific to X windows. Win32 specific: - now Windows 95/98/ME can read the physical cdrom (Don Becker) - The default configuration for Win32 VC++, given in .conf.win32-vcpp, now enables the NE2000 and renames all .cc files to .cpp. This keeps VC++ happy but may make it hard to use CVS. - The default configuration for Cygwin, given in .conf.win32-cygwin, now enables cdrom and SB16. - See "new docs" on the web site for compile instructions for VC++ and Cygwin. - The sources include a VC++ workspace, in addition to the old "nmake" makefile. - ethernet support (emulated NE2000 card), coded by Don Becker. This implementation requires a library called WinPCap, which you can download from http://netgroup-serv.polito.it/winpcap. - new utility called niclist.exe which lists the ID number of all your network cards (well probably you just have one). The ID be used when setting up your .bochsrc. - patch [ #466403 ] make text colors more accurate. The author did not leave his/her name. - fix GUI bug [ #452159 ] win32: mouse stuck if bochs win partly off screen Now we center the mouse periodically, whether or not the mouse has wandered outside of the window or not. - event handler recognizes the extended keycode flag - fixes for raw floppy and floppy disk images (Don Becker) Linux specific: - Ethernet (emulated NE2000 card) now works in Linux! Contributed by splite@purdue.edu. This has been tested using host OS kernel 2.2.14, and works with telnet, ftp, irc, lynx, etc. Because it is a packet filter solution, you aren't able to talk to the host machine, only to other machines on the network. - The default configuration for Linux, given in .conf.linux, now enables the NE2000 model. - RPM build process configures with --prefix=/usr so that everything is installed in /usr/bochs instead of /usr/local/bochs. - DLX Linux disk image is now installed so that only root can write it, to avoid security problems. When you run the bochs-dlx script, it creates a local copy in your home directory and then runs it. - code that determines the capacity of a cdrom now works for both ATAPI and SCSI drives (splite@purdue.edu) - applied patch from bochs@sigint.cs.purdue.edu. The comments are: > The Linux 2.4.5 CD-ROM driver sends a READ_DISC_INFO command which caused > an "unrecognized ATAPI command" panic. Looks like READ_DISC_INFO is only > recognized by CD-R and CD-RW drives, so I ignore it for now. Amiga MorphOS specific: - Bochs now compiles and works on Amiga MorphOS. Configure with --with-amigaos. For AmigaOS only, see .bochsrc for use of fullscreeen and screenmode options. The Amiga MorphsOS is written and maintained by Nicholai Benalal . - raw cdrom supported if you configure with --enable-cdrom BeOS specific: - Bochs compiles and works on BeOS. Configure with --with-beos. Bernd Thorsten Korz maintains the BeOS port. - raw cdrom supported if you configure with --enable-cdrom MacOS X specific: - Bochs now compiles and works on MacOS X. Configure with --with-carbon. Emmanuel Mailliard ported the Macintosh code to the Carbon API. - The MacOS X application is built using (gasp) mkdir, copy, and rez. Surely this is not the right way, but it works. - raw cdrom supported if you configure with --enable-cdrom RFB mode: - apply patch.rfb-mouse by MURANAKA Masaki (monaka@users.sf.net) see this source forge bug [ #457968 ] Strange mouse motion on RFB - add a retry loop in RFB code, so that if port 5900 is not available it can try 5901, etc. Bochs Debugger: - do a vga update whenever you print a debugger prompt. - added debugger command "info fpu" that prints the FPU registers. If you do "info all" you get cpu and fpu registers. - added debugger command "info ne2k" which prints all the registers of the NE2000 model - add ability to do register tracing and flag tracing (Dave Poirier). Try the trace-reg-on and trace-reg-off commands. - instruction trace now includes time ticks - fixed problems in which bochs compiled with debugger measured time differently from bochs compiled without debugger. Also when instruction trace was enabled, breakpoints and control-C did not work. Also, breakpoints at the beginning of an interrupt handler did not work. ------------------------------------------------------------------------- Changes in 1.2.1 (June 12, 2001): - more work on makefile for building RPMs - [ #432382 ] build debian packages patch add build/debian directory from Rob Lemley which allows us to make Debian packages! - optimize for speed when simulating one processor. Now 1-processor performance should be equivalent to 1.1.2. - [ #425640 ] sb16 assumes fpos_t is long int This fixes compiles of iodev/sb16.cc on linux systems with newer libraries in which fpos_t is not an integer. - [ #432488 ] SMP:assert "n_logfn < MAX_LOGFNS" fails increase MAX_LOGFNS since we ran out of them on an SMP simulation with 4 processors - changes to compile clean on cygwin: - don't use the WIN32 snprintf define for cygwin - add ssize_t definition for cygwin - only compile "struct timeval tval" if select is available on that platform. - [ #432491 ] SMP: CPUID says no APIC feature clean up inconsistent use of BX_SUPPORT_APIC and BX_APIC_SUPPORT, which caused the CPUID to report no APIC was present - [ #431025 ] --enable-external-device-models broken removed configure options for external-device-models and external-cpu-memory. These don't work and aren't going to be fixed. - [ #429448 ] configure: -lreadline when not there Now configure allows you to choose not to use readline, even if it's found on your system. - [ #428915 ] apply extended keyboard patch extended keyboard patch by Dave Poirier - [ #428626 ] if no X11 found, configure&make fails Now configure halts if X windows is selected but no X libraries are found. - updated rombios to version 1.13. This fixes several problems: - [ #430472 ] DOS HIMEM "A20 line" error This problem was apparantly caused when Bryce added a function that prints the BIOS version, and he called it too early in the boot process. Now the same function is called later, and it doesn't break the A20. - [ #431010 ] SMP structure overwritten in v1.2 SMP structures were getting overwritten by BCC-generated data, preventing SMP operating systems from detecting that other processors were available. - [ #431016 ] bios: SMP struct has wrong entry count SMP structure had the wrong entry counts - very minor doc updates (typos, replace broken link to mtools info) - quit when the user clicks the power button, even if they have disabled panics. - win32 now defaults to having mouse capture mode turned off. For new users, it would be distressing for their mouse cursor to disappear until they pressed F12. - [ #428222 ] vga font not installed added script called "install-x11-fonts" which should help people install the VGA font on X windows systems, if it isn't already there. ------------------------------------------------------------------------- Changes in 1.2 (June 3, 2001): - [ #427259 ] rombios HALT calls don't print Fixed bios/rombios.c HALT macro so that it writes the line number of the panic to the PANIC_PORT (port 0x400) and then does NOT do a halt instruction. Also changed iodev/unmapped.cc so that the line number written to PANIC_PORT is displayed as a BX_PANIC message. Because the HALT macro now triggers the normal panic behavior, it can be controlled by the bochsrc. - [ #429016 ] crash if no hard drive rombios used to call HALT macro if no hard drive was found. Now it only calls HALT if a hard drive has an illegal geometry. - [ #425388 ] include source for simple disk img tool [ #428478 ] mkimg tool creates image 1 byte too big Added bximage tool, which makes empty floppy and hard disk images. It is now included in the top level Makefile, so it will get built by default on all platforms. - [ #426036 ] eth_fbsd.cc compile problem on solaris26 added configure test so that "configure --enable-ne2000" only includes the Berkeley Packet Filter code (eth_fbsd) if the header file can be found. If you don't have BPF the ne2000 will not actually move packets, but at least it will compile clean now. - [ #428214 ] 1.2.pre1 need documentation for binaries Write windows and linux specific documentation to be installed in binary releases. - [ #429258 ] disable RESET for version 1.2 Since soft reset was not completely working, I reverted the reset patch. Now it does panics on reset instead of trying to reboot, as the old bochs versions did. - [ #428222 ] Should the linux RPM install vga font? now font/vga.pcf will be installed in the RPM package - [ #429020 ] stop renaming the BIOS!!! new BIOS changes are now in BIOS-bochs-latest, instead of a BIOS whose name changes every time we change anything! To help distinguish different BIOS versions, the BIOS now prints its RCS Id into the log file. - [ #428625 ] compile problem if SHOW_IPS is on removed extra paren that broke SHOW_IPS - [ #428219 ] PCI doesn't compile with SMF=1 - [ #429375 ] pthreads detection broken - [ #429073 ] configure: if no X11, makes bad config - [ #429229 ] install current .bochsrc in binary rels - install Tim's man pages on linux RPM - BIOS prints messages in log in case of boot failure - rewrote instructions for compiling in win32 (win32.txt) - fixed link in HTML changelog.html to point to the real sources on SF. - added missing LOG_THIS definition to gui/nogui.cc and gui/rfb.cc - added additional check for null pointer in debugger exit routine - added diskd to .bochsrc ------------------------------------------------------------------------- Changes in version 1.2-pre1 (May 25, 2001): - major cleanup of .bochsrc - major cleanup of stderr output: prints bochs version information when starting, and at the end it tries to print the message that caused bochs to quit. - two hard disk support (diskd). At present, you cannot have two hard drives and a cdrom at the same time, because there is only one IDE controller with two channels. - split hard disk support allows different partitions to be stored in different image files - two new GUI choices: term mode and RFB mode. Term is a text-only interface, and RFB creates a server that can be accessed using the AT&T VNC viewer. - now Bochs can simulate an SMP machine, if you configure with --enable-processors=N. Configuring more than one processor has a major performance impact, so the default is 1 processor. See SMP documentation for more details. - to make SMP work, bx_mem and bx_cpu have been replaced with bx_mem_array[] and bx_cpu_array[]. The cpus are referenced through the BX_CPU(n) macro and memories through the BX_MEM(n). Normal mode has one cpu and one memory, SMP mode has multiple cpu's and one memory, cosimulation mode has multiple cpus and multiple memories. - use --enable-cpu-level=6 to make Bochs claim to be a Pentium Pro. The only feature that requires CPU level 6 is apic support. - new logging system by Todd Fries, which has 4 levels of event severity (panic, error, info, debug). There are new .bochsrc options that control what action to take when a panic/error/info/debug event occurs. - now searches for .bochsrc, bochsrc, bochsrc.txt, and (on unix only) $HOME/.bochsrc. - use GNU readline library if --enable-debugger is on, as long as readline can be found on the machine - configure checks for existence strtoull and strtouq. if neither exists, Bochs uses its own implementation - applied patches from Cliff Hones to fix up the rombios. This includes many improvements, which you can list by doing "cvs log -r 1.6 bios/rombios.c" or looking at cvsweb. - added suggested geometries of larger disks to the documentation - this is the first release to have official binary packages for win32 and Linux. There is a new "make rpm" in the top-level Makefile which will create an RPM of the current bochs directory. To use this, become root and type "configure; make rpm". - applied some FreeBSD patches from Maxim Sobolev (cdrom and serial). ------------------------------------------------------------------------- Changes in version 1.1.2 (bugfix3, May 16, 2001): - updated Elpin VGA BIOS to version 2.40, and changed pointer in .bochsrc - fixed .conf.x86 script so that it uses c++ instead of egcs for C++ files - now Makefile targets that recurse into subdirectories use double colons, so that it will always recurse into subdirectories. Now a single make command should notice a modified source file in a subdir. - fixed bug in bx_panic. If BX_PANIC_IS_FATAL==0 and a (non-fatal) panic occurs, it used to call bx_atexit() and then return. It should never call bx_atexit, which starts to shut down the simulator, unless it's really going to quit! - support 2.88 MB floppy disks - since dataseghack is checked in as non-executable, invoke it with "csh dataseghack" - double fault patch from Thomas Petazzoni , sourceforge patch #423726. - removed -fno-builtin from fpu makefiles - redefine u_char, u_short, etc. in order to not conflict with system definitions of these same types. - in cdrom.cc, remove the extern "C" { } structure around some of the header files. This is no longer necessary. - do not panic on hard disk command 0x1f2 (read sector count) - in keyboard.cc: - apply Todd Fries' reset patch - recognize most of the "Grey" insert/delete/home/end/etc. keys the same as keypad keys. - removed panic on "kbd_ctrl_to_kbd(): got value of 0x??" - implement mouse command 0xf6 (set defaults) - apply Suboner@aol.com's Xwindows timing patch from http://sourceforge.net/tracker/index.php?func=detail&aid=418730&group_id=12580&atid=312580 - remove all patches from patches subdir which have already been applied. The remaining ones are under consideration but not applied. ------------------------------------------------------------------------- Changes in version 1.1.1 (bugfix2, April 9, 2001): - in soundwin.cc, arg 3 should be typecast to LPWAVEFORMATEX - in fpu_entry.c, Bryce mistyped his own initials! - in configure.in and configure, define good defaults for VC++ #define BX_64BIT_CONSTANTS_USE_LL 0 #define inline __inline #define BX_NO_EMPTY_STRUCTS 1 #define BX_NO_ATTRIBUTES 1 #define BX_HAVE_HASH_MAP 0 - in config.h.in, fixed typo in #error message ------------------------------------------------------------------------- Changes in version 1.1 (bugfix1, April 6, 2001): (FIXED, patch #414360: update copyrights) update headers. Change copyright to 2001, replace config.h.in header with the standard mandrake header that every other file uses. (FIXED, patch #414356: inlines) make macro to replace inline and static/extern keywords. Then make define the macro appropriately based on configure. (FIXED: patch #414234: macos-no-strdup) --with-macos should force HAVE_STRDUP=0. (FIXED, patch #403027: Fix mouse bugs in Linux and BSD) Linux and BSD (maybe others) cause panic in mouse code. (FIXED, patch #413851: const64bit patch) VC++ does not allow "LL" after 64-bit constant. (FIXED, patch #413859: fabs symbol conflict) fpu code contains fabs, which conflicts with math library fabs. (FIXED, patch #403004: Implement aborts on a few SET FEATURE commands...) Implement aborts on a few SET FEATURE commands for ATA. (FIXED, patch #402991: Update to iodev/vga.cc to add 3c3h read support) Implement VGA enable register, at 0x3c3. (FIXED, patch #403027: Fix mouse bugs in Linux and BSD) Mouse panic in linux/BSD: KBD: io write 0x64: command = 0xD3(write mouse outb) (FIXED, patch #414229: panic-is-fatal) Allow user to decide if panic is fatal, or just a warning (FIXED, patch #414230: sun-cdrom) Support Sun CDROM (FIXED, patch #413574: portable1) there are cases where a pointer is cast to a 32-bit int, then later cast to a pointer and dereferenced, which crashes any 64-bit machine. (FIXED, patch #413574: portable1) some machines have no snprintf or strtoull. include a replacement function when needed. (FIXED, patch #413574: portable1) Some compilers don't allow "typedef struct { } foo;" (FIXED, patch #413574: portable1) Some people don't have hash_map.h, used in dbg_main.cc. Disable this code if hash_map.h not found. (FIXED, patch #413574: portable1) Some compilers can't handle labels at the end of a block, as in void main () { /*code*/ label: } (FIXED, patch #413574: portable1) Most compilers can't handle __attribute__. Use macro to define it away. (FIXED, patch #413574: portable1) if --enable-debugger, turn on --enable-disasm too. (FIXED, patch #413574: portable1) ome compilers can't handle any chars after an #endif (FIXED, patch #413574: portable1) wrong type arg1 of bx_dbg_watch and bx_dbg_unwatch. The code in lexer.l was calling it with integers (not booleans) (FIXED, patch #413574: portable1) in fpu code, "setcc" macro was implemented with braces inside parens, which some compilers don't understand. (FIXED, patch #413574: portable1) in fpu_entry.c, FPU_load_int32 was consistently called with arg1 of type (s32 *), but should be (u32 *) (FIXED, patch #413574: portable1) comment out sigcontext structure in fpu/stubs/asm/sigcontext.h because it conflicted with sigcontext of other machines. This struct was never used by bochs anyway. (FIXED, patch #414046: portable2) move definition of missing library functions into osdep.h and osdep.cc, include contents of macutils*. (FIXED, patch #414061: win32-rawcd) CDROM drive letter for WIN32 should not be hardcoded. (FIXED, patch #414060: win32-rawfloppy) Bypass fstat when opening WIN32 raw floppy disk. (FIXED, patch #414226: pit-panic) WinME install dies with panic: bochs: panic, pit: outp(43h): comm Bh, mode 00, bcd 00 unhandled I think I had a similar problem. All three timers should support modes 0, 2, and 3. Other modes really aren't implemented. bochs-2.6/bochs.h0000644000175000017500000004261112020641507013605 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bochs.h 11370 2012-08-26 12:32:10Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // // bochs.h is the master header file for all C++ code. It includes all // the system header files needed by bochs, and also includes all the bochs // C++ header files. Because bochs.h and the files that it includes has // structure and class definitions, it cannot be called from C code. // #ifndef BX_BOCHS_H # define BX_BOCHS_H 1 #include "config.h" /* generated by configure script from config.h.in */ #ifndef __QNXNTO__ extern "C" { #endif #ifdef WIN32 // In a win32 compile (including cygwin), windows.h is required for several // files in gui and iodev. It is important to include it here in a header // file so that WIN32-specific data types can be used in fields of classes. #include #endif #include #include #include #if defined(__sun__) #undef EAX #undef ECX #undef EDX #undef EBX #undef ESP #undef EBP #undef ESI #undef EDI #undef EIP #undef CS #undef DS #undef ES #undef SS #undef FS #undef GS #endif #include #include #ifndef WIN32 # include #else # include #endif #include #if BX_WITH_MACOS # include # include # include # include #elif BX_WITH_CARBON # include # include # include /* for MAXPATHLEN */ # include # include #else # ifndef WIN32 # include # endif # include # include #endif #include #include #include #include #ifdef macintosh # define SuperDrive "[fd:]" #endif #ifndef __QNXNTO__ } #endif #include "osdep.h" /* platform dependent includes and defines */ #include "bx_debug/debug.h" #include "gui/siminterface.h" // BX_SHARE_PATH should be defined by the makefile. If not, give it // a value of NULL to avoid compile problems. #ifndef BX_SHARE_PATH #define BX_SHARE_PATH NULL #endif // prototypes int bx_begin_simulation(int argc, char *argv[]); void bx_stop_simulation(); char *bx_find_bochsrc(void); int bx_parse_cmdline(int arg, int argc, char *argv[]); int bx_read_configuration(const char *rcfile); int bx_write_configuration(const char *rcfile, int overwrite); void bx_reset_options(void); void bx_set_log_actions_by_device(bx_bool panic_flag); // special config parameter and options functions for plugins void bx_init_std_nic_options(const char *name, bx_list_c *menu); void bx_init_usb_options(const char *usb_name, const char *pname, int maxports); int bx_parse_nic_params(const char *context, const char *param, bx_list_c *base); int bx_parse_usb_port_params(const char *context, bx_bool devopt, const char *param, int maxports, bx_list_c *base); int bx_write_pci_nic_options(FILE *fp, bx_list_c *base); int bx_write_usb_options(FILE *fp, int maxports, bx_list_c *base); Bit32u crc32(const Bit8u *buf, int len); // for param-tree testing only void print_tree(bx_param_c *node, int level = 0); // // some macros to interface the CPU and memory to external environment // so that these functions can be redirected to the debugger when // needed. // #define BXRS_PARAM_SPECIAL(parent, name, maxvalue, save_handler, restore_handler) \ { \ bx_param_num_c *param = new bx_param_num_c(parent, #name, "", "", 0, maxvalue, 0); \ param->set_base(BASE_HEX); \ param->set_sr_handlers(this, save_handler, restore_handler); \ } #define BXRS_PARAM_SPECIAL64(parent, name, save_handler, restore_handler) \ BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT64U, save_handler, restore_handler) #define BXRS_PARAM_SPECIAL32(parent, name, save_handler, restore_handler) \ BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT32U, save_handler, restore_handler) #define BXRS_PARAM_SPECIAL16(parent, name, save_handler, restore_handler) \ BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT16U, save_handler, restore_handler) #define BXRS_PARAM_SPECIAL8(parent, name, save_handler, restore_handler) \ BXRS_PARAM_SPECIAL(parent, name, BX_MAX_BIT8U, save_handler, restore_handler) #define BXRS_HEX_PARAM_SIMPLE32(parent, name) \ new bx_shadow_num_c(parent, #name, (Bit32u*)&(name), BASE_HEX) #define BXRS_HEX_PARAM_SIMPLE64(parent, name) \ new bx_shadow_num_c(parent, #name, (Bit64u*)&(name), BASE_HEX) #define BXRS_HEX_PARAM_SIMPLE(parent, name) \ new bx_shadow_num_c(parent, #name, &(name), BASE_HEX) #define BXRS_HEX_PARAM_FIELD(parent, name, field) \ new bx_shadow_num_c(parent, #name, &(field), BASE_HEX) #define BXRS_DEC_PARAM_SIMPLE(parent, name) \ new bx_shadow_num_c(parent, #name, &(name), BASE_DEC) #define BXRS_DEC_PARAM_FIELD(parent, name, field) \ new bx_shadow_num_c(parent, #name, &(field), BASE_DEC) #define BXRS_PARAM_BOOL(parent, name, field) \ new bx_shadow_bool_c(parent, #name, (bx_bool*)(&(field))) // =-=-=-=-=-=-=- Normal optimized use -=-=-=-=-=-=-=-=-=-=-=-=-=-= // some pc_systems functions just redirect to the IO devices so optimize // by eliminating call here // // #define BX_INP(addr, len) bx_pc_system.inp(addr, len) // #define BX_OUTP(addr, val, len) bx_pc_system.outp(addr, val, len) #define BX_INP(addr, len) bx_devices.inp(addr, len) #define BX_OUTP(addr, val, len) bx_devices.outp(addr, val, len) #define BX_TICK1() bx_pc_system.tick1() #define BX_TICKN(n) bx_pc_system.tickn(n) #define BX_INTR bx_pc_system.INTR #define BX_SET_INTR(b) bx_pc_system.set_INTR(b) #define BX_HRQ bx_pc_system.HRQ #if BX_SUPPORT_SMP #define BX_CPU(x) (bx_cpu_array[x]) #else #define BX_CPU(x) (&bx_cpu) #endif #define BX_MEM(x) (&bx_mem) #define BX_SET_ENABLE_A20(enabled) bx_pc_system.set_enable_a20(enabled) #define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20() #if BX_SUPPORT_A20 # define A20ADDR(x) ((bx_phy_address)(x) & bx_pc_system.a20_mask) #else # define A20ADDR(x) ((bx_phy_address)(x)) #endif // you can't use static member functions on the CPU, if there are going // to be 2 cpus. Check this early on. #if BX_SUPPORT_SMP # if BX_USE_CPU_SMF # error For SMP simulation, BX_USE_CPU_SMF must be 0. # endif #endif // // Ways for the the external environment to report back information // to the debugger. // #if BX_DEBUGGER # define BX_DBG_ASYNC_INTR bx_guard.async.irq # define BX_DBG_ASYNC_DMA bx_guard.async.dma # define BX_DBG_DMA_REPORT(addr, len, what, val) \ if (bx_guard.report.dma) bx_dbg_dma_report(addr, len, what, val) # define BX_DBG_IAC_REPORT(vector, irq) \ if (bx_guard.report.irq) bx_dbg_iac_report(vector, irq) # define BX_DBG_A20_REPORT(val) \ if (bx_guard.report.a20) bx_dbg_a20_report(val) # define BX_DBG_IO_REPORT(port, size, op, val) \ if (bx_guard.report.io) bx_dbg_io_report(port, size, op, val) # define BX_DBG_LIN_MEMORY_ACCESS(cpu, lin, phy, len, pl, rw, data) \ bx_dbg_lin_memory_access(cpu, lin, phy, len, pl, rw, data) # define BX_DBG_PHY_MEMORY_ACCESS(cpu, phy, len, rw, why, data) \ bx_dbg_phy_memory_access(cpu, phy, len, rw, why, data) #else // #if BX_DEBUGGER // debugger not compiled in, use empty stubs # define BX_DBG_ASYNC_INTR 1 # define BX_DBG_ASYNC_DMA 1 # define BX_DBG_DMA_REPORT(addr, len, what, val) /* empty */ # define BX_DBG_IAC_REPORT(vector, irq) /* empty */ # define BX_DBG_A20_REPORT(val) /* empty */ # define BX_DBG_IO_REPORT(port, size, op, val) /* empty */ # define BX_DBG_LIN_MEMORY_ACCESS(cpu, lin, phy, len, pl, rw, data) /* empty */ # define BX_DBG_PHY_MEMORY_ACCESS(cpu, phy, len, rw, attr, data) /* empty */ #endif // #if BX_DEBUGGER #define MAGIC_LOGNUM 0x12345678 typedef class BOCHSAPI logfunctions { char *name; char *prefix; // values of onoff: 0=ignore, 1=report, 2=ask, 3=fatal #define ACT_IGNORE 0 #define ACT_REPORT 1 #define ACT_ASK 2 #define ACT_FATAL 3 #define N_ACT 4 int onoff[N_LOGLEV]; class iofunctions *logio; // default log actions for all devices, declared and initialized // in logio.cc. BOCHSAPI_CYGONLY static int default_onoff[N_LOGLEV]; public: logfunctions(void); logfunctions(class iofunctions *); ~logfunctions(void); void info(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void error(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void panic(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void ldebug(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3); void fatal (const char *prefix, const char *fmt, va_list ap, int exit_status); void ask (int level, const char *prefix, const char *fmt, va_list ap); void put(const char *p); void put(const char *n, const char *p); void setio(class iofunctions *); void setonoff(int loglev, int value) { assert (loglev >= 0 && loglev < N_LOGLEV); onoff[loglev] = value; } const char *get_name() const { return name; } const char *getprefix() const { return prefix; } int getonoff(int level) const { assert (level>=0 && level= 0 && loglev < N_LOGLEV); assert (action >= 0 && action < N_ACT); default_onoff[loglev] = action; } static int get_default_action(int loglev) { assert (loglev >= 0 && loglev < N_LOGLEV); return default_onoff[loglev]; } } logfunc_t; #define BX_LOGPREFIX_SIZE 51 class BOCHSAPI iofunctions { int magic; char logprefix[BX_LOGPREFIX_SIZE]; FILE *logfd; class logfunctions *log; void init(void); void flush(void); // Log Class types public: iofunctions(void); iofunctions(FILE *); iofunctions(int); iofunctions(const char *); ~iofunctions(void); void out(int level, const char *pre, const char *fmt, va_list ap); void init_log(const char *fn); void init_log(int fd); void init_log(FILE *fs); void exit_log(); void set_log_prefix(const char *prefix); int get_n_logfns() const { return n_logfn; } logfunc_t *get_logfn(int index) { return logfn_list[index]; } void add_logfn(logfunc_t *fn); void remove_logfn(logfunc_t *fn); void set_log_action(int loglevel, int action); const char *getlevel(int i) const; const char *getaction(int i) const; protected: int n_logfn; #define MAX_LOGFNS 512 logfunc_t *logfn_list[MAX_LOGFNS]; const char *logfn; }; typedef class BOCHSAPI iofunctions iofunc_t; #define SAFE_GET_IOFUNC() \ ((io==NULL)? (io=new iofunc_t("/dev/stderr")) : io) #define SAFE_GET_GENLOG() \ ((genlog==NULL)? (genlog=new logfunc_t(SAFE_GET_IOFUNC())) : genlog) #if BX_NO_LOGGING #define BX_INFO(x) #define BX_DEBUG(x) #define BX_ERROR(x) #define BX_PANIC(x) (LOG_THIS panic) x #define BX_ASSERT(x) #else #define BX_INFO(x) (LOG_THIS info) x #define BX_DEBUG(x) (LOG_THIS ldebug) x #define BX_ERROR(x) (LOG_THIS error) x #define BX_PANIC(x) (LOG_THIS panic) x #if BX_ASSERT_ENABLE #define BX_ASSERT(x) do {if (!(x)) BX_PANIC(("failed assertion \"%s\" at %s:%d\n", #x, __FILE__, __LINE__));} while (0) #else #define BX_ASSERT(x) #endif #endif BOCHSAPI extern iofunc_t *io; BOCHSAPI extern logfunc_t *genlog; #ifndef UNUSED # define UNUSED(x) ((void)x) #endif //Generic MAX and MIN Functions #define BX_MAX(a,b) ((a) > (b) ? (a) : (b)) #define BX_MIN(a,b) ((a) < (b) ? (a) : (b)) #if BX_SUPPORT_X86_64 #define FMT_ADDRX FMT_ADDRX64 #else #define FMT_ADDRX FMT_ADDRX32 #endif #if BX_PHY_ADDRESS_LONG #define FMT_PHY_ADDRX FMT_ADDRX64 #else #define FMT_PHY_ADDRX FMT_ADDRX32 #endif #define FMT_LIN_ADDRX FMT_ADDRX #if BX_GDBSTUB // defines for GDB stub void bx_gdbstub_init(void); void bx_gdbstub_break(void); int bx_gdbstub_check(unsigned int eip); #define GDBSTUB_STOP_NO_REASON (0xac0) #if BX_SUPPORT_SMP #error GDB stub was written for single processor support. If multiprocessor support is added, then we can remove this check. // The big problem is knowing which CPU gdb is referring to. In other words, // what should we put for "n" in BX_CPU(n)->dbg_xlate_linear2phy() and // BX_CPU(n)->dword.eip, etc. #endif #endif typedef struct { bx_bool interrupts; bx_bool exceptions; bx_bool print_timestamps; #if BX_DEBUGGER bx_bool magic_break_enabled; #endif #if BX_GDBSTUB bx_bool gdbstub_enabled; #endif #if BX_SUPPORT_APIC bx_bool apic; #endif #if BX_DEBUG_LINUX bx_bool linux_syscall; #endif } bx_debug_t; #if BX_SHOW_IPS BOCHSAPI_MSVCONLY void bx_show_ips_handler(void); #endif void CDECL bx_signal_handler(int signum); int bx_atexit(void); BOCHSAPI extern bx_debug_t bx_dbg; #if BX_SUPPORT_APIC // determinted by XAPIC option BOCHSAPI extern Bit32u apic_id_mask; #endif // memory access type (read/write/execute/rw) #define BX_READ 0 #define BX_WRITE 1 #define BX_EXECUTE 2 #define BX_RW 3 // types of reset #define BX_RESET_SOFTWARE 10 #define BX_RESET_HARDWARE 11 #include "memory/memory.h" #include "pc_system.h" #include "gui/gui.h" /* --- EXTERNS --- */ #if BX_GUI_SIGHANDLER extern bx_bool bx_gui_sighandler; #endif // This value controls how often each I/O device's periodic() method // gets called. The timer is set up in iodev/devices.cc. #define BX_IODEV_HANDLER_PERIOD 100 // microseconds //#define BX_IODEV_HANDLER_PERIOD 10 // microseconds #define BX_PATHNAME_LEN 512 #define BX_KBD_XT_TYPE 0 #define BX_KBD_AT_TYPE 1 #define BX_KBD_MF_TYPE 2 #define BX_N_OPTROM_IMAGES 4 #define BX_N_OPTRAM_IMAGES 4 #define BX_N_SERIAL_PORTS 4 #define BX_N_PARALLEL_PORTS 2 #define BX_N_USB_UHCI_PORTS 2 #define BX_N_USB_OHCI_PORTS 2 #define BX_N_USB_XHCI_PORTS 4 #define BX_N_USB_HUB_PORTS 8 #define BX_N_PCI_SLOTS 5 #define BX_N_USER_PLUGINS 8 void bx_center_print(FILE *file, const char *line, unsigned maxwidth); #include "instrument.h" BX_CPP_INLINE Bit16u bx_bswap16(Bit16u val16) { return (val16<<8) | (val16>>8); } #if BX_HAVE___BUILTIN_BSWAP32 #define bx_bswap32 __builtin_bswap32 #else BX_CPP_INLINE Bit32u bx_bswap32(Bit32u val32) { val32 = ((val32<<8) & 0xFF00FF00) | ((val32>>8) & 0x00FF00FF); return (val32<<16) | (val32>>16); } #endif #if BX_HAVE___BUILTIN_BSWAP64 #define bx_bswap64 __builtin_bswap64 #else BX_CPP_INLINE Bit64u bx_bswap64(Bit64u val64) { Bit32u lo = bx_bswap32((Bit32u)(val64 >> 32)); Bit32u hi = bx_bswap32((Bit32u)(val64 & 0xFFFFFFFF)); return ((Bit64u)hi << 32) | (Bit64u)lo; } #endif // These are some convenience macros which abstract out accesses between // a variable in native byte ordering to/from guest (x86) memory, which is // always in little endian format. You must deal with alignment (if your // system cares) and endian rearranging. Don't assume anything. You could // put some platform specific asm() statements here, to make use of native // instructions to help perform these operations more efficiently than C++. #ifdef BX_LITTLE_ENDIAN #define WriteHostWordToLittleEndian(hostPtr, nativeVar16) \ *((Bit16u*)(hostPtr)) = (nativeVar16) #define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) \ *((Bit32u*)(hostPtr)) = (nativeVar32) #define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) \ *((Bit64u*)(hostPtr)) = (nativeVar64) #define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) \ (nativeVar16) = *((Bit16u*)(hostPtr)) #define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) \ (nativeVar32) = *((Bit32u*)(hostPtr)) #define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) \ (nativeVar64) = *((Bit64u*)(hostPtr)) #else #define WriteHostWordToLittleEndian(hostPtr, nativeVar16) { \ *(Bit16u *)(hostPtr) = bx_bswap16((Bit16u)(nativeVar16)); \ } #define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) { \ *(Bit32u *)(hostPtr) = bx_bswap32((Bit32u)(nativeVar32)); \ } #define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) { \ *(Bit64u *)(hostPtr) = bx_bswap64((Bit64u)(nativeVar64)); \ } #define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) { \ (nativeVar16) = bx_bswap16(*(Bit16u *)(hostPtr)); \ } #define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) { \ (nativeVar32) = bx_bswap32(*(Bit32u *)(hostPtr)); \ } #define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) { \ (nativeVar64) = bx_bswap64(*(Bit64u *)(hostPtr)); \ } #endif #define CopyHostWordLittleEndian(hostAddrDst, hostAddrSrc) \ (* (Bit16u *)(hostAddrDst)) = (* (Bit16u *)(hostAddrSrc)); #define CopyHostDWordLittleEndian(hostAddrDst, hostAddrSrc) \ (* (Bit32u *)(hostAddrDst)) = (* (Bit32u *)(hostAddrSrc)); #define CopyHostQWordLittleEndian(hostAddrDst, hostAddrSrc) \ (* (Bit64u *)(hostAddrDst)) = (* (Bit64u *)(hostAddrSrc)); #endif /* BX_BOCHS_H */ bochs-2.6/load32bitOShack.cc0000644000175000017500000002224212020641507015517 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: load32bitOShack.cc 10409 2011-06-19 05:37:30Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA #include "bochs.h" #include "param_names.h" #include "cpu/cpu.h" #include "iodev/iodev.h" #define LOG_THIS genlog-> static void bx_load_linux_hack(void); static void bx_load_null_kernel_hack(void); static Bit32u bx_load_kernel_image(char *path, Bit32u paddr); void bx_load32bitOSimagehack(void) { if (SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG) && (SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr()[0] != '\0')) { // Replay IO from log to initialize IO devices to // a reasonable state needed for the OS. This is done // in lieu of running the 16-bit BIOS to init things, // since we want to test straight 32bit stuff for // freemware. FILE *fp = fopen(SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr(), "r"); if (fp == NULL) { BX_PANIC(("could not open IO init file.")); } while (1) { unsigned len, op, port, val; int ret; ret = fscanf(fp, "%u %u %x %x\n", &len, &op, &port, &val); if (ret != 4) { BX_PANIC(("could not open IO init file.")); } if (op == 0) { // read bx_devices.inp(port, len); } else if (op == 1) { // write bx_devices.outp(port, val, len); } else { BX_PANIC(("bad IO op in init filen")); } if (feof(fp)) break; } } //if iolog file to load // Invoke proper hack depending on which OS image we're loading switch (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get()) { case Load32bitOSLinux: bx_load_linux_hack(); break; case Load32bitOSNullKernel: bx_load_null_kernel_hack(); break; default: BX_PANIC(("load32bitOSImage: OS not recognized")); } } struct gdt_entry { Bit32u low; Bit32u high; }; struct linux_setup_params { /* 0x000 */ Bit8u orig_x; /* 0x001 */ Bit8u orig_y; /* 0x002 */ Bit16u memory_size_std; /* 0x004 */ Bit16u orig_video_page; /* 0x006 */ Bit8u orig_video_mode; /* 0x007 */ Bit8u orig_video_cols; /* 0x008 */ Bit16u unused1; /* 0x00a */ Bit16u orig_video_ega_bx; /* 0x00c */ Bit16u unused2; /* 0x00e */ Bit8u orig_video_lines; /* 0x00f */ Bit8u orig_video_isVGA; /* 0x010 */ Bit16u orig_video_points; /* 0x012 */ Bit8u pad1[0x40 - 0x12]; /* 0x040 */ Bit8u apm_info[0x80 - 0x40]; /* 0x080 */ Bit8u hd0_info[16]; /* 0x090 */ Bit8u hd1_info[16]; /* 0x0a0 */ Bit8u pad2[0x1e0 - 0xa0]; /* 0x1e0 */ Bit32u memory_size_ext; /* 0x1e4 */ Bit8u pad3[0x1f1 - 0x1e4]; /* 0x1f1 */ Bit8u setup_sects; /* 0x1f2 */ Bit16u mount_root_rdonly; /* 0x1f4 */ Bit16u sys_size; /* 0x1f6 */ Bit16u swap_dev; /* 0x1f8 */ Bit16u ramdisk_flags; /* 0x1fa */ Bit16u vga_mode; /* 0x1fc */ Bit16u orig_root_dev; /* 0x1fe */ Bit16u bootsect_magic; /* 0x200 */ Bit8u pad4[0x210 - 0x200]; /* 0x210 */ Bit32u loader_type; /* 0x214 */ Bit32u kernel_start; /* 0x218 */ Bit32u initrd_start; /* 0x21c */ Bit32u initrd_size; /* 0x220 */ Bit8u pad5[0x400 - 0x220]; /* 0x400 */ struct gdt_entry gdt[128]; /* 0x800 */ Bit8u commandline[2048]; }; static void bx_load_linux_setup_params(Bit32u initrd_start, Bit32u initrd_size) { struct linux_setup_params *params = (struct linux_setup_params *) BX_MEM(0)->get_vector(0x00090000); memset(params, '\0', sizeof(*params)); /* Video settings (standard VGA) */ params->orig_x = 0; params->orig_y = 0; params->orig_video_page = 0; params->orig_video_mode = 3; params->orig_video_cols = 80; params->orig_video_lines = 25; params->orig_video_points = 16; params->orig_video_isVGA = 1; params->orig_video_ega_bx = 3; /* Memory size (total mem - 1MB, in KB) */ params->memory_size_ext = (Bit32u)(BX_MEM(0)->get_memory_len()/(1024*1024) - 1) * 1024; /* Boot parameters */ params->loader_type = 1; params->bootsect_magic = 0xaa55; params->mount_root_rdonly = 0; params->orig_root_dev = 0x0100; params->initrd_start = initrd_start; params->initrd_size = initrd_size; /* Initial GDT */ params->gdt[2].high = 0x00cf9a00; params->gdt[2].low = 0x0000ffff; params->gdt[3].high = 0x00cf9200; params->gdt[3].low = 0x0000ffff; } void bx_load_linux_hack(void) { Bit32u initrd_start = 0, initrd_size = 0; // The RESET function will have been called first. // Set CPU and memory features which are assumed at this point. // Load Linux kernel image bx_load_kernel_image(SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(), 0x100000); // Load initial ramdisk image if requested char *tmpPtr = SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->getptr(); if (tmpPtr && tmpPtr[0]) /* The initial value is "" and not NULL */ { initrd_start = 0x00800000; /* FIXME: load at top of memory */ initrd_size = bx_load_kernel_image(tmpPtr, initrd_start); } // Setup Linux startup parameters buffer bx_load_linux_setup_params(initrd_start, initrd_size); // Enable A20 line BX_SET_ENABLE_A20(1); // Setup PICs the way Linux likes it BX_OUTP(0x20, 0x11, 1); BX_OUTP(0xA0, 0x11, 1); BX_OUTP(0x21, 0x20, 1); BX_OUTP(0xA1, 0x28, 1); BX_OUTP(0x21, 0x04, 1); BX_OUTP(0xA1, 0x02, 1); BX_OUTP(0x21, 0x01, 1); BX_OUTP(0xA1, 0x01, 1); BX_OUTP(0x21, 0xFF, 1); BX_OUTP(0xA1, 0xFB, 1); // Disable interrupts and NMIs BX_CPU(0)->clear_IF(); BX_OUTP(0x70, 0x80, 1); // Enter protected mode // Fixed by george (kyriazis at nvidia.com) // BX_CPU(0)->cr0.pe = 1; // BX_CPU(0)->cr0.val32 |= 0x01; if (! BX_CPU(0)->SetCR0(BX_CPU(0)->cr0.val32 | 0x01)) { BX_INFO(("bx_load_linux_hack: can't enable protected mode in CR0")); BX_EXIT(1); } // load esi with real_mode BX_CPU(0)->gen_reg[BX_32BIT_REG_ESI].dword.erx = 0x90000; // Set up initial GDT BX_CPU(0)->gdtr.limit = 0x400; BX_CPU(0)->gdtr.base = 0x00090400; // Jump to protected mode entry point BX_CPU(0)->jump_protected(NULL, 0x10, 0x100000); } void bx_load_null_kernel_hack(void) { // The RESET function will have been called first. // Set CPU and memory features which are assumed at this point. bx_load_kernel_image(SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(), 0x100000); // EIP deltas BX_CPU(0)->prev_rip = BX_CPU(0)->gen_reg[BX_32BIT_REG_EIP].dword.erx = 0x100000; // CS deltas BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.base = 0x00000000; BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // page granularity BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32bit // DS deltas BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000; BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xFFFFFFFF; BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.g = 1; // page granularity BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 1; // 32bit // CR0 deltas BX_CPU(0)->cr0.set_PE(1); // protected mode BX_CPU(0)->handleCpuModeChange(); } Bit32u bx_load_kernel_image(char *path, Bit32u paddr) { struct stat stat_buf; int fd, ret; unsigned long size, offset; Bit32u page_size; // read in ROM BIOS image file fd = open(path, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (fd < 0) { BX_INFO(("load_kernel_image: couldn't open image file '%s'.", path)); BX_EXIT(1); } ret = fstat(fd, &stat_buf); if (ret) { BX_INFO(("load_kernel_image: couldn't stat image file '%s'.", path)); BX_EXIT(1); } size = (unsigned long) stat_buf.st_size; page_size = ((Bit32u)size + 0xfff) & ~0xfff; if ((paddr + size) > BX_MEM(0)->get_memory_len()) { BX_INFO(("load_kernel_image: address range > physical memsize!")); BX_EXIT(1); } offset = 0; while (size > 0) { ret = read(fd, (bx_ptr_t) BX_MEM(0)->get_vector(paddr + offset), size); if (ret <= 0) { BX_INFO(("load_kernel_image: read failed on image")); BX_EXIT(1); } size -= ret; offset += ret; } close(fd); BX_INFO(("load_kernel_image: '%s', size=%u read into memory at %08x", path, (unsigned) stat_buf.st_size, (unsigned) paddr)); return page_size; } bochs-2.6/doc/0000755000175000017500000000000012020641457013103 5ustar guillemguillembochs-2.6/doc/man/0000755000175000017500000000000012020641457013656 5ustar guillemguillembochs-2.6/doc/man/bochs-dlx.10000644000175000017500000000334312020641457015626 0ustar guillemguillem.\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" .TH bochs-dlx 1 "29 Dec 2005" "bochs-dlx" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bochs-dlx \- Runs DLX-Linux under the Bochs x86 Emulator .\"SKIP_SECTION" .SH USAGE .B bochs-dlx .LP No command line arguments are accepted. If you require adjustments to the normal runtime parameters, edit /usr/local/share/bochs/dlxlinux/bochsrc.txt or run bochs(1) directly. .\"SKIP_SECTION" .SH DESCRIPTION .LP Bochs-dlx is a shell script that runs a sample 10Mbyte disk image of DLX Linux inside Bochs. Bochs-dlx is simple by design so that it is possible to try out Bochs without learning how to configure it first. .\"SKIP_SECTION" .SH LICENSE This program is distributed under the terms of the GNU Lesser General Public License as published by the Free Software Foundation. See the COPYING file located in /usr/local/share/doc/bochs/ for details on the license and the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: http://bochs.sourceforge.net/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochs(1), bochsrc(5), bximage(1), bxcommit(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: http://bochs.sourceforge.net Online Bochs Documentation http://bochs.sourceforge.net/doc/docbook .fi .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web site. Just go to http://bochs.sourceforge.net, and click "Bug Reports" on the sidebar under "Features." .PP Provide a detailed description of the bug, the version of the program you are running, the operating system you are running the program on and the operating system you are running in the emulator. bochs-2.6/doc/man/bxcommit.10000644000175000017500000000463512020641457015572 0ustar guillemguillem.\"Document Author: Christophe Bothamy - cbothamy@free.fr" .TH bxcommit 1 "1 Jan 2012" "bxcommit" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bxcommit \- Interactive Tool to Commit Redologs into flat Disk Images for Bochs .\"SKIP_SECTION" .SH SYNOPSIS .B bxcommit .RI \|[ options \|] .RI \|[ flat_filename \|] .RI \|[ redolog_filename \|] .\"SKIP_SECTION" .SH DESCRIPTION .LP Bxcommit is an easy to use console based tool for committing redologs into flat disk images, particularly for use with Bochs. It is completely interactive if no command line arguments are used. It can be switched to a non-interactive mode if all required parameters are given in the command line. .SH OPTIONS .LP When you run bxcommit without one of the following options, it will appear in interactive mode and ask for all required parameters to do the commit. .TP .BI \-mode=undoable commit undoable redolog to flat file .TP .BI \-mode=growing create flat disk image from growing disk image .TP .BI \-d delete redolog file after commit .TP .BI \-q quiet mode (don't prompt for user input) .TP .BI \--help display this help and exit .LP The first filename parameter specifies the name of the flat image that will be created or modified. The second one specifies the name of the redolog. .\"SKIP_SECTION" .SH LICENSE This program is distributed under the terms of the GNU Lesser General Public License as published by the Free Software Foundation. See the COPYING file located in /usr/local/share/doc/bochs/ for details on the license and the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: http://bochs.sourceforge.net/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochs(1), bochsrc(5), bochs-dlx(1), bximage(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: http://bochs.sourceforge.net Online Bochs Documentation http://bochs.sourceforge.net/doc/docbook .fi .\"SKIP_SECTION" .SH AUTHORS Bxcommit was written by Christophe Bothamy, based on Bochs bximage tool source code. .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web site. Just go to http://bochs.sourceforge.net, and click "Bug Reports" on the sidebar under "Feedback." .PP Provide a detailed description of the bug, the version of the program you are running, the operating system you are running the program on and the operating system you are running in the emulator. bochs-2.6/doc/man/bximage.10000644000175000017500000000522312020641457015356 0ustar guillemguillem.\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" .TH bximage 1 "29 Dec 2005" "bximage" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bximage \- Interactive Disk Image Creator for Bochs .\"SKIP_SECTION" .SH SYNOPSIS .B bximage .RI \|[ options \|] .RI \|[ filename \|] .\"SKIP_SECTION" .SH DESCRIPTION .LP Bximage is an easy to use console based tool for creating disk images, particularly for use with Bochs. It is completely interactive if no command line arguments are used. It can be switched to a non-interactive mode if all required parameters are given in the command line. .\".\"DONT_SPLIT" .SH OPTIONS .LP When you run bximage without one of the following options, it will appear in interactive mode and ask for all required parameters to create an image. .TP .BI \-fd Create a floppy image. .TP .BI \-hd Create a hard disk image. .TP .BI \-mode=... Image mode (for hard disks only - see the .I bochsrc sample for supported options). .TP .BI \-size=... Image size in megabytes (e.g. 1.44 for floppy image, 10 for hard disk image). .TP .BI \-q Quiet mode (don't prompt for user input). Without this option bximage uses the command line parameters as defaults for the interactive mode. If this option is given and one of the required parameters is missing, bximage will fall back to interactive mode. .TP .BI \--help Print a summary of the command line options for bximage and exit. .LP The .I filename parameter specifies the name of the image to be created. .\"SKIP_SECTION" .SH LICENSE This program is distributed under the terms of the GNU Lesser General Public License as published by the Free Software Foundation. See the COPYING file located in /usr/local/share/doc/bochs/ for details on the license and the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: http://bochs.sourceforge.net/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochs(1), bochsrc(5), bochs-dlx(1), bxcommit(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: http://bochs.sourceforge.net Online Bochs Documentation http://bochs.sourceforge.net/doc/docbook .fi .\"SKIP_SECTION" .SH AUTHORS Bximage was written by Bryce Denney, based on several similar tools from the bochs-developers list. .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web site. Just go to http://bochs.sourceforge.net, and click "Bug Reports" on the sidebar under "Feedback." .PP Provide a detailed description of the bug, the version of the program you are running, the operating system you are running the program on and the operating system you are running in the emulator. bochs-2.6/doc/man/bochs.10000644000175000017500000000642312020641457015043 0ustar guillemguillem.\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" .TH bochs 1 "29 Jul 2012" "bochs @version@" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bochs \- Portable x86 Emulator. .\"SKIP_SECTION" .SH SYNOPSIS .B bochs .RI \|[ bochs_options \|] .RI \|[ bochsrc_options \|] .\"SKIP_SECTION" .SH DESCRIPTION .LP Bochs is a portable Intel Architecture 32 (x86) emulator that runs on most popular operating systems. Inside the emulator, it can run many operating systems including Linux and Microsoft(R) Windows(R). .\".\"DONT_SPLIT" .SH OPTIONS .LP When you run bochs without one of the following options, it will search for a configuration file called .bochsrc in the current directory and your home directory and display the start menu. .TP .BI \-q With this option the start menu will be skipped after loading the configuration file. .TP .BI \-f\ configfile This option specifies the name of the configuration file. .TP .BI \-qf\ configfile When you run bochs with this option, it will skip the start menu and use the specified configuration file. .TP .BI \-n With this option bochs doesn't load a configuration file. In that case the setup for the emulation must be done with bochsrc options on the command line or in the start menu. .TP .BI \-r\ path Restore the Bochs state from path .TP .BI \-log\ filename Specify Bochs log file name .TP .BI \-h,\ --help Print a summary of the command line options for bochs and exit. .TP .BI \-h,\ --help\ features Display available features / devices and exit .TP .BI \-h,\ --help\ cpu Display supported CPU models and exit .LP You can override the settings from the configuration file with command line arguments, using the same syntax as the bochsrc file. If you have any spaces in your command line arguments, they should be enclosed in single quotes. For information on Bochs command line and configuration file arguments, see the man page .B bochsrc(5). Example: bochs -q 'boot:a' 'floppya: 1_44=a.img, status=inserted' .\"SKIP_SECTION" .SH LICENSE This program is distributed under the terms of the GNU Lesser General Public License as published by the Free Software Foundation. See the COPYING file located in /usr/local/share/doc/bochs/ for details on the license and the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: http://bochs.sourceforge.net/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochsrc(5), bochs-dlx(1), bximage(1), bxcommit(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: http://bochs.sourceforge.net Online Bochs Documentation http://bochs.sourceforge.net/doc/docbook .fi .\"SKIP_SECTION" .SH AUTHORS The Bochs emulator was created by Kevin Lawton (kevin@mandrakesoft.com), and is currently maintained by the members of the Bochs x86 Emulator Project. You can see a current roster of members at: http://bochs.sourceforge.net/getinvolved.html .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web site. Just go to http://bochs.sourceforge.net, and click "Bug Reports" on the sidebar under "Feedback". .PP Provide a detailed description of the bug, the version of the program you are running, the operating system you are running the program on and the operating system you are running in the emulator. bochs-2.6/doc/man/bochsrc.50000644000175000017500000011565412020641457015403 0ustar guillemguillem.\"Document Author: Timothy R. Butler - tbutler@uninetsolutions.com" .TH bochsrc 5 "28 Aug 2012" "bochsrc" "The Bochs Project" .\"SKIP_SECTION" .SH NAME bochsrc \- Configuration file for Bochs. .\"SKIP_SECTION" .SH DESCRIPTION .LP Bochsrc is the configuration file that specifies where Bochs should look for disk images, how the Bochs emulation layer should work, etc. The syntax used for bochsrc can also be used as command line arguments for Bochs. The .bochsrc file should be placed either in the current directory before running Bochs or in your home directory. Starting with Bochs 1.3, you can use environment variables in the bochsrc file, for example: floppya: 1_44="$IMAGES/bootdisk.img", status=inserted Starting with version 2.0, two environment variables have a built-in default value which is set at compile time. $BXSHARE points to the "share" directory which is typically /usr/local/share/bochs on UNIX machines. See the $(sharedir) variable in the Makefile for the exact value. $BXSHARE is used by disk images to locate the directory where the BIOS images and keymaps can be found. If $BXSHARE is not defined, Bochs will supply the default value. Also, $LTDL_LIBRARY_PATH points to a list of directories (separated by colons if more than one) to search in for Bochs plugins. A compile-time default is provided if this variable is not defined by the user. .\".\"DONT_SPLIT" .SH OPTIONS .TP .I "#include" This option includes another configuration file. It is possible to put installation defaults in a global config file (e.g. location of rom images). Example: #include /etc/bochsrc .TP .I "plugin_ctrl:" Controls the presence of optional device plugins. These plugins are loaded directly with this option and some of them install a config option that is only available when the plugin device is loaded. The value "1" means to load the plugin and "0" will unload it (if loaded before). These plugins will be loaded by default (if present): 'biosdev', 'extfpuirq', 'gameport', 'iodebug','parallel', 'serial', 'speaker' and 'unmapped'. These plugins are also supported, but they are usually loaded directly with their bochsrc option: 'e1000', 'es1370', 'ne2k', 'pcidev', 'pcipnic', 'sb16', 'usb_ohci', 'usb_uhci' and 'usb_xhci'. Example: plugin_ctrl: unmapped=0, e1000=1 # unload 'unmapped' and load 'e1000' .TP .I "config_interface:" The configuration interface is a series of menus or dialog boxes that allows you to change all the settings that control Bochs's behavior. Depending on the platform there are up to 3 choices of configuration interface: a text mode version called "textconfig" and two graphical versions called "win32config" and "wx". The text mode version uses stdin/stdout and is always compiled in, unless Bochs is compiled for wx only. The choice "win32config" is only available on win32 and it is the default there. The choice "wx" is only available when you use "--with-wx" on the configure command. If you do not write a config_interface line, Bochs will choose a default for you. .B NOTE: if you use the "wx" configuration interface, you must also use the "wx" display library. Example: config_interface: textconfig .TP .I "display_library:" The display library is the code that displays the Bochs VGA screen. Bochs has a selection of about 10 different display library implementations for different platforms. If you run configure with multiple --with-* options, the display_library command lets you choose which one you want to run with. If you do not write a display_library line, Bochs will choose a default for you. The choices are: x X windows interface, cross platform win32 native win32 libraries carbon Carbon library (for MacOS X) macintosh MacOS pre-10 amigaos native AmigaOS libraries sdl SDL library, cross platform term text only, uses curses/ncurses library, cross platform rfb provides an interface to AT&T's VNC viewer, cross platform wx wxWidgets library, cross platform nogui no display at all .B NOTE: if you use the "wx" configuration interface, you must also use the "wx" display library. .B Specific options: Some display libraries now support specific options to control their behaviour. These options are supported by more than one display library: "gui_debug" - use GTK debugger gui (sdl, x) "hideIPS" - disable IPS output in status bar (rfb, sdl, wx, x) "nokeyrepeat" - turn off host keyboard repeat (sdl, x) See the examples below for other currently supported options. Examples: display_library: x display_library: rfb, options="timeout=60" # time to wait for client display_library: sdl, options="fullscreen" # startup in fullscreen mode .TP .I "romimage:" The ROM BIOS controls what the PC does when it first powers on. Normally, you can use a precompiled BIOS in the source or binary distribution called .B BIOS-bochs-latest. The default ROM BIOS is usually loaded starting at address 0xe0000, and it is exactly 128k long. The legacy version of the Bochs BIOS is usually loaded starting at address 0xf0000, and it is exactly 64k long. You can also use the environment variable $BXSHARE to specify the location of the BIOS. The usage of external large BIOS images (up to 512k) at memory top is now supported, but we still recommend to use the BIOS distributed with Bochs. The start address is optional, since it can be calculated from image size. Examples: romimage: file=bios/BIOS-bochs-latest romimage: file=$BXSHARE/BIOS-bochs-legacy romimage: file=mybios.bin, address=0xfff80000 romimage: file=mybios.bin .TP .I "cpu:" This defines cpu-related parameters inside Bochs: count: Set the number of processors:cores per processor:threads per core when Bochs is compiled for SMP emulation. Bochs currently supports up to 8 processors. If Bochs is compiled without SMP support, it won't accept values different from 1. quantum: Maximum amount of instructions allowed to execute by processor before returning control to another cpu. This option exists only in Bochs binary compiled with SMP support. reset_on_triple_fault: Reset the CPU when triple fault occur (highly recommended) rather than PANIC. Remember that if you trying to continue after triple fault the simulation will be completely bogus ! cpuid_limit_winnt: Determine whether to limit maximum CPUID function to 2. This mode is required to workaround WinNT installation and boot issues. mwait_is_nop: When this option is enabled MWAIT will not put the CPU into a sleep state. This option exists only if Bochs compiled with --enable-monitor-mwait. msrs: Define path to user CPU Model Specific Registers (MSRs) specification. See example in msrs.def. ignore_bad_msrs: Ignore MSR references that Bochs does not understand; print a warning message instead of generating #GP exception. This option is enabled by default but will not be avaiable if configurable MSRs are enabled. ips: Emulated Instructions Per Second. This is the number of IPS that Bochs is capable of running on your machine. You can recompile Bochs with --enable-show-ips option enabled, to find your workstation's capability. Measured IPS value will then be logged into your log file or status bar (if supported by the gui). IPS is used to calibrate many time-dependent events within the bochs simulation. For example, changing IPS affects the frequency of VGA updates, the duration of time before a key starts to autorepeat, and the measurement of BogoMips and other benchmarks. Example Specifications[1] Bochs Machine/Compiler Mips -------------------------------------------------------------------- 2.4.6 3.4Ghz Intel Core i7 2600 with Win7x64/g++ 4.5.2 85 to 95 Mips 2.3.7 3.2Ghz Intel Core 2 Q9770 with WinXP/g++ 3.4 50 to 55 Mips 2.3.7 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 38 to 43 Mips 2.2.6 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 21 to 25 Mips 2.2.6 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips [1] IPS measurements depend on OS and compiler configuration in addition to processor clock speed. Example: cpu: count=2, ips=10000000, msrs="msrs.def" .TP .I "cpuid:" This defines features and functionality supported by Bochs emulated CPU: mmx: Select MMX instruction set support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. apic: Select APIC configuration (LEGACY/XAPIC/XAPIC_EXT/X2APIC). This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. sep: Select SYSENTER/SYSEXIT instruction set support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. sse: Select SSE instruction set support. Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 could be selected. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. sse4a: Select AMD SSE4A instructions support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. aes: Select AES instruction set support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. movbe: Select MOVBE Intel(R) Atom instruction support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. adx: Select ADCX/ADOX instructions support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. xsave: Select XSAVE extensions support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. xsaveopt: Select XSAVEOPT instruction support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. avx: Select AVX/AVX2 instruction set support. This option exists only if Bochs compiled with --enable-avx option. avx_f16c: Select AVX float16 convert instructions support. This option exists only if Bochs compiled with --enable-avx option. avx_fma: Select AVX fused multiply add (FMA) instructions support. This option exists only if Bochs compiled with --enable-avx option. bmi: Select BMI1/BMI2 instructions support. This option exists only if Bochs compiled with --enable-avx option. fma4: Select AMD four operand FMA instructions support. This option exists only if Bochs compiled with --enable-avx option. xop: Select AMD XOP instructions support. This option exists only if Bochs compiled with --enable-avx option. tbm: Select AMD TBM instructions support. This option exists only if Bochs compiled with --enable-avx option. x86_64: Enable x85-64 and long mode support. This option exists only if Bochs compiled with x86-64 support. 1g_pages: Enable 1G page size support in long mode. This option exists only if Bochs compiled with x86-64 support. pcid: Enable Process-Context Identifiers (PCID) support in long mode. This option exists only if Bochs compiled with x86-64 support. smep: Enable Supervisor Mode Execution Protection (SMEP) support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. mwait: Select MONITOR/MWAIT instructions support. This option exists only if Bochs compiled with --enable-monitor-mwait. vmx: Select VMX extensions emulation support. This option exists only if Bochs compiled with --enable-vmx option. svm: Select AMD SVM (Secure Virtual Machine) extensions emulation support. This option exists only if Bochs compiled with --enable-svm option. family: Set family information returned by CPUID. Default family value determined by configure option --enable-cpu-level. model: Set model information returned by CPUID. Default model value is 3. stepping: Set stepping information returned by CPUID. Default stepping value is 3. vendor_string: Set the CPUID vendor string returned by CPUID(0x0). This should be a twelve-character ASCII string. brand_string: Set the CPUID vendor string returned by CPUID(0x80000002 .. 0x80000004). This should be at most a forty-eight-character ASCII string. Example: cpuid: mmx=1, sep=1, sse=sse4_2, xapic=1, aes=1, movbe=1, xsave=1 .TP .I "megs:" Set the number of Megabytes of physical memory you want to emulate. The default is 32MB, most OS's won't need more than that. The maximum amount of memory supported is 2048Mb. Example: megs: 32 .TP .I "optromimage1: \fP, \fIoptromimage2: \fP, \fIoptromimage3: \fPor \fIoptromimage4:" You may now load up to 4 optional ROM images. Be sure to use a read-only area, typically between C8000 and EFFFF. These optional ROM images should not overwrite the rombios (located at F0000-FFFFF) and the videobios (located at C0000-C7FFF). Those ROM images will be initialized by the bios if they contain the right signature (0x55AA). It can also be a convenient way to upload some arbitrary code/data in the simulation, that can be retrieved by the boot loader Example: optromimage1: file=optionalrom.bin, address=0xd0000 .TP .I "vgaromimage:" You also need to load a VGA ROM BIOS into 0xC0000. Examples: vgaromimage: file=bios/VGABIOS-elpin-2.40 vgaromimage: file=bios/VGABIOS-lgpl-latest vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest .TP .I "vga:" This defines parameters related to the VGA display. extension: Here you can specify the display extension to be used. With the value 'none' you can use standard VGA with no extension. Other supported values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support. update_freq: The VGA update frequency is based on the emulated clock and the default value is 5. Keep in mind that you must tweak the 'cpu: ips=N' directive to be as close to the number of emulated instructions-per-second your workstation can do, for this to be accurate. If the realtime sync is enabled with the 'clock' option, the value is based on the real time. This parameter can be changed at runtime. Examples: vga: extension=cirrus, update_freq=10 vga: extension=vbe .TP .I "floppya: \fPor \fIfloppyb:" Point this to the pathname of a floppy image file or device. Floppya is the first drive, and floppyb is the second drive. If you're booting from a floppy, floppya should point to a bootable disk. You can set the initial status of the media to \&'ejected' or 'inserted'. Usually you will want to use 'inserted'. The parameter 'type' can be used to enable the floppy drive without media and status specified. Usually the drive type is set up based on the media type. The optional parameter 'write_protected' can be used to control the media write protect switch. By default it is turned off. Example: 2.88M 3.5" media: floppya: 2_88=path, status=ejected 1.44M 3.5" media (write protected): floppya: 1_44=path, status=inserted, write_protected=1 1.2M 5.25" media: floppyb: 1_2=path, status=ejected 720K 3.5" media: floppya: 720k=path, status=inserted 360K 5.25" media: floppya: 360k=path, status=inserted Autodetect floppy media type: floppya: image=path, status=inserted Use directory as 1.44M VFAT media: floppya: 1_44=vvfat:path, status=inserted 1.44M 3.5" floppy drive, no media: floppya: type=1_44 .TP .I "ata0: \fP, \fIata1: \fP, \fIata2: \fPor \fIata3:" These options enables up to 4 ata channels. For each channel the two base io addresses and the irq must be specified. ata0 and ata1 are enabled by default, with the values shown below. Examples: ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9 .TP .I "ata\fR[\fB0-3\fR]\fI-master: \fPor \fIata\fR[\fB0-3\fR]\fI-slave:" This defines the type and characteristics of all attached ata devices: type= type of attached device [disk|cdrom] path= path of the image mode= image mode [flat|concat|external|dll|sparse|vmware3|vmware4|undoable|growing|volatile|vpc|vvfat], only valid for disks cylinders= only valid for disks heads= only valid for disks spt= only valid for disks status= only valid for cdroms [inserted|ejected] biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos] translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto] model= string returned by identify device command journal= optional filename of the redolog for undoable, volatile and vvfat disks Point this at a hard disk image file, cdrom iso file, or a physical cdrom device. To create a hard disk image, try running bximage. It will help you choose the size and then suggest a line that works with it. In UNIX it is possible to use a raw device as a Bochs hard disk, but WE DON'T RECOMMEND IT. The path is mandatory for hard disks. Disk geometry autodetection works with images created by bximage if CHS is set to 0/0/0 (cylinders are calculated using heads=16 and spt=63). For other hard disk images and modes the cylinders, heads, and spt are mandatory. In all cases the disk size reported from the image must be exactly C*H*S*512. The mode option defines how the disk image is handled. Disks can be defined as: - flat : one file flat layout - concat : multiple files layout - external : developer's specific, through a C++ class - dll : developer's specific, through a DLL - sparse : stackable, commitable, rollbackable - vmware3 : vmware3 disk support - vmware4 : vmware4 disk support (aka VMDK) - undoable : flat file with commitable redolog - growing : growing file - volatile : flat file with volatile redolog - vpc : fixed / dynamic size VirtualPC image - vvfat: local directory appears as read-only VFAT disk (with volatile redolog) The disk translation scheme (implemented in legacy int13 bios functions, and used by older operating systems like MS-DOS), can be defined as: - none : no translation, for disks up to 528MB (1032192 sectors) - large : a standard bitshift algorithm, for disks up to 4.2GB (8257536 sectors) - rechs : a revised bitshift algorithm, using a 15 heads fake physical geometry, for disks up to 7.9GB (15482880 sectors). (don't use this unless you understand what you're doing) - lba : a standard lba-assisted algorithm, for disks up to 8.4GB (16450560 sectors) - auto : autoselection of best translation scheme. (it should be changed if system does not boot) Default values are: mode=flat, biosdetect=auto, translation=auto, model="Generic 1234" The biosdetect option has currently no effect on the bios Examples: ata0-master: type=disk, path=10M.sample, cylinders=306, heads=4, spt=17 ata0-slave: type=disk, path=20M.sample, cylinders=615, heads=4, spt=17 ata1-master: type=disk, path=30M.sample, cylinders=615, heads=6, spt=17 ata1-slave: type=disk, path=46M.sample, cylinders=940, heads=6, spt=17 ata2-master: type=disk, path=62M.sample, cylinders=940, heads=8, spt=17 ata2-slave: type=disk, path=112M.sample, cylinders=900, heads=15, spt=17 ata3-master: type=disk, path=483M.sample, cylinders=1024, heads=15, spt=63 ata3-slave: type=cdrom, path=iso.sample, status=inserted .TP .I "com1: \fP, \fIcom2: \fP, \fIcom3: \fPor \fIcom4:" This defines a serial port (UART type 16550A). In the 'term' you can specify a device to use as com1. This can be a real serial line, or a pty. To use a pty (under X/Unix), create two windows (xterms, usually). One of them will run bochs, and the other will act as com1. Find out the tty the com1 window using the `tty' command, and use that as the `dev' parameter. Then do `sleep 1000000' in the com1 window to keep the shell from messing with things, and run bochs in the other window. Serial I/O to com1 (port 0x3f8) will all go to the other window. Other serial modes are 'null' (no input/output), 'file' (output to a file specified as the 'dev' parameter), 'raw' (use the real serial port - under construction for win32) and 'mouse' (standard serial mouse - requires mouse option setting 'type=serial' or 'type=serial_wheel') Examples: com1: enabled=1, mode=term, dev=/dev/ttyp7 com2: enabled=1, mode=file, dev=serial.out com1: enabled=1, mode=mouse .TP .I "parport1: \fPor \fIparport2:" This defines a parallel (printer) port. When turned on and an output file is defined the emulated printer port sends characters printed by the guest OS into the output file. On some platforms a device filename can be used to send the data to the real parallel port (e.g. "/dev/lp0" on Linux). Examples: parport1: enabled=1, file=parport.out parport2: enabled=1, file="/dev/lp0" parport1: enabled=0 .TP .I "boot:" This defines the boot sequence. Now you can specify up to 3 boot drives, which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM). Legacy 'a' and 'c' are also supported. Example: boot: cdrom, floppy, disk .TP .I "floppy_bootsig_check:" This disables the 0xaa55 signature check on boot floppies The check is enabled by default. Example: floppy_bootsig_check: disabled=1 .TP .I "log:" Give the path of the log file you'd like Bochs debug and misc. verbiage to be written to. If you really don't want it, make it /dev/null. Example: log: bochs.out log: /dev/tty (unix only) log: /dev/null (unix only) .TP .I "logprefix:" This handles the format of the string prepended to each log line : You may use those special tokens : %t : 11 decimal digits timer tick %i : 8 hexadecimal digits of cpu0 current eip %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror) %d : 5 characters string of the device, between brackets Default : %t%e%d Examples: logprefix: %t-%e-@%i-%d logprefix: %i%e%d .TP .I "panic:" If Bochs reaches a condition where it cannot emulate correctly, it does a panic. This can be a configuration problem (like a misspelled bochsrc line) or an emulation problem (like an unsupported video mode). The "panic" setting in bochsrc tells Bochs how to respond to a panic. You can set this to fatal (terminate the session), report (print information to the console), or ignore (do nothing). The safest setting is action=fatal. If you are getting panics, you can try action=report instead. If you allow Bochs to continue after a panic, don't be surprised if you get strange behavior or crashes if a panic occurs. Please report panic messages unless it is just a configuration problem like "could not find hard drive image." Example: panic: action=fatal .TP .I "error:" Bochs produces an error message when it finds a condition that really shouldn't happen, but doesn't endanger the simulation. An example of an error might be if the emulated software produces an illegal disk command. The "error" setting tells Bochs how to respond to an error condition. You can set this to fatal (terminate the session), report (print information to the console), or ignore (do nothing). Example: error: action=report .TP .I "info:" This setting tells Bochs what to do when an event occurs that generates informational messages. You can set this to fatal (that would not be very smart though), report (print information to the console), or ignore (do nothing). For general usage, the "report" option is probably a good choice. Example: info: action=report .TP .I "debug:" This setting tells Bochs what to do with messages intended to assist in debugging. You can set this to fatal (but you shouldn't), report (print information to the console), or ignore (do nothing). You should generally set this to ignore, unless you are trying to diagnose a particular problem. .B NOTE: When action=report, Bochs may spit out thousands of debug messages per second, which can impact performance and fill up your disk. Example: debug: action=ignore .TP .I "debugger_log:" Give the path of the log file you'd like Bochs to log debugger output. If you really don't want it, make it '/dev/null', or '-'. Example: log: debugger.out log: /dev/null (unix only) log: - .TP .I "sb16:" This defines the SB16 sound emulation. It can have several of the following properties. All properties are in this format: sb16: property=value .B PROPERTIES FOR sb16: midi: The filename is where the midi data is sent. This can be a device or just a file if you want to record the midi data. midimode: 0 = No data should be output. 1 = output to device (system dependent - midi denotes the device driver). 2 = SMF file output, including headers. 3 = Output the midi data stream to the file (no midi headers and no delta times, just command and data bytes). wave: This is the device/file where wave output is stored. wavemode: 0 = no data 1 = output to device (system dependent - wave denotes the device driver). 2 = VOC file output, including headers. 3 = Output the raw wave stream to the file. log: The file to write the sb16 emulator messages to. loglevel: 0 = No log. 1 = Resource changes, midi program and bank changes. 2 = Severe errors. 3 = All errors. 4 = All errors plus all port accesses. 5 = All errors and port accesses plus a lot of extra information. It is possible to change the loglevel at runtime. dmatimer: Microseconds per second for a DMA cycle. Make it smaller to fix non-continuous sound. 750000 is usually a good value. This needs a reasonably correct setting for the IPS parameter of the CPU option. It is possible to adjust the dmatimer at runtime. Example for output to OSS: sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000 Example for output to ALSA: sb16: midimode=1, midi=alsa:128:0, wavemode=1, wave=alsa, log=sb16.log, dmatimer=600000 Example for output using SDL: sb16: wavemode=1, wave=sdl .B NOTE: The examples are wrapped onto three lines for formatting reasons, but it should all be on one line in the actual bochsrc file. .TP .I "es1370:" This defines the ES1370 sound emulation. The parameter 'enabled' controls the presence of the device. The 'wavedev' parameter is similar to the 'wave' parameter of the SB16 soundcard. The emulation supports recording and playback (except DAC1+DAC2 output at the same time). Examples: es1370: enabled=1, wavedev="" # win32 es1370: enabled=1, wavedev=alsa # Linux with ALSA es1370: enabled=1, wavedev=sdl # use SDL audio (if present) for output .TP .I "keyboard:" This defines parameters related to the emulated keyboard: type: Type of keyboard return by a "identify keyboard" command to the keyboard controller. It must be one of "xt", "at" or "mf". Defaults to "mf". It should be ok for almost everybody. A known exception is french macs, that do have a "at"-like keyboard. serial_delay: Approximate time in microseconds that it takes one character to be transferred from the keyboard to controller over the serial path. paste_delay: Approximate time in microseconds between attempts to paste characters to the keyboard controller. This leaves time for the guest os to deal with the flow of characters. The ideal setting depends on how your operating system processes characters. The default of 100000 usec (.1 seconds) was chosen because it works consistently in Windows. If your OS is losing characters during a paste, increase the paste delay until it stops losing characters. keymap: This enables a remap of a physical localized keyboard to a virtualized us keyboard, as the PC architecture expects. Examples: keyboard: type=mf, serial_delay=200, paste_delay=100000 keyboard: keymap=gui/keymaps/x11-pc-de.map .TP .I "clock:" This defines the parameters of the clock inside Bochs. sync This defines the method how to synchronize the Bochs internal time with realtime. With the value 'none' the Bochs time relies on the IPS value and no host time synchronization is used. The 'slowdown' method sacrifices performance to preserve reproducibility while allowing host time correlation. The 'realtime' method sacrifices reproducibility to preserve performance and host-time correlation. It is possible to enable both synchronization methods. time0 Specifies the start (boot) time of the virtual machine. Use a time value as returned by the time(2) system call. If no time0 value is set or if time0 equal to 1 (special case) or if time0 equal 'local', the simulation will be started at the current local host time. If time0 equal to 2 (special case) or if time0 equal 'utc', the simulation will be started at the current utc time. Syntax: clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc] Default value are sync=none, time0=local Example: clock: sync=realtime, time0=938581955 # Wed Sep 29 07:12:35 1999 .TP .I "mouse:" This defines parameters for the emulated mouse type, the initial status of the mouse capture and the runtime method to toggle it. type With the mouse type option you can select the type of mouse to emulate. The default value is 'ps2'. The other choices are 'imps2' (wheel mouse on PS/2), 'serial', 'serial_wheel' and 'serial_msys' (one com port requires setting 'mode=mouse'). To connect a mouse to an USB port, see the 'usb_uhci', 'usb_ohci' or 'usb_xhci' option (requires PCI and USB support). enabled The Bochs gui creates mouse "events" unless the 'enabled' option is set to 0. The hardware emulation itself is not disabled by this. Unless you have a particular reason for enabling the mouse by default, it is recommended that you leave it off. You can also toggle the mouse usage at runtime (RFB, SDL, Win32, wxWidgets and X11 - see below). toggle The default method to toggle the mouse capture at runtime is to press the CTRL key and the middle mouse button ('ctrl+mbutton'). This option allows to change the method to 'ctrl+f10' (like DOSBox), 'ctrl+alt' (like QEMU) or 'f12' (replaces win32 'legacyF12' option). Examples: mouse: enabled=1 mouse: type=imps2, enabled=1 mouse: type=serial, enabled=1 mouse: enabled=0, toggle=ctrl+f10 .TP .I "private_colormap:" Requests that the GUI create and use it's own non-shared colormap. This colormap will be used when in the bochs window. If not enabled, a shared colormap scheme may be used. Once again, enabled=1 turns on this feature and 0 turns it off. Example: private_colormap: enabled=1 .TP .I "pci:" This option controls the presence of a PCI chipset in Bochs. Currently it only supports the i440FX chipset. You can also specify the devices connected to PCI slots. Up to 5 slots are available. For these combined PCI/ISA devices assigning to slot is mandatory if you want to emulate the PCI model: cirrus, ne2k and pcivga. These PCI-only devices are also supported, but they are auto-assigned if you don't use the slot configuration: e1000, es1370, pcidev, pcipnic, usb_ohci and usb_xhci. Example: pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=ne2k .TP .I "pcidev:" Enables the mapping of a host PCI hardware device within the PCI subsystem of the Bochs x86 emulator. This feature requires Linux as a host OS. Example: pcidev: vendor=0x1234, device=0x5678 The vendor and device arguments should contain the vendor ID respectively the device ID of the PCI device you want to map within Bochs. .B The PCI mapping is still very experimental. .TP .I "ne2k:" Defines the characteristics of an attached ne2000 isa card : ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT, bootrom=BOOTROM .B PROPERTIES FOR ne2k: IOADDR, IRQ: You probably won't need to change ioaddr and irq, unless there are IRQ conflicts. These parameters are ignored if the NE2000 is assigned to a PCI slot. MAC: The MAC address MUST NOT match the address of any machine on the net. Also, the first byte must be an even number (bit 0 set means a multicast address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast address. For the ethertap module, you must use fe:fd:00:00:00:01. There may be other restrictions too. To be safe, just use the b0:c4... address. ETHMOD: The ethmod value defines which low level OS specific module to be used to access physical ethernet interface. Current implemented values include - fbsd : ethernet on freebsd and openbsd - linux : ethernet on linux - win32 : ethernet on win32 - tap : ethernet through a linux tap interface - tuntap : ethernet through a linux tuntap interface - slirp : ethernet backend for Slirp with builtin DHCP / TFTP servers If you don't want to make connections to any physical networks, you can use the following 'ethmod's to simulate a virtual network. - null : All packets are discarded, but logged to a few files - vde : Virtual Distributed Ethernet - vnet : ARP, ICMP-echo(ping), DHCP and TFTP are simulated The virtual host uses 192.168.10.1 DHCP assigns 192.168.10.2 to the guest The TFTP server use 'ethdev' for the root directory and doesn't overwrite files ETHDEV: The ethdev value is the name of the network interface on your host platform. On UNIX machines, you can get the name by running ifconfig. On Windows machines, you must run niclist to get the name of the ethdev. Niclist source code is in misc/niclist.c and it is included in Windows binary releases. SCRIPT: The script value is optional, and is the name of a script that is executed after bochs initialize the network interface. You can use this script to configure this network interface, or enable masquerading. This is mainly useful for the tun/tap devices that only exist during Bochs execution. The network interface name is supplied to the script as first parameter. BOOTROM: The bootrom value is optional, and is the name of the ROM image to load. Note that this feature is only implemented for the PCI version of the NE2000. Examples: ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xlo ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" ne2k: mac=b0:c4:20:00:00:01, ethmod=slirp, script=/usr/local/bin/slirp, bootrom=ne2k_pci.rom .TP .I "pcipnic:" To support the Bochs/Etherboot pseudo-NIC, Bochs must be compiled with the --enable-pnic configure option. It accepts the same syntax (for mac, ethmod, ethdev, script, bootrom) and supports the same networking modules as the NE2000 adapter. Example: pnic: enabled=1, mac=b0:c4:20:00:00:00, ethmod=vnet .TP .I "e1000:" To support the Intel(R) 82540EM Gigabit Ethernet adapter, Bochs must be compiled with the --eanble-e1000 configure option. The E1000 accepts the same syntax (for mac, ethmod, ethdev, script, bootrom) and supports the same networking modules as the NE2000 adapter. Example: e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=slirp, script=/usr/local/bin/slirp .TP .I "user_shortcut:" This defines the keyboard shortcut to be sent when you press the "user" button in the header bar. The shortcut string is a combination of maximum 3 key names (listed below) separated with a '-' character. Valid key names: "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc", "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup", "plus", "right", "shift", "space", "tab", "up", "win", "print" and "power". Example: user_shortcut: keys=ctrl-alt-del .TP .I "cmosimage:" This defines image file that can be loaded into the CMOS RAM at startup. The rtc_init parameter controls whether initialize the RTC with values stored in the image. By default the time0 argument given to the clock option is used. With 'rtc_init=image' the image is the source for the initial time. Example: cmosimage: file=cmos.img, rtc_init=time0 .TP .I "usb_uhci:" This option controls the presence of the USB root hub which is a part of the i440FX PCI chipset. With the portX option you can connect devices to the hub (currently supported: 'mouse', 'tablet', 'keypad', 'disk', 'cdrom', 'hub' and 'printer'). The optionsX parameter can be used to assign specific options to the device connected to the corresponding USB port. Currently this feature is only used to set the speed reported by device and by the 'disk' device to specify an alternative redolog file of some image modes. If you connect the mouse or tablet to one of the ports, Bochs forwards the mouse movement data to the USB device instead of the selected mouse type. When connecting the keypad to one of the ports, Bochs forwards the input of the numeric keypad to the USB device instead of the PS/2 keyboard. To connect a 'flat' mode image as an USB hardisk you can use the 'disk' device with the path to the image separated with a colon. To use other disk image modes similar to ATA disks the syntax 'disk:mode:filename' must be used (see below). To emulate an USB cdrom you can use the 'cdrom' device name and the path to an ISO image or raw device name also separated with a colon. An option to insert/eject media is available in the runtime configuration. The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is sent to a file specified in bochsrc.txt. The current code appends the PCL code to the file if the file already existed. It would probably be nice to overwrite the file instead, asking user first. Example: usb_uhci: enabled=1, port1=mouse, port2=disk:usbstick.img usb_uhci: enabled=1, port1=hub:7, port2=disk:growing:usbdisk.img usb_uhci: enabled=1, port1=printer:printdata.bin, port2=cdrom:image.iso .TP .I "usb_ohci:" This option controls the presence of the USB OHCI host controller with a 2-port hub. The portX option accepts the same device types with the same syntax as the UHCI controller (see above). Example: usb_ohci: enabled=1 .TP .I "usb_xhci:" This option controls the presence of the experimental USB xHCI host controller with a 4-port hub. The portX option accepts the same device types with the same syntax as the UHCI controller (see above). Example: usb_xhci: enabled=1 .TP .I "user_plugin:" Load user-defined plugin. This option is available only if Bochs is compiled with plugin support. Maximum 8 different plugins are supported. See the example in the Bochs sources how to write a plugin device. Example: user_plugin: name=testdev .\"SKIP_SECTION" .SH LICENSE This program is distributed under the terms of the GNU Lesser General Public License as published by the Free Software Foundation. See the LICENSE and COPYING files located in /usr/share/doc/bochs/ for details on the license and the lack of warranty. .\"SKIP_SECTION" .SH AVAILABILITY The latest version of this program can be found at: http://bochs.sourceforge.net/getcurrent.html .\"SKIP_SECTION" .SH SEE ALSO bochs(1), bochs-dlx(1), bximage(1), bxcommit(1) .PP .nf The Bochs IA-32 Emulator site on the World Wide Web: http://bochs.sourceforge.net Online Bochs Documentation http://bochs.sourceforge.net/doc/docbook .fi .\"SKIP_SECTION" .SH AUTHORS The Bochs emulator was created by Kevin Lawton (kevin@mandrakesoft.com), and is currently maintained by the members of the Bochs x86 Emulator Project. You can see a current roster of members at: http://bochs.sourceforge.net/getinvolved.html .\"SKIP_SECTION" .SH BUGS Please report all bugs to the bug tracker on our web site. Just go to http://bochs.sourceforge.net, and click "Bug Reports" on the sidebar under "Feedback". .PP Provide a detailed description of the bug, the version of the program you are running, the operating system you are running the program on and the operating system you are running in the emulator. bochs-2.6/doc/docbook/0000755000175000017500000000000012020641457014523 5ustar guillemguillembochs-2.6/doc/docbook/misc.txt0000644000175000017500000002221712020641457016223 0ustar guillemguillem$Id: misc.txt,v 1.33 2008-02-05 22:33:34 sshwarts Exp $ This is a temporary place to paste in stuff that should go into the docs one day. When it is transferred into docbook, let's remove it from misc.txt. -------------------------------------------------------------------------- -------------macintosh.txt----------------- BBD Mon Nov 25 08:23:28 EST 2002 This file has been in our main directory for years and years, and has not been updated since nobody has tried to compile for MacOS pre-10 in a long time. I didn't want to leave it sitting there since it is so incredibly obsolete. I think it would be good to put it into the documentation with proper warnings about the fact that it hasn't been updated in 4 years and may need significant hacking to make it work again. ------------------ Changes by Bryce Denney 4/5/2001: I moved the contents of macutils.h into osdep.h, and macutils.c into osdep.cc. There are functions missing on other platforms too, so I wanted to bring them all into the same place. The original macintosh.txt follows. STATUS OF THE MAC PORT: ----------------------- 23 Dec 1998 Contents: Status How to Set up MacBochs Problems Other Issues New Files Changed Files Status ------ This is an experimental Macintosh port of Bochs. The Mac port compiles fine under CodeWarrior Pro R1 (CW12) and is capable of booting Win95 in command- line mode and running DOS programs. A CodeWarrior project ("Bochs.proj") is included (you may need to edit the type and creator information with ResEdit in order for CodeWarrior to recognise it as a project file). NOTE: MacBochs is very much a "work in progress", and much of the code is incomplete. This preliminary version is being made available mainly to interested developers who may want to contribute to the development of MacBochs by contributing some code or testing it on their own Macs. If anyone can test with some "clean" Windows installer disks, it would be useful. I've been testing MacBochs with my SoftWindows HD image and disk images derived from it, and I'm not sure if the various SoftWindows-specific drivers are interfering. 23 Dec 98 - updated MacBochs to bochs-981222. The new version seems noticeably faster. Finished implementing the Bochs headerbar. Added support for ejecting floppy disks from within Bochs (click the Drive A: icon on the headerbar or press Cmd-E). 17 Dec 98 - added real floppy disk support. Also optimized the graphics screen drawing a bit more. Keyboard support still broken and in need of a major overhaul. Does anyone have experience with KCHR resources and KeyTranslate()? How to Set up MacBochs ---------------------- This is a very brief, step-by-step guide on setting up MacBochs. More detailed documentation will be available later. - Step 1. Compile the version of Bochs you want to use (PPC, 68k or FAT) or obtain a pre-compiled binary. There is a CodeWarrior project included with the source distribution. - Step 2. Create a hard disk image. Bochs ALWAYS needs a hard disk image available to it, otherwise it won't boot. To create a hard disk image on the Mac, you need to use a recent version of DiskCopy. First, create an untitled, empty folder anywhere on your Mac hard disk. Then, launch DiskCopy and choose to create a folder image of that folder. DO NOT ENTER THE DISK SIZE IN MEGABYTES. In the file "install.html" in the "docs-html" folder you will find a table of disk sizes and geometries. Make a note of the number of total SECTORS required for your desired hard disk size, as well as the cylinders, heads and sectors per track (spt). In DiskCopy, you need to choose "Custom..." from the menu of image sizes, and choose to enter the size in "blocks" (on the Mac, a block is pretty much the same as a sector). Then enter the number of total sectors you need. Make sure the image is "Read/Write", not "Read Only", and make sure you have entered the correct cyl=, heads= and spt= settings in your bochsrc file. Your image file should now be accessible to Bochs. You'll eventually need to use a utility like "fdisk" to make the image readable. - Step 3. Obtain a bootable PC floppy or floppy image. You'll need to install an operating system in order to do anything useful with Bochs. If you have installer floppies for a PC operating system (eg. Windows or MS-DOS) you can use those. Otherwise you can download disk images for FreeDOS or one of the many variants of Linux. MacBochs now supports real PC floppy disks. To use the Mac floppy drive instead of a disk image, use the special filename "[fd:]" in the appropriate line of your bochsrc. - Step 4. Set up your bochsrc file. You set up your Bochs preferences by editing the "bochsrc" file. You'll need to set up your bochsrc to work with your floppy and hard disk images, as well as telling Bochs how many megs of PC RAM you want. Problems -------- There are some so far unresolved problems in the "macintosh.cc" GUI file: - Keyboard support is VERY rudimentary; ie. it only supports alphanumerics and a couple of special keys like Enter. The keyboard-related code is full of holes and I'm going to completely rehash it. - Mouse support hasn't been tested, but probably isn't fully working either. Other Issues ------------ - The Mac port uses a ready-made config file (configmac.h), like the Win32 port used to. Macs are pretty homogeneous, so the settings should be appropriate for most machines. - The Mac port has an extra source file: "macutils.c" (with header file "macutils.h"), which is used for Mac floppy drive support, among other things. - Like the Win32 port, the Mac port expects the "bochsrc" file to be in the same directory as the Bochs application. - Be sure to use Mac pathname conventions when editing the bochsrc file (ie ':' instead of '/' or '\'). New files --------- The following are new, Mac-specific files: gui/macintosh.cc configmac.h macutils.h macutils.c Bochs.proj Changed Files ------------- The following files from the main bochs distribution have been modified to compile properly on the Mac: bochs.h main.cc memory/memory.cc memory/misc_mem.cc iodev/floppy.cc iodev/harddrv.cc The changes are just conditional compilations which won't affect other platforms (search for "#ifdef macintosh" and "#ifndef macintosh" if you want to see what the changes are). These changes will need to be integrated into the main distribution if the MacOS port is going to go ahead seriously. -- David Batterham or -------------------------------------------------------------------------- WinNT4 guest network problems From: Jeremy Wilkins To: bochs-developers@lists.sourceforge.net Subject: [Bochs-developers] Odd network errors with NT4 Guest OS I'm having trouble transferring files over the network to the guest OS (NT4 SP1). If I'm using SMB then the it errors out early on with a session cancelled. The file is 36Mb (SP6). I've tried with various file sizes, 3Meg files work, 5 meg files do not. I've also tried shuffling the files over http with similar problems, small files are fine (can browse websites) but large files just error out. The system is a 1Ghz Windows XP SP1 box with bochs 2.02, guest OS is allocated 64Mb of RAM and running Windows NT4 SP1. Any clues, anyone experiencing similar problems? -- From: didier To: Jeremy Wilkins Cc: bochs-developers@lists.sourceforge.net Subject: Re: [Bochs-developers] Odd network errors with NT4 Guest OS Did you try with a big IPS? start the guest clock applet and try to get a more or less accurate time, with 1 Ghz should be in the 50 000 000 range. IIRC NT timeout and abort before it send the whole packet. -- From: Jeremy Wilkins To: didier , bochs-developers@lists.sourceforge.net Subject: Re: [Bochs-developers] Odd network errors with NT4 Guest OS Thanks, 60 000 000 seems to have done the trick (I can copy sp6 across anyway). My original guess of 4000000 IPS was probably a bit low :) thanks again ------------------------------------------ TAP under FreeBSD Date: Fri, 14 Feb 2003 02:12:38 +0100 From: Ronald Klop To: bochs-developers at lists.sourceforge.net I've made eth_tap.cc working under FreeBSD 4.7, because the fbsd network driver didn't work for me. It's not a very clean patch, but the changes are minimal. Some notes: - I found that some of the includes aren't used at all (on FreeBSD). - The socket which is created before /dev/tap0 is opened doesn't work, because tap0 is created after opening the device. - Maybe the eth_tap device can use a configure script like the eth_tuntap device, because the device must be configured after opening. - The padding of the ethernet frame with 2 bytes isn't needed in FreeBSD. - I didn't do any work to check for this in configure, because I don't know how configure works and don't have the time work it out now. - the guest os must set (maybe this can be documented somewhere): kldload if_tap (if tap is not compiled in the kernel) ifconfig tap0 inet 10.0.1.1 netmask 255.255.255.0 sysctl net.inet.ip.forwarding=1 sysctl net.link.ether.inet.proxyall=1 -------------------------------------------------------------------------- bochs-2.6/doc/docbook/Makefile.jade0000644000175000017500000000537012020641457017072 0ustar guillemguillem################################################################### # doc/docbook/Makefile # $Id: Makefile.jade 10213 2011-02-25 15:32:08Z sshwarts $ # # Builds documentation in various formats from SGML source, and # allows easy update to the Bochs web site. # ################################################################### # name of the major documentation sections SECTIONS=user documentation development # these files get installed in addition to the sections EXTRAS=README index.html images include # complete list of what to install INSTALL_LIST=$(SECTIONS) $(EXTRAS) # ssh to this server to install the docs REMOTE_HOST=shell.sf.net # path of preexisting install in, on the remote server. Each section # will go into a subdirectory of $REMOTE_PATH, as in # $REMOTE_PATH/user. REMOTE_PATH=/home/groups/b/bo/bochs/htdocs/doc/docbook # -x means don't try to forward X authorization, it won't work for SF SSH=ssh -x # docbook defines and stuff DSSSL_ROOT=/usr/share/sgml/docbook/stylesheet/dsssl/modular/ HTML_STYLESHEET=$(DSSSL_ROOT)/html/docbook.dsl JADE=jade JADE_ARGS=-t sgml -d $(HTML_STYLESHEET) # -V nochunks SGML_VALIDATE=nsgmls -s all: all_html all_html: user/book1.html documentation/book1.html development/book1.html user/book1.html: user/user.dbk rm -f user/*.htm* export i=user; cd $$i; $(JADE) $(JADE_ARGS) $$i.dbk cp user/book1.htm user/book1.html documentation/book1.html: documentation/documentation.dbk rm -f documentation/*.htm* export i=documentation; cd $$i; $(JADE) $(JADE_ARGS) $$i.dbk cp documentation/book1.htm documentation/book1.html development/book1.html: development/development.dbk rm -f development/*.htm* export i=development; cd $$i; $(JADE) $(JADE_ARGS) $$i.dbk cp development/book1.htm development/book1.html validate:: for i in $(SECTIONS); do $(SGML_VALIDATE) $$i/$$i.dbk; done # install the stuff on the remote server using ssh. The bryce->bdenney # stuff is just because Bryce's local username and sourceforge # username don't match. If your usernames match then the "whoami" # will work ok. webinst: #all # fix tags in all html files ./fixtitles.pl `find . -name '*.htm'` ./fixtitles.pl `find . -name '*.html'` # fix permissions locally so that tar will install things right chmod 664 `find $(INSTALL_LIST) -type f -print` chmod 775 `find $(INSTALL_LIST) -type d -print` # copy to remote @echo Installing documentation on $(REMOTE_PATH) case "`whoami`" in \ bryce) sfuser=bdenney;; \ daemian) sfuser=vasudeva;; \ *) sfuser=`whoami`;; \ esac; \ tar cf - $(INSTALL_LIST) | \ $(SSH) $$sfuser@$(REMOTE_HOST) "cd $(REMOTE_PATH) && umask 002 && tar xvf -" clean: #remove generated files for S in $(SECTIONS); do \ rm -f $$S/*.htm* $$S/*.ps $$S/*.pdf $$S/*.out $$S/*.rtf $$S/*.tex $$S/*.fot; \ done ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������bochs-2.6/doc/docbook/README������������������������������������������������������������������������0000644�0001750�0001750�00000001170�12020641457�015402� 0����������������������������������������������������������������������������������������������������ustar �guillem�������������������������guillem����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������This is the base directory for the DocBook documents for the Bochs project. It has been broken down into the following directories: user - The Bochs User Guide - describes how to setup and use Bochs development - The Bochs Development Guide - contains development information and how to contribute to the Bochs project documentation - The Bochs Documentation Guide - contains information on how to contribute to the documentation of the the Bochs project images - pictures that may be reused in any of the three books. They can be referenced using "../images/FILENAME". include - files to be included from other docbook files ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������bochs-2.6/doc/docbook/index.html��������������������������������������������������������������������0000644�0001750�0001750�00000002622�12020641457�016522� 0����������������������������������������������������������������������������������������������������ustar �guillem�������������������������guillem����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> <TITLE>Bochs Documentation

Bochs Documentation

The documentation is divided into three parts:

bochs-2.6/doc/docbook/Makefile.in0000644000175000017500000000672212020641457016577 0ustar guillemguillem################################################################### # doc/docbook/Makefile # $Id: Makefile.in 10766 2011-11-06 12:11:46Z vruppert $ # # Builds documentation in various formats from SGML source, and # allows easy update to the Bochs web site. # ################################################################### prefix = @prefix@ srcdir = @srcdir@ docdir = $(prefix)/share/doc/bochs DOCBOOK2HTML = @DOCBOOK2HTML@ WGET = @WGET@ TARGZ = bochsdoc.tar.gz RENDERED_DOC_URL = http://bochs.sf.net/doc/docbook/$(TARGZ) DESTDIR= # name of the major documentation sections SECTIONS=user documentation development SECTION_HTML=$(SECTIONS:%=%/index.html) # these files get installed in addition to the sections EXTRAS=index.html images # complete list of what to install INSTALL_LIST=$(SECTIONS) $(EXTRAS) # ssh to this server to install the docs REMOTE_HOST=shell.sf.net # path of preexisting install on the remote server. Each section # will go into a subdirectory of $REMOTE_PATH, as in # $REMOTE_PATH/user. REMOTE_PATH=/home/groups/b/bo/bochs/htdocs/doc/docbook # -x means don't try to forward X authorization, it won't work for SF SSH=ssh -x all: $(SECTION_HTML) user/index.html: $(srcdir)/user/user.dbk -mkdir -p user $(DOCBOOK2HTML) -o user $(srcdir)/user/user.dbk documentation/index.html: $(srcdir)/documentation/documentation.dbk -mkdir -p documentation $(DOCBOOK2HTML) -o documentation $(srcdir)/documentation/documentation.dbk development/index.html: $(srcdir)/development/development.dbk -mkdir -p development $(DOCBOOK2HTML) -o development $(srcdir)/development/development.dbk fixperm:: # fix permissions locally so that tar will install things right chmod 664 `find $(INSTALL_LIST) -type f -print` chmod 775 `find $(INSTALL_LIST) -type d -print` copy_from_srcdir:: for i in $(EXTRAS); do if test -e $(srcdir)/$$i -a ! -e $$i; then cp -r $(srcdir)/$$i $$i; fi; done $(TARGZ): all copy_from_srcdir fixperm rm -f $(TARGZ) tar cf - --exclude=.svn --exclude=*.dbk $(INSTALL_LIST) | gzip > $(TARGZ) install: all copy_from_srcdir for i in $(DESTDIR)$(docdir); do if test ! -d $$i; then mkdir -p $$i; fi; done #for i in $(INSTALL_LIST); do cp -r $$i $(DESTDIR)$(docdir); done for i in $(INSTALL_LIST); do tar cf - --exclude=.svn --exclude=*.dbk $$i | ( cd $(DESTDIR)$(docdir); tar xf - ); done test_sfuser: @if test "$$SFUSER" = ""; then SFUSER=`whoami`; export SFUSER; fi; \ echo Your Source Forge username is $${SFUSER}. @echo 'If this is not correct, set the environment variable $$SFUSER.' # Install the stuff on the remote server using ssh. It will assume that your # local username is the same as your Source Forge username, unless you define # an environment variable SFUSER. webinst: $(TARGZ) # copy to remote @echo Installing documentation on $(REMOTE_PATH) if test "$$SFUSER" = ""; then SFUSER=`whoami`; export SFUSER; fi; \ scp $(TARGZ) $${SFUSER}@$(REMOTE_HOST):$(REMOTE_PATH); \ $(SSH) $${SFUSER}@$(REMOTE_HOST) "cd $(REMOTE_PATH) && umask 002 && gunzip -c $(TARGZ) | tar xvf -" # Download rendered docs in a TAR file from the Bochs web site using wget. # This is useful for getting documentation onto platforms that don't have # docbook tools. dl_docs:: rm -f $(TARGZ) $(WGET) $(RENDERED_DOC_URL) gunzip -c $(TARGZ) | tar xvf - touch */*.html clean: # remove generated files for S in $(SECTIONS); do \ rm -f $$S/*.html $$S/*.htm $$S/*.ps $$S/*.pdf $$S/*.out; \ done @RMCOMMAND@ $(TARGZ) dist-clean: clean rm -f Makefile bochs-2.6/doc/docbook/outline.txt0000644000175000017500000001175712020641457016756 0ustar guillemguillem--- Bryce Denney wrote: > Hi Michael, > > I added some flesh to the skeleton. I tried to keep things in approximately > the order that brand new user might need the information. It goes through > the process of: > > 1. Is this thing worth looking at? > 2. Ok, but will I be able to do X,Y,Z? > 3. Fine, I'll download it. What should I download > and how do you install? > 4. Let's see something work soon, right now, or I'm > going to erase the > whole thing. (Dlxlinux) > 5. Now how do you change the settings, try a > different disk image, make a > disk, etc. Who do I ask for help? > > If they get to #5, they are a bochs user. And > eventually... > > 6. Hey, I added USB support to talk to my scanner, > anybody want to try it? > > Here's the outline that the docbooks are organized by, basically. Title Pages Contents Bochs Users Guide Introduction to Bochs What is Bochs? portable x86 emulator, etc. Who uses Bochs? run more than one operating system without rebooting OS developers use Bochs to system software without endangering their development machine or rebooting. students use Bochs to learn about how PC hardware works hardware designers use bochs to help test new hardware Will it work for me? platforms supported (brief list) speed issues. if speed is top priority, maybe look elsewhere Licensing FAQ Installation How to get it pointer to SF web site most stable version: latest release. binaries and source available latest version by using CVS software by downloading CVS snapshot Installing a Binary For Windows, unzip into some directory. Look for DOC-win32.html for more instructions. Quick start: find dlxlinux/start.bat and double click For Unix, rpm -i bochs-.rpm. Look for /usr/local/bochs/latest/DOC-linux.html, man pages for bochs. Quick start: run bochs-dlx (in /usr/local/bin) Compiling from source Unix Run configure to make the Makefiles List of configure arguments Option of using .conf.* scripts What to report if configure fails: Tar up config.* and send to bochs-testing@tlw.com Make What to try if make fails: turn off configure options, look at SF bugs and patches section to see if it's a known problem, try to fix it yourself, if using CVS version try a release source file instead, fix it yourself Make install, what it installs and where /usr/local/bochs/$VERSION/* /usr/local/bin/bochs (and bximage) /usr/man/man1/bochs*.1 (and bximage.1) make install_dlx option How to build an RPM in Linux Instructions for win32 VC++ Getting the makefiles Download them from web site in a zip, install them on top of the source directory Run configure on a unix box, copy the Makefiles and config.h to your windows machine RUN CONFIGURE IN BOCHS! This would be awesome. Cygwin? Building it with NMAKE Installation? Maybe download an existing windows binary package and drop in your new binary. There is no make install, though this may be added some day. Instructions for cygwin? I have no idea. Setup What does Bochs need? bochsrc, BIOS, VGABIOS, VGA font, disk images. table of bochsrc options and what they do BIOS/VGABIOS, what do they do? VGA font, how to install it disk images where to find one pre-made make a blank one with bximage grab one from a real hard disk Using Bochs Resources for users bochs-developers mailing list, archive testing status page: tells what has been tried and who got it working SourceForge look for bug reports how to report problems, make feature requests Common problems and what to do about them What's a panic? How to report it to bug tracker, how to make it non-fatal. Mouse behavior, enabling and disabling Keyboard mapping problems [...] Tips and Techniques Mount disk image in loopback Using two hard disks [...] Guest operating systems Notes for different OSes Linux What disk images are available. Installing from scratch. What works Known problems OpenBSD FreeBSD FreeDOS DOS Windows * [...] Bochs Developers Guide Resources for developers All the resources for users CVS how to browse on web interface anonymous CVS (read only) write access CVS (must be officially a developer) how to make a patch using CVS SourceForge bug, feature, and patch trackers About the code cpu directory does this, iodev does that, gui does that configure script, makefiles, header files log functions: what is a panic, what is an error, etc. objects that do all the work (cpu, mem) timers Debugger compile with debugger support get started in debugger command reference techniques Coding coding conventions patches: how to make, where to submit, what happens then? life cycle of a CVS release Documentation Layout Docbook Basics Conventions Rendering Glossary Index bochs-2.6/doc/docbook/documentation/0000755000175000017500000000000012020641456017373 5ustar guillemguillembochs-2.6/doc/docbook/documentation/documentation.dbk0000644000175000017500000004554412020641456022742 0ustar guillemguillem %bochsdefs; ]> Bochs Documentation Manual BryceDenney MichaelCalabrese Layout of Bochs Documentation The Bochs documentation is divided into three major divisions: The User's Guide introduces the Bochs Emulator, and covers installation and use. Developer's Guide: Describes the internals of the Bochs Emulator for developers. Documentation Guide: Describes how the documentation is organized, and how to render it, and how to add to it. This section is in the documentation guide. In docbook terminology, each of the three divisions is a book. Inside each book are a series of chapters. A chapter may be divided into sections, and each section is divided into more sections. Eventually we will add fancy things like a table of contents, index, and glossary, when we learn how. Docbook Basics Some of the most commonly used docbook patterns are described here for quick reference. For all the details (sometimes more than you wanted), try &docbookTDG; by Norman Walsh and Leonard Muellner, which O'Reilly & Associates has generously placed on their web site. In this section, many of the SGML tags are linked to the page of Walsh's book that describes that tag in detail.
Small Tutorial Docbook files are text files containing SGML. If you have ever looked at HTML, then a docbook file will look familiar. Not the same, but familiar. The easiest way of getting familiar with the docbook format is by looking at examples such as the Bochs documentation itself. When you compare the source code to the rendered documentation on the web site, it will be pretty obvious what all the codes are doing. HTML is very forgiving about breaking the syntax rules, such as not putting </h1> at then end of an <h1> section. SGML is picky; if you forget that kind of thing in SGML, it will insist that you fix it. Every paragraph must begin with the <para> tag and end with the corresponding end tag, </para>. <para> This is a paragraph. </para> A chapter looks like this: <chapter> <title>title of the chapter</title> text of the chapter </chapter> The text of the chapter must contain at least one complete <para> tag, and it can include <section>s. A section looks like this: <section> <title>title of the section</title> text of the section </section> The text of the section must contain at least one complete <para> tag, and it can include other <section>s. To make a link to any URL, use the syntax: <ulink url="URL">text of the hyperlink</ulink> However, if you like to link to another target inside the same document, for example to a section, use something like that: <section id="unique identifier"> All stuff that is needed here... </section> ... <link linkend="unique identifier to link to">text of hyperlink</link> To include a picture in the text, use the <graphic> tag. In SGML, this graphic tag has no closing tag. <graphic format="fmt" fileref="filename"> The fmt can be one of many formats including GIF, JPG, PNG, PS, and EPS. The filename should be on the local disk. If there is a pathname, it should be relative to the source file or it won't be found on anyone's system other than yours. There are over 300 tags defined in the latest version of docbook, so we won't try to list them all here. Once you get the idea, you can either find examples in the rest of the documentation that do what you need, or look at Walsh and Muellner's DocBook: The Definitive Guide for more details.
References and Other Tutorials Docbook was created more than 10 years ago, but since 1999, Docbook has been under the guidance of the DocBook Technical Committee at OASIS. The OASIS website distributes the official DocBook DTDs, and has pages on Docbook history, samples, tools, and runs a few docbook mailing lists. Since the Linux Documentation Project uses docbook, they have written some good tutorial material. In particular the LDP Author Guide, by Jorge Godoy is very good. O'Reilly & Associates publishes a book called DocBook: The Definitive Guide by Norman Walsh and Leonard Muellner. You can buy it or read it online. Norman Walsh knows what he's talking about, since he is the chair of the DocBook Technical Committee. This is good for reference, since it has a complete list of tags and their grammar. DocBook HOWTO, also by Jorge Godoy An article on lwn.net called Exploring SGML Docbook focuses mostly on installation of tools from scratch: openjade, Norman Walsh's DSSSL stylesheets, and jade2tex. If you can get the tools from RPMs or whatever package your OS uses, use that instead.
Conventions Put a &FIXME; near things that need to be fixed up. A &FIXME; causes the under construction symbol to appear, like this &FIXME;. A &NEEDHELP; indicates, that you need someone's help in order to document something, you don't know for sure. This is mostly the case if you need inside information from a developer. The symbol looks like this: &NEEDHELP;. Don't get confused because &FIXME; looks the same as &NEEDHELP; - this is just for the moment. When you like to use one of them, think of what it should mean, instead of how it looks like: Take &FIXME; if you have great ideas of what to document, but have no time or no knowledge about it, or just noticed something wrong or outdated. &NEEDHELP; instead should be used to request help on something (see above). This is just a first try to clearify the difference between &NEEDHELP; and &FIXME;. To maintain a consistent spelling, some "problem words" are mentioned here, along with a hint on how to spell them. list of problem words Bochs Bochs is written with a leading capital letter. bochsrc This is what the Bochs configuration file should be refered as. It is a good compromise between what is common on Unix and what is possible on Windows (file names starting with a dot aren't easy to create). Remember to use <filename>bochsrc</filename>. CD-ROM This abbreviation is written in all capital letters, with a hyphen in between. Unix Unix is written using a leading capital letter, followed by all lower-case letters. See the Unix entry in Wikipedia.
&FIXME; SGML docbook...lower case elements...indentation...remarks...master document/include files
Reading and Writing The DocBook source code -- user.dbk, for example -- is a plain text file that can be directly edited and saved with any text editor such as emacs or vi. If you just want to read the documentation, you should not need to read and understand this section, and render the docs yourself. The &bochswebsite; has all this information in readable form already. To render DocBook source code into the nice readable form the end-user will require, several tools are needed. These tools allow the .dbk file to be rendered into such formats as HTML, PDF, and PostScript. This section describes the tools you need and the steps you take to render the Bochs documentation. The rendering process is one-way. That is, the DocBook source files will be downloaded from SVN, edited, and uploaded to SVN as .dbk files. Along the way, it will probably be necessary to render them into HTML, but only to check one's work or to post them as part of a web page. (I hope I'm not the only person to spend nine minutes trying to figure out how to 'compile' HTML into DocBook format.) Jade and DSSSL Here is what the Linux Documentation Project says about jade:
LDP author's guide Jade is the front-end processor for SGML and XML. It uses the DSSSL and DocBook DTD to perform the verification and rendering from SGML and XML into the target format.
What does all this mean? For purposes of Bochs documentation, jade reads the docbook source file and writes out a HTML/PDF/PS file. Bochs documentation is in SGML format, though apparantly jade can handle XML Docbooks as well. DSSSL stands for Document Style Semantics and Specification Language, and it tells jade how to translate the docbook tags into the target format. DSSSL files are written in the Scheme programming language, which is a variant of LISP. Learn more about DSSSL at Jim Clark's DSSSL page. The DocBook DTD is the formal description of what elements and attributes can be used in a docbook. Installation The easiest way to get jade working in Linux is to install packages. The recent RedHat, Suse, and Mandrake Linux distributions all include openjade and SGML tools. If you can get the right packages installed, you may save yourself a few hours of compiling and configuring from scratch. For plex86, which also uses docbook, Kevin Lawton listed the packages that he installed on Mandrake to get jade working: jadetex-3.5-2mdk openjade-1.3-10mdk docbook-dtd31-sgml-1.0-3mdk docbook-utils-0.6-1mdk docbook-style-dsssl-1.62-4mdk docbook-dtd412-xml-1.0-3mdk sgml-common-0.2-4mdk xml-common-0.1-3mdk Under Debian, the following packages seem to be a bare minimum to install DocBook and get it to render Bochs documentation into reader-friendly formats: jade docbook docbook-dsssl It's worth mentioning that, at the time of this writing, at least some of the above-mentioned packages were in the testing or unstable branches of Debian. Under FreeBSD, just install the following ports: textproc/jade textproc/dsssl-docbook-modular textproc/docbook-410 Hopefully, the required packages on other Linux distributions have similar names. If you have jade working, please tell a documentation writer the package names that you used so that we can include it in the docs. &NEEDHELP; If you cannot get jade to work using packages, you need to find and install three things: the DocBook DTD version 4.1 from &OASIS;, the program jade (or openjade), and the Docbook DSSSL stylesheets for the formats that you want to render to. The whole process is described in &docbookTDG; in Appendix III section A. If you want to render to PostScript or Adobe PDF, you also need to install TeX and and some associated tools. It is a nontrivial process. Just use the packages. For now, building the Bochs documentation also depends on some scripts called docbook2html, docbook2pdf, and docbook2ps. These come from the docbook-tools project at http://sources.redhat.com/docbook-tools. Using jade with docbook2x scripts Check to see if you have the docbook2ps, docbook2pdf, and docbook2html scripts. If so, you can probably use the Bochs Makefile. Just do cd $BOCHS/doc/docbook make It should render three docbook books, one in user, one in development, and one in and documentation. If there are no errors, look for the user guide in $BOCHS/doc/docbook/user/user.pdf, $BOCHS/doc/docbook/users/user.ps, and $BOCHS/doc/docbook/users/book1.html. The HTML is broken into lots of little chunks that link to each other, but book1.html is the first one. Using jade directly If you don't have docbook2format scripts, you can also run jade manually. The command is long, so you may want to make your own script or edit your copy of the makefile. These commands assume that you installed Norman Walsh's DSSSL stylesheets in $DSSSL. To render the user's guide into HTML, type: cd $BOCHS/doc/docbook/user jade -t sgml -d $DSSSL/html/docbook.dsl user.dbk Or, if you want to render the developer's guide into TeX format, cd $BOCHS/doc/docbook/developer jade -t tex -d $DSSSL/print/docbook.dsl developer.dbk Or, if you want to render the documentation guide into Rich Text Format, cd $BOCHS/doc/docbook/documentation jade -t rtf -d $DSSSL/print/docbook.dsl documentation.dbk I believe that the HTML stylesheet must have "-t sgml" but the print stylesheet in the second example can have "-t rtf" for Rich Text Format, "-t tex" for TeX, or "-t mif" for MIF. Bochs has the convention of calling the docbook files name.dbk, but any file name would work. Some other people call them NAME.sgm for SGML. Configuration If the generated HTML files do not have the same names as the Bochs documentation on the web, some kind of configuration is required. You need to edit the DSL file to make sure the following settings are used. (define %root-filename% "index") ;; name for the root html file (define %html-ext% ".html") ;; default extension for html output files (define %html-prefix% "") ;; prefix for all filenames generated (except root) (define %use-id-as-filename% #t) ;; if #t uses ID value, if present, as filename ;; otherwise a code is used to indicate level ;; of chunk, and general element number ;; (nth element in the document) (define use-output-dir #f) ;; output in separate directory? If you like to have the screen sections shaded, this setting should help. (define %shade-verbatim% #t)
Nsgmls The Bochs documentation is written in SGML docbook style, so any tool which can check SGML syntax can be used to check the docbook. The DTD (data type description) for docbook tells exactly which elements can be used and where. It says which attributes are required and which are optional, and how elements should be nested. The term "validate" has a specific meaning in SGML. When you validate a SGML document, it means that you read the DTD and then check that the document conforms to all the rules of the DTD. A program called nsgmls, written by James Clark jjc@jclark.com, can validate an SGML document such as our docbook. Although nsgmls can do many other things, this command will validate the docbook against the DTD which defines the syntax: nsgmls -s filename Nsgmls is part of SP, a "free object-oriented toolkit for SGML parsing and entity management" by James Clark jjc@jclark.com. SP can be found at http://www.jclark.com/sp. There is a complete man page for nsgmls here.
bochs-2.6/doc/docbook/development/0000755000175000017500000000000012020641455017043 5ustar guillemguillembochs-2.6/doc/docbook/development/development.dbk0000644000175000017500000024244612020641455022063 0ustar guillemguillem %bochsdefs; ]> Bochs Developers Guide KevinLawton BryceDenney ChristopheBothamy MichaelCalabrese Resources for developers The development guide describes resources that are intended for developers in particular. Many Bochs resources are also covered in the User Guide, including compile instructions, bochsrc options, how to find the mailing lists, etc.
Setting up SVN write access If you are an official SourceForge developer, then you can use SVN with write access. The SVN contains the most recent copy of the source code, and with write access you can upload any changes you make to the SVN server for others to use. The SVN checkout command is identical to the one for normal users, but you might want to get the whole tree to work with branches and tags. svn co https://bochs.svn.sourceforge.net/svnroot/bochs bochs-svn Depending on your network connection this may take a long time, since it downloads all files from all branches and tags that ever have been created.
Using SVN write access
Checking in files Once you have a Bochs directory, you can compile the files, edit them, test them, etc. See the documentation section, Tracking the source code with SVN for more info on SVN, in the User Manual. But what's new and different is that you can now do SVN commits. When a file is all fixed and ready to share with the rest of the world, you run a commit command to upload your version to the server. First, it's good to do a SVN update to make sure nobody else has changed it since you downloaded it last. At the first commit you'll always have to specify your SF username and type your password. $ svn update file.cc $ svn commit --username sfusername file.cc [editor opens. type log message, save, and exit.] Login area: <https://bochs.svn.sourceforge.net:443> SourceForge Subversion area Username: sfusername Password for 'sfusername': <--type your password Sending file.cc Transmitting file data . Committed revision 10. When SVN starts an editor, The default is usually vi. If you want a different editor, set the EDITOR environment variable to the name of your preferred editor. When you're done, just save the file and quit the editor. Unless there's some problem, you will see a message that says what the new revision number for the file is, and then "done". If while you're editing the log message, you decide that you don't want to commit after all, don't save the file. Quit the editor, and when it asks where the log message went, tell it to abort. Here is an example of a successful checkin: $ svn commit misc.txt [edit log msg] Sending misc.txt Transmitting file data . Committed revision 6. And here is an aborted one: $ svn commit misc.txt [quit editor without saving] Log message unchanged or not specified a)bort, c)ontinue, e)dit: a
SourceForge bug, feature, and patch trackers &FIXME;
Ideas for other sections Ideas: - how to browse code with viewvc - how to find an identifier, variable, or specific text in the code - how to make patches with SVN
About the code
Overview The initial versions of some sections in this chapter are based on a document written by Peter "Firefly" Lund. It was added and updated in January 2006. The Bochs virtual PC consists of many pieces of hardware. At a bare minimum there are always a CPU, a PIT (Programmable Interval Timer), a PIC (Programmable Interrupt Controller), a DMA controller, some memory (this includes both RAM and BIOS ROMs), a video card (usually VGA), a keyboard port (also handles the mouse), an RTC with battery backed NVRAM, and some extra motherboard circuitry. There might also be a NE2K ethernet card, a PCI controller, a Sound Blaster 16, an IDE controller (+ harddisks/CDROM), a SCSI controller (+ harddisks), a floppy controller, an APIC .. There may also be more than one CPU. Most of these pieces of hardware have their own C++ class - and if Bochs is configured to have more than one piece of a type of hardware, each will have its own object. The pieces of hardware communicates over a couple of buses with each other - some of the things that the buses carry are reads and writes in memory space, reads and writes in I/O space, interrupt requests, interrupt acknowledges, DMA requests, DMA acknowledges, and NMI request/acknowledge. How that is simulated is explained later.&FIXME; Other important pieces of the puzzle are: the options object (reads/writes configuration files, can be written to and queried while Bochs is running) and the GUI object. There are many different but compatible implementations of the GUI object, depending on whether you compile for X (Unix/Linux), Win32, Macintosh (two versions: one for Mac OS X and one for older OS's), Amiga, etc. And then there is the supporting cast: debugger, config menu, panic handler, disassembler, tracer, instrumentation.
Directory Structure Directory structure Location Meaning biosSystem and VGA BIOS images, system BIOS sources and makefilebuildadditional stuff required for building Bochs on different platformsbx_debugthe builtin Bochs debuggercputhe cpu emulation sourcesdisasmthe disassembler for the Bochs debuggerdoc/docbookthe Bochs documentation in DocBook formatdoc/manBochs manual pagesdocs-htmlold Bochs documentation in HTML (will be replaced by DocBook)fputhe fpu emulation sourcesguidisplay libraries (guis), the simulator interface and text mode config interfacegui/bitmapsbitmaps for the headerbargui/fontthe default VGA font used by most of the display librariesgui/keymapskeymaps for the keyboard mapping featurehosthost specific drivers (currently only used by the pcidev kernel module for Linux)instrumentdirectory tree for the instrumentation featureiodevstandard PC devices, PCI core devicesiodev/hdimagesupport for different disk image types and lowlevel cdrom accessiodev/networkingnetworking devices and lowlevel modulesiodev/soundsound devices and lowlevel modulesiodev/usbUSB HCs and pluggable devicesmemorymemory management and ROM loadermiscuseful utilities (e.g. bximage, bxcommit, niclist)misc/sb16tool to control the SB16 emulation from the guest sidepatchespending patches
Emulator Objects
Weird macros and other mysteries 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.
Static methods hack 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 config.h 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. Declaration of a class, from iodev/pic.h: ... #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); }; And iodev/pic.cc: ... #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; ... } ... 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.
CPU und memory objects in UP/SMP configurations 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. 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?
The configuration parameter tree 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. 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. Bit32u megs = SIM->get_param_num("memory.standard.ram.size")->get(); 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. The table below shows all parameter types used by the Bochs configuration interface. Parameter types Type Description bx_object_c Base class for all the other parameter types. It contains the unique parameter id and the object type value. bx_param_c Generic parameter class. It contains the name, label, description and the input/output formats. bx_param_num_c Numerical (decimal/hex) config settings are stored in this parameter type. bx_param_bool_c 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. bx_param_enum_c Based on bx_param_num_c this parameter type contains a list of valid values. bx_param_string_c Configuration strings are stored in this type of parameter. bx_param_filename_c Based on bx_param_string_c this parameter type is used for file names. bx_list_c Contains a list of pointers to parameters (bx_param_*_c and bx_list_c). In the config interface it is used for menus/dialogs.
The save/restore feature 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. The table below shows the additional parameter types for save/restore. Save/restore parameter types Type Description bx_shadow_num_c Based on bx_param_num_c this type stores a pointer to a numerical variable. bx_shadow_bool_c This parameter type stores a pointer to a boolean variable. bx_shadow_data_c This special parameter type stores pointer size of a binary array. bx_shadow_filedata_c This special parameter type stores the descriptor of an open file (added in Bochs 2.5).
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. All devices can uses these two save/restore specific methods: register_state() is called after the device init() to register the device members for save/restore after_restore_state() is an optional method to do things directly after restore
Configure Scripting &FIXME; configure script, makefiles, header files
Log Functions &FIXME; log functions: what is a panic, what is an error, etc.
timers &FIXME;
Bochs's CMOS map In addition to the default CMOS RAM layout, the Bochs BIOS uses some additional registers for harddisk parameters and the boot sequence. The following table shows all CMOS registers and their meaning. Legend: S - set by the emulator (Bochs) Q - set by the emulator (Qemu) B - set by the bios U - unused by the bios LOC NOTES MEANING 0x00 S rtc seconds 0x01 B second alarm 0x02 S rtc minutes 0x03 B minute alarm 0x04 S rtc hours 0x05 B hour alarm 0x06 S,U day of week 0x07 S,B date of month 0x08 S,B month 0x09 S,B year 0x0a S,B status register A 0x0b S,B status register B 0x0c S status register C 0x0d S status register D 0x0f S shutdown status values: 0x00: normal startup 0x09: normal 0x0d+: normal 0x05: eoi ? else: unimpl 0x10 S fd drive type (2 nibbles: high=fd0, low=fd1) values: 1: 360K 5.25" 2: 1.2MB 5.25" 3: 720K 3.5" 4: 1.44MB 3.5" 5: 2.88MB 3.5" !0x11 configuration bits!! 0x12 S how many disks first (hd type) !0x13 advanced configuration bits!! 0x14 S,U equipment byte (?) bits where what 7-6 floppy.cc 5-4 vga.cc 0 = vga 2 keyboard.cc 1 = enabled 0 floppy.cc 0x15 S,U base memory - low 0x16 S,U base memory - high 0x17 S,U extended memory in k - low 0x18 S,U extended memory in k - high 0x19 S hd0: extended type 0x1a S hd1: extended type 0x1b S,U hd0:cylinders - low 0x1c S,U hd0:cylinders - high 0x1d S,U hd0:heads 0x1e S,U hd0:write pre-comp - low 0x1f S,U hd0:write pre-comp - high 0x20 S,U hd0:retries/bad_map/heads>8 0x21 S,U hd0:landing zone - low 0x22 S,U hd0:landing zone - high 0x23 S,U hd0:sectors per track 0x24 S,U hd1:cylinders - low 0x25 S,U hd1:cylinders - high 0x26 S,U hd1:heads 0x27 S,U hd1:write pre-comp - low 0x28 S,U hd1:write pre-comp - high 0x29 S,U hd1:retries/bad_map/heads>8 0x2a S,U hd1:landing zone - low 0x2b S,U hd1:landing zone - high 0x2c S,U hd1:sectors per track 0x2d S boot from (bit5: 0:hd, 1:fd) 0x2e S,U standard cmos checksum (0x10->0x2d) - high 0x2f S,U standard cmos checksum (0x10->0x2d) - low 0x30 S extended memory in k - low 0x31 S extended memory in k - high 0x32 S rtc century 0x34 S extended memory in 64k - low 0x35 S extended memory in 64k - high 0x37 S ps/2 rtc century (copy of 0x32, needed for winxp) 0x38 S eltorito boot sequence + boot signature check bits 0 floppy boot signature check (1: disabled, 0: enabled) 7-4 boot drive #3 (0: unused, 1: fd, 2: hd, 3:cd, else: fd) 0x39 S ata translation policy - ata0 + ata1 bits 1-0 ata0-master (0: none, 1: LBA, 2: LARGE, 3: R-ECHS) 3-2 ata0-slave 5-4 ata1-master 7-6 ata1-slave 0x3a S ata translation policy - ata2 + ata3 (see above) 0x3d S eltorito boot sequence (see above) bits 3-0 boot drive #1 7-4 boot drive #2 0x5b S extra memory above 4GB 0x5c S extra memory above 4GB 0x5d S extra memory above 4GB 0x5f Q number of processors
Sound Blaster 16 Emulation A little more up-to-date version of the user related part of this section is available in the user guide. Sound Blaster 16 (SB16) emulation for Bochs was written and donated by Josef Drexler, who has a web page on the topic. The entire set of his SB16 patches have been integrated into Bochs, however, so you can find everything you need here. SB16 Emulation has been tested with several soundcards and versions of Linux. Please give Josef feedback on whether is does or doesn't work on your combination of software and hardware.
How well does it work? Right now, MPU401 emulation is next to perfect. It supports UART and SBMIDI mode, because the SB16's MPU401 ports can't do anything else as well. The digital audio basically works, but the emulation is too slow for fluent output unless the application doesn't do much in the background (or the foreground, really). The sound tends to looping or crackle on slower computer, but the emulation appears to be correct. Even a MOD player works, although only for lower sampling speeds. Also, the MIDI data running through the MPU401 ports can be written into a SMF, that is the standard midi file. The wave output can be written into a VOC file, which has a format defined by Creative Labs. This file format can be converted to WAV by sox for example.
Output to a sound card Output is supported on Linux and Windows 95 at the moment. On Linux, the output goes to any file or device. If you have a wavetable synthesizer, midi can go to /dev/midi00, otherwise you may need a midi interpreter. For example, the midid program from the DosEmu project would work. Wave output should go to /dev/dsp. These devices are assumed to be OSS devices, if they're not some of the ioctl's might fail. On Windows, midi and output goes to the midi mapper and the wave mapper, respectively. A future version might have selectable output devices.
Installation on Linux Prerequisites: A wavetable synthesizer on /dev/midi00 and a working /dev/dsp if you want real time music and sound, otherwise output to midi and wave files is also possible. Optionally, you can use a software midi interpreter, such as the midid program from the DosEmu project instead of /dev/midi00.
Configuring Bochs There are a few values in config.h that are relevant to the sound functions. Edit config.h after running configure, but before compiling. BX_USE_SB16_SMF should be 1 unless you intend to have several sound cards running at the same time. BX_SOUND_OUTPUT_C is the name of the class used for output. The default is to have no output functions, so you need to change this if you want any sound. The following are supported at the moment: bx_sound_linux_c for output to /dev/dsp and /dev/midi00 on Linux (and maybe other OSes that use the OSS driver) bx_sound_windows_c for output to the midi and wave mapper of Windows 3.1 and higher. bx_sound_output_c for no output at all. Setup the SB16 emulation in your .bochsrc, according to instructions in that file.
Runtime configuration The source for the SB16CTRL program that is used to modify the runtime behaviour of the SB16 emulator is included in misc/sb16. You can compile it or download the executable. See the section "Sound Blaster 16 Emulation" in the user documentation for information about the commands of SB16CTRL.
Features planned for the future Ports to more OS's, but I can't do this myself Finishing the OPL3 FM emulation by translating the music to midi data
Description of the sound output classes This file is intended for programmers who would like to port the sound output routines to their platform. It gives a short outline what services have to be provided. You should also have a look at the exisiting files, SOUNDLNX.CC for Linux and SOUNDWIN.CC for Windows and their respective header files to get an idea about how these things really work.
Files The main include file is bochs.h. It has all definitions for the system-independent functions that the SB16 emulation uses, which are defined in sb16.h. Additionally, every output driver will have an include file, which should be included at the end of sb16.h to allow the emulator to use that driver. To actually make the emulator use any specific driver, BX_SOUND_OUTPUT_C has to be set to the name of the respective output class. Note that if your class contains any system-specific statements, include-files and so on, you should enclose both the include-file and the CC-file in an #if defined (OS-define) construct. Also don't forget to add your file to the object list in iodev/Makefile and iodev/Makefile.in.
Classes The following classes are involved with the SB16 emulation: bx_sb16_c is the class containing the emulator itself, that is the part acting on port accesses by the application, handling the DMA transfers and so on. It also prepares the data for the output classes. bx_sound_output_c is the base output class. It has all the methods used by the emulator, but only as stubs and does not actually produce any output. These methods are then called by the emulator whenever output is necessary. bx_sound_OS_c is derived from bx_sound_output_c. It contains the code to generate output for the OS operating system. It is necessary to override all the methods defined in the base class, unless virtual functions are used. Note that this should remain an option, so try to override all methods, even if only as stubs. They should be declared virtual if and only if BX_USE_SOUND_VIRTUAL is defined, just as in the examples. The constructor should call the inherited constructor as usual, even though the current constructor does not do anything yet.
Methods The following are the methods that the output class has to override. All but constructor and destructor have to return either BX_SOUND_OUTPUT_OK (0) if the function was successful, or BX_SOUND_OUTPUT_ERR (1) if not. If any of the initialization functions fail, output to that device is disabled until the emulator is restarted.
bx_sound_OS_c(bx_sb16_c*sb16) The emulator instantiates the class at the initialization of Bochs. Description of the parameter: sb16 is a pointer to the emulator class. This pointer can then be used to access for example the writelog function to generate sound-related log messages. Apart from that, no access to the emulator should be necessary. The constructor should not allocate the output devices. This shouldn't be done until the actual output occurs; in either initmidioutput() or initwaveoutput(). Otherwise it would be impossible to have two copies of Bochs running concurrently (if anybody ever wants to do this).
~bx_sound_OS_c() The instance is destroyed just before Bochs ends.
int openmidioutput(char *device) openmidioutput() is called when the first midi output starts. It is only called if the midi output mode is 1 (midimode 1). It should prepare the given MIDI hardware for receiving midi commands. openmidioutput() will always be called before openwaveoutput(), and closemidioutput()will always be called before closewaveoutput(), but not in all cases will both functions be called.
Description of the parameters: device is a system-dependent variable. It contains the value of the MIDI=device configuration option. Note that only one midi output device will be used at any one time. device may not have the same value throughout one session, but it will be closed before it is changed.
int midiready() midiready() is called whenever the applications asks if the midi queue can accept more data. Return values: BX_SOUND_OUTPUT_OK if the midi output device is ready. BX_SOUND_OUTPUT_ERR if it isn't ready. Note: midiready() will be called a few times before the device is opened. If this is the case, it should always report that it is ready, otherwise the application (not Bochs) will hang.
int sendmidicommand(int delta, int command, int length, Bit8u data[]) sendmidicommand()is called whenever a complete midi command has been written to the emulator. It should then send the given midi command to the midi hardware. It will only be called after the midi output has been opened. Note that if at all possible it should not wait for the completion of the command and instead indicate that the device is not ready during the execution of the command. This is to avoid delays in the program while it is generating midi output. Description of the parameters: delta is the number of delta ticks that have passed since the last command has been issued. It is always zero for the first command. There are 24 delta ticks per quarter, and 120 quarters per minute, thus 48 delta ticks per second. command is the midi command byte (sometimes called status byte), in the usual range of 0x80..0xff. For more information please see the midi standard specification. length is the number of data bytes that are contained in the data structure. This does not include the status byte which is not replicated in the data array. It can only be greater than 3 for SysEx messages (commands 0xF0 and 0xF7) data[] is the array of these data bytes, in the order they have in the standard MIDI specification. Note, it might be NULL if length==0.
int closemidioutput() closemidioutput() is called before shutting down Bochs or when the emulator gets the stop_output command through the emulator port. After this, no more output will be necessary until openmidioutput() is called again, but midiready() might still be called. It should do the following: Wait for all remaining messages to be completed Reset and close the midi output device
int openwaveoutput(char *device) openwaveoutput() is called when the first wave output occurs, and only if the selected wavemode is 1. It should do the following: Open the given device, and prepare it for wave output or Store the device name so that the device can be opened in startplayback(). openmidioutput() will always be called before openwaveoutput(), and closemidioutput()will always be called before closewaveoutput(), but not in all cases will both functions be called. openwaveoutput() will typically be called once, whereas startplayback() is called for every new DMA transfer to the SB16 emulation. If feasible, it could be useful to open and/or lock the output device in startplayback() as opposed to openwaveoutput() to ensure that it can be used by other applications while Bochs doesn't need it. However, many older applications don't use the auto-init DMA mode, which means that they start a new DMA transfer for every single block of output, which means usually for every 2048 bytes or so. Unfortunately there is no way of knowing whether the application will restart an expired DMA transfer soon, so that in these cases the startwaveplayback function will be called very often, and it isn't a good idea to have it reopen the device every time. The buffer when writing to the device should not be overly large. Usually about four buffers of 4096 bytes produce best results. Smaller buffers could mean too much overhead, while larger buffers contribute to the fact that the actual output will always be late when the application tries to synchronize it with for example graphics. The parameters are the following: device is the wave device selected by the user. It is strictly system-dependent. The value is that of the WAVE=device configuration option. Note that only one wave output device will be used at any one time. device may not have the same value throughout one session, but it will be closed before it is changed.
int startwaveplayback(int frequency, int bits, int stereo, int format) This function is called whenever the application starts a new DMA transfer. It should do the following: Open the wave output device, unless openwaveoutput() did that already Prepare the device for data and set the device parameters to those given in the function call The parameters are the following: frequency is the desired frequency of the output. Because of the capabities of the SB16, it can have any value between 5000 and 44,100. bits is either 8 or 16, denoting the resolution of one sample. stereo is either 1 for stereo output, or 0 for mono output. format is a bit-coded value (see below). format bits Bit number Meaning 0 (LSB) 0: unsigned data 1: signed data 1..6 Type of codec (see below) 7 0: no reference byte 1: with reference byte 8..x reserved (0)
codecs Value Meaning 0 PCM (raw data) 1 reserved 2 2-bit ADPCM (Creative Labs format) 3 2.4-bit (3-bit) ADPCM (Creative Labs format) 4 4-bit ADPCM (Creative Labs format)
Other codecs are not supported by the SB hardware. In fact, most applications will translate their data into raw data, so that in most cases the codec will be zero. The number of bytes per sample can be calculated from this as (bits / 8) * (stereo + 1).
int waveready() This is called whenever the emulator has another output buffer ready and would like to pass it to the output class. This happens every BX_SOUND_OUTPUT_WAVEPACKETSIZE bytes, or whenever a DMA transfer is done or aborted. It should return whether the output device is ready for another buffer of BX_SOUND_OUTPUT_WAVEPACKETSIZE bytes. If BX_SOUND_OUTPUT_ERR is returned, the emulator waits about 1/(frequency * bytes per sample) seconds and then asks again. The DMA transfer is stalled during that time, but the application keeps running, until the output device becomes ready. As opposed to midiready(), waveready() will not be called unless the device is open.
int sendwavepacket(int length, Bit8u data[]) This function is called whenever a data packet of at most BX_SB16_WAVEPACKETSIZE is ready at the SB16 emulator. It should then do the following: Send this wave packet to the wave hardware This function has to be synchronous, meaning that it has to return immediately, and not wait until the output is done. Also, this function might be called before the previous output is done. If your hardware can't append the new output to the old one, you will have to implement this yourself, or the output will be very chunky, with as much silence between the blocks as the blocks take to play. This is not what you want. Instead, waveready() should return BX_SOUND_OUTPUT_ERR until the device accepts another block of data. Parameters: length is the number of data bytes in the data stream. It will never be larger than BX_SB16_WAVEPACKETSIZE. data is the array of data bytes. The order of bytes in the data stream is the same as that in the Wave file format: wave output types Output type Sequence of data bytes 8 bit mono Sample 1; Sample 2; Sample 3; etc. 8 bit stereo Sample 1, Channel 0; Sample 1, Channel 1; Sample 2, Channel 0; Sample 2, Channel 1; etc. 16 bit mono Sample 1, LSB; Sample 1, MSB; Sample 2, LSB; Sample 2, MSB; etc. 16 bit stereo Sample 1, LSB, Channel 0; Sample 1, MSB, Channel 0; Sample 1, LSB, Channel 1; Sample 1, MSB, Channel 1; etc.
Typically 8 bit data will be unsigned with values from 0 to 255, and 16 bit data will be signed with values from -32768 to 32767, although the SB16 is not limited to this. For further information on the codecs and the use of reference bytes please refer to the Creative Labs Sound Blaster Programmer's Manual, which can be downloaded from the Creative Labs web site.
int stopwaveplayback() This function is called at the end of a DMA transfer. It should do the following: Close the output device if it was opened by startwaveplayback(). and it's not going to be opened soon. Which is almost impossible to tell.
int closewaveoutput() This function is called just before Bochs exits. It should do the following: Close the output device, if this hasn't been done by stopwaveplayback(). Typically, stopwaveplayback() will be called several times, whenever a DMA transfer is done, where closewaveoutput() will only be called once. However, in the future it might be possible that openwaveoutput() is called again, for example if the user chose to switch devices while Bochs was running. This is not supported at the moment, but might be in the future.
Harddisk Images based on redologs This section describes how the three new disk images "undoable", "growing", and "volatile" are implemented in Bochs 2.1. It also applies to the write support the "vvfat" disk image mode in Bochs 2.4.6. undoable -> flat file, plus growing, commitable, rollbackable redolog file growing -> growing files, all previously unwritten sectors go to the end of file volatile -> flat file, plus hidden growing redolog vvfat -> virtual VFAT disk created from directory, plus hidden growing redolog
Description The idea behind volatile and undoable disk images is to have a flat file, associated with one redolog file. In case of vvfat, a directory is associated with the redolog file. Reading a sector is done from the redolog file if it contains the sector, or from the flat file / vvfat directory otherwise. Sectors written go to the redolog, so flat files are opened in read only mode in this configuration. The redolog is designed in a way so it starts as a small file and grows with every new sectors written to it. Previously written sectors are done in place. Redolog files can not shrink. The redolog is a growing file that can be created on the fly. Now, it turns out that if you only use a redolog without any flat file, you get a "growing" disk image. So "undoable", "volatile", "growing" and "vvfat" harddisk images classes are implemented on top of a redolog class.
How redologs works ? At the start of a redolog file, there is a header, so Bochs can check whether a file is consistent. This header could also be checked when we implement automatic type and size detection. The generic part of the header contains values like type of image, and spec version number. The header also has a specific part. For redologs, the number of entries of the catalog, the extent, bitmap and disk size are stored. In a redolog, the disk image is divided in a number of equal size "extents". Each extent is a collection of successive 512-bytes sectors of the disk image, preceeded by a n*512bytes bitmap. the n*512bytes bitmap defines the presence (data has been written to it) of a specific sector in the extent, one bit for each sector. Therefore with a 512bytes bitmap, each extent can hold up to 4k blocks Typically the catalog can have 256k entries. With a 256k entries catalog and 512bytes bitmaps, the redolog can hold up to 512GiB All data is stored on images as little-endian values
Header At the start of a redolog file, there is a header. This header is designed to be reusable by other disk image types. The header length is 512 bytes. It contains : Generic header description Start position in bytes Length in bytes Data type Description Possible values 0 32 string magical value Bochs Virtual HD Image 32 16 string type of file Redolog 48 16 string subtype of file Undoable, Volatile, Growing 64 4 Bit32u version of used specification 0x00010000 68 4 Bit32u header size 512
Redolog specific header description Start position in bytes Length in bytes Data type Description 72 4 Bit32u number of entries in the catalog 76 4 Bit32u bitmap size in bytes 80 4 Bit32u extent size in bytes 84 8 Bit64u disk size in bytes
Catalog Immediately following the header, there is a catalog containing the position number (in extents) where each extent is located in the file. Each position is a Bit32u entity.
Extent &FIXME;
Parameters The following tables shows what parameters are used when creating redologs or creating "growing" images : How number of entries in the catalog and number of blocks by extents are computed Catalog entries Catalog size(KiB) Bitmap size (B) Extent size (KiB) Disk Max Size 512 2 1 4 2MiB 512 2 2 8 4MiB 1k 4 2 8 8MiB 1k 4 4 16 16MiB 2k 8 4 16 32MiB 2k 8 8 32 64MiB 4k 16 8 32 128MiB 4k 16 16 64 256MiB 8k 32 16 64 512MiB 8k 32 32 128 1GiB 16k 64 32 128 2GiB 16k 64 64 256 4GiB 32k 128 64 256 8GiB 32k 128 128 512 16GiB 64k 256 128 512 32GiB 64k 256 256 1024 64GiB 128k 512 256 1024 128GiB 128k 512 512 2048 256GiB 256k 1024 512 2048 512GiB 256k 1024 1024 4096 1TiB 512k 2048 1024 4096 2TiB 512k 2048 2048 8192 4TiB 1024k 4096 2048 8192 8TiB 1024k 4096 4096 16384 16TiB 2048k 8192 4096 16384 32TiB
Redolog class description The class redolog_t(); implements the necessary methods to create, open, close, read and write data to a redolog. Managment of header catalog and sector bitmaps is done internally by the class.
Constants #define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image" #define STANDARD_HEADER_VERSION (0x00010000) #define STANDARD_HEADER_SIZE (512) These constants are used in the generic part of the header. #define REDOLOG_TYPE "Redolog" #define REDOLOG_SUBTYPE_UNDOABLE "Undoable" #define REDOLOG_SUBTYPE_VOLATILE "Volatile" #define REDOLOG_SUBTYPE_GROWING "Growing" These constants are used in the specific part of the header. #define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff) This constant is used in the catalog for an unwritten extent.
Methods redolog_t(); instanciates a new redolog. int make_header (const char* type, Bit64u size); creates a header structure in memory, and sets its type and parameters based on the disk image size. Returns 0. int create (const char* filename, const char* type, Bit64u size); creates a new empty redolog file, with header and catalog, named filename of type type for a size bytes image. Returns 0 for OK or -1 if a problem occured. int create (int filedes, const char* type, Bit64u size); creates a new empty redolog file, with header and catalog, in a previously opened file described by filedes, of type type for a size bytes image. Returns 0 for OK or -1 if a problem occured. int open (const char* filename, const char* type, Bit64u size); opens a redolog file named filename, and checks for consistency of header values against a type and size. Returns 0 for OK or -1 if a problem occured. void close (); closes a redolog file. off_t lseek (off_t offset, int whence); seeks at logical data offset offset in a redolog. offset must be a multiple of 512. Only SEEK_SET is supported for whence. Returns -1 if a problem occured, or the current logical offset in the redolog. ssize_t read (void* buf, size_t count); reads count bytes of data of the redolog, from current logical offset, and copies it into buf. count must be 512. Returns the number of bytes read, that can be 0 if the data has not previously be written to the redolog. ssize_t write (const void* buf, size_t count); writes count bytes of data from buf to the redolog, at current logical offset. count must be 512. Returns the number of bytes written.
Disk image classes description "volatile" and "undoable" disk images are easily implemented by instanciating a default_image_t object (flat image) and a redolog_t object (redolog). "growing" disk images only instanciates a redolog_t object. Classe names are undoable_image_t, volatile_image_t and growing_image_t. When using these disk images, the underlying data structure and layout is completely hidden to the caller. Then, all offset and size values are "logical" values, as if the disk was a flat file.
Constants #define UNDOABLE_REDOLOG_EXTENSION ".redolog" #define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION)) #define VOLATILE_REDOLOG_EXTENSION ".XXXXXX" #define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION)) These constants are used when building redolog file names
undoable_image_t methods undoable_image_t(Bit64u size, const char* redolog_name); instanciates a new undoable_image_t object. This disk image logical length is size bytes and the redolog filename is redolog_name. int open (const char* pathname); opens the flat disk image pathname, as an undoable disk image. The associated redolog will be named pathname with a UNDOABLE_REDOLOG_EXTENSION suffix, unless set in the constructor. Returns 0 for OK or -1 if a problem occured. void close (); closes the flat image and its redolog. off_t lseek (off_t offset, int whence); seeks at logical data position offset in the undoable disk image. Only SEEK_SET is supported for whence. Returns -1 if a problem occured, or the current logical offset in the undoable disk image. ssize_t read (void* buf, size_t count); reads count bytes of data from the undoable disk image, from current logical offset, and copies it into buf. count must be 512. Returns the number of bytes read. Data will be read from the redolog if it has been previously written or from the flat image otherwise. ssize_t write (const void* buf, size_t count); writes count bytes of data from buf to the undoable disk image, at current logical offset. count must be 512. Returns the number of bytes written. Data will always be written to the redolog.
volatile_image_t methods volatile_image_t(Bit64u size, const char* redolog_name); instanciates a new volatile_image_t object. This disk image logical length is size bytes and the redolog filename is redolog_name plus a random suffix. int open (const char* pathname); opens the flat disk image pathname, as a volatile disk image. The associated redolog will be named pathname with a random suffix, unless set in the constructor. Returns 0 for OK or -1 if a problem occured. void close (); closes the flat image and its redolog. The redolog is deleted/lost after close is called. off_t lseek (off_t offset, int whence); seeks at logical data position offset in the volatile disk image. Only SEEK_SET is supported for whence. Returns -1 if a problem occured, or the current logical offset in the volatile disk image. ssize_t read (void* buf, size_t count); reads count bytes of data from the volatile disk image, from current logical offset, and copies it into buf. count must be 512. Returns the number of bytes read. Data will be read from the redolog if it has been previously written or from the flat image otherwise. ssize_t write (const void* buf, size_t count); writes count bytes of data from buf to the volatile disk image, at current logical offset. count must be 512. Returns the number of bytes written. Data will always be written to the redolog.
growing_image_t methods growing_image_t(Bit64u size); instanciates a new growing_image_t object. This disk image logical length is size bytes. int open (const char* pathname); opens the growing disk image pathname, Returns 0 for OK or -1 if a problem occured. void close (); closes the growing disk image. off_t lseek (off_t offset, int whence); seeks at logical data position offset in the growable disk image. Only SEEK_SET is supported for whence. Returns -1 if a problem occured, or the current logical offset in the grwoing image. ssize_t read (void* buf, size_t count); reads count bytes of data from the growing disk image, from current logical offset, and copies it into buf. count must be 512. Returns the number of bytes read. The buffer will be filled with null bytes if data has not been previously written to the growing image. ssize_t write (const void* buf, size_t count); writes count bytes of data from buf to the growing disk image, at current logical offset. count must be 512. Returns the number of bytes written.
How to add keymapping in a GUI client Christophe Bothamy, wrote the keymapping code for Bochs, provided these instructions to help developers to add keymapping to a GUI. Bochs creates a bx_keymap_c object named bx_keymap. This object allows you to : - load the configuration specified keymap file - get the translated BX_KEY_* from your GUI key You have to provide a translation function from string to your Bit32u key constant. Casting will be necessary if your key constants are not Bit32u typed. The function must be "static Bit32u (*)(const char *)" typed, and must return BX_KEYMAP_UNKNOWN if it can not translate the parameter string. What you have to do is : - call once "void loadKeymap(Bit32u (*)(const char*))", providing your translation function, to load the keymap - call "Bit32u getBXKey(Bit32u)" that returns the BX_KEY_* constant, for each key you want to map. The file gui/x.cc implements this architecture, so you can refer to it as an example.
Debugger
compile with debugger support &FIXME;
get started in debugger &FIXME;
command reference &FIXME;
techniques &FIXME;
I/O Interface to Bochs Debugger This device was added by Dave Poirier (eks@void-core.2y.net). Compiling Bochs with iodebug support ./configure --enable-iodebug make Other optional fields may be added to the ./configure line, see Bochs documentation for all the information. To enable the iodebug plugin at runtime, it must be loaded with the 'plugin_ctrl' bochsrc option. Using the I/O Interface to the debugger port range: 0x8A00 - 0x8A01 Port 0x8A00 servers as command register. You can use it to enable the i/o interface, change which data register is active, etc. Port 0x8A01 is used as data register for the memory monitoring.
Commands supported by port 0x8A00 0x8A00 Used to enable the device. Any I/O to the debug module before this command is sent is sent will simply be ignored. 0x8A01 Selects register 0: Memory monitoring range start address (inclusive) 0x8A02 Selects register 1: Memory monitoring range end address (exclusive) 0x8A80 Enable address range memory monitoring as indicated by register 0 and 1 and clears both registers 0x8AE0 - Return to Debugger Prompt If the debugger is enabled (via --enable-debugger), sending 0x8AE0 to port 0x8A00 after the device has been enabled will return the Bochs to the debugger prompt. Basically the same as doing CTRL+C. 0x8AE2 - Instruction Trace Disable If the debugger is enabled (via --enable-debugger), sending 0x8AE2 to port 0x8A00 after the device has been enabled will disable instruction tracing 0x8AE3 - Instruction Trace Enable If the debugger is enabled (via --enable-debugger), sending 0x8AE3 to port 0x8A00 after the device has been enabled will enable instruction tracing 0x8AE4 - Register Trace Disable If the debugger is enabled (via --enable-debugger), sending 0x8AE4 to port 0x8A00 after the device has been enabled will disable register tracing. 0x8AE5 - Register Trace Enable If the debugger is enabled (via --enable-debugger), sending 0x8AE5 to port 0x8A00 after the device has been enabled will enable register tracing. This currently output the value of all the registers for each instruction traced. Note: instruction tracing must be enabled to view the register tracing 0x8AFF Disable the I/O interface to the debugger and the memory monitoring functions. all accesses must be done using word reading this register will return 0x8A00 if currently activated, otherwise 0
Access to port 0x8A01 (write-only) All accesses to this port must be done using words. Writing to this port will shift to the left by 16 the current value of the register and add the provided value to it. Sample: reg0 = 0x01234567 out port: 0x8A01 data: 0xABCD reg0 = 0x4567ABCD
Sample Enable memory monitoring on first page of text screen (0xb8000-0xb8fa0): add in bochrc file: optromimage1: file="asmio.rom", address=0xd0000 /* * Make asmio ROM file: * gcc -c asmio.S * objcopy -O binary asmio.o asmio.rom */ .text .global start .code16 /* ROM Header */ .byte 0x55 .byte 0xAA .byte 1 /* 512 bytes long */ start: /* Monitor memory access on first page of text screen */ mov $0x8A00,%dx /* Enable iodebug (0x8A00->0x8A00) */ mov %dx,%ax out %ax,%dx mov $0x8A01,%ax /* Select register 0 start addr (0x8A01->0x8A00) */ out %ax,%dx mov $0x8A01,%dx /* Write start addr 0xB8000 (high word first) */ mov $0xB,%ax out %ax,%dx mov $0x8000,%ax /* Write start addr (low word) */ out %ax,%dx mov $0x8A02,%ax /* Select register 1 end addr (0x8A02->0x8A00) */ mov $0x8A00,%dx out %ax,%dx mov $0x8A01,%dx /* Write end addr 0xB8FA0 (high word first) */ mov $0xB,%ax out %ax,%dx mov $0x8FA0,%ax /* Write end addr (low word) */ out %ax,%dx mov $0x8A00,%dx /* Enable addr range memory monitoring (0x8A80->0x8A00) */ mov $0x8A80,%ax out %ax,%dx mov $0x8A00,%dx /* Return to Bochs Debugger Prompt (0x8AE0->0x8A00) */ mov $0x8AE0,%ax out %ax,%dx lret .byte 0x6b /* Checksum (code dependent!, update it as needed) */ .align 512 /* NOP follow */
Coding
Coding guidelines Don't make use of any external C++ classes. They are not offered on all platforms and this would make Bochs non-portable. There is use of such classes in the optional debugger. I plan on removing this use. Don't use fancy C++ features. Bochs is incredibly performance sensitive, and will be increasingly so as more speed enhancements are added. There's a time and place for most everything and this is not it. Some advanced features create overhead in the generated code that you don't see. They also convolute the code, and sometimes occlude that is really going on. Don't use templates Don't use virtual functions if not strictly required Don't use C++ exceptions Use soft tabs. At least when you submit code, convert all hard tabs to spaces. There is no uniform way to handle tabs properly. Please do compile with all warnings turned on. It's really difficult to spot interesting warnings when a compile is littered with non-interesting ones. Don't use signed ints where unsigned will do. Make sure that contributed code / patches are LGPL compatible.
patches: &FIXME; how to make, where to submit, what happens then?
Building a Bochs release
Preparing source files and SVN Update version number and strings in configure.in. VERSION="2.5" VER_STRING="2.5" REL_STRING="Build from SVN snapshot on November 27, 2011" In the README file you have to update version number and date. Add some information about new features if necessary. Bochs x86 Pentium+ Emulator Updated: Sun Nov 27 16:55:00 CET 2011 Version: 2.5 In the file bochs.manifest you have to update the version number for the Windows build. version="2.5.0.0" Check date, update/sumup info in CHANGES. Run autoconf to regenerate configure and check them in. Create an SVN tag that contains all files of the revision that was used in the release. For prereleases I create a normal SVN tag like this: svn mkdir tags/REL_2_5_pre1_FINAL svn copy trunk/bochs tags/REL_2_5_pre1_FINAL/bochs svn commit But for a real release, I make an SVN branch tag AND a normal tag. svn mkdir tags/REL_2_5_FINAL svn copy trunk/bochs tags/REL_2_5_FINAL/bochs svn mkdir branches/REL_2_5 svn copy trunk/bochs branches/REL_2_5/bochs svn commit The tag marks where the branch split off of the main trunk. This is very useful in maintaining the branch since you can do diffs against it. svn diff tags/REL_2_5_FINAL/bochs trunk/bochs svn diff tags/REL_2_5_FINAL/bochs branches/REL_2_5 etc. All bugfix-only releases after the final release should be created from the REL_2_5 branch. Now you can start building packages with the sources from the created release tag.
Building the release on win32 These instructions require cygwin and MSVC++. In Cygwin: sh .conf.win32-vcpp # runs configure make win32_snap # unzip workspace, make a win32 source ZIP Copy the source ZIP to a windows machine, if necessary. Open up Visual C++ and load the workspace file Bochs.dsw. Check the Build:Set Active Project Configuration is set the way you want it. For releases I use "Win32 Release". To create "bochsdbg.exe" with Bochs debugger support, manually change two lines in config.h to turn on the debugger. #define BX_DEBUGGER 1 #define BX_DISASM 1 VC++ will rebuild Bochs with debugger and overwrite bochs.exe. To avoid trashing the non-debug version, move it out of the way while the debugger version is being built. Then rename the debugger version to bochsdbg.exe. cd obj-release mv bochs.exe bochs-normal.exe (build again with BX_DEBUGGER=1 this time) mv bochs.exe bochsdbg.exe mv bochs-normal.exe bochs.exe To get the docbook installed, you need to do something like this: make dl_docbook copy up to date doc files Then you can do cd doc/docbook; touch */*.html Do make install_win32 into /tmp or someplace: make install_win32 prefix=/tmp/bochs-2.5 This copies all the files into /tmp/bochs-2.5 and then creates a binary ZIP at /tmp/bochs-2.5.zip. Rename that bochs-2.5.win32-bin.zip. Now make the NSIS installer package (the current script is known to work with NSIS 2.44) cd build/win32/nsis Unzip the binary ZIP file into bochs-$VERSION (must match Makefile) and then run make. unzip ~/bochs-2.5.zip make That gives an installer called Bochs-2.5.exe. Test and upload it.
Building the release on Linux Do a clean SVN checkout from the release tag and specify a not yet existing directory name with the version number as the destination. Then create the source package from this new directory. svn co https://bochs.svn.sourceforge.net/svnroot/bochs/tags/REL_2_4_FINAL/bochs bochs-2.4 tar czvf bochs-2.5.tar.gz --exclude=.svn bochs-2.5 The source TAR file bochs-2.5.tar.gz is ready to upload. The RPM will be building using the configuration in .conf.linux with a few parameters from build/redhat/make-rpm. Make any last minute changes to .conf.linux. Any changes will go into the source RPM. The DLX Linux demo package will be downloaded to the Bochs root directory if it is not already present there. ./build/redhat/make-rpm | tee ../build.txt This produces two rpm files in the current directory. Test and upload.
Creating a file release and uploading files on SF When you are ready with creating release packages you have to upload them using the SF file manager feature. Create a subdirectory with the version number in the bochs directory. Point the download destination to the new directory and start uploading packages. The top of the CHANGES file should be used as the release notes. After setting up the file properties the new release is ready for download.
Webmastering
Bochs project webspace The Bochs project webspace is stored under the SF directory /home/project-web/bochs. It can be accessed from the SF shell using SSH or with the commands sftp, scp and rsync. Some parts of the directory structure must be updated from the local CVS repository, others from Bochs SVN (directories bochs and sfsite). The online documentation, disk images and screenshots must be uploaded manually. Directory structure Location Meaning cgi-binCGI scripts for the websitehtdocsroot directory of the websitehtdocs/doc/docbookBochs online documentationhtdocs/docs-htmlold Bochs documentationhtdocs/guestosdisk images directly stored on the Bochs websitehtdocs/screenshotscreenshots of Bochs running several guest operating systemshtdocs/svn-snapshotlink to current snapshothtdocs/techspectechnical specifications of several hardware componentslxrBochs source browsersfsite-cvsrootlocal CVS repositorysitebinshell scripts (e.g. for snapshot generation)sitemanwebsite manual pagessnapshotSVN snapshot storage areatmptemp directory for shell scripts
Updating the Bochs website content The main HTML content of the Bochs website (except online documentation) is stored in the sfsite directory of the Bochs SVN repository. Unlike other SF projects you don't need to upload these files to the Bochs project webspace. Running a simple SVN update on the SF shell is enough after the files have been updated in the repository. Please see Setting up SVN write access for general instructions. The only difference is the directory name sfsite instead of bochs. The example below shows how to start the SF shell with SSH and to update the HTML files. ssh -t vruppert,bochs@shell.sourceforge.net create vruppert,bochs@shell.sourceforge.net's password: Requesting a new shell for "vruppert" and waiting for it to start. queued... starting... This is an interactive shell created for user vruppert,bochs. Use the "timeleft" command to see how much time remains before shutdown. Use the "shutdown" command to destroy the shell before the time limit. For path information and login help, type "sf-help". [vruppert@shell-24002 ~]$ cd /home/project-web/bochs/htdocs/ [vruppert@shell-24002 htdocs]$ svn update U index.html Updated to revision 10752 [vruppert@shell-24002 htdocs]$ shutdown Requesting that your shell be shut down. This request will be processed soon. [vruppert@shell-24002 htdocs]$ Broadcast message from root (Mon Oct 31 09:45:04 2011): The system is going down for system halt NOW! Connection to shell-24002 closed by remote host. Connection to shell-24002 closed. Connection to shell.sourceforge.net closed.
Updating the SVN snapshot The SVN snapshot The SVN snapshot link can be found on the bottom of the page getcurrent.html. can be updated with SF shell access using SSH. There is a script called update-svn-snapshot.sh that can do all the required steps (checking out SVN, packing the source tree into one archive, updating the website link). See previous section how to create a shell. cd /home/project-web/bochs/sitebin/ ./update-svn-snapshot.sh
Updating the online documentation To update the online documentation, a file called bochsdoc.tar.gz must be generated with the make. This file must be uploaded to the location of the online documentation on SF using scp. cd doc/docbook make bochsdoc.tar.gz scp bochsdoc.tar.gz vruppert,bochs@web.sf.net:htdocs/doc/docbook After a successful upload, the HTML files must be unpacked from the SF shell. See section Updating the Bochs website content how to create a shell. cd /home/project-web/bochs/htdocs/doc/docbook tar xvzf bochsdoc.tar.gz The updated files can be accessed from the sidebar of the Bochs website.
other content &FIXME; sources, tmp
available tools &FIXME; sources, tmp
bochs-2.6/doc/docbook/fixtitles.pl0000755000175000017500000000263512020641457017104 0ustar guillemguillem#!/bin/sh exec perl -x $0 $*; echo "Could not exec perl!"; exit 1 # The line above allows perl to be anywhere, as long as it's in your # PATH environment variable. #!perl # # fix-titles.pl # $Id: fixtitles.pl 10213 2011-02-25 15:32:08Z sshwarts $ # # The HTML stylesheet likes to print html has the ends of tags on a different # line, like this: # FreeBSD # # Glimpse, which is indexing our website, finds this very confusing and # it cannot pick out the title from this mess. This script takes a list # of HTML files on the command line and attempts to make the tag # look more normal so that glimpse can understand it. # # WARNING: This is a hack. It's made to work on docbook generated html, but # may do strange things on anything else. use strict; foreach my $file (@ARGV) { print "Fixing $file\n"; rename $file, "$file.orig"; open (IN, "$file.orig") || die "open $file.orig"; open (OUT, ">$file") || die "open $file for writing"; while (<IN>) { if (/^<HTML$/) { print OUT "<HTML>\n"; } elsif (/^><HEAD$/) { print OUT "<HEAD>\n"; } elsif (/^><TITLE$/) { print OUT "<TITLE>"; } elsif (/^>(.*)<\/TITLE$/) { print OUT "$1\n"; # next line has one extra >, so read it and remove it. $_ = ; s/^>//; print OUT; } else { print OUT; } } close IN; close OUT; unlink "$file.orig"; } bochs-2.6/doc/docbook/user/0000755000175000017500000000000012020641457015501 5ustar guillemguillembochs-2.6/doc/docbook/user/user.dbk0000644000175000017500000122417312020641457017153 0ustar guillemguillem %bochsdefs; ]> Bochs User Manual KevinLawton BryceDenney N. DavidGuarneri VolkerRuppert ChristopheBothamy MichaelCalabrese StanislavShwartsman Introduction to Bochs
What is Bochs? Bochs is a program that simulates a complete Intel x86 computer. It includes emulation of the Intel x86 CPU, common I/O devices, and a custom BIOS. Bochs can be compiled to emulate many different x86 CPUs, from early 386 to the most recent x86-64 Intel and AMD processors which may even not reached the market yet. Bochs interprets every instruction from power-up to reboot, and has device models for all of the standard PC peripherals: keyboard, mouse, VGA card/monitor, disks, timer chips, network card, etc. Because Bochs simulates the whole PC environment, the software running in the simulation "believes" it is running on a real machine. This approach allows Bochs to run a wide variety of software with no modification, include most popular x86 operating systems: Windows 95/98/NT/2000/XP and Vista, all Linux flavors, all BSD flavors, and more. Bochs is written in the C++ programming language, and is designed to run on many different host platforms Since Bochs can run on one kind of machine and simulate another machine, we have to be clear in our terminology to avoid confusion. The host platform is the machine that runs the Bochs software. The guest platform is the operating system and applications that Bochs is simulating. , including x86, PPC, Alpha, Sun, and MIPS. No matter what the host platform is, Bochs still simulates x86 hardware. In other words, it does not depend on the native instructions of the host machine at all. This is both a strength and a weakness, and it's the major difference between Bochs and many other x86 emulation software such as VirtualBox, VMware, etc. Because Bochs uses software simulation for every single x86 instruction, it can simulate a Windows application on an Alpha or Sun workstation. However, the downside of Bochs' approach is simulation performance. To model the processor accurately, Bochs must run many instructions for every simulated x86 instruction, and this makes the simulated machine many times slower than the physical machine. Commercial PC emulators (VMware, Connectix, etc.) can achieve much high emulation speed using a technique called virtualization Virtualization takes advantage of simulating x86 instructions on an x86 machine, allowing large portions of the simulation to take place at native hardware speed. Whenever the simulated machine talks to the hardware or enters certain privileged modes (such as in kernel code), the simulator typically takes control and simulates that code in software at much slower speed, just like Bochs does. , but they are neither portable to non-x86 platforms nor open source. To do anything interesting in the simulated machine, Bochs needs to interact with the operating system on the host platform (the host OS). When you press a key in the Bochs display window, a key event goes into the device model for the keyboard. When the simulated machine needs to read from the simulated hard disk, Bochs reads from a disk image file on the host machine. When the simulated machine sends a network packet to the local network, Bochs uses the host platform's network card to send the packet out into the real world. These interactions between Bochs and the host operating system can be complicated, and in some cases they are host platform specific. Sending a network packet in FreeBSD requires different code than sending the packet in Windows XP, for example. For this reason, certain features are supported on some host platforms and not others. On GNU/Linux, Bochs can simulate a network card that communicates with the world, but on MacOSX the simulated network card may not work because the communication code between the device model and the MacOSX operating system has not been written. Bochs was written by Kevin Lawton starting in 1994. It started as a program with a commercial license, at the price of 25 USD, for use as-is. If a user needed to link it to other software, that user would have to negotiate a special license. &NEEDHELP; We need a Bochs historian to help out here. For background, it would be interesting to know how much Bochs sources used to cost and what it was used for. I thought I saw an interview out there somewhere where Kevin says why he started it and some more background information. Finally, in March 2000, MandrakeSoft (now called Mandriva) bought Bochs and made it open source under the GNU LGPL. In March 2001, Kevin helped a few developers to move all Bochs activities from bochs.com to a new site at bochs.sourceforge.net. Since then the Bochs project has settled into its new home, and around release times has even hit #1 most active project of the week at SourceForge.
Who uses Bochs? It is hard to estimate how many people have tried Bochs or use it on a regular basis, but a few statistics give an indication. The bochs-developers mailing list, which is the primary source of news on bugs and releases, has over 400 subscribers. The latest version has been downloaded over 150,000 times from SourceForge, not counting any mirror website or SVN users. Bochs has many possible uses, and different people use it for different things. Many people use it to run applications in a second operating system without needing two different computers or dual-booting. Running Windows software on a non-x86 workstation or on an x86 Unix box are common uses. Also, because every hardware instruction and every line of simulator code is accessible, Bochs is used extensively for debugging new operating systems. If you were writing boot code for your home-brewed x86 operating system and it didn't work right, booting it in Bochs could give you great visibility into what is really going on. The Bochs debugger lets you simulate quickly or slowly, pausing whenever you want to look at the contents of memory or the CPU registers. Or, if you wanted to study which parts of a program take the most time, you could use Bochs to measure how often certain pieces of the code were executed. Bochs has been used as a teaching tool in Operating Systems classes, in which students used and modified it to learn how the PC hardware works. As a final project the students had to add a new peripheral device, so they had to learn all about I/O ports, interrupts, and device drivers. In industry, it is used to support legacy applications on modern hardware, and as a reference model when testing new x86-compatible hardware. There may be as many uses of Bochs as there are users. Do you want to run your old DOS games? Or learn how to program under GNU/Linux, without leaving your Windows desktop? Or reverse engineer your printer driver? You decide.
Is Bochs right for me? Bochs is very useful for some applications, and not well suited to others. This section tries to answer the question, "Is Bochs right for me?" Bochs may or may not be right for you, depending on what it is you want to do. Perhaps all you want to do is run one or two applications native to Microsoft Windows on GNU/Linux, or vice-versa. Perhaps your biggest concern is speed and performance. Maybe you don't mind tweaking a few files here and there when you want another application to work in that setting. In cases where the objective is to simulate x86 hardware on an x86, VirtualBox, Wine, and VMware might be your best options. On the other hand, perhaps you have a vital application running on an older operating system that only runs well on old hardware. You are concerned that the life cycle of this hardware is coming to an end, and your backup and restoration hardware and tools no longer suffice for the amount of data that you have. You need to transfer backup disk images over a network, and want to use modern procedures for hardware maintenance. Perhaps the application is important enough to run on a larger computer, such as a 64-bit machine, or even a mainframe. Bochs would be an excellent option in such a scenario. Perhaps your objective is to debug software or hardware drivers. Bochs offers a controlled environment that can better assist you in determining cause and effect relationships. You can take snapshots that show you what is going on behind the scenes. You can isolate the line that caused that crash. You can have multiple images and compare them under a microscope. In these situation, Bochs could save you time and resources. Information Technology changes faster than any other field. It is very easy to forget transitional software that came and went. But history is important to all fields, and to build on the future, it is important to understand the past. Computer programmers, however, do not have the same advantage as an architect, who can, for example, take a trip to Greece and touch a pillar. Much of the history of Computer Science is left on corroding floppies and malfunctioning hardware. Bochs gives you the benefit of having one or more complete environments where you can understand firsthand the behavior of operating systems and programs. This cannot be achieved with an "emulator" such as Wine.
Will it work for me? Whether Bochs works for you depends on your host hardware, host operating system, guest operating system, guest software, and your ability to work in a command-line environment using documentation. There is no wizard to help you through the setup process. You do not get a recovery or installation disk to assist you in the process of installing a guest operating system. Bochs only provides you with the "virtual hardware", and it is up to you to do the rest. Bochs will run on Windows, GNU/Linux, FreeBSD, OpenBSD, or MacOSX. If you are running on x86 hardware, you have a range of choices. Check the installation section for your host platform to see what options Bochs supports on your platform. If the most important factor is speed, you may want to try a virtualization product instead of Bochs (VMware, VirtualBox, QEMU). If you are using a non-x86 machine, then Bochs is one of the few choices for running x86 software. Bochs has been known to work on Solaris (Sparc), GNU/Linux (PowerPC/Alpha), MacOS (PowerPC), IRIX (MIPS), Digital Unix (Alpha), and AIX (PowerPC). You can also find more detailed testing information on the testing status page on the &bochswebsite;.
Bochs License Bochs is copyrighted by MandrakeSoft S.A. Mandriva has a web site at http://mandriva.com and distributed under the GNU Lesser General Public License Complete text of the GNU LGPL is included with the source code in a file called COPYING, and is also here. . The following text appears at the top of every source code file released under the LGPL in the Bochs distribution: Parts of Bochs have specific licenses which are compatible with the GNU Lesser General Public License. Hence each source file contains its own licensing information. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Third Party Software Licensing and Temporary Files Before you install or use any Operating System, BIOS, or other software package within the Bochs PC emulation environment, make sure you are and will be in compliance with all the software licenses pertaining to the software you wish to install. It is completely your responsibility to provide licenses and records on all software that you install and/or use. It is also completely your responsibility to maintain total compliance with all Software Licenses involved. In the process of installing Software within the Bochs PC emulation environment, it may be helpful or necessary to copy or convert files from the original distribution format to a second format to facilitate the installation. You should delete the intermediate files after installation, making certain that only the original distribution files remain.
Features The following table shows the features of Bochs and which platforms they currently work with. Bochs Features Feature Supported? Description configure script Yes Bochs uses GNU autoconf to configure Makefiles and headers. Autoconf helps Bochs to compile on a wide variety of platforms. 386,486,Pentium Emulation Yes Bochs can be configured to emulate one of several families of Intel hardware. Some Pentium features are incomplete, such as SMM (System Management Mode). P6 and later CPU Emulation Yes Bochs can be configured to emulate any P6 family processor including optional MMX and SSEx instructions. x86-64 Extensions Emulation Yes Bochs can be configured to emulate x86-64 with many recent Intel and AMD extensions. Command Line Debugger Yes Powerful command line debugger (optional) that lets you stop execution and examine registers and memory, set breakpoints, etc. GUI Debugger Yes Chourdakis Michael and Bruce Ewing contributed very powerful GUI frontend for Bochs internal debugger. GUI debugger frontend is supported for Win32 and GTK hosts. Floating Point Yes Uses software floating point engine based on SoftFloat floating point emulation library. Enhanced BIOS Yes Implements ElTorito, EDD v3.0, basic APM feature, PCIBIOS features and the PCI interrupt routing table. The latest version of the Bochs BIOS has a 32-bit init for ACPI, SMM and SMP. Bochs also known to work with recent SeaBIOS images. VGA Yes VGA color graphics emulation in a window. VBE (VESA) Support Yes Currently resolutions up to 2560x1600x32bpp are supported. You must enable VBE with the VGA extension option and use the LGPL'd VGABIOS. For more information see . Cirrus Logic video card Yes Cirrus Logic CL-GD5430 ISA or CL-GD5446 PCI video card support. For more information see . Floppy disk Yes Supports floppy disk images on all platforms: 2.88M 3.5", 1.44M 3.5", 1.2M 5.25", 720K 3.5" and 360K 5.25". On Unix and Windows NT/2000/XP, Bochs can access the physical floppy drive. It is also possible to use a local directory as VFAT media (1.44M only). Multiple ATA channels Yes Emulates up to 4 ATA channels. Up to 8 ATA/ATAPI emulated devices can be attached, two per ATA channel. So you can have eight hard disks or seven hard disks and a CD-ROM or four hard disks and four CD-ROMs, or one hard disk and seven CD-ROMs, etc... Hard disk Yes Emulates ATA-6/IDE hard drives via image files. Physical hard disk access is supported on some architecture, but NOT recommended, primarily for safety reasons. With LBA48 support, hard disks up to 255TB are supported, on any platform that support large files access. It is also possible to use a local directory as VFAT drive. CD-ROM Yes Emulates ATAPI-4/IDE CD-ROM. The CD-ROMs can read from an ISO disk image on any platform. On Windows (9x/ME/NT/2000/XP), Linux, SunOS, FreeBSD, NetBSD, OpenBSD, Amiga/MorphOS and MacOSX, Bochs can read from the physical CD-ROM drive. The Bochs BIOS supports booting from the first CD-ROM drive. Keyboard Yes Emulates a PS/2 keyboard with North American key mappings. Optional keyboard layout remapping files are provided to support localized keyboard in X11 (Belgian, Danish, French, German, Italian, Russian, Slovenian, Spanish, Swedish, U.K.). Mouse Yes Emulates a serial, PS/2 or USB mouse with 3 buttons + optional mouse wheel support. Sound card Yes Emulates a Sound Blaster 16 card (ISA, no plug&play) or an ES1370 PCI card. On Windows, Linux, FreeBSD, MacOS 9 and MacOSX, the output can be sent to the host computer's sound system. For the SB16, see for details. Network card Yes Emulates an NE2000 compatible network card (ISA / PCI) or an Intel(R) 82540EM Gigabit Ethernet adapter (PCI). On Windows NT/2000, Linux, FreeBSD, and NetBSD, Bochs will forward packets to and from the operating system so that the guest OS can talk on the physical network. Unfortunately, on some platforms the guest OS can talk to any machine on the network BUT NOT the host machine. On Windows and on systems that allow the TAP or TUN/TAP interface, there is no such limitation. Often the host machine may be configured so the guest OS has access to the internet. On MacOSX, you may download the TUN driver from: Parallel Port Yes Parallel port emulation was added by Volker Ruppert for Bochs 1.3. Data that is sent to the parallel port by the guest OS can be saved into a file or sent directly into the parallel port device (Unix only). Serial Port Yes The serial port (16550A UART emulation) is usable, on GNU/Linux, NetBSD, OpenBSD, FreeBSD and MacOSX as host and guest. On other OSes the emulation is present, but the connection to hard- or software of the host is not implemented yet. Up to 4 ports are available. Gameport Yes Emulates a standard PC gameport. The connection to a real joystick is currently supported on Linux and win32 only. PCI Yes Emulates most of the i440FX PCI chipset. The Host-to-PCI bridge (PMC/DBX), the PCI-to-ISA bridge and the PCI IDE controller (PIIX3) are available. For PCI cards there are 5 PCI slots supported. USB incomplete Three types of host controllers (UHCI, OHCI and xHCI) and the devices 'mouse', 'tablet', 'keypad', 'disk', 'cdrom', 'hub' and 'printer'. are available. Plugging in and removing devices at runtime is possible. Access to real hardware is not implemented yet. Plugins Yes Compiling gui and devices as plugins is supported on Linux, MacOS X, Solaris, Cygwin, MinGW/MSYS and VS2008Ex (workspace provided). PIC Yes Master and slave programmable interrupt controller. CMOS functions Yes Real time clock (RTC) and CMOS RAM are available Dynamic Translation/Virtualization No Because Bochs is designed to be portable, it does not attempt to do any dynamic code translation or virtualization. See for details. Simulate a Multiprocessor Yes Bochs can be configured to simulate up to 255 processor threads. This feature is still experimental, but it can boot several Linux or Windows guests with SMP support. Please note that this does NOT mean that Bochs can run faster on a physical SMP machine. Take advantage of your SMP box No At present, Bochs does not use threads or parallel processing, so it will not run any faster on multiprocessor hardware. Copy and Paste Yes Depending on the host platform, the text-mode screen text can be exported to the clipboard. Text in the clipboard can also be pasted, through Bochs, to the guest OS, as simulated keystrokes.
Supported Platforms The following table shows the supported platforms with a small description and the available display libraries on these platforms. The display library is the code that displays the Bochs VGA screen and handles keyboard and mouse events. Supported platforms Platform Description Display Libraries Unix/X11 X windows has always been well supported because it was Kevin Lawton's main development platform. Bryce Denney maintains the Unix/X11 platform now. Most features and fixes (not all) are tried first in Unix and then ported to the others; see for compile instructions. x, sdl, wx, term, rfb Win32 This port was done by David Ross and is now maintained by Don Becker. You can compile with Microsoft Visual C++, see for compile instructions, or Cygwin, see . win32, sdl, wx, rfb MacOS X Emmanuel Mailliard ported the Macintosh code to MacOS X with Carbon API. Jeremy Parsons (Br'fin) has been maintaining the MacOS X port since March 2002; see for compile instructions. carbon, x, rfb, sdl PowerPC-Macintosh David Batterham ported Bochs to the Mac. He compiled with CodeWarrior Pro R1 (CW12) but has not had time to maintain the Mac port since early 2000. If you have Mac development tools and want to contribute, contact the &devlist;; see for compile instructions. macos Amiga/MorphOS This port is written and maintained by Nicholai Benalal, see for compile instructions. amigaos
FAQ Is Bochs Open Source? Yes! Bochs is released under the GNU LGPL, much thanks to MandrakeSoft (now called Mandriva). How do you pronounce "Bochs"? Phonetically the same as the English word "box". It's just a play on the word "box", since techies like to call their machines a "Linux box", "Windows box", ... Bochs emulates a box inside a box. Who is the author of Bochs? Kevin Lawton is the primary author of Bochs. There have been bug fixes, enhancements, and code contributions from some few hundred people, so it is not possible to list them all. Recently, Kevin has been working on a PC virtualization project called plex86. In Fall 2002, he made contributed some major CPU speedups and helped with integration and debugging of the x86-64 emulation code. Who maintains Bochs now? With Kevin's help, in April 2001, the members of the bochs-developers mailing list set up a new official Bochs site hosted by Source Forge. The admins on this project are Greg Alexander, Don Becker, Christophe Bothamy, Bryce Denney, Volker Ruppert and Stanislav Shwartsman. Tell me about performance when running Bochs. Because Bochs emulates every x86 instruction and all the devices in a PC system, it does not reach high emulation speeds. Users who have an x86 processor and want the highest emulation speeds may want to consider PC virtualization software such as Vmware or VirtualBox (free software). Another related project is QEMU. Does Bochs use a disk partition to install the OS? No. It uses a disk image file, which is simply a large file, like any other file, on your platform's disk. Why can't I use Bochs with my current WinXP installation? Think about this. If you had two different PC's, they would require different hardware drivers. So you may not be able to safely move a disk drive with WinXP on it, from one to the other. Bochs is no different. It emulates a certain set of hardware devices, and requires each OS be configured for those devices. Is there a developer's email list for Bochs? Yes. For instructions on joining, refer to . Is there an IRC channel for Bochs? Yes. You will usually find Bochs developers and users on IRC at irc.freenode.net:6667, channel #bochs. Do you know of any snapshots of Bochs running Windows? Yes! Look for "Screen Shots" on &bochs-sf-net; or on other Bochs sites. Does Bochs support a CD-ROM? Yes, a CD-ROM is supported in Linux, Windows, and most BSDs. The CD-ROM drivers for Bochs allow the guest operating system to access the host operating system's CD-ROM data directly. Does Bochs support a sound device? Yes, Bochs emulates a Sound Blaster 16 card (ISA, no plug&play) or an ES1370 PCI. Output to the host sound system is implemented for some platforms. See for details. Does Bochs support a network card? Yes. Bochs emulates an NE2000 compatible network card (ISA / PCI) or an Intel(R) 82540EM Gigabit Ethernet adapter (PCI). Networking is not supported on all platforms. See for details. What applications are known to run inside of Bochs? Well, lot's of different OS's run inside of Bochs, so thousands. I'm assuming you are asking about Windows programs. To give you a few, the following ones from the Winstone'98 tests worked: Access 97, CorelDRAW! 7, Excel 97, Lotus 1-2-3 97, Word 97, PowerPoint 97, Quattro Pro 7, WordPerfect 7. Also, I've compiled an entire OS kernel inside Bochs before. Not to mention, running DOOM, though at then-pathetic speeds. I am new to Bochs, how do I start? You should read first. Next, you can check if there specific instructions on how to install your (guest) OS inside of Bochs.
Release Notes The change log is stored in the Bochs source code in a file called CHANGES. Click here to see the latest version of the CHANGES file. The link above is provided by Source Forge and might change one day. If it stops working, you can download the current source code with SVN and read the CHANGES file there. Installation
Downloading Bochs You can download Bochs from our web site at &bochs-sf-net;. First, you need to choose what version to get: a recent release or a development version. If you trying to get things working for the first time, a release version is recommended since it has been tested the most. The development versions (sometimes called SVN snapshots) may have some newer bug fixes and new features, but have not been tested as much as the releases. Second, you can choose to compile Bochs from source code or install a binary (if one is available for your platform). Binary packages will be quicker to install, and most include a small demo of a guest operating system called DLX Linux to get you started. However, some features can only be enabled if you compile Bochs yourself, for example the Bochs debugger. For multiuser systems, you will probably need system administrator privileges (root) to install a binary package. If you decide to get a binary, download it to your hard disk, uncompress it, then go to the section called Installing a Binary for more information. If you are going to compile Bochs yourself, you need the gzipped tarball containing the source code, called bochs-version.tar.gz. For Windows and Mac, the prebuilt Makefiles are separate, so also get the Makefiles for your platform. To unpack a compressed TAR file A TAR file is a single file that contains many files packed inside. Bochs TAR files are compressed with a program called gzip, and another program called gunzip is used to uncompress them. on a Unix machine On Windows, look for software called WinZip to unpack the TAR. , type gunzip -c bochs-version.tar.gz | tar -xvf - This creates a directory called bochs-version full of files. This directory will be referred to as &bochsdir;. Go into &bochsdir; and you are ready to compile. Instructions for compiling Bochs are in the section, Compiling Bochs. Alternatively, you can also obtain the sources for any Bochs version using SVN. See the SVN instructions for details.
Tracking the source code with SVN SVN (Subversion) is a tool used by many software developers to manage changes within their source code tree. SVN provides the means to store not only the current version of a piece of source code, but a record of all changes (and who made those changes) that have occurred to that source code. Use of SVN is particularly common on projects with multiple developers, since SVN ensures changes made by one developer are not accidentally removed when another developer posts their changes to the source tree. The Bochs source code and documentation are available using SVN You can download SVN software and documentation from subversion.apache.org. .
Checking out Bochs When you have SVN installed, the first step is to do a checkout. The initial checkout command is long and ugly, but usually you only have to do it once. The example below shows the SVN checkout process of the Bochs trunk in Unix. On the Windows platform, you can download a SVN client from subversion.apache.org, or use SVN within Cygwin Cygwin is an open source Unix-like environment for Windows platforms, available at www.cygwin.com. .
Checking out Bochs in SVN user$ svn co https://bochs.svn.sourceforge.net/svnroot/bochs/trunk/bochs bochs A bochs/ltdl.c A bochs/Makefile.in A bochs/bochs.h . . (This might take a few minutes, depending on your network connection.) . A bochs/install.sh U bochs Checkout, Revision 10754. user$ cd bochs user$ ls aclocal.m4 cpu logio.cc pc_system.cc bios cpudb.h ltdl.c pc_system.h bochs.h crc.cc ltdlconf.h.in plugin.cc build disasm ltdl.h plugin.h bx_debug doc ltmain.sh README bxversion.h.in docs-html main.cc README-plugins bxversion.rc.in extplugin.h Makefile.in README.rfb CHANGES fpu memory README-wxWindows config.cc gdbstub.cc misc TESTFORM.txt config.guess gui msrs.def TODO config.h.in host osdep.cc win32_enh_dbg.rc config.sub install-sh osdep.h win32res.rc configure instrument param_names.h wxbochs.rc configure.in iodev PARAM_TREE.txt COPYING load32bitOShack.cc patches user$ _
This is just an example output of a checkout of specific version of the Bochs trunk and folder. Depending on the checkout command and revision, you most likely will see more/other files. If you have write access to the Bochs SVN tree, see the Developers Guide See the Developers Guide and/or look at SourceForge's Subversion documentation, for instructions. for details. The SVN checkout process (above) gives you a directory called bochs that contains the very latest source code. I will refer to this directory as &bochsdir;. In each subdirectory directory there's also a directory called ".svn" which tells the SVN software where the code was checked out, what version you have, and where to go for future updates.
Getting the Latest Version Most developers use SVN to always give them the latest source code. The minute that any developer checks in a change, they are available to everyone else through SVN. You just have to type svn update in the &bochsdir; directory, and SVN will retrieve any files and directories that have been changed since you did a checkout. If you update regularly, each update takes a short time because it downloads only the files that changed. See also Getting a release version. The svn update command tells you if any new files have been downloaded from the server, and it also tells you if you have modified any of the SVN-controlled files. As it checks through the source directories, it will list files that have changed, with a single letter before the name that tells the status of that file. The most common status letters are listed below. Status letters in a SVN update Letter Meaning Description ? unknown This file is in your bochs directory, but SVN does not know anything about it. For example, when you compile Bochs, any files created during the build process appear as ?. U update SVN downloaded a new version of this file because it changed on the server, usually because someone else did a checkin. A added SVN downloaded a newly added file from the server. D deleted This file has been deleted on the server and SVN removed it from your local copy. C conflict You have changed this file on your disk, but this change conflicts with a change that was checked in. Conflicts occur when two people change the same line of code in different ways. You need to edit the conflicting file(s) and clean it up by hand. Or, sometimes it's easiest to discard your own edits and download a fresh copy, by deleting the conflicting file and running svn update again.
Getting a Release Version You can also use the SVN checkout command to get the Bochs source code for any release since March 2000. The command is user$ svn co https://bochs.svn.sourceforge.net/svnroot/bochs/tags/tagname bochs The tagname tells which release you want, and it can be one of the following: Bochs Release Tags Bochs version Release tag for SVN 2.5.1 (bugfix) REL_2_5_1_FINAL 2.5 REL_2_5_FINAL 2.4.6 REL_2_4_6_FINAL 2.4.5 REL_2_4_5_FINAL 2.4.2 REL_2_4_2_FINAL 2.4.1 REL_2_4_1_FINAL 2.4 REL_2_4_FINAL 2.3.7 REL_2_3_7_FINAL 2.3.6 REL_2_3_6_FINAL 2.3.5 REL_2_3_5_FINAL 2.3 REL_2_3_FINAL 2.2.6 (intermediate2) REL_2_2_6_FINAL 2.2.5 (intermediate1) REL_2_2_5_FINAL 2.2.1 (bugfix1) REL_2_2_1_FINAL 2.2 REL_2_2_FINAL 2.1.1 (bugfix1) REL_2_1_1_FINAL 2.1 REL_2_1_FINAL 2.0.2 (bugfix2) REL_2_0_2_FINAL 2.0.1 (bugfix1) REL_2_0_1_FINAL 2.0 REL_2_0_FINAL 1.4.1 (bugfix1) REL_1_4_1_FINAL 1.4 REL_1_4_FINAL 1.3 REL_1_3_FINAL 1.2.1 (bugfix1) REL_1_2_1_FINAL 1.2 REL_1_2_FINAL 1.1.2 (bugfix3) REL_1_1_2_BASE 1.1.1 (bugfix2) REL_1_1_1_BASE 1.1 (bugfix1) REL_1_1_BASE
More about SVN Entire books have been written on SVN, so there's no sense in duplicating it all here in the Bochs documentation. Some sources of additional information are listed below. The subversion.apache.org site has tons of SVN FAQs and documentation. A German SVN FAQ is available at University of Muenster.
Installing a Binary This section is divided up by platform, since installing a binary package is different on different platforms.
Windows The Bochs binaries for Windows are distributed in an EXE installer package. The Bochs installer can be started like any other Windows program and it brings up the installation wizard. Here you can select the destination folder and the installation options. The wizard installs the files and creates the registry keys, start menu and desktop links. Previous releases of Bochs were distributed as ZIP packages, too. These packages contained the same set of files as the installer package from the same version. If you are new to Bochs you should try out the DLX Linux demo distributed with Bochs. The installation wizard has created a link on the desktop if you decided to install the demo. If you doubleclick the icon two windows will appear: one is the Bochs Display window, and the other is text window that is used for the runtime configuration and for log messages if no logfile is specified. You can find more information on the DLX Linux demo in the next section below the DLX Linux screenshot. Files in Bochs directory (Windows version) File Description BIOS-bochs-latest default ROM BIOS image for Bochs BIOS-bochs-legacy ROM BIOS image without 32-bit init code bochs.exe the main Bochs executable bochs.ico the Bochs icon (used for links in start menu and on the desktop) bochsdbg.exe the main Bochs executable with debugger enabled bochsrc-sample.txt sample Bochs configuration file bxcommit.exe tool for committing redologs to flat disk images bximage.exe tool for making new disk images CHANGES.txt what has changed between versions COPYING.txt copy of the LGPL license LICENSE.txt Bochs license information README.txt the read-me file from the source distribution. TODO.txt the TODO file from the source distribution. niclist.exe tool to find out the network interface name penguin.ico the Linux logo (used for the DLX link in start menu) sb16ctrl.exe tool to control sb16 in Bochs sb16ctrl.txt examples of sb16ctrl commands VGABIOS-elpin-2.40 VGA BIOS image for Bochs VGABIOS-elpin-LICENSE.txt license for VGA BIOS VGABIOS-lgpl-latest LGPL'd VGA BIOS image for Bochs VGABIOS-lgpl-latest-debug LGPL'd VGA BIOS image for Bochs with debug output to the logfile VGABIOS-lgpl-latest-cirrus LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled VGABIOS-lgpl-latest-cirrus-debug LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile VGABIOS-lgpl-README.txt readme for the LGPL'd VGA BIOS uninstall.exe uninstall program for Bochs (created by the installation wizard) dlxlinux\ directory containing DLX linux sample disk image and configuration files dlxlinux\readme.txt description of DLX linux dlxlinux\bochsrc.txt Bochs configuration file for DLX dlxlinux/hd10meg.img disk image file (10 meg) dlxlinux\start.bat Run this BAT file to try out DLX Linux inside Bochs! dlxlinux\testform.txt Form for reporting success or failure doc\index.html a local copy of all Bochs documentation (online copy) keymaps\*.map keymap tables (on Windows used for the paste feature only)
Linux RPM RPM stands for "RedHat Package Manager." An RPM is a compressed file containing files to be installed on your system. Many Linux distributions, not just RedHat ones, can install files from an RPM. First, download the Bochs RPM for your architecture to your computer. For example, if you have an Intel-compatible computer, be sure to get the RPM that says "for Linux x86 distributions" or "i386". Once you have the package on your local disk, you should become the root user and install it as follows Many distributions have their own RPM installer program, often graphical, and they should work ok. It is helpful to be able to see the text output from RPM, so if you use a fancy RPM installer, be sure to find the text output and check that it looks correct. :
Installing an RPM in Linux user$ su Password: root# ls -l bochs-2.5.x86_64.rpm -rw-r--r-- 1 user users 2628643 Nov 27 17:20 bochs-2.5.x86_64.rpm root# rpm -i bochs-2.5.x86_64.rpm root# exit user$ _
All RPM installations are done as the root user because they require permission to update system files and directories. If you do not have root access you need to compile Bochs in your home directory. RPM installation can fail for a few reasons. It will fail if you already have a Bochs package installed. In this case, try upgrading the old package to the new package with rpm --upgrade NAME.i386.rpm. Another potential problem is missing RPM dependencies. If you are getting errors about missing files or RPMs, then first you should try to install the RPMs that provide the missing pieces. If that cannot be done, download the source RPM and build a new binary RPM that is appropriate for your platform. The command is rpmbuild --rebuild NAME.src.rpm. As a last resort, you can run rpm with the --nodeps option to ignore dependencies and install it anyway, but if it is missing important pieces it may not run properly. The Bochs RPM installs four new commands and associated manual pages: bochs, bochs-dlx, bximage and bxcommit. First, let's try out the DLX Linux demo by typing bochs-dlx. user$ bochs-dlx --------------------------------------------------------------- DLX Linux Demo, for Bochs x86 Emulator --------------------------------------------------------------- Checking for bochs binary...ok Checking for DLX linux directory...ok Checking for /bin/gzip...ok Checking for /usr/users/bryce/.bochsdlx directory... --------------------------------------------------------------- To run the DLX Linux demo, I need to create a directory called /usr/users/bryce/.bochsdlx, and copy some configuration files and a 10 megabyte disk image into the directory. --------------------------------------------------------------- Is that okay? [y/n] y Copying /usr/share/bochs/dlxlinux/bochsrc.txt -> /usr/users/bryce/.bochsdlx/. Copying /usr/share/bochs/dlxlinux/README -> /usr/users/bryce/.bochsdlx/. Copying /usr/share/bochs/dlxlinux/testform.txt -> /usr/users/bryce/.bochsdlx/. Uncompressing /usr/share/bochs/dlxlinux/hd10meg.img.gz -> /usr/users/bryce/.bochsdlx/hd10meg.img Entering /usr/users/bryce/.bochsdlx Running bochs ======================================================================== Bochs x86 Emulator 2.4.6.svn Build from SVN snapshot, after release 2.4.6 Compiled on Oct 20 2011 at 19:40:05 ======================================================================== Then you get a new X11 window containing the VGA display of the simulated machine. First you see the VGA BIOS screen, then Linux uncompresses and boots, and you get a login prompt. Type "root" and ENTER to log in to DLX linux.
Screenshot of Bochs running DLX Linux
Booting is complete when you see "dlx login:" and a cursor. At this login prompt, type "root". On UNIX systems, root is the system admin user. There is no password for root on this sample disk image, so it lets you log in without typing any password. Now you should see a UNIX prompt, and you can begin to type UNIX commands. Welcome to DLX V1.0 (C) 1995-96 Erich Boehm (C) 1995 Hannes Boehm dlx login: root Linux 1.3.89. dlx:~# pwd /root dlx:~# cd / dlx:~# ls bin/ etc/ lost+found/ root/ usr/ boot/ fd/ mnt/ sbin/ var/ dev/ lib/ proc/ tmp/ zip/ dlx:/# df Filesystem 1024-blocks Used Available Capacity Mounted on /dev/hda1 10060 2736 6005 29% / dlx:/# _ When you get tired of playing with DLX Linux, just type "reboot" in the Bochs window to shut down the DLX Linux operating system, and when it starts to reboot again press the "Power" button at the top of the Bochs display to end the application. Here is a list of the files that are installed by the RPM, and a brief description of each one. Files in RPM package File Description /usr/share/doc/bochs/CHANGES what has changed between versions /usr/share/doc/bochs/COPYING copy of the LGPL license /usr/share/doc/bochs/LICENSE Bochs license information /usr/share/doc/bochs/README the read-me file from the source distribution. /usr/share/doc/bochs/TODO the TODO file from the source distribution. /usr/bin/bochs the main Bochs executable /usr/bin/bximage tool for making new disk images /usr/bin/bxcommit tool for committing redologs to flat disk images /usr/lib/bochs/plugins/* device and gui plugins for Bochs (plugin version only) /usr/share/doc/bochs/bochsrc-sample.txt sample Bochs configuration file /usr/share/man/man1/* man pages for bochs, bochs-dlx, bximage and bxcommit /usr/share/man/man5/* man page for bochsrc /usr/share/doc/bochs/index.html a local copy of all Bochs documentation ( Online copy ) /usr/share/bochs/BIOS-bochs-latest default ROM BIOS image for Bochs /usr/share/bochs/BIOS-bochs-legacy ROM BIOS image without 32-bit init code /usr/share/bochs/VGABIOS-elpin-2.40 VGA BIOS image for Bochs /usr/share/bochs/VGABIOS-elpin-LICENSE license for VGA BIOS /usr/share/bochs/VGABIOS-lgpl-latest LGPL'd VGA BIOS image for Bochs /usr/share/bochs/VGABIOS-lgpl-latest-debug LGPL'd VGA BIOS image for Bochs with debug output to the logfile /usr/share/bochs/VGABIOS-lgpl-latest-cirrus LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled /usr/share/bochs/VGABIOS-lgpl-latest-cirrus-debug LGPL'd VGA BIOS image for Bochs with the Cirrus extension enabled and debug output to the logfile /usr/share/bochs/VGABIOS-lgpl-README readme for the LGPL'd VGA BIOS /usr/bin/bochs-dlx run this script to try out DLX Linux inside Bochs! /usr/share/bochs/dlxlinux/ directory containing DLX linux sample disk image and configuration files /usr/share/bochs/dlxlinux/readme.txt description of DLX linux /usr/share/bochs/keymaps/*.map keymap tables for X11 and SDL
MacOS X DMG This was contributed by Aard Vark in January 2003 The MacOS X binary distribution is a mountable disk image (.dmg file). Once you've downloaded the binary distribution file, just double click on it to automatically unpack the archive and mount the volume on the desktop. An icon will appear exactly as if you'd inserted a CD-ROM or removable storage device, and a finder window containing the volume should automatically open. It is likely to have an odd name such as _dmg_top, but don't worry about that. Copy the Bochs-2.0 (or whatever version) folder from the disk image onto your hard disk. Either Home or Applications would be sensible places to put it. Because the disk image is mounted read only, you can't run the included dlxlinux guest OS until you've copied it to the hard disk. Once you've installed the binaries, it's probably a good idea to drag the _dmg_top volume to trash to unmount it, so you don't get confused and try to run bochs from there. Then open the bochs folder from wherever you installed it. The MacOS X version of bochs requires a terminal window to run. If you just double click on the Bochs icon, you'll get an error message telling you to double click on "bochs.scpt" to start Bochs in a new terminal window. You'll need to configure Bochs before you will get very far with the bochs.scpt in the top folder, so to try out bochs open the dlxlinux folder and double click on the bochs.scpt icon inside. This will open a new terminal window which will contain the Bochs startup messages, and a configuration menu. The default option is [5], which starts the simulation, so press enter to do so. You will then get a new window containing the VGA display of the simulated machine. The new window will probably appear behind the current terminal window, so either click on the bochs icon in the dock or the simulation window to bring it to the front. If you're quick enough you'll then see the VGA BIOS screen, then Linux uncompresses and boots, and you get a login prompt. Type "root" and ENTER to log in to DLX Linux. Once you've finished playing with DLX Linux, just type "reboot" in the Bochs window to shut down the DLX Linux operating system, and when it starts to reboot again press the "Power" button in the "MacBochs Hardware Controls" window (it's the circle containing a vertical bar at the far right - have a look at the Linux screenshots, since the Mac version doesn't seem to have descriptions or tool-tips).
Compiling Bochs
Standard Compile Bochs is written in C++, so you need a C++ compiler on your system. Most platforms have been tested with GNU gcc/g++, but other compilers are known to work too. By now, you should have unpacked your source TAR file or checked out Bochs from SVN. If not, you can return to Downloading Bochs for details. The top level directory of the source code will be referred to as &bochsdir;. (&bochsdir; contains the files bochs.h and main.cc and subdirectories cpu and bios.) The standard compile process has three basic steps: configure, make, and make install. Each step is described in a separate section below. The standard compile process is used on all Unix machines, MacOS X, and Cygwin (win32). There are separate instructions for compiling for Win32 with Microsoft VC++.
Configure There is a script called configure which tests your machine, C/C++ compiler and libraries to discover what settings should work on your system. If you run configure with no arguments after it, defaults will be used for all settings. To change the settings, you can run configure with options that override the defaults. You can get a list of valid configure options by typing configure --help. One useful configure option is --prefix=directory, which sets the directory in which Bochs will be installed. All the possible configure options are documented in a later section. Among other things, the configure script tries to detect your platform and which compile options to use. If you want to control this, set these environment variables before running configure: CC, CXX, CFLAGS, CXXFLAGS. Here is an example that sets the environment variables, using bash/ksh The syntax for bash and ksh is given. In csh and variants, use the syntax setenv VARIABLE value to change environment variables. Do not use an equal sign for csh! syntax: export CC=egcs export CXX="$CC" export CFLAGS="-Wall -O2 -m486 -fomit-frame-pointer -pipe" export CXXFLAGS="$CFLAGS" Once the configure script knows what options are selected, it creates a Makefile in every source code directory, and creates $BOCHS/config.h with all the option values written as preprocessor #defines. Now the sources are ready to compile.
Configure Shortcut Scripts In the Bochs source directory, you will see a series of scripts called .conf.platform. These scripts run the configure script for you, with a set of options that are appropriate for that platform. It is not necessary to use the shortcut scripts; they are simply there to show you an example that the developers have used. Some of these scripts have been used to build official binary packages. If a shortcut script is "almost right" for you, just edit it and then run it! If you run a shortcut script, you don't need to run configure manually. Run a shortcut script using Bourne shell, like this: sh .conf.win32-vcpp These .conf.platform have been tested in recent Bochs versions: .conf.linux .conf.sparc .conf.macos .conf.macosx .conf.win32-vcpp .conf.win32-cygwin
Make The make command compiles Bochs. Make is a program used by many software projects that reads the &Makefile; in each source directory and follows the instructions that it finds there. A &Makefile; tells which files depend on which other files, what commands to use to compile and link the code, and more. After you have finished the configure step, just type make to build the source code. The reason that make is so popular is that it is smart about when to compile and when not to compile. If you run make once, it compiles every file. But when you run it again, it checks to see if any source files have been modified; if not, there's nothing to do! For example, the &Makefile; says that main.o depends on main.cc. Knowing this, it will only compile main.cc if it is newer than main.o. Of course, make can only do the right thing if the &Makefile; lists all the dependencies correctly, so human error can sometimes lead make astray. If make refuses to build something that you think it should, or you are getting strange compile errors, try doing make all-clean and then make again. All-clean means to clean up the compiled files in every subdirectory, while make clean means to clean up just the current directory This is different from the terminology of some other projects, and it may cause confusion. Sometimes "clean" implies that all subdirectories are affected. . However, it's important to note that make all-clean leaves the configuration intact. You do not have to run configure again. If you're really in the mood for cleaning, make dist-clean erases all the configuration information too. In theory, after a dist-clean your directory should look much like when you first untarred it or checked it out. There's usually some extra stuff lying around, but the &Makefile; tries at least to erase any files that it created.
Make Install Once the program has been built, the next step is typically to run make install to copy the executables, documentation, and other required files into a public place so that all users can use it. By default the files are copied to some directories in /usr/local. The following tables shows the directories and their contents. &FIXME; make install_dlx option Installed files bin binary executables (bochs, bxcommit, bximage) lib/bochs/plugins plugins (if present) man/man1 manpages for installed binaries man/man5 manpage for the config file (bochsrc) share/bochs BIOS images, VGABIOS images, keymaps share/doc/bochs HTML docs, license, readme, changes, bochsrc sample
Configure Options This section describes the configure options for Bochs. Perhaps the most important option is , since it gives you a list of all the other options. The configure script will detect your platform and choose the default GUI for your platform. If the default choice is not what you want, use the options to override the default. The options in the first table tell which GUI library is the default for each platform. Starting in version 2.0, you can use multiple options at once to compile with multiple display libraries, and then choose between them at runtime with the display_library option in the configuration file. Or, you can let the configure script detect which libraries are on your system and use them all, by configuring with . The concept of platform detection and default GUIs was added in Bochs 1.4. In Bochs 1.3 and before, the X11 GUI was always the default. Defaults by Platform Platform Default GUI Extra compile flags win32, Cygwin or MinGW/MSYS --with-win32 If using nmake method, compile using cl /nologo /MT /W3 /EHs-c- /DNDEBUG /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS. If using Visual C++ workspace, see the workspace file for compile settings. See Compiling on Win32 with Microsoft VC++ for instructions. MacOS X or Darwin --with-carbon -fpascal-strings -fno-common -arch ppc -Wno-four-char-constants -Wno-unknown-pragmas -Dmacintosh MacOS 9 or before --with-macos none AmigaOS --with-amigaos none any other platform --with-x11 none
Configure Options to Select the Display Library (optional) Option Comments --with-x11 Use X windows user interface. On many operating systems, Bochs will use X windows by default. --with-win32 Use the native Win32 GUI. This is the default on win32 platforms. --with-carbon Compile for MacOS X with the Carbon GUI. See the .conf.macosx file for the correct MacOS X compile options. --with-amigaos Compile for Amiga MorphOS. This code is written by Nicholai Benalal. --with-rfb Enable support for the RFB protocol to talk to AT&T's VNC Viewer. Refer to for details. --with-sdl Enable support for the SDL GUI interface; see . --with-term Use text-only gui with curses library. Almost certainly won't work right with the debugger or the control panel. --with-macos Use Macintosh/CodeWarrior environment. This is for running configure on a platform which supports running configure, so that you may then transfer the configured code over to the real compile environment. --with-wx Enable support for wxWidgets configuration and display interface; see . --with-svga Use SVGALIB library for Linux. This allows a full-screen text and graphics display without X windows. The SVGALIB port was written by Igor Popik. --with-nogui No native GUI; just use blank stubs. This is if you don't care about having video output, but are just running tests. --with-all-libs Automatically detect which libraries are installed on your system and enable them. This option is still experimental; it might enable libraries that are not usable and cause the compile to fail. If you have trouble, just list the options for the specific display libraries that you want.
The remaining options can generally be used with any GUI. For each option such as , you can also write to explicitly turn it off. Configure Options Option Default Comments --enable-cpu-level={} 6 Select which CPU level to emulate. Choices are 3,4,5,6 which mean to target 386, 486, Pentium, or Pentium Pro and later emulation. --enable-smp no Compile in support for SMP simulation. This allows you to boot Linux and maybe other OSes in SMP mode, and bochs will simulate all the different CPUs and communication between them. Do not expect this option to speed up your simulation! On the contrary, it has to spend extra time simulating the different CPUs (even if they're mostly idle) and the communication between them. Use it to try out an SMP OS if you don't have an SMP machine, or to debug SMP OS drivers. Refer to for more details on SMP in Bochs. --enable-fpu yes If you want to compile Bochs to make use of the FPU emulator written by Stanislav Shwartsman, use this option. --enable-3dnow no 3DNow! instruction set support (incomplete) --enable-x86-64 no Add support for x86-64 instruction set, written by Peter Tattam and Stanislav Shwartsman. --enable-vmx no Intel Virtualization Extensions (VMX) support --enable-svm no AMD SVM (Secure Virtual Machine) extensions emulation support --enable-avx no AVX instructions support --enable-x86-debugger no X86 debugger support. If the software you run in bochs needs to use the x86 hardware debugging facilities such as DR0..DR7, instruction and data breakpoints etc., then you should use this option. Otherwise don't use it, as it will slow down the emulation. --enable-monitor-mwait no MONITOR/MWAIT instructions support (still experimental) --enable-alignment-check yes if cpu level >= 4 support for alignment check in the CPU and #AC exception --enable-misaligned-sse no support for AMD's misaligned SSE extension --enable-configurable-msrs no support for user configurations of emulated MSR registers (see example in msrs.def) --enable-long-phy-address no support for guest physical address larger than 32 bit --enable-a20-pin yes support for the A20 pin --enable-large-ramfile yes support for guest memory larger than the host supports --enable-cdrom yes Enable use of a real CDROM. The cdrom emulation is always present, and emulates a drive without media by default. You can use this option to compile in support for accessing the media in your workstation's cdrom drive. The supported platforms are Linux, Solaris, FreeBSD, OpenBSD, MacOS X and Windows. For other platforms, a small amount of code specific to your platform must be written. --enable-sb16 no Enable Sound Blaster emulation. The lowlevel sound interface is autodetected. See section Sound Blaster 16 Emulation for supported platforms and more info. This option also enables the standard PC gameport which is a part of the SB16. If you don't want to use it, you might use . --enable-es1370 no Enable ES1370 sound emulation. Just like the SB16 option, the lowlevel sound interface is autodetected and the gameport is turned on. --enable-gameport no Enables the standard PC gameport. This option is only necessary if you want to have a gameport, but no SB16 (see above). The connection to a real joystick is currently supported on Linux and win32 only. --enable-idle-hack no Enables Roland Mainz's experimental idle code, which is intended to keep Bochs from always using 100% of CPU time. When Bochs is waiting around for an interrupt, the idle code uses a select() loop and some X11 tricks to wait until user input arrives. This is designed to keep Bochs responsive while still yielding to other processes when Bochs is idle. It only works with X11 or term GUI. --enable-ne2000 no Enable NE2000 network card support. This requires a low-level component to be written for each OS. The NE2000 option is only supported on FreeBSD, OpenBSD, Linux, and Windows 9x/NT/2K/XP. When enabled and configured, the NE2000 device model can talk to any computer on the network EXCEPT FOR the local host. Exception: Under most circumstances, Bochs can talk to the local host on Windows, and in the ethertap interface for Linux. --enable-pnic no Enable PCI pseudo NIC (network card) support. --enable-e1000 no Enable Intel(R) 82540EM Gigabit Ethernet adapter support. --enable-clgd54xx no Enable Cirrus Logic GD54xx (CL-GD5430 ISA or CL-GD5446 PCI) video card support. For more information see . --enable-plugins no Plugins are shared libraries that can be loaded on demand. Example: the serial device is implemented as a plugin. In Unix, the serial plugin is called libbx_serial.so. When Bochs reads its configuration file, if the serial device is enabled it loads libbx_serial.so. See the Features section for supported platforms. --enable-repeat-speedups no enable support repeated I/O and memory copy speedups --enable-fast-function-calls no enable support for fast function calls (gcc on x86 only) --enable-handlers-chaining no enable support for handlers chaining optimization --enable-all-optimizations no Turn on the enables for all speed optimizations that the developers believe are safe to use: --enable-repeat-speedups, --enable-fast-function-calls, --enable-handlers-chaining. --enable-debugger no Compile in support for Bochs internal command-line debugger. This has nothing to do with x86 hardware debug support. It is a more powerful and non-intrusive native debugger. Enabling this will of course slow down the emulation. You only need this option if you know you need it. After you have run ./configure, you may want to edit config.h to customize the debugger further; see for more information. --enable-debugger-gui yes if debugger is on Enable support for the gui frontend of the Bochs debugger. This feature is supported on Windows hosts and on hosts with GTK2 installed. --enable-readline detected by configure Compile the debugger with the GNU readline library, which gives command line editing and history. --enable-gdb-stub no Enable support for the remote GDB stub. See Using Bochs and the remote GDB stub. NOTE: This feature cannot be used if the Bochs debugger is also enabled. --enable-disasm yes Compile in support for built-in disassembler. Bochs has a built-in disassembler, which is useful if you either run the built-in debugger (), or want disassembly of the current instruction when there is a panic in bochs. --enable-iodebug yes if debugger is on Dave Poirier has written an experimental interface to the debugger using I/O ports, so that software running in the guest OS can access features of the debugger. You only want this option if you are developing guest OS code for use in Bochs. In other words, most people don't. Also, it should only be used with . See the developer documentation for details. --enable-pci no Enable limited i440FX PCI support. This is still incomplete, but usable. --enable-pcidev no Enable PCI host device mapping support. This requires to be set as well as Linux 2.4, 2.6 or 3.x as host. --enable-usb no Enable i440FX PCI USB support (UHCI). The host controller with 2-port root hub and 6 USB device types are available. --enable-usb-ohci no Enable USB OHCI support. The host controller with 2-port root hub is available (USB device types: same as UHCI). --enable-usb-xhci no Enable experimental USB xHCI support. The host controller with 4-port root hub is available (USB device types: same as UHCI). --enable-raw-serial no Enable support for the serial port emulation to access to the host's serial port. This feature is partly implemented for Windows hosts only. --enable-docbook detected Build the docbook documentation in doc/docbook. The configure script will enable this option automatically if you have a program called docbook2html installed. --enable-instrumentation= no Compile in support for instrumentation. This allows you to collect instrumentation data from bochs as it executes code. You have to create your own instrumentation library and define the instrumentation macros (hooks in bochs) to either call your library functions or not, depending upon whether you want to collect each piece of data. --enable-xpm yes Enables the check for the XPM library. This option is only valid if the x display library is enabled (). --enable-show-ips yes Enables logging of measured IPS, see the ips parameter of the cpu option. --enable-logging yes By default, Bochs generates logfile output that can be configured with bochsrc options and at runtime. Use to turn off this feature completely. --enable-assert-checks yes if debugger is on BX_ASSERT event causes a panic on assertion failure if enabled (logging feature must be enabled, too). --enable-cpp no Use .cpp as C++ suffix. Renames all the .cc files to .cpp for use with compilers which want that, like older MS C++ compilers. Don't use this option unless you know you need it.
Transcript of Successful Compilation This example shows the output of a compilation and installation on Linux. user$ ls -l bochs-2.5.tar.gz -rw-r--r-- 1 user users 4117999 27. Nov 17:14 bochs-2.5.tar.gz user$ gunzip -c bochs-2.5.tar.gz | tar -xvf - bochs-2.5/ bochs-2.5/.conf.sparc bochs-2.5/build/ bochs-2.5/build/macosx/ bochs-2.5/build/macosx/pbdevelopment.plist bochs-2.5/build/macosx/make-dmg.sh . . . bochs-2.5/memory/memory.cc bochs-2.5/memory/misc_mem.cc bochs-2.5/memory/Makefile.in user$ cd bochs-2.5 user$ ./configure --enable-cpu-level=6 checking build system type... x86_64-unknown-linux-gnu checking host system type... x86_64-unknown-linux-gnu checking target system type... x86_64-unknown-linux-gnu checking if you are configuring for another platform... no checking for standard CFLAGS on this platform... checking for gcc... gcc . . . config.status: creating build/win32/nsis/bochs.nsi config.status: creating host/linux/pcidev/Makefile config.status: creating config.h config.status: creating ltdlconf.h user$ make cd iodev && \ make libiodev.a make[1]: Entering directory `/home/volker/Archiv/test/bochs-2.5/iodev' g++ -c -I.. -I./.. -I../instrument/stubs -I./../instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES devices.cc -o devices.o g++ -c -I.. -I./.. -I../instrument/stubs -I./../instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES virt_timer.cc -o virt_timer.o g++ -c -I.. -I./.. -I../instrument/stubs -I./../instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES slowdown_timer.cc -o slowdown_timer.o g++ -c -I.. -I./.. -I../instrument/stubs -I./../instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES pic.cc -o pic.o . . . echo done done /bin/sh ./libtool --mode=link g++ -o bochs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -DBX_SHARE_PATH='"/usr/local/share/bochs"' -export-dynamic logio.o main.o config.o load32bitOShack.o pc_system.o osdep.o plugin.o crc.o \ iodev/libiodev.a cpu/libcpu.a cpu/cpudb/libcpudb.a \ memory/libmemory.a gui/libgui.a \ disasm/libdisasm.a \ fpu/libfpu.a \ -lSM -lICE -lX11 -lXpm -lXrandr \ \ \ \ \ -lm mkdir .libs g++ -o bochs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES -DBX_SHARE_PATH=\"/usr/local/share/bochs\" logio.o main.o config.o load32bitOShack.o pc_system.o osdep.o plugin.o crc.o -Wl,--export-dynamic iodev/libiodev.a cpu/libcpu.a cpu/cpudb/libcpudb.a memory/libmemory.a gui/libgui.a disasm/libdisasm.a fpu/libfpu.a -lSM -lICE -lX11 -lXpm -lXrandr -lm gcc -c -I. -I./. -Iinstrument/stubs -I./instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES ./misc/bximage.c -o misc/bximage.o /bin/sh ./libtool --mode=link g++ -o bximage -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES misc/bximage.o g++ -o bximage -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES misc/bximage.o gcc -c -I. -I./. -Iinstrument/stubs -I./instrument/stubs -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES ./misc/bxcommit.c -o misc/bxcommit.o /bin/sh ./libtool --mode=link g++ -o bxcommit -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES misc/bxcommit.o g++ -o bxcommit -g -O2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILES misc/bxcommit.o user$ su root# make install cd iodev && \ make libiodev.a make[1]: Entering directory `/home/volker/Archiv/test/bochs-2.5/iodev' . . . for i in CHANGES COPYING README TODO; do if test -f $i; then install -m 644 $i /usr/local/share/doc/bochs; else install -m 644 ./$i /usr/local/share/doc/bochs; fi; done rm -f /usr/local/share/doc/bochs/README cat ./build/linux/README.linux-binary ./README > /usr/local/share/doc/bochs/README install -m 644 ./.bochsrc /usr/local/share/doc/bochs/bochsrc-sample.txt root# exit user$ _
Compiling on Win32 with Microsoft VC++ The standard compile uses the configure script, but the Windows platform cannot run the configure script natively. The current solution to this problem is that the Bochs configure script must be run on a different platform that does support shell scripts, with options that cause it to configure for a Win32 platform instead of the native one. Many people have access to a UNIX machine that could run the configure script, or you can use Cygwin or MinGW/MSYS to run the configure script. Because Bochs depends so much on the configure script, if you are doing much win32 Bochs development, you should consider downloading Cygwin or MinGW/MSYS so that you can run the configure step natively. . Download the Bochs sources on a machine that can run shell scripts. Edit the configure shortcut script .conf.win32-vcpp if you want to adjust the configure options. Then type these commands in the Bochs source directory: sh .conf.win32-vcpp make win32_snap These commands will run the configure step, produce VC++ makefiles and workspace files, and pack it all into a .zip file in the directory above the source directory If the source directory is /home/joe/bochs-win32, the resulting .zip file is in /home/joe/bochs-win32-msvc-src.zip. . The .zip file is all ready to transfer to the target Windows machine to be unzipped and compiled. Or, if you run the sh/make steps in Cygwin, you are already on the target machine so you don't need the .zip file. When you have the Win32 sources transferred to a Windows machine with VC++, find the workspace file called bochs.sln in the folder "vs2008" and load it in VC++. Choose Project:Set Active Project and be sure that "bochs" is selected. Then choose Build:Build bochs.exe. This will build all the required libraries (iodev, cpu, etc.) and the auxiliary programs bximage.exe, bxcommit.exe and niclist.exe. Using workspaces is easy and intuitive, but there is one caveat. The workspaces come directly out of a ZIP file in build/win32/vs2008ex-workspace.zip, and they are not controlled by the configure script. When you compile with certain configure options (e.g. ) you need to link with additional libraries. For now you must add them to the VC++ workspace by hand. In version 2.0, we have improved the situation considerably by adding #if...#endif around every optional file and including nearly every Bochs source file in the workspace. This solves the problem of having to manually add source files to the workspace when you turn on configure options such as . The problem of adding link libraries remains unresolved. To compile with the Bochs debugger enabled, add to the configure line in .conf.win32-vcpp before running it. No modifications to the workspace are necessary. An alternative way to compile is to run nmake.exe in an MS-DOS window. Instead of using the workspace files, nmake uses the Bochs makefiles that are generated by configure. The nmake method is currently used to build the release binaries. The make install for Win32 is presently broken. In the future, a make install that runs in Cygwin may be provided.
Compiling on Win32 with Cygwin Cygwin is a free Unix-like environment for Windows written by Steve Chamberlain and now maintained by RedHat, Inc. You can download it from www.cygwin.com. Because Cygwin supports the configure script and uses GNU gcc/g++, you can use the standard compile process. The configure script should automatically detect Cygwin and add "-mno-cygwin -DWIN32" to the compiler options. You should get a working Bochs if you just type: configure make Optionally, you can use the configure shortcut script for Cygwin, .conf.win32-cygwin, instead of running configure directly. If this script is close to what you need, just edit the script and then run it. To use the configure shortcut script and compile in Cygwin, the commands are sh .conf.win32-cygwin make To find out the options which are known to work in Cygwin, open the file .conf.win32-cygwin in any text editor/viewer and have a look at the end of that file.
Compiling on MacOS 9 with CodeWarrior It is possible that this hasn't been tried since 1999. In theory, you run sh .conf.macos on a Unix box to build the makefiles and headers, copy the whole thing over to a Mac, and then use CodeWarrior to compile. Since it hasn't been tested in so long, it is quite likely that some work is needed to bring the Mac port up to date. If you are interested and have the required MacOS development tools, please let us know by contacting the &devlist;. Someone requests a MacOS port almost once a month, but none of the developers know how to help them.
Compiling on MacOS X The port to MacOS X with Carbon API by Emmanuel Mailliard is quite new, and the configure and makefile support was added by Bryce Denney. You will need the compiler and libraries from the development tools CD. Bochs should configure and compile with the Carbon GUI if you simply type: configure make Optionally, you can use the configure shortcut script for MacOS X, .conf.macosx, instead of running configure directly. If this script is close to what you need, just edit the script and then run it. To use the configure shortcut script and compile, the commands are sh .conf.macosx make MacOS X has a special format for an application bundle, which looks like a directory that contains the required resource files and binaries. The Makefile currently creates this application bundle "by hand" using mkdir and copy, which is surely the wrong way to do it. Bryce doesn't know the official way to create an application from a Makefile, so this hack will remain until a real Mac developer helps to clean it up. On MacOS X the default GUI is the Carbon interface, but you can also try other Bochs GUIs. Use for X windows, for VNC/RFB, or for SDL.
Compiling on Amiga/MorphOS Nicholai Benalal created this port to MorphOS running on Amiga. It should compile with: configure make If the platform is not detected properly, you might need to use as a configure option. Optionally, you can use the configure shortcut script, .conf.amigaos.
Compiling with the RFB interface The RFB code was written by Don Becker x-odus@iname.com, who has a Bochs-RFB web page on his site, http://www.psyon.org/bochs-rfb/. This interface allows you to view the Bochs display with AT&T's VNC Viewer. The protocol used between a VNC server and a VNC viewer is called RFB. Because the RFB code in Bochs is written with portable network socket and POSIX thread code, it can be compiled on many platforms and has been tested in Linux and Win32. No additional libraries are required. To try it, type: configure --with-rfb make RFB currently uses this setup: port range 5900 to 5949 (using the first one available) no authentification 30 seconds waiting for client 8 bpp (BGR233) supported only desktop size 720x480 (for text mode and standard VGA)
Compiling with the SDL interface Dave Poirier has written an SDL interface for Bochs. Simple DirectMedia Layer, or SDL, is a cross-platform multimedia library distributed from libsdl.org. SDL is available for many platforms including Win32, Linux, BSD, IRIX, MacOS, MacOS X, and AmigaOS. To compile Bochs with SDL, you must first install the SDL library from libsdl.org. You can either get the source code and compile it yourself, or install the development libraries for your platform (already compiled). Then, go into the Bochs directory and type: configure --with-sdl make If you are on FreeBSD and have SDL installed using the ports collection, Bochs won't be able to find the library automatically, as the SDL config script is called sdl11-config in that case (even for version 1.2). The easiest way to make Bochs find it, is to create a symlink to that script called sdl-config inside a directory which is in the path. For example: ln -s /usr/local/bin/sdl11-config ~/bin/sdl-config To compile in Microsoft VS2008Ex, you have to configure on a different system (see Compiling on Win32 with Microsoft VC++). Before running the configure script, you have to add to the shortcut script. If you have already configured, you can set BX_WITH_SDL to 1 in config.h. Then you have to set up the project for SDL this way: - add source file sdl.cc to the module gui - add path to the SDL include files to the modules bochs and gui - add lbraries SDL.lib and SDLmain.lib to the module bochs - change the runtime library for all modules to Multithreaded-DLL (/MD) Compiling with MSVC nmake is not supported yet.
Compiling with the wxWidgets interface wxWidgets is a cross-platform C++ user interface library which you can download for free at wxwidgets.org. The wxWidgets port of Bochs provides both a graphical configuration interface for editing bochsrc options (see config_interface option) and a display (see display_library option). It was written by Bryce Denney, Don Becker, Dave Poirier, and Volker Ruppert. configure --with-wx make If you want Bochs to use a wxWidgets installation not in your path (but installed somewhere else), you need to set the WX_CONFIG environment variable to the proper wx-config script, before running configure (example for csh): setenv WX_CONFIG '/home/compile/wx/bin/wx-config'
Building an RPM on Linux RPM stands for "RedHat Package Manager." An RPM is a compressed file containing files to be installed on your system. Bochs has a special shell script called make-rpm that helps to build an RPM of Bochs. Start with a clean source directory. Edit .conf.linux first if you want to adjust the configure options. Then, type: ./build/redhat/make-rpm | tee /tmp/build.txt When this command completes, you should have a source RPM and a binary RPM of Bochs in the current directory. The tee part of the command (optional) saves a transcript of the build process into /tmp/build.txt, which is very useful if anything goes wrong. Instructions for installing an RPM are here. In the past, you had to build rpms as root, but as of version 2.0 you can build them as a normal user.
Compile Problems &FIXME; what if configure fails? - tar up config.* and send to bochs-developers - report the problem with a source forge bug report. what if make fails? - try make dist-clean, and run configure and make again - use configure options to disable options. For example, if errors in fpu/fpu.cc, you could try --disable-fpu. - search for the error on the Bochs website (bug reports, patches) - if familiar with C++, many minor problems can be corrected - move to more stable code. if it's SVN, see if a release version will compile. Report problem to bochs-developers. - report the problem with a source forge bug report.
Setup
What does Bochs need? These are the minimum requirements for running an OS inside of Bochs: the Bochs executable the BIOS image (usually called BIOS-bochs-latest) the VGA BIOS image (e.g. VGABIOS-lgpl-latest or VGABIOS-elpin-2.40) at least one bootable media, either as disk image (floppy, hard disk or CD-ROM) or physical disk (floppy or CD-ROM) Both VGA BIOS versions as well as the ROM BIOS are part of Bochs. No separate download is necessary. If you want to use the Cirrus SVGA adapter instead of VGA + Bochs VBE, you should have a look at . In that case you have to pass the configuration options on the command line or to use the configuration interface to set up Bochs for the simulation. Running Bochs is easier if you use a configuration file (we call it bochsrc). See for all supported options. The easiest way to setup Bochs for the first time is to use the example configuration file called bochsrc-sample.txt. Locate that file (location depends on the (host) OS and on the installation facility used) and copy it to a location where Bochs looks for that file, see . The next step is to change the configuration so that it fits your needs: You most likely want to setup a hard disk (see and ), and install some OS on it using either a set of floppy disks (see ) or a CD-ROM (see again) as installation media. Make sure you boot the emulation from the media you want, using the right setting as boot option. If your keyboard output inside of Bochs is wrong, you may also need a keymap file to remap your keyboard layout to the U.S. layout. A set of keymap files for the X window system and SDL (Linux port) is distributed with Bochs. If your keyboard layout is not supported yet, you can create your own one by following the instructions given in . A collection of disk images of different operating systems can be found at . Some disk images are the size of a floppy disk (1 meg compressed) and others are gigantic (160 meg compressed). If you want to create a disk image yourself, please see . &FIXME; This should be completed - BIOS/VGABIOS, what do they do?
bochsrc Bochs uses a configuration file called bochsrc to know where to look for disk images, how the Bochs emulation layer should work, etc. When you first start up Bochs, it looks around for its configuration file (see ), and parses it. Here are a few lines from a sample file: ata0-master: type=disk, path="30M.sample", cylinders=615, heads=6, spt=17 boot: disk The format is very strict, so be sure to put the right number of spaces and use lowercase letters. As you can see, most lines have a keyword telling what is being configured, followed by a colon, followed by a few variable=value pairs, separated by commas. For very simple options, sometimes just a single value is needed. The source and binary distributions come with a sample bochsrc, so you can just copy the sample file and edit the settings you need to change. The syntax used for bochsrc can also be used as command line arguments for Bochs. If you have any spaces in your command line arguments, they should be enclosed in single quotes, for example: bochs 'boot:floppy' 'floppya: 1_44=a.img, status=inserted' For other arguments, see section Command line arguments. Starting with version 1.3, you can use environment variables in the bochsrc file, for example: floppya: 1_44="$IMAGES/bootdisk.img", status=inserted boot: floppy Starting with version 2.0, two environment variables have a built-in default value which is set at compile time. $BXSHARE points to the "share" directory which is typically /usr/local/share/bochs on UNIX machines. See the $(sharedir) variable in the Makefile for the exact value. $BXSHARE is used by disk images to locate the directory where the BIOS images and keymaps can be found. If $BXSHARE is not defined, Bochs will supply the default value. Also, $LTDL_LIBRARY_PATH points to a list of directories (separated by colons if more than one) to search in for Bochs plugins. A compile-time default is provided if this variable is not defined by the user. On Win32 and MacOSX, the default for the share directory is determined by a platform-specific specific algorithm. On Win32, we use the registry to see what directory Bochs and its support files were installed in. On MacOSX, the share directory is the directory where the application is located. Starting with version 2.0, you can can use #include in the bochsrc to read the configuration from other files. Now it is possible to put platform or installation defaults in a global config file (e.g. location of rom images). Put this on top of your config file if the global configuration is stored in /etc: #include /etc/bochsrc The section below lists all the supported bochsrc options.
plugin_ctrl Example: plugin_ctrl: unmapped=0, e1000=1 # unload 'unmapped' and load 'e1000' Controls the presence of optional device plugins. These plugins are loaded directly with this option and some of them install a config option that is only available when the plugin device is loaded. The value "1" means to load the plugin and "0" will unload it (if loaded before). These plugins will be loaded by default (if present): 'biosdev', 'extfpuirq', 'gameport', 'iodebug','parallel', 'serial', 'speaker' and 'unmapped'. These plugins are also supported, but they are usually loaded directly with their bochsrc option: 'e1000', 'es1370', 'ne2k', 'pcidev', 'pcipnic', 'sb16', 'usb_ohci', 'usb_uhci' and 'usb_xhci'.
megs Examples: megs: 32 megs: 128 Set the number of megabytes of physical memory you want to emulate. The default is 32MB; most OS's won't need more than that. The maximum amount of memory supported is 2048MB. Due to limitations in the host OS, Bochs fails to allocate more than 1024MB on most 32-bit systems. In order to overcome this problem configure and build Bochs with option.
cpu Example: cpu: count=2, ips=10000000 This defines the parameters of the cpu inside Bochs: count Set the number of processors:cores per processor:threads per core when Bochs is compiled for SMP emulation. Bochs currently supports up to 8 processors. If Bochs is compiled without SMP support, it won't accept values different from 1. For more information on SMP see . quantum Maximum amount of instructions allowed to execute by processor before returning control to another cpu. This option exists only in Bochs binary compiled with SMP support. reset_on_triple_fault Reset the CPU when triple fault occur (highly recommended) rather than PANIC. Remember that if you are trying to continue after triple fault the simulation will be completely bogus ! cpuid_limit_winnt Determine whether to limit maximum CPUID function to 2. This mode is required to workaround WinNT installation and boot issues. mwait_is_nop When this option is enabled MWAIT will not put the CPU into a sleep state. This option exists only if Bochs compiled with . msrs Define path to user CPU Model Specific Registers (MSRs) specification. See example in msrs.def. ignore_bad_msrs Ignore MSR references that Bochs does not understand; print a warning message instead of generating #GP exception. This option is enabled by default but will not be avaiable if configurable MSRs are enabled. ips Emulated Instructions Per Second. This is the number of IPS that Bochs is capable of running on your machine. You can recompile Bochs with option enabled, to find your workstation's capability. Measured IPS value will then be logged into your log file or in the status bar (if supported by the gui). IPS is used to calibrate many time-dependent events within the Bochs simulation. For example, changing IPS affects the frequency of VGA updates, the duration of time before a key starts to autorepeat, and the measurement of BogoMips and other benchmarks. The table below lists some typical IPS settings for different machinesIPS measurements depend on OS and compiler configuration in addition to host processor clock speed.. Example IPS Settings Bochs Speed Machine/Compiler Typical IPS 2.4.63.4GhzIntel Core i7 2600 with Win7x64/g++ 4.5.2 85 to 95 MIPS2.3.73.2GhzIntel Core 2 Q9770 with WinXP/g++ 3.4 50 to 55 MIPS2.3.72.6GhzIntel Core 2 Duo with WinXP/g++ 3.4 38 to 43 MIPS2.2.62.6GhzIntel Core 2 Duo with WinXP/g++ 3.4 21 to 25 MIPS2.2.62.1GhzAthlon XP with Linux 2.6/g++ 3.4 12 to 15 MIPS
cpuid Example: cpuid: mmx=1, sep=1, sse=sse4_2, apic=xapic, aes=1, movbe=1, xsave=1 This defines features and functionality supported by Bochs emulated CPU: mmx Select MMX instruction set support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. apic Select APIC configuration (LEGACY/XAPIC/XAPIC_EXT/X2APIC). This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. sep Select SYSENTER/SYSEXIT instruction set support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. sse Select SSE instruction set support. Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 could be selected. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. sse4a Select AMD SSE4A instructions support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. aes Select AES instruction set support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. movbe Select MOVBE Intel(R) Atom instruction support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. adx Select ADCX/ADOX instructions support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. xsave Select XSAVE extensions support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. xsaveopt Select XSAVEOPT instruction support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. avx Select AVX/AVX2 instruction set support. This option exists only if Bochs compiled with option. avx_f16c Select AVX float16 convert instructions support. This option exists only if Bochs compiled with option. avx_fma Select AVX fused multiply add (FMA) instructions support. This option exists only if Bochs compiled with option. bmi Select BMI1/BMI2 instructions support. This option exists only if Bochs compiled with option. fma4 Select AMD four operand FMA instructions support. This option exists only if Bochs compiled with option. xop Select AMD XOP instructions support. This option exists only if Bochs compiled with option. tbm Select AMD TBM instructions support. This option exists only if Bochs compiled with option. x86_64 Enable x86-64 and long mode support. This option exists only if Bochs compiled with x86-64 support. 1g_pages Enable 1G page size support in long mode. This option exists only if Bochs compiled with x86-64 support. pcid Enable Process-Context Identifiers (PCID) support in long mode. This option exists only if Bochs compiled with x86-64 support. smep Enable Supervisor Mode Execution Protection (SMEP) support. This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. mwait Select MONITOR/MWAIT instructions support. This option exists only if Bochs compiled with . vmx Select VMX extensions emulation support. This option exists only if Bochs compiled with option. svm Select AMD SVM (Secure Virtual Machine) extensions emulation support. This option exists only if Bochs compiled with option. family Set family information returned by CPUID. Default family value determined by configure option --enable-cpu-level. model Set model information returned by CPUID. Default model value is 3. stepping Set stepping information returned by CPUID. Default stepping value is 3. vendor_string Set the CPUID vendor string returned by CPUID(0x0). This should be a twelve-character ASCII string. brand_string Set the CPUID brand string returned by CPUID(0x80000002 .. 0x80000004]). This should be at most a forty-eight-character ASCII string.
romimage Examples: romimage: file=bios/BIOS-bochs-latest, address=0xe0000 romimage: file=$BXSHARE/BIOS-bochs-legacy, address=0xf0000 romimage: file=mybios.bin, address=0xfff80000 romimage: file=mybios.bin The ROM BIOS controls what the PC does when it first powers on. Normally, you can use a precompiled BIOS in the source or binary distribution called BIOS-bochs-latest. The default ROM BIOS is usually loaded starting at address 0xe0000, and it is exactly 128k long. The legacy version of the Bochs BIOS is usually loaded starting at address 0xf0000, and it is exactly 64k long. You can also use the environment variable $BXSHARE to specify the location of the BIOS. The usage of external large BIOS images (up to 512k) at memory top is now supported, but we still recommend to use the BIOS distributed with Bochs. The start address is optional, since it can be calculated from image size.
optromimage1, optromimage2, optromimage3 or optromimage4 Example: optromimage1: file=optionalrom.bin, address=0xd0000 This enables Bochs to load up to 4 optional ROM images. Be sure to use a read-only area, typically between C8000 and EFFFF. These optional ROM images should not overwrite the rombios (located at F0000-FFFFF) and the videobios (located at C0000-C7FFF). Those ROM images will be initialized by the BIOS if they contain the right signature (0x55AA). It can also be a convenient way to upload some arbitrary code/data in the simulation, that can be retrieved by the boot loader
vgaromimage Examples: vgaromimage: file=bios/VGABIOS-elpin-2.40 vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus This tells Bochs what VGA ROM BIOS to load (at 0xC0000). A VGA BIOS from Elpin Systems, Inc. as well as a free LGPL'd VGA BIOS are provided in the source and binary distributions. Please check with the vga option to decide what VGA BIOS to use.
vga Examples: vga: extension=cirrus, update_freq=10 vga: extension=vbe This defines parameters related to the VGA display The 'extension' option can be used to specify the VGA display extension. With the value 'none' you can use standard VGA with no extension. Other supported values are 'vbe' for Bochs VBE (needs VGABIOS-lgpl-latest as VGA BIOS, see vgaromimage option) and 'cirrus' for Cirrus SVGA support (needs VGABIOS-lgpl-latest-cirrus as VGA BIOS). The VGA update frequency is based on the emulated clock and the default value is 5. Keep in mind that you must tweak the 'cpu: ips=N' directive to be as close to the number of emulated instructions-per-second your workstation can do, for this to be accurate. If the realtime sync is enabled with the clock option, the value is based on the real time. This parameter can be changed at runtime.
floppya/floppyb Examples: 2.88M 3.5" media: floppya: 2_88=a:, status=inserted 1.44M 3.5" media (write protected): floppya: 1_44=floppya.img, status=inserted, write_protected=1 1.2M 5.25" media: floppyb: 1_2=/dev/fd0, status=inserted 720K 3.5" media: floppya: 720k=/usr/local/bochs/images/win95.img, status=inserted auto-detect floppy media type: floppya: image=floppy.img, status=inserted use directory as VFAT media: floppya: 1_44=vvfat:path, status=inserted 1.44M 3.5" floppy drive, no media: floppya: type=1_44 Floppya is the first drive, and floppyb is the second drive. If you're booting from a floppy, floppya should point to a bootable disk. To read from a disk image, write the name of the image file. In many operating systems Bochs can read directly from a raw floppy drive. For raw disk access, use the device name (Unix systems) or the drive letter and a colon (Windows systems). Following floppy media types are supported: 2_88, 1_44, 1_2, 720k, 360k, 320k, 180k, 160k, as well as "image" to let Bochs auto-detect the type of floppy media (does only work with images, not with raw floppy drives). In that case the size must match one of the supported types. You can set the initial status of the media to ejected or inserted. Usually you will want to use inserted. The parameter 'type' can be used to enable the floppy drive without media and status specified. Usually the drive type is set up based on the media type. The optional parameter 'write_protected' can be used to control the media write protect switch. By default it is turned off.
ata0, ata1, ata2, ata3 Examples: ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9 These options enables up to 4 ata channels. For each channel the two base io addresses and the irq must be specified. ata0 and ata1 are enabled by default, with the values shown above.
ata0-master, ata0-slave, ata1-*, ata2-*, ata3-* Examples: ata0-master: type=disk, path=10M.img, mode=flat, cylinders=306, heads=4, spt=17, translation=none ata1-master: type=disk, path=2GB.cow, mode=vmware3, cylinders=5242, heads=16, spt=50, translation=echs ata1-slave: type=disk, path=3GB.img, mode=sparse, cylinders=6541, heads=16, spt=63, translation=auto ata2-master: type=disk, path=7GB.img, mode=undoable, cylinders=14563, heads=16, spt=63, translation=lba ata2-slave: type=cdrom, path=iso.sample, status=inserted This defines the type and characteristics of all attached ata devices: ata devices configuration options Option Comments Possible values type type of attached device [disk | cdrom] path path of the image mode image type, only valid for disks [flat | concat | external | dll | sparse | vmware3 | vmware4 | undoable | growing | volatile | vpc | vvfat ] cylinders only valid for disks heads only valid for disks spt only valid for disks status only valid for cdroms [inserted | ejected] biosdetect type of biosdetection [none | auto], only for disks on ata0 [cmos] translation type of translation done by the BIOS (legacy int13), only for disks [none | lba | large | rechs | auto] model string returned by identify device ATA command journal optional filename of the redolog for undoable, volatile and vvfat disks
You have to tell the type of the attached device. For Bochs 2.0 or later, it can be disk or cdrom. You have to point the "path" at a hard disk image file, cdrom iso file, or physical cdrom device. To create a hard disk image, try running bximage (see ). It will help you choose the size and then suggest a line that works with it. In Unix it is possible to use a raw device as a Bochs hard disk, but we don't recommend it for safety reasons. In Windows, there is no easy way. Disk geometry autodetection works with images created by bximage if CHS is set to 0/0/0 (cylinders are calculated using heads=16 and spt=63). For other hard disk images and modes the cylinders, heads, and spt are mandatory. In all cases the disk size reported from the image must be exactly C*H*S*512. Flat hard disk images from other projects might store additional information at the end of the file that makes this check fail. Only in this case it is safe to select "continue" when Bochs panics. The disk translation scheme (implemented in legacy int13 BIOS functions, and used by older operating systems like MS-DOS), can be defined as: none : no translation, for disks up to 528MB (1032192 sectors) large : a standard bitshift algorithm, for disks up to 4.2GB (8257536 sectors) rechs : a revised bitshift algorithm, using a 15 heads fake physical geometry, for disks up to 7.9GB (15482880 sectors). (don't use this unless you understand what you're doing) lba : a standard lba-assisted algorithm, for disks up to 8.4GB (16450560 sectors) auto : autoselection of best translation scheme. (it should be changed if system does not boot) Please see for a discussion on translation scheme. The mode option defines how the disk image is handled. Disks can be defined as: flat : one file flat layout concat : multiple files layout external : developer's specific, through a C++ class dll : developer's specific, through a DLL sparse : stackable, commitable, rollbackable vmware3 : vmware version 3 disk support vmware4 : vmware version 4 disk support (aka VMDK) undoable : flat file with commitable redolog growing : growing file volatile : flat file with volatile redolog vpc: fixed / dynamic size VirtualPC image vvfat: local directory appears as VFAT disk (with volatile redolog / optional commit) Please see for a discussion on disk modes. Default values are: mode=flat, biosdetect=auto, translation=auto, model="Generic 1234" The biosdetect option has currently no effect on the BIOS. Make sure the proper ata option is enabled when using a device on that ata channel.
boot Examples: boot: floppy boot: cdrom, disk boot: network, disk boot: cdrom, floppy, disk This defines the boot sequence. You can specify up to 3 boot drives, which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM). Legacy 'a' and 'c' are also supported.
floppy_bootsig_check Example: floppy_bootsig_check: disabled=1 This disables the 0xaa55 signature check on boot floppies The check is enabled by default.
config_interface The configuration interface is a series of menus or dialog boxes that allows you to edit all the settings that control Bochs' behavior. Depending on the platform there are up to 3 choices of configuration interface: a text mode version called "textconfig" and two graphical versions called "win32config" and "wx". The text mode version uses stdin/stdout and is always compiled in, unless Bochs is compiled for wx only. The choice "win32config" is only available on win32 and it is the default there. The choice "wx" is only available when Bochs is compiled with wxWidgets support, see . If you do not write a config_interface line, Bochs will choose a default for you (usually textconfig). wxWidgets provides both a configuration interface and a display library. So if you use the "wx" configuration interface, you must also use the "wx" display library, see display_library option. Examples: config_interface: textconfig config_interface: win32config config_interface: wx
display_library The display library is the code that displays the Bochs VGA screen. Bochs has a selection of about 10 different display library implementations for different platforms. If you run configure with multiple options, the display_library option lets you choose which one you want to run with. If you do not use a display_library line, Bochs will choose a default for you. wxWidgets provides both a configuration interface and a display library. So if you use the "wx" display library, you must also use the "wx" configuration interface, see config_interface option. Examples: display_library: x display_library: sdl Some display libraries now support specific options to control their behaviour. These options are supported by more than one display library: "gui_debug" - use GTK debugger gui (sdl, x) / Win32 debugger gui (sdl, win32) "hideIPS" - disable IPS output in status bar (rfb, sdl, win32, wx, x) "nokeyrepeat" - turn off host keyboard repeat (sdl, win32, x) See the examples below for other currently supported options. display_library: rfb, options="timeout=60" # time to wait for client display_library: sdl, options="fullscreen" # startup in fullscreen mode display_library values Option Description x use X windows interface, cross platform win32 use native win32 libraries carbon use Carbon library (for MacOS X) macintosh use MacOS pre-10 amigaos use native AmigaOS libraries sdl use SDL library, cross platform, details in svga use SVGALIB library for Linux, allows graphics without X windows term text only, uses curses/ncurses library, cross platform rfb provides an interface to AT&T's VNC viewer, cross platform, details in wx use wxWidgets library, cross platform, details in nogui no display at all
log Examples: log: bochsout.txt log: - log: /dev/tty (Unix only) log: /dev/null (Unix only) log: nul (win32 only) Give the path of the log file you'd like Bochs debug and misc. verbiage to be to be written to. If you don't use this option or set the filename to '-' the output is written to the console. If you really don't want it, make it "/dev/null" (Unix) or "nul" (win32). :^(
logprefix Examples: logprefix: %t-%e-@%i-%d logprefix: %i%e%d This handles the format of the string prepended to each log line. You may use those special tokens : %t : 11 decimal digits timer tick %i : 8 hexadecimal digits of current cpu eip (ignored in SMP configuration) %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror) %d : 5 characters string of the device, between brackets Default is %t%e%d
debug/info/error/panic Examples: debug: action=ignore, pci=report info: action=report error: action=report panic: action=ask During simulation, Bochs encounters certain events that the user might want to know about. These events are divided into four levels of importance: debug, info, error, and panic. Debug messages are usually only useful when writing Bochs code or when trying to locate a problem. There may be thousands of debug messages per second, so be careful before turning them on. Info messages tell about interesting events that don't happen that frequently. Bochs produces an "error" message when it finds a condition that really shouldn't happen, but doesn't endanger the simulation. An example of an error might be if the emulated software produces an illegal disk command. Panic messages mean that Bochs cannot simulate correctly and should probably shut down. A panic can be a configuration problem (like a misspelled bochsrc line) or an emulation problem (like an unsupported video mode). The debug, info, error, and panic lines in the bochsrc control what Bochs will do when it encounters each type of event. The allowed actions are: fatal (terminate bochs), ask (ask the user what to do), report (print information to the console or log file), or ignore (do nothing). The recommended settings are listed in the sample above. It is also possible to specify the 'action' to do for each Bochs facility separately (e.g. crash on panics from everything except the cdrom, and only report those). See the log function module table for valid module names. The safest action for panics is "fatal" or "ask". If you are getting lots of panics and get tired of telling it to continue each time, you can try action=report instead. If you allow Bochs to continue after a panic, don't be surprised if you get strange behavior or crashes after a panic occurs. Please report panic messages to the bochs-developers mailing list unless it is just a configuration problem like "could not find hard drive image."
debugger_log Examples: debugger_log: debugger.out debugger_log: /dev/null (Unix only) debugger_log: - Give the path of the log file you'd like Bochs to log debugger output. If you really don't want it, make it '/dev/null', or '-'.
com[1-4] Examples: com1: enabled=1, mode=null com1: enabled=1, mode=mouse com1: enabled=1, mode=term, dev=/dev/ttyp9 com2: enabled=1, mode=file, dev=serial.out com3: enabled=1, mode=raw, dev=com1 com3: enabled=1, mode=socket-client, dev=localhost:8888 com3: enabled=1, mode=socket-server, dev=localhost:8888 com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe This defines a serial port (UART type 16550A). When using the mode 'term', you can specify a device to use as com1. This can be a real serial line, or a pty. To use a pty (under X/Unix), create two windows (xterms, usually). One of them will run Bochs, and the other will act as com1. Find out the tty of the com1 window using the `tty' command, and use that as the `dev' parameter. Then do `sleep 1000000' in the com1 window to keep the shell from messing with things, and run Bochs in the other window. Serial I/O to com1 (port 0x3f8) will all go to the other window. When using socket* and pipe* (win32 only) modes Bochs becomes either socket/named pipe client or server. In client mode it connects to an already running server (if connection fails Bochs treats com port as not connected). In server mode it opens socket/named pipe and waits until a client application connects to it before starting simulation. This mode is useful for remote debugging (e.g. with gdb's "target remote host:port" command or windbg's command line option -k com:pipe,port=\\.\pipe\pipename). Note: 'socket' is a shorthand for 'socket-client', 'pipe' for 'pipe-client'. Socket modes use simple TCP communication, pipe modes use duplex byte mode pipes. Other serial modes are 'null' (no input/output), 'file' (output to a file specified as the 'dev' parameter), 'raw' (use the real serial port - under construction for win32), 'mouse' (standard serial mouse - requires mouse option setting 'type=serial' or 'type=serial_wheel').
parport[1-2] Examples: parport1: enabled=1, file="parport.out" parport2: enabled=1, file="/dev/lp0" parport1: enabled=0 This defines a parallel (printer) port. When turned on and an output file is defined, the emulated printer port sends characters printed by the guest OS into the output file. On some platforms, a device filename can be used to send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on win32 platforms).
sb16 Example: sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000 The example is wrapped onto several lines for formatting reasons, but it should all be on one line in the actual bochsrc file. This defines the Sound Blaster 16 emulation, see for more information. It can have several of the following properties. All properties are in the usual "property=value" format. midi: The filename is where the midi data is sent to. This can be a device or just a file if you want to record the midi data. On a Windows host this parameter is ignored when using output to the sound device. On a Linux host with ALSA present and this parameter starting with "alsa:", the default sequencer device will be used with the given client and port parameters instead of an OSS device. midimode: 0 = No data should be output. 1 = output to device (system dependent - midi denotes the device driver). 2 = SMF file output, including headers. 3 = Output the midi data stream to the file (no midi headers and no delta times, just command and data bytes). wave: This is the device/file where wave output is stored. On a Windows host this parameter is ignored when using output to the sound device. On a Linux host with ALSA present and this parameter set to "alsa", the default PCM output device will be used instead of an OSS device. If Bochs is compiled with SDL support, this parameter can be set to "sdl" to use the SDL audio subsystem for output. wavemode: 0 = no data 1 = output to device (system dependent - wave denotes the device driver). 2 = VOC file output, including headers. 3 = Output the raw wave stream to the file. log: The file to write the sb16 emulator messages to. loglevel: 0 = No log. 1 = Resource changes, midi program and bank changes. 2 = Severe errors. 3 = All errors. 4 = All errors plus all port accesses. 5 = All errors and port accesses plus a lot of extra information. It is possible to change the loglevel at runtime. dmatimer: Microseconds per second for a DMA cycle. Make it smaller to fix non-continuous sound. 750000 is usually a good value. This needs a reasonably correct setting for the ips parameter of the cpu option. It is possible to adjust the dmatimer value at runtime.
es1370 Examples: es1370: enabled=1, wavedev="" # win32 es1370: enabled=1, wavedev=alsa # Linux with ALSA es1370: enabled=1, wavedev=sdl # use SDL audio (if present) for output This defines the ES1370 sound emulation. The parameter 'enabled' controls the presence of the device. The 'wavedev' parameter is similar to the 'wave' parameter of the SB16 soundcard. The emulation supports recording and playback (except DAC1+DAC2 output at the same time).
keyboard Examples: keyboard: type=mf, serial_delay=200, paste_delay=100000 keyboard: keymap=gui/keymaps/x11-pc-de.map This defines parameters related to the emulated keyboard. type Type of keyboard return by a "identify keyboard" command to the keyboard controller. It must be one of "xt", "at" or "mf". Defaults to "mf". It should be ok for almost everybody. A known exception is french macs, that do have a "at"-like keyboard. serial_delay Approximate time in microseconds that it takes one character to be transferred from the keyboard to controller over the serial path. paste_delay Approximate time in microseconds between attempts to paste characters to the keyboard controller. This leaves time for the guest os to deal with the flow of characters. The ideal setting depends on how your operating system processes characters. The default of 100000 usec (.1 seconds) was chosen because it works consistently in Windows. If your OS is losing characters during a paste, increase the paste delay until it stops losing characters. keymap This enables a remap of a physical localized keyboard to a virtualized us keyboard, as the PC architecture expects. Keyboard mapping is available for the display libraries x, sdl (Linux port) and wx (GTK port). For SDL you have to use keymaps designed for SDL, the wxWidgets GUI uses the keymaps for X11.
clock This defines the parameters of the clock inside Bochs: sync This defines the method how to synchronize the Bochs internal time with realtime. With the value 'none' the Bochs time relies on the IPS value and no host time synchronization is used. The 'slowdown' method sacrifices performance to preserve reproducibility while allowing host time correlation. The 'realtime' method sacrifices reproducibility to preserve performance and host-time correlation. It is possible to enable both synchronization methods. time0 Specifies the start (boot) time of the virtual machine. Use a time value as returned by the time(2) system call. If no time0 value is set or if time0 equal to 1 (special case) or if time0 equal 'local', the simulation will be started at the current local host time. If time0 equal to 2 (special case) or if time0 equal 'utc', the simulation will be started at the current utc time. Syntax: clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc] Examples: clock: sync=none, time0=local # Now (localtime) clock: sync=slowdown, time0=315529200 # Tue Jan 1 00:00:00 1980 clock: sync=none, time0=631148400 # Mon Jan 1 00:00:00 1990 clock: sync=realtime, time0=938581955 # Wed Sep 29 07:12:35 1999 clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000 clock: sync=none, time0=1 # Now (localtime) clock: sync=none, time0=utc # Now (utc/gmt) Default value are sync=none, time0=local
mouse Examples: mouse: enabled=1 mouse: type=imps2, enabled=1 mouse: type=serial, enabled=1 mouse: enabled=0, toggle=ctrl+f10 This defines parameters for the emulated mouse type, the initial status of the mouse capture and the runtime method to toggle it. type With the mouse type option you can select the type of mouse to emulate. The default value is 'ps2'. The other choices are 'imps2' (wheel mouse on PS/2), 'serial', 'serial_wheel' and 'serial_msys' (one com port requires setting 'mode=mouse', see com option). To connect a mouse to an USB port, see the usb_uhci, 'usb_ohci 'or 'usb_xhci' option (requires PCI and USB support). enabled The Bochs gui creates mouse "events" unless the 'enabled' option is set to 0. The hardware emulation itself is not disabled by this. Unless you have a particular reason for enabling the mouse by default, it is recommended that you leave it off. You can also toggle the mouse usage at runtime (see headerbar and the 'toggle' option below). toggle The default method to toggle the mouse capture at runtime is to press the CTRL key and the middle mouse button ('ctrl+mbutton'). This option allows to change the method to 'ctrl+f10' (like DOSBox) or 'ctrl+alt' (like QEMU) or 'f12' (replaces win32 'legacyF12' option).
private_colormap Example: private_colormap: enabled=1 Requests that the GUI creates and uses its own non-shared colormap. This colormap will be used when in the Bochs window. If not enabled, a shared colormap scheme may be used. Once again, enabled=1 turns on this feature and 0 turns it off.
pci Examples: pci: enabled=1, chipset=i440fx # default if compiled with PCI support pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=ne2k This option controls the presence of a PCI chipset in Bochs. Currently it only supports the i440FX chipset. You can also specify the devices connected to PCI slots. Up to 5 slots are available. For these combined PCI/ISA devices assigning to slot is mandatory if you want to emulate the PCI model: cirrus, ne2k and pcivga. These PCI-only devices are also supported, but they are auto-assigned if you don't use the slot configuration: e1000, es1370, pcidev, pcipnic, usb_ohci and usb_xhci.
pcidev Example: pcidev: vendor=0xbabe, device=0x2bad Enables the mapping of a host PCI hardware device within the virtual PCI subsystem of the Bochs x86 emulator. The arguments vendor and device should contain the PCI vendor ID respectively the PCI device ID of the host PCI device you want to map within Bochs. The PCI device mapping is still in a very early stage of development and thus it is very experimental. This feature requires Linux as a host operating system. Besides the pcidev config line you will need to load a pcidev kernel module within your Linux host OS. This kernel module is located in the bochs/host/linux/pcidev/ directory.
usb_uhci Examples: usb_uhci: enabled=1, port1=mouse, port2=disk:usbstick.img usb_uhci: enabled=1, port1=hub:7, port2=disk:growing:usbdisk.img usb_uhci: enabled=1, port2=disk:undoable:usbdisk.img, options1=journal:redo.log usb_uhci: enabled=1, port1=printer:printdata.bin, port2=cdrom:image.iso This option controls the presence of the USB root hub which is a part of the i440FX PCI chipset. With the portX option you can connect devices to the hub (currently supported: 'mouse', 'tablet', 'keypad', 'disk', 'cdrom', 'hub' and 'printer'). The optionsX parameter can be used to assign specific options to the device connected to the corresponding USB port. Currently this feature is only used to set the speed reported by device and by the 'disk' device to specify an alternative redolog file of some image modes. If you connect the mouse or tablet to one of the ports, Bochs forwards the mouse movement data to the USB device instead of the selected mouse type. When connecting the keypad to one of the ports, Bochs forwards the input of the numeric keypad to the USB device instead of the PS/2 keyboard. To connect a 'flat' mode image as an USB hardisk you can use the 'disk' device with the path to the image separated with a colon. To use other disk image modes similar to ATA disks the syntax 'disk:mode:filename' must be used (see above). To emulate an USB cdrom you can use the 'cdrom' device name and the path to an ISO image or raw device name also separated with a colon. An option to insert/eject media is available in the runtime configuration. The device name 'hub' connects an external hub with max. 8 ports (default: 4) to the root hub. To specify the number of ports you have to add the value separated with a colon. Connecting devices to the external hub ports is only available in the runtime configuration. The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is sent to a file specified in bochsrc.txt. The current code appends the PCL code to the file if the file already existed. It would probably be nice to overwrite the file instead, asking user first. PCI support must be enabled to use USB UHCI.
usb_ohci Example: usb_ohci: enabled=1, port1=printer:printdata.bin This option controls the presence of the USB OHCI host controller with a 2-port hub. The portX option accepts the same device types with the same syntax as the UHCI controller (see the usb_uhci option).
usb_xhci Example: usb_xhci: enabled=1 This option controls the presence of the experimental USB xHCI host controller with a 4-port hub. The portX option accepts the same device types with the same syntax as the UHCI controller (see the usb_uhci option).
gdbstub Example: gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0 Default: gdbstub: enabled=0 This enables the GDB stub. See .
ne2k The ne2k line configures an emulated NE2000-compatible Ethernet adapter, which allows the guest machine to communicate on the network. To disable the NE2000 just comment out the ne2k line. Examples: ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0 ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=en0 #macosx ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig ne2k: mac=fe:fd:00:00:00:01, ethmod=slirp, script=/usr/local/bin/slirp, bootrom=ne2k_pci.rom IOADDR, IRQ: You probably won't need to change ioaddr and irq, unless there are IRQ conflicts. These parameters are ignored if the NE2000 is assigned to a PCI slot. MAC: The MAC address MUST NOT match the address of any machine on the net. Also, the first byte must be an even number (bit 0 set means a multicast address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast address. For the ethertap module, you must use fe:fd:00:00:00:01. There may be other restrictions too. To be safe, just use the b0:c4... address. ETHMOD: The ethmod value defines which low level OS specific module to be used to access physical ethernet interface. You can also specify a network simulator or a module with no input/output ("null"). See the table below for currently supported values. ETHDEV: The ethdev value is the name of the network interface on your host platform. On UNIX machines, you can get the name by running ifconfig. On Windows machines, you must run niclist to get the name of the ethdev. Niclist source code is in misc/niclist.c and it is included in Windows binary releases. SCRIPT: The script value is optional, and is the name of a script that is executed after bochs initialize the network interface. You can use this script to configure this network interface, or enable masquerading. This is mainly useful for the tun/tap devices that only exist during Bochs execution. The network interface name is supplied to the script as first parameter. BOOTROM: The bootrom value is optional, and is the name of the ROM image to load. Note that this feature is only implemented for the PCI version of the NE2000. The following table shows the available ethernet modules with description, whether the "ethdev" and "script" parameters are used or not and the Bochs version where this module was added. Ethernet modules Module Description ethdev script Bochs version fbsd FreeBSD / OpenBSD packetmover. Yes No 1.0 linux Linux packetmover - 'root' privileges required, no connection to the host machine. Yes No 1.3 null Null packetmover. All packets are discarded, but logged to a few files. No No 1.0 tap TAP packetmover. Yes Yes 1.4 tuntap TUN/TAP packetmover - see Configuring and using a tuntap network interface. Yes Yes 2.0 vde Virtual Distributed Ethernet packetmover. Yes Yes 2.2 vnet ARP, ping (ICMP-echo), DHCP and read/write TFTP simulation. The virtual host uses 192.168.10.1. DHCP assigns 192.168.10.2 to the guest. The TFTP server uses the 'ethdev' value for the root directory and doesn't overwrite files. Yes, for TFTP No 2.2 slirp Ethernet backend for Slirp with builtin DHCP / TFTP servers. Adds user mode networking to Bochs using Slirp. Only tested with the most recent Slirp version with Debian patches applied. The fullbolt Slirp version should be used for maximum speed. The "script" parameter should point to the Slirp binary. The TFTP server uses the 'ethdev' value for the root directory and doesn't overwrite files. No Yes 2.5 win32 Win32 packetmover - WinPCap driver required. Yes No 1.3
pcipnic Example: pcipnic: enabled=1, mac=b0:c4:20:00:00:00, ethmod=vnet To support the Bochs/Etherboot pseudo-NIC, Bochs must be compiled with the configure option. It accepts the same syntax (for mac, ethmod, ethdev, script, bootrom) and supports the same networking modules as the NE2000 adapter.
e1000 Example: e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=slirp, script=/usr/local/bin/slirp To support the Intel(R) 82540EM Gigabit Ethernet adapter, Bochs must be compiled with the configure option. It accepts the same syntax (for mac, ethmod, ethdev, script, bootrom) and supports the same networking modules as the NE2000 adapter.
user_shortcut Examples: user_shortcut: keys=ctrl-alt-del user_shortcut: keys=ctrl-alt-esc This defines the keyboard shortcut to be sent when you press the "user" button in the headerbar. The shortcut string is a combination of maximum 3 key names (listed below) separated with a '-' character. Valid key names: "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc", "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup", "plus", "right", "shift", "space", "tab", "up", "win", "print" and "power".
cmosimage Example: cmosimage: file=cmos.img, rtc_init=time0 This defines image file that can be loaded into the CMOS RAM at startup. The rtc_init parameter controls whether initialize the RTC with values stored in the image. By default the time0 argument given to the clock option is used. With 'rtc_init=image' the image is the source for the initial time.
user_plugin Example: user_plugin: name=testdev Load user-defined plugin. This option is available only if Bochs is compiled with plugin support. Maximum 8 different plugins are supported. See the example in the Bochs sources how to write a plugin device.
magic_break Example: magic_break: enabled=1 This enables the "magic breakpoint" feature when using the debugger. The useless cpu instruction XCHG BX, BX causes Bochs to enter the debugger mode. This might be useful for software development.
port_e9_hack Example: port_e9_hack: enabled=1 The 0xE9 port doesn't exists in normal ISA architecture. However, we define a convention here, to display on the console of the system running Bochs anything that is written to it. The idea is to provide debug output very early when writing BIOS or OS code for example, without having to bother with setting up a serial port or etc. Reading from port 0xE9 will will return 0xe9 to let you know if the feature is available. Leave this 0 unless you have a reason to use it.
debug_symbols Example: debug_symbols: file=mysymbols.sym debug_symbols: file=mysymbols.sym, offset=0x1000 This loads symbols from the specified file for use in Bochs' internal debugger. Symbols are loaded into global context. This is equivalent to issuing ldsym debugger command at start up.
Sound Blaster 16 Emulation This section is a detailed description for configuring Sound Blaster 16 from source. If you have a binary and all you want to know is what to put in your bochsrc file, see sb16 option. The original version of the Sound Blaster 16 (SB16) emulation for Bochs was written and donated by Josef Drexler. The entire set of his SB16 patches have been integrated into Bochs, however, so you can find everything you need here.
How well does it work? Right now, MPU401 emulation is next to perfect. It supports UART and SBMIDI mode, because the SB16's MPU401 ports can't do anything else as well. The digital audio basically works, but the emulation is too slow for fluent output unless the application doesn't do much in the background (or the foreground, really). The sound tends to looping or crackle on slower computer, but the emulation appears to be correct. Even a MOD player works, although only for lower sampling speeds. Also, the MIDI data running through the MPU401 ports can be written into a SMF, that is the standard midi file. The wave output can be written into a VOC file, which has a format defined by Creative Labs. This file format can be converted to WAV by sox for example.
Output to a sound card Output is supported on Windows, Linux, FreeBSD, MacOS 9 and MacOSX at the moment. On Linux, the output goes to any file or device. If you have a wavetable synthesizer, midi can go to /dev/midi00, otherwise you may need a midi interpreter. For example, the midid program from the DosEmu project would work. Wave output should go to /dev/dsp. These devices are assumed to be OSS devices, if they're not some of the ioctl's might fail. If ALSA is present on Linux and the wave device is set to alsa, Bochs uses it's default PCM output device instead of an OSS device. On Windows, midi and (wave) output go to the midi mapper and the wave mapper, respectively. A future version might have selectable output devices.
Installation on Linux
Prerequisites A wavetable synthesizer on /dev/midi00 and a working /dev/dsp if you want real time music and sound, otherwise output to midi and wave files is also possible. Optionally, you can use a software midi interpreter, such as the midid program from the DosEmu project instead of /dev/midi00.
Configuring Bochs You need to configure Bochs using the option. There are a few values in config.h that are relevant to the sound functions. Edit config.h after running configure, but before compiling. BX_USE_SB16_SMF should be 1 unless you intend to have several sound cards running at the same time. BX_SOUND_OUTPUT_C is the name of the class used for output. The default is to have no output functions, so you need to change this if you want any sound. The following are supported at the moment: bx_sound_linux_c for output to /dev/dsp and /dev/midi00 on Linux, FreeBSD and maybe other OSes that use the OSS driver. bx_sound_windows_c for output to the midi and wave mapper of Windows 3.1 and higher. bx_sound_output_c for no output at all. Setup the SB16 emulation in your bochsrc, according to instructions in that file (see sb16 option).
Runtime configuration The source for the SB16CTRL program that is used to modify the runtime behavior of the SB16 emulation is included in misc/sb16/. It is a C program that can be run from inside the emulation. It currently supports the following commands: Supported options for <command>sb16ctl</command> Option Description Show the selected emulator info string, e.g. sb16ctrl -i 3 to show how many patch translations are active. Load a translation into the translation table. The numbers are: "OldBankMSB,OldBankLSB,OldProgram,NewBankMSB,NewBankLSB,NewProgram". All values can be 0..127 or 255. 255 for "Old" values means match any and for "New" values means don't change, e.g. sb16ctrl -t 255,255,0,255,255,32 to change patch 0 (Piano) to patch 32 (Acoustic Bass). Reset the patch translation table e.g. sb16ctrl -r. Upload the given numbers to the midi output device. Note that it should be a complete midi message, and also that it is subject to patch translation, e.g. sb16ctrl -m 0x80,64,0 to send a note-off message to channel 0. Read in a file and execute the commands in it. These have the same format as the above commands, except that they don't have the dash "-" in front of them. Comment lines are supported and start with a hash sign "#". Show a brief summary of the commands.
All numbers can be valid parameters to the strtol() function, so hex and octal notation is fine. They have to be delimited by either commas "," or slashes "/", spaces are not allowed. The command line can have any number of commands. However, if none are given, "-f -" is assumed, which means commands are taken from stdin.
Features planned for the future Port it to more OS's. Finish the OPL3 FM emulation by translating the music to midi data.
Description of the sound output classes You can find a description of the sound output classes and more details on Sound Blaster 16 emulation in the developer documentation.
How to write your own keymap table Christophe Bothamy wrote the keymapping code for Bochs, and provided this documentation for how to create new keymaps. Keymapping was first implemented for X windows only, so there are many references to X-specific values in this section. In Bochs 2.0 keymapping is also available for SDL (Linux port) and wxWidgets (wxGTK port). The standard US Keyboard looks like this: ------------------------------------------- Top row Esc F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 ------------------------------------------- 2nd row ` 1 2 3 4 5 6 7 8 9 0 - = \ Back ------------------------------------------- 3rd row Tab Q W E R T Y U I O P [ ] Enter ------------------------------------------- 4rd row Caps A S D F G H J K L ; ' ------------------------------------------- 5rd row lShift l\ Z X C V B N M , . / rShift ------------------------------------------- 6rd row lCtrl lAlt Space rAlt rCtrl ------------------------------------------- Each key of the US keyboard maps to a Bochs constant named BX_KEY_symbol. You can find the current list of BX_KEY_symbol in the BX_KEY table, below. Please note that there is only one BX_KEY_symbol for each physical key. Now, for each key of the US keyboard, look at which symbols you can type on your real keyboard. Each symbol maps to a X-windows XK_symbol constant. In X11/keysymdef.h, you will find the list of all possible XK_symbol on your system. Alternatively, you can use a small utility called "xev" that prints out the symbol names of a pressed key. Note that the symbol name given by xev does not contain the XK_ prefix. Don't forget to add a line for every symbol you can type on each key. For the key BX_KEY_A, you can type both lowercase 'a' and uppercase 'A', so you would need two different entries. You can then create your own map file. Keymap files are found in the "gui/keymaps" directory in the source code, or in the "keymaps" directory in binary releases. Look at the existing keymap file as an example, and create a file containing one line for each symbol. The first column tells what key or combination of keys can be used to produce a given symbol. The second column is the ASCII equivalent for that symbol, or a special keyword (none, space, return, tab, backslash, or apostrophe). The third column is the X windows keysym for that symbol. For example : BX_KEY_0 '0' XK_0 BX_KEY_1 '1' XK_1 BX_KEY_2 '2' XK_2 BX_KEY_0+BX_KEY_SHIFT_L ')' XK_parenright BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam BX_KEY_2+BX_KEY_SHIFT_L '@' XK_at BX_KEY_A 'a' XK_a BX_KEY_B 'b' XK_b BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B BX_KEY_TAB tab XK_Tab BX_KEY_ENTER return XK_Return BX_KEY_F1 none XK_F1 BX_KEY_F2 none XK_F2 BX_KEY_F3 none XK_F3 Now that there are several keymap files in the Bochs distribution, it is easiest to copy an existing keymap and follow the examples you see. When it works, be sure to send it to the mailing list or post it on Source Forge so that we can include it in the next release. You may need to look up some of your country specific X11 symbols in X11/keysymdef.h. BX_KEY constants BX_KEY constant Keyboard Symbol BX_KEY_CTRL_L left Ctrl BX_KEY_SHIFT_L left Shift BX_KEY_F1 F1 BX_KEY_F2 F2 BX_KEY_F3 F3 BX_KEY_F4 F4 BX_KEY_F5 F5 BX_KEY_F6 F6 BX_KEY_F7 F7 BX_KEY_F8 F8 BX_KEY_F9 F9 BX_KEY_F10 F10 BX_KEY_F11 F11 BX_KEY_F12 F12 BX_KEY_CTRL_R right Ctrl BX_KEY_SHIFT_R right Shift BX_KEY_CAPS_LOCK CapsLock BX_KEY_NUM_LOCK NumLock BX_KEY_ALT_L left Alt BX_KEY_ALT_R right Alt BX_KEY_A A BX_KEY_B B BX_KEY_C C BX_KEY_D D BX_KEY_E E BX_KEY_F F BX_KEY_G G BX_KEY_H H BX_KEY_I I BX_KEY_J J BX_KEY_K K BX_KEY_L L BX_KEY_M M BX_KEY_N N BX_KEY_O O BX_KEY_P P BX_KEY_Q Q BX_KEY_R R BX_KEY_S S BX_KEY_T T BX_KEY_U U BX_KEY_V V BX_KEY_W W BX_KEY_X X BX_KEY_Y Y BX_KEY_Z Z BX_KEY_0 0 BX_KEY_1 1 BX_KEY_2 2 BX_KEY_3 3 BX_KEY_4 4 BX_KEY_5 5 BX_KEY_6 6 BX_KEY_7 7 BX_KEY_8 8 BX_KEY_9 9 BX_KEY_ESC Esc BX_KEY_SPACE SpaceBar BX_KEY_SINGLE_QUOTE ' BX_KEY_COMMA , BX_KEY_PERIOD . BX_KEY_SLASH / BX_KEY_SEMICOLON ; BX_KEY_EQUALS = BX_KEY_LEFT_BRACKET [ BX_KEY_BACKSLASH \ BX_KEY_RIGHT_BRACKET ] BX_KEY_MINUS - BX_KEY_GRAVE ` BX_KEY_BACKSPACE BackSpace BX_KEY_ENTER Enter BX_KEY_TAB Tab BX_KEY_LEFT_BACKSLASH left \ BX_KEY_PRINT PrintScreen BX_KEY_SCRL_LOCK ScrollLock BX_KEY_PAUSE Pause BX_KEY_INSERT Ins BX_KEY_DELETE Del BX_KEY_HOME Home BX_KEY_END End BX_KEY_PAGE_UP PageUo BX_KEY_PAGE_DOWN PageDown BX_KEY_KP_ADD Numeric Keypad + BX_KEY_KP_SUBTRACT Numeric Keypad - BX_KEY_KP_END Numeric Keypad 1 BX_KEY_KP_DOWN Numeric Keypad 2 BX_KEY_KP_PAGE_DOWN Numeric Keypad 3 BX_KEY_KP_LEFT Numeric Keypad 4 BX_KEY_KP_5 Numeric Keypad 5 BX_KEY_KP_RIGHT Numeric Keypad 6 BX_KEY_KP_HOME Numeric Keypad 7 BX_KEY_KP_UP Numeric Keypad 8 BX_KEY_KP_PAGE_UP Numeric Keypad 9 BX_KEY_KP_INSERT Numeric Keypad 0 BX_KEY_KP_DELETE Numeric Keypad . BX_KEY_KP_ENTER Numeric Keypad Enter BX_KEY_KP_MULTIPLY Numeric Keypad * BX_KEY_KP_DIVIDE Numeric Keypad / BX_KEY_UP UpArrow BX_KEY_DOWN DownArrow BX_KEY_LEFT LeftArrow BX_KEY_RIGHT RightArrow BX_KEY_WIN_L Left Windows BX_KEY_WIN_R Right Windows BX_KEY_MENU Menu BX_KEY_ALT_SYSREQ Alt-Sysreq BX_KEY_CTRL_BREAK Ctrl-Break BX_KEY_INT_BACK Internet - back BX_KEY_INT_FORWARD Internet - forward BX_KEY_INT_STOP Internet - stop BX_KEY_INT_MAIL Internet - mail BX_KEY_INT_SEARCH Internet - search BX_KEY_INT_FAVInternet - favoritesBX_KEY_INT_HOME Internet - home BX_KEY_POWER_MYCOMP Powerkeys - my computer BX_KEY_POWER_CALC Powerkeys - calculator BX_KEY_POWER_SLEEP Powerkeys - sleep BX_KEY_POWER_POWER Powerkeys - power BX_KEY_POWER_WAKE Powerkeys - wake
Using Bochs &FIXME; - using plugins? - Resources for users testing status page: tells what has been tried and who got it working search on bochs web site SourceForge - look for bug reports - how to report problems (present as FIXME request in chapter 6 as well) - How to make feature requests?
Command line arguments The following table shows the arguments that can be used on the command line. For other arguments, see section bochsrc. command line arguments Argument Description -q quick start (skip configuration interface) -f filename specify configuration file -log filename specify Bochs log file -dbglog filename specify Bochs internal debugger log file -n don't try to load a configuration file -r path specify path for restoring state -noconsole disable console window (Windows only) --help display help message and exit --help features display available features / devices and exit --help cpu display supported CPU models and exit (CPU level > 4 only)
These arguments are handled directly after starting Bochs. The next step is to load a default or specified configuration file (unless disabled with -n). Then the rest of the command line (bochsrc options) is parsed. This is done after reading the configuration file so that the command line arguments can override the settings from the file.
Search order for the configuration file If no configuration file is specified on the command line and config file loading is not disabled, Bochs searches for a default configuration file. This is the search order: .bochsrc in the current directory bochsrc in the current directory bochsrc.txt in the current directory (win32 only) bochsrc.bxrc in the current directory (Unix only) .bochsrc in the user's home directory (Unix only) bochsrc in the /etc directory
The configuration interface 'textconfig' The configuration interface 'textconfig' is the text mode version of the Bochs configuration system. It is a series of menus (using stdin/stdout) that allows you to edit all the settings that control Bochs' behavior. If you do not write a config_interface line, Bochs will choose it as the default for you (unless Bochs is compiled for Win32 or wxWidgets only). It consists of these three parts: the start menu the headerbar buttons the runtime configuration
The start menu If you start Bochs without the quickstart argument (-q), the Bochs configuration main menu appears: ------------------------------ Bochs Configuration: Main Menu ------------------------------ This is the Bochs Configuration Interface, where you can describe the machine that you want to simulate. Bochs has already searched for a configuration file (typically called bochsrc.txt) and loaded it if it could be found. When you are satisfied with the configuration, go ahead and start the simulation. You can also start bochs with the -q option to skip these menus. 1. Restore factory default configuration 2. Read options from... 3. Edit options 4. Save options to... 5. Restore the Bochs state from... 6. Begin simulation 7. Quit now Please choose one: [5] Here you can load, edit and save the configuration and finally start the simulation. It is possible to start Bochs without a config file and to edit all the settings using the item "Edit options". Don't forget to save the configuration if you want to use this setup for another Bochs session.
The Bochs headerbar The headerbar appears on top of the Bochs simulation window. Here you can control the behavoiur of Bochs at runtime if you click on one of these buttons: floppy buttons Here you can toggle the status of the floppy media (inserted/ejected). Bochs for win32 presents you a small dialog box for changing the floppy image. You can setup floppy drives using floppya/floppyb option. cdrom button Here you can toggle the status of the cdrom media (inserted/ejected). CD-ROM drives can be set up using ata(0-3)-master/-slave option. On some platforms this button brings a up a small dialog box for changing the CD-ROM image. mouse button Here you can enable the creation of mouse events by the host. Once mouse events are captured, you cannot reach the button anymore, in order to disable capturing again. By default you can enable and disable the mouse capture pressing the CTRL key and the third (middle) mouse button. See the mouse option parameter 'toggle' for other methods to toggle the mouse capture. &FIXME; Support for 2 button mouse to toggle the capture mode not yet complete. Some display libraries still don't support changing the mouse capture at runtime, but it is already supported on RFB, SDL, Win32, wxWidgets and X11. user button Press this button if you want to send the keyboard shortcut defined with the user_shortcut option to the guest. Depending on the used display_library option, it may even be possible to edit the shortcut before sending it. copy button The text mode screen text can be exported to the clipboard after pressing this button. The button has no effect in graphics mode. paste button Text in the clipboard can also be pasted, through Bochs, to the guest OS, as simulated keystrokes. Keyboard mapping must be enabled to make this feature work. snapshot button Press this button if you want to save a snapshot of the Bochs screen. The text modes and most of the graphics modes (except CGA) are supported. If gui dialogs are supported (e.g. on win32) Bochs presents you a "Save as..." dialog box to specify the filename. All other platforms are using the fixed filenames "snapshot.txt" or "snapshot.bmp". config button This button stops the Bochs simulation and starts the runtime configuration. (see below). reset button Press this button to trigger a hardware reset. suspend button Press this button to save current simulation state to a disk. The simulation could be restored back using bochs -r command. For more details read "Save and restore simulation" section of the user manual. power button This button stops the simulation and quits bochs. Some of this features may not be implemented or work different on your host platform.
The runtime configuration If you want to change certain settings at runtime, you have to press the "config" button in the headerbar. The simulation stops and the runtime menu appears on the console window / xterm. --------------------- Bochs Runtime Options --------------------- 1. Floppy disk 0: /dev/fd0, size=1.44M, inserted 2. Floppy disk 1: floppyb.img, size=1.44M, inserted 3. 1st CDROM: (master on ata1) /dev/cdrom, ejected 4. 2nd CDROM: (slave on ata1) /dev/cdrecorder, ejected 5. 3rd CDROM: (not present) 6. 4th CDROM: (not present) 7. (not implemented) 8. Log options for all devices 9. Log options for individual devices 10. Instruction tracing: off (doesn't exist yet) 11. USB runtime options 12. Misc runtime options 13. Continue simulation 14. Quit now Please choose one: [15] In the runtime configuration you can change the floppy/cdrom image or device, change the log options or adjust some other settings. If you have trouble with a specific device, you can change the log options for this device only to get more information (e.g. report debug messages). This cannot be done in the configuration file yet.
Save and restore simulation Starting with version 2.3, Bochs has limited save/restore support. The state of cpu(s), memory and all devices can be saved now. When running Bochs with there will be a button in the header bar called "Suspend". Depending on config interface and gui there will be a prompt where you can enter a path to an existing directory or a gui folder selection dialog box. It is possible to save the state at any time, but we recommend to do it when the simulation is idle. After pressing OK/Enter, Bochs will save a set of files into the selected folder. The state of hard disk images is not handled yet, so Bochs will ask you if you want to continue after saving state. We don't recommend to continue unless you are running a read-only guest system (e.g. Live-CD). To restore the saved simulation state you can select the restore function in the text mode start menu or specify the restore path at the command line: bochs -r /path/to/save-restore-data Then Bochs will start up using the saved configuration and log options, restores the state of the hardware and begins the simulation. In the restore mode Bochs will ignore bochsrc options from the command line and does not load a normal config file.
Common problems and what to do about them (Troubleshooting) &FIXME; How to report a panic to the bug tracker? Keyboard mapping problems [...]
Bochs panics! What can I do? Bochs does a very good job in emulating an x86 compatible computer, however, it does not (yet) include a full (100%) emulation of every possible instruction, (BIOS) function call or (hardware) device. Thus, in case something unusual happens, either a not-so-common call to some (BIOS) function or device by some software running inside of it, Bochs has two possibilities to react: If the command doesn't look important (mainly happens only to non-implemented functions in the BIOS), a notice is logged to the log file and the emulation continues. If, however, the command looks important, Bochs panics, because the software being emulated might depend on the successful execution of the given instruction or behavior of the device. A panic does not always mean that the software won't run inside of Bochs, as the software might just be probing the computer for the presence of some instruction/device, and in case it is not found, it simply won't be used at all, by the software. You can tell Bochs what to do in case of a panic, by re-configuring the panic option. If you change the action to "ask", Bochs reports what has happened and asks you what to do. The appearance of the "ask" feature depends on the display library used and the platform. Some display libraries don't support it at all. Some of the device names reported in the panic message are abbreviations, since the length of the 'prefix' is limited to 5 characters. The log function module table may help you finding out the name of the device that caused the panic. It also gives you a short description of the module.
Mouse behavior, enabling and disabling Refer to for information on how to enable or disable the mouse inside of Bochs at run-time. &FIXME; Mouse behavior
Text-mode is broken in some ancient DOS program If you are using a program written for DOS which seems to use the text-mode but doesn't display the text properly, you can try the other VGA BIOS, either VGABIOS-lgpl-latest or VGABIOS-elpin-2.40, see the vgaromimage option. &NEEDHELP; Maybe it is a bug in the LGPL VGA BIOS, but for now, it seems to work.
Mailing Lists The Bochs community uses three mailing lists to communicate, called bochs-developers, bochs-cvs and bochs-announce.
bochs-developers mailing list Bochs-developers is the forum for all Bochs discussions and questions. On average, subscribers get between five and ten messages per day. There are about 350 subscribers. If this sounds like too much email, maybe the bochs-announce list is more appropriate for you. Anyone may join the list, unless they abuse it of course. To subscribe, go to the Bochs-Developers Info Page and type your email address and a password into the web form and click Subscribe. In a few minutes you will get a confirmation email. Follow the directions in the email to complete the subscription process. To unsubscribe, go to the same page and type your email address in the blank at the bottom and click on Edit Options. Then type your password and click Unsubscribe. Once you have subscribed, you can write to bochs-developers@lists.sourceforge.net to send a message to everyone on the list. While it's possible to post without being a subscriber, it's not recommended. If you aren't a subscriber, you might miss the response to your question. Archive of bochs-developers messages
bochs-announce mailing list Bochs-announce is a moderated, low-traffic list which carries only periodic announcements of Bochs releases and important events. If you have a very important and truly relevant Bochs announcement, you can try posting it to bochs-announce, but the moderator will have to approve it before it will go out. On average, bochs-announce subscribers get one or two messages per month. There are about 75 subscribers. Anyone may join the list. To subscribe, go to the Bochs-Announce Info Page and type your email address and a password into the web form and click Subscribe. In a few minutes you will get a confirmation email. Follow the directions in the email to complete the subscription process. To unsubscribe, go to the same page and type your email address in the blank at the bottom and click on Edit Options. Then type your password and click Unsubscribe. There is no need to subscribe to both lists, because all bochs-announce messages are forwarded to the developers list. If you subscribe to both, you will get 2 copies of every announcement. Archive of bochs-announce messages
bochs-cvs mailing list This is the svn commit mailinglist (a unified diff email will be sent whenever someone does a checkin in the bochs SVN repository). Archive of bochs-cvs messages
Mailing List Etiquette Here are a few guidelines for use of the Bochs mailing lists: Please check the documentation before asking questions, but on this list you are very UNLIKELY to get flamed and insulted for being a Bochs beginner. Sending commercial promotions to the list probably will get you some angry responses though. If you are having difficulty finding what you are looking for, try doing a search on Google. If you are searching for Bochs options, for example, you can use this syntax in the Google search box: configuration options site:bochs.sourceforge.net For best results, be sure not to put a space between "site:" and "bochs.sourceforge.net". Be sure to look at more than the first item on the search results. If you still cannot find what you are looking for, be sure you are prepared when you post your question, and post in the right forum. Be sure you include important details, such as the operating system and version of your host, and what it is you are trying to do. If you are getting errors or something is not working, summarize what you checked and what you changed. This will help isolate the problem. Bochs is for everyone. If you are an experienced Bochs user or developer and are helping someone else, be considerate of the other person's feelings. We share a common interest, and we need to encourage each other and be supportive. Also, keep in mind that messages are limited to 40K, so if you want to share a large screen shot or disk image, put it on a web or FTP site and tell people how to find it. Patches are usually small enough that they aren't a problem, especially if compressed. Distribution of copyrighted material, or even offers to distribute copyrighted material WILL NOT be tolerated. The Bochs Project does not distribute any software (disk images) in violation of the license agreement, and users who do so will be warned first and then blocked from the list if it happens again. As an open source project, we rely on donated services from Source Forge and other groups, and we can't afford to put them or ourselves at risk of legal action. It is possible to subscribe and unsubscribe by email. If you do this, you must write to bochs-announce-request or bochs-developers-request. Don't forget the "-request" part or your subscribe message will go to 300+ people.
Tips and Techniques
Specify log options by device This table shows the name used for setting up the log actions per device, the prefix that appears in the log file or when a panic occurs and a short description of the module. This example shows how to turn on debug messages for a specific device in bochsrc. debug: action=ignore, pci=report The names can be used in upper case or lower case, since the check is not case sensitive. Note that the module names cannot be checked while reading the config file, since most of the modules do not exist at this point. Invalid names or names of modules not present in the current configuration will cause a panic when the simulation is starting. Log function module names and prefixes Name Prefix Description ACPI ACPI PIIX4 ACPI controller apic0 APIC0 APIC of first CPU BIOS BIOS System BIOS busmouse BUSM Busmouse BXVGA BXVGA VGA adapter with VBE support CD1 CD1 Lowlevel CD-ROM support for the first device (if configured, there can be CD2, CD3, CD4, ...) cirrus CLVGA Cirrus SVGA CMOS CMOS CMOS RAM + RTC cpu0 CPU0 First CPU (SMP emulation can have cpu1, cpu2, cpu3,...) devices DEV Devices subsystem DMA DMA DMA controller E1000 E1000 Intel(R) Gigabit Ethernet es1370 E1370 ES1370 soundcard extfpuirq EFIRQ External FPU IRQ floppy FDD Floppy controller gameport GAME Standard PC gameport GDBST GDBST GDB stub support GUI GUI Generic GUI code harddrv HD IDE HD/CD emulation hdimage IMG Disk image support ioapic IOAP I/O APIC iodebug IODBG I/O interface to debugger keyboard KBD PS/2 keyboard and mouse keymap KMAP Keyboard mapping logio IO Bochs logging subsystem memory MEM0 Memory management MGUI MGUI MacOS9 / MacOSX gui NE2K NE2K NE2000 ethernet adapter NGUI NGUI GUI without input/output interface ("nogui") parallel PAR Parallel port support PCI PCI i440FX PCI bridge pci2isa P2I PCI-to-ISA bridge pcidev PCI2H Host PCI device mapping pcipnic PNIC PCI pseudo NIC pci_ide PIDE PCI IDE controller pc_system SYS CPU-to-devices interface and timing control PIC PIC Programmable interrupt controller PIT PIT I/O interface for 82C54 timer pit82c54 PIT81 82C54 timer core PLGIN PLGIN Plugin interface RFB RFB RFB gui SB16 SB16 SB16 soundcard SCSIC SCSIC SCSI CD-ROM emulation for USB SCSID SCSID SCSI hard drive emulation for USB SDL SDL SDL gui serial SER Serial port emulation serial_raw SERR Lowlevel serial port support siminterface CTRL Simulator interface slowdown_timer STIME Slowdown timer speaker SPEAK Lowlevel support for the PC speaker SVGA SVGA SVGA gui TGUI TGUI Term gui unmappped UNMP Unmapped I/O handler usb_hid USBHI USB HID device emulation usb_hub USBHB External USB hub emulation usb_msd USBMS USB MSD (disk/cdrom) emulation usb_ohci OHCI USB OHCI controller usb_printer USBPR USB printer emulation usb_uhci UHCI USB UHCI controller usb_xhci XHCI USB xHCI controller VGA VGA Standard VGA vgabios VBIOS VGA BIOS virt_timer VTIME Virtual timer WGUI WGUI WIN32 gui WX WX wxWidgets gui XGUI XGUI X11 gui
How to make a simple disk image This was contributed by Greg Alexander in October 2001. What you need: An executable version of Bochs. See Downloading Bochs and Compiling Bochs. The bximage program, included with Bochs. A FreeDOS boot disk, or a boot disk from another OS capable of producing DOS partitions (e.g. a Linux install disk). (Optional) mtools, a program for manipulating DOS disks/images.
Create a flat image Option 1: Using the Unix dd utility: You will need to know the geometry of the disk you want to create. You have to compute the disk sector count: Sectors = Cylinders * Heads * SectorsPerTrack Use the dd command to create your file: dd if=/dev/zero of=teaching.img bs=512 count=sectors (replace "sectors" with the number you computed at the previous step). When you'll update your configuration file, please fill in the same cylinders, heads and sector per track values. Option 2: Run bximage to create a disk image file. You will be greeted with the following prompt: ======================================================================== bximage Disk Image Creation Tool for Bochs ======================================================================== Do you want to create a floppy disk image or a hard disk image? Please type hd or fd. [hd] Since we are creating a hard disk image, accept the default of hd by pressing Enter or typing 'hd' and pressing Enter. Next, bximage will ask for the type of hd to create: What kind of image should I create? Please type flat, sparse or growing. [flat] We want to create a simple flat image, so accept the default by pressing Enter. Then, bximage will ask for the size of the disk image you want to create, in Megabytes: Enter the hard disk size in megabytes, between 1 and 8257535 [10] Enter the size of the hard disk you want to create, and press Enter. Bochs will give you some information about the image it is creating, and ask you for a filename to use for the file it is creating. I told it to use the default of 10 megabytes, and was given the following information along with the prompt for a filename: [10] 10 I will create a hard disk image with cyl=20 heads=16 sectors per track=63 total sectors=20160 total size=9.84 megabytes What should I name the image? [c.img] At this point, type in the filename you want to use for the image. The default of "c.img" is appropriate if this will be your only hard disk image. After you have typed in the name of the filename you want to use, press Enter. Bximage will tell you it is writing the disk and will display a status bar as you wait. When it is finished, it will give you a final status report and tell you a line that should be added to your bochsrc when you want to use this disk image. I named my 10 Megabyte image "teaching.img" and the output of bximage looked like this: [c.img] teaching.img Writing: [..........] Done. I wrote 10321920 bytes to teaching.img. The following line should appear in your bochsrc: ata0-master: type=disk, path="teaching.img", mode=flat, cylinders=20, heads=16, spt=63 At this point, a file called "teaching.img" was created in my current directory and is ready to be used as an image file for a Bochs session. You may want to name your image teaching_20-16-63.img so that you always know the values to use for CHS.
Partition and format your image file Option 1: Using FreeDOS (Advantage: Creates a MBR on the partition.) First, you need to edit the bochsrc file that Bochs uses for configuration information (see ). Open bochsrc with a text editor. Remove all lines in the file which start with "ata0-master:". Add the "ata0-master:" line that was displayed when you ran bximage to bochsrc at the same place where you removed the old "ata0-master:" lines from. Also, you need to download or create a FreeDOS (or DOS, or Windows, or Linux) disk image. Modify the "floppya:" line in your bochsrc to point at the downloaded FreeDOS floppy image and change its status to "status=inserted". Save and close your bochsrc. Now run Bochs (see ). Use the standard FreeDOS commands fdisk and format to format your hard drive image. You must make the image bootable to be able to boot without a floppy disk. However, creating a bootable disk image is best done with a boot disk from the OS you intend to install on the image. Option 2: Using mtools (Disadvantage: Cannot create bootable images without a MBR image.) Use a text editor to add the following line to the file ~/.mtoolsrc: drive c: file="path/filename.img" partition=1 Save and close .mtoolsrc. Next, execute the following commands to create a partition table for the drive image: mpartition -I -s spt -t cyl -h heads c: mpartition -cpv -s spt -t cyl -h heads c: For example, for my 10 meg drive, I used: mpartition -I -s 63 -t 20 -h 16 c: mpartition -cpv -s 63 -t 20 -h 16 c: Next, format the partition you just created using the mformat command: mformat c: And you now have a formatted disk image containing a single DOS partition. The mpartition command doesn't handle images larger than 1024 cylinders properly. The partition size reported by fdisk is okay, but mformat reports only 504 MB (tested with mtools 3.9.9).
Use mtools to manipulate disk images Mtools is a set of programs that can read, write, and format DOS disk images. There are links to the Mtools main page and a Win32 port of Mtools on the Bochs Links page, under Resources. The mtools web site has a detailed manual. If anyone wants to write instructions specific to Bochs, we can add it right here.
Bochs GNU/Linux DiskTools &FIXME; Bochs tools are external tools developed by ..., and useful to copy to / from guest partition from a GNU/Linux host.
Win32 only: Tools to manipulate disk images
Winimage Someone on the bochs-developers list mentioned that they use a program called WinImage, from www.winimage.com to read and write disk images (floppy and hard disk). Winimage is a commercial product with a 30-day trial. If anyone wants to write a tutorial, send mail to &devlist; and volunteer.
DiskExplorer This section was contributed by Luca Cassioli and Stanislav Shwartsman I eventually found what all of you were looking for for a long time: a freeware, graphical, win32 compatible HardDisk image editor! It can handle a large variety of formats, but the one you need is VMWARE 2.0 PLAIN DISK: you can import/export to/from Bochs images COMPLETE DIRECTORIES! You can find it at http://hp.vector.co.jp/authors/VA013937/editdisk/index_e.html
Ben Lunt's MTOOLs for Bochs and Win32 and/or DOS Ben Lunt wrote a set of utilities for Dos/Win32 to manipulate flat disk images. You can find it at http://www.frontiernet.net/~fys/mtools.htm These utilities includes : BOCHSRC.EXE "Bochs Resource" A utility to create/modify a Bochs resource file. MKDOSFS.EXE "Make DOS FS" A utility to create a FAT disk image of specified size. MCOPYF.EXE "Copy From" A utility to copy an existing file from a FAT disk image to the current directory. MDEL.EXE "Delete file" A utility to delete an existing file from a FAT disk image. MDIREX.EXE "Directory Extended" A utility to view a FAT disk images directory and FAT contents. MGETIMG.EXE "Get Disk Image" A utility to create a disk image from a floppy (multiple formats). MBOOTCD.EXE "Create a CDROM Image with boot options" Create a CDROM image capable of booting with only a ROOT and a single file. MGETCD.EXE "Get Disk Image of Physical CD" A utility to create a disk image from a CD. MCDINFO.EXE "Get CD Info" A utility to the info from a CD. Not much yet, but a little.
X Windows: Color allocation problems One common problem in X windows is that the screen colors can be abnormal if other X programs have already allocated all the colors. If the colors don't look right, try quitting colorful applications such as Netscape, clearing any complex images in the background, etc. so that Bochs has a chance to allocate the colors it needs. If Bochs continues to have problems, or you want Bochs to have perfect colors without having to quit any other application, you can try turning on the private_colormap option in the configuration file. Using a private colormap causes the Bochs window to have its own set of 256 colors to work with. When the cursor is over the Bochs display, Bochs will look correct and other parts of the screen may change to very strange colors. When the cursor goes to any other window, the other windows will look correct and Bochs will have strange colors. A better solution, if your hardware can support it, is to run your X server with 24-bit or 32-bit color.
Screen saver turns on too quickly One thing you may notice is that the screen saver turns on (screen goes blank) very quickly after you have stopped typing. The reason is that Bochs simulates everything as fast as it can. If the CPU is very busy (running instructions nonstop), simulated time goes by slowly. If the CPU is idle (just waiting for you to type, for example), simulated time speeds up dramatically. In any case, if the screen saver blanks out the screen, just press a key (try shift or control) to restore the screen. There are two strategies to fix this problem. One is to increase the ips parameter of the cpu option in your configuration file. This will cause the simulation time to pass more slowly. The other strategy is to enable the experimental realtime PIT, which tries to keep Bochs in sync with real time. See the bochsrc option clock.
Mounting a disk image using the loop device This section describes how to access a floppy or hard disk image within Linux using the loop device. Why would you want to do this? Let's say you have made a small Linux disk image for Bochs, and you want to install some more software on it. You have already downloaded the software onto your real system, so now you want to transfer it to the Bochs disk image. A fast way to transfer the files is to mount the disk image using the loop device.
...on Linux This section was contributed by Volker Ruppert. Today I have made some tests with the loop device, because I want to exchange files with the bochs disk images. This is what I found out: 1. Using Floppy images is easy, because there is no partition table: losetup /dev/loop0 /usr/local/bochs/dlxlinux/floppya.img Now you can use the image like a real floppy: - format : mkfs.minix /dev/loop0 - filesystem check : fsck.minix /dev/loop0 - mount : mount /dev/loop0 -o loop /mnt/floppy Before you want to restart bochs you must do this: losetup -d /dev/loop0 Don't forget to umount before. 2. If you want access to a hard disk image, you have to calculate the size of the first cylinder. This value is the offset argument for losetup. offset = bytes per sector * sectors per cylinder The command for dlxlinux image looks like this: losetup /dev/loop0 /usr/local/bochs/dlxlinux/hd10meg.img -o 8704 For images created by bximage you must use the value 32256. 3. The hard disk image access doesn't work if the image contains more than one partition. 4. I have made this tests with Linux and I don't know how this could be done with other operating systems.
...on FreeBSD This section was contributed by Alexander Schuch. The following example mounts a Windows 95 hard disk image called Windows 95 B (2031-16-63) into the FreeBSD file system. It is specific to FreeBSD 5.x; for hints on how to do the same task on FreeBSD 4.x, or for more information in general, check the proper section of the FreeBSD handbook: Network, Memory, and File-Backed File Systems. You can use the same procedure for mounting floppy disk images. # mdconfig -a -t vnode -f "Windows 95 B (2031-16-63)" md0 mdconfig returns the device, your file now is accessable from. # mount -t msdosfs /dev/md0s1 /mnt If you already have other md devices configured, you need to substitute md0s1 with, for example, md6s1. Once you are done working with the image, unmount the md device and detach it. # umount /mnt # mdconfig -d -u 0 And again, if there are other md devices configured, use the proper device number. In case you forgot the number, just ask mdconfig, like: # mdconfig -l md7 # mdconfig -d -u 7
Simulating a Symmetric Multiprocessor (SMP) Machine Bochs can now simulate an SMP machine when you use in the configure command. SMP support was added by Bryce Denney, who was very interested in watching a multiprocessor operating system work at a low level. It should also be helpful to operating system developers who are writing SMP drivers, or just for users who want to test drive an SMP machine to see what it looks like. Starting with Bochs 2.2.6 you can set up the number of processors in the bochsrc. See how to set up the number of processors. It is important to understand that configuring bochs for 4 processors will NOT make your single-threaded applications run faster in general! On the contrary, it has to spend time simulating idle processors as well as the ones doing your task. The point is to simulate an SMP system, not to speed up a uniprocessor application. What was required to make SMP work in Bochs? local APIC on each processor with timer one I/O APIC model implement RDTSC (read time stamp counter) a data structure called the Intel Multiprocessor Configuration must be present in BIOS memory space. An SMP-aware operating system probes BIOS memory to find the structure, which contains information about how many processors, their IDs, interrupt sources, etc. Starting with Bochs 2.2.5 these structures are dynamically created by Bochs. ACPI support is required to boot SMP system in most of modern operating systems. For example WinXP 64 bit require ACPI support even for single processor configuration. What needs to be done to improve SMP support? debugger support is still limited. For example, you can set breakpoints, but you can't specify which processor you want to set the breakpoint for. test on any possible SMP operating systems. Currently success reported for Knoppix 4.0.2, WinNT 4.0 and WinXP SMP. several parts of the APIC model which weren't needed before are not implemented yet. A number of people have suggested using threads to simulate each CPU in a different thread. Then on a real SMP machine, the threads can execute in parallel. This is a great idea, but it's not done at present.
Setting Up Networking in DLX Linux All Bochs binaries come with a working version of DLX Linux. This section describes how to configure networking in Bochs and enable it within DLX Linux. First you must add a ne2k line in your bochsrc file. Then, when you boot the DLX Linux image, you need to type some Linux commands to set up an IP address, a network route, and a name server. When you have an ne2k line in your bochsrc file, Bochs will emulate a network card called an NE2000. Below are some examples of valid ne2k lines for various operating systems. Choose the one that's closest to what you need, add it to your bochsrc file, and edit the values if necessary. # sample for Mac OS X ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=en0 # sample for FreeBSD ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0 # sample for Linux ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 # sample for Windows ne2k: ioaddr=0x300, irq=9, mac=00:c4:3B:00:C3:00, ethmod=win32, ethdev=NE2000 You see the pattern. Usually you won't need to change the I/O address, IRQ number, or MAC address. The ethmod value depends on your host operating system, and it must be either null, fbsd (for FreeBSD or OpenBSD), linux, or win32. The ethdev setting is the name of the network interface on your system, and is also OS-dependent. On UNIX systems you can get the name of the network interface by running ifconfig. (Don't choose the loopback interface.) On Windows systems, the correct ethdev setting is not always obvious, so we provide a utility called niclist to list the names of network interfaces to use. When you run niclist, it will suggest an ne2k line which is a very good first try. Next, if you are on a UNIX machine you will need to become the root user. Since bochs is sending and receiving raw network packets, you need to be root to use the network device. To allow normal users to do this would be a security problem. Now run Bochs to boot DLX Linux. Press enter a few times to accept the default configuration choices. This tells Bochs read the configuration file and then begin. DLX Linux should boot in the Bochs window, and you should see that Linux detects the NE2000 card. Eventually it gets to a login prompt. ne.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov) NE*000 ethercard probe at 0x300: b0 c4 20 00 00 00 eth0: NE2000 found at 0x300, using IRQ 9. At the login prompt, type "root" to log in as root. Then type the ifconfig and route commands to set up networking. The exact IP numbers in the example won't work for you; you must choose an IP configuration that is legal on your network. dlx login: root Linux 1.3.89. dlx:~# ifconfig eth0 192.168.0.99 # set bochs IP address dlx:~# route add -net 192.168.0.0 # first 3 numbers match IP dlx:~# route add default gw 192.168.0.1 # your gateway to the net dlx:~# _ The bochs IP address must be an unused IP address on your network. If you duplicate someone else's IP address, your network will become very confused. Finally, the network is ready and you can test it out with ping, telnet, or ftp to various machines by their numerical IP address. Keep in mind that for all UNIX host platforms, Bochs networking cannot talk to the host machine. That means the host machine can't be the gateway either. You need another physical machine on the network that bochs can talk to. On Win32 this restriction does not apply. When you have a working network configuration, you can make DLX Linux recreate the same settings the next time you boot. Just add the ifconfig and route commands to the end of /etc/rc.d/rc.inet1. I won't try to describe how to use the vi editor in this limited amount of space... To configure a name server, set up /etc/resolv.conf with the IP address of your name server as shown. dlx:~# echo 'nameserver 192.168.0.1' > /etc/resolv.conf
Configuring and using a tuntap network interface If you use linux (optionally FreeBSD and Solaris, not tested), you may want to access the network through a tuntap interface. The main advantage of this interface, is that the guest has access to the host. The guest can even have access to the whole network if the host routes or masquerades the guest requests. No extra IP address is needed, all can be done using private IP addresses. You'll find here instructions to set up Linux/Bochs to provide network access to the guest OS through a tuntap interface and private IP network. We're going to see howto : enable the tuntap interface in the Linux Kernel configure Bochs to use the tuntap interface set up the private network between the host and the guest set up the host to masquerade the guest network accesses
Tuntap description From the tuntap.txt file in the Linux kernel tree : TUN/TAP provides packet reception and transmission for user space programs. It can be viewed as a simple Point-to-Point or Ethernet device, which instead of receiving packets from a physical media, receives them from user space program and instead of sending packets via physical media writes them to the user space program. When a program opens /dev/net/tun, driver creates and registers corresponding net device tunX or tapX. After a program closed above devices, driver will automatically delete tunXX or tapXX device and all routes corresponding to it.
Set up the linux Kernel <footnote><para>much of the information of the following section is taken from <ulink url="http://maconlinux.org/lists/mol-general/August01/0056.html"> this email from Samuel Rydh of the Mac-On-Linux list</ulink></para></footnote> First make sure the tuntap module is included in the kernel : if you use a recent distribution, chances are that the needed modules are already build Make sure that "Kernel module loader" - module auto-loading support is enabled in your kernel. Add following line to the /etc/modules.conf: alias char-major-10-200 tun Run: depmod -a The driver will be automatically loaded when application access /dev/net/tun. Otherwise, recompile the kernel, including the configuration option CONFIG_TUN (Network device support -> Universal TUN/TAP device driver support) Make sure there is a /dev/net/tun device. (Can be created with 'mkdir /dev/net ; mknod /dev/net/tun c 10 200'). In the same way, to use masquerading, you need a kernel with the following options : CONFIG_IP_NF_CONNTRACK (Connection tracking) CONFIG_IP_NF_IPTABLES (IP tables support) CONFIG_IP_NF_NAT (Full NAT) Some of the other options in this group is probably also needed, (but the default setting should be OK).
Configure Bochs to use the tuntap interface Make sure Bochs has ne2000 support. If you have to recompile Bochs, when running ./configure (see ) edit your .bochsrc configuration file and add something like : ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=/path/to/tunconfig Since the tuntap interface cannot be configured until a process opens it, Bochs may run a script file for you. In this case /path/to/tunconfig should be changed to match the actual place where you'll create this script.
Set up the private network between the host and the guest We'll set up a private network between the host and the guest with the following parameters: Host IP : 192.168.1.1 Guest IP : 192.168.1.2 If your parameters are different, adapt the rest of the section to suit your needs. Create the /path/to/tunconfig script : #!/bin/bash /sbin/ifconfig ${1##/*/} 192.168.1.1 The script get the interface name as the first parameter. Linux will forward incoming packets between interfaces. Make it executable :chmod 755 /path/to/tunconfig Run Bochs, install the guest OS, and set the following network parameters in the guest OS: IP: 192.168.1.2 netmask: 255.255.255.0 gateway: 192.168.1.1 nameserver: whatever is used in linux Bochs must be started by root (at least for now - the script won't have root privileges otherwise). You may also have to edit /etc/hosts.allow in the host OS and add : ALL: 192.168.1.2 Don't forget to set up the route on the guest. At this point, you should be able to ping/telnet/ftp/ssh the guest from the host and vice-versa.
Set up the host to masquerade the guest network accesses We are going to set up standard masquerading configuration. Edit the /path/to/tunconfig script ans add : /sbin/iptables -D POSTROUTING -t nat -s 192.168.1.0/24 -d ! 192.168.1.0/24 -j MASQUERADE >& /dev/null /sbin/iptables -t nat -s 192.168.1.0/24 -d ! 192.168.1.0/24 -A POSTROUTING -j MASQUERADE echo 1 > /proc/sys/net/ipv4/ip_forward The configuration assumes the default policy is ACCEPT (can be examined by doing '/sbin/iptables -L') The iptables package must be installed. And voila... The host should forward the packets of the guest to the rest of your network. You could even have acces to the internet... &FIXME; add nice screenshot You may need to load other modules if you want to use other fancy protocols (ftp,etc...)
Using Bochs internal debugger Note, if you are looking for a graphical front-end for the bochs debugger, you may want to check out BFE. This is a package written by a Bochs user which can interface with the text based Bochs debugger. No linking is necessary. It's not part of Bochs, but you may find it useful. You can now conditionally compile in a GDB like command line debugger, that allows you to set breakpoints, step through instructions, and other useful functions. If there isn't a command for something you believe is generally useful for the debugger, let me know and I'll implement it if possible. To use the debugger, you must configure Bochs with the and flags. For example: ./configure --enable-debugger --enable-disasm You must use flex version 2.5.4 or greater. I have heard that version 2.5.2 will not work. When you first start up Bochs, you will see the command line prompt bochs:1> From here, you may use the following commands:
Execution Control c continue executing cont continue s [count] execute count instructions, default is 1 step [count] s [cpu] [count] for SMP simulation, execute count instructions on cpu, default is 1 step [cpu] [count] s all [count] for SMP simulation, execute count instructions on all cpus step all [count] Ctrl-C stop execution, and return to command line prompt Ctrl-D if at empty line on command line, exit q quit debugger and execution quit exit
BreakPoints NOTE: The format of 'seg', 'off', and 'addr' in these descriptions, are as follows. I don't have any way to set the current radix. hexidecimal: 0xcdef0123 decimal: 123456789 octal: 01234567 vbreak seg:off Set a virtual address instruction breakpoint vb seg:off lbreak addr Set a linear address instruction breakpoint lb addr pbreak [*] addr Set a physical address instruction breakpoint pb [*] addr (the '*' is optional for GDB compatibility) break [*] addr b [*] addr info break Display state of all current breakpoints bpe n Enable a breakpoint bpd n Disable a breakpoint delete n Delete a breakpoint del n d n
Memory WatchPoints watch read addr Insert a read watch point at physical address addr watch r addr Insert a read watch point at physical address addr watch write addr Insert a write watch point at physical address addr watch w addr Insert a write watch point at physical address addr watch Display state of current memory watchpoints watch stop Stop simulation when a watchpoint is encountered (default) watch continue Do not stop simulation when a watchpoint is encountered unwatch addr Remove watchpoint to specific physical address unwatch Remove all watch points trace-mem on/off Enable/Disable memory access tracing
Manipulating Memory x /nuf addr Examine memory at linear address addr xp /nuf addr Examine memory at physical address addr n Count of how many units to display u Unit size; one of b Individual bytes h Halfwords (2 bytes) w Words (4 bytes) g Giant words (8 bytes) NOTE: these are *not* typical Intel nomenclature sizes, but they are consistent with GDB convention. f Printing format. one of x Print in hexadecimal d Print in decimal u Print in unsigned decimal o Print in octal t Print in binary n, f, and u are optional parameters. u and f default to the last values you used, or to w(words) and x(hex) if none have been supplied. n currently defaults to 1. If none of these optional parameters are used, no slash should be typed. addr is also optional. If you don't specify it, it will be the value the next address (as if you had specified n+1 in the last x command). setpmem addr datasize val Set physical memory location of size datasize to value val. writemem dump a number of bytes of virtual memory starting from the specified linear address into a file crc addr1 addr2 Show CRC32 for physical memory range addr1..addr2
Info commands r|reg|regs|registers List of CPU integer registers and their contents fp|fpu List of all FPU registers and their contents mmx List of all MMX registers and their contents sse|xmm List of all SSE registers and their contents ymm List of all AVX registers and their contents sreg Show segment registers and their contents dreg Show debug registers and their contents creg Show control registers and their contents info cpu List of all CPU registers and their contents info eflags Show decoded EFLAGS register info break Information about current breakpoint status info tab Show paging address translation info device Show state of the specified device
Manipulating CPU Registers set reg = expr Change a CPU register to value of expression. Currently only general purpose registers are supported, you may not change: eflags, eip, cs, ss, ds, es, fs, gs. Examples: set eax = 2+2/2 set esi = 2*eax+ebx registers List of CPU registers and their contents regs reg r
Disassembly commands disassemble start end Disassemble instructions in given linear address range, inclusive of start, exclusive of end. Use "set $disassemble_size =" to tell debugger desired segment size. Use a value for end of less than start (or zero) if you only want the first instruction disassembled. disassemble switch-mode Switch between Intel and AT&T disassebly styles for debugger disassembler. disassemble size = n Tell debugger what segment size to use when the "disassemble" command is used. Use values of 0, 16 or 32 for n. Value of 0 means "use segment size specified by current CS segment". Default is 0. set $auto_disassemble = n Cause debugger to disassemble current instruction every time execution stops if n=1. Default is 0. Segment size of current CPU context is used for disassembly, so the "disassemble size" variable is ignored. set disassemble on The same as 'set $auto_disassemble = 1' set disassemble off The same as 'set $auto_disassemble = 0'
Instruction tracing trace on Disassemble every executed instruction. Note that instructions which caused exceptions are not really executed, and therefore not traced. trace off Disable instruction tracing.
Instrumentation To use instrumentation features in bochs, you must compile in support for it. You should build a custom instrumentation library in a separate directory in the "instrument/" directory. To tell configure which instrumentation library you want to use, use the option. The default library consists of a set of stubs, and the following are equivalent: ./configure [...] --enable-instrumentation ./configure [...] --enable-instrumentation="instrument/stubs" You could make a separate directory with your custom library, for example "instrument/myinstrument", copy the contents of the "instrument/stubs" directory to it, then customize it. Use: ./configure [...] --enable-instrumentation="instrument/myinstrument"
Instrumentation commands instrument [command] calls BX_INSTR_DEBUG_CMD instrumentation callback with [command]
Other Commands ptime Print the current time (number of ticks since start of simulation). sb delta Insert a time break point "delta" instructions into the future ("delta" is a 64-bit integer followed by "L", for example 1000L). sba time Insert a time break point at "time" ("time" is a 64-bit integer followed by "L", for example 1000L). print-stack [num words] Print the num words top 16-bit words on the stack. Num words defaults to 16. Only works reliably in protected mode when the base address of the stack segment is zero. modebp Toggles CPU mode switch breakpoint. ldsym [global] filename [offset] Load symbols from file filename. If the global keyword is added, then the the symbols will be visible in all contexts for which symbols have not been loaded. Offset (default is 0) is added to every symbol entry. The symbols are loaded in the current (executing) context. The symbol file consists of zero or more lines of the format "%x %s". show [string] Toggles show symbolic info (calls to begin with). show - shows current show mode show mode - show, when processor switch mode show int - show, when interrupt is happens show call - show, when call is happens show ret - show, when iret is happens show off - toggles off symbolic info show dbg-all - turn on all show flags show dbg-none - turn off all show flags
Related links &FIXME; add links Cosimulation Instrumentation
Using Bochs and the remote GDB stub This section covers how you can use Bochs with a remote GDB stub to debug your kernel.
Configuring Bochs The GDB stub is not active in standard Bochs binary package. So you must recompile Bochs. Download the Bochs source package, unpack it and run the configure script with the argument. $ ./configure --enable-gdb-stub After that, just run make and you should have a Bochs binary that contain a GDB stub in your directory.
Running Bochs Enable the gdbstub option in bochsrc, then just start Bochs as normal. Bochs will stop and wait for GDB to connect to the stub.
Running GDB Bochs GDB stub waits for a connection on TCP port 1234. Just start GDB like this: $ gdb YOUR-KERNEL . . . (gdb) target remote localhost:1234 Remote debugging using localhost:1234 0x0000fff0 in ?? () (gdb) You are now connected to the remote GDB stub in Bochs. You are now able to set breakpoints. Use the continue (c) command to continue the simulation. Hitting ^C works. Example: Program received signal 0, Signal 0. syscall_testsuite_result (aux=0x1f11fe4) at ../rtmk/syscalls.c:33 33 { (gdb)
Using the serial port This section describes what is possible to do with Bochs serial port emulation. These examples use dlxlinux disk image (downloaded from http://bochs.sourceforge.net/guestos/dlxlinux3.tar.gz ) running as guest, on a debian x86 linux 2.4.19 host. For the examples to work in dlxlinux, after you login as root, you will need to kill the running gpm, as it grabs the serial port. Welcome to DLX V1.0 (C) 1995-96 Erich Boehm (C) 1995 Hannes Boehm dlx login: root Linux 1.3.89. dlx:~# ps | grep gpm 30 S0 S 0:00 /usr/bin/gpm -t bare 40 1 S 0:00 grep gpm dlx:~# kill -9 30 dlx:~#
Logging serial port output to a file The first example shows how to log information sent to the serial port on the guest system into a file on the host system. Update the com1: section of your configuration file: com1: enabled=1, mode=file, dev=serial.txt After you've launch dlxlinux, everything sent to the serial port will be logged to serial.txt : dlx:~# echo "logging to the serial port" > /dev/cua0 host$ cat serial.txt logging to the serial port host$
Interactivity : connecting to a virtual terminal The second example shows how to connect to the guest OS, using a virtual terminal on the host OS. First, you need to find an unused virtual terminal. Typically, X uses vt7; vt8 and up are unused. On my system, I can switch from X to vt9 by pressing ctrl-alt-f9 : this virtual terminal is not used, the screen is all black. Pressing alt-f7 switches back to X. Once you found an unused vt, update the com1: section of your configuration file: com1: enabled=1, mode=term, dev=/dev/tty9 The number must be set according to the terminal you want to use (here 9). Now, launch dlxlinux. After you log in as root and kill gpm, enter the following command: dlx:~# /sbin/agetty 38400 cua0 If you switch to vt9, you can see dlx welcome banner, and the login prompt: Welcome to DLX V1.0 (C) 1995-96 Erich Boehm (C) 1995 Hannes Boehm dlx login: Note that dlxlinux is configured so you can not login as root from a serial port. If you want to login, you have to create a new user first. Also, if you plan to use this feature, the best would be to deactivate gpm in /etc/rc.d/rc.local, and add a agetty line in /etc/inittab, for example: T0:1234:respawn:/bin/agetty 38400 cua0
Interactivity : connecting to a pseudo terminal The third example is very similar to the second one, except that we connect to the guest OS with kermit as client, and we the connection is done through a pseudo terminal. This example uses /dev/ptyp0 and /dev/ttyp0 as pseudo terminal pair. We will tie Bochs to the controlling terminal, whereas kermit will use the slave terminal. Update the com1: section of your configuration file: com1: enabled=1, mode=term, dev=/dev/ptyp0 and lauch dlxlinux. After you log in as root, enter the command: dlx:~# /sbin/agetty 38400 cua0 Then in the host OS, launch kermit : host$ kermit -l /dev/ttyp0 C-Kermit 7.0.196, 1 Jan 2000, for Linux Copyright (C) 1985, 2000, Trustees of Columbia University in the City of New York. Type ? or HELP for help. (/tmp/) C-Kermit>connect Connecting to /dev/ttyp0, speed 0. The escape character is Ctrl-\ (ASCII 28, FS) Type the escape character followed by C to get back, or followed by ? to see other options. ---------------------------------------------------- Welcome to DLX V1.0 (C) 1995-96 Erich Boehm (C) 1995 Hannes Boehm dlx login: The same comments as for example 2 apply here.
BIOS Tips
Booting from CD-ROMs A bootable CD-ROM has a special layout that is detected by the BIOS boot loader code, and executed if it conforms the specifications. This layout is called "El Torito Bootable CD-ROM Format Specification" and has been published by Phoenix and IBM. A copy of this spec is on Bochs tech specs page. El Torito specifies 3 ways to have a bootable CD: floppy emulation boot: A standard floppy image is burnt on the CD. In this case the BIOS has to redirect all first floppy accesses to this image and the real floppy drive becomes the second one. a "no emulation" boot: In this case the BIOS is instructed to load an arbitrary number of sectors straight into memory, and execute it. hard disk emulation: A hard disk image is burnt on the CD. The BIOS has to redirect all hard disk accesses to that image. The real hard disks are still available, with BIOS numbers 81h and up. In Bochs 2.0, hard disk emulation is not implemented in the BIOS. There are also subtilities about multiple boot-images CD-ROMs, that are not handled by Bochs. However, our BIOS may be more strict than real PC BIOSes, I don't know. But I would definitely be interested to know of any CD that can boot on real hardware, but does not in Bochs. When failing to boot from CD-ROM, the BIOS outputs the reason of the failure as an error code, in the log file, and on the screen. Here is a summary of what can happen when booting from the CD. CD Boot error codes Error code Reason 0x01 no atapi device found 0x02 no atapi cdrom found 0x03 can not read cd - BRVD 0x04 cd is not eltorito (BRVD) 0x05 cd is not eltorito (ISO TAG) 0x06 cd is not eltorito (ELTORITO TAG) 0x07 can not read cd - boot catalog 0x08 boot catalog : bad header 0x09 boot catalog : bad platform 0x0A boot catalog : bad signature 0x0B boot catalog : bootable flag not set 0x0C can not read cd - boot image
0x01 no atapi device found 0x02 no atapi cdrom found For the first two errors, an ata-*: type=cdrom is probably missing from the configuration file. This is what you get if no cdrom has been defined in Bochs conf file. 0x03 can not read cd - BRVD For this error, the cdrom support has not been compiled in Bochs, or Bochs could not open the file or device. This is what you get if Bochs is not able to read the cd. 0x04 cd is not eltorito (BRVD) 0x05 cd is not eltorito (ISO TAG) 0x06 cd is not eltorito (ELTORITO TAG) For these errors, the data has been read from the cd, but the cd does not conform to the El Torito specification. This is what you get if the cd is not bootable. 0x08 boot catalog : bad header 0x09 boot catalog : bad platform 0x0A boot catalog : bad signature 0x0B boot catalog : bootable flag not set now the cd is eltorito, but the boot catalog is corrupted, or the cd was made to boot on a ppc system. This should not happen for a x86 bootable cd. 0x07 can not read cd - boot catalog 0x0C can not read cd - boot image here, specific part of the cd could not be read. This should definitely not happen.
Disk translation Since the beginning of the PC era, disks have grown in size by a factor of 10000. Due to differences between the ATA specification and BIOSes implementations, when disks reached critical sizes, it became necessary to translate the CHS geometry (cylinders, heads, sectors per track) between the BIOS (int 13h) and the ATA interface. Please refer to the ATA-FAQ and Hale Landis' document for a complete discussion of the problem. Unfortunately, there has never been any standard on the translation algorithms. Bochs implements 4 well-known algorithms, selectable in the configuration file in the "ataX-xxxx: ..., translation='algorithm'" section. Disk translation algorithms Algorithm Maximum disk size Maximum logical and physical geometry (CHS) Description none 528MB (1032192 sectors) LCHS:1024/16/63 PCHS:1024/16/63 no translation is done. The CHS received at the int13h interface is sent as is to the ATA interface. large 4.2GB (8257536 sectors) LCHS:1024/128/63 PCHS:8192/16/63 a standard bitshift algorithm (named Extended-CHS) is used to translate the CHS between the int13h interface and the ATA interface. The translation is achieved by multiplying/dividing the cylinder/head count by a power of 2 (2, 4 or 8). (a factor of 16 could not be used because the head count would become 256, and MS-DOS thought this was 0) Note that the number of sectors per track is not changed, so a lower spt value will lead to a lower maximum disk size. echs synonym for large rechs 7.9GB (15482880 sectors) LCHS:1024/240/63 PCHS:15360/16/63 a revised bitshift algorithm (called Revised Extended-CHS) is used to translate the CHS between the int13h interface and the ATA interface. First the number of physical heads is forced to 15, and the number of cylinders is adjusted accordingly. Then, as in the simple extended CHS algorithm, the translation is achieved by multiplying/dividing the cylinder/head count by a power of 2 (2, 4, 8 or 16). The head count being forced to 15, it can safely be multiplied by 16 without crashing dos. Note that the number of sectors per track is not changed, so a lower spt value will lead to a lower maximum disk size. lba 8.4GB (16450560 sectors) LCHS:1024/255/63 PCHS:16320/16/63 a LBA-assisted algorithm is used to translate the CHS between the int13h interface and the ATA interface. The translation is achieved by first computing the physical size of the disk (LBA=C*H*S). Then the sectors per track is forced to 63, and the head count to 255. Then the cylinder count is computed (C=LBA/(63*255)) Note that the number of sectors per track is forced to 63 in the logical geometry, regardless of the actual geometry reported by the disk. Also note that the LBA-assisted algorithm has nothing to do with LBA access at the ATA interface. auto the best suited algorithm between none, large and lba is used
Setting a specific CHS translation should be done if you use a disk dump of an actual disk, or use a real disk as a block device. You need to know which geometry was used to format the disk, and which translation was used. You must not set the translation to 'auto'. rechs translation should only be useful for Compaq users who wants to use a disk as a block device. Please report if you know any other system that use such translation. If you plan to create a new disk image (for example with bximage), format it and install an OS on it, select the "auto" translation for an automatic selection of the best algorithm based on the disk image size. Be warned that an image created with the "auto" translation might not be readable with previous versions of Bochs. Upward compatibility will be maintained. This translation applies only to int13h BIOS disk accesses. Older OSes (e.g. MS-DOS) tend to use them a lot. On modern OSes, disk accesses through BIOS int13h are limited to boot loaders. The usual rules and tricks of the installed OS still apply (ie 1024 cylinders boot limit).
How to enter special key combination Your window manager may trap the key combination you want to enter in Bochs guest OS, for example controlaltdelete. Here is a work-around: Press and hold controlalt, move your mouse cursor outside of the Bochs window. Release them, move the cursor back in the Bochs window and press delete. This should work for any key combination. If you need one key combination frequently, set it up as user key combination in your configuration file. This key combination is sent to the guest OS when you press the user button in the headerbar. Depending on the used display_library option, it may even be possible to edit the shortcut before sending it.
Notes about VESA usage Since Bochs 1.4 it is possible to use VESA graphics. There are some limitations in the current implementation, but in general it should work ok (we have run several test programs, the XFree86 VESA display driver, etc.) In order to use VESA VBE, you need to enable it in your bochsrc by setting the vga option to vbe. Finally, you need to use the LGPL'd VGABIOS as vgaromimage option for applications to correctly detect VESA support. The VGABIOS is already included in the Bochs release, so no separate download is necessary. To take advantage of the VBE, you must tell Bochs to use the LGPL'd VGA BIOS version 0.4c or higher. A current version of the VGA BIOS will work. Current limitations: 4bpp modes support is incomplete (8, 15, 16, 24 and 32bpp should work) banked mode is very slow (if you can, just use Linear Frame Buffering instead!) only 320x200, 640x400, 640x480, 800x600, 1024x768 are currently supported Interesting Facts: You need a display driver capable of using the VESA BIOS for this to work (a recent XFree86 will do, Windows 9x/NT/2K/XP probably will not work 'out of the box'. Currently the VBE2 extension should be supported ok
Instructions to setup Bochs VBE in Windows Guest OS This was contributed by Martin Bochnig in February 2004. Instructions for Win95/98: ========================== I can only confirm that SciTech finally made a VBE driver for Windows. It works out of the box, at least with win95 as guest OS, provided you use Bochs 2.1 with the LGPL vgabios. Here is how I did it : - install win95 with the vga driver. - download sdd 7 beta from - download pmhelp.vxd from - copy pmhelp.vxd to the win95 system directory - install sdd7 800x600 and 1024x768 in 16 and 24 bpp modes here. I did not try 32bpp. This was contributed by Stanislav Shwartsman in September 2004. Instructions for Win2000/XP: ============================ Bochs VBE Display Drivers for Windows NT/2000
Notes about Cirrus SVGA usage Since Bochs 2.2 it is possible to use Cirrus SVGA graphics. The Cirrus device supports both ISA and PCI depending on the bochsrc settings. If PCI is disabled or the Cirrus card is not assigned to a PCI slot, it appears as a CL-GD5430 ISA with 2MB VRAM. If you assign the Cirrus card to a PCI slot, it appears as a CL-GD5446 PCI with 4MB VRAM. In order to use Cirrus SVGA, you need to compile Bochs using the option and enable it in your bochsrc by setting the vga option to cirrus. Finally, you need to use the Cirrus version of the LGPL'd VGABIOS as vgaromimage option for applications to correctly detect Cirrus support. # Enable CL-GD5446 PCI vga: extension=cirrus vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest-cirrus pci: enabled=1, chipset=i440fx, slot1=cirrus The VGABIOS is already included in the Bochs release, so no separate download is necessary.
Disk Image Modes Bochs can handle independent disk image format for each disk present on the ata interfaces. The disk image type is selected in the configuration file by the "mode" option of the ataX-xxx directives. Example: ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17 If unspecified, the default "mode" is flat. Supported Disk Modes Name Description Features flat one file, flat layout accessible with mtools or winimage-like tools concat multiple files, concatenated mappable to contained partitions external accessed through an external C++ class developer specific, needs a C++ class at compile time dll accessed through a DLL developer specific, windows only sparse up to 10 layers stackable files commitable, rollbackable, growing vmware3 vmware3 disk support vmware version 3 compatibility vmware4 vmware4 disk support vmware version 4 (VMDK) compatibility undoable flat file with a commitable redolog commitable, rollbackable growing one growing file growing volatile flat file with a volatile redolog always rollbacked vpc VirtualPC disk support fixed / dynamic size supported vvfat local directory appears as VFAT disk (with volatile redolog) optional commit or rollback
flat
description In flat mode, all sectors of the harddisk are stored in one flat file, in lba order.
image creation Flat disk images can be created with the bximage utility (see for more information).
path The "path" option of the ataX-xxx directive in the configuration file must point to the flat image file.
external tools Flat images content can be accessed from the host by the following tools : mtools (see ) mount with a loopback (see ) Winimage / DiskExplorer (see ) Bochs Tools (see )
typical use Flat mode is Bochs default harddisk layout. This is also the layout of disk images provided on Bochs websites.
limitations On some host OSes, Bochs flat disk images are limited to 2GiB.
concat
description In concat mode, all sectors of the harddisk are stored in several flat files, in lba order.
image creation Disk images for the usage in 'concat' mode can be created with the bximage utility (see for more information).
path The "path" option of the ataX-xxx directive in the configuration file must point to the first file (e.g. win95-1). The lower layer files names are found by adding 1 to the last character (e.g. win95-2, win95-3, etc.).
external tools If every single file contains a complete partition, they can be accessed with same tools as the 'flat' mode images.
typical use If the partition sizes and file sizes are set up correctly, this allows you to store each partition in a separate file, which is very convenient if you want to operate on a single partition (e.g. mount with loopback, create file system, fsck, etc.).
limitations On some host OSes, there is a limit of 2GiB per file.
external/dll
description This mode is only useful for developers and needs an additional C++ class compiled in, or an additional DLL linked to Bochs.
sparse
description Sparse disk support has been added by JustinSB. Sparse disk features are: Large hard drive can be created, and only used space will be stored in the file. In practice, on Unix, this is not a large gain as it is done anyway. Multiple sparse drive images can be mounted on top of each other. Writes go to the top image. This allows several similar configurations to share a master "base" file, and also allows file system rollback or no-write options. Up to 10 disk images can be layered on top of each other.
image creation Sparse disk images must be created with the bximage utility (see for more information). Be sure to enter "sparse" when selecting the image type.
path The "path" option of the ataX-xxx directive in the configuration file must point to the top layered file. The lower layer files names are found by substracting 1 from the last character (must be a digit)
external tools No external tool support Sparse disk images yet.
typical use
Space Saving Create a sparse disk image using bximage. Set size to eg 10GB. Only allocated space will be stored, so your drive image should be only about as large as the files stored on it.
Disk Rollback Create a sparse disk image called "c.img.0". Point .bochsrc at "c.img.0". In bochs, install your favorite OS. Switch off bochs. Create a sparse disk image (of the same size) and name it "c.img.1". Point .bochsrc at "c.img.1" "c.img.0" is visible, but all writes go to "c.img.1". After using bochs, you can simply delete "c.img.1" to undo changes and go back to a clean OS install.
Disk Optional Commit Create a sparse disk image called "c.img.0". Point .bochsrc at "c.img.0". In bochs, install your favorite OS. Switch off bochs. Create a sparse disk image (of the same size) and name it "c.img.1". Point .bochsrc at "c.img.1" "c.img.0" is visible, but all writes go to "c.img.1". After using bochs, if you want to keep the changes, use the (currently non-existent) merge utility to make a single unified drive image. Alternatively simply create a new partition on top called "c.img.2".
Common Base Create a sparse disk image called "base.img". Point .bochsrc at "base.img". In bochs, install your favorite OS. Switch off bochs. Create a sparse disk image (of the same size) and name it "www.img.1". Make "wwww.img.0" a symlink to "base.img". Point .bochsrc at "www.img.1". Using bochs, install a webserver. Create a symlink to "base.img" called "db.img.0". Create a sparse disk image (of the same size) and name it "db.img.1". Point .bochsrc at "db.img.1". Using bochs, install a database server. Now both a database server and webserver can be run in separate virtual machines, but they share the common OS image, saving drive space.
limitations There is a need for supporting utilities (yet unwritten) : to merge two sparse disk images into a single image to defragment a sparse disk image and remove unused space
vmware3/vmware4
description Sharvil Nanavati has added vmware3/4 disk image support into Bochs for Net Integration Technologies, Inc. You should be able to use disk images created by vmware version 3 and 4.
image creation Create such disk image with vmware version 3 or 4.
path The "path" option of the ataX-xxx directive in the configuration file must point to the vmware3/4 disk image.
external tools &FIXME; give a look at vmware3/4 tools : disk image creation, etc.
typical use If you want to use an existing vmware3/4 disk image.
limitations Only vmware versions 3 and 4 disk image files are supported.
undoable
description Undoable disks are commitable/rollbackable disk images. An undoable disk is based on a read-only flat image (see ), associated with a growing redolog, that contains all changes (writes) made to the flat image content. This redolog is dynamically created at runtime, if it does not previously exists. All writes go to the redolog, reads are done from the redolog if previously written, or from the flat file otherwise. If unspecified with the "journal" option of the ataX-xxx directive, the redolog file name is created by adding a ".redolog" suffix to the flat image name. File size of the redolog can grow up to the total disk size plus a small overhead due to internal data management (about 3% for a 32MiB disk, less than 0.5% for a 2GiB disk). After a run, the redolog will still be present, so the changes are still visible the next time you run Bochs with this disk image. After a run, the redolog can be committed (merged) to the flat image with the bxcommit utility. After a run, the redolog can be rollbacked (discarded) by simply deleting the redolog file. In this mode, the flat file is always open in read-only mode, so it can safely be stored on a read-only medium (for example on a cdrom).
image creation The flat disk images must be created with the bximage utility (see for more information). The growing redolog is created automatically if needed.
path The "path" option of the ataX-xxx directive in the configuration file must be the flat image name. The redolog name can be set with the "journal" option of the same directive. If not set, the redolog name is created by adding the ".redolog" suffix to the flat image name.
external tools See for tools to access the flat disk image content. The up-to-date content can only be seen after you commit the redolog to the flat file with the bxcommit utility.
typical use &FIXME; to be completed
Commit &FIXME; to be completed
Rollback &FIXME; to be completed
Common Base &FIXME; to be completed
Harddisk Image on a Read-Only Medium &FIXME; to be completed
limitations &FIXME; to be completed
growing
description Growing disk images start as a small files, and grow whenever new data is written to them. Once a sector is written in the growing file, subsequent writes to the same sector will happen in place. File size of Growing disk images can go up to the total disk size plus a small overhead due to internal data management. (about 3% for a 32MiB disk, less than 0.5% for a 2GiB disk).
image creation Growing disk images must be created with the bximage utility (see for more information). Be sure to enter "growing" when selecting the image type.
path The "path" option of the ataX-xxx directive in the configuration file must be the growing image name.
external tools No external tool support Growing disk images yet.
typical use Growing disk images can be used whenever you want to maximize disk space. However, please note that Bochs will not check if enough disk space is available before writing new data. If no disk space is available, a panic will occur.
limitations &FIXME; to be completed
volatile
description Volatile disks are always-rollbacked disk images. An volatile disk is based on a read-only flat image (see ), associated with a growing temporary redolog, that contains all changes (writes) made to the flat image content. All data written to the disk image are lost at the end of the Bochs session. The redolog is dynamically created at runtime, when Bochs starts, and is deleted when Bochs closes (win32) or just after it has been created (Unix). All writes go to the redolog, reads are done from the redolog if previously written, or from the flat file otherwise. If unspecified with the "journal" option of the ataX-xxx directive, the redolog file name is created by adding a ".redolog" suffix to the flat image name. File size of the redolog can grow up to the total disk size plus a small overhead due to internal data management (about 3% for a 32MiB disk, less than 0.5% for a 2GiB disk). After a run, the redolog is not any more present, so the changes are discarded. In this mode, the flat file is always open in read-only mode, so it can safely be stored on a read-only medium (for example on a cdrom).
image creation The flat disk images must be created with the bximage utility (see for more information). The growing redolog is created automatically.
path The "path" option of the ataX-xxx directive in the configuration file must be the flat image name. The redolog name can be set with the "journal" option of the same directive. If not set, the redolog name is created by adding the ".redolog" suffix to the flat image name. A random suffix is also appended to the redolog name.
external tools See for tools to access the flat disk image content.
typical use &FIXME; can be completed
Repeatable simulations &FIXME; to be completed
Multiple Bochs instances &FIXME; to be completed
Harddisk Image on a Read-Only Medium &FIXME; to be completed
limitations &FIXME; to be completed
vpc
description The "vpc" disk image mode is mostly a port of Qemu's "vpc" block driver for VirtualPC disk images (written by Alex Beregszaszi and Kevin Wolf).
image creation Create such disk image with Microsoft VirtualPC (tm) or Qemu's disk image utility (qemu-img).
path The "path" option of the ataX-xxx directive in the configuration file must point to the VirtualPC disk image.
external tools Use Microsoft VirtualPC (tm) tools to manipulate these disk images.
typical use Share disk images with VirtualPC.
limitations The based on the Qemu code the disk size is limited to 127 GB.
vvfat
description The "vvfat" disk image mode is mostly a port of Qemu's "virtual VFAT" block driver (written by Johannes E. Schindelin). It supports the read-only part of this implementation plus some additions. The structures of the virtual disk are created from the contents of the specified local directory when Bochs is starting. All writes to this virtual disk go to a volatile redolog and when closing Bochs, the user can decide whether or not to commit the changes. If "No" is seclected, all changes will be lost when Bochs quits and the files of the local directory are not modified. Otherwise the changes of files and directories are committed. WARNING: Don't use important data without backup in the "vvfat" directory when using this "optional commit" feature. In addition to Qemu's "vvfat" implementation the Bochs one supports configurable disk geometry, FAT32 and reading MBR and/or boot sector from file. When using the autodetection feature, the CHS values 1024/16/63 (Qemu defaults) are used. To use an MBR image file from a real disk it must be named vvfat_mbr.bin and placed in the specified directory. Bochs uses the geometry and file system type from this file and doesn't show it on the virtual disk. The same applies to a boot sector image file, but it must be named vvfat_boot.bin. Using both image file is also possible if they match (grabbed from the same disk). FAT32 is enabled for disk with minimum 2 GB size, or if MBR / boot sector image enable this filesystem. When using "vvfat" for a floppy, FAT12 is used (1.44M media only). In all other cases FAT16 is used. Long filename support is always present. Special FAT file attributes are stored in a special file named vvfat_attr.cfg. When using the "optional commit" feature, modified attributes are saved to this file. The "optional commit" also supports setting the file modification date and time.
image creation Not necessary. The directory must exist before running Bochs.
path The "path" option of the ataX-xxx directive in the configuration file must point to an existing local directory. The redolog name can be set with the "journal" option of the same directive. If not set, the redolog name is created by adding the filename "vvfat.dir.redolog" to the path. A random suffix is also appended to the redolog name.
external tools You can use your favourite file manager to copy file to the directory you'd like to use. The directory should not be modified while Bochs is running.
typical use Accessing files of the host hard drive is only possible with vvfat.
limitations There is no runtime write support present yet. All changes are written to the volatile redolog and they can only be committed on Bochs exit. When using the MBR from image file only the first partition is used and it must be of type FAT16 or FAT32. FAT12 can be used for the floppy only. An extended partition or other file system types are not supported.
Using the bximage tool Bximage is an easy to use console based tool for creating disk images, particularly for use with Bochs. It is completely interactive if no command line arguments are used. It can be switched to a non-interactive mode if all required parameters are given in the command line. When you run bximage without one of the following options, it will appear in interactive mode and ask for all required parameters to create an image. bximage [options] [filename] Supported options: -fd Create a floppy image. -hd Create a hard disk image. -mode=... Image mode (for hard disks only - see the bochsrc sample for supported options). -size=... Image size in megabytes (e.g. 1.44 for floppy image, 10 for hard disk image). -q Quiet mode (don't prompt for user input). Without this option bximage uses the command line parameters as defaults for the interactive mode. If this option is given and one of the required parameters is missing, bximage will fall back to interactive mode. --help Print a summary of the command line options for bximage and exit. The filename parameter specifies the name of the image to be created. For an example of the usage, refer to .
Using the bxcommit tool This tool can commit redologs into flat images. For now, only "undoable" and "growing" redologs to flat image commits are supported. Sparse disk image commits may be added in the future. This tool is completely interactive if no command line arguments are used. Then bxcommit asks for the operation mode, the flat image name, the redolog name, and whether to remove to redolog file after the commit is done. It can be switched to a non-interactive mode if all required parameters are given in the command line. bxcommit [options] [flat filename] [redolog filename] Supported options: -mode=undoable commit undoable redolog to flat file -mode=growing create flat disk image from growing disk image -d delete redolog file after commit -q quiet mode (don't prompt for user input) --help display this help and exit The first filename parameter specifies the name of the flat image that will be created or modified. The second one specifies the name of the redolog. Session example : $ ./bxcommit ======================================================================== bxcommit Undoable Disk Image Commit Tool for Bochs ======================================================================== What is the flat image name? [c.img] myfile.img What is the redolog name? [myfile.img.redolog] toapply.redolog Shall I remove the redolog afterwards? [yes]
Guest operating systems In the past several tweaks were necessary to install a guest OS inside of Bochs. Nowadays it's almost the same as installing it on a real machine. There are only a few Bochs specific issues you should know about. Note that we cannot give you a full installation guide if you don't know how to install an OS in the real world. The following remarks apply to all guest OS installations. Some specific issues are reported in the next sections. First of all you need the installation media or image (floppy/CD/DVD). For platforms that don't support raw device access it might be necessary to create an image from the media. You must read the message regarding software licenses in before you install or use a commercial guest operating system in Bochs. Then you need to create a hard drive image with bximage. For the required size see the documentation of the OS you'd like to install. See how to create the image. Finally you have to create configuration for your guest OS. You can edit the sample configuration distributed with Bochs or use the configuration interface to adjust the settings. Check the documentation of your guest OS for the required memory size, cpu speed and supported hardware. Now you should be able to run Bochs and start the installation process. Depending on the host cpu speed and the size of the guest OS it can take a few minutes or even some hours. What disk images are available. What works Known problems
Knoppix Contributed by Alexander Schuch.
Getting Knoppix Knoppix is a live CD (700M) or live DVD (3.2G) based on Debian GNU/Linux, with lots of ready-to-run programs (web browser, office suite, a few games, and more), using KDE as desktop environment. It can be booted directly from CD, without any installation needed. You can download it from knoppix.org.
Preparing Bochs As Knoppix runs completely from CD/DVD, you don't need to setup a hard disk. You just need to set up the location of the downloaded ISO image in your bochsrc, and make Bochs boot from it. Because Knoppix contains a graphical user interface, and has no other storage space but the emulated RAM, it needs at least 128MB of it, see megs option. Furthermore, you need to enable VBE support in Bochs (see ).
Using Knoppix There is nothing more to do! Just start Bochs and wait for Knoppix to load... You are logged in as normal user, if you want to become super user, just su. There is no password needed (empty password).
FreeBSD 5.2.1 Contributed by Alexander Schuch. This section describes how to install FreeBSD 5.2.1 (miniinst) inside of Bochs, using an ISO image.
Getting FreeBSD As 5.2.1-RELEASE-i386-miniinst.iso (240M) is no longer available from the FreeBSD FTP server, you might want to ask a (file) search engine of your choice for a download location. Once you downloaded the file, you should check its integrity using the provided MD5 checksum from the FreeBSD 5.2.1 release announcement.
Preparing Bochs Create a new hard disk image using bximage (see ) with a size of at least 350M, as the standard installation uses 280M on its own. Next, you need to setup your bochsrc so that Bochs knows about your (still empty) hard disk, as well as about your ISO image. Make Bochs boot from CD-ROM and start the emulation.
Installing FreeBSD This is just a very short step-by-step installation guide for FreeBSD in Bochs. It doesn't explain what you do nor why you do it, it just tells you how to do it. For in-deepth information refer to the FreeBSD handbook: Installing FreeBSD. FreeBSD boots up and shows a nice (text-mode) boot option screen. Just press return there, that is, use the default option. After loading the kernel and needed device drivers, select 'Standard' in the installation menu. A fdisk like partition program is loaded next, where you just press A to use the entire disk, followed by Q to finish the selection. The next dialog asks for the boot manager you want to use. Select 'Standard' and continue. In the Disklabel Editor, you have to setup the layout of your partition. If your (virtual) hard disk is large enough, you can press A for auto-layout. However, you need to make sure that the /usr partition is at least 250M large, or you will end up with a 'disk full' error message during installation. If this is not the case, select one partition after another and press D to delete it again. After you deleted all partitions, create two new ones. The first one will be a swap partition; press C, enter '32M' as size and select 'Swap' from the dialog. Press C again, and accept the remaining capacity for your filesystem partition. Choose 'FS' as partition type and enter '/' (slash) as mount point. Your partition layout is complete now; press Q to leave the editor. This 'all-in-one' partition layout is not recommended for a FreeBSD installation on a real box; use 'auto-layout' or something comparable to that there. You now can choose what set of programs/files (distribution) you want to install. Take 'User' (option 8), and select 'No' when asked to install the ports collection. You are back in the distribution selection, where you select the first item, called 'Exit'. Choose to install from 'CD/DVD' and answer the 'Are you sure?' dialog with 'yes'. Now, while FreeBSD installs, it is a very good time to take a look at the FreeBSD documentation, especially the FreeBSD handbook and the FreeBSD FAQ.
Post-installation configuration All files are installed on your (virtual) hard disk now, and FreeBSD is ready for getting set up. As this is a very basic FreeBSD installation, you just answer 'no' to nearly all questions, but the one about your mouse: Answer 'yes' for PS/2 mouse, and choose 'Exit' at mouse configuration. The miniinst FreeBSD ISO image contains nearly no binary packages, so don't browse the package collection. Then, when asked to create a new user account, answer 'yes' and create a new user called 'bochs' (or whatever you like). You might want to use /bin/csh or /bin/tcsh as shell rather than /bin/sh. Next, you are asked for the super user (root) password. The installation is finished now, there is no need to visit the general configuration menu again - answer 'no' to that question. FreeBSD will then reboot. Shutdown Bochs, as soon as the (virtual) computer boots.
Using FreeBSD Open your bochsrc and change the boot sequence, so that Bochs will boot from hard disk, rather than from CD-ROM from now on. Start Bochs again and watch the FreeBSD boot process. Your keyboard might use the wrong keymap, so login (into FreeBSD) as super user and use /stand/sysinstall to start the FreeBSD configuration program. Choose 'keymap' and select the keymap you want to use. You have successfully installed FreeBSD now. You might want to shutdown FreeBSD using shutdown -h now, quit Bochs, and create a backup of your hard disk image, before you start playing around.
DOS You must read the message regarding software licenses in before you install or use MS-DOS, OS/2, DR-DOS, or any other DOS as a guest operating system in Bochs.
Accessing your CDROM To access your CDROM in DOS, you must download an IDE CDROM driver. Bochs emulates a very generic CDROM drive, and several drivers are known to work. Others don't. This section describes how to set up your config.sys and autoexec.bat to enable the CDROM. The drivers that have been reported to work are OAKCDROM.SYS that comes with several versions of Windows and SBIDE.SYS version 1.21 from Creative Labs To get it, go to Creative Labs web site, click on Support, then click Download Files. You get to a screen where you must select the operating system and the product for which you want the driver. Choose DOS as the operating system, and "CD-ROM: 4x and above" as the product. There are several choices, but you want sbide121.exe from April 15, 1997. Version 2.0 does not work. The download file is a self-extracting ZIP file, so on DOS or Windows you just run it; on other platforms you can try using the unzip command. The driver is called SBIDE.SYS. and OAKCDROM.SYS that comes with several versions of Windows. Copy the driver to your boot disk, and then set up the startup files as follows. config.sys: device=himem.sys device=oakcdrom.sys /D:CD001 -or- device=sbide.sys /D:CD001 /P:1f0,14,3f6 autoexec.bat: mscdex.exe /M:10 /D:CD001 If the files mentioned in config.sys and autoexec.bat are not in the root directory, give the full pathname, like c:\windows\himem.sys.
SB16 driver for DOS To use the SB16 device in DOS you need to load a driver for it. The file SBBASIC.EXE contains a self-extracting archive with all required file. After unpacking it to C:\SB16 you can execute INSTALL.EXE to install the driver. The file DISK.ID should contain the version string SDR-31STD-1-US (Revision 1).
Bootdisks of early DOS versions On the Web there are bootdisks available for most of the DOS versions ever released, but some of them have been reported to fail in Bochs. The bootdisk for MS-DOS 1.25 contains a boot sector of a newer DOS version, so it would fail on real hardware, too. The floppy image for MS-DOS 2.11 has a boot sector that tries to boot from hard disk instead of the floppy.
Windows NT 4.0 You must read the message regarding software licenses in before you install Windows NT 4.0 as a guest operating system in Bochs. Here are the known issues about installing and running Windows NT4.0 : If you want to use the LGPL'd VGABIOS to install Windows NT 4.0 you'll need version 0.4c or higher. With older versions you'll get a black screen after first reboot. to log in you must press ctrl-alt-del, and it is likely that the window manager will trap this key combination. You can either use the trick described in or define a user short-cut (callable through the user short-cut gui button) in you configuration file, for example: user_shortcut: keys=ctrl-alt-del For installing and using Windows NT it is necessary to limit the maximum CPUID to 3. In the configuration file you need to add a line like this: cpuid: cpuid_limit_winnt=1
Windows 2000 / Windows 2000 Server You must read the message regarding software licenses in before you install Windows 2000 / Windows 2000 Server as a guest operating system in Bochs.
Windows XP You must read the message regarding software licenses in before you install Windows XP as a guest operating system in Bochs. Windows XP has been reported to install from the CDROM, and run inside Bochs. The only known issue is to set the IPS to, at least, a value of 10000000.
Windows 7 You must read the message regarding software licenses in before you install Windows 7 as a guest operating system in Bochs.
SCO OpenServer 5.0.5 Contributed by Carl Sopchak You must read the message regarding software licenses in before you install SCO OpenServer 5.0.5 as a guest operating system in Bochs. Back in April and May of 2002, I did some work on Bochs in order to get it to install and boot SCO's OpenServer 5.0.5 (OSR5). Since that time, I have had several e-mails asking about this error message or that. The newsgroup posts done at the time had all of the information that I knew, so I pointed people there. (I had not used Bochs since...) In February of 2003, I got another such e-mail. Since the sender indicated they were willing to pay me to get this going for them, I agreed to spend a few hours on it (for free, which is not common :-}). Subsequently, I decided to document this once and for all. (I did not charge anyone anything, this time...) Note: These steps were originally used with Bochs 1.4.1 (or thereabouts, since I was using CVS heavily at the time). It is possible (likely) that later versions of Bochs are more tolerant/bug free, and this install may be abbreviated. However, I have not tried to streamline it at all. These steps were performed and confirmed using Bochs version 2.0.2, and SCO OpenServer version 5.0.5. The host OS was Red Hat Linux 8.0. First, I downloaded the tarball, and extracted the source tree. I decided to use the tarball instead of the RPM so that I knew what options were compiled in, etc. linux-$ tar -xzvf bochs-2.0.2.tar.gz Next, I configured and compiled Bochs... linux-$ cd bochs-2.0.2 linux-$ ./configure --enable-cdrom --enable-ne2000 linux-$ make I then created my disk image: linux-$ ./bximage ======================================================================== bximage Disk Image Creation Tool for Bochs ======================================================================== Do you want to create a floppy disk image or a hard disk image? Please type hd or fd. [hd] hd What kind of image should I create? Please type flat, sparse or growing. [flat] Enter the hard disk size in megabytes, between 1 and 8257535 [10] 2048 I will create a hard disk image with cyl=4161 heads=16 sectors per track=63 total sectors=4194288 total size=2047.99 megabytes What should I name the image? [c.img] hd0.img Writing: [] Done. I wrote 2147475456 bytes to hd0.img. The following line should appear in your .bochsrc: ata0-master: type=disk, path="hd0.img", cylinders=4161, heads=16, spt=63 I then created my .bochsrc file. I did this via the interactive portion of Bochs, with the end result as follows: floppya: 1_44="/dev/fd0", status=inserted floppyb: 1_44="b.img", status=inserted ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, path="hd0.img", cylinders=4161, heads=16, spt=63, translation=auto, biosdetect=auto, model="Generic 1234" ata0-slave: type=cdrom, path="/dev/cdrom", status=inserted, biosdetect=auto, model="Generic 1234" ata1: enabled=0 ata2: enabled=0 ata3: enabled=0 romimage: file=bios/BIOS-bochs-latest vgaromimage: file=bios/VGABIOS-lgpl-latest megs: 64 parport1: enabled=1, file="lp.pipe" com1: enabled=0 # no sb16 boot: cdrom floppy_bootsig_check: disabled=0 vga: update_freq=5 keyboard_serial_delay: 250 keyboard_paste_delay: 100000 cpu: ips=3000000 clock: sync=realtime, time0=0 mouse: enabled=0 private_colormap: enabled=0 pci: enabled=0 # no ne2k # no loader log: osr5.log logprefix: %t-%e-%i%d debugger_log: - panic: action=ask error: action=report info: action=report debug: action=ignore keyboard: type=mf, keymap= user_shortcut: keys=none config_interface: textconfig display_library: x Some important things to note are that you want to boot from the cdrom, and you do NOT want the ne2000 card configured initially. (We'll add that later...) At this point, Bochs is ready to roll! Insert the OSR5 install CD into the drive, and start Bochs. You should soon see the SCO "boot:" prompt: SCO OpenServer(TM) Release 5 boot : defbootstr disable=fdi,dptr Note the disable= parameter that you need. These two SCO drivers cause the install to fail, so they need to be disabled for the install boot. You will not need this once OSR5 is installed. During the install of OSR5, there are two default configuration answers that need to be changed. For the hard disk setup, you should turn bad tracking off, since it's unnecessary on an emulated disk. (It won't hurt to do it, it will just take a VERY long time!) For the network setup, change the network card to Deferred. You can change other settings, if you so desire. However, I would do the initial install with as little configured as you can get away with, then add whatever else is needed (one step at a time) after the initial install completes. Let the install copy the files. Go get lunch. Take a nap. Go have dinner... This can take a LONG time. On my Pentium 4 1.7GHz system, this step took just over eight hours! (BTW, it was MUCH longer in version 1.4.1. Great job, guys!) After the install finishes, you will need to change the following lines in .bochsrc file: ne2k: ioaddr=0x300, irq=10, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 boot: disk Obviously, if you're not using Linux, the ethmode and ethdev values on the ne2k line will be different. Also, since Bochs uses "raw" network card access, you'll have to "setuid root" on the Bochs executable: linux-$ chown root bochs linux-$ chmod u+s bochs (If there is a way to give a "normal user" CAP_NET_RAW capability, that would be an alternative. I don't know how to do that...) Restart Bochs. Now, you can just press Enter at the OSR5 boot: prompt, because the offending drivers have been linked out of the kernel. Before you configure the network card, I'd strongly suggest getting the latest "nat" driver from SCO. Version 5.0.5b of this driver, according to the SCO web site, "correct[s] possible system lockup under high load due to internal buffer overflow." The driver can be found here. To get the Disk Image file into SCO, I downloaded the VOL.000.000 file to my linux box, and used tar to get it on to a floppy: linux-$ tar -cvf /dev/fd0 VOL.000.000 I then used tar within OSR5 to move it from the floppy to the /tmp directory: osr5-# cd /tmp osr5-# tar -xvf /dev/fd0135ds18 You can then use 'custom' to install the driver from the image file. You will then want to use 'scoadmin network' to configure the network card. Choose the Novell NE2000 card, and set the parameters to match the ne2k: line in the .bochsrc file. DO NOT have OSR5 look for the card, as Bochs may likely crash. (It did in version 1.4.1.) You can also configure a printer, if you want. Using the spoolpipe utility that I wrote (which can be found in Bochs' misc directory), you can print from OSR5 through the parallel port, and you'll hardly notice that the printing is going through an extra layer of operating system! (You could also set up a printer using network printing, if the printer is not on the host machine...) Obviously, dont forget to apply the release supplements and other patches that are considered "must haves" for OSR5: rs505a, oss600a, oss497b (others?). That's about as far as I have got. I played around with OSR5 within Bochs a bit, but I can by no means say that I did any kind of real testing, let alone exhaustive testing. And of course, YMMV! :-)
bochs-2.6/doc/docbook/include/0000755000175000017500000000000012020641455016144 5ustar guillemguillembochs-2.6/doc/docbook/include/defs.sgm0000644000175000017500000000274612020641455017606 0ustar guillemguillem '> '> Bochs web site'> bochs.sourceforge.net'> bochs-developers mailing list'> $BOCHS'> Makefile'> DocBook: The Definitive Guide'> OASIS'> bochs-2.6/doc/docbook/images/0000755000175000017500000000000012020641456015767 5ustar guillemguillembochs-2.6/doc/docbook/images/headerbar.png0000644000175000017500000000426612020641456020422 0ustar guillemguillem‰PNG  IHDR‚"ü­HàPLTEüþüvH‚ ȸ’“v;|86ïi÷o¿”ä—´8‚iâS÷ˆ¿ÏgÈÂvÈ\íþA ÷÷”¿¿¤à·j vX·ï o¤4Xj©8øg&æS“÷ˆ­¿Ï9àgÂv8i(þ’ ÷È¿\ìB³ù÷o¿¿¸ @÷ø¿’0÷î÷<v8÷“¿mog÷¿÷Ô<@¢æ÷÷‘¿4e©øæ ‘ÃÄWvv; „F¶÷ ¿@@Fø@IDV’8‘©£ªø÷<¿:×vT÷€Ã·vTˆ@?IùV¿@@ø÷”@$’ß@Gâ¸e0÷¿/ZH“Ä_v^0A’÷¥vv÷L¿Gmd÷T¿_÷X<¥8÷“¿øT8C“^W’;CN’vFÀH(U/8¤ij—lÄ0v€W°´vG÷¿|ïo”T$Æ·´÷‚°¿GhSˆ”sÏ“€c\Â#vOø¿þ  ÷”ø¿¿˜hÂvs@|÷ÂïHo8Uiµn÷‚¿Sˆ”ϘÂëvAþú H÷U¿0A³³n÷ ÷¿¿È@nÁ÷‚¿ RÈõ\¿÷#<ðÈ’\o?˜Üx pHYsÄÄ•+\IDATxœíY‹’Ü( ÿÿÓ©;#Ô­ÆãI6UQoÕ#Þ4-ái4~Ã!d°õi…+<ªÞøóø‚Ⱦ_IÆ…ÿµGŠ·;Ú7o ús-þb©D*£Û1[´͸žy‹ÇC¿-TP°¬|UpfáŽ[ȵ·x·¤²~ÏòUz©ª„Xã2ÿ4¥/‰Ë¤,É/{³Õ¿ÍñÍ&öÀ8aƒ>`Ü®b£Â ÉœU•n‘ÂöDY9‰' Šv,ë`IÔj#8(í,*TG;OËfAv¾8]¯•þ™å±Qñ¨±­»ý€U”h“ ¤hZ…5ð)‘KVqTæ_ÍlÓ¢Ñîý|%’&ÑNåÁ’fàð¬Ú&ûm[Ö”‚XW™6M׆[ ( †¦f;GÌšgiAóêXØ\3ê9’vh¢~rsïiLäô$ó/á¸Ouñ±`ì*ïß5ÈѼ“?) ÂfmËàNwvªÔ%÷ܸÁÒtÄ£ò!âž¾­›Žü®ò’W¢¾î¼>l›5ü[fd^ÚGȹ³>™¬që l\IãS°$l)¸u=ÜGýú FÁ¡^ZgÃñÄ]‡–â2EWÏߚÿ‰©Œ!s×¢÷ZùØLâGùz8Î\c™‚lŠÜ؇m5+ÞB¼¹õ4N`q¡è%¢(Hþiâ×õ$6¾•´š Ð(«\<;ðŒÕΛìjÞ|TáS®¨·AÆGA{ÌÎÞQA¼HUn•8ÒꊘAÙ ºëJã9’¾£`åÂôšàó|À¥ã±|  Ñ*(‹„W>ÅŠÉW'›gãH–üˆ‚è·bRËR°A>n«jô™ âuøÞ¾ŒHA›W>àÆ-ÂeOò;–`Ø;}‚Í»;¥`EL§ªžYÐèç*hœ3¤™hôA×æà§˜ŽR—–v™¬WøùLƒC¾µL.ó• âÿA“óî¢~¡ü_bx>…6êLREÓ@îႾäW‰á)øF…hè(H3oÚ=Án±–V-yzR9¶ùXpÅéÔ¶pBÁŠƒØŠÏú¾ ÎÙy RÁÍ÷«F€¤kó.Xz¸´³E„M|¬‚WÆüyAÁo¨`þŠ“ß-€ÄMƧPŽm‚Fì; &RÒú³*ÈmTA;)£q†{ æ9UP“ç Ö&Mà ¼¾¡`u±³C8F¼ŽÄ¥h"wÄ´¼Ã®$3¢sÁ¨ ÙB,HáÔ Ñþ .ŠÀ u(ñ¥qñ,\\Ëtí• RO[ Ú¯åí((UÂe¾¡ za“=<‰¼!@llp¦‚žiˆÎ4ÀXÂ6RÁô>ÍC_ö ý'Iª@lKj~ƒ‚*‚S‚þ‰£bc‹D¯l +ÈÀ†lY,x¦‚XX$érü“_ÂaÈ)XÚÕ ké‡4¬®Lc‹\ù‚ ŒǨ(6¿ñ´¹+ûx˜…4©µ~u„k{JÁý¹© ÑŽ˜Ç+g± •6­ 6¢Í󗈦å½E[ÁדYdÁŸ{ ‡¡RÁÜ>W†U´¿Š`â` ò‹õJ®Ò1u1§ lmØ#%Ÿz±¤ïÁ“‡_RAPzÍÇióÚÅÅiÔØ­PBÁ”’ÙB æPYigÁ9›GEQ˸QÁ­®O‰ë>œ³ø'!;œ¶q’‰QT(g¾UðÙæcF%'V®xmþšu|;ÒæàÀ}³/&³2Ç‚Cùú­±Ñ8™aÁi§ö›‘Ü´9ø×à‘´~·ÓFãçð uÞCgø`°[IEND®B`‚bochs-2.6/doc/docbook/images/undercon.png0000644000175000017500000000057712020641456020323 0ustar guillemguillem‰PNG  IHDR(&DÚÄ.0PLTE€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ{±Ä tRNSÿÿÿÿÿÿÿÿSOxbKGDºÙ pHYsHHFÉk>ÓIDATxÚm’1Ä ·ã$˜2ežãÞŸ;–µAI B£/Ƹs]øÕöÆÚxYøï xÁ!ÆV±Å­b‹[E‰[*J‘–ŠU;êFA©¨Ò‚RAqÌB©‚¢E¢TÁ­§ ÞÈó[Khžù©¢2N˜ æ²á'Ó¥d.¨¯DlJS$¯÷¢+¼#mŠzfÂñ^£¨†ò £¨Öfó(f“i2‚Äü/8Åýqê[{~±böÃ0´ÓØôÀµÓ(öÃЖøïþ–xÿ†Ù`… ¥g€IEND®B`‚bochs-2.6/doc/docbook/images/dlxlinux-in-linux.png0000644000175000017500000002042012020641456022103 0ustar guillemguillem‰PNG  IHDRˆÊ¥Zåœ pHYsHHFÉk> ÂIDATxÚí ¶ª8E3S§—QÜ©ÙýTH}N%Q =»W?¯!$¶!?±\—+!/âC Œz¹ò°\—òo‹rWˆHÈYjD_Q~ºþ&çä²7‹È6"ÙÅŒJ8dñOáC™`F%’OÄrÇnˆ"3íå¤Âo¯.Ò=[¸ïöÒ¨cÜqÏäøß%â_p¡÷FœÍ´ŸÀ'DܼëyDl÷åô">®ëýåÿÿÅ;QE¸½Yÿþ»mý“ûÜ6´P»«ùW\SAËåñÏß=YUÊNÑõö¿59³Å–EU”JEýû˜‡[D\ßfQ)ò§ý’u·›ºYûPuíÿêÞ/3Xl;Ì–±,MNYÌq¶R©ãü\…x„ˆ²“¢¨«$qQMD|í¶‹(¶£Üüµ¶  VPôÒî Ú× jsÏéÌ"ÞïÂcžÙjÄ?u–Õ­Ùú8±ôjÎQåŠE¼ÿßµÛ©bërº²¨ÚQ&.wøàYˆó°NˆxsîïkDl—Slùû›ÑÆÜšM¹žñß衈¨  \&äD.ÙDôb­ñí¶ˆ—á­Ù7³tOØ»TB>Á2,:Ú°$´3¤ˆÃ¶ðÖŸCéÝšÿ‰ÕBÎÐYQ=Ç?{“²·f!®æþ@b:^1Ù@e.&C]ýiÓò[\YtRö¼ØzüÍ|S¯9Á…ýÐÿ¤gC(â ‰.üŒ•{J6ˆØ‚ñ9>aDùh pÌ7Mñ‘󔈴dÖ‡2ÁuoHùtÉ ùÇ¿/O]Ì7¨ìªJÑïúÛ=ƒÍä”÷Çn.÷Tþ¯µi&é¢ó*×Áö¨Ää¤ü»ž·kzÿ¿¨€2¨‡&.ÿ¥uV´8åj…Ûï—+Þ^V6„äæqÁï/e¤ÜooBïzôm½ˆï¬8ÓTBF¼x»ðÏíHNKy8wÿ£½®"®ž.Þ]×ê³4E­úˆZn/ùå)iP)^@ù‡pÑTœÊgµœ™Õ9]Z¥kº¾Yö“ñn/õ-¾U­r…÷Õ¶^åB|ú ’¸7 ¯Eµ—šñQm©ú¯ý½xXVñÿÉÍýuR M ߨ "Y‚èáR‚@S–pCÑ›¯VÄyõ¶«Ì#tÔ"gÄ‹q]«Ì¥(ŠW²6 ×Í '¢Ï3zgBVÙå€~/ ¹Ø6¢¯ît0Þn›·0Šø5Ü/·•óUã\Bv§‹Q‹çE · Mü ¸#¯—-é 6¼5«úÜš£í«„e)[a•ø=¬5‹­ˆü<\7™ÖXTn\PQtg`ow5"¿ˆu칸Ð-}RSíuyA؆˜®¬¿yůàO=J%z{Á½fÑí…½f´ÝˆXpÞäœÈ±ßSuâ‹^L *äºY#®)ª“B¿]ÝÜÿlƒ#v1ê_Åâ1áñàŒ#Š]à8"Ø®çöÂ䔈ºgy#{ÒÇuiD\#¶ˆ¬¿ ááÒXÞxçEåj¯ ¬Å?°F„Ûåݘ“Ì߆¬Ûª¯\Y—<\ŸñùQÍò‘¯@^ò«YAãE¼!¢^vjÄ`»2Ò,á&gGzˆLñÀŸK€ÛÒÑãK·ëWŽf²¯‚îÍ"øs p[^"¢0P¿!ç'¸3oqK¯ùÉÑÔ4ñK@}•­5â¶qÄçjDØ`$çG·÷ÕˆÛfV”õXD¼½Í/«¡všø4Qh£¹:lÙ½½¯Â6$b°½(õ`ùìÙGèx8»ú¦8ë]µÛÙnªlYvò5<†Ž;Kb{έG,QWdÂívÐ]ž| rFcÏ• *Ì‹~ä¬ñÄ `w{Ü: ‰_„Zô°+T_^VE…iz#W»þ°³=.<ùüØË\Å 7ê—ÙíQá?}öÈÄMÀÝ\V ù ‘¤`±Þø?dy]°ïcÑÖè“»Eé´÷A¸ß¯N¥7Ú/Š^ûM§?y^¢xöôØó¾µ|)h5â¿RÿÿÿCF}6æŽÈ xˆuVIJSD!¼þu²í€:œð|‘ˆ»”:øøç“;Æü—‹xôùøNUé×J_Ýêê}¹§›½ªŽ_uü5²iØø8üö/.˜. ,jz˜ý\% /³M–eÿ¢ŽCœ@³]ìÎ*‡:ßEçtùr EÔ'ª`õ9\Î8!öžúÇÝê}M¬/”½5‹øÆC½K‹ ?+0û*0¾IÌ~"ZŸHÏ&ˆã‰Hè¼o._tеpª½Î€¶& E8BDUÁD"±=ÚO[]L®ó_Âqú¶<í8\ym†f[»á`qù²ET—´´·ˆh}z½ˆ&À‰¨O€w@¢>s¡AsÄ×t¨`àü)K»#‰yaM9BñöÔ¨íõüü;ˆõl˜nfk€T{‚ÖR¾®ñdú¶q%^Û~¦ÊuÝu7ðnÂÕ÷ùtöÃñ]ø¤‰úøÍd=ßh<¯ÉߟoS¾s‰øÖ\mUv@2äÜ|DDS#íNƒ"~oMeïNè]…&/‡«oH ("IE$)"ÖærãÃøµû>J7Los uæl}~Y#¾HÄq²h¶c"ÚdjÛ¢¸wò¶ˆøÄ@˶Ïyp€EñíxÝ:¼¢gT³NNô—¢f `záº97CPPºÑ8P4$³iSǧ޼'¢›cFŽÍŸÛ4ÿÈôªMß^PþÝ9ã¢s’Åtë¥Lþ§CÞÉ3".Õ‰]ÿf|™H/^×'¦V#‹¬¨Œ—ôì\òèøèáxNÄ"ŰAµç%ÚO½Wñ¡ˆ¾8=mšfa…?0òV¶ˆëXD½E$=ŽqÔFì·†«6bÑM¼¨¨Š©Ã)â ÐÚ¦ {§ìúE× Öñ¡ýŒ‰Ï­+4â°S¢zͨn%ïf<ŷẜâFm^òQñ4×÷4ý-†"NO¼žf†ö4ý)¸ú†¤€"’PD’ùuÒ%lІÚÐjì…ƒa˜`3 TÄá ˜rª°È Ø?¦¦™÷‹1Ô¨ÒpE;-?Ô˜í=û3ßë ½ ¦ƒóÞ¦Ûp`–C¥/K3šÒ™< »_o ÝÆÁˆÏϯ0#¢ù€ßþÝŸcUu¯x *€Šj‘ˆ-]WÛ"†Ç5aÙ/Q•£Ú…>ö¸+>??€ÑÍŒ€Ó!.(\_¸¾/‘Øv>¹wk‰ˆ&¢e7w EÇ-ÖCög˜Lþ-@A(¢=n;•ú£"V{b¦O|…ëû¢[ŒÓePÁ­×ð‘_Öeò‘/ÍÛ¾Xð.-Ž'ºUjïd+´ÅXN‘mÛÚãÖÅÿ)ñ£‹5Àc!^_(ÎìàÚéê¨Ó8·"F5šyÖ‹MݯŊjÄjlè”Ï}0Ñ1‹j)0lÅþ ¡ˆÝ¶»½ NÁHDPÍÝšË@DØ]Òýf±ÕØÁ­ÙœsBúgãK™Ñ·5<ƒ+°MÄ Ðr?מ[ã×AÑ7vVPÞ®eH»"‹‰Op·ˆ.\ODÓl³V»Ò+Uùàøáñ ·=^ûp䂽üYEûN=ÿÐsÛÐÚb?yç[ÿ‚¼ªM)ǘKñÚ HÑfSñîÅP»©r.oñþ¢¼æxÔñ¹ò•ÚKº&ªâ÷’/&á_ö ½|ç$¡ˆä¡ˆ$‘¤€"’PD’ô40¸, à†ûàø_©æu.~ã3~X§—~È(›'¯>–ÎJ8œW l{'㻡40 ›gĬÁ’¼xk†ÜM—¬mxˆ5Šo³ˆ¦ÎTúGàÆ×É;.¶3 cïœ`ŠKÍ“D"FñKÆïÌCªòG+ õLŠÍµÖãä&CЃ:íœhðü@wõìzÆUXµ}2¾ÍÁÇ×SŠÑÃÍ)·âûgâ€]É{€aZ§L‘ˆnùÜÜ– ÈuÂ2±0´ãÛ @|_#‹ ¢¯/bå½ùtD¼G@8± D Ú|‘ˆÃôŸ±”PD_òJÎ ¢ŒZ(âwÒQ·án(ÑðŠióI£Ý½¶ßþaâÛ†E<7ðùˆ­‘XŠN“_ŽÂ½QÙÈ< Ý‹_Ô(¾mÑ¢W+kÛ0ÚOô†È[8Áßëm oŸç"¾Šøy("oÁ) ˆ$‘¤€"’ȯ“ª¯mn Fãp>âL4;Þ­[$/Ô¸ã0¿òâüÂ}Á¾ì8}“"Î]`1ðm¼éaÅäcŒrœß´ø;ó#ó|ÄCDœŽk ÛUÎÖ, ˜›U:‘ˆE‹?{8ûò#ý|Ä{X;ŸË Ÿ~ f*Ì­´M¯éÕ:âú„"êt}~&»çòNO vDù¹tŽÎ@ÔóÝ:9W+çñ³~,œ‹/6±{XÛ¸$T5¥ÊvEGÚü@±Í`ÂqVD°Áˆhžåb&XÌb„HÄøN¿¼is×”;ʯ"– ghïQì¯â‹`ÙÈŸ1¨‰ÆŠ©^쬈GåG Q_°j6qÜ[ÄèæWBwçG&xˆ¾³›‹e$FÅÃ7A8GˆøD~d5 }Òßâ荒²~Eíozßk@ð‘\•éú[¢) ¶‚·„"ºü*Jø©üÈó?“«åût¹ŸàÔ…ÿZv‰ÈKIŽfú÷šå+=$GÃÕ7$‘¤€"’è¹æÇ@F×ßÖàMŸQÔp xÙ»ûžœ1ŽX£°ÃÉÖéLûQÃu~m_Ûƒ§‰§'Ÿˆá:¿Nñô¸)>ùu†­šp5 ó Mê©=“N¸ŸQïFÞÑÃóÔ¹l\gØÐ„qÅϲQóÃ2E;_-3éˆè7ÓÃoDõšÕÔ©{vŒЖÒ-¸…Øæ¾…„ÛD¬  -÷äŒèáSóé&£_2¯h"šÛôf]=üJÂÎÊí¶—ˆH¿,¢èF ï %z&ú‰ˆºÉúÕ55ms•6ž8 -;)B·.Qçé^³Ò¶k·ì­ó[7Ã÷äļo⑤àm"òþIzpõ IE$) ˆ$îùˆjÇŽ«è}ç}f±Ä:Ü2^ÿH~ÿ|D¹`ÁLi @ì"¿(‚½‚ž¨VÈ<¿Uí‡^Á2/ò{ø§rxƒï—¢µ2v™xÏ):òÿ|ÄXÄÙç‚u\:8˜;&?Ì–qî9…îÑ8ÅÚ¦¼ä\1ù‡Øô­Y¬ 5PDì!kDrc b·³bÕ’»»ýZ˜_×H qËð©+"XLHÉ?Üóç´ãçõ@¶iRDòNñ‘PD’ŠHR@I ("IE$)0ëa;nƱCÂD9dCè÷š ÁÜÜüÂØmáä'Ù"bð~ÀXD*Ià mñÔýà…öd…ö¾Íœ¸Õî‰æ5Z¿C~ôÈý¨Á­YIe朱áW¸2›Тø\IJGÄR„tbnyÉçÓGOÒ]ø÷´ˆ.œ"’•OŠè$¿ËœˆªS¡ßO´ñ×HÙY!ÿ{ÍÑs‹ŠÑÞû^ðº×ÒWY{ã„R8ÅG’@I ("IE$) ˆ$‘¤À‰(æ;ºSx”!›ñ5"šA„ñ8uG¶³EÄà#àé_Ÿ>*r: ˆnædÝ"˜GÈHĪæ‡K¸p;ŠGÉf𭹪s¬ˆQ<ŠH63±ûU"’ÍlÑwV("9ŠHR€´Å—žŠú¢I#ŒÇgb“pФ€"’PD’ŠHR@I ("Iø:iQ‰¦öôwž!Õí27šãbûµ_ßÀËÏô·^wäÛÍE¬‚ ĉh¿o©î±_>Æ8dj¿ÈCóíþlÔgý¯[7LF¤ˆÀ"%¢[nø븦2"šºíY§M¢ˆÏE4úaÛsÅ¿ÄÄŠ|Ž¢­¸ô"ÌsM¶"ŸÖt€k%”!.Ÿõ8ayåDÒ°ÜkUújÒDS†,b·U?—+ŸecjS}ë´3„Ñóƒѧ#ŒÓÉÚp•tôjó‘5~¯ÜŤm›6…"n"® >è‚bÛó]͵IDQ©R™ø¾o•]‘¡ åÊ‹SÖª»èŽ@Ÿ h#>€•2)b‹n¡›jÄÇûêðé'¢Þ_þSA>]ÁqQÄcп`n;]"ºk;ÑQ¥D?‹ЮêŠ<%"Ú®DÔL_HÙF¬[¦ÿšo#êðŠŽ;jn‘:v3+k[©,tÚˆE6Ýì½Èuûº¿I_ö *ÌK÷vñì0’ìKWy$½VŸ¯ËÇzè˽œs>DÁE~±ËoNñ½[ *8ä'E¤‡ùø9ßýE~qbŽŸ‘ä„"’PD’ø[|fR¬·92l†gZ°>)0Y1Øö”á»_ýÝÀy0å÷œJŸ@ü_ˆ¨SÁnÆ¢”ö†—`¨Îfè÷PÙ¿BD<„8³÷³ÅúmæE´ËžÖàb…Ss6|î¢ÉgfâÁUí3e¦Ïþ:iõ ±å › DDÓÏñE­-);Aã“•øzUÜú×ôäúÈþqº2B/Ãõ”æ8ªM€ Ü\3˜3]Ð3X-0zÔl;ª ˆ®…¶·æÁ=PÎK‹)8øè§IN°žV·1u>y‚P½f5‡ŠhçxÛjTÝÁ[>Œ´ˆhÁ <Žˆèç˜][¤VŠx0zøFÞE:5º5ã ŸÑÇvý$$"HU‘ñXÀ×I[ö‹èƒ@'Æ%´_DØFD…uŸ "’†"¾,â í5æÑ…ŽÚf ¦ŒEDº"³œË×ÌcÍgZD¹E܄Тã^FŠ®£ôË.Z£ ƒ*€ÇÔ¢WŠO§]7ô¶àqØôE£ûÓ—9?ñÏÞaðTŽ¡ˆ/†·æ9ByC9žÈ)¸ú†¤€"’PD’1ŽxgCÁºÁÝmž£ÚJ݉•q!êløQǽíøí⌙r>W®ÙSõÒÆ®^}DtÏu÷b’ƒŽ£>%b¸×ÄÔÞ“0µ»ƒ §0w¤{Dß'b‘2Þþò%¸¤—ï±ÑgwŸšc>ô¸ûeŒò{cüc"ʉU=r¾Í9·‰³Þ/\§çæi䌅øÓº?»ŸœI3#n&$XÌ”ˆã5å¿KWÝ…¢rª3¯G Žs9E¾Šóg ^<¥§øäKÔüž£-êDÛ¹ãÁ¬m«úycóùÒ³ûÉ œ+yYOÐq+Py'_¤«&0£r´«)0:Nñixœg×7˜:¯±=%] (>pòìù³Ÿ³YĹîQÅ@˜&ßÉàâÍ‹(OœÏÏ–Ó• …‚ãçµêW} R7ˆÎõ:Šð«Ý\"™[KRýáàb÷ÛnªF,¥À‚r¢œkP÷ EôçÇÖ;oQ]$|æDî1úÍ"öO¼?îðÂ?#¢Ò–Åß"Ñ.'QPäeğ»*ü•"N^X'¢¹õŒÂà ‹îGˆhË…ƒœG× ¼zÍy°§ü-"ºFkãÙF¸fž1è±ÛýoeÌÁF½O½uzj§g÷½E›~^úÇm³«A¾sÇ_õùvùÙrÚœ]¯ïßÒq‚»òõÎÇËD|YŽ>®W~b_‘Û{Ë››‰xtUÿê[Göã?;Ÿ«}íxkþã?9\}CR@I ("IÁ†ÇÒöü¿`w?µ¸16¹NŒG\úzˆÁîUÏèlχmÿ3ã´cŽºÐ±ˆû~oùèò‘OàEÔ‹0ÊRQ6Ok”‡3Å͘÷p&@V¸ªF g Š1éæKr#Ûˆ‡,6hS|K:~ê°›¤VS"úx­|¥“®Ï—d&|Ó"Z*ÆMŽÚ¿Z…Ö™Ì÷ÅÒùRÂsð‹²©†5WñûT#šˆ:)¼|rq{ï›|€Šè‹$Sô"²R<ÛD´W|$btkFm·žˆ³mDnó±ÃBô3~@ûÉu€vœK·Ý[ñ~ë_aïZ„ÇéÂ| |% 8dŠïcW”*} O‹øÉŽ)=üž¯?4^Ìqêï‚«oH ("IE$)пŧ† íj‚YÂØlÔ‘Y#¶ 1ýÿÖnA›"’$¢œV)â9‰³QD²(âR+vg"F3î o!1@ÄÒÚ†÷8ПxÎ×Mÿš©jBf³_Ç/[‚2—¥;:žmŒOWmgÃ:åU°›a)¥ înüŠè¿Ž\ƒÖ@?ô^‚˜{íÇ…Á;˜Q}s^8³²lŒf\J)“*˜Èþ±a@ç)÷2+¢‰ÇáƒáBVÿÙU§YMÍ7Ñ⬈ò"H1äÕ2ü¨)‹è/½OW¦Rˆö¸@~»D\oÒÐyЏ?  DË6kÕÃPû%,4õ7Ï=,²\µ€„m¾¢yØŽG~'Ì|ḛ̀”È݈mÎh„–°\½ ¤7Å÷ƒ'í9 Qîr*Bî>òsœ ®¾!) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤`±ÖÿßÝþY¨êÝ0z­õ‘ô=9›xoòóù/Ñ`t¹¹¶×Z—S “¾‹78>úγFntD,Oiýÿ`™v,¢×À]ûåߎ¸Ë?êÕ&ÒÒÐzÇ?Ž¿ë¬‘;oQ]4#‡ÃÔ@ÅÕIâ_ŸcÝ&"®O;GL_бÝr¢[]‘憎'6X+iŠ(CÀ.;E\7É[w;®—>îG¼Šò !RÄjn£Á…½Ÿñ®(ÖU{„5Ÿ ¯{D\?k9Ý#_ŠŽß™µf£ÏÏ´9I ¢hÍY‘•å„':‰ˆò/ÕåE¤GhÛ ¢Øð¸ìT„³JÜ®ï D´IMŠøâ[³ú˾Ší°œ •y]8EÜ€QÜrï¼@ÄZܾíýs•CD¬ñCHeG¤y!ô ¯ðB.Ñ-O ™ ý 6^öV*Pƒ㌊ 7!\q,"oÍ»i3+ídŠî¢xoçÅ·Åa¯YíE\«73R½q@[vRt´°SâÊùh멈b´@ß.¢ó}àHNñ‘PD’ŠHR@I ("IE$)8•ˆÝá5×\äpÊÔœïÞá®K<†3‰8О[ÖM|bV»#—ƒ=ÍIE|r=b”ú”ˆ`™$E|š‰xÜzÄ0ñ‘ˆ¸Èu‰p&YØK[vsýÿñzK®K|šS‰H¾ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$‘¤€"’PD’ŠHR@I ("IE$) ˆ$RÄö{0jø+{¼¿ù@VT(p°ˆüñÒ8BÄñ("iý¯ÄWô/9Õö³Jò÷í^Ñïó×c‰¤‰Ø~Ðpý…±ÑsÛøÁ/¹Wü[vÔ4VX¾s²WÄBɈ÷ˆhö£ˆÄò QË’"’.±ˆûÛˆó"ÒEò@vVZ/þà6þ]b+9Ñ·¿wÌ^3YyjŠ"‘£Ø-bÔ7!dûkDŽG“áê’ŠHR@I Ä8âÚäÛ·ÊÆ.bðÃ5„„¨E¦—q™U6jO?€MH qTÑQD² ¢^_(ÿÇ“w8„"’-Ä·f±|+˜voã6"E$}æE VãD!ª&¤ˆdE$)0"Še\‘¼-b툷íZW·öuðí@Bô€vë]Ù]V_~Z©bAâú¾ø÷­«BIÈ]Ä §øÈg¹ü»+_("ù07¯ÿªEB>Èÿ·æ+WßÃe`$O‹x½ñéà ggþùˆµÂï!SDrÓ¥OõR("9‚Ýâ/ŠHŽfæùˆ~u—¡ˆä¶<±NÉlyXY¶RDr4‘¤`FD¶ÉË™y>"{Íäålx>âŠH^§øH ("IWßPD’‚UDB>ÊCÄ«r X`èåJÈkÀrÝ¿N êÊOWÖä{¹¢Àÿªh©™ÏIEND®B`‚bochs-2.6/win32_enh_dbg.rc0000644000175000017500000000656212020641507015301 0ustar guillemguillem#include #include "gui/wenhdbg_res.h" MENU_1 MENU BEGIN POPUP "&Command" BEGIN MENUITEM "Continue [c]\tF5",CMD_CONT MENUITEM "Step [s]\tF11",CMD_STEP1 MENUITEM "Step #...\tF9",CMD_STEPN MENUITEM "Break\tCtrl+C",CMD_BREAK MENUITEM SEPARATOR MENUITEM "Breakpoint (ASM selected)\tF6",CMD_BRKPT MENUITEM "Watch Write (PhysDump selected)\tF6",CMD_WPTWR MENUITEM "Watch Read (PhysDump selected)\tCtrl+F6",CMD_WPTRD MENUITEM SEPARATOR MENUITEM "Find...\tCtrl+F",CMD_FIND MENUITEM "Refresh Screen\tF4",CMD_RFRSH END POPUP "&View" BEGIN MENUITEM "Physical Dump...\tCtrl+F7",CMD_PHYDMP MENUITEM "Linear Dump...\tF7",CMD_LINDMP MENUITEM "Stack\tF2",CMD_STACK MENUITEM "GDT\tCtrl+F2",CMD_GDTV MENUITEM "IDT\tShift+F2",CMD_IDTV MENUITEM "Page Table\tAlt+F2",CMD_PAGEV MENUITEM "Current MemDump\tEsc",CMD_CMEM MENUITEM SEPARATOR MENUITEM "Bochs param_tree\tCtrl+F3",CMD_PTREE MENUITEM "Disassemble...\tCtrl+D",CMD_DISASM END POPUP "&Options" BEGIN MENUITEM "Break on CPU mode change\tShift+F6",CMD_MODEB MENUITEM "Default disassembled lines ...",CMD_DADEF MENUITEM "Toggle Intel/ATT syntax\tF3",CMD_ATTI MENUITEM SEPARATOR MENUITEM "Font...",CMD_FONT MENUITEM "Text in UPPERCASE",CMD_UCASE MENUITEM "Show Input/Output Windows",CMD_IOWIN MENUITEM "Show Buttons",CMD_SBTN MENUITEM SEPARATOR MENUITEM "MemDump in Hex\tAlt+F7",CMD_MHEX MENUITEM "MemDump in ASCII\tShift+F7",CMD_MASCII MENUITEM "LittleEndian",CMD_LEND POPUP "Dump 'Wordsize'" BEGIN MENUITEM "1 byte\tAlt+1",CMD_WS_1 MENUITEM "2 bytes\tAlt+2",CMD_WS_2 MENUITEM "4 bytes\tAlt+4",CMD_WS_4 MENUITEM "8 bytes\tAlt+8",CMD_WS_8 MENUITEM "16 bytes\tAlt+6 ",CMD_WS16 END MENUITEM SEPARATOR MENUITEM "Ignore extra ASM lines",CMD_IGNSA MENUITEM "Ignore 'Next at t='",CMD_IGNNT MENUITEM SEPARATOR MENUITEM "Colorize Register Types",CMD_RCLR // the next 8 MUST be in strict menuID order MENUITEM "Show 32bit Registers",CMD_EREG MENUITEM "Show Segment Registers",CMD_SREG MENUITEM "Show System Registers",CMD_SYSR MENUITEM "Show Control Registers",CMD_CREG MENUITEM "Show MMX/FPU Registers\tAlt+F3",CMD_FPUR MENUITEM "Show SSE Registers\tCtrl+F4",CMD_XMMR MENUITEM "Show Debug Registers\tShift+F4",CMD_DREG MENUITEM "Show Test Registers",CMD_TREG END POPUP "&Help" BEGIN MENUITEM "About...",CMD_ABOUT END END DIALOG_AT DIALOGEX 0, 0, 365, 62 STYLE DS_ABSALIGN | DS_MODALFRAME | DS_3DLOOK | DS_CENTER | 0x200L | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX FONT 8, "Tahoma", 400, 0 BEGIN CONTROL "", 101, "static", SS_CENTER | WS_CHILD | WS_VISIBLE, 10, 9, 284, 26 CONTROL "", 102, "edit", ES_AUTOHSCROLL | ES_LEFT | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 10, 41, 285, 15 CONTROL "OK", IDOK, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 303, 22, 50, 14 CONTROL "Cancel", IDCANCEL, "BUTTON", BS_PUSHBUTTON | BS_CENTER | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 303, 41, 50, 14 END bochs-2.6/pc_system.h0000644000175000017500000001475312020641507014523 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pc_system.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_PCSYS_H #define BX_PCSYS_H #define BX_MAX_TIMERS 64 #define BX_NULL_TIMER_HANDLE 10000 typedef void (*bx_timer_handler_t)(void *); BOCHSAPI extern class bx_pc_system_c bx_pc_system; #ifdef PROVIDE_M_IPS extern double m_ips; #endif class BOCHSAPI bx_pc_system_c : private logfunctions { private: // =============================== // Timer oriented private features // =============================== struct { bx_bool inUse; // Timer slot is in-use (currently registered). Bit64u period; // Timer periodocity in cpu ticks. Bit64u timeToFire; // Time to fire next (in absolute ticks). bx_bool active; // 0=inactive, 1=active. bx_bool continuous; // 0=one-shot timer, 1=continuous periodicity. bx_timer_handler_t funct; // A callback function for when the // timer fires. void *this_ptr; // The this-> pointer for C++ callbacks // has to be stored as well. #define BxMaxTimerIDLen 32 char id[BxMaxTimerIDLen]; // String ID of timer. } timer[BX_MAX_TIMERS]; unsigned numTimers; // Number of currently allocated timers. unsigned triggeredTimer; // ID of the actually triggered timer. Bit32u currCountdown; // Current countdown ticks value (decrements to 0). Bit32u currCountdownPeriod; // Length of current countdown period. Bit64u ticksTotal; // Num ticks total since start of emulator execution. Bit64u lastTimeUsec; // Last sequentially read time in usec. Bit64u usecSinceLast; // Number of useconds claimed since then. // A special null timer is always inserted in the timer[0] slot. This // make sure that at least one timer is always active, and that the // duration is always less than a maximum 32-bit integer, so a 32-bit // counter can be used for the current countdown. static const Bit64u NullTimerInterval; static void nullTimer(void* this_ptr); #if !defined(PROVIDE_M_IPS) // This is the emulator speed, as measured in millions of // x86 instructions per second that it can emulate on some hypothetically // nomimal workload. double m_ips; // Millions of Instructions Per Second #endif // This handler is called when the function which decrements the clock // ticks finds that an event has occurred. void countdownEvent(void); public: // ============================== // Timer oriented public features // ============================== void initialize(Bit32u ips); int register_timer(void *this_ptr, bx_timer_handler_t, Bit32u useconds, bx_bool continuous, bx_bool active, const char *id); bx_bool unregisterTimer(unsigned timerID); void start_timers(void); void activate_timer(unsigned timer_index, Bit32u useconds, bx_bool continuous); void deactivate_timer(unsigned timer_index); unsigned triggeredTimerID(void) { return triggeredTimer; } static BX_CPP_INLINE void tick1(void) { if (--bx_pc_system.currCountdown == 0) { bx_pc_system.countdownEvent(); } } static BX_CPP_INLINE void tickn(Bit32u n) { while (n >= bx_pc_system.currCountdown) { n -= bx_pc_system.currCountdown; bx_pc_system.currCountdown = 0; bx_pc_system.countdownEvent(); // bx_pc_system.currCountdown is adjusted to new value by countdownevent(). } // 'n' is not (or no longer) >= the countdown size. We can just decrement // the remaining requested ticks and continue. bx_pc_system.currCountdown -= n; } int register_timer_ticks(void* this_ptr, bx_timer_handler_t, Bit64u ticks, bx_bool continuous, bx_bool active, const char *id); void activate_timer_ticks(unsigned index, Bit64u instructions, bx_bool continuous); Bit64u time_usec(); Bit64u time_usec_sequential(); static BX_CPP_INLINE Bit64u time_ticks() { return bx_pc_system.ticksTotal + Bit64u(bx_pc_system.currCountdownPeriod - bx_pc_system.currCountdown); } static BX_CPP_INLINE Bit32u getNumCpuTicksLeftNextEvent(void) { return bx_pc_system.currCountdown; } #if BX_DEBUGGER static void timebp_handler(void* this_ptr); #endif static void benchmarkTimer(void* this_ptr); // =========================== // Non-timer oriented features // =========================== bx_bool HRQ; // Hold Request // Address line 20 control: // 1 = enabled: extended memory is accessible // 0 = disabled: A20 address line is forced low to simulate // an 8088 address map bx_bool enable_a20; // start out masking physical memory addresses to: // 8086: 20 bits // 286: 24 bits // 386: 32 bits // when A20 line is disabled, mask physical memory addresses to: // 286: 20 bits // 386: 20 bits bx_phy_address a20_mask; volatile bx_bool kill_bochs_request; void set_HRQ(bx_bool val); // set the Hold ReQuest line void set_INTR(bx_bool value); // set the INTR line to value // Cpu and System Reset int Reset(unsigned type); Bit8u IAC(void); bx_pc_system_c(); Bit32u inp(Bit16u addr, unsigned io_len) BX_CPP_AttrRegparmN(2); void outp(Bit16u addr, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); void set_enable_a20(bx_bool value); bx_bool get_enable_a20(void); void MemoryMappingChanged(void); // flush TLB in all CPUs void invlpg(bx_address addr); // flush TLB page in all CPUs void exit(void); void register_state(void); }; #endif bochs-2.6/instrument/0000755000175000017500000000000012020641474014545 5ustar guillemguillembochs-2.6/instrument/example2/0000755000175000017500000000000012020641474016262 5ustar guillemguillembochs-2.6/instrument/example2/Makefile.in0000644000175000017500000000304312020641474020327 0ustar guillemguillem# Copyright (C) 2001 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ SHELL = @SHELL@ @SET_MAKE@ CC = @CC@ CFLAGS = @CFLAGS@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ # =========================================================== # end of configurable options # =========================================================== BX_OBJS = \ instrument.o BX_INCLUDES = BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/. .@CPP_SUFFIX@.o: $(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@ .c.o: $(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@ libinstrument.a: $(BX_OBJS) @RMCOMMAND@ libinstrument.a @MAKELIB@ $(BX_OBJS) $(RANLIB) libinstrument.a $(BX_OBJS): $(BX_INCLUDES) clean: @RMCOMMAND@ *.o @RMCOMMAND@ *.a dist-clean: clean @RMCOMMAND@ Makefile bochs-2.6/instrument/example2/instrument.cc0000644000175000017500000000667612020641474021020 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.cc 11295 2012-07-24 15:32:55Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2009-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include "bochs.h" #include "cpu/cpu.h" #define BX_IA_STATS_ENTRIES (BX_IA_LAST*2) /* /r and /m form */ static struct bx_instr_ia_stats { bx_bool active; Bit32u ia_cnt[BX_IA_STATS_ENTRIES]; Bit32u total_cnt; Bit32u interrupts; Bit32u exceptions; } *ia_stats; static logfunctions *instrument_log = new logfunctions (); #define LOG_THIS instrument_log-> void bx_instr_initialize(unsigned cpu) { assert(cpu < BX_SMP_PROCESSORS); if (ia_stats == NULL) ia_stats = new bx_instr_ia_stats[BX_SMP_PROCESSORS]; ia_stats[cpu].active = 0; fprintf(stderr, "Initialize cpu %d instrumentation module\n", cpu); } void bx_instr_reset(unsigned cpu, unsigned type) { ia_stats[cpu].active = 1; ia_stats[cpu].total_cnt = 0; for(int n=0; n < BX_IA_STATS_ENTRIES; n++) ia_stats[cpu].ia_cnt[n] = 0; ia_stats[cpu].interrupts = ia_stats[cpu].exceptions = 0; } void bx_instr_interrupt(unsigned cpu, unsigned vector) { if(ia_stats[cpu].active) ia_stats[cpu].interrupts++; } void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code) { if(ia_stats[cpu].active) ia_stats[cpu].exceptions++; } void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) { if(ia_stats[cpu].active) ia_stats[cpu].interrupts++; } #define IA_CNT_DUMP_THRESHOLD 100000000 /* 100M */ void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i) { if(ia_stats[cpu].active) { ia_stats[cpu].ia_cnt[i->getIaOpcode() * 2 + !!i->modC0()]++; ia_stats[cpu].total_cnt++; if (ia_stats[cpu].total_cnt > IA_CNT_DUMP_THRESHOLD) { printf("Dump IA stats for CPU %d\n", cpu); printf("----------------------------------------------------------\n"); printf("Interrupts: %d, Exceptions: %d\n", ia_stats[cpu].interrupts, ia_stats[cpu].exceptions); while(1) { Bit32u max = 0, max_index = 0; for (int n=0;n < BX_IA_STATS_ENTRIES; n++) { if (ia_stats[cpu].ia_cnt[n] > max) { max = ia_stats[cpu].ia_cnt[n]; max_index = n; } } if (max == 0) break; printf("%s /%c: %f%%\n", get_bx_opcode_name(max_index/2), (max_index & 1) ? 'm' : 'r', ia_stats[cpu].ia_cnt[max_index] * 100.0f / ia_stats[cpu].total_cnt); ia_stats[cpu].ia_cnt[max_index] = 0; } ia_stats[cpu].interrupts = ia_stats[cpu].exceptions = ia_stats[cpu].total_cnt = 0; } } } bochs-2.6/instrument/example2/instrument.h0000644000175000017500000001270512020641474020650 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.h 11295 2012-07-24 15:32:55Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2009-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if BX_INSTRUMENTATION class bxInstruction_c; // define if you want to store instruction opcode bytes in bxInstruction_c //#define BX_INSTR_STORE_OPCODE_BYTES // called from the CPU core void bx_instr_initialize(unsigned cpu); void bx_instr_reset(unsigned cpu, unsigned type); void bx_instr_interrupt(unsigned cpu, unsigned vector); void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code); void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip); void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i); /* initialization/deinitialization of instrumentalization*/ #define BX_INSTR_INIT_ENV() #define BX_INSTR_EXIT_ENV() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id) #define BX_INSTR_EXIT(cpu_id) #define BX_INSTR_RESET(cpu_id, type) bx_instr_reset(cpu_id, type) #define BX_INSTR_HLT(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) #define BX_INSTR_NEW_INSTRUCTION(cpu_id) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() #define BX_INSTR_DEBUG_CMD(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \ bx_instr_exception(cpu_id, vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) bx_instr_before_execution(cpu_id, i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) /* linear memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) /* physical memory access */ #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) #define BX_INSTR_INP2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) #else // BX_INSTRUMENTATION /* initialization/deinitialization of instrumentalization */ #define BX_INSTR_INIT_ENV() #define BX_INSTR_EXIT_ENV() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) #define BX_INSTR_EXIT(cpu_id) #define BX_INSTR_RESET(cpu_id, type) #define BX_INSTR_HLT(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) #define BX_INSTR_NEW_INSTRUCTION(cpu_id) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() #define BX_INSTR_DEBUG_CMD(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) /* linear memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) /* physical memory access */ #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) #define BX_INSTR_INP2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) #endif // BX_INSTRUMENTATION bochs-2.6/instrument/example1/0000755000175000017500000000000012020641474016261 5ustar guillemguillembochs-2.6/instrument/example1/Makefile.in0000644000175000017500000000304312020641474020326 0ustar guillemguillem# Copyright (C) 2001 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ SHELL = @SHELL@ @SET_MAKE@ CC = @CC@ CFLAGS = @CFLAGS@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ # =========================================================== # end of configurable options # =========================================================== BX_OBJS = \ instrument.o BX_INCLUDES = BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/. .@CPP_SUFFIX@.o: $(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@ .c.o: $(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@ libinstrument.a: $(BX_OBJS) @RMCOMMAND@ libinstrument.a @MAKELIB@ $(BX_OBJS) $(RANLIB) libinstrument.a $(BX_OBJS): $(BX_INCLUDES) clean: @RMCOMMAND@ *.o @RMCOMMAND@ *.a dist-clean: clean @RMCOMMAND@ Makefile bochs-2.6/instrument/example1/instrument.cc0000644000175000017500000001175312020641474021007 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.cc 11295 2012-07-24 15:32:55Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include "bochs.h" #include "cpu/cpu.h" #include "disasm/disasm.h" bxInstrumentation *icpu = NULL; static disassembler bx_disassembler; void bx_instr_init_env(void) {} void bx_instr_exit_env(void) {} void bx_instr_initialize(unsigned cpu) { assert(cpu < BX_SMP_PROCESSORS); if (icpu == NULL) icpu = new bxInstrumentation[BX_SMP_PROCESSORS]; icpu[cpu].set_cpu_id(cpu); fprintf(stderr, "Initialize cpu %d\n", cpu); } void bxInstrumentation::bx_instr_reset(unsigned type) { ready = is_branch = 0; num_data_accesses = 0; active = 1; } void bxInstrumentation::bx_print_instruction(void) { char disasm_tbuf[512]; // buffer for instruction disassembly bx_disassembler.disasm(is32, is64, 0, 0, opcode, disasm_tbuf); if(opcode_length != 0) { unsigned n; fprintf(stderr, "----------------------------------------------------------\n"); fprintf(stderr, "CPU: %d: %s\n", cpu_id, disasm_tbuf); fprintf(stderr, "LEN: %d\tBYTES: ", opcode_length); for(n=0;n < opcode_length;n++) fprintf(stderr, "%02x", opcode[n]); if(is_branch) { fprintf(stderr, "\tBRANCH "); if(is_taken) fprintf(stderr, "TARGET " FMT_ADDRX " (TAKEN)", target_linear); else fprintf(stderr, "(NOT TAKEN)"); } fprintf(stderr, "\n"); for(n=0;n < num_data_accesses;n++) { fprintf(stderr, "MEM ACCESS[%u]: 0x" FMT_ADDRX " (linear) 0x" FMT_PHY_ADDRX " (physical) %s SIZE: %d\n", n, data_access[n].laddr, data_access[n].paddr, data_access[n].rw == BX_READ ? "RD":"WR", data_access[n].size); } fprintf(stderr, "\n"); } } void bxInstrumentation::bx_instr_before_execution(bxInstruction_c *i) { if (!active) return; if (ready) bx_print_instruction(); // prepare instruction_t structure for new instruction ready = 1; num_data_accesses = 0; is_branch = 0; is32 = BX_CPU(cpu_id)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b; is64 = BX_CPU(cpu_id)->long64_mode(); opcode_length = i->ilen(); memcpy(opcode, i->get_opcode_bytes(), opcode_length); } void bxInstrumentation::bx_instr_after_execution(bxInstruction_c *i) { if (!active) return; if (ready) { bx_print_instruction(); ready = 0; } } void bxInstrumentation::branch_taken(bx_address new_eip) { if (!active || !ready) return; is_branch = 1; is_taken = 1; // find linear address target_linear = BX_CPU(cpu_id)->get_laddr(BX_SEG_REG_CS, new_eip); } void bxInstrumentation::bx_instr_cnear_branch_taken(bx_address branch_eip, bx_address new_eip) { branch_taken(new_eip); } void bxInstrumentation::bx_instr_cnear_branch_not_taken(bx_address branch_eip) { if (!active || !ready) return; is_branch = 1; is_taken = 0; } void bxInstrumentation::bx_instr_ucnear_branch(unsigned what, bx_address branch_eip, bx_address new_eip) { branch_taken(new_eip); } void bxInstrumentation::bx_instr_far_branch(unsigned what, Bit16u new_cs, bx_address new_eip) { branch_taken(new_eip); } void bxInstrumentation::bx_instr_interrupt(unsigned vector) { if(active) { fprintf(stderr, "CPU %u: interrupt %02xh\n", cpu_id, vector); } } void bxInstrumentation::bx_instr_exception(unsigned vector, unsigned error_code) { if(active) { fprintf(stderr, "CPU %u: exception %02xh error_code=%x\n", cpu_id, vector, error_code); } } void bxInstrumentation::bx_instr_hwinterrupt(unsigned vector, Bit16u cs, bx_address eip) { if(active) { fprintf(stderr, "CPU %u: hardware interrupt %02xh\n", cpu_id, vector); } } void bxInstrumentation::bx_instr_lin_access(bx_address lin, bx_phy_adress phy, unsigned len, unsigned rw) { if(!active || !ready) return; if (num_data_accesses < MAX_DATA_ACCESSES) { data_access[num_data_accesses].laddr = lin; data_access[num_data_accesses].paddr = phy; data_access[num_data_accesses].rw = rw; data_access[num_data_accesses].size = len; num_data_accesses++; } } bochs-2.6/instrument/example1/instrument.h0000644000175000017500000001653112020641474020650 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.h 11295 2012-07-24 15:32:55Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if BX_INSTRUMENTATION class bxInstruction_c; // define if you want to store instruction opcode bytes in bxInstruction_c #define BX_INSTR_STORE_OPCODE_BYTES void bx_instr_init_env(void); void bx_instr_exit_env(void); void bx_instr_initialize(unsigned cpu); // maximum size of an instruction #define MAX_OPCODE_LENGTH 16 // maximum physical addresses an instruction can generate #define MAX_DATA_ACCESSES 1024 class bxInstrumentation { public: bx_bool ready; // is current instruction ready to be printed bx_bool active; unsigned cpu_id; /* decoding */ unsigned opcode_length; Bit8u opcode[MAX_OPCODE_LENGTH]; bx_bool is32, is64; /* memory accesses */ unsigned num_data_accesses; struct { bx_address laddr; // linear address bx_phy_address paddr; // physical address unsigned rw; // BX_READ, BX_WRITE or BX_RW unsigned size; // 1 .. 32 } data_access[MAX_DATA_ACCESSES]; /* branch resolution and target */ bx_bool is_branch; bx_bool is_taken; bx_address target_linear; public: bxInstrumentation(): ready(0), active(0) {} void set_cpu_id(unsigned cpu) { cpu_id = cpu; } void activate() { active = 1; } void deactivate() { active = 0; } void toggle_active() { active = !active; } bx_bool is_active() const { return active; } void bx_instr_reset(unsigned type); void bx_instr_cnear_branch_taken(bx_address branch_eip, bx_address new_eip); void bx_instr_cnear_branch_not_taken(bx_address branch_eip); void bx_instr_ucnear_branch(unsigned what, bx_address branch_eip, bx_address new_eip); void bx_instr_far_branch(unsigned what, Bit16u new_cs, bx_address new_eip); void bx_instr_before_execution(bxInstruction_c *i); void bx_instr_after_execution(bxInstruction_c *i); void bx_instr_interrupt(unsigned vector); void bx_instr_exception(unsigned vector, unsigned error_code); void bx_instr_hwinterrupt(unsigned vector, Bit16u cs, bx_address eip); void bx_instr_lin_access(bx_address lin, bx_phy_adress phy, unsigned len, unsigned rw); private: void branch_taken(bx_address new_eip); void bx_print_instruction(void); }; void bx_instr_init(unsigned cpu); extern bxInstrumentation *icpu; /* initialization/deinitialization of instrumentalization*/ #define BX_INSTR_INIT_ENV() bx_instr_init_env() #define BX_INSTR_EXIT_ENV() bx_instr_exit_env() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id) #define BX_INSTR_EXIT(cpu_id) #define BX_INSTR_RESET(cpu_id, type) icpu[cpu_id].bx_instr_reset(type) #define BX_INSTR_HLT(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() #define BX_INSTR_DEBUG_CMD(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) icpu[cpu_id].bx_instr_cnear_branch_taken(branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) icpu[cpu_id].bx_instr_cnear_branch_not_taken(branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) icpu[cpu_id].bx_instr_ucnear_branch(what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) icpu[cpu_id].bx_instr_far_branch(what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \ icpu[cpu_id].bx_instr_exception(vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) icpu[cpu_id].bx_instr_interrupt(vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) icpu[cpu_id].bx_instr_hwinterrupt(vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) icpu[cpu_id].bx_instr_before_execution(i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) icpu[cpu_id].bx_instr_after_execution(i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) /* memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) \ icpu[cpu_id].bx_instr_lin_access(lin, phy, len, rw) #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) #define BX_INSTR_INP2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) #else // BX_INSTRUMENTATION /* initialization/deinitialization of instrumentalization */ #define BX_INSTR_INIT_ENV() #define BX_INSTR_EXIT_ENV() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) #define BX_INSTR_EXIT(cpu_id) #define BX_INSTR_RESET(cpu_id, type) #define BX_INSTR_HLT(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() #define BX_INSTR_DEBUG_CMD(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) /* linear memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) /* physical memory access */ #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) #define BX_INSTR_INP2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) #endif // BX_INSTRUMENTATION bochs-2.6/instrument/instrumentation.txt0000644000175000017500000002145312020641474020556 0ustar guillemguillemREADME-instrumentation To use instrumentation features in bochs, you must compile in support for it. You should build a custom instrumentation library in a separate directory in the "instrument/" directory. To tell configure which instrumentation library you want to use, use the "--enable-instrumentation" option. The default library consists of a set of stubs, and the following are equivalent: ./configure [...] --enable-instrumentation ./configure [...] --enable-instrumentation="instrument/stubs" You could make a separate directory with your custom library, for example "instrument/myinstrument", copy the contents of the "instrument/stubs" directory to it, then customize it. Use: ./configure [...] --enable-instrumentation="instrument/myinstrument" ----------------------------------------------------------------------------- BOCHS instrumentation callbacks void bx_instr_init_env(); The callback is called when Bochs is initialized, before of reading .bochsrc. It can be used for registration of parameters in siminterface. Then when bx_instr_init() is called it can access configuration parameters defined by bx_instr_init_env(), so instrumentalization module can use additional options in .bochsrc. void bx_instr_exit_env(); The callback is called each time Bochs exits. void bx_instr_initialize(unsigned cpu); The callback is called each time, when Bochs initializes the CPU object. It can be used for initialization of user's data, dynamic memory allocation and etc. void bx_instr_exit(unsigned cpu); The callback is called each time, when Bochs destructs the CPU object. It can be used for destruction of user's data, allocated by bx_instr_init callback. void bx_instr_reset(unsigned cpu, unsigned type); The callback is called each time, when Bochs resets the CPU object. It would be executed once at the start of simulation and each time that user presses RESET BUTTON on the simulator's control panel. void bx_instr_hlt(unsigned cpu); The callback is called each time, when Bochs' emulated CPU enters HALT or SHUTDOWN state. void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags); The callback is called each time, when Bochs' emulated CPU enters to the MWAIT state. The callback receives monitored memory range and MWAIT flags as a parameters. void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip); The callback is called each time, when currently executed instruction is a conditional near branch and it is taken. void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip); The callback is called each time, when currently executed instruction is a conditional near branch and it is not taken. void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip); The callback is called each time, when currently executed instruction is an unconditional near branch (always taken). void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip); The callback is called each time, when currently executed instruction is an unconditional far branch (always taken). Possible operation types, passed through bx_instr_ucnear_branch and bx_instr_far_branch are: #define BX_INSTR_IS_JMP 10 #define BX_INSTR_IS_JMP_INDIRECT 11 #define BX_INSTR_IS_CALL 12 #define BX_INSTR_IS_CALL_INDIRECT 13 #define BX_INSTR_IS_RET 14 #define BX_INSTR_IS_IRET 15 #define BX_INSTR_IS_INT 16 #define BX_INSTR_IS_SYSCALL 17 #define BX_INSTR_IS_SYSRET 18 #define BX_INSTR_IS_SYSENTER 19 #define BX_INSTR_IS_SYSEXIT 20 void bx_instr_opcode(unsigned cpu, bxInstruction_c *i, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64); The callback is called each time, when Bochs completes to decode a new instruction. Through this callback function Bochs could provide an opcode of the instruction, opcode length and an execution mode (16/32/64). Note, that Bochs uses translation caches so each simulated instruction might be executed multiple times but decoded only once. void bx_instr_interrupt(unsigned cpu, unsigned vector); The callback is called each time, when Bochs simulator executes an interrupt (software interrupt, hardware interrupt or an exception). void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code); The callback is called each time, when Bochs simulator executes an exception. void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip); The callback is called each time, when Bochs simulator executes a hardware interrupt. void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr); The callback is called each time the CLFLUSH instruction is executed. void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr_value); void bx_instr_cache_cntrl(unsigned cpu, unsigned what); The callback is called each time, when Bochs simulator executes a cache/tlb control instruction. Possible instruction types, passed through bx_instr_tlb_cntrl are: #define BX_INSTR_MOV_CR0 10 #define BX_INSTR_MOV_CR3 11 #define BX_INSTR_MOV_CR4 12 #define BX_INSTR_TASK_SWITCH 13 #define BX_INSTR_CONTEXT_SWITCH 14 /* VMM and SMM enter/exit */ #define BX_INSTR_INVLPG 15 #define BX_INSTR_INVEPT 16 #define BX_INSTR_INVVPID 17 #define BX_INSTR_INVPCID 18 The new_cr_value is provided for first 4 instruction types only and undefined for all others. Possible instruction types, passed through bx_instr_cache_cntrl are: #define BX_INSTR_INVD 10 #define BX_INSTR_WBINVD 11 void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset); The callback is called each time, when Bochs simulator executes a PREFETCH instruction. Possible PREFETCH types: #define BX_INSTR_PREFETCH_NTA 00 #define BX_INSTR_PREFETCH_T0 01 #define BX_INSTR_PREFETCH_T1 02 #define BX_INSTR_PREFETCH_T2 03 The seg/offset arguments indicate the address of the requested prefetch. void bx_instr_wrmsr(unsigned cpu, unsigned msr, Bit64u value); This callback is called each time when WRMSR instruction is executed. MSR number and written value passed as parameters to the callback function. void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i); The callback is called each time, when Bochs simulator starts a new repeat iteration. void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i); The callback is called each time, when Bochs simulator starts a new instruction execution. In case of repeat instruction the callback will be called only once before the first iteration will be started. void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i); The callback is called each time, when Bochs simulator finishes any instruction execution. In case of repeat instruction the callback will be called only once after all repeat iterations. void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw); The callback is called each time, when Bochs simulator executes a linear memory access. Note that no page split accesses will be generated because Bochs splits page split accesses to two different memory accesses during its execution flow. The callback also will not be generated in case of direct physical memory access like page walks, SMM, VMM or SVM operations. Possible access types are: BX_READ, BX_WRITE and BX_RW. Currently the callback is not supported when repeat-speedups optimization is enabled. void bx_instr_phy_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw); The callback is called each time, when Bochs simulator executes a physical memory access. Physical accesses include memory accesses generated by the CPU during page walks, SMM, VMM or SVM operations. Note that no page split accesses will be generated because Bochs splits page split accesses to two different memory accesses during its execution flow. Possible access types are: BX_READ, BX_WRITE and BX_RW. void bx_instr_inp(Bit16u addr, unsigned len); void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val); void bx_instr_outp(Bit16u addr, unsigned len, unsigned val); These callback functions are a feedback from various system devices. ----------------------------------------------------------------------------- Known problems: 1. BX_INSTR_LIN_ACCESS doesn't work when repeat-speedups feature is enabled. Feature requests: 1. BX_INSTR_CNEAR_BRANCH_NOT_TAKEN callback should have an additional 'not taken' new_EIP parameter. 2. BX_INSTR_SMI, BX_INSTR_NMI, BX_INSTR_SIPI and other external events callbacks bochs-2.6/instrument/stubs/0000755000175000017500000000000012020641474015705 5ustar guillemguillembochs-2.6/instrument/stubs/Makefile.in0000644000175000017500000000304312020641474017752 0ustar guillemguillem# Copyright (C) 2001 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ SHELL = @SHELL@ @SET_MAKE@ CC = @CC@ CFLAGS = @CFLAGS@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ # =========================================================== # end of configurable options # =========================================================== BX_OBJS = \ instrument.o BX_INCLUDES = BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/. .@CPP_SUFFIX@.o: $(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@ .c.o: $(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@ libinstrument.a: $(BX_OBJS) @RMCOMMAND@ libinstrument.a @MAKELIB@ $(BX_OBJS) $(RANLIB) libinstrument.a $(BX_OBJS): $(BX_INCLUDES) clean: @RMCOMMAND@ *.o @RMCOMMAND@ *.a dist-clean: clean @RMCOMMAND@ Makefile bochs-2.6/instrument/stubs/instrument.cc0000644000175000017500000000613612020641474020432 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.cc 11312 2012-08-05 13:40:32Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "bochs.h" #if BX_INSTRUMENTATION void bx_instr_init_env(void) {} void bx_instr_exit_env(void) {} void bx_instr_initialize(unsigned cpu) {} void bx_instr_exit(unsigned cpu) {} void bx_instr_reset(unsigned cpu, unsigned type) {} void bx_instr_hlt(unsigned cpu) {} void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags) {} void bx_instr_debug_promt() {} void bx_instr_debug_cmd(const char *cmd) {} void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip) {} void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip) {} void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip) {} void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip) {} void bx_instr_opcode(unsigned cpu, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64) {} void bx_instr_interrupt(unsigned cpu, unsigned vector) {} void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code) {} void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) {} void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3) {} void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr) {} void bx_instr_cache_cntrl(unsigned cpu, unsigned what) {} void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset) {} void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i) {} void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i) {} void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i) {} void bx_instr_inp(Bit16u addr, unsigned len) {} void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val) {} void bx_instr_outp(Bit16u addr, unsigned len, unsigned val) {} void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw) {} void bx_instr_phy_access(unsigned cpu, bx_address phy, unsigned len, unsigned rw) {} void bx_instr_wrmsr(unsigned cpu, unsigned addr, Bit64u value) {} #endif bochs-2.6/instrument/stubs/instrument.h0000644000175000017500000001764712020641474020305 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.h 11295 2012-07-24 15:32:55Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if BX_INSTRUMENTATION class bxInstruction_c; // define if you want to store instruction opcode bytes in bxInstruction_c //#define BX_INSTR_STORE_OPCODE_BYTES void bx_instr_init_env(void); void bx_instr_exit_env(void); // called from the CPU core void bx_instr_initialize(unsigned cpu); void bx_instr_exit(unsigned cpu); void bx_instr_reset(unsigned cpu, unsigned type); void bx_instr_hlt(unsigned cpu); void bx_instr_mwait(unsigned cpu, bx_phy_address addr, unsigned len, Bit32u flags); void bx_instr_debug_promt(); void bx_instr_debug_cmd(const char *cmd); void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip); void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip); void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip); void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip); void bx_instr_opcode(unsigned cpu, bxInstruction_c *i, const Bit8u *opcode, unsigned len, bx_bool is32, bx_bool is64); void bx_instr_interrupt(unsigned cpu, unsigned vector); void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code); void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip); void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, bx_phy_address new_cr3); void bx_instr_cache_cntrl(unsigned cpu, unsigned what); void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset); void bx_instr_clflush(unsigned cpu, bx_address laddr, bx_phy_address paddr); void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i); void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i); void bx_instr_repeat_iteration(unsigned cpu, bxInstruction_c *i); void bx_instr_inp(Bit16u addr, unsigned len); void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val); void bx_instr_outp(Bit16u addr, unsigned len, unsigned val); void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_address phy, unsigned len, unsigned rw); void bx_instr_phy_access(unsigned cpu, bx_address phy, unsigned len, unsigned rw); void bx_instr_wrmsr(unsigned cpu, unsigned addr, Bit64u value); /* initialization/deinitialization of instrumentalization*/ #define BX_INSTR_INIT_ENV() bx_instr_init_env() #define BX_INSTR_EXIT_ENV() bx_instr_exit_env() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id) #define BX_INSTR_EXIT(cpu_id) bx_instr_exit(cpu_id) #define BX_INSTR_RESET(cpu_id, type) bx_instr_reset(cpu_id, type) #define BX_INSTR_HLT(cpu_id) bx_instr_hlt(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) \ bx_instr_mwait(cpu_id, addr, len, flags) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() bx_instr_debug_promt() #define BX_INSTR_DEBUG_CMD(cmd) bx_instr_debug_cmd(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) bx_instr_cnear_branch_taken(cpu_id, branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) bx_instr_cnear_branch_not_taken(cpu_id, branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) bx_instr_ucnear_branch(cpu_id, what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) bx_instr_far_branch(cpu_id, what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) \ bx_instr_opcode(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \ bx_instr_exception(cpu_id, vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) bx_instr_clflush(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) bx_instr_cache_cntrl(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) bx_instr_tlb_cntrl(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) \ bx_instr_prefetch_hint(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) bx_instr_before_execution(cpu_id, i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) bx_instr_after_execution(cpu_id, i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) bx_instr_repeat_iteration(cpu_id, i) /* linear memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) bx_instr_lin_access(cpu_id, lin, phy, len, rw) /* physical memory access */ #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) bx_instr_phy_access(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) bx_instr_inp(addr, len) #define BX_INSTR_INP2(addr, len, val) bx_instr_inp2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) bx_instr_outp(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) bx_instr_wrmsr(cpu_id, addr, value) #else /* initialization/deinitialization of instrumentalization */ #define BX_INSTR_INIT_ENV() #define BX_INSTR_EXIT_ENV() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) #define BX_INSTR_EXIT(cpu_id) #define BX_INSTR_RESET(cpu_id, type) #define BX_INSTR_HLT(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() #define BX_INSTR_DEBUG_CMD(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) /* linear memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) /* physical memory access */ #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) #define BX_INSTR_INP2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) #endif bochs-2.6/instrument/example0/0000755000175000017500000000000012020641474016260 5ustar guillemguillembochs-2.6/instrument/example0/Makefile.in0000644000175000017500000000304212020641474020324 0ustar guillemguillem# Copyright (C) 2001 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ SHELL = @SHELL@ @SET_MAKE@ CC = @CC@ CFLAGS = @CFLAGS@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ # =========================================================== # end of configurable options # =========================================================== BX_OBJS = \ instrument.o BX_INCLUDES = BX_INCDIRS = -I../.. -I$(srcdir)/../.. -I. -I$(srcdir)/. .@CPP_SUFFIX@.o: $(CXX) -c $(CXXFLAGS) $(BX_INCDIRS) @CXXFP@$< @OFP@$@ .c.o: $(CC) -c $(CFLAGS) $(BX_INCDIRS) @CFP@$< @OFP@$@ libinstrument.a: $(BX_OBJS) @RMCOMMAND@ libinstrument.a @MAKELIB@ $(BX_OBJS) $(RANLIB) libinstrument.a $(BX_OBJS): $(BX_INCLUDES) clean: @RMCOMMAND@ *.o @RMCOMMAND@ *.a dist-clean: clean @RMCOMMAND@ Makefile bochs-2.6/instrument/example0/instrument.cc0000644000175000017500000001450012020641474020777 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.cc 11295 2012-07-24 15:32:55Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include "bochs.h" #include "cpu/cpu.h" #include "disasm/disasm.h" // maximum size of an instruction #define MAX_OPCODE_LENGTH 16 // maximum physical addresses an instruction can generate #define MAX_DATA_ACCESSES 1024 // Use this variable to turn on/off collection of instrumentation data // If you are not using the debugger to turn this on/off, then possibly // start this at 1 instead of 0. static bx_bool active = 1; static disassembler bx_disassembler; static struct instruction_t { bx_bool ready; // is current instruction ready to be printed unsigned opcode_length; Bit8u opcode[MAX_OPCODE_LENGTH]; bx_bool is32, is64; unsigned num_data_accesses; struct { bx_address laddr; // linear address bx_phy_address paddr; // physical address unsigned rw; // BX_READ, BX_WRITE or BX_RW unsigned size; // 1 .. 32 } data_access[MAX_DATA_ACCESSES]; bx_bool is_branch; bx_bool is_taken; bx_address target_linear; } *instruction; static logfunctions *instrument_log = new logfunctions (); #define LOG_THIS instrument_log-> void bx_instr_init_env(void) {} void bx_instr_exit_env(void) {} void bx_instr_initialize(unsigned cpu) { assert(cpu < BX_SMP_PROCESSORS); if (instruction == NULL) instruction = new struct instruction_t[BX_SMP_PROCESSORS]; fprintf(stderr, "Initialize cpu %d\n", cpu); } void bx_instr_reset(unsigned cpu, unsigned type) { instruction[cpu].ready = 0; instruction[cpu].num_data_accesses = 0; instruction[cpu].is_branch = 0; } void bx_print_instruction(unsigned cpu, const instruction_t *i) { char disasm_tbuf[512]; // buffer for instruction disassembly unsigned length = i->opcode_length, n; bx_disassembler.disasm(i->is32, i->is64, 0, 0, i->opcode, disasm_tbuf); if(length != 0) { fprintf(stderr, "----------------------------------------------------------\n"); fprintf(stderr, "CPU: %d: %s\n", cpu, disasm_tbuf); fprintf(stderr, "LEN: %d\tBYTES: ", length); for(n=0;n < length;n++) fprintf(stderr, "%02x", i->opcode[n]); if(i->is_branch) { fprintf(stderr, "\tBRANCH "); if(i->is_taken) fprintf(stderr, "TARGET " FMT_ADDRX " (TAKEN)", i->target_linear); else fprintf(stderr, "(NOT TAKEN)"); } fprintf(stderr, "\n"); for(n=0;n < i->num_data_accesses;n++) { fprintf(stderr, "MEM ACCESS[%u]: 0x" FMT_ADDRX " (linear) 0x" FMT_PHY_ADDRX " (physical) %s SIZE: %d\n", n, i->data_access[n].laddr, i->data_access[n].paddr, i->data_access[n].rw == BX_READ ? "RD":"WR", i->data_access[n].size); } fprintf(stderr, "\n"); } } void bx_instr_before_execution(unsigned cpu, bxInstruction_c *bx_instr) { if (!active) return; instruction_t *i = &instruction[cpu]; if (i->ready) bx_print_instruction(cpu, i); // prepare instruction_t structure for new instruction i->ready = 1; i->num_data_accesses = 0; i->is_branch = 0; i->is32 = BX_CPU(cpu)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b; i->is64 = BX_CPU(cpu)->long64_mode(); i->opcode_length = bx_instr->ilen(); memcpy(i->opcode, bx_instr->get_opcode_bytes(), i->opcode_length); } void bx_instr_after_execution(unsigned cpu, bxInstruction_c *bx_instr) { if (!active) return; instruction_t *i = &instruction[cpu]; if (i->ready) { bx_print_instruction(cpu, i); i->ready = 0; } } static void branch_taken(unsigned cpu, bx_address new_eip) { if (!active || !instruction[cpu].ready) return; instruction[cpu].is_branch = 1; instruction[cpu].is_taken = 1; // find linear address instruction[cpu].target_linear = BX_CPU(cpu)->get_laddr(BX_SEG_REG_CS, new_eip); } void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip) { branch_taken(cpu, new_eip); } void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip) { if (!active || !instruction[cpu].ready) return; instruction[cpu].is_branch = 1; instruction[cpu].is_taken = 0; } void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip) { branch_taken(cpu, new_eip); } void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip) { branch_taken(cpu, new_eip); } void bx_instr_interrupt(unsigned cpu, unsigned vector) { if(active) { fprintf(stderr, "CPU %u: interrupt %02xh\n", cpu, vector); } } void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code) { if(active) { fprintf(stderr, "CPU %u: exception %02xh, error_code = %x\n", cpu, vector, error_code); } } void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip) { if(active) { fprintf(stderr, "CPU %u: hardware interrupt %02xh\n", cpu, vector); } } void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_phy_address phy, unsigned len, unsigned rw) { if(!active || !instruction[cpu].ready) return; unsigned index = instruction[cpu].num_data_accesses; if (index < MAX_DATA_ACCESSES) { instruction[cpu].data_access[index].laddr = lin; instruction[cpu].data_access[index].paddr = phy; instruction[cpu].data_access[index].rw = rw; instruction[cpu].data_access[index].size = len; instruction[cpu].num_data_accesses++; index++; } } bochs-2.6/instrument/example0/instrument.h0000644000175000017500000001437412020641474020652 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instrument.h 11295 2012-07-24 15:32:55Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if BX_INSTRUMENTATION class bxInstruction_c; // define if you want to store instruction opcode bytes in bxInstruction_c #define BX_INSTR_STORE_OPCODE_BYTES void bx_instr_init_env(void); void bx_instr_exit_env(void); // called from the CPU core void bx_instr_initialize(unsigned cpu); void bx_instr_reset(unsigned cpu, unsigned type); void bx_instr_cnear_branch_taken(unsigned cpu, bx_address branch_eip, bx_address new_eip); void bx_instr_cnear_branch_not_taken(unsigned cpu, bx_address branch_eip); void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address branch_eip, bx_address new_eip); void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip); void bx_instr_before_execution(unsigned cpu, bxInstruction_c *i); void bx_instr_after_execution(unsigned cpu, bxInstruction_c *i); void bx_instr_interrupt(unsigned cpu, unsigned vector); void bx_instr_exception(unsigned cpu, unsigned vector, unsigned error_code); void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip); void bx_instr_lin_access(unsigned cpu, bx_address lin, bx_phy_address phy, unsigned len, unsigned rw); /* initialization/deinitialization of instrumentalization*/ #define BX_INSTR_INIT_ENV() bx_instr_init_env() #define BX_INSTR_EXIT_ENV() bx_instr_exit_env() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) bx_instr_initialize(cpu_id) #define BX_INSTR_EXIT(cpu_id) #define BX_INSTR_RESET(cpu_id, type) bx_instr_reset(cpu_id, type) #define BX_INSTR_HLT(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() #define BX_INSTR_DEBUG_CMD(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) bx_instr_cnear_branch_taken(cpu_id, branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) bx_instr_cnear_branch_not_taken(cpu_id, branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) bx_instr_ucnear_branch(cpu_id, what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) bx_instr_far_branch(cpu_id, what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) \ bx_instr_exception(cpu_id, vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) bx_instr_before_execution(cpu_id, i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) bx_instr_after_execution(cpu_id, i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) /* memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) \ bx_instr_lin_access(cpu_id, lin, phy, len, rw) #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) #define BX_INSTR_INP2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) #else // BX_INSTRUMENTATION /* initialization/deinitialization of instrumentalization */ #define BX_INSTR_INIT_ENV() #define BX_INSTR_EXIT_ENV() /* simulation init, shutdown, reset */ #define BX_INSTR_INITIALIZE(cpu_id) #define BX_INSTR_EXIT(cpu_id) #define BX_INSTR_RESET(cpu_id, type) #define BX_INSTR_HLT(cpu_id) #define BX_INSTR_MWAIT(cpu_id, addr, len, flags) /* called from command line debugger */ #define BX_INSTR_DEBUG_PROMPT() #define BX_INSTR_DEBUG_CMD(cmd) /* branch resolution */ #define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, branch_eip, new_eip) #define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id, branch_eip) #define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, branch_eip, new_eip) #define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) /* decoding completed */ #define BX_INSTR_OPCODE(cpu_id, i, opcode, len, is32, is64) /* exceptional case and interrupt */ #define BX_INSTR_EXCEPTION(cpu_id, vector, error_code) #define BX_INSTR_INTERRUPT(cpu_id, vector) #define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) /* TLB/CACHE control instruction executed */ #define BX_INSTR_CLFLUSH(cpu_id, laddr, paddr) #define BX_INSTR_CACHE_CNTRL(cpu_id, what) #define BX_INSTR_TLB_CNTRL(cpu_id, what, new_cr3) #define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) /* execution */ #define BX_INSTR_BEFORE_EXECUTION(cpu_id, i) #define BX_INSTR_AFTER_EXECUTION(cpu_id, i) #define BX_INSTR_REPEAT_ITERATION(cpu_id, i) /* linear memory access */ #define BX_INSTR_LIN_ACCESS(cpu_id, lin, phy, len, rw) /* physical memory access */ #define BX_INSTR_PHY_ACCESS(cpu_id, phy, len, rw) /* feedback from device units */ #define BX_INSTR_INP(addr, len) #define BX_INSTR_INP2(addr, len, val) #define BX_INSTR_OUTP(addr, len, val) /* wrmsr callback */ #define BX_INSTR_WRMSR(cpu_id, addr, value) #endif // BX_INSTRUMENTATION bochs-2.6/plugin.cc0000644000175000017500000006502412020641507014146 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: plugin.cc 11141 2012-04-16 19:17:10Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // // This file defines the plugin and plugin-device registration functions and // the device registration functions. It handles dynamic loading of modules, // using the LTDL library for cross-platform support. // // This file is based on the plugin.c file from plex86, but with significant // changes to make it work in Bochs. // Plex86 is Copyright (C) 1999-2000 The plex86 developers team // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "iodev/iodev.h" #include "plugin.h" #define LOG_THIS genlog-> #define PLUGIN_INIT_FMT_STRING "lib%s_LTX_plugin_init" #define PLUGIN_FINI_FMT_STRING "lib%s_LTX_plugin_fini" #define PLUGIN_PATH "" #ifndef WIN32 #define PLUGIN_FILENAME_FORMAT "libbx_%s.so" #else #define PLUGIN_FILENAME_FORMAT "bx_%s.dll" #endif extern "C" { void (*pluginRegisterIRQ)(unsigned irq, const char* name) = 0; void (*pluginUnregisterIRQ)(unsigned irq, const char* name) = 0; void (*pluginSetHRQ)(unsigned val) = 0; void (*pluginSetHRQHackCallback)(void (*callback)(void)) = 0; int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback, unsigned base, const char *name, Bit8u mask) = 0; int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, unsigned base, const char *name, Bit8u mask) = 0; int (*pluginUnregisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback, unsigned base, Bit8u mask) = 0; int (*pluginUnregisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, unsigned base, Bit8u mask) = 0; int (*pluginRegisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback, unsigned base, unsigned end, const char *name, Bit8u mask) = 0; int (*pluginRegisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback, unsigned base, unsigned end, const char *name, Bit8u mask) = 0; int (*pluginUnregisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback, unsigned begin, unsigned end, Bit8u mask) = 0; int (*pluginUnregisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback, unsigned begin, unsigned end, Bit8u mask) = 0; int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback, const char *name, Bit8u mask) = 0; int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, const char *name, Bit8u mask) = 0; int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *), Bit32u useconds, bx_bool continuous, bx_bool active, const char* name) = 0; void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous) = 0; void (*pluginHRQHackCallback)(void); unsigned pluginHRQ = 0; plugin_t *plugins = NULL; /* Head of the linked list of plugins */ #if BX_PLUGINS static void plugin_init_one(plugin_t *plugin); #endif device_t *devices = NULL; /* Head of the linked list of registered devices */ device_t *core_devices = NULL; /* Head of the linked list of registered core devices */ plugin_t *current_plugin_context = NULL; /************************************************************************/ /* Builtins declarations */ /************************************************************************/ static void builtinRegisterIRQ(unsigned irq, const char* name) { #if 0 pluginlog->panic("builtinRegisterIRQ called, no pic plugin loaded?"); #else bx_devices.register_irq(irq, name); #endif } static void builtinUnregisterIRQ(unsigned irq, const char* name) { #if 0 pluginlog->panic("builtinUnregisterIRQ called, no pic plugin loaded?"); #else bx_devices.unregister_irq(irq, name); #endif } static void builtinSetHRQ(unsigned val) { #if 0 pluginlog->panic("builtinSetHRQ called, no plugin loaded?"); #else pluginHRQ = val; #endif } static void builtinSetHRQHackCallback(void (*callback)(void)) { #if 0 pluginlog->panic("builtinSetHRQHackCallback called, no plugin loaded?"); #else pluginHRQHackCallback = callback; #endif } static int builtinRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback, unsigned base, const char *name, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.register_io_read_handler (thisPtr, callback, base, name, mask); pluginlog->ldebug("plugin %s registered I/O read address at %04x", name, base); return ret; } static int builtinRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback, unsigned base, const char *name, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.register_io_write_handler (thisPtr, callback, base, name, mask); pluginlog->ldebug("plugin %s registered I/O write address at %04x", name, base); return ret; } static int builtinUnregisterIOReadHandler(void *thisPtr, ioReadHandler_t callback, unsigned base, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.unregister_io_read_handler (thisPtr, callback, base, mask); pluginlog->ldebug("plugin unregistered I/O read address at %04x", base); return ret; } static int builtinUnregisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback, unsigned base, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.unregister_io_write_handler (thisPtr, callback, base, mask); pluginlog->ldebug("plugin unregistered I/O write address at %04x", base); return ret; } static int builtinRegisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback, unsigned base, unsigned end, const char *name, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.register_io_read_handler_range (thisPtr, callback, base, end, name, mask); pluginlog->ldebug("plugin %s registered I/O read addresses %04x to %04x", name, base, end); return ret; } static int builtinRegisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback, unsigned base, unsigned end, const char *name, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.register_io_write_handler_range (thisPtr, callback, base, end, name, mask); pluginlog->ldebug("plugin %s registered I/O write addresses %04x to %04x", name, base, end); return ret; } static int builtinUnregisterIOReadHandlerRange(void *thisPtr, ioReadHandler_t callback, unsigned begin, unsigned end, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.unregister_io_read_handler_range (thisPtr, callback, begin, end, mask); pluginlog->ldebug("plugin unregistered I/O read addresses %04x to %04x", begin, end); return ret; } static int builtinUnregisterIOWriteHandlerRange(void *thisPtr, ioWriteHandler_t callback, unsigned begin, unsigned end, Bit8u mask) { int ret; BX_ASSERT(mask<8); ret = bx_devices.unregister_io_write_handler_range (thisPtr, callback, begin, end, mask); pluginlog->ldebug("plugin unregistered I/O write addresses %04x to %04x", begin, end); return ret; } static int builtinRegisterDefaultIOReadHandler(void *thisPtr, ioReadHandler_t callback, const char *name, Bit8u mask) { BX_ASSERT(mask<8); bx_devices.register_default_io_read_handler (thisPtr, callback, name, mask); pluginlog->ldebug("plugin %s registered default I/O read ", name); return 0; } static int builtinRegisterDefaultIOWriteHandler(void *thisPtr, ioWriteHandler_t callback, const char *name, Bit8u mask) { BX_ASSERT(mask<8); bx_devices.register_default_io_write_handler (thisPtr, callback, name, mask); pluginlog->ldebug("plugin %s registered default I/O write ", name); return 0; } static int builtinRegisterTimer(void *this_ptr, void (*funct)(void *), Bit32u useconds, bx_bool continuous, bx_bool active, const char* name) { int id = bx_pc_system.register_timer (this_ptr, funct, useconds, continuous, active, name); pluginlog->ldebug("plugin %s registered timer %d", name, id); return id; } static void builtinActivateTimer(unsigned id, Bit32u usec, bx_bool continuous) { bx_pc_system.activate_timer (id, usec, continuous); pluginlog->ldebug("plugin activated timer %d", id); } #if BX_PLUGINS /************************************************************************/ /* Plugin initialization / deinitialization */ /************************************************************************/ void plugin_init_all (void) { plugin_t *plugin; pluginlog->info("Initializing plugins"); for (plugin = plugins; plugin; plugin = plugin->next) { char *arg_ptr = plugin->args; /* process the command line */ plugin->argc = 0; while (plugin->argc < MAX_ARGC) { while (*arg_ptr && isspace (*arg_ptr)) arg_ptr++; if (!*arg_ptr) break; plugin->argv[plugin->argc++] = arg_ptr; while (*arg_ptr && !isspace (*arg_ptr)) arg_ptr++; if (!*arg_ptr) break; *arg_ptr++ = '\0'; } /* initialize the plugin */ if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv)) { pluginlog->panic("Plugin initialization failed for %s", plugin->name); plugin_abort(); } plugin->initialized = 1; } } void plugin_init_one(plugin_t *plugin) { char *arg_ptr = plugin->args; /* process the command line */ plugin->argc = 0; while (plugin->argc < MAX_ARGC) { while (*arg_ptr && isspace (*arg_ptr)) arg_ptr++; if (!*arg_ptr) break; plugin->argv[plugin->argc++] = arg_ptr; while (*arg_ptr && !isspace (*arg_ptr)) arg_ptr++; if (!*arg_ptr) break; *arg_ptr++ = '\0'; } /* initialize the plugin */ if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv)) { pluginlog->info("Plugin initialization failed for %s", plugin->name); plugin_abort(); } plugin->initialized = 1; } plugin_t *plugin_unload(plugin_t *plugin) { plugin_t *dead_plug; if (plugin->initialized) plugin->plugin_fini(); #if defined(_MSC_VER) FreeLibrary(plugin->handle); #else lt_dlclose(plugin->handle); #endif delete [] plugin->name; dead_plug = plugin; plugin = plugin->next; free(dead_plug); return plugin; } void plugin_fini_all (void) { plugin_t *plugin; for (plugin = plugins; plugin; plugin = plugin_unload(plugin)); } void plugin_load(char *name, char *args, plugintype_t type) { plugin_t *plugin, *temp; if (plugins != NULL) { temp = plugins; while (temp != NULL) { if (!strcmp(name, temp->name)) { BX_PANIC(("plugin '%s' already loaded", name)); return; } temp = temp->next; } } plugin = (plugin_t *)malloc (sizeof(plugin_t)); if (!plugin) { BX_PANIC(("malloc plugin_t failed")); } plugin->type = type; plugin->name = name; plugin->args = args; plugin->initialized = 0; char plugin_filename[BX_PATHNAME_LEN], buf[BX_PATHNAME_LEN]; sprintf(buf, PLUGIN_FILENAME_FORMAT, name); sprintf(plugin_filename, "%s%s", PLUGIN_PATH, buf); // Set context so that any devices that the plugin registers will // be able to see which plugin created them. The registration will // be called from either dlopen (global constructors) or plugin_init. BX_ASSERT(current_plugin_context == NULL); current_plugin_context = plugin; #if defined(_MSC_VER) plugin->handle = LoadLibrary(plugin_filename); BX_INFO(("DLL handle is %p", plugin->handle)); if (!plugin->handle) { current_plugin_context = NULL; BX_PANIC(("LoadLibrary failed for module '%s': error=%d", name, GetLastError())); free(plugin); return; } #else plugin->handle = lt_dlopen (plugin_filename); BX_INFO(("lt_dlhandle is %p", plugin->handle)); if (!plugin->handle) { current_plugin_context = NULL; BX_PANIC(("dlopen failed for module '%s': %s", name, lt_dlerror ())); free(plugin); return; } #endif if (type != PLUGTYPE_USER) { sprintf(buf, PLUGIN_INIT_FMT_STRING, name); } else { sprintf(buf, PLUGIN_INIT_FMT_STRING, "user"); } #if defined(_MSC_VER) plugin->plugin_init = (plugin_init_t) GetProcAddress(plugin->handle, buf); if (plugin->plugin_init == NULL) { pluginlog->panic("could not find plugin_init: error=%d", GetLastError()); plugin_abort (); } #else plugin->plugin_init = (plugin_init_t) lt_dlsym (plugin->handle, buf); if (plugin->plugin_init == NULL) { pluginlog->panic("could not find plugin_init: %s", lt_dlerror ()); plugin_abort (); } #endif if (type != PLUGTYPE_USER) { sprintf(buf, PLUGIN_FINI_FMT_STRING, name); } else { sprintf(buf, PLUGIN_FINI_FMT_STRING, "user"); } #if defined(_MSC_VER) plugin->plugin_fini = (plugin_fini_t) GetProcAddress(plugin->handle, buf); if (plugin->plugin_fini == NULL) { pluginlog->panic("could not find plugin_fini: error=%d", GetLastError()); plugin_abort (); } #else plugin->plugin_fini = (plugin_fini_t) lt_dlsym (plugin->handle, buf); if (plugin->plugin_fini == NULL) { pluginlog->panic("could not find plugin_fini: %s", lt_dlerror ()); plugin_abort(); } #endif pluginlog->info("loaded plugin %s",plugin_filename); /* Insert plugin at the _end_ of the plugin linked list. */ plugin->next = NULL; if (!plugins) { /* Empty list, this become the first entry. */ plugins = plugin; } else { /* Non-empty list. Add to end. */ temp = plugins; while (temp->next) temp = temp->next; temp->next = plugin; } plugin_init_one(plugin); // check that context didn't change. This should only happen if we // need a reentrant plugin_load. BX_ASSERT(current_plugin_context == plugin); current_plugin_context = NULL; } void plugin_abort(void) { pluginlog->panic("plugin load aborted"); } #endif /* end of #if BX_PLUGINS */ /************************************************************************/ /* Plugin system: initialisation of plugins entry points */ /************************************************************************/ void plugin_startup(void) { pluginRegisterIRQ = builtinRegisterIRQ; pluginUnregisterIRQ = builtinUnregisterIRQ; pluginSetHRQHackCallback = builtinSetHRQHackCallback; pluginSetHRQ = builtinSetHRQ; pluginRegisterIOReadHandler = builtinRegisterIOReadHandler; pluginRegisterIOWriteHandler = builtinRegisterIOWriteHandler; pluginUnregisterIOReadHandler = builtinUnregisterIOReadHandler; pluginUnregisterIOWriteHandler = builtinUnregisterIOWriteHandler; pluginRegisterIOReadHandlerRange = builtinRegisterIOReadHandlerRange; pluginRegisterIOWriteHandlerRange = builtinRegisterIOWriteHandlerRange; pluginUnregisterIOReadHandlerRange = builtinUnregisterIOReadHandlerRange; pluginUnregisterIOWriteHandlerRange = builtinUnregisterIOWriteHandlerRange; pluginRegisterDefaultIOReadHandler = builtinRegisterDefaultIOReadHandler; pluginRegisterDefaultIOWriteHandler = builtinRegisterDefaultIOWriteHandler; pluginRegisterTimer = builtinRegisterTimer; pluginActivateTimer = builtinActivateTimer; #if BX_PLUGINS pluginlog = new logfunctions(); pluginlog->put("PLGIN"); #if !defined(_MSC_VER) int status = lt_dlinit (); if (status != 0) { BX_ERROR (("initialization error in ltdl library (for loading plugins)")); BX_PANIC (("error message was: %s", lt_dlerror ())); } #endif #endif } /************************************************************************/ /* Plugin system: Device registration */ /************************************************************************/ void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *devmodel, const char *name) { device_t *device, **devlist; device = (device_t *)malloc (sizeof (device_t)); if (!device) { pluginlog->panic("can't allocate device_t"); } device->name = name; BX_ASSERT(devmodel != NULL); device->devmodel = devmodel; device->plugin = plugin; // this can be NULL device->next = NULL; device->plugtype = type; switch (type) { case PLUGTYPE_CORE: devlist = &core_devices; break; case PLUGTYPE_STANDARD: case PLUGTYPE_OPTIONAL: case PLUGTYPE_USER: default: devlist = &devices; break; } if (!*devlist) { /* Empty list, this become the first entry. */ *devlist = device; } else { /* Non-empty list. Add to end. */ device_t *temp = *devlist; while (temp->next) temp = temp->next; temp->next = device; } } /************************************************************************/ /* Plugin system: Remove registered plugin device */ /************************************************************************/ void pluginUnregisterDeviceDevmodel(const char *name) { device_t *device, *prev = NULL; for (device = devices; device; device = device->next) { if (!strcmp(name, device->name)) { if (prev == NULL) { devices = device->next; } else { prev->next = device->next; } free(device); break; } else { prev = device; } } } /************************************************************************/ /* Plugin system: Check if a plugin is loaded */ /************************************************************************/ bx_bool pluginDevicePresent(const char *name) { device_t *device; for (device = devices; device; device = device->next) { if (!strcmp(name, device->name)) return 1; } return 0; } #if BX_PLUGINS /************************************************************************/ /* Plugin system: Load one plugin */ /************************************************************************/ int bx_load_plugin(const char *name, plugintype_t type) { char *namecopy = new char[1+strlen(name)]; strcpy(namecopy, name); plugin_load(namecopy, (char*)"", type); return 1; } void bx_unload_plugin(const char *name, bx_bool devflag) { plugin_t *plugin, *prev = NULL; for (plugin = plugins; plugin; plugin = plugin->next) { if (!strcmp(plugin->name, name)) { if (devflag) { pluginUnregisterDeviceDevmodel(plugin->name); } plugin = plugin_unload(plugin); if (prev == NULL) { plugins = plugin; } else { prev->next = plugin; } break; } else { prev = plugin; } } } #endif /* end of #if BX_PLUGINS */ /*************************************************************************/ /* Plugin system: Execute init function of all registered plugin-devices */ /*************************************************************************/ void bx_init_plugins() { device_t *device; for (device = core_devices; device; device = device->next) { pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name); device->devmodel->init(); } for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_STANDARD) { pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name); device->devmodel->init(); } } for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_OPTIONAL) { pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name); device->devmodel->init(); } } #if BX_PLUGINS for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_USER) { pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name); device->devmodel->init(); } } #endif } /**************************************************************************/ /* Plugin system: Execute reset function of all registered plugin-devices */ /**************************************************************************/ void bx_reset_plugins(unsigned signal) { device_t *device; for (device = core_devices; device; device = device->next) { pluginlog->info("reset of '%s' plugin device by virtual method",device->name); device->devmodel->reset(signal); } for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_STANDARD) { pluginlog->info("reset of '%s' plugin device by virtual method",device->name); device->devmodel->reset(signal); } } for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_OPTIONAL) { pluginlog->info("reset of '%s' plugin device by virtual method",device->name); device->devmodel->reset(signal); } } #if BX_PLUGINS for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_USER) { pluginlog->info("reset of '%s' plugin device by virtual method",device->name); device->devmodel->reset(signal); } } #endif } /*******************************************************/ /* Plugin system: Unload all registered plugin-devices */ /*******************************************************/ void bx_unload_plugins() { device_t *device, *next; device = devices; while (device != NULL) { if (device->plugin != NULL) { #if BX_PLUGINS bx_unload_plugin(device->name, 0); #endif } else { #if !BX_PLUGINS if (!bx_unload_opt_plugin(device->name, 0)) { delete device->devmodel; } #endif } next = device->next; free(device); device = next; } devices = NULL; } void bx_unload_core_plugins() { device_t *device, *next; device = core_devices; while (device != NULL) { if (device->plugin != NULL) { #if BX_PLUGINS bx_unload_plugin(device->name, 0); #endif } else { delete device->devmodel; } next = device->next; free(device); device = next; } core_devices = NULL; } /**************************************************************************/ /* Plugin system: Register device state of all registered plugin-devices */ /**************************************************************************/ void bx_plugins_register_state() { device_t *device; for (device = core_devices; device; device = device->next) { pluginlog->info("register state of '%s' plugin device by virtual method",device->name); device->devmodel->register_state(); } for (device = devices; device; device = device->next) { pluginlog->info("register state of '%s' plugin device by virtual method",device->name); device->devmodel->register_state(); } } /***************************************************************************/ /* Plugin system: Execute code after restoring state of all plugin devices */ /***************************************************************************/ void bx_plugins_after_restore_state() { device_t *device; for (device = core_devices; device; device = device->next) { device->devmodel->after_restore_state(); } for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_STANDARD) { device->devmodel->after_restore_state(); } } for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_OPTIONAL) { device->devmodel->after_restore_state(); } } #if BX_PLUGINS for (device = devices; device; device = device->next) { if (device->plugtype == PLUGTYPE_USER) { device->devmodel->after_restore_state(); } } #endif } #if !BX_PLUGINS // special code for loading optional plugins when plugins are turned off typedef struct { const char *name; plugin_init_t plugin_init; plugin_fini_t plugin_fini; bx_bool status; } builtin_plugin_t; #define BUILTIN_PLUGIN_ENTRY(mod) {#mod, lib##mod##_LTX_plugin_init, lib##mod##_LTX_plugin_fini, 0} static builtin_plugin_t builtin_opt_plugins[] = { BUILTIN_PLUGIN_ENTRY(unmapped), BUILTIN_PLUGIN_ENTRY(biosdev), BUILTIN_PLUGIN_ENTRY(speaker), BUILTIN_PLUGIN_ENTRY(extfpuirq), BUILTIN_PLUGIN_ENTRY(parallel), BUILTIN_PLUGIN_ENTRY(serial), #if BX_SUPPORT_E1000 BUILTIN_PLUGIN_ENTRY(e1000), #endif #if BX_SUPPORT_ES1370 BUILTIN_PLUGIN_ENTRY(es1370), #endif #if BX_SUPPORT_GAMEPORT BUILTIN_PLUGIN_ENTRY(gameport), #endif #if BX_SUPPORT_IODEBUG BUILTIN_PLUGIN_ENTRY(iodebug), #endif #if BX_SUPPORT_NE2K BUILTIN_PLUGIN_ENTRY(ne2k), #endif #if BX_SUPPORT_PCIDEV BUILTIN_PLUGIN_ENTRY(pcidev), #endif #if BX_SUPPORT_PCIPNIC BUILTIN_PLUGIN_ENTRY(pcipnic), #endif #if BX_SUPPORT_SB16 BUILTIN_PLUGIN_ENTRY(sb16), #endif #if BX_SUPPORT_USB_OHCI BUILTIN_PLUGIN_ENTRY(usb_ohci), #endif #if BX_SUPPORT_USB_UHCI BUILTIN_PLUGIN_ENTRY(usb_uhci), #endif #if BX_SUPPORT_USB_XHCI BUILTIN_PLUGIN_ENTRY(usb_xhci), #endif {"NULL", NULL, NULL, 0} }; int bx_load_opt_plugin(const char *name) { int i = 0; while (strcmp(builtin_opt_plugins[i].name, "NULL")) { if (!strcmp(name, builtin_opt_plugins[i].name)) { if (builtin_opt_plugins[i].status == 0) { builtin_opt_plugins[i].plugin_init(NULL, PLUGTYPE_OPTIONAL, 0, NULL); builtin_opt_plugins[i].status = 1; } return 1; } i++; }; return 0; } int bx_unload_opt_plugin(const char *name, bx_bool devflag) { int i = 0; while (strcmp(builtin_opt_plugins[i].name, "NULL")) { if (!strcmp(name, builtin_opt_plugins[i].name)) { if (builtin_opt_plugins[i].status == 1) { if (devflag) { pluginUnregisterDeviceDevmodel(builtin_opt_plugins[i].name); } builtin_opt_plugins[i].plugin_fini(); builtin_opt_plugins[i].status = 0; } return 1; } i++; }; return 0; } #endif } bochs-2.6/ltdl.h0000644000175000017500000003042312020641507013444 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ltdl.h 10209 2011-02-24 22:05:47Z sshwarts $ // // NOTE: The ltdl library comes from the Libtool package. Bochs uses // ltdl and libtool to build and load plugins. The libtool // documentation describes how to copy ltdl.c and ltdl.h into your // distribution, so it is clearly legal to do so. ///////////////////////////////////////////////////////////////////////// /* ltdl.h -- generic dlopen functions Copyright (C) 1998-2000 Free Software Foundation, Inc. Originally by Thomas Tanner This file is part of GNU Libtool. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. As a special exception to the GNU Lesser General Public License, if you distribute this file as part of a program or library that is built using GNU libtool, you may include it under the same distribution terms that you use for the rest of that program. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* Only include this header file once. */ #ifndef LTDL_H #define LTDL_H 1 #ifdef __cplusplus extern "C" { #endif #include /* for size_t declaration */ #ifdef __cplusplus }; #endif /* --- MACROS FOR PORTABILITY --- */ /* Saves on those hard to debug '\0' typos.... */ #define LT_EOS_CHAR '\0' /* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations, so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at the end of C declarations. */ #ifdef __cplusplus # define LT_BEGIN_C_DECLS extern "C" { # define LT_END_C_DECLS } #else # define LT_BEGIN_C_DECLS /* empty */ # define LT_END_C_DECLS /* empty */ #endif LT_BEGIN_C_DECLS /* LT_PARAMS is a macro used to wrap function prototypes, so that compilers that don't understand ANSI C prototypes still work, and ANSI C compilers can issue warnings about type mismatches. */ #if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus) # define LT_PARAMS(protos) protos # define lt_ptr void* #else # define LT_PARAMS(protos) () # define lt_ptr char* #endif /* LT_STMT_START/END are used to create macros which expand to a a single compound statement in a portable way. */ #if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus) # define LT_STMT_START (void)( # define LT_STMT_END ) #else # if (defined (sun) || defined (__sun__)) # define LT_STMT_START if (1) # define LT_STMT_END else (void)0 # else # define LT_STMT_START do # define LT_STMT_END while (0) # endif #endif /* LT_CONC creates a new concatenated symbol for the compiler in a portable way. */ #if defined(__STDC__) || defined(__cplusplus) # define LT_CONC(s,t) s##t #else # define LT_CONC(s,t) s/**/t #endif /* LT_STRLEN can be used safely on NULL pointers. */ #define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0) /* --- WINDOWS SUPPORT --- */ /* Canonicalise Windows and Cygwin recognition macros. */ #ifdef __CYGWIN32__ # ifndef __CYGWIN__ # define __CYGWIN__ __CYGWIN32__ # endif #endif #if defined(_WIN32) || defined(WIN32) # ifndef __WINDOWS__ # ifdef _WIN32 # define __WINDOWS__ _WIN32 # else # ifdef WIN32 # define __WINDOWS__ WIN32 # endif # endif # endif #endif #ifdef __WINDOWS__ # ifndef __CYGWIN__ /* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory separator when it is set. */ # define LT_DIRSEP_CHAR '\\' # define LT_PATHSEP_CHAR ';' # endif #endif #ifndef LT_PATHSEP_CHAR # define LT_PATHSEP_CHAR ':' #endif /* DLL building support on win32 hosts; mostly to workaround their ridiculous implementation of data symbol exporting. */ #ifndef LT_SCOPE # ifdef __WINDOWS__ # ifdef DLL_EXPORT /* defined by libtool (if required) */ # define LT_SCOPE __declspec(dllexport) # endif # ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */ # define LT_SCOPE extern __declspec(dllimport) # endif # endif # ifndef LT_SCOPE /* static linking or !__WINDOWS__ */ # define LT_SCOPE extern # endif #endif /* --- DYNAMIC MODULE LOADING API --- */ typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */ /* Initialisation and finalisation functions for libltdl. */ extern int lt_dlinit LT_PARAMS((void)); extern int lt_dlexit LT_PARAMS((void)); /* Module search path manipulation. */ extern int lt_dladdsearchdir LT_PARAMS((const char *search_dir)); extern int lt_dlinsertsearchdir LT_PARAMS((const char *before, const char *search_dir)); extern int lt_dlsetsearchpath LT_PARAMS((const char *search_path)); extern const char *lt_dlgetsearchpath LT_PARAMS((void)); extern int lt_dlforeachfile LT_PARAMS(( const char *search_path, int (*func) (const char *filename, lt_ptr data), lt_ptr data)); /* Portable libltdl versions of the system dlopen() API. */ extern lt_dlhandle lt_dlopen LT_PARAMS((const char *filename)); extern lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename)); extern lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle, const char *name)); extern const char *lt_dlerror LT_PARAMS((void)); extern int lt_dlclose LT_PARAMS((lt_dlhandle handle)); /* Module residency management. */ extern int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle)); extern int lt_dlisresident LT_PARAMS((lt_dlhandle handle)); /* --- MUTEX LOCKING --- */ typedef void lt_dlmutex_lock LT_PARAMS((void)); typedef void lt_dlmutex_unlock LT_PARAMS((void)); typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg)); typedef const char *lt_dlmutex_geterror LT_PARAMS((void)); extern int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock, lt_dlmutex_unlock *unlock, lt_dlmutex_seterror *seterror, lt_dlmutex_geterror *geterror)); /* --- MEMORY HANDLING --- */ /* By default, the realloc function pointer is set to our internal realloc implementation which iself uses lt_dlmalloc and lt_dlfree. libltdl relies on a featureful realloc, but if you are sure yours has the right semantics then you can assign it directly. Generally, it is safe to assign just a malloc() and a free() function. */ LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size)); LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size)); LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr)); /* --- PRELOADED MODULE SUPPORT --- */ /* A preopened symbol. Arrays of this type comprise the exported symbols for a dlpreopened module. */ typedef struct { const char *name; lt_ptr address; } lt_dlsymlist; extern int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded)); extern int lt_dlpreload_default LT_PARAMS((const lt_dlsymlist *preloaded)); #define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \ extern const lt_dlsymlist lt_preloaded_symbols[]; \ lt_dlpreload_default(lt_preloaded_symbols); \ }LT_STMT_END /* --- MODULE INFORMATION --- */ /* Read only information pertaining to a loaded module. */ typedef struct { char *filename; /* file name */ char *name; /* module name */ int ref_count; /* number of times lt_dlopened minus number of times lt_dlclosed. */ } lt_dlinfo; extern const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle)); extern lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place)); extern int lt_dlforeach LT_PARAMS(( int (*func) (lt_dlhandle handle, lt_ptr data), lt_ptr data)); /* Associating user data with loaded modules. */ typedef unsigned lt_dlcaller_id; extern lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void)); extern lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key, lt_dlhandle handle, lt_ptr data)); extern lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key, lt_dlhandle handle)); /* --- USER MODULE LOADER API --- */ typedef struct lt_dlloader lt_dlloader; typedef lt_ptr lt_user_data; typedef lt_ptr lt_module; /* Function pointer types for creating user defined module loaders. */ typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data, const char *filename)); typedef int lt_module_close LT_PARAMS((lt_user_data loader_data, lt_module handle)); typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data, lt_module handle, const char *symbol)); typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data)); struct lt_user_dlloader { const char *sym_prefix; lt_module_open *module_open; lt_module_close *module_close; lt_find_sym *find_sym; lt_dlloader_exit *dlloader_exit; lt_user_data dlloader_data; }; extern lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place)); extern lt_dlloader *lt_dlloader_find LT_PARAMS(( const char *loader_name)); extern const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place)); extern lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place)); extern int lt_dlloader_add LT_PARAMS((lt_dlloader *place, const struct lt_user_dlloader *dlloader, const char *loader_name)); extern int lt_dlloader_remove LT_PARAMS(( const char *loader_name)); /* --- ERROR MESSAGE HANDLING --- */ /* Bryce rewrote the error table in a way that would be likely to work on all compilers. VC++ was not able to handle it the way it was done originally. */ /* ORIG COMMENT: Defining error strings alongside their symbolic names in a macro in this way allows us to expand the macro in different contexts with confidence that the enumeration of symbolic names will map correctly onto the table of error strings. */ #define lt_dlerror_symbols_list \ LT_ERROR_UNKNOWN, \ LT_ERROR_DLOPEN_NOT_SUPPORTED, \ LT_ERROR_INVALID_LOADER, \ LT_ERROR_INIT_LOADER, \ LT_ERROR_REMOVE_LOADER, \ LT_ERROR_FILE_NOT_FOUND, \ LT_ERROR_DEPLIB_NOT_FOUND, \ LT_ERROR_NO_SYMBOLS, \ LT_ERROR_CANNOT_OPEN, \ LT_ERROR_CANNOT_CLOSE, \ LT_ERROR_SYMBOL_NOT_FOUND, \ LT_ERROR_NO_MEMORY, \ LT_ERROR_INVALID_HANDLE, \ LT_ERROR_BUFFER_OVERFLOW, \ LT_ERROR_INVALID_ERRORCODE, \ LT_ERROR_SHUTDOWN, \ LT_ERROR_CLOSE_RESIDENT_MODULE, \ LT_ERROR_INVALID_MUTEX_ARGS, \ LT_ERROR_INVALID_POSITION, #define lt_dlerror_names_list \ "unknown error", \ "dlopen support not available", \ "invalid loader", \ "loader initialization failed", \ "loader removal failed", \ "file not found", \ "dependency library not found", \ "no symbols defined", \ "can't open the module", \ "can't close the module", \ "symbol not found", \ "not enough memory", \ "invalid module handle", \ "internal buffer overflow", \ "invalid errorcode", \ "library already shutdown", \ "can't close resident module", \ "invalid mutex handler registration", \ "invalid search path insert position", /* Enumerate the symbolic error names. */ enum { lt_dlerror_symbols_list LT_ERROR_MAX }; /* These functions are only useful from inside custom module loaders. */ extern int lt_dladderror LT_PARAMS((const char *diagnostic)); extern int lt_dlseterror LT_PARAMS((int errorcode)); /* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */ #ifdef LT_NON_POSIX_NAMESPACE # define lt_ptr_t lt_ptr # define lt_module_t lt_module # define lt_module_open_t lt_module_open # define lt_module_close_t lt_module_close # define lt_find_sym_t lt_find_sym # define lt_dlloader_exit_t lt_dlloader_exit # define lt_dlloader_t lt_dlloader # define lt_dlloader_data_t lt_user_data #endif LT_END_C_DECLS #endif /* !LTDL_H */ bochs-2.6/misc/0000755000175000017500000000000012020641466013271 5ustar guillemguillembochs-2.6/misc/spoolpipe.c0000644000175000017500000001411112020641466015445 0ustar guillemguillem/* $Id: spoolpipe.c 10209 2011-02-24 22:05:47Z sshwarts $ * * spoolpipe.c * by Carl Sopchak * * Read a pipe that stays open, send the data to a temp file. Print * the temp file if no new input data is seen within a period of time. This * is useful, e.g., to create separate spool files without exiting a program * that doesn't close it's printer output file. * * --------------------------------------------------------------------------- * * Copyright (c) 2002 Cegis Enterprises, Inc. Syracuse, NY 13215 * * --------------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * -------------------------------------------------------------------------- * Modification log: * * 2002/05/20 - Initial programming * * -------------------------------------------------------------------------- */ #define BUF_SIZE 4*1024 #define DEBUG 0 #include #include #include #include #include #include #include #include int infd, outfd; unsigned int delay = 60; // default delay, in seconds unsigned int count_down = 0; char buffer[BUF_SIZE]; ssize_t readcnt, writecnt; int didwait = 0; // have we already waited? int havedata = 0; // have we read anything in? int q; pid_t pid, wait_pid; int wait_status; int main (int argc, char *argv[]) { #if DEBUG printf("Command line arguments (%d):\n", argc); for (q = 0; q < argc ; q++) { printf(" %d = %s\n", q, argv[q]); } #endif if ((argc < 3) || (argc > 4)) { printf("usage: %s []\n", argv[0]); exit(1); } if (argc == 4) { // get delay delay = strtol(argv[3], (char **) NULL, 10); if (delay < 0) { printf("Unable to convert maximum delay value: %s\n", argv[3]); exit(2); } } // get delay #if DEBUG printf("Delay is set to %d seconds.\n", delay); #endif infd = open(argv[1], O_RDONLY | O_NONBLOCK); if (infd == -1) { printf("Error opening input pipe %s: %d - %s\n", argv[1], errno, strerror(errno)); exit(3); } outfd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, S_IRWXU); if (outfd == -1) { printf("Error opening output file %s: %d - %s\n", argv[2], errno, strerror(errno)); exit(4); } count_down = delay; while (1) { // must kill with a signal.... readcnt = read(infd, buffer, (size_t) BUF_SIZE); #if DEBUG printf("read() returned with readcnt = %d, errno = %d\n", readcnt, errno); #endif if ((readcnt == -1) && (errno != EAGAIN)) { // EAGAIN - no data waiting, can ignore printf("Error reading input pipe: %d - %s\n", errno, strerror(errno)); exit(5); } else { // no errors reading input pipe if (readcnt > 0) { writecnt = write(outfd, buffer, readcnt); if (writecnt == -1) { printf("Error writing output file: %d - %s\n", errno, strerror(errno)); exit(6); } didwait = 0; // reset wait flag (wait again) count_down = delay; havedata = 1; // set flag that we got some data } else { //readcnt must = 0 if (!didwait) { //have not waited yet... if (count_down > 0) { // sleep a bit sleep(1); count_down -= 1; } else { didwait = 1; // set wait flag (don't wait again) } } else { // already waited if (havedata) { // have data to print, close & reopen output file if (close(outfd) != 0) { printf("Error closing output file: %d - %s\n", errno, strerror(errno)); exit(7); } #if DEBUG printf("Spooling temp file...\n"); #endif pid = fork(); if (pid == -1) { printf("Error forking new process: %d - %s\n", errno, strerror(errno)); exit(9); } if (pid == 0) { // we're now running in the child process... execlp("lpr", "lpr", argv[2], NULL); exit(99); // should never get here... } // we're now running in the child process... if (pid > 0) { // we're running in the parent process... wait_pid = waitpid(pid, (int *)&wait_status, 0); if (wait_pid != pid) { // some sort of error printf("Wait for 'lpr' command returned abnormally!\n"); if (WIFEXITED(wait_status)) { printf(" 'lpr' exited normally.\n"); } else { printf(" 'lpr' exited abnormally, return code = %d.\n", WEXITSTATUS(wait_status)); } if (WIFSIGNALED(wait_status)) { printf(" 'lpr' received uncaught signal %d\n", WTERMSIG(wait_status)); } } // some sort of error } // we're running in the parent process... outfd = open(argv[2], O_RDWR | O_TRUNC); if (outfd == -1) { printf("Error re-opening output file: %d - %s\n", errno, strerror(errno)); exit(8); } } // have data to print, close & repoen output file. havedata = 0; // no more data waiting count_down = delay; didwait = 0; // reset wait flag (wait again) } // already waited } // readcnt must = 0 } // no errors reading input pipe } // must kill with a signal... exit(0); } // eof(spoolpipe.c) bochs-2.6/misc/niclist.c0000644000175000017500000001240712020641466015106 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // // misc/niclist.c // by Don Becker // $Id: niclist.c 10409 2011-06-19 05:37:30Z vruppert $ // // This program is for win32 only. It lists the network interface cards // that you can use in the "ethdev" field of the ne2k line in your bochsrc. // // For this program and for win32 ethernet, the winpcap library is required. // Download it from http://www.winpcap.org/ // ///////////////////////////////////////////////////////////////////////// #ifndef WIN32 #error Niclist will only work on WIN32 platforms. #endif #include #include #include #include #if defined(_MSC_VER) #define getch _getch #endif #define MAX_ADAPTERS 10 #define NIC_BUFFER_SIZE 2048 // declare our NT/9X structures to hold the adapter name and descriptions typedef struct { LPWSTR wstrName; LPSTR strDesc; } NIC_INFO_NT; typedef struct { LPSTR strName; LPSTR strDesc; } NIC_INFO_9X; // declare an array of structures to hold our adapter information NIC_INFO_NT niNT[MAX_ADAPTERS]; NIC_INFO_9X ni9X[MAX_ADAPTERS]; BOOLEAN (*PacketGetAdapterNames)(PTSTR, PULONG) = NULL; PCHAR (*PacketGetVersion)() = NULL; void myexit (int code) { printf ("\nPress any key to continue\n"); getch(); exit(code); } int CDECL main(int argc, char **argv) { int i; HINSTANCE hPacket; DWORD dwVersion, dwMajorVersion; char AdapterInfo[NIC_BUFFER_SIZE] = { '\0','\0' }; unsigned long AdapterLength = NIC_BUFFER_SIZE; LPWSTR wstrName; LPSTR strName, strDesc; int nAdapterCount; PCHAR dllVersion; PCHAR testString; int nDLLMajorVersion, nDLLMinorVersion; // Attemp to load the WinpCap packet library hPacket = LoadLibrary("PACKET.DLL"); if(hPacket) { // Now look up the address PacketGetAdapterNames = (BOOLEAN (*)(PTSTR, PULONG))GetProcAddress(hPacket, "PacketGetAdapterNames"); PacketGetVersion = (PCHAR (*)())GetProcAddress(hPacket, "PacketGetVersion"); } else { printf("Could not load WinPCap driver!\n"); printf ("You can download them for free from\n"); printf ("http://www.winpcap.org/\n"); myexit(1); } dwVersion = GetVersion(); dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); // Get DLL Version and Tokenize dllVersion = PacketGetVersion(); nDLLMajorVersion = -1; nDLLMinorVersion = -1; for (testString = strtok(dllVersion, ",. "); testString != NULL; testString = strtok(NULL, ",. ")) { // If Single Character, Convert if (strlen( testString ) == 1) { // Check Major First if (nDLLMajorVersion == -1) { nDLLMajorVersion = atoi(testString); } else if ( nDLLMinorVersion == -1 ) { nDLLMinorVersion = atoi(testString); } } } // Get out blob of adapter info PacketGetAdapterNames(AdapterInfo,&AdapterLength); // If this is Windows NT ... And DLL Returns UNICODE if(!(dwVersion >= 0x80000000 && dwMajorVersion >= 4) && (nDLLMajorVersion < 3 || (nDLLMajorVersion == 3 && nDLLMinorVersion < 1))) { wstrName=(LPWSTR)AdapterInfo; // Obtain Names nAdapterCount = 0; while ((*wstrName)) { // store pointer to name niNT[nAdapterCount].wstrName=wstrName; wstrName += lstrlenW(wstrName) +1; nAdapterCount++; } strDesc = (LPSTR)++wstrName; // Obtain descriptions .... for(i=0;i // rule1 is the original rule used in Bochs from 2000-03-25. It has bad // overflow problems. int rule1 (Bit32u limit, Bit32u length, Bit32u offset); // rule2 is Bryce's first try, which turned out to have bad underflow problems // instead. int rule2 (Bit32u limit, Bit32u length, Bit32u offset); // rule3 is Bryce's second try, which as far as he knows works for all // cases. int rule3 (Bit32u limit, Bit32u length, Bit32u offset); // edit this to test other rules. #define TEST_RULE rule3 typedef struct { Bit32u limit, length, offset, the_answer; } TestStruct; TestStruct tests[] = { // limit length offset exception {0x0a, 4, 0, 0}, {0x0a, 4, 1, 0}, {0x0a, 4, 2, 0}, {0x0a, 4, 3, 0}, {0x0a, 4, 4, 0}, {0x0a, 4, 5, 0}, {0x0a, 4, 6, 0}, {0x0a, 4, 7, 0}, {0x0a, 4, 8, 1}, {0x0a, 4, 9, 1}, {0x0a, 4, 0x0a, 1}, {0x0a, 4, 0x0b, 1}, {0x0a, 4, 0x0c, 1}, {0x0a, 4, 0xfffffffd, 1}, {0x0a, 4, 0xfffffffe, 1}, {0x0a, 4, 0xffffffff, 1}, {0x0a, 2, 0, 0}, {0x0a, 2, 1, 0}, {0x0a, 2, 2, 0}, {0x0a, 2, 3, 0}, {0x0a, 2, 4, 0}, {0x0a, 2, 5, 0}, {0x0a, 2, 6, 0}, {0x0a, 2, 7, 0}, {0x0a, 2, 8, 0}, {0x0a, 2, 9, 0}, {0x0a, 2, 0x0a, 1}, {0x0a, 2, 0x0b, 1}, {0x0a, 2, 0x0c, 1}, {0x0a, 2, 0xfffffffd, 1}, {0x0a, 2, 0xfffffffe, 1}, {0x0a, 2, 0xffffffff, 1}, {0x0a, 1, 0, 0}, {0x0a, 1, 1, 0}, {0x0a, 1, 2, 0}, {0x0a, 1, 3, 0}, {0x0a, 1, 4, 0}, {0x0a, 1, 5, 0}, {0x0a, 1, 6, 0}, {0x0a, 1, 7, 0}, {0x0a, 1, 8, 0}, {0x0a, 1, 9, 0}, {0x0a, 1, 0x0a, 0}, {0x0a, 1, 0x0b, 1}, {0x0a, 1, 0x0c, 1}, // // try a few near the common 0xffff boundary // {0xffff, 1, 0, 0}, {0xffff, 1, 0x100, 0}, {0xffff, 1, 0x1000, 0}, {0xffff, 1, 0x8000, 0}, {0xffff, 1, 0xf000, 0}, {0xffff, 1, 0xfff0, 0}, {0xffff, 1, 0xfff1, 0}, {0xffff, 1, 0xfff2, 0}, {0xffff, 1, 0xfff3, 0}, {0xffff, 1, 0xfff4, 0}, {0xffff, 1, 0xfff5, 0}, {0xffff, 1, 0xfff6, 0}, {0xffff, 1, 0xfff7, 0}, {0xffff, 1, 0xfff8, 0}, {0xffff, 1, 0xfff9, 0}, {0xffff, 1, 0xfffa, 0}, {0xffff, 1, 0xfffb, 0}, {0xffff, 1, 0xfffc, 0}, {0xffff, 1, 0xfffd, 0}, {0xffff, 1, 0xfffe, 0}, {0xffff, 1, 0xffff, 0}, {0xffff, 1, 0x10000, 1}, {0xffff, 1, 0x10001, 1}, {0xffff, 1, 0x10002, 1}, {0xffff, 1, 0x10021, 1}, {0xffff, 1, 0x40001, 1}, {0xffff, 1, 0xffffffff, 1}, // // near 0xffff, length 2 // {0xffff, 2, 0, 0}, {0xffff, 2, 0x100, 0}, {0xffff, 2, 0x1000, 0}, {0xffff, 2, 0x8000, 0}, {0xffff, 2, 0xf000, 0}, {0xffff, 2, 0xfff0, 0}, {0xffff, 2, 0xfff1, 0}, {0xffff, 2, 0xfff2, 0}, {0xffff, 2, 0xfff3, 0}, {0xffff, 2, 0xfff4, 0}, {0xffff, 2, 0xfff5, 0}, {0xffff, 2, 0xfff6, 0}, {0xffff, 2, 0xfff7, 0}, {0xffff, 2, 0xfff8, 0}, {0xffff, 2, 0xfff9, 0}, {0xffff, 2, 0xfffa, 0}, {0xffff, 2, 0xfffb, 0}, {0xffff, 2, 0xfffc, 0}, {0xffff, 2, 0xfffd, 0}, {0xffff, 2, 0xfffe, 0}, {0xffff, 2, 0xffff, 1}, {0xffff, 2, 0x10000, 1}, {0xffff, 2, 0x10001, 1}, {0xffff, 2, 0x10002, 1}, {0xffff, 2, 0x10021, 1}, {0xffff, 2, 0x40001, 1}, {0xffff, 2, 0xffffffff, 1}, // // near 0xffff, length 4 // {0xffff, 4, 0, 0}, {0xffff, 4, 0x100, 0}, {0xffff, 4, 0x1000, 0}, {0xffff, 4, 0x8000, 0}, {0xffff, 4, 0xf000, 0}, {0xffff, 4, 0xfff0, 0}, {0xffff, 4, 0xfff1, 0}, {0xffff, 4, 0xfff2, 0}, {0xffff, 4, 0xfff3, 0}, {0xffff, 4, 0xfff4, 0}, {0xffff, 4, 0xfff5, 0}, {0xffff, 4, 0xfff6, 0}, {0xffff, 4, 0xfff7, 0}, {0xffff, 4, 0xfff8, 0}, {0xffff, 4, 0xfff9, 0}, {0xffff, 4, 0xfffa, 0}, {0xffff, 4, 0xfffb, 0}, {0xffff, 4, 0xfffc, 0}, {0xffff, 4, 0xfffd, 1}, {0xffff, 4, 0xfffe, 1}, {0xffff, 4, 0xffff, 1}, {0xffff, 4, 0x10000, 1}, {0xffff, 4, 0x10001, 1}, {0xffff, 4, 0x10002, 1}, {0xffff, 4, 0x10021, 1}, {0xffff, 4, 0x40001, 1}, {0xffff, 4, 0xffffffff, 1}, // // now a few near the max limit 0xffffffff // {0xffffffff, 1, 0, 0}, {0xffffffff, 1, 0x100, 0}, {0xffffffff, 1, 0x1000, 0}, {0xffffffff, 1, 0x8000, 0}, {0xffffffff, 1, 0xf000, 0}, {0xffffffff, 1, 0xfff0, 0}, {0xffffffff, 1, 0xfff1, 0}, {0xffffffff, 1, 0xfff2, 0}, {0xffffffff, 1, 0xfff3, 0}, {0xffffffff, 1, 0xfff4, 0}, {0xffffffff, 1, 0xfff5, 0}, {0xffffffff, 1, 0xfff6, 0}, {0xffffffff, 1, 0xfff7, 0}, {0xffffffff, 1, 0xfff8, 0}, {0xffffffff, 1, 0xfff9, 0}, {0xffffffff, 1, 0xfffa, 0}, {0xffffffff, 1, 0xfffb, 0}, {0xffffffff, 1, 0xfffc, 0}, {0xffffffff, 1, 0xfffd, 0}, {0xffffffff, 1, 0xfffe, 0}, {0xffffffff, 1, 0xffff, 0}, {0xffffffff, 1, 0x10000, 0}, {0xffffffff, 1, 0x10001, 0}, {0xffffffff, 1, 0x10002, 0}, {0xffffffff, 1, 0x10021, 0}, {0xffffffff, 1, 0x40001, 0}, {0xffffffff, 1, 0xfffffff0, 0}, {0xffffffff, 1, 0xfffffff9, 0}, {0xffffffff, 1, 0xfffffffa, 0}, {0xffffffff, 1, 0xfffffffb, 0}, {0xffffffff, 1, 0xfffffffc, 0}, {0xffffffff, 1, 0xfffffffd, 0}, {0xffffffff, 1, 0xfffffffe, 0}, {0xffffffff, 1, 0xffffffff, 0}, {0xffffffff, 1, 0x00000000, 0}, {0xffffffff, 1, 0x00000001, 0}, {0xffffffff, 1, 0x00000002, 0}, {0xffffffff, 1, 0x00000003, 0}, {0xffffffff, 1, 0x00000004, 0}, {0xffffffff, 1, 0x00000005, 0}, // // repeat with length 2 // {0xffffffff, 2, 0, 0}, {0xffffffff, 2, 0x100, 0}, {0xffffffff, 2, 0x1000, 0}, {0xffffffff, 2, 0x8000, 0}, {0xffffffff, 2, 0xf000, 0}, {0xffffffff, 2, 0xfff0, 0}, {0xffffffff, 2, 0xfff1, 0}, {0xffffffff, 2, 0xfff2, 0}, {0xffffffff, 2, 0xfff3, 0}, {0xffffffff, 2, 0xfff4, 0}, {0xffffffff, 2, 0xfff5, 0}, {0xffffffff, 2, 0xfff6, 0}, {0xffffffff, 2, 0xfff7, 0}, {0xffffffff, 2, 0xfff8, 0}, {0xffffffff, 2, 0xfff9, 0}, {0xffffffff, 2, 0xfffa, 0}, {0xffffffff, 2, 0xfffb, 0}, {0xffffffff, 2, 0xfffc, 0}, {0xffffffff, 2, 0xfffd, 0}, {0xffffffff, 2, 0xfffe, 0}, {0xffffffff, 2, 0xffff, 0}, {0xffffffff, 2, 0x10000, 0}, {0xffffffff, 2, 0x10001, 0}, {0xffffffff, 2, 0x10002, 0}, {0xffffffff, 2, 0x10021, 0}, {0xffffffff, 2, 0x40001, 0}, {0xffffffff, 2, 0xfffffff0, 0}, {0xffffffff, 2, 0xfffffff9, 0}, {0xffffffff, 2, 0xfffffffa, 0}, {0xffffffff, 2, 0xfffffffb, 0}, {0xffffffff, 2, 0xfffffffc, 0}, {0xffffffff, 2, 0xfffffffd, 0}, {0xffffffff, 2, 0xfffffffe, 0}, {0xffffffff, 2, 0xffffffff, 1}, {0xffffffff, 2, 0x00000000, 0}, {0xffffffff, 2, 0x00000001, 0}, {0xffffffff, 2, 0x00000002, 0}, {0xffffffff, 2, 0x00000003, 0}, {0xffffffff, 2, 0x00000004, 0}, {0xffffffff, 2, 0x00000005, 0}, // // repeat with length 4 // {0xffffffff, 4, 0, 0}, {0xffffffff, 4, 0x100, 0}, {0xffffffff, 4, 0x1000, 0}, {0xffffffff, 4, 0x8000, 0}, {0xffffffff, 4, 0xf000, 0}, {0xffffffff, 4, 0xfff0, 0}, {0xffffffff, 4, 0xfff1, 0}, {0xffffffff, 4, 0xfff2, 0}, {0xffffffff, 4, 0xfff3, 0}, {0xffffffff, 4, 0xfff4, 0}, {0xffffffff, 4, 0xfff5, 0}, {0xffffffff, 4, 0xfff6, 0}, {0xffffffff, 4, 0xfff7, 0}, {0xffffffff, 4, 0xfff8, 0}, {0xffffffff, 4, 0xfff9, 0}, {0xffffffff, 4, 0xfffa, 0}, {0xffffffff, 4, 0xfffb, 0}, {0xffffffff, 4, 0xfffc, 0}, {0xffffffff, 4, 0xfffd, 0}, {0xffffffff, 4, 0xfffe, 0}, {0xffffffff, 4, 0xffff, 0}, {0xffffffff, 4, 0x10000, 0}, {0xffffffff, 4, 0x10001, 0}, {0xffffffff, 4, 0x10002, 0}, {0xffffffff, 4, 0x10021, 0}, {0xffffffff, 4, 0x40001, 0}, {0xffffffff, 4, 0xfffffff0, 0}, {0xffffffff, 4, 0xfffffff9, 0}, {0xffffffff, 4, 0xfffffffa, 0}, {0xffffffff, 4, 0xfffffffb, 0}, {0xffffffff, 4, 0xfffffffc, 0}, {0xffffffff, 4, 0xfffffffd, 1}, {0xffffffff, 4, 0xfffffffe, 1}, {0xffffffff, 4, 0xffffffff, 1}, {0xffffffff, 4, 0x00000000, 0}, {0xffffffff, 4, 0x00000001, 0}, {0xffffffff, 4, 0x00000002, 0}, {0xffffffff, 4, 0x00000003, 0}, {0xffffffff, 4, 0x00000004, 0}, {0xffffffff, 4, 0x00000005, 0}, // // now make some underflow cases to disprove my new rule // {1, 1, 0, 0}, {1, 1, 1, 0}, {1, 1, 2, 1}, {1, 1, 3, 1}, {1, 1, 4, 1}, {1, 1, 0xfffffffc, 1}, {1, 1, 0xfffffffd, 1}, {1, 1, 0xfffffffe, 1}, {1, 1, 0xffffffff, 1}, {1, 2, 0, 0}, {1, 2, 1, 1}, {1, 2, 2, 1}, {1, 2, 3, 1}, {1, 2, 4, 1}, {1, 2, 0xfffffffc, 1}, {1, 2, 0xfffffffd, 1}, {1, 2, 0xfffffffe, 1}, {1, 2, 0xffffffff, 1}, {1, 4, 0, 1}, {1, 4, 1, 1}, {1, 4, 2, 1}, {1, 4, 3, 1}, {1, 4, 4, 1}, {1, 4, 0xfffffffc, 1}, {1, 4, 0xfffffffd, 1}, {1, 4, 0xfffffffe, 1}, {1, 4, 0xffffffff, 1} }; int main () { int total=0, mismatches=0; int t; for (t=0; tlimit, ts->length, ts->offset); printf ("limit=%x len=%x offset=%x exception=%x %s\n", ts->limit, ts->length, ts->offset, my_answer, (ts->the_answer==my_answer) ? "" : "MISMATCH"); if (ts->the_answer!=my_answer) mismatches++; total++; } printf ("mismatches=%d\n", mismatches); printf ("total=%d\n", total); } int rule1 (Bit32u limit, Bit32u length, Bit32u offset) { if ((offset + length - 1) > limit) return 1; return 0; } int rule2 (Bit32u limit, Bit32u length, Bit32u offset) { if (offset > (limit - length + 1)) return 1; return 0; } int rule3 (Bit32u limit, Bit32u length, Bit32u offset) { if (offset > (limit - length + 1) || (length-1 > limit)) { return 1; } return 0; } bochs-2.6/misc/Makefile.in0000644000175000017500000000250312020641466015336 0ustar guillemguillem# Copyright (C) 2001 MandrakeSoft S.A. # # MandrakeSoft S.A. # 43, rue d'Aboukir # 75002 Paris - France # http://www.linux-mandrake.com/ # http://www.mandrakesoft.com/ # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA @SUFFIX_LINE@ SHELL = @SHELL@ @SET_MAKE@ CC = @CC@ CXX = @CXX@ CFLAGS = @CFLAGS@ @GUI_CFLAGS@ CXXFLAGS = @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(CXXFLAGS) @CXXFP@$< @OFP@$@ all: make_cmos_image make_cmos_image@EXE@: make_cmos_image.o @LINK@ make_cmos_image.o clean: @RMCOMMAND@ *.o @RMCOMMAND@ make_cmos_image@EXE@ dist-clean: clean @RMCOMMAND@ Makefile bochs-2.6/misc/sb16/0000755000175000017500000000000012077504622014050 5ustar guillemguillembochs-2.6/misc/sb16/sb16ctrl.c0000644000175000017500000002323412020641466015654 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: sb16ctrl.c,v 1.7 2009-02-08 09:05:52 vruppert Exp $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // This file (SB16CTRL.C) written and donated by Josef Drexler // The purpose of this program is to provide runtime configuration // options to the SB16 Emulator until Bochs has a more sophisticated // user interface allowing to do these things better. #include #include #include #include #ifdef dos # include #endif #if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) # include # include # define inp inb # define outp(a,b) outb(b,a) #endif /* #define DEBUG */ #define EMULPORT 0x333 int checked = 0; int filelevel = 0; int verbose = 0; char ofline[256] = " in the command line"; /****************************** * System dependent functions * ******************************/ /* Read a value from the emulator port */ int reademul() { return inp(EMULPORT); } /* Write a value to the emulator port */ void writeemul(int value) { outp(EMULPORT, value); } /* Enable access to the emulator port */ void enableport() { #if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) if (ioperm(EMULPORT, 1, 1)) { printf("Could not access emulator port %03x: %s.\n", EMULPORT, strerror(errno)); exit(1); } #endif } /******************************** * System independent functions * ********************************/ /* Forward definitions*/ void command(int cmd, char *arg); void checkemulator(); /* Convert a string into a number */ int strtoi(char *nptr, char **endptr, int base) { int value, digit; int sign = 1; /* Skip leading white space */ while( isspace(*nptr) ) nptr++; /* Check if there is a sign */ if (*nptr == '-') { sign = -1; nptr++; } else if (*nptr == '+') { sign = 1; nptr++; } /* Check the base if undefined and determine it */ if (base == 0) { if (*nptr == '0') { nptr++; if ( (*nptr == 'x') || (*nptr == 'X') ) { nptr++; base = 16; } else base = 8; } else base = 10; } /* Convert the number */ value = 0; digit = -1; while ( isalnum(*nptr) ) { if ( isdigit(*nptr) ) digit = *nptr - '0'; else digit = tolower(*nptr) - 'a' + 10; if ( (digit >= base) || (digit < 0) ) break; /* Isn't a valid char, abort conversion */ value = value * base + digit; nptr++; } if (endptr != NULL) *endptr = nptr; return sign * value; } /* Print the command line usage */ void usage() { printf("SB16 emulator control program for Bochs.\n" "\n" "Usage: sb16ctrl [-i #] [-t #,#,#,#,#,#] [-r] [-m #,..] [-f filename]\n" "\n" "This program is used to control the operation of the SB16 emulator\n" "until it has a more sophisticated interface.\n" "Any number of commands can be given. If none are present \"-f -\"\n" "is assumed.\n" "\n" "-i # show the selected emulator info string\n" "-t #,#,#,#,#,# load the patch translation into the emulator\n" "-r resets the patch translation table\n" "-m #,... sends the given midi message (up to 255 bytes)\n" "-f filename loads commands from the given file, or stdin if \"-\"\n" "-v be verbose\n" "\n" "# can be decimal, octal (first digit 0) or hexadecimal (0x..)\n" "\n" ); } /* Execute the given command */ void emulcommand(int command) { if (checked == 0) checkemulator(); writeemul(command); } /* Check if we got the expected response */ int testemul(int value, char *msg) { int i; if (checked == 0) checkemulator(); i = reademul(); #ifndef DEBUG if ( (i != value) && (msg) ) { printf("Bochs emulator/SB16 error: %s\n", msg); exit(1); } #endif return i; } /* Check if we are running inside the emulator */ void checkemulator() { int i; checked = 1; enableport(); /* Check emulator status */ for (i=0; i<9; i++) writeemul(1); /* Clear input queue */ writeemul(10); /* Check Emulator present */ testemul(254, "no check ACK: Emulator not present"); testemul(0x55, "Emulator not present"); /* should return 0x55 */ } /* Read internal emulator string and print it */ void showemul(int i) { int j; emulcommand(5); /* 5 means dump info */ writeemul(i); /* Argument to command 5; info number */ testemul(254, "no info ACK"); printf("Emulator info string %d:", i); do { j = reademul(); if (j == 255) break; printf("%c", j); } while (j != 10); } /* Process a string - change "," and "/" into a space, and ignore everything after comments "#" */ void procstr(char *str) { int i; for (i=0; str[i] != 0; i++) switch(str[i]) { case ',': case '/': case 10: case 13: str[i] = ' '; break; case '#': str[i] = 0; str[i+1] = 0; break; } } /* Upload a mapping to the emulator */ void loadmap(char *map) { int i; int trans[6]; char *nextnum; procstr(map); nextnum = map; for (i=0;i<6;i++) { if (nextnum) { trans[i] = strtoi(nextnum, &nextnum, 0); if ( (!nextnum) || ( (trans[i] > 127) && (trans[i] < 255) ) || (trans[i] > 255) ) printf("Parse error in value %d%s. Command ignored.", i, ofline); } if (!nextnum) trans[i] = 255; } /* Load the remap into the emulator, command 4 */ emulcommand(4); /* 4 load remap */ testemul(254, "no load remap ACK"); for (i=0;i<6;i++) writeemul(trans[i]); testemul(6, "insufficient data"); /* test receipt of 6 arguments */ } /* Reset the translation table */ void resettable() { emulcommand(7); testemul(254, "no table reset ACK"); } /* Send a series of midi bytes to the sound device */ void loadmidi(char *msg) { int i; procstr(msg); while ( (msg) && (*msg) ) { i = strtoi(msg, &msg, 0); emulcommand(11); /* 11: Send midi data byte */ writeemul(i); testemul(254, "no midi data ACK"); } } /* read a file of commands */ void loadfile(char *filename) { FILE *file; char cmd; char *pos; char msg[256]; int lineno = 0; filelevel++; if (filelevel > 10) { printf("Error - Too many nested \"f\" commands.\n"); exit(1); } if (strcmp(filename, "-") == 0) file = stdin; else file = fopen(filename, "r"); if (!file) { printf("File %s not found.\n", filename); return; } while (!feof(file)) { fgets(msg, sizeof msg, file); lineno++; pos = msg; procstr(msg); while ( (*pos == ' ') || (*pos == 9) ) pos++; if (*pos) cmd = *pos++; else continue; if (cmd == '#') /* it's a comment */ continue; while ( (*pos == ' ') || (*pos == 9) ) pos++; sprintf(ofline, " in line %d of file %s", lineno, filename); command(cmd, pos); } if (strcmp(filename, "-") != 0) fclose(file); filelevel--; } void command(int cmd, char *arg) { if (verbose) { if (arg) printf("Executing command %c %s%s\n", cmd, arg, ofline); else printf("Executing command %c %s\n", cmd, ofline); } switch (cmd) { case 't': loadmap(arg); break; case 'i': showemul(strtoi(arg, NULL, 0)); break; case 'm': loadmidi(arg); break; case 'f': loadfile(arg); break; case 'h': usage(); break; case 'r': resettable(); break; default: printf("Command %c %s not recognized.\n", cmd, ofline); break; } } int main(int argc, char **argv) { int i, opt, optargnum; char *optarg; /* No args given, read from stdin */ if (argc < 2) { loadfile("-"); return 0; } /* Check command line*/ i = 1; while (i < argc) { if ( (argv[i][0] != '/') && (argv[i][0] != '-') ) { printf("Unknown command '%s'.\n" "sb16ctrl -h gives a list of command line options.\n", argv[i]); return 1; } optargnum = -1; opt = argv[i++][1]; switch (opt) { case 'h': usage(); return 0; case 'v': verbose++; break; case 'r': optargnum = 0; case 't': case 'i': case 'm': case 'f': if (optargnum == -1) optargnum = 1; /* Fallthrough for all commands to here */ if (optargnum > 0) { if ( (i >= argc) || (argv[i][0] == '-') || (argv[i][0] == '/') ) { printf("Option '%c' needs an argument.\n" "sb16ctrl -h gives a list of command line options.\n", opt); return 1; } optarg = argv[i++]; } else optarg = NULL; command(opt, optarg); break; default: printf("Unknown option '%c'.\n" "sb16ctrl -h gives a list of command line options.\n", opt); return 1; } } return 0; } bochs-2.6/misc/sb16/sb16ctrl.example0000644000175000017500000000202212020641466017055 0ustar guillemguillem# # example for an sb16ctrl file # # comments start with hash character '#' (obviously...) # Numbers can be octal (0...) or hex (0x...) or decimal. # # # first, reset the translation table with command 'r' r # then load a few translations. # The format is: # t OldBankMSB OldBankLSB OldProgram NewBankMSB NewBankLSB NewProgram # # All values are in the range of 0-127 or 255. # For old values, 255 means "match any". # For new values, 255 means "don't change". # # When deciding whether a program change is to be remapped, these # remappings are checked first to last, and the first applicable remap # is used. # This would map all bank changes to bank 0/0 # t 255 255 255 0 0 255 # it's commented out, otherwise none of the below changes would # be checked, as this one matches anything. t 255 255 0 0 0 19 # remap piano to church organ t 255 255 255 0 0 0 # everything remaining -> piano # now show the number of translations that have been loaded i 3 # and enable GS/GM mode m 0xF0,0x41,0x10,0x42,0x12,0x40,0x00,0x7F,0x00,0x41,0xF7 bochs-2.6/misc/bxcommit.c0000644000175000017500000003356412020641466015272 0ustar guillemguillem/* * misc/bximage.c * $Id: bxcommit.c 11315 2012-08-05 18:13:38Z vruppert $ * * Commits a redolog file in a flat file for bochs images. * */ #include #include #include #ifndef _MSC_VER #include #else #include #endif #include #include #include #include #include #ifdef WIN32 # include #endif #include "config.h" #include #if !BX_HAVE_SNPRINTF #include /* XXX use real snprintf */ /* if they don't have snprintf, just use sprintf */ int snprintf(char *s, size_t maxlen, const char *format, ...) { va_list arg; int done; va_start(arg, format); done = vsprintf(s, format, arg); va_end(arg); return done; } #endif /* !BX_HAVE_SNPRINTF */ #include "../osdep.h" #include "bswap.h" #define HDIMAGE_HEADERS_ONLY 1 #include "../iodev/hdimage/hdimage.h" #define BXCOMMIT_MODE_COMMIT_UNDOABLE 1 #define BXCOMMIT_MODE_GROWING_TO_FLAT 2 int bxcommit_mode; int bx_remove; int bx_interactive; char bx_flat_filename[256]; char bx_redolog_name[256]; char *EOF_ERR = "ERROR: End of input"; char *svnid = "$Id: bxcommit.c 11315 2012-08-05 18:13:38Z vruppert $"; char *divider = "========================================================================"; const char *main_menu_prompt = "\n" "1. Commit 'undoable' redolog to 'flat' file\n" "2. Create 'flat' disk image from 'growing' disk image\n" "\n" "0. Quit\n" "\n" "Please choose one "; void myexit(int code) { #ifdef WIN32 printf("\nPress any key to continue\n"); getch(); #endif exit(code); } /* stolen from main.cc */ void bx_center_print(FILE *file, char *line, int maxwidth) { int imax; int i; imax = (maxwidth - strlen(line)) >> 1; for (i=0; imax) { printf("Your choice (%s) was not an integer between %d and %d.\n\n", clean, min, max); } else { // choice is okay *out = n; return 0; } } } int ask_menu(const char *prompt, int n_choices, char *choice[], int the_default, int *out) { char buffer[1024]; char *clean; int i; *out = -1; while (1) { printf("%s", prompt); printf("[%s] ", choice[the_default]); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default *out = the_default; return 0; } for (i=0; i0) printf(", "); printf("%s", choice[i]); } printf("\n"); } } int ask_yn(const char *prompt, int the_default, int *out) { char buffer[16]; char *clean; *out = -1; while (1) { printf("%s", prompt); printf("[%s] ", the_default?"yes":"no"); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default *out = the_default; return 0; } switch (tolower(clean[0])) { case 'y': *out=1; return 0; case 'n': *out=0; return 0; } printf("Please type either yes or no.\n"); } } int ask_string(const char *prompt, char *the_default, char *out) { char buffer[1024]; char *clean; printf("%s", prompt); printf("[%s] ", the_default); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default strcpy(out, the_default); return 0; } strcpy(out, clean); return 0; } /* produce the image file */ int commit_redolog() { int flatfd = -1, redologfd; redolog_header_t header; Bit32u *catalog, catalog_size; Bit8u *bitmap; Bit32u i, bitmap_blocks, extent_blocks; Bit8u buffer[512]; if (bxcommit_mode == BXCOMMIT_MODE_COMMIT_UNDOABLE) { // check if flat file exists flatfd = open(bx_flat_filename, O_WRONLY #ifdef O_BINARY | O_BINARY #endif ); if (flatfd < 0) { fatal("ERROR: flat file not found or not writable"); } } // Check if redolog exists printf("\nOpening '%s'\n", bx_redolog_name); redologfd = open(bx_redolog_name, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (redologfd < 0) { fatal("ERROR: redolog file not found"); } printf ("\nReading redolog header: ["); if (read(redologfd, &header, STANDARD_HEADER_SIZE) != STANDARD_HEADER_SIZE) fatal("\nERROR: while reading redolog header!"); // Print infos on redlog printf("Type='%s', Subtype='%s', Version=%d.%d] Done.", header.standard.type, header.standard.subtype, dtoh32(header.standard.version)/0x10000, dtoh32(header.standard.version)%0x10000); printf("\nChecking redolog header: ["); if (strcmp((char *)header.standard.magic, STANDARD_HEADER_MAGIC) != 0) fatal("\nERROR: bad magic in redolog header!"); if (strcmp((char *)header.standard.type, REDOLOG_TYPE) != 0) fatal("\nERROR: bad type in redolog header!"); if (bxcommit_mode == BXCOMMIT_MODE_COMMIT_UNDOABLE) { if (strcmp((char *)header.standard.subtype, REDOLOG_SUBTYPE_UNDOABLE) != 0) fatal("\nERROR: bad subtype in redolog header!"); } else if (bxcommit_mode == BXCOMMIT_MODE_GROWING_TO_FLAT) { if (strcmp((char *)header.standard.subtype, REDOLOG_SUBTYPE_GROWING) != 0) fatal("\nERROR: bad subtype in redolog header!"); } else { fatal("\nERROR: unknown bxcommit mode!"); } if (header.standard.version != htod32(STANDARD_HEADER_VERSION)) fatal("\nERROR: bad version in redolog header!"); printf("#entries=%d, bitmap size=%d, exent size = %d] Done.", dtoh32(header.specific.catalog), dtoh32(header.specific.bitmap), dtoh32(header.specific.extent)); if (bxcommit_mode == BXCOMMIT_MODE_GROWING_TO_FLAT) { flatfd = open(bx_flat_filename, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (flatfd >= 0) { close(flatfd); fatal("ERROR: flat file already exists"); } printf("\nCreating flat image file: ["); flatfd = open(bx_flat_filename, O_WRONLY | O_CREAT #ifdef O_BINARY | O_BINARY #endif , S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP ); if (flatfd < 0) { fatal("ERROR: flat file is not writable"); } lseek(flatfd, dtoh64(header.specific.disk) - 512, SEEK_SET); if (write(flatfd, buffer, 512) != 512) fatal("ERROR: while writing block in flat file !"); printf("...] Done."); } catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u)); bitmap = (Bit8u*)malloc(dtoh32(header.specific.bitmap)); printf("\nReading Catalog: ["); lseek(redologfd, dtoh32(header.standard.header), SEEK_SET); catalog_size = dtoh32(header.specific.catalog) * sizeof(Bit32u); if ((Bit32u) read(redologfd, catalog, catalog_size) != catalog_size) fatal("\nERROR: while reading redolog catalog!"); printf("...] Done."); printf("\nCommitting changes to flat file: [ 0%%]"); bitmap_blocks = 1 + (dtoh32(header.specific.bitmap) - 1) / 512; extent_blocks = 1 + (dtoh32(header.specific.extent) - 1) / 512; for(i=0; i # include # include #ifdef _MSC_VER # include #endif #endif #include #include #include #include #include #include "config.h" #include #include "../osdep.h" #include "bswap.h" #define HDIMAGE_HEADERS_ONLY 1 #include "../iodev/hdimage/hdimage.h" #define BX_MAX_CYL_BITS 24 // 8 TB const int bx_max_hd_megs = (int)(((1 << BX_MAX_CYL_BITS) - 1) * 16.0 * 63.0 / 2048.0); int bx_hdimage; int bx_fdsize_idx; int bx_hdsize; int bx_hdimagemode; int bx_interactive; char bx_filename[256]; typedef int (*WRITE_IMAGE)(FILE*, Bit64u); #ifdef WIN32 typedef int (*WRITE_IMAGE_WIN32)(HANDLE, Bit64u); #endif char *EOF_ERR = "ERROR: End of input"; char *rcsid = "$Id: bximage.c 11315 2012-08-05 18:13:38Z vruppert $"; char *divider = "========================================================================"; /* menu data for choosing floppy/hard disk */ char *fdhd_menu = "\nDo you want to create a floppy disk image or a hard disk image?\nPlease type hd or fd. "; char *fdhd_choices[] = { "fd", "hd" }; int fdhd_n_choices = 2; /* menu data for choosing floppy size */ char *fdsize_menu = "\nChoose the size of floppy disk image to create, in megabytes.\nPlease type 0.16, 0.18, 0.32, 0.36, 0.72, 1.2, 1.44, 1.68, 1.72, or 2.88.\n "; char *fdsize_choices[] = { "0.16","0.18","0.32","0.36","0.72","1.2","1.44","1.68","1.72","2.88" }; int fdsize_n_choices = 10; /* menu data for choosing disk mode */ char *hdmode_menu = "\nWhat kind of image should I create?\nPlease type flat, sparse or growing. "; char *hdmode_choices[] = {"flat", "sparse", "growing" }; int hdmode_n_choices = 3; void myexit(int code) { #ifdef WIN32 printf("\nPress any key to continue\n"); getch(); #endif exit(code); } /* stolen from main.cc */ void bx_center_print(FILE *file, char *line, int maxwidth) { int imax; int i; imax = (maxwidth - strlen(line)) >> 1; for (i=0; imax) { printf("Your choice (%s) was not an integer between %d and %d.\n\n", clean, min, max); } else { // choice is okay *out = n; return 0; } } } int ask_menu(const char *prompt, int n_choices, char *choice[], int the_default, int *out) { char buffer[1024]; char *clean; int i; *out = -1; while(1) { printf("%s", prompt); printf("[%s] ", choice[the_default]); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default *out = the_default; return 0; } for (i=0; i0) printf(", "); printf("%s", choice[i]); } printf("\n"); } } int ask_yn(const char *prompt, int the_default, int *out) { char buffer[16]; char *clean; *out = -1; while (1) { printf("%s", prompt); printf("[%s] ", the_default?"yes":"no"); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default *out = the_default; return 0; } switch(tolower(clean[0])) { case 'y': *out=1; return 0; case 'n': *out=0; return 0; } printf("Please type either yes or no.\n"); } } int ask_string(const char *prompt, char *the_default, char *out) { char buffer[1024]; char *clean; out[0] = 0; printf("%s", prompt); printf("[%s] ", the_default); if (!fgets(buffer, sizeof(buffer), stdin)) return -1; clean = clean_string(buffer); if (strlen(clean) < 1) { // empty line, use the default strcpy(out, the_default); return 0; } strcpy(out, clean); return 0; } // fileset is like memset but for a file handle void fileset(FILE * fp, int c, size_t n) { #define BLOCK_SIZE (1024) int block[BLOCK_SIZE]; size_t left_to_write = n; memset(block, c, sizeof(block)); while(left_to_write > 0) { size_t write = sizeof(block); if (write > left_to_write) write = left_to_write; if (1 != fwrite(block, write, 1, fp)) { fclose(fp); fatal("ERROR: The disk image is not complete - could not write data block!"); } left_to_write -= write; } } /* Create a suited redolog header */ void make_redolog_header(redolog_header_t *header, const char* type, Bit64u size) { Bit32u entries, extent_size, bitmap_size; Bit64u maxsize; // Set standard header values strcpy((char*)header->standard.magic, STANDARD_HEADER_MAGIC); strcpy((char*)header->standard.type, REDOLOG_TYPE); strcpy((char*)header->standard.subtype, type); header->standard.version = htod32(STANDARD_HEADER_VERSION); header->standard.header = htod32(STANDARD_HEADER_SIZE); entries = 512; bitmap_size = 1; // Compute #entries and extent size values do { static Bit32u flip=0; extent_size = 8 * bitmap_size * 512; header->specific.catalog = htod32(entries); header->specific.bitmap = htod32(bitmap_size); header->specific.extent = htod32(extent_size); maxsize = (Bit64u)entries * (Bit64u)extent_size; flip++; if(flip&0x01) bitmap_size *= 2; else entries *= 2; } while (maxsize < size); header->specific.disk = htod64(size); } /* produce a flat image file */ #ifdef WIN32 int make_flat_image_win32(HANDLE hFile, Bit64u sec) { LARGE_INTEGER pos; DWORD dwCount, errCode; USHORT mode; char buffer[1024]; SetLastError(NO_ERROR); mode = COMPRESSION_FORMAT_DEFAULT; dwCount = 0; memset(buffer, 0, 512); WriteFile(hFile, buffer, 512, &dwCount, NULL); // set the first sector to 0, Win98 doesn't zero out the file // if there is a write at/over the end DeviceIoControl(hFile, FSCTL_SET_COMPRESSION, &mode, sizeof(mode), NULL, 0, &dwCount, NULL); pos.u.LowPart = (unsigned long)((sec - 1) << 9); pos.u.HighPart = (unsigned long)((sec - 1) >> 23); pos.u.LowPart = SetFilePointer(hFile, pos.u.LowPart, &pos.u.HighPart, FILE_BEGIN); memset(buffer, 0, 512); if ((pos.u.LowPart == 0xffffffff && GetLastError() != NO_ERROR) || !WriteFile(hFile, buffer, 512, &dwCount, NULL) || dwCount != 512) { errCode = GetLastError(); CloseHandle(hFile); if (errCode == ERROR_DISK_FULL) { fatal("\nERROR: Not enough space on disk for image!"); } else { sprintf(buffer, "\nERROR: Disk image creation failed with error code %i!", errCode); fatal(buffer); } } return 0; } #endif int make_flat_image(FILE *fp, Bit64u sec) { /* * seek to sec*512-1 and write a single character. * can't just do: fseek(fp, 512*sec-1, SEEK_SET) * because 512*sec may be too large for signed int. */ while(sec > 0) { /* temp <-- min(sec, 4194303) * 4194303 is (int)(0x7FFFFFFF/512) */ long temp = (long)((sec < 4194303) ? sec : 4194303); fseek(fp, 512*temp, SEEK_CUR); sec -= temp; } fseek(fp, -1, SEEK_CUR); if (fputc('\0', fp) == EOF) { fclose(fp); fatal("\nERROR: The disk image is not complete! (image larger then free space?)"); } return 0; } /* produce a sparse image file */ int make_sparse_image(FILE *fp, Bit64u sec) { Bit64u numpages; sparse_header_t header; size_t sizesofar; size_t padtopagesize; memset(&header, 0, sizeof(header)); header.magic = htod32(SPARSE_HEADER_MAGIC); header.version = htod32(SPARSE_HEADER_VERSION); header.pagesize = htod32((1 << 10) * 32); // Use 32 KB Pages - could be configurable numpages = (sec / (dtoh32(header.pagesize) / 512)) + 1; header.numpages = htod32((Bit32u)numpages); header.disk = htod64(sec * 512); if (numpages != dtoh32(header.numpages)) { fclose(fp); fatal("ERROR: The disk image is too large for a sparse image!"); // Could increase page size here. // But note this only happens at 128 Terabytes! } if (fwrite(&header, sizeof(header), 1, fp) != 1) { fclose(fp); fatal("ERROR: The disk image is not complete - could not write header!"); } fileset(fp, 0xff, 4 * dtoh32(header.numpages)); sizesofar = SPARSE_HEADER_SIZE + (4 * dtoh32(header.numpages)); padtopagesize = dtoh32(header.pagesize) - (sizesofar & (dtoh32(header.pagesize) - 1)); fileset(fp, 0, padtopagesize); return 0; } /* produce a growing image file */ int make_growing_image(FILE *fp, Bit64u sec) { redolog_header_t header; Bit32u i, not_allocated = htod32(REDOLOG_PAGE_NOT_ALLOCATED); memset(&header, 0, sizeof(header)); make_redolog_header(&header, REDOLOG_SUBTYPE_GROWING, sec * 512); if (fwrite(&header, sizeof(header), 1, fp) != 1) { fclose(fp); fatal("ERROR: The disk image is not complete - could not write header!"); } for (i=0; i bx_max_hd_megs)) { printf("Hard disk image size out of range\n\n"); ret = 0; } } else { printf("Image type (fd/hd) not specified\n\n"); } } else if (!strcmp("-q", argv[arg])) { bx_interactive = 0; } else if (argv[arg][0] == '-') { printf("Unknown option: %s\n\n", argv[arg]); ret = 0; } else { strcpy(bx_filename, argv[arg]); } arg++; } if (bx_hdimage == -1) { bx_hdimage = 1; bx_fdsize_idx = 6; bx_interactive = 1; } if (bx_hdimage == 1) { if (bx_hdimagemode == -1) { bx_hdimagemode = 0; bx_interactive = 1; } if (bx_hdsize == -1) { bx_hdsize = 10; bx_interactive = 1; } } else { if (bx_fdsize_idx == -1) { bx_fdsize_idx = 6; bx_interactive = 1; } } if (!strlen(bx_filename)) { bx_interactive = 1; } return ret; } int CDECL main(int argc, char *argv[]) { Bit64s sectors = 0; char filename[256]; char bochsrc_line[256]; char prompt[80]; WRITE_IMAGE write_function=NULL; #ifdef WIN32 WRITE_IMAGE_WIN32 writefn_win32=NULL; #endif if (!parse_cmdline(argc, argv)) myexit(1); print_banner(); if (bx_interactive) { if (ask_menu(fdhd_menu, fdhd_n_choices, fdhd_choices, bx_hdimage, &bx_hdimage) < 0) fatal(EOF_ERR); } if (bx_hdimage) { Bit64u cyl; int hdsize, heads=16, spt=63; int mode; if (bx_interactive) { if (ask_menu(hdmode_menu, hdmode_n_choices, hdmode_choices, bx_hdimagemode, &mode) < 0) fatal (EOF_ERR); sprintf(prompt, "\nEnter the hard disk size in megabytes, between 1 and %d\n", bx_max_hd_megs); if (ask_int(prompt, 1, bx_max_hd_megs, bx_hdsize, &hdsize) < 0) fatal(EOF_ERR); } else { mode = bx_hdimagemode; hdsize = bx_hdsize; } cyl = (Bit64u)(hdsize*1024.0*1024.0/16.0/63.0/512.0); assert(cyl < (1 << BX_MAX_CYL_BITS)); sectors = cyl*heads*spt; printf("\nI will create a '%s' hard disk image with\n", hdmode_choices[mode]); printf(" cyl=" FMT_LL "d\n", cyl); printf(" heads=%d\n", heads); printf(" sectors per track=%d\n", spt); printf(" total sectors=" FMT_LL "d\n", sectors); printf(" total size=%.2f megabytes\n", (float)(Bit64s)(sectors/2)/1024.0); if (bx_interactive) { if (!strlen(bx_filename)) strcpy(bx_filename, "c.img"); if (ask_string("\nWhat should I name the image?\n", bx_filename, filename) < 0) fatal(EOF_ERR); } else { strcpy(filename, bx_filename); } sprintf(bochsrc_line, "ata0-master: type=disk, path=\"%s\", mode=%s, cylinders=" FMT_LL "d, heads=%d, spt=%d", filename, hdmode_choices[mode], cyl, heads, spt); switch (mode) { case 1: write_function=make_sparse_image; break; case 2: write_function=make_growing_image; break; default: #ifdef WIN32 writefn_win32=make_flat_image_win32; #else write_function=make_flat_image; #endif } } else { int fdsize, cyl=0, heads=0, spt=0; if (bx_interactive) { if (ask_menu(fdsize_menu, fdsize_n_choices, fdsize_choices, bx_fdsize_idx, &fdsize) < 0) fatal(EOF_ERR); } else { fdsize = bx_fdsize_idx; } switch (fdsize) { case 0: cyl=40; heads=1; spt=8; break; /* 0.16 meg */ case 1: cyl=40; heads=1; spt=9; break; /* 0.18 meg */ case 2: cyl=40; heads=2; spt=8; break; /* 0.32 meg */ case 3: cyl=40; heads=2; spt=9; break; /* 0.36 meg */ case 4: cyl=80; heads=2; spt=9; break; /* 0.72 meg */ case 5: cyl=80; heads=2; spt=15; break; /* 1.2 meg */ case 6: cyl=80; heads=2; spt=18; break; /* 1.44 meg */ case 7: cyl=80; heads=2; spt=21; break; /* 1.68 meg */ case 8: cyl=82; heads=2; spt=21; break; /* 1.72 meg */ case 9: cyl=80; heads=2; spt=36; break; /* 2.88 meg */ default: fatal("ERROR: fdsize out of range"); } sectors = cyl*heads*spt; printf("I will create a floppy image with\n"); printf(" cyl=%d\n", cyl); printf(" heads=%d\n", heads); printf(" sectors per track=%d\n", spt); printf(" total sectors=" FMT_LL "d\n", sectors); printf(" total bytes=" FMT_LL "d\n", sectors*512); if (bx_interactive) { if (!strlen(bx_filename)) strcpy(bx_filename, "a.img"); if (ask_string("\nWhat should I name the image?\n", bx_filename, filename) < 0) fatal(EOF_ERR); } else { strcpy(filename, bx_filename); } sprintf(bochsrc_line, "floppya: image=\"%s\", status=inserted", filename); write_function=make_flat_image; } if (sectors < 1) fatal("ERROR: Illegal disk size!"); if (strlen (filename) < 1) fatal("ERROR: Illegal filename"); #ifdef WIN32 if (writefn_win32 != NULL) { make_image_win32(sectors, filename, writefn_win32); } else #endif { make_image(sectors, filename, write_function); } printf("\nI wrote " FMT_LL "u bytes to ", sectors*512); printf("%s.\n", filename); printf("\nThe following line should appear in your bochsrc:\n"); printf(" %s\n", bochsrc_line); #ifdef WIN32 if (OpenClipboard(NULL)) { HGLOBAL hgClip; EmptyClipboard(); hgClip = GlobalAlloc(GMEM_DDESHARE, (strlen(bochsrc_line) + 1)); strcpy((char *)GlobalLock(hgClip), bochsrc_line); GlobalUnlock(hgClip); SetClipboardData(CF_TEXT, hgClip); CloseClipboard(); printf("(The line is stored in your windows clipboard, use CTRL-V to paste)\n"); } #endif myexit(0); // make picky compilers (c++, gcc) happy, // even though we leave via 'myexit' just above return 0; } bochs-2.6/misc/make_cmos_image.cc0000644000175000017500000000630412020641466016703 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: make_cmos_image.cc 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Program which generates sample CMOS image files extern "C" { #include #include #include #include #include #include } #if 1 unsigned char cmos[] = { 0x29, 0x2b, 0x30, 0x2b, 0x16, 0x0b, 0x00, 0x01, 0x01, 0x96, 0x26, 0x02, 0x50, 0x80, 0x00, 0x00, 0x40, 0x8f, 0xf0, 0xc0, 0x3f, 0x80, 0x02, 0x00, 0x3c, 0x2f, 0x00, 0x4c, 0x0c, 0x10, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x2b, 0x03, 0x03, 0x03, 0x04, 0xce, 0x00, 0x3c, 0x19, 0xff, 0xff, 0xf0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x7b }; #else unsigned char cmos[] = { 0x29, 0x2b, 0x30, 0x2b, 0x16, 0x0b, 0x00, 0x01, 0x01, 0x96, 0x26, 0x02, 0x50, 0x80, 0x00, 0x00, 0x40, 0x8f, 0xf0, 0xc0, 0x0f, 0x80, 0x02, 0x00, 0x3c, 0x2f, 0x00, 0x1e, 0x00, 0x04, 0xff, 0xff, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x03, 0x03, 0x03, 0x05, 0xc5, 0x00, 0x3c, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, // 0x21 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x10, // 50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #endif int main(int argc, char *argv[]) { int fd, ret; if (argc != 2) { fprintf(stderr, "usage: %s pathname\n", argv[0]); exit(1); } fd = open(argv[1], O_WRONLY | O_CREAT #ifdef O_BINARY | O_BINARY #endif , S_IRUSR | S_IWUSR ); if (fd < 0) { perror("trying to open cmos image file to write.\n"); exit(1); } ret = write(fd, cmos, sizeof(cmos)); if (ret != sizeof(cmos)) { perror("write() did not write all CMOS data.\n"); exit(1); } printf("CMOS data successfuly written to file '%s'.\n", argv[1]); } bochs-2.6/misc/bswap.h0000644000175000017500000000313212020641466014555 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bswap.h 11289 2012-07-19 18:03:10Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_BSWAP_H #define BX_BSWAP_H #if BX_HAVE___BUILTIN_BSWAP32 #define bx_bswap32 __builtin_bswap32 #else BX_CPP_INLINE Bit32u bx_bswap32(Bit32u val32) { val32 = ((val32<<8) & 0xFF00FF00) | ((val32>>8) & 0x00FF00FF); return (val32<<16) | (val32>>16); } #endif #if BX_HAVE___BUILTIN_BSWAP64 #define bx_bswap64 __builtin_bswap64 #else BX_CPP_INLINE Bit64u bx_bswap64(Bit64u val64) { Bit32u lo = bx_bswap32((Bit32u)(val64 >> 32)); Bit32u hi = bx_bswap32((Bit32u)(val64 & 0xFFFFFFFF)); return ((Bit64u)hi << 32) | (Bit64u)lo; } #endif #endif bochs-2.6/install-sh0000755000175000017500000001273612020641507014347 0ustar guillemguillem#!/bin/sh # # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its # documentation for any purpose is hereby granted without fee, provided that # the above copyright notice appear in all copies and that both that # copyright notice and this permission notice appear in supporting # documentation, and that the name of M.I.T. not be used in advertising or # publicity pertaining to distribution of the software without specific, # written prior permission. M.I.T. makes no representations about the # suitability of this software for any purpose. It is provided "as is" # without express or implied warranty. # # Calling this script install-sh is preferred over install.sh, to prevent # `make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. It can only install one file at a time, a restriction # shared with many OS's install programs. # set DOITPROG to echo to test this script # Don't use :- since 4.3BSD and earlier shells don't like it. doit="${DOITPROG-}" # put in absolute paths if you don't have them in your path; or use env. vars. mvprog="${MVPROG-mv}" cpprog="${CPPROG-cp}" chmodprog="${CHMODPROG-chmod}" chownprog="${CHOWNPROG-chown}" chgrpprog="${CHGRPPROG-chgrp}" stripprog="${STRIPPROG-strip}" rmprog="${RMPROG-rm}" mkdirprog="${MKDIRPROG-mkdir}" transformbasename="" transform_arg="" instcmd="$mvprog" chmodcmd="$chmodprog 0755" chowncmd="" chgrpcmd="" stripcmd="" rmcmd="$rmprog -f" mvcmd="$mvprog" src="" dst="" dir_arg="" while [ x"$1" != x ]; do case $1 in -c) instcmd="$cpprog" shift continue;; -d) dir_arg=true shift continue;; -m) chmodcmd="$chmodprog $2" shift shift continue;; -o) chowncmd="$chownprog $2" shift shift continue;; -g) chgrpcmd="$chgrpprog $2" shift shift continue;; -s) stripcmd="$stripprog" shift continue;; -t=*) transformarg=`echo $1 | sed 's/-t=//'` shift continue;; -b=*) transformbasename=`echo $1 | sed 's/-b=//'` shift continue;; *) if [ x"$src" = x ] then src=$1 else # this colon is to work around a 386BSD /bin/sh bug : dst=$1 fi shift continue;; esac done if [ x"$src" = x ] then echo "install: no input file specified" exit 1 else true fi if [ x"$dir_arg" != x ]; then dst=$src src="" if [ -d $dst ]; then instcmd=: chmodcmd="" else instcmd=mkdir fi else # Waiting for this to be detected by the "$instcmd $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if [ -f $src -o -d $src ] then true else echo "install: $src does not exist" exit 1 fi if [ x"$dst" = x ] then echo "install: no destination specified" exit 1 else true fi # If destination is a directory, append the input filename; if your system # does not like double slashes in filenames, you may need to add some logic if [ -d $dst ] then dst="$dst"/`basename $src` else true fi fi ## this sed command emulates the dirname command dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` # Make sure that the destination directory exists. # this part is taken from Noah Friedman's mkinstalldirs script # Skip lots of stat calls in the usual case. if [ ! -d "$dstdir" ]; then defaultIFS=' ' IFS="${IFS-${defaultIFS}}" oIFS="${IFS}" # Some sh's can't handle IFS=/ for some reason. IFS='%' set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` IFS="${oIFS}" pathcomp='' while [ $# -ne 0 ] ; do pathcomp="${pathcomp}${1}" shift if [ ! -d "${pathcomp}" ] ; then $mkdirprog "${pathcomp}" else true fi pathcomp="${pathcomp}/" done fi if [ x"$dir_arg" != x ] then $doit $instcmd $dst && if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi else # If we're going to rename the final executable, determine the name now. if [ x"$transformarg" = x ] then dstfile=`basename $dst` else dstfile=`basename $dst $transformbasename | sed $transformarg`$transformbasename fi # don't allow the sed command to completely eliminate the filename if [ x"$dstfile" = x ] then dstfile=`basename $dst` else true fi # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# # Move or copy the file name to the temp name $doit $instcmd $src $dsttmp && trap "rm -f ${dsttmp}" 0 && # and set any options; do chmod last to preserve setuid bits # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $instcmd $src $dsttmp" command. if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && # Now rename the file to the real destination. $doit $rmcmd -f $dstdir/$dstfile && $doit $mvcmd $dsttmp $dstdir/$dstfile fi && exit 0 bochs-2.6/configure0000755000175000017500000311431412020641507014250 0ustar guillemguillem#! /bin/sh # From configure.in Id: configure.in 11392 2012-09-02 11:11:00Z vruppert . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.68. # # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software # Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV export CONFIG_SHELL case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, $0: including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" # Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} case X$ECHO in X*--fallback-echo) # Remove one level of quotation (which was required for Make). ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` ;; esac echo=${ECHO-echo} if test "X$1" = X--no-reexec; then # Discard the --no-reexec flag, and continue. shift elif test "X$1" = X--fallback-echo; then # Avoid inline document here, it may be left over : elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then # Yippee, $echo works! : else # Restart under the correct shell. exec $SHELL "$0" --no-reexec ${1+"$@"} fi if test "X$1" = X--fallback-echo; then # used as fallback echo shift cat </dev/null && echo_test_string="`eval $cmd`" && (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null then break fi done fi if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then : else # The Solaris, AIX, and Digital Unix default echo programs unquote # backslashes. This makes it impossible to quote backslashes using # echo "$something" | sed 's/\\/\\\\/g' # # So, first we look for a working echo in the user's PATH. lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for dir in $PATH /usr/ucb; do IFS="$lt_save_ifs" if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$dir/echo" break fi done IFS="$lt_save_ifs" if test "X$echo" = Xecho; then # We didn't find a better echo, so look for alternatives. if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # This shell has a builtin print -r that does the trick. echo='print -r' elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && test "X$CONFIG_SHELL" != X/bin/ksh; then # If we have ksh, try running configure again with it. ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} export ORIGINAL_CONFIG_SHELL CONFIG_SHELL=/bin/ksh export CONFIG_SHELL exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} else # Try using printf. echo='printf %s\n' if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then # Cool, printf works : elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL export CONFIG_SHELL SHELL="$CONFIG_SHELL" export SHELL echo="$CONFIG_SHELL $0 --fallback-echo" elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && test "X$echo_testing_string" = 'X\t' && echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && test "X$echo_testing_string" = "X$echo_test_string"; then echo="$CONFIG_SHELL $0 --fallback-echo" else # maybe with a smaller string... prev=: for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null then break fi prev="$cmd" done if test "$prev" != 'sed 50q "$0"'; then echo_test_string=`eval $prev` export echo_test_string exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} else # Oops. We lost completely, so just stick with echo. echo=echo fi fi fi fi fi fi # Copy echo and quote the copy suitably for passing to libtool from # the Makefile, instead of quoting the original, which is used later. ECHO=$echo if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" fi tagnames=${tagnames+${tagnames},}CXX tagnames=${tagnames+${tagnames},}F77 test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME= PACKAGE_TARNAME= PACKAGE_VERSION= PACKAGE_STRING= PACKAGE_BUGREPORT= PACKAGE_URL= ac_unique_file="bochs.h" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='LTLIBOBJS LIBOBJS TAR GZIP INSTALL_PLUGINS_VAR PLUGIN_TARGET PLUGIN_VAR IODEV_EXT_PLUGIN_OBJS IODEV_EXT_NON_PLUGIN_OBJS IODEV_PLUGIN_OBJS IODEV_NON_PLUGIN_OBJS GUI_PLUGIN_OBJS GUI_NON_PLUGIN_OBJS EXTRA_LINK_OPTS REL_STRING WIN_VER_STRING VER_STRING VERSION CD_UP_THREE CD_UP_TWO CD_UP_ONE COMMAND_SEPARATOR PLUGIN_LIBNAME_TRANSFORMATION PRIMARY_TARGET EXE LINK_CONSOLE LINK RMCOMMAND MAKELIB OFP CFP CXXFP SLASH DASH BXIMAGE_LINK_OPTS GUI_LINK_OPTS_WX GUI_LINK_OPTS_TERM GUI_LINK_OPTS DEVICE_LINK_OPTS GUI_OBJS RFB_LIBS INSTALL_LIST_FOR_PLATFORM INSTALL_TARGET PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC EXPORT_DYNAMIC DIALOG_OBJS ENH_DBG_OBJS WGET TOOLKIT_CXXFLAGS WX_CXXFLAGS WX_CFLAGS GUI_CXXFLAGS GUI_CFLAGS WX_CONFIG RC_CMD EXTERNAL_DEPENDENCY INLINE_VAR NONINLINE_VAR EXTRA_BX_OBJS IODEV_LIB_VAR HDIMAGE_LIB_VAR CLEAN_DOCBOOK_VAR INSTALL_DOCBOOK_VAR BUILD_DOCBOOK_VAR DOCBOOK2HTML GAME_OBJS SOUND_LINK_OPTS SOUNDLOW_OBJS SOUNDCARD_OBJS SOUND_LIB_VAR CDROM_OBJS FPU_VAR INSTRUMENT_VAR INSTRUMENT_DIR READLINE_LIB IODEBUG_OBJS GDBSTUB_VAR DISASM_VAR DEBUGGER_VAR NO_FLEX_YACC YACC FLEX CPP_SUFFIX SUFFIX_LINE NETLOW_OBJS NETDEV_OBJS NETWORK_LIB_VAR USB_LIB_VAR SCSI_OBJS USBDEV_OBJS USBCORE_OBJ USBHC_OBJS CLEAN_PCIDEV_VAR KERNEL_MODULE_SUFFIX PCIDEV_MODULE_MAKE_ALL DEPMOD RMMOD INSMOD LSMOD KERNELDIR PCI_OBJ BX_LARGE_RAMFILE OBJS64 NONPLUGIN_GUI_LINK_OPTS DEFINE_PLUGIN_PATH BX_USE_IDLE_HACK X_EXTRA_LIBS X_LIBS X_PRE_LIBS X_CFLAGS XMKMF PKGCONFIG LIBADD_DL LIBTOOL ac_ct_F77 FFLAGS F77 CXXCPP CPP STRIP RANLIB AR ECHO LN_S EGREP GREP SET_MAKE ac_ct_CXX CXXFLAGS CXX OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC target_os target_vendor target_cpu target host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_static enable_shared enable_fast_install with_gnu_ld enable_libtool_lock with_pic with_tags enable_ltdl_install with_x enable_largefile enable_idle_hack enable_plugins enable_a20_pin enable_x86_64 enable_smp enable_cpu_level enable_long_phy_address enable_large_ramfile enable_ne2000 enable_pci enable_pcidev enable_usb enable_usb_ohci enable_usb_xhci enable_pnic enable_e1000 enable_repeat_speedups enable_fast_function_calls enable_handlers_chaining enable_configurable_msrs enable_show_ips enable_cpp enable_debugger enable_disasm enable_debugger_gui enable_gdb_stub enable_iodebug enable_all_optimizations enable_readline enable_instrumentation enable_logging enable_assert_checks enable_raw_serial enable_clgd54xx enable_fpu enable_vmx enable_svm enable_3dnow enable_alignment_check enable_misaligned_sse enable_monitor_mwait enable_avx enable_x86_debugger enable_cdrom enable_sb16 enable_es1370 enable_gameport enable_docbook with_x11 with_win32 with_macos with_carbon with_nogui with_term with_rfb with_amigaos with_sdl with_svga with_wx with_all_libs enable_xpm enable_apic enable_x2apic enable_vbe enable_acpi enable_trace_cache ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CXX CXXFLAGS CCC CPP CXXCPP F77 FFLAGS XMKMF' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe $as_echo "$as_me: WARNING: if you wanted to set the --build type, don't use --host. If a cross compiler is detected then cross compile mode will be used" >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures this package to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] --target=TARGET configure for building compilers for TARGET [HOST] _ACEOF fi if test -n "$ac_init_help"; then cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-static[=PKGS] build static libraries [default=no] --enable-shared[=PKGS] build shared libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-ltdl-install install libltdl --disable-largefile omit support for large files --enable-idle-hack use Roland Mainz's idle hack --enable-plugins enable plugins --enable-a20-pin compile in support for A20 pin --enable-x86-64 compile in support for x86-64 instructions --enable-smp compile in support for SMP configurations --enable-cpu-level select cpu level (3,4,5,6) --enable-long-phy-address compile in support for physical address larger than 32 bit --enable-large-ramfile enable large ramfile support --enable-ne2000 enable NE2000 support --enable-pci enable i440FX PCI support --enable-pcidev enable PCI host device mapping support (linux host only) --enable-usb enable USB UHCI support --enable-usb-ohci enable USB OHCI support --enable-usb-xhci enable experimental USB xHCI support (incomplete) --enable-pnic enable PCI pseudo NIC support --enable-e1000 enable Intel(R) Gigabit Ethernet support --enable-repeat-speedups support repeated IO and mem copy speedups --enable-fast-function-calls support for fast function calls (gcc on x86 only) --enable-handlers-chaining support handlers-chaining emulation speedups --enable-configurable-msrs support for configurable MSR registers --enable-show-ips show IPS in Bochs log file --enable-cpp use .cpp as C++ suffix --enable-debugger compile in support for Bochs internal debugger --enable-disasm compile in support for disassembler --enable-debugger-gui compile in support for Bochs internal debugger GUI --enable-gdb-stub enable gdb stub support --enable-iodebug enable I/O interface to debugger --enable-all-optimizations compile in all possible optimizations --enable-readline use readline library, if available --enable-instrumentation compile in support for instrumentation --enable-logging enable logging --enable-assert-checks enable BX_ASSERT checks --enable-raw-serial use raw serial port access --enable-clgd54xx enable CLGD54XX emulation --enable-fpu compile in FPU emulation --enable-vmx VMX (virtualization extensions) emulation (--enable-vmx=no|1|2) --enable-svm SVM (AMD: secure virtual machine) emulation --enable-3dnow 3DNow! support (incomplete) --enable-alignment-check alignment check (#AC) support --enable-misaligned-sse misaligned SSE support --enable-monitor-mwait support for MONITOR/MWAIT instructions (experimental) --enable-avx support for AVX instructions --enable-x86-debugger x86 debugger support --enable-cdrom CDROM support --enable-sb16 Sound Blaster 16 Support --enable-es1370 enable ES1370 soundcard support --enable-gameport enable standard PC gameport support --enable-docbook build the Docbook documentation --enable-xpm enable the check for XPM support --enable-apic enable APIC support (deprecated) --enable-x2apic enable X2APIC support (deprecated) --enable-vbe use VESA BIOS extensions (deprecated) --enable-acpi use ACPI extensions support (deprecated) --enable-trace-cache support instruction trace cache (deprecated) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-pic try to use only PIC/non-PIC objects [default=use both] --with-tags[=TAGS] include additional configurations [automatic] --with-x use the X Window System --with-x11 use X11 GUI --with-win32 use Win32 GUI --with-macos use Macintosh/CodeWarrior environment --with-carbon compile for MacOS X with Carbon GUI --with-nogui no native GUI, just use blank stubs --with-term textmode terminal environment --with-rfb use RFB protocol, works with VNC viewer --with-amigaos use AmigaOS (or MorphOS) GUI --with-sdl use SDL libraries --with-svga use SVGALib libraries --with-wx use wxWidgets libraries --with-all-libs compile all guis that Bochs supports Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor CXXCPP C++ preprocessor F77 Fortran 77 compiler command FFLAGS Fortran 77 compiler flags XMKMF Path to xmkmf, Makefile generator for X Window System Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to the package provider. _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF configure generated by GNU Autoconf 2.68 Copyright (C) 2010 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_cxx_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_cxx_try_cpp LINENO # ------------------------ # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_cpp # ac_fn_cxx_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_cxx_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_cxx_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_cxx_try_link # ac_fn_cxx_check_func LINENO FUNC VAR # ------------------------------------ # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_cxx_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_cxx_check_func # ac_fn_f77_try_compile LINENO # ---------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_f77_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_f77_try_compile # ac_fn_f77_try_link LINENO # ------------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_f77_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_f77_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || $as_test_x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_f77_try_link # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_compute_int LINENO EXPR VAR INCLUDES # -------------------------------------------- # Tries to find the compile-time value of EXPR in a program that includes # INCLUDES, setting VAR accordingly. Returns whether the value could be # computed ac_fn_c_compute_int () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if test "$cross_compiling" = yes; then # Depending upon the size, compute the lo and hi bounds. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= 0)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=0 ac_mid=0 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid; break else as_fn_arith $ac_mid + 1 && ac_lo=$as_val if test $ac_lo -le $ac_mid; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) < 0)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=-1 ac_mid=-1 while :; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) >= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_lo=$ac_mid; break else as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val if test $ac_mid -le $ac_hi; then ac_lo= ac_hi= break fi as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done else ac_lo= ac_hi= fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Binary search between lo and hi bounds. while test "x$ac_lo" != "x$ac_hi"; do as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { static int test_array [1 - 2 * !(($2) <= $ac_mid)]; test_array [0] = 0 ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_hi=$ac_mid else as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext done case $ac_lo in #(( ?*) eval "$3=\$ac_lo"; ac_retval=0 ;; '') ac_retval=1 ;; esac else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 static long int longval () { return $2; } static unsigned long int ulongval () { return $2; } #include #include int main () { FILE *f = fopen ("conftest.val", "w"); if (! f) return 1; if (($2) < 0) { long int i = longval (); if (i != ($2)) return 1; fprintf (f, "%ld", i); } else { unsigned long int i = ulongval (); if (i != ($2)) return 1; fprintf (f, "%lu", i); } /* Do not output a trailing newline, as this causes \r\n confusion on some platforms. */ return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : echo >>conftest.val; read $3 &5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by $as_me, which was generated by GNU Autoconf 2.68. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_headers="$ac_config_headers config.h" ac_config_headers="$ac_config_headers ltdlconf.h" VERSION="2.6" VER_STRING="2.6" WIN_VER_STRING="2, 6, 0, 0" REL_STRING="Built from SVN snapshot on September 2nd, 2012" ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5 $as_echo_n "checking target system type... " >&6; } if ${ac_cv_target+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$target_alias" = x; then ac_cv_target=$ac_cv_host else ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5 $as_echo "$ac_cv_target" >&6; } case $ac_cv_target in *-*-*) ;; *) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;; esac target=$ac_cv_target ac_save_IFS=$IFS; IFS='-' set x $ac_cv_target shift target_cpu=$1 target_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: target_os=$* IFS=$ac_save_IFS case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac # The aliases save the names the user supplied, while $host etc. # will get canonicalized. test -n "$target_alias" && test "$program_prefix$program_suffix$program_transform_name" = \ NONENONEs,x,x, && program_prefix=${target_alias}- { $as_echo "$as_me:${as_lineno-$LINENO}: checking if you are configuring for another platform" >&5 $as_echo_n "checking if you are configuring for another platform... " >&6; } if test "$cross_compiling" = yes -o "$target_os" = "windows"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } cross_configure=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } cross_configure=0 fi # this case statement defines the compile flags which are needed to # compile bochs on a platform. Don't put things like optimization settings # into the configure.in file, since people will want to be able to change # those settings by defining CFLAGS and CXXFLAGS before running configure. NO_LT=0 MSVC_TARGET=0 need_dlcompat_for_plugins=0 case "$target" in *-pc-windows* | *-pc-winnt*) DEFAULT_GUI=win32 # default to win32 gui MSVC_TARGET=1 ;; *-pc-cygwin*) NO_LT=1 # do not use libtool at all on cygwin if test "$with_term" = yes; then # ncurses won't compile with -mno-cygwin or -DWIN32 # also, I can't get it to link without this -DBROKEN_LINKER=1 hack. # see /usr/include/curses.h for details. ADD_FLAGS="-DBROKEN_LINKER=1" fi ;; *-mingw32*) NO_LT=1 # do not use libtool at all on cygwin if test "$with_term" = yes; then # ncurses won't compile with -mno-cygwin or -DWIN32 # also, I can't get it to link without this -DBROKEN_LINKER=1 hack. # see /usr/include/curses.h for details. ADD_FLAGS="-DBROKEN_LINKER=1" else # default case ADD_FLAGS="-DWIN32" # required for mingw compile+win32 gui DEFAULT_GUI=win32 # default to win32 gui fi ;; *-macosx* | *-darwin*) ADD_FLAGS="-fpascal-strings -fno-common -Wno-four-char-constants -Wno-unknown-pragmas -Dmacintosh" # required for macosx compile DEFAULT_GUI=carbon # default to carbon need_dlcompat_for_plugins=1 ;; *-macos*) DEFAULT_GUI=macos # macos defaults to macos ;; *-amigaos* | *-morphos*) DEFAULT_GUI=amigaos # amigaos or morphos defaults to amigaos gui ;; *-solaris*) ADD_FLAGS="-D_XOPEN_SOURCE_EXTENDED=1 -D__EXTENSIONS__" # required for correct function prototypes LIBS="$LIBS -lsocket -lnsl" DEFAULT_GUI=x11 ;; *) DEFAULT_GUI=x11 ;; esac if test "${ADD_FLAGS:+set}" = set; then CFLAGS="$CFLAGS $ADD_FLAGS" CXXFLAGS="$CXXFLAGS $ADD_FLAGS" CPPFLAGS="$CPPFLAGS $ADD_FLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for standard CFLAGS on this platform" >&5 $as_echo_n "checking for standard CFLAGS on this platform... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ADD_FLAGS" >&5 $as_echo "$ADD_FLAGS" >&6; } if (test "$with_sdl" != yes) && \ (test "$with_svga" != yes) && \ (test "$with_x11" != yes) && \ (test "$with_win32" != yes) && \ (test "$with_nogui" != yes) && \ (test "$with_term" != yes) && \ (test "$with_rfb" != yes) && \ (test "$with_amigaos" != yes) && \ (test "$with_carbon" != yes) && \ (test "$with_wx" != yes) && \ (test "$with_macos" != yes); then # use DEFAULT_GUI. Set the appropriate variable. # DEFAULT_GUI must be set to one of the names above. Otherwise, no # valid $with_* variable will be set and who knows what will happen? eval "with_${DEFAULT_GUI}=yes" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu if test -z "$CXX"; then if test -n "$CCC"; then CXX=$CCC else if test -n "$ac_tool_prefix"; then for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CXX"; then ac_cv_prog_CXX="$CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CXX=$ac_cv_prog_CXX if test -n "$CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 $as_echo "$CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CXX" && break done fi if test -z "$CXX"; then ac_ct_CXX=$CXX for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CXX+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CXX"; then ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_CXX="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CXX=$ac_cv_prog_ac_ct_CXX if test -n "$ac_ct_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 $as_echo "$ac_ct_CXX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CXX" && break done if test "x$ac_ct_CXX" = x; then CXX="g++" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CXX=$ac_ct_CXX fi fi fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 $as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } if ${ac_cv_cxx_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_cxx_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 $as_echo "$ac_cv_cxx_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GXX=yes else GXX= fi ac_test_CXXFLAGS=${CXXFLAGS+set} ac_save_CXXFLAGS=$CXXFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 $as_echo_n "checking whether $CXX accepts -g... " >&6; } if ${ac_cv_prog_cxx_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_cxx_werror_flag=$ac_cxx_werror_flag ac_cxx_werror_flag=yes ac_cv_prog_cxx_g=no CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes else CXXFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : else ac_cxx_werror_flag=$ac_save_cxx_werror_flag CXXFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : ac_cv_prog_cxx_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cxx_werror_flag=$ac_save_cxx_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 $as_echo "$ac_cv_prog_cxx_g" >&6; } if test "$ac_test_CXXFLAGS" = set; then CXXFLAGS=$ac_save_CXXFLAGS elif test $ac_cv_prog_cxx_g = yes; then if test "$GXX" = yes; then CXXFLAGS="-g -O2" else CXXFLAGS="-g" fi else if test "$GXX" = yes; then CXXFLAGS="-O2" else CXXFLAGS= fi fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi if test "$MSVC_TARGET" != 1; then # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=no fi # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${lt_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else # Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && break cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done SED=$lt_cv_path_SED fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 $as_echo "$SED" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD-compatible nm" >&5 $as_echo_n "checking for BSD-compatible nm... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/${ac_tool_prefix}nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac esac fi done IFS="$lt_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } NM="$lt_cv_path_NM" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognise dependent libraries" >&5 $as_echo_n "checking how to recognise dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix4* | aix5*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi4*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin* | mingw* | pw32*) # win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='win32_libid' ;; darwin* | rhapsody*) # this will be overwritten by pass_all, but leave it in just in case lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' lt_cv_file_magic_cmd='/usr/bin/file -L' case "$host_os" in rhapsody* | darwin1.[012]) lt_cv_file_magic_test_file=`/System/Library/Frameworks/System.framework/System` ;; *) # Darwin 1.3 on lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' ;; esac lt_cv_deplibs_check_method=pass_all ;; freebsd* | kfreebsd*-gnu) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case "$host_cpu" in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux*) case $host_cpu in alpha* | hppa* | i*86 | ia64* | m68* | mips* | powerpc* | sparc* | s390* | sh*) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; esac lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 5114 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case "`/usr/bin/file conftest.o`" in *32-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; esac need_locks="$enable_libtool_lock" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 $as_echo_n "checking how to run the C++ preprocessor... " >&6; } if test -z "$CXXCPP"; then if ${ac_cv_prog_CXXCPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CXXCPP needs to be expanded for CXXCPP in "$CXX -E" "/lib/cpp" do ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CXXCPP=$CXXCPP fi CXXCPP=$ac_cv_prog_CXXCPP else ac_cv_prog_CXXCPP=$CXXCPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 $as_echo "$CXXCPP" >&6; } ac_preproc_ok=false for ac_cxx_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_cxx_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu if test -n "$ac_tool_prefix"; then for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_F77+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$F77"; then ac_cv_prog_F77="$F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_F77="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi F77=$ac_cv_prog_F77 if test -n "$F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $F77" >&5 $as_echo "$F77" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$F77" && break done fi if test -z "$F77"; then ac_ct_F77=$F77 for ac_prog in g77 xlf f77 frt pgf77 cf77 fort77 fl32 af77 xlf90 f90 pgf90 pghpf epcf90 gfortran g95 xlf95 f95 fort ifort ifc efc pgfortran pgf95 lf95 ftn do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_F77+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_F77"; then ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_F77="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_F77=$ac_cv_prog_ac_ct_F77 if test -n "$ac_ct_F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_F77" >&5 $as_echo "$ac_ct_F77" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_F77" && break done if test "x$ac_ct_F77" = x; then F77="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac F77=$ac_ct_F77 fi fi # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for Fortran 77 compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done rm -f a.out # If we don't use `.F' as extension, the preprocessor is not run on the # input file. (Note that this only needs to work for GNU compilers.) ac_save_ext=$ac_ext ac_ext=F { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU Fortran 77 compiler" >&5 $as_echo_n "checking whether we are using the GNU Fortran 77 compiler... " >&6; } if ${ac_cv_f77_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat > conftest.$ac_ext <<_ACEOF program main #ifndef __GNUC__ choke me #endif end _ACEOF if ac_fn_f77_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_f77_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_f77_compiler_gnu" >&5 $as_echo "$ac_cv_f77_compiler_gnu" >&6; } ac_ext=$ac_save_ext ac_test_FFLAGS=${FFLAGS+set} ac_save_FFLAGS=$FFLAGS FFLAGS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $F77 accepts -g" >&5 $as_echo_n "checking whether $F77 accepts -g... " >&6; } if ${ac_cv_prog_f77_g+:} false; then : $as_echo_n "(cached) " >&6 else FFLAGS=-g cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_compile "$LINENO"; then : ac_cv_prog_f77_g=yes else ac_cv_prog_f77_g=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_f77_g" >&5 $as_echo "$ac_cv_prog_f77_g" >&6; } if test "$ac_test_FFLAGS" = set; then FFLAGS=$ac_save_FFLAGS elif test $ac_cv_prog_f77_g = yes; then if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-g -O2" else FFLAGS="-g" fi else if test "x$ac_cv_f77_compiler_gnu" = xyes; then FFLAGS="-O2" else FFLAGS= fi fi if test $ac_compiler_gnu = yes; then G77=yes else G77= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 testring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; amigaos* | morphos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; *) # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while (test "X"`$CONFIG_SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ = "XX$testring") >/dev/null 2>&1 && new_result=`expr "X$testring" : ".*" 2>&1` && lt_cv_sys_max_cmd_len=$new_result && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` testring=$testring$testring done testring= # Add a significant safety factor because C++ compilers can tack on massive # amounts of additional arguments before passing them to the linker. # It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32*) symcode='[ABCDGISTW]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris* | sysv5*) symcode='[BDRT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. Xsed='sed -e s/^X//' sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' # Constants: rm="rm -f" # Global variables: default_ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except M$VC, # which needs '.lib'). libext=a ltmain="$ac_aux_dir/ltmain.sh" ofile="$default_ofile" with_gnu_ld="$lt_cv_prog_gnu_ld" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. set dummy ${ac_tool_prefix}ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_AR="${ac_tool_prefix}ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_AR"; then ac_ct_AR=$AR # Extract the first word of "ar", so it can be a program name with args. set dummy ar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_AR="ar" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi else AR="$ac_cv_prog_AR" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$AR" && AR=ar test -z "$AR_FLAGS" && AR_FLAGS=cru test -z "$AS" && AS=as test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$DLLTOOL" && DLLTOOL=dlltool test -z "$LD" && LD=ld test -z "$LN_S" && LN_S="ln -s" test -z "$MAGIC_CMD" && MAGIC_CMD=file test -z "$NM" && NM=nm test -z "$SED" && SED=sed test -z "$OBJDUMP" && OBJDUMP=objdump test -z "$RANLIB" && RANLIB=: test -z "$STRIP" && STRIP=: test -z "$ac_objext" && ac_objext=o # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" ;; *) old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi # Only perform the check for file, if the check method requires it case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac enable_dlopen=yes enable_win32_dll=no # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Use C for the default configuration in the libtool script tagname= lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}\n' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # # Check for any special shared library compilation flags. # lt_prog_cc_shlib= if test "$GCC" = no; then case $host_os in sco3.2v5*) lt_prog_cc_shlib='-belf' ;; esac fi if test -n "$lt_prog_cc_shlib"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&5 $as_echo "$as_me: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&2;} if echo "$old_CC $old_CFLAGS " | grep "[ ]$lt_prog_cc_shlib[ ]" >/dev/null; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 $as_echo "$as_me: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} lt_cv_prog_cc_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_prog_compiler_static works" >&5 $as_echo_n "checking if $compiler static flag $lt_prog_compiler_static works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_prog_compiler_static" printf "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 else lt_cv_prog_compiler_static_works=yes fi fi $rm conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag=' -fno-builtin' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:6802: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:6806: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; *) lt_prog_compiler_pic='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; linux*) case $CC in icc* | ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; sco3.2v5*) lt_prog_compiler_pic='-Kpic' lt_prog_compiler_static='-dn' ;; solaris*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 $as_echo "$lt_prog_compiler_pic" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7035: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7039: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_pic_works=yes fi fi $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:7102: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7106: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= enable_shared_with_static_runtimes=no archive_cmds= archive_expsym_cmds= old_archive_From_new_cmds= old_archive_from_expsyms_cmds= export_dynamic_flag_spec= whole_archive_flag_spec= thread_safe_flag_spec= hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no hardcode_shlibpath_var=unsupported link_all_deplibs=unknown hardcode_automatic=no module_cmds= module_expsym_cmds= always_export_symbols=no export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; linux*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_cmds="$tmp_archive_cmds" supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac if test $supports_anon_versioning = yes; then archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' else archive_expsym_cmds="$tmp_archive_cmds" fi else ld_shlibs=no fi ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_libdir_separator=':' link_all_deplibs=yes if test "$GCC" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct=yes else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec=' ' archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes # see comment about different semantics on the GNU ld section ld_shlibs=no ;; bsdi4*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then archive_cmds_need_lc=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='-all_load $convenience' link_all_deplibs=yes else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=no hardcode_shlibpath_var=no ;; ia64*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=no hardcode_shlibpath_var=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; *) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld='-rpath $libdir' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; openbsd*) hardcode_direct=yes hardcode_shlibpath_var=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; sco3.2v5*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag=' -z text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4.2uw2*) archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=no hardcode_shlibpath_var=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) no_undefined_flag='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv5*) no_undefined_flag=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec= hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc=no else archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 $as_echo "$archive_cmds_need_lc" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || \ test -n "$runpath_var " || \ test "X$hardcode_automatic"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # Report which librarie types wil actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; darwin* | rhapsody*) if test "$GCC" = yes; then archive_cmds_need_lc=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag='-undefined dynamic_lookup' ;; esac fi ;; esac output_verbose_link_cmd='echo' archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' module_cmds='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported whole_archive_flag_spec='-all_load $convenience' link_all_deplibs=yes else ld_shlibs=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler \ CC \ LD \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ lt_prog_compiler_static \ lt_prog_compiler_no_builtin_flag \ export_dynamic_flag_spec \ thread_safe_flag_spec \ whole_archive_flag_spec \ enable_shared_with_static_runtimes \ old_archive_cmds \ old_archive_from_new_cmds \ predep_objects \ postdep_objects \ predeps \ postdeps \ compiler_lib_search_path \ archive_cmds \ archive_expsym_cmds \ postinstall_cmds \ postuninstall_cmds \ old_archive_from_expsyms_cmds \ allow_undefined_flag \ no_undefined_flag \ export_symbols_cmds \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ hardcode_automatic \ module_cmds \ module_expsym_cmds \ lt_cv_prog_compiler_c_o \ exclude_expsyms \ include_expsyms; do case $var in old_archive_cmds | \ old_archive_from_new_cmds | \ archive_cmds | \ archive_expsym_cmds | \ module_cmds | \ module_expsym_cmds | \ old_archive_from_expsyms_cmds | \ export_symbols_cmds | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="${ofile}T" trap "$rm \"$cfgfile\"; exit 1" 1 2 15 $rm -f "$cfgfile" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ofile" >&5 $as_echo "$as_me: creating $ofile" >&6;} cat <<__EOF__ >> "$cfgfile" #! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler # Is the compiler the GNU C compiler? with_gcc=$GCC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP="$STRIP" # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # ### END LIBTOOL CONFIG __EOF__ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" # Check whether --with-tags was given. if test "${with_tags+set}" = set; then : withval=$with_tags; tagnames="$withval" fi if test -f "$ltmain" && test -n "$tagnames"; then if test ! -f "${ofile}"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: output file \`$ofile' does not exist" >&5 $as_echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} fi if test -z "$LTCC"; then eval "`$SHELL ${ofile} --config | grep '^LTCC='`" if test -z "$LTCC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: output file \`$ofile' does not look like a libtool script" >&5 $as_echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 $as_echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} fi fi # Extract list of available tagged configurations in $ofile. # Note that this assumes the entire list is on one line. available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for tagname in $tagnames; do IFS="$lt_save_ifs" # Check whether tagname contains only valid characters case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in "") ;; *) as_fn_error $? "invalid tag name: $tagname" "$LINENO" 5 ;; esac if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null then as_fn_error $? "tag name \"$tagname\" already exists" "$LINENO" 5 fi # Update the list of available tags. if test -n "$tagname"; then echo appending configuration tag \"$tagname\" to $ofile case $tagname in CXX) if test -n "$CXX" && test "X$CXX" != "Xno"; then ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu archive_cmds_need_lc_CXX=no allow_undefined_flag_CXX= always_export_symbols_CXX=no archive_expsym_cmds_CXX= export_dynamic_flag_spec_CXX= hardcode_direct_CXX=no hardcode_libdir_flag_spec_CXX= hardcode_libdir_flag_spec_ld_CXX= hardcode_libdir_separator_CXX= hardcode_minus_L_CXX=no hardcode_automatic_CXX=no module_cmds_CXX= module_expsym_cmds_CXX= link_all_deplibs_CXX=unknown old_archive_cmds_CXX=$old_archive_cmds no_undefined_flag_CXX= whole_archive_flag_spec_CXX= enable_shared_with_static_runtimes_CXX=no # Dependencies to place before and after the object being linked: predep_objects_CXX= postdep_objects_CXX= predeps_CXX= postdeps_CXX= compiler_lib_search_path_CXX= # Source file extension for C++ test sources. ac_ext=cc # Object file extension for compiled C++ test sources. objext=o objext_CXX=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC compiler_CXX=$CC cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' else lt_prog_compiler_no_builtin_flag_CXX= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some GNU ld's only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU ld's only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_CXX= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } ld_shlibs_CXX=yes case $host_os in aix3*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_CXX='' hardcode_direct_CXX=yes hardcode_libdir_separator_CXX=':' link_all_deplibs_CXX=yes if test "$GXX" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_CXX=yes else # We have old collect2 hardcode_direct_CXX=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_CXX=yes hardcode_libdir_flag_spec_CXX='-L$libdir' hardcode_libdir_separator_CXX= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_CXX=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_CXX='-berok' # Determine the default libpath from the value encoded in an empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_CXX="-z nodefs" archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_CXX=' ${wl}-bernotok' allow_undefined_flag_CXX=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols_CXX=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_CXX=' ' archive_cmds_need_lc_CXX=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_CXX='-L$libdir' allow_undefined_flag_CXX=unsupported always_export_symbols_CXX=no enable_shared_with_static_runtimes_CXX=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs_CXX=no fi ;; darwin* | rhapsody*) if test "$GXX" = yes; then archive_cmds_need_lc_CXX=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag_CXX='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_CXX='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_CXX='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag_CXX='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_CXX='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_CXX='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct_CXX=no hardcode_automatic_CXX=yes hardcode_shlibpath_var_CXX=unsupported whole_archive_flag_spec_CXX='-all_load $convenience' link_all_deplibs_CXX=yes else ld_shlibs_CXX=no fi ;; dgux*) case $cc_basename in ec++) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; ghcx) # Green Hills C++ Compiler # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; freebsd12*) # C++ shared libraries reported to be fairly broken before switch to ELF ld_shlibs_CXX=no ;; freebsd-elf*) archive_cmds_need_lc_CXX=no ;; freebsd* | kfreebsd*-gnu) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions ld_shlibs_CXX=yes ;; gnu*) ;; hpux9*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC) archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld_CXX='+b $libdir' hardcode_libdir_separator_CXX=: ;; ia64*) hardcode_libdir_flag_spec_CXX='-L$libdir' ;; *) hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' hardcode_libdir_separator_CXX=: export_dynamic_flag_spec_CXX='${wl}-E' ;; esac fi case "$host_cpu" in hppa*64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no ;; ia64*) hardcode_direct_CXX=no hardcode_shlibpath_var_CXX=no hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; *) hardcode_direct_CXX=yes hardcode_minus_L_CXX=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; aCC) case "$host_cpu" in hppa*64*|ia64*) archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case "$host_cpu" in ia64*|hppa*64*) archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; irix5* | irix6*) case $cc_basename in CC) # SGI C++ archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi link_all_deplibs_CXX=yes ;; esac hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: ;; linux*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc) # Intel C++ with_gnu_ld=yes archive_cmds_need_lc_CXX=no archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' export_dynamic_flag_spec_CXX='${wl}--export-dynamic' whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; cxx) # Compaq C++ archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; esac ;; lynxos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; m88k*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; mvs*) case $cc_basename in cxx) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_direct_CXX=yes hardcode_shlibpath_var_CXX=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; osf3*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx) allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' hardcode_libdir_separator_CXX=: # Archives containing C++ object files must be created using # the KAI C++ compiler. old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; cxx) allow_undefined_flag_CXX=' -expect_unresolved \*' archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ $rm $lib.exp' hardcode_libdir_flag_spec_CXX='-rpath $libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_CXX=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support ld_shlibs_CXX=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; sco*) archive_cmds_need_lc_CXX=no case $cc_basename in CC) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; lcc) # Lucid # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ no_undefined_flag_CXX=' -zdefs' archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' hardcode_libdir_flag_spec_CXX='-R$libdir' hardcode_shlibpath_var_CXX=no case $host_os in solaris2.0-5 | solaris2.0-5.*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system # linker. # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac link_all_deplibs_CXX=yes # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' ;; gcx) # Green Hills C++ Compiler archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then no_undefined_flag_CXX=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' fi ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) archive_cmds_need_lc_CXX=no ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; *) # FIXME: insert proper C++ library support ld_shlibs_CXX=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no GCC_CXX="$GXX" LD_CXX="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no # The `*' in the case matches for architectures that use `case' in # $output_verbose_cmd can trigger glob expansion during the loop # eval without this substitution. output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" for p in `eval $output_verbose_link_cmd`; do case $p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test $p = "-L" \ || test $p = "-R"; then prev=$p continue else prev= fi if test "$pre_test_object_deps_done" = no; then case $p in -L* | -R*) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$compiler_lib_search_path_CXX"; then compiler_lib_search_path_CXX="${prev}${p}" else compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$postdeps_CXX"; then postdeps_CXX="${prev}${p}" else postdeps_CXX="${postdeps_CXX} ${prev}${p}" fi fi ;; *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test "$pre_test_object_deps_done" = no; then if test -z "$predep_objects_CXX"; then predep_objects_CXX="$p" else predep_objects_CXX="$predep_objects_CXX $p" fi else if test -z "$postdep_objects_CXX"; then postdep_objects_CXX="$p" else postdep_objects_CXX="$postdep_objects_CXX $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling CXX test program" fi $rm -f confest.$objext case " $postdeps_CXX " in *" -lc "*) archive_cmds_need_lc_CXX=no ;; esac lt_prog_compiler_wl_CXX= lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_CXX='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_CXX='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all lt_prog_compiler_pic_CXX= ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_CXX=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_CXX='-fPIC' ;; esac else case $host_os in aix4* | aix5*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_CXX='-Bstatic' else lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++) lt_prog_compiler_pic_CXX='-KPIC' ;; ghcx) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; freebsd* | kfreebsd*-gnu) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" if test "$host_cpu" != ia64; then lt_prog_compiler_pic_CXX='+Z' fi ;; aCC) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_CXX='+Z' ;; esac ;; *) ;; esac ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC) lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_static_CXX='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux*) case $cc_basename in KCC) # KAI C++ Compiler lt_prog_compiler_wl_CXX='--backend -Wl,' lt_prog_compiler_pic_CXX='-fPIC' ;; icpc) # Intel C++ lt_prog_compiler_wl_CXX='-Wl,' lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-static' ;; cxx) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx) lt_prog_compiler_pic_CXX='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC) lt_prog_compiler_wl_CXX='--backend -Wl,' ;; RCC) # Rational C++ 2.4.1 lt_prog_compiler_pic_CXX='-pic' ;; cxx) # Digital/Compaq C++ lt_prog_compiler_wl_CXX='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. lt_prog_compiler_pic_CXX= lt_prog_compiler_static_CXX='-non_shared' ;; *) ;; esac ;; psos*) ;; sco*) case $cc_basename in CC) lt_prog_compiler_pic_CXX='-fPIC' ;; *) ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ lt_prog_compiler_pic_CXX='-KPIC' lt_prog_compiler_static_CXX='-Bstatic' lt_prog_compiler_wl_CXX='-Qoption ld ' ;; gcx) # Green Hills C++ Compiler lt_prog_compiler_pic_CXX='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x lt_prog_compiler_pic_CXX='-pic' lt_prog_compiler_static_CXX='-Bstatic' ;; lcc) # Lucid lt_prog_compiler_pic_CXX='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 lt_prog_compiler_pic_CXX='-KPIC' ;; *) ;; esac ;; unixware*) ;; vxworks*) ;; *) lt_prog_compiler_can_build_shared_CXX=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_CXX" >&5 $as_echo "$lt_prog_compiler_pic_CXX" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_CXX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_CXX=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:11105: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:11109: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_pic_works_CXX=yes fi fi $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then case $lt_prog_compiler_pic_CXX in "" | " "*) ;; *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; esac else lt_prog_compiler_pic_CXX= lt_prog_compiler_can_build_shared_CXX=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_CXX= ;; *) lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_CXX=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:11172: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:11176: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o_CXX=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 $as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix4* | aix5*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) export_symbols_cmds_CXX="$ltdll_cmds" ;; cygwin* | mingw*) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 $as_echo "$ld_shlibs_CXX" >&6; } test "$ld_shlibs_CXX" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_CXX" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_CXX=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_CXX in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_CXX compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_CXX allow_undefined_flag_CXX= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc_CXX=no else archive_cmds_need_lc_CXX=yes fi allow_undefined_flag_CXX=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_CXX" >&5 $as_echo "$archive_cmds_need_lc_CXX" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_CXX= if test -n "$hardcode_libdir_flag_spec_CXX" || \ test -n "$runpath_var CXX" || \ test "X$hardcode_automatic_CXX"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_CXX" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && test "$hardcode_minus_L_CXX" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_CXX=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_CXX=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_CXX=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 $as_echo "$hardcode_action_CXX" >&6; } if test "$hardcode_action_CXX" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_cxx_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else ac_fn_cxx_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_cxx_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_CXX \ CC_CXX \ LD_CXX \ lt_prog_compiler_wl_CXX \ lt_prog_compiler_pic_CXX \ lt_prog_compiler_static_CXX \ lt_prog_compiler_no_builtin_flag_CXX \ export_dynamic_flag_spec_CXX \ thread_safe_flag_spec_CXX \ whole_archive_flag_spec_CXX \ enable_shared_with_static_runtimes_CXX \ old_archive_cmds_CXX \ old_archive_from_new_cmds_CXX \ predep_objects_CXX \ postdep_objects_CXX \ predeps_CXX \ postdeps_CXX \ compiler_lib_search_path_CXX \ archive_cmds_CXX \ archive_expsym_cmds_CXX \ postinstall_cmds_CXX \ postuninstall_cmds_CXX \ old_archive_from_expsyms_cmds_CXX \ allow_undefined_flag_CXX \ no_undefined_flag_CXX \ export_symbols_cmds_CXX \ hardcode_libdir_flag_spec_CXX \ hardcode_libdir_flag_spec_ld_CXX \ hardcode_libdir_separator_CXX \ hardcode_automatic_CXX \ module_cmds_CXX \ module_expsym_cmds_CXX \ lt_cv_prog_compiler_c_o_CXX \ exclude_expsyms_CXX \ include_expsyms_CXX; do case $var in old_archive_cmds_CXX | \ old_archive_from_new_cmds_CXX | \ archive_cmds_CXX | \ archive_expsym_cmds_CXX | \ module_cmds_CXX | \ module_expsym_cmds_CXX | \ old_archive_from_expsyms_cmds_CXX | \ export_symbols_cmds_CXX | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_CXX # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_CXX # Is the compiler the GNU C compiler? with_gcc=$GCC_CXX # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_CXX # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP="$STRIP" # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_CXX # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_CXX pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_CXX # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_CXX old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_CXX archive_expsym_cmds=$lt_archive_expsym_cmds_CXX postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_CXX module_expsym_cmds=$lt_module_expsym_cmds_CXX # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_CXX # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_CXX # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_CXX # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_CXX # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_CXX # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_CXX # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_CXX # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_CXX # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_CXX # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_CXX # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_CXX # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_CXX # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_CXX" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_CXX # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_CXX # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_CXX # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_CXX # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld else tagname="" fi ;; F77) if test -n "$F77" && test "X$F77" != "Xno"; then ac_ext=f ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_f77_compiler_gnu archive_cmds_need_lc_F77=no allow_undefined_flag_F77= always_export_symbols_F77=no archive_expsym_cmds_F77= export_dynamic_flag_spec_F77= hardcode_direct_F77=no hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_minus_L_F77=no hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= link_all_deplibs_F77=unknown old_archive_cmds_F77=$old_archive_cmds no_undefined_flag_F77= whole_archive_flag_spec_F77= enable_shared_with_static_runtimes_F77=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o objext_F77=$objext # Code to be used in simple compile tests lt_simple_compile_test_code=" subroutine t\n return\n end\n" # Code to be used in simple link tests lt_simple_link_test_code=" program t\n end\n" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${F77-"f77"} compiler=$CC compiler_F77=$CC cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) test "$enable_shared" = yes && enable_static=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } test "$ld_shlibs_F77" = no && can_build_shared=no GCC_F77="$G77" LD_F77="$LD" lt_prog_compiler_wl_F77= lt_prog_compiler_pic_F77= lt_prog_compiler_static_F77= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_static_F77='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_F77='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_F77=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_F77=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_F77='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_F77='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_F77='-Bstatic' else lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_F77='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_F77='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_F77='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_F77='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_F77='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_F77='-non_shared' ;; newsos6) lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; linux*) case $CC in icc* | ecc*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-static' ;; ccc*) lt_prog_compiler_wl_F77='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_F77='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_F77='-non_shared' ;; sco3.2v5*) lt_prog_compiler_pic_F77='-Kpic' lt_prog_compiler_static_F77='-dn' ;; solaris*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sunos4*) lt_prog_compiler_wl_F77='-Qoption ld ' lt_prog_compiler_pic_F77='-PIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_prog_compiler_wl_F77='-Wl,' lt_prog_compiler_pic_F77='-KPIC' lt_prog_compiler_static_F77='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_F77='-Kconform_pic' lt_prog_compiler_static_F77='-Bstatic' fi ;; uts4*) lt_prog_compiler_pic_F77='-pic' lt_prog_compiler_static_F77='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_F77=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_F77" >&5 $as_echo "$lt_prog_compiler_pic_F77" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_F77"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... " >&6; } if ${lt_cv_prog_compiler_pic_works_F77+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_F77=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_F77" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:13118: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:13122: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_pic_works_F77=yes fi fi $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_F77" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_F77" >&6; } if test x"$lt_cv_prog_compiler_pic_works_F77" = xyes; then case $lt_prog_compiler_pic_F77 in "" | " "*) ;; *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; esac else lt_prog_compiler_pic_F77= lt_prog_compiler_can_build_shared_F77=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_F77= ;; *) lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_F77+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_F77=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:13185: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:13189: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o_F77=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_F77" >&5 $as_echo "$lt_cv_prog_compiler_c_o_F77" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag_F77= enable_shared_with_static_runtimes_F77=no archive_cmds_F77= archive_expsym_cmds_F77= old_archive_From_new_cmds_F77= old_archive_from_expsyms_cmds_F77= export_dynamic_flag_spec_F77= whole_archive_flag_spec_F77= thread_safe_flag_spec_F77= hardcode_libdir_flag_spec_F77= hardcode_libdir_flag_spec_ld_F77= hardcode_libdir_separator_F77= hardcode_direct_F77=no hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=unsupported link_all_deplibs_F77=unknown hardcode_automatic_F77=no module_cmds_F77= module_expsym_cmds_F77= always_export_symbols_F77=no export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_F77= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_F77=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_F77=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_F77=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_F77=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_F77=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_F77='-L$libdir' allow_undefined_flag_F77=unsupported always_export_symbols_F77=no enable_shared_with_static_runtimes_F77=yes export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_F77=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; sunos4*) archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; linux*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_cmds_F77="$tmp_archive_cmds" supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac if test $supports_anon_versioning = yes; then archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' else archive_expsym_cmds_F77="$tmp_archive_cmds" fi else ld_shlibs_F77=no fi ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_F77=no fi ;; esac if test "$ld_shlibs_F77" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_F77='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_F77= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_F77=unsupported always_export_symbols_F77=yes archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_F77=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_F77=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_F77='' hardcode_direct_F77=yes hardcode_libdir_separator_F77=':' link_all_deplibs_F77=yes if test "$GCC" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_F77=yes else # We have old collect2 hardcode_direct_F77=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_F77=yes hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_libdir_separator_F77= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_F77=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_F77='-berok' # Determine the default libpath from the value encoded in an empty executable. cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_F77="-z nodefs" archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat > conftest.$ac_ext <<_ACEOF program main end _ACEOF if ac_fn_f77_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_F77=' ${wl}-bernotok' allow_undefined_flag_F77=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols_F77=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_F77=' ' archive_cmds_need_lc_F77=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes # see comment about different semantics on the GNU ld section ld_shlibs_F77=no ;; bsdi4*) export_dynamic_flag_spec_F77=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_F77=' ' allow_undefined_flag_F77=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_F77='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_F77=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then archive_cmds_need_lc_F77=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag_F77='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_F77='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_F77='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag_F77='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_F77='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_F77='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_F77='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct_F77=no hardcode_automatic_F77=yes hardcode_shlibpath_var_F77=unsupported whole_archive_flag_spec_F77='-all_load $convenience' link_all_deplibs_F77=yes else ld_shlibs_F77=no fi ;; dgux*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; freebsd1*) ld_shlibs_F77=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes export_dynamic_flag_spec_F77='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld_F77='+b $libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=no hardcode_shlibpath_var_F77=no ;; ia64*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=no hardcode_shlibpath_var_F77=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; *) hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_direct_F77=yes export_dynamic_flag_spec_F77='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_F77=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: link_all_deplibs_F77=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no ;; newsos6) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: hardcode_shlibpath_var_F77=no ;; openbsd*) hardcode_direct_F77=yes hardcode_shlibpath_var_F77=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' export_dynamic_flag_spec_F77='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-R$libdir' ;; *) archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_minus_L_F77=yes allow_undefined_flag_F77=unsupported archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_F77=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_F77=' -expect_unresolved \*' archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_F77='-rpath $libdir' fi hardcode_libdir_separator_F77=: ;; sco3.2v5*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag_F77=' -z text' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_F77='-R$libdir' hardcode_shlibpath_var_F77=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_F77=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_direct_F77=yes hardcode_minus_L_F77=yes hardcode_shlibpath_var_F77=no ;; sysv4) case $host_vendor in sni) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_F77='$CC -r -o $output$reload_objs' hardcode_direct_F77=no ;; motorola) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv4.3*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no export_dynamic_flag_spec_F77='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_F77=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_F77=yes fi ;; sysv4.2uw2*) archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_F77=yes hardcode_minus_L_F77=no hardcode_shlibpath_var_F77=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) no_undefined_flag_F77='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_F77='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_F77=no ;; sysv5*) no_undefined_flag_F77=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec_F77= hardcode_shlibpath_var_F77=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_F77='-L$libdir' hardcode_shlibpath_var_F77=no ;; *) ld_shlibs_F77=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_F77" >&5 $as_echo "$ld_shlibs_F77" >&6; } test "$ld_shlibs_F77" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_F77" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_F77=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_F77 in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_F77 compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_F77 allow_undefined_flag_F77= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc_F77=no else archive_cmds_need_lc_F77=yes fi allow_undefined_flag_F77=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_F77" >&5 $as_echo "$archive_cmds_need_lc_F77" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_F77= if test -n "$hardcode_libdir_flag_spec_F77" || \ test -n "$runpath_var F77" || \ test "X$hardcode_automatic_F77"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_F77" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && test "$hardcode_minus_L_F77" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_F77=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_F77=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_F77=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_F77" >&5 $as_echo "$hardcode_action_F77" >&6; } if test "$hardcode_action_F77" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_F77 \ CC_F77 \ LD_F77 \ lt_prog_compiler_wl_F77 \ lt_prog_compiler_pic_F77 \ lt_prog_compiler_static_F77 \ lt_prog_compiler_no_builtin_flag_F77 \ export_dynamic_flag_spec_F77 \ thread_safe_flag_spec_F77 \ whole_archive_flag_spec_F77 \ enable_shared_with_static_runtimes_F77 \ old_archive_cmds_F77 \ old_archive_from_new_cmds_F77 \ predep_objects_F77 \ postdep_objects_F77 \ predeps_F77 \ postdeps_F77 \ compiler_lib_search_path_F77 \ archive_cmds_F77 \ archive_expsym_cmds_F77 \ postinstall_cmds_F77 \ postuninstall_cmds_F77 \ old_archive_from_expsyms_cmds_F77 \ allow_undefined_flag_F77 \ no_undefined_flag_F77 \ export_symbols_cmds_F77 \ hardcode_libdir_flag_spec_F77 \ hardcode_libdir_flag_spec_ld_F77 \ hardcode_libdir_separator_F77 \ hardcode_automatic_F77 \ module_cmds_F77 \ module_expsym_cmds_F77 \ lt_cv_prog_compiler_c_o_F77 \ exclude_expsyms_F77 \ include_expsyms_F77; do case $var in old_archive_cmds_F77 | \ old_archive_from_new_cmds_F77 | \ archive_cmds_F77 | \ archive_expsym_cmds_F77 | \ module_cmds_F77 | \ module_expsym_cmds_F77 | \ old_archive_from_expsyms_cmds_F77 | \ export_symbols_cmds_F77 | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_F77 # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_F77 # Is the compiler the GNU C compiler? with_gcc=$GCC_F77 # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_F77 # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP="$STRIP" # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_F77 # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_F77 pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_F77 # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_F77 old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_F77 archive_expsym_cmds=$lt_archive_expsym_cmds_F77 postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_F77 module_expsym_cmds=$lt_module_expsym_cmds_F77 # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_F77 # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_F77 # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_F77 # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_F77 # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_F77 # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_F77 # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_F77 # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_F77 # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_F77 # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_F77 # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_F77 # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_F77 # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_F77" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_F77 # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_F77 # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_F77 # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_F77 # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; GCJ) if test -n "$GCJ" && test "X$GCJ" != "Xno"; then # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o objext_GCJ=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}\n" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String argv) {}; }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${GCJ-"gcj"} compiler=$CC compiler_GCJ=$CC # GCJ did not exist at the time GCC didn't implicitly link libc in. archive_cmds_need_lc_GCJ=no ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... lt_prog_compiler_no_builtin_flag_GCJ= if test "$GCC" = yes; then lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:15150: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:15154: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl_GCJ= lt_prog_compiler_pic_GCJ= lt_prog_compiler_static_GCJ= { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if test "$GCC" = yes; then lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_static_GCJ='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic_GCJ='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared_GCJ=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic_GCJ=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac ;; *) lt_prog_compiler_pic_GCJ='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl_GCJ='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static_GCJ='-Bstatic' else lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic_GCJ='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl_GCJ='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static_GCJ='-non_shared' ;; newsos6) lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; linux*) case $CC in icc* | ecc*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-static' ;; ccc*) lt_prog_compiler_wl_GCJ='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl_GCJ='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static_GCJ='-non_shared' ;; sco3.2v5*) lt_prog_compiler_pic_GCJ='-Kpic' lt_prog_compiler_static_GCJ='-dn' ;; solaris*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sunos4*) lt_prog_compiler_wl_GCJ='-Qoption ld ' lt_prog_compiler_pic_GCJ='-PIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) lt_prog_compiler_wl_GCJ='-Wl,' lt_prog_compiler_pic_GCJ='-KPIC' lt_prog_compiler_static_GCJ='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic_GCJ='-Kconform_pic' lt_prog_compiler_static_GCJ='-Bstatic' fi ;; uts4*) lt_prog_compiler_pic_GCJ='-pic' lt_prog_compiler_static_GCJ='-Bstatic' ;; *) lt_prog_compiler_can_build_shared_GCJ=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic_GCJ" >&5 $as_echo "$lt_prog_compiler_pic_GCJ" >&6; } # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic_GCJ"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... " >&6; } if ${lt_cv_prog_compiler_pic_works_GCJ+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works_GCJ=no ac_outfile=conftest.$ac_objext printf "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic_GCJ" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:15383: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:15387: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s conftest.err; then lt_cv_prog_compiler_pic_works_GCJ=yes fi fi $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_GCJ" >&5 $as_echo "$lt_cv_prog_compiler_pic_works_GCJ" >&6; } if test x"$lt_cv_prog_compiler_pic_works_GCJ" = xyes; then case $lt_prog_compiler_pic_GCJ in "" | " "*) ;; *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; esac else lt_prog_compiler_pic_GCJ= lt_prog_compiler_can_build_shared_GCJ=no fi fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic_GCJ= ;; *) lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o_GCJ+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o_GCJ=no $rm -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out printf "$lt_simple_compile_test_code" > conftest.$ac_ext # According to Tom Tromey, Ian Lance Taylor reported there are C compilers # that will create temporary files in the current directory regardless of # the output directory. Thus, making CWD read-only will cause this test # to fail, enabling locking or at least warning the user not to do parallel # builds. chmod -w . lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:15450: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:15454: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings if test ! -s out/conftest.err; then lt_cv_prog_compiler_c_o_GCJ=yes fi fi chmod u+w . $rm conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files $rm out/* && rmdir out cd .. rmdir conftest $rm conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 $as_echo "$lt_cv_prog_compiler_c_o_GCJ" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $rm conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag_GCJ= enable_shared_with_static_runtimes_GCJ=no archive_cmds_GCJ= archive_expsym_cmds_GCJ= old_archive_From_new_cmds_GCJ= old_archive_from_expsyms_cmds_GCJ= export_dynamic_flag_spec_GCJ= whole_archive_flag_spec_GCJ= thread_safe_flag_spec_GCJ= hardcode_libdir_flag_spec_GCJ= hardcode_libdir_flag_spec_ld_GCJ= hardcode_libdir_separator_GCJ= hardcode_direct_GCJ=no hardcode_minus_L_GCJ=no hardcode_shlibpath_var_GCJ=unsupported link_all_deplibs_GCJ=unknown hardcode_automatic_GCJ=no module_cmds_GCJ= module_expsym_cmds_GCJ= always_export_symbols_GCJ=no export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms_GCJ= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs_GCJ=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs_GCJ=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. ld_shlibs_GCJ=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then allow_undefined_flag_GCJ=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs_GCJ=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec_GCJ='-L$libdir' allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=no enable_shared_with_static_runtimes_GCJ=yes export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs_GCJ=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; sunos4*) archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; linux*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_cmds_GCJ="$tmp_archive_cmds" supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac if test $supports_anon_versioning = yes; then archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' else archive_expsym_cmds_GCJ="$tmp_archive_cmds" fi else ld_shlibs_GCJ=no fi ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs_GCJ=no fi ;; esac if test "$ld_shlibs_GCJ" = yes; then runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec_GCJ= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag_GCJ=unsupported always_export_symbols_GCJ=yes archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L_GCJ=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct_GCJ=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds_GCJ='' hardcode_direct_GCJ=yes hardcode_libdir_separator_GCJ=':' link_all_deplibs_GCJ=yes if test "$GCC" = yes; then case $host_os in aix4.012|aix4.012.*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 hardcode_direct_GCJ=yes else # We have old collect2 hardcode_direct_GCJ=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L_GCJ=yes hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_libdir_separator_GCJ= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols_GCJ=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag_GCJ='-berok' # Determine the default libpath from the value encoded in an empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag_GCJ="-z nodefs" archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` # Check for a 64-bit object if we didn't find anything. if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'`; fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag_GCJ=' ${wl}-bernotok' allow_undefined_flag_GCJ=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) always_export_symbols_GCJ=yes # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec_GCJ=' ' archive_cmds_need_lc_GCJ=yes # This is similar to how AIX traditionally builds it's shared libraries. archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes # see comment about different semantics on the GNU ld section ld_shlibs_GCJ=no ;; bsdi4*) export_dynamic_flag_spec_GCJ=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec_GCJ=' ' allow_undefined_flag_GCJ=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_From_new_cmds_GCJ='true' # FIXME: Should let the user specify the lib program. old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' enable_shared_with_static_runtimes_GCJ=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then archive_cmds_need_lc_GCJ=no case "$host_os" in rhapsody* | darwin1.[012]) allow_undefined_flag_GCJ='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[012]) allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' ;; 10.*) allow_undefined_flag_GCJ='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_cmds_GCJ='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else archive_cmds_GCJ='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi module_cmds_GCJ='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' hardcode_direct_GCJ=no hardcode_automatic_GCJ=yes hardcode_shlibpath_var_GCJ=unsupported whole_archive_flag_spec_GCJ='-all_load $convenience' link_all_deplibs_GCJ=yes else ld_shlibs_GCJ=no fi ;; dgux*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; freebsd1*) ld_shlibs_GCJ=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no ;; ia64*) hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_direct_GCJ=no hardcode_shlibpath_var_GCJ=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes ;; *) hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_direct_GCJ=yes export_dynamic_flag_spec_GCJ='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L_GCJ=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: link_all_deplibs_GCJ=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; newsos6) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: hardcode_shlibpath_var_GCJ=no ;; openbsd*) hardcode_direct_GCJ=yes hardcode_shlibpath_var_GCJ=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' export_dynamic_flag_spec_GCJ='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-R$libdir' ;; *) archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' ;; esac fi ;; os2*) hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_minus_L_GCJ=yes allow_undefined_flag_GCJ=unsupported archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator_GCJ=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' else allow_undefined_flag_GCJ=' -expect_unresolved \*' archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec_GCJ='-rpath $libdir' fi hardcode_libdir_separator_GCJ=: ;; sco3.2v5*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no export_dynamic_flag_spec_GCJ='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) no_undefined_flag_GCJ=' -z text' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi hardcode_libdir_flag_spec_GCJ='-R$libdir' hardcode_shlibpath_var_GCJ=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; esac link_all_deplibs_GCJ=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=yes hardcode_shlibpath_var_GCJ=no ;; sysv4) case $host_vendor in sni) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds_GCJ='$CC -r -o $output$reload_objs' hardcode_direct_GCJ=no ;; motorola) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_GCJ=no ;; sysv4.3*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no export_dynamic_flag_spec_GCJ='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var_GCJ=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs_GCJ=yes fi ;; sysv4.2uw2*) archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' hardcode_direct_GCJ=yes hardcode_minus_L_GCJ=no hardcode_shlibpath_var_GCJ=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) no_undefined_flag_GCJ='${wl}-z ${wl}text' if test "$GCC" = yes; then archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds_GCJ='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' hardcode_shlibpath_var_GCJ=no ;; sysv5*) no_undefined_flag_GCJ=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' hardcode_libdir_flag_spec_GCJ= hardcode_shlibpath_var_GCJ=no runpath_var='LD_RUN_PATH' ;; uts4*) archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec_GCJ='-L$libdir' hardcode_shlibpath_var_GCJ=no ;; *) ld_shlibs_GCJ=no ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_GCJ" >&5 $as_echo "$ld_shlibs_GCJ" >&6; } test "$ld_shlibs_GCJ" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc_GCJ" in x|xyes) # Assume -lc should be added archive_cmds_need_lc_GCJ=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds_GCJ in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl_GCJ compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ allow_undefined_flag_GCJ= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then archive_cmds_need_lc_GCJ=no else archive_cmds_need_lc_GCJ=yes fi allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc_GCJ" >&5 $as_echo "$archive_cmds_need_lc_GCJ" >&6; } ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } library_names_spec= libname_spec='lib$name' soname_spec= shrext=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix4* | aix5*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi4*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32*) version_type=windows shrext=".dll" need_version=no need_lib_prefix=no case $GCC,$host_os in yes,cygwin* | yes,mingw* | yes,pw32*) library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $rm \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" ;; mingw*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH printed by # mingw gcc, but we are running on Cygwin. Gcc prints its search # path with ; separators, and with drive letters. We can handle the # drive letters (cygwin fileutils understands them), so leave them, # especially as we might pass files found there to a mingw objdump, # which wouldn't understand a cygwinified path. Ahh. sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' ;; esac ;; *) library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' ;; esac dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext='$(test .$module = .yes && echo .so || echo .dylib)' # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. if test "$GCC" = yes; then sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` else sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' fi sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; kfreebsd*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='GNU ld.so' ;; freebsd*) objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.01* | freebsdelf3.01*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; *) # from 3.2 on shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case "$host_cpu" in ia64*) shrext='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555. postinstall_cmds='chmod 555 $lib' ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; nto-qnx*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; openbsd*) version_type=sunos need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; sco3.2v5*) version_type=osf soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no export_dynamic_flag_spec='${wl}-Blargedynsym' runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action_GCJ= if test -n "$hardcode_libdir_flag_spec_GCJ" || \ test -n "$runpath_var GCJ" || \ test "X$hardcode_automatic_GCJ"="Xyes" ; then # We can hardcode non-existant directories. if test "$hardcode_direct_GCJ" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && test "$hardcode_minus_L_GCJ" != no; then # Linking always hardcodes the temporary library directory. hardcode_action_GCJ=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action_GCJ=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action_GCJ=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_GCJ" >&5 $as_echo "$hardcode_action_GCJ" >&6; } if test "$hardcode_action_GCJ" = relink; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then LDFLAGS="$LDFLAGS $link_static_flag" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_GCJ \ CC_GCJ \ LD_GCJ \ lt_prog_compiler_wl_GCJ \ lt_prog_compiler_pic_GCJ \ lt_prog_compiler_static_GCJ \ lt_prog_compiler_no_builtin_flag_GCJ \ export_dynamic_flag_spec_GCJ \ thread_safe_flag_spec_GCJ \ whole_archive_flag_spec_GCJ \ enable_shared_with_static_runtimes_GCJ \ old_archive_cmds_GCJ \ old_archive_from_new_cmds_GCJ \ predep_objects_GCJ \ postdep_objects_GCJ \ predeps_GCJ \ postdeps_GCJ \ compiler_lib_search_path_GCJ \ archive_cmds_GCJ \ archive_expsym_cmds_GCJ \ postinstall_cmds_GCJ \ postuninstall_cmds_GCJ \ old_archive_from_expsyms_cmds_GCJ \ allow_undefined_flag_GCJ \ no_undefined_flag_GCJ \ export_symbols_cmds_GCJ \ hardcode_libdir_flag_spec_GCJ \ hardcode_libdir_flag_spec_ld_GCJ \ hardcode_libdir_separator_GCJ \ hardcode_automatic_GCJ \ module_cmds_GCJ \ module_expsym_cmds_GCJ \ lt_cv_prog_compiler_c_o_GCJ \ exclude_expsyms_GCJ \ include_expsyms_GCJ; do case $var in old_archive_cmds_GCJ | \ old_archive_from_new_cmds_GCJ | \ archive_cmds_GCJ | \ archive_expsym_cmds_GCJ | \ module_cmds_GCJ | \ module_expsym_cmds_GCJ | \ old_archive_from_expsyms_cmds_GCJ | \ export_symbols_cmds_GCJ | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_GCJ # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_GCJ # Is the compiler the GNU C compiler? with_gcc=$GCC_GCJ # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_GCJ # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP="$STRIP" # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_GCJ # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_GCJ pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_GCJ # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_GCJ old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_GCJ archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_GCJ module_expsym_cmds=$lt_module_expsym_cmds_GCJ # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_GCJ # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_GCJ # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_GCJ # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_GCJ # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_GCJ # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_GCJ # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_GCJ # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_GCJ # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_GCJ # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_GCJ # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_GCJ" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_GCJ # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_GCJ # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_GCJ # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_GCJ # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" else tagname="" fi ;; RC) # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o objext_RC=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' # Code to be used in simple link tests lt_simple_link_test_code="$lt_simple_compile_test_code" # ltmain only uses $CC for tagged configurations so make sure $CC is set. # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # Allow CC to be a program name with arguments. compiler=$CC # Allow CC to be a program name with arguments. lt_save_CC="$CC" CC=${RC-"windres"} compiler=$CC compiler_RC=$CC lt_cv_prog_compiler_c_o_RC=yes # The else clause should only fire when bootstrapping the # libtool distribution, otherwise you forgot to ship ltmain.sh # with your package, and you will get complaints that there are # no rules to generate ltmain.sh. if test -f "$ltmain"; then # See if we are running on zsh, and set the options which allow our commands through # without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi # Now quote all the things that may contain metacharacters while being # careful not to overquote the AC_SUBSTed values. We take copies of the # variables and quote the copies for generation of the libtool script. for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ libname_spec library_names_spec soname_spec extract_expsyms_cmds \ old_striplib striplib file_magic_cmd finish_cmds finish_eval \ deplibs_check_method reload_flag reload_cmds need_locks \ lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ old_postinstall_cmds old_postuninstall_cmds \ compiler_RC \ CC_RC \ LD_RC \ lt_prog_compiler_wl_RC \ lt_prog_compiler_pic_RC \ lt_prog_compiler_static_RC \ lt_prog_compiler_no_builtin_flag_RC \ export_dynamic_flag_spec_RC \ thread_safe_flag_spec_RC \ whole_archive_flag_spec_RC \ enable_shared_with_static_runtimes_RC \ old_archive_cmds_RC \ old_archive_from_new_cmds_RC \ predep_objects_RC \ postdep_objects_RC \ predeps_RC \ postdeps_RC \ compiler_lib_search_path_RC \ archive_cmds_RC \ archive_expsym_cmds_RC \ postinstall_cmds_RC \ postuninstall_cmds_RC \ old_archive_from_expsyms_cmds_RC \ allow_undefined_flag_RC \ no_undefined_flag_RC \ export_symbols_cmds_RC \ hardcode_libdir_flag_spec_RC \ hardcode_libdir_flag_spec_ld_RC \ hardcode_libdir_separator_RC \ hardcode_automatic_RC \ module_cmds_RC \ module_expsym_cmds_RC \ lt_cv_prog_compiler_c_o_RC \ exclude_expsyms_RC \ include_expsyms_RC; do case $var in old_archive_cmds_RC | \ old_archive_from_new_cmds_RC | \ archive_cmds_RC | \ archive_expsym_cmds_RC | \ module_cmds_RC | \ module_expsym_cmds_RC | \ old_archive_from_expsyms_cmds_RC | \ export_symbols_cmds_RC | \ extract_expsyms_cmds | reload_cmds | finish_cmds | \ postinstall_cmds | postuninstall_cmds | \ old_postinstall_cmds | old_postuninstall_cmds | \ sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) # Double-quote double-evaled strings. eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" ;; *) eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" ;; esac done case $lt_echo in *'\$0 --fallback-echo"') lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` ;; esac cfgfile="$ofile" cat <<__EOF__ >> "$cfgfile" # ### BEGIN LIBTOOL TAG CONFIG: $tagname # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc_RC # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_compiler_RC # Is the compiler the GNU C compiler? with_gcc=$GCC_RC # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_LD_RC # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP="$STRIP" # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl_RC # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic_RC pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static_RC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_old_archive_cmds_RC old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC # Commands used to build and install a shared archive. archive_cmds=$lt_archive_cmds_RC archive_expsym_cmds=$lt_archive_expsym_cmds_RC postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_module_cmds_RC module_expsym_cmds=$lt_module_expsym_cmds_RC # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_predep_objects_RC # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_postdep_objects_RC # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_predeps_RC # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_postdeps_RC # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_compiler_lib_search_path_RC # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag_RC # Flag that forces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag_RC # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action_RC # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$hardcode_direct_RC # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$hardcode_minus_L_RC # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var_RC # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$hardcode_automatic_RC # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs_RC # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$fix_srcfile_path_RC" # Set to yes if exported symbols are required. always_export_symbols=$always_export_symbols_RC # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds_RC # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms_RC # Symbols that must always be exported. include_expsyms=$lt_include_expsyms_RC # ### END LIBTOOL TAG CONFIG: $tagname __EOF__ else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ;; *) as_fn_error $? "Unsupported tag name: $tagname" "$LINENO" 5 ;; esac # Append the new tag name to the list of available tags. if test -n "$tagname" ; then available_tags="$available_tags $tagname" fi fi done IFS="$lt_save_ifs" # Now substitute the updated list of available tags. if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then mv "${ofile}T" "$ofile" chmod +x "$ofile" else rm -f "${ofile}T" as_fn_error $? "unable to update list of available tagged configurations." "$LINENO" 5 fi fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' # Prevent multiple expansion { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { /* FIXME: Include the comments suggested by Paul. */ #ifndef __cplusplus /* Ultrix mips cc rejects this. */ typedef int charset[2]; const charset cs; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; /* NEC SVR4.0.2 mips cc rejects this. */ struct point {int x, y;}; static struct point const zero = {0,0}; /* AIX XL C 1.02.0.0 rejects this. It does not let you subtract one const X* pointer from another in an arm of an if-expression whose if-part is not a constant expression */ const char *g = "string"; pcpcc = &g + (g ? g-g : 0); /* HPUX 7.0 cc rejects these. */ ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; { /* SCO 3.2v4 cc rejects this. */ char *t; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; if (s) return 0; } { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ int x[] = {25, 17}; const int *foo = &x[0]; ++foo; } { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ typedef const int *iptr; iptr p = 0; ++p; } { /* AIX XL C 1.02.0.0 rejects this saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ struct s { int j; const int *ap[3]; }; struct s *b; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; if (!foo) return 0; } return !cs[0] && !zero.x; #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_const=yes else ac_cv_c_const=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 $as_echo "$ac_cv_c_const" >&6; } if test $ac_cv_c_const = no; then $as_echo "#define const /**/" >>confdefs.h fi ac_header_dirent=no for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 $as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } if eval \${$as_ac_Header+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include <$ac_hdr> int main () { if ((DIR *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$as_ac_Header=yes" else eval "$as_ac_Header=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$as_ac_Header { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 _ACEOF ac_header_dirent=$ac_hdr; break fi done # Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. if test $ac_header_dirent = dirent.h; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' dir; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 $as_echo_n "checking for library containing opendir... " >&6; } if ${ac_cv_search_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF for ac_lib in '' x; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_opendir=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_opendir+:} false; then : break fi done if ${ac_cv_search_opendir+:} false; then : else ac_cv_search_opendir=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 $as_echo "$ac_cv_search_opendir" >&6; } ac_res=$ac_cv_search_opendir if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi # Check whether --enable-ltdl-install was given. if test "${enable_ltdl_install+set}" = set; then : enableval=$enable_ltdl_install; fi if test x"${enable_ltdl_install-no}" != xno; then $as_echo "#define INSTALL_LTDL 1" >>confdefs.h fi if test x"${enable_ltdl_convenience-no}" != xno; then $as_echo "#define CONVENIENCE_LTDL 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking which extension is used for loadable modules" >&5 $as_echo_n "checking which extension is used for loadable modules... " >&6; } if ${libltdl_cv_shlibext+:} false; then : $as_echo_n "(cached) " >&6 else module=yes eval libltdl_cv_shlibext=$shrext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_shlibext" >&5 $as_echo "$libltdl_cv_shlibext" >&6; } if test -n "$libltdl_cv_shlibext"; then cat >>confdefs.h <<_ACEOF #define LTDL_SHLIB_EXT "$libltdl_cv_shlibext" _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variable specifies run-time library path" >&5 $as_echo_n "checking which variable specifies run-time library path... " >&6; } if ${libltdl_cv_shlibpath_var+:} false; then : $as_echo_n "(cached) " >&6 else libltdl_cv_shlibpath_var="$shlibpath_var" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_shlibpath_var" >&5 $as_echo "$libltdl_cv_shlibpath_var" >&6; } if test -n "$libltdl_cv_shlibpath_var"; then cat >>confdefs.h <<_ACEOF #define LTDL_SHLIBPATH_VAR "$libltdl_cv_shlibpath_var" _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the default library search path" >&5 $as_echo_n "checking for the default library search path... " >&6; } if ${libltdl_cv_sys_search_path+:} false; then : $as_echo_n "(cached) " >&6 else libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_sys_search_path" >&5 $as_echo "$libltdl_cv_sys_search_path" >&6; } if test -n "$libltdl_cv_sys_search_path"; then sys_search_path= for dir in $libltdl_cv_sys_search_path; do if test -z "$sys_search_path"; then sys_search_path="$dir" else sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" fi done cat >>confdefs.h <<_ACEOF #define LTDL_SYSSEARCHPATH "$sys_search_path" _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${libltdl_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else libltdl_cv_objdir="$objdir" if test -n "$objdir"; then : else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then libltdl_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. libltdl_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_objdir" >&5 $as_echo "$libltdl_cv_objdir" >&6; } cat >>confdefs.h <<_ACEOF #define LTDL_OBJDIR "$libltdl_cv_objdir/" _ACEOF { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libtool supports -dlopen/-dlpreopen" >&5 $as_echo_n "checking whether libtool supports -dlopen/-dlpreopen... " >&6; } if ${libltdl_cv_preloaded_symbols+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$lt_cv_sys_global_symbol_pipe"; then libltdl_cv_preloaded_symbols=yes else libltdl_cv_preloaded_symbols=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_preloaded_symbols" >&5 $as_echo "$libltdl_cv_preloaded_symbols" >&6; } if test x"$libltdl_cv_preloaded_symbols" = xyes; then $as_echo "#define HAVE_PRELOADED_SYMBOLS 1" >>confdefs.h fi LIBADD_DL= ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : $as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : $as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h LIBADD_DL="$LIBADD_DL -ldld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : $as_echo "#define HAVE_LIBDL 1" >>confdefs.h LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if HAVE_DLFCN_H # include #endif int main () { dlopen(0, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define HAVE_LIBDL 1" >>confdefs.h libltdl_cv_func_dlopen="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : $as_echo "#define HAVE_LIBDL 1" >>confdefs.h LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : $as_echo "#define HAVE_DLD 1" >>confdefs.h LIBADD_DL="$LIBADD_DL -ldld" else ac_fn_c_check_func "$LINENO" "_dyld_func_lookup" "ac_cv_func__dyld_func_lookup" if test "x$ac_cv_func__dyld_func_lookup" = xyes; then : $as_echo "#define HAVE_DYLD 1" >>confdefs.h fi fi fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi fi fi if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes then lt_save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" for ac_func in dlerror do : ac_fn_c_check_func "$LINENO" "dlerror" "ac_cv_func_dlerror" if test "x$ac_cv_func_dlerror" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLERROR 1 _ACEOF fi done LIBS="$lt_save_LIBS" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _ prefix in compiled symbols" >&5 $as_echo_n "checking for _ prefix in compiled symbols... " >&6; } if ${ac_cv_sys_symbol_underscore+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_sys_symbol_underscore=no cat > conftest.$ac_ext <&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. ac_nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist\""; } >&5 (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $ac_nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$ac_nlist"; then # See whether the symbols have a leading underscore. if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then ac_cv_sys_symbol_underscore=yes else if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then : else echo "configure: cannot find nm_test_func in $ac_nlist" >&5 fi fi else echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "configure: failed program was:" >&5 cat conftest.c >&5 fi rm -rf conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_symbol_underscore" >&5 $as_echo "$ac_cv_sys_symbol_underscore" >&6; } if test x"$ac_cv_sys_symbol_underscore" = xyes; then if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have to add an underscore for dlsym" >&5 $as_echo_n "checking whether we have to add an underscore for dlsym... " >&6; } if ${libltdl_cv_need_uscore+:} false; then : $as_echo_n "(cached) " >&6 else libltdl_cv_need_uscore=unknown save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" if test "$cross_compiling" = yes; then : libltdl_cv_need_uscore=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext < #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif #ifdef __cplusplus extern "C" void exit (int); #endif void fnord() { int i=42;} int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; /* dlclose (self); */ } exit (status); } EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) libltdl_cv_need_uscore=no ;; x$lt_dlneed_uscore) libltdl_cv_need_uscore=yes ;; x$lt_unknown|x*) ;; esac else : # compilation failed fi fi rm -fr conftest* LIBS="$save_LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_need_uscore" >&5 $as_echo "$libltdl_cv_need_uscore" >&6; } fi fi if test x"$libltdl_cv_need_uscore" = xyes; then $as_echo "#define NEED_USCORE 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether deplibs are loaded by dlopen" >&5 $as_echo_n "checking whether deplibs are loaded by dlopen... " >&6; } if ${libltdl_cv_sys_dlopen_deplibs+:} false; then : $as_echo_n "(cached) " >&6 else # PORTME does your system automatically load deplibs for dlopen? # or its logical equivalent (e.g. shl_load for HP-UX < 11) # For now, we just catch OSes we know something about -- in the # future, we'll try test this programmatically. libltdl_cv_sys_dlopen_deplibs=unknown case "$host_os" in aix3*|aix4.1.*|aix4.2.*) # Unknown whether this is true for these versions of AIX, but # we want this `case' here to explicitly catch those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; aix[45]*) libltdl_cv_sys_dlopen_deplibs=yes ;; darwin*) # Assuming the user has installed a libdl from somewhere, this is true # If you are looking for one http://www.opendarwin.org/projects/dlcompat libltdl_cv_sys_dlopen_deplibs=yes ;; kfreebsd*-gnu) libltdl_cv_sys_dlopen_deplibs=yes ;; gnu*) libltdl_cv_sys_dlopen_deplibs=yes ;; hpux10*|hpux11*) libltdl_cv_sys_dlopen_deplibs=yes ;; irix[12345]*|irix6.[01]*) # Catch all versions of IRIX before 6.2, and indicate that we don't # know how it worked for any of those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; irix*) # The case above catches anything before 6.2, and it's known that # at 6.2 and later dlopen does load deplibs. libltdl_cv_sys_dlopen_deplibs=yes ;; linux*) libltdl_cv_sys_dlopen_deplibs=yes ;; netbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; openbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; osf[1234]*) # dlopen did load deplibs (at least at 4.x), but until the 5.x series, # it did *not* use an RPATH in a shared library to find objects the # library depends on, so we explictly say `no'. libltdl_cv_sys_dlopen_deplibs=no ;; osf5.0|osf5.0a|osf5.1) # dlopen *does* load deplibs and with the right loader patch applied # it even uses RPATH in a shared library to search for shared objects # that the library depends on, but there's no easy way to know if that # patch is installed. Since this is the case, all we can really # say is unknown -- it depends on the patch being installed. If # it is, this changes to `yes'. Without it, it would be `no'. libltdl_cv_sys_dlopen_deplibs=unknown ;; osf*) # the two cases above should catch all versions of osf <= 5.1. Read # the comments above for what we know about them. # At > 5.1, deplibs are loaded *and* any RPATH in a shared library # is used to find them so we can finally say `yes'. libltdl_cv_sys_dlopen_deplibs=yes ;; solaris*) libltdl_cv_sys_dlopen_deplibs=yes ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libltdl_cv_sys_dlopen_deplibs" >&5 $as_echo "$libltdl_cv_sys_dlopen_deplibs" >&6; } if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then $as_echo "#define LTDL_DLOPEN_DEPLIBS 1" >>confdefs.h fi for ac_header in argz.h do : ac_fn_c_check_header_mongrel "$LINENO" "argz.h" "ac_cv_header_argz_h" "$ac_includes_default" if test "x$ac_cv_header_argz_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ARGZ_H 1 _ACEOF fi done ac_fn_c_check_type "$LINENO" "error_t" "ac_cv_type_error_t" "#if HAVE_ARGZ_H # include #endif " if test "x$ac_cv_type_error_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ERROR_T 1 _ACEOF else $as_echo "#define error_t int" >>confdefs.h fi for ac_func in argz_append argz_create_sep argz_insert argz_next argz_stringify do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ stdio.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dl.h sys/dl.h dld.h mach-o/dyld.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in string.h strings.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF break fi done for ac_func in strchr index do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF break fi done for ac_func in strrchr rindex do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF break fi done for ac_func in memcpy bcopy do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF break fi done for ac_func in memmove strcmp do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in closedir opendir readdir do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done fi # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKGCONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKGCONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKGCONFIG="$PKGCONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_PKGCONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_PKGCONFIG" && ac_cv_path_PKGCONFIG="not_found" ;; esac fi PKGCONFIG=$ac_cv_path_PKGCONFIG if test -n "$PKGCONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5 $as_echo "$PKGCONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$PKGCONFIG" = not_found; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X" >&5 $as_echo_n "checking for X... " >&6; } # Check whether --with-x was given. if test "${with_x+set}" = set; then : withval=$with_x; fi # $have_x is `yes', `no', `disabled', or empty when we do not yet know. if test "x$with_x" = xno; then # The user explicitly disabled X. have_x=disabled else case $x_includes,$x_libraries in #( *\'*) as_fn_error $? "cannot use X directory names containing '" "$LINENO" 5;; #( *,NONE | NONE,*) if ${ac_cv_have_x+:} false; then : $as_echo_n "(cached) " >&6 else # One or both of the vars are not set, and there is no cached value. ac_x_includes=no ac_x_libraries=no rm -f -r conftest.dir if mkdir conftest.dir; then cd conftest.dir cat >Imakefile <<'_ACEOF' incroot: @echo incroot='${INCROOT}' usrlibdir: @echo usrlibdir='${USRLIBDIR}' libdir: @echo libdir='${LIBDIR}' _ACEOF if (export CC; ${XMKMF-xmkmf}) >/dev/null 2>/dev/null && test -f Makefile; then # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. for ac_var in incroot usrlibdir libdir; do eval "ac_im_$ac_var=\`\${MAKE-make} $ac_var 2>/dev/null | sed -n 's/^$ac_var=//p'\`" done # Open Windows xmkmf reportedly sets LIBDIR instead of USRLIBDIR. for ac_extension in a so sl dylib la dll; do if test ! -f "$ac_im_usrlibdir/libX11.$ac_extension" && test -f "$ac_im_libdir/libX11.$ac_extension"; then ac_im_usrlibdir=$ac_im_libdir; break fi done # Screen out bogus values from the imake configuration. They are # bogus both because they are the default anyway, and because # using them would break gcc on systems where it needs fixed includes. case $ac_im_incroot in /usr/include) ac_x_includes= ;; *) test -f "$ac_im_incroot/X11/Xos.h" && ac_x_includes=$ac_im_incroot;; esac case $ac_im_usrlibdir in /usr/lib | /usr/lib64 | /lib | /lib64) ;; *) test -d "$ac_im_usrlibdir" && ac_x_libraries=$ac_im_usrlibdir ;; esac fi cd .. rm -f -r conftest.dir fi # Standard set of common directories for X headers. # Check X11 before X11Rn because it is often a symlink to the current release. ac_x_header_dirs=' /usr/X11/include /usr/X11R7/include /usr/X11R6/include /usr/X11R5/include /usr/X11R4/include /usr/include/X11 /usr/include/X11R7 /usr/include/X11R6 /usr/include/X11R5 /usr/include/X11R4 /usr/local/X11/include /usr/local/X11R7/include /usr/local/X11R6/include /usr/local/X11R5/include /usr/local/X11R4/include /usr/local/include/X11 /usr/local/include/X11R7 /usr/local/include/X11R6 /usr/local/include/X11R5 /usr/local/include/X11R4 /usr/X386/include /usr/x386/include /usr/XFree86/include/X11 /usr/include /usr/local/include /usr/unsupported/include /usr/athena/include /usr/local/x11r5/include /usr/lpp/Xamples/include /usr/openwin/include /usr/openwin/share/include' if test "$ac_x_includes" = no; then # Guess where to find include files, by looking for Xlib.h. # First, try using that file with no special directory specified. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # We can compile using X headers with no special include directory. ac_x_includes= else for ac_dir in $ac_x_header_dirs; do if test -r "$ac_dir/X11/Xlib.h"; then ac_x_includes=$ac_dir break fi done fi rm -f conftest.err conftest.i conftest.$ac_ext fi # $ac_x_includes = no if test "$ac_x_libraries" = no; then # Check for the libraries. # See if we find them without any special options. # Don't add to $LIBS permanently. ac_save_LIBS=$LIBS LIBS="-lX11 $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { XrmInitialize () ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : LIBS=$ac_save_LIBS # We can link X programs with no special library path. ac_x_libraries= else LIBS=$ac_save_LIBS for ac_dir in `$as_echo "$ac_x_includes $ac_x_header_dirs" | sed s/include/lib/g` do # Don't even attempt the hair of trying to link an X program! for ac_extension in a so sl dylib la dll; do if test -r "$ac_dir/libX11.$ac_extension"; then ac_x_libraries=$ac_dir break 2 fi done done fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi # $ac_x_libraries = no case $ac_x_includes,$ac_x_libraries in #( no,* | *,no | *\'*) # Didn't find X, or a directory has "'" in its name. ac_cv_have_x="have_x=no";; #( *) # Record where we found X for the cache. ac_cv_have_x="have_x=yes\ ac_x_includes='$ac_x_includes'\ ac_x_libraries='$ac_x_libraries'" esac fi ;; #( *) have_x=yes;; esac eval "$ac_cv_have_x" fi # $with_x != no if test "$have_x" != yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_x" >&5 $as_echo "$have_x" >&6; } no_x=yes else # If each of the values was on the command line, it overrides each guess. test "x$x_includes" = xNONE && x_includes=$ac_x_includes test "x$x_libraries" = xNONE && x_libraries=$ac_x_libraries # Update the cache value to reflect the command line values. ac_cv_have_x="have_x=yes\ ac_x_includes='$x_includes'\ ac_x_libraries='$x_libraries'" { $as_echo "$as_me:${as_lineno-$LINENO}: result: libraries $x_libraries, headers $x_includes" >&5 $as_echo "libraries $x_libraries, headers $x_includes" >&6; } fi if test "$no_x" = yes; then # Not all programs may use this symbol, but it does not hurt to define it. $as_echo "#define X_DISPLAY_MISSING 1" >>confdefs.h X_CFLAGS= X_PRE_LIBS= X_LIBS= X_EXTRA_LIBS= else if test -n "$x_includes"; then X_CFLAGS="$X_CFLAGS -I$x_includes" fi # It would also be nice to do this for all -L options, not just this one. if test -n "$x_libraries"; then X_LIBS="$X_LIBS -L$x_libraries" # For Solaris; some versions of Sun CC require a space after -R and # others require no space. Words are not sufficient . . . . { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -R must be followed by a space" >&5 $as_echo_n "checking whether -R must be followed by a space... " >&6; } ac_xsave_LIBS=$LIBS; LIBS="$LIBS -R$x_libraries" ac_xsave_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } X_LIBS="$X_LIBS -R$x_libraries" else LIBS="$ac_xsave_LIBS -R $x_libraries" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } X_LIBS="$X_LIBS -R $x_libraries" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: neither works" >&5 $as_echo "neither works" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_c_werror_flag=$ac_xsave_c_werror_flag LIBS=$ac_xsave_LIBS fi # Check for system-dependent libraries X programs must link with. # Do this before checking for the system-independent R6 libraries # (-lICE), since we may need -lsocket or whatever for X linking. if test "$ISC" = yes; then X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl_s -linet" else # Martyn Johnson says this is needed for Ultrix, if the X # libraries were built with DECnet support. And Karl Berry says # the Alpha needs dnet_stub (dnet does not exist). ac_xsave_LIBS="$LIBS"; LIBS="$LIBS $X_LIBS -lX11" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char XOpenDisplay (); int main () { return XOpenDisplay (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet... " >&6; } if ${ac_cv_lib_dnet_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnet_dnet_ntoa=yes else ac_cv_lib_dnet_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet" fi if test $ac_cv_lib_dnet_dnet_ntoa = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dnet_ntoa in -ldnet_stub" >&5 $as_echo_n "checking for dnet_ntoa in -ldnet_stub... " >&6; } if ${ac_cv_lib_dnet_stub_dnet_ntoa+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldnet_stub $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dnet_ntoa (); int main () { return dnet_ntoa (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dnet_stub_dnet_ntoa=yes else ac_cv_lib_dnet_stub_dnet_ntoa=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dnet_stub_dnet_ntoa" >&5 $as_echo "$ac_cv_lib_dnet_stub_dnet_ntoa" >&6; } if test "x$ac_cv_lib_dnet_stub_dnet_ntoa" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -ldnet_stub" fi fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$ac_xsave_LIBS" # msh@cis.ufl.edu says -lnsl (and -lsocket) are needed for his 386/AT, # to get the SysV transport functions. # Chad R. Larson says the Pyramis MIS-ES running DC/OSx (SVR4) # needs -lnsl. # The nsl library prevents programs from opening the X display # on Irix 5.2, according to T.E. Dickey. # The functions gethostbyname, getservbyname, and inet_addr are # in -lbsd on LynxOS 3.0.1/i386, according to Lars Hecking. ac_fn_c_check_func "$LINENO" "gethostbyname" "ac_cv_func_gethostbyname" if test "x$ac_cv_func_gethostbyname" = xyes; then : fi if test $ac_cv_func_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lnsl" >&5 $as_echo_n "checking for gethostbyname in -lnsl... " >&6; } if ${ac_cv_lib_nsl_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lnsl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_nsl_gethostbyname=yes else ac_cv_lib_nsl_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_gethostbyname" >&5 $as_echo "$ac_cv_lib_nsl_gethostbyname" >&6; } if test "x$ac_cv_lib_nsl_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lnsl" fi if test $ac_cv_lib_nsl_gethostbyname = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gethostbyname in -lbsd" >&5 $as_echo_n "checking for gethostbyname in -lbsd... " >&6; } if ${ac_cv_lib_bsd_gethostbyname+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gethostbyname (); int main () { return gethostbyname (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bsd_gethostbyname=yes else ac_cv_lib_bsd_gethostbyname=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_gethostbyname" >&5 $as_echo "$ac_cv_lib_bsd_gethostbyname" >&6; } if test "x$ac_cv_lib_bsd_gethostbyname" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lbsd" fi fi fi # lieder@skyler.mavd.honeywell.com says without -lsocket, # socket/setsockopt and other routines are undefined under SCO ODT # 2.0. But -lsocket is broken on IRIX 5.2 (and is not necessary # on later versions), says Simon Leinen: it contains gethostby* # variants that don't use the name server (or something). -lsocket # must be given before -lnsl if both are needed. We assume that # if connect needs -lnsl, so does gethostbyname. ac_fn_c_check_func "$LINENO" "connect" "ac_cv_func_connect" if test "x$ac_cv_func_connect" = xyes; then : fi if test $ac_cv_func_connect = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for connect in -lsocket" >&5 $as_echo_n "checking for connect in -lsocket... " >&6; } if ${ac_cv_lib_socket_connect+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char connect (); int main () { return connect (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_connect=yes else ac_cv_lib_socket_connect=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_connect" >&5 $as_echo "$ac_cv_lib_socket_connect" >&6; } if test "x$ac_cv_lib_socket_connect" = xyes; then : X_EXTRA_LIBS="-lsocket $X_EXTRA_LIBS" fi fi # Guillermo Gomez says -lposix is necessary on A/UX. ac_fn_c_check_func "$LINENO" "remove" "ac_cv_func_remove" if test "x$ac_cv_func_remove" = xyes; then : fi if test $ac_cv_func_remove = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for remove in -lposix" >&5 $as_echo_n "checking for remove in -lposix... " >&6; } if ${ac_cv_lib_posix_remove+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lposix $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char remove (); int main () { return remove (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_posix_remove=yes else ac_cv_lib_posix_remove=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_posix_remove" >&5 $as_echo "$ac_cv_lib_posix_remove" >&6; } if test "x$ac_cv_lib_posix_remove" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lposix" fi fi # BSDI BSD/OS 2.1 needs -lipc for XOpenDisplay. ac_fn_c_check_func "$LINENO" "shmat" "ac_cv_func_shmat" if test "x$ac_cv_func_shmat" = xyes; then : fi if test $ac_cv_func_shmat = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmat in -lipc" >&5 $as_echo_n "checking for shmat in -lipc... " >&6; } if ${ac_cv_lib_ipc_shmat+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lipc $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shmat (); int main () { return shmat (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ipc_shmat=yes else ac_cv_lib_ipc_shmat=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ipc_shmat" >&5 $as_echo "$ac_cv_lib_ipc_shmat" >&6; } if test "x$ac_cv_lib_ipc_shmat" = xyes; then : X_EXTRA_LIBS="$X_EXTRA_LIBS -lipc" fi fi fi # Check for libraries that X11R6 Xt/Xaw programs need. ac_save_LDFLAGS=$LDFLAGS test -n "$x_libraries" && LDFLAGS="$LDFLAGS -L$x_libraries" # SM needs ICE to (dynamically) link under SunOS 4.x (so we have to # check for ICE first), but we must link in the order -lSM -lICE or # we get undefined symbols. So assume we have SM if we have ICE. # These have to be linked with before -lX11, unlike the other # libraries we check for below, so use a different variable. # John Interrante, Karl Berry { $as_echo "$as_me:${as_lineno-$LINENO}: checking for IceConnectionNumber in -lICE" >&5 $as_echo_n "checking for IceConnectionNumber in -lICE... " >&6; } if ${ac_cv_lib_ICE_IceConnectionNumber+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lICE $X_EXTRA_LIBS $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char IceConnectionNumber (); int main () { return IceConnectionNumber (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ICE_IceConnectionNumber=yes else ac_cv_lib_ICE_IceConnectionNumber=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ICE_IceConnectionNumber" >&5 $as_echo "$ac_cv_lib_ICE_IceConnectionNumber" >&6; } if test "x$ac_cv_lib_ICE_IceConnectionNumber" = xyes; then : X_PRE_LIBS="$X_PRE_LIBS -lSM -lICE" fi LDFLAGS=$ac_save_LDFLAGS fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5 $as_echo_n "checking whether byte ordering is bigendian... " >&6; } if ${ac_cv_c_bigendian+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_bigendian=unknown # See if we're dealing with a universal compiler. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __APPLE_CC__ not a universal capable compiler #endif typedef int dummy; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # Check for potential -arch flags. It is not universal unless # there are at least two -arch flags with different values. ac_arch= ac_prev= for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do if test -n "$ac_prev"; then case $ac_word in i?86 | x86_64 | ppc | ppc64) if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then ac_arch=$ac_word else ac_cv_c_bigendian=universal break fi ;; esac ac_prev= elif test "x$ac_word" = "x-arch"; then ac_prev=arch fi done fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_c_bigendian = unknown; then # See if sys/param.h defines the BYTE_ORDER macro. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if ! (defined BYTE_ORDER && defined BIG_ENDIAN \ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \ && LITTLE_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # See if defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris). cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN) bogus endian macros #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : # It does; now see whether it defined to _BIG_ENDIAN or not. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { #ifndef _BIG_ENDIAN not big endian #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_bigendian=yes else ac_cv_c_bigendian=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test $ac_cv_c_bigendian = unknown; then # Compile a test program. if test "$cross_compiling" = yes; then : # Try to guess by grepping values from an object file. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 }; short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 }; int use_ascii (int i) { return ascii_mm[i] + ascii_ii[i]; } short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 }; short int ebcdic_mm[] = { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 }; int use_ebcdic (int i) { return ebcdic_mm[i] + ebcdic_ii[i]; } extern int foo; int main () { return use_ascii (foo) == use_ebcdic (foo); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then ac_cv_c_bigendian=yes fi if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then if test "$ac_cv_c_bigendian" = unknown; then ac_cv_c_bigendian=no else # finding both strings is unlikely to happen, but who knows? ac_cv_c_bigendian=unknown fi fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* Are we little or big endian? From Harbison&Steele. */ union { long int l; char c[sizeof (long int)]; } u; u.l = 1; return u.c[sizeof (long int) - 1] == 1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_c_bigendian=no else ac_cv_c_bigendian=yes fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5 $as_echo "$ac_cv_c_bigendian" >&6; } case $ac_cv_c_bigendian in #( yes) $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h ;; #( no) ;; #( universal) $as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h ;; #( *) as_fn_error $? "unknown endianness presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 $as_echo_n "checking for inline... " >&6; } if ${ac_cv_c_inline+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_c_inline=no for ac_kw in inline __inline__ __inline; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifndef __cplusplus typedef int foo_t; static $ac_kw foo_t static_foo () {return 0; } $ac_kw foo_t foo () {return 0; } #endif _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_c_inline=$ac_kw fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext test "$ac_cv_c_inline" != no && break done fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 $as_echo "$ac_cv_c_inline" >&6; } case $ac_cv_c_inline in inline | yes) ;; *) case $ac_cv_c_inline in no) ac_val=;; *) ac_val=$ac_cv_c_inline;; esac cat >>confdefs.h <<_ACEOF #ifndef __cplusplus #define inline $ac_val #endif _ACEOF ;; esac # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned char" >&5 $as_echo_n "checking size of unsigned char... " >&6; } if ${ac_cv_sizeof_unsigned_char+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned char))" "ac_cv_sizeof_unsigned_char" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_char" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned char) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_char=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_char" >&5 $as_echo "$ac_cv_sizeof_unsigned_char" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_CHAR $ac_cv_sizeof_unsigned_char _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short" >&5 $as_echo_n "checking size of unsigned short... " >&6; } if ${ac_cv_sizeof_unsigned_short+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned short))" "ac_cv_sizeof_unsigned_short" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_short" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned short) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_short=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_short" >&5 $as_echo "$ac_cv_sizeof_unsigned_short" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_SHORT $ac_cv_sizeof_unsigned_short _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5 $as_echo_n "checking size of unsigned int... " >&6; } if ${ac_cv_sizeof_unsigned_int+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_int" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned int) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_int=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5 $as_echo "$ac_cv_sizeof_unsigned_int" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5 $as_echo_n "checking size of unsigned long... " >&6; } if ${ac_cv_sizeof_unsigned_long+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5 $as_echo "$ac_cv_sizeof_unsigned_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5 $as_echo_n "checking size of unsigned long long... " >&6; } if ${ac_cv_sizeof_unsigned_long_long+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long" "$ac_includes_default"; then : else if test "$ac_cv_type_unsigned_long_long" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (unsigned long long) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_unsigned_long_long=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5 $as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long _ACEOF # The cast to long int works around a bug in the HP C Compiler # version HP92453-01 B.11.11.23709.GP, which incorrectly rejects # declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. # This bug is HP SR number 8606223364. { $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int *" >&5 $as_echo_n "checking size of int *... " >&6; } if ${ac_cv_sizeof_int_p+:} false; then : $as_echo_n "(cached) " >&6 else if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int *))" "ac_cv_sizeof_int_p" "$ac_includes_default"; then : else if test "$ac_cv_type_int_p" = yes; then { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "cannot compute sizeof (int *) See \`config.log' for more details" "$LINENO" 5; } else ac_cv_sizeof_int_p=0 fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int_p" >&5 $as_echo "$ac_cv_sizeof_int_p" >&6; } cat >>confdefs.h <<_ACEOF #define SIZEOF_INT_P $ac_cv_sizeof_int_p _ACEOF for ac_func in getenv do : ac_fn_c_check_func "$LINENO" "getenv" "ac_cv_func_getenv" if test "x$ac_cv_func_getenv" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETENV 1 _ACEOF $as_echo "#define BX_HAVE_GETENV 1" >>confdefs.h fi done for ac_func in setenv do : ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv" if test "x$ac_cv_func_setenv" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SETENV 1 _ACEOF $as_echo "#define BX_HAVE_SETENV 1" >>confdefs.h fi done for ac_func in snprintf do : ac_fn_c_check_func "$LINENO" "snprintf" "ac_cv_func_snprintf" if test "x$ac_cv_func_snprintf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SNPRINTF 1 _ACEOF $as_echo "#define BX_HAVE_SNPRINTF 1" >>confdefs.h fi done for ac_func in vsnprintf do : ac_fn_c_check_func "$LINENO" "vsnprintf" "ac_cv_func_vsnprintf" if test "x$ac_cv_func_vsnprintf" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VSNPRINTF 1 _ACEOF $as_echo "#define BX_HAVE_VSNPRINTF 1" >>confdefs.h fi done if test "$MSVC_TARGET" != 1; then for ac_func in select do : ac_fn_c_check_func "$LINENO" "select" "ac_cv_func_select" if test "x$ac_cv_func_select" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SELECT 1 _ACEOF $as_echo "#define BX_HAVE_SELECT 1" >>confdefs.h fi done ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "#include #include " if test "x$ac_cv_type_socklen_t" = xyes; then : $as_echo "#define BX_HAVE_SOCKLEN_T 1" >>confdefs.h fi for ac_func in strtoull do : ac_fn_c_check_func "$LINENO" "strtoull" "ac_cv_func_strtoull" if test "x$ac_cv_func_strtoull" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRTOULL 1 _ACEOF $as_echo "#define BX_HAVE_STRTOULL 1" >>confdefs.h fi done for ac_func in strtouq do : ac_fn_c_check_func "$LINENO" "strtouq" "ac_cv_func_strtouq" if test "x$ac_cv_func_strtouq" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRTOUQ 1 _ACEOF $as_echo "#define BX_HAVE_STRTOUQ 1" >>confdefs.h fi done for ac_func in strdup do : ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" if test "x$ac_cv_func_strdup" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRDUP 1 _ACEOF $as_echo "#define BX_HAVE_STRDUP 1" >>confdefs.h fi done for ac_func in strrev do : ac_fn_c_check_func "$LINENO" "strrev" "ac_cv_func_strrev" if test "x$ac_cv_func_strrev" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRREV 1 _ACEOF $as_echo "#define BX_HAVE_STRREV 1" >>confdefs.h fi done for ac_func in stricmp do : ac_fn_c_check_func "$LINENO" "stricmp" "ac_cv_func_stricmp" if test "x$ac_cv_func_stricmp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRICMP 1 _ACEOF $as_echo "#define BX_HAVE_STRICMP 1" >>confdefs.h fi done for ac_func in strcasecmp do : ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp" if test "x$ac_cv_func_strcasecmp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRCASECMP 1 _ACEOF $as_echo "#define BX_HAVE_STRCASECMP 1" >>confdefs.h fi done for ac_func in mkstemp do : ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp" if test "x$ac_cv_func_mkstemp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MKSTEMP 1 _ACEOF $as_echo "#define BX_HAVE_MKSTEMP 1" >>confdefs.h fi done ac_fn_c_check_header_mongrel "$LINENO" "sys/mman.h" "ac_cv_header_sys_mman_h" "$ac_includes_default" if test "x$ac_cv_header_sys_mman_h" = xyes; then : $as_echo "#define BX_HAVE_SYS_MMAN_H 1" >>confdefs.h fi for ac_func in gettimeofday do : ac_fn_c_check_func "$LINENO" "gettimeofday" "ac_cv_func_gettimeofday" if test "x$ac_cv_func_gettimeofday" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GETTIMEOFDAY 1 _ACEOF $as_echo "#define BX_HAVE_GETTIMEOFDAY 1" >>confdefs.h fi done for ac_func in usleep do : ac_fn_c_check_func "$LINENO" "usleep" "ac_cv_func_usleep" if test "x$ac_cv_func_usleep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_USLEEP 1 _ACEOF $as_echo "#define BX_HAVE_USLEEP 1" >>confdefs.h fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap32" >&5 $as_echo_n "checking for __builtin_bswap32... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { __builtin_bswap32(0x12345678); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define BX_HAVE___BUILTIN_BSWAP32 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __builtin_bswap64" >&5 $as_echo_n "checking for __builtin_bswap64... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { __builtin_bswap64(0x12345678); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : $as_echo "#define BX_HAVE___BUILTIN_BSWAP64 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext for ac_func in tmpfile64 do : ac_fn_c_check_func "$LINENO" "tmpfile64" "ac_cv_func_tmpfile64" if test "x$ac_cv_func_tmpfile64" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TMPFILE64 1 _ACEOF $as_echo "#define BX_HAVE_TMPFILE64 1" >>confdefs.h fi done for ac_func in fseek64 do : ac_fn_c_check_func "$LINENO" "fseek64" "ac_cv_func_fseek64" if test "x$ac_cv_func_fseek64" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FSEEK64 1 _ACEOF $as_echo "#define BX_HAVE_FSEEK64 1" >>confdefs.h fi done for ac_func in fseeko64 do : ac_fn_c_check_func "$LINENO" "fseeko64" "ac_cv_func_fseeko64" if test "x$ac_cv_func_fseeko64" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FSEEKO64 1 _ACEOF $as_echo "#define BX_HAVE_FSEEKO64 1" >>confdefs.h fi done else $as_echo "#define BX_HAVE_SELECT 1" >>confdefs.h $as_echo "#define BX_HAVE_SOCKLEN_T 0" >>confdefs.h $as_echo "#define BX_HAVE_STRTOULL 1" >>confdefs.h $as_echo "#define BX_HAVE_STRTOUQ 0" >>confdefs.h $as_echo "#define BX_HAVE_STRDUP 1" >>confdefs.h $as_echo "#define BX_HAVE_STRREV 1" >>confdefs.h $as_echo "#define BX_HAVE_STRICMP 1" >>confdefs.h $as_echo "#define BX_HAVE_STRCASECMP 0" >>confdefs.h $as_echo "#define BX_HAVE_MKSTEMP 0" >>confdefs.h $as_echo "#define BX_HAVE_SYS_MMAN_H 0" >>confdefs.h $as_echo "#define BX_HAVE_GETTIMEOFDAY 0" >>confdefs.h $as_echo "#define BX_HAVE_USLEEP 0" >>confdefs.h $as_echo "#define BX_HAVE___BUILTIN_BSWAP32 0" >>confdefs.h $as_echo "#define BX_HAVE___BUILTIN_BSWAP64 0" >>confdefs.h $as_echo "#define BX_HAVE_TMPFILE64 0" >>confdefs.h $as_echo "#define BX_HAVE_FSEEK64 0" >>confdefs.h $as_echo "#define BX_HAVE_FSEEKO64 0" >>confdefs.h fi for ac_func in sleep do : ac_fn_c_check_func "$LINENO" "sleep" "ac_cv_func_sleep" if test "x$ac_cv_func_sleep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SLEEP 1 _ACEOF $as_echo "#define BX_HAVE_SLEEP 1" >>confdefs.h fi done for ac_func in nanosleep do : ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep" if test "x$ac_cv_func_nanosleep" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_NANOSLEEP 1 _ACEOF $as_echo "#define BX_HAVE_NANOSLEEP 1" >>confdefs.h fi done for ac_func in abort do : ac_fn_c_check_func "$LINENO" "abort" "ac_cv_func_abort" if test "x$ac_cv_func_abort" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_ABORT 1 _ACEOF $as_echo "#define BX_HAVE_ABORT 1" >>confdefs.h fi done ac_fn_c_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" "#include #include " if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes; then : $as_echo "#define BX_HAVE_SOCKADDR_IN_SIN_LEN 1" >>confdefs.h fi for ac_func in timelocal do : ac_fn_c_check_func "$LINENO" "timelocal" "ac_cv_func_timelocal" if test "x$ac_cv_func_timelocal" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_TIMELOCAL 1 _ACEOF $as_echo "#define BX_HAVE_TIMELOCAL 1" >>confdefs.h fi done for ac_func in gmtime do : ac_fn_c_check_func "$LINENO" "gmtime" "ac_cv_func_gmtime" if test "x$ac_cv_func_gmtime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GMTIME 1 _ACEOF $as_echo "#define BX_HAVE_GMTIME 1" >>confdefs.h fi done for ac_func in mktime do : ac_fn_c_check_func "$LINENO" "mktime" "ac_cv_func_mktime" if test "x$ac_cv_func_mktime" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MKTIME 1 _ACEOF $as_echo "#define BX_HAVE_MKTIME 1" >>confdefs.h fi done # Check whether --enable-largefile was given. if test "${enable_largefile+set}" = set; then : enableval=$enable_largefile; fi if test "$enable_largefile" != no; then wx_largefile=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 $as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } if ${ac_cv_sys_file_offset_bits+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _FILE_OFFSET_BITS 64 #include int main () { typedef struct { unsigned int field: sizeof(off_t) == 8; } wxlf; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_file_offset_bits=64 else ac_cv_sys_file_offset_bits=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 $as_echo "$ac_cv_sys_file_offset_bits" >&6; } if test "$ac_cv_sys_file_offset_bits" != no; then wx_largefile=yes cat >>confdefs.h <<_ACEOF #define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits _ACEOF fi if test "x$wx_largefile" != "xyes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 $as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } if ${ac_cv_sys_large_files+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #define _LARGE_FILES 1 #include int main () { typedef struct { unsigned int field: sizeof(off_t) == 8; } wxlf; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_sys_large_files=1 else ac_cv_sys_large_files=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 $as_echo "$ac_cv_sys_large_files" >&6; } if test "$ac_cv_sys_large_files" != no; then wx_largefile=yes cat >>confdefs.h <<_ACEOF #define _LARGE_FILES $ac_cv_sys_large_files _ACEOF fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if large file support is available" >&5 $as_echo_n "checking if large file support is available... " >&6; } if test "x$wx_largefile" = "xyes"; then $as_echo "#define HAVE_LARGEFILE_SUPPORT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $wx_largefile" >&5 $as_echo "$wx_largefile" >&6; } fi case "x$ac_cv_sys_file_offset_bits" in #( xno | xunknown) ;; *) if test "x$ac_cv_sys_file_offset_bits" = "x64"; then BX_LARGEFILE_FLAGS="-D_FILE_OFFSET_BITS=64 -D_LARGE_FILES" else BX_LARGEFILE_FLAGS="-D_LARGE_FILES" fi CPPFLAGS="$CPPFLAGS $BX_LARGEFILE_FLAGS" CFLAGS="$CFLAGS $BX_LARGEFILE_FLAGS" CXXFLAGS="$CXXFLAGS $BX_LARGEFILE_FLAGS" ;; esac have_cos=0 have_floor=0 for ac_func in cos do : ac_fn_c_check_func "$LINENO" "cos" "ac_cv_func_cos" if test "x$ac_cv_func_cos" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_COS 1 _ACEOF have_cos=1 fi done for ac_func in floor do : ac_fn_c_check_func "$LINENO" "floor" "ac_cv_func_floor" if test "x$ac_cv_func_floor" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FLOOR 1 _ACEOF have_floor=1 fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking if math functions link without -lm" >&5 $as_echo_n "checking if math functions link without -lm... " >&6; } if test "$have_cos" = 1 -a "$have_floor" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } LIBS="$LIBS -lm" # use different functions to bypass configure caching have_sin=0 have_ceil=0 for ac_func in sin do : ac_fn_c_check_func "$LINENO" "sin" "ac_cv_func_sin" if test "x$ac_cv_func_sin" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SIN 1 _ACEOF have_sin=1 fi done for ac_func in ceil do : ac_fn_c_check_func "$LINENO" "ceil" "ac_cv_func_ceil" if test "x$ac_cv_func_ceil" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_CEIL 1 _ACEOF have_ceil=1 fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking if math functions link with -lm" >&5 $as_echo_n "checking if math functions link with -lm... " >&6; } if test "$have_sin" = 1 -a "$have_ceil" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } # not sure we should warn the user, crash, etc. # expect link failure fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows __attribute__" >&5 $as_echo_n "checking if compiler allows __attribute__... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { typedef struct { } __attribute__ ((packed)) junk; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_NO_ATTRIBUTES 1" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=cpp ac_cpp='$CXXCPP $CPPFLAGS' ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_cxx_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for set" >&5 $as_echo_n "checking for set... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_HAVE_SET 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for set.h" >&5 $as_echo_n "checking for set.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_HAVE_SET_H 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for map" >&5 $as_echo_n "checking for map... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_HAVE_MAP 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for map.h" >&5 $as_echo_n "checking for map.h... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { ; return 0; } _ACEOF if ac_fn_cxx_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_HAVE_MAP_H 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test "$with_all_libs" = yes; then if test "$cross_configure" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Using --with-all-libs while cross configuring is very unlikely to be what you want. You should specify the --with-* args yourself." >&5 $as_echo "$as_me: WARNING: Using --with-all-libs while cross configuring is very unlikely to be what you want. You should specify the --with-* args yourself." >&2;} fi if test "$with_amigaos" != yes; then can_compile_amigaos=1 ac_fn_c_check_header_mongrel "$LINENO" "proto/intuition.h" "ac_cv_header_proto_intuition_h" "$ac_includes_default" if test "x$ac_cv_header_proto_intuition_h" = xyes; then : else can_compile_amigaos=0 fi ac_fn_c_check_header_mongrel "$LINENO" "intuition/intuitionbase.h" "ac_cv_header_intuition_intuitionbase_h" "$ac_includes_default" if test "x$ac_cv_header_intuition_intuitionbase_h" = xyes; then : else can_compile_amigaos=0 fi ac_fn_c_check_header_mongrel "$LINENO" "cybergraphx/cybergraphics.h" "ac_cv_header_cybergraphx_cybergraphics_h" "$ac_includes_default" if test "x$ac_cv_header_cybergraphx_cybergraphics_h" = xyes; then : else can_compile_amigaos=0 fi ac_fn_c_check_header_mongrel "$LINENO" "devices/trackdisk.h" "ac_cv_header_devices_trackdisk_h" "$ac_includes_default" if test "x$ac_cv_header_devices_trackdisk_h" = xyes; then : else can_compile_amigaos=0 fi if test $can_compile_amigaos = 1; then with_amigaos=yes fi fi if test "$with_macos" != yes; then can_compile_macos=1 ac_fn_c_check_header_mongrel "$LINENO" "Quickdraw.h" "ac_cv_header_Quickdraw_h" "$ac_includes_default" if test "x$ac_cv_header_Quickdraw_h" = xyes; then : else can_compile_macos=0 fi ac_fn_c_check_header_mongrel "$LINENO" "Dialogs.h" "ac_cv_header_Dialogs_h" "$ac_includes_default" if test "x$ac_cv_header_Dialogs_h" = xyes; then : else can_compile_macos=0 fi if test $can_compile_macos = 1; then with_macos=yes fi fi if test "$with_carbon" != yes; then can_compile_carbon=1 ac_fn_c_check_header_mongrel "$LINENO" "Carbon.h" "ac_cv_header_Carbon_h" "$ac_includes_default" if test "x$ac_cv_header_Carbon_h" = xyes; then : else can_compile_carbon=0 fi ac_fn_c_check_header_mongrel "$LINENO" "ApplicationServices/ApplicationServices.h" "ac_cv_header_ApplicationServices_ApplicationServices_h" "$ac_includes_default" if test "x$ac_cv_header_ApplicationServices_ApplicationServices_h" = xyes; then : else can_compile_carbon=0 fi if test $can_compile_carbon = 1; then with_carbon=yes fi fi if test "$with_win32" != yes; then can_compile_win32=1 ac_fn_c_check_header_mongrel "$LINENO" "windows.h" "ac_cv_header_windows_h" "$ac_includes_default" if test "x$ac_cv_header_windows_h" = xyes; then : else can_compile_win32=0 fi ac_fn_c_check_header_mongrel "$LINENO" "commctrl.h" "ac_cv_header_commctrl_h" "$ac_includes_default" if test "x$ac_cv_header_commctrl_h" = xyes; then : else can_compile_win32=0 fi if test $can_compile_win32 = 1; then with_win32=yes fi fi if test "$with_sdl" != yes; then can_compile_sdl=1 ac_fn_c_check_header_mongrel "$LINENO" "SDL/SDL.h" "ac_cv_header_SDL_SDL_h" "$ac_includes_default" if test "x$ac_cv_header_SDL_SDL_h" = xyes; then : else can_compile_sdl=0 fi ac_fn_c_check_header_mongrel "$LINENO" "SDL/SDL_main.h" "ac_cv_header_SDL_SDL_main_h" "$ac_includes_default" if test "x$ac_cv_header_SDL_SDL_main_h" = xyes; then : else can_compile_sdl=0 fi if test $can_compile_sdl = 1; then with_sdl=yes fi fi if test "$with_svga" != yes; then can_compile_svga=1 ac_fn_c_check_header_mongrel "$LINENO" "vga.h" "ac_cv_header_vga_h" "$ac_includes_default" if test "x$ac_cv_header_vga_h" = xyes; then : else can_compile_svga=0 fi ac_fn_c_check_header_mongrel "$LINENO" "vgagl.h" "ac_cv_header_vgagl_h" "$ac_includes_default" if test "x$ac_cv_header_vgagl_h" = xyes; then : else can_compile_svga=0 fi if test $can_compile_svga = 1; then with_svga=yes fi fi if test "$with_x11" != yes; then can_compile_x11=1 ac_fn_c_check_header_mongrel "$LINENO" "X11/Xlib.h" "ac_cv_header_X11_Xlib_h" "$ac_includes_default" if test "x$ac_cv_header_X11_Xlib_h" = xyes; then : else can_compile_x11=0 fi ac_fn_c_check_header_mongrel "$LINENO" "X11/Xutil.h" "ac_cv_header_X11_Xutil_h" "$ac_includes_default" if test "x$ac_cv_header_X11_Xutil_h" = xyes; then : else can_compile_x11=0 fi if test $can_compile_x11 = 1; then with_x11=yes fi fi if test "$with_rfb" != yes; then can_compile_rfb=1 case $target in *-pc-windows* | *-pc-winnt* | *-pc-cygwin* | *-mingw32*) ac_fn_c_check_header_mongrel "$LINENO" "winsock.h" "ac_cv_header_winsock_h" "$ac_includes_default" if test "x$ac_cv_header_winsock_h" = xyes; then : else can_compile_rfb=0 fi ac_fn_c_check_header_mongrel "$LINENO" "process.h" "ac_cv_header_process_h" "$ac_includes_default" if test "x$ac_cv_header_process_h" = xyes; then : else can_compile_rfb=0 fi ;; *) ac_fn_c_check_header_mongrel "$LINENO" "sys/socket.h" "ac_cv_header_sys_socket_h" "$ac_includes_default" if test "x$ac_cv_header_sys_socket_h" = xyes; then : else can_compile_rfb=0 fi ac_fn_c_check_header_mongrel "$LINENO" "netinet/tcp.h" "ac_cv_header_netinet_tcp_h" "$ac_includes_default" if test "x$ac_cv_header_netinet_tcp_h" = xyes; then : else can_compile_rfb=0 fi ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : else can_compile_rfb=0 fi ;; esac if test $can_compile_rfb = 1; then with_rfb=yes fi fi if test "$with_term" != yes; then can_compile_term=1 ac_fn_c_check_header_mongrel "$LINENO" "curses.h" "ac_cv_header_curses_h" "$ac_includes_default" if test "x$ac_cv_header_curses_h" = xyes; then : else can_compile_term=0 fi ac_fn_c_check_header_mongrel "$LINENO" "signal.h" "ac_cv_header_signal_h" "$ac_includes_default" if test "x$ac_cv_header_signal_h" = xyes; then : else can_compile_term=0 fi if test $can_compile_term = 1; then with_term=yes fi fi if test "$with_nogui" != yes; then with_nogui=yes fi fi # end of if $with_all_libs = yes { $as_echo "$as_me:${as_lineno-$LINENO}: checking for idle hack" >&5 $as_echo_n "checking for idle hack... " >&6; } # Check whether --enable-idle-hack was given. if test "${enable_idle_hack+set}" = set; then : enableval=$enable_idle_hack; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_USE_IDLE_HACK 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_USE_IDLE_HACK 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_USE_IDLE_HACK 0" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default" if test "x$ac_cv_header_dlfcn_h" = xyes; then : $as_echo "#define BX_HAVE_DLFCN_H 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "assert.h" "ac_cv_header_assert_h" "$ac_includes_default" if test "x$ac_cv_header_assert_h" = xyes; then : $as_echo "#define HAVE_ASSERT_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for plugins support" >&5 $as_echo_n "checking for plugins support... " >&6; } # Check whether --enable-plugins was given. if test "${enable_plugins+set}" = set; then : enableval=$enable_plugins; if test "$enableval" = yes; then bx_plugins=1 else bx_plugins=0 fi else bx_plugins=0 fi if test "$bx_plugins" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_PLUGINS 1" >>confdefs.h GUI_NON_PLUGIN_OBJS='$(OBJS_THAT_CANNOT_BE_PLUGINS)' GUI_PLUGIN_OBJS='$(OBJS_THAT_CAN_BE_PLUGINS)' DEFINE_PLUGIN_PATH='-DBX_PLUGIN_PATH="\"${plugdir}\""' # and the $(OBJS_THAT_SUPPORT_OTHER_PLUGINS) will be built and linked # by special link rules for the plugins that they support. LIBS="$LIBS $LIBADD_DL" have_ltdl=0 ac_fn_c_check_header_mongrel "$LINENO" "ltdl.h" "ac_cv_header_ltdl_h" "$ac_includes_default" if test "x$ac_cv_header_ltdl_h" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for lt_dlinit in -lltdl" >&5 $as_echo_n "checking for lt_dlinit in -lltdl... " >&6; } if ${ac_cv_lib_ltdl_lt_dlinit+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lltdl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char lt_dlinit (); int main () { return lt_dlinit (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ltdl_lt_dlinit=yes else ac_cv_lib_ltdl_lt_dlinit=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ltdl_lt_dlinit" >&5 $as_echo "$ac_cv_lib_ltdl_lt_dlinit" >&6; } if test "x$ac_cv_lib_ltdl_lt_dlinit" = xyes; then : have_ltdl=1 fi fi if test "$have_ltdl" = 1; then PLUGIN_VAR="-lltdl" $as_echo "#define BX_HAVE_LTDL 1" >>confdefs.h else PLUGIN_VAR="ltdl.o" fi PLUGIN_TARGET=bochs_plugins INSTALL_PLUGINS_VAR=install_libtool_plugins NONPLUGIN_GUI_LINK_OPTS='' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } bx_plugins=0 $as_echo "#define BX_PLUGINS 0" >>confdefs.h GUI_NON_PLUGIN_OBJS='$(OBJS_THAT_CANNOT_BE_PLUGINS) $(OBJS_THAT_CAN_BE_PLUGINS) $(OBJS_THAT_SUPPORT_OTHER_PLUGINS)' GUI_PLUGIN_OBJS='' NONPLUGIN_GUI_LINK_OPTS='$(GUI_LINK_OPTS)' fi # copy gui variables into iodev variables. Later, we will add to the gui # objs list, according to which display libraries are enabled. IODEV_NON_PLUGIN_OBJS=$GUI_NON_PLUGIN_OBJS IODEV_PLUGIN_OBJS=$GUI_PLUGIN_OBJS IODEV_EXT_NON_PLUGIN_OBJS=$GUI_NON_PLUGIN_OBJS IODEV_EXT_PLUGIN_OBJS=$GUI_PLUGIN_OBJS # on MacOSX if they enabled plugins, make sure that dlopen() was found. # It is provided by a library called dlcompat. if test "$bx_plugins" = 1 -a "$need_dlcompat_for_plugins" = 1; then have_dlopen=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : have_dlopen=1 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if you have dlcompat" >&5 $as_echo_n "checking if you have dlcompat... " >&6; } if test "$have_dlopen" = 0; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "To use plugins on MacOSX you must use a library called dlcompat. The configure script was not able to find dlcompat. If it is already installed then you must set up your environment variables to point to it, as is done in .conf.macosx. If you cannot resolve this, you should turn off plugins." "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler allows LL for 64-bit constants" >&5 $as_echo_n "checking if compiler allows LL for 64-bit constants... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { { 42LL; } ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_64BIT_CONSTANTS_USE_LL 0" >>confdefs.h fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: checking for A20 support" >&5 $as_echo_n "checking for A20 support... " >&6; } # Check whether --enable-a20-pin was given. if test "${enable_a20_pin+set}" = set; then : enableval=$enable_a20_pin; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_A20 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_A20 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_A20 1" >>confdefs.h fi use_x86_64=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86-64 support" >&5 $as_echo_n "checking for x86-64 support... " >&6; } # Check whether --enable-x86-64 was given. if test "${enable_x86_64+set}" = set; then : enableval=$enable_x86_64; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } OBJS64='$(OBJS64)' $as_echo "#define BX_SUPPORT_X86_64 1" >>confdefs.h use_x86_64=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } OBJS64='' $as_echo "#define BX_SUPPORT_X86_64 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } OBJS64='' $as_echo "#define BX_SUPPORT_X86_64 0" >>confdefs.h fi use_smp=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SMP support" >&5 $as_echo_n "checking for SMP support... " >&6; } # Check whether --enable-smp was given. if test "${enable_smp+set}" = set; then : enableval=$enable_smp; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_SMP 1" >>confdefs.h $as_echo "#define BX_USE_CPU_SMF 0" >>confdefs.h use_smp=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_SMP 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_SMP 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cpu level" >&5 $as_echo_n "checking for cpu level... " >&6; } # Check whether --enable-cpu-level was given. if test "${enable_cpu_level+set}" = set; then : enableval=$enable_cpu_level; case "$enableval" in 3) { $as_echo "$as_me:${as_lineno-$LINENO}: result: 3" >&5 $as_echo "3" >&6; } $as_echo "#define BX_CPU_LEVEL 3" >>confdefs.h ;; 4) { $as_echo "$as_me:${as_lineno-$LINENO}: result: 4" >&5 $as_echo "4" >&6; } $as_echo "#define BX_CPU_LEVEL 4" >>confdefs.h ;; 5) { $as_echo "$as_me:${as_lineno-$LINENO}: result: 5" >&5 $as_echo "5" >&6; } $as_echo "#define BX_CPU_LEVEL 5" >>confdefs.h ;; 6) { $as_echo "$as_me:${as_lineno-$LINENO}: result: 6" >&5 $as_echo "6" >&6; } $as_echo "#define BX_CPU_LEVEL 6" >>confdefs.h ;; *) echo " " echo "ERROR: you must supply a valid CPU level to --enable-cpu-level" exit 1 ;; esac bx_cpu_level=$enableval if test "$use_smp" = 1 -a "$enableval" -lt 5; then echo "ERROR: with >1 processor, use --enable-cpu-level=5 or more" exit 1 fi if test "$use_x86_64" = 1 -a "$enableval" -lt 6; then echo "ERROR: --enable-cpu-level=6 required for x86-64 emulation" exit 1 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: 6" >&5 $as_echo "6" >&6; } $as_echo "#define BX_CPU_LEVEL 6" >>confdefs.h bx_cpu_level=6 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for larger than 32 bit physical address emulation" >&5 $as_echo_n "checking for larger than 32 bit physical address emulation... " >&6; } # Check whether --enable-long-phy-address was given. if test "${enable_long_phy_address+set}" = set; then : enableval=$enable_long_phy_address; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_PHY_ADDRESS_LONG 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_PHY_ADDRESS_LONG 0" >>confdefs.h fi else if test "$bx_cpu_level" -ge 5; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_PHY_ADDRESS_LONG 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_PHY_ADDRESS_LONG 0" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for large ramfile support" >&5 $as_echo_n "checking for large ramfile support... " >&6; } # Check whether --enable-large-ramfile was given. if test "${enable_large_ramfile+set}" = set; then : enableval=$enable_large_ramfile; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_LARGE_RAMFILE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_LARGE_RAMFILE 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_LARGE_RAMFILE 1" >>confdefs.h fi networking=no NETDEV_OBJS='' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for NE2000 support" >&5 $as_echo_n "checking for NE2000 support... " >&6; } # Check whether --enable-ne2000 was given. if test "${enable_ne2000+set}" = set; then : enableval=$enable_ne2000; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_NE2K 1" >>confdefs.h NETDEV_OBJS='ne2k.o' networking=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_NE2K 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_NE2K 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for i440FX PCI support" >&5 $as_echo_n "checking for i440FX PCI support... " >&6; } # Check whether --enable-pci was given. if test "${enable_pci+set}" = set; then : enableval=$enable_pci; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_PCI 1" >>confdefs.h pci=1 PCI_OBJ='pci.o pci2isa.o pci_ide.o acpi.o' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_PCI 0" >>confdefs.h pci=0 PCI_OBJ='' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_PCI 0" >>confdefs.h pci=0 PCI_OBJ='' fi # # PCI host device support # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PCI host device mapping support" >&5 $as_echo_n "checking for PCI host device mapping support... " >&6; } # Check whether --enable-pcidev was given. if test "${enable_pcidev+set}" = set; then : enableval=$enable_pcidev; if test "$enableval" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test "$pci" != "1"; then as_fn_error $? "PCI host device mapping requires PCI support" "$LINENO" 5 fi case "$target" in *-linux*) { $as_echo "$as_me:${as_lineno-$LINENO}: Linux detected as host for PCI host device mapping" >&5 $as_echo "$as_me: Linux detected as host for PCI host device mapping" >&6;} linux_version=`uname -r` case "$linux_version" in 2.4*) PCIDEV_MODULE_MAKE_ALL="all-kernel24" KERNEL_MODULE_SUFFIX="o" ;; 2.6*|3.*) PCIDEV_MODULE_MAKE_ALL="all-kernel26" KERNEL_MODULE_SUFFIX="ko" ;; *) as_fn_error $? "Linux kernel 2.4, 2.6 or 3.x is required for PCI host device mapping" "$LINENO" 5 ;; esac KERNELDIR="/lib/modules/$linux_version/build" LSMOD="lsmod" INSMOD="insmod" RMMOD="rmmod" DEPMOD="depmod" CLEAN_PCIDEV_VAR=clean_pcidev ;; *) as_fn_error $? "PCI host device mapping requires Linux as host" "$LINENO" 5 ;; esac $as_echo "#define BX_SUPPORT_PCIDEV 1" >>confdefs.h PCI_OBJ="$PCI_OBJ pcidev.o" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_PCIDEV 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_PCIDEV 0" >>confdefs.h fi use_usb=0 USBHC_OBJS='' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB UHCI support" >&5 $as_echo_n "checking for USB UHCI support... " >&6; } # Check whether --enable-usb was given. if test "${enable_usb+set}" = set; then : enableval=$enable_usb; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_USB_UHCI 1" >>confdefs.h USBHC_OBJS="usb_uhci.o" use_usb=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_USB_UHCI 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_USB_UHCI 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB OHCI support" >&5 $as_echo_n "checking for USB OHCI support... " >&6; } # Check whether --enable-usb-ohci was given. if test "${enable_usb_ohci+set}" = set; then : enableval=$enable_usb_ohci; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_USB_OHCI 1" >>confdefs.h USBHC_OBJS="$USBHC_OBJS usb_ohci.o" use_usb=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_USB_OHCI 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_USB_OHCI 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for experimental USB xHCI support" >&5 $as_echo_n "checking for experimental USB xHCI support... " >&6; } # Check whether --enable-usb-xhci was given. if test "${enable_usb_xhci+set}" = set; then : enableval=$enable_usb_xhci; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_USB_XHCI 1" >>confdefs.h USBHC_OBJS="$USBHC_OBJS usb_xhci.o" use_usb=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_USB_XHCI 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_USB_XHCI 0" >>confdefs.h fi if test "$use_usb" = 1; then USBCORE_OBJ="usb_common.o" USBDEV_OBJS="usb_hid.o usb_hub.o usb_msd.o usb_printer.o" SCSI_OBJS="scsi_device.o" if test "$bx_plugins" = 0; then USB_LIB_VAR='iodev/usb/libusb.a' fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PCI pseudo NIC support" >&5 $as_echo_n "checking for PCI pseudo NIC support... " >&6; } # Check whether --enable-pnic was given. if test "${enable_pnic+set}" = set; then : enableval=$enable_pnic; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_PCIPNIC 1" >>confdefs.h NETDEV_OBJS="$NETDEV_OBJS pcipnic.o" networking=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_PCIPNIC 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_PCIPNIC 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Intel(R) Gigabit Ethernet support" >&5 $as_echo_n "checking for Intel(R) Gigabit Ethernet support... " >&6; } # Check whether --enable-e1000 was given. if test "${enable_e1000+set}" = set; then : enableval=$enable_e1000; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_E1000 1" >>confdefs.h NETDEV_OBJS="$NETDEV_OBJS e1000.o" networking=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_E1000 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_E1000 0" >>confdefs.h fi NETLOW_OBJS='' if test "$networking" = yes; then NETLOW_OBJS='eth_null.o eth_vnet.o' if test "$MSVC_TARGET" != 1; then ac_fn_c_check_header_mongrel "$LINENO" "net/bpf.h" "ac_cv_header_net_bpf_h" "$ac_includes_default" if test "x$ac_cv_header_net_bpf_h" = xyes; then : NETLOW_OBJS="$NETLOW_OBJS eth_fbsd.o" $as_echo "#define BX_NETMOD_FBSD 1" >>confdefs.h fi ac_fn_c_check_header_mongrel "$LINENO" "netpacket/packet.h" "ac_cv_header_netpacket_packet_h" "$ac_includes_default" if test "x$ac_cv_header_netpacket_packet_h" = xyes; then : NETLOW_OBJS="$NETLOW_OBJS eth_linux.o" $as_echo "#define BX_NETMOD_LINUX 1" >>confdefs.h fi for ac_func in fork do : ac_fn_c_check_func "$LINENO" "fork" "ac_cv_func_fork" if test "x$ac_cv_func_fork" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_FORK 1 _ACEOF have_fork=1 fi done for ac_func in execlp do : ac_fn_c_check_func "$LINENO" "execlp" "ac_cv_func_execlp" if test "x$ac_cv_func_execlp" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_EXECLP 1 _ACEOF have_execlp=1 fi done for ac_func in socketpair do : ac_fn_c_check_func "$LINENO" "socketpair" "ac_cv_func_socketpair" if test "x$ac_cv_func_socketpair" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SOCKETPAIR 1 _ACEOF have_socketpair=1 fi done if test x"$have_fork" = x1 -a x"$have_execlp" = x1 -a x"$have_socketpair" = x1; then NETLOW_OBJS="$NETLOW_OBJS eth_slirp.o" $as_echo "#define BX_NETMOD_SLIRP 1" >>confdefs.h fi fi case "$target" in *-pc-windows* | *-pc-winnt* | *-pc-cygwin* | *-mingw32*) NETLOW_OBJS="$NETLOW_OBJS eth_win32.o" $as_echo "#define BX_NETMOD_WIN32 1" >>confdefs.h ;; *-macosx* | *-darwin*) NETLOW_OBJS="$NETLOW_OBJS eth_tuntap.o" $as_echo "#define BX_NETMOD_TUNTAP 1" >>confdefs.h ;; *) ac_fn_c_check_header_compile "$LINENO" "net/if.h" "ac_cv_header_net_if_h" " #include #include " if test "x$ac_cv_header_net_if_h" = xyes; then : use_ethertap=yes $as_echo "#define BX_HAVE_NET_IF_H 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "linux/netlink.h" "ac_cv_header_linux_netlink_h" " #include #include " if test "x$ac_cv_header_linux_netlink_h" = xyes; then : use_ethertap=yes fi if test "$use_ethertap" = yes; then NETLOW_OBJS="$NETLOW_OBJS eth_tap.o eth_vde.o" $as_echo "#define BX_NETMOD_TAP 1" >>confdefs.h $as_echo "#define BX_NETMOD_VDE 1" >>confdefs.h fi ac_fn_c_check_header_compile "$LINENO" "net/if_tun.h" "ac_cv_header_net_if_tun_h" " #include #include #include " if test "x$ac_cv_header_net_if_tun_h" = xyes; then : use_tuntap=yes fi ac_fn_c_check_header_compile "$LINENO" "linux/if_tun.h" "ac_cv_header_linux_if_tun_h" " #include #include " if test "x$ac_cv_header_linux_if_tun_h" = xyes; then : use_tuntap=yes fi if test "$use_tuntap" = yes; then NETLOW_OBJS="$NETLOW_OBJS eth_tuntap.o" $as_echo "#define BX_NETMOD_TUNTAP 1" >>confdefs.h fi ;; esac if test "$bx_plugins" = 0; then NETWORK_LIB_VAR='iodev/network/libnetwork.a' fi $as_echo "#define BX_NETWORKING 1" >>confdefs.h else $as_echo "#define BX_NETWORKING 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for repeated IO and mem copy speedups" >&5 $as_echo_n "checking for repeated IO and mem copy speedups... " >&6; } # Check whether --enable-repeat-speedups was given. if test "${enable_repeat_speedups+set}" = set; then : enableval=$enable_repeat_speedups; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } speedup_repeat=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedup_repeat=0 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedup_repeat=0 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc fast function calls optimization" >&5 $as_echo_n "checking for gcc fast function calls optimization... " >&6; } # Check whether --enable-fast-function-calls was given. if test "${enable_fast_function_calls+set}" = set; then : enableval=$enable_fast_function_calls; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } speedup_fastcall=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedup_fastcall=0 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedup_fastcall=0 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for handlers chaining speedups" >&5 $as_echo_n "checking for handlers chaining speedups... " >&6; } # Check whether --enable-handlers-chaining was given. if test "${enable_handlers_chaining+set}" = set; then : enableval=$enable_handlers_chaining; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } speedup_handlers_chaining=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedup_handlers_chaining=0 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedup_handlers_chaining=0 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking support for configurable MSR registers" >&5 $as_echo_n "checking support for configurable MSR registers... " >&6; } # Check whether --enable-configurable-msrs was given. if test "${enable_configurable_msrs+set}" = set; then : enableval=$enable_configurable_msrs; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_CONFIGURE_MSRS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_CONFIGURE_MSRS 0" >>confdefs.h fi else if test "$bx_cpu_level" -ge 5; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_CONFIGURE_MSRS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_CONFIGURE_MSRS 0" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking show IPS" >&5 $as_echo_n "checking show IPS... " >&6; } # Check whether --enable-show-ips was given. if test "${enable_show_ips+set}" = set; then : enableval=$enable_show_ips; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SHOW_IPS 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SHOW_IPS 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SHOW_IPS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for use of .cpp as suffix" >&5 $as_echo_n "checking for use of .cpp as suffix... " >&6; } # Check whether --enable-cpp was given. if test "${enable_cpp+set}" = set; then : enableval=$enable_cpp; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SUFFIX_LINE='.SUFFIXES: .cpp' CPP_SUFFIX='cpp' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SUFFIX_LINE='.SUFFIXES: .cc' CPP_SUFFIX='cc' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SUFFIX_LINE='.SUFFIXES: .cc' CPP_SUFFIX='cc' fi if test "$enable_cpp" = yes; then echo "moving .cc source files to .cpp" sourcefiles=`find . -name "*.cc" -print` if test "$sourcefiles" != ""; then for ccname in $sourcefiles do cppname=`echo $ccname | sed -e "s/\.cc$/.cpp/"` echo "mv $ccname $cppname" mv $ccname $cppname done else echo "no more .cc source files to rename" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Bochs internal debugger support" >&5 $as_echo_n "checking for Bochs internal debugger support... " >&6; } # Check whether --enable-debugger was given. if test "${enable_debugger+set}" = set; then : enableval=$enable_debugger; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_DEBUGGER 1" >>confdefs.h DEBUGGER_VAR='$(DEBUGGER_LIB)' NO_FLEX_YACC='' # Extract the first word of "flex", so it can be a program name with args. set dummy flex; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_FLEX+:} false; then : $as_echo_n "(cached) " >&6 else case $FLEX in [\\/]* | ?:[\\/]*) ac_cv_path_FLEX="$FLEX" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_FLEX="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_FLEX" && ac_cv_path_FLEX="not_found" ;; esac fi FLEX=$ac_cv_path_FLEX if test -n "$FLEX"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FLEX" >&5 $as_echo "$FLEX" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "yacc", so it can be a program name with args. set dummy yacc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_YACC+:} false; then : $as_echo_n "(cached) " >&6 else case $YACC in [\\/]* | ?:[\\/]*) ac_cv_path_YACC="$YACC" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_YACC="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_YACC" && ac_cv_path_YACC="not_found" ;; esac fi YACC=$ac_cv_path_YACC if test -n "$YACC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5 $as_echo "$YACC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to generate parser / lexer files" >&5 $as_echo_n "checking whether to generate parser / lexer files... " >&6; } if test "$FLEX" = not_found -o "$YACC" = not_found -o "$MSVC_TARGET" = 1; then NO_FLEX_YACC='#' { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi bx_debugger=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_DEBUGGER 0" >>confdefs.h DEBUGGER_VAR='' bx_debugger=0 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_DEBUGGER 0" >>confdefs.h DEBUGGER_VAR='' bx_debugger=0 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for disassembler support" >&5 $as_echo_n "checking for disassembler support... " >&6; } # Check whether --enable-disasm was given. if test "${enable_disasm+set}" = set; then : enableval=$enable_disasm; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_DISASM 1" >>confdefs.h DISASM_VAR='$(DISASM_LIB)' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if test "$bx_debugger" = 1; then echo "ERROR: debugger is enabled, so --enable-disasm is required" exit 1 fi $as_echo "#define BX_DISASM 0" >>confdefs.h DISASM_VAR='' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_DISASM 1" >>confdefs.h DISASM_VAR='$(DISASM_LIB)' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking enable Bochs internal debugger GUI" >&5 $as_echo_n "checking enable Bochs internal debugger GUI... " >&6; } # Check whether --enable-debugger-gui was given. if test "${enable_debugger_gui+set}" = set; then : enableval=$enable_debugger_gui; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_DEBUGGER_GUI 1" >>confdefs.h gui_debugger=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_DEBUGGER_GUI 0" >>confdefs.h gui_debugger=0 fi else if test "$bx_debugger" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_DEBUGGER_GUI 1" >>confdefs.h gui_debugger=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_DEBUGGER_GUI 0" >>confdefs.h gui_debugger=0 fi fi bx_gdb_stub=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gdb stub enable" >&5 $as_echo_n "checking for gdb stub enable... " >&6; } # Check whether --enable-gdb-stub was given. if test "${enable_gdb_stub+set}" = set; then : enableval=$enable_gdb_stub; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_GDBSTUB 1" >>confdefs.h GDBSTUB_VAR='$(GDBSTUB_OBJS)' bx_gdb_stub=1 if test "$bx_debugger" = 1; then as_fn_error $? "--enable-debugger and --enable-gdb-stub are mutually exclusive" "$LINENO" 5 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_GDBSTUB 0" >>confdefs.h GDBSTUB_VAR='' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_GDBSTUB 0" >>confdefs.h GDBSTUB_VAR='' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for I/O Interface to the debugger" >&5 $as_echo_n "checking for I/O Interface to the debugger... " >&6; } IODEBUG_OBJS='' # Check whether --enable-iodebug was given. if test "${enable_iodebug+set}" = set; then : enableval=$enable_iodebug; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_IODEBUG 1" >>confdefs.h IODEBUG_OBJS='iodebug.o' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_IODEBUG 0" >>confdefs.h fi else if test "$bx_debugger" = 1; then # enable by default if debugger is on { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_IODEBUG 1" >>confdefs.h IODEBUG_OBJS='iodebug.o' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ALL optimizations enabled" >&5 $as_echo_n "checking for ALL optimizations enabled... " >&6; } # Check whether --enable-all-optimizations was given. if test "${enable_all_optimizations+set}" = set; then : enableval=$enable_all_optimizations; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } speedups_all=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedups_all=0 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } speedups_all=0 fi # # Optimizations section. Decide what the status of various optimizations # should be based on configure choices and other factors. # if test "$speedups_all" = 1; then # Configure requested to force all options enabled. speedup_repeat=1 speedup_fastcall=1 speedup_handlers_chaining=1 fi if test "$speedup_repeat" = 1; then $as_echo "#define BX_SUPPORT_REPEAT_SPEEDUPS 1" >>confdefs.h else $as_echo "#define BX_SUPPORT_REPEAT_SPEEDUPS 0" >>confdefs.h fi if test "$speedup_fastcall" = 1; then $as_echo "#define BX_FAST_FUNC_CALL 1" >>confdefs.h else $as_echo "#define BX_FAST_FUNC_CALL 0" >>confdefs.h fi if test "$bx_debugger" = 1 -a "$speedup_handlers_chaining" = 1; then speedup_handlers_chaining=0 echo "ERROR: handlers-chaining speedups are not supported with internal debugger or gdbstub yet" fi if test "$bx_gdb_stub" = 1 -a "$speedup_handlers_chaining" = 1; then speedup_handlers_chaining=0 echo "ERROR: handlers-chaining speedups are not supported with internal debugger or gdbstub yet" fi if test "$speedup_handlers_chaining" = 1; then $as_echo "#define BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS 1" >>confdefs.h else $as_echo "#define BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS 0" >>confdefs.h fi READLINE_LIB="" rl_without_curses_ok=no rl_with_curses_ok=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether user wants readline" >&5 $as_echo_n "checking whether user wants readline... " >&6; } # Check whether --enable-readline was given. if test "${enable_readline+set}" = set; then : enableval=$enable_readline; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } want_readline=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } want_readline=no fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } want_readline=yes fi use_readline=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use readline" >&5 $as_echo_n "checking whether to use readline... " >&6; } if test "$want_readline" = yes; then if test "$bx_debugger" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if readline works without -lcurses" >&5 $as_echo_n "checking if readline works without -lcurses... " >&6; } OLD_LIBS=$LIBS LIBS="$LIBS -lreadline" if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { rl_initialize(); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } rl_without_curses_ok=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if readline works with -lcurses" >&5 $as_echo_n "checking if readline works with -lcurses... " >&6; } LIBS="$LIBS -lcurses" if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main() { rl_initialize(); exit(0); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } rl_with_curses_ok=yes else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi LIBS=$OLD_LIBS if test "$rl_without_curses_ok" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBREADLINE 1" >>confdefs.h READLINE_LIB="-lreadline" use_readline=1 elif test "$rl_with_curses_ok" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_LIBREADLINE 1" >>confdefs.h READLINE_LIB="-lreadline -lcurses" use_readline=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } echo WARNING: The readline library was disabled because it was not found. fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ac_fn_c_check_header_mongrel "$LINENO" "readline/history.h" "ac_cv_header_readline_history_h" "$ac_includes_default" if test "x$ac_cv_header_readline_history_h" = xyes; then : $as_echo "#define HAVE_READLINE_HISTORY_H 1" >>confdefs.h fi INSTRUMENT_DIR='instrument/stubs' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for instrumentation support" >&5 $as_echo_n "checking for instrumentation support... " >&6; } # Check whether --enable-instrumentation was given. if test "${enable_instrumentation+set}" = set; then : enableval=$enable_instrumentation; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_INSTRUMENTATION 1" >>confdefs.h INSTRUMENT_VAR='$(INSTRUMENT_LIB)' elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_INSTRUMENTATION 0" >>confdefs.h INSTRUMENT_VAR='' else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_INSTRUMENTATION 1" >>confdefs.h INSTRUMENT_DIR=$enableval INSTRUMENT_VAR='$(INSTRUMENT_LIB)' fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_INSTRUMENTATION 0" >>confdefs.h INSTRUMENT_VAR='' fi if test "$bx_plugins" = 0; then case $target in *-pc-windows*) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS wsock32.lib" ;; *-cygwin* | *-mingw32*) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lwsock32" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking enable logging" >&5 $as_echo_n "checking enable logging... " >&6; } # Check whether --enable-logging was given. if test "${enable_logging+set}" = set; then : enableval=$enable_logging; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_NO_LOGGING 0" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_NO_LOGGING 1" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_NO_LOGGING 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking enable assert checks" >&5 $as_echo_n "checking enable assert checks... " >&6; } # Check whether --enable-assert-checks was given. if test "${enable_assert_checks+set}" = set; then : enableval=$enable_assert_checks; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_ASSERT_ENABLE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_ASSERT_ENABLE 0" >>confdefs.h fi else if test "$bx_debugger" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_ASSERT_ENABLE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_ASSERT_ENABLE 0" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for raw serial support" >&5 $as_echo_n "checking for raw serial support... " >&6; } # Check whether --enable-raw-serial was given. if test "${enable_raw_serial+set}" = set; then : enableval=$enable_raw_serial; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define USE_RAW_SERIAL 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define USE_RAW_SERIAL 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define USE_RAW_SERIAL 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CLGD54XX emulation" >&5 $as_echo_n "checking for CLGD54XX emulation... " >&6; } # Check whether --enable-clgd54xx was given. if test "${enable_clgd54xx+set}" = set; then : enableval=$enable_clgd54xx; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_CLGD54XX 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_CLGD54XX 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_CLGD54XX 0" >>confdefs.h fi support_fpu=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for FPU emulation" >&5 $as_echo_n "checking for FPU emulation... " >&6; } FPU_VAR='' # Check whether --enable-fpu was given. if test "${enable_fpu+set}" = set; then : enableval=$enable_fpu; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_FPU 1" >>confdefs.h FPU_VAR='$(FPU_LIB)' elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_FPU 0" >>confdefs.h support_fpu=0 else echo " " echo "ERROR: --enable-fpu does not accept a path" exit 1 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_FPU 1" >>confdefs.h FPU_VAR='$(FPU_LIB)' fi support_vmx=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VMX support" >&5 $as_echo_n "checking for VMX support... " >&6; } # Check whether --enable-vmx was given. if test "${enable_vmx+set}" = set; then : enableval=$enable_vmx; case "$enableval" in no | 0) support_vmx=0 { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_VMX 0" >>confdefs.h ;; yes | 1) support_vmx=1 { $as_echo "$as_me:${as_lineno-$LINENO}: result: 1" >&5 $as_echo "1" >&6; } $as_echo "#define BX_SUPPORT_VMX 1" >>confdefs.h ;; 2) support_vmx=2 { $as_echo "$as_me:${as_lineno-$LINENO}: result: 2" >&5 $as_echo "2" >&6; } $as_echo "#define BX_SUPPORT_VMX 2" >>confdefs.h ;; *) echo "ERROR: --enable-vmx=$enableval not understood. Use --enable-vmx=no|1|2" exit 1 ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_VMX 0" >>confdefs.h fi if test "$support_vmx" -gt 0 -a "$bx_cpu_level" -lt 6; then as_fn_error $? "for VMX support the CPU level must be set to 6" "$LINENO" 5 fi if test "$support_vmx" -gt 1 -a "$use_x86_64" = 0; then as_fn_error $? "VMXx2 support require x86-64 enabled" "$LINENO" 5 fi support_svm=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SVM support" >&5 $as_echo_n "checking for SVM support... " >&6; } # Check whether --enable-svm was given. if test "${enable_svm+set}" = set; then : enableval=$enable_svm; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_SVM 1" >>confdefs.h support_svm=1 elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_SVM 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_SVM 0" >>confdefs.h fi if test "$support_svm" -gt 0 -a "$bx_cpu_level" -lt 6; then as_fn_error $? "for SVM support the CPU level must be set to 6" "$LINENO" 5 fi if test "$support_svm" -gt 1 -a "$use_x86_64" = 0; then as_fn_error $? "SVM support require x86-64 enabled" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 3DNow! support" >&5 $as_echo_n "checking for 3DNow! support... " >&6; } # Check whether --enable-3dnow was given. if test "${enable_3dnow+set}" = set; then : enableval=$enable_3dnow; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_3DNOW 1" >>confdefs.h elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_3DNOW 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_3DNOW 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for alignment check support" >&5 $as_echo_n "checking for alignment check support... " >&6; } # Check whether --enable-alignment-check was given. if test "${enable_alignment_check+set}" = set; then : enableval=$enable_alignment_check; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_ALIGNMENT_CHECK 1" >>confdefs.h elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_ALIGNMENT_CHECK 0" >>confdefs.h fi else if test "$bx_cpu_level" -gt 3; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_ALIGNMENT_CHECK 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_ALIGNMENT_CHECK 0" >>confdefs.h fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for misaligned SSE support" >&5 $as_echo_n "checking for misaligned SSE support... " >&6; } # Check whether --enable-misaligned-sse was given. if test "${enable_misaligned_sse+set}" = set; then : enableval=$enable_misaligned_sse; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_MISALIGNED_SSE 1" >>confdefs.h elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_MISALIGNED_SSE 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_MISALIGNED_SSE 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MONITOR/MWAIT instructions support (experimental)" >&5 $as_echo_n "checking for MONITOR/MWAIT instructions support (experimental)... " >&6; } # Check whether --enable-monitor_mwait was given. if test "${enable_monitor_mwait+set}" = set; then : enableval=$enable_monitor_mwait; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_MONITOR_MWAIT 1" >>confdefs.h elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_MONITOR_MWAIT 0" >>confdefs.h fi else if test "$bx_cpu_level" -gt 5; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_MONITOR_MWAIT 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_MONITOR_MWAIT 0" >>confdefs.h fi fi support_avx=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AVX instructions support" >&5 $as_echo_n "checking for AVX instructions support... " >&6; } # Check whether --enable-avx was given. if test "${enable_avx+set}" = set; then : enableval=$enable_avx; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_AVX 1" >>confdefs.h support_avx=1 elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_AVX 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_AVX 0" >>confdefs.h fi if test "$support_avx" -gt 0 -a "$use_x86_64" = 0; then as_fn_error $? "for AVX support x86-64 emulation must be compiled in!" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for x86 debugger support" >&5 $as_echo_n "checking for x86 debugger support... " >&6; } # Check whether --enable-x86-debugger was given. if test "${enable_x86_debugger+set}" = set; then : enableval=$enable_x86_debugger; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_X86_DEBUGGER 1" >>confdefs.h elif test "$enableval" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_X86_DEBUGGER 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_X86_DEBUGGER 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CDROM support" >&5 $as_echo_n "checking for CDROM support... " >&6; } # Check whether --enable-cdrom was given. if test "${enable_cdrom+set}" = set; then : enableval=$enable_cdrom; if test "$enableval" = no; then bx_cdrom=0 else bx_cdrom=1 fi else bx_cdrom=1 fi if test "$bx_cdrom" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } CDROM_OBJS='cdrom.o' case $target in *-pc-windows* | *-pc-winnt* | *-pc-cygwin* | *-mingw32*) CDROM_OBJS="$CDROM_OBJS cdrom_win32.o" $as_echo "#define BX_SUPPORT_CDROM 1" >>confdefs.h ;; *) ac_fn_c_check_header_mongrel "$LINENO" "IOKit/storage/IOCDMedia.h" "ac_cv_header_IOKit_storage_IOCDMedia_h" "$ac_includes_default" if test "x$ac_cv_header_IOKit_storage_IOCDMedia_h" = xyes; then : can_use_osx_cdrom=yes fi if test "$with_amigaos" = yes; then # use the amiga cdrom file instead. CDROM_OBJS="$CDROM_OBJS cdrom_amigaos.o" elif test "$can_use_osx_cdrom" = yes; then # use cdrom_osx { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using OSX IOKit CD Interface" >&5 $as_echo "Using OSX IOKit CD Interface" >&6; } CDROM_OBJS="$CDROM_OBJS cdrom_osx.o" EXTRA_LINK_OPTS="${EXTRA_LINK_OPTS} -framework IOKit -framework CoreFoundation "'$(GUI_LINK_OPTS)' else CDROM_OBJS="$CDROM_OBJS cdrom_misc.o" fi $as_echo "#define BX_SUPPORT_CDROM 1" >>confdefs.h ;; esac else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } CDROM_OBJS='' $as_echo "#define BX_SUPPORT_CDROM 0" >>confdefs.h fi SOUNDCARD_OBJS='' SOUNDLOW_OBJS='' GAME_OBJS='' soundcard_present=0 gameport_present=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Sound Blaster 16 support" >&5 $as_echo_n "checking for Sound Blaster 16 support... " >&6; } # Check whether --enable-sb16 was given. if test "${enable_sb16+set}" = set; then : enableval=$enable_sb16; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SOUNDCARD_OBJS='sb16.o' soundcard_present=1 $as_echo "#define BX_SUPPORT_SB16 1" >>confdefs.h GAME_OBJS='gameport.o' gameport_present=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_SB16 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_SB16 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ES1370 soundcard support" >&5 $as_echo_n "checking for ES1370 soundcard support... " >&6; } # Check whether --enable-es1370 was given. if test "${enable_es1370+set}" = set; then : enableval=$enable_es1370; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } if test "$pci" != "1"; then as_fn_error $? "ES1370 soundcard requires PCI support" "$LINENO" 5 fi SOUNDCARD_OBJS="$SOUNDCARD_OBJS es1370.o" soundcard_present=1 $as_echo "#define BX_SUPPORT_ES1370 1" >>confdefs.h GAME_OBJS='gameport.o' gameport_present=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_ES1370 0" >>confdefs.h fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define BX_SUPPORT_ES1370 0" >>confdefs.h fi if test "$soundcard_present" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sound lowlevel module" >&5 $as_echo_n "checking for sound lowlevel module... " >&6; } $as_echo "#define BX_SUPPORT_SOUNDLOW 1" >>confdefs.h case "$target" in *-linux* | *-freebsd*) SOUNDLOW_OBJS='soundlnx.o' $as_echo "#define BX_SOUND_LOWLEVEL_C bx_sound_linux_c" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: linux" >&5 $as_echo "linux" >&6; } bx_have_alsa=0 ac_fn_c_check_header_mongrel "$LINENO" "alsa/asoundlib.h" "ac_cv_header_alsa_asoundlib_h" "$ac_includes_default" if test "x$ac_cv_header_alsa_asoundlib_h" = xyes; then : bx_have_alsa=1 fi if test "$bx_have_alsa" = 1; then $as_echo "#define BX_HAVE_ALSASOUND 1" >>confdefs.h if test "$bx_plugins" = 1; then SOUND_LINK_OPTS="$SOUND_LINK_OPTS -lasound" else DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lasound" fi fi ;; *-pc-windows*) SOUNDLOW_OBJS='soundwin.o' $as_echo "#define BX_SOUND_LOWLEVEL_C bx_sound_windows_c" >>confdefs.h DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS winmm.lib" { $as_echo "$as_me:${as_lineno-$LINENO}: result: win" >&5 $as_echo "win" >&6; } ;; *-cygwin* | *-mingw32*) SOUNDLOW_OBJS='soundwin.o' $as_echo "#define BX_SOUND_LOWLEVEL_C bx_sound_windows_c" >>confdefs.h DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lwinmm" { $as_echo "$as_me:${as_lineno-$LINENO}: result: win" >&5 $as_echo "win" >&6; } ;; *-macosx* | *-macos* | *-apple-darwin*) SOUNDLOW_OBJS='soundosx.o' $as_echo "#define BX_SOUND_LOWLEVEL_C bx_sound_osx_c" >>confdefs.h DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -framework CoreServices -framework AudioUnit -framework AudioToolbox" { $as_echo "$as_me:${as_lineno-$LINENO}: result: osx" >&5 $as_echo "osx" >&6; } ;; *) SOUNDLOW_OBJS='' $as_echo "#define BX_SOUND_LOWLEVEL_C bx_sound_lowlevel_c" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: dummy" >&5 $as_echo "dummy" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for additional sound lowlevel modules" >&5 $as_echo_n "checking for additional sound lowlevel modules... " >&6; } if test "$with_sdl" = yes; then SOUNDLOW_OBJS="$SOUNDLOW_OBJS soundsdl.o" if test "$bx_plugins" = 1; then SOUND_LINK_OPTS="$SOUND_LINK_OPTS `sdl-config --libs`" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: sdl" >&5 $as_echo "sdl" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi if test "$bx_plugins" = 0; then SOUND_LIB_VAR='iodev/sound/libsound.a' fi else $as_echo "#define BX_SUPPORT_SOUNDLOW 0" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for standard PC gameport support" >&5 $as_echo_n "checking for standard PC gameport support... " >&6; } # Check whether --enable-gameport was given. if test "${enable_gameport+set}" = set; then : enableval=$enable_gameport; if test "$enableval" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define BX_SUPPORT_GAMEPORT 1" >>confdefs.h if test "$gameport_present" = 0; then GAME_OBJS='gameport.o' case $target in *-cygwin* | *-mingw32*) DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS -lwinmm" ;; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } GAME_OBJS='' $as_echo "#define BX_SUPPORT_GAMEPORT 0" >>confdefs.h fi else if test "$gameport_present" = 1; then $as_echo "#define BX_SUPPORT_GAMEPORT 1" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else $as_echo "#define BX_SUPPORT_GAMEPORT 0" >>confdefs.h { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi # Extract the first word of "docbook2html", so it can be a program name with args. set dummy docbook2html; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_DOCBOOK2HTML+:} false; then : $as_echo_n "(cached) " >&6 else case $DOCBOOK2HTML in [\\/]* | ?:[\\/]*) ac_cv_path_DOCBOOK2HTML="$DOCBOOK2HTML" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_DOCBOOK2HTML="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_DOCBOOK2HTML" && ac_cv_path_DOCBOOK2HTML="not_found" ;; esac fi DOCBOOK2HTML=$ac_cv_path_DOCBOOK2HTML if test -n "$DOCBOOK2HTML"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOCBOOK2HTML" >&5 $as_echo "$DOCBOOK2HTML" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build docbook documentation" >&5 $as_echo_n "checking whether to build docbook documentation... " >&6; } build_docbook=0 # Check whether --enable-docbook was given. if test "${enable_docbook+set}" = set; then : enableval=$enable_docbook; if test "$enableval" = yes; then build_docbook=1; fi else if test "$DOCBOOK2HTML" != not_found; then build_docbook=1; fi fi if test $build_docbook = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } BUILD_DOCBOOK_VAR=build_docbook INSTALL_DOCBOOK_VAR=install_docbook CLEAN_DOCBOOK_VAR=clean_docbook if test "$DOCBOOK2HTML" = not_found; then echo "ERROR: docbook2html must be installed to build the documentation" exit 1 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi PRIMARY_TARGET='bochs' PLUGIN_LIBNAME_TRANSFORMATION='%.o=libbx_%.la' if test "$bx_plugins" = 0; then HDIMAGE_LIB_VAR='iodev/hdimage/libhdimage.a' fi IODEV_LIB_VAR='iodev/libiodev.a' NONINLINE_VAR='$(NONINLINE_OBJS)' # Check whether --with-x11 was given. if test "${with_x11+set}" = set; then : withval=$with_x11; fi # Check whether --with-win32 was given. if test "${with_win32+set}" = set; then : withval=$with_win32; fi # Check whether --with-macos was given. if test "${with_macos+set}" = set; then : withval=$with_macos; fi # Check whether --with-carbon was given. if test "${with_carbon+set}" = set; then : withval=$with_carbon; fi # Check whether --with-nogui was given. if test "${with_nogui+set}" = set; then : withval=$with_nogui; fi # Check whether --with-term was given. if test "${with_term+set}" = set; then : withval=$with_term; fi # Check whether --with-rfb was given. if test "${with_rfb+set}" = set; then : withval=$with_rfb; fi # Check whether --with-amigaos was given. if test "${with_amigaos+set}" = set; then : withval=$with_amigaos; fi # Check whether --with-sdl was given. if test "${with_sdl+set}" = set; then : withval=$with_sdl; fi # Check whether --with-svga was given. if test "${with_svga+set}" = set; then : withval=$with_svga; fi # Check whether --with-wx was given. if test "${with_wx+set}" = set; then : withval=$with_wx; fi # Check whether --with-all-libs was given. if test "${with_all_libs+set}" = set; then : withval=$with_all_libs; fi DASH="-" SLASH="/" CXXFP="" CFP="" OFP="-o " MAKELIB="ar rv \$@" RMCOMMAND="rm -f " # first define link variables without libtool LINK="\$(CXX) -o \$@ \$(CXXFLAGS) \$(LDFLAGS)" LINK_CONSOLE="\$(CXX) -o \$@ \$(CXXFLAGS_CONSOLE) \$(LDFLAGS)" # unless NO_LT is set, add libtool to the front of the link command if test "$NO_LT" != 1; then LINK="\$(LIBTOOL) --mode=link --tag CXX $LINK" LINK_CONSOLE="\$(LIBTOOL) --mode=link --tag CXX $LINK_CONSOLE" fi EXE="" COMMAND_SEPARATOR="&& \\" CD_UP_ONE="echo done" CD_UP_TWO="echo done" CD_UP_THREE="echo done" INSTALL_TARGET=install_unix INSTALL_LIST_FOR_PLATFORM= # check for existence of and usable version of wxWidgets. This comes # early so that it could affect which one gets chosen. if test x$WX_CONFIG = x; then # Extract the first word of " wx-config --version ", so it can be a program name with args. set dummy wx-config --version ; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_WX_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$WX_CONFIG"; then ac_cv_prog_WX_CONFIG="$WX_CONFIG" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_WX_CONFIG="wx-config" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_WX_CONFIG" && ac_cv_prog_WX_CONFIG="not_found" fi fi WX_CONFIG=$ac_cv_prog_WX_CONFIG if test -n "$WX_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG" >&5 $as_echo "$WX_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets configuration script" >&5 $as_echo_n "checking for wxWidgets configuration script... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_CONFIG" >&5 $as_echo "$WX_CONFIG" >&6; } ok_wx_version=0 wx_multi_lib=0 needs_gtk2=0 wx_needs_gdk2=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for wxWidgets library version" >&5 $as_echo_n "checking for wxWidgets library version... " >&6; } if test x$WX_CONFIG != xnot_found; then WX_VERSION=`$WX_CONFIG --version` WX_BASENAME=`$WX_CONFIG --basename` # test that version >= 2.3.2. Anybody have a better way to do this? Yuck. case x$WX_VERSION in x2.[012]*) ;; # less than version 2.3.x x2.3.[01]) ;; # less than version 2.3.2 x2.3.[2-4]*) ok_wx_version=1 ;; # 2.3.2 or greater x2.[4-5]*) ok_wx_version=1 ;; # version 2.4 / 2.5 x2.[6-9]*) # version 2.6 or greater ok_wx_version=1 wx_multi_lib=1 case x$WX_BASENAME in xwx_gtk2|xwx_gtk2u) wx_needs_gdk2=1 ;; *) ;; esac ;; x[3-9]*) ok_wx_version=1 ;; # version 3 or greater *) ;; # who knows? esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WX_VERSION" >&5 $as_echo "$WX_VERSION" >&6; } if test "$cross_configure" = 0; then if test "$ok_wx_version" = 1; then # detected a usable version if test "$with_all_libs" = yes; then with_wx=yes fi else if test "$with_wx" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Bochs for wxWidgets cannot be compiled here, disabling it" >&5 $as_echo "$as_me: WARNING: Bochs for wxWidgets cannot be compiled here, disabling it" >&2;} fi with_wx=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default gui on this platform" >&5 $as_echo_n "checking for default gui on this platform... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DEFAULT_GUI" >&5 $as_echo "$DEFAULT_GUI" >&6; } display_libs="" # the $with_* variable tells the gui library to use, but does NOT necessarily # indicate the platform. Settings that depend on the platform should be # handled later. XPM_LIB='' if test "$with_x11" = yes; then display_libs="$display_libs X11" if test "$no_x" = yes; then echo ERROR: X windows gui was selected, but X windows libraries were not found. exit 1 fi check_xpm=0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether user wants XPM support" >&5 $as_echo_n "checking whether user wants XPM support... " >&6; } # Check whether --enable-xpm was given. if test "${enable_xpm+set}" = set; then : enableval=$enable_xpm; if test "$enableval" = yes; then check_xpm=0 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } check_xpm=1 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } check_xpm=0 fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } check_xpm=1 fi if test $check_xpm = 1; then ac_fn_c_check_header_mongrel "$LINENO" "X11/xpm.h" "ac_cv_header_X11_xpm_h" "$ac_includes_default" if test "x$ac_cv_header_X11_xpm_h" = xyes; then : $as_echo "#define BX_HAVE_XPM_H 1" >>confdefs.h XPM_LIB='-lXpm' fi fi if test "$PKGCONFIG" != not_found; then X_CFLAGS="`pkg-config --cflags x11`" X_LIBS="`pkg-config --libs x11` $XPM_LIB -lXrandr" else X_LIBS="$X_LIBS -lX11 $XPM_LIB -lXrandr" fi $as_echo "#define BX_WITH_X11 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_X11)" GUI_CFLAGS="$GUI_CFLAGS \$(X_CFLAGS)" GUI_CXXFLAGS="$GUI_CXXFLAGS \$(X_CFLAGS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_X)" # The enhanced X debugger depends on GTK2 if test "$gui_debugger" = 1; then needs_gtk2=1 fi fi if test "$with_sdl" = yes; then display_libs="$display_libs sdl" $as_echo "#define BX_WITH_SDL 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_SDL)" # GUI_*FLAGS are added to the compilation of every bochs file, not just # the files in gui/*.cc. SDL_CFLAGS=`sdl-config --cflags` GUI_CFLAGS="$GUI_CFLAGS $SDL_CFLAGS" GUI_CXXFLAGS="$GUI_CXXFLAGS $SDL_CFLAGS" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_SDL)" # The enhanced X debugger depends on GTK2 if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then needs_gtk2=1 fi if test "$with_win32" != yes -a "$with_wx" != yes; then case $target in *-pc-windows*) RC_CMD="rc /fo" EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" ;; *-cygwin* | *-mingw32*) RC_CMD="windres -I. -o " EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" ;; esac fi fi if test "$with_svga" = yes; then display_libs="$display_libs svga" $as_echo "#define BX_WITH_SVGA 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_SVGA)" # GUI_*FLAGS are added to the compilation of every bochs file, not just # the files in gui/*.cc. GUI_CFLAGS="$GUI_CFLAGS" GUI_CXXFLAGS="$GUI_CXXFLAGS" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_SVGA)" fi if test "$with_rfb" = yes; then display_libs="$display_libs rfb" $as_echo "#define BX_WITH_RFB 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_RFB)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_RFB)" fi if test "$with_amigaos" = yes; then display_libs="$display_libs amigaos" $as_echo "#define BX_WITH_AMIGAOS 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_AMIGAOS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_AMIGAOS)" fi if test "$with_win32" = yes; then display_libs="$display_libs win32" $as_echo "#define BX_WITH_WIN32 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_WIN32)" case $target in *-pc-windows*) if test "$with_wx" != yes; then RC_CMD="rc /fo" EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" fi GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_WIN32_VCPP)" ;; *-cygwin* | *-mingw32*) if test "$with_wx" != yes; then RC_CMD="windres -I. -o " EXTRA_BX_OBJS="$EXTRA_BX_OBJS win32res.o" fi GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_WIN32)" ;; *) echo Unsupported compile setup: GUI library is win32, but target is neither windows nor cygwin. ;; esac fi if test "$with_macos" = yes; then display_libs="$display_libs macos" $as_echo "#define BX_WITH_MACOS 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_MACOS)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_MACOS)" fi if test "$with_carbon" = yes; then display_libs="$display_libs carbon" $as_echo "#define BX_WITH_CARBON 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_CARBON)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_CARBON)" if test "$bx_plugins" = 1; then PRIMARY_TARGET=bochs.app/.build_plugins # only for carbon application else PRIMARY_TARGET=bochs.app/.build # only for carbon application fi INSTALL_TARGET='install_macosx' fi if test "$with_term" = yes; then display_libs="$display_libs term" $as_echo "#define BX_WITH_TERM 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_TERM)" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_TERM)" use_curses=yes fi if test "$with_wx" = yes; then display_libs="$display_libs wxWidgets" if test "$cross_configure" = 1; then true # do not insist, if configuring for another machine else if test x$ok_wx_version != x1; then echo ERROR: A usable version of wxWidgets was not found. echo Upgrade the library or choose another gui. exit 1 fi fi $as_echo "#define BX_WITH_WX 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_WX)" SPECIFIC_GUI_SUPPORT_OBJS="$SPECIFIC_GUI_SUPPORT_OBJS \$(GUI_OBJS_WX_SUPPORT)" WX_CFLAGS="`$WX_CONFIG --cflags`" WX_CXXFLAGS="`$WX_CONFIG --cxxflags`" if test "$wx_needs_gdk2" = 1; then GDK_CFLAGS="`pkg-config --cflags gdk-2.0`" WX_CFLAGS="$WX_CFLAGS $GDK_CFLAGS" WX_CXXFLAGS="$WX_CXXFLAGS $GDK_CFLAGS" fi if test "$wx_multi_lib" = 1; then GUI_LINK_OPTS_WX="`$WX_CONFIG --libs core,base`" else GUI_LINK_OPTS_WX="`$WX_CONFIG --libs`" fi # GUI_C*FLAGS are added to the compilation of every bochs file, not just # the files in gui/*.cc. They are not used when building other things # such as bximage. GUI_CFLAGS="$GUI_CFLAGS $WX_CFLAGS" GUI_CXXFLAGS="$GUI_CXXFLAGS $WX_CXXFLAGS" GUI_LINK_OPTS="$GUI_LINK_OPTS \$(GUI_LINK_OPTS_WX)" # using debugger with readline is failing due to thread/signal handler # problems. case $target in *-pc-windows* | *-cygwin* | *-mingw32*) EXTRA_BX_OBJS="$EXTRA_BX_OBJS wxbochs_resources.o" GUI_LINK_OPTS_WX="$GUI_LINK_OPTS_WX --subsystem,windows -mwindows" ;; *) # This is required for XStringToKeysym if test "$with_x11" != yes -a "$bx_plugins" != 1; then GUI_LINK_OPTS="$GUI_LINK_OPTS -lX11" fi ;; esac # The enhanced X debugger depends on GTK2 (unused yet, but fixes link failure) if test "$gui_debugger" = 1 -a "$DEFAULT_GUI" != win32; then needs_gtk2=1 fi fi if test "$with_nogui" = yes; then display_libs="$display_libs nogui" $as_echo "#define BX_WITH_NOGUI 1" >>confdefs.h SPECIFIC_GUI_OBJS="$SPECIFIC_GUI_OBJS \$(GUI_OBJS_NOGUI)" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for display libraries" >&5 $as_echo_n "checking for display libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $display_libs" >&5 $as_echo "$display_libs" >&6; } if test "$display_libs" = ""; then echo "No display libraries were selected. Use --with-* options to enable" echo "individual display libraries, or --with-all-libs to detect the ones" echo "that Bochs supports." exit 1 fi # some display libraries and the enhanced debugger may depend on the GTK+ software package if test "$needs_gtk2" = 1; then # pkg-config is required to set TOOLKIT_CXXFLAGS and LIBS if test "$PKGCONFIG" != not_found; then TOOLKIT_CXXFLAGS="`pkg-config --cflags gtk+-2.0`" LIBS="$LIBS `pkg-config --libs gtk+-2.0`" else echo "ERROR: pkg-config was not found, or unable to access the gtk+-2.0 package." echo "Install pkg-config and the gtk+ development package," echo "or disable the gui debugger, or the wxWidgets display library (whichever is being used)." exit 1 fi fi if test "$display_libs" = " wxWidgets"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default configuration interface" >&5 $as_echo_n "checking for default configuration interface... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: wxWidgets" >&5 $as_echo "wxWidgets" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default display library" >&5 $as_echo_n "checking for default display library... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: wxWidgets" >&5 $as_echo "wxWidgets" >&6; } $as_echo "#define BX_DEFAULT_CONFIG_INTERFACE \"wx\"" >>confdefs.h $as_echo "#define BX_DEFAULT_DISPLAY_LIBRARY \"wx\"" >>confdefs.h $as_echo "#define BX_USE_TEXTCONFIG 0" >>confdefs.h else $as_echo "#define BX_USE_TEXTCONFIG 1" >>confdefs.h fi if test "$bx_plugins" = 1; then # every item in this list will be compiled as a plugin. Do not include # support objs; they will be mentioned in plugin-specific makefile rules. GUI_PLUGIN_OBJS="$GUI_PLUGIN_OBJS $SPECIFIC_GUI_OBJS" else # include support objs GUI_NON_PLUGIN_OBJS="$GUI_NON_PLUGIN_OBJS $SPECIFIC_GUI_OBJS $SPECIFIC_GUI_SUPPORT_OBJS" fi for ac_prog in wget curl fetch do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_WGET+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$WGET"; then ac_cv_prog_WGET="$WGET" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_WGET="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi WGET=$ac_cv_prog_WGET if test -n "$WGET"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $WGET" >&5 $as_echo "$WGET" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$WGET" && break done test -n "$WGET" || WGET="not_found" if test "$WGET" = not_found; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find wget (or equivalent) command" >&5 $as_echo "$as_me: WARNING: cannot find wget (or equivalent) command" >&2;} fi # everybody has to re-invent the wheel. differently. test "${WGET}" = "curl" && WGET="curl -O" # modify settings based on target platform case "$target" in *-macosx*) $as_echo "#define BX_HAVE_STRDUP 0" >>confdefs.h ;; *-macos*) $as_echo "#define BX_HAVE_STRDUP 0" >>confdefs.h $as_echo "#define BX_PLUGINS 0" >>confdefs.h $as_echo "#define BX_HAVE_DLFCN_H 0" >>confdefs.h $as_echo "#define BX_HAVE_SOCKLEN_T 0" >>confdefs.h $as_echo "#define BX_HAVE_SELECT 0" >>confdefs.h $as_echo "#define BX_HAVE_GETTIMEOFDAY 0" >>confdefs.h $as_echo "#define BX_NO_ATTRIBUTES 1" >>confdefs.h $as_echo "#define BX_NETMOD_TUNTAP 0" >>confdefs.h $as_echo "#define BX_NETMOD_TAP 0" >>confdefs.h ;; *-pc-windows*) INSTALL_TARGET='install_win32' CC="cl" CXX="$CC" #C_OPT="/Zi" # for debugging C_OPT="/Ox" # optimize for speed if test "$bx_plugins" = 1; then CFLAGS="/nologo /MD /W3 /EHs-c- /DNDEBUG /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS $C_OPT" else CFLAGS="/nologo /MT /W3 /EHs-c- /DNDEBUG /DWIN32 /D_WINDOWS /D_CRT_SECURE_NO_WARNINGS $C_OPT" fi CXXFLAGS="$CFLAGS" DASH="/" SLASH="\\" CXXFP="/Tp" CFP="/Tc" OFP="/Fo" MAKE=nmake MAKELIB="lib /nologo /subsystem:console /verbose /out:\$@" RMCOMMAND="-del" RANLIB="echo" #L_OPT="/debug" # for debugging L_OPT="" # no debug info LINK="link $L_OPT /nologo /subsystem:console /incremental:no /out:\$@ " LINK_CONSOLE=$LINK EXE=".exe" PRIMARY_TARGET="bochs.exe" BXIMAGE_LINK_OPTS="user32.lib" # also compile niclist if networking is on if test "$networking" = yes; then PRIMARY_TARGET="$PRIMARY_TARGET niclist.exe" fi COMMAND_SEPARATOR="" CD_UP_ONE="cd .." CD_UP_TWO="cd ..\.." CD_UP_THREE="cd ..\..\.." have_gettimeofday=0 # even though it may exist in build environment $as_echo "#define BX_64BIT_CONSTANTS_USE_LL 0" >>confdefs.h $as_echo "#define inline __forceinline" >>confdefs.h $as_echo "#define BX_NO_ATTRIBUTES 1" >>confdefs.h $as_echo "#define HAVE_LIBREADLINE 0" >>confdefs.h $as_echo "#define HAVE_READLINE_HISTORY_H 0" >>confdefs.h READLINE_LIB=""; $as_echo "#define BX_HAVE_DLFCN_H 0" >>confdefs.h $as_echo "#define BX_NETMOD_TAP 0" >>confdefs.h ;; *-pc-cygwin*) EXE=".exe" PRIMARY_TARGET="bochs.exe" BXIMAGE_LINK_OPTS="-luser32" if test "$networking" = yes; then PRIMARY_TARGET="$PRIMARY_TARGET niclist.exe" fi $as_echo "#define BX_HAVE_SELECT 1" >>confdefs.h ;; *-pc-mingw*) BXIMAGE_LINK_OPTS="-luser32" if test "$networking" = yes; then PRIMARY_TARGET="$PRIMARY_TARGET niclist" fi $as_echo "#define BX_HAVE_SELECT 1" >>confdefs.h ;; esac ENH_DBG_OBJS="" if test "$gui_debugger" = 1; then if test "$needs_gtk2" = 1; then ENH_DBG_OBJS="gtk_enh_dbg_osdep.o" elif test "$DEFAULT_GUI" = win32; then ENH_DBG_OBJS="win32_enh_dbg_osdep.o" fi fi DIALOG_OBJS="" EXPORT_DYNAMIC="-export-dynamic" case $target in *-pc-windows* | *-pc-winnt*) if test "$bx_plugins" = 1; then # set variables for building DLL plugins PLUGIN_VAR="" PLUGIN_LIBNAME_TRANSFORMATION='%.o=bx_%.dll' INSTALL_PLUGINS_VAR=install_dll_plugins LIBS="$LIBS advapi32.lib comctl32.lib comdlg32.lib gdi32.lib shell32.lib user32.lib" else if test "$with_win32" != yes; then LIBS="$LIBS comctl32.lib" fi fi DIALOG_OBJS="win32dialog.o win32paramdlg.o" EXPORT_DYNAMIC="" ;; *-cygwin* | *-mingw*) if test "$bx_plugins" = 1; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for opendir in -lmingwex" >&5 $as_echo_n "checking for opendir in -lmingwex... " >&6; } if ${ac_cv_lib_mingwex_opendir+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lmingwex $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char opendir (); int main () { return opendir (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_mingwex_opendir=yes else ac_cv_lib_mingwex_opendir=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_mingwex_opendir" >&5 $as_echo "$ac_cv_lib_mingwex_opendir" >&6; } if test "x$ac_cv_lib_mingwex_opendir" = xyes; then : LIBS="$LIBS -lmingwex" fi # set variables for building DLL plugins PRIMARY_TARGET=".win32_dll_plugin_target" PLUGIN_LIBNAME_TRANSFORMATION='%.o=bx_%.dll' INSTALL_PLUGINS_VAR=install_dll_plugins else if test "$with_win32" != yes; then LIBS="$LIBS -lcomctl32" fi fi DIALOG_OBJS="win32dialog.o win32paramdlg.o" EXPORT_DYNAMIC="" ;; esac if test "$use_curses" = yes -a "$cross_configure" = 0; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -lcurses" >&5 $as_echo_n "checking for mvaddch in -lcurses... " >&6; } if ${ac_cv_lib_curses_mvaddch+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lcurses $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mvaddch (); int main () { return mvaddch (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_curses_mvaddch=yes else ac_cv_lib_curses_mvaddch=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_mvaddch" >&5 $as_echo "$ac_cv_lib_curses_mvaddch" >&6; } if test "x$ac_cv_lib_curses_mvaddch" = xyes; then : GUI_LINK_OPTS_TERM='-lcurses' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -lncurses" >&5 $as_echo_n "checking for mvaddch in -lncurses... " >&6; } if ${ac_cv_lib_ncurses_mvaddch+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lncurses $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mvaddch (); int main () { return mvaddch (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_ncurses_mvaddch=yes else ac_cv_lib_ncurses_mvaddch=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_mvaddch" >&5 $as_echo "$ac_cv_lib_ncurses_mvaddch" >&6; } if test "x$ac_cv_lib_ncurses_mvaddch" = xyes; then : GUI_LINK_OPTS_TERM='-lncurses' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -ltermlib" >&5 $as_echo_n "checking for mvaddch in -ltermlib... " >&6; } if ${ac_cv_lib_termlib_mvaddch+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ltermlib $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mvaddch (); int main () { return mvaddch (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_termlib_mvaddch=yes else ac_cv_lib_termlib_mvaddch=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_termlib_mvaddch" >&5 $as_echo "$ac_cv_lib_termlib_mvaddch" >&6; } if test "x$ac_cv_lib_termlib_mvaddch" = xyes; then : GUI_LINK_OPTS_TERM='-ltermlib' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mvaddch in -lpdcurses" >&5 $as_echo_n "checking for mvaddch in -lpdcurses... " >&6; } if ${ac_cv_lib_pdcurses_mvaddch+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lpdcurses $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mvaddch (); int main () { return mvaddch (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_pdcurses_mvaddch=yes else ac_cv_lib_pdcurses_mvaddch=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pdcurses_mvaddch" >&5 $as_echo "$ac_cv_lib_pdcurses_mvaddch" >&6; } if test "x$ac_cv_lib_pdcurses_mvaddch" = xyes; then : GUI_LINK_OPTS_TERM='-lpdcurses' fi if test "$GUI_LINK_OPTS_TERM" = ""; then echo Curses library not found: tried curses, ncurses, termlib and pdcurses. exit 1 fi fi if test "$with_term" = yes; then old_LIBS="$LIBS" LIBS="$LIBS $GUI_LINK_OPTS_TERM" for ac_func in color_set do : ac_fn_c_check_func "$LINENO" "color_set" "ac_cv_func_color_set" if test "x$ac_cv_func_color_set" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_COLOR_SET 1 _ACEOF $as_echo "#define BX_HAVE_COLOR_SET 1" >>confdefs.h fi done for ac_func in mvhline do : ac_fn_c_check_func "$LINENO" "mvhline" "ac_cv_func_mvhline" if test "x$ac_cv_func_mvhline" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MVHLINE 1 _ACEOF $as_echo "#define BX_HAVE_MVHLINE 1" >>confdefs.h fi done for ac_func in mvvline do : ac_fn_c_check_func "$LINENO" "mvvline" "ac_cv_func_mvvline" if test "x$ac_cv_func_mvvline" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_MVVLINE 1 _ACEOF $as_echo "#define BX_HAVE_MVVLINE 1" >>confdefs.h fi done LIBS="$old_LIBS" fi if test "$with_rfb" = yes; then # we need the socket function case $target in *-pc-windows*) # is this okay without a check ? RFB_LIBS="$RFB_LIBS wsock32.lib" have_socket=yes ;; *-pc-winnt* | *-pc-cygwin* | *-mingw32*) # is this okay without a check ? RFB_LIBS="$RFB_LIBS -lwsock32" have_socket=yes ;; *) for ac_func in socket do : ac_fn_c_check_func "$LINENO" "socket" "ac_cv_func_socket" if test "x$ac_cv_func_socket" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SOCKET 1 _ACEOF have_socket=yes fi done if test "$have_socket" != yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socket in -lsocket" >&5 $as_echo_n "checking for socket in -lsocket... " >&6; } if ${ac_cv_lib_socket_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsocket $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_socket_socket=yes else ac_cv_lib_socket_socket=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_socket" >&5 $as_echo "$ac_cv_lib_socket_socket" >&6; } if test "x$ac_cv_lib_socket_socket" = xyes; then : RFB_LIBS="$RFB_LIBS -lsocket" have_socket=yes fi fi ;; esac if test "$have_socket" != yes; then echo 'ERROR: socket function required for RFB compile' exit 1 fi fi # The ACX_PTHREAD function was written by # Steven G. Johnson and # Alejandro Forero Cuervo # I found it in the ac-archive project on Source Forge. pthread_ok=no acx_pthread_ok=no # First, check if the POSIX threads header, pthread.h, is available. # If it isn't, don't bother looking for the threads libraries. ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" if test "x$ac_cv_header_pthread_h" = xyes; then : else acx_pthread_ok=noheader fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test x"$acx_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all. acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # pthread: Linux, etcetera # --thread-safe: KAI C++ case "${host_cpu}-${host_os}" in *solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthread or # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" ;; esac if test x"$acx_pthread_ok" = xno; then for flag in $acx_pthread_flags; do case $flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { pthread_t th; pthread_join(th, 0); pthread_attr_init(0); pthread_cleanup_push(0, 0); pthread_create(0,0,0,0); pthread_cleanup_pop(0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : acx_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $acx_pthread_ok" >&5 $as_echo "$acx_pthread_ok" >&6; } if test "x$acx_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$acx_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: threads are created detached by default # and the JOINABLE attribute has a nonstandard name (UNDETACHED). { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_JOINABLE; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=PTHREAD_CREATE_JOINABLE else ok=unknown fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x"$ok" = xunknown; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr=PTHREAD_CREATE_UNDETACHED; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ok=PTHREAD_CREATE_UNDETACHED else ok=unknown fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then $as_echo "#define PTHREAD_CREATE_JOINABLE \$ok" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${ok}" >&5 $as_echo "${ok}" >&6; } if test x"$ok" = xunknown; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: we do not know how to create joinable pthreads" >&5 $as_echo "$as_me: WARNING: we do not know how to create joinable pthreads" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case "${host_cpu}-${host_os}" in *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; *solaris* | alpha*-osf*) flag="-D_REENTRANT";; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${flag}" >&5 $as_echo "${flag}" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with cc_r # Extract the first word of "cc_r", so it can be a program name with args. set dummy cc_r; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_prog_PTHREAD_CC="cc_r" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_PTHREAD_CC" && ac_cv_prog_PTHREAD_CC="${CC}" fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else PTHREAD_CC="$CC" fi # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$acx_pthread_ok" = xyes; then pthread_ok=yes #echo Using PTHREAD_LIBS=$PTHREAD_LIBS #echo Using PTHREAD_CFLAGS=$PTHREAD_CFLAGS #echo Using PTHREAD_CC=$PTHREAD_CC : else acx_pthread_ok=no fi # since some features need the pthread library, check that it was found. # But on win32 platforms, the pthread library is not needed. if test "$cross_configure" = 0; then if test "$with_rfb" = yes -o "$soundcard_present" = 1; then if test "$pthread_ok" = yes; then if test "$with_rfb" = yes; then RFB_LIBS="$RFB_LIBS $PTHREAD_LIBS" fi if test "$soundcard_present" = 1; then if test "$bx_plugins" = 1; then SOUND_LINK_OPTS="$SOUND_LINK_OPTS $PTHREAD_LIBS" else DEVICE_LINK_OPTS="$DEVICE_LINK_OPTS $PTHREAD_LIBS" fi fi CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" else case "$target" in *-pc-windows* | *-pc-winnt* | *-cygwin* | *-mingw32*) # pthread not needed for win32 platform ;; *) echo ERROR: the pthread library is required, but could not be found.; exit 1 esac fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for APIC support (deprecated)" >&5 $as_echo_n "checking for APIC support (deprecated)... " >&6; } # Check whether --enable-apic was given. if test "${enable_apic+set}" = set; then : enableval=$enable_apic; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } as_fn_error $? "DEPRECATED - enabled automatically with SMP or when CPU_LEVEL >= 5" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for X2APIC support (deprecated)" >&5 $as_echo_n "checking for X2APIC support (deprecated)... " >&6; } # Check whether --enable-x2apic was given. if test "${enable_x2apic+set}" = set; then : enableval=$enable_x2apic; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } as_fn_error $? "DEPRECATED - moved to .bochsrc options" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for VESA BIOS extensions (deprecated)" >&5 $as_echo_n "checking for VESA BIOS extensions (deprecated)... " >&6; } # Check whether --enable-vbe was given. if test "${enable_vbe+set}" = set; then : enableval=$enable_vbe; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } as_fn_error $? "DEPRECATED - this feature always available with .bochsrc option" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ACPI extensions support (deprecated)" >&5 $as_echo_n "checking for ACPI extensions support (deprecated)... " >&6; } # Check whether --enable-acpi was given. if test "${enable_acpi+set}" = set; then : enableval=$enable_acpi; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } as_fn_error $? "DEPRECATED - this feature enabled with PCI configure option and could be turned on through .bochsrc option" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for instruction trace cache support (deprecated)" >&5 $as_echo_n "checking for instruction trace cache support (deprecated)... " >&6; } # Check whether --enable-trace-cache was given. if test "${enable_trace_cache+set}" = set; then : enableval=$enable_trace_cache; { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enableval" >&5 $as_echo "$enableval" >&6; } as_fn_error $? "DEPRECATED - this feature will be enabled in all configurations" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Create some subdirectories for when you run configure from some other # directory. if test ! -d instrument; then mkdir instrument; fi if test ! -d build; then mkdir build; fi if test ! -d build/linux; then mkdir build/linux; fi if test ! -d build/win32; then mkdir build/win32; fi if test ! -d build/win32/nsis; then mkdir build/win32/nsis; fi # Extract the first word of "gzip", so it can be a program name with args. set dummy gzip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GZIP+:} false; then : $as_echo_n "(cached) " >&6 else case $GZIP in [\\/]* | ?:[\\/]*) ac_cv_path_GZIP="$GZIP" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_GZIP="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GZIP=$ac_cv_path_GZIP if test -n "$GZIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GZIP" >&5 $as_echo "$GZIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "tar", so it can be a program name with args. set dummy tar; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_TAR+:} false; then : $as_echo_n "(cached) " >&6 else case $TAR in [\\/]* | ?:[\\/]*) ac_cv_path_TAR="$TAR" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then ac_cv_path_TAR="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi TAR=$ac_cv_path_TAR if test -n "$TAR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $TAR" >&5 $as_echo "$TAR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ac_config_files="$ac_config_files Makefile iodev/Makefile iodev/hdimage/Makefile iodev/usb/Makefile iodev/network/Makefile iodev/sound/Makefile bx_debug/Makefile bios/Makefile cpu/Makefile cpu/cpudb/Makefile memory/Makefile gui/Makefile disasm/Makefile ${INSTRUMENT_DIR}/Makefile misc/Makefile fpu/Makefile doc/docbook/Makefile build/linux/bochs-dlx bxversion.h bxversion.rc build/macosx/Info.plist build/win32/nsis/Makefile build/win32/nsis/bochs.nsi host/linux/pcidev/Makefile" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -p'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -p' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -p' fi else as_ln_s='cp -p' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi if test -x / >/dev/null 2>&1; then as_test_x='test -x' else if ls -dL / >/dev/null 2>&1; then as_ls_L_option=L else as_ls_L_option= fi as_test_x=' eval sh -c '\'' if test -d "$1"; then test -d "$1/."; else case $1 in #( -*)set "./$1";; esac; case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( ???[sx]*):;;*)false;;esac;fi '\'' sh ' fi as_executable_p=$as_test_x # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by $as_me, which was generated by GNU Autoconf 2.68. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ config.status configured by $0, generated by GNU Autoconf 2.68, with options \\"\$ac_cs_config\\" Copyright (C) 2010 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "ltdlconf.h") CONFIG_HEADERS="$CONFIG_HEADERS ltdlconf.h" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "iodev/Makefile") CONFIG_FILES="$CONFIG_FILES iodev/Makefile" ;; "iodev/hdimage/Makefile") CONFIG_FILES="$CONFIG_FILES iodev/hdimage/Makefile" ;; "iodev/usb/Makefile") CONFIG_FILES="$CONFIG_FILES iodev/usb/Makefile" ;; "iodev/network/Makefile") CONFIG_FILES="$CONFIG_FILES iodev/network/Makefile" ;; "iodev/sound/Makefile") CONFIG_FILES="$CONFIG_FILES iodev/sound/Makefile" ;; "bx_debug/Makefile") CONFIG_FILES="$CONFIG_FILES bx_debug/Makefile" ;; "bios/Makefile") CONFIG_FILES="$CONFIG_FILES bios/Makefile" ;; "cpu/Makefile") CONFIG_FILES="$CONFIG_FILES cpu/Makefile" ;; "cpu/cpudb/Makefile") CONFIG_FILES="$CONFIG_FILES cpu/cpudb/Makefile" ;; "memory/Makefile") CONFIG_FILES="$CONFIG_FILES memory/Makefile" ;; "gui/Makefile") CONFIG_FILES="$CONFIG_FILES gui/Makefile" ;; "disasm/Makefile") CONFIG_FILES="$CONFIG_FILES disasm/Makefile" ;; "${INSTRUMENT_DIR}/Makefile") CONFIG_FILES="$CONFIG_FILES ${INSTRUMENT_DIR}/Makefile" ;; "misc/Makefile") CONFIG_FILES="$CONFIG_FILES misc/Makefile" ;; "fpu/Makefile") CONFIG_FILES="$CONFIG_FILES fpu/Makefile" ;; "doc/docbook/Makefile") CONFIG_FILES="$CONFIG_FILES doc/docbook/Makefile" ;; "build/linux/bochs-dlx") CONFIG_FILES="$CONFIG_FILES build/linux/bochs-dlx" ;; "bxversion.h") CONFIG_FILES="$CONFIG_FILES bxversion.h" ;; "bxversion.rc") CONFIG_FILES="$CONFIG_FILES bxversion.rc" ;; "build/macosx/Info.plist") CONFIG_FILES="$CONFIG_FILES build/macosx/Info.plist" ;; "build/win32/nsis/Makefile") CONFIG_FILES="$CONFIG_FILES build/win32/nsis/Makefile" ;; "build/win32/nsis/bochs.nsi") CONFIG_FILES="$CONFIG_FILES build/win32/nsis/bochs.nsi" ;; "host/linux/pcidev/Makefile") CONFIG_FILES="$CONFIG_FILES host/linux/pcidev/Makefile" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi bochs-2.6/cpu/0000755000175000017500000000000012020641453013121 5ustar guillemguillembochs-2.6/cpu/mmx.cc0000644000175000017500000021764612020641453014251 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: mmx.cc 11330 2012-08-09 13:11:25Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2002-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 5 void BX_CPU_C::print_state_MMX(void) { for(int i=0;i<8;i++) { BxPackedMmxRegister mm = BX_READ_MMX_REG(i); BX_DEBUG(("MM%d: %08x%08x\n", i, MMXUD1(mm), MMXUD0(mm))); } } #endif #if BX_CPU_LEVEL >= 6 /* 0F 38 00 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFB_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2, result; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ for(unsigned j=0; j<8; j++) { unsigned mask = op2.mmxubyte(j); if (mask & 0x80) result.mmxubyte(j) = 0; else result.mmxubyte(j) = op1.mmxubyte(mask & 0x7); } BX_WRITE_MMX_REG(i->dst(), result); BX_NEXT_INSTR(i); } /* 0F 38 01 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = MMXUW0(op1) + MMXUW1(op1); MMXUW1(op1) = MMXUW2(op1) + MMXUW3(op1); MMXUW2(op1) = MMXUW0(op2) + MMXUW1(op2); MMXUW3(op1) = MMXUW2(op2) + MMXUW3(op2); BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 02 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDD_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(op1) = MMXUD0(op1) + MMXUD1(op1); MMXUD1(op1) = MMXUD0(op2) + MMXUD1(op2); BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 03 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PHADDSW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) + Bit32s(MMXSW1(op1))); MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) + Bit32s(MMXSW3(op1))); MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op2)) + Bit32s(MMXSW1(op2))); MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op2)) + Bit32s(MMXSW3(op2))); BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 04 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMADDUBSW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ for(unsigned j=0; j<4; j++) { Bit32s temp = Bit32s(op1.mmxubyte(j*2+0))*Bit32s(op2.mmxsbyte(j*2)) + Bit32s(op1.mmxubyte(j*2+1))*Bit32s(op2.mmxsbyte(j*2+1)); op1.mmx16s(j) = SaturateDwordSToWordS(temp); } BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 05 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBSW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) - Bit32s(MMXSW1(op1))); MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) - Bit32s(MMXSW3(op1))); MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op2)) - Bit32s(MMXSW1(op2))); MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op2)) - Bit32s(MMXSW3(op2))); BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 05 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = MMXUW0(op1) - MMXUW1(op1); MMXUW1(op1) = MMXUW2(op1) - MMXUW3(op1); MMXUW2(op1) = MMXUW0(op2) - MMXUW1(op2); MMXUW3(op1) = MMXUW2(op2) - MMXUW3(op2); BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 06 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PHSUBD_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(op1) = MMXUD0(op1) - MMXUD1(op1); MMXUD1(op1) = MMXUD0(op2) - MMXUD1(op2); BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 08 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGNB_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ for(unsigned j=0; j<8; j++) { int sign = (op2.mmxsbyte(j) > 0) - (op2.mmxsbyte(j) < 0); op1.mmxsbyte(j) *= sign; } BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 09 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGNW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ for(unsigned j=0; j<4; j++) { int sign = (op2.mmx16s(j) > 0) - (op2.mmx16s(j) < 0); op1.mmx16s(j) *= sign; } BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 0A */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSIGND_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ int sign; sign = (MMXSD0(op2) > 0) - (MMXSD0(op2) < 0); MMXSD0(op1) *= sign; sign = (MMXSD1(op2) > 0) - (MMXSD1(op2) < 0); MMXSD1(op1) *= sign; BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 0B */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHRSW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = (((MMXSW0(op1) * MMXSW0(op2)) >> 14) + 1) >> 1; MMXUW1(op1) = (((MMXSW1(op1) * MMXSW1(op2)) >> 14) + 1) >> 1; MMXUW2(op1) = (((MMXSW2(op1) * MMXSW2(op2)) >> 14) + 1) >> 1; MMXUW3(op1) = (((MMXSW3(op1) * MMXSW3(op2)) >> 14) + 1) >> 1; BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* 0F 38 1C */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSB_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op; if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if (MMXSB0(op) < 0) MMXUB0(op) = -MMXSB0(op); if (MMXSB1(op) < 0) MMXUB1(op) = -MMXSB1(op); if (MMXSB2(op) < 0) MMXUB2(op) = -MMXSB2(op); if (MMXSB3(op) < 0) MMXUB3(op) = -MMXSB3(op); if (MMXSB4(op) < 0) MMXUB4(op) = -MMXSB4(op); if (MMXSB5(op) < 0) MMXUB5(op) = -MMXSB5(op); if (MMXSB6(op) < 0) MMXUB6(op) = -MMXSB6(op); if (MMXSB7(op) < 0) MMXUB7(op) = -MMXSB7(op); BX_WRITE_MMX_REG(i->dst(), op); BX_NEXT_INSTR(i); } /* 0F 38 1D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSW_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op; if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if (MMXSW0(op) < 0) MMXUW0(op) = -MMXSW0(op); if (MMXSW1(op) < 0) MMXUW1(op) = -MMXSW1(op); if (MMXSW2(op) < 0) MMXUW2(op) = -MMXSW2(op); if (MMXSW3(op) < 0) MMXUW3(op) = -MMXSW3(op); BX_WRITE_MMX_REG(i->dst(), op); BX_NEXT_INSTR(i); } /* 0F 38 1E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PABSD_PqQq(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op; if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if (MMXSD0(op) < 0) MMXUD0(op) = -MMXSD0(op); if (MMXSD1(op) < 0) MMXUD1(op) = -MMXSD1(op); BX_WRITE_MMX_REG(i->dst(), op); BX_NEXT_INSTR(i); } /* 0F 3A 0F */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PALIGNR_PqQqIb(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ unsigned shift = i->Ib() * 8; if(shift == 0) MMXUQ(op1) = MMXUQ(op2); else if(shift < 64) MMXUQ(op1) = (MMXUQ(op2) >> shift) | (MMXUQ(op1) << (64-shift)); else if(shift < 128) MMXUQ(op1) = MMXUQ(op1) >> (shift-64); else MMXUQ(op1) = 0; BX_WRITE_MMX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } #endif /* 0F 60 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLBW_PqQd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_dword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB7(op1) = MMXUB3(op2); MMXUB6(op1) = MMXUB3(op1); MMXUB5(op1) = MMXUB2(op2); MMXUB4(op1) = MMXUB2(op1); MMXUB3(op1) = MMXUB1(op2); MMXUB2(op1) = MMXUB1(op1); MMXUB1(op1) = MMXUB0(op2); //MMXUB0(op1) = MMXUB0(op1); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 61 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLWD_PqQd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_dword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW3(op1) = MMXUW1(op2); MMXUW2(op1) = MMXUW1(op1); MMXUW1(op1) = MMXUW0(op2); //MMXUW0(op1) = MMXUW0(op1); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 62 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKLDQ_PqQd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_dword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD1(op1) = MMXUD0(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 63 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSWB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSB0(op1) = SaturateWordSToByteS(MMXSW0(op1)); MMXSB1(op1) = SaturateWordSToByteS(MMXSW1(op1)); MMXSB2(op1) = SaturateWordSToByteS(MMXSW2(op1)); MMXSB3(op1) = SaturateWordSToByteS(MMXSW3(op1)); MMXSB4(op1) = SaturateWordSToByteS(MMXSW0(op2)); MMXSB5(op1) = SaturateWordSToByteS(MMXSW1(op2)); MMXSB6(op1) = SaturateWordSToByteS(MMXSW2(op2)); MMXSB7(op1) = SaturateWordSToByteS(MMXSW3(op2)); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 64 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) = (MMXSB0(op1) > MMXSB0(op2)) ? 0xff : 0; MMXUB1(op1) = (MMXSB1(op1) > MMXSB1(op2)) ? 0xff : 0; MMXUB2(op1) = (MMXSB2(op1) > MMXSB2(op2)) ? 0xff : 0; MMXUB3(op1) = (MMXSB3(op1) > MMXSB3(op2)) ? 0xff : 0; MMXUB4(op1) = (MMXSB4(op1) > MMXSB4(op2)) ? 0xff : 0; MMXUB5(op1) = (MMXSB5(op1) > MMXSB5(op2)) ? 0xff : 0; MMXUB6(op1) = (MMXSB6(op1) > MMXSB6(op2)) ? 0xff : 0; MMXUB7(op1) = (MMXSB7(op1) > MMXSB7(op2)) ? 0xff : 0; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 65 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = (MMXSW0(op1) > MMXSW0(op2)) ? 0xffff : 0; MMXUW1(op1) = (MMXSW1(op1) > MMXSW1(op2)) ? 0xffff : 0; MMXUW2(op1) = (MMXSW2(op1) > MMXSW2(op2)) ? 0xffff : 0; MMXUW3(op1) = (MMXSW3(op1) > MMXSW3(op2)) ? 0xffff : 0; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 66 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPGTD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(op1) = (MMXSD0(op1) > MMXSD0(op2)) ? 0xffffffff : 0; MMXUD1(op1) = (MMXSD1(op1) > MMXSD1(op2)) ? 0xffffffff : 0; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 67 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKUSWB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) = SaturateWordSToByteU(MMXSW0(op1)); MMXUB1(op1) = SaturateWordSToByteU(MMXSW1(op1)); MMXUB2(op1) = SaturateWordSToByteU(MMXSW2(op1)); MMXUB3(op1) = SaturateWordSToByteU(MMXSW3(op1)); MMXUB4(op1) = SaturateWordSToByteU(MMXSW0(op2)); MMXUB5(op1) = SaturateWordSToByteU(MMXSW1(op2)); MMXUB6(op1) = SaturateWordSToByteU(MMXSW2(op2)); MMXUB7(op1) = SaturateWordSToByteU(MMXSW3(op2)); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 68 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHBW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) = MMXUB4(op1); MMXUB1(op1) = MMXUB4(op2); MMXUB2(op1) = MMXUB5(op1); MMXUB3(op1) = MMXUB5(op2); MMXUB4(op1) = MMXUB6(op1); MMXUB5(op1) = MMXUB6(op2); MMXUB6(op1) = MMXUB7(op1); MMXUB7(op1) = MMXUB7(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 69 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHWD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = MMXUW2(op1); MMXUW1(op1) = MMXUW2(op2); MMXUW2(op1) = MMXUW3(op1); MMXUW3(op1) = MMXUW3(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 6A */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUNPCKHDQ_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(op1) = MMXUD1(op1); MMXUD1(op1) = MMXUD1(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 6B */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PACKSSDW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSW0(op1) = SaturateDwordSToWordS(MMXSD0(op1)); MMXSW1(op1) = SaturateDwordSToWordS(MMXSD1(op1)); MMXSW2(op1) = SaturateDwordSToWordS(MMXSD0(op2)); MMXSW3(op1) = SaturateDwordSToWordS(MMXSD1(op2)); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 6E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_PqEdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op; MMXUQ(op) = (Bit64u) BX_READ_32BIT_REG(i->src()); BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_PqEdM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); MMXUQ(op) = (Bit64u) read_virtual_dword(i->seg(), eaddr); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 6E */ #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqEqR(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op; MMXUQ(op) = BX_READ_64BIT_REG(i->src()); BX_WRITE_MMX_REG(i->dst(), op); BX_NEXT_INSTR(i); } #endif /* 0F 6F */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqQqR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BX_WRITE_MMX_REG(i->dst(), BX_READ_MMX_REG(i->src())); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_PqQqM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 70 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFW_PqQqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op, result; Bit8u order = i->Ib(); /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(result) = op.mmx16u((order) & 0x3); MMXUW1(result) = op.mmx16u((order>>2) & 0x3); MMXUW2(result) = op.mmx16u((order>>4) & 0x3); MMXUW3(result) = op.mmx16u((order>>6) & 0x3); BX_WRITE_MMX_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* 0F 74 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) = (MMXUB0(op1) == MMXUB0(op2)) ? 0xff : 0; MMXUB1(op1) = (MMXUB1(op1) == MMXUB1(op2)) ? 0xff : 0; MMXUB2(op1) = (MMXUB2(op1) == MMXUB2(op2)) ? 0xff : 0; MMXUB3(op1) = (MMXUB3(op1) == MMXUB3(op2)) ? 0xff : 0; MMXUB4(op1) = (MMXUB4(op1) == MMXUB4(op2)) ? 0xff : 0; MMXUB5(op1) = (MMXUB5(op1) == MMXUB5(op2)) ? 0xff : 0; MMXUB6(op1) = (MMXUB6(op1) == MMXUB6(op2)) ? 0xff : 0; MMXUB7(op1) = (MMXUB7(op1) == MMXUB7(op2)) ? 0xff : 0; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 75 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = (MMXUW0(op1) == MMXUW0(op2)) ? 0xffff : 0; MMXUW1(op1) = (MMXUW1(op1) == MMXUW1(op2)) ? 0xffff : 0; MMXUW2(op1) = (MMXUW2(op1) == MMXUW2(op2)) ? 0xffff : 0; MMXUW3(op1) = (MMXUW3(op1) == MMXUW3(op2)) ? 0xffff : 0; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 76 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPEQD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(op1) = (MMXUD0(op1) == MMXUD0(op2)) ? 0xffffffff : 0; MMXUD1(op1) = (MMXUD1(op1) == MMXUD1(op2)) ? 0xffffffff : 0; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 77 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::EMMS(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); FPU_TAG_WORD = 0xffff; FPU_TOS = 0; /* reset FPU Top-Of-Stack */ #endif BX_NEXT_INSTR(i); } /* 0F 7E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_EdPdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); BxPackedMmxRegister op = BX_READ_MMX_REG(i->src()); BX_WRITE_32BIT_REGZ(i->dst(), MMXUD0(op)); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_EdPdM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op = BX_READ_MMX_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ write_virtual_dword(i->seg(), eaddr, MMXUD0(op)); // do not cause FPU2MMX transition if memory write faults BX_CPU_THIS_PTR prepareFPU2MMX(); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 /* 0F 7E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_EqPqR(bxInstruction_c *i) { BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); BX_WRITE_64BIT_REG(i->dst(), BX_MMX_REG(i->src())); BX_NEXT_INSTR(i); } #endif /* 0F 7F - MOVQ_QqPqM */ /* 0F E7 - MOVNTQ_MqPq */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_QqPqM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ write_virtual_qword(i->seg(), eaddr, BX_MMX_REG(i->src())); // do not cause FPU2MMX transition if memory write faults BX_CPU_THIS_PTR prepareFPU2MMX(); #endif BX_NEXT_INSTR(i); } /* 0F C4 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRW_PqEwIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()); Bit16u op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op2 = read_virtual_word(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ op1.mmx16u(i->Ib() & 0x3) = op2; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F C5 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRW_GdPqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->src()); Bit32u result = (Bit32u) op.mmx16u(i->Ib() & 0x3); BX_WRITE_32BIT_REGZ(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* 0F D1 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUQ(op2) > 15) MMXUQ(op1) = 0; else { Bit8u shift = MMXUB0(op2); MMXUW0(op1) >>= shift; MMXUW1(op1) >>= shift; MMXUW2(op1) >>= shift; MMXUW3(op1) >>= shift; } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F D2 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUQ(op2) > 31) MMXUQ(op1) = 0; else { Bit8u shift = MMXUB0(op2); MMXUD0(op1) >>= shift; MMXUD1(op1) >>= shift; } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F D3 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUQ(op2) > 63) { MMXUQ(op1) = 0; } else { MMXUQ(op1) >>= MMXUB0(op2); } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F D4 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDQ_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(op1) += MMXUQ(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F D5 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULLW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ Bit32u product1 = Bit32u(MMXUW0(op1)) * Bit32u(MMXUW0(op2)); Bit32u product2 = Bit32u(MMXUW1(op1)) * Bit32u(MMXUW1(op2)); Bit32u product3 = Bit32u(MMXUW2(op1)) * Bit32u(MMXUW2(op2)); Bit32u product4 = Bit32u(MMXUW3(op1)) * Bit32u(MMXUW3(op2)); MMXUW0(op1) = product1 & 0xffff; MMXUW1(op1) = product2 & 0xffff; MMXUW2(op1) = product3 & 0xffff; MMXUW3(op1) = product4 & 0xffff; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F D7 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVMSKB_GdPRq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->src()); Bit32u result = 0; if(MMXUB0(op) & 0x80) result |= 0x01; if(MMXUB1(op) & 0x80) result |= 0x02; if(MMXUB2(op) & 0x80) result |= 0x04; if(MMXUB3(op) & 0x80) result |= 0x08; if(MMXUB4(op) & 0x80) result |= 0x10; if(MMXUB5(op) & 0x80) result |= 0x20; if(MMXUB6(op) & 0x80) result |= 0x40; if(MMXUB7(op) & 0x80) result |= 0x80; BX_WRITE_32BIT_REGZ(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* 0F D8 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2, result; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(result) = 0; if(MMXUB0(op1) > MMXUB0(op2)) MMXUB0(result) = MMXUB0(op1) - MMXUB0(op2); if(MMXUB1(op1) > MMXUB1(op2)) MMXUB1(result) = MMXUB1(op1) - MMXUB1(op2); if(MMXUB2(op1) > MMXUB2(op2)) MMXUB2(result) = MMXUB2(op1) - MMXUB2(op2); if(MMXUB3(op1) > MMXUB3(op2)) MMXUB3(result) = MMXUB3(op1) - MMXUB3(op2); if(MMXUB4(op1) > MMXUB4(op2)) MMXUB4(result) = MMXUB4(op1) - MMXUB4(op2); if(MMXUB5(op1) > MMXUB5(op2)) MMXUB5(result) = MMXUB5(op1) - MMXUB5(op2); if(MMXUB6(op1) > MMXUB6(op2)) MMXUB6(result) = MMXUB6(op1) - MMXUB6(op2); if(MMXUB7(op1) > MMXUB7(op2)) MMXUB7(result) = MMXUB7(op1) - MMXUB7(op2); BX_WRITE_MMX_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* 0F D9 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBUSW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2, result; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(result) = 0; if(MMXUW0(op1) > MMXUW0(op2)) MMXUW0(result) = MMXUW0(op1) - MMXUW0(op2); if(MMXUW1(op1) > MMXUW1(op2)) MMXUW1(result) = MMXUW1(op1) - MMXUW1(op2); if(MMXUW2(op1) > MMXUW2(op2)) MMXUW2(result) = MMXUW2(op1) - MMXUW2(op2); if(MMXUW3(op1) > MMXUW3(op2)) MMXUW3(result) = MMXUW3(op1) - MMXUW3(op2); BX_WRITE_MMX_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* 0F DA */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMINUB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUB0(op2) < MMXUB0(op1)) MMXUB0(op1) = MMXUB0(op2); if(MMXUB1(op2) < MMXUB1(op1)) MMXUB1(op1) = MMXUB1(op2); if(MMXUB2(op2) < MMXUB2(op1)) MMXUB2(op1) = MMXUB2(op2); if(MMXUB3(op2) < MMXUB3(op1)) MMXUB3(op1) = MMXUB3(op2); if(MMXUB4(op2) < MMXUB4(op1)) MMXUB4(op1) = MMXUB4(op2); if(MMXUB5(op2) < MMXUB5(op1)) MMXUB5(op1) = MMXUB5(op2); if(MMXUB6(op2) < MMXUB6(op1)) MMXUB6(op1) = MMXUB6(op2); if(MMXUB7(op2) < MMXUB7(op1)) MMXUB7(op1) = MMXUB7(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F DB */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PAND_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(op1) &= MMXUQ(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F DC */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) = SaturateWordSToByteU(Bit16s(MMXUB0(op1)) + Bit16s(MMXUB0(op2))); MMXUB1(op1) = SaturateWordSToByteU(Bit16s(MMXUB1(op1)) + Bit16s(MMXUB1(op2))); MMXUB2(op1) = SaturateWordSToByteU(Bit16s(MMXUB2(op1)) + Bit16s(MMXUB2(op2))); MMXUB3(op1) = SaturateWordSToByteU(Bit16s(MMXUB3(op1)) + Bit16s(MMXUB3(op2))); MMXUB4(op1) = SaturateWordSToByteU(Bit16s(MMXUB4(op1)) + Bit16s(MMXUB4(op2))); MMXUB5(op1) = SaturateWordSToByteU(Bit16s(MMXUB5(op1)) + Bit16s(MMXUB5(op2))); MMXUB6(op1) = SaturateWordSToByteU(Bit16s(MMXUB6(op1)) + Bit16s(MMXUB6(op2))); MMXUB7(op1) = SaturateWordSToByteU(Bit16s(MMXUB7(op1)) + Bit16s(MMXUB7(op2))); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F DD */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDUSW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = SaturateDwordSToWordU(Bit32s(MMXUW0(op1)) + Bit32s(MMXUW0(op2))); MMXUW1(op1) = SaturateDwordSToWordU(Bit32s(MMXUW1(op1)) + Bit32s(MMXUW1(op2))); MMXUW2(op1) = SaturateDwordSToWordU(Bit32s(MMXUW2(op1)) + Bit32s(MMXUW2(op2))); MMXUW3(op1) = SaturateDwordSToWordU(Bit32s(MMXUW3(op1)) + Bit32s(MMXUW3(op2))); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F DE */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMAXUB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUB0(op2) > MMXUB0(op1)) MMXUB0(op1) = MMXUB0(op2); if(MMXUB1(op2) > MMXUB1(op1)) MMXUB1(op1) = MMXUB1(op2); if(MMXUB2(op2) > MMXUB2(op1)) MMXUB2(op1) = MMXUB2(op2); if(MMXUB3(op2) > MMXUB3(op1)) MMXUB3(op1) = MMXUB3(op2); if(MMXUB4(op2) > MMXUB4(op1)) MMXUB4(op1) = MMXUB4(op2); if(MMXUB5(op2) > MMXUB5(op1)) MMXUB5(op1) = MMXUB5(op2); if(MMXUB6(op2) > MMXUB6(op1)) MMXUB6(op1) = MMXUB6(op2); if(MMXUB7(op2) > MMXUB7(op1)) MMXUB7(op1) = MMXUB7(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F DF */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PANDN_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(op1) = ~(MMXUQ(op1)) & MMXUQ(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E0 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PAVGB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) = (MMXUB0(op1) + MMXUB0(op2) + 1) >> 1; MMXUB1(op1) = (MMXUB1(op1) + MMXUB1(op2) + 1) >> 1; MMXUB2(op1) = (MMXUB2(op1) + MMXUB2(op2) + 1) >> 1; MMXUB3(op1) = (MMXUB3(op1) + MMXUB3(op2) + 1) >> 1; MMXUB4(op1) = (MMXUB4(op1) + MMXUB4(op2) + 1) >> 1; MMXUB5(op1) = (MMXUB5(op1) + MMXUB5(op2) + 1) >> 1; MMXUB6(op1) = (MMXUB6(op1) + MMXUB6(op2) + 1) >> 1; MMXUB7(op1) = (MMXUB7(op1) + MMXUB7(op2) + 1) >> 1; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E1 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(!MMXUQ(op2)) { BX_NEXT_INSTR(i); } if(MMXUQ(op2) > 15) { MMXUW0(op1) = (MMXUW0(op1) & 0x8000) ? 0xffff : 0; MMXUW1(op1) = (MMXUW1(op1) & 0x8000) ? 0xffff : 0; MMXUW2(op1) = (MMXUW2(op1) & 0x8000) ? 0xffff : 0; MMXUW3(op1) = (MMXUW3(op1) & 0x8000) ? 0xffff : 0; } else { Bit8u shift = MMXUB0(op2); MMXUW0(op1) = (Bit16u)(MMXSW0(op1) >> shift); MMXUW1(op1) = (Bit16u)(MMXSW1(op1) >> shift); MMXUW2(op1) = (Bit16u)(MMXSW2(op1) >> shift); MMXUW3(op1) = (Bit16u)(MMXSW3(op1) >> shift); } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E2 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(!MMXUQ(op2)) { BX_NEXT_INSTR(i); } if(MMXUQ(op2) > 31) { MMXUD0(op1) = (MMXUD0(op1) & 0x80000000) ? 0xffffffff : 0; MMXUD1(op1) = (MMXUD1(op1) & 0x80000000) ? 0xffffffff : 0; } else { Bit8u shift = MMXUB0(op2); MMXUD0(op1) = (Bit32u)(MMXSD0(op1) >> shift); MMXUD1(op1) = (Bit32u)(MMXSD1(op1) >> shift); } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E3 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PAVGW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) = (MMXUW0(op1) + MMXUW0(op2) + 1) >> 1; MMXUW1(op1) = (MMXUW1(op1) + MMXUW1(op2) + 1) >> 1; MMXUW2(op1) = (MMXUW2(op1) + MMXUW2(op2) + 1) >> 1; MMXUW3(op1) = (MMXUW3(op1) + MMXUW3(op2) + 1) >> 1; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E4 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHUW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ Bit32u product1 = Bit32u(MMXUW0(op1)) * Bit32u(MMXUW0(op2)); Bit32u product2 = Bit32u(MMXUW1(op1)) * Bit32u(MMXUW1(op2)); Bit32u product3 = Bit32u(MMXUW2(op1)) * Bit32u(MMXUW2(op2)); Bit32u product4 = Bit32u(MMXUW3(op1)) * Bit32u(MMXUW3(op2)); MMXUW0(op1) = (Bit16u)(product1 >> 16); MMXUW1(op1) = (Bit16u)(product2 >> 16); MMXUW2(op1) = (Bit16u)(product3 >> 16); MMXUW3(op1) = (Bit16u)(product4 >> 16); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E5 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2)); Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2)); Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2)); Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2)); MMXUW0(op1) = Bit16u(product1 >> 16); MMXUW1(op1) = Bit16u(product2 >> 16); MMXUW2(op1) = Bit16u(product3 >> 16); MMXUW3(op1) = Bit16u(product4 >> 16); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E8 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSB0(op1) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) - Bit16s(MMXSB0(op2))); MMXSB1(op1) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) - Bit16s(MMXSB1(op2))); MMXSB2(op1) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) - Bit16s(MMXSB2(op2))); MMXSB3(op1) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) - Bit16s(MMXSB3(op2))); MMXSB4(op1) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) - Bit16s(MMXSB4(op2))); MMXSB5(op1) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) - Bit16s(MMXSB5(op2))); MMXSB6(op1) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) - Bit16s(MMXSB6(op2))); MMXSB7(op1) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) - Bit16s(MMXSB7(op2))); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F E9 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBSW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) - Bit32s(MMXSW0(op2))); MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) - Bit32s(MMXSW1(op2))); MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) - Bit32s(MMXSW2(op2))); MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) - Bit32s(MMXSW3(op2))); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F EA */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMINSW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXSW0(op2) < MMXSW0(op1)) MMXSW0(op1) = MMXSW0(op2); if(MMXSW1(op2) < MMXSW1(op1)) MMXSW1(op1) = MMXSW1(op2); if(MMXSW2(op2) < MMXSW2(op1)) MMXSW2(op1) = MMXSW2(op2); if(MMXSW3(op2) < MMXSW3(op1)) MMXSW3(op1) = MMXSW3(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F EB */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POR_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(op1) |= MMXUQ(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F EC */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSB0(op1) = SaturateWordSToByteS(Bit16s(MMXSB0(op1)) + Bit16s(MMXSB0(op2))); MMXSB1(op1) = SaturateWordSToByteS(Bit16s(MMXSB1(op1)) + Bit16s(MMXSB1(op2))); MMXSB2(op1) = SaturateWordSToByteS(Bit16s(MMXSB2(op1)) + Bit16s(MMXSB2(op2))); MMXSB3(op1) = SaturateWordSToByteS(Bit16s(MMXSB3(op1)) + Bit16s(MMXSB3(op2))); MMXSB4(op1) = SaturateWordSToByteS(Bit16s(MMXSB4(op1)) + Bit16s(MMXSB4(op2))); MMXSB5(op1) = SaturateWordSToByteS(Bit16s(MMXSB5(op1)) + Bit16s(MMXSB5(op2))); MMXSB6(op1) = SaturateWordSToByteS(Bit16s(MMXSB6(op1)) + Bit16s(MMXSB6(op2))); MMXSB7(op1) = SaturateWordSToByteS(Bit16s(MMXSB7(op1)) + Bit16s(MMXSB7(op2))); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F ED */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDSW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXSW0(op1) = SaturateDwordSToWordS(Bit32s(MMXSW0(op1)) + Bit32s(MMXSW0(op2))); MMXSW1(op1) = SaturateDwordSToWordS(Bit32s(MMXSW1(op1)) + Bit32s(MMXSW1(op2))); MMXSW2(op1) = SaturateDwordSToWordS(Bit32s(MMXSW2(op1)) + Bit32s(MMXSW2(op2))); MMXSW3(op1) = SaturateDwordSToWordS(Bit32s(MMXSW3(op1)) + Bit32s(MMXSW3(op2))); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F EE */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMAXSW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXSW0(op2) > MMXSW0(op1)) MMXSW0(op1) = MMXSW0(op2); if(MMXSW1(op2) > MMXSW1(op1)) MMXSW1(op1) = MMXSW1(op2); if(MMXSW2(op2) > MMXSW2(op1)) MMXSW2(op1) = MMXSW2(op2); if(MMXSW3(op2) > MMXSW3(op1)) MMXSW3(op1) = MMXSW3(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F EF */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PXOR_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(op1) ^= MMXUQ(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F1 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUQ(op2) > 15) MMXUQ(op1) = 0; else { Bit8u shift = MMXUB0(op2); MMXUW0(op1) <<= shift; MMXUW1(op1) <<= shift; MMXUW2(op1) <<= shift; MMXUW3(op1) <<= shift; } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F2 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUQ(op2) > 31) MMXUQ(op1) = 0; else { Bit8u shift = MMXUB0(op2); MMXUD0(op1) <<= shift; MMXUD1(op1) <<= shift; } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F3 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUQ(op2) > 63) { MMXUQ(op1) = 0; } else { MMXUQ(op1) <<= MMXUB0(op2); } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F4 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULUDQ_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(op1) = Bit64u(MMXUD0(op1)) * Bit64u(MMXUD0(op2)); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F5 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMADDWD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ if(MMXUD0(op1) == 0x80008000 && MMXUD0(op2) == 0x80008000) { MMXUD0(op1) = 0x80000000; } else { MMXUD0(op1) = Bit32s(MMXSW0(op1))*Bit32s(MMXSW0(op2)) + Bit32s(MMXSW1(op1))*Bit32s(MMXSW1(op2)); } if(MMXUD1(op1) == 0x80008000 && MMXUD1(op2) == 0x80008000) { MMXUD1(op1) = 0x80000000; } else { MMXUD1(op1) = Bit32s(MMXSW2(op1))*Bit32s(MMXSW2(op2)) + Bit32s(MMXSW3(op1))*Bit32s(MMXSW3(op2)); } BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F6 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSADBW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; Bit16u temp = 0; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ temp += abs(MMXUB0(op1) - MMXUB0(op2)); temp += abs(MMXUB1(op1) - MMXUB1(op2)); temp += abs(MMXUB2(op1) - MMXUB2(op2)); temp += abs(MMXUB3(op1) - MMXUB3(op2)); temp += abs(MMXUB4(op1) - MMXUB4(op2)); temp += abs(MMXUB5(op1) - MMXUB5(op2)); temp += abs(MMXUB6(op1) - MMXUB6(op2)); temp += abs(MMXUB7(op1) - MMXUB7(op2)); MMXUQ(op1) = (Bit64u) temp; BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F7 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MASKMOVQ_PqPRq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ bx_address rdi = RDI & i->asize_mask(); BxPackedMmxRegister op = BX_READ_MMX_REG(i->src1()), tmp, mask = BX_READ_MMX_REG(i->src2()); /* do read-modify-write for efficiency */ MMXUQ(tmp) = read_RMW_virtual_qword(i->seg(), rdi); if(!MMXUQ(mask)) { BX_NEXT_INSTR(i); } if(MMXUB0(mask) & 0x80) MMXUB0(tmp) = MMXUB0(op); if(MMXUB1(mask) & 0x80) MMXUB1(tmp) = MMXUB1(op); if(MMXUB2(mask) & 0x80) MMXUB2(tmp) = MMXUB2(op); if(MMXUB3(mask) & 0x80) MMXUB3(tmp) = MMXUB3(op); if(MMXUB4(mask) & 0x80) MMXUB4(tmp) = MMXUB4(op); if(MMXUB5(mask) & 0x80) MMXUB5(tmp) = MMXUB5(op); if(MMXUB6(mask) & 0x80) MMXUB6(tmp) = MMXUB6(op); if(MMXUB7(mask) & 0x80) MMXUB7(tmp) = MMXUB7(op); write_RMW_virtual_qword(MMXUQ(tmp)); #endif BX_NEXT_INSTR(i); } /* 0F F8 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) -= MMXUB0(op2); MMXUB1(op1) -= MMXUB1(op2); MMXUB2(op1) -= MMXUB2(op2); MMXUB3(op1) -= MMXUB3(op2); MMXUB4(op1) -= MMXUB4(op2); MMXUB5(op1) -= MMXUB5(op2); MMXUB6(op1) -= MMXUB6(op2); MMXUB7(op1) -= MMXUB7(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F F9 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) -= MMXUW0(op2); MMXUW1(op1) -= MMXUW1(op2); MMXUW2(op1) -= MMXUW2(op2); MMXUW3(op1) -= MMXUW3(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F FA */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(op1) -= MMXUD0(op2); MMXUD1(op1) -= MMXUD1(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F FB */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSUBQ_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUQ(op1) -= MMXUQ(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F FC */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDB_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUB0(op1) += MMXUB0(op2); MMXUB1(op1) += MMXUB1(op2); MMXUB2(op1) += MMXUB2(op2); MMXUB3(op1) += MMXUB3(op2); MMXUB4(op1) += MMXUB4(op2); MMXUB5(op1) += MMXUB5(op2); MMXUB6(op1) += MMXUB6(op2); MMXUB7(op1) += MMXUB7(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F FD */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUW0(op1) += MMXUW0(op2); MMXUW1(op1) += MMXUW1(op2); MMXUW2(op1) += MMXUW2(op2); MMXUW3(op1) += MMXUW3(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F FE */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PADDD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(op1) += MMXUD0(op2); MMXUD1(op1) += MMXUD1(op2); BX_WRITE_MMX_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* 0F 71 GrpA 010 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLW_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift > 15) MMXUQ(op) = 0; else { MMXUW0(op) >>= shift; MMXUW1(op) >>= shift; MMXUW2(op) >>= shift; MMXUW3(op) >>= shift; } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 71 GrpA 100 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAW_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift == 0) { BX_NEXT_INSTR(i); } if(shift > 15) { MMXUW0(op) = (MMXUW0(op) & 0x8000) ? 0xffff : 0; MMXUW1(op) = (MMXUW1(op) & 0x8000) ? 0xffff : 0; MMXUW2(op) = (MMXUW2(op) & 0x8000) ? 0xffff : 0; MMXUW3(op) = (MMXUW3(op) & 0x8000) ? 0xffff : 0; } else { MMXUW0(op) = (Bit16u)(MMXSW0(op) >> shift); MMXUW1(op) = (Bit16u)(MMXSW1(op) >> shift); MMXUW2(op) = (Bit16u)(MMXSW2(op) >> shift); MMXUW3(op) = (Bit16u)(MMXSW3(op) >> shift); } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 71 GrpA 110 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLW_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift > 15) MMXUQ(op) = 0; else { MMXUW0(op) <<= shift; MMXUW1(op) <<= shift; MMXUW2(op) <<= shift; MMXUW3(op) <<= shift; } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 72 GrpA 010 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLD_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift > 31) MMXUQ(op) = 0; else { MMXUD0(op) >>= shift; MMXUD1(op) >>= shift; } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 72 GrpA 100 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRAD_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift == 0) { BX_NEXT_INSTR(i); } if(shift > 31) { MMXUD0(op) = (MMXUD0(op) & 0x80000000) ? 0xffffffff : 0; MMXUD1(op) = (MMXUD1(op) & 0x80000000) ? 0xffffffff : 0; } else { MMXUD0(op) = (Bit32u)(MMXSD0(op) >> shift); MMXUD1(op) = (Bit32u)(MMXSD1(op) >> shift); } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 72 GrpA 110 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLD_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift > 31) MMXUQ(op) = 0; else { MMXUD0(op) <<= shift; MMXUD1(op) <<= shift; } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 73 GrpA 010 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSRLQ_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift > 63) { MMXUQ(op) = 0; } else { MMXUQ(op) >>= shift; } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 0F 73 GrpA 110 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSLLQ_PqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->dst()); Bit8u shift = i->Ib(); if(shift > 63) { MMXUQ(op) = 0; } else { MMXUQ(op) <<= shift; } BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } bochs-2.6/cpu/iret.cc0000644000175000017500000004361112020641453014400 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: iret.cc 11106 2012-03-25 11:54:32Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2005-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(1) BX_CPU_C::iret_protected(bxInstruction_c *i) { Bit16u raw_cs_selector, raw_ss_selector; bx_selector_t cs_selector, ss_selector; Bit32u dword1, dword2; bx_descriptor_t cs_descriptor, ss_descriptor; #if BX_SUPPORT_X86_64 if (long_mode()) { long_iret(i); return; } #endif if (BX_CPU_THIS_PTR get_NT()) /* NT = 1: RETURN FROM NESTED TASK */ { /* what's the deal with NT & VM ? */ Bit16u raw_link_selector; bx_selector_t link_selector; bx_descriptor_t tss_descriptor; if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("iret_protected: VM sholdn't be set here !")); BX_DEBUG(("IRET: nested task return")); if (BX_CPU_THIS_PTR tr.cache.valid==0) BX_PANIC(("IRET: TR not valid")); // examine back link selector in TSS addressed by current TR raw_link_selector = system_read_word(BX_CPU_THIS_PTR tr.cache.u.segment.base); // must specify global, else #TS(new TSS selector) parse_selector(raw_link_selector, &link_selector); if (link_selector.ti) { BX_ERROR(("iret: link selector.ti=1")); exception(BX_TS_EXCEPTION, raw_link_selector & 0xfffc); } // index must be within GDT limits, else #TS(new TSS selector) fetch_raw_descriptor(&link_selector, &dword1, &dword2, BX_TS_EXCEPTION); // AR byte must specify TSS, else #TS(new TSS selector) // new TSS must be busy, else #TS(new TSS selector) parse_descriptor(dword1, dword2, &tss_descriptor); if (tss_descriptor.valid==0 || tss_descriptor.segment) { BX_ERROR(("iret: TSS selector points to bad TSS")); exception(BX_TS_EXCEPTION, raw_link_selector & 0xfffc); } if (tss_descriptor.type != BX_SYS_SEGMENT_BUSY_286_TSS && tss_descriptor.type != BX_SYS_SEGMENT_BUSY_386_TSS) { BX_ERROR(("iret: TSS selector points to bad TSS")); exception(BX_TS_EXCEPTION, raw_link_selector & 0xfffc); } // TSS must be present, else #NP(new TSS selector) if (! IS_PRESENT(tss_descriptor)) { BX_ERROR(("iret: task descriptor.p == 0")); exception(BX_NP_EXCEPTION, raw_link_selector & 0xfffc); } // switch tasks (without nesting) to TSS specified by back link selector task_switch(i, &link_selector, &tss_descriptor, BX_TASK_FROM_IRET, dword1, dword2); return; } /* NT = 0: INTERRUPT RETURN ON STACK -or STACK_RETURN_TO_V86 */ unsigned top_nbytes_same; Bit32u new_eip = 0, new_esp, temp_ESP, new_eflags = 0; Bit16u new_ip = 0, new_flags = 0; /* 16bit opsize | 32bit opsize * ============================== * SS eSP+8 | SS eSP+16 * SP eSP+6 | ESP eSP+12 * ------------------------------- * FLAGS eSP+4 | EFLAGS eSP+8 * CS eSP+2 | CS eSP+4 * IP eSP+0 | EIP eSP+0 */ if (i->os32L()) { top_nbytes_same = 12; } else { top_nbytes_same = 6; } if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) temp_ESP = ESP; else temp_ESP = SP; if (i->os32L()) { new_eflags = stack_read_dword(temp_ESP + 8); raw_cs_selector = (Bit16u) stack_read_dword(temp_ESP + 4); new_eip = stack_read_dword(temp_ESP + 0); // if VM=1 in flags image on stack then STACK_RETURN_TO_V86 if (new_eflags & EFlagsVMMask) { if (CPL == 0) { stack_return_to_v86(new_eip, raw_cs_selector, new_eflags); return; } else BX_INFO(("iret: VM set on stack, CPL!=0")); } } else { new_flags = stack_read_word(temp_ESP + 4); raw_cs_selector = stack_read_word(temp_ESP + 2); new_ip = stack_read_word(temp_ESP + 0); } parse_selector(raw_cs_selector, &cs_selector); // return CS selector must be non-null, else #GP(0) if ((raw_cs_selector & 0xfffc) == 0) { BX_ERROR(("iret: return CS selector null")); exception(BX_GP_EXCEPTION, 0); } // selector index must be within descriptor table limits, // else #GP(return selector) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // return CS selector RPL must be >= CPL, else #GP(return selector) if (cs_selector.rpl < CPL) { BX_ERROR(("iret: return selector RPL < CPL")); exception(BX_GP_EXCEPTION, raw_cs_selector & 0xfffc); } // check code-segment descriptor check_cs(&cs_descriptor, raw_cs_selector, 0, cs_selector.rpl); if (cs_selector.rpl == CPL) { /* INTERRUPT RETURN TO SAME LEVEL */ /* top 6/12 bytes on stack must be within limits, else #SS(0) */ /* satisfied above */ if (i->os32L()) { /* load CS-cache with new code segment descriptor */ branch_far32(&cs_selector, &cs_descriptor, new_eip, cs_selector.rpl); // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask | EFlagsRFMask; #if BX_CPU_LEVEL >= 4 changeMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC #endif if (CPL <= BX_CPU_THIS_PTR get_IOPL()) changeMask |= EFlagsIFMask; if (CPL == 0) changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask; // IF only changed if (CPL <= EFLAGS.IOPL) // VIF, VIP, IOPL only changed if CPL == 0 // VM unaffected writeEFlags(new_eflags, changeMask); } else { /* load CS-cache with new code segment descriptor */ branch_far32(&cs_selector, &cs_descriptor, (Bit32u) new_ip, cs_selector.rpl); /* load flags with third word on stack */ write_flags(new_flags, CPL==0, CPL<=BX_CPU_THIS_PTR get_IOPL()); } /* increment stack by 6/12 */ if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) ESP += top_nbytes_same; else SP += top_nbytes_same; return; } else { /* INTERRUPT RETURN TO OUTER PRIVILEGE LEVEL */ /* 16bit opsize | 32bit opsize * ============================== * SS eSP+8 | SS eSP+16 * SP eSP+6 | ESP eSP+12 * FLAGS eSP+4 | EFLAGS eSP+8 * CS eSP+2 | CS eSP+4 * IP eSP+0 | EIP eSP+0 */ /* examine return SS selector and associated descriptor */ if (i->os32L()) { raw_ss_selector = stack_read_word(temp_ESP + 16); } else { raw_ss_selector = stack_read_word(temp_ESP + 8); } /* selector must be non-null, else #GP(0) */ if ((raw_ss_selector & 0xfffc) == 0) { BX_ERROR(("iret: SS selector null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(raw_ss_selector, &ss_selector); /* selector RPL must = RPL of return CS selector, * else #GP(SS selector) */ if (ss_selector.rpl != cs_selector.rpl) { BX_ERROR(("iret: SS.rpl != CS.rpl")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* selector index must be within its descriptor table limits, * else #GP(SS selector) */ fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &ss_descriptor); /* AR byte must indicate a writable data segment, * else #GP(SS selector) */ if (ss_descriptor.valid==0 || ss_descriptor.segment==0 || IS_CODE_SEGMENT(ss_descriptor.type) || !IS_DATA_SEGMENT_WRITEABLE(ss_descriptor.type)) { BX_ERROR(("iret: SS AR byte not writable or code segment")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* stack segment DPL must equal the RPL of the return CS selector, * else #GP(SS selector) */ if (ss_descriptor.dpl != cs_selector.rpl) { BX_ERROR(("iret: SS.dpl != CS selector RPL")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* SS must be present, else #NP(SS selector) */ if (! IS_PRESENT(ss_descriptor)) { BX_ERROR(("iret: SS not present!")); exception(BX_NP_EXCEPTION, raw_ss_selector & 0xfffc); } if (i->os32L()) { new_esp = stack_read_dword(temp_ESP + 12); new_eflags = stack_read_dword(temp_ESP + 8); new_eip = stack_read_dword(temp_ESP + 0); } else { new_esp = stack_read_word(temp_ESP + 6); new_eflags = stack_read_word(temp_ESP + 4); new_eip = stack_read_word(temp_ESP + 0); } // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask | EFlagsRFMask; #if BX_CPU_LEVEL >= 4 changeMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC #endif if (CPL <= BX_CPU_THIS_PTR get_IOPL()) changeMask |= EFlagsIFMask; if (CPL == 0) changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask; if (! i->os32L()) // 16 bit changeMask &= 0xffff; /* load CS:EIP from stack */ /* load the CS-cache with CS descriptor */ /* set CPL to the RPL of the return CS selector */ branch_far32(&cs_selector, &cs_descriptor, new_eip, cs_selector.rpl); // IF only changed if (prev_CPL <= EFLAGS.IOPL) // VIF, VIP, IOPL only changed if prev_CPL == 0 // VM unaffected writeEFlags(new_eflags, changeMask); // load SS:eSP from stack // load the SS-cache with SS descriptor load_ss(&ss_selector, &ss_descriptor, cs_selector.rpl); if (ss_descriptor.u.segment.d_b) ESP = new_esp; else SP = new_esp; validate_seg_regs(); } } #if BX_SUPPORT_X86_64 void BX_CPP_AttrRegparmN(1) BX_CPU_C::long_iret(bxInstruction_c *i) { Bit16u raw_cs_selector, raw_ss_selector; bx_selector_t cs_selector, ss_selector; Bit32u dword1, dword2; bx_descriptor_t cs_descriptor, ss_descriptor; Bit32u new_eflags; Bit64u new_rip, new_rsp, temp_RSP; BX_DEBUG (("LONG MODE IRET")); if (BX_CPU_THIS_PTR get_NT()) { BX_ERROR(("iret64: return from nested task in x86-64 mode !")); exception(BX_GP_EXCEPTION, 0); } /* 64bit opsize * ============ * SS eSP+32 * ESP eSP+24 * ------------- * EFLAGS eSP+16 * CS eSP+8 * EIP eSP+0 */ if (long64_mode()) temp_RSP = RSP; else { if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) temp_RSP = ESP; else temp_RSP = SP; } unsigned top_nbytes_same = 0; /* stop compiler warnings */ #if BX_SUPPORT_X86_64 if (i->os64L()) { new_eflags = (Bit32u) stack_read_qword(temp_RSP + 16); raw_cs_selector = (Bit16u) stack_read_qword(temp_RSP + 8); new_rip = stack_read_qword(temp_RSP + 0); top_nbytes_same = 24; } else #endif if (i->os32L()) { new_eflags = stack_read_dword(temp_RSP + 8); raw_cs_selector = (Bit16u) stack_read_dword(temp_RSP + 4); new_rip = (Bit64u) stack_read_dword(temp_RSP + 0); top_nbytes_same = 12; } else { new_eflags = stack_read_word(temp_RSP + 4); raw_cs_selector = stack_read_word(temp_RSP + 2); new_rip = (Bit64u) stack_read_word(temp_RSP + 0); top_nbytes_same = 6; } // ignore VM flag in long mode new_eflags &= ~EFlagsVMMask; parse_selector(raw_cs_selector, &cs_selector); // return CS selector must be non-null, else #GP(0) if ((raw_cs_selector & 0xfffc) == 0) { BX_ERROR(("iret64: return CS selector null")); exception(BX_GP_EXCEPTION, 0); } // selector index must be within descriptor table limits, // else #GP(return selector) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // return CS selector RPL must be >= CPL, else #GP(return selector) if (cs_selector.rpl < CPL) { BX_ERROR(("iret64: return selector RPL < CPL")); exception(BX_GP_EXCEPTION, raw_cs_selector & 0xfffc); } // check code-segment descriptor check_cs(&cs_descriptor, raw_cs_selector, 0, cs_selector.rpl); /* INTERRUPT RETURN TO SAME PRIVILEGE LEVEL */ if (cs_selector.rpl == CPL && !i->os64L()) { /* top 24 bytes on stack must be within limits, else #SS(0) */ /* satisfied above */ /* load CS:EIP from stack */ /* load CS-cache with new code segment descriptor */ if(cs_descriptor.u.segment.l) { branch_far64(&cs_selector, &cs_descriptor, new_rip, CPL); } else { branch_far32(&cs_selector, &cs_descriptor, (Bit32u) new_rip, CPL); } // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask | EFlagsRFMask | EFlagsIDMask | EFlagsACMask; if (CPL <= BX_CPU_THIS_PTR get_IOPL()) changeMask |= EFlagsIFMask; if (CPL == 0) changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask; if (! i->os32L()) // 16 bit changeMask &= 0xffff; // IF only changed if (CPL <= EFLAGS.IOPL) // VIF, VIP, IOPL only changed if CPL == 0 // VM unaffected writeEFlags(new_eflags, changeMask); /* we are NOT in 64-bit mode */ if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) ESP += top_nbytes_same; else SP += top_nbytes_same; } else { /* INTERRUPT RETURN TO OUTER PRIVILEGE LEVEL or 64 BIT MODE */ /* 64bit opsize * ============ * SS eSP+32 * ESP eSP+24 * EFLAGS eSP+16 * CS eSP+8 * EIP eSP+0 */ /* examine return SS selector and associated descriptor */ #if BX_SUPPORT_X86_64 if (i->os64L()) { raw_ss_selector = (Bit16u) stack_read_qword(temp_RSP + 32); new_rsp = stack_read_qword(temp_RSP + 24); } else #endif { if (i->os32L()) { raw_ss_selector = (Bit16u) stack_read_dword(temp_RSP + 16); new_rsp = (Bit64u) stack_read_dword(temp_RSP + 12); } else { raw_ss_selector = stack_read_word(temp_RSP + 8); new_rsp = (Bit64u) stack_read_word(temp_RSP + 6); } } if ((raw_ss_selector & 0xfffc) == 0) { if (! IS_LONG64_SEGMENT(cs_descriptor) || cs_selector.rpl == 3) { BX_ERROR(("iret64: SS selector null")); exception(BX_GP_EXCEPTION, 0); } } else { parse_selector(raw_ss_selector, &ss_selector); /* selector RPL must = RPL of return CS selector, * else #GP(SS selector) */ if (ss_selector.rpl != cs_selector.rpl) { BX_ERROR(("iret64: SS.rpl != CS.rpl")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* selector index must be within its descriptor table limits, * else #GP(SS selector) */ fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &ss_descriptor); /* AR byte must indicate a writable data segment, * else #GP(SS selector) */ if (ss_descriptor.valid==0 || ss_descriptor.segment==0 || IS_CODE_SEGMENT(ss_descriptor.type) || !IS_DATA_SEGMENT_WRITEABLE(ss_descriptor.type)) { BX_ERROR(("iret64: SS AR byte not writable or code segment")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* stack segment DPL must equal the RPL of the return CS selector, * else #GP(SS selector) */ if (ss_descriptor.dpl != cs_selector.rpl) { BX_ERROR(("iret64: SS.dpl != CS selector RPL")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* SS must be present, else #NP(SS selector) */ if (! IS_PRESENT(ss_descriptor)) { BX_ERROR(("iret64: SS not present!")); exception(BX_NP_EXCEPTION, raw_ss_selector & 0xfffc); } } Bit8u prev_cpl = CPL; /* previous CPL */ // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask | EFlagsRFMask | EFlagsIDMask | EFlagsACMask; if (prev_cpl <= BX_CPU_THIS_PTR get_IOPL()) changeMask |= EFlagsIFMask; if (prev_cpl == 0) changeMask |= EFlagsVIPMask | EFlagsVIFMask | EFlagsIOPLMask; if (! i->os32L()) // 16 bit changeMask &= 0xffff; /* set CPL to the RPL of the return CS selector */ branch_far64(&cs_selector, &cs_descriptor, new_rip, cs_selector.rpl); // IF only changed if (prev_CPL <= EFLAGS.IOPL) // VIF, VIP, IOPL only changed if prev_CPL == 0 // VM unaffected writeEFlags(new_eflags, changeMask); if ((raw_ss_selector & 0xfffc) != 0) { // load SS:RSP from stack // load the SS-cache with SS descriptor load_ss(&ss_selector, &ss_descriptor, cs_selector.rpl); } else { // we are in 64-bit mode ! load_null_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], raw_ss_selector); } if (long64_mode()) RSP = new_rsp; else { if (ss_descriptor.u.segment.d_b) ESP = (Bit32u) new_rsp; else SP = (Bit16u) new_rsp; } if (prev_cpl != CPL) validate_seg_regs(); } } #endif bochs-2.6/cpu/sse_move.cc0000644000175000017500000006706012020641453015261 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: sse_move.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2003-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 6 #include "simd_int.h" void BX_CPU_C::print_state_SSE(void) { BX_DEBUG(("MXCSR: 0x%08x\n", BX_MXCSR_REGISTER)); for(unsigned n=0;n= 0; index--, twd <<= 2, tag_byte <<= 1) { if(tag_byte & 0x80) { const floatx80 &fpu_reg = BX_FPU_REG(index); twd |= FPU_tagof(fpu_reg); } else { twd |= FPU_Tag_Empty; } } return (twd >> 2); } #endif /* ************************************ */ /* SSE: SAVE/RESTORE FPU/MMX/SSEx STATE */ /* ************************************ */ /* 0F AE Grp15 010 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LDMXCSR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u new_mxcsr = read_virtual_dword(i->seg(), eaddr); if(new_mxcsr & ~MXCSR_MASK) exception(BX_GP_EXCEPTION, 0); BX_MXCSR_REGISTER = new_mxcsr; #endif BX_NEXT_INSTR(i); } /* 0F AE Grp15 011 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STMXCSR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 Bit32u mxcsr = BX_MXCSR_REGISTER & MXCSR_MASK; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword(i->seg(), eaddr, mxcsr); #endif BX_NEXT_INSTR(i); } /* 0F AE Grp15 000 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FXSAVE(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 unsigned index; BxPackedXmmRegister xmm; BX_DEBUG(("FXSAVE: save FPU/MMX/SSE state")); if (BX_CPU_THIS_PTR cr0.get_EM() || BX_CPU_THIS_PTR cr0.get_TS()) exception(BX_NM_EXCEPTION, 0); xmm.xmm16u(0) = BX_CPU_THIS_PTR the_i387.get_control_word(); xmm.xmm16u(1) = BX_CPU_THIS_PTR the_i387.get_status_word(); xmm.xmm16u(2) = pack_FPU_TW(BX_CPU_THIS_PTR the_i387.get_tag_word()); /* x87 FPU Opcode (16 bits) */ /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ xmm.xmm16u(3) = BX_CPU_THIS_PTR the_i387.foo; /* * x87 FPU IP Offset (32/64 bits) * The contents of this field differ depending on the current * addressing mode (16/32/64 bit) when the FXSAVE instruction was executed: * + 64-bit mode - 64-bit IP offset * + 32-bit mode - 32-bit IP offset * + 16-bit mode - low 16 bits are IP offset; high 16 bits are reserved. * x87 CS FPU IP Selector * + 16 bit, in 16/32 bit mode only */ #if BX_SUPPORT_X86_64 if (i->os64L()) /* 64 bit operand size mode */ { xmm.xmm64u(1) = (BX_CPU_THIS_PTR the_i387.fip); } else #endif { xmm.xmm32u(2) = (Bit32u)(BX_CPU_THIS_PTR the_i387.fip); xmm.xmm32u(3) = (BX_CPU_THIS_PTR the_i387.fcs); } bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dqword_aligned(i->seg(), eaddr, (Bit8u *) &xmm); bx_address asize_mask = i->asize_mask(); /* * x87 FPU Instruction Operand (Data) Pointer Offset (32/64 bits) * The contents of this field differ depending on the current * addressing mode (16/32 bit) when the FXSAVE instruction was executed: * + 64-bit mode - 64-bit offset * + 32-bit mode - 32-bit offset * + 16-bit mode - low 16 bits are offset; high 16 bits are reserved. * x87 DS FPU Instruction Operand (Data) Pointer Selector * + 16 bit, in 16/32 bit mode only */ #if BX_SUPPORT_X86_64 if (i->os64L()) /* 64 bit operand size mode */ { xmm.xmm64u(0) = (BX_CPU_THIS_PTR the_i387.fdp); } else #endif { xmm.xmm32u(0) = (Bit32u)(BX_CPU_THIS_PTR the_i387.fdp); xmm.xmm32u(1) = (BX_CPU_THIS_PTR the_i387.fds); } if (bx_cpuid_support_sse()) { xmm.xmm32u(2) = BX_MXCSR_REGISTER; xmm.xmm32u(3) = MXCSR_MASK; } else { xmm.xmm32u(2) = 0; xmm.xmm32u(3) = 0; } write_virtual_dqword(i->seg(), (eaddr + 16) & asize_mask, (Bit8u *) &xmm); /* store i387 register file */ for(index=0; index < 8; index++) { const floatx80 &fp = BX_READ_FPU_REG(index); xmm.xmm64u(0) = fp.fraction; xmm.xmm64u(1) = 0; xmm.xmm16u(4) = fp.exp; write_virtual_dqword(i->seg(), (eaddr+index*16+32) & asize_mask, (Bit8u *) &xmm); } #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR efer.get_FFXSR() && CPL == 0 && long64_mode()) { BX_NEXT_INSTR(i); // skip saving of the XMM state } #endif if(BX_CPU_THIS_PTR cr4.get_OSFXSR() && bx_cpuid_support_sse()) { /* store XMM register file */ for(index=0; index < BX_XMM_REGISTERS; index++) { // save XMM8-XMM15 only in 64-bit mode if (index < 8 || long64_mode()) { write_virtual_dqword(i->seg(), (eaddr+index*16+160) & asize_mask, (Bit8u *)(&BX_READ_XMM_REG(index))); } } } /* do not touch reserved fields */ #endif BX_NEXT_INSTR(i); } /* 0F AE Grp15 001 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FXRSTOR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister xmm; unsigned index; BX_DEBUG(("FXRSTOR: restore FPU/MMX/SSE state")); if (BX_CPU_THIS_PTR cr0.get_EM() || BX_CPU_THIS_PTR cr0.get_TS()) exception(BX_NM_EXCEPTION, 0); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword_aligned(i->seg(), eaddr, (Bit8u *) &xmm); bx_address asize_mask = i->asize_mask(); BX_CPU_THIS_PTR the_i387.cwd = xmm.xmm16u(0); BX_CPU_THIS_PTR the_i387.swd = xmm.xmm16u(1); BX_CPU_THIS_PTR the_i387.tos = (xmm.xmm16u(1) >> 11) & 0x07; /* always set bit 6 as '1 */ BX_CPU_THIS_PTR the_i387.cwd = (BX_CPU_THIS_PTR the_i387.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; /* Restore x87 FPU Opcode */ /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ BX_CPU_THIS_PTR the_i387.foo = xmm.xmm16u(3) & 0x7FF; /* Restore x87 FPU IP */ #if BX_SUPPORT_X86_64 if (i->os64L()) { BX_CPU_THIS_PTR the_i387.fip = xmm.xmm64u(1); BX_CPU_THIS_PTR the_i387.fcs = 0; } else #endif { BX_CPU_THIS_PTR the_i387.fip = xmm.xmm32u(2); BX_CPU_THIS_PTR the_i387.fcs = xmm.xmm16u(6); } Bit32u tag_byte = xmm.xmmubyte(4); /* Restore x87 FPU DP */ read_virtual_dqword(i->seg(), (eaddr + 16) & asize_mask, (Bit8u *) &xmm); #if BX_SUPPORT_X86_64 if (i->os64L()) { BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm64u(0); BX_CPU_THIS_PTR the_i387.fds = 0; } else #endif { BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm32u(0); BX_CPU_THIS_PTR the_i387.fds = xmm.xmm16u(2); } if(/* BX_CPU_THIS_PTR cr4.get_OSFXSR() && */ bx_cpuid_support_sse()) { Bit32u new_mxcsr = xmm.xmm32u(2); if(new_mxcsr & ~MXCSR_MASK) exception(BX_GP_EXCEPTION, 0); BX_MXCSR_REGISTER = new_mxcsr; } /* load i387 register file */ for(index=0; index < 8; index++) { floatx80 reg; reg.fraction = read_virtual_qword(i->seg(), (eaddr+index*16+32) & asize_mask); reg.exp = read_virtual_word (i->seg(), (eaddr+index*16+40) & asize_mask); // update tag only if it is not empty BX_WRITE_FPU_REGISTER_AND_TAG(reg, IS_TAG_EMPTY(index) ? FPU_Tag_Empty : FPU_tagof(reg), index); } BX_CPU_THIS_PTR the_i387.twd = unpack_FPU_TW(tag_byte); /* check for unmasked exceptions */ if (FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask) { /* set the B and ES bits in the status-word */ FPU_PARTIAL_STATUS |= FPU_SW_Summary | FPU_SW_Backward; } else { /* clear the B and ES bits in the status-word */ FPU_PARTIAL_STATUS &= ~(FPU_SW_Summary | FPU_SW_Backward); } #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR efer.get_FFXSR() && CPL == 0 && long64_mode()) { BX_NEXT_INSTR(i); // skip restore of the XMM state } #endif /* If the OSFXSR bit in CR4 is not set, the FXRSTOR instruction does not restore the states of the XMM and MXCSR registers. */ if(BX_CPU_THIS_PTR cr4.get_OSFXSR() && bx_cpuid_support_sse()) { /* load XMM register file */ for(index=0; index < BX_XMM_REGISTERS; index++) { // restore XMM8-XMM15 only in 64-bit mode if (index < 8 || long64_mode()) { read_virtual_dqword(i->seg(), (eaddr+index*16+160) & asize_mask, (Bit8u *)(&BX_READ_XMM_REG(index))); } } } #endif BX_NEXT_INSTR(i); } /* *************************** */ /* SSE: MEMORY MOVE OPERATIONS */ /* *************************** */ /* All these opcodes never generate SIMD floating point exeptions */ /* MOVUPS: 0F 10 */ /* MOVUPD: 66 0F 10 */ /* MOVDQU: F3 0F 6F */ /* LDDQU: F2 0F F0 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVUPS_VpsWpsM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword(i->seg(), eaddr, &BX_XMM_REG(i->dst())); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVUPS_WpsVpsM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dqword(i->seg(), eaddr, &BX_XMM_REG(i->src())); #endif BX_NEXT_INSTR(i); } /* MOVAPS: 0F 28 */ /* MOVAPD: 66 0F 28 */ /* MOVDQA: F3 0F 6F */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVAPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BX_WRITE_XMM_REG(i->dst(), BX_READ_XMM_REG(i->src())); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVAPS_VpsWpsM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword_aligned(i->seg(), eaddr, &BX_XMM_REG(i->dst())); #endif BX_NEXT_INSTR(i); } /* MOVAPS: 0F 29 */ /* MOVNTPS: 0F 2B */ /* MOVNTPD: 66 0F 2B */ /* MOVNTDQ: 66 0F E7 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVAPS_WpsVpsM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dqword_aligned(i->seg(), eaddr, &BX_XMM_REG(i->src())); #endif BX_NEXT_INSTR(i); } /* F3 0F 10 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 /* If the source operand is an XMM register, the high-order 96 bits of the destination XMM register are not modified. */ BX_WRITE_XMM_REG_LO_DWORD(i->dst(), BX_READ_XMM_REG_LO_DWORD(i->src())); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSS_VssWssM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* If the source operand is a memory location, the high-order 96 bits of the destination XMM register are cleared to 0s */ op.xmm64u(0) = (Bit64u) read_virtual_dword(i->seg(), eaddr); op.xmm64u(1) = 0; BX_WRITE_XMM_REGZ(i->dst(), op, i->getVL()); #endif BX_NEXT_INSTR(i); } /* F3 0F 11 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSS_WssVssM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword(i->seg(), eaddr, BX_READ_XMM_REG_LO_DWORD(i->src())); #endif BX_NEXT_INSTR(i); } /* MOVLPS: 0F 13 */ /* MOVLPD: 66 0F 13 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD_WsdVsdM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword(i->seg(), eaddr, BX_XMM_REG_LO_QWORD(i->src())); #endif BX_NEXT_INSTR(i); } /* F2 0F 10 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 /* If the source operand is an XMM register, the high-order 64 bits of the destination XMM register are not modified. */ BX_WRITE_XMM_REG_LO_QWORD(i->dst(), BX_READ_XMM_REG_LO_QWORD(i->src())); #endif BX_NEXT_INSTR(i); } /* MOVHLPS: 0F 12 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVHLPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BX_WRITE_XMM_REG_LO_QWORD(i->dst(), BX_READ_XMM_REG_HI_QWORD(i->src())); #endif BX_NEXT_INSTR(i); } /* MOVLPS: 0F 12 */ /* MOVLPD: 66 0F 12 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVLPS_VpsMq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit64u val64 = read_virtual_qword(i->seg(), eaddr); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), val64); #endif BX_NEXT_INSTR(i); } /* F2 0F 12 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVDDUP_VpdWqR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 sse_pbroadcastq(&BX_XMM_REG(i->dst()), BX_READ_XMM_REG_LO_QWORD(i->src())); #endif BX_NEXT_INSTR(i); } /* F3 0F 12 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSLDUP_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32u(1) = op.xmm32u(0); op.xmm32u(3) = op.xmm32u(2); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* F3 0F 16 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSHDUP_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32u(0) = op.xmm32u(1); op.xmm32u(2) = op.xmm32u(3); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* MOVLHPS: 0F 16 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVLHPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BX_WRITE_XMM_REG_HI_QWORD(i->dst(), BX_READ_XMM_REG_LO_QWORD(i->src())); #endif BX_NEXT_INSTR(i); } /* MOVHPS: 0F 16 */ /* MOVHPD: 66 0F 16 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVHPS_VpsMq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit64u val64 = read_virtual_qword(i->seg(), eaddr); BX_WRITE_XMM_REG_HI_QWORD(i->dst(), val64); #endif BX_NEXT_INSTR(i); } /* MOVHPS: 0F 17 */ /* MOVHPD: 66 0F 17 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVHPS_MqVps(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword(i->seg(), eaddr, BX_XMM_REG_HI_QWORD(i->src())); #endif BX_NEXT_INSTR(i); } /* 66 0F F7 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MASKMOVDQU_VdqUdq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address rdi = RDI & i->asize_mask(); BxPackedXmmRegister op = BX_READ_XMM_REG(i->src1()), mask = BX_READ_XMM_REG(i->src2()), temp; // check for write permissions before writing even if mask is all 0s temp.xmm64u(0) = read_RMW_virtual_qword(i->seg(), rdi); temp.xmm64u(1) = read_RMW_virtual_qword(i->seg(), (rdi + 8) & i->asize_mask()); /* no data will be written to memory if mask is all 0s */ if ((mask.xmm64u(0) | mask.xmm64u(1)) == 0) { BX_NEXT_INSTR(i); } for(unsigned j=0; j<16; j++) { if(mask.xmmubyte(j) & 0x80) temp.xmmubyte(j) = op.xmmubyte(j); } // and write result back to the memory write_RMW_virtual_qword(temp.xmm64u(1)); // write permissions already checked by read_RMW_virtual_qword_64 write_virtual_qword(i->seg(), rdi, temp.xmm64u(0)); #endif BX_NEXT_INSTR(i); } /* 0F 50 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVMSKPS_GdVRps(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 Bit32u mask = sse_pmovmskd(&BX_XMM_REG(i->src())); BX_WRITE_32BIT_REGZ(i->dst(), mask); #endif BX_NEXT_INSTR(i); } /* 66 0F 50 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVMSKPD_GdVRpd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 Bit32u mask = sse_pmovmskq(&BX_XMM_REG(i->src())); BX_WRITE_32BIT_REGZ(i->dst(), mask); #endif BX_NEXT_INSTR(i); } /* 66 0F 6E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_VdqEdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op; op.xmm64u(0) = (Bit64u) BX_READ_32BIT_REG(i->src()); op.xmm64u(1) = 0; BX_WRITE_XMM_REGZ(i->dst(), op, i->getVL()); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 /* 66 0F 6E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_VdqEqR(bxInstruction_c *i) { BxPackedXmmRegister op; op.xmm64u(0) = BX_READ_64BIT_REG(i->src()); op.xmm64u(1) = 0; BX_WRITE_XMM_REGZ(i->dst(), op, i->getVL()); BX_NEXT_INSTR(i); } #endif /* 66 0F 7E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVD_EdVdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_XMM_REG_LO_DWORD(i->src())); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 /* 66 0F 7E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_EqVqR(bxInstruction_c *i) { BX_WRITE_64BIT_REG(i->dst(), BX_READ_XMM_REG_LO_QWORD(i->src())); BX_NEXT_INSTR(i); } #endif /* F3 0F 7E */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_VqWqR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op; op.xmm64u(0) = BX_READ_XMM_REG_LO_QWORD(i->src()); op.xmm64u(1) = 0; /* zero-extension to 128 bit */ BX_WRITE_XMM_REGZ(i->dst(), op, i->getVL()); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ_VqWqM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op.xmm64u(0) = read_virtual_qword(i->seg(), eaddr); op.xmm64u(1) = 0; /* zero-extension to 128 bit */ BX_WRITE_XMM_REGZ(i->dst(), op, i->getVL()); #endif BX_NEXT_INSTR(i); } /* F2 0F D6 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVDQ2Q_PqVRq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BX_CPU_THIS_PTR FPU_check_pending_exceptions(); /* check floating point status word for a pending FPU exceptions */ BX_CPU_THIS_PTR prepareFPU2MMX(); BxPackedMmxRegister mm; MMXUQ(mm) = BX_READ_XMM_REG_LO_QWORD(i->src()); BX_WRITE_MMX_REG(i->dst(), mm); #endif BX_NEXT_INSTR(i); } /* F3 0F D6 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVQ2DQ_VdqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BX_CPU_THIS_PTR FPU_check_pending_exceptions(); /* check floating point status word for a pending FPU exceptions */ BX_CPU_THIS_PTR prepareFPU2MMX(); BxPackedXmmRegister op; op.xmm64u(0) = BX_MMX_REG(i->src()); op.xmm64u(1) = 0; BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* 66 0F D7 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVMSKB_GdUdq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 Bit32u mask = sse_pmovmskb(&BX_XMM_REG(i->src())); BX_WRITE_32BIT_REGZ(i->dst(), mask); #endif BX_NEXT_INSTR(i); } /* ************************** */ /* 3-BYTE-OPCODE INSTRUCTIONS */ /* ************************** */ #if BX_CPU_LEVEL >= 6 /* 66 0F 38 20 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVSXBW_VdqWqR(bxInstruction_c *i) { BxPackedXmmRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.xmm16u(0) = MMXSB0(op); result.xmm16u(1) = MMXSB1(op); result.xmm16u(2) = MMXSB2(op); result.xmm16u(3) = MMXSB3(op); result.xmm16u(4) = MMXSB4(op); result.xmm16u(5) = MMXSB5(op); result.xmm16u(6) = MMXSB6(op); result.xmm16u(7) = MMXSB7(op); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 21 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVSXBD_VdqWdR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit32u val32 = BX_READ_XMM_REG_LO_DWORD(i->src()); result.xmm32u(0) = (Bit8s) (val32 & 0xFF); result.xmm32u(1) = (Bit8s) ((val32 >> 8) & 0xFF); result.xmm32u(2) = (Bit8s) ((val32 >> 16) & 0xFF); result.xmm32u(3) = (Bit8s) (val32 >> 24); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 22 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVSXBQ_VdqWwR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit16u val16 = BX_READ_XMM_REG_LO_WORD(i->src()); result.xmm64u(0) = (Bit8s) (val16 & 0xFF); result.xmm64u(1) = (Bit8s) (val16 >> 8); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 23 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVSXWD_VdqWqR(bxInstruction_c *i) { BxPackedXmmRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.xmm32u(0) = (Bit16s) MMXSW0(op); result.xmm32u(1) = (Bit16s) MMXSW1(op); result.xmm32u(2) = (Bit16s) MMXSW2(op); result.xmm32u(3) = (Bit16s) MMXSW3(op); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 24 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVSXWQ_VdqWdR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit32u val32 = BX_READ_XMM_REG_LO_DWORD(i->src()); result.xmm64u(0) = (Bit16s) (val32 & 0xFFFF); result.xmm64u(1) = (Bit16s) (val32 >> 16); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 25 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVSXDQ_VdqWqR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit64u val64 = BX_READ_XMM_REG_LO_QWORD(i->src()); result.xmm64u(0) = (Bit32s) (val64 & 0xFFFFFFFF); result.xmm64u(1) = (Bit32s) (val64 >> 32); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 30 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVZXBW_VdqWqR(bxInstruction_c *i) { BxPackedXmmRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.xmm16u(0) = MMXUB0(op); result.xmm16u(1) = MMXUB1(op); result.xmm16u(2) = MMXUB2(op); result.xmm16u(3) = MMXUB3(op); result.xmm16u(4) = MMXUB4(op); result.xmm16u(5) = MMXUB5(op); result.xmm16u(6) = MMXUB6(op); result.xmm16u(7) = MMXUB7(op); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 31 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVZXBD_VdqWdR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit32u val32 = BX_READ_XMM_REG_LO_DWORD(i->src()); result.xmm32u(0) = val32 & 0xFF; result.xmm32u(1) = (val32 >> 8) & 0xFF; result.xmm32u(2) = (val32 >> 16) & 0xFF; result.xmm32u(3) = val32 >> 24; BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 32 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVZXBQ_VdqWwR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit16u val16 = BX_READ_XMM_REG_LO_WORD(i->src()); result.xmm64u(0) = val16 & 0xFF; result.xmm64u(1) = val16 >> 8; BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 33 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVZXWD_VdqWqR(bxInstruction_c *i) { BxPackedXmmRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.xmm32u(0) = MMXUW0(op); result.xmm32u(1) = MMXUW1(op); result.xmm32u(2) = MMXUW2(op); result.xmm32u(3) = MMXUW3(op); BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 34 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVZXWQ_VdqWdR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit32u val32 = BX_READ_XMM_REG_LO_DWORD(i->src()); result.xmm64u(0) = val32 & 0xFFFF; result.xmm64u(1) = val32 >> 16; BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 35 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMOVZXDQ_VdqWqR(bxInstruction_c *i) { BxPackedXmmRegister result; Bit64u val64 = BX_READ_XMM_REG_LO_QWORD(i->src()); result.xmm64u(0) = val64 & 0xFFFFFFFF; result.xmm64u(1) = val64 >> 32; BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 3A 0F */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PALIGNR_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); sse_palignr(&op2, &op1, i->Ib()); BX_WRITE_XMM_REG(i->dst(), op2); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/arith16.cc0000644000175000017500000003412712020641453014715 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: arith16.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_RX(bxInstruction_c *i) { Bit32u rx = ++BX_READ_16BIT_REG(i->dst()); SET_FLAGS_OSZAP_ADD_16(rx - 1, 0, rx); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_RX(bxInstruction_c *i) { Bit32u rx = --BX_READ_16BIT_REG(i->dst()); SET_FLAGS_OSZAP_SUB_16(rx + 1, 0, rx); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwGwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u sum_16 = op1_16 + op2_16; write_RMW_virtual_word(sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GwEwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u sum_16 = op1_16 + op2_16; BX_WRITE_16BIT_REG(i->dst(), sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GwEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = read_virtual_word(i->seg(), eaddr); Bit32u sum_16 = op1_16 + op2_16; BX_WRITE_16BIT_REG(i->dst(), sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwGwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u sum_16 = op1_16 + op2_16 + getB_CF(); write_RMW_virtual_word(sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GwEwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u sum_16 = op1_16 + op2_16 + getB_CF(); BX_WRITE_16BIT_REG(i->dst(), sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GwEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = read_virtual_word(i->seg(), eaddr); Bit32u sum_16 = op1_16 + op2_16 + getB_CF(); BX_WRITE_16BIT_REG(i->dst(), sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwGwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u diff_16 = op1_16 - (op2_16 + getB_CF()); write_RMW_virtual_word(diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GwEwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u diff_16 = op1_16 - (op2_16 + getB_CF()); BX_WRITE_16BIT_REG(i->dst(), diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GwEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = read_virtual_word(i->seg(), eaddr); Bit32u diff_16 = op1_16 - (op2_16 + getB_CF()); BX_WRITE_16BIT_REG(i->dst(), diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwIwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = i->Iw(); Bit32u diff_16 = op1_16 - (op2_16 + getB_CF()); write_RMW_virtual_word(diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EwIwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = i->Iw(); Bit32u diff_16 = op1_16 - (op2_16 + getB_CF()); BX_WRITE_16BIT_REG(i->dst(), diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwGwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u diff_16 = op1_16 - op2_16; write_RMW_virtual_word(diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GwEwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u diff_16 = op1_16 - op2_16; BX_WRITE_16BIT_REG(i->dst(), diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GwEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = read_virtual_word(i->seg(), eaddr); Bit32u diff_16 = op1_16 - op2_16; BX_WRITE_16BIT_REG(i->dst(), diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwGwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_virtual_word(i->seg(), eaddr); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GwEwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GwEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = read_virtual_word(i->seg(), eaddr); Bit32u diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CBW(bxInstruction_c *i) { /* CBW: no flags are effected */ AX = (Bit8s) AL; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CWD(bxInstruction_c *i) { /* CWD: no flags are affected */ if (AX & 0x8000) { DX = 0xFFFF; } else { DX = 0x0000; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EwGwM(bxInstruction_c *i) { /* XADD dst(r/m), src(r) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u sum_16 = op1_16 + op2_16; write_RMW_virtual_word(sum_16); /* and write destination into source */ BX_WRITE_16BIT_REG(i->src(), op1_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EwGwR(bxInstruction_c *i) { /* XADD dst(r/m), src(r) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u sum_16 = op1_16 + op2_16; // and write destination into source // Note: if both op1 & op2 are registers, the last one written // should be the sum, as op1 & op2 may be the same register. // For example: XADD AL, AL BX_WRITE_16BIT_REG(i->src(), op1_16); BX_WRITE_16BIT_REG(i->dst(), sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwIwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = i->Iw(); Bit32u sum_16 = op1_16 + op2_16; write_RMW_virtual_word(sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EwIwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = i->Iw(); Bit32u sum_16 = op1_16 + op2_16; BX_WRITE_16BIT_REG(i->dst(), sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwIwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = i->Iw(); Bit32u sum_16 = op1_16 + op2_16 + getB_CF(); write_RMW_virtual_word(sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EwIwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = i->Iw(); Bit32u sum_16 = op1_16 + op2_16 + getB_CF(); BX_WRITE_16BIT_REG(i->dst(), sum_16); SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwIwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit32u op2_16 = i->Iw(); Bit32u diff_16 = op1_16 - op2_16; write_RMW_virtual_word(diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EwIwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = i->Iw(); Bit32u diff_16 = op1_16 - op2_16; BX_WRITE_16BIT_REG(i->dst(), diff_16); SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwIwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_virtual_word(i->seg(), eaddr); Bit32u op2_16 = i->Iw(); Bit32u diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EwIwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u op2_16 = i->Iw(); Bit32u diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op1_16 = 0 - (Bit32s)(Bit16s)(op1_16); write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAPC_SUB_16(0, 0 - op1_16, op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EwR(bxInstruction_c *i) { Bit32u op1_16 = BX_READ_16BIT_REG(i->dst()); op1_16 = 0 - (Bit32s)(Bit16s)(op1_16); BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_SUB_16(0, 0 - op1_16, op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op1_16++; write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAP_ADD_16(op1_16 - 1, 0, op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op1_16--; write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAP_SUB_16(op1_16 + 1, 0, op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EwGwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); Bit16u diff_16 = AX - op1_16; SET_FLAGS_OSZAPC_SUB_16(AX, op1_16, diff_16); if (diff_16 == 0) { // if accumulator == dest // dest <-- src write_RMW_virtual_word(BX_READ_16BIT_REG(i->src())); } else { // accumulator <-- dest AX = op1_16; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EwGwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit16u diff_16 = AX - op1_16; SET_FLAGS_OSZAPC_SUB_16(AX, op1_16, diff_16); if (diff_16 == 0) { // if accumulator == dest // dest <-- src BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); } else { // accumulator <-- dest AX = op1_16; } BX_NEXT_INSTR(i); } bochs-2.6/cpu/shift64.cc0000644000175000017500000003253412020641453014726 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: shift64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, result_64; unsigned count; unsigned cf, of; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHLD_EqGq) count = CL; else // BX_IA_SHLD_EqGqIb count = i->Ib(); count &= 0x3f; // use only 6 LSB's if (count) { op2_64 = BX_READ_64BIT_REG(i->src()); result_64 = (op1_64 << count) | (op2_64 >> (64 - count)); write_RMW_virtual_qword(result_64); SET_FLAGS_OSZAPC_LOGIC_64(result_64); cf = (op1_64 >> (64 - count)) & 0x1; of = cf ^ (result_64 >> 63); // of = cf ^ result63 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, result_64; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_SHLD_EqGq) count = CL; else // BX_IA_SHLD_EqGqIb count = i->Ib(); count &= 0x3f; // use only 6 LSB's if (count) { op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); result_64 = (op1_64 << count) | (op2_64 >> (64 - count)); BX_WRITE_64BIT_REG(i->dst(), result_64); SET_FLAGS_OSZAPC_LOGIC_64(result_64); cf = (op1_64 >> (64 - count)) & 0x1; of = cf ^ (result_64 >> 63); // of = cf ^ result63 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, result_64; unsigned count; unsigned cf, of; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHRD_EqGq) count = CL; else // BX_IA_SHRD_EqGqIb count = i->Ib(); count &= 0x3f; // use only 6 LSB's if (count) { op2_64 = BX_READ_64BIT_REG(i->src()); result_64 = (op2_64 << (64 - count)) | (op1_64 >> count); write_RMW_virtual_qword(result_64); SET_FLAGS_OSZAPC_LOGIC_64(result_64); cf = (op1_64 >> (count - 1)) & 0x1; of = ((result_64 << 1) ^ result_64) >> 63; // of = result62 ^ result63 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, result_64; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_SHRD_EqGq) count = CL; else // BX_IA_SHRD_EqGqIb count = i->Ib(); count &= 0x3f; // use only 6 LSB's if (count) { op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); result_64 = (op2_64 << (64 - count)) | (op1_64 >> count); BX_WRITE_64BIT_REG(i->dst(), result_64); SET_FLAGS_OSZAPC_LOGIC_64(result_64); cf = (op1_64 >> (count - 1)) & 0x1; of = ((result_64 << 1) ^ result_64) >> 63; // of = result62 ^ result63 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EqM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_ROL_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { Bit64u result_64 = (op1_64 << count) | (op1_64 >> (64 - count)); write_RMW_virtual_qword(result_64); unsigned bit0 = (result_64 & 0x1); unsigned bit63 = (result_64 >> 63); // of = cf ^ result63 SET_FLAGS_OxxxxC(bit0 ^ bit63, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EqR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_ROL_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64u result_64 = (op1_64 << count) | (op1_64 >> (64 - count)); BX_WRITE_64BIT_REG(i->dst(), result_64); unsigned bit0 = (result_64 & 0x1); unsigned bit63 = (result_64 >> 63); // of = cf ^ result63 SET_FLAGS_OxxxxC(bit0 ^ bit63, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EqM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_ROR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { Bit64u result_64 = (op1_64 >> count) | (op1_64 << (64 - count)); write_RMW_virtual_qword(result_64); unsigned bit63 = (result_64 >> 63) & 1; unsigned bit62 = (result_64 >> 62) & 1; // of = result62 ^ result63 SET_FLAGS_OxxxxC(bit62 ^ bit63, bit63); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EqR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_ROR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64u result_64 = (op1_64 >> count) | (op1_64 << (64 - count)); BX_WRITE_64BIT_REG(i->dst(), result_64); unsigned bit63 = (result_64 >> 63) & 1; unsigned bit62 = (result_64 >> 62) & 1; // of = result62 ^ result63 SET_FLAGS_OxxxxC(bit62 ^ bit63, bit63); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EqM(bxInstruction_c *i) { Bit64u result_64; unsigned count; unsigned cf, of; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_RCL_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (!count) { BX_NEXT_INSTR(i); } if (count==1) { result_64 = (op1_64 << 1) | getB_CF(); } else { result_64 = (op1_64 << count) | (getB_CF() << (count - 1)) | (op1_64 >> (65 - count)); } write_RMW_virtual_qword(result_64); cf = (op1_64 >> (64 - count)) & 0x1; of = cf ^ (result_64 >> 63); // of = cf ^ result63 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EqR(bxInstruction_c *i) { Bit64u result_64; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_RCL_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (!count) { BX_NEXT_INSTR(i); } Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); if (count==1) { result_64 = (op1_64 << 1) | getB_CF(); } else { result_64 = (op1_64 << count) | (getB_CF() << (count - 1)) | (op1_64 >> (65 - count)); } BX_WRITE_64BIT_REG(i->dst(), result_64); cf = (op1_64 >> (64 - count)) & 0x1; of = cf ^ (result_64 >> 63); // of = cf ^ result63 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EqM(bxInstruction_c *i) { Bit64u result_64; unsigned count; unsigned of, cf; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_RCR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (!count) { BX_NEXT_INSTR(i); } if (count==1) { result_64 = (op1_64 >> 1) | (((Bit64u) getB_CF()) << 63); } else { result_64 = (op1_64 >> count) | (getB_CF() << (64 - count)) | (op1_64 << (65 - count)); } write_RMW_virtual_qword(result_64); cf = (op1_64 >> (count - 1)) & 0x1; of = ((result_64 << 1) ^ result_64) >> 63; SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EqR(bxInstruction_c *i) { Bit64u result_64; unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_RCR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (!count) { BX_NEXT_INSTR(i); } Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); if (count==1) { result_64 = (op1_64 >> 1) | (((Bit64u) getB_CF()) << 63); } else { result_64 = (op1_64 >> count) | (getB_CF() << (64 - count)) | (op1_64 << (65 - count)); } BX_WRITE_64BIT_REG(i->dst(), result_64); cf = (op1_64 >> (count - 1)) & 0x1; of = ((result_64 << 1) ^ result_64) >> 63; SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EqM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHL_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { /* count < 64, since only lower 6 bits used */ Bit64u result_64 = (op1_64 << count); unsigned cf = (op1_64 >> (64 - count)) & 0x1; unsigned of = cf ^ (result_64 >> 63); write_RMW_virtual_qword(result_64); SET_FLAGS_OSZAPC_LOGIC_64(result_64); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EqR(bxInstruction_c *i) { Bit64u op1_64, result_64; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_SHL_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { op1_64 = BX_READ_64BIT_REG(i->dst()); /* count < 64, since only lower 6 bits used */ result_64 = (op1_64 << count); BX_WRITE_64BIT_REG(i->dst(), result_64); cf = (op1_64 >> (64 - count)) & 0x1; of = cf ^ (result_64 >> 63); SET_FLAGS_OSZAPC_LOGIC_64(result_64); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EqM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { Bit64u result_64 = (op1_64 >> count); write_RMW_virtual_qword(result_64); unsigned cf = (op1_64 >> (count - 1)) & 0x1; // note, that of == result63 if count == 1 and // of == 0 if count >= 2 unsigned of = ((result_64 << 1) ^ result_64) >> 63; SET_FLAGS_OSZAPC_LOGIC_64(result_64); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EqR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SHR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64u result_64 = (op1_64 >> count); BX_WRITE_64BIT_REG(i->dst(), result_64); unsigned cf = (op1_64 >> (count - 1)) & 0x1; // note, that of == result63 if count == 1 and // of == 0 if count >= 2 unsigned of = ((result_64 << 1) ^ result_64) >> 63; SET_FLAGS_OSZAPC_LOGIC_64(result_64); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EqM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SAR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { /* count < 64, since only lower 6 bits used */ Bit64u result_64 = ((Bit64s) op1_64) >> count; write_RMW_virtual_qword(result_64); SET_FLAGS_OSZAPC_LOGIC_64(result_64); unsigned cf = (op1_64 >> (count - 1)) & 1; SET_FLAGS_OxxxxC(0, cf); /* signed overflow cannot happen in SAR instruction */ } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EqR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SAR_Eq) count = CL; else count = i->Ib(); count &= 0x3f; if (count) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); /* count < 64, since only lower 6 bits used */ Bit64u result_64 = ((Bit64s) op1_64) >> count; BX_WRITE_64BIT_REG(i->dst(), result_64); SET_FLAGS_OSZAPC_LOGIC_64(result_64); unsigned cf = (op1_64 >> (count - 1)) & 1; SET_FLAGS_OxxxxC(0, cf); /* signed overflow cannot happen in SAR instruction */ } BX_NEXT_INSTR(i); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/vmcs.cc0000644000175000017500000005636712020641453014421 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmcs.cc 11158 2012-05-02 18:11:39Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2009-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_VMX static unsigned vmcs_map[16][1+VMX_HIGHEST_VMCS_ENCODING]; void BX_CPU_C::init_VMCS(void) { static bx_bool vmcs_map_ready = 0; unsigned type, field; init_vmx_capabilities(); if (vmcs_map_ready) return; vmcs_map_ready = 1; for (type=0; type<16; type++) { for (field=0; field <= VMX_HIGHEST_VMCS_ENCODING; field++) { vmcs_map[type][field] = 0xffffffff; } } #if 1 // try to build generic VMCS map for (type=0; type<16; type++) { for (field=0; field <= VMX_HIGHEST_VMCS_ENCODING; field++) { unsigned encoding = ((type & 0xc) << 11) + ((type & 3) << 10) + field; if (vmcs_map[type][field] != 0xffffffff) { BX_PANIC(("VMCS type %d field %d (encoding = 0x%08x) is already initialized", type, field, encoding)); } if (vmcs_field_supported(encoding)) { // allocate 64 fields (4 byte each) per type vmcs_map[type][field] = VMCS_DATA_OFFSET + (type*64 + field) * 4; if(vmcs_map[type][field] >= VMX_VMCS_AREA_SIZE) { BX_PANIC(("VMCS type %d field %d (encoding = 0x%08x) is out of VMCS boundaries", type, field, encoding)); } BX_DEBUG(("VMCS field 0x%08x located at 0x%08x", encoding, vmcs_map[type][field])); } else { BX_DEBUG(("VMCS field 0x%08x is not supported", encoding)); } } } #else // define your own VMCS format #include "vmcs.h" #endif } #define VMCS_ENCODING_RESERVED_BITS (0xffff9000) unsigned vmcs_field_offset(Bit32u encoding) { if (encoding & VMCS_ENCODING_RESERVED_BITS) return 0xffffffff; unsigned field = VMCS_FIELD(encoding); if (field >= VMX_HIGHEST_VMCS_ENCODING) return 0xffffffff; return vmcs_map[VMCS_FIELD_INDEX(encoding)][field]; } bx_bool BX_CPU_C::vmcs_field_supported(Bit32u encoding) { switch(encoding) { #if BX_SUPPORT_VMX >= 2 /* VMCS 16-bit control fields */ /* binary 0000_00xx_xxxx_xxx0 */ case VMCS_16BIT_CONTROL_VPID: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_VPID); #endif /* VMCS 16-bit guest-state fields */ /* binary 0000_10xx_xxxx_xxx0 */ case VMCS_16BIT_GUEST_ES_SELECTOR: case VMCS_16BIT_GUEST_CS_SELECTOR: case VMCS_16BIT_GUEST_SS_SELECTOR: case VMCS_16BIT_GUEST_DS_SELECTOR: case VMCS_16BIT_GUEST_FS_SELECTOR: case VMCS_16BIT_GUEST_GS_SELECTOR: case VMCS_16BIT_GUEST_LDTR_SELECTOR: case VMCS_16BIT_GUEST_TR_SELECTOR: return 1; /* VMCS 16-bit host-state fields */ /* binary 0000_11xx_xxxx_xxx0 */ case VMCS_16BIT_HOST_ES_SELECTOR: case VMCS_16BIT_HOST_CS_SELECTOR: case VMCS_16BIT_HOST_SS_SELECTOR: case VMCS_16BIT_HOST_DS_SELECTOR: case VMCS_16BIT_HOST_FS_SELECTOR: case VMCS_16BIT_HOST_GS_SELECTOR: case VMCS_16BIT_HOST_TR_SELECTOR: return 1; /* VMCS 32_bit control fields */ /* binary 0100_00xx_xxxx_xxx0 */ case VMCS_32BIT_CONTROL_PIN_BASED_EXEC_CONTROLS: case VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS: case VMCS_32BIT_CONTROL_EXECUTION_BITMAP: case VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MASK: case VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MATCH: case VMCS_32BIT_CONTROL_CR3_TARGET_COUNT: case VMCS_32BIT_CONTROL_VMEXIT_CONTROLS: case VMCS_32BIT_CONTROL_VMEXIT_MSR_STORE_COUNT: case VMCS_32BIT_CONTROL_VMEXIT_MSR_LOAD_COUNT: case VMCS_32BIT_CONTROL_VMENTRY_CONTROLS: case VMCS_32BIT_CONTROL_VMENTRY_MSR_LOAD_COUNT: case VMCS_32BIT_CONTROL_VMENTRY_INTERRUPTION_INFO: case VMCS_32BIT_CONTROL_VMENTRY_EXCEPTION_ERR_CODE: case VMCS_32BIT_CONTROL_VMENTRY_INSTRUCTION_LENGTH: return 1; #if BX_SUPPORT_X86_64 case VMCS_32BIT_CONTROL_TPR_THRESHOLD: if (bx_cpuid_support_x86_64()) return BX_SUPPORT_VMX_EXTENSION(BX_VMX_TPR_SHADOW); else return 0; #endif case VMCS_32BIT_CONTROL_SECONDARY_VMEXEC_CONTROLS: return BX_CPU_THIS_PTR vmx_cap.vmx_vmexec_ctrl2_supported_bits; #if BX_SUPPORT_VMX >= 2 case VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_GAP: case VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_WINDOW: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAUSE_LOOP_EXITING); #endif /* VMCS 32-bit read only data fields */ /* binary 0100_01xx_xxxx_xxx0 */ case VMCS_32BIT_INSTRUCTION_ERROR: case VMCS_32BIT_VMEXIT_REASON: case VMCS_32BIT_VMEXIT_INTERRUPTION_INFO: case VMCS_32BIT_VMEXIT_INTERRUPTION_ERR_CODE: case VMCS_32BIT_IDT_VECTORING_INFO: case VMCS_32BIT_IDT_VECTORING_ERR_CODE: case VMCS_32BIT_VMEXIT_INSTRUCTION_LENGTH: case VMCS_32BIT_VMEXIT_INSTRUCTION_INFO: return 1; /* VMCS 32-bit guest-state fields */ /* binary 0100_10xx_xxxx_xxx0 */ case VMCS_32BIT_GUEST_ES_LIMIT: case VMCS_32BIT_GUEST_CS_LIMIT: case VMCS_32BIT_GUEST_SS_LIMIT: case VMCS_32BIT_GUEST_DS_LIMIT: case VMCS_32BIT_GUEST_FS_LIMIT: case VMCS_32BIT_GUEST_GS_LIMIT: case VMCS_32BIT_GUEST_LDTR_LIMIT: case VMCS_32BIT_GUEST_TR_LIMIT: case VMCS_32BIT_GUEST_GDTR_LIMIT: case VMCS_32BIT_GUEST_IDTR_LIMIT: case VMCS_32BIT_GUEST_ES_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_CS_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_SS_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_DS_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_FS_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_GS_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_LDTR_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_TR_ACCESS_RIGHTS: case VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE: case VMCS_32BIT_GUEST_ACTIVITY_STATE: case VMCS_32BIT_GUEST_SMBASE: case VMCS_32BIT_GUEST_IA32_SYSENTER_CS_MSR: return 1; #if BX_SUPPORT_VMX >= 2 case VMCS_32BIT_GUEST_PREEMPTION_TIMER_VALUE: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PREEMPTION_TIMER); #endif /* VMCS 32-bit host-state fields */ /* binary 0100_11xx_xxxx_xxx0 */ case VMCS_32BIT_HOST_IA32_SYSENTER_CS_MSR: return 1; /* VMCS 64-bit control fields */ /* binary 0010_00xx_xxxx_xxx0 */ case VMCS_64BIT_CONTROL_IO_BITMAP_A: case VMCS_64BIT_CONTROL_IO_BITMAP_A_HI: case VMCS_64BIT_CONTROL_IO_BITMAP_B: case VMCS_64BIT_CONTROL_IO_BITMAP_B_HI: case VMCS_64BIT_CONTROL_MSR_BITMAPS: case VMCS_64BIT_CONTROL_MSR_BITMAPS_HI: case VMCS_64BIT_CONTROL_VMEXIT_MSR_STORE_ADDR: case VMCS_64BIT_CONTROL_VMEXIT_MSR_STORE_ADDR_HI: case VMCS_64BIT_CONTROL_VMEXIT_MSR_LOAD_ADDR: case VMCS_64BIT_CONTROL_VMEXIT_MSR_LOAD_ADDR_HI: case VMCS_64BIT_CONTROL_VMENTRY_MSR_LOAD_ADDR: case VMCS_64BIT_CONTROL_VMENTRY_MSR_LOAD_ADDR_HI: case VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR: case VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR_HI: case VMCS_64BIT_CONTROL_TSC_OFFSET: case VMCS_64BIT_CONTROL_TSC_OFFSET_HI: return 1; #if BX_SUPPORT_X86_64 case VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR: case VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR_HI: if (bx_cpuid_support_x86_64()) return BX_SUPPORT_VMX_EXTENSION(BX_VMX_TPR_SHADOW); else return 0; case VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR: case VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_APIC_VIRTUALIZATION); #endif #if BX_SUPPORT_VMX >= 2 case VMCS_64BIT_CONTROL_EPTPTR: case VMCS_64BIT_CONTROL_EPTPTR_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT); case VMCS_64BIT_CONTROL_VMFUNC_CTRLS: case VMCS_64BIT_CONTROL_VMFUNC_CTRLS_HI: return BX_CPU_THIS_PTR vmx_cap.vmx_vmfunc_supported_bits; case VMCS_64BIT_CONTROL_EPTP_LIST_ADDRESS: case VMCS_64BIT_CONTROL_EPTP_LIST_ADDRESS_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPTP_SWITCHING); #endif #if BX_SUPPORT_VMX >= 2 /* VMCS 64-bit read only data fields */ /* binary 0010_01xx_xxxx_xxx0 */ case VMCS_64BIT_GUEST_PHYSICAL_ADDR: case VMCS_64BIT_GUEST_PHYSICAL_ADDR_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT); #endif /* VMCS 64-bit guest state fields */ /* binary 0010_10xx_xxxx_xxx0 */ case VMCS_64BIT_GUEST_LINK_POINTER: case VMCS_64BIT_GUEST_LINK_POINTER_HI: case VMCS_64BIT_GUEST_IA32_DEBUGCTL: case VMCS_64BIT_GUEST_IA32_DEBUGCTL_HI: return 1; #if BX_SUPPORT_VMX >= 2 case VMCS_64BIT_GUEST_IA32_PAT: case VMCS_64BIT_GUEST_IA32_PAT_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT); case VMCS_64BIT_GUEST_IA32_EFER: case VMCS_64BIT_GUEST_IA32_EFER_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER); #endif case VMCS_64BIT_GUEST_IA32_PERF_GLOBAL_CTRL: case VMCS_64BIT_GUEST_IA32_PERF_GLOBAL_CTRL_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL); #if BX_SUPPORT_VMX >= 2 case VMCS_64BIT_GUEST_IA32_PDPTE0: case VMCS_64BIT_GUEST_IA32_PDPTE0_HI: case VMCS_64BIT_GUEST_IA32_PDPTE1: case VMCS_64BIT_GUEST_IA32_PDPTE1_HI: case VMCS_64BIT_GUEST_IA32_PDPTE2: case VMCS_64BIT_GUEST_IA32_PDPTE2_HI: case VMCS_64BIT_GUEST_IA32_PDPTE3: case VMCS_64BIT_GUEST_IA32_PDPTE3_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT); #endif #if BX_SUPPORT_VMX >= 2 /* VMCS 64-bit host state fields */ /* binary 0010_11xx_xxxx_xxx0 */ case VMCS_64BIT_HOST_IA32_PAT: case VMCS_64BIT_HOST_IA32_PAT_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT); case VMCS_64BIT_HOST_IA32_EFER: case VMCS_64BIT_HOST_IA32_EFER_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER); #endif case VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL: case VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL_HI: return BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL); /* VMCS natural width control fields */ /* binary 0110_00xx_xxxx_xxx0 */ case VMCS_CONTROL_CR0_GUEST_HOST_MASK: case VMCS_CONTROL_CR4_GUEST_HOST_MASK: case VMCS_CONTROL_CR0_READ_SHADOW: case VMCS_CONTROL_CR4_READ_SHADOW: case VMCS_CR3_TARGET0: case VMCS_CR3_TARGET1: case VMCS_CR3_TARGET2: case VMCS_CR3_TARGET3: return 1; /* VMCS natural width read only data fields */ /* binary 0110_01xx_xxxx_xxx0 */ case VMCS_VMEXIT_QUALIFICATION: case VMCS_IO_RCX: case VMCS_IO_RSI: case VMCS_IO_RDI: case VMCS_IO_RIP: case VMCS_GUEST_LINEAR_ADDR: return 1; /* VMCS natural width guest state fields */ /* binary 0110_10xx_xxxx_xxx0 */ case VMCS_GUEST_CR0: case VMCS_GUEST_CR3: case VMCS_GUEST_CR4: case VMCS_GUEST_ES_BASE: case VMCS_GUEST_CS_BASE: case VMCS_GUEST_SS_BASE: case VMCS_GUEST_DS_BASE: case VMCS_GUEST_FS_BASE: case VMCS_GUEST_GS_BASE: case VMCS_GUEST_LDTR_BASE: case VMCS_GUEST_TR_BASE: case VMCS_GUEST_GDTR_BASE: case VMCS_GUEST_IDTR_BASE: case VMCS_GUEST_DR7: case VMCS_GUEST_RSP: case VMCS_GUEST_RIP: case VMCS_GUEST_RFLAGS: case VMCS_GUEST_PENDING_DBG_EXCEPTIONS: case VMCS_GUEST_IA32_SYSENTER_ESP_MSR: case VMCS_GUEST_IA32_SYSENTER_EIP_MSR: return 1; /* VMCS natural width host state fields */ /* binary 0110_11xx_xxxx_xxx0 */ case VMCS_HOST_CR0: case VMCS_HOST_CR3: case VMCS_HOST_CR4: case VMCS_HOST_FS_BASE: case VMCS_HOST_GS_BASE: case VMCS_HOST_TR_BASE: case VMCS_HOST_GDTR_BASE: case VMCS_HOST_IDTR_BASE: case VMCS_HOST_IA32_SYSENTER_ESP_MSR: case VMCS_HOST_IA32_SYSENTER_EIP_MSR: case VMCS_HOST_RSP: case VMCS_HOST_RIP: return 1; default: return 0; } return 0; } void BX_CPU_C::init_vmx_capabilities(void) { struct bx_VMX_Cap *cap = &BX_CPU_THIS_PTR vmx_cap; // pin based vm exec controls // ----------------------------------------------------------- // [00] External Interrupt Exiting // 1 [01] Reserved (must be '1) // 1 [02] Reserved (must be '1) // [03] NMI Exiting // 1 [04] Reserved (must be '1) // [05] Virtual NMI (require Virtual NMI support) // [06] Activate VMX Preemption Timer (require VMX Preemption Timer support) cap->vmx_pin_vmexec_ctrl_supported_bits = VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT | VMX_VM_EXEC_CTRL1_NMI_VMEXIT; if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VIRTUAL_NMI)) cap->vmx_pin_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL1_VIRTUAL_NMI; #if BX_SUPPORT_VMX >= 2 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PREEMPTION_TIMER)) cap->vmx_pin_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL1_VMX_PREEMPTION_TIMER_VMEXIT; #endif // proc based vm exec controls // ----------------------------------------------------------- // 0 [00] Reserved (must be '0) // 1 [01] Reserved (must be '1) // [02] Interrupt Window Exiting // [03] TSC Offset Enable // 1 [06-04] Reserved (must be '1) // [07] HLT Exiting // 1 [08] Reserved (must be '1) // [09] INVLPG Exiting // [10] MWAIT Exiting (require MONITOR/MWAIT support) // [11] RDPMC Exiting // [12] RDTSC Exiting // 1 [14-13] Reserved (must be '1) // 1 [15] CR3 Write Exiting (legacy must be '1, introduced with EPT support) // 1 [16] CR3 Read Exiting (legacy must be '1, introduced with EPT support) // 0 [18-17] Reserved (must be '0) // [19] CR8 Write Exiting (require TPR Shadow support, require x86-64 support) // [20] CR8 Read Exiting (require TPR Shadow support, require x86-64 support) // [21] TPR Shadow Enable (require TPR Shadow support, require x86-64 support) // [22] NMI Window Exiting (require Virtual NMI support) // [23] DRx Access Exiting // [24] I/O Access Exiting // [25] I/O Bitmaps // 1 [26] Reserved (must be '1) // [27] Monitor Trap Flag Enable (require Monitor Trap Flag support) // [28] MSR Bitmaps // [29] MONITOR Exiting (require MONITOR/MWAIT support) // [30] PAUSE Exiting // [31] Secondary proc-based vmexec controls cap->vmx_proc_vmexec_ctrl_supported_bits = VMX_VM_EXEC_CTRL2_INTERRUPT_WINDOW_VMEXIT | VMX_VM_EXEC_CTRL2_TSC_OFFSET | VMX_VM_EXEC_CTRL2_HLT_VMEXIT | VMX_VM_EXEC_CTRL2_INVLPG_VMEXIT | VMX_VM_EXEC_CTRL2_RDPMC_VMEXIT | VMX_VM_EXEC_CTRL2_RDTSC_VMEXIT | VMX_VM_EXEC_CTRL2_DRx_ACCESS_VMEXIT | VMX_VM_EXEC_CTRL2_IO_VMEXIT | VMX_VM_EXEC_CTRL2_IO_BITMAPS | VMX_VM_EXEC_CTRL2_MSR_BITMAPS | VMX_VM_EXEC_CTRL2_PAUSE_VMEXIT; #if BX_SUPPORT_MONITOR_MWAIT if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT)) { cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_MWAIT_VMEXIT | VMX_VM_EXEC_CTRL2_MONITOR_VMEXIT; } #endif #if BX_SUPPORT_X86_64 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_TPR_SHADOW)) { cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_TPR_SHADOW; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_CR8_WRITE_VMEXIT | VMX_VM_EXEC_CTRL2_CR8_READ_VMEXIT; } #endif if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VIRTUAL_NMI)) cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT; if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_MONITOR_TRAP_FLAG)) cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_MONITOR_TRAP_FLAG; #if BX_SUPPORT_VMX >= 2 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT)) { cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_CR3_WRITE_VMEXIT | VMX_VM_EXEC_CTRL2_CR3_READ_VMEXIT; } #endif // secondary proc based vm exec controls // ----------------------------------------------------------- // [00] Apic Virtualization (require x86-64 for TPR shadow) // [01] EPT Enable (require x86-64 for 4-level page walk) // [02] Descriptor Table Exiting // [03] Enable RDTSCP instruction (RDTSCP will #UD if not set) // [04] Virtualize X2APIC Mode (doesn't require actual X2APIC to be enabled) // [05] VPID Enable // [06] WBINVD Exiting // [07] Unrestricted Guest (require EPT) // [08] Reserved // [09] Reserved // [10] PAUSE Loop Exiting // [11] RDRAND Exiting (require RDRAND instruction support) // [12] Enable INVPCID instruction (require INVPCID instruction support) // [13] Enable VM Functions cap->vmx_vmexec_ctrl2_supported_bits = 0; #if BX_SUPPORT_X86_64 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_APIC_VIRTUALIZATION)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES; #endif #if BX_SUPPORT_VMX >= 2 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_EPT_ENABLE; if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_DESCRIPTOR_TABLE_EXIT)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT; #endif if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_RDTSCP)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_RDTSCP; #if BX_SUPPORT_VMX >= 2 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_X2APIC_VIRTUALIZATION)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE; if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VPID)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VPID_ENABLE; #endif if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_WBINVD_VMEXIT)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT; #if BX_SUPPORT_VMX >= 2 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_UNRESTRICTED_GUEST)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST; if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAUSE_LOOP_EXITING)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_PAUSE_LOOP_VMEXIT; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_INVPCID)) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_INVPCID; #endif // enable secondary vm exec controls if needed if (cap->vmx_vmexec_ctrl2_supported_bits != 0) cap->vmx_proc_vmexec_ctrl_supported_bits |= VMX_VM_EXEC_CTRL2_SECONDARY_CONTROLS; // vmexit controls // ----------------------------------------------------------- // 1 [01-00] Reserved (must be '1) // 1 [02] Save guest MSR_DEBUGCTL on VMEXIT (legacy must be '1) // 1 [08-03] Reserved (must be '1) // [09] Host Address Space Size (x86-64 host, x86-64 support required) // 1 [11-10] Reserved (must be '1) // [12] Load host MSR_PERF_GLOBAL_CTRL on VMEXIT // 1 [14-13] Reserved (must be '1) // [15] Acknowledge interrupts on VMEXIT // 1 [17-16] Reserved (must be '1) // [18] Save guest MSR_PAT on VMEXIT // [19] Load host MSR_PAT on VMEXIT // [20] Save guest MSR_EFER on VMEXIT // [21] Load host MSR_EFER on VMEXIT // [22] Save VMX preemption timer counter on VMEXIT cap->vmx_vmexit_ctrl_supported_bits = VMX_VMEXIT_CTRL1_INTA_ON_VMEXIT | VMX_VMEXIT_CTRL1_SAVE_DBG_CTRLS; #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_HOST_ADDR_SPACE_SIZE; #endif if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL)) cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_LOAD_PERF_GLOBAL_CTRL_MSR; #if BX_SUPPORT_VMX >= 2 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT)) { cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_STORE_PAT_MSR | VMX_VMEXIT_CTRL1_LOAD_PAT_MSR; } if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER)) { cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_STORE_EFER_MSR | VMX_VMEXIT_CTRL1_LOAD_EFER_MSR; } if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PREEMPTION_TIMER)) cap->vmx_vmexit_ctrl_supported_bits |= VMX_VMEXIT_CTRL1_STORE_VMX_PREEMPTION_TIMER; #endif // vmentry controls // ----------------------------------------------------------- // 1 [01-00] Reserved (must be '1) // 1 [02] Load MSR_DEBUGCTL on VMEXIT (legacy must be '1) // 1 [08-03] Reserved (must be '1) // [09] x86-64 guest (x86-64 support required) // [10] Enter to SMM mode // [11] Deactivate Dual SMM Monitor treatment // 1 [12] Reserved (must be '1) // [13] Load guest MSR_PERF_GLOBAL_CTRL // [14] Load guest MSR_PAT // [15] Load guest MSR_EFER cap->vmx_vmentry_ctrl_supported_bits = VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS | VMX_VMENTRY_CTRL1_SMM_ENTER | VMX_VMENTRY_CTRL1_DEACTIVATE_DUAL_MONITOR_TREATMENT; #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_X86_64_GUEST; #endif if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PERF_GLOBAL_CTRL)) cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_PERF_GLOBAL_CTRL_MSR; #if BX_SUPPORT_VMX >= 2 if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_PAT)) cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_PAT_MSR; if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EFER)) cap->vmx_vmentry_ctrl_supported_bits |= VMX_VMENTRY_CTRL1_LOAD_EFER_MSR; #endif #if BX_SUPPORT_VMX >= 2 // EPT/VPID capabilities // ----------------------------------------------------------- // [0] - BX_EPT_ENTRY_EXECUTE_ONLY support // [6] - 4-levels EPT page walk length // [8] - allow UC EPT paging structure memory type // [14] - allow WB EPT paging structure memory type // [16] - EPT 2M pages support // [17] - EPT 1G pages support // [20] - INVEPT instruction supported // [21] - EPT A/D bits supported // [25] - INVEPT single-context invalidation supported // [26] - INVEPT all-context invalidation supported // [32] - INVVPID instruction supported // [40] - individual-address INVVPID is supported // [41] - single-context INVVPID is supported // [42] - all-context INVVPID is supported // [43] - single-context-retaining-globals INVVPID is supported if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT)) { cap->vmx_ept_vpid_cap_supported_bits = BX_CONST64(0x06114141); if (bx_cpuid_support_1g_paging()) cap->vmx_ept_vpid_cap_supported_bits |= (1 << 17); if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT_ACCESS_DIRTY)) cap->vmx_ept_vpid_cap_supported_bits |= (1 << 21); } if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_VPID)) cap->vmx_ept_vpid_cap_supported_bits |= BX_CONST64(0x00000f01) << 32; // vm functions // ----------------------------------------------------------- // [00] EPTP switching // [63-01] reserved cap->vmx_vmfunc_supported_bits = 0; if (BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPTP_SWITCHING)) cap->vmx_vmfunc_supported_bits |= VMX_VMFUNC_EPTP_SWITCHING_MASK; // enable vm functions secondary vmexec control if needed if (cap->vmx_vmfunc_supported_bits != 0) cap->vmx_vmexec_ctrl2_supported_bits |= VMX_VM_EXEC_CTRL3_VMFUNC_ENABLE; #endif } #endif bochs-2.6/cpu/crc32.cc0000644000175000017500000001043712020641453014351 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: crc32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 6 // 3-byte opcodes #define CRC32_POLYNOMIAL BX_CONST64(0x11edc6f41) // primitives for CRC32 usage BX_CPP_INLINE Bit8u BitReflect8(Bit8u val8) { return ((val8 & 0x80) >> 7) | ((val8 & 0x40) >> 5) | ((val8 & 0x20) >> 3) | ((val8 & 0x10) >> 1) | ((val8 & 0x08) << 1) | ((val8 & 0x04) << 3) | ((val8 & 0x02) << 5) | ((val8 & 0x01) << 7); } BX_CPP_INLINE Bit16u BitReflect16(Bit16u val16) { return ((Bit16u)(BitReflect8(val16 & 0xff)) << 8) | BitReflect8(val16 >> 8); } BX_CPP_INLINE Bit32u BitReflect32(Bit32u val32) { return ((Bit32u)(BitReflect16(val32 & 0xffff)) << 16) | BitReflect16(val32 >> 16); } static Bit32u mod2_64bit(Bit64u divisor, Bit64u dividend) { Bit64u remainder = dividend >> 32; for (int bitpos=31; bitpos>=0; bitpos--) { // copy one more bit from the dividend remainder = (remainder << 1) | ((dividend >> bitpos) & 1); // if MSB is set, then XOR divisor and get new remainder if (((remainder >> 32) & 1) == 1) { remainder ^= divisor; } } return (Bit32u) remainder; } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CRC32_GdEbR(bxInstruction_c *i) { Bit8u op1 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u op2 = BX_READ_32BIT_REG(i->dst()); op2 = BitReflect32(op2); Bit64u tmp1 = ((Bit64u) BitReflect8 (op1)) << 32; Bit64u tmp2 = ((Bit64u) op2) << 8; Bit64u tmp3 = tmp1 ^ tmp2; op2 = mod2_64bit(CRC32_POLYNOMIAL, tmp3); BX_WRITE_32BIT_REGZ(i->dst(), BitReflect32(op2)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CRC32_GdEwR(bxInstruction_c *i) { Bit32u op2 = BX_READ_32BIT_REG(i->dst()); op2 = BitReflect32(op2); Bit16u op1 = BX_READ_16BIT_REG(i->src()); Bit64u tmp1 = ((Bit64u) BitReflect16(op1)) << 32; Bit64u tmp2 = ((Bit64u) op2) << 16; Bit64u tmp3 = tmp1 ^ tmp2; op2 = mod2_64bit(CRC32_POLYNOMIAL, tmp3); BX_WRITE_32BIT_REGZ(i->dst(), BitReflect32(op2)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CRC32_GdEdR(bxInstruction_c *i) { Bit32u op2 = BX_READ_32BIT_REG(i->dst()); op2 = BitReflect32(op2); Bit32u op1 = BX_READ_32BIT_REG(i->src()); Bit64u tmp1 = ((Bit64u) BitReflect32(op1)) << 32; Bit64u tmp2 = ((Bit64u) op2) << 32; Bit64u tmp3 = tmp1 ^ tmp2; op2 = mod2_64bit(CRC32_POLYNOMIAL, tmp3); BX_WRITE_32BIT_REGZ(i->dst(), BitReflect32(op2)); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CRC32_GdEqR(bxInstruction_c *i) { Bit32u op2 = BX_READ_32BIT_REG(i->dst()); op2 = BitReflect32(op2); Bit64u op1 = BX_READ_64BIT_REG(i->src()); Bit64u tmp1 = ((Bit64u) BitReflect32(op1 & 0xffffffff)) << 32; Bit64u tmp2 = ((Bit64u) op2) << 32; Bit64u tmp3 = tmp1 ^ tmp2; op2 = mod2_64bit(CRC32_POLYNOMIAL, tmp3); tmp1 = ((Bit64u) BitReflect32(op1 >> 32)) << 32; tmp2 = ((Bit64u) op2) << 32; tmp3 = tmp1 ^ tmp2; op2 = mod2_64bit(CRC32_POLYNOMIAL, tmp3); BX_WRITE_32BIT_REGZ(i->dst(), BitReflect32(op2)); BX_NEXT_INSTR(i); } #endif // BX_SUPPORT_X86_64 #endif // BX_CPU_LEVEL >= 6 bochs-2.6/cpu/xsave.cc0000644000175000017500000003374712020641453014574 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: xsave.cc 11301 2012-07-27 08:13:39Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR /* 0F AE /4 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XSAVE(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 unsigned index; BxPackedXmmRegister xmm; BX_CPU_THIS_PTR prepareXSAVE(); BX_DEBUG(("XSAVE: save processor state XCR0=0x%08x", BX_CPU_THIS_PTR xcr0.get32())); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); bx_address laddr = get_laddr(i->seg(), eaddr); if (laddr & 0x3f) { BX_ERROR(("XSAVE: access not aligned to 64-byte")); exception(BX_GP_EXCEPTION, 0); } bx_address asize_mask = i->asize_mask(); // // We will go feature-by-feature and not run over all XCR0 bits // Bit64u header1 = read_virtual_qword(i->seg(), (eaddr + 512) & asize_mask); Bit32u features_save_enable_mask = BX_CPU_THIS_PTR xcr0.get32() & EAX; ///////////////////////////////////////////////////////////////////////////// if ((features_save_enable_mask & BX_XCR0_FPU_MASK) != 0) { xmm.xmm16u(0) = BX_CPU_THIS_PTR the_i387.get_control_word(); xmm.xmm16u(1) = BX_CPU_THIS_PTR the_i387.get_status_word(); xmm.xmm16u(2) = pack_FPU_TW(BX_CPU_THIS_PTR the_i387.get_tag_word()); /* x87 FPU Opcode (16 bits) */ /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ xmm.xmm16u(3) = BX_CPU_THIS_PTR the_i387.foo; /* * x87 FPU IP Offset (32/64 bits) * The contents of this field differ depending on the current * addressing mode (16/32/64 bit) when the FXSAVE instruction was executed: * + 64-bit mode - 64-bit IP offset * + 32-bit mode - 32-bit IP offset * + 16-bit mode - low 16 bits are IP offset; high 16 bits are reserved. * x87 CS FPU IP Selector * + 16 bit, in 16/32 bit mode only */ #if BX_SUPPORT_X86_64 if (i->os64L()) { xmm.xmm64u(1) = (BX_CPU_THIS_PTR the_i387.fip); } else #endif { xmm.xmm32u(2) = (Bit32u)(BX_CPU_THIS_PTR the_i387.fip); xmm.xmm32u(3) = (BX_CPU_THIS_PTR the_i387.fcs); } write_virtual_dqword(i->seg(), eaddr, (Bit8u *) &xmm); /* * x87 FPU Instruction Operand (Data) Pointer Offset (32/64 bits) * The contents of this field differ depending on the current * addressing mode (16/32 bit) when the FXSAVE instruction was executed: * + 64-bit mode - 64-bit offset * + 32-bit mode - 32-bit offset * + 16-bit mode - low 16 bits are offset; high 16 bits are reserved. * x87 DS FPU Instruction Operand (Data) Pointer Selector * + 16 bit, in 16/32 bit mode only */ #if BX_SUPPORT_X86_64 if (i->os64L()) { write_virtual_qword(i->seg(), (eaddr + 16) & asize_mask, BX_CPU_THIS_PTR the_i387.fdp); } else #endif { write_virtual_dword(i->seg(), (eaddr + 16) & asize_mask, (Bit32u) BX_CPU_THIS_PTR the_i387.fdp); write_virtual_dword(i->seg(), (eaddr + 20) & asize_mask, (Bit32u) BX_CPU_THIS_PTR the_i387.fds); } /* do not touch MXCSR state */ /* store i387 register file */ for(index=0; index < 8; index++) { const floatx80 &fp = BX_READ_FPU_REG(index); xmm.xmm64u(0) = fp.fraction; xmm.xmm64u(1) = 0; xmm.xmm16u(4) = fp.exp; write_virtual_dqword(i->seg(), (eaddr+index*16+32) & asize_mask, (Bit8u *) &xmm); } header1 |= BX_XCR0_FPU_MASK; } ///////////////////////////////////////////////////////////////////////////// if ((features_save_enable_mask & (BX_XCR0_SSE_MASK | BX_XCR0_AVX_MASK)) != 0) { // store MXCSR write_virtual_dword(i->seg(), (eaddr + 24) & asize_mask, BX_MXCSR_REGISTER); write_virtual_dword(i->seg(), (eaddr + 28) & asize_mask, MXCSR_MASK); } ///////////////////////////////////////////////////////////////////////////// if ((features_save_enable_mask & BX_XCR0_SSE_MASK) != 0) { /* store XMM register file */ for(index=0; index < BX_XMM_REGISTERS; index++) { // save XMM8-XMM15 only in 64-bit mode if (index < 8 || long64_mode()) { write_virtual_dqword(i->seg(), (eaddr+index*16+160) & asize_mask, (Bit8u *)(&BX_READ_XMM_REG(index))); } } header1 |= BX_XCR0_SSE_MASK; } #if BX_SUPPORT_AVX ///////////////////////////////////////////////////////////////////////////// if ((features_save_enable_mask & BX_XCR0_AVX_MASK) != 0) { /* store AVX state */ for(index=0; index < BX_XMM_REGISTERS; index++) { // save YMM8-YMM15 only in 64-bit mode if (index < 8 || long64_mode()) { write_virtual_dqword(i->seg(), (eaddr+index*16+576) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG_LINE(index, 1))); } } header1 |= BX_XCR0_AVX_MASK; } #endif // always update header to 'dirty' state write_virtual_qword(i->seg(), (eaddr + 512) & asize_mask, header1); #endif BX_NEXT_INSTR(i); } /* 0F AE /5 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XRSTOR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 unsigned index; BxPackedXmmRegister xmm; BX_CPU_THIS_PTR prepareXSAVE(); BX_DEBUG(("XRSTOR: restore processor state XCR0=0x%08x", BX_CPU_THIS_PTR xcr0.get32())); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); bx_address laddr = get_laddr(i->seg(), eaddr); if (laddr & 0x3f) { BX_ERROR(("XRSTOR: access not aligned to 64-byte")); exception(BX_GP_EXCEPTION, 0); } bx_address asize_mask = i->asize_mask(); Bit64u header1 = read_virtual_qword(i->seg(), (eaddr + 512) & asize_mask); Bit64u header2 = read_virtual_qword(i->seg(), (eaddr + 520) & asize_mask); Bit64u header3 = read_virtual_qword(i->seg(), (eaddr + 528) & asize_mask); if ((~BX_CPU_THIS_PTR xcr0.get32() & header1) != 0) { BX_ERROR(("XRSTOR: Broken header state")); exception(BX_GP_EXCEPTION, 0); } if (header2 != 0 || header3 != 0) { BX_ERROR(("XRSTOR: Reserved header state is not '0")); exception(BX_GP_EXCEPTION, 0); } // // We will go feature-by-feature and not run over all XCR0 bits // Bit32u features_load_enable_mask = BX_CPU_THIS_PTR xcr0.get32() & EAX; ///////////////////////////////////////////////////////////////////////////// if ((features_load_enable_mask & BX_XCR0_FPU_MASK) != 0) { if (header1 & BX_XCR0_FPU_MASK) { // load FPU state from XSAVE area read_virtual_dqword(i->seg(), eaddr, (Bit8u *) &xmm); BX_CPU_THIS_PTR the_i387.cwd = xmm.xmm16u(0); BX_CPU_THIS_PTR the_i387.swd = xmm.xmm16u(1); BX_CPU_THIS_PTR the_i387.tos = (xmm.xmm16u(1) >> 11) & 0x07; /* always set bit 6 as '1 */ BX_CPU_THIS_PTR the_i387.cwd = (BX_CPU_THIS_PTR the_i387.cwd & ~FPU_CW_Reserved_Bits) | 0x0040; /* Restore x87 FPU Opcode */ /* The lower 11 bits contain the FPU opcode, upper 5 bits are reserved */ BX_CPU_THIS_PTR the_i387.foo = xmm.xmm16u(3) & 0x7FF; /* Restore x87 FPU IP */ #if BX_SUPPORT_X86_64 if (i->os64L()) { BX_CPU_THIS_PTR the_i387.fip = xmm.xmm64u(1); BX_CPU_THIS_PTR the_i387.fcs = 0; } else #endif { BX_CPU_THIS_PTR the_i387.fip = xmm.xmm32u(2); BX_CPU_THIS_PTR the_i387.fcs = xmm.xmm16u(6); } Bit32u tag_byte = xmm.xmmubyte(4); /* Restore x87 FPU DP */ read_virtual_dqword(i->seg(), (eaddr + 16) & asize_mask, (Bit8u *) &xmm); #if BX_SUPPORT_X86_64 if (i->os64L()) { BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm64u(0); BX_CPU_THIS_PTR the_i387.fds = 0; } else #endif { BX_CPU_THIS_PTR the_i387.fdp = xmm.xmm32u(0); BX_CPU_THIS_PTR the_i387.fds = xmm.xmm16u(2); } /* load i387 register file */ for(index=0; index < 8; index++) { floatx80 reg; reg.fraction = read_virtual_qword(i->seg(), (eaddr+index*16+32) & asize_mask); reg.exp = read_virtual_word (i->seg(), (eaddr+index*16+40) & asize_mask); // update tag only if it is not empty BX_WRITE_FPU_REGISTER_AND_TAG(reg, IS_TAG_EMPTY(index) ? FPU_Tag_Empty : FPU_tagof(reg), index); } /* Restore floating point tag word - see desription for FXRSTOR instruction */ BX_CPU_THIS_PTR the_i387.twd = unpack_FPU_TW(tag_byte); /* check for unmasked exceptions */ if (FPU_PARTIAL_STATUS & ~FPU_CONTROL_WORD & FPU_CW_Exceptions_Mask) { /* set the B and ES bits in the status-word */ FPU_PARTIAL_STATUS |= FPU_SW_Summary | FPU_SW_Backward; } else { /* clear the B and ES bits in the status-word */ FPU_PARTIAL_STATUS &= ~(FPU_SW_Summary | FPU_SW_Backward); } } else { // initialize FPU with reset values BX_CPU_THIS_PTR the_i387.init(); for (index=0;index<8;index++) { static floatx80 reg = { 0, 0 }; BX_FPU_REG(index) = reg; } } } ///////////////////////////////////////////////////////////////////////////// if ((features_load_enable_mask & (BX_XCR0_SSE_MASK | BX_XCR0_AVX_MASK)) != 0) { Bit32u new_mxcsr = read_virtual_dword(i->seg(), (eaddr + 24) & asize_mask); if(new_mxcsr & ~MXCSR_MASK) exception(BX_GP_EXCEPTION, 0); BX_MXCSR_REGISTER = new_mxcsr; } static BxPackedXmmRegister xmmnil; /* compiler will clear the variable */ ///////////////////////////////////////////////////////////////////////////// if ((features_load_enable_mask & BX_XCR0_SSE_MASK) != 0) { if (header1 & BX_XCR0_SSE_MASK) { // load SSE state from XSAVE area for(index=0; index < BX_XMM_REGISTERS; index++) { // restore XMM8-XMM15 only in 64-bit mode if (index < 8 || long64_mode()) { read_virtual_dqword(i->seg(), (eaddr+index*16+160) & asize_mask, (Bit8u *)(&BX_READ_XMM_REG(index))); } } } else { // initialize SSE with reset values for(index=0; index < BX_XMM_REGISTERS; index++) { // set XMM8-XMM15 only in 64-bit mode if (index < 8 || long64_mode()) BX_WRITE_XMM_REG(index, xmmnil); } } } #if BX_SUPPORT_AVX ///////////////////////////////////////////////////////////////////////////// if ((features_load_enable_mask & BX_XCR0_AVX_MASK) != 0) { if (header1 & BX_XCR0_AVX_MASK) { // load AVX state from XSAVE area for(index=0; index < BX_XMM_REGISTERS; index++) { // restore YMM8-YMM15 only in 64-bit mode if (index < 8 || long64_mode()) { read_virtual_dqword(i->seg(), (eaddr+index*16+576) & asize_mask, (Bit8u *)(&BX_READ_AVX_REG_LINE(index, 1))); } } } else { // initialize upper part of AVX registers with reset values for(index=0; index < BX_XMM_REGISTERS; index++) { // set YMM8-YMM15 only in 64-bit mode if (index < 8 || long64_mode()) { for (int j=2;j < BX_VLMAX*2;j++) BX_CPU_THIS_PTR vmm[index].avx64u(j) = 0; } } } } #endif #endif BX_NEXT_INSTR(i); } /* 0F 01 D0 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XGETBV(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 if(! BX_CPU_THIS_PTR cr4.get_OSXSAVE()) { BX_ERROR(("XGETBV: OSXSAVE feature is not enabled in CR4!")); exception(BX_UD_EXCEPTION, 0); } // For now hardcoded handle only XCR0 register, it should take a few // years until extension will be required if (ECX != 0) { BX_ERROR(("XGETBV: Invalid XCR register %d", ECX)); exception(BX_GP_EXCEPTION, 0); } RDX = 0; RAX = BX_CPU_THIS_PTR xcr0.get32(); #endif BX_NEXT_INSTR(i); } /* 0F 01 D1 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XSETBV(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 if(! BX_CPU_THIS_PTR cr4.get_OSXSAVE()) { BX_ERROR(("XSETBV: OSXSAVE feature is not enabled in CR4!")); exception(BX_UD_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: XSETBV in VMX non-root operation")); VMexit(VMX_VMEXIT_XSETBV, 0); } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_XSETBV)) Svm_Vmexit(SVM_VMEXIT_XSETBV); } #endif // CPL is always 3 in vm8086 mode if (/* v8086_mode() || */ CPL != 0) { BX_ERROR(("XSETBV: The current priveledge level is not 0")); exception(BX_GP_EXCEPTION, 0); } // For now hardcoded handle only XCR0 register, it should take a few // years until extension will be required if (ECX != 0) { BX_ERROR(("XSETBV: Invalid XCR register %d", ECX)); exception(BX_GP_EXCEPTION, 0); } if (EDX != 0 || (EAX & ~BX_CPU_THIS_PTR xcr0_suppmask) != 0 || (EAX & 1) == 0) { BX_ERROR(("XSETBV: Attempting to change reserved bits!")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_AVX if ((EAX & (BX_XCR0_AVX_BIT | BX_XCR0_SSE_BIT)) == BX_XCR0_AVX_BIT) { BX_ERROR(("XSETBV: Attempting to set AVX without SSE!")); exception(BX_GP_EXCEPTION, 0); } #endif BX_CPU_THIS_PTR xcr0.set32(EAX); #if BX_SUPPORT_AVX handleAvxModeChange(); #endif #endif // BX_CPU_LEVEL >= 6 BX_NEXT_TRACE(i); } bochs-2.6/cpu/ctrl_xfer_pro.cc0000644000175000017500000001260712020641453016306 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: ctrl_xfer_pro.cc 11107 2012-03-25 19:07:17Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR /* pass zero in check_rpl if no needed selector RPL checking for non-conforming segments */ void BX_CPU_C::check_cs(bx_descriptor_t *descriptor, Bit16u cs_raw, Bit8u check_rpl, Bit8u check_cpl) { // descriptor AR byte must indicate code segment else #GP(selector) if (descriptor->valid==0 || descriptor->segment==0 || IS_DATA_SEGMENT(descriptor->type)) { BX_ERROR(("check_cs(0x%04x): not a valid code segment !", cs_raw)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } #if BX_SUPPORT_X86_64 if (long_mode()) { if (descriptor->u.segment.l && descriptor->u.segment.d_b) { BX_ERROR(("check_cs(0x%04x): Both CS.L and CS.D_B bits enabled !", cs_raw)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } } #endif // if non-conforming, code segment descriptor DPL must = CPL else #GP(selector) if (IS_CODE_SEGMENT_NON_CONFORMING(descriptor->type)) { if (descriptor->dpl != check_cpl) { BX_ERROR(("check_cs(0x%04x): non-conforming code seg descriptor dpl != cpl, dpl=%d, cpl=%d", cs_raw, descriptor->dpl, check_cpl)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } /* RPL of destination selector must be <= CPL else #GP(selector) */ if (check_rpl > check_cpl) { BX_ERROR(("check_cs(0x%04x): non-conforming code seg selector rpl > cpl, rpl=%d, cpl=%d", cs_raw, check_rpl, check_cpl)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } } // if conforming, then code segment descriptor DPL must <= CPL else #GP(selector) else { if (descriptor->dpl > check_cpl) { BX_ERROR(("check_cs(0x%04x): conforming code seg descriptor dpl > cpl, dpl=%d, cpl=%d", cs_raw, descriptor->dpl, check_cpl)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } } // code segment must be present else #NP(selector) if (! descriptor->p) { BX_ERROR(("check_cs(0x%04x): code segment not present !", cs_raw)); exception(BX_NP_EXCEPTION, cs_raw & 0xfffc); } } void BX_CPP_AttrRegparmN(3) BX_CPU_C::load_cs(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl) { // Add cpl to the selector value. selector->value = (0xfffc & selector->value) | cpl; touch_segment(selector, descriptor); #ifdef BX_SUPPORT_CS_LIMIT_DEMOTION // Handle special case of CS.LIMIT demotion (new descriptor limit is // smaller than current one) if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled > descriptor->u.segment.limit_scaled) BX_CPU_THIS_PTR iCache.flushICacheEntries(); #endif BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector = *selector; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache = *descriptor; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl = cpl; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 1; #if BX_SUPPORT_X86_64 if (long_mode()) { handleCpuModeChange(); } #endif updateFetchModeMask(/* CS reloaded */); #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(/* CPL change */); #endif // Loading CS will invalidate the EIP fetch window. invalidate_prefetch_q(); } void BX_CPU_C::branch_far32(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit32u eip, Bit8u cpl) { /* instruction pointer must be in code segment limit else #GP(0) */ if (eip > descriptor->u.segment.limit_scaled) { BX_ERROR(("branch_far32: EIP > limit")); exception(BX_GP_EXCEPTION, 0); } /* Load CS:IP from destination pointer */ /* Load CS-cache with new segment descriptor */ load_cs(selector, descriptor, cpl); /* Change the EIP value */ EIP = eip; } void BX_CPU_C::branch_far64(bx_selector_t *selector, bx_descriptor_t *descriptor, bx_address rip, Bit8u cpl) { #if BX_SUPPORT_X86_64 if (long_mode() && descriptor->u.segment.l) { if (! IsCanonical(rip)) { BX_ERROR(("branch_far64: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0); } } else #endif { rip &= 0xffffffff; /* instruction pointer must be in code segment limit else #GP(0) */ if (rip > descriptor->u.segment.limit_scaled) { BX_ERROR(("branch_far64: RIP > limit")); exception(BX_GP_EXCEPTION, 0); } } /* Load CS:IP from destination pointer */ /* Load CS-cache with new segment descriptor */ load_cs(selector, descriptor, cpl); /* Change the RIP value */ RIP = rip; } bochs-2.6/cpu/vmx.h0000644000175000017500000011605312020641453014112 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmx.h 11385 2012-08-31 15:38:28Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2009-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef _BX_VMX_INTEL_H_ #define _BX_VMX_INTEL_H_ #define VMX_VMCS_AREA_SIZE 4096 #define VMX_VMCS_REVISION_ID 0x10 /* better to be uniq bochs VMCS revision id */ // VMCS pointer is always 64-bit variable #define BX_INVALID_VMCSPTR BX_CONST64(0xFFFFFFFFFFFFFFFF) // bits supported in IA32_FEATURE_CONTROL MSR #define BX_IA32_FEATURE_CONTROL_LOCK_BIT 0x1 #define BX_IA32_FEATURE_CONTROL_VMX_ENABLE_BIT 0x4 #define BX_IA32_FEATURE_CONTROL_BITS \ (BX_IA32_FEATURE_CONTROL_LOCK_BIT | BX_IA32_FEATURE_CONTROL_VMX_ENABLE_BIT) // VMX error codes enum VMX_error_code { VMXERR_NO_ERROR = 0, VMXERR_VMCALL_IN_VMX_ROOT_OPERATION = 1, VMXERR_VMCLEAR_WITH_INVALID_ADDR = 2, VMXERR_VMCLEAR_WITH_VMXON_VMCS_PTR = 3, VMXERR_VMLAUNCH_NON_CLEAR_VMCS = 4, VMXERR_VMRESUME_NON_LAUNCHED_VMCS = 5, VMXERR_VMRESUME_VMCS_CORRUPTED = 6, VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD = 7, VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD = 8, VMXERR_VMPTRLD_INVALID_PHYSICAL_ADDRESS = 9, VMXERR_VMPTRLD_WITH_VMXON_PTR = 10, VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID = 11, VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS = 12, VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT = 13, VMXERR_RESERVED14 = 14, VMXERR_VMXON_IN_VMX_ROOT_OPERATION = 15, VMXERR_VMENTRY_INVALID_EXECUTIVE_VMCS = 16, VMXERR_VMENTRY_NON_LAUNCHED_EXECUTIVE_VMCS = 17, VMXERR_VMENTRY_NOT_VMXON_EXECUTIVE_VMCS = 18, VMXERR_VMCALL_NON_CLEAR_VMCS = 19, VMXERR_VMCALL_INVALID_VMEXIT_FIELD = 20, VMXERR_RESERVED21 = 21, VMXERR_VMCALL_INVALID_MSEG_REVISION_ID = 22, VMXERR_VMXOFF_WITH_CONFIGURED_SMM_MONITOR = 23, VMXERR_VMCALL_WITH_INVALID_SMM_MONITOR_FEATURES = 24, VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD_IN_EXECUTIVE_VMCS = 25, VMXERR_VMENTRY_MOV_SS_BLOCKING = 26, VMXERR_RESERVED27 = 27, VMXERR_INVALID_INVEPT_INVVPID = 28 }; enum VMX_vmexit_reason { VMX_VMEXIT_EXCEPTION_NMI = 0, VMX_VMEXIT_EXTERNAL_INTERRUPT = 1, VMX_VMEXIT_TRIPLE_FAULT = 2, VMX_VMEXIT_INIT = 3, VMX_VMEXIT_SIPI = 4, VMX_VMEXIT_IO_SMI = 5, VMX_VMEXIT_SMI = 6, VMX_VMEXIT_INTERRUPT_WINDOW = 7, VMX_VMEXIT_NMI_WINDOW = 8, VMX_VMEXIT_TASK_SWITCH = 9, VMX_VMEXIT_CPUID = 10, VMX_VMEXIT_GETSEC = 11, VMX_VMEXIT_HLT = 12, VMX_VMEXIT_INVD = 13, VMX_VMEXIT_INVLPG = 14, VMX_VMEXIT_RDPMC = 15, VMX_VMEXIT_RDTSC = 16, VMX_VMEXIT_RSM = 17, VMX_VMEXIT_VMCALL = 18, VMX_VMEXIT_VMCLEAR = 19, VMX_VMEXIT_VMLAUNCH = 20, VMX_VMEXIT_VMPTRLD = 21, VMX_VMEXIT_VMPTRST = 22, VMX_VMEXIT_VMREAD = 23, VMX_VMEXIT_VMRESUME = 24, VMX_VMEXIT_VMWRITE = 25, VMX_VMEXIT_VMXOFF = 26, VMX_VMEXIT_VMXON = 27, VMX_VMEXIT_CR_ACCESS = 28, VMX_VMEXIT_DR_ACCESS = 29, VMX_VMEXIT_IO_INSTRUCTION = 30, VMX_VMEXIT_RDMSR = 31, VMX_VMEXIT_WRMSR = 32, VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE = 33, VMX_VMEXIT_VMENTRY_FAILURE_MSR = 34, VMX_VMEXIT_RESERVED35 = 35, VMX_VMEXIT_MWAIT = 36, VMX_VMEXIT_MONITOR_TRAP_FLAG = 37, VMX_VMEXIT_RESERVED38 = 38, VMX_VMEXIT_MONITOR = 39, VMX_VMEXIT_PAUSE = 40, VMX_VMEXIT_VMENTRY_FAILURE_MCA = 41, // will never happen in Bochs VMX_VMEXIT_RESERVED42 = 42, VMX_VMEXIT_TPR_THRESHOLD = 43, VMX_VMEXIT_APIC_ACCESS = 44, VMX_VMEXIT_VIRTUALIZED_EOI = 45, VMX_VMEXIT_GDTR_IDTR_ACCESS = 46, VMX_VMEXIT_LDTR_TR_ACCESS = 47, VMX_VMEXIT_EPT_VIOLATION = 48, VMX_VMEXIT_EPT_MISCONFIGURATION = 49, VMX_VMEXIT_INVEPT = 50, VMX_VMEXIT_RDTSCP = 51, VMX_VMEXIT_VMX_PREEMPTION_TIMER_EXPIRED = 52, VMX_VMEXIT_INVVPID = 53, VMX_VMEXIT_WBINVD = 54, VMX_VMEXIT_XSETBV = 55, VMX_VMEXIT_APIC_WRITE = 56, VMX_VMEXIT_RDRAND = 57, VMX_VMEXIT_INVPCID = 58, VMX_VMEXIT_VMFUNC = 59, VMX_VMEXIT_RESERVED60 = 60, VMX_VMEXIT_RDSEED = 61 }; // VMexit on CR register access enum { VMX_VMEXIT_CR_ACCESS_CR_WRITE = 0, VMX_VMEXIT_CR_ACCESS_CR_READ, VMX_VMEXIT_CR_ACCESS_CLTS, VMX_VMEXIT_CR_ACCESS_LMSW }; // VMENTRY error on loading guest state qualification enum VMX_vmentry_error { VMENTER_ERR_NO_ERROR = 0, VMENTER_ERR_GUEST_STATE_PDPTR_LOADING = 2, VMENTER_ERR_GUEST_STATE_INJECT_NMI_BLOCKING_EVENTS = 3, VMENTER_ERR_GUEST_STATE_LINK_POINTER = 4 }; // VMABORT error code enum VMX_vmabort_code { VMABORT_SAVING_GUEST_MSRS_FAILURE, VMABORT_HOST_PDPTR_CORRUPTED, VMABORT_VMEXIT_VMCS_CORRUPTED, VMABORT_LOADING_HOST_MSRS, VMABORT_VMEXIT_MACHINE_CHECK_ERROR }; // VMX APIC ACCESS VMEXIT qualification #define VMX_APIC_READ_INSTRUCTION_EXECUTION 0x0000 #define VMX_APIC_WRITE_INSTRUCTION_EXECUTION 0x1000 #define VMX_APIC_INSTRUCTION_FETCH 0x2000 /* won't happen because cpu::prefetch will crash */ #define VMX_APIC_ACCESS_DURING_EVENT_DELIVERY 0x3000 // VM Functions List enum VMFunctions { VMX_VMFUNC_EPTP_SWITCHING = 0 }; #define VMX_VMFUNC_EPTP_SWITCHING_MASK (BX_CONST64(1) << VMX_VMFUNC_EPTP_SWITCHING) // ============= // VMCS fields // ============= /* VMCS 16-bit control fields */ /* binary 0000_00xx_xxxx_xxx0 */ #define VMCS_16BIT_CONTROL_VPID 0x00000000 /* VPID */ #define VMCS_16BIT_CONTROL_POSTED_INTERRUPT_VECTOR 0x00000002 /* Posted Interrupts */ /* VMCS 16-bit guest-state fields */ /* binary 0000_10xx_xxxx_xxx0 */ #define VMCS_16BIT_GUEST_ES_SELECTOR 0x00000800 #define VMCS_16BIT_GUEST_CS_SELECTOR 0x00000802 #define VMCS_16BIT_GUEST_SS_SELECTOR 0x00000804 #define VMCS_16BIT_GUEST_DS_SELECTOR 0x00000806 #define VMCS_16BIT_GUEST_FS_SELECTOR 0x00000808 #define VMCS_16BIT_GUEST_GS_SELECTOR 0x0000080A #define VMCS_16BIT_GUEST_LDTR_SELECTOR 0x0000080C #define VMCS_16BIT_GUEST_TR_SELECTOR 0x0000080E #define VMCS_16BIT_GUEST_INTERRUPT_STATUS 0x00000810 /* Virtual Interrupt Delivery */ /* VMCS 16-bit host-state fields */ /* binary 0000_11xx_xxxx_xxx0 */ #define VMCS_16BIT_HOST_ES_SELECTOR 0x00000C00 #define VMCS_16BIT_HOST_CS_SELECTOR 0x00000C02 #define VMCS_16BIT_HOST_SS_SELECTOR 0x00000C04 #define VMCS_16BIT_HOST_DS_SELECTOR 0x00000C06 #define VMCS_16BIT_HOST_FS_SELECTOR 0x00000C08 #define VMCS_16BIT_HOST_GS_SELECTOR 0x00000C0A #define VMCS_16BIT_HOST_TR_SELECTOR 0x00000C0C /* VMCS 64-bit control fields */ /* binary 0010_00xx_xxxx_xxx0 */ #define VMCS_64BIT_CONTROL_IO_BITMAP_A 0x00002000 #define VMCS_64BIT_CONTROL_IO_BITMAP_A_HI 0x00002001 #define VMCS_64BIT_CONTROL_IO_BITMAP_B 0x00002002 #define VMCS_64BIT_CONTROL_IO_BITMAP_B_HI 0x00002003 #define VMCS_64BIT_CONTROL_MSR_BITMAPS 0x00002004 #define VMCS_64BIT_CONTROL_MSR_BITMAPS_HI 0x00002005 #define VMCS_64BIT_CONTROL_VMEXIT_MSR_STORE_ADDR 0x00002006 #define VMCS_64BIT_CONTROL_VMEXIT_MSR_STORE_ADDR_HI 0x00002007 #define VMCS_64BIT_CONTROL_VMEXIT_MSR_LOAD_ADDR 0x00002008 #define VMCS_64BIT_CONTROL_VMEXIT_MSR_LOAD_ADDR_HI 0x00002009 #define VMCS_64BIT_CONTROL_VMENTRY_MSR_LOAD_ADDR 0x0000200A #define VMCS_64BIT_CONTROL_VMENTRY_MSR_LOAD_ADDR_HI 0x0000200B #define VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR 0x0000200C #define VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR_HI 0x0000200D #define VMCS_64BIT_CONTROL_TSC_OFFSET 0x00002010 #define VMCS_64BIT_CONTROL_TSC_OFFSET_HI 0x00002011 #define VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR 0x00002012 /* TPR shadow */ #define VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR_HI 0x00002013 #define VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR 0x00002014 /* APIC virtualization */ #define VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR_HI 0x00002015 #define VMCS_64BIT_CONTROL_POSTED_INTERRUPT_DESC_ADDR 0x00002016 /* Posted Interrupts */ #define VMCS_64BIT_CONTROL_POSTED_INTERRUPT_DESC_ADDR_HI 0x00002017 #define VMCS_64BIT_CONTROL_VMFUNC_CTRLS 0x00002018 /* VM Functions */ #define VMCS_64BIT_CONTROL_VMFUNC_CTRLS_HI 0x00002019 #define VMCS_64BIT_CONTROL_EPTPTR 0x0000201A /* EPT */ #define VMCS_64BIT_CONTROL_EPTPTR_HI 0x0000201B #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP0 0x0000201C /* Virtual Interrupt Delivery */ #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP0_HI 0x0000201D #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP1 0x0000201E #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP1_HI 0x0000201F #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP2 0x00002020 #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP2_HI 0x00002021 #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP3 0x00002022 #define VMCS_64BIT_CONTROL_EOI_EXIT_BITMAP3_HI 0x00002023 #define VMCS_64BIT_CONTROL_EPTP_LIST_ADDRESS 0x00002024 /* VM Functions - EPTP switching */ #define VMCS_64BIT_CONTROL_EPTP_LIST_ADDRESS_HI 0x00002025 /* VMCS 64-bit read only data fields */ /* binary 0010_01xx_xxxx_xxx0 */ #define VMCS_64BIT_GUEST_PHYSICAL_ADDR 0x00002400 /* EPT */ #define VMCS_64BIT_GUEST_PHYSICAL_ADDR_HI 0x00002401 /* VMCS 64-bit guest state fields */ /* binary 0010_10xx_xxxx_xxx0 */ #define VMCS_64BIT_GUEST_LINK_POINTER 0x00002800 #define VMCS_64BIT_GUEST_LINK_POINTER_HI 0x00002801 #define VMCS_64BIT_GUEST_IA32_DEBUGCTL 0x00002802 #define VMCS_64BIT_GUEST_IA32_DEBUGCTL_HI 0x00002803 #define VMCS_64BIT_GUEST_IA32_PAT 0x00002804 /* PAT */ #define VMCS_64BIT_GUEST_IA32_PAT_HI 0x00002805 #define VMCS_64BIT_GUEST_IA32_EFER 0x00002806 /* EFER */ #define VMCS_64BIT_GUEST_IA32_EFER_HI 0x00002807 #define VMCS_64BIT_GUEST_IA32_PERF_GLOBAL_CTRL 0x00002808 /* Perf Global Ctrl */ #define VMCS_64BIT_GUEST_IA32_PERF_GLOBAL_CTRL_HI 0x00002809 #define VMCS_64BIT_GUEST_IA32_PDPTE0 0x0000280A /* EPT */ #define VMCS_64BIT_GUEST_IA32_PDPTE0_HI 0x0000280B #define VMCS_64BIT_GUEST_IA32_PDPTE1 0x0000280C #define VMCS_64BIT_GUEST_IA32_PDPTE1_HI 0x0000280D #define VMCS_64BIT_GUEST_IA32_PDPTE2 0x0000280E #define VMCS_64BIT_GUEST_IA32_PDPTE2_HI 0x0000280F #define VMCS_64BIT_GUEST_IA32_PDPTE3 0x00002810 #define VMCS_64BIT_GUEST_IA32_PDPTE3_HI 0x00002811 /* VMCS 64-bit host state fields */ /* binary 0010_11xx_xxxx_xxx0 */ #define VMCS_64BIT_HOST_IA32_PAT 0x00002C00 /* PAT */ #define VMCS_64BIT_HOST_IA32_PAT_HI 0x00002C01 #define VMCS_64BIT_HOST_IA32_EFER 0x00002C02 /* EFER */ #define VMCS_64BIT_HOST_IA32_EFER_HI 0x00002C03 #define VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL 0x00002C04 /* Perf Global Ctrl */ #define VMCS_64BIT_HOST_IA32_PERF_GLOBAL_CTRL_HI 0x00002C05 /* VMCS 32_bit control fields */ /* binary 0100_00xx_xxxx_xxx0 */ #define VMCS_32BIT_CONTROL_PIN_BASED_EXEC_CONTROLS 0x00004000 #define VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS 0x00004002 #define VMCS_32BIT_CONTROL_EXECUTION_BITMAP 0x00004004 #define VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MASK 0x00004006 #define VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MATCH 0x00004008 #define VMCS_32BIT_CONTROL_CR3_TARGET_COUNT 0x0000400A #define VMCS_32BIT_CONTROL_VMEXIT_CONTROLS 0x0000400C #define VMCS_32BIT_CONTROL_VMEXIT_MSR_STORE_COUNT 0x0000400E #define VMCS_32BIT_CONTROL_VMEXIT_MSR_LOAD_COUNT 0x00004010 #define VMCS_32BIT_CONTROL_VMENTRY_CONTROLS 0x00004012 #define VMCS_32BIT_CONTROL_VMENTRY_MSR_LOAD_COUNT 0x00004014 #define VMCS_32BIT_CONTROL_VMENTRY_INTERRUPTION_INFO 0x00004016 #define VMCS_32BIT_CONTROL_VMENTRY_EXCEPTION_ERR_CODE 0x00004018 #define VMCS_32BIT_CONTROL_VMENTRY_INSTRUCTION_LENGTH 0x0000401A #define VMCS_32BIT_CONTROL_TPR_THRESHOLD 0x0000401C /* TPR shadow */ #define VMCS_32BIT_CONTROL_SECONDARY_VMEXEC_CONTROLS 0x0000401E #define VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_GAP 0x00004020 /* PAUSE loop exiting */ #define VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_WINDOW 0x00004022 /* PAUSE loop exiting */ /* VMCS 32-bit read only data fields */ /* binary 0100_01xx_xxxx_xxx0 */ #define VMCS_32BIT_INSTRUCTION_ERROR 0x00004400 #define VMCS_32BIT_VMEXIT_REASON 0x00004402 #define VMCS_32BIT_VMEXIT_INTERRUPTION_INFO 0x00004404 #define VMCS_32BIT_VMEXIT_INTERRUPTION_ERR_CODE 0x00004406 #define VMCS_32BIT_IDT_VECTORING_INFO 0x00004408 #define VMCS_32BIT_IDT_VECTORING_ERR_CODE 0x0000440A #define VMCS_32BIT_VMEXIT_INSTRUCTION_LENGTH 0x0000440C #define VMCS_32BIT_VMEXIT_INSTRUCTION_INFO 0x0000440E /* VMCS 32-bit guest-state fields */ /* binary 0100_10xx_xxxx_xxx0 */ #define VMCS_32BIT_GUEST_ES_LIMIT 0x00004800 #define VMCS_32BIT_GUEST_CS_LIMIT 0x00004802 #define VMCS_32BIT_GUEST_SS_LIMIT 0x00004804 #define VMCS_32BIT_GUEST_DS_LIMIT 0x00004806 #define VMCS_32BIT_GUEST_FS_LIMIT 0x00004808 #define VMCS_32BIT_GUEST_GS_LIMIT 0x0000480A #define VMCS_32BIT_GUEST_LDTR_LIMIT 0x0000480C #define VMCS_32BIT_GUEST_TR_LIMIT 0x0000480E #define VMCS_32BIT_GUEST_GDTR_LIMIT 0x00004810 #define VMCS_32BIT_GUEST_IDTR_LIMIT 0x00004812 #define VMCS_32BIT_GUEST_ES_ACCESS_RIGHTS 0x00004814 #define VMCS_32BIT_GUEST_CS_ACCESS_RIGHTS 0x00004816 #define VMCS_32BIT_GUEST_SS_ACCESS_RIGHTS 0x00004818 #define VMCS_32BIT_GUEST_DS_ACCESS_RIGHTS 0x0000481A #define VMCS_32BIT_GUEST_FS_ACCESS_RIGHTS 0x0000481C #define VMCS_32BIT_GUEST_GS_ACCESS_RIGHTS 0x0000481E #define VMCS_32BIT_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 #define VMCS_32BIT_GUEST_TR_ACCESS_RIGHTS 0x00004822 #define VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE 0x00004824 #define VMCS_32BIT_GUEST_ACTIVITY_STATE 0x00004826 #define VMCS_32BIT_GUEST_SMBASE 0x00004828 #define VMCS_32BIT_GUEST_IA32_SYSENTER_CS_MSR 0x0000482A #define VMCS_32BIT_GUEST_PREEMPTION_TIMER_VALUE 0x0000482E /* VMX preemption timer */ /* VMCS 32-bit host-state fields */ /* binary 0100_11xx_xxxx_xxx0 */ #define VMCS_32BIT_HOST_IA32_SYSENTER_CS_MSR 0x00004C00 /* VMCS natural width control fields */ /* binary 0110_00xx_xxxx_xxx0 */ #define VMCS_CONTROL_CR0_GUEST_HOST_MASK 0x00006000 #define VMCS_CONTROL_CR4_GUEST_HOST_MASK 0x00006002 #define VMCS_CONTROL_CR0_READ_SHADOW 0x00006004 #define VMCS_CONTROL_CR4_READ_SHADOW 0x00006006 #define VMCS_CR3_TARGET0 0x00006008 #define VMCS_CR3_TARGET1 0x0000600A #define VMCS_CR3_TARGET2 0x0000600C #define VMCS_CR3_TARGET3 0x0000600E /* VMCS natural width read only data fields */ /* binary 0110_01xx_xxxx_xxx0 */ #define VMCS_VMEXIT_QUALIFICATION 0x00006400 #define VMCS_IO_RCX 0x00006402 #define VMCS_IO_RSI 0x00006404 #define VMCS_IO_RDI 0x00006406 #define VMCS_IO_RIP 0x00006408 #define VMCS_GUEST_LINEAR_ADDR 0x0000640A /* VMCS natural width guest state fields */ /* binary 0110_10xx_xxxx_xxx0 */ #define VMCS_GUEST_CR0 0x00006800 #define VMCS_GUEST_CR3 0x00006802 #define VMCS_GUEST_CR4 0x00006804 #define VMCS_GUEST_ES_BASE 0x00006806 #define VMCS_GUEST_CS_BASE 0x00006808 #define VMCS_GUEST_SS_BASE 0x0000680A #define VMCS_GUEST_DS_BASE 0x0000680C #define VMCS_GUEST_FS_BASE 0x0000680E #define VMCS_GUEST_GS_BASE 0x00006810 #define VMCS_GUEST_LDTR_BASE 0x00006812 #define VMCS_GUEST_TR_BASE 0x00006814 #define VMCS_GUEST_GDTR_BASE 0x00006816 #define VMCS_GUEST_IDTR_BASE 0x00006818 #define VMCS_GUEST_DR7 0x0000681A #define VMCS_GUEST_RSP 0x0000681C #define VMCS_GUEST_RIP 0x0000681E #define VMCS_GUEST_RFLAGS 0x00006820 #define VMCS_GUEST_PENDING_DBG_EXCEPTIONS 0x00006822 #define VMCS_GUEST_IA32_SYSENTER_ESP_MSR 0x00006824 #define VMCS_GUEST_IA32_SYSENTER_EIP_MSR 0x00006826 /* VMCS natural width host state fields */ /* binary 0110_11xx_xxxx_xxx0 */ #define VMCS_HOST_CR0 0x00006C00 #define VMCS_HOST_CR3 0x00006C02 #define VMCS_HOST_CR4 0x00006C04 #define VMCS_HOST_FS_BASE 0x00006C06 #define VMCS_HOST_GS_BASE 0x00006C08 #define VMCS_HOST_TR_BASE 0x00006C0A #define VMCS_HOST_GDTR_BASE 0x00006C0C #define VMCS_HOST_IDTR_BASE 0x00006C0E #define VMCS_HOST_IA32_SYSENTER_ESP_MSR 0x00006C10 #define VMCS_HOST_IA32_SYSENTER_EIP_MSR 0x00006C12 #define VMCS_HOST_RSP 0x00006C14 #define VMCS_HOST_RIP 0x00006C16 #define VMX_HIGHEST_VMCS_ENCODING (0x30) // =============================== // VMCS fields encoding/decoding // =============================== // extract VMCS field using its encoding #define VMCS_FIELD(encoding) ((encoding) & 0x3ff) // check if the VMCS field encoding corresponding to HI part of 64-bit value #define IS_VMCS_FIELD_HI(encoding) ((encoding) & 1) // bits 11:10 of VMCS field encoding indicate field's type #define VMCS_FIELD_TYPE(encoding) (((encoding) >> 10) & 3) #define VMCS_FIELD_TYPE_CONTROL 0x0 #define VMCS_FIELD_TYPE_READ_ONLY 0x1 #define VMCS_FIELD_TYPE_GUEST_STATE 0x2 #define VMCS_FIELD_TYPE_HOST_STATE 0x3 // bits 14:13 of VMCS field encoding indicate field's width #define VMCS_FIELD_WIDTH(encoding) (((encoding) >> 13) & 3) #define VMCS_FIELD_WIDTH_16BIT 0x0 #define VMCS_FIELD_WIDTH_64BIT 0x1 #define VMCS_FIELD_WIDTH_32BIT 0x2 #define VMCS_FIELD_WIDTH_NATURAL_WIDTH 0x3 #define VMCS_FIELD_INDEX(encoding) \ ((VMCS_FIELD_WIDTH(encoding) << 2) + VMCS_FIELD_TYPE(encoding)) // ============= // VMCS layout // ============= #define VMCS_REVISION_ID_FIELD_ADDR (0x0000) #define VMCS_VMX_ABORT_FIELD_ADDR (0x0004) #define VMCS_LAUNCH_STATE_FIELD_ADDR (0x0008) // invent Bochs CPU VMCS layout - allocate 64 fields of each type #define VMCS_DATA_OFFSET (0x0010) #if ((VMCS_DATA_OFFSET + 4*(64*15 + VMX_HIGHEST_VMCS_ENCODING)) > VMX_VMCS_AREA_SIZE) #error "VMCS area size exceeded !" #endif // ============= // VMCS state // ============= enum VMX_state { VMCS_STATE_CLEAR = 0, VMCS_STATE_LAUNCHED }; // ================ // VMCS structure // ================ typedef struct bx_VMCS_GUEST_STATE { bx_address cr0; bx_address cr3; bx_address cr4; bx_address dr7; bx_address rip; bx_address rsp; bx_address rflags; bx_segment_reg_t sregs[6]; bx_global_segment_reg_t gdtr; bx_global_segment_reg_t idtr; bx_segment_reg_t ldtr; bx_segment_reg_t tr; Bit64u ia32_debugctl_msr; bx_address sysenter_esp_msr; bx_address sysenter_eip_msr; Bit32u sysenter_cs_msr; Bit32u smbase; Bit32u activity_state; Bit32u interruptibility_state; Bit32u tmpDR6; Bit64u link_pointer; #if BX_SUPPORT_VMX >= 2 #if BX_SUPPORT_X86_64 Bit64u efer_msr; #endif Bit64u pat_msr; Bit64u pdptr[4]; #endif } VMCS_GUEST_STATE; typedef struct bx_VMCS_HOST_STATE { bx_address cr0; bx_address cr3; bx_address cr4; Bit16u segreg_selector[6]; bx_address fs_base; bx_address gs_base; bx_address gdtr_base; bx_address idtr_base; Bit32u tr_selector; bx_address tr_base; bx_address rsp; bx_address rip; bx_address sysenter_esp_msr; bx_address sysenter_eip_msr; Bit32u sysenter_cs_msr; #if BX_SUPPORT_VMX >= 2 #if BX_SUPPORT_X86_64 Bit64u efer_msr; #endif Bit64u pat_msr; #endif } VMCS_HOST_STATE; typedef struct bx_VMX_Cap { // // VMX Capabilities // Bit32u vmx_pin_vmexec_ctrl_supported_bits; Bit32u vmx_proc_vmexec_ctrl_supported_bits; Bit32u vmx_vmexec_ctrl2_supported_bits; Bit32u vmx_vmexit_ctrl_supported_bits; Bit32u vmx_vmentry_ctrl_supported_bits; #if BX_SUPPORT_VMX >= 2 Bit64u vmx_ept_vpid_cap_supported_bits; Bit64u vmx_vmfunc_supported_bits; #endif } VMX_CAP; typedef struct bx_VMCS { // // VM-Execution Control Fields // #define VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT (1 << 0) #define VMX_VM_EXEC_CTRL1_NMI_VMEXIT (1 << 3) #define VMX_VM_EXEC_CTRL1_VIRTUAL_NMI (1 << 5) /* Virtual NMI */ #define VMX_VM_EXEC_CTRL1_VMX_PREEMPTION_TIMER_VMEXIT (1 << 6) /* VMX preemption timer */ #define VMX_VM_EXEC_CTRL1_PROCESS_POSTED_INTERRUPTS (1 << 7) /* Posted Interrupts */ #define VMX_VM_EXEC_CTRL1_SUPPORTED_BITS \ (BX_CPU_THIS_PTR vmx_cap.vmx_pin_vmexec_ctrl_supported_bits) Bit32u vmexec_ctrls1; #define VMX_VM_EXEC_CTRL2_INTERRUPT_WINDOW_VMEXIT (1 << 2) #define VMX_VM_EXEC_CTRL2_TSC_OFFSET (1 << 3) #define VMX_VM_EXEC_CTRL2_HLT_VMEXIT (1 << 7) #define VMX_VM_EXEC_CTRL2_INVLPG_VMEXIT (1 << 9) #define VMX_VM_EXEC_CTRL2_MWAIT_VMEXIT (1 << 10) #define VMX_VM_EXEC_CTRL2_RDPMC_VMEXIT (1 << 11) #define VMX_VM_EXEC_CTRL2_RDTSC_VMEXIT (1 << 12) #define VMX_VM_EXEC_CTRL2_CR3_WRITE_VMEXIT (1 << 15) /* legacy must be '1 */ #define VMX_VM_EXEC_CTRL2_CR3_READ_VMEXIT (1 << 16) /* legacy must be '1 */ #define VMX_VM_EXEC_CTRL2_CR8_WRITE_VMEXIT (1 << 19) /* TPR shadow */ #define VMX_VM_EXEC_CTRL2_CR8_READ_VMEXIT (1 << 20) /* TPR shadow */ #define VMX_VM_EXEC_CTRL2_TPR_SHADOW (1 << 21) /* TPR shadow */ #define VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT (1 << 22) /* Virtual NMI */ #define VMX_VM_EXEC_CTRL2_DRx_ACCESS_VMEXIT (1 << 23) #define VMX_VM_EXEC_CTRL2_IO_VMEXIT (1 << 24) #define VMX_VM_EXEC_CTRL2_IO_BITMAPS (1 << 25) #define VMX_VM_EXEC_CTRL2_MONITOR_TRAP_FLAG (1 << 27) /* Monitor Trap Flag */ #define VMX_VM_EXEC_CTRL2_MSR_BITMAPS (1 << 28) #define VMX_VM_EXEC_CTRL2_MONITOR_VMEXIT (1 << 29) #define VMX_VM_EXEC_CTRL2_PAUSE_VMEXIT (1 << 30) #define VMX_VM_EXEC_CTRL2_SECONDARY_CONTROLS (1 << 31) #define VMX_VM_EXEC_CTRL2_SUPPORTED_BITS \ (BX_CPU_THIS_PTR vmx_cap.vmx_proc_vmexec_ctrl_supported_bits) Bit32u vmexec_ctrls2; #define VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES (1 << 0) /* APIC virtualization */ #define VMX_VM_EXEC_CTRL3_EPT_ENABLE (1 << 1) /* EPT */ #define VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT (1 << 2) /* Descriptor Table VMEXIT */ #define VMX_VM_EXEC_CTRL3_RDTSCP (1 << 3) #define VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE (1 << 4) /* Virtualize X2APIC */ #define VMX_VM_EXEC_CTRL3_VPID_ENABLE (1 << 5) /* VPID */ #define VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT (1 << 6) /* WBINVD VMEXIT */ #define VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST (1 << 7) /* Unrestricted Guest */ #define VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_REGISTERS (1 << 8) #define VMX_VM_EXEC_CTRL3_VIRTUAL_INT_DELIVERY (1 << 9) #define VMX_VM_EXEC_CTRL3_PAUSE_LOOP_VMEXIT (1 << 10) /* PAUSE loop exiting */ #define VMX_VM_EXEC_CTRL3_RDRAND_VMEXIT (1 << 11) #define VMX_VM_EXEC_CTRL3_INVPCID (1 << 12) #define VMX_VM_EXEC_CTRL3_VMFUNC_ENABLE (1 << 13) /* VM Functions */ #define VMX_VM_EXEC_CTRL3_RDSEED_VMEXIT (1 << 16) #define VMX_VM_EXEC_CTRL3_SUPPORTED_BITS \ (BX_CPU_THIS_PTR vmx_cap.vmx_vmexec_ctrl2_supported_bits) Bit32u vmexec_ctrls3; Bit32u vm_exceptions_bitmap; Bit32u vm_pf_mask; Bit32u vm_pf_match; Bit64u io_bitmap_addr[2]; Bit64u tsc_offset; bx_phy_address msr_bitmap_addr; bx_address vm_cr0_mask; bx_address vm_cr0_read_shadow; bx_address vm_cr4_mask; bx_address vm_cr4_read_shadow; #define VMX_CR3_TARGET_MAX_CNT 4 Bit32u vm_cr3_target_cnt; bx_address vm_cr3_target_value[VMX_CR3_TARGET_MAX_CNT]; #if BX_SUPPORT_X86_64 bx_phy_address virtual_apic_page_addr; Bit32u vm_tpr_threshold; bx_phy_address apic_access_page; #endif #if BX_SUPPORT_VMX >= 2 Bit64u eptptr; Bit16u vpid; #endif Bit64u executive_vmcsptr; #if BX_SUPPORT_VMX >= 2 Bit32u pause_loop_exiting_gap; Bit32u pause_loop_exiting_window; Bit64u last_pause_time; // used for pause loop exiting Bit32u first_pause_time; #endif // // VM-Exit Control Fields // #define VMX_VMEXIT_CTRL1_SAVE_DBG_CTRLS (1 << 2) /* legacy must be '1 */ #define VMX_VMEXIT_CTRL1_HOST_ADDR_SPACE_SIZE (1 << 9) #define VMX_VMEXIT_CTRL1_LOAD_PERF_GLOBAL_CTRL_MSR (1 << 12) /* Perf Global Control */ #define VMX_VMEXIT_CTRL1_INTA_ON_VMEXIT (1 << 15) #define VMX_VMEXIT_CTRL1_STORE_PAT_MSR (1 << 18) /* PAT */ #define VMX_VMEXIT_CTRL1_LOAD_PAT_MSR (1 << 19) /* PAT */ #define VMX_VMEXIT_CTRL1_STORE_EFER_MSR (1 << 20) /* EFER */ #define VMX_VMEXIT_CTRL1_LOAD_EFER_MSR (1 << 21) /* EFER */ #define VMX_VMEXIT_CTRL1_STORE_VMX_PREEMPTION_TIMER (1 << 22) /* VMX preemption timer */ #define VMX_VMEXIT_CTRL1_SUPPORTED_BITS \ (BX_CPU_THIS_PTR vmx_cap.vmx_vmexit_ctrl_supported_bits) Bit32u vmexit_ctrls; Bit32u vmexit_msr_store_cnt; bx_phy_address vmexit_msr_store_addr; Bit32u vmexit_msr_load_cnt; bx_phy_address vmexit_msr_load_addr; // // VM-Entry Control Fields // #define VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS (1 << 2) /* legacy must be '1 */ #define VMX_VMENTRY_CTRL1_X86_64_GUEST (1 << 9) #define VMX_VMENTRY_CTRL1_SMM_ENTER (1 << 10) #define VMX_VMENTRY_CTRL1_DEACTIVATE_DUAL_MONITOR_TREATMENT (1 << 11) #define VMX_VMENTRY_CTRL1_LOAD_PERF_GLOBAL_CTRL_MSR (1 << 13) /* Perf Global Ctrl */ #define VMX_VMENTRY_CTRL1_LOAD_PAT_MSR (1 << 14) /* PAT */ #define VMX_VMENTRY_CTRL1_LOAD_EFER_MSR (1 << 15) /* EFER */ #define VMX_VMENTRY_CTRL1_SUPPORTED_BITS \ (BX_CPU_THIS_PTR vmx_cap.vmx_vmentry_ctrl_supported_bits) Bit32u vmentry_ctrls; Bit32u vmentry_msr_load_cnt; bx_phy_address vmentry_msr_load_addr; Bit32u vmentry_interr_info; Bit32u vmentry_excep_err_code; Bit32u vmentry_instr_length; // // VM Functions // #if BX_SUPPORT_VMX >= 2 #define VMX_VMFUNC_CTRL1_SUPPORTED_BITS \ (BX_CPU_THIS_PTR vmx_cap.vmx_vmfunc_supported_bits) Bit64u vmfunc_ctrls; Bit64u eptp_list_address; #endif // // VMCS Hidden and Read-Only Fields // Bit32u idt_vector_info; Bit32u idt_vector_error_code; // // VMCS Host State // VMCS_HOST_STATE host_state; } VMCS_CACHE; enum VMX_Activity_State { BX_VMX_ACTIVE_STATE = 0, BX_VMX_STATE_HLT, BX_VMX_STATE_SHUTDOWN, BX_VMX_STATE_WAIT_FOR_SIPI, BX_VMX_LAST_ACTIVITY_STATE }; #define PIN_VMEXIT(ctrl) (BX_CPU_THIS_PTR vmcs.vmexec_ctrls1 & (ctrl)) #define VMEXIT(ctrl) (BX_CPU_THIS_PTR vmcs.vmexec_ctrls2 & (ctrl)) #define SECONDARY_VMEXEC_CONTROL(ctrl) (BX_CPU_THIS_PTR vmcs.vmexec_ctrls3 & (ctrl)) #define BX_VMX_INTERRUPTS_BLOCKED_BY_STI (1 << 0) #define BX_VMX_INTERRUPTS_BLOCKED_BY_MOV_SS (1 << 1) #define BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED (1 << 2) #define BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED (1 << 3) #define BX_VMX_INTERRUPTIBILITY_STATE_MASK \ (BX_VMX_INTERRUPTS_BLOCKED_BY_STI | BX_VMX_INTERRUPTS_BLOCKED_BY_MOV_SS | \ BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED | \ BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED) // // IA32_VMX_BASIC MSR (0x480) // -------------- // // 31:00 32-bit VMCS revision id // 32:47 VMCS region size, 0 <= size <= 4096 // 48:48 use 32-bit physical address, set when x86_64 disabled // 49:49 support of dual-monitor treatment of SMI and SMM // 53:50 memory type used for VMCS access // 54:54 logical processor reports information in the VM-exit // instruction-information field on VM exits due to // execution of INS/OUTS // 55:55 set if any VMX controls that default to `1 may be // cleared to `0, also indicates that IA32_VMX_TRUE_PINBASED_CTLS, // IA32_VMX_TRUE_PROCBASED_CTLS, IA32_VMX_TRUE_EXIT_CTLS and // IA32_VMX_TRUE_ENTRY_CTLS MSRs are supported. // 56:63 reserved, must be zero // #define VMX_MSR_VMX_BASIC_LO (VMX_VMCS_REVISION_ID) #define VMX_MSR_VMX_BASIC_HI \ (VMX_VMCS_AREA_SIZE | ((!bx_cpuid_support_x86_64()) << 16) | \ (BX_MEMTYPE_WB << 18) | (1<<22)) | ((BX_SUPPORT_VMX >= 2) ? (1<<23) : 0) #define VMX_MSR_VMX_BASIC \ ((((Bit64u) VMX_MSR_VMX_BASIC_HI) << 32) | VMX_MSR_VMX_BASIC_LO) // ------------------------------------------------------------------------ // reserved bit (must be '1) settings for VMX MSRs // ------------------------------------------------------------------------ // ----------------------------------------- // 3322|2222|2222|1111|1111|11 | | // 1098|7654|3210|9876|5432|1098|7654|3210 // ----------------------------------------- // ----.----.----.----.----.----.---1.-11- MSR (0x481) IA32_MSR_VMX_PINBASED_CTRLS // ----.-1--.----.---1.111-.---1.-111.--1- MSR (0x482) IA32_MSR_VMX_PROCBASED_CTRLS // ----.----.----.--11.-11-.11-1.1111.1111 MSR (0x483) IA32_MSR_VMX_VMEXIT_CTRLS // ----.----.----.----.---1.---1.1111.1111 MSR (0x484) IA32_MSR_VMX_VMENTRY_CTRLS // // IA32_MSR_VMX_PINBASED_CTRLS MSR (0x481) // --------------------------- // Bits 1, 2 and 4 must be '1 // Allowed 0-settings: VMentry fail if a bit is '0 in pin-based vmexec controls // but set to '1 in this MSR #define VMX_MSR_VMX_PINBASED_CTRLS_LO (0x00000016) // Allowed 1-settings: VMentry fail if a bit is '1 in pin-based vmexec controls // but set to '0 in this MSR. #define VMX_MSR_VMX_PINBASED_CTRLS_HI \ (VMX_VM_EXEC_CTRL1_SUPPORTED_BITS | VMX_MSR_VMX_PINBASED_CTRLS_LO) #define VMX_MSR_VMX_PINBASED_CTRLS \ ((((Bit64u) VMX_MSR_VMX_PINBASED_CTRLS_HI) << 32) | VMX_MSR_VMX_PINBASED_CTRLS_LO) // IA32_MSR_VMX_TRUE_PINBASED_CTRLS MSR (0x48d) // -------------------------------- // no changes from original IA32_MSR_VMX_PINBASED_CTRLS #define VMX_MSR_VMX_TRUE_PINBASED_CTRLS_LO (VMX_MSR_VMX_PINBASED_CTRLS_LO) #define VMX_MSR_VMX_TRUE_PINBASED_CTRLS_HI (VMX_MSR_VMX_PINBASED_CTRLS_HI) #define VMX_MSR_VMX_TRUE_PINBASED_CTRLS \ ((((Bit64u) VMX_MSR_VMX_TRUE_PINBASED_CTRLS_HI) << 32) | VMX_MSR_VMX_TRUE_PINBASED_CTRLS_LO) // IA32_MSR_VMX_PROCBASED_CTRLS MSR (0x482) // ---------------------------- // Bits 1, 4-6, 8, 13-16, 26 must be '1 // Bits 0, 17, 18 must be '0 // Bits 19-21 also must be '0 when x86-64 is not supported // Allowed 0-settings (must be '1 bits) #define VMX_MSR_VMX_PROCBASED_CTRLS_LO (0x0401E172) // Allowed 1-settings #define VMX_MSR_VMX_PROCBASED_CTRLS_HI \ (VMX_VM_EXEC_CTRL2_SUPPORTED_BITS | VMX_MSR_VMX_PROCBASED_CTRLS_LO) #define VMX_MSR_VMX_PROCBASED_CTRLS \ ((((Bit64u) VMX_MSR_VMX_PROCBASED_CTRLS_HI) << 32) | VMX_MSR_VMX_PROCBASED_CTRLS_LO) // IA32_MSR_VMX_TRUE_PROCBASED_CTRLS MSR (0x48e) // --------------------------------- // Bits 15 and 16 no longer must be '1 #define VMX_MSR_VMX_TRUE_PROCBASED_CTRLS_LO (0x04006172) #define VMX_MSR_VMX_TRUE_PROCBASED_CTRLS_HI (VMX_MSR_VMX_PROCBASED_CTRLS_HI) #define VMX_MSR_VMX_TRUE_PROCBASED_CTRLS \ ((((Bit64u) VMX_MSR_VMX_TRUE_PROCBASED_CTRLS_HI) << 32) | VMX_MSR_VMX_TRUE_PROCBASED_CTRLS_LO) // IA32_MSR_VMX_VMEXIT_CTRLS MSR (0x483) // ------------------------- // Bits 0-8, 10, 11, 13, 14, 16, 17 must be '1 // Allowed 0-settings (must be '1 bits) #define VMX_MSR_VMX_VMEXIT_CTRLS_LO (0x00036DFF) // Allowed 1-settings #define VMX_MSR_VMX_VMEXIT_CTRLS_HI \ (VMX_VMEXIT_CTRL1_SUPPORTED_BITS | VMX_MSR_VMX_VMEXIT_CTRLS_LO) #define VMX_MSR_VMX_VMEXIT_CTRLS \ ((((Bit64u) VMX_MSR_VMX_VMEXIT_CTRLS_HI) << 32) | VMX_MSR_VMX_VMEXIT_CTRLS_LO) // IA32_MSR_VMX_TRUE_VMEXIT_CTRLS MSR (0x48f) // ------------------------------ // Bit 2 no longer must be '1 #define VMX_MSR_VMX_TRUE_VMEXIT_CTRLS_LO (0x00036DFB) #define VMX_MSR_VMX_TRUE_VMEXIT_CTRLS_HI (VMX_MSR_VMX_VMEXIT_CTRLS_HI) #define VMX_MSR_VMX_TRUE_VMEXIT_CTRLS \ ((((Bit64u) VMX_MSR_VMX_TRUE_VMEXIT_CTRLS_HI) << 32) | VMX_MSR_VMX_TRUE_VMEXIT_CTRLS_LO) // IA32_MSR_VMX_VMENTRY_CTRLS MSR (0x484) // -------------------------- // Bits 0-8, 12 must be '1 // Allowed 0-settings (must be '1 bits) #define VMX_MSR_VMX_VMENTRY_CTRLS_LO (0x000011FF) // Allowed 1-settings #define VMX_MSR_VMX_VMENTRY_CTRLS_HI \ (VMX_VMENTRY_CTRL1_SUPPORTED_BITS | VMX_MSR_VMX_VMENTRY_CTRLS_LO) #define VMX_MSR_VMX_VMENTRY_CTRLS \ ((((Bit64u) VMX_MSR_VMX_VMENTRY_CTRLS_HI) << 32) | VMX_MSR_VMX_VMENTRY_CTRLS_LO) // IA32_MSR_VMX_TRUE_VMENTRY_CTRLS MSR (0x490) // ------------------------------- // Bit 2 is longer must be '1 #define VMX_MSR_VMX_TRUE_VMENTRY_CTRLS_LO (0x000011FB) #define VMX_MSR_VMX_TRUE_VMENTRY_CTRLS_HI (VMX_MSR_VMX_VMENTRY_CTRLS_HI) #define VMX_MSR_VMX_TRUE_VMENTRY_CTRLS \ ((((Bit64u) VMX_MSR_VMX_TRUE_VMENTRY_CTRLS_HI) << 32) | VMX_MSR_VMX_TRUE_VMENTRY_CTRLS_LO) // IA32_MSR_VMX_MISC MSR (0x485) // ----------------- // [4:0] - TSC:VMX_PREEMPTION_TIMER ratio // [5] - VMEXITs store the value of EFER.LMA into the “x86-64 guest" // VMENTRY control (must set to '1 if 'unrestricted guest' is supported) // [6] - support VMENTER to HLT state // [7] - support VMENTER to SHUTDOWN state // [8] - support VMENTER to WAIT_FOR_SIPI state // [24:16] - number of CR3 target values supported // [27:25] - (N+1)*512 - recommended maximum MSRs in MSR store list // [28] - MSR_IA32_SMM_MONITOR_CTL[2] enable // [31-29] - Reserved // [63:32] - MSEG revision ID used by processor #if BX_SUPPORT_VMX >= 2 #define VMX_MISC_STORE_LMA_TO_X86_64_GUEST_VMENTRY_CONTROL (1<<5) #else #define VMX_MISC_STORE_LMA_TO_X86_64_GUEST_VMENTRY_CONTROL (0) #endif //Rate to increase VMX preemtion timer #define VMX_MISC_PREEMPTION_TIMER_RATE (0) #define VMX_MSR_MISC ((VMX_CR3_TARGET_MAX_CNT << 16) | \ VMX_MISC_STORE_LMA_TO_X86_64_GUEST_VMENTRY_CONTROL | \ VMX_MISC_PREEMPTION_TIMER_RATE) // // IA32_VMX_CR0_FIXED0 MSR (0x486) IA32_VMX_CR0_FIXED1 MSR (0x487) // ------------------- ------------------- // allowed 0-setting in CR0 in VMX mode // bits PE(0), NE(5) and PG(31) required to be set in CR0 to enter VMX mode #define VMX_MSR_CR0_FIXED0_LO (0x80000021) #define VMX_MSR_CR0_FIXED0_HI (0x00000000) #define VMX_MSR_CR0_FIXED0 \ ((((Bit64u) VMX_MSR_CR0_FIXED0_HI) << 32) | VMX_MSR_CR0_FIXED0_LO) // allowed 1-setting in CR0 in VMX mode #define VMX_MSR_CR0_FIXED1_LO (0xFFFFFFFF) #define VMX_MSR_CR0_FIXED1_HI (0x00000000) #define VMX_MSR_CR0_FIXED1 \ ((((Bit64u) VMX_MSR_CR0_FIXED1_HI) << 32) | VMX_MSR_CR0_FIXED1_LO) // // IA32_VMX_CR4_FIXED0 MSR (0x488) IA32_VMX_CR4_FIXED1 MSR (0x489) // ------------------- ------------------- // allowed 0-setting in CR0 in VMX mode // bit VMXE(13) required to be set in CR4 to enter VMX mode #define VMX_MSR_CR4_FIXED0_LO (0x00002000) #define VMX_MSR_CR4_FIXED0_HI (0x00000000) #define VMX_MSR_CR4_FIXED0 \ ((((Bit64u) VMX_MSR_CR4_FIXED0_HI) << 32) | VMX_MSR_CR4_FIXED0_LO) // allowed 1-setting in CR0 in VMX mode #define VMX_MSR_CR4_FIXED1_LO (BX_CPU_THIS_PTR cr4_suppmask) #define VMX_MSR_CR4_FIXED1_HI (0) #define VMX_MSR_CR4_FIXED1 \ ((((Bit64u) VMX_MSR_CR4_FIXED1_HI) << 32) | VMX_MSR_CR4_FIXED1_LO) // // IA32_VMX_VMCS_ENUM MSR (0x48a) // ------------------ // // 09:01 highest index value used for any VMCS encoding // 63:10 reserved, must be zero // #define VMX_MSR_VMCS_ENUM_LO (VMX_HIGHEST_VMCS_ENCODING) #define VMX_MSR_VMCS_ENUM_HI (0x00000000) #define VMX_MSR_VMCS_ENUM \ ((((Bit64u) VMX_MSR_VMCS_ENUM_HI) << 32) | VMX_MSR_VMCS_ENUM_LO) // IA32_VMX_MSR_PROCBASED_CTRLS2 MSR (0x48b) // ----------------------------- // Allowed 0-settings (must be '1 bits) #define VMX_MSR_VMX_PROCBASED_CTRLS2_LO (0x00000000) // Allowed 1-settings #define VMX_MSR_VMX_PROCBASED_CTRLS2_HI \ (VMX_VM_EXEC_CTRL3_SUPPORTED_BITS | VMX_MSR_VMX_PROCBASED_CTRLS2_LO) #define VMX_MSR_VMX_PROCBASED_CTRLS2 \ ((((Bit64u) VMX_MSR_VMX_PROCBASED_CTRLS2_HI) << 32) | VMX_MSR_VMX_PROCBASED_CTRLS2_LO) #if BX_SUPPORT_VMX >= 2 // IA32_VMX_EPT_VPID_CAP MSR (0x48c) // --------------------- enum VMX_INVEPT_INVVPID_type { BX_INVEPT_INVVPID_INDIVIDUAL_ADDRESS_INVALIDATION = 0, BX_INVEPT_INVVPID_SINGLE_CONTEXT_INVALIDATION, BX_INVEPT_INVVPID_ALL_CONTEXT_INVALIDATION, BX_INVEPT_INVVPID_SINGLE_CONTEXT_NON_GLOBAL_INVALIDATION }; #define VMX_MSR_VMX_EPT_VPID_CAP \ (BX_CPU_THIS_PTR vmx_cap.vmx_ept_vpid_cap_supported_bits) #define BX_VMX_EPT_ACCESS_DIRTY_ENABLED (BX_CPU_THIS_PTR vmcs.eptptr & 0x40) #endif #endif // _BX_VMX_INTEL_H_ bochs-2.6/cpu/stack32.cc0000644000175000017500000001667612020641453014722 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: stack32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_EdM(bxInstruction_c *i) { RSP_SPECULATIVE; Bit32u val32 = pop_32(); // Note: there is one little weirdism here. It is possible to use // ESP in the modrm addressing. If used, the value of ESP after the // pop is used to calculate the address. Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword_32(i->seg(), eaddr, val32); RSP_COMMIT; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_ERX(bxInstruction_c *i) { push_32(BX_READ_32BIT_REG(i->dst())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_ERX(bxInstruction_c *i) { BX_WRITE_32BIT_REGZ(i->dst(), pop_32()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH32_Sw(bxInstruction_c *i) { Bit16u val_16 = BX_CPU_THIS_PTR sregs[i->src()].selector.value; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { stack_write_word((Bit32u) (ESP-4), val_16); ESP -= 4; } else { stack_write_word((Bit16u) (SP-4), val_16); SP -= 4; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP32_Sw(bxInstruction_c *i) { Bit16u selector; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { selector = stack_read_word(ESP); load_seg_reg(&BX_CPU_THIS_PTR sregs[i->dst()], selector); ESP += 4; } else { selector = stack_read_word(SP); load_seg_reg(&BX_CPU_THIS_PTR sregs[i->dst()], selector); SP += 4; } if (i->dst() == BX_SEG_REG_SS) { // POP SS inhibits interrupts, debug exceptions and single-step // trap exceptions until the execution boundary following the // next instruction is reached. // Same code as MOV_SwEw() inhibit_interrupts(BX_INHIBIT_INTERRUPTS_BY_MOVSS); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_Id(bxInstruction_c *i) { push_32(i->Id()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_EdM(bxInstruction_c *i) { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_virtual_dword_32(i->seg(), eaddr); push_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHAD32(bxInstruction_c *i) { Bit32u temp_ESP = ESP; Bit16u temp_SP = SP; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { stack_write_dword((Bit32u) (temp_ESP - 4), EAX); stack_write_dword((Bit32u) (temp_ESP - 8), ECX); stack_write_dword((Bit32u) (temp_ESP - 12), EDX); stack_write_dword((Bit32u) (temp_ESP - 16), EBX); stack_write_dword((Bit32u) (temp_ESP - 20), temp_ESP); stack_write_dword((Bit32u) (temp_ESP - 24), EBP); stack_write_dword((Bit32u) (temp_ESP - 28), ESI); stack_write_dword((Bit32u) (temp_ESP - 32), EDI); ESP -= 32; } else { stack_write_dword((Bit16u) (temp_SP - 4), EAX); stack_write_dword((Bit16u) (temp_SP - 8), ECX); stack_write_dword((Bit16u) (temp_SP - 12), EDX); stack_write_dword((Bit16u) (temp_SP - 16), EBX); stack_write_dword((Bit16u) (temp_SP - 20), temp_ESP); stack_write_dword((Bit16u) (temp_SP - 24), EBP); stack_write_dword((Bit16u) (temp_SP - 28), ESI); stack_write_dword((Bit16u) (temp_SP - 32), EDI); SP -= 32; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPAD32(bxInstruction_c *i) { Bit32u edi, esi, ebp, ebx, edx, ecx, eax; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { Bit32u temp_ESP = ESP; edi = stack_read_dword((Bit32u) (temp_ESP + 0)); esi = stack_read_dword((Bit32u) (temp_ESP + 4)); ebp = stack_read_dword((Bit32u) (temp_ESP + 8)); stack_read_dword((Bit32u) (temp_ESP + 12)); ebx = stack_read_dword((Bit32u) (temp_ESP + 16)); edx = stack_read_dword((Bit32u) (temp_ESP + 20)); ecx = stack_read_dword((Bit32u) (temp_ESP + 24)); eax = stack_read_dword((Bit32u) (temp_ESP + 28)); ESP += 32; } else { Bit16u temp_SP = SP; edi = stack_read_dword((Bit16u) (temp_SP + 0)); esi = stack_read_dword((Bit16u) (temp_SP + 4)); ebp = stack_read_dword((Bit16u) (temp_SP + 8)); stack_read_dword((Bit16u) (temp_SP + 12)); ebx = stack_read_dword((Bit16u) (temp_SP + 16)); edx = stack_read_dword((Bit16u) (temp_SP + 20)); ecx = stack_read_dword((Bit16u) (temp_SP + 24)); eax = stack_read_dword((Bit16u) (temp_SP + 28)); SP += 32; } EDI = edi; ESI = esi; EBP = ebp; EBX = ebx; EDX = edx; ECX = ecx; EAX = eax; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ENTER32_IwIb(bxInstruction_c *i) { Bit16u imm16 = i->Iw(); Bit8u level = i->Ib2(); level &= 0x1F; RSP_SPECULATIVE; push_32(EBP); Bit32u frame_ptr32 = ESP; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { Bit32u ebp = EBP; // Use temp copy for case of exception. if (level > 0) { /* do level-1 times */ while (--level) { ebp -= 4; Bit32u temp32 = stack_read_dword(ebp); push_32(temp32); } /* push(frame pointer) */ push_32(frame_ptr32); } ESP -= imm16; // ENTER finishes with memory write check on the final stack pointer // the memory is touched but no write actually occurs // emulate it by doing RMW read access from SS:ESP read_RMW_virtual_dword_32(BX_SEG_REG_SS, ESP); } else { Bit16u bp = BP; if (level > 0) { /* do level-1 times */ while (--level) { bp -= 4; Bit32u temp32 = stack_read_dword(bp); push_32(temp32); } /* push(frame pointer) */ push_32(frame_ptr32); } SP -= imm16; // ENTER finishes with memory write check on the final stack pointer // the memory is touched but no write actually occurs // emulate it by doing RMW read access from SS:SP read_RMW_virtual_dword_32(BX_SEG_REG_SS, SP); } EBP = frame_ptr32; RSP_COMMIT; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LEAVE32(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u value32; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { value32 = stack_read_dword(EBP); ESP = EBP + 4; } else { value32 = stack_read_dword(BP); SP = BP + 4; } EBP = value32; BX_NEXT_INSTR(i); } bochs-2.6/cpu/vmexit.cc0000644000175000017500000005515612020641453014760 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmexit.cc 11321 2012-08-06 20:41:16Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2009-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_VMX // BX_READ(0) form means nnn(), rm(); BX_WRITE(1) form means rm(), nnn() Bit32u gen_instruction_info(bxInstruction_c *i, Bit32u reason, bx_bool rw_form) { Bit32u instr_info = 0; switch(reason) { case VMX_VMEXIT_VMREAD: case VMX_VMEXIT_VMWRITE: #if BX_SUPPORT_VMX >= 2 case VMX_VMEXIT_GDTR_IDTR_ACCESS: case VMX_VMEXIT_LDTR_TR_ACCESS: case VMX_VMEXIT_INVEPT: case VMX_VMEXIT_INVVPID: case VMX_VMEXIT_INVPCID: #endif if (rw_form == BX_READ) instr_info |= i->dst() << 28; else instr_info |= i->src() << 28; break; default: break; } // -------------------------------------- // instruction information field format // -------------------------------------- // // [.2:.0] | Memory operand scale field (encoded) // [.6:.3] | Reg1, undefined when memory operand // [.9:.7] | Memory operand address size // [10:10] | Memory/Register format (0 - mem, 1 - reg) // [14:11] | Reserved // [17:15] | Memory operand segment register field // [21:18] | Memory operand index field // [22:22] | Memory operand index field invalid // [26:23] | Memory operand base field // [27:27] | Memory operand base field invalid // [31:28] | Reg2, if exists // if (i->modC0()) { // reg/reg format instr_info |= (1 << 10); if (rw_form == BX_READ) instr_info |= i->src() << 3; else instr_info |= i->dst() << 3; } else { // memory format if (i->as64L()) instr_info |= 1 << 8; else if (i->as32L()) instr_info |= 1 << 7; instr_info |= i->seg() << 15; if (i->sibIndex() != BX_NIL_REGISTER) instr_info |= i->sibScale() | (i->sibIndex() << 18); else instr_info |= 1 << 22; // index invalid if (i->sibBase() != BX_NIL_REGISTER) instr_info |= i->sibBase() << 23; else instr_info |= 1 << 27; // base invalid } return instr_info; } void BX_CPP_AttrRegparmN(3) BX_CPU_C::VMexit_Instruction(bxInstruction_c *i, Bit32u reason, bx_bool rw_form) { Bit64u qualification = 0; Bit32u instr_info = 0; switch(reason) { case VMX_VMEXIT_VMREAD: case VMX_VMEXIT_VMWRITE: case VMX_VMEXIT_VMPTRLD: case VMX_VMEXIT_VMPTRST: case VMX_VMEXIT_VMCLEAR: case VMX_VMEXIT_VMXON: #if BX_SUPPORT_VMX >= 2 case VMX_VMEXIT_GDTR_IDTR_ACCESS: case VMX_VMEXIT_LDTR_TR_ACCESS: case VMX_VMEXIT_INVEPT: case VMX_VMEXIT_INVVPID: #endif #if BX_SUPPORT_X86_64 if (long64_mode()) { qualification = (Bit64u) i->displ32s(); if (i->sibBase() == BX_64BIT_REG_RIP) qualification += RIP; } else #endif qualification = (Bit64u) ((Bit32u) i->displ32s()); instr_info = gen_instruction_info(i, reason, rw_form); VMwrite32(VMCS_32BIT_VMEXIT_INSTRUCTION_INFO, instr_info); break; default: BX_PANIC(("VMexit_Instruction reason %d", reason)); } VMexit(reason, qualification); } void BX_CPU_C::VMexit_PAUSE(void) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); if (VMEXIT(VMX_VM_EXEC_CTRL2_PAUSE_VMEXIT)) { BX_DEBUG(("VMEXIT: PAUSE")); VMexit(VMX_VMEXIT_PAUSE, 0); } #if BX_SUPPORT_VMX >= 2 if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_PAUSE_LOOP_VMEXIT) && CPL == 0) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; Bit64u currtime = bx_pc_system.time_ticks(); if ((currtime - vm->last_pause_time) > vm->pause_loop_exiting_gap) { vm->first_pause_time = currtime; } else { if ((currtime - vm->first_pause_time) > vm->pause_loop_exiting_window) VMexit(VMX_VMEXIT_PAUSE, 0); } vm->last_pause_time = currtime; } #endif } void BX_CPU_C::VMexit_ExtInterrupt(void) { if (! BX_CPU_THIS_PTR in_vmx_guest) return; if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT)) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if (! (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_INTA_ON_VMEXIT)) { // interrupt wasn't acknowledged and still pending, interruption info is invalid VMwrite32(VMCS_32BIT_VMEXIT_INTERRUPTION_INFO, 0); VMexit(VMX_VMEXIT_EXTERNAL_INTERRUPT, 0); } } } #if BX_SUPPORT_VMX >= 2 void BX_CPU_C::VMexit_PreemptionTimerExpired(void) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VMX_PREEMPTION_TIMER_VMEXIT)) { BX_DEBUG(("VMEXIT: VMX Preemption Timer Expired")); VMexit(VMX_VMEXIT_VMX_PREEMPTION_TIMER_EXPIRED, 0); } } #endif void BX_CPU_C::VMexit_Event(unsigned type, unsigned vector, Bit16u errcode, bx_bool errcode_valid, Bit64u qualification) { if (! BX_CPU_THIS_PTR in_vmx_guest) return; VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; bx_bool vmexit = 0; VMX_vmexit_reason reason = VMX_VMEXIT_EXCEPTION_NMI; switch(type) { case BX_EXTERNAL_INTERRUPT: reason = VMX_VMEXIT_EXTERNAL_INTERRUPT; if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT)) vmexit = 1; break; case BX_NMI: if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT)) vmexit = 1; break; case BX_PRIVILEGED_SOFTWARE_INTERRUPT: case BX_SOFTWARE_EXCEPTION: case BX_HARDWARE_EXCEPTION: BX_ASSERT(vector < BX_CPU_HANDLED_EXCEPTIONS); if (vector == BX_PF_EXCEPTION) { // page faults are specially treated bx_bool err_match = ((errcode & vm->vm_pf_mask) == vm->vm_pf_match); bx_bool bitmap = (vm->vm_exceptions_bitmap >> BX_PF_EXCEPTION) & 1; vmexit = (err_match == bitmap); } else { vmexit = (vm->vm_exceptions_bitmap >> vector) & 1; } break; case BX_SOFTWARE_INTERRUPT: break; // no VMEXIT on software interrupt default: BX_ERROR(("VMexit_Event: unknown event type %d", type)); } // ---------------------------------------------------- // VMExit interruption info // ---------------------------------------------------- // [.7:.0] | Interrupt/Exception vector // [10:.8] | Interrupt/Exception type // [11:11] | error code pushed to the stack // [12:12] | NMI unblocking due to IRET // [30:13] | reserved // [31:31] | interruption info valid // if (! vmexit) { // record IDT vectoring information vm->idt_vector_error_code = errcode; vm->idt_vector_info = vector | (type << 8); if (errcode_valid) vm->idt_vector_info |= (1 << 11); // error code delivered return; } BX_DEBUG(("VMEXIT: event vector 0x%02x type %d error code=0x%04x", vector, type, errcode)); // VMEXIT is not considered to occur during event delivery if it results // in a double fault exception that causes VMEXIT directly if (vector == BX_DF_EXCEPTION) BX_CPU_THIS_PTR in_event = 0; // clear in_event indication on #DF if (vector == BX_DB_EXCEPTION) { // qualifcation for debug exceptions similar to debug_trap field qualification = BX_CPU_THIS_PTR debug_trap & 0x0000600f; } // clear debug_trap field BX_CPU_THIS_PTR debug_trap = 0; BX_CPU_THIS_PTR inhibit_mask = 0; Bit32u interruption_info = vector | (type << 8); if (errcode_valid) interruption_info |= (1 << 11); // error code delivered interruption_info |= (1 << 31); // valid VMwrite32(VMCS_32BIT_VMEXIT_INTERRUPTION_INFO, interruption_info); VMwrite32(VMCS_32BIT_VMEXIT_INTERRUPTION_ERR_CODE, errcode); VMexit(reason, qualification); } void BX_CPU_C::VMexit_TripleFault(void) { if (! BX_CPU_THIS_PTR in_vmx_guest) return; BX_ERROR(("VMEXIT: triple fault")); // VMEXIT is not considered to occur during event delivery if it results // in a triple fault exception (that causes VMEXIT directly) BX_CPU_THIS_PTR in_event = 0; VMexit(VMX_VMEXIT_TRIPLE_FAULT, 0); } void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_TaskSwitch(Bit16u tss_selector, unsigned source) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); BX_ERROR(("VMEXIT: task switch")); VMexit(VMX_VMEXIT_TASK_SWITCH, tss_selector | (source << 30)); } #define BX_VMX_LO_MSR_START 0x00000000 #define BX_VMX_LO_MSR_END 0x00001FFF #define BX_VMX_HI_MSR_START 0xC0000000 #define BX_VMX_HI_MSR_END 0xC0001FFF void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_MSR(unsigned op, Bit32u msr) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); bx_bool vmexit = 0; if (! VMEXIT(VMX_VM_EXEC_CTRL2_MSR_BITMAPS)) vmexit = 1; else { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; Bit8u field; if (msr >= BX_VMX_HI_MSR_START) { if (msr > BX_VMX_HI_MSR_END) vmexit = 1; else { // check MSR-HI bitmaps bx_phy_address pAddr = vm->msr_bitmap_addr + ((msr - BX_VMX_HI_MSR_START) >> 3) + 1024 + ((op == VMX_VMEXIT_RDMSR) ? 0 : 2048); access_read_physical(pAddr, 1, &field); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_MSR_BITMAP_ACCESS, &field); if (field & (1 << (msr & 7))) vmexit = 1; } } else { if (msr > BX_VMX_LO_MSR_END) vmexit = 1; else { // check MSR-LO bitmaps bx_phy_address pAddr = vm->msr_bitmap_addr + (msr >> 3) + ((op == VMX_VMEXIT_RDMSR) ? 0 : 2048); access_read_physical(pAddr, 1, &field); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_MSR_BITMAP_ACCESS, &field); if (field & (1 << (msr & 7))) vmexit = 1; } } } if (vmexit) { BX_DEBUG(("VMEXIT: %sMSR 0x%08x", (op == VMX_VMEXIT_RDMSR) ? "RD" : "WR", msr)); VMexit(op, 0); } } #define VMX_VMEXIT_IO_PORTIN (1 << 3) #define VMX_VMEXIT_IO_INSTR_STRING (1 << 4) #define VMX_VMEXIT_IO_INSTR_REP (1 << 5) #define VMX_VMEXIT_IO_INSTR_IMM (1 << 6) void BX_CPP_AttrRegparmN(3) BX_CPU_C::VMexit_IO(bxInstruction_c *i, unsigned port, unsigned len) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); BX_ASSERT(port <= 0xFFFF); bool vmexit = 0; if (VMEXIT(VMX_VM_EXEC_CTRL2_IO_BITMAPS)) { // always VMEXIT on port "wrap around" case if ((port + len) > 0x10000) vmexit = 1; else { Bit8u bitmap[2]; bx_phy_address pAddr; if ((port & 0x7fff) + len > 0x8000) { // special case - the IO access split cross both I/O bitmaps pAddr = BX_CPU_THIS_PTR vmcs.io_bitmap_addr[0] + 0xfff; access_read_physical(pAddr, 1, &bitmap[0]); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_IO_BITMAP_ACCESS, &bitmap[0]); pAddr = BX_CPU_THIS_PTR vmcs.io_bitmap_addr[1]; access_read_physical(pAddr, 1, &bitmap[1]); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_IO_BITMAP_ACCESS, &bitmap[1]); } else { // access_read_physical cannot read 2 bytes cross 4K boundary :( pAddr = BX_CPU_THIS_PTR vmcs.io_bitmap_addr[(port >> 15) & 1] + ((port & 0x7fff) / 8); access_read_physical(pAddr, 1, &bitmap[0]); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_IO_BITMAP_ACCESS, &bitmap[0]); pAddr++; access_read_physical(pAddr, 1, &bitmap[1]); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_IO_BITMAP_ACCESS, &bitmap[1]); } Bit16u combined_bitmap = bitmap[1]; combined_bitmap = (combined_bitmap << 8) | bitmap[0]; unsigned mask = ((1 << len) - 1) << (port & 7); if (combined_bitmap & mask) vmexit = 1; } } else if (VMEXIT(VMX_VM_EXEC_CTRL2_IO_VMEXIT)) vmexit = 1; if (vmexit) { BX_DEBUG(("VMEXIT: I/O port 0x%04x", port)); Bit32u qualification = 0; switch(i->getIaOpcode()) { case BX_IA_IN_ALIb: case BX_IA_IN_AXIb: case BX_IA_IN_EAXIb: qualification = VMX_VMEXIT_IO_PORTIN | VMX_VMEXIT_IO_INSTR_IMM; break; case BX_IA_OUT_IbAL: case BX_IA_OUT_IbAX: case BX_IA_OUT_IbEAX: qualification = VMX_VMEXIT_IO_INSTR_IMM; break; case BX_IA_IN_ALDX: case BX_IA_IN_AXDX: case BX_IA_IN_EAXDX: qualification = VMX_VMEXIT_IO_PORTIN; // no immediate break; case BX_IA_OUT_DXAL: case BX_IA_OUT_DXAX: case BX_IA_OUT_DXEAX: qualification = 0; // PORTOUT, no immediate break; case BX_IA_REP_INSB_YbDX: case BX_IA_REP_INSW_YwDX: case BX_IA_REP_INSD_YdDX: qualification = VMX_VMEXIT_IO_PORTIN | VMX_VMEXIT_IO_INSTR_STRING; if (i->repUsedL()) qualification |= VMX_VMEXIT_IO_INSTR_REP; break; case BX_IA_REP_OUTSB_DXXb: case BX_IA_REP_OUTSW_DXXw: case BX_IA_REP_OUTSD_DXXd: qualification = VMX_VMEXIT_IO_INSTR_STRING; // PORTOUT if (i->repUsedL()) qualification |= VMX_VMEXIT_IO_INSTR_REP; break; default: BX_PANIC(("VMexit_IO: I/O instruction %s unknown", i->getIaOpcodeName())); } if (qualification & VMX_VMEXIT_IO_INSTR_STRING) { bx_address asize_mask = (bx_address) i->asize_mask(), laddr; if (qualification & VMX_VMEXIT_IO_PORTIN) laddr = get_laddr(BX_SEG_REG_ES, RDI & asize_mask); else // PORTOUT laddr = get_laddr(i->seg(), RSI & asize_mask); VMwrite_natural(VMCS_GUEST_LINEAR_ADDR, laddr); Bit32u instruction_info = i->seg() << 15; if (i->as64L()) instruction_info |= (1 << 8); else if (i->as32L()) instruction_info |= (1 << 7); VMwrite32(VMCS_32BIT_VMEXIT_INSTRUCTION_INFO, instruction_info); } VMexit(VMX_VMEXIT_IO_INSTRUCTION, qualification | (len-1) | (port << 16)); } } // // ---------------------------------------------------------------- // Exit qualification for CR access // ---------------------------------------------------------------- // [.3:.0] | Number of CR register (CR0, CR3, CR4, CR8) // [.5:.4] | CR access type (0 - MOV to CR, 1 - MOV from CR, 2 - CLTS, 3 - LMSW) // [.6:.6] | LMSW operand reg/mem (cleared for CR access and CLTS) // [.7:.7] | reserved // [11:.8] | Source Operand Register for CR access (cleared for CLTS and LMSW) // [15:12] | reserved // [31:16] | LMSW source data (cleared for CR access and CLTS) // [63:32] | reserved // bx_bool BX_CPU_C::VMexit_CLTS(void) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if (vm->vm_cr0_mask & vm->vm_cr0_read_shadow & 0x8) { BX_DEBUG(("VMEXIT: CLTS")); // all rest of the fields cleared to zero Bit64u qualification = VMX_VMEXIT_CR_ACCESS_CLTS << 4; VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } if ((vm->vm_cr0_mask & 0x8) != 0 && (vm->vm_cr0_read_shadow & 0x8) == 0) return 1; /* do not clear CR0.TS */ else return 0; } Bit32u BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_LMSW(bxInstruction_c *i, Bit32u msw) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; Bit32u mask = vm->vm_cr0_mask & 0xF; /* LMSW affects only low 4 bits */ bx_bool vmexit = 0; if ((mask & msw & 0x1) != 0 && (vm->vm_cr0_read_shadow & 0x1) == 0) vmexit = 1; if ((mask & vm->vm_cr0_read_shadow & 0xE) != (mask & msw & 0xE)) vmexit = 1; if (vmexit) { BX_DEBUG(("VMEXIT: CR0 write by LMSW of value 0x%04x", msw)); Bit64u qualification = VMX_VMEXIT_CR_ACCESS_LMSW << 4; qualification |= msw << 16; if (! i->modC0()) { qualification |= (1 << 6); // memory operand VMwrite_natural(VMCS_GUEST_LINEAR_ADDR, get_laddr(i->seg(), RMAddr(i))); } VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } // keep untouched all the bits set in CR0 mask return (BX_CPU_THIS_PTR cr0.get32() & mask) | (msw & ~mask); } bx_address BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_CR0_Write(bxInstruction_c *i, bx_address val) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if ((vm->vm_cr0_mask & vm->vm_cr0_read_shadow) != (vm->vm_cr0_mask & val)) { BX_DEBUG(("VMEXIT: CR0 write")); Bit64u qualification = i->src() << 8; VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } // keep untouched all the bits set in CR0 mask return (BX_CPU_THIS_PTR cr0.get32() & vm->vm_cr0_mask) | (val & ~vm->vm_cr0_mask); } void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_CR3_Read(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); if (VMEXIT(VMX_VM_EXEC_CTRL2_CR3_READ_VMEXIT)) { BX_DEBUG(("VMEXIT: CR3 read")); Bit64u qualification = 3 | (VMX_VMEXIT_CR_ACCESS_CR_READ << 4) | (i->dst() << 8); VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } } void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_CR3_Write(bxInstruction_c *i, bx_address val) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if (VMEXIT(VMX_VM_EXEC_CTRL2_CR3_WRITE_VMEXIT)) { for (unsigned n=0; n < vm->vm_cr3_target_cnt; n++) { if (vm->vm_cr3_target_value[n] == val) return; } BX_DEBUG(("VMEXIT: CR3 write")); Bit64u qualification = 3 | (i->src() << 8); VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } } bx_address BX_CPP_AttrRegparmN(2) BX_CPU_C::VMexit_CR4_Write(bxInstruction_c *i, bx_address val) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if ((vm->vm_cr4_mask & vm->vm_cr4_read_shadow) != (vm->vm_cr4_mask & val)) { BX_DEBUG(("VMEXIT: CR4 write")); Bit64u qualification = 4 | (i->src() << 8); VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } // keep untouched all the bits set in CR4 mask return (BX_CPU_THIS_PTR cr4.get32() & vm->vm_cr4_mask) | (val & ~vm->vm_cr4_mask); } void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_CR8_Read(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); if (VMEXIT(VMX_VM_EXEC_CTRL2_CR8_READ_VMEXIT)) { BX_DEBUG(("VMEXIT: CR8 read")); Bit64u qualification = 8 | (VMX_VMEXIT_CR_ACCESS_CR_READ << 4) | (i->dst() << 8); VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } } void BX_CPP_AttrRegparmN(1) BX_CPU_C::VMexit_CR8_Write(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); if (VMEXIT(VMX_VM_EXEC_CTRL2_CR8_WRITE_VMEXIT)) { BX_DEBUG(("VMEXIT: CR8 write")); Bit64u qualification = 8 | (i->src() << 8); VMexit(VMX_VMEXIT_CR_ACCESS, qualification); } } // // ---------------------------------------------------------------- // Exit qualification for DR access // ---------------------------------------------------------------- // [.3:.0] | Number of DR register // [.4:.4] | DR access type (0 - MOV to DR, 1 - MOV from DR) // [.7:.5] | reserved // [11:.8] | Source Operand Register // [63:12] | reserved // void BX_CPU_C::VMexit_DR_Access(unsigned read, unsigned dr, unsigned reg) { BX_ASSERT(BX_CPU_THIS_PTR in_vmx_guest); if (VMEXIT(VMX_VM_EXEC_CTRL2_DRx_ACCESS_VMEXIT)) { BX_DEBUG(("VMEXIT: DR%d %s access", dr, read ? "READ" : "WRITE")); Bit64u qualification = dr | (reg << 8); if (read) qualification |= (1 << 4); VMexit(VMX_VMEXIT_DR_ACCESS, qualification); } } #if BX_SUPPORT_X86_64 Bit32u BX_CPU_C::VMX_Read_VTPR(void) { bx_phy_address pAddr = BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr + 0x80; Bit32u vtpr; access_read_physical(pAddr, 4, (Bit8u*)(&vtpr)); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_READ, BX_VMX_VTPR_ACCESS, (Bit8u*)(&vtpr)); return vtpr; } void BX_CPU_C::VMX_Write_VTPR(Bit8u vtpr) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; bx_phy_address pAddr = vm->virtual_apic_page_addr + 0x80; Bit32u field32 = vtpr; access_write_physical(pAddr, 4, (Bit8u*)(&field32)); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMX_VTPR_ACCESS, (Bit8u*)(&field32)); Bit8u tpr_shadow = vtpr >> 4; if (tpr_shadow < vm->vm_tpr_threshold) { // commit current instruction to produce trap-like VMexit BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP VMexit(VMX_VMEXIT_TPR_THRESHOLD, 0); } } // apic virtualization bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::is_virtual_apic_page(bx_phy_address paddr) { if (BX_CPU_THIS_PTR in_vmx_guest) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)) if (PPFOf(paddr) == PPFOf(vm->apic_access_page)) return 1; } return 0; } // apic virtualization void BX_CPU_C::VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *data) { BX_ASSERT(SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)); Bit32u offset = PAGE_OFFSET(paddr); // access is not instruction fetch because cpu::prefetch will crash them if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == 0x80 && len <= 4) { // VTPR access Bit32u vtpr = VMX_Read_VTPR(); if (len == 1) *((Bit8u *) data) = vtpr & 0xff; else if (len == 2) *((Bit16u *) data) = vtpr & 0xffff; else if (len == 4) *((Bit32u *) data) = vtpr; else BX_PANIC(("PANIC: Unsupported Virtual APIC access len = 3 !")); return; } Bit32u qualification = offset | (BX_CPU_THIS_PTR in_event) ? VMX_APIC_ACCESS_DURING_EVENT_DELIVERY : VMX_APIC_READ_INSTRUCTION_EXECUTION; VMexit(VMX_VMEXIT_APIC_ACCESS, qualification); } // apic virtualization void BX_CPU_C::VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *data) { BX_ASSERT(SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)); Bit32u offset = PAGE_OFFSET(paddr); if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == 0x80 && len <= 4) { // VTPR access VMX_Write_VTPR(*((Bit8u *) data)); return; } Bit32u qualification = offset | (BX_CPU_THIS_PTR in_event) ? VMX_APIC_ACCESS_DURING_EVENT_DELIVERY : VMX_APIC_WRITE_INSTRUCTION_EXECUTION; VMexit(VMX_VMEXIT_APIC_ACCESS, qualification); } #endif #if BX_SUPPORT_VMX >= 2 Bit16u BX_CPU_C::VMX_Get_Current_VPID(void) { if (! BX_CPU_THIS_PTR in_vmx_guest || !SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VPID_ENABLE)) return 0; return BX_CPU_THIS_PTR vmcs.vpid; } #endif #endif // BX_SUPPORT_VMX bochs-2.6/cpu/i387.h0000644000175000017500000001606412020641453013773 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: i387.h 10208 2011-02-24 21:54:04Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004-2009 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef _BX_I387_RELATED_EXTENSIONS_H_ #define _BX_I387_RELATED_EXTENSIONS_H_ #if BX_SUPPORT_FPU #include "fpu/softfloat.h" #define BX_FPU_REG(index) \ (BX_CPU_THIS_PTR the_i387.st_space[index & 0x7]) #if defined(NEED_CPU_REG_SHORTCUTS) #define FPU_PARTIAL_STATUS (BX_CPU_THIS_PTR the_i387.swd) #define FPU_CONTROL_WORD (BX_CPU_THIS_PTR the_i387.cwd) #define FPU_TAG_WORD (BX_CPU_THIS_PTR the_i387.twd) #define FPU_TOS (BX_CPU_THIS_PTR the_i387.tos) #endif #include "fpu/tag_w.h" #include "fpu/status_w.h" #include "fpu/control_w.h" extern int FPU_tagof(const floatx80 ®); // // Minimal i387 structure // struct BOCHSAPI_MSVCONLY i387_t { i387_t() {} public: void init(); // used by FINIT/FNINIT instructions void reset(); // called on CPU reset int is_IA_masked() const { return (cwd & FPU_CW_Invalid); } Bit16u get_control_word() const { return cwd; } Bit16u get_tag_word() const { return twd; } Bit16u get_status_word() const { return (swd & ~FPU_SW_Top & 0xFFFF) | ((tos << 11) & FPU_SW_Top); } Bit16u get_partial_status() const { return swd; } void FPU_pop (); void FPU_push(); void FPU_settagi(int tag, int stnr); void FPU_settagi_valid(int stnr); int FPU_gettagi(int stnr); floatx80 FPU_read_regi(int stnr) { return st_space[(tos+stnr) & 7]; } void FPU_save_regi(floatx80 reg, int stnr); void FPU_save_regi(floatx80 reg, int tag, int stnr); public: Bit16u cwd; // control word Bit16u swd; // status word Bit16u twd; // tag word Bit16u foo; // last instruction opcode bx_address fip; bx_address fdp; Bit16u fcs; Bit16u fds; floatx80 st_space[8]; unsigned char tos; unsigned char align1; unsigned char align2; unsigned char align3; }; #define IS_TAG_EMPTY(i) \ ((BX_CPU_THIS_PTR the_i387.FPU_gettagi(i)) == FPU_Tag_Empty) #define BX_READ_FPU_REG(i) \ (BX_CPU_THIS_PTR the_i387.FPU_read_regi(i)) #define BX_WRITE_FPU_REG(value, i) \ BX_CPU_THIS_PTR the_i387.FPU_save_regi((value), (i)); #define BX_WRITE_FPU_REGISTER_AND_TAG(value, tag, i) \ BX_CPU_THIS_PTR the_i387.FPU_save_regi((value), (tag), (i)); BX_CPP_INLINE int i387_t::FPU_gettagi(int stnr) { return (twd >> (((stnr+tos) & 7)*2)) & 3; } BX_CPP_INLINE void i387_t::FPU_settagi_valid(int stnr) { int regnr = (stnr + tos) & 7; twd &= ~(3 << (regnr*2)); // FPU_Tag_Valid == '00 } BX_CPP_INLINE void i387_t::FPU_settagi(int tag, int stnr) { int regnr = (stnr + tos) & 7; twd &= ~(3 << (regnr*2)); twd |= (tag & 3) << (regnr*2); } BX_CPP_INLINE void i387_t::FPU_push(void) { tos = (tos - 1) & 7; } BX_CPP_INLINE void i387_t::FPU_pop(void) { twd |= 3 << (tos*2); tos = (tos + 1) & 7; } // it is only possisble to read FPU tag word through certain // instructions like FNSAVE, and they update tag word to its // real value anyway BX_CPP_INLINE void i387_t::FPU_save_regi(floatx80 reg, int stnr) { st_space[(stnr+tos) & 7] = reg; FPU_settagi_valid(stnr); } BX_CPP_INLINE void i387_t::FPU_save_regi(floatx80 reg, int tag, int stnr) { st_space[(stnr+tos) & 7] = reg; FPU_settagi(tag, stnr); } #include BX_CPP_INLINE void i387_t::init() { cwd = 0x037F; swd = 0; tos = 0; twd = 0xFFFF; foo = 0; fip = 0; fcs = 0; fds = 0; fdp = 0; } BX_CPP_INLINE void i387_t::reset() { cwd = 0x0040; swd = 0; tos = 0; twd = 0x5555; foo = 0; fip = 0; fcs = 0; fds = 0; fdp = 0; memset(st_space, 0, sizeof(floatx80)*8); } typedef union bx_packed_mmx_reg_t { Bit8s mmx_sbyte[8]; Bit16s mmx_s16[4]; Bit32s mmx_s32[2]; Bit64s mmx_s64; Bit8u mmx_ubyte[8]; Bit16u mmx_u16[4]; Bit32u mmx_u32[2]; Bit64u mmx_u64; } BxPackedMmxRegister; #ifdef BX_BIG_ENDIAN #define mmx64s(i) mmx_s64 #define mmx32s(i) mmx_s32[1 - (i)] #define mmx16s(i) mmx_s16[3 - (i)] #define mmxsbyte(i) mmx_sbyte[7 - (i)] #define mmxubyte(i) mmx_ubyte[7 - (i)] #define mmx16u(i) mmx_u16[3 - (i)] #define mmx32u(i) mmx_u32[1 - (i)] #define mmx64u mmx_u64 #else #define mmx64s(i) mmx_s64 #define mmx32s(i) mmx_s32[(i)] #define mmx16s(i) mmx_s16[(i)] #define mmxsbyte(i) mmx_sbyte[(i)] #define mmxubyte(i) mmx_ubyte[(i)] #define mmx16u(i) mmx_u16[(i)] #define mmx32u(i) mmx_u32[(i)] #define mmx64u mmx_u64 #endif /* for compatability with already written code */ #define MMXSB0(reg) (reg.mmxsbyte(0)) #define MMXSB1(reg) (reg.mmxsbyte(1)) #define MMXSB2(reg) (reg.mmxsbyte(2)) #define MMXSB3(reg) (reg.mmxsbyte(3)) #define MMXSB4(reg) (reg.mmxsbyte(4)) #define MMXSB5(reg) (reg.mmxsbyte(5)) #define MMXSB6(reg) (reg.mmxsbyte(6)) #define MMXSB7(reg) (reg.mmxsbyte(7)) #define MMXSW0(reg) (reg.mmx16s(0)) #define MMXSW1(reg) (reg.mmx16s(1)) #define MMXSW2(reg) (reg.mmx16s(2)) #define MMXSW3(reg) (reg.mmx16s(3)) #define MMXSD0(reg) (reg.mmx32s(0)) #define MMXSD1(reg) (reg.mmx32s(1)) #define MMXSQ(reg) (reg.mmx64s) #define MMXUQ(reg) (reg.mmx64u) #define MMXUD0(reg) (reg.mmx32u(0)) #define MMXUD1(reg) (reg.mmx32u(1)) #define MMXUW0(reg) (reg.mmx16u(0)) #define MMXUW1(reg) (reg.mmx16u(1)) #define MMXUW2(reg) (reg.mmx16u(2)) #define MMXUW3(reg) (reg.mmx16u(3)) #define MMXUB0(reg) (reg.mmxubyte(0)) #define MMXUB1(reg) (reg.mmxubyte(1)) #define MMXUB2(reg) (reg.mmxubyte(2)) #define MMXUB3(reg) (reg.mmxubyte(3)) #define MMXUB4(reg) (reg.mmxubyte(4)) #define MMXUB5(reg) (reg.mmxubyte(5)) #define MMXUB6(reg) (reg.mmxubyte(6)) #define MMXUB7(reg) (reg.mmxubyte(7)) #define BX_MMX_REG(index) (BX_FPU_REG(index).fraction) #define BX_READ_MMX_REG(index) \ (*((const BxPackedMmxRegister*)(&(BX_MMX_REG(index))))) #define BX_WRITE_MMX_REG(index, value) \ { \ (BX_FPU_REG(index)).fraction = MMXUQ(value); \ (BX_FPU_REG(index)).exp = 0xffff; \ } #endif /* BX_SUPPORT_FPU */ #endif bochs-2.6/cpu/cpu.h0000644000175000017500000072562312020641453014100 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cpu.h 11377 2012-08-28 16:05:39Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_CPU_H # define BX_CPU_H 1 #include // // segment register encoding #define BX_SEG_REG_ES 0 #define BX_SEG_REG_CS 1 #define BX_SEG_REG_SS 2 #define BX_SEG_REG_DS 3 #define BX_SEG_REG_FS 4 #define BX_SEG_REG_GS 5 // NULL now has to fit in 3 bits. #define BX_SEG_REG_NULL 7 #define BX_NULL_SEG_REG(seg) ((seg) == BX_SEG_REG_NULL) // #define BX_16BIT_REG_AX 0 #define BX_16BIT_REG_CX 1 #define BX_16BIT_REG_DX 2 #define BX_16BIT_REG_BX 3 #define BX_16BIT_REG_SP 4 #define BX_16BIT_REG_BP 5 #define BX_16BIT_REG_SI 6 #define BX_16BIT_REG_DI 7 #define BX_32BIT_REG_EAX 0 #define BX_32BIT_REG_ECX 1 #define BX_32BIT_REG_EDX 2 #define BX_32BIT_REG_EBX 3 #define BX_32BIT_REG_ESP 4 #define BX_32BIT_REG_EBP 5 #define BX_32BIT_REG_ESI 6 #define BX_32BIT_REG_EDI 7 #define BX_64BIT_REG_RAX 0 #define BX_64BIT_REG_RCX 1 #define BX_64BIT_REG_RDX 2 #define BX_64BIT_REG_RBX 3 #define BX_64BIT_REG_RSP 4 #define BX_64BIT_REG_RBP 5 #define BX_64BIT_REG_RSI 6 #define BX_64BIT_REG_RDI 7 #define BX_64BIT_REG_R8 8 #define BX_64BIT_REG_R9 9 #define BX_64BIT_REG_R10 10 #define BX_64BIT_REG_R11 11 #define BX_64BIT_REG_R12 12 #define BX_64BIT_REG_R13 13 #define BX_64BIT_REG_R14 14 #define BX_64BIT_REG_R15 15 #if BX_SUPPORT_X86_64 # define BX_GENERAL_REGISTERS 16 #else # define BX_GENERAL_REGISTERS 8 #endif #define BX_TMP_REGISTER (BX_GENERAL_REGISTERS) #define BX_16BIT_REG_IP (BX_GENERAL_REGISTERS+1) #define BX_32BIT_REG_EIP (BX_GENERAL_REGISTERS+1) #define BX_64BIT_REG_RIP (BX_GENERAL_REGISTERS+1) #define BX_NIL_REGISTER (BX_GENERAL_REGISTERS+2) #if defined(NEED_CPU_REG_SHORTCUTS) /* WARNING: Only BX_CPU_C member functions can use these shortcuts safely! Functions that use the shortcuts outside of BX_CPU_C might work when BX_USE_CPU_SMF=1 but will fail when BX_USE_CPU_SMF=0 (for example in SMP mode). */ // access to 8 bit general registers #define AL (BX_CPU_THIS_PTR gen_reg[0].word.byte.rl) #define CL (BX_CPU_THIS_PTR gen_reg[1].word.byte.rl) #define DL (BX_CPU_THIS_PTR gen_reg[2].word.byte.rl) #define BL (BX_CPU_THIS_PTR gen_reg[3].word.byte.rl) #define AH (BX_CPU_THIS_PTR gen_reg[0].word.byte.rh) #define CH (BX_CPU_THIS_PTR gen_reg[1].word.byte.rh) #define DH (BX_CPU_THIS_PTR gen_reg[2].word.byte.rh) #define BH (BX_CPU_THIS_PTR gen_reg[3].word.byte.rh) #define TMP8L (BX_CPU_THIS_PTR gen_reg[BX_TMP_REGISTER].word.byte.rl) // access to 16 bit general registers #define AX (BX_CPU_THIS_PTR gen_reg[0].word.rx) #define CX (BX_CPU_THIS_PTR gen_reg[1].word.rx) #define DX (BX_CPU_THIS_PTR gen_reg[2].word.rx) #define BX (BX_CPU_THIS_PTR gen_reg[3].word.rx) #define SP (BX_CPU_THIS_PTR gen_reg[4].word.rx) #define BP (BX_CPU_THIS_PTR gen_reg[5].word.rx) #define SI (BX_CPU_THIS_PTR gen_reg[6].word.rx) #define DI (BX_CPU_THIS_PTR gen_reg[7].word.rx) // access to 16 bit instruction pointer #define IP (BX_CPU_THIS_PTR gen_reg[BX_16BIT_REG_IP].word.rx) #define TMP16 (BX_CPU_THIS_PTR gen_reg[BX_TMP_REGISTER].word.rx) // accesss to 32 bit general registers #define EAX (BX_CPU_THIS_PTR gen_reg[0].dword.erx) #define ECX (BX_CPU_THIS_PTR gen_reg[1].dword.erx) #define EDX (BX_CPU_THIS_PTR gen_reg[2].dword.erx) #define EBX (BX_CPU_THIS_PTR gen_reg[3].dword.erx) #define ESP (BX_CPU_THIS_PTR gen_reg[4].dword.erx) #define EBP (BX_CPU_THIS_PTR gen_reg[5].dword.erx) #define ESI (BX_CPU_THIS_PTR gen_reg[6].dword.erx) #define EDI (BX_CPU_THIS_PTR gen_reg[7].dword.erx) // access to 32 bit instruction pointer #define EIP (BX_CPU_THIS_PTR gen_reg[BX_32BIT_REG_EIP].dword.erx) #define TMP32 (BX_CPU_THIS_PTR gen_reg[BX_TMP_REGISTER].dword.erx) #if BX_SUPPORT_X86_64 // accesss to 64 bit general registers #define RAX (BX_CPU_THIS_PTR gen_reg[0].rrx) #define RCX (BX_CPU_THIS_PTR gen_reg[1].rrx) #define RDX (BX_CPU_THIS_PTR gen_reg[2].rrx) #define RBX (BX_CPU_THIS_PTR gen_reg[3].rrx) #define RSP (BX_CPU_THIS_PTR gen_reg[4].rrx) #define RBP (BX_CPU_THIS_PTR gen_reg[5].rrx) #define RSI (BX_CPU_THIS_PTR gen_reg[6].rrx) #define RDI (BX_CPU_THIS_PTR gen_reg[7].rrx) #define R8 (BX_CPU_THIS_PTR gen_reg[8].rrx) #define R9 (BX_CPU_THIS_PTR gen_reg[9].rrx) #define R10 (BX_CPU_THIS_PTR gen_reg[10].rrx) #define R11 (BX_CPU_THIS_PTR gen_reg[11].rrx) #define R12 (BX_CPU_THIS_PTR gen_reg[12].rrx) #define R13 (BX_CPU_THIS_PTR gen_reg[13].rrx) #define R14 (BX_CPU_THIS_PTR gen_reg[14].rrx) #define R15 (BX_CPU_THIS_PTR gen_reg[15].rrx) // access to 64 bit instruction pointer #define RIP (BX_CPU_THIS_PTR gen_reg[BX_64BIT_REG_RIP].rrx) #define TMP64 (BX_CPU_THIS_PTR gen_reg[BX_TMP_REGISTER].rrx) #define PREV_RIP (BX_CPU_THIS_PTR prev_rip) // access to 64 bit MSR registers #define MSR_FSBASE (BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base) #define MSR_GSBASE (BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base) #define MSR_LSTAR (BX_CPU_THIS_PTR msr.lstar) #define MSR_CSTAR (BX_CPU_THIS_PTR msr.cstar) #define MSR_FMASK (BX_CPU_THIS_PTR msr.fmask) #define MSR_KERNELGSBASE (BX_CPU_THIS_PTR msr.kernelgsbase) #define MSR_TSC_AUX (BX_CPU_THIS_PTR msr.tsc_aux) #else // simplify merge between 32-bit and 64-bit mode #define RAX EAX #define RCX ECX #define RDX EDX #define RBX EBX #define RSP ESP #define RBP EBP #define RSI ESI #define RDI EDI #define RIP EIP #endif // BX_SUPPORT_X86_64 == 0 #if BX_SUPPORT_X86_64 #define BX_READ_8BIT_REGx(index,extended) ((((index) & 4) == 0 || (extended)) ? \ (BX_CPU_THIS_PTR gen_reg[index].word.byte.rl) : \ (BX_CPU_THIS_PTR gen_reg[(index)-4].word.byte.rh)) #define BX_READ_64BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].rrx) #define BX_READ_64BIT_REG_HIGH(index) (BX_CPU_THIS_PTR gen_reg[index].dword.hrx) #else #define BX_READ_8BIT_REG(index) (((index) & 4) ? \ (BX_CPU_THIS_PTR gen_reg[(index)-4].word.byte.rh) : \ (BX_CPU_THIS_PTR gen_reg[index].word.byte.rl)) #define BX_READ_8BIT_REGx(index,ext) BX_READ_8BIT_REG(index) #endif #define BX_READ_8BIT_REGH(index) (BX_CPU_THIS_PTR gen_reg[index].word.byte.rh) #define BX_READ_16BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].word.rx) #define BX_READ_32BIT_REG(index) (BX_CPU_THIS_PTR gen_reg[index].dword.erx) #define BX_WRITE_8BIT_REGH(index, val) {\ BX_CPU_THIS_PTR gen_reg[index].word.byte.rh = val; \ } #define BX_WRITE_16BIT_REG(index, val) {\ BX_CPU_THIS_PTR gen_reg[index].word.rx = val; \ } /* #define BX_WRITE_32BIT_REG(index, val) {\ BX_CPU_THIS_PTR gen_reg[index].dword.erx = val; \ } */ #if BX_SUPPORT_X86_64 #define BX_WRITE_8BIT_REGx(index, extended, val) {\ if (((index) & 4) == 0 || (extended)) \ BX_CPU_THIS_PTR gen_reg[index].word.byte.rl = val; \ else \ BX_CPU_THIS_PTR gen_reg[(index)-4].word.byte.rh = val; \ } #define BX_WRITE_32BIT_REGZ(index, val) {\ BX_CPU_THIS_PTR gen_reg[index].rrx = (Bit32u) val; \ } #define BX_WRITE_64BIT_REG(index, val) {\ BX_CPU_THIS_PTR gen_reg[index].rrx = val; \ } #define BX_CLEAR_64BIT_HIGH(index) {\ BX_CPU_THIS_PTR gen_reg[index].dword.hrx = 0; \ } #else #define BX_WRITE_8BIT_REG(index, val) {\ if ((index) & 4) \ BX_CPU_THIS_PTR gen_reg[(index)-4].word.byte.rh = val; \ else \ BX_CPU_THIS_PTR gen_reg[index].word.byte.rl = val; \ } #define BX_WRITE_8BIT_REGx(index, ext, val) BX_WRITE_8BIT_REG(index, val) // For x86-32, I just pretend this one is like the macro above, // so common code can be used. #define BX_WRITE_32BIT_REGZ(index, val) {\ BX_CPU_THIS_PTR gen_reg[index].dword.erx = (Bit32u) val; \ } #define BX_CLEAR_64BIT_HIGH(index) #endif #define CPL (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl) #define USER_PL (BX_CPU_THIS_PTR user_pl) /* CPL == 3 */ #if BX_SUPPORT_SMP #define BX_CPU_ID (BX_CPU_THIS_PTR bx_cpuid) #else #define BX_CPU_ID (0) #endif #endif // defined(NEED_CPU_REG_SHORTCUTS) // // possible types passed to BX_INSTR_TLB_CNTRL() #define BX_INSTR_MOV_CR0 10 #define BX_INSTR_MOV_CR3 11 #define BX_INSTR_MOV_CR4 12 #define BX_INSTR_TASK_SWITCH 13 #define BX_INSTR_CONTEXT_SWITCH 14 #define BX_INSTR_INVLPG 15 #define BX_INSTR_INVEPT 16 #define BX_INSTR_INVVPID 17 #define BX_INSTR_INVPCID 18 // possible types passed to BX_INSTR_CACHE_CNTRL() #define BX_INSTR_INVD 10 #define BX_INSTR_WBINVD 11 // possible types passed to BX_INSTR_FAR_BRANCH() and BX_INSTR_UCNEAR_BRANCH() #define BX_INSTR_IS_JMP 10 #define BX_INSTR_IS_JMP_INDIRECT 11 #define BX_INSTR_IS_CALL 12 #define BX_INSTR_IS_CALL_INDIRECT 13 #define BX_INSTR_IS_RET 14 #define BX_INSTR_IS_IRET 15 #define BX_INSTR_IS_INT 16 #define BX_INSTR_IS_SYSCALL 17 #define BX_INSTR_IS_SYSRET 18 #define BX_INSTR_IS_SYSENTER 19 #define BX_INSTR_IS_SYSEXIT 20 // possible types passed to BX_INSTR_PREFETCH_HINT() #define BX_INSTR_PREFETCH_NTA 0 #define BX_INSTR_PREFETCH_T0 1 #define BX_INSTR_PREFETCH_T1 2 #define BX_INSTR_PREFETCH_T2 3 // // passed to internal debugger together with BX_READ/BX_WRITE/BX_EXECUTE/BX_RW enum { BX_PDPTR0_ACCESS = 1, BX_PDPTR1_ACCESS, BX_PDPTR2_ACCESS, BX_PDPTR3_ACCESS, BX_PTE_ACCESS, BX_PDE_ACCESS, BX_PDTE_ACCESS, BX_PML4E_ACCESS, BX_EPT_PTE_ACCESS, BX_EPT_PDE_ACCESS, BX_EPT_PDTE_ACCESS, BX_EPT_PML4E_ACCESS, BX_VMCS_ACCESS, BX_MSR_BITMAP_ACCESS, BX_IO_BITMAP_ACCESS, BX_VMX_LOAD_MSR_ACCESS, BX_VMX_STORE_MSR_ACCESS, BX_VMX_VTPR_ACCESS, BX_SMRAM_ACCESS }; struct BxExceptionInfo { unsigned exception_type; unsigned exception_class; bx_bool push_error; }; #define BX_DE_EXCEPTION 0 // Divide Error (fault) #define BX_DB_EXCEPTION 1 // Debug (fault/trap) #define BX_BP_EXCEPTION 3 // Breakpoint (trap) #define BX_OF_EXCEPTION 4 // Overflow (trap) #define BX_BR_EXCEPTION 5 // BOUND (fault) #define BX_UD_EXCEPTION 6 #define BX_NM_EXCEPTION 7 #define BX_DF_EXCEPTION 8 #define BX_TS_EXCEPTION 10 #define BX_NP_EXCEPTION 11 #define BX_SS_EXCEPTION 12 #define BX_GP_EXCEPTION 13 #define BX_PF_EXCEPTION 14 #define BX_MF_EXCEPTION 16 #define BX_AC_EXCEPTION 17 #define BX_MC_EXCEPTION 18 #define BX_XM_EXCEPTION 19 #define BX_CPU_HANDLED_EXCEPTIONS 32 /* MSR registers */ #define BX_MSR_TSC 0x010 #define BX_MSR_APICBASE 0x01b #if BX_CPU_LEVEL >= 6 #define BX_MSR_SYSENTER_CS 0x174 #define BX_MSR_SYSENTER_ESP 0x175 #define BX_MSR_SYSENTER_EIP 0x176 #endif #define BX_MSR_DEBUGCTLMSR 0x1d9 #define BX_MSR_LASTBRANCHFROMIP 0x1db #define BX_MSR_LASTBRANCHTOIP 0x1dc #define BX_MSR_LASTINTOIP 0x1dd #if BX_CPU_LEVEL >= 6 #define BX_MSR_MTRRCAP 0x0fe #define BX_MSR_MTRRPHYSBASE0 0x200 #define BX_MSR_MTRRPHYSMASK0 0x201 #define BX_MSR_MTRRPHYSBASE1 0x202 #define BX_MSR_MTRRPHYSMASK1 0x203 #define BX_MSR_MTRRPHYSBASE2 0x204 #define BX_MSR_MTRRPHYSMASK2 0x205 #define BX_MSR_MTRRPHYSBASE3 0x206 #define BX_MSR_MTRRPHYSMASK3 0x207 #define BX_MSR_MTRRPHYSBASE4 0x208 #define BX_MSR_MTRRPHYSMASK4 0x209 #define BX_MSR_MTRRPHYSBASE5 0x20a #define BX_MSR_MTRRPHYSMASK5 0x20b #define BX_MSR_MTRRPHYSBASE6 0x20c #define BX_MSR_MTRRPHYSMASK6 0x20d #define BX_MSR_MTRRPHYSBASE7 0x20e #define BX_MSR_MTRRPHYSMASK7 0x20f #define BX_MSR_MTRRFIX64K_00000 0x250 #define BX_MSR_MTRRFIX16K_80000 0x258 #define BX_MSR_MTRRFIX16K_A0000 0x259 #define BX_MSR_MTRRFIX4K_C0000 0x268 #define BX_MSR_MTRRFIX4K_C8000 0x269 #define BX_MSR_MTRRFIX4K_D0000 0x26a #define BX_MSR_MTRRFIX4K_D8000 0x26b #define BX_MSR_MTRRFIX4K_E0000 0x26c #define BX_MSR_MTRRFIX4K_E8000 0x26d #define BX_MSR_MTRRFIX4K_F0000 0x26e #define BX_MSR_MTRRFIX4K_F8000 0x26f #define BX_MSR_PAT 0x277 #define BX_MSR_MTRR_DEFTYPE 0x2ff #endif #define BX_MSR_TSC_DEADLINE 0x6E0 #define BX_MSR_MAX_INDEX 0x1000 enum { BX_MEMTYPE_UC = 0, BX_MEMTYPE_WC, BX_MEMTYPE_RESERVED2, BX_MEMTYPE_RESERVED3, BX_MEMTYPE_WT, BX_MEMTYPE_WP, BX_MEMTYPE_WB }; #if BX_SUPPORT_VMX #define BX_MSR_VMX_BASIC 0x480 #define BX_MSR_VMX_PINBASED_CTRLS 0x481 #define BX_MSR_VMX_PROCBASED_CTRLS 0x482 #define BX_MSR_VMX_VMEXIT_CTRLS 0x483 #define BX_MSR_VMX_VMENTRY_CTRLS 0x484 #define BX_MSR_VMX_MISC 0x485 #define BX_MSR_VMX_CR0_FIXED0 0x486 #define BX_MSR_VMX_CR0_FIXED1 0x487 #define BX_MSR_VMX_CR4_FIXED0 0x488 #define BX_MSR_VMX_CR4_FIXED1 0x489 #define BX_MSR_VMX_VMCS_ENUM 0x48a #define BX_MSR_VMX_PROCBASED_CTRLS2 0x48b #define BX_MSR_VMX_EPT_VPID_CAP 0x48c #define BX_MSR_VMX_TRUE_PINBASED_CTRLS 0x48d #define BX_MSR_VMX_TRUE_PROCBASED_CTRLS 0x48e #define BX_MSR_VMX_TRUE_VMEXIT_CTRLS 0x48f #define BX_MSR_VMX_TRUE_VMENTRY_CTRLS 0x490 #define BX_MSR_VMX_VMFUNC 0x491 #define BX_MSR_IA32_FEATURE_CONTROL 0x03A #define BX_MSR_IA32_SMM_MONITOR_CTL 0x09B #endif #define BX_MSR_EFER 0xc0000080 #define BX_MSR_STAR 0xc0000081 #define BX_MSR_LSTAR 0xc0000082 #define BX_MSR_CSTAR 0xc0000083 #define BX_MSR_FMASK 0xc0000084 #define BX_MSR_FSBASE 0xc0000100 #define BX_MSR_GSBASE 0xc0000101 #define BX_MSR_KERNELGSBASE 0xc0000102 #define BX_MSR_TSC_AUX 0xc0000103 #define BX_SVM_VM_CR_MSR 0xc0010114 #define BX_SVM_IGNNE_MSR 0xc0010115 #define BX_SVM_SMM_CTL_MSR 0xc0010116 #define BX_SVM_HSAVE_PA_MSR 0xc0010117 #define BX_MODE_IA32_REAL 0x0 // CR0.PE=0 | #define BX_MODE_IA32_V8086 0x1 // CR0.PE=1, EFLAGS.VM=1 | EFER.LMA=0 #define BX_MODE_IA32_PROTECTED 0x2 // CR0.PE=1, EFLAGS.VM=0 | #define BX_MODE_LONG_COMPAT 0x3 // EFER.LMA = 1, CR0.PE=1, CS.L=0 #define BX_MODE_LONG_64 0x4 // EFER.LMA = 1, CR0.PE=1, CS.L=1 extern const char* cpu_mode_string(unsigned cpu_mode); #if BX_SUPPORT_X86_64 #define IsCanonical(offset) ((Bit64u)((((Bit64s)(offset)) >> (BX_LIN_ADDRESS_WIDTH-1)) + 1) < 2) #endif #define IsValidPhyAddr(addr) ((addr & BX_PHY_ADDRESS_RESERVED_BITS) == 0) #if BX_SUPPORT_APIC #define BX_CPU_INTR (BX_CPU_THIS_PTR INTR || BX_CPU_THIS_PTR lapic.INTR) #else #define BX_CPU_INTR (BX_CPU_THIS_PTR INTR) #endif #define CACHE_LINE_SIZE 64 class BX_CPU_C; class BX_MEM_C; #if BX_USE_CPU_SMF == 0 // normal member functions. This can ONLY be used within BX_CPU_C classes. // Anyone on the outside should use the BX_CPU macro (defined in bochs.h) // instead. # define BX_CPU_THIS_PTR this-> # define BX_CPU_THIS this # define BX_SMF // with normal member functions, calling a member fn pointer looks like // object->*(fnptr)(arg, ...); // Since this is different from when SMF=1, encapsulate it in a macro. # define BX_CPU_CALL_METHOD(func, args) \ (this->*((BxExecutePtr_tR) (func))) args # define BX_CPU_CALL_METHODR(func, args) \ (this->*((BxResolvePtr_tR) (func))) args # define BX_CPU_CALL_REP_ITERATION(func, args) \ (this->*((BxRepIterationPtr_tR) (func))) args #else // static member functions. With SMF, there is only one CPU by definition. # define BX_CPU_THIS_PTR BX_CPU(0)-> # define BX_CPU_THIS BX_CPU(0) # define BX_SMF static # define BX_CPU_CALL_METHOD(func, args) \ ((BxExecutePtr_tR) (func)) args # define BX_CPU_CALL_METHODR(func, args) \ ((BxResolvePtr_tR) (func)) args # define BX_CPU_CALL_REP_ITERATION(func, args) \ ((BxRepIterationPtr_tR) (func)) args #endif #if BX_SUPPORT_SMP // multiprocessor simulation, we need an array of cpus and memories BOCHSAPI extern BX_CPU_C **bx_cpu_array; #else // single processor simulation, so there's one of everything BOCHSAPI extern BX_CPU_C bx_cpu; #endif // notify internal debugger/instrumentation about memory access #define BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, paddr, size, pl, rw, dataptr) { \ BX_INSTR_LIN_ACCESS(BX_CPU_ID, (laddr), (paddr), (size), (rw)); \ BX_DBG_LIN_MEMORY_ACCESS(BX_CPU_ID, (laddr), (paddr), (size), (pl), (rw), (dataptr)); \ } #define BX_NOTIFY_PHY_MEMORY_ACCESS(paddr, size, rw, why, dataptr) { \ BX_INSTR_PHY_ACCESS(BX_CPU_ID, (paddr), (size), (rw)); \ BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, (paddr), (size), (rw), (why), (dataptr)); \ } // accessors for all eflags in bx_flags_reg_t // The macro is used once for each flag bit // Do not use for arithmetic flags ! #define DECLARE_EFLAG_ACCESSOR(name,bitnum) \ BX_SMF BX_CPP_INLINE Bit32u get_##name (); \ BX_SMF BX_CPP_INLINE bx_bool getB_##name (); \ BX_SMF BX_CPP_INLINE void assert_##name (); \ BX_SMF BX_CPP_INLINE void clear_##name (); \ BX_SMF BX_CPP_INLINE void set_##name (bx_bool val); #define IMPLEMENT_EFLAG_ACCESSOR(name,bitnum) \ BX_CPP_INLINE bx_bool BX_CPU_C::getB_##name () { \ return 1 & (BX_CPU_THIS_PTR eflags >> bitnum); \ } \ BX_CPP_INLINE Bit32u BX_CPU_C::get_##name () { \ return BX_CPU_THIS_PTR eflags & (1 << bitnum); \ } #define IMPLEMENT_EFLAG_SET_ACCESSOR(name,bitnum) \ BX_CPP_INLINE void BX_CPU_C::assert_##name () { \ BX_CPU_THIS_PTR eflags |= (1<= 4 #define IMPLEMENT_EFLAG_SET_ACCESSOR_AC(bitnum) \ BX_CPP_INLINE void BX_CPU_C::assert_AC () { \ BX_CPU_THIS_PTR eflags |= (1<> 12); \ } #define EFlagsCFMask (1 << 0) #define EFlagsPFMask (1 << 2) #define EFlagsAFMask (1 << 4) #define EFlagsZFMask (1 << 6) #define EFlagsSFMask (1 << 7) #define EFlagsTFMask (1 << 8) #define EFlagsIFMask (1 << 9) #define EFlagsDFMask (1 << 10) #define EFlagsOFMask (1 << 11) #define EFlagsIOPLMask (3 << 12) #define EFlagsNTMask (1 << 14) #define EFlagsRFMask (1 << 16) #define EFlagsVMMask (1 << 17) #define EFlagsACMask (1 << 18) #define EFlagsVIFMask (1 << 19) #define EFlagsVIPMask (1 << 20) #define EFlagsIDMask (1 << 21) #define EFlagsOSZAPCMask \ (EFlagsCFMask | EFlagsPFMask | EFlagsAFMask | EFlagsZFMask | EFlagsSFMask | EFlagsOFMask) #define EFlagsOSZAPMask \ (EFlagsPFMask | EFlagsAFMask | EFlagsZFMask | EFlagsSFMask | EFlagsOFMask) #define EFlagsValidMask 0x003f7fd5 // only supported bits for EFLAGS #if BX_CPU_LEVEL >= 5 typedef struct { #if BX_SUPPORT_APIC bx_phy_address apicbase; #endif #define MSR_STAR (BX_CPU_THIS_PTR msr.star) // SYSCALL/SYSRET instruction msr's Bit64u star; #if BX_SUPPORT_X86_64 Bit64u lstar; Bit64u cstar; Bit32u fmask; Bit64u kernelgsbase; Bit32u tsc_aux; #endif #if BX_CPU_LEVEL >= 6 // SYSENTER/SYSEXIT instruction msr's Bit32u sysenter_cs_msr; bx_address sysenter_esp_msr; bx_address sysenter_eip_msr; Bit64u mtrrphys[16]; Bit64u mtrrfix64k_00000; Bit64u mtrrfix16k[2]; Bit64u mtrrfix4k[8]; Bit16u mtrr_deftype; Bit64u pat; #endif #if BX_SUPPORT_VMX Bit32u ia32_feature_ctrl; #endif #if BX_SUPPORT_SVM Bit64u svm_hsave_pa; #endif /* TODO finish of the others */ } bx_regs_msr_t; #endif #include "cpuid.h" #include "crregs.h" #include "descriptor.h" #include "instr.h" #include "lazy_flags.h" // BX_TLB_SIZE: Number of entries in TLB // BX_TLB_INDEX_OF(lpf): This macro is passed the linear page frame // (top 20 bits of the linear address. It must map these bits to // one of the TLB cache slots, given the size of BX_TLB_SIZE. // There will be a many-to-one mapping to each TLB cache slot. // When there are collisions, the old entry is overwritten with // one for the newest access. #define BX_TLB_SIZE 1024 #define BX_TLB_MASK ((BX_TLB_SIZE-1) << 12) #define BX_TLB_INDEX_OF(lpf, len) ((((unsigned)(lpf) + (len)) & BX_TLB_MASK) >> 12) typedef bx_ptr_equiv_t bx_hostpageaddr_t; typedef struct { bx_address lpf; // linear page frame bx_phy_address ppf; // physical page frame bx_hostpageaddr_t hostPageAddr; Bit32u accessBits; Bit32u lpf_mask; // linear address mask of the page size } bx_TLB_entry; #if BX_SUPPORT_X86_64 #define LPF_MASK BX_CONST64(0xfffffffffffff000) #else #define LPF_MASK (0xfffff000) #endif #if BX_PHY_ADDRESS_LONG #define PPF_MASK BX_CONST64(0xfffffffffffff000) #else #define PPF_MASK (0xfffff000) #endif #define LPFOf(laddr) ((laddr) & LPF_MASK) #define PPFOf(laddr) ((laddr) & PPF_MASK) #define AlignedAccessLPFOf(laddr, alignment_mask) \ ((laddr) & (LPF_MASK | (alignment_mask))) #define PAGE_OFFSET(laddr) ((Bit32u)(laddr) & 0xfff) #include "icache.h" // general purpose register #if BX_SUPPORT_X86_64 #ifdef BX_BIG_ENDIAN typedef struct { union { struct { Bit32u dword_filler; Bit16u word_filler; union { Bit16u rx; struct { Bit8u rh; Bit8u rl; } byte; }; } word; Bit64u rrx; struct { Bit32u hrx; // hi 32 bits Bit32u erx; // lo 32 bits } dword; }; } bx_gen_reg_t; #else typedef struct { union { struct { union { Bit16u rx; struct { Bit8u rl; Bit8u rh; } byte; }; Bit16u word_filler; Bit32u dword_filler; } word; Bit64u rrx; struct { Bit32u erx; // lo 32 bits Bit32u hrx; // hi 32 bits } dword; }; } bx_gen_reg_t; #endif #else // #if BX_SUPPORT_X86_64 #ifdef BX_BIG_ENDIAN typedef struct { union { struct { Bit32u erx; } dword; struct { Bit16u word_filler; union { Bit16u rx; struct { Bit8u rh; Bit8u rl; } byte; }; } word; }; } bx_gen_reg_t; #else typedef struct { union { struct { Bit32u erx; } dword; struct { union { Bit16u rx; struct { Bit8u rl; Bit8u rh; } byte; }; Bit16u word_filler; } word; }; } bx_gen_reg_t; #endif #endif // #if BX_SUPPORT_X86_64 #if BX_SUPPORT_APIC #include "apic.h" #endif #if BX_SUPPORT_FPU #include "i387.h" #include "xmm.h" #endif #if BX_SUPPORT_VMX #include "vmx.h" #endif #if BX_SUPPORT_SVM #include "svm.h" #endif #if BX_SUPPORT_MONITOR_MWAIT struct monitor_addr_t { bx_phy_address monitor_addr; bx_bool armed; monitor_addr_t(): monitor_addr(0xffffffff), armed(0) {} BX_CPP_INLINE void arm(bx_phy_address addr) { // align to cache line monitor_addr = addr & ~((bx_phy_address)(CACHE_LINE_SIZE - 1)); armed = 1; } BX_CPP_INLINE void reset_monitor(void) { armed = 0; } }; #endif class BX_SMM_State; class BOCHSAPI BX_CPU_C : public logfunctions { public: // for now... unsigned bx_cpuid; #if BX_CPU_LEVEL >= 4 bx_cpuid_t *cpuid; #endif Bit64u isa_extensions_bitmask; Bit32u cpu_extensions_bitmask; #if BX_SUPPORT_VMX Bit32u vmx_extensions_bitmask; #endif #if BX_SUPPORT_SVM Bit32u svm_extensions_bitmask; #endif #define BX_CPUID_SUPPORT_ISA_EXTENSION(feature) \ (BX_CPU_THIS_PTR isa_extensions_bitmask & (feature)) #define BX_CPUID_SUPPORT_CPU_EXTENSION(feature) \ (BX_CPU_THIS_PTR cpu_extensions_bitmask & (feature)) #define BX_SUPPORT_VMX_EXTENSION(feature) \ (BX_CPU_THIS_PTR vmx_extensions_bitmask & (feature)) #define BX_SUPPORT_SVM_EXTENSION(feature) \ (BX_CPU_THIS_PTR svm_extensions_bitmask & (feature)) // General register set // rax: accumulator // rbx: base // rcx: count // rdx: data // rbp: base pointer // rsi: source index // rdi: destination index // esp: stack pointer // r8..r15 x86-64 extended registers // rip: instruction pointer // nil: null register // tmp: temp register bx_gen_reg_t gen_reg[BX_GENERAL_REGISTERS+3]; /* 31|30|29|28| 27|26|25|24| 23|22|21|20| 19|18|17|16 * ==|==|=====| ==|==|==|==| ==|==|==|==| ==|==|==|== * 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|ID|VP| VF|AC|VM|RF * * 15|14|13|12| 11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0 * ==|==|=====| ==|==|==|==| ==|==|==|==| ==|==|==|== * 0|NT| IOPL| OF|DF|IF|TF| SF|ZF| 0|AF| 0|PF| 1|CF */ Bit32u eflags; // Raw 32-bit value in x86 bit position. // lazy arithmetic flags state bx_lf_flags_entry oszapc; // so that we can back up when handling faults, exceptions, etc. // we need to store the value of the instruction pointer, before // each fetch/execute cycle. bx_address prev_rip; bx_address prev_rsp; bx_bool speculative_rsp; Bit64u icount; Bit64u icount_last_sync; #define BX_INHIBIT_INTERRUPTS 0x01 #define BX_INHIBIT_DEBUG 0x02 #define BX_INHIBIT_INTERRUPTS_BY_MOVSS \ (BX_INHIBIT_INTERRUPTS | BX_INHIBIT_DEBUG) // What events to inhibit at any given time. Certain instructions // inhibit interrupts, some debug exceptions and single-step traps. unsigned inhibit_mask; Bit64u inhibit_icount; /* user segment register set */ bx_segment_reg_t sregs[6]; /* system segment registers */ bx_global_segment_reg_t gdtr; /* global descriptor table register */ bx_global_segment_reg_t idtr; /* interrupt descriptor table register */ bx_segment_reg_t ldtr; /* local descriptor table register */ bx_segment_reg_t tr; /* task register */ /* debug registers DR0-DR7 */ bx_address dr[4]; /* DR0-DR3 */ bx_dr6_t dr6; bx_dr7_t dr7; Bit32u debug_trap; // holds DR6 value (16bit) to be set /* Control registers */ bx_cr0_t cr0; bx_address cr2; bx_address cr3; #if BX_CPU_LEVEL >= 5 bx_cr4_t cr4; Bit32u cr4_suppmask; bx_efer_t efer; Bit32u efer_suppmask; #endif #if BX_CPU_LEVEL >= 5 // TSC: Time Stamp Counter // Instead of storing a counter and incrementing it every instruction, we // remember the time in ticks that it was reset to zero. With a little // algebra, we can also support setting it to something other than zero. // Don't read this directly; use get_TSC and set_TSC to access the TSC. Bit64u tsc_last_reset; #if BX_SUPPORT_VMX || BX_SUPPORT_SVM Bit64s tsc_offset; #endif #endif #if BX_CPU_LEVEL >= 6 xcr0_t xcr0; Bit32u xcr0_suppmask; #endif /* SMM base register */ Bit32u smbase; #if BX_CPU_LEVEL >= 5 bx_regs_msr_t msr; #endif #if BX_CONFIGURE_MSRS MSR *msrs[BX_MSR_MAX_INDEX]; #endif #if BX_SUPPORT_FPU i387_t the_i387; #endif #if BX_CPU_LEVEL >= 6 #if BX_SUPPORT_AVX bx_avx_reg_t vmm[BX_XMM_REGISTERS+1]; #else bx_xmm_reg_t vmm[BX_XMM_REGISTERS+1]; #endif bx_mxcsr_t mxcsr; Bit32u mxcsr_mask; #endif #if BX_SUPPORT_MONITOR_MWAIT monitor_addr_t monitor; #endif #if BX_SUPPORT_APIC bx_local_apic_c lapic; #endif #if BX_SUPPORT_VMX bx_bool in_vmx; bx_bool in_vmx_guest; bx_bool in_smm_vmx; // save in_vmx and in_vmx_guest flags when in SMM mode bx_bool in_smm_vmx_guest; bx_bool vmx_interrupt_window; #if BX_SUPPORT_VMX >= 2 bx_bool pending_vmx_timer_expired; #endif Bit64u vmcsptr; bx_hostpageaddr_t vmcshostptr; Bit64u vmxonptr; VMCS_CACHE vmcs; VMX_CAP vmx_cap; #endif #if BX_SUPPORT_SVM bx_bool in_svm_guest; bx_bool svm_gif; /* global interrupt enable flag, when zero all external interrupt disabled */ bx_phy_address vmcbptr; bx_hostpageaddr_t vmcbhostptr; VMCB_CACHE vmcb; // make SVM integration easier #define SVM_GIF (BX_CPU_THIS_PTR svm_gif) #else #define SVM_GIF (1) #endif #if BX_SUPPORT_VMX || BX_SUPPORT_SVM bx_bool in_event; #endif bx_bool EXT; /* 1 if processing external interrupt or exception * or if not related to current instruction, * 0 if current CS:IP caused exception */ unsigned errorno; /* signal exception during instruction emulation */ #define BX_ACTIVITY_STATE_ACTIVE (0) #define BX_ACTIVITY_STATE_HLT (1) #define BX_ACTIVITY_STATE_SHUTDOWN (2) #define BX_ACTIVITY_STATE_WAIT_FOR_SIPI (3) #define BX_ACTIVITY_STATE_MWAIT (4) #define BX_ACTIVITY_STATE_MWAIT_IF (5) unsigned activity_state; Bit32u async_event; #define BX_ASYNC_EVENT_STOP_TRACE (0x80000000) #if BX_X86_DEBUGGER bx_bool in_repeat; bx_bool codebp; #endif bx_bool in_smm; unsigned cpu_mode; bx_bool user_pl; bx_bool INTR; bx_bool pending_SMI; bx_bool pending_NMI; bx_bool pending_INIT; bx_bool disable_SMI; bx_bool disable_NMI; bx_bool disable_INIT; #if BX_CPU_LEVEL >= 5 bx_bool ignore_bad_msrs; #endif #if BX_CPU_LEVEL >= 6 unsigned sse_ok; #if BX_SUPPORT_AVX unsigned avx_ok; #endif #endif // for exceptions jmp_buf jmp_buf_env; Bit8u curr_exception; // Boundaries of current code page, based on EIP bx_address eipPageBias; Bit32u eipPageWindowSize; const Bit8u *eipFetchPtr; bx_phy_address pAddrFetchPage; // Guest physical address of current instruction page // Boundaries of current stack page, based on ESP bx_address espPageBias; // Linear address of current stack page Bit32u espPageWindowSize; const Bit8u *espHostPtr; bx_phy_address pAddrStackPage; // Guest physical address of current stack page #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK unsigned alignment_check_mask; #endif #if BX_DEBUGGER bx_phy_address watchpoint; Bit8u break_point; Bit8u magic_break; Bit8u stop_reason; bx_bool trace; bx_bool trace_reg; bx_bool trace_mem; bx_bool mode_break; #if BX_SUPPORT_VMX bx_bool vmexit_break; #endif unsigned show_flag; bx_guard_found_t guard_found; #endif // for paging struct { bx_TLB_entry entry[BX_TLB_SIZE] BX_CPP_AlignN(16); #if BX_CPU_LEVEL >= 5 bx_bool split_large; #endif } TLB; #if BX_CPU_LEVEL >= 6 struct { Bit64u entry[4]; } PDPTR_CACHE; #endif // An instruction cache. Each entry should be exactly 32 bytes, and // this structure should be aligned on a 32-byte boundary to be friendly // with the host cache lines. bxICache_c iCache BX_CPP_AlignN(32); Bit32u fetchModeMask; struct { bx_address rm_addr; // The address offset after resolution bx_phy_address paddress1; // physical address after translation of 1st len1 bytes of data bx_phy_address paddress2; // physical address after translation of 2nd len2 bytes of data Bit32u len1; // Number of bytes in page 1 Bit32u len2; // Number of bytes in page 2 bx_ptr_equiv_t pages; // Number of pages access spans (1 or 2). Also used // for the case when a native host pointer is // available for the R-M-W instructions. The host // pointer is stuffed here. Since this field has // to be checked anyways (and thus cached), if it // is greated than 2 (the maximum possible for // normal cases) it is a native pointer and is used // for a direct write access. } address_xlation; BX_SMF void setEFlags(Bit32u val) BX_CPP_AttrRegparmN(1); BX_SMF BX_CPP_INLINE void setEFlagsOSZAPC(Bit32u flags32) { set_OF(1 & ((flags32) >> 11)); set_SF(1 & ((flags32) >> 7)); set_ZF(1 & ((flags32) >> 6)); set_AF(1 & ((flags32) >> 4)); set_PF(1 & ((flags32) >> 2)); set_CF(1 & ((flags32) >> 0)); } BX_SMF BX_CPP_INLINE void SET_FLAGS_OxxxxC(Bit32u new_of, Bit32u new_cf) { Bit32u temp_po = new_of ^ new_cf; BX_CPU_THIS_PTR oszapc.auxbits &= ~(LF_MASK_PO | LF_MASK_CF); BX_CPU_THIS_PTR oszapc.auxbits |= (temp_po << LF_BIT_PO) | (new_cf << LF_BIT_CF); } BX_SMF BX_CPP_INLINE void ASSERT_FLAGS_OxxxxC() { SET_FLAGS_OxxxxC(1, 1); } // ZF BX_SMF BX_CPP_INLINE bx_bool getB_ZF(void) { return (0 == BX_CPU_THIS_PTR oszapc.result); } BX_SMF BX_CPP_INLINE bx_bool get_ZF(void) { return getB_ZF(); } BX_SMF BX_CPP_INLINE void set_ZF(bx_bool val) { if (val) assert_ZF(); else clear_ZF(); } BX_SMF BX_CPP_INLINE void clear_ZF(void) { BX_CPU_THIS_PTR oszapc.result |= (1 << 8); } BX_SMF BX_CPP_INLINE void assert_ZF(void) { // merge the sign bit into the Sign Delta BX_CPU_THIS_PTR oszapc.auxbits ^= (((BX_CPU_THIS_PTR oszapc.result >> BX_LF_SIGN_BIT) & 1) << LF_BIT_SD); // merge the parity bits into the Parity Delta Byte Bit32u temp_pdb = (255 & BX_CPU_THIS_PTR oszapc.result); BX_CPU_THIS_PTR oszapc.auxbits ^= (temp_pdb << LF_BIT_PDB); // now zero the .result value BX_CPU_THIS_PTR oszapc.result = 0; } // SF BX_SMF BX_CPP_INLINE bx_bool getB_SF(void) { return ((BX_CPU_THIS_PTR oszapc.result >> BX_LF_SIGN_BIT) ^ (BX_CPU_THIS_PTR oszapc.auxbits >> LF_BIT_SD)) & 1; } BX_SMF BX_CPP_INLINE bx_bool get_SF(void) { return getB_SF(); } BX_SMF BX_CPP_INLINE void set_SF(bx_bool val) { bx_bool temp_sf = getB_SF(); BX_CPU_THIS_PTR oszapc.auxbits ^= (temp_sf ^ val) << LF_BIT_SD; } BX_SMF BX_CPP_INLINE void clear_SF(void) { set_SF(0); } BX_SMF BX_CPP_INLINE void assert_SF(void) { set_SF(1); } // PF - bit 2 in EFLAGS, represented by lower 8 bits of oszapc.result BX_SMF BX_CPP_INLINE bx_bool getB_PF(void) { Bit32u temp = (255 & BX_CPU_THIS_PTR oszapc.result); temp = temp ^ (255 & (BX_CPU_THIS_PTR oszapc.auxbits >> LF_BIT_PDB)); temp = (temp ^ (temp >> 4)) & 0x0F; return (0x9669U >> temp) & 1; } BX_SMF BX_CPP_INLINE bx_bool get_PF(void) { return getB_PF(); } BX_SMF BX_CPP_INLINE void set_PF(bx_bool val) { Bit32u temp_pdb = (255 & BX_CPU_THIS_PTR oszapc.result) ^ (!val); BX_CPU_THIS_PTR oszapc.auxbits &= ~(LF_MASK_PDB); BX_CPU_THIS_PTR oszapc.auxbits |= (temp_pdb << LF_BIT_PDB); } BX_SMF BX_CPP_INLINE void clear_PF(void) { set_PF(0); } BX_SMF BX_CPP_INLINE void assert_PF(void) { set_PF(1); } // AF - bit 4 in EFLAGS, represented by bit LF_BIT_AF of oszapc.auxbits BX_SMF BX_CPP_INLINE bx_bool getB_AF(void) { return ((BX_CPU_THIS_PTR oszapc.auxbits >> LF_BIT_AF) & 1); } BX_SMF BX_CPP_INLINE bx_bool get_AF(void) { return getB_AF(); } BX_SMF BX_CPP_INLINE void set_AF(bx_bool val) { BX_CPU_THIS_PTR oszapc.auxbits &= ~(LF_MASK_AF); BX_CPU_THIS_PTR oszapc.auxbits |= (val) << LF_BIT_AF; } BX_SMF BX_CPP_INLINE void clear_AF(void) { BX_CPU_THIS_PTR oszapc.auxbits &= ~(LF_MASK_AF); } BX_SMF BX_CPP_INLINE void assert_AF(void) { BX_CPU_THIS_PTR oszapc.auxbits |= (LF_MASK_AF); } // CF BX_SMF BX_CPP_INLINE bx_bool getB_CF(void) { return ((BX_CPU_THIS_PTR oszapc.auxbits >> LF_BIT_CF) & 1); } BX_SMF BX_CPP_INLINE bx_bool get_CF(void) { return BX_CPU_THIS_PTR oszapc.auxbits & (1U << LF_BIT_CF); } BX_SMF BX_CPP_INLINE void set_CF(bx_bool val) { bx_bool temp_of = getB_OF(); SET_FLAGS_OxxxxC(temp_of, (val)); } BX_SMF BX_CPP_INLINE void clear_CF(void) { bx_bool temp_of = getB_OF(); SET_FLAGS_OxxxxC(temp_of, (0)); } BX_SMF BX_CPP_INLINE void assert_CF(void) { bx_bool temp_of = getB_OF(); SET_FLAGS_OxxxxC(temp_of, (1)); } // OF BX_SMF BX_CPP_INLINE bx_bool getB_OF(void) { return ((BX_CPU_THIS_PTR oszapc.auxbits + (1U << LF_BIT_PO)) >> LF_BIT_CF) & 1; } BX_SMF BX_CPP_INLINE bx_bool get_OF(void) { return (BX_CPU_THIS_PTR oszapc.auxbits + (1U << LF_BIT_PO)) & (1U << LF_BIT_CF); } BX_SMF BX_CPP_INLINE void set_OF(bx_bool val) { bx_bool temp_cf = getB_CF(); SET_FLAGS_OxxxxC((val), temp_cf); } BX_SMF BX_CPP_INLINE void clear_OF(void) { bx_bool temp_cf = getB_CF(); SET_FLAGS_OxxxxC((0), temp_cf); } BX_SMF BX_CPP_INLINE void assert_OF(void) { bx_bool temp_cf = getB_CF(); SET_FLAGS_OxxxxC((1), temp_cf); } // constructors & destructors... BX_CPU_C(unsigned id = 0); ~BX_CPU_C(); void initialize(void); void after_restore_state(void); void register_state(void); #if BX_WITH_WX void register_wx_state(void); #endif static Bit64s param_save_handler(void *devptr, bx_param_c *param); static void param_restore_handler(void *devptr, bx_param_c *param, Bit64s val); #if !BX_USE_CPU_SMF Bit64s param_save(bx_param_c *param); void param_restore(bx_param_c *param, Bit64s val); #endif // // prototypes for CPU instructions... BX_SMF BX_INSF_TYPE PUSH16_Sw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP16_Sw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH32_Sw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP32_Sw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DAA(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DAS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AAA(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AAS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AAM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AAD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSHAD32(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSHAD16(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POPAD32(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POPAD16(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ARPL_EwGw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_Id(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSB32_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSB16_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSW32_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSW16_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSD32_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSD16_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSB32_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSB16_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSW32_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSW16_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSD32_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSD16_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_INSB_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_INSW_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_INSD_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_OUTSB_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_OUTSW_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_OUTSD_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BOUND_GwMa(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BOUND_GdMa(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EbGbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EbGbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV32_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV32_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV32S_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV32S_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EwSwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EwSwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_SwEw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LEA_GdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LEA_GwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CBW(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CWD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL32_Ap(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL16_Ap(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSHF_Fw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POPF_Fw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSHF_Fd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POPF_Fd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAHF(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LAHF(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_ALOd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EAXOd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_AXOd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_OdAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_OdEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_OdAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // repeatable instructions BX_SMF BX_INSF_TYPE REP_MOVSB_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_MOVSW_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_MOVSD_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_CMPSB_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_CMPSW_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_CMPSD_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_STOSB_YbAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_LODSB_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_SCASB_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_STOSW_YwAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_LODSW_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_SCASW_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_STOSD_YdEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_LODSD_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_SCASD_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // qualified by address size BX_SMF void CMPSB16_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSW16_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSD16_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSB32_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSW32_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSD32_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASB16_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASW16_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASD16_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASB32_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASW32_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASD32_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSB16_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSW16_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSD16_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSB32_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSW32_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSD32_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSB16_YbAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSW16_YwAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSD16_YdEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSB32_YbAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSW32_YwAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSD32_YdEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSB16_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSW16_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSD16_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSB32_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSW32_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSD32_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ENTER16_IwIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ENTER32_IwIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LEAVE16(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LEAVE32(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INT1(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INT3(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INT_Ib(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INTO(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IRET32(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IRET16(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SALC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XLAT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOPNE16_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOPE16_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOP16_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOPNE32_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOPE32_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOP32_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JCXZ_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JECXZ_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IN_ALIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IN_AXIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IN_EAXIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OUT_IbAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OUT_IbAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OUT_IbEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP_Ap(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IN_ALDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IN_AXDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IN_EAXDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OUT_DXAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OUT_DXAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OUT_DXEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE HLT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CLC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE STC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CLI(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE STI(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CLD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE STD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LAR_GvEw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LSL_GvEw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CLTS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INVD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE WBINVD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CLFLUSH(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR0Rd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR2Rd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR3Rd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR4Rd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RdCR0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RdCR2(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RdCR3(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RdCR4(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_DdRd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RdDd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JO_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNO_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JB_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNB_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JZ_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNZ_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JBE_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNBE_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JS_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNS_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JP_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNP_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JL_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNL_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JLE_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNLE_Jw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JO_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNO_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JB_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNB_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JZ_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNZ_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JBE_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNBE_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JS_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNS_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JP_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNP_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JL_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNL_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JLE_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNLE_Jd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETO_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNO_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETB_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNB_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETZ_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNZ_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETBE_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNBE_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETS_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNS_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETP_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNP_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETL_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNL_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETLE_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNLE_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETO_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNO_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETB_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNB_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETZ_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNZ_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETBE_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNBE_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETS_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNS_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETP_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNP_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETL_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNL_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETLE_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SETNLE_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CPUID(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRD_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRD_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLD_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLD_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRD_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRD_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLD_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLD_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSF_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSF_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSR_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSR_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EwIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EdIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EwIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EdIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EwIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EdIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EwIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EdIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EwIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EwIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EwIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EwIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LES_GwMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LDS_GwMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LSS_GwMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LFS_GwMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LGS_GwMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LES_GdMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LDS_GdMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LSS_GdMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LFS_GdMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LGS_GdMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GwEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GdEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GdEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GwEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GdEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GdEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GwEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GdEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GdEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GwEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GdEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GdEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSWAP_RX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSWAP_ERX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GbEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GbEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GwEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EwIwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EdIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_GdEdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MUL_ALEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_ALEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIV_ALEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IDIV_ALEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MUL_EAXEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_EAXEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIV_EAXEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IDIV_EAXEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_EbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_EbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL32_Ep(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL16_Ep(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP32_Ep(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP16_Ep(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP_EdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SLDT_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE STR_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LLDT_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LTR_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VERR_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VERW_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SGDT_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SIDT_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LGDT_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LIDT_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SMSW_EwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SMSW_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LMSW_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // LOAD methods BX_SMF BX_INSF_TYPE LOAD_Eb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_Ew(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_Ed(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE LOAD_Eq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF BX_INSF_TYPE LOADU_Wdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_Wdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_Wss(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_Wsd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_Ww(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_Wb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_AVX BX_SMF BX_INSF_TYPE LOAD_Vector(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOAD_VectorQ(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif #if BX_SUPPORT_FPU == 0 // if FPU is disabled BX_SMF BX_INSF_TYPE FPU_ESC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF BX_INSF_TYPE FWAIT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_FPU // load/store BX_SMF BX_INSF_TYPE FLD_STi(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLD_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLD_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLD_EXTENDED_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FILD_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FILD_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FILD_QWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FBLD_PACKED_BCD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FST_STi(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FST_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FST_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSTP_EXTENDED_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIST_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIST_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FISTP_QWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FBSTP_PACKED_BCD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FISTTP16(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // SSE3 BX_SMF BX_INSF_TYPE FISTTP32(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FISTTP64(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // control BX_SMF BX_INSF_TYPE FNINIT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FNCLEX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FRSTOR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FNSAVE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDENV(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FNSTENV(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDCW(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FNSTCW(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FNSTSW(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FNSTSW_AX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // const BX_SMF BX_INSF_TYPE FLD1(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDL2T(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDL2E(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDPI(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDLG2(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDLN2(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FLDZ(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // add BX_SMF BX_INSF_TYPE FADD_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FADD_STi_ST0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FADD_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FADD_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIADD_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIADD_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // mul BX_SMF BX_INSF_TYPE FMUL_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FMUL_STi_ST0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FMUL_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FMUL_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIMUL_WORD_INTEGER (bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIMUL_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // sub BX_SMF BX_INSF_TYPE FSUB_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSUBR_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSUB_STi_ST0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSUBR_STi_ST0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSUB_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSUBR_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSUB_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSUBR_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FISUB_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FISUBR_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FISUB_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FISUBR_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // div BX_SMF BX_INSF_TYPE FDIV_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDIVR_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDIV_STi_ST0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDIVR_STi_ST0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDIV_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDIVR_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDIV_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDIVR_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIDIV_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIDIVR_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIDIV_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FIDIVR_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // compare BX_SMF BX_INSF_TYPE FCOM_STi(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FUCOM_STi(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCOMI_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FUCOMI_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCOM_SINGLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCOM_DOUBLE_REAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FICOM_WORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FICOM_DWORD_INTEGER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCOMPP(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FUCOMPP(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVB_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVE_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVBE_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVU_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVNB_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVNE_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVNBE_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCMOVNU_ST0_STj(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // misc BX_SMF BX_INSF_TYPE FXCH_STi(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FNOP(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FPLEGACY(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCHS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FABS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FTST(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FXAM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FDECSTP(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FINCSTP(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FFREE_STi(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FFREEP_STi(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE F2XM1(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FYL2X(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FPTAN(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FPATAN(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FXTRACT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FPREM1(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FPREM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FYL2XP1(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSQRT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSINCOS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FRNDINT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #undef FSCALE // is #included on Mac OS X from bochs.h BX_SMF BX_INSF_TYPE FSCALE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FSIN(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FCOS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif /* MMX */ BX_SMF BX_INSF_TYPE PUNPCKLBW_PqQd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKLWD_PqQd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKLDQ_PqQd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PACKSSWB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPGTB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPGTW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPGTD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PACKUSWB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKHBW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKHWD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKHDQ_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PACKSSDW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVD_PqEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVD_PqEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_PqQqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_PqQqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPEQB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPEQW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPEQD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE EMMS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVD_EdPdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVD_EdPdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_QqPqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLQ_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULLW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBUSB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBUSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PAND_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDUSB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDUSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PANDN_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULHW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBSB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POR_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDSB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PXOR_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLQ_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMADDWD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLW_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAW_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLW_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLD_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAD_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLD_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLQ_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLQ_PqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* MMX */ #if BX_SUPPORT_3DNOW BX_SMF BX_INSF_TYPE PFPNACC_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PI2FW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PI2FD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PF2IW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PF2ID_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFNACC_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFCMPGE_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFMIN_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFRCP_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFRSQRT_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFSUB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFADD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFCMPGT_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFMAX_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFRCPIT1_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFRSQIT1_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFSUBR_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFACC_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFCMPEQ_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFMUL_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PFRCPIT2_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULHRW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSWAPD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF BX_INSF_TYPE SYSCALL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SYSRET(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSE */ BX_SMF BX_INSF_TYPE FXSAVE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE FXRSTOR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LDMXCSR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE STMXCSR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PREFETCH(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSE */ /* SSE */ BX_SMF BX_INSF_TYPE ANDPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ORPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XORPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ANDNPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVUPS_VpsWpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVUPS_WpsVpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSS_VssWssM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSS_WssVssM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSD_WsdVsdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVHLPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVLPS_VpsMq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVLHPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVHPS_VpsMq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVHPS_MqVps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVAPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVAPS_VpsWpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVAPS_WpsVpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPI2PS_VpsQqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPI2PS_VpsQqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSI2SS_VssEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTPS2PI_PqWps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTSS2SI_GdWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPS2PI_PqWps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSS2SI_GdWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE UCOMISS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE COMISS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVMSKPS_GdVRps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SQRTPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SQRTSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RSQRTPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RSQRTSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCPPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCPSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADDPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADDSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MULPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MULSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUBPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUBSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MINPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MINSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIVPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIVSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MAXPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MAXSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSHUFW_PqQqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSHUFLW_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPPS_VpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPSS_VssWssIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PINSRW_PqEwIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRW_GdPqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHUFPS_VpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVMSKB_GdPRq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINUB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXUB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PAVGB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PAVGW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULHUW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSADBW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MASKMOVQ_PqPRq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSE */ /* SSE2 */ BX_SMF BX_INSF_TYPE MOVSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPI2PD_VpdQqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPI2PD_VpdQqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSI2SD_VsdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTPD2PI_PqWpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTSD2SI_GdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPD2PI_PqWpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSD2SI_GdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE UCOMISD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE COMISD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVMSKPD_GdVRpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SQRTPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SQRTSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADDPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADDSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MULPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MULSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUBPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUBSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPS2PD_VpdWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPD2PS_VpsWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSD2SS_VssWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSS2SD_VsdWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTDQ2PS_VpsWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPS2DQ_VdqWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTPS2DQ_VdqWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MINPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MINSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIVPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIVSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MAXPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MAXSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKLBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKLWD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE UNPCKLPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PACKSSWB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPGTB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPGTW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPGTD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PACKUSWB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKHBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKHWD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE UNPCKHPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PACKSSDW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKLQDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUNPCKHQDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVD_VdqEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSHUFD_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSHUFHW_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPEQB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPEQW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPEQD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVD_EdVdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_VqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_VqWqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPPD_VpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPSD_VsdWsdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PINSRW_VdqHdqEwIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRW_GdUdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHUFPD_VpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDQ_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULLW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVDQ2Q_PqVRq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ2DQ_VdqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVMSKB_GdUdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBUSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBUSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINUB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDUSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDUSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXUB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PAVGB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PAVGW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULHUW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULHW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTPD2DQ_VqWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTPD2DQ_VqWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTDQ2PD_VpdWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULUDQ_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULUDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMADDWD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSADBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MASKMOVDQU_VdqUdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBQ_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSUBQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PADDD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLW_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAW_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLW_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLD_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRAD_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLD_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSRLDQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSLLDQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSE2 */ /* SSE3 */ BX_SMF BX_INSF_TYPE MOVDDUP_VpdWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSLDUP_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSHDUP_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE HADDPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE HADDPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE HSUBPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE HSUBPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADDSUBPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADDSUBPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSE3 */ #if BX_CPU_LEVEL >= 6 /* SSSE3 */ BX_SMF BX_INSF_TYPE PSHUFB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHADDW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHADDD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHADDSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMADDUBSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHSUBSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHSUBW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHSUBD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSIGNB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSIGNW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSIGND_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULHRSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PABSB_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PABSW_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PABSD_PqQq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PALIGNR_PqQqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSHUFB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHADDW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHADDD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHADDSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMADDUBSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHSUBSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHSUBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHSUBD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSIGNB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSIGNW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PSIGND_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULHRSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PABSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PABSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PABSD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PALIGNR_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSSE3 */ /* SSE4.1 */ BX_SMF BX_INSF_TYPE PBLENDVB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLENDVPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLENDVPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PTEST_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPEQQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PACKUSDW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVSXBW_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVSXBD_VdqWdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVSXBQ_VdqWwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVSXWD_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVSXWQ_VdqWdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVSXDQ_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVZXBW_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVZXBD_VdqWdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVZXBQ_VdqWwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVZXWD_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVZXWQ_VdqWdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMOVZXDQ_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINSD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINUW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMINUD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXSD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXUW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMAXUD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PMULLD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PHMINPOSUW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROUNDPS_VpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROUNDPD_VpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROUNDSS_VssWssIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROUNDSD_VsdWsdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLENDPS_VpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLENDPD_VpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PBLENDW_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRB_EbdVdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRB_EbdVdqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRW_EwdVdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRW_EwdVdqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRD_EdVdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXTRD_EdVdqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE EXTRACTPS_EdVpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE EXTRACTPS_EdVpsIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PINSRB_VdqHdqEbIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PINSRB_VdqHdqEbIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INSERTPS_VpsHpsWssIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PINSRD_VdqHdqEdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PINSRD_VdqHdqEdIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DPPS_VpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DPPD_VpdHpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MPSADBW_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSE4.1 */ /* SSE4.2 */ BX_SMF BX_INSF_TYPE CRC32_GdEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CRC32_GdEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CRC32_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE CRC32_GdEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF BX_INSF_TYPE PCMPGTQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPESTRM_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPESTRI_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPISTRM_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCMPISTRI_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SSE4.2 */ /* MOVBE Intel Atom(R) instruction */ BX_SMF BX_INSF_TYPE MOVBE_GwMw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVBE_GdMd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVBE_MwGw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVBE_MdGd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE MOVBE_GqMq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVBE_MqGq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif /* MOVBE Intel Atom(R) instruction */ #endif /* XSAVE/XRSTOR extensions */ BX_SMF BX_INSF_TYPE XSAVE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XRSTOR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XGETBV(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XSETBV(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* XSAVE/XRSTOR extensions */ #if BX_CPU_LEVEL >= 6 /* AES instructions */ BX_SMF BX_INSF_TYPE AESIMC_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AESENC_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AESENCLAST_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AESDEC_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AESDECLAST_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AESKEYGENASSIST_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PCLMULQDQ_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* AES instructions */ #endif /* VMX instructions */ BX_SMF BX_INSF_TYPE VMXON(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMXOFF(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMCALL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMLAUNCH(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMCLEAR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMPTRLD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMPTRST(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMREAD_EdGd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMWRITE_GdEd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMFUNC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* VMX instructions */ /* SVM instructions */ BX_SMF BX_INSF_TYPE VMRUN(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMMCALL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMLOAD(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMSAVE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SKINIT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CLGI(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE STGI(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INVLPGA(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SVM instructions */ /* SMX instructions */ BX_SMF BX_INSF_TYPE GETSEC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* SMX instructions */ #if BX_CPU_LEVEL >= 6 /* VMXx2 */ BX_SMF BX_INSF_TYPE INVEPT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INVVPID(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* VMXx2 */ BX_SMF BX_INSF_TYPE INVPCID(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif #if BX_SUPPORT_AVX /* AVX */ BX_SMF BX_INSF_TYPE VZEROUPPER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VZEROALL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVSS_VssHpsWssR(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVSD_VsdHpdWsdR(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVAPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVAPS_VpsWpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVUPS_VpsWpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVAPS_WpsVpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVUPS_WpsVpsM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVLPD_VpdHpdMq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVHPD_VpdHpdMq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVLHPS_VpsHpsWps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVHLPS_VpsHpsWps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVSHDUP_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVSLDUP_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVDDUP_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VUNPCKLPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VUNPCKHPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VUNPCKLPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VUNPCKHPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVMSKPS_GdVRps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMOVMSKPD_GdVRpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVMSKB_GdUdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSQRTPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSQRTPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSQRTSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSQRTSD_VsdHpdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VHADDPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VHADDPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VHSUBPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VHSUBPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VADDPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VADDPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VADDSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VADDSD_VsdHpdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMULPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMULPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMULSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMULSD_VsdHpdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSUBPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSUBPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSUBSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSUBSD_VsdHpdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTSS2SD_VsdWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTSD2SS_VssWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTDQ2PS_VpsWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTPS2DQ_VdqWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTTPS2DQ_VdqWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTPS2PD_VpdWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTPD2PS_VpsWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTPD2DQ_VqWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTDQ2PD_VpdWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTTPD2DQ_VqWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTSI2SD_VsdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTSI2SS_VssEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTSI2SD_VsdEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTSI2SS_VssEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMINPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMINPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMINSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMINSD_VsdHpdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VDIVPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VDIVPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VDIVSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VDIVSD_VsdHpdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMAXPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMAXPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMAXSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMAXSD_VsdHpdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCMPPS_VpsHpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCMPSS_VssHpsWssIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCMPPD_VpdHpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCMPSD_VsdHpdWsdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VADDSUBPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VADDSUBPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VROUNDPS_VpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VROUNDPD_VpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VROUNDSS_VssHpsWssIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VROUNDSD_VsdHpdWsdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VDPPS_VpsHpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VRSQRTPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VRSQRTSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VRCPPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VRCPSS_VssHpsWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSHUFPS_VpsHpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VSHUFPD_VpdHpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VBLENDPS_VpsHpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VBLENDPD_VpdHpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPBLENDVB_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPTEST_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VTESTPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VTESTPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VANDPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VANDNPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VORPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VXORPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VBROADCASTF128_VdqMdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VBLENDVPS_VpsHpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VBLENDVPD_VpdHpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VINSERTF128_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VEXTRACTF128_WdqVdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VEXTRACTF128_WdqVdqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMILPS_VpsWpsIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMILPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMILPD_VpdWpdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMILPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERM2F128_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMASKMOVPS_VpsHpsMps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMASKMOVPD_VpdHpdMpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMASKMOVPS_MpsHpsVps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMASKMOVPD_MpdHpdVpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTPH2PS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VCVTPS2PH_WpsVpsIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* AVX */ /* AVX2 */ BX_SMF BX_INSF_TYPE VPCMPEQB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCMPEQW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCMPEQD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCMPEQQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCMPGTB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCMPGTW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCMPGTD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCMPGTQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMINSB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMINSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMINSD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMINUB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMINUW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMINUD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMAXSB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMAXSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMAXSD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMAXUB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMAXUW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMAXUD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSIGNB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSIGNW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSIGND_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPABSB_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPABSW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPABSD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBSB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBUSB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSUBUSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDSB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDUSB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPADDUSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPAVGB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPAVGW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHSUBW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHSUBD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHSUBSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHUFHW_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHUFLW_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPACKUSWB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPACKSSWB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPACKUSDW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPACKSSDW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPUNPCKLBW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPUNPCKHBW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPUNPCKLWD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPUNPCKHWD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMULLD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMULLW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMULHW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMULHUW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMULDQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMULUDQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMULHRSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMADDUBSW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMADDWD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VMPSADBW_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPBLENDW_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSADBW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHUFB_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRAW_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRAD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLW_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLD_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLW_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLD_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRAW_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRAD_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLDQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLDQ_UdqIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPALIGNR_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVSXBW256_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVSXBD256_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVSXBQ256_VdqWdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVSXWD256_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVSXWQ256_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVSXDQ256_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVZXBW256_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVZXBD256_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVZXBQ256_VdqWdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVZXWD256_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVZXWQ256_VdqWqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMOVZXDQ256_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMQ_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRAVD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLVD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSLLVQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLVD_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSRLVQ_VdqHdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPBROADCASTB_VdqWb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPBROADCASTW_VdqWw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPBROADCASTD_VdqWd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPBROADCASTQ_VdqWq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VGATHERDPS_VpsHps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VGATHERQPS_VpsHps(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VGATHERDPD_VpdHpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VGATHERQPD_VpdHpd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* AVX2 */ /* AVX2 FMA */ BX_SMF BX_INSF_TYPE VFMADDPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMADDPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMADDSD_VpdHsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMADDSS_VpsHssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMADDSUBPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMADDSUBPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBADDPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBADDPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBSD_VpdHsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBSS_VpsHssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMADDPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMADDPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMADDSD_VpdHsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMADDSS_VpsHssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMSUBPD_VpdHpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMSUBPS_VpsHpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMSUBSD_VpdHsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMSUBSS_VpsHssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* AVX2 FMA */ /* BMI */ BX_SMF BX_INSF_TYPE ANDN_GdBdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MULX_GdBdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSI_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSMSK_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSR_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RORX_GdEdIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLX_GdEdBdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRX_GdEdBdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SARX_GdEdBdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BEXTR_GdEdBdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BZHI_GdEdBdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXT_GdEdBdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PDEP_GdEdBdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ANDN_GqBqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MULX_GqBqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSI_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSMSK_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSR_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RORX_GqEqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLX_GqEqBqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRX_GqEqBqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SARX_GqEqBqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BEXTR_GqEqBqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BZHI_GqEqBqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PEXT_GqEqBqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PDEP_GqEqBqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* BMI */ /* FMA4 specific handlers (AMD) */ BX_SMF BX_INSF_TYPE VFMADDSS_VssHssWssVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMADDSD_VsdHsdWsdVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBSS_VssHssWssVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFMSUBSD_VsdHsdWsdVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMADDSS_VssHssWssVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMADDSD_VsdHsdWsdVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMSUBSS_VssHssWssVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFNMSUBSD_VsdHsdWsdVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* FMA4 specific handlers (AMD) */ /* XOP (AMD) */ BX_SMF BX_INSF_TYPE VPCMOV_VdqHdqWdqVIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPPERM_VdqHdqWdqVIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHAB_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHAW_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHAD_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHAQ_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTB_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTW_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTD_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTQ_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHLB_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHLW_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHLD_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPSHLQ_VdqWdqHdq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSSWW_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSSWD_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSSDQL_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSSDD_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSSDQH_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSWW_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSWD_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSDQL_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSDD_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMACSDQH_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMADCSSWD_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPMADCSWD_VdqHdqWdqVIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTB_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTW_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTD_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPROTQ_VdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMB_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMW_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMD_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMQ_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMUB_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMUW_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMUD_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPCOMUQ_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFRCZPS_VpsWpsR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFRCZPD_VpdWpdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFRCZSS_VssWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VFRCZSD_VsdWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDBD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDBQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDWD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDWQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDUBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDUBD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDUBQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDUWD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDUWQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHADDUDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHSUBBW_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHSUBWD_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPHSUBDQ_VdqWdqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMIL2PS_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE VPERMIL2PD_VdqHdqWdqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* XOP (AMD) */ /* TBM (AMD) */ BX_SMF BX_INSF_TYPE BEXTR_GdEdIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCFILL_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCI_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCIC_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCMSK_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCS_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSFILL_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSIC_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE T1MSKC_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TZMSK_BdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BEXTR_GqEqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCFILL_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCI_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCIC_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCMSK_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLCS_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSFILL_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BLSIC_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE T1MSKC_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TZMSK_BqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); /* TBM (AMD) */ #endif BX_SMF BX_INSF_TYPE LZCNT_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LZCNT_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE LZCNT_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif /* BMI - TZCNT */ BX_SMF BX_INSF_TYPE TZCNT_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TZCNT_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE TZCNT_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif /* BMI - TZCNT */ /* SSE4A */ BX_SMF BX_INSF_TYPE EXTRQ_UdqIbIb(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE EXTRQ_VdqUq(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INSERTQ_VdqUqIbIb(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INSERTQ_VdqUdq(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); /* SSE4A */ BX_SMF BX_INSF_TYPE CMPXCHG8B(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETnear32_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETnear32(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETnear16_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETnear16(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETfar32_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETfar16_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EbGbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVO_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNO_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVB_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNB_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVZ_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNZ_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVBE_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNBE_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVS_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNS_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVP_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNP_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVL_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNL_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVLE_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNLE_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVO_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNO_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVB_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNB_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVZ_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNZ_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVBE_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNBE_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVS_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNS_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVP_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNP_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVL_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNL_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVLE_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNLE_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CWDE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CDQ(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EbGbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EwGwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EbGbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EwGwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EdGdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MUL_AXEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_AXEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIV_AXEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IDIV_AXEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_GwEwIwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOP(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PAUSE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RLIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RHIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RXIw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_ERXId(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_RX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_RX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_ERX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_ERX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_RXAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_ERXEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_RX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_ERX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP_RX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP_EwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP_ERX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP_EdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POPCNT_GwEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POPCNT_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE POPCNT_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF BX_INSF_TYPE ADCX_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADOX_GdEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE ADCX_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADOX_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif #if BX_SUPPORT_X86_64 // 64 bit extensions BX_SMF BX_INSF_TYPE ADD_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADD_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE OR_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ADC_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SBB_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE AND_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SUB_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XOR_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMP_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_RAXId(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LEA_GqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RAXOq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_OqRAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EAXOq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_OqEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_AXOq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_OqAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_ALOq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_OqAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV64S_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV64S_GqEqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // repeatable instructions BX_SMF BX_INSF_TYPE REP_MOVSQ_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_CMPSQ_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_STOSQ_YqRAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_LODSQ_RAXXq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE REP_SCASQ_RAXXq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); // qualified by address size BX_SMF void CMPSB64_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSW64_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSD64_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASB64_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASW64_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASD64_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSB64_ALXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSW64_AXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSD64_EAXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSB64_YbAL(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSW64_YwAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSD64_YdEAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSB64_XbYb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSW64_XwYw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSD64_XdYd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSQ32_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void CMPSQ64_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASQ32_RAXXq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void SCASQ64_RAXXq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSQ32_RAXXq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void LODSQ64_RAXXq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSQ32_YqRAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void STOSQ64_YqRAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSQ32_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void MOVSQ64_XqYq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSB64_YbDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSW64_YwDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void INSD64_YdDX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSB64_DXXb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSW64_DXXw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF void OUTSD64_DXXd(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JO_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNO_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JB_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNB_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JZ_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNZ_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JBE_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNBE_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JS_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNS_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JP_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNP_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JL_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNL_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JLE_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JNLE_Jq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ENTER64_IwIb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LEAVE64(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IRET64(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR0Rq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR2Rq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR3Rq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_CR4Rq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RqCR0(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RqCR2(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RqCR3(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RqCR4(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_DqRq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RqDq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLD_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHLD_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRD_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHRD_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV64_GdEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV64_EdGdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GqEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GqEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GqEbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GqEwM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GqEdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GqEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVZX_GqEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GqEbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GqEwR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVSX_GqEdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSF_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSR_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EqIbM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BT_EqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTS_EqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTR_EqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BTC_EqIbR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BSWAP_RRX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROL_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE ROR_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCL_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RCR_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHL_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SHR_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SAR_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NOT_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE NEG_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE TEST_EqIdM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MUL_RAXEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_RAXEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DIV_RAXEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IDIV_RAXEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE IMUL_GqEqIdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INC_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE DEC_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CALL64_Ep(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP_EqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JMP64_Ep(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSHF_Fq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POPF_Fq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CDQE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CQO(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EqGqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XADD_EqGqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETnear64_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETnear64(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RETfar64_Iw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVO_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNO_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVB_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNB_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVZ_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNZ_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVBE_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNBE_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVS_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNS_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVP_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNP_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVL_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNL_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVLE_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMOVNLE_GqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOV_RRXIq(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH_RRX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP_EqM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP_RRX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE XCHG_RRXRAX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH64_Id(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE PUSH64_Sw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE POP64_Sw(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LSS_GqMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LFS_GqMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LGS_GqMp(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SGDT64_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SIDT64_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LGDT64_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LIDT64_Ms(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CMPXCHG16B(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SWAPGS(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RDFSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RDGSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE WRFSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE WRGSBASE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOPNE64_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOPE64_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE LOOP64_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE JRCXZ_Jb(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_EqPqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_EqVqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_PqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MOVQ_VdqEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSI2SS_VssEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSI2SD_VsdEqR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTSD2SI_GqWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTTSS2SI_GqWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSD2SI_GqWsdR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE CVTSS2SI_GqWssR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif // #if BX_SUPPORT_X86_64 BX_SMF BX_INSF_TYPE RDTSCP(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE INVLPG(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RSM(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE WRMSR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RDTSC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RDPMC(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE RDMSR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SYSENTER(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE SYSEXIT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MONITOR(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE MWAIT(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE UndefinedOpcode(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BxError(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS BX_SMF BX_INSF_TYPE BxEndTrace(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif #if BX_CPU_LEVEL >= 6 BX_SMF BX_INSF_TYPE BxNoSSE(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF BX_INSF_TYPE BxNoAVX(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF bx_address BxResolve16BaseIndex(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF bx_address BxResolve32Base(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF bx_address BxResolve32BaseIndex(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF bx_address BxResolve64Base(bxInstruction_c *) BX_CPP_AttrRegparmN(1); BX_SMF bx_address BxResolve64BaseIndex(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif #if BX_SUPPORT_AVX BX_SMF bx_address BxResolveGatherD(bxInstruction_c *, unsigned) BX_CPP_AttrRegparmN(2); BX_SMF bx_address BxResolveGatherQ(bxInstruction_c *, unsigned) BX_CPP_AttrRegparmN(2); #endif // #if BX_DEBUGGER BX_SMF void dbg_take_irq(void); BX_SMF void dbg_force_interrupt(unsigned vector); BX_SMF void dbg_take_dma(void); BX_SMF bx_bool dbg_set_reg(unsigned reg, Bit32u val); BX_SMF bx_bool dbg_get_sreg(bx_dbg_sreg_t *sreg, unsigned sreg_no); BX_SMF bx_bool dbg_set_sreg(unsigned sreg_no, bx_segment_reg_t *sreg); BX_SMF void dbg_get_tr(bx_dbg_sreg_t *sreg); BX_SMF void dbg_get_ldtr(bx_dbg_sreg_t *sreg); BX_SMF void dbg_get_gdtr(bx_dbg_global_sreg_t *sreg); BX_SMF void dbg_get_idtr(bx_dbg_global_sreg_t *sreg); BX_SMF unsigned dbg_query_pending(void); #endif #if BX_DEBUGGER || BX_GDBSTUB BX_SMF bx_bool dbg_instruction_epilog(void); #endif #if BX_DEBUGGER || BX_DISASM || BX_INSTRUMENTATION || BX_GDBSTUB BX_SMF bx_bool dbg_xlate_linear2phy(bx_address linear, bx_phy_address *phy, bx_bool verbose = 0); #if BX_SUPPORT_VMX >= 2 BX_SMF bx_bool dbg_translate_guest_physical(bx_phy_address guest_paddr, bx_phy_address *phy, bx_bool verbose = 0); #endif #endif #if BX_LARGE_RAMFILE BX_SMF bx_bool check_addr_in_tlb_buffers(const Bit8u *addr, const Bit8u *end); #endif BX_SMF void atexit(void); // now for some ancillary functions... BX_SMF void cpu_loop(void); #if BX_SUPPORT_SMP BX_SMF void cpu_run_trace(void); #endif BX_SMF bx_bool handleAsyncEvent(void); BX_SMF bx_bool handleWaitForEvent(void); BX_SMF bx_bool interrupts_enabled(void); BX_SMF void InterruptAcknowledge(void); BX_SMF int fetchDecode32(const Bit8u *fetchPtr, bxInstruction_c *i, unsigned remainingInPage) BX_CPP_AttrRegparmN(3); #if BX_SUPPORT_X86_64 BX_SMF int fetchDecode64(const Bit8u *fetchPtr, bxInstruction_c *i, unsigned remainingInPage) BX_CPP_AttrRegparmN(3); #endif BX_SMF void boundaryFetch(const Bit8u *fetchPtr, unsigned remainingInPage, bxInstruction_c *); BX_SMF bxICacheEntry_c *serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr); BX_SMF bxICacheEntry_c* getICacheEntry(void); BX_SMF bx_bool mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr); #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS BX_SMF BX_INSF_TYPE linkTrace(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); #endif BX_SMF void prefetch(void); BX_SMF void updateFetchModeMask(void); BX_SMF BX_CPP_INLINE void invalidate_prefetch_q(void) { BX_CPU_THIS_PTR eipPageWindowSize = 0; } BX_SMF BX_CPP_INLINE void invalidate_stack_cache(void) { BX_CPU_THIS_PTR espPageWindowSize = 0; } BX_SMF bx_bool write_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned len) BX_CPP_AttrRegparmN(3); BX_SMF bx_bool read_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned len) BX_CPP_AttrRegparmN(3); BX_SMF bx_bool execute_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned len) BX_CPP_AttrRegparmN(3); BX_SMF Bit8u read_virtual_byte_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit16u read_virtual_word_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit32u read_virtual_dword_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit64u read_virtual_qword_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); #if BX_CPU_LEVEL >= 6 BX_SMF void read_virtual_dqword_32(unsigned seg, Bit32u off, BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); BX_SMF void read_virtual_dqword_aligned_32(unsigned seg, Bit32u off, BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); #if BX_SUPPORT_AVX BX_SMF void read_virtual_dword_vector_32(unsigned seg, Bit32u off, unsigned elements, BxPackedAvxRegister *data); BX_SMF void read_virtual_dword_vector_aligned_32(unsigned seg, Bit32u off, unsigned elements, BxPackedAvxRegister *data); #endif #endif BX_SMF void write_virtual_byte_32(unsigned seg, Bit32u offset, Bit8u data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_word_32(unsigned seg, Bit32u offset, Bit16u data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_dword_32(unsigned seg, Bit32u offset, Bit32u data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_qword_32(unsigned seg, Bit32u offset, Bit64u data) BX_CPP_AttrRegparmN(3); #if BX_CPU_LEVEL >= 6 BX_SMF void write_virtual_dqword_32(unsigned seg, Bit32u offset, const BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_dqword_aligned_32(unsigned seg, Bit32u offset, const BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); #if BX_SUPPORT_AVX BX_SMF void write_virtual_dword_vector_32(unsigned seg, Bit32u off, unsigned elements, const BxPackedAvxRegister *data); BX_SMF void write_virtual_dword_vector_aligned_32(unsigned seg, Bit32u off, unsigned elements, const BxPackedAvxRegister *data); #endif #endif BX_SMF Bit8u read_RMW_virtual_byte_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit16u read_RMW_virtual_word_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit32u read_RMW_virtual_dword_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit64u read_RMW_virtual_qword_32(unsigned seg, Bit32u offset) BX_CPP_AttrRegparmN(2); BX_SMF void write_RMW_virtual_byte(Bit8u val8) BX_CPP_AttrRegparmN(1); BX_SMF void write_RMW_virtual_word(Bit16u val16) BX_CPP_AttrRegparmN(1); BX_SMF void write_RMW_virtual_dword(Bit32u val32) BX_CPP_AttrRegparmN(1); BX_SMF void write_RMW_virtual_qword(Bit64u val64) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF void write_virtual_byte_64(unsigned seg, Bit64u offset, Bit8u data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_word_64(unsigned seg, Bit64u offset, Bit16u data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_dword_64(unsigned seg, Bit64u offset, Bit32u data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_qword_64(unsigned seg, Bit64u offset, Bit64u data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_dqword_64(unsigned seg, Bit64u offset, const BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); BX_SMF void write_virtual_dqword_aligned_64(unsigned seg, Bit64u offset, const BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); #if BX_SUPPORT_AVX BX_SMF void write_virtual_dword_vector_64(unsigned seg, Bit64u offset, unsigned elements, const BxPackedAvxRegister *data); BX_SMF void write_virtual_dword_vector_aligned_64(unsigned seg, Bit64u offset, unsigned elements, const BxPackedAvxRegister *data); #endif BX_SMF Bit8u read_virtual_byte_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit16u read_virtual_word_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit32u read_virtual_dword_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit64u read_virtual_qword_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); BX_SMF void read_virtual_dqword_64(unsigned seg, Bit64u off, BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); BX_SMF void read_virtual_dqword_aligned_64(unsigned seg, Bit64u off, BxPackedXmmRegister *data) BX_CPP_AttrRegparmN(3); #if BX_SUPPORT_AVX BX_SMF void read_virtual_dword_vector_64(unsigned seg, Bit64u offset, unsigned elements, BxPackedAvxRegister *data); BX_SMF void read_virtual_dword_vector_aligned_64(unsigned seg, Bit64u offset, unsigned elements, BxPackedAvxRegister *data); #endif BX_SMF Bit8u read_RMW_virtual_byte_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit16u read_RMW_virtual_word_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit32u read_RMW_virtual_dword_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); BX_SMF Bit64u read_RMW_virtual_qword_64(unsigned seg, Bit64u offset) BX_CPP_AttrRegparmN(2); #endif // write of word/dword to new stack could happen only in legacy mode BX_SMF void write_new_stack_word_32(bx_segment_reg_t *seg, Bit32u offset, unsigned curr_pl, Bit16u data); BX_SMF void write_new_stack_dword_32(bx_segment_reg_t *seg, Bit32u offset, unsigned curr_pl, Bit32u data); BX_SMF void write_new_stack_qword_32(bx_segment_reg_t *seg, Bit32u offset, unsigned curr_pl, Bit64u data); #if BX_SUPPORT_X86_64 BX_SMF void write_new_stack_word_64(Bit64u offset, unsigned curr_pl, Bit16u data); BX_SMF void write_new_stack_dword_64(Bit64u offset, unsigned curr_pl, Bit32u data); BX_SMF void write_new_stack_qword_64(Bit64u offset, unsigned curr_pl, Bit64u data); #endif #if BX_SUPPORT_X86_64 // write #define write_virtual_byte(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_byte_64(seg, (Bit64u) offset, data) : \ write_virtual_byte_32(seg, (Bit32u) offset, data) #define write_virtual_word(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_word_64(seg, (Bit64u) offset, data) : \ write_virtual_word_32(seg, (Bit32u) offset, data) #define write_virtual_dword(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_dword_64(seg, (Bit64u) offset, data) : \ write_virtual_dword_32(seg, (Bit32u) offset, data) #define write_virtual_qword(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_qword_64(seg, (Bit64u) offset, data) : \ write_virtual_qword_32(seg, (Bit32u) offset, data) #define write_virtual_dqword(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_dqword_64(seg, (Bit64u) offset, (const BxPackedXmmRegister*)(data)) : \ write_virtual_dqword_32(seg, (Bit32u) offset, (const BxPackedXmmRegister*)(data)) #define write_virtual_dqword_aligned(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_dqword_aligned_64(seg, (Bit64u) offset, (const BxPackedXmmRegister*)(data)) : \ write_virtual_dqword_aligned_32(seg, (Bit32u) offset, (const BxPackedXmmRegister*)(data)) #if BX_SUPPORT_AVX #define write_virtual_dword_vector(seg, offset, elements, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_dword_vector_64(seg, (Bit64u) offset, elements, (const BxPackedAvxRegister*)(data)) : \ write_virtual_dword_vector_32(seg, (Bit32u) offset, elements, (const BxPackedAvxRegister*)(data)) #define write_virtual_dword_vector_aligned(seg, offset, elements, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ write_virtual_dword_vector_aligned_64(seg, (Bit64u) offset, elements, (const BxPackedAvxRegister*)(data)) : \ write_virtual_dword_vector_aligned_32(seg, (Bit32u) offset, elements, (const BxPackedAvxRegister*)(data)) #endif // read #define read_virtual_byte(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_byte_64(seg, (Bit64u) offset) : \ read_virtual_byte_32(seg, (Bit32u) offset) #define read_virtual_word(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_word_64(seg, (Bit64u) offset) : \ read_virtual_word_32(seg, (Bit32u) offset) #define read_virtual_dword(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_dword_64(seg, (Bit64u) offset) : \ read_virtual_dword_32(seg, (Bit32u) offset) #define read_virtual_qword(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_qword_64(seg, (Bit64u) offset) : \ read_virtual_qword_32(seg, (Bit32u) offset) #define read_virtual_dqword(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_dqword_64(seg, (Bit64u) offset, (BxPackedXmmRegister*)(data)) : \ read_virtual_dqword_32(seg, (Bit32u) offset, (BxPackedXmmRegister*)(data)) #define read_virtual_dqword_aligned(seg, offset, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_dqword_aligned_64(seg, (Bit64u) offset, (BxPackedXmmRegister*)(data)) : \ read_virtual_dqword_aligned_32(seg, (Bit32u) offset, (BxPackedXmmRegister*)(data)) #if BX_SUPPORT_AVX #define read_virtual_dword_vector(seg, offset, elements, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_dword_vector_64(seg, (Bit64u) offset, elements, (BxPackedAvxRegister*)(data)) : \ read_virtual_dword_vector_32(seg, (Bit32u) offset, elements, (BxPackedAvxRegister*)(data)) #define read_virtual_dword_vector_aligned(seg, offset, elements, data) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_virtual_dword_vector_aligned_64(seg, (Bit64u) offset, elements, (BxPackedAvxRegister*)(data)) : \ read_virtual_dword_vector_aligned_32(seg, (Bit32u) offset, elements, (BxPackedAvxRegister*)(data)) #endif // RMW #define read_RMW_virtual_byte(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_RMW_virtual_byte_64(seg, (Bit64u) offset) : \ read_RMW_virtual_byte_32(seg, (Bit32u) offset) #define read_RMW_virtual_word(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_RMW_virtual_word_64(seg, (Bit64u) offset) : \ read_RMW_virtual_word_32(seg, (Bit32u) offset) #define read_RMW_virtual_dword(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_RMW_virtual_dword_64(seg, (Bit64u) offset) : \ read_RMW_virtual_dword_32(seg, (Bit32u) offset) #define read_RMW_virtual_qword(seg, offset) \ (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ? \ read_RMW_virtual_qword_64(seg, (Bit64u) offset) : \ read_RMW_virtual_qword_32(seg, (Bit32u) offset) #else // write #define write_virtual_byte(seg, offset, data) \ write_virtual_byte_32(seg, offset, data) #define write_virtual_word(seg, offset, data) \ write_virtual_word_32(seg, offset, data) #define write_virtual_dword(seg, offset, data) \ write_virtual_dword_32(seg, offset, data) #define write_virtual_qword(seg, offset, data) \ write_virtual_qword_32(seg, offset, data) #define write_virtual_dqword(seg, offset, data) \ write_virtual_dqword_32(seg, offset, (const BxPackedXmmRegister*)(data)) #define write_virtual_dqword_aligned(seg, offset, data) \ write_virtual_dqword_aligned_32(seg, offset, (const BxPackedXmmRegister*)(data)) #if BX_SUPPORT_AVX #define write_virtual_dword_vector(seg, offset, elements, data) \ write_virtual_dword_vector_32(seg, offset, elements, (const BxPackedAvxRegister*)(data)) #define write_virtual_dword_vector_aligned(seg, offset, elements, data) \ write_virtual_dword_vector_aligned_32(seg, offset, elements, (const BxPackedAvxRegister*)(data)) #endif // read #define read_virtual_byte(seg, offset) \ read_virtual_byte_32(seg, offset) #define read_virtual_word(seg, offset) \ read_virtual_word_32(seg, offset) #define read_virtual_dword(seg, offset) \ read_virtual_dword_32(seg, offset) #define read_virtual_qword(seg, offset) \ read_virtual_qword_32(seg, offset) #define read_virtual_dqword(seg, offset, data) \ read_virtual_dqword_32(seg, offset, (BxPackedXmmRegister*)(data)) #define read_virtual_dqword_aligned(seg, offset, data) \ read_virtual_dqword_aligned_32(seg, offset, (BxPackedXmmRegister*)(data)) #if BX_SUPPORT_AVX #define read_virtual_dword_vector(seg, offset, elements, data) \ read_virtual_dword_vector_32(seg, offset, elements, (BxPackedAvxRegister*)(data)) #define read_virtual_dword_vector_aligned(seg, offset, elements, data) \ read_virtual_dword_vector_aligned_32(seg, offset, elements, (BxPackedAvxRegister*)(data)) #endif // RMW #define read_RMW_virtual_byte(seg, offset) \ read_RMW_virtual_byte_32(seg, offset) #define read_RMW_virtual_word(seg, offset) \ read_RMW_virtual_word_32(seg, offset) #define read_RMW_virtual_dword(seg, offset) \ read_RMW_virtual_dword_32(seg, offset) #define read_RMW_virtual_qword(seg, offset) \ read_RMW_virtual_qword_32(seg, offset) #endif BX_SMF void stack_write_byte(bx_address offset, Bit8u data) BX_CPP_AttrRegparmN(2); BX_SMF void stack_write_word(bx_address offset, Bit16u data) BX_CPP_AttrRegparmN(2); BX_SMF void stack_write_dword(bx_address offset, Bit32u data) BX_CPP_AttrRegparmN(2); BX_SMF void stack_write_qword(bx_address offset, Bit64u data) BX_CPP_AttrRegparmN(2); BX_SMF Bit8u stack_read_byte(bx_address offset) BX_CPP_AttrRegparmN(1); BX_SMF Bit16u stack_read_word(bx_address offset) BX_CPP_AttrRegparmN(1); BX_SMF Bit32u stack_read_dword(bx_address offset) BX_CPP_AttrRegparmN(1); BX_SMF Bit64u stack_read_qword(bx_address offset) BX_CPP_AttrRegparmN(1); BX_SMF void stackPrefetch(bx_address offset, unsigned len) BX_CPP_AttrRegparmN(2); BX_SMF Bit8u system_read_byte(bx_address laddr) BX_CPP_AttrRegparmN(1); BX_SMF Bit16u system_read_word(bx_address laddr) BX_CPP_AttrRegparmN(1); BX_SMF Bit32u system_read_dword(bx_address laddr) BX_CPP_AttrRegparmN(1); BX_SMF Bit64u system_read_qword(bx_address laddr) BX_CPP_AttrRegparmN(1); BX_SMF void system_write_byte(bx_address laddr, Bit8u data) BX_CPP_AttrRegparmN(2); BX_SMF void system_write_word(bx_address laddr, Bit16u data) BX_CPP_AttrRegparmN(2); BX_SMF void system_write_dword(bx_address laddr, Bit32u data) BX_CPP_AttrRegparmN(2); BX_SMF Bit8u* v2h_read_byte(bx_address laddr, bx_bool user) BX_CPP_AttrRegparmN(2); BX_SMF Bit8u* v2h_write_byte(bx_address laddr, bx_bool user) BX_CPP_AttrRegparmN(2); BX_SMF void branch_near16(Bit16u new_IP) BX_CPP_AttrRegparmN(1); BX_SMF void branch_near32(Bit32u new_EIP) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF void branch_near64(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF void branch_far32(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit32u eip, Bit8u cpl); BX_SMF void branch_far64(bx_selector_t *selector, bx_descriptor_t *descriptor, bx_address rip, Bit8u cpl); #if BX_SUPPORT_REPEAT_SPEEDUPS BX_SMF Bit32u FastRepMOVSB(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u byteCount); BX_SMF Bit32u FastRepMOVSW(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u wordCount); BX_SMF Bit32u FastRepMOVSD(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u dwordCount); BX_SMF Bit32u FastRepSTOSB(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit8u val, Bit32u byteCount); BX_SMF Bit32u FastRepSTOSW(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit16u val, Bit32u wordCount); BX_SMF Bit32u FastRepSTOSD(bxInstruction_c *i, unsigned dstSeg, bx_address dstOff, Bit32u val, Bit32u dwordCount); BX_SMF Bit32u FastRepINSW(bxInstruction_c *i, bx_address dstOff, Bit16u port, Bit32u wordCount); BX_SMF Bit32u FastRepOUTSW(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, Bit16u port, Bit32u wordCount); #endif BX_SMF void repeat(bxInstruction_c *i, BxRepIterationPtr_tR execute) BX_CPP_AttrRegparmN(2); BX_SMF void repeat_ZF(bxInstruction_c *i, BxRepIterationPtr_tR execute) BX_CPP_AttrRegparmN(2); // linear address for access_linear expected to be canonical ! BX_SMF void access_read_linear(bx_address laddr, unsigned len, unsigned curr_pl, unsigned rw, void *data); BX_SMF void access_write_linear(bx_address laddr, unsigned len, unsigned curr_pl, void *data); BX_SMF void page_fault(unsigned fault, bx_address laddr, unsigned user, unsigned rw); BX_SMF void access_read_physical(bx_phy_address paddr, unsigned len, void *data); BX_SMF void access_write_physical(bx_phy_address paddr, unsigned len, void *data); BX_SMF bx_hostpageaddr_t getHostMemAddr(bx_phy_address addr, unsigned rw); // linear address for translate_linear expected to be canonical ! BX_SMF bx_phy_address translate_linear(bx_address laddr, unsigned user, unsigned rw); BX_SMF bx_phy_address translate_linear_legacy(bx_address laddr, Bit32u &lpf_mask, Bit32u &combined_access, unsigned user, unsigned rw); BX_SMF void update_access_dirty(bx_phy_address *entry_addr, Bit32u *entry, unsigned leaf, unsigned write); #if BX_CPU_LEVEL >= 6 BX_SMF bx_phy_address translate_linear_load_PDPTR(bx_address laddr, unsigned user, unsigned rw); BX_SMF bx_phy_address translate_linear_PAE(bx_address laddr, Bit32u &lpf_mask, Bit32u &combined_access, unsigned user, unsigned rw); BX_SMF int check_entry_PAE(const char *s, Bit64u entry, Bit64u reserved, unsigned rw, bx_bool *nx_fault); BX_SMF void update_access_dirty_PAE(bx_phy_address *entry_addr, Bit64u *entry, unsigned max_level, unsigned leaf, unsigned write); #endif #if BX_SUPPORT_X86_64 BX_SMF bx_phy_address translate_linear_long_mode(bx_address laddr, Bit32u &lpf_mask, Bit32u &combined_access, unsigned user, unsigned rw); #endif #if BX_SUPPORT_VMX >= 2 BX_SMF bx_phy_address translate_guest_physical(bx_phy_address guest_paddr, bx_address guest_laddr, bx_bool guest_laddr_valid, bx_bool is_page_walk, unsigned rw); BX_SMF void update_ept_access_dirty(bx_phy_address *entry_addr, Bit64u *entry, unsigned leaf, unsigned write); BX_SMF bx_bool is_eptptr_valid(Bit64u eptptr); #endif #if BX_SUPPORT_SVM BX_SMF void nested_page_fault(unsigned fault, bx_phy_address guest_paddr, unsigned rw, unsigned is_page_walk); BX_SMF bx_phy_address nested_walk_long_mode(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk); BX_SMF bx_phy_address nested_walk_PAE(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk); BX_SMF bx_phy_address nested_walk_legacy(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk); BX_SMF bx_phy_address nested_walk(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk); #endif #if BX_CPU_LEVEL >= 6 BX_SMF void TLB_flushNonGlobal(void); #endif BX_SMF void TLB_flush(void); BX_SMF void TLB_invlpg(bx_address laddr); BX_SMF void set_INTR(bx_bool value); BX_SMF void inhibit_interrupts(unsigned mask); BX_SMF bx_bool interrupts_inhibited(unsigned mask); BX_SMF const char *strseg(bx_segment_reg_t *seg); BX_SMF void interrupt(Bit8u vector, unsigned type, bx_bool push_error, Bit16u error_code); BX_SMF void real_mode_int(Bit8u vector, bx_bool push_error, Bit16u error_code); BX_SMF void protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error, Bit16u error_code); #if BX_SUPPORT_X86_64 BX_SMF void long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error, Bit16u error_code); #endif BX_SMF void exception(unsigned vector, Bit16u error_code) BX_CPP_AttrNoReturn(); BX_SMF void init_SMRAM(void); BX_SMF int int_number(unsigned s); BX_SMF bx_bool SetCR0(bx_address val) BX_CPP_AttrRegparmN(1); BX_SMF bx_bool check_CR0(bx_address val) BX_CPP_AttrRegparmN(1); BX_SMF bx_bool SetCR3(bx_address val) BX_CPP_AttrRegparmN(1); #if BX_CPU_LEVEL >= 5 BX_SMF bx_bool SetCR4(bx_address val) BX_CPP_AttrRegparmN(1); BX_SMF bx_bool check_CR4(bx_address val) BX_CPP_AttrRegparmN(1); BX_SMF Bit32u get_cr4_allow_mask(void); #endif #if BX_CPU_LEVEL >= 6 BX_SMF bx_bool CheckPDPTR(bx_phy_address cr3_val) BX_CPP_AttrRegparmN(1); #endif #if BX_SUPPORT_VMX >= 2 BX_SMF bx_bool CheckPDPTR(Bit64u *pdptr) BX_CPP_AttrRegparmN(1); #endif #if BX_CPU_LEVEL >= 5 BX_SMF bx_bool SetEFER(bx_address val) BX_CPP_AttrRegparmN(1); #endif BX_SMF void reset(unsigned source); BX_SMF void shutdown(void); BX_SMF void handleCpuModeChange(void); BX_SMF void handleCpuContextChange(void); #if BX_CPU_LEVEL >= 4 BX_SMF void handleAlignmentCheck(void); #endif #if BX_CPU_LEVEL >= 6 BX_SMF void handleSseModeChange(void); BX_SMF void handleAvxModeChange(void); #endif #if BX_CPU_LEVEL >= 5 BX_SMF bx_bool rdmsr(Bit32u index, Bit64u *val_64) BX_CPP_AttrRegparmN(2); BX_SMF bx_bool handle_unknown_rdmsr(Bit32u index, Bit64u *val_64) BX_CPP_AttrRegparmN(2); BX_SMF bx_bool wrmsr(Bit32u index, Bit64u val_64) BX_CPP_AttrRegparmN(2); BX_SMF bx_bool handle_unknown_wrmsr(Bit32u index, Bit64u val_64) BX_CPP_AttrRegparmN(2); #endif #if BX_SUPPORT_APIC BX_SMF bx_bool relocate_apic(Bit64u val_64); #endif BX_SMF void task_gate(bxInstruction_c *i, bx_selector_t *selector, bx_descriptor_t *gate_descriptor, unsigned source); BX_SMF void jump_protected(bxInstruction_c *i, Bit16u cs, bx_address disp) BX_CPP_AttrRegparmN(3); BX_SMF void jmp_call_gate(bx_selector_t *selector, bx_descriptor_t *gate_descriptor) BX_CPP_AttrRegparmN(2); BX_SMF void call_gate(bx_descriptor_t *gate_descriptor) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF void jmp_call_gate64(bx_selector_t *selector) BX_CPP_AttrRegparmN(1); #endif BX_SMF void call_protected(bxInstruction_c *i, Bit16u cs, bx_address disp) BX_CPP_AttrRegparmN(3); #if BX_SUPPORT_X86_64 BX_SMF void call_gate64(bx_selector_t *selector) BX_CPP_AttrRegparmN(1); #endif BX_SMF void return_protected(bxInstruction_c *i, Bit16u pop_bytes) BX_CPP_AttrRegparmN(2); BX_SMF void iret_protected(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #if BX_SUPPORT_X86_64 BX_SMF void long_iret(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif BX_SMF void validate_seg_reg(unsigned seg); BX_SMF void validate_seg_regs(void); BX_SMF void stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector, Bit32u flags32); BX_SMF void iret16_stack_return_from_v86(bxInstruction_c *); BX_SMF void iret32_stack_return_from_v86(bxInstruction_c *); BX_SMF int v86_redirect_interrupt(Bit8u vector); BX_SMF void init_v8086_mode(void); BX_SMF void task_switch_load_selector(bx_segment_reg_t *seg, bx_selector_t *selector, Bit16u raw_selector, Bit8u cs_rpl); BX_SMF void task_switch(bxInstruction_c *i, bx_selector_t *selector, bx_descriptor_t *descriptor, unsigned source, Bit32u dword1, Bit32u dword2, bx_bool push_error = 0, Bit32u error_code = 0); BX_SMF void get_SS_ESP_from_TSS(unsigned pl, Bit16u *ss, Bit32u *esp); #if BX_SUPPORT_X86_64 BX_SMF Bit64u get_RSP_from_TSS(unsigned pl); #endif BX_SMF void write_flags(Bit16u flags, bx_bool change_IOPL, bx_bool change_IF) BX_CPP_AttrRegparmN(3); BX_SMF void writeEFlags(Bit32u eflags, Bit32u changeMask) BX_CPP_AttrRegparmN(2); // Newer variant. BX_SMF void write_eflags_fpu_compare(int float_relation); BX_SMF Bit32u force_flags(void); BX_SMF Bit32u read_eflags(void) { return BX_CPU_THIS_PTR force_flags(); } BX_SMF bx_bool allow_io(bxInstruction_c *i, Bit16u addr, unsigned len) BX_CPP_AttrRegparmN(3); BX_SMF Bit32u get_descriptor_l(const bx_descriptor_t *) BX_CPP_AttrRegparmN(1); BX_SMF Bit32u get_descriptor_h(const bx_descriptor_t *) BX_CPP_AttrRegparmN(1); BX_SMF bx_bool set_segment_ar_data(bx_segment_reg_t *seg, bx_bool valid, Bit16u raw_selector, bx_address base, Bit32u limit_scaled, Bit16u ar_data); BX_SMF void check_cs(bx_descriptor_t *descriptor, Bit16u cs_raw, Bit8u check_rpl, Bit8u check_cpl); // the basic assumption of the code that load_cs and load_ss cannot fail ! BX_SMF void load_cs(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl) BX_CPP_AttrRegparmN(3); BX_SMF void load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl) BX_CPP_AttrRegparmN(3); BX_SMF void touch_segment(bx_selector_t *selector, bx_descriptor_t *descriptor) BX_CPP_AttrRegparmN(2); BX_SMF void fetch_raw_descriptor(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2, unsigned exception_no); BX_SMF bx_bool fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2) BX_CPP_AttrRegparmN(3); BX_SMF void load_seg_reg(bx_segment_reg_t *seg, Bit16u new_value) BX_CPP_AttrRegparmN(2); BX_SMF void load_null_selector(bx_segment_reg_t *seg, unsigned value) BX_CPP_AttrRegparmN(2); #if BX_SUPPORT_X86_64 BX_SMF void fetch_raw_descriptor_64(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2, Bit32u *dword3, unsigned exception_no); BX_SMF bx_bool fetch_raw_descriptor2_64(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2, Bit32u *dword3); #endif BX_SMF void push_16(Bit16u value16) BX_CPP_AttrRegparmN(1); BX_SMF void push_32(Bit32u value32) BX_CPP_AttrRegparmN(1); BX_SMF Bit16u pop_16(void); BX_SMF Bit32u pop_32(void); #if BX_SUPPORT_X86_64 BX_SMF void push_64(Bit64u value64) BX_CPP_AttrRegparmN(1); BX_SMF Bit64u pop_64(void); #endif BX_SMF void sanity_checks(void); BX_SMF void assert_checks(void); BX_SMF void enter_system_management_mode(void); BX_SMF bx_bool resume_from_system_management_mode(BX_SMM_State *smm_state); BX_SMF void smram_save_state(Bit32u *smm_saved_state); BX_SMF bx_bool smram_restore_state(const Bit32u *smm_saved_state); BX_SMF void deliver_INIT(void); BX_SMF void deliver_NMI(void); BX_SMF void deliver_SMI(void); BX_SMF void deliver_SIPI(unsigned vector); BX_SMF void debug(bx_address offset); #if BX_DISASM BX_SMF void debug_disasm_instruction(bx_address offset); #endif #if BX_X86_DEBUGGER // x86 hardware debug support BX_SMF bx_bool hwbreakpoint_check(bx_address laddr, unsigned opa, unsigned opb); #if BX_CPU_LEVEL >= 5 BX_SMF void iobreakpoint_match(unsigned port, unsigned len); #endif BX_SMF Bit32u code_breakpoint_match(bx_address laddr); BX_SMF void hwbreakpoint_match(bx_address laddr, unsigned len, unsigned rw); BX_SMF Bit32u hwdebug_compare(bx_address laddr, unsigned len, unsigned opa, unsigned opb); #endif BX_SMF void init_FetchDecodeTables(void); #if BX_SUPPORT_APIC BX_SMF BX_CPP_INLINE Bit8u get_apic_id(void) { return BX_CPU_THIS_PTR bx_cpuid; } #endif BX_SMF BX_CPP_INLINE int bx_cpuid_support_x86_64(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_debug_extensions(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_1g_paging(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_vme(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_tsc(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_pae(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_pge(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_pse(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_mmx(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_sse(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_sep(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_fxsave_fxrstor(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_pcid(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_xsave(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_fsgsbase(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_smep(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_x2apic(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_smx(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_vmx(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_svm(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_rdtscp(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_tsc_deadline(void); BX_SMF BX_CPP_INLINE int bx_cpuid_support_xapic_extensions(void); BX_SMF BX_CPP_INLINE unsigned which_cpu(void) { return BX_CPU_THIS_PTR bx_cpuid; } BX_SMF BX_CPP_INLINE const bx_gen_reg_t *get_gen_regfile() { return BX_CPU_THIS_PTR gen_reg; } BX_SMF BX_CPP_INLINE Bit64u get_icount(void) { return BX_CPU_THIS_PTR icount; } BX_SMF BX_CPP_INLINE void sync_icount(void) { BX_CPU_THIS_PTR icount_last_sync = BX_CPU_THIS_PTR icount; } BX_SMF BX_CPP_INLINE Bit64u get_icount_last_sync(void) { return BX_CPU_THIS_PTR icount_last_sync; } BX_SMF BX_CPP_INLINE bx_address get_instruction_pointer(void); BX_SMF BX_CPP_INLINE Bit32u get_eip(void) { return (BX_CPU_THIS_PTR gen_reg[BX_32BIT_REG_EIP].dword.erx); } BX_SMF BX_CPP_INLINE Bit16u get_ip (void) { return (BX_CPU_THIS_PTR gen_reg[BX_16BIT_REG_IP].word.rx); } #if BX_SUPPORT_X86_64 BX_SMF BX_CPP_INLINE Bit64u get_rip(void) { return (BX_CPU_THIS_PTR gen_reg[BX_64BIT_REG_RIP].rrx); } #endif BX_SMF BX_CPP_INLINE Bit8u get_reg8l(unsigned reg); BX_SMF BX_CPP_INLINE Bit8u get_reg8h(unsigned reg); BX_SMF BX_CPP_INLINE void set_reg8l(unsigned reg, Bit8u val); BX_SMF BX_CPP_INLINE void set_reg8h(unsigned reg, Bit8u val); BX_SMF BX_CPP_INLINE Bit16u get_reg16(unsigned reg); BX_SMF BX_CPP_INLINE void set_reg16(unsigned reg, Bit16u val); BX_SMF BX_CPP_INLINE Bit32u get_reg32(unsigned reg); BX_SMF BX_CPP_INLINE void set_reg32(unsigned reg, Bit32u val); #if BX_SUPPORT_X86_64 BX_SMF BX_CPP_INLINE Bit64u get_reg64(unsigned reg); BX_SMF BX_CPP_INLINE void set_reg64(unsigned reg, Bit64u val); #endif #if BX_CPU_LEVEL >= 6 BX_SMF BX_CPP_INLINE unsigned get_cr8(); #endif BX_SMF bx_address get_segment_base(unsigned seg); // The linear address must be truncated to the 32-bit when CPU is not // executing in long64 mode. The function must be used to compute // linear address everywhere when a code is shared between long64 and // legacy mode. For legacy mode only just use Bit32u to store linear // address value. BX_SMF bx_address get_laddr(unsigned seg, bx_address offset); BX_SMF Bit32u get_laddr32(unsigned seg, Bit32u offset); #if BX_SUPPORT_X86_64 BX_SMF Bit64u get_laddr64(unsigned seg, Bit64u offset); #endif DECLARE_EFLAG_ACCESSOR (ID, 21) DECLARE_EFLAG_ACCESSOR (VIP, 20) DECLARE_EFLAG_ACCESSOR (VIF, 19) DECLARE_EFLAG_ACCESSOR (AC, 18) DECLARE_EFLAG_ACCESSOR (VM, 17) DECLARE_EFLAG_ACCESSOR (RF, 16) DECLARE_EFLAG_ACCESSOR (NT, 14) DECLARE_EFLAG_ACCESSOR_IOPL( 12) DECLARE_EFLAG_ACCESSOR (DF, 10) DECLARE_EFLAG_ACCESSOR (IF, 9) DECLARE_EFLAG_ACCESSOR (TF, 8) BX_SMF BX_CPP_INLINE bx_bool real_mode(void); BX_SMF BX_CPP_INLINE bx_bool smm_mode(void); BX_SMF BX_CPP_INLINE bx_bool protected_mode(void); BX_SMF BX_CPP_INLINE bx_bool v8086_mode(void); BX_SMF BX_CPP_INLINE bx_bool long_mode(void); BX_SMF BX_CPP_INLINE bx_bool long64_mode(void); BX_SMF BX_CPP_INLINE unsigned get_cpu_mode(void); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 BX_SMF BX_CPP_INLINE bx_bool alignment_check(void); #endif #if BX_CPU_LEVEL >= 5 BX_SMF Bit64u get_TSC(); BX_SMF void set_TSC(Bit64u tsc); #endif #if BX_SUPPORT_FPU BX_SMF void print_state_FPU(void); BX_SMF void prepareFPU(bxInstruction_c *i, bx_bool = 1); BX_SMF void FPU_check_pending_exceptions(void); BX_SMF void FPU_update_last_instruction(bxInstruction_c *i); BX_SMF void FPU_stack_underflow(int stnr, int pop_stack = 0); BX_SMF void FPU_stack_overflow(void); BX_SMF unsigned FPU_exception(unsigned exception, bx_bool = 0); BX_SMF bx_address fpu_save_environment(bxInstruction_c *i); BX_SMF bx_address fpu_load_environment(bxInstruction_c *i); BX_SMF Bit8u pack_FPU_TW(Bit16u tag_word); BX_SMF Bit16u unpack_FPU_TW(Bit16u tag_byte); #endif #if BX_CPU_LEVEL >= 5 BX_SMF void prepareMMX(void); BX_SMF void prepareFPU2MMX(void); /* cause transition from FPU to MMX technology state */ BX_SMF void print_state_MMX(void); #endif #if BX_CPU_LEVEL >= 6 BX_SMF void check_exceptionsSSE(int); BX_SMF void print_state_SSE(void); BX_SMF void prepareXSAVE(void); BX_SMF void print_state_AVX(void); #endif #if BX_SUPPORT_MONITOR_MWAIT BX_SMF bx_bool is_monitor(bx_phy_address addr, unsigned len); BX_SMF void check_monitor(bx_phy_address addr, unsigned len); #endif BX_SMF bx_address read_CR0(void); #if BX_CPU_LEVEL >= 5 BX_SMF bx_address read_CR4(void); #endif #if BX_CPU_LEVEL >= 6 BX_SMF Bit32u ReadCR8(bxInstruction_c *i); BX_SMF void WriteCR8(bxInstruction_c *i, bx_address val); #endif #if BX_SUPPORT_VMX BX_SMF Bit16u VMread16(unsigned encoding) BX_CPP_AttrRegparmN(1); BX_SMF Bit32u VMread32(unsigned encoding) BX_CPP_AttrRegparmN(1); BX_SMF Bit64u VMread64(unsigned encoding) BX_CPP_AttrRegparmN(1); BX_SMF bx_address VMread_natural(unsigned encoding) BX_CPP_AttrRegparmN(1); BX_SMF void VMwrite16(unsigned encoding, Bit16u val_16) BX_CPP_AttrRegparmN(2); BX_SMF void VMwrite32(unsigned encoding, Bit32u val_32) BX_CPP_AttrRegparmN(2); BX_SMF void VMwrite64(unsigned encoding, Bit64u val_64) BX_CPP_AttrRegparmN(2); BX_SMF void VMwrite_natural(unsigned encoding, bx_address val) BX_CPP_AttrRegparmN(2); BX_SMF void VMsucceed(void); BX_SMF void VMfailInvalid(void); BX_SMF void VMfail(Bit32u error_code); BX_SMF void VMabort(VMX_vmabort_code error_code); BX_SMF Bit32u LoadMSRs(Bit32u msr_cnt, bx_phy_address pAddr); BX_SMF Bit32u StoreMSRs(Bit32u msr_cnt, bx_phy_address pAddr); BX_SMF unsigned VMXReadRevisionID(bx_phy_address pAddr); BX_SMF VMX_error_code VMenterLoadCheckVmControls(void); BX_SMF VMX_error_code VMenterLoadCheckHostState(void); BX_SMF Bit32u VMenterLoadCheckGuestState(Bit64u *qualification); BX_SMF void VMenterInjectEvents(void); BX_SMF void VMexit(Bit32u reason, Bit64u qualification); BX_SMF void VMexitSaveGuestState(void); BX_SMF void VMexitSaveGuestMSRs(void); BX_SMF void VMexitLoadHostState(void); BX_SMF void set_VMCSPTR(Bit64u vmxptr); BX_SMF void init_vmx_capabilities(); BX_SMF void init_VMCS(void); BX_SMF bx_bool vmcs_field_supported(Bit32u encoding); BX_SMF void register_vmx_state(bx_param_c *parent); #if BX_SUPPORT_VMX >= 2 BX_SMF Bit16u VMX_Get_Current_VPID(void); #endif #if BX_SUPPORT_X86_64 BX_SMF bx_bool is_virtual_apic_page(bx_phy_address paddr) BX_CPP_AttrRegparmN(1); BX_SMF void VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *data); BX_SMF void VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *data); BX_SMF Bit32u VMX_Read_VTPR(void); BX_SMF void VMX_Write_VTPR(Bit8u vtpr); #endif // vmexit reasons BX_SMF void VMexit_Instruction(bxInstruction_c *i, Bit32u reason, bx_bool rw = BX_READ) BX_CPP_AttrRegparmN(3); BX_SMF void VMexit_Event(unsigned type, unsigned vector, Bit16u errcode, bx_bool errcode_valid, Bit64u qualification = 0); BX_SMF void VMexit_TripleFault(void); BX_SMF void VMexit_ExtInterrupt(void); BX_SMF void VMexit_TaskSwitch(Bit16u tss_selector, unsigned source) BX_CPP_AttrRegparmN(2); BX_SMF void VMexit_PAUSE(void); #if BX_SUPPORT_VMX >= 2 BX_SMF void VMexit_PreemptionTimerExpired(void); #endif BX_SMF bx_bool VMexit_CLTS(void); BX_SMF void VMexit_MSR(unsigned op, Bit32u msr) BX_CPP_AttrRegparmN(2); BX_SMF void VMexit_IO(bxInstruction_c *i, unsigned port, unsigned len) BX_CPP_AttrRegparmN(3); BX_SMF Bit32u VMexit_LMSW(bxInstruction_c *i, Bit32u msw) BX_CPP_AttrRegparmN(2); BX_SMF bx_address VMexit_CR0_Write(bxInstruction_c *i, bx_address) BX_CPP_AttrRegparmN(2); BX_SMF void VMexit_CR3_Read(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF void VMexit_CR3_Write(bxInstruction_c *i, bx_address) BX_CPP_AttrRegparmN(2); BX_SMF bx_address VMexit_CR4_Write(bxInstruction_c *i, bx_address) BX_CPP_AttrRegparmN(2); BX_SMF void VMexit_CR8_Read(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF void VMexit_CR8_Write(bxInstruction_c *i) BX_CPP_AttrRegparmN(1); BX_SMF void VMexit_DR_Access(unsigned read, unsigned dr, unsigned reg); #if BX_SUPPORT_VMX >= 2 BX_SMF void vmfunc_eptp_switching(void); #endif #endif #if BX_SUPPORT_SVM BX_SMF void SvmEnterSaveHostState(SVM_HOST_STATE *host); BX_SMF bx_bool SvmEnterLoadCheckControls(SVM_CONTROLS *ctrls); BX_SMF bx_bool SvmEnterLoadCheckGuestState(void); BX_SMF bx_bool SvmInjectEvents(void); BX_SMF void Svm_Vmexit(int reason, Bit64u exitinfo1 = 0, Bit64u exitinfo2 = 0); BX_SMF void SvmExitSaveGuestState(void); BX_SMF void SvmExitLoadHostState(SVM_HOST_STATE *host); BX_SMF Bit8u vmcb_read8(unsigned offset); BX_SMF Bit16u vmcb_read16(unsigned offset); BX_SMF Bit32u vmcb_read32(unsigned offset); BX_SMF Bit64u vmcb_read64(unsigned offset); BX_SMF void vmcb_write8(unsigned offset, Bit8u val_8); BX_SMF void vmcb_write16(unsigned offset, Bit16u val_16); BX_SMF void vmcb_write32(unsigned offset, Bit32u val_32); BX_SMF void vmcb_write64(unsigned offset, Bit64u val_64); BX_SMF void svm_segment_read(bx_segment_reg_t *seg, unsigned offset); BX_SMF void svm_segment_write(bx_segment_reg_t *seg, unsigned offset); BX_SMF void SvmInterceptException(unsigned type, unsigned vector, Bit16u errcode, bx_bool errcode_valid, Bit64u qualification = 0); BX_SMF void SvmInterceptIO(bxInstruction_c *i, unsigned port, unsigned len); BX_SMF void SvmInterceptMSR(unsigned op, Bit32u msr); BX_SMF void SvmInterceptTaskSwitch(Bit16u tss_selector, unsigned source, bx_bool push_error, Bit32u error_code); BX_SMF void VirtualInterruptAcknowledge(void); BX_SMF void register_svm_state(bx_param_c *parent); #endif #if BX_CONFIGURE_MSRS int load_MSRs(const char *file); #endif }; #if BX_CPU_LEVEL >= 5 BX_CPP_INLINE void BX_CPU_C::prepareMMX(void) { if(BX_CPU_THIS_PTR cr0.get_EM()) exception(BX_UD_EXCEPTION, 0); if(BX_CPU_THIS_PTR cr0.get_TS()) exception(BX_NM_EXCEPTION, 0); /* check floating point status word for a pending FPU exceptions */ FPU_check_pending_exceptions(); } BX_CPP_INLINE void BX_CPU_C::prepareFPU2MMX(void) { BX_CPU_THIS_PTR the_i387.twd = 0; BX_CPU_THIS_PTR the_i387.tos = 0; /* reset FPU Top-Of-Stack */ } #endif #if BX_CPU_LEVEL >= 6 BX_CPP_INLINE void BX_CPU_C::prepareXSAVE(void) { if(! BX_CPU_THIS_PTR cr4.get_OSXSAVE()) exception(BX_UD_EXCEPTION, 0); if(BX_CPU_THIS_PTR cr0.get_TS()) exception(BX_NM_EXCEPTION, 0); } #endif // Can be used as LHS or RHS. #define RMAddr(i) (BX_CPU_THIS_PTR address_xlation.rm_addr) #if defined(NEED_CPU_REG_SHORTCUTS) #include "stack.h" #define RSP_SPECULATIVE { \ BX_CPU_THIS_PTR speculative_rsp = 1; \ BX_CPU_THIS_PTR prev_rsp = RSP; \ } #define RSP_COMMIT { \ BX_CPU_THIS_PTR speculative_rsp = 0; \ } #endif // defined(NEED_CPU_REG_SHORTCUTS) // // bit 0 - CS.D_B // bit 1 - long64 mode (CS.L) // bit 2 - SSE_OK // bit 3 - AVX_OK // // updateFetchModeMask - has to be called everytime // CS.L / CS.D_B / CR0.PE, CR0.TS or CR0.EM / CR4.OSFXSR / CR4.OSXSAVE changes // BX_CPP_INLINE void BX_CPU_C::updateFetchModeMask(void) { BX_CPU_THIS_PTR fetchModeMask = #if BX_CPU_LEVEL >= 6 #if BX_SUPPORT_AVX (BX_CPU_THIS_PTR avx_ok << 3) | #endif (BX_CPU_THIS_PTR sse_ok << 2) | #endif #if BX_SUPPORT_X86_64 ((BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64)<<1) | #endif (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b); BX_CPU_THIS_PTR user_pl = // CPL == 3 (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl == 3); } #if BX_X86_DEBUGGER #define BX_HWDebugInstruction 0x00 #define BX_HWDebugMemW 0x01 #define BX_HWDebugIO 0x02 #define BX_HWDebugMemRW 0x03 #endif BX_CPP_INLINE bx_address BX_CPU_C::get_segment_base(unsigned seg) { #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { if (seg < BX_SEG_REG_FS) return 0; } #endif return BX_CPU_THIS_PTR sregs[seg].cache.u.segment.base; } BX_CPP_INLINE Bit32u BX_CPU_C::get_laddr32(unsigned seg, Bit32u offset) { return (Bit32u) BX_CPU_THIS_PTR sregs[seg].cache.u.segment.base + offset; } #if BX_SUPPORT_X86_64 BX_CPP_INLINE Bit64u BX_CPU_C::get_laddr64(unsigned seg, Bit64u offset) { if (seg < BX_SEG_REG_FS) return offset; else return BX_CPU_THIS_PTR sregs[seg].cache.u.segment.base + offset; } #endif BX_CPP_INLINE bx_address BX_CPU_C::get_laddr(unsigned seg, bx_address offset) { #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { return get_laddr64(seg, offset); } #endif return get_laddr32(seg, (Bit32u) offset); } BX_CPP_INLINE Bit8u BX_CPU_C::get_reg8l(unsigned reg) { assert(reg < BX_GENERAL_REGISTERS); return (BX_CPU_THIS_PTR gen_reg[reg].word.byte.rl); } BX_CPP_INLINE void BX_CPU_C::set_reg8l(unsigned reg, Bit8u val) { assert(reg < BX_GENERAL_REGISTERS); BX_CPU_THIS_PTR gen_reg[reg].word.byte.rl = val; } BX_CPP_INLINE Bit8u BX_CPU_C::get_reg8h(unsigned reg) { assert(reg < BX_GENERAL_REGISTERS); return (BX_CPU_THIS_PTR gen_reg[reg].word.byte.rh); } BX_CPP_INLINE void BX_CPU_C::set_reg8h(unsigned reg, Bit8u val) { assert(reg < BX_GENERAL_REGISTERS); BX_CPU_THIS_PTR gen_reg[reg].word.byte.rh = val; } #if BX_SUPPORT_X86_64 BX_CPP_INLINE bx_address BX_CPU_C::get_instruction_pointer(void) { return BX_CPU_THIS_PTR get_rip(); } #else BX_CPP_INLINE bx_address BX_CPU_C::get_instruction_pointer(void) { return BX_CPU_THIS_PTR get_eip(); } #endif BX_CPP_INLINE Bit16u BX_CPU_C::get_reg16(unsigned reg) { assert(reg < BX_GENERAL_REGISTERS); return (BX_CPU_THIS_PTR gen_reg[reg].word.rx); } BX_CPP_INLINE void BX_CPU_C::set_reg16(unsigned reg, Bit16u val) { assert(reg < BX_GENERAL_REGISTERS); BX_CPU_THIS_PTR gen_reg[reg].word.rx = val; } BX_CPP_INLINE Bit32u BX_CPU_C::get_reg32(unsigned reg) { assert(reg < BX_GENERAL_REGISTERS); return (BX_CPU_THIS_PTR gen_reg[reg].dword.erx); } BX_CPP_INLINE void BX_CPU_C::set_reg32(unsigned reg, Bit32u val) { assert(reg < BX_GENERAL_REGISTERS); BX_CPU_THIS_PTR gen_reg[reg].dword.erx = val; } #if BX_SUPPORT_X86_64 BX_CPP_INLINE Bit64u BX_CPU_C::get_reg64(unsigned reg) { assert(reg < BX_GENERAL_REGISTERS); return (BX_CPU_THIS_PTR gen_reg[reg].rrx); } BX_CPP_INLINE void BX_CPU_C::set_reg64(unsigned reg, Bit64u val) { assert(reg < BX_GENERAL_REGISTERS); BX_CPU_THIS_PTR gen_reg[reg].rrx = val; } #endif #if BX_CPU_LEVEL >= 6 // CR8 is aliased to APIC->TASK PRIORITY register // APIC.TPR[7:4] = CR8[3:0] // APIC.TPR[3:0] = 0 // Reads of CR8 return zero extended APIC.TPR[7:4] BX_CPP_INLINE unsigned BX_CPU_C::get_cr8(void) { return (BX_CPU_THIS_PTR lapic.get_tpr() >> 4) & 0xf; } #endif BX_CPP_INLINE bx_bool BX_CPU_C::real_mode(void) { return (BX_CPU_THIS_PTR cpu_mode == BX_MODE_IA32_REAL); } BX_CPP_INLINE bx_bool BX_CPU_C::smm_mode(void) { return (BX_CPU_THIS_PTR in_smm); } BX_CPP_INLINE bx_bool BX_CPU_C::v8086_mode(void) { return (BX_CPU_THIS_PTR cpu_mode == BX_MODE_IA32_V8086); } BX_CPP_INLINE bx_bool BX_CPU_C::protected_mode(void) { return (BX_CPU_THIS_PTR cpu_mode >= BX_MODE_IA32_PROTECTED); } BX_CPP_INLINE bx_bool BX_CPU_C::long_mode(void) { #if BX_SUPPORT_X86_64 return BX_CPU_THIS_PTR efer.get_LMA(); #else return 0; #endif } BX_CPP_INLINE bx_bool BX_CPU_C::long64_mode(void) { #if BX_SUPPORT_X86_64 return (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); #else return 0; #endif } BX_CPP_INLINE unsigned BX_CPU_C::get_cpu_mode(void) { return (BX_CPU_THIS_PTR cpu_mode); } #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 BX_CPP_INLINE bx_bool BX_CPU_C::alignment_check(void) { return BX_CPU_THIS_PTR alignment_check_mask; } #endif BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_svm(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_SVM) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_smx(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_SMX) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_vmx(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_VMX) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_xsave(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_XSAVE) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_x2apic(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_X2APIC) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pcid(void) { #if BX_SUPPORT_X86_64 return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PCID) != 0; #else return 0; #endif } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_fsgsbase(void) { #if BX_SUPPORT_X86_64 return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_FSGSBASE) != 0; #else return 0; #endif } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_smep(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_SMEP) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_vme(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_VME) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_tsc(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_PENTIUM) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_debug_extensions(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_DEBUG_EXTENSIONS) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pse(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PSE) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pae(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PAE) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_pge(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_PGE) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_mmx(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_MMX) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_sse(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_SSE) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_sep(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_SYSENTER_SYSEXIT) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_fxsave_fxrstor(void) { return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_SSE) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_x86_64(void) { #if BX_SUPPORT_X86_64 return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_LONG_MODE) != 0; #else return 0; #endif } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_1g_paging(void) { #if BX_SUPPORT_X86_64 return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_1G_PAGES) != 0; #else return 0; #endif } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_rdtscp(void) { #if BX_SUPPORT_X86_64 return (BX_CPU_THIS_PTR isa_extensions_bitmask & BX_ISA_RDTSCP) != 0; #else return 0; #endif } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_tsc_deadline(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_TSC_DEADLINE) != 0; } BX_CPP_INLINE int BX_CPU_C::bx_cpuid_support_xapic_extensions(void) { return (BX_CPU_THIS_PTR cpu_extensions_bitmask & BX_CPU_XAPIC_EXT) != 0; } IMPLEMENT_EFLAG_ACCESSOR (ID, 21) IMPLEMENT_EFLAG_ACCESSOR (VIP, 20) IMPLEMENT_EFLAG_ACCESSOR (VIF, 19) IMPLEMENT_EFLAG_ACCESSOR (AC, 18) IMPLEMENT_EFLAG_ACCESSOR (VM, 17) IMPLEMENT_EFLAG_ACCESSOR (RF, 16) IMPLEMENT_EFLAG_ACCESSOR (NT, 14) IMPLEMENT_EFLAG_ACCESSOR_IOPL( 12) IMPLEMENT_EFLAG_ACCESSOR (DF, 10) IMPLEMENT_EFLAG_ACCESSOR (IF, 9) IMPLEMENT_EFLAG_ACCESSOR (TF, 8) IMPLEMENT_EFLAG_SET_ACCESSOR (ID, 21) IMPLEMENT_EFLAG_SET_ACCESSOR (VIP, 20) IMPLEMENT_EFLAG_SET_ACCESSOR (VIF, 19) #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 IMPLEMENT_EFLAG_SET_ACCESSOR_AC ( 18) #else IMPLEMENT_EFLAG_SET_ACCESSOR (AC, 18) #endif IMPLEMENT_EFLAG_SET_ACCESSOR_VM ( 17) IMPLEMENT_EFLAG_SET_ACCESSOR_RF (RF, 16) IMPLEMENT_EFLAG_SET_ACCESSOR (NT, 14) IMPLEMENT_EFLAG_SET_ACCESSOR (DF, 10) IMPLEMENT_EFLAG_SET_ACCESSOR_IF_TF(IF, 9) IMPLEMENT_EFLAG_SET_ACCESSOR_IF_TF(TF, 8) #define BX_TASK_FROM_CALL 0 #define BX_TASK_FROM_IRET 1 #define BX_TASK_FROM_JUMP 2 #define BX_TASK_FROM_INT 3 // exception types for interrupt method enum { BX_EXTERNAL_INTERRUPT = 0, BX_NMI = 2, BX_HARDWARE_EXCEPTION = 3, // all exceptions except #BP and #OF BX_SOFTWARE_INTERRUPT = 4, BX_PRIVILEGED_SOFTWARE_INTERRUPT = 5, BX_SOFTWARE_EXCEPTION = 6 }; #if BX_CPU_LEVEL >= 6 enum { BX_INVPCID_INDIVIDUAL_ADDRESS_NON_GLOBAL_INVALIDATION, BX_INVPCID_SINGLE_CONTEXT_NON_GLOBAL_INVALIDATION, BX_INVPCID_ALL_CONTEXT_INVALIDATION, BX_INVPCID_ALL_CONTEXT_NON_GLOBAL_INVALIDATION }; #endif // // // For decoding... // // If the BxImmediate mask is set, the lowest 4 bits of the attribute // specify which kinds of immediate data required by instruction. #define BxImmediate 0x000f // bits 3..0: any immediate #define BxImmediate_I1 0x0001 // imm8 = 1 #define BxImmediate_Ib 0x0002 // 8 bit #define BxImmediate_Ib_SE 0x0003 // sign extend to OS size #define BxImmediate_Iw 0x0004 // 16 bit #define BxImmediate_Id 0x0005 // 32 bit #define BxImmediate_O 0x0006 // MOV_ALOd, mov_OdAL, mov_eAXOv, mov_OveAX #if BX_SUPPORT_X86_64 #define BxImmediate_Iq 0x0007 // 64 bit override #endif #define BxImmediate_BrOff8 0x0008 // Relative branch offset byte #define BxImmediate_Ib4 BxImmediate_Ib // Register encoded in Ib[7:4] #define BxImmediate_Ib5 BxImmediate_Ib #define BxImmediate_BrOff16 BxImmediate_Iw // Relative branch offset word, not encodable in 64-bit mode #define BxImmediate_BrOff32 BxImmediate_Id // Relative branch offset dword // Lookup for opcode and attributes in another opcode tables // Totally 15 opcode groups supported #define BxGroupX 0x00f0 // bits 7..4: opcode groups definition #define BxPrefixSSE66 0x0010 // Group encoding: 0001, SSE_PREFIX_66 #define BxPrefixSSEF3 0x0020 // Group encoding: 0010, SSE_PREFIX_F3 #define BxPrefixSSEF2 0x0030 // Group encoding: 0011, SSE_PREFIX_F2 #define BxPrefixSSE 0x0040 // Group encoding: 0100 #define BxGroupN 0x0050 // Group encoding: 0101 #define BxSplitGroupN 0x0060 // Group encoding: 0110 #define BxFPEscape 0x0070 // Group encoding: 0111 #define Bx3ByteOp 0x0080 // Group encoding: 1000 #define BxOSizeGrp 0x0090 // Group encoding: 1001 #define BxPrefixVEX 0x00A0 // Group encoding: 1010 #define BxSplitVexW 0x00B0 // Group encoding: 1011 #define BxSplitVexW64 0x00C0 // Group encoding: 1100 - VexW ignored in 32-bit mode #define BxSplitMod11B 0x00D0 // Group encoding: 1101 // The BxImmediate2 mask specifies kind of second immediate data // required by instruction. #define BxImmediate2 0x0300 // bits 8.9: any immediate #define BxImmediate_Ib2 0x0100 #define BxImmediate_Iw2 0x0200 #define BxImmediate_Id2 0x0300 #define BxLockable 0x0400 // bit 10 #define BxRepeatable 0x0800 // bit 11 #define BxVexW0 0x1000 // bit 12 #define BxVexW1 0x2000 // bit 13 #define BxTraceEnd 0x8000 // bit 15 #ifdef BX_TRACE_CACHE_NO_SPECULATIVE_TRACING #define BxTraceJCC BxTraceEnd #else #define BxTraceJCC 0 #endif #define BxGroup1 BxGroupN #define BxGroup1A BxGroupN #define BxGroup2 BxGroupN #define BxGroup3 BxGroupN #define BxGroup4 BxGroupN #define BxGroup5 BxGroupN #define BxGroup6 BxGroupN #define BxGroup7 BxFPEscape #define BxGroup8 BxGroupN #define BxGroup9 BxGroupN #define BxGroup11 BxGroupN #define BxGroup12 BxGroupN #define BxGroup13 BxGroupN #define BxGroup14 BxGroupN #define BxGroup15 BxSplitGroupN #define BxGroup16 BxGroupN #define BxGroup17 BxGroupN #define BxGroup17A BxGroupN #define BxGroupFP BxSplitGroupN // #endif // #ifndef BX_CPU_H bochs-2.6/cpu/todo0000644000175000017500000000260712020641453014016 0ustar guillemguillemTODO (know issues in CPU model): ------------------------------- [!] The following 3DNow! instructions still not implemented: PF2IW_PqQq PFNACC_PqQq PFPNACC_PqQq PFCMPGE_PqQq PFCMPGT_PqQq PFCMPEQ_PqQq PFMIN_PqQq PFMAX_PqQq PFRCP_PqQq PFRSQRT_PqQq PFSUB_PqQq PFSUBR_PqQq PFADD_PqQq PFACC_PqQq, PFMUL_PqQq PFRCPIT1_PqQq PFRSQIT1_PqQq PFRCPIT2_PqQq [!] CPUID does not report 3DNow! instruction set [!] Some of APIC functionality still not implemented, for example - LVT pins handling - Filter interrupts according processor priority (PPR) [!] REP NOP is PAUSE (on P4/XEON) When running in SMP mode, this means that we are in a spin loop. This processor should yield to the other one, as we are anyhow waiting for a lock, and any other processor is responsible for this. [!] 32-bit linear address wrap when executing in legacy mode might be not implemented correctly for system memory accesses (like descriptor tables and etc) [!] AMD and Intel x86_64 implementations are different. Currently Bochs emulation is according to Intel version. Do we need to support both ? [!] VMX: - Dual-monitor treatment of SMIs and SMM not implemented yet - VMENTER to not-active state not supported yet [!] SVM: - Decoding assists, pause filter, VMCB clean are not implemented yet - More? [!] TODO: Convert CPUDB to plugins and search for them in runtime bochs-2.6/cpu/gather.cc0000644000175000017500000001622512020641453014710 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: gather.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX bx_address BX_CPP_AttrRegparmN(2) BX_CPU_C::BxResolveGatherD(bxInstruction_c *i, unsigned element) { Bit32s index = BX_READ_AVX_REG(i->sibIndex()).avx32s(element); if (i->as64L()) return (BX_READ_64BIT_REG(i->sibBase()) + (((Bit64s) index) << i->sibScale()) + i->displ32s()); else return (Bit32u) (BX_READ_32BIT_REG(i->sibBase()) + (index << i->sibScale()) + i->displ32s()); } bx_address BX_CPP_AttrRegparmN(2) BX_CPU_C::BxResolveGatherQ(bxInstruction_c *i, unsigned element) { Bit64s index = BX_READ_AVX_REG(i->sibIndex()).avx64s(element); if (i->as64L()) return (BX_READ_64BIT_REG(i->sibBase()) + (index << i->sibScale()) + i->displ32s()); else return (Bit32u) (BX_READ_32BIT_REG(i->sibBase()) + (index << i->sibScale()) + i->displ32s()); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERDPS_VpsHps(bxInstruction_c *i) { if (! i->as32L()) { BX_ERROR(("VGATHERDPS_VpsHps: Gather with 16-bit address size")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == BX_NIL_REGISTER) { BX_ERROR(("VGATHERDPS_VpsHps: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) { BX_ERROR(("VGATHERDPS_VpsHps: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } BxPackedAvxRegister *mask = &BX_AVX_REG(i->src2()), *dest = &BX_AVX_REG(i->dst()); // index size = 32, element_size = 32, max vector size = 256 // num_elements: // 128 bit => 4 // 256 bit => 8 unsigned n, num_elements = 4 * i->getVL(); for (n=0; n < num_elements; n++) { if (mask->avx32u(n) & 0x80000000) mask->avx32u(n) = 0xffffffff; else mask->avx32u(n) = 0; } for (n=0; n < 8; n++) { if (n >= num_elements) { mask->avx32u(n) = 0; dest->avx32u(n) = 0; continue; } if (mask->avx32u(n)) { dest->avx32u(n) = read_virtual_dword(i->seg(), BxResolveGatherD(i, n)); } mask->avx32u(n) = 0; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERQPS_VpsHps(bxInstruction_c *i) { if (! i->as32L()) { BX_ERROR(("VGATHERQPS_VpsHps: Gather with 16-bit address size")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == BX_NIL_REGISTER) { BX_ERROR(("VGATHERQPS_VpsHps: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) { BX_ERROR(("VGATHERQPS_VpsHps: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } // index size = 64, element_size = 32, max vector size = 256 // num_elements: // 128 bit => 2 // 256 bit => 4 BxPackedAvxRegister *mask = &BX_AVX_REG(i->src2()), *dest = &BX_AVX_REG(i->dst()); unsigned n, num_elements = 2 * i->getVL(); for (n=0; n < num_elements; n++) { if (mask->avx32u(n) & 0x80000000) mask->avx32u(n) = 0xffffffff; else mask->avx32u(n) = 0; } for (n=0; n < 4; n++) { if (n >= num_elements) { mask->avx32u(n) = 0; dest->avx32u(n) = 0; continue; } if (mask->avx32u(n)) { dest->avx32u(n) = read_virtual_dword(i->seg(), BxResolveGatherQ(i, n)); } mask->avx32u(n) = 0; } BX_CLEAR_AVX_HIGH(i->dst()); BX_CLEAR_AVX_HIGH(i->src2()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERDPD_VpdHpd(bxInstruction_c *i) { if (! i->as32L()) { BX_ERROR(("VGATHERDPD_VpdHpd: Gather with 16-bit address size")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == BX_NIL_REGISTER) { BX_ERROR(("VGATHERDPD_VpdHpd: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) { BX_ERROR(("VGATHERDPD_VpdHpd: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } // index size = 32, element_size = 64, max vector size = 256 // num_elements: // 128 bit => 2 // 256 bit => 4 BxPackedAvxRegister *mask = &BX_AVX_REG(i->src2()), *dest = &BX_AVX_REG(i->dst()); unsigned n, num_elements = 2 * i->getVL(); for (n=0; n < num_elements; n++) { if (mask->avx64u(n) & BX_CONST64(0x8000000000000000)) mask->avx64u(n) = BX_CONST64(0xffffffffffffffff); else mask->avx64u(n) = 0; } for (unsigned n=0; n < 4; n++) { if (n >= num_elements) { mask->avx64u(n) = 0; dest->avx64u(n) = 0; continue; } if (mask->avx64u(n)) { dest->avx64u(n) = read_virtual_qword(i->seg(), BxResolveGatherD(i, n)); } mask->avx64u(n) = 0; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VGATHERQPD_VpdHpd(bxInstruction_c *i) { if (! i->as32L()) { BX_ERROR(("VGATHERQPD_VpdHpd: Gather with 16-bit address size")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == BX_NIL_REGISTER) { BX_ERROR(("VGATHERQPD_VpdHpd: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } if (i->sibIndex() == i->src2() || i->sibIndex() == i->dst() || i->src2() == i->dst()) { BX_ERROR(("VGATHERQPD_VpdHpd: incorrect source operands")); exception(BX_UD_EXCEPTION, 0); } // index size = 64, element_size = 64, max vector size = 256 // num_elements: // 128 bit => 2 // 256 bit => 4 BxPackedAvxRegister *mask = &BX_AVX_REG(i->src2()), *dest = &BX_AVX_REG(i->dst()); unsigned n, num_elements = 2 * i->getVL(); for (n=0; n < num_elements; n++) { if (mask->avx64u(n) & BX_CONST64(0x8000000000000000)) mask->avx64u(n) = BX_CONST64(0xffffffffffffffff); else mask->avx64u(n) = 0; } for (n=0; n < 4; n++) { if (n >= num_elements) { mask->avx64u(n) = 0; dest->avx64u(n) = 0; continue; } if (mask->avx64u(n)) { dest->avx64u(n) = read_virtual_qword(i->seg(), BxResolveGatherQ(i, n)); } mask->avx64u(n) = 0; } BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/simd_int.h0000644000175000017500000012150012020641453015077 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: simd_int.h 10742 2011-10-20 17:37:57Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_SIMD_INT_FUNCTIONS_H #define BX_SIMD_INT_FUNCTIONS_H // absolute value BX_CPP_INLINE void sse_pabsb(BxPackedXmmRegister *op) { for(unsigned n=0; n<16; n++) { if(op->xmmsbyte(n) < 0) op->xmmubyte(n) = -op->xmmsbyte(n); } } BX_CPP_INLINE void sse_pabsw(BxPackedXmmRegister *op) { for(unsigned n=0; n<8; n++) { if(op->xmm16s(n) < 0) op->xmm16u(n) = -op->xmm16s(n); } } BX_CPP_INLINE void sse_pabsd(BxPackedXmmRegister *op) { for(unsigned n=0; n<4; n++) { if(op->xmm32s(n) < 0) op->xmm32u(n) = -op->xmm32s(n); } } // min/max BX_CPP_INLINE void sse_pminsb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { if(op2->xmmsbyte(n) < op1->xmmsbyte(n)) op1->xmmubyte(n) = op2->xmmubyte(n); } } BX_CPP_INLINE void sse_pminub(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { if(op2->xmmubyte(n) < op1->xmmubyte(n)) op1->xmmubyte(n) = op2->xmmubyte(n); } } BX_CPP_INLINE void sse_pminsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { if(op2->xmm16s(n) < op1->xmm16s(n)) op1->xmm16s(n) = op2->xmm16s(n); } } BX_CPP_INLINE void sse_pminuw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { if(op2->xmm16u(n) < op1->xmm16u(n)) op1->xmm16s(n) = op2->xmm16s(n); } } BX_CPP_INLINE void sse_pminsd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { if(op2->xmm32s(n) < op1->xmm32s(n)) op1->xmm32u(n) = op2->xmm32u(n); } } BX_CPP_INLINE void sse_pminud(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { if(op2->xmm32u(n) < op1->xmm32u(n)) op1->xmm32u(n) = op2->xmm32u(n); } } BX_CPP_INLINE void sse_pmaxsb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { if(op2->xmmsbyte(n) > op1->xmmsbyte(n)) op1->xmmubyte(n) = op2->xmmubyte(n); } } BX_CPP_INLINE void sse_pmaxub(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { if(op2->xmmubyte(n) > op1->xmmubyte(n)) op1->xmmubyte(n) = op2->xmmubyte(n); } } BX_CPP_INLINE void sse_pmaxsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { if(op2->xmm16s(n) > op1->xmm16s(n)) op1->xmm16s(n) = op2->xmm16s(n); } } BX_CPP_INLINE void sse_pmaxuw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { if(op2->xmm16u(n) > op1->xmm16u(n)) op1->xmm16s(n) = op2->xmm16s(n); } } BX_CPP_INLINE void sse_pmaxsd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { if(op2->xmm32s(n) > op1->xmm32s(n)) op1->xmm32u(n) = op2->xmm32u(n); } } BX_CPP_INLINE void sse_pmaxud(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { if(op2->xmm32u(n) > op1->xmm32u(n)) op1->xmm32u(n) = op2->xmm32u(n); } } // unpack BX_CPP_INLINE void sse_unpcklps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm32u(3) = op2->xmm32u(1); op1->xmm32u(2) = op1->xmm32u(1); op1->xmm32u(1) = op2->xmm32u(0); //op1->xmm32u(0) = op1->xmm32u(0); } BX_CPP_INLINE void sse_unpckhps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm32u(0) = op1->xmm32u(2); op1->xmm32u(1) = op2->xmm32u(2); op1->xmm32u(2) = op1->xmm32u(3); op1->xmm32u(3) = op2->xmm32u(3); } BX_CPP_INLINE void sse_unpcklpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { //op1->xmm64u(0) = op1->xmm64u(0); op1->xmm64u(1) = op2->xmm64u(0); } BX_CPP_INLINE void sse_unpckhpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm64u(0) = op1->xmm64u(1); op1->xmm64u(1) = op2->xmm64u(1); } BX_CPP_INLINE void sse_punpcklbw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmmubyte(0xF) = op2->xmmubyte(7); op1->xmmubyte(0xE) = op1->xmmubyte(7); op1->xmmubyte(0xD) = op2->xmmubyte(6); op1->xmmubyte(0xC) = op1->xmmubyte(6); op1->xmmubyte(0xB) = op2->xmmubyte(5); op1->xmmubyte(0xA) = op1->xmmubyte(5); op1->xmmubyte(0x9) = op2->xmmubyte(4); op1->xmmubyte(0x8) = op1->xmmubyte(4); op1->xmmubyte(0x7) = op2->xmmubyte(3); op1->xmmubyte(0x6) = op1->xmmubyte(3); op1->xmmubyte(0x5) = op2->xmmubyte(2); op1->xmmubyte(0x4) = op1->xmmubyte(2); op1->xmmubyte(0x3) = op2->xmmubyte(1); op1->xmmubyte(0x2) = op1->xmmubyte(1); op1->xmmubyte(0x1) = op2->xmmubyte(0); //op1->xmmubyte(0x0) = op1->xmmubyte(0); } BX_CPP_INLINE void sse_punpckhbw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmmubyte(0x0) = op1->xmmubyte(0x8); op1->xmmubyte(0x1) = op2->xmmubyte(0x8); op1->xmmubyte(0x2) = op1->xmmubyte(0x9); op1->xmmubyte(0x3) = op2->xmmubyte(0x9); op1->xmmubyte(0x4) = op1->xmmubyte(0xA); op1->xmmubyte(0x5) = op2->xmmubyte(0xA); op1->xmmubyte(0x6) = op1->xmmubyte(0xB); op1->xmmubyte(0x7) = op2->xmmubyte(0xB); op1->xmmubyte(0x8) = op1->xmmubyte(0xC); op1->xmmubyte(0x9) = op2->xmmubyte(0xC); op1->xmmubyte(0xA) = op1->xmmubyte(0xD); op1->xmmubyte(0xB) = op2->xmmubyte(0xD); op1->xmmubyte(0xC) = op1->xmmubyte(0xE); op1->xmmubyte(0xD) = op2->xmmubyte(0xE); op1->xmmubyte(0xE) = op1->xmmubyte(0xF); op1->xmmubyte(0xF) = op2->xmmubyte(0xF); } BX_CPP_INLINE void sse_punpcklwd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16u(7) = op2->xmm16u(3); op1->xmm16u(6) = op1->xmm16u(3); op1->xmm16u(5) = op2->xmm16u(2); op1->xmm16u(4) = op1->xmm16u(2); op1->xmm16u(3) = op2->xmm16u(1); op1->xmm16u(2) = op1->xmm16u(1); op1->xmm16u(1) = op2->xmm16u(0); //op1->xmm16u(0) = op1->xmm16u(0); } BX_CPP_INLINE void sse_punpckhwd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16u(0) = op1->xmm16u(4); op1->xmm16u(1) = op2->xmm16u(4); op1->xmm16u(2) = op1->xmm16u(5); op1->xmm16u(3) = op2->xmm16u(5); op1->xmm16u(4) = op1->xmm16u(6); op1->xmm16u(5) = op2->xmm16u(6); op1->xmm16u(6) = op1->xmm16u(7); op1->xmm16u(7) = op2->xmm16u(7); } // pack BX_CPP_INLINE void sse_packuswb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmmubyte(0x0) = SaturateWordSToByteU(op1->xmm16s(0)); op1->xmmubyte(0x1) = SaturateWordSToByteU(op1->xmm16s(1)); op1->xmmubyte(0x2) = SaturateWordSToByteU(op1->xmm16s(2)); op1->xmmubyte(0x3) = SaturateWordSToByteU(op1->xmm16s(3)); op1->xmmubyte(0x4) = SaturateWordSToByteU(op1->xmm16s(4)); op1->xmmubyte(0x5) = SaturateWordSToByteU(op1->xmm16s(5)); op1->xmmubyte(0x6) = SaturateWordSToByteU(op1->xmm16s(6)); op1->xmmubyte(0x7) = SaturateWordSToByteU(op1->xmm16s(7)); op1->xmmubyte(0x8) = SaturateWordSToByteU(op2->xmm16s(0)); op1->xmmubyte(0x9) = SaturateWordSToByteU(op2->xmm16s(1)); op1->xmmubyte(0xA) = SaturateWordSToByteU(op2->xmm16s(2)); op1->xmmubyte(0xB) = SaturateWordSToByteU(op2->xmm16s(3)); op1->xmmubyte(0xC) = SaturateWordSToByteU(op2->xmm16s(4)); op1->xmmubyte(0xD) = SaturateWordSToByteU(op2->xmm16s(5)); op1->xmmubyte(0xE) = SaturateWordSToByteU(op2->xmm16s(6)); op1->xmmubyte(0xF) = SaturateWordSToByteU(op2->xmm16s(7)); } BX_CPP_INLINE void sse_packsswb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmmsbyte(0x0) = SaturateWordSToByteS(op1->xmm16s(0)); op1->xmmsbyte(0x1) = SaturateWordSToByteS(op1->xmm16s(1)); op1->xmmsbyte(0x2) = SaturateWordSToByteS(op1->xmm16s(2)); op1->xmmsbyte(0x3) = SaturateWordSToByteS(op1->xmm16s(3)); op1->xmmsbyte(0x4) = SaturateWordSToByteS(op1->xmm16s(4)); op1->xmmsbyte(0x5) = SaturateWordSToByteS(op1->xmm16s(5)); op1->xmmsbyte(0x6) = SaturateWordSToByteS(op1->xmm16s(6)); op1->xmmsbyte(0x7) = SaturateWordSToByteS(op1->xmm16s(7)); op1->xmmsbyte(0x8) = SaturateWordSToByteS(op2->xmm16s(0)); op1->xmmsbyte(0x9) = SaturateWordSToByteS(op2->xmm16s(1)); op1->xmmsbyte(0xA) = SaturateWordSToByteS(op2->xmm16s(2)); op1->xmmsbyte(0xB) = SaturateWordSToByteS(op2->xmm16s(3)); op1->xmmsbyte(0xC) = SaturateWordSToByteS(op2->xmm16s(4)); op1->xmmsbyte(0xD) = SaturateWordSToByteS(op2->xmm16s(5)); op1->xmmsbyte(0xE) = SaturateWordSToByteS(op2->xmm16s(6)); op1->xmmsbyte(0xF) = SaturateWordSToByteS(op2->xmm16s(7)); } BX_CPP_INLINE void sse_packusdw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16u(0) = SaturateDwordSToWordU(op1->xmm32s(0)); op1->xmm16u(1) = SaturateDwordSToWordU(op1->xmm32s(1)); op1->xmm16u(2) = SaturateDwordSToWordU(op1->xmm32s(2)); op1->xmm16u(3) = SaturateDwordSToWordU(op1->xmm32s(3)); op1->xmm16u(4) = SaturateDwordSToWordU(op2->xmm32s(0)); op1->xmm16u(5) = SaturateDwordSToWordU(op2->xmm32s(1)); op1->xmm16u(6) = SaturateDwordSToWordU(op2->xmm32s(2)); op1->xmm16u(7) = SaturateDwordSToWordU(op2->xmm32s(3)); } BX_CPP_INLINE void sse_packssdw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16s(0) = SaturateDwordSToWordS(op1->xmm32s(0)); op1->xmm16s(1) = SaturateDwordSToWordS(op1->xmm32s(1)); op1->xmm16s(2) = SaturateDwordSToWordS(op1->xmm32s(2)); op1->xmm16s(3) = SaturateDwordSToWordS(op1->xmm32s(3)); op1->xmm16s(4) = SaturateDwordSToWordS(op2->xmm32s(0)); op1->xmm16s(5) = SaturateDwordSToWordS(op2->xmm32s(1)); op1->xmm16s(6) = SaturateDwordSToWordS(op2->xmm32s(2)); op1->xmm16s(7) = SaturateDwordSToWordS(op2->xmm32s(3)); } // shuffle BX_CPP_INLINE void sse_pshufb(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { unsigned mask = op2->xmmubyte(n); if (mask & 0x80) r->xmmubyte(n) = 0; else r->xmmubyte(n) = op1->xmmubyte(mask & 0xf); } } BX_CPP_INLINE void sse_pshufhw(BxPackedXmmRegister *r, const BxPackedXmmRegister *op, Bit8u order) { r->xmm64u(0) = op->xmm64u(0); r->xmm16u(4) = op->xmm16u(4 + ((order >> 0) & 0x3)); r->xmm16u(5) = op->xmm16u(4 + ((order >> 2) & 0x3)); r->xmm16u(6) = op->xmm16u(4 + ((order >> 4) & 0x3)); r->xmm16u(7) = op->xmm16u(4 + ((order >> 6) & 0x3)); } BX_CPP_INLINE void sse_pshuflw(BxPackedXmmRegister *r, const BxPackedXmmRegister *op, Bit8u order) { r->xmm16u(0) = op->xmm16u((order >> 0) & 0x3); r->xmm16u(1) = op->xmm16u((order >> 2) & 0x3); r->xmm16u(2) = op->xmm16u((order >> 4) & 0x3); r->xmm16u(3) = op->xmm16u((order >> 6) & 0x3); r->xmm64u(1) = op->xmm64u(1); } BX_CPP_INLINE void sse_shufps(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, Bit8u order) { r->xmm32u(0) = op1->xmm32u((order >> 0) & 0x3); r->xmm32u(1) = op1->xmm32u((order >> 2) & 0x3); r->xmm32u(2) = op2->xmm32u((order >> 4) & 0x3); r->xmm32u(3) = op2->xmm32u((order >> 6) & 0x3); } BX_CPP_INLINE void sse_shufpd(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, Bit8u order) { r->xmm64u(0) = op1->xmm64u((order >> 0) & 0x1); r->xmm64u(1) = op2->xmm64u((order >> 1) & 0x1); } BX_CPP_INLINE void sse_permilps(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { r->xmm32u(0) = op1->xmm32u(op2->xmm32u(0) & 0x3); r->xmm32u(1) = op1->xmm32u(op2->xmm32u(1) & 0x3); r->xmm32u(2) = op1->xmm32u(op2->xmm32u(2) & 0x3); r->xmm32u(3) = op1->xmm32u(op2->xmm32u(3) & 0x3); } BX_CPP_INLINE void sse_permilpd(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { r->xmm64u(0) = op1->xmm64u((op2->xmm32u(0) >> 1) & 0x1); r->xmm64u(1) = op1->xmm64u((op2->xmm32u(2) >> 1) & 0x1); } BX_CPP_INLINE void sse_permil2ps(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, unsigned m2z) { for(unsigned n=0; n < 4; n++) { Bit32u ctrl = op3->xmm32u(n); if ((m2z ^ ((ctrl >> 3) & 0x1)) == 0x3) r->xmm32u(n) = 0; else r->xmm32u(n) = (ctrl & 0x4) ? op1->xmm32u(ctrl & 0x3) : op2->xmm32u(ctrl & 0x3); } } BX_CPP_INLINE void sse_permil2pd(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, unsigned m2z) { for(unsigned n=0; n < 2; n++) { Bit32u ctrl = op3->xmm32u(n*2); if ((m2z ^ ((ctrl >> 3) & 0x1)) == 0x3) r->xmm64u(n) = 0; else r->xmm64u(n) = (ctrl & 0x4) ? op1->xmm64u((ctrl >> 1) & 0x1) : op2->xmm64u((ctrl >> 1) & 0x1); } } // sign BX_CPP_INLINE void sse_psignb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { int sign = (op2->xmmsbyte(n) > 0) - (op2->xmmsbyte(n) < 0); op1->xmmsbyte(n) *= sign; } } BX_CPP_INLINE void sse_psignw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { int sign = (op2->xmm16s(n) > 0) - (op2->xmm16s(n) < 0); op1->xmm16s(n) *= sign; } } BX_CPP_INLINE void sse_psignd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { int sign = (op2->xmm32s(n) > 0) - (op2->xmm32s(n) < 0); op1->xmm32s(n) *= sign; } } // mask creation BX_CPP_INLINE Bit32u sse_pmovmskb(const BxPackedXmmRegister *op) { unsigned mask = 0; if(op->xmmubyte(0x0) & 0x80) mask |= 0x0001; if(op->xmmubyte(0x1) & 0x80) mask |= 0x0002; if(op->xmmubyte(0x2) & 0x80) mask |= 0x0004; if(op->xmmubyte(0x3) & 0x80) mask |= 0x0008; if(op->xmmubyte(0x4) & 0x80) mask |= 0x0010; if(op->xmmubyte(0x5) & 0x80) mask |= 0x0020; if(op->xmmubyte(0x6) & 0x80) mask |= 0x0040; if(op->xmmubyte(0x7) & 0x80) mask |= 0x0080; if(op->xmmubyte(0x8) & 0x80) mask |= 0x0100; if(op->xmmubyte(0x9) & 0x80) mask |= 0x0200; if(op->xmmubyte(0xA) & 0x80) mask |= 0x0400; if(op->xmmubyte(0xB) & 0x80) mask |= 0x0800; if(op->xmmubyte(0xC) & 0x80) mask |= 0x1000; if(op->xmmubyte(0xD) & 0x80) mask |= 0x2000; if(op->xmmubyte(0xE) & 0x80) mask |= 0x4000; if(op->xmmubyte(0xF) & 0x80) mask |= 0x8000; return mask; } BX_CPP_INLINE Bit32u sse_pmovmskd(const BxPackedXmmRegister *op) { unsigned mask = 0; if(op->xmm32u(0) & 0x80000000) mask |= 0x1; if(op->xmm32u(1) & 0x80000000) mask |= 0x2; if(op->xmm32u(2) & 0x80000000) mask |= 0x4; if(op->xmm32u(3) & 0x80000000) mask |= 0x8; return mask; } BX_CPP_INLINE Bit32u sse_pmovmskq(const BxPackedXmmRegister *op) { unsigned mask = 0; if(op->xmm32u(1) & 0x80000000) mask |= 0x1; if(op->xmm32u(3) & 0x80000000) mask |= 0x2; return mask; } // blend BX_CPP_INLINE void sse_pblendw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, unsigned mask) { if (mask & 0x01) op1->xmm16u(0) = op2->xmm16u(0); if (mask & 0x02) op1->xmm16u(1) = op2->xmm16u(1); if (mask & 0x04) op1->xmm16u(2) = op2->xmm16u(2); if (mask & 0x08) op1->xmm16u(3) = op2->xmm16u(3); if (mask & 0x10) op1->xmm16u(4) = op2->xmm16u(4); if (mask & 0x20) op1->xmm16u(5) = op2->xmm16u(5); if (mask & 0x40) op1->xmm16u(6) = op2->xmm16u(6); if (mask & 0x80) op1->xmm16u(7) = op2->xmm16u(7); } BX_CPP_INLINE void sse_blendps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, unsigned mask) { if (mask & 0x1) op1->xmm32u(0) = op2->xmm32u(0); if (mask & 0x2) op1->xmm32u(1) = op2->xmm32u(1); if (mask & 0x4) op1->xmm32u(2) = op2->xmm32u(2); if (mask & 0x8) op1->xmm32u(3) = op2->xmm32u(3); } BX_CPP_INLINE void sse_blendpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, unsigned mask) { if (mask & 0x1) op1->xmm64u(0) = op2->xmm64u(0); if (mask & 0x2) op1->xmm64u(1) = op2->xmm64u(1); } BX_CPP_INLINE void sse_pblendvb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *mask) { for(unsigned n=0; n<16; n++) { if (mask->xmmubyte(n) & 0x80) op1->xmmubyte(n) = op2->xmmubyte(n); } } BX_CPP_INLINE void sse_blendvps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *mask) { for(unsigned n=0; n<4; n++) { if (mask->xmm32u(n) & 0x80000000) op1->xmm32u(n) = op2->xmm32u(n); } } BX_CPP_INLINE void sse_blendvpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *mask) { if (mask->xmm32u(1) & 0x80000000) op1->xmm64u(0) = op2->xmm64u(0); if (mask->xmm32u(3) & 0x80000000) op1->xmm64u(1) = op2->xmm64u(1); } // arithmetic (logic) BX_CPP_INLINE void sse_andps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm64u(0) &= op2->xmm64u(0); op1->xmm64u(1) &= op2->xmm64u(1); } BX_CPP_INLINE void sse_andnps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm64u(0) = ~(op1->xmm64u(0)) & op2->xmm64u(0); op1->xmm64u(1) = ~(op1->xmm64u(1)) & op2->xmm64u(1); } BX_CPP_INLINE void sse_orps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm64u(0) |= op2->xmm64u(0); op1->xmm64u(1) |= op2->xmm64u(1); } BX_CPP_INLINE void sse_xorps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm64u(0) ^= op2->xmm64u(0); op1->xmm64u(1) ^= op2->xmm64u(1); } // arithmetic (add/sub) BX_CPP_INLINE void sse_paddb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) += op2->xmmubyte(n); } } BX_CPP_INLINE void sse_paddw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) += op2->xmm16u(n); } } BX_CPP_INLINE void sse_paddd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) += op2->xmm32u(n); } } BX_CPP_INLINE void sse_paddq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) += op2->xmm64u(n); } } BX_CPP_INLINE void sse_psubb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) -= op2->xmmubyte(n); } } BX_CPP_INLINE void sse_psubw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) -= op2->xmm16u(n); } } BX_CPP_INLINE void sse_psubd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) -= op2->xmm32u(n); } } BX_CPP_INLINE void sse_psubq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) -= op2->xmm64u(n); } } // arithmetic (add/sub with saturation) BX_CPP_INLINE void sse_paddsb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmsbyte(n) = SaturateWordSToByteS(Bit16s(op1->xmmsbyte(n)) + Bit16s(op2->xmmsbyte(n))); } } BX_CPP_INLINE void sse_paddsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16s(n) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(n)) + Bit32s(op2->xmm16s(n))); } } BX_CPP_INLINE void sse_paddusb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = SaturateWordSToByteU(Bit16s(op1->xmmubyte(n)) + Bit16s(op2->xmmubyte(n))); } } BX_CPP_INLINE void sse_paddusw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = SaturateDwordSToWordU(Bit32s(op1->xmm16u(n)) + Bit32s(op2->xmm16u(n))); } } BX_CPP_INLINE void sse_psubsb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmsbyte(n) = SaturateWordSToByteS(Bit16s(op1->xmmsbyte(n)) - Bit16s(op2->xmmsbyte(n))); } } BX_CPP_INLINE void sse_psubsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16s(n) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(n)) - Bit32s(op2->xmm16s(n))); } } BX_CPP_INLINE void sse_psubusb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { if(op1->xmmubyte(n) > op2->xmmubyte(n)) op1->xmmubyte(n) -= op2->xmmubyte(n); else op1->xmmubyte(n) = 0; } } BX_CPP_INLINE void sse_psubusw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { if(op1->xmm16u(n) > op2->xmm16u(n)) op1->xmm16u(n) -= op2->xmm16u(n); else op1->xmm16u(n) = 0; } } // arithmetic (horizontal add/sub) BX_CPP_INLINE void sse_phaddw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16u(0) = op1->xmm16u(0) + op1->xmm16u(1); op1->xmm16u(1) = op1->xmm16u(2) + op1->xmm16u(3); op1->xmm16u(2) = op1->xmm16u(4) + op1->xmm16u(5); op1->xmm16u(3) = op1->xmm16u(6) + op1->xmm16u(7); op1->xmm16u(4) = op2->xmm16u(0) + op2->xmm16u(1); op1->xmm16u(5) = op2->xmm16u(2) + op2->xmm16u(3); op1->xmm16u(6) = op2->xmm16u(4) + op2->xmm16u(5); op1->xmm16u(7) = op2->xmm16u(6) + op2->xmm16u(7); } BX_CPP_INLINE void sse_phaddd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm32u(0) = op1->xmm32u(0) + op1->xmm32u(1); op1->xmm32u(1) = op1->xmm32u(2) + op1->xmm32u(3); op1->xmm32u(2) = op2->xmm32u(0) + op2->xmm32u(1); op1->xmm32u(3) = op2->xmm32u(2) + op2->xmm32u(3); } BX_CPP_INLINE void sse_phaddsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16s(0) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(0)) + Bit32s(op1->xmm16s(1))); op1->xmm16s(1) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(2)) + Bit32s(op1->xmm16s(3))); op1->xmm16s(2) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(4)) + Bit32s(op1->xmm16s(5))); op1->xmm16s(3) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(6)) + Bit32s(op1->xmm16s(7))); op1->xmm16s(4) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(0)) + Bit32s(op2->xmm16s(1))); op1->xmm16s(5) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(2)) + Bit32s(op2->xmm16s(3))); op1->xmm16s(6) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(4)) + Bit32s(op2->xmm16s(5))); op1->xmm16s(7) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(6)) + Bit32s(op2->xmm16s(7))); } BX_CPP_INLINE void sse_phsubw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16u(0) = op1->xmm16u(0) - op1->xmm16u(1); op1->xmm16u(1) = op1->xmm16u(2) - op1->xmm16u(3); op1->xmm16u(2) = op1->xmm16u(4) - op1->xmm16u(5); op1->xmm16u(3) = op1->xmm16u(6) - op1->xmm16u(7); op1->xmm16u(4) = op2->xmm16u(0) - op2->xmm16u(1); op1->xmm16u(5) = op2->xmm16u(2) - op2->xmm16u(3); op1->xmm16u(6) = op2->xmm16u(4) - op2->xmm16u(5); op1->xmm16u(7) = op2->xmm16u(6) - op2->xmm16u(7); } BX_CPP_INLINE void sse_phsubd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm32u(0) = op1->xmm32u(0) - op1->xmm32u(1); op1->xmm32u(1) = op1->xmm32u(2) - op1->xmm32u(3); op1->xmm32u(2) = op2->xmm32u(0) - op2->xmm32u(1); op1->xmm32u(3) = op2->xmm32u(2) - op2->xmm32u(3); } BX_CPP_INLINE void sse_phsubsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm16s(0) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(0)) - Bit32s(op1->xmm16s(1))); op1->xmm16s(1) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(2)) - Bit32s(op1->xmm16s(3))); op1->xmm16s(2) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(4)) - Bit32s(op1->xmm16s(5))); op1->xmm16s(3) = SaturateDwordSToWordS(Bit32s(op1->xmm16s(6)) - Bit32s(op1->xmm16s(7))); op1->xmm16s(4) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(0)) - Bit32s(op2->xmm16s(1))); op1->xmm16s(5) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(2)) - Bit32s(op2->xmm16s(3))); op1->xmm16s(6) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(4)) - Bit32s(op2->xmm16s(5))); op1->xmm16s(7) = SaturateDwordSToWordS(Bit32s(op2->xmm16s(6)) - Bit32s(op2->xmm16s(7))); } // average BX_CPP_INLINE void sse_pavgb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmubyte(n) + op2->xmmubyte(n) + 1) >> 1; } } BX_CPP_INLINE void sse_pavgw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16u(n) + op2->xmm16u(n) + 1) >> 1; } } // multiply BX_CPP_INLINE void sse_pmullw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { Bit32u product = Bit32u(op1->xmm16u(n)) * Bit32u(op2->xmm16u(n)); op1->xmm16u(n) = product & 0xffff; } } BX_CPP_INLINE void sse_pmulhw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { Bit32s product = Bit32s(op1->xmm16s(n)) * Bit32s(op2->xmm16s(n)); op1->xmm16u(n) = (Bit16u)(product >> 16); } } BX_CPP_INLINE void sse_pmulhuw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { Bit32u product = Bit32u(op1->xmm16u(n)) * Bit32u(op2->xmm16u(n)); op1->xmm16u(n) = (Bit16u)(product >> 16); } } BX_CPP_INLINE void sse_pmulld(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { Bit64s product = Bit64s(op1->xmm32s(n)) * Bit64s(op2->xmm32s(n)); op1->xmm32u(n) = (Bit32u)(product & 0xffffffff); } } BX_CPP_INLINE void sse_pmuldq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm64s(0) = Bit64s(op1->xmm32s(0)) * Bit64s(op2->xmm32s(0)); op1->xmm64s(1) = Bit64s(op1->xmm32s(2)) * Bit64s(op2->xmm32s(2)); } BX_CPP_INLINE void sse_pmuludq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { op1->xmm64u(0) = Bit64u(op1->xmm32u(0)) * Bit64u(op2->xmm32u(0)); op1->xmm64u(1) = Bit64u(op1->xmm32u(2)) * Bit64u(op2->xmm32u(2)); } BX_CPP_INLINE void sse_pmulhrsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (((op1->xmm16s(n) * op2->xmm16s(n)) >> 14) + 1) >> 1; } } // multiply/add BX_CPP_INLINE void sse_pmaddubsw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { Bit32s temp = Bit32s(op1->xmmubyte(n*2)) * Bit32s(op2->xmmsbyte(n*2)) + Bit32s(op1->xmmubyte(n*2+1)) * Bit32s(op2->xmmsbyte(n*2+1)); op1->xmm16s(n) = SaturateDwordSToWordS(temp); } } BX_CPP_INLINE void sse_pmaddwd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { if((op1->xmm32u(n) & op2->xmm32u(n)) == 0x80008000) { op1->xmm32u(n) = 0x80000000; } else { op1->xmm32u(n) = Bit32s(op1->xmm16s(n*2)) * Bit32s(op2->xmm16s(n*2)) + Bit32s(op1->xmm16s(n*2+1)) * Bit32s(op2->xmm16s(n*2+1)); } } } // broadcast BX_CPP_INLINE void sse_pbroadcastb(BxPackedXmmRegister *op, Bit8u val_8) { for(unsigned n=0; n<16; n++) { op->xmmubyte(n) = val_8; } } BX_CPP_INLINE void sse_pbroadcastw(BxPackedXmmRegister *op, Bit8u val_16) { for(unsigned n=0; n<8; n++) { op->xmm16u(n) = val_16; } } BX_CPP_INLINE void sse_pbroadcastd(BxPackedXmmRegister *op, Bit32u val_32) { for(unsigned n=0; n<4; n++) { op->xmm32u(n) = val_32; } } BX_CPP_INLINE void sse_pbroadcastq(BxPackedXmmRegister *op, Bit64u val_64) { for(unsigned n=0; n<2; n++) { op->xmm64u(n) = val_64; } } // sum of absolute differences (SAD) BX_CPP_INLINE void sse_psadbw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { Bit16u temp1 = 0, temp2 = 0; temp1 += abs(op1->xmmubyte(0x0) - op2->xmmubyte(0x0)); temp1 += abs(op1->xmmubyte(0x1) - op2->xmmubyte(0x1)); temp1 += abs(op1->xmmubyte(0x2) - op2->xmmubyte(0x2)); temp1 += abs(op1->xmmubyte(0x3) - op2->xmmubyte(0x3)); temp1 += abs(op1->xmmubyte(0x4) - op2->xmmubyte(0x4)); temp1 += abs(op1->xmmubyte(0x5) - op2->xmmubyte(0x5)); temp1 += abs(op1->xmmubyte(0x6) - op2->xmmubyte(0x6)); temp1 += abs(op1->xmmubyte(0x7) - op2->xmmubyte(0x7)); temp2 += abs(op1->xmmubyte(0x8) - op2->xmmubyte(0x8)); temp2 += abs(op1->xmmubyte(0x9) - op2->xmmubyte(0x9)); temp2 += abs(op1->xmmubyte(0xA) - op2->xmmubyte(0xA)); temp2 += abs(op1->xmmubyte(0xB) - op2->xmmubyte(0xB)); temp2 += abs(op1->xmmubyte(0xC) - op2->xmmubyte(0xC)); temp2 += abs(op1->xmmubyte(0xD) - op2->xmmubyte(0xD)); temp2 += abs(op1->xmmubyte(0xE) - op2->xmmubyte(0xE)); temp2 += abs(op1->xmmubyte(0xF) - op2->xmmubyte(0xF)); op1->xmm64u(0) = Bit64u(temp1); op1->xmm64u(1) = Bit64u(temp2); } // multiple sum of absolute differences (MSAD) BX_CPP_INLINE void sse_mpsadbw(BxPackedXmmRegister *r, const BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, Bit8u offset) { unsigned src_offset = (offset & 0x3) * 4; unsigned dst_offset = ((offset >> 2) & 1) * 4; for (unsigned j=0; j < 8; j++) { r->xmm16u(j) = 0; for (unsigned k=0; k < 4; k++) { Bit8u temp1 = op1->xmmubyte(j + k + dst_offset); Bit8u temp2 = op2->xmmubyte( k + src_offset); if (temp1 > temp2) r->xmm16u(j) += (temp1 - temp2); else r->xmm16u(j) += (temp2 - temp1); } } } // bitwise select BX_CPP_INLINE void sse_pselect(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3) { for(unsigned n=0;n < 2;n++) { op1->xmm64u(n) = (op3->xmm64u(n) & op1->xmm64u(n)) | (~op3->xmm64u(n) & op2->xmm64u(n)); } } // shift BX_CPP_INLINE void sse_psravd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for (unsigned n=0; n < 4; n++) { Bit32u shift = op2->xmm32u(n); if(shift > 31) op1->xmm32u(n) = (op1->xmm32u(n) & 0x80000000) ? 0xffffffff : 0; else op1->xmm32u(n) = (Bit32u)(op1->xmm32s(n) >> shift); } } BX_CPP_INLINE void sse_psllvd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for (unsigned n=0; n < 4; n++) { Bit32u shift = op2->xmm32u(n); if(shift > 31) op1->xmm32u(n) = 0; else op1->xmm32u(n) <<= shift; } } BX_CPP_INLINE void sse_psllvq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for (unsigned n=0; n < 2; n++) { Bit64u shift = op2->xmm64u(n); if(shift > 63) op1->xmm64u(n) = 0; else op1->xmm64u(n) <<= shift; } } BX_CPP_INLINE void sse_psrlvd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for (unsigned n=0; n < 4; n++) { Bit32u shift = op2->xmm32u(n); if(shift > 31) op1->xmm32u(n) = 0; else op1->xmm32u(n) >>= shift; } } BX_CPP_INLINE void sse_psrlvq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for (unsigned n=0; n < 2; n++) { Bit64u shift = op2->xmm64u(n); if(shift > 63) op1->xmm64u(n) = 0; else op1->xmm64u(n) >>= shift; } } BX_CPP_INLINE void sse_psraw(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 15) { for (unsigned n=0; n < 8; n++) op->xmm16u(n) = (op->xmm16u(n) & 0x8000) ? 0xffff : 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 8; n++) op->xmm16u(n) = (Bit16u)(op->xmm16s(n) >> shift); } } BX_CPP_INLINE void sse_psrad(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 31) { for (unsigned n=0; n < 4; n++) op->xmm32u(n) = (op->xmm32u(n) & 0x80000000) ? 0xffffffff : 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 4; n++) op->xmm32u(n) = (Bit32u)(op->xmm32s(n) >> shift); } } BX_CPP_INLINE void sse_psrlw(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 15) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 8; n++) op->xmm16u(n) >>= shift; } } BX_CPP_INLINE void sse_psrld(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 31) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 4; n++) op->xmm32u(n) >>= shift; } } BX_CPP_INLINE void sse_psrlq(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 64) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 2; n++) op->xmm64u(n) >>= shift; } } BX_CPP_INLINE void sse_psllw(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 15) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 8; n++) op->xmm16u(n) <<= shift; } } BX_CPP_INLINE void sse_pslld(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 31) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 4; n++) op->xmm32u(n) <<= shift; } } BX_CPP_INLINE void sse_psllq(BxPackedXmmRegister *op, Bit64u shift_64) { if(shift_64 > 63) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { Bit8u shift = (Bit8u) shift_64; for (unsigned n=0; n < 2; n++) op->xmm64u(n) <<= shift; } } BX_CPP_INLINE void sse_psrldq(BxPackedXmmRegister *op, Bit8u shift) { if(shift > 15) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { if (shift > 7) { op->xmm64u(0) = op->xmm64u(1); op->xmm64u(1) = 0; shift -= 8; } shift <<= 3; if (shift != 0) { op->xmm64u(0) = (op->xmm64u(0) >> shift) | (op->xmm64u(1) << (64-shift)); op->xmm64u(1) = (op->xmm64u(1) >> shift); } } } BX_CPP_INLINE void sse_pslldq(BxPackedXmmRegister *op, Bit8u shift) { if(shift > 15) { op->xmm64u(0) = 0; op->xmm64u(1) = 0; } else { if (shift > 7) { op->xmm64u(1) = op->xmm64u(0); op->xmm64u(0) = 0; shift -= 8; } shift <<= 3; if (shift != 0) { op->xmm64u(1) = (op->xmm64u(1) << shift) | (op->xmm64u(0) >> (64-shift)); op->xmm64u(0) = (op->xmm64u(0) << shift); } } } BX_CPP_INLINE void sse_palignr(BxPackedXmmRegister *op2, const BxPackedXmmRegister *op1, Bit8u shift) { // op2 = [op1:op2] >> shift if (shift > 15) { *op2 = *op1; sse_psrldq(op2, shift - 16); return; } shift <<= 3; if (shift > 64) { shift -= 64; op2->xmm64u(0) = (op2->xmm64u(1) >> shift) | (op1->xmm64u(0) << (64-shift)); op2->xmm64u(1) = (op1->xmm64u(0) >> shift) | (op1->xmm64u(1) << (64-shift)); } else if (shift == 64) { op2->xmm64u(0) = op2->xmm64u(1); op2->xmm64u(1) = op1->xmm64u(0); } else if (shift != 0) { op2->xmm64u(0) = (op2->xmm64u(0) >> shift) | (op2->xmm64u(1) << (64-shift)); op2->xmm64u(1) = (op2->xmm64u(1) >> shift) | (op1->xmm64u(0) << (64-shift)); } } // rotate (right) BX_CPP_INLINE void sse_prorb(BxPackedXmmRegister *op, int shift) { shift &= 0x7; for(unsigned n=0;n<16;n++) { op->xmmubyte(n) = (op->xmmubyte(n) >> shift) | (op->xmmubyte(n) << (8 - shift)); } } BX_CPP_INLINE void sse_prorw(BxPackedXmmRegister *op, int shift) { shift &= 0xf; for(unsigned n=0;n<8;n++) { op->xmm16u(n) = (op->xmm16u(n) >> shift) | (op->xmm16u(n) << (16 - shift)); } } BX_CPP_INLINE void sse_prord(BxPackedXmmRegister *op, int shift) { shift &= 0x1f; for(unsigned n=0;n<4;n++) { op->xmm32u(n) = (op->xmm32u(n) >> shift) | (op->xmm32u(n) << (32 - shift)); } } BX_CPP_INLINE void sse_prorq(BxPackedXmmRegister *op, int shift) { shift &= 0x3f; for(unsigned n=0;n<2;n++) { op->xmm64u(n) = (op->xmm64u(n) >> shift) | (op->xmm64u(n) << (64 - shift)); } } // rotate (left) BX_CPP_INLINE void sse_prolb(BxPackedXmmRegister *op, int shift) { shift &= 0x7; for(unsigned n=0;n<16;n++) { op->xmmubyte(n) = (op->xmmubyte(n) << shift) | (op->xmmubyte(n) >> (8 - shift)); } } BX_CPP_INLINE void sse_prolw(BxPackedXmmRegister *op, int shift) { shift &= 0xf; for(unsigned n=0;n<8;n++) { op->xmm16u(n) = (op->xmm16u(n) << shift) | (op->xmm16u(n) >> (16 - shift)); } } BX_CPP_INLINE void sse_prold(BxPackedXmmRegister *op, int shift) { shift &= 0x1f; for(unsigned n=0;n<4;n++) { op->xmm32u(n) = (op->xmm32u(n) << shift) | (op->xmm32u(n) >> (32 - shift)); } } BX_CPP_INLINE void sse_prolq(BxPackedXmmRegister *op, int shift) { shift &= 0x3f; for(unsigned n=0;n<2;n++) { op->xmm64u(n) = (op->xmm64u(n) << shift) | (op->xmm64u(n) >> (64 - shift)); } } // variable shift/rotate (XOP) BX_CPP_INLINE void sse_protb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 16;n++) { int shift = op2->xmmsbyte(n); if (shift > 0) { // rotate left shift &= 0x7; op1->xmmubyte(n) = (op1->xmmubyte(n) << shift) | (op1->xmmubyte(n) >> (8 - shift)); } else if (shift < 0) { // rotate right shift = -shift & 0x7; op1->xmmubyte(n) = (op1->xmmubyte(n) >> shift) | (op1->xmmubyte(n) << (8 - shift)); } } } BX_CPP_INLINE void sse_protw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 8;n++) { int shift = op2->xmmsbyte(n*2); if (shift > 0) { // rotate left shift &= 0xf; op1->xmm16u(n) = (op1->xmm16u(n) << shift) | (op1->xmm16u(n) >> (16 - shift)); } else if (shift < 0) { // rotate right shift = -shift & 0xf; op1->xmm16u(n) = (op1->xmm16u(n) >> shift) | (op1->xmm16u(n) << (16 - shift)); } } } BX_CPP_INLINE void sse_protd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 4;n++) { int shift = op2->xmmsbyte(n*4); if (shift > 0) { // rotate left shift &= 0x1f; op1->xmm32u(n) = (op1->xmm32u(n) << shift) | (op1->xmm32u(n) >> (32 - shift)); } else if (shift < 0) { // rotate right shift = -shift & 0x1f; op1->xmm32u(n) = (op1->xmm32u(n) >> shift) | (op1->xmm32u(n) << (32 - shift)); } } } BX_CPP_INLINE void sse_protq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 2;n++) { int shift = op2->xmmsbyte(n*8); if (shift > 0) { // rotate left shift &= 0x3f; op1->xmm64u(n) = (op1->xmm64u(n) << shift) | (op1->xmm64u(n) >> (64 - shift)); } else if (shift < 0) { // rotate right shift = -shift & 0x3f; op1->xmm64u(n) = (op1->xmm64u(n) >> shift) | (op1->xmm64u(n) << (64 - shift)); } } } BX_CPP_INLINE void sse_pshab(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 16;n++) { int shift = op2->xmmsbyte(n); if (shift > 0) { // shift left op1->xmmsbyte(n) <<= (shift & 0x7); } else if (shift < 0) { // shift right op1->xmmsbyte(n) >>= (-shift & 0x7); } } } BX_CPP_INLINE void sse_pshaw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 8;n++) { int shift = op2->xmmsbyte(n*2); if (shift > 0) { // shift left op1->xmm16s(n) <<= (shift & 0xf); } else if (shift < 0) { // shift right op1->xmm16s(n) >>= (-shift & 0xf); } } } BX_CPP_INLINE void sse_pshad(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 4;n++) { int shift = op2->xmmsbyte(n*4); if (shift > 0) { // shift left op1->xmm32s(n) <<= (shift & 0x1f); } else if (shift < 0) { // shift right op1->xmm32s(n) >>= (-shift & 0x1f); } } } BX_CPP_INLINE void sse_pshaq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 2;n++) { int shift = op2->xmmsbyte(n*8); if (shift > 0) { // shift left op1->xmm64s(n) <<= (shift & 0x3f); } else if (shift < 0) { // shift right op1->xmm64s(n) >>= (-shift & 0x3f); } } } BX_CPP_INLINE void sse_pshlb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 16;n++) { int shift = op2->xmmsbyte(n); if (shift > 0) { // shift left op1->xmmubyte(n) <<= (shift & 0x7); } else if (shift < 0) { // shift right op1->xmmubyte(n) >>= (-shift & 0x7); } } } BX_CPP_INLINE void sse_pshlw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 8;n++) { int shift = op2->xmmubyte(n*2); if (shift > 0) { // shift left op1->xmm16u(n) <<= (shift & 0xf); } else if (shift < 0) { // shift right op1->xmm16u(n) >>= (-shift & 0xf); } } } BX_CPP_INLINE void sse_pshld(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 4;n++) { int shift = op2->xmmsbyte(n*4); if (shift > 0) { // shift left op1->xmm32u(n) <<= (shift & 0x1f); } else if (shift < 0) { // shift right op1->xmm32u(n) >>= (-shift & 0x1f); } } } BX_CPP_INLINE void sse_pshlq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0;n < 2;n++) { int shift = op2->xmmsbyte(n*8); if (shift > 0) { // shift left op1->xmm64u(n) <<= (shift & 0x3f); } else if (shift < 0) { // shift right op1->xmm64u(n) >>= (-shift & 0x3f); } } } #endif bochs-2.6/cpu/fetchdecode_sse.h0000644000175000017500000013201712020641453016405 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fetchdecode_sse.h 11327 2012-08-08 20:11:27Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2005-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_SSE_FETCHDECODE_TABLES_H #define BX_SSE_FETCHDECODE_TABLES_H /* ********** */ /* SSE Groups */ /* ********** */ static const BxOpcodeInfo_t BxOpcodeGroupSSE_ERR[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_PAUSE[3] = { /* 66 */ { 0, BX_IA_NOP }, /* F3 */ { 0, BX_IA_PAUSE }, /* F2 */ { 0, BX_IA_NOP } }; static const BxOpcodeInfo_t BxOpcodeInfoG17A[8] = { /* 0 */ { BxImmediate_Ib | BxImmediate_Ib2, BX_IA_EXTRQ_UdqIbIb }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE4A_0f78[3] = { /* 66 */ { BxGroup17A, BX_IA_ERROR, BxOpcodeInfoG17A }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { BxImmediate_Ib | BxImmediate_Ib2, BX_IA_INSERTQ_VdqUqIbIb } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE4A_0f79[3] = { /* 66 */ { 0, BX_IA_EXTRQ_VdqUq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_INSERTQ_VdqUdq } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_TZCNT16[3] = { /* 66 */ { 0, BX_IA_BSF_GwEw }, /* F3 */ { 0, BX_IA_TZCNT_GwEw }, /* F2 */ { 0, BX_IA_BSF_GwEw } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_TZCNT32[3] = { /* 66 */ { 0, BX_IA_BSF_GdEd }, /* F3 */ { 0, BX_IA_TZCNT_GdEd }, /* F2 */ { 0, BX_IA_BSF_GdEd } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_TZCNT64[3] = { /* 66 */ { 0, BX_IA_BSF_GqEq }, /* F3 */ { 0, BX_IA_TZCNT_GqEq }, /* F2 */ { 0, BX_IA_BSF_GqEq } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupSSE_LZCNT16[3] = { /* 66 */ { 0, BX_IA_BSR_GwEw }, /* F3 */ { 0, BX_IA_LZCNT_GwEw }, /* F2 */ { 0, BX_IA_BSR_GwEw } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_LZCNT32[3] = { /* 66 */ { 0, BX_IA_BSR_GdEd }, /* F3 */ { 0, BX_IA_LZCNT_GdEd }, /* F2 */ { 0, BX_IA_BSR_GdEd } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_LZCNT64[3] = { /* 66 */ { 0, BX_IA_BSR_GqEq }, /* F3 */ { 0, BX_IA_LZCNT_GqEq }, /* F2 */ { 0, BX_IA_BSR_GqEq } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f10[3] = { /* 66 */ { 0, BX_IA_MOVUPD_VpdWpd }, /* F3 */ { 0, BX_IA_MOVSS_VssWss }, /* F2 */ { 0, BX_IA_MOVSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f11[3] = { /* 66 */ { 0, BX_IA_MOVUPD_WpdVpd }, /* F3 */ { 0, BX_IA_MOVSS_WssVss }, /* F2 */ { 0, BX_IA_MOVSD_WsdVsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f12[3] = { /* 66 */ { 0, BX_IA_MOVLPD_VsdMq }, /* F3 */ { 0, BX_IA_MOVSLDUP_VpsWps }, /* F2 */ { 0, BX_IA_MOVDDUP_VpdWq } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f13M[3] = { /* 66 */ { 0, BX_IA_MOVLPD_MqVsd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f14[3] = { /* 66 */ { 0, BX_IA_UNPCKLPD_VpdWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f15[3] = { /* 66 */ { 0, BX_IA_UNPCKHPD_VpdWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f16[3] = { /* 66 */ { 0, BX_IA_MOVHPD_VsdMq }, /* F3 */ { 0, BX_IA_MOVSHDUP_VpsWps }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f17M[3] = { /* 66 */ { 0, BX_IA_MOVHPD_MqVsd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f28[3] = { /* 66 */ { 0, BX_IA_MOVAPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f29[3] = { /* 66 */ { 0, BX_IA_MOVAPD_WpdVpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2a[3] = { /* 66 */ { 0, BX_IA_CVTPI2PD_VpdQq }, /* F3 */ { 0, BX_IA_CVTSI2SS_VssEd }, /* F2 */ { 0, BX_IA_CVTSI2SD_VsdEd } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2aQ[3] = { /* 66 */ { 0, BX_IA_CVTPI2PD_VpdQq }, /* F3 */ { 0, BX_IA_CVTSI2SS_VssEq }, /* F2 */ { 0, BX_IA_CVTSI2SD_VsdEq } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2bM[3] = { /* 66 */ { 0, BX_IA_MOVNTPD_MpdVpd }, /* F3 */ { 0, BX_IA_MOVNTSS_MssVss }, /* F2 */ { 0, BX_IA_MOVNTSD_MsdVsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2c[3] = { /* 66 */ { 0, BX_IA_CVTTPD2PI_PqWpd }, /* F3 */ { 0, BX_IA_CVTTSS2SI_GdWss }, /* F2 */ { 0, BX_IA_CVTTSD2SI_GdWsd } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2cQ[3] = { /* 66 */ { 0, BX_IA_CVTTPD2PI_PqWpd }, /* F3 */ { 0, BX_IA_CVTTSS2SI_GqWss }, /* F2 */ { 0, BX_IA_CVTTSD2SI_GqWsd } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2d[3] = { /* 66 */ { 0, BX_IA_CVTPD2PI_PqWpd }, /* F3 */ { 0, BX_IA_CVTSS2SI_GdWss }, /* F2 */ { 0, BX_IA_CVTSD2SI_GdWsd } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2dQ[3] = { /* 66 */ { 0, BX_IA_CVTPD2PI_PqWpd }, /* F3 */ { 0, BX_IA_CVTSS2SI_GqWss }, /* F2 */ { 0, BX_IA_CVTSD2SI_GqWsd } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2e[3] = { /* 66 */ { 0, BX_IA_UCOMISD_VsdWsd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f2f[3] = { /* 66 */ { 0, BX_IA_COMISD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f50R[3] = { /* 66 */ { 0, BX_IA_MOVMSKPD_GdVRpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f51[3] = { /* 66 */ { 0, BX_IA_SQRTPD_VpdWpd }, /* F3 */ { 0, BX_IA_SQRTSS_VssWss }, /* F2 */ { 0, BX_IA_SQRTSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f52[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_RSQRTSS_VssWss }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f53[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_RCPSS_VssWss }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f54[3] = { /* 66 */ { 0, BX_IA_ANDPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f55[3] = { /* 66 */ { 0, BX_IA_ANDNPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f56[3] = { /* 66 */ { 0, BX_IA_ORPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f57[3] = { /* 66 */ { 0, BX_IA_XORPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f58[3] = { /* 66 */ { 0, BX_IA_ADDPD_VpdWpd }, /* F3 */ { 0, BX_IA_ADDSS_VssWss }, /* F2 */ { 0, BX_IA_ADDSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f59[3] = { /* 66 */ { 0, BX_IA_MULPD_VpdWpd }, /* F3 */ { 0, BX_IA_MULSS_VssWss }, /* F2 */ { 0, BX_IA_MULSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f5a[3] = { /* 66 */ { 0, BX_IA_CVTPD2PS_VpsWpd }, /* F3 */ { 0, BX_IA_CVTSS2SD_VsdWss }, /* F2 */ { 0, BX_IA_CVTSD2SS_VssWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f5b[3] = { /* 66 */ { 0, BX_IA_CVTPS2DQ_VdqWps }, /* F3 */ { 0, BX_IA_CVTTPS2DQ_VdqWps }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f5c[3] = { /* 66 */ { 0, BX_IA_SUBPD_VpdWpd }, /* F3 */ { 0, BX_IA_SUBSS_VssWss }, /* F2 */ { 0, BX_IA_SUBSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f5d[3] = { /* 66 */ { 0, BX_IA_MINPD_VpdWpd }, /* F3 */ { 0, BX_IA_MINSS_VssWss }, /* F2 */ { 0, BX_IA_MINSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f5e[3] = { /* 66 */ { 0, BX_IA_DIVPD_VpdWpd }, /* F3 */ { 0, BX_IA_DIVSS_VssWss }, /* F2 */ { 0, BX_IA_DIVSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f5f[3] = { /* 66 */ { 0, BX_IA_MAXPD_VpdWpd }, /* F3 */ { 0, BX_IA_MAXSS_VssWss }, /* F2 */ { 0, BX_IA_MAXSD_VsdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f60[3] = { /* 66 */ { 0, BX_IA_PUNPCKLBW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f61[3] = { /* 66 */ { 0, BX_IA_PUNPCKLWD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f62[3] = { /* 66 */ { 0, BX_IA_PUNPCKLDQ_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f63[3] = { /* 66 */ { 0, BX_IA_PACKSSWB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f64[3] = { /* 66 */ { 0, BX_IA_PCMPGTB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f65[3] = { /* 66 */ { 0, BX_IA_PCMPGTW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f66[3] = { /* 66 */ { 0, BX_IA_PCMPGTD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f67[3] = { /* 66 */ { 0, BX_IA_PACKUSWB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f68[3] = { /* 66 */ { 0, BX_IA_PUNPCKHBW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f69[3] = { /* 66 */ { 0, BX_IA_PUNPCKHWD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f6a[3] = { /* 66 */ { 0, BX_IA_PUNPCKHDQ_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f6b[3] = { /* 66 */ { 0, BX_IA_PACKSSDW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f6e[3] = { /* 66 */ { 0, BX_IA_MOVD_VdqEd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f6eQ[3] = { /* 66 */ { 0, BX_IA_MOVQ_VdqEq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f6f[3] = { /* 66 */ { 0, BX_IA_MOVDQA_VdqWdq }, /* F3 */ { 0, BX_IA_MOVDQU_VdqWdq }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f70[3] = { /* 66 */ { 0, BX_IA_PSHUFD_VdqWdqIb }, /* F3 */ { 0, BX_IA_PSHUFHW_VdqWdqIb }, /* F2 */ { 0, BX_IA_PSHUFLW_VdqWdqIb } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f74[3] = { /* 66 */ { 0, BX_IA_PCMPEQB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f75[3] = { /* 66 */ { 0, BX_IA_PCMPEQW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f76[3] = { /* 66 */ { 0, BX_IA_PCMPEQD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f7c[3] = { /* 66 */ { 0, BX_IA_HADDPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_HADDPS_VpsWps } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f7d[3] = { /* 66 */ { 0, BX_IA_HSUBPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_HSUBPS_VpsWps } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f7e[3] = { /* 66 */ { 0, BX_IA_MOVD_EdVd }, /* F3 */ { 0, BX_IA_MOVQ_VqWq }, /* F2 */ { 0, BX_IA_ERROR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f7eQ[3] = { /* 66 */ { 0, BX_IA_MOVQ_EqVq }, /* F3 */ { 0, BX_IA_MOVQ_VqWq }, /* F2 */ { 0, BX_IA_ERROR } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f7f[3] = { /* 66 */ { 0, BX_IA_MOVDQA_WdqVdq }, /* F3 */ { 0, BX_IA_MOVDQU_WdqVdq }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fc2[3] = { /* 66 */ { 0, BX_IA_CMPPD_VpdWpdIb }, /* F3 */ { 0, BX_IA_CMPSS_VssWssIb }, /* F2 */ { 0, BX_IA_CMPSD_VsdWsdIb } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fc4[3] = { /* 66 */ { 0, BX_IA_PINSRW_VdqEwIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fc5R[3] = { /* 66 */ { 0, BX_IA_PEXTRW_GdUdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fc6[3] = { /* 66 */ { 0, BX_IA_SHUFPD_VpdWpdIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd0[3] = { /* 66 */ { 0, BX_IA_ADDSUBPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ADDSUBPS_VpsWps } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd1[3] = { /* 66 */ { 0, BX_IA_PSRLW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd2[3] = { /* 66 */ { 0, BX_IA_PSRLD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd3[3] = { /* 66 */ { 0, BX_IA_PSRLQ_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd4[3] = { /* 66 */ { 0, BX_IA_PADDQ_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd5[3] = { /* 66 */ { 0, BX_IA_PMULLW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd6[3] = { /* 66 */ { 0, BX_IA_MOVQ_WqVq }, /* F3 */ { 0, BX_IA_MOVQ2DQ_VdqQq }, /* F2 */ { 0, BX_IA_MOVDQ2Q_PqVRq } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd7R[3] = { /* 66 */ { 0, BX_IA_PMOVMSKB_GdUdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd8[3] = { /* 66 */ { 0, BX_IA_PSUBUSB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fd9[3] = { /* 66 */ { 0, BX_IA_PSUBUSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fda[3] = { /* 66 */ { 0, BX_IA_PMINUB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fdb[3] = { /* 66 */ { 0, BX_IA_PAND_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fdc[3] = { /* 66 */ { 0, BX_IA_PADDUSB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fdd[3] = { /* 66 */ { 0, BX_IA_PADDUSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fde[3] = { /* 66 */ { 0, BX_IA_PMAXUB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fdf[3] = { /* 66 */ { 0, BX_IA_PANDN_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe0[3] = { /* 66 */ { 0, BX_IA_PAVGB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe1[3] = { /* 66 */ { 0, BX_IA_PSRAW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe2[3] = { /* 66 */ { 0, BX_IA_PSRAD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe3[3] = { /* 66 */ { 0, BX_IA_PAVGW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe4[3] = { /* 66 */ { 0, BX_IA_PMULHUW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe5[3] = { /* 66 */ { 0, BX_IA_PMULHW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe6[3] = { /* 66 */ { 0, BX_IA_CVTTPD2DQ_VqWpd }, /* F3 */ { 0, BX_IA_CVTDQ2PD_VpdWq }, /* F2 */ { 0, BX_IA_CVTPD2DQ_VqWpd } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe7M[3] = { /* 66 */ { 0, BX_IA_MOVNTDQ_MdqVdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe8[3] = { /* 66 */ { 0, BX_IA_PSUBSB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fe9[3] = { /* 66 */ { 0, BX_IA_PSUBSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fea[3] = { /* 66 */ { 0, BX_IA_PMINSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0feb[3] = { /* 66 */ { 0, BX_IA_POR_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fec[3] = { /* 66 */ { 0, BX_IA_PADDSB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fed[3] = { /* 66 */ { 0, BX_IA_PADDSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fee[3] = { /* 66 */ { 0, BX_IA_PMAXSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0fef[3] = { /* 66 */ { 0, BX_IA_PXOR_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff1[3] = { /* 66 */ { 0, BX_IA_PSLLW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff2[3] = { /* 66 */ { 0, BX_IA_PSLLD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff3[3] = { /* 66 */ { 0, BX_IA_PSLLQ_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff4[3] = { /* 66 */ { 0, BX_IA_PMULUDQ_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff5[3] = { /* 66 */ { 0, BX_IA_PMADDWD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff6[3] = { /* 66 */ { 0, BX_IA_PSADBW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff7R[3] = { /* 66 */ { 0, BX_IA_MASKMOVDQU_VdqUdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR }, }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff8[3] = { /* 66 */ { 0, BX_IA_PSUBB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ff9[3] = { /* 66 */ { 0, BX_IA_PSUBW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ffa[3] = { /* 66 */ { 0, BX_IA_PSUBD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ffb[3] = { /* 66 */ { 0, BX_IA_PSUBQ_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ffc[3] = { /* 66 */ { 0, BX_IA_PADDB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ffd[3] = { /* 66 */ { 0, BX_IA_PADDW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0ffe[3] = { /* 66 */ { 0, BX_IA_PADDD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1202[3] = { /* 66 */ { 0, BX_IA_PSRLW_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1204[3] = { /* 66 */ { 0, BX_IA_PSRAW_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1206[3] = { /* 66 */ { 0, BX_IA_PSLLW_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1302[3] = { /* 66 */ { 0, BX_IA_PSRLD_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1304[3] = { /* 66 */ { 0, BX_IA_PSRAD_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1306[3] = { /* 66 */ { 0, BX_IA_PSLLD_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1402[3] = { /* 66 */ { 0, BX_IA_PSRLQ_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G1406[3] = { /* 66 */ { 0, BX_IA_PSLLQ_UdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_G9VMX6[3] = { /* 66 */ { 0, BX_IA_VMCLEAR_Mq }, /* F3 */ { 0, BX_IA_VMXON_Mq }, /* F2 */ { 0, BX_IA_ERROR } }; #if BX_CPU_LEVEL >= 6 static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3800[3] = { /* 66 */ { 0, BX_IA_PSHUFB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3801[3] = { /* 66 */ { 0, BX_IA_PHADDW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3802[3] = { /* 66 */ { 0, BX_IA_PHADDD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3803[3] = { /* 66 */ { 0, BX_IA_PHADDSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3804[3] = { /* 66 */ { 0, BX_IA_PMADDUBSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3805[3] = { /* 66 */ { 0, BX_IA_PHSUBW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3806[3] = { /* 66 */ { 0, BX_IA_PHSUBD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3807[3] = { /* 66 */ { 0, BX_IA_PHSUBSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3808[3] = { /* 66 */ { 0, BX_IA_PSIGNB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3809[3] = { /* 66 */ { 0, BX_IA_PSIGNW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f380a[3] = { /* 66 */ { 0, BX_IA_PSIGND_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f380b[3] = { /* 66 */ { 0, BX_IA_PMULHRSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f381c[3] = { /* 66 */ { 0, BX_IA_PABSB_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f381d[3] = { /* 66 */ { 0, BX_IA_PABSW_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f381e[3] = { /* 66 */ { 0, BX_IA_PABSD_VdqWdq }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f0[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_CRC32_GdEb } }; static const BxOpcodeInfo_t BxOpcodeGroupOsize0f38f0[BX_SUPPORT_X86_64 + 2] = { /* 16 */ { BxPrefixSSE, BX_IA_MOVBE_GwMw, BxOpcodeGroupSSE_0f38f0 }, /* 32 */ { BxPrefixSSE, BX_IA_MOVBE_GdMd, BxOpcodeGroupSSE_0f38f0 }, #if BX_SUPPORT_X86_64 /* 64 */ { BxPrefixSSE, BX_IA_MOVBE_GqMq, BxOpcodeGroupSSE_0f38f0 }, #endif }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f1w[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_CRC32_GdEw } }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f1d[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_CRC32_GdEd } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f1q[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_CRC32_GdEq } }; #endif static const BxOpcodeInfo_t BxOpcodeGroupOsize0f38f1[BX_SUPPORT_X86_64 + 2] = { /* 16 */ { BxPrefixSSE, BX_IA_MOVBE_MwGw, BxOpcodeGroupSSE_0f38f1w }, /* 32 */ { BxPrefixSSE, BX_IA_MOVBE_MdGd, BxOpcodeGroupSSE_0f38f1d }, #if BX_SUPPORT_X86_64 /* 64 */ { BxPrefixSSE, BX_IA_MOVBE_MqGq, BxOpcodeGroupSSE_0f38f1q }, #endif }; static const BxOpcodeInfo_t BxOpcodeGroupOsize_660f38f6[BX_SUPPORT_X86_64 + 2] = { /* 16 */ { 0, BX_IA_ADCX_GdEd }, /* 32 */ { 0, BX_IA_ADCX_GdEd }, #if BX_SUPPORT_X86_64 /* 64 */ { 0, BX_IA_ADCX_GqEq }, #endif }; static const BxOpcodeInfo_t BxOpcodeGroupOsize_f20f38f6[BX_SUPPORT_X86_64 + 2] = { /* 16 */ { 0, BX_IA_ADOX_GdEd }, /* 32 */ { 0, BX_IA_ADOX_GdEd }, #if BX_SUPPORT_X86_64 /* 64 */ { 0, BX_IA_ADOX_GqEq }, #endif }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f38f6[3] = { /* 66 */ { BxOSizeGrp, BX_IA_ERROR, BxOpcodeGroupOsize_660f38f6 }, /* F2 */ { BxOSizeGrp, BX_IA_ERROR, BxOpcodeGroupOsize_f20f38f6 }, /* F3 */ { 0, BX_IA_ERROR }, }; static const BxOpcodeInfo_t BxOpcodeGroupSSE_0f3a0f[3] = { /* 66 */ { 0, BX_IA_PALIGNR_VdqWdqIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; /* ************************************************************************ */ /* 3-byte opcode table (Table A-4, 0F 38) */ static const BxOpcodeInfo_t BxOpcode3ByteTable0f38[256] = { /* 00 */ { BxPrefixSSE, BX_IA_PSHUFB_PqQq, BxOpcodeGroupSSE_0f3800 }, /* 01 */ { BxPrefixSSE, BX_IA_PHADDW_PqQq, BxOpcodeGroupSSE_0f3801 }, /* 02 */ { BxPrefixSSE, BX_IA_PHADDD_PqQq, BxOpcodeGroupSSE_0f3802 }, /* 03 */ { BxPrefixSSE, BX_IA_PHADDSW_PqQq, BxOpcodeGroupSSE_0f3803 }, /* 04 */ { BxPrefixSSE, BX_IA_PMADDUBSW_PqQq, BxOpcodeGroupSSE_0f3804 }, /* 05 */ { BxPrefixSSE, BX_IA_PHSUBW_PqQq, BxOpcodeGroupSSE_0f3805 }, /* 06 */ { BxPrefixSSE, BX_IA_PHSUBD_PqQq, BxOpcodeGroupSSE_0f3806 }, /* 07 */ { BxPrefixSSE, BX_IA_PHSUBSW_PqQq, BxOpcodeGroupSSE_0f3807 }, /* 08 */ { BxPrefixSSE, BX_IA_PSIGNB_PqQq, BxOpcodeGroupSSE_0f3808 }, /* 09 */ { BxPrefixSSE, BX_IA_PSIGNW_PqQq, BxOpcodeGroupSSE_0f3809 }, /* 0A */ { BxPrefixSSE, BX_IA_PSIGND_PqQq, BxOpcodeGroupSSE_0f380a }, /* 0B */ { BxPrefixSSE, BX_IA_PMULHRSW_PqQq, BxOpcodeGroupSSE_0f380b }, /* 0C */ { 0, BX_IA_ERROR }, /* 0D */ { 0, BX_IA_ERROR }, /* 0E */ { 0, BX_IA_ERROR }, /* 0F */ { 0, BX_IA_ERROR }, /* 10 */ { BxPrefixSSE66, BX_IA_PBLENDVB_VdqWdq }, /* 11 */ { 0, BX_IA_ERROR }, /* 12 */ { 0, BX_IA_ERROR }, /* 13 */ { 0, BX_IA_ERROR }, /* 14 */ { BxPrefixSSE66, BX_IA_BLENDVPS_VpsWps }, /* 15 */ { BxPrefixSSE66, BX_IA_BLENDVPD_VpdWpd }, /* 16 */ { 0, BX_IA_ERROR }, /* 17 */ { BxPrefixSSE66, BX_IA_PTEST_VdqWdq }, /* 18 */ { 0, BX_IA_ERROR }, /* 19 */ { 0, BX_IA_ERROR }, /* 1A */ { 0, BX_IA_ERROR }, /* 1B */ { 0, BX_IA_ERROR }, /* 1C */ { BxPrefixSSE, BX_IA_PABSB_PqQq, BxOpcodeGroupSSE_0f381c }, /* 1D */ { BxPrefixSSE, BX_IA_PABSW_PqQq, BxOpcodeGroupSSE_0f381d }, /* 1E */ { BxPrefixSSE, BX_IA_PABSD_PqQq, BxOpcodeGroupSSE_0f381e }, /* 1F */ { 0, BX_IA_ERROR }, /* 20 */ { BxPrefixSSE66, BX_IA_PMOVSXBW_VdqWq }, /* 21 */ { BxPrefixSSE66, BX_IA_PMOVSXBD_VdqWd }, /* 22 */ { BxPrefixSSE66, BX_IA_PMOVSXBQ_VdqWw }, /* 23 */ { BxPrefixSSE66, BX_IA_PMOVSXWD_VdqWq }, /* 24 */ { BxPrefixSSE66, BX_IA_PMOVSXWQ_VdqWd }, /* 25 */ { BxPrefixSSE66, BX_IA_PMOVSXDQ_VdqWq }, /* 26 */ { 0, BX_IA_ERROR }, /* 27 */ { 0, BX_IA_ERROR }, /* 28 */ { BxPrefixSSE66, BX_IA_PMULDQ_VdqWdq }, /* 29 */ { BxPrefixSSE66, BX_IA_PCMPEQQ_VdqWdq }, /* 2A */ { BxPrefixSSE66, BX_IA_MOVNTDQA_VdqMdq }, /* 2B */ { BxPrefixSSE66, BX_IA_PACKUSDW_VdqWdq }, /* 2C */ { 0, BX_IA_ERROR }, /* 2D */ { 0, BX_IA_ERROR }, /* 2E */ { 0, BX_IA_ERROR }, /* 2F */ { 0, BX_IA_ERROR }, /* 30 */ { BxPrefixSSE66, BX_IA_PMOVZXBW_VdqWq }, /* 31 */ { BxPrefixSSE66, BX_IA_PMOVZXBD_VdqWd }, /* 32 */ { BxPrefixSSE66, BX_IA_PMOVZXBQ_VdqWw }, /* 33 */ { BxPrefixSSE66, BX_IA_PMOVZXWD_VdqWq }, /* 34 */ { BxPrefixSSE66, BX_IA_PMOVZXWQ_VdqWd }, /* 35 */ { BxPrefixSSE66, BX_IA_PMOVZXDQ_VdqWq }, /* 36 */ { 0, BX_IA_ERROR }, /* 37 */ { BxPrefixSSE66, BX_IA_PCMPGTQ_VdqWdq }, /* 38 */ { BxPrefixSSE66, BX_IA_PMINSB_VdqWdq }, /* 39 */ { BxPrefixSSE66, BX_IA_PMINSD_VdqWdq }, /* 3A */ { BxPrefixSSE66, BX_IA_PMINUW_VdqWdq }, /* 3B */ { BxPrefixSSE66, BX_IA_PMINUD_VdqWdq }, /* 3C */ { BxPrefixSSE66, BX_IA_PMAXSB_VdqWdq }, /* 3D */ { BxPrefixSSE66, BX_IA_PMAXSD_VdqWdq }, /* 3E */ { BxPrefixSSE66, BX_IA_PMAXUW_VdqWdq }, /* 3F */ { BxPrefixSSE66, BX_IA_PMAXUD_VdqWdq }, /* 40 */ { BxPrefixSSE66, BX_IA_PMULLD_VdqWdq }, /* 41 */ { BxPrefixSSE66, BX_IA_PHMINPOSUW_VdqWdq }, /* 42 */ { 0, BX_IA_ERROR }, /* 43 */ { 0, BX_IA_ERROR }, /* 44 */ { 0, BX_IA_ERROR }, /* 45 */ { 0, BX_IA_ERROR }, /* 46 */ { 0, BX_IA_ERROR }, /* 47 */ { 0, BX_IA_ERROR }, /* 48 */ { 0, BX_IA_ERROR }, /* 49 */ { 0, BX_IA_ERROR }, /* 4A */ { 0, BX_IA_ERROR }, /* 4B */ { 0, BX_IA_ERROR }, /* 4C */ { 0, BX_IA_ERROR }, /* 4D */ { 0, BX_IA_ERROR }, /* 4E */ { 0, BX_IA_ERROR }, /* 4F */ { 0, BX_IA_ERROR }, /* 50 */ { 0, BX_IA_ERROR }, /* 51 */ { 0, BX_IA_ERROR }, /* 52 */ { 0, BX_IA_ERROR }, /* 53 */ { 0, BX_IA_ERROR }, /* 54 */ { 0, BX_IA_ERROR }, /* 55 */ { 0, BX_IA_ERROR }, /* 56 */ { 0, BX_IA_ERROR }, /* 57 */ { 0, BX_IA_ERROR }, /* 58 */ { 0, BX_IA_ERROR }, /* 59 */ { 0, BX_IA_ERROR }, /* 5A */ { 0, BX_IA_ERROR }, /* 5B */ { 0, BX_IA_ERROR }, /* 5C */ { 0, BX_IA_ERROR }, /* 5D */ { 0, BX_IA_ERROR }, /* 5E */ { 0, BX_IA_ERROR }, /* 5F */ { 0, BX_IA_ERROR }, /* 60 */ { 0, BX_IA_ERROR }, /* 61 */ { 0, BX_IA_ERROR }, /* 62 */ { 0, BX_IA_ERROR }, /* 63 */ { 0, BX_IA_ERROR }, /* 64 */ { 0, BX_IA_ERROR }, /* 65 */ { 0, BX_IA_ERROR }, /* 66 */ { 0, BX_IA_ERROR }, /* 67 */ { 0, BX_IA_ERROR }, /* 68 */ { 0, BX_IA_ERROR }, /* 69 */ { 0, BX_IA_ERROR }, /* 6A */ { 0, BX_IA_ERROR }, /* 6B */ { 0, BX_IA_ERROR }, /* 6C */ { 0, BX_IA_ERROR }, /* 6D */ { 0, BX_IA_ERROR }, /* 6E */ { 0, BX_IA_ERROR }, /* 6F */ { 0, BX_IA_ERROR }, /* 70 */ { 0, BX_IA_ERROR }, /* 71 */ { 0, BX_IA_ERROR }, /* 72 */ { 0, BX_IA_ERROR }, /* 73 */ { 0, BX_IA_ERROR }, /* 74 */ { 0, BX_IA_ERROR }, /* 75 */ { 0, BX_IA_ERROR }, /* 76 */ { 0, BX_IA_ERROR }, /* 77 */ { 0, BX_IA_ERROR }, /* 78 */ { 0, BX_IA_ERROR }, /* 79 */ { 0, BX_IA_ERROR }, /* 7A */ { 0, BX_IA_ERROR }, /* 7B */ { 0, BX_IA_ERROR }, /* 7C */ { 0, BX_IA_ERROR }, /* 7D */ { 0, BX_IA_ERROR }, /* 7E */ { 0, BX_IA_ERROR }, /* 7F */ { 0, BX_IA_ERROR }, /* 80 */ { BxPrefixSSE66 | BxTraceEnd, BX_IA_INVEPT }, /* 81 */ { BxPrefixSSE66 | BxTraceEnd, BX_IA_INVVPID }, /* 82 */ { BxPrefixSSE66 | BxTraceEnd, BX_IA_INVPCID }, /* 83 */ { 0, BX_IA_ERROR }, /* 84 */ { 0, BX_IA_ERROR }, /* 85 */ { 0, BX_IA_ERROR }, /* 86 */ { 0, BX_IA_ERROR }, /* 87 */ { 0, BX_IA_ERROR }, /* 88 */ { 0, BX_IA_ERROR }, /* 89 */ { 0, BX_IA_ERROR }, /* 8A */ { 0, BX_IA_ERROR }, /* 8B */ { 0, BX_IA_ERROR }, /* 8C */ { 0, BX_IA_ERROR }, /* 8D */ { 0, BX_IA_ERROR }, /* 8E */ { 0, BX_IA_ERROR }, /* 8F */ { 0, BX_IA_ERROR }, /* 90 */ { 0, BX_IA_ERROR }, /* 91 */ { 0, BX_IA_ERROR }, /* 92 */ { 0, BX_IA_ERROR }, /* 93 */ { 0, BX_IA_ERROR }, /* 94 */ { 0, BX_IA_ERROR }, /* 95 */ { 0, BX_IA_ERROR }, /* 96 */ { 0, BX_IA_ERROR }, /* 97 */ { 0, BX_IA_ERROR }, /* 98 */ { 0, BX_IA_ERROR }, /* 99 */ { 0, BX_IA_ERROR }, /* 9A */ { 0, BX_IA_ERROR }, /* 9B */ { 0, BX_IA_ERROR }, /* 9C */ { 0, BX_IA_ERROR }, /* 9D */ { 0, BX_IA_ERROR }, /* 9E */ { 0, BX_IA_ERROR }, /* 9F */ { 0, BX_IA_ERROR }, /* A0 */ { 0, BX_IA_ERROR }, /* A1 */ { 0, BX_IA_ERROR }, /* A2 */ { 0, BX_IA_ERROR }, /* A3 */ { 0, BX_IA_ERROR }, /* A4 */ { 0, BX_IA_ERROR }, /* A5 */ { 0, BX_IA_ERROR }, /* A6 */ { 0, BX_IA_ERROR }, /* A7 */ { 0, BX_IA_ERROR }, /* A8 */ { 0, BX_IA_ERROR }, /* A9 */ { 0, BX_IA_ERROR }, /* AA */ { 0, BX_IA_ERROR }, /* AB */ { 0, BX_IA_ERROR }, /* AC */ { 0, BX_IA_ERROR }, /* AD */ { 0, BX_IA_ERROR }, /* AE */ { 0, BX_IA_ERROR }, /* AF */ { 0, BX_IA_ERROR }, /* B0 */ { 0, BX_IA_ERROR }, /* B1 */ { 0, BX_IA_ERROR }, /* B2 */ { 0, BX_IA_ERROR }, /* B3 */ { 0, BX_IA_ERROR }, /* B4 */ { 0, BX_IA_ERROR }, /* B5 */ { 0, BX_IA_ERROR }, /* B6 */ { 0, BX_IA_ERROR }, /* B7 */ { 0, BX_IA_ERROR }, /* B8 */ { 0, BX_IA_ERROR }, /* B9 */ { 0, BX_IA_ERROR }, /* BA */ { 0, BX_IA_ERROR }, /* BB */ { 0, BX_IA_ERROR }, /* BC */ { 0, BX_IA_ERROR }, /* BD */ { 0, BX_IA_ERROR }, /* BE */ { 0, BX_IA_ERROR }, /* BF */ { 0, BX_IA_ERROR }, /* C0 */ { 0, BX_IA_ERROR }, /* C1 */ { 0, BX_IA_ERROR }, /* C2 */ { 0, BX_IA_ERROR }, /* C3 */ { 0, BX_IA_ERROR }, /* C4 */ { 0, BX_IA_ERROR }, /* C5 */ { 0, BX_IA_ERROR }, /* C6 */ { 0, BX_IA_ERROR }, /* C7 */ { 0, BX_IA_ERROR }, /* C8 */ { 0, BX_IA_ERROR }, /* C9 */ { 0, BX_IA_ERROR }, /* CA */ { 0, BX_IA_ERROR }, /* CB */ { 0, BX_IA_ERROR }, /* CC */ { 0, BX_IA_ERROR }, /* CD */ { 0, BX_IA_ERROR }, /* CE */ { 0, BX_IA_ERROR }, /* CF */ { 0, BX_IA_ERROR }, /* D0 */ { 0, BX_IA_ERROR }, /* D1 */ { 0, BX_IA_ERROR }, /* D2 */ { 0, BX_IA_ERROR }, /* D3 */ { 0, BX_IA_ERROR }, /* D4 */ { 0, BX_IA_ERROR }, /* D5 */ { 0, BX_IA_ERROR }, /* D6 */ { 0, BX_IA_ERROR }, /* D7 */ { 0, BX_IA_ERROR }, /* D8 */ { 0, BX_IA_ERROR }, /* D9 */ { 0, BX_IA_ERROR }, /* DA */ { 0, BX_IA_ERROR }, /* DB */ { BxPrefixSSE66, BX_IA_AESIMC_VdqWdq }, /* DC */ { BxPrefixSSE66, BX_IA_AESENC_VdqWdq }, /* DD */ { BxPrefixSSE66, BX_IA_AESENCLAST_VdqWdq }, /* DE */ { BxPrefixSSE66, BX_IA_AESDEC_VdqWdq }, /* DF */ { BxPrefixSSE66, BX_IA_AESDECLAST_VdqWdq }, /* E0 */ { 0, BX_IA_ERROR }, /* E1 */ { 0, BX_IA_ERROR }, /* E2 */ { 0, BX_IA_ERROR }, /* E3 */ { 0, BX_IA_ERROR }, /* E4 */ { 0, BX_IA_ERROR }, /* E5 */ { 0, BX_IA_ERROR }, /* E6 */ { 0, BX_IA_ERROR }, /* E7 */ { 0, BX_IA_ERROR }, /* E8 */ { 0, BX_IA_ERROR }, /* E9 */ { 0, BX_IA_ERROR }, /* EA */ { 0, BX_IA_ERROR }, /* EB */ { 0, BX_IA_ERROR }, /* EC */ { 0, BX_IA_ERROR }, /* ED */ { 0, BX_IA_ERROR }, /* EE */ { 0, BX_IA_ERROR }, /* EF */ { 0, BX_IA_ERROR }, /* F0 */ { BxOSizeGrp, BX_IA_ERROR, BxOpcodeGroupOsize0f38f0 }, /* F1 */ { BxOSizeGrp, BX_IA_ERROR, BxOpcodeGroupOsize0f38f1 }, /* F2 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_ERROR }, /* F4 */ { 0, BX_IA_ERROR }, /* F5 */ { 0, BX_IA_ERROR }, /* F6 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f38f6 }, /* F7 */ { 0, BX_IA_ERROR }, /* F8 */ { 0, BX_IA_ERROR }, /* F9 */ { 0, BX_IA_ERROR }, /* FA */ { 0, BX_IA_ERROR }, /* FB */ { 0, BX_IA_ERROR }, /* FC */ { 0, BX_IA_ERROR }, /* FD */ { 0, BX_IA_ERROR }, /* FE */ { 0, BX_IA_ERROR }, /* FF */ { 0, BX_IA_ERROR } }; /* ************************************************************************ */ /* 3-byte opcode table (Table A-5, 0F 3A) */ static const BxOpcodeInfo_t BxOpcode3ByteTable0f3a[256] = { /* 00 */ { 0, BX_IA_ERROR }, /* 01 */ { 0, BX_IA_ERROR }, /* 02 */ { 0, BX_IA_ERROR }, /* 03 */ { 0, BX_IA_ERROR }, /* 04 */ { 0, BX_IA_ERROR }, /* 05 */ { 0, BX_IA_ERROR }, /* 06 */ { 0, BX_IA_ERROR }, /* 07 */ { 0, BX_IA_ERROR }, /* 08 */ { BxPrefixSSE66, BX_IA_ROUNDPS_VpsWpsIb }, /* 09 */ { BxPrefixSSE66, BX_IA_ROUNDPD_VpdWpdIb }, /* 0A */ { BxPrefixSSE66, BX_IA_ROUNDSS_VssWssIb }, /* 0B */ { BxPrefixSSE66, BX_IA_ROUNDSD_VsdWsdIb }, /* 0C */ { BxPrefixSSE66, BX_IA_BLENDPS_VpsWpsIb }, /* 0D */ { BxPrefixSSE66, BX_IA_BLENDPD_VpdWpdIb }, /* 0E */ { BxPrefixSSE66, BX_IA_PBLENDW_VdqWdqIb }, /* 0F */ { BxPrefixSSE, BX_IA_PALIGNR_PqQqIb, BxOpcodeGroupSSE_0f3a0f }, /* 10 */ { 0, BX_IA_ERROR }, /* 11 */ { 0, BX_IA_ERROR }, /* 12 */ { 0, BX_IA_ERROR }, /* 13 */ { 0, BX_IA_ERROR }, /* 14 */ { BxPrefixSSE66, BX_IA_PEXTRB_EbdVdqIb }, /* 15 */ { BxPrefixSSE66, BX_IA_PEXTRW_EwdVdqIb }, /* 16 */ { BxPrefixSSE66, BX_IA_PEXTRD_EdVdqIb }, /* 17 */ { BxPrefixSSE66, BX_IA_EXTRACTPS_EdVpsIb }, /* 18 */ { 0, BX_IA_ERROR }, /* 19 */ { 0, BX_IA_ERROR }, /* 1A */ { 0, BX_IA_ERROR }, /* 1B */ { 0, BX_IA_ERROR }, /* 1C */ { 0, BX_IA_ERROR }, /* 1D */ { 0, BX_IA_ERROR }, /* 1E */ { 0, BX_IA_ERROR }, /* 1F */ { 0, BX_IA_ERROR }, /* 20 */ { BxPrefixSSE66, BX_IA_PINSRB_VdqEbIb }, /* 21 */ { BxPrefixSSE66, BX_IA_INSERTPS_VpsWssIb }, /* 22 */ { BxPrefixSSE66, BX_IA_PINSRD_VdqEdIb }, /* 23 */ { 0, BX_IA_ERROR }, /* 24 */ { 0, BX_IA_ERROR }, /* 25 */ { 0, BX_IA_ERROR }, /* 26 */ { 0, BX_IA_ERROR }, /* 27 */ { 0, BX_IA_ERROR }, /* 28 */ { 0, BX_IA_ERROR }, /* 29 */ { 0, BX_IA_ERROR }, /* 2A */ { 0, BX_IA_ERROR }, /* 2B */ { 0, BX_IA_ERROR }, /* 2C */ { 0, BX_IA_ERROR }, /* 2D */ { 0, BX_IA_ERROR }, /* 2E */ { 0, BX_IA_ERROR }, /* 2F */ { 0, BX_IA_ERROR }, /* 30 */ { 0, BX_IA_ERROR }, /* 31 */ { 0, BX_IA_ERROR }, /* 32 */ { 0, BX_IA_ERROR }, /* 33 */ { 0, BX_IA_ERROR }, /* 34 */ { 0, BX_IA_ERROR }, /* 35 */ { 0, BX_IA_ERROR }, /* 36 */ { 0, BX_IA_ERROR }, /* 37 */ { 0, BX_IA_ERROR }, /* 38 */ { 0, BX_IA_ERROR }, /* 39 */ { 0, BX_IA_ERROR }, /* 3A */ { 0, BX_IA_ERROR }, /* 3B */ { 0, BX_IA_ERROR }, /* 3C */ { 0, BX_IA_ERROR }, /* 3D */ { 0, BX_IA_ERROR }, /* 3E */ { 0, BX_IA_ERROR }, /* 3F */ { 0, BX_IA_ERROR }, /* 40 */ { BxPrefixSSE66, BX_IA_DPPS_VpsWpsIb }, /* 41 */ { BxPrefixSSE66, BX_IA_DPPD_VpdWpdIb }, /* 42 */ { BxPrefixSSE66, BX_IA_MPSADBW_VdqWdqIb }, /* 43 */ { 0, BX_IA_ERROR }, /* 44 */ { BxPrefixSSE66, BX_IA_PCLMULQDQ_VdqWdqIb }, /* 45 */ { 0, BX_IA_ERROR }, /* 46 */ { 0, BX_IA_ERROR }, /* 47 */ { 0, BX_IA_ERROR }, /* 48 */ { 0, BX_IA_ERROR }, /* 49 */ { 0, BX_IA_ERROR }, /* 4A */ { 0, BX_IA_ERROR }, /* 4B */ { 0, BX_IA_ERROR }, /* 4C */ { 0, BX_IA_ERROR }, /* 4D */ { 0, BX_IA_ERROR }, /* 4E */ { 0, BX_IA_ERROR }, /* 4F */ { 0, BX_IA_ERROR }, /* 50 */ { 0, BX_IA_ERROR }, /* 51 */ { 0, BX_IA_ERROR }, /* 52 */ { 0, BX_IA_ERROR }, /* 53 */ { 0, BX_IA_ERROR }, /* 54 */ { 0, BX_IA_ERROR }, /* 55 */ { 0, BX_IA_ERROR }, /* 56 */ { 0, BX_IA_ERROR }, /* 57 */ { 0, BX_IA_ERROR }, /* 58 */ { 0, BX_IA_ERROR }, /* 59 */ { 0, BX_IA_ERROR }, /* 5A */ { 0, BX_IA_ERROR }, /* 5B */ { 0, BX_IA_ERROR }, /* 5C */ { 0, BX_IA_ERROR }, /* 5D */ { 0, BX_IA_ERROR }, /* 5E */ { 0, BX_IA_ERROR }, /* 5F */ { 0, BX_IA_ERROR }, /* 60 */ { BxPrefixSSE66, BX_IA_PCMPESTRM_VdqWdqIb }, /* 61 */ { BxPrefixSSE66, BX_IA_PCMPESTRI_VdqWdqIb }, /* 62 */ { BxPrefixSSE66, BX_IA_PCMPISTRM_VdqWdqIb }, /* 63 */ { BxPrefixSSE66, BX_IA_PCMPISTRI_VdqWdqIb }, /* 64 */ { 0, BX_IA_ERROR }, /* 65 */ { 0, BX_IA_ERROR }, /* 66 */ { 0, BX_IA_ERROR }, /* 67 */ { 0, BX_IA_ERROR }, /* 68 */ { 0, BX_IA_ERROR }, /* 69 */ { 0, BX_IA_ERROR }, /* 6A */ { 0, BX_IA_ERROR }, /* 6B */ { 0, BX_IA_ERROR }, /* 6C */ { 0, BX_IA_ERROR }, /* 6D */ { 0, BX_IA_ERROR }, /* 6E */ { 0, BX_IA_ERROR }, /* 6F */ { 0, BX_IA_ERROR }, /* 70 */ { 0, BX_IA_ERROR }, /* 71 */ { 0, BX_IA_ERROR }, /* 72 */ { 0, BX_IA_ERROR }, /* 73 */ { 0, BX_IA_ERROR }, /* 74 */ { 0, BX_IA_ERROR }, /* 75 */ { 0, BX_IA_ERROR }, /* 76 */ { 0, BX_IA_ERROR }, /* 77 */ { 0, BX_IA_ERROR }, /* 78 */ { 0, BX_IA_ERROR }, /* 79 */ { 0, BX_IA_ERROR }, /* 7A */ { 0, BX_IA_ERROR }, /* 7B */ { 0, BX_IA_ERROR }, /* 7C */ { 0, BX_IA_ERROR }, /* 7D */ { 0, BX_IA_ERROR }, /* 7E */ { 0, BX_IA_ERROR }, /* 7F */ { 0, BX_IA_ERROR }, /* 80 */ { 0, BX_IA_ERROR }, /* 81 */ { 0, BX_IA_ERROR }, /* 82 */ { 0, BX_IA_ERROR }, /* 83 */ { 0, BX_IA_ERROR }, /* 84 */ { 0, BX_IA_ERROR }, /* 85 */ { 0, BX_IA_ERROR }, /* 86 */ { 0, BX_IA_ERROR }, /* 87 */ { 0, BX_IA_ERROR }, /* 88 */ { 0, BX_IA_ERROR }, /* 89 */ { 0, BX_IA_ERROR }, /* 8A */ { 0, BX_IA_ERROR }, /* 8B */ { 0, BX_IA_ERROR }, /* 8C */ { 0, BX_IA_ERROR }, /* 8D */ { 0, BX_IA_ERROR }, /* 8E */ { 0, BX_IA_ERROR }, /* 8F */ { 0, BX_IA_ERROR }, /* 90 */ { 0, BX_IA_ERROR }, /* 91 */ { 0, BX_IA_ERROR }, /* 92 */ { 0, BX_IA_ERROR }, /* 93 */ { 0, BX_IA_ERROR }, /* 94 */ { 0, BX_IA_ERROR }, /* 95 */ { 0, BX_IA_ERROR }, /* 96 */ { 0, BX_IA_ERROR }, /* 97 */ { 0, BX_IA_ERROR }, /* 98 */ { 0, BX_IA_ERROR }, /* 99 */ { 0, BX_IA_ERROR }, /* 9A */ { 0, BX_IA_ERROR }, /* 9B */ { 0, BX_IA_ERROR }, /* 9C */ { 0, BX_IA_ERROR }, /* 9D */ { 0, BX_IA_ERROR }, /* 9E */ { 0, BX_IA_ERROR }, /* 9F */ { 0, BX_IA_ERROR }, /* A0 */ { 0, BX_IA_ERROR }, /* A1 */ { 0, BX_IA_ERROR }, /* A2 */ { 0, BX_IA_ERROR }, /* A3 */ { 0, BX_IA_ERROR }, /* A4 */ { 0, BX_IA_ERROR }, /* A5 */ { 0, BX_IA_ERROR }, /* A6 */ { 0, BX_IA_ERROR }, /* A7 */ { 0, BX_IA_ERROR }, /* A8 */ { 0, BX_IA_ERROR }, /* A9 */ { 0, BX_IA_ERROR }, /* AA */ { 0, BX_IA_ERROR }, /* AB */ { 0, BX_IA_ERROR }, /* AC */ { 0, BX_IA_ERROR }, /* AD */ { 0, BX_IA_ERROR }, /* AE */ { 0, BX_IA_ERROR }, /* AF */ { 0, BX_IA_ERROR }, /* B0 */ { 0, BX_IA_ERROR }, /* B1 */ { 0, BX_IA_ERROR }, /* B2 */ { 0, BX_IA_ERROR }, /* B3 */ { 0, BX_IA_ERROR }, /* B4 */ { 0, BX_IA_ERROR }, /* B5 */ { 0, BX_IA_ERROR }, /* B6 */ { 0, BX_IA_ERROR }, /* B7 */ { 0, BX_IA_ERROR }, /* B8 */ { 0, BX_IA_ERROR }, /* B9 */ { 0, BX_IA_ERROR }, /* BA */ { 0, BX_IA_ERROR }, /* BB */ { 0, BX_IA_ERROR }, /* BC */ { 0, BX_IA_ERROR }, /* BD */ { 0, BX_IA_ERROR }, /* BE */ { 0, BX_IA_ERROR }, /* BF */ { 0, BX_IA_ERROR }, /* C0 */ { 0, BX_IA_ERROR }, /* C1 */ { 0, BX_IA_ERROR }, /* C2 */ { 0, BX_IA_ERROR }, /* C3 */ { 0, BX_IA_ERROR }, /* C4 */ { 0, BX_IA_ERROR }, /* C5 */ { 0, BX_IA_ERROR }, /* C6 */ { 0, BX_IA_ERROR }, /* C7 */ { 0, BX_IA_ERROR }, /* C8 */ { 0, BX_IA_ERROR }, /* C9 */ { 0, BX_IA_ERROR }, /* CA */ { 0, BX_IA_ERROR }, /* CB */ { 0, BX_IA_ERROR }, /* CC */ { 0, BX_IA_ERROR }, /* CD */ { 0, BX_IA_ERROR }, /* CE */ { 0, BX_IA_ERROR }, /* CF */ { 0, BX_IA_ERROR }, /* D0 */ { 0, BX_IA_ERROR }, /* D1 */ { 0, BX_IA_ERROR }, /* D2 */ { 0, BX_IA_ERROR }, /* D3 */ { 0, BX_IA_ERROR }, /* D4 */ { 0, BX_IA_ERROR }, /* D5 */ { 0, BX_IA_ERROR }, /* D6 */ { 0, BX_IA_ERROR }, /* D7 */ { 0, BX_IA_ERROR }, /* D8 */ { 0, BX_IA_ERROR }, /* D9 */ { 0, BX_IA_ERROR }, /* DA */ { 0, BX_IA_ERROR }, /* DB */ { 0, BX_IA_ERROR }, /* DC */ { 0, BX_IA_ERROR }, /* DD */ { 0, BX_IA_ERROR }, /* DE */ { 0, BX_IA_ERROR }, /* DF */ { BxPrefixSSE66, BX_IA_AESKEYGENASSIST_VdqWdqIb }, /* E0 */ { 0, BX_IA_ERROR }, /* E1 */ { 0, BX_IA_ERROR }, /* E2 */ { 0, BX_IA_ERROR }, /* E3 */ { 0, BX_IA_ERROR }, /* E4 */ { 0, BX_IA_ERROR }, /* E5 */ { 0, BX_IA_ERROR }, /* E6 */ { 0, BX_IA_ERROR }, /* E7 */ { 0, BX_IA_ERROR }, /* E8 */ { 0, BX_IA_ERROR }, /* E9 */ { 0, BX_IA_ERROR }, /* EA */ { 0, BX_IA_ERROR }, /* EB */ { 0, BX_IA_ERROR }, /* EC */ { 0, BX_IA_ERROR }, /* ED */ { 0, BX_IA_ERROR }, /* EE */ { 0, BX_IA_ERROR }, /* EF */ { 0, BX_IA_ERROR }, /* F0 */ { 0, BX_IA_ERROR }, /* F1 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_ERROR }, /* F4 */ { 0, BX_IA_ERROR }, /* F5 */ { 0, BX_IA_ERROR }, /* F6 */ { 0, BX_IA_ERROR }, /* F7 */ { 0, BX_IA_ERROR }, /* F8 */ { 0, BX_IA_ERROR }, /* F9 */ { 0, BX_IA_ERROR }, /* FA */ { 0, BX_IA_ERROR }, /* FB */ { 0, BX_IA_ERROR }, /* FC */ { 0, BX_IA_ERROR }, /* FD */ { 0, BX_IA_ERROR }, /* FE */ { 0, BX_IA_ERROR }, /* FF */ { 0, BX_IA_ERROR } }; #endif // BX_CPU_LEVEL >= 6 #endif // BX_SSE_FETCHDECODE_TABLES_H bochs-2.6/cpu/descriptor.h0000644000175000017500000001765312020641453015464 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: descriptor.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2009 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_DESCRIPTOR_H #define BX_DESCRIPTOR_H // // |---------------------------------------------| // | Segment Descriptor | // |---------------------------------------------| // |33222222|2|2|2|2| 11 11 |1|11|1|11 | | // |10987654|3|2|1|0| 98 76 |5|43|2|1098|76543210| // |--------|-|-|-|-|-------|-|--|-|----|--------| // |Base |G|D|L|A|Limit |P|D |S|Type|Base | // |[31-24] | |/| |V|[19-16]| |P | | |[23-16] | // | | |B| |L| | |L | | | | // |------------------------|--------------------| // | Base [15-0] | Limit [15-0] | // |------------------------|--------------------| // typedef struct { /* bx_selector_t */ Bit16u value; /* the 16bit value of the selector */ /* the following fields are extracted from the value field in protected mode only. They're used for sake of efficiency */ Bit16u index; /* 13bit index extracted from value in protected mode */ Bit8u ti; /* table indicator bit extracted from value */ Bit8u rpl; /* RPL extracted from value */ } bx_selector_t; #define BX_SELECTOR_RPL(selector) ((selector) & 0x03) #define BX_SELECTOR_RPL_MASK (0xfffc) typedef struct { // do not go above 4 bits ! #define SegValidCache (0x01) #define SegAccessROK (0x02) #define SegAccessWOK (0x04) unsigned valid; // Holds above values, Or'd together. Used to // hold only 0 or 1. bx_bool p; /* present */ Bit8u dpl; /* descriptor privilege level 0..3 */ bx_bool segment; /* 0 = system/gate, 1 = data/code segment */ Bit8u type; /* For system & gate descriptors: * 0 = invalid descriptor (reserved) * 1 = 286 available Task State Segment (TSS) * 2 = LDT descriptor * 3 = 286 busy Task State Segment (TSS) * 4 = 286 call gate * 5 = task gate * 6 = 286 interrupt gate * 7 = 286 trap gate * 8 = (reserved) * 9 = 386 available TSS * 10 = (reserved) * 11 = 386 busy TSS * 12 = 386 call gate * 13 = (reserved) * 14 = 386 interrupt gate * 15 = 386 trap gate */ // For system & gate descriptors: #define BX_GATE_TYPE_NONE (0x0) #define BX_SYS_SEGMENT_AVAIL_286_TSS (0x1) #define BX_SYS_SEGMENT_LDT (0x2) #define BX_SYS_SEGMENT_BUSY_286_TSS (0x3) #define BX_286_CALL_GATE (0x4) #define BX_TASK_GATE (0x5) #define BX_286_INTERRUPT_GATE (0x6) #define BX_286_TRAP_GATE (0x7) /* 0x8 reserved */ #define BX_SYS_SEGMENT_AVAIL_386_TSS (0x9) /* 0xa reserved */ #define BX_SYS_SEGMENT_BUSY_386_TSS (0xb) #define BX_386_CALL_GATE (0xc) /* 0xd reserved */ #define BX_386_INTERRUPT_GATE (0xe) #define BX_386_TRAP_GATE (0xf) // For data/code descriptors: #define BX_DATA_READ_ONLY (0x0) #define BX_DATA_READ_ONLY_ACCESSED (0x1) #define BX_DATA_READ_WRITE (0x2) #define BX_DATA_READ_WRITE_ACCESSED (0x3) #define BX_DATA_READ_ONLY_EXPAND_DOWN (0x4) #define BX_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED (0x5) #define BX_DATA_READ_WRITE_EXPAND_DOWN (0x6) #define BX_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED (0x7) #define BX_CODE_EXEC_ONLY (0x8) #define BX_CODE_EXEC_ONLY_ACCESSED (0x9) #define BX_CODE_EXEC_READ (0xa) #define BX_CODE_EXEC_READ_ACCESSED (0xb) #define BX_CODE_EXEC_ONLY_CONFORMING (0xc) #define BX_CODE_EXEC_ONLY_CONFORMING_ACCESSED (0xd) #define BX_CODE_EXEC_READ_CONFORMING (0xe) #define BX_CODE_EXEC_READ_CONFORMING_ACCESSED (0xf) union { struct { bx_address base; /* base address: 286=24bits, 386=32bits, long=64 */ Bit32u limit_scaled; /* for efficiency, this contrived field is set to * limit for byte granular, and * (limit << 12) | 0xfff for page granular seg's */ bx_bool g; /* granularity: 0=byte, 1=4K (page) */ bx_bool d_b; /* default size: 0=16bit, 1=32bit */ #if BX_SUPPORT_X86_64 bx_bool l; /* long mode: 0=compat, 1=64 bit */ #endif bx_bool avl; /* available for use by system */ } segment; struct { Bit8u param_count; /* 5bits (0..31) #words/dword to copy from caller's * stack to called procedure's stack. */ Bit16u dest_selector; Bit32u dest_offset; } gate; struct { /* type 5: Task Gate Descriptor */ Bit16u tss_selector; /* TSS segment selector */ } taskgate; } u; } bx_descriptor_t; #define IS_PRESENT(descriptor) (descriptor.p) #if BX_SUPPORT_X86_64 #define IS_LONG64_SEGMENT(descriptor) (descriptor.u.segment.l) #else #define IS_LONG64_SEGMENT(descriptor) (0) #endif #define BX_SEGMENT_CODE (0x8) #define BX_SEGMENT_DATA_EXPAND_DOWN (0x4) #define BX_SEGMENT_CODE_CONFORMING (0x4) #define BX_SEGMENT_DATA_WRITE (0x2) #define BX_SEGMENT_CODE_READ (0x2) #define BX_SEGMENT_ACCESSED (0x1) #define IS_CODE_SEGMENT(type) ((type) & BX_SEGMENT_CODE) #define IS_CODE_SEGMENT_CONFORMING(type) ((type) & BX_SEGMENT_CODE_CONFORMING) #define IS_DATA_SEGMENT_EXPAND_DOWN(type) ((type) & BX_SEGMENT_DATA_EXPAND_DOWN) #define IS_CODE_SEGMENT_READABLE(type) ((type) & BX_SEGMENT_CODE_READ) #define IS_DATA_SEGMENT_WRITEABLE(type) ((type) & BX_SEGMENT_DATA_WRITE) #define IS_SEGMENT_ACCESSED(type) ((type) & BX_SEGMENT_ACCESSED) #define IS_DATA_SEGMENT(type) (! IS_CODE_SEGMENT(type)) #define IS_CODE_SEGMENT_NON_CONFORMING(type) \ (! IS_CODE_SEGMENT_CONFORMING(type)) typedef struct { bx_selector_t selector; bx_descriptor_t cache; } bx_segment_reg_t; typedef struct { bx_address base; /* base address: 24bits=286,32bits=386,64bits=x86-64 */ Bit16u limit; /* limit, 16bits */ } bx_global_segment_reg_t; void parse_selector(Bit16u raw_selector, bx_selector_t *selector); Bit8u get_ar_byte(const bx_descriptor_t *d); void set_ar_byte(bx_descriptor_t *d, Bit8u ar_byte); void parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp); #endif bochs-2.6/cpu/tbm32.cc0000644000175000017500000001073112020641453014361 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: tbm32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BEXTR_GdEdIdR(bxInstruction_c *i) { Bit16u control = (Bit16u) i->Id(); unsigned start = control & 0xff; unsigned len = control >> 8; Bit32u op1_32 = 0; if (start < 32 && len > 0) { op1_32 = BX_READ_32BIT_REG(i->src()); op1_32 >>= start; if (len < 32) { Bit32u extract_mask = (1 << len) - 1; op1_32 &= extract_mask; } } SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCFILL_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 + 1) & op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF((op_32 + 1) == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCI_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = ~(op_32 + 1) | op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF((op_32 + 1) == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCIC_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 + 1) & ~op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF((op_32 + 1) == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCMSK_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 + 1) ^ op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF((op_32 + 1) == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCS_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 + 1) | op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF((op_32 + 1) == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSFILL_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 - 1) | op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF(op_32 == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSIC_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 - 1) | ~op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF(op_32 == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::T1MSKC_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 + 1) | ~op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF((op_32 + 1) == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TZMSK_BdEdR(bxInstruction_c *i) { Bit32u op_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op_32 - 1) & ~op_32; SET_FLAGS_OSZAPC_LOGIC_32(result_32); set_CF(op_32 == 0); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/instr.h0000644000175000017500000002705712020641453014444 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: instr.h 11377 2012-08-28 16:05:39Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_INSTR_H #define BX_INSTR_H class bxInstruction_c; typedef void BX_INSF_TYPE; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS #define BX_SYNC_TIME_IF_SINGLE_PROCESSOR(allowed_delta) { \ if (BX_SMP_PROCESSORS == 1) { \ Bit32u delta = BX_CPU_THIS_PTR icount - BX_CPU_THIS_PTR icount_last_sync; \ if (delta >= allowed_delta) { \ BX_CPU_THIS_PTR sync_icount(); \ BX_TICKN(delta); \ } \ } \ } #define BX_COMMIT_INSTRUCTION(i) { \ BX_CPU_THIS_PTR prev_rip = RIP; /* commit new RIP */ \ BX_INSTR_AFTER_EXECUTION(BX_CPU_ID, (i)); \ BX_CPU_THIS_PTR icount++; \ } #define BX_EXECUTE_INSTRUCTION(i) { \ BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, (i)); \ RIP += (i)->ilen(); \ return BX_CPU_CALL_METHOD(i->execute, (i)); \ } #define BX_NEXT_TRACE(i) { \ BX_COMMIT_INSTRUCTION(i); \ return; \ } #define BX_LINK_TRACE(i) { \ BX_COMMIT_INSTRUCTION(i); \ linkTrace(i); \ return; \ } #define BX_NEXT_INSTR(i) { \ BX_COMMIT_INSTRUCTION(i); \ if (BX_CPU_THIS_PTR async_event) return; \ ++i; \ BX_EXECUTE_INSTRUCTION(i); \ } #else // BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS #define BX_NEXT_TRACE(i) { return; } #define BX_NEXT_INSTR(i) { return; } #define BX_LINK_TRACE(i) { return; } #define BX_SYNC_TIME_IF_SINGLE_PROCESSOR(allowed_delta) \ if (BX_SMP_PROCESSORS == 1) BX_TICK1() #endif // #if BX_USE_CPU_SMF typedef BX_INSF_TYPE (BX_CPP_AttrRegparmN(1) *BxExecutePtr_tR)(bxInstruction_c *); typedef bx_address (BX_CPP_AttrRegparmN(1) *BxResolvePtr_tR)(bxInstruction_c *); typedef void (BX_CPP_AttrRegparmN(1) *BxRepIterationPtr_tR)(bxInstruction_c *); #else typedef BX_INSF_TYPE (BX_CPU_C::*BxExecutePtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN(1); typedef bx_address (BX_CPU_C::*BxResolvePtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN(1); typedef void (BX_CPU_C::*BxRepIterationPtr_tR)(bxInstruction_c *) BX_CPP_AttrRegparmN(1); #endif // extern bx_address bx_asize_mask[]; const char *get_bx_opcode_name(Bit16u ia_opcode); // class bxInstruction_c { public: // Function pointers; a function to resolve the modRM address // given the current state of the CPU and the instruction data, // and a function to execute the instruction after resolving // the memory address (if any). BxExecutePtr_tR execute; union { BxExecutePtr_tR execute2; bxInstruction_c *next; } handlers; BxResolvePtr_tR ResolveModrm; struct { // 15...0 opcode Bit16u ia_opcode; // 7...4 (unused) // 3...0 ilen (0..15) Bit8u ilen; // 7...6 VEX Vector Length (0=no VL, 1=128 bit, 2=256 bit) // repUsed (0=none, 2=0xF2, 3=0xF3) // 5...5 extend8bit // 4...4 mod==c0 (modrm) // 3...3 os64 // 2...2 os32 // 1...1 as64 // 0...0 as32 Bit8u metaInfo1; } metaInfo; #define BX_INSTR_METADATA_DST 0 #define BX_INSTR_METADATA_SRC1 1 #define BX_INSTR_METADATA_SRC2 2 #define BX_INSTR_METADATA_SRC3 3 #define BX_INSTR_METADATA_SEG 4 #define BX_INSTR_METADATA_BASE 5 #define BX_INSTR_METADATA_INDEX 6 #define BX_INSTR_METADATA_SCALE 7 // using 5-bit field for registers (16 regs in 64-bit, RIP, NIL) Bit8u metaData[8]; union { // Form (longest case): [opcode+modrm+sib/displacement32/immediate32] struct { union { Bit32u Id; Bit16u Iw; Bit8u Ib; }; union { Bit16u displ16u; // for 16-bit modrm forms Bit32u displ32u; // for 32-bit modrm forms Bit32u Id2; Bit16u Iw2; Bit8u Ib2; }; } modRMForm; #if BX_SUPPORT_X86_64 struct { Bit64u Iq; // for MOV Rx,imm64 } IqForm; #endif }; #ifdef BX_INSTR_STORE_OPCODE_BYTES Bit8u opcode_bytes[16]; BX_CPP_INLINE const Bit8u* get_opcode_bytes(void) const { return opcode_bytes; } BX_CPP_INLINE void set_opcode_bytes(const Bit8u *opcode) { memcpy(opcode_bytes, opcode, ilen()); } #endif BX_CPP_INLINE BxExecutePtr_tR execute2(void) const { return handlers.execute2; } BX_CPP_INLINE unsigned seg(void) const { return metaData[BX_INSTR_METADATA_SEG]; } BX_CPP_INLINE void setSeg(unsigned val) { metaData[BX_INSTR_METADATA_SEG] = val; } BX_CPP_INLINE void setFoo(unsigned foo) { // none of x87 instructions has immediate modRMForm.Iw = foo; } BX_CPP_INLINE unsigned foo() const { return modRMForm.Iw; } BX_CPP_INLINE unsigned b1() const { return modRMForm.Iw >> 8; } BX_CPP_INLINE void setSibScale(unsigned scale) { metaData[BX_INSTR_METADATA_SCALE] = scale; } BX_CPP_INLINE unsigned sibScale() const { return metaData[BX_INSTR_METADATA_SCALE]; } BX_CPP_INLINE void setSibIndex(unsigned index) { metaData[BX_INSTR_METADATA_INDEX] = index; } BX_CPP_INLINE unsigned sibIndex() const { return metaData[BX_INSTR_METADATA_INDEX]; } BX_CPP_INLINE void setSibBase(unsigned base) { metaData[BX_INSTR_METADATA_BASE] = base; } BX_CPP_INLINE unsigned sibBase() const { return metaData[BX_INSTR_METADATA_BASE]; } BX_CPP_INLINE Bit32s displ32s() const { return (Bit32s) modRMForm.displ32u; } BX_CPP_INLINE Bit16s displ16s() const { return (Bit16s) modRMForm.displ16u; } BX_CPP_INLINE Bit32u Id() const { return modRMForm.Id; } BX_CPP_INLINE Bit16u Iw() const { return modRMForm.Iw; } BX_CPP_INLINE Bit8u Ib() const { return modRMForm.Ib; } BX_CPP_INLINE Bit16u Id2() const { return modRMForm.Id2; } BX_CPP_INLINE Bit16u Iw2() const { return modRMForm.Iw2; } BX_CPP_INLINE Bit8u Ib2() const { return modRMForm.Ib2; } #if BX_SUPPORT_X86_64 BX_CPP_INLINE Bit64u Iq() const { return IqForm.Iq; } #endif // Info in the metaInfo field. // Note: the 'L' at the end of certain flags, means the value returned // is for Logical comparisons, eg if (i->os32L() && i->as32L()). If you // want a bx_bool value, use os32B() etc. This makes for smaller // code, when a strict 0 or 1 is not necessary. BX_CPP_INLINE void init(unsigned os32, unsigned as32, unsigned os64, unsigned as64) { metaInfo.metaInfo1 = (os32<<2) | (os64<<3) | (as32<<0) | (as64<<1); // VL = 0 } BX_CPP_INLINE unsigned os32L(void) const { return metaInfo.metaInfo1 & (1<<2); } BX_CPP_INLINE void setOs32B(unsigned bit) { metaInfo.metaInfo1 = (metaInfo.metaInfo1 & ~(1<<2)) | (bit<<2); } BX_CPP_INLINE void assertOs32(void) { metaInfo.metaInfo1 |= (1<<2); } #if BX_SUPPORT_X86_64 BX_CPP_INLINE unsigned os64L(void) const { return metaInfo.metaInfo1 & (1<<3); } BX_CPP_INLINE void assertOs64(void) { metaInfo.metaInfo1 |= (1<<3); } #else BX_CPP_INLINE unsigned os64L(void) const { return 0; } #endif BX_CPP_INLINE unsigned as32L(void) const { return metaInfo.metaInfo1 & 0x1; } BX_CPP_INLINE void setAs32B(unsigned bit) { metaInfo.metaInfo1 = (metaInfo.metaInfo1 & ~0x1) | (bit); } #if BX_SUPPORT_X86_64 BX_CPP_INLINE unsigned as64L(void) const { return metaInfo.metaInfo1 & (1<<1); } BX_CPP_INLINE void clearAs64(void) { metaInfo.metaInfo1 &= ~(1<<1); } #else BX_CPP_INLINE unsigned as64L(void) const { return 0; } #endif BX_CPP_INLINE unsigned asize(void) const { return metaInfo.metaInfo1 & 0x3; } BX_CPP_INLINE bx_address asize_mask(void) const { return bx_asize_mask[asize()]; } #if BX_SUPPORT_X86_64 BX_CPP_INLINE unsigned extend8bitL(void) const { return metaInfo.metaInfo1 & (1<<5); } BX_CPP_INLINE void assertExtend8bit(void) { metaInfo.metaInfo1 |= (1<<5); } #endif BX_CPP_INLINE unsigned ilen(void) const { return metaInfo.ilen; } BX_CPP_INLINE void setILen(unsigned ilen) { metaInfo.ilen = ilen; } BX_CPP_INLINE unsigned getIaOpcode(void) const { return metaInfo.ia_opcode; } BX_CPP_INLINE void setIaOpcode(Bit16u op) { metaInfo.ia_opcode = op; } BX_CPP_INLINE const char* getIaOpcodeName(void) const { return get_bx_opcode_name(getIaOpcode()); } BX_CPP_INLINE unsigned repUsedL(void) const { return metaInfo.metaInfo1 >> 6; } BX_CPP_INLINE unsigned repUsedValue(void) const { return metaInfo.metaInfo1 >> 6; } BX_CPP_INLINE void setRepUsed(unsigned value) { metaInfo.metaInfo1 = (metaInfo.metaInfo1 & 0x3f) | (value << 6); } BX_CPP_INLINE unsigned getVL(void) const { #if BX_SUPPORT_AVX return metaInfo.metaInfo1 >> 6; #else return 0; #endif } BX_CPP_INLINE void setVL(unsigned value) { metaInfo.metaInfo1 = (metaInfo.metaInfo1 & 0x3f) | (value << 6); } BX_CPP_INLINE void setSrcReg(unsigned src, unsigned reg) { metaData[src] = reg; } BX_CPP_INLINE unsigned dst() const { return metaData[BX_INSTR_METADATA_DST]; } BX_CPP_INLINE unsigned src1() const { return metaData[BX_INSTR_METADATA_SRC1]; } BX_CPP_INLINE unsigned src2() const { return metaData[BX_INSTR_METADATA_SRC2]; } BX_CPP_INLINE unsigned src3() const { return metaData[BX_INSTR_METADATA_SRC3]; } BX_CPP_INLINE unsigned src() const { return src1(); } BX_CPP_INLINE unsigned modC0() const { // This is a cheaper way to test for modRM instructions where // the mod field is 0xc0. FetchDecode flags this condition since // it is quite common to be tested for. return metaInfo.metaInfo1 & (1<<4); } BX_CPP_INLINE void assertModC0() { metaInfo.metaInfo1 |= (1<<4); } #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS BX_CPP_INLINE bxInstruction_c* getNextTrace() const { return handlers.next; } BX_CPP_INLINE void setNextTrace(bxInstruction_c* iptr) { handlers.next = iptr; } #endif }; // enum { #define bx_define_opcode(a, b, c, d, s1, s2, s3, s4, e) a, #include "ia_opcodes.h" BX_IA_LAST }; #undef bx_define_opcode #endif bochs-2.6/cpu/shift32.cc0000644000175000017500000003401012020641453014710 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: shift32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EdGdM(bxInstruction_c *i) { unsigned count; unsigned of, cf; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHLD_EdGd) count = CL; else // BX_IA_SHLD_EdGdIb count = i->Ib(); count &= 0x1f; // use only 5 LSB's if (count) { Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op1_32 << count) | (op2_32 >> (32 - count)); write_RMW_virtual_dword(result_32); SET_FLAGS_OSZAPC_LOGIC_32(result_32); cf = (op1_32 >> (32 - count)) & 0x1; of = cf ^ (result_32 >> 31); // of = cf ^ result31 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, result_32; unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_SHLD_EdGd) count = CL; else // BX_IA_SHLD_EdGdIb count = i->Ib(); count &= 0x1f; // use only 5 LSB's if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register } else { op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); result_32 = (op1_32 << count) | (op2_32 >> (32 - count)); BX_WRITE_32BIT_REGZ(i->dst(), result_32); SET_FLAGS_OSZAPC_LOGIC_32(result_32); cf = (op1_32 >> (32 - count)) & 0x1; of = cf ^ (result_32 >> 31); // of = cf ^ result31 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EdGdM(bxInstruction_c *i) { unsigned count; unsigned cf, of; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHRD_EdGd) count = CL; else // BX_IA_SHRD_EdGdIb count = i->Ib(); count &= 0x1f; // use only 5 LSB's if (count) { Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); Bit32u result_32 = (op2_32 << (32 - count)) | (op1_32 >> count); write_RMW_virtual_dword(result_32); SET_FLAGS_OSZAPC_LOGIC_32(result_32); cf = (op1_32 >> (count - 1)) & 0x1; of = ((result_32 << 1) ^ result_32) >> 31; // of = result30 ^ result31 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, result_32; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_SHRD_EdGd) count = CL; else // BX_IA_SHRD_EdGdIb count = i->Ib(); count &= 0x1f; // use only 5 LSB's if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register } else { op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); result_32 = (op2_32 << (32 - count)) | (op1_32 >> count); BX_WRITE_32BIT_REGZ(i->dst(), result_32); SET_FLAGS_OSZAPC_LOGIC_32(result_32); cf = (op1_32 >> (count - 1)) & 0x1; of = ((result_32 << 1) ^ result_32) >> 31; // of = result30 ^ result31 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EdM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_ROL_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (count) { Bit32u result_32 = (op1_32 << count) | (op1_32 >> (32 - count)); write_RMW_virtual_dword(result_32); unsigned bit0 = (result_32 & 0x1); unsigned bit31 = (result_32 >> 31); // of = cf ^ result31 SET_FLAGS_OxxxxC(bit0 ^ bit31, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EdR(bxInstruction_c *i) { Bit32u op1_32, result_32; unsigned count; unsigned bit0, bit31; if (i->getIaOpcode() == BX_IA_ROL_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register } else { op1_32 = BX_READ_32BIT_REG(i->dst()); result_32 = (op1_32 << count) | (op1_32 >> (32 - count)); BX_WRITE_32BIT_REGZ(i->dst(), result_32); bit0 = (result_32 & 0x1); bit31 = (result_32 >> 31); // of = cf ^ result31 SET_FLAGS_OxxxxC(bit0 ^ bit31, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EdM(bxInstruction_c *i) { unsigned count; unsigned bit31, bit30; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_ROR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (count) { Bit32u result_32 = (op1_32 >> count) | (op1_32 << (32 - count)); write_RMW_virtual_dword(result_32); bit31 = (result_32 >> 31) & 1; bit30 = (result_32 >> 30) & 1; // of = result30 ^ result31 SET_FLAGS_OxxxxC(bit30 ^ bit31, bit31); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EdR(bxInstruction_c *i) { Bit32u op1_32, result_32; unsigned count; unsigned bit31, bit30; if (i->getIaOpcode() == BX_IA_ROR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register } else { op1_32 = BX_READ_32BIT_REG(i->dst()); result_32 = (op1_32 >> count) | (op1_32 << (32 - count)); BX_WRITE_32BIT_REGZ(i->dst(), result_32); bit31 = (result_32 >> 31) & 1; bit30 = (result_32 >> 30) & 1; // of = result30 ^ result31 SET_FLAGS_OxxxxC(bit30 ^ bit31, bit31); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EdM(bxInstruction_c *i) { Bit32u result_32; unsigned count; unsigned cf, of; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_RCL_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_NEXT_INSTR(i); } if (count==1) { result_32 = (op1_32 << 1) | getB_CF(); } else { result_32 = (op1_32 << count) | (getB_CF() << (count - 1)) | (op1_32 >> (33 - count)); } write_RMW_virtual_dword(result_32); cf = (op1_32 >> (32 - count)) & 0x1; of = cf ^ (result_32 >> 31); // of = cf ^ result31 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EdR(bxInstruction_c *i) { Bit32u result_32; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_RCL_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); if (count==1) { result_32 = (op1_32 << 1) | getB_CF(); } else { result_32 = (op1_32 << count) | (getB_CF() << (count - 1)) | (op1_32 >> (33 - count)); } BX_WRITE_32BIT_REGZ(i->dst(), result_32); cf = (op1_32 >> (32 - count)) & 0x1; of = cf ^ (result_32 >> 31); // of = cf ^ result31 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EdM(bxInstruction_c *i) { Bit32u result_32; unsigned count; unsigned cf, of; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_RCR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_NEXT_INSTR(i); } if (count==1) { result_32 = (op1_32 >> 1) | (getB_CF() << 31); } else { result_32 = (op1_32 >> count) | (getB_CF() << (32 - count)) | (op1_32 << (33 - count)); } write_RMW_virtual_dword(result_32); cf = (op1_32 >> (count - 1)) & 0x1; of = ((result_32 << 1) ^ result_32) >> 31; // of = result30 ^ result31 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EdR(bxInstruction_c *i) { Bit32u result_32; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_RCR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); if (count==1) { result_32 = (op1_32 >> 1) | (getB_CF() << 31); } else { result_32 = (op1_32 >> count) | (getB_CF() << (32 - count)) | (op1_32 << (33 - count)); } BX_WRITE_32BIT_REGZ(i->dst(), result_32); cf = (op1_32 >> (count - 1)) & 0x1; of = ((result_32 << 1) ^ result_32) >> 31; // of = result30 ^ result31 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EdM(bxInstruction_c *i) { unsigned count; unsigned cf, of; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHL_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (count) { /* count < 32, since only lower 5 bits used */ Bit32u result_32 = (op1_32 << count); write_RMW_virtual_dword(result_32); cf = (op1_32 >> (32 - count)) & 0x1; of = cf ^ (result_32 >> 31); SET_FLAGS_OSZAPC_LOGIC_32(result_32); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EdR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SHL_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register } else { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); /* count < 32, since only lower 5 bits used */ Bit32u result_32 = (op1_32 << count); BX_WRITE_32BIT_REGZ(i->dst(), result_32); unsigned cf = (op1_32 >> (32 - count)) & 0x1; unsigned of = cf ^ (result_32 >> 31); SET_FLAGS_OSZAPC_LOGIC_32(result_32); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EdM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SHR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (count) { Bit32u result_32 = (op1_32 >> count); write_RMW_virtual_dword(result_32); unsigned cf = (op1_32 >> (count - 1)) & 0x1; // note, that of == result31 if count == 1 and // of == 0 if count >= 2 unsigned of = ((result_32 << 1) ^ result_32) >> 31; SET_FLAGS_OSZAPC_LOGIC_32(result_32); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EdR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SHR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register } else { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); Bit32u result_32 = (op1_32 >> count); BX_WRITE_32BIT_REGZ(i->dst(), result_32); unsigned cf = (op1_32 >> (count - 1)) & 0x1; // note, that of == result31 if count == 1 and // of == 0 if count >= 2 unsigned of = ((result_32 << 1) ^ result_32) >> 31; SET_FLAGS_OSZAPC_LOGIC_32(result_32); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EdM(bxInstruction_c *i) { unsigned count; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); if (i->getIaOpcode() == BX_IA_SAR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (count) { /* count < 32, since only lower 5 bits used */ Bit32u result_32 = ((Bit32s) op1_32) >> count; write_RMW_virtual_dword(result_32); SET_FLAGS_OSZAPC_LOGIC_32(result_32); unsigned cf = (op1_32 >> (count - 1)) & 1; SET_FLAGS_OxxxxC(0, cf); /* signed overflow cannot happen in SAR instruction */ } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EdR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SAR_Ed) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register } else { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); /* count < 32, since only lower 5 bits used */ Bit32u result_32 = ((Bit32s) op1_32) >> count; BX_WRITE_32BIT_REGZ(i->dst(), result_32); SET_FLAGS_OSZAPC_LOGIC_32(result_32); unsigned cf = (op1_32 >> (count - 1)) & 1; SET_FLAGS_OxxxxC(0, cf); /* signed overflow cannot happen in SAR instruction */ } BX_NEXT_INSTR(i); } bochs-2.6/cpu/debugstuff.cc0000644000175000017500000003546112020641453015577 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: debugstuff.cc 11142 2012-04-16 19:18:23Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_DISASM #include "disasm/disasm.h" void BX_CPU_C::debug_disasm_instruction(bx_address offset) { #if BX_DEBUGGER bx_dbg_disassemble_current(BX_CPU_ID, 1); // only one cpu, print time stamp #else bx_phy_address phy_addr; Bit8u instr_buf[16]; char char_buf[512]; size_t i=0; static char letters[] = "0123456789ABCDEF"; static disassembler bx_disassemble; unsigned remainsInPage = 0x1000 - PAGE_OFFSET(offset); bx_bool valid = dbg_xlate_linear2phy(get_laddr(BX_SEG_REG_CS, offset), &phy_addr); if (valid) { BX_MEM(0)->dbg_fetch_mem(BX_CPU_THIS, phy_addr, 16, instr_buf); unsigned isize = bx_disassemble.disasm( BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64, BX_CPU_THIS_PTR get_segment_base(BX_SEG_REG_CS), offset, instr_buf, char_buf+i); if (isize <= remainsInPage) { i=strlen(char_buf); char_buf[i++] = ' '; char_buf[i++] = ':'; char_buf[i++] = ' '; for (unsigned j=0; j> 4) & 0xf]; char_buf[i++] = letters[(instr_buf[j] >> 0) & 0xf]; } char_buf[i] = 0; BX_INFO(("0x" FMT_ADDRX ">> %s", offset, char_buf)); } else { BX_INFO(("0x" FMT_ADDRX ": (instruction unavailable) page split instruction", offset)); } } else { BX_INFO(("0x" FMT_ADDRX ": (instruction unavailable) page not present", offset)); } #endif // #if BX_DEBUGGER } #endif // #if BX_DISASM const char* cpu_mode_string(unsigned cpu_mode) { static const char *cpu_mode_name[] = { "real mode", "v8086 mode", "protected mode", "compatibility mode", "long mode", "unknown mode" }; if(cpu_mode >= 5) cpu_mode = 5; return cpu_mode_name[cpu_mode]; } const char* cpu_state_string(unsigned state) { static const char *cpu_state_name[] = { "active", "halted", "in shutdown", "waiting for SIPI", "executing mwait", "executing mwait inhibit interrups", "unknown state" }; if(state >= 6) state = 6; return cpu_state_name[state]; } void BX_CPU_C::debug(bx_address offset) { BX_INFO(("CPU is in %s (%s)", cpu_mode_string(BX_CPU_THIS_PTR get_cpu_mode()), cpu_state_string(BX_CPU_THIS_PTR activity_state))); BX_INFO(("CS.mode = %u bit", long64_mode() ? 64 : (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b ? 32 : 16))); BX_INFO(("SS.mode = %u bit", long64_mode() ? 64 : (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b ? 32 : 16))); #if BX_CPU_LEVEL >= 5 BX_INFO(("EFER = 0x%08x", BX_CPU_THIS_PTR efer.get32())); #endif #if BX_SUPPORT_X86_64 if (long_mode()) { BX_INFO(("| RAX=%08x%08x RBX=%08x%08x", (unsigned) (RAX >> 32), (unsigned) EAX, (unsigned) (RBX >> 32), (unsigned) EBX)); BX_INFO(("| RCX=%08x%08x RDX=%08x%08x", (unsigned) (RCX >> 32), (unsigned) ECX, (unsigned) (RDX >> 32), (unsigned) EDX)); BX_INFO(("| RSP=%08x%08x RBP=%08x%08x", (unsigned) (RSP >> 32), (unsigned) ESP, (unsigned) (RBP >> 32), (unsigned) EBP)); BX_INFO(("| RSI=%08x%08x RDI=%08x%08x", (unsigned) (RSI >> 32), (unsigned) ESI, (unsigned) (RDI >> 32), (unsigned) EDI)); BX_INFO(("| R8=%08x%08x R9=%08x%08x", (unsigned) (R8 >> 32), (unsigned) (R8 & 0xFFFFFFFF), (unsigned) (R9 >> 32), (unsigned) (R9 & 0xFFFFFFFF))); BX_INFO(("| R10=%08x%08x R11=%08x%08x", (unsigned) (R10 >> 32), (unsigned) (R10 & 0xFFFFFFFF), (unsigned) (R11 >> 32), (unsigned) (R11 & 0xFFFFFFFF))); BX_INFO(("| R12=%08x%08x R13=%08x%08x", (unsigned) (R12 >> 32), (unsigned) (R12 & 0xFFFFFFFF), (unsigned) (R13 >> 32), (unsigned) (R13 & 0xFFFFFFFF))); BX_INFO(("| R14=%08x%08x R15=%08x%08x", (unsigned) (R14 >> 32), (unsigned) (R14 & 0xFFFFFFFF), (unsigned) (R15 >> 32), (unsigned) (R15 & 0xFFFFFFFF))); } else #endif { BX_INFO(("| EAX=%08x EBX=%08x ECX=%08x EDX=%08x", (unsigned) EAX, (unsigned) EBX, (unsigned) ECX, (unsigned) EDX)); BX_INFO(("| ESP=%08x EBP=%08x ESI=%08x EDI=%08x", (unsigned) ESP, (unsigned) EBP, (unsigned) ESI, (unsigned) EDI)); } BX_INFO(("| IOPL=%1u %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", BX_CPU_THIS_PTR get_IOPL(), BX_CPU_THIS_PTR get_ID() ? "ID" : "id", BX_CPU_THIS_PTR get_VIP() ? "VIP" : "vip", BX_CPU_THIS_PTR get_VIF() ? "VIF" : "vif", BX_CPU_THIS_PTR get_AC() ? "AC" : "ac", BX_CPU_THIS_PTR get_VM() ? "VM" : "vm", BX_CPU_THIS_PTR get_RF() ? "RF" : "rf", BX_CPU_THIS_PTR get_NT() ? "NT" : "nt", BX_CPU_THIS_PTR get_OF() ? "OF" : "of", BX_CPU_THIS_PTR get_DF() ? "DF" : "df", BX_CPU_THIS_PTR get_IF() ? "IF" : "if", BX_CPU_THIS_PTR get_TF() ? "TF" : "tf", BX_CPU_THIS_PTR get_SF() ? "SF" : "sf", BX_CPU_THIS_PTR get_ZF() ? "ZF" : "zf", BX_CPU_THIS_PTR get_AF() ? "AF" : "af", BX_CPU_THIS_PTR get_PF() ? "PF" : "pf", BX_CPU_THIS_PTR get_CF() ? "CF" : "cf")); BX_INFO(("| SEG sltr(index|ti|rpl) base limit G D")); BX_INFO(("| CS:%04x( %04x| %01u| %1u) %08x %08x %1u %1u", (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.index, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.ti, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.rpl, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b)); BX_INFO(("| DS:%04x( %04x| %01u| %1u) %08x %08x %1u %1u", (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.index, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.ti, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.rpl, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.d_b)); BX_INFO(("| SS:%04x( %04x| %01u| %1u) %08x %08x %1u %1u", (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.index, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.ti, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b)); BX_INFO(("| ES:%04x( %04x| %01u| %1u) %08x %08x %1u %1u", (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.index, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.ti, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.rpl, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.base, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.limit_scaled, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.g, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.u.segment.d_b)); BX_INFO(("| FS:%04x( %04x| %01u| %1u) %08x %08x %1u %1u", (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.index, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.ti, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.rpl, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.limit_scaled, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.g, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.d_b)); BX_INFO(("| GS:%04x( %04x| %01u| %1u) %08x %08x %1u %1u", (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.index, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.ti, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.rpl, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.limit_scaled, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.g, (unsigned) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.d_b)); #if BX_SUPPORT_X86_64 if (long_mode()) { BX_INFO(("| MSR_FS_BASE:%08x%08x", (unsigned) (MSR_FSBASE >> 32), (unsigned) (MSR_FSBASE & 0xFFFFFFFF))); BX_INFO(("| MSR_GS_BASE:%08x%08x", (unsigned) (MSR_GSBASE >> 32), (unsigned) (MSR_GSBASE & 0xFFFFFFFF))); BX_INFO(("| RIP=%08x%08x (%08x%08x)", (unsigned) (BX_CPU_THIS_PTR gen_reg[BX_64BIT_REG_RIP].dword.hrx), (unsigned) EIP, (unsigned) (BX_CPU_THIS_PTR prev_rip >> 32), (unsigned) (BX_CPU_THIS_PTR prev_rip & 0xffffffff))); BX_INFO(("| CR0=0x%08x CR2=0x%08x%08x", (unsigned) (BX_CPU_THIS_PTR cr0.get32()), (unsigned) (BX_CPU_THIS_PTR cr2 >> 32), (unsigned) (BX_CPU_THIS_PTR cr2 & 0xffffffff))); BX_INFO(("| CR3=0x%08x CR4=0x%08x", (unsigned) BX_CPU_THIS_PTR cr3, (unsigned) BX_CPU_THIS_PTR cr4.get32())); } else #endif // BX_SUPPORT_X86_64 { BX_INFO(("| EIP=%08x (%08x)", (unsigned) EIP, (unsigned) BX_CPU_THIS_PTR prev_rip)); #if BX_CPU_LEVEL < 5 BX_INFO(("| CR0=0x%08x CR2=0x%08x CR3=0x%08x", (unsigned) BX_CPU_THIS_PTR cr0.get32(), (unsigned) BX_CPU_THIS_PTR cr2, (unsigned) BX_CPU_THIS_PTR cr3)); #else BX_INFO(("| CR0=0x%08x CR2=0x%08x", BX_CPU_THIS_PTR cr0.get32(), BX_CPU_THIS_PTR cr2)); BX_INFO(("| CR3=0x%08x CR4=0x%08x", (unsigned) BX_CPU_THIS_PTR cr3, (unsigned) BX_CPU_THIS_PTR cr4.get32())); #endif } #if BX_DISASM debug_disasm_instruction(offset); #endif // #if BX_DISASM } #if BX_DEBUGGER bx_bool BX_CPU_C::dbg_set_reg(unsigned reg, Bit32u val) { // returns 1=OK, 0=can't change Bit32u current_sys_bits; switch (reg) { case BX_DBG_REG_EIP: RIP = BX_CPU_THIS_PTR prev_rip = val; invalidate_prefetch_q(); return(1); case BX_DBG_REG_EFLAGS: if (val & 0xffff0000) { BX_INFO(("dbg_set_reg: can not set upper 16 bits of eflags.")); return(0); } // make sure none of the system bits are being changed current_sys_bits = ((BX_CPU_THIS_PTR getB_NT()) << 14) | (BX_CPU_THIS_PTR get_IOPL () << 12) | ((BX_CPU_THIS_PTR getB_TF()) << 8); if (current_sys_bits != (val & 0x0000f100)) { BX_INFO(("dbg_set_reg: can not modify NT, IOPL, or TF.")); return(0); } BX_CPU_THIS_PTR set_CF(val & 0x01); val >>= 2; BX_CPU_THIS_PTR set_PF(val & 0x01); val >>= 2; BX_CPU_THIS_PTR set_AF(val & 0x01); val >>= 2; BX_CPU_THIS_PTR set_ZF(val & 0x01); val >>= 1; BX_CPU_THIS_PTR set_SF(val & 0x01); val >>= 2; BX_CPU_THIS_PTR set_IF(val & 0x01); val >>= 1; BX_CPU_THIS_PTR set_DF(val & 0x01); val >>= 1; BX_CPU_THIS_PTR set_OF(val & 0x01); return(1); } return(0); } unsigned BX_CPU_C::dbg_query_pending(void) { unsigned ret = 0; if (BX_HRQ) { // DMA Hold Request ret |= BX_DBG_PENDING_DMA; } if (BX_CPU_THIS_PTR INTR && BX_CPU_THIS_PTR get_IF()) { ret |= BX_DBG_PENDING_IRQ; } return(ret); } bx_bool BX_CPU_C::dbg_get_sreg(bx_dbg_sreg_t *sreg, unsigned sreg_no) { if (sreg_no > 5) return(0); sreg->valid = BX_CPU_THIS_PTR sregs[sreg_no].cache.valid; sreg->sel = BX_CPU_THIS_PTR sregs[sreg_no].selector.value; sreg->des_l = get_descriptor_l(&BX_CPU_THIS_PTR sregs[sreg_no].cache); sreg->des_h = get_descriptor_h(&BX_CPU_THIS_PTR sregs[sreg_no].cache); #if BX_SUPPORT_X86_64 sreg->dword3 = BX_CPU_THIS_PTR sregs[sreg_no].cache.u.segment.base >> 32; #endif return(1); } bx_bool BX_CPU_C::dbg_set_sreg(unsigned sreg_no, bx_segment_reg_t *sreg) { if (sreg_no < 6) { BX_CPU_THIS_PTR sregs[sreg_no] = *sreg; if (sreg_no == BX_SEG_REG_CS) { handleCpuModeChange(); #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(/* CPL change */); #endif invalidate_prefetch_q(); return 1; } } return 0; } void BX_CPU_C::dbg_get_tr(bx_dbg_sreg_t *sreg) { sreg->valid = BX_CPU_THIS_PTR tr.cache.valid; sreg->sel = BX_CPU_THIS_PTR tr.selector.value; sreg->des_l = get_descriptor_l(&BX_CPU_THIS_PTR tr.cache); sreg->des_h = get_descriptor_h(&BX_CPU_THIS_PTR tr.cache); #if BX_SUPPORT_X86_64 sreg->dword3 = BX_CPU_THIS_PTR tr.cache.u.segment.base >> 32; #endif } void BX_CPU_C::dbg_get_ldtr(bx_dbg_sreg_t *sreg) { sreg->valid = BX_CPU_THIS_PTR ldtr.cache.valid; sreg->sel = BX_CPU_THIS_PTR ldtr.selector.value; sreg->des_l = get_descriptor_l(&BX_CPU_THIS_PTR ldtr.cache); sreg->des_h = get_descriptor_h(&BX_CPU_THIS_PTR ldtr.cache); #if BX_SUPPORT_X86_64 sreg->dword3 = BX_CPU_THIS_PTR ldtr.cache.u.segment.base >> 32; #endif } void BX_CPU_C::dbg_get_gdtr(bx_dbg_global_sreg_t *sreg) { sreg->base = BX_CPU_THIS_PTR gdtr.base; sreg->limit = BX_CPU_THIS_PTR gdtr.limit; } void BX_CPU_C::dbg_get_idtr(bx_dbg_global_sreg_t *sreg) { sreg->base = BX_CPU_THIS_PTR idtr.base; sreg->limit = BX_CPU_THIS_PTR idtr.limit; } #endif // #if BX_DEBUGGER void BX_CPU_C::atexit(void) { debug(BX_CPU_THIS_PTR prev_rip); } bochs-2.6/cpu/arith32.cc0000644000175000017500000003663312020641453014717 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: arith32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_ERX(bxInstruction_c *i) { Bit32u erx = ++BX_READ_32BIT_REG(i->dst()); SET_FLAGS_OSZAP_ADD_32(erx - 1, 0, erx); BX_CLEAR_64BIT_HIGH(i->dst()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_ERX(bxInstruction_c *i) { Bit32u erx = --BX_READ_32BIT_REG(i->dst()); SET_FLAGS_OSZAP_SUB_32(erx + 1, 0, erx); BX_CLEAR_64BIT_HIGH(i->dst()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, sum_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); sum_32 = op1_32 + op2_32; write_RMW_virtual_dword(sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GdEdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, sum_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); sum_32 = op1_32 + op2_32; BX_WRITE_32BIT_REGZ(i->dst(), sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GdEdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, sum_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); sum_32 = op1_32 + op2_32; BX_WRITE_32BIT_REGZ(i->dst(), sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EdGdM(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32, sum_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); sum_32 = op1_32 + op2_32 + temp_CF; write_RMW_virtual_dword(sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GdEdR(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32, sum_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); sum_32 = op1_32 + op2_32 + temp_CF; BX_WRITE_32BIT_REGZ(i->dst(), sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GdEdM(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32, sum_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); sum_32 = op1_32 + op2_32 + temp_CF; BX_WRITE_32BIT_REGZ(i->dst(), sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EdGdM(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32, diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); diff_32 = op1_32 - (op2_32 + temp_CF); write_RMW_virtual_dword(diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GdEdR(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32, diff_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); diff_32 = op1_32 - (op2_32 + temp_CF); BX_WRITE_32BIT_REGZ(i->dst(), diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GdEdM(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32, diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); diff_32 = op1_32 - (op2_32 + temp_CF); BX_WRITE_32BIT_REGZ(i->dst(), diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EdIdM(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32 = i->Id(), diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); diff_32 = op1_32 - (op2_32 + temp_CF); write_RMW_virtual_dword(diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EdIdR(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32 = i->Id(), diff_32; op1_32 = BX_READ_32BIT_REG(i->dst()); diff_32 = op1_32 - (op2_32 + temp_CF); BX_WRITE_32BIT_REGZ(i->dst(), diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); diff_32 = op1_32 - op2_32; write_RMW_virtual_dword(diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GdEdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); diff_32 = op1_32 - op2_32; BX_WRITE_32BIT_REGZ(i->dst(), diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GdEdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); diff_32 = op1_32 - op2_32; BX_WRITE_32BIT_REGZ(i->dst(), diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GdEdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GdEdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CWDE(bxInstruction_c *i) { /* CWDE: no flags are effected */ Bit32u tmp = (Bit16s) AX; RAX = tmp; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CDQ(bxInstruction_c *i) { /* CDQ: no flags are affected */ if (EAX & 0x80000000) { RDX = 0xFFFFFFFF; } else { RDX = 0x00000000; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, sum_32; /* XADD dst(r/m), src(r) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); sum_32 = op1_32 + op2_32; write_RMW_virtual_dword(sum_32); /* and write destination into source */ BX_WRITE_32BIT_REGZ(i->src(), op1_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, sum_32; /* XADD dst(r/m), src(r) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); sum_32 = op1_32 + op2_32; // and write destination into source // Note: if both op1 & op2 are registers, the last one written // should be the sum, as op1 & op2 may be the same register. // For example: XADD AL, AL BX_WRITE_32BIT_REGZ(i->src(), op1_32); BX_WRITE_32BIT_REGZ(i->dst(), sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EdIdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, sum_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = i->Id(); sum_32 = op1_32 + op2_32; write_RMW_virtual_dword(sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EdIdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, sum_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = i->Id(); sum_32 = op1_32 + op2_32; BX_WRITE_32BIT_REGZ(i->dst(), sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EdIdM(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32 = i->Id(), sum_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); sum_32 = op1_32 + op2_32 + temp_CF; write_RMW_virtual_dword(sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EdIdR(bxInstruction_c *i) { bx_bool temp_CF = getB_CF(); Bit32u op1_32, op2_32 = i->Id(), sum_32; op1_32 = BX_READ_32BIT_REG(i->dst()); sum_32 = op1_32 + op2_32 + temp_CF; BX_WRITE_32BIT_REGZ(i->dst(), sum_32); SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EdIdM(bxInstruction_c *i) { Bit32u op1_32, op2_32 = i->Id(), diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); diff_32 = op1_32 - op2_32; write_RMW_virtual_dword(diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EdIdR(bxInstruction_c *i) { Bit32u op1_32, op2_32 = i->Id(), diff_32; op1_32 = BX_READ_32BIT_REG(i->dst()); diff_32 = op1_32 - op2_32; BX_WRITE_32BIT_REGZ(i->dst(), diff_32); SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EdIdM(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_virtual_dword(i->seg(), eaddr); op2_32 = i->Id(); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EdIdR(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = i->Id(); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op1_32 = - (Bit32s)(op1_32); write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAPC_SUB_32(0, 0 - op1_32, op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); op1_32 = - (Bit32s)(op1_32); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_SUB_32(0, 0 - op1_32, op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op1_32++; write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAP_ADD_32(op1_32 - 1, 0, op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op1_32--; write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAP_SUB_32(op1_32 + 1, 0, op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EdGdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); Bit32u diff_32 = EAX - op1_32; SET_FLAGS_OSZAPC_SUB_32(EAX, op1_32, diff_32); if (diff_32 == 0) { // if accumulator == dest // dest <-- src write_RMW_virtual_dword(BX_READ_32BIT_REG(i->src())); } else { // accumulator <-- dest RAX = op1_32; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EdGdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); Bit32u diff_32 = EAX - op1_32; SET_FLAGS_OSZAPC_SUB_32(EAX, op1_32, diff_32); if (diff_32 == 0) { // if accumulator == dest // dest <-- src BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); } else { // accumulator <-- dest RAX = op1_32; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG8B(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); // check write permission for following write Bit64u op1_64 = read_RMW_virtual_qword(i->seg(), eaddr); Bit64u op2_64 = ((Bit64u) EDX << 32) | EAX; if (op1_64 == op2_64) { // if accumulator == dest // dest <-- src (ECX:EBX) op2_64 = ((Bit64u) ECX << 32) | EBX; write_RMW_virtual_qword(op2_64); assert_ZF(); } else { // accumulator <-- dest RAX = GET32L(op1_64); RDX = GET32H(op1_64); clear_ZF(); } BX_NEXT_INSTR(i); } bochs-2.6/cpu/logical32.cc0000644000175000017500000001702012020641453015207 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: logical32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 ^= op2_32; write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GdEdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 ^= op2_32; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GdEdM(bxInstruction_c *i) { Bit32u op1_32, op2_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); op1_32 ^= op2_32; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EdIdM(bxInstruction_c *i) { Bit32u op1_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op1_32 ^= i->Id(); write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EdIdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); op1_32 ^= i->Id(); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EdIdM(bxInstruction_c *i) { Bit32u op1_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op1_32 |= i->Id(); write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EdIdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); op1_32 |= i->Id(); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op1_32 = ~op1_32; write_RMW_virtual_dword(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); op1_32 = ~op1_32; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 |= op2_32; write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GdEdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 |= op2_32; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GdEdM(bxInstruction_c *i) { Bit32u op1_32, op2_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); op1_32 |= op2_32; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 &= op2_32; write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GdEdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 &= op2_32; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GdEdM(bxInstruction_c *i) { Bit32u op1_32, op2_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = read_virtual_dword(i->seg(), eaddr); op1_32 &= op2_32; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EdIdM(bxInstruction_c *i) { Bit32u op1_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); op1_32 &= i->Id(); write_RMW_virtual_dword(op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EdIdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); op1_32 &= i->Id(); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 &= op2_32; SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EdGdM(bxInstruction_c *i) { Bit32u op1_32, op2_32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_32 = read_virtual_dword(i->seg(), eaddr); op2_32 = BX_READ_32BIT_REG(i->src()); op1_32 &= op2_32; SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EdIdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); op1_32 &= i->Id(); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EdIdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_virtual_dword(i->seg(), eaddr); op1_32 &= i->Id(); SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_NEXT_INSTR(i); } bochs-2.6/cpu/simd_compare.h0000644000175000017500000002405312020641453015740 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: simd_compare.h 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_SIMD_INT_COMPARE_FUNCTIONS_H #define BX_SIMD_INT_COMPARE_FUNCTIONS_H // compare less than (signed) BX_CPP_INLINE void sse_pcmpltb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmsbyte(n) < op2->xmmsbyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpltw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16s(n) < op2->xmm16s(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpltd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32s(n) < op2->xmm32s(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpltq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64s(n) < op2->xmm64s(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare less than (unsigned) BX_CPP_INLINE void sse_pcmpltub(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmubyte(n) < op2->xmmubyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpltuw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16u(n) < op2->xmm16u(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpltud(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32u(n) < op2->xmm32u(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpltuq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64u(n) < op2->xmm64u(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare less than or equal (signed) BX_CPP_INLINE void sse_pcmpleb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmsbyte(n) <= op2->xmmsbyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmplew(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16s(n) <= op2->xmm16s(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpled(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32s(n) <= op2->xmm32s(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpleq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64s(n) <= op2->xmm64s(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare less than or equal (unsigned) BX_CPP_INLINE void sse_pcmpleub(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmubyte(n) <= op2->xmmubyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpleuw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16u(n) <= op2->xmm16u(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpleud(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32u(n) <= op2->xmm32u(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpleuq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64u(n) <= op2->xmm64u(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare greater than (signed) BX_CPP_INLINE void sse_pcmpgtb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmsbyte(n) > op2->xmmsbyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpgtw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16s(n) > op2->xmm16s(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpgtd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32s(n) > op2->xmm32s(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpgtq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64s(n) > op2->xmm64s(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare greater than (unsigned) BX_CPP_INLINE void sse_pcmpgtub(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmubyte(n) > op2->xmmubyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpgtuw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16u(n) > op2->xmm16u(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpgtud(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32u(n) > op2->xmm32u(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpgtuq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64u(n) > op2->xmm64u(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare greater than or equal (signed) BX_CPP_INLINE void sse_pcmpgeb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmsbyte(n) >= op2->xmmsbyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpgew(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16s(n) >= op2->xmm16s(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpged(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32s(n) >= op2->xmm32s(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpgeq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64s(n) >= op2->xmm64s(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare greater than or equal (unsigned) BX_CPP_INLINE void sse_pcmpgeub(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmubyte(n) >= op2->xmmubyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpgeuw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16u(n) >= op2->xmm16u(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpgeud(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32u(n) >= op2->xmm32u(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpgeuq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64u(n) >= op2->xmm64u(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare equal BX_CPP_INLINE void sse_pcmpeqb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmubyte(n) == op2->xmmubyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpeqw(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16u(n) == op2->xmm16u(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpeqd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32u(n) == op2->xmm32u(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpeqq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64u(n) == op2->xmm64u(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare not equal BX_CPP_INLINE void sse_pcmpneb(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<16; n++) { op1->xmmubyte(n) = (op1->xmmubyte(n) != op2->xmmubyte(n)) ? 0xff : 0; } } BX_CPP_INLINE void sse_pcmpnew(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<8; n++) { op1->xmm16u(n) = (op1->xmm16u(n) != op2->xmm16u(n)) ? 0xffff : 0; } } BX_CPP_INLINE void sse_pcmpned(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<4; n++) { op1->xmm32u(n) = (op1->xmm32u(n) != op2->xmm32u(n)) ? 0xffffffff : 0; } } BX_CPP_INLINE void sse_pcmpneq(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = (op1->xmm64u(n) != op2->xmm64u(n)) ? BX_CONST64(0xffffffffffffffff) : 0; } } // compare true/false BX_CPP_INLINE void sse_pcmptrue(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = BX_CONST64(0xffffffffffffffff); } } BX_CPP_INLINE void sse_pcmpfalse(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2) { for(unsigned n=0; n<2; n++) { op1->xmm64u(n) = 0; } } #endif bochs-2.6/cpu/avx.cc0000644000175000017500000004777612020641453014253 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: avx.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX #include "simd_int.h" /* VZEROUPPER: VEX.128.0F.77 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VZEROUPPER(bxInstruction_c *i) { for(unsigned index=0; index < BX_XMM_REGISTERS; index++) { if (index < 8 || long64_mode()) BX_CLEAR_AVX_HIGH(index); } BX_NEXT_INSTR(i); } /* VZEROALL: VEX.256.0F.77 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VZEROALL(bxInstruction_c *i) { // prepare empty AVX register - zeroed by compiler because of static variable static BxPackedAvxRegister nil; for(unsigned index=0; index < BX_XMM_REGISTERS; index++) { if (index < 8 || long64_mode()) BX_WRITE_AVX_REG(index, nil); } BX_NEXT_INSTR(i); } /* VMOVSS: VEX.F3.0F 10 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src2()); op.xmm32u(0) = BX_READ_XMM_REG_LO_DWORD(i->src1()); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } /* VMOVSS: VEX.F2.0F 10 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op; op.xmm64u(0) = BX_READ_XMM_REG_LO_QWORD(i->src1()); op.xmm64u(1) = BX_READ_XMM_REG_HI_QWORD(i->src2()); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } /* VMOVAPS: VEX 0F 28 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVAPD: VEX.66.0F 28 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVDQA: VEX.66.0F 6F (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVAPS_VpsWpsR(bxInstruction_c *i) { BX_WRITE_AVX_REGZ(i->dst(), BX_READ_AVX_REG(i->src()), i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVAPS_VpsWpsM(bxInstruction_c *i) { BxPackedAvxRegister op; unsigned len = i->getVL(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dword_vector_aligned(i->seg(), eaddr, len << 2, &op); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* VMOVUPS: VEX 0F 10 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVUPD: VEX.66.0F 10 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVDQU: VEX.F3.0F 6F (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVUPS_VpsWpsM(bxInstruction_c *i) { BxPackedAvxRegister op; unsigned len = i->getVL(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dword_vector(i->seg(), eaddr, len << 2, &op); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* VMOVUPS: VEX 0F 11 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVUPD: VEX.66.0F 11 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVUQA: VEX.66.0F 7F (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVUPS_WpsVpsM(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword_vector(i->seg(), eaddr, i->getVL() << 2, &op); BX_NEXT_INSTR(i); } /* VMOVAPS: VEX 0F 29 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVAPD: VEX.66.0F 29 (VEX.W ignore, VEX.VVV #UD) */ /* VMOVDQA: VEX.66.0F 7F (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVAPS_WpsVpsM(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword_vector_aligned(i->seg(), eaddr, i->getVL() << 2, &op); BX_NEXT_INSTR(i); } /* VEX.F2.0F 12 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVDDUP_VpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); for (unsigned n=0; n < (2*len); n+=2) { op.avx64u(n+1) = op.avx64u(n); } BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* VEX.F3.0F 12 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVSLDUP_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); for (unsigned n=0; n < (4*len); n+=2) { op.avx32u(n+1) = op.avx32u(n); } BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* VEX.F3.0F 12 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVSHDUP_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); for (unsigned n=0; n < (4*len); n+=2) { op.avx32u(n) = op.avx32u(n+1); } BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* VEX.0F 12 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVHLPS_VpsHpsWps(bxInstruction_c *i) { BxPackedXmmRegister op; op.xmm64u(0) = BX_READ_XMM_REG_HI_QWORD(i->src2()); op.xmm64u(1) = BX_READ_XMM_REG_HI_QWORD(i->src1()); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } /* VEX.66.0F 12 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVLPD_VpdHpdMq(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); BxPackedXmmRegister op; op.xmm64u(0) = read_virtual_qword(i->seg(), eaddr); op.xmm64u(1) = BX_READ_XMM_REG_HI_QWORD(i->src1()); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } /* VEX.0F 16 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVLHPS_VpsHpsWps(bxInstruction_c *i) { BxPackedXmmRegister op; op.xmm64u(0) = BX_READ_XMM_REG_LO_QWORD(i->src1()); op.xmm64u(1) = BX_READ_XMM_REG_LO_QWORD(i->src2()); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } /* VEX.66.0F 16 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVHPD_VpdHpdMq(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); BxPackedXmmRegister op; op.xmm64u(0) = BX_READ_XMM_REG_LO_QWORD(i->src1()); op.xmm64u(1) = read_virtual_qword(i->seg(), eaddr); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } /* VEX.0F 50 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVMSKPS_GdVRps(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); Bit32u mask = 0; for (unsigned n=0; n < len; n++) mask |= sse_pmovmskd(&op.avx128(n)) << (4*n); BX_WRITE_32BIT_REGZ(i->dst(), mask); BX_NEXT_INSTR(i); } /* VEX.66.0F 50 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMOVMSKPD_GdVRpd(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); Bit32u mask = 0; for (unsigned n=0; n < len; n++) mask |= sse_pmovmskq(&op.avx128(n)) << (2*n); BX_WRITE_32BIT_REGZ(i->dst(), mask); BX_NEXT_INSTR(i); } /* VEX.66.0F 50 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVMSKB_GdUdq(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); Bit32u mask = 0; for (unsigned n=0; n < len; n++) mask |= sse_pmovmskb(&op.avx128(n)) << (16*n); BX_WRITE_32BIT_REGZ(i->dst(), mask); BX_NEXT_INSTR(i); } /* Opcode: VEX.0F.C6 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSHUFPS_VpsHpsWpsIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_shufps(&result.avx128(n), &op1.avx128(n), &op2.avx128(n), i->Ib()); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.C6 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSHUFPD_VpdHpdWpdIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; unsigned len = i->getVL(); Bit8u order = i->Ib(); for (unsigned n=0; n < len; n++) { sse_shufpd(&result.avx128(n), &op1.avx128(n), &op2.avx128(n), order); order >>= 2; } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38.17 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPTEST_VdqWdqR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->dst()), op2 = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); unsigned result = EFlagsZFMask | EFlagsCFMask; for (unsigned n=0; n < (2*len); n++) { if ((op2.avx64u(n) & op1.avx64u(n)) != 0) result &= ~EFlagsZFMask; if ((op2.avx64u(n) & ~op1.avx64u(n)) != 0) result &= ~EFlagsCFMask; } setEFlagsOSZAPC(result); BX_NEXT_INSTR(i); } /* Opcode: VEX.256.66.0F.38.1A (VEX.W=0, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VBROADCASTF128_VdqMdq(bxInstruction_c *i) { unsigned len = i->getVL(); BxPackedAvxRegister op; BxPackedXmmRegister src; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword(i->seg(), eaddr, (Bit8u*) &src); for (unsigned n=0; n < len; n++) { op.avx64u(n*2) = src.xmm64u(0); op.avx64u(n*2+1) = src.xmm64u(1); } BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 0C (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VBLENDPS_VpsHpsWpsIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); Bit8u mask = i->Ib(); for (unsigned n=0; n < len; n++) { sse_blendps(&op1.avx128(n), &op2.avx128(n), mask); mask >>= 4; } BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 0D (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VBLENDPD_VpdHpdWpdIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); Bit8u mask = i->Ib(); for (unsigned n=0; n < len; n++) { sse_blendpd(&op1.avx128(n), &op2.avx128(n), mask); mask >>= 2; } BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 4A (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VBLENDVPS_VpsHpsWpsIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()), mask = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_blendvps(&op1.avx128(n), &op2.avx128(n), &mask.avx128(n)); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 4B (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VBLENDVPD_VpdHpdWpdIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()), mask = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_blendvpd(&op1.avx128(n), &op2.avx128(n), &mask.avx128(n)); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 4C (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPBLENDVB_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()), mask = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_pblendvb(&op1.avx128(n), &op2.avx128(n), &mask.avx128(n)); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 18 (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VINSERTF128_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); op1.avx128(i->Ib() & 1) = BX_READ_XMM_REG(i->src2()); BX_WRITE_AVX_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 19 (VEX.W=0, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VEXTRACTF128_WdqVdqIbM(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dqword(i->seg(), eaddr, &(op.avx128(i->Ib() & 1))); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VEXTRACTF128_WdqVdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op.avx128(i->Ib() & 1)); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38 0C (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMILPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_permilps(&result.avx128(n), &op1.avx128(n), &op2.avx128(n)); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 05 (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMILPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_permilpd(&result.avx128(n), &op1.avx128(n), &op2.avx128(n)); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 04 (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMILPS_VpsWpsIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src()), result; unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_shufps(&result.avx128(n), &op1.avx128(n), &op1.avx128(n), i->Ib()); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 05 (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMILPD_VpdWpdIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src()), result; unsigned len = i->getVL(); Bit8u order = i->Ib(); for (unsigned n=0; n < len; n++) { sse_shufpd(&result.avx128(n), &op1.avx128(n), &op1.avx128(n), order); order >>= 2; } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A 06 (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERM2F128_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; Bit8u order = i->Ib(); for (unsigned n=0;n<2;n++) { if (order & 0x8) { result.avx64u(n*2) = result.avx64u(n*2+1) = 0; } else { if (order & 0x2) result.avx128(n) = op2.avx128(order & 0x1); else result.avx128(n) = op1.avx128(order & 0x1); } order >>= 4; } BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38 2C (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMASKMOVPS_VpsHpsMps(bxInstruction_c *i) { BxPackedAvxRegister mask = BX_READ_AVX_REG(i->src1()), result; unsigned len = i->getVL(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_X86_64 if (i->as64L()) { for (unsigned n=0; n < (4*len); n++) { if (mask.avx32u(n) & 0x80000000) { if (! IsCanonical(get_laddr64(i->seg(), eaddr + 4*n))) exception(int_number(i->seg()), 0); } } } #endif for (int n=4*len-1; n >= 0; n--) { if (mask.avx32u(n) & 0x80000000) result.avx32u(n) = read_virtual_dword(i->seg(), (eaddr + 4*n) & i->asize_mask()); else result.avx32u(n) = 0; } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38 2D (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMASKMOVPD_VpdHpdMpd(bxInstruction_c *i) { BxPackedAvxRegister mask = BX_READ_AVX_REG(i->src1()), result; unsigned len = i->getVL(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_X86_64 if (i->as64L()) { for (unsigned n=0; n < (2*len); n++) { if (mask.avx32u(n*2+1) & 0x80000000) { if (! IsCanonical(get_laddr64(i->seg(), eaddr + 8*n))) exception(int_number(i->seg()), 0); } } } #endif for (int n=2*len-1; n >= 0; n--) { if (mask.avx32u(n*2+1) & 0x80000000) result.avx64u(n) = read_virtual_qword(i->seg(), (eaddr + 8*n) & i->asize_mask()); else result.avx64u(n) = 0; } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38 2C (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMASKMOVPS_MpsHpsVps(bxInstruction_c *i) { BxPackedAvxRegister mask = BX_READ_AVX_REG(i->src1()), op = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_X86_64 if (i->as64L()) { for (unsigned n=0; n < (4*len); n++) { if (mask.avx32u(n) & 0x80000000) { if (! IsCanonical(get_laddr64(i->seg(), eaddr + 4*n))) exception(int_number(i->seg()), 0); } } } #endif // see you can successfully write all the elements first for (int n=4*len-1; n >= 0; n--) { if (mask.avx32u(n) & 0x80000000) read_RMW_virtual_dword(i->seg(), (eaddr + 4*n) & i->asize_mask()); } for (unsigned n=0; n < (4*len); n++) { if (mask.avx32u(n) & 0x80000000) write_virtual_dword(i->seg(), (eaddr + 4*n) & i->asize_mask(), op.avx32u(n)); } BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38 2D (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMASKMOVPD_MpdHpdVpd(bxInstruction_c *i) { BxPackedAvxRegister mask = BX_READ_AVX_REG(i->src1()), op = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_X86_64 if (i->as64L()) { for (unsigned n=0; n < (2*len); n++) { if (mask.avx32u(n*2+1) & 0x80000000) { if (! IsCanonical(get_laddr64(i->seg(), eaddr + 8*n))) exception(int_number(i->seg()), 0); } } } #endif // see you can successfully write all the elements first for (int n=2*len-1; n >= 0; n--) { if (mask.avx32u(2*n+1) & 0x80000000) read_RMW_virtual_qword(i->seg(), (eaddr + 8*n) & i->asize_mask()); } for (unsigned n=0; n < (2*len); n++) { if (mask.avx32u(2*n+1) & 0x80000000) write_virtual_qword(i->seg(), (eaddr + 8*n) & i->asize_mask(), op.avx64u(n)); } BX_NEXT_INSTR(i); } #endif // BX_SUPPORT_AVX bochs-2.6/cpu/stack16.cc0000644000175000017500000001563212020641453014713 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: stack16.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_RX(bxInstruction_c *i) { push_16(BX_READ_16BIT_REG(i->dst())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH16_Sw(bxInstruction_c *i) { push_16(BX_CPU_THIS_PTR sregs[i->src()].selector.value); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP16_Sw(bxInstruction_c *i) { RSP_SPECULATIVE; Bit16u selector = pop_16(); load_seg_reg(&BX_CPU_THIS_PTR sregs[i->dst()], selector); RSP_COMMIT; if (i->dst() == BX_SEG_REG_SS) { // POP SS inhibits interrupts, debug exceptions and single-step // trap exceptions until the execution boundary following the // next instruction is reached. // Same code as MOV_SwEw() inhibit_interrupts(BX_INHIBIT_INTERRUPTS_BY_MOVSS); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_RX(bxInstruction_c *i) { BX_WRITE_16BIT_REG(i->dst(), pop_16()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_EwM(bxInstruction_c *i) { RSP_SPECULATIVE; Bit16u val16 = pop_16(); // Note: there is one little weirdism here. It is possible to use // SP in the modrm addressing. If used, the value of SP after the // pop is used to calculate the address. bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), eaddr, val16); RSP_COMMIT; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_Iw(bxInstruction_c *i) { push_16(i->Iw()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_EwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_virtual_word(i->seg(), eaddr); push_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHAD16(bxInstruction_c *i) { Bit32u temp_ESP = ESP; Bit16u temp_SP = SP; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { stack_write_word((Bit32u)(temp_ESP - 2), AX); stack_write_word((Bit32u)(temp_ESP - 4), CX); stack_write_word((Bit32u)(temp_ESP - 6), DX); stack_write_word((Bit32u)(temp_ESP - 8), BX); stack_write_word((Bit32u)(temp_ESP - 10), temp_SP); stack_write_word((Bit32u)(temp_ESP - 12), BP); stack_write_word((Bit32u)(temp_ESP - 14), SI); stack_write_word((Bit32u)(temp_ESP - 16), DI); ESP -= 16; } else { stack_write_word((Bit16u)(temp_SP - 2), AX); stack_write_word((Bit16u)(temp_SP - 4), CX); stack_write_word((Bit16u)(temp_SP - 6), DX); stack_write_word((Bit16u)(temp_SP - 8), BX); stack_write_word((Bit16u)(temp_SP - 10), temp_SP); stack_write_word((Bit16u)(temp_SP - 12), BP); stack_write_word((Bit16u)(temp_SP - 14), SI); stack_write_word((Bit16u)(temp_SP - 16), DI); SP -= 16; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPAD16(bxInstruction_c *i) { Bit16u di, si, bp, bx, dx, cx, ax; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { Bit32u temp_ESP = ESP; di = stack_read_word((Bit32u)(temp_ESP + 0)); si = stack_read_word((Bit32u)(temp_ESP + 2)); bp = stack_read_word((Bit32u)(temp_ESP + 4)); stack_read_word((Bit32u)(temp_ESP + 6)); bx = stack_read_word((Bit32u)(temp_ESP + 8)); dx = stack_read_word((Bit32u)(temp_ESP + 10)); cx = stack_read_word((Bit32u)(temp_ESP + 12)); ax = stack_read_word((Bit32u)(temp_ESP + 14)); ESP += 16; } else { Bit16u temp_SP = SP; di = stack_read_word((Bit16u)(temp_SP + 0)); si = stack_read_word((Bit16u)(temp_SP + 2)); bp = stack_read_word((Bit16u)(temp_SP + 4)); stack_read_word((Bit16u)(temp_SP + 6)); bx = stack_read_word((Bit16u)(temp_SP + 8)); dx = stack_read_word((Bit16u)(temp_SP + 10)); cx = stack_read_word((Bit16u)(temp_SP + 12)); ax = stack_read_word((Bit16u)(temp_SP + 14)); SP += 16; } DI = di; SI = si; BP = bp; BX = bx; DX = dx; CX = cx; AX = ax; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ENTER16_IwIb(bxInstruction_c *i) { Bit16u imm16 = i->Iw(); Bit8u level = i->Ib2(); level &= 0x1F; RSP_SPECULATIVE; push_16(BP); Bit16u frame_ptr16 = SP; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { Bit32u ebp = EBP; // Use temp copy for case of exception. if (level > 0) { /* do level-1 times */ while (--level) { ebp -= 2; Bit16u temp16 = stack_read_word(ebp); push_16(temp16); } /* push(frame pointer) */ push_16(frame_ptr16); } ESP -= imm16; // ENTER finishes with memory write check on the final stack pointer // the memory is touched but no write actually occurs // emulate it by doing RMW read access from SS:ESP read_RMW_virtual_word(BX_SEG_REG_SS, ESP); BP = frame_ptr16; } else { Bit16u bp = BP; if (level > 0) { /* do level-1 times */ while (--level) { bp -= 2; Bit16u temp16 = stack_read_word(bp); push_16(temp16); } /* push(frame pointer) */ push_16(frame_ptr16); } SP -= imm16; // ENTER finishes with memory write check on the final stack pointer // the memory is touched but no write actually occurs // emulate it by doing RMW read access from SS:SP read_RMW_virtual_word_32(BX_SEG_REG_SS, SP); } BP = frame_ptr16; RSP_COMMIT; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LEAVE16(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit16u value16; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { value16 = stack_read_word(EBP); ESP = EBP + 2; } else { value16 = stack_read_word(BP); SP = BP + 2; } BP = value16; BX_NEXT_INSTR(i); } bochs-2.6/cpu/apic.cc0000644000175000017500000012503512020641453014352 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: apic.cc 11203 2012-06-04 14:27:34Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2002-2012 Zwane Mwaikambo, Stanislav Shwartsman // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #include "iodev/iodev.h" #if BX_SUPPORT_APIC extern bx_bool simulate_xapic; #define LOG_THIS this-> #define BX_CPU_APIC(i) (&(BX_CPU(i)->lapic)) #define BX_LAPIC_FIRST_VECTOR 0x10 #define BX_LAPIC_LAST_VECTOR 0xff ///////////// APIC BUS ///////////// int apic_bus_deliver_interrupt(Bit8u vector, apic_dest_t dest, Bit8u delivery_mode, bx_bool logical_dest, bx_bool level, bx_bool trig_mode) { if(delivery_mode == APIC_DM_LOWPRI) { if(! logical_dest) { // I/O subsytem initiated interrupt with lowest priority delivery // which is not supported in physical destination mode return 0; } else { return apic_bus_deliver_lowest_priority(vector, dest, trig_mode, 0); } } // determine destination local apics and deliver if(! logical_dest) { // physical destination mode if((dest & apic_id_mask) == apic_id_mask) { return apic_bus_broadcast_interrupt(vector, delivery_mode, trig_mode, apic_id_mask); } else { // the destination is single agent for (unsigned i=0;iget_id() == dest) { BX_CPU_APIC(i)->deliver(vector, delivery_mode, trig_mode); return 1; } } return 0; } } else { // logical destination mode if(dest == 0) return 0; bx_bool interrupt_delivered = 0; for (int i=0; imatch_logical_addr(dest)) { BX_CPU_APIC(i)->deliver(vector, delivery_mode, trig_mode); interrupt_delivered = 1; } } return interrupt_delivered; } } int apic_bus_deliver_lowest_priority(Bit8u vector, apic_dest_t dest, bx_bool trig_mode, bx_bool broadcast) { int i; if (! BX_CPU_APIC(0)->is_xapic()) { // search for if focus processor exists for (i=0; iis_focus(vector)) { BX_CPU_APIC(i)->deliver(vector, APIC_DM_LOWPRI, trig_mode); return 1; } } } // focus processor not found, looking for lowest priority agent int lowest_priority_agent = -1, lowest_priority = 0x100, priority; for (i=0; imatch_logical_addr(dest)) { if (BX_CPU_APIC(i)->is_xapic()) priority = BX_CPU_APIC(i)->get_tpr(); else priority = BX_CPU_APIC(i)->get_apr(); if(priority < lowest_priority) { lowest_priority = priority; lowest_priority_agent = i; } } } if(lowest_priority_agent >= 0) { BX_CPU_APIC(lowest_priority_agent)->deliver(vector, APIC_DM_LOWPRI, trig_mode); return 1; } return 0; } int apic_bus_broadcast_interrupt(Bit8u vector, Bit8u delivery_mode, bx_bool trig_mode, int exclude_cpu) { if(delivery_mode == APIC_DM_LOWPRI) { return apic_bus_deliver_lowest_priority(vector, 0 /* doesn't matter */, trig_mode, 1); } // deliver to all bus agents except 'exclude_cpu' for (int i=0; ideliver(vector, delivery_mode, trig_mode); } return 1; } static void apic_bus_broadcast_eoi(Bit8u vector) { DEV_ioapic_receive_eoi(vector); } #endif // available even if APIC is not compiled in BOCHSAPI_MSVCONLY void apic_bus_deliver_smi(void) { BX_CPU(0)->deliver_SMI(); } void apic_bus_broadcast_smi(void) { for (unsigned i=0; ideliver_SMI(); } #if BX_SUPPORT_APIC //////////////////////////////////// bx_local_apic_c::bx_local_apic_c(BX_CPU_C *mycpu, unsigned id) : base_addr(BX_LAPIC_BASE_ADDR), cpu(mycpu) { apic_id = id; #if BX_SUPPORT_SMP if (apic_id >= bx_cpu_count) BX_PANIC(("PANIC: invalid APIC_ID assigned %d (max = %d)", apic_id, bx_cpu_count)); #else if (apic_id != 0) BX_PANIC(("PANIC: invalid APIC_ID assigned %d", apic_id)); #endif char name[16], logname[16]; sprintf(name, "APIC%x", apic_id); sprintf(logname, "apic%x", apic_id); put(logname, name); // Register a non-active timer for use when the timer is started. timer_handle = bx_pc_system.register_timer_ticks(this, bx_local_apic_c::periodic_smf, 0, 0, 0, "lapic"); timer_active = 0; #if BX_SUPPORT_VMX >= 2 // Register a non-active timer for VMX preemption timer. vmx_timer_handle = bx_pc_system.register_timer_ticks(this, bx_local_apic_c::vmx_preemption_timer_expired, 0, 0, 0, "vmx_preemtion"); BX_DEBUG(("vmx_timer is = %d", vmx_timer_handle)); vmx_preemption_timer_rate = VMX_MISC_PREEMPTION_TIMER_RATE; vmx_timer_active = 0; #endif xapic = simulate_xapic; // xAPIC or legacy APIC reset(BX_RESET_HARDWARE); } void bx_local_apic_c::reset(unsigned type) { int i; // default address for a local APIC, can be moved base_addr = BX_LAPIC_BASE_ADDR; error_status = shadow_error_status = 0; ldr = 0; dest_format = 0xf; icr_hi = 0; icr_lo = 0; task_priority = 0; for(i=0; i= 6 ier[i] = 1; // all interrupts are enabled #endif } timer_divconf = 0; timer_divide_factor = 1; timer_initial = 0; timer_current = 0; ticksInitial = 0; if(timer_active) { bx_pc_system.deactivate_timer(timer_handle); timer_active = 0; } #if BX_SUPPORT_VMX >= 2 if(vmx_timer_active) { bx_pc_system.deactivate_timer(vmx_timer_handle); vmx_timer_active = 0; } #endif for(i=0; i= 6 xapic_ext = 0; #endif } #if BX_CPU_LEVEL >= 6 void bx_local_apic_c::enable_xapic_extensions(void) { apic_version_id |= 0x80000000; xapic_ext = BX_XAPIC_EXT_SUPPORT_IER | BX_XAPIC_EXT_SUPPORT_SEOI; } #endif void bx_local_apic_c::set_base(bx_phy_address newbase) { #if BX_CPU_LEVEL >= 6 if (mode == BX_APIC_X2APIC_MODE) ldr = ((apic_id & 0xfffffff0) << 16) | (1 << (apic_id & 0xf)); #endif mode = (newbase >> 10) & 3; newbase &= ~((bx_phy_address) 0xfff); base_addr = newbase; BX_INFO(("allocate APIC id=%d (MMIO %s) to 0x" FMT_PHY_ADDRX, apic_id, (mode == BX_APIC_XAPIC_MODE) ? "enabled" : "disabled", newbase)); } bx_bool bx_local_apic_c::is_selected(bx_phy_address addr) { if (mode != BX_APIC_XAPIC_MODE) return 0; if((addr & ~0xfff) == base_addr) { if((addr & 0xf) != 0) BX_INFO(("warning: misaligned APIC access. addr=0x" FMT_PHY_ADDRX, addr)); return 1; } return 0; } void bx_local_apic_c::read(bx_phy_address addr, void *data, unsigned len) { if((addr & ~0x3) != ((addr+len-1) & ~0x3)) { BX_PANIC(("APIC read at address 0x" FMT_PHY_ADDRX " spans 32-bit boundary !", addr)); return; } Bit32u value = read_aligned(addr & ~0x3); if(len == 4) { // must be 32-bit aligned *((Bit32u *)data) = value; return; } // handle partial read, independent of endian-ness value >>= (addr&3)*8; if (len == 1) *((Bit8u *) data) = value & 0xff; else if (len == 2) *((Bit16u *)data) = value & 0xffff; else BX_PANIC(("Unsupported APIC read at address 0x" FMT_PHY_ADDRX ", len=%d", addr, len)); } void bx_local_apic_c::write(bx_phy_address addr, void *data, unsigned len) { if (len != 4) { BX_PANIC(("APIC write with len=%d (should be 4)", len)); return; } if(addr & 0xf) { BX_PANIC(("APIC write at unaligned address 0x" FMT_PHY_ADDRX, addr)); return; } write_aligned(addr, *((Bit32u*) data)); } #define BX_LAPIC_ID 0x020 #define BX_LAPIC_VERSION 0x030 #define BX_LAPIC_TPR 0x080 #define BX_LAPIC_ARBITRATION_PRIORITY 0x090 #define BX_LAPIC_PPR 0x0A0 #define BX_LAPIC_EOI 0x0B0 #define BX_LAPIC_RRD 0x0C0 #define BX_LAPIC_LDR 0x0D0 #define BX_LAPIC_DESTINATION_FORMAT 0x0E0 #define BX_LAPIC_SPURIOUS_VECTOR 0x0F0 #define BX_LAPIC_ISR1 0x100 #define BX_LAPIC_ISR2 0x110 #define BX_LAPIC_ISR3 0x120 #define BX_LAPIC_ISR4 0x130 #define BX_LAPIC_ISR5 0x140 #define BX_LAPIC_ISR6 0x150 #define BX_LAPIC_ISR7 0x160 #define BX_LAPIC_ISR8 0x170 #define BX_LAPIC_TMR1 0x180 #define BX_LAPIC_TMR2 0x190 #define BX_LAPIC_TMR3 0x1A0 #define BX_LAPIC_TMR4 0x1B0 #define BX_LAPIC_TMR5 0x1C0 #define BX_LAPIC_TMR6 0x1D0 #define BX_LAPIC_TMR7 0x1E0 #define BX_LAPIC_TMR8 0x1F0 #define BX_LAPIC_IRR1 0x200 #define BX_LAPIC_IRR2 0x210 #define BX_LAPIC_IRR3 0x220 #define BX_LAPIC_IRR4 0x230 #define BX_LAPIC_IRR5 0x240 #define BX_LAPIC_IRR6 0x250 #define BX_LAPIC_IRR7 0x260 #define BX_LAPIC_IRR8 0x270 #define BX_LAPIC_ESR 0x280 #define BX_LAPIC_LVT_CMCI 0x2F0 #define BX_LAPIC_ICR_LO 0x300 #define BX_LAPIC_ICR_HI 0x310 #define BX_LAPIC_LVT_TIMER 0x320 #define BX_LAPIC_LVT_THERMAL 0x330 #define BX_LAPIC_LVT_PERFMON 0x340 #define BX_LAPIC_LVT_LINT0 0x350 #define BX_LAPIC_LVT_LINT1 0x360 #define BX_LAPIC_LVT_ERROR 0x370 #define BX_LAPIC_TIMER_INITIAL_COUNT 0x380 #define BX_LAPIC_TIMER_CURRENT_COUNT 0x390 #define BX_LAPIC_TIMER_DIVIDE_CFG 0x3E0 #define BX_LAPIC_SELF_IPI 0x3F0 // extended AMD #define BX_LAPIC_EXT_APIC_FEATURE 0x400 #define BX_LAPIC_EXT_APIC_CONTROL 0x410 #define BX_LAPIC_SPECIFIC_EOI 0x420 #define BX_LAPIC_IER1 0x480 #define BX_LAPIC_IER2 0x490 #define BX_LAPIC_IER3 0x4A0 #define BX_LAPIC_IER4 0x4B0 #define BX_LAPIC_IER5 0x4C0 #define BX_LAPIC_IER6 0x4D0 #define BX_LAPIC_IER7 0x4E0 #define BX_LAPIC_IER8 0x4F0 // APIC read: 4 byte read from 16-byte aligned APIC address Bit32u bx_local_apic_c::read_aligned(bx_phy_address addr) { BX_ASSERT((addr & 0xf) == 0); Bit32u data = 0; // default value for unimplemented registers unsigned apic_reg = addr & 0xff0; BX_DEBUG(("LAPIC read from register 0x%04x", apic_reg)); #if BX_CPU_LEVEL >= 6 if (apic_reg >= 0x400 && !cpu->bx_cpuid_support_xapic_extensions()) apic_reg = 0xffffffff; // choose some obviosly invalid register if extended xapic is not supported #endif switch(apic_reg) { case BX_LAPIC_ID: // local APIC id data = apic_id << 24; break; case BX_LAPIC_VERSION: // local APIC version data = apic_version_id; break; case BX_LAPIC_TPR: // task priority data = task_priority & 0xff; break; case BX_LAPIC_ARBITRATION_PRIORITY: data = get_apr(); break; case BX_LAPIC_PPR: // processor priority data = get_ppr(); break; case BX_LAPIC_EOI: // EOI /* * Read-modify-write operations should operate without generating * exceptions, and are used by some operating systems to EOI. * The results of reads should be ignored by the OS. */ break; case BX_LAPIC_LDR: // logical destination data = (ldr & apic_id_mask) << 24; break; case BX_LAPIC_DESTINATION_FORMAT: data = ((dest_format & 0xf) << 28) | 0x0fffffff; break; case BX_LAPIC_SPURIOUS_VECTOR: { Bit32u reg = spurious_vector; if(software_enabled) reg |= 0x100; if(focus_disable) reg |= 0x200; data = reg; } break; case BX_LAPIC_ISR1: case BX_LAPIC_ISR2: case BX_LAPIC_ISR3: case BX_LAPIC_ISR4: case BX_LAPIC_ISR5: case BX_LAPIC_ISR6: case BX_LAPIC_ISR7: case BX_LAPIC_ISR8: { unsigned index = (apic_reg - BX_LAPIC_ISR1) << 1; Bit32u value = 0, mask = 1; for(int i=0;i<32;i++) { if(isr[index+i]) value |= mask; mask <<= 1; } data = value; } break; case BX_LAPIC_TMR1: case BX_LAPIC_TMR2: case BX_LAPIC_TMR3: case BX_LAPIC_TMR4: case BX_LAPIC_TMR5: case BX_LAPIC_TMR6: case BX_LAPIC_TMR7: case BX_LAPIC_TMR8: { unsigned index = (apic_reg - BX_LAPIC_TMR1) << 1; Bit32u value = 0, mask = 1; for(int i=0;i<32;i++) { if(tmr[index+i]) value |= mask; mask <<= 1; } data = value; } break; case BX_LAPIC_IRR1: case BX_LAPIC_IRR2: case BX_LAPIC_IRR3: case BX_LAPIC_IRR4: case BX_LAPIC_IRR5: case BX_LAPIC_IRR6: case BX_LAPIC_IRR7: case BX_LAPIC_IRR8: { unsigned index = (apic_reg - BX_LAPIC_IRR1) << 1; Bit32u value = 0, mask = 1; for(int i=0;i<32;i++) { if(irr[index+i]) value |= mask; mask <<= 1; } data = value; } break; case BX_LAPIC_ESR: // error status reg data = error_status; break; case BX_LAPIC_ICR_LO: // interrupt command reg 0-31 data = icr_lo; break; case BX_LAPIC_ICR_HI: // interrupt command reg 31-63 data = icr_hi; break; case BX_LAPIC_LVT_TIMER: // LVT Timer Reg case BX_LAPIC_LVT_THERMAL: // LVT Thermal Monitor case BX_LAPIC_LVT_PERFMON: // LVT Performance Counter case BX_LAPIC_LVT_LINT0: // LVT LINT0 Reg case BX_LAPIC_LVT_LINT1: // LVT Lint1 Reg case BX_LAPIC_LVT_ERROR: // LVT Error Reg { int index = (apic_reg - BX_LAPIC_LVT_TIMER) >> 4; data = lvt[index]; break; } case BX_LAPIC_TIMER_INITIAL_COUNT: // initial count for timer data = timer_initial; break; case BX_LAPIC_TIMER_CURRENT_COUNT: // current count for timer data = get_current_timer_count(); break; case BX_LAPIC_TIMER_DIVIDE_CFG: // timer divide configuration data = timer_divconf; break; #if BX_CPU_LEVEL >= 6 case BX_LAPIC_EXT_APIC_FEATURE: /* report extended xAPIC capabilities */ data = BX_XAPIC_EXT_SUPPORT_IER | BX_XAPIC_EXT_SUPPORT_SEOI; break; case BX_LAPIC_EXT_APIC_CONTROL: /* report enabled extended xAPIC capabilities */ data = xapic_ext; break; case BX_LAPIC_SPECIFIC_EOI: /* * Read-modify-write operations should operate without generating * exceptions, and are used by some operating systems to EOI. * The results of reads should be ignored by the OS. */ break; case BX_LAPIC_IER1: case BX_LAPIC_IER2: case BX_LAPIC_IER3: case BX_LAPIC_IER4: case BX_LAPIC_IER5: case BX_LAPIC_IER6: case BX_LAPIC_IER7: case BX_LAPIC_IER8: { unsigned index = (apic_reg - BX_LAPIC_IER1) << 1; Bit32u value = 0, mask = 1; for(int i=0;i<32;i++) { if(ier[index+i]) value |= mask; mask <<= 1; } data = value; } break; #endif default: shadow_error_status |= APIC_ERR_ILLEGAL_ADDR; // but for now I want to know about it in case I missed some. BX_ERROR(("APIC read: register %x not implemented", apic_reg)); } BX_DEBUG(("read from APIC address 0x" FMT_PHY_ADDRX " = %08x", addr, data)); return data; } // APIC write: 4 byte write to 16-byte aligned APIC address void bx_local_apic_c::write_aligned(bx_phy_address addr, Bit32u value) { BX_ASSERT((addr & 0xf) == 0); unsigned apic_reg = addr & 0xff0; BX_DEBUG(("LAPIC write 0x%08x to register 0x%04x", value, apic_reg)); #if BX_CPU_LEVEL >= 6 if (apic_reg >= 0x400 && !cpu->bx_cpuid_support_xapic_extensions()) apic_reg = 0xffffffff; // choose some obviosly invalid register if extended xapic is not supported #endif switch(apic_reg) { case BX_LAPIC_TPR: // task priority set_tpr(value & 0xff); break; case BX_LAPIC_EOI: // EOI receive_EOI(value); break; case BX_LAPIC_LDR: // logical destination ldr = (value >> 24) & apic_id_mask; BX_DEBUG(("set logical destination to %08x", ldr)); break; case BX_LAPIC_DESTINATION_FORMAT: dest_format = (value >> 28) & 0xf; BX_DEBUG(("set destination format to %02x", dest_format)); break; case BX_LAPIC_SPURIOUS_VECTOR: write_spurious_interrupt_register(value); break; case BX_LAPIC_ESR: // error status reg // Here's what the IA-devguide-3 says on p.7-45: // The ESR is a read/write register and is reset after being written to // by the processor. A write to the ESR must be done just prior to // reading the ESR to allow the register to be updated. error_status = shadow_error_status; shadow_error_status = 0; break; case BX_LAPIC_ICR_LO: // interrupt command reg 0-31 icr_lo = value & ~(1<<12); // force delivery status bit = 0(idle) send_ipi((icr_hi >> 24) & 0xff, icr_lo); break; case BX_LAPIC_ICR_HI: // interrupt command reg 31-63 icr_hi = value & 0xff000000; break; case BX_LAPIC_LVT_TIMER: // LVT Timer Reg case BX_LAPIC_LVT_THERMAL: // LVT Thermal Monitor case BX_LAPIC_LVT_PERFMON: // LVT Performance Counter case BX_LAPIC_LVT_LINT0: // LVT LINT0 Reg case BX_LAPIC_LVT_LINT1: // LVT LINT1 Reg case BX_LAPIC_LVT_ERROR: // LVT Error Reg set_lvt_entry(apic_reg, value); break; case BX_LAPIC_TIMER_INITIAL_COUNT: set_initial_timer_count(value); break; case BX_LAPIC_TIMER_DIVIDE_CFG: // only bits 3, 1, and 0 are writable timer_divconf = value & 0xb; set_divide_configuration(timer_divconf); break; /* all read-only registers go here */ case BX_LAPIC_ID: // local APIC id case BX_LAPIC_VERSION: // local APIC version case BX_LAPIC_ARBITRATION_PRIORITY: case BX_LAPIC_RRD: case BX_LAPIC_PPR: // processor priority // ISRs not writable case BX_LAPIC_ISR1: case BX_LAPIC_ISR2: case BX_LAPIC_ISR3: case BX_LAPIC_ISR4: case BX_LAPIC_ISR5: case BX_LAPIC_ISR6: case BX_LAPIC_ISR7: case BX_LAPIC_ISR8: // TMRs not writable case BX_LAPIC_TMR1: case BX_LAPIC_TMR2: case BX_LAPIC_TMR3: case BX_LAPIC_TMR4: case BX_LAPIC_TMR5: case BX_LAPIC_TMR6: case BX_LAPIC_TMR7: case BX_LAPIC_TMR8: // IRRs not writable case BX_LAPIC_IRR1: case BX_LAPIC_IRR2: case BX_LAPIC_IRR3: case BX_LAPIC_IRR4: case BX_LAPIC_IRR5: case BX_LAPIC_IRR6: case BX_LAPIC_IRR7: case BX_LAPIC_IRR8: // current count for timer case BX_LAPIC_TIMER_CURRENT_COUNT: // all read-only registers should fall into this line BX_INFO(("warning: write to read-only APIC register 0x%x", apic_reg)); break; #if BX_CPU_LEVEL >= 6 case BX_LAPIC_EXT_APIC_FEATURE: // all read-only registers should fall into this line BX_INFO(("warning: write to read-only APIC register 0x%x", apic_reg)); break; case BX_LAPIC_EXT_APIC_CONTROL: /* set extended xAPIC capabilities */ xapic_ext = value & (BX_XAPIC_EXT_SUPPORT_IER | BX_XAPIC_EXT_SUPPORT_SEOI); break; case BX_LAPIC_SPECIFIC_EOI: receive_SEOI(value & 0xff); break; case BX_LAPIC_IER1: case BX_LAPIC_IER2: case BX_LAPIC_IER3: case BX_LAPIC_IER4: case BX_LAPIC_IER5: case BX_LAPIC_IER6: case BX_LAPIC_IER7: case BX_LAPIC_IER8: { if ((xapic_ext & BX_XAPIC_EXT_SUPPORT_IER) == 0) { BX_ERROR(("IER writes are currently disabled reg %x", apic_reg)); break; } unsigned index = (apic_reg - BX_LAPIC_IER1) << 1; Bit32u mask = 1; for(int i=0;i<32;i++) { if(value & mask) ier[index+i] = 1; mask <<= 1; } } break; #endif default: shadow_error_status |= APIC_ERR_ILLEGAL_ADDR; // but for now I want to know about it in case I missed some. BX_ERROR(("APIC write: register %x not implemented", apic_reg)); } } void bx_local_apic_c::set_lvt_entry(unsigned apic_reg, Bit32u value) { static Bit32u lvt_mask[] = { 0x000710ff, /* TIMER */ 0x000117ff, /* THERMAL */ 0x000117ff, /* PERFMON */ 0x0001f7ff, /* LINT0 */ 0x0001f7ff, /* LINT1 */ 0x000110ff /* ERROR */ }; unsigned lvt_entry = (apic_reg - BX_LAPIC_LVT_TIMER) >> 4; #if BX_CPU_LEVEL >= 6 if (apic_reg == BX_LAPIC_LVT_TIMER) { if (! cpu->bx_cpuid_support_tsc_deadline()) { value &= ~0x40000; // cannot enable TSC-Deadline when not supported } else { if ((value ^ lvt[lvt_entry]) & 0x40000) { // Transition between TSC-Deadline and other timer modes disarm the timer if(timer_active) { bx_pc_system.deactivate_timer(timer_handle); timer_active = 0; } } } } #endif lvt[lvt_entry] = value & lvt_mask[lvt_entry]; if(! software_enabled) { lvt[lvt_entry] |= 0x10000; } } void bx_local_apic_c::send_ipi(apic_dest_t dest, Bit32u lo_cmd) { int dest_shorthand = (lo_cmd >> 18) & 3; int trig_mode = (lo_cmd >> 15) & 1; int level = (lo_cmd >> 14) & 1; int logical_dest = (lo_cmd >> 11) & 1; int delivery_mode = (lo_cmd >> 8) & 7; int vector = (lo_cmd & 0xff); int accepted = 0; if(delivery_mode == APIC_DM_INIT) { if(level == 0 && trig_mode == 1) { // special mode in local apic. See "INIT Level Deassert" in the // Intel Soft. Devel. Guide Vol 3, page 7-34. This magic code // causes all APICs(regardless of dest address) to set their // arbitration ID to their APIC ID. Not supported by Pentium 4 // and Intel Xeon processors. return; // we not model APIC bus arbitration ID anyway } } switch(dest_shorthand) { case 0: // no shorthand, use real destination value accepted = apic_bus_deliver_interrupt(vector, dest, delivery_mode, logical_dest, level, trig_mode); break; case 1: // self trigger_irq(vector, trig_mode); accepted = 1; break; case 2: // all including self accepted = apic_bus_broadcast_interrupt(vector, delivery_mode, trig_mode, apic_id_mask); break; case 3: // all but self accepted = apic_bus_broadcast_interrupt(vector, delivery_mode, trig_mode, get_id()); break; default: BX_PANIC(("Invalid desination shorthand %#x", dest_shorthand)); } if(! accepted) { BX_DEBUG(("An IPI wasn't accepted, raise APIC_ERR_TX_ACCEPT_ERR")); shadow_error_status |= APIC_ERR_TX_ACCEPT_ERR; } } void bx_local_apic_c::write_spurious_interrupt_register(Bit32u value) { BX_DEBUG(("write of %08x to spurious interrupt register", value)); if (xapic) spurious_vector = value & 0xff; else // bits 0-3 of the spurious vector hardwired to '1 spurious_vector = (value & 0xf0) | 0xf; software_enabled = (value >> 8) & 1; focus_disable = (value >> 9) & 1; if(! software_enabled) { for(unsigned i=0; i= 6 void bx_local_apic_c::receive_SEOI(Bit8u vec) { if ((xapic_ext & BX_XAPIC_EXT_SUPPORT_SEOI) == 0) { BX_ERROR(("SEOI functionality is disabled")); return; } if (isr[vec]) { BX_DEBUG(("local apic received SEOI for vector 0x%02x", vec)); isr[vec] = 0; if(tmr[vec]) { apic_bus_broadcast_eoi(vec); tmr[vec] = 0; } service_local_apic(); } if(bx_dbg.apic) print_status(); } #endif void bx_local_apic_c::startup_msg(Bit8u vector) { cpu->deliver_SIPI(vector); } int bx_local_apic_c::highest_priority_int(Bit8u *array) { for(int i=BX_LAPIC_LAST_VECTOR; i>=BX_LAPIC_FIRST_VECTOR; i--) { #if BX_CPU_LEVEL >= 6 if (! ier[i]) continue; #endif if (array[i]) return i; } return -1; } void bx_local_apic_c::service_local_apic(void) { if(bx_dbg.apic) { BX_INFO(("service_local_apic()")); print_status(); } if(INTR) return; // INTR already up; do nothing // find first interrupt in irr. int first_irr = highest_priority_int(irr); if (first_irr < 0) return; // no interrupts, leave INTR=0 int first_isr = highest_priority_int(isr); if (first_isr >= 0 && first_irr <= first_isr) { BX_DEBUG(("lapic(%d): not delivering int 0x%02x because int 0x%02x is in service", apic_id, first_irr, first_isr)); return; } if(((Bit32u)(first_irr) & 0xf0) <= (task_priority & 0xf0)) { BX_DEBUG(("lapic(%d): not delivering int 0x%02X because task_priority is 0x%02X", apic_id, first_irr, task_priority)); return; } // interrupt has appeared in irr. Raise INTR. When the CPU // acknowledges, we will run highest_priority_int again and // return it. BX_DEBUG(("service_local_apic(): setting INTR=1 for vector 0x%02x", first_irr)); INTR = 1; cpu->async_event = 1; } bx_bool bx_local_apic_c::deliver(Bit8u vector, Bit8u delivery_mode, Bit8u trig_mode) { switch(delivery_mode) { case APIC_DM_FIXED: case APIC_DM_LOWPRI: BX_DEBUG(("Deliver lowest priority of fixed interrupt vector %02x", vector)); trigger_irq(vector, trig_mode); break; case APIC_DM_SMI: BX_INFO(("Deliver SMI")); cpu->deliver_SMI(); return 1; case APIC_DM_NMI: BX_INFO(("Deliver NMI")); cpu->deliver_NMI(); return 1; case APIC_DM_INIT: BX_INFO(("Deliver INIT IPI")); cpu->deliver_INIT(); break; case APIC_DM_SIPI: BX_INFO(("Deliver Start Up IPI")); startup_msg(vector); break; case APIC_DM_EXTINT: BX_DEBUG(("Deliver EXTINT vector %02x", vector)); trigger_irq(vector, trig_mode, 1); break; default: return 0; } return 1; } void bx_local_apic_c::trigger_irq(Bit8u vector, unsigned trigger_mode, bx_bool bypass_irr_isr) { BX_DEBUG(("trigger interrupt vector=0x%02x", vector)); if(/* vector > BX_LAPIC_LAST_VECTOR || */ vector < BX_LAPIC_FIRST_VECTOR) { shadow_error_status |= APIC_ERR_RX_ILLEGAL_VEC; BX_INFO(("bogus vector %#x, ignoring ...", vector)); return; } BX_DEBUG(("triggered vector %#02x", vector)); if(bypass_irr_isr) { goto service_vector; } if(irr[vector] != 0) { BX_DEBUG(("triggered vector %#02x not accepted", vector)); return; } service_vector: irr[vector] = 1; tmr[vector] = trigger_mode; // set for level triggered service_local_apic(); } void bx_local_apic_c::untrigger_irq(Bit8u vector, unsigned trigger_mode) { BX_DEBUG(("untrigger interrupt vector=0x%02x", vector)); // hardware says "no more". clear the bit. If the CPU hasn't yet // acknowledged the interrupt, it will never be serviced. BX_ASSERT(irr[vector] == 1); irr[vector] = 0; if(bx_dbg.apic) print_status(); } Bit8u bx_local_apic_c::acknowledge_int(void) { // CPU calls this when it is ready to service one interrupt if(!INTR) BX_PANIC(("APIC %d acknowledged an interrupt, but INTR=0", apic_id)); BX_ASSERT(INTR); int vector = highest_priority_int(irr); if (vector < 0) goto spurious; if((vector & 0xf0) <= get_ppr()) goto spurious; BX_ASSERT(irr[vector] == 1); BX_DEBUG(("acknowledge_int() returning vector 0x%02x", vector)); irr[vector] = 0; isr[vector] = 1; if(bx_dbg.apic) { BX_INFO(("Status after setting isr:")); print_status(); } INTR = 0; cpu->async_event = 1; service_local_apic(); // will set INTR again if another is ready return vector; spurious: INTR = 0; cpu->async_event = 1; return spurious_vector; } void bx_local_apic_c::print_status(void) { BX_INFO(("lapic %d: status is {:", apic_id)); for(int vec=0; vec= 6 if (mode == BX_APIC_X2APIC_MODE) { // only cluster model supported in x2apic mode if (address == 0xffffffff) // // broadcast all return 1; if ((address & 0xffff0000) == (ldr & 0xffff0000)) match = ((address & ldr & 0x0000ffff) != 0); return match; } #endif if (dest_format == 0xf) { // flat model match = ((address & ldr) != 0); BX_DEBUG(("comparing MDA %02x to my LDR %02x -> %s", address, ldr, match ? "Match" : "Not a match")); } else if (dest_format == 0) { // cluster model if (address == 0xff) // broadcast all return 1; if ((unsigned)(address & 0xf0) == (unsigned)(ldr & 0xf0)) match = ((address & ldr & 0x0f) != 0); } else { BX_PANIC(("bx_local_apic_c::match_logical_addr: unsupported dest format 0x%x", dest_format)); } return match; } Bit8u bx_local_apic_c::get_ppr(void) { int ppr = highest_priority_int(isr); if((ppr < 0) || ((task_priority & 0xF0) >= ((Bit32u) ppr & 0xF0))) ppr = task_priority; else ppr &= 0xF0; return ppr; } void bx_local_apic_c::set_tpr(Bit8u priority) { if(priority < task_priority) { task_priority = priority; service_local_apic(); } else { task_priority = priority; } } Bit8u bx_local_apic_c::get_apr(void) { Bit32u tpr = (task_priority >> 4) & 0xf; int first_isr = highest_priority_int(isr); if (first_isr < 0) first_isr = 0; int first_irr = highest_priority_int(irr); if (first_irr < 0) first_irr = 0; Bit32u isrv = (first_isr >> 4) & 0xf; Bit32u irrv = (first_irr >> 4) & 0xf; Bit8u apr; if((tpr >= irrv) && (tpr > isrv)) { apr = task_priority & 0xff; } else { apr = ((tpr & isrv) > irrv) ?(tpr & isrv) : irrv; apr <<= 4; } BX_DEBUG(("apr = %d", apr)); return(Bit8u) apr; } bx_bool bx_local_apic_c::is_focus(Bit8u vector) { if(focus_disable) return 0; return(irr[vector] || isr[vector]) ? 1 : 0; } void bx_local_apic_c::periodic_smf(void *this_ptr) { bx_local_apic_c *class_ptr = (bx_local_apic_c *) this_ptr; class_ptr->periodic(); } void bx_local_apic_c::periodic(void) { if(!timer_active) { BX_ERROR(("bx_local_apic_c::periodic called, timer_active==0")); return; } Bit32u timervec = lvt[APIC_LVT_TIMER]; // If timer is not masked, trigger interrupt if((timervec & 0x10000)==0) { trigger_irq(timervec & 0xff, APIC_EDGE_TRIGGERED); } else { BX_DEBUG(("local apic timer LVT masked")); } // timer reached zero since the last call to periodic if(timervec & 0x20000) { // Periodic mode - reload timer values timer_current = timer_initial; timer_active = 1; ticksInitial = bx_pc_system.time_ticks(); // timer value when it started to count BX_DEBUG(("local apic timer(periodic) triggered int, reset counter to 0x%08x", timer_current)); bx_pc_system.activate_timer_ticks(timer_handle, Bit64u(timer_initial) * Bit64u(timer_divide_factor), 0); } else { // one-shot mode timer_current = 0; timer_active = 0; BX_DEBUG(("local apic timer(one-shot) triggered int")); bx_pc_system.deactivate_timer(timer_handle); } } void bx_local_apic_c::set_divide_configuration(Bit32u value) { BX_ASSERT(value == (value & 0x0b)); // move bit 3 down to bit 0 value = ((value & 8) >> 1) | (value & 3); BX_ASSERT(value >= 0 && value <= 7); timer_divide_factor = (value==7) ? 1 : (2 << value); BX_INFO(("set timer divide factor to %d", timer_divide_factor)); } void bx_local_apic_c::set_initial_timer_count(Bit32u value) { Bit32u timervec = lvt[APIC_LVT_TIMER]; #if BX_CPU_LEVEL >= 6 // in TSC-deadline mode writes to initial time count are ignored if (timervec & 0x40000) return; #endif // If active before, deactivate the current timer before changing it. if(timer_active) { bx_pc_system.deactivate_timer(timer_handle); timer_active = 0; } timer_initial = value; timer_current = 0; if(timer_initial != 0) // terminate the counting if timer_initial = 0 { // This should trigger the counter to start. If already started, // restart from the new start value. BX_DEBUG(("APIC: Initial Timer Count Register = %u", value)); timer_current = timer_initial; timer_active = 1; ticksInitial = bx_pc_system.time_ticks(); // timer value when it started to count bx_pc_system.activate_timer_ticks(timer_handle, Bit64u(timer_initial) * Bit64u(timer_divide_factor), 0); } } Bit32u bx_local_apic_c::get_current_timer_count(void) { #if BX_CPU_LEVEL >= 6 Bit32u timervec = lvt[APIC_LVT_TIMER]; // in TSC-deadline mode current timer count always reads 0 if (timervec & 0x40000) return 0; #endif if(timer_active==0) { return timer_current; } else { Bit64u delta64 = (bx_pc_system.time_ticks() - ticksInitial) / timer_divide_factor; Bit32u delta32 = (Bit32u) delta64; if(delta32 > timer_initial) BX_PANIC(("APIC: R(curr timer count): delta < initial")); timer_current = timer_initial - delta32; return timer_current; } } #if BX_CPU_LEVEL >= 6 void bx_local_apic_c::set_tsc_deadline(Bit64u deadline) { Bit32u timervec = lvt[APIC_LVT_TIMER]; if ((timervec & 0x40000) == 0) { BX_ERROR(("APIC: TSC-Deadline timer is disabled")); return; } // If active before, deactivate the current timer before changing it. if(timer_active) { bx_pc_system.deactivate_timer(timer_handle); timer_active = 0; } ticksInitial = deadline; if (deadline != 0) { BX_INFO(("APIC: TSC-Deadline is set to " FMT_LL "d", deadline)); Bit64u currtime = bx_pc_system.time_ticks(); timer_active = 1; bx_pc_system.activate_timer_ticks(timer_handle, (deadline > currtime) ? (deadline - currtime) : 1 , 0); } } Bit64u bx_local_apic_c::get_tsc_deadline(void) { Bit32u timervec = lvt[APIC_LVT_TIMER]; // read as zero if TSC-deadline timer is disabled if ((timervec & 0x40000) == 0) return 0; return ticksInitial; /* also holds TSC-deadline value */ } #endif #if BX_SUPPORT_VMX >= 2 Bit32u bx_local_apic_c::read_vmx_preemption_timer(void) { Bit32u diff = (bx_pc_system.time_ticks() >> vmx_preemption_timer_rate) - (vmx_preemption_timer_initial >> vmx_preemption_timer_rate); if (vmx_preemption_timer_value < diff) return 0; else return vmx_preemption_timer_value - diff; } void bx_local_apic_c::set_vmx_preemption_timer(Bit32u value) { vmx_preemption_timer_value = value; vmx_preemption_timer_initial = bx_pc_system.time_ticks(); vmx_preemption_timer_fire = ((vmx_preemption_timer_initial >> vmx_preemption_timer_rate) + value) << vmx_preemption_timer_rate; BX_DEBUG(("VMX Preemption timer. value = %u, rate = %u, init = %u, fire = %u", value, vmx_preemption_timer_rate, vmx_preemption_timer_initial, vmx_preemption_timer_fire)); bx_pc_system.activate_timer_ticks(vmx_timer_handle, vmx_preemption_timer_fire - vmx_preemption_timer_initial, 0); vmx_timer_active = 1; } void bx_local_apic_c::deactivate_vmx_preemption_timer(void) { if (! vmx_timer_active) return; bx_pc_system.deactivate_timer(vmx_timer_handle); vmx_timer_active = 0; } // Invoked when VMX preemption timer expired void bx_local_apic_c::vmx_preemption_timer_expired(void *this_ptr) { bx_local_apic_c *class_ptr = (bx_local_apic_c *) this_ptr; class_ptr->cpu->pending_vmx_timer_expired = 1; class_ptr->cpu->async_event = 1; class_ptr->deactivate_vmx_preemption_timer(); } #endif #if BX_CPU_LEVEL >= 6 // return false when x2apic is not supported/not readable bx_bool bx_local_apic_c::read_x2apic(unsigned index, Bit64u *val_64) { index = (index - 0x800) << 4; switch(index) { // return full 32-bit lapic id case BX_LAPIC_ID: *val_64 = apic_id; break; case BX_LAPIC_LDR: *val_64 = ldr; break; // full 64-bit access to ICR case BX_LAPIC_ICR_LO: *val_64 = ((Bit64u) icr_lo) | (((Bit64u) icr_hi) << 32); break; // not supported/not readable in x2apic mode case BX_LAPIC_ARBITRATION_PRIORITY: case BX_LAPIC_DESTINATION_FORMAT: case BX_LAPIC_ICR_HI: case BX_LAPIC_EOI: // write only case BX_LAPIC_SELF_IPI: // write only return 0; // compatible to legacy lapic mode case BX_LAPIC_VERSION: case BX_LAPIC_TPR: case BX_LAPIC_PPR: case BX_LAPIC_SPURIOUS_VECTOR: case BX_LAPIC_ISR1: case BX_LAPIC_ISR2: case BX_LAPIC_ISR3: case BX_LAPIC_ISR4: case BX_LAPIC_ISR5: case BX_LAPIC_ISR6: case BX_LAPIC_ISR7: case BX_LAPIC_ISR8: case BX_LAPIC_TMR1: case BX_LAPIC_TMR2: case BX_LAPIC_TMR3: case BX_LAPIC_TMR4: case BX_LAPIC_TMR5: case BX_LAPIC_TMR6: case BX_LAPIC_TMR7: case BX_LAPIC_TMR8: case BX_LAPIC_IRR1: case BX_LAPIC_IRR2: case BX_LAPIC_IRR3: case BX_LAPIC_IRR4: case BX_LAPIC_IRR5: case BX_LAPIC_IRR6: case BX_LAPIC_IRR7: case BX_LAPIC_IRR8: case BX_LAPIC_ESR: case BX_LAPIC_LVT_TIMER: case BX_LAPIC_LVT_THERMAL: case BX_LAPIC_LVT_PERFMON: case BX_LAPIC_LVT_LINT0: case BX_LAPIC_LVT_LINT1: case BX_LAPIC_LVT_ERROR: case BX_LAPIC_TIMER_INITIAL_COUNT: case BX_LAPIC_TIMER_CURRENT_COUNT: case BX_LAPIC_TIMER_DIVIDE_CFG: *val_64 = read_aligned(index); break; default: BX_DEBUG(("read_x2apic: not supported apic register 0x%08x", index)); return 0; } return 1; } // return false when x2apic is not supported/not writeable bx_bool bx_local_apic_c::write_x2apic(unsigned index, Bit32u val32_hi, Bit32u val32_lo) { index = (index - 0x800) << 4; if (index != BX_LAPIC_ICR_LO) { // upper 32-bit are reserved for all x2apic MSRs except for the ICR if (val32_hi != 0) return 0; } switch(index) { // read only/not available in x2apic mode case BX_LAPIC_ID: case BX_LAPIC_VERSION: case BX_LAPIC_ARBITRATION_PRIORITY: case BX_LAPIC_PPR: case BX_LAPIC_LDR: case BX_LAPIC_DESTINATION_FORMAT: case BX_LAPIC_ISR1: case BX_LAPIC_ISR2: case BX_LAPIC_ISR3: case BX_LAPIC_ISR4: case BX_LAPIC_ISR5: case BX_LAPIC_ISR6: case BX_LAPIC_ISR7: case BX_LAPIC_ISR8: case BX_LAPIC_TMR1: case BX_LAPIC_TMR2: case BX_LAPIC_TMR3: case BX_LAPIC_TMR4: case BX_LAPIC_TMR5: case BX_LAPIC_TMR6: case BX_LAPIC_TMR7: case BX_LAPIC_TMR8: case BX_LAPIC_IRR1: case BX_LAPIC_IRR2: case BX_LAPIC_IRR3: case BX_LAPIC_IRR4: case BX_LAPIC_IRR5: case BX_LAPIC_IRR6: case BX_LAPIC_IRR7: case BX_LAPIC_IRR8: case BX_LAPIC_ICR_HI: case BX_LAPIC_TIMER_CURRENT_COUNT: return 0; // send self ipi case BX_LAPIC_SELF_IPI: trigger_irq(val32_lo & 0xff, APIC_EDGE_TRIGGERED); return 1; case BX_LAPIC_ICR_LO: // handle full 64-bit write send_ipi(val32_hi, val32_lo); return 1; case BX_LAPIC_TPR: // handle reserved bits, only bits 0-7 are writeable if ((val32_lo & 0xffffff00) != 0) return 0; break; // use legacy write case BX_LAPIC_SPURIOUS_VECTOR: // handle reserved bits, only bits 0-8, 12 are writeable // we do not support directed EOI capability, so reserve bit 12 as well if ((val32_lo & 0xfffffe00) != 0) return 0; break; // use legacy write case BX_LAPIC_EOI: case BX_LAPIC_ESR: if (val32_lo != 0) return 0; break; // use legacy write case BX_LAPIC_LVT_TIMER: case BX_LAPIC_LVT_THERMAL: case BX_LAPIC_LVT_PERFMON: case BX_LAPIC_LVT_LINT0: case BX_LAPIC_LVT_LINT1: case BX_LAPIC_LVT_ERROR: case BX_LAPIC_TIMER_INITIAL_COUNT: case BX_LAPIC_TIMER_DIVIDE_CFG: break; // use legacy write default: BX_DEBUG(("write_x2apic: not supported apic register 0x%08x", index)); return 0; } write_aligned(index, val32_lo); return 1; } #endif void bx_local_apic_c::register_state(bx_param_c *parent) { unsigned i; char name[6]; bx_list_c *lapic = new bx_list_c(parent, "local_apic"); BXRS_HEX_PARAM_SIMPLE(lapic, base_addr); BXRS_HEX_PARAM_SIMPLE(lapic, apic_id); BXRS_HEX_PARAM_SIMPLE(lapic, mode); BXRS_HEX_PARAM_SIMPLE(lapic, spurious_vector); BXRS_PARAM_BOOL(lapic, software_enabled, software_enabled); BXRS_PARAM_BOOL(lapic, focus_disable, focus_disable); BXRS_HEX_PARAM_SIMPLE(lapic, task_priority); BXRS_HEX_PARAM_SIMPLE(lapic, ldr); BXRS_HEX_PARAM_SIMPLE(lapic, dest_format); bx_list_c *ISR = new bx_list_c(lapic, "isr"); bx_list_c *TMR = new bx_list_c(lapic, "tmr"); bx_list_c *IRR = new bx_list_c(lapic, "irr"); for (i=0; i= 6 if (cpu->bx_cpuid_support_xapic_extensions()) { BXRS_HEX_PARAM_SIMPLE(lapic, xapic_ext); bx_list_c *IER = new bx_list_c(lapic, "ier"); for (i=0; i= 2 BXRS_DEC_PARAM_SIMPLE(lapic, vmx_timer_handle); BXRS_HEX_PARAM_SIMPLE(lapic, vmx_preemption_timer_initial); BXRS_HEX_PARAM_SIMPLE(lapic, vmx_preemption_timer_fire); BXRS_HEX_PARAM_SIMPLE(lapic, vmx_preemption_timer_value); BXRS_HEX_PARAM_SIMPLE(lapic, vmx_preemption_timer_rate); BXRS_PARAM_BOOL(lapic, vmx_timer_active, vmx_timer_active); #endif } #endif /* if BX_SUPPORT_APIC */ bochs-2.6/cpu/fetchdecode_x87.h0000644000175000017500000006320612020641453016244 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fetchdecode_x87.h 11013 2012-02-01 12:07:53Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2005-2010 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_X87_FETCHDECODE_TABLES_H #define BX_X87_FETCHDECODE_TABLES_H // // Common FetchDecode Opcode Tables - x87 and 3dnow! // #if BX_SUPPORT_FPU /* ************************************************************************ */ /* FPU Opcodes */ // D8 (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FPGroupD8[8*2] = { /* /r form */ /* 0 */ { 0, BX_IA_FADD_ST0_STj }, /* 1 */ { 0, BX_IA_FMUL_ST0_STj }, /* 2 */ { 0, BX_IA_FCOM_STi }, /* 3 */ { 0, BX_IA_FCOMP_STi }, /* 4 */ { 0, BX_IA_FSUB_ST0_STj }, /* 5 */ { 0, BX_IA_FSUBR_ST0_STj }, /* 6 */ { 0, BX_IA_FDIV_ST0_STj }, /* 7 */ { 0, BX_IA_FDIVR_ST0_STj }, /* /m form */ /* 0 */ { 0, BX_IA_FADD_SINGLE_REAL }, /* 1 */ { 0, BX_IA_FMUL_SINGLE_REAL }, /* 2 */ { 0, BX_IA_FCOM_SINGLE_REAL }, /* 3 */ { 0, BX_IA_FCOMP_SINGLE_REAL }, /* 4 */ { 0, BX_IA_FSUB_SINGLE_REAL }, /* 5 */ { 0, BX_IA_FSUBR_SINGLE_REAL }, /* 6 */ { 0, BX_IA_FDIV_SINGLE_REAL }, /* 7 */ { 0, BX_IA_FDIVR_SINGLE_REAL } }; // D9 (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FloatingPointD9[64+8] = { /* /m form */ /* 0 */ { 0, BX_IA_FLD_SINGLE_REAL }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_FST_SINGLE_REAL }, /* 3 */ { 0, BX_IA_FSTP_SINGLE_REAL }, /* 4 */ { 0, BX_IA_FLDENV }, /* 5 */ { 0, BX_IA_FLDCW }, /* 6 */ { 0, BX_IA_FNSTENV }, /* 7 */ { 0, BX_IA_FNSTCW }, /* /r form */ /* D9 C0 */ { 0, BX_IA_FLD_STi }, /* D9 C1 */ { 0, BX_IA_FLD_STi }, /* D9 C2 */ { 0, BX_IA_FLD_STi }, /* D9 C3 */ { 0, BX_IA_FLD_STi }, /* D9 C4 */ { 0, BX_IA_FLD_STi }, /* D9 C5 */ { 0, BX_IA_FLD_STi }, /* D9 C6 */ { 0, BX_IA_FLD_STi }, /* D9 C7 */ { 0, BX_IA_FLD_STi }, /* D9 C8 */ { 0, BX_IA_FXCH_STi }, /* D9 C9 */ { 0, BX_IA_FXCH_STi }, /* D9 CA */ { 0, BX_IA_FXCH_STi }, /* D9 CB */ { 0, BX_IA_FXCH_STi }, /* D9 CC */ { 0, BX_IA_FXCH_STi }, /* D9 CD */ { 0, BX_IA_FXCH_STi }, /* D9 CE */ { 0, BX_IA_FXCH_STi }, /* D9 CF */ { 0, BX_IA_FXCH_STi }, /* D9 D0 */ { 0, BX_IA_FNOP }, /* D9 D1 */ { 0, BX_IA_ERROR }, /* D9 D2 */ { 0, BX_IA_ERROR }, /* D9 D3 */ { 0, BX_IA_ERROR }, /* D9 D4 */ { 0, BX_IA_ERROR }, /* D9 D5 */ { 0, BX_IA_ERROR }, /* D9 D6 */ { 0, BX_IA_ERROR }, /* D9 D7 */ { 0, BX_IA_ERROR }, /* D9 D8 */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 D9 */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 DA */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 DB */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 DC */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 DD */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 DE */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 DF */ { 0, BX_IA_FSTP_STi }, // undocumented /* D9 E0 */ { 0, BX_IA_FCHS }, /* D9 E1 */ { 0, BX_IA_FABS }, /* D9 E2 */ { 0, BX_IA_ERROR }, /* D9 E3 */ { 0, BX_IA_ERROR }, /* D9 E4 */ { 0, BX_IA_FTST }, /* D9 E5 */ { 0, BX_IA_FXAM }, /* D9 E6 */ { 0, BX_IA_ERROR }, /* D9 E7 */ { 0, BX_IA_ERROR }, /* D9 E8 */ { 0, BX_IA_FLD1 }, /* D9 E9 */ { 0, BX_IA_FLDL2T }, /* D9 EA */ { 0, BX_IA_FLDL2E }, /* D9 EB */ { 0, BX_IA_FLDPI }, /* D9 EC */ { 0, BX_IA_FLDLG2 }, /* D9 ED */ { 0, BX_IA_FLDLN2 }, /* D9 EE */ { 0, BX_IA_FLDZ }, /* D9 EF */ { 0, BX_IA_ERROR }, /* D9 F0 */ { 0, BX_IA_F2XM1 }, /* D9 F1 */ { 0, BX_IA_FYL2X }, /* D9 F2 */ { 0, BX_IA_FPTAN }, /* D9 F3 */ { 0, BX_IA_FPATAN }, /* D9 F4 */ { 0, BX_IA_FXTRACT }, /* D9 F5 */ { 0, BX_IA_FPREM1 }, /* D9 F6 */ { 0, BX_IA_FDECSTP }, /* D9 F7 */ { 0, BX_IA_FINCSTP }, /* D9 F8 */ { 0, BX_IA_FPREM }, /* D9 F9 */ { 0, BX_IA_FYL2XP1 }, /* D9 FA */ { 0, BX_IA_FSQRT }, /* D9 FB */ { 0, BX_IA_FSINCOS }, /* D9 FC */ { 0, BX_IA_FRNDINT }, /* D9 FD */ { 0, BX_IA_FSCALE }, /* D9 FE */ { 0, BX_IA_FSIN }, /* D9 FF */ { 0, BX_IA_FCOS } }; // DA (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FloatingPointDA[64+8] = { /* /m form */ /* 0 */ { 0, BX_IA_FIADD_DWORD_INTEGER }, /* 1 */ { 0, BX_IA_FIMUL_DWORD_INTEGER }, /* 2 */ { 0, BX_IA_FICOM_DWORD_INTEGER }, /* 3 */ { 0, BX_IA_FICOMP_DWORD_INTEGER }, /* 4 */ { 0, BX_IA_FISUB_DWORD_INTEGER }, /* 5 */ { 0, BX_IA_FISUBR_DWORD_INTEGER }, /* 6 */ { 0, BX_IA_FIDIV_DWORD_INTEGER }, /* 7 */ { 0, BX_IA_FIDIVR_DWORD_INTEGER }, /* /r form */ /* DA C0 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C1 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C2 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C3 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C4 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C5 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C6 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C7 */ { 0, BX_IA_FCMOVB_ST0_STj }, /* DA C8 */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA C9 */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA CA */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA CB */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA CC */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA CD */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA CE */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA CF */ { 0, BX_IA_FCMOVE_ST0_STj }, /* DA D0 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D1 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D2 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D3 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D4 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D5 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D6 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D7 */ { 0, BX_IA_FCMOVBE_ST0_STj }, /* DA D8 */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA D9 */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA DA */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA DB */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA DC */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA DD */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA DE */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA DF */ { 0, BX_IA_FCMOVU_ST0_STj }, /* DA E0 */ { 0, BX_IA_ERROR }, /* DA E1 */ { 0, BX_IA_ERROR }, /* DA E2 */ { 0, BX_IA_ERROR }, /* DA E3 */ { 0, BX_IA_ERROR }, /* DA E4 */ { 0, BX_IA_ERROR }, /* DA E5 */ { 0, BX_IA_ERROR }, /* DA E6 */ { 0, BX_IA_ERROR }, /* DA E7 */ { 0, BX_IA_ERROR }, /* DA E8 */ { 0, BX_IA_ERROR }, /* DA E9 */ { 0, BX_IA_FUCOMPP }, /* DA EA */ { 0, BX_IA_ERROR }, /* DA EB */ { 0, BX_IA_ERROR }, /* DA EC */ { 0, BX_IA_ERROR }, /* DA ED */ { 0, BX_IA_ERROR }, /* DA EE */ { 0, BX_IA_ERROR }, /* DA EF */ { 0, BX_IA_ERROR }, /* DA F0 */ { 0, BX_IA_ERROR }, /* DA F1 */ { 0, BX_IA_ERROR }, /* DA F2 */ { 0, BX_IA_ERROR }, /* DA F3 */ { 0, BX_IA_ERROR }, /* DA F4 */ { 0, BX_IA_ERROR }, /* DA F5 */ { 0, BX_IA_ERROR }, /* DA F6 */ { 0, BX_IA_ERROR }, /* DA F7 */ { 0, BX_IA_ERROR }, /* DA F8 */ { 0, BX_IA_ERROR }, /* DA F9 */ { 0, BX_IA_ERROR }, /* DA FA */ { 0, BX_IA_ERROR }, /* DA FB */ { 0, BX_IA_ERROR }, /* DA FC */ { 0, BX_IA_ERROR }, /* DA FD */ { 0, BX_IA_ERROR }, /* DA FE */ { 0, BX_IA_ERROR }, /* DA FF */ { 0, BX_IA_ERROR } }; // DB (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FloatingPointDB[64+8] = { /* /m form */ /* 0 */ { 0, BX_IA_FILD_DWORD_INTEGER }, /* 1 */ { 0, BX_IA_FISTTP32 }, /* 2 */ { 0, BX_IA_FIST_DWORD_INTEGER }, /* 3 */ { 0, BX_IA_FISTP_DWORD_INTEGER }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_FLD_EXTENDED_REAL }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_FSTP_EXTENDED_REAL }, /* /r form */ /* DB C0 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C1 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C2 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C3 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C4 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C5 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C6 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C7 */ { 0, BX_IA_FCMOVNB_ST0_STj }, /* DB C8 */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB C9 */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB CA */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB CB */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB CC */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB CD */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB CE */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB CF */ { 0, BX_IA_FCMOVNE_ST0_STj }, /* DB D0 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D1 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D2 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D3 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D4 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D5 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D6 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D7 */ { 0, BX_IA_FCMOVNBE_ST0_STj }, /* DB D8 */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB D9 */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB DA */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB DB */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB DC */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB DD */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB DE */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB DF */ { 0, BX_IA_FCMOVNU_ST0_STj }, /* DB E0 */ { 0, BX_IA_FPLEGACY }, // feni (287 only) /* DB E1 */ { 0, BX_IA_FPLEGACY }, // fdisi (287 only) /* DB E2 */ { 0, BX_IA_FNCLEX }, /* DB E3 */ { 0, BX_IA_FNINIT }, /* DB E4 */ { 0, BX_IA_FPLEGACY }, // fsetpm (287 only) /* DB E5 */ { 0, BX_IA_ERROR }, /* DB E6 */ { 0, BX_IA_ERROR }, /* DB E7 */ { 0, BX_IA_ERROR }, /* DB E8 */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB E9 */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB EA */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB EB */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB EC */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB ED */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB EE */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB EF */ { 0, BX_IA_FUCOMI_ST0_STj }, /* DB F0 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F1 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F2 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F3 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F4 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F5 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F6 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F7 */ { 0, BX_IA_FCOMI_ST0_STj }, /* DB F8 */ { 0, BX_IA_ERROR }, /* DB F9 */ { 0, BX_IA_ERROR }, /* DB FA */ { 0, BX_IA_ERROR }, /* DB FB */ { 0, BX_IA_ERROR }, /* DB FC */ { 0, BX_IA_ERROR }, /* DB FD */ { 0, BX_IA_ERROR }, /* DB FE */ { 0, BX_IA_ERROR }, /* DB FF */ { 0, BX_IA_ERROR } }; // DC (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FPGroupDC[8*2] = { /* /r form */ /* 0 */ { 0, BX_IA_FADD_STi_ST0 }, /* 1 */ { 0, BX_IA_FMUL_STi_ST0 }, /* 2 */ { 0, BX_IA_FCOM_STi }, // undocumented /* 3 */ { 0, BX_IA_FCOMP_STi }, // undocumented /* 4 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* 5 */ { 0, BX_IA_FSUB_STi_ST0 }, /* 6 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* 7 */ { 0, BX_IA_FDIV_STi_ST0 }, /* /m form */ /* 0 */ { 0, BX_IA_FADD_DOUBLE_REAL }, /* 1 */ { 0, BX_IA_FMUL_DOUBLE_REAL }, /* 2 */ { 0, BX_IA_FCOM_DOUBLE_REAL }, /* 3 */ { 0, BX_IA_FCOMP_DOUBLE_REAL }, /* 4 */ { 0, BX_IA_FSUB_DOUBLE_REAL }, /* 5 */ { 0, BX_IA_FSUBR_DOUBLE_REAL }, /* 6 */ { 0, BX_IA_FDIV_DOUBLE_REAL }, /* 7 */ { 0, BX_IA_FDIVR_DOUBLE_REAL } }; // DD (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FPGroupDD[8*2] = { /* /r form */ /* 0 */ { 0, BX_IA_FFREE_STi }, /* 1 */ { 0, BX_IA_FXCH_STi }, // undocumented /* 2 */ { 0, BX_IA_FST_STi }, /* 3 */ { 0, BX_IA_FSTP_STi }, /* 4 */ { 0, BX_IA_FUCOM_STi }, /* 5 */ { 0, BX_IA_FUCOMP_STi }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR }, /* /m form */ /* 0 */ { 0, BX_IA_FLD_DOUBLE_REAL }, /* 1 */ { 0, BX_IA_FISTTP64 }, /* 2 */ { 0, BX_IA_FST_DOUBLE_REAL }, /* 3 */ { 0, BX_IA_FSTP_DOUBLE_REAL }, /* 4 */ { 0, BX_IA_FRSTOR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_FNSAVE }, /* 7 */ { 0, BX_IA_FNSTSW } }; // DE (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FloatingPointDE[64+8] = { /* /m form */ /* 0 */ { 0, BX_IA_FIADD_WORD_INTEGER }, /* 1 */ { 0, BX_IA_FIMUL_WORD_INTEGER }, /* 2 */ { 0, BX_IA_FICOM_WORD_INTEGER }, /* 3 */ { 0, BX_IA_FICOMP_WORD_INTEGER }, /* 4 */ { 0, BX_IA_FISUB_WORD_INTEGER }, /* 5 */ { 0, BX_IA_FISUBR_WORD_INTEGER }, /* 6 */ { 0, BX_IA_FIDIV_WORD_INTEGER }, /* 7 */ { 0, BX_IA_FIDIVR_WORD_INTEGER }, /* /r form */ // all instructions pop FPU stack /* DE C0 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C1 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C2 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C3 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C4 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C5 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C6 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C7 */ { 0, BX_IA_FADD_STi_ST0 }, /* DE C8 */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE C9 */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE CA */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE CB */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE CC */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE CD */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE CE */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE CF */ { 0, BX_IA_FMUL_STi_ST0 }, /* DE D0 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D1 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D2 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D3 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D4 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D5 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D6 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D7 */ { 0, BX_IA_FCOMP_STi }, // undocumented, special FPSTACK pop case /* DE D8 */ { 0, BX_IA_ERROR }, /* DE D9 */ { 0, BX_IA_FCOMPP }, /* DE DA */ { 0, BX_IA_ERROR }, /* DE DB */ { 0, BX_IA_ERROR }, /* DE DC */ { 0, BX_IA_ERROR }, /* DE DD */ { 0, BX_IA_ERROR }, /* DE DE */ { 0, BX_IA_ERROR }, /* DE DF */ { 0, BX_IA_ERROR }, /* DE E0 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E1 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E2 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E3 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E4 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E5 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E6 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E7 */ { 0, BX_IA_FSUBR_STi_ST0 }, /* DE E8 */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE E9 */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE EA */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE EB */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE EC */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE ED */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE EE */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE EF */ { 0, BX_IA_FSUB_STi_ST0 }, /* DE F0 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F1 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F2 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F3 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F4 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F5 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F6 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F7 */ { 0, BX_IA_FDIVR_STi_ST0 }, /* DE F8 */ { 0, BX_IA_FDIV_STi_ST0 }, /* DE F9 */ { 0, BX_IA_FDIV_STi_ST0 }, /* DE FA */ { 0, BX_IA_FDIV_STi_ST0 }, /* DE FB */ { 0, BX_IA_FDIV_STi_ST0 }, /* DE FC */ { 0, BX_IA_FDIV_STi_ST0 }, /* DE FD */ { 0, BX_IA_FDIV_STi_ST0 }, /* DE FE */ { 0, BX_IA_FDIV_STi_ST0 }, /* DE FF */ { 0, BX_IA_FDIV_STi_ST0 } }; // DF (modrm is outside 00h - BFh) static const BxOpcodeInfo_t BxOpcodeInfo_FloatingPointDF[64+8] = { /* /m form */ /* 0 */ { 0, BX_IA_FILD_WORD_INTEGER }, /* 1 */ { 0, BX_IA_FISTTP16 }, /* 2 */ { 0, BX_IA_FIST_WORD_INTEGER }, /* 3 */ { 0, BX_IA_FISTP_WORD_INTEGER }, /* 4 */ { 0, BX_IA_FBLD_PACKED_BCD }, /* 5 */ { 0, BX_IA_FILD_QWORD_INTEGER }, /* 6 */ { 0, BX_IA_FBSTP_PACKED_BCD }, /* 7 */ { 0, BX_IA_FISTP_QWORD_INTEGER }, /* /r form */ /* DF C0 */ { 0, BX_IA_FFREEP_STi }, // 287+ compatibility opcode /* DF C1 */ { 0, BX_IA_FFREEP_STi }, /* DF C2 */ { 0, BX_IA_FFREEP_STi }, /* DF C3 */ { 0, BX_IA_FFREEP_STi }, /* DF C4 */ { 0, BX_IA_FFREEP_STi }, /* DF C5 */ { 0, BX_IA_FFREEP_STi }, /* DF C6 */ { 0, BX_IA_FFREEP_STi }, /* DF C7 */ { 0, BX_IA_FFREEP_STi }, /* DF C8 */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF C9 */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF CA */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF CB */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF CC */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF CD */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF CE */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF CF */ { 0, BX_IA_FXCH_STi }, // undocumented /* DF D0 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D1 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D2 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D3 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D4 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D5 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D6 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D7 */ { 0, BX_IA_FSTP_STi }, // undocumented, special FPSTACK pop case /* DF D8 */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF D9 */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF DA */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF DB */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF DC */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF DD */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF DE */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF DF */ { 0, BX_IA_FSTP_STi }, // undocumented /* DF E0 */ { 0, BX_IA_FNSTSW_AX }, /* DF E1 */ { 0, BX_IA_ERROR }, /* DF E2 */ { 0, BX_IA_ERROR }, /* DF E3 */ { 0, BX_IA_ERROR }, /* DF E4 */ { 0, BX_IA_ERROR }, /* DF E5 */ { 0, BX_IA_ERROR }, /* DF E6 */ { 0, BX_IA_ERROR }, /* DF E7 */ { 0, BX_IA_ERROR }, /* DF E8 */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF E9 */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF EA */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF EB */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF EC */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF ED */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF EE */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF EF */ { 0, BX_IA_FUCOMIP_ST0_STj }, /* DF F0 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F1 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F2 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F3 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F4 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F5 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F6 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F7 */ { 0, BX_IA_FCOMIP_ST0_STj }, /* DF F8 */ { 0, BX_IA_ERROR }, /* DF F9 */ { 0, BX_IA_ERROR }, /* DF FA */ { 0, BX_IA_ERROR }, /* DF FB */ { 0, BX_IA_ERROR }, /* DF FC */ { 0, BX_IA_ERROR }, /* DF FD */ { 0, BX_IA_ERROR }, /* DF FE */ { 0, BX_IA_ERROR }, /* DF FF */ { 0, BX_IA_ERROR }, }; #endif /* ************************************************************************ */ /* 3DNow! Opcodes */ #if BX_SUPPORT_3DNOW static Bit16u Bx3DNowOpcode[256] = { // 256 entries for 3DNow opcodes, by suffix /* 00 */ BX_IA_ERROR, /* 01 */ BX_IA_ERROR, /* 02 */ BX_IA_ERROR, /* 03 */ BX_IA_ERROR, /* 04 */ BX_IA_ERROR, /* 05 */ BX_IA_ERROR, /* 06 */ BX_IA_ERROR, /* 07 */ BX_IA_ERROR, /* 08 */ BX_IA_ERROR, /* 09 */ BX_IA_ERROR, /* 0A */ BX_IA_ERROR, /* 0B */ BX_IA_ERROR, /* 0C */ BX_IA_PI2FW_PqQq, /* 0D */ BX_IA_PI2FD_PqQq, /* 0E */ BX_IA_ERROR, /* 0F */ BX_IA_ERROR, /* 10 */ BX_IA_ERROR, /* 11 */ BX_IA_ERROR, /* 12 */ BX_IA_ERROR, /* 13 */ BX_IA_ERROR, /* 14 */ BX_IA_ERROR, /* 15 */ BX_IA_ERROR, /* 16 */ BX_IA_ERROR, /* 17 */ BX_IA_ERROR, /* 18 */ BX_IA_ERROR, /* 19 */ BX_IA_ERROR, /* 1A */ BX_IA_ERROR, /* 1B */ BX_IA_ERROR, /* 1C */ BX_IA_PF2IW_PqQq, /* 1D */ BX_IA_PF2ID_PqQq, /* 1E */ BX_IA_ERROR, /* 1F */ BX_IA_ERROR, /* 20 */ BX_IA_ERROR, /* 21 */ BX_IA_ERROR, /* 22 */ BX_IA_ERROR, /* 23 */ BX_IA_ERROR, /* 24 */ BX_IA_ERROR, /* 25 */ BX_IA_ERROR, /* 26 */ BX_IA_ERROR, /* 27 */ BX_IA_ERROR, /* 28 */ BX_IA_ERROR, /* 29 */ BX_IA_ERROR, /* 2A */ BX_IA_ERROR, /* 2B */ BX_IA_ERROR, /* 2C */ BX_IA_ERROR, /* 2D */ BX_IA_ERROR, /* 2E */ BX_IA_ERROR, /* 2F */ BX_IA_ERROR, /* 30 */ BX_IA_ERROR, /* 31 */ BX_IA_ERROR, /* 32 */ BX_IA_ERROR, /* 33 */ BX_IA_ERROR, /* 34 */ BX_IA_ERROR, /* 35 */ BX_IA_ERROR, /* 36 */ BX_IA_ERROR, /* 37 */ BX_IA_ERROR, /* 38 */ BX_IA_ERROR, /* 39 */ BX_IA_ERROR, /* 3A */ BX_IA_ERROR, /* 3B */ BX_IA_ERROR, /* 3C */ BX_IA_ERROR, /* 3D */ BX_IA_ERROR, /* 3E */ BX_IA_ERROR, /* 3F */ BX_IA_ERROR, /* 40 */ BX_IA_ERROR, /* 41 */ BX_IA_ERROR, /* 42 */ BX_IA_ERROR, /* 43 */ BX_IA_ERROR, /* 44 */ BX_IA_ERROR, /* 45 */ BX_IA_ERROR, /* 46 */ BX_IA_ERROR, /* 47 */ BX_IA_ERROR, /* 48 */ BX_IA_ERROR, /* 49 */ BX_IA_ERROR, /* 4A */ BX_IA_ERROR, /* 4B */ BX_IA_ERROR, /* 4C */ BX_IA_ERROR, /* 4D */ BX_IA_ERROR, /* 4E */ BX_IA_ERROR, /* 4F */ BX_IA_ERROR, /* 50 */ BX_IA_ERROR, /* 51 */ BX_IA_ERROR, /* 52 */ BX_IA_ERROR, /* 53 */ BX_IA_ERROR, /* 54 */ BX_IA_ERROR, /* 55 */ BX_IA_ERROR, /* 56 */ BX_IA_ERROR, /* 57 */ BX_IA_ERROR, /* 58 */ BX_IA_ERROR, /* 59 */ BX_IA_ERROR, /* 5A */ BX_IA_ERROR, /* 5B */ BX_IA_ERROR, /* 5C */ BX_IA_ERROR, /* 5D */ BX_IA_ERROR, /* 5E */ BX_IA_ERROR, /* 5F */ BX_IA_ERROR, /* 60 */ BX_IA_ERROR, /* 61 */ BX_IA_ERROR, /* 62 */ BX_IA_ERROR, /* 63 */ BX_IA_ERROR, /* 64 */ BX_IA_ERROR, /* 65 */ BX_IA_ERROR, /* 66 */ BX_IA_ERROR, /* 67 */ BX_IA_ERROR, /* 68 */ BX_IA_ERROR, /* 69 */ BX_IA_ERROR, /* 6A */ BX_IA_ERROR, /* 6B */ BX_IA_ERROR, /* 6C */ BX_IA_ERROR, /* 6D */ BX_IA_ERROR, /* 6E */ BX_IA_ERROR, /* 6F */ BX_IA_ERROR, /* 70 */ BX_IA_ERROR, /* 71 */ BX_IA_ERROR, /* 72 */ BX_IA_ERROR, /* 73 */ BX_IA_ERROR, /* 74 */ BX_IA_ERROR, /* 75 */ BX_IA_ERROR, /* 76 */ BX_IA_ERROR, /* 77 */ BX_IA_ERROR, /* 78 */ BX_IA_ERROR, /* 79 */ BX_IA_ERROR, /* 7A */ BX_IA_ERROR, /* 7B */ BX_IA_ERROR, /* 7C */ BX_IA_ERROR, /* 7D */ BX_IA_ERROR, /* 7E */ BX_IA_ERROR, /* 7F */ BX_IA_ERROR, /* 80 */ BX_IA_ERROR, /* 81 */ BX_IA_ERROR, /* 82 */ BX_IA_ERROR, /* 83 */ BX_IA_ERROR, /* 84 */ BX_IA_ERROR, /* 85 */ BX_IA_ERROR, /* 86 */ BX_IA_ERROR, /* 87 */ BX_IA_ERROR, /* 88 */ BX_IA_ERROR, /* 89 */ BX_IA_ERROR, /* 8A */ BX_IA_PFNACC_PqQq, /* 8B */ BX_IA_ERROR, /* 8C */ BX_IA_ERROR, /* 8D */ BX_IA_ERROR, /* 8E */ BX_IA_PFPNACC_PqQq, /* 8F */ BX_IA_ERROR, /* 90 */ BX_IA_PFCMPGE_PqQq, /* 91 */ BX_IA_ERROR, /* 92 */ BX_IA_ERROR, /* 93 */ BX_IA_ERROR, /* 94 */ BX_IA_PFMIN_PqQq, /* 95 */ BX_IA_ERROR, /* 96 */ BX_IA_PFRCP_PqQq, /* 97 */ BX_IA_PFRSQRT_PqQq, /* 98 */ BX_IA_ERROR, /* 99 */ BX_IA_ERROR, /* 9A */ BX_IA_PFSUB_PqQq, /* 9B */ BX_IA_ERROR, /* 9C */ BX_IA_ERROR, /* 9D */ BX_IA_ERROR, /* 9E */ BX_IA_PFADD_PqQq, /* 9F */ BX_IA_ERROR, /* A0 */ BX_IA_PFCMPGT_PqQq, /* A1 */ BX_IA_ERROR, /* A2 */ BX_IA_ERROR, /* A3 */ BX_IA_ERROR, /* A4 */ BX_IA_PFMAX_PqQq, /* A5 */ BX_IA_ERROR, /* A6 */ BX_IA_PFRCPIT1_PqQq, /* A7 */ BX_IA_PFRSQIT1_PqQq, /* A8 */ BX_IA_ERROR, /* A9 */ BX_IA_ERROR, /* AA */ BX_IA_PFSUBR_PqQq, /* AB */ BX_IA_ERROR, /* AC */ BX_IA_ERROR, /* AD */ BX_IA_ERROR, /* AE */ BX_IA_PFACC_PqQq, /* AF */ BX_IA_ERROR, /* B0 */ BX_IA_PFCMPEQ_PqQq, /* B1 */ BX_IA_ERROR, /* B2 */ BX_IA_ERROR, /* B3 */ BX_IA_ERROR, /* B4 */ BX_IA_PFMUL_PqQq, /* B5 */ BX_IA_ERROR, /* B6 */ BX_IA_PFRCPIT2_PqQq, /* B7 */ BX_IA_PMULHRW_PqQq, /* B8 */ BX_IA_ERROR, /* B9 */ BX_IA_ERROR, /* BA */ BX_IA_ERROR, /* BB */ BX_IA_PSWAPD_PqQq, /* BC */ BX_IA_ERROR, /* BD */ BX_IA_ERROR, /* BE */ BX_IA_ERROR, /* BF */ BX_IA_PAVGB_PqQq, /* C0 */ BX_IA_ERROR, /* C1 */ BX_IA_ERROR, /* C2 */ BX_IA_ERROR, /* C3 */ BX_IA_ERROR, /* C4 */ BX_IA_ERROR, /* C5 */ BX_IA_ERROR, /* C6 */ BX_IA_ERROR, /* C7 */ BX_IA_ERROR, /* C8 */ BX_IA_ERROR, /* C9 */ BX_IA_ERROR, /* CA */ BX_IA_ERROR, /* CB */ BX_IA_ERROR, /* CC */ BX_IA_ERROR, /* CD */ BX_IA_ERROR, /* CE */ BX_IA_ERROR, /* CF */ BX_IA_ERROR, /* D0 */ BX_IA_ERROR, /* D1 */ BX_IA_ERROR, /* D2 */ BX_IA_ERROR, /* D3 */ BX_IA_ERROR, /* D4 */ BX_IA_ERROR, /* D5 */ BX_IA_ERROR, /* D6 */ BX_IA_ERROR, /* D7 */ BX_IA_ERROR, /* D8 */ BX_IA_ERROR, /* D9 */ BX_IA_ERROR, /* DA */ BX_IA_ERROR, /* DB */ BX_IA_ERROR, /* DC */ BX_IA_ERROR, /* DD */ BX_IA_ERROR, /* DE */ BX_IA_ERROR, /* DF */ BX_IA_ERROR, /* E0 */ BX_IA_ERROR, /* E1 */ BX_IA_ERROR, /* E2 */ BX_IA_ERROR, /* E3 */ BX_IA_ERROR, /* E4 */ BX_IA_ERROR, /* E5 */ BX_IA_ERROR, /* E6 */ BX_IA_ERROR, /* E7 */ BX_IA_ERROR, /* E8 */ BX_IA_ERROR, /* E9 */ BX_IA_ERROR, /* EA */ BX_IA_ERROR, /* EB */ BX_IA_ERROR, /* EC */ BX_IA_ERROR, /* ED */ BX_IA_ERROR, /* EE */ BX_IA_ERROR, /* EF */ BX_IA_ERROR, /* F0 */ BX_IA_ERROR, /* F1 */ BX_IA_ERROR, /* F2 */ BX_IA_ERROR, /* F3 */ BX_IA_ERROR, /* F4 */ BX_IA_ERROR, /* F5 */ BX_IA_ERROR, /* F6 */ BX_IA_ERROR, /* F7 */ BX_IA_ERROR, /* F8 */ BX_IA_ERROR, /* F9 */ BX_IA_ERROR, /* FA */ BX_IA_ERROR, /* FB */ BX_IA_ERROR, /* FC */ BX_IA_ERROR, /* FD */ BX_IA_ERROR, /* FE */ BX_IA_ERROR, /* FF */ BX_IA_ERROR }; #endif #endif // BX_X87_FETCHDECODE_TABLES_H bochs-2.6/cpu/access.cc0000644000175000017500000003743012020641453014700 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: access.cc 11103 2012-03-20 18:26:04Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2005-2010 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR bx_address bx_asize_mask[] = { 0xffff, // as16 (asize = '00) 0xffffffff, // as32 (asize = '01) #if BX_SUPPORT_X86_64 BX_CONST64(0xffffffffffffffff), // as64 (asize = '10) BX_CONST64(0xffffffffffffffff) // as64 (asize = '11) #endif }; bx_bool BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned length) { Bit32u upper_limit; if (seg->cache.valid==0) { BX_DEBUG(("write_virtual_checks(): segment descriptor not valid")); return 0; } if (seg->cache.p == 0) { /* not present */ BX_ERROR(("write_virtual_checks(): segment not present")); return 0; } length--; switch (seg->cache.type) { case 0: case 1: // read only case 4: case 5: // read only, expand down case 8: case 9: // execute only case 10: case 11: // execute/read case 12: case 13: // execute only, conforming case 14: case 15: // execute/read-only, conforming BX_ERROR(("write_virtual_checks(): no write access to seg")); return 0; case 2: case 3: /* read/write */ if (offset > (seg->cache.u.segment.limit_scaled - length) || length > seg->cache.u.segment.limit_scaled) { BX_ERROR(("write_virtual_checks(): write beyond limit, r/w")); return 0; } if (seg->cache.u.segment.limit_scaled >= 31) { // Mark cache as being OK type for succeeding read/writes. The limit // checks still needs to be done though, but is more simple. We // could probably also optimize that out with a flag for the case // when limit is the maximum 32bit value. Limit should accomodate // at least a dword, since we subtract from it in the simple // limit check in other functions, and we don't want the value to roll. // Only normal segments (not expand down) are handled this way. seg->cache.valid |= SegAccessROK | SegAccessWOK; } break; case 6: case 7: /* read/write, expand down */ if (seg->cache.u.segment.d_b) upper_limit = 0xffffffff; else upper_limit = 0x0000ffff; if (offset <= seg->cache.u.segment.limit_scaled || offset > upper_limit || (upper_limit - offset) < length) { BX_ERROR(("write_virtual_checks(): write beyond limit, r/w ED")); return 0; } break; default: BX_PANIC(("write_virtual_checks(): unknown descriptor type=%d", seg->cache.type)); } return 1; } bx_bool BX_CPP_AttrRegparmN(3) BX_CPU_C::read_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned length) { Bit32u upper_limit; if (seg->cache.valid==0) { BX_DEBUG(("read_virtual_checks(): segment descriptor not valid")); return 0; } if (seg->cache.p == 0) { /* not present */ BX_ERROR(("read_virtual_checks(): segment not present")); return 0; } length--; switch (seg->cache.type) { case 0: case 1: /* read only */ case 2: case 3: /* read/write */ case 10: case 11: /* execute/read */ case 14: case 15: /* execute/read-only, conforming */ if (offset > (seg->cache.u.segment.limit_scaled - length) || length > seg->cache.u.segment.limit_scaled) { BX_ERROR(("read_virtual_checks(): read beyond limit")); return 0; } if (seg->cache.u.segment.limit_scaled >= 31) { // Mark cache as being OK type for succeeding reads. See notes for // write checks; similar code. seg->cache.valid |= SegAccessROK; } break; case 4: case 5: /* read only, expand down */ case 6: case 7: /* read/write, expand down */ if (seg->cache.u.segment.d_b) upper_limit = 0xffffffff; else upper_limit = 0x0000ffff; if (offset <= seg->cache.u.segment.limit_scaled || offset > upper_limit || (upper_limit - offset) < length) { BX_ERROR(("read_virtual_checks(): read beyond limit ED")); return 0; } break; case 8: case 9: /* execute only */ case 12: case 13: /* execute only, conforming */ /* can't read or write an execute-only segment */ BX_ERROR(("read_virtual_checks(): execute only")); return 0; default: BX_PANIC(("read_virtual_checks(): unknown descriptor type=%d", seg->cache.type)); } return 1; } bx_bool BX_CPP_AttrRegparmN(3) BX_CPU_C::execute_virtual_checks(bx_segment_reg_t *seg, Bit32u offset, unsigned length) { Bit32u upper_limit; if (seg->cache.valid==0) { BX_DEBUG(("execute_virtual_checks(): segment descriptor not valid")); return 0; } if (seg->cache.p == 0) { /* not present */ BX_ERROR(("execute_virtual_checks(): segment not present")); return 0; } length--; switch (seg->cache.type) { case 0: case 1: /* read only */ case 2: case 3: /* read/write */ case 10: case 11: /* execute/read */ case 14: case 15: /* execute/read-only, conforming */ if (offset > (seg->cache.u.segment.limit_scaled - length) || length > seg->cache.u.segment.limit_scaled) { BX_ERROR(("execute_virtual_checks(): read beyond limit")); return 0; } if (seg->cache.u.segment.limit_scaled >= 31) { // Mark cache as being OK type for succeeding reads. See notes for // write checks; similar code. seg->cache.valid |= SegAccessROK; } break; case 8: case 9: /* execute only */ case 12: case 13: /* execute only, conforming */ if (offset > (seg->cache.u.segment.limit_scaled - length) || length > seg->cache.u.segment.limit_scaled) { BX_ERROR(("execute_virtual_checks(): read beyond limit execute only")); return 0; } break; case 4: case 5: /* read only, expand down */ case 6: case 7: /* read/write, expand down */ if (seg->cache.u.segment.d_b) upper_limit = 0xffffffff; else upper_limit = 0x0000ffff; if (offset <= seg->cache.u.segment.limit_scaled || offset > upper_limit || (upper_limit - offset) < length) { BX_ERROR(("execute_virtual_checks(): read beyond limit ED")); return 0; } break; default: BX_PANIC(("execute_virtual_checks(): unknown descriptor type=%d", seg->cache.type)); } return 1; } const char *BX_CPU_C::strseg(bx_segment_reg_t *seg) { if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]) return("ES"); else if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]) return("CS"); else if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]) return("SS"); else if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]) return("DS"); else if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]) return("FS"); else if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS]) return("GS"); else { BX_PANIC(("undefined segment passed to strseg()!")); return("??"); } } int BX_CPU_C::int_number(unsigned s) { if (s == BX_SEG_REG_SS) return BX_SS_EXCEPTION; else return BX_GP_EXCEPTION; } Bit8u BX_CPP_AttrRegparmN(1) BX_CPU_C::system_read_byte(bx_address laddr) { Bit8u data; unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); bx_address lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); data = *hostAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 1, 0, BX_READ, (Bit8u*) &data); return data; } #if BX_SUPPORT_X86_64 if (! IsCanonical(laddr)) { BX_ERROR(("system_read_byte(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif access_read_linear(laddr, 1, 0, BX_READ, (void *) &data); return data; } Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::system_read_word(bx_address laddr) { Bit16u data; unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); bx_address lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); ReadHostWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 2, 0, BX_READ, (Bit8u*) &data); return data; } #if BX_SUPPORT_X86_64 if (! IsCanonical(laddr) || ! IsCanonical(laddr+1)) { BX_ERROR(("system_read_word(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif access_read_linear(laddr, 2, 0, BX_READ, (void *) &data); return data; } Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::system_read_dword(bx_address laddr) { Bit32u data; unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); bx_address lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); ReadHostDWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 4, 0, BX_READ, (Bit8u*) &data); return data; } #if BX_SUPPORT_X86_64 if (! IsCanonical(laddr) || ! IsCanonical(laddr+3)) { BX_ERROR(("system_read_dword(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif access_read_linear(laddr, 4, 0, BX_READ, (void *) &data); return data; } Bit64u BX_CPP_AttrRegparmN(1) BX_CPU_C::system_read_qword(bx_address laddr) { Bit64u data; unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); bx_address lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); ReadHostQWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 8, 0, BX_READ, (Bit8u*) &data); return data; } #if BX_SUPPORT_X86_64 if (! IsCanonical(laddr) || ! IsCanonical(laddr+7)) { BX_ERROR(("system_read_qword(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif access_read_linear(laddr, 8, 0, BX_READ, (void *) &data); return data; } void BX_CPP_AttrRegparmN(2) BX_CPU_C::system_write_byte(bx_address laddr, Bit8u data) { unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & 0x2)) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 1, 0, BX_WRITE, (Bit8u*) &data); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 1); *hostAddr = data; return; } } #if BX_SUPPORT_X86_64 if (! IsCanonical(laddr)) { BX_ERROR(("system_write_byte(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif access_write_linear(laddr, 1, 0, (void *) &data); } void BX_CPP_AttrRegparmN(2) BX_CPU_C::system_write_word(bx_address laddr, Bit16u data) { unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & 0x2)) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 2, 0, BX_WRITE, (Bit8u*) &data); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostAddr, data); return; } } #if BX_SUPPORT_X86_64 if (! IsCanonical(laddr) || ! IsCanonical(laddr+1)) { BX_ERROR(("system_write_word(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif access_write_linear(laddr, 2, 0, (void *) &data); } void BX_CPP_AttrRegparmN(2) BX_CPU_C::system_write_dword(bx_address laddr, Bit32u data) { unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & 0x2)) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 4, 0, BX_WRITE, (Bit8u*) &data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostAddr, data); return; } } #if BX_SUPPORT_X86_64 if (! IsCanonical(laddr) || ! IsCanonical(laddr+3)) { BX_ERROR(("system_write_dword(): canonical failure")); exception(BX_GP_EXCEPTION, 0); } #endif access_write_linear(laddr, 4, 0, (void *) &data); } Bit8u* BX_CPP_AttrRegparmN(2) BX_CPU_C::v2h_read_byte(bx_address laddr, bx_bool user) { unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); bx_address lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & user)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); return hostAddr; } } return 0; } Bit8u* BX_CPP_AttrRegparmN(2) BX_CPU_C::v2h_write_byte(bx_address laddr, bx_bool user) { unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); bx_address lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | user))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(tlbEntry->ppf); return hostAddr; } } return 0; } bochs-2.6/cpu/svm.cc0000644000175000017500000011402212020641453014235 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: svm.cc 11221 2012-06-18 11:41:26Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_SVM // for debugging and save/restore static const char *svm_segname[] = { "ES", "CS", "SS", "DS", "FS", "GS", "GDTR", "LDTR", "IDTR", "TR" }; // When loading segment bases from the VMCB or the host save area // (on VMRUN or #VMEXIT), segment bases are canonicalized (i.e. // sign-extended from the highest implemented address bit to bit 63) BX_CPP_INLINE Bit64u CanonicalizeAddress(Bit64u laddr) { if (laddr & BX_CONST64(0x0000800000000000)) { return laddr | BX_CONST64(0xffff000000000000); } else { return laddr & BX_CONST64(0x0000ffffffffffff); } } BX_CPP_INLINE Bit8u BX_CPU_C::vmcb_read8(unsigned offset) { Bit8u val_8; bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit8u *hostAddr = (Bit8u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); val_8 = *hostAddr; } else { access_read_physical(pAddr, 1, (Bit8u*)(&val_8)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&val_8)); return val_8; } BX_CPP_INLINE Bit16u BX_CPU_C::vmcb_read16(unsigned offset) { Bit16u val_16; bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit16u *hostAddr = (Bit16u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); ReadHostWordFromLittleEndian(hostAddr, val_16); } else { access_read_physical(pAddr, 2, (Bit8u*)(&val_16)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 2, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&val_16)); return val_16; } BX_CPP_INLINE Bit32u BX_CPU_C::vmcb_read32(unsigned offset) { Bit32u val_32; bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit32u *hostAddr = (Bit32u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); ReadHostDWordFromLittleEndian(hostAddr, val_32); } else { access_read_physical(pAddr, 4, (Bit8u*)(&val_32)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&val_32)); return val_32; } BX_CPP_INLINE Bit64u BX_CPU_C::vmcb_read64(unsigned offset) { Bit64u val_64; bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit64u *hostAddr = (Bit64u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); ReadHostQWordFromLittleEndian(hostAddr, val_64); } else { access_read_physical(pAddr, 8, (Bit8u*)(&val_64)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 8, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&val_64)); return val_64; } BX_CPP_INLINE void BX_CPU_C::vmcb_write8(unsigned offset, Bit8u val_8) { bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit8u *hostAddr = (Bit8u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); pageWriteStampTable.decWriteStamp(pAddr, 1); *hostAddr = val_8; } else { access_write_physical(pAddr, 1, (Bit8u*)(&val_8)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&val_8)); } BX_CPP_INLINE void BX_CPU_C::vmcb_write16(unsigned offset, Bit16u val_16) { bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit16u *hostAddr = (Bit16u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostAddr, val_16); } else { access_write_physical(pAddr, 2, (Bit8u*)(&val_16)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 2, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&val_16)); } BX_CPP_INLINE void BX_CPU_C::vmcb_write32(unsigned offset, Bit32u val_32) { bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit32u *hostAddr = (Bit32u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostAddr, val_32); } else { access_write_physical(pAddr, 4, (Bit8u*)(&val_32)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&val_32)); } BX_CPP_INLINE void BX_CPU_C::vmcb_write64(unsigned offset, Bit64u val_64) { bx_phy_address pAddr = BX_CPU_THIS_PTR vmcbptr + offset; if (BX_CPU_THIS_PTR vmcbhostptr) { Bit64u *hostAddr = (Bit64u*) (BX_CPU_THIS_PTR vmcbhostptr | offset); pageWriteStampTable.decWriteStamp(pAddr, 8); WriteHostQWordToLittleEndian(hostAddr, val_64); } else { access_write_physical(pAddr, 8, (Bit8u*)(&val_64)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 8, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&val_64)); } BX_CPP_INLINE void BX_CPU_C::svm_segment_read(bx_segment_reg_t *seg, unsigned offset) { Bit16u selector = vmcb_read16(offset); Bit16u attr = vmcb_read16(offset + 2); Bit32u limit = vmcb_read32(offset + 4); bx_address base = CanonicalizeAddress(vmcb_read64(offset + 8)); bx_bool valid = (attr >> 7) & 1; set_segment_ar_data(seg, valid, selector, base, limit, (attr & 0xff) | ((attr & 0xf00) << 4)); } BX_CPP_INLINE void BX_CPU_C::svm_segment_write(bx_segment_reg_t *seg, unsigned offset) { Bit32u selector = seg->selector.value; bx_address base = seg->cache.u.segment.base; Bit32u limit = seg->cache.u.segment.limit_scaled; Bit32u attr = (seg->cache.valid) ? (get_descriptor_h(&seg->cache) & 0x00f0ff00) : 0; vmcb_write16(offset, selector); vmcb_write16(offset + 2, ((attr >> 8) & 0xff) | ((attr >> 12) & 0xf00)); vmcb_write32(offset + 4, limit); vmcb_write64(offset + 8, base); } void BX_CPU_C::SvmEnterSaveHostState(SVM_HOST_STATE *host) { for (int n=0;n < 4; n++) host->sregs[n] = BX_CPU_THIS_PTR sregs[n]; host->gdtr = BX_CPU_THIS_PTR gdtr; host->idtr = BX_CPU_THIS_PTR idtr; host->efer = BX_CPU_THIS_PTR efer; host->cr0 = BX_CPU_THIS_PTR cr0; host->cr3 = BX_CPU_THIS_PTR cr3; host->cr4 = BX_CPU_THIS_PTR cr4; host->eflags = read_eflags(); host->rip = RIP; host->rsp = RSP; host->rax = RAX; } void BX_CPU_C::SvmExitLoadHostState(SVM_HOST_STATE *host) { BX_CPU_THIS_PTR tsc_offset = 0; for (unsigned n=0;n < 4; n++) { BX_CPU_THIS_PTR sregs[n] = host->sregs[n]; // we don't save selector details so parse selector again after loading parse_selector(BX_CPU_THIS_PTR sregs[n].selector.value, &BX_CPU_THIS_PTR sregs[n].selector); } BX_CPU_THIS_PTR gdtr = host->gdtr; BX_CPU_THIS_PTR idtr = host->idtr; BX_CPU_THIS_PTR efer = host->efer; BX_CPU_THIS_PTR cr0.set32(host->cr0.get32() | BX_CR0_PE_MASK); // always set the CR0.PE BX_CPU_THIS_PTR cr3 = host->cr3; BX_CPU_THIS_PTR cr4 = host->cr4; if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) { if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) { BX_ERROR(("SvmExitLoadHostState(): PDPTR check failed !")); shutdown(); } } BX_CPU_THIS_PTR dr7.set32(0x00000400); setEFlags(host->eflags & ~EFlagsVMMask); // ignore saved copy of EFLAGS.VM RIP = BX_CPU_THIS_PTR prev_rip = host->rip; RSP = host->rsp; RAX = host->rax; CPL = 0; handleCpuContextChange(); #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_CONTEXT_SWITCH, 0); } void BX_CPU_C::SvmExitSaveGuestState(void) { for (unsigned n=0;n < 4; n++) { svm_segment_write(&BX_CPU_THIS_PTR sregs[n], SVM_GUEST_ES_SELECTOR + n * 0x10); } vmcb_write64(SVM_GUEST_GDTR_BASE, BX_CPU_THIS_PTR gdtr.base); vmcb_write16(SVM_GUEST_GDTR_LIMIT, BX_CPU_THIS_PTR gdtr.limit); vmcb_write64(SVM_GUEST_IDTR_BASE, BX_CPU_THIS_PTR idtr.base); vmcb_write16(SVM_GUEST_IDTR_LIMIT, BX_CPU_THIS_PTR idtr.limit); vmcb_write64(SVM_GUEST_EFER_MSR, BX_CPU_THIS_PTR efer.get32()); vmcb_write64(SVM_GUEST_CR0, BX_CPU_THIS_PTR cr0.get32()); vmcb_write64(SVM_GUEST_CR2, BX_CPU_THIS_PTR cr2); vmcb_write64(SVM_GUEST_CR3, BX_CPU_THIS_PTR cr3); vmcb_write64(SVM_GUEST_CR4, BX_CPU_THIS_PTR cr4.get32()); vmcb_write64(SVM_GUEST_DR6, BX_CPU_THIS_PTR dr6.get32()); vmcb_write64(SVM_GUEST_DR7, BX_CPU_THIS_PTR dr7.get32()); vmcb_write64(SVM_GUEST_RFLAGS, read_eflags()); vmcb_write64(SVM_GUEST_RAX, RAX); vmcb_write64(SVM_GUEST_RSP, RSP); vmcb_write64(SVM_GUEST_RIP, RIP); vmcb_write8(SVM_GUEST_CPL, CPL); vmcb_write8(SVM_CONTROL_INTERRUPT_SHADOW, interrupts_inhibited(BX_INHIBIT_INTERRUPTS)); SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; vmcb_write8(SVM_CONTROL_VTPR, ctrls->v_tpr); vmcb_write8(SVM_CONTROL_VIRQ, ctrls->v_irq); } extern bx_bool isValidMSR_PAT(Bit64u pat_msr); bx_bool BX_CPU_C::SvmEnterLoadCheckControls(SVM_CONTROLS *ctrls) { ctrls->cr_rd_ctrl = vmcb_read16(SVM_CONTROL16_INTERCEPT_CR_READ); ctrls->cr_wr_ctrl = vmcb_read16(SVM_CONTROL16_INTERCEPT_CR_WRITE); ctrls->dr_rd_ctrl = vmcb_read16(SVM_CONTROL16_INTERCEPT_DR_READ); ctrls->dr_wr_ctrl = vmcb_read16(SVM_CONTROL16_INTERCEPT_DR_WRITE); ctrls->intercept_vector[0] = vmcb_read32(SVM_CONTROL32_INTERCEPT1); ctrls->intercept_vector[1] = vmcb_read32(SVM_CONTROL32_INTERCEPT2); if (! SVM_INTERCEPT(SVM_INTERCEPT1_VMRUN)) { BX_ERROR(("VMRUN: VMRUN intercept bit is not set!")); return 0; } ctrls->exceptions_intercept = vmcb_read32(SVM_CONTROL32_INTERCEPT_EXCEPTIONS); // force 4K page alignment ctrls->iopm_base = PPFOf(vmcb_read64(SVM_CONTROL64_IOPM_BASE_PHY_ADDR)); if (! IsValidPhyAddr(ctrls->iopm_base)) { BX_ERROR(("VMRUN: invalid IOPM Base Address !")); return 0; } // force 4K page alignment ctrls->msrpm_base = PPFOf(vmcb_read64(SVM_CONTROL64_MSRPM_BASE_PHY_ADDR)); if (! IsValidPhyAddr(ctrls->msrpm_base)) { BX_ERROR(("VMRUN: invalid MSRPM Base Address !")); return 0; } Bit32u guest_asid = vmcb_read32(SVM_CONTROL32_GUEST_ASID); if (guest_asid == 0) { BX_ERROR(("VMRUN: attempt to run guest with host ASID !")); return 0; } ctrls->v_tpr = vmcb_read8(SVM_CONTROL_VTPR); ctrls->v_irq = vmcb_read8(SVM_CONTROL_VIRQ) & 0x1; ctrls->v_intr_masking = vmcb_read8(SVM_CONTROL_VINTR_MASKING) & 0x1; ctrls->v_intr_vector = vmcb_read8(SVM_CONTROL_VINTR_VECTOR); Bit8u vintr_control = vmcb_read8(SVM_CONTROL_VINTR_PRIO_IGN_TPR); ctrls->v_intr_prio = vintr_control & 0xf; ctrls->v_ignore_tpr = (vintr_control >> 4) & 0x1; ctrls->nested_paging = vmcb_read8(SVM_CONTROL_NESTED_PAGING_ENABLE); if (! BX_SUPPORT_SVM_EXTENSION(BX_CPUID_SVM_NESTED_PAGING)) { if (ctrls->nested_paging) { BX_ERROR(("VMRUN: Nesting paging is not supported in this SVM configuration !")); ctrls->nested_paging = 0; } } if (ctrls->nested_paging) { if (! BX_CPU_THIS_PTR cr0.get_PG()) { BX_ERROR(("VMRUN: attempt to enter nested paging mode when host paging is disabled !")); return 0; } Bit64u guest_pat = vmcb_read32(SVM_GUEST_PAT); if (! isValidMSR_PAT(guest_pat)) { BX_ERROR(("VMRUN: invalid memory type in guest PAT_MSR !")); return 0; } ctrls->ncr3 = vmcb_read64(SVM_CONTROL64_NESTED_PAGING_HOST_CR3); if (long_mode()) { if (! IsValidPhyAddr(ctrls->ncr3)) { BX_ERROR(("VMRUN(): NCR3 reserved bits set !")); return 0; } } BX_DEBUG(("VMRUN: Starting Nested Paging Mode !")); } return 1; } bx_bool BX_CPU_C::SvmEnterLoadCheckGuestState(void) { SVM_GUEST_STATE guest; Bit32u tmp; unsigned n; bx_bool paged_real_mode = 0; guest.eflags = vmcb_read32(SVM_GUEST_RFLAGS); guest.rip = vmcb_read64(SVM_GUEST_RIP); guest.rsp = vmcb_read64(SVM_GUEST_RSP); guest.rax = vmcb_read64(SVM_GUEST_RAX); guest.efer.val32 = vmcb_read32(SVM_GUEST_EFER_MSR); tmp = vmcb_read32(SVM_GUEST_EFER_MSR_HI); if (tmp) { BX_ERROR(("VMRUN: Guest EFER[63:32] is not zero")); return 0; } if (guest.efer.val32 & ~BX_CPU_THIS_PTR efer_suppmask) { BX_ERROR(("VMRUN: Guest EFER reserved bits set")); return 0; } if (! guest.efer.get_SVME()) { BX_ERROR(("VMRUN: Guest EFER.SVME = 0")); return 0; } guest.cr0.val32 = vmcb_read32(SVM_GUEST_CR0); tmp = vmcb_read32(SVM_GUEST_CR0_HI); if (tmp) { BX_ERROR(("VMRUN: Guest CR0[63:32] is not zero")); return 0; } // always assign EFER.LMA := EFER.LME & CR0.PG guest.efer.set_LMA(guest.cr0.get_PG() && guest.efer.get_LME()); guest.cr2 = vmcb_read64(SVM_GUEST_CR2); guest.cr3 = vmcb_read64(SVM_GUEST_CR3); guest.cr4.val32 = vmcb_read32(SVM_GUEST_CR4); tmp = vmcb_read32(SVM_GUEST_CR4_HI); if (tmp) { BX_ERROR(("VMRUN: Guest CR4[63:32] is not zero")); return 0; } if (guest.cr4.val32 & ~BX_CPU_THIS_PTR cr4_suppmask) { BX_ERROR(("VMRUN: Guest CR4 reserved bits set")); return 0; } guest.dr6 = vmcb_read32(SVM_GUEST_DR6); tmp = vmcb_read32(SVM_GUEST_DR6_HI); if (tmp) { BX_ERROR(("VMRUN: Guest DR6[63:32] is not zero")); return 0; } guest.dr7 = vmcb_read32(SVM_GUEST_DR7); tmp = vmcb_read32(SVM_GUEST_DR7_HI); if (tmp) { BX_ERROR(("VMRUN: Guest DR7[63:32] is not zero")); return 0; } for (n=0;n < 4; n++) { svm_segment_read(&guest.sregs[n], SVM_GUEST_ES_SELECTOR + n * 0x10); } if (guest.sregs[BX_SEG_REG_CS].cache.u.segment.d_b && guest.sregs[BX_SEG_REG_CS].cache.u.segment.l) { BX_ERROR(("VMRUN: VMCB CS.D_B/L mismatch")); return 0; } if (! guest.cr0.get_PE() || (guest.eflags & EFlagsVMMask) != 0) { // real or vm8086 mode: make all segments valid for (n=0;n < 4; n++) { guest.sregs[n].cache.valid = 1; } if (! guest.cr0.get_PE() && guest.cr0.get_PG()) { // special case : entering paged real mode BX_DEBUG(("VMRUN: entering paged real mode")); paged_real_mode = 1; guest.cr0.val32 &= ~BX_CR0_PG_MASK; } } guest.cpl = vmcb_read8(SVM_GUEST_CPL); // // FIXME: patch segment attributes // // CS: only D, L, and R are observed // DS/ES/FS/GS: only D, P, DPL, E, W, and Code/Data are observed // SS: only B, P, E, W, and Code/Data are observed guest.sregs[BX_SEG_REG_SS].cache.dpl = guest.cpl; guest.gdtr.base = CanonicalizeAddress(vmcb_read64(SVM_GUEST_GDTR_BASE)); guest.gdtr.limit = vmcb_read16(SVM_GUEST_GDTR_LIMIT); guest.idtr.base = CanonicalizeAddress(vmcb_read64(SVM_GUEST_IDTR_BASE)); guest.idtr.limit = vmcb_read16(SVM_GUEST_IDTR_LIMIT); guest.inhibit_interrupts = vmcb_read8(SVM_CONTROL_INTERRUPT_SHADOW) & 0x1; // // Load guest state // BX_CPU_THIS_PTR tsc_offset = vmcb_read64(SVM_CONTROL64_TSC_OFFSET); BX_CPU_THIS_PTR efer.set32(guest.efer.get32()); if (! check_CR0(guest.cr0.get32())) { BX_ERROR(("SVM: VMRUN CR0 is broken !")); return 0; } if (! check_CR4(guest.cr4.get32())) { BX_ERROR(("SVM: VMRUN CR4 is broken !")); return 0; } BX_CPU_THIS_PTR cr0.set32(guest.cr0.get32()); BX_CPU_THIS_PTR cr4.set32(guest.cr4.get32()); BX_CPU_THIS_PTR cr3 = guest.cr3; if (paged_real_mode) BX_CPU_THIS_PTR cr0.val32 |= BX_CR0_PG_MASK; SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; if (! ctrls->nested_paging) { if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) { if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) { BX_ERROR(("SVM: VMRUN PDPTR check failed !")); return 0; } } } BX_CPU_THIS_PTR dr6.set32(guest.dr6); BX_CPU_THIS_PTR dr7.set32(guest.dr7 | 0x400); for (n=0;n < 4; n++) { BX_CPU_THIS_PTR sregs[n] = guest.sregs[n]; } BX_CPU_THIS_PTR gdtr = guest.gdtr; BX_CPU_THIS_PTR idtr = guest.idtr; RIP = BX_CPU_THIS_PTR prev_rip = guest.rip; RSP = guest.rsp; RAX = guest.rax; CPL = guest.cpl; if (guest.inhibit_interrupts) { inhibit_interrupts(BX_INHIBIT_INTERRUPTS); } BX_CPU_THIS_PTR async_event = 0; setEFlags((Bit32u) guest.eflags); // injecting virtual interrupt if (SVM_V_IRQ) BX_CPU_THIS_PTR async_event = 1; handleCpuContextChange(); #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_CONTEXT_SWITCH, 0); return 1; } void BX_CPU_C::Svm_Vmexit(int reason, Bit64u exitinfo1, Bit64u exitinfo2) { BX_DEBUG(("SVM VMEXIT reason=%d exitinfo1=%08x%08x exitinfo2=%08x%08x", reason, GET32H(exitinfo1), GET32L(exitinfo1), GET32H(exitinfo2), GET32L(exitinfo2))); if (! BX_CPU_THIS_PTR in_svm_guest) { if (reason != SVM_VMEXIT_INVALID) BX_PANIC(("PANIC: VMEXIT %d not in SVM guest mode !", reason)); } if (BX_SUPPORT_SVM_EXTENSION(BX_CPUID_SVM_NRIP_SAVE)) vmcb_write64(SVM_CONTROL64_NRIP, RIP); // VMEXITs are FAULT-like: restore RIP/RSP to value before VMEXIT occurred RIP = BX_CPU_THIS_PTR prev_rip; if (BX_CPU_THIS_PTR speculative_rsp) RSP = BX_CPU_THIS_PTR prev_rsp; BX_CPU_THIS_PTR in_svm_guest = 0; BX_CPU_THIS_PTR svm_gif = 0; // // STEP 0: Update exit reason // SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; vmcb_write64(SVM_CONTROL64_EXITCODE, (Bit64u) ((Bit64s) reason)); vmcb_write64(SVM_CONTROL64_EXITINFO1, exitinfo1); vmcb_write64(SVM_CONTROL64_EXITINFO2, exitinfo2); // clean interrupt injection field vmcb_write32(SVM_CONTROL32_EVENT_INJECTION, ctrls->eventinj & ~0x80000000); if (BX_CPU_THIS_PTR in_event) { vmcb_write32(SVM_CONTROL32_EXITINTINFO, ctrls->exitintinfo | 0x80000000); vmcb_write32(SVM_CONTROL32_EXITINTINFO_ERROR_CODE, ctrls->exitintinfo_error_code); BX_CPU_THIS_PTR in_event = 0; } else { vmcb_write32(SVM_CONTROL32_EXITINTINFO, 0); } // // Step 1: Save guest state in the VMCB // SvmExitSaveGuestState(); // // Step 2: // SvmExitLoadHostState(&BX_CPU_THIS_PTR vmcb.host_state); // // STEP 3: Go back to SVM host // BX_CPU_THIS_PTR errorno = 0; BX_CPU_THIS_PTR EXT = 0; #if BX_DEBUGGER if (BX_CPU_THIS_PTR vmexit_break) { BX_CPU_THIS_PTR stop_reason = STOP_VMEXIT_BREAK_POINT; bx_debug_break(); // trap into debugger } #endif longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop } extern struct BxExceptionInfo exceptions_info[]; bx_bool BX_CPU_C::SvmInjectEvents(void) { SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; ctrls->eventinj = vmcb_read32(SVM_CONTROL32_EVENT_INJECTION); if ((ctrls->eventinj & 0x80000000) == 0) return 1; /* the VMENTRY injecting event to the guest */ unsigned vector = ctrls->eventinj & 0xff; unsigned type = (ctrls->eventinj >> 8) & 7; unsigned push_error = ctrls->eventinj & (1 << 11); unsigned error_code = push_error ? vmcb_read32(SVM_CONTROL32_EVENT_INJECTION_ERRORCODE) : 0; switch(type) { case BX_NMI: vector = 2; case BX_EXTERNAL_INTERRUPT: BX_CPU_THIS_PTR EXT = 1; break; case BX_HARDWARE_EXCEPTION: if (vector == 2 || vector > 31) { BX_ERROR(("SvmInjectEvents: invalid vector %d for HW exception", vector)); return 0; } if (vector == BX_BP_EXCEPTION || vector == BX_OF_EXCEPTION) { type = BX_SOFTWARE_EXCEPTION; } BX_CPU_THIS_PTR EXT = 1; break; case BX_SOFTWARE_INTERRUPT: break; default: BX_ERROR(("SvmInjectEvents: unsupported event injection type %d !", type)); return 0; } BX_DEBUG(("SvmInjectEvents: Injecting vector 0x%02x (error_code 0x%04x)", vector, error_code)); if (type == BX_HARDWARE_EXCEPTION) { // record exception the same way as BX_CPU_C::exception does BX_ASSERT(vector < BX_CPU_HANDLED_EXCEPTIONS); BX_CPU_THIS_PTR curr_exception = exceptions_info[vector].exception_type; BX_CPU_THIS_PTR errorno = 1; } ctrls->exitintinfo = ctrls->eventinj & ~0x80000000; ctrls->exitintinfo_error_code = error_code; interrupt(vector, type, push_error, error_code); BX_CPU_THIS_PTR errorno = 0; // injection success BX_CPU_THIS_PTR EXT = 0; return 1; } void BX_CPU_C::SvmInterceptException(unsigned type, unsigned vector, Bit16u errcode, bx_bool errcode_valid, Bit64u qualification) { if (! BX_CPU_THIS_PTR in_svm_guest) return; BX_ASSERT(vector < 32); SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; BX_ASSERT(type == BX_HARDWARE_EXCEPTION || type == BX_SOFTWARE_EXCEPTION); if (! SVM_EXCEPTION_INTERCEPTED(vector)) { // ----------------------------------------- // EXITINTINFO // ----------------------------------------- // [.7:.0] | Interrupt/Exception vector // [10:.8] | Interrupt/Exception type // [11:11] | error code pushed to the stack // [30:12] | reserved // [31:31] | interruption info valid // // record IDT vectoring information ctrls->exitintinfo_error_code = errcode; ctrls->exitintinfo = vector | (BX_HARDWARE_EXCEPTION << 8); if (errcode_valid) BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo |= (1 << 11); // error code delivered return; } BX_ERROR(("SVM VMEXIT: event vector 0x%02x type %d error code=0x%04x", vector, type, errcode)); // VMEXIT is not considered to occur during event delivery if it results // in a double fault exception that causes VMEXIT directly if (vector == BX_DF_EXCEPTION) BX_CPU_THIS_PTR in_event = 0; // clear in_event indication on #DF BX_CPU_THIS_PTR debug_trap = 0; // clear debug_trap field BX_CPU_THIS_PTR inhibit_mask = 0; Svm_Vmexit(SVM_VMEXIT_EXCEPTION + vector, (errcode_valid ? errcode : 0), qualification); } #define SVM_VMEXIT_IO_PORTIN (1 << 0) #define SVM_VMEXIT_IO_INSTR_STRING (1 << 2) #define SVM_VMEXIT_IO_INSTR_REP (1 << 3) #define SVM_VMEXIT_IO_INSTR_LEN8 (1 << 4) #define SVM_VMEXIT_IO_INSTR_LEN16 (1 << 5) #define SVM_VMEXIT_IO_INSTR_LEN32 (1 << 6) #define SVM_VMEXIT_IO_INSTR_ASIZE16 (1 << 7) #define SVM_VMEXIT_IO_INSTR_ASIZE32 (1 << 8) #define SVM_VMEXIT_IO_INSTR_ASIZE64 (1 << 9) void BX_CPU_C::SvmInterceptIO(bxInstruction_c *i, unsigned port, unsigned len) { if (! BX_CPU_THIS_PTR in_svm_guest) return; if (! SVM_INTERCEPT(SVM_INTERCEPT0_IO)) return; Bit8u bitmap[2]; bx_phy_address pAddr; // access_read_physical cannot read 2 bytes cross 4K boundary :( pAddr = BX_CPU_THIS_PTR vmcb.ctrls.iopm_base + (port / 8); access_read_physical(pAddr, 1, &bitmap[0]); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_IO_BITMAP_ACCESS, &bitmap[0]); pAddr++; access_read_physical(pAddr, 1, &bitmap[1]); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 1, BX_READ, BX_IO_BITMAP_ACCESS, &bitmap[1]); Bit16u combined_bitmap = bitmap[1]; combined_bitmap = (combined_bitmap << 8) | bitmap[0]; unsigned mask = ((1 << len) - 1) << (port & 7); if (combined_bitmap & mask) { BX_ERROR(("SVM VMEXIT: I/O port 0x%04x", port)); Bit32u qualification = 0; switch(i->getIaOpcode()) { case BX_IA_IN_ALIb: case BX_IA_IN_AXIb: case BX_IA_IN_EAXIb: case BX_IA_IN_ALDX: case BX_IA_IN_AXDX: case BX_IA_IN_EAXDX: qualification = SVM_VMEXIT_IO_PORTIN; break; case BX_IA_OUT_IbAL: case BX_IA_OUT_IbAX: case BX_IA_OUT_IbEAX: case BX_IA_OUT_DXAL: case BX_IA_OUT_DXAX: case BX_IA_OUT_DXEAX: qualification = 0; // PORTOUT break; case BX_IA_REP_INSB_YbDX: case BX_IA_REP_INSW_YwDX: case BX_IA_REP_INSD_YdDX: qualification = SVM_VMEXIT_IO_PORTIN | SVM_VMEXIT_IO_INSTR_STRING; if (i->repUsedL()) qualification |= SVM_VMEXIT_IO_INSTR_REP; break; case BX_IA_REP_OUTSB_DXXb: case BX_IA_REP_OUTSW_DXXw: case BX_IA_REP_OUTSD_DXXd: qualification = SVM_VMEXIT_IO_INSTR_STRING; // PORTOUT if (i->repUsedL()) qualification |= SVM_VMEXIT_IO_INSTR_REP; break; default: BX_PANIC(("VMexit_IO: I/O instruction %s unknown", i->getIaOpcodeName())); } qualification |= (port << 16); if (len == 1) qualification |= SVM_VMEXIT_IO_INSTR_LEN8; else if (len == 2) qualification |= SVM_VMEXIT_IO_INSTR_LEN16; else if (len == 4) qualification |= SVM_VMEXIT_IO_INSTR_LEN32; if (i->as64L()) qualification |= SVM_VMEXIT_IO_INSTR_ASIZE64; else if (i->as32L()) qualification |= SVM_VMEXIT_IO_INSTR_ASIZE32; else qualification |= SVM_VMEXIT_IO_INSTR_ASIZE16; Svm_Vmexit(SVM_VMEXIT_IO, qualification, RIP); } } void BX_CPU_C::SvmInterceptMSR(unsigned op, Bit32u msr) { if (! BX_CPU_THIS_PTR in_svm_guest) return; if (! SVM_INTERCEPT(SVM_INTERCEPT0_MSR)) return; BX_ASSERT(op == BX_READ || op == BX_WRITE); bx_bool vmexit = 1; int msr_map_offset = -1; if (msr <= 0x1fff) msr_map_offset = 0; else if (msr >= 0xc0000000 && msr <= 0xc0001fff) msr_map_offset = 2048; else if (msr >= 0xc0010000 && msr <= 0xc0011fff) msr_map_offset = 4096; if (msr_map_offset >= 0) { bx_phy_address msr_bitmap_addr = BX_CPU_THIS_PTR vmcb.ctrls.msrpm_base + msr_map_offset; Bit32u msr_offset = (msr & 0x1fff) * 2 + op; Bit8u msr_bitmap; access_read_physical(msr_bitmap_addr + (msr_offset / 8), 1, (Bit8u*)(&msr_bitmap)); BX_NOTIFY_PHY_MEMORY_ACCESS(msr_bitmap_addr + (msr_offset / 8), 1, BX_READ, BX_MSR_BITMAP_ACCESS, &msr_bitmap); vmexit = (msr_bitmap >> (msr_offset & 7)) & 0x1; } if (vmexit) { Svm_Vmexit(SVM_VMEXIT_MSR, op); // 0 - RDMSR, 1 - WRMSR } } void BX_CPU_C::SvmInterceptTaskSwitch(Bit16u tss_selector, unsigned source, bx_bool push_error, Bit32u error_code) { BX_ASSERT(BX_CPU_THIS_PTR in_svm_guest); BX_DEBUG(("SVM VMEXIT: task switch")); // // SVM VMexit EXITINFO2: // -------------------- // EXITINFO2[31-0] - error code to push into new stack (if applicable) // EXITINFO2[36] - task switch caused by IRET // EXITINFO2[38] - task switch caused by JUMP FAR // EXITINFO2[44] - task switch has error code to push // EXITINFO2[48] - value of EFLAGS.RF that would be saved in outgoing TSS // Bit64u qualification = error_code; if (source == BX_TASK_FROM_IRET) qualification |= BX_CONST64(1) << 36; if (source == BX_TASK_FROM_JUMP) qualification |= BX_CONST64(1) << 38; if (push_error) qualification |= BX_CONST64(1) << 44; Bit32u flags = read_eflags(); if (flags & EFlagsRFMask) qualification |= BX_CONST64(1) << 48; Svm_Vmexit(SVM_VMEXIT_TASK_SWITCH, tss_selector, qualification); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMRUN(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (! protected_mode() || ! BX_CPU_THIS_PTR efer.get_SVME()) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("VMRUN with CPL != 0")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_VMRUN)) Svm_Vmexit(SVM_VMEXIT_VMRUN); } bx_address pAddr = RAX & i->asize_mask(); if ((pAddr & 0xfff) != 0 || ! IsValidPhyAddr(pAddr)) { BX_ERROR(("VMRUN: invalid or not page aligned VMCB physical address !")); exception(BX_GP_EXCEPTION, 0); } BX_CPU_THIS_PTR vmcbptr = pAddr; BX_CPU_THIS_PTR vmcbhostptr = BX_CPU_THIS_PTR getHostMemAddr(pAddr, BX_WRITE); BX_DEBUG(("VMRUN VMCB ptr: 0x" FMT_ADDRX64, BX_CPU_THIS_PTR vmcbptr)); // // Step 1: Save host state to physical memory indicated in SVM_HSAVE_PHY_ADDR_MSR // SvmEnterSaveHostState(&BX_CPU_THIS_PTR vmcb.host_state); // // Step 2: Load control information from the VMCB // if (!SvmEnterLoadCheckControls(&BX_CPU_THIS_PTR vmcb.ctrls)) Svm_Vmexit(SVM_VMEXIT_INVALID); // // Step 3: Load guest state from the VMCB and enter SVM // if (!SvmEnterLoadCheckGuestState()) Svm_Vmexit(SVM_VMEXIT_INVALID); BX_CPU_THIS_PTR in_svm_guest = 1; BX_CPU_THIS_PTR svm_gif = 1; // // Step 4: Inject events to the guest // if (!SvmInjectEvents()) Svm_Vmexit(SVM_VMEXIT_INVALID); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMMCALL(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR efer.get_SVME()) { if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_VMMCALL)) Svm_Vmexit(SVM_VMEXIT_VMMCALL); } } exception(BX_UD_EXCEPTION, 0); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLOAD(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (! protected_mode() || ! BX_CPU_THIS_PTR efer.get_SVME()) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("VMLOAD with CPL != 0")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_VMLOAD)) Svm_Vmexit(SVM_VMEXIT_VMLOAD); } bx_address pAddr = RAX & i->asize_mask(); if ((pAddr & 0xfff) != 0 || ! IsValidPhyAddr(pAddr)) { BX_ERROR(("VMLOAD: invalid or not page aligned VMCB physical address !")); exception(BX_GP_EXCEPTION, 0); } BX_CPU_THIS_PTR vmcbptr = pAddr; BX_CPU_THIS_PTR vmcbhostptr = BX_CPU_THIS_PTR getHostMemAddr(pAddr, BX_WRITE); BX_DEBUG(("VMLOAD VMCB ptr: 0x" FMT_ADDRX64, BX_CPU_THIS_PTR vmcbptr)); bx_segment_reg_t fs, gs, guest_tr, guest_ldtr; svm_segment_read(&fs, SVM_GUEST_FS_SELECTOR); svm_segment_read(&gs, SVM_GUEST_GS_SELECTOR); svm_segment_read(&guest_tr, SVM_GUEST_TR_SELECTOR); svm_segment_read(&guest_ldtr, SVM_GUEST_LDTR_SELECTOR); BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS] = fs; BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS] = gs; BX_CPU_THIS_PTR tr = guest_tr; BX_CPU_THIS_PTR ldtr = guest_ldtr; MSR_KERNELGSBASE = CanonicalizeAddress(vmcb_read64(SVM_GUEST_KERNEL_GSBASE_MSR)); MSR_STAR = vmcb_read64(SVM_GUEST_STAR_MSR); MSR_LSTAR = CanonicalizeAddress(vmcb_read64(SVM_GUEST_LSTAR_MSR)); MSR_CSTAR = CanonicalizeAddress(vmcb_read64(SVM_GUEST_CSTAR_MSR)); MSR_FMASK = vmcb_read64(SVM_GUEST_SFMASK_MSR); BX_CPU_THIS_PTR msr.sysenter_cs_msr = vmcb_read64(SVM_GUEST_SYSENTER_CS_MSR); BX_CPU_THIS_PTR msr.sysenter_eip_msr = CanonicalizeAddress(vmcb_read64(SVM_GUEST_SYSENTER_EIP_MSR)); BX_CPU_THIS_PTR msr.sysenter_esp_msr = CanonicalizeAddress(vmcb_read64(SVM_GUEST_SYSENTER_ESP_MSR)); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMSAVE(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (! protected_mode() || ! BX_CPU_THIS_PTR efer.get_SVME()) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("VMSAVE with CPL != 0")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_VMSAVE)) Svm_Vmexit(SVM_VMEXIT_VMSAVE); } bx_address pAddr = RAX & i->asize_mask(); if ((pAddr & 0xfff) != 0 || ! IsValidPhyAddr(pAddr)) { BX_ERROR(("VMSAVE: invalid or not page aligned VMCB physical address !")); exception(BX_GP_EXCEPTION, 0); } BX_CPU_THIS_PTR vmcbptr = pAddr; BX_CPU_THIS_PTR vmcbhostptr = BX_CPU_THIS_PTR getHostMemAddr(pAddr, BX_WRITE); BX_DEBUG(("VMSAVE VMCB ptr: 0x" FMT_ADDRX64, BX_CPU_THIS_PTR vmcbptr)); svm_segment_write(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS], SVM_GUEST_FS_SELECTOR); svm_segment_write(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS], SVM_GUEST_GS_SELECTOR); svm_segment_write(&BX_CPU_THIS_PTR tr, SVM_GUEST_TR_SELECTOR); svm_segment_write(&BX_CPU_THIS_PTR ldtr, SVM_GUEST_LDTR_SELECTOR); vmcb_write64(SVM_GUEST_KERNEL_GSBASE_MSR, MSR_KERNELGSBASE); vmcb_write64(SVM_GUEST_STAR_MSR, MSR_STAR); vmcb_write64(SVM_GUEST_LSTAR_MSR, MSR_LSTAR); vmcb_write64(SVM_GUEST_CSTAR_MSR, MSR_CSTAR); vmcb_write64(SVM_GUEST_SFMASK_MSR, MSR_FMASK); vmcb_write64(SVM_GUEST_SYSENTER_CS_MSR, BX_CPU_THIS_PTR msr.sysenter_cs_msr); vmcb_write64(SVM_GUEST_SYSENTER_ESP_MSR, BX_CPU_THIS_PTR msr.sysenter_esp_msr); vmcb_write64(SVM_GUEST_SYSENTER_EIP_MSR, BX_CPU_THIS_PTR msr.sysenter_eip_msr); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SKINIT(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (! protected_mode() || ! BX_CPU_THIS_PTR efer.get_SVME()) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("SKINIT with CPL != 0")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_SKINIT)) Svm_Vmexit(SVM_VMEXIT_SKINIT); } BX_PANIC(("SVM: SKINIT is not implemented yet")); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLGI(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (! protected_mode() || ! BX_CPU_THIS_PTR efer.get_SVME()) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("CLGI with CPL != 0")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_CLGI)) Svm_Vmexit(SVM_VMEXIT_CLGI); } BX_CPU_THIS_PTR svm_gif = 0; BX_CPU_THIS_PTR async_event = 1; #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STGI(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (! protected_mode() || ! BX_CPU_THIS_PTR efer.get_SVME()) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("STGI with CPL != 0")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_STGI)) Svm_Vmexit(SVM_VMEXIT_STGI); } BX_CPU_THIS_PTR svm_gif = 1; BX_CPU_THIS_PTR async_event = 1; #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVLPGA(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (! protected_mode() || ! BX_CPU_THIS_PTR efer.get_SVME()) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("INVLPGA with CPL != 0")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_INVLPGA)) Svm_Vmexit(SVM_VMEXIT_INVLPGA); } TLB_flush(); // FIXME: flush all entries for now #endif BX_NEXT_TRACE(i); } #if BX_SUPPORT_SVM void BX_CPU_C::register_svm_state(bx_param_c *parent) { if (! bx_cpuid_support_svm()) return; // register SVM state for save/restore param tree bx_list_c *svm = new bx_list_c(parent, "SVM"); BXRS_PARAM_BOOL(svm, in_svm_guest, BX_CPU_THIS_PTR in_svm_guest); BXRS_PARAM_BOOL(svm, gif, BX_CPU_THIS_PTR svm_gif); // // VMCB Control Fields // bx_list_c *vmcb_ctrls = new bx_list_c(svm, "VMCB_CTRLS"); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, cr_rd_ctrl, BX_CPU_THIS_PTR vmcb.ctrls.cr_rd_ctrl); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, cr_wr_ctrl, BX_CPU_THIS_PTR vmcb.ctrls.cr_wr_ctrl); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, dr_rd_ctrl, BX_CPU_THIS_PTR vmcb.ctrls.dr_rd_ctrl); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, dr_wr_ctrl, BX_CPU_THIS_PTR vmcb.ctrls.dr_wr_ctrl); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, exceptions_intercept, BX_CPU_THIS_PTR vmcb.ctrls.exceptions_intercept); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, intercept_vector0, BX_CPU_THIS_PTR vmcb.ctrls.intercept_vector[0]); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, intercept_vector1, BX_CPU_THIS_PTR vmcb.ctrls.intercept_vector[1]); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, iopm_base, BX_CPU_THIS_PTR vmcb.ctrls.iopm_base); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, msrpm_base, BX_CPU_THIS_PTR vmcb.ctrls.msrpm_base); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, exitintinfo, BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, exitintinfo_errcode, BX_CPU_THIS_PTR vmcb.ctrls.exitintinfo_error_code); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, eventinj, BX_CPU_THIS_PTR vmcb.ctrls.eventinj); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, v_tpr, BX_CPU_THIS_PTR vmcb.ctrls.v_tpr); BXRS_PARAM_BOOL(vmcb_ctrls, v_irq, BX_CPU_THIS_PTR vmcb.ctrls.v_irq); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, v_intr_prio, BX_CPU_THIS_PTR vmcb.ctrls.v_intr_prio); BXRS_PARAM_BOOL(vmcb_ctrls, v_ignore_tpr, BX_CPU_THIS_PTR vmcb.ctrls.v_ignore_tpr); BXRS_PARAM_BOOL(vmcb_ctrls, v_intr_masking, BX_CPU_THIS_PTR vmcb.ctrls.v_intr_masking); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, v_intr_vector, BX_CPU_THIS_PTR vmcb.ctrls.v_intr_vector); BXRS_PARAM_BOOL(vmcb_ctrls, nested_paging, BX_CPU_THIS_PTR vmcb.ctrls.nested_paging); BXRS_HEX_PARAM_FIELD(vmcb_ctrls, ncr3, BX_CPU_THIS_PTR vmcb.ctrls.ncr3); // // VMCB Host State // bx_list_c *host = new bx_list_c(svm, "VMCB_HOST_STATE"); for(unsigned n=0; n<4; n++) { bx_segment_reg_t *segment = &BX_CPU_THIS_PTR vmcb.host_state.sregs[n]; bx_list_c *sreg = new bx_list_c(host, svm_segname[n]); BXRS_HEX_PARAM_FIELD(sreg, selector, segment->selector.value); BXRS_HEX_PARAM_FIELD(sreg, valid, segment->cache.valid); BXRS_PARAM_BOOL(sreg, p, segment->cache.p); BXRS_HEX_PARAM_FIELD(sreg, dpl, segment->cache.dpl); BXRS_PARAM_BOOL(sreg, segment, segment->cache.segment); BXRS_HEX_PARAM_FIELD(sreg, type, segment->cache.type); BXRS_HEX_PARAM_FIELD(sreg, base, segment->cache.u.segment.base); BXRS_HEX_PARAM_FIELD(sreg, limit_scaled, segment->cache.u.segment.limit_scaled); BXRS_PARAM_BOOL(sreg, granularity, segment->cache.u.segment.g); BXRS_PARAM_BOOL(sreg, d_b, segment->cache.u.segment.d_b); #if BX_SUPPORT_X86_64 BXRS_PARAM_BOOL(sreg, l, segment->cache.u.segment.l); #endif BXRS_PARAM_BOOL(sreg, avl, segment->cache.u.segment.avl); } bx_list_c *GDTR = new bx_list_c(host, "GDTR"); BXRS_HEX_PARAM_FIELD(GDTR, base, BX_CPU_THIS_PTR vmcb.host_state.gdtr.base); BXRS_HEX_PARAM_FIELD(GDTR, limit, BX_CPU_THIS_PTR vmcb.host_state.gdtr.limit); bx_list_c *IDTR = new bx_list_c(host, "IDTR"); BXRS_HEX_PARAM_FIELD(IDTR, base, BX_CPU_THIS_PTR vmcb.host_state.idtr.base); BXRS_HEX_PARAM_FIELD(IDTR, limit, BX_CPU_THIS_PTR vmcb.host_state.idtr.limit); BXRS_HEX_PARAM_FIELD(host, efer, BX_CPU_THIS_PTR vmcb.host_state.efer.val32); BXRS_HEX_PARAM_FIELD(host, cr0, BX_CPU_THIS_PTR vmcb.host_state.cr0.val32); BXRS_HEX_PARAM_FIELD(host, cr3, BX_CPU_THIS_PTR vmcb.host_state.cr3); BXRS_HEX_PARAM_FIELD(host, cr4, BX_CPU_THIS_PTR vmcb.host_state.cr4.val32); BXRS_HEX_PARAM_FIELD(host, eflags, BX_CPU_THIS_PTR vmcb.host_state.eflags); BXRS_HEX_PARAM_FIELD(host, rip, BX_CPU_THIS_PTR vmcb.host_state.rip); BXRS_HEX_PARAM_FIELD(host, rsp, BX_CPU_THIS_PTR vmcb.host_state.rsp); BXRS_HEX_PARAM_FIELD(host, rax, BX_CPU_THIS_PTR vmcb.host_state.rax); } #endif bochs-2.6/cpu/init.cc0000644000175000017500000012532112020641453014377 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: init.cc 11232 2012-06-24 17:52:45Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #include "param_names.h" BX_CPU_C::BX_CPU_C(unsigned id): bx_cpuid(id) #if BX_CPU_LEVEL >= 4 , cpuid(NULL) #endif #if BX_SUPPORT_APIC ,lapic (this, id) #endif { // in case of SMF, you cannot reference any member data // in the constructor because the only access to it is via // global variables which aren't initialized quite yet. char name[16], logname[16]; sprintf(name, "CPU%x", bx_cpuid); sprintf(logname, "cpu%x", bx_cpuid); put(logname, name); isa_extensions_bitmask = BX_SUPPORT_FPU ? BX_ISA_X87 : 0; cpu_extensions_bitmask = 0; #if BX_SUPPORT_VMX vmx_extensions_bitmask = 0; #endif #if BX_SUPPORT_SVM svm_extensions_bitmask = 0; #endif } #if BX_WITH_WX #define IF_SEG_REG_GET(x) \ if (!strcmp(param->get_name(), #x)) { \ return BX_CPU(cpu)->sregs[BX_SEG_REG_##x].selector.value; \ } #define IF_SEG_REG_SET(reg, val) \ if (!strcmp(param->get_name(), #reg)) { \ BX_CPU(cpu)->load_seg_reg(&BX_CPU(cpu)->sregs[BX_SEG_REG_##reg],val); \ } #define IF_LAZY_EFLAG_GET(flag) \ if (!strcmp(param->get_name(), #flag)) { \ return BX_CPU(cpu)->get_##flag(); \ } #define IF_LAZY_EFLAG_SET(flag, val) \ if (!strcmp(param->get_name(), #flag)) { \ BX_CPU(cpu)->set_##flag(val); \ } #define IF_EFLAG_GET(flag) \ if (!strcmp(param->get_name(), #flag)) { \ return BX_CPU(cpu)->get_##flag(); \ } #define IF_EFLAG_SET(flag, val) \ if (!strcmp(param->get_name(), #flag)) { \ BX_CPU(cpu)->set_##flag(val); \ } // implement get/set handler for parameters that need unusual set/get static Bit64s cpu_param_handler(bx_param_c *param, int set, Bit64s val) { #if BX_SUPPORT_SMP int cpu = atoi(param->get_parent()->get_name()); #endif if (set) { if (!strcmp(param->get_name(), "LDTR")) { BX_CPU(cpu)->panic("setting LDTR not implemented"); } if (!strcmp(param->get_name(), "TR")) { BX_CPU(cpu)->panic("setting LDTR not implemented"); } IF_SEG_REG_SET(CS, val); IF_SEG_REG_SET(DS, val); IF_SEG_REG_SET(SS, val); IF_SEG_REG_SET(ES, val); IF_SEG_REG_SET(FS, val); IF_SEG_REG_SET(GS, val); IF_LAZY_EFLAG_SET(OF, val); IF_LAZY_EFLAG_SET(SF, val); IF_LAZY_EFLAG_SET(ZF, val); IF_LAZY_EFLAG_SET(AF, val); IF_LAZY_EFLAG_SET(PF, val); IF_LAZY_EFLAG_SET(CF, val); IF_EFLAG_SET(ID, val); IF_EFLAG_SET(VIP, val); IF_EFLAG_SET(VIF, val); IF_EFLAG_SET(AC, val); IF_EFLAG_SET(VM, val); IF_EFLAG_SET(RF, val); IF_EFLAG_SET(NT, val); IF_EFLAG_SET(IOPL, val); IF_EFLAG_SET(DF, val); IF_EFLAG_SET(IF, val); IF_EFLAG_SET(TF, val); } else { if (!strcmp(param->get_name(), "LDTR")) { return BX_CPU(cpu)->ldtr.selector.value; } if (!strcmp(param->get_name(), "TR")) { return BX_CPU(cpu)->tr.selector.value; } IF_SEG_REG_GET (CS); IF_SEG_REG_GET (DS); IF_SEG_REG_GET (SS); IF_SEG_REG_GET (ES); IF_SEG_REG_GET (FS); IF_SEG_REG_GET (GS); IF_LAZY_EFLAG_GET(OF); IF_LAZY_EFLAG_GET(SF); IF_LAZY_EFLAG_GET(ZF); IF_LAZY_EFLAG_GET(AF); IF_LAZY_EFLAG_GET(PF); IF_LAZY_EFLAG_GET(CF); IF_EFLAG_GET(ID); IF_EFLAG_GET(VIP); IF_EFLAG_GET(VIF); IF_EFLAG_GET(AC); IF_EFLAG_GET(VM); IF_EFLAG_GET(RF); IF_EFLAG_GET(NT); IF_EFLAG_GET(IOPL); IF_EFLAG_GET(DF); IF_EFLAG_GET(IF); IF_EFLAG_GET(TF); } return val; } #undef IF_SEG_REG_GET #undef IF_SEG_REG_SET #endif #if BX_CPU_LEVEL >= 4 #include "generic_cpuid.h" #define bx_define_cpudb(model) \ extern bx_cpuid_t *create_ ##model##_cpuid(BX_CPU_C *cpu); #include "cpudb.h" #undef bx_define_cpudb static bx_cpuid_t *cpuid_factory(BX_CPU_C *cpu) { unsigned cpu_model = SIM->get_param_enum(BXPN_CPU_MODEL)->get(); #define bx_define_cpudb(model) \ case bx_cpudb_##model: \ return create_ ##model##_cpuid(cpu); switch(cpu_model) { #include "cpudb.h" default: return 0; } #undef bx_define_cpudb } #endif // BX_CPU_C constructor void BX_CPU_C::initialize(void) { BX_CPU_THIS_PTR set_INTR(0); #if BX_CPU_LEVEL >= 4 BX_CPU_THIS_PTR cpuid = cpuid_factory(this); if (! BX_CPU_THIS_PTR cpuid) BX_PANIC(("Failed to create CPUID module !")); BX_CPU_THIS_PTR isa_extensions_bitmask = cpuid->get_isa_extensions_bitmask(); BX_CPU_THIS_PTR cpu_extensions_bitmask = cpuid->get_cpu_extensions_bitmask(); #if BX_SUPPORT_VMX BX_CPU_THIS_PTR vmx_extensions_bitmask = cpuid->get_vmx_extensions_bitmask(); #endif #if BX_SUPPORT_SVM BX_CPU_THIS_PTR svm_extensions_bitmask = cpuid->get_svm_extensions_bitmask(); #endif #endif init_FetchDecodeTables(); // must be called after init_isa_features_bitmask() #if BX_CONFIGURE_MSRS for (unsigned n=0; n < BX_MSR_MAX_INDEX; n++) { BX_CPU_THIS_PTR msrs[n] = 0; } const char *msrs_filename = SIM->get_param_string(BXPN_CONFIGURABLE_MSRS_PATH)->getptr(); load_MSRs(msrs_filename); #endif // ignore bad MSRS if user asked for it #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR ignore_bad_msrs = SIM->get_param_bool(BXPN_IGNORE_BAD_MSRS)->get(); #endif init_SMRAM(); #if BX_SUPPORT_VMX init_VMCS(); #endif #if BX_WITH_WX register_wx_state(); #endif } #if BX_WITH_WX void BX_CPU_C::register_wx_state(void) { if (SIM->get_param(BXPN_WX_CPU_STATE) != NULL) { // Register some of the CPUs variables as shadow parameters so that // they can be visible in the config interface. // (Experimental, obviously not a complete list) bx_param_num_c *param; char cpu_name[10], cpu_title[10], cpu_pname[16]; const char *fmt16 = "%04X"; const char *fmt32 = "%08X"; Bit32u oldbase = bx_param_num_c::set_default_base(16); const char *oldfmt = bx_param_num_c::set_default_format(fmt32); sprintf(cpu_name, "%d", BX_CPU_ID); sprintf(cpu_title, "CPU %d", BX_CPU_ID); sprintf(cpu_pname, "%s.%d", BXPN_WX_CPU_STATE, BX_CPU_ID); if (SIM->get_param(cpu_pname) == NULL) { bx_list_c *list = new bx_list_c(SIM->get_param(BXPN_WX_CPU_STATE), cpu_name, cpu_title); #define DEFPARAM_NORMAL(name,field) \ new bx_shadow_num_c(list, #name, &(field)) DEFPARAM_NORMAL(EAX, EAX); DEFPARAM_NORMAL(EBX, EBX); DEFPARAM_NORMAL(ECX, ECX); DEFPARAM_NORMAL(EDX, EDX); DEFPARAM_NORMAL(ESP, ESP); DEFPARAM_NORMAL(EBP, EBP); DEFPARAM_NORMAL(ESI, ESI); DEFPARAM_NORMAL(EDI, EDI); DEFPARAM_NORMAL(EIP, EIP); DEFPARAM_NORMAL(DR0, dr[0]); DEFPARAM_NORMAL(DR1, dr[1]); DEFPARAM_NORMAL(DR2, dr[2]); DEFPARAM_NORMAL(DR3, dr[3]); DEFPARAM_NORMAL(DR6, dr6.val32); DEFPARAM_NORMAL(DR7, dr7.val32); DEFPARAM_NORMAL(CR0, cr0.val32); DEFPARAM_NORMAL(CR2, cr2); DEFPARAM_NORMAL(CR3, cr3); #if BX_CPU_LEVEL >= 5 DEFPARAM_NORMAL(CR4, cr4.val32); #endif // segment registers require a handler function because they have // special get/set requirements. #define DEFPARAM_SEG_REG(x) \ param = new bx_param_num_c(list, \ #x, #x, "", 0, 0xffff, 0); \ param->set_handler(cpu_param_handler); \ param->set_format(fmt16); #define DEFPARAM_GLOBAL_SEG_REG(name,field) \ param = new bx_shadow_num_c(list, \ #name"_base", &(field.base)); \ param = new bx_shadow_num_c(list, \ #name"_limit", &(field.limit)); DEFPARAM_SEG_REG(CS); DEFPARAM_SEG_REG(DS); DEFPARAM_SEG_REG(SS); DEFPARAM_SEG_REG(ES); DEFPARAM_SEG_REG(FS); DEFPARAM_SEG_REG(GS); DEFPARAM_SEG_REG(LDTR); DEFPARAM_SEG_REG(TR); DEFPARAM_GLOBAL_SEG_REG(GDTR, BX_CPU_THIS_PTR gdtr); DEFPARAM_GLOBAL_SEG_REG(IDTR, BX_CPU_THIS_PTR idtr); #undef DEFPARAM_NORMAL #undef DEFPARAM_SEG_REG #undef DEFPARAM_GLOBAL_SEG_REG param = new bx_shadow_num_c(list, "EFLAGS", &BX_CPU_THIS_PTR eflags); // flags implemented in lazy_flags.cc must be done with a handler // that calls their get function, to force them to be computed. #define DEFPARAM_EFLAG(name) \ param = new bx_param_bool_c(list, \ #name, #name, "", get_##name()); \ param->set_handler(cpu_param_handler); #define DEFPARAM_LAZY_EFLAG(name) \ param = new bx_param_bool_c(list, \ #name, #name, "", get_##name()); \ param->set_handler(cpu_param_handler); #if BX_CPU_LEVEL >= 4 DEFPARAM_EFLAG(ID); DEFPARAM_EFLAG(VIP); DEFPARAM_EFLAG(VIF); DEFPARAM_EFLAG(AC); #endif #if BX_CPU_LEVEL >= 3 DEFPARAM_EFLAG(VM); DEFPARAM_EFLAG(RF); #endif #if BX_CPU_LEVEL >= 2 DEFPARAM_EFLAG(NT); // IOPL is a special case because it is 2 bits wide. param = new bx_shadow_num_c( list, "IOPL", &BX_CPU_THIS_PTR eflags, 10, 12, 13); param->set_range(0, 3); param->set_format("%d"); #endif DEFPARAM_LAZY_EFLAG(OF); DEFPARAM_EFLAG(DF); DEFPARAM_EFLAG(IF); DEFPARAM_EFLAG(TF); DEFPARAM_LAZY_EFLAG(SF); DEFPARAM_LAZY_EFLAG(ZF); DEFPARAM_LAZY_EFLAG(AF); DEFPARAM_LAZY_EFLAG(PF); DEFPARAM_LAZY_EFLAG(CF); // restore defaults bx_param_num_c::set_default_base(oldbase); bx_param_num_c::set_default_format(oldfmt); } } } #endif // save/restore functionality void BX_CPU_C::register_state(void) { unsigned n; char name[10]; sprintf(name, "cpu%d", BX_CPU_ID); bx_list_c *cpu = new bx_list_c(SIM->get_bochs_root(), name, name); BXRS_HEX_PARAM_SIMPLE(cpu, isa_extensions_bitmask); BXRS_HEX_PARAM_SIMPLE(cpu, cpu_extensions_bitmask); #if BX_SUPPORT_VMX BXRS_HEX_PARAM_SIMPLE(cpu, vmx_extensions_bitmask); #endif #if BX_SUPPORT_SVM BXRS_HEX_PARAM_SIMPLE(cpu, svm_extensions_bitmask); #endif BXRS_DEC_PARAM_SIMPLE(cpu, cpu_mode); BXRS_HEX_PARAM_SIMPLE(cpu, activity_state); BXRS_HEX_PARAM_SIMPLE(cpu, inhibit_mask); BXRS_HEX_PARAM_SIMPLE(cpu, inhibit_icount); BXRS_HEX_PARAM_SIMPLE(cpu, debug_trap); BXRS_DEC_PARAM_SIMPLE(cpu, icount); BXRS_DEC_PARAM_SIMPLE(cpu, icount_last_sync); #if BX_SUPPORT_X86_64 BXRS_HEX_PARAM_SIMPLE(cpu, RAX); BXRS_HEX_PARAM_SIMPLE(cpu, RBX); BXRS_HEX_PARAM_SIMPLE(cpu, RCX); BXRS_HEX_PARAM_SIMPLE(cpu, RDX); BXRS_HEX_PARAM_SIMPLE(cpu, RSP); BXRS_HEX_PARAM_SIMPLE(cpu, RBP); BXRS_HEX_PARAM_SIMPLE(cpu, RSI); BXRS_HEX_PARAM_SIMPLE(cpu, RDI); BXRS_HEX_PARAM_SIMPLE(cpu, R8); BXRS_HEX_PARAM_SIMPLE(cpu, R9); BXRS_HEX_PARAM_SIMPLE(cpu, R10); BXRS_HEX_PARAM_SIMPLE(cpu, R11); BXRS_HEX_PARAM_SIMPLE(cpu, R12); BXRS_HEX_PARAM_SIMPLE(cpu, R13); BXRS_HEX_PARAM_SIMPLE(cpu, R14); BXRS_HEX_PARAM_SIMPLE(cpu, R15); BXRS_HEX_PARAM_SIMPLE(cpu, RIP); #else BXRS_HEX_PARAM_SIMPLE(cpu, EAX); BXRS_HEX_PARAM_SIMPLE(cpu, EBX); BXRS_HEX_PARAM_SIMPLE(cpu, ECX); BXRS_HEX_PARAM_SIMPLE(cpu, EDX); BXRS_HEX_PARAM_SIMPLE(cpu, ESP); BXRS_HEX_PARAM_SIMPLE(cpu, EBP); BXRS_HEX_PARAM_SIMPLE(cpu, ESI); BXRS_HEX_PARAM_SIMPLE(cpu, EDI); BXRS_HEX_PARAM_SIMPLE(cpu, EIP); #endif BXRS_PARAM_SPECIAL32(cpu, EFLAGS, param_save_handler, param_restore_handler); #if BX_CPU_LEVEL >= 3 BXRS_HEX_PARAM_FIELD(cpu, DR0, dr[0]); BXRS_HEX_PARAM_FIELD(cpu, DR1, dr[1]); BXRS_HEX_PARAM_FIELD(cpu, DR2, dr[2]); BXRS_HEX_PARAM_FIELD(cpu, DR3, dr[3]); BXRS_HEX_PARAM_FIELD(cpu, DR6, dr6.val32); BXRS_HEX_PARAM_FIELD(cpu, DR7, dr7.val32); #endif BXRS_HEX_PARAM_FIELD(cpu, CR0, cr0.val32); BXRS_HEX_PARAM_FIELD(cpu, CR2, cr2); BXRS_HEX_PARAM_FIELD(cpu, CR3, cr3); #if BX_CPU_LEVEL >= 5 BXRS_HEX_PARAM_FIELD(cpu, CR4, cr4.val32); #endif #if BX_CPU_LEVEL >= 6 if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVE)) { BXRS_HEX_PARAM_FIELD(cpu, XCR0, xcr0.val32); } #endif #if BX_CPU_LEVEL >= 5 BXRS_HEX_PARAM_FIELD(cpu, tsc_last_reset, tsc_last_reset); #if BX_SUPPORT_VMX || BX_SUPPORT_SVM BXRS_HEX_PARAM_FIELD(cpu, tsc_offset, tsc_offset); #endif #endif for(n=0; n<6; n++) { bx_segment_reg_t *segment = &BX_CPU_THIS_PTR sregs[n]; bx_list_c *sreg = new bx_list_c(cpu, strseg(segment)); BXRS_PARAM_SPECIAL16(sreg, selector, param_save_handler, param_restore_handler); BXRS_HEX_PARAM_FIELD(sreg, valid, segment->cache.valid); BXRS_PARAM_BOOL(sreg, p, segment->cache.p); BXRS_HEX_PARAM_FIELD(sreg, dpl, segment->cache.dpl); BXRS_PARAM_BOOL(sreg, segment, segment->cache.segment); BXRS_HEX_PARAM_FIELD(sreg, type, segment->cache.type); BXRS_HEX_PARAM_FIELD(sreg, base, segment->cache.u.segment.base); BXRS_HEX_PARAM_FIELD(sreg, limit_scaled, segment->cache.u.segment.limit_scaled); BXRS_PARAM_BOOL(sreg, granularity, segment->cache.u.segment.g); BXRS_PARAM_BOOL(sreg, d_b, segment->cache.u.segment.d_b); #if BX_SUPPORT_X86_64 BXRS_PARAM_BOOL(sreg, l, segment->cache.u.segment.l); #endif BXRS_PARAM_BOOL(sreg, avl, segment->cache.u.segment.avl); } bx_list_c *GDTR = new bx_list_c(cpu, "GDTR"); BXRS_HEX_PARAM_FIELD(GDTR, base, gdtr.base); BXRS_HEX_PARAM_FIELD(GDTR, limit, gdtr.limit); bx_list_c *IDTR = new bx_list_c(cpu, "IDTR"); BXRS_HEX_PARAM_FIELD(IDTR, base, idtr.base); BXRS_HEX_PARAM_FIELD(IDTR, limit, idtr.limit); bx_list_c *LDTR = new bx_list_c(cpu, "LDTR"); BXRS_PARAM_SPECIAL16(LDTR, selector, param_save_handler, param_restore_handler); BXRS_HEX_PARAM_FIELD(LDTR, valid, ldtr.cache.valid); BXRS_PARAM_BOOL(LDTR, p, ldtr.cache.p); BXRS_HEX_PARAM_FIELD(LDTR, dpl, ldtr.cache.dpl); BXRS_PARAM_BOOL(LDTR, segment, ldtr.cache.segment); BXRS_HEX_PARAM_FIELD(LDTR, type, ldtr.cache.type); BXRS_HEX_PARAM_FIELD(LDTR, base, ldtr.cache.u.segment.base); BXRS_HEX_PARAM_FIELD(LDTR, limit_scaled, ldtr.cache.u.segment.limit_scaled); BXRS_PARAM_BOOL(LDTR, granularity, ldtr.cache.u.segment.g); BXRS_PARAM_BOOL(LDTR, d_b, ldtr.cache.u.segment.d_b); BXRS_PARAM_BOOL(LDTR, avl, ldtr.cache.u.segment.avl); bx_list_c *TR = new bx_list_c(cpu, "TR"); BXRS_PARAM_SPECIAL16(TR, selector, param_save_handler, param_restore_handler); BXRS_HEX_PARAM_FIELD(TR, valid, tr.cache.valid); BXRS_PARAM_BOOL(TR, p, tr.cache.p); BXRS_HEX_PARAM_FIELD(TR, dpl, tr.cache.dpl); BXRS_PARAM_BOOL(TR, segment, tr.cache.segment); BXRS_HEX_PARAM_FIELD(TR, type, tr.cache.type); BXRS_HEX_PARAM_FIELD(TR, base, tr.cache.u.segment.base); BXRS_HEX_PARAM_FIELD(TR, limit_scaled, tr.cache.u.segment.limit_scaled); BXRS_PARAM_BOOL(TR, granularity, tr.cache.u.segment.g); BXRS_PARAM_BOOL(TR, d_b, tr.cache.u.segment.d_b); BXRS_PARAM_BOOL(TR, avl, tr.cache.u.segment.avl); BXRS_HEX_PARAM_SIMPLE(cpu, smbase); #if BX_CPU_LEVEL >= 6 bx_list_c *PDPTRS = new bx_list_c(cpu, "PDPTR_CACHE"); BXRS_HEX_PARAM_FIELD(PDPTRS, entry0, PDPTR_CACHE.entry[0]); BXRS_HEX_PARAM_FIELD(PDPTRS, entry1, PDPTR_CACHE.entry[1]); BXRS_HEX_PARAM_FIELD(PDPTRS, entry2, PDPTR_CACHE.entry[2]); BXRS_HEX_PARAM_FIELD(PDPTRS, entry3, PDPTR_CACHE.entry[3]); #endif #if BX_CPU_LEVEL >= 5 bx_list_c *MSR = new bx_list_c(cpu, "MSR"); #if BX_SUPPORT_APIC BXRS_HEX_PARAM_FIELD(MSR, apicbase, msr.apicbase); #endif BXRS_HEX_PARAM_FIELD(MSR, EFER, efer.val32); BXRS_HEX_PARAM_FIELD(MSR, star, msr.star); #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) { BXRS_HEX_PARAM_FIELD(MSR, lstar, msr.lstar); BXRS_HEX_PARAM_FIELD(MSR, cstar, msr.cstar); BXRS_HEX_PARAM_FIELD(MSR, fmask, msr.fmask); BXRS_HEX_PARAM_FIELD(MSR, kernelgsbase, msr.kernelgsbase); BXRS_HEX_PARAM_FIELD(MSR, tsc_aux, msr.tsc_aux); } #endif #if BX_CPU_LEVEL >= 6 BXRS_HEX_PARAM_FIELD(MSR, sysenter_cs_msr, msr.sysenter_cs_msr); BXRS_HEX_PARAM_FIELD(MSR, sysenter_esp_msr, msr.sysenter_esp_msr); BXRS_HEX_PARAM_FIELD(MSR, sysenter_eip_msr, msr.sysenter_eip_msr); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase0, msr.mtrrphys[0]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask0, msr.mtrrphys[1]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase1, msr.mtrrphys[2]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask1, msr.mtrrphys[3]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase2, msr.mtrrphys[4]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask2, msr.mtrrphys[5]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase3, msr.mtrrphys[6]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask3, msr.mtrrphys[7]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase4, msr.mtrrphys[8]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask4, msr.mtrrphys[9]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase5, msr.mtrrphys[10]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask5, msr.mtrrphys[11]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase6, msr.mtrrphys[12]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask6, msr.mtrrphys[13]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysbase7, msr.mtrrphys[14]); BXRS_HEX_PARAM_FIELD(MSR, mtrrphysmask7, msr.mtrrphys[15]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix64k_00000, msr.mtrrfix64k_00000); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix16k_80000, msr.mtrrfix16k[0]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix16k_a0000, msr.mtrrfix16k[1]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_c0000, msr.mtrrfix4k[0]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_c8000, msr.mtrrfix4k[1]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_d0000, msr.mtrrfix4k[2]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_d8000, msr.mtrrfix4k[3]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_e0000, msr.mtrrfix4k[4]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_e8000, msr.mtrrfix4k[5]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_f0000, msr.mtrrfix4k[6]); BXRS_HEX_PARAM_FIELD(MSR, mtrrfix4k_f8000, msr.mtrrfix4k[7]); BXRS_HEX_PARAM_FIELD(MSR, pat, msr.pat); BXRS_HEX_PARAM_FIELD(MSR, mtrr_deftype, msr.mtrr_deftype); #endif #if BX_CONFIGURE_MSRS bx_list_c *MSRS = new bx_list_c(cpu, "USER_MSR"); for(n=0; n < BX_MSR_MAX_INDEX; n++) { if (! msrs[n]) continue; sprintf(name, "msr_0x%03x", n); bx_list_c *m = new bx_list_c(MSRS, name); BXRS_HEX_PARAM_FIELD(m, index, msrs[n]->index); BXRS_DEC_PARAM_FIELD(m, type, msrs[n]->type); BXRS_HEX_PARAM_FIELD(m, val64, msrs[n]->val64); BXRS_HEX_PARAM_FIELD(m, reset, msrs[n]->reset_value); BXRS_HEX_PARAM_FIELD(m, reserved, msrs[n]->reserved); BXRS_HEX_PARAM_FIELD(m, ignored, msrs[n]->ignored); } #endif #endif #if BX_SUPPORT_FPU bx_list_c *fpu = new bx_list_c(cpu, "FPU"); BXRS_HEX_PARAM_FIELD(fpu, cwd, the_i387.cwd); BXRS_HEX_PARAM_FIELD(fpu, swd, the_i387.swd); BXRS_HEX_PARAM_FIELD(fpu, twd, the_i387.twd); BXRS_HEX_PARAM_FIELD(fpu, foo, the_i387.foo); BXRS_HEX_PARAM_FIELD(fpu, fcs, the_i387.fcs); BXRS_HEX_PARAM_FIELD(fpu, fip, the_i387.fip); BXRS_HEX_PARAM_FIELD(fpu, fds, the_i387.fds); BXRS_HEX_PARAM_FIELD(fpu, fdp, the_i387.fdp); for (n=0; n<8; n++) { sprintf(name, "st%d", n); bx_list_c *STx = new bx_list_c(fpu, name); BXRS_HEX_PARAM_FIELD(STx, exp, the_i387.st_space[n].exp); BXRS_HEX_PARAM_FIELD(STx, fraction, the_i387.st_space[n].fraction); } BXRS_DEC_PARAM_FIELD(fpu, tos, the_i387.tos); #endif #if BX_CPU_LEVEL >= 6 if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE)) { bx_list_c *sse = new bx_list_c(cpu, "SSE"); BXRS_HEX_PARAM_FIELD(sse, mxcsr, mxcsr.mxcsr); for (n=0; n= 5 BXRS_PARAM_BOOL(tlb, split_large, TLB.split_large); #endif for (n=0; nparam_save(param); } Bit64s BX_CPU_C::param_save(bx_param_c *param) { #else UNUSED(devptr); #endif // !BX_USE_CPU_SMF const char *pname, *segname; bx_segment_reg_t *segment = NULL; Bit64s val = 0; pname = param->get_name(); if (!strcmp(pname, "EFLAGS")) { val = read_eflags(); } else if (!strcmp(pname, "selector")) { segname = param->get_parent()->get_name(); if (!strcmp(segname, "CS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]; } else if (!strcmp(segname, "DS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; } else if (!strcmp(segname, "SS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]; } else if (!strcmp(segname, "ES")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]; } else if (!strcmp(segname, "FS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]; } else if (!strcmp(segname, "GS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS]; } else if (!strcmp(segname, "LDTR")) { segment = &BX_CPU_THIS_PTR ldtr; } else if (!strcmp(segname, "TR")) { segment = &BX_CPU_THIS_PTR tr; } if (segment != NULL) { val = segment->selector.value; } } else { BX_PANIC(("Unknown param %s in param_save handler !", pname)); } return val; } void BX_CPU_C::param_restore_handler(void *devptr, bx_param_c *param, Bit64s val) { #if !BX_USE_CPU_SMF BX_CPU_C *class_ptr = (BX_CPU_C *) devptr; class_ptr->param_restore(param, val); } void BX_CPU_C::param_restore(bx_param_c *param, Bit64s val) { #else UNUSED(devptr); #endif // !BX_USE_CPU_SMF const char *pname, *segname; bx_segment_reg_t *segment = NULL; pname = param->get_name(); if (!strcmp(pname, "EFLAGS")) { BX_CPU_THIS_PTR setEFlags((Bit32u)val); } else if (!strcmp(pname, "selector")) { segname = param->get_parent()->get_name(); if (!strcmp(segname, "CS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]; } else if (!strcmp(segname, "DS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; } else if (!strcmp(segname, "SS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]; } else if (!strcmp(segname, "ES")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]; } else if (!strcmp(segname, "FS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]; } else if (!strcmp(segname, "GS")) { segment = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS]; } else if (!strcmp(segname, "LDTR")) { segment = &BX_CPU_THIS_PTR ldtr; } else if (!strcmp(segname, "TR")) { segment = &BX_CPU_THIS_PTR tr; } if (segment != NULL) { bx_selector_t *selector = &(segment->selector); parse_selector((Bit16u)val, selector); } } else { BX_PANIC(("Unknown param %s in param_restore handler !", pname)); } } void BX_CPU_C::after_restore_state(void) { handleCpuContextChange(); BX_CPU_THIS_PTR prev_rip = RIP; if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_IA32_REAL) CPL = 0; else { if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_IA32_V8086) CPL = 3; } #if BX_SUPPORT_VMX set_VMCSPTR(BX_CPU_THIS_PTR vmcsptr); #endif assert_checks(); debug(RIP); } // end of save/restore functionality BX_CPU_C::~BX_CPU_C() { #if BX_CPU_LEVEL >= 4 delete cpuid; #endif BX_INSTR_EXIT(BX_CPU_ID); BX_DEBUG(("Exit.")); } void BX_CPU_C::reset(unsigned source) { unsigned n; if (source == BX_RESET_HARDWARE) BX_INFO(("cpu hardware reset")); else if (source == BX_RESET_SOFTWARE) BX_INFO(("cpu software reset")); else BX_INFO(("cpu reset")); for (n=0;n= 3 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 0; /* byte granular */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0; /* 16bit default size */ #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 16bit default size */ #endif BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; #endif flushICaches(); /* DS (Data Segment) and descriptor cache */ parse_selector(0x0000, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xFFFF; #if BX_CPU_LEVEL >= 3 BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.avl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g = 0; /* byte granular */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 0; /* 16bit default size */ #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.l = 0; /* 16bit default size */ #endif #endif // use DS segment as template for the others BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; #if BX_CPU_LEVEL >= 3 BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; #endif /* GDTR (Global Descriptor Table Register) */ BX_CPU_THIS_PTR gdtr.base = 0x00000000; BX_CPU_THIS_PTR gdtr.limit = 0xFFFF; /* IDTR (Interrupt Descriptor Table Register) */ BX_CPU_THIS_PTR idtr.base = 0x00000000; BX_CPU_THIS_PTR idtr.limit = 0xFFFF; /* always byte granular */ /* LDTR (Local Descriptor Table Register) */ BX_CPU_THIS_PTR ldtr.selector.value = 0x0000; BX_CPU_THIS_PTR ldtr.selector.index = 0x0000; BX_CPU_THIS_PTR ldtr.selector.ti = 0; BX_CPU_THIS_PTR ldtr.selector.rpl = 0; BX_CPU_THIS_PTR ldtr.cache.valid = 1; /* valid */ BX_CPU_THIS_PTR ldtr.cache.p = 1; /* present */ BX_CPU_THIS_PTR ldtr.cache.dpl = 0; /* field not used */ BX_CPU_THIS_PTR ldtr.cache.segment = 0; /* system segment */ BX_CPU_THIS_PTR ldtr.cache.type = BX_SYS_SEGMENT_LDT; BX_CPU_THIS_PTR ldtr.cache.u.segment.base = 0x00000000; BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled = 0xFFFF; BX_CPU_THIS_PTR ldtr.cache.u.segment.avl = 0; BX_CPU_THIS_PTR ldtr.cache.u.segment.g = 0; /* byte granular */ /* TR (Task Register) */ BX_CPU_THIS_PTR tr.selector.value = 0x0000; BX_CPU_THIS_PTR tr.selector.index = 0x0000; /* undefined */ BX_CPU_THIS_PTR tr.selector.ti = 0; BX_CPU_THIS_PTR tr.selector.rpl = 0; BX_CPU_THIS_PTR tr.cache.valid = 1; /* valid */ BX_CPU_THIS_PTR tr.cache.p = 1; /* present */ BX_CPU_THIS_PTR tr.cache.dpl = 0; /* field not used */ BX_CPU_THIS_PTR tr.cache.segment = 0; /* system segment */ BX_CPU_THIS_PTR tr.cache.type = BX_SYS_SEGMENT_BUSY_386_TSS; BX_CPU_THIS_PTR tr.cache.u.segment.base = 0x00000000; BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled = 0xFFFF; BX_CPU_THIS_PTR tr.cache.u.segment.avl = 0; BX_CPU_THIS_PTR tr.cache.u.segment.g = 0; /* byte granular */ BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_REAL; // DR0 - DR7 (Debug Registers) #if BX_CPU_LEVEL >= 3 for (n=0; n<4; n++) BX_CPU_THIS_PTR dr[n] = 0; #endif #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR dr6.val32 = 0xFFFF0FF0; #else BX_CPU_THIS_PTR dr6.val32 = 0xFFFF1FF0; #endif BX_CPU_THIS_PTR dr7.val32 = 0x00000400; #if BX_X86_DEBUGGER BX_CPU_THIS_PTR in_repeat = 0; BX_CPU_THIS_PTR codebp = 0; #endif BX_CPU_THIS_PTR in_smm = 0; BX_CPU_THIS_PTR disable_SMI = 0; BX_CPU_THIS_PTR pending_SMI = 0; BX_CPU_THIS_PTR disable_NMI = 0; BX_CPU_THIS_PTR pending_NMI = 0; BX_CPU_THIS_PTR disable_INIT = 0; BX_CPU_THIS_PTR pending_INIT = 0; if (source == BX_RESET_HARDWARE) { BX_CPU_THIS_PTR smbase = 0x30000; // do not change SMBASE on INIT } BX_CPU_THIS_PTR cr0.set32(0x60000010); // handle reserved bits #if BX_CPU_LEVEL == 3 // reserved bits all set to 1 on 386 BX_CPU_THIS_PTR cr0.val32 |= 0x7ffffff0; #endif #if BX_CPU_LEVEL >= 3 BX_CPU_THIS_PTR cr2 = 0; BX_CPU_THIS_PTR cr3 = 0; #endif #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR cr4.set32(0); BX_CPU_THIS_PTR cr4_suppmask = get_cr4_allow_mask(); #endif #if BX_CPU_LEVEL >= 6 BX_CPU_THIS_PTR xcr0.set32(0x1); BX_CPU_THIS_PTR xcr0_suppmask = 0x3; #if BX_SUPPORT_AVX if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX)) BX_CPU_THIS_PTR xcr0_suppmask |= BX_XCR0_AVX_MASK; #endif #endif /* initialise MSR registers to defaults */ #if BX_CPU_LEVEL >= 5 #if BX_SUPPORT_APIC /* APIC Address, APIC enabled and BSP is default, we'll fill in the rest later */ BX_CPU_THIS_PTR msr.apicbase = BX_LAPIC_BASE_ADDR; BX_CPU_THIS_PTR lapic.reset(source); BX_CPU_THIS_PTR msr.apicbase |= 0x900; BX_CPU_THIS_PTR lapic.set_base(BX_CPU_THIS_PTR msr.apicbase); #if BX_CPU_LEVEL >= 6 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_XAPIC_EXT)) BX_CPU_THIS_PTR lapic.enable_xapic_extensions(); #endif #endif BX_CPU_THIS_PTR efer.set32(0); BX_CPU_THIS_PTR efer_suppmask = 0; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_NX)) BX_CPU_THIS_PTR efer_suppmask |= BX_EFER_NXE_MASK; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SYSCALL_SYSRET_LEGACY)) BX_CPU_THIS_PTR efer_suppmask |= BX_EFER_SCE_MASK; #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) { BX_CPU_THIS_PTR efer_suppmask |= (BX_EFER_SCE_MASK | BX_EFER_LME_MASK | BX_EFER_LMA_MASK); if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_FFXSR)) BX_CPU_THIS_PTR efer_suppmask |= BX_EFER_FFXSR_MASK; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SVM)) BX_CPU_THIS_PTR efer_suppmask |= BX_EFER_SVME_MASK; } #endif BX_CPU_THIS_PTR msr.star = 0; #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) { BX_CPU_THIS_PTR msr.lstar = 0; BX_CPU_THIS_PTR msr.cstar = 0; BX_CPU_THIS_PTR msr.fmask = 0x00020200; BX_CPU_THIS_PTR msr.kernelgsbase = 0; BX_CPU_THIS_PTR msr.tsc_aux = 0; } #endif #if BX_SUPPORT_VMX || BX_SUPPORT_SVM BX_CPU_THIS_PTR tsc_offset = 0; #endif if (source == BX_RESET_HARDWARE) { BX_CPU_THIS_PTR set_TSC(0); // do not change TSC on INIT } #endif // BX_CPU_LEVEL >= 5 #if BX_CPU_LEVEL >= 6 BX_CPU_THIS_PTR msr.sysenter_cs_msr = 0; BX_CPU_THIS_PTR msr.sysenter_esp_msr = 0; BX_CPU_THIS_PTR msr.sysenter_eip_msr = 0; #endif // Do not change MTRR on INIT #if BX_CPU_LEVEL >= 6 if (source == BX_RESET_HARDWARE) { for (n=0; n<16; n++) BX_CPU_THIS_PTR msr.mtrrphys[n] = 0; BX_CPU_THIS_PTR msr.mtrrfix64k_00000 = 0; // all fix range MTRRs undefined according to manual BX_CPU_THIS_PTR msr.mtrrfix16k[0] = 0; BX_CPU_THIS_PTR msr.mtrrfix16k[1] = 0; for (n=0; n<8; n++) BX_CPU_THIS_PTR msr.mtrrfix4k[n] = 0; BX_CPU_THIS_PTR msr.pat = BX_CONST64(0x0007040600070406); BX_CPU_THIS_PTR msr.mtrr_deftype = BX_CONST64(0x806); } #endif // All configurable MSRs do not change on INIT #if BX_CONFIGURE_MSRS if (source == BX_RESET_HARDWARE) { for (n=0; n < BX_MSR_MAX_INDEX; n++) { if (BX_CPU_THIS_PTR msrs[n]) BX_CPU_THIS_PTR msrs[n]->reset(); } } #endif BX_CPU_THIS_PTR EXT = 0; BX_CPU_THIS_PTR errorno = 0; // invalidate the code prefetch queue BX_CPU_THIS_PTR eipPageBias = 0; BX_CPU_THIS_PTR eipPageWindowSize = 0; BX_CPU_THIS_PTR eipFetchPtr = NULL; // invalidate current stack page BX_CPU_THIS_PTR espPageBias = 0; BX_CPU_THIS_PTR espPageWindowSize = 0; BX_CPU_THIS_PTR espHostPtr = NULL; #if BX_DEBUGGER BX_CPU_THIS_PTR stop_reason = STOP_NO_REASON; BX_CPU_THIS_PTR magic_break = 0; BX_CPU_THIS_PTR trace = 0; BX_CPU_THIS_PTR trace_reg = 0; BX_CPU_THIS_PTR trace_mem = 0; BX_CPU_THIS_PTR mode_break = 0; #if BX_SUPPORT_VMX BX_CPU_THIS_PTR vmexit_break = 0; #endif #endif // Reset the Floating Point Unit #if BX_SUPPORT_FPU if (source == BX_RESET_HARDWARE) { BX_CPU_THIS_PTR the_i387.reset(); } #endif #if BX_CPU_LEVEL >= 6 BX_CPU_THIS_PTR sse_ok = 0; #if BX_SUPPORT_AVX BX_CPU_THIS_PTR avx_ok = 0; #endif // Reset XMM state - unchanged on #INIT if (source == BX_RESET_HARDWARE) { static BxPackedXmmRegister xmmnil; /* compiler will clear the variable */ for(n=0; n= 2 BX_CPU_THIS_PTR pending_vmx_timer_expired = 0; #endif BX_CPU_THIS_PTR vmcsptr = BX_CPU_THIS_PTR vmxonptr = BX_INVALID_VMCSPTR; BX_CPU_THIS_PTR vmcshostptr = 0; /* enable VMX, should be done in BIOS instead */ BX_CPU_THIS_PTR msr.ia32_feature_ctrl = /*BX_IA32_FEATURE_CONTROL_LOCK_BIT | */BX_IA32_FEATURE_CONTROL_VMX_ENABLE_BIT; #endif #if BX_SUPPORT_SVM BX_CPU_THIS_PTR in_svm_guest = 0; BX_CPU_THIS_PTR svm_gif = 1; BX_CPU_THIS_PTR vmcbptr = 0; BX_CPU_THIS_PTR vmcbhostptr = 0; #endif #if BX_SUPPORT_VMX || BX_SUPPORT_SVM BX_CPU_THIS_PTR in_event = 0; #endif #if BX_SUPPORT_SMP // notice if I'm the bootstrap processor. If not, do the equivalent of // a HALT instruction. int apic_id = lapic.get_id(); if (BX_BOOTSTRAP_PROCESSOR == apic_id) { // boot normally BX_CPU_THIS_PTR msr.apicbase |= 0x0100; /* set bit 8 BSP */ BX_INFO(("CPU[%d] is the bootstrap processor", apic_id)); } else { // it's an application processor, halt until IPI is heard. BX_CPU_THIS_PTR msr.apicbase &= ~0x0100; /* clear bit 8 BSP */ BX_INFO(("CPU[%d] is an application processor. Halting until IPI.", apic_id)); activity_state = BX_ACTIVITY_STATE_WAIT_FOR_SIPI; disable_INIT = 1; // INIT is disabled when CPU is waiting for SIPI async_event = 1; } #endif handleCpuContextChange(); #if BX_CPU_LEVEL >= 4 BX_CPU_THIS_PTR cpuid->dump_cpuid(); #endif BX_INSTR_RESET(BX_CPU_ID, source); } void BX_CPU_C::sanity_checks(void) { Bit32u eax = EAX, ecx = ECX, edx = EDX, ebx = EBX, esp = ESP, ebp = EBP, esi = ESI, edi = EDI; EAX = 0xFFEEDDCC; ECX = 0xBBAA9988; EDX = 0x77665544; EBX = 0x332211FF; ESP = 0xEEDDCCBB; EBP = 0xAA998877; ESI = 0x66554433; EDI = 0x2211FFEE; Bit8u al, cl, dl, bl, ah, ch, dh, bh; al = AL; cl = CL; dl = DL; bl = BL; ah = AH; ch = CH; dh = DH; bh = BH; if ( al != (EAX & 0xFF) || cl != (ECX & 0xFF) || dl != (EDX & 0xFF) || bl != (EBX & 0xFF) || ah != ((EAX >> 8) & 0xFF) || ch != ((ECX >> 8) & 0xFF) || dh != ((EDX >> 8) & 0xFF) || bh != ((EBX >> 8) & 0xFF) ) { BX_PANIC(("problems using BX_READ_8BIT_REGx()!")); } Bit16u ax, cx, dx, bx, sp, bp, si, di; ax = AX; cx = CX; dx = DX; bx = BX; sp = SP; bp = BP; si = SI; di = DI; if ( ax != (EAX & 0xFFFF) || cx != (ECX & 0xFFFF) || dx != (EDX & 0xFFFF) || bx != (EBX & 0xFFFF) || sp != (ESP & 0xFFFF) || bp != (EBP & 0xFFFF) || si != (ESI & 0xFFFF) || di != (EDI & 0xFFFF) ) { BX_PANIC(("problems using BX_READ_16BIT_REG()!")); } EAX = eax; /* restore registers */ ECX = ecx; EDX = edx; EBX = ebx; ESP = esp; EBP = ebp; ESI = esi; EDI = edi; if (sizeof(Bit8u) != 1 || sizeof(Bit8s) != 1) BX_PANIC(("data type Bit8u or Bit8s is not of length 1 byte!")); if (sizeof(Bit16u) != 2 || sizeof(Bit16s) != 2) BX_PANIC(("data type Bit16u or Bit16s is not of length 2 bytes!")); if (sizeof(Bit32u) != 4 || sizeof(Bit32s) != 4) BX_PANIC(("data type Bit32u or Bit32s is not of length 4 bytes!")); if (sizeof(Bit64u) != 8 || sizeof(Bit64s) != 8) BX_PANIC(("data type Bit64u or Bit64u is not of length 8 bytes!")); BX_DEBUG(("#(%u)all sanity checks passed!", BX_CPU_ID)); } void BX_CPU_C::assert_checks(void) { // check CPU mode consistency #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR efer.get_LMA()) { if (! BX_CPU_THIS_PTR cr0.get_PE()) { BX_PANIC(("assert_checks: EFER.LMA is set when CR0.PE=0 !")); } if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l) { if (BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64) BX_PANIC(("assert_checks: unconsistent cpu_mode BX_MODE_LONG_64 !")); } else { if (BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_COMPAT) BX_PANIC(("assert_checks: unconsistent cpu_mode BX_MODE_LONG_COMPAT !")); } } else #endif { if (BX_CPU_THIS_PTR cr0.get_PE()) { if (BX_CPU_THIS_PTR get_VM()) { if (BX_CPU_THIS_PTR cpu_mode != BX_MODE_IA32_V8086) BX_PANIC(("assert_checks: unconsistent cpu_mode BX_MODE_IA32_V8086 !")); } else { if (BX_CPU_THIS_PTR cpu_mode != BX_MODE_IA32_PROTECTED) BX_PANIC(("assert_checks: unconsistent cpu_mode BX_MODE_IA32_PROTECTED !")); } } else { if (BX_CPU_THIS_PTR cpu_mode != BX_MODE_IA32_REAL) BX_PANIC(("assert_checks: unconsistent cpu_mode BX_MODE_IA32_REAL !")); } } // check CR0 consistency if (! check_CR0(BX_CPU_THIS_PTR cr0.val32)) BX_PANIC(("assert_checks: CR0 consistency checks failed !")); #if BX_CPU_LEVEL >= 5 // check CR4 consistency if (! check_CR4(BX_CPU_THIS_PTR cr4.val32)) BX_PANIC(("assert_checks: CR4 consistency checks failed !")); #endif #if BX_SUPPORT_X86_64 // VM should be OFF in long mode if (long_mode()) { if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("assert_checks: VM is set in long mode !")); } // CS.L and CS.D_B are mutualy exclusive if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l && BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b) { BX_PANIC(("assert_checks: CS.l and CS.d_b set together !")); } #endif // check LDTR type if (BX_CPU_THIS_PTR ldtr.cache.valid) { if (BX_CPU_THIS_PTR ldtr.cache.type != BX_SYS_SEGMENT_LDT) { BX_PANIC(("assert_checks: LDTR is not LDT type !")); } } // check Task Register type if(BX_CPU_THIS_PTR tr.cache.valid) { switch(BX_CPU_THIS_PTR tr.cache.type) { case BX_SYS_SEGMENT_BUSY_286_TSS: case BX_SYS_SEGMENT_AVAIL_286_TSS: #if BX_CPU_LEVEL >= 3 if (BX_CPU_THIS_PTR tr.cache.u.segment.g != 0) BX_PANIC(("assert_checks: tss286.g != 0 !")); if (BX_CPU_THIS_PTR tr.cache.u.segment.avl != 0) BX_PANIC(("assert_checks: tss286.avl != 0 !")); #endif break; case BX_SYS_SEGMENT_BUSY_386_TSS: case BX_SYS_SEGMENT_AVAIL_386_TSS: break; default: BX_PANIC(("assert_checks: TR is not TSS type !")); } } #if BX_SUPPORT_X86_64 == 0 && BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR efer_suppmask & (BX_EFER_SCE_MASK | BX_EFER_LME_MASK | BX_EFER_LMA_MASK | BX_EFER_FFXSR_MASK)) { BX_PANIC(("assert_checks: EFER supports x86-64 specific bits !")); } #endif } bochs-2.6/cpu/load.cc0000644000175000017500000001152512020641453014353 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: load.cc 11356 2012-08-21 19:58:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Eb(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); TMP8L = read_virtual_byte(i->seg(), eaddr); return BX_CPU_CALL_METHOD(i->execute2(), (i)); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Ew(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); TMP16 = read_virtual_word(i->seg(), eaddr); return BX_CPU_CALL_METHOD(i->execute2(), (i)); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Ed(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); TMP32 = read_virtual_dword(i->seg(), eaddr); return BX_CPU_CALL_METHOD(i->execute2(), (i)); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Eq(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); TMP64 = read_virtual_qword_64(i->seg(), eaddr); return BX_CPU_CALL_METHOD(i->execute2(), (i)); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Wb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u val_8 = read_virtual_byte(i->seg(), eaddr); BX_WRITE_XMM_REG_LO_BYTE(BX_TMP_REGISTER, val_8); return BX_CPU_CALL_METHOD(i->execute2(), (i)); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Ww(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u val_16 = read_virtual_word(i->seg(), eaddr); BX_WRITE_XMM_REG_LO_WORD(BX_TMP_REGISTER, val_16); return BX_CPU_CALL_METHOD(i->execute2(), (i)); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Wss(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u val_32 = read_virtual_dword(i->seg(), eaddr); BX_WRITE_XMM_REG_LO_DWORD(BX_TMP_REGISTER, val_32); return BX_CPU_CALL_METHOD(i->execute2(), (i)); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Wsd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u val_64 = read_virtual_qword(i->seg(), eaddr); BX_WRITE_XMM_REG_LO_QWORD(BX_TMP_REGISTER, val_64); return BX_CPU_CALL_METHOD(i->execute2(), (i)); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Wdq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_MISALIGNED_SSE if (BX_CPU_THIS_PTR mxcsr.get_MM()) read_virtual_dqword(i->seg(), eaddr, &BX_READ_XMM_REG(BX_TMP_REGISTER)); else #endif read_virtual_dqword_aligned(i->seg(), eaddr, &BX_READ_XMM_REG(BX_TMP_REGISTER)); return BX_CPU_CALL_METHOD(i->execute2(), (i)); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOADU_Wdq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword(i->seg(), eaddr, &BX_READ_XMM_REG(BX_TMP_REGISTER)); return BX_CPU_CALL_METHOD(i->execute2(), (i)); #endif } #if BX_SUPPORT_AVX BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_Vector(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dword_vector(i->seg(), eaddr, i->getVL() << 2, &BX_READ_AVX_REG(BX_TMP_REGISTER)); return BX_CPU_CALL_METHOD(i->execute2(), (i)); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOAD_VectorQ(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dword_vector(i->seg(), eaddr, i->getVL() << 1, &BX_READ_AVX_REG(BX_TMP_REGISTER)); return BX_CPU_CALL_METHOD(i->execute2(), (i)); } #endif bochs-2.6/cpu/proc_ctrl.cc0000644000175000017500000012573012020641453015427 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: proc_ctrl.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "param_names.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::UndefinedOpcode(bxInstruction_c *i) { BX_DEBUG(("UndefinedOpcode: generate #UD exception")); exception(BX_UD_EXCEPTION, 0); BX_NEXT_TRACE(i); // keep compiler happy } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOP(bxInstruction_c *i) { // No operation. BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PAUSE(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_PAUSE(); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_PAUSE)) Svm_Vmexit(SVM_VMEXIT_PAUSE); } #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PREFETCH(bxInstruction_c *i) { #if BX_INSTRUMENTATION BX_INSTR_PREFETCH_HINT(BX_CPU_ID, i->src(), i->seg(), BX_CPU_CALL_METHODR(i->ResolveModrm, (i))); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CPUID(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 4 #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { BX_DEBUG(("VMEXIT: CPUID in VMX non-root operation")); VMexit(VMX_VMEXIT_CPUID, 0); } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_CPUID)) Svm_Vmexit(SVM_VMEXIT_CPUID); } #endif struct cpuid_function_t leaf; BX_CPU_THIS_PTR cpuid->get_cpuid_leaf(EAX, ECX, &leaf); RAX = leaf.eax; RBX = leaf.ebx; RCX = leaf.ecx; RDX = leaf.edx; #endif BX_NEXT_INSTR(i); } // // The shutdown state is very similar to the state following the exection // if HLT instruction. In this mode the processor stops executing // instructions until #NMI, #SMI, #RESET or #INIT is received. If // shutdown occurs why in NMI interrupt handler or in SMM, a hardware // reset must be used to restart the processor execution. // void BX_CPU_C::shutdown(void) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_SHUTDOWN)) Svm_Vmexit(SVM_VMEXIT_SHUTDOWN); } #endif BX_PANIC(("Entering to shutdown state still not implemented")); BX_CPU_THIS_PTR clear_IF(); // artificial trap bit, why use another variable. BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_HLT; BX_CPU_THIS_PTR async_event = 1; // so processor knows to check // Execution of this instruction completes. The processor // will remain in a halt state until one of the above conditions // is met. BX_INSTR_HLT(BX_CPU_ID); #if BX_DEBUGGER bx_dbg_halt(BX_CPU_ID); #endif #if BX_USE_IDLE_HACK bx_gui->sim_is_idle(); #endif longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::HLT(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_DEBUG(("HLT: %s priveledge check failed, CPL=%d, generate #GP(0)", cpu_mode_string(BX_CPU_THIS_PTR cpu_mode), CPL)); exception(BX_GP_EXCEPTION, 0); } if (! BX_CPU_THIS_PTR get_IF()) { BX_INFO(("WARNING: HLT instruction with IF=0!")); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (VMEXIT(VMX_VM_EXEC_CTRL2_HLT_VMEXIT)) { BX_DEBUG(("VMEXIT: HLT")); VMexit(VMX_VMEXIT_HLT, 0); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_HLT)) Svm_Vmexit(SVM_VMEXIT_HLT); } #endif // stops instruction execution and places the processor in a // HALT state. An enabled interrupt, NMI, or reset will resume // execution. If interrupt (including NMI) is used to resume // execution after HLT, the saved CS:eIP points to instruction // following HLT. // artificial trap bit, why use another variable. BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_HLT; BX_CPU_THIS_PTR async_event = 1; // so processor knows to check // Execution of this instruction completes. The processor // will remain in a halt state until one of the above conditions // is met. BX_INSTR_HLT(BX_CPU_ID); #if BX_DEBUGGER bx_dbg_halt(BX_CPU_ID); #endif #if BX_USE_IDLE_HACK bx_gui->sim_is_idle(); #endif BX_NEXT_TRACE(i); } /* 0F 08 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVD(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("INVD: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: INVD in VMX non-root operation")); VMexit(VMX_VMEXIT_INVD, 0); } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_INVD)) Svm_Vmexit(SVM_VMEXIT_INVD); } #endif invalidate_prefetch_q(); BX_DEBUG(("INVD: Flush internal caches !")); BX_INSTR_CACHE_CNTRL(BX_CPU_ID, BX_INSTR_INVD); flushICaches(); BX_NEXT_TRACE(i); } /* 0F 09 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::WBINVD(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("WBINVD: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_WBINVD_VMEXIT)) { BX_ERROR(("VMEXIT: WBINVD in VMX non-root operation")); VMexit(VMX_VMEXIT_WBINVD, 0); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_WBINVD)) Svm_Vmexit(SVM_VMEXIT_WBINVD); } #endif invalidate_prefetch_q(); BX_DEBUG(("WBINVD: Flush internal caches !")); BX_INSTR_CACHE_CNTRL(BX_CPU_ID, BX_INSTR_WBINVD); flushICaches(); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLFLUSH(bxInstruction_c *i) { bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[i->seg()]; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); bx_address laddr = get_laddr(i->seg(), eaddr); #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { if (! IsCanonical(laddr)) { BX_ERROR(("CLFLUSH: non-canonical access !")); exception(int_number(i->seg()), 0); } } else #endif { // check if we could access the memory segment if (!(seg->cache.valid & SegAccessROK)) { if (! execute_virtual_checks(seg, (Bit32u) eaddr, 1)) exception(int_number(i->seg()), 0); } else { if (eaddr > seg->cache.u.segment.limit_scaled) { BX_ERROR(("CLFLUSH: segment limit violation")); exception(int_number(i->seg()), 0); } } } #if BX_INSTRUMENTATION bx_phy_address paddr = #endif translate_linear(laddr, USER_PL, BX_READ); BX_INSTR_CLFLUSH(BX_CPU_ID, laddr, paddr); #if BX_X86_DEBUGGER hwbreakpoint_match(laddr, 1, BX_READ); #endif BX_NEXT_INSTR(i); } void BX_CPU_C::handleCpuModeChange(void) { unsigned mode = BX_CPU_THIS_PTR cpu_mode; #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR efer.get_LMA()) { if (! BX_CPU_THIS_PTR cr0.get_PE()) { BX_PANIC(("change_cpu_mode: EFER.LMA is set when CR0.PE=0 !")); } if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l) { BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_64; } else { BX_CPU_THIS_PTR cpu_mode = BX_MODE_LONG_COMPAT; // clear upper part of RIP/RSP when leaving 64-bit long mode BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RIP); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSP); } // switching between compatibility and long64 mode also affect SS.BASE // which is always zero in long64 mode invalidate_stack_cache(); } else #endif { if (BX_CPU_THIS_PTR cr0.get_PE()) { if (BX_CPU_THIS_PTR get_VM()) { BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_V8086; CPL = 3; } else BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_PROTECTED; } else { BX_CPU_THIS_PTR cpu_mode = BX_MODE_IA32_REAL; // CS segment in real mode always allows full access BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_DATA_READ_WRITE_ACCESSED; CPL = 0; } } updateFetchModeMask(); #if BX_CPU_LEVEL >= 6 #if BX_SUPPORT_AVX handleAvxModeChange(); /* protected mode reloaded */ #endif #endif if (mode != BX_CPU_THIS_PTR cpu_mode) { BX_DEBUG(("%s activated", cpu_mode_string(BX_CPU_THIS_PTR cpu_mode))); #if BX_DEBUGGER if (BX_CPU_THIS_PTR mode_break) { BX_CPU_THIS_PTR stop_reason = STOP_MODE_BREAK_POINT; bx_debug_break(); // trap into debugger } #endif } } #if BX_CPU_LEVEL >= 4 void BX_CPU_C::handleAlignmentCheck(void) { if (CPL == 3 && BX_CPU_THIS_PTR cr0.get_AM() && BX_CPU_THIS_PTR get_AC()) { #if BX_SUPPORT_ALIGNMENT_CHECK == 0 BX_PANIC(("WARNING: Alignment check (#AC exception) was not compiled in !")); #else BX_CPU_THIS_PTR alignment_check_mask = 0xF; #endif } #if BX_SUPPORT_ALIGNMENT_CHECK else { BX_CPU_THIS_PTR alignment_check_mask = 0; } #endif } #endif #if BX_CPU_LEVEL >= 6 void BX_CPU_C::handleSseModeChange(void) { if(BX_CPU_THIS_PTR cr0.get_TS()) { BX_CPU_THIS_PTR sse_ok = 0; } else { if(BX_CPU_THIS_PTR cr0.get_EM() || !BX_CPU_THIS_PTR cr4.get_OSFXSR()) BX_CPU_THIS_PTR sse_ok = 0; else BX_CPU_THIS_PTR sse_ok = 1; } updateFetchModeMask(); /* SSE_OK changed */ } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BxNoSSE(bxInstruction_c *i) { if(BX_CPU_THIS_PTR cr0.get_EM() || !BX_CPU_THIS_PTR cr4.get_OSFXSR()) exception(BX_UD_EXCEPTION, 0); if(BX_CPU_THIS_PTR cr0.get_TS()) exception(BX_NM_EXCEPTION, 0); BX_ASSERT(0); BX_NEXT_TRACE(i); // keep compiler happy } #if BX_SUPPORT_AVX void BX_CPU_C::handleAvxModeChange(void) { if(BX_CPU_THIS_PTR cr0.get_TS()) { BX_CPU_THIS_PTR avx_ok = 0; } else { if (! protected_mode() || ! BX_CPU_THIS_PTR cr4.get_OSXSAVE() || (~BX_CPU_THIS_PTR xcr0.val32 & 0x6) != 0) BX_CPU_THIS_PTR avx_ok = 0; else BX_CPU_THIS_PTR avx_ok = 1; } updateFetchModeMask(); /* AVX_OK changed */ } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BxNoAVX(bxInstruction_c *i) { if (! protected_mode() || ! BX_CPU_THIS_PTR cr4.get_OSXSAVE()) exception(BX_UD_EXCEPTION, 0); if (~BX_CPU_THIS_PTR xcr0.val32 & 0x6) exception(BX_UD_EXCEPTION, 0); if(BX_CPU_THIS_PTR cr0.get_TS()) exception(BX_NM_EXCEPTION, 0); BX_ASSERT(0); BX_NEXT_TRACE(i); // keep compiler happy } #endif #endif void BX_CPU_C::handleCpuContextChange(void) { TLB_flush(); invalidate_prefetch_q(); invalidate_stack_cache(); #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(); #endif handleCpuModeChange(); #if BX_CPU_LEVEL >= 6 handleSseModeChange(); #if BX_SUPPORT_AVX handleAvxModeChange(); #endif #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDPMC(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 if (! BX_CPU_THIS_PTR cr4.get_PCE() && CPL != 0 ) { BX_ERROR(("RDPMC: not allowed to use instruction !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (VMEXIT(VMX_VM_EXEC_CTRL2_RDPMC_VMEXIT)) { BX_DEBUG(("VMEXIT: RDPMC")); VMexit(VMX_VMEXIT_RDPMC, 0); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_RDPMC)) Svm_Vmexit(SVM_VMEXIT_RDPMC); } #endif /* According to manual, Pentium 4 has 18 counters, * previous versions have two. And the P4 also can do * short read-out (EDX always 0). Otherwise it is * limited to 40 bits. */ if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE2)) { // Pentium 4 processor (see cpuid.cc) if ((ECX & 0x7fffffff) >= 18) exception(BX_GP_EXCEPTION, 0); } else { if ((ECX & 0xffffffff) >= 2) exception(BX_GP_EXCEPTION, 0); } // Most counters are for hardware specific details, which // we anyhow do not emulate (like pipeline stalls etc) // Could be interesting to count number of memory reads, // writes. Misaligned etc... But to monitor bochs, this // is easier done from the host. RAX = 0; RDX = 0; // if P4 and ECX & 0x10000000, then always 0 (short read 32 bits) BX_ERROR(("RDPMC: Performance Counters Support not implemented yet")); #endif BX_NEXT_INSTR(i); } #if BX_CPU_LEVEL >= 5 Bit64u BX_CPU_C::get_TSC(void) { Bit64u tsc = bx_pc_system.time_ticks() - BX_CPU_THIS_PTR tsc_last_reset; #if BX_SUPPORT_VMX || BX_SUPPORT_SVM tsc += BX_CPU_THIS_PTR tsc_offset; #endif return tsc; } void BX_CPU_C::set_TSC(Bit64u newval) { // compute the correct setting of tsc_last_reset so that a get_TSC() // will return newval BX_CPU_THIS_PTR tsc_last_reset = bx_pc_system.time_ticks() - newval; // verify BX_ASSERT(get_TSC() == newval); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDTSC(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_TSD() && CPL != 0) { BX_ERROR(("RDTSC: not allowed to use instruction !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (VMEXIT(VMX_VM_EXEC_CTRL2_RDTSC_VMEXIT)) { BX_DEBUG(("VMEXIT: RDTSC")); VMexit(VMX_VMEXIT_RDTSC, 0); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) if (SVM_INTERCEPT(SVM_INTERCEPT0_RDTSC)) Svm_Vmexit(SVM_VMEXIT_RDTSC); #endif // return ticks Bit64u ticks = BX_CPU_THIS_PTR get_TSC(); RAX = GET32L(ticks); RDX = GET32H(ticks); BX_DEBUG(("RDTSC: ticks 0x%08x:%08x", EDX, EAX)); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDTSCP(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 #if BX_SUPPORT_VMX // RDTSCP will always #UD in legacy VMX mode if (BX_CPU_THIS_PTR in_vmx_guest) { if (! SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_RDTSCP)) { BX_ERROR(("RDTSCP in VMX guest: not allowed to use instruction !")); exception(BX_UD_EXCEPTION, 0); } } #endif if (BX_CPU_THIS_PTR cr4.get_TSD() && CPL != 0) { BX_ERROR(("RDTSCP: not allowed to use instruction !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (VMEXIT(VMX_VM_EXEC_CTRL2_RDTSC_VMEXIT)) { BX_DEBUG(("VMEXIT: RDTSCP")); VMexit(VMX_VMEXIT_RDTSCP, 0); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) if (SVM_INTERCEPT(SVM_INTERCEPT1_RDTSCP)) Svm_Vmexit(SVM_VMEXIT_RDTSCP); #endif // return ticks Bit64u ticks = BX_CPU_THIS_PTR get_TSC(); RAX = GET32L(ticks); RDX = GET32H(ticks); RCX = MSR_TSC_AUX; #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_MONITOR_MWAIT bx_bool BX_CPU_C::is_monitor(bx_phy_address begin_addr, unsigned len) { if (! BX_CPU_THIS_PTR monitor.armed) return 0; bx_phy_address monitor_begin = BX_CPU_THIS_PTR monitor.monitor_addr; bx_phy_address monitor_end = monitor_begin + CACHE_LINE_SIZE - 1; bx_phy_address end_addr = begin_addr + len; if (begin_addr >= monitor_end || end_addr <= monitor_begin) return 0; else return 1; } void BX_CPU_C::check_monitor(bx_phy_address begin_addr, unsigned len) { if (is_monitor(begin_addr, len)) { // wakeup from MWAIT state if(BX_CPU_THIS_PTR activity_state >= BX_ACTIVITY_STATE_MWAIT) BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_ACTIVE; // clear monitor BX_CPU_THIS_PTR monitor.reset_monitor(); } } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MONITOR(bxInstruction_c *i) { #if BX_SUPPORT_MONITOR_MWAIT // CPL is always 0 in real mode if (/* !real_mode() && */ CPL != 0) { BX_DEBUG(("MWAIT instruction not recognized when CPL != 0")); exception(BX_UD_EXCEPTION, 0); } BX_DEBUG(("MONITOR instruction executed EAX = 0x%08x", EAX)); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (VMEXIT(VMX_VM_EXEC_CTRL2_MONITOR_VMEXIT)) { BX_DEBUG(("VMEXIT: MONITOR")); VMexit(VMX_VMEXIT_MONITOR, 0); } } #endif if (RCX != 0) { BX_ERROR(("MONITOR: no optional extensions supported")); exception(BX_GP_EXCEPTION, 0); } bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[i->seg()]; bx_address offset = RAX & i->asize_mask(); // set MONITOR bx_address laddr = get_laddr(i->seg(), offset); #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { if (! IsCanonical(laddr)) { BX_ERROR(("MONITOR: non-canonical access !")); exception(int_number(i->seg()), 0); } } else #endif { // check if we could access the memory segment if (!(seg->cache.valid & SegAccessROK)) { if (! execute_virtual_checks(seg, (Bit32u) offset, 1)) exception(int_number(i->seg()), 0); } else { if (offset > seg->cache.u.segment.limit_scaled) { BX_ERROR(("MONITOR: segment limit violation")); exception(int_number(i->seg()), 0); } } } bx_phy_address paddr = translate_linear(laddr, USER_PL, BX_READ); #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_MONITOR)) Svm_Vmexit(SVM_VMEXIT_MONITOR); } #endif // Set the monitor immediately. If monitor is still armed when we MWAIT, // the processor will stall. bx_pc_system.invlpg(paddr); BX_CPU_THIS_PTR monitor.arm(paddr); BX_DEBUG(("MONITOR for phys_addr=0x" FMT_PHY_ADDRX, BX_CPU_THIS_PTR monitor.monitor_addr)); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MWAIT(bxInstruction_c *i) { #if BX_SUPPORT_MONITOR_MWAIT // CPL is always 0 in real mode if (/* !real_mode() && */ CPL != 0) { BX_DEBUG(("MWAIT instruction not recognized when CPL != 0")); exception(BX_UD_EXCEPTION, 0); } BX_DEBUG(("MWAIT instruction executed ECX = 0x%08x", ECX)); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (VMEXIT(VMX_VM_EXEC_CTRL2_MWAIT_VMEXIT)) { BX_DEBUG(("VMEXIT: MWAIT")); VMexit(VMX_VMEXIT_MWAIT, BX_CPU_THIS_PTR monitor.armed); } } #endif // only one extension is supported // ECX[0] - interrupt MWAIT even if EFLAGS.IF = 0 if (RCX & ~(BX_CONST64(1))) { BX_ERROR(("MWAIT: incorrect optional extensions in RCX")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_MWAIT_ARMED)) if (BX_CPU_THIS_PTR monitor.armed) Svm_Vmexit(SVM_VMEXIT_MWAIT_CONDITIONAL); if (SVM_INTERCEPT(SVM_INTERCEPT1_MWAIT)) Svm_Vmexit(SVM_VMEXIT_MWAIT); } #endif // If monitor has already triggered, we just return. if (! BX_CPU_THIS_PTR monitor.armed) { BX_DEBUG(("MWAIT: the MONITOR was not armed or already triggered")); BX_NEXT_TRACE(i); } static bx_bool mwait_is_nop = SIM->get_param_bool(BXPN_MWAIT_IS_NOP)->get(); if (mwait_is_nop) { BX_NEXT_TRACE(i); } // stops instruction execution and places the processor in a optimized // state. Events that cause exit from MWAIT state are: // A store from another processor to monitored range, any unmasked // interrupt, including INTR, NMI, SMI, INIT or reset will resume // the execution. Any far control transfer between MONITOR and MWAIT // resets the monitoring logic. if (ECX & 1) { #if BX_SUPPORT_VMX // When "interrupt window exiting" VMX control is set MWAIT instruction // won't cause the processor to enter BX_ACTIVITY_STATE_MWAIT_IF sleep // state with EFLAGS.IF = 0 if (BX_CPU_THIS_PTR vmx_interrupt_window && ! BX_CPU_THIS_PTR get_IF()) { BX_NEXT_TRACE(i); } #endif BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_MWAIT_IF; } else { BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_MWAIT; } BX_CPU_THIS_PTR async_event = 1; // so processor knows to check // Execution of this instruction completes. The processor // will remain in a optimized state until one of the above // conditions is met. BX_INSTR_MWAIT(BX_CPU_ID, BX_CPU_THIS_PTR monitor.monitor_addr, CACHE_LINE_SIZE, ECX); #if BX_USE_IDLE_HACK bx_gui->sim_is_idle(); #endif #if BX_DEBUGGER bx_dbg_halt(BX_CPU_ID); #endif #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SYSENTER(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 if (real_mode()) { BX_ERROR(("SYSENTER not recognized in real mode !")); exception(BX_GP_EXCEPTION, 0); } if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) { BX_ERROR(("SYSENTER with zero sysenter_cs_msr !")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); BX_CPU_THIS_PTR clear_VM(); // do this just like the book says to do BX_CPU_THIS_PTR clear_IF(); BX_CPU_THIS_PTR clear_RF(); #if BX_SUPPORT_X86_64 if (long_mode()) { if (!IsCanonical(BX_CPU_THIS_PTR msr.sysenter_eip_msr)) { BX_ERROR(("SYSENTER with non-canonical SYSENTER_EIP_MSR !")); exception(BX_GP_EXCEPTION, 0); } if (!IsCanonical(BX_CPU_THIS_PTR msr.sysenter_esp_msr)) { BX_ERROR(("SYSENTER with non-canonical SYSENTER_ESP_MSR !")); exception(BX_GP_EXCEPTION, 0); } } #endif parse_selector(BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; // base address BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // 4k granularity BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; // available for use by system BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = !long_mode(); #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = long_mode(); #endif #if BX_SUPPORT_X86_64 handleCpuModeChange(); // mode change could happen only when in long_mode() #else updateFetchModeMask(/* CS reloaded */); #endif #if BX_SUPPORT_ALIGNMENT_CHECK BX_CPU_THIS_PTR alignment_check_mask = 0; // CPL=0 #endif parse_selector((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 8) & BX_SELECTOR_RPL_MASK, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; // base address BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; // 4k granularity BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; // 32-bit mode BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; // available for use by system #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.l = 0; #endif #if BX_SUPPORT_X86_64 if (long_mode()) { RSP = BX_CPU_THIS_PTR msr.sysenter_esp_msr; RIP = BX_CPU_THIS_PTR msr.sysenter_eip_msr; } else #endif { ESP = (Bit32u) BX_CPU_THIS_PTR msr.sysenter_esp_msr; EIP = (Bit32u) BX_CPU_THIS_PTR msr.sysenter_eip_msr; } BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_SYSENTER, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SYSEXIT(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 if (real_mode() || CPL != 0) { BX_ERROR(("SYSEXIT from real mode or with CPL<>0 !")); exception(BX_GP_EXCEPTION, 0); } if ((BX_CPU_THIS_PTR msr.sysenter_cs_msr & BX_SELECTOR_RPL_MASK) == 0) { BX_ERROR(("SYSEXIT with zero sysenter_cs_msr !")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); #if BX_SUPPORT_X86_64 if (i->os64L()) { if (!IsCanonical(RDX)) { BX_ERROR(("SYSEXIT with non-canonical RDX (RIP) pointer !")); exception(BX_GP_EXCEPTION, 0); } if (!IsCanonical(RCX)) { BX_ERROR(("SYSEXIT with non-canonical RCX (RSP) pointer !")); exception(BX_GP_EXCEPTION, 0); } parse_selector(((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 32) & BX_SELECTOR_RPL_MASK) | 3, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; // base address BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // 4k granularity BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; // available for use by system BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 1; RSP = RCX; RIP = RDX; } else #endif { parse_selector(((BX_CPU_THIS_PTR msr.sysenter_cs_msr + 16) & BX_SELECTOR_RPL_MASK) | 3, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; // base address BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // 4k granularity BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; // available for use by system BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; #endif ESP = ECX; EIP = EDX; } #if BX_SUPPORT_X86_64 handleCpuModeChange(); // mode change could happen only when in long_mode() #else updateFetchModeMask(/* CS reloaded */); #endif handleAlignmentCheck(/* CPL change */); parse_selector(((BX_CPU_THIS_PTR msr.sysenter_cs_msr + (i->os64L() ? 40:24)) & BX_SELECTOR_RPL_MASK) | 3, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; // base address BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; // scaled segment limit BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; // 4k granularity BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; // 32-bit mode BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; // available for use by system #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.l = 0; #endif BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_SYSEXIT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SYSCALL(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 bx_address temp_RIP; BX_DEBUG(("Execute SYSCALL instruction")); if (!BX_CPU_THIS_PTR efer.get_SCE()) { exception(BX_UD_EXCEPTION, 0); } invalidate_prefetch_q(); #if BX_SUPPORT_X86_64 if (long_mode()) { RCX = RIP; R11 = read_eflags() & ~(EFlagsRFMask); if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { temp_RIP = MSR_LSTAR; } else { temp_RIP = MSR_CSTAR; } // set up CS segment, flat, 64-bit DPL=0 parse_selector((MSR_STAR >> 32) & BX_SELECTOR_RPL_MASK, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 1; /* 64-bit code */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */ handleCpuModeChange(); // mode change could only happen when in long_mode() #if BX_SUPPORT_ALIGNMENT_CHECK BX_CPU_THIS_PTR alignment_check_mask = 0; // CPL=0 #endif // set up SS segment, flat, 64-bit DPL=0 parse_selector(((MSR_STAR >> 32) + 8) & BX_SELECTOR_RPL_MASK, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; /* base address */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; /* 4k granularity */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; /* 32 bit stack */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.l = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; /* available for use by system */ writeEFlags(read_eflags() & (~MSR_FMASK), EFlagsValidMask); BX_CPU_THIS_PTR clear_RF(); RIP = temp_RIP; } else #endif { // legacy mode ECX = EIP; temp_RIP = MSR_STAR & 0xFFFFFFFF; // set up CS segment, flat, 32-bit DPL=0 parse_selector((MSR_STAR >> 32) & BX_SELECTOR_RPL_MASK, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 32-bit code */ #endif BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */ updateFetchModeMask(/* CS reloaded */); #if BX_SUPPORT_ALIGNMENT_CHECK BX_CPU_THIS_PTR alignment_check_mask = 0; // CPL=0 #endif // set up SS segment, flat, 32-bit DPL=0 parse_selector(((MSR_STAR >> 32) + 8) & BX_SELECTOR_RPL_MASK, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.base = 0; /* base address */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.g = 1; /* 4k granularity */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b = 1; /* 32 bit stack */ #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.l = 0; #endif BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.avl = 0; /* available for use by system */ BX_CPU_THIS_PTR clear_VM(); BX_CPU_THIS_PTR clear_IF(); BX_CPU_THIS_PTR clear_RF(); RIP = temp_RIP; } BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_SYSCALL, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SYSRET(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 bx_address temp_RIP; BX_DEBUG(("Execute SYSRET instruction")); if (!BX_CPU_THIS_PTR efer.get_SCE()) { exception(BX_UD_EXCEPTION, 0); } if(!protected_mode() || CPL != 0) { BX_ERROR(("SYSRET: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { if (i->os64L()) { if (!IsCanonical(RCX)) { BX_ERROR(("SYSRET: canonical failure for RCX (RIP)")); exception(BX_GP_EXCEPTION, 0); } // Return to 64-bit mode, set up CS segment, flat, 64-bit DPL=3 parse_selector((((MSR_STAR >> 48) + 16) & BX_SELECTOR_RPL_MASK) | 3, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 1; /* 64-bit code */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */ temp_RIP = RCX; } else { // Return to 32-bit compatibility mode, set up CS segment, flat, 32-bit DPL=3 parse_selector((MSR_STAR >> 48) | 3, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 32-bit code */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */ temp_RIP = ECX; } handleCpuModeChange(); // mode change could only happen when in long64 mode handleAlignmentCheck(/* CPL change */); // SS base, limit, attributes unchanged parse_selector((Bit16u)(((MSR_STAR >> 48) + 8) | 3), &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = BX_DATA_READ_WRITE_ACCESSED; writeEFlags((Bit32u) R11, EFlagsValidMask); } else // (!64BIT_MODE) #endif { // Return to 32-bit legacy mode, set up CS segment, flat, 32-bit DPL=3 parse_selector((MSR_STAR >> 48) | 3, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; /* base address */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF; /* scaled segment limit */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* 4k granularity */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 32-bit code */ #endif BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; /* available for use by system */ updateFetchModeMask(/* CS reloaded */); handleAlignmentCheck(/* CPL change */); // SS base, limit, attributes unchanged parse_selector((Bit16u)(((MSR_STAR >> 48) + 8) | 3), &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 3; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR assert_IF(); temp_RIP = ECX; } handleCpuModeChange(); RIP = temp_RIP; BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_SYSRET, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); #endif BX_NEXT_TRACE(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SWAPGS(bxInstruction_c *i) { if(CPL != 0) exception(BX_GP_EXCEPTION, 0); Bit64u temp_GS_base = MSR_GSBASE; MSR_GSBASE = MSR_KERNELGSBASE; MSR_KERNELGSBASE = temp_GS_base; BX_NEXT_INSTR(i); } /* F3 0F AE /0 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDFSBASE(bxInstruction_c *i) { if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE()) exception(BX_UD_EXCEPTION, 0); if (i->os64L()) { BX_WRITE_64BIT_REG(i->dst(), MSR_FSBASE); } else { BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) MSR_FSBASE); } BX_NEXT_INSTR(i); } /* F3 0F AE /1 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDGSBASE(bxInstruction_c *i) { if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE()) exception(BX_UD_EXCEPTION, 0); if (i->os64L()) { BX_WRITE_64BIT_REG(i->dst(), MSR_GSBASE); } else { BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) MSR_GSBASE); } BX_NEXT_INSTR(i); } /* F3 0F AE /2 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::WRFSBASE(bxInstruction_c *i) { if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE()) exception(BX_UD_EXCEPTION, 0); if (i->os64L()) { Bit64u fsbase = BX_READ_64BIT_REG(i->src()); if (!IsCanonical(fsbase)) { BX_ERROR(("WRFSBASE: canonical failure !")); exception(BX_GP_EXCEPTION, 0); } MSR_FSBASE = fsbase; } else { // 32-bit value is always canonical MSR_FSBASE = BX_READ_32BIT_REG(i->src()); } BX_NEXT_INSTR(i); } /* F3 0F AE /3 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::WRGSBASE(bxInstruction_c *i) { if (! BX_CPU_THIS_PTR cr4.get_FSGSBASE()) exception(BX_UD_EXCEPTION, 0); if (i->os64L()) { Bit64u gsbase = BX_READ_64BIT_REG(i->src()); if (!IsCanonical(gsbase)) { BX_ERROR(("WRGSBASE: canonical failure !")); exception(BX_GP_EXCEPTION, 0); } MSR_GSBASE = gsbase; } else { // 32-bit value is always canonical MSR_GSBASE = BX_READ_32BIT_REG(i->src()); } BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/vm8086.cc0000644000175000017500000002074112020641453014404 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vm8086.cc 11107 2012-03-25 19:07:17Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR // // Notes: // // The high bits of the 32bit eip image are ignored by // the IRET to VM. The high bits of the 32bit esp image // are loaded into ESP. A subsequent push uses // only the low 16bits since it's in VM. In neither case // did a protection fault occur during actual tests. This // is contrary to the Intel docs which claim a #GP for // eIP out of code limits. // // IRET to VM does affect IOPL, IF, VM, and RF // #if BX_CPU_LEVEL >= 3 void BX_CPU_C::stack_return_to_v86(Bit32u new_eip, Bit32u raw_cs_selector, Bit32u flags32) { Bit32u temp_ESP, new_esp; Bit16u raw_es_selector, raw_ds_selector, raw_fs_selector, raw_gs_selector, raw_ss_selector; // Must be 32bit effective opsize, VM is set in upper 16bits of eFLAGS // and CPL = 0 to get here // ---------------- // | | OLD GS | eSP+32 // | | OLD FS | eSP+28 // | | OLD DS | eSP+24 // | | OLD ES | eSP+20 // | | OLD SS | eSP+16 // | OLD ESP | eSP+12 // | OLD EFLAGS | eSP+8 // | | OLD CS | eSP+4 // | OLD EIP | eSP+0 // ---------------- if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) temp_ESP = ESP; else temp_ESP = SP; // load SS:ESP from stack new_esp = stack_read_dword(temp_ESP+12); raw_ss_selector = (Bit16u) stack_read_dword(temp_ESP+16); // load ES,DS,FS,GS from stack raw_es_selector = (Bit16u) stack_read_dword(temp_ESP+20); raw_ds_selector = (Bit16u) stack_read_dword(temp_ESP+24); raw_fs_selector = (Bit16u) stack_read_dword(temp_ESP+28); raw_gs_selector = (Bit16u) stack_read_dword(temp_ESP+32); writeEFlags(flags32, EFlagsValidMask); // load CS:IP from stack; already read and passed as args BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value = raw_cs_selector; EIP = new_eip & 0xffff; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = raw_es_selector; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value = raw_ds_selector; BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value = raw_fs_selector; BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value = raw_gs_selector; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value = raw_ss_selector; ESP = new_esp; // full 32 bit are loaded init_v8086_mode(); } #if BX_CPU_LEVEL >= 5 #define BX_CR4_VME_ENABLED (BX_CPU_THIS_PTR cr4.get_VME()) #else #define BX_CR4_VME_ENABLED (0) #endif void BX_CPU_C::iret16_stack_return_from_v86(bxInstruction_c *i) { if ((BX_CPU_THIS_PTR get_IOPL() < 3) && (BX_CR4_VME_ENABLED == 0)) { // trap to virtual 8086 monitor BX_DEBUG(("IRET in vm86 with IOPL != 3, VME = 0")); exception(BX_GP_EXCEPTION, 0); } Bit16u ip, cs_raw, flags16; ip = pop_16(); cs_raw = pop_16(); flags16 = pop_16(); #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_VME() && BX_CPU_THIS_PTR get_IOPL() < 3) { if (((flags16 & EFlagsIFMask) && BX_CPU_THIS_PTR get_VIP()) || (flags16 & EFlagsTFMask)) { BX_DEBUG(("iret16_stack_return_from_v86(): #GP(0) in VME mode")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = (Bit32u) ip; // IF, IOPL unchanged, EFLAGS.VIF = TMP_FLAGS.IF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask | EFlagsVIFMask; Bit32u flags32 = (Bit32u) flags16; if (flags16 & EFlagsIFMask) flags32 |= EFlagsVIFMask; writeEFlags(flags32, changeMask); return; } #endif load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = (Bit32u) ip; write_flags(flags16, /*IOPL*/ 0, /*IF*/ 1); } void BX_CPU_C::iret32_stack_return_from_v86(bxInstruction_c *i) { if (BX_CPU_THIS_PTR get_IOPL() < 3) { // trap to virtual 8086 monitor BX_DEBUG(("IRET in vm86 with IOPL != 3, VME = 0")); exception(BX_GP_EXCEPTION, 0); } Bit32u eip, cs_raw, flags32; // Build a mask of the following bits: // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u change_mask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsIFMask | EFlagsDFMask | EFlagsNTMask | EFlagsRFMask; #if BX_CPU_LEVEL >= 4 change_mask |= (EFlagsIDMask | EFlagsACMask); // ID/AC #endif eip = pop_32(); cs_raw = pop_32(); flags32 = pop_32(); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) cs_raw); EIP = eip; // VIF, VIP, VM, IOPL unchanged writeEFlags(flags32, change_mask); } int BX_CPU_C::v86_redirect_interrupt(Bit8u vector) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_VME()) { bx_address tr_base = BX_CPU_THIS_PTR tr.cache.u.segment.base; if (BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled < 103) { BX_ERROR(("v86_redirect_interrupt(): TR.limit < 103 in VME")); exception(BX_GP_EXCEPTION, 0); } Bit32u io_base = system_read_word(tr_base + 102), offset = io_base - 32 + (vector >> 3); if (offset > BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled) { BX_ERROR(("v86_redirect_interrupt(): failed to fetch VME redirection bitmap")); exception(BX_GP_EXCEPTION, 0); } Bit8u vme_redirection_bitmap = system_read_byte(tr_base + offset); if (!(vme_redirection_bitmap & (1 << (vector & 7)))) { // redirect interrupt through virtual-mode idt Bit16u temp_flags = (Bit16u) read_eflags(); Bit16u temp_CS = system_read_word(vector*4 + 2); Bit16u temp_IP = system_read_word(vector*4); if (BX_CPU_THIS_PTR get_IOPL() < 3) { temp_flags |= EFlagsIOPLMask; if (BX_CPU_THIS_PTR get_VIF()) temp_flags |= EFlagsIFMask; else temp_flags &= ~EFlagsIFMask; } Bit16u old_IP = IP; Bit16u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value; push_16(temp_flags); // push return address onto new stack push_16(old_CS); push_16(old_IP); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], (Bit16u) temp_CS); EIP = temp_IP; BX_CPU_THIS_PTR clear_TF(); BX_CPU_THIS_PTR clear_RF(); if (BX_CPU_THIS_PTR get_IOPL() == 3) BX_CPU_THIS_PTR clear_IF(); else BX_CPU_THIS_PTR clear_VIF(); return 1; } } #endif // interrupt is not redirected or VME is OFF if (BX_CPU_THIS_PTR get_IOPL() < 3) { BX_DEBUG(("v86_redirect_interrupt(): interrupt cannot be redirected, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0); } return 0; } void BX_CPU_C::init_v8086_mode(void) { for(unsigned sreg = 0; sreg < 6; sreg++) { BX_CPU_THIS_PTR sregs[sreg].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[sreg].cache.p = 1; BX_CPU_THIS_PTR sregs[sreg].cache.dpl = 3; BX_CPU_THIS_PTR sregs[sreg].cache.segment = 1; BX_CPU_THIS_PTR sregs[sreg].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[sreg].cache.u.segment.base = BX_CPU_THIS_PTR sregs[sreg].selector.value << 4; BX_CPU_THIS_PTR sregs[sreg].cache.u.segment.limit_scaled = 0xffff; BX_CPU_THIS_PTR sregs[sreg].cache.u.segment.g = 0; BX_CPU_THIS_PTR sregs[sreg].cache.u.segment.d_b = 0; BX_CPU_THIS_PTR sregs[sreg].cache.u.segment.avl = 0; BX_CPU_THIS_PTR sregs[sreg].selector.rpl = 3; } handleCpuModeChange(); #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(/* CPL change */); #endif invalidate_stack_cache(); } #endif /* BX_CPU_LEVEL >= 3 */ bochs-2.6/cpu/soft_int.cc0000644000175000017500000001157612020641453015267 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soft_int.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BOUND_GwMa(bxInstruction_c *i) { Bit16s op1_16 = BX_READ_16BIT_REG(i->dst()); Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16s bound_min = (Bit16s) read_virtual_word_32(i->seg(), eaddr); Bit16s bound_max = (Bit16s) read_virtual_word_32(i->seg(), (eaddr+2) & i->asize_mask()); if (op1_16 < bound_min || op1_16 > bound_max) { BX_INFO(("BOUND_GdMa: fails bounds test")); exception(BX_BR_EXCEPTION, 0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BOUND_GdMa(bxInstruction_c *i) { Bit32s op1_32 = BX_READ_32BIT_REG(i->dst()); Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32s bound_min = (Bit32s) read_virtual_dword_32(i->seg(), eaddr); Bit32s bound_max = (Bit32s) read_virtual_dword_32(i->seg(), (eaddr+4) & i->asize_mask()); if (op1_32 < bound_min || op1_32 > bound_max) { BX_INFO(("BOUND_GdMa: fails bounds test")); exception(BX_BR_EXCEPTION, 0); } BX_NEXT_INSTR(i); } // This is an undocumented instrucion (opcode 0xf1) which // is useful for an ICE system BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INT1(bxInstruction_c *i) { #if BX_SUPPORT_VMX VMexit_Event(BX_PRIVILEGED_SOFTWARE_INTERRUPT, 1, 0, 0); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT1_ICEBP)) Svm_Vmexit(SVM_VMEXIT_ICEBP); } #endif #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_softint; #endif BX_CPU_THIS_PTR EXT = 1; // interrupt is not RSP safe interrupt(1, BX_PRIVILEGED_SOFTWARE_INTERRUPT, 0, 0); BX_CPU_THIS_PTR EXT = 0; BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_INT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INT3(bxInstruction_c *i) { // INT 3 is not IOPL sensitive #if BX_SUPPORT_VMX VMexit_Event(BX_SOFTWARE_EXCEPTION, 3, 0, 0); #endif #if BX_SUPPORT_SVM SvmInterceptException(BX_SOFTWARE_EXCEPTION, 3, 0, 0); #endif #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_softint; #endif // interrupt is not RSP safe interrupt(3, BX_SOFTWARE_EXCEPTION, 0, 0); BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_INT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INT_Ib(bxInstruction_c *i) { Bit8u vector = i->Ib(); #if BX_SUPPORT_VMX VMexit_Event(BX_SOFTWARE_INTERRUPT, vector, 0, 0); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_SOFTINT)) Svm_Vmexit(SVM_VMEXIT_SOFTWARE_INTERRUPT); } #endif #ifdef SHOW_EXIT_STATUS if ((vector == 0x21) && (AH == 0x4c)) { BX_INFO(("INT 21/4C called AL=0x%02x, BX=0x%04x", (unsigned) AL, (unsigned) BX)); } #endif #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_softint; #endif interrupt(vector, BX_SOFTWARE_INTERRUPT, 0, 0); BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_INT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INTO(bxInstruction_c *i) { if (get_OF()) { #if BX_SUPPORT_VMX VMexit_Event(BX_SOFTWARE_EXCEPTION, 4, 0, 0); #endif #if BX_SUPPORT_SVM SvmInterceptException(BX_SOFTWARE_EXCEPTION, 4, 0, 0); #endif #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_softint; #endif // interrupt is not RSP safe interrupt(4, BX_SOFTWARE_EXCEPTION, 0, 0); BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_INT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); } BX_NEXT_TRACE(i); } bochs-2.6/cpu/Makefile.in0000644000175000017500000013130512020641453015171 0ustar guillemguillem# Copyright (C) 2001-2011 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ top_builddir = .. top_srcdir = @top_srcdir@ SHELL = @SHELL@ @SET_MAKE@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ X_LIBS = @X_LIBS@ X_PRE_LIBS = @X_PRE_LIBS@ RANLIB = @RANLIB@ BX_INCDIRS = -I.. -I$(srcdir)/.. -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@ # Objects which are synced between the cpu and cpu64 code and # are used for either compile. OBJS = \ init.o \ cpu.o \ event.o \ icache.o \ resolver.o \ fetchdecode.o \ access.o \ access32.o \ shift16.o \ logical16.o \ ctrl_xfer32.o \ ctrl_xfer16.o \ mmx.o \ 3dnow.o \ fpu_emu.o \ sse.o \ sse_move.o \ sse_pfp.o \ sse_rcp.o \ sse_string.o \ xsave.o \ aes.o \ svm.o \ vmx.o \ vmcs.o \ vmexit.o \ vmfunc.o \ soft_int.o \ apic.o \ bcd.o \ mult16.o \ tasking.o \ shift32.o \ shift8.o \ arith8.o \ stack.o \ stack16.o \ protect_ctrl.o \ mult8.o \ load.o \ data_xfer8.o \ vm8086.o \ logical8.o \ logical32.o \ arith16.o \ segment_ctrl.o \ data_xfer16.o \ data_xfer32.o \ exception.o \ generic_cpuid.o \ proc_ctrl.o \ crregs.o \ msr.o \ smm.o \ flag_ctrl_pro.o \ stack32.o \ debugstuff.o \ flag_ctrl.o \ mult32.o \ arith32.o \ jmp_far.o \ call_far.o \ ret_far.o \ iret.o \ ctrl_xfer_pro.o \ segment_ctrl_pro.o \ io.o \ crc32.o \ bit.o \ bit16.o \ bit32.o \ bmi32.o \ string.o \ paging.o # Objects which are only used for x86-64 code OBJS64 = \ access64.o \ arith64.o \ ctrl_xfer64.o \ data_xfer64.o \ fetchdecode64.o \ logical64.o \ mult64.o \ shift64.o \ bit64.o \ stack64.o \ avx.o \ avx_pfp.o \ avx_fma.o \ avx2.o \ gather.o \ bmi64.o \ tbm32.o \ tbm64.o \ xop.o BX_INCLUDES = ../bochs.h ../config.h all: libcpu.a .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(BX_INCDIRS) $(CXXFLAGS) @CXXFP@$< @OFP@$@ libcpu.a: $(OBJS) @OBJS64@ @RMCOMMAND@ libcpu.a @MAKELIB@ $(OBJS) @OBJS64@ $(RANLIB) libcpu.a $(OBJS): $(BX_INCLUDES) $(OBJS64): $(BX_INCLUDES) clean: @RMCOMMAND@ *.o @RMCOMMAND@ *.a dist-clean: clean @RMCOMMAND@ Makefile ########################################### # dependencies generated by # gcc -MM -I.. -I../instrument/stubs *.cc | sed 's/\.cc/.@CPP_SUFFIX@/g' ########################################### 3dnow.o: 3dnow.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h access.o: access.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h access32.o: access32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h access64.o: access64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h aes.o: aes.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h apic.o: apic.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ ../param_names.h arith16.o: arith16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h arith32.o: arith32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h arith64.o: arith64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h arith8.o: arith8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h avx.o: avx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h simd_int.h avx2.o: avx2.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h simd_int.h simd_compare.h gather.o: gather.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h avx_pfp.o: avx_pfp.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../fpu/softfloat-compare.h ../fpu/softfloat.h \ simd_pfp.h avx_fma.o: avx_fma.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../fpu/softfloat-compare.h ../fpu/softfloat.h \ simd_pfp.h xop.o: xop.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h simd_int.h simd_compare.h svm.o: svm.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h simd_int.h simd_compare.h bcd.o: bcd.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h bit.o: bit.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h bit16.o: bit16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h bit32.o: bit32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h bit64.o: bit64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h bmi32.o: bmi32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h bmi64.o: bmi64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h tbm32.o: tbm32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h tbm64.o: tbm64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h call_far.o: call_far.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h cpu.o: cpu.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h event.o: event.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ ../param_names.h crc32.o: crc32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h crregs.o: crregs.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ctrl_xfer16.o: ctrl_xfer16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ctrl_xfer32.o: ctrl_xfer32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ctrl_xfer64.o: ctrl_xfer64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ctrl_xfer_pro.o: ctrl_xfer_pro.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h data_xfer16.o: data_xfer16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h data_xfer32.o: data_xfer32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h data_xfer64.o: data_xfer64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h data_xfer8.o: data_xfer8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h debugstuff.o: debugstuff.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../disasm/disasm.h exception.o: exception.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../param_names.h ../iodev/iodev.h ../plugin.h \ ../extplugin.h fetchdecode.o: fetchdecode.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h fetchdecode.h fetchdecode_x87.h fetchdecode_sse.h \ fetchdecode_avx.h fetchdecode_xop.h fetchdecode64.o: fetchdecode64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h fetchdecode.h fetchdecode_x87.h fetchdecode_sse.h \ fetchdecode_avx.h fetchdecode_xop.h flag_ctrl.o: flag_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h flag_ctrl_pro.o: flag_ctrl_pro.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h fpu_emu.o: fpu_emu.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h generic_cpuid.o: generic_cpuid.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h ../param_names.h generic_cpuid.h ../cpu/cpuid.h icache.o: icache.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h init.o: init.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../param_names.h generic_cpuid.h ../cpu/cpuid.h io.o: io.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ ../param_names.h iret.o: iret.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h jmp_far.o: jmp_far.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h load.o: load.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h logical16.o: logical16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h logical32.o: logical32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h logical64.o: logical64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h logical8.o: logical8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h mmx.o: mmx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h msr.o: msr.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h mult16.o: mult16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h mult32.o: mult32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h mult64.o: mult64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h mult8.o: mult8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h paging.o: paging.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h proc_ctrl.o: proc_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../param_names.h cpu.h \ cpuid.h crregs.h descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h \ apic.h i387.h ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h \ ../fpu/control_w.h xmm.h vmx.h svm.h stack.h protect_ctrl.o: protect_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h resolver.o: resolver.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ret_far.o: ret_far.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h segment_ctrl.o: segment_ctrl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h segment_ctrl_pro.o: segment_ctrl_pro.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h shift16.o: shift16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h shift32.o: shift32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h shift64.o: shift64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h shift8.o: shift8.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h smm.o: smm.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h smm.h soft_int.o: soft_int.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h sse.o: sse.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h simd_int.h simd_compare.h sse_move.o: sse_move.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h simd_int.h sse_pfp.o: sse_pfp.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../fpu/softfloat-compare.h ../fpu/softfloat.h \ simd_pfp.h sse_rcp.o: sse_rcp.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../fpu/softfloat-specialize.h ../fpu/softfloat.h sse_string.o: sse_string.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h stack.o: stack.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h stack16.o: stack16.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h stack32.o: stack32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h stack64.o: stack64.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h string.o: string.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h tasking.o: tasking.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h \ descriptor.h instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h vm8086.o: vm8086.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h vmcs.o: vmcs.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h vmexit.o: vmexit.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h vmx.o: vmx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h ../iodev/iodev.h ../plugin.h ../extplugin.h \ ../param_names.h vmfunc.o: vmfunc.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h xsave.o: xsave.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h ../cpudb.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../gui/gui.h \ ../instrument/stubs/instrument.h cpu.h cpuid.h crregs.h descriptor.h \ instr.h ia_opcodes.h lazy_flags.h icache.h apic.h i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ xmm.h vmx.h svm.h stack.h bochs-2.6/cpu/sse.cc0000644000175000017500000005400712020641453014230 0ustar guillemguillem/////////////////////////////////////////////////6//////////////////////// // $Id: sse.cc 11323 2012-08-07 14:38:43Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2003-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR /* ********************************************** */ /* SSE Integer Operations (128bit MMX extensions) */ /* ********************************************** */ #if BX_CPU_LEVEL >= 6 #include "simd_int.h" #include "simd_compare.h" #define SSE_2OP(HANDLER, func) \ /* SSE instruction with two src operands */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C :: HANDLER (bxInstruction_c *i) \ { \ BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); \ (func)(&op1, &op2); \ BX_WRITE_XMM_REG(i->dst(), op1); \ \ BX_NEXT_INSTR(i); \ } SSE_2OP(PHADDW_VdqWdqR, sse_phaddw) SSE_2OP(PHADDSW_VdqWdqR, sse_phaddsw) SSE_2OP(PHADDD_VdqWdqR, sse_phaddd) SSE_2OP(PHSUBW_VdqWdqR, sse_phsubw) SSE_2OP(PHSUBSW_VdqWdqR, sse_phsubsw) SSE_2OP(PHSUBD_VdqWdqR, sse_phsubd) SSE_2OP(PSIGNB_VdqWdqR, sse_psignb) SSE_2OP(PSIGNW_VdqWdqR, sse_psignw) SSE_2OP(PSIGND_VdqWdqR, sse_psignd) SSE_2OP(PCMPEQQ_VdqWdqR, sse_pcmpeqq) SSE_2OP(PCMPGTQ_VdqWdqR, sse_pcmpgtq) SSE_2OP(PMINSB_VdqWdqR, sse_pminsb) SSE_2OP(PMINSD_VdqWdqR, sse_pminsd) SSE_2OP(PMINUW_VdqWdqR, sse_pminuw) SSE_2OP(PMINUD_VdqWdqR, sse_pminud) SSE_2OP(PMAXSB_VdqWdqR, sse_pmaxsb) SSE_2OP(PMAXSD_VdqWdqR, sse_pmaxsd) SSE_2OP(PMAXUW_VdqWdqR, sse_pmaxuw) SSE_2OP(PMAXUD_VdqWdqR, sse_pmaxud) SSE_2OP(PACKUSDW_VdqWdqR, sse_packusdw) SSE_2OP(PMULLD_VdqWdqR, sse_pmulld) SSE_2OP(PMULDQ_VdqWdqR, sse_pmuldq) SSE_2OP(PMULHRSW_VdqWdqR, sse_pmulhrsw) SSE_2OP(PMADDUBSW_VdqWdqR, sse_pmaddubsw) #endif // BX_CPU_LEVEL >= 6 #if BX_CPU_LEVEL >= 6 #define SSE_2OP_CPU_LEVEL6(HANDLER, func) \ SSE_2OP(HANDLER, func) #else #define SSE_2OP_CPU_LEVEL6(HANDLER, func) \ /* SSE instruction with two src operands */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C :: HANDLER (bxInstruction_c *i) \ { \ BX_NEXT_INSTR(i); \ } #endif SSE_2OP_CPU_LEVEL6(PMINUB_VdqWdqR, sse_pminub) SSE_2OP_CPU_LEVEL6(PMINSW_VdqWdqR, sse_pminsw) SSE_2OP_CPU_LEVEL6(PMAXUB_VdqWdqR, sse_pmaxub) SSE_2OP_CPU_LEVEL6(PMAXSW_VdqWdqR, sse_pmaxsw) SSE_2OP_CPU_LEVEL6(PAVGB_VdqWdqR, sse_pavgb) SSE_2OP_CPU_LEVEL6(PAVGW_VdqWdqR, sse_pavgw) SSE_2OP_CPU_LEVEL6(PCMPEQB_VdqWdqR, sse_pcmpeqb) SSE_2OP_CPU_LEVEL6(PCMPEQW_VdqWdqR, sse_pcmpeqw) SSE_2OP_CPU_LEVEL6(PCMPEQD_VdqWdqR, sse_pcmpeqd) SSE_2OP_CPU_LEVEL6(PCMPGTB_VdqWdqR, sse_pcmpgtb) SSE_2OP_CPU_LEVEL6(PCMPGTW_VdqWdqR, sse_pcmpgtw) SSE_2OP_CPU_LEVEL6(PCMPGTD_VdqWdqR, sse_pcmpgtd) SSE_2OP_CPU_LEVEL6(ANDPS_VpsWpsR, sse_andps) SSE_2OP_CPU_LEVEL6(ANDNPS_VpsWpsR, sse_andnps) SSE_2OP_CPU_LEVEL6(ORPS_VpsWpsR, sse_orps) SSE_2OP_CPU_LEVEL6(XORPS_VpsWpsR, sse_xorps) SSE_2OP_CPU_LEVEL6(PSUBB_VdqWdqR, sse_psubb) SSE_2OP_CPU_LEVEL6(PSUBW_VdqWdqR, sse_psubw) SSE_2OP_CPU_LEVEL6(PSUBD_VdqWdqR, sse_psubd) SSE_2OP_CPU_LEVEL6(PSUBQ_VdqWdqR, sse_psubq) SSE_2OP_CPU_LEVEL6(PADDB_VdqWdqR, sse_paddb) SSE_2OP_CPU_LEVEL6(PADDW_VdqWdqR, sse_paddw) SSE_2OP_CPU_LEVEL6(PADDD_VdqWdqR, sse_paddd) SSE_2OP_CPU_LEVEL6(PADDQ_VdqWdqR, sse_paddq) SSE_2OP_CPU_LEVEL6(PSUBSB_VdqWdqR, sse_psubsb) SSE_2OP_CPU_LEVEL6(PSUBUSB_VdqWdqR, sse_psubusb) SSE_2OP_CPU_LEVEL6(PSUBSW_VdqWdqR, sse_psubsw) SSE_2OP_CPU_LEVEL6(PSUBUSW_VdqWdqR, sse_psubusw) SSE_2OP_CPU_LEVEL6(PADDSB_VdqWdqR, sse_paddsb) SSE_2OP_CPU_LEVEL6(PADDUSB_VdqWdqR, sse_paddusb) SSE_2OP_CPU_LEVEL6(PADDSW_VdqWdqR, sse_paddsw) SSE_2OP_CPU_LEVEL6(PADDUSW_VdqWdqR, sse_paddusw) SSE_2OP_CPU_LEVEL6(PACKUSWB_VdqWdqR, sse_packuswb) SSE_2OP_CPU_LEVEL6(PACKSSWB_VdqWdqR, sse_packsswb) SSE_2OP_CPU_LEVEL6(PACKSSDW_VdqWdqR, sse_packssdw) SSE_2OP_CPU_LEVEL6(UNPCKLPS_VpsWpsR, sse_unpcklps) SSE_2OP_CPU_LEVEL6(UNPCKHPS_VpsWpsR, sse_unpckhps) SSE_2OP_CPU_LEVEL6(PUNPCKLQDQ_VdqWdqR, sse_unpcklpd) SSE_2OP_CPU_LEVEL6(PUNPCKHQDQ_VdqWdqR, sse_unpckhpd) SSE_2OP_CPU_LEVEL6(PUNPCKLBW_VdqWdqR, sse_punpcklbw) SSE_2OP_CPU_LEVEL6(PUNPCKLWD_VdqWdqR, sse_punpcklwd) SSE_2OP_CPU_LEVEL6(PUNPCKHBW_VdqWdqR, sse_punpckhbw) SSE_2OP_CPU_LEVEL6(PUNPCKHWD_VdqWdqR, sse_punpckhwd) SSE_2OP_CPU_LEVEL6(PMULLW_VdqWdqR, sse_pmullw) SSE_2OP_CPU_LEVEL6(PMULHW_VdqWdqR, sse_pmulhw) SSE_2OP_CPU_LEVEL6(PMULHUW_VdqWdqR, sse_pmulhuw) SSE_2OP_CPU_LEVEL6(PMULUDQ_VdqWdqR, sse_pmuludq) SSE_2OP_CPU_LEVEL6(PMADDWD_VdqWdqR, sse_pmaddwd) SSE_2OP_CPU_LEVEL6(PSADBW_VdqWdqR, sse_psadbw) #if BX_CPU_LEVEL >= 6 #define SSE_1OP(HANDLER, func) \ /* SSE instruction with single src operand */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C :: HANDLER (bxInstruction_c *i) \ { \ BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); \ (func)(&op); \ BX_WRITE_XMM_REG(i->dst(), op); \ \ BX_NEXT_INSTR(i); \ } SSE_1OP(PABSB_VdqWdqR, sse_pabsb) SSE_1OP(PABSW_VdqWdqR, sse_pabsw) SSE_1OP(PABSD_VdqWdqR, sse_pabsd) BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFB_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()), result; sse_pshufb(&result, &op1, &op2); BX_WRITE_XMM_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PBLENDVB_VdqWdqR(bxInstruction_c *i) { sse_pblendvb(&BX_XMM_REG(i->dst()), &BX_XMM_REG(i->src()), &BX_XMM_REG(0)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLENDVPS_VpsWpsR(bxInstruction_c *i) { sse_blendvps(&BX_XMM_REG(i->dst()), &BX_XMM_REG(i->src()), &BX_XMM_REG(0)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLENDVPD_VpdWpdR(bxInstruction_c *i) { sse_blendvpd(&BX_XMM_REG(i->dst()), &BX_XMM_REG(i->src()), &BX_XMM_REG(0)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PTEST_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); unsigned result = 0; if ((op2.xmm64u(0) & op1.xmm64u(0)) == 0 && (op2.xmm64u(1) & op1.xmm64u(1)) == 0) result |= EFlagsZFMask; if ((op2.xmm64u(0) & ~op1.xmm64u(0)) == 0 && (op2.xmm64u(1) & ~op1.xmm64u(1)) == 0) result |= EFlagsCFMask; setEFlagsOSZAPC(result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PHMINPOSUW_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); unsigned min = 0; for (unsigned j=1; j < 8; j++) { if (op.xmm16u(j) < op.xmm16u(min)) min = j; } op.xmm16u(0) = op.xmm16u(min); op.xmm16u(1) = min; op.xmm32u(1) = 0; op.xmm64u(1) = 0; BX_WRITE_XMM_REGZ(i->dst(), op, i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLENDPS_VpsWpsIbR(bxInstruction_c *i) { sse_blendps(&BX_XMM_REG(i->dst()), &BX_XMM_REG(i->src()), i->Ib()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLENDPD_VpdWpdIbR(bxInstruction_c *i) { sse_blendpd(&BX_XMM_REG(i->dst()), &BX_XMM_REG(i->src()), i->Ib()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PBLENDW_VdqWdqIbR(bxInstruction_c *i) { sse_pblendw(&BX_XMM_REG(i->dst()), &BX_XMM_REG(i->src()), i->Ib()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRB_EbdVdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); Bit8u result = op.xmmubyte(i->Ib() & 0xF); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRB_EbdVdqIbM(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); Bit8u result = op.xmmubyte(i->Ib() & 0xF); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_byte(i->seg(), eaddr, result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRW_EwdVdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); Bit16u result = op.xmm16u(i->Ib() & 7); BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRW_EwdVdqIbM(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); Bit16u result = op.xmm16u(i->Ib() & 7); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), eaddr, result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRD_EdVdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); #if BX_SUPPORT_X86_64 if (i->os64L()) /* 64 bit operand size mode */ { Bit64u result = op.xmm64u(i->Ib() & 1); BX_WRITE_64BIT_REG(i->dst(), result); } else #endif { Bit32u result = op.xmm32u(i->Ib() & 3); BX_WRITE_32BIT_REGZ(i->dst(), result); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRD_EdVdqIbM(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_X86_64 if (i->os64L()) /* 64 bit operand size mode */ { Bit64u result = op.xmm64u(i->Ib() & 1); write_virtual_qword_64(i->seg(), eaddr, result); } else #endif { Bit32u result = op.xmm32u(i->Ib() & 3); write_virtual_dword(i->seg(), eaddr, result); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::EXTRACTPS_EdVpsIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); Bit32u result = op.xmm32u(i->Ib() & 3); BX_WRITE_32BIT_REGZ(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::EXTRACTPS_EdVpsIbM(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); Bit32u result = op.xmm32u(i->Ib() & 3); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword(i->seg(), eaddr, result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRB_VdqHdqEbIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); Bit8u op2 = (Bit8u) BX_READ_16BIT_REG(i->src2()); // won't allow reading of AH/CH/BH/DH op1.xmmubyte(i->Ib() & 0xF) = op2; BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRB_VdqHdqEbIbM(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1.xmmubyte(i->Ib() & 0xF) = read_virtual_byte(i->seg(), eaddr); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INSERTPS_VpsHpsWssIb(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); Bit8u control = i->Ib(); Bit32u op2; /* op2 is a register or memory reference */ if (i->modC0()) { BxPackedXmmRegister temp = BX_READ_XMM_REG(i->src2()); op2 = temp.xmm32u((control >> 6) & 3); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2 = read_virtual_dword(i->seg(), eaddr); } op1.xmm32u((control >> 4) & 3) = op2; if (control & 1) op1.xmm32u(0) = 0; if (control & 2) op1.xmm32u(1) = 0; if (control & 4) op1.xmm32u(2) = 0; if (control & 8) op1.xmm32u(3) = 0; BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRD_VdqHdqEdIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); #if BX_SUPPORT_X86_64 if (i->os64L()) { /* 64 bit operand size mode */ op1.xmm64u(i->Ib() & 1) = BX_READ_64BIT_REG(i->src2()); } else #endif { op1.xmm32u(i->Ib() & 3) = BX_READ_32BIT_REG(i->src2()); } BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRD_VdqHdqEdIbM(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_X86_64 if (i->os64L()) { /* 64 bit operand size mode */ Bit64u op2 = read_virtual_qword_64(i->seg(), eaddr); op1.xmm64u(i->Ib() & 1) = op2; } else #endif { Bit32u op2 = read_virtual_dword(i->seg(), eaddr); op1.xmm32u(i->Ib() & 3) = op2; } BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MPSADBW_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()), result; sse_mpsadbw(&result, &op1, &op2, i->Ib() & 0x7); BX_WRITE_XMM_REG(i->dst(), result); BX_NEXT_INSTR(i); } #endif // BX_CPU_LEVEL >= 6 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFD_VdqWdqIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()), result; sse_shufps(&result, &op, &op, i->Ib()); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFHW_VdqWdqIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()), result; sse_pshufhw(&result, &op, i->Ib()); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSHUFLW_VdqWdqIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()), result; sse_pshuflw(&result, &op, i->Ib()); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PINSRW_VdqHdqEwIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); Bit8u count = i->Ib() & 0x7; op1.xmm16u(count) = BX_READ_16BIT_REG(i->src2()); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXTRW_GdUdqIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); Bit8u count = i->Ib() & 0x7; Bit32u result = (Bit32u) op.xmm16u(count); BX_WRITE_32BIT_REGZ(i->dst(), result); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHUFPS_VpsWpsIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()), result; sse_shufps(&result, &op1, &op2, i->Ib()); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHUFPD_VpdWpdIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()), result; sse_shufpd(&result, &op1, &op2, i->Ib()); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } #if BX_CPU_LEVEL >= 6 #define SSE_PSHIFT_CPU_LEVEL6(HANDLER, func) \ /* SSE packed shift instruction */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ BxPackedXmmRegister op = BX_READ_XMM_REG(i->dst()); \ \ (func)(&op, BX_READ_XMM_REG_LO_QWORD(i->src())); \ \ BX_WRITE_XMM_REG(i->dst(), op); \ \ BX_NEXT_INSTR(i); \ } #else #define SSE_PSHIFT_CPU_LEVEL6(HANDLER, func) \ /* SSE instruction with two src operands */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C :: HANDLER (bxInstruction_c *i) \ { \ BX_NEXT_INSTR(i); \ } #endif SSE_PSHIFT_CPU_LEVEL6(PSRLW_VdqWdqR, sse_psrlw); SSE_PSHIFT_CPU_LEVEL6(PSRLD_VdqWdqR, sse_psrld); SSE_PSHIFT_CPU_LEVEL6(PSRLQ_VdqWdqR, sse_psrlq); SSE_PSHIFT_CPU_LEVEL6(PSRAW_VdqWdqR, sse_psraw); SSE_PSHIFT_CPU_LEVEL6(PSRAD_VdqWdqR, sse_psrad); SSE_PSHIFT_CPU_LEVEL6(PSLLW_VdqWdqR, sse_psllw); SSE_PSHIFT_CPU_LEVEL6(PSLLD_VdqWdqR, sse_pslld); SSE_PSHIFT_CPU_LEVEL6(PSLLQ_VdqWdqR, sse_psllq); #if BX_CPU_LEVEL >= 6 #define SSE_PSHIFT_IMM_CPU_LEVEL6(HANDLER, func) \ /* SSE packed shift with imm8 instruction */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ (func)(&BX_XMM_REG(i->dst()), i->Ib()); \ \ BX_NEXT_INSTR(i); \ } #else #define SSE_PSHIFT_IMM_CPU_LEVEL6(HANDLER, func) \ /* SSE packed shift with imm8 instruction */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C :: HANDLER (bxInstruction_c *i) \ { \ BX_NEXT_INSTR(i); \ } #endif SSE_PSHIFT_IMM_CPU_LEVEL6(PSRLW_UdqIb, sse_psrlw); SSE_PSHIFT_IMM_CPU_LEVEL6(PSRLD_UdqIb, sse_psrld); SSE_PSHIFT_IMM_CPU_LEVEL6(PSRLQ_UdqIb, sse_psrlq); SSE_PSHIFT_IMM_CPU_LEVEL6(PSRAW_UdqIb, sse_psraw); SSE_PSHIFT_IMM_CPU_LEVEL6(PSRAD_UdqIb, sse_psrad); SSE_PSHIFT_IMM_CPU_LEVEL6(PSLLW_UdqIb, sse_psllw); SSE_PSHIFT_IMM_CPU_LEVEL6(PSLLD_UdqIb, sse_pslld); SSE_PSHIFT_IMM_CPU_LEVEL6(PSLLQ_UdqIb, sse_psllq); SSE_PSHIFT_IMM_CPU_LEVEL6(PSRLDQ_UdqIb, sse_psrldq); SSE_PSHIFT_IMM_CPU_LEVEL6(PSLLDQ_UdqIb, sse_pslldq); /* ************************ */ /* SSE4A (AMD) INSTRUCTIONS */ /* ************************ */ #if BX_CPU_LEVEL >= 6 BX_CPP_INLINE Bit64u sse_extrq(Bit64u src, unsigned shift, unsigned len) { len &= 0x3f; shift &= 0x3f; src >>= shift; if (len) { Bit64u mask = (BX_CONST64(1) << len) - 1; return src & mask; } return src; } BX_CPP_INLINE Bit64u sse_insertq(Bit64u dest, Bit64u src, unsigned shift, unsigned len) { Bit64u mask; len &= 0x3f; shift &= 0x3f; if (len == 0) { mask = BX_CONST64(0xffffffffffffffff); } else { mask = (BX_CONST64(1) << len) - 1; } return (dest & ~(mask << shift)) | ((src & mask) << shift); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::EXTRQ_UdqIbIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BX_WRITE_XMM_REG_LO_QWORD(i->dst(), sse_extrq(BX_READ_XMM_REG_LO_QWORD(i->dst()), i->Ib2(), i->Ib())); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::EXTRQ_VdqUq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 Bit16u ctrl = BX_READ_XMM_REG_LO_WORD(i->src()); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), sse_extrq(BX_READ_XMM_REG_LO_QWORD(i->dst()), ctrl >> 8, ctrl)); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INSERTQ_VdqUqIbIb(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 Bit64u dst = BX_READ_XMM_REG_LO_QWORD(i->dst()), src = BX_READ_XMM_REG_LO_QWORD(i->src()); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), sse_insertq(dst, src, i->Ib2(), i->Ib())); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INSERTQ_VdqUdq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister src = BX_READ_XMM_REG(i->src()); Bit64u dst = BX_READ_XMM_REG_LO_QWORD(i->dst()); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), sse_insertq(dst, src.xmm64u(0), src.xmmubyte(9), src.xmmubyte(8))); #endif BX_NEXT_INSTR(i); } bochs-2.6/cpu/string.cc0000644000175000017500000013310312020641453014737 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: string.cc 11117 2012-03-28 21:11:19Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR // // Repeat Speedups methods // #if BX_SUPPORT_REPEAT_SPEEDUPS Bit32u BX_CPU_C::FastRepMOVSB(bxInstruction_c *i, unsigned srcSeg, bx_address srcOff, unsigned dstSeg, bx_address dstOff, Bit32u count) { Bit32u bytesFitSrc, bytesFitDst; signed int pointerDelta; bx_address laddrDst, laddrSrc; Bit8u *hostAddrSrc, *hostAddrDst; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); bx_segment_reg_t *srcSegPtr = &BX_CPU_THIS_PTR sregs[srcSeg]; if (!(srcSegPtr->cache.valid & SegAccessROK)) return 0; if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled) return 0; bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg]; if (!(dstSegPtr->cache.valid & SegAccessWOK)) return 0; if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled) return 0; laddrSrc = get_laddr32(srcSeg, srcOff); hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl); if (! hostAddrSrc) return 0; laddrDst = get_laddr32(dstSeg, dstOff); hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrDst) return 0; // See how many bytes can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward. bytesFitSrc = 1 + PAGE_OFFSET(laddrSrc); bytesFitDst = 1 + PAGE_OFFSET(laddrDst); pointerDelta = (signed int) -1; } else { // Counting upward. bytesFitSrc = 0x1000 - PAGE_OFFSET(laddrSrc); bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst); pointerDelta = (signed int) 1; } // Restrict word count to the number that will fit in either // source or dest pages. if (count > bytesFitSrc) count = bytesFitSrc; if (count > bytesFitDst) count = bytesFitDst; if (count > bx_pc_system.getNumCpuTicksLeftNextEvent()) count = bx_pc_system.getNumCpuTicksLeftNextEvent(); // If after all the restrictions, there is anything left to do... if (count) { // Transfer data directly using host addresses for (unsigned j=0; jcache.valid & SegAccessROK)) return 0; if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled) return 0; bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg]; if (!(dstSegPtr->cache.valid & SegAccessWOK)) return 0; if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled) return 0; laddrSrc = get_laddr32(srcSeg, srcOff); hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl); if (! hostAddrSrc) return 0; laddrDst = get_laddr32(dstSeg, dstOff); hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrDst) return 0; // See how many words can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward. // Note: 1st word must not cross page boundary. if (((laddrSrc & 0xfff) > 0xffe) || ((laddrDst & 0xfff) > 0xffe)) return 0; wordsFitSrc = (2 + PAGE_OFFSET(laddrSrc)) >> 1; wordsFitDst = (2 + PAGE_OFFSET(laddrDst)) >> 1; pointerDelta = (signed int) -2; } else { // Counting upward. wordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 1; wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1; pointerDelta = (signed int) 2; } // Restrict word count to the number that will fit in either // source or dest pages. if (count > wordsFitSrc) count = wordsFitSrc; if (count > wordsFitDst) count = wordsFitDst; if (count > bx_pc_system.getNumCpuTicksLeftNextEvent()) count = bx_pc_system.getNumCpuTicksLeftNextEvent(); // If after all the restrictions, there is anything left to do... if (count) { // Transfer data directly using host addresses for (unsigned j=0; jcache.valid & SegAccessROK)) return 0; if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled) return 0; bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[dstSeg]; if (!(dstSegPtr->cache.valid & SegAccessWOK)) return 0; if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled) return 0; laddrSrc = get_laddr32(srcSeg, srcOff); hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl); if (! hostAddrSrc) return 0; laddrDst = get_laddr32(dstSeg, dstOff); hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrDst) return 0; // See how many dwords can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward. // Note: 1st dword must not cross page boundary. if (((laddrSrc & 0xfff) > 0xffc) || ((laddrDst & 0xfff) > 0xffc)) return 0; dwordsFitSrc = (4 + PAGE_OFFSET(laddrSrc)) >> 2; dwordsFitDst = (4 + PAGE_OFFSET(laddrDst)) >> 2; pointerDelta = (signed int) -4; } else { // Counting upward. dwordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 2; dwordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 2; pointerDelta = (signed int) 4; } // Restrict dword count to the number that will fit in either // source or dest pages. if (count > dwordsFitSrc) count = dwordsFitSrc; if (count > dwordsFitDst) count = dwordsFitDst; if (count > bx_pc_system.getNumCpuTicksLeftNextEvent()) count = bx_pc_system.getNumCpuTicksLeftNextEvent(); // If after all the restrictions, there is anything left to do... if (count) { // Transfer data directly using host addresses for (unsigned j=0; jcache.valid & SegAccessWOK)) return 0; if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled) return 0; laddrDst = get_laddr32(dstSeg, dstOff); hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrDst) return 0; // See how many bytes can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward. bytesFitDst = 1 + PAGE_OFFSET(laddrDst); pointerDelta = (signed int) -1; } else { // Counting upward. bytesFitDst = 0x1000 - PAGE_OFFSET(laddrDst); pointerDelta = (signed int) 1; } // Restrict word count to the number that will fit in either // source or dest pages. if (count > bytesFitDst) count = bytesFitDst; if (count > bx_pc_system.getNumCpuTicksLeftNextEvent()) count = bx_pc_system.getNumCpuTicksLeftNextEvent(); // If after all the restrictions, there is anything left to do... if (count) { // Transfer data directly using host addresses for (unsigned j=0; jcache.valid & SegAccessWOK)) return 0; if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled) return 0; laddrDst = get_laddr32(dstSeg, dstOff); hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrDst) return 0; // See how many words can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward. // Note: 1st word must not cross page boundary. if ((laddrDst & 0xfff) > 0xffe) return 0; wordsFitDst = (2 + PAGE_OFFSET(laddrDst)) >> 1; pointerDelta = (signed int) -2; } else { // Counting upward. wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1; pointerDelta = (signed int) 2; } // Restrict word count to the number that will fit in either // source or dest pages. if (count > wordsFitDst) count = wordsFitDst; if (count > bx_pc_system.getNumCpuTicksLeftNextEvent()) count = bx_pc_system.getNumCpuTicksLeftNextEvent(); // If after all the restrictions, there is anything left to do... if (count) { // Transfer data directly using host addresses for (unsigned j=0; jcache.valid & SegAccessWOK)) return 0; if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled) return 0; laddrDst = get_laddr32(dstSeg, dstOff); hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrDst) return 0; // See how many dwords can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward. // Note: 1st dword must not cross page boundary. if ((laddrDst & 0xfff) > 0xffc) return 0; dwordsFitDst = (4 + PAGE_OFFSET(laddrDst)) >> 2; pointerDelta = (signed int) -4; } else { // Counting upward. dwordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 2; pointerDelta = (signed int) 4; } // Restrict dword count to the number that will fit in either // source or dest pages. if (count > dwordsFitDst) count = dwordsFitDst; if (count > bx_pc_system.getNumCpuTicksLeftNextEvent()) count = bx_pc_system.getNumCpuTicksLeftNextEvent(); // If after all the restrictions, there is anything left to do... if (count) { // Transfer data directly using host addresses for (unsigned j=0; jas64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB64_XbYb); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB32_XbYb); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSB16_XbYb); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSW_XwYw(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW64_XwYw); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW32_XwYw); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSW16_XwYw); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSD_XdYd(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD64_XdYd); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD32_XdYd); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSD16_XdYd); } BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_MOVSQ_XqYq(bxInstruction_c *i) { if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSQ64_XqYq); } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::MOVSQ32_XqYq); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } BX_NEXT_INSTR(i); } #endif // // MOVSB/MOVSW/MOVSD/MOVSQ methods // // 16 bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB16_XbYb(bxInstruction_c *i) { Bit8u temp8 = read_virtual_byte_32(i->seg(), SI); write_virtual_byte_32(BX_SEG_REG_ES, DI, temp8); if (BX_CPU_THIS_PTR get_DF()) { /* decrement SI, DI */ SI--; DI--; } else { /* increment SI, DI */ SI++; DI++; } } // 32 bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB32_XbYb(bxInstruction_c *i) { Bit8u temp8; Bit32u incr = 1; #if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0) /* If conditions are right, we can transfer IO to physical memory * in a batch, rather than one instruction at a time */ if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) { Bit32u byteCount = FastRepMOVSB(i, i->seg(), ESI, BX_SEG_REG_ES, EDI, ECX); if (byteCount) { // Decrement the ticks count by the number of iterations, minus // one, since the main cpu loop will decrement one. Also, // the count is predecremented before examined, so defintely // don't roll it under zero. BX_TICKN(byteCount-1); // Decrement eCX. Note, the main loop will decrement 1 also, so // decrement by one less than expected, like the case above. RCX = ECX - (byteCount-1); incr = byteCount; } else { temp8 = read_virtual_byte(i->seg(), ESI); write_virtual_byte(BX_SEG_REG_ES, EDI, temp8); } } else #endif { temp8 = read_virtual_byte(i->seg(), ESI); write_virtual_byte(BX_SEG_REG_ES, EDI, temp8); } if (BX_CPU_THIS_PTR get_DF()) { RSI = ESI - incr; RDI = EDI - incr; } else { RSI = ESI + incr; RDI = EDI + incr; } } #if BX_SUPPORT_X86_64 // 64 bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSB64_XbYb(bxInstruction_c *i) { Bit8u temp8; Bit64u rsi = RSI; Bit64u rdi = RDI; temp8 = read_virtual_byte_64(i->seg(), rsi); write_virtual_byte_64(BX_SEG_REG_ES, rdi, temp8); if (BX_CPU_THIS_PTR get_DF()) { /* decrement RSI, RDI */ rsi--; rdi--; } else { /* increment RSI, RDI */ rsi++; rdi++; } RSI = rsi; RDI = rdi; } #endif /* 16 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW16_XwYw(bxInstruction_c *i) { Bit16u si = SI; Bit16u di = DI; Bit16u temp16 = read_virtual_word_32(i->seg(), si); write_virtual_word_32(BX_SEG_REG_ES, di, temp16); if (BX_CPU_THIS_PTR get_DF()) { /* decrement SI, DI */ si -= 2; di -= 2; } else { /* increment SI, DI */ si += 2; di += 2; } SI = si; DI = di; } /* 16 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW32_XwYw(bxInstruction_c *i) { Bit16u temp16; Bit32u esi = ESI; Bit32u edi = EDI; temp16 = read_virtual_word(i->seg(), esi); write_virtual_word(BX_SEG_REG_ES, edi, temp16); if (BX_CPU_THIS_PTR get_DF()) { esi -= 2; edi -= 2; } else { esi += 2; edi += 2; } // zero extension of RSI/RDI RSI = esi; RDI = edi; } #if BX_SUPPORT_X86_64 /* 16 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSW64_XwYw(bxInstruction_c *i) { Bit16u temp16; Bit64u rsi = RSI; Bit64u rdi = RDI; temp16 = read_virtual_word_64(i->seg(), rsi); write_virtual_word_64(BX_SEG_REG_ES, rdi, temp16); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 2; rdi -= 2; } else { rsi += 2; rdi += 2; } RSI = rsi; RDI = rdi; } #endif /* 32 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD16_XdYd(bxInstruction_c *i) { Bit32u temp32; Bit16u si = SI; Bit16u di = DI; temp32 = read_virtual_dword_32(i->seg(), si); write_virtual_dword_32(BX_SEG_REG_ES, di, temp32); if (BX_CPU_THIS_PTR get_DF()) { si -= 4; di -= 4; } else { si += 4; di += 4; } SI = si; DI = di; } /* 32 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD32_XdYd(bxInstruction_c *i) { Bit32u temp32; Bit32u incr = 4; Bit32u esi = ESI; Bit32u edi = EDI; #if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0) /* If conditions are right, we can transfer IO to physical memory * in a batch, rather than one instruction at a time. */ if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) { Bit32u dwordCount = FastRepMOVSD(i, i->seg(), esi, BX_SEG_REG_ES, edi, ECX); if (dwordCount) { // Decrement the ticks count by the number of iterations, minus // one, since the main cpu loop will decrement one. Also, // the count is predecremented before examined, so defintely // don't roll it under zero. BX_TICKN(dwordCount-1); // Decrement eCX. Note, the main loop will decrement 1 also, so // decrement by one less than expected, like the case above. RCX = ECX - (dwordCount-1); incr = dwordCount << 2; // count * 4 } else { temp32 = read_virtual_dword(i->seg(), esi); write_virtual_dword(BX_SEG_REG_ES, edi, temp32); } } else #endif { temp32 = read_virtual_dword(i->seg(), esi); write_virtual_dword(BX_SEG_REG_ES, edi, temp32); } if (BX_CPU_THIS_PTR get_DF()) { esi -= incr; edi -= incr; } else { esi += incr; edi += incr; } // zero extension of RSI/RDI RSI = esi; RDI = edi; } #if BX_SUPPORT_X86_64 /* 32 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSD64_XdYd(bxInstruction_c *i) { Bit32u temp32; Bit64u rsi = RSI; Bit64u rdi = RDI; temp32 = read_virtual_dword_64(i->seg(), rsi); write_virtual_dword_64(BX_SEG_REG_ES, rdi, temp32); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 4; rdi -= 4; } else { rsi += 4; rdi += 4; } RSI = rsi; RDI = rdi; } /* 64 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSQ32_XqYq(bxInstruction_c *i) { Bit64u temp64; Bit32u esi = ESI; Bit32u edi = EDI; temp64 = read_virtual_qword_64(i->seg(), esi); write_virtual_qword_64(BX_SEG_REG_ES, edi, temp64); if (BX_CPU_THIS_PTR get_DF()) { esi -= 8; edi -= 8; } else { esi += 8; edi += 8; } // zero extension of RSI/RDI RSI = esi; RDI = edi; } /* 64 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSQ64_XqYq(bxInstruction_c *i) { Bit64u temp64; Bit64u rsi = RSI; Bit64u rdi = RDI; temp64 = read_virtual_qword_64(i->seg(), rsi); write_virtual_qword_64(BX_SEG_REG_ES, rdi, temp64); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 8; rdi -= 8; } else { rsi += 8; rdi += 8; } RSI = rsi; RDI = rdi; } #endif // // REP CMPS methods // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSB_XbYb(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB64_XbYb); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB32_XbYb); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSB16_XbYb); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSW_XwYw(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW64_XwYw); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW32_XwYw); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSW16_XwYw); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSD_XdYd(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD64_XdYd); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD32_XdYd); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSD16_XdYd); } BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_CMPSQ_XqYq(bxInstruction_c *i) { if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSQ64_XqYq); } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::CMPSQ32_XqYq); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI/RDI BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); } BX_NEXT_INSTR(i); } #endif // // CMPSB/CMPSW/CMPSD/CMPSQ methods // /* 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB16_XbYb(bxInstruction_c *i) { Bit8u op1_8, op2_8, diff_8; Bit16u si = SI; Bit16u di = DI; op1_8 = read_virtual_byte_32(i->seg(), si); op2_8 = read_virtual_byte_32(BX_SEG_REG_ES, di); diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); if (BX_CPU_THIS_PTR get_DF()) { si--; di--; } else { si++; di++; } DI = di; SI = si; } /* 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB32_XbYb(bxInstruction_c *i) { Bit8u op1_8, op2_8, diff_8; Bit32u esi = ESI; Bit32u edi = EDI; op1_8 = read_virtual_byte(i->seg(), esi); op2_8 = read_virtual_byte(BX_SEG_REG_ES, edi); diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); if (BX_CPU_THIS_PTR get_DF()) { esi--; edi--; } else { esi++; edi++; } // zero extension of RSI/RDI RDI = edi; RSI = esi; } #if BX_SUPPORT_X86_64 /* 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSB64_XbYb(bxInstruction_c *i) { Bit8u op1_8, op2_8, diff_8; Bit64u rsi = RSI; Bit64u rdi = RDI; op1_8 = read_virtual_byte_64(i->seg(), rsi); op2_8 = read_virtual_byte_64(BX_SEG_REG_ES, rdi); diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); if (BX_CPU_THIS_PTR get_DF()) { rsi--; rdi--; } else { rsi++; rdi++; } RDI = rdi; RSI = rsi; } #endif /* 16 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW16_XwYw(bxInstruction_c *i) { Bit16u op1_16, op2_16, diff_16; Bit16u si = SI; Bit16u di = DI; op1_16 = read_virtual_word_32(i->seg(), si); op2_16 = read_virtual_word_32(BX_SEG_REG_ES, di); diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); if (BX_CPU_THIS_PTR get_DF()) { si -= 2; di -= 2; } else { si += 2; di += 2; } DI = di; SI = si; } /* 16 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW32_XwYw(bxInstruction_c *i) { Bit16u op1_16, op2_16, diff_16; Bit32u esi = ESI; Bit32u edi = EDI; op1_16 = read_virtual_word(i->seg(), esi); op2_16 = read_virtual_word(BX_SEG_REG_ES, edi); diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); if (BX_CPU_THIS_PTR get_DF()) { esi -= 2; edi -= 2; } else { esi += 2; edi += 2; } // zero extension of RSI/RDI RDI = edi; RSI = esi; } #if BX_SUPPORT_X86_64 /* 16 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSW64_XwYw(bxInstruction_c *i) { Bit16u op1_16, op2_16, diff_16; Bit64u rsi = RSI; Bit64u rdi = RDI; op1_16 = read_virtual_word_64(i->seg(), rsi); op2_16 = read_virtual_word_64(BX_SEG_REG_ES, rdi); diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 2; rdi -= 2; } else { rsi += 2; rdi += 2; } RDI = rdi; RSI = rsi; } #endif /* 32 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD16_XdYd(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; Bit16u si = SI; Bit16u di = DI; op1_32 = read_virtual_dword_32(i->seg(), si); op2_32 = read_virtual_dword_32(BX_SEG_REG_ES, di); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); if (BX_CPU_THIS_PTR get_DF()) { si -= 4; di -= 4; } else { si += 4; di += 4; } DI = di; SI = si; } /* 32 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD32_XdYd(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; Bit32u esi = ESI; Bit32u edi = EDI; op1_32 = read_virtual_dword(i->seg(), esi); op2_32 = read_virtual_dword(BX_SEG_REG_ES, edi); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); if (BX_CPU_THIS_PTR get_DF()) { esi -= 4; edi -= 4; } else { esi += 4; edi += 4; } // zero extension of RSI/RDI RDI = edi; RSI = esi; } #if BX_SUPPORT_X86_64 /* 32 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD64_XdYd(bxInstruction_c *i) { Bit32u op1_32, op2_32, diff_32; Bit64u rsi = RSI; Bit64u rdi = RDI; op1_32 = read_virtual_dword_64(i->seg(), rsi); op2_32 = read_virtual_dword_64(BX_SEG_REG_ES, rdi); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 4; rdi -= 4; } else { rsi += 4; rdi += 4; } RDI = rdi; RSI = rsi; } /* 64 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSQ32_XqYq(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; Bit32u esi = ESI; Bit32u edi = EDI; op1_64 = read_virtual_qword_64(i->seg(), esi); op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, edi); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); if (BX_CPU_THIS_PTR get_DF()) { esi -= 8; edi -= 8; } else { esi += 8; edi += 8; } // zero extension of RSI/RDI RDI = edi; RSI = esi; } /* 64 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSQ64_XqYq(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; Bit64u rsi = RSI; Bit64u rdi = RDI; op1_64 = read_virtual_qword_64(i->seg(), rsi); op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, rdi); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 8; rdi -= 8; } else { rsi += 8; rdi += 8; } RDI = rdi; RSI = rsi; } #endif // // REP SCAS methods // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASB_ALXb(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB64_ALXb); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB32_ALXb); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASB16_ALXb); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASW_AXXw(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW64_AXXw); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW32_AXXw); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASW16_AXXw); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASD_EAXXd(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD64_EAXXd); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD32_EAXXd); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASD16_EAXXd); } BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_SCASQ_RAXXq(bxInstruction_c *i) { if (i->as64L()) { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASQ64_RAXXq); } else { BX_CPU_THIS_PTR repeat_ZF(i, &BX_CPU_C::SCASQ32_RAXXq); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } BX_NEXT_INSTR(i); } #endif // // SCASB/SCASW/SCASD/SCASQ methods // /* 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB16_ALXb(bxInstruction_c *i) { Bit8u op1_8 = AL, op2_8, diff_8; Bit16u di = DI; op2_8 = read_virtual_byte_32(BX_SEG_REG_ES, di); diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); if (BX_CPU_THIS_PTR get_DF()) { di--; } else { di++; } DI = di; } /* 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB32_ALXb(bxInstruction_c *i) { Bit8u op1_8 = AL, op2_8, diff_8; Bit32u edi = EDI; op2_8 = read_virtual_byte(BX_SEG_REG_ES, edi); diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); if (BX_CPU_THIS_PTR get_DF()) { edi--; } else { edi++; } // zero extension of RDI RDI = edi; } #if BX_SUPPORT_X86_64 /* 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASB64_ALXb(bxInstruction_c *i) { Bit8u op1_8 = AL, op2_8, diff_8; Bit64u rdi = RDI; op2_8 = read_virtual_byte_64(BX_SEG_REG_ES, rdi); diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); if (BX_CPU_THIS_PTR get_DF()) { rdi--; } else { rdi++; } RDI = rdi; } #endif /* 16 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW16_AXXw(bxInstruction_c *i) { Bit16u op1_16 = AX, op2_16, diff_16; Bit16u di = DI; op2_16 = read_virtual_word_32(BX_SEG_REG_ES, di); diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); if (BX_CPU_THIS_PTR get_DF()) { di -= 2; } else { di += 2; } DI = di; } /* 16 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW32_AXXw(bxInstruction_c *i) { Bit16u op1_16 = AX, op2_16, diff_16; Bit32u edi = EDI; op2_16 = read_virtual_word(BX_SEG_REG_ES, edi); diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); if (BX_CPU_THIS_PTR get_DF()) { edi -= 2; } else { edi += 2; } // zero extension of RDI RDI = edi; } #if BX_SUPPORT_X86_64 /* 16 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASW64_AXXw(bxInstruction_c *i) { Bit16u op1_16 = AX, op2_16, diff_16; Bit64u rdi = RDI; op2_16 = read_virtual_word_64(BX_SEG_REG_ES, rdi); diff_16 = op1_16 - op2_16; SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16); if (BX_CPU_THIS_PTR get_DF()) { rdi -= 2; } else { rdi += 2; } RDI = rdi; } #endif /* 32 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD16_EAXXd(bxInstruction_c *i) { Bit32u op1_32 = EAX, op2_32, diff_32; Bit16u di = DI; op2_32 = read_virtual_dword_32(BX_SEG_REG_ES, di); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); if (BX_CPU_THIS_PTR get_DF()) { di -= 4; } else { di += 4; } DI = di; } /* 32 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD32_EAXXd(bxInstruction_c *i) { Bit32u op1_32 = EAX, op2_32, diff_32; Bit32u edi = EDI; op2_32 = read_virtual_dword(BX_SEG_REG_ES, edi); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); if (BX_CPU_THIS_PTR get_DF()) { edi -= 4; } else { edi += 4; } // zero extension of RDI RDI = edi; } #if BX_SUPPORT_X86_64 /* 32 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASD64_EAXXd(bxInstruction_c *i) { Bit32u op1_32 = EAX, op2_32, diff_32; Bit64u rdi = RDI; op2_32 = read_virtual_dword_64(BX_SEG_REG_ES, rdi); diff_32 = op1_32 - op2_32; SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32); if (BX_CPU_THIS_PTR get_DF()) { rdi -= 4; } else { rdi += 4; } RDI = rdi; } /* 64 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASQ32_RAXXq(bxInstruction_c *i) { Bit64u op1_64 = RAX, op2_64, diff_64; Bit32u edi = EDI; op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, edi); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); if (BX_CPU_THIS_PTR get_DF()) { edi -= 8; } else { edi += 8; } // zero extension of RDI RDI = edi; } /* 64 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::SCASQ64_RAXXq(bxInstruction_c *i) { Bit64u op1_64 = RAX, op2_64, diff_64; Bit64u rdi = RDI; op2_64 = read_virtual_qword_64(BX_SEG_REG_ES, rdi); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); if (BX_CPU_THIS_PTR get_DF()) { rdi -= 8; } else { rdi += 8; } RDI = rdi; } #endif // // REP STOS methods // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSB_YbAL(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB64_YbAL); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB32_YbAL); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSB16_YbAL); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSW_YwAX(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW64_YwAX); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW32_YwAX); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSW16_YwAX); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSD_YdEAX(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD64_YdEAX); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD32_YdEAX); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSD16_YdEAX); } BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_STOSQ_YqRAX(bxInstruction_c *i) { if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSQ64_YqRAX); } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::STOSQ32_YqRAX); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } BX_NEXT_INSTR(i); } #endif // // STOSB/STOSW/STOSD/STOSQ methods // // 16 bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB16_YbAL(bxInstruction_c *i) { Bit16u di = DI; write_virtual_byte_32(BX_SEG_REG_ES, di, AL); if (BX_CPU_THIS_PTR get_DF()) { di--; } else { di++; } DI = di; } // 32 bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB32_YbAL(bxInstruction_c *i) { Bit32u incr = 1; Bit32u edi = EDI; #if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0) /* If conditions are right, we can transfer IO to physical memory * in a batch, rather than one instruction at a time. */ if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) { Bit32u byteCount = FastRepSTOSB(i, BX_SEG_REG_ES, edi, AL, ECX); if (byteCount) { // Decrement the ticks count by the number of iterations, minus // one, since the main cpu loop will decrement one. Also, // the count is predecremented before examined, so defintely // don't roll it under zero. BX_TICKN(byteCount-1); // Decrement eCX. Note, the main loop will decrement 1 also, so // decrement by one less than expected, like the case above. RCX = ECX - (byteCount-1); incr = byteCount; } else { write_virtual_byte(BX_SEG_REG_ES, edi, AL); } } else #endif { write_virtual_byte(BX_SEG_REG_ES, edi, AL); } if (BX_CPU_THIS_PTR get_DF()) { edi -= incr; } else { edi += incr; } // zero extension of RDI RDI = edi; } #if BX_SUPPORT_X86_64 // 64 bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSB64_YbAL(bxInstruction_c *i) { Bit64u rdi = RDI; write_virtual_byte_64(BX_SEG_REG_ES, rdi, AL); if (BX_CPU_THIS_PTR get_DF()) { rdi--; } else { rdi++; } RDI = rdi; } #endif /* 16 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW16_YwAX(bxInstruction_c *i) { Bit16u di = DI; write_virtual_word_32(BX_SEG_REG_ES, di, AX); if (BX_CPU_THIS_PTR get_DF()) { di -= 2; } else { di += 2; } DI = di; } /* 16 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW32_YwAX(bxInstruction_c *i) { Bit32u edi = EDI; write_virtual_word(BX_SEG_REG_ES, edi, AX); if (BX_CPU_THIS_PTR get_DF()) { edi -= 2; } else { edi += 2; } // zero extension of RDI RDI = edi; } #if BX_SUPPORT_X86_64 /* 16 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSW64_YwAX(bxInstruction_c *i) { Bit64u rdi = RDI; write_virtual_word_64(BX_SEG_REG_ES, rdi, AX); if (BX_CPU_THIS_PTR get_DF()) { rdi -= 2; } else { rdi += 2; } RDI = rdi; } #endif /* 32 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD16_YdEAX(bxInstruction_c *i) { Bit16u di = DI; write_virtual_dword_32(BX_SEG_REG_ES, di, EAX); if (BX_CPU_THIS_PTR get_DF()) { di -= 4; } else { di += 4; } DI = di; } /* 32 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD32_YdEAX(bxInstruction_c *i) { Bit32u edi = EDI; write_virtual_dword(BX_SEG_REG_ES, edi, EAX); if (BX_CPU_THIS_PTR get_DF()) { edi -= 4; } else { edi += 4; } // zero extension of RDI RDI = edi; } #if BX_SUPPORT_X86_64 /* 32 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSD64_YdEAX(bxInstruction_c *i) { Bit64u rdi = RDI; write_virtual_dword_64(BX_SEG_REG_ES, rdi, EAX); if (BX_CPU_THIS_PTR get_DF()) { rdi -= 4; } else { rdi += 4; } RDI = rdi; } /* 64 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSQ32_YqRAX(bxInstruction_c *i) { Bit32u edi = EDI; write_virtual_qword_64(BX_SEG_REG_ES, edi, RAX); if (BX_CPU_THIS_PTR get_DF()) { edi -= 8; } else { edi += 8; } // zero extension of RDI RDI = edi; } /* 64 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::STOSQ64_YqRAX(bxInstruction_c *i) { Bit64u rdi = RDI; write_virtual_qword_64(BX_SEG_REG_ES, rdi, RAX); if (BX_CPU_THIS_PTR get_DF()) { rdi -= 8; } else { rdi += 8; } RDI = rdi; } #endif // // REP LODS methods // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSB_ALXb(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB64_ALXb); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB32_ALXb); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSB16_ALXb); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSW_AXXw(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW64_AXXw); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW32_AXXw); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSW16_AXXw); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSD_EAXXd(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD64_EAXXd); else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD32_EAXXd); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSD16_EAXXd); } BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_LODSQ_RAXXq(bxInstruction_c *i) { if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSQ64_RAXXq); } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::LODSQ32_RAXXq); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } BX_NEXT_INSTR(i); } #endif // // LODSB/LODSW/LODSD/LODSQ methods // /* 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB16_ALXb(bxInstruction_c *i) { Bit16u si = SI; AL = read_virtual_byte_32(i->seg(), si); if (BX_CPU_THIS_PTR get_DF()) { si--; } else { si++; } SI = si; } /* 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB32_ALXb(bxInstruction_c *i) { Bit32u esi = ESI; AL = read_virtual_byte(i->seg(), esi); if (BX_CPU_THIS_PTR get_DF()) { esi--; } else { esi++; } // zero extension of RSI RSI = esi; } #if BX_SUPPORT_X86_64 /* 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSB64_ALXb(bxInstruction_c *i) { Bit64u rsi = RSI; AL = read_virtual_byte_64(i->seg(), rsi); if (BX_CPU_THIS_PTR get_DF()) { rsi--; } else { rsi++; } RSI = rsi; } #endif /* 16 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW16_AXXw(bxInstruction_c *i) { Bit16u si = SI; AX = read_virtual_word_32(i->seg(), si); if (BX_CPU_THIS_PTR get_DF()) { si -= 2; } else { si += 2; } SI = si; } /* 16 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW32_AXXw(bxInstruction_c *i) { Bit32u esi = ESI; AX = read_virtual_word(i->seg(), esi); if (BX_CPU_THIS_PTR get_DF()) { esi -= 2; } else { esi += 2; } // zero extension of RSI RSI = esi; } #if BX_SUPPORT_X86_64 /* 16 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSW64_AXXw(bxInstruction_c *i) { Bit64u rsi = RSI; AX = read_virtual_word_64(i->seg(), rsi); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 2; } else { rsi += 2; } RSI = rsi; } #endif /* 32 bit opsize mode, 16 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD16_EAXXd(bxInstruction_c *i) { Bit16u si = SI; RAX = read_virtual_dword_32(i->seg(), si); if (BX_CPU_THIS_PTR get_DF()) { si -= 4; } else { si += 4; } SI = si; } /* 32 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD32_EAXXd(bxInstruction_c *i) { Bit32u esi = ESI; RAX = read_virtual_dword(i->seg(), esi); if (BX_CPU_THIS_PTR get_DF()) { esi -= 4; } else { esi += 4; } // zero extension of RSI RSI = esi; } #if BX_SUPPORT_X86_64 /* 32 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSD64_EAXXd(bxInstruction_c *i) { Bit64u rsi = RSI; RAX = read_virtual_dword_64(i->seg(), rsi); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 4; } else { rsi += 4; } RSI = rsi; } /* 64 bit opsize mode, 32 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSQ32_RAXXq(bxInstruction_c *i) { Bit32u esi = ESI; RAX = read_virtual_qword_64(i->seg(), esi); if (BX_CPU_THIS_PTR get_DF()) { esi -= 8; } else { esi += 8; } // zero extension of RSI RSI = esi; } /* 64 bit opsize mode, 64 bit address size */ void BX_CPP_AttrRegparmN(1) BX_CPU_C::LODSQ64_RAXXq(bxInstruction_c *i) { Bit64u rsi = RSI; RAX = read_virtual_qword_64(i->seg(), rsi); if (BX_CPU_THIS_PTR get_DF()) { rsi -= 8; } else { rsi += 8; } RSI = rsi; } #endif bochs-2.6/cpu/fetchdecode.h0000644000175000017500000006643112020641453015541 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fetchdecode.h 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2005-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_COMMON_FETCHDECODE_TABLES_H #define BX_COMMON_FETCHDECODE_TABLES_H typedef struct BxOpcodeInfo_t { Bit16u Attr; Bit16u IA; const BxOpcodeInfo_t *AnotherArray; } BxOpcodeInfo_t; // // This file contains common IA-32/X86-64 opcode tables, like FPU opcode // table, 3DNow! opcode table or SSE opcode groups (choose the opcode // according to instruction prefixes) // BX_CPP_INLINE Bit16u FetchWORD(const Bit8u *iptr) { Bit16u data; ReadHostWordFromLittleEndian(iptr, data); return data; } BX_CPP_INLINE Bit32u FetchDWORD(const Bit8u *iptr) { Bit32u data; ReadHostDWordFromLittleEndian(iptr, data); return data; } #if BX_SUPPORT_X86_64 BX_CPP_INLINE Bit64u FetchQWORD(const Bit8u *iptr) { Bit64u data; ReadHostQWordFromLittleEndian(iptr, data); return data; } #endif #define BX_PREPARE_SSE (0x80) #define BX_PREPARE_AVX (0x40) struct bxIAOpcodeTable { BxExecutePtr_tR execute1; BxExecutePtr_tR execute2; Bit8u src[4]; }; enum { BX_SRC_NONE = 0, BX_SRC_EAX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_MEM_NO_VVV, BX_SRC_VVV, BX_SRC_VIB, BX_SRC_VIB_RM, // RM when VEX.W = 1, VIB otherwise BX_SRC_RM_VIB, // RM when VEX.W = 0, VIB otherwise BX_SRC_RM_VVV, // RM when VEX.W = 1, VVV otherwise BX_SRC_VVV_RM // RM when VEX.W = 0, VVV otherwise }; #define BX_SRC_XMM0 (BX_SRC_EAX) // // Common FetchDecode Opcode Tables // #include "fetchdecode_x87.h" #include "fetchdecode_sse.h" #include "fetchdecode_avx.h" #include "fetchdecode_xop.h" /* ************************************************************************ */ /* Opcode Groups */ /* ******* */ /* Group 1 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG1EbIb[8] = { // attributes defined in main area /* 0 */ { BxLockable, BX_IA_ADD_EbIb }, /* 1 */ { BxLockable, BX_IA_OR_EbIb }, /* 2 */ { BxLockable, BX_IA_ADC_EbIb }, /* 3 */ { BxLockable, BX_IA_SBB_EbIb }, /* 4 */ { BxLockable, BX_IA_AND_EbIb }, /* 5 */ { BxLockable, BX_IA_SUB_EbIb }, /* 6 */ { BxLockable, BX_IA_XOR_EbIb }, /* 7 */ { 0, BX_IA_CMP_EbIb } }; static const BxOpcodeInfo_t BxOpcodeInfoG1Ew[8] = { // attributes defined in main area /* 0 */ { BxLockable, BX_IA_ADD_EwIw }, /* 1 */ { BxLockable, BX_IA_OR_EwIw }, /* 2 */ { BxLockable, BX_IA_ADC_EwIw }, /* 3 */ { BxLockable, BX_IA_SBB_EwIw }, /* 4 */ { BxLockable, BX_IA_AND_EwIw }, /* 5 */ { BxLockable, BX_IA_SUB_EwIw }, /* 6 */ { BxLockable, BX_IA_XOR_EwIw }, /* 7 */ { 0, BX_IA_CMP_EwIw } }; static const BxOpcodeInfo_t BxOpcodeInfoG1Ed[8] = { // attributes defined in main area /* 0 */ { BxLockable, BX_IA_ADD_EdId }, /* 1 */ { BxLockable, BX_IA_OR_EdId }, /* 2 */ { BxLockable, BX_IA_ADC_EdId }, /* 3 */ { BxLockable, BX_IA_SBB_EdId }, /* 4 */ { BxLockable, BX_IA_AND_EdId }, /* 5 */ { BxLockable, BX_IA_SUB_EdId }, /* 6 */ { BxLockable, BX_IA_XOR_EdId }, /* 7 */ { 0, BX_IA_CMP_EdId } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G1Eq[8] = { // attributes defined in main area /* 0 */ { BxLockable, BX_IA_ADD_EqId }, /* 1 */ { BxLockable, BX_IA_OR_EqId }, /* 2 */ { BxLockable, BX_IA_ADC_EqId }, /* 3 */ { BxLockable, BX_IA_SBB_EqId }, /* 4 */ { BxLockable, BX_IA_AND_EqId }, /* 5 */ { BxLockable, BX_IA_SUB_EqId }, /* 6 */ { BxLockable, BX_IA_XOR_EqId }, /* 7 */ { 0, BX_IA_CMP_EqId } }; #endif /* ******** */ /* Group 1A */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoG1AEw[8] = { /* 0 */ { 0, BX_IA_POP_Ew }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoG1AEd[8] = { /* 0 */ { 0, BX_IA_POP_Ed }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G1AEq[8] = { /* 0 */ { 0, BX_IA_POP_Eq }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; #endif /* ******* */ /* Group 2 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG2Eb[8] = { /* 0 */ { 0, BX_IA_ROL_Eb }, /* 1 */ { 0, BX_IA_ROR_Eb }, /* 2 */ { 0, BX_IA_RCL_Eb }, /* 3 */ { 0, BX_IA_RCR_Eb }, /* 4 */ { 0, BX_IA_SHL_Eb }, /* 5 */ { 0, BX_IA_SHR_Eb }, /* 6 */ { 0, BX_IA_SHL_Eb }, /* 7 */ { 0, BX_IA_SAR_Eb } }; static const BxOpcodeInfo_t BxOpcodeInfoG2Ew[8] = { /* 0 */ { 0, BX_IA_ROL_Ew }, /* 1 */ { 0, BX_IA_ROR_Ew }, /* 2 */ { 0, BX_IA_RCL_Ew }, /* 3 */ { 0, BX_IA_RCR_Ew }, /* 4 */ { 0, BX_IA_SHL_Ew }, /* 5 */ { 0, BX_IA_SHR_Ew }, /* 6 */ { 0, BX_IA_SHL_Ew }, /* 7 */ { 0, BX_IA_SAR_Ew } }; static const BxOpcodeInfo_t BxOpcodeInfoG2Ed[8] = { /* 0 */ { 0, BX_IA_ROL_Ed }, /* 1 */ { 0, BX_IA_ROR_Ed }, /* 2 */ { 0, BX_IA_RCL_Ed }, /* 3 */ { 0, BX_IA_RCR_Ed }, /* 4 */ { 0, BX_IA_SHL_Ed }, /* 5 */ { 0, BX_IA_SHR_Ed }, /* 6 */ { 0, BX_IA_SHL_Ed }, /* 7 */ { 0, BX_IA_SAR_Ed } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G2Eq[8] = { /* 0 */ { 0, BX_IA_ROL_Eq }, /* 1 */ { 0, BX_IA_ROR_Eq }, /* 2 */ { 0, BX_IA_RCL_Eq }, /* 3 */ { 0, BX_IA_RCR_Eq }, /* 4 */ { 0, BX_IA_SHL_Eq }, /* 5 */ { 0, BX_IA_SHR_Eq }, /* 6 */ { 0, BX_IA_SHL_Eq }, /* 7 */ { 0, BX_IA_SAR_Eq } }; #endif /* ********* */ /* Group2 Ib */ /* ********* */ static const BxOpcodeInfo_t BxOpcodeInfoG2EbIb[8] = { // attributes defined in main area /* 0 */ { 0, BX_IA_ROL_EbIb }, /* 1 */ { 0, BX_IA_ROR_EbIb }, /* 2 */ { 0, BX_IA_RCL_EbIb }, /* 3 */ { 0, BX_IA_RCR_EbIb }, /* 4 */ { 0, BX_IA_SHL_EbIb }, /* 5 */ { 0, BX_IA_SHR_EbIb }, /* 6 */ { 0, BX_IA_SHL_EbIb }, /* 7 */ { 0, BX_IA_SAR_EbIb } }; static const BxOpcodeInfo_t BxOpcodeInfoG2EwIb[8] = { // attributes defined in main area /* 0 */ { 0, BX_IA_ROL_EwIb }, /* 1 */ { 0, BX_IA_ROR_EwIb }, /* 2 */ { 0, BX_IA_RCL_EwIb }, /* 3 */ { 0, BX_IA_RCR_EwIb }, /* 4 */ { 0, BX_IA_SHL_EwIb }, /* 5 */ { 0, BX_IA_SHR_EwIb }, /* 6 */ { 0, BX_IA_SHL_EwIb }, /* 7 */ { 0, BX_IA_SAR_EwIb } }; static const BxOpcodeInfo_t BxOpcodeInfoG2EdIb[8] = { // attributes defined in main area /* 0 */ { 0, BX_IA_ROL_EdIb }, /* 1 */ { 0, BX_IA_ROR_EdIb }, /* 2 */ { 0, BX_IA_RCL_EdIb }, /* 3 */ { 0, BX_IA_RCR_EdIb }, /* 4 */ { 0, BX_IA_SHL_EdIb }, /* 5 */ { 0, BX_IA_SHR_EdIb }, /* 6 */ { 0, BX_IA_SHL_EdIb }, /* 7 */ { 0, BX_IA_SAR_EdIb } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G2EqIb[8] = { // attributes defined in main area /* 0 */ { 0, BX_IA_ROL_EqIb }, /* 1 */ { 0, BX_IA_ROR_EqIb }, /* 2 */ { 0, BX_IA_RCL_EqIb }, /* 3 */ { 0, BX_IA_RCR_EqIb }, /* 4 */ { 0, BX_IA_SHL_EqIb }, /* 5 */ { 0, BX_IA_SHR_EqIb }, /* 6 */ { 0, BX_IA_SHL_EqIb }, /* 7 */ { 0, BX_IA_SAR_EqIb } }; #endif /* ******* */ /* Group 3 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG3Eb[8] = { /* 0 */ { BxImmediate_Ib, BX_IA_TEST_EbIb }, /* 1 */ { BxImmediate_Ib, BX_IA_TEST_EbIb }, /* 2 */ { BxLockable, BX_IA_NOT_Eb }, /* 3 */ { BxLockable, BX_IA_NEG_Eb }, /* 4 */ { 0, BX_IA_MUL_ALEb }, /* 5 */ { 0, BX_IA_IMUL_ALEb }, /* 6 */ { 0, BX_IA_DIV_ALEb }, /* 7 */ { 0, BX_IA_IDIV_ALEb } }; static const BxOpcodeInfo_t BxOpcodeInfoG3Ew[8] = { /* 0 */ { BxImmediate_Iw, BX_IA_TEST_EwIw }, /* 1 */ { BxImmediate_Iw, BX_IA_TEST_EwIw }, /* 2 */ { BxLockable, BX_IA_NOT_Ew }, /* 3 */ { BxLockable, BX_IA_NEG_Ew }, /* 4 */ { 0, BX_IA_MUL_AXEw }, /* 5 */ { 0, BX_IA_IMUL_AXEw }, /* 6 */ { 0, BX_IA_DIV_AXEw }, /* 7 */ { 0, BX_IA_IDIV_AXEw } }; static const BxOpcodeInfo_t BxOpcodeInfoG3Ed[8] = { /* 0 */ { BxImmediate_Id, BX_IA_TEST_EdId }, /* 1 */ { BxImmediate_Id, BX_IA_TEST_EdId }, /* 2 */ { BxLockable, BX_IA_NOT_Ed }, /* 3 */ { BxLockable, BX_IA_NEG_Ed }, /* 4 */ { 0, BX_IA_MUL_EAXEd }, /* 5 */ { 0, BX_IA_IMUL_EAXEd }, /* 6 */ { 0, BX_IA_DIV_EAXEd }, /* 7 */ { 0, BX_IA_IDIV_EAXEd } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G3Eq[8] = { /* 0 */ { BxImmediate_Id, BX_IA_TEST_EqId }, /* 1 */ { BxImmediate_Id, BX_IA_TEST_EqId }, /* 2 */ { BxLockable, BX_IA_NOT_Eq }, /* 3 */ { BxLockable, BX_IA_NEG_Eq }, /* 4 */ { 0, BX_IA_MUL_RAXEq }, /* 5 */ { 0, BX_IA_IMUL_RAXEq }, /* 6 */ { 0, BX_IA_DIV_RAXEq }, /* 7 */ { 0, BX_IA_IDIV_RAXEq } }; #endif /* ******* */ /* Group 4 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG4[8] = { /* 0 */ { BxLockable, BX_IA_INC_Eb }, /* 1 */ { BxLockable, BX_IA_DEC_Eb }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; /* ******* */ /* Group 5 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG5w[8] = { // attributes defined in main area /* 0 */ { BxLockable, BX_IA_INC_Ew }, /* 1 */ { BxLockable, BX_IA_DEC_Ew }, /* 2 */ { BxTraceEnd, BX_IA_CALL_Ew }, /* 3 */ { BxTraceEnd, BX_IA_CALL16_Ep }, /* 4 */ { BxTraceEnd, BX_IA_JMP_Ew }, /* 5 */ { BxTraceEnd, BX_IA_JMP16_Ep }, /* 6 */ { 0, BX_IA_PUSH_Ew }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoG5d[8] = { // attributes defined in main area /* 0 */ { BxLockable, BX_IA_INC_Ed }, /* 1 */ { BxLockable, BX_IA_DEC_Ed }, /* 2 */ { BxTraceEnd, BX_IA_CALL_Ed }, /* 3 */ { BxTraceEnd, BX_IA_CALL32_Ep }, /* 4 */ { BxTraceEnd, BX_IA_JMP_Ed }, /* 5 */ { BxTraceEnd, BX_IA_JMP32_Ep }, /* 6 */ { 0, BX_IA_PUSH_Ed }, /* 7 */ { 0, BX_IA_ERROR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G5w[8] = { /* 0 */ { BxLockable, BX_IA_INC_Ew }, /* 1 */ { BxLockable, BX_IA_DEC_Ew }, /* 2 */ { BxTraceEnd, BX_IA_CALL_Eq }, /* 3 */ { BxTraceEnd, BX_IA_CALL16_Ep }, /* 4 */ { BxTraceEnd, BX_IA_JMP_Eq }, /* 5 */ { BxTraceEnd, BX_IA_JMP16_Ep }, /* 6 */ { 0, BX_IA_PUSH_Ew }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfo64G5d[8] = { /* 0 */ { BxLockable, BX_IA_INC_Ed }, /* 1 */ { BxLockable, BX_IA_DEC_Ed }, /* 2 */ { BxTraceEnd, BX_IA_CALL_Eq }, /* 3 */ { BxTraceEnd, BX_IA_CALL32_Ep }, /* 4 */ { BxTraceEnd, BX_IA_JMP_Eq }, /* 5 */ { BxTraceEnd, BX_IA_JMP32_Ep }, /* 6 */ { 0, BX_IA_PUSH_Eq }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfo64G5q[8] = { /* 0 */ { BxLockable, BX_IA_INC_Eq }, /* 1 */ { BxLockable, BX_IA_DEC_Eq }, /* 2 */ { BxTraceEnd, BX_IA_CALL_Eq }, /* 3 */ { BxTraceEnd, BX_IA_CALL64_Ep }, // TODO: 64-bit offset for Intel /* 4 */ { BxTraceEnd, BX_IA_JMP_Eq }, /* 5 */ { BxTraceEnd, BX_IA_JMP64_Ep }, // TODO: 64-bit offset for Intel /* 6 */ { 0, BX_IA_PUSH_Eq }, /* 7 */ { 0, BX_IA_ERROR } }; #endif /* ******* */ /* Group 6 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG6[8] = { /* 0 */ { 0, BX_IA_SLDT_Ew }, /* 1 */ { 0, BX_IA_STR_Ew }, /* 2 */ { 0, BX_IA_LLDT_Ew }, /* 3 */ { 0, BX_IA_LTR_Ew }, /* 4 */ { 0, BX_IA_VERR_Ew }, /* 5 */ { 0, BX_IA_VERW_Ew }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; /* ******* */ /* Group 7 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG7[64+8] = { /* /m form */ /* 0 */ { 0, BX_IA_SGDT_Ms }, /* 1 */ { 0, BX_IA_SIDT_Ms }, /* 2 */ { 0, BX_IA_LGDT_Ms }, /* 3 */ { 0, BX_IA_LIDT_Ms }, /* 4 */ { 0, BX_IA_SMSW_Ew }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 7 */ { BxTraceEnd, BX_IA_INVLPG }, /* /r form */ /* 0F 01 C0 */ { 0, BX_IA_ERROR }, /* 0F 01 C1 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMCALL, BxOpcodeGroupSSE_ERR }, /* 0F 01 C2 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMLAUNCH, BxOpcodeGroupSSE_ERR }, /* 0F 01 C3 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMRESUME, BxOpcodeGroupSSE_ERR }, /* 0F 01 C4 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMXOFF, BxOpcodeGroupSSE_ERR }, /* 0F 01 C5 */ { 0, BX_IA_ERROR }, /* 0F 01 C6 */ { 0, BX_IA_ERROR }, /* 0F 01 C7 */ { 0, BX_IA_ERROR }, /* 0F 01 C8 */ { BxPrefixSSE, BX_IA_MONITOR, BxOpcodeGroupSSE_ERR }, /* 0F 01 C9 */ { BxPrefixSSE | BxTraceEnd, BX_IA_MWAIT, BxOpcodeGroupSSE_ERR }, /* 0F 01 CA */ { 0, BX_IA_ERROR }, /* 0F 01 CB */ { 0, BX_IA_ERROR }, /* 0F 01 CC */ { 0, BX_IA_ERROR }, /* 0F 01 CD */ { 0, BX_IA_ERROR }, /* 0F 01 CE */ { 0, BX_IA_ERROR }, /* 0F 01 CF */ { 0, BX_IA_ERROR }, /* 0F 01 D0 */ { BxPrefixSSE, BX_IA_XGETBV, BxOpcodeGroupSSE_ERR }, /* 0F 01 D1 */ { BxPrefixSSE | BxTraceEnd, BX_IA_XSETBV, BxOpcodeGroupSSE_ERR }, /* 0F 01 D2 */ { 0, BX_IA_ERROR }, /* 0F 01 D3 */ { 0, BX_IA_ERROR }, /* 0F 01 D4 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMFUNC, BxOpcodeGroupSSE_ERR }, /* 0F 01 D5 */ { 0, BX_IA_ERROR }, /* 0F 01 D6 */ { 0, BX_IA_ERROR }, /* 0F 01 D7 */ { 0, BX_IA_ERROR }, /* 0F 01 D8 */ { 0, BX_IA_VMRUN }, /* 0F 01 D9 */ { 0, BX_IA_VMMCALL }, /* 0F 01 DA */ { 0, BX_IA_VMLOAD }, /* 0F 01 DB */ { 0, BX_IA_VMSAVE }, /* 0F 01 DC */ { 0, BX_IA_STGI }, /* 0F 01 DD */ { 0, BX_IA_CLGI }, /* 0F 01 DE */ { 0, BX_IA_SKINIT }, /* 0F 01 DF */ { 0, BX_IA_INVLPGA }, /* 0F 01 E0 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E1 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E2 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E3 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E4 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E5 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E6 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E7 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E8 */ { 0, BX_IA_ERROR }, /* 0F 01 E9 */ { 0, BX_IA_ERROR }, /* 0F 01 EA */ { 0, BX_IA_ERROR }, /* 0F 01 EB */ { 0, BX_IA_ERROR }, /* 0F 01 EC */ { 0, BX_IA_ERROR }, /* 0F 01 ED */ { 0, BX_IA_ERROR }, /* 0F 01 EE */ { 0, BX_IA_ERROR }, /* 0F 01 EF */ { 0, BX_IA_ERROR }, /* 0F 01 F0 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F1 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F2 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F3 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F4 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F5 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F6 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F7 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F8 */ { 0, BX_IA_ERROR }, /* 0F 01 F9 */ { BxTraceEnd, BX_IA_RDTSCP }, // end trace to avoid multiple TSC samples in one cycle /* 0F 01 FA */ { 0, BX_IA_ERROR }, /* 0F 01 FB */ { 0, BX_IA_ERROR }, /* 0F 01 FC */ { 0, BX_IA_ERROR }, /* 0F 01 FD */ { 0, BX_IA_ERROR }, /* 0F 01 FE */ { 0, BX_IA_ERROR }, /* 0F 01 FF */ { 0, BX_IA_ERROR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfoG7q[64+8] = { /* /m form */ /* 0 */ { 0, BX_IA_SGDT64_Ms }, /* 1 */ { 0, BX_IA_SIDT64_Ms }, /* 2 */ { 0, BX_IA_LGDT64_Ms }, /* 3 */ { 0, BX_IA_LIDT64_Ms }, /* 4 */ { 0, BX_IA_SMSW_Ew }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 7 */ { BxTraceEnd, BX_IA_INVLPG }, /* /r form */ /* 0F 01 C0 */ { 0, BX_IA_ERROR }, /* 0F 01 C1 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMCALL, BxOpcodeGroupSSE_ERR }, /* 0F 01 C2 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMLAUNCH, BxOpcodeGroupSSE_ERR }, /* 0F 01 C3 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMRESUME, BxOpcodeGroupSSE_ERR }, /* 0F 01 C4 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMXOFF, BxOpcodeGroupSSE_ERR }, /* 0F 01 C5 */ { 0, BX_IA_ERROR }, /* 0F 01 C6 */ { 0, BX_IA_ERROR }, /* 0F 01 C7 */ { 0, BX_IA_ERROR }, /* 0F 01 C8 */ { BxPrefixSSE, BX_IA_MONITOR, BxOpcodeGroupSSE_ERR }, /* 0F 01 C9 */ { BxPrefixSSE | BxTraceEnd, BX_IA_MWAIT, BxOpcodeGroupSSE_ERR }, /* 0F 01 CA */ { 0, BX_IA_ERROR }, /* 0F 01 CB */ { 0, BX_IA_ERROR }, /* 0F 01 CC */ { 0, BX_IA_ERROR }, /* 0F 01 CD */ { 0, BX_IA_ERROR }, /* 0F 01 CE */ { 0, BX_IA_ERROR }, /* 0F 01 CF */ { 0, BX_IA_ERROR }, /* 0F 01 D0 */ { BxPrefixSSE, BX_IA_XGETBV, BxOpcodeGroupSSE_ERR }, /* 0F 01 D1 */ { BxPrefixSSE | BxTraceEnd, BX_IA_XSETBV, BxOpcodeGroupSSE_ERR }, /* 0F 01 D2 */ { 0, BX_IA_ERROR }, /* 0F 01 D3 */ { 0, BX_IA_ERROR }, /* 0F 01 D4 */ { BxTraceEnd | BxPrefixSSE, BX_IA_VMFUNC, BxOpcodeGroupSSE_ERR }, /* 0F 01 D5 */ { 0, BX_IA_ERROR }, /* 0F 01 D6 */ { 0, BX_IA_ERROR }, /* 0F 01 D7 */ { 0, BX_IA_ERROR }, /* 0F 01 D8 */ { 0, BX_IA_VMRUN }, /* 0F 01 D9 */ { 0, BX_IA_VMMCALL }, /* 0F 01 DA */ { 0, BX_IA_VMLOAD }, /* 0F 01 DB */ { 0, BX_IA_VMSAVE }, /* 0F 01 DC */ { 0, BX_IA_STGI }, /* 0F 01 DD */ { 0, BX_IA_CLGI }, /* 0F 01 DE */ { 0, BX_IA_SKINIT }, /* 0F 01 DF */ { 0, BX_IA_INVLPGA }, /* 0F 01 E0 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E1 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E2 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E3 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E4 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E5 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E6 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E7 */ { 0, BX_IA_SMSW_Ew }, /* 0F 01 E8 */ { 0, BX_IA_ERROR }, /* 0F 01 E9 */ { 0, BX_IA_ERROR }, /* 0F 01 EA */ { 0, BX_IA_ERROR }, /* 0F 01 EB */ { 0, BX_IA_ERROR }, /* 0F 01 EC */ { 0, BX_IA_ERROR }, /* 0F 01 ED */ { 0, BX_IA_ERROR }, /* 0F 01 EE */ { 0, BX_IA_ERROR }, /* 0F 01 EF */ { 0, BX_IA_ERROR }, /* 0F 01 F0 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F1 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F2 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F3 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F4 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F5 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F6 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F7 */ { BxTraceEnd, BX_IA_LMSW_Ew }, /* 0F 01 F8 */ { 0, BX_IA_SWAPGS }, /* 0F 01 F9 */ { BxTraceEnd, BX_IA_RDTSCP }, // end trace to avoid multiple TSC samples in one cycle /* 0F 01 FA */ { 0, BX_IA_ERROR }, /* 0F 01 FB */ { 0, BX_IA_ERROR }, /* 0F 01 FC */ { 0, BX_IA_ERROR }, /* 0F 01 FD */ { 0, BX_IA_ERROR }, /* 0F 01 FE */ { 0, BX_IA_ERROR }, /* 0F 01 FF */ { 0, BX_IA_ERROR } }; #endif /* ******* */ /* Group 8 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG8EwIb[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib, BX_IA_BT_EwIb }, /* 5 */ { BxImmediate_Ib | BxLockable, BX_IA_BTS_EwIb }, /* 6 */ { BxImmediate_Ib | BxLockable, BX_IA_BTR_EwIb }, /* 7 */ { BxImmediate_Ib | BxLockable, BX_IA_BTC_EwIb } }; static const BxOpcodeInfo_t BxOpcodeInfoG8EdIb[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib, BX_IA_BT_EdIb }, /* 5 */ { BxImmediate_Ib | BxLockable, BX_IA_BTS_EdIb }, /* 6 */ { BxImmediate_Ib | BxLockable, BX_IA_BTR_EdIb }, /* 7 */ { BxImmediate_Ib | BxLockable, BX_IA_BTC_EdIb } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G8EqIb[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib, BX_IA_BT_EqIb }, /* 5 */ { BxImmediate_Ib | BxLockable, BX_IA_BTS_EqIb }, /* 6 */ { BxImmediate_Ib | BxLockable, BX_IA_BTR_EqIb }, /* 7 */ { BxImmediate_Ib | BxLockable, BX_IA_BTC_EqIb } }; #endif /* ******* */ /* Group 9 */ /* ******* */ static const BxOpcodeInfo_t BxOpcodeInfoG9M[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { BxLockable, BX_IA_CMPXCHG8B }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxPrefixSSE, BX_IA_VMPTRLD_Mq, BxOpcodeGroupSSE_G9VMX6 }, /* 7 */ { BxPrefixSSE, BX_IA_VMPTRST_Mq, BxOpcodeGroupSSE_ERR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G9qM[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { BxLockable, BX_IA_CMPXCHG16B }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxPrefixSSE, BX_IA_VMPTRLD_Mq, BxOpcodeGroupSSE_G9VMX6 }, /* 7 */ { BxPrefixSSE, BX_IA_VMPTRST_Mq, BxOpcodeGroupSSE_ERR } }; #endif /* ******** */ /* Group 11 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoG11Eb[8] = { /* 0 */ { BxImmediate_Ib, BX_IA_MOV_EbIb }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoG11Ew[8] = { /* 0 */ { BxImmediate_Iw, BX_IA_MOV_EwIw }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoG11Ed[8] = { /* 0 */ { BxImmediate_Id, BX_IA_MOV_EdId }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfo64G11Eq[8] = { /* 0 */ { BxImmediate_Id, BX_IA_MOV_EqId }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; #endif /* ******** */ /* Group 12 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoG12R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSRLW_PqIb, BxOpcodeGroupSSE_G1202 }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSRAW_PqIb, BxOpcodeGroupSSE_G1204 }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSLLW_PqIb, BxOpcodeGroupSSE_G1206 }, /* 7 */ { 0, BX_IA_ERROR } }; /* ******** */ /* Group 13 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoG13R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSRLD_PqIb, BxOpcodeGroupSSE_G1302 }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSRAD_PqIb, BxOpcodeGroupSSE_G1304 }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSLLD_PqIb, BxOpcodeGroupSSE_G1306 }, /* 7 */ { 0, BX_IA_ERROR } }; /* ******** */ /* Group 14 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoG14R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSRLQ_PqIb, BxOpcodeGroupSSE_G1402 }, /* 3 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_PSRLDQ_UdqIb }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE, BX_IA_PSLLQ_PqIb, BxOpcodeGroupSSE_G1406 }, /* 7 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_PSLLDQ_UdqIb } }; /* ******** */ /* Group 15 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoG15[8*2] = { /* /r form */ /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { BxPrefixSSE, BX_IA_LFENCE, BxOpcodeGroupSSE_ERR }, /* 6 */ { BxPrefixSSE, BX_IA_MFENCE, BxOpcodeGroupSSE_ERR }, /* 7 */ { BxPrefixSSE, BX_IA_SFENCE, BxOpcodeGroupSSE_ERR }, /* /m form */ /* 0 */ { BxPrefixSSE, BX_IA_FXSAVE, BxOpcodeGroupSSE_ERR }, /* 1 */ { BxPrefixSSE, BX_IA_FXRSTOR, BxOpcodeGroupSSE_ERR }, /* 2 */ { BxPrefixSSE, BX_IA_LDMXCSR, BxOpcodeGroupSSE_ERR }, /* 3 */ { BxPrefixSSE, BX_IA_STMXCSR, BxOpcodeGroupSSE_ERR }, /* 4 */ { BxPrefixSSE, BX_IA_XSAVE, BxOpcodeGroupSSE_ERR }, /* 5 */ { BxPrefixSSE, BX_IA_XRSTOR, BxOpcodeGroupSSE_ERR }, /* 6 */ { BxPrefixSSE, BX_IA_XSAVEOPT, BxOpcodeGroupSSE_ERR }, /* 7 */ { BxPrefixSSE, BX_IA_CLFLUSH, BxOpcodeGroupSSE_ERR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfoG15q[8*2] = { /* /r form */ /* 0 */ { BxPrefixSSEF3, BX_IA_RDFSBASE }, /* 1 */ { BxPrefixSSEF3, BX_IA_RDGSBASE }, /* 2 */ { BxPrefixSSEF3, BX_IA_WRFSBASE }, /* 3 */ { BxPrefixSSEF3, BX_IA_WRGSBASE }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { BxPrefixSSE, BX_IA_LFENCE, BxOpcodeGroupSSE_ERR }, /* 6 */ { BxPrefixSSE, BX_IA_MFENCE, BxOpcodeGroupSSE_ERR }, /* 7 */ { BxPrefixSSE, BX_IA_SFENCE, BxOpcodeGroupSSE_ERR }, /* /m form */ /* 0 */ { BxPrefixSSE, BX_IA_FXSAVE, BxOpcodeGroupSSE_ERR }, /* 1 */ { BxPrefixSSE, BX_IA_FXRSTOR, BxOpcodeGroupSSE_ERR }, /* 2 */ { BxPrefixSSE, BX_IA_LDMXCSR, BxOpcodeGroupSSE_ERR }, /* 3 */ { BxPrefixSSE, BX_IA_STMXCSR, BxOpcodeGroupSSE_ERR }, /* 4 */ { BxPrefixSSE, BX_IA_XSAVE, BxOpcodeGroupSSE_ERR }, /* 5 */ { BxPrefixSSE, BX_IA_XRSTOR, BxOpcodeGroupSSE_ERR }, /* 6 */ { BxPrefixSSE, BX_IA_XSAVEOPT, BxOpcodeGroupSSE_ERR }, /* 7 */ { BxPrefixSSE, BX_IA_CLFLUSH, BxOpcodeGroupSSE_ERR } }; #endif static const BxOpcodeInfo_t BxOpcodeInfoMOV_RdCd[8] = { /* 0 */ { 0, BX_IA_MOV_RdCR0 }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_MOV_RdCR2 }, /* 3 */ { 0, BX_IA_MOV_RdCR3 }, /* 4 */ { 0, BX_IA_MOV_RdCR4 }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoMOV_CdRd[8] = { /* 0 */ { BxTraceEnd, BX_IA_MOV_CR0Rd }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_MOV_CR2Rd }, /* 3 */ { BxTraceEnd, BX_IA_MOV_CR3Rd }, /* 4 */ { BxTraceEnd, BX_IA_MOV_CR4Rd }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; #if BX_SUPPORT_X86_64 static const BxOpcodeInfo_t BxOpcodeInfoMOV_RqCq[8] = { /* 0 */ { 0, BX_IA_MOV_RqCR0 }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_MOV_RqCR2 }, /* 3 */ { 0, BX_IA_MOV_RqCR3 }, /* 4 */ { 0, BX_IA_MOV_RqCR4 }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoMOV_CqRq[8] = { /* 0 */ { BxTraceEnd, BX_IA_MOV_CR0Rq }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { 0, BX_IA_MOV_CR2Rq }, /* 3 */ { BxTraceEnd, BX_IA_MOV_CR3Rq }, /* 4 */ { BxTraceEnd, BX_IA_MOV_CR4Rq }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; #endif #endif // BX_COMMON_FETCHDECODE_TABLES_H bochs-2.6/cpu/mult8.cc0000644000175000017500000000642212020641453014505 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: mult8.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MUL_ALEbR(bxInstruction_c *i) { Bit8u op1 = AL; Bit8u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u product_16 = ((Bit16u) op1) * ((Bit16u) op2); Bit8u product_8l = (product_16 & 0xFF); Bit8u product_8h = product_16 >> 8; /* now write product back to destination */ AX = product_16; /* set EFLAGS */ SET_FLAGS_OSZAPC_LOGIC_8(product_8l); if(product_8h != 0) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_ALEbR(bxInstruction_c *i) { Bit8s op1 = AL; Bit8s op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit16s product_16 = op1 * op2; Bit8u product_8 = (product_16 & 0xFF); /* now write product back to destination */ AX = product_16; /* set EFLAGS: * IMUL r/m8: condition for clearing CF & OF: * AX = sign-extend of AL to 16 bits */ SET_FLAGS_OSZAPC_LOGIC_8(product_8); if(product_16 != (Bit8s) product_16) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIV_ALEbR(bxInstruction_c *i) { Bit8u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); if (op2 == 0) { exception(BX_DE_EXCEPTION, 0); } Bit16u op1 = AX; Bit16u quotient_16 = op1 / op2; Bit8u remainder_8 = op1 % op2; Bit8u quotient_8l = quotient_16 & 0xFF; if (quotient_16 != quotient_8l) { exception(BX_DE_EXCEPTION, 0); } /* now write quotient back to destination */ AL = quotient_8l; AH = remainder_8; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IDIV_ALEbR(bxInstruction_c *i) { Bit16s op1 = AX; /* check MIN_INT case */ if (op1 == ((Bit16s)0x8000)) exception(BX_DE_EXCEPTION, 0); Bit8s op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); if (op2 == 0) exception(BX_DE_EXCEPTION, 0); Bit16s quotient_16 = op1 / op2; Bit8s remainder_8 = op1 % op2; Bit8s quotient_8l = quotient_16 & 0xFF; if (quotient_16 != quotient_8l) exception(BX_DE_EXCEPTION, 0); /* now write quotient back to destination */ AL = quotient_8l; AH = remainder_8; BX_NEXT_INSTR(i); } bochs-2.6/cpu/vmfunc.cc0000644000175000017500000000523012020641453014726 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmfunc.cc 11301 2012-07-27 08:13:39Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMFUNC(bxInstruction_c *i) { #if BX_SUPPORT_VMX >= 2 if (! BX_CPU_THIS_PTR in_vmx_guest || ! SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VMFUNC_ENABLE)) exception(BX_UD_EXCEPTION, 0); VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; Bit32u function = EAX; if (function >= 64) { BX_ERROR(("VMFUNC: invalid function 0x%08x", function)); exception(BX_UD_EXCEPTION, 0); } if (0 == (vm->vmfunc_ctrls & (BX_CONST64(1)<= 2 void BX_CPU_C::vmfunc_eptp_switching(void) { Bit32u eptp_list_entry = ECX; if (eptp_list_entry >= 512) { BX_ERROR(("vmfunc_eptp_switching: invalid EPTP list entry %d", eptp_list_entry)); VMexit(VMX_VMEXIT_VMFUNC, 0); } VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; Bit64u temp_eptp; access_read_physical(vm->eptp_list_address + 8 * ECX, 8, &temp_eptp); if (! is_eptptr_valid(temp_eptp)) { BX_ERROR(("vmfunc_eptp_switching: invalid EPTP value in EPTP entry %d", ECX)); VMexit(VMX_VMEXIT_VMFUNC, 0); } vm->eptptr = temp_eptp; VMwrite64(VMCS_64BIT_CONTROL_EPTPTR, temp_eptp); TLB_flush(); } #endif bochs-2.6/cpu/cpu.cc0000644000175000017500000005423612020641453014231 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cpu.cc 11374 2012-08-26 15:49:30Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #define InstrumentICACHE 0 #if InstrumentICACHE static unsigned iCacheLookups=0; static unsigned iCacheMisses=0; #define InstrICache_StatsMask 0xffffff #define InstrICache_Stats() {\ if ((iCacheLookups & InstrICache_StatsMask) == 0) { \ BX_INFO(("ICACHE lookups: %u, misses: %u, hit rate = %6.2f%% ", \ iCacheLookups, \ iCacheMisses, \ (iCacheLookups-iCacheMisses) * 100.0f / iCacheLookups)); \ iCacheLookups = iCacheMisses = 0; \ } \ } #define InstrICache_Increment(v) (v)++ #else #define InstrICache_Stats() #define InstrICache_Increment(v) #endif void BX_CPU_C::cpu_loop(void) { #if BX_DEBUGGER BX_CPU_THIS_PTR break_point = 0; BX_CPU_THIS_PTR magic_break = 0; BX_CPU_THIS_PTR stop_reason = STOP_NO_REASON; #endif if (setjmp(BX_CPU_THIS_PTR jmp_buf_env)) { // can get here only from exception function or VMEXIT BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(0); #if BX_DEBUGGER || BX_GDBSTUB if (dbg_instruction_epilog()) return; #endif #if BX_GDBSTUB if (bx_dbg.gdbstub_enabled) return; #endif } // If the exception() routine has encountered a nasty fault scenario, // the debugger may request that control is returned to it so that // the situation may be examined. #if BX_DEBUGGER if (bx_guard.interrupt_requested) return; #endif // We get here either by a normal function call, or by a longjmp // back from an exception() call. In either case, commit the // new EIP/ESP, and set up other environmental fields. This code // mirrors similar code below, after the interrupt() call. BX_CPU_THIS_PTR prev_rip = RIP; // commit new EIP BX_CPU_THIS_PTR speculative_rsp = 0; BX_CPU_THIS_PTR EXT = 0; while (1) { // check on events which occurred for previous instructions (traps) // and ones which are asynchronous to the CPU (hardware interrupts) if (BX_CPU_THIS_PTR async_event) { if (handleAsyncEvent()) { // If request to return to caller ASAP. return; } } bxICacheEntry_c *entry = getICacheEntry(); bxInstruction_c *i = entry->i; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS for(;;) { // want to allow changing of the instruction inside instrumentation callback BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, i); RIP += i->ilen(); // when handlers chaining is enabled this single call will execute entire trace BX_CPU_CALL_METHOD(i->execute, (i)); // might iterate repeat instruction BX_SYNC_TIME_IF_SINGLE_PROCESSOR(0); if (BX_CPU_THIS_PTR async_event) break; i = getICacheEntry()->i; } #else // BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0 bxInstruction_c *last = i + (entry->tlen); for(;;) { #if BX_DEBUGGER if (BX_CPU_THIS_PTR trace) debug_disasm_instruction(BX_CPU_THIS_PTR prev_rip); #endif // want to allow changing of the instruction inside instrumentation callback BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, i); RIP += i->ilen(); BX_CPU_CALL_METHOD(i->execute, (i)); // might iterate repeat instruction BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP BX_INSTR_AFTER_EXECUTION(BX_CPU_ID, i); BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(0); // note instructions generating exceptions never reach this point #if BX_DEBUGGER || BX_GDBSTUB if (dbg_instruction_epilog()) return; #endif if (BX_CPU_THIS_PTR async_event) break; if (++i == last) { entry = getICacheEntry(); i = entry->i; last = i + (entry->tlen); } } #endif // clear stop trace magic indication that probably was set by repeat or branch32/64 BX_CPU_THIS_PTR async_event &= ~BX_ASYNC_EVENT_STOP_TRACE; } // while (1) } #if BX_SUPPORT_SMP void BX_CPU_C::cpu_run_trace(void) { if (setjmp(BX_CPU_THIS_PTR jmp_buf_env)) { // can get here only from exception function or VMEXIT BX_CPU_THIS_PTR icount++; return; } // check on events which occurred for previous instructions (traps) // and ones which are asynchronous to the CPU (hardware interrupts) if (BX_CPU_THIS_PTR async_event) { if (handleAsyncEvent()) { // If request to return to caller ASAP. return; } } bxICacheEntry_c *entry = getICacheEntry(); bxInstruction_c *i = entry->i; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS // want to allow changing of the instruction inside instrumentation callback BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, i); RIP += i->ilen(); // when handlers chaining is enabled this single call will execute entire trace BX_CPU_CALL_METHOD(i->execute, (i)); // might iterate repeat instruction if (BX_CPU_THIS_PTR async_event) { // clear stop trace magic indication that probably was set by repeat or branch32/64 BX_CPU_THIS_PTR async_event &= ~BX_ASYNC_EVENT_STOP_TRACE; } #else bxInstruction_c *last = i + (entry->tlen); for(;;) { // want to allow changing of the instruction inside instrumentation callback BX_INSTR_BEFORE_EXECUTION(BX_CPU_ID, i); RIP += i->ilen(); BX_CPU_CALL_METHOD(i->execute, (i)); // might iterate repeat instruction BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP BX_INSTR_AFTER_EXECUTION(BX_CPU_ID, i); BX_CPU_THIS_PTR icount++; if (BX_CPU_THIS_PTR async_event) { // clear stop trace magic indication that probably was set by repeat or branch32/64 BX_CPU_THIS_PTR async_event &= ~BX_ASYNC_EVENT_STOP_TRACE; break; } if (++i == last) break; } #endif // BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS } #endif bxICacheEntry_c* BX_CPU_C::getICacheEntry(void) { bx_address eipBiased = RIP + BX_CPU_THIS_PTR eipPageBias; if (eipBiased >= BX_CPU_THIS_PTR eipPageWindowSize) { prefetch(); eipBiased = RIP + BX_CPU_THIS_PTR eipPageBias; } bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrFetchPage + eipBiased; bxICacheEntry_c *entry = BX_CPU_THIS_PTR iCache.get_entry(pAddr, BX_CPU_THIS_PTR fetchModeMask); InstrICache_Increment(iCacheLookups); InstrICache_Stats(); if (entry->pAddr != pAddr) { // iCache miss. No validated instruction with matching fetch parameters // is in the iCache. InstrICache_Increment(iCacheMisses); entry = serveICacheMiss(entry, (Bit32u) eipBiased, pAddr); } return entry; } #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS // The function is called after taken branch instructions and tries to link the branch to the next trace BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::linkTrace(bxInstruction_c *i) { #if BX_SUPPORT_SMP if (BX_SMP_PROCESSORS > 1) return; #endif if (BX_CPU_THIS_PTR async_event) return; Bit32u delta = BX_CPU_THIS_PTR icount - BX_CPU_THIS_PTR icount_last_sync; if(delta >= bx_pc_system.getNumCpuTicksLeftNextEvent()) return; bxInstruction_c *next = i->getNextTrace(); if (next) { BX_EXECUTE_INSTRUCTION(next); return; } bx_address eipBiased = EIP + BX_CPU_THIS_PTR eipPageBias; if (eipBiased >= BX_CPU_THIS_PTR eipPageWindowSize) { /* prefetch(); eipBiased = RIP + BX_CPU_THIS_PTR eipPageBias; */ // You would like to have the prefetch() instead of this return; statement and link also // branches that cross page boundary but this potentially could cause functional failure. // An OS might modify the page tables and invalidate the TLB but it won't affect Bochs // execution because of a trace linked into another old trace with data before the page // invalidation. The case would be detected if doing prefetch() properly. return; } bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrFetchPage + eipBiased; bxICacheEntry_c *entry = BX_CPU_THIS_PTR iCache.get_entry(pAddr, BX_CPU_THIS_PTR fetchModeMask); InstrICache_Increment(iCacheLookups); InstrICache_Stats(); if (entry->pAddr == pAddr) // link traces - handle only hit cases { i->setNextTrace(entry->i); i = entry->i; BX_EXECUTE_INSTRUCTION(i); } } #endif #define BX_REPEAT_TIME_UPDATE_INTERVAL (BX_MAX_TRACE_LENGTH-1) void BX_CPP_AttrRegparmN(2) BX_CPU_C::repeat(bxInstruction_c *i, BxRepIterationPtr_tR execute) { // non repeated instruction if (! i->repUsedL()) { BX_CPU_CALL_REP_ITERATION(execute, (i)); return; } #if BX_X86_DEBUGGER BX_CPU_THIS_PTR in_repeat = 0; #endif #if BX_SUPPORT_X86_64 if (i->as64L()) { while(1) { if (RCX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); RCX --; } if (RCX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } else #endif if (i->as32L()) { while(1) { if (ECX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); RCX = ECX - 1; } if (ECX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } else // 16bit addrsize { while(1) { if (CX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); CX --; } if (CX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } #if BX_X86_DEBUGGER BX_CPU_THIS_PTR in_repeat = 1; #endif RIP = BX_CPU_THIS_PTR prev_rip; // repeat loop not done, restore RIP // assert magic async_event to stop trace execution BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE; } void BX_CPP_AttrRegparmN(2) BX_CPU_C::repeat_ZF(bxInstruction_c *i, BxRepIterationPtr_tR execute) { unsigned rep = i->repUsedValue(); // non repeated instruction if (! rep) { BX_CPU_CALL_REP_ITERATION(execute, (i)); return; } #if BX_X86_DEBUGGER BX_CPU_THIS_PTR in_repeat = 0; #endif if (rep == 3) { /* repeat prefix 0xF3 */ #if BX_SUPPORT_X86_64 if (i->as64L()) { while(1) { if (RCX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); RCX --; } if (! get_ZF() || RCX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } else #endif if (i->as32L()) { while(1) { if (ECX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); RCX = ECX - 1; } if (! get_ZF() || ECX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } else // 16bit addrsize { while(1) { if (CX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); CX --; } if (! get_ZF() || CX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } } else { /* repeat prefix 0xF2 */ #if BX_SUPPORT_X86_64 if (i->as64L()) { while(1) { if (RCX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); RCX --; } if (get_ZF() || RCX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } else #endif if (i->as32L()) { while(1) { if (ECX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); RCX = ECX - 1; } if (get_ZF() || ECX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } else // 16bit addrsize { while(1) { if (CX != 0) { BX_CPU_CALL_REP_ITERATION(execute, (i)); BX_INSTR_REPEAT_ITERATION(BX_CPU_ID, i); CX --; } if (get_ZF() || CX == 0) return; #if BX_DEBUGGER == 0 if (BX_CPU_THIS_PTR async_event) #endif break; // exit always if debugger enabled BX_CPU_THIS_PTR icount++; BX_SYNC_TIME_IF_SINGLE_PROCESSOR(BX_REPEAT_TIME_UPDATE_INTERVAL); } } } #if BX_X86_DEBUGGER BX_CPU_THIS_PTR in_repeat = 1; #endif RIP = BX_CPU_THIS_PTR prev_rip; // repeat loop not done, restore RIP // assert magic async_event to stop trace execution BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE; } // boundaries of consideration: // // * physical memory boundary: 1024k (1Megabyte) (increments of...) // * A20 boundary: 1024k (1Megabyte) // * page boundary: 4k // * ROM boundary: 2k (dont care since we are only reading) // * segment boundary: any void BX_CPU_C::prefetch(void) { bx_address laddr; unsigned pageOffset; #if BX_SUPPORT_X86_64 if (long64_mode()) { if (! IsCanonical(RIP)) { BX_ERROR(("prefetch: #GP(0): RIP crossed canonical boundary")); exception(BX_GP_EXCEPTION, 0); } // linear address is equal to RIP in 64-bit long mode pageOffset = PAGE_OFFSET(EIP); laddr = RIP; // Calculate RIP at the beginning of the page. BX_CPU_THIS_PTR eipPageBias = pageOffset - RIP; BX_CPU_THIS_PTR eipPageWindowSize = 4096; } else #endif { #if BX_CPU_LEVEL >= 5 if (USER_PL && BX_CPU_THIS_PTR get_VIP() && BX_CPU_THIS_PTR get_VIF()) { if (BX_CPU_THIS_PTR cr4.get_PVI() | (v8086_mode() && BX_CPU_THIS_PTR cr4.get_VME())) { BX_ERROR(("prefetch: inconsistent VME state")); exception(BX_GP_EXCEPTION, 0); } } #endif BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RIP); /* avoid 32-bit EIP wrap */ laddr = get_laddr32(BX_SEG_REG_CS, EIP); pageOffset = PAGE_OFFSET(laddr); // Calculate RIP at the beginning of the page. BX_CPU_THIS_PTR eipPageBias = (bx_address) pageOffset - EIP; Bit32u limit = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled; if (EIP > limit) { BX_ERROR(("prefetch: EIP [%08x] > CS.limit [%08x]", EIP, limit)); exception(BX_GP_EXCEPTION, 0); } BX_CPU_THIS_PTR eipPageWindowSize = 4096; if (limit + BX_CPU_THIS_PTR eipPageBias < 4096) { BX_CPU_THIS_PTR eipPageWindowSize = (Bit32u)(limit + BX_CPU_THIS_PTR eipPageBias + 1); } } #if BX_X86_DEBUGGER if (hwbreakpoint_check(laddr, BX_HWDebugInstruction, BX_HWDebugInstruction)) { BX_CPU_THIS_PTR async_event = 1; BX_CPU_THIS_PTR codebp = 1; if (! interrupts_inhibited(BX_INHIBIT_DEBUG)) { // The next instruction could already hit a code breakpoint but // async_event won't take effect immediatelly. // Check if the next executing instruction hits code breakpoint // check only if not fetching page cross instruction // this check is 32-bit wrap safe as well if (EIP == (Bit32u) BX_CPU_THIS_PTR prev_rip) { Bit32u dr6_bits = code_breakpoint_match(laddr); if (dr6_bits & BX_DEBUG_TRAP_HIT) { BX_ERROR(("#DB: x86 code breakpoint catched")); BX_CPU_THIS_PTR debug_trap |= dr6_bits; exception(BX_DB_EXCEPTION, 0); } } } } else { BX_CPU_THIS_PTR codebp = 0; } #endif BX_CPU_THIS_PTR clear_RF(); bx_address lpf = LPFOf(laddr); unsigned TLB_index = BX_TLB_INDEX_OF(lpf, 0); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[TLB_index]; Bit8u *fetchPtr = 0; if ((tlbEntry->lpf == lpf) && !(tlbEntry->accessBits & (0x4 | USER_PL))) { BX_CPU_THIS_PTR pAddrFetchPage = tlbEntry->ppf; fetchPtr = (Bit8u*) tlbEntry->hostPageAddr; } else { bx_phy_address pAddr = translate_linear(laddr, USER_PL, BX_EXECUTE); BX_CPU_THIS_PTR pAddrFetchPage = PPFOf(pAddr); } if (fetchPtr) { BX_CPU_THIS_PTR eipFetchPtr = fetchPtr; } else { BX_CPU_THIS_PTR eipFetchPtr = (const Bit8u*) getHostMemAddr(BX_CPU_THIS_PTR pAddrFetchPage, BX_EXECUTE); // Sanity checks if (! BX_CPU_THIS_PTR eipFetchPtr) { bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrFetchPage + pageOffset; if (pAddr >= BX_MEM(0)->get_memory_len()) { BX_PANIC(("prefetch: running in bogus memory, pAddr=0x" FMT_PHY_ADDRX, pAddr)); } else { BX_PANIC(("prefetch: getHostMemAddr vetoed direct read, pAddr=0x" FMT_PHY_ADDRX, pAddr)); } } } } #if BX_DEBUGGER || BX_GDBSTUB bx_bool BX_CPU_C::dbg_instruction_epilog(void) { #if BX_DEBUGGER bx_address debug_eip = RIP; Bit16u cs = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value; BX_CPU_THIS_PTR guard_found.cs = cs; BX_CPU_THIS_PTR guard_found.eip = debug_eip; BX_CPU_THIS_PTR guard_found.laddr = get_laddr(BX_SEG_REG_CS, debug_eip); BX_CPU_THIS_PTR guard_found.code_32_64 = BX_CPU_THIS_PTR fetchModeMask; // // Take care of break point conditions generated during instruction execution // // Check if we hit read/write or time breakpoint if (BX_CPU_THIS_PTR break_point) { Bit64u tt = bx_pc_system.time_ticks(); switch (BX_CPU_THIS_PTR break_point) { case BREAK_POINT_TIME: BX_INFO(("[" FMT_LL "d] Caught time breakpoint", tt)); BX_CPU_THIS_PTR stop_reason = STOP_TIME_BREAK_POINT; return(1); // on a breakpoint case BREAK_POINT_READ: BX_INFO(("[" FMT_LL "d] Caught read watch point", tt)); BX_CPU_THIS_PTR stop_reason = STOP_READ_WATCH_POINT; return(1); // on a breakpoint case BREAK_POINT_WRITE: BX_INFO(("[" FMT_LL "d] Caught write watch point", tt)); BX_CPU_THIS_PTR stop_reason = STOP_WRITE_WATCH_POINT; return(1); // on a breakpoint default: BX_PANIC(("Weird break point condition")); } } if (BX_CPU_THIS_PTR magic_break) { BX_INFO(("[" FMT_LL "d] Stopped on MAGIC BREAKPOINT", bx_pc_system.time_ticks())); BX_CPU_THIS_PTR stop_reason = STOP_MAGIC_BREAK_POINT; return(1); // on a breakpoint } // see if debugger requesting icount guard if (bx_guard.guard_for & BX_DBG_GUARD_ICOUNT) { if (get_icount() >= BX_CPU_THIS_PTR guard_found.icount_max) { return(1); } } // convenient point to see if user requested debug break or typed Ctrl-C if (bx_guard.interrupt_requested) { return(1); } // support for 'show' command in debugger extern unsigned dbg_show_mask; if(dbg_show_mask) { int rv = bx_dbg_show_symbolic(); if (rv) return(rv); } // Just committed an instruction, before fetching a new one // see if debugger is looking for iaddr breakpoint of any type if (bx_guard.guard_for & BX_DBG_GUARD_IADDR_ALL) { #if (BX_DBG_MAX_VIR_BPOINTS > 0) if (bx_guard.guard_for & BX_DBG_GUARD_IADDR_VIR) { for (unsigned n=0; n 0) if (bx_guard.guard_for & BX_DBG_GUARD_IADDR_LIN) { for (unsigned n=0; n 0) if (bx_guard.guard_for & BX_DBG_GUARD_IADDR_PHY) { bx_phy_address phy; bx_bool valid = dbg_xlate_linear2phy(BX_CPU_THIS_PTR guard_found.laddr, &phy); if (valid) { for (unsigned n=0; nsrc()); Bit64u product_64 = ((Bit64u) op1_32) * ((Bit64u) op2_32); Bit32u product_32l = GET32L(product_64); Bit32u product_32h = GET32H(product_64); /* now write product back to destination */ RAX = product_32l; RDX = product_32h; /* set EFLAGS */ SET_FLAGS_OSZAPC_LOGIC_32(product_32l); if(product_32h != 0) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_EAXEdR(bxInstruction_c *i) { Bit32s op1_32 = EAX; Bit32s op2_32 = BX_READ_32BIT_REG(i->src()); Bit64s product_64 = ((Bit64s) op1_32) * ((Bit64s) op2_32); Bit32u product_32l = GET32L(product_64); Bit32u product_32h = GET32H(product_64); /* now write product back to destination */ RAX = product_32l; RDX = product_32h; /* set eflags: * IMUL r/m32: condition for clearing CF & OF: * EDX:EAX = sign-extend of EAX */ SET_FLAGS_OSZAPC_LOGIC_32(product_32l); if(product_64 != (Bit32s)product_64) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIV_EAXEdR(bxInstruction_c *i) { Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); if (op2_32 == 0) { exception(BX_DE_EXCEPTION, 0); } Bit64u op1_64 = (((Bit64u) EDX) << 32) + ((Bit64u) EAX); Bit64u quotient_64 = op1_64 / op2_32; Bit32u remainder_32 = (Bit32u) (op1_64 % op2_32); Bit32u quotient_32l = (Bit32u) (quotient_64 & 0xFFFFFFFF); if (quotient_64 != quotient_32l) { exception(BX_DE_EXCEPTION, 0); } /* set EFLAGS: * DIV affects the following flags: O,S,Z,A,P,C are undefined */ /* now write quotient back to destination */ RAX = quotient_32l; RDX = remainder_32; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IDIV_EAXEdR(bxInstruction_c *i) { Bit64s op1_64 = (((Bit64u) EDX) << 32) | ((Bit64u) EAX); /* check MIN_INT case */ if (op1_64 == ((Bit64s)BX_CONST64(0x8000000000000000))) exception(BX_DE_EXCEPTION, 0); Bit32s op2_32 = BX_READ_32BIT_REG(i->src()); if (op2_32 == 0) exception(BX_DE_EXCEPTION, 0); Bit64s quotient_64 = op1_64 / op2_32; Bit32s remainder_32 = (Bit32s) (op1_64 % op2_32); Bit32s quotient_32l = (Bit32s) (quotient_64 & 0xFFFFFFFF); if (quotient_64 != quotient_32l) { exception(BX_DE_EXCEPTION, 0); } /* set EFLAGS: * IDIV affects the following flags: O,S,Z,A,P,C are undefined */ /* now write quotient back to destination */ RAX = (Bit32u) quotient_32l; RDX = (Bit32u) remainder_32; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GdEdIdR(bxInstruction_c *i) { Bit32s op2_32 = BX_READ_32BIT_REG(i->src()); Bit32s op3_32 = i->Id(); Bit64s product_64 = ((Bit64s) op2_32) * ((Bit64s) op3_32); Bit32u product_32 = (Bit32u)(product_64 & 0xFFFFFFFF); /* now write product back to destination */ BX_WRITE_32BIT_REGZ(i->dst(), product_32); /* set eflags: * IMUL r32,r/m32,imm32: condition for clearing CF & OF: * result exactly fits within r32 */ SET_FLAGS_OSZAPC_LOGIC_32(product_32); if(product_64 != (Bit32s) product_64) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GdEdR(bxInstruction_c *i) { Bit32s op1_32 = BX_READ_32BIT_REG(i->dst()); Bit32s op2_32 = BX_READ_32BIT_REG(i->src()); Bit64s product_64 = ((Bit64s) op1_32) * ((Bit64s) op2_32); Bit32u product_32 = (Bit32u)(product_64 & 0xFFFFFFFF); /* now write product back to destination */ BX_WRITE_32BIT_REGZ(i->dst(), product_32); /* set eflags: * IMUL r32,r/m32: condition for clearing CF & OF: * result exactly fits within r32 */ SET_FLAGS_OSZAPC_LOGIC_32(product_32); if(product_64 != (Bit32s) product_64) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } bochs-2.6/cpu/jmp_far.cc0000644000175000017500000002253512020641453015055 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: jmp_far.cc 10969 2012-01-11 20:21:29Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2005-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // //////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(3) BX_CPU_C::jump_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp) { bx_descriptor_t descriptor; bx_selector_t selector; Bit32u dword1, dword2; /* destination selector is not null else #GP(0) */ if ((cs_raw & 0xfffc) == 0) { BX_ERROR(("jump_protected: cs == 0")); exception(BX_GP_EXCEPTION, 0); } parse_selector(cs_raw, &selector); /* destination selector index is within its descriptor table limits else #GP(selector) */ fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION); /* examine AR byte of destination selector for legal values: */ parse_descriptor(dword1, dword2, &descriptor); if (descriptor.segment) { check_cs(&descriptor, cs_raw, BX_SELECTOR_RPL(cs_raw), CPL); branch_far64(&selector, &descriptor, disp, CPL); return; } else { // call gate DPL must be >= CPL else #GP(gate selector) if (descriptor.dpl < CPL) { BX_ERROR(("jump_protected: call gate.dpl < CPL")); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } // call gate DPL must be >= gate selector RPL else #GP(gate selector) if (descriptor.dpl < selector.rpl) { BX_ERROR(("jump_protected: call gate.dpl < selector.rpl")); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } #if BX_SUPPORT_X86_64 if (long_mode()) { if (descriptor.type != BX_386_CALL_GATE) { BX_ERROR(("jump_protected: gate type %u unsupported in long mode", (unsigned) descriptor.type)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } // gate must be present else #NP(gate selector) if (! IS_PRESENT(descriptor)) { BX_ERROR(("jump_protected: call gate not present!")); exception(BX_NP_EXCEPTION, cs_raw & 0xfffc); } jmp_call_gate64(&selector); return; } #endif switch (descriptor.type) { case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_AVAIL_386_TSS: if (descriptor.type==BX_SYS_SEGMENT_AVAIL_286_TSS) BX_DEBUG(("jump_protected: jump to 286 TSS")); else BX_DEBUG(("jump_protected: jump to 386 TSS")); if (descriptor.valid==0 || selector.ti) { BX_ERROR(("jump_protected: jump to bad TSS selector !")); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } // TSS must be present, else #NP(TSS selector) if (! IS_PRESENT(descriptor)) { BX_ERROR(("jump_protected: jump to not present TSS !")); exception(BX_NP_EXCEPTION, cs_raw & 0xfffc); } // SWITCH_TASKS _without_ nesting to TSS task_switch(i, &selector, &descriptor, BX_TASK_FROM_JUMP, dword1, dword2); return; case BX_TASK_GATE: task_gate(i, &selector, &descriptor, BX_TASK_FROM_JUMP); return; case BX_286_CALL_GATE: case BX_386_CALL_GATE: jmp_call_gate(&selector, &descriptor); return; default: BX_ERROR(("jump_protected: gate type %u unsupported", (unsigned) descriptor.type)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } } } void BX_CPU_C::task_gate(bxInstruction_c *i, bx_selector_t *selector, bx_descriptor_t *gate_descriptor, unsigned source) { Bit16u raw_tss_selector; bx_selector_t tss_selector; bx_descriptor_t tss_descriptor; Bit32u dword1, dword2; // task gate must be present else #NP(gate selector) if (! gate_descriptor->p) { BX_ERROR(("task_gate: task gate not present")); exception(BX_NP_EXCEPTION, selector->value & 0xfffc); } // examine selector to TSS, given in Task Gate descriptor // must specify global in the local/global bit else #GP(TSS selector) raw_tss_selector = gate_descriptor->u.taskgate.tss_selector; parse_selector(raw_tss_selector, &tss_selector); if (tss_selector.ti) { BX_ERROR(("task_gate: tss_selector.ti=1")); exception(BX_GP_EXCEPTION, raw_tss_selector & 0xfffc); } // index must be within GDT limits else #GP(TSS selector) fetch_raw_descriptor(&tss_selector, &dword1, &dword2, BX_GP_EXCEPTION); // descriptor AR byte must specify available TSS // else #GP(TSS selector) parse_descriptor(dword1, dword2, &tss_descriptor); if (tss_descriptor.valid==0 || tss_descriptor.segment) { BX_ERROR(("task_gate: TSS selector points to bad TSS")); exception(BX_GP_EXCEPTION, raw_tss_selector & 0xfffc); } if (tss_descriptor.type!=BX_SYS_SEGMENT_AVAIL_286_TSS && tss_descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS) { BX_ERROR(("task_gate: TSS selector points to bad TSS")); exception(BX_GP_EXCEPTION, raw_tss_selector & 0xfffc); } // task state segment must be present, else #NP(tss selector) if (! IS_PRESENT(tss_descriptor)) { BX_ERROR(("task_gate: TSS descriptor.p == 0")); exception(BX_NP_EXCEPTION, raw_tss_selector & 0xfffc); } // SWITCH_TASKS _without_ nesting to TSS task_switch(i, &tss_selector, &tss_descriptor, source, dword1, dword2); } void BX_CPP_AttrRegparmN(2) BX_CPU_C::jmp_call_gate(bx_selector_t *selector, bx_descriptor_t *gate_descriptor) { bx_selector_t gate_cs_selector; bx_descriptor_t gate_cs_descriptor; Bit32u dword1, dword2; if (gate_descriptor->type==BX_286_CALL_GATE) BX_DEBUG(("jmp_call_gate: jump to 286 CALL GATE")); else BX_DEBUG(("jmp_call_gate: jump to 386 CALL GATE")); // task gate must be present else #NP(gate selector) if (! gate_descriptor->p) { BX_ERROR(("jmp_call_gate: call gate not present!")); exception(BX_NP_EXCEPTION, selector->value & 0xfffc); } // examine selector to code segment given in call gate descriptor // selector must not be null, else #GP(0) Bit16u gate_cs_raw = gate_descriptor->u.gate.dest_selector; if ((gate_cs_raw & 0xfffc) == 0) { BX_ERROR(("jmp_call_gate: CS selector null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(gate_cs_raw, &gate_cs_selector); // selector must be within its descriptor table limits else #GP(CS selector) fetch_raw_descriptor(&gate_cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &gate_cs_descriptor); // check code-segment descriptor check_cs(&gate_cs_descriptor, gate_cs_raw, 0, CPL); Bit32u temp_EIP = gate_descriptor->u.gate.dest_offset; branch_far32(&gate_cs_selector, &gate_cs_descriptor, temp_EIP, CPL); } #if BX_SUPPORT_X86_64 void BX_CPP_AttrRegparmN(1) BX_CPU_C::jmp_call_gate64(bx_selector_t *gate_selector) { bx_selector_t cs_selector; Bit32u dword1, dword2, dword3; bx_descriptor_t cs_descriptor; bx_descriptor_t gate_descriptor; BX_DEBUG(("jmp_call_gate64: jump to CALL GATE 64")); fetch_raw_descriptor_64(gate_selector, &dword1, &dword2, &dword3, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &gate_descriptor); Bit16u dest_selector = gate_descriptor.u.gate.dest_selector; // selector must not be null else #GP(0) if ((dest_selector & 0xfffc) == 0) { BX_ERROR(("jmp_call_gate64: selector in gate null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(dest_selector, &cs_selector); // selector must be within its descriptor table limits, // else #GP(code segment selector) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // find the RIP in the gate_descriptor Bit64u new_RIP = gate_descriptor.u.gate.dest_offset; new_RIP |= ((Bit64u)dword3 << 32); // AR byte of selected descriptor must indicate code segment, // else #GP(code segment selector) if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || IS_DATA_SEGMENT(cs_descriptor.type)) { BX_ERROR(("jmp_call_gate64: not code segment in 64-bit call gate")); exception(BX_GP_EXCEPTION, dest_selector & 0xfffc); } // In long mode, only 64-bit call gates are allowed, and they must point // to 64-bit code segments, else #GP(selector) if (! IS_LONG64_SEGMENT(cs_descriptor) || cs_descriptor.u.segment.d_b) { BX_ERROR(("jmp_call_gate64: not 64-bit code segment in 64-bit call gate")); exception(BX_GP_EXCEPTION, dest_selector & 0xfffc); } // check code-segment descriptor check_cs(&cs_descriptor, dest_selector, 0, CPL); // and transfer the control branch_far64(&cs_selector, &cs_descriptor, new_RIP, CPL); } #endif bochs-2.6/cpu/bmi64.cc0000644000175000017500000001643312020641453014360 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bmi64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 #if BX_SUPPORT_AVX BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ANDN_GqBqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src1()); Bit64u op2_64 = BX_READ_64BIT_REG(i->src2()); op1_64 = ~op1_64 & op2_64; SET_FLAGS_OSZAxC_LOGIC_64(op1_64); // keep PF unchanged BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } extern void long_mul(Bit128u *product, Bit64u op1, Bit64u op2); BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MULX_GqBqEqR(bxInstruction_c *i) { Bit64u op1_64 = RDX; Bit64u op2_64 = BX_READ_64BIT_REG(i->src2()); Bit128u product_128; // product_128 = ((Bit128u) op1_64) * ((Bit128u) op2_64); // product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF); // product_64h = (Bit64u) (product_128 >> 64); long_mul(&product_128,op1_64,op2_64); BX_WRITE_64BIT_REG(i->src1(), product_128.lo); BX_WRITE_64BIT_REG(i->dst(), product_128.hi); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSI_BqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src()); bx_bool tmpCF = (op1_64 != 0); op1_64 = (-op1_64) & op1_64; SET_FLAGS_OSZAxC_LOGIC_64(op1_64); // keep PF unchanged set_CF(tmpCF); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSMSK_BqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src()); bx_bool tmpCF = (op1_64 == 0); op1_64 = (op1_64-1) ^ op1_64; SET_FLAGS_OSZAxC_LOGIC_64(op1_64); // keep PF unchanged set_CF(tmpCF); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSR_BqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src()); bx_bool tmpCF = (op1_64 == 0); op1_64 = (op1_64-1) & op1_64; SET_FLAGS_OSZAxC_LOGIC_64(op1_64); // keep PF unchanged set_CF(tmpCF); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RORX_GqEqIbR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src()); unsigned count = i->Ib() & 0x3f; if (count) { op1_64 = (op1_64 >> count) | (op1_64 << (64 - count)); } BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRX_GqEqBqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src1()); unsigned count = BX_READ_32BIT_REG(i->src2()) & 0x3f; if (count) op1_64 >>= count; BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SARX_GqEqBqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src1()); unsigned count = BX_READ_32BIT_REG(i->src2()) & 0x3f; if (count) { /* count < 64, since only lower 6 bits used */ op1_64 = ((Bit64s) op1_64) >> count; } BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLX_GqEqBqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src1()); unsigned count = BX_READ_32BIT_REG(i->src2()) & 0x3f; if (count) op1_64 <<= count; BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BEXTR_GqEqBqR(bxInstruction_c *i) { Bit16u control = BX_READ_16BIT_REG(i->src2()); unsigned start = control & 0xff; unsigned len = control >> 8; Bit64u op1_64 = 0; if (start < 64 && len > 0) { op1_64 = BX_READ_64BIT_REG(i->src1()); op1_64 >>= start; if (len < 64) { Bit64u extract_mask = (BX_CONST64(1) << len) - 1; op1_64 &= extract_mask; } } SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BZHI_GqEqBqR(bxInstruction_c *i) { unsigned control = BX_READ_16BIT_REG(i->src1()) & 0xff; bx_bool tmpCF = 0; Bit64u op1_64 = BX_READ_64BIT_REG(i->src2()); if (control < 64) { Bit64u mask = (BX_CONST64(1) << control) - 1; op1_64 &= mask; } else { tmpCF = 1; } SET_FLAGS_OSZAxC_LOGIC_64(op1_64); // keep PF unchanged set_CF(tmpCF); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXT_GqEqBqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src1()); Bit64u op2_64 = BX_READ_64BIT_REG(i->src2()), result_64 = 0; Bit64u wr_mask = 0x1; for (; op2_64 != 0; op2_64 >>= 1) { if (op2_64 & 0x1) { if (op1_64 & 0x1) result_64 |= wr_mask; wr_mask <<= 1; } op1_64 >>= 1; } BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PDEP_GqEqBqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src1()); Bit64u op2_64 = BX_READ_64BIT_REG(i->src2()), result_64 = 0; Bit64u wr_mask = 0x1; for (; op2_64 != 0; op2_64 >>= 1) { if (op2_64 & 0x1) { if (op1_64 & 0x1) result_64 |= wr_mask; op1_64 >>= 1; } wr_mask <<= 1; } BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } #endif // BX_SUPPORT_AVX BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADCX_GqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); Bit64u sum_64 = op1_64 + op2_64 + getB_CF(); BX_WRITE_64BIT_REG(i->dst(), sum_64); Bit64u carry_out = ADD_COUT_VEC(op1_64, op2_64, sum_64); set_CF(carry_out >> 63); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADOX_GqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); Bit64u sum_64 = op1_64 + op2_64 + getB_OF(); BX_WRITE_64BIT_REG(i->dst(), sum_64); Bit64u overflow = GET_ADD_OVERFLOW(op1_64, op2_64, sum_64, BX_CONST64(0x8000000000000000)); set_OF(!!overflow); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/paging.cc0000644000175000017500000021245212020641453014703 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: paging.cc 11299 2012-07-26 16:03:26Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR // X86 Registers Which Affect Paging: // ================================== // // CR0: // bit 31: PG, Paging (386+) // bit 16: WP, Write Protect (486+) // 0: allow supervisor level writes into user level RO pages // 1: inhibit supervisor level writes into user level RO pages // // CR3: // bit 31..12: PDBR, Page Directory Base Register (386+) // bit 4: PCD, Page level Cache Disable (486+) // Controls caching of current page directory. Affects only the processor's // internal caches (L1 and L2). // This flag ignored if paging disabled (PG=0) or cache disabled (CD=1). // Values: // 0: Page Directory can be cached // 1: Page Directory not cached // bit 3: PWT, Page level Writes Transparent (486+) // Controls write-through or write-back caching policy of current page // directory. Affects only the processor's internal caches (L1 and L2). // This flag ignored if paging disabled (PG=0) or cache disabled (CD=1). // Values: // 0: write-back caching enabled // 1: write-through caching enabled // // CR4: // bit 4: PSE, Page Size Extension (Pentium+) // 0: 4KByte pages (typical) // 1: 4MByte or 2MByte pages // bit 5: PAE, Physical Address Extension (Pentium Pro+) // 0: 32bit physical addresses // 1: 36bit physical addresses // bit 7: PGE, Page Global Enable (Pentium Pro+) // The global page feature allows frequently used or shared pages // to be marked as global (PDE or PTE bit 8). Global pages are // not flushed from TLB on a task switch or write to CR3. // Values: // 0: disables global page feature // 1: enables global page feature // // page size extention and physical address size extention matrix (legacy mode) // ============================================================================== // CR0.PG CR4.PAE CR4.PSE PDPE.PS PDE.PS | page size physical address size // ============================================================================== // 0 X X R X | -- paging disabled // 1 0 0 R X | 4K 32bits // 1 0 1 R 0 | 4K 32bits // 1 0 1 R 1 | 4M 32bits // 1 1 X R 0 | 4K 36bits // 1 1 X R 1 | 2M 36bits // page size extention and physical address size extention matrix (long mode) // ============================================================================== // CR0.PG CR4.PAE CR4.PSE PDPE.PS PDE.PS | page size physical address size // ============================================================================== // 1 1 X 0 0 | 4K 52bits // 1 1 X 0 1 | 2M 52bits // 1 1 X 1 - | 1G 52bits // Page Directory/Table Entry Fields Defined: // ========================================== // NX: No Execute // This bit controls the ability to execute code from all physical // pages mapped by the table entry. // 0: Code can be executed from the mapped physical pages // 1: Code cannot be executed // The NX bit can only be set when the no-execute page-protection // feature is enabled by setting EFER.NXE=1, If EFER.NXE=0, the // NX bit is treated as reserved. In this case, #PF occurs if the // NX bit is not cleared to zero. // // G: Global flag // Indiciates a global page when set. When a page is marked // global and the PGE flag in CR4 is set, the page table or // directory entry for the page is not invalidated in the TLB // when CR3 is loaded or a task switch occurs. Only software // clears and sets this flag. For page directory entries that // point to page tables, this flag is ignored and the global // characteristics of a page are set in the page table entries. // // PS: Page Size flag // Only used in page directory entries. When PS=0, the page // size is 4KBytes and the page directory entry points to a // page table. When PS=1, the page size is 4MBytes for // normal 32-bit addressing and 2MBytes if extended physical // addressing. // // PAT: Page-Attribute Table // This bit is only present in the lowest level of the page // translation hierarchy. The PAT bit is the high-order bit // of a 3-bit index into the PAT register. The other two // bits involved in forming the index are the PCD and PWT // bits. // // D: Dirty bit: // Processor sets the Dirty bit in the 2nd-level page table before a // write operation to an address mapped by that page table entry. // Dirty bit in directory entries is undefined. // // A: Accessed bit: // Processor sets the Accessed bits in both levels of page tables before // a read/write operation to a page. // // PCD: Page level Cache Disable // Controls caching of individual pages or page tables. // This allows a per-page based mechanism to disable caching, for // those pages which contained memory mapped IO, or otherwise // should not be cached. Processor ignores this flag if paging // is not used (CR0.PG=0) or the cache disable bit is set (CR0.CD=1). // Values: // 0: page or page table can be cached // 1: page or page table is not cached (prevented) // // PWT: Page level Write Through // Controls the write-through or write-back caching policy of individual // pages or page tables. Processor ignores this flag if paging // is not used (CR0.PG=0) or the cache disable bit is set (CR0.CD=1). // Values: // 0: write-back caching // 1: write-through caching // // U/S: User/Supervisor level // 0: Supervisor level - for the OS, drivers, etc. // 1: User level - application code and data // // R/W: Read/Write access // 0: read-only access // 1: read/write access // // P: Present // 0: Not present // 1: Present // ========================================== // Combined page directory/page table protection: // ============================================== // There is one column for the combined effect on a 386 // and one column for the combined effect on a 486+ CPU. // The 386 CPU behavior is not supported by Bochs. // // +----------------+-----------------+----------------+----------------+ // | Page Directory| Page Table | Combined 386 | Combined 486+ | // |Privilege Type | Privilege Type | Privilege Type| Privilege Type| // |----------------+-----------------+----------------+----------------| // |User R | User R | User R | User R | // |User R | User RW | User R | User R | // |User RW | User R | User R | User R | // |User RW | User RW | User RW | User RW | // |User R | Supervisor R | User R | Supervisor RW | // |User R | Supervisor RW | User R | Supervisor RW | // |User RW | Supervisor R | User R | Supervisor RW | // |User RW | Supervisor RW | User RW | Supervisor RW | // |Supervisor R | User R | User R | Supervisor RW | // |Supervisor R | User RW | User R | Supervisor RW | // |Supervisor RW | User R | User R | Supervisor RW | // |Supervisor RW | User RW | User RW | Supervisor RW | // |Supervisor R | Supervisor R | Supervisor RW | Supervisor RW | // |Supervisor R | Supervisor RW | Supervisor RW | Supervisor RW | // |Supervisor RW | Supervisor R | Supervisor RW | Supervisor RW | // |Supervisor RW | Supervisor RW | Supervisor RW | Supervisor RW | // +----------------+-----------------+----------------+----------------+ // Page Fault Error Code Format: // ============================= // // bits 31..4: Reserved // bit 3: RSVD (Pentium Pro+) // 0: fault caused by reserved bits set to 1 in a page directory // when the PSE or PAE flags in CR4 are set to 1 // 1: fault was not caused by reserved bit violation // bit 2: U/S (386+) // 0: fault originated when in supervior mode // 1: fault originated when in user mode // bit 1: R/W (386+) // 0: access causing the fault was a read // 1: access causing the fault was a write // bit 0: P (386+) // 0: fault caused by a nonpresent page // 1: fault caused by a page level protection violation // Some paging related notes: // ========================== // // - When the processor is running in supervisor level, all pages are both // readable and writable (write-protect ignored). When running at user // level, only pages which belong to the user level are accessible; // read/write & read-only are readable, read/write are writable. // // - If the Present bit is 0 in either level of page table, an // access which uses these entries will generate a page fault. // // - (A)ccess bit is used to report read or write access to a page // or 2nd level page table. // // - (D)irty bit is used to report write access to a page. // // - Processor running at CPL=0,1,2 maps to U/S=0 // Processor running at CPL=3 maps to U/S=1 #if BX_SUPPORT_X86_64 #define BX_INVALID_TLB_ENTRY BX_CONST64(0xffffffffffffffff) #else #define BX_INVALID_TLB_ENTRY 0xffffffff #endif // bit [11] of the TLB lpf used for TLB_NoHostPtr valid indication #define TLB_LPFOf(laddr) AlignedAccessLPFOf(laddr, 0x7ff) #if BX_CPU_LEVEL >= 4 # define BX_PRIV_CHECK_SIZE 32 #else # define BX_PRIV_CHECK_SIZE 16 #endif // The 'priv_check' array is used to decide if the current access // has the proper paging permissions. An index is formed, based // on parameters such as the access type and level, the write protect // flag and values cached in the TLB. The format of the index into this // array is: // // |4 |3 |2 |1 |0 | // |wp|us|us|rw|rw| // | | | | | // | | | | +---> r/w of current access // | | +--+------> u/s,r/w combined of page dir & table (cached) // | +------------> u/s of current access // +---------------> Current CR0.WP value /* 0xff0bbb0b */ static const Bit8u priv_check[BX_PRIV_CHECK_SIZE] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, #if BX_CPU_LEVEL >= 4 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1 #endif }; #define BX_PAGING_PHY_ADDRESS_RESERVED_BITS \ (BX_PHY_ADDRESS_RESERVED_BITS & BX_CONST64(0xfffffffffffff)) #define PAGE_DIRECTORY_NX_BIT (BX_CONST64(0x8000000000000000)) #define BX_CR3_PAGING_MASK (BX_CONST64(0x000ffffffffff000)) // Each entry in the TLB cache has 3 entries: // // lpf: Linear Page Frame (page aligned linear address of page) // bits 32..12 Linear page frame // bit 11 0: TLB HostPtr access allowed, 1: not allowed // bit 10...0 Invalidate index // // ppf: Physical Page Frame (page aligned phy address of page) // // hostPageAddr: // Host Page Frame address used for direct access to // the mem.vector[] space allocated for the guest physical // memory. If this is zero, it means that a pointer // to the host space could not be generated, likely because // that page of memory is not standard memory (it might // be memory mapped IO, ROM, etc). // // accessBits: // // bit 31: Page is a global page. // // The following bits are used for a very efficient permissions // check. The goal is to be able, using only the current privilege // level and access type, to determine if the page tables allow the // access to occur or at least should rewalk the page tables. On // the first read access, permissions are set to only read, so a // rewalk is necessary when a subsequent write fails the tests. // This allows for the dirty bit to be set properly, but for the // test to be efficient. Note that the CR0.WP flag is not present. // The values in the following flags is based on the current CR0.WP // value, necessitating a TLB flush when CR0.WP changes. // // The test is: // OK = (accessBits & ((E<<2) | (W<<1) | U)) == 0 // // where E:1=Execute, 0=Data; // W:1=Write, 0=Read; // U:1=CPL3, 0=CPL0-2 // // Thus for reads, it is: // OK = ( U ) // for writes: // OK = 0x2 | ( U ) // and for code fetches: // OK = 0x4 | ( U ) // // Note, that the TLB should have TLB_NoHostPtr bit set in the lpf when // direct access through host pointer is NOT allowed for the page. // A memory operation asking for a direct access through host pointer // will not set TLB_NoHostPtr bit in its lpf and thus get TLB miss // result when the direct access is not allowed. // #define TLB_NoHostPtr (0x800) /* set this bit when direct access is NOT allowed */ #define TLB_GlobalPage (0x80000000) #define TLB_SysOnly (0x1) #define TLB_ReadOnly (0x2) #define TLB_NoExecute (0x4) // === TLB Instrumentation section ============================== // Note: this is an approximation of what Peter Tattam had. #define InstrumentTLB 0 #if InstrumentTLB static unsigned tlbLookups=0; static unsigned tlbMisses=0; static unsigned tlbGlobalFlushes=0; static unsigned tlbNonGlobalFlushes=0; #define InstrTLB_StatsMask 0xfffff #define InstrTLB_Stats() {\ if ((tlbLookups & InstrTLB_StatsMask) == 0) { \ BX_INFO(("TLB lookup:%8d miss:%8d %6.2f%% flush:%8d %6.2f%%", \ tlbLookups, \ tlbMisses, \ tlbMisses * 100.0 / tlbLookups, \ (tlbGlobalFlushes+tlbNonGlobalFlushes), \ (tlbGlobalFlushes+tlbNonGlobalFlushes) * 100.0 / tlbLookups \ )); \ tlbLookups = tlbMisses = tlbGlobalFlushes = tlbNonGlobalFlushes = 0; \ } \ } #define InstrTLB_Increment(v) (v)++ #else #define InstrTLB_Stats() #define InstrTLB_Increment(v) #endif // ============================================================== void BX_CPU_C::TLB_flush(void) { #if InstrumentTLB InstrTLB_Increment(tlbGlobalFlushes); #endif invalidate_prefetch_q(); invalidate_stack_cache(); for (unsigned n=0; n= 5 BX_CPU_THIS_PTR TLB.split_large = 0; // flush whole TLB #endif #if BX_SUPPORT_MONITOR_MWAIT // invalidating of the TLB might change translation for monitored page // and cause subsequent MWAIT instruction to wait forever BX_CPU_THIS_PTR monitor.reset_monitor(); #endif } #if BX_CPU_LEVEL >= 6 void BX_CPU_C::TLB_flushNonGlobal(void) { #if InstrumentTLB InstrTLB_Increment(tlbNonGlobalFlushes); #endif invalidate_prefetch_q(); invalidate_stack_cache(); BX_CPU_THIS_PTR TLB.split_large = 0; Bit32u lpf_mask = 0; for (unsigned n=0; naccessBits & TLB_GlobalPage)) { tlbEntry->lpf = BX_INVALID_TLB_ENTRY; tlbEntry->accessBits = 0; } else { lpf_mask |= tlbEntry->lpf_mask; } } if (lpf_mask > 0xfff) BX_CPU_THIS_PTR TLB.split_large = 1; #if BX_SUPPORT_MONITOR_MWAIT // invalidating of the TLB might change translation for monitored page // and cause subsequent MWAIT instruction to wait forever BX_CPU_THIS_PTR monitor.reset_monitor(); #endif } #endif void BX_CPU_C::TLB_invlpg(bx_address laddr) { invalidate_prefetch_q(); invalidate_stack_cache(); BX_DEBUG(("TLB_invlpg(0x"FMT_ADDRX"): invalidate TLB entry", laddr)); #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR TLB.split_large) { Bit32u lpf_mask = 0; BX_CPU_THIS_PTR TLB.split_large = 0; // make sure INVLPG handles correctly large pages for (unsigned n=0; nlpf_mask; if ((laddr & ~entry_lpf_mask) == (tlbEntry->lpf & ~entry_lpf_mask)) { tlbEntry->lpf = BX_INVALID_TLB_ENTRY; tlbEntry->accessBits = 0; } else { lpf_mask |= entry_lpf_mask; } } if (lpf_mask > 0xfff) BX_CPU_THIS_PTR TLB.split_large = 1; } else #endif { unsigned TLB_index = BX_TLB_INDEX_OF(laddr, 0); bx_address lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[TLB_index]; if (TLB_LPFOf(tlbEntry->lpf) == lpf) { tlbEntry->lpf = BX_INVALID_TLB_ENTRY; tlbEntry->accessBits = 0; } } #if BX_SUPPORT_MONITOR_MWAIT // invalidating of the TLB entry might change translation for monitored // page and cause subsequent MWAIT instruction to wait forever BX_CPU_THIS_PTR monitor.reset_monitor(); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVLPG(bxInstruction_c* i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("INVLPG: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0); } bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); bx_address laddr = get_laddr(i->seg(), eaddr); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if (VMEXIT(VMX_VM_EXEC_CTRL2_INVLPG_VMEXIT)) { BX_ERROR(("VMEXIT: INVLPG 0x" FMT_ADDRX, laddr)); VMexit(VMX_VMEXIT_INVLPG, laddr); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_INVLPG)) Svm_Vmexit(SVM_VMEXIT_INVLPG); } #endif #if BX_SUPPORT_X86_64 if (IsCanonical(laddr)) #endif { BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_INVLPG, laddr); TLB_invlpg(laddr); } BX_NEXT_TRACE(i); } // error checking order - page not present, reserved bits, protection #define ERROR_NOT_PRESENT 0x00 #define ERROR_PROTECTION 0x01 #define ERROR_RESERVED 0x08 #define ERROR_CODE_ACCESS 0x10 void BX_CPU_C::page_fault(unsigned fault, bx_address laddr, unsigned user, unsigned rw) { unsigned isWrite = rw & 1; Bit32u error_code = fault | (user << 2) | (isWrite << 1); #if BX_CPU_LEVEL >= 6 if (rw == BX_EXECUTE) { if (BX_CPU_THIS_PTR cr4.get_SMEP()) error_code |= ERROR_CODE_ACCESS; // I/D = 1 if (BX_CPU_THIS_PTR cr4.get_PAE() && BX_CPU_THIS_PTR efer.get_NXE()) error_code |= ERROR_CODE_ACCESS; } #endif #if BX_SUPPORT_SVM SvmInterceptException(BX_HARDWARE_EXCEPTION, BX_PF_EXCEPTION, error_code, 1, laddr); // before the CR2 was modified #endif #if BX_SUPPORT_VMX VMexit_Event(BX_HARDWARE_EXCEPTION, BX_PF_EXCEPTION, error_code, 1, laddr); // before the CR2 was modified #endif BX_CPU_THIS_PTR cr2 = laddr; #if BX_SUPPORT_X86_64 BX_DEBUG(("page fault for address %08x%08x @ %08x%08x", GET32H(laddr), GET32L(laddr), GET32H(RIP), GET32L(RIP))); #else BX_DEBUG(("page fault for address %08x @ %08x", laddr, EIP)); #endif exception(BX_PF_EXCEPTION, error_code); } #define BX_LEVEL_PML4 3 #define BX_LEVEL_PDPTE 2 #define BX_LEVEL_PDE 1 #define BX_LEVEL_PTE 0 static const char *bx_paging_level[4] = { "PTE", "PDE", "PDPE", "PML4" }; // keep it 4 letters #if BX_CPU_LEVEL >= 6 // Format of a Long Mode Non-Leaf Entry // ----------------------------------------------------------- // 00 | Present (P) // 01 | R/W // 02 | U/S // 03 | Page-Level Write-Through (PWT) // 04 | Page-Level Cache-Disable (PCD) // 05 | Accessed (A) // 06 | (ignored) // 07 | Page Size (PS), must be 0 if no Large Page on the level // 11-08 | (ignored) // PA-12 | Physical address of 4-KByte aligned page-directory-pointer table // 51-PA | Reserved (must be zero) // 62-52 | (ignored) // 63 | Execute-Disable (XD) (if EFER.NXE=1, reserved otherwise) // ----------------------------------------------------------- #define PAGING_PAE_RESERVED_BITS (BX_PAGING_PHY_ADDRESS_RESERVED_BITS) // in legacy PAE mode bits [62:52] are reserved. bit 63 is NXE #define PAGING_LEGACY_PAE_RESERVED_BITS \ (BX_PAGING_PHY_ADDRESS_RESERVED_BITS | BX_CONST64(0x7ff0000000000000)) // Format of a PDPTE that References a 1-GByte Page // ----------------------------------------------------------- // 00 | Present (P) // 01 | R/W // 02 | U/S // 03 | Page-Level Write-Through (PWT) // 04 | Page-Level Cache-Disable (PCD) // 05 | Accessed (A) // 06 | (ignored) // 07 | Page Size, must be 1 to indicate a 1-GByte Page // 08 | Global (G) (if CR4.PGE=1, ignored otherwise) // 11-09 | (ignored) // 12 | PAT (if PAT is supported, reserved otherwise) // 29-13 | Reserved (must be zero) // PA-30 | Physical address of the 1-Gbyte Page // 51-PA | Reserved (must be zero) // 62-52 | (ignored) // 63 | Execute-Disable (XD) (if EFER.NXE=1, reserved otherwise) // ----------------------------------------------------------- #define PAGING_PAE_PDPTE1G_RESERVED_BITS \ (BX_PAGING_PHY_ADDRESS_RESERVED_BITS | BX_CONST64(0x3FFFE000)) // Format of a PAE PDE that Maps a 2-MByte Page // ----------------------------------------------------------- // 00 | Present (P) // 01 | R/W // 02 | U/S // 03 | Page-Level Write-Through (PWT) // 04 | Page-Level Cache-Disable (PCD) // 05 | Accessed (A) // 06 | Dirty (D) // 07 | Page Size (PS), must be 1 to indicate a 2-MByte Page // 08 | Global (G) (if CR4.PGE=1, ignored otherwise) // 11-09 | (ignored) // 12 | PAT (if PAT is supported, reserved otherwise) // 20-13 | Reserved (must be zero) // PA-21 | Physical address of the 2-MByte page // 51-PA | Reserved (must be zero) // 62-52 | ignored in long mode, reserved (must be 0) in legacy PAE mode // 63 | Execute-Disable (XD) (if EFER.NXE=1, reserved otherwise) // ----------------------------------------------------------- #define PAGING_PAE_PDE2M_RESERVED_BITS \ (BX_PAGING_PHY_ADDRESS_RESERVED_BITS | BX_CONST64(0x001FE000)) // Format of a PAE PTE that Maps a 4-KByte Page // ----------------------------------------------------------- // 00 | Present (P) // 01 | R/W // 02 | U/S // 03 | Page-Level Write-Through (PWT) // 04 | Page-Level Cache-Disable (PCD) // 05 | Accessed (A) // 06 | Dirty (D) // 07 | PAT (if PAT is supported, reserved otherwise) // 08 | Global (G) (if CR4.PGE=1, ignored otherwise) // 11-09 | (ignored) // PA-12 | Physical address of the 4-KByte page // 51-PA | Reserved (must be zero) // 62-52 | ignored in long mode, reserved (must be 0) in legacy PAE mode // 63 | Execute-Disable (XD) (if EFER.NXE=1, reserved otherwise) // ----------------------------------------------------------- int BX_CPU_C::check_entry_PAE(const char *s, Bit64u entry, Bit64u reserved, unsigned rw, bx_bool *nx_fault) { if (!(entry & 0x1)) { BX_DEBUG(("PAE %s: entry not present", s)); return ERROR_NOT_PRESENT; } if (entry & reserved) { BX_DEBUG(("PAE %s: reserved bit is set 0x" FMT_ADDRX64, s, entry)); return ERROR_RESERVED | ERROR_PROTECTION; } if (entry & PAGE_DIRECTORY_NX_BIT) { if (rw == BX_EXECUTE) { BX_DEBUG(("PAE %s: non-executable page fault occured", s)); *nx_fault = 1; } } return -1; } #if BX_SUPPORT_X86_64 // Translate a linear address to a physical address in long mode bx_phy_address BX_CPU_C::translate_linear_long_mode(bx_address laddr, Bit32u &lpf_mask, Bit32u &combined_access, unsigned user, unsigned rw) { bx_phy_address entry_addr[4]; bx_phy_address ppf = BX_CPU_THIS_PTR cr3 & BX_CR3_PAGING_MASK; Bit64u entry[4]; bx_bool nx_fault = 0; int leaf; Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff); lpf_mask = 0xfff; combined_access = 0x06; Bit64u reserved = PAGING_PAE_RESERVED_BITS; if (! BX_CPU_THIS_PTR efer.get_NXE()) reserved |= PAGE_DIRECTORY_NX_BIT; for (leaf = BX_LEVEL_PML4;; --leaf) { entry_addr[leaf] = ppf + ((laddr >> (9 + 9*leaf)) & 0xff8); #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) entry_addr[leaf] = translate_guest_physical(entry_addr[leaf], laddr, 1, 1, BX_READ); } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest && SVM_NESTED_PAGING_ENABLED) { entry_addr[leaf] = nested_walk(entry_addr[leaf], BX_RW, 1); } #endif access_read_physical(entry_addr[leaf], 8, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_READ, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); offset_mask >>= 9; Bit64u curr_entry = entry[leaf]; int fault = check_entry_PAE(bx_paging_level[leaf], curr_entry, reserved, rw, &nx_fault); if (fault >= 0) page_fault(fault, laddr, user, rw); combined_access &= curr_entry; // U/S and R/W ppf = curr_entry & BX_CONST64(0x000ffffffffff000); if (leaf == BX_LEVEL_PTE) break; if (curr_entry & 0x80) { if (leaf > (BX_LEVEL_PDE + !!bx_cpuid_support_1g_paging())) { BX_DEBUG(("PAE %s: PS bit set !", bx_paging_level[leaf])); page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, user, rw); } ppf &= BX_CONST64(0x000fffffffffe000); if (ppf & offset_mask) { BX_DEBUG(("PAE %s: reserved bit is set: 0x" FMT_ADDRX64, bx_paging_level[leaf], curr_entry)); page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, user, rw); } lpf_mask = offset_mask; break; } } bx_bool isWrite = (rw & 1); // write or r-m-w unsigned priv_index = (BX_CPU_THIS_PTR cr0.get_WP() << 4) | // bit 4 (user<<3) | // bit 3 (combined_access | isWrite); // bit 2,1,0 if (!priv_check[priv_index] || nx_fault) page_fault(ERROR_PROTECTION, laddr, user, rw); if (BX_CPU_THIS_PTR cr4.get_SMEP() && rw == BX_EXECUTE && !user) { if (combined_access & 0x4) // User page page_fault(ERROR_PROTECTION, laddr, user, rw); } if (BX_CPU_THIS_PTR cr4.get_PGE()) combined_access |= (entry[leaf] & 0x100); // G // Update A/D bits if needed update_access_dirty_PAE(entry_addr, entry, BX_LEVEL_PML4, leaf, isWrite); return ppf | (laddr & offset_mask); } #endif void BX_CPU_C::update_access_dirty_PAE(bx_phy_address *entry_addr, Bit64u *entry, unsigned max_level, unsigned leaf, unsigned write) { // Update A bit if needed for (unsigned level=max_level; level > leaf; level--) { if (!(entry[level] & 0x20)) { entry[level] |= 0x20; access_write_physical(entry_addr[level], 8, &entry[level]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[level], 8, BX_WRITE, (BX_PTE_ACCESS + level), (Bit8u*)(&entry[level])); } } // Update A/D bits if needed if (!(entry[leaf] & 0x20) || (write && !(entry[leaf] & 0x40))) { entry[leaf] |= (0x20 | (write<<6)); // Update A and possibly D bits access_write_physical(entry_addr[leaf], 8, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_WRITE, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); } } // Format of Legacy PAE PDPTR entry (PDPTE) // ----------------------------------------------------------- // 00 | Present (P) // 02-01 | Reserved (must be zero) // 03 | Page-Level Write-Through (PWT) (486+), 0=reserved otherwise // 04 | Page-Level Cache-Disable (PCD) (486+), 0=reserved otherwise // 08-05 | Reserved (must be zero) // 11-09 | (ignored) // PA-12 | Physical address of 4-KByte aligned page directory // 63-PA | Reserved (must be zero) // ----------------------------------------------------------- #define PAGING_PAE_PDPTE_RESERVED_BITS \ (BX_PAGING_PHY_ADDRESS_RESERVED_BITS | BX_CONST64(0xFFF00000000001E6)) bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::CheckPDPTR(bx_phy_address cr3_val) { // with Nested Paging PDPTRs are not loaded for guest page tables but // accessed on demand as part of the guest page walk #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest && SVM_NESTED_PAGING_ENABLED) return 1; #endif cr3_val &= 0xffffffe0; #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) cr3_val = translate_guest_physical(cr3_val, 0, 0, 1, BX_READ); } #endif Bit64u pdptr[4]; unsigned n; for (n=0; n<4; n++) { // read and check PDPTE entries bx_phy_address pdpe_entry_addr = (bx_phy_address) (cr3_val | (n << 3)); access_read_physical(pdpe_entry_addr, 8, &(pdptr[n])); BX_NOTIFY_PHY_MEMORY_ACCESS(pdpe_entry_addr, 8, BX_READ, (BX_PDPTR0_ACCESS + n), (Bit8u*) &(pdptr[n])); if (pdptr[n] & 0x1) { if (pdptr[n] & PAGING_PAE_PDPTE_RESERVED_BITS) return 0; } } // load new PDPTRs for (n=0; n<4; n++) BX_CPU_THIS_PTR PDPTR_CACHE.entry[n] = pdptr[n]; return 1; /* PDPTRs are fine */ } #if BX_SUPPORT_VMX >= 2 bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::CheckPDPTR(Bit64u *pdptr) { for (unsigned n=0; n<4; n++) { if (pdptr[n] & 0x1) { if (pdptr[n] & PAGING_PAE_PDPTE_RESERVED_BITS) return 0; } } return 1; /* PDPTRs are fine */ } #endif bx_phy_address BX_CPU_C::translate_linear_load_PDPTR(bx_address laddr, unsigned user, unsigned rw) { unsigned index = (laddr >> 30) & 0x3; Bit64u pdptr; #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest && SVM_NESTED_PAGING_ENABLED) { bx_phy_address cr3_val = BX_CPU_THIS_PTR cr3 & 0xffffffe0; cr3_val = nested_walk(cr3_val, BX_RW, 1); bx_phy_address pdpe_entry_addr = (bx_phy_address) (cr3_val | (index << 3)); access_read_physical(pdpe_entry_addr, 8, &pdptr); BX_NOTIFY_PHY_MEMORY_ACCESS(pdpe_entry_addr, 8, BX_READ, (BX_PDPTR0_ACCESS + index), (Bit8u*) &pdptr); if (pdptr & 0x1) { if (pdptr & PAGING_PAE_PDPTE_RESERVED_BITS) { BX_DEBUG(("PAE PDPTE%d entry reserved bits set: 0x" FMT_ADDRX64, index, pdptr)); page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, user, rw); } } } else #endif { pdptr = BX_CPU_THIS_PTR PDPTR_CACHE.entry[index]; } if (! (pdptr & 0x1)) { BX_DEBUG(("PAE PDPTE entry not present !")); page_fault(ERROR_NOT_PRESENT, laddr, user, rw); } return pdptr; } // Translate a linear address to a physical address in PAE paging mode bx_phy_address BX_CPU_C::translate_linear_PAE(bx_address laddr, Bit32u &lpf_mask, Bit32u &combined_access, unsigned user, unsigned rw) { bx_phy_address entry_addr[2]; Bit64u entry[2]; bx_bool nx_fault = 0; int leaf; lpf_mask = 0xfff; combined_access = 0x06; Bit64u reserved = PAGING_LEGACY_PAE_RESERVED_BITS; if (! BX_CPU_THIS_PTR efer.get_NXE()) reserved |= PAGE_DIRECTORY_NX_BIT; Bit64u pdpte = translate_linear_load_PDPTR(laddr, user, rw); bx_phy_address ppf = pdpte & BX_CONST64(0x000ffffffffff000); for (leaf = BX_LEVEL_PDE;; --leaf) { entry_addr[leaf] = ppf + ((laddr >> (9 + 9*leaf)) & 0xff8); #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) entry_addr[leaf] = translate_guest_physical(entry_addr[leaf], laddr, 1, 1, BX_READ); } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest && SVM_NESTED_PAGING_ENABLED) { entry_addr[leaf] = nested_walk(entry_addr[leaf], BX_RW, 1); } #endif access_read_physical(entry_addr[leaf], 8, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_READ, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); Bit64u curr_entry = entry[leaf]; int fault = check_entry_PAE(bx_paging_level[leaf], curr_entry, reserved, rw, &nx_fault); if (fault >= 0) page_fault(fault, laddr, user, rw); combined_access &= curr_entry; // U/S and R/W ppf = curr_entry & BX_CONST64(0x000ffffffffff000); if (leaf == BX_LEVEL_PTE) break; // Ignore CR4.PSE in PAE mode if (curr_entry & 0x80) { if (curr_entry & PAGING_PAE_PDE2M_RESERVED_BITS) { BX_DEBUG(("PAE PDE2M: reserved bit is set PDE=0x" FMT_ADDRX64, curr_entry)); page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, user, rw); } // Make up the physical page frame address ppf = (bx_phy_address)(curr_entry & BX_CONST64(0x000fffffffe00000)); lpf_mask = 0x1fffff; break; } } bx_bool isWrite = (rw & 1); // write or r-m-w unsigned priv_index = (BX_CPU_THIS_PTR cr0.get_WP() << 4) | // bit 4 (user<<3) | // bit 3 (combined_access | isWrite); // bit 2,1,0 if (!priv_check[priv_index] || nx_fault) page_fault(ERROR_PROTECTION, laddr, user, rw); if (BX_CPU_THIS_PTR cr4.get_SMEP() && rw == BX_EXECUTE && !user) { if (combined_access & 0x4) // User page page_fault(ERROR_PROTECTION, laddr, user, rw); } if (BX_CPU_THIS_PTR cr4.get_PGE()) combined_access |= (entry[leaf] & 0x100); // G // Update A/D bits if needed update_access_dirty_PAE(entry_addr, entry, BX_LEVEL_PDE, leaf, isWrite); return ppf | (laddr & lpf_mask); } #endif // Format of a PDE that Maps a 4-MByte Page // ----------------------------------------------------------- // 00 | Present (P) // 01 | R/W // 02 | U/S // 03 | Page-Level Write-Through (PWT) // 04 | Page-Level Cache-Disable (PCD) // 05 | Accessed (A) // 06 | Dirty (D) // 07 | Page size, must be 1 to indicate 4-Mbyte page // 08 | Global (G) (if CR4.PGE=1, ignored otherwise) // 11-09 | (ignored) // 12 | PAT (if PAT is supported, reserved otherwise) // PA-13 | Bits PA-32 of physical address of the 4-MByte page // 21-PA | Reserved (must be zero) // 31-22 | Bits 31-22 of physical address of the 4-MByte page // ----------------------------------------------------------- #define PAGING_PDE4M_RESERVED_BITS \ (((1 << (41-BX_PHY_ADDRESS_WIDTH))-1) << (13 + BX_PHY_ADDRESS_WIDTH - 32)) // Translate a linear address to a physical address in legacy paging mode bx_phy_address BX_CPU_C::translate_linear_legacy(bx_address laddr, Bit32u &lpf_mask, Bit32u &combined_access, unsigned user, unsigned rw) { bx_phy_address entry_addr[2], ppf = (Bit32u) BX_CPU_THIS_PTR cr3 & BX_CR3_PAGING_MASK; Bit32u entry[2]; int leaf; lpf_mask = 0xfff; combined_access = 0x06; for (leaf = BX_LEVEL_PDE;; --leaf) { entry_addr[leaf] = ppf + ((laddr >> (10 + 10*leaf)) & 0xffc); #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) entry_addr[leaf] = translate_guest_physical(entry_addr[leaf], laddr, 1, 1, BX_READ); } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest && SVM_NESTED_PAGING_ENABLED) { entry_addr[leaf] = nested_walk(entry_addr[leaf], BX_RW, 1); } #endif access_read_physical(entry_addr[leaf], 4, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 4, BX_READ, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); Bit32u curr_entry = entry[leaf]; if (!(curr_entry & 0x1)) { BX_DEBUG(("%s: entry not present", bx_paging_level[leaf])); page_fault(ERROR_NOT_PRESENT, laddr, user, rw); } combined_access &= curr_entry; // U/S and R/W ppf = curr_entry & 0xfffff000; if (leaf == BX_LEVEL_PTE) break; #if BX_CPU_LEVEL >= 5 if ((curr_entry & 0x80) != 0 && BX_CPU_THIS_PTR cr4.get_PSE()) { // 4M paging, only if CR4.PSE enabled, ignore PDE.PS otherwise if (curr_entry & PAGING_PDE4M_RESERVED_BITS) { BX_DEBUG(("PSE PDE4M: reserved bit is set: PDE=0x%08x", entry[BX_LEVEL_PDE])); page_fault(ERROR_RESERVED | ERROR_PROTECTION, laddr, user, rw); } // make up the physical frame number ppf = (curr_entry & 0xffc00000); #if BX_PHY_ADDRESS_WIDTH > 32 ppf |= ((bx_phy_address)(curr_entry & 0x003fe000)) << 19; #endif lpf_mask = 0x3fffff; break; } #endif } bx_bool isWrite = (rw & 1); // write or r-m-w unsigned priv_index = #if BX_CPU_LEVEL >= 4 (BX_CPU_THIS_PTR cr0.get_WP() << 4) | // bit 4 #endif (user<<3) | // bit 3 (combined_access | isWrite); // bit 2,1,0 if (!priv_check[priv_index]) page_fault(ERROR_PROTECTION, laddr, user, rw); #if BX_CPU_LEVEL >= 6 if (BX_CPU_THIS_PTR cr4.get_SMEP() && rw == BX_EXECUTE && !user) { if (combined_access & 0x4) // User page page_fault(ERROR_PROTECTION, laddr, user, rw); } if (BX_CPU_THIS_PTR cr4.get_PGE()) combined_access |= (entry[leaf] & 0x100); // G #endif update_access_dirty(entry_addr, entry, leaf, isWrite); return ppf | (laddr & lpf_mask); } void BX_CPU_C::update_access_dirty(bx_phy_address *entry_addr, Bit32u *entry, unsigned leaf, unsigned write) { if (leaf == BX_LEVEL_PTE) { // Update PDE A bit if needed if (!(entry[BX_LEVEL_PDE] & 0x20)) { entry[BX_LEVEL_PDE] |= 0x20; access_write_physical(entry_addr[BX_LEVEL_PDE], 4, &entry[BX_LEVEL_PDE]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[BX_LEVEL_PDE], 4, BX_WRITE, BX_PDE_ACCESS, (Bit8u*)(&entry[BX_LEVEL_PDE])); } } // Update A/D bits if needed if (!(entry[leaf] & 0x20) || (write && !(entry[leaf] & 0x40))) { entry[leaf] |= (0x20 | (write<<6)); // Update A and possibly D bits access_write_physical(entry_addr[leaf], 4, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 4, BX_WRITE, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); } } // Translate a linear address to a physical address bx_phy_address BX_CPU_C::translate_linear(bx_address laddr, unsigned user, unsigned rw) { Bit32u combined_access = 0x06; Bit32u lpf_mask = 0xfff; // 4K pages #if BX_SUPPORT_X86_64 if (! long_mode()) laddr &= 0xffffffff; #endif bx_phy_address paddress, ppf, poffset = PAGE_OFFSET(laddr); unsigned isWrite = rw & 1; // write or r-m-w unsigned isExecute = (rw == BX_EXECUTE); InstrTLB_Increment(tlbLookups); InstrTLB_Stats(); bx_address lpf = LPFOf(laddr); unsigned TLB_index = BX_TLB_INDEX_OF(lpf, 0); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[TLB_index]; // already looked up TLB for code access if (TLB_LPFOf(tlbEntry->lpf) == lpf) { paddress = tlbEntry->ppf | poffset; if (! (tlbEntry->accessBits & ((isExecute<<2) | (isWrite<<1) | user))) return paddress; // The current access does not have permission according to the info // in our TLB cache entry. Re-walk the page tables, in case there is // updated information in the memory image, and let the long path code // generate an exception if one is warranted. } InstrTLB_Increment(tlbMisses); if(BX_CPU_THIS_PTR cr0.get_PG()) { BX_DEBUG(("page walk for address 0x" FMT_LIN_ADDRX, laddr)); #if BX_CPU_LEVEL >= 6 #if BX_SUPPORT_X86_64 if (long_mode()) paddress = translate_linear_long_mode(laddr, lpf_mask, combined_access, user, rw); else #endif if (BX_CPU_THIS_PTR cr4.get_PAE()) paddress = translate_linear_PAE(laddr, lpf_mask, combined_access, user, rw); else #endif paddress = translate_linear_legacy(laddr, lpf_mask, combined_access, user, rw); #if BX_CPU_LEVEL >= 5 if (lpf_mask > 0xfff) BX_CPU_THIS_PTR TLB.split_large = 1; #endif } else { // no paging paddress = (bx_phy_address) laddr; } // Calculate physical memory address and fill in TLB cache entry #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) { paddress = translate_guest_physical(paddress, laddr, 1, 0, rw); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest && SVM_NESTED_PAGING_ENABLED) { paddress = nested_walk(paddress, rw, 0); } #endif paddress = A20ADDR(paddress); ppf = PPFOf(paddress); // direct memory access is NOT allowed by default tlbEntry->lpf = lpf | TLB_NoHostPtr; tlbEntry->lpf_mask = lpf_mask; tlbEntry->ppf = ppf; tlbEntry->accessBits = 0; if ((combined_access & 4) == 0) { // System tlbEntry->accessBits |= TLB_SysOnly; if (! isWrite) tlbEntry->accessBits |= TLB_ReadOnly; } else { // Current operation is a read or a page is read only // Not efficient handling of system write to user read only page: // hopefully it is very rare case, optimize later if (! isWrite || (combined_access & 2) == 0) { tlbEntry->accessBits |= TLB_ReadOnly; } } #if BX_CPU_LEVEL >= 6 if (combined_access & 0x100) // Global bit tlbEntry->accessBits |= TLB_GlobalPage; // EFER.NXE change won't flush TLB if (BX_CPU_THIS_PTR cr4.get_PAE() && rw != BX_EXECUTE) tlbEntry->accessBits |= TLB_NoExecute; #endif // Attempt to get a host pointer to this physical page. Put that // pointer in the TLB cache. Note if the request is vetoed, NULL // will be returned, and it's OK to OR zero in anyways. tlbEntry->hostPageAddr = BX_CPU_THIS_PTR getHostMemAddr(ppf, rw); if (tlbEntry->hostPageAddr) { // All access allowed also via direct pointer #if BX_X86_DEBUGGER if (! hwbreakpoint_check(laddr, BX_HWDebugMemW, BX_HWDebugMemRW)) #endif tlbEntry->lpf = lpf; // allow direct access with HostPtr } return paddress; } #if BX_SUPPORT_SVM void BX_CPU_C::nested_page_fault(unsigned fault, bx_phy_address guest_paddr, unsigned rw, unsigned is_page_walk) { unsigned isWrite = rw & 1; Bit64u error_code = fault | (1 << 2) | (isWrite << 1); if (rw == BX_EXECUTE) error_code |= ERROR_CODE_ACCESS; // I/D = 1 if (is_page_walk) error_code |= BX_CONST64(1) << 32; else error_code |= BX_CONST64(1) << 33; Svm_Vmexit(SVM_VMEXIT_NPF, error_code, guest_paddr); } bx_phy_address BX_CPU_C::nested_walk_long_mode(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk) { bx_phy_address entry_addr[4]; Bit64u entry[4]; bx_bool nx_fault = 0; int leaf; SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; SVM_HOST_STATE *host_state = &BX_CPU_THIS_PTR vmcb.host_state; bx_phy_address ppf = ctrls->ncr3 & BX_CR3_PAGING_MASK; Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff); unsigned combined_access = 0x06; Bit64u reserved = PAGING_PAE_RESERVED_BITS; if (! host_state->efer.get_NXE()) reserved |= PAGE_DIRECTORY_NX_BIT; for (leaf = BX_LEVEL_PML4;; --leaf) { entry_addr[leaf] = ppf + ((guest_paddr >> (9 + 9*leaf)) & 0xff8); access_read_physical(entry_addr[leaf], 8, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_READ, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); offset_mask >>= 9; Bit64u curr_entry = entry[leaf]; int fault = check_entry_PAE(bx_paging_level[leaf], curr_entry, reserved, rw, &nx_fault); if (fault >= 0) nested_page_fault(fault, guest_paddr, rw, is_page_walk); combined_access &= curr_entry; // U/S and R/W ppf = curr_entry & BX_CONST64(0x000ffffffffff000); if (leaf == BX_LEVEL_PTE) break; if (curr_entry & 0x80) { if (leaf > (BX_LEVEL_PDE + !!bx_cpuid_support_1g_paging())) { BX_DEBUG(("Nested PAE Walk %s: PS bit set !", bx_paging_level[leaf])); nested_page_fault(ERROR_RESERVED | ERROR_PROTECTION, guest_paddr, rw, is_page_walk); } ppf &= BX_CONST64(0x000fffffffffe000); if (ppf & offset_mask) { BX_DEBUG(("Nested PAE Walk %s: reserved bit is set: 0x" FMT_ADDRX64, bx_paging_level[leaf], curr_entry)); nested_page_fault(ERROR_RESERVED | ERROR_PROTECTION, guest_paddr, rw, is_page_walk); } break; } } bx_bool isWrite = (rw & 1); // write or r-m-w unsigned priv_index = (1<<3) /* user */ | (combined_access | isWrite); if (!priv_check[priv_index] || nx_fault) nested_page_fault(ERROR_PROTECTION, guest_paddr, rw, is_page_walk); // Update A/D bits if needed update_access_dirty_PAE(entry_addr, entry, BX_LEVEL_PML4, leaf, isWrite); // Make up the physical page frame address return ppf | (bx_phy_address)(guest_paddr & offset_mask); } bx_phy_address BX_CPU_C::nested_walk_PAE(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk) { bx_phy_address entry_addr[2]; Bit64u entry[2]; bx_bool nx_fault = 0; int leaf; unsigned combined_access = 0x06; SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; SVM_HOST_STATE *host_state = &BX_CPU_THIS_PTR vmcb.host_state; bx_phy_address ncr3 = ctrls->ncr3 & 0xffffffe0; unsigned index = (guest_paddr >> 30) & 0x3; Bit64u pdptr; bx_phy_address pdpe_entry_addr = (bx_phy_address) (ncr3 | (index << 3)); access_read_physical(pdpe_entry_addr, 8, &pdptr); BX_NOTIFY_PHY_MEMORY_ACCESS(pdpe_entry_addr, 8, BX_READ, (BX_PDPTR0_ACCESS + index), (Bit8u*) &pdptr); if (! (pdptr & 0x1)) { BX_DEBUG(("Nested PAE Walk PDPTE%d entry not present !", index)); nested_page_fault(ERROR_NOT_PRESENT, guest_paddr, rw, is_page_walk); } if (pdptr & PAGING_PAE_PDPTE_RESERVED_BITS) { BX_DEBUG(("Nested PAE Walk PDPTE%d entry reserved bits set: 0x" FMT_ADDRX64, index, pdptr)); nested_page_fault(ERROR_RESERVED | ERROR_PROTECTION, guest_paddr, rw, is_page_walk); } Bit64u reserved = PAGING_LEGACY_PAE_RESERVED_BITS; if (! host_state->efer.get_NXE()) reserved |= PAGE_DIRECTORY_NX_BIT; bx_phy_address ppf = pdptr & BX_CONST64(0x000ffffffffff000); for (leaf = BX_LEVEL_PDE;; --leaf) { entry_addr[leaf] = ppf + ((guest_paddr >> (9 + 9*leaf)) & 0xff8); access_read_physical(entry_addr[leaf], 8, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_READ, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); Bit64u curr_entry = entry[leaf]; int fault = check_entry_PAE(bx_paging_level[leaf], curr_entry, reserved, rw, &nx_fault); if (fault >= 0) nested_page_fault(fault, guest_paddr, rw, is_page_walk); combined_access &= curr_entry; // U/S and R/W ppf = curr_entry & BX_CONST64(0x000ffffffffff000); if (leaf == BX_LEVEL_PTE) break; // Ignore CR4.PSE in PAE mode if (curr_entry & 0x80) { if (curr_entry & PAGING_PAE_PDE2M_RESERVED_BITS) { BX_DEBUG(("PAE PDE2M: reserved bit is set PDE=0x" FMT_ADDRX64, curr_entry)); nested_page_fault(ERROR_RESERVED | ERROR_PROTECTION, guest_paddr, rw, is_page_walk); } // Make up the physical page frame address ppf = (bx_phy_address)((curr_entry & BX_CONST64(0x000fffffffe00000)) | (guest_paddr & 0x001ff000)); break; } } bx_bool isWrite = (rw & 1); // write or r-m-w unsigned priv_index = (1<<3) /* user */ | (combined_access | isWrite); if (!priv_check[priv_index] || nx_fault) nested_page_fault(ERROR_PROTECTION, guest_paddr, rw, is_page_walk); // Update A/D bits if needed update_access_dirty_PAE(entry_addr, entry, BX_LEVEL_PDE, leaf, isWrite); Bit32u page_offset = PAGE_OFFSET(guest_paddr); return ppf | page_offset; } bx_phy_address BX_CPU_C::nested_walk_legacy(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk) { bx_phy_address entry_addr[2]; Bit32u entry[2]; int leaf; SVM_CONTROLS *ctrls = &BX_CPU_THIS_PTR vmcb.ctrls; SVM_HOST_STATE *host_state = &BX_CPU_THIS_PTR vmcb.host_state; bx_phy_address ppf = ctrls->ncr3 & BX_CR3_PAGING_MASK; unsigned combined_access = 0x06; for (leaf = BX_LEVEL_PDE;; --leaf) { entry_addr[leaf] = ppf + ((guest_paddr >> (10 + 10*leaf)) & 0xffc); access_read_physical(entry_addr[leaf], 4, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 4, BX_READ, (BX_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); Bit32u curr_entry = entry[leaf]; if (!(curr_entry & 0x1)) { BX_DEBUG(("Nested %s Walk: entry not present", bx_paging_level[leaf])); nested_page_fault(ERROR_NOT_PRESENT, guest_paddr, rw, is_page_walk); } combined_access &= curr_entry; // U/S and R/W ppf = curr_entry & 0xfffff000; if (leaf == BX_LEVEL_PTE) break; if ((curr_entry & 0x80) != 0 && host_state->cr4.get_PSE()) { // 4M paging, only if CR4.PSE enabled, ignore PDE.PS otherwise if (curr_entry & PAGING_PDE4M_RESERVED_BITS) { BX_DEBUG(("Nested PSE Walk PDE4M: reserved bit is set: PDE=0x%08x", entry[BX_LEVEL_PDE])); nested_page_fault(ERROR_RESERVED | ERROR_PROTECTION, guest_paddr, rw, is_page_walk); } // make up the physical frame number ppf = (curr_entry & 0xffc00000) | (guest_paddr & 0x003ff000); #if BX_PHY_ADDRESS_WIDTH > 32 ppf |= ((bx_phy_address)(curr_entry & 0x003fe000)) << 19; #endif break; } } bx_bool isWrite = (rw & 1); // write or r-m-w unsigned priv_index = (1<<3) /* user */ | (combined_access | isWrite); if (!priv_check[priv_index]) nested_page_fault(ERROR_PROTECTION, guest_paddr, rw, is_page_walk); update_access_dirty(entry_addr, entry, leaf, isWrite); Bit32u page_offset = PAGE_OFFSET(guest_paddr); return ppf | page_offset; } bx_phy_address BX_CPU_C::nested_walk(bx_phy_address guest_paddr, unsigned rw, bx_bool is_page_walk) { SVM_HOST_STATE *host_state = &BX_CPU_THIS_PTR vmcb.host_state; BX_DEBUG(("Nested walk for guest paddr 0x" FMT_ADDRX, guest_paddr)); if (host_state->efer.get_LMA()) return nested_walk_long_mode(guest_paddr, rw, is_page_walk); else if (host_state->cr4.get_PAE()) return nested_walk_PAE(guest_paddr, rw, is_page_walk); else return nested_walk_legacy(guest_paddr, rw, is_page_walk); } #endif #if BX_SUPPORT_VMX >= 2 /* EPT access type */ #define BX_EPT_READ 0x01 #define BX_EPT_WRITE 0x02 #define BX_EPT_EXECUTE 0x04 /* EPT access mask */ #define BX_EPT_ENTRY_NOT_PRESENT 0x00 #define BX_EPT_ENTRY_READ_ONLY 0x01 #define BX_EPT_ENTRY_WRITE_ONLY 0x02 #define BX_EPT_ENTRY_READ_WRITE 0x03 #define BX_EPT_ENTRY_EXECUTE_ONLY 0x04 #define BX_EPT_ENTRY_READ_EXECUTE 0x05 #define BX_EPT_ENTRY_WRITE_EXECUTE 0x06 #define BX_EPT_ENTRY_READ_WRITE_EXECUTE 0x07 // Format of a EPT Entry // ----------------------------------------------------------- // 00 | Read access // 01 | Write access // 02 | Execute Access // 05-03 | EPT Memory type (for leaf entries, reserved otherwise) // 06 | Ignore PAT memory type (for leaf entries, reserved otherwise) // 07 | Page Size, must be 1 to indicate a Large Page // 11-08 | (ignored) // PA-12 | Physical address // 51-PA | Reserved (must be zero) // 63-52 | (ignored) // ----------------------------------------------------------- #define PAGING_EPT_RESERVED_BITS (BX_PAGING_PHY_ADDRESS_RESERVED_BITS) bx_phy_address BX_CPU_C::translate_guest_physical(bx_phy_address guest_paddr, bx_address guest_laddr, bx_bool guest_laddr_valid, bx_bool is_page_walk, unsigned rw) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; bx_phy_address entry_addr[4], ppf = LPFOf(vm->eptptr); Bit64u entry[4]; int leaf; Bit32u combined_access = 0x7, access_mask = 0; Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff); BX_DEBUG(("EPT walk for guest paddr 0x" FMT_ADDRX, guest_paddr)); // when EPT A/D enabled treat guest page table accesses as writes if (BX_VMX_EPT_ACCESS_DIRTY_ENABLED && is_page_walk && guest_laddr_valid) rw = BX_WRITE; if (rw == BX_EXECUTE) access_mask |= BX_EPT_EXECUTE; if (rw & 1) access_mask |= BX_EPT_WRITE; // write or r-m-w if (rw == BX_READ) access_mask |= BX_EPT_READ; Bit32u vmexit_reason = 0, vmexit_qualification = access_mask; for (leaf = BX_LEVEL_PML4;; --leaf) { entry_addr[leaf] = ppf + ((guest_paddr >> (9 + 9*leaf)) & 0xff8); access_read_physical(entry_addr[leaf], 8, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_READ, (BX_EPT_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); offset_mask >>= 9; Bit64u curr_entry = entry[leaf]; Bit32u curr_access_mask = curr_entry & 0x7; combined_access &= curr_access_mask; if (curr_access_mask == BX_EPT_ENTRY_NOT_PRESENT) { BX_DEBUG(("EPT %s: not present", bx_paging_level[leaf])); vmexit_reason = VMX_VMEXIT_EPT_VIOLATION; break; } if (curr_access_mask == BX_EPT_ENTRY_WRITE_ONLY || curr_access_mask == BX_EPT_ENTRY_WRITE_EXECUTE) { BX_DEBUG(("EPT %s: EPT misconfiguration mask=%d", bx_paging_level[leaf], curr_access_mask)); vmexit_reason = VMX_VMEXIT_EPT_MISCONFIGURATION; break; } extern bx_bool isMemTypeValidMTRR(unsigned memtype); if (! isMemTypeValidMTRR((curr_entry >> 3) & 7)) { BX_DEBUG(("EPT %s: EPT misconfiguration memtype=%d", bx_paging_level[leaf], (unsigned)((curr_entry >> 3) & 7))); vmexit_reason = VMX_VMEXIT_EPT_MISCONFIGURATION; break; } if (curr_entry & PAGING_EPT_RESERVED_BITS) { BX_DEBUG(("EPT %s: reserved bit is set 0x" FMT_ADDRX64, bx_paging_level[leaf], curr_entry)); vmexit_reason = VMX_VMEXIT_EPT_MISCONFIGURATION; break; } ppf = curr_entry & BX_CONST64(0x000ffffffffff000); if (leaf == BX_LEVEL_PTE) break; if (curr_entry & 0x80) { if (leaf > (BX_LEVEL_PDE + !!bx_cpuid_support_1g_paging())) { BX_DEBUG(("EPT %s: PS bit set !", bx_paging_level[leaf])); vmexit_reason = VMX_VMEXIT_EPT_MISCONFIGURATION; break; } ppf &= BX_CONST64(0x000fffffffffe000); if (ppf & offset_mask) { BX_DEBUG(("EPT %s: reserved bit is set: 0x" FMT_ADDRX64, bx_paging_level[leaf], curr_entry)); vmexit_reason = VMX_VMEXIT_EPT_MISCONFIGURATION; break; } // Make up the physical page frame address ppf += (bx_phy_address)(guest_paddr & offset_mask); break; } } if (!vmexit_reason && (access_mask & combined_access) != access_mask) { vmexit_reason = VMX_VMEXIT_EPT_VIOLATION; } if (vmexit_reason) { BX_ERROR(("VMEXIT: EPT %s for guest paddr 0x" FMT_ADDRX " laddr 0x" FMT_ADDRX, (vmexit_reason == VMX_VMEXIT_EPT_VIOLATION) ? "violation" : "misconfig", guest_paddr, guest_laddr)); VMwrite64(VMCS_64BIT_GUEST_PHYSICAL_ADDR, guest_paddr); if (vmexit_reason == VMX_VMEXIT_EPT_MISCONFIGURATION) { VMexit(VMX_VMEXIT_EPT_MISCONFIGURATION, 0); } else { if (guest_laddr_valid) { VMwrite_natural(VMCS_GUEST_LINEAR_ADDR, guest_laddr); vmexit_qualification |= 0x80; if (! is_page_walk) vmexit_qualification |= 0x100; } VMexit(VMX_VMEXIT_EPT_VIOLATION, vmexit_qualification | (combined_access << 3)); } } if (BX_VMX_EPT_ACCESS_DIRTY_ENABLED) { update_ept_access_dirty(entry_addr, entry, leaf, rw & 1); } Bit32u page_offset = PAGE_OFFSET(guest_paddr); return ppf | page_offset; } // Access bit 8, Dirty bit 9 void BX_CPU_C::update_ept_access_dirty(bx_phy_address *entry_addr, Bit64u *entry, unsigned leaf, unsigned write) { // Update A bit if needed for (unsigned level=BX_LEVEL_PML4; level > leaf; level--) { if (!(entry[level] & 0x100)) { entry[level] |= 0x100; access_write_physical(entry_addr[level], 8, &entry[level]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[level], 8, BX_WRITE, (BX_EPT_PTE_ACCESS + level), (Bit8u*)(&entry[level])); } } // Update A/D bits if needed if (!(entry[leaf] & 0x100) || (write && !(entry[leaf] & 0x200))) { entry[leaf] |= (0x100 | (write<<9)); // Update A and possibly D bits access_write_physical(entry_addr[leaf], 8, &entry[leaf]); BX_NOTIFY_PHY_MEMORY_ACCESS(entry_addr[leaf], 8, BX_WRITE, (BX_EPT_PTE_ACCESS + leaf), (Bit8u*)(&entry[leaf])); } } #endif #if BX_DEBUGGER || BX_DISASM || BX_INSTRUMENTATION || BX_GDBSTUB #if BX_DEBUGGER void dbg_print_paging_pte(int level, Bit64u entry) { dbg_printf("%4s: 0x%08x%08x", bx_paging_level[level], GET32H(entry), GET32L(entry)); if (entry & BX_CONST64(0x8000000000000000)) dbg_printf(" XD"); else dbg_printf(" "); if (level == BX_LEVEL_PTE) { dbg_printf(" %s %s %s", (entry & 0x0100) ? "G" : "g", (entry & 0x0080) ? "PAT" : "pat", (entry & 0x0040) ? "D" : "d"); } else { if (entry & 0x80) { dbg_printf(" PS %s %s %s", (entry & 0x0100) ? "G" : "g", (entry & 0x1000) ? "PAT" : "pat", (entry & 0x0040) ? "D" : "d"); } else { dbg_printf(" ps "); } } dbg_printf(" %s %s %s %s %s %s\n", (entry & 0x20) ? "A" : "a", (entry & 0x10) ? "PCD" : "pcd", (entry & 0x08) ? "PWT" : "pwt", (entry & 0x04) ? "U" : "S", (entry & 0x02) ? "W" : "R", (entry & 0x01) ? "P" : "p"); } #if BX_SUPPORT_VMX >= 2 void dbg_print_ept_paging_pte(int level, Bit64u entry) { dbg_printf("EPT %4s: 0x%08x%08x", bx_paging_level[level], GET32H(entry), GET32L(entry)); if (level != BX_LEVEL_PTE && (entry & 0x80)) dbg_printf(" PS"); else dbg_printf(" "); dbg_printf(" %s %s %s\n", (entry & 0x04) ? "E" : "e", (entry & 0x02) ? "W" : "w", (entry & 0x01) ? "R" : "r"); } #endif #endif // BX_DEBUGGER #if BX_SUPPORT_VMX >= 2 bx_bool BX_CPU_C::dbg_translate_guest_physical(bx_phy_address guest_paddr, bx_phy_address *phy, bx_bool verbose) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; bx_phy_address pt_address = LPFOf(vm->eptptr); Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff); for (int level = 3; level >= 0; --level) { Bit64u pte; pt_address += ((guest_paddr >> (9 + 9*level)) & 0xff8); offset_mask >>= 9; BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, pt_address, 8, &pte); #if BX_DEBUGGER if (verbose) dbg_print_ept_paging_pte(level, pte); #endif switch(pte & 7) { case BX_EPT_ENTRY_NOT_PRESENT: case BX_EPT_ENTRY_WRITE_ONLY: case BX_EPT_ENTRY_WRITE_EXECUTE: return 0; } if (pte & BX_PAGING_PHY_ADDRESS_RESERVED_BITS) return 0; pt_address = bx_phy_address(pte & BX_CONST64(0x000ffffffffff000)); if (level == BX_LEVEL_PTE) break; if (pte & 0x80) { if (level > (BX_LEVEL_PDE + !!bx_cpuid_support_1g_paging())) return 0; pt_address &= BX_CONST64(0x000fffffffffe000); if (pt_address & offset_mask) return 0; break; } } *phy = pt_address + (bx_phy_address)(guest_paddr & offset_mask); return 1; } #endif bx_bool BX_CPU_C::dbg_xlate_linear2phy(bx_address laddr, bx_phy_address *phy, bx_bool verbose) { bx_phy_address paddress; #if BX_SUPPORT_X86_64 if (! long_mode()) laddr &= 0xffffffff; #endif if (! BX_CPU_THIS_PTR cr0.get_PG()) { paddress = (bx_phy_address) laddr; } else { bx_phy_address pt_address = BX_CPU_THIS_PTR cr3 & BX_CR3_PAGING_MASK; // see if page is in the TLB first if (! verbose) { bx_address lpf = LPFOf(laddr); unsigned TLB_index = BX_TLB_INDEX_OF(lpf, 0); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[TLB_index]; if (TLB_LPFOf(tlbEntry->lpf) == lpf) { paddress = tlbEntry->ppf | PAGE_OFFSET(laddr); *phy = paddress; return 1; } } #if BX_CPU_LEVEL >= 6 if (BX_CPU_THIS_PTR cr4.get_PAE()) { Bit64u offset_mask = BX_CONST64(0x0000ffffffffffff); int level = 3; if (! long_mode()) { pt_address = BX_CPU_THIS_PTR PDPTR_CACHE.entry[(laddr >> 30) & 3]; if (! (pt_address & 0x1)) goto page_fault; pt_address &= BX_CONST64(0x000ffffffffff000); offset_mask >>= 18; level = 1; } for (; level >= 0; --level) { Bit64u pte; pt_address += ((laddr >> (9 + 9*level)) & 0xff8); offset_mask >>= 9; #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) { if (! dbg_translate_guest_physical(pt_address, &pt_address, verbose)) goto page_fault; } } #endif BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, pt_address, 8, &pte); #if BX_DEBUGGER if (verbose) dbg_print_paging_pte(level, pte); #endif if(!(pte & 1)) goto page_fault; if (pte & BX_PAGING_PHY_ADDRESS_RESERVED_BITS) goto page_fault; pt_address = bx_phy_address(pte & BX_CONST64(0x000ffffffffff000)); if (level == BX_LEVEL_PTE) break; if (pte & 0x80) { // large page pt_address &= BX_CONST64(0x000fffffffffe000); if (pt_address & offset_mask) goto page_fault; if (bx_cpuid_support_1g_paging() && level == BX_LEVEL_PDPTE) break; if (level == BX_LEVEL_PDE) break; goto page_fault; } } paddress = pt_address + (bx_phy_address)(laddr & offset_mask); } else // not PAE #endif { Bit32u offset_mask = 0xfff; for (int level = 1; level >= 0; --level) { Bit32u pte; pt_address += ((laddr >> (10 + 10*level)) & 0xffc); #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) { if (! dbg_translate_guest_physical(pt_address, &pt_address, verbose)) goto page_fault; } } #endif BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, pt_address, 4, &pte); #if BX_DEBUGGER if (verbose) dbg_print_paging_pte(level, pte); #endif if (!(pte & 1)) goto page_fault; pt_address = pte & 0xfffff000; #if BX_CPU_LEVEL >= 6 if (level == BX_LEVEL_PDE && (pte & 0x80) != 0 && BX_CPU_THIS_PTR cr4.get_PSE()) { offset_mask = 0x3fffff; pt_address = pte & 0xffc00000; #if BX_PHY_ADDRESS_WIDTH > 32 pt_address += ((bx_phy_address)(pte & 0x003fe000)) << 19; #endif break; } #endif } paddress = pt_address + (bx_phy_address)(laddr & offset_mask); } } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_EPT_ENABLE)) { if (! dbg_translate_guest_physical(paddress, &paddress, verbose)) goto page_fault; } } #endif *phy = A20ADDR(paddress); return 1; page_fault: *phy = 0; return 0; } #endif void BX_CPU_C::access_write_linear(bx_address laddr, unsigned len, unsigned curr_pl, void *data) { Bit32u pageOffset = PAGE_OFFSET(laddr); /* check for reference across multiple pages */ if ((pageOffset + len) <= 4096) { // Access within single page. BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(laddr, (curr_pl==3), BX_WRITE); BX_CPU_THIS_PTR address_xlation.pages = 1; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, BX_CPU_THIS_PTR address_xlation.paddress1, len, curr_pl, BX_WRITE, (Bit8u*) data); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, len, data); #if BX_X86_DEBUGGER hwbreakpoint_match(laddr, len, BX_WRITE); #endif } else { // access across 2 pages BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(laddr, (curr_pl == 3), BX_WRITE); BX_CPU_THIS_PTR address_xlation.len1 = 4096 - pageOffset; BX_CPU_THIS_PTR address_xlation.len2 = len - BX_CPU_THIS_PTR address_xlation.len1; BX_CPU_THIS_PTR address_xlation.pages = 2; bx_address laddr2 = laddr + BX_CPU_THIS_PTR address_xlation.len1; #if BX_SUPPORT_X86_64 if (! long64_mode()) laddr2 &= 0xffffffff; /* handle linear address wrap in legacy mode */ #endif BX_CPU_THIS_PTR address_xlation.paddress2 = translate_linear(laddr2, (curr_pl == 3), BX_WRITE); #ifdef BX_LITTLE_ENDIAN BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, curr_pl, BX_WRITE, (Bit8u*) data); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr2, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, curr_pl, BX_WRITE, ((Bit8u*)data) + BX_CPU_THIS_PTR address_xlation.len1); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, ((Bit8u*)data) + BX_CPU_THIS_PTR address_xlation.len1); #else // BX_BIG_ENDIAN BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, curr_pl, BX_WRITE, ((Bit8u*)data) + (len - BX_CPU_THIS_PTR address_xlation.len1)); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, ((Bit8u*)data) + (len - BX_CPU_THIS_PTR address_xlation.len1)); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr2, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, curr_pl, BX_WRITE, (Bit8u*) data); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, data); #endif #if BX_X86_DEBUGGER hwbreakpoint_match(laddr, BX_CPU_THIS_PTR address_xlation.len1, BX_WRITE); hwbreakpoint_match(laddr2, BX_CPU_THIS_PTR address_xlation.len2, BX_WRITE); #endif } } void BX_CPU_C::access_read_linear(bx_address laddr, unsigned len, unsigned curr_pl, unsigned xlate_rw, void *data) { BX_ASSERT(xlate_rw == BX_READ || xlate_rw == BX_RW); Bit32u pageOffset = PAGE_OFFSET(laddr); /* check for reference across multiple pages */ if ((pageOffset + len) <= 4096) { // Access within single page. BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(laddr, (curr_pl == 3), xlate_rw); BX_CPU_THIS_PTR address_xlation.pages = 1; access_read_physical(BX_CPU_THIS_PTR address_xlation.paddress1, len, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, BX_CPU_THIS_PTR address_xlation.paddress1, len, curr_pl, BX_READ, (Bit8u*) data); #if BX_X86_DEBUGGER hwbreakpoint_match(laddr, len, xlate_rw); #endif } else { // access across 2 pages BX_CPU_THIS_PTR address_xlation.paddress1 = translate_linear(laddr, (curr_pl == 3), xlate_rw); BX_CPU_THIS_PTR address_xlation.len1 = 4096 - pageOffset; BX_CPU_THIS_PTR address_xlation.len2 = len - BX_CPU_THIS_PTR address_xlation.len1; BX_CPU_THIS_PTR address_xlation.pages = 2; bx_address laddr2 = laddr + BX_CPU_THIS_PTR address_xlation.len1; #if BX_SUPPORT_X86_64 if (! long64_mode()) laddr2 &= 0xffffffff; /* handle linear address wrap in legacy mode */ #endif BX_CPU_THIS_PTR address_xlation.paddress2 = translate_linear(laddr2, (curr_pl == 3), xlate_rw); #ifdef BX_LITTLE_ENDIAN access_read_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, curr_pl, BX_READ, (Bit8u*) data); access_read_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, ((Bit8u*)data) + BX_CPU_THIS_PTR address_xlation.len1); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr2, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, curr_pl, BX_READ, ((Bit8u*)data) + BX_CPU_THIS_PTR address_xlation.len1); #else // BX_BIG_ENDIAN access_read_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, ((Bit8u*)data) + (len - BX_CPU_THIS_PTR address_xlation.len1)); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, curr_pl, BX_READ, ((Bit8u*)data) + (len - BX_CPU_THIS_PTR address_xlation.len1)); access_read_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr2, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, curr_pl, BX_READ, (Bit8u*) data); #endif #if BX_X86_DEBUGGER hwbreakpoint_match(laddr, BX_CPU_THIS_PTR address_xlation.len1, xlate_rw); hwbreakpoint_match(laddr2, BX_CPU_THIS_PTR address_xlation.len2, xlate_rw); #endif } } void BX_CPU_C::access_write_physical(bx_phy_address paddr, unsigned len, void *data) { #if BX_SUPPORT_VMX && BX_SUPPORT_X86_64 if (is_virtual_apic_page(paddr)) { VMX_Virtual_Apic_Write(paddr, len, data); return; } #endif #if BX_SUPPORT_APIC if (BX_CPU_THIS_PTR lapic.is_selected(paddr)) { BX_CPU_THIS_PTR lapic.write(paddr, data, len); return; } #endif BX_MEM(0)->writePhysicalPage(BX_CPU_THIS, paddr, len, data); } void BX_CPU_C::access_read_physical(bx_phy_address paddr, unsigned len, void *data) { #if BX_SUPPORT_VMX && BX_SUPPORT_X86_64 if (is_virtual_apic_page(paddr)) { VMX_Virtual_Apic_Read(paddr, len, data); return; } #endif #if BX_SUPPORT_APIC if (BX_CPU_THIS_PTR lapic.is_selected(paddr)) { BX_CPU_THIS_PTR lapic.read(paddr, data, len); return; } #endif BX_MEM(0)->readPhysicalPage(BX_CPU_THIS, paddr, len, data); } bx_hostpageaddr_t BX_CPU_C::getHostMemAddr(bx_phy_address paddr, unsigned rw) { #if BX_SUPPORT_VMX && BX_SUPPORT_X86_64 if (is_virtual_apic_page(paddr)) return 0; // Do not allow direct access to virtual apic page #endif #if BX_SUPPORT_APIC if (BX_CPU_THIS_PTR lapic.is_selected(paddr)) return 0; // Vetoed! APIC address space #endif return (bx_hostpageaddr_t) BX_MEM(0)->getHostMemAddr(BX_CPU_THIS, paddr, rw); } #if BX_LARGE_RAMFILE bx_bool BX_CPU_C::check_addr_in_tlb_buffers(const Bit8u *addr, const Bit8u *end) { for (unsigned tlb_entry_num=0; tlb_entry_num < BX_TLB_SIZE; tlb_entry_num++) { if (((BX_CPU_THIS_PTR TLB.entry[tlb_entry_num].hostPageAddr)>=(const bx_hostpageaddr_t)addr) && ((BX_CPU_THIS_PTR TLB.entry[tlb_entry_num].hostPageAddr)<(const bx_hostpageaddr_t)end)) return true; } return false; } #endif bochs-2.6/cpu/data_xfer64.cc0000644000175000017500000002677212020641453015555 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: data_xfer64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_RRXRAX(bxInstruction_c *i) { Bit64u temp64 = RAX; RAX = BX_READ_64BIT_REG(i->dst()); BX_WRITE_64BIT_REG(i->dst(), temp64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RRXIq(bxInstruction_c *i) { BX_WRITE_64BIT_REG(i->dst(), i->Iq()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV64_GdEdM(bxInstruction_c *i) { Bit64u eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u val32 = read_virtual_dword_64(i->seg(), eaddr); BX_WRITE_32BIT_REGZ(i->dst(), val32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV64_EdGdM(bxInstruction_c *i) { Bit64u eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword_64(i->seg(), eaddr, BX_READ_32BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EqGqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword_64(i->seg(), eaddr, BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV64S_EqGqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); stack_write_qword(eaddr, BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GqEqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u val64 = read_virtual_qword_64(i->seg(), eaddr); BX_WRITE_64BIT_REG(i->dst(), val64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV64S_GqEqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); BX_WRITE_64BIT_REG(i->dst(), stack_read_qword(eaddr)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GqEqR(bxInstruction_c *i) { BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LEA_GqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); BX_WRITE_64BIT_REG(i->dst(), eaddr); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_ALOq(bxInstruction_c *i) { AL = read_virtual_byte_64(i->seg(), i->Iq()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OqAL(bxInstruction_c *i) { write_virtual_byte_64(i->seg(), i->Iq(), AL); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_AXOq(bxInstruction_c *i) { AX = read_virtual_word_64(i->seg(), i->Iq()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OqAX(bxInstruction_c *i) { write_virtual_word_64(i->seg(), i->Iq(), AX); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EAXOq(bxInstruction_c *i) { RAX = read_virtual_dword_64(i->seg(), i->Iq()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OqEAX(bxInstruction_c *i) { write_virtual_dword_64(i->seg(), i->Iq(), EAX); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RAXOq(bxInstruction_c *i) { RAX = read_virtual_qword_64(i->seg(), i->Iq()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OqRAX(bxInstruction_c *i) { write_virtual_qword_64(i->seg(), i->Iq(), RAX); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EqIdM(bxInstruction_c *i) { Bit64u op_64 = (Bit32s) i->Id(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword_64(i->seg(), eaddr, op_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EqIdR(bxInstruction_c *i) { Bit64u op_64 = (Bit32s) i->Id(); BX_WRITE_64BIT_REG(i->dst(), op_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GqEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op2_8 = read_virtual_byte_64(i->seg(), eaddr); /* zero extend byte op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit64u) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GqEbR(bxInstruction_c *i) { Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); /* zero extend byte op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit64u) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GqEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op2_16 = read_virtual_word_64(i->seg(), eaddr); /* zero extend word op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit64u) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GqEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* zero extend word op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit64u) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GqEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op2_8 = read_virtual_byte_64(i->seg(), eaddr); /* sign extend byte op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit8s) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GqEbR(bxInstruction_c *i) { Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); /* sign extend byte op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit8s) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GqEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op2_16 = read_virtual_word_64(i->seg(), eaddr); /* sign extend word op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit16s) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GqEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* sign extend word op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit16s) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GqEdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op2_32 = read_virtual_dword_64(i->seg(), eaddr); /* sign extend word op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit32s) op2_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GqEdR(bxInstruction_c *i) { Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); /* sign extend word op2 into qword op1 */ BX_WRITE_64BIT_REG(i->dst(), (Bit32s) op2_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EqGqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); write_RMW_virtual_qword(op2_64); BX_WRITE_64BIT_REG(i->src(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EqGqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); BX_WRITE_64BIT_REG(i->src(), op1_64); BX_WRITE_64BIT_REG(i->dst(), op2_64); BX_NEXT_INSTR(i); } // Note: CMOV accesses a memory source operand (read), regardless // of whether condition is true or not. Thus, exceptions may // occur even if the MOV does not take place. BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVO_GqEqR(bxInstruction_c *i) { if (get_OF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNO_GqEqR(bxInstruction_c *i) { if (!get_OF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVB_GqEqR(bxInstruction_c *i) { if (get_CF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNB_GqEqR(bxInstruction_c *i) { if (!get_CF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVZ_GqEqR(bxInstruction_c *i) { if (get_ZF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNZ_GqEqR(bxInstruction_c *i) { if (!get_ZF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVBE_GqEqR(bxInstruction_c *i) { if (get_CF() || get_ZF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNBE_GqEqR(bxInstruction_c *i) { if (! (get_CF() || get_ZF())) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVS_GqEqR(bxInstruction_c *i) { if (get_SF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNS_GqEqR(bxInstruction_c *i) { if (!get_SF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVP_GqEqR(bxInstruction_c *i) { if (get_PF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNP_GqEqR(bxInstruction_c *i) { if (!get_PF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVL_GqEqR(bxInstruction_c *i) { if (getB_SF() != getB_OF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNL_GqEqR(bxInstruction_c *i) { if (getB_SF() == getB_OF()) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVLE_GqEqR(bxInstruction_c *i) { if (get_ZF() || (getB_SF() != getB_OF())) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNLE_GqEqR(bxInstruction_c *i) { if (! get_ZF() && (getB_SF() == getB_OF())) BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); BX_NEXT_INSTR(i); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/arith8.cc0000644000175000017500000003446312020641453014641 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: arith8.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u sum = op1 + op2; write_RMW_virtual_byte(sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GbEbR(bxInstruction_c *i) { Bit32u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u sum = op1 + op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GbEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2 = read_virtual_byte(i->seg(), eaddr); Bit32u sum = op1 + op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u sum = op1 + op2 + getB_CF(); write_RMW_virtual_byte(sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GbEbR(bxInstruction_c *i) { Bit32u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u sum = op1 + op2 + getB_CF(); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GbEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2 = read_virtual_byte(i->seg(), eaddr); Bit32u sum = op1 + op2 + getB_CF(); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u diff_8 = op1_8 - (op2_8 + getB_CF()); write_RMW_virtual_byte(diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GbEbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u diff_8 = op1_8 - (op2_8 + getB_CF()); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GbEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = read_virtual_byte(i->seg(), eaddr); Bit32u diff_8 = op1_8 - (op2_8 + getB_CF()); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EbIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2_8 = i->Ib(); Bit32u diff_8 = op1_8 - (op2_8 + getB_CF()); write_RMW_virtual_byte(diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EbIbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = i->Ib(); Bit32u diff_8 = op1_8 - (op2_8 + getB_CF()); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u diff_8 = op1_8 - op2_8; write_RMW_virtual_byte(diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GbEbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u diff_8 = op1_8 - op2_8; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GbEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = read_virtual_byte(i->seg(), eaddr); Bit32u diff_8 = op1_8 - op2_8; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_virtual_byte(i->seg(), eaddr); Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GbEbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GbEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = read_virtual_byte(i->seg(), eaddr); Bit32u diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EbGbM(bxInstruction_c *i) { /* XADD dst(r/m8), src(r8) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u sum = op1 + op2; write_RMW_virtual_byte(sum); /* and write destination into source */ BX_WRITE_8BIT_REGx(i->src(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EbGbR(bxInstruction_c *i) { /* XADD dst(r/m8), src(r8) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ Bit32u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); Bit32u sum = op1 + op2; // and write destination into source // Note: if both op1 & op2 are registers, the last one written // should be the sum, as op1 & op2 may be the same register. // For example: XADD AL, AL BX_WRITE_8BIT_REGx(i->src(), i->extend8bitL(), op1); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EbIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2 = i->Ib(); Bit32u sum = op1 + op2; write_RMW_virtual_byte(sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EbIbR(bxInstruction_c *i) { Bit32u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2 = i->Ib(); Bit32u sum = op1 + op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EbIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2 = i->Ib(); Bit32u sum = op1 + op2 + getB_CF(); write_RMW_virtual_byte(sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EbIbR(bxInstruction_c *i) { Bit32u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2 = i->Ib(); Bit32u sum = op1 + op2 + getB_CF(); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), sum); SET_FLAGS_OSZAPC_ADD_8(op1, op2, sum); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EbIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u op2_8 = i->Ib(); Bit32u diff_8 = op1_8 - op2_8; write_RMW_virtual_byte(diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EbIbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = i->Ib(); Bit32u diff_8 = op1_8 - op2_8; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), diff_8); SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EbIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_virtual_byte(i->seg(), eaddr); Bit32u op2_8 = i->Ib(); Bit32u diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EbIbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u op2_8 = i->Ib(); Bit32u diff_8 = op1_8 - op2_8; SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); op1_8 = - (Bit8s)(op1_8); write_RMW_virtual_byte(op1_8); SET_FLAGS_OSZAPC_SUB_8(0, 0 - op1_8, op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1_8 = - (Bit8s)(op1_8); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1_8); SET_FLAGS_OSZAPC_SUB_8(0, 0 - op1_8, op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); op1_8++; write_RMW_virtual_byte(op1_8); SET_FLAGS_OSZAP_ADD_8(op1_8 - 1, 0, op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1_8++; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1_8); SET_FLAGS_OSZAP_ADD_8(op1_8 - 1, 0, op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); op1_8--; write_RMW_virtual_byte(op1_8); SET_FLAGS_OSZAP_SUB_8(op1_8 + 1, 0, op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1_8--; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1_8); SET_FLAGS_OSZAP_SUB_8(op1_8 + 1, 0, op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); Bit32u diff_8 = AL - op1_8; SET_FLAGS_OSZAPC_SUB_8(AL, op1_8, diff_8); if (diff_8 == 0) { // if accumulator == dest // dest <-- src Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); write_RMW_virtual_byte(op2_8); } else { // accumulator <-- dest AL = op1_8; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EbGbR(bxInstruction_c *i) { Bit32u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit32u diff_8 = AL - op1_8; SET_FLAGS_OSZAPC_SUB_8(AL, op1_8, diff_8); if (diff_8 == 0) { // if accumulator == dest // dest <-- src Bit32u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op2_8); } else { // accumulator <-- dest AL = op1_8; } BX_NEXT_INSTR(i); } bochs-2.6/cpu/arith64.cc0000644000175000017500000003774412020641453014730 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: arith64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); sum_64 = op1_64 + op2_64; write_RMW_virtual_qword(sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); sum_64 = op1_64 + op2_64; BX_WRITE_64BIT_REG(i->dst(), sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); sum_64 = op1_64 + op2_64; BX_WRITE_64BIT_REG(i->dst(), sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); sum_64 = op1_64 + op2_64 + getB_CF(); write_RMW_virtual_qword(sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); sum_64 = op1_64 + op2_64 + getB_CF(); BX_WRITE_64BIT_REG(i->dst(), sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); sum_64 = op1_64 + op2_64 + getB_CF(); BX_WRITE_64BIT_REG(i->dst(), sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); diff_64 = op1_64 - (op2_64 + getB_CF()); write_RMW_virtual_qword(diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); diff_64 = op1_64 - (op2_64 + getB_CF()); BX_WRITE_64BIT_REG(i->dst(), diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); diff_64 = op1_64 - (op2_64 + getB_CF()); BX_WRITE_64BIT_REG(i->dst(), diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = (Bit32s) i->Id(); diff_64 = op1_64 - (op2_64 + getB_CF()); write_RMW_virtual_qword(diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SBB_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = (Bit32s) i->Id(); diff_64 = op1_64 - (op2_64 + getB_CF()); BX_WRITE_64BIT_REG(i->dst(), diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); diff_64 = op1_64 - op2_64; write_RMW_virtual_qword(diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); diff_64 = op1_64 - op2_64; BX_WRITE_64BIT_REG(i->dst(), diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); diff_64 = op1_64 - op2_64; BX_WRITE_64BIT_REG(i->dst(), diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CDQE(bxInstruction_c *i) { /* CWDE: no flags are affected */ RAX = (Bit32s) EAX; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CQO(bxInstruction_c *i) { /* CQO: no flags are affected */ if (RAX & BX_CONST64(0x8000000000000000)) RDX = BX_CONST64(0xffffffffffffffff); else RDX = 0; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; /* XADD dst(r/m), src(r) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); sum_64 = op1_64 + op2_64; write_RMW_virtual_qword(sum_64); /* and write destination into source */ BX_WRITE_64BIT_REG(i->src(), op1_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XADD_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; /* XADD dst(r/m), src(r) * temp <-- src + dst | sum = op2 + op1 * src <-- dst | op2 = op1 * dst <-- tmp | op1 = sum */ op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); sum_64 = op1_64 + op2_64; // and write destination into source // Note: if both op1 & op2 are registers, the last one written // should be the sum, as op1 & op2 may be the same register. // For example: XADD AL, AL BX_WRITE_64BIT_REG(i->src(), op1_64); BX_WRITE_64BIT_REG(i->dst(), sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = (Bit32s) i->Id(); sum_64 = op1_64 + op2_64; write_RMW_virtual_qword(sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADD_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = (Bit32s) i->Id(); sum_64 = op1_64 + op2_64; BX_WRITE_64BIT_REG(i->dst(), sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = (Bit32s) i->Id(); sum_64 = op1_64 + op2_64 + getB_CF(); write_RMW_virtual_qword(sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADC_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64, sum_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = (Bit32s) i->Id(); sum_64 = op1_64 + op2_64 + getB_CF(); BX_WRITE_64BIT_REG(i->dst(), sum_64); SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = (Bit32s) i->Id(); diff_64 = op1_64 - op2_64; write_RMW_virtual_qword(diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUB_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = (Bit32s) i->Id(); diff_64 = op1_64 - op2_64; BX_WRITE_64BIT_REG(i->dst(), diff_64); SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_virtual_qword_64(i->seg(), eaddr); op2_64 = (Bit32s) i->Id(); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMP_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64, diff_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = (Bit32s) i->Id(); diff_64 = op1_64 - op2_64; SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op1_64 = - (Bit64s)(op1_64); write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAPC_SUB_64(0, -op1_64, op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NEG_EqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); op1_64 = - (Bit64s)(op1_64); BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_SUB_64(0, -op1_64, op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op1_64++; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAP_ADD_64(op1_64 - 1, 0, op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INC_EqR(bxInstruction_c *i) { Bit64u rrx = ++BX_READ_64BIT_REG(i->dst()); SET_FLAGS_OSZAP_ADD_64(rrx - 1, 0, rrx); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op1_64--; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAP_SUB_64(op1_64 + 1, 0, op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DEC_EqR(bxInstruction_c *i) { Bit64u rrx = --BX_READ_64BIT_REG(i->dst()); SET_FLAGS_OSZAP_SUB_64(rrx + 1, 0, rrx); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EqGqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); Bit64u diff_64 = RAX - op1_64; SET_FLAGS_OSZAPC_SUB_64(RAX, op1_64, diff_64); if (diff_64 == 0) { // if accumulator == dest // dest <-- src write_RMW_virtual_qword(BX_READ_64BIT_REG(i->src())); } else { // accumulator <-- dest RAX = op1_64; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG_EqGqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64u diff_64 = RAX - op1_64; SET_FLAGS_OSZAPC_SUB_64(RAX, op1_64, diff_64); if (diff_64 == 0) { // if accumulator == dest // dest <-- src BX_WRITE_64BIT_REG(i->dst(), BX_READ_64BIT_REG(i->src())); } else { // accumulator <-- dest RAX = op1_64; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPXCHG16B(bxInstruction_c *i) { Bit64u diff; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); bx_address laddr = get_laddr64(i->seg(), eaddr); if (laddr & 0xf) { BX_ERROR(("CMPXCHG16B: not aligned memory location (#GP)")); exception(BX_GP_EXCEPTION, 0); } // check write permission for following write Bit64u op1_64_lo = read_RMW_virtual_qword_64(i->seg(), eaddr); Bit64u op1_64_hi = read_RMW_virtual_qword_64(i->seg(), (eaddr + 8) & i->asize_mask()); diff = RAX - op1_64_lo; diff |= RDX - op1_64_hi; if (diff == 0) { // if accumulator == dest // dest <-- src (RCX:RBX) write_RMW_virtual_qword(RCX); // write permissions already checked by read_RMW_virtual_qword_64 write_virtual_qword_64(i->seg(), eaddr, RBX); assert_ZF(); } else { clear_ZF(); // accumulator <-- dest RAX = op1_64_lo; RDX = op1_64_hi; } BX_NEXT_INSTR(i); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/3dnow.cc0000644000175000017500000002211612020641453014464 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: 3dnow.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2002-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_3DNOW BX_CPP_INLINE void prepare_softfloat_status_word(float_status_t &status, int rounding_mode) { status.float_exception_flags = 0; // clear exceptions before execution status.float_nan_handling_mode = float_first_operand_nan; status.float_rounding_mode = rounding_mode; status.flush_underflow_to_zero = 0; } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFPNACC_PqQq(bxInstruction_c *i) { BX_PANIC(("PFPNACC_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } /* 0F 0F /r 0C */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PI2FW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BxPackedMmxRegister result, op; BX_CPU_THIS_PTR prepareMMX(); /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ float_status_t status_word; prepare_softfloat_status_word(status_word, float_round_to_zero); MMXUD0(result) = int32_to_float32((Bit32s)(MMXSW0(op)), status_word); MMXUD1(result) = int32_to_float32((Bit32s)(MMXSW2(op)), status_word); /* now write result back to destination */ BX_WRITE_MMX_REG(i->dst(), result); BX_NEXT_INSTR(i); #endif } /* 0F 0F /r 0D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PI2FD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BxPackedMmxRegister result, op; BX_CPU_THIS_PTR prepareMMX(); /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ float_status_t status_word; prepare_softfloat_status_word(status_word, float_round_to_zero); MMXUD0(result) = int32_to_float32(MMXSD0(op), status_word); MMXUD1(result) = int32_to_float32(MMXSD1(op), status_word); /* now write result back to destination */ BX_WRITE_MMX_REG(i->dst(), result); BX_NEXT_INSTR(i); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PF2IW_PqQq(bxInstruction_c *i) { BX_PANIC(("PF2IW_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } /* 0F 0F /r 1D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PF2ID_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BxPackedMmxRegister result, op; BX_CPU_THIS_PTR prepareMMX(); /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ float_status_t status_word; prepare_softfloat_status_word(status_word, float_round_to_zero); MMXSD0(result) = float32_to_int32_round_to_zero(MMXUD0(op), status_word); MMXSD1(result) = float32_to_int32_round_to_zero(MMXUD1(op), status_word); /* now write result back to destination */ BX_WRITE_MMX_REG(i->dst(), result); BX_NEXT_INSTR(i); #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFNACC_PqQq(bxInstruction_c *i) { BX_PANIC(("PFNACC_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFCMPGE_PqQq(bxInstruction_c *i) { BX_PANIC(("PFCMPGE_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFMIN_PqQq(bxInstruction_c *i) { BX_PANIC(("PFMIN_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFRCP_PqQq(bxInstruction_c *i) { BX_PANIC(("PFRCP_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFRSQRT_PqQq(bxInstruction_c *i) { BX_PANIC(("PFRSQRT_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFSUB_PqQq(bxInstruction_c *i) { BX_PANIC(("PFSUB_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFADD_PqQq(bxInstruction_c *i) { BX_PANIC(("PFADD_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFCMPGT_PqQq(bxInstruction_c *i) { BX_PANIC(("PFCMPGT_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFMAX_PqQq(bxInstruction_c *i) { BX_PANIC(("PFMAX_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFRCPIT1_PqQq(bxInstruction_c *i) { BX_PANIC(("PFRCPIT1_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFRSQIT1_PqQq(bxInstruction_c *i) { BX_PANIC(("PFRSQIT1_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFSUBR_PqQq(bxInstruction_c *i) { BX_PANIC(("PFSUBR_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFACC_PqQq(bxInstruction_c *i) { BX_PANIC(("PFACC_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFCMPEQ_PqQq(bxInstruction_c *i) { BX_PANIC(("PFCMPEQ_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFMUL_PqQq(bxInstruction_c *i) { BX_PANIC(("PFMUL_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PFRCPIT2_PqQq(bxInstruction_c *i) { BX_PANIC(("PFRCPIT2_PqQq: 3DNow! instruction still not implemented")); BX_NEXT_INSTR(i); } /* 0F 0F /r B7 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PMULHRW_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister op1 = BX_READ_MMX_REG(i->dst()), op2, result; /* op2 is a register or memory reference */ if (i->modC0()) { op2 = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op2) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ Bit32s product1 = Bit32s(MMXSW0(op1)) * Bit32s(MMXSW0(op2)) + 0x8000; Bit32s product2 = Bit32s(MMXSW1(op1)) * Bit32s(MMXSW1(op2)) + 0x8000; Bit32s product3 = Bit32s(MMXSW2(op1)) * Bit32s(MMXSW2(op2)) + 0x8000; Bit32s product4 = Bit32s(MMXSW3(op1)) * Bit32s(MMXSW3(op2)) + 0x8000; MMXUW0(result) = Bit16u(product1 >> 16); MMXUW1(result) = Bit16u(product2 >> 16); MMXUW2(result) = Bit16u(product3 >> 16); MMXUW3(result) = Bit16u(product4 >> 16); /* now write result back to destination */ BX_WRITE_MMX_REG(i->dst(), result); BX_NEXT_INSTR(i); #endif } /* 0F 0F /r BB */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PSWAPD_PqQq(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR prepareMMX(); BxPackedMmxRegister result, op; /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_MMX_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } BX_CPU_THIS_PTR prepareFPU2MMX(); /* FPU2MMX transition */ MMXUD0(result) = MMXUD1(op); MMXUD1(result) = MMXUD0(op); /* now write result back to destination */ BX_WRITE_MMX_REG(i->dst(), result); BX_NEXT_INSTR(i); #endif } #endif bochs-2.6/cpu/cpudb/0000755000175000017500000000000012020641451014214 5ustar guillemguillembochs-2.6/cpu/cpudb/p2_klamath.h0000644000175000017500000000377712020641451016425 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p2_klamath.h 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_P2_KLAMATH_CPUID_DEFINITIONS_H #define BX_P2_KLAMATH_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 6 #include "cpu/cpuid.h" class p2_klamath_t : public bx_cpuid_t { public: p2_klamath_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) {} virtual ~p2_klamath_t() {} // return CPU name virtual const char *get_name(void) const { return "p2_klamath"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_p2_klamath_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 6 #endif bochs-2.6/cpu/cpudb/corei7_sandy_bridge_2600K.txt0000644000175000017500000003327612020641451021454 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.58 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 4 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Core 1 -- Thread 0 2 -- Core 2 -- Thread 0 4 -- Core 3 -- Thread 0 6 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 4 (max 8) Number of threads 4 (max 16) Name Intel Core i7 2600K Codename Sandy Bridge Specification Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz (Engineering Sample) Package (platform ID) Socket 1155 LGA (0x1) CPUID 6.A.7 Extended CPUID 6.2A Core Stepping D2 Technology 32 nm TDP Limit 95 Watts Core Speed 1596.3 MHz Multiplier x FSB 16.0 x 99.8 MHz Stock frequency 3400 MHz Instructions sets MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES, AVX L1 Data cache 4 x 32 KBytes, 8-way set associative, 64-byte line size L1 Instruction cache 4 x 32 KBytes, 8-way set associative, 64-byte line size L2 cache 4 x 256 KBytes, 8-way set associative, 64-byte line size L3 cache 8 MBytes, 16-way set associative, 64-byte line size FID/VID Control yes Turbo Mode supported, enabled Max non-turbo ratio 34x Max turbo ratio 38x Max efficiency ratio 16x Max Power 120 Watts Min Power 60 Watts O/C bins unlimited Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01400001h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000206A7 0x00100800 0x1F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B0FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x0000000B 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300803 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000000 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000000 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30303632 0x80000004 0x5043204B 0x20402055 0x30342E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x08850089 MSR 0x000000CE 0x00001000 0x68012200 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x23242526 MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x88360000 MSR 0x000001FC 0x00000000 0x0004005F MSR 0x00000601 0x18141494 0x0000030C MSR 0x00000602 0x18141494 0x00000104 MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x000083B6 0x001482F8 MSR 0x00000611 0x00000000 0x149E2357 MSR 0x00000639 0x00000000 0x1D11FE3D MSR 0x00000641 0x00000000 0xA710DDB9 MSR 0x00000614 0x000A03C0 0x01E002F8 MSR 0x0000019C 0x00000000 0x88360000 MSR 0x000001A2 0x00000000 0x00621400 MSR 0x00000198 0x00001F39 0x00001000 MSR 0x00000199 0x00000000 0x00001000 CPU Thread 1 APIC ID 2 Topology Processor ID 0, Core ID 1, Thread ID 0 Type 01400001h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000206A7 0x02100800 0x1F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B0FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x0000000B 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300803 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000002 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000002 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30303632 0x80000004 0x5043204B 0x20402055 0x30342E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x08850089 MSR 0x000000CE 0x00001000 0x68012200 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x23242526 MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x88370000 MSR 0x000001FC 0x00000000 0x0004005F MSR 0x00000601 0x18141494 0x0000030C MSR 0x00000602 0x18141494 0x00000104 MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x000083B6 0x001482F8 MSR 0x00000611 0x00000000 0x149E6AC0 MSR 0x00000639 0x00000000 0x1D120C3C MSR 0x00000641 0x00000000 0xA710E264 MSR 0x00000614 0x000A03C0 0x01E002F8 MSR 0x0000019C 0x00000000 0x883D0000 MSR 0x000001A2 0x00000000 0x00621400 MSR 0x00000198 0x00001FDD 0x00001000 MSR 0x00000199 0x00000000 0x00001000 CPU Thread 2 APIC ID 4 Topology Processor ID 0, Core ID 2, Thread ID 0 Type 01400001h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000206A7 0x04100800 0x1F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B0FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x0000000B 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300803 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000004 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000004 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30303632 0x80000004 0x5043204B 0x20402055 0x30342E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x08850089 MSR 0x000000CE 0x00001000 0x68012200 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x23242526 MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x88370000 MSR 0x000001FC 0x00000000 0x0004005F MSR 0x00000601 0x18141494 0x0000030C MSR 0x00000602 0x18141494 0x00000104 MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x000083B6 0x001482F8 MSR 0x00000611 0x00000000 0x149EB54C MSR 0x00000639 0x00000000 0x1D121D9A MSR 0x00000641 0x00000000 0xA710E70C MSR 0x00000614 0x000A03C0 0x01E002F8 MSR 0x0000019C 0x00000000 0x883B0000 MSR 0x000001A2 0x00000000 0x00621400 MSR 0x00000198 0x00001EE7 0x00001000 MSR 0x00000199 0x00000000 0x00001000 CPU Thread 3 APIC ID 6 Topology Processor ID 0, Core ID 3, Thread ID 0 Type 01400001h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000206A7 0x06100800 0x1F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B0FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x0000000B 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300803 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000006 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000006 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30303632 0x80000004 0x5043204B 0x20402055 0x30342E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x08850089 MSR 0x000000CE 0x00001000 0x68012200 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x23242526 MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x88370000 MSR 0x000001FC 0x00000000 0x0004005F MSR 0x00000601 0x18141494 0x0000030C MSR 0x00000602 0x18141494 0x00000104 MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x000083B6 0x001482F8 MSR 0x00000611 0x00000000 0x149F02B6 MSR 0x00000639 0x00000000 0x1D123295 MSR 0x00000641 0x00000000 0xA710EBC8 MSR 0x00000614 0x000A03C0 0x01E002F8 MSR 0x0000019C 0x00000000 0x883E0000 MSR 0x000001A2 0x00000000 0x00621400 MSR 0x00000198 0x00001F8B 0x00001000 MSR 0x00000199 0x00000000 0x00001000 bochs-2.6/cpu/cpudb/athlon64_clawhammer.h0000644000175000017500000000476112020641451020234 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: athlon64_clawhammer.h 10668 2011-09-14 20:22:24Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_ATHLON64_CLAWHAMMER_CPUID_DEFINITIONS_H #define BX_ATHLON64_CLAWHAMMER_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class athlon64_clawhammer_t : public bx_cpuid_t { public: athlon64_clawhammer_t(BX_CPU_C *cpu); virtual ~athlon64_clawhammer_t() {} // return CPU name virtual const char *get_name(void) const { return "athlon64_clawhammer"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; void get_cpuid_hidden_level(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_athlon64_clawhammer_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/phenomx3_8650_toliman.h0000644000175000017500000000547212020641451020343 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: phenomx3_8650_toliman.h 11049 2012-02-19 20:15:23Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_PHENOM_X3_8650_TOLIMAN_CPUID_DEFINITIONS_H #define BX_PHENOM_X3_8650_TOLIMAN_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class phenom_8650_toliman_t : public bx_cpuid_t { public: phenom_8650_toliman_t(BX_CPU_C *cpu); virtual ~phenom_8650_toliman_t() {} // return CPU name virtual const char *get_name(void) const { return "phenom_8650_toliman"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; #if BX_SUPPORT_SVM virtual Bit32u get_svm_extensions_bitmask(void) const; #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; #if BX_SUPPORT_MONITOR_MWAIT void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; #endif void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; #if BX_SUPPORT_SVM void get_ext_cpuid_leaf_A(cpuid_function_t *leaf) const; #endif void get_ext_cpuid_leaf_19(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1A(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_phenom_8650_toliman_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/p4_willamette.cc0000644000175000017500000002401712020641451017301 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p4_willamette.cc 10955 2012-01-07 17:54:19Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "p4_willamette.h" #define LOG_THIS cpu-> #if BX_CPU_LEVEL >= 6 void p4_willamette_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: default: get_std_cpuid_leaf_2(leaf); return; } } Bit64u p4_willamette_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2; } Bit32u p4_willamette_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | #if BX_PHY_ADDRESS_LONG BX_CPU_PSE36 | #endif BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC; } // leaf 0x00000000 // void p4_willamette_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x2; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void p4_willamette_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00000F12; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags leaf->ecx = 0; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void p4_willamette_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x665B5001; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x007A7040; } // leaf 0x80000000 // void p4_willamette_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000004; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void p4_willamette_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = 0; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = 0; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void p4_willamette_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = " Intel(R) Pentium(R) 4 CPU 1.80GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } void p4_willamette_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0x2; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000004; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_p4_willamette_cpuid(BX_CPU_C *cpu) { return new p4_willamette_t(cpu); } #endif bochs-2.6/cpu/cpudb/amd_k6_2_chomper.txt0000644000175000017500000000345312020641451020061 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.53.1 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 1 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 1 (max 1) Name AMD K6-2 Codename Chomper Specification AMD-K6(tm) 3D processor Package Socket 7 (321) CPUID 5.8.0 Extended CPUID 6.8 Core Stepping Technology 0.25 um Core Speed 267.3 MHz Instructions sets MMX, 3DNow! L1 Data cache 32 KBytes, 2-way set associative, 32-byte line size L1 Instruction cache 32 KBytes, 2-way set associative, 32-byte line size FID/VID Control no Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 02000802h Max CPUID level 00000001h Max CPUID ext. level 80000005h Cache descriptor Level 1, I, 32 KB, 1 thread(s) Cache descriptor Level 1, D, 32 KB, 1 thread(s) CPUID 0x00000000 0x00000001 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00000580 0x00000000 0x00000000 0x008001BF 0x80000000 0x80000005 0x00000000 0x00000000 0x00000000 0x80000001 0x00000680 0x00000000 0x00000000 0x808009BF 0x80000002 0x2D444D41 0x7428364B 0x3320296D 0x72702044 0x80000003 0x7365636F 0x00726F73 0x00000000 0x00000000 0x80000004 0x00000000 0x00000000 0x00000000 0x00000000 0x80000005 0x00000000 0x02800140 0x20020220 0x20020220 bochs-2.6/cpu/cpudb/amd_k6_2_chomper.cc0000644000175000017500000002531712020641451017632 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: amd_k6_2_chomper.cc 10877 2011-12-28 21:54:51Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "amd_k6_2_chomper.h" #define LOG_THIS cpu-> #if BX_CPU_LEVEL >= 5 && BX_SUPPORT_X86_64 == 0 amd_k6_2_chomper_t::amd_k6_2_chomper_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (BX_SUPPORT_X86_64) BX_PANIC(("x86-64 should be disabled for AMD K6-2 configuration")); if (BX_CPU_LEVEL != 5) BX_PANIC(("AMD K6-2 configuration should be compiled with BX_CPU_LEVEL=5")); BX_INFO(("WARNING: 3DNow! is not implemented yet !")); } void amd_k6_2_chomper_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x8FFFFFFF: get_cpuid_hidden_level(leaf); return; case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_ext_cpuid_leaf_5(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; default: get_reserved_leaf(leaf); return; } } Bit64u amd_k6_2_chomper_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_MMX | BX_ISA_SYSCALL_SYSRET_LEGACY | BX_ISA_3DNOW; } Bit32u amd_k6_2_chomper_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | #if BX_PHY_ADDRESS_LONG BX_CPU_PSE36 | #endif BX_CPU_PSE; } // leaf 0x00000000 // void amd_k6_2_chomper_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x1; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void amd_k6_2_chomper_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00000580; leaf->ebx = 0; leaf->ecx = 0; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSENTER/SYSEXIT support // [12:12] MTRR: Memory Type Range Reg // [13:13] PGE/PTE Global Bit // [14:14] MCA: Machine Check Architecture // [15:15] CMOV: Cond Mov/Cmp Instructions // [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] SSE: SSE Extensions // [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_MMX; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000000 // void amd_k6_2_chomper_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000005; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x80000001 // void amd_k6_2_chomper_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (same as 0x00000001.EAX) leaf->eax = 0x00000680; leaf->ebx = 0; leaf->ecx = 0; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSCALL/SYSRET support // [12:12] MTRR: Memory Type Range Reg // [13:13] PGE/PTE Global Bit // [14:14] MCA: Machine Check Architecture // [15:15] CMOV: Cond Mov/Cmp Instructions // [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] Reserved // [19:19] Reserved // [20:20] No-Execute page protection // [21:21] Reserved // [22:22] MMXExt: AMD Extensions to MMX Technology // * [23:23] MMX Technology // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] FFXSR: Fast FXSAVE/FXRSTOR // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // * [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD2_SYSCALL_SYSRET | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_MMX | BX_CPUID_STD2_3DNOW; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void amd_k6_2_chomper_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "AMD-K6(tm) 3D processor\0\0\0\0\0\0\0\0\0\0\0\0\0"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); leaf->ecx = 0; leaf->edx = 0; break; case 0x80000004: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 // void amd_k6_2_chomper_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x800000005 - L1 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x02800140; leaf->ecx = 0x20020220; leaf->edx = 0x20020220; } // leaf 0x8FFFFFFF // void amd_k6_2_chomper_t::get_cpuid_hidden_level(cpuid_function_t *leaf) const { static const char* magic_string = "NexGenerationAMD"; memcpy(&(leaf->eax), magic_string , 4); memcpy(&(leaf->ebx), magic_string + 4, 4); memcpy(&(leaf->ecx), magic_string + 8, 4); memcpy(&(leaf->edx), magic_string + 12, 4); #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } void amd_k6_2_chomper_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=1; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000005; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } get_cpuid_leaf(0x8fffffff, 0x00000000, &leaf); BX_INFO(("CPUID[0x8fffffff]: %08x %08x %08x %08x", leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } bx_cpuid_t *create_amd_k6_2_chomper_cpuid(BX_CPU_C *cpu) { return new amd_k6_2_chomper_t(cpu); } #endif bochs-2.6/cpu/cpudb/corei5_arrandale_m520.h0000644000175000017500000000557212020641451020340 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei5_arrandale_m520.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_COREI5_ARRANDALE_M520_CPUID_DEFINITIONS_H #define BX_COREI5_ARRANDALE_M520_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class corei5_arrandale_m520_t : public bx_cpuid_t { public: corei5_arrandale_m520_t(BX_CPU_C *cpu); virtual ~corei5_arrandale_m520_t() {} // return CPU name virtual const char *get_name(void) const { return "corei5_arrandale_m520"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; #if BX_SUPPORT_VMX >= 2 virtual Bit32u get_vmx_extensions_bitmask(void) const; #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_corei5_arrandale_m520_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/corei5_lynnfield_750.cc0000644000175000017500000005120212020641451020350 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei5_lynnfield_750.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "corei5_lynnfield_750.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 corei5_lynnfield_750_t::corei5_lynnfield_750_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Intel Core i5 750 (Lynnfield) configuration")); if (BX_SUPPORT_VMX == 1) BX_INFO(("You must compile with --enable-vmx=2 for Intel Core i5 750 (Lynnfield) VMX configuration")); if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void corei5_lynnfield_750_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: get_std_cpuid_leaf_A(leaf); return; case 0x0000000B: default: get_std_cpuid_extended_topology_leaf(subfunction, leaf); return; } } Bit64u corei5_lynnfield_750_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_SSSE3 | BX_ISA_SSE4_1 | BX_ISA_SSE4_2 | BX_ISA_POPCNT | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif #if BX_SUPPORT_VMX >= 2 BX_ISA_VMX | #endif BX_ISA_SMX | BX_ISA_RDTSCP | BX_ISA_CMPXCHG16B | BX_ISA_LM_LAHF_SAHF; } Bit32u corei5_lynnfield_750_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX; } #if BX_SUPPORT_VMX >= 2 Bit32u corei5_lynnfield_750_t::get_vmx_extensions_bitmask(void) const { return BX_VMX_TPR_SHADOW | BX_VMX_VIRTUAL_NMI | BX_VMX_APIC_VIRTUALIZATION | BX_VMX_WBINVD_VMEXIT | /* BX_VMX_MONITOR_TRAP_FLAG | */ // not implemented yet BX_VMX_VPID | BX_VMX_EPT | BX_VMX_SAVE_DEBUGCTL_DISABLE | BX_VMX_PERF_GLOBAL_CTRL | // MSR not implemented yet BX_VMX_PAT | BX_VMX_EFER | BX_VMX_DESCRIPTOR_TABLE_EXIT | BX_VMX_X2APIC_VIRTUALIZATION | BX_VMX_PREEMPTION_TIMER; } #endif // leaf 0x00000000 // void corei5_lynnfield_750_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) leaf->eax = 0x2; else leaf->eax = 0xB; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void corei5_lynnfield_750_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x000106e5; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // * [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // * [4:4] DS-CPL: CPL qualified debug store // * [5:5] VMX: Virtual Machine Technology // * [6:6] SMX: Secure Virtual Machine Technology // * [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // * [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // * [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // * [19:19] SSE4.1 Instructions // * [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // * [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_DTES64 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_DS_CPL | #if BX_SUPPORT_VMX >= 2 BX_CPUID_EXT_VMX | #endif BX_CPUID_EXT_SMX | BX_CPUID_EXT_EST | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_SSSE3 | BX_CPUID_EXT_CMPXCHG16B | BX_CPUID_EXT_xTPR | BX_CPUID_EXT_PDCM | BX_CPUID_EXT_SSE4_1 | BX_CPUID_EXT_SSE4_2 | BX_CPUID_EXT_POPCNT; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_THERMAL_MONITOR | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void corei5_lynnfield_750_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x55035a01; leaf->ebx = 0x00f0b0e4; leaf->ecx = 0x00000000; leaf->edx = 0x09ca212c; } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void corei5_lynnfield_750_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters // EAX: // [04-00] - Cache Type Field // 0 = No more caches // 1 = Data Cache // 2 = Instruction Cache // 3 = Unified Cache // [07-05] - Cache Level (starts at 1)] // [08] - Self Initializing cache level (doesn't need software initialization) // [09] - Fully Associative cache // [13-10] - Reserved // [25-14] - Maximum number of addressable IDs for logical processors sharing this cache // [31-26] - Maximum number of addressable IDs for processor cores in the physical package - 1 // EBX: // [11-00] - L = System Coherency Line Size // [21-12] - P = Physical Line partitions // [31-22] - W = Ways of associativity // ECX: Number of Sets // EDX: // [00] - Writeback invalidate // [01] - Cache Inclusiveness // [02] - Complex Cache Indexing // [31-03] - Reserved switch(subfunction) { case 0: leaf->eax = 0x1C004121; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000000; break; case 1: leaf->eax = 0x1C004122; leaf->ebx = 0x00C0003F; leaf->ecx = 0x0000007F; leaf->edx = 0x00000000; break; case 2: leaf->eax = 0x1C004143; leaf->ebx = 0x01C0003F; leaf->ecx = 0x000001FF; leaf->edx = 0x00000000; break; case 3: leaf->eax = 0x1C03C163; leaf->ebx = 0x03C0003F; leaf->ecx = 0x00001FFF; leaf->edx = 0x00000002; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; } } // leaf 0x00000005 // void corei5_lynnfield_750_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x00001120; #else leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000006 // void corei5_lynnfield_750_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0x00000003; leaf->ebx = 0x00000002; leaf->ecx = 0x00000001; leaf->edx = 0x00000000; } // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void corei5_lynnfield_750_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0x07300403; leaf->ebx = 0x00000044; leaf->ecx = 0x00000000; leaf->edx = 0x00000603; BX_INFO(("WARNING: Architectural Performance Monitoring is not implemented")); } BX_CPP_INLINE static Bit32u ilog2(Bit32u x) { Bit32u count = 0; while(x>>=1) count++; return count; } // leaf 0x0000000B // void corei5_lynnfield_750_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x0000000B - Extended Topology Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = subfunction; leaf->edx = cpu->get_apic_id(); #if BX_SUPPORT_SMP switch(subfunction) { case 0: if (nthreads > 1) { leaf->eax = ilog2(nthreads-1)+1; leaf->ebx = nthreads; leaf->ecx |= (1<<8); } else if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } else { leaf->eax = 1; leaf->ebx = 1; // number of logical CPUs at this level } break; case 1: if (nthreads > 1) { if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } else if (ncores > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; case 2: if (nthreads > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; default: break; } #endif } // leaf 0x80000000 // void corei5_lynnfield_750_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void corei5_lynnfield_750_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // * [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // * [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // * [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD2_NX | BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE; if (cpu->long64_mode()) leaf->edx |= BX_CPUID_STD2_SYSCALL_SYSRET; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void corei5_lynnfield_750_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "Intel(R) Core(TM) i5 CPU 750 @ 2.67GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void corei5_lynnfield_750_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x01006040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void corei5_lynnfield_750_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x00000100; // bit 8 - invariant TSC } // leaf 0x80000008 // void corei5_lynnfield_750_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void corei5_lynnfield_750_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0xb; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_corei5_lynnfield_750_cpuid(BX_CPU_C *cpu) { return new corei5_lynnfield_750_t(cpu); } #endif bochs-2.6/cpu/cpudb/athlon64_venice.txt0000644000175000017500000000735412020641451017756 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.52.1 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 1 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 1 (max 1) Name AMD Athlon 64 3000+ Codename Venice Specification AMD Athlon(tm) 64 Processor 3000+ Package Socket 939 CPUID F.F.2 Extended CPUID F.2F Brand ID 4 Core Stepping DH-E6 Technology 90 nm Core Speed 1808.4 MHz Multiplier x FSB 9.0 x 200.9 MHz HT Link speed 1004.7 MHz Stock frequency 1800 MHz Instructions sets MMX (+), 3DNow! (+), SSE, SSE2, SSE3, x86-64 L1 Data cache 64 KBytes, 2-way set associative, 64-byte line size L1 Instruction cache 64 KBytes, 2-way set associative, 64-byte line size L2 cache 512 KBytes, 16-way set associative, 64-byte line size FID/VID Control yes Max FID 9.0x VID range 1.100 V - 1.450 V K8 Thermal sensor yes K8 Revision ID 4.2 Attached device PCI device at bus 0, device 24, function 0 Attached device PCI device at bus 0, device 24, function 1 Attached device PCI device at bus 0, device 24, function 2 Attached device PCI device at bus 0, device 24, function 3 Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 02002001h Max CPUID level 00000001h Max CPUID ext. level 80000018h Cache descriptor Level 1, I, 64 KB, 1 thread(s) Cache descriptor Level 1, D, 64 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) CPUID 0x00000000 0x00000001 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00020FF2 0x00000800 0x00000001 0x078BFBFF 0x80000000 0x80000018 0x68747541 0x444D4163 0x69746E65 0x80000001 0x00020FF2 0x00000108 0x00000001 0xE3D3FBFF 0x80000002 0x20444D41 0x6C687441 0x74286E6F 0x3620296D 0x80000003 0x72502034 0x7365636F 0x20726F73 0x30303033 0x80000004 0x0000002B 0x00000000 0x00000000 0x00000000 0x80000005 0xFF08FF08 0xFF20FF20 0x40020140 0x40020140 0x80000006 0x00000000 0x42004200 0x02008140 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x0000003F 0x80000008 0x00003028 0x00000000 0x00000000 0x00000000 0x80000009 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000A 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000B 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000D 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000E 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000F 0x00000000 0x00000000 0x00000000 0x00000000 0x80000010 0x00000000 0x00000000 0x00000000 0x00000000 0x80000011 0x00000000 0x00000000 0x00000000 0x00000000 0x80000012 0x00000000 0x00000000 0x00000000 0x00000000 0x80000013 0x00000000 0x00000000 0x00000000 0x00000000 0x80000014 0x00000000 0x00000000 0x00000000 0x00000000 0x80000015 0x00000000 0x00000000 0x00000000 0x00000000 0x80000016 0x00000000 0x00000000 0x00000000 0x00000000 0x80000017 0x00000000 0x00000000 0x00000000 0x00000000 0x80000018 0x00000000 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0xC001001E 0x00000000 0x00000042 MSR 0xC0010015 0x00000000 0x0A000000 MSR 0xC0010042 0x12040606 0x040A0A0A MSR 0xC0010041 0x00002710 0x0000060A bochs-2.6/cpu/cpudb/amd_k6_2_chomper.h0000644000175000017500000000453412020641451017472 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: amd_k6_2_chomper.h 10668 2011-09-14 20:22:24Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_amd_k6_2_chomper_CPUID_DEFINITIONS_H #define BX_amd_k6_2_chomper_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 5 && BX_SUPPORT_X86_64 == 0 #include "cpu/cpuid.h" class amd_k6_2_chomper_t : public bx_cpuid_t { public: amd_k6_2_chomper_t(BX_CPU_C *cpu); virtual ~amd_k6_2_chomper_t() {} // return CPU name virtual const char *get_name(void) const { return "amd_k6_2_chomper"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_cpuid_hidden_level(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_amd_k6_2_chomper_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 5 && BX_SUPPORT_X86_64 == 0 #endif bochs-2.6/cpu/cpudb/core_duo_t2400_yonah.cc0000644000175000017500000004237412020641451020363 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: core_duo_t2400_yonah.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "core_duo_t2400_yonah.h" #define LOG_THIS cpu-> #if BX_CPU_LEVEL >= 6 core_duo_t2400_yonah_t::core_duo_t2400_yonah_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void core_duo_t2400_yonah_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: default: get_std_cpuid_leaf_A(leaf); return; } } Bit64u core_duo_t2400_yonah_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif #if BX_SUPPORT_VMX BX_ISA_VMX | #endif BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3; } Bit32u core_duo_t2400_yonah_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | #if BX_PHY_ADDRESS_LONG BX_CPU_PSE36 | #endif BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_NX; } // leaf 0x00000000 // void core_duo_t2400_yonah_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) leaf->eax = 0x2; else leaf->eax = 0xA; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void core_duo_t2400_yonah_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x000006EC; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // [4:4] DS-CPL: CPL qualified debug store // * [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // * [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // * [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif #if BX_SUPPORT_VMX BX_CPUID_EXT_VMX | #endif BX_CPUID_EXT_EST | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_xTPR | BX_CPUID_EXT_PDCM; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void core_duo_t2400_yonah_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x02B3B001; leaf->ebx = 0x000000F0; leaf->ecx = 0x00000000; leaf->edx = 0x2C04307D; } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void core_duo_t2400_yonah_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters // EAX: // [04-00] - Cache Type Field // 0 = No more caches // 1 = Data Cache // 2 = Instruction Cache // 3 = Unified Cache // [07-05] - Cache Level (starts at 1)] // [08] - Self Initializing cache level (doesn't need software initialization) // [09] - Fully Associative cache // [13-10] - Reserved // [25-14] - Maximum number of addressable IDs for logical processors sharing this cache // [31-26] - Maximum number of addressable IDs for processor cores in the physical package - 1 // EBX: // [11-00] - L = System Coherency Line Size // [21-12] - P = Physical Line partitions // [31-22] - W = Ways of associativity // ECX: Number of Sets // EDX: // [00] - Writeback invalidate // [01] - Cache Inclusiveness // [02] - Complex Cache Indexing // [31-03] - Reserved switch(subfunction) { case 0: leaf->eax = 0x04000121; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000001; break; case 1: leaf->eax = 0x04000122; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000001; break; case 2: leaf->eax = 0x04004143; leaf->ebx = 0x01C0003F; leaf->ecx = 0x00000FFF; leaf->edx = 0x00000001; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; } } // leaf 0x00000005 // void core_duo_t2400_yonah_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x00022220; #else leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000006 // void core_duo_t2400_yonah_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0x00000001; leaf->ebx = 0x00000002; leaf->ecx = 0x00000001; leaf->edx = 0x00000000; } // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void core_duo_t2400_yonah_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0x07280201; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x00000000; BX_INFO(("WARNING: Architectural Performance Monitoring is not implemented")); } // leaf 0x80000000 // void core_duo_t2400_yonah_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void core_duo_t2400_yonah_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = 0; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD2_NX; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void core_duo_t2400_yonah_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "Intel(R) Core(TM) Duo CPU T2400 @ 1.83GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void core_duo_t2400_yonah_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x08006040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void core_duo_t2400_yonah_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x80000008 // void core_duo_t2400_yonah_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void core_duo_t2400_yonah_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0xA; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_core_duo_t2400_yonah_cpuid(BX_CPU_C *cpu) { return new core_duo_t2400_yonah_t(cpu); } #endif bochs-2.6/cpu/cpudb/p3_katmai.cc0000644000175000017500000001437612020641451016406 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p3_katmai.cc 10688 2011-09-25 17:36:20Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "p3_katmai.h" #if BX_CPU_LEVEL >= 6 #define LOG_THIS cpu-> void p3_katmai_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: default: get_std_cpuid_leaf_3(leaf); return; } } Bit64u p3_katmai_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_SSE; } Bit32u p3_katmai_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | #if BX_PHY_ADDRESS_LONG BX_CPU_PSE36 | #endif BX_CPU_MTRR | BX_CPU_PAT; } // leaf 0x00000000 // void p3_katmai_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x3; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void p3_katmai_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00000673; leaf->ebx = 0; leaf->ecx = 0; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // * [18:18] PSN: Processor Serial Number // [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void p3_katmai_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x03020101; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x0C040843; } // leaf 0x00000003 // void p3_katmai_t::get_std_cpuid_leaf_3(cpuid_function_t *leaf) const { // CPUID function 0x00000003 - Processor Serial Number leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } void p3_katmai_t::dump_cpuid(void) const { struct cpuid_function_t leaf; for (unsigned n=0; n<=0x3; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_p3_katmai_cpuid(BX_CPU_C *cpu) { return new p3_katmai_t(cpu); } #endif bochs-2.6/cpu/cpudb/corei7_ivy_bridge_3770K.h0000644000175000017500000000612012020641451020552 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei7_ivy_bridge_3770K.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_COREI7_IVY_BRIDGE_3770K_CPUID_DEFINITIONS_H #define BX_COREI7_IVY_BRIDGE_3770K_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 && BX_SUPPORT_AVX #include "cpu/cpuid.h" class corei7_ivy_bridge_3770k_t : public bx_cpuid_t { public: corei7_ivy_bridge_3770k_t(BX_CPU_C *cpu); virtual ~corei7_ivy_bridge_3770k_t() {} // return CPU name virtual const char *get_name(void) const { return "corei7_ivy_bridge_3770k"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; #if BX_SUPPORT_VMX >= 2 virtual Bit32u get_vmx_extensions_bitmask(void) const; #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_corei7_ivy_bridge_3770k_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 && BX_SUPPORT_AVX #endif bochs-2.6/cpu/cpudb/p4_prescott_celeron_336.h0000644000175000017500000000500512020641451020735 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p4_prescott_celeron_336.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_P4_PSC_CELERON_336_CPUID_DEFINITIONS_H #define BX_P4_PSC_CELERON_336_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class p4_prescott_celeron_336_t : public bx_cpuid_t { public: p4_prescott_celeron_336_t(BX_CPU_C *cpu); virtual ~p4_prescott_celeron_336_t() {} // return CPU name virtual const char *get_name(void) const { return "p4_prescott_celeron_336"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_3(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_p4_prescott_celeron_336_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/core2_penryn_t9600.h0000644000175000017500000000551312020641451017640 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: core2_penryn_t9600.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_CORE2_PNR_T9600_CPUID_DEFINITIONS_H #define BX_CORE2_PNR_T9600_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class core2_penryn_t9600_t : public bx_cpuid_t { public: core2_penryn_t9600_t(BX_CPU_C *cpu); virtual ~core2_penryn_t9600_t() {} // return CPU name virtual const char *get_name(void) const { return "core2_penryn_t9600"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; #if BX_SUPPORT_VMX virtual Bit32u get_vmx_extensions_bitmask(void) const; #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_core2_penryn_t9600_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/athlon64_venice.h0000644000175000017500000000472112020641451017361 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: athlon64_venice.h 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_ATHLON64_VENICE_CPUID_DEFINITIONS_H #define BX_ATHLON64_VENICE_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class athlon64_venice_t : public bx_cpuid_t { public: athlon64_venice_t(BX_CPU_C *cpu); virtual ~athlon64_venice_t() {} // return CPU name virtual const char *get_name(void) const { return "athlon64_venice"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; void get_cpuid_hidden_level(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_athlon64_venice_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/Makefile.in0000644000175000017500000003014612020641451016265 0ustar guillemguillem# Copyright (C) 2011 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ top_builddir = ../.. top_srcdir = @top_srcdir@ SHELL = @SHELL@ @SET_MAKE@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ BX_INCDIRS = -I.. -I../.. -I$(srcdir)/.. -I$(srcdir)/../.. -I../../@INSTRUMENT_DIR@ -I$(srcdir)/../../@INSTRUMENT_DIR@ CPUDB_OBJS = pentium_mmx.o \ amd_k6_2_chomper.o \ p2_klamath.o \ p3_katmai.o \ p4_willamette.o \ p4_prescott_celeron_336.o \ athlon64_clawhammer.o \ athlon64_venice.o \ turion64_tyler.o \ phenomx3_8650_toliman.o \ core_duo_t2400_yonah.o \ core2_penryn_t9600.o \ corei5_lynnfield_750.o \ corei5_arrandale_m520.o \ corei7_sandy_bridge_2600K.o \ corei7_ivy_bridge_3770K.o \ atom_n270.o BX_INCLUDES = ../../bochs.h ../../config.h all: libcpudb.a .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(BX_INCDIRS) $(CXXFLAGS) @CXXFP@$< @OFP@$@ libcpudb.a: $(CPUDB_OBJS) @RMCOMMAND@ libcpudb.a @MAKELIB@ $(CPUDB_OBJS) $(RANLIB) libcpudb.a $(CPUDB_OBJS): $(BX_INCLUDES) clean: @RMCOMMAND@ *.o @RMCOMMAND@ *.a dist-clean: clean @RMCOMMAND@ Makefile ########################################### # dependencies generated by # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | sed 's/\.cc/.@CPP_SUFFIX@/g' ########################################### athlon64_clawhammer.o: athlon64_clawhammer.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ athlon64_clawhammer.h ../../cpu/cpuid.h athlon64_venice.o: athlon64_venice.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ athlon64_venice.h ../../cpu/cpuid.h turion64_tyler.o: turion64_tyler.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ turion64_tyler.h ../../cpu/cpuid.h phenomx3_8650_toliman.o: phenomx3_8650_toliman.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ phenomx3_8650_toliman.h ../../cpu/cpuid.h atom_n270.o: atom_n270.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h ../crregs.h \ ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h ../icache.h \ ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ ../../param_names.h atom_n270.h core2_penryn_t9600.o: core2_penryn_t9600.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h ../crregs.h \ ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h ../icache.h \ ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ ../../param_names.h core2_penryn_t9600.h ../../cpu/cpuid.h core_duo_t2400_yonah.o: core_duo_t2400_yonah.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ ../../param_names.h core_duo_t2400_yonah.h corei7_sandy_bridge_2600K.o: corei7_sandy_bridge_2600K.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ ../../param_names.h corei7_sandy_bridge_2600K.h ../../cpu/cpuid.h corei7_ivy_bridge_3770K.o: corei7_ivy_bridge_3770K.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ ../../param_names.h corei7_ivy_bridge_3770K.h ../../cpu/cpuid.h corei5_arrandale_m520.o: corei5_arrandale_m520.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ ../../param_names.h corei5_arrandale_m520.h ../../cpu/cpuid.h corei5_lynnfield_750.o: corei5_lynnfield_750.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ ../../param_names.h corei5_lynnfield_750.h ../../cpu/cpuid.h p2_klamath.o: p2_klamath.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h ../crregs.h \ ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h ../icache.h \ ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ p2_klamath.h p3_katmai.o: p3_katmai.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h ../crregs.h \ ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h ../icache.h \ ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h p3_katmai.h p4_prescott_celeron_336.o: p4_prescott_celeron_336.@CPP_SUFFIX@ ../../bochs.h \ ../../config.h ../../osdep.h ../../bx_debug/debug.h ../../config.h \ ../../osdep.h ../../gui/siminterface.h ../../cpudb.h \ ../../gui/paramtree.h ../../memory/memory.h ../../pc_system.h \ ../../gui/gui.h ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h \ ../crregs.h ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h \ ../icache.h ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ p4_prescott_celeron_336.h ../../cpu/cpuid.h p4_willamette.o: p4_willamette.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h ../crregs.h \ ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h ../icache.h \ ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ p4_willamette.h pentium_mmx.o: pentium_mmx.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h ../crregs.h \ ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h ../icache.h \ ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ pentium_mmx.h amd_k6_2_chomper.o: amd_k6_2_chomper.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../cpu.h ../cpuid.h ../crregs.h \ ../descriptor.h ../instr.h ../ia_opcodes.h ../lazy_flags.h ../icache.h \ ../apic.h ../i387.h ../../fpu/softfloat.h ../../fpu/tag_w.h \ ../../fpu/status_w.h ../../fpu/control_w.h ../xmm.h ../vmx.h ../svm.h \ amd_k6_2_chomper.h bochs-2.6/cpu/cpudb/corei5_lynnfield_750.txt0000644000175000017500000003125612020641451020611 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.58 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 4 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Core 1 -- Thread 0 2 -- Core 2 -- Thread 0 4 -- Core 3 -- Thread 0 6 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 4 (max 8) Number of threads 4 (max 16) Name Intel Core i5 750 Codename Lynnfield Specification Intel(R) Core(TM) i5 CPU 750 @ 2.67GHz Package (platform ID) Socket 1156 LGA (0x1) CPUID 6.E.5 Extended CPUID 6.1E Core Stepping B1 Technology 45 nm TDP Limit 95 Watts Core Speed 1158.1 MHz Multiplier x FSB 9.0 x 128.7 MHz Rated Bus speed 2316.1 MHz Stock frequency 2666 MHz Instructions sets MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x L1 Data cache 4 x 32 KBytes, 8-way set associative, 64-byte line size L1 Instruction cache 4 x 32 KBytes, 4-way set associative, 64-byte line size L2 cache 4 x 256 KBytes, 8-way set associative, 64-byte line size L3 cache 8 MBytes, 16-way set associative, 64-byte line size FID/VID Control yes Turbo Mode supported, enabled Max turbo frequency 3200 MHz Max non-turbo ratio 20x Max turbo ratio 24x Max efficiency ratio 9x TDC Limit 89 Amps Core TDP 89 Watts Uncore TDP 6 Watts Power @ 9x 14 Watts Power @ 10x 17 Watts Power @ 11x 20 Watts Power @ 12x 25 Watts Power @ 13x 30 Watts Power @ 14x 36 Watts Power @ 15x 43 Watts Power @ 16x 51 Watts Power @ 17x 60 Watts Power @ 18x 70 Watts Power @ 19x 82 Watts Power @ 20x 95 Watts Max bus number 255 Attached device PCI device at bus 255, device 2, function 1 Attached device PCI device at bus 255, device 3, function 4 Attached device PCI device at bus 255, device 2, function 1 Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000106E5 0x00100800 0x0098E3FD 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B0E4 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000003 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000044 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000001 0x00000100 0x00000000 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100000 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x20202020 0x80000004 0x30353720 0x20402020 0x37362E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x0000003A 0x00000000 0x00000007 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x40031400 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x15151818 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x02C802F8 MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x8848000C MSR 0x000001A2 0x00000000 0x00631000 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x00000009 MSR 0x00000199 0x00000000 0x00000009 CPU Thread 1 APIC ID 2 Topology Processor ID 0, Core ID 1, Thread ID 0 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000106E5 0x02100800 0x0098E3FD 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B0E4 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000003 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000044 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000001 0x00000100 0x00000002 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000002 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100000 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x20202020 0x80000004 0x30353720 0x20402020 0x37362E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000007 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x40031400 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x15151818 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x02C802F8 MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x8849000C MSR 0x000001A2 0x00000000 0x00631000 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x00000009 MSR 0x00000199 0x00000000 0x00000009 CPU Thread 2 APIC ID 4 Topology Processor ID 0, Core ID 2, Thread ID 0 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000106E5 0x04100800 0x0098E3FD 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B0E4 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000003 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000044 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000001 0x00000100 0x00000004 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000004 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100000 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x20202020 0x80000004 0x30353720 0x20402020 0x37362E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000007 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x40031400 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x15151818 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x02C802F8 MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x8845000C MSR 0x000001A2 0x00000000 0x00631000 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x00000009 MSR 0x00000199 0x00000000 0x00000009 CPU Thread 3 APIC ID 6 Topology Processor ID 0, Core ID 3, Thread ID 0 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000106E5 0x06100800 0x0098E3FD 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B0E4 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000003 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000044 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000001 0x00000100 0x00000006 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000006 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100000 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x20202020 0x80000004 0x30353720 0x20402020 0x37362E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000007 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x40031400 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x15151818 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x02C802F8 MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x8849000C MSR 0x000001A2 0x00000000 0x00631000 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x00000009 MSR 0x00000199 0x00000000 0x00000009 bochs-2.6/cpu/cpudb/p2_klamath.cc0000644000175000017500000001352312020641451016551 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p2_klamath.cc 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "p2_klamath.h" #if BX_CPU_LEVEL >= 6 #define LOG_THIS cpu-> void p2_klamath_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: default: get_std_cpuid_leaf_2(leaf); return; } } Bit64u p2_klamath_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT; } Bit32u p2_klamath_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | #if BX_PHY_ADDRESS_LONG BX_CPU_PSE36 | #endif BX_CPU_MTRR; } // leaf 0x00000000 // void p2_klamath_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x2; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void p2_klamath_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00000634; leaf->ebx = 0; leaf->ecx = 0; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] SSE: SSE Extensions // [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_MMX; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void p2_klamath_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x03020101; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x0c040843; } void p2_klamath_t::dump_cpuid(void) const { struct cpuid_function_t leaf; for (unsigned n=0; n<=0x2; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_p2_klamath_cpuid(BX_CPU_C *cpu) { return new p2_klamath_t(cpu); } #endif bochs-2.6/cpu/cpudb/corei7_sandy_bridge_2600K.h0000644000175000017500000000602112020641451021050 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei7_sandy_bridge_2600K.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_COREI7_SANDY_BRIDGE_2600K_CPUID_DEFINITIONS_H #define BX_COREI7_SANDY_BRIDGE_2600K_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 && BX_SUPPORT_AVX #include "cpu/cpuid.h" class corei7_sandy_bridge_2600k_t : public bx_cpuid_t { public: corei7_sandy_bridge_2600k_t(BX_CPU_C *cpu); virtual ~corei7_sandy_bridge_2600k_t() {} // return CPU name virtual const char *get_name(void) const { return "corei7_sandy_bridge_2600k"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; #if BX_SUPPORT_VMX >= 2 virtual Bit32u get_vmx_extensions_bitmask(void) const; #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_corei7_sandy_bridge_2600k_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 && BX_SUPPORT_AVX #endif bochs-2.6/cpu/cpudb/corei7_ivy_bridge_3770K.cc0000644000175000017500000006127212020641451020721 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei7_ivy_bridge_3770K.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "corei7_ivy_bridge_3770K.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 && BX_SUPPORT_AVX corei7_ivy_bridge_3770k_t::corei7_ivy_bridge_3770k_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Intel Core i7 Ivy Bridge configuration")); if (! BX_SUPPORT_AVX) BX_PANIC(("You must enable AVX for Intel Core i7 Ivy Bridge configuration")); if (BX_SUPPORT_VMX == 1) BX_INFO(("You must compile with --enable-vmx=2 for Intel Core i7 Ivy Bridge VMX configuration")); if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); BX_INFO(("WARNING: RDRAND is not implemented yet !")); } void corei7_ivy_bridge_3770k_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: get_std_cpuid_leaf_7(subfunction, leaf); return; case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: get_std_cpuid_leaf_A(leaf); return; case 0x0000000B: get_std_cpuid_extended_topology_leaf(subfunction, leaf); return; case 0x0000000C: get_reserved_leaf(leaf); return; case 0x0000000D: default: get_std_cpuid_xsave_leaf(subfunction, leaf); return; } } Bit64u corei7_ivy_bridge_3770k_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_SSSE3 | BX_ISA_SSE4_1 | BX_ISA_SSE4_2 | BX_ISA_POPCNT | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif #if BX_SUPPORT_VMX >= 2 BX_ISA_VMX | #endif /* BX_ISA_SMX | */ BX_ISA_RDTSCP | BX_ISA_XSAVE | BX_ISA_XSAVEOPT | BX_ISA_AES_PCLMULQDQ | BX_ISA_FSGSBASE | BX_ISA_AVX | BX_ISA_AVX_F16C | BX_ISA_CMPXCHG16B | BX_ISA_LM_LAHF_SAHF; } Bit32u corei7_ivy_bridge_3770k_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | /* BX_CPU_X2APIC | */ BX_CPU_LONG_MODE | BX_CPU_NX | BX_CPU_PCID | BX_CPU_SMEP | BX_CPU_TSC_DEADLINE; } #if BX_SUPPORT_VMX >= 2 // // MSR 00000480 : 00DA0400 00000010 BX_MSR_VMX_BASIC // MSR 00000481 : 0000007F 00000016 BX_MSR_VMX_PINBASED_CTRLS // MSR 00000482 : FFF9FFFE 0401E172 BX_MSR_VMX_PROCBASED_CTRLS // MSR 00000483 : 007FFFFF 00036DFF BX_MSR_VMX_VMEXIT_CTRLS // MSR 00000484 : 0000FFFF 000011FF BX_MSR_VMX_VMENTRY_CTRLS // MSR 00000485 : 00000000 100401E5 BX_MSR_VMX_MISC // MSR 00000486 : 00000000 80000021 BX_MSR_VMX_CR0_FIXED0 // MSR 00000487 : 00000000 FFFFFFFF BX_MSR_VMX_CR0_FIXED1 // MSR 00000488 : 00000000 00002000 BX_MSR_VMX_CR4_FIXED0 // MSR 00000489 : 00000000 001727FF BX_MSR_VMX_CR4_FIXED1 // MSR 0000048A : 00000000 0000002A BX_MSR_VMX_VMCS_ENUM // MSR 0000048B : 000000FF 00000000 BX_MSR_VMX_PROCBASED_CTRLS2 // MSR 0000048C : 00000F01 06114141 BX_MSR_VMX_MSR_VMX_EPT_VPID_CAP // MSR 0000048D : 0000007F 00000016 BX_MSR_VMX_TRUE_PINBASED_CTRLS // MSR 0000048E : FFF9FFFE 04006172 BX_MSR_VMX_TRUE_PROCBASED_CTRLS // MSR 0000048F : 007FFFFF 00036DFB BX_MSR_VMX_TRUE_VMEXIT_CTRLS // MSR 00000490 : 0000FFFF 000011FB BX_MSR_VMX_TRUE_VMENTRY_CTRLS // Bit32u corei7_ivy_bridge_3770k_t::get_vmx_extensions_bitmask(void) const { return BX_VMX_TPR_SHADOW | BX_VMX_VIRTUAL_NMI | BX_VMX_APIC_VIRTUALIZATION | BX_VMX_WBINVD_VMEXIT | /* BX_VMX_MONITOR_TRAP_FLAG | */ // not implemented yet BX_VMX_VPID | BX_VMX_EPT | BX_VMX_UNRESTRICTED_GUEST | BX_VMX_SAVE_DEBUGCTL_DISABLE | BX_VMX_PERF_GLOBAL_CTRL | // MSR not implemented yet BX_VMX_PAT | BX_VMX_EFER | BX_VMX_DESCRIPTOR_TABLE_EXIT | BX_VMX_X2APIC_VIRTUALIZATION | BX_VMX_PREEMPTION_TIMER; } #endif // leaf 0x00000000 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) leaf->eax = 0x2; else leaf->eax = 0xD; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x000306a9; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // * [1:1] PCLMULQDQ Instruction support // * [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // * [4:4] DS-CPL: CPL qualified debug store // * [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // * [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // * [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // * [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // * [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // * [19:19] SSE4.1 Instructions // * [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // * [23:23] POPCNT instruction // * [24:24] TSC Deadline // * [25:25] AES Instructions // * [26:26] XSAVE extensions support // * [27:27] OSXSAVE support // * [28:28] AVX extensions support // * [29:29] AVX F16C - Float16 conversion support // * [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_PCLMULQDQ | BX_CPUID_EXT_DTES64 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_DS_CPL | #if BX_SUPPORT_VMX >= 2 BX_CPUID_EXT_VMX | #endif /* BX_CPUID_EXT_SMX | */ BX_CPUID_EXT_EST | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_SSSE3 | BX_CPUID_EXT_CMPXCHG16B | BX_CPUID_EXT_xTPR | BX_CPUID_EXT_PDCM | BX_CPUID_EXT_PCID | BX_CPUID_EXT_SSE4_1 | BX_CPUID_EXT_SSE4_2 | /* BX_CPUID_EXT_X2APIC | */ BX_CPUID_EXT_POPCNT | BX_CPUID_EXT_TSC_DEADLINE | BX_CPUID_EXT_AES | BX_CPUID_EXT_XSAVE | BX_CPUID_EXT_AVX | BX_CPUID_EXT_AVX_F16C; // BX_CPUID_EXT_RDRAND not implemented yet if (cpu->cr4.get_OSXSAVE()) leaf->ecx |= BX_CPUID_EXT_OSXSAVE; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_THERMAL_MONITOR | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x76035A01; leaf->ebx = 0x00F0B2FF; leaf->ecx = 0x00000000; leaf->edx = 0x00CA0000; } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters // EAX: // [04-00] - Cache Type Field // 0 = No more caches // 1 = Data Cache // 2 = Instruction Cache // 3 = Unified Cache // [07-05] - Cache Level (starts at 1)] // [08] - Self Initializing cache level (doesn't need software initialization) // [09] - Fully Associative cache // [13-10] - Reserved // [25-14] - Maximum number of addressable IDs for logical processors sharing this cache // [31-26] - Maximum number of addressable IDs for processor cores in the physical package - 1 // EBX: // [11-00] - L = System Coherency Line Size // [21-12] - P = Physical Line partitions // [31-22] - W = Ways of associativity // ECX: Number of Sets // EDX: // [00] - Writeback invalidate // [01] - Cache Inclusiveness // [02] - Complex Cache Indexing // [31-03] - Reserved switch(subfunction) { case 0: leaf->eax = 0x1C004121; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000000; break; case 1: leaf->eax = 0x1C004122; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000000; break; case 2: leaf->eax = 0x1C004143; leaf->ebx = 0x01C0003F; leaf->ecx = 0x000001FF; leaf->edx = 0x00000000; break; case 3: leaf->eax = 0x1C03C163; leaf->ebx = 0x03C0003F; leaf->ecx = 0x00001FFF; leaf->edx = 0x00000006; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; } } // leaf 0x00000005 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x00001120; #else leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000006 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0x00000077; leaf->ebx = 0x00000002; leaf->ecx = 0x00000009; leaf->edx = 0x00000000; } // leaf 0x00000007 // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const { switch(subfunction) { case 0: leaf->eax = 0; /* report max sub-leaf that supported in leaf 7 */ // * [0:0] FS/GS BASE access instructions // [2:1] reserved // [3:3] BMI1: Advanced Bit Manipulation Extensions // [4:4] reserved // [5:5] AVX2 // [6:6] reserved // * [7:7] SMEP: Supervisor Mode Execution Protection // [8:8] BMI2: Advanced Bit Manipulation Extensions // * [9:9] Support for Enhanced REP MOVSB/STOSB // [10:10] Support for INVPCID instruction // [31:10] reserved leaf->ebx = BX_CPUID_EXT3_FSGSBASE | BX_CPUID_EXT3_SMEP | BX_CPUID_EXT3_ENCHANCED_REP_STRINGS; leaf->ecx = 0; leaf->edx = 0; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } } // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void corei7_ivy_bridge_3770k_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0x07300403; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x00000603; BX_INFO(("WARNING: Architectural Performance Monitoring is not implemented")); } BX_CPP_INLINE static Bit32u ilog2(Bit32u x) { Bit32u count = 0; while(x>>=1) count++; return count; } // leaf 0x0000000B // void corei7_ivy_bridge_3770k_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x0000000B - Extended Topology Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = subfunction; leaf->edx = cpu->get_apic_id(); #if BX_SUPPORT_SMP switch(subfunction) { case 0: if (nthreads > 1) { leaf->eax = ilog2(nthreads-1)+1; leaf->ebx = nthreads; leaf->ecx |= (1<<8); } else if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } else { leaf->eax = 1; leaf->ebx = 1; // number of logical CPUs at this level } break; case 1: if (nthreads > 1) { if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } else if (ncores > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; case 2: if (nthreads > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; default: break; } #endif } // leaf 0x0000000C reserved // // leaf 0x0000000D // void corei7_ivy_bridge_3770k_t::get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { switch(subfunction) { case 0: // EAX - valid bits of XCR0 (lower part) // EBX - Maximum size (in bytes) required by enabled features // ECX - Maximum size (in bytes) required by CPU supported features // EDX - valid bits of XCR0 (upper part) leaf->eax = cpu->xcr0_suppmask; leaf->ebx = 512+64; if (cpu->xcr0.get_AVX()) leaf->ebx += 256; leaf->ecx = 512+64+256 /* AVX */; leaf->edx = 0; return; case 1: leaf->eax = 1; /* XSAVEOPT supported */ leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; case 2: // AVX leaf leaf->eax = 256; leaf->ebx = 576; leaf->ecx = 0; leaf->edx = 0; return; default: break; } leaf->eax = 0; // reserved leaf->ebx = 0; // reserved leaf->ecx = 0; // reserved leaf->edx = 0; // reserved } // leaf 0x80000000 // void corei7_ivy_bridge_3770k_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void corei7_ivy_bridge_3770k_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // * [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // * [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // * [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD2_NX | BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE; if (cpu->long64_mode()) leaf->edx |= BX_CPUID_STD2_SYSCALL_SYSRET; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void corei7_ivy_bridge_3770k_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = " Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void corei7_ivy_bridge_3770k_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x01006040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void corei7_ivy_bridge_3770k_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x00000100; // bit 8 - invariant TSC } // leaf 0x80000008 // void corei7_ivy_bridge_3770k_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void corei7_ivy_bridge_3770k_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0xd; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_corei7_ivy_bridge_3770k_cpuid(BX_CPU_C *cpu) { return new corei7_ivy_bridge_3770k_t(cpu); } #endif bochs-2.6/cpu/cpudb/core2_penryn_t9600.cc0000644000175000017500000004740312020641451020002 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: core2_penryn_t9600.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "core2_penryn_t9600.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 core2_penryn_t9600_t::core2_penryn_t9600_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Intel Mobile Core2 Duo T9600 (Penryn) configuration")); if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void core2_penryn_t9600_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: get_std_cpuid_leaf_A(leaf); return; case 0x0000000B: case 0x0000000C: get_reserved_leaf(leaf); return; case 0x0000000D: default: get_std_cpuid_xsave_leaf(subfunction, leaf); return; } } Bit64u core2_penryn_t9600_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_SSSE3 | BX_ISA_SSE4_1 | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif #if BX_SUPPORT_VMX BX_ISA_VMX | #endif BX_ISA_SMX | BX_ISA_XSAVE | BX_ISA_CMPXCHG16B | BX_ISA_LM_LAHF_SAHF; } Bit32u core2_penryn_t9600_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX; } #if BX_SUPPORT_VMX // // MSR 00000480 : 005A0800 0000000D BX_MSR_VMX_BASIC // MSR 00000481 : 0000003F 00000016 BX_MSR_VMX_PINBASED_CTRLS // MSR 00000482 : F7F9FFFE 0401E172 BX_MSR_VMX_PROCBASED_CTRLS // MSR 00000483 : 0003FFFF 00036DFF BX_MSR_VMX_VMEXIT_CTRLS // MSR 00000484 : 00003FFF 000011FF BX_MSR_VMX_VMENTRY_CTRLS // MSR 00000485 : 00000000 000403C0 BX_MSR_VMX_MISC // MSR 00000486 : 00000000 80000021 BX_MSR_VMX_CR0_FIXED0 // MSR 00000487 : 00000000 FFFFFFFF BX_MSR_VMX_CR0_FIXED1 // MSR 00000488 : 00000000 00002000 BX_MSR_VMX_CR4_FIXED0 // MSR 00000489 : 00000000 000467FF BX_MSR_VMX_CR4_FIXED1 // MSR 0000048A : 00000000 0000002C BX_MSR_VMX_VMCS_ENUM // MSR 0000048B : 00000041 00000000 BX_MSR_VMX_PROCBASED_CTRLS2 // Bit32u core2_penryn_t9600_t::get_vmx_extensions_bitmask(void) const { return BX_VMX_TPR_SHADOW | BX_VMX_VIRTUAL_NMI | BX_VMX_PERF_GLOBAL_CTRL | /* not implemented */ BX_VMX_APIC_VIRTUALIZATION | BX_VMX_WBINVD_VMEXIT; } #endif // leaf 0x00000000 // void core2_penryn_t9600_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) leaf->eax = 0x2; else leaf->eax = 0xD; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void core2_penryn_t9600_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x0001067a; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // * [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // * [4:4] DS-CPL: CPL qualified debug store // * [5:5] VMX: Virtual Machine Technology // * [6:6] SMX: Secure Virtual Machine Technology // * [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // * [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // * [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // * [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // * [26:26] XSAVE extensions support // * [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_DTES64 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_DS_CPL | #if BX_SUPPORT_VMX BX_CPUID_EXT_VMX | #endif BX_CPUID_EXT_SMX | BX_CPUID_EXT_EST | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_SSSE3 | BX_CPUID_EXT_CMPXCHG16B | BX_CPUID_EXT_xTPR | BX_CPUID_EXT_PDCM | BX_CPUID_EXT_SSE4_1 | BX_CPUID_EXT_XSAVE; if (cpu->cr4.get_OSXSAVE()) leaf->ecx |= BX_CPUID_EXT_OSXSAVE; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_THERMAL_MONITOR | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void core2_penryn_t9600_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x05B0B101; leaf->ebx = 0x005657F0; leaf->ecx = 0x00000000; leaf->edx = 0x2CB4304E; } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void core2_penryn_t9600_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters // EAX: // [04-00] - Cache Type Field // 0 = No more caches // 1 = Data Cache // 2 = Instruction Cache // 3 = Unified Cache // [07-05] - Cache Level (starts at 1)] // [08] - Self Initializing cache level (doesn't need software initialization) // [09] - Fully Associative cache // [13-10] - Reserved // [25-14] - Maximum number of addressable IDs for logical processors sharing this cache // [31-26] - Maximum number of addressable IDs for processor cores in the physical package - 1 // EBX: // [11-00] - L = System Coherency Line Size // [21-12] - P = Physical Line partitions // [31-22] - W = Ways of associativity // ECX: Number of Sets // EDX: // [00] - Writeback invalidate // [01] - Cache Inclusiveness // [02] - Complex Cache Indexing // [31-03] - Reserved switch(subfunction) { case 0: leaf->eax = 0x04000121; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000001; break; case 1: leaf->eax = 0x04000122; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000001; break; case 2: leaf->eax = 0x04004143; leaf->ebx = 0x05C0003F; leaf->ecx = 0x00000FFF; leaf->edx = 0x00000001; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; } } // leaf 0x00000005 // void core2_penryn_t9600_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x03122220; #else leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000006 // void core2_penryn_t9600_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0x00000003; leaf->ebx = 0x00000002; leaf->ecx = 0x00000003; leaf->edx = 0x00000000; } // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void core2_penryn_t9600_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0x07280202; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x00000503; BX_INFO(("WARNING: Architectural Performance Monitoring is not implemented")); } // leaf 0x0000000B not supported // // leaf 0x0000000C reserved // // leaf 0x0000000D // void core2_penryn_t9600_t::get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { switch(subfunction) { case 0: // EAX - valid bits of XCR0 (lower part) // EBX - Maximum size (in bytes) required by enabled features // ECX - Maximum size (in bytes) required by CPU supported features // EDX - valid bits of XCR0 (upper part) leaf->eax = 3; leaf->ebx = 512+64; leaf->ecx = 512+64; leaf->edx = 0; return; default: break; } leaf->eax = 0; // reserved leaf->ebx = 0; // reserved leaf->ecx = 0; // reserved leaf->edx = 0; // reserved } // leaf 0x80000000 // void core2_penryn_t9600_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void core2_penryn_t9600_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // * [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // * [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD2_NX | BX_CPUID_STD2_LONG_MODE; if (cpu->long64_mode()) leaf->edx |= BX_CPUID_STD2_SYSCALL_SYSRET; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void core2_penryn_t9600_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "Intel(R) Core(TM)2 Duo CPU T9600 @ 2.80GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void core2_penryn_t9600_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x18008040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void core2_penryn_t9600_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x80000008 // void core2_penryn_t9600_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void core2_penryn_t9600_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0xd; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_core2_penryn_t9600_cpuid(BX_CPU_C *cpu) { return new core2_penryn_t9600_t(cpu); } #endif bochs-2.6/cpu/cpudb/p4_willamette.h0000644000175000017500000000433012020641451017137 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p4_willamette.h 10954 2012-01-07 17:06:03Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_P4_WMT_CPUID_DEFINITIONS_H #define BX_P4_WMT_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 6 #include "cpu/cpuid.h" class p4_willamette_t : public bx_cpuid_t { public: p4_willamette_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) {} virtual ~p4_willamette_t() {} // return CPU name virtual const char *get_name(void) const { return "p4_willamette"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_p4_willamette_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 6 #endif bochs-2.6/cpu/cpudb/p4_willamette.txt0000644000175000017500000000425512020641451017535 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.54 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 1 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 1 (max 1) Name Intel Pentium 4 Codename Willamette Specification Intel(R) Pentium(R) 4 CPU 1.80GHz Package (platform ID) Socket 478 mPGA (0x2) CPUID F.1.2 Extended CPUID F.1 Brand ID 8 Core Stepping D0 Technology 0.18 um Core Speed 1794.7 MHz Multiplier x FSB 18.0 x 99.7 MHz Rated Bus speed 398.8 MHz Stock frequency 1800 MHz Instructions sets MMX, SSE, SSE2 L1 Data cache 8 KBytes, 4-way set associative, 64-byte line size Trace cache 12 Kuops, 8-way set associative L2 cache 256 KBytes, 8-way set associative, 64-byte line size FID/VID Control no Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01001001h Max CPUID level 00000002h Max CPUID ext. level 80000004h Cache descriptor Level 2, U, 256 KB, 1 thread(s) Cache descriptor Level 1, T, 12 KB, 1 thread(s) Cache descriptor Level 1, D, 8 KB, 1 thread(s) CPUID 0x00000000 0x00000002 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00000F12 0x00010808 0x00000000 0x3FEBFBFF 0x00000002 0x665B5001 0x00000000 0x00000000 0x007A7040 0x80000000 0x80000004 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000000 0x00000000 0x80000002 0x20202020 0x20202020 0x20202020 0x6E492020 0x80000003 0x286C6574 0x50202952 0x69746E65 0x52286D75 0x80000004 0x20342029 0x20555043 0x30382E31 0x007A4847 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x00000017 0x00080000 0x00000000 MSR 0x0000002A 0x00000000 0x00004200 MSR 0x000001A0 0x00000000 0x00000089 bochs-2.6/cpu/cpudb/corei5_arrandale_m520.txt0000644000175000017500000003053212020641451020722 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.57.1 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 4 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Thread 1 1 -- Core 2 -- Thread 0 4 -- Thread 1 5 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 2 (max 8) Number of threads 4 (max 16) Name Intel Core i5 520M Codename Arrandale Specification Intel(R) Core(TM) i5 CPU M 520 @ 2.40GHz Package (platform ID) Socket 989 rPGA (0x4) CPUID 6.5.2 Extended CPUID 6.25 Core Stepping C2 Technology 32 nm Core Speed 1330.1 MHz Multiplier x FSB 10.0 x 133.0 MHz Rated Bus speed 2394.1 MHz Stock frequency 2400 MHz Instructions sets MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES L1 Data cache 2 x 32 KBytes, 8-way set associative, 64-byte line size L1 Instruction cache 2 x 32 KBytes, 4-way set associative, 64-byte line size L2 cache 2 x 256 KBytes, 8-way set associative, 64-byte line size L3 cache 3 MBytes, 12-way set associative, 64-byte line size FID/VID Control yes Turbo Mode supported, enabled Max turbo frequency 2933 MHz Max non-turbo ratio 18x Max turbo ratio 22x Max efficiency ratio 9x Max bus number 255 Attached device PCI device at bus 255, device 2, function 1 Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 3 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00020652 0x00100800 0x0298E3FF 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B2DD 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x02C0003F 0x00000FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000007 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000004 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000000 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x4D202020 0x80000004 0x30323520 0x20402020 0x30342E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x20011200 MSR 0x00000017 0x00100000 0x00000000 MSR 0x00000035 0x00000000 0x00020004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x00001416 MSR 0x00000194 0x00000000 0x00000000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x819080C8 MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x883E0100 MSR 0x000001A2 0x00000000 0x00690A00 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x0000000B MSR 0x00000199 0x00000000 0x00000009 CPU Thread 1 APIC ID 1 Topology Processor ID 0, Core ID 0, Thread ID 1 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 3 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00020652 0x01100800 0x0298E3FF 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B2DD 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x02C0003F 0x00000FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000007 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000004 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000001 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000001 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x4D202020 0x80000004 0x30323520 0x20402020 0x30342E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x20011200 MSR 0x00000017 0x00100000 0x00000000 MSR 0x00000035 0x00000000 0x00020004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x00001416 MSR 0x00000194 0x00000000 0x00000000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x819080CC MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x883D0100 MSR 0x000001A2 0x00000000 0x00690A00 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x0000000B MSR 0x00000199 0x00000000 0x00000009 CPU Thread 2 APIC ID 4 Topology Processor ID 0, Core ID 2, Thread ID 0 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 3 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00020652 0x04100800 0x0298E3FF 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B2DD 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x02C0003F 0x00000FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000007 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000004 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000004 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000004 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x4D202020 0x80000004 0x30323520 0x20402020 0x30342E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x20011200 MSR 0x00000017 0x00100000 0x00000000 MSR 0x00000035 0x00000000 0x00020004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x00001416 MSR 0x00000194 0x00000000 0x00000000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x819080CC MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x88420100 MSR 0x000001A2 0x00000000 0x00690A00 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x0000000B MSR 0x00000199 0x00000000 0x00000009 CPU Thread 3 APIC ID 5 Topology Processor ID 0, Core ID 2, Thread ID 1 Type 01020005h Max CPUID level 0000000Bh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 3 MB, 16 thread(s) CPUID 0x00000000 0x0000000B 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00020652 0x05100800 0x0298E3FF 0xBFEBFBFF 0x00000002 0x55035A01 0x00F0B2DD 0x00000000 0x09CA212C 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x00C0003F 0x0000007F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x02C0003F 0x00000FFF 0x00000002 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000007 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000004 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000005 0x0000000B 0x00000004 0x00000004 0x00000201 0x00000005 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x35692029 0x55504320 0x20202020 0x4D202020 0x80000004 0x30323520 0x20402020 0x30342E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00000900 0x20011200 MSR 0x00000017 0x00100000 0x00000000 MSR 0x00000035 0x00000000 0x00020004 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x00001416 MSR 0x00000194 0x00000000 0x00000000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001AC 0x00000000 0x819080CC MSR 0x000001FC 0x00000000 0x00000003 MSR 0x00000300 0x00000000 0xE0000001 MSR 0x0000019C 0x00000000 0x883E0100 MSR 0x000001A2 0x00000000 0x00690A00 MSR 0xC0000103 0x00000000 0x00000000 MSR 0x00000198 0x00000000 0x0000000B MSR 0x00000199 0x00000000 0x00000009 bochs-2.6/cpu/cpudb/athlon64_clawhammer.cc0000644000175000017500000003273312020641451020372 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: athlon64_clawhammer.cc 10920 2012-01-01 17:54:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "athlon64_clawhammer.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 athlon64_clawhammer_t::athlon64_clawhammer_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Athlon64 configuration")); BX_INFO(("WARNING: 3DNow! is not implemented yet !")); } void athlon64_clawhammer_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x8FFFFFFF: get_cpuid_hidden_level(leaf); return; case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_ext_cpuid_leaf_5(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; default: get_reserved_leaf(leaf); return; } } Bit64u athlon64_clawhammer_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_3DNOW | BX_ISA_SYSCALL_SYSRET_LEGACY | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_LM_LAHF_SAHF; } Bit32u athlon64_clawhammer_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX; } // leaf 0x00000000 // void athlon64_clawhammer_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x1; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void athlon64_clawhammer_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00000F48; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags leaf->ecx = 0; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000000 // void athlon64_clawhammer_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000018; memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000001 // void athlon64_clawhammer_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (same as 0x00000001.EAX) leaf->eax = 0x00000F48; // EBX: Brand ID leaf->ebx = 0x00000106; leaf->ecx = 0; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 for AMD // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSCALL/SYSRET support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] Reserved // [19:19] Reserved // * [20:20] No-Execute page protection // [21:21] Reserved // * [22:22] MMXExt: AMD Extensions to MMX Technology // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] FFXSR: Fast FXSAVE/FXRSTOR // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // * [30:30] AMD 3DNow! Extensions // * [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD2_SYSCALL_SYSRET | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD2_NX | BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD2_LONG_MODE | BX_CPUID_STD2_3DNOW_EXT | BX_CPUID_STD2_3DNOW; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void athlon64_clawhammer_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "AMD Athlon(tm) 64 Processor 2800+\0\0\0"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 // void athlon64_clawhammer_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x800000005 - L1 Cache and TLB Identifiers leaf->eax = 0xFF08FF08; leaf->ebx = 0xFF20FF20; leaf->ecx = 0x40020140; leaf->edx = 0x40020140; } // leaf 0x80000006 // void athlon64_clawhammer_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x42004200; leaf->ecx = 0x02008140; leaf->edx = 0x00000000; } // leaf 0x80000007 // void athlon64_clawhammer_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x0000000F; } // leaf 0x80000008 // void athlon64_clawhammer_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } // leaf 0x80000009 : Reserved // // leaf 0x8000000A : SVM // // leaf 0x8000000B - 0x80000018: Reserved // // leaf 0x8FFFFFFF // void athlon64_clawhammer_t::get_cpuid_hidden_level(cpuid_function_t *leaf) const { static const char* magic_string = "IT'S HAMMER TIME"; memcpy(&(leaf->eax), magic_string , 4); memcpy(&(leaf->ebx), magic_string + 4, 4); memcpy(&(leaf->ecx), magic_string + 8, 4); memcpy(&(leaf->edx), magic_string + 12, 4); #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } void athlon64_clawhammer_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=1; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000018; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } get_cpuid_leaf(0x8fffffff, 0x00000000, &leaf); BX_INFO(("CPUID[0x8fffffff]: %08x %08x %08x %08x", leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } bx_cpuid_t *create_athlon64_clawhammer_cpuid(BX_CPU_C *cpu) { return new athlon64_clawhammer_t(cpu); } #endif bochs-2.6/cpu/cpudb/turion64_tyler.h0000644000175000017500000000474012020641451017303 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: turion64_tyler.h 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_TURION64_TYLER_CPUID_DEFINITIONS_H #define BX_TURION64_TYLER_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class turion64_tyler_t : public bx_cpuid_t { public: turion64_tyler_t(BX_CPU_C *cpu); virtual ~turion64_tyler_t() {} // return CPU name virtual const char *get_name(void) const { return "turion64_tyler"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; #if BX_SUPPORT_SVM void get_ext_cpuid_leaf_A(cpuid_function_t *leaf) const; #endif }; extern bx_cpuid_t *create_turion64_tyler_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/athlon64_clawhammer.txt0000644000175000017500000000715012020641451020617 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.52.2 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 1 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 1 (max 1) Name AMD Athlon 64 2800+ Codename ClawHammer Specification AMD Athlon(tm) 64 Processor 2800+ Package Socket 754 CPUID F.4.8 Extended CPUID F.4 Brand ID 4 Core Stepping SH7-C0 Technology 0.13 um Core Speed 1808.9 MHz Multiplier x FSB 9.0 x 201.0 MHz HT Link speed 804.0 MHz Stock frequency 1800 MHz Instructions sets MMX (+), 3DNow! (+), SSE, SSE2, x86-64 L1 Data cache 64 KBytes, 2-way set associative, 64-byte line size L1 Instruction cache 64 KBytes, 2-way set associative, 64-byte line size L2 cache 512 KBytes, 16-way set associative, 64-byte line size FID/VID Control yes Max FID 9.0x K8 Thermal sensor yes K8 Revision ID 2.4 Attached device PCI device at bus 0, device 24, function 0 Attached device PCI device at bus 0, device 24, function 1 Attached device PCI device at bus 0, device 24, function 2 Attached device PCI device at bus 0, device 24, function 3 Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 02002001h Max CPUID level 00000001h Max CPUID ext. level 80000018h Cache descriptor Level 1, I, 64 KB, 1 thread(s) Cache descriptor Level 1, D, 64 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) CPUID 0x00000000 0x00000001 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00000F48 0x00000800 0x00000000 0x078BFBFF 0x80000000 0x80000018 0x68747541 0x444D4163 0x69746E65 0x80000001 0x00000F48 0x00000106 0x00000000 0xE1D3FBFF 0x80000002 0x20444D41 0x6C687441 0x74286E6F 0x3620296D 0x80000003 0x72502034 0x7365636F 0x20726F73 0x30303832 0x80000004 0x0000002B 0x00000000 0x00000000 0x00000000 0x80000005 0xFF08FF08 0xFF20FF20 0x40020140 0x40020140 0x80000006 0x00000000 0x42004200 0x02008140 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x0000000F 0x80000008 0x00003028 0x00000000 0x00000000 0x00000000 0x80000009 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000A 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000B 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000D 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000E 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000F 0x00000000 0x00000000 0x00000000 0x00000000 0x80000010 0x00000000 0x00000000 0x00000000 0x00000000 0x80000011 0x00000000 0x00000000 0x00000000 0x00000000 0x80000012 0x00000000 0x00000000 0x00000000 0x00000000 0x80000013 0x00000000 0x00000000 0x00000000 0x00000000 0x80000014 0x00000000 0x00000000 0x00000000 0x00000000 0x80000015 0x00000000 0x00000000 0x00000000 0x00000000 0x80000016 0x00000000 0x00000000 0x00000000 0x00000000 0x80000017 0x00000000 0x00000000 0x00000000 0x00000000 0x80000018 0x00000000 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0xC001001E 0x00000000 0x00000024 MSR 0xC0010015 0x00000000 0x0A000000 MSR 0xC0010042 0x00000202 0x000A0A0A MSR 0xC0010041 0x00000001 0x0000020A bochs-2.6/cpu/cpudb/corei7_ivy_bridge_3770K.txt0000644000175000017500000006333112020641451021151 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.60 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 8 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Thread 1 1 -- Core 1 -- Thread 0 2 -- Thread 1 3 -- Core 2 -- Thread 0 4 -- Thread 1 5 -- Core 3 -- Thread 0 6 -- Thread 1 7 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 4 (max 8) Number of threads 8 (max 16) Name Intel Core i7 3770K Codename Ivy Bridge Specification Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz Package (platform ID) Socket 1155 LGA (0x1) CPUID 6.A.9 Extended CPUID 6.3A Core Stepping Technology 22 nm TDP Limit 77 Watts Core Speed 1635.3 MHz Multiplier x FSB 16.0 x 102.2 MHz Stock frequency 3500 MHz Instructions sets MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, EM64T, VT-x, AES, AVX L1 Data cache 4 x 32 KBytes, 8-way set associative, 64-byte line size L1 Instruction cache 4 x 32 KBytes, 8-way set associative, 64-byte line size L2 cache 4 x 256 KBytes, 8-way set associative, 64-byte line size L3 cache 8 MBytes, 16-way set associative, 64-byte line size FID/VID Control yes Turbo Mode supported, enabled Max non-turbo ratio 35x Max turbo ratio 42x Max efficiency ratio 16x Min Power 60 Watts O/C bins unlimited Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x00100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000000 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000000 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x88490000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96F5A31F MSR 0x00000639 0x00000000 0x0C959E46 MSR 0x00000641 0x00000000 0x00075FC9 MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x884B0000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x00002578 0x00002A00 MSR 0x00000199 0x00000000 0x0000FF00 CPU Thread 1 APIC ID 1 Topology Processor ID 0, Core ID 0, Thread ID 1 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x01100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000001 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000001 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x884A0000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96F6FB06 MSR 0x00000639 0x00000000 0x0C95FCFD MSR 0x00000641 0x00000000 0x0007605F MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x884D0000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x0000254F 0x00002500 MSR 0x00000199 0x00000000 0x0000FF00 CPU Thread 2 APIC ID 2 Topology Processor ID 0, Core ID 1, Thread ID 0 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x02100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000002 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000002 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x884B0000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96F81804 MSR 0x00000639 0x00000000 0x0C9620C3 MSR 0x00000641 0x00000000 0x000760D2 MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x884C0000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x000024AB 0x00002A00 MSR 0x00000199 0x00000000 0x0000FF00 CPU Thread 3 APIC ID 3 Topology Processor ID 0, Core ID 1, Thread ID 1 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x03100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000003 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000003 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x884C0000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96F930C8 MSR 0x00000639 0x00000000 0x0C964038 MSR 0x00000641 0x00000000 0x00076174 MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x884C0000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x000024AB 0x00002A00 MSR 0x00000199 0x00000000 0x0000FF00 CPU Thread 4 APIC ID 4 Topology Processor ID 0, Core ID 2, Thread ID 0 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x04100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000004 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000004 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x88470000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96FA4695 MSR 0x00000639 0x00000000 0x0C965CBA MSR 0x00000641 0x00000000 0x000761E7 MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x88470000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x0000233A 0x00002500 MSR 0x00000199 0x00000000 0x0000FF00 CPU Thread 5 APIC ID 5 Topology Processor ID 0, Core ID 2, Thread ID 1 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x05100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000005 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000005 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x884B0000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96FB6402 MSR 0x00000639 0x00000000 0x0C967C4A MSR 0x00000641 0x00000000 0x0007625A MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x884B0000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x00002578 0x00002A00 MSR 0x00000199 0x00000000 0x0000FF00 CPU Thread 6 APIC ID 6 Topology Processor ID 0, Core ID 3, Thread ID 0 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x06100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000006 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000006 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x884B0000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96FCAB7F MSR 0x00000639 0x00000000 0x0C96C517 MSR 0x00000641 0x00000000 0x000762F8 MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x884B0000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x0000254F 0x00002500 MSR 0x00000199 0x00000000 0x0000FF00 CPU Thread 7 APIC ID 7 Topology Processor ID 0, Core ID 3, Thread ID 1 Type 01020101h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 256 KB, 2 thread(s) Cache descriptor Level 3, U, 8 MB, 16 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000306A9 0x07100800 0x7F9AE3BF 0xBFEBFBFF 0x00000002 0x76035A01 0x00F0B2FF 0x00000000 0x00CA0000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x1C004121 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004122 0x01C0003F 0x0000003F 0x00000000 0x00000004 0x1C004143 0x01C0003F 0x000001FF 0x00000000 0x00000004 0x1C03C163 0x03C0003F 0x00001FFF 0x00000006 0x00000005 0x00000040 0x00000040 0x00000003 0x00001120 0x00000006 0x00000077 0x00000002 0x00000009 0x00000000 0x00000007 0x00000000 0x00000281 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07300403 0x00000000 0x00000000 0x00000603 0x0000000B 0x00000001 0x00000002 0x00000100 0x00000007 0x0000000B 0x00000004 0x00000008 0x00000201 0x00000007 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000007 0x00000340 0x00000340 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x28100800 0x80000002 0x20202020 0x49202020 0x6C65746E 0x20295228 0x80000003 0x65726F43 0x294D5428 0x2D376920 0x30373733 0x80000004 0x5043204B 0x20402055 0x30352E33 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000100 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000005 MSR 0x000001A0 0x00000000 0x00850089 MSR 0x000000CE 0x00081010 0xF0012300 MSR 0x00000017 0x00040000 0x00000000 MSR 0x00000035 0x00000000 0x00040008 MSR 0x000000C1 0x00000000 0x00000000 MSR 0x000000C2 0x00000000 0x00000000 MSR 0x000000C3 0x00000000 0x00000000 MSR 0x000000C4 0x00000000 0x00000000 MSR 0x00000186 0x00000000 0x00000000 MSR 0x00000187 0x00000000 0x00000000 MSR 0x000001AD 0x00000000 0x252A2A2A MSR 0x00000194 0x00000000 0x000F0000 MSR 0x0000019A 0x00000000 0x00000000 MSR 0x000001A4 0x00000000 0x00000000 MSR 0x000001B1 0x00000000 0x884D0000 MSR 0x000001FC 0x00000000 0x0014005D MSR 0x00000601 0x18141494 0x80001FFF MSR 0x00000602 0x18141494 0x80001FFF MSR 0x00000606 0x00000000 0x000A1003 MSR 0x00000610 0x800087F8 0x001487F8 MSR 0x00000611 0x00000000 0x96FDC342 MSR 0x00000639 0x00000000 0x0C96E3AD MSR 0x00000641 0x00000000 0x0007636C MSR 0x00000614 0x00000000 0x01E00268 MSR 0x0000019C 0x00000000 0x884D0000 MSR 0x000001A2 0x00000000 0x00691400 MSR 0x00000198 0x000024AB 0x00002A00 MSR 0x00000199 0x00000000 0x0000FF00 bochs-2.6/cpu/cpudb/p4_prescott_celeron_336.cc0000644000175000017500000003332112020641451021075 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p4_prescott_celeron_336.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "p4_prescott_celeron_336.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 p4_prescott_celeron_336_t::p4_prescott_celeron_336_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for P4 (Prescott) configuration")); if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void p4_prescott_celeron_336_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: default: get_std_cpuid_leaf_3(leaf); return; } } Bit64u p4_prescott_celeron_336_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif BX_ISA_SSSE3 | BX_ISA_CMPXCHG16B; } Bit32u p4_prescott_celeron_336_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX; } // leaf 0x00000000 // void p4_prescott_celeron_336_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x3; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void p4_prescott_celeron_336_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00000F41; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // * [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // * [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // [9:9] SSSE3: SSSE3 Instructions // * [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_DTES64 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_DS_CPL | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_CNXT_ID | BX_CPUID_EXT_CMPXCHG16B | BX_CPUID_EXT_xTPR; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_THERMAL_MONITOR | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void p4_prescott_celeron_336_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x605B5101; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x003C7040; } // leaf 0x00000003 // void p4_prescott_celeron_336_t::get_std_cpuid_leaf_3(cpuid_function_t *leaf) const { // CPUID function 0x00000003 - Processor Serial Number leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x80000000 // void p4_prescott_celeron_336_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void p4_prescott_celeron_336_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = 0; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // ? [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // * [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD2_NX | BX_CPUID_STD2_LONG_MODE; if (cpu->long64_mode()) leaf->edx |= BX_CPUID_STD2_SYSCALL_SYSRET; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void p4_prescott_celeron_336_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = " Intel(R) Celeron(R) CPU 2.80GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void p4_prescott_celeron_336_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x01004040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void p4_prescott_celeron_336_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x80000008 // void p4_prescott_celeron_336_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void p4_prescott_celeron_336_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0x3; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_p4_prescott_celeron_336_cpuid(BX_CPU_C *cpu) { return new p4_prescott_celeron_336_t(cpu); } #endif bochs-2.6/cpu/cpudb/core_duo_t2400_yonah.h0000644000175000017500000000546112020641451020221 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: core_duo_t2400_yonah.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_CORE_DUO_T2400_YONAH_CPUID_DEFINITIONS_H #define BX_CORE_DUO_T2400_YONAH_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 6 #include "cpu/cpuid.h" class core_duo_t2400_yonah_t : public bx_cpuid_t { public: core_duo_t2400_yonah_t(BX_CPU_C *cpu); virtual ~core_duo_t2400_yonah_t() {} // return CPU name virtual const char *get_name(void) const { return "core_duo_t2400_yonah"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; #if BX_SUPPORT_VMX virtual Bit32u get_vmx_extensions_bitmask(void) const { return 0; } // only basic support #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_core_duo_t2400_yonah_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 6 #endif bochs-2.6/cpu/cpudb/pentium_mmx.txt0000644000175000017500000000263712020641451017327 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.53.1 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 1 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 1 (max 1) Name Intel Pentium MMX Codename P55 Specification Package Socket 7 (321) CPUID 5.4.3 Extended CPUID 5.4 Core Stepping MXB1 Technology 0.35 um Core Speed 167.1 MHz Instructions sets MMX L1 Data cache 16 KBytes, 4-way set associative, 32-byte line size L1 Instruction cache 16 KBytes, 4-way set associative, 32-byte line size FID/VID Control no Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01000402h Max CPUID level 00000001h Cache descriptor Level 1, I, 16 KB, 1 thread(s) Cache descriptor Level 1, D, 16 KB, 1 thread(s) CPUID 0x00000000 0x00000001 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00000543 0x00000000 0x00000000 0x008001BF bochs-2.6/cpu/cpudb/atom_n270.cc0000644000175000017500000004224412020641451016237 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: atom_n270.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "atom_n270.h" #define LOG_THIS cpu-> #if BX_CPU_LEVEL >= 6 atom_n270_t::atom_n270_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void atom_n270_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: default: get_std_cpuid_leaf_A(leaf); return; } } Bit64u atom_n270_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_SSSE3 | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif BX_ISA_MOVBE; } Bit32u atom_n270_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | #if BX_PHY_ADDRESS_LONG BX_CPU_PSE36 | #endif BX_CPU_PAE | BX_CPU_PGE | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC; } // leaf 0x00000000 // void atom_n270_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) leaf->eax = 0x2; else leaf->eax = 0xA; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void atom_n270_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x000106C2; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // * [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // * [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // * [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // * [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // * [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // * [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_DTES64 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_DS_CPL | BX_CPUID_EXT_EST | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_SSSE3 | BX_CPUID_EXT_xTPR | BX_CPUID_EXT_PDCM | BX_CPUID_EXT_MOVBE; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // - [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_THERMAL_MONITOR | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void atom_n270_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x4FBA5901; leaf->ebx = 0x0E3080C0; leaf->ecx = 0x00000000; leaf->edx = 0x00000000; } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void atom_n270_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters // EAX: // [04-00] - Cache Type Field // 0 = No more caches // 1 = Data Cache // 2 = Instruction Cache // 3 = Unified Cache // [07-05] - Cache Level (starts at 1)] // [08] - Self Initializing cache level (doesn't need software initialization) // [09] - Fully Associative cache // [13-10] - Reserved // [25-14] - Maximum number of addressable IDs for logical processors sharing this cache // [31-26] - Maximum number of addressable IDs for processor cores in the physical package - 1 // EBX: // [11-00] - L = System Coherency Line Size // [21-12] - P = Physical Line partitions // [31-22] - W = Ways of associativity // ECX: Number of Sets // EDX: // [00] - Writeback invalidate // [01] - Cache Inclusiveness // [02] - Complex Cache Indexing // [31-03] - Reserved switch(subfunction) { case 0: leaf->eax = 0x00004121; leaf->ebx = 0x0140003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000001; break; case 1: leaf->eax = 0x00004122; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000001; break; case 2: leaf->eax = 0x00004143; leaf->ebx = 0x01C0003F; leaf->ecx = 0x000003FF; leaf->edx = 0x00000001; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; } } // leaf 0x00000005 // void atom_n270_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x00020220; #else leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000006 // void atom_n270_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0x00000001; leaf->ebx = 0x00000002; leaf->ecx = 0x00000001; leaf->edx = 0x00000000; } // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void atom_n270_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0x07280203; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x00002501; BX_INFO(("WARNING: Architectural Performance Monitoring is not implemented")); } // leaf 0x80000000 // void atom_n270_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void atom_n270_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // ? [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = 0; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void atom_n270_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = " Intel(R) Atom(TM) CPU N270 @ 1.60GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void atom_n270_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x02008040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void atom_n270_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x80000008 // void atom_n270_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); // physical address should be 32-bit, no PSE-36 leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void atom_n270_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0xA; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_atom_n270_cpuid(BX_CPU_C *cpu) { return new atom_n270_t(cpu); } #endif bochs-2.6/cpu/cpudb/turion64_tyler.txt0000644000175000017500000001364612020641451017700 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.58 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 2 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Core 1 -- Thread 0 1 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 2 (max 2) Number of threads 2 (max 2) Name AMD Turion 64 X2 Mobile TL-60 Codename Tyler Specification AMD Turion(tm) 64 X2 Mobile Technology TL-60 Package Socket S1 (638) CPUID F.8.2 Extended CPUID F.68 Brand ID 2 Core Stepping Technology 65 nm Core Speed 2000.3 MHz Multiplier x FSB 10.0 x 200.0 MHz HT Link speed 800.1 MHz Stock frequency 2000 MHz Instructions sets MMX (+), 3DNow! (+), SSE, SSE2, SSE3, x86-64, AMD-V L1 Data cache 2 x 64 KBytes, 2-way set associative, 64-byte line size L1 Instruction cache 2 x 64 KBytes, 2-way set associative, 64-byte line size L2 cache 2 x 512 KBytes, 16-way set associative, 64-byte line size FID/VID Control yes Max FID 10.0x Max VID 1.175 V K8 Thermal sensor yes K8 Revision ID 6.0 Attached device PCI device at bus 0, device 24, function 0 Attached device PCI device at bus 0, device 24, function 1 Attached device PCI device at bus 0, device 24, function 2 Attached device PCI device at bus 0, device 24, function 3 Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 02002009h Max CPUID level 00000001h Max CPUID ext. level 80000018h Cache descriptor Level 1, I, 64 KB, 1 thread(s) Cache descriptor Level 1, D, 64 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) CPUID 0x00000000 0x00000001 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00060F82 0x00020800 0x00002001 0x178BFBFF 0x80000000 0x80000018 0x68747541 0x444D4163 0x69746E65 0x80000001 0x00060F82 0x0000059F 0x0000011F 0xEBD3FBFF 0x80000002 0x20444D41 0x69727554 0x74286E6F 0x3620296D 0x80000003 0x32582034 0x626F4D20 0x20656C69 0x68636554 0x80000004 0x6F6C6F6E 0x54207967 0x30362D4C 0x00000000 0x80000005 0xFF08FF08 0xFF20FF20 0x40020140 0x40020140 0x80000006 0x00000000 0x42004200 0x02008140 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x0000007F 0x80000008 0x00003028 0x00000000 0x00000001 0x00000000 0x80000009 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000A 0x00000001 0x00000040 0x00000000 0x00000002 0x8000000B 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000D 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000E 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000F 0x00000000 0x00000000 0x00000000 0x00000000 0x80000010 0x00000000 0x00000000 0x00000000 0x00000000 0x80000011 0x00000000 0x00000000 0x00000000 0x00000000 0x80000012 0x00000000 0x00000000 0x00000000 0x00000000 0x80000013 0x00000000 0x00000000 0x00000000 0x00000000 0x80000014 0x00000000 0x00000000 0x00000000 0x00000000 0x80000015 0x00000000 0x00000000 0x00000000 0x00000000 0x80000016 0x00000000 0x00000000 0x00000000 0x00000000 0x80000017 0x00000000 0x00000000 0x00000000 0x00000000 0x80000018 0x00000000 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0xC0010114 0x00000000 0x00000018 MSR 0xC001001E 0x00000000 0x00000060 MSR 0xC0010015 0x00000000 0x00000041 MSR 0xC0010042 0x320F1E1E 0x0F0C0000 MSR 0xC0010041 0x00000001 0x00001E00 CPU Thread 1 APIC ID 1 Topology Processor ID 0, Core ID 1, Thread ID 0 Type 02002009h Max CPUID level 00000001h Max CPUID ext. level 80000018h Cache descriptor Level 1, I, 64 KB, 1 thread(s) Cache descriptor Level 1, D, 64 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) CPUID 0x00000000 0x00000001 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00060F82 0x01020800 0x00002001 0x178BFBFF 0x80000000 0x80000018 0x68747541 0x444D4163 0x69746E65 0x80000001 0x00060F82 0x0000059F 0x0000011F 0xEBD3FBFF 0x80000002 0x20444D41 0x69727554 0x74286E6F 0x3620296D 0x80000003 0x32582034 0x626F4D20 0x20656C69 0x68636554 0x80000004 0x6F6C6F6E 0x54207967 0x30362D4C 0x00000000 0x80000005 0xFF08FF08 0xFF20FF20 0x40020140 0x40020140 0x80000006 0x00000000 0x42004200 0x02008140 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x0000007F 0x80000008 0x00003028 0x00000000 0x00000001 0x00000000 0x80000009 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000A 0x00000001 0x00000040 0x00000000 0x00000002 0x8000000B 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000D 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000E 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000F 0x00000000 0x00000000 0x00000000 0x00000000 0x80000010 0x00000000 0x00000000 0x00000000 0x00000000 0x80000011 0x00000000 0x00000000 0x00000000 0x00000000 0x80000012 0x00000000 0x00000000 0x00000000 0x00000000 0x80000013 0x00000000 0x00000000 0x00000000 0x00000000 0x80000014 0x00000000 0x00000000 0x00000000 0x00000000 0x80000015 0x00000000 0x00000000 0x00000000 0x00000000 0x80000016 0x00000000 0x00000000 0x00000000 0x00000000 0x80000017 0x00000000 0x00000000 0x00000000 0x00000000 0x80000018 0x00000000 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0xC0010114 0x00000000 0x00000018 MSR 0xC001001E 0x00000000 0x00000060 MSR 0xC0010015 0x00000000 0x00000041 MSR 0xC0010042 0x320F1E1E 0x0F0C0000 MSR 0xC0010041 0x00000001 0x00001E00 bochs-2.6/cpu/cpudb/p3_katmai.txt0000644000175000017500000000344412020641451016632 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.53.1 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 1 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 1 (max 1) Name Intel Pentium III Codename Katmai Specification Package (platform ID) Slot 1 SECC2 (0x0) CPUID 6.7.3 Extended CPUID 6.7 Core Stepping kC0 Technology 0.25 um Core Speed 597.0 MHz Multiplier x FSB 6.0 x 99.5 MHz Stock frequency 600 MHz Instructions sets MMX, SSE L1 Data cache 16 KBytes, 4-way set associative, 32-byte line size L1 Instruction cache 16 KBytes, 4-way set associative, 32-byte line size L2 cache 512 KBytes, 4-way set associative, 32-byte line size FID/VID Control no Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01000806h Max CPUID level 00000003h Cache descriptor Level 1, D, 16 KB, 1 thread(s) Cache descriptor Level 1, I, 16 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) CPUID 0x00000000 0x00000003 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00000673 0x00000000 0x00000000 0x0387F9FF 0x00000002 0x03020101 0x00000000 0x00000000 0x0C040843 0x00000003 0x00000000 0x00000000 0x11814197 0x0001C236 MSR 0x00000017 0x40210000 0x00000000 MSR 0x0000002A 0x00000000 0xC6C80000 bochs-2.6/cpu/cpudb/pentium_mmx.h0000644000175000017500000000375512020641451016741 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pentium_mmx.h 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_PENTIUM_MMX_CPUID_DEFINITIONS_H #define BX_PENTIUM_MMX_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 5 && BX_SUPPORT_X86_64 == 0 #include "cpu/cpuid.h" class pentium_mmx_t : public bx_cpuid_t { public: pentium_mmx_t(BX_CPU_C *cpu); virtual ~pentium_mmx_t() {} // return CPU name virtual const char *get_name(void) const { return "pentium_mmx"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_pentium_mmx_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 5 && BX_SUPPORT_X86_64 == 0 #endif bochs-2.6/cpu/cpudb/p4_prescott_celeron_336.txt0000644000175000017500000000471212020641451021331 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.53.1 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 1 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 1 (max 1) Name Intel Celeron 336 Codename Prescott Specification Intel(R) Celeron(R) CPU 2.80GHz Package (platform ID) Socket 775 LGA (0x4) CPUID F.4.1 Extended CPUID F.4 Core Stepping E0 Technology 90 nm Core Speed 2800.0 MHz Multiplier x FSB 21.0 x 133.3 MHz Rated Bus speed 533.3 MHz Stock frequency 2800 MHz Instructions sets MMX, SSE, SSE2, SSE3, EM64T L1 Data cache 16 KBytes, 8-way set associative, 64-byte line size Trace cache 12 Kuops, 8-way set associative L2 cache 256 KBytes, 4-way set associative, 64-byte line size FID/VID Control no Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01001006h Max CPUID level 00000003h Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 16 KB, 1 thread(s) Cache descriptor Level 2, U, 256 KB, 1 thread(s) Cache descriptor Level 1, T, 12 KB, 1 thread(s) CPUID 0x00000000 0x00000003 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x00000F41 0x00010800 0x0000651D 0xBFEBFBFF 0x00000002 0x605B5101 0x00000000 0x00000000 0x003C7040 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000000 0x20100000 0x80000002 0x20202020 0x20202020 0x20202020 0x20202020 0x80000003 0x65746E49 0x2952286C 0x6C654320 0x6E6F7265 0x80000004 0x20295228 0x20555043 0x30382E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x01004040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000000 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x000001A0 0x00000000 0x20C62089 MSR 0x00000017 0x00120000 0x00000000 MSR 0x0000002C 0x00000000 0x15110715 bochs-2.6/cpu/cpudb/core_duo_t2400_yonah.txt0000644000175000017500000001220512020641451020603 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.55 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 2 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Core 1 -- Thread 0 1 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 2 (max 2) Number of threads 2 (max 2) Name Intel Core Duo T2400 Codename Yonah Specification Intel(R) Core(TM) Duo CPU T2400 @ 1.83GHz Package (platform ID) Socket 479 mPGA (0x5) CPUID 6.E.C Extended CPUID 6.E Core Stepping D0 Technology 65 nm Core Speed 997.6 MHz Multiplier x FSB 6.0 x 166.3 MHz Rated Bus speed 665.1 MHz Stock frequency 1833 MHz Instructions sets MMX, SSE, SSE2, SSE3, VT-x L1 Data cache 2 x 32 KBytes, 8-way set associative, 64-byte line size L1 Instruction cache 2 x 32 KBytes, 8-way set associative, 64-byte line size L2 cache 2048 KBytes, 8-way set associative, 64-byte line size FID/VID Control yes FID range 6.0x - 11.0x Max VID 1.263 V Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01004002h Max CPUID level 0000000Ah Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 1 thread(s) Cache descriptor Level 1, I, 32 KB, 1 thread(s) Cache descriptor Level 2, U, 2 MB, 2 thread(s) CPUID 0x00000000 0x0000000A 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000006EC 0x00020800 0x0000C1A9 0xBFE9FBFF 0x00000002 0x02B3B001 0x000000F0 0x00000000 0x2C04307D 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x04000121 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04000122 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04004143 0x01C0003F 0x00000FFF 0x00000001 0x00000005 0x00000040 0x00000040 0x00000003 0x00022220 0x00000006 0x00000001 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07280201 0x00000000 0x00000000 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000000 0x00100000 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x75442029 0x5043206F 0x20202055 0x54202020 0x80000004 0x30303432 0x20402020 0x33382E31 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x08006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000000 0x80000008 0x00002020 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x0000003A 0x00000000 0x00000001 MSR 0x000001A0 0x00000003 0x64953488 MSR 0x00000017 0x00140000 0xD80485AC MSR 0x000000CD 0x00000000 0x00000133 MSR 0x0000019C 0x00000000 0x88320100 MSR 0x000000EE 0x00000000 0x82B90400 MSR 0x00000198 0x06130B2C 0x06000613 MSR 0x00000199 0x00000000 0x00000613 CPU Thread 1 APIC ID 1 Topology Processor ID 0, Core ID 1, Thread ID 0 Type 01004002h Max CPUID level 0000000Ah Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 1 thread(s) Cache descriptor Level 1, I, 32 KB, 1 thread(s) Cache descriptor Level 2, U, 2 MB, 2 thread(s) CPUID 0x00000000 0x0000000A 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000006EC 0x01020800 0x0000C1A9 0xBFE9FBFF 0x00000002 0x02B3B001 0x000000F0 0x00000000 0x2C04307D 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x04000121 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04000122 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04004143 0x01C0003F 0x00000FFF 0x00000001 0x00000005 0x00000040 0x00000040 0x00000003 0x00022220 0x00000006 0x00000001 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07280201 0x00000000 0x00000000 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000000 0x00100000 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x75442029 0x5043206F 0x20202055 0x54202020 0x80000004 0x30303432 0x20402020 0x33382E31 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x08006040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000000 0x80000008 0x00002020 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000001 MSR 0x000001A0 0x00000003 0x64953488 MSR 0x00000017 0x00140000 0xD80485AC MSR 0x000000CD 0x00000000 0x00000133 MSR 0x0000019C 0x00000000 0x88330100 MSR 0x000000EE 0x00000000 0x82B90400 MSR 0x00000198 0x06130B2C 0x06000613 MSR 0x00000199 0x00000000 0x00000613 bochs-2.6/cpu/cpudb/pentium_mmx.cc0000644000175000017500000001274212020641451017073 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pentium_mmx.cc 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "pentium_mmx.h" #if BX_CPU_LEVEL >= 5 && BX_SUPPORT_X86_64 == 0 #define LOG_THIS cpu-> pentium_mmx_t::pentium_mmx_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (BX_SUPPORT_X86_64) BX_PANIC(("x86-64 should be disabled for Pentium MMX configuration")); if (BX_CPU_LEVEL != 5) BX_PANIC(("Pentium MMX should be compiled with BX_CPU_LEVEL=5")); } void pentium_mmx_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: default: get_std_cpuid_leaf_1(leaf); return; } } Bit64u pentium_mmx_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_MMX; } Bit32u pentium_mmx_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | #if BX_PHY_ADDRESS_LONG BX_CPU_PSE36 | #endif BX_CPU_PSE; } // leaf 0x00000000 // void pentium_mmx_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x1; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void pentium_mmx_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00000543; leaf->ebx = 0; leaf->ecx = 0; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSENTER/SYSEXIT support // [12:12] MTRR: Memory Type Range Reg // [13:13] PGE/PTE Global Bit // [14:14] MCA: Machine Check Architecture // [15:15] CMOV: Cond Mov/Cmp Instructions // [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] SSE: SSE Extensions // [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | #if BX_PHY_ADDRESS_LONG BX_CPUID_STD_PSE36 | #endif BX_CPUID_STD_MMX; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } void pentium_mmx_t::dump_cpuid(void) const { struct cpuid_function_t leaf; for (unsigned n=0; n<=0x1; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_pentium_mmx_cpuid(BX_CPU_C *cpu) { return new pentium_mmx_t(cpu); } #endif bochs-2.6/cpu/cpudb/corei5_lynnfield_750.h0000644000175000017500000000556212020641451020222 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei5_lynnfield_750.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_COREI5_LYNNFIELD_750_CPUID_DEFINITIONS_H #define BX_COREI5_LYNNFIELD_750_CPUID_DEFINITIONS_H #if BX_SUPPORT_X86_64 #include "cpu/cpuid.h" class corei5_lynnfield_750_t : public bx_cpuid_t { public: corei5_lynnfield_750_t(BX_CPU_C *cpu); virtual ~corei5_lynnfield_750_t() {} // return CPU name virtual const char *get_name(void) const { return "corei5_lynnfield_750"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; #if BX_SUPPORT_VMX >= 2 virtual Bit32u get_vmx_extensions_bitmask(void) const; #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_corei5_lynnfield_750_cpuid(BX_CPU_C *cpu); #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/cpudb/phenomx3_8650_toliman.cc0000644000175000017500000004662112020641451020502 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: phenomx3_8650_toliman.cc 11049 2012-02-19 20:15:23Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "phenomx3_8650_toliman.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 phenom_8650_toliman_t::phenom_8650_toliman_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Phenom X3 8650 (Toliman) configuration")); BX_INFO(("WARNING: 3DNow! is not implemented yet !")); if (! BX_SUPPORT_MISALIGNED_SSE) BX_INFO(("WARNING: Misaligned SSE support is not compiled in !")); if (! BX_SUPPORT_SVM) BX_INFO(("WARNING: SVM support is not compiled in !")); if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void phenom_8650_toliman_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_ext_cpuid_leaf_5(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; #if BX_SUPPORT_SVM case 0x8000000A: get_ext_cpuid_leaf_A(leaf); return; #endif case 0x80000019: get_ext_cpuid_leaf_19(leaf); return; case 0x8000001A: get_ext_cpuid_leaf_1A(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; #if BX_SUPPORT_MONITOR_MWAIT case 0x00000005: get_std_cpuid_leaf_5(leaf); return; #endif default: get_reserved_leaf(leaf); return; } } Bit64u phenom_8650_toliman_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_3DNOW | BX_ISA_SYSCALL_SYSRET_LEGACY | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif BX_ISA_CMPXCHG16B | BX_ISA_POPCNT | BX_ISA_LZCNT | BX_ISA_SSE4A | BX_ISA_LM_LAHF_SAHF | #if BX_SUPPORT_SVM BX_ISA_SVM | #endif BX_ISA_RDTSCP; } Bit32u phenom_8650_toliman_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX | BX_CPU_FFXSR | BX_CPU_1G_PAGES | #if BX_SUPPORT_MISALIGNED_SSE BX_CPU_MISALIGNED_SSE | #endif BX_CPU_ALT_MOV_CR8 | BX_CPU_XAPIC_EXT; } #if BX_SUPPORT_SVM Bit32u phenom_8650_toliman_t::get_svm_extensions_bitmask(void) const { return BX_CPUID_SVM_NESTED_PAGING | BX_CPUID_SVM_LBR_VIRTUALIZATION | BX_CPUID_SVM_SVM_LOCK; } #endif // leaf 0x00000000 // void phenom_8650_toliman_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string #if BX_SUPPORT_MONITOR_MWAIT leaf->eax = 0x5; #else leaf->eax = 0x1; #endif // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void phenom_8650_toliman_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00100F23; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // [7:7] EST: Enhanced Intel SpeedStep Technology // [8:8] TM2: Thermal Monitor 2 // [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // [14:14] xTPR update control // [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // * [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_CMPXCHG16B | BX_CPUID_EXT_POPCNT; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // * [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_HT; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } #if BX_SUPPORT_MONITOR_MWAIT // leaf 0x00000005 // void phenom_8650_toliman_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0; } #endif // leaf 0x80000000 // void phenom_8650_toliman_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x8000001A; memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000001 // void phenom_8650_toliman_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (same as 0x00000001.EAX) leaf->eax = 0x00100F23; // EBX: Brand ID leaf->ebx = 0x10000563; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // * [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // * [2:2] SVM: Secure Virtual Machine (AMD) // * [3:3] Extended APIC Space // * [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // * [5:5] LZCNT: LZCNT instruction support // * [6:6] SSE4A: SSE4A Instructions support // * [7:7] Misaligned SSE support // * [8:8] PREFETCHW: PREFETCHW instruction support // * [9:9] OSVW: OS visible workarounds (AMD) // * [10:10] IBS: Instruction based sampling // [11:11] XOP: Extended Operations Support and XOP Prefix // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [14:14] Reserved // [15:15] LWP: Light weight profiling // [16:16] FMA4: Four-operand FMA instructions support // [17:17] Reserved // [18:18] Reserved // [19:19] Reserved // [20:20] NodeId: Indicates support for NodeId MSR (0xc001100c) // [21:21] Reserved // [22:22] TBM: trailing bit manipulation instructions support // [23:23] Topology extensions support // [31:24] Reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF | BX_CPUID_EXT2_CMP_LEGACY | #if BX_SUPPORT_SVM BX_CPUID_EXT2_SVM | #endif BX_CPUID_EXT2_EXT_APIC_SPACE | BX_CPUID_EXT2_ALT_MOV_CR8 | BX_CPUID_EXT2_LZCNT | BX_CPUID_EXT2_SSE4A | #if BX_SUPPORT_MISALIGNED_SSE BX_CPUID_EXT2_MISALIGNED_SSE | #endif BX_CPUID_EXT2_PREFETCHW | BX_CPUID_EXT2_OSVW | BX_CPUID_EXT2_IBS; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 for AMD // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSCALL/SYSRET support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] Reserved // [19:19] Reserved // * [20:20] No-Execute page protection // [21:21] Reserved // * [22:22] AMD MMX Extensions // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] Fast FXSAVE/FXRSTOR mode support // * [26:26] 1G paging support // * [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // * [30:30] AMD 3DNow! Extensions // * [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD2_SYSCALL_SYSRET | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD2_NX | BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD2_FFXSR | BX_CPUID_STD2_1G_PAGES | BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE | BX_CPUID_STD2_3DNOW_EXT | BX_CPUID_STD2_3DNOW; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void phenom_8650_toliman_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "AMD Phenom(tm) 8650 Triple-Core Processor\0\0\0"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); leaf->edx = 0; break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 // void phenom_8650_toliman_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x800000005 - L1 Cache and TLB Identifiers leaf->eax = 0xFF30FF10; leaf->ebx = 0xFF20FF20; leaf->ecx = 0x40020140; leaf->edx = 0x40020140; } // leaf 0x80000006 // void phenom_8650_toliman_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x20800000; leaf->ebx = 0x42004200; leaf->ecx = 0x02008140; leaf->edx = 0x0010A140; } // leaf 0x80000007 // void phenom_8650_toliman_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x000001F9; } // leaf 0x80000008 // void phenom_8650_toliman_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = ncores - 1; leaf->edx = 0; } // leaf 0x80000009 : Reserved // #if BX_SUPPORT_SVM // leaf 0x8000000A : SVM // void phenom_8650_toliman_t::get_ext_cpuid_leaf_A(cpuid_function_t *leaf) const { leaf->eax = 0x01; /* SVM revision ID */ leaf->ebx = 0x40; /* number of ASIDs */ leaf->ecx = 0; // * [0:0] NP - Nested paging support // * [1:1] LBR virtualization // * [2:2] SVM Lock // [3:3] NRIPS - Next RIP save on VMEXIT // [4:4] TscRate - MSR based TSC ratio control // [5:5] VMCB Clean bits support // [6:6] Flush by ASID support // [7:7] Decode assists support // [9:8] Reserved // [10:10] Pause filter support // [11:11] Reserved // [12:12] Pause filter threshold support // [31:13] Reserved leaf->edx = BX_CPUID_SVM_NESTED_PAGING | BX_CPUID_SVM_LBR_VIRTUALIZATION | BX_CPUID_SVM_SVM_LOCK; } #endif // leaf 0x8000000B - 0x80000018: Reserved // void phenom_8650_toliman_t::get_ext_cpuid_leaf_19(cpuid_function_t *leaf) const { // CPUID function 0x800000019 - 1G Page TLB Identifiers leaf->eax = 0xF0300000; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } void phenom_8650_toliman_t::get_ext_cpuid_leaf_1A(cpuid_function_t *leaf) const { // CPUID function 0x80000001A - Performance Optimization Identifiers leaf->eax = 0x00000003; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } void phenom_8650_toliman_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n <= (BX_SUPPORT_MONITOR_MWAIT ? 0x5 : 0x1); n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x8000001A; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_phenom_8650_toliman_cpuid(BX_CPU_C *cpu) { return new phenom_8650_toliman_t(cpu); } #endif bochs-2.6/cpu/cpudb/core2_penryn_t9600.txt0000644000175000017500000001316712020641451020234 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.58 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 2 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Core 1 -- Thread 0 1 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 2 (max 2) Number of threads 2 (max 2) Name Intel Mobile Core 2 Duo T9600 Codename Penryn Specification Intel(R) Core(TM)2 Duo CPU T9600 @ 2.80GHz Package (platform ID) Socket P (478) (0x7) CPUID 6.7.A Extended CPUID 6.17 Core Stepping E0 Technology 45 nm Core Speed 2792.9 MHz Multiplier x FSB 10.5 x 266.0 MHz Rated Bus speed 1064.0 MHz Stock frequency 2800 MHz Instructions sets MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, EM64T, VT-x L1 Data cache 2 x 32 KBytes, 8-way set associative, 64-byte line size L1 Instruction cache 2 x 32 KBytes, 8-way set associative, 64-byte line size L2 cache 6144 KBytes, 24-way set associative, 64-byte line size FID/VID Control yes FID range 6.0x - 10.5x Max VID 1.163 V Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01008001h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 1 thread(s) Cache descriptor Level 1, I, 32 KB, 1 thread(s) Cache descriptor Level 2, U, 6 MB, 2 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x0001067A 0x00020800 0x0C08E3FD 0xBFEBFBFF 0x00000002 0x05B0B101 0x005657F0 0x00000000 0x2CB4304E 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x04000121 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04000122 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04004143 0x05C0003F 0x00000FFF 0x00000001 0x00000005 0x00000040 0x00000040 0x00000003 0x03122220 0x00000006 0x00000003 0x00000002 0x00000003 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000400 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07280202 0x00000000 0x00000000 0x00000503 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000003 0x00000240 0x00000240 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x20000800 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x44203229 0x43206F75 0x20205550 0x54202020 0x80000004 0x30303639 0x20402020 0x30382E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x18008040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000000 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x0000003A 0x00000000 0x00000009 MSR 0x00000017 0x001C0000 0x98F4CA24 MSR 0x000000CD 0x00000000 0x000001E0 MSR 0x0000003F 0x00000000 0x00000000 MSR 0x000000CE 0x80170B2C 0x4345060F MSR 0x000001A0 0x00000017 0x64972488 MSR 0x000000EE 0x00000000 0x9EB91000 MSR 0x0000011E 0x00000000 0x74782111 MSR 0x0000019C 0x00000000 0x88420180 MSR 0x00000198 0x06170B2C 0x0600860F MSR 0x00000199 0x00000000 0x0000860F CPU Thread 1 APIC ID 1 Topology Processor ID 0, Core ID 1, Thread ID 0 Type 01008001h Max CPUID level 0000000Dh Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 32 KB, 1 thread(s) Cache descriptor Level 1, I, 32 KB, 1 thread(s) Cache descriptor Level 2, U, 6 MB, 2 thread(s) CPUID 0x00000000 0x0000000D 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x0001067A 0x01020800 0x0C08E3FD 0xBFEBFBFF 0x00000002 0x05B0B101 0x005657F0 0x00000000 0x2CB4304E 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x04000121 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04000122 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x04004143 0x05C0003F 0x00000FFF 0x00000001 0x00000005 0x00000040 0x00000040 0x00000003 0x03122220 0x00000006 0x00000003 0x00000002 0x00000003 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000400 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07280202 0x00000000 0x00000000 0x00000503 0x0000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000D 0x00000003 0x00000240 0x00000240 0x00000000 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x20000800 0x80000002 0x65746E49 0x2952286C 0x726F4320 0x4D542865 0x80000003 0x44203229 0x43206F75 0x20205550 0x54202020 0x80000004 0x30303639 0x20402020 0x30382E32 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x18008040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000000 0x80000008 0x00003024 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x0000003A 0x00000000 0x00000009 MSR 0x00000017 0x001C0000 0x98F4CA24 MSR 0x000000CD 0x00000000 0x000001E0 MSR 0x0000003F 0x00000000 0x00000000 MSR 0x000000CE 0x80170B2C 0x4345060F MSR 0x000001A0 0x00000017 0x64972488 MSR 0x000000EE 0x00000000 0x9EB91000 MSR 0x0000011E 0x00000000 0x74782111 MSR 0x0000019C 0x00000000 0x88440100 MSR 0x00000198 0x06174A24 0x0600860F MSR 0x00000199 0x00000000 0x0000860F bochs-2.6/cpu/cpudb/atom_n270.h0000644000175000017500000000514412020641451016077 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: atom_n270.h 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_ATOM_N270_CPUID_DEFINITIONS_H #define BX_ATOM_N270_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 6 #include "cpu/cpuid.h" class atom_n270_t : public bx_cpuid_t { public: atom_n270_t(BX_CPU_C *cpu); virtual ~atom_n270_t() {} // return CPU name virtual const char *get_name(void) const { return "atom_n270"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_atom_n270_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 6 #endif bochs-2.6/cpu/cpudb/corei7_sandy_bridge_2600K.cc0000644000175000017500000005710112020641451021213 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei7_sandy_bridge_2600K.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "corei7_sandy_bridge_2600K.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 && BX_SUPPORT_AVX corei7_sandy_bridge_2600k_t::corei7_sandy_bridge_2600k_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Intel Core i7 Sandy Bridge configuration")); if (! BX_SUPPORT_AVX) BX_PANIC(("You must enable AVX for Intel Core i7 Sandy Bridge configuration")); if (BX_SUPPORT_VMX == 1) BX_INFO(("You must compile with --enable-vmx=2 for Intel Core i7 Sandy Bridge VMX configuration")); if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void corei7_sandy_bridge_2600k_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: get_std_cpuid_leaf_A(leaf); return; case 0x0000000B: get_std_cpuid_extended_topology_leaf(subfunction, leaf); return; case 0x0000000C: get_reserved_leaf(leaf); return; case 0x0000000D: default: get_std_cpuid_xsave_leaf(subfunction, leaf); return; } } Bit64u corei7_sandy_bridge_2600k_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_SSSE3 | BX_ISA_SSE4_1 | BX_ISA_SSE4_2 | BX_ISA_POPCNT | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif #if BX_SUPPORT_VMX >= 2 BX_ISA_VMX | #endif /* BX_ISA_SMX | */ BX_ISA_RDTSCP | BX_ISA_XSAVE | BX_ISA_XSAVEOPT | BX_ISA_AES_PCLMULQDQ | BX_ISA_AVX | BX_ISA_CMPXCHG16B | BX_ISA_LM_LAHF_SAHF; } Bit32u corei7_sandy_bridge_2600k_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | /* BX_CPU_X2APIC | */ BX_CPU_LONG_MODE | BX_CPU_NX | BX_CPU_PCID | BX_CPU_TSC_DEADLINE; } #if BX_SUPPORT_VMX >= 2 // // MSR 00000480 : 00DA0400 00000010 BX_MSR_VMX_BASIC // MSR 00000481 : 0000007F 00000016 BX_MSR_VMX_PINBASED_CTRLS // MSR 00000482 : FFF9FFFE 0401E172 BX_MSR_VMX_PROCBASED_CTRLS // MSR 00000483 : 007FFFFF 00036DFF BX_MSR_VMX_VMEXIT_CTRLS // MSR 00000484 : 0000FFFF 000011FF BX_MSR_VMX_VMENTRY_CTRLS // MSR 00000485 : 00000000 100401E5 BX_MSR_VMX_MISC // MSR 00000486 : 00000000 80000021 BX_MSR_VMX_CR0_FIXED0 // MSR 00000487 : 00000000 FFFFFFFF BX_MSR_VMX_CR0_FIXED1 // MSR 00000488 : 00000000 00002000 BX_MSR_VMX_CR4_FIXED0 // MSR 00000489 : 00000000 000627FF BX_MSR_VMX_CR4_FIXED1 // MSR 0000048A : 00000000 0000002A BX_MSR_VMX_VMCS_ENUM // MSR 0000048B : 000000FF 00000000 BX_MSR_VMX_PROCBASED_CTRLS2 // MSR 0000048C : 00000F01 06114141 BX_MSR_VMX_MSR_VMX_EPT_VPID_CAP // MSR 0000048D : 0000007F 00000016 BX_MSR_VMX_TRUE_PINBASED_CTRLS // MSR 0000048E : FFF9FFFE 04006172 BX_MSR_VMX_TRUE_PROCBASED_CTRLS // MSR 0000048F : 007FFFFF 00036DFB BX_MSR_VMX_TRUE_VMEXIT_CTRLS // MSR 00000490 : 0000FFFF 000011FB BX_MSR_VMX_TRUE_VMENTRY_CTRLS // Bit32u corei7_sandy_bridge_2600k_t::get_vmx_extensions_bitmask(void) const { return BX_VMX_TPR_SHADOW | BX_VMX_VIRTUAL_NMI | BX_VMX_APIC_VIRTUALIZATION | BX_VMX_WBINVD_VMEXIT | /* BX_VMX_MONITOR_TRAP_FLAG | */ // not implemented yet BX_VMX_VPID | BX_VMX_EPT | BX_VMX_UNRESTRICTED_GUEST | BX_VMX_SAVE_DEBUGCTL_DISABLE | BX_VMX_PERF_GLOBAL_CTRL | // MSR not implemented yet BX_VMX_PAT | BX_VMX_EFER | BX_VMX_DESCRIPTOR_TABLE_EXIT | BX_VMX_X2APIC_VIRTUALIZATION | BX_VMX_PREEMPTION_TIMER; } #endif // leaf 0x00000000 // void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) leaf->eax = 0x2; else leaf->eax = 0xD; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x000206a7; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // * [1:1] PCLMULQDQ Instruction support // * [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // * [4:4] DS-CPL: CPL qualified debug store // * [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // * [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // * [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // * [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // * [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // * [19:19] SSE4.1 Instructions // * [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // * [23:23] POPCNT instruction // * [24:24] TSC Deadline // * [25:25] AES Instructions // * [26:26] XSAVE extensions support // * [27:27] OSXSAVE support // * [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_PCLMULQDQ | BX_CPUID_EXT_DTES64 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_DS_CPL | #if BX_SUPPORT_VMX >= 2 BX_CPUID_EXT_VMX | #endif /* BX_CPUID_EXT_SMX | */ BX_CPUID_EXT_EST | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_SSSE3 | BX_CPUID_EXT_CMPXCHG16B | BX_CPUID_EXT_xTPR | BX_CPUID_EXT_PDCM | BX_CPUID_EXT_PCID | BX_CPUID_EXT_SSE4_1 | BX_CPUID_EXT_SSE4_2 | /* BX_CPUID_EXT_X2APIC | */ BX_CPUID_EXT_POPCNT | BX_CPUID_EXT_TSC_DEADLINE | BX_CPUID_EXT_AES | BX_CPUID_EXT_XSAVE | BX_CPUID_EXT_AVX; if (cpu->cr4.get_OSXSAVE()) leaf->ecx |= BX_CPUID_EXT_OSXSAVE; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_THERMAL_MONITOR | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x76035A01; leaf->ebx = 0x00F0B0FF; leaf->ecx = 0x00000000; leaf->edx = 0x00CA0000; } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters // EAX: // [04-00] - Cache Type Field // 0 = No more caches // 1 = Data Cache // 2 = Instruction Cache // 3 = Unified Cache // [07-05] - Cache Level (starts at 1)] // [08] - Self Initializing cache level (doesn't need software initialization) // [09] - Fully Associative cache // [13-10] - Reserved // [25-14] - Maximum number of addressable IDs for logical processors sharing this cache // [31-26] - Maximum number of addressable IDs for processor cores in the physical package - 1 // EBX: // [11-00] - L = System Coherency Line Size // [21-12] - P = Physical Line partitions // [31-22] - W = Ways of associativity // ECX: Number of Sets // EDX: // [00] - Writeback invalidate // [01] - Cache Inclusiveness // [02] - Complex Cache Indexing // [31-03] - Reserved switch(subfunction) { case 0: leaf->eax = 0x1C004121; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000000; break; case 1: leaf->eax = 0x1C004122; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000000; break; case 2: leaf->eax = 0x1C004143; leaf->ebx = 0x01C0003F; leaf->ecx = 0x000001FF; leaf->edx = 0x00000000; break; case 3: leaf->eax = 0x1C03C163; leaf->ebx = 0x03C0003F; leaf->ecx = 0x00001FFF; leaf->edx = 0x00000006; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; } } // leaf 0x00000005 // void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x00001120; #else leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000006 // void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0x00000077; leaf->ebx = 0x00000002; leaf->ecx = 0x0000000B; leaf->edx = 0x00000000; } // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void corei7_sandy_bridge_2600k_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0x07300803; leaf->ebx = 0x00000000; leaf->ecx = 0x00000000; leaf->edx = 0x00000603; BX_INFO(("WARNING: Architectural Performance Monitoring is not implemented")); } BX_CPP_INLINE static Bit32u ilog2(Bit32u x) { Bit32u count = 0; while(x>>=1) count++; return count; } // leaf 0x0000000B // void corei7_sandy_bridge_2600k_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x0000000B - Extended Topology Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = subfunction; leaf->edx = cpu->get_apic_id(); #if BX_SUPPORT_SMP switch(subfunction) { case 0: if (nthreads > 1) { leaf->eax = ilog2(nthreads-1)+1; leaf->ebx = nthreads; leaf->ecx |= (1<<8); } else if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } else { leaf->eax = 1; leaf->ebx = 1; // number of logical CPUs at this level } break; case 1: if (nthreads > 1) { if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } else if (ncores > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; case 2: if (nthreads > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; default: break; } #endif } // leaf 0x0000000C reserved // // leaf 0x0000000D // void corei7_sandy_bridge_2600k_t::get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { switch(subfunction) { case 0: // EAX - valid bits of XCR0 (lower part) // EBX - Maximum size (in bytes) required by enabled features // ECX - Maximum size (in bytes) required by CPU supported features // EDX - valid bits of XCR0 (upper part) leaf->eax = cpu->xcr0_suppmask; leaf->ebx = 512+64; if (cpu->xcr0.get_AVX()) leaf->ebx += 256; leaf->ecx = 512+64+256 /* AVX */; leaf->edx = 0; return; case 1: leaf->eax = 1; /* XSAVEOPT supported */ leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; case 2: // AVX leaf leaf->eax = 256; leaf->ebx = 576; leaf->ecx = 0; leaf->edx = 0; return; default: break; } leaf->eax = 0; // reserved leaf->ebx = 0; // reserved leaf->ecx = 0; // reserved leaf->edx = 0; // reserved } // leaf 0x80000000 // void corei7_sandy_bridge_2600k_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void corei7_sandy_bridge_2600k_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // * [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // * [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // * [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD2_NX | BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE; if (cpu->long64_mode()) leaf->edx |= BX_CPUID_STD2_SYSCALL_SYSRET; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void corei7_sandy_bridge_2600k_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = " Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void corei7_sandy_bridge_2600k_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x01006040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void corei7_sandy_bridge_2600k_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x00000100; // bit 8 - invariant TSC } // leaf 0x80000008 // void corei7_sandy_bridge_2600k_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void corei7_sandy_bridge_2600k_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0xd; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_corei7_sandy_bridge_2600k_cpuid(BX_CPU_C *cpu) { return new corei7_sandy_bridge_2600k_t(cpu); } #endif bochs-2.6/cpu/cpudb/athlon64_venice.cc0000644000175000017500000003653612020641451017530 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: athlon64_venice.cc 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "athlon64_venice.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 athlon64_venice_t::athlon64_venice_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Athlon64 configuration")); BX_INFO(("WARNING: 3DNow! is not implemented yet !")); } void athlon64_venice_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x8FFFFFFF: get_cpuid_hidden_level(leaf); return; case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_ext_cpuid_leaf_5(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; default: get_reserved_leaf(leaf); return; } } Bit64u athlon64_venice_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_3DNOW | BX_ISA_SYSCALL_SYSRET_LEGACY | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_LM_LAHF_SAHF; } Bit32u athlon64_venice_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX | BX_CPU_FFXSR; } // leaf 0x00000000 // void athlon64_venice_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x1; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void athlon64_venice_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00020FF2; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // [2:2] DTES64: 64-bit DS area // [3:3] MONITOR/MWAIT support // [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // [7:7] EST: Enhanced Intel SpeedStep Technology // [8:8] TM2: Thermal Monitor 2 // [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // [13:13] CMPXCHG16B: CMPXCHG16B instruction support // [14:14] xTPR update control // [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000000 // void athlon64_venice_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000018; memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000001 // void athlon64_venice_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (same as 0x00000001.EAX) leaf->eax = 0x00020FF2; // EBX: Brand ID leaf->ebx = 0x00000108; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 for AMD // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSCALL/SYSRET support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] Reserved // [19:19] Reserved // * [20:20] No-Execute page protection // [21:21] Reserved // * [22:22] AMD MMX Extensions // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] Fast FXSAVE/FXRSTOR mode support // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // * [30:30] AMD 3DNow! Extensions // * [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD2_SYSCALL_SYSRET | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD2_NX | BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD2_FFXSR | BX_CPUID_STD2_LONG_MODE | BX_CPUID_STD2_3DNOW_EXT | BX_CPUID_STD2_3DNOW; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void athlon64_venice_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "AMD Athlon(tm) 64 Processor 3000+\0\0\0"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 // void athlon64_venice_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x800000005 - L1 Cache and TLB Identifiers leaf->eax = 0xFF08FF08; leaf->ebx = 0xFF20FF20; leaf->ecx = 0x40020140; leaf->edx = 0x40020140; } // leaf 0x80000006 // void athlon64_venice_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x42004200; leaf->ecx = 0x02008140; leaf->edx = 0x00000000; } // leaf 0x80000007 // void athlon64_venice_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x0000003F; } // leaf 0x80000008 // void athlon64_venice_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } // leaf 0x80000009 : Reserved // // leaf 0x8000000A : SVM // // leaf 0x8000000B - 0x80000018: Reserved // // leaf 0x8FFFFFFF // void athlon64_venice_t::get_cpuid_hidden_level(cpuid_function_t *leaf) const { static const char* magic_string = "IT'S HAMMER TIME"; memcpy(&(leaf->eax), magic_string , 4); memcpy(&(leaf->ebx), magic_string + 4, 4); memcpy(&(leaf->ecx), magic_string + 8, 4); memcpy(&(leaf->edx), magic_string + 12, 4); #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } void athlon64_venice_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=1; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000018; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } get_cpuid_leaf(0x8fffffff, 0x00000000, &leaf); BX_INFO(("CPUID[0x8fffffff]: %08x %08x %08x %08x", leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } bx_cpuid_t *create_athlon64_venice_cpuid(BX_CPU_C *cpu) { return new athlon64_venice_t(cpu); } #endif bochs-2.6/cpu/cpudb/p3_katmai.h0000644000175000017500000000406212020641451016237 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: p3_katmai.h 10688 2011-09-25 17:36:20Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_P3_KATMAI_CPUID_DEFINITIONS_H #define BX_P3_KATMAI_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 6 #include "cpu/cpuid.h" class p3_katmai_t : public bx_cpuid_t { public: p3_katmai_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) {} virtual ~p3_katmai_t() {} // return CPU name virtual const char *get_name(void) const { return "p3_katmai"; } virtual Bit64u get_isa_extensions_bitmask(void) const; virtual Bit32u get_cpu_extensions_bitmask(void) const; virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_3(cpuid_function_t *leaf) const; }; extern bx_cpuid_t *create_p3_katmai_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 6 #endif bochs-2.6/cpu/cpudb/atom_n270.txt0000644000175000017500000001241512020641451016466 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.56 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 2 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Thread 1 1 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 1 (max 1) Number of threads 2 (max 2) Name Intel Atom N270 Codename Diamondville Specification Intel(R) Atom(TM) CPU N270 @ 1.60GHz Package (platform ID) Socket 437 FCBGA8 (0x2) CPUID 6.C.2 Extended CPUID 6.1C Core Stepping C0 Technology 45 nm Core Speed 798.1 MHz Multiplier x FSB 6.0 x 133.0 MHz Rated Bus speed 532.1 MHz Stock frequency 1600 MHz Instructions sets MMX, SSE, SSE2, SSE3, SSSE3 L1 Data cache 24 KBytes, 6-way set associative, 64-byte line size L1 Instruction cache 32 KBytes, 8-way set associative, 64-byte line size L2 cache 512 KBytes, 8-way set associative, 64-byte line size FID/VID Control yes FID range 6.0x - 12.0x Max VID 1.113 V Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 01010001h Max CPUID level 0000000Ah Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 24 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 512 KB, 2 thread(s) CPUID 0x00000000 0x0000000A 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000106C2 0x00020800 0x0040C39D 0xBFE9FBFF 0x00000002 0x4FBA5901 0x0E3080C0 0x00000000 0x00000000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x00004121 0x0140003F 0x0000003F 0x00000001 0x00000004 0x00004122 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x00004143 0x01C0003F 0x000003FF 0x00000001 0x00000005 0x00000040 0x00000040 0x00000003 0x00020220 0x00000006 0x00000001 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07280203 0x00000000 0x00000000 0x00002501 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x00000000 0x80000002 0x20202020 0x20202020 0x746E4920 0x52286C65 0x80000003 0x74412029 0x54286D6F 0x4320294D 0x4E205550 0x80000004 0x20303732 0x20402020 0x30362E31 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x02008040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000000 0x80000008 0x00002020 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0x00000017 0x00080000 0x9024AC20 MSR 0x000000CD 0x00000000 0x00000111 MSR 0x0000003F 0x00000000 0x00000000 MSR 0x000000CE 0x200F0C00 0x4B4B0000 MSR 0x000001A0 0x00000007 0x64950480 MSR 0x000000EE 0x00000000 0x02F90002 MSR 0x0000011E 0x00000000 0x7E00011F MSR 0x0000019C 0x00000000 0x88380000 MSR 0x00000198 0x060F0C20 0x06000C20 MSR 0x00000199 0x00000000 0x00000C20 CPU Thread 1 APIC ID 1 Topology Processor ID 0, Core ID 0, Thread ID 1 Type 01010001h Max CPUID level 0000000Ah Max CPUID ext. level 80000008h Cache descriptor Level 1, D, 24 KB, 2 thread(s) Cache descriptor Level 1, I, 32 KB, 2 thread(s) Cache descriptor Level 2, U, 512 KB, 2 thread(s) CPUID 0x00000000 0x0000000A 0x756E6547 0x6C65746E 0x49656E69 0x00000001 0x000106C2 0x01020800 0x0040C39D 0xBFE9FBFF 0x00000002 0x4FBA5901 0x0E3080C0 0x00000000 0x00000000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x00004121 0x0140003F 0x0000003F 0x00000001 0x00000004 0x00004122 0x01C0003F 0x0000003F 0x00000001 0x00000004 0x00004143 0x01C0003F 0x000003FF 0x00000001 0x00000005 0x00000040 0x00000040 0x00000003 0x00020220 0x00000006 0x00000001 0x00000002 0x00000001 0x00000000 0x00000007 0x00000000 0x00000000 0x00000000 0x00000000 0x00000008 0x00000000 0x00000000 0x00000000 0x00000000 0x00000009 0x00000000 0x00000000 0x00000000 0x00000000 0x0000000A 0x07280203 0x00000000 0x00000000 0x00002501 0x80000000 0x80000008 0x00000000 0x00000000 0x00000000 0x80000001 0x00000000 0x00000000 0x00000001 0x00000000 0x80000002 0x20202020 0x20202020 0x746E4920 0x52286C65 0x80000003 0x74412029 0x54286D6F 0x4320294D 0x4E205550 0x80000004 0x20303732 0x20402020 0x30362E31 0x007A4847 0x80000005 0x00000000 0x00000000 0x00000000 0x00000000 0x80000006 0x00000000 0x00000000 0x02008040 0x00000000 0x80000007 0x00000000 0x00000000 0x00000000 0x00000000 0x80000008 0x00002020 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0x00000017 0x00080000 0x9024AC20 MSR 0x000000CD 0x00000000 0x00000111 MSR 0x0000003F 0x00000000 0x00000000 MSR 0x000000CE 0x200F0C00 0x4B4B0000 MSR 0x000001A0 0x00000007 0x64950480 MSR 0x000000EE 0x00000000 0x02F90002 MSR 0x0000011E 0x00000000 0x7E00011F MSR 0x0000019C 0x00000000 0x88370000 MSR 0x00000198 0x060F0C20 0x06000C20 MSR 0x00000199 0x00000000 0x00000C20 bochs-2.6/cpu/cpudb/phenomx3_8650_toliman.txt0000644000175000017500000002507012020641451020727 0ustar guillemguillemCPU-Z TXT Report ------------------------------------------------------------------------- Binaries ------------------------------------------------------------------------- CPU-Z version 1.56 Processors ------------------------------------------------------------------------- Number of processors 1 Number of threads 3 APICs ------------------------------------------------------------------------- Processor 0 -- Core 0 -- Thread 0 0 -- Core 1 -- Thread 0 1 -- Core 2 -- Thread 0 2 Processors Information ------------------------------------------------------------------------- Processor 1 ID = 0 Number of cores 3 (max 3) Number of threads 3 (max 3) Name AMD Phenom X3 8650 Codename Toliman Specification AMD Phenom(tm) 8650 Triple-Core Processor Package Socket AM2+ (940) CPUID F.2.3 Extended CPUID 10.2 Brand ID 2 Core Stepping DR-B3 Technology 65 nm Core Speed 2310.4 MHz Multiplier x FSB 11.5 x 200.9 MHz HT Link speed 1004.5 MHz Stock frequency 2300 MHz Instructions sets MMX (+), 3DNow! (+), SSE, SSE2, SSE3, SSE4A, x86-64, AMD-V L1 Data cache 3 x 64 KBytes, 2-way set associative, 64-byte line size L1 Instruction cache 3 x 64 KBytes, 2-way set associative, 64-byte line size L2 cache 3 x 512 KBytes, 16-way set associative, 64-byte line size L3 cache 2 MBytes, 32-way set associative, 64-byte line size FID/VID Control yes FID range 5.8x - 11.5x Max VID 1.250 V P-State FID 0x7 - VID 0x18 - IDD 25 (11.5x - 1.250 V) P-State FID 0x107 - VID 0x28 - IDD 19 (5.8x - 1.050 V) Package Type 0x1 Model 86 String 1 0x0 String 2 0x3 Page 0x0 CmpCap 3 TDP Limit 97 Watts TDC Limit 75 Amps Attached device PCI device at bus 0, device 24, function 0 Attached device PCI device at bus 0, device 24, function 1 Attached device PCI device at bus 0, device 24, function 2 Attached device PCI device at bus 0, device 24, function 3 Attached device PCI device at bus 0, device 24, function 4 Thread dumps ------------------------------------------------------------------------- CPU Thread 0 APIC ID 0 Topology Processor ID 0, Core ID 0, Thread ID 0 Type 02004002h Max CPUID level 00000005h Max CPUID ext. level 8000001Ah Cache descriptor Level 1, I, 64 KB, 1 thread(s) Cache descriptor Level 1, D, 64 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) Cache descriptor Level 3, U, 2 MB, 3 thread(s) CPUID 0x00000000 0x00000005 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00100F23 0x00030800 0x00802009 0x178BFBFF 0x00000002 0x00000000 0x00000000 0x00000000 0x00000000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x00000000 0x00000000 0x00000000 0x00000000 0x00000005 0x00000040 0x00000040 0x00000003 0x00000000 0x80000000 0x8000001A 0x68747541 0x444D4163 0x69746E65 0x80000001 0x00100F23 0x10000563 0x000007FF 0xEFD3FBFF 0x80000002 0x20444D41 0x6E656850 0x74286D6F 0x3820296D 0x80000003 0x20303536 0x70697254 0x432D656C 0x2065726F 0x80000004 0x636F7250 0x6F737365 0x00000072 0x00000000 0x80000005 0xFF30FF10 0xFF30FF20 0x40020140 0x40020140 0x80000006 0x20800000 0x42004200 0x02008140 0x0010A140 0x80000007 0x00000000 0x00000000 0x00000000 0x000001F9 0x80000008 0x00003030 0x00000000 0x00002002 0x00000000 0x80000009 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000A 0x00000001 0x00000040 0x00000000 0x00000007 0x8000000B 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000D 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000E 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000F 0x00000000 0x00000000 0x00000000 0x00000000 0x80000010 0x00000000 0x00000000 0x00000000 0x00000000 0x80000011 0x00000000 0x00000000 0x00000000 0x00000000 0x80000012 0x00000000 0x00000000 0x00000000 0x00000000 0x80000013 0x00000000 0x00000000 0x00000000 0x00000000 0x80000014 0x00000000 0x00000000 0x00000000 0x00000000 0x80000015 0x00000000 0x00000000 0x00000000 0x00000000 0x80000016 0x00000000 0x00000000 0x00000000 0x00000000 0x80000017 0x00000000 0x00000000 0x00000000 0x00000000 0x80000018 0x00000000 0x00000000 0x00000000 0x00000000 0x80000019 0xF0300000 0x00000000 0x00000000 0x00000000 0x8000001A 0x00000003 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00900 MSR 0xC0010114 0x00000000 0x00000018 MSR 0xC0010061 0x00000000 0x00000010 MSR 0xC0010062 0x00000000 0x00000000 MSR 0xC0010063 0x00000000 0x00000000 MSR 0xC0010064 0x800001F5 0x30003007 MSR 0xC0010065 0x800001BC 0x30005047 MSR 0xC0010066 0x00000000 0x30000000 MSR 0xC0010067 0x00000000 0x30000000 MSR 0xC0010068 0x00000000 0x30000000 MSR 0xC0010071 0x28AE00C1 0x30003007 MSR 0xC0010015 0x00000000 0x01000010 MSR 0xC001001F 0x00404000 0x00000008 MSR 0xC0010058 0x00000000 0xF0000001 MSR 0xC0010004 0x0000AA29 0x66ABCF3B MSR 0xC0010071 0x28AE00C1 0x30003007 MSR 0xC0010070 0x00000000 0x30003007 CPU Thread 1 APIC ID 1 Topology Processor ID 0, Core ID 1, Thread ID 0 Type 02004002h Max CPUID level 00000005h Max CPUID ext. level 8000001Ah Cache descriptor Level 1, I, 64 KB, 1 thread(s) Cache descriptor Level 1, D, 64 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) Cache descriptor Level 3, U, 2 MB, 3 thread(s) CPUID 0x00000000 0x00000005 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00100F23 0x01030800 0x00802009 0x178BFBFF 0x00000002 0x00000000 0x00000000 0x00000000 0x00000000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x00000000 0x00000000 0x00000000 0x00000000 0x00000005 0x00000040 0x00000040 0x00000003 0x00000000 0x80000000 0x8000001A 0x68747541 0x444D4163 0x69746E65 0x80000001 0x00100F23 0x10000563 0x000007FF 0xEFD3FBFF 0x80000002 0x20444D41 0x6E656850 0x74286D6F 0x3820296D 0x80000003 0x20303536 0x70697254 0x432D656C 0x2065726F 0x80000004 0x636F7250 0x6F737365 0x00000072 0x00000000 0x80000005 0xFF30FF10 0xFF30FF20 0x40020140 0x40020140 0x80000006 0x20800000 0x42004200 0x02008140 0x0010A140 0x80000007 0x00000000 0x00000000 0x00000000 0x000001F9 0x80000008 0x00003030 0x00000000 0x00002002 0x00000000 0x80000009 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000A 0x00000001 0x00000040 0x00000000 0x00000007 0x8000000B 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000D 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000E 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000F 0x00000000 0x00000000 0x00000000 0x00000000 0x80000010 0x00000000 0x00000000 0x00000000 0x00000000 0x80000011 0x00000000 0x00000000 0x00000000 0x00000000 0x80000012 0x00000000 0x00000000 0x00000000 0x00000000 0x80000013 0x00000000 0x00000000 0x00000000 0x00000000 0x80000014 0x00000000 0x00000000 0x00000000 0x00000000 0x80000015 0x00000000 0x00000000 0x00000000 0x00000000 0x80000016 0x00000000 0x00000000 0x00000000 0x00000000 0x80000017 0x00000000 0x00000000 0x00000000 0x00000000 0x80000018 0x00000000 0x00000000 0x00000000 0x00000000 0x80000019 0xF0300000 0x00000000 0x00000000 0x00000000 0x8000001A 0x00000003 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0xC0010114 0x00000000 0x00000018 MSR 0xC0010061 0x00000000 0x00000010 MSR 0xC0010062 0x00000000 0x00000000 MSR 0xC0010063 0x00000000 0x00000000 MSR 0xC0010064 0x800001F5 0x30003007 MSR 0xC0010065 0x800001BC 0x30005047 MSR 0xC0010066 0x00000000 0x30000000 MSR 0xC0010067 0x00000000 0x30000000 MSR 0xC0010068 0x00000000 0x30000000 MSR 0xC0010071 0x28AE00C1 0x30003007 MSR 0xC0010015 0x00000000 0x01000010 MSR 0xC001001F 0x00404000 0x00000008 MSR 0xC0010058 0x00000000 0xF0000001 MSR 0xC0010004 0x0000D8D3 0x18DFD847 MSR 0xC0010071 0x28AE00C1 0x30003007 MSR 0xC0010070 0x00000000 0x30003007 CPU Thread 2 APIC ID 2 Topology Processor ID 0, Core ID 2, Thread ID 0 Type 02004002h Max CPUID level 00000005h Max CPUID ext. level 8000001Ah Cache descriptor Level 1, I, 64 KB, 1 thread(s) Cache descriptor Level 1, D, 64 KB, 1 thread(s) Cache descriptor Level 2, U, 512 KB, 1 thread(s) Cache descriptor Level 3, U, 2 MB, 3 thread(s) CPUID 0x00000000 0x00000005 0x68747541 0x444D4163 0x69746E65 0x00000001 0x00100F23 0x02030800 0x00802009 0x178BFBFF 0x00000002 0x00000000 0x00000000 0x00000000 0x00000000 0x00000003 0x00000000 0x00000000 0x00000000 0x00000000 0x00000004 0x00000000 0x00000000 0x00000000 0x00000000 0x00000005 0x00000040 0x00000040 0x00000003 0x00000000 0x80000000 0x8000001A 0x68747541 0x444D4163 0x69746E65 0x80000001 0x00100F23 0x10000563 0x000007FF 0xEFD3FBFF 0x80000002 0x20444D41 0x6E656850 0x74286D6F 0x3820296D 0x80000003 0x20303536 0x70697254 0x432D656C 0x2065726F 0x80000004 0x636F7250 0x6F737365 0x00000072 0x00000000 0x80000005 0xFF30FF10 0xFF30FF20 0x40020140 0x40020140 0x80000006 0x20800000 0x42004200 0x02008140 0x0010A140 0x80000007 0x00000000 0x00000000 0x00000000 0x000001F9 0x80000008 0x00003030 0x00000000 0x00002002 0x00000000 0x80000009 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000A 0x00000001 0x00000040 0x00000000 0x00000007 0x8000000B 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000C 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000D 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000E 0x00000000 0x00000000 0x00000000 0x00000000 0x8000000F 0x00000000 0x00000000 0x00000000 0x00000000 0x80000010 0x00000000 0x00000000 0x00000000 0x00000000 0x80000011 0x00000000 0x00000000 0x00000000 0x00000000 0x80000012 0x00000000 0x00000000 0x00000000 0x00000000 0x80000013 0x00000000 0x00000000 0x00000000 0x00000000 0x80000014 0x00000000 0x00000000 0x00000000 0x00000000 0x80000015 0x00000000 0x00000000 0x00000000 0x00000000 0x80000016 0x00000000 0x00000000 0x00000000 0x00000000 0x80000017 0x00000000 0x00000000 0x00000000 0x00000000 0x80000018 0x00000000 0x00000000 0x00000000 0x00000000 0x80000019 0xF0300000 0x00000000 0x00000000 0x00000000 0x8000001A 0x00000003 0x00000000 0x00000000 0x00000000 MSR 0x0000001B 0x00000000 0xFEE00800 MSR 0xC0010114 0x00000000 0x00000018 MSR 0xC0010061 0x00000000 0x00000010 MSR 0xC0010062 0x00000000 0x00000000 MSR 0xC0010063 0x00000000 0x00000000 MSR 0xC0010064 0x800001F5 0x30003007 MSR 0xC0010065 0x800001BC 0x30005047 MSR 0xC0010066 0x00000000 0x30000000 MSR 0xC0010067 0x00000000 0x30000000 MSR 0xC0010068 0x00000000 0x30000000 MSR 0xC0010071 0x28AE00C1 0x30003007 MSR 0xC0010015 0x00000000 0x01000010 MSR 0xC001001F 0x00404000 0x00000008 MSR 0xC0010058 0x00000000 0xF0000001 MSR 0xC0010004 0x0000DBAC 0x882A1120 MSR 0xC0010071 0x28AE00C1 0x30003007 MSR 0xC0010070 0x00000000 0x30003007 bochs-2.6/cpu/cpudb/turion64_tyler.cc0000644000175000017500000004104112020641451017434 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: turion64_tyler.cc 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "turion64_tyler.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 turion64_tyler_t::turion64_tyler_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Turion64 configuration")); BX_INFO(("WARNING: 3DNow! is not implemented yet !")); if (! BX_SUPPORT_SVM) BX_INFO(("WARNING: SVM Support is not compiled in !")); } void turion64_tyler_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_ext_cpuid_leaf_5(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; #if BX_SUPPORT_SVM case 0x8000000A: get_ext_cpuid_leaf_A(leaf); return; #endif case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; default: get_reserved_leaf(leaf); return; } } Bit64u turion64_tyler_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_3DNOW | BX_ISA_SYSCALL_SYSRET_LEGACY | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_CMPXCHG16B | BX_ISA_LM_LAHF_SAHF | #if BX_SUPPORT_SVM BX_ISA_SVM | #endif BX_ISA_RDTSCP; } Bit32u turion64_tyler_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX | BX_CPU_FFXSR | BX_CPU_ALT_MOV_CR8 | BX_CPU_XAPIC_EXT; } // leaf 0x00000000 // void turion64_tyler_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = 0x1; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void turion64_tyler_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00060F82; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // [2:2] DTES64: 64-bit DS area // [3:3] MONITOR/MWAIT support // [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // [7:7] EST: Enhanced Intel SpeedStep Technology // [8:8] TM2: Thermal Monitor 2 // [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // [14:14] xTPR update control // [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_CMPXCHG16B; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // * [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_HT; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000000 // void turion64_tyler_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "AuthenticAMD"; // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000018; memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000001 // void turion64_tyler_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (same as 0x00000001.EAX) leaf->eax = 0x00060F82; // EBX: Brand ID leaf->ebx = 0x0000059F; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // * [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // * [2:2] SVM: Secure Virtual Machine (AMD) // * [3:3] Extended APIC Space // * [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support // [7:7] Misaligned SSE support // * [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [10:10] IBS: Instruction based sampling // [11:11] XOP: Extended Operations Support and XOP Prefix // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [14:14] Reserved // [15:15] LWP: Light weight profiling // [16:16] FMA4: Four-operand FMA instructions support // [17:17] Reserved // [18:18] Reserved // [19:19] Reserved // [20:20] NodeId: Indicates support for NodeId MSR (0xc001100c) // [21:21] Reserved // [22:22] TBM: trailing bit manipulation instructions support // [23:23] Topology extensions support // [31:24] Reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF | BX_CPUID_EXT2_CMP_LEGACY | #if BX_SUPPORT_SVM BX_CPUID_EXT2_SVM | #endif BX_CPUID_EXT2_EXT_APIC_SPACE | BX_CPUID_EXT2_ALT_MOV_CR8 | BX_CPUID_EXT2_PREFETCHW; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 for AMD // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSCALL/SYSRET support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] Reserved // [19:19] Reserved // * [20:20] No-Execute page protection // [21:21] Reserved // * [22:22] AMD MMX Extensions // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] Fast FXSAVE/FXRSTOR mode support // [26:26] 1G paging support // * [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // * [30:30] AMD 3DNow! Extensions // * [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD2_SYSCALL_SYSRET | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD2_NX | BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD2_FFXSR | BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE | BX_CPUID_STD2_3DNOW_EXT | BX_CPUID_STD2_3DNOW; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void turion64_tyler_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "AMD Turion(tm) 64 X2 Mobile Technology TL-60"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); leaf->edx = 0; break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 // void turion64_tyler_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x800000005 - L1 Cache and TLB Identifiers leaf->eax = 0xFF08FF08; leaf->ebx = 0xFF20FF20; leaf->ecx = 0x40020140; leaf->edx = 0x40020140; } // leaf 0x80000006 // void turion64_tyler_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x42004200; leaf->ecx = 0x02008140; leaf->edx = 0x00000000; } // leaf 0x80000007 // void turion64_tyler_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x0000007F; } // leaf 0x80000008 // void turion64_tyler_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = ncores - 1; leaf->edx = 0; } // leaf 0x80000009 : Reserved // #if BX_SUPPORT_SVM // leaf 0x8000000A : SVM // void turion64_tyler_t::get_ext_cpuid_leaf_A(cpuid_function_t *leaf) const { leaf->eax = 0x01; /* SVM revision ID */ leaf->ebx = 0x40; /* number of ASIDs */ leaf->ecx = 0; // [0:0] NP - Nested paging support // * [1:1] LBR virtualization // [2:2] SVM Lock // [3:3] NRIPS - Next RIP save on VMEXIT // [4:4] TscRate - MSR based TSC ratio control // [5:5] VMCB Clean bits support // [6:6] Flush by ASID support // [7:7] Decode assists support // [9:8] Reserved // [10:10] Pause filter support // [11:11] Reserved // [12:12] Pause filter threshold support // [31:13] Reserved leaf->edx = BX_CPUID_SVM_LBR_VIRTUALIZATION; } #endif // leaf 0x8000000B - 0x80000018: Reserved // void turion64_tyler_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=1; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000018; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_turion64_tyler_cpuid(BX_CPU_C *cpu) { return new turion64_tyler_t(cpu); } #endif bochs-2.6/cpu/cpudb/corei5_arrandale_m520.cc0000644000175000017500000005353312020641451020476 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: corei5_arrandale_m520.cc 11217 2012-06-14 18:56:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "corei5_arrandale_m520.h" #define LOG_THIS cpu-> #if BX_SUPPORT_X86_64 corei5_arrandale_m520_t::corei5_arrandale_m520_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { if (! BX_SUPPORT_X86_64) BX_PANIC(("You must enable x86-64 for Intel Core i5 M 520 (Arrandale) configuration")); if (BX_SUPPORT_VMX == 1) BX_INFO(("You must compile with --enable-vmx=2 for Intel Core i5 M 520 (Arrandale) VMX configuration")); if (! BX_SUPPORT_MONITOR_MWAIT) BX_INFO(("WARNING: MONITOR/MWAIT support is not compiled in !")); } void corei5_arrandale_m520_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; switch(function) { case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_reserved_leaf(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: get_std_cpuid_leaf_A(leaf); return; case 0x0000000B: default: get_std_cpuid_extended_topology_leaf(subfunction, leaf); return; } } Bit64u corei5_arrandale_m520_t::get_isa_extensions_bitmask(void) const { return BX_ISA_X87 | BX_ISA_486 | BX_ISA_PENTIUM | BX_ISA_P6 | BX_ISA_MMX | BX_ISA_SYSENTER_SYSEXIT | BX_ISA_CLFLUSH | BX_ISA_SSE | BX_ISA_SSE2 | BX_ISA_SSE3 | BX_ISA_SSSE3 | BX_ISA_SSE4_1 | BX_ISA_SSE4_2 | BX_ISA_POPCNT | #if BX_SUPPORT_MONITOR_MWAIT BX_ISA_MONITOR_MWAIT | #endif #if BX_SUPPORT_VMX >= 2 BX_ISA_VMX | #endif BX_ISA_SMX | BX_ISA_RDTSCP | BX_ISA_AES_PCLMULQDQ | BX_ISA_CMPXCHG16B | BX_ISA_LM_LAHF_SAHF; } Bit32u corei5_arrandale_m520_t::get_cpu_extensions_bitmask(void) const { return BX_CPU_DEBUG_EXTENSIONS | BX_CPU_VME | BX_CPU_PSE | BX_CPU_PAE | BX_CPU_PGE | BX_CPU_PSE36 | BX_CPU_MTRR | BX_CPU_PAT | BX_CPU_XAPIC | BX_CPU_LONG_MODE | BX_CPU_NX; } #if BX_SUPPORT_VMX >= 2 // // MSR 00000480 : 00DA0400 0000000F BX_MSR_VMX_BASIC // MSR 00000481 : 0000007F 00000016 BX_MSR_VMX_PINBASED_CTRLS // MSR 00000482 : FFF9FFFE 04006172 BX_MSR_VMX_PROCBASED_CTRLS // MSR 00000483 : 007FFFFF 00036DFB BX_MSR_VMX_VMEXIT_CTRLS // MSR 00000484 : 0000FFFF 000011FF BX_MSR_VMX_VMENTRY_CTRLS // MSR 00000485 : 00000000 000401E5 BX_MSR_VMX_MISC // MSR 00000486 : 00000000 80000021 BX_MSR_VMX_CR0_FIXED0 // MSR 00000487 : 00000000 FFFFFFFF BX_MSR_VMX_CR0_FIXED1 // MSR 00000488 : 00000000 00002000 BX_MSR_VMX_CR4_FIXED0 // MSR 00000489 : 00000000 000067FF BX_MSR_VMX_CR4_FIXED1 // MSR 0000048A : 00000000 0000002A BX_MSR_VMX_VMCS_ENUM // MSR 0000048B : 000000FF 00000000 BX_MSR_VMX_PROCBASED_CTRLS2 // MSR 0000048C : 00000F01 06114141 BX_MSR_VMX_MSR_VMX_EPT_VPID_CAP // MSR 0000048D : 0000007F 00000016 BX_MSR_VMX_TRUE_PINBASED_CTRLS // MSR 0000048E : FFF9FFFE 04006172 BX_MSR_VMX_TRUE_PROCBASED_CTRLS // MSR 0000048F : 007FFFFF 00036DFB BX_MSR_VMX_TRUE_VMEXIT_CTRLS // MSR 00000490 : 0000FFFF 000011FB BX_MSR_VMX_TRUE_VMENTRY_CTRLS // Bit32u corei5_arrandale_m520_t::get_vmx_extensions_bitmask(void) const { return BX_VMX_TPR_SHADOW | BX_VMX_VIRTUAL_NMI | BX_VMX_APIC_VIRTUALIZATION | BX_VMX_WBINVD_VMEXIT | /* BX_VMX_MONITOR_TRAP_FLAG | */ // not implemented yet BX_VMX_VPID | BX_VMX_EPT | BX_VMX_UNRESTRICTED_GUEST | BX_VMX_SAVE_DEBUGCTL_DISABLE | BX_VMX_PERF_GLOBAL_CTRL | // MSR not implemented yet BX_VMX_PAT | BX_VMX_EFER | BX_VMX_DESCRIPTOR_TABLE_EXIT | BX_VMX_X2APIC_VIRTUALIZATION | BX_VMX_PREEMPTION_TIMER; } #endif // leaf 0x00000000 // void corei5_arrandale_m520_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static const char* vendor_string = "GenuineIntel"; // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) leaf->eax = 0x2; else leaf->eax = 0xB; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void corei5_arrandale_m520_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = 0x00020652; // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID unsigned n_logical_processors = ncores*nthreads; leaf->ebx = ((CACHE_LINE_SIZE / 8) << 8) | (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags // * [0:0] SSE3: SSE3 Instructions // * [1:1] PCLMULQDQ Instruction support // * [2:2] DTES64: 64-bit DS area // * [3:3] MONITOR/MWAIT support // * [4:4] DS-CPL: CPL qualified debug store // * [5:5] VMX: Virtual Machine Technology // * [6:6] SMX: Secure Virtual Machine Technology // * [7:7] EST: Enhanced Intel SpeedStep Technology // * [8:8] TM2: Thermal Monitor 2 // * [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // * [13:13] CMPXCHG16B: CMPXCHG16B instruction support // * [14:14] xTPR update control // * [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // * [19:19] SSE4.1 Instructions // * [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // * [23:23] POPCNT instruction // [24:24] TSC Deadline // * [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved leaf->ecx = BX_CPUID_EXT_SSE3 | BX_CPUID_EXT_PCLMULQDQ | BX_CPUID_EXT_DTES64 | #if BX_SUPPORT_MONITOR_MWAIT BX_CPUID_EXT_MONITOR_MWAIT | #endif BX_CPUID_EXT_DS_CPL | #if BX_SUPPORT_VMX >= 2 BX_CPUID_EXT_VMX | #endif BX_CPUID_EXT_SMX | BX_CPUID_EXT_EST | BX_CPUID_EXT_THERMAL_MONITOR2 | BX_CPUID_EXT_SSSE3 | BX_CPUID_EXT_CMPXCHG16B | BX_CPUID_EXT_xTPR | BX_CPUID_EXT_PDCM | BX_CPUID_EXT_SSE4_1 | BX_CPUID_EXT_SSE4_2 | BX_CPUID_EXT_POPCNT | BX_CPUID_EXT_AES; // EDX: Standard Feature Flags // * [0:0] FPU on chip // * [1:1] VME: Virtual-8086 Mode enhancements // * [2:2] DE: Debug Extensions (I/O breakpoints) // * [3:3] PSE: Page Size Extensions // * [4:4] TSC: Time Stamp Counter // * [5:5] MSR: RDMSR and WRMSR support // * [6:6] PAE: Physical Address Extensions // * [7:7] MCE: Machine Check Exception // * [8:8] CXS: CMPXCHG8B instruction // * [9:9] APIC: APIC on Chip // [10:10] Reserved // * [11:11] SYSENTER/SYSEXIT support // * [12:12] MTRR: Memory Type Range Reg // * [13:13] PGE/PTE Global Bit // * [14:14] MCA: Machine Check Architecture // * [15:15] CMOV: Cond Mov/Cmp Instructions // * [16:16] PAT: Page Attribute Table // * [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // * [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // * [21:21] DS: Debug Store // * [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // * [23:23] MMX Technology // * [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // * [25:25] SSE: SSE Extensions // * [26:26] SSE2: SSE2 Extensions // * [27:27] Self Snoop // * [28:28] Hyper Threading Technology // * [29:29] TM: Thermal Monitor // [30:30] Reserved // * [31:31] PBE: Pending Break Enable leaf->edx = BX_CPUID_STD_X87 | BX_CPUID_STD_VME | BX_CPUID_STD_DEBUG_EXTENSIONS | BX_CPUID_STD_PSE | BX_CPUID_STD_TSC | BX_CPUID_STD_MSR | BX_CPUID_STD_PAE | BX_CPUID_STD_MCE | BX_CPUID_STD_CMPXCHG8B | BX_CPUID_STD_SYSENTER_SYSEXIT | BX_CPUID_STD_MTRR | BX_CPUID_STD_GLOBAL_PAGES | BX_CPUID_STD_MCA | BX_CPUID_STD_CMOV | BX_CPUID_STD_PAT | BX_CPUID_STD_PSE36 | BX_CPUID_STD_CLFLUSH | BX_CPUID_STD_DEBUG_STORE | BX_CPUID_STD_ACPI | BX_CPUID_STD_MMX | BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE | BX_CPUID_STD_SSE2 | BX_CPUID_STD_SELF_SNOOP | BX_CPUID_STD_HT | BX_CPUID_STD_THERMAL_MONITOR | BX_CPUID_STD_PBE; #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) leaf->edx |= BX_CPUID_STD_APIC; // APIC on chip #endif } // leaf 0x00000002 // void corei5_arrandale_m520_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors leaf->eax = 0x55035A01; leaf->ebx = 0x00F0B2DD; leaf->ecx = 0x00000000; leaf->edx = 0x09CA212C; } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void corei5_arrandale_m520_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters // EAX: // [04-00] - Cache Type Field // 0 = No more caches // 1 = Data Cache // 2 = Instruction Cache // 3 = Unified Cache // [07-05] - Cache Level (starts at 1)] // [08] - Self Initializing cache level (doesn't need software initialization) // [09] - Fully Associative cache // [13-10] - Reserved // [25-14] - Maximum number of addressable IDs for logical processors sharing this cache // [31-26] - Maximum number of addressable IDs for processor cores in the physical package - 1 // EBX: // [11-00] - L = System Coherency Line Size // [21-12] - P = Physical Line partitions // [31-22] - W = Ways of associativity // ECX: Number of Sets // EDX: // [00] - Writeback invalidate // [01] - Cache Inclusiveness // [02] - Complex Cache Indexing // [31-03] - Reserved switch(subfunction) { case 0: leaf->eax = 0x1C004121; leaf->ebx = 0x01C0003F; leaf->ecx = 0x0000003F; leaf->edx = 0x00000000; break; case 1: leaf->eax = 0x1C004122; leaf->ebx = 0x00C0003F; leaf->ecx = 0x0000007F; leaf->edx = 0x00000000; break; case 2: leaf->eax = 0x1C004143; leaf->ebx = 0x01C0003F; leaf->ecx = 0x000001FF; leaf->edx = 0x00000000; break; case 3: leaf->eax = 0x1C03C163; leaf->ebx = 0x02C0003F; leaf->ecx = 0x00000FFF; leaf->edx = 0x00000002; break; default: leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; } } // leaf 0x00000005 // void corei5_arrandale_m520_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x00001120; #else leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000006 // void corei5_arrandale_m520_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0x00000007; leaf->ebx = 0x00000002; leaf->ecx = 0x00000001; leaf->edx = 0x00000000; } // leaf 0x00000007 not supported // // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void corei5_arrandale_m520_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0x07300403; leaf->ebx = 0x00000004; leaf->ecx = 0x00000000; leaf->edx = 0x00000603; BX_INFO(("WARNING: Architectural Performance Monitoring is not implemented")); } BX_CPP_INLINE static Bit32u ilog2(Bit32u x) { Bit32u count = 0; while(x>>=1) count++; return count; } // leaf 0x0000000B // void corei5_arrandale_m520_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x0000000B - Extended Topology Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = subfunction; leaf->edx = cpu->get_apic_id(); #if BX_SUPPORT_SMP switch(subfunction) { case 0: if (nthreads > 1) { leaf->eax = ilog2(nthreads-1)+1; leaf->ebx = nthreads; leaf->ecx |= (1<<8); } else if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } else { leaf->eax = 1; leaf->ebx = 1; // number of logical CPUs at this level } break; case 1: if (nthreads > 1) { if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } else if (ncores > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; case 2: if (nthreads > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; default: break; } #endif } // leaf 0x80000000 // void corei5_arrandale_m520_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: reserved // EDX: reserved // ECX: reserved leaf->eax = 0x80000008; leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; } // leaf 0x80000001 // void corei5_arrandale_m520_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information (reserved for Intel) leaf->eax = 0; // EBX: Brand ID (reserved for Intel) leaf->ebx = 0; // ECX: // * [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [11:10] reserved // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [31:14] reserved leaf->ecx = BX_CPUID_EXT2_LAHF_SAHF; // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [10:0] Reserved for Intel // * [11:11] SYSCALL/SYSRET support // [19:12] Reserved for Intel // * [20:20] No-Execute page protection // [25:21] Reserved // [26:26] 1G paging support // * [27:27] Support RDTSCP Instruction // [28:28] Reserved // * [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = BX_CPUID_STD2_NX | BX_CPUID_STD2_RDTSCP | BX_CPUID_STD2_LONG_MODE; if (cpu->long64_mode()) leaf->edx |= BX_CPUID_STD2_SYSCALL_SYSRET; } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void corei5_arrandale_m520_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x80000002-0x80000004 - Processor Name String Identifier static const char* brand_string = "Intel(R) Core(TM) i5 CPU M 520 @ 2.40GHz"; switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 - L1 Cache and TLB Identifiers (reserved for Intel) // leaf 0x80000006 // void corei5_arrandale_m520_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0x00000000; leaf->ebx = 0x00000000; leaf->ecx = 0x01006040; leaf->edx = 0x00000000; } // leaf 0x80000007 // void corei5_arrandale_m520_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0x00000100; // bit 8 - invariant TSC } // leaf 0x80000008 // void corei5_arrandale_m520_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } void corei5_arrandale_m520_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n<=0xb; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } for (n=0x80000000; n<=0x80000008; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } bx_cpuid_t *create_corei5_arrandale_m520_cpuid(BX_CPU_C *cpu) { return new corei5_arrandale_m520_t(cpu); } #endif bochs-2.6/cpu/cpudb/p2_klamath.txt0000644000175000017500000000225512020641451017003 0ustar guillemguillem---------------------- CPU-Z version 1.31 ---------------------- CPUID Output ------------------------------------------------------------------------------ Number of CPUs 1 Name Intel Pentium II Code name Klamath Specification Intel Pentium II 300 MHz Family/Model/Stepping 634 Extended Family/Model 0/0 Package Slot 1 SECC Core Stepping C1 Technology 0.35µ Instructions Sets MMX Features Clock Speed 299.1 MHz Clock multiplier x4.5 Front Side Bus Frequency 66.5 MHz Bus Speed 66.5 MHz Stock frequency 300 MHz L1 Data Cache 16 KBytes, 4-way set associative, 32 Bytes line size L1 Instruction Cache 16 KBytes, 4-way set associative, 32 Bytes line size L2 Cache 512 KBytes, 4-way set associative, 32 Bytes line size L2 Latency 0 L2 Speed 149.6 MHz (1/2) L2 Location On Cartridge L2 ECC Check enabled L2 Data Prefetch Logic no L2 Bus Width 64 bits eax ebx ecx edx Function 00000000 00000002 756e6547 6c65746e 49656e69 Function 00000001 00000634 00000000 00000000 0080fbff Function 00000002 03020101 00000000 00000000 0c040843 edx eax MSR 0000002A 00000000 C5800000 MSR 0000011E 00000000 00044521 MSR 0000008B 00000037 00000000 bochs-2.6/cpu/cpuid.h0000644000175000017500000005202012020641453014375 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cpuid.h 11276 2012-07-12 14:51:54Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2010-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_CPU_MODEL_SPECIFIC #define BX_CPU_MODEL_SPECIFIC struct cpuid_function_t { Bit32u eax; Bit32u ebx; Bit32u ecx; Bit32u edx; }; class bx_cpuid_t { public: bx_cpuid_t(BX_CPU_C *_cpu); virtual ~bx_cpuid_t() {} // return CPU name virtual const char *get_name(void) const { return NULL; } virtual Bit64u get_isa_extensions_bitmask(void) const = 0; virtual Bit32u get_cpu_extensions_bitmask(void) const = 0; #if BX_SUPPORT_VMX virtual Bit32u get_vmx_extensions_bitmask(void) const { return 0; } #endif #if BX_SUPPORT_SVM virtual Bit32u get_svm_extensions_bitmask(void) const { return 0; } #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const = 0; virtual void dump_cpuid(void) const = 0; #if BX_CPU_LEVEL >= 5 virtual int rdmsr(Bit32u index, Bit64u *msr) { return -1; } virtual int wrmsr(Bit32u index, Bit64u msr) { return -1; } #endif protected: BX_CPU_C *cpu; unsigned nprocessors; unsigned ncores; unsigned nthreads; void get_reserved_leaf(cpuid_function_t *leaf) const { leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } }; typedef bx_cpuid_t* (*bx_create_cpuid_method)(BX_CPU_C *cpu); // cpuid ISA (duplicated in disasm.h) #define BX_ISA_X87 (BX_CONST64(1) << 0) /* FPU (X87) instruction */ #define BX_ISA_486 (BX_CONST64(1) << 1) /* 486 new instruction */ #define BX_ISA_PENTIUM (BX_CONST64(1) << 2) /* Pentium new instruction */ #define BX_ISA_P6 (BX_CONST64(1) << 3) /* P6 new instruction */ #define BX_ISA_MMX (BX_CONST64(1) << 4) /* MMX instruction */ #define BX_ISA_3DNOW (BX_CONST64(1) << 5) /* 3DNow! instruction (AMD) */ #define BX_ISA_SYSCALL_SYSRET_LEGACY (BX_CONST64(1) << 6) /* SYSCALL/SYSRET in legacy mode (AMD) */ #define BX_ISA_SYSENTER_SYSEXIT (BX_CONST64(1) << 7) /* SYSENTER/SYSEXIT instruction */ #define BX_ISA_CLFLUSH (BX_CONST64(1) << 8) /* CLFLUSH instruction */ #define BX_ISA_SSE (BX_CONST64(1) << 9) /* SSE instruction */ #define BX_ISA_SSE2 (BX_CONST64(1) << 10) /* SSE2 instruction */ #define BX_ISA_SSE3 (BX_CONST64(1) << 11) /* SSE3 instruction */ #define BX_ISA_SSSE3 (BX_CONST64(1) << 12) /* SSSE3 instruction */ #define BX_ISA_SSE4_1 (BX_CONST64(1) << 13) /* SSE4_1 instruction */ #define BX_ISA_SSE4_2 (BX_CONST64(1) << 14) /* SSE4_2 instruction */ #define BX_ISA_POPCNT (BX_CONST64(1) << 15) /* POPCNT instruction */ #define BX_ISA_MONITOR_MWAIT (BX_CONST64(1) << 16) /* MONITOR/MWAIT instruction */ #define BX_ISA_VMX (BX_CONST64(1) << 17) /* VMX instruction */ #define BX_ISA_SMX (BX_CONST64(1) << 18) /* SMX instruction */ #define BX_ISA_LM_LAHF_SAHF (BX_CONST64(1) << 19) /* Long Mode LAHF/SAHF instruction */ #define BX_ISA_CMPXCHG16B (BX_CONST64(1) << 20) /* CMPXCHG16B instruction */ #define BX_ISA_RDTSCP (BX_CONST64(1) << 21) /* RDTSCP instruction */ #define BX_ISA_XSAVE (BX_CONST64(1) << 22) /* XSAVE/XRSTOR extensions instruction */ #define BX_ISA_XSAVEOPT (BX_CONST64(1) << 23) /* XSAVEOPT instruction */ #define BX_ISA_AES_PCLMULQDQ (BX_CONST64(1) << 24) /* AES+PCLMULQDQ instruction */ #define BX_ISA_MOVBE (BX_CONST64(1) << 25) /* MOVBE Intel Atom(R) instruction */ #define BX_ISA_FSGSBASE (BX_CONST64(1) << 26) /* FS/GS BASE access instruction */ #define BX_ISA_INVPCID (BX_CONST64(1) << 27) /* INVPCID instruction */ #define BX_ISA_AVX (BX_CONST64(1) << 28) /* AVX instruction */ #define BX_ISA_AVX2 (BX_CONST64(1) << 29) /* AVX2 instruction */ #define BX_ISA_AVX_F16C (BX_CONST64(1) << 30) /* AVX F16 convert instruction */ #define BX_ISA_AVX_FMA (BX_CONST64(1) << 31) /* AVX FMA instruction */ #define BX_ISA_SSE4A (BX_CONST64(1) << 32) /* SSE4A instruction (AMD) */ #define BX_ISA_LZCNT (BX_CONST64(1) << 33) /* LZCNT instruction */ #define BX_ISA_BMI1 (BX_CONST64(1) << 34) /* BMI1 instruction */ #define BX_ISA_BMI2 (BX_CONST64(1) << 35) /* BMI2 instruction */ #define BX_ISA_FMA4 (BX_CONST64(1) << 36) /* FMA4 instruction (AMD) */ #define BX_ISA_XOP (BX_CONST64(1) << 37) /* XOP instruction (AMD) */ #define BX_ISA_TBM (BX_CONST64(1) << 38) /* TBM instruction (AMD) */ #define BX_ISA_SVM (BX_CONST64(1) << 39) /* SVM instruction (AMD) */ #define BX_ISA_ADX (BX_CONST64(1) << 40) /* ADCX/ADOX instruction */ // cpuid non-ISA features #define BX_CPU_DEBUG_EXTENSIONS (1 << 0) /* Debug Extensions support */ #define BX_CPU_VME (1 << 1) /* VME support */ #define BX_CPU_PSE (1 << 2) /* PSE support */ #define BX_CPU_PAE (1 << 3) /* PAE support */ #define BX_CPU_PGE (1 << 4) /* Global Pages support */ #define BX_CPU_PSE36 (1 << 5) /* PSE-36 support */ #define BX_CPU_MTRR (1 << 6) /* MTRR support */ #define BX_CPU_PAT (1 << 7) /* PAT support */ #define BX_CPU_XAPIC (1 << 8) /* XAPIC support */ #define BX_CPU_X2APIC (1 << 9) /* X2APIC support */ #define BX_CPU_XAPIC_EXT (1 << 10) /* XAPIC Extensions support */ #define BX_CPU_NX (1 << 11) /* No-Execute support */ #define BX_CPU_LONG_MODE (1 << 12) /* Long Mode (x86-64) support */ #define BX_CPU_1G_PAGES (1 << 13) /* 1Gb pages support */ #define BX_CPU_PCID (1 << 14) /* PCID pages support */ #define BX_CPU_SMEP (1 << 15) /* SMEP support */ #define BX_CPU_FFXSR (1 << 16) /* EFER.FFXSR support */ #define BX_CPU_ALT_MOV_CR8 (1 << 17) /* LOCK CR0 access CR8 */ #define BX_CPU_TSC_DEADLINE (1 << 18) /* TSC-Deadline */ #define BX_CPU_MISALIGNED_SSE (1 << 19) /* Misaligned SSE */ // cpuid VMX features #define BX_VMX_TPR_SHADOW (1 << 0) /* TPR shadow */ #define BX_VMX_VIRTUAL_NMI (1 << 1) /* Virtual NMI */ #define BX_VMX_APIC_VIRTUALIZATION (1 << 2) /* APIC Virtualization */ #define BX_VMX_WBINVD_VMEXIT (1 << 3) /* WBINVD VMEXIT */ #define BX_VMX_PERF_GLOBAL_CTRL (1 << 4) /* Save/Restore MSR_PERF_GLOBAL_CTRL */ #define BX_VMX_MONITOR_TRAP_FLAG (1 << 5) /* Monitor trap Flag (MTF) */ #define BX_VMX_X2APIC_VIRTUALIZATION (1 << 6) /* Virtualize X2APIC */ #define BX_VMX_EPT (1 << 7) /* Extended Page Tables (EPT) */ #define BX_VMX_VPID (1 << 8) /* VPID */ #define BX_VMX_UNRESTRICTED_GUEST (1 << 9) /* Unrestricted Guest */ #define BX_VMX_PREEMPTION_TIMER (1 << 10) /* VMX preemption timer */ #define BX_VMX_SAVE_DEBUGCTL_DISABLE (1 << 11) /* Disable Save/Restore of MSR_DEBUGCTL */ #define BX_VMX_PAT (1 << 12) /* Save/Restore MSR_PAT */ #define BX_VMX_EFER (1 << 13) /* Save/Restore MSR_EFER */ #define BX_VMX_DESCRIPTOR_TABLE_EXIT (1 << 14) /* Descriptor Table VMEXIT */ #define BX_VMX_PAUSE_LOOP_EXITING (1 << 15) /* Pause Loop Exiting */ #define BX_VMX_EPTP_SWITCHING (1 << 16) /* EPTP switching (VM Function 0) */ #define BX_VMX_EPT_ACCESS_DIRTY (1 << 17) /* Extended Page Tables (EPT) A/D Bits */ // CPUID defines - STD features CPUID[0x00000001].EDX // ---------------------------- // [0:0] FPU on chip // [1:1] VME: Virtual-8086 Mode enhancements // [2:2] DE: Debug Extensions (I/O breakpoints) // [3:3] PSE: Page Size Extensions // [4:4] TSC: Time Stamp Counter // [5:5] MSR: RDMSR and WRMSR support // [6:6] PAE: Physical Address Extensions // [7:7] MCE: Machine Check Exception // [8:8] CXS: CMPXCHG8B instruction // [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSENTER/SYSEXIT support // [12:12] MTRR: Memory Type Range Reg // [13:13] PGE/PTE Global Bit // [14:14] MCA: Machine Check Architecture // [15:15] CMOV: Cond Mov/Cmp Instructions // [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // [23:23] MMX Technology // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] SSE: SSE Extensions // [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable #define BX_CPUID_STD_X87 (1 << 0) #define BX_CPUID_STD_VME (1 << 1) #define BX_CPUID_STD_DEBUG_EXTENSIONS (1 << 2) #define BX_CPUID_STD_PSE (1 << 3) #define BX_CPUID_STD_TSC (1 << 4) #define BX_CPUID_STD_MSR (1 << 5) #define BX_CPUID_STD_PAE (1 << 6) #define BX_CPUID_STD_MCE (1 << 7) #define BX_CPUID_STD_CMPXCHG8B (1 << 8) #define BX_CPUID_STD_APIC (1 << 9) #define BX_CPUID_STD_RESERVED10 (1 << 10) #define BX_CPUID_STD_SYSENTER_SYSEXIT (1 << 11) #define BX_CPUID_STD_MTRR (1 << 12) #define BX_CPUID_STD_GLOBAL_PAGES (1 << 13) #define BX_CPUID_STD_MCA (1 << 14) #define BX_CPUID_STD_CMOV (1 << 15) #define BX_CPUID_STD_PAT (1 << 16) #define BX_CPUID_STD_PSE36 (1 << 17) #define BX_CPUID_STD_PROCESSOR_SERIAL_NUMBER (1 << 18) #define BX_CPUID_STD_CLFLUSH (1 << 19) #define BX_CPUID_STD_RESERVED20 (1 << 20) #define BX_CPUID_STD_DEBUG_STORE (1 << 21) #define BX_CPUID_STD_ACPI (1 << 22) #define BX_CPUID_STD_MMX (1 << 23) #define BX_CPUID_STD_FXSAVE_FXRSTOR (1 << 24) #define BX_CPUID_STD_SSE (1 << 25) #define BX_CPUID_STD_SSE2 (1 << 26) #define BX_CPUID_STD_SELF_SNOOP (1 << 27) #define BX_CPUID_STD_HT (1 << 28) #define BX_CPUID_STD_THERMAL_MONITOR (1 << 29) #define BX_CPUID_STD_RESERVED30 (1 << 30) #define BX_CPUID_STD_PBE (1 << 31) // CPUID defines - EXT features CPUID[0x00000001].ECX // ---------------------------- // [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // [2:2] DTES64: 64-bit DS area // [3:3] MONITOR/MWAIT support // [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // [7:7] EST: Enhanced Intel SpeedStep Technology // [8:8] TM2: Thermal Monitor 2 // [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // [13:13] CMPXCHG16B: CMPXCHG16B instruction support // [14:14] xTPR update control // [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved #define BX_CPUID_EXT_SSE3 (1 << 0) #define BX_CPUID_EXT_PCLMULQDQ (1 << 1) #define BX_CPUID_EXT_DTES64 (1 << 2) #define BX_CPUID_EXT_MONITOR_MWAIT (1 << 3) #define BX_CPUID_EXT_DS_CPL (1 << 4) #define BX_CPUID_EXT_VMX (1 << 5) #define BX_CPUID_EXT_SMX (1 << 6) #define BX_CPUID_EXT_EST (1 << 7) #define BX_CPUID_EXT_THERMAL_MONITOR2 (1 << 8) #define BX_CPUID_EXT_SSSE3 (1 << 9) #define BX_CPUID_EXT_CNXT_ID (1 << 10) #define BX_CPUID_EXT_RESERVED11 (1 << 11) #define BX_CPUID_EXT_FMA (1 << 12) #define BX_CPUID_EXT_CMPXCHG16B (1 << 13) #define BX_CPUID_EXT_xTPR (1 << 14) #define BX_CPUID_EXT_PDCM (1 << 15) #define BX_CPUID_EXT_RESERVED16 (1 << 16) #define BX_CPUID_EXT_PCID (1 << 17) #define BX_CPUID_EXT_DCA (1 << 18) #define BX_CPUID_EXT_SSE4_1 (1 << 19) #define BX_CPUID_EXT_SSE4_2 (1 << 20) #define BX_CPUID_EXT_X2APIC (1 << 21) #define BX_CPUID_EXT_MOVBE (1 << 22) #define BX_CPUID_EXT_POPCNT (1 << 23) #define BX_CPUID_EXT_TSC_DEADLINE (1 << 24) #define BX_CPUID_EXT_AES (1 << 25) #define BX_CPUID_EXT_XSAVE (1 << 26) #define BX_CPUID_EXT_OSXSAVE (1 << 27) #define BX_CPUID_EXT_AVX (1 << 28) #define BX_CPUID_EXT_AVX_F16C (1 << 29) #define BX_CPUID_EXT_RDRAND (1 << 30) #define BX_CPUID_EXT_RESERVED31 (1 << 31) // CPUID defines - EXT3 features CPUID[0x00000007].EBX // ----------------------------- // [0:0] FS/GS BASE access instructions // [2:1] reserved // [3:3] BMI1: Advanced Bit Manipulation Extensions // [4:4] HLE: Hardware Lock Elision // [5:5] AVX2 // [6:6] reserved // [7:7] SMEP: Supervisor Mode Execution Protection // [8:8] BMI2: Advanced Bit Manipulation Extensions // [9:9] Support for Enhanced REP MOVSB/STOSB // [10:10] Support for INVPCID instruction // [11:11] RTM: Restricted Transactional Memory // [17:12] reserved // [18:18] RDSEED instruction support // [19:19] ADCX/ADOX instructions support // [31:20] reserved #define BX_CPUID_EXT3_FSGSBASE (1 << 0) #define BX_CPUID_EXT3_RESERVED1 (1 << 1) #define BX_CPUID_EXT3_RESERVED2 (1 << 2) #define BX_CPUID_EXT3_BMI1 (1 << 3) #define BX_CPUID_EXT3_HLE (1 << 4) #define BX_CPUID_EXT3_AVX2 (1 << 5) #define BX_CPUID_EXT3_RESERVED6 (1 << 6) #define BX_CPUID_EXT3_SMEP (1 << 7) #define BX_CPUID_EXT3_BMI2 (1 << 8) #define BX_CPUID_EXT3_ENCHANCED_REP_STRINGS (1 << 9) #define BX_CPUID_EXT3_INVPCID (1 << 10) #define BX_CPUID_EXT3_RTM (1 << 11) #define BX_CPUID_EXT3_RESERVED12 (1 << 12) #define BX_CPUID_EXT3_RESERVED13 (1 << 13) #define BX_CPUID_EXT3_RESERVED14 (1 << 14) #define BX_CPUID_EXT3_RESERVED15 (1 << 15) #define BX_CPUID_EXT3_RESERVED16 (1 << 16) #define BX_CPUID_EXT3_RESERVED17 (1 << 17) #define BX_CPUID_EXT3_RDSEED (1 << 18) #define BX_CPUID_EXT3_ADX (1 << 19) // ... // CPUID defines - STD2 features CPUID[0x80000001].EDX // ----------------------------- // ... #define BX_CPUID_STD2_SYSCALL_SYSRET (1 << 11) // ... #define BX_CPUID_STD2_NX (1 << 20) #define BX_CPUID_STD2_RESERVED21 (1 << 21) #define BX_CPUID_STD2_AMD_MMX_EXT (1 << 22) #define BX_CPUID_STD2_RESERVED23 (1 << 23) #define BX_CPUID_STD2_RESERVED24 (1 << 24) #define BX_CPUID_STD2_FFXSR (1 << 25) #define BX_CPUID_STD2_1G_PAGES (1 << 26) #define BX_CPUID_STD2_RDTSCP (1 << 27) #define BX_CPUID_STD2_RESERVED28 (1 << 28) #define BX_CPUID_STD2_LONG_MODE (1 << 29) #define BX_CPUID_STD2_3DNOW_EXT (1 << 30) #define BX_CPUID_STD2_3DNOW (1 << 31) // CPUID defines - EXT2 features CPUID[0x80000001].ECX // ----------------------------- // [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [10:10] IBS: Instruction based sampling // [11:11] XOP: Extended Operations Support and XOP Prefix // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [14:14] reserved // [15:15] LWP: Light weight profiling // [16:16] FMA4: Four-operand FMA instructions support // [18:17] reserved // [19:19] NodeId: Indicates support for NodeId MSR (0xc001100c) // [20:20] reserved // [21:21] TBM: trailing bit manipulation instruction support // [22:22] Topology extensions support // [31:23] reserved #define BX_CPUID_EXT2_LAHF_SAHF (1 << 0) #define BX_CPUID_EXT2_CMP_LEGACY (1 << 1) #define BX_CPUID_EXT2_SVM (1 << 2) #define BX_CPUID_EXT2_EXT_APIC_SPACE (1 << 3) #define BX_CPUID_EXT2_ALT_MOV_CR8 (1 << 4) #define BX_CPUID_EXT2_LZCNT (1 << 5) #define BX_CPUID_EXT2_SSE4A (1 << 6) #define BX_CPUID_EXT2_MISALIGNED_SSE (1 << 7) #define BX_CPUID_EXT2_PREFETCHW (1 << 8) #define BX_CPUID_EXT2_OSVW (1 << 9) #define BX_CPUID_EXT2_IBS (1 << 10) #define BX_CPUID_EXT2_XOP (1 << 11) #define BX_CPUID_EXT2_SKINIT (1 << 12) #define BX_CPUID_EXT2_WDT (1 << 13) #define BX_CPUID_EXT2_RESERVED14 (1 << 14) #define BX_CPUID_EXT2_LWP (1 << 15) #define BX_CPUID_EXT2_FMA4 (1 << 16) #define BX_CPUID_EXT2_RESERVED17 (1 << 17) #define BX_CPUID_EXT2_RESERVED18 (1 << 18) #define BX_CPUID_EXT2_NODEID (1 << 19) #define BX_CPUID_EXT2_RESERVED20 (1 << 20) #define BX_CPUID_EXT2_TBM (1 << 21) #define BX_CPUID_EXT2_TOPOLOGY_EXTENSIONS (1 << 22) // CPUID defines - SVM features CPUID[0x8000000A].EDX // ---------------------------- // [0:0] NP - Nested paging support // [1:1] LBR virtualization // [2:2] SVM Lock // [3:3] NRIPS - Next RIP save on VMEXIT // [4:4] TscRate - MSR based TSC ratio control // [5:5] VMCB Clean bits support // [6:6] Flush by ASID support // [7:7] Decode assists support // [8:8] Reserved // [9:9] Reserved // [10:10] Pause filter support // [11:11] Reserved // [12:12] Pause filter threshold support #define BX_CPUID_SVM_NESTED_PAGING (1 << 0) #define BX_CPUID_SVM_LBR_VIRTUALIZATION (1 << 1) #define BX_CPUID_SVM_SVM_LOCK (1 << 2) #define BX_CPUID_SVM_NRIP_SAVE (1 << 3) #define BX_CPUID_SVM_TSCRATE (1 << 4) #define BX_CPUID_SVM_VMCB_CLEAN_BITS (1 << 5) #define BX_CPUID_SVM_FLUSH_BY_ASID (1 << 6) #define BX_CPUID_SVM_DECODE_ASSIST (1 << 7) #define BX_CPUID_SVM_RESERVED8 (1 << 8) #define BX_CPUID_SVM_RESERVED9 (1 << 9) #define BX_CPUID_SVM_PAUSE_FILTER (1 << 10) #define BX_CPUID_SVM_RESERVED11 (1 << 11) #define BX_CPUID_SVM_PAUSE_FILTER_THRESHOLD (1 << 12) #endif bochs-2.6/cpu/data_xfer8.cc0000644000175000017500000000735512020641453015467 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: data_xfer8.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RLIb(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), i->Ib()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RHIb(bxInstruction_c *i) { BX_WRITE_8BIT_REGH(i->dst() & 0x3, i->Ib()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_byte(i->seg(), eaddr, BX_READ_8BIT_REGx(i->src(), i->extend8bitL())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GbEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u val8 = read_virtual_byte(i->seg(), eaddr); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), val8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GbEbR(bxInstruction_c *i) { Bit8u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_ALOd(bxInstruction_c *i) { AL = read_virtual_byte_32(i->seg(), i->Id()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OdAL(bxInstruction_c *i) { write_virtual_byte_32(i->seg(), i->Id(), AL); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EbIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_byte(i->seg(), eaddr, i->Ib()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XLAT(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->as64L()) { AL = read_virtual_byte_64(i->seg(), RBX + AL); } else #endif if (i->as32L()) { AL = read_virtual_byte(i->seg(), (Bit32u) (EBX + AL)); } else { AL = read_virtual_byte_32(i->seg(), (Bit16u) (BX + AL)); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EbGbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op1 = read_RMW_virtual_byte(i->seg(), eaddr); Bit8u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); write_RMW_virtual_byte(op2); BX_WRITE_8BIT_REGx(i->src(), i->extend8bitL(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EbGbR(bxInstruction_c *i) { Bit8u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit8u op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); BX_WRITE_8BIT_REGx(i->src(), i->extend8bitL(), op1); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op2); BX_NEXT_INSTR(i); } bochs-2.6/cpu/data_xfer16.cc0000644000175000017500000002352012020641453015536 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: data_xfer16.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RXIw(bxInstruction_c *i) { BX_WRITE_16BIT_REG(i->dst(), i->Iw()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_RXAX(bxInstruction_c *i) { Bit16u temp16 = AX; AX = BX_READ_16BIT_REG(i->dst()); BX_WRITE_16BIT_REG(i->dst(), temp16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwGwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), eaddr, BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GwEwR(bxInstruction_c *i) { BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GwEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u val16 = read_virtual_word(i->seg(), eaddr); BX_WRITE_16BIT_REG(i->dst(), val16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwSwR(bxInstruction_c *i) { /* Illegal to use nonexisting segments */ if (i->src() >= 6) { BX_INFO(("MOV_EwSw: using of nonexisting segment register %d", i->src())); exception(BX_UD_EXCEPTION, 0); } Bit16u seg_reg = BX_CPU_THIS_PTR sregs[i->src()].selector.value; if (i->os32L()) { BX_WRITE_32BIT_REGZ(i->dst(), seg_reg); } else { BX_WRITE_16BIT_REG(i->dst(), seg_reg); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwSwM(bxInstruction_c *i) { /* Illegal to use nonexisting segments */ if (i->src() >= 6) { BX_INFO(("MOV_EwSw: using of nonexisting segment register %d", i->src())); exception(BX_UD_EXCEPTION, 0); } bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u seg_reg = BX_CPU_THIS_PTR sregs[i->src()].selector.value; write_virtual_word(i->seg(), eaddr, seg_reg); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_SwEw(bxInstruction_c *i) { Bit16u op2_16; /* Attempt to load CS or nonexisting segment register */ if (i->dst() >= 6 || i->dst() == BX_SEG_REG_CS) { BX_INFO(("MOV_EwSw: can't use this segment register %d", i->dst())); exception(BX_UD_EXCEPTION, 0); } if (i->modC0()) { op2_16 = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op2_16 = read_virtual_word(i->seg(), eaddr); } load_seg_reg(&BX_CPU_THIS_PTR sregs[i->dst()], op2_16); if (i->dst() == BX_SEG_REG_SS) { // MOV SS inhibits interrupts, debug exceptions and single-step // trap exceptions until the execution boundary following the // next instruction is reached. // Same code as POP_SS() inhibit_interrupts(BX_INHIBIT_INTERRUPTS_BY_MOVSS); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LEA_GwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); BX_WRITE_16BIT_REG(i->dst(), (Bit16u) eaddr); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_AXOd(bxInstruction_c *i) { AX = read_virtual_word_32(i->seg(), i->Id()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OdAX(bxInstruction_c *i) { write_virtual_word_32(i->seg(), i->Id(), AX); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EwIwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), eaddr, i->Iw()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GwEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op2_8 = read_virtual_byte(i->seg(), eaddr); /* zero extend byte op2 into word op1 */ BX_WRITE_16BIT_REG(i->dst(), (Bit16u) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GwEbR(bxInstruction_c *i) { Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); /* zero extend byte op2 into word op1 */ BX_WRITE_16BIT_REG(i->dst(), (Bit16u) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GwEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op2_8 = read_virtual_byte(i->seg(), eaddr); /* sign extend byte op2 into word op1 */ BX_WRITE_16BIT_REG(i->dst(), (Bit8s) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GwEbR(bxInstruction_c *i) { Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(),i->extend8bitL()); /* sign extend byte op2 into word op1 */ BX_WRITE_16BIT_REG(i->dst(), (Bit8s) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EwGwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op2_16 = BX_READ_16BIT_REG(i->src()); write_RMW_virtual_word(op2_16); BX_WRITE_16BIT_REG(i->src(), op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EwGwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; #if BX_DEBUGGER // Note for mortals: the instruction to trigger this is "xchgw %bx,%bx" if (bx_dbg.magic_break_enabled && (i->src() == 3) && (i->dst() == 3)) { BX_CPU_THIS_PTR magic_break = 1; BX_NEXT_INSTR(i); } #endif op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); BX_WRITE_16BIT_REG(i->src(), op1_16); BX_WRITE_16BIT_REG(i->dst(), op2_16); BX_NEXT_INSTR(i); } // Note: CMOV accesses a memory source operand (read), regardless // of whether condition is true or not. Thus, exceptions may // occur even if the MOV does not take place. BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVO_GwEwR(bxInstruction_c *i) { if (get_OF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNO_GwEwR(bxInstruction_c *i) { if (!get_OF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVB_GwEwR(bxInstruction_c *i) { if (get_CF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNB_GwEwR(bxInstruction_c *i) { if (!get_CF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVZ_GwEwR(bxInstruction_c *i) { if (get_ZF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNZ_GwEwR(bxInstruction_c *i) { if (!get_ZF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVBE_GwEwR(bxInstruction_c *i) { if (get_CF() || get_ZF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNBE_GwEwR(bxInstruction_c *i) { if (! (get_CF() || get_ZF())) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVS_GwEwR(bxInstruction_c *i) { if (get_SF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNS_GwEwR(bxInstruction_c *i) { if (!get_SF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVP_GwEwR(bxInstruction_c *i) { if (get_PF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNP_GwEwR(bxInstruction_c *i) { if (!get_PF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVL_GwEwR(bxInstruction_c *i) { if (getB_SF() != getB_OF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNL_GwEwR(bxInstruction_c *i) { if (getB_SF() == getB_OF()) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVLE_GwEwR(bxInstruction_c *i) { if (get_ZF() || (getB_SF() != getB_OF())) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNLE_GwEwR(bxInstruction_c *i) { if (! get_ZF() && (getB_SF() == getB_OF())) BX_WRITE_16BIT_REG(i->dst(), BX_READ_16BIT_REG(i->src())); BX_NEXT_INSTR(i); } bochs-2.6/cpu/tasking.cc0000644000175000017500000010032512020641453015071 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: tasking.cc 11299 2012-07-26 16:03:26Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR // Notes: // ====== // ====================== // 286 Task State Segment // ====================== // dynamic item | hex dec offset // 0 task LDT selector | 2a 42 // 1 DS selector | 28 40 // 1 SS selector | 26 38 // 1 CS selector | 24 36 // 1 ES selector | 22 34 // 1 DI | 20 32 // 1 SI | 1e 30 // 1 BP | 1c 28 // 1 SP | 1a 26 // 1 BX | 18 24 // 1 DX | 16 22 // 1 CX | 14 20 // 1 AX | 12 18 // 1 flag word | 10 16 // 1 IP (entry point) | 0e 14 // 0 SS for CPL 2 | 0c 12 // 0 SP for CPL 2 | 0a 10 // 0 SS for CPL 1 | 08 08 // 0 SP for CPL 1 | 06 06 // 0 SS for CPL 0 | 04 04 // 0 SP for CPL 0 | 02 02 // back link selector to TSS | 00 00 // ====================== // 386 Task State Segment // ====================== // |31 16|15 0| hex dec // |I/O Map Base |000000000000000000000|T| 64 100 static // |0000000000000000| LDT | 60 96 static // |0000000000000000| GS selector | 5c 92 dynamic // |0000000000000000| FS selector | 58 88 dynamic // |0000000000000000| DS selector | 54 84 dynamic // |0000000000000000| SS selector | 50 80 dynamic // |0000000000000000| CS selector | 4c 76 dynamic // |0000000000000000| ES selector | 48 72 dynamic // | EDI | 44 68 dynamic // | ESI | 40 64 dynamic // | EBP | 3c 60 dynamic // | ESP | 38 56 dynamic // | EBX | 34 52 dynamic // | EDX | 30 48 dynamic // | ECX | 2c 44 dynamic // | EAX | 28 40 dynamic // | EFLAGS | 24 36 dynamic // | EIP (entry point) | 20 32 dynamic // | CR3 (PDPR) | 1c 28 static // |000000000000000 | SS for CPL 2 | 18 24 static // | ESP for CPL 2 | 14 20 static // |000000000000000 | SS for CPL 1 | 10 16 static // | ESP for CPL 1 | 0c 12 static // |000000000000000 | SS for CPL 0 | 08 08 static // | ESP for CPL 0 | 04 04 static // |000000000000000 | back link to prev TSS | 00 00 dynamic (updated only when return expected) // ================================================== // Effect of task switch on Busy, NT, and Link Fields // ================================================== // Field jump call/interrupt iret // ------------------------------------------------------ // new busy bit Set Set No change // old busy bit Cleared No change Cleared // new NT flag No change Set No change // old NT flag No change No change Cleared // new link No change old TSS selector No change // old link No change No change No change // CR0.TS Set Set Set // Note: I checked 386, 486, and Pentium, and they all exhibited // exactly the same behaviour as above. There seems to // be some misprints in the Intel docs. void BX_CPU_C::task_switch(bxInstruction_c *i, bx_selector_t *tss_selector, bx_descriptor_t *tss_descriptor, unsigned source, Bit32u dword1, Bit32u dword2, bx_bool push_error, Bit32u error_code) { Bit32u obase32; // base address of old TSS Bit32u nbase32; // base address of new TSS Bit32u temp32, newCR3; Bit16u raw_cs_selector, raw_ss_selector, raw_ds_selector, raw_es_selector, raw_fs_selector, raw_gs_selector, raw_ldt_selector; Bit16u trap_word; bx_selector_t cs_selector, ss_selector, ds_selector, es_selector, fs_selector, gs_selector, ldt_selector; bx_descriptor_t cs_descriptor, ss_descriptor, ldt_descriptor; Bit32u old_TSS_max, new_TSS_max, old_TSS_limit, new_TSS_limit; Bit32u newEAX, newECX, newEDX, newEBX; Bit32u newESP, newEBP, newESI, newEDI; Bit32u newEFLAGS, newEIP; BX_DEBUG(("TASKING: ENTER")); invalidate_prefetch_q(); // Discard any traps and inhibits for new context; traps will // resume upon return. BX_CPU_THIS_PTR debug_trap = 0; BX_CPU_THIS_PTR inhibit_mask = 0; // STEP 1: The following checks are made before calling task_switch(), // for JMP & CALL only. These checks are NOT made for exceptions, // interrupts & IRET. // // 1) TSS DPL must be >= CPL // 2) TSS DPL must be >= TSS selector RPL // 3) TSS descriptor is not busy. // STEP 2: The processor performs limit-checking on the target TSS // to verify that the TSS limit is greater than or equal // to 67h (2Bh for 16-bit TSS). // Gather info about new TSS if (tss_descriptor->type <= 3) { // {1,3} new_TSS_max = 0x2B; } else { // tss_descriptor->type = {9,11} new_TSS_max = 0x67; } nbase32 = (Bit32u) tss_descriptor->u.segment.base; new_TSS_limit = tss_descriptor->u.segment.limit_scaled; if (new_TSS_limit < new_TSS_max) { BX_ERROR(("task_switch(): new TSS limit < %d", new_TSS_max)); exception(BX_TS_EXCEPTION, tss_selector->value & 0xfffc); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_TASK_SWITCH)) SvmInterceptTaskSwitch(tss_selector->value, source, push_error, error_code); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_TaskSwitch(tss_selector->value, source); #endif // Gather info about old TSS if (BX_CPU_THIS_PTR tr.cache.type <= 3) { old_TSS_max = 0x29; } else { old_TSS_max = 0x5F; } obase32 = (Bit32u) BX_CPU_THIS_PTR tr.cache.u.segment.base; // old TSS.base old_TSS_limit = BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled; if (old_TSS_limit < old_TSS_max) { BX_ERROR(("task_switch(): old TSS limit < %d", old_TSS_max)); exception(BX_TS_EXCEPTION, BX_CPU_THIS_PTR tr.selector.value & 0xfffc); } if (obase32 == nbase32) { BX_INFO(("TASK SWITCH: switching to the same TSS !")); } // Check that old TSS, new TSS, and all segment descriptors // used in the task switch are paged in. if (BX_CPU_THIS_PTR cr0.get_PG()) { translate_linear(nbase32, 0, BX_READ); // old TSS translate_linear(nbase32 + new_TSS_max, 0, BX_READ); // ??? Humm, we check the new TSS region with READ above, // but sometimes we need to write the link field in that // region. We also sometimes update other fields, perhaps // we need to WRITE check them here also, so that we keep // the written state consistent (ie, we don't encounter a // page fault in the middle). if (source == BX_TASK_FROM_CALL || source == BX_TASK_FROM_INT) { translate_linear(nbase32, 0, BX_WRITE); translate_linear(nbase32 + 1, 0, BX_WRITE); } } // Privilege and busy checks done in CALL, JUMP, INT, IRET // Step 3: If JMP or IRET, clear busy bit in old task TSS descriptor, // otherwise leave set. // effect on Busy bit of old task if (source == BX_TASK_FROM_JUMP || source == BX_TASK_FROM_IRET) { // Bit is cleared Bit32u laddr = (Bit32u) BX_CPU_THIS_PTR gdtr.base + (BX_CPU_THIS_PTR tr.selector.index<<3) + 4; access_read_linear(laddr, 4, 0, BX_RW, &temp32); temp32 &= ~0x200; access_write_linear(laddr, 4, 0, &temp32); } // STEP 4: If the task switch was initiated with an IRET instruction, // clears the NT flag in a temporarily saved EFLAGS image; // if initiated with a CALL or JMP instruction, an exception, or // an interrupt, the NT flag is left unchanged. Bit32u oldEFLAGS = read_eflags(); /* if moving to busy task, clear NT bit */ if (tss_descriptor->type == BX_SYS_SEGMENT_BUSY_286_TSS || tss_descriptor->type == BX_SYS_SEGMENT_BUSY_386_TSS) { oldEFLAGS &= ~EFlagsNTMask; } // STEP 5: Save the current task state in the TSS. Up to this point, // any exception that occurs aborts the task switch without // changing the processor state. /* save current machine state in old task's TSS */ if (BX_CPU_THIS_PTR tr.cache.type <= 3) { // check that we won't page fault while writing if (BX_CPU_THIS_PTR cr0.get_PG()) { translate_linear(Bit32u(obase32 + 14), 0, BX_WRITE); translate_linear(Bit32u(obase32 + 41), 0, BX_WRITE); } system_write_word(Bit32u(obase32 + 14), IP); system_write_word(Bit32u(obase32 + 16), oldEFLAGS); system_write_word(Bit32u(obase32 + 18), AX); system_write_word(Bit32u(obase32 + 20), CX); system_write_word(Bit32u(obase32 + 22), DX); system_write_word(Bit32u(obase32 + 24), BX); system_write_word(Bit32u(obase32 + 26), SP); system_write_word(Bit32u(obase32 + 28), BP); system_write_word(Bit32u(obase32 + 30), SI); system_write_word(Bit32u(obase32 + 32), DI); system_write_word(Bit32u(obase32 + 34), BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value); system_write_word(Bit32u(obase32 + 36), BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); system_write_word(Bit32u(obase32 + 38), BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value); system_write_word(Bit32u(obase32 + 40), BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value); } else { // check that we won't page fault while writing if (BX_CPU_THIS_PTR cr0.get_PG()) { translate_linear(Bit32u(obase32 + 0x20), 0, BX_WRITE); translate_linear(Bit32u(obase32 + 0x5d), 0, BX_WRITE); } system_write_dword(Bit32u(obase32 + 0x20), EIP); system_write_dword(Bit32u(obase32 + 0x24), oldEFLAGS); system_write_dword(Bit32u(obase32 + 0x28), EAX); system_write_dword(Bit32u(obase32 + 0x2c), ECX); system_write_dword(Bit32u(obase32 + 0x30), EDX); system_write_dword(Bit32u(obase32 + 0x34), EBX); system_write_dword(Bit32u(obase32 + 0x38), ESP); system_write_dword(Bit32u(obase32 + 0x3c), EBP); system_write_dword(Bit32u(obase32 + 0x40), ESI); system_write_dword(Bit32u(obase32 + 0x44), EDI); system_write_word(Bit32u(obase32 + 0x48), BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value); system_write_word(Bit32u(obase32 + 0x4c), BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); system_write_word(Bit32u(obase32 + 0x50), BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value); system_write_word(Bit32u(obase32 + 0x54), BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value); system_write_word(Bit32u(obase32 + 0x58), BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value); system_write_word(Bit32u(obase32 + 0x5c), BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value); } // effect on link field of new task if (source == BX_TASK_FROM_CALL || source == BX_TASK_FROM_INT) { // set to selector of old task's TSS system_write_word(nbase32, BX_CPU_THIS_PTR tr.selector.value); } // STEP 6: The new-task state is loaded from the TSS if (tss_descriptor->type <= 3) { newEIP = system_read_word(Bit32u(nbase32 + 14)); newEFLAGS = system_read_word(Bit32u(nbase32 + 16)); // incoming TSS is 16bit: // - upper word of general registers is set to 0xFFFF // - upper word of eflags is zero'd // - FS, GS are zero'd // - upper word of eIP is zero'd Bit16u temp16 = system_read_word(Bit32u(nbase32 + 18)); newEAX = 0xffff0000 | temp16; temp16 = system_read_word(Bit32u(nbase32 + 20)); newECX = 0xffff0000 | temp16; temp16 = system_read_word(Bit32u(nbase32 + 22)); newEDX = 0xffff0000 | temp16; temp16 = system_read_word(Bit32u(nbase32 + 24)); newEBX = 0xffff0000 | temp16; temp16 = system_read_word(Bit32u(nbase32 + 26)); newESP = 0xffff0000 | temp16; temp16 = system_read_word(Bit32u(nbase32 + 28)); newEBP = 0xffff0000 | temp16; temp16 = system_read_word(Bit32u(nbase32 + 30)); newESI = 0xffff0000 | temp16; temp16 = system_read_word(Bit32u(nbase32 + 32)); newEDI = 0xffff0000 | temp16; raw_es_selector = system_read_word(Bit32u(nbase32 + 34)); raw_cs_selector = system_read_word(Bit32u(nbase32 + 36)); raw_ss_selector = system_read_word(Bit32u(nbase32 + 38)); raw_ds_selector = system_read_word(Bit32u(nbase32 + 40)); raw_ldt_selector = system_read_word(Bit32u(nbase32 + 42)); raw_fs_selector = 0; // use a NULL selector raw_gs_selector = 0; // use a NULL selector // No CR3 change for 286 task switch newCR3 = 0; // keep compiler happy (not used) trap_word = 0; // keep compiler happy (not used) } else { if (BX_CPU_THIS_PTR cr0.get_PG()) newCR3 = system_read_dword(Bit32u(nbase32 + 0x1c)); else newCR3 = 0; // keep compiler happy (not used) newEIP = system_read_dword(Bit32u(nbase32 + 0x20)); newEFLAGS = system_read_dword(Bit32u(nbase32 + 0x24)); newEAX = system_read_dword(Bit32u(nbase32 + 0x28)); newECX = system_read_dword(Bit32u(nbase32 + 0x2c)); newEDX = system_read_dword(Bit32u(nbase32 + 0x30)); newEBX = system_read_dword(Bit32u(nbase32 + 0x34)); newESP = system_read_dword(Bit32u(nbase32 + 0x38)); newEBP = system_read_dword(Bit32u(nbase32 + 0x3c)); newESI = system_read_dword(Bit32u(nbase32 + 0x40)); newEDI = system_read_dword(Bit32u(nbase32 + 0x44)); raw_es_selector = system_read_word(Bit32u(nbase32 + 0x48)); raw_cs_selector = system_read_word(Bit32u(nbase32 + 0x4c)); raw_ss_selector = system_read_word(Bit32u(nbase32 + 0x50)); raw_ds_selector = system_read_word(Bit32u(nbase32 + 0x54)); raw_fs_selector = system_read_word(Bit32u(nbase32 + 0x58)); raw_gs_selector = system_read_word(Bit32u(nbase32 + 0x5c)); raw_ldt_selector = system_read_word(Bit32u(nbase32 + 0x60)); trap_word = system_read_word(Bit32u(nbase32 + 0x64)); } // Step 7: If CALL, interrupt, or JMP, set busy flag in new task's // TSS descriptor. If IRET, leave set. if (source != BX_TASK_FROM_IRET) { // set the new task's busy bit Bit32u laddr = (Bit32u)(BX_CPU_THIS_PTR gdtr.base) + (tss_selector->index<<3) + 4; access_read_linear(laddr, 4, 0, BX_RW, &dword2); dword2 |= 0x200; access_write_linear(laddr, 4, 0, &dword2); } // // Commit point. At this point, we commit to the new // context. If an unrecoverable error occurs in further // processing, we complete the task switch without performing // additional access and segment availablility checks and // generate the appropriate exception prior to beginning // execution of the new task. // // Step 8: Load the task register with the segment selector and // descriptor for the new task TSS. BX_CPU_THIS_PTR tr.selector = *tss_selector; BX_CPU_THIS_PTR tr.cache = *tss_descriptor; BX_CPU_THIS_PTR tr.cache.type |= 2; // mark TSS in TR as busy // Step 9: Set TS flag in the CR0 image stored in the new task TSS. BX_CPU_THIS_PTR cr0.set_TS(1); // Task switch clears LE/L3/L2/L1/L0 in DR7 BX_CPU_THIS_PTR dr7.val32 &= ~0x00000155; // Step 10: If call or interrupt, set the NT flag in the eflags // image stored in new task's TSS. If IRET or JMP, // NT is restored from new TSS eflags image. (no change) // effect on NT flag of new task if (source == BX_TASK_FROM_CALL || source == BX_TASK_FROM_INT) { newEFLAGS |= EFlagsNTMask; // NT flag is set } // Step 11: Load the new task (dynamic) state from new TSS. // Any errors associated with loading and qualification of // segment descriptors in this step occur in the new task's // context. State loaded here includes LDTR, CR3, // EFLAGS, EIP, general purpose registers, and segment // descriptor parts of the segment registers. BX_CPU_THIS_PTR prev_rip = EIP = newEIP; EAX = newEAX; ECX = newECX; EDX = newEDX; EBX = newEBX; ESP = newESP; EBP = newEBP; ESI = newESI; EDI = newEDI; BX_CPU_THIS_PTR speculative_rsp = 0; writeEFlags(newEFLAGS, EFlagsValidMask); // Fill in selectors for all segment registers. If errors // occur later, the selectors will at least be loaded. parse_selector(raw_cs_selector, &cs_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector = cs_selector; parse_selector(raw_ss_selector, &ss_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector = ss_selector; parse_selector(raw_ds_selector, &ds_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector = ds_selector; parse_selector(raw_es_selector, &es_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector = es_selector; parse_selector(raw_fs_selector, &fs_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector = fs_selector; parse_selector(raw_gs_selector, &gs_selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector = gs_selector; parse_selector(raw_ldt_selector, &ldt_selector); BX_CPU_THIS_PTR ldtr.selector = ldt_selector; // Start out with invalid descriptor caches, fill in with // values only as they are validated BX_CPU_THIS_PTR ldtr.cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid = 0; if ((tss_descriptor->type >= 9) && BX_CPU_THIS_PTR cr0.get_PG()) { // change CR3 only if it actually modified if (newCR3 != BX_CPU_THIS_PTR cr3) { BX_DEBUG(("task_switch changing CR3 to 0x%08x", newCR3)); if (! SetCR3(newCR3)) // Tell paging unit about new cr3 value exception(BX_TS_EXCEPTION, 0); #if BX_CPU_LEVEL >= 6 if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE()) { if (! CheckPDPTR(newCR3)) { BX_ERROR(("task_switch(exception after commit point): PDPTR check failed !")); // clear PDPTRs before raising task switch exception for (unsigned n=0; n<4; n++) BX_CPU_THIS_PTR PDPTR_CACHE.entry[n] = 0; exception(BX_TS_EXCEPTION, 0); } } #endif BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_TASK_SWITCH, newCR3); } } unsigned save_CPL = CPL; /* set CPL to 3 to force a privilege level change and stack switch if SS is not properly loaded */ CPL = 3; // LDTR if (ldt_selector.ti) { // LDT selector must be in GDT BX_INFO(("task_switch(exception after commit point): bad LDT selector TI=1")); exception(BX_TS_EXCEPTION, raw_ldt_selector & 0xfffc); } if ((raw_ldt_selector & 0xfffc) != 0) { bx_bool good = fetch_raw_descriptor2(&ldt_selector, &dword1, &dword2); if (!good) { BX_ERROR(("task_switch(exception after commit point): bad LDT fetch")); exception(BX_TS_EXCEPTION, raw_ldt_selector & 0xfffc); } parse_descriptor(dword1, dword2, &ldt_descriptor); // LDT selector of new task is valid, else #TS(new task's LDT) if (ldt_descriptor.valid==0 || ldt_descriptor.type!=BX_SYS_SEGMENT_LDT || ldt_descriptor.segment) { BX_ERROR(("task_switch(exception after commit point): bad LDT segment")); exception(BX_TS_EXCEPTION, raw_ldt_selector & 0xfffc); } // LDT of new task is present in memory, else #TS(new tasks's LDT) if (! IS_PRESENT(ldt_descriptor)) { BX_ERROR(("task_switch(exception after commit point): LDT not present")); exception(BX_TS_EXCEPTION, raw_ldt_selector & 0xfffc); } // All checks pass, fill in LDTR shadow cache BX_CPU_THIS_PTR ldtr.cache = ldt_descriptor; } else { // NULL LDT selector is OK, leave cache invalid } if (v8086_mode()) { // load seg regs as 8086 registers load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], raw_ss_selector); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS], raw_ds_selector); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES], raw_es_selector); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS], raw_fs_selector); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS], raw_gs_selector); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], raw_cs_selector); // CPL is set from CS selector } else { // SS if ((raw_ss_selector & 0xfffc) != 0) { bx_bool good = fetch_raw_descriptor2(&ss_selector, &dword1, &dword2); if (!good) { BX_ERROR(("task_switch(exception after commit point): bad SS fetch")); exception(BX_TS_EXCEPTION, raw_ss_selector & 0xfffc); } parse_descriptor(dword1, dword2, &ss_descriptor); // SS selector must be within its descriptor table limits else #TS(SS) // SS descriptor AR byte must must indicate writable data segment, // else #TS(SS) if (ss_descriptor.valid==0 || ss_descriptor.segment==0 || IS_CODE_SEGMENT(ss_descriptor.type) || !IS_DATA_SEGMENT_WRITEABLE(ss_descriptor.type)) { BX_ERROR(("task_switch(exception after commit point): SS not valid or writeable segment")); exception(BX_TS_EXCEPTION, raw_ss_selector & 0xfffc); } // // Stack segment is present in memory, else #SS(new stack segment) // if (! IS_PRESENT(ss_descriptor)) { BX_ERROR(("task_switch(exception after commit point): SS not present")); exception(BX_SS_EXCEPTION, raw_ss_selector & 0xfffc); } // Stack segment DPL matches CS.RPL, else #TS(new stack segment) if (ss_descriptor.dpl != cs_selector.rpl) { BX_ERROR(("task_switch(exception after commit point): SS.rpl != CS.RPL")); exception(BX_TS_EXCEPTION, raw_ss_selector & 0xfffc); } // Stack segment DPL matches selector RPL, else #TS(new stack segment) if (ss_descriptor.dpl != ss_selector.rpl) { BX_ERROR(("task_switch(exception after commit point): SS.dpl != SS.rpl")); exception(BX_TS_EXCEPTION, raw_ss_selector & 0xfffc); } touch_segment(&ss_selector, &ss_descriptor); // All checks pass, fill in shadow cache BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache = ss_descriptor; invalidate_stack_cache(); } else { // SS selector is valid, else #TS(new stack segment) BX_ERROR(("task_switch(exception after commit point): SS NULL")); exception(BX_TS_EXCEPTION, raw_ss_selector & 0xfffc); } CPL = save_CPL; task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS], &ds_selector, raw_ds_selector, cs_selector.rpl); task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES], &es_selector, raw_es_selector, cs_selector.rpl); task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS], &fs_selector, raw_fs_selector, cs_selector.rpl); task_switch_load_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS], &gs_selector, raw_gs_selector, cs_selector.rpl); // if new selector is not null then perform following checks: // index must be within its descriptor table limits else #TS(selector) // AR byte must indicate data or readable code else #TS(selector) // if data or non-conforming code then: // DPL must be >= CPL else #TS(selector) // DPL must be >= RPL else #TS(selector) // AR byte must indicate PRESENT else #NP(selector) // load cache with new segment descriptor and set valid bit // CS if ((raw_cs_selector & 0xfffc) != 0) { bx_bool good = fetch_raw_descriptor2(&cs_selector, &dword1, &dword2); if (!good) { BX_ERROR(("task_switch(exception after commit point): bad CS fetch")); exception(BX_TS_EXCEPTION, raw_cs_selector & 0xfffc); } parse_descriptor(dword1, dword2, &cs_descriptor); // CS descriptor AR byte must indicate code segment else #TS(CS) if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || IS_DATA_SEGMENT(cs_descriptor.type)) { BX_ERROR(("task_switch(exception after commit point): CS not valid executable seg")); exception(BX_TS_EXCEPTION, raw_cs_selector & 0xfffc); } // if non-conforming then DPL must equal selector RPL else #TS(CS) if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl != cs_selector.rpl) { BX_ERROR(("task_switch(exception after commit point): non-conforming: CS.dpl!=CS.RPL")); exception(BX_TS_EXCEPTION, raw_cs_selector & 0xfffc); } // if conforming then DPL must be <= selector RPL else #TS(CS) if (IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl > cs_selector.rpl) { BX_ERROR(("task_switch(exception after commit point): conforming: CS.dpl>RPL")); exception(BX_TS_EXCEPTION, raw_cs_selector & 0xfffc); } // Code segment is present in memory, else #NP(new code segment) if (! IS_PRESENT(cs_descriptor)) { BX_ERROR(("task_switch(exception after commit point): CS.p==0")); exception(BX_NP_EXCEPTION, raw_cs_selector & 0xfffc); } touch_segment(&cs_selector, &cs_descriptor); #ifdef BX_SUPPORT_CS_LIMIT_DEMOTION // Handle special case of CS.LIMIT demotion (new descriptor limit is smaller than current one) if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled > cs_descriptor.u.segment.limit_scaled) BX_CPU_THIS_PTR iCache.flushICacheEntries(); #endif // All checks pass, fill in shadow cache BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache = cs_descriptor; } else { // If new cs selector is null #TS(CS) BX_ERROR(("task_switch(exception after commit point): CS NULL")); exception(BX_TS_EXCEPTION, raw_cs_selector & 0xfffc); } updateFetchModeMask(/* CS reloaded */); #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(); // task switch, CPL was modified #endif } if (tss_descriptor->type >= 9 && (trap_word & 0x1)) { BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_TASK_SWITCH_BIT; // BT flag BX_CPU_THIS_PTR async_event = 1; // so processor knows to check BX_INFO(("task_switch: T bit set in new TSS")); } #if BX_CPU_LEVEL >= 6 handleSseModeChange(); /* CR0.TS changes */ #if BX_SUPPORT_AVX handleAvxModeChange(); #endif #endif // // Step 12: Begin execution of new task. // BX_DEBUG(("TASKING: LEAVE")); RSP_SPECULATIVE; // push error code onto stack if (push_error) { if (tss_descriptor->type >= 9) // TSS386 push_32(error_code); else push_16(error_code); } // instruction pointer must be in CS limit, else #GP(0) if (EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("task_switch: EIP > CS.limit")); exception(BX_GP_EXCEPTION, 0); } RSP_COMMIT; } void BX_CPU_C::task_switch_load_selector(bx_segment_reg_t *seg, bx_selector_t *selector, Bit16u raw_selector, Bit8u cs_rpl) { bx_descriptor_t descriptor; Bit32u dword1, dword2; // NULL selector is OK, will leave cache invalid if ((raw_selector & 0xfffc) != 0) { bx_bool good = fetch_raw_descriptor2(selector, &dword1, &dword2); if (!good) { BX_ERROR(("task_switch(%s): bad selector fetch !", strseg(seg))); exception(BX_TS_EXCEPTION, raw_selector & 0xfffc); } parse_descriptor(dword1, dword2, &descriptor); /* AR byte must indicate data or readable code segment else #TS(selector) */ if (descriptor.segment==0 || (IS_CODE_SEGMENT(descriptor.type) && IS_CODE_SEGMENT_READABLE(descriptor.type) == 0)) { BX_ERROR(("task_switch(%s): not data or readable code !", strseg(seg))); exception(BX_TS_EXCEPTION, raw_selector & 0xfffc); } /* If data or non-conforming code, then both the RPL and the CPL * must be less than or equal to DPL in AR byte else #GP(selector) */ if (IS_DATA_SEGMENT(descriptor.type) || IS_CODE_SEGMENT_NON_CONFORMING(descriptor.type)) { if ((selector->rpl > descriptor.dpl) || (cs_rpl > descriptor.dpl)) { BX_ERROR(("load_seg_reg(%s): RPL & CPL must be <= DPL", strseg(seg))); exception(BX_TS_EXCEPTION, raw_selector & 0xfffc); } } if (! IS_PRESENT(descriptor)) { BX_ERROR(("task_switch(%s): descriptor not present !", strseg(seg))); exception(BX_NP_EXCEPTION, raw_selector & 0xfffc); } touch_segment(selector, &descriptor); // All checks pass, fill in shadow cache seg->cache = descriptor; } } void BX_CPU_C::get_SS_ESP_from_TSS(unsigned pl, Bit16u *ss, Bit32u *esp) { if (BX_CPU_THIS_PTR tr.cache.valid==0) BX_PANIC(("get_SS_ESP_from_TSS: TR.cache invalid")); if (BX_CPU_THIS_PTR tr.cache.type==BX_SYS_SEGMENT_AVAIL_386_TSS || BX_CPU_THIS_PTR tr.cache.type==BX_SYS_SEGMENT_BUSY_386_TSS) { // 32-bit TSS Bit32u TSSstackaddr = 8*pl + 4; if ((TSSstackaddr+7) > BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled) { BX_DEBUG(("get_SS_ESP_from_TSS(386): TSSstackaddr > TSS.LIMIT")); exception(BX_TS_EXCEPTION, BX_CPU_THIS_PTR tr.selector.value & 0xfffc); } *ss = system_read_word (BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr + 4); *esp = system_read_dword(BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr); } else if (BX_CPU_THIS_PTR tr.cache.type==BX_SYS_SEGMENT_AVAIL_286_TSS || BX_CPU_THIS_PTR tr.cache.type==BX_SYS_SEGMENT_BUSY_286_TSS) { // 16-bit TSS Bit32u TSSstackaddr = 4*pl + 2; if ((TSSstackaddr+3) > BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled) { BX_DEBUG(("get_SS_ESP_from_TSS(286): TSSstackaddr > TSS.LIMIT")); exception(BX_TS_EXCEPTION, BX_CPU_THIS_PTR tr.selector.value & 0xfffc); } *ss = system_read_word(BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr + 2); *esp = (Bit32u) system_read_word(BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr); } else { BX_PANIC(("get_SS_ESP_from_TSS: TR is bogus type (%u)", (unsigned) BX_CPU_THIS_PTR tr.cache.type)); } } #if BX_SUPPORT_X86_64 Bit64u BX_CPU_C::get_RSP_from_TSS(unsigned pl) { if (BX_CPU_THIS_PTR tr.cache.valid==0) BX_PANIC(("get_RSP_from_TSS: TR.cache invalid")); // 32-bit TSS Bit32u TSSstackaddr = 8*pl + 4; if ((TSSstackaddr+7) > BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled) { BX_DEBUG(("get_RSP_from_TSS(): TSSstackaddr > TSS.LIMIT")); exception(BX_TS_EXCEPTION, BX_CPU_THIS_PTR tr.selector.value & 0xfffc); } Bit64u rsp = system_read_qword(BX_CPU_THIS_PTR tr.cache.u.segment.base + TSSstackaddr); if (! IsCanonical(rsp)) { BX_ERROR(("get_RSP_from_TSS: canonical address failure 0x%08x%08x", GET32H(rsp), GET32L(rsp))); exception(BX_SS_EXCEPTION, BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value & 0xfffc); } return rsp; } #endif // #if BX_SUPPORT_X86_64 bochs-2.6/cpu/generic_cpuid.h0000644000175000017500000001007412020641453016074 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: generic_cpuid.h 11169 2012-05-11 06:51:04Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_GENERIC_CPUID_DEFINITIONS_H #define BX_GENERIC_CPUID_DEFINITIONS_H #if BX_CPU_LEVEL >= 4 #include "cpu/cpuid.h" class bx_generic_cpuid_t : public bx_cpuid_t { public: bx_generic_cpuid_t(BX_CPU_C *cpu); virtual ~bx_generic_cpuid_t() {} // return CPU name virtual const char *get_name(void) const { return "bochs"; } virtual Bit64u get_isa_extensions_bitmask(void) const { return isa_extensions_bitmask; } virtual Bit32u get_cpu_extensions_bitmask(void) const { return cpu_extensions_bitmask; } #if BX_SUPPORT_VMX virtual Bit32u get_vmx_extensions_bitmask(void) const { return vmx_extensions_bitmask; } #endif #if BX_SUPPORT_SVM virtual Bit32u get_svm_extensions_bitmask(void) const { return svm_extensions_bitmask; } #endif virtual void get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const; virtual void dump_cpuid(void) const; private: void init_isa_extensions_bitmask(void); void init_cpu_extensions_bitmask(void); #if BX_SUPPORT_VMX void init_vmx_extensions_bitmask(void); #endif #if BX_SUPPORT_SVM void init_svm_extensions_bitmask(void); #endif Bit64u isa_extensions_bitmask; Bit32u cpu_extensions_bitmask; #if BX_SUPPORT_VMX Bit32u vmx_extensions_bitmask; #endif #if BX_SUPPORT_SVM Bit32u svm_extensions_bitmask; #endif unsigned max_std_leaf; unsigned max_ext_leaf; void get_std_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_1(cpuid_function_t *leaf) const; #if BX_CPU_LEVEL >= 6 void get_std_cpuid_leaf_2(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_leaf_A(cpuid_function_t *leaf) const; void get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const; void get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const; void get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const; #if BX_SUPPORT_SVM void get_ext_cpuid_leaf_A(cpuid_function_t *leaf) const; #endif Bit32u get_std2_cpuid_features(void) const; Bit32u get_ext2_cpuid_features(void) const; Bit32u get_ext3_cpuid_features(void) const; Bit32u get_extended_cpuid_features(void) const; #endif Bit32u get_cpu_version_information(void) const; Bit32u get_std_cpuid_features(void) const; }; extern bx_cpuid_t *create_bx_generic_cpuid(BX_CPU_C *cpu); #endif // BX_CPU_LEVEL >= 4 #endif bochs-2.6/cpu/bit.cc0000644000175000017500000002430712020641453014214 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bit.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 3 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETO_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = getB_OF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETO_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), getB_OF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNO_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !getB_OF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNO_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), !getB_OF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETB_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = getB_CF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETB_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), getB_CF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNB_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !getB_CF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNB_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), !getB_CF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETZ_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = getB_ZF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETZ_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), getB_ZF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNZ_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !getB_ZF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNZ_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), !getB_ZF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETBE_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = (getB_CF() | getB_ZF()); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETBE_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), (getB_CF() | getB_ZF())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNBE_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !(getB_CF() | getB_ZF()); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNBE_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), !(getB_CF() | getB_ZF())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETS_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = getB_SF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETS_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), getB_SF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNS_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !getB_SF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNS_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), !getB_SF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETP_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = getB_PF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETP_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), getB_PF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNP_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !getB_PF(); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNP_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), !getB_PF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETL_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = (getB_SF() ^ getB_OF()); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETL_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), (getB_SF() ^ getB_OF())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNL_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !(getB_SF() ^ getB_OF()); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNL_EbR(bxInstruction_c *i) { BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), !(getB_SF() ^ getB_OF())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETLE_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = getB_ZF() | (getB_SF() ^ getB_OF()); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETLE_EbR(bxInstruction_c *i) { Bit8u result_8 = getB_ZF() | (getB_SF() ^ getB_OF()); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNLE_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u result_8 = !(getB_ZF() | (getB_SF() ^ getB_OF())); write_virtual_byte(i->seg(), eaddr, result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SETNLE_EbR(bxInstruction_c *i) { Bit8u result_8 = !(getB_ZF() | (getB_SF() ^ getB_OF())); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSWAP_RX(bxInstruction_c *i) { BX_ERROR(("BSWAP with 16-bit opsize: undefined behavior !")); BX_WRITE_16BIT_REG(i->dst(), 0); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSWAP_ERX(bxInstruction_c *i) { Bit32u val32 = BX_READ_32BIT_REG(i->dst()); BX_WRITE_32BIT_REGZ(i->dst(), bx_bswap32(val32)); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSWAP_RRX(bxInstruction_c *i) { Bit64u val64 = BX_READ_64BIT_REG(i->dst()); BX_WRITE_64BIT_REG(i->dst(), bx_bswap64(val64)); BX_NEXT_INSTR(i); } #endif #if BX_CPU_LEVEL >= 6 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_GwMw(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u val16 = read_virtual_word(i->seg(), eaddr); BX_WRITE_16BIT_REG(i->dst(), bx_bswap16(val16)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_MwGw(bxInstruction_c *i) { Bit16u val16 = BX_READ_16BIT_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), eaddr, bx_bswap16(val16)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_GdMd(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u val32 = read_virtual_dword(i->seg(), eaddr); BX_WRITE_32BIT_REGZ(i->dst(), bx_bswap32(val32)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_MdGd(bxInstruction_c *i) { Bit32u val32 = BX_READ_32BIT_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword(i->seg(), eaddr, bx_bswap32(val32)); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_GqMq(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u val64 = read_virtual_qword(i->seg(), eaddr); BX_WRITE_64BIT_REG(i->dst(), bx_bswap64(val64)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVBE_MqGq(bxInstruction_c *i) { Bit64u val64 = BX_READ_64BIT_REG(i->src()); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword_64(i->seg(), eaddr, bx_bswap64(val64)); BX_NEXT_INSTR(i); } #endif // BX_SUPPORT_X86_64 #endif // BX_CPU_LEVEL >= 6 #endif // BX_CPU_LEVEL >= 3 bochs-2.6/cpu/bit16.cc0000644000175000017500000002303712020641453014362 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bit16.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 3 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSF_GwEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); if (op2_16 == 0) { assert_ZF(); /* op1_16 undefined */ } else { Bit16u op1_16 = 0; while ((op2_16 & 0x01) == 0) { op1_16++; op2_16 >>= 1; } SET_FLAGS_OSZAPC_LOGIC_16(op1_16); clear_ZF(); BX_WRITE_16BIT_REG(i->dst(), op1_16); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSR_GwEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); if (op2_16 == 0) { assert_ZF(); /* op1_16 undefined */ } else { Bit16u op1_16 = 15; while ((op2_16 & 0x8000) == 0) { op1_16--; op2_16 <<= 1; } SET_FLAGS_OSZAPC_LOGIC_16(op1_16); clear_ZF(); BX_WRITE_16BIT_REG(i->dst(), op1_16); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EwGwM(bxInstruction_c *i) { bx_address op1_addr; Bit16u op1_16, op2_16, index; Bit32s displacement32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_16 = BX_READ_16BIT_REG(i->src()); index = op2_16 & 0xf; displacement32 = ((Bit16s) (op2_16&0xfff0)) / 16; op1_addr = eaddr + 2 * displacement32; /* pointer, segment address pair */ op1_16 = read_virtual_word(i->seg(), op1_addr & i->asize_mask()); set_CF((op1_16 >> index) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EwGwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op2_16 &= 0xf; set_CF((op1_16 >> op2_16) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EwGwM(bxInstruction_c *i) { bx_address op1_addr; Bit16u op1_16, op2_16, index; Bit32s displacement32; bx_bool bit_i; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_16 = BX_READ_16BIT_REG(i->src()); index = op2_16 & 0xf; displacement32 = ((Bit16s) (op2_16 & 0xfff0)) / 16; op1_addr = eaddr + 2 * displacement32; /* pointer, segment address pair */ op1_16 = read_RMW_virtual_word(i->seg(), op1_addr & i->asize_mask()); bit_i = (op1_16 >> index) & 0x01; op1_16 |= (1 << index); write_RMW_virtual_word(op1_16); set_CF(bit_i); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EwGwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op2_16 &= 0xf; set_CF((op1_16 >> op2_16) & 0x01); op1_16 |= (1 << op2_16); /* now write result back to the destination */ BX_WRITE_16BIT_REG(i->dst(), op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EwGwM(bxInstruction_c *i) { bx_address op1_addr; Bit16u op1_16, op2_16, index; Bit32s displacement32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_16 = BX_READ_16BIT_REG(i->src()); index = op2_16 & 0xf; displacement32 = ((Bit16s) (op2_16&0xfff0)) / 16; op1_addr = eaddr + 2 * displacement32; /* pointer, segment address pair */ op1_16 = read_RMW_virtual_word(i->seg(), op1_addr & i->asize_mask()); bx_bool temp_cf = (op1_16 >> index) & 0x01; op1_16 &= ~(1 << index); /* now write back to destination */ write_RMW_virtual_word(op1_16); set_CF(temp_cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EwGwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op2_16 &= 0xf; set_CF((op1_16 >> op2_16) & 0x01); op1_16 &= ~(1 << op2_16); /* now write result back to the destination */ BX_WRITE_16BIT_REG(i->dst(), op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EwGwM(bxInstruction_c *i) { bx_address op1_addr; Bit16u op1_16, op2_16, index_16; Bit16s displacement16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_16 = BX_READ_16BIT_REG(i->src()); index_16 = op2_16 & 0xf; displacement16 = ((Bit16s) (op2_16 & 0xfff0)) / 16; op1_addr = eaddr + 2 * displacement16; op1_16 = read_RMW_virtual_word(i->seg(), op1_addr & i->asize_mask()); bx_bool temp_CF = (op1_16 >> index_16) & 0x01; op1_16 ^= (1 << index_16); /* toggle bit */ write_RMW_virtual_word(op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EwGwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op2_16 &= 0xf; bx_bool temp_CF = (op1_16 >> op2_16) & 0x01; op1_16 ^= (1 << op2_16); /* toggle bit */ BX_WRITE_16BIT_REG(i->dst(), op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EwIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_virtual_word(i->seg(), eaddr); Bit8u op2_8 = i->Ib() & 0xf; set_CF((op1_16 >> op2_8) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EwIbR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit8u op2_8 = i->Ib() & 0xf; set_CF((op1_16 >> op2_8) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EwIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0xf; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); bx_bool temp_CF = (op1_16 >> op2_8) & 0x01; op1_16 |= (1 << op2_8); write_RMW_virtual_word(op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EwIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0xf; Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); bx_bool temp_CF = (op1_16 >> op2_8) & 0x01; op1_16 |= (1 << op2_8); BX_WRITE_16BIT_REG(i->dst(), op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EwIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0xf; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); bx_bool temp_CF = (op1_16 >> op2_8) & 0x01; op1_16 ^= (1 << op2_8); /* toggle bit */ write_RMW_virtual_word(op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EwIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0xf; Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); bx_bool temp_CF = (op1_16 >> op2_8) & 0x01; op1_16 ^= (1 << op2_8); /* toggle bit */ BX_WRITE_16BIT_REG(i->dst(), op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EwIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0xf; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); bx_bool temp_CF = (op1_16 >> op2_8) & 0x01; op1_16 &= ~(1 << op2_8); write_RMW_virtual_word(op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EwIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0xf; Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); bx_bool temp_CF = (op1_16 >> op2_8) & 0x01; op1_16 &= ~(1 << op2_8); BX_WRITE_16BIT_REG(i->dst(), op1_16); set_CF(temp_CF); BX_NEXT_INSTR(i); } /* F3 0F B8 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPCNT_GwEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); Bit16u op1_16 = 0; while (op2_16 != 0) { if (op2_16 & 1) op1_16++; op2_16 >>= 1; } Bit32u flags = op1_16 ? 0 : EFlagsZFMask; setEFlagsOSZAPC(flags); BX_WRITE_16BIT_REG(i->dst(), op1_16); BX_NEXT_INSTR(i); } /* F3 0F BC */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TZCNT_GwEwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->src()); Bit16u mask = 0x1, result_16 = 0; while ((op1_16 & mask) == 0 && mask) { mask <<= 1; result_16++; } set_CF(! op1_16); set_ZF(! result_16); BX_WRITE_16BIT_REG(i->dst(), result_16); BX_NEXT_INSTR(i); } /* F3 0F BD */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LZCNT_GwEwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->src()); Bit16u mask = 0x8000, result_16 = 0; while ((op1_16 & mask) == 0 && mask) { mask >>= 1; result_16++; } set_CF(! op1_16); set_ZF(! result_16); BX_WRITE_16BIT_REG(i->dst(), result_16); BX_NEXT_INSTR(i); } #endif // (BX_CPU_LEVEL >= 3) bochs-2.6/cpu/access32.cc0000644000175000017500000014354212020641453015047 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: access32.cc 11329 2012-08-08 20:43:07Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_byte_32(unsigned s, Bit32u offset, Bit8u data) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset <= seg->cache.u.segment.limit_scaled) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 1, CPL, BX_WRITE, (Bit8u*) &data); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 1); *hostAddr = data; return; } } access_write_linear(laddr, 1, CPL, (void *) &data); return; } else { BX_ERROR(("write_virtual_byte_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 1)) exception(int_number(s), 0); goto accessOK; } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_word_32(unsigned s, Bit32u offset, Bit16u data) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset < seg->cache.u.segment.limit_scaled) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 2, CPL, BX_WRITE, (Bit8u*) &data); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostAddr, data); return; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 1) { BX_ERROR(("write_virtual_word_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_write_linear(laddr, 2, CPL, (void *) &data); return; } else { BX_ERROR(("write_virtual_word_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 2)) exception(int_number(s), 0); goto accessOK; } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_dword_32(unsigned s, Bit32u offset, Bit32u data) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset < (seg->cache.u.segment.limit_scaled-2)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 4, CPL, BX_WRITE, (Bit8u*) &data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostAddr, data); return; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 3) { BX_ERROR(("write_virtual_dword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_write_linear(laddr, 4, CPL, (void *) &data); return; } else { BX_ERROR(("write_virtual_dword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 4)) exception(int_number(s), 0); goto accessOK; } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_qword_32(unsigned s, Bit32u offset, Bit64u data) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset <= (seg->cache.u.segment.limit_scaled-7)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 8, CPL, BX_WRITE, (Bit8u*) &data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 8); WriteHostQWordToLittleEndian(hostAddr, data); return; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 7) { BX_ERROR(("write_virtual_qword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_write_linear(laddr, 8, CPL, (void *) &data); return; } else { BX_ERROR(("write_virtual_qword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 8)) exception(int_number(s), 0); goto accessOK; } #if BX_CPU_LEVEL >= 6 void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_dqword_32(unsigned s, Bit32u offset, const BxPackedXmmRegister *data) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset <= (seg->cache.u.segment.limit_scaled-15)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 15); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 16, CPL, BX_WRITE, (Bit8u*) data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 16); WriteHostQWordToLittleEndian(hostAddr, data->xmm64u(0)); WriteHostQWordToLittleEndian(hostAddr+1, data->xmm64u(1)); return; } } access_write_linear(laddr, 16, CPL, (void *) data); return; } else { BX_ERROR(("write_virtual_dqword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 16)) exception(int_number(s), 0); goto accessOK; } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_dqword_aligned_32(unsigned s, Bit32u offset, const BxPackedXmmRegister *data) { bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u laddr = get_laddr32(s, offset); // must check alignment here because #GP on misaligned access is higher // priority than other segment related faults if (laddr & 15) { BX_ERROR(("write_virtual_dqword_aligned_32(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (seg->cache.valid & SegAccessWOK) { if (offset <= (seg->cache.u.segment.limit_scaled-15)) { accessOK: unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 16, CPL, BX_WRITE, (Bit8u*) data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 16); WriteHostQWordToLittleEndian(hostAddr, data->xmm64u(0)); WriteHostQWordToLittleEndian(hostAddr+1, data->xmm64u(1)); return; } } access_write_linear(laddr, 16, CPL, (void *) data); return; } else { BX_ERROR(("write_virtual_dqword_aligned_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 16)) exception(int_number(s), 0); goto accessOK; } #if BX_SUPPORT_AVX void BX_CPU_C::write_virtual_dword_vector_32(unsigned s, Bit32u offset, unsigned elements, const BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); Bit32u laddr; unsigned len = elements << 2; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset <= (seg->cache.u.segment.limit_scaled-len+1)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, len-1); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, len, CPL, BX_WRITE, (Bit8u*) data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, len); for (unsigned n=0; n < elements; n++) { WriteHostDWordToLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } return; } } access_write_linear(laddr, len, CPL, (void *) data); return; } else { BX_ERROR(("write_virtual_dword_vector_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, len)) exception(int_number(s), 0); goto accessOK; } void BX_CPU_C::write_virtual_dword_vector_aligned_32(unsigned s, Bit32u offset, unsigned elements, const BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); unsigned len = elements << 2; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u laddr = get_laddr32(s, offset); // must check alignment here because #GP on misaligned access is higher // priority than other segment related faults if (laddr & (len-1)) { BX_ERROR(("write_virtual_dword_vector_aligned_32(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (seg->cache.valid & SegAccessWOK) { if (offset <= (seg->cache.u.segment.limit_scaled-len+1)) { accessOK: unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, len, CPL, BX_WRITE, (Bit8u*) data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, len); for (unsigned n=0; n < elements; n++) { WriteHostDWordToLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } return; } } access_write_linear(laddr, len, CPL, (void *) data); return; } else { BX_ERROR(("write_virtual_dword_vector_aligned_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, len)) exception(int_number(s), 0); goto accessOK; } #endif // BX_SUPPORT_AVX #endif Bit8u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_byte_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit8u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessROK) { if (offset <= seg->cache.u.segment.limit_scaled) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); data = *hostAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 1, CPL, BX_READ, (Bit8u*) &data); return data; } } access_read_linear(laddr, 1, CPL, BX_READ, (void *) &data); return data; } else { BX_ERROR(("read_virtual_byte_32(): segment limit violation")); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, 1)) exception(int_number(s), 0); goto accessOK; } Bit16u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_word_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit16u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessROK) { if (offset < seg->cache.u.segment.limit_scaled) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); ReadHostWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 2, CPL, BX_READ, (Bit8u*) &data); return data; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 1) { BX_ERROR(("read_virtual_word_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_read_linear(laddr, 2, CPL, BX_READ, (void *) &data); return data; } else { BX_ERROR(("read_virtual_word_32(): segment limit violation")); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, 2)) exception(int_number(s), 0); goto accessOK; } Bit32u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_dword_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit32u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessROK) { if (offset < (seg->cache.u.segment.limit_scaled-2)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); ReadHostDWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 4, CPL, BX_READ, (Bit8u*) &data); return data; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 3) { BX_ERROR(("read_virtual_dword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_read_linear(laddr, 4, CPL, BX_READ, (void *) &data); return data; } else { BX_ERROR(("read_virtual_dword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, 4)) exception(int_number(s), 0); goto accessOK; } Bit64u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_qword_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit64u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessROK) { if (offset <= (seg->cache.u.segment.limit_scaled-7)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); ReadHostQWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 8, CPL, BX_READ, (Bit8u*) &data); return data; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 7) { BX_ERROR(("read_virtual_qword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_read_linear(laddr, 8, CPL, BX_READ, (void *) &data); return data; } else { BX_ERROR(("read_virtual_qword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, 8)) exception(int_number(s), 0); goto accessOK; } #if BX_CPU_LEVEL >= 6 void BX_CPP_AttrRegparmN(3) BX_CPU_C::read_virtual_dqword_32(unsigned s, Bit32u offset, BxPackedXmmRegister *data) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessROK) { if (offset <= (seg->cache.u.segment.limit_scaled-15)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 15); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); ReadHostQWordFromLittleEndian(hostAddr, data->xmm64u(0)); ReadHostQWordFromLittleEndian(hostAddr+1, data->xmm64u(1)); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 16, CPL, BX_READ, (Bit8u*) data); return; } } access_read_linear(laddr, 16, CPL, BX_READ, (void *) data); return; } else { BX_ERROR(("read_virtual_dqword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, 16)) exception(int_number(s), 0); goto accessOK; } void BX_CPP_AttrRegparmN(3) BX_CPU_C::read_virtual_dqword_aligned_32(unsigned s, Bit32u offset, BxPackedXmmRegister *data) { bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u laddr = get_laddr32(s, offset); // must check alignment here because #GP on misaligned access is higher // priority than other segment related faults if (laddr & 15) { BX_ERROR(("read_virtual_dqword_aligned_32(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (seg->cache.valid & SegAccessROK) { if (offset <= (seg->cache.u.segment.limit_scaled-15)) { accessOK: unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); ReadHostQWordFromLittleEndian(hostAddr, data->xmm64u(0)); ReadHostQWordFromLittleEndian(hostAddr+1, data->xmm64u(1)); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 16, CPL, BX_READ, (Bit8u*) data); return; } } access_read_linear(laddr, 16, CPL, BX_READ, (void *) data); return; } else { BX_ERROR(("read_virtual_dqword_aligned_32(): segment limit violation")); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, 16)) exception(int_number(s), 0); goto accessOK; } #if BX_SUPPORT_AVX void BX_CPU_C::read_virtual_dword_vector_32(unsigned s, Bit32u offset, unsigned elements, BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); Bit32u laddr; unsigned len = elements << 2; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessROK) { if (offset <= (seg->cache.u.segment.limit_scaled-len+1)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, len-1); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); for (unsigned n=0; n < elements; n++) { ReadHostDWordFromLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), len, CPL, BX_READ, (Bit8u*) data); return; } } access_read_linear(laddr, len, CPL, BX_READ, (void *) data); return; } else { BX_ERROR(("read_virtual_dword_vector_32(len=%d): segment limit violation", len)); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, len)) exception(int_number(s), 0); goto accessOK; } void BX_CPU_C::read_virtual_dword_vector_aligned_32(unsigned s, Bit32u offset, unsigned elements, BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); unsigned len = elements << 2; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u laddr = get_laddr32(s, offset); // must check alignment here because #GP on misaligned access is higher // priority than other segment related faults if (laddr & (len-1)) { BX_ERROR(("read_virtual_dword_vector_aligned_32(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (seg->cache.valid & SegAccessROK) { if (offset <= (seg->cache.u.segment.limit_scaled-len+1)) { accessOK: unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); for (unsigned n=0; n < elements; n++) { ReadHostDWordFromLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), len, CPL, BX_READ, (Bit8u*) data); return; } } access_read_linear(laddr, len, CPL, BX_READ, (void *) data); return; } else { BX_ERROR(("read_virtual_dword_vector_aligned_32(): segment limit violation")); exception(int_number(s), 0); } } if (!read_virtual_checks(seg, offset, len)) exception(int_number(s), 0); goto accessOK; } #endif #endif ////////////////////////////////////////////////////////////// // special Read-Modify-Write operations // // address translation info is kept across read/write calls // ////////////////////////////////////////////////////////////// Bit8u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_byte_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit8u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset <= seg->cache.u.segment.limit_scaled) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit32u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 1); data = *hostAddr; BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 1, CPL, BX_READ, (Bit8u*) &data); return data; } } access_read_linear(laddr, 1, CPL, BX_RW, (void *) &data); return data; } else { BX_ERROR(("read_RMW_virtual_byte_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 1)) exception(int_number(s), 0); goto accessOK; } Bit16u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_word_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit16u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset < seg->cache.u.segment.limit_scaled) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 2); ReadHostWordFromLittleEndian(hostAddr, data); BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 2, CPL, BX_READ, (Bit8u*) &data); return data; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 1) { BX_ERROR(("read_RMW_virtual_word_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_read_linear(laddr, 2, CPL, BX_RW, (void *) &data); return data; } else { BX_ERROR(("read_RMW_virtual_word_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 2)) exception(int_number(s), 0); goto accessOK; } Bit32u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_dword_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit32u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset < (seg->cache.u.segment.limit_scaled-2)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 4); ReadHostDWordFromLittleEndian(hostAddr, data); BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 4, CPL, BX_READ, (Bit8u*) &data); return data; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 3) { BX_ERROR(("read_RMW_virtual_dword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_read_linear(laddr, 4, CPL, BX_RW, (void *) &data); return data; } else { BX_ERROR(("read_RMW_virtual_dword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 4)) exception(int_number(s), 0); goto accessOK; } Bit64u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_qword_32(unsigned s, Bit32u offset) { Bit32u laddr; bx_segment_reg_t *seg = &BX_CPU_THIS_PTR sregs[s]; Bit64u data; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); if (seg->cache.valid & SegAccessWOK) { if (offset <= (seg->cache.u.segment.limit_scaled-7)) { accessOK: laddr = get_laddr32(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 8); ReadHostQWordFromLittleEndian(hostAddr, data); BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 8, CPL, BX_READ, (Bit8u*) &data); return data; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 7) { BX_ERROR(("read_RMW_virtual_qword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_read_linear(laddr, 8, CPL, BX_RW, (void *) &data); return data; } else { BX_ERROR(("read_RMW_virtual_qword_32(): segment limit violation")); exception(int_number(s), 0); } } if (!write_virtual_checks(seg, offset, 8)) exception(int_number(s), 0); goto accessOK; } void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_byte(Bit8u val8) { BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 1, BX_WRITE, 0, (Bit8u*) &val8); if (BX_CPU_THIS_PTR address_xlation.pages > 2) { // Pages > 2 means it stores a host address for direct access. Bit8u *hostAddr = (Bit8u *) BX_CPU_THIS_PTR address_xlation.pages; *hostAddr = val8; } else { // address_xlation.pages must be 1 access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, 1, &val8); } } void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_word(Bit16u val16) { if (BX_CPU_THIS_PTR address_xlation.pages > 2) { // Pages > 2 means it stores a host address for direct access. Bit16u *hostAddr = (Bit16u *) BX_CPU_THIS_PTR address_xlation.pages; WriteHostWordToLittleEndian(hostAddr, val16); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 2, BX_WRITE, 0, (Bit8u*) &val16); } else if (BX_CPU_THIS_PTR address_xlation.pages == 1) { access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, 2, &val16); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 2, BX_WRITE, 0, (Bit8u*) &val16); } else { #ifdef BX_LITTLE_ENDIAN access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, 1, &val16); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 1, BX_WRITE, 0, (Bit8u*) &val16); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, 1, ((Bit8u *) &val16) + 1); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress2, 1, BX_WRITE, 0, ((Bit8u*) &val16)+1); #else access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, 1, ((Bit8u *) &val16) + 1); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 1, BX_WRITE, 0, ((Bit8u*) &val16)+1); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, 1, &val16); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress2, 1, BX_WRITE, 0, (Bit8u*) &val16); #endif } } void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_dword(Bit32u val32) { if (BX_CPU_THIS_PTR address_xlation.pages > 2) { // Pages > 2 means it stores a host address for direct access. Bit32u *hostAddr = (Bit32u *) BX_CPU_THIS_PTR address_xlation.pages; WriteHostDWordToLittleEndian(hostAddr, val32); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 4, BX_WRITE, 0, (Bit8u*) &val32); } else if (BX_CPU_THIS_PTR address_xlation.pages == 1) { access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, 4, &val32); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 4, BX_WRITE, 0, (Bit8u*) &val32); } else { #ifdef BX_LITTLE_ENDIAN access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, &val32); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, BX_WRITE, 0, (Bit8u*) &val32); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, ((Bit8u *) &val32) + BX_CPU_THIS_PTR address_xlation.len1); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, BX_WRITE, 0, ((Bit8u *) &val32) + BX_CPU_THIS_PTR address_xlation.len1); #else access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, ((Bit8u *) &val32) + (4 - BX_CPU_THIS_PTR address_xlation.len1)); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, BX_WRITE, 0, ((Bit8u *) &val32) + (4 - BX_CPU_THIS_PTR address_xlation.len1)); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, &val32); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, BX_WRITE, 0, (Bit8u*) &val32); #endif } } void BX_CPP_AttrRegparmN(1) BX_CPU_C::write_RMW_virtual_qword(Bit64u val64) { if (BX_CPU_THIS_PTR address_xlation.pages > 2) { // Pages > 2 means it stores a host address for direct access. Bit64u *hostAddr = (Bit64u *) BX_CPU_THIS_PTR address_xlation.pages; WriteHostQWordToLittleEndian(hostAddr, val64); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 8, BX_WRITE, 0, (Bit8u*) &val64); } else if (BX_CPU_THIS_PTR address_xlation.pages == 1) { access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, 8, &val64); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, 8, BX_WRITE, 0, (Bit8u*) &val64); } else { #ifdef BX_LITTLE_ENDIAN access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, &val64); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, BX_WRITE, 0, (Bit8u*) &val64); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, ((Bit8u *) &val64) + BX_CPU_THIS_PTR address_xlation.len1); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, BX_WRITE, 0, ((Bit8u *) &val64) + BX_CPU_THIS_PTR address_xlation.len1); #else access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, ((Bit8u *) &val64) + (8 - BX_CPU_THIS_PTR address_xlation.len1)); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress1, BX_CPU_THIS_PTR address_xlation.len1, BX_WRITE, 0, ((Bit8u *) &val64) + (8 - BX_CPU_THIS_PTR address_xlation.len1)); access_write_physical(BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, &val64); BX_DBG_PHY_MEMORY_ACCESS(BX_CPU_ID, BX_CPU_THIS_PTR address_xlation.paddress2, BX_CPU_THIS_PTR address_xlation.len2, BX_WRITE, 0, (Bit8u*) &val64); #endif } } // // Write data to new stack, these methods are required for emulation // correctness but not performance critical. // // assuming the write happens in legacy mode void BX_CPU_C::write_new_stack_word_32(bx_segment_reg_t *seg, Bit32u offset, unsigned curr_pl, Bit16u data) { Bit32u laddr; if (seg->cache.valid & SegAccessWOK) { if (offset < seg->cache.u.segment.limit_scaled) { accessOK: laddr = (Bit32u)(seg->cache.u.segment.base) + offset; bx_bool user = (curr_pl == 3); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | user))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 2, curr_pl, BX_WRITE, (Bit8u*) &data); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostAddr, data); return; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && user) { if (laddr & 1) { BX_ERROR(("write_new_stack_word_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_write_linear(laddr, 2, curr_pl, (void *) &data); return; } else { BX_ERROR(("write_new_stack_word_32(): segment limit violation")); exception(BX_SS_EXCEPTION, seg->selector.rpl != CPL ? (seg->selector.value & 0xfffc) : 0); } } // add error code when segment violation occurs when pushing into new stack if (!write_virtual_checks(seg, offset, 2)) exception(BX_SS_EXCEPTION, seg->selector.rpl != CPL ? (seg->selector.value & 0xfffc) : 0); goto accessOK; } // assuming the write happens in legacy mode void BX_CPU_C::write_new_stack_dword_32(bx_segment_reg_t *seg, Bit32u offset, unsigned curr_pl, Bit32u data) { Bit32u laddr; if (seg->cache.valid & SegAccessWOK) { if (offset < (seg->cache.u.segment.limit_scaled-2)) { accessOK: laddr = (Bit32u)(seg->cache.u.segment.base) + offset; bx_bool user = (curr_pl == 3); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | user))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 4, curr_pl, BX_WRITE, (Bit8u*) &data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostAddr, data); return; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && user) { if (laddr & 3) { BX_ERROR(("write_new_stack_dword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_write_linear(laddr, 4, curr_pl, (void *) &data); return; } else { BX_ERROR(("write_new_stack_dword_32(): segment limit violation")); exception(BX_SS_EXCEPTION, seg->selector.rpl != CPL ? (seg->selector.value & 0xfffc) : 0); } } // add error code when segment violation occurs when pushing into new stack if (!write_virtual_checks(seg, offset, 4)) exception(BX_SS_EXCEPTION, seg->selector.rpl != CPL ? (seg->selector.value & 0xfffc) : 0); goto accessOK; } // assuming the write happens in legacy mode void BX_CPU_C::write_new_stack_qword_32(bx_segment_reg_t *seg, Bit32u offset, unsigned curr_pl, Bit64u data) { Bit32u laddr; if (seg->cache.valid & SegAccessWOK) { if (offset <= (seg->cache.u.segment.limit_scaled-7)) { accessOK: laddr = (Bit32u)(seg->cache.u.segment.base) + offset; bx_bool user = (curr_pl == 3); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit32u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit32u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | user))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 8, curr_pl, BX_WRITE, (Bit8u*) &data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 8); WriteHostQWordToLittleEndian(hostAddr, data); return; } } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && user) { if (laddr & 7) { BX_ERROR(("write_new_stack_qword_32(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif access_write_linear(laddr, 8, curr_pl, (void *) &data); return; } else { BX_ERROR(("write_new_stack_qword_32(): segment limit violation")); exception(BX_SS_EXCEPTION, seg->selector.rpl != CPL ? (seg->selector.value & 0xfffc) : 0); } } // add error code when segment violation occurs when pushing into new stack if (!write_virtual_checks(seg, offset, 8)) exception(BX_SS_EXCEPTION, seg->selector.rpl != CPL ? (seg->selector.value & 0xfffc) : 0); goto accessOK; } bochs-2.6/cpu/sse_pfp.cc0000644000175000017500000015401312020641453015073 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: sse_pfp.cc 11336 2012-08-11 07:41:13Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2003-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 6 #include "fpu/softfloat-compare.h" #include "simd_pfp.h" void BX_CPU_C::check_exceptionsSSE(int exceptions_flags) { exceptions_flags &= MXCSR_EXCEPTIONS; int unmasked = ~(MXCSR.get_exceptions_masks()) & exceptions_flags; // unmasked pre-computational exception detected (#IA, #DE or #DZ) if (unmasked & 0x7) exceptions_flags &= 0x7; MXCSR.set_exceptions(exceptions_flags); if (unmasked) { if(BX_CPU_THIS_PTR cr4.get_OSXMMEXCPT()) exception(BX_XM_EXCEPTION, 0); else exception(BX_UD_EXCEPTION, 0); } } void mxcsr_to_softfloat_status_word(float_status_t &status, bx_mxcsr_t mxcsr) { status.float_exception_flags = 0; // clear exceptions before execution status.float_nan_handling_mode = float_first_operand_nan; status.float_rounding_mode = mxcsr.get_rounding_mode(); // if underflow is masked and FUZ is 1, set it to 1, else to 0 status.flush_underflow_to_zero = (mxcsr.get_flush_masked_underflow() && mxcsr.get_UM()) ? 1 : 0; status.float_exception_masks = mxcsr.get_exceptions_masks(); status.denormals_are_zeros = mxcsr.get_DAZ(); } /* Comparison predicate for CMPSS/CMPPS instructions */ static float32_compare_method compare32[8] = { float32_eq_ordered_quiet, float32_lt_ordered_signalling, float32_le_ordered_signalling, float32_unordered_quiet, float32_neq_unordered_quiet, float32_nlt_unordered_signalling, float32_nle_unordered_signalling, float32_ordered_quiet }; /* Comparison predicate for CMPSD/CMPPD instructions */ static float64_compare_method compare64[8] = { float64_eq_ordered_quiet, float64_lt_ordered_signalling, float64_le_ordered_signalling, float64_unordered_quiet, float64_neq_unordered_quiet, float64_nlt_unordered_signalling, float64_nle_unordered_signalling, float64_ordered_quiet }; #endif // BX_CPU_LEVEL >= 6 /* * Opcode: 0F 2A * Convert two 32bit signed integers from MMX/MEM to two single precision FP * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PS_VpsQqR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 /* check floating point status word for a pending FPU exceptions */ FPU_check_pending_exceptions(); BxPackedMmxRegister op = BX_READ_MMX_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); MMXUD0(op) = int32_to_float32(MMXUD0(op), status); MMXUD1(op) = int32_to_float32(MMXUD1(op), status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), MMXUQ(op)); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PS_VpsQqM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedMmxRegister op; // do not cause transition to MMX state because no MMX register touched bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); MMXUD0(op) = int32_to_float32(MMXUD0(op), status); MMXUD1(op) = int32_to_float32(MMXUD1(op), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), MMXUQ(op)); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 2A * Convert two 32bit signed integers from MMX/MEM to two double precision FP * Possible floating point exceptions: - */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PD_VpdQqR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister result; /* check floating point status word for a pending FPU exceptions */ FPU_check_pending_exceptions(); prepareFPU2MMX(); /* cause FPU2MMX state transition */ BxPackedMmxRegister op = BX_READ_MMX_REG(i->src()); result.xmm64u(0) = int32_to_float64(MMXUD0(op)); result.xmm64u(1) = int32_to_float64(MMXUD1(op)); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPI2PD_VpdQqM(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedMmxRegister op; BxPackedXmmRegister result; // do not cause transition to MMX state because no MMX register touched bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); result.xmm64u(0) = int32_to_float64(MMXUD0(op)); result.xmm64u(1) = int32_to_float64(MMXUD1(op)); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 2A * Convert one 32bit signed integer to one double precision FP * Possible floating point exceptions: - */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SD_VsdEdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 result = int32_to_float64(BX_READ_32BIT_REG(i->src())); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), result); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SD_VsdEqR(bxInstruction_c *i) { float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); float64 result = int64_to_float64(BX_READ_64BIT_REG(i->src()), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), result); BX_NEXT_INSTR(i); } #endif /* * Opcode: F3 0F 2A * Convert one 32bit signed integer to one single precision FP * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SS_VssEdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); float32 result = int32_to_float32(BX_READ_32BIT_REG(i->src()), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), result); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSI2SS_VssEqR(bxInstruction_c *i) { float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); float32 result = int64_to_float32(BX_READ_64BIT_REG(i->src()), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), result); BX_NEXT_INSTR(i); } #endif /* * Opcode: 0F 2C * Convert two single precision FP numbers to two signed doubleword integers * in MMX using truncation if the conversion is inexact * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPS2PI_PqWps(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 /* check floating point status word for a pending FPU exceptions */ FPU_check_pending_exceptions(); BxPackedMmxRegister op; /* op is a register or memory reference */ if (i->modC0()) { MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); MMXUD0(op) = float32_to_int32_round_to_zero(MMXUD0(op), status); MMXUD1(op) = float32_to_int32_round_to_zero(MMXUD1(op), status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ check_exceptionsSSE(status.float_exception_flags); BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 2C * Convert two double precision FP numbers to two signed doubleword integers * in MMX using truncation if the conversion is inexact * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPD2PI_PqWpd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 /* check floating point status word for a pending FPU exceptions */ FPU_check_pending_exceptions(); BxPackedXmmRegister op; BxPackedMmxRegister result; /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_XMM_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_MISALIGNED_SSE if (BX_CPU_THIS_PTR mxcsr.get_MM()) read_virtual_dqword(i->seg(), eaddr, (Bit8u *) &op); else #endif read_virtual_dqword_aligned(i->seg(), eaddr, (Bit8u *) &op); } float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); MMXUD0(result) = float64_to_int32_round_to_zero(op.xmm64u(0), status); MMXUD1(result) = float64_to_int32_round_to_zero(op.xmm64u(1), status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ check_exceptionsSSE(status.float_exception_flags); BX_WRITE_MMX_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 2C * Convert one double precision FP number to doubleword integer using * truncation if the conversion is inexact * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSD2SI_GdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit32u result = float64_to_int32_round_to_zero(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_32BIT_REGZ(i->dst(), result); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSD2SI_GqWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit64u result = float64_to_int64_round_to_zero(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); } #endif /* * Opcode: F3 0F 2C * Convert one single precision FP number to doubleword integer using * truncation if the conversion is inexact * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSS2SI_GdWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit32u result = float32_to_int32_round_to_zero(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_32BIT_REGZ(i->dst(), result); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTSS2SI_GqWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit64u result = float32_to_int64_round_to_zero(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); } #endif /* * Opcode: 0F 2D * Convert two single precision FP numbers to two signed doubleword integers * in MMX register. When a conversion is inexact, the value returned is * rounded according to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2PI_PqWps(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 /* check floating point status word for a pending FPU exceptions */ FPU_check_pending_exceptions(); BxPackedMmxRegister op; /* op is a register or memory reference */ if (i->modC0()) { MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ MMXUQ(op) = read_virtual_qword(i->seg(), eaddr); } float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); MMXUD0(op) = float32_to_int32(MMXUD0(op), status); MMXUD1(op) = float32_to_int32(MMXUD1(op), status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ check_exceptionsSSE(status.float_exception_flags); BX_WRITE_MMX_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 2D * Convert two double precision FP numbers to two signed doubleword integers * in MMX register. When a conversion is inexact, the value returned is * rounded according to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2PI_PqWpd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 /* check floating point status word for a pending FPU exceptions */ FPU_check_pending_exceptions(); BxPackedXmmRegister op; BxPackedMmxRegister result; /* op is a register or memory reference */ if (i->modC0()) { op = BX_READ_XMM_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); #if BX_SUPPORT_MISALIGNED_SSE if (BX_CPU_THIS_PTR mxcsr.get_MM()) read_virtual_dqword(i->seg(), eaddr, (Bit8u *) &op); else #endif read_virtual_dqword_aligned(i->seg(), eaddr, (Bit8u *) &op); } float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); MMXUD0(result) = float64_to_int32(op.xmm64u(0), status); MMXUD1(result) = float64_to_int32(op.xmm64u(1), status); prepareFPU2MMX(); /* cause FPU2MMX state transition */ check_exceptionsSSE(status.float_exception_flags); BX_WRITE_MMX_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 2D * Convert one double precision FP number to doubleword integer * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SI_GdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit32u result = float64_to_int32(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_32BIT_REGZ(i->dst(), result); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SI_GqWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit64u result = float64_to_int64(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); } #endif /* * Opcode: F3 0F 2D * Convert one single precision FP number to doubleword integer. * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SI_GdWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit32u result = float32_to_int32(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_32BIT_REGZ(i->dst(), result); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SI_GqWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit64u result = float32_to_int64(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_64BIT_REG(i->dst(), result); BX_NEXT_INSTR(i); } #endif /* * Opcode: 0F 5A * Convert two single precision FP numbers to two double precision FP numbers * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2PD_VpdWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); result.xmm64u(0) = float32_to_float64(MMXUD0(op), status); result.xmm64u(1) = float32_to_float64(MMXUD1(op), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 5A * Convert two double precision FP numbers to two single precision FP. * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #D, #O, #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2PS_VpsWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm32u(0) = float64_to_float32(op.xmm64u(0), status); op.xmm32u(1) = float64_to_float32(op.xmm64u(1), status); op.xmm64u(1) = 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 5A * Convert one double precision FP number to one single precision FP. * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #D, #O, #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSD2SS_VssWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); float32 result = float64_to_float32(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 5A * Convert one single precision FP number to one double precision FP. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTSS2SD_VsdWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); float64 result = float32_to_float64(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 5B * Convert four signed integers to four single precision FP numbers. * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTDQ2PS_VpsWdqR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm32u(0) = int32_to_float32(op.xmm32u(0), status); op.xmm32u(1) = int32_to_float32(op.xmm32u(1), status); op.xmm32u(2) = int32_to_float32(op.xmm32u(2), status); op.xmm32u(3) = int32_to_float32(op.xmm32u(3), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 5B * Convert four single precision FP to four doubleword integers. * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPS2DQ_VdqWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm32u(0) = float32_to_int32(op.xmm32u(0), status); op.xmm32u(1) = float32_to_int32(op.xmm32u(1), status); op.xmm32u(2) = float32_to_int32(op.xmm32u(2), status); op.xmm32u(3) = float32_to_int32(op.xmm32u(3), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 5B * Convert four single precision FP to four doubleword integers using * truncation if the conversion is inexact. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPS2DQ_VdqWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm32u(0) = float32_to_int32_round_to_zero(op.xmm32u(0), status); op.xmm32u(1) = float32_to_int32_round_to_zero(op.xmm32u(1), status); op.xmm32u(2) = float32_to_int32_round_to_zero(op.xmm32u(2), status); op.xmm32u(3) = float32_to_int32_round_to_zero(op.xmm32u(3), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F E6 * Convert two double precision FP to two signed doubleword integers using * truncation if the conversion is inexact. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTTPD2DQ_VqWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm32u(0) = float64_to_int32_round_to_zero(op.xmm64u(0), status); op.xmm32u(1) = float64_to_int32_round_to_zero(op.xmm64u(1), status); op.xmm64u(1) = 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F E6 * Convert two double precision FP to two signed doubleword integers. * When a conversion is inexact, the value returned is rounded according * to rounding control bits in MXCSR register. * Possible floating point exceptions: #I, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTPD2DQ_VqWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm32u(0) = float64_to_int32(op.xmm64u(0), status); op.xmm32u(1) = float64_to_int32(op.xmm64u(1), status); op.xmm64u(1) = 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F E6 * Convert two 32bit signed integers from XMM/MEM to two double precision FP * Possible floating point exceptions: - */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CVTDQ2PD_VpdWqR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.xmm64u(0) = int32_to_float64(MMXUD0(op)); result.xmm64u(1) = int32_to_float64(MMXUD1(op)); BX_WRITE_XMM_REG(i->dst(), result); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 2E * Compare two single precision FP numbers and set EFLAGS accordintly. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::UCOMISS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int rc = float32_compare_quiet(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 2E * Compare two double precision FP numbers and set EFLAGS accordintly. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::UCOMISD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int rc = float64_compare_quiet(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 2F * Compare two single precision FP numbers and set EFLAGS accordintly. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::COMISS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int rc = float32_compare(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 2F * Compare two double precision FP numbers and set EFLAGS accordintly. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::COMISD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int rc = float64_compare(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_CPU_THIS_PTR write_eflags_fpu_compare(rc); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 51 * Square Root packed single precision. * Possible floating point exceptions: #I, #D, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm32u(0) = float32_sqrt(op.xmm32u(0), status); op.xmm32u(1) = float32_sqrt(op.xmm32u(1), status); op.xmm32u(2) = float32_sqrt(op.xmm32u(2), status); op.xmm32u(3) = float32_sqrt(op.xmm32u(3), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 51 * Square Root packed double precision. * Possible floating point exceptions: #I, #D, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op.xmm64u(0) = float64_sqrt(op.xmm64u(0), status); op.xmm64u(1) = float64_sqrt(op.xmm64u(1), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 51 * Square Root scalar double precision. * Possible floating point exceptions: #I, #D, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op = float64_sqrt(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 51 * Square Root scalar single precision. * Possible floating point exceptions: #I, #D, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SQRTSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op = float32_sqrt(op, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 58 * Add packed single precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_addps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 58 * Add packed double precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_addpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 58 * Add the lower double precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_add(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 58 * Add the lower single precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_add(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 59 * Multiply packed single precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MULPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_mulps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 59 * Multiply packed double precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MULPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_mulpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 59 * Multiply the lower double precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MULSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_mul(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 59 * Multiply the lower single precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MULSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_mul(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 5C * Subtract packed single precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_subps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 5C * Subtract packed double precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_subpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 5C * Subtract the lower double precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_sub(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 5C * Subtract the lower single precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SUBSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_sub(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 5D * Calculate the minimum single precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MINPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_minps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 5D * Calculate the minimum double precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MINPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_minpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 5D * Calculate the minimum scalar double precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MINSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_min(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 5D * Calculate the minimum scalar single precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MINSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_min(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 5E * Divide packed single precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #Z, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_divps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 5E * Divide packed double precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #Z, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_divpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 5E * Divide the lower double precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #Z, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_div(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 5E * Divide the lower single precision FP number from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #Z, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIVSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_div(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 5F * Calculate the maximum single precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_maxps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 5F * Calculate the maximum double precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_maxpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 5F * Calculate the maximum scalar double precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXSD_VsdWsdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_max(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 5F * Calculate the maxumim scalar single precision FP between XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MAXSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_max(op1, op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 7C * Add horizontally packed double precision FP in XMM2/MEM from XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::HADDPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_haddpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 7C * Add horizontally packed single precision FP in XMM2/MEM from XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::HADDPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_haddps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F 7D * Subtract horizontally packed double precision FP in XMM2/MEM from XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::HSUBPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_hsubpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F 7D * Subtract horizontally packed single precision FP in XMM2/MEM from XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::HSUBPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_hsubps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F C2 * Compare packed single precision FP values using Ib as comparison predicate. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPS_VpsWpsIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 7; op1.xmm32u(0) = compare32[ib](op1.xmm32u(0), op2.xmm32u(0), status) ? 0xFFFFFFFF : 0; op1.xmm32u(1) = compare32[ib](op1.xmm32u(1), op2.xmm32u(1), status) ? 0xFFFFFFFF : 0; op1.xmm32u(2) = compare32[ib](op1.xmm32u(2), op2.xmm32u(2), status) ? 0xFFFFFFFF : 0; op1.xmm32u(3) = compare32[ib](op1.xmm32u(3), op2.xmm32u(3), status) ? 0xFFFFFFFF : 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F C2 * Compare packed double precision FP values using Ib as comparison predicate. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPPD_VpdWpdIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 7; op1.xmm64u(0) = compare64[ib](op1.xmm64u(0), op2.xmm64u(0), status) ? BX_CONST64(0xFFFFFFFFFFFFFFFF) : 0; op1.xmm64u(1) = compare64[ib](op1.xmm64u(1), op2.xmm64u(1), status) ? BX_CONST64(0xFFFFFFFFFFFFFFFF) : 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F C2 * Compare double precision FP values using Ib as comparison predicate. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSD_VsdWsdIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 7; if(compare64[ib](op1, op2, status)) { op1 = BX_CONST64(0xFFFFFFFFFFFFFFFF); } else { op1 = 0; } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F C2 * Compare single precision FP values using Ib as comparison predicate. * Possible floating point exceptions: #I, #D */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMPSS_VssWssIbR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->dst()), op2 = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 7; op1 = compare32[ib](op1, op2, status) ? 0xFFFFFFFF : 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: 66 0F D0 * Add/Subtract packed double precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSUBPD_VpdWpdR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_addsubpd(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* * Opcode: F2 0F D0 * Add/Substract packed single precision FP numbers from XMM2/MEM to XMM1. * Possible floating point exceptions: #I, #D, #O, #U, #P */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADDSUBPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); sse_addsubps(&op1, &op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); #endif BX_NEXT_INSTR(i); } #if BX_CPU_LEVEL >= 6 /* 66 0F 3A 08 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDPS_VpsWpsIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; op.xmm32u(0) = float32_round_to_int(op.xmm32u(0), status); op.xmm32u(1) = float32_round_to_int(op.xmm32u(1), status); op.xmm32u(2) = float32_round_to_int(op.xmm32u(2), status); op.xmm32u(3) = float32_round_to_int(op.xmm32u(3), status); // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); BX_NEXT_INSTR(i); } /* 66 0F 3A 09 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDPD_VpdWpdIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; op.xmm64u(0) = float64_round_to_int(op.xmm64u(0), status); op.xmm64u(1) = float64_round_to_int(op.xmm64u(1), status); // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op); BX_NEXT_INSTR(i); } /* 66 0F 3A 0A */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDSS_VssWssIbR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; op = float32_round_to_int(op, status); // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op); BX_NEXT_INSTR(i); } /* 66 0F 3A 0B */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROUNDSD_VsdWsdIbR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; op = float64_round_to_int(op, status); // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op); BX_NEXT_INSTR(i); } /* Opcode: 66 0F 3A 40 * Selectively multiply packed SP floating-point values from xmm1 with * packed SP floating-point values from xmm2, add and selectively * store the packed SP floating-point values or zero values to xmm1 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DPPS_VpsWpsIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()), tmp; Bit8u mask = i->Ib(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); tmp.xmm64u(0) = tmp.xmm64u(1) = 0; if (mask & 0x10) tmp.xmm32u(0) = float32_mul(op1.xmm32u(0), op2.xmm32u(0), status); if (mask & 0x20) tmp.xmm32u(1) = float32_mul(op1.xmm32u(1), op2.xmm32u(1), status); if (mask & 0x40) tmp.xmm32u(2) = float32_mul(op1.xmm32u(2), op2.xmm32u(2), status); if (mask & 0x80) tmp.xmm32u(3) = float32_mul(op1.xmm32u(3), op2.xmm32u(3), status); float32 tmp1 = float32_add(tmp.xmm32u(0), tmp.xmm32u(1), status); float32 tmp2 = float32_add(tmp.xmm32u(2), tmp.xmm32u(3), status); op1.xmm64u(0) = op1.xmm64u(1) = 0; #ifdef BX_DPPS_DPPD_NAN_MATCHING_HARDWARE float32 r1 = float32_add(tmp1, tmp2, status); float32 r2 = float32_add(tmp2, tmp1, status); if (mask & 0x01) op1.xmm32u(0) = r1; if (mask & 0x02) op1.xmm32u(1) = r1; if (mask & 0x04) op1.xmm32u(2) = r2; if (mask & 0x08) op1.xmm32u(3) = r2; #else float32 r = float32_add(tmp1, tmp2, status); if (mask & 0x01) op1.xmm32u(0) = r; if (mask & 0x02) op1.xmm32u(1) = r; if (mask & 0x04) op1.xmm32u(2) = r; if (mask & 0x08) op1.xmm32u(3) = r; #endif check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: 66 0F 3A 41 * Selectively multiply packed DP floating-point values from xmm1 with * packed DP floating-point values from xmm2, add and selectively * store the packed DP floating-point values or zero values to xmm1 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DPPD_VpdHpdWpdIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()), tmp; Bit8u mask = i->Ib(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); tmp.xmm64u(0) = tmp.xmm64u(1) = 0; if (mask & 0x10) tmp.xmm64u(0) = float64_mul(op1.xmm64u(0), op2.xmm64u(0), status); if (mask & 0x20) tmp.xmm64u(1) = float64_mul(op1.xmm64u(1), op2.xmm64u(1), status); op1.xmm64u(0) = op1.xmm64u(1) = 0; #ifdef BX_DPPS_DPPD_NAN_MATCHING_HARDWARE if (mask & 0x01) op1.xmm64u(0) = float64_add(tmp.xmm64u(0), tmp.xmm64u(1), status); if (mask & 0x02) op1.xmm64u(1) = float64_add(tmp.xmm64u(1), tmp.xmm64u(0), status); #else float64 result = float64_add(tmp.xmm64u(0), tmp.xmm64u(1), status); if (mask & 0x01) op1.xmm64u(0) = result; if (mask & 0x02) op1.xmm64u(1) = result; #endif check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } #endif // BX_CPU_LEVEL >= 6 bochs-2.6/cpu/protect_ctrl.cc0000644000175000017500000006707512020641453016153 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: protect_ctrl.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ARPL_EwGw(bxInstruction_c *i) { Bit16u op2_16, op1_16; if (! protected_mode()) { BX_DEBUG(("ARPL: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } /* op1_16 is a register or memory reference */ if (i->modC0()) { op1_16 = BX_READ_16BIT_REG(i->dst()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_16 = read_RMW_virtual_word(i->seg(), eaddr); } op2_16 = BX_READ_16BIT_REG(i->src()); if ((op1_16 & 0x03) < (op2_16 & 0x03)) { op1_16 = (op1_16 & 0xfffc) | (op2_16 & 0x03); /* now write back to destination */ if (i->modC0()) { BX_WRITE_16BIT_REG(i->dst(), op1_16); } else { write_RMW_virtual_word(op1_16); } assert_ZF(); } else { clear_ZF(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LAR_GvEw(bxInstruction_c *i) { /* for 16 bit operand size mode */ Bit16u raw_selector; bx_descriptor_t descriptor; bx_selector_t selector; Bit32u dword1, dword2; #if BX_SUPPORT_X86_64 Bit32u dword3 = 0; #endif if (! protected_mode()) { BX_ERROR(("LAR: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } if (i->modC0()) { raw_selector = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ raw_selector = read_virtual_word(i->seg(), eaddr); } /* if selector null, clear ZF and done */ if ((raw_selector & 0xfffc) == 0) { clear_ZF(); BX_NEXT_INSTR(i); } parse_selector(raw_selector, &selector); if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) { BX_DEBUG(("LAR: failed to fetch descriptor")); clear_ZF(); BX_NEXT_INSTR(i); } parse_descriptor(dword1, dword2, &descriptor); if (descriptor.valid==0) { BX_DEBUG(("LAR: descriptor not valid")); clear_ZF(); BX_NEXT_INSTR(i); } /* if source selector is visible at CPL & RPL, * within the descriptor table, and of type accepted by LAR instruction, * then load register with segment limit and set ZF */ if (descriptor.segment) { /* normal segment */ if (IS_CODE_SEGMENT(descriptor.type) && IS_CODE_SEGMENT_CONFORMING(descriptor.type)) { /* ignore DPL for conforming segments */ } else { if (descriptor.dpl < CPL || descriptor.dpl < selector.rpl) { clear_ZF(); BX_NEXT_INSTR(i); } } } else { /* system or gate segment */ switch (descriptor.type) { case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_BUSY_286_TSS: case BX_286_CALL_GATE: case BX_TASK_GATE: if (long_mode()) { BX_DEBUG(("LAR: descriptor type in not accepted in long mode")); clear_ZF(); BX_NEXT_INSTR(i); } /* fall through */ case BX_SYS_SEGMENT_LDT: case BX_SYS_SEGMENT_AVAIL_386_TSS: case BX_SYS_SEGMENT_BUSY_386_TSS: case BX_386_CALL_GATE: #if BX_SUPPORT_X86_64 if (long64_mode() || (descriptor.type == BX_386_CALL_GATE && long_mode()) ) { if (!fetch_raw_descriptor2_64(&selector, &dword1, &dword2, &dword3)) { BX_ERROR(("LAR: failed to fetch 64-bit descriptor")); clear_ZF(); BX_NEXT_INSTR(i); } } #endif break; default: /* rest not accepted types to LAR */ BX_DEBUG(("LAR: not accepted descriptor type")); clear_ZF(); BX_NEXT_INSTR(i); } if (descriptor.dpl < CPL || descriptor.dpl < selector.rpl) { clear_ZF(); BX_NEXT_INSTR(i); } } assert_ZF(); if (i->os32L()) { /* masked by 00FxFF00, where x is undefined */ BX_WRITE_32BIT_REGZ(i->dst(), dword2 & 0x00ffff00); } else { BX_WRITE_16BIT_REG(i->dst(), dword2 & 0xff00); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LSL_GvEw(bxInstruction_c *i) { /* for 16 bit operand size mode */ Bit16u raw_selector; Bit32u limit32; bx_selector_t selector; Bit32u dword1, dword2; #if BX_SUPPORT_X86_64 Bit32u dword3 = 0; #endif if (! protected_mode()) { BX_ERROR(("LSL: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } if (i->modC0()) { raw_selector = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ raw_selector = read_virtual_word(i->seg(), eaddr); } /* if selector null, clear ZF and done */ if ((raw_selector & 0xfffc) == 0) { clear_ZF(); BX_NEXT_INSTR(i); } parse_selector(raw_selector, &selector); if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) { BX_DEBUG(("LSL: failed to fetch descriptor")); clear_ZF(); BX_NEXT_INSTR(i); } Bit32u descriptor_dpl = (dword2 >> 13) & 0x03; if ((dword2 & 0x00001000) == 0) { // system segment Bit32u type = (dword2 >> 8) & 0x0000000f; switch (type) { case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_BUSY_286_TSS: if (long_mode()) { clear_ZF(); BX_NEXT_INSTR(i); } /* fall through */ case BX_SYS_SEGMENT_LDT: case BX_SYS_SEGMENT_AVAIL_386_TSS: case BX_SYS_SEGMENT_BUSY_386_TSS: #if BX_SUPPORT_X86_64 if (long64_mode()) { if (!fetch_raw_descriptor2_64(&selector, &dword1, &dword2, &dword3)) { BX_ERROR(("LSL: failed to fetch 64-bit descriptor")); clear_ZF(); BX_NEXT_INSTR(i); } } #endif if (descriptor_dpl < CPL || descriptor_dpl < selector.rpl) { clear_ZF(); BX_NEXT_INSTR(i); } limit32 = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000); if (dword2 & 0x00800000) limit32 = (limit32 << 12) | 0x00000fff; break; default: /* rest not accepted types to LSL */ clear_ZF(); BX_NEXT_INSTR(i); } } else { // data & code segment limit32 = (dword1 & 0x0000ffff) | (dword2 & 0x000f0000); if (dword2 & 0x00800000) limit32 = (limit32 << 12) | 0x00000fff; if ((dword2 & 0x00000c00) != 0x00000c00) { // non-conforming code segment if (descriptor_dpl < CPL || descriptor_dpl < selector.rpl) { clear_ZF(); BX_NEXT_INSTR(i); } } } /* all checks pass, limit32 is now byte granular, write to op1 */ assert_ZF(); if (i->os32L()) { BX_WRITE_32BIT_REGZ(i->dst(), limit32); } else { // chop off upper 16 bits BX_WRITE_16BIT_REG(i->dst(), (Bit16u) limit32); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SLDT_Ew(bxInstruction_c *i) { if (! protected_mode()) { BX_ERROR(("SLDT: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_LDTR_TR_ACCESS, BX_WRITE); #endif Bit16u val16 = BX_CPU_THIS_PTR ldtr.selector.value; if (i->modC0()) { if (i->os32L()) { BX_WRITE_32BIT_REGZ(i->dst(), val16); } else { BX_WRITE_16BIT_REG(i->dst(), val16); } } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ write_virtual_word(i->seg(), eaddr, val16); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STR_Ew(bxInstruction_c *i) { if (! protected_mode()) { BX_ERROR(("STR: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_LDTR_TR_ACCESS, BX_WRITE); #endif Bit16u val16 = BX_CPU_THIS_PTR tr.selector.value; if (i->modC0()) { if (i->os32L()) { BX_WRITE_32BIT_REGZ(i->dst(), val16); } else { BX_WRITE_16BIT_REG(i->dst(), val16); } } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ write_virtual_word(i->seg(), eaddr, val16); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LLDT_Ew(bxInstruction_c *i) { /* protected mode */ bx_descriptor_t descriptor; bx_selector_t selector; Bit16u raw_selector; Bit32u dword1, dword2; #if BX_SUPPORT_X86_64 Bit32u dword3 = 0; #endif if (! protected_mode()) { BX_ERROR(("LLDT: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } if (CPL != 0) { BX_ERROR(("LLDT: The current priveledge level is not 0")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_LDTR_TR_ACCESS, BX_READ); #endif if (i->modC0()) { raw_selector = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ raw_selector = read_virtual_word(i->seg(), eaddr); } /* if selector is NULL, invalidate and done */ if ((raw_selector & 0xfffc) == 0) { BX_CPU_THIS_PTR ldtr.selector.value = raw_selector; BX_CPU_THIS_PTR ldtr.cache.valid = 0; BX_NEXT_INSTR(i); } /* parse fields in selector */ parse_selector(raw_selector, &selector); // #GP(selector) if the selector operand does not point into GDT if (selector.ti != 0) { BX_ERROR(("LLDT: selector.ti != 0")); exception(BX_GP_EXCEPTION, raw_selector & 0xfffc); } /* fetch descriptor; call handles out of limits checks */ #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { fetch_raw_descriptor_64(&selector, &dword1, &dword2, &dword3, BX_GP_EXCEPTION); } else #endif { fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION); } parse_descriptor(dword1, dword2, &descriptor); /* if selector doesn't point to an LDT descriptor #GP(selector) */ if (descriptor.valid == 0 || descriptor.segment || descriptor.type != BX_SYS_SEGMENT_LDT) { BX_ERROR(("LLDT: doesn't point to an LDT descriptor!")); exception(BX_GP_EXCEPTION, raw_selector & 0xfffc); } /* #NP(selector) if LDT descriptor is not present */ if (! IS_PRESENT(descriptor)) { BX_ERROR(("LLDT: LDT descriptor not present!")); exception(BX_NP_EXCEPTION, raw_selector & 0xfffc); } #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { descriptor.u.segment.base |= ((Bit64u)(dword3) << 32); BX_DEBUG(("64 bit LDT base = 0x%08x%08x", GET32H(descriptor.u.segment.base), GET32L(descriptor.u.segment.base))); if (!IsCanonical(descriptor.u.segment.base)) { BX_ERROR(("LLDT: non-canonical LDT descriptor base!")); exception(BX_GP_EXCEPTION, raw_selector & 0xfffc); } } #endif BX_CPU_THIS_PTR ldtr.selector = selector; BX_CPU_THIS_PTR ldtr.cache = descriptor; BX_CPU_THIS_PTR ldtr.cache.valid = 1; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LTR_Ew(bxInstruction_c *i) { bx_descriptor_t descriptor; bx_selector_t selector; Bit16u raw_selector; Bit32u dword1, dword2; #if BX_SUPPORT_X86_64 Bit32u dword3 = 0; #endif if (! protected_mode()) { BX_ERROR(("LTR: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } if (CPL != 0) { BX_ERROR(("LTR: The current priveledge level is not 0")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_LDTR_TR_ACCESS, BX_READ); #endif if (i->modC0()) { raw_selector = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ raw_selector = read_virtual_word(i->seg(), eaddr); } /* if selector is NULL, invalidate and done */ if ((raw_selector & BX_SELECTOR_RPL_MASK) == 0) { BX_ERROR(("LTR: loading with NULL selector!")); exception(BX_GP_EXCEPTION, 0); } /* parse fields in selector, then check for null selector */ parse_selector(raw_selector, &selector); if (selector.ti) { BX_ERROR(("LTR: selector.ti != 0")); exception(BX_GP_EXCEPTION, raw_selector & 0xfffc); } /* fetch descriptor; call handles out of limits checks */ #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { fetch_raw_descriptor_64(&selector, &dword1, &dword2, &dword3, BX_GP_EXCEPTION); } else #endif { fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION); } parse_descriptor(dword1, dword2, &descriptor); /* #GP(selector) if object is not a TSS or is already busy */ if (descriptor.valid==0 || descriptor.segment || (descriptor.type!=BX_SYS_SEGMENT_AVAIL_286_TSS && descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS)) { BX_ERROR(("LTR: doesn't point to an available TSS descriptor!")); exception(BX_GP_EXCEPTION, raw_selector & 0xfffc); } #if BX_SUPPORT_X86_64 if (long_mode() && descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS) { BX_ERROR(("LTR: doesn't point to an available TSS386 descriptor in long mode!")); exception(BX_GP_EXCEPTION, raw_selector & 0xfffc); } #endif /* #NP(selector) if TSS descriptor is not present */ if (! IS_PRESENT(descriptor)) { BX_ERROR(("LTR: TSS descriptor not present!")); exception(BX_NP_EXCEPTION, raw_selector & 0xfffc); } #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { descriptor.u.segment.base |= ((Bit64u)(dword3) << 32); BX_DEBUG(("64 bit TSS base = 0x%08x%08x", GET32H(descriptor.u.segment.base), GET32L(descriptor.u.segment.base))); if (!IsCanonical(descriptor.u.segment.base)) { BX_ERROR(("LTR: non-canonical TSS descriptor base!")); exception(BX_GP_EXCEPTION, raw_selector & 0xfffc); } } #endif BX_CPU_THIS_PTR tr.selector = selector; BX_CPU_THIS_PTR tr.cache = descriptor; BX_CPU_THIS_PTR tr.cache.valid = 1; // tr.cache.type should not have busy bit, or it would not get // through the conditions above. BX_ASSERT((BX_CPU_THIS_PTR tr.cache.type & 2) == 0); BX_CPU_THIS_PTR tr.cache.type |= 2; // mark as busy /* mark as busy */ if (!(dword2 & 0x0200)) { dword2 |= 0x0200; /* set busy bit */ access_write_linear(BX_CPU_THIS_PTR gdtr.base + selector.index*8 + 4, 4, 0, &dword2); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VERR_Ew(bxInstruction_c *i) { /* for 16 bit operand size mode */ Bit16u raw_selector; bx_descriptor_t descriptor; bx_selector_t selector; Bit32u dword1, dword2; if (! protected_mode()) { BX_ERROR(("VERR: not recognized in real or virtual-8086 mode")); exception(BX_UD_EXCEPTION, 0); } if (i->modC0()) { raw_selector = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ raw_selector = read_virtual_word(i->seg(), eaddr); } /* if selector null, clear ZF and done */ if ((raw_selector & 0xfffc) == 0) { BX_DEBUG(("VERR: null selector")); clear_ZF(); BX_NEXT_INSTR(i); } /* if source selector is visible at CPL & RPL, * within the descriptor table, and of type accepted by VERR instruction, * then load register with segment limit and set ZF */ parse_selector(raw_selector, &selector); if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) { /* not within descriptor table */ BX_DEBUG(("VERR: not within descriptor table")); clear_ZF(); BX_NEXT_INSTR(i); } parse_descriptor(dword1, dword2, &descriptor); if (descriptor.segment==0) { /* system or gate descriptor */ BX_DEBUG(("VERR: system descriptor")); clear_ZF(); /* inaccessible */ BX_NEXT_INSTR(i); } if (descriptor.valid==0) { BX_DEBUG(("VERR: valid bit cleared")); clear_ZF(); /* inaccessible */ BX_NEXT_INSTR(i); } /* normal data/code segment */ if (IS_CODE_SEGMENT(descriptor.type)) { /* code segment */ /* ignore DPL for readable conforming segments */ if (IS_CODE_SEGMENT_CONFORMING(descriptor.type) && IS_CODE_SEGMENT_READABLE(descriptor.type)) { BX_DEBUG(("VERR: conforming code, OK")); assert_ZF(); /* accessible */ BX_NEXT_INSTR(i); } if (!IS_CODE_SEGMENT_READABLE(descriptor.type)) { BX_DEBUG(("VERR: code not readable")); clear_ZF(); /* inaccessible */ BX_NEXT_INSTR(i); } /* readable, non-conforming code segment */ if ((descriptor.dplmodC0()) { raw_selector = BX_READ_16BIT_REG(i->src()); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ raw_selector = read_virtual_word(i->seg(), eaddr); } /* if selector null, clear ZF and done */ if ((raw_selector & 0xfffc) == 0) { BX_DEBUG(("VERW: null selector")); clear_ZF(); BX_NEXT_INSTR(i); } /* if source selector is visible at CPL & RPL, * within the descriptor table, and of type accepted by VERW instruction, * then load register with segment limit and set ZF */ parse_selector(raw_selector, &selector); if (!fetch_raw_descriptor2(&selector, &dword1, &dword2)) { /* not within descriptor table */ BX_DEBUG(("VERW: not within descriptor table")); clear_ZF(); BX_NEXT_INSTR(i); } parse_descriptor(dword1, dword2, &descriptor); /* rule out system segments & code segments */ if (descriptor.segment==0 || IS_CODE_SEGMENT(descriptor.type)) { BX_DEBUG(("VERW: system seg or code")); clear_ZF(); BX_NEXT_INSTR(i); } if (descriptor.valid==0) { BX_DEBUG(("VERW: valid bit cleared")); clear_ZF(); BX_NEXT_INSTR(i); } /* data segment */ if (IS_DATA_SEGMENT_WRITEABLE(descriptor.type)) { /* writable */ if ((descriptor.dpl= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_WRITE); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_READ)) Svm_Vmexit(SVM_VMEXIT_GDTR_READ); } #endif Bit16u limit_16 = BX_CPU_THIS_PTR gdtr.limit; Bit32u base_32 = (Bit32u) BX_CPU_THIS_PTR gdtr.base; Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word_32(i->seg(), eaddr, limit_16); write_virtual_dword_32(i->seg(), (eaddr+2) & i->asize_mask(), base_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT_Ms(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_WRITE); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_READ)) Svm_Vmexit(SVM_VMEXIT_IDTR_READ); } #endif Bit16u limit_16 = BX_CPU_THIS_PTR idtr.limit; Bit32u base_32 = (Bit32u) BX_CPU_THIS_PTR idtr.base; Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word_32(i->seg(), eaddr, limit_16); write_virtual_dword_32(i->seg(), (eaddr+2) & i->asize_mask(), base_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT_Ms(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); // CPL is always 0 is real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("LGDT: CPL != 0 causes #GP")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_READ); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_GDTR_WRITE); } #endif Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u limit_16 = read_virtual_word_32(i->seg(), eaddr); Bit32u base_32 = read_virtual_dword_32(i->seg(), (eaddr + 2) & i->asize_mask()); if (i->os32L() == 0) base_32 &= 0x00ffffff; /* ignore upper 8 bits */ BX_CPU_THIS_PTR gdtr.limit = limit_16; BX_CPU_THIS_PTR gdtr.base = base_32; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT_Ms(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); // CPL is always 0 is real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("LIDT: CPL != 0 causes #GP")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_READ); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_IDTR_WRITE); } #endif Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u limit_16 = read_virtual_word_32(i->seg(), eaddr); Bit32u base_32 = read_virtual_dword_32(i->seg(), (eaddr + 2) & i->asize_mask()); if (i->os32L() == 0) base_32 &= 0x00ffffff; /* ignore upper 8 bits */ BX_CPU_THIS_PTR idtr.limit = limit_16; BX_CPU_THIS_PTR idtr.base = base_32; BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SGDT64_Ms(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_WRITE); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_READ)) Svm_Vmexit(SVM_VMEXIT_GDTR_READ); } #endif Bit16u limit_16 = BX_CPU_THIS_PTR gdtr.limit; Bit64u base_64 = BX_CPU_THIS_PTR gdtr.base; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word_64(i->seg(), eaddr, limit_16); write_virtual_qword_64(i->seg(), (eaddr+2) & i->asize_mask(), base_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SIDT64_Ms(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_WRITE); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_READ)) Svm_Vmexit(SVM_VMEXIT_IDTR_READ); } #endif Bit16u limit_16 = BX_CPU_THIS_PTR idtr.limit; Bit64u base_64 = BX_CPU_THIS_PTR idtr.base; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word_64(i->seg(), eaddr, limit_16); write_virtual_qword_64(i->seg(), (eaddr+2) & i->asize_mask(), base_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LGDT64_Ms(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); if (CPL!=0) { BX_ERROR(("LGDT64_Ms: CPL != 0 in long mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_READ); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_GDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_GDTR_WRITE); } #endif bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u base_64 = read_virtual_qword_64(i->seg(), (eaddr + 2) & i->asize_mask()); if (! IsCanonical(base_64)) { BX_ERROR(("LGDT64_Ms: loaded base64 address is not in canonical form!")); exception(BX_GP_EXCEPTION, 0); } Bit16u limit_16 = read_virtual_word_64(i->seg(), eaddr); BX_CPU_THIS_PTR gdtr.limit = limit_16; BX_CPU_THIS_PTR gdtr.base = base_64; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LIDT64_Ms(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); if (CPL != 0) { BX_ERROR(("LIDT64_Ms: CPL != 0 in long mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest) if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_DESCRIPTOR_TABLE_VMEXIT)) VMexit_Instruction(i, VMX_VMEXIT_GDTR_IDTR_ACCESS, BX_READ); #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_IDTR_WRITE)) Svm_Vmexit(SVM_VMEXIT_IDTR_WRITE); } #endif bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u base_64 = read_virtual_qword_64(i->seg(), (eaddr + 2) & i->asize_mask()); if (! IsCanonical(base_64)) { BX_ERROR(("LIDT64_Ms: loaded base64 address is not in canonical form!")); exception(BX_GP_EXCEPTION, 0); } Bit16u limit_16 = read_virtual_word_64(i->seg(), eaddr); BX_CPU_THIS_PTR idtr.limit = limit_16; BX_CPU_THIS_PTR idtr.base = base_64; BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/smm.cc0000644000175000017500000010530312020641453014226 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: smm.cc 11305 2012-08-01 14:56:51Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #include "smm.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 3 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RSM(bxInstruction_c *i) { /* If we are not in System Management Mode, then #UD should be generated */ if (! BX_CPU_THIS_PTR smm_mode()) { BX_INFO(("RSM not in System Management Mode !")); exception(BX_UD_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx) { if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: RSM in VMX non-root operation")); VMexit(VMX_VMEXIT_RSM, 0); } else { BX_ERROR(("RSM in VMX root operation !")); exception(BX_UD_EXCEPTION, 0); } } #endif BX_INFO(("RSM: Resuming from System Management Mode")); BX_CPU_THIS_PTR disable_NMI = 0; Bit32u saved_state[SMM_SAVE_STATE_MAP_SIZE], n; // reset reserved bits for(n=0;n= 5 BX_CPU_THIS_PTR cr4.set32(0); #endif #if BX_CPU_LEVEL >= 5 BX_CPU_THIS_PTR efer.set32(0); #endif parse_selector(BX_CPU_THIS_PTR smbase >> 4, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = BX_CPU_THIS_PTR smbase; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xffffffff; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* page granular */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 0; /* 16bit default size */ #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = 0; /* 16bit default size */ #endif /* DS (Data Segment) and descriptor cache */ parse_selector(0x0000, &BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xffffffff; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.avl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.g = 1; /* byte granular */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 0; /* 16bit default size */ #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.u.segment.l = 0; /* 16bit default size */ #endif // use DS segment as template for the others BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS] = BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]; handleCpuContextChange(); #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_CONTEXT_SWITCH, 0); } #define SMRAM_TRANSLATE(addr) (((0x8000 - (addr)) >> 2) - 1) // SMRAM SMM_SAVE_STATE_MAP_SIZE is 128 elements, find the element for each field static unsigned smram_map[SMRAM_FIELD_LAST]; #if BX_SUPPORT_X86_64 void BX_CPU_C::init_SMRAM(void) { static bx_bool smram_map_ready = 0; if (smram_map_ready) return; smram_map_ready = 1; smram_map[SMRAM_FIELD_SMBASE_OFFSET] = SMRAM_TRANSLATE(0x7f00); smram_map[SMRAM_FIELD_SMM_REVISION_ID] = SMRAM_TRANSLATE(0x7efc); smram_map[SMRAM_FIELD_RAX_HI32] = SMRAM_TRANSLATE(0x7ffc); smram_map[SMRAM_FIELD_EAX] = SMRAM_TRANSLATE(0x7ff8); smram_map[SMRAM_FIELD_RCX_HI32] = SMRAM_TRANSLATE(0x7ff4); smram_map[SMRAM_FIELD_ECX] = SMRAM_TRANSLATE(0x7ff0); smram_map[SMRAM_FIELD_RDX_HI32] = SMRAM_TRANSLATE(0x7fec); smram_map[SMRAM_FIELD_EDX] = SMRAM_TRANSLATE(0x7fe8); smram_map[SMRAM_FIELD_RBX_HI32] = SMRAM_TRANSLATE(0x7fe4); smram_map[SMRAM_FIELD_EBX] = SMRAM_TRANSLATE(0x7fe0); smram_map[SMRAM_FIELD_RSP_HI32] = SMRAM_TRANSLATE(0x7fdc); smram_map[SMRAM_FIELD_ESP] = SMRAM_TRANSLATE(0x7fd8); smram_map[SMRAM_FIELD_RBP_HI32] = SMRAM_TRANSLATE(0x7fd4); smram_map[SMRAM_FIELD_EBP] = SMRAM_TRANSLATE(0x7fd0); smram_map[SMRAM_FIELD_RSI_HI32] = SMRAM_TRANSLATE(0x7fcc); smram_map[SMRAM_FIELD_ESI] = SMRAM_TRANSLATE(0x7fc8); smram_map[SMRAM_FIELD_RDI_HI32] = SMRAM_TRANSLATE(0x7fc4); smram_map[SMRAM_FIELD_EDI] = SMRAM_TRANSLATE(0x7fc0); smram_map[SMRAM_FIELD_R8_HI32] = SMRAM_TRANSLATE(0x7fbc); smram_map[SMRAM_FIELD_R8] = SMRAM_TRANSLATE(0x7fb8); smram_map[SMRAM_FIELD_R9_HI32] = SMRAM_TRANSLATE(0x7fb4); smram_map[SMRAM_FIELD_R9] = SMRAM_TRANSLATE(0x7fb0); smram_map[SMRAM_FIELD_R10_HI32] = SMRAM_TRANSLATE(0x7fac); smram_map[SMRAM_FIELD_R10] = SMRAM_TRANSLATE(0x7fa8); smram_map[SMRAM_FIELD_R11_HI32] = SMRAM_TRANSLATE(0x7fa4); smram_map[SMRAM_FIELD_R11] = SMRAM_TRANSLATE(0x7fa0); smram_map[SMRAM_FIELD_R12_HI32] = SMRAM_TRANSLATE(0x7f9c); smram_map[SMRAM_FIELD_R12] = SMRAM_TRANSLATE(0x7f98); smram_map[SMRAM_FIELD_R13_HI32] = SMRAM_TRANSLATE(0x7f94); smram_map[SMRAM_FIELD_R13] = SMRAM_TRANSLATE(0x7f90); smram_map[SMRAM_FIELD_R14_HI32] = SMRAM_TRANSLATE(0x7f8c); smram_map[SMRAM_FIELD_R14] = SMRAM_TRANSLATE(0x7f88); smram_map[SMRAM_FIELD_R15_HI32] = SMRAM_TRANSLATE(0x7f84); smram_map[SMRAM_FIELD_R15] = SMRAM_TRANSLATE(0x7f80); smram_map[SMRAM_FIELD_RIP_HI32] = SMRAM_TRANSLATE(0x7f7c); smram_map[SMRAM_FIELD_EIP] = SMRAM_TRANSLATE(0x7f78); smram_map[SMRAM_FIELD_RFLAGS_HI32] = SMRAM_TRANSLATE(0x7f74); // always zero smram_map[SMRAM_FIELD_EFLAGS] = SMRAM_TRANSLATE(0x7f70); smram_map[SMRAM_FIELD_DR6_HI32] = SMRAM_TRANSLATE(0x7f6c); // always zero smram_map[SMRAM_FIELD_DR6] = SMRAM_TRANSLATE(0x7f68); smram_map[SMRAM_FIELD_DR7_HI32] = SMRAM_TRANSLATE(0x7f64); // always zero smram_map[SMRAM_FIELD_DR7] = SMRAM_TRANSLATE(0x7f60); smram_map[SMRAM_FIELD_CR0_HI32] = SMRAM_TRANSLATE(0x7f5c); // always zero smram_map[SMRAM_FIELD_CR0] = SMRAM_TRANSLATE(0x7f58); smram_map[SMRAM_FIELD_CR3_HI32] = SMRAM_TRANSLATE(0x7f54); // zero when physical address size 32-bit smram_map[SMRAM_FIELD_CR3] = SMRAM_TRANSLATE(0x7f50); smram_map[SMRAM_FIELD_CR4_HI32] = SMRAM_TRANSLATE(0x7f4c); // always zero smram_map[SMRAM_FIELD_CR4] = SMRAM_TRANSLATE(0x7f48); smram_map[SMRAM_FIELD_EFER_HI32] = SMRAM_TRANSLATE(0x7ed4); // always zero smram_map[SMRAM_FIELD_EFER] = SMRAM_TRANSLATE(0x7ed0); smram_map[SMRAM_FIELD_IO_INSTRUCTION_RESTART] = SMRAM_TRANSLATE(0x7ec8); smram_map[SMRAM_FIELD_AUTOHALT_RESTART] = SMRAM_TRANSLATE(0x7ec8); smram_map[SMRAM_FIELD_NMI_MASK] = SMRAM_TRANSLATE(0x7ec8); smram_map[SMRAM_FIELD_TR_BASE_HI32] = SMRAM_TRANSLATE(0x7e9c); smram_map[SMRAM_FIELD_TR_BASE] = SMRAM_TRANSLATE(0x7e98); smram_map[SMRAM_FIELD_TR_LIMIT] = SMRAM_TRANSLATE(0x7e94); smram_map[SMRAM_FIELD_TR_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e90); smram_map[SMRAM_FIELD_IDTR_BASE_HI32] = SMRAM_TRANSLATE(0x7e8c); smram_map[SMRAM_FIELD_IDTR_BASE] = SMRAM_TRANSLATE(0x7e88); smram_map[SMRAM_FIELD_IDTR_LIMIT] = SMRAM_TRANSLATE(0x7e84); smram_map[SMRAM_FIELD_LDTR_BASE_HI32] = SMRAM_TRANSLATE(0x7e7c); smram_map[SMRAM_FIELD_LDTR_BASE] = SMRAM_TRANSLATE(0x7e78); smram_map[SMRAM_FIELD_LDTR_LIMIT] = SMRAM_TRANSLATE(0x7e74); smram_map[SMRAM_FIELD_LDTR_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e70); smram_map[SMRAM_FIELD_GDTR_BASE_HI32] = SMRAM_TRANSLATE(0x7e6c); smram_map[SMRAM_FIELD_GDTR_BASE] = SMRAM_TRANSLATE(0x7e68); smram_map[SMRAM_FIELD_GDTR_LIMIT] = SMRAM_TRANSLATE(0x7e64); smram_map[SMRAM_FIELD_ES_BASE_HI32] = SMRAM_TRANSLATE(0x7e0c); smram_map[SMRAM_FIELD_ES_BASE] = SMRAM_TRANSLATE(0x7e08); smram_map[SMRAM_FIELD_ES_LIMIT] = SMRAM_TRANSLATE(0x7e04); smram_map[SMRAM_FIELD_ES_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e00); smram_map[SMRAM_FIELD_CS_BASE_HI32] = SMRAM_TRANSLATE(0x7e1c); smram_map[SMRAM_FIELD_CS_BASE] = SMRAM_TRANSLATE(0x7e18); smram_map[SMRAM_FIELD_CS_LIMIT] = SMRAM_TRANSLATE(0x7e14); smram_map[SMRAM_FIELD_CS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e10); smram_map[SMRAM_FIELD_SS_BASE_HI32] = SMRAM_TRANSLATE(0x7e2c); smram_map[SMRAM_FIELD_SS_BASE] = SMRAM_TRANSLATE(0x7e28); smram_map[SMRAM_FIELD_SS_LIMIT] = SMRAM_TRANSLATE(0x7e24); smram_map[SMRAM_FIELD_SS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e20); smram_map[SMRAM_FIELD_DS_BASE_HI32] = SMRAM_TRANSLATE(0x7e3c); smram_map[SMRAM_FIELD_DS_BASE] = SMRAM_TRANSLATE(0x7e38); smram_map[SMRAM_FIELD_DS_LIMIT] = SMRAM_TRANSLATE(0x7e34); smram_map[SMRAM_FIELD_DS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e30); smram_map[SMRAM_FIELD_FS_BASE_HI32] = SMRAM_TRANSLATE(0x7e4c); smram_map[SMRAM_FIELD_FS_BASE] = SMRAM_TRANSLATE(0x7e48); smram_map[SMRAM_FIELD_FS_LIMIT] = SMRAM_TRANSLATE(0x7e44); smram_map[SMRAM_FIELD_FS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e40); smram_map[SMRAM_FIELD_GS_BASE_HI32] = SMRAM_TRANSLATE(0x7e5c); smram_map[SMRAM_FIELD_GS_BASE] = SMRAM_TRANSLATE(0x7e58); smram_map[SMRAM_FIELD_GS_LIMIT] = SMRAM_TRANSLATE(0x7e54); smram_map[SMRAM_FIELD_GS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7e50); for (unsigned n=0; n= SMM_SAVE_STATE_MAP_SIZE) { BX_PANIC(("smram map[%d] = %d", n, smram_map[n])); } } } #else // source for Intel P6 SMM save state map used: www.sandpile.org void BX_CPU_C::init_SMRAM(void) { smram_map[SMRAM_FIELD_SMBASE_OFFSET] = SMRAM_TRANSLATE(0x7ef8); smram_map[SMRAM_FIELD_SMM_REVISION_ID] = SMRAM_TRANSLATE(0x7efc); smram_map[SMRAM_FIELD_EAX] = SMRAM_TRANSLATE(0x7fd0); smram_map[SMRAM_FIELD_ECX] = SMRAM_TRANSLATE(0x7fd4); smram_map[SMRAM_FIELD_EDX] = SMRAM_TRANSLATE(0x7fd8); smram_map[SMRAM_FIELD_EBX] = SMRAM_TRANSLATE(0x7fdc); smram_map[SMRAM_FIELD_ESP] = SMRAM_TRANSLATE(0x7fe0); smram_map[SMRAM_FIELD_EBP] = SMRAM_TRANSLATE(0x7fe4); smram_map[SMRAM_FIELD_ESI] = SMRAM_TRANSLATE(0x7fe8); smram_map[SMRAM_FIELD_EDI] = SMRAM_TRANSLATE(0x7fec); smram_map[SMRAM_FIELD_EIP] = SMRAM_TRANSLATE(0x7ff0); smram_map[SMRAM_FIELD_EFLAGS] = SMRAM_TRANSLATE(0x7ff4); smram_map[SMRAM_FIELD_DR6] = SMRAM_TRANSLATE(0x7fcc); smram_map[SMRAM_FIELD_DR7] = SMRAM_TRANSLATE(0x7fc8); smram_map[SMRAM_FIELD_CR0] = SMRAM_TRANSLATE(0x7ffc); smram_map[SMRAM_FIELD_CR3] = SMRAM_TRANSLATE(0x7ff8); smram_map[SMRAM_FIELD_CR4] = SMRAM_TRANSLATE(0x7f14); smram_map[SMRAM_FIELD_EFER] = SMRAM_TRANSLATE(0x7f10); smram_map[SMRAM_FIELD_IO_INSTRUCTION_RESTART] = SMRAM_TRANSLATE(0x7f00); smram_map[SMRAM_FIELD_AUTOHALT_RESTART] = SMRAM_TRANSLATE(0x7f00); smram_map[SMRAM_FIELD_NMI_MASK] = SMRAM_TRANSLATE(0x7f00); smram_map[SMRAM_FIELD_TR_SELECTOR] = SMRAM_TRANSLATE(0x7fc4); smram_map[SMRAM_FIELD_TR_BASE] = SMRAM_TRANSLATE(0x7f64); smram_map[SMRAM_FIELD_TR_LIMIT] = SMRAM_TRANSLATE(0x7f60); smram_map[SMRAM_FIELD_TR_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f5c); smram_map[SMRAM_FIELD_LDTR_SELECTOR] = SMRAM_TRANSLATE(0x7fc0); smram_map[SMRAM_FIELD_LDTR_BASE] = SMRAM_TRANSLATE(0x7f80); smram_map[SMRAM_FIELD_LDTR_LIMIT] = SMRAM_TRANSLATE(0x7f7c); smram_map[SMRAM_FIELD_LDTR_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f78); smram_map[SMRAM_FIELD_IDTR_BASE] = SMRAM_TRANSLATE(0x7f58); smram_map[SMRAM_FIELD_IDTR_LIMIT] = SMRAM_TRANSLATE(0x7f54); smram_map[SMRAM_FIELD_GDTR_BASE] = SMRAM_TRANSLATE(0x7f74); smram_map[SMRAM_FIELD_GDTR_LIMIT] = SMRAM_TRANSLATE(0x7f70); smram_map[SMRAM_FIELD_ES_SELECTOR] = SMRAM_TRANSLATE(0x7fa8); smram_map[SMRAM_FIELD_ES_BASE] = SMRAM_TRANSLATE(0x7f8c); smram_map[SMRAM_FIELD_ES_LIMIT] = SMRAM_TRANSLATE(0x7f88); smram_map[SMRAM_FIELD_ES_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f84); smram_map[SMRAM_FIELD_CS_SELECTOR] = SMRAM_TRANSLATE(0x7fac); smram_map[SMRAM_FIELD_CS_BASE] = SMRAM_TRANSLATE(0x7f98); smram_map[SMRAM_FIELD_CS_LIMIT] = SMRAM_TRANSLATE(0x7f94); smram_map[SMRAM_FIELD_CS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f90); smram_map[SMRAM_FIELD_SS_SELECTOR] = SMRAM_TRANSLATE(0x7fb0); smram_map[SMRAM_FIELD_SS_BASE] = SMRAM_TRANSLATE(0x7fa4); smram_map[SMRAM_FIELD_SS_LIMIT] = SMRAM_TRANSLATE(0x7fa0); smram_map[SMRAM_FIELD_SS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f9c); smram_map[SMRAM_FIELD_DS_SELECTOR] = SMRAM_TRANSLATE(0x7fb4); smram_map[SMRAM_FIELD_DS_BASE] = SMRAM_TRANSLATE(0x7f34); smram_map[SMRAM_FIELD_DS_LIMIT] = SMRAM_TRANSLATE(0x7f30); smram_map[SMRAM_FIELD_DS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f2c); smram_map[SMRAM_FIELD_FS_SELECTOR] = SMRAM_TRANSLATE(0x7fb8); smram_map[SMRAM_FIELD_FS_BASE] = SMRAM_TRANSLATE(0x7f40); smram_map[SMRAM_FIELD_FS_LIMIT] = SMRAM_TRANSLATE(0x7f3c); smram_map[SMRAM_FIELD_FS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f38); smram_map[SMRAM_FIELD_GS_SELECTOR] = SMRAM_TRANSLATE(0x7fbc); smram_map[SMRAM_FIELD_GS_BASE] = SMRAM_TRANSLATE(0x7f4c); smram_map[SMRAM_FIELD_GS_LIMIT] = SMRAM_TRANSLATE(0x7f48); smram_map[SMRAM_FIELD_GS_SELECTOR_AR] = SMRAM_TRANSLATE(0x7f44); for (unsigned n=0; n= SMM_SAVE_STATE_MAP_SIZE) { BX_PANIC(("smram map[%d] = %d", n, smram_map[n])); } } } #endif #define SMRAM_FIELD(state, field) (state[smram_map[field]]) #if BX_SUPPORT_X86_64 BX_CPP_INLINE Bit64u SMRAM_FIELD64(const Bit32u *saved_state, unsigned hi, unsigned lo) { Bit64u tmp = ((Bit64u) SMRAM_FIELD(saved_state, hi)) << 32; tmp |= (Bit64u) SMRAM_FIELD(saved_state, lo); return tmp; } void BX_CPU_C::smram_save_state(Bit32u *saved_state) { // --- General Purpose Registers --- // for (int n=0; n> 8) & 0xf0ff) | (BX_CPU_THIS_PTR tr.cache.valid << 8); SMRAM_FIELD(saved_state, SMRAM_FIELD_TR_SELECTOR_AR) = BX_CPU_THIS_PTR tr.selector.value | (tr_ar << 16); // --- LDTR --- // SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_BASE_HI32) = GET32H(BX_CPU_THIS_PTR ldtr.cache.u.segment.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_BASE) = GET32L(BX_CPU_THIS_PTR ldtr.cache.u.segment.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_LIMIT) = BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled; Bit32u ldtr_ar = ((get_descriptor_h(&BX_CPU_THIS_PTR ldtr.cache) >> 8) & 0xf0ff) | (BX_CPU_THIS_PTR ldtr.cache.valid << 8); SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_SELECTOR_AR) = BX_CPU_THIS_PTR ldtr.selector.value | (ldtr_ar << 16); // --- IDTR --- // SMRAM_FIELD(saved_state, SMRAM_FIELD_IDTR_BASE_HI32) = GET32H(BX_CPU_THIS_PTR idtr.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_IDTR_BASE) = GET32L(BX_CPU_THIS_PTR idtr.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_IDTR_LIMIT) = BX_CPU_THIS_PTR idtr.limit; // --- GDTR --- // SMRAM_FIELD(saved_state, SMRAM_FIELD_GDTR_BASE_HI32) = GET32H(BX_CPU_THIS_PTR gdtr.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_GDTR_BASE) = GET32L(BX_CPU_THIS_PTR gdtr.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_GDTR_LIMIT) = BX_CPU_THIS_PTR gdtr.limit; for (int segreg = 0; segreg < 6; segreg++) { bx_segment_reg_t *seg = &(BX_CPU_THIS_PTR sregs[segreg]); SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_BASE_HI32 + 4*segreg) = GET32H(seg->cache.u.segment.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_BASE + 4*segreg) = GET32L(seg->cache.u.segment.base); SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_LIMIT + 4*segreg) = seg->cache.u.segment.limit_scaled; Bit32u seg_ar = ((get_descriptor_h(&seg->cache) >> 8) & 0xf0ff) | (seg->cache.valid << 8); SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_SELECTOR_AR + 4*segreg) = seg->selector.value | (seg_ar << 16); } } bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state) { BX_SMM_State smm_state; smm_state.smm_revision_id = SMRAM_FIELD(saved_state, SMRAM_FIELD_SMM_REVISION_ID); smm_state.cr0.val32 = SMRAM_FIELD(saved_state, SMRAM_FIELD_CR0); smm_state.cr3 = SMRAM_FIELD64(saved_state, SMRAM_FIELD_CR3_HI32, SMRAM_FIELD_CR3); smm_state.cr4.val32 = SMRAM_FIELD(saved_state, SMRAM_FIELD_CR4); smm_state.efer.val32 = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFER); smm_state.eflags = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFLAGS); for (int n=0; n= 5 SMRAM_FIELD(saved_state, SMRAM_FIELD_CR4) = BX_CPU_THIS_PTR cr4.get32(); SMRAM_FIELD(saved_state, SMRAM_FIELD_EFER) = BX_CPU_THIS_PTR efer.get32(); #endif SMRAM_FIELD(saved_state, SMRAM_FIELD_DR6) = BX_CPU_THIS_PTR dr6.get32(); SMRAM_FIELD(saved_state, SMRAM_FIELD_DR7) = BX_CPU_THIS_PTR dr7.get32(); // --- Task Register --- // SMRAM_FIELD(saved_state, SMRAM_FIELD_TR_SELECTOR) = BX_CPU_THIS_PTR tr.selector.value; SMRAM_FIELD(saved_state, SMRAM_FIELD_TR_BASE) = BX_CPU_THIS_PTR tr.cache.u.segment.base; SMRAM_FIELD(saved_state, SMRAM_FIELD_TR_LIMIT) = BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled; Bit32u tr_ar = ((get_descriptor_h(&BX_CPU_THIS_PTR tr.cache) >> 8) & 0xf0ff) | (BX_CPU_THIS_PTR tr.cache.valid << 8); SMRAM_FIELD(saved_state, SMRAM_FIELD_TR_SELECTOR_AR) = BX_CPU_THIS_PTR tr.selector.value | (tr_ar << 16); // --- LDTR --- // SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_SELECTOR) = BX_CPU_THIS_PTR ldtr.selector.value; SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_BASE) = BX_CPU_THIS_PTR ldtr.cache.u.segment.base; SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_LIMIT) = BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled; Bit32u ldtr_ar = ((get_descriptor_h(&BX_CPU_THIS_PTR ldtr.cache) >> 8) & 0xf0ff) | (BX_CPU_THIS_PTR ldtr.cache.valid << 8); SMRAM_FIELD(saved_state, SMRAM_FIELD_LDTR_SELECTOR_AR) = BX_CPU_THIS_PTR ldtr.selector.value | (ldtr_ar << 16); // --- IDTR --- // SMRAM_FIELD(saved_state, SMRAM_FIELD_IDTR_BASE) = BX_CPU_THIS_PTR idtr.base; SMRAM_FIELD(saved_state, SMRAM_FIELD_IDTR_LIMIT) = BX_CPU_THIS_PTR idtr.limit; // --- GDTR --- // SMRAM_FIELD(saved_state, SMRAM_FIELD_GDTR_BASE) = BX_CPU_THIS_PTR gdtr.base; SMRAM_FIELD(saved_state, SMRAM_FIELD_GDTR_LIMIT) = BX_CPU_THIS_PTR gdtr.limit; for (int segreg = 0; segreg < 6; segreg++) { bx_segment_reg_t *seg = &(BX_CPU_THIS_PTR sregs[segreg]); SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_SELECTOR + 4*segreg) = seg->selector.value; SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_BASE + 4*segreg) = seg->cache.u.segment.base; SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_LIMIT + 4*segreg) = seg->cache.u.segment.limit_scaled; Bit32u seg_ar = ((get_descriptor_h(&seg->cache) >> 8) & 0xf0ff) | (seg->cache.valid << 8); SMRAM_FIELD(saved_state, SMRAM_FIELD_ES_SELECTOR_AR + 4*segreg) = seg->selector.value | (seg_ar << 16); } } bx_bool BX_CPU_C::smram_restore_state(const Bit32u *saved_state) { BX_SMM_State smm_state; smm_state.smm_revision_id = SMRAM_FIELD(saved_state, SMRAM_FIELD_SMM_REVISION_ID); smm_state.cr0.val32 = SMRAM_FIELD(saved_state, SMRAM_FIELD_CR0); smm_state.cr3 = SMRAM_FIELD(saved_state, SMRAM_FIELD_CR3); #if BX_CPU_LEVEL >= 5 smm_state.cr4.val32 = SMRAM_FIELD(saved_state, SMRAM_FIELD_CR4); smm_state.efer.val32 = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFER); #endif smm_state.eflags = SMRAM_FIELD(saved_state, SMRAM_FIELD_EFLAGS); for (int n=0; ncr4.get_VMXE()) { BX_PANIC(("SMM restore: CR4.VMXE is set in restore image !")); return 0; } // restore state normally from SMRAM; // CR4.VMXE = value stored internally; // IF internal storage indicates that the logical processor had been in VMX operation (root or non-root) // THEN // enter VMX operation (root or non-root); // restore VMX-critical state // set CR0.PE, CR0.NE, and CR0.PG to 1; // IF RFLAGS.VM = 0 // THEN // CS.RPL = SS.DPL; // SS.RPL = SS.DPL; // FI; // If necessary, restore current VMCS pointer; // Leave SMM; Deassert SMMEM on subsequent bus transactions; // IF logical processor will be in VMX operation after RSM // THEN // block A20M and leave A20M mode; // FI; if (BX_CPU_THIS_PTR in_smm_vmx) { BX_CPU_THIS_PTR in_vmx = 1; BX_CPU_THIS_PTR in_vmx_guest = BX_CPU_THIS_PTR in_smm_vmx_guest; BX_INFO(("SMM Restore: enable VMX %s mode", BX_CPU_THIS_PTR in_vmx_guest ? "guest" : "host")); smm_state->cr0.set_PG(1); // set CR0.PG, CR0.NE and CR0.PE smm_state->cr0.set_NE(1); smm_state->cr0.set_PE(1); smm_state->cr4.set_VMXE(1); // block and disable A20M; } #endif // check CR0 conditions for entering to shutdown state if (!check_CR0(smm_state->cr0.get32())) { BX_PANIC(("SMM restore: CR0 consistency check failed !")); return 0; } #if BX_CPU_LEVEL >= 5 if (!check_CR4(smm_state->cr4.get32())) { BX_PANIC(("SMM restore: CR4 consistency check failed !")); return 0; } // shutdown if write to reserved CR4 bits if (!SetCR4(smm_state->cr4.get32())) { BX_PANIC(("SMM restore: incorrect CR4 state !")); return 0; } if (smm_state->efer.get32() & ~((Bit64u) BX_CPU_THIS_PTR efer_suppmask)) { BX_PANIC(("SMM restore: Attempt to set EFER reserved bits: 0x%08x !", smm_state->efer.get32())); return 0; } BX_CPU_THIS_PTR efer.set32(smm_state->efer.val32); #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR efer.get_LMA()) { if (smm_state->eflags & EFlagsVMMask) { BX_PANIC(("SMM restore: If EFER.LMA = 1 => RFLAGS.VM=0 !")); return 0; } if (!BX_CPU_THIS_PTR cr4.get_PAE() || !smm_state->cr0.get_PG() || !smm_state->cr0.get_PE() || !BX_CPU_THIS_PTR efer.get_LME()) { BX_PANIC(("SMM restore: If EFER.LMA = 1 <=> CR4.PAE, CR0.PG, CR0.PE, EFER.LME=1 !")); return 0; } } else { if (BX_CPU_THIS_PTR cr4.get_PCIDE()) { BX_PANIC(("SMM restore: CR4.PCIDE must be clear when not in long mode !")); return 0; } } if (BX_CPU_THIS_PTR cr4.get_PAE() && smm_state->cr0.get_PG() && smm_state->cr0.get_PE() && BX_CPU_THIS_PTR efer.get_LME()) { if (! BX_CPU_THIS_PTR efer.get_LMA()) { BX_PANIC(("SMM restore: If EFER.LMA = 1 <=> CR4.PAE, CR0.PG, CR0.PE, EFER.LME=1 !")); return 0; } } #endif #endif // hack CR0 to be able to back to long mode correctly BX_CPU_THIS_PTR cr0.set_PE(0); // real mode (bit 0) BX_CPU_THIS_PTR cr0.set_PG(0); // paging disabled (bit 31) if (! SetCR0(smm_state->cr0.get32())) { BX_PANIC(("SMM restore: failed to restore CR0 !")); return 0; } setEFlags(smm_state->eflags); if (!SetCR3(smm_state->cr3)) { BX_PANIC(("SMM restore: failed to restore CR3 !")); return 0; } #if BX_CPU_LEVEL >= 6 if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) { if (! CheckPDPTR(smm_state->cr3)) { BX_ERROR(("SMM restore: PDPTR check failed !")); return 0; } } #endif #if BX_SUPPORT_X86_64 for (int n=0; ngen_reg[n]); #else for (int n=0; ngen_reg[n]); #endif RIP = BX_CPU_THIS_PTR prev_rip = smm_state->rip; BX_CPU_THIS_PTR dr6.val32 = smm_state->dr6; BX_CPU_THIS_PTR dr7.val32 = smm_state->dr7; BX_CPU_THIS_PTR gdtr = smm_state->gdtr; BX_CPU_THIS_PTR idtr = smm_state->idtr; for (int segreg = 0; segreg < 6; segreg++) { Bit16u ar_data = smm_state->segreg[segreg].selector_ar >> 16; if (set_segment_ar_data(&BX_CPU_THIS_PTR sregs[segreg], (ar_data >> 8) & 1, smm_state->segreg[segreg].selector_ar & 0xf0ff, smm_state->segreg[segreg].base, smm_state->segreg[segreg].limit, ar_data)) { if (! BX_CPU_THIS_PTR sregs[segreg].cache.segment) { BX_PANIC(("SMM restore: restored valid non segment %d !", segreg)); return 0; } } } Bit16u ar_data = smm_state->ldtr.selector_ar >> 16; if (set_segment_ar_data(&BX_CPU_THIS_PTR ldtr, (ar_data >> 8) & 1, smm_state->ldtr.selector_ar & 0xf0ff, smm_state->ldtr.base, smm_state->ldtr.limit, ar_data)) { if (BX_CPU_THIS_PTR ldtr.cache.type != BX_SYS_SEGMENT_LDT) { BX_PANIC(("SMM restore: LDTR is not LDT descriptor type !")); return 0; } } ar_data = smm_state->tr.selector_ar >> 16; if (set_segment_ar_data(&BX_CPU_THIS_PTR tr, (ar_data >> 8) & 1, smm_state->tr.selector_ar & 0xf0ff, smm_state->tr.base, smm_state->tr.limit, ar_data)) { if (BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_286_TSS && BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_286_TSS && BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS && BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_386_TSS) { BX_PANIC(("SMM restore: TR is not TSS descriptor type !")); return 0; } } if (SMM_REVISION_ID & SMM_SMBASE_RELOCATION) { BX_CPU_THIS_PTR smbase = smm_state->smbase; #if BX_CPU_LEVEL < 6 if (BX_CPU_THIS_PTR smbase & 0x7fff) { BX_PANIC(("SMM restore: SMBASE must be aligned to 32K !")); return 0; } #endif } handleCpuContextChange(); #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_CONTEXT_SWITCH, 0); return 1; } #endif /* BX_CPU_LEVEL >= 3 */ bochs-2.6/cpu/avx_pfp.cc0000644000175000017500000012036612020641453015103 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: avx_pfp.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX extern void mxcsr_to_softfloat_status_word(float_status_t &status, bx_mxcsr_t mxcsr); extern float32 approximate_rsqrt(float32 op); extern float32 approximate_rcp(float32 op); #include "fpu/softfloat-compare.h" #include "simd_pfp.h" void BX_CPU_C::print_state_AVX(void) { BX_DEBUG(("MXCSR: 0x%08x\n", BX_MXCSR_REGISTER)); for(int n=0;nsrc1()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = int32_to_float32(BX_READ_32BIT_REG(i->src2()), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.F3.0F 2A (VEX.W=1) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SS_VssEqR(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = int64_to_float32(BX_READ_64BIT_REG(i->src2()), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* Opcode: VEX.F2.0F 2A (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SD_VsdEdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); op1.xmm64u(0) = int32_to_float64(BX_READ_32BIT_REG(i->src2())); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.F2.0F 2A (VEX.W=1) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSI2SD_VsdEqR(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = int64_to_float64(BX_READ_64BIT_REG(i->src2()), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); #endif BX_NEXT_INSTR(i); } /* Opcode: VEX.0F 51 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTPS_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (4*len); n++) { op.avx32u(n) = float32_sqrt(op.avx32u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F 51 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTPD_VpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (2*len); n++) { op.avx64u(n) = float64_sqrt(op.avx64u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 51 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float32_sqrt(op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 51 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSQRTSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float64_sqrt(op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.0F 52 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VRSQRTPS_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); for (unsigned n=0; n < (4*len); n++) op.avx32u(n) = approximate_rsqrt(op.avx32u(n)); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 52 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VRSQRTSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); op1.xmm32u(0) = approximate_rsqrt(op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.0F 53 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCPPS_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); for (unsigned n=0; n < (4*len); n++) op.avx32u(n) = approximate_rcp(op.avx32u(n)); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 53 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VRCPSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); op1.xmm32u(0) = approximate_rcp(op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F 58 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VADDPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_addps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 58 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VADDPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_addpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 58 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VADDSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float32_add(op1.xmm32u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 58 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VADDSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float64_add(op1.xmm64u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F 59 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMULPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_mulps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 59 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMULPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_mulpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 59 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMULSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float32_mul(op1.xmm32u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 59 (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMULSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float64_mul(op1.xmm64u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.0F 5A (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PD_VpdWpsR(bxInstruction_c *i) { BxPackedAvxRegister result; BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (2*len); n++) { result.avx64u(n) = float32_to_float64(op.xmm32u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F 5A (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPD2PS_VpsWpdR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); BxPackedXmmRegister result; result.xmm64u(1) = 0; /* clear upper part of the result for case of VL128 */ float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); unsigned len = i->getVL(); for (unsigned n=0; n < (2*len); n++) { result.xmm32u(n) = float64_to_float32(op.avx64u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), result); BX_NEXT_INSTR(i); } /* Opcode: VEX.F3.0F 5A (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSS2SD_VsdWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float32_to_float64(op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.F3.0F 5A (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTSD2SS_VssWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float64_to_float32(op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F 5B (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTDQ2PS_VpsWdqR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (4*len); n++) { op.avx32u(n) = int32_to_float32(op.avx32u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 5B (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2DQ_VdqWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (4*len); n++) { op.avx32u(n) = float32_to_int32(op.avx32u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 5B (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTPS2DQ_VdqWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (4*len); n++) { op.avx32u(n) = float32_to_int32_round_to_zero(op.avx32u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F 5C (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSUBPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_subps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 5C (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSUBPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_subpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 5C (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSUBSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float32_sub(op1.xmm32u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 5C (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VSUBSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float64_sub(op1.xmm64u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F 5D (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMINPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_minps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 5D (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMINPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_minpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 5D (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMINSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float32_min(op1.xmm32u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 5D (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMINSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float64_min(op1.xmm64u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F 5E (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VDIVPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_divps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 5E (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VDIVPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_divpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 5E (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VDIVSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float32_div(op1.xmm32u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 5E (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VDIVSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float64_div(op1.xmm64u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F 5F (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMAXPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_maxps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 5F (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMAXPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_maxpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F 5F (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMAXSS_VssHpsWssR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm32u(0) = float32_max(op1.xmm32u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 5F (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMAXSD_VsdHpdWsdR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1.xmm64u(0) = float64_max(op1.xmm64u(0), op2, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 7C (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VHADDPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_haddpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 7C (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VHADDPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_haddps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F 7D (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VHSUBPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_hsubpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F 7D (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VHSUBPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_hsubps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.0F C2 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPS_VpsHpsWpsIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 0x1F; for (unsigned n=0; n < (4*len); n++) { op1.avx32u(n) = compare32[ib](op1.avx32u(n), op2.avx32u(n), status) ? 0xFFFFFFFF : 0; } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.66.0F C2 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPPD_VpdHpdWpdIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 0x1F; for (unsigned n=0; n < (2*len); n++) { op1.avx64u(n) = compare64[ib](op1.avx64u(n), op2.avx64u(n), status) ? BX_CONST64(0xFFFFFFFFFFFFFFFF) : 0; } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F C2 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSD_VsdHpdWsdIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 0x1F; if(compare64[ib](op1.xmm64u(0), op2, status)) { op1.xmm64u(0) = BX_CONST64(0xFFFFFFFFFFFFFFFF); } else { op1.xmm64u(0) = 0; } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F3.0F C2 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCMPSS_VssHpsWssIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); int ib = i->Ib() & 0x1F; if(compare32[ib](op1.xmm32u(0), op2, status)) { op1.xmm32u(0) = 0xFFFFFFFF; } else { op1.xmm32u(0) = 0; } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F D0 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VADDSUBPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_addsubpd(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.NDS.F2.0F D0 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VADDSUBPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) { sse_addsubps(&op1.avx128(n), &op2.avx128(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.E6 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTTPD2DQ_VqWpdR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); BxPackedXmmRegister result; result.xmm64u(1) = 0; /* clear upper part of the result for case of VL128 */ float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); unsigned len = i->getVL(); for (unsigned n=0; n < (2*len); n++) { result.xmm32u(n) = float64_to_int32_round_to_zero(op.avx64u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), result); BX_NEXT_INSTR(i); } /* Opcode: VEX.F2.0F.E6 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPD2DQ_VqWpdR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); BxPackedXmmRegister result; result.xmm64u(1) = 0; /* clear upper part of the result for case of VL128 */ float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); unsigned len = i->getVL(); for (unsigned n=0; n < (2*len); n++) { result.xmm32u(n) = float64_to_int32(op.avx64u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), result); BX_NEXT_INSTR(i); } /* Opcode: VEX.F3.0F.E6 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTDQ2PD_VpdWqR(bxInstruction_c *i) { BxPackedAvxRegister result; BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); unsigned len = i->getVL(); for (unsigned n=0; n < (2*len); n++) { result.avx64u(n) = int32_to_float64(op.xmm32u(n)); } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38.0E (VEX.W=0, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VTESTPS_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->dst()), op2 = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); unsigned result = EFlagsZFMask | EFlagsCFMask; for (unsigned n=0; n < (2*len); n++) { if ((op2.avx64u(n) & op1.avx64u(n) & BX_CONST64(0x8000000080000000)) != 0) result &= ~EFlagsZFMask; if ((op2.avx64u(n) & ~op1.avx64u(n) & BX_CONST64(0x8000000080000000)) != 0) result &= ~EFlagsCFMask; } setEFlagsOSZAPC(result); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.38.0F (VEX.W=0, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VTESTPD_VpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->dst()), op2 = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); unsigned result = EFlagsZFMask | EFlagsCFMask; for (unsigned n=0; n < (2*len); n++) { if ((op2.avx64u(n) & op1.avx64u(n) & BX_CONST64(0x8000000000000000)) != 0) result &= ~EFlagsZFMask; if ((op2.avx64u(n) & ~op1.avx64u(n) & BX_CONST64(0x8000000000000000)) != 0) result &= ~EFlagsCFMask; } setEFlagsOSZAPC(result); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A.08 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDPS_VpsWpsIbR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; for(unsigned n=0; n < (4*len); n++) { op.avx32u(n) = float32_round_to_int(op.avx32u(n), status); } // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A.09 (VEX.W ignore, VEX.VVV #UD) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDPD_VpdWpdIbR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; for(unsigned n=0; n < (2*len); n++) { op.avx64u(n) = float64_round_to_int(op.avx64u(n), status); } // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A.0A (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDSS_VssHpsWssIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; op1.xmm32u(0) = float32_round_to_int(op2, status); // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A.0B (VEX.W ignore, VEX.L ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VROUNDSD_VsdHpdWsdIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); Bit8u control = i->Ib(); // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; op1.xmm64u(0) = float64_round_to_int(op2, status); // ignore precision exception result if (control & 0x8) status.float_exception_flags &= ~float_flag_inexact; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A.40 (VEX.W ignore) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VDPPS_VpsHpsWpsIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); Bit8u mask = i->Ib(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (4*len); n+=4) { BxPackedXmmRegister tmp; tmp.xmm64u(0) = tmp.xmm64u(1) = 0; if (mask & 0x10) tmp.xmm32u(0) = float32_mul(op1.avx32u(n+0), op2.avx32u(n+0), status); if (mask & 0x20) tmp.xmm32u(1) = float32_mul(op1.avx32u(n+1), op2.avx32u(n+1), status); if (mask & 0x40) tmp.xmm32u(2) = float32_mul(op1.avx32u(n+2), op2.avx32u(n+2), status); if (mask & 0x80) tmp.xmm32u(3) = float32_mul(op1.avx32u(n+3), op2.avx32u(n+3), status); float32 tmp1 = float32_add(tmp.xmm32u(0), tmp.xmm32u(1), status); float32 tmp2 = float32_add(tmp.xmm32u(2), tmp.xmm32u(3), status); #ifdef BX_DPPS_DPPD_NAN_MATCHING_HARDWARE float32 r1 = float32_add(tmp1, tmp2, status); float32 r2 = float32_add(tmp2, tmp1, status); op1.avx32u(n+0) = (mask & 0x01) ? r1 : 0; op1.avx32u(n+1) = (mask & 0x02) ? r1 : 0; op1.avx32u(n+2) = (mask & 0x04) ? r2 : 0; op1.avx32u(n+3) = (mask & 0x08) ? r2 : 0; #else float32 r = float32_add(tmp1, tmp2, status); op1.avx32u(n+0) = (mask & 0x01) ? r : 0; op1.avx32u(n+1) = (mask & 0x02) ? r : 0; op1.avx32u(n+2) = (mask & 0x04) ? r : 0; op1.avx32u(n+3) = (mask & 0x08) ? r : 0; #endif } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A.13 (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPH2PS_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister result; BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); status.denormals_are_zeros = 0; // ignore MXCSR.DAZ for (unsigned n=0; n < (4*len); n++) { result.avx32u(n) = float16_to_float32(op.xmm16u(n), status); } // no denormal exception is reported on MXCSR check_exceptionsSSE(status.float_exception_flags & ~float_flag_denormal); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } /* Opcode: VEX.66.0F.3A.1D (VEX.W=0) */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VCVTPS2PH_WpsVpsIb(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); BxPackedXmmRegister result; result.xmm64u(1) = 0; /* clear upper part of the result for case of VL128 */ float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); unsigned len = i->getVL(); Bit8u control = i->Ib(); status.flush_underflow_to_zero = 0; // ignore MXCSR.FUZ // override MXCSR rounding mode with control coming from imm8 if ((control & 0x4) == 0) status.float_rounding_mode = control & 0x3; for (unsigned n=0; n < (4*len); n++) { result.xmm16u(n) = float32_to_float16(op.avx32u(n), status); } check_exceptionsSSE(status.float_exception_flags); if (i->modC0()) { BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), result); } else { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); if (len == BX_VL256) write_virtual_dqword(i->seg(), eaddr, &result); else write_virtual_qword(i->seg(), eaddr, result.xmm64u(0)); } BX_NEXT_INSTR(i); } #endif // BX_SUPPORT_AVX bochs-2.6/cpu/generic_cpuid.cc0000644000175000017500000012467512020641453016247 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: generic_cpuid.cc 11276 2012-07-12 14:51:54Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu.h" #include "param_names.h" #include "generic_cpuid.h" #define LOG_THIS cpu-> bx_cpuid_t::bx_cpuid_t(BX_CPU_C *_cpu): cpu(_cpu) { #if BX_SUPPORT_SMP nthreads = SIM->get_param_num(BXPN_CPU_NTHREADS)->get(); ncores = SIM->get_param_num(BXPN_CPU_NCORES)->get(); nprocessors = SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get(); #else nthreads = 1; ncores = 1; nprocessors = 1; #endif } #if BX_CPU_LEVEL >= 4 bx_generic_cpuid_t::bx_generic_cpuid_t(BX_CPU_C *cpu): bx_cpuid_t(cpu) { init_isa_extensions_bitmask(); init_cpu_extensions_bitmask(); #if BX_SUPPORT_VMX init_vmx_extensions_bitmask(); #endif #if BX_SUPPORT_SVM init_svm_extensions_bitmask(); #endif #if BX_CPU_LEVEL <= 5 // 486 and Pentium processors max_std_leaf = 1; #else // for Pentium Pro, Pentium II, Pentium 4 processors max_std_leaf = 2; // do not report CPUID functions above 0x3 if cpuid_limit_winnt is set // to workaround WinNT issue. static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (! cpuid_limit_winnt) { if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT)) max_std_leaf = 0x5; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC)) max_std_leaf = 0xB; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVE)) max_std_leaf = 0xD; } #endif #if BX_CPU_LEVEL <= 5 max_ext_leaf = 0; #else max_ext_leaf = 0x80000008; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SVM)) max_ext_leaf = 0x8000000A; #endif } void bx_generic_cpuid_t::get_cpuid_leaf(Bit32u function, Bit32u subfunction, cpuid_function_t *leaf) const { static bx_bool cpuid_limit_winnt = SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get(); if (cpuid_limit_winnt) if (function > 2 && function < 0x80000000) function = 2; #if BX_CPU_LEVEL >= 6 if (function >= 0x80000000 && function > max_ext_leaf) function = max_std_leaf; #endif if (function < 0x80000000 && function > max_std_leaf) function = max_std_leaf; switch(function) { #if BX_CPU_LEVEL >= 6 case 0x80000000: get_ext_cpuid_leaf_0(leaf); return; case 0x80000001: get_ext_cpuid_leaf_1(leaf); return; case 0x80000002: case 0x80000003: case 0x80000004: get_ext_cpuid_brand_string_leaf(function, leaf); return; case 0x80000005: get_ext_cpuid_leaf_5(leaf); return; case 0x80000006: get_ext_cpuid_leaf_6(leaf); return; case 0x80000007: get_ext_cpuid_leaf_7(leaf); return; case 0x80000008: get_ext_cpuid_leaf_8(leaf); return; #if BX_SUPPORT_SVM case 0x8000000A: get_ext_cpuid_leaf_A(leaf); return; #endif #endif case 0x00000000: get_std_cpuid_leaf_0(leaf); return; case 0x00000001: get_std_cpuid_leaf_1(leaf); return; #if BX_CPU_LEVEL >= 6 case 0x00000002: get_std_cpuid_leaf_2(leaf); return; case 0x00000003: get_reserved_leaf(leaf); return; case 0x00000004: get_std_cpuid_leaf_4(subfunction, leaf); return; case 0x00000005: get_std_cpuid_leaf_5(leaf); return; case 0x00000006: get_std_cpuid_leaf_6(leaf); return; case 0x00000007: get_std_cpuid_leaf_7(subfunction, leaf); return; case 0x00000008: case 0x00000009: get_reserved_leaf(leaf); return; case 0x0000000A: get_std_cpuid_leaf_A(leaf); return; case 0x0000000B: get_std_cpuid_extended_topology_leaf(subfunction, leaf); return; case 0x0000000C: get_reserved_leaf(leaf); return; case 0x0000000D: default: get_std_cpuid_xsave_leaf(subfunction, leaf); return; #endif } } // leaf 0x00000000 // void bx_generic_cpuid_t::get_std_cpuid_leaf_0(cpuid_function_t *leaf) const { static Bit8u *vendor_string = (Bit8u *)SIM->get_param_string(BXPN_VENDOR_STRING)->getptr(); // EAX: highest std function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = max_std_leaf; // CPUID vendor string (e.g. GenuineIntel, AuthenticAMD, CentaurHauls, ...) memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x00000001 // void bx_generic_cpuid_t::get_std_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information // [3:0] Stepping ID // [7:4] Model: starts at 1 // [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... // [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved // [19:16] Extended Model // [27:20] Extended Family leaf->eax = get_cpu_version_information(); // EBX: // [7:0] Brand ID // [15:8] CLFLUSH cache line size (value*8 = cache line size in bytes) // [23:16] Number of logical processors in one physical processor // [31:24] Local Apic ID leaf->ebx = 0; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CLFLUSH)) { leaf->ebx |= (CACHE_LINE_SIZE / 8) << 8; } unsigned n_logical_processors = ncores*nthreads; leaf->ebx |= (n_logical_processors << 16); #if BX_SUPPORT_APIC leaf->ebx |= ((cpu->get_apic_id() & 0xff) << 24); #endif // ECX: Extended Feature Flags #if BX_CPU_LEVEL >= 6 leaf->ecx = get_extended_cpuid_features(); #else leaf->ecx = 0; #endif // EDX: Standard Feature Flags leaf->edx = get_std_cpuid_features(); } #if BX_CPU_LEVEL >= 6 // leaf 0x00000002 // void bx_generic_cpuid_t::get_std_cpuid_leaf_2(cpuid_function_t *leaf) const { // CPUID function 0x00000002 - Cache and TLB Descriptors #if BX_CPU_VENDOR_INTEL leaf->eax = 0x00410601; // for Pentium Pro compatibility leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #else leaf->eax = 0; // ignore for AMD leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; #endif } // leaf 0x00000003 - Processor Serial Number (not supported) // // leaf 0x00000004 // void bx_generic_cpuid_t::get_std_cpuid_leaf_4(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x00000004 - Deterministic Cache Parameters leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x00000005 // void bx_generic_cpuid_t::get_std_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x00000005 - MONITOR/MWAIT Leaf #if BX_SUPPORT_MONITOR_MWAIT if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT)) { // EAX - Smallest monitor-line size in bytes // EBX - Largest monitor-line size in bytes // ECX - // [31:2] - reserved // [1:1] - exit MWAIT even with EFLAGS.IF = 0 // [0:0] - MONITOR/MWAIT extensions are supported // EDX - // [03-00] - number of C0 sub C-states supported using MWAIT // [07-04] - number of C1 sub C-states supported using MWAIT // [11-08] - number of C2 sub C-states supported using MWAIT // [15-12] - number of C3 sub C-states supported using MWAIT // [19-16] - number of C4 sub C-states supported using MWAIT // [31-20] - reserved (MBZ) leaf->eax = CACHE_LINE_SIZE; leaf->ebx = CACHE_LINE_SIZE; leaf->ecx = 3; leaf->edx = 0x00000020; } else #endif { leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } } // leaf 0x00000006 // void bx_generic_cpuid_t::get_std_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x00000006 - Thermal and Power Management Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x00000007 // void bx_generic_cpuid_t::get_std_cpuid_leaf_7(Bit32u subfunction, cpuid_function_t *leaf) const { leaf->eax = 0; /* report max sub-leaf that supported in leaf 7 */ leaf->ebx = get_ext3_cpuid_features(); leaf->ecx = 0; leaf->edx = 0; } // leaf 0x00000008 reserved // // leaf 0x00000009 direct cache access not supported // // leaf 0x0000000A // void bx_generic_cpuid_t::get_std_cpuid_leaf_A(cpuid_function_t *leaf) const { // CPUID function 0x0000000A - Architectural Performance Monitoring Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } BX_CPP_INLINE static Bit32u ilog2(Bit32u x) { Bit32u count = 0; while(x>>=1) count++; return count; } // leaf 0x0000000B // void bx_generic_cpuid_t::get_std_cpuid_extended_topology_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { // CPUID function 0x0000000B - Extended Topology Leaf leaf->eax = 0; leaf->ebx = 0; leaf->ecx = subfunction; leaf->edx = cpu->get_apic_id(); #if BX_SUPPORT_SMP switch(subfunction) { case 0: if (nthreads > 1) { leaf->eax = ilog2(nthreads-1)+1; leaf->ebx = nthreads; leaf->ecx |= (1<<8); } else if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } else { leaf->eax = 1; leaf->ebx = 1; // number of logical CPUs at this level } break; case 1: if (nthreads > 1) { if (ncores > 1) { leaf->eax = ilog2(ncores-1)+1; leaf->ebx = ncores; leaf->ecx |= (2<<8); } else if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } else if (ncores > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; case 2: if (nthreads > 1) { if (nprocessors > 1) { leaf->eax = ilog2(nprocessors-1)+1; leaf->ebx = nprocessors; } } break; default: break; } #endif } // leaf 0x0000000C - reserved // // leaf 0x0000000D // void bx_generic_cpuid_t::get_std_cpuid_xsave_leaf(Bit32u subfunction, cpuid_function_t *leaf) const { if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVE)) { switch(subfunction) { case 0: // EAX - valid bits of XCR0 (lower part) // EBX - Maximum size (in bytes) required by enabled features // ECX - Maximum size (in bytes) required by CPU supported features // EDX - valid bits of XCR0 (upper part) leaf->eax = cpu->xcr0_suppmask; leaf->ebx = 512+64; #if BX_SUPPORT_AVX if (cpu->xcr0.get_AVX()) leaf->ebx += 256; #endif leaf->ecx = 512+64; #if BX_SUPPORT_AVX if (cpu->xcr0_suppmask & BX_XCR0_AVX_MASK) leaf->ecx += 256; #endif leaf->edx = 0; return; case 1: leaf->eax = BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVEOPT); leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; return; #if BX_SUPPORT_AVX case 2: // AVX leaf if (cpu->xcr0_suppmask & BX_XCR0_AVX_MASK) { leaf->eax = 256; leaf->ebx = 576; leaf->ecx = 0; leaf->edx = 0; break; } // else fall through #endif default: leaf->eax = 0; // reserved leaf->ebx = 0; // reserved leaf->ecx = 0; // reserved leaf->edx = 0; // reserved break; } } } // leaf 0x80000000 // void bx_generic_cpuid_t::get_ext_cpuid_leaf_0(cpuid_function_t *leaf) const { // EAX: highest extended function understood by CPUID // EBX: vendor ID string // EDX: vendor ID string // ECX: vendor ID string leaf->eax = max_ext_leaf; #if BX_CPU_VENDOR_INTEL leaf->ebx = 0; leaf->edx = 0; // Reserved for Intel leaf->ecx = 0; #else static Bit8u *vendor_string = (Bit8u *)SIM->get_param_string(BXPN_VENDOR_STRING)->getptr(); memcpy(&(leaf->ebx), vendor_string, 4); memcpy(&(leaf->edx), vendor_string + 4, 4); memcpy(&(leaf->ecx), vendor_string + 8, 4); #endif #ifdef BX_BIG_ENDIAN leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000001 // void bx_generic_cpuid_t::get_ext_cpuid_leaf_1(cpuid_function_t *leaf) const { // EAX: CPU Version Information leaf->eax = BX_CPU_VENDOR_INTEL ? 0 : get_cpu_version_information(); // EBX: Brand ID leaf->ebx = 0; // ECX: leaf->ecx = get_ext2_cpuid_features(); // EDX: // Many of the bits in EDX are the same as FN 0x00000001 [*] for AMD // [*] [0:0] FPU on chip // [*] [1:1] VME: Virtual-8086 Mode enhancements // [*] [2:2] DE: Debug Extensions (I/O breakpoints) // [*] [3:3] PSE: Page Size Extensions // [*] [4:4] TSC: Time Stamp Counter // [*] [5:5] MSR: RDMSR and WRMSR support // [*] [6:6] PAE: Physical Address Extensions // [*] [7:7] MCE: Machine Check Exception // [*] [8:8] CXS: CMPXCHG8B instruction // [*] [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSCALL/SYSRET support // [*] [12:12] MTRR: Memory Type Range Reg // [*] [13:13] PGE/PTE Global Bit // [*] [14:14] MCA: Machine Check Architecture // [*] [15:15] CMOV: Cond Mov/Cmp Instructions // [*] [16:16] PAT: Page Attribute Table // [*] [17:17] PSE-36: Physical Address Extensions // [18:19] Reserved // [20:20] No-Execute page protection // [21:21] Reserved // [22:22] AMD MMX Extensions // [*] [23:23] MMX Technology // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] Fast FXSAVE/FXRSTOR mode support // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions leaf->edx = get_std2_cpuid_features(); } // leaf 0x80000002 // // leaf 0x80000003 // // leaf 0x80000004 // void bx_generic_cpuid_t::get_ext_cpuid_brand_string_leaf(Bit32u function, cpuid_function_t *leaf) const { // CPUID function 0x800000002-0x800000004 - Processor Name String Identifier static Bit8u *brand_string = (Bit8u *)SIM->get_param_string(BXPN_BRAND_STRING)->getptr(); switch(function) { case 0x80000002: memcpy(&(leaf->eax), brand_string , 4); memcpy(&(leaf->ebx), brand_string + 4, 4); memcpy(&(leaf->ecx), brand_string + 8, 4); memcpy(&(leaf->edx), brand_string + 12, 4); break; case 0x80000003: memcpy(&(leaf->eax), brand_string + 16, 4); memcpy(&(leaf->ebx), brand_string + 20, 4); memcpy(&(leaf->ecx), brand_string + 24, 4); memcpy(&(leaf->edx), brand_string + 28, 4); break; case 0x80000004: memcpy(&(leaf->eax), brand_string + 32, 4); memcpy(&(leaf->ebx), brand_string + 36, 4); memcpy(&(leaf->ecx), brand_string + 40, 4); memcpy(&(leaf->edx), brand_string + 44, 4); break; default: break; } #ifdef BX_BIG_ENDIAN leaf->eax = bx_bswap32(leaf->eax); leaf->ebx = bx_bswap32(leaf->ebx); leaf->ecx = bx_bswap32(leaf->ecx); leaf->edx = bx_bswap32(leaf->edx); #endif } // leaf 0x80000005 // void bx_generic_cpuid_t::get_ext_cpuid_leaf_5(cpuid_function_t *leaf) const { // CPUID function 0x800000005 - L1 Cache and TLB Identifiers leaf->eax = 0x01ff01ff; leaf->ebx = 0x01ff01ff; leaf->ecx = 0x40020140; leaf->edx = 0x40020140; } // leaf 0x80000006 // void bx_generic_cpuid_t::get_ext_cpuid_leaf_6(cpuid_function_t *leaf) const { // CPUID function 0x800000006 - L2 Cache and TLB Identifiers leaf->eax = 0; leaf->ebx = 0x42004200; leaf->ecx = 0x02008140; leaf->edx = 0; } // leaf 0x80000007 // void bx_generic_cpuid_t::get_ext_cpuid_leaf_7(cpuid_function_t *leaf) const { // CPUID function 0x800000007 - Advanced Power Management leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; leaf->edx = 0; } // leaf 0x80000008 // void bx_generic_cpuid_t::get_ext_cpuid_leaf_8(cpuid_function_t *leaf) const { // virtual & phys address size in low 2 bytes. leaf->eax = BX_PHY_ADDRESS_WIDTH | (BX_LIN_ADDRESS_WIDTH << 8); leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } #if BX_SUPPORT_SVM // leaf 0x8000000A // void bx_generic_cpuid_t::get_ext_cpuid_leaf_A(cpuid_function_t *leaf) const { if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SVM)) { leaf->eax = BX_SVM_REVISION; leaf->ebx = 0x40; /* number of ASIDs */ leaf->ecx = 0; // * [0:0] NP - Nested paging support // [1:1] LBR virtualization // [2:2] SVM Lock // * [3:3] NRIPS - Next RIP save on VMEXIT // [4:4] TscRate - MSR based TSC ratio control // [5:5] VMCB Clean bits support // [6:6] Flush by ASID support // [7:7] Decode assists support // [9:8] Reserved // [10:10] Pause filter support // [11:11] Reserved // [12:12] Pause filter threshold support // [31:13] Reserved leaf->edx = BX_CPUID_SVM_NESTED_PAGING | BX_CPUID_SVM_NRIP_SAVE; } else { leaf->eax = 0; leaf->ebx = 0; leaf->ecx = 0; // Reserved, undefined leaf->edx = 0; } } #endif #endif void bx_generic_cpuid_t::init_isa_extensions_bitmask(void) { Bit64u features_bitmask = 0; #if BX_SUPPORT_FPU features_bitmask |= BX_ISA_X87; #endif #if BX_CPU_LEVEL >= 4 features_bitmask |= BX_ISA_486; #if BX_CPU_LEVEL >= 5 features_bitmask |= BX_ISA_PENTIUM; static bx_bool mmx_enabled = SIM->get_param_bool(BXPN_CPUID_MMX)->get(); if (mmx_enabled) features_bitmask |= BX_ISA_MMX; #if BX_SUPPORT_3DNOW features_bitmask |= BX_ISA_3DNOW; if (! mmx_enabled) { BX_PANIC(("PANIC: 3DNOW emulation requires MMX support !")); return; } #endif #if BX_CPU_LEVEL >= 6 features_bitmask |= BX_ISA_P6; #if BX_SUPPORT_MONITOR_MWAIT static bx_bool mwait_enabled = SIM->get_param_bool(BXPN_CPUID_MWAIT)->get(); if (mwait_enabled) features_bitmask |= BX_ISA_MONITOR_MWAIT; #endif static unsigned sse_enabled = SIM->get_param_enum(BXPN_CPUID_SSE)->get(); // determine SSE in runtime switch (sse_enabled) { case BX_CPUID_SUPPORT_SSE4_2: features_bitmask |= BX_ISA_SSE4_2; case BX_CPUID_SUPPORT_SSE4_1: features_bitmask |= BX_ISA_SSE4_1; case BX_CPUID_SUPPORT_SSSE3: features_bitmask |= BX_ISA_SSSE3; case BX_CPUID_SUPPORT_SSE3: features_bitmask |= BX_ISA_SSE3; case BX_CPUID_SUPPORT_SSE2: features_bitmask |= BX_ISA_SSE2; case BX_CPUID_SUPPORT_SSE: features_bitmask |= BX_ISA_SSE; case BX_CPUID_SUPPORT_NOSSE: default: break; }; if (sse_enabled) { if (mmx_enabled == 0 || BX_CPU_LEVEL < 6) { BX_PANIC(("PANIC: SSE support requires P6 emulation with MMX enabled !")); return; } } // enable CLFLUSH only when SSE2 or higher is enabled if (sse_enabled >= BX_CPUID_SUPPORT_SSE2) features_bitmask |= BX_ISA_CLFLUSH; // enable POPCNT if SSE4.2 is enabled if (sse_enabled >= BX_CPUID_SUPPORT_SSE4_2) features_bitmask |= BX_ISA_POPCNT; static bx_bool sse4a_enabled = SIM->get_param_bool(BXPN_CPUID_SSE4A)->get(); if (sse4a_enabled) { features_bitmask |= BX_ISA_SSE4A; if (! sse_enabled) { BX_PANIC(("PANIC: SSE4A require SSE to be enabled !")); return; } } static bx_bool sep_enabled = SIM->get_param_bool(BXPN_CPUID_SEP)->get(); if (sep_enabled) features_bitmask |= BX_ISA_SYSENTER_SYSEXIT; static bx_bool xsave_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVE)->get(); if (xsave_enabled) { features_bitmask |= BX_ISA_XSAVE; if (! sse_enabled) { BX_PANIC(("PANIC: XSAVE emulation requires SSE support !")); return; } } static bx_bool xsaveopt_enabled = SIM->get_param_bool(BXPN_CPUID_XSAVEOPT)->get(); if (xsaveopt_enabled) { features_bitmask |= BX_ISA_XSAVEOPT; if (! xsave_enabled) { BX_PANIC(("PANIC: XSAVEOPT emulation requires XSAVE !")); return; } } static bx_bool aes_enabled = SIM->get_param_bool(BXPN_CPUID_AES)->get(); if (aes_enabled) { features_bitmask |= BX_ISA_AES_PCLMULQDQ; // AES required 3-byte opcode (SSS3E support or more) if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) { BX_PANIC(("PANIC: AES support requires SSSE3 or higher !")); return; } } static bx_bool movbe_enabled = SIM->get_param_bool(BXPN_CPUID_MOVBE)->get(); if (movbe_enabled) { features_bitmask |= BX_ISA_MOVBE; // MOVBE required 3-byte opcode (SSS3E support or more) if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) { BX_PANIC(("PANIC: MOVBE support requires SSSE3 or higher !")); return; } } static bx_bool adx_enabled = SIM->get_param_bool(BXPN_CPUID_ADX)->get(); if (adx_enabled) { features_bitmask |= BX_ISA_ADX; // ADX required 3-byte opcode (SSS3E support or more) if (sse_enabled < BX_CPUID_SUPPORT_SSSE3) { BX_PANIC(("PANIC: ADX support requires SSSE3 or higher !")); return; } } #if BX_SUPPORT_X86_64 static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get(); if (x86_64_enabled) { features_bitmask |= BX_ISA_CMPXCHG16B | BX_ISA_RDTSCP | BX_ISA_LM_LAHF_SAHF; if (sse_enabled < BX_CPUID_SUPPORT_SSE2) { BX_PANIC(("PANIC: x86-64 emulation requires SSE2 support !")); return; } if (! sep_enabled) { BX_PANIC(("PANIC: x86-64 emulation requires SYSENTER/SYSEXIT support !")); return; } static bx_bool fsgsbase_enabled = SIM->get_param_bool(BXPN_CPUID_FSGSBASE)->get(); if (fsgsbase_enabled) features_bitmask |= BX_ISA_FSGSBASE; static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get(); if (apic_enabled < BX_CPUID_SUPPORT_XAPIC) { BX_PANIC(("PANIC: x86-64 emulation requires XAPIC support !")); return; } } else { if (BX_SUPPORT_VMX >= 2) { BX_PANIC(("PANIC: VMXx2 emulation requires x86-64 support !")); return; } } #if BX_SUPPORT_AVX static unsigned avx_enabled = SIM->get_param_num(BXPN_CPUID_AVX)->get(); if (avx_enabled) { features_bitmask |= BX_ISA_AVX; if (! xsave_enabled) { BX_PANIC(("PANIC: AVX emulation requires XSAVE support !")); return; } if (! x86_64_enabled) { BX_PANIC(("PANIC: AVX emulation requires x86-64 support !")); return; } if (avx_enabled >= 2) features_bitmask |= BX_ISA_AVX2; } static bx_bool avx_f16c_enabled = SIM->get_param_bool(BXPN_CPUID_AVX_F16CVT)->get(); if (avx_f16c_enabled) { if (! avx_enabled) { BX_PANIC(("PANIC: Float16 convert emulation requires AVX support !")); return; } features_bitmask |= BX_ISA_AVX_F16C; } static bx_bool avx_fma_enabled = SIM->get_param_bool(BXPN_CPUID_AVX_FMA)->get(); if (avx_fma_enabled) { if (avx_enabled < 2) { BX_PANIC(("PANIC: FMA emulation requires AVX2 support !")); return; } features_bitmask |= BX_ISA_AVX_FMA; } static unsigned bmi_enabled = SIM->get_param_num(BXPN_CPUID_BMI)->get(); if (bmi_enabled) { features_bitmask |= BX_ISA_BMI1 | BX_ISA_LZCNT; if (! avx_enabled) { BX_PANIC(("PANIC: Bit Manipulation Instructions (BMI) emulation requires AVX support !")); return; } if (bmi_enabled >= 2) features_bitmask |= BX_ISA_BMI2; } static bx_bool fma4_enabled = SIM->get_param_bool(BXPN_CPUID_FMA4)->get(); if (fma4_enabled) { if (! avx_enabled) { BX_PANIC(("PANIC: FMA4 emulation requires AVX support !")); return; } features_bitmask |= BX_ISA_FMA4; } static bx_bool xop_enabled = SIM->get_param_bool(BXPN_CPUID_XOP)->get(); if (xop_enabled) { if (! avx_enabled) { BX_PANIC(("PANIC: XOP emulation requires AVX support !")); return; } features_bitmask |= BX_ISA_XOP; } static bx_bool tbm_enabled = SIM->get_param_bool(BXPN_CPUID_TBM)->get(); if (tbm_enabled) { if (! avx_enabled || ! xop_enabled) { BX_PANIC(("PANIC: TBM emulation requires AVX and XOP support !")); return; } features_bitmask |= BX_ISA_TBM; } #endif // BX_SUPPORT_AVX #endif // BX_SUPPORT_X86_64 #if BX_SUPPORT_VMX static unsigned vmx_enabled = SIM->get_param_num(BXPN_CPUID_VMX)->get(); if (vmx_enabled) { features_bitmask |= BX_ISA_VMX; if (! sep_enabled) { BX_PANIC(("PANIC: VMX emulation requires SYSENTER/SYSEXIT support !")); return; } } #endif #if BX_SUPPORT_SVM static unsigned svm_enabled = SIM->get_param_num(BXPN_CPUID_SVM)->get(); if (svm_enabled) { features_bitmask |= BX_ISA_SVM; if (! x86_64_enabled) { BX_PANIC(("PANIC: SVM emulation requires x86-64 support !")); return; } } #endif #if BX_SUPPORT_VMX && BX_SUPPORT_SVM if (vmx_enabled && svm_enabled) { BX_PANIC(("PANIC: VMX and SVM emulation cannot be enabled together in same configuration !")); return; } #endif #endif // CPU_LEVEL >= 6 #endif // CPU_LEVEL >= 5 #endif // CPU_LEVEL >= 4 this->isa_extensions_bitmask = features_bitmask; } void bx_generic_cpuid_t::init_cpu_extensions_bitmask(void) { Bit32u features_bitmask = 0; #if BX_SUPPORT_APIC static unsigned apic_enabled = SIM->get_param_enum(BXPN_CPUID_APIC)->get(); // determine SSE in runtime switch (apic_enabled) { #if BX_CPU_LEVEL >= 6 case BX_CPUID_SUPPORT_X2APIC: features_bitmask |= BX_CPU_X2APIC | BX_CPU_XAPIC; break; case BX_CPUID_SUPPORT_XAPIC_EXT: features_bitmask |= BX_CPU_XAPIC_EXT | BX_CPU_XAPIC; break; #endif case BX_CPUID_SUPPORT_XAPIC: features_bitmask |= BX_CPU_XAPIC; break; case BX_CPUID_SUPPORT_LEGACY_APIC: break; default: BX_PANIC(("unknown APIC option %d", apic_enabled)); }; #endif #if BX_CPU_LEVEL >= 5 features_bitmask |= BX_CPU_VME; features_bitmask |= BX_CPU_DEBUG_EXTENSIONS; features_bitmask |= BX_CPU_PSE; #if BX_CPU_LEVEL >= 6 features_bitmask |= BX_CPU_PAE; features_bitmask |= BX_CPU_PGE; #if BX_PHY_ADDRESS_LONG features_bitmask |= BX_CPU_PSE36; #endif features_bitmask |= BX_CPU_MTRR; features_bitmask |= BX_CPU_PAT; #if BX_SUPPORT_MISALIGNED_SSE features_bitmask |= BX_CPU_MISALIGNED_SSE; #endif static bx_bool smep_enabled = SIM->get_param_bool(BXPN_CPUID_SMEP)->get(); if (smep_enabled) features_bitmask |= BX_CPU_SMEP; #if BX_SUPPORT_X86_64 static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get(); if (x86_64_enabled) { features_bitmask |= BX_CPU_LONG_MODE | BX_CPU_FFXSR | BX_CPU_NX; static bx_bool pcid_enabled = SIM->get_param_bool(BXPN_CPUID_PCID)->get(); if (pcid_enabled) features_bitmask |= BX_CPU_PCID; static bx_bool xlarge_pages = SIM->get_param_bool(BXPN_CPUID_1G_PAGES)->get(); if (xlarge_pages) features_bitmask |= BX_CPU_1G_PAGES; } #if BX_SUPPORT_SVM static unsigned svm_enabled = SIM->get_param_num(BXPN_CPUID_SVM)->get(); if (svm_enabled) { features_bitmask |= BX_CPU_ALT_MOV_CR8 | BX_CPU_XAPIC_EXT; // auto-enable together with SVM } #endif #endif // BX_SUPPORT_X86_64 #endif // CPU_LEVEL >= 6 #endif // CPU_LEVEL >= 5 this->cpu_extensions_bitmask = features_bitmask; } #if BX_SUPPORT_VMX void bx_generic_cpuid_t::init_vmx_extensions_bitmask(void) { Bit32u features_bitmask = 0; static unsigned vmx_enabled = SIM->get_param_num(BXPN_CPUID_VMX)->get(); if (vmx_enabled) { features_bitmask |= BX_VMX_VIRTUAL_NMI; static bx_bool x86_64_enabled = SIM->get_param_bool(BXPN_CPUID_X86_64)->get(); if (x86_64_enabled) { features_bitmask |= BX_VMX_TPR_SHADOW | BX_VMX_APIC_VIRTUALIZATION | BX_VMX_WBINVD_VMEXIT; #if BX_SUPPORT_VMX >= 2 if (vmx_enabled >= 2) { features_bitmask |= BX_VMX_PREEMPTION_TIMER | BX_VMX_PAT | BX_VMX_EFER | BX_VMX_EPT | BX_VMX_VPID | BX_VMX_UNRESTRICTED_GUEST | BX_VMX_DESCRIPTOR_TABLE_EXIT | BX_VMX_X2APIC_VIRTUALIZATION | BX_VMX_PAUSE_LOOP_EXITING; features_bitmask |= BX_VMX_SAVE_DEBUGCTL_DISABLE | /* BX_VMX_MONITOR_TRAP_FLAG | */ // not implemented yet BX_VMX_PERF_GLOBAL_CTRL; } #endif } } this->vmx_extensions_bitmask = features_bitmask; } #endif #if BX_SUPPORT_SVM void bx_generic_cpuid_t::init_svm_extensions_bitmask(void) { Bit32u features_bitmask = 0; static bx_bool svm_enabled = SIM->get_param_bool(BXPN_CPUID_SVM)->get(); if (svm_enabled) { features_bitmask = BX_CPUID_SVM_NESTED_PAGING | BX_CPUID_SVM_NRIP_SAVE; } this->svm_extensions_bitmask = features_bitmask; } #endif /* * Get CPU version information: * * [3:0] Stepping ID * [7:4] Model: starts at 1 * [11:8] Family: 4=486, 5=Pentium, 6=PPro, ... * [13:12] Type: 0=OEM, 1=overdrive, 2=dual cpu, 3=reserved * [19:16] Extended Model * [27:29] Extended Family */ Bit32u bx_generic_cpuid_t::get_cpu_version_information(void) const { static Bit32u stepping = SIM->get_param_num(BXPN_CPUID_STEPPING)->get(); static Bit32u model = SIM->get_param_num(BXPN_CPUID_MODEL)->get(); static Bit32u family = SIM->get_param_num(BXPN_CPUID_FAMILY)->get(); if (family < 6 && family != BX_CPU_LEVEL) BX_PANIC(("PANIC: CPUID family %x not matching configured cpu level %d", family, BX_CPU_LEVEL)); return ((family & 0xfff0) << 16) | ((model & 0xf0) << 12) | ((family & 0x0f) << 8) | ((model & 0x0f) << 4) | stepping; } #if BX_CPU_LEVEL >= 6 /* Get CPU extended feature flags. */ Bit32u bx_generic_cpuid_t::get_extended_cpuid_features(void) const { // [0:0] SSE3: SSE3 Instructions // [1:1] PCLMULQDQ Instruction support // [2:2] DTES64: 64-bit DS area // [3:3] MONITOR/MWAIT support // [4:4] DS-CPL: CPL qualified debug store // [5:5] VMX: Virtual Machine Technology // [6:6] SMX: Secure Virtual Machine Technology // [7:7] EST: Enhanced Intel SpeedStep Technology // [8:8] TM2: Thermal Monitor 2 // [9:9] SSSE3: SSSE3 Instructions // [10:10] CNXT-ID: L1 context ID // [11:11] reserved // [12:12] FMA Instructions support // [13:13] CMPXCHG16B: CMPXCHG16B instruction support // [14:14] xTPR update control // [15:15] PDCM - Perfon and Debug Capability MSR // [16:16] reserved // [17:17] PCID: Process Context Identifiers // [18:18] DCA - Direct Cache Access // [19:19] SSE4.1 Instructions // [20:20] SSE4.2 Instructions // [21:21] X2APIC // [22:22] MOVBE instruction // [23:23] POPCNT instruction // [24:24] TSC Deadline // [25:25] AES Instructions // [26:26] XSAVE extensions support // [27:27] OSXSAVE support // [28:28] AVX extensions support // [29:29] AVX F16C - Float16 conversion support // [30:30] RDRAND instruction // [31:31] reserved Bit32u features = 0; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE3)) features |= BX_CPUID_EXT_SSE3; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AES_PCLMULQDQ)) features |= BX_CPUID_EXT_PCLMULQDQ; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MONITOR_MWAIT)) features |= BX_CPUID_EXT_MONITOR_MWAIT; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_VMX)) features |= BX_CPUID_EXT_VMX; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSSE3)) features |= BX_CPUID_EXT_SSSE3; #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) features |= BX_CPUID_EXT_CMPXCHG16B; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PCID)) features |= BX_CPUID_EXT_PCID; #endif if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE4_1)) features |= BX_CPUID_EXT_SSE4_1; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE4_2)) features |= BX_CPUID_EXT_SSE4_2; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_X2APIC)) features |= BX_CPUID_EXT_X2APIC; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MOVBE)) features |= BX_CPUID_EXT_MOVBE; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_POPCNT)) features |= BX_CPUID_EXT_POPCNT; // support for AES if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AES_PCLMULQDQ)) features |= BX_CPUID_EXT_AES; // support XSAVE extensions if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XSAVE)) { features |= BX_CPUID_EXT_XSAVE; if (cpu->cr4.get_OSXSAVE()) features |= BX_CPUID_EXT_OSXSAVE; } #if BX_SUPPORT_AVX if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX)) features |= BX_CPUID_EXT_AVX; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX_F16C)) features |= BX_CPUID_EXT_AVX_F16C; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX_FMA)) features |= BX_CPUID_EXT_FMA; #endif return features; } #endif /* Get CPU feature flags. Returned by CPUID functions 1 and 80000001. */ Bit32u bx_generic_cpuid_t::get_std_cpuid_features(void) const { // [0:0] FPU on chip // [1:1] VME: Virtual-8086 Mode enhancements // [2:2] DE: Debug Extensions (I/O breakpoints) // [3:3] PSE: Page Size Extensions // [4:4] TSC: Time Stamp Counter // [5:5] MSR: RDMSR and WRMSR support // [6:6] PAE: Physical Address Extensions // [7:7] MCE: Machine Check Exception // [8:8] CXS: CMPXCHG8B instruction // [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSENTER/SYSEXIT support // [12:12] MTRR: Memory Type Range Reg // [13:13] PGE/PTE Global Bit // [14:14] MCA: Machine Check Architecture // [15:15] CMOV: Cond Mov/Cmp Instructions // [16:16] PAT: Page Attribute Table // [17:17] PSE-36: Physical Address Extensions // [18:18] PSN: Processor Serial Number // [19:19] CLFLUSH: CLFLUSH Instruction support // [20:20] Reserved // [21:21] DS: Debug Store // [22:22] ACPI: Thermal Monitor and Software Controlled Clock Facilities // [23:23] MMX Technology // [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] SSE: SSE Extensions // [26:26] SSE2: SSE2 Extensions // [27:27] Self Snoop // [28:28] Hyper Threading Technology // [29:29] TM: Thermal Monitor // [30:30] Reserved // [31:31] PBE: Pending Break Enable Bit32u features = 0; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_X87)) features |= BX_CPUID_STD_X87; #if BX_CPU_LEVEL >= 5 if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_PENTIUM)) { // Pentium only features features |= BX_CPUID_STD_TSC; features |= BX_CPUID_STD_MSR; // support Machine Check features |= BX_CPUID_STD_MCE | BX_CPUID_STD_MCA; features |= BX_CPUID_STD_CMPXCHG8B; } if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_VME)) features |= BX_CPUID_STD_VME; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_DEBUG_EXTENSIONS)) features |= BX_CPUID_STD_DEBUG_EXTENSIONS; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE)) features |= BX_CPUID_STD_PSE; #endif #if BX_SUPPORT_APIC // if MSR_APICBASE APIC Global Enable bit has been cleared, // the CPUID feature flag for the APIC is set to 0. if (cpu->msr.apicbase & 0x800) features |= BX_CPUID_STD_APIC; // APIC on chip #endif if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SYSENTER_SYSEXIT)) features |= BX_CPUID_STD_SYSENTER_SYSEXIT; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_CLFLUSH)) features |= BX_CPUID_STD_CLFLUSH; #if BX_CPU_LEVEL >= 5 if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_MMX)) features |= BX_CPUID_STD_MMX; #endif #if BX_CPU_LEVEL >= 6 if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_P6)) { features |= BX_CPUID_STD_CMOV; features |= BX_CPUID_STD_ACPI; } if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_MTRR)) features |= BX_CPUID_STD_MTRR; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAT)) features |= BX_CPUID_STD_PAT; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PAE)) features |= BX_CPUID_STD_PAE; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PGE)) features |= BX_CPUID_STD_GLOBAL_PAGES; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_PSE36)) features |= BX_CPUID_STD_PSE36; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE)) features |= BX_CPUID_STD_FXSAVE_FXRSTOR | BX_CPUID_STD_SSE; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE2)) features |= BX_CPUID_STD_SSE2; if (BX_CPU_VENDOR_INTEL) features |= BX_CPUID_STD_SELF_SNOOP; #endif features |= BX_CPUID_STD_HT; return features; } #if BX_CPU_LEVEL >= 6 /* Get CPU feature flags. Returned by CPUID function 80000001 in EDX register */ Bit32u bx_generic_cpuid_t::get_std2_cpuid_features(void) const { // Many of the bits in EDX are the same as EAX [*] for AMD // [*] [0:0] FPU on chip // [*] [1:1] VME: Virtual-8086 Mode enhancements // [*] [2:2] DE: Debug Extensions (I/O breakpoints) // [*] [3:3] PSE: Page Size Extensions // [*] [4:4] TSC: Time Stamp Counter // [*] [5:5] MSR: RDMSR and WRMSR support // [*] [6:6] PAE: Physical Address Extensions // [*] [7:7] MCE: Machine Check Exception // [*] [8:8] CXS: CMPXCHG8B instruction // [*] [9:9] APIC: APIC on Chip // [10:10] Reserved // [11:11] SYSCALL/SYSRET support // [*] [12:12] MTRR: Memory Type Range Reg // [*] [13:13] PGE/PTE Global Bit // [*] [14:14] MCA: Machine Check Architecture // [*] [15:15] CMOV: Cond Mov/Cmp Instructions // [*] [16:16] PAT: Page Attribute Table // [*] [17:17] PSE-36: Physical Address Extensions // [18:19] Reserved // [20:20] No-Execute page protection // [21:21] Reserved // [22:22] AMD MMX Extensions // [*] [23:23] MMX Technology // [*] [24:24] FXSR: FXSAVE/FXRSTOR (also indicates CR4.OSFXSR is available) // [25:25] Fast FXSAVE/FXRSTOR mode support // [26:26] 1G paging support // [27:27] Support RDTSCP Instruction // [28:28] Reserved // [29:29] Long Mode // [30:30] AMD 3DNow! Extensions // [31:31] AMD 3DNow! Instructions Bit32u features = BX_CPU_VENDOR_INTEL ? 0 : get_std_cpuid_features(); features &= 0x0183F3FF; #if BX_SUPPORT_3DNOW // only AMD is interesting in AMD MMX extensions features |= BX_CPUID_STD2_AMD_MMX_EXT | BX_CPUID_STD2_3DNOW_EXT | BX_CPUID_STD2_3DNOW; #endif #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) { features |= BX_CPUID_STD2_LONG_MODE; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_RDTSCP)) features |= BX_CPUID_STD2_RDTSCP; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_NX)) features |= BX_CPUID_STD2_NX; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_FFXSR)) features |= BX_CPUID_STD2_FFXSR; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_1G_PAGES)) features |= BX_CPUID_STD2_1G_PAGES; if (cpu->long64_mode()) features |= BX_CPUID_STD2_SYSCALL_SYSRET; } #endif return features; } /* Get CPU feature flags. Returned by CPUID function 80000001 in ECX register */ Bit32u bx_generic_cpuid_t::get_ext2_cpuid_features(void) const { // ECX: // [0:0] LAHF/SAHF instructions support in 64-bit mode // [1:1] CMP_Legacy: Core multi-processing legacy mode (AMD) // [2:2] SVM: Secure Virtual Machine (AMD) // [3:3] Extended APIC Space // [4:4] AltMovCR8: LOCK MOV CR0 means MOV CR8 // [5:5] LZCNT: LZCNT instruction support // [6:6] SSE4A: SSE4A Instructions support (deprecated?) // [7:7] Misaligned SSE support // [8:8] PREFETCHW: PREFETCHW instruction support // [9:9] OSVW: OS visible workarounds (AMD) // [10:10] IBS: Instruction based sampling // [11:11] XOP: Extended Operations Support and XOP Prefix // [12:12] SKINIT support // [13:13] WDT: Watchdog timer support // [14:14] reserved // [15:15] LWP: Light weight profiling // [16:16] FMA4: Four-operand FMA instructions support // [18:17] reserved // [19:19] NodeId: Indicates support for NodeId MSR (0xc001100c) // [20:20] reserved // [21:21] TBM: trailing bit manipulation instructions support // [22:22] Topology extensions support // [31:23] reserved Bit32u features = 0; #if BX_SUPPORT_X86_64 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_LONG_MODE)) features |= BX_CPUID_EXT2_LAHF_SAHF | BX_CPUID_EXT2_PREFETCHW; #endif #if BX_SUPPORT_MISALIGNED_SSE features |= BX_CPUID_EXT2_MISALIGNED_SSE; #endif if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_LZCNT)) features |= BX_CPUID_EXT2_LZCNT; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_SSE4A)) features |= BX_CPUID_EXT2_SSE4A; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_XOP)) features |= BX_CPUID_EXT2_XOP; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_FMA4)) features |= BX_CPUID_EXT2_FMA4; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_TBM)) features |= BX_CPUID_EXT2_TBM; return features; } Bit32u bx_generic_cpuid_t::get_ext3_cpuid_features(void) const { Bit32u features = 0; // [0:0] FS/GS BASE access instructions // [2:1] reserved // [3:3] BMI1: Advanced Bit Manipulation Extensions // [4:4] reserved // [5:5] AVX2 // [6:6] reserved // [7:7] SMEP: Supervisor Mode Execution Protection // [8:8] BMI2: Advanced Bit Manipulation Extensions // [9:9] Support for Enhanced REP MOVSB/STOSB // [10:10] Support for INVPCID instruction // [31:10] reserved if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_FSGSBASE)) features |= BX_CPUID_EXT3_FSGSBASE; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_BMI1)) features |= BX_CPUID_EXT3_BMI1; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_AVX2)) features |= BX_CPUID_EXT3_AVX2; if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_SMEP)) features |= BX_CPUID_EXT3_SMEP; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_BMI2)) features |= BX_CPUID_EXT3_BMI2; if (BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_INVPCID)) features |= BX_CPUID_EXT3_INVPCID; return features; } #endif void bx_generic_cpuid_t::dump_cpuid(void) const { struct cpuid_function_t leaf; unsigned n; for (n=0; n <= max_std_leaf; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } #if BX_CPU_LEVEL >= 6 if (max_ext_leaf > 0) { for (n=0x80000000; n <= max_ext_leaf; n++) { get_cpuid_leaf(n, 0x00000000, &leaf); BX_INFO(("CPUID[0x%08x]: %08x %08x %08x %08x", n, leaf.eax, leaf.ebx, leaf.ecx, leaf.edx)); } } #endif } bx_cpuid_t *create_bx_generic_cpuid(BX_CPU_C *cpu) { return new bx_generic_cpuid_t(cpu); } #endif bochs-2.6/cpu/access64.cc0000644000175000017500000010676712020641453015064 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: access64.cc 11137 2012-04-11 19:01:25Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_byte_64(unsigned s, Bit64u offset, Bit8u data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 1, CPL, BX_WRITE, (Bit8u*) &data); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 1); *hostAddr = data; return; } } if (! IsCanonical(laddr)) { BX_ERROR(("write_virtual_byte_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, 1, CPL, (void *) &data); } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_word_64(unsigned s, Bit64u offset, Bit16u data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 2, CPL, BX_WRITE, (Bit8u*) &data); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostAddr, data); return; } } if (! IsCanonical(laddr)) { BX_ERROR(("write_virtual_word_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 1) { BX_ERROR(("write_virtual_word_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+1)) { BX_ERROR(("write_virtual_word_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, 2, CPL, (void *) &data); } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_dword_64(unsigned s, Bit64u offset, Bit32u data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 4, CPL, BX_WRITE, (Bit8u*) &data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostAddr, data); return; } } if (! IsCanonical(laddr)) { BX_ERROR(("write_virtual_dword_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 3) { BX_ERROR(("write_virtual_dword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+3)) { BX_ERROR(("write_virtual_dword_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, 4, CPL, (void *) &data); } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_qword_64(unsigned s, Bit64u offset, Bit64u data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 8, CPL, BX_WRITE, (Bit8u*) &data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 8); WriteHostQWordToLittleEndian(hostAddr, data); return; } } if (! IsCanonical(laddr)) { BX_ERROR(("write_virtual_qword_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 7) { BX_ERROR(("write_virtual_qword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+7)) { BX_ERROR(("write_virtual_qword_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, 8, CPL, (void *) &data); } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_dqword_64(unsigned s, Bit64u offset, const BxPackedXmmRegister *data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 15); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 16, CPL, BX_WRITE, (Bit8u*) data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 16); WriteHostQWordToLittleEndian(hostAddr, data->xmm64u(0)); WriteHostQWordToLittleEndian(hostAddr+1, data->xmm64u(1)); return; } } if (! IsCanonical(laddr) || ! IsCanonical(laddr+15)) { BX_ERROR(("write_virtual_dqword_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, 16, CPL, (void *) data); } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_virtual_dqword_aligned_64(unsigned s, Bit64u offset, const BxPackedXmmRegister *data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = AlignedAccessLPFOf(laddr, 15); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 16, CPL, BX_WRITE, (Bit8u*) data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 16); WriteHostQWordToLittleEndian(hostAddr, data->xmm64u(0)); WriteHostQWordToLittleEndian(hostAddr+1, data->xmm64u(1)); return; } } if (laddr & 15) { BX_ERROR(("write_virtual_dqword_aligned_64(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (! IsCanonical(laddr) || ! IsCanonical(laddr+15)) { BX_ERROR(("write_virtual_dqword_aligned_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, 16, CPL, (void *) data); } #if BX_SUPPORT_AVX void BX_CPU_C::write_virtual_dword_vector_64(unsigned s, Bit64u offset, unsigned elements, const BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); unsigned len = elements << 2; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, len-1); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, len, CPL, BX_WRITE, (Bit8u*) data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, len); for (unsigned n = 0; n < elements; n++) { WriteHostDWordToLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } return; } } if (! IsCanonical(laddr) || ! IsCanonical(laddr+len-1)) { BX_ERROR(("write_virtual_dword_vector_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, len, CPL, (void *) data); } void BX_CPU_C::write_virtual_dword_vector_aligned_64(unsigned s, Bit64u offset, unsigned elements, const BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); unsigned len = elements << 2; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = AlignedAccessLPFOf(laddr, len-1); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, len, CPL, BX_WRITE, (Bit8u*) data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, len); for (unsigned n = 0; n < elements; n++) { WriteHostDWordToLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } return; } } if (laddr & (len-1)) { BX_ERROR(("write_virtual_dword_vector_aligned_64(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (! IsCanonical(laddr) || ! IsCanonical(laddr+len-1)) { BX_ERROR(("write_virtual_dword_vector_aligned_64(): canonical failure")); exception(int_number(s), 0); } access_write_linear(laddr, len, CPL, (void *) data); } #endif Bit8u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_byte_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit8u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); data = *hostAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 1, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_virtual_byte_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 1, CPL, BX_READ, (void *) &data); return data; } Bit16u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_word_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit16u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); ReadHostWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 2, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_virtual_word_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 1) { BX_ERROR(("read_virtual_word_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+1)) { BX_ERROR(("read_virtual_word_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 2, CPL, BX_READ, (void *) &data); return data; } Bit32u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_dword_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit32u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); ReadHostDWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 4, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_virtual_dword_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 3) { BX_ERROR(("read_virtual_dword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+3)) { BX_ERROR(("read_virtual_dword_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 4, CPL, BX_READ, (void *) &data); return data; } Bit64u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_virtual_qword_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); ReadHostQWordFromLittleEndian(hostAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 8, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_virtual_qword_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 7) { BX_ERROR(("read_virtual_qword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+7)) { BX_ERROR(("read_virtual_qword_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 8, CPL, BX_READ, (void *) &data); return data; } void BX_CPP_AttrRegparmN(3) BX_CPU_C::read_virtual_dqword_64(unsigned s, Bit64u offset, BxPackedXmmRegister *data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 15); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); ReadHostQWordFromLittleEndian(hostAddr, data->xmm64u(0)); ReadHostQWordFromLittleEndian(hostAddr+1, data->xmm64u(1)); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 16, CPL, BX_READ, (Bit8u*) data); return; } } if (! IsCanonical(laddr) || ! IsCanonical(laddr+15)) { BX_ERROR(("read_virtual_dqword_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 16, CPL, BX_READ, (void *) data); } void BX_CPP_AttrRegparmN(3) BX_CPU_C::read_virtual_dqword_aligned_64(unsigned s, Bit64u offset, BxPackedXmmRegister *data) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = AlignedAccessLPFOf(laddr, 15); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); ReadHostQWordFromLittleEndian(hostAddr, data->xmm64u(0)); ReadHostQWordFromLittleEndian(hostAddr+1, data->xmm64u(1)); BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), 16, CPL, BX_READ, (Bit8u*) data); return; } } if (laddr & 15) { BX_ERROR(("read_virtual_dqword_aligned_64(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (! IsCanonical(laddr) || ! IsCanonical(laddr+15)) { BX_ERROR(("read_virtual_dqword_aligned_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 16, CPL, BX_READ, (void *) data); } #if BX_SUPPORT_AVX void BX_CPU_C::read_virtual_dword_vector_64(unsigned s, Bit64u offset, unsigned elements, BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); unsigned len = elements << 2; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, len-1); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); for (unsigned n=0; n < elements; n++) { ReadHostDWordFromLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), len, CPL, BX_READ, (Bit8u*) data); return; } } if (! IsCanonical(laddr) || ! IsCanonical(laddr+len-1)) { BX_ERROR(("read_virtual_dword_vector_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, len, CPL, BX_READ, (void *) data); } void BX_CPU_C::read_virtual_dword_vector_aligned_64(unsigned s, Bit64u offset, unsigned elements, BxPackedAvxRegister *data) { BX_ASSERT(elements > 0); unsigned len = elements << 2; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = AlignedAccessLPFOf(laddr, len-1); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us read access // from this CPL. if (! (tlbEntry->accessBits & USER_PL)) { // Read this pl OK. bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); for (unsigned n=0; n < elements; n++) { ReadHostDWordFromLittleEndian(hostAddr, data->avx32u(n)); hostAddr++; } BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, (tlbEntry->ppf | pageOffset), len, CPL, BX_READ, (Bit8u*) data); return; } } if (laddr & (len-1)) { BX_ERROR(("read_virtual_dword_vector_aligned_64(): #GP misaligned access")); exception(BX_GP_EXCEPTION, 0); } if (! IsCanonical(laddr) || ! IsCanonical(laddr+len-1)) { BX_ERROR(("read_virtual_dword_vector_aligned_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, len, CPL, BX_READ, (void *) data); } #endif ////////////////////////////////////////////////////////////// // special Read-Modify-Write operations // // address translation info is kept across read/write calls // ////////////////////////////////////////////////////////////// Bit8u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_byte_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit8u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit8u *hostAddr = (Bit8u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 1); data = *hostAddr; BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 1, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_RMW_virtual_byte_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 1, CPL, BX_RW, (void *) &data); return data; } Bit16u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_word_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit16u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 2); ReadHostWordFromLittleEndian(hostAddr, data); BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 2, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_RMW_virtual_word_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 1) { BX_ERROR(("read_RMW_virtual_word_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+1)) { BX_ERROR(("read_RMW_virtual_word_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 2, CPL, BX_RW, (void *) &data); return data; } Bit32u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_dword_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit32u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 4); ReadHostDWordFromLittleEndian(hostAddr, data); BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 4, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_RMW_virtual_dword_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 3) { BX_ERROR(("read_RMW_virtual_dword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+3)) { BX_ERROR(("read_RMW_virtual_dword_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 4, CPL, BX_RW, (void *) &data); return data; } Bit64u BX_CPP_AttrRegparmN(2) BX_CPU_C::read_RMW_virtual_qword_64(unsigned s, Bit64u offset) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64); Bit64u data; Bit64u laddr = get_laddr64(s, offset); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 8); ReadHostQWordFromLittleEndian(hostAddr, data); BX_CPU_THIS_PTR address_xlation.pages = (bx_ptr_equiv_t) hostAddr; BX_CPU_THIS_PTR address_xlation.paddress1 = pAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 8, CPL, BX_READ, (Bit8u*) &data); return data; } } if (! IsCanonical(laddr)) { BX_ERROR(("read_RMW_virtual_qword_64(): canonical failure")); exception(int_number(s), 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { if (laddr & 7) { BX_ERROR(("read_RMW_virtual_qword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+7)) { BX_ERROR(("read_RMW_virtual_qword_64(): canonical failure")); exception(int_number(s), 0); } access_read_linear(laddr, 8, CPL, BX_RW, (void *) &data); return data; } void BX_CPU_C::write_new_stack_word_64(Bit64u laddr, unsigned curr_pl, Bit16u data) { bx_bool user = (curr_pl == 3); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 1); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (1 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | user))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 2, curr_pl, BX_WRITE, (Bit8u*) &data); Bit16u *hostAddr = (Bit16u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostAddr, data); return; } } if (! IsCanonical(laddr)) { BX_ERROR(("write_new_stack_word_64(): canonical failure")); exception(BX_SS_EXCEPTION, 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && user) { if (laddr & 1) { BX_ERROR(("write_new_stack_word_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+1)) { BX_ERROR(("write_new_stack_word_64(): canonical failure")); exception(BX_SS_EXCEPTION, 0); } access_write_linear(laddr, 2, curr_pl, (void *) &data); } void BX_CPU_C::write_new_stack_dword_64(Bit64u laddr, unsigned curr_pl, Bit32u data) { bx_bool user = (curr_pl == 3); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 3); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (3 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | user))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 4, curr_pl, BX_WRITE, (Bit8u*) &data); Bit32u *hostAddr = (Bit32u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostAddr, data); return; } } if (! IsCanonical(laddr)) { BX_ERROR(("write_new_stack_dword_64(): canonical failure")); exception(BX_SS_EXCEPTION, 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && user) { if (laddr & 3) { BX_ERROR(("write_new_stack_dword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+3)) { BX_ERROR(("write_new_stack_dword_64(): canonical failure")); exception(BX_SS_EXCEPTION, 0); } access_write_linear(laddr, 4, curr_pl, (void *) &data); } void BX_CPU_C::write_new_stack_qword_64(Bit64u laddr, unsigned curr_pl, Bit64u data) { bx_bool user = (curr_pl == 3); unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 7); #if BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL >= 4 Bit64u lpf = AlignedAccessLPFOf(laddr, (7 & BX_CPU_THIS_PTR alignment_check_mask)); #else Bit64u lpf = LPFOf(laddr); #endif bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access // from this CPL. if (! (tlbEntry->accessBits & (0x2 | user))) { bx_hostpageaddr_t hostPageAddr = tlbEntry->hostPageAddr; Bit32u pageOffset = PAGE_OFFSET(laddr); bx_phy_address pAddr = tlbEntry->ppf | pageOffset; BX_NOTIFY_LIN_MEMORY_ACCESS(laddr, pAddr, 8, curr_pl, BX_WRITE, (Bit8u*) &data); Bit64u *hostAddr = (Bit64u*) (hostPageAddr | pageOffset); pageWriteStampTable.decWriteStamp(pAddr, 8); WriteHostQWordToLittleEndian(hostAddr, data); return; } } if (! IsCanonical(laddr)) { BX_ERROR(("write_new_stack_qword_64(): canonical failure")); exception(BX_SS_EXCEPTION, 0); } #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && user) { if (laddr & 7) { BX_ERROR(("write_new_stack_qword_64(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif if (! IsCanonical(laddr+7)) { BX_ERROR(("write_new_stack_qword_64(): canonical failure")); exception(BX_SS_EXCEPTION, 0); } access_write_linear(laddr, 8, curr_pl, (void *) &data); } #endif bochs-2.6/cpu/tbm64.cc0000644000175000017500000001075012020641453014367 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: tbm64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 && BX_SUPPORT_AVX BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BEXTR_GqEqIdR(bxInstruction_c *i) { Bit16u control = (Bit16u) i->Id(); unsigned start = control & 0xff; unsigned len = control >> 8; Bit64u op1_64 = 0; if (start < 64 && len > 0) { op1_64 = BX_READ_64BIT_REG(i->src()); op1_64 >>= start; if (len < 64) { Bit64u extract_mask = (BX_CONST64(1) << len) - 1; op1_64 &= extract_mask; } } SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCFILL_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 + 1) & op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF((op_64 + 1) == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCI_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = ~(op_64 + 1) | op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF((op_64 + 1) == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCIC_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 + 1) & ~op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF((op_64 + 1) == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCMSK_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 + 1) ^ op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF((op_64 + 1) == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLCS_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 + 1) | op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF((op_64 + 1) == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSFILL_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 - 1) | op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF(op_64 == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSIC_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 - 1) | ~op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF(op_64 == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::T1MSKC_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 + 1) | ~op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF((op_64 + 1) == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TZMSK_BqEqR(bxInstruction_c *i) { Bit64u op_64 = BX_READ_64BIT_REG(i->src()); Bit64u result_64 = (op_64 - 1) & ~op_64; SET_FLAGS_OSZAPC_LOGIC_64(result_64); set_CF(op_64 == 0); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/mult64.cc0000644000175000017500000002123212020641453014563 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: mult64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 static unsigned partial_add(Bit32u *sum, Bit32u b) { Bit32u t = *sum; *sum += b; return (*sum < t); } void long_mul(Bit128u *product, Bit64u op1, Bit64u op2) { Bit32u op_1[2],op_2[2]; Bit32u result[5]; Bit64u nn; unsigned c; int i,j,k; op_1[0] = (Bit32u)(op1 & 0xffffffff); op_1[1] = (Bit32u)(op1 >> 32); op_2[0] = (Bit32u)(op2 & 0xffffffff); op_2[1] = (Bit32u)(op2 >> 32); for (i = 0; i < 4; i++) result[i] = 0; for (i = 0; i < 2; i++) { for (j = 0; j < 2; j++) { nn = (Bit64u) op_1[i] * (Bit64u) op_2[j]; k = i + j; c = partial_add(&result[k++], (Bit32u)(nn & 0xffffffff)); c = partial_add(&result[k++], (Bit32u)(nn >> 32) + c); while (k < 4 && c != 0) { c = partial_add(&result[k++], c); } } } product->lo = result[0] + ((Bit64u) result[1] << 32); product->hi = result[2] + ((Bit64u) result[3] << 32); } void long_neg(Bit128s *n) { Bit64u t = n->lo; n->lo = - (Bit64s)(n->lo); if (t - 1 > t) --n->hi; n->hi = ~n->hi; } void long_imul(Bit128s *product, Bit64s op1, Bit64s op2) { unsigned s1,s2; if ((s1 = (op1 < 0))) op1 = -op1; if ((s2 = (op2 < 0))) op2 = -op2; long_mul((Bit128u*)product,(Bit64u)op1,(Bit64u)op2); if (s1 ^ s2) long_neg(product); } void long_shl(Bit128u *a) { Bit64u c = a->lo >> 63; a->lo <<= 1; a->hi <<= 1; a->hi |= c; } void long_shr(Bit128u *a) { Bit64u c; c = a->hi << 63; a->hi >>= 1; a->lo >>= 1; a->lo |= c; } unsigned long_sub(Bit128u *a,Bit128u *b) { Bit64u t = a->lo; a->lo -= b->lo; int c = (a->lo > t); t = a -> hi; a->hi -= b->hi + c; return(a->hi > t); } int long_le(Bit128u *a,Bit128u *b) { if (a->hi == b->hi) { return(a->lo <= b->lo); } else { return(a->hi <= b->hi); } } void long_div(Bit128u *quotient,Bit64u *remainder,const Bit128u *dividend,Bit64u divisor) { /* n := 0; while (divisor <= dividend) do inc(n); divisor := divisor * 2; end; quotient := 0; while n > 0 do divisor := divisor div 2; quotient := quotient * 2; temp := dividend; dividend := dividend - divisor; if temp > dividend then dividend := temp; else inc(quotient); end; dec(n); end; remainder := dividend; */ Bit128u d,acc,q,temp; int n,c; d.lo = divisor; d.hi = 0; acc.lo = dividend->lo; acc.hi = dividend->hi; q.lo = 0; q.hi = 0; n = 0; while (long_le(&d,&acc) && n < 128) { long_shl(&d); n++; } while (n > 0) { long_shr(&d); long_shl(&q); temp.lo = acc.lo; temp.hi = acc.hi; c = long_sub(&acc,&d); if (c) { acc.lo = temp.lo; acc.hi = temp.hi; } else { q.lo++; } n--; } *remainder = acc.lo; quotient->lo = q.lo; quotient->hi = q.hi; } void long_idiv(Bit128s *quotient,Bit64s *remainder,Bit128s *dividend,Bit64s divisor) { unsigned s1,s2; Bit128s temp; temp = *dividend; if ((s1 = (temp.hi < 0))) { long_neg(&temp); } if ((s2 = (divisor < 0))) divisor = -divisor; long_div((Bit128u*)quotient,(Bit64u*)remainder,(Bit128u*)&temp,divisor); if (s1 ^ s2) { long_neg(quotient); } if (s1) { *remainder = -*remainder; } } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MUL_RAXEqR(bxInstruction_c *i) { Bit128u product_128; Bit64u op1_64 = RAX; Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); // product_128 = ((Bit128u) op1_64) * ((Bit128u) op2_64); // product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF); // product_64h = (Bit64u) (product_128 >> 64); long_mul(&product_128,op1_64,op2_64); /* now write product back to destination */ RAX = product_128.lo; RDX = product_128.hi; /* set EFLAGS */ SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo); if(product_128.hi != 0) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_RAXEqR(bxInstruction_c *i) { Bit128s product_128; Bit64s op1_64 = RAX; Bit64s op2_64 = BX_READ_64BIT_REG(i->src()); // product_128 = ((Bit128s) op1_64) * ((Bit128s) op2_64); // product_64l = (Bit64u) (product_128 & 0xFFFFFFFFFFFFFFFF); // product_64h = (Bit64u) (product_128 >> 64); long_imul(&product_128,op1_64,op2_64); /* now write product back to destination */ RAX = product_128.lo; RDX = product_128.hi; /* set eflags: * IMUL r/m64: condition for clearing CF & OF: * RDX:RAX = sign-extend of RAX */ SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo); /* magic compare between RDX:RAX and sign extended RAX */ if (((Bit64u)(product_128.hi) + (product_128.lo >> 63)) != 0) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIV_RAXEqR(bxInstruction_c *i) { Bit64u remainder_64, quotient_64l; Bit128u op1_128, quotient_128; Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); if (op2_64 == 0) { exception(BX_DE_EXCEPTION, 0); } op1_128.lo = RAX; op1_128.hi = RDX; // quotient_128 = op1_128 / op2_64; // remainder_64 = (Bit64u) (op1_128 % op2_64); // quotient_64l = (Bit64u) (quotient_128 & 0xFFFFFFFFFFFFFFFF); long_div("ient_128,&remainder_64,&op1_128,op2_64); quotient_64l = quotient_128.lo; if (quotient_128.hi != 0) exception(BX_DE_EXCEPTION, 0); /* set EFLAGS: * DIV affects the following flags: O,S,Z,A,P,C are undefined */ /* now write quotient back to destination */ RAX = quotient_64l; RDX = remainder_64; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IDIV_RAXEqR(bxInstruction_c *i) { Bit64s remainder_64, quotient_64l; Bit128s op1_128, quotient_128; op1_128.lo = RAX; op1_128.hi = RDX; /* check MIN_INT case */ if ((op1_128.hi == (Bit64s) BX_CONST64(0x8000000000000000)) && (!op1_128.lo)) exception(BX_DE_EXCEPTION, 0); Bit64s op2_64 = BX_READ_64BIT_REG(i->src()); if (op2_64 == 0) { exception(BX_DE_EXCEPTION, 0); } // quotient_128 = op1_128 / op2_64; // remainder_64 = (Bit64s) (op1_128 % op2_64); // quotient_64l = (Bit64s) (quotient_128 & 0xFFFFFFFFFFFFFFFF); long_idiv("ient_128,&remainder_64,&op1_128,op2_64); quotient_64l = quotient_128.lo; if ((!(quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) 0) || ((quotient_128.lo & BX_CONST64(0x8000000000000000)) && quotient_128.hi != (Bit64s) BX_CONST64(0xffffffffffffffff))) { exception(BX_DE_EXCEPTION, 0); } /* set EFLAGS: * IDIV affects the following flags: O,S,Z,A,P,C are undefined */ /* now write quotient back to destination */ RAX = quotient_64l; RDX = remainder_64; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqIdR(bxInstruction_c *i) { Bit128s product_128; Bit64s op1_64 = BX_READ_64BIT_REG(i->src()); Bit64s op2_64 = (Bit32s) i->Id(); long_imul(&product_128,op1_64,op2_64); /* now write product back to destination */ BX_WRITE_64BIT_REG(i->dst(), product_128.lo); SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo); if (((Bit64u)(product_128.hi) + (product_128.lo >> 63)) != 0) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GqEqR(bxInstruction_c *i) { Bit128s product_128; Bit64s op1_64 = BX_READ_64BIT_REG(i->dst()); Bit64s op2_64 = BX_READ_64BIT_REG(i->src()); long_imul(&product_128,op1_64,op2_64); /* now write product back to destination */ BX_WRITE_64BIT_REG(i->dst(), product_128.lo); SET_FLAGS_OSZAPC_LOGIC_64(product_128.lo); if (((Bit64u)(product_128.hi) + (product_128.lo >> 63)) != 0) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/event.cc0000644000175000017500000003437612020641453014566 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: event.cc 11309 2012-08-02 20:43:14Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #include "iodev/iodev.h" bx_bool BX_CPU_C::handleWaitForEvent(void) { // For one processor, pass the time as quickly as possible until // an interrupt wakes up the CPU. while (1) { if ((BX_CPU_INTR && (BX_CPU_THIS_PTR get_IF() || BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_MWAIT_IF)) || #if BX_SUPPORT_VMX >= 2 BX_CPU_THIS_PTR pending_vmx_timer_expired || #endif BX_CPU_THIS_PTR pending_NMI || BX_CPU_THIS_PTR pending_SMI || BX_CPU_THIS_PTR pending_INIT) { // interrupt ends the HALT condition #if BX_SUPPORT_MONITOR_MWAIT if (BX_CPU_THIS_PTR activity_state >= BX_ACTIVITY_STATE_MWAIT) BX_CPU_THIS_PTR monitor.reset_monitor(); #endif BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_ACTIVE; BX_CPU_THIS_PTR inhibit_mask = 0; // clear inhibits for after resume break; } if (BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_ACTIVE) { // happens also when MWAIT monitor was hit // BX_INFO(("handleWaitForEvent: reset detected in HLT state")); break; } if (BX_HRQ && BX_DBG_ASYNC_DMA) { // handle DMA also when CPU is halted DEV_dma_raise_hlda(); } // for multiprocessor simulation, even if this CPU is halted we still // must give the others a chance to simulate. If an interrupt has // arrived, then clear the HALT condition; otherwise just return from // the CPU loop with stop_reason STOP_CPU_HALTED. #if BX_SUPPORT_SMP if (BX_SMP_PROCESSORS > 1) { // HALT condition remains, return so other CPUs have a chance #if BX_DEBUGGER BX_CPU_THIS_PTR stop_reason = STOP_CPU_HALTED; #endif return 1; // Return to caller of cpu_loop. } #endif #if BX_DEBUGGER if (bx_guard.interrupt_requested) return 1; // Return to caller of cpu_loop. #endif if (bx_pc_system.kill_bochs_request) { // setting kill_bochs_request causes the cpu loop to return ASAP. return 1; // Return to caller of cpu_loop. } BX_TICKN(10); // when in HLT run time faster for single CPU } return 0; } BX_CPP_INLINE bx_bool BX_CPU_C::interrupts_enabled(void) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest && SVM_V_INTR_MASKING) return SVM_HOST_IF; #endif return BX_CPU_THIS_PTR get_IF(); } void BX_CPU_C::InterruptAcknowledge(void) { Bit8u vector; #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_INTR)) Svm_Vmexit(SVM_VMEXIT_INTR); } #endif #if BX_SUPPORT_VMX VMexit_ExtInterrupt(); #endif // NOTE: similar code in ::take_irq() #if BX_SUPPORT_APIC if (BX_CPU_THIS_PTR lapic.INTR) vector = BX_CPU_THIS_PTR lapic.acknowledge_int(); else #endif // if no local APIC, always acknowledge the PIC. vector = DEV_pic_iac(); // may set INTR with next interrupt BX_CPU_THIS_PTR EXT = 1; /* external event */ #if BX_SUPPORT_VMX VMexit_Event(BX_EXTERNAL_INTERRUPT, vector, 0, 0); #endif BX_INSTR_HWINTERRUPT(BX_CPU_ID, vector, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); interrupt(vector, BX_EXTERNAL_INTERRUPT, 0, 0); BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP BX_CPU_THIS_PTR EXT = 0; } #if BX_SUPPORT_SVM void BX_CPU_C::VirtualInterruptAcknowledge(void) { Bit8u vector = SVM_V_INTR_VECTOR; if (SVM_INTERCEPT(SVM_INTERCEPT0_VINTR)) Svm_Vmexit(SVM_VMEXIT_VINTR); SVM_V_IRQ = 0; BX_CPU_THIS_PTR EXT = 1; /* external event */ BX_INSTR_HWINTERRUPT(BX_CPU_ID, vector, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); interrupt(vector, BX_EXTERNAL_INTERRUPT, 0, 0); BX_CPU_THIS_PTR prev_rip = RIP; // commit new RIP BX_CPU_THIS_PTR EXT = 0; } #endif bx_bool BX_CPU_C::handleAsyncEvent(void) { // // This area is where we process special conditions and events. // if (BX_CPU_THIS_PTR activity_state != BX_ACTIVITY_STATE_ACTIVE) { // For one processor, pass the time as quickly as possible until // an interrupt wakes up the CPU. if (handleWaitForEvent()) return 1; } if (bx_pc_system.kill_bochs_request) { // setting kill_bochs_request causes the cpu loop to return ASAP. return 1; // Return to caller of cpu_loop. } // Priority 1: Hardware Reset and Machine Checks // RESET // Machine Check // (bochs doesn't support these) #if BX_SUPPORT_SVM // debug exceptions or trap due to breakpoint register match // ignored and discarded if GIF == 0 // debug traps due to EFLAGS.TF remain untouched if (! BX_CPU_THIS_PTR svm_gif) BX_CPU_THIS_PTR debug_trap &= BX_DEBUG_SINGLE_STEP_BIT; #endif // Priority 2: Trap on Task Switch // T flag in TSS is set if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_TASK_SWITCH_BIT) { exception(BX_DB_EXCEPTION, 0); // no error, not interrupt } // Priority 3: External Hardware Interventions // FLUSH // STOPCLK // SMI // INIT if (BX_CPU_THIS_PTR pending_SMI && ! BX_CPU_THIS_PTR smm_mode() && SVM_GIF) { // clear SMI pending flag and disable NMI when SMM was accepted BX_CPU_THIS_PTR pending_SMI = 0; enter_system_management_mode(); } if (BX_CPU_THIS_PTR pending_INIT && ! BX_CPU_THIS_PTR disable_INIT && SVM_GIF) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_INIT)) Svm_Vmexit(SVM_VMEXIT_INIT); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: INIT pin asserted")); VMexit(VMX_VMEXIT_INIT, 0); } #endif // reset will clear pending INIT reset(BX_RESET_SOFTWARE); #if BX_SUPPORT_SMP if (BX_SMP_PROCESSORS > 1) { // if HALT condition remains, return so other CPUs have a chance if (BX_CPU_THIS_PTR activity_state != BX_ACTIVITY_STATE_ACTIVE) { #if BX_DEBUGGER BX_CPU_THIS_PTR stop_reason = STOP_CPU_HALTED; #endif return 1; // Return to caller of cpu_loop. } } #endif } // Priority 4: Traps on Previous Instruction // Breakpoints // Debug Trap Exceptions (TF flag set or data/IO breakpoint) if (! interrupts_inhibited(BX_INHIBIT_DEBUG)) { // A trap may be inhibited on this boundary due to an instruction which loaded SS #if BX_X86_DEBUGGER // Pages with code breakpoints always have async_event=1 and therefore come here BX_CPU_THIS_PTR debug_trap |= code_breakpoint_match(get_laddr(BX_SEG_REG_CS, BX_CPU_THIS_PTR prev_rip)); #endif if (BX_CPU_THIS_PTR debug_trap & 0xf000) { exception(BX_DB_EXCEPTION, 0); // no error, not interrupt } else { BX_CPU_THIS_PTR debug_trap = 0; } } // Priority 5: External Interrupts // VMX Preemption Timer Expired. // NMI Interrupts // Maskable Hardware Interrupts if (interrupts_inhibited(BX_INHIBIT_INTERRUPTS) || ! SVM_GIF) { // Processing external interrupts is inhibited on this // boundary because of certain instructions like STI. } #if BX_SUPPORT_VMX >= 2 else if (BX_CPU_THIS_PTR in_vmx_guest && BX_CPU_THIS_PTR pending_vmx_timer_expired) { BX_CPU_THIS_PTR pending_vmx_timer_expired = 0; VMexit_PreemptionTimerExpired(); } #endif #if BX_SUPPORT_VMX else if (! BX_CPU_THIS_PTR disable_NMI && BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT)) { // NMI-window exiting BX_ERROR(("VMEXIT: NMI window exiting")); VMexit(VMX_VMEXIT_NMI_WINDOW, 0); } #endif else if (BX_CPU_THIS_PTR pending_NMI && ! BX_CPU_THIS_PTR disable_NMI) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_NMI)) Svm_Vmexit(SVM_VMEXIT_NMI); } #endif BX_CPU_THIS_PTR pending_NMI = 0; BX_CPU_THIS_PTR disable_NMI = 1; BX_CPU_THIS_PTR EXT = 1; /* external event */ #if BX_SUPPORT_VMX VMexit_Event(BX_NMI, 2, 0, 0); #endif BX_INSTR_HWINTERRUPT(BX_CPU_ID, 2, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); interrupt(2, BX_NMI, 0, 0); } #if BX_SUPPORT_VMX else if (BX_CPU_THIS_PTR vmx_interrupt_window && BX_CPU_THIS_PTR get_IF()) { // interrupt-window exiting BX_DEBUG(("VMEXIT: interrupt window exiting")); VMexit(VMX_VMEXIT_INTERRUPT_WINDOW, 0); } #endif else if (BX_CPU_INTR && BX_DBG_ASYNC_INTR && (interrupts_enabled() #if BX_SUPPORT_VMX || (BX_CPU_THIS_PTR in_vmx_guest && PIN_VMEXIT(VMX_VM_EXEC_CTRL1_EXTERNAL_INTERRUPT_VMEXIT)) #endif )) { InterruptAcknowledge(); } #if BX_SUPPORT_SVM else if (BX_CPU_THIS_PTR in_svm_guest && SVM_V_IRQ && BX_CPU_THIS_PTR get_IF() && ((SVM_V_INTR_PRIO > SVM_V_TPR) || SVM_V_IGNORE_TPR)) { // virtual interrupt acknowledge VirtualInterruptAcknowledge(); } #endif else if (BX_HRQ && BX_DBG_ASYNC_DMA) { // NOTE: similar code in ::take_dma() // assert Hold Acknowledge (HLDA) and go into a bus hold state DEV_dma_raise_hlda(); } if (BX_CPU_THIS_PTR get_TF()) { // TF is set before execution of next instruction. Schedule // a debug trap (#DB) after execution. After completion of // next instruction, the code above will invoke the trap. BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_SINGLE_STEP_BIT; } // Priority 6: Faults from fetching next instruction // Code breakpoint fault // Code segment limit violation (priority 7 on 486/Pentium) // Code page fault (priority 7 on 486/Pentium) // (handled in main decode loop) // Priority 7: Faults from decoding next instruction // Instruction length > 15 bytes // Illegal opcode // Coprocessor not available // (handled in main decode loop etc) // Priority 8: Faults on executing an instruction // Floating point execution // Overflow // Bound error // Invalid TSS // Segment not present // Stack fault // General protection // Data page fault // Alignment check // (handled by rest of the code) if (!((BX_CPU_INTR && interrupts_enabled() && SVM_GIF) || BX_CPU_THIS_PTR debug_trap || // BX_CPU_THIS_PTR get_TF() // implies debug_trap is set BX_HRQ #if BX_SUPPORT_VMX || BX_CPU_THIS_PTR vmx_interrupt_window || (BX_CPU_THIS_PTR in_vmx_guest && ! BX_CPU_THIS_PTR disable_NMI && VMEXIT(VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT)) #endif #if BX_SUPPORT_VMX >= 2 || BX_CPU_THIS_PTR pending_vmx_timer_expired #endif #if BX_SUPPORT_SVM || (BX_CPU_THIS_PTR in_svm_guest && SVM_V_IRQ && BX_CPU_THIS_PTR get_IF() && ((SVM_V_INTR_PRIO > SVM_V_TPR) || SVM_V_IGNORE_TPR)) #endif #if BX_X86_DEBUGGER // a debug code breakpoint is set in current page || BX_CPU_THIS_PTR codebp #endif )) BX_CPU_THIS_PTR async_event = 0; return 0; // Continue executing cpu_loop. } // Certain instructions inhibit interrupts, some debug exceptions and single-step traps. void BX_CPU_C::inhibit_interrupts(unsigned mask) { BX_DEBUG(("inhibit interrupts mask = %d", mask)); BX_CPU_THIS_PTR inhibit_mask = mask; BX_CPU_THIS_PTR inhibit_icount = get_icount() + 1; // inhibit for next instruction } bx_bool BX_CPU_C::interrupts_inhibited(unsigned mask) { return (get_icount() <= BX_CPU_THIS_PTR inhibit_icount) && (BX_CPU_THIS_PTR inhibit_mask & mask) == mask; } void BX_CPU_C::deliver_SIPI(unsigned vector) { if (BX_CPU_THIS_PTR activity_state == BX_ACTIVITY_STATE_WAIT_FOR_SIPI) { BX_CPU_THIS_PTR activity_state = BX_ACTIVITY_STATE_ACTIVE; RIP = 0; load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], vector*0x100); BX_CPU_THIS_PTR disable_INIT = 0; // enable INIT pin back BX_INFO(("CPU %d started up at %04X:%08X by APIC", BX_CPU_THIS_PTR bx_cpuid, vector*0x100, EIP)); } else { BX_INFO(("CPU %d started up by APIC, but was not halted at the time", BX_CPU_THIS_PTR bx_cpuid)); } } void BX_CPU_C::deliver_INIT(void) { if (! BX_CPU_THIS_PTR disable_INIT) { BX_CPU_THIS_PTR pending_INIT = 1; BX_CPU_THIS_PTR async_event = 1; } } void BX_CPU_C::deliver_NMI(void) { BX_CPU_THIS_PTR pending_NMI = 1; BX_CPU_THIS_PTR async_event = 1; } void BX_CPU_C::deliver_SMI(void) { BX_CPU_THIS_PTR pending_SMI = 1; BX_CPU_THIS_PTR async_event = 1; } void BX_CPU_C::set_INTR(bx_bool value) { BX_CPU_THIS_PTR INTR = value; BX_CPU_THIS_PTR async_event = 1; } #if BX_DEBUGGER void BX_CPU_C::dbg_take_irq(void) { // NOTE: similar code in ::cpu_loop() if (BX_CPU_INTR && BX_CPU_THIS_PTR get_IF()) { if (setjmp(BX_CPU_THIS_PTR jmp_buf_env) == 0) { // normal return from setjmp setup unsigned vector = DEV_pic_iac(); // may set INTR with next interrupt BX_CPU_THIS_PTR EXT = 1; // external event BX_CPU_THIS_PTR async_event = 1; // set in case INTR is triggered interrupt(vector, BX_EXTERNAL_INTERRUPT, 0, 0); } } } void BX_CPU_C::dbg_force_interrupt(unsigned vector) { // Used to force simulator to take an interrupt, without // regard to IF if (setjmp(BX_CPU_THIS_PTR jmp_buf_env) == 0) { // normal return from setjmp setup BX_CPU_THIS_PTR EXT = 1; // external event BX_CPU_THIS_PTR async_event = 1; // probably don't need this interrupt(vector, BX_EXTERNAL_INTERRUPT, 0, 0); } } void BX_CPU_C::dbg_take_dma(void) { // NOTE: similar code in ::cpu_loop() if (BX_HRQ) { BX_CPU_THIS_PTR async_event = 1; // set in case INTR is triggered DEV_dma_raise_hlda(); } } #endif // #if BX_DEBUGGER bochs-2.6/cpu/shift8.cc0000644000175000017500000002661712020641453014651 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: shift8.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EbR(bxInstruction_c *i) { unsigned count; unsigned bit0, bit7; if (i->getIaOpcode() == BX_IA_ROL_Eb) count = CL; else count = i->Ib(); Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); if ((count & 0x07) == 0) { if (count & 0x18) { bit0 = (op1_8 & 1); bit7 = (op1_8 >> 7); SET_FLAGS_OxxxxC(bit0 ^ bit7, bit0); } } else { count &= 0x7; // use only lowest 3 bits Bit8u result_8 = (op1_8 << count) | (op1_8 >> (8 - count)); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); /* set eflags: * ROL count affects the following flags: C, O */ bit0 = (result_8 & 1); bit7 = (result_8 >> 7); SET_FLAGS_OxxxxC(bit0 ^ bit7, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EbM(bxInstruction_c *i) { unsigned count; unsigned bit0, bit7; if (i->getIaOpcode() == BX_IA_ROL_Eb) count = CL; else count = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); if ((count & 0x07) == 0) { if (count & 0x18) { bit0 = (op1_8 & 1); bit7 = (op1_8 >> 7); SET_FLAGS_OxxxxC(bit0 ^ bit7, bit0); } } else { count &= 0x7; // use only lowest 3 bits Bit8u result_8 = (op1_8 << count) | (op1_8 >> (8 - count)); write_RMW_virtual_byte(result_8); /* set eflags: * ROL count affects the following flags: C, O */ bit0 = (result_8 & 1); bit7 = (result_8 >> 7); SET_FLAGS_OxxxxC(bit0 ^ bit7, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EbR(bxInstruction_c *i) { unsigned count; unsigned bit6, bit7; if (i->getIaOpcode() == BX_IA_ROR_Eb) count = CL; else count = i->Ib(); Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); if ((count & 0x07) == 0) { if (count & 0x18) { bit6 = (op1_8 >> 6) & 1; bit7 = (op1_8 >> 7) & 1; SET_FLAGS_OxxxxC(bit6 ^ bit7, bit7); } } else { count &= 0x7; /* use only bottom 3 bits */ Bit8u result_8 = (op1_8 >> count) | (op1_8 << (8 - count)); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); /* set eflags: * ROR count affects the following flags: C, O */ bit6 = (result_8 >> 6) & 1; bit7 = (result_8 >> 7) & 1; SET_FLAGS_OxxxxC(bit6 ^ bit7, bit7); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EbM(bxInstruction_c *i) { unsigned count; unsigned bit6, bit7; if (i->getIaOpcode() == BX_IA_ROR_Eb) count = CL; else count = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); if ((count & 0x07) == 0) { if (count & 0x18) { bit6 = (op1_8 >> 6) & 1; bit7 = (op1_8 >> 7) & 1; SET_FLAGS_OxxxxC(bit6 ^ bit7, bit7); } } else { count &= 0x7; /* use only bottom 3 bits */ Bit8u result_8 = (op1_8 >> count) | (op1_8 << (8 - count)); write_RMW_virtual_byte(result_8); /* set eflags: * ROR count affects the following flags: C, O */ bit6 = (result_8 >> 6) & 1; bit7 = (result_8 >> 7) & 1; SET_FLAGS_OxxxxC(bit6 ^ bit7, bit7); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EbR(bxInstruction_c *i) { Bit8u result_8; unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_RCL_Eb) count = CL; else count = i->Ib(); count = (count & 0x1f) % 9; if (! count) { BX_NEXT_INSTR(i); } Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); if (count==1) { result_8 = (op1_8 << 1) | getB_CF(); } else { result_8 = (op1_8 << count) | (getB_CF() << (count - 1)) | (op1_8 >> (9 - count)); } BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); cf = (op1_8 >> (8 - count)) & 0x01; of = cf ^ (result_8 >> 7); // of = cf ^ result7 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EbM(bxInstruction_c *i) { Bit8u result_8; unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_RCL_Eb) count = CL; else count = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); count = (count & 0x1f) % 9; if (! count) { BX_NEXT_INSTR(i); } if (count==1) { result_8 = (op1_8 << 1) | getB_CF(); } else { result_8 = (op1_8 << count) | (getB_CF() << (count - 1)) | (op1_8 >> (9 - count)); } write_RMW_virtual_byte(result_8); cf = (op1_8 >> (8 - count)) & 0x01; of = cf ^ (result_8 >> 7); // of = cf ^ result7 SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EbR(bxInstruction_c *i) { unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_RCR_Eb) count = CL; else count = i->Ib(); count = (count & 0x1f) % 9; if (count) { Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit8u result_8 = (op1_8 >> count) | (getB_CF() << (8 - count)) | (op1_8 << (9 - count)); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); cf = (op1_8 >> (count - 1)) & 0x1; of = (((result_8 << 1) ^ result_8) >> 7) & 0x1; // of = result6 ^ result7 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EbM(bxInstruction_c *i) { unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_RCR_Eb) count = CL; else count = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); count = (count & 0x1f) % 9; if (count) { Bit8u result_8 = (op1_8 >> count) | (getB_CF() << (8 - count)) | (op1_8 << (9 - count)); write_RMW_virtual_byte(result_8); cf = (op1_8 >> (count - 1)) & 0x1; of = (((result_8 << 1) ^ result_8) >> 7) & 0x1; // of = result6 ^ result7 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EbR(bxInstruction_c *i) { Bit8u result_8; unsigned count; unsigned of = 0, cf = 0; if (i->getIaOpcode() == BX_IA_SHL_Eb) count = CL; else count = i->Ib(); count &= 0x1f; if (!count) { BX_NEXT_INSTR(i); } Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); if (count <= 8) { result_8 = (op1_8 << count); cf = (op1_8 >> (8 - count)) & 0x1; of = cf ^ (result_8 >> 7); } else { result_8 = 0; } BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); SET_FLAGS_OSZAPC_LOGIC_8(result_8); SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EbM(bxInstruction_c *i) { Bit8u result_8; unsigned count; unsigned of = 0, cf = 0; if (i->getIaOpcode() == BX_IA_SHL_Eb) count = CL; else count = i->Ib(); count &= 0x1f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); if (!count) { BX_NEXT_INSTR(i); } if (count <= 8) { result_8 = (op1_8 << count); cf = (op1_8 >> (8 - count)) & 0x1; of = cf ^ (result_8 >> 7); } else { result_8 = 0; } write_RMW_virtual_byte(result_8); SET_FLAGS_OSZAPC_LOGIC_8(result_8); SET_FLAGS_OxxxxC(of, cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EbR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SHR_Eb) count = CL; else count = i->Ib(); count &= 0x1f; if (count) { Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit8u result_8 = (op1_8 >> count); BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); unsigned cf = (op1_8 >> (count - 1)) & 0x1; // note, that of == result7 if count == 1 and // of == 0 if count >= 2 unsigned of = (((result_8 << 1) ^ result_8) >> 7) & 0x1; SET_FLAGS_OSZAPC_LOGIC_8(result_8); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EbM(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SHR_Eb) count = CL; else count = i->Ib(); count &= 0x1f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); if (count) { Bit8u result_8 = (op1_8 >> count); write_RMW_virtual_byte(result_8); unsigned cf = (op1_8 >> (count - 1)) & 0x1; // note, that of == result7 if count == 1 and // of == 0 if count >= 2 unsigned of = (((result_8 << 1) ^ result_8) >> 7) & 0x1; SET_FLAGS_OSZAPC_LOGIC_8(result_8); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EbR(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SAR_Eb) count = CL; else count = i->Ib(); count &= 0x1f; if (count) { Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); Bit8u result_8 = ((Bit8s) op1_8) >> count; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), result_8); unsigned cf = (((Bit8s) op1_8) >> (count - 1)) & 0x1; SET_FLAGS_OSZAPC_LOGIC_8(result_8); /* signed overflow cannot happen in SAR instruction */ SET_FLAGS_OxxxxC(0, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EbM(bxInstruction_c *i) { unsigned count; if (i->getIaOpcode() == BX_IA_SAR_Eb) count = CL; else count = i->Ib(); count &= 0x1f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); if (count) { Bit8u result_8 = ((Bit8s) op1_8) >> count; write_RMW_virtual_byte(result_8); unsigned cf = (((Bit8s) op1_8) >> (count - 1)) & 0x1; SET_FLAGS_OSZAPC_LOGIC_8(result_8); /* signed overflow cannot happen in SAR instruction */ SET_FLAGS_OxxxxC(0, cf); } BX_NEXT_INSTR(i); } bochs-2.6/cpu/stack.h0000644000175000017500000000704512020641453014405 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: stack.h 11106 2012-03-25 11:54:32Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_PUSHPOP_H #define BX_PUSHPOP_H BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::push_16(Bit16u value16) { #if BX_SUPPORT_X86_64 if (long64_mode()) { /* StackAddrSize = 64 */ stack_write_word(RSP-2, value16); RSP -= 2; } else #endif if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { /* StackAddrSize = 32 */ stack_write_word((Bit32u) (ESP-2), value16); ESP -= 2; } else /* StackAddrSize = 16 */ { stack_write_word((Bit16u) (SP-2), value16); SP -= 2; } } BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::push_32(Bit32u value32) { #if BX_SUPPORT_X86_64 if (long64_mode()) { /* StackAddrSize = 64 */ stack_write_dword(RSP-4, value32); RSP -= 4; } else #endif if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { /* StackAddrSize = 32 */ stack_write_dword((Bit32u) (ESP-4), value32); ESP -= 4; } else /* StackAddrSize = 16 */ { stack_write_dword((Bit16u) (SP-4), value32); SP -= 4; } } /* push 64 bit operand */ #if BX_SUPPORT_X86_64 BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::push_64(Bit64u value64) { /* StackAddrSize = 64 */ stack_write_qword(RSP-8, value64); RSP -= 8; } #endif /* pop 16 bit operand from the stack */ BX_CPP_INLINE Bit16u BX_CPU_C::pop_16(void) { Bit16u value16; #if BX_SUPPORT_X86_64 if (long64_mode()) { /* StackAddrSize = 64 */ value16 = stack_read_word(RSP); RSP += 2; } else #endif if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { /* StackAddrSize = 32 */ value16 = stack_read_word(ESP); ESP += 2; } else { /* StackAddrSize = 16 */ value16 = stack_read_word(SP); SP += 2; } return value16; } /* pop 32 bit operand from the stack */ BX_CPP_INLINE Bit32u BX_CPU_C::pop_32(void) { Bit32u value32; #if BX_SUPPORT_X86_64 if (long64_mode()) { /* StackAddrSize = 64 */ value32 = stack_read_dword(RSP); RSP += 4; } else #endif if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) { /* StackAddrSize = 32 */ value32 = stack_read_dword(ESP); ESP += 4; } else { /* StackAddrSize = 16 */ value32 = stack_read_dword(SP); SP += 4; } return value32; } /* pop 64 bit operand from the stack */ #if BX_SUPPORT_X86_64 BX_CPP_INLINE Bit64u BX_CPU_C::pop_64(void) { /* StackAddrSize = 64 */ Bit64u value64 = stack_read_qword(RSP); RSP += 8; return value64; } #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/xop.cc0000644000175000017500000007226412020641453014251 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: xop.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX extern void mxcsr_to_softfloat_status_word(float_status_t &status, bx_mxcsr_t mxcsr); #include "simd_int.h" #include "simd_compare.h" typedef void (*simd_compare_method)(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2); // comparison predicate for PCOMB static simd_compare_method compare8[8] = { sse_pcmpltb, sse_pcmpleb, sse_pcmpgtb, sse_pcmpgeb, sse_pcmpeqb, sse_pcmpneb, sse_pcmpfalse, sse_pcmptrue }; // comparison predicate for PCOMUB static simd_compare_method compare8u[8] = { sse_pcmpltub, sse_pcmpleub, sse_pcmpgtub, sse_pcmpgeub, sse_pcmpeqb, sse_pcmpneb, sse_pcmpfalse, sse_pcmptrue }; // comparison predicate for PCOMW static simd_compare_method compare16[8] = { sse_pcmpltw, sse_pcmplew, sse_pcmpgtw, sse_pcmpgew, sse_pcmpeqw, sse_pcmpnew, sse_pcmpfalse, sse_pcmptrue }; // comparison predicate for PCOMUW static simd_compare_method compare16u[8] = { sse_pcmpltuw, sse_pcmpleuw, sse_pcmpgtuw, sse_pcmpgeuw, sse_pcmpeqw, sse_pcmpnew, sse_pcmpfalse, sse_pcmptrue }; // comparison predicate for PCOMD static simd_compare_method compare32[8] = { sse_pcmpltd, sse_pcmpled, sse_pcmpgtd, sse_pcmpged, sse_pcmpeqd, sse_pcmpned, sse_pcmpfalse, sse_pcmptrue }; // comparison predicate for PCOMUD static simd_compare_method compare32u[8] = { sse_pcmpltud, sse_pcmpleud, sse_pcmpgtud, sse_pcmpgeud, sse_pcmpeqd, sse_pcmpned, sse_pcmpfalse, sse_pcmptrue }; // comparison predicate for PCOMQ static simd_compare_method compare64[8] = { sse_pcmpltq, sse_pcmpleq, sse_pcmpgtq, sse_pcmpgeq, sse_pcmpeqq, sse_pcmpneq, sse_pcmpfalse, sse_pcmptrue }; // comparison predicate for PCOMUQ static simd_compare_method compare64u[8] = { sse_pcmpltuq, sse_pcmpleuq, sse_pcmpgtuq, sse_pcmpgeuq, sse_pcmpeqq, sse_pcmpneq, sse_pcmpfalse, sse_pcmptrue }; typedef Bit8u (*vpperm_operation)(Bit8u byte); BX_CPP_INLINE Bit8u vpperm_bit_reverse(Bit8u v8) { return (v8 >> 7) | ((v8 >> 5) & 0x02) | ((v8 >> 3) & 0x04) | ((v8 >> 1) & 0x08) | ((v8 << 1) & 0x10) | ((v8 << 3) & 0x20) | ((v8 << 5) & 0x40) | (v8 << 7); } BX_CPP_INLINE Bit8u vpperm_noop(Bit8u v8) { return v8; } BX_CPP_INLINE Bit8u vpperm_invert(Bit8u v8) { return ~v8; } BX_CPP_INLINE Bit8u vpperm_invert_bit_reverse(Bit8u v8) { return vpperm_bit_reverse(~v8); } BX_CPP_INLINE Bit8u vpperm_zeros(Bit8u v8) { return 0; } BX_CPP_INLINE Bit8u vpperm_ones(Bit8u v8) { return 0xff; } BX_CPP_INLINE Bit8u vpperm_replicate_msb(Bit8u v8) { return (((Bit8s) v8) >> 7); } BX_CPP_INLINE Bit8u vpperm_invert_replicate_msb(Bit8u v8) { return vpperm_replicate_msb(~v8); } // logical operation for VPPERM static vpperm_operation vpperm_op[8] = { vpperm_noop, vpperm_invert, vpperm_bit_reverse, vpperm_invert_bit_reverse, vpperm_zeros, vpperm_ones, vpperm_replicate_msb, vpperm_invert_replicate_msb }; BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCMOV_VdqHdqWdqVIb(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) { sse_pselect(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n)); } BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPPERM_VdqHdqWdqVIb(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()), dst; for (unsigned n=0;n<16;n++) { unsigned control = op3.xmmubyte(n); if (control & 0x10) dst.xmmubyte(n) = op1.xmmubyte(control & 0xf); else dst.xmmubyte(n) = op2.xmmubyte(control & 0xf); dst.xmmubyte(n) = vpperm_op[control >> 5](dst.xmmubyte(n)); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), dst); BX_NEXT_INSTR(i); } #define XOP_SHIFT_ROTATE(HANDLER, func) \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); \ \ (func)(&op1, &op2); \ \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); \ \ BX_NEXT_INSTR(i); \ } XOP_SHIFT_ROTATE(VPSHAB_VdqWdqHdq, sse_pshab); XOP_SHIFT_ROTATE(VPSHAW_VdqWdqHdq, sse_pshaw); XOP_SHIFT_ROTATE(VPSHAD_VdqWdqHdq, sse_pshad); XOP_SHIFT_ROTATE(VPSHAQ_VdqWdqHdq, sse_pshaq); XOP_SHIFT_ROTATE(VPSHLB_VdqWdqHdq, sse_pshlb); XOP_SHIFT_ROTATE(VPSHLW_VdqWdqHdq, sse_pshlw); XOP_SHIFT_ROTATE(VPSHLD_VdqWdqHdq, sse_pshld); XOP_SHIFT_ROTATE(VPSHLQ_VdqWdqHdq, sse_pshlq); XOP_SHIFT_ROTATE(VPROTB_VdqWdqHdq, sse_protb); XOP_SHIFT_ROTATE(VPROTW_VdqWdqHdq, sse_protw); XOP_SHIFT_ROTATE(VPROTD_VdqWdqHdq, sse_protd); XOP_SHIFT_ROTATE(VPROTQ_VdqWdqHdq, sse_protq); BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSSWW_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); for(unsigned n=0;n<8;n++) { op1.xmm16s(n) = SaturateDwordSToWordS(((Bit32s) op1.xmm16s(n) * (Bit32s) op2.xmm16s(n)) + (Bit32s) op3.xmm16s(n)); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSSWD_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); op1.xmm32s(0) = SaturateQwordSToDwordS(((Bit32s) op1.xmm16s(1) * (Bit32s) op2.xmm16s(1)) + (Bit64s) op3.xmm32s(0)); op1.xmm32s(1) = SaturateQwordSToDwordS(((Bit32s) op1.xmm16s(3) * (Bit32s) op2.xmm16s(3)) + (Bit64s) op3.xmm32s(1)); op1.xmm32s(2) = SaturateQwordSToDwordS(((Bit32s) op1.xmm16s(5) * (Bit32s) op2.xmm16s(5)) + (Bit64s) op3.xmm32s(2)); op1.xmm32s(3) = SaturateQwordSToDwordS(((Bit32s) op1.xmm16s(7) * (Bit32s) op2.xmm16s(7)) + (Bit64s) op3.xmm32s(3)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_CPP_INLINE Bit64s add_saturate64(Bit64s a, Bit64s b) { Bit64s r = a + b; Bit64u overflow = GET_ADD_OVERFLOW(a, b, r, BX_CONST64(0x8000000000000000)); if (! overflow) return r; // signed overflow detected, saturate if (a > 0) overflow--; return (Bit64s) overflow; } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSSDQL_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); Bit64s product1 = (Bit64s) op1.xmm32s(0) * (Bit64s) op2.xmm32s(0); Bit64s product2 = (Bit64s) op1.xmm32s(2) * (Bit64s) op2.xmm32s(2); op1.xmm64s(0) = add_saturate64(product1, op3.xmm64s(0)); op1.xmm64s(1) = add_saturate64(product2, op3.xmm64s(1)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSSDD_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); for(unsigned n=0;n<4;n++) { op1.xmm32s(n) = SaturateQwordSToDwordS(((Bit64s) op1.xmm32s(n) * (Bit64s) op2.xmm32s(n)) + (Bit64s) op3.xmm32s(n)); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSSDQH_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); Bit64s product1 = (Bit64s) op1.xmm32s(1) * (Bit64s) op2.xmm32s(1); Bit64s product2 = (Bit64s) op1.xmm32s(3) * (Bit64s) op2.xmm32s(3); op1.xmm64s(0) = add_saturate64(product1, op3.xmm64s(0)); op1.xmm64s(1) = add_saturate64(product2, op3.xmm64s(1)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSWW_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); for(unsigned n=0;n<8;n++) { op1.xmm16s(n) = ((Bit32s) op1.xmm16s(n) * (Bit32s) op2.xmm16s(n)) + (Bit32s) op3.xmm16s(n); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSWD_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); op1.xmm32s(0) = ((Bit32s) op1.xmm16s(1) * (Bit32s) op2.xmm16s(1)) + (Bit64s) op3.xmm32s(0); op1.xmm32s(1) = ((Bit32s) op1.xmm16s(3) * (Bit32s) op2.xmm16s(3)) + (Bit64s) op3.xmm32s(1); op1.xmm32s(2) = ((Bit32s) op1.xmm16s(5) * (Bit32s) op2.xmm16s(5)) + (Bit64s) op3.xmm32s(2); op1.xmm32s(3) = ((Bit32s) op1.xmm16s(7) * (Bit32s) op2.xmm16s(7)) + (Bit64s) op3.xmm32s(3); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSDQL_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); Bit64s product1 = (Bit64s) op1.xmm32s(0) * (Bit64s) op2.xmm32s(0); Bit64s product2 = (Bit64s) op1.xmm32s(2) * (Bit64s) op2.xmm32s(2); op1.xmm64s(0) = product1 + op3.xmm64s(0); op1.xmm64s(1) = product2 + op3.xmm64s(1); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSDD_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); for(unsigned n=0;n<4;n++) { op1.xmm32s(n) = ((Bit64s) op1.xmm32s(n) * (Bit64s) op2.xmm32s(n)) + (Bit64s) op3.xmm32s(n); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMACSDQH_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); Bit64s product1 = (Bit64s) op1.xmm32s(1) * (Bit64s) op2.xmm32s(1); Bit64s product2 = (Bit64s) op1.xmm32s(3) * (Bit64s) op2.xmm32s(3); op1.xmm64s(0) = product1 + op3.xmm64s(0); op1.xmm64s(1) = product2 + op3.xmm64s(1); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMADCSSWD_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); Bit32s product[8]; for(unsigned n=0;n < 8;n++) product[n] = (Bit32s) op1.xmm16s(n) * (Bit32s) op2.xmm16s(n); op1.xmm32s(0) = SaturateQwordSToDwordS((Bit64s) product[0] + (Bit64s) product[1] + (Bit64s) op3.xmm32s(0)); op1.xmm32s(1) = SaturateQwordSToDwordS((Bit64s) product[2] + (Bit64s) product[3] + (Bit64s) op3.xmm32s(1)); op1.xmm32s(2) = SaturateQwordSToDwordS((Bit64s) product[4] + (Bit64s) product[5] + (Bit64s) op3.xmm32s(2)); op1.xmm32s(3) = SaturateQwordSToDwordS((Bit64s) product[6] + (Bit64s) product[7] + (Bit64s) op3.xmm32s(3)); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMADCSWD_VdqHdqWdqVIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister op3 = BX_READ_XMM_REG(i->src3()); Bit32s product[8]; for(unsigned n=0;n < 8;n++) product[n] = (Bit32s) op1.xmm16s(n) * (Bit32s) op2.xmm16s(n); op1.xmm32s(0) = product[0] + product[1] + op3.xmm32s(0); op1.xmm32s(1) = product[2] + product[3] + op3.xmm32s(1); op1.xmm32s(2) = product[4] + product[5] + op3.xmm32s(2); op1.xmm32s(3) = product[6] + product[7] + op3.xmm32s(3); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPROTB_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); int count = i->Ib(); if (count > 0) { // rotate left sse_prolb(&op, count); } else if (count < 0) { // rotate right sse_prorb(&op, -count); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPROTW_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); int count = i->Ib(); if (count > 0) { // rotate left sse_prolw(&op, count); } else if (count < 0) { // rotate right sse_prorw(&op, -count); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPROTD_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); int count = i->Ib(); if (count > 0) { // rotate left sse_prold(&op, count); } else if (count < 0) { // rotate right sse_prord(&op, -count); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPROTQ_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); int count = i->Ib(); if (count > 0) { // rotate left sse_prolq(&op, count); } else if (count < 0) { // rotate right sse_prorq(&op, -count); } BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMB_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare8[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMW_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare16[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMD_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare32[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMQ_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare64[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMUB_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare8u[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMUW_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare16u[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMUD_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare32u[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPCOMUQ_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); compare64u[i->Ib() & 7](&op1, &op2); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZPS_VpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (4*len); n++) { op.avx32u(n) = float32_frc(op.avx32u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZPD_VpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < (2*len); n++) { op.avx64u(n) = float64_frc(op.avx64u(n), status); } check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZSS_VssWssR(bxInstruction_c *i) { float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); BxPackedXmmRegister r; float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); r.xmm64u(0) = (Bit64u) float32_frc(op, status); r.xmm64u(1) = 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), r); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFRCZSD_VsdWsdR(bxInstruction_c *i) { float64 op = BX_READ_XMM_REG_LO_QWORD(i->src()); BxPackedXmmRegister r; float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); r.xmm64u(0) = float64_frc(op, status); r.xmm64u(1) = 0; check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), r); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDBW_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm16s(0) = (Bit16s) op.xmmsbyte(0x0) + (Bit16s) op.xmmsbyte(0x1); op.xmm16s(1) = (Bit16s) op.xmmsbyte(0x2) + (Bit16s) op.xmmsbyte(0x3); op.xmm16s(2) = (Bit16s) op.xmmsbyte(0x4) + (Bit16s) op.xmmsbyte(0x5); op.xmm16s(3) = (Bit16s) op.xmmsbyte(0x6) + (Bit16s) op.xmmsbyte(0x7); op.xmm16s(4) = (Bit16s) op.xmmsbyte(0x8) + (Bit16s) op.xmmsbyte(0x9); op.xmm16s(5) = (Bit16s) op.xmmsbyte(0xA) + (Bit16s) op.xmmsbyte(0xB); op.xmm16s(6) = (Bit16s) op.xmmsbyte(0xC) + (Bit16s) op.xmmsbyte(0xD); op.xmm16s(7) = (Bit16s) op.xmmsbyte(0xE) + (Bit16s) op.xmmsbyte(0xF); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDBD_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32s(0) = (Bit32s) op.xmmsbyte(0x0) + (Bit32s) op.xmmsbyte(0x1) + (Bit32s) op.xmmsbyte(0x2) + (Bit32s) op.xmmsbyte(0x3); op.xmm32s(1) = (Bit32s) op.xmmsbyte(0x4) + (Bit32s) op.xmmsbyte(0x5) + (Bit32s) op.xmmsbyte(0x6) + (Bit32s) op.xmmsbyte(0x7); op.xmm32s(2) = (Bit32s) op.xmmsbyte(0x8) + (Bit32s) op.xmmsbyte(0x9) + (Bit32s) op.xmmsbyte(0xA) + (Bit32s) op.xmmsbyte(0xB); op.xmm32s(3) = (Bit32s) op.xmmsbyte(0xC) + (Bit32s) op.xmmsbyte(0xD) + (Bit32s) op.xmmsbyte(0xE) + (Bit32s) op.xmmsbyte(0xF); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDBQ_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm64s(0) = (Bit32s) op.xmmsbyte(0x0) + (Bit32s) op.xmmsbyte(0x1) + (Bit32s) op.xmmsbyte(0x2) + (Bit32s) op.xmmsbyte(0x3) + (Bit32s) op.xmmsbyte(0x4) + (Bit32s) op.xmmsbyte(0x5) + (Bit32s) op.xmmsbyte(0x6) + (Bit32s) op.xmmsbyte(0x7); op.xmm64s(1) = (Bit32s) op.xmmsbyte(0x8) + (Bit32s) op.xmmsbyte(0x9) + (Bit32s) op.xmmsbyte(0xA) + (Bit32s) op.xmmsbyte(0xB) + (Bit32s) op.xmmsbyte(0xC) + (Bit32s) op.xmmsbyte(0xD) + (Bit32s) op.xmmsbyte(0xE) + (Bit32s) op.xmmsbyte(0xF); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDWD_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32s(0) = (Bit32s) op.xmm16s(0) + (Bit32s) op.xmm16s(1); op.xmm32s(1) = (Bit32s) op.xmm16s(2) + (Bit32s) op.xmm16s(3); op.xmm32s(2) = (Bit32s) op.xmm16s(4) + (Bit32s) op.xmm16s(5); op.xmm32s(3) = (Bit32s) op.xmm16s(6) + (Bit32s) op.xmm16s(7); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDWQ_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm64s(0) = (Bit32s) op.xmm16s(0) + (Bit32s) op.xmm16s(1) + (Bit32s) op.xmm16s(2) + (Bit32s) op.xmm16s(3); op.xmm64s(1) = (Bit32s) op.xmm16s(4) + (Bit32s) op.xmm16s(5) + (Bit32s) op.xmm16s(6) + (Bit32s) op.xmm16s(7); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDDQ_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm64s(0) = (Bit64s) op.xmm32s(0) + (Bit64s) op.xmm32s(1); op.xmm64s(1) = (Bit64s) op.xmm32s(2) + (Bit64s) op.xmm32s(3); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDUBW_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm16u(0) = (Bit16u) op.xmmubyte(0x0) + (Bit16u) op.xmmubyte(0x1); op.xmm16u(1) = (Bit16u) op.xmmubyte(0x2) + (Bit16u) op.xmmubyte(0x3); op.xmm16u(2) = (Bit16u) op.xmmubyte(0x4) + (Bit16u) op.xmmubyte(0x5); op.xmm16u(3) = (Bit16u) op.xmmubyte(0x6) + (Bit16u) op.xmmubyte(0x7); op.xmm16u(4) = (Bit16u) op.xmmubyte(0x8) + (Bit16u) op.xmmubyte(0x9); op.xmm16u(5) = (Bit16u) op.xmmubyte(0xA) + (Bit16u) op.xmmubyte(0xB); op.xmm16u(6) = (Bit16u) op.xmmubyte(0xC) + (Bit16u) op.xmmubyte(0xD); op.xmm16u(7) = (Bit16u) op.xmmubyte(0xE) + (Bit16u) op.xmmubyte(0xF); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDUBD_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32u(0) = (Bit32u) op.xmmubyte(0x0) + (Bit32s) op.xmmubyte(0x1) + (Bit32u) op.xmmubyte(0x2) + (Bit32s) op.xmmubyte(0x3); op.xmm32u(1) = (Bit32u) op.xmmubyte(0x4) + (Bit32s) op.xmmubyte(0x5) + (Bit32u) op.xmmubyte(0x6) + (Bit32s) op.xmmubyte(0x7); op.xmm32u(2) = (Bit32u) op.xmmubyte(0x8) + (Bit32s) op.xmmubyte(0x9) + (Bit32u) op.xmmubyte(0xA) + (Bit32s) op.xmmubyte(0xB); op.xmm32u(3) = (Bit32u) op.xmmubyte(0xC) + (Bit32s) op.xmmubyte(0xD) + (Bit32u) op.xmmubyte(0xE) + (Bit32s) op.xmmubyte(0xF); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDUBQ_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm64u(0) = (Bit32u) op.xmmubyte(0x0) + (Bit32u) op.xmmubyte(0x1) + (Bit32u) op.xmmubyte(0x2) + (Bit32u) op.xmmubyte(0x3) + (Bit32u) op.xmmubyte(0x4) + (Bit32u) op.xmmubyte(0x5) + (Bit32u) op.xmmubyte(0x6) + (Bit32u) op.xmmubyte(0x7); op.xmm64u(1) = (Bit32u) op.xmmubyte(0x8) + (Bit32u) op.xmmubyte(0x9) + (Bit32u) op.xmmubyte(0xA) + (Bit32u) op.xmmubyte(0xB) + (Bit32u) op.xmmubyte(0xC) + (Bit32u) op.xmmubyte(0xD) + (Bit32u) op.xmmubyte(0xE) + (Bit32u) op.xmmubyte(0xF); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDUWD_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32u(0) = (Bit32u) op.xmm16u(0) + (Bit32u) op.xmm16u(1); op.xmm32u(1) = (Bit32u) op.xmm16u(2) + (Bit32u) op.xmm16u(3); op.xmm32u(2) = (Bit32u) op.xmm16u(4) + (Bit32u) op.xmm16u(5); op.xmm32u(3) = (Bit32u) op.xmm16u(6) + (Bit32u) op.xmm16u(7); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDUWQ_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm64u(0) = (Bit32u) op.xmm16u(0) + (Bit32u) op.xmm16u(1) + (Bit32u) op.xmm16u(2) + (Bit32u) op.xmm16u(3); op.xmm64u(1) = (Bit32u) op.xmm16u(4) + (Bit32u) op.xmm16u(5) + (Bit32u) op.xmm16u(6) + (Bit32u) op.xmm16u(7); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHADDUDQ_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm64u(0) = (Bit64u) op.xmm32u(0) + (Bit64u) op.xmm32u(1); op.xmm64u(1) = (Bit64u) op.xmm32u(2) + (Bit64u) op.xmm32u(3); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHSUBBW_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm16s(0) = (Bit16s) op.xmmsbyte(0x0) - (Bit16s) op.xmmsbyte(0x1); op.xmm16s(1) = (Bit16s) op.xmmsbyte(0x2) - (Bit16s) op.xmmsbyte(0x3); op.xmm16s(2) = (Bit16s) op.xmmsbyte(0x4) - (Bit16s) op.xmmsbyte(0x5); op.xmm16s(3) = (Bit16s) op.xmmsbyte(0x6) - (Bit16s) op.xmmsbyte(0x7); op.xmm16s(4) = (Bit16s) op.xmmsbyte(0x8) - (Bit16s) op.xmmsbyte(0x9); op.xmm16s(5) = (Bit16s) op.xmmsbyte(0xA) - (Bit16s) op.xmmsbyte(0xB); op.xmm16s(6) = (Bit16s) op.xmmsbyte(0xC) - (Bit16s) op.xmmsbyte(0xD); op.xmm16s(7) = (Bit16s) op.xmmsbyte(0xE) - (Bit16s) op.xmmsbyte(0xF); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHSUBWD_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32s(0) = (Bit32s) op.xmm16s(0) - (Bit32s) op.xmm16s(1); op.xmm32s(1) = (Bit32s) op.xmm16s(2) - (Bit32s) op.xmm16s(3); op.xmm32s(2) = (Bit32s) op.xmm16s(4) - (Bit32s) op.xmm16s(5); op.xmm32s(3) = (Bit32s) op.xmm16s(6) - (Bit32s) op.xmm16s(7); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPHSUBDQ_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm64s(0) = (Bit64s) op.xmm32s(0) - (Bit64s) op.xmm32s(1); op.xmm64s(1) = (Bit64s) op.xmm32s(2) - (Bit64s) op.xmm32s(3); BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), op); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMIL2PS_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()), result; unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) { sse_permil2ps(&result.avx128(n), &op1.avx128(n), &op2.avx128(n), &op3.avx128(n), i->Ib() & 3); } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMIL2PD_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()), result; unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) { sse_permil2pd(&result.avx128(n), &op1.avx128(n), &op2.avx128(n), &op3.avx128(n), i->Ib() & 3); } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/stack.cc0000644000175000017500000002761712020641453014552 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: stack.cc 11117 2012-03-28 21:11:19Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(2) BX_CPU_C::stackPrefetch(bx_address offset, unsigned len) { bx_address laddr; unsigned pageOffset; BX_CPU_THIS_PTR espHostPtr = 0; // initialize with NULL pointer BX_CPU_THIS_PTR espPageWindowSize = 0; len--; #if BX_SUPPORT_X86_64 if (long64_mode()) { laddr = offset; pageOffset = PAGE_OFFSET(offset); // canonical violations will miss the TLB below if (pageOffset + len >= 4096) // don't care for page split accesses return; BX_CPU_THIS_PTR espPageWindowSize = 4096; } else #endif { laddr = get_laddr32(BX_SEG_REG_SS, offset); pageOffset = PAGE_OFFSET(laddr); if (pageOffset + len >= 4096) // don't care for page split accesses return; Bit32u limit = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.limit_scaled; Bit32u pageStart = offset - pageOffset; if (! BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid) { BX_ERROR(("stackPrefetch: SS not valid")); exception(BX_SS_EXCEPTION, 0); } BX_ASSERT(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.p); BX_ASSERT(IS_DATA_SEGMENT_WRITEABLE(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type)); // check that the begining of the page is within stack segment limits // problem can happen with EXPAND DOWN segments if (IS_DATA_SEGMENT_EXPAND_DOWN(BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.type)) { Bit32u upper_limit; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) upper_limit = 0xffffffff; else upper_limit = 0x0000ffff; if (offset <= limit || offset > upper_limit || (upper_limit - offset) < len) { BX_ERROR(("stackPrefetch(%d): access [0x%08x] > SS.limit [0x%08x] ED", len+1, (Bit32u) offset, limit)); exception(BX_SS_EXCEPTION, 0); } // check that the begining of the page is within stack segment limits // handle correctly the wrap corner case for EXPAND DOWN Bit32u pageEnd = pageStart + 0xfff; if (pageStart > limit && pageStart < pageEnd) { BX_CPU_THIS_PTR espPageWindowSize = 4096; if ((upper_limit - offset) < (4096 - pageOffset)) BX_CPU_THIS_PTR espPageWindowSize = (Bit32u)(upper_limit - offset + 1); } } else { if (offset > (limit - len) || len > limit) { BX_ERROR(("stackPrefetch(%d): access [0x%08x] > SS.limit [0x%08x]", len+1, (Bit32u) offset, limit)); exception(BX_SS_EXCEPTION, 0); } if (pageStart <= limit) { BX_CPU_THIS_PTR espPageWindowSize = 4096; if ((limit - offset) < (4096 - pageOffset)) BX_CPU_THIS_PTR espPageWindowSize = (Bit32u)(limit - offset + 1); } } } unsigned tlbIndex = BX_TLB_INDEX_OF(laddr, 0); Bit64u lpf = LPFOf(laddr); bx_TLB_entry *tlbEntry = &BX_CPU_THIS_PTR TLB.entry[tlbIndex]; if (tlbEntry->lpf == lpf) { // See if the TLB entry privilege level allows us write access from this CPL // Assuming that we always can read if write access is OK if (! (tlbEntry->accessBits & (0x2 | USER_PL))) { BX_CPU_THIS_PTR espPageBias = (bx_address) pageOffset - offset; BX_CPU_THIS_PTR pAddrStackPage = tlbEntry->ppf; BX_CPU_THIS_PTR espHostPtr = (Bit8u*) tlbEntry->hostPageAddr; } } if (! BX_CPU_THIS_PTR espHostPtr || BX_CPU_THIS_PTR espPageWindowSize < 7) BX_CPU_THIS_PTR espPageWindowSize = 0; else BX_CPU_THIS_PTR espPageWindowSize -= 7; } void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_byte(bx_address offset, Bit8u data) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 1); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit8u *hostPageAddr = (Bit8u*)(BX_CPU_THIS_PTR espHostPtr + espBiased); bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased; BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 1, CPL, BX_WRITE, (Bit8u*) &data); pageWriteStampTable.decWriteStamp(pAddr, 1); *hostPageAddr = data; } else { write_virtual_byte(BX_SEG_REG_SS, offset, data); } } void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_word(bx_address offset, Bit16u data) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 2); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit16u *hostPageAddr = (Bit16u*)(BX_CPU_THIS_PTR espHostPtr + espBiased); bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased; #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && (pAddr & 1) != 0) { BX_ERROR(("stack_write_word(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } #endif BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 2, CPL, BX_WRITE, (Bit8u*) &data); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostPageAddr, data); } else { write_virtual_word(BX_SEG_REG_SS, offset, data); } } void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_dword(bx_address offset, Bit32u data) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 4); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit32u *hostPageAddr = (Bit32u*)(BX_CPU_THIS_PTR espHostPtr + espBiased); bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased; #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && (pAddr & 3) != 0) { BX_ERROR(("stack_write_dword(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } #endif BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 4, CPL, BX_WRITE, (Bit8u*) &data); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostPageAddr, data); } else { write_virtual_dword(BX_SEG_REG_SS, offset, data); } } void BX_CPP_AttrRegparmN(2) BX_CPU_C::stack_write_qword(bx_address offset, Bit64u data) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 8); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit64u *hostPageAddr = (Bit64u*)(BX_CPU_THIS_PTR espHostPtr + espBiased); bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased; #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check() && (pAddr & 7) != 0) { BX_ERROR(("stack_write_qword(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } #endif BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), pAddr, 8, CPL, BX_WRITE, (Bit8u*) &data); pageWriteStampTable.decWriteStamp(pAddr, 8); WriteHostQWordToLittleEndian(hostPageAddr, data); } else { write_virtual_qword(BX_SEG_REG_SS, offset, data); } } Bit8u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_byte(bx_address offset) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 1); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit8u *hostPageAddr = (Bit8u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data; data = *hostPageAddr; BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 1, CPL, BX_READ, (Bit8u*) &data); return data; } else { return read_virtual_byte(BX_SEG_REG_SS, offset); } } Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_word(bx_address offset) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 2); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit16u *hostPageAddr = (Bit16u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data; #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased; if (pAddr & 1) { BX_ERROR(("stack_read_word(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif ReadHostWordFromLittleEndian(hostPageAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 2, CPL, BX_READ, (Bit8u*) &data); return data; } else { return read_virtual_word(BX_SEG_REG_SS, offset); } } Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_dword(bx_address offset) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 4); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit32u *hostPageAddr = (Bit32u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data; #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased; if (pAddr & 3) { BX_ERROR(("stack_read_dword(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif ReadHostDWordFromLittleEndian(hostPageAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 4, CPL, BX_READ, (Bit8u*) &data); return data; } else { return read_virtual_dword(BX_SEG_REG_SS, offset); } } Bit64u BX_CPP_AttrRegparmN(1) BX_CPU_C::stack_read_qword(bx_address offset) { bx_address espBiased = offset + BX_CPU_THIS_PTR espPageBias; if (espBiased >= BX_CPU_THIS_PTR espPageWindowSize) { stackPrefetch(offset, 8); espBiased = offset + BX_CPU_THIS_PTR espPageBias; } if (BX_CPU_THIS_PTR espHostPtr) { Bit64u *hostPageAddr = (Bit64u*)(BX_CPU_THIS_PTR espHostPtr + espBiased), data; #if BX_CPU_LEVEL >= 4 && BX_SUPPORT_ALIGNMENT_CHECK if (BX_CPU_THIS_PTR alignment_check()) { bx_phy_address pAddr = BX_CPU_THIS_PTR pAddrStackPage + espBiased; if (pAddr & 7) { BX_ERROR(("stack_read_qword(): #AC misaligned access")); exception(BX_AC_EXCEPTION, 0); } } #endif ReadHostQWordFromLittleEndian(hostPageAddr, data); BX_NOTIFY_LIN_MEMORY_ACCESS(get_laddr(BX_SEG_REG_SS, offset), (BX_CPU_THIS_PTR pAddrStackPage + espBiased), 8, CPL, BX_READ, (Bit8u*) &data); return data; } else { return read_virtual_qword(BX_SEG_REG_SS, offset); } } bochs-2.6/cpu/logical16.cc0000644000175000017500000001676112020641453015224 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: logical16.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EwGwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 ^= op2_16; write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GwEwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 ^= op2_16; BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GwEwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = read_virtual_word(i->seg(), eaddr); op1_16 ^= op2_16; BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EwIwM(bxInstruction_c *i) { Bit16u op1_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op1_16 ^= i->Iw(); write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EwIwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); op1_16 ^= i->Iw(); BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EwIwM(bxInstruction_c *i) { Bit16u op1_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op1_16 |= i->Iw(); write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EwIwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); op1_16 |= i->Iw(); BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op1_16 = ~op1_16; write_RMW_virtual_word(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); op1_16 = ~op1_16; BX_WRITE_16BIT_REG(i->dst(), op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EwGwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 |= op2_16; write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GwEwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 |= op2_16; BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GwEwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = read_virtual_word(i->seg(), eaddr); op1_16 |= op2_16; BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EwGwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 &= op2_16; write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GwEwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 &= op2_16; BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GwEwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = read_virtual_word(i->seg(), eaddr); op1_16 &= op2_16; BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EwIwM(bxInstruction_c *i) { Bit16u op1_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_RMW_virtual_word(i->seg(), eaddr); op1_16 &= i->Iw(); write_RMW_virtual_word(op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EwIwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); op1_16 &= i->Iw(); BX_WRITE_16BIT_REG(i->dst(), op1_16); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EwGwR(bxInstruction_c *i) { Bit16u op1_16, op2_16; op1_16 = BX_READ_16BIT_REG(i->dst()); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 &= op2_16; SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EwGwM(bxInstruction_c *i) { Bit16u op1_16, op2_16; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_virtual_word(i->seg(), eaddr); op2_16 = BX_READ_16BIT_REG(i->src()); op1_16 &= op2_16; SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EwIwR(bxInstruction_c *i) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); op1_16 &= i->Iw(); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EwIwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_virtual_word(i->seg(), eaddr); op1_16 &= i->Iw(); SET_FLAGS_OSZAPC_LOGIC_16(op1_16); BX_NEXT_INSTR(i); } bochs-2.6/cpu/icache.h0000644000175000017500000002015112020641453014505 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: icache.h 11389 2012-09-01 19:13:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_ICACHE_H #define BX_ICACHE_H extern void handleSMC(bx_phy_address pAddr, Bit32u mask); class bxPageWriteStampTable { #define PHY_MEM_PAGES (1024*1024) Bit32u *fineGranularityMapping; public: bxPageWriteStampTable() { fineGranularityMapping = new Bit32u[PHY_MEM_PAGES]; resetWriteStamps(); } ~bxPageWriteStampTable() { delete [] fineGranularityMapping; } BX_CPP_INLINE Bit32u hash(bx_phy_address pAddr) const { // can share writeStamps between multiple pages if >32 bit phy address return ((Bit32u) pAddr) >> 12; } BX_CPP_INLINE Bit32u getFineGranularityMapping(bx_phy_address pAddr) const { return fineGranularityMapping[hash(pAddr)]; } BX_CPP_INLINE void markICache(bx_phy_address pAddr, unsigned len) { Bit32u mask = 1 << (PAGE_OFFSET((Bit32u) pAddr) >> 7); mask |= 1 << (PAGE_OFFSET((Bit32u) pAddr + len - 1) >> 7); fineGranularityMapping[hash(pAddr)] |= mask; } BX_CPP_INLINE void markICacheMask(bx_phy_address pAddr, Bit32u mask) { fineGranularityMapping[hash(pAddr)] |= mask; } // whole page is being altered BX_CPP_INLINE void decWriteStamp(bx_phy_address pAddr) { Bit32u index = hash(pAddr); if (fineGranularityMapping[index]) { handleSMC(pAddr, 0xffffffff); // one of the CPUs might be running trace from this page fineGranularityMapping[index] = 0; } } // assumption: write does not split 4K page BX_CPP_INLINE void decWriteStamp(bx_phy_address pAddr, unsigned len) { Bit32u index = hash(pAddr); if (fineGranularityMapping[index]) { Bit32u mask = 1 << (PAGE_OFFSET((Bit32u) pAddr) >> 7); mask |= 1 << (PAGE_OFFSET((Bit32u) pAddr + len - 1) >> 7); if (fineGranularityMapping[index] & mask) { // one of the CPUs might be running trace from this page handleSMC(pAddr, mask); fineGranularityMapping[index] &= ~mask; } } } BX_CPP_INLINE void resetWriteStamps(void); }; BX_CPP_INLINE void bxPageWriteStampTable::resetWriteStamps(void) { for (Bit32u i=0; i>6)) & (BxICacheEntries-1)) ^ fetchModeMask; return ((pAddr) & (BxICacheEntries-1)) ^ fetchModeMask; } BX_CPP_INLINE void alloc_trace(bxICacheEntry_c *e) { // took +1 garbend for instruction chaining speedup (end-of-trace opcode) if ((mpindex + BX_MAX_TRACE_LENGTH + 1) > BxICacheMemPool) { flushICacheEntries(); } e->i = &mpool[mpindex]; e->tlen = 0; } BX_CPP_INLINE void commit_trace(unsigned len) { mpindex += len; } BX_CPP_INLINE void commit_page_split_trace(bx_phy_address paddr, bxICacheEntry_c *entry) { mpindex += entry->tlen; // register page split entry if (pageSplitIndex[nextPageSplitIndex].ppf != BX_ICACHE_INVALID_PHY_ADDRESS) pageSplitIndex[nextPageSplitIndex].e->pAddr = BX_ICACHE_INVALID_PHY_ADDRESS; pageSplitIndex[nextPageSplitIndex].ppf = paddr; pageSplitIndex[nextPageSplitIndex].e = entry; nextPageSplitIndex = (nextPageSplitIndex+1) & (BX_ICACHE_PAGE_SPLIT_ENTRIES-1); } BX_CPP_INLINE bxICacheEntry_c *lookup_victim_cache(bx_phy_address pAddr, Bit32u fetchModeMask) { for (int i=0; i < BX_ICACHE_VICTIM_ENTRIES;i++) { bxVictimCacheEntry *e = &victimCache[i]; if (e->vc_entry.pAddr == pAddr && e->fetchModeMask == fetchModeMask) { return &e->vc_entry; } } return NULL; } BX_CPP_INLINE void victim_entry(bxICacheEntry_c *entry, Bit32u fetchModeMask) { if (entry->pAddr != BX_ICACHE_INVALID_PHY_ADDRESS) { victimCache[nextVictimCacheIndex].fetchModeMask = fetchModeMask; victimCache[nextVictimCacheIndex].vc_entry = *entry; nextVictimCacheIndex = (nextVictimCacheIndex+1) & (BX_ICACHE_VICTIM_ENTRIES-1); } } BX_CPP_INLINE void handleSMC(bx_phy_address pAddr, Bit32u mask); BX_CPP_INLINE void flushICacheEntries(void); BX_CPP_INLINE bxICacheEntry_c* get_entry(bx_phy_address pAddr, unsigned fetchModeMask) { return &(entry[hash(pAddr, fetchModeMask)]); } }; BX_CPP_INLINE void bxICache_c::flushICacheEntries(void) { bxICacheEntry_c* e = entry; unsigned i; for (i=0; ipAddr = BX_ICACHE_INVALID_PHY_ADDRESS; e->traceMask = 0; } nextPageSplitIndex = 0; for (i=0;ivc_entry.pAddr = BX_ICACHE_INVALID_PHY_ADDRESS; } bxICacheEntry_c *e = get_entry(pAddr, 0); // go over 32 "cache lines" of 128 byte each for (unsigned n=0; n < 32; n++) { Bit32u line_mask = (1 << n); if (line_mask > mask) break; for (unsigned index=0; index < 128; index++, e++) { if (pAddr == LPFOf(e->pAddr) && (e->traceMask & mask) != 0) { e->pAddr = BX_ICACHE_INVALID_PHY_ADDRESS; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS for (unsigned instr=0;instr < e->tlen; instr++) genDummyICacheEntry(e->i + instr); #endif } } } } extern void flushICaches(void); #endif bochs-2.6/cpu/flag_ctrl_pro.cc0000644000175000017500000000667012020641453016256 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: flag_ctrl_pro.cc 11107 2012-03-25 19:07:17Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(1) BX_CPU_C::setEFlags(Bit32u val) { // VM flag could not be set from long mode #if BX_SUPPORT_X86_64 if (long_mode()) { if (BX_CPU_THIS_PTR get_VM()) BX_PANIC(("VM is set in long mode !")); val &= ~EFlagsVMMask; } #endif if (val & EFlagsRFMask) invalidate_prefetch_q(); if (val & EFlagsTFMask) { BX_CPU_THIS_PTR async_event = 1; // TF == 1 || RF == 1 } if (val & EFlagsIFMask) { if (! BX_CPU_THIS_PTR get_IF()) BX_CPU_THIS_PTR async_event = 1; // IF bit was set } BX_CPU_THIS_PTR eflags = val; setEFlagsOSZAPC(val); // update lazy flags state #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(/* EFLAGS.AC reloaded */); #endif handleCpuModeChange(); // VM flag might be changed } void BX_CPP_AttrRegparmN(2) BX_CPU_C::writeEFlags(Bit32u flags, Bit32u changeMask) { // Build a mask of the non-reserved bits: // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u supportMask = 0x00037fd5; #if BX_CPU_LEVEL >= 4 supportMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC #endif #if BX_CPU_LEVEL >= 5 supportMask |= (EFlagsVIPMask | EFlagsVIFMask); // VIP/VIF #endif // Screen out changing of any unsupported bits. changeMask &= supportMask; Bit32u newEFlags = (read_eflags() & ~changeMask) | (flags & changeMask); setEFlags(newEFlags); } void BX_CPP_AttrRegparmN(3) BX_CPU_C::write_flags(Bit16u flags, bx_bool change_IOPL, bx_bool change_IF) { // Build a mask of the following bits: // x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = 0x0dd5; #if BX_CPU_LEVEL >= 3 changeMask |= EFlagsNTMask; // NT is modified as requested. if (change_IOPL) changeMask |= EFlagsIOPLMask; // IOPL is modified as requested. #endif if (change_IF) changeMask |= EFlagsIFMask; writeEFlags(Bit32u(flags), changeMask); } // Cause arithmetic flags to be in known state and cached in val32. Bit32u BX_CPU_C::force_flags(void) { Bit32u newflags = getB_CF(); newflags |= getB_PF() << 2; newflags |= getB_AF() << 4; newflags |= getB_ZF() << 6; newflags |= getB_SF() << 7; newflags |= getB_OF() << 11; BX_CPU_THIS_PTR eflags = (BX_CPU_THIS_PTR eflags & ~EFlagsOSZAPCMask) | (newflags & EFlagsOSZAPCMask); return BX_CPU_THIS_PTR eflags; } bochs-2.6/cpu/fpu_emu.cc0000644000175000017500000000344412020641453015075 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fpu_emu.cc 10451 2011-07-06 20:01:18Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR /* 9B */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FWAIT(bxInstruction_c *i) { #if BX_SUPPORT_FPU if (BX_CPU_THIS_PTR cr0.get_TS() && BX_CPU_THIS_PTR cr0.get_MP()) exception(BX_NM_EXCEPTION, 0); BX_CPU_THIS_PTR FPU_check_pending_exceptions(); BX_NEXT_INSTR(i); #endif } /* relevant only when FPU support is disabled */ #if BX_SUPPORT_FPU == 0 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::FPU_ESC(bxInstruction_c *i) { if (BX_CPU_THIS_PTR cr0.get_EM() || BX_CPU_THIS_PTR cr0.get_TS()) exception(BX_NM_EXCEPTION, 0); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/segment_ctrl_pro.cc0000644000175000017500000005377212020641453017014 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: segment_ctrl_pro.cc 11107 2012-03-25 19:07:17Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(2) BX_CPU_C::load_seg_reg(bx_segment_reg_t *seg, Bit16u new_value) { if (protected_mode()) { if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]) { bx_selector_t ss_selector; bx_descriptor_t descriptor; Bit32u dword1, dword2; parse_selector(new_value, &ss_selector); if ((new_value & 0xfffc) == 0) { /* null selector */ #if BX_SUPPORT_X86_64 // allow SS = 0 in 64 bit mode only with cpl != 3 and rpl=cpl if (long64_mode() && CPL != 3 && ss_selector.rpl == CPL) { load_null_selector(seg, new_value); return; } #endif BX_ERROR(("load_seg_reg(SS): loading null selector")); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); /* selector's RPL must = CPL, else #GP(selector) */ if (ss_selector.rpl != CPL) { BX_ERROR(("load_seg_reg(SS): rpl != CPL")); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } parse_descriptor(dword1, dword2, &descriptor); if (descriptor.valid==0) { BX_ERROR(("load_seg_reg(SS): valid bit cleared")); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } /* AR byte must indicate a writable data segment else #GP(selector) */ if (descriptor.segment==0 || IS_CODE_SEGMENT(descriptor.type) || IS_DATA_SEGMENT_WRITEABLE(descriptor.type) == 0) { BX_ERROR(("load_seg_reg(SS): not writable data segment")); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } /* DPL in the AR byte must equal CPL else #GP(selector) */ if (descriptor.dpl != CPL) { BX_ERROR(("load_seg_reg(SS): dpl != CPL")); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } /* segment must be marked PRESENT else #SS(selector) */ if (! IS_PRESENT(descriptor)) { BX_ERROR(("load_seg_reg(SS): not present")); exception(BX_SS_EXCEPTION, new_value & 0xfffc); } touch_segment(&ss_selector, &descriptor); /* load SS with selector, load SS cache with descriptor */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector = ss_selector; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache = descriptor; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1; invalidate_stack_cache(); return; } else if ((seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS]) || (seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]) || (seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS]) || (seg==&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS]) ) { bx_descriptor_t descriptor; bx_selector_t selector; Bit32u dword1, dword2; if ((new_value & 0xfffc) == 0) { /* null selector */ load_null_selector(seg, new_value); return; } parse_selector(new_value, &selector); fetch_raw_descriptor(&selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &descriptor); if (descriptor.valid==0) { BX_ERROR(("load_seg_reg(%s, 0x%04x): invalid segment", strseg(seg), new_value)); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } /* AR byte must indicate data or readable code segment else #GP(selector) */ if (descriptor.segment==0 || (IS_CODE_SEGMENT(descriptor.type) && IS_CODE_SEGMENT_READABLE(descriptor.type) == 0)) { BX_ERROR(("load_seg_reg(%s, 0x%04x): not data or readable code", strseg(seg), new_value)); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } /* If data or non-conforming code, then both the RPL and the CPL * must be less than or equal to DPL in AR byte else #GP(selector) */ if (IS_DATA_SEGMENT(descriptor.type) || IS_CODE_SEGMENT_NON_CONFORMING(descriptor.type)) { if ((selector.rpl > descriptor.dpl) || (CPL > descriptor.dpl)) { BX_ERROR(("load_seg_reg(%s, 0x%04x): RPL & CPL must be <= DPL", strseg(seg), new_value)); exception(BX_GP_EXCEPTION, new_value & 0xfffc); } } /* segment must be marked PRESENT else #NP(selector) */ if (! IS_PRESENT(descriptor)) { BX_ERROR(("load_seg_reg(%s, 0x%04x): segment not present", strseg(seg), new_value)); exception(BX_NP_EXCEPTION, new_value & 0xfffc); } touch_segment(&selector, &descriptor); /* load segment register with selector */ /* load segment register-cache with descriptor */ seg->selector = selector; seg->cache = descriptor; seg->cache.valid = 1; return; } else { BX_PANIC(("load_seg_reg(): invalid segment register passed!")); return; } } /* real or v8086 mode */ /* www.x86.org: According to Intel, each time any segment register is loaded in real mode, the base address is calculated as 16 times the segment value, while the access rights and size limit attributes are given fixed, "real-mode compatible" values. This is not true. In fact, only the CS descriptor caches for the 286, 386, and 486 get loaded with fixed values each time the segment register is loaded. Loading CS, or any other segment register in real mode, on later Intel processors doesn't change the access rights or the segment size limit attributes stored in the descriptor cache registers. For these segments, the access rights and segment size limit attributes from any previous setting are honored. */ seg->selector.value = new_value; seg->selector.rpl = real_mode() ? 0 : 3; seg->cache.valid = 1; seg->cache.u.segment.base = new_value << 4; seg->cache.segment = 1; /* regular segment */ seg->cache.p = 1; /* present */ /* Do not modify segment limit and AR bytes when in real mode */ /* Support for big real mode */ if (!real_mode()) { seg->cache.type = BX_DATA_READ_WRITE_ACCESSED; seg->cache.dpl = 3; /* we are in v8086 mode */ seg->cache.u.segment.limit_scaled = 0xffff; seg->cache.u.segment.g = 0; /* byte granular */ seg->cache.u.segment.d_b = 0; /* default 16bit size */ #if BX_SUPPORT_X86_64 seg->cache.u.segment.l = 0; /* default 16bit size */ #endif seg->cache.u.segment.avl = 0; } if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS]) { invalidate_prefetch_q(); updateFetchModeMask(/* CS reloaded */); #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(/* CPL change */); #endif } if (seg == &BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS]) invalidate_stack_cache(); } void BX_CPP_AttrRegparmN(2) BX_CPU_C::load_null_selector(bx_segment_reg_t *seg, unsigned value) { BX_ASSERT((value & 0xfffc) == 0); seg->selector.index = 0; seg->selector.ti = 0; seg->selector.rpl = BX_SELECTOR_RPL(value); seg->selector.value = value; seg->cache.valid = 0; /* invalidate null selector */ seg->cache.p = 0; seg->cache.dpl = 0; seg->cache.segment = 1; /* data/code segment */ seg->cache.type = 0; seg->cache.u.segment.base = 0; seg->cache.u.segment.limit_scaled = 0; seg->cache.u.segment.g = 0; seg->cache.u.segment.d_b = 0; seg->cache.u.segment.avl = 0; #if BX_SUPPORT_X86_64 seg->cache.u.segment.l = 0; #endif invalidate_stack_cache(); } BX_CPP_INLINE void BX_CPU_C::validate_seg_reg(unsigned seg) { /* FOR (seg = ES, DS, FS, GS) DO IF ((seg.attr.dpl < CPL) && ((seg.attr.type = 'data') || (seg.attr.type = 'non-conforming-code'))) { seg = NULL // can't use lower dpl data segment at higher cpl } END */ bx_segment_reg_t *segment = &BX_CPU_THIS_PTR sregs[seg]; if (segment->cache.dpl < CPL) { // invalidate if data or non-conforming code segment if (segment->cache.valid==0 || segment->cache.segment==0 || IS_DATA_SEGMENT(segment->cache.type) || IS_CODE_SEGMENT_NON_CONFORMING(segment->cache.type)) { segment->selector.value = 0; segment->cache.valid = 0; } } } void BX_CPU_C::validate_seg_regs(void) { validate_seg_reg(BX_SEG_REG_ES); validate_seg_reg(BX_SEG_REG_DS); validate_seg_reg(BX_SEG_REG_FS); validate_seg_reg(BX_SEG_REG_GS); } void parse_selector(Bit16u raw_selector, bx_selector_t *selector) { selector->value = raw_selector; selector->index = raw_selector >> 3; selector->ti = (raw_selector >> 2) & 0x01; selector->rpl = raw_selector & 0x03; } Bit8u get_ar_byte(const bx_descriptor_t *d) { return (d->type) | (d->segment << 4) | (d->dpl << 5) | (d->p << 7); } void set_ar_byte(bx_descriptor_t *d, Bit8u ar_byte) { d->p = (ar_byte >> 7) & 0x01; d->dpl = (ar_byte >> 5) & 0x03; d->segment = (ar_byte >> 4) & 0x01; d->type = (ar_byte & 0x0f); } Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::get_descriptor_l(const bx_descriptor_t *d) { Bit32u limit = d->u.segment.limit_scaled; if (d->u.segment.g) limit >>= 12; Bit32u val = ((d->u.segment.base & 0xffff) << 16) | (limit & 0xffff); if (d->segment || !d->valid) { return(val); } else { switch (d->type) { case BX_SYS_SEGMENT_LDT: case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_BUSY_286_TSS: case BX_SYS_SEGMENT_AVAIL_386_TSS: case BX_SYS_SEGMENT_BUSY_386_TSS: return(val); default: BX_ERROR(("#get_descriptor_l(): type %d not finished", d->type)); return(0); } } } Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::get_descriptor_h(const bx_descriptor_t *d) { Bit32u val; Bit32u limit = d->u.segment.limit_scaled; if (d->u.segment.g) limit >>= 12; if (d->segment || !d->valid) { val = (d->u.segment.base & 0xff000000) | ((d->u.segment.base >> 16) & 0x000000ff) | (d->type << 8) | (d->segment << 12) | (d->dpl << 13) | (d->p << 15) | (limit & 0xf0000) | (d->u.segment.avl << 20) | #if BX_SUPPORT_X86_64 (d->u.segment.l << 21) | #endif (d->u.segment.d_b << 22) | (d->u.segment.g << 23); return(val); } else { switch (d->type) { case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_BUSY_286_TSS: case BX_SYS_SEGMENT_LDT: case BX_SYS_SEGMENT_AVAIL_386_TSS: case BX_SYS_SEGMENT_BUSY_386_TSS: val = ((d->u.segment.base >> 16) & 0xff) | (d->type << 8) | (d->dpl << 13) | (d->p << 15) | (limit & 0xf0000) | (d->u.segment.avl << 20) | (d->u.segment.d_b << 22) | (d->u.segment.g << 23) | (d->u.segment.base & 0xff000000); return(val); default: BX_ERROR(("#get_descriptor_h(): type %d not finished", d->type)); return(0); } } } bx_bool BX_CPU_C::set_segment_ar_data(bx_segment_reg_t *seg, bx_bool valid, Bit16u raw_selector, bx_address base, Bit32u limit_scaled, Bit16u ar_data) { parse_selector(raw_selector, &seg->selector); bx_descriptor_t *d = &seg->cache; d->p = (ar_data >> 7) & 0x1; d->dpl = (ar_data >> 5) & 0x3; d->segment = (ar_data >> 4) & 0x1; d->type = (ar_data & 0x0f); d->valid = valid; if (d->segment || !valid) { /* data/code segment descriptors */ d->u.segment.g = (ar_data >> 15) & 0x1; d->u.segment.d_b = (ar_data >> 14) & 0x1; #if BX_SUPPORT_X86_64 d->u.segment.l = (ar_data >> 13) & 0x1; #endif d->u.segment.avl = (ar_data >> 12) & 0x1; d->u.segment.base = base; d->u.segment.limit_scaled = limit_scaled; } else { switch(d->type) { case BX_SYS_SEGMENT_LDT: case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_BUSY_286_TSS: case BX_SYS_SEGMENT_AVAIL_386_TSS: case BX_SYS_SEGMENT_BUSY_386_TSS: d->u.segment.avl = (ar_data >> 12) & 0x1; d->u.segment.d_b = (ar_data >> 14) & 0x1; d->u.segment.g = (ar_data >> 15) & 0x1; d->u.segment.base = base; d->u.segment.limit_scaled = limit_scaled; break; default: BX_ERROR(("set_segment_ar_data(): case %u unsupported, valid=%d", (unsigned) d->type, d->valid)); } } return d->valid; } void parse_descriptor(Bit32u dword1, Bit32u dword2, bx_descriptor_t *temp) { Bit8u AR_byte; Bit32u limit; AR_byte = dword2 >> 8; temp->p = (AR_byte >> 7) & 0x1; temp->dpl = (AR_byte >> 5) & 0x3; temp->segment = (AR_byte >> 4) & 0x1; temp->type = (AR_byte & 0xf); temp->valid = 0; /* start out invalid */ if (temp->segment) { /* data/code segment descriptors */ limit = (dword1 & 0xffff) | (dword2 & 0x000F0000); temp->u.segment.base = (dword1 >> 16) | ((dword2 & 0xFF) << 16); temp->u.segment.g = (dword2 & 0x00800000) > 0; temp->u.segment.d_b = (dword2 & 0x00400000) > 0; #if BX_SUPPORT_X86_64 temp->u.segment.l = (dword2 & 0x00200000) > 0; #endif temp->u.segment.avl = (dword2 & 0x00100000) > 0; temp->u.segment.base |= (dword2 & 0xFF000000); if (temp->u.segment.g) temp->u.segment.limit_scaled = (limit << 12) | 0xfff; else temp->u.segment.limit_scaled = limit; temp->valid = 1; } else { // system & gate segment descriptors switch (temp->type) { case BX_286_CALL_GATE: case BX_286_INTERRUPT_GATE: case BX_286_TRAP_GATE: // param count only used for call gate temp->u.gate.param_count = dword2 & 0x1f; temp->u.gate.dest_selector = dword1 >> 16; temp->u.gate.dest_offset = dword1 & 0xffff; temp->valid = 1; break; case BX_386_CALL_GATE: case BX_386_INTERRUPT_GATE: case BX_386_TRAP_GATE: // param count only used for call gate temp->u.gate.param_count = dword2 & 0x1f; temp->u.gate.dest_selector = dword1 >> 16; temp->u.gate.dest_offset = (dword2 & 0xffff0000) | (dword1 & 0x0000ffff); temp->valid = 1; break; case BX_TASK_GATE: temp->u.taskgate.tss_selector = dword1 >> 16; temp->valid = 1; break; case BX_SYS_SEGMENT_LDT: case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_BUSY_286_TSS: case BX_SYS_SEGMENT_AVAIL_386_TSS: case BX_SYS_SEGMENT_BUSY_386_TSS: limit = (dword1 & 0xffff) | (dword2 & 0x000F0000); temp->u.segment.base = (dword1 >> 16) | ((dword2 & 0xff) << 16) | (dword2 & 0xff000000); temp->u.segment.g = (dword2 & 0x00800000) > 0; temp->u.segment.d_b = (dword2 & 0x00400000) > 0; temp->u.segment.avl = (dword2 & 0x00100000) > 0; if (temp->u.segment.g) temp->u.segment.limit_scaled = (limit << 12) | 0xfff; else temp->u.segment.limit_scaled = limit; temp->valid = 1; break; default: // reserved temp->valid = 0; break; } } } void BX_CPP_AttrRegparmN(2) BX_CPU_C::touch_segment(bx_selector_t *selector, bx_descriptor_t *descriptor) { if (! IS_SEGMENT_ACCESSED(descriptor->type)) { Bit8u AR_byte = get_ar_byte(descriptor); AR_byte |= 1; descriptor->type |= 1; if (selector->ti == 0) { /* GDT */ access_write_linear(BX_CPU_THIS_PTR gdtr.base + selector->index*8 + 5, 1, 0, &AR_byte); } else { /* LDT */ access_write_linear(BX_CPU_THIS_PTR ldtr.cache.u.segment.base + selector->index*8 + 5, 1, 0, &AR_byte); } } } void BX_CPP_AttrRegparmN(3) BX_CPU_C::load_ss(bx_selector_t *selector, bx_descriptor_t *descriptor, Bit8u cpl) { // Add cpl to the selector value. selector->value = (BX_SELECTOR_RPL_MASK & selector->value) | cpl; if ((selector->value & BX_SELECTOR_RPL_MASK) != 0) touch_segment(selector, descriptor); BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector = *selector; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache = *descriptor; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.rpl = cpl; BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.valid = 1; invalidate_stack_cache(); } void BX_CPU_C::fetch_raw_descriptor(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2, unsigned exception_no) { Bit32u index = selector->index; bx_address offset; Bit64u raw_descriptor; if (selector->ti == 0) { /* GDT */ if ((index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit) { BX_ERROR(("fetch_raw_descriptor: GDT: index (%x) %x > limit (%x)", index*8 + 7, index, BX_CPU_THIS_PTR gdtr.limit)); exception(exception_no, selector->value & 0xfffc); } offset = BX_CPU_THIS_PTR gdtr.base + index*8; } else { /* LDT */ if (BX_CPU_THIS_PTR ldtr.cache.valid==0) { BX_ERROR(("fetch_raw_descriptor: LDTR.valid=0")); exception(exception_no, selector->value & 0xfffc); } if ((index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled) { BX_ERROR(("fetch_raw_descriptor: LDT: index (%x) %x > limit (%x)", index*8 + 7, index, BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled)); exception(exception_no, selector->value & 0xfffc); } offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8; } raw_descriptor = system_read_qword(offset); *dword1 = GET32L(raw_descriptor); *dword2 = GET32H(raw_descriptor); } bx_bool BX_CPP_AttrRegparmN(3) BX_CPU_C::fetch_raw_descriptor2(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2) { Bit32u index = selector->index; bx_address offset; Bit64u raw_descriptor; if (selector->ti == 0) { /* GDT */ if ((index*8 + 7) > BX_CPU_THIS_PTR gdtr.limit) return 0; offset = BX_CPU_THIS_PTR gdtr.base + index*8; } else { /* LDT */ if (BX_CPU_THIS_PTR ldtr.cache.valid==0) { BX_ERROR(("fetch_raw_descriptor2: LDTR.valid=0")); return 0; } if ((index*8 + 7) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled) return 0; offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8; } raw_descriptor = system_read_qword(offset); *dword1 = GET32L(raw_descriptor); *dword2 = GET32H(raw_descriptor); return 1; } #if BX_SUPPORT_X86_64 void BX_CPU_C::fetch_raw_descriptor_64(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2, Bit32u *dword3, unsigned exception_no) { Bit32u index = selector->index; bx_address offset; Bit64u raw_descriptor1, raw_descriptor2; if (selector->ti == 0) { /* GDT */ if ((index*8 + 15) > BX_CPU_THIS_PTR gdtr.limit) { BX_ERROR(("fetch_raw_descriptor64: GDT: index (%x) %x > limit (%x)", index*8 + 15, index, BX_CPU_THIS_PTR gdtr.limit)); exception(exception_no, selector->value & 0xfffc); } offset = BX_CPU_THIS_PTR gdtr.base + index*8; } else { /* LDT */ if (BX_CPU_THIS_PTR ldtr.cache.valid==0) { BX_ERROR(("fetch_raw_descriptor64: LDTR.valid=0")); exception(exception_no, selector->value & 0xfffc); } if ((index*8 + 15) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled) { BX_ERROR(("fetch_raw_descriptor64: LDT: index (%x) %x > limit (%x)", index*8 + 15, index, BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled)); exception(exception_no, selector->value & 0xfffc); } offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8; } raw_descriptor1 = system_read_qword(offset); raw_descriptor2 = system_read_qword(offset + 8); if (raw_descriptor2 & BX_CONST64(0x00001F0000000000)) { BX_ERROR(("fetch_raw_descriptor64: extended attributes DWORD4 TYPE != 0")); exception(BX_GP_EXCEPTION, selector->value & 0xfffc); } *dword1 = GET32L(raw_descriptor1); *dword2 = GET32H(raw_descriptor1); *dword3 = GET32L(raw_descriptor2); } bx_bool BX_CPU_C::fetch_raw_descriptor2_64(const bx_selector_t *selector, Bit32u *dword1, Bit32u *dword2, Bit32u *dword3) { Bit32u index = selector->index; bx_address offset; Bit64u raw_descriptor1, raw_descriptor2; if (selector->ti == 0) { /* GDT */ if ((index*8 + 15) > BX_CPU_THIS_PTR gdtr.limit) { BX_ERROR(("fetch_raw_descriptor2_64: GDT: index (%x) %x > limit (%x)", index*8 + 15, index, BX_CPU_THIS_PTR gdtr.limit)); return 0; } offset = BX_CPU_THIS_PTR gdtr.base + index*8; } else { /* LDT */ if (BX_CPU_THIS_PTR ldtr.cache.valid==0) { BX_ERROR(("fetch_raw_descriptor2_64: LDTR.valid=0")); return 0; } if ((index*8 + 15) > BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled) { BX_ERROR(("fetch_raw_descriptor2_64: LDT: index (%x) %x > limit (%x)", index*8 + 15, index, BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled)); return 0; } offset = BX_CPU_THIS_PTR ldtr.cache.u.segment.base + index*8; } raw_descriptor1 = system_read_qword(offset); raw_descriptor2 = system_read_qword(offset + 8); if (raw_descriptor2 & BX_CONST64(0x00001F0000000000)) { BX_ERROR(("fetch_raw_descriptor2_64: extended attributes DWORD4 TYPE != 0")); return 0; } *dword1 = GET32L(raw_descriptor1); *dword2 = GET32H(raw_descriptor1); *dword3 = GET32L(raw_descriptor2); return 1; } #endif bochs-2.6/cpu/io.cc0000644000175000017500000005346212020641453014051 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: io.cc 11117 2012-03-28 21:11:19Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #include "iodev/iodev.h" // // Repeat Speedups methods // #if BX_SUPPORT_REPEAT_SPEEDUPS Bit32u BX_CPU_C::FastRepINSW(bxInstruction_c *i, bx_address dstOff, Bit16u port, Bit32u wordCount) { Bit32u wordsFitDst; signed int pointerDelta; Bit8u *hostAddrDst; unsigned count; BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); bx_segment_reg_t *dstSegPtr = &BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES]; if (!(dstSegPtr->cache.valid & SegAccessWOK)) return 0; if ((dstOff | 0xfff) > dstSegPtr->cache.u.segment.limit_scaled) return 0; bx_address laddrDst = get_laddr32(BX_SEG_REG_ES, dstOff); // check that the address is word aligned if (laddrDst & 1) return 0; hostAddrDst = v2h_write_byte(laddrDst, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrDst) return 0; // See how many words can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward // 1st word must cannot cross page boundary because it is word aligned wordsFitDst = (2 + (PAGE_OFFSET(laddrDst))) >> 1; pointerDelta = -2; } else { // Counting upward wordsFitDst = (0x1000 - PAGE_OFFSET(laddrDst)) >> 1; pointerDelta = 2; } // Restrict word count to the number that will fit in this page. if (wordCount > wordsFitDst) wordCount = wordsFitDst; // If after all the restrictions, there is anything left to do... if (wordCount) { for (count=0; countcache.valid & SegAccessROK)) return 0; if ((srcOff | 0xfff) > srcSegPtr->cache.u.segment.limit_scaled) return 0; bx_address laddrSrc = get_laddr32(srcSeg, srcOff); // check that the address is word aligned if (laddrSrc & 1) return 0; hostAddrSrc = v2h_read_byte(laddrSrc, BX_CPU_THIS_PTR user_pl); // Check that native host access was not vetoed for that page if (!hostAddrSrc) return 0; // See how many words can fit in the rest of this page. if (BX_CPU_THIS_PTR get_DF()) { // Counting downward // 1st word must cannot cross page boundary because it is word aligned wordsFitSrc = (2 + (PAGE_OFFSET(laddrSrc))) >> 1; pointerDelta = (unsigned) -2; } else { // Counting upward wordsFitSrc = (0x1000 - PAGE_OFFSET(laddrSrc)) >> 1; pointerDelta = 2; } // Restrict word count to the number that will fit in this page. if (wordCount > wordsFitSrc) wordCount = wordsFitSrc; // If after all the restrictions, there is anything left to do... if (wordCount) { for (count=0; countas64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB64_YbDX); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB32_YbDX); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSB16_YbDX); } BX_NEXT_INSTR(i); } // 16-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB16_YbDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit8u value8 = read_RMW_virtual_byte_32(BX_SEG_REG_ES, DI); value8 = BX_INP(DX, 1); write_RMW_virtual_byte(value8); if (BX_CPU_THIS_PTR get_DF()) DI--; else DI++; } // 32-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB32_YbDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit8u value8 = read_RMW_virtual_byte(BX_SEG_REG_ES, EDI); value8 = BX_INP(DX, 1); /* no seg override possible */ write_RMW_virtual_byte(value8); if (BX_CPU_THIS_PTR get_DF()) { RDI = EDI - 1; } else { RDI = EDI + 1; } } #if BX_SUPPORT_X86_64 // 64-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSB64_YbDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit8u value8 = read_RMW_virtual_byte_64(BX_SEG_REG_ES, RDI); value8 = BX_INP(DX, 1); write_RMW_virtual_byte(value8); if (BX_CPU_THIS_PTR get_DF()) RDI--; else RDI++; } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSW_YwDX(bxInstruction_c *i) { if (! allow_io(i, DX, 2)) { BX_DEBUG(("INSW_YwDX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW64_YwDX); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW32_YwDX); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSW16_YwDX); } BX_NEXT_INSTR(i); } // 16-bit operand size, 16-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW16_YwDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit16u value16 = read_RMW_virtual_word_32(BX_SEG_REG_ES, DI); value16 = BX_INP(DX, 2); write_RMW_virtual_word(value16); if (BX_CPU_THIS_PTR get_DF()) DI -= 2; else DI += 2; } // 16-bit operand size, 32-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW32_YwDX(bxInstruction_c *i) { Bit16u value16=0; Bit32u edi = EDI; unsigned incr = 2; #if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0) /* If conditions are right, we can transfer IO to physical memory * in a batch, rather than one instruction at a time. */ if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) { Bit32u wordCount = ECX; BX_ASSERT(wordCount > 0); wordCount = FastRepINSW(i, edi, DX, wordCount); if (wordCount) { // Decrement the ticks count by the number of iterations, minus // one, since the main cpu loop will decrement one. Also, // the count is predecremented before examined, so defintely // don't roll it under zero. BX_TICKN(wordCount-1); RCX = ECX - (wordCount-1); incr = wordCount << 1; // count * 2. } else { // trigger any segment or page faults before reading from IO port value16 = read_RMW_virtual_word(BX_SEG_REG_ES, edi); value16 = BX_INP(DX, 2); write_RMW_virtual_word(value16); } } else #endif { // trigger any segment or page faults before reading from IO port value16 = read_RMW_virtual_word_32(BX_SEG_REG_ES, edi); value16 = BX_INP(DX, 2); write_RMW_virtual_word(value16); } if (BX_CPU_THIS_PTR get_DF()) RDI = EDI - incr; else RDI = EDI + incr; } #if BX_SUPPORT_X86_64 // 16-bit operand size, 64-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSW64_YwDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit16u value16 = read_RMW_virtual_word_64(BX_SEG_REG_ES, RDI); value16 = BX_INP(DX, 2); write_RMW_virtual_word(value16); if (BX_CPU_THIS_PTR get_DF()) RDI -= 2; else RDI += 2; } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_INSD_YdDX(bxInstruction_c *i) { if (! allow_io(i, DX, 4)) { BX_DEBUG(("INSD_YdDX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD64_YdDX); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD32_YdDX); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RDI); // always clear upper part of RDI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::INSD16_YdDX); } BX_NEXT_INSTR(i); } // 32-bit operand size, 16-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD16_YdDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit32u value32 = read_RMW_virtual_dword_32(BX_SEG_REG_ES, DI); value32 = BX_INP(DX, 4); write_RMW_virtual_dword(value32); if (BX_CPU_THIS_PTR get_DF()) DI -= 4; else DI += 4; } // 32-bit operand size, 32-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD32_YdDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit32u value32 = read_RMW_virtual_dword(BX_SEG_REG_ES, EDI); value32 = BX_INP(DX, 4); write_RMW_virtual_dword(value32); if (BX_CPU_THIS_PTR get_DF()) RDI = EDI - 4; else RDI = EDI + 4; } #if BX_SUPPORT_X86_64 // 32-bit operand size, 64-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::INSD64_YdDX(bxInstruction_c *i) { // trigger any segment or page faults before reading from IO port Bit32u value32 = read_RMW_virtual_dword_64(BX_SEG_REG_ES, RDI); value32 = BX_INP(DX, 4); write_RMW_virtual_dword(value32); if (BX_CPU_THIS_PTR get_DF()) RDI -= 4; else RDI += 4; } #endif // // REP OUTS methods // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSB_DXXb(bxInstruction_c *i) { if (! allow_io(i, DX, 1)) { BX_DEBUG(("OUTSB_DXXb: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB64_DXXb); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB32_DXXb); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSB16_DXXb); } BX_NEXT_INSTR(i); } // 16-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB16_DXXb(bxInstruction_c *i) { Bit8u value8 = read_virtual_byte_32(i->seg(), SI); BX_OUTP(DX, value8, 1); if (BX_CPU_THIS_PTR get_DF()) SI--; else SI++; } // 32-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB32_DXXb(bxInstruction_c *i) { Bit8u value8 = read_virtual_byte(i->seg(), ESI); BX_OUTP(DX, value8, 1); if (BX_CPU_THIS_PTR get_DF()) RSI = ESI - 1; else RSI = ESI + 1; } #if BX_SUPPORT_X86_64 // 64-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSB64_DXXb(bxInstruction_c *i) { Bit8u value8 = read_virtual_byte_64(i->seg(), RSI); BX_OUTP(DX, value8, 1); if (BX_CPU_THIS_PTR get_DF()) RSI--; else RSI++; } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSW_DXXw(bxInstruction_c *i) { if (! allow_io(i, DX, 2)) { BX_DEBUG(("OUTSW_DXXw: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW64_DXXw); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW32_DXXw); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSW16_DXXw); } BX_NEXT_INSTR(i); } // 16-bit operand size, 16-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW16_DXXw(bxInstruction_c *i) { Bit16u value16 = read_virtual_word_32(i->seg(), SI); BX_OUTP(DX, value16, 2); if (BX_CPU_THIS_PTR get_DF()) SI -= 2; else SI += 2; } // 16-bit operand size, 32-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW32_DXXw(bxInstruction_c *i) { Bit16u value16; Bit32u esi = ESI; unsigned incr = 2; #if (BX_SUPPORT_REPEAT_SPEEDUPS) && (BX_DEBUGGER == 0) /* If conditions are right, we can transfer IO to physical memory * in a batch, rather than one instruction at a time. */ if (i->repUsedL() && !BX_CPU_THIS_PTR async_event) { Bit32u wordCount = ECX; wordCount = FastRepOUTSW(i, i->seg(), esi, DX, wordCount); if (wordCount) { // Decrement eCX. Note, the main loop will decrement 1 also, so // decrement by one less than expected, like the case above. BX_TICKN(wordCount-1); // Main cpu loop also decrements one more. RCX = ECX - (wordCount-1); incr = wordCount << 1; // count * 2. } else { value16 = read_virtual_word(i->seg(), esi); BX_OUTP(DX, value16, 2); } } else #endif { value16 = read_virtual_word(i->seg(), esi); BX_OUTP(DX, value16, 2); } if (BX_CPU_THIS_PTR get_DF()) RSI = ESI - incr; else RSI = ESI + incr; } #if BX_SUPPORT_X86_64 // 16-bit operand size, 64-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSW64_DXXw(bxInstruction_c *i) { Bit16u value16 = read_virtual_word_64(i->seg(), RSI); BX_OUTP(DX, value16, 2); if (BX_CPU_THIS_PTR get_DF()) RSI -= 2; else RSI += 2; } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::REP_OUTSD_DXXd(bxInstruction_c *i) { if (! allow_io(i, DX, 4)) { BX_DEBUG(("OUTSD_DXXd: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_X86_64 if (i->as64L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD64_DXXd); } else #endif if (i->as32L()) { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD32_DXXd); BX_CLEAR_64BIT_HIGH(BX_64BIT_REG_RSI); // always clear upper part of RSI } else { BX_CPU_THIS_PTR repeat(i, &BX_CPU_C::OUTSD16_DXXd); } BX_NEXT_INSTR(i); } // 32-bit operand size, 16-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD16_DXXd(bxInstruction_c *i) { Bit32u value32 = read_virtual_dword_32(i->seg(), SI); BX_OUTP(DX, value32, 4); if (BX_CPU_THIS_PTR get_DF()) SI -= 4; else SI += 4; } // 32-bit operand size, 32-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD32_DXXd(bxInstruction_c *i) { Bit32u value32 = read_virtual_dword(i->seg(), ESI); BX_OUTP(DX, value32, 4); if (BX_CPU_THIS_PTR get_DF()) RSI = ESI - 4; else RSI = ESI + 4; } #if BX_SUPPORT_X86_64 // 32-bit operand size, 64-bit address size void BX_CPP_AttrRegparmN(1) BX_CPU_C::OUTSD64_DXXd(bxInstruction_c *i) { Bit32u value32 = read_virtual_dword_64(i->seg(), RSI); BX_OUTP(DX, value32, 4); if (BX_CPU_THIS_PTR get_DF()) RSI -= 4; else RSI += 4; } #endif // // non repeatable IN/OUT methods // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALIb(bxInstruction_c *i) { unsigned port = i->Ib(); if (! allow_io(i, port, 1)) { BX_DEBUG(("IN_ALIb: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } AL = BX_INP(port, 1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXIb(bxInstruction_c *i) { unsigned port = i->Ib(); if (! allow_io(i, port, 2)) { BX_DEBUG(("IN_AXIb: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } AX = BX_INP(port, 2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXIb(bxInstruction_c *i) { unsigned port = i->Ib(); if (! allow_io(i, port, 4)) { BX_DEBUG(("IN_EAXIb: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } RAX = BX_INP(port, 4); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAL(bxInstruction_c *i) { unsigned port = i->Ib(); if (! allow_io(i, port, 1)) { BX_DEBUG(("OUT_IbAL: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } BX_OUTP(port, AL, 1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbAX(bxInstruction_c *i) { unsigned port = i->Ib(); if (! allow_io(i, port, 2)) { BX_DEBUG(("OUT_IbAX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } BX_OUTP(port, AX, 2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_IbEAX(bxInstruction_c *i) { unsigned port = i->Ib(); if (! allow_io(i, port, 4)) { BX_DEBUG(("OUT_IbEAX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } BX_OUTP(port, EAX, 4); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_ALDX(bxInstruction_c *i) { unsigned port = DX; if (! allow_io(i, port, 1)) { BX_DEBUG(("IN_ALDX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } AL = BX_INP(port, 1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_AXDX(bxInstruction_c *i) { unsigned port = DX; if (! allow_io(i, port, 2)) { BX_DEBUG(("IN_AXDX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } AX = BX_INP(port, 2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IN_EAXDX(bxInstruction_c *i) { unsigned port = DX; if (! allow_io(i, port, 4)) { BX_DEBUG(("IN_EAXDX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } RAX = BX_INP(port, 4); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAL(bxInstruction_c *i) { unsigned port = DX; if (! allow_io(i, port, 1)) { BX_DEBUG(("OUT_DXAL: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } BX_OUTP(port, AL, 1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXAX(bxInstruction_c *i) { unsigned port = DX; if (! allow_io(i, port, 2)) { BX_DEBUG(("OUT_DXAX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } BX_OUTP(port, AX, 2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OUT_DXEAX(bxInstruction_c *i) { unsigned port = DX; if (! allow_io(i, port, 4)) { BX_DEBUG(("OUT_DXEAX: I/O access not allowed !")); exception(BX_GP_EXCEPTION, 0); } BX_OUTP(port, EAX, 4); BX_NEXT_INSTR(i); } bx_bool BX_CPP_AttrRegparmN(3) BX_CPU_C::allow_io(bxInstruction_c *i, Bit16u port, unsigned len) { /* If CPL <= IOPL, then all IO portesses are accessible. * Otherwise, must check the IO permission map on >286. * On the 286, there is no IO permissions map */ if (BX_CPU_THIS_PTR cr0.get_PE() && (BX_CPU_THIS_PTR get_VM() || (CPL > BX_CPU_THIS_PTR get_IOPL()))) { if (BX_CPU_THIS_PTR tr.cache.valid==0 || (BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_AVAIL_386_TSS && BX_CPU_THIS_PTR tr.cache.type != BX_SYS_SEGMENT_BUSY_386_TSS)) { BX_ERROR(("allow_io(): TR doesn't point to a valid 32bit TSS, TR.TYPE=%u", BX_CPU_THIS_PTR tr.cache.type)); return(0); } if (BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled < 103) { BX_ERROR(("allow_io(): TR.limit < 103")); return(0); } Bit32u io_base = system_read_word(BX_CPU_THIS_PTR tr.cache.u.segment.base + 102); if ((io_base + port/8) >= BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled) { BX_DEBUG(("allow_io(): IO port %x (len %d) outside TSS IO permission map (base=%x, limit=%x) #GP(0)", port, len, io_base, BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled)); return(0); } Bit16u permission16 = system_read_word(BX_CPU_THIS_PTR tr.cache.u.segment.base + io_base + port/8); unsigned bit_index = port & 0x7; unsigned mask = (1 << len) - 1; if ((permission16 >> bit_index) & mask) return(0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_IO)) SvmInterceptIO(i, port, len); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_IO(i, port, len); #endif #if BX_X86_DEBUGGER && BX_CPU_LEVEL >= 5 iobreakpoint_match(port, len); #endif return(1); } bochs-2.6/cpu/sse_rcp.cc0000644000175000017500000011703012020641453015070 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: sse_rcp.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2003-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 6 #include "fpu/softfloat-specialize.h" BX_CPP_INLINE float32 convert_to_QNaN(float32 op) { return op | 0x00400000; } static Bit16u rcp_table[2048] = { 0x7ff0, 0x7fd0, 0x7fb0, 0x7f90, 0x7f70, 0x7f50, 0x7f30, 0x7f10, 0x7ef0, 0x7ed0, 0x7eb0, 0x7e90, 0x7e70, 0x7e50, 0x7e30, 0x7e10, 0x7df8, 0x7dd8, 0x7db8, 0x7d98, 0x7d78, 0x7d58, 0x7d38, 0x7d18, 0x7cf8, 0x7cd8, 0x7cb8, 0x7c98, 0x7c80, 0x7c60, 0x7c40, 0x7c20, 0x7c00, 0x7be0, 0x7bc0, 0x7ba0, 0x7b88, 0x7b68, 0x7b48, 0x7b28, 0x7b08, 0x7ae8, 0x7ac8, 0x7ab0, 0x7a90, 0x7a70, 0x7a50, 0x7a30, 0x7a10, 0x79f8, 0x79d8, 0x79b8, 0x7998, 0x7978, 0x7960, 0x7940, 0x7920, 0x7900, 0x78e0, 0x78c8, 0x78a8, 0x7888, 0x7868, 0x7850, 0x7830, 0x7810, 0x77f0, 0x77d8, 0x77b8, 0x7798, 0x7778, 0x7760, 0x7740, 0x7720, 0x7700, 0x76e8, 0x76c8, 0x76a8, 0x7690, 0x7670, 0x7650, 0x7630, 0x7618, 0x75f8, 0x75d8, 0x75c0, 0x75a0, 0x7580, 0x7568, 0x7548, 0x7528, 0x7510, 0x74f0, 0x74d0, 0x74b8, 0x7498, 0x7478, 0x7460, 0x7440, 0x7420, 0x7408, 0x73e8, 0x73d0, 0x73b0, 0x7390, 0x7378, 0x7358, 0x7338, 0x7320, 0x7300, 0x72e8, 0x72c8, 0x72a8, 0x7290, 0x7270, 0x7258, 0x7238, 0x7220, 0x7200, 0x71e0, 0x71c8, 0x71a8, 0x7190, 0x7170, 0x7158, 0x7138, 0x7118, 0x7100, 0x70e0, 0x70c8, 0x70a8, 0x7090, 0x7070, 0x7058, 0x7038, 0x7020, 0x7000, 0x6fe8, 0x6fc8, 0x6fb0, 0x6f90, 0x6f78, 0x6f58, 0x6f40, 0x6f20, 0x6f08, 0x6ee8, 0x6ed0, 0x6eb0, 0x6e98, 0x6e78, 0x6e60, 0x6e40, 0x6e28, 0x6e08, 0x6df0, 0x6dd0, 0x6db8, 0x6da0, 0x6d80, 0x6d68, 0x6d48, 0x6d30, 0x6d10, 0x6cf8, 0x6cd8, 0x6cc0, 0x6ca8, 0x6c88, 0x6c70, 0x6c50, 0x6c38, 0x6c20, 0x6c00, 0x6be8, 0x6bc8, 0x6bb0, 0x6b98, 0x6b78, 0x6b60, 0x6b40, 0x6b28, 0x6b10, 0x6af0, 0x6ad8, 0x6ac0, 0x6aa0, 0x6a88, 0x6a70, 0x6a50, 0x6a38, 0x6a20, 0x6a00, 0x69e8, 0x69c8, 0x69b0, 0x6998, 0x6978, 0x6960, 0x6948, 0x6930, 0x6910, 0x68f8, 0x68e0, 0x68c0, 0x68a8, 0x6890, 0x6870, 0x6858, 0x6840, 0x6820, 0x6808, 0x67f0, 0x67d8, 0x67b8, 0x67a0, 0x6788, 0x6770, 0x6750, 0x6738, 0x6720, 0x6700, 0x66e8, 0x66d0, 0x66b8, 0x6698, 0x6680, 0x6668, 0x6650, 0x6638, 0x6618, 0x6600, 0x65e8, 0x65d0, 0x65b0, 0x6598, 0x6580, 0x6568, 0x6550, 0x6530, 0x6518, 0x6500, 0x64e8, 0x64c8, 0x64b0, 0x6498, 0x6480, 0x6468, 0x6450, 0x6430, 0x6418, 0x6400, 0x63e8, 0x63d0, 0x63b8, 0x6398, 0x6380, 0x6368, 0x6350, 0x6338, 0x6320, 0x6300, 0x62e8, 0x62d0, 0x62b8, 0x62a0, 0x6288, 0x6270, 0x6250, 0x6238, 0x6220, 0x6208, 0x61f0, 0x61d8, 0x61c0, 0x61a8, 0x6190, 0x6170, 0x6158, 0x6140, 0x6128, 0x6110, 0x60f8, 0x60e0, 0x60c8, 0x60b0, 0x6098, 0x6080, 0x6060, 0x6048, 0x6030, 0x6018, 0x6000, 0x5fe8, 0x5fd0, 0x5fb8, 0x5fa0, 0x5f88, 0x5f70, 0x5f58, 0x5f40, 0x5f28, 0x5f10, 0x5ef8, 0x5ee0, 0x5ec8, 0x5eb0, 0x5e98, 0x5e80, 0x5e68, 0x5e50, 0x5e30, 0x5e18, 0x5e00, 0x5de8, 0x5dd0, 0x5db8, 0x5da0, 0x5d88, 0x5d70, 0x5d58, 0x5d40, 0x5d30, 0x5d18, 0x5d00, 0x5ce8, 0x5cd0, 0x5cb8, 0x5ca0, 0x5c88, 0x5c70, 0x5c58, 0x5c40, 0x5c28, 0x5c10, 0x5bf8, 0x5be0, 0x5bc8, 0x5bb0, 0x5b98, 0x5b80, 0x5b68, 0x5b50, 0x5b38, 0x5b20, 0x5b08, 0x5af8, 0x5ae0, 0x5ac8, 0x5ab0, 0x5a98, 0x5a80, 0x5a68, 0x5a50, 0x5a38, 0x5a20, 0x5a08, 0x59f8, 0x59e0, 0x59c8, 0x59b0, 0x5998, 0x5980, 0x5968, 0x5950, 0x5938, 0x5928, 0x5910, 0x58f8, 0x58e0, 0x58c8, 0x58b0, 0x5898, 0x5880, 0x5870, 0x5858, 0x5840, 0x5828, 0x5810, 0x57f8, 0x57e0, 0x57d0, 0x57b8, 0x57a0, 0x5788, 0x5770, 0x5758, 0x5748, 0x5730, 0x5718, 0x5700, 0x56e8, 0x56d0, 0x56c0, 0x56a8, 0x5690, 0x5678, 0x5660, 0x5650, 0x5638, 0x5620, 0x5608, 0x55f0, 0x55e0, 0x55c8, 0x55b0, 0x5598, 0x5588, 0x5570, 0x5558, 0x5540, 0x5528, 0x5518, 0x5500, 0x54e8, 0x54d0, 0x54c0, 0x54a8, 0x5490, 0x5478, 0x5468, 0x5450, 0x5438, 0x5420, 0x5410, 0x53f8, 0x53e0, 0x53c8, 0x53b8, 0x53a0, 0x5388, 0x5370, 0x5360, 0x5348, 0x5330, 0x5318, 0x5308, 0x52f0, 0x52d8, 0x52c8, 0x52b0, 0x5298, 0x5280, 0x5270, 0x5258, 0x5240, 0x5230, 0x5218, 0x5200, 0x51f0, 0x51d8, 0x51c0, 0x51b0, 0x5198, 0x5180, 0x5170, 0x5158, 0x5140, 0x5128, 0x5118, 0x5100, 0x50e8, 0x50d8, 0x50c0, 0x50a8, 0x5098, 0x5080, 0x5070, 0x5058, 0x5040, 0x5030, 0x5018, 0x5000, 0x4ff0, 0x4fd8, 0x4fc0, 0x4fb0, 0x4f98, 0x4f80, 0x4f70, 0x4f58, 0x4f48, 0x4f30, 0x4f18, 0x4f08, 0x4ef0, 0x4ee0, 0x4ec8, 0x4eb0, 0x4ea0, 0x4e88, 0x4e78, 0x4e60, 0x4e48, 0x4e38, 0x4e20, 0x4e10, 0x4df8, 0x4de0, 0x4dd0, 0x4db8, 0x4da8, 0x4d90, 0x4d78, 0x4d68, 0x4d50, 0x4d40, 0x4d28, 0x4d18, 0x4d00, 0x4ce8, 0x4cd8, 0x4cc0, 0x4cb0, 0x4c98, 0x4c88, 0x4c70, 0x4c60, 0x4c48, 0x4c30, 0x4c20, 0x4c08, 0x4bf8, 0x4be0, 0x4bd0, 0x4bb8, 0x4ba8, 0x4b90, 0x4b80, 0x4b68, 0x4b58, 0x4b40, 0x4b30, 0x4b18, 0x4b08, 0x4af0, 0x4ad8, 0x4ac8, 0x4ab0, 0x4aa0, 0x4a88, 0x4a78, 0x4a60, 0x4a50, 0x4a38, 0x4a28, 0x4a10, 0x4a00, 0x49e8, 0x49d8, 0x49c8, 0x49b0, 0x49a0, 0x4988, 0x4978, 0x4960, 0x4950, 0x4938, 0x4928, 0x4910, 0x4900, 0x48e8, 0x48d8, 0x48c0, 0x48b0, 0x4898, 0x4888, 0x4878, 0x4860, 0x4850, 0x4838, 0x4828, 0x4810, 0x4800, 0x47e8, 0x47d8, 0x47c8, 0x47b0, 0x47a0, 0x4788, 0x4778, 0x4760, 0x4750, 0x4740, 0x4728, 0x4718, 0x4700, 0x46f0, 0x46d8, 0x46c8, 0x46b8, 0x46a0, 0x4690, 0x4678, 0x4668, 0x4658, 0x4640, 0x4630, 0x4618, 0x4608, 0x45f8, 0x45e0, 0x45d0, 0x45b8, 0x45a8, 0x4598, 0x4580, 0x4570, 0x4560, 0x4548, 0x4538, 0x4520, 0x4510, 0x4500, 0x44e8, 0x44d8, 0x44c8, 0x44b0, 0x44a0, 0x4488, 0x4478, 0x4468, 0x4450, 0x4440, 0x4430, 0x4418, 0x4408, 0x43f8, 0x43e0, 0x43d0, 0x43c0, 0x43a8, 0x4398, 0x4388, 0x4370, 0x4360, 0x4350, 0x4338, 0x4328, 0x4318, 0x4300, 0x42f0, 0x42e0, 0x42c8, 0x42b8, 0x42a8, 0x4290, 0x4280, 0x4270, 0x4260, 0x4248, 0x4238, 0x4228, 0x4210, 0x4200, 0x41f0, 0x41d8, 0x41c8, 0x41b8, 0x41a8, 0x4190, 0x4180, 0x4170, 0x4158, 0x4148, 0x4138, 0x4128, 0x4110, 0x4100, 0x40f0, 0x40d8, 0x40c8, 0x40b8, 0x40a8, 0x4090, 0x4080, 0x4070, 0x4060, 0x4048, 0x4038, 0x4028, 0x4018, 0x4000, 0x3ff0, 0x3fe0, 0x3fd0, 0x3fb8, 0x3fa8, 0x3f98, 0x3f88, 0x3f70, 0x3f60, 0x3f50, 0x3f40, 0x3f28, 0x3f18, 0x3f08, 0x3ef8, 0x3ee8, 0x3ed0, 0x3ec0, 0x3eb0, 0x3ea0, 0x3e88, 0x3e78, 0x3e68, 0x3e58, 0x3e48, 0x3e30, 0x3e20, 0x3e10, 0x3e00, 0x3df0, 0x3dd8, 0x3dc8, 0x3db8, 0x3da8, 0x3d98, 0x3d80, 0x3d70, 0x3d60, 0x3d50, 0x3d40, 0x3d28, 0x3d18, 0x3d08, 0x3cf8, 0x3ce8, 0x3cd8, 0x3cc0, 0x3cb0, 0x3ca0, 0x3c90, 0x3c80, 0x3c70, 0x3c58, 0x3c48, 0x3c38, 0x3c28, 0x3c18, 0x3c08, 0x3bf0, 0x3be0, 0x3bd0, 0x3bc0, 0x3bb0, 0x3ba0, 0x3b90, 0x3b78, 0x3b68, 0x3b58, 0x3b48, 0x3b38, 0x3b28, 0x3b18, 0x3b00, 0x3af0, 0x3ae0, 0x3ad0, 0x3ac0, 0x3ab0, 0x3aa0, 0x3a88, 0x3a78, 0x3a68, 0x3a58, 0x3a48, 0x3a38, 0x3a28, 0x3a18, 0x3a08, 0x39f0, 0x39e0, 0x39d0, 0x39c0, 0x39b0, 0x39a0, 0x3990, 0x3980, 0x3970, 0x3958, 0x3948, 0x3938, 0x3928, 0x3918, 0x3908, 0x38f8, 0x38e8, 0x38d8, 0x38c8, 0x38b8, 0x38a8, 0x3890, 0x3880, 0x3870, 0x3860, 0x3850, 0x3840, 0x3830, 0x3820, 0x3810, 0x3800, 0x37f0, 0x37e0, 0x37d0, 0x37c0, 0x37a8, 0x3798, 0x3788, 0x3778, 0x3768, 0x3758, 0x3748, 0x3738, 0x3728, 0x3718, 0x3708, 0x36f8, 0x36e8, 0x36d8, 0x36c8, 0x36b8, 0x36a8, 0x3698, 0x3688, 0x3678, 0x3668, 0x3658, 0x3648, 0x3630, 0x3620, 0x3610, 0x3600, 0x35f0, 0x35e0, 0x35d0, 0x35c0, 0x35b0, 0x35a0, 0x3590, 0x3580, 0x3570, 0x3560, 0x3550, 0x3540, 0x3530, 0x3520, 0x3510, 0x3500, 0x34f0, 0x34e0, 0x34d0, 0x34c0, 0x34b0, 0x34a0, 0x3490, 0x3480, 0x3470, 0x3460, 0x3450, 0x3440, 0x3430, 0x3420, 0x3410, 0x3400, 0x33f0, 0x33e0, 0x33d0, 0x33c8, 0x33b8, 0x33a8, 0x3398, 0x3388, 0x3378, 0x3368, 0x3358, 0x3348, 0x3338, 0x3328, 0x3318, 0x3308, 0x32f8, 0x32e8, 0x32d8, 0x32c8, 0x32b8, 0x32a8, 0x3298, 0x3288, 0x3278, 0x3268, 0x3260, 0x3250, 0x3240, 0x3230, 0x3220, 0x3210, 0x3200, 0x31f0, 0x31e0, 0x31d0, 0x31c0, 0x31b0, 0x31a0, 0x3190, 0x3180, 0x3178, 0x3168, 0x3158, 0x3148, 0x3138, 0x3128, 0x3118, 0x3108, 0x30f8, 0x30e8, 0x30d8, 0x30c8, 0x30c0, 0x30b0, 0x30a0, 0x3090, 0x3080, 0x3070, 0x3060, 0x3050, 0x3040, 0x3030, 0x3028, 0x3018, 0x3008, 0x2ff8, 0x2fe8, 0x2fd8, 0x2fc8, 0x2fb8, 0x2fa8, 0x2fa0, 0x2f90, 0x2f80, 0x2f70, 0x2f60, 0x2f50, 0x2f40, 0x2f30, 0x2f28, 0x2f18, 0x2f08, 0x2ef8, 0x2ee8, 0x2ed8, 0x2ec8, 0x2eb8, 0x2eb0, 0x2ea0, 0x2e90, 0x2e80, 0x2e70, 0x2e60, 0x2e50, 0x2e48, 0x2e38, 0x2e28, 0x2e18, 0x2e08, 0x2df8, 0x2df0, 0x2de0, 0x2dd0, 0x2dc0, 0x2db0, 0x2da0, 0x2d90, 0x2d88, 0x2d78, 0x2d68, 0x2d58, 0x2d48, 0x2d38, 0x2d30, 0x2d20, 0x2d10, 0x2d00, 0x2cf0, 0x2ce0, 0x2cd8, 0x2cc8, 0x2cb8, 0x2ca8, 0x2c98, 0x2c90, 0x2c80, 0x2c70, 0x2c60, 0x2c50, 0x2c40, 0x2c38, 0x2c28, 0x2c18, 0x2c08, 0x2bf8, 0x2bf0, 0x2be0, 0x2bd0, 0x2bc0, 0x2bb0, 0x2ba8, 0x2b98, 0x2b88, 0x2b78, 0x2b68, 0x2b60, 0x2b50, 0x2b40, 0x2b30, 0x2b20, 0x2b18, 0x2b08, 0x2af8, 0x2ae8, 0x2ae0, 0x2ad0, 0x2ac0, 0x2ab0, 0x2aa0, 0x2a98, 0x2a88, 0x2a78, 0x2a68, 0x2a60, 0x2a50, 0x2a40, 0x2a30, 0x2a20, 0x2a18, 0x2a08, 0x29f8, 0x29e8, 0x29e0, 0x29d0, 0x29c0, 0x29b0, 0x29a8, 0x2998, 0x2988, 0x2978, 0x2970, 0x2960, 0x2950, 0x2940, 0x2938, 0x2928, 0x2918, 0x2908, 0x2900, 0x28f0, 0x28e0, 0x28d0, 0x28c8, 0x28b8, 0x28a8, 0x2898, 0x2890, 0x2880, 0x2870, 0x2868, 0x2858, 0x2848, 0x2838, 0x2830, 0x2820, 0x2810, 0x2800, 0x27f8, 0x27e8, 0x27d8, 0x27d0, 0x27c0, 0x27b0, 0x27a0, 0x2798, 0x2788, 0x2778, 0x2770, 0x2760, 0x2750, 0x2740, 0x2738, 0x2728, 0x2718, 0x2710, 0x2700, 0x26f0, 0x26e8, 0x26d8, 0x26c8, 0x26b8, 0x26b0, 0x26a0, 0x2690, 0x2688, 0x2678, 0x2668, 0x2660, 0x2650, 0x2640, 0x2638, 0x2628, 0x2618, 0x2608, 0x2600, 0x25f0, 0x25e0, 0x25d8, 0x25c8, 0x25b8, 0x25b0, 0x25a0, 0x2590, 0x2588, 0x2578, 0x2568, 0x2560, 0x2550, 0x2540, 0x2538, 0x2528, 0x2518, 0x2510, 0x2500, 0x24f0, 0x24e8, 0x24d8, 0x24c8, 0x24c0, 0x24b0, 0x24a0, 0x2498, 0x2488, 0x2478, 0x2470, 0x2460, 0x2450, 0x2448, 0x2438, 0x2430, 0x2420, 0x2410, 0x2408, 0x23f8, 0x23e8, 0x23e0, 0x23d0, 0x23c0, 0x23b8, 0x23a8, 0x23a0, 0x2390, 0x2380, 0x2378, 0x2368, 0x2358, 0x2350, 0x2340, 0x2330, 0x2328, 0x2318, 0x2310, 0x2300, 0x22f0, 0x22e8, 0x22d8, 0x22d0, 0x22c0, 0x22b0, 0x22a8, 0x2298, 0x2288, 0x2280, 0x2270, 0x2268, 0x2258, 0x2248, 0x2240, 0x2230, 0x2228, 0x2218, 0x2208, 0x2200, 0x21f0, 0x21e8, 0x21d8, 0x21c8, 0x21c0, 0x21b0, 0x21a8, 0x2198, 0x2188, 0x2180, 0x2170, 0x2168, 0x2158, 0x2148, 0x2140, 0x2130, 0x2128, 0x2118, 0x2108, 0x2100, 0x20f0, 0x20e8, 0x20d8, 0x20d0, 0x20c0, 0x20b0, 0x20a8, 0x2098, 0x2090, 0x2080, 0x2078, 0x2068, 0x2058, 0x2050, 0x2040, 0x2038, 0x2028, 0x2020, 0x2010, 0x2000, 0x1ff8, 0x1fe8, 0x1fe0, 0x1fd0, 0x1fc8, 0x1fb8, 0x1fb0, 0x1fa0, 0x1f90, 0x1f88, 0x1f78, 0x1f70, 0x1f60, 0x1f58, 0x1f48, 0x1f40, 0x1f30, 0x1f20, 0x1f18, 0x1f08, 0x1f00, 0x1ef0, 0x1ee8, 0x1ed8, 0x1ed0, 0x1ec0, 0x1eb8, 0x1ea8, 0x1ea0, 0x1e90, 0x1e80, 0x1e78, 0x1e68, 0x1e60, 0x1e50, 0x1e48, 0x1e38, 0x1e30, 0x1e20, 0x1e18, 0x1e08, 0x1e00, 0x1df0, 0x1de8, 0x1dd8, 0x1dd0, 0x1dc0, 0x1db8, 0x1da8, 0x1da0, 0x1d90, 0x1d80, 0x1d78, 0x1d68, 0x1d60, 0x1d50, 0x1d48, 0x1d38, 0x1d30, 0x1d20, 0x1d18, 0x1d08, 0x1d00, 0x1cf0, 0x1ce8, 0x1cd8, 0x1cd0, 0x1cc0, 0x1cb8, 0x1ca8, 0x1ca0, 0x1c90, 0x1c88, 0x1c78, 0x1c70, 0x1c60, 0x1c58, 0x1c48, 0x1c40, 0x1c30, 0x1c28, 0x1c18, 0x1c10, 0x1c00, 0x1bf8, 0x1bf0, 0x1be0, 0x1bd8, 0x1bc8, 0x1bc0, 0x1bb0, 0x1ba8, 0x1b98, 0x1b90, 0x1b80, 0x1b78, 0x1b68, 0x1b60, 0x1b50, 0x1b48, 0x1b38, 0x1b30, 0x1b20, 0x1b18, 0x1b08, 0x1b00, 0x1af8, 0x1ae8, 0x1ae0, 0x1ad0, 0x1ac8, 0x1ab8, 0x1ab0, 0x1aa0, 0x1a98, 0x1a88, 0x1a80, 0x1a70, 0x1a68, 0x1a60, 0x1a50, 0x1a48, 0x1a38, 0x1a30, 0x1a20, 0x1a18, 0x1a08, 0x1a00, 0x19f8, 0x19e8, 0x19e0, 0x19d0, 0x19c8, 0x19b8, 0x19b0, 0x19a0, 0x1998, 0x1990, 0x1980, 0x1978, 0x1968, 0x1960, 0x1950, 0x1948, 0x1938, 0x1930, 0x1928, 0x1918, 0x1910, 0x1900, 0x18f8, 0x18e8, 0x18e0, 0x18d8, 0x18c8, 0x18c0, 0x18b0, 0x18a8, 0x1898, 0x1890, 0x1888, 0x1878, 0x1870, 0x1860, 0x1858, 0x1850, 0x1840, 0x1838, 0x1828, 0x1820, 0x1810, 0x1808, 0x1800, 0x17f0, 0x17e8, 0x17d8, 0x17d0, 0x17c8, 0x17b8, 0x17b0, 0x17a0, 0x1798, 0x1790, 0x1780, 0x1778, 0x1768, 0x1760, 0x1758, 0x1748, 0x1740, 0x1730, 0x1728, 0x1720, 0x1710, 0x1708, 0x16f8, 0x16f0, 0x16e8, 0x16d8, 0x16d0, 0x16c8, 0x16b8, 0x16b0, 0x16a0, 0x1698, 0x1690, 0x1680, 0x1678, 0x1668, 0x1660, 0x1658, 0x1648, 0x1640, 0x1638, 0x1628, 0x1620, 0x1610, 0x1608, 0x1600, 0x15f0, 0x15e8, 0x15e0, 0x15d0, 0x15c8, 0x15b8, 0x15b0, 0x15a8, 0x1598, 0x1590, 0x1588, 0x1578, 0x1570, 0x1568, 0x1558, 0x1550, 0x1540, 0x1538, 0x1530, 0x1520, 0x1518, 0x1510, 0x1500, 0x14f8, 0x14f0, 0x14e0, 0x14d8, 0x14d0, 0x14c0, 0x14b8, 0x14a8, 0x14a0, 0x1498, 0x1488, 0x1480, 0x1478, 0x1468, 0x1460, 0x1458, 0x1448, 0x1440, 0x1438, 0x1428, 0x1420, 0x1418, 0x1408, 0x1400, 0x13f8, 0x13e8, 0x13e0, 0x13d8, 0x13c8, 0x13c0, 0x13b8, 0x13a8, 0x13a0, 0x1398, 0x1388, 0x1380, 0x1378, 0x1368, 0x1360, 0x1358, 0x1348, 0x1340, 0x1338, 0x1328, 0x1320, 0x1318, 0x1308, 0x1300, 0x12f8, 0x12e8, 0x12e0, 0x12d8, 0x12d0, 0x12c0, 0x12b8, 0x12b0, 0x12a0, 0x1298, 0x1290, 0x1280, 0x1278, 0x1270, 0x1260, 0x1258, 0x1250, 0x1240, 0x1238, 0x1230, 0x1228, 0x1218, 0x1210, 0x1208, 0x11f8, 0x11f0, 0x11e8, 0x11d8, 0x11d0, 0x11c8, 0x11c0, 0x11b0, 0x11a8, 0x11a0, 0x1190, 0x1188, 0x1180, 0x1178, 0x1168, 0x1160, 0x1158, 0x1148, 0x1140, 0x1138, 0x1128, 0x1120, 0x1118, 0x1110, 0x1100, 0x10f8, 0x10f0, 0x10e8, 0x10d8, 0x10d0, 0x10c8, 0x10b8, 0x10b0, 0x10a8, 0x10a0, 0x1090, 0x1088, 0x1080, 0x1070, 0x1068, 0x1060, 0x1058, 0x1048, 0x1040, 0x1038, 0x1030, 0x1020, 0x1018, 0x1010, 0x1000, 0x0ff8, 0x0ff0, 0x0fe8, 0x0fd8, 0x0fd0, 0x0fc8, 0x0fc0, 0x0fb0, 0x0fa8, 0x0fa0, 0x0f98, 0x0f88, 0x0f80, 0x0f78, 0x0f70, 0x0f60, 0x0f58, 0x0f50, 0x0f48, 0x0f38, 0x0f30, 0x0f28, 0x0f20, 0x0f10, 0x0f08, 0x0f00, 0x0ef8, 0x0ee8, 0x0ee0, 0x0ed8, 0x0ed0, 0x0ec0, 0x0eb8, 0x0eb0, 0x0ea8, 0x0e98, 0x0e90, 0x0e88, 0x0e80, 0x0e70, 0x0e68, 0x0e60, 0x0e58, 0x0e48, 0x0e40, 0x0e38, 0x0e30, 0x0e28, 0x0e18, 0x0e10, 0x0e08, 0x0e00, 0x0df0, 0x0de8, 0x0de0, 0x0dd8, 0x0dc8, 0x0dc0, 0x0db8, 0x0db0, 0x0da8, 0x0d98, 0x0d90, 0x0d88, 0x0d80, 0x0d70, 0x0d68, 0x0d60, 0x0d58, 0x0d50, 0x0d40, 0x0d38, 0x0d30, 0x0d28, 0x0d18, 0x0d10, 0x0d08, 0x0d00, 0x0cf8, 0x0ce8, 0x0ce0, 0x0cd8, 0x0cd0, 0x0cc8, 0x0cb8, 0x0cb0, 0x0ca8, 0x0ca0, 0x0c98, 0x0c88, 0x0c80, 0x0c78, 0x0c70, 0x0c60, 0x0c58, 0x0c50, 0x0c48, 0x0c40, 0x0c30, 0x0c28, 0x0c20, 0x0c18, 0x0c10, 0x0c00, 0x0bf8, 0x0bf0, 0x0be8, 0x0be0, 0x0bd8, 0x0bc8, 0x0bc0, 0x0bb8, 0x0bb0, 0x0ba8, 0x0b98, 0x0b90, 0x0b88, 0x0b80, 0x0b78, 0x0b68, 0x0b60, 0x0b58, 0x0b50, 0x0b48, 0x0b40, 0x0b30, 0x0b28, 0x0b20, 0x0b18, 0x0b10, 0x0b00, 0x0af8, 0x0af0, 0x0ae8, 0x0ae0, 0x0ad8, 0x0ac8, 0x0ac0, 0x0ab8, 0x0ab0, 0x0aa8, 0x0a98, 0x0a90, 0x0a88, 0x0a80, 0x0a78, 0x0a70, 0x0a60, 0x0a58, 0x0a50, 0x0a48, 0x0a40, 0x0a38, 0x0a28, 0x0a20, 0x0a18, 0x0a10, 0x0a08, 0x0a00, 0x09f0, 0x09e8, 0x09e0, 0x09d8, 0x09d0, 0x09c8, 0x09c0, 0x09b0, 0x09a8, 0x09a0, 0x0998, 0x0990, 0x0988, 0x0978, 0x0970, 0x0968, 0x0960, 0x0958, 0x0950, 0x0948, 0x0938, 0x0930, 0x0928, 0x0920, 0x0918, 0x0910, 0x0900, 0x08f8, 0x08f0, 0x08e8, 0x08e0, 0x08d8, 0x08d0, 0x08c0, 0x08b8, 0x08b0, 0x08a8, 0x08a0, 0x0898, 0x0890, 0x0880, 0x0878, 0x0870, 0x0868, 0x0860, 0x0858, 0x0850, 0x0848, 0x0838, 0x0830, 0x0828, 0x0820, 0x0818, 0x0810, 0x0808, 0x0800, 0x07f0, 0x07e8, 0x07e0, 0x07d8, 0x07d0, 0x07c8, 0x07c0, 0x07b0, 0x07a8, 0x07a0, 0x0798, 0x0790, 0x0788, 0x0780, 0x0778, 0x0770, 0x0760, 0x0758, 0x0750, 0x0748, 0x0740, 0x0738, 0x0730, 0x0728, 0x0718, 0x0710, 0x0708, 0x0700, 0x06f8, 0x06f0, 0x06e8, 0x06e0, 0x06d8, 0x06c8, 0x06c0, 0x06b8, 0x06b0, 0x06a8, 0x06a0, 0x0698, 0x0690, 0x0688, 0x0680, 0x0670, 0x0668, 0x0660, 0x0658, 0x0650, 0x0648, 0x0640, 0x0638, 0x0630, 0x0620, 0x0618, 0x0610, 0x0608, 0x0600, 0x05f8, 0x05f0, 0x05e8, 0x05e0, 0x05d8, 0x05d0, 0x05c0, 0x05b8, 0x05b0, 0x05a8, 0x05a0, 0x0598, 0x0590, 0x0588, 0x0580, 0x0578, 0x0570, 0x0560, 0x0558, 0x0550, 0x0548, 0x0540, 0x0538, 0x0530, 0x0528, 0x0520, 0x0518, 0x0510, 0x0508, 0x04f8, 0x04f0, 0x04e8, 0x04e0, 0x04d8, 0x04d0, 0x04c8, 0x04c0, 0x04b8, 0x04b0, 0x04a8, 0x04a0, 0x0498, 0x0488, 0x0480, 0x0478, 0x0470, 0x0468, 0x0460, 0x0458, 0x0450, 0x0448, 0x0440, 0x0438, 0x0430, 0x0428, 0x0420, 0x0418, 0x0408, 0x0400, 0x03f8, 0x03f0, 0x03e8, 0x03e0, 0x03d8, 0x03d0, 0x03c8, 0x03c0, 0x03b8, 0x03b0, 0x03a8, 0x03a0, 0x0398, 0x0390, 0x0388, 0x0378, 0x0370, 0x0368, 0x0360, 0x0358, 0x0350, 0x0348, 0x0340, 0x0338, 0x0330, 0x0328, 0x0320, 0x0318, 0x0310, 0x0308, 0x0300, 0x02f8, 0x02f0, 0x02e8, 0x02d8, 0x02d0, 0x02c8, 0x02c0, 0x02b8, 0x02b0, 0x02a8, 0x02a0, 0x0298, 0x0290, 0x0288, 0x0280, 0x0278, 0x0270, 0x0268, 0x0260, 0x0258, 0x0250, 0x0248, 0x0240, 0x0238, 0x0230, 0x0228, 0x0220, 0x0218, 0x0210, 0x0200, 0x01f8, 0x01f0, 0x01e8, 0x01e0, 0x01d8, 0x01d0, 0x01c8, 0x01c0, 0x01b8, 0x01b0, 0x01a8, 0x01a0, 0x0198, 0x0190, 0x0188, 0x0180, 0x0178, 0x0170, 0x0168, 0x0160, 0x0158, 0x0150, 0x0148, 0x0140, 0x0138, 0x0130, 0x0128, 0x0120, 0x0118, 0x0110, 0x0108, 0x0100, 0x00f8, 0x00f0, 0x00e8, 0x00e0, 0x00d8, 0x00d0, 0x00c8, 0x00c0, 0x00b8, 0x00b0, 0x00a8, 0x00a0, 0x0098, 0x0090, 0x0088, 0x0080, 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008 }; // approximate reciprocal of scalar single precision FP float32 approximate_rcp(float32 op) { float_class_t op_class = float32_class(op); int sign = float32_sign(op); switch(op_class) { case float_zero: case float_denormal: return packFloat32(sign, 0xFF, 0); case float_negative_inf: case float_positive_inf: return packFloat32(sign, 0x00, 0); case float_NaN: return convert_to_QNaN(op); case float_normalized: break; } Bit32u fraction = float32_fraction(op); Bit16s exp = float32_exp(op); /* * Calculate (1/1.yyyyyyyyyyy1), the result is always rounded to the * 12th bit after the decimal point by round-to-nearest, regardless * of the current rounding mode. * * Using precalculated 2048-entry table. */ exp = 253 - exp; /* check for underflow */ if (exp <= 0) return packFloat32(sign, 0x00, 0); return packFloat32(sign, exp, (Bit32u)(rcp_table[fraction >> 12]) << 8); } #endif /* * Opcode: 0F 53 * Approximate reciprocals of packed single precision FP values from XMM2/MEM. * Possible floating point exceptions: - */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCPPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32u(0) = approximate_rcp(op.xmm32u(0)); op.xmm32u(1) = approximate_rcp(op.xmm32u(1)); op.xmm32u(2) = approximate_rcp(op.xmm32u(2)); op.xmm32u(3) = approximate_rcp(op.xmm32u(3)); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: F3 0F 53 * Approximate reciprocal of scalar single precision FP value from XMM2/MEM32. * Possible floating point exceptions: - */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCPSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); op = approximate_rcp(op); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op); #endif BX_NEXT_INSTR(i); } #if BX_CPU_LEVEL >= 6 Bit16u rsqrt_table0[1024] = { 0x34f8, 0x34e0, 0x34d0, 0x34b8, 0x34a0, 0x3488, 0x3470, 0x3460, 0x3448, 0x3430, 0x3418, 0x3400, 0x33f0, 0x33d8, 0x33c0, 0x33a8, 0x3398, 0x3380, 0x3368, 0x3350, 0x3338, 0x3328, 0x3310, 0x32f8, 0x32e8, 0x32d0, 0x32b8, 0x32a0, 0x3290, 0x3278, 0x3260, 0x3250, 0x3238, 0x3220, 0x3208, 0x31f8, 0x31e0, 0x31c8, 0x31b8, 0x31a0, 0x3188, 0x3178, 0x3160, 0x3148, 0x3138, 0x3120, 0x3108, 0x30f8, 0x30e0, 0x30c8, 0x30b8, 0x30a0, 0x3090, 0x3078, 0x3060, 0x3050, 0x3038, 0x3028, 0x3010, 0x2ff8, 0x2fe8, 0x2fd0, 0x2fc0, 0x2fa8, 0x2f90, 0x2f80, 0x2f68, 0x2f58, 0x2f40, 0x2f30, 0x2f18, 0x2f00, 0x2ef0, 0x2ed8, 0x2ec8, 0x2eb0, 0x2ea0, 0x2e88, 0x2e78, 0x2e60, 0x2e50, 0x2e38, 0x2e20, 0x2e10, 0x2df8, 0x2de8, 0x2dd0, 0x2dc0, 0x2da8, 0x2d98, 0x2d80, 0x2d70, 0x2d58, 0x2d48, 0x2d38, 0x2d20, 0x2d10, 0x2cf8, 0x2ce8, 0x2cd0, 0x2cc0, 0x2ca8, 0x2c98, 0x2c80, 0x2c70, 0x2c58, 0x2c48, 0x2c38, 0x2c20, 0x2c10, 0x2bf8, 0x2be8, 0x2bd0, 0x2bc0, 0x2bb0, 0x2b98, 0x2b88, 0x2b70, 0x2b60, 0x2b50, 0x2b38, 0x2b28, 0x2b10, 0x2b00, 0x2af0, 0x2ad8, 0x2ac8, 0x2ab8, 0x2aa0, 0x2a90, 0x2a78, 0x2a68, 0x2a58, 0x2a40, 0x2a30, 0x2a20, 0x2a08, 0x29f8, 0x29e8, 0x29d0, 0x29c0, 0x29b0, 0x2998, 0x2988, 0x2978, 0x2960, 0x2950, 0x2940, 0x2928, 0x2918, 0x2908, 0x28f0, 0x28e0, 0x28d0, 0x28c0, 0x28a8, 0x2898, 0x2888, 0x2870, 0x2860, 0x2850, 0x2840, 0x2828, 0x2818, 0x2808, 0x27f8, 0x27e0, 0x27d0, 0x27c0, 0x27b0, 0x2798, 0x2788, 0x2778, 0x2768, 0x2750, 0x2740, 0x2730, 0x2720, 0x2708, 0x26f8, 0x26e8, 0x26d8, 0x26c8, 0x26b0, 0x26a0, 0x2690, 0x2680, 0x2670, 0x2658, 0x2648, 0x2638, 0x2628, 0x2618, 0x2600, 0x25f0, 0x25e0, 0x25d0, 0x25c0, 0x25b0, 0x2598, 0x2588, 0x2578, 0x2568, 0x2558, 0x2548, 0x2530, 0x2520, 0x2510, 0x2500, 0x24f0, 0x24e0, 0x24d0, 0x24b8, 0x24a8, 0x2498, 0x2488, 0x2478, 0x2468, 0x2458, 0x2448, 0x2430, 0x2420, 0x2410, 0x2400, 0x23f0, 0x23e0, 0x23d0, 0x23c0, 0x23b0, 0x23a0, 0x2388, 0x2378, 0x2368, 0x2358, 0x2348, 0x2338, 0x2328, 0x2318, 0x2308, 0x22f8, 0x22e8, 0x22d8, 0x22c8, 0x22b8, 0x22a8, 0x2290, 0x2280, 0x2270, 0x2260, 0x2250, 0x2240, 0x2230, 0x2220, 0x2210, 0x2200, 0x21f0, 0x21e0, 0x21d0, 0x21c0, 0x21b0, 0x21a0, 0x2190, 0x2180, 0x2170, 0x2160, 0x2150, 0x2140, 0x2130, 0x2120, 0x2110, 0x2100, 0x20f0, 0x20e0, 0x20d0, 0x20c0, 0x20b0, 0x20a0, 0x2090, 0x2080, 0x2070, 0x2060, 0x2050, 0x2040, 0x2030, 0x2020, 0x2010, 0x2000, 0x1ff0, 0x1fe8, 0x1fd8, 0x1fc8, 0x1fb8, 0x1fa8, 0x1f98, 0x1f88, 0x1f78, 0x1f68, 0x1f58, 0x1f48, 0x1f38, 0x1f28, 0x1f18, 0x1f08, 0x1f00, 0x1ef0, 0x1ee0, 0x1ed0, 0x1ec0, 0x1eb0, 0x1ea0, 0x1e90, 0x1e80, 0x1e70, 0x1e60, 0x1e58, 0x1e48, 0x1e38, 0x1e28, 0x1e18, 0x1e08, 0x1df8, 0x1de8, 0x1de0, 0x1dd0, 0x1dc0, 0x1db0, 0x1da0, 0x1d90, 0x1d80, 0x1d70, 0x1d68, 0x1d58, 0x1d48, 0x1d38, 0x1d28, 0x1d18, 0x1d08, 0x1d00, 0x1cf0, 0x1ce0, 0x1cd0, 0x1cc0, 0x1cb0, 0x1ca8, 0x1c98, 0x1c88, 0x1c78, 0x1c68, 0x1c58, 0x1c50, 0x1c40, 0x1c30, 0x1c20, 0x1c10, 0x1c08, 0x1bf8, 0x1be8, 0x1bd8, 0x1bc8, 0x1bc0, 0x1bb0, 0x1ba0, 0x1b90, 0x1b80, 0x1b78, 0x1b68, 0x1b58, 0x1b48, 0x1b38, 0x1b30, 0x1b20, 0x1b10, 0x1b00, 0x1af0, 0x1ae8, 0x1ad8, 0x1ac8, 0x1ab8, 0x1ab0, 0x1aa0, 0x1a90, 0x1a80, 0x1a78, 0x1a68, 0x1a58, 0x1a48, 0x1a40, 0x1a30, 0x1a20, 0x1a10, 0x1a08, 0x19f8, 0x19e8, 0x19d8, 0x19d0, 0x19c0, 0x19b0, 0x19a0, 0x1998, 0x1988, 0x1978, 0x1970, 0x1960, 0x1950, 0x1940, 0x1938, 0x1928, 0x1918, 0x1910, 0x1900, 0x18f0, 0x18e0, 0x18d8, 0x18c8, 0x18b8, 0x18b0, 0x18a0, 0x1890, 0x1888, 0x1878, 0x1868, 0x1858, 0x1850, 0x1840, 0x1830, 0x1828, 0x1818, 0x1808, 0x1800, 0x17f0, 0x17e0, 0x17d8, 0x17c8, 0x17b8, 0x17b0, 0x17a0, 0x1790, 0x1788, 0x1778, 0x1768, 0x1760, 0x1750, 0x1740, 0x1738, 0x1728, 0x1718, 0x1710, 0x1700, 0x16f8, 0x16e8, 0x16d8, 0x16d0, 0x16c0, 0x16b0, 0x16a8, 0x1698, 0x1688, 0x1680, 0x1670, 0x1668, 0x1658, 0x1648, 0x1640, 0x1630, 0x1628, 0x1618, 0x1608, 0x1600, 0x15f0, 0x15e0, 0x15d8, 0x15c8, 0x15c0, 0x15b0, 0x15a0, 0x1598, 0x1588, 0x1580, 0x1570, 0x1560, 0x1558, 0x1548, 0x1540, 0x1530, 0x1528, 0x1518, 0x1508, 0x1500, 0x14f0, 0x14e8, 0x14d8, 0x14d0, 0x14c0, 0x14b0, 0x14a8, 0x1498, 0x1490, 0x1480, 0x1478, 0x1468, 0x1458, 0x1450, 0x1440, 0x1438, 0x1428, 0x1420, 0x1410, 0x1408, 0x13f8, 0x13f0, 0x13e0, 0x13d0, 0x13c8, 0x13b8, 0x13b0, 0x13a0, 0x1398, 0x1388, 0x1380, 0x1370, 0x1368, 0x1358, 0x1350, 0x1340, 0x1338, 0x1328, 0x1318, 0x1310, 0x1300, 0x12f8, 0x12e8, 0x12e0, 0x12d0, 0x12c8, 0x12b8, 0x12b0, 0x12a0, 0x1298, 0x1288, 0x1280, 0x1270, 0x1268, 0x1258, 0x1250, 0x1240, 0x1238, 0x1228, 0x1220, 0x1210, 0x1208, 0x11f8, 0x11f0, 0x11e8, 0x11d8, 0x11d0, 0x11c0, 0x11b8, 0x11a8, 0x11a0, 0x1190, 0x1188, 0x1178, 0x1170, 0x1160, 0x1158, 0x1148, 0x1140, 0x1130, 0x1128, 0x1120, 0x1110, 0x1108, 0x10f8, 0x10f0, 0x10e0, 0x10d8, 0x10c8, 0x10c0, 0x10b0, 0x10a8, 0x10a0, 0x1090, 0x1088, 0x1078, 0x1070, 0x1060, 0x1058, 0x1050, 0x1040, 0x1038, 0x1028, 0x1020, 0x1010, 0x1008, 0x1000, 0x0ff0, 0x0fe8, 0x0fd8, 0x0fd0, 0x0fc0, 0x0fb8, 0x0fb0, 0x0fa0, 0x0f98, 0x0f88, 0x0f80, 0x0f78, 0x0f68, 0x0f60, 0x0f50, 0x0f48, 0x0f40, 0x0f30, 0x0f28, 0x0f18, 0x0f10, 0x0f08, 0x0ef8, 0x0ef0, 0x0ee0, 0x0ed8, 0x0ed0, 0x0ec0, 0x0eb8, 0x0ea8, 0x0ea0, 0x0e98, 0x0e88, 0x0e80, 0x0e78, 0x0e68, 0x0e60, 0x0e50, 0x0e48, 0x0e40, 0x0e30, 0x0e28, 0x0e20, 0x0e10, 0x0e08, 0x0df8, 0x0df0, 0x0de8, 0x0dd8, 0x0dd0, 0x0dc8, 0x0db8, 0x0db0, 0x0da8, 0x0d98, 0x0d90, 0x0d80, 0x0d78, 0x0d70, 0x0d60, 0x0d58, 0x0d50, 0x0d40, 0x0d38, 0x0d30, 0x0d20, 0x0d18, 0x0d10, 0x0d00, 0x0cf8, 0x0cf0, 0x0ce0, 0x0cd8, 0x0cd0, 0x0cc0, 0x0cb8, 0x0cb0, 0x0ca0, 0x0c98, 0x0c90, 0x0c80, 0x0c78, 0x0c70, 0x0c60, 0x0c58, 0x0c50, 0x0c40, 0x0c38, 0x0c30, 0x0c28, 0x0c18, 0x0c10, 0x0c08, 0x0bf8, 0x0bf0, 0x0be8, 0x0bd8, 0x0bd0, 0x0bc8, 0x0bb8, 0x0bb0, 0x0ba8, 0x0ba0, 0x0b90, 0x0b88, 0x0b80, 0x0b70, 0x0b68, 0x0b60, 0x0b58, 0x0b48, 0x0b40, 0x0b38, 0x0b28, 0x0b20, 0x0b18, 0x0b10, 0x0b00, 0x0af8, 0x0af0, 0x0ae0, 0x0ad8, 0x0ad0, 0x0ac8, 0x0ab8, 0x0ab0, 0x0aa8, 0x0a98, 0x0a90, 0x0a88, 0x0a80, 0x0a70, 0x0a68, 0x0a60, 0x0a58, 0x0a48, 0x0a40, 0x0a38, 0x0a30, 0x0a20, 0x0a18, 0x0a10, 0x0a08, 0x09f8, 0x09f0, 0x09e8, 0x09e0, 0x09d0, 0x09c8, 0x09c0, 0x09b8, 0x09a8, 0x09a0, 0x0998, 0x0990, 0x0980, 0x0978, 0x0970, 0x0968, 0x0958, 0x0950, 0x0948, 0x0940, 0x0930, 0x0928, 0x0920, 0x0918, 0x0910, 0x0900, 0x08f8, 0x08f0, 0x08e8, 0x08d8, 0x08d0, 0x08c8, 0x08c0, 0x08b8, 0x08a8, 0x08a0, 0x0898, 0x0890, 0x0880, 0x0878, 0x0870, 0x0868, 0x0860, 0x0850, 0x0848, 0x0840, 0x0838, 0x0830, 0x0820, 0x0818, 0x0810, 0x0808, 0x0800, 0x07f0, 0x07e8, 0x07e0, 0x07d8, 0x07d0, 0x07c0, 0x07b8, 0x07b0, 0x07a8, 0x07a0, 0x0790, 0x0788, 0x0780, 0x0778, 0x0770, 0x0768, 0x0758, 0x0750, 0x0748, 0x0740, 0x0738, 0x0728, 0x0720, 0x0718, 0x0710, 0x0708, 0x0700, 0x06f0, 0x06e8, 0x06e0, 0x06d8, 0x06d0, 0x06c8, 0x06b8, 0x06b0, 0x06a8, 0x06a0, 0x0698, 0x0690, 0x0680, 0x0678, 0x0670, 0x0668, 0x0660, 0x0658, 0x0648, 0x0640, 0x0638, 0x0630, 0x0628, 0x0620, 0x0618, 0x0608, 0x0600, 0x05f8, 0x05f0, 0x05e8, 0x05e0, 0x05d8, 0x05c8, 0x05c0, 0x05b8, 0x05b0, 0x05a8, 0x05a0, 0x0598, 0x0588, 0x0580, 0x0578, 0x0570, 0x0568, 0x0560, 0x0558, 0x0548, 0x0540, 0x0538, 0x0530, 0x0528, 0x0520, 0x0518, 0x0510, 0x0500, 0x04f8, 0x04f0, 0x04e8, 0x04e0, 0x04d8, 0x04d0, 0x04c8, 0x04c0, 0x04b0, 0x04a8, 0x04a0, 0x0498, 0x0490, 0x0488, 0x0480, 0x0478, 0x0470, 0x0460, 0x0458, 0x0450, 0x0448, 0x0440, 0x0438, 0x0430, 0x0428, 0x0420, 0x0410, 0x0408, 0x0400, 0x03f8, 0x03f0, 0x03e8, 0x03e0, 0x03d8, 0x03d0, 0x03c8, 0x03c0, 0x03b0, 0x03a8, 0x03a0, 0x0398, 0x0390, 0x0388, 0x0380, 0x0378, 0x0370, 0x0368, 0x0360, 0x0358, 0x0348, 0x0340, 0x0338, 0x0330, 0x0328, 0x0320, 0x0318, 0x0310, 0x0308, 0x0300, 0x02f8, 0x02f0, 0x02e8, 0x02d8, 0x02d0, 0x02c8, 0x02c0, 0x02b8, 0x02b0, 0x02a8, 0x02a0, 0x0298, 0x0290, 0x0288, 0x0280, 0x0278, 0x0270, 0x0268, 0x0260, 0x0250, 0x0248, 0x0240, 0x0238, 0x0230, 0x0228, 0x0220, 0x0218, 0x0210, 0x0208, 0x0200, 0x01f8, 0x01f0, 0x01e8, 0x01e0, 0x01d8, 0x01d0, 0x01c8, 0x01c0, 0x01b8, 0x01b0, 0x01a0, 0x0198, 0x0190, 0x0188, 0x0180, 0x0178, 0x0170, 0x0168, 0x0160, 0x0158, 0x0150, 0x0148, 0x0140, 0x0138, 0x0130, 0x0128, 0x0120, 0x0118, 0x0110, 0x0108, 0x0100, 0x00f8, 0x00f0, 0x00e8, 0x00e0, 0x00d8, 0x00d0, 0x00c8, 0x00c0, 0x00b8, 0x00b0, 0x00a8, 0x00a0, 0x0098, 0x0090, 0x0088, 0x0080, 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008 }; Bit16u rsqrt_table1[1024] = { 0x7ff0, 0x7fd0, 0x7fb0, 0x7f90, 0x7f70, 0x7f50, 0x7f30, 0x7f10, 0x7ef0, 0x7ed0, 0x7eb0, 0x7e90, 0x7e70, 0x7e58, 0x7e38, 0x7e18, 0x7df8, 0x7dd8, 0x7db8, 0x7d98, 0x7d78, 0x7d58, 0x7d38, 0x7d20, 0x7d00, 0x7ce0, 0x7cc0, 0x7ca0, 0x7c80, 0x7c60, 0x7c48, 0x7c28, 0x7c08, 0x7be8, 0x7bc8, 0x7bb0, 0x7b90, 0x7b70, 0x7b50, 0x7b30, 0x7b18, 0x7af8, 0x7ad8, 0x7ab8, 0x7aa0, 0x7a80, 0x7a60, 0x7a40, 0x7a28, 0x7a08, 0x79e8, 0x79c8, 0x79b0, 0x7990, 0x7970, 0x7958, 0x7938, 0x7918, 0x7900, 0x78e0, 0x78c0, 0x78a8, 0x7888, 0x7868, 0x7850, 0x7830, 0x7810, 0x77f8, 0x77d8, 0x77b8, 0x77a0, 0x7780, 0x7768, 0x7748, 0x7728, 0x7710, 0x76f0, 0x76d8, 0x76b8, 0x7698, 0x7680, 0x7660, 0x7648, 0x7628, 0x7610, 0x75f0, 0x75d0, 0x75b8, 0x7598, 0x7580, 0x7560, 0x7548, 0x7528, 0x7510, 0x74f0, 0x74d8, 0x74b8, 0x74a0, 0x7480, 0x7468, 0x7448, 0x7430, 0x7410, 0x73f8, 0x73d8, 0x73c0, 0x73a8, 0x7388, 0x7370, 0x7350, 0x7338, 0x7318, 0x7300, 0x72e8, 0x72c8, 0x72b0, 0x7290, 0x7278, 0x7260, 0x7240, 0x7228, 0x7208, 0x71f0, 0x71d8, 0x71b8, 0x71a0, 0x7188, 0x7168, 0x7150, 0x7130, 0x7118, 0x7100, 0x70e0, 0x70c8, 0x70b0, 0x7090, 0x7078, 0x7060, 0x7048, 0x7028, 0x7010, 0x6ff8, 0x6fd8, 0x6fc0, 0x6fa8, 0x6f88, 0x6f70, 0x6f58, 0x6f40, 0x6f20, 0x6f08, 0x6ef0, 0x6ed8, 0x6eb8, 0x6ea0, 0x6e88, 0x6e70, 0x6e50, 0x6e38, 0x6e20, 0x6e08, 0x6df0, 0x6dd0, 0x6db8, 0x6da0, 0x6d88, 0x6d70, 0x6d50, 0x6d38, 0x6d20, 0x6d08, 0x6cf0, 0x6cd8, 0x6cb8, 0x6ca0, 0x6c88, 0x6c70, 0x6c58, 0x6c40, 0x6c20, 0x6c08, 0x6bf0, 0x6bd8, 0x6bc0, 0x6ba8, 0x6b90, 0x6b78, 0x6b58, 0x6b40, 0x6b28, 0x6b10, 0x6af8, 0x6ae0, 0x6ac8, 0x6ab0, 0x6a98, 0x6a80, 0x6a68, 0x6a48, 0x6a30, 0x6a18, 0x6a00, 0x69e8, 0x69d0, 0x69b8, 0x69a0, 0x6988, 0x6970, 0x6958, 0x6940, 0x6928, 0x6910, 0x68f8, 0x68e0, 0x68c8, 0x68b0, 0x6898, 0x6880, 0x6868, 0x6850, 0x6838, 0x6820, 0x6808, 0x67f0, 0x67d8, 0x67c0, 0x67a8, 0x6790, 0x6778, 0x6760, 0x6748, 0x6730, 0x6718, 0x6700, 0x66e8, 0x66d8, 0x66c0, 0x66a8, 0x6690, 0x6678, 0x6660, 0x6648, 0x6630, 0x6618, 0x6600, 0x65e8, 0x65d0, 0x65c0, 0x65a8, 0x6590, 0x6578, 0x6560, 0x6548, 0x6530, 0x6518, 0x6508, 0x64f0, 0x64d8, 0x64c0, 0x64a8, 0x6490, 0x6478, 0x6468, 0x6450, 0x6438, 0x6420, 0x6408, 0x63f0, 0x63e0, 0x63c8, 0x63b0, 0x6398, 0x6380, 0x6370, 0x6358, 0x6340, 0x6328, 0x6310, 0x6300, 0x62e8, 0x62d0, 0x62b8, 0x62a0, 0x6290, 0x6278, 0x6260, 0x6248, 0x6238, 0x6220, 0x6208, 0x61f0, 0x61e0, 0x61c8, 0x61b0, 0x6198, 0x6188, 0x6170, 0x6158, 0x6140, 0x6130, 0x6118, 0x6100, 0x60f0, 0x60d8, 0x60c0, 0x60a8, 0x6098, 0x6080, 0x6068, 0x6058, 0x6040, 0x6028, 0x6018, 0x6000, 0x5fe8, 0x5fd8, 0x5fc0, 0x5fa8, 0x5f98, 0x5f80, 0x5f68, 0x5f58, 0x5f40, 0x5f28, 0x5f18, 0x5f00, 0x5ee8, 0x5ed8, 0x5ec0, 0x5ea8, 0x5e98, 0x5e80, 0x5e70, 0x5e58, 0x5e40, 0x5e30, 0x5e18, 0x5e00, 0x5df0, 0x5dd8, 0x5dc8, 0x5db0, 0x5d98, 0x5d88, 0x5d70, 0x5d60, 0x5d48, 0x5d38, 0x5d20, 0x5d08, 0x5cf8, 0x5ce0, 0x5cd0, 0x5cb8, 0x5ca8, 0x5c90, 0x5c78, 0x5c68, 0x5c50, 0x5c40, 0x5c28, 0x5c18, 0x5c00, 0x5bf0, 0x5bd8, 0x5bc8, 0x5bb0, 0x5b98, 0x5b88, 0x5b70, 0x5b60, 0x5b48, 0x5b38, 0x5b20, 0x5b10, 0x5af8, 0x5ae8, 0x5ad0, 0x5ac0, 0x5aa8, 0x5a98, 0x5a80, 0x5a70, 0x5a58, 0x5a48, 0x5a30, 0x5a20, 0x5a08, 0x59f8, 0x59e8, 0x59d0, 0x59c0, 0x59a8, 0x5998, 0x5980, 0x5970, 0x5958, 0x5948, 0x5930, 0x5920, 0x5910, 0x58f8, 0x58e8, 0x58d0, 0x58c0, 0x58a8, 0x5898, 0x5888, 0x5870, 0x5860, 0x5848, 0x5838, 0x5828, 0x5810, 0x5800, 0x57e8, 0x57d8, 0x57c8, 0x57b0, 0x57a0, 0x5788, 0x5778, 0x5768, 0x5750, 0x5740, 0x5728, 0x5718, 0x5708, 0x56f0, 0x56e0, 0x56d0, 0x56b8, 0x56a8, 0x5698, 0x5680, 0x5670, 0x5658, 0x5648, 0x5638, 0x5620, 0x5610, 0x5600, 0x55e8, 0x55d8, 0x55c8, 0x55b0, 0x55a0, 0x5590, 0x5578, 0x5568, 0x5558, 0x5540, 0x5530, 0x5520, 0x5510, 0x54f8, 0x54e8, 0x54d8, 0x54c0, 0x54b0, 0x54a0, 0x5488, 0x5478, 0x5468, 0x5458, 0x5440, 0x5430, 0x5420, 0x5410, 0x53f8, 0x53e8, 0x53d8, 0x53c0, 0x53b0, 0x53a0, 0x5390, 0x5378, 0x5368, 0x5358, 0x5348, 0x5330, 0x5320, 0x5310, 0x5300, 0x52e8, 0x52d8, 0x52c8, 0x52b8, 0x52a8, 0x5290, 0x5280, 0x5270, 0x5260, 0x5248, 0x5238, 0x5228, 0x5218, 0x5208, 0x51f0, 0x51e0, 0x51d0, 0x51c0, 0x51b0, 0x5198, 0x5188, 0x5178, 0x5168, 0x5158, 0x5140, 0x5130, 0x5120, 0x5110, 0x5100, 0x50e8, 0x50d8, 0x50c8, 0x50b8, 0x50a8, 0x5098, 0x5080, 0x5070, 0x5060, 0x5050, 0x5040, 0x5030, 0x5020, 0x5008, 0x4ff8, 0x4fe8, 0x4fd8, 0x4fc8, 0x4fb8, 0x4fa8, 0x4f90, 0x4f80, 0x4f70, 0x4f60, 0x4f50, 0x4f40, 0x4f30, 0x4f20, 0x4f08, 0x4ef8, 0x4ee8, 0x4ed8, 0x4ec8, 0x4eb8, 0x4ea8, 0x4e98, 0x4e88, 0x4e70, 0x4e60, 0x4e50, 0x4e40, 0x4e30, 0x4e20, 0x4e10, 0x4e00, 0x4df0, 0x4de0, 0x4dd0, 0x4db8, 0x4da8, 0x4d98, 0x4d88, 0x4d78, 0x4d68, 0x4d58, 0x4d48, 0x4d38, 0x4d28, 0x4d18, 0x4d08, 0x4cf8, 0x4ce8, 0x4cd8, 0x4cc8, 0x4cb8, 0x4ca0, 0x4c90, 0x4c80, 0x4c70, 0x4c60, 0x4c50, 0x4c40, 0x4c30, 0x4c20, 0x4c10, 0x4c00, 0x4bf0, 0x4be0, 0x4bd0, 0x4bc0, 0x4bb0, 0x4ba0, 0x4b90, 0x4b80, 0x4b70, 0x4b60, 0x4b50, 0x4b40, 0x4b30, 0x4b20, 0x4b10, 0x4b00, 0x4af0, 0x4ae0, 0x4ad0, 0x4ac0, 0x4ab0, 0x4aa0, 0x4a90, 0x4a80, 0x4a70, 0x4a60, 0x4a50, 0x4a40, 0x4a30, 0x4a20, 0x4a10, 0x4a00, 0x49f0, 0x49e0, 0x49d0, 0x49c0, 0x49b8, 0x49a8, 0x4998, 0x4988, 0x4978, 0x4968, 0x4958, 0x4948, 0x4938, 0x4928, 0x4918, 0x4908, 0x48f8, 0x48e8, 0x48d8, 0x48c8, 0x48b8, 0x48b0, 0x48a0, 0x4890, 0x4880, 0x4870, 0x4860, 0x4850, 0x4840, 0x4830, 0x4820, 0x4810, 0x4800, 0x47f8, 0x47e8, 0x47d8, 0x47c8, 0x47b8, 0x47a8, 0x4798, 0x4788, 0x4778, 0x4768, 0x4760, 0x4750, 0x4740, 0x4730, 0x4720, 0x4710, 0x4700, 0x46f0, 0x46e0, 0x46d8, 0x46c8, 0x46b8, 0x46a8, 0x4698, 0x4688, 0x4678, 0x4670, 0x4660, 0x4650, 0x4640, 0x4630, 0x4620, 0x4610, 0x4608, 0x45f8, 0x45e8, 0x45d8, 0x45c8, 0x45b8, 0x45a8, 0x45a0, 0x4590, 0x4580, 0x4570, 0x4560, 0x4550, 0x4548, 0x4538, 0x4528, 0x4518, 0x4508, 0x44f8, 0x44f0, 0x44e0, 0x44d0, 0x44c0, 0x44b0, 0x44a8, 0x4498, 0x4488, 0x4478, 0x4468, 0x4460, 0x4450, 0x4440, 0x4430, 0x4420, 0x4418, 0x4408, 0x43f8, 0x43e8, 0x43d8, 0x43d0, 0x43c0, 0x43b0, 0x43a0, 0x4390, 0x4388, 0x4378, 0x4368, 0x4358, 0x4350, 0x4340, 0x4330, 0x4320, 0x4310, 0x4308, 0x42f8, 0x42e8, 0x42d8, 0x42d0, 0x42c0, 0x42b0, 0x42a0, 0x4298, 0x4288, 0x4278, 0x4268, 0x4260, 0x4250, 0x4240, 0x4230, 0x4228, 0x4218, 0x4208, 0x41f8, 0x41f0, 0x41e0, 0x41d0, 0x41c0, 0x41b8, 0x41a8, 0x4198, 0x4188, 0x4180, 0x4170, 0x4160, 0x4158, 0x4148, 0x4138, 0x4128, 0x4120, 0x4110, 0x4100, 0x40f8, 0x40e8, 0x40d8, 0x40c8, 0x40c0, 0x40b0, 0x40a0, 0x4098, 0x4088, 0x4078, 0x4068, 0x4060, 0x4050, 0x4040, 0x4038, 0x4028, 0x4018, 0x4010, 0x4000, 0x3ff0, 0x3fe8, 0x3fd8, 0x3fc8, 0x3fb8, 0x3fb0, 0x3fa0, 0x3f90, 0x3f88, 0x3f78, 0x3f68, 0x3f60, 0x3f50, 0x3f40, 0x3f38, 0x3f28, 0x3f18, 0x3f10, 0x3f00, 0x3ef0, 0x3ee8, 0x3ed8, 0x3ec8, 0x3ec0, 0x3eb0, 0x3ea0, 0x3e98, 0x3e88, 0x3e80, 0x3e70, 0x3e60, 0x3e58, 0x3e48, 0x3e38, 0x3e30, 0x3e20, 0x3e10, 0x3e08, 0x3df8, 0x3df0, 0x3de0, 0x3dd0, 0x3dc8, 0x3db8, 0x3da8, 0x3da0, 0x3d90, 0x3d80, 0x3d78, 0x3d68, 0x3d60, 0x3d50, 0x3d40, 0x3d38, 0x3d28, 0x3d20, 0x3d10, 0x3d00, 0x3cf8, 0x3ce8, 0x3cd8, 0x3cd0, 0x3cc0, 0x3cb8, 0x3ca8, 0x3c98, 0x3c90, 0x3c80, 0x3c78, 0x3c68, 0x3c58, 0x3c50, 0x3c40, 0x3c38, 0x3c28, 0x3c20, 0x3c10, 0x3c00, 0x3bf8, 0x3be8, 0x3be0, 0x3bd0, 0x3bc0, 0x3bb8, 0x3ba8, 0x3ba0, 0x3b90, 0x3b88, 0x3b78, 0x3b68, 0x3b60, 0x3b50, 0x3b48, 0x3b38, 0x3b30, 0x3b20, 0x3b10, 0x3b08, 0x3af8, 0x3af0, 0x3ae0, 0x3ad8, 0x3ac8, 0x3ac0, 0x3ab0, 0x3aa0, 0x3a98, 0x3a88, 0x3a80, 0x3a70, 0x3a68, 0x3a58, 0x3a50, 0x3a40, 0x3a38, 0x3a28, 0x3a20, 0x3a10, 0x3a00, 0x39f8, 0x39e8, 0x39e0, 0x39d0, 0x39c8, 0x39b8, 0x39b0, 0x39a0, 0x3998, 0x3988, 0x3980, 0x3970, 0x3968, 0x3958, 0x3950, 0x3940, 0x3938, 0x3928, 0x3918, 0x3910, 0x3900, 0x38f8, 0x38e8, 0x38e0, 0x38d0, 0x38c8, 0x38b8, 0x38b0, 0x38a0, 0x3898, 0x3888, 0x3880, 0x3870, 0x3868, 0x3858, 0x3850, 0x3840, 0x3838, 0x3828, 0x3820, 0x3818, 0x3808, 0x3800, 0x37f0, 0x37e8, 0x37d8, 0x37d0, 0x37c0, 0x37b8, 0x37a8, 0x37a0, 0x3790, 0x3788, 0x3778, 0x3770, 0x3760, 0x3758, 0x3748, 0x3740, 0x3730, 0x3728, 0x3720, 0x3710, 0x3708, 0x36f8, 0x36f0, 0x36e0, 0x36d8, 0x36c8, 0x36c0, 0x36b0, 0x36a8, 0x3698, 0x3690, 0x3688, 0x3678, 0x3670, 0x3660, 0x3658, 0x3648, 0x3640, 0x3630, 0x3628, 0x3620, 0x3610, 0x3608, 0x35f8, 0x35f0, 0x35e0, 0x35d8, 0x35d0, 0x35c0, 0x35b8, 0x35a8, 0x35a0, 0x3590, 0x3588, 0x3580, 0x3570, 0x3568, 0x3558, 0x3550, 0x3540, 0x3538, 0x3530, 0x3520, 0x3518, 0x3508 }; // approximate reciprocal sqrt of scalar single precision FP float32 approximate_rsqrt(float32 op) { float_class_t op_class = float32_class(op); int sign = float32_sign(op); switch(op_class) { case float_zero: case float_denormal: return packFloat32(sign, 0xFF, 0); case float_positive_inf: return 0; case float_negative_inf: return float32_default_nan; case float_NaN: return convert_to_QNaN(op); case float_normalized: break; }; if (sign == 1) return float32_default_nan; Bit32u fraction = float32_fraction(op); Bit16s exp = float32_exp(op); /* * Calculate (1/1.yyyyyyyyyy1), the result is always rounded to the * 11th bit after the decimal point by round-to-nearest, regardless * of the current rounding mode. * * Using two precalculated 1024-entry tables. */ Bit16u *rsqrt_table = (exp & 1) ? rsqrt_table1 : rsqrt_table0; exp = 126 - ((exp - 127) >> 1); /* check for underflow */ if (exp <= 0) return packFloat32(sign, 0x00, 0); return packFloat32(sign, exp, (Bit32u)(rsqrt_table[fraction >> 13]) << 8); } #endif /* * Opcode: F3 0F 52 * Approximate reciprocal of square root of scalar single precision FP value * from XMM2/MEM32. * Possible floating point exceptions: - */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RSQRTSS_VssWssR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 float32 op = BX_READ_XMM_REG_LO_DWORD(i->src()); op = approximate_rsqrt(op); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op); #endif BX_NEXT_INSTR(i); } /* * Opcode: 0F 52 * Approximate reciprocal of square root of packed single precision FP values * from XMM2/MEM. * Possible floating point exceptions: - */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RSQRTPS_VpsWpsR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); op.xmm32u(0) = approximate_rsqrt(op.xmm32u(0)); op.xmm32u(1) = approximate_rsqrt(op.xmm32u(1)); op.xmm32u(2) = approximate_rsqrt(op.xmm32u(2)); op.xmm32u(3) = approximate_rsqrt(op.xmm32u(3)); BX_WRITE_XMM_REG(i->dst(), op); #endif BX_NEXT_INSTR(i); } bochs-2.6/cpu/aes.cc0000644000175000017500000003313412020641453014204 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: aes.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 6 // // XMM - Byte Representation of a 128-bit AES State // // F E D C B A // 1 1 1 1 1 1 // 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 // --+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-- // P O N M L K J I H G F E D C B A // // // XMM - Matrix Representation of a 128-bit AES State // // | A E I M | | S(0,0) S(0,1) S(0,2) S(0,3) | | S(0) S(4) S(8) S(C) | // | B F J N | = | S(1,0) S(1,1) S(1,2) S(1,3) | = | S(1) S(5) S(9) S(D) | // | C G K O | | S(2,0) S(2,1) S(2,2) S(2,3) | | S(2) S(6) S(A) S(E) | // | D H L P | | S(3,0) S(3,1) S(2,3) S(3,3) | | S(3) S(7) S(B) S(F) | // // // AES ShiftRows transformation // // | A E I M | | A E I M | // | B F J N | => | F J N B | // | C G K O | | K O C G | // | D H L P | | P D H L | // BX_CPP_INLINE void AES_ShiftRows(BxPackedXmmRegister &state) { BxPackedXmmRegister tmp = state; state.xmmubyte(0x0) = tmp.xmmubyte(0x0); // A => A state.xmmubyte(0x1) = tmp.xmmubyte(0x5); state.xmmubyte(0x2) = tmp.xmmubyte(0xA); state.xmmubyte(0x3) = tmp.xmmubyte(0xF); state.xmmubyte(0x4) = tmp.xmmubyte(0x4); // E => E state.xmmubyte(0x5) = tmp.xmmubyte(0x9); state.xmmubyte(0x6) = tmp.xmmubyte(0xE); state.xmmubyte(0x7) = tmp.xmmubyte(0x3); state.xmmubyte(0x8) = tmp.xmmubyte(0x8); // I => I state.xmmubyte(0x9) = tmp.xmmubyte(0xD); state.xmmubyte(0xA) = tmp.xmmubyte(0x2); state.xmmubyte(0xB) = tmp.xmmubyte(0x7); state.xmmubyte(0xC) = tmp.xmmubyte(0xC); // M => M state.xmmubyte(0xD) = tmp.xmmubyte(0x1); state.xmmubyte(0xE) = tmp.xmmubyte(0x6); state.xmmubyte(0xF) = tmp.xmmubyte(0xB); } // // AES InverseShiftRows transformation // // | A E I M | | A E I M | // | B F J N | => | N B F J | // | C G K O | | K O C G | // | D H L P | | H L P D | // BX_CPP_INLINE void AES_InverseShiftRows(BxPackedXmmRegister &state) { BxPackedXmmRegister tmp = state; state.xmmubyte(0x0) = tmp.xmmubyte(0x0); // A => A state.xmmubyte(0x1) = tmp.xmmubyte(0xD); state.xmmubyte(0x2) = tmp.xmmubyte(0xA); state.xmmubyte(0x3) = tmp.xmmubyte(0x7); state.xmmubyte(0x4) = tmp.xmmubyte(0x4); // E => E state.xmmubyte(0x5) = tmp.xmmubyte(0x1); state.xmmubyte(0x6) = tmp.xmmubyte(0xE); state.xmmubyte(0x7) = tmp.xmmubyte(0xB); state.xmmubyte(0x8) = tmp.xmmubyte(0x8); // I => I state.xmmubyte(0x9) = tmp.xmmubyte(0x5); state.xmmubyte(0xA) = tmp.xmmubyte(0x2); state.xmmubyte(0xB) = tmp.xmmubyte(0xF); state.xmmubyte(0xC) = tmp.xmmubyte(0xC); // M => M state.xmmubyte(0xD) = tmp.xmmubyte(0x9); state.xmmubyte(0xE) = tmp.xmmubyte(0x6); state.xmmubyte(0xF) = tmp.xmmubyte(0x3); } static Bit8u sbox_transformation[256] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; static Bit8u inverse_sbox_transformation[256] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; BX_CPP_INLINE void AES_SubstituteBytes(BxPackedXmmRegister &state) { for (int i=0; i<16; i++) state.xmmubyte(i) = sbox_transformation[state.xmmubyte(i)]; } BX_CPP_INLINE void AES_InverseSubstituteBytes(BxPackedXmmRegister &state) { for (int i=0; i<16; i++) state.xmmubyte(i) = inverse_sbox_transformation[state.xmmubyte(i)]; } /* * Galois Field multiplication of a by b, modulo m. * Just like arithmetic multiplication, except that additions and * subtractions are replaced by XOR. * The code was taken from: http://www.darkside.com.au/ice/index.html */ BX_CPP_INLINE unsigned gf_mul(unsigned a, unsigned b) { unsigned res = 0, m = 0x11b; while (b) { if (b & 1) res ^= a; a <<= 1; b >>= 1; if (a >= 256) a ^= m; } return res; } #define AES_STATE(s,a,b) (s.xmmubyte((b)*4+(a))) static void AES_MixColumns(BxPackedXmmRegister &state) { BxPackedXmmRegister tmp = state; for(int j=0; j<4; j++) { AES_STATE(state, 0, j) = gf_mul(0x2, AES_STATE(tmp, 0, j)) ^ gf_mul(0x3, AES_STATE(tmp, 1, j)) ^ AES_STATE(tmp, 2, j) ^ AES_STATE(tmp, 3, j); AES_STATE(state, 1, j) = AES_STATE(tmp, 0, j) ^ gf_mul(0x2, AES_STATE(tmp, 1, j)) ^ gf_mul(0x3, AES_STATE(tmp, 2, j)) ^ AES_STATE(tmp, 3, j); AES_STATE(state, 2, j) = AES_STATE(tmp, 0, j) ^ AES_STATE(tmp, 1, j) ^ gf_mul(0x2, AES_STATE(tmp, 2, j)) ^ gf_mul(0x3, AES_STATE(tmp, 3, j)); AES_STATE(state, 3, j) = gf_mul(0x3, AES_STATE(tmp, 0, j)) ^ AES_STATE(tmp, 1, j) ^ AES_STATE(tmp, 2, j) ^ gf_mul(0x2, AES_STATE(tmp, 3, j)); } } static void AES_InverseMixColumns(BxPackedXmmRegister &state) { BxPackedXmmRegister tmp = state; for(int j=0; j<4; j++) { AES_STATE(state, 0, j) = gf_mul(0xE, AES_STATE(tmp, 0, j)) ^ gf_mul(0xB, AES_STATE(tmp, 1, j)) ^ gf_mul(0xD, AES_STATE(tmp, 2, j)) ^ gf_mul(0x9, AES_STATE(tmp, 3, j)); AES_STATE(state, 1, j) = gf_mul(0x9, AES_STATE(tmp, 0, j)) ^ gf_mul(0xE, AES_STATE(tmp, 1, j)) ^ gf_mul(0xB, AES_STATE(tmp, 2, j)) ^ gf_mul(0xD, AES_STATE(tmp, 3, j)); AES_STATE(state, 2, j) = gf_mul(0xD, AES_STATE(tmp, 0, j)) ^ gf_mul(0x9, AES_STATE(tmp, 1, j)) ^ gf_mul(0xE, AES_STATE(tmp, 2, j)) ^ gf_mul(0xB, AES_STATE(tmp, 3, j)); AES_STATE(state, 3, j) = gf_mul(0xB, AES_STATE(tmp, 0, j)) ^ gf_mul(0xD, AES_STATE(tmp, 1, j)) ^ gf_mul(0x9, AES_STATE(tmp, 2, j)) ^ gf_mul(0xE, AES_STATE(tmp, 3, j)); } } BX_CPP_INLINE Bit32u AES_SubWord(Bit32u x) { Bit8u b0 = sbox_transformation[(x) & 0xff]; Bit8u b1 = sbox_transformation[(x>>8) & 0xff]; Bit8u b2 = sbox_transformation[(x>>16) & 0xff]; Bit8u b3 = sbox_transformation[(x>>24) & 0xff]; return b0 | ((Bit32u)(b1) << 8) | ((Bit32u)(b2) << 16) | ((Bit32u)(b3) << 24); } BX_CPP_INLINE Bit32u AES_RotWord(Bit32u x) { return (x >> 8) | (x << 24); } /* 66 0F 38 DB */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AESIMC_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); AES_InverseMixColumns(op); BX_WRITE_XMM_REGZ(i->dst(), op, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 DC */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AESENC_VdqHdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); AES_ShiftRows(op1); AES_SubstituteBytes(op1); AES_MixColumns(op1); op1.xmm64u(0) ^= op2.xmm64u(0); op1.xmm64u(1) ^= op2.xmm64u(1); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 DD */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AESENCLAST_VdqHdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); AES_ShiftRows(op1); AES_SubstituteBytes(op1); op1.xmm64u(0) ^= op2.xmm64u(0); op1.xmm64u(1) ^= op2.xmm64u(1); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 DE */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AESDEC_VdqHdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); AES_InverseShiftRows(op1); AES_InverseSubstituteBytes(op1); AES_InverseMixColumns(op1); op1.xmm64u(0) ^= op2.xmm64u(0); op1.xmm64u(1) ^= op2.xmm64u(1); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 38 DF */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AESDECLAST_VdqHdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); AES_InverseShiftRows(op1); AES_InverseSubstituteBytes(op1); op1.xmm64u(0) ^= op2.xmm64u(0); op1.xmm64u(1) ^= op2.xmm64u(1); BX_WRITE_XMM_REGZ(i->dst(), op1, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 3A DF */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AESKEYGENASSIST_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()), result; Bit32u rcon32 = i->Ib(); result.xmm32u(0) = AES_SubWord(op.xmm32u(1)); result.xmm32u(1) = AES_RotWord(result.xmm32u(0)) ^ rcon32; result.xmm32u(2) = AES_SubWord(op.xmm32u(3)); result.xmm32u(3) = AES_RotWord(result.xmm32u(2)) ^ rcon32; BX_WRITE_XMM_REGZ(i->dst(), result, i->getVL()); BX_NEXT_INSTR(i); } /* 66 0F 3A 44 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCLMULQDQ_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->src1()), op2 = BX_READ_XMM_REG(i->src2()); BxPackedXmmRegister r, a; Bit8u imm8 = i->Ib(); // // Initialize sources for Carry Less Multiplication [R = A CLMUL B] // // A determined by imm8[0] a.xmm64u(0) = op1.xmm64u(imm8 & 1); a.xmm64u(1) = 0; // B determined by imm8[4] Bit64u b = op2.xmm64u((imm8 >> 4) & 1); r.xmm64u(0) = 0; r.xmm64u(1) = 0; for (int n = 0; b && n < 64; n++) { if (b & 1) { r.xmm64u(0) ^= a.xmm64u(0); r.xmm64u(1) ^= a.xmm64u(1); } a.xmm64u(1) = (a.xmm64u(1) << 1) | (a.xmm64u(0) >> 63); a.xmm64u(0) <<= 1; b >>= 1; } BX_WRITE_XMM_REGZ(i->dst(), r, i->getVL()); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/msr.cc0000644000175000017500000006714012020641453014241 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: msr.cc 11299 2012-07-26 16:03:26Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 5 bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::rdmsr(Bit32u index, Bit64u *msr) { Bit64u val64 = 0; #if BX_CPU_LEVEL >= 6 if (bx_cpuid_support_x2apic()) { if (index >= 0x800 && index <= 0xBFF) { if (BX_CPU_THIS_PTR msr.apicbase & 0x400) // X2APIC mode return BX_CPU_THIS_PTR lapic.read_x2apic(index, msr); else return 0; } } #endif switch(index) { #if BX_CPU_LEVEL >= 6 case BX_MSR_SYSENTER_CS: if (! bx_cpuid_support_sep()) { BX_ERROR(("RDMSR MSR_SYSENTER_CS: SYSENTER/SYSEXIT feature not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = BX_CPU_THIS_PTR msr.sysenter_cs_msr; break; case BX_MSR_SYSENTER_ESP: if (! bx_cpuid_support_sep()) { BX_ERROR(("RDMSR MSR_SYSENTER_ESP: SYSENTER/SYSEXIT feature not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = BX_CPU_THIS_PTR msr.sysenter_esp_msr; break; case BX_MSR_SYSENTER_EIP: if (! bx_cpuid_support_sep()) { BX_ERROR(("RDMSR MSR_SYSENTER_EIP: SYSENTER/SYSEXIT feature not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = BX_CPU_THIS_PTR msr.sysenter_eip_msr; break; #endif #if BX_CPU_LEVEL >= 6 case BX_MSR_MTRRCAP: // read only MSR val64 = BX_CONST64(0x0000000000000508); break; case BX_MSR_MTRRPHYSBASE0: case BX_MSR_MTRRPHYSMASK0: case BX_MSR_MTRRPHYSBASE1: case BX_MSR_MTRRPHYSMASK1: case BX_MSR_MTRRPHYSBASE2: case BX_MSR_MTRRPHYSMASK2: case BX_MSR_MTRRPHYSBASE3: case BX_MSR_MTRRPHYSMASK3: case BX_MSR_MTRRPHYSBASE4: case BX_MSR_MTRRPHYSMASK4: case BX_MSR_MTRRPHYSBASE5: case BX_MSR_MTRRPHYSMASK5: case BX_MSR_MTRRPHYSBASE6: case BX_MSR_MTRRPHYSMASK6: case BX_MSR_MTRRPHYSBASE7: case BX_MSR_MTRRPHYSMASK7: val64 = BX_CPU_THIS_PTR msr.mtrrphys[index - BX_MSR_MTRRPHYSBASE0]; break; case BX_MSR_MTRRFIX64K_00000: val64 = BX_CPU_THIS_PTR msr.mtrrfix64k_00000; break; case BX_MSR_MTRRFIX16K_80000: case BX_MSR_MTRRFIX16K_A0000: val64 = BX_CPU_THIS_PTR msr.mtrrfix16k[index - BX_MSR_MTRRFIX16K_80000]; break; case BX_MSR_MTRRFIX4K_C0000: case BX_MSR_MTRRFIX4K_C8000: case BX_MSR_MTRRFIX4K_D0000: case BX_MSR_MTRRFIX4K_D8000: case BX_MSR_MTRRFIX4K_E0000: case BX_MSR_MTRRFIX4K_E8000: case BX_MSR_MTRRFIX4K_F0000: case BX_MSR_MTRRFIX4K_F8000: val64 = BX_CPU_THIS_PTR msr.mtrrfix4k[index - BX_MSR_MTRRFIX4K_C0000]; break; case BX_MSR_PAT: val64 = BX_CPU_THIS_PTR msr.pat; break; case BX_MSR_MTRR_DEFTYPE: val64 = BX_CPU_THIS_PTR msr.mtrr_deftype; break; #endif case BX_MSR_TSC: val64 = BX_CPU_THIS_PTR get_TSC(); break; #if BX_SUPPORT_APIC case BX_MSR_APICBASE: val64 = BX_CPU_THIS_PTR msr.apicbase; BX_INFO(("RDMSR: Read %08x:%08x from MSR_APICBASE", GET32H(val64), GET32L(val64))); break; #endif #if BX_CPU_LEVEL >= 6 case BX_MSR_TSC_DEADLINE: if (! bx_cpuid_support_tsc_deadline()) { BX_ERROR(("RDMSR BX_MSR_TSC_DEADLINE: TSC-Deadline not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = BX_CPU_THIS_PTR lapic.get_tsc_deadline(); break; #endif #if BX_SUPPORT_VMX /* case BX_MSR_IA32_SMM_MONITOR_CTL: BX_PANIC(("Dual-monitor treatment of SMI and SMM is not implemented")); break; */ case BX_MSR_IA32_FEATURE_CONTROL: val64 = BX_CPU_THIS_PTR msr.ia32_feature_ctrl; break; case BX_MSR_VMX_BASIC: val64 = VMX_MSR_VMX_BASIC; break; case BX_MSR_VMX_PINBASED_CTRLS: val64 = VMX_MSR_VMX_PINBASED_CTRLS; break; case BX_MSR_VMX_PROCBASED_CTRLS: val64 = VMX_MSR_VMX_PROCBASED_CTRLS; break; case BX_MSR_VMX_VMEXIT_CTRLS: val64 = VMX_MSR_VMX_VMEXIT_CTRLS; break; case BX_MSR_VMX_VMENTRY_CTRLS: val64 = VMX_MSR_VMX_VMENTRY_CTRLS; break; case BX_MSR_VMX_PROCBASED_CTRLS2: if (BX_CPU_THIS_PTR vmx_cap.vmx_vmexec_ctrl2_supported_bits) { val64 = VMX_MSR_VMX_PROCBASED_CTRLS2; break; } return 0; #if BX_SUPPORT_VMX >= 2 case BX_MSR_VMX_TRUE_PINBASED_CTRLS: val64 = VMX_MSR_VMX_TRUE_PINBASED_CTRLS; break; case BX_MSR_VMX_TRUE_PROCBASED_CTRLS: val64 = VMX_MSR_VMX_TRUE_PROCBASED_CTRLS; break; case BX_MSR_VMX_TRUE_VMEXIT_CTRLS: val64 = VMX_MSR_VMX_TRUE_VMEXIT_CTRLS; break; case BX_MSR_VMX_TRUE_VMENTRY_CTRLS: val64 = VMX_MSR_VMX_TRUE_VMENTRY_CTRLS; break; case BX_MSR_VMX_EPT_VPID_CAP: if (VMX_MSR_VMX_EPT_VPID_CAP != 0) { val64 = VMX_MSR_VMX_EPT_VPID_CAP; break; } return 0; case BX_MSR_VMX_VMFUNC: if (BX_CPU_THIS_PTR vmx_cap.vmx_vmfunc_supported_bits) { val64 = BX_CPU_THIS_PTR vmx_cap.vmx_vmfunc_supported_bits; break; } return 0; #endif case BX_MSR_VMX_MISC: val64 = VMX_MSR_MISC; break; case BX_MSR_VMX_CR0_FIXED0: val64 = VMX_MSR_CR0_FIXED0; break; case BX_MSR_VMX_CR0_FIXED1: val64 = VMX_MSR_CR0_FIXED1; break; case BX_MSR_VMX_CR4_FIXED0: val64 = VMX_MSR_CR4_FIXED0; break; case BX_MSR_VMX_CR4_FIXED1: val64 = VMX_MSR_CR4_FIXED1; break; case BX_MSR_VMX_VMCS_ENUM: val64 = VMX_MSR_VMCS_ENUM; break; #endif case BX_MSR_EFER: if (! BX_CPU_THIS_PTR efer_suppmask) { BX_ERROR(("RDMSR MSR_EFER: EFER MSR is not supported !")); return handle_unknown_rdmsr(index, msr); } val64 = BX_CPU_THIS_PTR efer.get32(); break; #if BX_SUPPORT_SVM case BX_SVM_HSAVE_PA_MSR: if (! bx_cpuid_support_svm()) { BX_ERROR(("RDMSR SVM_HSAVE_PA_MSR: SVM support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = BX_CPU_THIS_PTR msr.svm_hsave_pa; break; #endif case BX_MSR_STAR: if ((BX_CPU_THIS_PTR efer_suppmask & BX_EFER_SCE_MASK) == 0) { BX_ERROR(("RDMSR MSR_STAR: SYSCALL/SYSRET support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_STAR; break; #if BX_SUPPORT_X86_64 case BX_MSR_LSTAR: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("RDMSR MSR_LSTAR: long mode support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_LSTAR; break; case BX_MSR_CSTAR: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("RDMSR MSR_CSTAR: long mode support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_CSTAR; break; case BX_MSR_FMASK: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("RDMSR MSR_FMASK: long mode support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_FMASK; break; case BX_MSR_FSBASE: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("RDMSR MSR_FSBASE: long mode support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_FSBASE; break; case BX_MSR_GSBASE: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("RDMSR MSR_GSBASE: long mode support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_GSBASE; break; case BX_MSR_KERNELGSBASE: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("RDMSR MSR_KERNELGSBASE: long mode support not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_KERNELGSBASE; break; case BX_MSR_TSC_AUX: if (! bx_cpuid_support_rdtscp()) { BX_ERROR(("RDMSR MSR_TSC_AUX: RTDSCP feature not enabled !")); return handle_unknown_rdmsr(index, msr); } val64 = MSR_TSC_AUX; // 32 bit MSR break; #endif default: return handle_unknown_rdmsr(index, msr); } BX_DEBUG(("RDMSR: read %08x:%08x from MSR %x", GET32H(val64), GET32L(val64), index)); *msr = val64; return 1; } bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::handle_unknown_rdmsr(Bit32u index, Bit64u *msr) { Bit64u val_64 = 0; // Try to check cpuid_t first (can implement some MSRs) int result = BX_CPU_THIS_PTR cpuid->rdmsr(index, &val_64); if (result == 0) return 0; // #GP fault due to not supported MSR if (result < 0) { // cpuid_t have no idea about this MSR #if BX_CONFIGURE_MSRS if (index < BX_MSR_MAX_INDEX && BX_CPU_THIS_PTR msrs[index]) { val_64 = BX_CPU_THIS_PTR msrs[index]->get64(); } else #endif { // failed to find the MSR, could #GP or ignore it silently BX_ERROR(("RDMSR: Unknown register %#x", index)); if (! BX_CPU_THIS_PTR ignore_bad_msrs) return 0; // will result in #GP fault due to unknown MSR } } *msr = val_64; return 1; } #endif // BX_CPU_LEVEL >= 5 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RDMSR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("RDMSR: CPL != 0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } Bit32u index = ECX; Bit64u val64 = 0; #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_MSR)) SvmInterceptMSR(BX_READ, index); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_MSR(VMX_VMEXIT_RDMSR, index); #endif #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest && index == 0x808) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE)) { RAX = VMX_Read_VTPR() & 0xff; RDX = 0; BX_NEXT_INSTR(i); } } #endif if (!rdmsr(index, &val64)) exception(BX_GP_EXCEPTION, 0); RAX = GET32L(val64); RDX = GET32H(val64); #endif BX_NEXT_INSTR(i); } #if BX_CPU_LEVEL >= 6 bx_bool isMemTypeValidMTRR(unsigned memtype) { switch(memtype) { case BX_MEMTYPE_UC: case BX_MEMTYPE_WC: case BX_MEMTYPE_WT: case BX_MEMTYPE_WP: case BX_MEMTYPE_WB: return 1; default: return 0; } } BX_CPP_INLINE bx_bool isMemTypeValidPAT(unsigned memtype) { return (memtype == 0x07) /* UC- */ || isMemTypeValidMTRR(memtype); } bx_bool isValidMSR_PAT(Bit64u pat_msr) { if (! isMemTypeValidPAT(pat_msr & 0xFF) || ! isMemTypeValidPAT((pat_msr >> 8) & 0xFF) || ! isMemTypeValidPAT((pat_msr >> 16) & 0xFF) || ! isMemTypeValidPAT((pat_msr >> 24) & 0xFF) || ! isMemTypeValidPAT((pat_msr >> 32) & 0xFF) || ! isMemTypeValidPAT((pat_msr >> 40) & 0xFF) || ! isMemTypeValidPAT((pat_msr >> 48) & 0xFF) || ! isMemTypeValidPAT(pat_msr >> 56)) return 0; return 1; } bx_bool isValidMSR_FixedMTRR(Bit64u fixed_mtrr_msr) { if (! isMemTypeValidMTRR(fixed_mtrr_msr & 0xFF) || ! isMemTypeValidMTRR((fixed_mtrr_msr >> 8) & 0xFF) || ! isMemTypeValidMTRR((fixed_mtrr_msr >> 16) & 0xFF) || ! isMemTypeValidMTRR((fixed_mtrr_msr >> 24) & 0xFF) || ! isMemTypeValidMTRR((fixed_mtrr_msr >> 32) & 0xFF) || ! isMemTypeValidMTRR((fixed_mtrr_msr >> 40) & 0xFF) || ! isMemTypeValidMTRR((fixed_mtrr_msr >> 48) & 0xFF) || ! isMemTypeValidMTRR(fixed_mtrr_msr >> 56)) return 0; return 1; } #endif #if BX_CPU_LEVEL >= 5 bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::wrmsr(Bit32u index, Bit64u val_64) { Bit32u val32_lo = GET32L(val_64); Bit32u val32_hi = GET32H(val_64); BX_INSTR_WRMSR(BX_CPU_ID, index, val_64); BX_DEBUG(("WRMSR: write %08x:%08x to MSR %x", val32_hi, val32_lo, index)); #if BX_CPU_LEVEL >= 6 if (bx_cpuid_support_x2apic()) { if (index >= 0x800 && index <= 0xBFF) { if (BX_CPU_THIS_PTR msr.apicbase & 0x400) // X2APIC mode return BX_CPU_THIS_PTR lapic.write_x2apic(index, val32_hi, val32_lo); else return 0; } } #endif switch(index) { #if BX_CPU_LEVEL >= 6 case BX_MSR_SYSENTER_CS: if (! bx_cpuid_support_sep()) { BX_ERROR(("WRMSR MSR_SYSENTER_CS: SYSENTER/SYSEXIT feature not enabled !")); return handle_unknown_wrmsr(index, val_64); } BX_CPU_THIS_PTR msr.sysenter_cs_msr = val32_lo; break; case BX_MSR_SYSENTER_ESP: if (! bx_cpuid_support_sep()) { BX_ERROR(("WRMSR MSR_SYSENTER_ESP: SYSENTER/SYSEXIT feature not enabled !")); return handle_unknown_wrmsr(index, val_64); } #if BX_SUPPORT_X86_64 if (! IsCanonical(val_64)) { BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_SYSENTER_ESP !")); return 0; } #endif BX_CPU_THIS_PTR msr.sysenter_esp_msr = val_64; break; case BX_MSR_SYSENTER_EIP: if (! bx_cpuid_support_sep()) { BX_ERROR(("WRMSR MSR_SYSENTER_EIP: SYSENTER/SYSEXIT feature not enabled !")); return handle_unknown_wrmsr(index, val_64); } #if BX_SUPPORT_X86_64 if (! IsCanonical(val_64)) { BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_SYSENTER_EIP !")); return 0; } #endif BX_CPU_THIS_PTR msr.sysenter_eip_msr = val_64; break; #endif #if BX_CPU_LEVEL >= 6 case BX_MSR_MTRRCAP: BX_ERROR(("WRMSR: MTRRCAP is read only MSR")); return 0; case BX_MSR_MTRRPHYSBASE0: case BX_MSR_MTRRPHYSBASE1: case BX_MSR_MTRRPHYSBASE2: case BX_MSR_MTRRPHYSBASE3: case BX_MSR_MTRRPHYSBASE4: case BX_MSR_MTRRPHYSBASE5: case BX_MSR_MTRRPHYSBASE6: case BX_MSR_MTRRPHYSBASE7: if (! IsValidPhyAddr(val_64)) { BX_ERROR(("WRMSR[0x%08x]: attempt to write invalid phy addr to variable range MTRR %08x:%08x", index, val32_hi, val32_lo)); return 0; } // handle 8-11 reserved bits if (! isMemTypeValidMTRR(val32_lo & 0xFFF)) { BX_ERROR(("WRMSR: attempt to write invalid Memory Type to BX_MSR_MTRRPHYSBASE")); return 0; } BX_CPU_THIS_PTR msr.mtrrphys[index - BX_MSR_MTRRPHYSBASE0] = val_64; break; case BX_MSR_MTRRPHYSMASK0: case BX_MSR_MTRRPHYSMASK1: case BX_MSR_MTRRPHYSMASK2: case BX_MSR_MTRRPHYSMASK3: case BX_MSR_MTRRPHYSMASK4: case BX_MSR_MTRRPHYSMASK5: case BX_MSR_MTRRPHYSMASK6: case BX_MSR_MTRRPHYSMASK7: if (! IsValidPhyAddr(val_64)) { BX_ERROR(("WRMSR[0x%08x]: attempt to write invalid phy addr to variable range MTRR %08x:%08x", index, val32_hi, val32_lo)); return 0; } // handle 10-0 reserved bits if (val32_lo & 0x7ff) { BX_ERROR(("WRMSR[0x%08x]: variable range MTRR reserved bits violation %08x:%08x", index, val32_hi, val32_lo)); return 0; } BX_CPU_THIS_PTR msr.mtrrphys[index - BX_MSR_MTRRPHYSBASE0] = val_64; break; case BX_MSR_MTRRFIX64K_00000: if (! isValidMSR_FixedMTRR(val_64)) { BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_MTRRFIX64K_00000 !")); return 0; } BX_CPU_THIS_PTR msr.mtrrfix64k_00000 = val_64; break; case BX_MSR_MTRRFIX16K_80000: case BX_MSR_MTRRFIX16K_A0000: if (! isValidMSR_FixedMTRR(val_64)) { BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_MTRRFIX16K regsiter !")); return 0; } BX_CPU_THIS_PTR msr.mtrrfix16k[index - BX_MSR_MTRRFIX16K_80000] = val_64; break; case BX_MSR_MTRRFIX4K_C0000: case BX_MSR_MTRRFIX4K_C8000: case BX_MSR_MTRRFIX4K_D0000: case BX_MSR_MTRRFIX4K_D8000: case BX_MSR_MTRRFIX4K_E0000: case BX_MSR_MTRRFIX4K_E8000: case BX_MSR_MTRRFIX4K_F0000: case BX_MSR_MTRRFIX4K_F8000: if (! isValidMSR_FixedMTRR(val_64)) { BX_ERROR(("WRMSR: attempt to write invalid Memory Type to fixed memory range MTRR !")); return 0; } BX_CPU_THIS_PTR msr.mtrrfix4k[index - BX_MSR_MTRRFIX4K_C0000] = val_64; break; case BX_MSR_PAT: if (! isValidMSR_PAT(val_64)) { BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_PAT")); return 0; } BX_CPU_THIS_PTR msr.pat = val_64; break; case BX_MSR_MTRR_DEFTYPE: if (! isMemTypeValidMTRR(val32_lo & 0xFF)) { BX_ERROR(("WRMSR: attempt to write invalid Memory Type to MSR_MTRR_DEFTYPE")); return 0; } if (val32_hi || (val32_lo & 0xfffff300)) { BX_ERROR(("WRMSR: attempt to reserved bits in MSR_MTRR_DEFTYPE")); return 0; } BX_CPU_THIS_PTR msr.mtrr_deftype = val32_lo; break; #endif case BX_MSR_TSC: BX_INFO(("WRMSR: write 0x%08x%08x to MSR_TSC", val32_hi, val32_lo)); BX_CPU_THIS_PTR set_TSC(val_64); break; #if BX_SUPPORT_APIC case BX_MSR_APICBASE: return relocate_apic(val_64); #endif #if BX_CPU_LEVEL >= 6 case BX_MSR_TSC_DEADLINE: if (! bx_cpuid_support_tsc_deadline()) { BX_ERROR(("WRMSR BX_MSR_TSC_DEADLINE: TSC-Deadline not enabled !")); return handle_unknown_wrmsr(index, val_64); } BX_CPU_THIS_PTR lapic.set_tsc_deadline(val_64); break; #endif #if BX_SUPPORT_VMX // Support only two bits: lock bit (bit 0) and VMX enable (bit 2) case BX_MSR_IA32_FEATURE_CONTROL: if (BX_CPU_THIS_PTR msr.ia32_feature_ctrl & 0x1) { BX_ERROR(("WRMSR: IA32_FEATURE_CONTROL_MSR VMX lock bit is set !")); return 0; } /* if (val_64 & ~((Bit64u)(BX_IA32_FEATURE_CONTROL_BITS))) { BX_ERROR(("WRMSR: attempt to set reserved bits of IA32_FEATURE_CONTROL_MSR !")); return 0; } */ BX_CPU_THIS_PTR msr.ia32_feature_ctrl = val32_lo; break; case BX_MSR_VMX_BASIC: case BX_MSR_VMX_PINBASED_CTRLS: case BX_MSR_VMX_PROCBASED_CTRLS: case BX_MSR_VMX_PROCBASED_CTRLS2: case BX_MSR_VMX_VMEXIT_CTRLS: case BX_MSR_VMX_VMENTRY_CTRLS: case BX_MSR_VMX_MISC: case BX_MSR_VMX_CR0_FIXED0: case BX_MSR_VMX_CR0_FIXED1: case BX_MSR_VMX_CR4_FIXED0: case BX_MSR_VMX_CR4_FIXED1: case BX_MSR_VMX_VMCS_ENUM: case BX_MSR_VMX_EPT_VPID_CAP: case BX_MSR_VMX_TRUE_PINBASED_CTRLS: case BX_MSR_VMX_TRUE_PROCBASED_CTRLS: case BX_MSR_VMX_TRUE_VMEXIT_CTRLS: case BX_MSR_VMX_TRUE_VMENTRY_CTRLS: case BX_MSR_VMX_VMFUNC: BX_ERROR(("WRMSR: VMX read only MSR")); return 0; #endif #if BX_SUPPORT_SVM case BX_SVM_HSAVE_PA_MSR: if (! bx_cpuid_support_svm()) { BX_ERROR(("WRMSR SVM_HSAVE_PA_MSR: SVM support not enabled !")); return handle_unknown_wrmsr(index, val_64); } if ((val_64 & 0xfff) != 0 || ! IsValidPhyAddr(val_64)) { BX_ERROR(("WRMSR SVM_HSAVE_PA_MSR: invalid or not page aligned physical address !")); } BX_CPU_THIS_PTR msr.svm_hsave_pa = val_64; break; #endif case BX_MSR_EFER: if (! SetEFER(val_64)) return 0; break; case BX_MSR_STAR: if ((BX_CPU_THIS_PTR efer_suppmask & BX_EFER_SCE_MASK) == 0) { BX_ERROR(("RDMSR MSR_STAR: SYSCALL/SYSRET support not enabled !")); return handle_unknown_wrmsr(index, val_64); } MSR_STAR = val_64; break; #if BX_SUPPORT_X86_64 case BX_MSR_LSTAR: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("WRMSR MSR_LSTAR: long mode support not enabled !")); return handle_unknown_wrmsr(index, val_64); } if (! IsCanonical(val_64)) { BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_LSTAR !")); return 0; } MSR_LSTAR = val_64; break; case BX_MSR_CSTAR: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("WRMSR MSR_CSTAR: long mode support not enabled !")); return handle_unknown_wrmsr(index, val_64); } if (! IsCanonical(val_64)) { BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_CSTAR !")); return 0; } MSR_CSTAR = val_64; break; case BX_MSR_FMASK: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("WRMSR MSR_FMASK: long mode support not enabled !")); return handle_unknown_wrmsr(index, val_64); } MSR_FMASK = (Bit32u) val_64; break; case BX_MSR_FSBASE: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("WRMSR MSR_FSBASE: long mode support not enabled !")); return handle_unknown_wrmsr(index, val_64); } if (! IsCanonical(val_64)) { BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_FSBASE !")); return 0; } MSR_FSBASE = val_64; break; case BX_MSR_GSBASE: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("WRMSR MSR_GSBASE: long mode support not enabled !")); return handle_unknown_wrmsr(index, val_64); } if (! IsCanonical(val_64)) { BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_GSBASE !")); return 0; } MSR_GSBASE = val_64; break; case BX_MSR_KERNELGSBASE: if (! bx_cpuid_support_x86_64()) { BX_ERROR(("WRMSR MSR_KERNELGSBASE: long mode support not enabled !")); return handle_unknown_wrmsr(index, val_64); } if (! IsCanonical(val_64)) { BX_ERROR(("WRMSR: attempt to write non-canonical value to MSR_KERNELGSBASE !")); return 0; } MSR_KERNELGSBASE = val_64; break; case BX_MSR_TSC_AUX: if (! bx_cpuid_support_rdtscp()) { BX_ERROR(("WRMSR MSR_TSC_AUX: RTDSCP feature not enabled !")); return handle_unknown_wrmsr(index, val_64); } MSR_TSC_AUX = val32_lo; break; #endif // #if BX_SUPPORT_X86_64 default: return handle_unknown_wrmsr(index, val_64); } return 1; } bx_bool BX_CPP_AttrRegparmN(2) BX_CPU_C::handle_unknown_wrmsr(Bit32u index, Bit64u val_64) { // Try to check cpuid_t first (can implement some MSRs) int result = BX_CPU_THIS_PTR cpuid->wrmsr(index, val_64); if (result == 0) return 0; // #GP fault due to not supported MSR if (result < 0) { // cpuid_t have no idea about this MSR #if BX_CONFIGURE_MSRS if (index < BX_MSR_MAX_INDEX && BX_CPU_THIS_PTR msrs[index]) { if (! BX_CPU_THIS_PTR msrs[index]->set64(val_64)) { BX_ERROR(("WRMSR: Write failed to MSR %#x - #GP fault", index)); return 0; } return 1; } #endif // failed to find the MSR, could #GP or ignore it silently BX_ERROR(("WRMSR: Unknown register %#x", index)); if (! BX_CPU_THIS_PTR ignore_bad_msrs) return 0; // will result in #GP fault due to unknown MSR } return 1; } #endif // BX_CPU_LEVEL >= 5 #if BX_SUPPORT_APIC bx_bool BX_CPU_C::relocate_apic(Bit64u val_64) { /* MSR_APICBASE * [0:7] Reserved * [8] This is set if CPU is BSP * [9] Reserved * [10] X2APIC mode bit (1=enabled 0=disabled) * [11] APIC Global Enable bit (1=enabled 0=disabled) * [12:M] APIC Base Address (physical) * [M:63] Reserved */ #define BX_MSR_APICBASE_RESERVED_BITS (0x2ff | (bx_cpuid_support_x2apic() ? 0 : 0x400)) if (BX_CPU_THIS_PTR msr.apicbase & 0x800) { Bit32u val32_hi = GET32H(val_64), val32_lo = GET32L(val_64); BX_INFO(("WRMSR: wrote %08x:%08x to MSR_APICBASE", val32_hi, val32_lo)); if (! IsValidPhyAddr(val_64)) { BX_ERROR(("relocate_apic: invalid physical address")); return 0; } if (val32_lo & BX_MSR_APICBASE_RESERVED_BITS) { BX_ERROR(("relocate_apic: attempt to set reserved bits")); return 0; } #if BX_CPU_LEVEL >= 6 if (bx_cpuid_support_x2apic()) { unsigned apic_state = (BX_CPU_THIS_PTR msr.apicbase >> 10) & 3; unsigned new_state = (val32_lo >> 10) & 3; if (new_state == BX_APIC_STATE_INVALID) { BX_ERROR(("relocate_apic: attempt to set invalid apic state")); return 0; } if (apic_state == BX_APIC_X2APIC_MODE && new_state != BX_APIC_GLOBALLY_DISABLED) { BX_ERROR(("relocate_apic: attempt to switch from x2apic -> xapic")); return 0; } } #endif BX_CPU_THIS_PTR msr.apicbase = (bx_phy_address) val_64; BX_CPU_THIS_PTR lapic.set_base(BX_CPU_THIS_PTR msr.apicbase); // TLB flush is required for emulation correctness TLB_flush(); // don't care about performance of apic relocation } else { BX_INFO(("WRMSR: MSR_APICBASE APIC global enable bit cleared !")); } return 1; } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::WRMSR(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("WRMSR: CPL != 0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } Bit64u val_64 = ((Bit64u) EDX << 32) | EAX; Bit32u index = ECX; #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_MSR)) SvmInterceptMSR(BX_WRITE, index); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_MSR(VMX_VMEXIT_WRMSR, index); #endif #if BX_SUPPORT_VMX >= 2 if (BX_CPU_THIS_PTR in_vmx_guest && index == 0x808) { if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE)) { VMX_Write_VTPR(AL); BX_NEXT_INSTR(i); } } #endif if (! wrmsr(index, val_64)) exception(BX_GP_EXCEPTION, 0); #endif BX_NEXT_INSTR(i); } #if BX_CONFIGURE_MSRS int BX_CPU_C::load_MSRs(const char *file) { char line[512]; unsigned linenum = 0; Bit32u index, type; Bit32u reset_hi, reset_lo; Bit32u rsrv_hi, rsrv_lo; Bit32u ignr_hi, ignr_lo; FILE *fd = fopen (file, "r"); if (fd == NULL) return -1; int retval = 0; do { linenum++; char* ret = fgets(line, sizeof(line)-1, fd); line[sizeof(line) - 1] = '\0'; size_t len = strlen(line); if (len>0 && line[len-1] < ' ') line[len-1] = '\0'; if (ret != NULL && strlen(line)) { if (line[0] == '#') continue; retval = sscanf(line, "%x %d %08x %08x %08x %08x %08x %08x", &index, &type, &reset_hi, &reset_lo, &rsrv_hi, &rsrv_lo, &ignr_hi, &ignr_lo); if (retval < 8) { retval = -1; BX_PANIC(("%s:%d > error parsing MSRs config file!", file, linenum)); break; // quit parsing after first error } if (index >= BX_MSR_MAX_INDEX) { BX_PANIC(("%s:%d > MSR index is too big !", file, linenum)); continue; } if (BX_CPU_THIS_PTR msrs[index]) { BX_PANIC(("%s:%d > MSR[0x%03x] is already defined!", file, linenum, index)); continue; } if (type > 2) { BX_PANIC(("%s:%d > MSR[0x%03x] unknown type !", file, linenum, index)); continue; } BX_INFO(("loaded MSR[0x%03x] type=%d %08x:%08x %08x:%08x %08x:%08x", index, type, reset_hi, reset_lo, rsrv_hi, rsrv_lo, ignr_hi, ignr_lo)); BX_CPU_THIS_PTR msrs[index] = new MSR(index, type, ((Bit64u)(reset_hi) << 32) | reset_lo, ((Bit64u) (rsrv_hi) << 32) | rsrv_lo, ((Bit64u) (ignr_hi) << 32) | ignr_lo); } } while (!feof(fd)); fclose(fd); return retval; } #endif bochs-2.6/cpu/lazy_flags.h0000644000175000017500000001720212020641453015427 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: lazy_flags.h 11276 2012-07-12 14:51:54Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_LAZY_FLAGS_DEF #define BX_LAZY_FLAGS_DEF #if BX_SUPPORT_X86_64 #define BX_LF_SIGN_BIT 63 #else #define BX_LF_SIGN_BIT 31 #endif typedef struct { bx_address result; bx_address auxbits; } bx_lf_flags_entry; // These are the lazy flags bits in oszapc.auxbits which hold lazy state // of zero flag, adjust flag, carry flag, and overflow flag. #define LF_BIT_SD (0) /* lazy Sign Flag Delta */ #define LF_BIT_AF (3) /* lazy Adjust flag */ #define LF_BIT_PDB (8) /* lazy Parity Delta Byte (8 bits) */ #define LF_BIT_CF (31) /* lazy Carry Flag */ #define LF_BIT_PO (30) /* lazy Partial Overflow = CF ^ OF */ #define LF_MASK_SD (0x01 << LF_BIT_SD) #define LF_MASK_AF (0x01 << LF_BIT_AF) #define LF_MASK_PDB (0xFF << LF_BIT_PDB) #define LF_MASK_CF (0x01 << LF_BIT_CF) #define LF_MASK_PO (0x01 << LF_BIT_PO) #define ADD_COUT_VEC(op1, op2, result) \ (((op1) & (op2)) | (((op1) | (op2)) & (~(result)))) #define SUB_COUT_VEC(op1, op2, result) \ (((~(op1)) & (op2)) | ((~((op1) ^ (op2))) & (result))) #define GET_ADD_OVERFLOW(op1, op2, result, mask) \ ((((op1) ^ (result)) & ((op2) ^ (result))) & (mask)) // ******************* // OSZAPC // ******************* /* size, carries, result */ #define SET_FLAGS_OSZAPC_SIZE(size, lf_carries, lf_result) { \ bx_address temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ BX_CPU_THIS_PTR oszapc.result = (bx_address)(Bit##size##s)(lf_result); \ if ((size) == 32) temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ if ((size) == 16) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ if ((size) == 8) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ BX_CPU_THIS_PTR oszapc.auxbits = (bx_address)(Bit32u)temp; \ } /* carries, result */ #define SET_FLAGS_OSZAPC_8(carries, result) \ SET_FLAGS_OSZAPC_SIZE(8, carries, result) #define SET_FLAGS_OSZAPC_16(carries, result) \ SET_FLAGS_OSZAPC_SIZE(16, carries, result) #define SET_FLAGS_OSZAPC_32(carries, result) \ SET_FLAGS_OSZAPC_SIZE(32, carries, result) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAPC_64(carries, result) \ SET_FLAGS_OSZAPC_SIZE(64, carries, result) #endif /* result */ #define SET_FLAGS_OSZAPC_LOGIC_8(result_8) \ SET_FLAGS_OSZAPC_8(0, (result_8)) #define SET_FLAGS_OSZAPC_LOGIC_16(result_16) \ SET_FLAGS_OSZAPC_16(0, (result_16)) #define SET_FLAGS_OSZAPC_LOGIC_32(result_32) \ SET_FLAGS_OSZAPC_32(0, (result_32)) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAPC_LOGIC_64(result_64) \ SET_FLAGS_OSZAPC_64(BX_CONST64(0), (result_64)) #endif /* op1, op2, result */ #define SET_FLAGS_OSZAPC_ADD_8(op1_8, op2_8, sum_8) \ SET_FLAGS_OSZAPC_8(ADD_COUT_VEC((op1_8), (op2_8), (sum_8)), (sum_8)) #define SET_FLAGS_OSZAPC_ADD_16(op1_16, op2_16, sum_16) \ SET_FLAGS_OSZAPC_16(ADD_COUT_VEC((op1_16), (op2_16), (sum_16)), (sum_16)) #define SET_FLAGS_OSZAPC_ADD_32(op1_32, op2_32, sum_32) \ SET_FLAGS_OSZAPC_32(ADD_COUT_VEC((op1_32), (op2_32), (sum_32)), (sum_32)) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAPC_ADD_64(op1_64, op2_64, sum_64) \ SET_FLAGS_OSZAPC_64(ADD_COUT_VEC((op1_64), (op2_64), (sum_64)), (sum_64)) #endif /* op1, op2, result */ #define SET_FLAGS_OSZAPC_SUB_8(op1_8, op2_8, diff_8) \ SET_FLAGS_OSZAPC_8(SUB_COUT_VEC((op1_8), (op2_8), (diff_8)), (diff_8)) #define SET_FLAGS_OSZAPC_SUB_16(op1_16, op2_16, diff_16) \ SET_FLAGS_OSZAPC_16(SUB_COUT_VEC((op1_16), (op2_16), (diff_16)), (diff_16)) #define SET_FLAGS_OSZAPC_SUB_32(op1_32, op2_32, diff_32) \ SET_FLAGS_OSZAPC_32(SUB_COUT_VEC((op1_32), (op2_32), (diff_32)), (diff_32)) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAPC_SUB_64(op1_64, op2_64, diff_64) \ SET_FLAGS_OSZAPC_64(SUB_COUT_VEC((op1_64), (op2_64), (diff_64)), (diff_64)) #endif // ******************* // OSZAP // ******************* /* size, carries, result */ #define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \ bx_address temp = ((lf_carries) & (LF_MASK_AF)) | \ (((lf_carries) >> (size - 2)) << LF_BIT_PO); \ if ((size) == 32) temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \ if ((size) == 16) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \ if ((size) == 8) temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 24); \ BX_CPU_THIS_PTR oszapc.result = (bx_address)(Bit##size##s)(lf_result); \ bx_address delta_c = (BX_CPU_THIS_PTR oszapc.auxbits ^ temp) & LF_MASK_CF; \ delta_c ^= (delta_c >> 1); \ BX_CPU_THIS_PTR oszapc.auxbits = (bx_address)(Bit32u)(temp ^ delta_c); \ } /* carries, result */ #define SET_FLAGS_OSZAP_8(carries, result) \ SET_FLAGS_OSZAP_SIZE(8, carries, result) #define SET_FLAGS_OSZAP_16(carries, result) \ SET_FLAGS_OSZAP_SIZE(16, carries, result) #define SET_FLAGS_OSZAP_32(carries, result) \ SET_FLAGS_OSZAP_SIZE(32, carries, result) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAP_64(carries, result) \ SET_FLAGS_OSZAP_SIZE(64, carries, result) #endif /* op1, op2, result */ #define SET_FLAGS_OSZAP_ADD_8(op1_8, op2_8, sum_8) \ SET_FLAGS_OSZAP_8(ADD_COUT_VEC((op1_8), (op2_8), (sum_8)), (sum_8)) #define SET_FLAGS_OSZAP_ADD_16(op1_16, op2_16, sum_16) \ SET_FLAGS_OSZAP_16(ADD_COUT_VEC((op1_16), (op2_16), (sum_16)), (sum_16)) #define SET_FLAGS_OSZAP_ADD_32(op1_32, op2_32, sum_32) \ SET_FLAGS_OSZAP_32(ADD_COUT_VEC((op1_32), (op2_32), (sum_32)), (sum_32)) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAP_ADD_64(op1_64, op2_64, sum_64) \ SET_FLAGS_OSZAP_64(ADD_COUT_VEC((op1_64), (op2_64), (sum_64)), (sum_64)) #endif /* op1, op2, result */ #define SET_FLAGS_OSZAP_SUB_8(op1_8, op2_8, diff_8) \ SET_FLAGS_OSZAP_8(SUB_COUT_VEC((op1_8), (op2_8), (diff_8)), (diff_8)) #define SET_FLAGS_OSZAP_SUB_16(op1_16, op2_16, diff_16) \ SET_FLAGS_OSZAP_16(SUB_COUT_VEC((op1_16), (op2_16), (diff_16)), (diff_16)) #define SET_FLAGS_OSZAP_SUB_32(op1_32, op2_32, diff_32) \ SET_FLAGS_OSZAP_32(SUB_COUT_VEC((op1_32), (op2_32), (diff_32)), (diff_32)) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAP_SUB_64(op1_64, op2_64, diff_64) \ SET_FLAGS_OSZAP_64(SUB_COUT_VEC((op1_64), (op2_64), (diff_64)), (diff_64)) #endif // ******************* // OSZAxC // ******************* /* size, carries, result */ #define SET_FLAGS_OSZAxC_LOGIC_SIZE(size, lf_result) { \ bx_bool saved_PF = getB_PF(); \ SET_FLAGS_OSZAPC_SIZE(size, (Bit##size##u)(0), lf_result); \ set_PF(saved_PF); \ } /* result */ #define SET_FLAGS_OSZAxC_LOGIC_32(result_32) \ SET_FLAGS_OSZAxC_LOGIC_SIZE(32, (result_32)) #if BX_SUPPORT_X86_64 #define SET_FLAGS_OSZAxC_LOGIC_64(result_64) \ SET_FLAGS_OSZAxC_LOGIC_SIZE(64, (result_64)) #endif #endif // BX_LAZY_FLAGS_DEF bochs-2.6/cpu/call_far.cc0000644000175000017500000005050412020641453015177 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: call_far.cc 11106 2012-03-25 11:54:32Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2005-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(3) BX_CPU_C::call_protected(bxInstruction_c *i, Bit16u cs_raw, bx_address disp) { bx_selector_t cs_selector; Bit32u dword1, dword2; bx_descriptor_t cs_descriptor; /* new cs selector must not be null, else #GP(0) */ if ((cs_raw & 0xfffc) == 0) { BX_ERROR(("call_protected: CS selector null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(cs_raw, &cs_selector); // check new CS selector index within its descriptor limits, // else #GP(new CS selector) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // examine AR byte of selected descriptor for various legal values if (cs_descriptor.valid==0) { BX_ERROR(("call_protected: invalid CS descriptor")); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } if (cs_descriptor.segment) // normal segment { check_cs(&cs_descriptor, cs_raw, BX_SELECTOR_RPL(cs_raw), CPL); #if BX_SUPPORT_X86_64 if (long_mode() && cs_descriptor.u.segment.l) { Bit64u temp_rsp = RSP; // moving to long mode, push return address onto 64-bit stack if (i->os64L()) { write_new_stack_qword_64(temp_rsp - 8, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); write_new_stack_qword_64(temp_rsp - 16, cs_descriptor.dpl, RIP); temp_rsp -= 16; } else if (i->os32L()) { write_new_stack_dword_64(temp_rsp - 4, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); write_new_stack_dword_64(temp_rsp - 8, cs_descriptor.dpl, EIP); temp_rsp -= 8; } else { write_new_stack_word_64(temp_rsp - 2, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); write_new_stack_word_64(temp_rsp - 4, cs_descriptor.dpl, IP); temp_rsp -= 4; } // load code segment descriptor into CS cache // load CS with new code segment selector // set RPL of CS to CPL branch_far64(&cs_selector, &cs_descriptor, disp, CPL); RSP = temp_rsp; } else #endif { Bit32u temp_RSP; // moving to legacy mode, push return address onto 32-bit stack if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) temp_RSP = ESP; else temp_RSP = SP; #if BX_SUPPORT_X86_64 if (i->os64L()) { write_new_stack_qword_32(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], temp_RSP - 8, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); write_new_stack_qword_32(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], temp_RSP - 16, cs_descriptor.dpl, RIP); temp_RSP -= 16; } else #endif if (i->os32L()) { write_new_stack_dword_32(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], temp_RSP - 4, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); write_new_stack_dword_32(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], temp_RSP - 8, cs_descriptor.dpl, EIP); temp_RSP -= 8; } else { write_new_stack_word_32(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], temp_RSP - 2, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); write_new_stack_word_32(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], temp_RSP - 4, cs_descriptor.dpl, IP); temp_RSP -= 4; } // load code segment descriptor into CS cache // load CS with new code segment selector // set RPL of CS to CPL branch_far64(&cs_selector, &cs_descriptor, disp, CPL); if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) ESP = (Bit32u) temp_RSP; else SP = (Bit16u) temp_RSP; } return; } else { // gate & special segment bx_descriptor_t gate_descriptor = cs_descriptor; bx_selector_t gate_selector = cs_selector; // descriptor DPL must be >= CPL else #GP(gate selector) if (gate_descriptor.dpl < CPL) { BX_ERROR(("call_protected: descriptor.dpl < CPL")); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } // descriptor DPL must be >= gate selector RPL else #GP(gate selector) if (gate_descriptor.dpl < gate_selector.rpl) { BX_ERROR(("call_protected: descriptor.dpl < selector.rpl")); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } #if BX_SUPPORT_X86_64 if (long_mode()) { // call gate type is higher priority than non-present bit check if (gate_descriptor.type != BX_386_CALL_GATE) { BX_ERROR(("call_protected: gate type %u unsupported in long mode", (unsigned) gate_descriptor.type)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } // gate descriptor must be present else #NP(gate selector) if (! IS_PRESENT(gate_descriptor)) { BX_ERROR(("call_protected: call gate not present")); exception(BX_NP_EXCEPTION, cs_raw & 0xfffc); } call_gate64(&gate_selector); return; } #endif switch (gate_descriptor.type) { case BX_SYS_SEGMENT_AVAIL_286_TSS: case BX_SYS_SEGMENT_AVAIL_386_TSS: if (gate_descriptor.type==BX_SYS_SEGMENT_AVAIL_286_TSS) BX_DEBUG(("call_protected: 16bit available TSS")); else BX_DEBUG(("call_protected: 32bit available TSS")); if (gate_descriptor.valid==0 || gate_selector.ti) { BX_ERROR(("call_protected: call bad TSS selector !")); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } // TSS must be present, else #NP(TSS selector) if (! IS_PRESENT(gate_descriptor)) { BX_ERROR(("call_protected: call not present TSS !")); exception(BX_NP_EXCEPTION, cs_raw & 0xfffc); } // SWITCH_TASKS _without_ nesting to TSS task_switch(i, &gate_selector, &gate_descriptor, BX_TASK_FROM_CALL, dword1, dword2); return; case BX_TASK_GATE: task_gate(i, &gate_selector, &gate_descriptor, BX_TASK_FROM_CALL); return; case BX_286_CALL_GATE: case BX_386_CALL_GATE: // gate descriptor must be present else #NP(gate selector) if (! IS_PRESENT(gate_descriptor)) { BX_ERROR(("call_protected: gate not present")); exception(BX_NP_EXCEPTION, cs_raw & 0xfffc); } call_gate(&gate_descriptor); return; default: // can't get here BX_ERROR(("call_protected(): gate.type(%u) unsupported", (unsigned) gate_descriptor.type)); exception(BX_GP_EXCEPTION, cs_raw & 0xfffc); } } } void BX_CPP_AttrRegparmN(1) BX_CPU_C::call_gate(bx_descriptor_t *gate_descriptor) { bx_selector_t cs_selector; Bit32u dword1, dword2; bx_descriptor_t cs_descriptor; // examine code segment selector in call gate descriptor BX_DEBUG(("call_protected: call gate")); Bit16u dest_selector = gate_descriptor->u.gate.dest_selector; Bit32u new_EIP = gate_descriptor->u.gate.dest_offset; // selector must not be null else #GP(0) if ((dest_selector & 0xfffc) == 0) { BX_ERROR(("call_protected: selector in gate null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(dest_selector, &cs_selector); // selector must be within its descriptor table limits, // else #GP(code segment selector) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // AR byte of selected descriptor must indicate code segment, // else #GP(code segment selector) // DPL of selected descriptor must be <= CPL, // else #GP(code segment selector) if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || IS_DATA_SEGMENT(cs_descriptor.type) || cs_descriptor.dpl > CPL) { BX_ERROR(("call_protected: selected descriptor is not code")); exception(BX_GP_EXCEPTION, dest_selector & 0xfffc); } // code segment must be present else #NP(selector) if (! IS_PRESENT(cs_descriptor)) { BX_ERROR(("call_protected: code segment not present !")); exception(BX_NP_EXCEPTION, dest_selector & 0xfffc); } // CALL GATE TO MORE PRIVILEGE // if non-conforming code segment and DPL < CPL then if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && (cs_descriptor.dpl < CPL)) { Bit16u SS_for_cpl_x; Bit32u ESP_for_cpl_x; bx_selector_t ss_selector; bx_descriptor_t ss_descriptor; Bit16u return_SS, return_CS; Bit32u return_ESP, return_EIP; BX_DEBUG(("CALL GATE TO MORE PRIVILEGE LEVEL")); // get new SS selector for new privilege level from TSS get_SS_ESP_from_TSS(cs_descriptor.dpl, &SS_for_cpl_x, &ESP_for_cpl_x); // check selector & descriptor for new SS: // selector must not be null, else #TS(0) if ((SS_for_cpl_x & 0xfffc) == 0) { BX_ERROR(("call_protected: new SS null")); exception(BX_TS_EXCEPTION, 0); } // selector index must be within its descriptor table limits, // else #TS(SS selector) parse_selector(SS_for_cpl_x, &ss_selector); fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_TS_EXCEPTION); parse_descriptor(dword1, dword2, &ss_descriptor); // selector's RPL must equal DPL of code segment, // else #TS(SS selector) if (ss_selector.rpl != cs_descriptor.dpl) { BX_ERROR(("call_protected: SS selector.rpl != CS descr.dpl")); exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // stack segment DPL must equal DPL of code segment, // else #TS(SS selector) if (ss_descriptor.dpl != cs_descriptor.dpl) { BX_ERROR(("call_protected: SS descr.rpl != CS descr.dpl")); exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // descriptor must indicate writable data segment, // else #TS(SS selector) if (ss_descriptor.valid==0 || ss_descriptor.segment==0 || IS_CODE_SEGMENT(ss_descriptor.type) || !IS_DATA_SEGMENT_WRITEABLE(ss_descriptor.type)) { BX_ERROR(("call_protected: ss descriptor is not writable data seg")); exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // segment must be present, else #SS(SS selector) if (! IS_PRESENT(ss_descriptor)) { BX_ERROR(("call_protected: ss descriptor not present")); exception(BX_SS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // get word count from call gate, mask to 5 bits unsigned param_count = gate_descriptor->u.gate.param_count & 0x1f; // save return SS:eSP to be pushed on new stack return_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) return_ESP = ESP; else return_ESP = SP; // save return CS:eIP to be pushed on new stack return_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value; if (cs_descriptor.u.segment.d_b) return_EIP = EIP; else return_EIP = IP; // Prepare new stack segment bx_segment_reg_t new_stack; new_stack.selector = ss_selector; new_stack.cache = ss_descriptor; new_stack.selector.rpl = cs_descriptor.dpl; // add cpl to the selector value new_stack.selector.value = (0xfffc & new_stack.selector.value) | new_stack.selector.rpl; /* load new SS:SP value from TSS */ if (ss_descriptor.u.segment.d_b) { Bit32u temp_ESP = ESP_for_cpl_x; // push pointer of old stack onto new stack if (gate_descriptor->type==BX_386_CALL_GATE) { write_new_stack_dword_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, return_SS); write_new_stack_dword_32(&new_stack, temp_ESP-8, cs_descriptor.dpl, return_ESP); temp_ESP -= 8; for (unsigned n=param_count; n>0; n--) { temp_ESP -= 4; Bit32u param = stack_read_dword(return_ESP + (n-1)*4); write_new_stack_dword_32(&new_stack, temp_ESP, cs_descriptor.dpl, param); } // push return address onto new stack write_new_stack_dword_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, return_CS); write_new_stack_dword_32(&new_stack, temp_ESP-8, cs_descriptor.dpl, return_EIP); temp_ESP -= 8; } else { write_new_stack_word_32(&new_stack, temp_ESP-2, cs_descriptor.dpl, return_SS); write_new_stack_word_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, (Bit16u) return_ESP); temp_ESP -= 4; for (unsigned n=param_count; n>0; n--) { temp_ESP -= 2; Bit16u param = stack_read_word(return_ESP + (n-1)*2); write_new_stack_word_32(&new_stack, temp_ESP, cs_descriptor.dpl, param); } // push return address onto new stack write_new_stack_word_32(&new_stack, temp_ESP-2, cs_descriptor.dpl, return_CS); write_new_stack_word_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, (Bit16u) return_EIP); temp_ESP -= 4; } ESP = temp_ESP; } else { Bit16u temp_SP = (Bit16u) ESP_for_cpl_x; // push pointer of old stack onto new stack if (gate_descriptor->type==BX_386_CALL_GATE) { write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, return_SS); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-8), cs_descriptor.dpl, return_ESP); temp_SP -= 8; for (unsigned n=param_count; n>0; n--) { temp_SP -= 4; Bit32u param = stack_read_dword(return_ESP + (n-1)*4); write_new_stack_dword_32(&new_stack, temp_SP, cs_descriptor.dpl, param); } // push return address onto new stack write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, return_CS); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-8), cs_descriptor.dpl, return_EIP); temp_SP -= 8; } else { write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-2), cs_descriptor.dpl, return_SS); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, (Bit16u) return_ESP); temp_SP -= 4; for (unsigned n=param_count; n>0; n--) { temp_SP -= 2; Bit16u param = stack_read_word(return_ESP + (n-1)*2); write_new_stack_word_32(&new_stack, temp_SP, cs_descriptor.dpl, param); } // push return address onto new stack write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-2), cs_descriptor.dpl, return_CS); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, (Bit16u) return_EIP); temp_SP -= 4; } SP = temp_SP; } // new eIP must be in code segment limit else #GP(0) if (new_EIP > cs_descriptor.u.segment.limit_scaled) { BX_ERROR(("call_protected: EIP not within CS limits")); exception(BX_GP_EXCEPTION, 0); } /* load SS descriptor */ load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl); /* load new CS:IP value from gate */ /* load CS descriptor */ /* set CPL to stack segment DPL */ /* set RPL of CS to CPL */ load_cs(&cs_selector, &cs_descriptor, cs_descriptor.dpl); EIP = new_EIP; } else // CALL GATE TO SAME PRIVILEGE { BX_DEBUG(("CALL GATE TO SAME PRIVILEGE")); if (gate_descriptor->type == BX_386_CALL_GATE) { // call gate 32bit, push return address onto stack push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_32(EIP); } else { // call gate 16bit, push return address onto stack push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_16(IP); } // load CS:EIP from gate // load code segment descriptor into CS register // set RPL of CS to CPL branch_far32(&cs_selector, &cs_descriptor, new_EIP, CPL); } } #if BX_SUPPORT_X86_64 void BX_CPP_AttrRegparmN(1) BX_CPU_C::call_gate64(bx_selector_t *gate_selector) { bx_selector_t cs_selector; Bit32u dword1, dword2, dword3; bx_descriptor_t cs_descriptor; bx_descriptor_t gate_descriptor; // examine code segment selector in call gate descriptor BX_DEBUG(("call_gate64: CALL 64bit call gate")); fetch_raw_descriptor_64(gate_selector, &dword1, &dword2, &dword3, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &gate_descriptor); Bit16u dest_selector = gate_descriptor.u.gate.dest_selector; // selector must not be null else #GP(0) if ((dest_selector & 0xfffc) == 0) { BX_ERROR(("call_gate64: selector in gate null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(dest_selector, &cs_selector); // selector must be within its descriptor table limits, // else #GP(code segment selector) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // find the RIP in the gate_descriptor Bit64u new_RIP = gate_descriptor.u.gate.dest_offset; new_RIP |= ((Bit64u)dword3 << 32); // AR byte of selected descriptor must indicate code segment, // else #GP(code segment selector) // DPL of selected descriptor must be <= CPL, // else #GP(code segment selector) if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || IS_DATA_SEGMENT(cs_descriptor.type) || cs_descriptor.dpl > CPL) { BX_ERROR(("call_gate64: selected descriptor is not code")); exception(BX_GP_EXCEPTION, dest_selector & 0xfffc); } // In long mode, only 64-bit call gates are allowed, and they must point // to 64-bit code segments, else #GP(selector) if (! IS_LONG64_SEGMENT(cs_descriptor) || cs_descriptor.u.segment.d_b) { BX_ERROR(("call_gate64: not 64-bit code segment in call gate 64")); exception(BX_GP_EXCEPTION, dest_selector & 0xfffc); } // code segment must be present else #NP(selector) if (! IS_PRESENT(cs_descriptor)) { BX_ERROR(("call_gate64: code segment not present !")); exception(BX_NP_EXCEPTION, dest_selector & 0xfffc); } Bit64u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value; Bit64u old_RIP = RIP; // CALL GATE TO MORE PRIVILEGE // if non-conforming code segment and DPL < CPL then if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && (cs_descriptor.dpl < CPL)) { BX_DEBUG(("CALL GATE TO MORE PRIVILEGE LEVEL")); // get new RSP for new privilege level from TSS Bit64u RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl); Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value; Bit64u old_RSP = RSP; // push old stack long pointer onto new stack write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS); write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP); // push long pointer to return address onto new stack write_new_stack_qword_64(RSP_for_cpl_x - 24, cs_descriptor.dpl, old_CS); write_new_stack_qword_64(RSP_for_cpl_x - 32, cs_descriptor.dpl, old_RIP); RSP_for_cpl_x -= 32; // load CS:RIP (guaranteed to be in 64 bit mode) branch_far64(&cs_selector, &cs_descriptor, new_RIP, cs_descriptor.dpl); // set up null SS descriptor load_null_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], cs_descriptor.dpl); RSP = RSP_for_cpl_x; } else { BX_DEBUG(("CALL GATE TO SAME PRIVILEGE")); // push to 64-bit stack, switch to long64 guaranteed write_new_stack_qword_64(RSP - 8, CPL, old_CS); write_new_stack_qword_64(RSP - 16, CPL, old_RIP); // load CS:RIP (guaranteed to be in 64 bit mode) branch_far64(&cs_selector, &cs_descriptor, new_RIP, CPL); RSP -= 16; } } #endif bochs-2.6/cpu/fetchdecode.cc0000644000175000017500000024472012020641453015676 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fetchdecode.cc 11356 2012-08-21 19:58:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR /////////////////////////// // prefix bytes // opcode bytes // modrm/sib // address displacement // immediate constant /////////////////////////// #define X 0 /* undefined opcode */ static const Bit8u BxOpcodeHasModrm32[512] = { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /* ------------------------------- */ /* 00 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,X, /* 10 */ 1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0, /* 20 */ 1,1,1,1,0,0,X,0,1,1,1,1,0,0,X,0, /* 30 */ 1,1,1,1,0,0,X,0,1,1,1,1,0,0,X,0, /* 40 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ 0,0,1,1,X,X,X,X,0,1,0,1,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* D0 */ 1,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1, /* E0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* F0 */ X,0,X,X,0,0,1,1,0,0,0,0,0,0,1,1, /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /* ------------------------------- */ 1,1,1,1,X,0,0,0,0,0,X,0,X,1,0,1, /* 0F 00 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 10 */ 1,1,1,1,1,X,1,X,1,1,1,1,1,1,1,1, /* 0F 20 */ 0,0,0,0,0,0,X,X,1,X,1,X,X,X,X,X, /* 0F 30 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 60 */ 1,1,1,1,1,1,1,0,1,1,X,X,1,1,1,1, /* 0F 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0F 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 90 */ 0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1, /* 0F A0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F B0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 0F C0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F D0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F E0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,X /* 0F F0 */ /* ------------------------------- */ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ }; #undef X // Some info on the opcodes at {0F A6} and {0F A7} // // On 386 steps A0-B0: // {OF A6} = XBTS // {OF A7} = IBTS // On 486 steps A0-B0: // {OF A6} = CMPXCHG 8 // {OF A7} = CMPXCHG 16|32 // // On 486 >= B steps, and further processors, the // CMPXCHG instructions were moved to opcodes: // {OF B0} = CMPXCHG 8 // {OF B1} = CMPXCHG 16|32 static unsigned Resolve16BaseReg[8] = { BX_16BIT_REG_BX, BX_16BIT_REG_BX, BX_16BIT_REG_BP, BX_16BIT_REG_BP, BX_16BIT_REG_SI, BX_16BIT_REG_DI, BX_16BIT_REG_BP, BX_16BIT_REG_BX }; static unsigned Resolve16IndexReg[8] = { BX_16BIT_REG_SI, BX_16BIT_REG_DI, BX_16BIT_REG_SI, BX_16BIT_REG_DI, BX_NIL_REGISTER, BX_NIL_REGISTER, BX_NIL_REGISTER, BX_NIL_REGISTER }; // decoding instructions; accessing seg reg's by index static unsigned sreg_mod00_rm16[8] = { BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_SS, BX_SEG_REG_SS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS }; static unsigned sreg_mod01or10_rm16[8] = { BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_SS, BX_SEG_REG_SS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_SS, BX_SEG_REG_DS }; // decoding instructions; accessing seg reg's by index static unsigned sreg_mod0_base32[8] = { BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_SS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS }; static unsigned sreg_mod1or2_base32[8] = { BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_SS, BX_SEG_REG_SS, BX_SEG_REG_DS, BX_SEG_REG_DS }; // common fetchdecode32/64 opcode tables #include "fetchdecode.h" // table of all Bochs opcodes bxIAOpcodeTable BxOpcodesTable[] = { #define bx_define_opcode(a, b, c, d, s1, s2, s3, s4, e) { b, c, { s1, s2, s3, (s4) | (e) } }, #include "ia_opcodes.h" }; #undef bx_define_opcode /* ************************** */ /* 512 entries for 16bit mode */ /* 512 entries for 32bit mode */ /* ************************** */ static const BxOpcodeInfo_t BxOpcodeInfo32[512*2] = { // 512 entries for 16bit mode /* 00 /w */ { BxLockable, BX_IA_ADD_EbGb }, /* 01 /w */ { BxLockable, BX_IA_ADD_EwGw }, /* 02 /w */ { 0, BX_IA_ADD_GbEb }, /* 03 /w */ { 0, BX_IA_ADD_GwEw }, /* 04 /w */ { BxImmediate_Ib, BX_IA_ADD_ALIb }, /* 05 /w */ { BxImmediate_Iw, BX_IA_ADD_AXIw }, /* 06 /w */ { 0, BX_IA_PUSH16_ES }, /* 07 /w */ { 0, BX_IA_POP16_ES }, /* 08 /w */ { BxLockable, BX_IA_OR_EbGb }, /* 09 /w */ { BxLockable, BX_IA_OR_EwGw }, /* 0A /w */ { 0, BX_IA_OR_GbEb }, /* 0B /w */ { 0, BX_IA_OR_GwEw }, /* 0C /w */ { BxImmediate_Ib, BX_IA_OR_ALIb }, /* 0D /w */ { BxImmediate_Iw, BX_IA_OR_AXIw }, /* 0E /w */ { 0, BX_IA_PUSH16_CS }, /* 0F /w */ { 0, BX_IA_ERROR }, // 2-byte escape /* 10 /w */ { BxLockable, BX_IA_ADC_EbGb }, /* 11 /w */ { BxLockable, BX_IA_ADC_EwGw }, /* 12 /w */ { 0, BX_IA_ADC_GbEb }, /* 13 /w */ { 0, BX_IA_ADC_GwEw }, /* 14 /w */ { BxImmediate_Ib, BX_IA_ADC_ALIb }, /* 15 /w */ { BxImmediate_Iw, BX_IA_ADC_AXIw }, /* 16 /w */ { 0, BX_IA_PUSH16_SS }, /* 17 /w */ { 0, BX_IA_POP16_SS }, /* 18 /w */ { BxLockable, BX_IA_SBB_EbGb }, /* 19 /w */ { BxLockable, BX_IA_SBB_EwGw }, /* 1A /w */ { 0, BX_IA_SBB_GbEb }, /* 1B /w */ { 0, BX_IA_SBB_GwEw }, /* 1C /w */ { BxImmediate_Ib, BX_IA_SBB_ALIb }, /* 1D /w */ { BxImmediate_Iw, BX_IA_SBB_AXIw }, /* 1E /w */ { 0, BX_IA_PUSH16_DS }, /* 1F /w */ { 0, BX_IA_POP16_DS }, /* 20 /w */ { BxLockable, BX_IA_AND_EbGb }, /* 21 /w */ { BxLockable, BX_IA_AND_EwGw }, /* 22 /w */ { 0, BX_IA_AND_GbEb }, /* 23 /w */ { 0, BX_IA_AND_GwEw }, /* 24 /w */ { BxImmediate_Ib, BX_IA_AND_ALIb }, /* 25 /w */ { BxImmediate_Iw, BX_IA_AND_AXIw }, /* 26 /w */ { 0, BX_IA_ERROR }, // ES: /* 27 /w */ { 0, BX_IA_DAA }, /* 28 /w */ { BxLockable, BX_IA_SUB_EbGb }, /* 29 /w */ { BxLockable, BX_IA_SUB_EwGw }, /* 2A /w */ { 0, BX_IA_SUB_GbEb }, /* 2B /w */ { 0, BX_IA_SUB_GwEw }, /* 2C /w */ { BxImmediate_Ib, BX_IA_SUB_ALIb }, /* 2D /w */ { BxImmediate_Iw, BX_IA_SUB_AXIw }, /* 2E /w */ { 0, BX_IA_ERROR }, // CS: /* 2F /w */ { 0, BX_IA_DAS }, /* 30 /w */ { BxLockable, BX_IA_XOR_EbGb }, /* 31 /w */ { BxLockable, BX_IA_XOR_EwGw }, /* 32 /w */ { 0, BX_IA_XOR_GbEb }, /* 33 /w */ { 0, BX_IA_XOR_GwEw }, /* 34 /w */ { BxImmediate_Ib, BX_IA_XOR_ALIb }, /* 35 /w */ { BxImmediate_Iw, BX_IA_XOR_AXIw }, /* 36 /w */ { 0, BX_IA_ERROR }, // SS: /* 37 /w */ { 0, BX_IA_AAA }, /* 38 /w */ { 0, BX_IA_CMP_EbGb }, /* 39 /w */ { 0, BX_IA_CMP_EwGw }, /* 3A /w */ { 0, BX_IA_CMP_GbEb }, /* 3B /w */ { 0, BX_IA_CMP_GwEw }, /* 3C /w */ { BxImmediate_Ib, BX_IA_CMP_ALIb }, /* 3D /w */ { BxImmediate_Iw, BX_IA_CMP_AXIw }, /* 3E /w */ { 0, BX_IA_ERROR }, // DS: /* 3F /w */ { 0, BX_IA_AAS }, /* 40 /w */ { 0, BX_IA_INC_RX }, /* 41 /w */ { 0, BX_IA_INC_RX }, /* 42 /w */ { 0, BX_IA_INC_RX }, /* 43 /w */ { 0, BX_IA_INC_RX }, /* 44 /w */ { 0, BX_IA_INC_RX }, /* 45 /w */ { 0, BX_IA_INC_RX }, /* 46 /w */ { 0, BX_IA_INC_RX }, /* 47 /w */ { 0, BX_IA_INC_RX }, /* 48 /w */ { 0, BX_IA_DEC_RX }, /* 49 /w */ { 0, BX_IA_DEC_RX }, /* 4A /w */ { 0, BX_IA_DEC_RX }, /* 4B /w */ { 0, BX_IA_DEC_RX }, /* 4C /w */ { 0, BX_IA_DEC_RX }, /* 4D /w */ { 0, BX_IA_DEC_RX }, /* 4E /w */ { 0, BX_IA_DEC_RX }, /* 4F /w */ { 0, BX_IA_DEC_RX }, /* 50 /w */ { 0, BX_IA_PUSH_RX }, /* 51 /w */ { 0, BX_IA_PUSH_RX }, /* 52 /w */ { 0, BX_IA_PUSH_RX }, /* 53 /w */ { 0, BX_IA_PUSH_RX }, /* 54 /w */ { 0, BX_IA_PUSH_RX }, /* 55 /w */ { 0, BX_IA_PUSH_RX }, /* 56 /w */ { 0, BX_IA_PUSH_RX }, /* 57 /w */ { 0, BX_IA_PUSH_RX }, /* 58 /w */ { 0, BX_IA_POP_RX }, /* 59 /w */ { 0, BX_IA_POP_RX }, /* 5A /w */ { 0, BX_IA_POP_RX }, /* 5B /w */ { 0, BX_IA_POP_RX }, /* 5C /w */ { 0, BX_IA_POP_RX }, /* 5D /w */ { 0, BX_IA_POP_RX }, /* 5E /w */ { 0, BX_IA_POP_RX }, /* 5F /w */ { 0, BX_IA_POP_RX }, /* 60 /w */ { 0, BX_IA_PUSHAD16 }, /* 61 /w */ { 0, BX_IA_POPAD16 }, /* 62 /w */ { 0, BX_IA_BOUND_GwMa }, /* 63 /w */ { 0, BX_IA_ARPL_EwGw }, /* 64 /w */ { 0, BX_IA_ERROR }, // FS: /* 65 /w */ { 0, BX_IA_ERROR }, // GS: /* 66 /w */ { 0, BX_IA_ERROR }, // OS: /* 67 /w */ { 0, BX_IA_ERROR }, // AS: /* 68 /w */ { BxImmediate_Iw, BX_IA_PUSH_Iw }, /* 69 /w */ { BxImmediate_Iw, BX_IA_IMUL_GwEwIw }, /* 6A /w */ { BxImmediate_Ib_SE, BX_IA_PUSH_Iw }, /* 6B /w */ { BxImmediate_Ib_SE, BX_IA_IMUL_GwEwIw }, /* 6C /w */ { BxRepeatable, BX_IA_REP_INSB_YbDX }, /* 6D /w */ { BxRepeatable, BX_IA_REP_INSW_YwDX }, /* 6E /w */ { BxRepeatable, BX_IA_REP_OUTSB_DXXb }, /* 6F /w */ { BxRepeatable, BX_IA_REP_OUTSW_DXXw }, /* 70 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JO_Jw }, /* 71 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNO_Jw }, /* 72 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JB_Jw }, /* 73 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNB_Jw }, /* 74 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JZ_Jw }, /* 75 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNZ_Jw }, /* 76 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JBE_Jw }, /* 77 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNBE_Jw }, /* 78 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JS_Jw }, /* 79 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNS_Jw }, /* 7A /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JP_Jw }, /* 7B /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNP_Jw }, /* 7C /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JL_Jw }, /* 7D /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNL_Jw }, /* 7E /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JLE_Jw }, /* 7F /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNLE_Jw }, /* 80 /w */ { BxGroup1 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG1EbIb }, /* 81 /w */ { BxGroup1 | BxImmediate_Iw, BX_IA_ERROR, BxOpcodeInfoG1Ew }, /* 82 /w */ { BxGroup1 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG1EbIb }, /* 83 /w */ { BxGroup1 | BxImmediate_Ib_SE, BX_IA_ERROR, BxOpcodeInfoG1Ew }, /* 84 /w */ { 0, BX_IA_TEST_EbGb }, /* 85 /w */ { 0, BX_IA_TEST_EwGw }, /* 86 /w */ { BxLockable, BX_IA_XCHG_EbGb }, /* 87 /w */ { BxLockable, BX_IA_XCHG_EwGw }, /* 88 /w */ { 0, BX_IA_MOV_EbGb }, /* 89 /w */ { 0, BX_IA_MOV_EwGw }, /* 8A /w */ { 0, BX_IA_MOV_GbEb }, /* 8B /w */ { 0, BX_IA_MOV_GwEw }, /* 8C /w */ { 0, BX_IA_MOV_EwSw }, /* 8D /w */ { 0, BX_IA_LEA_GwM }, /* 8E /w */ { 0, BX_IA_MOV_SwEw }, /* 8F /w */ { BxGroup1A, BX_IA_ERROR, BxOpcodeInfoG1AEw }, /* 90 /w */ { BxPrefixSSE, BX_IA_NOP, BxOpcodeGroupSSE_PAUSE }, /* 91 /w */ { 0, BX_IA_XCHG_RXAX }, /* 92 /w */ { 0, BX_IA_XCHG_RXAX }, /* 93 /w */ { 0, BX_IA_XCHG_RXAX }, /* 94 /w */ { 0, BX_IA_XCHG_RXAX }, /* 95 /w */ { 0, BX_IA_XCHG_RXAX }, /* 96 /w */ { 0, BX_IA_XCHG_RXAX }, /* 97 /w */ { 0, BX_IA_XCHG_RXAX }, /* 98 /w */ { 0, BX_IA_CBW }, /* 99 /w */ { 0, BX_IA_CWD }, /* 9A /w */ { BxImmediate_Iw | BxImmediate_Iw2 | BxTraceEnd, BX_IA_CALL16_Ap }, /* 9B /w */ { 0, BX_IA_FWAIT }, /* 9C /w */ { 0, BX_IA_PUSHF_Fw }, /* 9D /w */ { BxTraceEnd, BX_IA_POPF_Fw }, /* 9E /w */ { 0, BX_IA_SAHF }, /* 9F /w */ { 0, BX_IA_LAHF }, /* A0 /w */ { BxImmediate_O, BX_IA_MOV_ALOd }, /* A1 /w */ { BxImmediate_O, BX_IA_MOV_AXOd }, /* A2 /w */ { BxImmediate_O, BX_IA_MOV_OdAL }, /* A3 /w */ { BxImmediate_O, BX_IA_MOV_OdAX }, /* A4 /w */ { BxRepeatable, BX_IA_REP_MOVSB_XbYb }, /* A5 /w */ { BxRepeatable, BX_IA_REP_MOVSW_XwYw }, /* A6 /w */ { BxRepeatable, BX_IA_REP_CMPSB_XbYb }, /* A7 /w */ { BxRepeatable, BX_IA_REP_CMPSW_XwYw }, /* A8 /w */ { BxImmediate_Ib, BX_IA_TEST_ALIb }, /* A9 /w */ { BxImmediate_Iw, BX_IA_TEST_AXIw }, /* AA /w */ { BxRepeatable, BX_IA_REP_STOSB_YbAL }, /* AB /w */ { BxRepeatable, BX_IA_REP_STOSW_YwAX }, /* AC /w */ { BxRepeatable, BX_IA_REP_LODSB_ALXb }, /* AD /w */ { BxRepeatable, BX_IA_REP_LODSW_AXXw }, /* AE /w */ { BxRepeatable, BX_IA_REP_SCASB_ALXb }, /* AF /w */ { BxRepeatable, BX_IA_REP_SCASW_AXXw }, /* B0 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B1 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B2 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B3 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B4 /w */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B5 /w */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B6 /w */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B7 /w */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B8 /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* B9 /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BA /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BB /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BC /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BD /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BE /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BF /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* C0 /w */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* C1 /w */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EwIb }, /* C2 /w */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETnear16_Iw }, /* C3 /w */ { BxTraceEnd, BX_IA_RETnear16 }, /* C4 /w */ { BxPrefixVEX, BX_IA_LES_GwMp }, /* C5 /w */ { BxPrefixVEX, BX_IA_LDS_GwMp }, /* C6 /w */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Eb }, /* C7 /w */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Ew }, /* C8 /w */ { BxImmediate_Iw | BxImmediate_Ib2, BX_IA_ENTER16_IwIb }, /* C9 /w */ { 0, BX_IA_LEAVE16 }, /* CA /w */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETfar16_Iw }, /* CB /w */ { BxTraceEnd, BX_IA_RETfar16 }, /* CC /w */ { BxTraceEnd, BX_IA_INT3 }, /* CD /w */ { BxImmediate_Ib | BxTraceEnd, BX_IA_INT_Ib }, /* CE /w */ { BxTraceEnd, BX_IA_INTO }, /* CF /w */ { BxTraceEnd, BX_IA_IRET16 }, /* D0 /w */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* D1 /w */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EwIb }, /* D2 /w */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Eb }, /* D3 /w */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Ew }, /* D4 /w */ { BxImmediate_Ib, BX_IA_AAM }, /* D5 /w */ { BxImmediate_Ib, BX_IA_AAD }, /* D6 /w */ { 0, BX_IA_SALC }, /* D7 /w */ { 0, BX_IA_XLAT }, #if BX_SUPPORT_FPU /* D8 /w */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupD8 }, /* D9 /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointD9 }, /* DA /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDA }, /* DB /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDB }, /* DC /w */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDC }, /* DD /w */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDD }, /* DE /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDE }, /* DF /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDF }, #else /* D8 /w */ { 0, BX_IA_FPU_ESC }, /* D9 /w */ { 0, BX_IA_FPU_ESC }, /* DA /w */ { 0, BX_IA_FPU_ESC }, /* DB /w */ { 0, BX_IA_FPU_ESC }, /* DC /w */ { 0, BX_IA_FPU_ESC }, /* DD /w */ { 0, BX_IA_FPU_ESC }, /* DE /w */ { 0, BX_IA_FPU_ESC }, /* DF /w */ { 0, BX_IA_FPU_ESC }, #endif /* E0 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPNE16_Jb }, /* E1 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPE16_Jb }, /* E2 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOP16_Jb }, /* E3 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JCXZ_Jb }, /* E4 /w */ { BxImmediate_Ib, BX_IA_IN_ALIb }, /* E5 /w */ { BxImmediate_Ib, BX_IA_IN_AXIb }, /* E6 /w */ { BxImmediate_Ib, BX_IA_OUT_IbAL }, /* E7 /w */ { BxImmediate_Ib, BX_IA_OUT_IbAX }, /* E8 /w */ { BxImmediate_BrOff16 | BxTraceEnd, BX_IA_CALL_Jw }, /* E9 /w */ { BxImmediate_BrOff16 | BxTraceEnd, BX_IA_JMP_Jw }, /* EA /w */ { BxImmediate_Iw | BxImmediate_Iw2 | BxTraceEnd, BX_IA_JMP_Ap }, /* EB /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JMP_Jw }, /* EC /w */ { 0, BX_IA_IN_ALDX }, /* ED /w */ { 0, BX_IA_IN_AXDX }, /* EE /w */ { 0, BX_IA_OUT_DXAL }, /* EF /w */ { 0, BX_IA_OUT_DXAX }, /* F0 /w */ { 0, BX_IA_ERROR }, // LOCK /* F1 /w */ { BxTraceEnd, BX_IA_INT1 }, /* F2 /w */ { 0, BX_IA_ERROR }, // REPNE/REPNZ /* F3 /w */ { 0, BX_IA_ERROR }, // REP, REPE/REPZ /* F4 /w */ { BxTraceEnd, BX_IA_HLT }, /* F5 /w */ { 0, BX_IA_CMC }, /* F6 /w */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Eb }, /* F7 /w */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Ew }, /* F8 /w */ { 0, BX_IA_CLC }, /* F9 /w */ { 0, BX_IA_STC }, /* FA /w */ { 0, BX_IA_CLI }, /* FB /w */ { 0, BX_IA_STI }, /* FC /w */ { 0, BX_IA_CLD }, /* FD /w */ { 0, BX_IA_STD }, /* FE /w */ { BxGroup4, BX_IA_ERROR, BxOpcodeInfoG4 }, /* FF /w */ { BxGroup5, BX_IA_ERROR, BxOpcodeInfoG5w }, /* 0F 00 /w */ { BxGroup6, BX_IA_ERROR, BxOpcodeInfoG6 }, /* 0F 01 /w */ { BxGroup7, BX_IA_ERROR, BxOpcodeInfoG7 }, /* 0F 02 /w */ { 0, BX_IA_LAR_GvEw }, /* 0F 03 /w */ { 0, BX_IA_LSL_GvEw }, /* 0F 04 /w */ { 0, BX_IA_ERROR }, /* 0F 05 /w */ { BxTraceEnd, BX_IA_SYSCALL_LEGACY }, /* 0F 06 /w */ { BxTraceEnd, BX_IA_CLTS }, /* 0F 07 /w */ { BxTraceEnd, BX_IA_SYSRET_LEGACY }, /* 0F 08 /w */ { BxTraceEnd, BX_IA_INVD }, /* 0F 09 /w */ { BxTraceEnd, BX_IA_WBINVD }, /* 0F 0A /w */ { 0, BX_IA_ERROR }, /* 0F 0B /w */ { BxTraceEnd, BX_IA_UD2A }, /* 0F 0C /w */ { 0, BX_IA_ERROR }, /* 0F 0D /w */ { 0, BX_IA_PREFETCHW }, // 3DNow! PREFETCHW on AMD, NOP on Intel /* 0F 0E /w */ { 0, BX_IA_FEMMS }, // 3DNow! FEMMS /* 0F 0F /w */ { BxImmediate_Ib, BX_IA_ERROR }, // 3DNow! Opcode Table /* 0F 10 /w */ { BxPrefixSSE, BX_IA_MOVUPS_VpsWps, BxOpcodeGroupSSE_0f10 }, /* 0F 11 /w */ { BxPrefixSSE, BX_IA_MOVUPS_WpsVps, BxOpcodeGroupSSE_0f11 }, /* 0F 12 /w */ { BxPrefixSSE, BX_IA_MOVLPS_VpsMq, BxOpcodeGroupSSE_0f12 }, /* 0F 13 /w */ { BxPrefixSSE, BX_IA_MOVLPS_MqVps, BxOpcodeGroupSSE_0f13M }, /* 0F 14 /w */ { BxPrefixSSE, BX_IA_UNPCKLPS_VpsWdq, BxOpcodeGroupSSE_0f14 }, /* 0F 15 /w */ { BxPrefixSSE, BX_IA_UNPCKHPS_VpsWdq, BxOpcodeGroupSSE_0f15 }, /* 0F 16 /w */ { BxPrefixSSE, BX_IA_MOVHPS_VpsMq, BxOpcodeGroupSSE_0f16 }, /* 0F 17 /w */ { BxPrefixSSE, BX_IA_MOVHPS_MqVps, BxOpcodeGroupSSE_0f17M }, #if BX_CPU_LEVEL >= 6 /* 0F 18 /w */ { 0, BX_IA_PREFETCH }, // opcode group G16, PREFETCH hints /* 0F 19 /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1A /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1B /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1C /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1D /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1E /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1F /w */ { 0, BX_IA_NOP }, // multi-byte NOP #else /* 0F 18 /w */ { 0, BX_IA_ERROR }, /* 0F 19 /w */ { 0, BX_IA_ERROR }, /* 0F 1A /w */ { 0, BX_IA_ERROR }, /* 0F 1B /w */ { 0, BX_IA_ERROR }, /* 0F 1C /w */ { 0, BX_IA_ERROR }, /* 0F 1D /w */ { 0, BX_IA_ERROR }, /* 0F 1E /w */ { 0, BX_IA_ERROR }, /* 0F 1F /w */ { 0, BX_IA_ERROR }, #endif /* 0F 20 /w */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_RdCd }, /* 0F 21 /w */ { 0, BX_IA_MOV_RdDd }, /* 0F 22 /w */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_CdRd }, /* 0F 23 /w */ { BxTraceEnd, BX_IA_MOV_DdRd }, /* 0F 24 /w */ { 0, BX_IA_ERROR }, // BX_IA_MOV_RdTd not implemented /* 0F 25 /w */ { 0, BX_IA_ERROR }, /* 0F 26 /w */ { 0, BX_IA_ERROR }, // BX_IA_MOV_TdRd not implemented /* 0F 27 /w */ { 0, BX_IA_ERROR }, /* 0F 28 /w */ { BxPrefixSSE, BX_IA_MOVAPS_VpsWps, BxOpcodeGroupSSE_0f28 }, /* 0F 29 /w */ { BxPrefixSSE, BX_IA_MOVAPS_WpsVps, BxOpcodeGroupSSE_0f29 }, /* 0F 2A /w */ { BxPrefixSSE, BX_IA_CVTPI2PS_VpsQq, BxOpcodeGroupSSE_0f2a }, /* 0F 2B /w */ { BxPrefixSSE, BX_IA_MOVNTPS_MpsVps, BxOpcodeGroupSSE_0f2bM }, /* 0F 2C /w */ { BxPrefixSSE, BX_IA_CVTTPS2PI_PqWps, BxOpcodeGroupSSE_0f2c }, /* 0F 2D /w */ { BxPrefixSSE, BX_IA_CVTPS2PI_PqWps, BxOpcodeGroupSSE_0f2d }, /* 0F 2E /w */ { BxPrefixSSE, BX_IA_UCOMISS_VssWss, BxOpcodeGroupSSE_0f2e }, /* 0F 2F /w */ { BxPrefixSSE, BX_IA_COMISS_VpsWps, BxOpcodeGroupSSE_0f2f }, /* 0F 30 /w */ { 0, BX_IA_WRMSR }, /* 0F 31 /w */ { BxTraceEnd, BX_IA_RDTSC }, // end trace to avoid multiple TSC samples in one cycle /* 0F 32 /w */ { BxTraceEnd, BX_IA_RDMSR }, // end trace to avoid multiple TSC samples in one cycle /* 0F 33 /w */ { 0, BX_IA_RDPMC }, /* 0F 34 /w */ { BxTraceEnd, BX_IA_SYSENTER }, /* 0F 35 /w */ { BxTraceEnd, BX_IA_SYSEXIT }, /* 0F 36 /w */ { 0, BX_IA_ERROR }, /* 0F 37 /w */ { 0, BX_IA_GETSEC }, #if BX_CPU_LEVEL >= 6 /* 0F 38 /w */ { Bx3ByteOp, BX_IA_ERROR, BxOpcode3ByteTable0f38 }, // 3-byte escape #else /* 0F 38 /w */ { 0, BX_IA_ERROR }, #endif /* 0F 39 /w */ { 0, BX_IA_ERROR }, #if BX_CPU_LEVEL >= 6 /* 0F 3A /w */ { Bx3ByteOp | BxImmediate_Ib, BX_IA_ERROR, BxOpcode3ByteTable0f3a }, // 3-byte escape #else /* 0F 3A /w */ { 0, BX_IA_ERROR }, #endif /* 0F 3B /w */ { 0, BX_IA_ERROR }, /* 0F 3C /w */ { 0, BX_IA_ERROR }, /* 0F 3D /w */ { 0, BX_IA_ERROR }, /* 0F 3E /w */ { 0, BX_IA_ERROR }, /* 0F 3F /w */ { 0, BX_IA_ERROR }, /* 0F 40 /w */ { 0, BX_IA_CMOVO_GwEw }, /* 0F 41 /w */ { 0, BX_IA_CMOVNO_GwEw }, /* 0F 42 /w */ { 0, BX_IA_CMOVB_GwEw }, /* 0F 43 /w */ { 0, BX_IA_CMOVNB_GwEw }, /* 0F 44 /w */ { 0, BX_IA_CMOVZ_GwEw }, /* 0F 45 /w */ { 0, BX_IA_CMOVNZ_GwEw }, /* 0F 46 /w */ { 0, BX_IA_CMOVBE_GwEw }, /* 0F 47 /w */ { 0, BX_IA_CMOVNBE_GwEw }, /* 0F 48 /w */ { 0, BX_IA_CMOVS_GwEw }, /* 0F 49 /w */ { 0, BX_IA_CMOVNS_GwEw }, /* 0F 4A /w */ { 0, BX_IA_CMOVP_GwEw }, /* 0F 4B /w */ { 0, BX_IA_CMOVNP_GwEw }, /* 0F 4C /w */ { 0, BX_IA_CMOVL_GwEw }, /* 0F 4D /w */ { 0, BX_IA_CMOVNL_GwEw }, /* 0F 4E /w */ { 0, BX_IA_CMOVLE_GwEw }, /* 0F 4F /w */ { 0, BX_IA_CMOVNLE_GwEw }, /* 0F 50 /w */ { BxPrefixSSE, BX_IA_MOVMSKPS_GdVRps, BxOpcodeGroupSSE_0f50R }, /* 0F 51 /w */ { BxPrefixSSE, BX_IA_SQRTPS_VpsWps, BxOpcodeGroupSSE_0f51 }, /* 0F 52 /w */ { BxPrefixSSE, BX_IA_RSQRTPS_VpsWps, BxOpcodeGroupSSE_0f52 }, /* 0F 53 /w */ { BxPrefixSSE, BX_IA_RCPPS_VpsWps, BxOpcodeGroupSSE_0f53 }, /* 0F 54 /w */ { BxPrefixSSE, BX_IA_ANDPS_VpsWps, BxOpcodeGroupSSE_0f54 }, /* 0F 55 /w */ { BxPrefixSSE, BX_IA_ANDNPS_VpsWps, BxOpcodeGroupSSE_0f55 }, /* 0F 56 /w */ { BxPrefixSSE, BX_IA_ORPS_VpsWps, BxOpcodeGroupSSE_0f56 }, /* 0F 57 /w */ { BxPrefixSSE, BX_IA_XORPS_VpsWps, BxOpcodeGroupSSE_0f57 }, /* 0F 58 /w */ { BxPrefixSSE, BX_IA_ADDPS_VpsWps, BxOpcodeGroupSSE_0f58 }, /* 0F 59 /w */ { BxPrefixSSE, BX_IA_MULPS_VpsWps, BxOpcodeGroupSSE_0f59 }, /* 0F 5A /w */ { BxPrefixSSE, BX_IA_CVTPS2PD_VpdWps, BxOpcodeGroupSSE_0f5a }, /* 0F 5B /w */ { BxPrefixSSE, BX_IA_CVTDQ2PS_VpsWdq, BxOpcodeGroupSSE_0f5b }, /* 0F 5C /w */ { BxPrefixSSE, BX_IA_SUBPS_VpsWps, BxOpcodeGroupSSE_0f5c }, /* 0F 5D /w */ { BxPrefixSSE, BX_IA_MINPS_VpsWps, BxOpcodeGroupSSE_0f5d }, /* 0F 5E /w */ { BxPrefixSSE, BX_IA_DIVPS_VpsWps, BxOpcodeGroupSSE_0f5e }, /* 0F 5F /w */ { BxPrefixSSE, BX_IA_MAXPS_VpsWps, BxOpcodeGroupSSE_0f5f }, /* 0F 60 /w */ { BxPrefixSSE, BX_IA_PUNPCKLBW_PqQd, BxOpcodeGroupSSE_0f60 }, /* 0F 61 /w */ { BxPrefixSSE, BX_IA_PUNPCKLWD_PqQd, BxOpcodeGroupSSE_0f61 }, /* 0F 62 /w */ { BxPrefixSSE, BX_IA_PUNPCKLDQ_PqQd, BxOpcodeGroupSSE_0f62 }, /* 0F 63 /w */ { BxPrefixSSE, BX_IA_PACKSSWB_PqQq, BxOpcodeGroupSSE_0f63 }, /* 0F 64 /w */ { BxPrefixSSE, BX_IA_PCMPGTB_PqQq, BxOpcodeGroupSSE_0f64 }, /* 0F 65 /w */ { BxPrefixSSE, BX_IA_PCMPGTW_PqQq, BxOpcodeGroupSSE_0f65 }, /* 0F 66 /w */ { BxPrefixSSE, BX_IA_PCMPGTD_PqQq, BxOpcodeGroupSSE_0f66 }, /* 0F 67 /w */ { BxPrefixSSE, BX_IA_PACKUSWB_PqQq, BxOpcodeGroupSSE_0f67 }, /* 0F 68 /w */ { BxPrefixSSE, BX_IA_PUNPCKHBW_PqQq, BxOpcodeGroupSSE_0f68 }, /* 0F 69 /w */ { BxPrefixSSE, BX_IA_PUNPCKHWD_PqQq, BxOpcodeGroupSSE_0f69 }, /* 0F 6A /w */ { BxPrefixSSE, BX_IA_PUNPCKHDQ_PqQq, BxOpcodeGroupSSE_0f6a }, /* 0F 6B /w */ { BxPrefixSSE, BX_IA_PACKSSDW_PqQq, BxOpcodeGroupSSE_0f6b }, /* 0F 6C /w */ { BxPrefixSSE66, BX_IA_PUNPCKLQDQ_VdqWdq }, /* 0F 6D /w */ { BxPrefixSSE66, BX_IA_PUNPCKHQDQ_VdqWdq }, /* 0F 6E /w */ { BxPrefixSSE, BX_IA_MOVD_PqEd, BxOpcodeGroupSSE_0f6e }, /* 0F 6F /w */ { BxPrefixSSE, BX_IA_MOVQ_PqQq, BxOpcodeGroupSSE_0f6f }, /* 0F 70 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PSHUFW_PqQqIb, BxOpcodeGroupSSE_0f70 }, /* 0F 71 /w */ { BxGroup12, BX_IA_ERROR, BxOpcodeInfoG12R }, /* 0F 72 /w */ { BxGroup13, BX_IA_ERROR, BxOpcodeInfoG13R }, /* 0F 73 /w */ { BxGroup14, BX_IA_ERROR, BxOpcodeInfoG14R }, /* 0F 74 /w */ { BxPrefixSSE, BX_IA_PCMPEQB_PqQq, BxOpcodeGroupSSE_0f74 }, /* 0F 75 /w */ { BxPrefixSSE, BX_IA_PCMPEQW_PqQq, BxOpcodeGroupSSE_0f75 }, /* 0F 76 /w */ { BxPrefixSSE, BX_IA_PCMPEQD_PqQq, BxOpcodeGroupSSE_0f76 }, /* 0F 77 /w */ { BxPrefixSSE, BX_IA_EMMS, BxOpcodeGroupSSE_ERR }, /* 0F 78 /w */ { BxPrefixSSE, BX_IA_VMREAD_EdGd, BxOpcodeGroupSSE4A_0f78 }, /* 0F 79 /w */ { BxPrefixSSE, BX_IA_VMWRITE_GdEd, BxOpcodeGroupSSE4A_0f79 }, /* 0F 7A /w */ { 0, BX_IA_ERROR }, /* 0F 7B /w */ { 0, BX_IA_ERROR }, /* 0F 7C /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7c }, /* 0F 7D /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7d }, /* 0F 7E /w */ { BxPrefixSSE, BX_IA_MOVD_EdPd, BxOpcodeGroupSSE_0f7e }, /* 0F 7F /w */ { BxPrefixSSE, BX_IA_MOVQ_QqPq, BxOpcodeGroupSSE_0f7f }, /* 0F 80 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JO_Jw }, /* 0F 81 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNO_Jw }, /* 0F 82 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JB_Jw }, /* 0F 83 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNB_Jw }, /* 0F 84 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JZ_Jw }, /* 0F 85 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNZ_Jw }, /* 0F 86 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JBE_Jw }, /* 0F 87 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNBE_Jw }, /* 0F 88 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JS_Jw }, /* 0F 89 /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNS_Jw }, /* 0F 8A /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JP_Jw }, /* 0F 8B /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNP_Jw }, /* 0F 8C /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JL_Jw }, /* 0F 8D /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNL_Jw }, /* 0F 8E /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JLE_Jw }, /* 0F 8F /w */ { BxImmediate_BrOff16 | BxTraceJCC, BX_IA_JNLE_Jw }, /* 0F 90 /w */ { 0, BX_IA_SETO_Eb }, /* 0F 91 /w */ { 0, BX_IA_SETNO_Eb }, /* 0F 92 /w */ { 0, BX_IA_SETB_Eb }, /* 0F 93 /w */ { 0, BX_IA_SETNB_Eb }, /* 0F 94 /w */ { 0, BX_IA_SETZ_Eb }, /* 0F 95 /w */ { 0, BX_IA_SETNZ_Eb }, /* 0F 96 /w */ { 0, BX_IA_SETBE_Eb }, /* 0F 97 /w */ { 0, BX_IA_SETNBE_Eb }, /* 0F 98 /w */ { 0, BX_IA_SETS_Eb }, /* 0F 99 /w */ { 0, BX_IA_SETNS_Eb }, /* 0F 9A /w */ { 0, BX_IA_SETP_Eb }, /* 0F 9B /w */ { 0, BX_IA_SETNP_Eb }, /* 0F 9C /w */ { 0, BX_IA_SETL_Eb }, /* 0F 9D /w */ { 0, BX_IA_SETNL_Eb }, /* 0F 9E /w */ { 0, BX_IA_SETLE_Eb }, /* 0F 9F /w */ { 0, BX_IA_SETNLE_Eb }, /* 0F A0 /w */ { 0, BX_IA_PUSH16_FS }, /* 0F A1 /w */ { 0, BX_IA_POP16_FS }, /* 0F A2 /w */ { 0, BX_IA_CPUID }, /* 0F A3 /w */ { 0, BX_IA_BT_EwGw }, /* 0F A4 /w */ { BxImmediate_Ib, BX_IA_SHLD_EwGwIb }, /* 0F A5 /w */ { 0, BX_IA_SHLD_EwGw }, /* 0F A6 /w */ { 0, BX_IA_ERROR }, // CMPXCHG_XBTS not implemented /* 0F A7 /w */ { 0, BX_IA_ERROR }, // CMPXCHG_IBTS not implemented /* 0F A8 /w */ { 0, BX_IA_PUSH16_GS }, /* 0F A9 /w */ { 0, BX_IA_POP16_GS }, /* 0F AA /w */ { BxTraceEnd, BX_IA_RSM }, /* 0F AB /w */ { BxLockable, BX_IA_BTS_EwGw }, /* 0F AC /w */ { BxImmediate_Ib, BX_IA_SHRD_EwGwIb }, /* 0F AD /w */ { 0, BX_IA_SHRD_EwGw }, /* 0F AE /w */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15 }, /* 0F AF /w */ { 0, BX_IA_IMUL_GwEw }, /* 0F B0 /w */ { BxLockable, BX_IA_CMPXCHG_EbGb }, /* 0F B1 /w */ { BxLockable, BX_IA_CMPXCHG_EwGw }, /* 0F B2 /w */ { 0, BX_IA_LSS_GwMp }, /* 0F B3 /w */ { BxLockable, BX_IA_BTR_EwGw }, /* 0F B4 /w */ { 0, BX_IA_LFS_GwMp }, /* 0F B5 /w */ { 0, BX_IA_LGS_GwMp }, /* 0F B6 /w */ { 0, BX_IA_MOVZX_GwEb }, /* 0F B7 /w */ { 0, BX_IA_MOV_GwEw }, // MOVZX_GwEw /* 0F B8 /w */ { BxPrefixSSEF3, BX_IA_POPCNT_GwEw }, /* 0F B9 /w */ { BxTraceEnd, BX_IA_UD2B }, /* 0F BA /w */ { BxGroup8, BX_IA_ERROR, BxOpcodeInfoG8EwIb }, /* 0F BB /w */ { BxLockable, BX_IA_BTC_EwGw }, /* 0F BC /w */ { BxPrefixSSE, BX_IA_BSF_GwEw, BxOpcodeGroupSSE_TZCNT16 }, /* 0F BD /w */ { BxPrefixSSE, BX_IA_BSR_GwEw, BxOpcodeGroupSSE_LZCNT16 }, /* 0F BE /w */ { 0, BX_IA_MOVSX_GwEb }, /* 0F BF /w */ { 0, BX_IA_MOV_GwEw }, // MOVSX_GwEw /* 0F C0 /w */ { BxLockable, BX_IA_XADD_EbGb }, /* 0F C1 /w */ { BxLockable, BX_IA_XADD_EwGw }, /* 0F C2 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_CMPPS_VpsWpsIb, BxOpcodeGroupSSE_0fc2 }, /* 0F C3 /w */ { BxPrefixSSE, BX_IA_MOVNTI32_MdGd, BxOpcodeGroupSSE_ERR }, /* 0F C4 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PINSRW_PqEwIb, BxOpcodeGroupSSE_0fc4 }, /* 0F C5 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PEXTRW_GdPqIb, BxOpcodeGroupSSE_0fc5R }, /* 0F C6 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_SHUFPS_VpsWpsIb, BxOpcodeGroupSSE_0fc6 }, /* 0F C7 /w */ { BxGroup9, BX_IA_ERROR, BxOpcodeInfoG9M }, /* 0F C8 /w */ { 0, BX_IA_BSWAP_RX }, /* 0F C9 /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CA /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CB /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CC /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CD /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CE /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CF /w */ { 0, BX_IA_BSWAP_RX }, /* 0F D0 /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd0 }, /* 0F D1 /w */ { BxPrefixSSE, BX_IA_PSRLW_PqQq, BxOpcodeGroupSSE_0fd1 }, /* 0F D2 /w */ { BxPrefixSSE, BX_IA_PSRLD_PqQq, BxOpcodeGroupSSE_0fd2 }, /* 0F D3 /w */ { BxPrefixSSE, BX_IA_PSRLQ_PqQq, BxOpcodeGroupSSE_0fd3 }, /* 0F D4 /w */ { BxPrefixSSE, BX_IA_PADDQ_PqQq, BxOpcodeGroupSSE_0fd4 }, /* 0F D5 /w */ { BxPrefixSSE, BX_IA_PMULLW_PqQq, BxOpcodeGroupSSE_0fd5 }, /* 0F D6 /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd6 }, /* 0F D7 /w */ { BxPrefixSSE, BX_IA_PMOVMSKB_GdPRq, BxOpcodeGroupSSE_0fd7R }, /* 0F D8 /w */ { BxPrefixSSE, BX_IA_PSUBUSB_PqQq, BxOpcodeGroupSSE_0fd8 }, /* 0F D9 /w */ { BxPrefixSSE, BX_IA_PSUBUSW_PqQq, BxOpcodeGroupSSE_0fd9 }, /* 0F DA /w */ { BxPrefixSSE, BX_IA_PMINUB_PqQq, BxOpcodeGroupSSE_0fda }, /* 0F DB /w */ { BxPrefixSSE, BX_IA_PAND_PqQq, BxOpcodeGroupSSE_0fdb }, /* 0F DC /w */ { BxPrefixSSE, BX_IA_PADDUSB_PqQq, BxOpcodeGroupSSE_0fdc }, /* 0F DD /w */ { BxPrefixSSE, BX_IA_PADDUSW_PqQq, BxOpcodeGroupSSE_0fdd }, /* 0F DE /w */ { BxPrefixSSE, BX_IA_PMAXUB_PqQq, BxOpcodeGroupSSE_0fde }, /* 0F DF /w */ { BxPrefixSSE, BX_IA_PANDN_PqQq, BxOpcodeGroupSSE_0fdf }, /* 0F E0 /w */ { BxPrefixSSE, BX_IA_PAVGB_PqQq, BxOpcodeGroupSSE_0fe0 }, /* 0F E1 /w */ { BxPrefixSSE, BX_IA_PSRAW_PqQq, BxOpcodeGroupSSE_0fe1 }, /* 0F E2 /w */ { BxPrefixSSE, BX_IA_PSRAD_PqQq, BxOpcodeGroupSSE_0fe2 }, /* 0F E3 /w */ { BxPrefixSSE, BX_IA_PAVGW_PqQq, BxOpcodeGroupSSE_0fe3 }, /* 0F E4 /w */ { BxPrefixSSE, BX_IA_PMULHUW_PqQq, BxOpcodeGroupSSE_0fe4 }, /* 0F E5 /w */ { BxPrefixSSE, BX_IA_PMULHW_PqQq, BxOpcodeGroupSSE_0fe5 }, /* 0F E6 /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fe6 }, /* 0F E7 /w */ { BxPrefixSSE, BX_IA_MOVNTQ_MqPq, BxOpcodeGroupSSE_0fe7M }, /* 0F E8 /w */ { BxPrefixSSE, BX_IA_PSUBSB_PqQq, BxOpcodeGroupSSE_0fe8 }, /* 0F E9 /w */ { BxPrefixSSE, BX_IA_PSUBSW_PqQq, BxOpcodeGroupSSE_0fe9 }, /* 0F EA /w */ { BxPrefixSSE, BX_IA_PMINSW_PqQq, BxOpcodeGroupSSE_0fea }, /* 0F EB /w */ { BxPrefixSSE, BX_IA_POR_PqQq, BxOpcodeGroupSSE_0feb }, /* 0F EC /w */ { BxPrefixSSE, BX_IA_PADDSB_PqQq, BxOpcodeGroupSSE_0fec }, /* 0F ED /w */ { BxPrefixSSE, BX_IA_PADDSW_PqQq, BxOpcodeGroupSSE_0fed }, /* 0F EE /w */ { BxPrefixSSE, BX_IA_PMAXSW_PqQq, BxOpcodeGroupSSE_0fee }, /* 0F EF /w */ { BxPrefixSSE, BX_IA_PXOR_PqQq, BxOpcodeGroupSSE_0fef }, /* 0F F0 /w */ { BxPrefixSSEF2, BX_IA_LDDQU_VdqMdq }, /* 0F F1 /w */ { BxPrefixSSE, BX_IA_PSLLW_PqQq, BxOpcodeGroupSSE_0ff1 }, /* 0F F2 /w */ { BxPrefixSSE, BX_IA_PSLLD_PqQq, BxOpcodeGroupSSE_0ff2 }, /* 0F F3 /w */ { BxPrefixSSE, BX_IA_PSLLQ_PqQq, BxOpcodeGroupSSE_0ff3 }, /* 0F F4 /w */ { BxPrefixSSE, BX_IA_PMULUDQ_PqQq, BxOpcodeGroupSSE_0ff4 }, /* 0F F5 /w */ { BxPrefixSSE, BX_IA_PMADDWD_PqQq, BxOpcodeGroupSSE_0ff5 }, /* 0F F6 /w */ { BxPrefixSSE, BX_IA_PSADBW_PqQq, BxOpcodeGroupSSE_0ff6 }, /* 0F F7 /w */ { BxPrefixSSE, BX_IA_MASKMOVQ_PqPRq, BxOpcodeGroupSSE_0ff7R }, /* 0F F8 /w */ { BxPrefixSSE, BX_IA_PSUBB_PqQq, BxOpcodeGroupSSE_0ff8 }, /* 0F F9 /w */ { BxPrefixSSE, BX_IA_PSUBW_PqQq, BxOpcodeGroupSSE_0ff9 }, /* 0F FA /w */ { BxPrefixSSE, BX_IA_PSUBD_PqQq, BxOpcodeGroupSSE_0ffa }, /* 0F FB /w */ { BxPrefixSSE, BX_IA_PSUBQ_PqQq, BxOpcodeGroupSSE_0ffb }, /* 0F FC /w */ { BxPrefixSSE, BX_IA_PADDB_PqQq, BxOpcodeGroupSSE_0ffc }, /* 0F FD /w */ { BxPrefixSSE, BX_IA_PADDW_PqQq, BxOpcodeGroupSSE_0ffd }, /* 0F FE /w */ { BxPrefixSSE, BX_IA_PADDD_PqQq, BxOpcodeGroupSSE_0ffe }, /* 0F FF /w */ { 0, BX_IA_ERROR }, // 512 entries for 32bit mode /* 00 /d */ { BxLockable, BX_IA_ADD_EbGb }, /* 01 /d */ { BxLockable, BX_IA_ADD_EdGd }, /* 02 /d */ { 0, BX_IA_ADD_GbEb }, /* 03 /d */ { 0, BX_IA_ADD_GdEd }, /* 04 /d */ { BxImmediate_Ib, BX_IA_ADD_ALIb }, /* 05 /d */ { BxImmediate_Id, BX_IA_ADD_EAXId }, /* 06 /d */ { 0, BX_IA_PUSH32_ES }, /* 07 /d */ { 0, BX_IA_POP32_ES }, /* 08 /d */ { BxLockable, BX_IA_OR_EbGb }, /* 09 /d */ { BxLockable, BX_IA_OR_EdGd }, /* 0A /d */ { 0, BX_IA_OR_GbEb }, /* 0B /d */ { 0, BX_IA_OR_GdEd }, /* 0C /d */ { BxImmediate_Ib, BX_IA_OR_ALIb }, /* 0D /d */ { BxImmediate_Id, BX_IA_OR_EAXId }, /* 0E /d */ { 0, BX_IA_PUSH32_CS }, /* 0F /d */ { 0, BX_IA_ERROR }, // 2-byte escape /* 10 /d */ { BxLockable, BX_IA_ADC_EbGb }, /* 11 /d */ { BxLockable, BX_IA_ADC_EdGd }, /* 12 /d */ { 0, BX_IA_ADC_GbEb }, /* 13 /d */ { 0, BX_IA_ADC_GdEd }, /* 14 /d */ { BxImmediate_Ib, BX_IA_ADC_ALIb }, /* 15 /d */ { BxImmediate_Id, BX_IA_ADC_EAXId }, /* 16 /d */ { 0, BX_IA_PUSH32_SS }, /* 17 /d */ { 0, BX_IA_POP32_SS }, /* 18 /d */ { BxLockable, BX_IA_SBB_EbGb }, /* 19 /d */ { BxLockable, BX_IA_SBB_EdGd }, /* 1A /d */ { 0, BX_IA_SBB_GbEb }, /* 1B /d */ { 0, BX_IA_SBB_GdEd }, /* 1C /d */ { BxImmediate_Ib, BX_IA_SBB_ALIb }, /* 1D /d */ { BxImmediate_Id, BX_IA_SBB_EAXId }, /* 1E /d */ { 0, BX_IA_PUSH32_DS }, /* 1F /d */ { 0, BX_IA_POP32_DS }, /* 20 /d */ { BxLockable, BX_IA_AND_EbGb }, /* 21 /d */ { BxLockable, BX_IA_AND_EdGd }, /* 22 /d */ { 0, BX_IA_AND_GbEb }, /* 23 /d */ { 0, BX_IA_AND_GdEd }, /* 24 /d */ { BxImmediate_Ib, BX_IA_AND_ALIb }, /* 25 /d */ { BxImmediate_Id, BX_IA_AND_EAXId }, /* 26 /d */ { 0, BX_IA_ERROR }, // ES: /* 27 /d */ { 0, BX_IA_DAA }, /* 28 /d */ { BxLockable, BX_IA_SUB_EbGb }, /* 29 /d */ { BxLockable, BX_IA_SUB_EdGd }, /* 2A /d */ { 0, BX_IA_SUB_GbEb }, /* 2B /d */ { 0, BX_IA_SUB_GdEd }, /* 2C /d */ { BxImmediate_Ib, BX_IA_SUB_ALIb }, /* 2D /d */ { BxImmediate_Id, BX_IA_SUB_EAXId }, /* 2E /d */ { 0, BX_IA_ERROR }, // CS: /* 2F /d */ { 0, BX_IA_DAS }, /* 30 /d */ { BxLockable, BX_IA_XOR_EbGb }, /* 31 /d */ { BxLockable, BX_IA_XOR_EdGd }, /* 32 /d */ { 0, BX_IA_XOR_GbEb }, /* 33 /d */ { 0, BX_IA_XOR_GdEd }, /* 34 /d */ { BxImmediate_Ib, BX_IA_XOR_ALIb }, /* 35 /d */ { BxImmediate_Id, BX_IA_XOR_EAXId }, /* 36 /d */ { 0, BX_IA_ERROR }, // SS: /* 37 /d */ { 0, BX_IA_AAA }, /* 38 /d */ { 0, BX_IA_CMP_EbGb }, /* 39 /d */ { 0, BX_IA_CMP_EdGd }, /* 3A /d */ { 0, BX_IA_CMP_GbEb }, /* 3B /d */ { 0, BX_IA_CMP_GdEd }, /* 3C /d */ { BxImmediate_Ib, BX_IA_CMP_ALIb }, /* 3D /d */ { BxImmediate_Id, BX_IA_CMP_EAXId }, /* 3E /d */ { 0, BX_IA_ERROR }, // DS: /* 3F /d */ { 0, BX_IA_AAS }, /* 40 /d */ { 0, BX_IA_INC_ERX }, /* 41 /d */ { 0, BX_IA_INC_ERX }, /* 42 /d */ { 0, BX_IA_INC_ERX }, /* 43 /d */ { 0, BX_IA_INC_ERX }, /* 44 /d */ { 0, BX_IA_INC_ERX }, /* 45 /d */ { 0, BX_IA_INC_ERX }, /* 46 /d */ { 0, BX_IA_INC_ERX }, /* 47 /d */ { 0, BX_IA_INC_ERX }, /* 48 /d */ { 0, BX_IA_DEC_ERX }, /* 49 /d */ { 0, BX_IA_DEC_ERX }, /* 4A /d */ { 0, BX_IA_DEC_ERX }, /* 4B /d */ { 0, BX_IA_DEC_ERX }, /* 4C /d */ { 0, BX_IA_DEC_ERX }, /* 4D /d */ { 0, BX_IA_DEC_ERX }, /* 4E /d */ { 0, BX_IA_DEC_ERX }, /* 4F /d */ { 0, BX_IA_DEC_ERX }, /* 50 /d */ { 0, BX_IA_PUSH_ERX }, /* 51 /d */ { 0, BX_IA_PUSH_ERX }, /* 52 /d */ { 0, BX_IA_PUSH_ERX }, /* 53 /d */ { 0, BX_IA_PUSH_ERX }, /* 54 /d */ { 0, BX_IA_PUSH_ERX }, /* 55 /d */ { 0, BX_IA_PUSH_ERX }, /* 56 /d */ { 0, BX_IA_PUSH_ERX }, /* 57 /d */ { 0, BX_IA_PUSH_ERX }, /* 58 /d */ { 0, BX_IA_POP_ERX }, /* 59 /d */ { 0, BX_IA_POP_ERX }, /* 5A /d */ { 0, BX_IA_POP_ERX }, /* 5B /d */ { 0, BX_IA_POP_ERX }, /* 5C /d */ { 0, BX_IA_POP_ERX }, /* 5D /d */ { 0, BX_IA_POP_ERX }, /* 5E /d */ { 0, BX_IA_POP_ERX }, /* 5F /d */ { 0, BX_IA_POP_ERX }, /* 60 /d */ { 0, BX_IA_PUSHAD32 }, /* 61 /d */ { 0, BX_IA_POPAD32 }, /* 62 /d */ { 0, BX_IA_BOUND_GdMa }, /* 63 /d */ { 0, BX_IA_ARPL_EwGw }, /* 64 /d */ { 0, BX_IA_ERROR }, // FS: /* 65 /d */ { 0, BX_IA_ERROR }, // GS: /* 66 /d */ { 0, BX_IA_ERROR }, // OS: /* 67 /d */ { 0, BX_IA_ERROR }, // AS: /* 68 /d */ { BxImmediate_Id, BX_IA_PUSH_Id }, /* 69 /d */ { BxImmediate_Id, BX_IA_IMUL_GdEdId }, /* 6A /d */ { BxImmediate_Ib_SE, BX_IA_PUSH_Id }, /* 6B /d */ { BxImmediate_Ib_SE, BX_IA_IMUL_GdEdId }, /* 6C /d */ { BxRepeatable, BX_IA_REP_INSB_YbDX }, /* 6D /d */ { BxRepeatable, BX_IA_REP_INSD_YdDX }, /* 6E /d */ { BxRepeatable, BX_IA_REP_OUTSB_DXXb }, /* 6F /d */ { BxRepeatable, BX_IA_REP_OUTSD_DXXd }, /* 70 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JO_Jd }, /* 71 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNO_Jd }, /* 72 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JB_Jd }, /* 73 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNB_Jd }, /* 74 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JZ_Jd }, /* 75 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNZ_Jd }, /* 76 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JBE_Jd }, /* 77 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNBE_Jd }, /* 78 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JS_Jd }, /* 79 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNS_Jd }, /* 7A /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JP_Jd }, /* 7B /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNP_Jd }, /* 7C /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JL_Jd }, /* 7D /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNL_Jd }, /* 7E /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JLE_Jd }, /* 7F /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNLE_Jd }, /* 80 /d */ { BxGroup1 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG1EbIb }, /* 81 /d */ { BxGroup1 | BxImmediate_Id, BX_IA_ERROR, BxOpcodeInfoG1Ed }, /* 82 /d */ { BxGroup1 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG1EbIb }, /* 83 /d */ { BxGroup1 | BxImmediate_Ib_SE, BX_IA_ERROR, BxOpcodeInfoG1Ed }, /* 84 /d */ { 0, BX_IA_TEST_EbGb }, /* 85 /d */ { 0, BX_IA_TEST_EdGd }, /* 86 /d */ { BxLockable, BX_IA_XCHG_EbGb }, /* 87 /d */ { BxLockable, BX_IA_XCHG_EdGd }, /* 88 /d */ { 0, BX_IA_MOV_EbGb }, /* 89 /d */ { 0, BX_IA_MOV32_EdGd }, /* 8A /d */ { 0, BX_IA_MOV_GbEb }, /* 8B /d */ { 0, BX_IA_MOV32_GdEd }, /* 8C /d */ { 0, BX_IA_MOV_EwSw }, /* 8D /d */ { 0, BX_IA_LEA_GdM }, /* 8E /d */ { 0, BX_IA_MOV_SwEw }, /* 8F /d */ { BxGroup1A, BX_IA_ERROR, BxOpcodeInfoG1AEd }, /* 90 /d */ { BxPrefixSSE, BX_IA_NOP, BxOpcodeGroupSSE_PAUSE }, /* 91 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 92 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 93 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 94 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 95 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 96 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 97 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 98 /d */ { 0, BX_IA_CWDE }, /* 99 /d */ { 0, BX_IA_CDQ }, /* 9A /d */ { BxImmediate_Id | BxImmediate_Iw2 | BxTraceEnd, BX_IA_CALL32_Ap }, /* 9B /d */ { 0, BX_IA_FWAIT }, /* 9C /d */ { 0, BX_IA_PUSHF_Fd }, /* 9D /d */ { BxTraceEnd, BX_IA_POPF_Fd }, /* 9E /d */ { 0, BX_IA_SAHF }, /* 9F /d */ { 0, BX_IA_LAHF }, /* A0 /d */ { BxImmediate_O, BX_IA_MOV_ALOd }, /* A1 /d */ { BxImmediate_O, BX_IA_MOV_EAXOd }, /* A2 /d */ { BxImmediate_O, BX_IA_MOV_OdAL }, /* A3 /d */ { BxImmediate_O, BX_IA_MOV_OdEAX }, /* A4 /d */ { BxRepeatable, BX_IA_REP_MOVSB_XbYb }, /* A5 /d */ { BxRepeatable, BX_IA_REP_MOVSD_XdYd }, /* A6 /d */ { BxRepeatable, BX_IA_REP_CMPSB_XbYb }, /* A7 /d */ { BxRepeatable, BX_IA_REP_CMPSD_XdYd }, /* A8 /d */ { BxImmediate_Ib, BX_IA_TEST_ALIb }, /* A9 /d */ { BxImmediate_Id, BX_IA_TEST_EAXId }, /* AA /d */ { BxRepeatable, BX_IA_REP_STOSB_YbAL }, /* AB /d */ { BxRepeatable, BX_IA_REP_STOSD_YdEAX }, /* AC /d */ { BxRepeatable, BX_IA_REP_LODSB_ALXb }, /* AD /d */ { BxRepeatable, BX_IA_REP_LODSD_EAXXd }, /* AE /d */ { BxRepeatable, BX_IA_REP_SCASB_ALXb }, /* AF /d */ { BxRepeatable, BX_IA_REP_SCASD_EAXXd }, /* B0 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B1 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B2 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B3 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B4 /d */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B5 /d */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B6 /d */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B7 /d */ { BxImmediate_Ib, BX_IA_MOV_RHIb }, /* B8 /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* B9 /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BA /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BB /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BC /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BD /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BE /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BF /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* C0 /d */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* C1 /d */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EdIb }, /* C2 /d */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETnear32_Iw }, /* C3 /d */ { BxTraceEnd, BX_IA_RETnear32 }, /* C4 /d */ { BxPrefixVEX, BX_IA_LES_GdMp }, /* C5 /d */ { BxPrefixVEX, BX_IA_LDS_GdMp }, /* C6 /d */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Eb }, /* C7 /d */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Ed }, /* C8 /d */ { BxImmediate_Iw | BxImmediate_Ib2, BX_IA_ENTER32_IwIb }, /* C9 /d */ { 0, BX_IA_LEAVE32 }, /* CA /d */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETfar32_Iw }, /* CB /d */ { BxTraceEnd, BX_IA_RETfar32 }, /* CC /d */ { BxTraceEnd, BX_IA_INT3 }, /* CD /d */ { BxImmediate_Ib | BxTraceEnd, BX_IA_INT_Ib }, /* CE /d */ { BxTraceEnd, BX_IA_INTO }, /* CF /d */ { BxTraceEnd, BX_IA_IRET32 }, /* D0 /d */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* D1 /d */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EdIb }, /* D2 /d */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Eb }, /* D3 /d */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Ed }, /* D4 /d */ { BxImmediate_Ib, BX_IA_AAM }, /* D5 /d */ { BxImmediate_Ib, BX_IA_AAD }, /* D6 /d */ { 0, BX_IA_SALC }, /* D7 /d */ { 0, BX_IA_XLAT }, #if BX_SUPPORT_FPU /* D8 /d */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupD8 }, /* D9 /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointD9 }, /* DA /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDA }, /* DB /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDB }, /* DC /d */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDC }, /* DD /d */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDD }, /* DE /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDE }, /* DF /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDF }, #else /* D8 /d */ { 0, BX_IA_FPU_ESC }, /* D9 /d */ { 0, BX_IA_FPU_ESC }, /* DA /d */ { 0, BX_IA_FPU_ESC }, /* DB /d */ { 0, BX_IA_FPU_ESC }, /* DC /d */ { 0, BX_IA_FPU_ESC }, /* DD /d */ { 0, BX_IA_FPU_ESC }, /* DE /d */ { 0, BX_IA_FPU_ESC }, /* DF /d */ { 0, BX_IA_FPU_ESC }, #endif /* E0 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPNE32_Jb }, /* E1 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPE32_Jb }, /* E2 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOP32_Jb }, /* E3 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JECXZ_Jb }, /* E4 /d */ { BxImmediate_Ib, BX_IA_IN_ALIb }, /* E5 /d */ { BxImmediate_Ib, BX_IA_IN_EAXIb }, /* E6 /d */ { BxImmediate_Ib, BX_IA_OUT_IbAL }, /* E7 /d */ { BxImmediate_Ib, BX_IA_OUT_IbEAX }, /* E8 /d */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_CALL_Jd }, /* E9 /d */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_JMP_Jd }, /* EA /d */ { BxImmediate_Id | BxImmediate_Iw2 | BxTraceEnd, BX_IA_JMP_Ap }, /* EB /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JMP_Jd }, /* EC /d */ { 0, BX_IA_IN_ALDX }, /* ED /d */ { 0, BX_IA_IN_EAXDX }, /* EE /d */ { 0, BX_IA_OUT_DXAL }, /* EF /d */ { 0, BX_IA_OUT_DXEAX }, /* F0 /d */ { 0, BX_IA_ERROR }, // LOCK: /* F1 /d */ { BxTraceEnd, BX_IA_INT1 }, /* F2 /d */ { 0, BX_IA_ERROR }, // REPNE/REPNZ /* F3 /d */ { 0, BX_IA_ERROR }, // REP,REPE/REPZ /* F4 /d */ { BxTraceEnd, BX_IA_HLT }, /* F5 /d */ { 0, BX_IA_CMC }, /* F6 /d */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Eb }, /* F7 /d */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Ed }, /* F8 /d */ { 0, BX_IA_CLC }, /* F9 /d */ { 0, BX_IA_STC }, /* FA /d */ { 0, BX_IA_CLI }, /* FB /d */ { 0, BX_IA_STI }, /* FC /d */ { 0, BX_IA_CLD }, /* FD /d */ { 0, BX_IA_STD }, /* FE /d */ { BxGroup4, BX_IA_ERROR, BxOpcodeInfoG4 }, /* FF /d */ { BxGroup5, BX_IA_ERROR, BxOpcodeInfoG5d }, /* 0F 00 /d */ { BxGroup6, BX_IA_ERROR, BxOpcodeInfoG6 }, /* 0F 01 /d */ { BxGroup7, BX_IA_ERROR, BxOpcodeInfoG7 }, /* 0F 02 /d */ { 0, BX_IA_LAR_GvEw }, /* 0F 03 /d */ { 0, BX_IA_LSL_GvEw }, /* 0F 04 /d */ { 0, BX_IA_ERROR }, /* 0F 05 /d */ { BxTraceEnd, BX_IA_SYSCALL_LEGACY }, /* 0F 06 /d */ { BxTraceEnd, BX_IA_CLTS }, /* 0F 07 /d */ { BxTraceEnd, BX_IA_SYSRET_LEGACY }, /* 0F 08 /d */ { BxTraceEnd, BX_IA_INVD }, /* 0F 09 /d */ { BxTraceEnd, BX_IA_WBINVD }, /* 0F 0A /d */ { 0, BX_IA_ERROR }, /* 0F 0B /d */ { BxTraceEnd, BX_IA_UD2A }, /* 0F 0C /d */ { 0, BX_IA_ERROR }, /* 0F 0D /d */ { 0, BX_IA_PREFETCHW }, // 3DNow! PREFETCHW on AMD, NOP on Intel /* 0F 0E /d */ { 0, BX_IA_FEMMS }, // 3DNow! FEMMS /* 0F 0F /d */ { BxImmediate_Ib, BX_IA_ERROR }, // 3DNow! Opcode Table /* 0F 10 /d */ { BxPrefixSSE, BX_IA_MOVUPS_VpsWps, BxOpcodeGroupSSE_0f10 }, /* 0F 11 /d */ { BxPrefixSSE, BX_IA_MOVUPS_WpsVps, BxOpcodeGroupSSE_0f11 }, /* 0F 12 /d */ { BxPrefixSSE, BX_IA_MOVLPS_VpsMq, BxOpcodeGroupSSE_0f12 }, /* 0F 13 /d */ { BxPrefixSSE, BX_IA_MOVLPS_MqVps, BxOpcodeGroupSSE_0f13M }, /* 0F 14 /d */ { BxPrefixSSE, BX_IA_UNPCKLPS_VpsWdq, BxOpcodeGroupSSE_0f14 }, /* 0F 15 /d */ { BxPrefixSSE, BX_IA_UNPCKHPS_VpsWdq, BxOpcodeGroupSSE_0f15 }, /* 0F 16 /d */ { BxPrefixSSE, BX_IA_MOVHPS_VpsMq, BxOpcodeGroupSSE_0f16 }, /* 0F 17 /d */ { BxPrefixSSE, BX_IA_MOVHPS_MqVps, BxOpcodeGroupSSE_0f17M }, #if BX_CPU_LEVEL >= 6 /* 0F 18 /d */ { 0, BX_IA_PREFETCH }, // opcode group G16, PREFETCH hints /* 0F 19 /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1A /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1B /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1C /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1D /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1E /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1F /d */ { 0, BX_IA_NOP }, // multi-byte NOP #else /* 0F 18 /d */ { 0, BX_IA_ERROR }, /* 0F 19 /d */ { 0, BX_IA_ERROR }, /* 0F 1A /d */ { 0, BX_IA_ERROR }, /* 0F 1B /d */ { 0, BX_IA_ERROR }, /* 0F 1C /d */ { 0, BX_IA_ERROR }, /* 0F 1D /d */ { 0, BX_IA_ERROR }, /* 0F 1E /d */ { 0, BX_IA_ERROR }, /* 0F 1F /d */ { 0, BX_IA_ERROR }, #endif /* 0F 20 /d */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_RdCd }, /* 0F 21 /d */ { 0, BX_IA_MOV_RdDd }, /* 0F 22 /d */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_CdRd }, /* 0F 23 /d */ { BxTraceEnd, BX_IA_MOV_DdRd }, /* 0F 24 /d */ { 0, BX_IA_ERROR }, // BX_IA_MOV_RdTd not implemented /* 0F 25 /d */ { 0, BX_IA_ERROR }, /* 0F 26 /d */ { 0, BX_IA_ERROR }, // BX_IA_MOV_TdRd not implemented /* 0F 27 /d */ { 0, BX_IA_ERROR }, /* 0F 28 /d */ { BxPrefixSSE, BX_IA_MOVAPS_VpsWps, BxOpcodeGroupSSE_0f28 }, /* 0F 29 /d */ { BxPrefixSSE, BX_IA_MOVAPS_WpsVps, BxOpcodeGroupSSE_0f29 }, /* 0F 2A /d */ { BxPrefixSSE, BX_IA_CVTPI2PS_VpsQq, BxOpcodeGroupSSE_0f2a }, /* 0F 2B /d */ { BxPrefixSSE, BX_IA_MOVNTPS_MpsVps, BxOpcodeGroupSSE_0f2bM }, /* 0F 2C /d */ { BxPrefixSSE, BX_IA_CVTTPS2PI_PqWps, BxOpcodeGroupSSE_0f2c }, /* 0F 2D /d */ { BxPrefixSSE, BX_IA_CVTPS2PI_PqWps, BxOpcodeGroupSSE_0f2d }, /* 0F 2E /d */ { BxPrefixSSE, BX_IA_UCOMISS_VssWss, BxOpcodeGroupSSE_0f2e }, /* 0F 2F /d */ { BxPrefixSSE, BX_IA_COMISS_VpsWps, BxOpcodeGroupSSE_0f2f }, /* 0F 30 /d */ { 0, BX_IA_WRMSR }, /* 0F 31 /d */ { BxTraceEnd, BX_IA_RDTSC }, // end trace to avoid multiple TSC samples in one cycle /* 0F 32 /d */ { BxTraceEnd, BX_IA_RDMSR }, // end trace to avoid multiple TSC samples in one cycle /* 0F 33 /d */ { 0, BX_IA_RDPMC }, /* 0F 34 /d */ { BxTraceEnd, BX_IA_SYSENTER }, /* 0F 35 /d */ { BxTraceEnd, BX_IA_SYSEXIT }, /* 0F 36 /d */ { 0, BX_IA_ERROR }, /* 0F 37 /d */ { 0, BX_IA_GETSEC }, #if BX_CPU_LEVEL >= 6 /* 0F 38 /d */ { Bx3ByteOp, BX_IA_ERROR, BxOpcode3ByteTable0f38 }, // 3-byte escape #else /* 0F 38 /d */ { 0, BX_IA_ERROR }, #endif /* 0F 39 /d */ { 0, BX_IA_ERROR }, #if BX_CPU_LEVEL >= 6 /* 0F 3A /d */ { Bx3ByteOp | BxImmediate_Ib, BX_IA_ERROR, BxOpcode3ByteTable0f3a }, // 3-byte escape #else /* 0F 3A /d */ { 0, BX_IA_ERROR }, #endif /* 0F 3B /d */ { 0, BX_IA_ERROR }, /* 0F 3C /d */ { 0, BX_IA_ERROR }, /* 0F 3D /d */ { 0, BX_IA_ERROR }, /* 0F 3E /d */ { 0, BX_IA_ERROR }, /* 0F 3F /d */ { 0, BX_IA_ERROR }, /* 0F 40 /d */ { 0, BX_IA_CMOVO_GdEd }, /* 0F 41 /d */ { 0, BX_IA_CMOVNO_GdEd }, /* 0F 42 /d */ { 0, BX_IA_CMOVB_GdEd }, /* 0F 43 /d */ { 0, BX_IA_CMOVNB_GdEd }, /* 0F 44 /d */ { 0, BX_IA_CMOVZ_GdEd }, /* 0F 45 /d */ { 0, BX_IA_CMOVNZ_GdEd }, /* 0F 46 /d */ { 0, BX_IA_CMOVBE_GdEd }, /* 0F 47 /d */ { 0, BX_IA_CMOVNBE_GdEd }, /* 0F 48 /d */ { 0, BX_IA_CMOVS_GdEd }, /* 0F 49 /d */ { 0, BX_IA_CMOVNS_GdEd }, /* 0F 4A /d */ { 0, BX_IA_CMOVP_GdEd }, /* 0F 4B /d */ { 0, BX_IA_CMOVNP_GdEd }, /* 0F 4C /d */ { 0, BX_IA_CMOVL_GdEd }, /* 0F 4D /d */ { 0, BX_IA_CMOVNL_GdEd }, /* 0F 4E /d */ { 0, BX_IA_CMOVLE_GdEd }, /* 0F 4F /d */ { 0, BX_IA_CMOVNLE_GdEd }, /* 0F 50 /d */ { BxPrefixSSE, BX_IA_MOVMSKPS_GdVRps, BxOpcodeGroupSSE_0f50R }, /* 0F 51 /d */ { BxPrefixSSE, BX_IA_SQRTPS_VpsWps, BxOpcodeGroupSSE_0f51 }, /* 0F 52 /d */ { BxPrefixSSE, BX_IA_RSQRTPS_VpsWps, BxOpcodeGroupSSE_0f52 }, /* 0F 53 /d */ { BxPrefixSSE, BX_IA_RCPPS_VpsWps, BxOpcodeGroupSSE_0f53 }, /* 0F 54 /d */ { BxPrefixSSE, BX_IA_ANDPS_VpsWps, BxOpcodeGroupSSE_0f54 }, /* 0F 55 /d */ { BxPrefixSSE, BX_IA_ANDNPS_VpsWps, BxOpcodeGroupSSE_0f55 }, /* 0F 56 /d */ { BxPrefixSSE, BX_IA_ORPS_VpsWps, BxOpcodeGroupSSE_0f56 }, /* 0F 57 /d */ { BxPrefixSSE, BX_IA_XORPS_VpsWps, BxOpcodeGroupSSE_0f57 }, /* 0F 58 /d */ { BxPrefixSSE, BX_IA_ADDPS_VpsWps, BxOpcodeGroupSSE_0f58 }, /* 0F 59 /d */ { BxPrefixSSE, BX_IA_MULPS_VpsWps, BxOpcodeGroupSSE_0f59 }, /* 0F 5A /d */ { BxPrefixSSE, BX_IA_CVTPS2PD_VpdWps, BxOpcodeGroupSSE_0f5a }, /* 0F 5B /d */ { BxPrefixSSE, BX_IA_CVTDQ2PS_VpsWdq, BxOpcodeGroupSSE_0f5b }, /* 0F 5C /d */ { BxPrefixSSE, BX_IA_SUBPS_VpsWps, BxOpcodeGroupSSE_0f5c }, /* 0F 5D /d */ { BxPrefixSSE, BX_IA_MINPS_VpsWps, BxOpcodeGroupSSE_0f5d }, /* 0F 5E /d */ { BxPrefixSSE, BX_IA_DIVPS_VpsWps, BxOpcodeGroupSSE_0f5e }, /* 0F 5F /d */ { BxPrefixSSE, BX_IA_MAXPS_VpsWps, BxOpcodeGroupSSE_0f5f }, /* 0F 60 /d */ { BxPrefixSSE, BX_IA_PUNPCKLBW_PqQd, BxOpcodeGroupSSE_0f60 }, /* 0F 61 /d */ { BxPrefixSSE, BX_IA_PUNPCKLWD_PqQd, BxOpcodeGroupSSE_0f61 }, /* 0F 62 /d */ { BxPrefixSSE, BX_IA_PUNPCKLDQ_PqQd, BxOpcodeGroupSSE_0f62 }, /* 0F 63 /d */ { BxPrefixSSE, BX_IA_PACKSSWB_PqQq, BxOpcodeGroupSSE_0f63 }, /* 0F 64 /d */ { BxPrefixSSE, BX_IA_PCMPGTB_PqQq, BxOpcodeGroupSSE_0f64 }, /* 0F 65 /d */ { BxPrefixSSE, BX_IA_PCMPGTW_PqQq, BxOpcodeGroupSSE_0f65 }, /* 0F 66 /d */ { BxPrefixSSE, BX_IA_PCMPGTD_PqQq, BxOpcodeGroupSSE_0f66 }, /* 0F 67 /d */ { BxPrefixSSE, BX_IA_PACKUSWB_PqQq, BxOpcodeGroupSSE_0f67 }, /* 0F 68 /d */ { BxPrefixSSE, BX_IA_PUNPCKHBW_PqQq, BxOpcodeGroupSSE_0f68 }, /* 0F 69 /d */ { BxPrefixSSE, BX_IA_PUNPCKHWD_PqQq, BxOpcodeGroupSSE_0f69 }, /* 0F 6A /d */ { BxPrefixSSE, BX_IA_PUNPCKHDQ_PqQq, BxOpcodeGroupSSE_0f6a }, /* 0F 6B /d */ { BxPrefixSSE, BX_IA_PACKSSDW_PqQq, BxOpcodeGroupSSE_0f6b }, /* 0F 6C /d */ { BxPrefixSSE66, BX_IA_PUNPCKLQDQ_VdqWdq }, /* 0F 6D /d */ { BxPrefixSSE66, BX_IA_PUNPCKHQDQ_VdqWdq }, /* 0F 6E /d */ { BxPrefixSSE, BX_IA_MOVD_PqEd, BxOpcodeGroupSSE_0f6e }, /* 0F 6F /d */ { BxPrefixSSE, BX_IA_MOVQ_PqQq, BxOpcodeGroupSSE_0f6f }, /* 0F 70 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PSHUFW_PqQqIb, BxOpcodeGroupSSE_0f70 }, /* 0F 71 /d */ { BxGroup12, BX_IA_ERROR, BxOpcodeInfoG12R }, /* 0F 72 /d */ { BxGroup13, BX_IA_ERROR, BxOpcodeInfoG13R }, /* 0F 73 /d */ { BxGroup14, BX_IA_ERROR, BxOpcodeInfoG14R }, /* 0F 74 /d */ { BxPrefixSSE, BX_IA_PCMPEQB_PqQq, BxOpcodeGroupSSE_0f74 }, /* 0F 75 /d */ { BxPrefixSSE, BX_IA_PCMPEQW_PqQq, BxOpcodeGroupSSE_0f75 }, /* 0F 76 /d */ { BxPrefixSSE, BX_IA_PCMPEQD_PqQq, BxOpcodeGroupSSE_0f76 }, /* 0F 77 /d */ { BxPrefixSSE, BX_IA_EMMS, BxOpcodeGroupSSE_ERR }, /* 0F 78 /d */ { BxPrefixSSE, BX_IA_VMREAD_EdGd, BxOpcodeGroupSSE4A_0f78 }, /* 0F 79 /d */ { BxPrefixSSE, BX_IA_VMWRITE_GdEd, BxOpcodeGroupSSE4A_0f79 }, /* 0F 7A /d */ { 0, BX_IA_ERROR }, /* 0F 7B /d */ { 0, BX_IA_ERROR }, /* 0F 7C /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7c }, /* 0F 7D /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7d }, /* 0F 7E /d */ { BxPrefixSSE, BX_IA_MOVD_EdPd, BxOpcodeGroupSSE_0f7e }, /* 0F 7F /d */ { BxPrefixSSE, BX_IA_MOVQ_QqPq, BxOpcodeGroupSSE_0f7f }, /* 0F 80 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JO_Jd }, /* 0F 81 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNO_Jd }, /* 0F 82 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JB_Jd }, /* 0F 83 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNB_Jd }, /* 0F 84 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JZ_Jd }, /* 0F 85 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNZ_Jd }, /* 0F 86 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JBE_Jd }, /* 0F 87 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNBE_Jd }, /* 0F 88 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JS_Jd }, /* 0F 89 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNS_Jd }, /* 0F 8A /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JP_Jd }, /* 0F 8B /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNP_Jd }, /* 0F 8C /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JL_Jd }, /* 0F 8D /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNL_Jd }, /* 0F 8E /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JLE_Jd }, /* 0F 8F /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNLE_Jd }, /* 0F 90 /d */ { 0, BX_IA_SETO_Eb }, /* 0F 91 /d */ { 0, BX_IA_SETNO_Eb }, /* 0F 92 /d */ { 0, BX_IA_SETB_Eb }, /* 0F 93 /d */ { 0, BX_IA_SETNB_Eb }, /* 0F 94 /d */ { 0, BX_IA_SETZ_Eb }, /* 0F 95 /d */ { 0, BX_IA_SETNZ_Eb }, /* 0F 96 /d */ { 0, BX_IA_SETBE_Eb }, /* 0F 97 /d */ { 0, BX_IA_SETNBE_Eb }, /* 0F 98 /d */ { 0, BX_IA_SETS_Eb }, /* 0F 99 /d */ { 0, BX_IA_SETNS_Eb }, /* 0F 9A /d */ { 0, BX_IA_SETP_Eb }, /* 0F 9B /d */ { 0, BX_IA_SETNP_Eb }, /* 0F 9C /d */ { 0, BX_IA_SETL_Eb }, /* 0F 9D /d */ { 0, BX_IA_SETNL_Eb }, /* 0F 9E /d */ { 0, BX_IA_SETLE_Eb }, /* 0F 9F /d */ { 0, BX_IA_SETNLE_Eb }, /* 0F A0 /d */ { 0, BX_IA_PUSH32_FS }, /* 0F A1 /d */ { 0, BX_IA_POP32_FS }, /* 0F A2 /d */ { 0, BX_IA_CPUID }, /* 0F A3 /d */ { 0, BX_IA_BT_EdGd }, /* 0F A4 /d */ { BxImmediate_Ib, BX_IA_SHLD_EdGdIb }, /* 0F A5 /d */ { 0, BX_IA_SHLD_EdGd }, /* 0F A6 /d */ { 0, BX_IA_ERROR }, // CMPXCHG_XBTS not implemented /* 0F A7 /d */ { 0, BX_IA_ERROR }, // CMPXCHG_IBTS not implemented /* 0F A8 /d */ { 0, BX_IA_PUSH32_GS }, /* 0F A9 /d */ { 0, BX_IA_POP32_GS }, /* 0F AA /d */ { BxTraceEnd, BX_IA_RSM }, /* 0F AB /d */ { BxLockable, BX_IA_BTS_EdGd }, /* 0F AC /d */ { BxImmediate_Ib, BX_IA_SHRD_EdGdIb }, /* 0F AD /d */ { 0, BX_IA_SHRD_EdGd }, /* 0F AE /d */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15 }, /* 0F AF /d */ { 0, BX_IA_IMUL_GdEd }, /* 0F B0 /d */ { BxLockable, BX_IA_CMPXCHG_EbGb }, /* 0F B1 /d */ { BxLockable, BX_IA_CMPXCHG_EdGd }, /* 0F B2 /d */ { 0, BX_IA_LSS_GdMp }, /* 0F B3 /d */ { BxLockable, BX_IA_BTR_EdGd }, /* 0F B4 /d */ { 0, BX_IA_LFS_GdMp }, /* 0F B5 /d */ { 0, BX_IA_LGS_GdMp }, /* 0F B6 /d */ { 0, BX_IA_MOVZX_GdEb }, /* 0F B7 /d */ { 0, BX_IA_MOVZX_GdEw }, /* 0F B8 /d */ { BxPrefixSSEF3, BX_IA_POPCNT_GdEd }, /* 0F B9 /d */ { BxTraceEnd, BX_IA_UD2B }, /* 0F BA /d */ { BxGroup8, BX_IA_ERROR, BxOpcodeInfoG8EdIb }, /* 0F BB /d */ { BxLockable, BX_IA_BTC_EdGd }, /* 0F BC /d */ { BxPrefixSSE, BX_IA_BSF_GdEd, BxOpcodeGroupSSE_TZCNT32 }, /* 0F BD /d */ { BxPrefixSSE, BX_IA_BSR_GdEd, BxOpcodeGroupSSE_LZCNT32 }, /* 0F BE /d */ { 0, BX_IA_MOVSX_GdEb }, /* 0F BF /d */ { 0, BX_IA_MOVSX_GdEw }, /* 0F C0 /d */ { BxLockable, BX_IA_XADD_EbGb }, /* 0F C1 /d */ { BxLockable, BX_IA_XADD_EdGd }, /* 0F C2 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_CMPPS_VpsWpsIb, BxOpcodeGroupSSE_0fc2 }, /* 0F C3 /d */ { BxPrefixSSE, BX_IA_MOVNTI32_MdGd, BxOpcodeGroupSSE_ERR }, /* 0F C4 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PINSRW_PqEwIb, BxOpcodeGroupSSE_0fc4 }, /* 0F C5 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PEXTRW_GdPqIb, BxOpcodeGroupSSE_0fc5R }, /* 0F C6 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_SHUFPS_VpsWpsIb, BxOpcodeGroupSSE_0fc6 }, /* 0F C7 /d */ { BxGroup9, BX_IA_ERROR, BxOpcodeInfoG9M }, /* 0F C8 /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F C9 /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CA /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CB /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CC /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CD /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CE /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CF /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F D0 /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd0 }, /* 0F D1 /d */ { BxPrefixSSE, BX_IA_PSRLW_PqQq, BxOpcodeGroupSSE_0fd1 }, /* 0F D2 /d */ { BxPrefixSSE, BX_IA_PSRLD_PqQq, BxOpcodeGroupSSE_0fd2 }, /* 0F D3 /d */ { BxPrefixSSE, BX_IA_PSRLQ_PqQq, BxOpcodeGroupSSE_0fd3 }, /* 0F D4 /d */ { BxPrefixSSE, BX_IA_PADDQ_PqQq, BxOpcodeGroupSSE_0fd4 }, /* 0F D5 /d */ { BxPrefixSSE, BX_IA_PMULLW_PqQq, BxOpcodeGroupSSE_0fd5 }, /* 0F D6 /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd6 }, /* 0F D7 /d */ { BxPrefixSSE, BX_IA_PMOVMSKB_GdPRq, BxOpcodeGroupSSE_0fd7R }, /* 0F D8 /d */ { BxPrefixSSE, BX_IA_PSUBUSB_PqQq, BxOpcodeGroupSSE_0fd8 }, /* 0F D9 /d */ { BxPrefixSSE, BX_IA_PSUBUSW_PqQq, BxOpcodeGroupSSE_0fd9 }, /* 0F DA /d */ { BxPrefixSSE, BX_IA_PMINUB_PqQq, BxOpcodeGroupSSE_0fda }, /* 0F DB /d */ { BxPrefixSSE, BX_IA_PAND_PqQq, BxOpcodeGroupSSE_0fdb }, /* 0F DC /d */ { BxPrefixSSE, BX_IA_PADDUSB_PqQq, BxOpcodeGroupSSE_0fdc }, /* 0F DD /d */ { BxPrefixSSE, BX_IA_PADDUSW_PqQq, BxOpcodeGroupSSE_0fdd }, /* 0F DE /d */ { BxPrefixSSE, BX_IA_PMAXUB_PqQq, BxOpcodeGroupSSE_0fde }, /* 0F DF /d */ { BxPrefixSSE, BX_IA_PANDN_PqQq, BxOpcodeGroupSSE_0fdf }, /* 0F E0 /d */ { BxPrefixSSE, BX_IA_PAVGB_PqQq, BxOpcodeGroupSSE_0fe0 }, /* 0F E1 /d */ { BxPrefixSSE, BX_IA_PSRAW_PqQq, BxOpcodeGroupSSE_0fe1 }, /* 0F E2 /d */ { BxPrefixSSE, BX_IA_PSRAD_PqQq, BxOpcodeGroupSSE_0fe2 }, /* 0F E3 /d */ { BxPrefixSSE, BX_IA_PAVGW_PqQq, BxOpcodeGroupSSE_0fe3 }, /* 0F E4 /d */ { BxPrefixSSE, BX_IA_PMULHUW_PqQq, BxOpcodeGroupSSE_0fe4 }, /* 0F E5 /d */ { BxPrefixSSE, BX_IA_PMULHW_PqQq, BxOpcodeGroupSSE_0fe5 }, /* 0F E6 /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fe6 }, /* 0F E7 /d */ { BxPrefixSSE, BX_IA_MOVNTQ_MqPq, BxOpcodeGroupSSE_0fe7M }, /* 0F E8 /d */ { BxPrefixSSE, BX_IA_PSUBSB_PqQq, BxOpcodeGroupSSE_0fe8 }, /* 0F E9 /d */ { BxPrefixSSE, BX_IA_PSUBSW_PqQq, BxOpcodeGroupSSE_0fe9 }, /* 0F EA /d */ { BxPrefixSSE, BX_IA_PMINSW_PqQq, BxOpcodeGroupSSE_0fea }, /* 0F EB /d */ { BxPrefixSSE, BX_IA_POR_PqQq, BxOpcodeGroupSSE_0feb }, /* 0F EC /d */ { BxPrefixSSE, BX_IA_PADDSB_PqQq, BxOpcodeGroupSSE_0fec }, /* 0F ED /d */ { BxPrefixSSE, BX_IA_PADDSW_PqQq, BxOpcodeGroupSSE_0fed }, /* 0F EE /d */ { BxPrefixSSE, BX_IA_PMAXSW_PqQq, BxOpcodeGroupSSE_0fee }, /* 0F EF /d */ { BxPrefixSSE, BX_IA_PXOR_PqQq, BxOpcodeGroupSSE_0fef }, /* 0F F0 /d */ { BxPrefixSSEF2, BX_IA_LDDQU_VdqMdq }, /* 0F F1 /d */ { BxPrefixSSE, BX_IA_PSLLW_PqQq, BxOpcodeGroupSSE_0ff1 }, /* 0F F2 /d */ { BxPrefixSSE, BX_IA_PSLLD_PqQq, BxOpcodeGroupSSE_0ff2 }, /* 0F F3 /d */ { BxPrefixSSE, BX_IA_PSLLQ_PqQq, BxOpcodeGroupSSE_0ff3 }, /* 0F F4 /d */ { BxPrefixSSE, BX_IA_PMULUDQ_PqQq, BxOpcodeGroupSSE_0ff4 }, /* 0F F5 /d */ { BxPrefixSSE, BX_IA_PMADDWD_PqQq, BxOpcodeGroupSSE_0ff5 }, /* 0F F6 /d */ { BxPrefixSSE, BX_IA_PSADBW_PqQq, BxOpcodeGroupSSE_0ff6 }, /* 0F F7 /d */ { BxPrefixSSE, BX_IA_MASKMOVQ_PqPRq, BxOpcodeGroupSSE_0ff7R }, /* 0F F8 /d */ { BxPrefixSSE, BX_IA_PSUBB_PqQq, BxOpcodeGroupSSE_0ff8 }, /* 0F F9 /d */ { BxPrefixSSE, BX_IA_PSUBW_PqQq, BxOpcodeGroupSSE_0ff9 }, /* 0F FA /d */ { BxPrefixSSE, BX_IA_PSUBD_PqQq, BxOpcodeGroupSSE_0ffa }, /* 0F FB /d */ { BxPrefixSSE, BX_IA_PSUBQ_PqQq, BxOpcodeGroupSSE_0ffb }, /* 0F FC /d */ { BxPrefixSSE, BX_IA_PADDB_PqQq, BxOpcodeGroupSSE_0ffc }, /* 0F FD /d */ { BxPrefixSSE, BX_IA_PADDW_PqQq, BxOpcodeGroupSSE_0ffd }, /* 0F FE /d */ { BxPrefixSSE, BX_IA_PADDD_PqQq, BxOpcodeGroupSSE_0ffe }, /* 0F FF /d */ { 0, BX_IA_ERROR } }; int BX_CPP_AttrRegparmN(3) BX_CPU_C::fetchDecode32(const Bit8u *iptr, bxInstruction_c *i, unsigned remainingInPage) { if (remainingInPage > 15) remainingInPage = 15; unsigned remain = remainingInPage; // remain must be at least 1 bx_bool is_32, lock=0; unsigned b1, b2 = 0, os_32, ia_opcode = 0; unsigned rm = 0, mod=0, nnn=0, mod_mem = 0, rep = 0; unsigned seg = BX_SEG_REG_DS, seg_override = BX_SEG_REG_NULL; #define SSE_PREFIX_NONE 0 #define SSE_PREFIX_66 1 #define SSE_PREFIX_F3 2 #define SSE_PREFIX_F2 3 unsigned sse_prefix = SSE_PREFIX_NONE; int vvv = -1; #if BX_SUPPORT_AVX int had_vex = 0, had_xop = 0, use_vvv = 0; bx_bool vex_w = 0, vex_l = 0; #endif os_32 = is_32 = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b; i->ResolveModrm = 0; i->init(/*os32*/ is_32, /*as32*/ is_32, /*os64*/ 0, /*as64*/ 0); fetch_b1: b1 = *iptr++; remain--; switch (b1) { case 0x0f: // 2-byte escape if (remain != 0) { remain--; b1 = 0x100 | *iptr++; break; } return(-1); case 0x66: // OpSize os_32 = !is_32; if(!sse_prefix) sse_prefix = SSE_PREFIX_66; i->setOs32B(os_32); if (remain != 0) { goto fetch_b1; } return(-1); case 0x67: // AddrSize i->setAs32B(!is_32); if (remain != 0) { goto fetch_b1; } return(-1); case 0xf2: // REPNE/REPNZ case 0xf3: // REP/REPE/REPZ sse_prefix = (b1 & 3) ^ 1; rep = b1 & 3; if (remain != 0) { goto fetch_b1; } return(-1); case 0x26: // ES: case 0x2e: // CS: case 0x36: // SS: case 0x3e: // DS: seg_override = (b1 >> 3) & 3; if (remain != 0) { goto fetch_b1; } return(-1); case 0x64: // FS: case 0x65: // GS: seg_override = (b1 & 0xf); if (remain != 0) { goto fetch_b1; } return(-1); case 0xf0: // LOCK: lock = 1; if (remain != 0) { goto fetch_b1; } return(-1); default: break; } i->modRMForm.Id = 0; unsigned index = b1 + (os_32 << 9); // *512 unsigned attr = BxOpcodeInfo32[index].Attr; bx_bool has_modrm = 0; #if BX_SUPPORT_AVX if ((attr & BxGroupX) == BxPrefixVEX && (*iptr & 0xc0) == 0xc0) { // VEX had_vex = 1; if (sse_prefix) had_vex = -1; if (! protected_mode()) had_vex = -1; unsigned vex, vex_opcext = 1; if (remain != 0) { remain--; vex = *iptr++; } else return(-1); if (b1 == 0xc4) { // decode 3-byte VEX prefix vex_opcext = vex & 0x1f; if (remain != 0) { remain--; vex = *iptr++; // fetch VEX3 } else return(-1); vex_w = (vex >> 7) & 0x1; } vvv = 15 - ((vex >> 3) & 0xf); vex_l = (vex >> 2) & 0x1; i->setVL(BX_VL128 + vex_l); sse_prefix = vex & 0x3; if (remain != 0) { remain--; b1 = *iptr++; // fetch new b1 } else return(-1); b1 += 256 * vex_opcext; if (b1 < 256 || b1 >= 1024) had_vex = -1; else { if (b1 >= 512) has_modrm = 1; else has_modrm = BxOpcodeHasModrm32[b1]; } } else if (b1 == 0x8f && (*iptr & 0xc8) == 0xc8) { // 3 byte XOP prefix had_xop = 1; if (! protected_mode()) had_xop = -1; unsigned vex; if (remain != 0) { remain--; vex = *iptr++; // fetch XOP2 } else return(-1); unsigned xop_opcext = (vex & 0x1f) - 8; if (xop_opcext >= 3) had_xop = -1; if (remain != 0) { remain--; vex = *iptr++; // fetch XOP3 } else return(-1); vex_w = (vex >> 7) & 0x1; vvv = 15 - ((vex >> 3) & 0xf); vex_l = (vex >> 2) & 0x1; i->setVL(BX_VL128 + vex_l); sse_prefix = vex & 0x3; if (sse_prefix) had_xop = -1; if (remain != 0) { remain--; b1 = *iptr++; // fetch new b1 } else return(-1); has_modrm = 1; b1 += 256 * xop_opcext; } else #endif { has_modrm = BxOpcodeHasModrm32[b1]; } if (has_modrm) { #if BX_CPU_LEVEL >= 6 unsigned b3 = 0; // handle 3-byte escape if ((attr & BxGroupX) == Bx3ByteOp) { if (remain != 0) { remain--; b3 = *iptr++; } else return(-1); } #endif // opcode requires modrm byte if (remain != 0) { remain--; b2 = *iptr++; } else return(-1); // Parse mod-nnn-rm and related bytes mod = b2 & 0xc0; // leave unshifted nnn = (b2 >> 3) & 0x7; rm = b2 & 0x7; i->setFoo((b2 | (b1 << 8)) & 0x7ff); /* for x87 */ // MOVs with CRx and DRx always use register ops and ignore the mod field. if ((b1 & ~3) == 0x120) mod = 0xc0; if (mod == 0xc0) { // mod == 11b i->assertModC0(); goto modrm_done; } mod_mem = 1; i->setSibBase(rm); // initialize with rm to use BxResolve32Base i->setSibIndex(BX_NIL_REGISTER); // initialize displ32 with zero to include cases with no diplacement i->modRMForm.displ32u = 0; if (i->as32L()) { // 32-bit addressing modes; note that mod==11b handled above i->ResolveModrm = &BX_CPU_C::BxResolve32Base; if (rm != 4) { // no s-i-b byte if (mod == 0x00) { // mod == 00b if (rm == 5) { i->setSibBase(BX_NIL_REGISTER); if (remain > 3) { i->modRMForm.displ32u = FetchDWORD(iptr); iptr += 4; remain -= 4; } else return(-1); } // mod==00b, rm!=4, rm!=5 goto modrm_done; } seg = sreg_mod1or2_base32[rm]; } else { // mod!=11b, rm==4, s-i-b byte follows unsigned sib, base, index, scale; if (remain != 0) { sib = *iptr++; remain--; } else { return(-1); } base = sib & 0x7; sib >>= 3; index = sib & 0x7; sib >>= 3; scale = sib; i->setSibScale(scale); i->setSibBase(base); // this part is a little tricky - assign index value always, // it will be really used if the instruction is Gather. Others // assume that BxResolve32Base will do the right thing. i->setSibIndex(index); if (index != 4) { i->ResolveModrm = &BX_CPU_C::BxResolve32BaseIndex; } if (mod == 0x00) { // mod==00b, rm==4 seg = sreg_mod0_base32[base]; if (base == 5) { i->setSibBase(BX_NIL_REGISTER); if (remain > 3) { i->modRMForm.displ32u = FetchDWORD(iptr); iptr += 4; remain -= 4; } else { return(-1); } } // mod==00b, rm==4, base!=5 goto modrm_done; } seg = sreg_mod1or2_base32[base]; } if (mod == 0x40) { // mod==01b if (remain != 0) { // 8 sign extended to 32 i->modRMForm.displ32u = (Bit8s) *iptr++; remain--; goto modrm_done; } else { return(-1); } } // (mod == 0x80), mod==10b if (remain > 3) { i->modRMForm.displ32u = FetchDWORD(iptr); iptr += 4; remain -= 4; } else { return(-1); } } else { // 16-bit addressing modes, mod==11b handled above i->ResolveModrm = &BX_CPU_C::BxResolve16BaseIndex; i->setSibBase(Resolve16BaseReg[rm]); i->setSibIndex(Resolve16IndexReg[rm]); if (mod == 0x00) { // mod == 00b seg = sreg_mod00_rm16[rm]; if (rm == 6) { i->setSibBase(BX_NIL_REGISTER); if (remain > 1) { i->modRMForm.displ16u = FetchWORD(iptr); iptr += 2; remain -= 2; goto modrm_done; } else return(-1); } goto modrm_done; } seg = sreg_mod01or10_rm16[rm]; if (mod == 0x40) { // mod == 01b if (remain != 0) { // 8 sign extended to 16 i->modRMForm.displ16u = (Bit8s) *iptr++; remain--; goto modrm_done; } else { return(-1); } } // (mod == 0x80) mod == 10b if (remain > 1) { i->modRMForm.displ16u = FetchWORD(iptr); iptr += 2; remain -= 2; } else { return(-1); } } modrm_done: // Resolve ExecutePtr and additional opcode Attr const BxOpcodeInfo_t *OpcodeInfoPtr = &(BxOpcodeInfo32[index]); #if BX_SUPPORT_AVX if (had_vex != 0) { if (had_vex < 0) OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR else OpcodeInfoPtr = &BxOpcodeTableAVX[(b1-256) + 768*vex_l]; } else if (had_xop != 0) { if (had_xop < 0) OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR else OpcodeInfoPtr = &BxOpcodeTableXOP[b1 + 768*vex_l]; } #endif attr = OpcodeInfoPtr->Attr; while(attr & BxGroupX) { Bit32u group = attr & BxGroupX; attr &= ~BxGroupX; if (group < BxPrefixSSE) { /* For opcodes with only one allowed SSE prefix */ if (sse_prefix != (group >> 4)) { OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR } /* get additional attributes from group table */ attr |= OpcodeInfoPtr->Attr; break; } switch(group) { case BxGroupN: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn]); break; case BxSplitGroupN: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn + (mod_mem << 3)]); break; #if BX_SUPPORT_AVX case BxSplitVexW64: // VexW is ignored in 32-bit mode BX_ASSERT(had_vex != 0 || had_xop != 0); OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[0]); break; case BxSplitVexW: // VexW is a real opcode extension BX_ASSERT(had_vex != 0 || had_xop != 0); OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[vex_w]); break; case BxSplitMod11B: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[mod_mem]); break; #endif #if BX_CPU_LEVEL >= 6 case Bx3ByteOp: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[b3]); break; #endif case BxOSizeGrp: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[os_32]); if (sse_prefix == SSE_PREFIX_66) sse_prefix = 0; break; case BxPrefixSSE: /* For SSE opcodes look into another table with the opcode prefixes (NONE, 0x66, 0xF3, 0xF2) */ if (sse_prefix) { OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[sse_prefix-1]); break; } continue; case BxFPEscape: if (mod_mem) OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn]); else OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[(b2 & 0x3f) + 8]); break; case BxPrefixVEX: continue; default: BX_PANIC(("fetchdecode32: Unknown opcode group %d", group)); } /* get additional attributes from group table */ attr |= OpcodeInfoPtr->Attr; } ia_opcode = OpcodeInfoPtr->IA; } else { // Opcode does not require a MODRM byte. // Note that a 2-byte opcode (0F XX) will jump to before // the if() above after fetching the 2nd byte, so this path is // taken in all cases if a modrm byte is NOT required. const BxOpcodeInfo_t *OpcodeInfoPtr = &(BxOpcodeInfo32[index]); #if BX_SUPPORT_AVX if (had_vex != 0) { if (had_vex < 0) OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR else OpcodeInfoPtr = &BxOpcodeTableAVX[(b1-256) + 768*vex_l]; } else if (had_xop != 0) { if (had_xop < 0) OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR else OpcodeInfoPtr = &BxOpcodeTableXOP[b1 + 768*vex_l]; } #endif unsigned group = attr & BxGroupX; if (group == BxPrefixSSE && sse_prefix) { OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[sse_prefix-1]); } ia_opcode = OpcodeInfoPtr->IA; rm = b1 & 0x7; nnn = (b1 >> 3) & 0x7; } if (lock) { // lock prefix invalid opcode // lock prefix not allowed or destination operand is not memory if (!mod_mem || !(attr & BxLockable)) { #if BX_CPU_LEVEL >= 6 if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_ALT_MOV_CR8) && (ia_opcode == BX_IA_MOV_CR0Rd || ia_opcode == BX_IA_MOV_RdCR0)) { nnn = 8; // extend CR0 -> CR8 } else #endif { BX_INFO(("LOCK prefix unallowed (op1=0x%x, modrm=0x%02x)", b1, b2)); // replace execution function with undefined-opcode ia_opcode = BX_IA_ERROR; } } } if (attr & BxRepeatable) i->setRepUsed(rep); unsigned imm_mode = attr & BxImmediate; if (imm_mode) { // make sure iptr was advanced after Ib(), Iw() and Id() switch (imm_mode) { case BxImmediate_I1: i->modRMForm.Ib = 1; break; case BxImmediate_Ib: if (remain != 0) { i->modRMForm.Ib = *iptr++; remain--; } else { return(-1); } break; case BxImmediate_BrOff8: case BxImmediate_Ib_SE: // Sign extend to OS size if (remain != 0) { Bit8s temp8s = *iptr; // this code works correctly both for LE and BE hosts if (i->os32L()) i->modRMForm.Id = (Bit32s) temp8s; else i->modRMForm.Iw = (Bit16s) temp8s; remain--; } else { return(-1); } break; case BxImmediate_Iw: if (remain > 1) { i->modRMForm.Iw = FetchWORD(iptr); iptr += 2; remain -= 2; } else { return(-1); } break; case BxImmediate_Id: if (remain > 3) { i->modRMForm.Id = FetchDWORD(iptr); iptr += 4; remain -= 4; } else { return(-1); } break; case BxImmediate_O: // For instructions which embed the address in the opcode. if (i->as32L()) { // fetch 32bit address into Id if (remain > 3) { i->modRMForm.Id = FetchDWORD(iptr); remain -= 4; } else return(-1); } else { // fetch 16bit address into Id if (remain > 1) { i->modRMForm.Id = (Bit32u) FetchWORD(iptr); remain -= 2; } else return(-1); } break; default: BX_INFO(("b1 was %x", b1)); BX_PANIC(("fetchdecode32: imm_mode = %u", imm_mode)); } unsigned imm_mode2 = attr & BxImmediate2; if (imm_mode2) { switch (imm_mode2) { case BxImmediate_Ib2: if (remain != 0) { i->modRMForm.Ib2 = *iptr; remain--; } else { return(-1); } break; case BxImmediate_Iw2: if (remain > 1) { i->modRMForm.Iw2 = FetchWORD(iptr); remain -= 2; } else { return(-1); } break; default: BX_INFO(("b1 was %x", b1)); BX_PANIC(("fetchdecode: imm_mode2 = %u", imm_mode2)); } } } #if BX_SUPPORT_3DNOW if(b1 == 0x10f) ia_opcode = Bx3DNowOpcode[i->modRMForm.Ib]; #endif // assign sources for (unsigned n = 0; n <= 3; n++) { unsigned def = (unsigned) BxOpcodesTable[ia_opcode].src[n] & 0xf; #if BX_SUPPORT_AVX if (def == BX_SRC_RM_VIB) { def = (vex_w) ? BX_SRC_RM : BX_SRC_VIB; } else if (def == BX_SRC_VIB_RM) { def = (vex_w) ? BX_SRC_VIB : BX_SRC_RM; } else if (def == BX_SRC_RM_VVV) { def = (vex_w) ? BX_SRC_RM : BX_SRC_VVV; } else if (def == BX_SRC_VVV_RM) { def = (vex_w) ? BX_SRC_VVV : BX_SRC_RM; } #endif switch(def) { case BX_SRC_EAX: i->setSrcReg(n, 0); break; case BX_SRC_NNN: i->setSrcReg(n, nnn); break; case BX_SRC_RM: i->setSrcReg(n, mod_mem ? BX_TMP_REGISTER : rm); break; #if BX_SUPPORT_AVX case BX_SRC_MEM_NO_VVV: if (mod_mem) break; // else fall through case BX_SRC_VVV: i->setSrcReg(n, vvv); use_vvv = 1; break; case BX_SRC_VIB: i->setSrcReg(n, (i->Ib() >> 4) & 7); break; #endif default: if (def != BX_SRC_NONE) BX_PANIC(("fetchdecode32: unknown definition %d for src %d", def, n)); } } // assign memory segment override if (! BX_NULL_SEG_REG(seg_override)) seg = seg_override; i->setSeg(seg); i->setILen(remainingInPage - remain); i->setIaOpcode(ia_opcode); #if BX_SUPPORT_AVX if (had_vex > 0 || had_xop > 0) { if (! use_vvv && vvv != 0) { ia_opcode = BX_IA_ERROR; } if ((attr & BxVexW0) != 0 && vex_w) { ia_opcode = BX_IA_ERROR; } if ((attr & BxVexW1) != 0 && !vex_w) { ia_opcode = BX_IA_ERROR; } } else { BX_ASSERT(! use_vvv); } #endif if (mod_mem) { i->execute = BxOpcodesTable[ia_opcode].execute1; i->handlers.execute2 = BxOpcodesTable[ia_opcode].execute2; if (ia_opcode == BX_IA_MOV32_GdEd) { if (seg == BX_SEG_REG_SS) i->execute = &BX_CPU_C::MOV32S_GdEdM; } if (ia_opcode == BX_IA_MOV32_EdGd) { if (seg == BX_SEG_REG_SS) i->execute = &BX_CPU_C::MOV32S_EdGdM; } } else { i->execute = BxOpcodesTable[ia_opcode].execute2; i->handlers.execute2 = NULL; } BX_ASSERT(i->execute); #if BX_CPU_LEVEL >= 6 Bit32u op_flags = BxOpcodesTable[ia_opcode].src[3]; if (! BX_CPU_THIS_PTR sse_ok) { if (op_flags & BX_PREPARE_SSE) { if (i->execute != &BX_CPU_C::BxError) i->execute = &BX_CPU_C::BxNoSSE; return(1); } } #if BX_SUPPORT_AVX if (! BX_CPU_THIS_PTR avx_ok) { if (op_flags & BX_PREPARE_AVX) { if (i->execute != &BX_CPU_C::BxError) i->execute = &BX_CPU_C::BxNoAVX; return(1); } } #endif #endif if ((attr & BxTraceEnd) || ia_opcode == BX_IA_ERROR) return(1); return(0); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BxError(bxInstruction_c *i) { unsigned ia_opcode = i->getIaOpcode(); if (ia_opcode == BX_IA_ERROR) { BX_DEBUG(("BxError: Encountered an unknown instruction (signalling #UD)")); #if BX_DISASM && BX_DEBUGGER == 0 // with debugger it easy to see the #UD if (LOG_THIS getonoff(LOGLEV_DEBUG)) debug_disasm_instruction(BX_CPU_THIS_PTR prev_rip); #endif } else { BX_DEBUG(("%s: instruction not supported - signalling #UD (features bitmask: 0x%08x)", get_bx_opcode_name(ia_opcode), BX_CPU_THIS_PTR isa_extensions_bitmask)); } exception(BX_UD_EXCEPTION, 0); BX_NEXT_TRACE(i); // keep compiler happy } const char *get_bx_opcode_name(Bit16u ia_opcode) { static const char* BxOpcodeNamesTable[BX_IA_LAST] = { #define bx_define_opcode(a, b, c, d, s1, s2, s3, s4, e) #a, #include "ia_opcodes.h" }; #undef bx_define_opcode return (ia_opcode < BX_IA_LAST) ? BxOpcodeNamesTable[ia_opcode] : 0; } void BX_CPU_C::init_FetchDecodeTables(void) { static Bit64u BxOpcodeFeatures[BX_IA_LAST] = { #define bx_define_opcode(a, b, c, d, s1, s2, s3, s4, e) d, #include "ia_opcodes.h" }; #undef bx_define_opcode Bit64u features = BX_CPU_THIS_PTR isa_extensions_bitmask; #if BX_CPU_LEVEL > 3 if (! features) BX_PANIC(("init_FetchDecodeTables: CPU features bitmask is empty !")); #endif if (BX_IA_LAST > 0xfff) BX_PANIC(("init_FetchDecodeTables: too many opcodes defined !")); for (unsigned n=0; n < BX_IA_LAST; n++) { Bit64u ia_opcode_features = BxOpcodeFeatures[n]; if (ia_opcode_features && (ia_opcode_features & features) == 0) { BxOpcodesTable[n].execute1 = &BX_CPU_C::BxError; BxOpcodesTable[n].execute2 = &BX_CPU_C::BxError; // won't allow this new #UD opcode to check prepare_SSE and similar BxOpcodesTable[n].src[3] = 0; } } // handle special case - BSF/BSR vs TZCNT/LZCNT if (! BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_LZCNT)) { BxOpcodesTable[BX_IA_LZCNT_GwEw] = BxOpcodesTable[BX_IA_BSR_GwEw]; BxOpcodesTable[BX_IA_LZCNT_GdEd] = BxOpcodesTable[BX_IA_BSR_GdEd]; #if BX_SUPPORT_X86_64 BxOpcodesTable[BX_IA_LZCNT_GqEq] = BxOpcodesTable[BX_IA_BSR_GqEq]; #endif } if (! BX_CPUID_SUPPORT_ISA_EXTENSION(BX_ISA_BMI1)) { BxOpcodesTable[BX_IA_TZCNT_GwEw] = BxOpcodesTable[BX_IA_BSF_GwEw]; BxOpcodesTable[BX_IA_TZCNT_GdEd] = BxOpcodesTable[BX_IA_BSF_GdEd]; #if BX_SUPPORT_X86_64 BxOpcodesTable[BX_IA_TZCNT_GqEq] = BxOpcodesTable[BX_IA_BSF_GqEq]; #endif } } bochs-2.6/cpu/bmi32.cc0000644000175000017500000001572712020641453014360 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bmi32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ANDN_GdBdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src1()); Bit32u op2_32 = BX_READ_32BIT_REG(i->src2()); op1_32 = ~op1_32 & op2_32; SET_FLAGS_OSZAxC_LOGIC_32(op1_32); // keep PF unchanged BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MULX_GdBdEdR(bxInstruction_c *i) { Bit32u op1_32 = EDX; Bit32u op2_32 = BX_READ_32BIT_REG(i->src2()); Bit64u product_64 = ((Bit64u) op1_32) * ((Bit64u) op2_32); BX_WRITE_32BIT_REGZ(i->src1(), GET32L(product_64)); BX_WRITE_32BIT_REGZ(i->dst(), GET32H(product_64)); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSI_BdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src()); bx_bool tmpCF = (op1_32 != 0); op1_32 = (-op1_32) & op1_32; SET_FLAGS_OSZAxC_LOGIC_32(op1_32); // keep PF unchanged set_CF(tmpCF); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSMSK_BdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src()); bx_bool tmpCF = (op1_32 == 0); op1_32 = (op1_32-1) ^ op1_32; SET_FLAGS_OSZAxC_LOGIC_32(op1_32); // keep PF unchanged set_CF(tmpCF); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BLSR_BdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src()); bx_bool tmpCF = (op1_32 == 0); op1_32 = (op1_32-1) & op1_32; SET_FLAGS_OSZAxC_LOGIC_32(op1_32); // keep PF unchanged set_CF(tmpCF); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RORX_GdEdIbR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src()); unsigned count = i->Ib() & 0x1f; if (count) { op1_32 = (op1_32 >> count) | (op1_32 << (32 - count)); } BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRX_GdEdBdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src1()); unsigned count = BX_READ_32BIT_REG(i->src2()) & 0x1f; if (count) op1_32 >>= count; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SARX_GdEdBdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src1()); unsigned count = BX_READ_32BIT_REG(i->src2()) & 0x1f; if (count) { /* count < 32, since only lower 5 bits used */ op1_32 = ((Bit32s) op1_32) >> count; } BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLX_GdEdBdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src1()); unsigned count = BX_READ_32BIT_REG(i->src2()) & 0x1f; if (count) op1_32 <<= count; BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BEXTR_GdEdBdR(bxInstruction_c *i) { Bit16u control = BX_READ_16BIT_REG(i->src2()); unsigned start = control & 0xff; unsigned len = control >> 8; Bit32u op1_32 = 0; if (start < 32 && len > 0) { op1_32 = BX_READ_32BIT_REG(i->src1()); op1_32 >>= start; if (len < 32) { Bit32u extract_mask = (1 << len) - 1; op1_32 &= extract_mask; } } SET_FLAGS_OSZAPC_LOGIC_32(op1_32); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BZHI_GdEdBdR(bxInstruction_c *i) { unsigned control = BX_READ_16BIT_REG(i->src1()) & 0xff; bx_bool tmpCF = 0; Bit32u op1_32 = BX_READ_32BIT_REG(i->src2()); if (control < 32) { Bit32u mask = (1 << control) - 1; op1_32 &= mask; } else { tmpCF = 1; } SET_FLAGS_OSZAxC_LOGIC_32(op1_32); // keep PF unchanged set_CF(tmpCF); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PEXT_GdEdBdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src1()); Bit32u op2_32 = BX_READ_32BIT_REG(i->src2()), result_32 = 0; Bit32u wr_mask = 0x1; for (; op2_32 != 0; op2_32 >>= 1) { if (op2_32 & 0x1) { if (op1_32 & 0x1) result_32 |= wr_mask; wr_mask <<= 1; } op1_32 >>= 1; } BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PDEP_GdEdBdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src1()); Bit32u op2_32 = BX_READ_32BIT_REG(i->src2()), result_32 = 0; Bit32u wr_mask = 0x1; for (; op2_32 != 0; op2_32 >>= 1) { if (op2_32 & 0x1) { if (op1_32 & 0x1) result_32 |= wr_mask; op1_32 >>= 1; } wr_mask <<= 1; } BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADCX_GdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); Bit32u sum_32 = op1_32 + op2_32 + getB_CF(); BX_WRITE_32BIT_REGZ(i->dst(), sum_32); Bit32u carry_out = ADD_COUT_VEC(op1_32, op2_32, sum_32); set_CF(carry_out >> 31); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ADOX_GdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); Bit32u sum_32 = op1_32 + op2_32 + getB_OF(); BX_WRITE_32BIT_REGZ(i->dst(), sum_32); Bit32u overflow = GET_ADD_OVERFLOW(op1_32, op2_32, sum_32, 0x80000000); set_OF(!!overflow); BX_NEXT_INSTR(i); } bochs-2.6/cpu/resolver.cc0000644000175000017500000000437412020641453015301 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: resolver.cc 10208 2011-02-24 21:54:04Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2009 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR // // 16 bit address size // bx_address BX_CPP_AttrRegparmN(1) BX_CPU_C::BxResolve16BaseIndex(bxInstruction_c *i) { return (Bit16u) (BX_READ_16BIT_REG(i->sibBase()) + BX_READ_16BIT_REG(i->sibIndex()) + i->displ16s()); } // // 32 bit address size // bx_address BX_CPP_AttrRegparmN(1) BX_CPU_C::BxResolve32Base(bxInstruction_c *i) { return (Bit32u) (BX_READ_32BIT_REG(i->sibBase()) + i->displ32s()); } bx_address BX_CPP_AttrRegparmN(1) BX_CPU_C::BxResolve32BaseIndex(bxInstruction_c *i) { return (Bit32u) (BX_READ_32BIT_REG(i->sibBase()) + (BX_READ_32BIT_REG(i->sibIndex()) << i->sibScale()) + i->displ32s()); } // // 64 bit address size // #if BX_SUPPORT_X86_64 bx_address BX_CPP_AttrRegparmN(1) BX_CPU_C::BxResolve64Base(bxInstruction_c *i) { return BX_READ_64BIT_REG(i->sibBase()) + i->displ32s(); } bx_address BX_CPP_AttrRegparmN(1) BX_CPU_C::BxResolve64BaseIndex(bxInstruction_c *i) { return BX_READ_64BIT_REG(i->sibBase()) + (BX_READ_64BIT_REG(i->sibIndex()) << i->sibScale()) + i->displ32s(); } #endif bochs-2.6/cpu/stack64.cc0000644000175000017500000000747112020641453014720 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: stack64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_EqM(bxInstruction_c *i) { RSP_SPECULATIVE; Bit64u val64 = pop_64(); // Note: there is one little weirdism here. It is possible to use // RSP in the modrm addressing. If used, the value of RSP after the // pop is used to calculate the address. bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword_64(i->seg(), eaddr, val64); RSP_COMMIT; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_RRX(bxInstruction_c *i) { push_64(BX_READ_64BIT_REG(i->dst())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP_RRX(bxInstruction_c *i) { BX_WRITE_64BIT_REG(i->dst(), pop_64()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH64_Sw(bxInstruction_c *i) { push_64(BX_CPU_THIS_PTR sregs[i->src()].selector.value); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POP64_Sw(bxInstruction_c *i) { Bit16u selector = stack_read_word(RSP); load_seg_reg(&BX_CPU_THIS_PTR sregs[i->dst()], selector); RSP += 8; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH64_Id(bxInstruction_c *i) { Bit64u imm64 = (Bit32s) i->Id(); push_64(imm64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSH_EqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_virtual_qword_64(i->seg(), eaddr); push_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ENTER64_IwIb(bxInstruction_c *i) { Bit8u level = i->Ib2(); level &= 0x1F; Bit64u temp_RSP = RSP, temp_RBP = RBP; temp_RSP -= 8; stack_write_qword(temp_RSP, temp_RBP); Bit64u frame_ptr64 = temp_RSP; if (level > 0) { /* do level-1 times */ while (--level) { temp_RBP -= 8; Bit64u temp64 = stack_read_qword(temp_RBP); temp_RSP -= 8; stack_write_qword(temp_RSP, temp64); } /* while (--level) */ /* push(frame pointer) */ temp_RSP -= 8; stack_write_qword(temp_RSP, frame_ptr64); } /* if (level > 0) ... */ temp_RSP -= i->Iw(); // ENTER finishes with memory write check on the final stack pointer // the memory is touched but no write actually occurs // emulate it by doing RMW read access from SS:RSP read_RMW_virtual_qword_64(BX_SEG_REG_SS, temp_RSP); RBP = frame_ptr64; RSP = temp_RSP; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LEAVE64(bxInstruction_c *i) { // restore frame pointer Bit64u temp64 = stack_read_qword(RBP); RSP = RBP + 8; RBP = temp64; BX_NEXT_INSTR(i); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/fetchdecode_xop.h0000644000175000017500000016061512020641453016426 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fetchdecode_xop.h 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_XOP_FETCHDECODE_TABLES_H #define BX_XOP_FETCHDECODE_TABLES_H #if BX_SUPPORT_AVX && BX_CPU_LEVEL >= 6 /* ************************************************************************ */ static const BxOpcodeInfo_t BxOpcodeInfoXOP_G1d[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_BLCFILL_BdEd }, /* 2 */ { 0, BX_IA_BLSFILL_BdEd }, /* 3 */ { 0, BX_IA_BLCS_BdEd }, /* 4 */ { 0, BX_IA_TZMSK_BdEd }, /* 5 */ { 0, BX_IA_BLCIC_BdEd }, /* 6 */ { 0, BX_IA_BLSIC_BdEd }, /* 7 */ { 0, BX_IA_T1MSKC_BdEd } }; static const BxOpcodeInfo_t BxOpcodeInfoXOP_G1q[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_BLCFILL_BqEq }, /* 2 */ { 0, BX_IA_BLSFILL_BqEq }, /* 3 */ { 0, BX_IA_BLCS_BqEq }, /* 4 */ { 0, BX_IA_TZMSK_BqEq }, /* 5 */ { 0, BX_IA_BLCIC_BqEq }, /* 6 */ { 0, BX_IA_BLSIC_BqEq }, /* 7 */ { 0, BX_IA_T1MSKC_BqEq } }; static const BxOpcodeInfo_t BxOpcodeInfoXOP_G1[2] = { /* 0 */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoXOP_G1d }, /* 1 */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoXOP_G1q } }; static const BxOpcodeInfo_t BxOpcodeInfoXOP_G2d[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_BLCMSK_BdEd }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_BLCI_BdEd }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoXOP_G2q[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_BLCMSK_BqEq }, /* 2 */ { 0, BX_IA_ERROR }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_BLCI_BqEq }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoXOP_G2[2] = { /* 0 */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoXOP_G2d }, /* 1 */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoXOP_G2q } }; static const BxOpcodeInfo_t BxOpcodeInfoXOP_A10[2] = { /* 0 */ { BxImmediate_Id, BX_IA_BEXTR_GdEdId }, /* 1 */ { BxImmediate_Id, BX_IA_BEXTR_GqEqId } }; /* ************************************************************************ */ static const BxOpcodeInfo_t BxOpcodeTableXOP[256*3*2] = { // 256 entries for XOP-encoded map 0x8 opcodes (VEX.L=0) /* 00 /0 */ { 0, BX_IA_ERROR }, /* 01 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoXOP_G1 }, /* 02 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoXOP_G2 }, /* 03 /0 */ { 0, BX_IA_ERROR }, /* 04 /0 */ { 0, BX_IA_ERROR }, /* 05 /0 */ { 0, BX_IA_ERROR }, /* 06 /0 */ { 0, BX_IA_ERROR }, /* 07 /0 */ { 0, BX_IA_ERROR }, /* 08 /0 */ { 0, BX_IA_ERROR }, /* 09 /0 */ { 0, BX_IA_ERROR }, /* 0A /0 */ { 0, BX_IA_ERROR }, /* 0B /0 */ { 0, BX_IA_ERROR }, /* 0C /0 */ { 0, BX_IA_ERROR }, /* 0D /0 */ { 0, BX_IA_ERROR }, /* 0E /0 */ { 0, BX_IA_ERROR }, /* 0F /0 */ { 0, BX_IA_ERROR }, /* 10 /0 */ { 0, BX_IA_ERROR }, /* 11 /0 */ { 0, BX_IA_ERROR }, /* 12 /0 */ { 0, BX_IA_ERROR }, /* 13 /0 */ { 0, BX_IA_ERROR }, /* 14 /0 */ { 0, BX_IA_ERROR }, /* 15 /0 */ { 0, BX_IA_ERROR }, /* 16 /0 */ { 0, BX_IA_ERROR }, /* 17 /0 */ { 0, BX_IA_ERROR }, /* 18 /0 */ { 0, BX_IA_ERROR }, /* 19 /0 */ { 0, BX_IA_ERROR }, /* 1A /0 */ { 0, BX_IA_ERROR }, /* 1B /0 */ { 0, BX_IA_ERROR }, /* 1C /0 */ { 0, BX_IA_ERROR }, /* 1D /0 */ { 0, BX_IA_ERROR }, /* 1E /0 */ { 0, BX_IA_ERROR }, /* 1F /0 */ { 0, BX_IA_ERROR }, /* 20 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 21 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 22 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 23 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 24 /0 */ { 0, BX_IA_ERROR }, /* 25 /0 */ { 0, BX_IA_ERROR }, /* 26 /0 */ { 0, BX_IA_ERROR }, /* 27 /0 */ { 0, BX_IA_ERROR }, /* 28 /0 */ { 0, BX_IA_ERROR }, /* 29 /0 */ { 0, BX_IA_ERROR }, /* 2A /0 */ { 0, BX_IA_ERROR }, /* 2B /0 */ { 0, BX_IA_ERROR }, /* 2C /0 */ { 0, BX_IA_ERROR }, /* 2D /0 */ { 0, BX_IA_ERROR }, /* 2E /0 */ { 0, BX_IA_ERROR }, /* 2F /0 */ { 0, BX_IA_ERROR }, /* 30 /0 */ { 0, BX_IA_ERROR }, /* 31 /0 */ { 0, BX_IA_ERROR }, /* 32 /0 */ { 0, BX_IA_ERROR }, /* 33 /0 */ { 0, BX_IA_ERROR }, /* 34 /0 */ { 0, BX_IA_ERROR }, /* 35 /0 */ { 0, BX_IA_ERROR }, /* 36 /0 */ { 0, BX_IA_ERROR }, /* 37 /0 */ { 0, BX_IA_ERROR }, /* 38 /0 */ { 0, BX_IA_ERROR }, /* 39 /0 */ { 0, BX_IA_ERROR }, /* 3A /0 */ { 0, BX_IA_ERROR }, /* 3B /0 */ { 0, BX_IA_ERROR }, /* 3C /0 */ { 0, BX_IA_ERROR }, /* 3D /0 */ { 0, BX_IA_ERROR }, /* 3E /0 */ { 0, BX_IA_ERROR }, /* 3F /0 */ { 0, BX_IA_ERROR }, /* 40 /0 */ { 0, BX_IA_ERROR }, /* 41 /0 */ { 0, BX_IA_ERROR }, /* 42 /0 */ { 0, BX_IA_ERROR }, /* 43 /0 */ { 0, BX_IA_ERROR }, /* 44 /0 */ { 0, BX_IA_ERROR }, /* 45 /0 */ { 0, BX_IA_ERROR }, /* 46 /0 */ { 0, BX_IA_ERROR }, /* 47 /0 */ { 0, BX_IA_ERROR }, /* 48 /0 */ { 0, BX_IA_ERROR }, /* 49 /0 */ { 0, BX_IA_ERROR }, /* 4A /0 */ { 0, BX_IA_ERROR }, /* 4B /0 */ { 0, BX_IA_ERROR }, /* 4C /0 */ { 0, BX_IA_ERROR }, /* 4D /0 */ { 0, BX_IA_ERROR }, /* 4E /0 */ { 0, BX_IA_ERROR }, /* 4F /0 */ { 0, BX_IA_ERROR }, /* 50 /0 */ { 0, BX_IA_ERROR }, /* 51 /0 */ { 0, BX_IA_ERROR }, /* 52 /0 */ { 0, BX_IA_ERROR }, /* 53 /0 */ { 0, BX_IA_ERROR }, /* 54 /0 */ { 0, BX_IA_ERROR }, /* 55 /0 */ { 0, BX_IA_ERROR }, /* 56 /0 */ { 0, BX_IA_ERROR }, /* 57 /0 */ { 0, BX_IA_ERROR }, /* 58 /0 */ { 0, BX_IA_ERROR }, /* 59 /0 */ { 0, BX_IA_ERROR }, /* 5A /0 */ { 0, BX_IA_ERROR }, /* 5B /0 */ { 0, BX_IA_ERROR }, /* 5C /0 */ { 0, BX_IA_ERROR }, /* 5D /0 */ { 0, BX_IA_ERROR }, /* 5E /0 */ { 0, BX_IA_ERROR }, /* 5F /0 */ { 0, BX_IA_ERROR }, /* 60 /0 */ { 0, BX_IA_ERROR }, /* 61 /0 */ { 0, BX_IA_ERROR }, /* 62 /0 */ { 0, BX_IA_ERROR }, /* 63 /0 */ { 0, BX_IA_ERROR }, /* 64 /0 */ { 0, BX_IA_ERROR }, /* 65 /0 */ { 0, BX_IA_ERROR }, /* 66 /0 */ { 0, BX_IA_ERROR }, /* 67 /0 */ { 0, BX_IA_ERROR }, /* 68 /0 */ { 0, BX_IA_ERROR }, /* 69 /0 */ { 0, BX_IA_ERROR }, /* 6A /0 */ { 0, BX_IA_ERROR }, /* 6B /0 */ { 0, BX_IA_ERROR }, /* 6C /0 */ { 0, BX_IA_ERROR }, /* 6D /0 */ { 0, BX_IA_ERROR }, /* 6E /0 */ { 0, BX_IA_ERROR }, /* 6F /0 */ { 0, BX_IA_ERROR }, /* 70 /0 */ { 0, BX_IA_ERROR }, /* 71 /0 */ { 0, BX_IA_ERROR }, /* 72 /0 */ { 0, BX_IA_ERROR }, /* 73 /0 */ { 0, BX_IA_ERROR }, /* 74 /0 */ { 0, BX_IA_ERROR }, /* 75 /0 */ { 0, BX_IA_ERROR }, /* 76 /0 */ { 0, BX_IA_ERROR }, /* 77 /0 */ { 0, BX_IA_ERROR }, /* 78 /0 */ { 0, BX_IA_ERROR }, /* 79 /0 */ { 0, BX_IA_ERROR }, /* 7A /0 */ { 0, BX_IA_ERROR }, /* 7B /0 */ { 0, BX_IA_ERROR }, /* 7C /0 */ { 0, BX_IA_ERROR }, /* 7D /0 */ { 0, BX_IA_ERROR }, /* 7E /0 */ { 0, BX_IA_ERROR }, /* 7F /0 */ { 0, BX_IA_ERROR }, /* 80 /0 */ { 0, BX_IA_ERROR }, /* 81 /0 */ { 0, BX_IA_ERROR }, /* 82 /0 */ { 0, BX_IA_ERROR }, /* 83 /0 */ { 0, BX_IA_ERROR }, /* 84 /0 */ { 0, BX_IA_ERROR }, /* 85 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSSWW_VdqHdqWdqVIb }, /* 86 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSSWD_VdqHdqWdqVIb }, /* 87 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSSDQL_VdqHdqWdqVIb }, /* 88 /0 */ { 0, BX_IA_ERROR }, /* 89 /0 */ { 0, BX_IA_ERROR }, /* 8A /0 */ { 0, BX_IA_ERROR }, /* 8B /0 */ { 0, BX_IA_ERROR }, /* 8C /0 */ { 0, BX_IA_ERROR }, /* 8D /0 */ { 0, BX_IA_ERROR }, /* 8E /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSSDD_VdqHdqWdqVIb }, /* 8F /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSSDQH_VdqHdqWdqVIb }, /* 90 /0 */ { 0, BX_IA_ERROR }, /* 91 /0 */ { 0, BX_IA_ERROR }, /* 92 /0 */ { 0, BX_IA_ERROR }, /* 93 /0 */ { 0, BX_IA_ERROR }, /* 94 /0 */ { 0, BX_IA_ERROR }, /* 95 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSWW_VdqHdqWdqVIb }, /* 96 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSWD_VdqHdqWdqVIb }, /* 97 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSDQL_VdqHdqWdqVIb }, /* 98 /0 */ { 0, BX_IA_ERROR }, /* 99 /0 */ { 0, BX_IA_ERROR }, /* 9A /0 */ { 0, BX_IA_ERROR }, /* 9B /0 */ { 0, BX_IA_ERROR }, /* 9C /0 */ { 0, BX_IA_ERROR }, /* 9D /0 */ { 0, BX_IA_ERROR }, /* 9E /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSDD_VdqHdqWdqVIb }, /* 9F /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMACSDQH_VdqHdqWdqVIb }, /* A0 /0 */ { 0, BX_IA_ERROR }, /* A1 /0 */ { 0, BX_IA_ERROR }, /* A2 /0 */ { BxImmediate_Ib4, BX_IA_VPCMOV_VdqHdqWdqVIb }, /* A3 /0 */ { BxImmediate_Ib4, BX_IA_VPPERM_VdqHdqWdqVIb }, /* A4 /0 */ { 0, BX_IA_ERROR }, /* A5 /0 */ { 0, BX_IA_ERROR }, /* A6 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMADCSSWD_VdqHdqWdqVIb }, /* A7 /0 */ { 0, BX_IA_ERROR }, /* A8 /0 */ { 0, BX_IA_ERROR }, /* A9 /0 */ { 0, BX_IA_ERROR }, /* AA /0 */ { 0, BX_IA_ERROR }, /* AB /0 */ { 0, BX_IA_ERROR }, /* AC /0 */ { 0, BX_IA_ERROR }, /* AD /0 */ { 0, BX_IA_ERROR }, /* AE /0 */ { 0, BX_IA_ERROR }, /* AF /0 */ { 0, BX_IA_ERROR }, /* B0 /0 */ { 0, BX_IA_ERROR }, /* B1 /0 */ { 0, BX_IA_ERROR }, /* B2 /0 */ { 0, BX_IA_ERROR }, /* B3 /0 */ { 0, BX_IA_ERROR }, /* B4 /0 */ { 0, BX_IA_ERROR }, /* B5 /0 */ { 0, BX_IA_ERROR }, /* B6 /0 */ { BxVexW0 | BxImmediate_Ib4, BX_IA_VPMADCSWD_VdqHdqWdqVIb }, /* B7 /0 */ { 0, BX_IA_ERROR }, /* B8 /0 */ { 0, BX_IA_ERROR }, /* B9 /0 */ { 0, BX_IA_ERROR }, /* BA /0 */ { 0, BX_IA_ERROR }, /* BB /0 */ { 0, BX_IA_ERROR }, /* BC /0 */ { 0, BX_IA_ERROR }, /* BD /0 */ { 0, BX_IA_ERROR }, /* BE /0 */ { 0, BX_IA_ERROR }, /* BF /0 */ { 0, BX_IA_ERROR }, /* C0 /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPROTB_VdqWdqIb }, /* C1 /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPROTW_VdqWdqIb }, /* C2 /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPROTD_VdqWdqIb }, /* C3 /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPROTQ_VdqWdqIb }, /* C4 /0 */ { 0, BX_IA_ERROR }, /* C5 /0 */ { 0, BX_IA_ERROR }, /* C6 /0 */ { 0, BX_IA_ERROR }, /* C7 /0 */ { 0, BX_IA_ERROR }, /* C8 /0 */ { 0, BX_IA_ERROR }, /* C9 /0 */ { 0, BX_IA_ERROR }, /* CA /0 */ { 0, BX_IA_ERROR }, /* CB /0 */ { 0, BX_IA_ERROR }, /* CC /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMB_VdqHdqWdqIb }, /* CD /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMW_VdqHdqWdqIb }, /* CE /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMD_VdqHdqWdqIb }, /* CF /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMQ_VdqHdqWdqIb }, /* D0 /0 */ { 0, BX_IA_ERROR }, /* D1 /0 */ { 0, BX_IA_ERROR }, /* D2 /0 */ { 0, BX_IA_ERROR }, /* D3 /0 */ { 0, BX_IA_ERROR }, /* D4 /0 */ { 0, BX_IA_ERROR }, /* D5 /0 */ { 0, BX_IA_ERROR }, /* D6 /0 */ { 0, BX_IA_ERROR }, /* D7 /0 */ { 0, BX_IA_ERROR }, /* D8 /0 */ { 0, BX_IA_ERROR }, /* D9 /0 */ { 0, BX_IA_ERROR }, /* DA /0 */ { 0, BX_IA_ERROR }, /* DB /0 */ { 0, BX_IA_ERROR }, /* DC /0 */ { 0, BX_IA_ERROR }, /* DD /0 */ { 0, BX_IA_ERROR }, /* DE /0 */ { 0, BX_IA_ERROR }, /* DF /0 */ { 0, BX_IA_ERROR }, /* E0 /0 */ { 0, BX_IA_ERROR }, /* E1 /0 */ { 0, BX_IA_ERROR }, /* E2 /0 */ { 0, BX_IA_ERROR }, /* E3 /0 */ { 0, BX_IA_ERROR }, /* E4 /0 */ { 0, BX_IA_ERROR }, /* E5 /0 */ { 0, BX_IA_ERROR }, /* E6 /0 */ { 0, BX_IA_ERROR }, /* E7 /0 */ { 0, BX_IA_ERROR }, /* E8 /0 */ { 0, BX_IA_ERROR }, /* E9 /0 */ { 0, BX_IA_ERROR }, /* EA /0 */ { 0, BX_IA_ERROR }, /* EB /0 */ { 0, BX_IA_ERROR }, /* EC /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMUB_VdqHdqWdqIb }, /* ED /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMUW_VdqHdqWdqIb }, /* EE /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMUD_VdqHdqWdqIb }, /* EF /0 */ { BxVexW0 | BxImmediate_Ib, BX_IA_VPCOMUQ_VdqHdqWdqIb }, /* F0 /0 */ { 0, BX_IA_ERROR }, /* F1 /0 */ { 0, BX_IA_ERROR }, /* F2 /0 */ { 0, BX_IA_ERROR }, /* F3 /0 */ { 0, BX_IA_ERROR }, /* F4 /0 */ { 0, BX_IA_ERROR }, /* F5 /0 */ { 0, BX_IA_ERROR }, /* F6 /0 */ { 0, BX_IA_ERROR }, /* F7 /0 */ { 0, BX_IA_ERROR }, /* F8 /0 */ { 0, BX_IA_ERROR }, /* F9 /0 */ { 0, BX_IA_ERROR }, /* FA /0 */ { 0, BX_IA_ERROR }, /* FB /0 */ { 0, BX_IA_ERROR }, /* FC /0 */ { 0, BX_IA_ERROR }, /* FD /0 */ { 0, BX_IA_ERROR }, /* FE /0 */ { 0, BX_IA_ERROR }, /* FF /0 */ { 0, BX_IA_ERROR }, // 256 entries for XOP-encoded map 0x9 opcodes (VEX.L=0) /* 00 /0 */ { 0, BX_IA_ERROR }, /* 01 /0 */ { 0, BX_IA_ERROR }, /* 02 /0 */ { 0, BX_IA_ERROR }, /* 03 /0 */ { 0, BX_IA_ERROR }, /* 04 /0 */ { 0, BX_IA_ERROR }, /* 05 /0 */ { 0, BX_IA_ERROR }, /* 06 /0 */ { 0, BX_IA_ERROR }, /* 07 /0 */ { 0, BX_IA_ERROR }, /* 08 /0 */ { 0, BX_IA_ERROR }, /* 09 /0 */ { 0, BX_IA_ERROR }, /* 0A /0 */ { 0, BX_IA_ERROR }, /* 0B /0 */ { 0, BX_IA_ERROR }, /* 0C /0 */ { 0, BX_IA_ERROR }, /* 0D /0 */ { 0, BX_IA_ERROR }, /* 0E /0 */ { 0, BX_IA_ERROR }, /* 0F /0 */ { 0, BX_IA_ERROR }, /* 10 /0 */ { 0, BX_IA_ERROR }, /* 11 /0 */ { 0, BX_IA_ERROR }, /* 12 /0 */ { 0, BX_IA_ERROR }, /* 13 /0 */ { 0, BX_IA_ERROR }, /* 14 /0 */ { 0, BX_IA_ERROR }, /* 15 /0 */ { 0, BX_IA_ERROR }, /* 16 /0 */ { 0, BX_IA_ERROR }, /* 17 /0 */ { 0, BX_IA_ERROR }, /* 18 /0 */ { 0, BX_IA_ERROR }, /* 19 /0 */ { 0, BX_IA_ERROR }, /* 1A /0 */ { 0, BX_IA_ERROR }, /* 1B /0 */ { 0, BX_IA_ERROR }, /* 1C /0 */ { 0, BX_IA_ERROR }, /* 1D /0 */ { 0, BX_IA_ERROR }, /* 1E /0 */ { 0, BX_IA_ERROR }, /* 1F /0 */ { 0, BX_IA_ERROR }, /* 20 /0 */ { 0, BX_IA_ERROR }, /* 21 /0 */ { 0, BX_IA_ERROR }, /* 22 /0 */ { 0, BX_IA_ERROR }, /* 23 /0 */ { 0, BX_IA_ERROR }, /* 24 /0 */ { 0, BX_IA_ERROR }, /* 25 /0 */ { 0, BX_IA_ERROR }, /* 26 /0 */ { 0, BX_IA_ERROR }, /* 27 /0 */ { 0, BX_IA_ERROR }, /* 28 /0 */ { 0, BX_IA_ERROR }, /* 29 /0 */ { 0, BX_IA_ERROR }, /* 2A /0 */ { 0, BX_IA_ERROR }, /* 2B /0 */ { 0, BX_IA_ERROR }, /* 2C /0 */ { 0, BX_IA_ERROR }, /* 2D /0 */ { 0, BX_IA_ERROR }, /* 2E /0 */ { 0, BX_IA_ERROR }, /* 2F /0 */ { 0, BX_IA_ERROR }, /* 30 /0 */ { 0, BX_IA_ERROR }, /* 31 /0 */ { 0, BX_IA_ERROR }, /* 32 /0 */ { 0, BX_IA_ERROR }, /* 33 /0 */ { 0, BX_IA_ERROR }, /* 34 /0 */ { 0, BX_IA_ERROR }, /* 35 /0 */ { 0, BX_IA_ERROR }, /* 36 /0 */ { 0, BX_IA_ERROR }, /* 37 /0 */ { 0, BX_IA_ERROR }, /* 38 /0 */ { 0, BX_IA_ERROR }, /* 39 /0 */ { 0, BX_IA_ERROR }, /* 3A /0 */ { 0, BX_IA_ERROR }, /* 3B /0 */ { 0, BX_IA_ERROR }, /* 3C /0 */ { 0, BX_IA_ERROR }, /* 3D /0 */ { 0, BX_IA_ERROR }, /* 3E /0 */ { 0, BX_IA_ERROR }, /* 3F /0 */ { 0, BX_IA_ERROR }, /* 40 /0 */ { 0, BX_IA_ERROR }, /* 41 /0 */ { 0, BX_IA_ERROR }, /* 42 /0 */ { 0, BX_IA_ERROR }, /* 43 /0 */ { 0, BX_IA_ERROR }, /* 44 /0 */ { 0, BX_IA_ERROR }, /* 45 /0 */ { 0, BX_IA_ERROR }, /* 46 /0 */ { 0, BX_IA_ERROR }, /* 47 /0 */ { 0, BX_IA_ERROR }, /* 48 /0 */ { 0, BX_IA_ERROR }, /* 49 /0 */ { 0, BX_IA_ERROR }, /* 4A /0 */ { 0, BX_IA_ERROR }, /* 4B /0 */ { 0, BX_IA_ERROR }, /* 4C /0 */ { 0, BX_IA_ERROR }, /* 4D /0 */ { 0, BX_IA_ERROR }, /* 4E /0 */ { 0, BX_IA_ERROR }, /* 4F /0 */ { 0, BX_IA_ERROR }, /* 50 /0 */ { 0, BX_IA_ERROR }, /* 51 /0 */ { 0, BX_IA_ERROR }, /* 52 /0 */ { 0, BX_IA_ERROR }, /* 53 /0 */ { 0, BX_IA_ERROR }, /* 54 /0 */ { 0, BX_IA_ERROR }, /* 55 /0 */ { 0, BX_IA_ERROR }, /* 56 /0 */ { 0, BX_IA_ERROR }, /* 57 /0 */ { 0, BX_IA_ERROR }, /* 58 /0 */ { 0, BX_IA_ERROR }, /* 59 /0 */ { 0, BX_IA_ERROR }, /* 5A /0 */ { 0, BX_IA_ERROR }, /* 5B /0 */ { 0, BX_IA_ERROR }, /* 5C /0 */ { 0, BX_IA_ERROR }, /* 5D /0 */ { 0, BX_IA_ERROR }, /* 5E /0 */ { 0, BX_IA_ERROR }, /* 5F /0 */ { 0, BX_IA_ERROR }, /* 60 /0 */ { 0, BX_IA_ERROR }, /* 61 /0 */ { 0, BX_IA_ERROR }, /* 62 /0 */ { 0, BX_IA_ERROR }, /* 63 /0 */ { 0, BX_IA_ERROR }, /* 64 /0 */ { 0, BX_IA_ERROR }, /* 65 /0 */ { 0, BX_IA_ERROR }, /* 66 /0 */ { 0, BX_IA_ERROR }, /* 67 /0 */ { 0, BX_IA_ERROR }, /* 68 /0 */ { 0, BX_IA_ERROR }, /* 69 /0 */ { 0, BX_IA_ERROR }, /* 6A /0 */ { 0, BX_IA_ERROR }, /* 6B /0 */ { 0, BX_IA_ERROR }, /* 6C /0 */ { 0, BX_IA_ERROR }, /* 6D /0 */ { 0, BX_IA_ERROR }, /* 6E /0 */ { 0, BX_IA_ERROR }, /* 6F /0 */ { 0, BX_IA_ERROR }, /* 70 /0 */ { 0, BX_IA_ERROR }, /* 71 /0 */ { 0, BX_IA_ERROR }, /* 72 /0 */ { 0, BX_IA_ERROR }, /* 73 /0 */ { 0, BX_IA_ERROR }, /* 74 /0 */ { 0, BX_IA_ERROR }, /* 75 /0 */ { 0, BX_IA_ERROR }, /* 76 /0 */ { 0, BX_IA_ERROR }, /* 77 /0 */ { 0, BX_IA_ERROR }, /* 78 /0 */ { 0, BX_IA_ERROR }, /* 79 /0 */ { 0, BX_IA_ERROR }, /* 7A /0 */ { 0, BX_IA_ERROR }, /* 7B /0 */ { 0, BX_IA_ERROR }, /* 7C /0 */ { 0, BX_IA_ERROR }, /* 7D /0 */ { 0, BX_IA_ERROR }, /* 7E /0 */ { 0, BX_IA_ERROR }, /* 7F /0 */ { 0, BX_IA_ERROR }, /* 80 /0 */ { BxVexW0, BX_IA_VFRCZPS_VpsWps }, /* 81 /0 */ { BxVexW0, BX_IA_VFRCZPD_VpdWpd }, /* 82 /0 */ { BxVexW0, BX_IA_VFRCZSS_VssWss }, /* 83 /0 */ { BxVexW0, BX_IA_VFRCZSD_VsdWsd }, /* 84 /0 */ { 0, BX_IA_ERROR }, /* 85 /0 */ { 0, BX_IA_ERROR }, /* 86 /0 */ { 0, BX_IA_ERROR }, /* 87 /0 */ { 0, BX_IA_ERROR }, /* 88 /0 */ { 0, BX_IA_VPSHAB_VdqWdqHdq }, /* 89 /0 */ { 0, BX_IA_VPSHAW_VdqWdqHdq }, /* 8A /0 */ { 0, BX_IA_VPSHAD_VdqWdqHdq }, /* 8B /0 */ { 0, BX_IA_VPSHAQ_VdqWdqHdq }, /* 8C /0 */ { 0, BX_IA_ERROR }, /* 8D /0 */ { 0, BX_IA_ERROR }, /* 8E /0 */ { 0, BX_IA_ERROR }, /* 8F /0 */ { 0, BX_IA_ERROR }, /* 90 /0 */ { 0, BX_IA_VPROTB_VdqWdqHdq }, /* 91 /0 */ { 0, BX_IA_VPROTW_VdqWdqHdq }, /* 92 /0 */ { 0, BX_IA_VPROTD_VdqWdqHdq }, /* 93 /0 */ { 0, BX_IA_VPROTQ_VdqWdqHdq }, /* 94 /0 */ { 0, BX_IA_VPSHLB_VdqWdqHdq }, /* 95 /0 */ { 0, BX_IA_VPSHLW_VdqWdqHdq }, /* 96 /0 */ { 0, BX_IA_VPSHLD_VdqWdqHdq }, /* 97 /0 */ { 0, BX_IA_VPSHLQ_VdqWdqHdq }, /* 98 /0 */ { 0, BX_IA_ERROR }, /* 99 /0 */ { 0, BX_IA_ERROR }, /* 9A /0 */ { 0, BX_IA_ERROR }, /* 9B /0 */ { 0, BX_IA_ERROR }, /* 9C /0 */ { 0, BX_IA_ERROR }, /* 9D /0 */ { 0, BX_IA_ERROR }, /* 9E /0 */ { 0, BX_IA_ERROR }, /* 9F /0 */ { 0, BX_IA_ERROR }, /* A0 /0 */ { 0, BX_IA_ERROR }, /* A1 /0 */ { 0, BX_IA_ERROR }, /* A2 /0 */ { 0, BX_IA_ERROR }, /* A3 /0 */ { 0, BX_IA_ERROR }, /* A4 /0 */ { 0, BX_IA_ERROR }, /* A5 /0 */ { 0, BX_IA_ERROR }, /* A6 /0 */ { 0, BX_IA_ERROR }, /* A7 /0 */ { 0, BX_IA_ERROR }, /* A8 /0 */ { 0, BX_IA_ERROR }, /* A9 /0 */ { 0, BX_IA_ERROR }, /* AA /0 */ { 0, BX_IA_ERROR }, /* AB /0 */ { 0, BX_IA_ERROR }, /* AC /0 */ { 0, BX_IA_ERROR }, /* AD /0 */ { 0, BX_IA_ERROR }, /* AE /0 */ { 0, BX_IA_ERROR }, /* AF /0 */ { 0, BX_IA_ERROR }, /* B0 /0 */ { 0, BX_IA_ERROR }, /* B1 /0 */ { 0, BX_IA_ERROR }, /* B2 /0 */ { 0, BX_IA_ERROR }, /* B3 /0 */ { 0, BX_IA_ERROR }, /* B4 /0 */ { 0, BX_IA_ERROR }, /* B5 /0 */ { 0, BX_IA_ERROR }, /* B6 /0 */ { 0, BX_IA_ERROR }, /* B7 /0 */ { 0, BX_IA_ERROR }, /* B8 /0 */ { 0, BX_IA_ERROR }, /* B9 /0 */ { 0, BX_IA_ERROR }, /* BA /0 */ { 0, BX_IA_ERROR }, /* BB /0 */ { 0, BX_IA_ERROR }, /* BC /0 */ { 0, BX_IA_ERROR }, /* BD /0 */ { 0, BX_IA_ERROR }, /* BE /0 */ { 0, BX_IA_ERROR }, /* BF /0 */ { 0, BX_IA_ERROR }, /* C0 /0 */ { 0, BX_IA_ERROR }, /* C1 /0 */ { BxVexW0, BX_IA_VPHADDBW_VdqWdq }, /* C2 /0 */ { BxVexW0, BX_IA_VPHADDBD_VdqWdq }, /* C3 /0 */ { BxVexW0, BX_IA_VPHADDBQ_VdqWdq }, /* C4 /0 */ { 0, BX_IA_ERROR }, /* C5 /0 */ { 0, BX_IA_ERROR }, /* C6 /0 */ { BxVexW0, BX_IA_VPHADDWD_VdqWdq }, /* C7 /0 */ { BxVexW0, BX_IA_VPHADDWQ_VdqWdq }, /* C8 /0 */ { 0, BX_IA_ERROR }, /* C9 /0 */ { 0, BX_IA_ERROR }, /* CA /0 */ { 0, BX_IA_ERROR }, /* CB /0 */ { BxVexW0, BX_IA_VPHADDDQ_VdqWdq }, /* CC /0 */ { 0, BX_IA_ERROR }, /* CD /0 */ { 0, BX_IA_ERROR }, /* CE /0 */ { 0, BX_IA_ERROR }, /* CF /0 */ { 0, BX_IA_ERROR }, /* D0 /0 */ { 0, BX_IA_ERROR }, /* D1 /0 */ { BxVexW0, BX_IA_VPHADDUBW_VdqWdq }, /* D2 /0 */ { BxVexW0, BX_IA_VPHADDUBD_VdqWdq }, /* D3 /0 */ { BxVexW0, BX_IA_VPHADDUBQ_VdqWdq }, /* D4 /0 */ { 0, BX_IA_ERROR }, /* D5 /0 */ { 0, BX_IA_ERROR }, /* D6 /0 */ { BxVexW0, BX_IA_VPHADDUWD_VdqWdq }, /* D7 /0 */ { BxVexW0, BX_IA_VPHADDUWQ_VdqWdq }, /* D8 /0 */ { 0, BX_IA_ERROR }, /* D9 /0 */ { 0, BX_IA_ERROR }, /* DA /0 */ { 0, BX_IA_ERROR }, /* DB /0 */ { BxVexW0, BX_IA_VPHADDUDQ_VdqWdq }, /* DC /0 */ { 0, BX_IA_ERROR }, /* DD /0 */ { 0, BX_IA_ERROR }, /* DE /0 */ { 0, BX_IA_ERROR }, /* DF /0 */ { 0, BX_IA_ERROR }, /* E0 /0 */ { 0, BX_IA_ERROR }, /* E1 /0 */ { BxVexW0, BX_IA_VPHSUBBW_VdqWdq }, /* E2 /0 */ { BxVexW0, BX_IA_VPHSUBWD_VdqWdq }, /* E3 /0 */ { BxVexW0, BX_IA_VPHSUBDQ_VdqWdq }, /* E4 /0 */ { 0, BX_IA_ERROR }, /* E5 /0 */ { 0, BX_IA_ERROR }, /* E6 /0 */ { 0, BX_IA_ERROR }, /* E7 /0 */ { 0, BX_IA_ERROR }, /* E8 /0 */ { 0, BX_IA_ERROR }, /* E9 /0 */ { 0, BX_IA_ERROR }, /* EA /0 */ { 0, BX_IA_ERROR }, /* EB /0 */ { 0, BX_IA_ERROR }, /* EC /0 */ { 0, BX_IA_ERROR }, /* ED /0 */ { 0, BX_IA_ERROR }, /* EE /0 */ { 0, BX_IA_ERROR }, /* EF /0 */ { 0, BX_IA_ERROR }, /* F0 /0 */ { 0, BX_IA_ERROR }, /* F1 /0 */ { 0, BX_IA_ERROR }, /* F2 /0 */ { 0, BX_IA_ERROR }, /* F3 /0 */ { 0, BX_IA_ERROR }, /* F4 /0 */ { 0, BX_IA_ERROR }, /* F5 /0 */ { 0, BX_IA_ERROR }, /* F6 /0 */ { 0, BX_IA_ERROR }, /* F7 /0 */ { 0, BX_IA_ERROR }, /* F8 /0 */ { 0, BX_IA_ERROR }, /* F9 /0 */ { 0, BX_IA_ERROR }, /* FA /0 */ { 0, BX_IA_ERROR }, /* FB /0 */ { 0, BX_IA_ERROR }, /* FC /0 */ { 0, BX_IA_ERROR }, /* FD /0 */ { 0, BX_IA_ERROR }, /* FE /0 */ { 0, BX_IA_ERROR }, /* FF /0 */ { 0, BX_IA_ERROR }, // 256 entries for XOP-encoded map 0xA opcodes (VEX.L=0) /* 00 /0 */ { 0, BX_IA_ERROR }, /* 01 /0 */ { 0, BX_IA_ERROR }, /* 02 /0 */ { 0, BX_IA_ERROR }, /* 03 /0 */ { 0, BX_IA_ERROR }, /* 04 /0 */ { 0, BX_IA_ERROR }, /* 05 /0 */ { 0, BX_IA_ERROR }, /* 06 /0 */ { 0, BX_IA_ERROR }, /* 07 /0 */ { 0, BX_IA_ERROR }, /* 08 /0 */ { 0, BX_IA_ERROR }, /* 09 /0 */ { 0, BX_IA_ERROR }, /* 0A /0 */ { 0, BX_IA_ERROR }, /* 0B /0 */ { 0, BX_IA_ERROR }, /* 0C /0 */ { 0, BX_IA_ERROR }, /* 0D /0 */ { 0, BX_IA_ERROR }, /* 0E /0 */ { 0, BX_IA_ERROR }, /* 0F /0 */ { 0, BX_IA_ERROR }, /* 10 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoXOP_A10 }, /* 11 /0 */ { 0, BX_IA_ERROR }, /* 12 /0 */ { 0, BX_IA_ERROR }, /* 13 /0 */ { 0, BX_IA_ERROR }, /* 14 /0 */ { 0, BX_IA_ERROR }, /* 15 /0 */ { 0, BX_IA_ERROR }, /* 16 /0 */ { 0, BX_IA_ERROR }, /* 17 /0 */ { 0, BX_IA_ERROR }, /* 18 /0 */ { 0, BX_IA_ERROR }, /* 19 /0 */ { 0, BX_IA_ERROR }, /* 1A /0 */ { 0, BX_IA_ERROR }, /* 1B /0 */ { 0, BX_IA_ERROR }, /* 1C /0 */ { 0, BX_IA_ERROR }, /* 1D /0 */ { 0, BX_IA_ERROR }, /* 1E /0 */ { 0, BX_IA_ERROR }, /* 1F /0 */ { 0, BX_IA_ERROR }, /* 20 /0 */ { 0, BX_IA_ERROR }, /* 21 /0 */ { 0, BX_IA_ERROR }, /* 22 /0 */ { 0, BX_IA_ERROR }, /* 23 /0 */ { 0, BX_IA_ERROR }, /* 24 /0 */ { 0, BX_IA_ERROR }, /* 25 /0 */ { 0, BX_IA_ERROR }, /* 26 /0 */ { 0, BX_IA_ERROR }, /* 27 /0 */ { 0, BX_IA_ERROR }, /* 28 /0 */ { 0, BX_IA_ERROR }, /* 29 /0 */ { 0, BX_IA_ERROR }, /* 2A /0 */ { 0, BX_IA_ERROR }, /* 2B /0 */ { 0, BX_IA_ERROR }, /* 2C /0 */ { 0, BX_IA_ERROR }, /* 2D /0 */ { 0, BX_IA_ERROR }, /* 2E /0 */ { 0, BX_IA_ERROR }, /* 2F /0 */ { 0, BX_IA_ERROR }, /* 30 /0 */ { 0, BX_IA_ERROR }, /* 31 /0 */ { 0, BX_IA_ERROR }, /* 32 /0 */ { 0, BX_IA_ERROR }, /* 33 /0 */ { 0, BX_IA_ERROR }, /* 34 /0 */ { 0, BX_IA_ERROR }, /* 35 /0 */ { 0, BX_IA_ERROR }, /* 36 /0 */ { 0, BX_IA_ERROR }, /* 37 /0 */ { 0, BX_IA_ERROR }, /* 38 /0 */ { 0, BX_IA_ERROR }, /* 39 /0 */ { 0, BX_IA_ERROR }, /* 3A /0 */ { 0, BX_IA_ERROR }, /* 3B /0 */ { 0, BX_IA_ERROR }, /* 3C /0 */ { 0, BX_IA_ERROR }, /* 3D /0 */ { 0, BX_IA_ERROR }, /* 3E /0 */ { 0, BX_IA_ERROR }, /* 3F /0 */ { 0, BX_IA_ERROR }, /* 40 /0 */ { 0, BX_IA_ERROR }, /* 41 /0 */ { 0, BX_IA_ERROR }, /* 42 /0 */ { 0, BX_IA_ERROR }, /* 43 /0 */ { 0, BX_IA_ERROR }, /* 44 /0 */ { 0, BX_IA_ERROR }, /* 45 /0 */ { 0, BX_IA_ERROR }, /* 46 /0 */ { 0, BX_IA_ERROR }, /* 47 /0 */ { 0, BX_IA_ERROR }, /* 48 /0 */ { 0, BX_IA_ERROR }, /* 49 /0 */ { 0, BX_IA_ERROR }, /* 4A /0 */ { 0, BX_IA_ERROR }, /* 4B /0 */ { 0, BX_IA_ERROR }, /* 4C /0 */ { 0, BX_IA_ERROR }, /* 4D /0 */ { 0, BX_IA_ERROR }, /* 4E /0 */ { 0, BX_IA_ERROR }, /* 4F /0 */ { 0, BX_IA_ERROR }, /* 50 /0 */ { 0, BX_IA_ERROR }, /* 51 /0 */ { 0, BX_IA_ERROR }, /* 52 /0 */ { 0, BX_IA_ERROR }, /* 53 /0 */ { 0, BX_IA_ERROR }, /* 54 /0 */ { 0, BX_IA_ERROR }, /* 55 /0 */ { 0, BX_IA_ERROR }, /* 56 /0 */ { 0, BX_IA_ERROR }, /* 57 /0 */ { 0, BX_IA_ERROR }, /* 58 /0 */ { 0, BX_IA_ERROR }, /* 59 /0 */ { 0, BX_IA_ERROR }, /* 5A /0 */ { 0, BX_IA_ERROR }, /* 5B /0 */ { 0, BX_IA_ERROR }, /* 5C /0 */ { 0, BX_IA_ERROR }, /* 5D /0 */ { 0, BX_IA_ERROR }, /* 5E /0 */ { 0, BX_IA_ERROR }, /* 5F /0 */ { 0, BX_IA_ERROR }, /* 60 /0 */ { 0, BX_IA_ERROR }, /* 61 /0 */ { 0, BX_IA_ERROR }, /* 62 /0 */ { 0, BX_IA_ERROR }, /* 63 /0 */ { 0, BX_IA_ERROR }, /* 64 /0 */ { 0, BX_IA_ERROR }, /* 65 /0 */ { 0, BX_IA_ERROR }, /* 66 /0 */ { 0, BX_IA_ERROR }, /* 67 /0 */ { 0, BX_IA_ERROR }, /* 68 /0 */ { 0, BX_IA_ERROR }, /* 69 /0 */ { 0, BX_IA_ERROR }, /* 6A /0 */ { 0, BX_IA_ERROR }, /* 6B /0 */ { 0, BX_IA_ERROR }, /* 6C /0 */ { 0, BX_IA_ERROR }, /* 6D /0 */ { 0, BX_IA_ERROR }, /* 6E /0 */ { 0, BX_IA_ERROR }, /* 6F /0 */ { 0, BX_IA_ERROR }, /* 70 /0 */ { 0, BX_IA_ERROR }, /* 71 /0 */ { 0, BX_IA_ERROR }, /* 72 /0 */ { 0, BX_IA_ERROR }, /* 73 /0 */ { 0, BX_IA_ERROR }, /* 74 /0 */ { 0, BX_IA_ERROR }, /* 75 /0 */ { 0, BX_IA_ERROR }, /* 76 /0 */ { 0, BX_IA_ERROR }, /* 77 /0 */ { 0, BX_IA_ERROR }, /* 78 /0 */ { 0, BX_IA_ERROR }, /* 79 /0 */ { 0, BX_IA_ERROR }, /* 7A /0 */ { 0, BX_IA_ERROR }, /* 7B /0 */ { 0, BX_IA_ERROR }, /* 7C /0 */ { 0, BX_IA_ERROR }, /* 7D /0 */ { 0, BX_IA_ERROR }, /* 7E /0 */ { 0, BX_IA_ERROR }, /* 7F /0 */ { 0, BX_IA_ERROR }, /* 80 /0 */ { 0, BX_IA_ERROR }, /* 81 /0 */ { 0, BX_IA_ERROR }, /* 82 /0 */ { 0, BX_IA_ERROR }, /* 83 /0 */ { 0, BX_IA_ERROR }, /* 84 /0 */ { 0, BX_IA_ERROR }, /* 85 /0 */ { 0, BX_IA_ERROR }, /* 86 /0 */ { 0, BX_IA_ERROR }, /* 87 /0 */ { 0, BX_IA_ERROR }, /* 88 /0 */ { 0, BX_IA_ERROR }, /* 89 /0 */ { 0, BX_IA_ERROR }, /* 8A /0 */ { 0, BX_IA_ERROR }, /* 8B /0 */ { 0, BX_IA_ERROR }, /* 8C /0 */ { 0, BX_IA_ERROR }, /* 8D /0 */ { 0, BX_IA_ERROR }, /* 8E /0 */ { 0, BX_IA_ERROR }, /* 8F /0 */ { 0, BX_IA_ERROR }, /* 90 /0 */ { 0, BX_IA_ERROR }, /* 91 /0 */ { 0, BX_IA_ERROR }, /* 92 /0 */ { 0, BX_IA_ERROR }, /* 93 /0 */ { 0, BX_IA_ERROR }, /* 94 /0 */ { 0, BX_IA_ERROR }, /* 95 /0 */ { 0, BX_IA_ERROR }, /* 96 /0 */ { 0, BX_IA_ERROR }, /* 97 /0 */ { 0, BX_IA_ERROR }, /* 98 /0 */ { 0, BX_IA_ERROR }, /* 99 /0 */ { 0, BX_IA_ERROR }, /* 9A /0 */ { 0, BX_IA_ERROR }, /* 9B /0 */ { 0, BX_IA_ERROR }, /* 9C /0 */ { 0, BX_IA_ERROR }, /* 9D /0 */ { 0, BX_IA_ERROR }, /* 9E /0 */ { 0, BX_IA_ERROR }, /* 9F /0 */ { 0, BX_IA_ERROR }, /* A0 /0 */ { 0, BX_IA_ERROR }, /* A1 /0 */ { 0, BX_IA_ERROR }, /* A2 /0 */ { 0, BX_IA_ERROR }, /* A3 /0 */ { 0, BX_IA_ERROR }, /* A4 /0 */ { 0, BX_IA_ERROR }, /* A5 /0 */ { 0, BX_IA_ERROR }, /* A6 /0 */ { 0, BX_IA_ERROR }, /* A7 /0 */ { 0, BX_IA_ERROR }, /* A8 /0 */ { 0, BX_IA_ERROR }, /* A9 /0 */ { 0, BX_IA_ERROR }, /* AA /0 */ { 0, BX_IA_ERROR }, /* AB /0 */ { 0, BX_IA_ERROR }, /* AC /0 */ { 0, BX_IA_ERROR }, /* AD /0 */ { 0, BX_IA_ERROR }, /* AE /0 */ { 0, BX_IA_ERROR }, /* AF /0 */ { 0, BX_IA_ERROR }, /* B0 /0 */ { 0, BX_IA_ERROR }, /* B1 /0 */ { 0, BX_IA_ERROR }, /* B2 /0 */ { 0, BX_IA_ERROR }, /* B3 /0 */ { 0, BX_IA_ERROR }, /* B4 /0 */ { 0, BX_IA_ERROR }, /* B5 /0 */ { 0, BX_IA_ERROR }, /* B6 /0 */ { 0, BX_IA_ERROR }, /* B7 /0 */ { 0, BX_IA_ERROR }, /* B8 /0 */ { 0, BX_IA_ERROR }, /* B9 /0 */ { 0, BX_IA_ERROR }, /* BA /0 */ { 0, BX_IA_ERROR }, /* BB /0 */ { 0, BX_IA_ERROR }, /* BC /0 */ { 0, BX_IA_ERROR }, /* BD /0 */ { 0, BX_IA_ERROR }, /* BE /0 */ { 0, BX_IA_ERROR }, /* BF /0 */ { 0, BX_IA_ERROR }, /* C0 /0 */ { 0, BX_IA_ERROR }, /* C1 /0 */ { 0, BX_IA_ERROR }, /* C2 /0 */ { 0, BX_IA_ERROR }, /* C3 /0 */ { 0, BX_IA_ERROR }, /* C4 /0 */ { 0, BX_IA_ERROR }, /* C5 /0 */ { 0, BX_IA_ERROR }, /* C6 /0 */ { 0, BX_IA_ERROR }, /* C7 /0 */ { 0, BX_IA_ERROR }, /* C8 /0 */ { 0, BX_IA_ERROR }, /* C9 /0 */ { 0, BX_IA_ERROR }, /* CA /0 */ { 0, BX_IA_ERROR }, /* CB /0 */ { 0, BX_IA_ERROR }, /* CC /0 */ { 0, BX_IA_ERROR }, /* CD /0 */ { 0, BX_IA_ERROR }, /* CE /0 */ { 0, BX_IA_ERROR }, /* CF /0 */ { 0, BX_IA_ERROR }, /* D0 /0 */ { 0, BX_IA_ERROR }, /* D1 /0 */ { 0, BX_IA_ERROR }, /* D2 /0 */ { 0, BX_IA_ERROR }, /* D3 /0 */ { 0, BX_IA_ERROR }, /* D4 /0 */ { 0, BX_IA_ERROR }, /* D5 /0 */ { 0, BX_IA_ERROR }, /* D6 /0 */ { 0, BX_IA_ERROR }, /* D7 /0 */ { 0, BX_IA_ERROR }, /* D8 /0 */ { 0, BX_IA_ERROR }, /* D9 /0 */ { 0, BX_IA_ERROR }, /* DA /0 */ { 0, BX_IA_ERROR }, /* DB /0 */ { 0, BX_IA_ERROR }, /* DC /0 */ { 0, BX_IA_ERROR }, /* DD /0 */ { 0, BX_IA_ERROR }, /* DE /0 */ { 0, BX_IA_ERROR }, /* DF /0 */ { 0, BX_IA_ERROR }, /* E0 /0 */ { 0, BX_IA_ERROR }, /* E1 /0 */ { 0, BX_IA_ERROR }, /* E2 /0 */ { 0, BX_IA_ERROR }, /* E3 /0 */ { 0, BX_IA_ERROR }, /* E4 /0 */ { 0, BX_IA_ERROR }, /* E5 /0 */ { 0, BX_IA_ERROR }, /* E6 /0 */ { 0, BX_IA_ERROR }, /* E7 /0 */ { 0, BX_IA_ERROR }, /* E8 /0 */ { 0, BX_IA_ERROR }, /* E9 /0 */ { 0, BX_IA_ERROR }, /* EA /0 */ { 0, BX_IA_ERROR }, /* EB /0 */ { 0, BX_IA_ERROR }, /* EC /0 */ { 0, BX_IA_ERROR }, /* ED /0 */ { 0, BX_IA_ERROR }, /* EE /0 */ { 0, BX_IA_ERROR }, /* EF /0 */ { 0, BX_IA_ERROR }, /* F0 /0 */ { 0, BX_IA_ERROR }, /* F1 /0 */ { 0, BX_IA_ERROR }, /* F2 /0 */ { 0, BX_IA_ERROR }, /* F3 /0 */ { 0, BX_IA_ERROR }, /* F4 /0 */ { 0, BX_IA_ERROR }, /* F5 /0 */ { 0, BX_IA_ERROR }, /* F6 /0 */ { 0, BX_IA_ERROR }, /* F7 /0 */ { 0, BX_IA_ERROR }, /* F8 /0 */ { 0, BX_IA_ERROR }, /* F9 /0 */ { 0, BX_IA_ERROR }, /* FA /0 */ { 0, BX_IA_ERROR }, /* FB /0 */ { 0, BX_IA_ERROR }, /* FC /0 */ { 0, BX_IA_ERROR }, /* FD /0 */ { 0, BX_IA_ERROR }, /* FE /0 */ { 0, BX_IA_ERROR }, /* FF /0 */ { 0, BX_IA_ERROR }, // 256 entries for XOP-encoded map 0x8 opcodes (VEX.L=1) /* 00 /1 */ { 0, BX_IA_ERROR }, /* 01 /1 */ { 0, BX_IA_ERROR }, /* 02 /1 */ { 0, BX_IA_ERROR }, /* 03 /1 */ { 0, BX_IA_ERROR }, /* 04 /1 */ { 0, BX_IA_ERROR }, /* 05 /1 */ { 0, BX_IA_ERROR }, /* 06 /1 */ { 0, BX_IA_ERROR }, /* 07 /1 */ { 0, BX_IA_ERROR }, /* 08 /1 */ { 0, BX_IA_ERROR }, /* 09 /1 */ { 0, BX_IA_ERROR }, /* 0A /1 */ { 0, BX_IA_ERROR }, /* 0B /1 */ { 0, BX_IA_ERROR }, /* 0C /1 */ { 0, BX_IA_ERROR }, /* 0D /1 */ { 0, BX_IA_ERROR }, /* 0E /1 */ { 0, BX_IA_ERROR }, /* 0F /1 */ { 0, BX_IA_ERROR }, /* 10 /1 */ { 0, BX_IA_ERROR }, /* 11 /1 */ { 0, BX_IA_ERROR }, /* 12 /1 */ { 0, BX_IA_ERROR }, /* 13 /1 */ { 0, BX_IA_ERROR }, /* 14 /1 */ { 0, BX_IA_ERROR }, /* 15 /1 */ { 0, BX_IA_ERROR }, /* 16 /1 */ { 0, BX_IA_ERROR }, /* 17 /1 */ { 0, BX_IA_ERROR }, /* 18 /1 */ { 0, BX_IA_ERROR }, /* 19 /1 */ { 0, BX_IA_ERROR }, /* 1A /1 */ { 0, BX_IA_ERROR }, /* 1B /1 */ { 0, BX_IA_ERROR }, /* 1C /1 */ { 0, BX_IA_ERROR }, /* 1D /1 */ { 0, BX_IA_ERROR }, /* 1E /1 */ { 0, BX_IA_ERROR }, /* 1F /1 */ { 0, BX_IA_ERROR }, /* 20 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 21 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 22 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 23 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 24 /1 */ { 0, BX_IA_ERROR }, /* 25 /1 */ { 0, BX_IA_ERROR }, /* 26 /1 */ { 0, BX_IA_ERROR }, /* 27 /1 */ { 0, BX_IA_ERROR }, /* 28 /1 */ { 0, BX_IA_ERROR }, /* 29 /1 */ { 0, BX_IA_ERROR }, /* 2A /1 */ { 0, BX_IA_ERROR }, /* 2B /1 */ { 0, BX_IA_ERROR }, /* 2C /1 */ { 0, BX_IA_ERROR }, /* 2D /1 */ { 0, BX_IA_ERROR }, /* 2E /1 */ { 0, BX_IA_ERROR }, /* 2F /1 */ { 0, BX_IA_ERROR }, /* 30 /1 */ { 0, BX_IA_ERROR }, /* 31 /1 */ { 0, BX_IA_ERROR }, /* 32 /1 */ { 0, BX_IA_ERROR }, /* 33 /1 */ { 0, BX_IA_ERROR }, /* 34 /1 */ { 0, BX_IA_ERROR }, /* 35 /1 */ { 0, BX_IA_ERROR }, /* 36 /1 */ { 0, BX_IA_ERROR }, /* 37 /1 */ { 0, BX_IA_ERROR }, /* 38 /1 */ { 0, BX_IA_ERROR }, /* 39 /1 */ { 0, BX_IA_ERROR }, /* 3A /1 */ { 0, BX_IA_ERROR }, /* 3B /1 */ { 0, BX_IA_ERROR }, /* 3C /1 */ { 0, BX_IA_ERROR }, /* 3D /1 */ { 0, BX_IA_ERROR }, /* 3E /1 */ { 0, BX_IA_ERROR }, /* 3F /1 */ { 0, BX_IA_ERROR }, /* 40 /1 */ { 0, BX_IA_ERROR }, /* 41 /1 */ { 0, BX_IA_ERROR }, /* 42 /1 */ { 0, BX_IA_ERROR }, /* 43 /1 */ { 0, BX_IA_ERROR }, /* 44 /1 */ { 0, BX_IA_ERROR }, /* 45 /1 */ { 0, BX_IA_ERROR }, /* 46 /1 */ { 0, BX_IA_ERROR }, /* 47 /1 */ { 0, BX_IA_ERROR }, /* 48 /1 */ { 0, BX_IA_ERROR }, /* 49 /1 */ { 0, BX_IA_ERROR }, /* 4A /1 */ { 0, BX_IA_ERROR }, /* 4B /1 */ { 0, BX_IA_ERROR }, /* 4C /1 */ { 0, BX_IA_ERROR }, /* 4D /1 */ { 0, BX_IA_ERROR }, /* 4E /1 */ { 0, BX_IA_ERROR }, /* 4F /1 */ { 0, BX_IA_ERROR }, /* 50 /1 */ { 0, BX_IA_ERROR }, /* 51 /1 */ { 0, BX_IA_ERROR }, /* 52 /1 */ { 0, BX_IA_ERROR }, /* 53 /1 */ { 0, BX_IA_ERROR }, /* 54 /1 */ { 0, BX_IA_ERROR }, /* 55 /1 */ { 0, BX_IA_ERROR }, /* 56 /1 */ { 0, BX_IA_ERROR }, /* 57 /1 */ { 0, BX_IA_ERROR }, /* 58 /1 */ { 0, BX_IA_ERROR }, /* 59 /1 */ { 0, BX_IA_ERROR }, /* 5A /1 */ { 0, BX_IA_ERROR }, /* 5B /1 */ { 0, BX_IA_ERROR }, /* 5C /1 */ { 0, BX_IA_ERROR }, /* 5D /1 */ { 0, BX_IA_ERROR }, /* 5E /1 */ { 0, BX_IA_ERROR }, /* 5F /1 */ { 0, BX_IA_ERROR }, /* 60 /1 */ { 0, BX_IA_ERROR }, /* 61 /1 */ { 0, BX_IA_ERROR }, /* 62 /1 */ { 0, BX_IA_ERROR }, /* 63 /1 */ { 0, BX_IA_ERROR }, /* 64 /1 */ { 0, BX_IA_ERROR }, /* 65 /1 */ { 0, BX_IA_ERROR }, /* 66 /1 */ { 0, BX_IA_ERROR }, /* 67 /1 */ { 0, BX_IA_ERROR }, /* 68 /1 */ { 0, BX_IA_ERROR }, /* 69 /1 */ { 0, BX_IA_ERROR }, /* 6A /1 */ { 0, BX_IA_ERROR }, /* 6B /1 */ { 0, BX_IA_ERROR }, /* 6C /1 */ { 0, BX_IA_ERROR }, /* 6D /1 */ { 0, BX_IA_ERROR }, /* 6E /1 */ { 0, BX_IA_ERROR }, /* 6F /1 */ { 0, BX_IA_ERROR }, /* 70 /1 */ { 0, BX_IA_ERROR }, /* 71 /1 */ { 0, BX_IA_ERROR }, /* 72 /1 */ { 0, BX_IA_ERROR }, /* 73 /1 */ { 0, BX_IA_ERROR }, /* 74 /1 */ { 0, BX_IA_ERROR }, /* 75 /1 */ { 0, BX_IA_ERROR }, /* 76 /1 */ { 0, BX_IA_ERROR }, /* 77 /1 */ { 0, BX_IA_ERROR }, /* 78 /1 */ { 0, BX_IA_ERROR }, /* 79 /1 */ { 0, BX_IA_ERROR }, /* 7A /1 */ { 0, BX_IA_ERROR }, /* 7B /1 */ { 0, BX_IA_ERROR }, /* 7C /1 */ { 0, BX_IA_ERROR }, /* 7D /1 */ { 0, BX_IA_ERROR }, /* 7E /1 */ { 0, BX_IA_ERROR }, /* 7F /1 */ { 0, BX_IA_ERROR }, /* 80 /1 */ { 0, BX_IA_ERROR }, /* 81 /1 */ { 0, BX_IA_ERROR }, /* 82 /1 */ { 0, BX_IA_ERROR }, /* 83 /1 */ { 0, BX_IA_ERROR }, /* 84 /1 */ { 0, BX_IA_ERROR }, /* 85 /1 */ { 0, BX_IA_ERROR }, /* 86 /1 */ { 0, BX_IA_ERROR }, /* 87 /1 */ { 0, BX_IA_ERROR }, /* 88 /1 */ { 0, BX_IA_ERROR }, /* 89 /1 */ { 0, BX_IA_ERROR }, /* 8A /1 */ { 0, BX_IA_ERROR }, /* 8B /1 */ { 0, BX_IA_ERROR }, /* 8C /1 */ { 0, BX_IA_ERROR }, /* 8D /1 */ { 0, BX_IA_ERROR }, /* 8E /1 */ { 0, BX_IA_ERROR }, /* 8F /1 */ { 0, BX_IA_ERROR }, /* 90 /1 */ { 0, BX_IA_ERROR }, /* 91 /1 */ { 0, BX_IA_ERROR }, /* 92 /1 */ { 0, BX_IA_ERROR }, /* 93 /1 */ { 0, BX_IA_ERROR }, /* 94 /1 */ { 0, BX_IA_ERROR }, /* 95 /1 */ { 0, BX_IA_ERROR }, /* 96 /1 */ { 0, BX_IA_ERROR }, /* 97 /1 */ { 0, BX_IA_ERROR }, /* 98 /1 */ { 0, BX_IA_ERROR }, /* 99 /1 */ { 0, BX_IA_ERROR }, /* 9A /1 */ { 0, BX_IA_ERROR }, /* 9B /1 */ { 0, BX_IA_ERROR }, /* 9C /1 */ { 0, BX_IA_ERROR }, /* 9D /1 */ { 0, BX_IA_ERROR }, /* 9E /1 */ { 0, BX_IA_ERROR }, /* 9F /1 */ { 0, BX_IA_ERROR }, /* A0 /1 */ { 0, BX_IA_ERROR }, /* A1 /1 */ { 0, BX_IA_ERROR }, /* A2 /1 */ { BxImmediate_Ib4, BX_IA_VPCMOV_VdqHdqWdqVIb }, /* A3 /1 */ { 0, BX_IA_ERROR }, /* A4 /1 */ { 0, BX_IA_ERROR }, /* A5 /1 */ { 0, BX_IA_ERROR }, /* A6 /1 */ { 0, BX_IA_ERROR }, /* A7 /1 */ { 0, BX_IA_ERROR }, /* A8 /1 */ { 0, BX_IA_ERROR }, /* A9 /1 */ { 0, BX_IA_ERROR }, /* AA /1 */ { 0, BX_IA_ERROR }, /* AB /1 */ { 0, BX_IA_ERROR }, /* AC /1 */ { 0, BX_IA_ERROR }, /* AD /1 */ { 0, BX_IA_ERROR }, /* AE /1 */ { 0, BX_IA_ERROR }, /* AF /1 */ { 0, BX_IA_ERROR }, /* B0 /1 */ { 0, BX_IA_ERROR }, /* B1 /1 */ { 0, BX_IA_ERROR }, /* B2 /1 */ { 0, BX_IA_ERROR }, /* B3 /1 */ { 0, BX_IA_ERROR }, /* B4 /1 */ { 0, BX_IA_ERROR }, /* B5 /1 */ { 0, BX_IA_ERROR }, /* B6 /1 */ { 0, BX_IA_ERROR }, /* B7 /1 */ { 0, BX_IA_ERROR }, /* B8 /1 */ { 0, BX_IA_ERROR }, /* B9 /1 */ { 0, BX_IA_ERROR }, /* BA /1 */ { 0, BX_IA_ERROR }, /* BB /1 */ { 0, BX_IA_ERROR }, /* BC /1 */ { 0, BX_IA_ERROR }, /* BD /1 */ { 0, BX_IA_ERROR }, /* BE /1 */ { 0, BX_IA_ERROR }, /* BF /1 */ { 0, BX_IA_ERROR }, /* C0 /1 */ { 0, BX_IA_ERROR }, /* C1 /1 */ { 0, BX_IA_ERROR }, /* C2 /1 */ { 0, BX_IA_ERROR }, /* C3 /1 */ { 0, BX_IA_ERROR }, /* C4 /1 */ { 0, BX_IA_ERROR }, /* C5 /1 */ { 0, BX_IA_ERROR }, /* C6 /1 */ { 0, BX_IA_ERROR }, /* C7 /1 */ { 0, BX_IA_ERROR }, /* C8 /1 */ { 0, BX_IA_ERROR }, /* C9 /1 */ { 0, BX_IA_ERROR }, /* CA /1 */ { 0, BX_IA_ERROR }, /* CB /1 */ { 0, BX_IA_ERROR }, /* CC /1 */ { 0, BX_IA_ERROR }, /* CD /1 */ { 0, BX_IA_ERROR }, /* CE /1 */ { 0, BX_IA_ERROR }, /* CF /1 */ { 0, BX_IA_ERROR }, /* D0 /1 */ { 0, BX_IA_ERROR }, /* D1 /1 */ { 0, BX_IA_ERROR }, /* D2 /1 */ { 0, BX_IA_ERROR }, /* D3 /1 */ { 0, BX_IA_ERROR }, /* D4 /1 */ { 0, BX_IA_ERROR }, /* D5 /1 */ { 0, BX_IA_ERROR }, /* D6 /1 */ { 0, BX_IA_ERROR }, /* D7 /1 */ { 0, BX_IA_ERROR }, /* D8 /1 */ { 0, BX_IA_ERROR }, /* D9 /1 */ { 0, BX_IA_ERROR }, /* DA /1 */ { 0, BX_IA_ERROR }, /* DB /1 */ { 0, BX_IA_ERROR }, /* DC /1 */ { 0, BX_IA_ERROR }, /* DD /1 */ { 0, BX_IA_ERROR }, /* DE /1 */ { 0, BX_IA_ERROR }, /* DF /1 */ { 0, BX_IA_ERROR }, /* E0 /1 */ { 0, BX_IA_ERROR }, /* E1 /1 */ { 0, BX_IA_ERROR }, /* E2 /1 */ { 0, BX_IA_ERROR }, /* E3 /1 */ { 0, BX_IA_ERROR }, /* E4 /1 */ { 0, BX_IA_ERROR }, /* E5 /1 */ { 0, BX_IA_ERROR }, /* E6 /1 */ { 0, BX_IA_ERROR }, /* E7 /1 */ { 0, BX_IA_ERROR }, /* E8 /1 */ { 0, BX_IA_ERROR }, /* E9 /1 */ { 0, BX_IA_ERROR }, /* EA /1 */ { 0, BX_IA_ERROR }, /* EB /1 */ { 0, BX_IA_ERROR }, /* EC /1 */ { 0, BX_IA_ERROR }, /* ED /1 */ { 0, BX_IA_ERROR }, /* EE /1 */ { 0, BX_IA_ERROR }, /* EF /1 */ { 0, BX_IA_ERROR }, /* F0 /1 */ { 0, BX_IA_ERROR }, /* F1 /1 */ { 0, BX_IA_ERROR }, /* F2 /1 */ { 0, BX_IA_ERROR }, /* F3 /1 */ { 0, BX_IA_ERROR }, /* F4 /1 */ { 0, BX_IA_ERROR }, /* F5 /1 */ { 0, BX_IA_ERROR }, /* F6 /1 */ { 0, BX_IA_ERROR }, /* F7 /1 */ { 0, BX_IA_ERROR }, /* F8 /1 */ { 0, BX_IA_ERROR }, /* F9 /1 */ { 0, BX_IA_ERROR }, /* FA /1 */ { 0, BX_IA_ERROR }, /* FB /1 */ { 0, BX_IA_ERROR }, /* FC /1 */ { 0, BX_IA_ERROR }, /* FD /1 */ { 0, BX_IA_ERROR }, /* FE /1 */ { 0, BX_IA_ERROR }, /* FF /1 */ { 0, BX_IA_ERROR }, // 256 entries for XOP-encoded map 0x9 opcodes (VEX.L=1) /* 00 /1 */ { 0, BX_IA_ERROR }, /* 01 /1 */ { 0, BX_IA_ERROR }, /* 02 /1 */ { 0, BX_IA_ERROR }, /* 03 /1 */ { 0, BX_IA_ERROR }, /* 04 /1 */ { 0, BX_IA_ERROR }, /* 05 /1 */ { 0, BX_IA_ERROR }, /* 06 /1 */ { 0, BX_IA_ERROR }, /* 07 /1 */ { 0, BX_IA_ERROR }, /* 08 /1 */ { 0, BX_IA_ERROR }, /* 09 /1 */ { 0, BX_IA_ERROR }, /* 0A /1 */ { 0, BX_IA_ERROR }, /* 0B /1 */ { 0, BX_IA_ERROR }, /* 0C /1 */ { 0, BX_IA_ERROR }, /* 0D /1 */ { 0, BX_IA_ERROR }, /* 0E /1 */ { 0, BX_IA_ERROR }, /* 0F /1 */ { 0, BX_IA_ERROR }, /* 10 /1 */ { 0, BX_IA_ERROR }, /* 11 /1 */ { 0, BX_IA_ERROR }, /* 12 /1 */ { 0, BX_IA_ERROR }, /* 13 /1 */ { 0, BX_IA_ERROR }, /* 14 /1 */ { 0, BX_IA_ERROR }, /* 15 /1 */ { 0, BX_IA_ERROR }, /* 16 /1 */ { 0, BX_IA_ERROR }, /* 17 /1 */ { 0, BX_IA_ERROR }, /* 18 /1 */ { 0, BX_IA_ERROR }, /* 19 /1 */ { 0, BX_IA_ERROR }, /* 1A /1 */ { 0, BX_IA_ERROR }, /* 1B /1 */ { 0, BX_IA_ERROR }, /* 1C /1 */ { 0, BX_IA_ERROR }, /* 1D /1 */ { 0, BX_IA_ERROR }, /* 1E /1 */ { 0, BX_IA_ERROR }, /* 1F /1 */ { 0, BX_IA_ERROR }, /* 20 /1 */ { 0, BX_IA_ERROR }, /* 21 /1 */ { 0, BX_IA_ERROR }, /* 22 /1 */ { 0, BX_IA_ERROR }, /* 23 /1 */ { 0, BX_IA_ERROR }, /* 24 /1 */ { 0, BX_IA_ERROR }, /* 25 /1 */ { 0, BX_IA_ERROR }, /* 26 /1 */ { 0, BX_IA_ERROR }, /* 27 /1 */ { 0, BX_IA_ERROR }, /* 28 /1 */ { 0, BX_IA_ERROR }, /* 29 /1 */ { 0, BX_IA_ERROR }, /* 2A /1 */ { 0, BX_IA_ERROR }, /* 2B /1 */ { 0, BX_IA_ERROR }, /* 2C /1 */ { 0, BX_IA_ERROR }, /* 2D /1 */ { 0, BX_IA_ERROR }, /* 2E /1 */ { 0, BX_IA_ERROR }, /* 2F /1 */ { 0, BX_IA_ERROR }, /* 30 /1 */ { 0, BX_IA_ERROR }, /* 31 /1 */ { 0, BX_IA_ERROR }, /* 32 /1 */ { 0, BX_IA_ERROR }, /* 33 /1 */ { 0, BX_IA_ERROR }, /* 34 /1 */ { 0, BX_IA_ERROR }, /* 35 /1 */ { 0, BX_IA_ERROR }, /* 36 /1 */ { 0, BX_IA_ERROR }, /* 37 /1 */ { 0, BX_IA_ERROR }, /* 38 /1 */ { 0, BX_IA_ERROR }, /* 39 /1 */ { 0, BX_IA_ERROR }, /* 3A /1 */ { 0, BX_IA_ERROR }, /* 3B /1 */ { 0, BX_IA_ERROR }, /* 3C /1 */ { 0, BX_IA_ERROR }, /* 3D /1 */ { 0, BX_IA_ERROR }, /* 3E /1 */ { 0, BX_IA_ERROR }, /* 3F /1 */ { 0, BX_IA_ERROR }, /* 40 /1 */ { 0, BX_IA_ERROR }, /* 41 /1 */ { 0, BX_IA_ERROR }, /* 42 /1 */ { 0, BX_IA_ERROR }, /* 43 /1 */ { 0, BX_IA_ERROR }, /* 44 /1 */ { 0, BX_IA_ERROR }, /* 45 /1 */ { 0, BX_IA_ERROR }, /* 46 /1 */ { 0, BX_IA_ERROR }, /* 47 /1 */ { 0, BX_IA_ERROR }, /* 48 /1 */ { 0, BX_IA_ERROR }, /* 49 /1 */ { 0, BX_IA_ERROR }, /* 4A /1 */ { 0, BX_IA_ERROR }, /* 4B /1 */ { 0, BX_IA_ERROR }, /* 4C /1 */ { 0, BX_IA_ERROR }, /* 4D /1 */ { 0, BX_IA_ERROR }, /* 4E /1 */ { 0, BX_IA_ERROR }, /* 4F /1 */ { 0, BX_IA_ERROR }, /* 50 /1 */ { 0, BX_IA_ERROR }, /* 51 /1 */ { 0, BX_IA_ERROR }, /* 52 /1 */ { 0, BX_IA_ERROR }, /* 53 /1 */ { 0, BX_IA_ERROR }, /* 54 /1 */ { 0, BX_IA_ERROR }, /* 55 /1 */ { 0, BX_IA_ERROR }, /* 56 /1 */ { 0, BX_IA_ERROR }, /* 57 /1 */ { 0, BX_IA_ERROR }, /* 58 /1 */ { 0, BX_IA_ERROR }, /* 59 /1 */ { 0, BX_IA_ERROR }, /* 5A /1 */ { 0, BX_IA_ERROR }, /* 5B /1 */ { 0, BX_IA_ERROR }, /* 5C /1 */ { 0, BX_IA_ERROR }, /* 5D /1 */ { 0, BX_IA_ERROR }, /* 5E /1 */ { 0, BX_IA_ERROR }, /* 5F /1 */ { 0, BX_IA_ERROR }, /* 60 /1 */ { 0, BX_IA_ERROR }, /* 61 /1 */ { 0, BX_IA_ERROR }, /* 62 /1 */ { 0, BX_IA_ERROR }, /* 63 /1 */ { 0, BX_IA_ERROR }, /* 64 /1 */ { 0, BX_IA_ERROR }, /* 65 /1 */ { 0, BX_IA_ERROR }, /* 66 /1 */ { 0, BX_IA_ERROR }, /* 67 /1 */ { 0, BX_IA_ERROR }, /* 68 /1 */ { 0, BX_IA_ERROR }, /* 69 /1 */ { 0, BX_IA_ERROR }, /* 6A /1 */ { 0, BX_IA_ERROR }, /* 6B /1 */ { 0, BX_IA_ERROR }, /* 6C /1 */ { 0, BX_IA_ERROR }, /* 6D /1 */ { 0, BX_IA_ERROR }, /* 6E /1 */ { 0, BX_IA_ERROR }, /* 6F /1 */ { 0, BX_IA_ERROR }, /* 70 /1 */ { 0, BX_IA_ERROR }, /* 71 /1 */ { 0, BX_IA_ERROR }, /* 72 /1 */ { 0, BX_IA_ERROR }, /* 73 /1 */ { 0, BX_IA_ERROR }, /* 74 /1 */ { 0, BX_IA_ERROR }, /* 75 /1 */ { 0, BX_IA_ERROR }, /* 76 /1 */ { 0, BX_IA_ERROR }, /* 77 /1 */ { 0, BX_IA_ERROR }, /* 78 /1 */ { 0, BX_IA_ERROR }, /* 79 /1 */ { 0, BX_IA_ERROR }, /* 7A /1 */ { 0, BX_IA_ERROR }, /* 7B /1 */ { 0, BX_IA_ERROR }, /* 7C /1 */ { 0, BX_IA_ERROR }, /* 7D /1 */ { 0, BX_IA_ERROR }, /* 7E /1 */ { 0, BX_IA_ERROR }, /* 7F /1 */ { 0, BX_IA_ERROR }, /* 80 /1 */ { BxVexW0, BX_IA_VFRCZPS_VpsWps }, /* 81 /1 */ { BxVexW0, BX_IA_VFRCZPD_VpdWpd }, /* 82 /1 */ { 0, BX_IA_ERROR }, /* 83 /1 */ { 0, BX_IA_ERROR }, /* 84 /1 */ { 0, BX_IA_ERROR }, /* 85 /1 */ { 0, BX_IA_ERROR }, /* 86 /1 */ { 0, BX_IA_ERROR }, /* 87 /1 */ { 0, BX_IA_ERROR }, /* 88 /1 */ { 0, BX_IA_ERROR }, /* 89 /1 */ { 0, BX_IA_ERROR }, /* 8A /1 */ { 0, BX_IA_ERROR }, /* 8B /1 */ { 0, BX_IA_ERROR }, /* 8C /1 */ { 0, BX_IA_ERROR }, /* 8D /1 */ { 0, BX_IA_ERROR }, /* 8E /1 */ { 0, BX_IA_ERROR }, /* 8F /1 */ { 0, BX_IA_ERROR }, /* 90 /1 */ { 0, BX_IA_ERROR }, /* 91 /1 */ { 0, BX_IA_ERROR }, /* 92 /1 */ { 0, BX_IA_ERROR }, /* 93 /1 */ { 0, BX_IA_ERROR }, /* 94 /1 */ { 0, BX_IA_ERROR }, /* 95 /1 */ { 0, BX_IA_ERROR }, /* 96 /1 */ { 0, BX_IA_ERROR }, /* 97 /1 */ { 0, BX_IA_ERROR }, /* 98 /1 */ { 0, BX_IA_ERROR }, /* 99 /1 */ { 0, BX_IA_ERROR }, /* 9A /1 */ { 0, BX_IA_ERROR }, /* 9B /1 */ { 0, BX_IA_ERROR }, /* 9C /1 */ { 0, BX_IA_ERROR }, /* 9D /1 */ { 0, BX_IA_ERROR }, /* 9E /1 */ { 0, BX_IA_ERROR }, /* 9F /1 */ { 0, BX_IA_ERROR }, /* A0 /1 */ { 0, BX_IA_ERROR }, /* A1 /1 */ { 0, BX_IA_ERROR }, /* A2 /1 */ { 0, BX_IA_ERROR }, /* A3 /1 */ { 0, BX_IA_ERROR }, /* A4 /1 */ { 0, BX_IA_ERROR }, /* A5 /1 */ { 0, BX_IA_ERROR }, /* A6 /1 */ { 0, BX_IA_ERROR }, /* A7 /1 */ { 0, BX_IA_ERROR }, /* A8 /1 */ { 0, BX_IA_ERROR }, /* A9 /1 */ { 0, BX_IA_ERROR }, /* AA /1 */ { 0, BX_IA_ERROR }, /* AB /1 */ { 0, BX_IA_ERROR }, /* AC /1 */ { 0, BX_IA_ERROR }, /* AD /1 */ { 0, BX_IA_ERROR }, /* AE /1 */ { 0, BX_IA_ERROR }, /* AF /1 */ { 0, BX_IA_ERROR }, /* B0 /1 */ { 0, BX_IA_ERROR }, /* B1 /1 */ { 0, BX_IA_ERROR }, /* B2 /1 */ { 0, BX_IA_ERROR }, /* B3 /1 */ { 0, BX_IA_ERROR }, /* B4 /1 */ { 0, BX_IA_ERROR }, /* B5 /1 */ { 0, BX_IA_ERROR }, /* B6 /1 */ { 0, BX_IA_ERROR }, /* B7 /1 */ { 0, BX_IA_ERROR }, /* B8 /1 */ { 0, BX_IA_ERROR }, /* B9 /1 */ { 0, BX_IA_ERROR }, /* BA /1 */ { 0, BX_IA_ERROR }, /* BB /1 */ { 0, BX_IA_ERROR }, /* BC /1 */ { 0, BX_IA_ERROR }, /* BD /1 */ { 0, BX_IA_ERROR }, /* BE /1 */ { 0, BX_IA_ERROR }, /* BF /1 */ { 0, BX_IA_ERROR }, /* C0 /1 */ { 0, BX_IA_ERROR }, /* C1 /1 */ { 0, BX_IA_ERROR }, /* C2 /1 */ { 0, BX_IA_ERROR }, /* C3 /1 */ { 0, BX_IA_ERROR }, /* C4 /1 */ { 0, BX_IA_ERROR }, /* C5 /1 */ { 0, BX_IA_ERROR }, /* C6 /1 */ { 0, BX_IA_ERROR }, /* C7 /1 */ { 0, BX_IA_ERROR }, /* C8 /1 */ { 0, BX_IA_ERROR }, /* C9 /1 */ { 0, BX_IA_ERROR }, /* CA /1 */ { 0, BX_IA_ERROR }, /* CB /1 */ { 0, BX_IA_ERROR }, /* CC /1 */ { 0, BX_IA_ERROR }, /* CD /1 */ { 0, BX_IA_ERROR }, /* CE /1 */ { 0, BX_IA_ERROR }, /* CF /1 */ { 0, BX_IA_ERROR }, /* D0 /1 */ { 0, BX_IA_ERROR }, /* D1 /1 */ { 0, BX_IA_ERROR }, /* D2 /1 */ { 0, BX_IA_ERROR }, /* D3 /1 */ { 0, BX_IA_ERROR }, /* D4 /1 */ { 0, BX_IA_ERROR }, /* D5 /1 */ { 0, BX_IA_ERROR }, /* D6 /1 */ { 0, BX_IA_ERROR }, /* D7 /1 */ { 0, BX_IA_ERROR }, /* D8 /1 */ { 0, BX_IA_ERROR }, /* D9 /1 */ { 0, BX_IA_ERROR }, /* DA /1 */ { 0, BX_IA_ERROR }, /* DB /1 */ { 0, BX_IA_ERROR }, /* DC /1 */ { 0, BX_IA_ERROR }, /* DD /1 */ { 0, BX_IA_ERROR }, /* DE /1 */ { 0, BX_IA_ERROR }, /* DF /1 */ { 0, BX_IA_ERROR }, /* E0 /1 */ { 0, BX_IA_ERROR }, /* E1 /1 */ { 0, BX_IA_ERROR }, /* E2 /1 */ { 0, BX_IA_ERROR }, /* E3 /1 */ { 0, BX_IA_ERROR }, /* E4 /1 */ { 0, BX_IA_ERROR }, /* E5 /1 */ { 0, BX_IA_ERROR }, /* E6 /1 */ { 0, BX_IA_ERROR }, /* E7 /1 */ { 0, BX_IA_ERROR }, /* E8 /1 */ { 0, BX_IA_ERROR }, /* E9 /1 */ { 0, BX_IA_ERROR }, /* EA /1 */ { 0, BX_IA_ERROR }, /* EB /1 */ { 0, BX_IA_ERROR }, /* EC /1 */ { 0, BX_IA_ERROR }, /* ED /1 */ { 0, BX_IA_ERROR }, /* EE /1 */ { 0, BX_IA_ERROR }, /* EF /1 */ { 0, BX_IA_ERROR }, /* F0 /1 */ { 0, BX_IA_ERROR }, /* F1 /1 */ { 0, BX_IA_ERROR }, /* F2 /1 */ { 0, BX_IA_ERROR }, /* F3 /1 */ { 0, BX_IA_ERROR }, /* F4 /1 */ { 0, BX_IA_ERROR }, /* F5 /1 */ { 0, BX_IA_ERROR }, /* F6 /1 */ { 0, BX_IA_ERROR }, /* F7 /1 */ { 0, BX_IA_ERROR }, /* F8 /1 */ { 0, BX_IA_ERROR }, /* F9 /1 */ { 0, BX_IA_ERROR }, /* FA /1 */ { 0, BX_IA_ERROR }, /* FB /1 */ { 0, BX_IA_ERROR }, /* FC /1 */ { 0, BX_IA_ERROR }, /* FD /1 */ { 0, BX_IA_ERROR }, /* FE /1 */ { 0, BX_IA_ERROR }, /* FF /1 */ { 0, BX_IA_ERROR }, // 256 entries for XOP-encoded map 0xA opcodes (VEX.L=1) /* 00 /1 */ { 0, BX_IA_ERROR }, /* 01 /1 */ { 0, BX_IA_ERROR }, /* 02 /1 */ { 0, BX_IA_ERROR }, /* 03 /1 */ { 0, BX_IA_ERROR }, /* 04 /1 */ { 0, BX_IA_ERROR }, /* 05 /1 */ { 0, BX_IA_ERROR }, /* 06 /1 */ { 0, BX_IA_ERROR }, /* 07 /1 */ { 0, BX_IA_ERROR }, /* 08 /1 */ { 0, BX_IA_ERROR }, /* 09 /1 */ { 0, BX_IA_ERROR }, /* 0A /1 */ { 0, BX_IA_ERROR }, /* 0B /1 */ { 0, BX_IA_ERROR }, /* 0C /1 */ { 0, BX_IA_ERROR }, /* 0D /1 */ { 0, BX_IA_ERROR }, /* 0E /1 */ { 0, BX_IA_ERROR }, /* 0F /1 */ { 0, BX_IA_ERROR }, /* 10 /1 */ { 0, BX_IA_ERROR }, /* 11 /1 */ { 0, BX_IA_ERROR }, /* 12 /1 */ { 0, BX_IA_ERROR }, /* 13 /1 */ { 0, BX_IA_ERROR }, /* 14 /1 */ { 0, BX_IA_ERROR }, /* 15 /1 */ { 0, BX_IA_ERROR }, /* 16 /1 */ { 0, BX_IA_ERROR }, /* 17 /1 */ { 0, BX_IA_ERROR }, /* 18 /1 */ { 0, BX_IA_ERROR }, /* 19 /1 */ { 0, BX_IA_ERROR }, /* 1A /1 */ { 0, BX_IA_ERROR }, /* 1B /1 */ { 0, BX_IA_ERROR }, /* 1C /1 */ { 0, BX_IA_ERROR }, /* 1D /1 */ { 0, BX_IA_ERROR }, /* 1E /1 */ { 0, BX_IA_ERROR }, /* 1F /1 */ { 0, BX_IA_ERROR }, /* 20 /1 */ { 0, BX_IA_ERROR }, /* 21 /1 */ { 0, BX_IA_ERROR }, /* 22 /1 */ { 0, BX_IA_ERROR }, /* 23 /1 */ { 0, BX_IA_ERROR }, /* 24 /1 */ { 0, BX_IA_ERROR }, /* 25 /1 */ { 0, BX_IA_ERROR }, /* 26 /1 */ { 0, BX_IA_ERROR }, /* 27 /1 */ { 0, BX_IA_ERROR }, /* 28 /1 */ { 0, BX_IA_ERROR }, /* 29 /1 */ { 0, BX_IA_ERROR }, /* 2A /1 */ { 0, BX_IA_ERROR }, /* 2B /1 */ { 0, BX_IA_ERROR }, /* 2C /1 */ { 0, BX_IA_ERROR }, /* 2D /1 */ { 0, BX_IA_ERROR }, /* 2E /1 */ { 0, BX_IA_ERROR }, /* 2F /1 */ { 0, BX_IA_ERROR }, /* 30 /1 */ { 0, BX_IA_ERROR }, /* 31 /1 */ { 0, BX_IA_ERROR }, /* 32 /1 */ { 0, BX_IA_ERROR }, /* 33 /1 */ { 0, BX_IA_ERROR }, /* 34 /1 */ { 0, BX_IA_ERROR }, /* 35 /1 */ { 0, BX_IA_ERROR }, /* 36 /1 */ { 0, BX_IA_ERROR }, /* 37 /1 */ { 0, BX_IA_ERROR }, /* 38 /1 */ { 0, BX_IA_ERROR }, /* 39 /1 */ { 0, BX_IA_ERROR }, /* 3A /1 */ { 0, BX_IA_ERROR }, /* 3B /1 */ { 0, BX_IA_ERROR }, /* 3C /1 */ { 0, BX_IA_ERROR }, /* 3D /1 */ { 0, BX_IA_ERROR }, /* 3E /1 */ { 0, BX_IA_ERROR }, /* 3F /1 */ { 0, BX_IA_ERROR }, /* 40 /1 */ { 0, BX_IA_ERROR }, /* 41 /1 */ { 0, BX_IA_ERROR }, /* 42 /1 */ { 0, BX_IA_ERROR }, /* 43 /1 */ { 0, BX_IA_ERROR }, /* 44 /1 */ { 0, BX_IA_ERROR }, /* 45 /1 */ { 0, BX_IA_ERROR }, /* 46 /1 */ { 0, BX_IA_ERROR }, /* 47 /1 */ { 0, BX_IA_ERROR }, /* 48 /1 */ { 0, BX_IA_ERROR }, /* 49 /1 */ { 0, BX_IA_ERROR }, /* 4A /1 */ { 0, BX_IA_ERROR }, /* 4B /1 */ { 0, BX_IA_ERROR }, /* 4C /1 */ { 0, BX_IA_ERROR }, /* 4D /1 */ { 0, BX_IA_ERROR }, /* 4E /1 */ { 0, BX_IA_ERROR }, /* 4F /1 */ { 0, BX_IA_ERROR }, /* 50 /1 */ { 0, BX_IA_ERROR }, /* 51 /1 */ { 0, BX_IA_ERROR }, /* 52 /1 */ { 0, BX_IA_ERROR }, /* 53 /1 */ { 0, BX_IA_ERROR }, /* 54 /1 */ { 0, BX_IA_ERROR }, /* 55 /1 */ { 0, BX_IA_ERROR }, /* 56 /1 */ { 0, BX_IA_ERROR }, /* 57 /1 */ { 0, BX_IA_ERROR }, /* 58 /1 */ { 0, BX_IA_ERROR }, /* 59 /1 */ { 0, BX_IA_ERROR }, /* 5A /1 */ { 0, BX_IA_ERROR }, /* 5B /1 */ { 0, BX_IA_ERROR }, /* 5C /1 */ { 0, BX_IA_ERROR }, /* 5D /1 */ { 0, BX_IA_ERROR }, /* 5E /1 */ { 0, BX_IA_ERROR }, /* 5F /1 */ { 0, BX_IA_ERROR }, /* 60 /1 */ { 0, BX_IA_ERROR }, /* 61 /1 */ { 0, BX_IA_ERROR }, /* 62 /1 */ { 0, BX_IA_ERROR }, /* 63 /1 */ { 0, BX_IA_ERROR }, /* 64 /1 */ { 0, BX_IA_ERROR }, /* 65 /1 */ { 0, BX_IA_ERROR }, /* 66 /1 */ { 0, BX_IA_ERROR }, /* 67 /1 */ { 0, BX_IA_ERROR }, /* 68 /1 */ { 0, BX_IA_ERROR }, /* 69 /1 */ { 0, BX_IA_ERROR }, /* 6A /1 */ { 0, BX_IA_ERROR }, /* 6B /1 */ { 0, BX_IA_ERROR }, /* 6C /1 */ { 0, BX_IA_ERROR }, /* 6D /1 */ { 0, BX_IA_ERROR }, /* 6E /1 */ { 0, BX_IA_ERROR }, /* 6F /1 */ { 0, BX_IA_ERROR }, /* 70 /1 */ { 0, BX_IA_ERROR }, /* 71 /1 */ { 0, BX_IA_ERROR }, /* 72 /1 */ { 0, BX_IA_ERROR }, /* 73 /1 */ { 0, BX_IA_ERROR }, /* 74 /1 */ { 0, BX_IA_ERROR }, /* 75 /1 */ { 0, BX_IA_ERROR }, /* 76 /1 */ { 0, BX_IA_ERROR }, /* 77 /1 */ { 0, BX_IA_ERROR }, /* 78 /1 */ { 0, BX_IA_ERROR }, /* 79 /1 */ { 0, BX_IA_ERROR }, /* 7A /1 */ { 0, BX_IA_ERROR }, /* 7B /1 */ { 0, BX_IA_ERROR }, /* 7C /1 */ { 0, BX_IA_ERROR }, /* 7D /1 */ { 0, BX_IA_ERROR }, /* 7E /1 */ { 0, BX_IA_ERROR }, /* 7F /1 */ { 0, BX_IA_ERROR }, /* 80 /1 */ { 0, BX_IA_ERROR }, /* 81 /1 */ { 0, BX_IA_ERROR }, /* 82 /1 */ { 0, BX_IA_ERROR }, /* 83 /1 */ { 0, BX_IA_ERROR }, /* 84 /1 */ { 0, BX_IA_ERROR }, /* 85 /1 */ { 0, BX_IA_ERROR }, /* 86 /1 */ { 0, BX_IA_ERROR }, /* 87 /1 */ { 0, BX_IA_ERROR }, /* 88 /1 */ { 0, BX_IA_ERROR }, /* 89 /1 */ { 0, BX_IA_ERROR }, /* 8A /1 */ { 0, BX_IA_ERROR }, /* 8B /1 */ { 0, BX_IA_ERROR }, /* 8C /1 */ { 0, BX_IA_ERROR }, /* 8D /1 */ { 0, BX_IA_ERROR }, /* 8E /1 */ { 0, BX_IA_ERROR }, /* 8F /1 */ { 0, BX_IA_ERROR }, /* 90 /1 */ { 0, BX_IA_ERROR }, /* 91 /1 */ { 0, BX_IA_ERROR }, /* 92 /1 */ { 0, BX_IA_ERROR }, /* 93 /1 */ { 0, BX_IA_ERROR }, /* 94 /1 */ { 0, BX_IA_ERROR }, /* 95 /1 */ { 0, BX_IA_ERROR }, /* 96 /1 */ { 0, BX_IA_ERROR }, /* 97 /1 */ { 0, BX_IA_ERROR }, /* 98 /1 */ { 0, BX_IA_ERROR }, /* 99 /1 */ { 0, BX_IA_ERROR }, /* 9A /1 */ { 0, BX_IA_ERROR }, /* 9B /1 */ { 0, BX_IA_ERROR }, /* 9C /1 */ { 0, BX_IA_ERROR }, /* 9D /1 */ { 0, BX_IA_ERROR }, /* 9E /1 */ { 0, BX_IA_ERROR }, /* 9F /1 */ { 0, BX_IA_ERROR }, /* A0 /1 */ { 0, BX_IA_ERROR }, /* A1 /1 */ { 0, BX_IA_ERROR }, /* A2 /1 */ { 0, BX_IA_ERROR }, /* A3 /1 */ { 0, BX_IA_ERROR }, /* A4 /1 */ { 0, BX_IA_ERROR }, /* A5 /1 */ { 0, BX_IA_ERROR }, /* A6 /1 */ { 0, BX_IA_ERROR }, /* A7 /1 */ { 0, BX_IA_ERROR }, /* A8 /1 */ { 0, BX_IA_ERROR }, /* A9 /1 */ { 0, BX_IA_ERROR }, /* AA /1 */ { 0, BX_IA_ERROR }, /* AB /1 */ { 0, BX_IA_ERROR }, /* AC /1 */ { 0, BX_IA_ERROR }, /* AD /1 */ { 0, BX_IA_ERROR }, /* AE /1 */ { 0, BX_IA_ERROR }, /* AF /1 */ { 0, BX_IA_ERROR }, /* B0 /1 */ { 0, BX_IA_ERROR }, /* B1 /1 */ { 0, BX_IA_ERROR }, /* B2 /1 */ { 0, BX_IA_ERROR }, /* B3 /1 */ { 0, BX_IA_ERROR }, /* B4 /1 */ { 0, BX_IA_ERROR }, /* B5 /1 */ { 0, BX_IA_ERROR }, /* B6 /1 */ { 0, BX_IA_ERROR }, /* B7 /1 */ { 0, BX_IA_ERROR }, /* B8 /1 */ { 0, BX_IA_ERROR }, /* B9 /1 */ { 0, BX_IA_ERROR }, /* BA /1 */ { 0, BX_IA_ERROR }, /* BB /1 */ { 0, BX_IA_ERROR }, /* BC /1 */ { 0, BX_IA_ERROR }, /* BD /1 */ { 0, BX_IA_ERROR }, /* BE /1 */ { 0, BX_IA_ERROR }, /* BF /1 */ { 0, BX_IA_ERROR }, /* C0 /1 */ { 0, BX_IA_ERROR }, /* C1 /1 */ { 0, BX_IA_ERROR }, /* C2 /1 */ { 0, BX_IA_ERROR }, /* C3 /1 */ { 0, BX_IA_ERROR }, /* C4 /1 */ { 0, BX_IA_ERROR }, /* C5 /1 */ { 0, BX_IA_ERROR }, /* C6 /1 */ { 0, BX_IA_ERROR }, /* C7 /1 */ { 0, BX_IA_ERROR }, /* C8 /1 */ { 0, BX_IA_ERROR }, /* C9 /1 */ { 0, BX_IA_ERROR }, /* CA /1 */ { 0, BX_IA_ERROR }, /* CB /1 */ { 0, BX_IA_ERROR }, /* CC /1 */ { 0, BX_IA_ERROR }, /* CD /1 */ { 0, BX_IA_ERROR }, /* CE /1 */ { 0, BX_IA_ERROR }, /* CF /1 */ { 0, BX_IA_ERROR }, /* D0 /1 */ { 0, BX_IA_ERROR }, /* D1 /1 */ { 0, BX_IA_ERROR }, /* D2 /1 */ { 0, BX_IA_ERROR }, /* D3 /1 */ { 0, BX_IA_ERROR }, /* D4 /1 */ { 0, BX_IA_ERROR }, /* D5 /1 */ { 0, BX_IA_ERROR }, /* D6 /1 */ { 0, BX_IA_ERROR }, /* D7 /1 */ { 0, BX_IA_ERROR }, /* D8 /1 */ { 0, BX_IA_ERROR }, /* D9 /1 */ { 0, BX_IA_ERROR }, /* DA /1 */ { 0, BX_IA_ERROR }, /* DB /1 */ { 0, BX_IA_ERROR }, /* DC /1 */ { 0, BX_IA_ERROR }, /* DD /1 */ { 0, BX_IA_ERROR }, /* DE /1 */ { 0, BX_IA_ERROR }, /* DF /1 */ { 0, BX_IA_ERROR }, /* E0 /1 */ { 0, BX_IA_ERROR }, /* E1 /1 */ { 0, BX_IA_ERROR }, /* E2 /1 */ { 0, BX_IA_ERROR }, /* E3 /1 */ { 0, BX_IA_ERROR }, /* E4 /1 */ { 0, BX_IA_ERROR }, /* E5 /1 */ { 0, BX_IA_ERROR }, /* E6 /1 */ { 0, BX_IA_ERROR }, /* E7 /1 */ { 0, BX_IA_ERROR }, /* E8 /1 */ { 0, BX_IA_ERROR }, /* E9 /1 */ { 0, BX_IA_ERROR }, /* EA /1 */ { 0, BX_IA_ERROR }, /* EB /1 */ { 0, BX_IA_ERROR }, /* EC /1 */ { 0, BX_IA_ERROR }, /* ED /1 */ { 0, BX_IA_ERROR }, /* EE /1 */ { 0, BX_IA_ERROR }, /* EF /1 */ { 0, BX_IA_ERROR }, /* F0 /1 */ { 0, BX_IA_ERROR }, /* F1 /1 */ { 0, BX_IA_ERROR }, /* F2 /1 */ { 0, BX_IA_ERROR }, /* F3 /1 */ { 0, BX_IA_ERROR }, /* F4 /1 */ { 0, BX_IA_ERROR }, /* F5 /1 */ { 0, BX_IA_ERROR }, /* F6 /1 */ { 0, BX_IA_ERROR }, /* F7 /1 */ { 0, BX_IA_ERROR }, /* F8 /1 */ { 0, BX_IA_ERROR }, /* F9 /1 */ { 0, BX_IA_ERROR }, /* FA /1 */ { 0, BX_IA_ERROR }, /* FB /1 */ { 0, BX_IA_ERROR }, /* FC /1 */ { 0, BX_IA_ERROR }, /* FD /1 */ { 0, BX_IA_ERROR }, /* FE /1 */ { 0, BX_IA_ERROR }, /* FF /1 */ { 0, BX_IA_ERROR } }; #endif // BX_SUPPORT_AVX && BX_CPU_LEVEL >= 6 #endif // BX_XOP_FETCHDECODE_TABLES_H bochs-2.6/cpu/simd_pfp.h0000644000175000017500000003130312020641453015073 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: simd_pfp.h 10724 2011-10-07 14:09:35Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_SIMD_PFP_FUNCTIONS_H #define BX_SIMD_PFP_FUNCTIONS_H // arithmetic add/sub/mul/div BX_CPP_INLINE void sse_addps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_add(op1->xmm32u(0), op2->xmm32u(0), status); op1->xmm32u(1) = float32_add(op1->xmm32u(1), op2->xmm32u(1), status); op1->xmm32u(2) = float32_add(op1->xmm32u(2), op2->xmm32u(2), status); op1->xmm32u(3) = float32_add(op1->xmm32u(3), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_addpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_add(op1->xmm64u(0), op2->xmm64u(0), status); op1->xmm64u(1) = float64_add(op1->xmm64u(1), op2->xmm64u(1), status); } BX_CPP_INLINE void sse_subps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_sub(op1->xmm32u(0), op2->xmm32u(0), status); op1->xmm32u(1) = float32_sub(op1->xmm32u(1), op2->xmm32u(1), status); op1->xmm32u(2) = float32_sub(op1->xmm32u(2), op2->xmm32u(2), status); op1->xmm32u(3) = float32_sub(op1->xmm32u(3), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_subpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_sub(op1->xmm64u(0), op2->xmm64u(0), status); op1->xmm64u(1) = float64_sub(op1->xmm64u(1), op2->xmm64u(1), status); } BX_CPP_INLINE void sse_mulps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_mul(op1->xmm32u(0), op2->xmm32u(0), status); op1->xmm32u(1) = float32_mul(op1->xmm32u(1), op2->xmm32u(1), status); op1->xmm32u(2) = float32_mul(op1->xmm32u(2), op2->xmm32u(2), status); op1->xmm32u(3) = float32_mul(op1->xmm32u(3), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_mulpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_mul(op1->xmm64u(0), op2->xmm64u(0), status); op1->xmm64u(1) = float64_mul(op1->xmm64u(1), op2->xmm64u(1), status); } BX_CPP_INLINE void sse_divps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_div(op1->xmm32u(0), op2->xmm32u(0), status); op1->xmm32u(1) = float32_div(op1->xmm32u(1), op2->xmm32u(1), status); op1->xmm32u(2) = float32_div(op1->xmm32u(2), op2->xmm32u(2), status); op1->xmm32u(3) = float32_div(op1->xmm32u(3), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_divpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_div(op1->xmm64u(0), op2->xmm64u(0), status); op1->xmm64u(1) = float64_div(op1->xmm64u(1), op2->xmm64u(1), status); } BX_CPP_INLINE void sse_addsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_sub(op1->xmm32u(0), op2->xmm32u(0), status); op1->xmm32u(1) = float32_add(op1->xmm32u(1), op2->xmm32u(1), status); op1->xmm32u(2) = float32_sub(op1->xmm32u(2), op2->xmm32u(2), status); op1->xmm32u(3) = float32_add(op1->xmm32u(3), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_addsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_sub(op1->xmm64u(0), op2->xmm64u(0), status); op1->xmm64u(1) = float64_add(op1->xmm64u(1), op2->xmm64u(1), status); } // horizontal arithmetic add/sub BX_CPP_INLINE void sse_haddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_add(op1->xmm32u(0), op1->xmm32u(1), status); op1->xmm32u(1) = float32_add(op1->xmm32u(2), op1->xmm32u(3), status); op1->xmm32u(2) = float32_add(op2->xmm32u(0), op2->xmm32u(1), status); op1->xmm32u(3) = float32_add(op2->xmm32u(2), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_haddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_add(op1->xmm64u(0), op1->xmm64u(1), status); op1->xmm64u(1) = float64_add(op2->xmm64u(0), op2->xmm64u(1), status); } BX_CPP_INLINE void sse_hsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_sub(op1->xmm32u(0), op1->xmm32u(1), status); op1->xmm32u(1) = float32_sub(op1->xmm32u(2), op1->xmm32u(3), status); op1->xmm32u(2) = float32_sub(op2->xmm32u(0), op2->xmm32u(1), status); op1->xmm32u(3) = float32_sub(op2->xmm32u(2), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_hsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_sub(op1->xmm64u(0), op1->xmm64u(1), status); op1->xmm64u(1) = float64_sub(op2->xmm64u(0), op2->xmm64u(1), status); } // min/max BX_CPP_INLINE void sse_minps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_min(op1->xmm32u(0), op2->xmm32u(0), status); op1->xmm32u(1) = float32_min(op1->xmm32u(1), op2->xmm32u(1), status); op1->xmm32u(2) = float32_min(op1->xmm32u(2), op2->xmm32u(2), status); op1->xmm32u(3) = float32_min(op1->xmm32u(3), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_minpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_min(op1->xmm64u(0), op2->xmm64u(0), status); op1->xmm64u(1) = float64_min(op1->xmm64u(1), op2->xmm64u(1), status); } BX_CPP_INLINE void sse_maxps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm32u(0) = float32_max(op1->xmm32u(0), op2->xmm32u(0), status); op1->xmm32u(1) = float32_max(op1->xmm32u(1), op2->xmm32u(1), status); op1->xmm32u(2) = float32_max(op1->xmm32u(2), op2->xmm32u(2), status); op1->xmm32u(3) = float32_max(op1->xmm32u(3), op2->xmm32u(3), status); } BX_CPP_INLINE void sse_maxpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, float_status_t &status) { op1->xmm64u(0) = float64_max(op1->xmm64u(0), op2->xmm64u(0), status); op1->xmm64u(1) = float64_max(op1->xmm64u(1), op2->xmm64u(1), status); } // fma BX_CPP_INLINE void fmaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm32u(0) = float32_muladd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), 0, status); op1->xmm32u(1) = float32_muladd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), 0, status); op1->xmm32u(2) = float32_muladd(op1->xmm32u(2), op2->xmm32u(2), op3->xmm32u(2), 0, status); op1->xmm32u(3) = float32_muladd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), 0, status); } BX_CPP_INLINE void fmaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm64u(0) = float64_muladd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), 0, status); op1->xmm64u(1) = float64_muladd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), 0, status); } BX_CPP_INLINE void fmsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm32u(0) = float32_muladd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), float_muladd_negate_c, status); op1->xmm32u(1) = float32_muladd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), float_muladd_negate_c, status); op1->xmm32u(2) = float32_muladd(op1->xmm32u(2), op2->xmm32u(2), op3->xmm32u(2), float_muladd_negate_c, status); op1->xmm32u(3) = float32_muladd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), float_muladd_negate_c, status); } BX_CPP_INLINE void fmsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm64u(0) = float64_muladd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), float_muladd_negate_c, status); op1->xmm64u(1) = float64_muladd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), float_muladd_negate_c, status); } BX_CPP_INLINE void fmaddsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm32u(0) = float32_muladd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), float_muladd_negate_c, status); op1->xmm32u(1) = float32_muladd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), 0, status); op1->xmm32u(2) = float32_muladd(op1->xmm32u(2), op2->xmm32u(2), op3->xmm32u(2), float_muladd_negate_c, status); op1->xmm32u(3) = float32_muladd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), 0, status); } BX_CPP_INLINE void fmaddsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm64u(0) = float64_muladd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), float_muladd_negate_c, status); op1->xmm64u(1) = float64_muladd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), 0, status); } BX_CPP_INLINE void fmsubaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm32u(0) = float32_muladd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), 0, status); op1->xmm32u(1) = float32_muladd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), float_muladd_negate_c, status); op1->xmm32u(2) = float32_muladd(op1->xmm32u(2), op2->xmm32u(2), op3->xmm32u(2), 0, status); op1->xmm32u(3) = float32_muladd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), float_muladd_negate_c, status); } BX_CPP_INLINE void fmsubaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm64u(0) = float64_muladd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), 0, status); op1->xmm64u(1) = float64_muladd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), float_muladd_negate_c, status); } BX_CPP_INLINE void fnmaddps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm32u(0) = float32_muladd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), float_muladd_negate_product, status); op1->xmm32u(1) = float32_muladd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), float_muladd_negate_product, status); op1->xmm32u(2) = float32_muladd(op1->xmm32u(2), op2->xmm32u(2), op3->xmm32u(2), float_muladd_negate_product, status); op1->xmm32u(3) = float32_muladd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), float_muladd_negate_product, status); } BX_CPP_INLINE void fnmaddpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm64u(0) = float64_muladd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), float_muladd_negate_product, status); op1->xmm64u(1) = float64_muladd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), float_muladd_negate_product, status); } BX_CPP_INLINE void fnmsubps(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm32u(0) = float32_muladd(op1->xmm32u(0), op2->xmm32u(0), op3->xmm32u(0), float_muladd_negate_result, status); op1->xmm32u(1) = float32_muladd(op1->xmm32u(1), op2->xmm32u(1), op3->xmm32u(1), float_muladd_negate_result, status); op1->xmm32u(2) = float32_muladd(op1->xmm32u(2), op2->xmm32u(2), op3->xmm32u(2), float_muladd_negate_result, status); op1->xmm32u(3) = float32_muladd(op1->xmm32u(3), op2->xmm32u(3), op3->xmm32u(3), float_muladd_negate_result, status); } BX_CPP_INLINE void fnmsubpd(BxPackedXmmRegister *op1, const BxPackedXmmRegister *op2, const BxPackedXmmRegister *op3, float_status_t &status) { op1->xmm64u(0) = float64_muladd(op1->xmm64u(0), op2->xmm64u(0), op3->xmm64u(0), float_muladd_negate_result, status); op1->xmm64u(1) = float64_muladd(op1->xmm64u(1), op2->xmm64u(1), op3->xmm64u(1), float_muladd_negate_result, status); } #endif bochs-2.6/cpu/mult16.cc0000644000175000017500000001121012020641453014553 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: mult16.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MUL_AXEwR(bxInstruction_c *i) { Bit16u op1_16 = AX; Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); Bit32u product_32 = ((Bit32u) op1_16) * ((Bit32u) op2_16); Bit16u product_16l = (product_32 & 0xFFFF); Bit16u product_16h = product_32 >> 16; /* now write product back to destination */ AX = product_16l; DX = product_16h; /* set EFLAGS */ SET_FLAGS_OSZAPC_LOGIC_16(product_16l); if(product_16h != 0) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_AXEwR(bxInstruction_c *i) { Bit16s op1_16 = AX; Bit16s op2_16 = BX_READ_16BIT_REG(i->src()); Bit32s product_32 = ((Bit32s) op1_16) * ((Bit32s) op2_16); Bit16u product_16l = (product_32 & 0xFFFF); Bit16u product_16h = product_32 >> 16; /* now write product back to destination */ AX = product_16l; DX = product_16h; /* set eflags: * IMUL r/m16: condition for clearing CF & OF: * DX:AX = sign-extend of AX */ SET_FLAGS_OSZAPC_LOGIC_16(product_16l); if(product_32 != (Bit16s)product_32) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DIV_AXEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); if (op2_16 == 0) exception(BX_DE_EXCEPTION, 0); Bit32u op1_32 = (((Bit32u) DX) << 16) | ((Bit32u) AX); Bit32u quotient_32 = op1_32 / op2_16; Bit16u remainder_16 = op1_32 % op2_16; Bit16u quotient_16l = quotient_32 & 0xFFFF; if (quotient_32 != quotient_16l) exception(BX_DE_EXCEPTION, 0); /* now write quotient back to destination */ AX = quotient_16l; DX = remainder_16; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IDIV_AXEwR(bxInstruction_c *i) { Bit32s op1_32 = ((((Bit32u) DX) << 16) | ((Bit32u) AX)); /* check MIN_INT case */ if (op1_32 == ((Bit32s)0x80000000)) exception(BX_DE_EXCEPTION, 0); Bit16s op2_16 = BX_READ_16BIT_REG(i->src()); if (op2_16 == 0) exception(BX_DE_EXCEPTION, 0); Bit32s quotient_32 = op1_32 / op2_16; Bit16s remainder_16 = op1_32 % op2_16; Bit16s quotient_16l = quotient_32 & 0xFFFF; if (quotient_32 != quotient_16l) exception(BX_DE_EXCEPTION, 0); /* now write quotient back to destination */ AX = quotient_16l; DX = remainder_16; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GwEwIwR(bxInstruction_c *i) { Bit16s op2_16 = BX_READ_16BIT_REG(i->src()); Bit16s op3_16 = i->Iw(); Bit32s product_32 = op2_16 * op3_16; Bit16u product_16 = (product_32 & 0xFFFF); /* now write product back to destination */ BX_WRITE_16BIT_REG(i->dst(), product_16); /* set eflags: * IMUL r16,r/m16,imm16: condition for clearing CF & OF: * result exactly fits within r16 */ SET_FLAGS_OSZAPC_LOGIC_16(product_16); if(product_32 != (Bit16s) product_32) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IMUL_GwEwR(bxInstruction_c *i) { Bit16s op1_16 = BX_READ_16BIT_REG(i->dst()); Bit16s op2_16 = BX_READ_16BIT_REG(i->src()); Bit32s product_32 = op1_16 * op2_16; Bit16u product_16 = (product_32 & 0xFFFF); /* now write product back to destination */ BX_WRITE_16BIT_REG(i->dst(), product_16); /* set eflags: * IMUL r16,r/m16: condition for clearing CF & OF: * result exactly fits within r16 */ SET_FLAGS_OSZAPC_LOGIC_16(product_16); if(product_32 != (Bit16s) product_32) { ASSERT_FLAGS_OxxxxC(); } BX_NEXT_INSTR(i); } bochs-2.6/cpu/ret_far.cc0000644000175000017500000001747512020641453015070 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: ret_far.cc 11106 2012-03-25 11:54:32Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2005-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // //////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR void BX_CPP_AttrRegparmN(2) BX_CPU_C::return_protected(bxInstruction_c *i, Bit16u pop_bytes) { Bit16u raw_cs_selector, raw_ss_selector; bx_selector_t cs_selector, ss_selector; bx_descriptor_t cs_descriptor, ss_descriptor; Bit32u stack_param_offset; bx_address return_RIP, return_RSP, temp_RSP; Bit32u dword1, dword2; /* + 6+N*2: SS | +12+N*4: SS | +24+N*8 SS */ /* + 4+N*2: SP | + 8+N*4: ESP | +16+N*8 RSP */ /* parm N | + parm N | + parm N */ /* parm 3 | + parm 3 | + parm 3 */ /* parm 2 | + parm 2 | + parm 2 */ /* + 4: parm 1 | + 8: parm 1 | +16: parm 1 */ /* + 2: CS | + 4: CS | + 8: CS */ /* + 0: IP | + 0: EIP | + 0: RIP */ #if BX_SUPPORT_X86_64 if (long64_mode()) temp_RSP = RSP; else #endif { if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) temp_RSP = ESP; else temp_RSP = SP; } #if BX_SUPPORT_X86_64 if (i->os64L()) { raw_cs_selector = (Bit16u) stack_read_qword(temp_RSP + 8); return_RIP = stack_read_qword(temp_RSP); stack_param_offset = 16; } else #endif if (i->os32L()) { raw_cs_selector = (Bit16u) stack_read_dword(temp_RSP + 4); return_RIP = stack_read_dword(temp_RSP); stack_param_offset = 8; } else { raw_cs_selector = stack_read_word(temp_RSP + 2); return_RIP = stack_read_word(temp_RSP); stack_param_offset = 4; } // selector must be non-null else #GP(0) if ((raw_cs_selector & 0xfffc) == 0) { BX_ERROR(("return_protected: CS selector null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(raw_cs_selector, &cs_selector); // selector index must be within its descriptor table limits, // else #GP(selector) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); // descriptor AR byte must indicate code segment, else #GP(selector) parse_descriptor(dword1, dword2, &cs_descriptor); // return selector RPL must be >= CPL, else #GP(return selector) if (cs_selector.rpl < CPL) { BX_ERROR(("return_protected: CS.rpl < CPL")); exception(BX_GP_EXCEPTION, raw_cs_selector & 0xfffc); } // check code-segment descriptor check_cs(&cs_descriptor, raw_cs_selector, 0, cs_selector.rpl); // if return selector RPL == CPL then // RETURN TO SAME PRIVILEGE LEVEL if (cs_selector.rpl == CPL) { BX_DEBUG(("return_protected: return to SAME PRIVILEGE LEVEL")); branch_far64(&cs_selector, &cs_descriptor, return_RIP, CPL); #if BX_SUPPORT_X86_64 if (long64_mode()) RSP += stack_param_offset + pop_bytes; else #endif { if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) RSP = ESP + stack_param_offset + pop_bytes; else SP += stack_param_offset + pop_bytes; } } /* RETURN TO OUTER PRIVILEGE LEVEL */ else { /* + 6+N*2: SS | +12+N*4: SS | +24+N*8 SS */ /* + 4+N*2: SP | + 8+N*4: ESP | +16+N*8 RSP */ /* parm N | + parm N | + parm N */ /* parm 3 | + parm 3 | + parm 3 */ /* parm 2 | + parm 2 | + parm 2 */ /* + 4: parm 1 | + 8: parm 1 | +16: parm 1 */ /* + 2: CS | + 4: CS | + 8: CS */ /* + 0: IP | + 0: EIP | + 0: RIP */ BX_DEBUG(("return_protected: return to OUTER PRIVILEGE LEVEL")); #if BX_SUPPORT_X86_64 if (i->os64L()) { raw_ss_selector = stack_read_word(temp_RSP + 24 + pop_bytes); return_RSP = stack_read_qword(temp_RSP + 16 + pop_bytes); } else #endif if (i->os32L()) { raw_ss_selector = stack_read_word(temp_RSP + 12 + pop_bytes); return_RSP = stack_read_dword(temp_RSP + 8 + pop_bytes); } else { raw_ss_selector = stack_read_word(temp_RSP + 6 + pop_bytes); return_RSP = stack_read_word(temp_RSP + 4 + pop_bytes); } /* selector index must be within its descriptor table limits, * else #GP(selector) */ parse_selector(raw_ss_selector, &ss_selector); if ((raw_ss_selector & 0xfffc) == 0) { #if BX_SUPPORT_X86_64 if (long_mode()) { if (! IS_LONG64_SEGMENT(cs_descriptor) || (cs_selector.rpl == 3)) { BX_ERROR(("return_protected: SS selector null")); exception(BX_GP_EXCEPTION, 0); } } else // not in long or compatibility mode #endif { BX_ERROR(("return_protected: SS selector null")); exception(BX_GP_EXCEPTION, 0); } } else { fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &ss_descriptor); /* selector RPL must = RPL of the return CS selector, * else #GP(selector) */ if (ss_selector.rpl != cs_selector.rpl) { BX_ERROR(("return_protected: ss.rpl != cs.rpl")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* descriptor AR byte must indicate a writable data segment, * else #GP(selector) */ if (ss_descriptor.valid==0 || ss_descriptor.segment==0 || IS_CODE_SEGMENT(ss_descriptor.type) || !IS_DATA_SEGMENT_WRITEABLE(ss_descriptor.type)) { BX_ERROR(("return_protected: SS.AR byte not writable data")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* descriptor dpl must = RPL of the return CS selector, * else #GP(selector) */ if (ss_descriptor.dpl != cs_selector.rpl) { BX_ERROR(("return_protected: SS.dpl != cs.rpl")); exception(BX_GP_EXCEPTION, raw_ss_selector & 0xfffc); } /* segment must be present else #SS(selector) */ if (! IS_PRESENT(ss_descriptor)) { BX_ERROR(("return_protected: ss.present == 0")); exception(BX_SS_EXCEPTION, raw_ss_selector & 0xfffc); } } branch_far64(&cs_selector, &cs_descriptor, return_RIP, cs_selector.rpl); if ((raw_ss_selector & 0xfffc) != 0) { // load SS:RSP from stack // load the SS-cache with SS descriptor load_ss(&ss_selector, &ss_descriptor, cs_selector.rpl); } #if BX_SUPPORT_X86_64 else { // we are in 64-bit mode (checked above) load_null_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], raw_ss_selector); } if (long64_mode()) RSP = return_RSP + pop_bytes; else #endif { if (ss_descriptor.u.segment.d_b) RSP = (Bit32u)(return_RSP + pop_bytes); else SP = (Bit16u)(return_RSP + pop_bytes); } /* check ES, DS, FS, GS for validity */ validate_seg_regs(); } } bochs-2.6/cpu/xmm.h0000644000175000017500000003205512020641453014100 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: xmm.h 10737 2011-10-19 20:54:04Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2003-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_SSE_EXTENSIONS_H #define BX_SSE_EXTENSIONS_H /* XMM REGISTER */ typedef union bx_xmm_reg_t { Bit8s xmm_sbyte[16]; Bit16s xmm_s16[8]; Bit32s xmm_s32[4]; Bit64s xmm_s64[2]; Bit8u xmm_ubyte[16]; Bit16u xmm_u16[8]; Bit32u xmm_u32[4]; Bit64u xmm_u64[2]; } BxPackedXmmRegister; #ifdef BX_BIG_ENDIAN #define xmm64s(i) xmm_s64[1 - (i)] #define xmm32s(i) xmm_s32[3 - (i)] #define xmm16s(i) xmm_s16[7 - (i)] #define xmmsbyte(i) xmm_sbyte[15 - (i)] #define xmmubyte(i) xmm_ubyte[15 - (i)] #define xmm16u(i) xmm_u16[7 - (i)] #define xmm32u(i) xmm_u32[3 - (i)] #define xmm64u(i) xmm_u64[1 - (i)] #else #define xmm64s(i) xmm_s64[(i)] #define xmm32s(i) xmm_s32[(i)] #define xmm16s(i) xmm_s16[(i)] #define xmmsbyte(i) xmm_sbyte[(i)] #define xmmubyte(i) xmm_ubyte[(i)] #define xmm16u(i) xmm_u16[(i)] #define xmm32u(i) xmm_u32[(i)] #define xmm64u(i) xmm_u64[(i)] #endif /* AVX REGISTER */ enum bx_avx_vector_length { BX_NO_VL, BX_VL128, BX_VL256 }; #if BX_SUPPORT_AVX #define BX_VLMAX BX_VL256 #else #define BX_VLMAX BX_VL128 #endif #if BX_SUPPORT_AVX typedef union bx_avx_reg_t { Bit8s avx_sbyte[32]; Bit16s avx_s16[16]; Bit32s avx_s32[8]; Bit64s avx_s64[4]; Bit8u avx_ubyte[32]; Bit16u avx_u16[16]; Bit32u avx_u32[8]; Bit64u avx_u64[4]; BxPackedXmmRegister avx_v128[2]; } BxPackedAvxRegister; #ifdef BX_BIG_ENDIAN #define avx64s(i) avx_s64[3 - (i)] #define avx32s(i) avx_s32[7 - (i)] #define avx16s(i) avx_s16[15 - (i)] #define avxsbyte(i) avx_sbyte[31 - (i)] #define avxubyte(i) avx_ubyte[31 - (i)] #define avx16u(i) avx_u16[15 - (i)] #define avx32u(i) avx_u32[7 - (i)] #define avx64u(i) avx_u64[3 - (i)] #define avx128(i) avx_v128[1 - (i)] #else #define avx64s(i) avx_s64[(i)] #define avx32s(i) avx_s32[(i)] #define avx16s(i) avx_s16[(i)] #define avxsbyte(i) avx_sbyte[(i)] #define avxubyte(i) avx_ubyte[(i)] #define avx16u(i) avx_u16[(i)] #define avx32u(i) avx_u32[(i)] #define avx64u(i) avx_u64[(i)] #define avx128(i) avx_v128[(i)] #endif #endif #if BX_SUPPORT_X86_64 # define BX_XMM_REGISTERS 16 #else # define BX_XMM_REGISTERS 8 #endif #if BX_SUPPORT_AVX /* read XMM register */ #define BX_READ_XMM_REG(index) ((BX_CPU_THIS_PTR vmm[index]).avx128(0)) #else /* read XMM register */ #define BX_READ_XMM_REG(index) ((BX_CPU_THIS_PTR vmm[index])) #endif /* read only high 64 bit of the register */ #define BX_READ_XMM_REG_HI_QWORD(index) \ ((BX_READ_XMM_REG(index)).xmm64u(1)) /* read only low 64 bit of the register */ #define BX_READ_XMM_REG_LO_QWORD(index) \ ((BX_READ_XMM_REG(index)).xmm64u(0)) /* read only low 32 bit of the register */ #define BX_READ_XMM_REG_LO_DWORD(index) \ ((BX_READ_XMM_REG(index)).xmm32u(0)) /* read only low 16 bit of the register */ #define BX_READ_XMM_REG_LO_WORD(index) \ ((BX_READ_XMM_REG(index)).xmm16u(0)) /* read only low 8 bit of the register */ #define BX_READ_XMM_REG_LO_BYTE(index) \ ((BX_READ_XMM_REG(index)).xmmubyte(0)) /* short names for above macroses */ #define BX_XMM_REG_HI_QWORD BX_READ_XMM_REG_HI_QWORD #define BX_XMM_REG_LO_QWORD BX_READ_XMM_REG_LO_QWORD #define BX_XMM_REG_LO_DWORD BX_READ_XMM_REG_LO_DWORD #define BX_XMM_REG BX_READ_XMM_REG /* store only high 64 bit of the register, rest of the register unchanged */ #define BX_WRITE_XMM_REG_HI_QWORD(index, reg64) \ { (BX_XMM_REG(index)).xmm64u(1) = (reg64); } /* store only low 64 bit of the register, rest of the register unchanged */ #define BX_WRITE_XMM_REG_LO_QWORD(index, reg64) \ { (BX_XMM_REG(index)).xmm64u(0) = (reg64); } /* store only low 32 bit of the register, rest of the register unchanged */ #define BX_WRITE_XMM_REG_LO_DWORD(index, reg32) \ { (BX_XMM_REG(index)).xmm32u(0) = (reg32); } /* store only low 16 bit of the register, rest of the register unchanged */ #define BX_WRITE_XMM_REG_LO_WORD(index, reg16) \ { (BX_XMM_REG(index)).xmm16u(0) = (reg16); } /* store only low 8 bit of the register, rest of the register unchanged */ #define BX_WRITE_XMM_REG_LO_BYTE(index, reg8) \ { (BX_XMM_REG(index)).xmmubyte(0) = (reg8); } /* store XMM register */ #define BX_WRITE_XMM_REG(index, reg) \ { (BX_XMM_REG(index)) = (reg); } #if BX_SUPPORT_AVX /* read AVX register */ #define BX_READ_AVX_REG(index) (BX_CPU_THIS_PTR vmm[index]) #define BX_AVX_REG BX_READ_AVX_REG /* read AVX register */ #define BX_READ_AVX_REG_LINE(index, line) \ ((BX_READ_AVX_REG(index)).avx128(line)) /* write AVX register */ #define BX_WRITE_AVX_REG(index, reg) \ { (BX_READ_AVX_REG(index)) = (reg); } /* clear upper part of AVX register */ #define BX_CLEAR_AVX_HIGH(index) \ { (BX_READ_AVX_REG(index)).avx64u(2) = (BX_READ_AVX_REG(index)).avx64u(3) = 0; } /* write AVX register and potentialy clear upper part of the register */ #define BX_WRITE_AVX_REGZ(index, reg, vlen) \ { BX_CPU_THIS_PTR vmm[index] = (reg); \ if (vlen == BX_VL128) BX_CLEAR_AVX_HIGH(index); } /* write XMM register while clearing upper part of AVX register */ #define BX_WRITE_XMM_REG_CLEAR_HIGH(index, reg) \ { BX_XMM_REG(index) = (reg); BX_CLEAR_AVX_HIGH(index); } /* write XMM register while clearing upper part of AVX register */ #define BX_WRITE_XMM_REGZ(index, reg, vlen) \ { (BX_XMM_REG(index)) = (reg); \ if (vlen == BX_VL128) BX_CLEAR_AVX_HIGH(index); } #else /* write XMM register while clearing upper part of AVX register */ #define BX_WRITE_XMM_REG_CLEAR_HIGH(index, reg) \ BX_WRITE_XMM_REG(index, reg) /* write XMM register while clearing upper part of AVX register */ #define BX_WRITE_XMM_REGZ(index, reg, vlen) \ BX_WRITE_XMM_REG(index, reg) #endif /* MXCSR REGISTER */ /* 31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16 * ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|== (reserved) * 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|MM| 0 * * 15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0 * ==|==|=====|==|==|==|==|==|==|==|==|==|==|==|== * FZ| R C |PM|UM|OM|ZM|DM|IM|DZ|PE|UE|OE|ZE|DE|IE */ /* MXCSR REGISTER FIELDS DESCRIPTION */ /* * IE 0 Invalid-Operation Exception 0 * DE 1 Denormalized-Operand Exception 0 * ZE 2 Zero-Divide Exception 0 * OE 3 Overflow Exception 0 * UE 4 Underflow Exception 0 * PE 5 Precision Exception 0 * DZ 6 Denormals are Zeros 0 * IM 7 Invalid-Operation Exception Mask 1 * DM 8 Denormalized-Operand Exception Mask 1 * ZM 9 Zero-Divide Exception Mask 1 * OM 10 Overflow Exception Mask 1 * UM 11 Underflow Exception Mask 1 * PM 12 Precision Exception Mask 1 * RC 13-14 Floating-Point Rounding Control 00 * FZ 15 Flush-to-Zero for Masked Underflow 0 * RZ 16 Reserved 0 * MM 17 Misaligned Exception Mask 0 */ #define MXCSR_EXCEPTIONS 0x0000003F #define MXCSR_DAZ 0x00000040 #define MXCSR_MASKED_EXCEPTIONS 0x00001F80 #define MXCSR_ROUNDING_CONTROL 0x00006000 #define MXCSR_FLUSH_MASKED_UNDERFLOW 0x00008000 #define MXCSR_MISALIGNED_EXCEPTION_MASK 0x00020000 #define MXCSR_IE 0x00000001 #define MXCSR_DE 0x00000002 #define MXCSR_ZE 0x00000004 #define MXCSR_OE 0x00000008 #define MXCSR_UE 0x00000010 #define MXCSR_PE 0x00000020 #define MXCSR_IM 0x00000080 #define MXCSR_DM 0x00000100 #define MXCSR_ZM 0x00000200 #define MXCSR_OM 0x00000400 #define MXCSR_UM 0x00000800 #define MXCSR_PM 0x00001000 #define MXCSR_RESET 0x00001F80 /* reset value of the MXCSR register */ struct BOCHSAPI bx_mxcsr_t { Bit32u mxcsr; bx_mxcsr_t (Bit32u val = MXCSR_RESET) : mxcsr(val) {} #define IMPLEMENT_MXCSR_ACCESSOR(name, bitmask, bitnum) \ int get_##name () const { \ return (mxcsr & (bitmask)) >> (bitnum); \ } IMPLEMENT_MXCSR_ACCESSOR(exceptions_masks, MXCSR_MASKED_EXCEPTIONS, 7); IMPLEMENT_MXCSR_ACCESSOR(DAZ, MXCSR_DAZ, 6); IMPLEMENT_MXCSR_ACCESSOR(rounding_mode, MXCSR_ROUNDING_CONTROL, 13); IMPLEMENT_MXCSR_ACCESSOR(flush_masked_underflow, MXCSR_FLUSH_MASKED_UNDERFLOW, 15); IMPLEMENT_MXCSR_ACCESSOR(MM, MXCSR_MISALIGNED_EXCEPTION_MASK, 17); IMPLEMENT_MXCSR_ACCESSOR(IE, MXCSR_IE, 0); IMPLEMENT_MXCSR_ACCESSOR(DE, MXCSR_DE, 1); IMPLEMENT_MXCSR_ACCESSOR(ZE, MXCSR_ZE, 2); IMPLEMENT_MXCSR_ACCESSOR(OE, MXCSR_OE, 3); IMPLEMENT_MXCSR_ACCESSOR(UE, MXCSR_UE, 4); IMPLEMENT_MXCSR_ACCESSOR(PE, MXCSR_PE, 5); IMPLEMENT_MXCSR_ACCESSOR(IM, MXCSR_IM, 7); IMPLEMENT_MXCSR_ACCESSOR(DM, MXCSR_DM, 8); IMPLEMENT_MXCSR_ACCESSOR(ZM, MXCSR_ZM, 9); IMPLEMENT_MXCSR_ACCESSOR(OM, MXCSR_OM, 10); IMPLEMENT_MXCSR_ACCESSOR(UM, MXCSR_UM, 11); IMPLEMENT_MXCSR_ACCESSOR(PM, MXCSR_PM, 12); void set_exceptions(int status) { mxcsr |= (status & MXCSR_EXCEPTIONS); } }; #if defined(NEED_CPU_REG_SHORTCUTS) #define MXCSR (BX_CPU_THIS_PTR mxcsr) #define BX_MXCSR_REGISTER (BX_CPU_THIS_PTR mxcsr.mxcsr) #define MXCSR_MASK (BX_CPU_THIS_PTR mxcsr_mask) #endif /* INTEGER SATURATION */ /* * SaturateWordSToByteS converts a signed 16-bit value to a signed * 8-bit value. If the signed 16-bit value is less than -128, it is * represented by the saturated value -128 (0x80). If it is greater * than 127, it is represented by the saturated value 127 (0x7F). */ BX_CPP_INLINE Bit8s BX_CPP_AttrRegparmN(1) SaturateWordSToByteS(Bit16s value) { if(value < -128) return -128; if(value > 127) return 127; return (Bit8s) value; } /* * SaturateDwordSToWordS converts a signed 32-bit value to a signed * 16-bit value. If the signed 32-bit value is less than -32768, it is * represented by the saturated value -32768 (0x8000). If it is greater * than 32767, it is represented by the saturated value 32767 (0x7FFF). */ BX_CPP_INLINE Bit16s BX_CPP_AttrRegparmN(1) SaturateDwordSToWordS(Bit32s value) { if(value < -32768) return -32768; if(value > 32767) return 32767; return (Bit16s) value; } /* * SaturateQwordSToDwordS converts a signed 64-bit value to a signed * 32-bit value. If the signed 64-bit value is less than -2147483648, it * is represented by the saturated value -2147483648 (0x80000000). If it * is greater than 2147483647, it is represented by the saturated value * 2147483647 (0x7FFFFFFF). */ BX_CPP_INLINE Bit32s BX_CPP_AttrRegparmN(1) SaturateQwordSToDwordS(Bit64s value) { if(value < BX_CONST64(-2147483648)) return BX_CONST64(-2147483648); if(value > 2147483647) return 2147483647; return (Bit32s) value; } /* * SaturateWordSToByteU converts a signed 16-bit value to an unsigned * 8-bit value. If the signed 16-bit value is less than zero it is * represented by the saturated value zero (0x00).If it is greater than * 255 it is represented by the saturated value 255 (0xFF). */ BX_CPP_INLINE Bit8u BX_CPP_AttrRegparmN(1) SaturateWordSToByteU(Bit16s value) { if(value < 0) return 0; if(value > 255) return 255; return (Bit8u) value; } /* * SaturateDwordSToWordU converts a signed 32-bit value to an unsigned * 16-bit value. If the signed 32-bit value is less than zero, it is * represented by the saturated value zero (0x0000). If it is greater * than 65535, it is represented by the saturated value 65535 (0xFFFF). */ BX_CPP_INLINE Bit16u BX_CPP_AttrRegparmN(1) SaturateDwordSToWordU(Bit32s value) { if(value < 0) return 0; if(value > 65535) return 65535; return (Bit16u) value; } /* * SaturateQwordSToDwordU converts a signed 64-bit value to an unsigned * 32-bit value. If the signed 64-bit value is less than zero, it is * represented by the saturated value zero (0x00000000). If it is greater * than 4294967295, it is represented by the saturated value 4294967295 * (0xFFFFFFFF). */ BX_CPP_INLINE Bit32u BX_CPP_AttrRegparmN(1) SaturateDwordSToWordU(Bit64s value) { if(value < 0) return 0; if(value > BX_CONST64(4294967295)) return BX_CONST64(4294967295); return (Bit32u) value; } #endif bochs-2.6/cpu/sse_string.cc0000644000175000017500000003213712020641453015616 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: sse_string.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 6 // Compare all pairs of Ai, Bj according to imm8 control static void compare_strings(Bit8u BoolRes[16][16], BxPackedXmmRegister op1, BxPackedXmmRegister op2, Bit8u imm) { unsigned i, j; unsigned aggregation_operation = (imm >> 2) & 3; // All possible comparisons are performed, the individual boolean // results of those comparisons are referred by // BoolRes[op2 element index, op1 element index] switch (imm & 3) { case 0: /* unsigned bytes compare */ for (i=0;i<16;i++) { for (j=0;j<16;j++) { switch (aggregation_operation) { case 0: /* 'equal' comparison */ case 2: case 3: BoolRes[j][i] = (op1.xmmubyte(i) == op2.xmmubyte(j)); break; case 1: /* 'ranges' comparison */ if ((i % 2) == 0) BoolRes[j][i] = (op1.xmmubyte(i) <= op2.xmmubyte(j)); else BoolRes[j][i] = (op1.xmmubyte(i) >= op2.xmmubyte(j)); break; } } } break; case 1: /* unsigned words compare */ for (i=0;i<8;i++) { for (j=0;j<8;j++) { switch (aggregation_operation) { case 0: /* 'equal' comparison */ case 2: case 3: BoolRes[j][i] = (op1.xmm16u(i) == op2.xmm16u(j)); break; case 1: /* 'ranges' comparison */ if ((i % 2) == 0) BoolRes[j][i] = (op1.xmm16u(i) <= op2.xmm16u(j)); else BoolRes[j][i] = (op1.xmm16u(i) >= op2.xmm16u(j)); break; } } } break; case 2: /* signed bytes compare */ for (i=0;i<16;i++) { for (j=0;j<16;j++) { switch (aggregation_operation) { case 0: /* 'equal' comparison */ case 2: case 3: BoolRes[j][i] = (op1.xmmsbyte(i) == op2.xmmsbyte(j)); break; case 1: /* 'ranges' comparison */ if ((i % 2) == 0) BoolRes[j][i] = (op1.xmmsbyte(i) <= op2.xmmsbyte(j)); else BoolRes[j][i] = (op1.xmmsbyte(i) >= op2.xmmsbyte(j)); break; } } } break; case 3: /* signed words compare */ for (i=0;i<8;i++) { for (j=0;j<8;j++) { switch (aggregation_operation) { case 0: /* 'equal' comparison */ case 2: case 3: BoolRes[j][i] = (op1.xmm16s(i) == op2.xmm16s(j)); break; case 1: /* 'ranges' comparison */ if ((i % 2) == 0) BoolRes[j][i] = (op1.xmm16s(i) <= op2.xmm16s(j)); else BoolRes[j][i] = (op1.xmm16s(i) >= op2.xmm16s(j)); break; } } } break; } } static unsigned find_eos32(Bit32s reg32, Bit8u imm) { if (imm & 0x1) { // 8 elements if (reg32 > 8 || reg32 < -8) return 8; else return abs(reg32); } else { // 16 elements if (reg32 > 16 || reg32 < -16) return 16; else return abs(reg32); } } #if BX_SUPPORT_X86_64 static unsigned find_eos64(Bit64s reg64, Bit8u imm) { if (imm & 0x1) { // 8 elements if (reg64 > 8 || reg64 < -8) return 8; else return (unsigned) abs(reg64); } else { // 16 elements if (reg64 > 16 || reg64 < -16) return 16; else return (unsigned) abs(reg64); } } #endif static unsigned find_eos(BxPackedXmmRegister op, Bit8u imm) { unsigned i = 0; if (imm & 0x1) { // 8 elements for(i=0;i<8;i++) if (op.xmm16u(i) == 0) break; } else { // 16 elements for(i=0;i<16;i++) if (op.xmmubyte(i) == 0) break; } return i; } static bx_bool override_if_data_invalid(bx_bool val, bx_bool i_valid, bx_bool j_valid, Bit8u imm) { unsigned aggregation_operation = (imm >> 2) & 3; switch(aggregation_operation) { case 0: // 'equal any' case 1: // 'ranges' if (! i_valid || ! j_valid) // one of the elements is invalid return 0; break; case 2: // 'equal each' if (! i_valid) { if (! j_valid) return 1; // both elements are invalid else return 0; // only i is invalid } else { if (! j_valid) return 0; // only j is invalid } break; case 3: // 'equal ordered' if (! i_valid) { // element i is invalid return 1; } else { if (! j_valid) { // only j is invalid return 0; } } break; } return val; } static Bit16u aggregate(Bit8u BoolRes[16][16], unsigned len1, unsigned len2, Bit8u imm) { unsigned aggregation_operation = (imm >> 2) & 3; unsigned num_elements = (imm & 0x1) ? 8 : 16; unsigned polarity = (imm >> 4) & 3; unsigned i,j,k; Bit16u result = 0; switch(aggregation_operation) { case 0: // 'equal any' for(j=0; jdst()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()), result; Bit8u imm8 = i->Ib(); // compare all pairs of Ai, Bj Bit8u BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned len1, len2, num_elements = (imm8 & 0x1) ? 8 : 16; #if BX_SUPPORT_X86_64 if (i->os64L()) { len1 = find_eos64(RAX, imm8); len2 = find_eos64(RDX, imm8); } else #endif { len1 = find_eos32(EAX, imm8); len2 = find_eos32(EDX, imm8); } Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // As defined by imm8[6], result2 is then either stored to the least // significant bits of XMM0 (zero extended to 128 bits) or expanded // into a byte/word-mask and then stored to XMM0 if (imm8 & 0x40) { if (num_elements == 8) { for (int index = 0; index < 8; index++) result.xmm16u(index) = (result2 & (1<getVL()); /* store result XMM0 */ BX_NEXT_INSTR(i); } /* 66 0F 3A 61 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPESTRI_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); Bit8u imm8 = i->Ib(); // compare all pairs of Ai, Bj Bit8u BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned len1, len2, num_elements = (imm8 & 0x1) ? 8 : 16; int index; #if BX_SUPPORT_X86_64 if (i->os64L()) { len1 = find_eos64(RAX, imm8); len2 = find_eos64(RDX, imm8); } else #endif { len1 = find_eos32(EAX, imm8); len2 = find_eos32(EDX, imm8); } Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // The index of the first (or last, according to imm8[6]) set bit of result2 // is returned to ECX. If no bits are set in IntRes2, ECX is set to 16 (8) if (imm8 & 0x40) { // The index returned to ECX is of the MSB in result2 for (index=num_elements-1; index>=0; index--) if (result2 & (1<dst()); BxPackedXmmRegister op2 = BX_READ_XMM_REG(i->src()), result; Bit8u imm8 = i->Ib(); // compare all pairs of Ai, Bj Bit8u BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned num_elements = (imm8 & 0x1) ? 8 : 16; unsigned len1 = find_eos(op1, imm8); unsigned len2 = find_eos(op2, imm8); Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // As defined by imm8[6], result2 is then either stored to the least // significant bits of XMM0 (zero extended to 128 bits) or expanded // into a byte/word-mask and then stored to XMM0 if (imm8 & 0x40) { if (num_elements == 8) { for (int index = 0; index < 8; index++) result.xmm16u(index) = (result2 & (1<getVL()); /* store result XMM0 */ BX_NEXT_INSTR(i); } /* 66 0F 3A 63 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PCMPISTRI_VdqWdqIbR(bxInstruction_c *i) { BxPackedXmmRegister op1 = BX_READ_XMM_REG(i->dst()), op2 = BX_READ_XMM_REG(i->src()); Bit8u imm8 = i->Ib(); // compare all pairs of Ai, Bj Bit8u BoolRes[16][16]; compare_strings(BoolRes, op1, op2, imm8); unsigned num_elements = (imm8 & 0x1) ? 8 : 16; int index; unsigned len1 = find_eos(op1, imm8); unsigned len2 = find_eos(op2, imm8); Bit16u result2 = aggregate(BoolRes, len1, len2, imm8); // The index of the first (or last, according to imm8[6]) set bit of result2 // is returned to ECX. If no bits are set in IntRes2, ECX is set to 16 (8) if (imm8 & 0x40) { // The index returned to ECX is of the MSB in result2 for (index=num_elements-1; index>=0; index--) if (result2 & (1<= 6 bochs-2.6/cpu/ctrl_xfer32.cc0000644000175000017500000005030112020641453015564 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ctrl_xfer32.cc 11356 2012-08-21 19:58:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 3 BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near32(Bit32u new_EIP) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); // check always, not only in protected mode if (new_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("branch_near32: offset outside of CS limits")); exception(BX_GP_EXCEPTION, 0); } EIP = new_EIP; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0 // assert magic async_event to stop trace execution BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE; #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32_Iw(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif RSP_SPECULATIVE; Bit16u imm16 = i->Iw(); Bit32u return_EIP = pop_32(); if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("RETnear32_Iw: offset outside of CS limits")); exception(BX_GP_EXCEPTION, 0); } EIP = return_EIP; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) ESP += imm16; else SP += imm16; RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear32(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif RSP_SPECULATIVE; Bit32u return_EIP = pop_32(); if (return_EIP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("RETnear32: offset outside of CS limits")); exception(BX_GP_EXCEPTION, 0); } EIP = return_EIP; RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar32_Iw(bxInstruction_c *i) { invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif Bit16u imm16 = i->Iw(); Bit16u cs_raw; Bit32u eip; if (protected_mode()) { return_protected(i, imm16); goto done; } RSP_SPECULATIVE; eip = pop_32(); cs_raw = (Bit16u) pop_32(); /* 32bit pop, MSW discarded */ // CS.LIMIT can't change when in real/v8086 mode if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("RETfar32_Iw: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = eip; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) ESP += imm16; else SP += imm16; RSP_COMMIT; done: BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_Jd(bxInstruction_c *i) { #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif Bit32u new_EIP = EIP + i->Id(); RSP_SPECULATIVE; /* push 32 bit EA of next instruction */ push_32(EIP); branch_near32(new_EIP); RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ap(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit16u cs_raw; Bit32u disp32; invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif disp32 = i->Id(); cs_raw = i->Iw2(); RSP_SPECULATIVE; if (protected_mode()) { call_protected(i, cs_raw, disp32); goto done; } // CS.LIMIT can't change when in real/v8086 mode if (disp32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("CALL32_Ap: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_32(EIP); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = disp32; done: RSP_COMMIT; BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EdR(bxInstruction_c *i) { #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif Bit32u new_EIP = BX_READ_32BIT_REG(i->dst()); RSP_SPECULATIVE; /* push 32 bit EA of next instruction */ push_32(EIP); branch_near32(new_EIP); RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL_INDIRECT, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL32_Ep(bxInstruction_c *i) { Bit16u cs_raw; Bit32u op1_32; invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_32 = read_virtual_dword(i->seg(), eaddr); cs_raw = read_virtual_word (i->seg(), (eaddr+4) & i->asize_mask()); RSP_SPECULATIVE; if (protected_mode()) { call_protected(i, cs_raw, op1_32); goto done; } // CS.LIMIT can't change when in real/v8086 mode if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("CALL32_Ep: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_32(EIP); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = op1_32; done: RSP_COMMIT; BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL_INDIRECT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Jd(bxInstruction_c *i) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JO_Jd(bxInstruction_c *i) { if (get_OF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNO_Jd(bxInstruction_c *i) { if (! get_OF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JB_Jd(bxInstruction_c *i) { if (get_CF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNB_Jd(bxInstruction_c *i) { if (! get_CF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JZ_Jd(bxInstruction_c *i) { if (get_ZF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNZ_Jd(bxInstruction_c *i) { if (! get_ZF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JBE_Jd(bxInstruction_c *i) { if (get_CF() || get_ZF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNBE_Jd(bxInstruction_c *i) { if (! (get_CF() || get_ZF())) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JS_Jd(bxInstruction_c *i) { if (get_SF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNS_Jd(bxInstruction_c *i) { if (! get_SF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JP_Jd(bxInstruction_c *i) { if (get_PF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNP_Jd(bxInstruction_c *i) { if (! get_PF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JL_Jd(bxInstruction_c *i) { if (getB_SF() != getB_OF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNL_Jd(bxInstruction_c *i) { if (getB_SF() == getB_OF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JLE_Jd(bxInstruction_c *i) { if (get_ZF() || (getB_SF() != getB_OF())) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNLE_Jd(bxInstruction_c *i) { if (! get_ZF() && (getB_SF() == getB_OF())) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Ap(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u disp32; Bit16u cs_raw; invalidate_prefetch_q(); if (i->os32L()) { disp32 = i->Id(); } else { disp32 = i->Iw(); } cs_raw = i->Iw2(); // jump_protected doesn't affect ESP so it is ESP safe if (protected_mode()) { jump_protected(i, cs_raw, disp32); goto done; } // CS.LIMIT can't change when in real/v8086 mode if (disp32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("JMP_Ap: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = disp32; done: BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EdR(bxInstruction_c *i) { Bit32u new_EIP = BX_READ_32BIT_REG(i->dst()); branch_near32(new_EIP); BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP_INDIRECT, PREV_RIP, new_EIP); BX_NEXT_TRACE(i); } /* Far indirect jump */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP32_Ep(bxInstruction_c *i) { Bit16u cs_raw; Bit32u op1_32; invalidate_prefetch_q(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ op1_32 = read_virtual_dword(i->seg(), eaddr); cs_raw = read_virtual_word (i->seg(), (eaddr+4) & i->asize_mask()); // jump_protected doesn't affect RSP so it is RSP safe if (protected_mode()) { jump_protected(i, cs_raw, op1_32); goto done; } // CS.LIMIT can't change when in real/v8086 mode if (op1_32 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("JMP32_Ep: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = op1_32; done: BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP_INDIRECT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET32(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); invalidate_prefetch_q(); #if BX_SUPPORT_VMX if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT)) #endif BX_CPU_THIS_PTR disable_NMI = 0; #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_iret; #endif if (protected_mode()) { iret_protected(i); goto done; } RSP_SPECULATIVE; if (v8086_mode()) { // IOPL check in stack_return_from_v86() iret32_stack_return_from_v86(i); } else { Bit32u eip = pop_32(); Bit16u cs_raw = (Bit16u) pop_32(); // #SS has higher priority Bit32u eflags32 = pop_32(); // CS.LIMIT can't change when in real/v8086 mode if (eip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("IRET32: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = eip; writeEFlags(eflags32, 0x00257fd5); // VIF, VIP, VM unchanged } RSP_COMMIT; done: BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JECXZ_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); Bit32u temp_ECX; if (i->as32L()) temp_ECX = ECX; else temp_ECX = CX; if (temp_ECX == 0) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_TRACE(i); } // // There is some weirdness in LOOP instructions definition. If an exception // was generated during the instruction execution (for example #GP fault // because EIP was beyond CS segment limits) CPU state should restore the // state prior to instruction execution. // // The final point that we are not allowed to decrement ECX register before // it is known that no exceptions can happen. // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE32_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); if (i->as32L()) { Bit32u count = ECX; count--; if (count != 0 && (get_ZF()==0)) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif ECX = count; } else { Bit16u count = CX; count--; if (count != 0 && (get_ZF()==0)) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif CX = count; } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE32_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); if (i->as32L()) { Bit32u count = ECX; count--; if (count != 0 && get_ZF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif ECX = count; } else { Bit16u count = CX; count--; if (count != 0 && get_ZF()) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif CX = count; } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP32_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); if (i->as32L()) { Bit32u count = ECX; count--; if (count != 0) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif ECX = count; } else { Bit16u count = CX; count--; if (count != 0) { Bit32u new_EIP = EIP + (Bit32s) i->Id(); branch_near32(new_EIP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_EIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif CX = count; } BX_NEXT_TRACE(i); } #endif bochs-2.6/cpu/flag_ctrl.cc0000644000175000017500000002256712020641453015401 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: flag_ctrl.cc 10969 2012-01-11 20:21:29Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAHF(bxInstruction_c *i) { set_SF((AH & 0x80) >> 7); set_ZF((AH & 0x40) >> 6); set_AF((AH & 0x10) >> 4); set_CF (AH & 0x01); set_PF((AH & 0x04) >> 2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LAHF(bxInstruction_c *i) { AH = read_eflags() & 0xFF; BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLC(bxInstruction_c *i) { clear_CF(); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STC(bxInstruction_c *i) { assert_CF(); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLI(bxInstruction_c *i) { Bit32u IOPL = BX_CPU_THIS_PTR get_IOPL(); if (protected_mode()) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_PVI() && (CPL == 3)) { if (IOPL < 3) { BX_CPU_THIS_PTR clear_VIF(); BX_NEXT_INSTR(i); } } else #endif { if (IOPL < CPL) { BX_DEBUG(("CLI: IOPL < CPL in protected mode")); exception(BX_GP_EXCEPTION, 0); } } } else if (v8086_mode()) { if (IOPL != 3) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_VME()) { BX_CPU_THIS_PTR clear_VIF(); BX_NEXT_INSTR(i); } #endif BX_DEBUG(("CLI: IOPL != 3 in v8086 mode")); exception(BX_GP_EXCEPTION, 0); } } BX_CPU_THIS_PTR clear_IF(); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STI(bxInstruction_c *i) { Bit32u IOPL = BX_CPU_THIS_PTR get_IOPL(); if (protected_mode()) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_PVI()) { if (CPL == 3 && IOPL < 3) { if (! BX_CPU_THIS_PTR get_VIP()) { BX_CPU_THIS_PTR assert_VIF(); BX_NEXT_INSTR(i); } BX_DEBUG(("STI: #GP(0) in VME mode")); exception(BX_GP_EXCEPTION, 0); } } #endif if (CPL > IOPL) { BX_DEBUG(("STI: CPL > IOPL in protected mode")); exception(BX_GP_EXCEPTION, 0); } } else if (v8086_mode()) { if (IOPL != 3) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_VME() && BX_CPU_THIS_PTR get_VIP() == 0) { BX_CPU_THIS_PTR assert_VIF(); BX_NEXT_INSTR(i); } #endif BX_DEBUG(("STI: IOPL != 3 in v8086 mode")); exception(BX_GP_EXCEPTION, 0); } } if (! BX_CPU_THIS_PTR get_IF()) { BX_CPU_THIS_PTR assert_IF(); inhibit_interrupts(BX_INHIBIT_INTERRUPTS); BX_CPU_THIS_PTR async_event = 1; } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLD(bxInstruction_c *i) { BX_CPU_THIS_PTR clear_DF(); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STD(bxInstruction_c *i) { BX_CPU_THIS_PTR assert_DF(); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMC(bxInstruction_c *i) { set_CF(! get_CF()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fw(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF); } #endif Bit16u flags = (Bit16u) read_eflags(); if (v8086_mode()) { if (BX_CPU_THIS_PTR get_IOPL() < 3) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_VME()) { flags |= EFlagsIOPLMask; if (BX_CPU_THIS_PTR get_VIF()) flags |= EFlagsIFMask; else flags &= ~EFlagsIFMask; } else #endif { BX_DEBUG(("PUSHFW: #GP(0) in v8086 (no VME) mode")); exception(BX_GP_EXCEPTION, 0); } } } push_16(flags); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fw(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF); } #endif // Build a mask of the following bits: // x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask; RSP_SPECULATIVE; Bit16u flags16 = pop_16(); if (protected_mode()) { if (CPL==0) changeMask |= EFlagsIOPLMask; if (CPL <= BX_CPU_THIS_PTR get_IOPL()) changeMask |= EFlagsIFMask; } else if (v8086_mode()) { if (BX_CPU_THIS_PTR get_IOPL() < 3) { #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_VME()) { if (((flags16 & EFlagsIFMask) && BX_CPU_THIS_PTR get_VIP()) || (flags16 & EFlagsTFMask)) { BX_ERROR(("POPFW: #GP(0) in VME mode")); exception(BX_GP_EXCEPTION, 0); } // IF, IOPL unchanged, EFLAGS.VIF = TMP_FLAGS.IF changeMask |= EFlagsVIFMask; Bit32u flags32 = (Bit32u) flags16; if (flags32 & EFlagsIFMask) flags32 |= EFlagsVIFMask; writeEFlags(flags32, changeMask); RSP_COMMIT; BX_NEXT_INSTR(i); } #endif BX_DEBUG(("POPFW: #GP(0) in v8086 (no VME) mode")); exception(BX_GP_EXCEPTION, 0); } changeMask |= EFlagsIFMask; } else { // All non-reserved flags can be modified changeMask |= (EFlagsIOPLMask | EFlagsIFMask); } writeEFlags((Bit32u) flags16, changeMask); RSP_COMMIT; BX_NEXT_INSTR(i); } #if BX_CPU_LEVEL >= 3 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fd(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF); } #endif if (v8086_mode() && (BX_CPU_THIS_PTR get_IOPL()<3)) { BX_DEBUG(("PUSHFD: #GP(0) in v8086 mode")); exception(BX_GP_EXCEPTION, 0); } // VM & RF flags cleared in image stored on the stack push_32(read_eflags() & 0x00fcffff); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fd(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF); } #endif // Build a mask of the following bits: // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask | EFlagsRFMask; #if BX_CPU_LEVEL >= 4 changeMask |= (EFlagsIDMask | EFlagsACMask); // ID/AC #endif RSP_SPECULATIVE; Bit32u flags32 = pop_32(); if (protected_mode()) { // IOPL changed only if (CPL == 0), // IF changed only if (CPL <= EFLAGS.IOPL), // VIF, VIP, VM are unaffected if (CPL==0) changeMask |= EFlagsIOPLMask; if (CPL <= BX_CPU_THIS_PTR get_IOPL()) changeMask |= EFlagsIFMask; } else if (v8086_mode()) { if (BX_CPU_THIS_PTR get_IOPL() < 3) { BX_ERROR(("POPFD: #GP(0) in v8086 mode")); exception(BX_GP_EXCEPTION, 0); } // v8086-mode: VM, IOPL, VIP, VIF are unaffected changeMask |= EFlagsIFMask; } else { // Real-mode // VIF, VIP, VM are unaffected changeMask |= (EFlagsIOPLMask | EFlagsIFMask); } writeEFlags(flags32, changeMask); RSP_COMMIT; BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fq(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF); } #endif // VM & RF flags cleared in image stored on the stack push_64(read_eflags() & 0x00fcffff); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fq(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF); } #endif // Build a mask of the following bits: // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask | EFlagsRFMask | EFlagsACMask | EFlagsIDMask; BX_ASSERT (protected_mode()); Bit32u eflags32 = (Bit32u) pop_64(); if (CPL==0) changeMask |= EFlagsIOPLMask; if (CPL <= BX_CPU_THIS_PTR get_IOPL()) changeMask |= EFlagsIFMask; // VIF, VIP, VM are unaffected writeEFlags(eflags32, changeMask); BX_NEXT_INSTR(i); } #endif #endif // BX_CPU_LEVEL >= 3 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SALC(bxInstruction_c *i) { if (get_CF()) { AL = 0xff; } else { AL = 0x00; } BX_NEXT_INSTR(i); } bochs-2.6/cpu/bit64.cc0000644000175000017500000002400012020641453014354 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bit64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSF_GqEqR(bxInstruction_c *i) { Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); if (op2_64 == 0) { assert_ZF(); /* op1_64 undefined */ } else { Bit64u op1_64 = 0; while ((op2_64 & 0x01) == 0) { op1_64++; op2_64 >>= 1; } SET_FLAGS_OSZAPC_LOGIC_64(op1_64); clear_ZF(); BX_WRITE_64BIT_REG(i->dst(), op1_64); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSR_GqEqR(bxInstruction_c *i) { Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); if (op2_64 == 0) { assert_ZF(); /* op1_64 undefined */ } else { Bit64u op1_64 = 63; while ((op2_64 & BX_CONST64(0x8000000000000000)) == 0) { op1_64--; op2_64 <<= 1; } SET_FLAGS_OSZAPC_LOGIC_64(op1_64); clear_ZF(); BX_WRITE_64BIT_REG(i->dst(), op1_64); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EqGqM(bxInstruction_c *i) { bx_address op1_addr; Bit64u op1_64, op2_64; Bit64s displacement64; Bit64u index; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_64 = BX_READ_64BIT_REG(i->src()); index = op2_64 & 0x3f; displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64; op1_addr = eaddr + 8 * displacement64; if (! i->as64L()) op1_addr = (Bit32u) op1_addr; /* pointer, segment address pair */ op1_64 = read_virtual_qword_64(i->seg(), op1_addr); set_CF((op1_64 >> index) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op2_64 &= 0x3f; set_CF((op1_64 >> op2_64) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EqGqM(bxInstruction_c *i) { bx_address op1_addr; Bit64u op1_64, op2_64, index; Bit64s displacement64; bx_bool bit_i; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_64 = BX_READ_64BIT_REG(i->src()); index = op2_64 & 0x3f; displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64; op1_addr = eaddr + 8 * displacement64; if (! i->as64L()) op1_addr = (Bit32u) op1_addr; /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), op1_addr); bit_i = (op1_64 >> index) & 0x01; op1_64 |= (((Bit64u) 1) << index); write_RMW_virtual_qword(op1_64); set_CF(bit_i); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op2_64 &= 0x3f; set_CF((op1_64 >> op2_64) & 0x01); op1_64 |= (((Bit64u) 1) << op2_64); /* now write result back to the destination */ BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EqGqM(bxInstruction_c *i) { bx_address op1_addr; Bit64u op1_64, op2_64, index; Bit64s displacement64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_64 = BX_READ_64BIT_REG(i->src()); index = op2_64 & 0x3f; displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64; op1_addr = eaddr + 8 * displacement64; if (! i->as64L()) op1_addr = (Bit32u) op1_addr; /* pointer, segment address pair */ op1_64 = read_RMW_virtual_qword_64(i->seg(), op1_addr); bx_bool temp_cf = (op1_64 >> index) & 0x01; op1_64 &= ~(((Bit64u) 1) << index); /* now write back to destination */ write_RMW_virtual_qword(op1_64); set_CF(temp_cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op2_64 &= 0x3f; set_CF((op1_64 >> op2_64) & 0x01); op1_64 &= ~(((Bit64u) 1) << op2_64); /* now write result back to the destination */ BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EqGqM(bxInstruction_c *i) { bx_address op1_addr; Bit64u op1_64, op2_64; Bit64s displacement64; Bit64u index; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_64 = BX_READ_64BIT_REG(i->src()); index = op2_64 & 0x3f; displacement64 = ((Bit64s) (op2_64 & BX_CONST64(0xffffffffffffffc0))) / 64; op1_addr = eaddr + 8 * displacement64; if (! i->as64L()) op1_addr = (Bit32u) op1_addr; op1_64 = read_RMW_virtual_qword_64(i->seg(), op1_addr); bx_bool temp_CF = (op1_64 >> index) & 0x01; op1_64 ^= (((Bit64u) 1) << index); /* toggle bit */ set_CF(temp_CF); write_RMW_virtual_qword(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op2_64 &= 0x3f; bx_bool temp_CF = (op1_64 >> op2_64) & 0x01; op1_64 ^= (((Bit64u) 1) << op2_64); /* toggle bit */ set_CF(temp_CF); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EqIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_virtual_qword_64(i->seg(), eaddr); Bit8u op2_8 = i->Ib() & 0x3f; set_CF((op1_64 >> op2_8) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EqIbR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); Bit8u op2_8 = i->Ib() & 0x3f; set_CF((op1_64 >> op2_8) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EqIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x3f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); bx_bool temp_CF = (op1_64 >> op2_8) & 0x01; op1_64 |= (((Bit64u) 1) << op2_8); write_RMW_virtual_qword(op1_64); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EqIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x3f; Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); bx_bool temp_CF = (op1_64 >> op2_8) & 0x01; op1_64 |= (((Bit64u) 1) << op2_8); BX_WRITE_64BIT_REG(i->dst(), op1_64); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EqIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x3f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); bx_bool temp_CF = (op1_64 >> op2_8) & 0x01; op1_64 ^= (((Bit64u) 1) << op2_8); /* toggle bit */ write_RMW_virtual_qword(op1_64); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EqIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x3f; Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); bx_bool temp_CF = (op1_64 >> op2_8) & 0x01; op1_64 ^= (((Bit64u) 1) << op2_8); /* toggle bit */ BX_WRITE_64BIT_REG(i->dst(), op1_64); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EqIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x3f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); bx_bool temp_CF = (op1_64 >> op2_8) & 0x01; op1_64 &= ~(((Bit64u) 1) << op2_8); write_RMW_virtual_qword(op1_64); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EqIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x3f; Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); bx_bool temp_CF = (op1_64 >> op2_8) & 0x01; op1_64 &= ~(((Bit64u) 1) << op2_8); BX_WRITE_64BIT_REG(i->dst(), op1_64); set_CF(temp_CF); BX_NEXT_INSTR(i); } /* F3 0F B8 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPCNT_GqEqR(bxInstruction_c *i) { Bit64u op2_64 = BX_READ_64BIT_REG(i->src()); Bit64u op1_64 = 0; while (op2_64 != 0) { if (op2_64 & 1) op1_64++; op2_64 >>= 1; } Bit32u flags = op1_64 ? 0 : EFlagsZFMask; setEFlagsOSZAPC(flags); BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } /* F3 0F BC */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TZCNT_GqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src()); Bit64u mask = 0x1, result_64 = 0; while ((op1_64 & mask) == 0 && mask) { mask <<= 1; result_64++; } set_CF(! op1_64); set_ZF(! result_64); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } /* F3 0F BD */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LZCNT_GqEqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->src()), result_64 = 0; Bit64u mask = BX_CONST64(0x8000000000000000); while ((op1_64 & mask) == 0 && mask) { mask >>= 1; result_64++; } set_CF(! op1_64); set_ZF(! result_64); BX_WRITE_64BIT_REG(i->dst(), result_64); BX_NEXT_INSTR(i); } #endif // BX_SUPPORT_X86_64 bochs-2.6/cpu/smm.h0000644000175000017500000001623512020641453014075 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: smm.h 11301 2012-07-27 08:13:39Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2006-2009 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_SMM_H #define BX_SMM_H /* SMM feature masks */ #define SMM_IO_INSTRUCTION_RESTART (0x00010000) #define SMM_SMBASE_RELOCATION (0x00020000) #define SMM_SAVE_STATE_MAP_SIZE 128 // // - For x86-64 configuration using AMD Athlon 64 512-byte SMM save state map // revision ID according to QEMU/Bochs BIOS // // - For x86-32 configuration using Intel P6 512-byte SMM save state map // #define SMM_REVISION_ID \ ((BX_SUPPORT_X86_64 ? 0x00000064 : 0) | SMM_SMBASE_RELOCATION) // // Some of the CPU field must be saved and restored in order to continue the // simulation correctly after the RSM instruction: // // --------------------------------------------------------------- // // 1. General purpose registers: EAX-EDI, R8-R15 // 2. EIP, RFLAGS // 3. Segment registers CS, DS, SS, ES, FS, GS // fields: valid - not required, initialized according to selector value // p - must be saved/restored // dpl - must be saved/restored // segment - must be 1 for seg registers, not required to save // type - must be saved/restored // base - must be saved/restored // limit - must be saved/restored // g - must be saved/restored // d_b - must be saved/restored // l - must be saved/restored // avl - must be saved/restored // 4. GDTR, IDTR // fields: base, limit // 5. LDTR, TR // fields: base, limit, anything else ? // 6. Debug Registers DR0-DR7, only DR6 and DR7 are saved // 7. Control Registers: CR0, CR2 is NOT saved, CR3, CR4, EFER // 8. SMBASE // 9. MSR/FPU/XMM/APIC are NOT saved accoring to Intel docs // struct BX_SMM_State { Bit32u smbase; Bit32u smm_revision_id; bx_address gen_reg[BX_GENERAL_REGISTERS]; bx_address rip; Bit32u eflags; Bit32u dr6; Bit32u dr7; bx_cr0_t cr0; bx_address cr3; #if BX_CPU_LEVEL >= 5 bx_cr4_t cr4; bx_efer_t efer; #endif Bit32u io_insruction_restart; Bit32u autohalt_restart; Bit32u nmi_mask; bx_global_segment_reg_t gdtr; bx_global_segment_reg_t idtr; struct { bx_address base; Bit32u limit; Bit32u selector_ar; } segreg[6], tr, ldtr; }; #if BX_SUPPORT_X86_64 enum SMMRAM_Fields { SMRAM_FIELD_SMBASE_OFFSET = 0, SMRAM_FIELD_SMM_REVISION_ID, SMRAM_FIELD_RAX_HI32, SMRAM_FIELD_EAX, SMRAM_FIELD_RCX_HI32, SMRAM_FIELD_ECX, SMRAM_FIELD_RDX_HI32, SMRAM_FIELD_EDX, SMRAM_FIELD_RBX_HI32, SMRAM_FIELD_EBX, SMRAM_FIELD_RSP_HI32, SMRAM_FIELD_ESP, SMRAM_FIELD_RBP_HI32, SMRAM_FIELD_EBP, SMRAM_FIELD_RSI_HI32, SMRAM_FIELD_ESI, SMRAM_FIELD_RDI_HI32, SMRAM_FIELD_EDI, SMRAM_FIELD_R8_HI32, SMRAM_FIELD_R8, SMRAM_FIELD_R9_HI32, SMRAM_FIELD_R9, SMRAM_FIELD_R10_HI32, SMRAM_FIELD_R10, SMRAM_FIELD_R11_HI32, SMRAM_FIELD_R11, SMRAM_FIELD_R12_HI32, SMRAM_FIELD_R12, SMRAM_FIELD_R13_HI32, SMRAM_FIELD_R13, SMRAM_FIELD_R14_HI32, SMRAM_FIELD_R14, SMRAM_FIELD_R15_HI32, SMRAM_FIELD_R15, SMRAM_FIELD_RIP_HI32, SMRAM_FIELD_EIP, SMRAM_FIELD_RFLAGS_HI32, // always zero SMRAM_FIELD_EFLAGS, SMRAM_FIELD_DR6_HI32, // always zero SMRAM_FIELD_DR6, SMRAM_FIELD_DR7_HI32, // always zero SMRAM_FIELD_DR7, SMRAM_FIELD_CR0_HI32, // always zero SMRAM_FIELD_CR0, SMRAM_FIELD_CR3_HI32, // zero when physical address size 32-bit SMRAM_FIELD_CR3, SMRAM_FIELD_CR4_HI32, // always zero SMRAM_FIELD_CR4, SMRAM_FIELD_EFER_HI32, // always zero SMRAM_FIELD_EFER, SMRAM_FIELD_IO_INSTRUCTION_RESTART, SMRAM_FIELD_AUTOHALT_RESTART, SMRAM_FIELD_NMI_MASK, SMRAM_FIELD_TR_BASE_HI32, SMRAM_FIELD_TR_BASE, SMRAM_FIELD_TR_LIMIT, SMRAM_FIELD_TR_SELECTOR_AR, SMRAM_FIELD_LDTR_BASE_HI32, SMRAM_FIELD_LDTR_BASE, SMRAM_FIELD_LDTR_LIMIT, SMRAM_FIELD_LDTR_SELECTOR_AR, SMRAM_FIELD_IDTR_BASE_HI32, SMRAM_FIELD_IDTR_BASE, SMRAM_FIELD_IDTR_LIMIT, SMRAM_FIELD_GDTR_BASE_HI32, SMRAM_FIELD_GDTR_BASE, SMRAM_FIELD_GDTR_LIMIT, SMRAM_FIELD_ES_BASE_HI32, SMRAM_FIELD_ES_BASE, SMRAM_FIELD_ES_LIMIT, SMRAM_FIELD_ES_SELECTOR_AR, SMRAM_FIELD_CS_BASE_HI32, SMRAM_FIELD_CS_BASE, SMRAM_FIELD_CS_LIMIT, SMRAM_FIELD_CS_SELECTOR_AR, SMRAM_FIELD_SS_BASE_HI32, SMRAM_FIELD_SS_BASE, SMRAM_FIELD_SS_LIMIT, SMRAM_FIELD_SS_SELECTOR_AR, SMRAM_FIELD_DS_BASE_HI32, SMRAM_FIELD_DS_BASE, SMRAM_FIELD_DS_LIMIT, SMRAM_FIELD_DS_SELECTOR_AR, SMRAM_FIELD_FS_BASE_HI32, SMRAM_FIELD_FS_BASE, SMRAM_FIELD_FS_LIMIT, SMRAM_FIELD_FS_SELECTOR_AR, SMRAM_FIELD_GS_BASE_HI32, SMRAM_FIELD_GS_BASE, SMRAM_FIELD_GS_LIMIT, SMRAM_FIELD_GS_SELECTOR_AR, SMRAM_FIELD_LAST }; #else enum SMMRAM_Fields { SMRAM_FIELD_SMBASE_OFFSET = 0, SMRAM_FIELD_SMM_REVISION_ID, SMRAM_FIELD_EAX, SMRAM_FIELD_ECX, SMRAM_FIELD_EDX, SMRAM_FIELD_EBX, SMRAM_FIELD_ESP, SMRAM_FIELD_EBP, SMRAM_FIELD_ESI, SMRAM_FIELD_EDI, SMRAM_FIELD_EIP, SMRAM_FIELD_EFLAGS, SMRAM_FIELD_DR6, SMRAM_FIELD_DR7, SMRAM_FIELD_CR0, SMRAM_FIELD_CR3, SMRAM_FIELD_CR4, SMRAM_FIELD_EFER, SMRAM_FIELD_IO_INSTRUCTION_RESTART, SMRAM_FIELD_AUTOHALT_RESTART, SMRAM_FIELD_NMI_MASK, SMRAM_FIELD_TR_SELECTOR, SMRAM_FIELD_TR_BASE, SMRAM_FIELD_TR_LIMIT, SMRAM_FIELD_TR_SELECTOR_AR, SMRAM_FIELD_LDTR_SELECTOR, SMRAM_FIELD_LDTR_BASE, SMRAM_FIELD_LDTR_LIMIT, SMRAM_FIELD_LDTR_SELECTOR_AR, SMRAM_FIELD_IDTR_BASE, SMRAM_FIELD_IDTR_LIMIT, SMRAM_FIELD_GDTR_BASE, SMRAM_FIELD_GDTR_LIMIT, SMRAM_FIELD_ES_SELECTOR, SMRAM_FIELD_ES_BASE, SMRAM_FIELD_ES_LIMIT, SMRAM_FIELD_ES_SELECTOR_AR, SMRAM_FIELD_CS_SELECTOR, SMRAM_FIELD_CS_BASE, SMRAM_FIELD_CS_LIMIT, SMRAM_FIELD_CS_SELECTOR_AR, SMRAM_FIELD_SS_SELECTOR, SMRAM_FIELD_SS_BASE, SMRAM_FIELD_SS_LIMIT, SMRAM_FIELD_SS_SELECTOR_AR, SMRAM_FIELD_DS_SELECTOR, SMRAM_FIELD_DS_BASE, SMRAM_FIELD_DS_LIMIT, SMRAM_FIELD_DS_SELECTOR_AR, SMRAM_FIELD_FS_SELECTOR, SMRAM_FIELD_FS_BASE, SMRAM_FIELD_FS_LIMIT, SMRAM_FIELD_FS_SELECTOR_AR, SMRAM_FIELD_GS_SELECTOR, SMRAM_FIELD_GS_BASE, SMRAM_FIELD_GS_LIMIT, SMRAM_FIELD_GS_SELECTOR_AR, SMRAM_FIELD_LAST }; #endif // BX_SUPPORT_X86_64 #endif bochs-2.6/cpu/vmx.cc0000644000175000017500000033427712020641453014262 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmx.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2009-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #include "iodev/iodev.h" #if BX_SUPPORT_VMX #define VMCSPTR_VALID() (BX_CPU_THIS_PTR vmcsptr != BX_INVALID_VMCSPTR) extern unsigned vmcs_field_offset(Bit32u encoding); #if BX_SUPPORT_VMX >= 2 extern bx_bool isValidMSR_PAT(Bit64u pat_msr); #endif //////////////////////////////////////////////////////////// // VMCS access //////////////////////////////////////////////////////////// void BX_CPU_C::set_VMCSPTR(Bit64u vmxptr) { BX_CPU_THIS_PTR vmcsptr = vmxptr; if (vmxptr != BX_INVALID_VMCSPTR) BX_CPU_THIS_PTR vmcshostptr = BX_CPU_THIS_PTR getHostMemAddr(vmxptr, BX_WRITE); else BX_CPU_THIS_PTR vmcshostptr = 0; } Bit16u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread16(unsigned encoding) { Bit16u field; unsigned offset = vmcs_field_offset(encoding); if(offset >= VMX_VMCS_AREA_SIZE) BX_PANIC(("VMread16: can't access encoding 0x%08x, offset=0x%x", encoding, offset)); bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset; BX_ASSERT(VMCS_FIELD_WIDTH(encoding) == VMCS_FIELD_WIDTH_16BIT); if (BX_CPU_THIS_PTR vmcshostptr) { Bit16u *hostAddr = (Bit16u*) (BX_CPU_THIS_PTR vmcshostptr | offset); ReadHostWordFromLittleEndian(hostAddr, field); } else { access_read_physical(pAddr, 2, (Bit8u*)(&field)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 2, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&field)); return field; } // write 16-bit value into VMCS 16-bit field void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite16(unsigned encoding, Bit16u val_16) { unsigned offset = vmcs_field_offset(encoding); if(offset >= VMX_VMCS_AREA_SIZE) BX_PANIC(("VMwrite16: can't access encoding 0x%08x, offset=0x%x", encoding, offset)); bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset; BX_ASSERT(VMCS_FIELD_WIDTH(encoding) == VMCS_FIELD_WIDTH_16BIT); if (BX_CPU_THIS_PTR vmcshostptr) { Bit16u *hostAddr = (Bit16u*) (BX_CPU_THIS_PTR vmcshostptr | offset); pageWriteStampTable.decWriteStamp(pAddr, 2); WriteHostWordToLittleEndian(hostAddr, val_16); } else { access_write_physical(pAddr, 2, (Bit8u*)(&val_16)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 2, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&val_16)); } Bit32u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread32(unsigned encoding) { Bit32u field; unsigned offset = vmcs_field_offset(encoding); if(offset >= VMX_VMCS_AREA_SIZE) BX_PANIC(("VMread32: can't access encoding 0x%08x, offset=0x%x", encoding, offset)); bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset; if (BX_CPU_THIS_PTR vmcshostptr) { Bit32u *hostAddr = (Bit32u*) (BX_CPU_THIS_PTR vmcshostptr | offset); ReadHostDWordFromLittleEndian(hostAddr, field); } else { access_read_physical(pAddr, 4, (Bit8u*)(&field)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&field)); return field; } // write 32-bit value into VMCS field void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite32(unsigned encoding, Bit32u val_32) { unsigned offset = vmcs_field_offset(encoding); if(offset >= VMX_VMCS_AREA_SIZE) BX_PANIC(("VMwrite32: can't access encoding 0x%08x, offset=0x%x", encoding, offset)); bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset; if (BX_CPU_THIS_PTR vmcshostptr) { Bit32u *hostAddr = (Bit32u*) (BX_CPU_THIS_PTR vmcshostptr | offset); pageWriteStampTable.decWriteStamp(pAddr, 4); WriteHostDWordToLittleEndian(hostAddr, val_32); } else { access_write_physical(pAddr, 4, (Bit8u*)(&val_32)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&val_32)); } Bit64u BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread64(unsigned encoding) { BX_ASSERT(!IS_VMCS_FIELD_HI(encoding)); Bit64u field; unsigned offset = vmcs_field_offset(encoding); if(offset >= VMX_VMCS_AREA_SIZE) BX_PANIC(("VMread64: can't access encoding 0x%08x, offset=0x%x", encoding, offset)); bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset; if (BX_CPU_THIS_PTR vmcshostptr) { Bit64u *hostAddr = (Bit64u*) (BX_CPU_THIS_PTR vmcshostptr | offset); ReadHostQWordFromLittleEndian(hostAddr, field); } else { access_read_physical(pAddr, 8, (Bit8u*)(&field)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 8, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&field)); return field; } // write 64-bit value into VMCS field void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite64(unsigned encoding, Bit64u val_64) { BX_ASSERT(!IS_VMCS_FIELD_HI(encoding)); unsigned offset = vmcs_field_offset(encoding); if(offset >= VMX_VMCS_AREA_SIZE) BX_PANIC(("VMwrite64: can't access encoding 0x%08x, offset=0x%x", encoding, offset)); bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + offset; if (BX_CPU_THIS_PTR vmcshostptr) { Bit64u *hostAddr = (Bit64u*) (BX_CPU_THIS_PTR vmcshostptr | offset); pageWriteStampTable.decWriteStamp(pAddr, 8); WriteHostQWordToLittleEndian(hostAddr, val_64); } else { access_write_physical(pAddr, 8, (Bit8u*)(&val_64)); } BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 8, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&val_64)); } #if BX_SUPPORT_X86_64 BX_CPP_INLINE bx_address BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread_natural(unsigned encoding) { return VMread64(encoding); } void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite_natural(unsigned encoding, bx_address val) { VMwrite64(encoding, val); } #else BX_CPP_INLINE bx_address BX_CPP_AttrRegparmN(1) BX_CPU_C::VMread_natural(unsigned encoding) { return VMread32(encoding); } void BX_CPP_AttrRegparmN(2) BX_CPU_C::VMwrite_natural(unsigned encoding, bx_address val) { VMwrite32(encoding, val); } #endif //////////////////////////////////////////////////////////// // VMfail/VMsucceed //////////////////////////////////////////////////////////// BX_CPP_INLINE void BX_CPU_C::VMsucceed(void) { setEFlagsOSZAPC(0); } BX_CPP_INLINE void BX_CPU_C::VMfailInvalid(void) { setEFlagsOSZAPC(EFlagsCFMask); } BX_CPP_INLINE void BX_CPU_C::VMfail(Bit32u error_code) { if (VMCSPTR_VALID()) { // executed only if there is a current VMCS setEFlagsOSZAPC(EFlagsZFMask); VMwrite32(VMCS_32BIT_INSTRUCTION_ERROR, error_code); } else { setEFlagsOSZAPC(EFlagsCFMask); } } void BX_CPU_C::VMabort(VMX_vmabort_code error_code) { Bit32u abort = error_code; bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + VMCS_VMX_ABORT_FIELD_ADDR; access_write_physical(pAddr, 4, &abort); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&abort)); #if BX_SUPPORT_VMX >= 2 // Deactivate VMX preemtion timer BX_CPU_THIS_PTR lapic.deactivate_vmx_preemption_timer(); #endif shutdown(); } unsigned BX_CPU_C::VMXReadRevisionID(bx_phy_address pAddr) { Bit32u revision; access_read_physical(pAddr + VMCS_REVISION_ID_FIELD_ADDR, 4, &revision); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr + VMCS_REVISION_ID_FIELD_ADDR, 4, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&revision)); return revision; } #if BX_SUPPORT_VMX >= 2 bx_bool BX_CPU_C::is_eptptr_valid(Bit64u eptptr) { // [2:0] EPT paging-structure memory type // 0 = Uncacheable (UC) // 6 = Write-back (WB) Bit32u memtype = eptptr & 7; if (memtype != BX_MEMTYPE_UC && memtype != BX_MEMTYPE_WB) return 0; // [5:3] This value is 1 less than the EPT page-walk length Bit32u walk_length = (eptptr >> 3) & 7; if (walk_length != 3) return 0; if (! BX_SUPPORT_VMX_EXTENSION(BX_VMX_EPT_ACCESS_DIRTY)) { if (eptptr & 0x40) { BX_ERROR(("is_eptptr_valid: EPTPTR A/D enabled when not supported by CPU")); return 0; } } #define BX_EPTPTR_RESERVED_BITS 0xf80 /* bits 11:5 are reserved */ if (eptptr & BX_EPTPTR_RESERVED_BITS) { BX_ERROR(("is_eptptr_valid: EPTPTR reserved bits set")); return 0; } if (! IsValidPhyAddr(eptptr)) return 0; return 1; } #endif //////////////////////////////////////////////////////////// // VMenter //////////////////////////////////////////////////////////// extern struct BxExceptionInfo exceptions_info[]; #define VMENTRY_INJECTING_EVENT(vmentry_interr_info) (vmentry_interr_info & 0x80000000) #define VMX_CHECKS_USE_MSR_VMX_PINBASED_CTRLS_LO \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_PINBASED_CTRLS_LO : VMX_MSR_VMX_PINBASED_CTRLS_LO) #define VMX_CHECKS_USE_MSR_VMX_PINBASED_CTRLS_HI \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_PINBASED_CTRLS_HI : VMX_MSR_VMX_PINBASED_CTRLS_HI) #define VMX_CHECKS_USE_MSR_VMX_PROCBASED_CTRLS_LO \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_PROCBASED_CTRLS_LO : VMX_MSR_VMX_PROCBASED_CTRLS_LO) #define VMX_CHECKS_USE_MSR_VMX_PROCBASED_CTRLS_HI \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_PROCBASED_CTRLS_HI : VMX_MSR_VMX_PROCBASED_CTRLS_HI) #define VMX_CHECKS_USE_MSR_VMX_VMEXIT_CTRLS_LO \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_VMEXIT_CTRLS_LO : VMX_MSR_VMX_VMEXIT_CTRLS_LO) #define VMX_CHECKS_USE_MSR_VMX_VMEXIT_CTRLS_HI \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_VMEXIT_CTRLS_HI : VMX_MSR_VMX_VMEXIT_CTRLS_HI) #define VMX_CHECKS_USE_MSR_VMX_VMENTRY_CTRLS_LO \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_VMENTRY_CTRLS_LO : VMX_MSR_VMX_VMENTRY_CTRLS_LO) #define VMX_CHECKS_USE_MSR_VMX_VMENTRY_CTRLS_HI \ ((BX_SUPPORT_VMX >= 2) ? VMX_MSR_VMX_TRUE_VMENTRY_CTRLS_HI : VMX_MSR_VMX_VMENTRY_CTRLS_HI) VMX_error_code BX_CPU_C::VMenterLoadCheckVmControls(void) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; // // Load VM-execution control fields to VMCS Cache // vm->vmexec_ctrls1 = VMread32(VMCS_32BIT_CONTROL_PIN_BASED_EXEC_CONTROLS); vm->vmexec_ctrls2 = VMread32(VMCS_32BIT_CONTROL_PROCESSOR_BASED_VMEXEC_CONTROLS); if (VMEXIT(VMX_VM_EXEC_CTRL2_SECONDARY_CONTROLS)) vm->vmexec_ctrls3 = VMread32(VMCS_32BIT_CONTROL_SECONDARY_VMEXEC_CONTROLS); else vm->vmexec_ctrls3 = 0; vm->vm_exceptions_bitmap = VMread32(VMCS_32BIT_CONTROL_EXECUTION_BITMAP); vm->vm_pf_mask = VMread32(VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MASK); vm->vm_pf_match = VMread32(VMCS_32BIT_CONTROL_PAGE_FAULT_ERR_CODE_MATCH); vm->vm_cr0_mask = VMread_natural(VMCS_CONTROL_CR0_GUEST_HOST_MASK); vm->vm_cr4_mask = VMread_natural(VMCS_CONTROL_CR4_GUEST_HOST_MASK); vm->vm_cr0_read_shadow = VMread_natural(VMCS_CONTROL_CR0_READ_SHADOW); vm->vm_cr4_read_shadow = VMread_natural(VMCS_CONTROL_CR4_READ_SHADOW); vm->vm_cr3_target_cnt = VMread32(VMCS_32BIT_CONTROL_CR3_TARGET_COUNT); for (int n=0; nvm_cr3_target_value[n] = VMread_natural(VMCS_CR3_TARGET0 + 2*n); vm->executive_vmcsptr = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_EXECUTIVE_VMCS_PTR); // // Check VM-execution control fields // if (~vm->vmexec_ctrls1 & VMX_CHECKS_USE_MSR_VMX_PINBASED_CTRLS_LO) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX pin-based controls allowed 0-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmexec_ctrls1 & ~VMX_CHECKS_USE_MSR_VMX_PINBASED_CTRLS_HI) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX pin-based controls allowed 1-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (~vm->vmexec_ctrls2 & VMX_CHECKS_USE_MSR_VMX_PROCBASED_CTRLS_LO) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX proc-based controls allowed 0-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmexec_ctrls2 & ~VMX_CHECKS_USE_MSR_VMX_PROCBASED_CTRLS_HI) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX proc-based controls allowed 1-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (~vm->vmexec_ctrls3 & VMX_MSR_VMX_PROCBASED_CTRLS2_LO) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX secondary proc-based controls allowed 0-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmexec_ctrls3 & ~VMX_MSR_VMX_PROCBASED_CTRLS2_HI) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX secondary proc-based controls allowed 1-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vm_cr3_target_cnt > VMX_CR3_TARGET_MAX_CNT) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: too may CR3 targets %d", vm->vm_cr3_target_cnt)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_IO_BITMAPS) { vm->io_bitmap_addr[0] = VMread64(VMCS_64BIT_CONTROL_IO_BITMAP_A); vm->io_bitmap_addr[1] = VMread64(VMCS_64BIT_CONTROL_IO_BITMAP_B); // I/O bitmaps control enabled for (int bitmap=0; bitmap < 2; bitmap++) { if (vm->io_bitmap_addr[bitmap] & 0xfff) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: I/O bitmap %c must be 4K aligned", 'A' + bitmap)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (! IsValidPhyAddr(vm->io_bitmap_addr[bitmap])) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: I/O bitmap %c phy addr malformed", 'A' + bitmap)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } } if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_MSR_BITMAPS) { // MSR bitmaps control enabled vm->msr_bitmap_addr = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_MSR_BITMAPS); if ((vm->msr_bitmap_addr & 0xfff) != 0 || ! IsValidPhyAddr(vm->msr_bitmap_addr)) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: MSR bitmap phy addr malformed")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } if (! (vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_VIRTUAL_NMI)) { if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: misconfigured virtual NMI control")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } #if BX_SUPPORT_X86_64 if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_TPR_SHADOW) { vm->virtual_apic_page_addr = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_VIRTUAL_APIC_PAGE_ADDR); vm->vm_tpr_threshold = VMread32(VMCS_32BIT_CONTROL_TPR_THRESHOLD); if ((vm->virtual_apic_page_addr & 0xfff) != 0 || ! IsValidPhyAddr(vm->virtual_apic_page_addr)) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: virtual apic phy addr malformed")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vm_tpr_threshold & 0xfffffff0) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: TPR threshold too big")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (! (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)) { Bit8u tpr_shadow = (VMX_Read_VTPR() >> 4) & 0xf; if (vm->vm_tpr_threshold > tpr_shadow) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: TPR threshold > TPR shadow")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } } if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES) { vm->apic_access_page = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_APIC_ACCESS_ADDR); if ((vm->apic_access_page & 0xfff) != 0 || ! IsValidPhyAddr(vm->apic_access_page)) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: apic access page phy addr malformed")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } #endif #if BX_SUPPORT_VMX >= 2 if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_X2APIC_MODE) { // 'use TPR shadow' must be set and "virtualize APIC accesses" must be clear if (!(vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_TPR_SHADOW) || (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES)) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: virtualize X2APIC mode misconfigured")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_EPT_ENABLE) { vm->eptptr = (bx_phy_address) VMread64(VMCS_64BIT_CONTROL_EPTPTR); if (! is_eptptr_valid(vm->eptptr)) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: invalid EPTPTR value")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } else { if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: unrestricted guest without EPT")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VPID_ENABLE) { vm->vpid = VMread16(VMCS_16BIT_CONTROL_VPID); if (vm->vpid == 0) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: guest VPID == 0")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_PAUSE_LOOP_VMEXIT) { vm->pause_loop_exiting_gap = VMread32(VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_GAP); vm->pause_loop_exiting_window = VMread32(VMCS_32BIT_CONTROL_PAUSE_LOOP_EXITING_WINDOW); } if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_VMFUNC_ENABLE) vm->vmfunc_ctrls = VMread64(VMCS_64BIT_CONTROL_VMFUNC_CTRLS); else vm->vmfunc_ctrls = 0; if (vm->vmfunc_ctrls & ~VMX_VMFUNC_CTRL1_SUPPORTED_BITS) { BX_ERROR(("VMFAIL: VMCS VM Functions control reserved bits set")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmfunc_ctrls & VMX_VMFUNC_EPTP_SWITCHING_MASK) { if ((vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_EPT_ENABLE) == 0) { BX_ERROR(("VMFAIL: VMFUNC EPTP-SWITCHING: EPT disabled")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } vm->eptp_list_address = VMread64(VMCS_64BIT_CONTROL_EPTP_LIST_ADDRESS); if ((vm->eptp_list_address & 0xfff) != 0 || ! IsValidPhyAddr(vm->eptp_list_address)) { BX_ERROR(("VMFAIL: VMFUNC EPTP-SWITCHING: eptp list phy addr malformed")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } #endif // // Load VM-exit control fields to VMCS Cache // vm->vmexit_ctrls = VMread32(VMCS_32BIT_CONTROL_VMEXIT_CONTROLS); vm->vmexit_msr_store_cnt = VMread32(VMCS_32BIT_CONTROL_VMEXIT_MSR_STORE_COUNT); vm->vmexit_msr_load_cnt = VMread32(VMCS_32BIT_CONTROL_VMEXIT_MSR_LOAD_COUNT); // // Check VM-exit control fields // if (~vm->vmexit_ctrls & VMX_CHECKS_USE_MSR_VMX_VMEXIT_CTRLS_LO) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX vmexit controls allowed 0-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmexit_ctrls & ~VMX_CHECKS_USE_MSR_VMX_VMEXIT_CTRLS_HI) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX vmexit controls allowed 1-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } #if BX_SUPPORT_VMX >= 2 if ((~vm->vmexec_ctrls1 & VMX_VM_EXEC_CTRL1_VMX_PREEMPTION_TIMER_VMEXIT) && (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_STORE_VMX_PREEMPTION_TIMER)) { BX_ERROR(("VMFAIL: save_VMX_preemption_timer VMEXIT control is set but VMX_preemption_timer VMEXEC control is clear")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } #endif if (vm->vmexit_msr_store_cnt > 0) { vm->vmexit_msr_store_addr = VMread64(VMCS_64BIT_CONTROL_VMEXIT_MSR_STORE_ADDR); if ((vm->vmexit_msr_store_addr & 0xf) != 0 || ! IsValidPhyAddr(vm->vmexit_msr_store_addr)) { BX_ERROR(("VMFAIL: VMCS VMEXIT CTRL: msr store addr malformed")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } Bit64u last_byte = vm->vmexit_msr_store_addr + (vm->vmexit_msr_store_cnt * 16) - 1; if (! IsValidPhyAddr(last_byte)) { BX_ERROR(("VMFAIL: VMCS VMEXIT CTRL: msr store addr too high")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } if (vm->vmexit_msr_load_cnt > 0) { vm->vmexit_msr_load_addr = VMread64(VMCS_64BIT_CONTROL_VMEXIT_MSR_LOAD_ADDR); if ((vm->vmexit_msr_load_addr & 0xf) != 0 || ! IsValidPhyAddr(vm->vmexit_msr_load_addr)) { BX_ERROR(("VMFAIL: VMCS VMEXIT CTRL: msr load addr malformed")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } Bit64u last_byte = (Bit64u) vm->vmexit_msr_load_addr + (vm->vmexit_msr_load_cnt * 16) - 1; if (! IsValidPhyAddr(last_byte)) { BX_ERROR(("VMFAIL: VMCS VMEXIT CTRL: msr load addr too high")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } // // Load VM-entry control fields to VMCS Cache // vm->vmentry_ctrls = VMread32(VMCS_32BIT_CONTROL_VMENTRY_CONTROLS); vm->vmentry_msr_load_cnt = VMread32(VMCS_32BIT_CONTROL_VMENTRY_MSR_LOAD_COUNT); // // Check VM-entry control fields // if (~vm->vmentry_ctrls & VMX_CHECKS_USE_MSR_VMX_VMENTRY_CTRLS_LO) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX vmentry controls allowed 0-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmentry_ctrls & ~VMX_CHECKS_USE_MSR_VMX_VMENTRY_CTRLS_HI) { BX_ERROR(("VMFAIL: VMCS EXEC CTRL: VMX vmentry controls allowed 1-settings")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (vm->vmentry_ctrls & VMX_VMENTRY_CTRL1_DEACTIVATE_DUAL_MONITOR_TREATMENT) { if (! BX_CPU_THIS_PTR in_smm) { BX_ERROR(("VMFAIL: VMENTRY from outside SMM with dual-monitor treatment enabled")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } if (vm->vmentry_msr_load_cnt > 0) { vm->vmentry_msr_load_addr = VMread64(VMCS_64BIT_CONTROL_VMENTRY_MSR_LOAD_ADDR); if ((vm->vmentry_msr_load_addr & 0xf) != 0 || ! IsValidPhyAddr(vm->vmentry_msr_load_addr)) { BX_ERROR(("VMFAIL: VMCS VMENTRY CTRL: msr load addr malformed")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } Bit64u last_byte = vm->vmentry_msr_load_addr + (vm->vmentry_msr_load_cnt * 16) - 1; if (! IsValidPhyAddr(last_byte)) { BX_ERROR(("VMFAIL: VMCS VMENTRY CTRL: msr load addr too high")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } // // Check VM-entry event injection info // vm->vmentry_interr_info = VMread32(VMCS_32BIT_CONTROL_VMENTRY_INTERRUPTION_INFO); vm->vmentry_excep_err_code = VMread32(VMCS_32BIT_CONTROL_VMENTRY_EXCEPTION_ERR_CODE); vm->vmentry_instr_length = VMread32(VMCS_32BIT_CONTROL_VMENTRY_INSTRUCTION_LENGTH); if (VMENTRY_INJECTING_EVENT(vm->vmentry_interr_info)) { /* the VMENTRY injecting event to the guest */ unsigned vector = vm->vmentry_interr_info & 0xff; unsigned event_type = (vm->vmentry_interr_info >> 8) & 7; unsigned push_error = (vm->vmentry_interr_info >> 11) & 1; unsigned error_code = push_error ? vm->vmentry_excep_err_code : 0; unsigned push_error_reference = 0; if (event_type == BX_HARDWARE_EXCEPTION && vector < BX_CPU_HANDLED_EXCEPTIONS && exceptions_info[vector].push_error) push_error_reference = 1; if (vm->vmentry_interr_info & 0x7ffff000) { BX_ERROR(("VMFAIL: VMENTRY broken interruption info field")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } switch (event_type) { case BX_EXTERNAL_INTERRUPT: break; case BX_NMI: if (vector != 2) { BX_ERROR(("VMFAIL: VMENTRY bad injected event vector %d", vector)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } break; case BX_HARDWARE_EXCEPTION: if (vector > 31) { BX_ERROR(("VMFAIL: VMENTRY bad injected event vector %d", vector)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } break; case BX_SOFTWARE_INTERRUPT: case BX_PRIVILEGED_SOFTWARE_INTERRUPT: case BX_SOFTWARE_EXCEPTION: if (vm->vmentry_instr_length == 0 || vm->vmentry_instr_length > 15) { BX_ERROR(("VMFAIL: VMENTRY bad injected event instr length")); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } break; default: BX_ERROR(("VMFAIL: VMENTRY bad injected event type %d", event_type)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } if (push_error != push_error_reference) { if (! (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST)) { BX_ERROR(("VMFAIL: VMENTRY injected event vector %d should push error", vector)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } if (error_code & 0x7fff0000) { BX_ERROR(("VMFAIL: VMENTRY bad error code 0x%08x for injected event %d", error_code, vector)); return VMXERR_VMENTRY_INVALID_VM_CONTROL_FIELD; } } return VMXERR_NO_ERROR; } VMX_error_code BX_CPU_C::VMenterLoadCheckHostState(void) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; VMCS_HOST_STATE *host_state = &vm->host_state; bx_bool x86_64_host = 0, x86_64_guest = 0; // // VM Host State Checks Related to Address-Space Size // Bit32u vmexit_ctrls = vm->vmexit_ctrls; if (vmexit_ctrls & VMX_VMEXIT_CTRL1_HOST_ADDR_SPACE_SIZE) { x86_64_host = 1; } Bit32u vmentry_ctrls = vm->vmentry_ctrls; if (vmentry_ctrls & VMX_VMENTRY_CTRL1_X86_64_GUEST) { x86_64_guest = 1; } #if BX_SUPPORT_X86_64 if (long_mode()) { if (! x86_64_host) { BX_ERROR(("VMFAIL: VMCS x86-64 host control invalid on VMENTRY")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } else #endif { if (x86_64_host || x86_64_guest) { BX_ERROR(("VMFAIL: VMCS x86-64 guest(%d)/host(%d) controls invalid on VMENTRY", x86_64_guest, x86_64_host)); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } // // Load and Check VM Host State to VMCS Cache // host_state->cr0 = (bx_address) VMread_natural(VMCS_HOST_CR0); if (~host_state->cr0 & VMX_MSR_CR0_FIXED0) { BX_ERROR(("VMFAIL: VMCS host state invalid CR0 0x%08x", (Bit32u) host_state->cr0)); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (host_state->cr0 & ~VMX_MSR_CR0_FIXED1) { BX_ERROR(("VMFAIL: VMCS host state invalid CR0 0x%08x", (Bit32u) host_state->cr0)); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } host_state->cr3 = (bx_address) VMread_natural(VMCS_HOST_CR3); #if BX_SUPPORT_X86_64 if (! IsValidPhyAddr(host_state->cr3)) { BX_ERROR(("VMFAIL: VMCS host state invalid CR3")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } #endif host_state->cr4 = (bx_address) VMread_natural(VMCS_HOST_CR4); if (~host_state->cr4 & VMX_MSR_CR4_FIXED0) { BX_ERROR(("VMFAIL: VMCS host state invalid CR4 0x" FMT_ADDRX, host_state->cr4)); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (host_state->cr4 & ~VMX_MSR_CR4_FIXED1) { BX_ERROR(("VMFAIL: VMCS host state invalid CR4 0x" FMT_ADDRX, host_state->cr4)); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } for(int n=0; n<6; n++) { host_state->segreg_selector[n] = VMread16(VMCS_16BIT_HOST_ES_SELECTOR + 2*n); if (host_state->segreg_selector[n] & 7) { BX_ERROR(("VMFAIL: VMCS host segreg %d TI/RPL != 0", n)); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } if (host_state->segreg_selector[BX_SEG_REG_CS] == 0) { BX_ERROR(("VMFAIL: VMCS host CS selector 0")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (! x86_64_host && host_state->segreg_selector[BX_SEG_REG_SS] == 0) { BX_ERROR(("VMFAIL: VMCS host SS selector 0")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } host_state->tr_selector = VMread16(VMCS_16BIT_HOST_TR_SELECTOR); if (! host_state->tr_selector || (host_state->tr_selector & 7) != 0) { BX_ERROR(("VMFAIL: VMCS invalid host TR selector")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } host_state->tr_base = (bx_address) VMread_natural(VMCS_HOST_TR_BASE); #if BX_SUPPORT_X86_64 if (! IsCanonical(host_state->tr_base)) { BX_ERROR(("VMFAIL: VMCS host TR BASE non canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } #endif host_state->fs_base = (bx_address) VMread_natural(VMCS_HOST_FS_BASE); host_state->gs_base = (bx_address) VMread_natural(VMCS_HOST_GS_BASE); #if BX_SUPPORT_X86_64 if (! IsCanonical(host_state->fs_base)) { BX_ERROR(("VMFAIL: VMCS host FS BASE non canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (! IsCanonical(host_state->gs_base)) { BX_ERROR(("VMFAIL: VMCS host GS BASE non canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } #endif host_state->gdtr_base = (bx_address) VMread_natural(VMCS_HOST_GDTR_BASE); host_state->idtr_base = (bx_address) VMread_natural(VMCS_HOST_IDTR_BASE); #if BX_SUPPORT_X86_64 if (! IsCanonical(host_state->gdtr_base)) { BX_ERROR(("VMFAIL: VMCS host GDTR BASE non canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (! IsCanonical(host_state->idtr_base)) { BX_ERROR(("VMFAIL: VMCS host IDTR BASE non canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } #endif host_state->sysenter_esp_msr = (bx_address) VMread_natural(VMCS_HOST_IA32_SYSENTER_ESP_MSR); host_state->sysenter_eip_msr = (bx_address) VMread_natural(VMCS_HOST_IA32_SYSENTER_EIP_MSR); host_state->sysenter_cs_msr = (Bit16u) VMread32(VMCS_32BIT_HOST_IA32_SYSENTER_CS_MSR); #if BX_SUPPORT_X86_64 if (! IsCanonical(host_state->sysenter_esp_msr)) { BX_ERROR(("VMFAIL: VMCS host SYSENTER_ESP_MSR non canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (! IsCanonical(host_state->sysenter_eip_msr)) { BX_ERROR(("VMFAIL: VMCS host SYSENTER_EIP_MSR non canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } #endif #if BX_SUPPORT_VMX >= 2 if (vmexit_ctrls & VMX_VMEXIT_CTRL1_LOAD_PAT_MSR) { host_state->pat_msr = VMread64(VMCS_64BIT_HOST_IA32_PAT); if (! isValidMSR_PAT(host_state->pat_msr)) { BX_ERROR(("VMFAIL: invalid Memory Type in host MSR_PAT")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } #endif host_state->rsp = (bx_address) VMread_natural(VMCS_HOST_RSP); host_state->rip = (bx_address) VMread_natural(VMCS_HOST_RIP); #if BX_SUPPORT_X86_64 #if BX_SUPPORT_VMX >= 2 if (vmexit_ctrls & VMX_VMEXIT_CTRL1_LOAD_EFER_MSR) { host_state->efer_msr = VMread64(VMCS_64BIT_HOST_IA32_EFER); if (host_state->efer_msr & ~((Bit64u) BX_CPU_THIS_PTR efer_suppmask)) { BX_ERROR(("VMFAIL: VMCS host EFER reserved bits set !")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } bx_bool lme = (host_state->efer_msr >> 8) & 0x1; bx_bool lma = (host_state->efer_msr >> 10) & 0x1; if (lma != lme || lma != x86_64_host) { BX_ERROR(("VMFAIL: VMCS host EFER (0x%08x) inconsistent value !", (Bit32u) host_state->efer_msr)); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } #endif if (x86_64_host) { if ((host_state->cr4 & BX_CR4_PAE_MASK) == 0) { BX_ERROR(("VMFAIL: VMCS host CR4.PAE=0 with x86-64 host")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (! IsCanonical(host_state->rip)) { BX_ERROR(("VMFAIL: VMCS host RIP non-canonical")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } else { if (GET32H(host_state->rip) != 0) { BX_ERROR(("VMFAIL: VMCS host RIP > 32 bit")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (host_state->cr4 & BX_CR4_PCIDE_MASK) { BX_ERROR(("VMFAIL: VMCS host CR4.PCIDE set")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } } #endif return VMXERR_NO_ERROR; } BX_CPP_INLINE bx_bool IsLimitAccessRightsConsistent(Bit32u limit, Bit32u ar) { bx_bool g = (ar >> 15) & 1; // access rights reserved bits set if (ar & 0xfffe0f00) return 0; if (g) { // if any of the bits in limit[11:00] are '0 <=> G must be '0 if ((limit & 0xfff) != 0xfff) return 0; } else { // if any of the bits in limit[31:20] are '1 <=> G must be '1 if ((limit & 0xfff00000) != 0) return 0; } return 1; } Bit32u BX_CPU_C::VMenterLoadCheckGuestState(Bit64u *qualification) { static const char *segname[] = { "ES", "CS", "SS", "DS", "FS", "GS" }; int n; VMCS_GUEST_STATE guest; VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; *qualification = VMENTER_ERR_NO_ERROR; // // Load and Check Guest State from VMCS // guest.rflags = VMread_natural(VMCS_GUEST_RFLAGS); // RFLAGS reserved bits [63:22], bit 15, bit 5, bit 3 must be zero if (guest.rflags & BX_CONST64(0xFFFFFFFFFFC08028)) { BX_ERROR(("VMENTER FAIL: RFLAGS reserved bits are set")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } // RFLAGS[1] must be always set if ((guest.rflags & 0x2) == 0) { BX_ERROR(("VMENTER FAIL: RFLAGS[1] cleared")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } bx_bool v8086_guest = 0; if (guest.rflags & EFlagsVMMask) v8086_guest = 1; bx_bool x86_64_guest = 0; // can't be 1 if X86_64 is not supported (checked before) Bit32u vmentry_ctrls = vm->vmentry_ctrls; #if BX_SUPPORT_X86_64 if (vmentry_ctrls & VMX_VMENTRY_CTRL1_X86_64_GUEST) { BX_DEBUG(("VMENTER to x86-64 guest")); x86_64_guest = 1; } #endif if (x86_64_guest && v8086_guest) { BX_ERROR(("VMENTER FAIL: Enter to x86-64 guest with RFLAGS.VM")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } guest.cr0 = VMread_natural(VMCS_GUEST_CR0); #if BX_SUPPORT_VMX >= 2 if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST) { if (~guest.cr0 & (VMX_MSR_CR0_FIXED0 & ~(BX_CR0_PE_MASK | BX_CR0_PG_MASK))) { BX_ERROR(("VMENTER FAIL: VMCS guest invalid CR0")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } bx_bool pe = (guest.cr0 & BX_CR0_PE_MASK) != 0; bx_bool pg = (guest.cr0 & BX_CR0_PG_MASK) != 0; if (pg && !pe) { BX_ERROR(("VMENTER FAIL: VMCS unrestricted guest CR0.PG without CR0.PE")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } else #endif { if (~guest.cr0 & VMX_MSR_CR0_FIXED0) { BX_ERROR(("VMENTER FAIL: VMCS guest invalid CR0")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } if (guest.cr0 & ~VMX_MSR_CR0_FIXED1) { BX_ERROR(("VMENTER FAIL: VMCS guest invalid CR0")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #if BX_SUPPORT_VMX >= 2 bx_bool real_mode_guest = 0; if (! (guest.cr0 & BX_CR0_PE_MASK)) real_mode_guest = 1; #endif guest.cr3 = VMread_natural(VMCS_GUEST_CR3); #if BX_SUPPORT_X86_64 if (! IsValidPhyAddr(guest.cr3)) { BX_ERROR(("VMENTER FAIL: VMCS guest invalid CR3")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #endif guest.cr4 = VMread_natural(VMCS_GUEST_CR4); if (~guest.cr4 & VMX_MSR_CR4_FIXED0) { BX_ERROR(("VMENTER FAIL: VMCS guest invalid CR4")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } if (guest.cr4 & ~VMX_MSR_CR4_FIXED1) { BX_ERROR(("VMENTER FAIL: VMCS guest invalid CR4")); return VMXERR_VMENTRY_INVALID_VM_HOST_STATE_FIELD; } #if BX_SUPPORT_X86_64 if (x86_64_guest) { if ((guest.cr4 & BX_CR4_PAE_MASK) == 0) { BX_ERROR(("VMENTER FAIL: VMCS guest CR4.PAE=0 in x86-64 mode")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } else { if (guest.cr4 & BX_CR4_PCIDE_MASK) { BX_ERROR(("VMENTER FAIL: VMCS CR4.PCIDE set in 32-bit guest")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #endif #if BX_SUPPORT_X86_64 if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS) { guest.dr7 = VMread_natural(VMCS_GUEST_DR7); if (GET32H(guest.dr7)) { BX_ERROR(("VMENTER FAIL: VMCS guest invalid DR7")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #endif // // Load and Check Guest State from VMCS - Segment Registers // for (n=0; n<6; n++) { Bit16u selector = VMread16(VMCS_16BIT_GUEST_ES_SELECTOR + 2*n); bx_address base = (bx_address) VMread_natural(VMCS_GUEST_ES_BASE + 2*n); Bit32u limit = VMread32(VMCS_32BIT_GUEST_ES_LIMIT + 2*n); Bit32u ar = VMread32(VMCS_32BIT_GUEST_ES_ACCESS_RIGHTS + 2*n) >> 8; bx_bool invalid = (ar >> 16) & 1; set_segment_ar_data(&guest.sregs[n], !invalid, (Bit16u) selector, base, limit, (Bit16u) ar); if (v8086_guest) { // guest in V8086 mode if (base != ((bx_address)(selector << 4))) { BX_ERROR(("VMENTER FAIL: VMCS v8086 guest bad %s.BASE", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (limit != 0xffff) { BX_ERROR(("VMENTER FAIL: VMCS v8086 guest %s.LIMIT != 0xFFFF", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } // present, expand-up read/write accessed, segment, DPL=3 if (ar != 0xF3) { BX_ERROR(("VMENTER FAIL: VMCS v8086 guest %s.AR != 0xF3", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } continue; // go to next segment register } #if BX_SUPPORT_X86_64 if (n >= BX_SEG_REG_FS) { if (! IsCanonical(base)) { BX_ERROR(("VMENTER FAIL: VMCS guest %s.BASE non canonical", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #endif if (n != BX_SEG_REG_CS && invalid) continue; #if BX_SUPPORT_X86_64 if (n == BX_SEG_REG_SS && (selector & BX_SELECTOR_RPL_MASK) == 0) { // SS is allowed to be NULL selector if going to 64-bit guest if (x86_64_guest && guest.sregs[BX_SEG_REG_CS].cache.u.segment.l) continue; } if (n < BX_SEG_REG_FS) { if (GET32H(base) != 0) { BX_ERROR(("VMENTER FAIL: VMCS guest %s.BASE > 32 bit", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #endif if (! guest.sregs[n].cache.segment) { BX_ERROR(("VMENTER FAIL: VMCS guest %s not segment", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! guest.sregs[n].cache.p) { BX_ERROR(("VMENTER FAIL: VMCS guest %s not present", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! IsLimitAccessRightsConsistent(limit, ar)) { BX_ERROR(("VMENTER FAIL: VMCS guest %s.AR/LIMIT malformed", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (n == BX_SEG_REG_CS) { // CS checks switch (guest.sregs[BX_SEG_REG_CS].cache.type) { case BX_CODE_EXEC_ONLY_ACCESSED: case BX_CODE_EXEC_READ_ACCESSED: // non-conforming segment if (guest.sregs[BX_SEG_REG_CS].selector.rpl != guest.sregs[BX_SEG_REG_CS].cache.dpl) { BX_ERROR(("VMENTER FAIL: VMCS guest non-conforming CS.RPL <> CS.DPL")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } break; case BX_CODE_EXEC_ONLY_CONFORMING_ACCESSED: case BX_CODE_EXEC_READ_CONFORMING_ACCESSED: // conforming segment if (guest.sregs[BX_SEG_REG_CS].selector.rpl < guest.sregs[BX_SEG_REG_CS].cache.dpl) { BX_ERROR(("VMENTER FAIL: VMCS guest non-conforming CS.RPL < CS.DPL")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } break; #if BX_SUPPORT_VMX >= 2 case BX_DATA_READ_WRITE_ACCESSED: if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST) { if (guest.sregs[BX_SEG_REG_CS].cache.dpl != 0) { BX_ERROR(("VMENTER FAIL: VMCS unrestricted guest CS.DPL != 0")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } break; } // fall through #endif default: BX_ERROR(("VMENTER FAIL: VMCS guest CS.TYPE")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #if BX_SUPPORT_X86_64 if (x86_64_guest) { if (guest.sregs[BX_SEG_REG_CS].cache.u.segment.d_b && guest.sregs[BX_SEG_REG_CS].cache.u.segment.l) { BX_ERROR(("VMENTER FAIL: VMCS x86_64 guest wrong CS.D_B/L")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #endif } else if (n == BX_SEG_REG_SS) { // SS checks switch (guest.sregs[BX_SEG_REG_SS].cache.type) { case BX_DATA_READ_WRITE_ACCESSED: case BX_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED: break; default: BX_ERROR(("VMENTER FAIL: VMCS guest SS.TYPE")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } else { // DS, ES, FS, GS if ((guest.sregs[n].cache.type & 0x1) == 0) { BX_ERROR(("VMENTER FAIL: VMCS guest %s not ACCESSED", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (guest.sregs[n].cache.type & 0x8) { if ((guest.sregs[n].cache.type & 0x2) == 0) { BX_ERROR(("VMENTER FAIL: VMCS guest CODE segment %s not READABLE", segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } if (! (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST)) { if (guest.sregs[n].cache.type < 11) { // data segment or non-conforming code segment if (guest.sregs[n].selector.rpl > guest.sregs[n].cache.dpl) { BX_ERROR(("VMENTER FAIL: VMCS guest non-conforming %s.RPL < %s.DPL", segname[n], segname[n])); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } } } } if (! v8086_guest) { if (! (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST)) { if (guest.sregs[BX_SEG_REG_SS].selector.rpl != guest.sregs[BX_SEG_REG_CS].selector.rpl) { BX_ERROR(("VMENTER FAIL: VMCS guest CS.RPL != SS.RPL")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (guest.sregs[BX_SEG_REG_SS].selector.rpl != guest.sregs[BX_SEG_REG_SS].cache.dpl) { BX_ERROR(("VMENTER FAIL: VMCS guest SS.RPL <> SS.DPL")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #if BX_SUPPORT_VMX >= 2 else { // unrestricted guest if (real_mode_guest || guest.sregs[BX_SEG_REG_CS].cache.type == BX_DATA_READ_WRITE_ACCESSED) { if (guest.sregs[BX_SEG_REG_SS].cache.dpl != 0) { BX_ERROR(("VMENTER FAIL: VMCS unrestricted guest SS.DPL != 0")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } } #endif } // // Load and Check Guest State from VMCS - GDTR/IDTR // Bit64u gdtr_base = VMread_natural(VMCS_GUEST_GDTR_BASE); Bit32u gdtr_limit = VMread32(VMCS_32BIT_GUEST_GDTR_LIMIT); Bit64u idtr_base = VMread_natural(VMCS_GUEST_IDTR_BASE); Bit32u idtr_limit = VMread32(VMCS_32BIT_GUEST_IDTR_LIMIT); #if BX_SUPPORT_X86_64 if (! IsCanonical(gdtr_base) || ! IsCanonical(idtr_base)) { BX_ERROR(("VMENTER FAIL: VMCS guest IDTR/IDTR.BASE non canonical")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #endif if (gdtr_limit > 0xffff || idtr_limit > 0xffff) { BX_ERROR(("VMENTER FAIL: VMCS guest GDTR/IDTR limit > 0xFFFF")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } // // Load and Check Guest State from VMCS - LDTR // Bit16u ldtr_selector = VMread16(VMCS_16BIT_GUEST_LDTR_SELECTOR); Bit64u ldtr_base = VMread_natural(VMCS_GUEST_LDTR_BASE); Bit32u ldtr_limit = VMread32(VMCS_32BIT_GUEST_LDTR_LIMIT); Bit32u ldtr_ar = VMread32(VMCS_32BIT_GUEST_LDTR_ACCESS_RIGHTS) >> 8; bx_bool ldtr_invalid = (ldtr_ar >> 16) & 1; if (set_segment_ar_data(&guest.ldtr, !ldtr_invalid, (Bit16u) ldtr_selector, ldtr_base, ldtr_limit, (Bit16u)(ldtr_ar))) { // ldtr is valid if (guest.ldtr.selector.ti) { BX_ERROR(("VMENTER FAIL: VMCS guest LDTR.TI set")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (guest.ldtr.cache.type != BX_SYS_SEGMENT_LDT) { BX_ERROR(("VMENTER FAIL: VMCS guest incorrect LDTR type")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (guest.ldtr.cache.segment) { BX_ERROR(("VMENTER FAIL: VMCS guest LDTR is not system segment")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! guest.ldtr.cache.p) { BX_ERROR(("VMENTER FAIL: VMCS guest LDTR not present")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! IsLimitAccessRightsConsistent(ldtr_limit, ldtr_ar)) { BX_ERROR(("VMENTER FAIL: VMCS guest LDTR.AR/LIMIT malformed")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #if BX_SUPPORT_X86_64 if (! IsCanonical(ldtr_base)) { BX_ERROR(("VMENTER FAIL: VMCS guest LDTR.BASE non canonical")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #endif } // // Load and Check Guest State from VMCS - TR // Bit16u tr_selector = VMread16(VMCS_16BIT_GUEST_TR_SELECTOR); Bit64u tr_base = VMread_natural(VMCS_GUEST_TR_BASE); Bit32u tr_limit = VMread32(VMCS_32BIT_GUEST_TR_LIMIT); Bit32u tr_ar = VMread32(VMCS_32BIT_GUEST_TR_ACCESS_RIGHTS) >> 8; bx_bool tr_invalid = (tr_ar >> 16) & 1; #if BX_SUPPORT_X86_64 if (! IsCanonical(tr_base)) { BX_ERROR(("VMENTER FAIL: VMCS guest TR.BASE non canonical")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #endif set_segment_ar_data(&guest.tr, !tr_invalid, (Bit16u) tr_selector, tr_base, tr_limit, (Bit16u)(tr_ar)); if (tr_invalid) { BX_ERROR(("VMENTER FAIL: VMCS guest TR invalid")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (guest.tr.selector.ti) { BX_ERROR(("VMENTER FAIL: VMCS guest TR.TI set")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (guest.tr.cache.segment) { BX_ERROR(("VMENTER FAIL: VMCS guest TR is not system segment")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! guest.tr.cache.p) { BX_ERROR(("VMENTER FAIL: VMCS guest TR not present")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! IsLimitAccessRightsConsistent(tr_limit, tr_ar)) { BX_ERROR(("VMENTER FAIL: VMCS guest TR.AR/LIMIT malformed")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } switch(guest.tr.cache.type) { case BX_SYS_SEGMENT_BUSY_386_TSS: break; case BX_SYS_SEGMENT_BUSY_286_TSS: if (! x86_64_guest) break; // fall through default: BX_ERROR(("VMENTER FAIL: VMCS guest incorrect TR type")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } // // Load and Check Guest State from VMCS - MSRS // guest.ia32_debugctl_msr = VMread64(VMCS_64BIT_GUEST_IA32_DEBUGCTL); guest.smbase = VMread32(VMCS_32BIT_GUEST_SMBASE); guest.sysenter_esp_msr = VMread_natural(VMCS_GUEST_IA32_SYSENTER_ESP_MSR); guest.sysenter_eip_msr = VMread_natural(VMCS_GUEST_IA32_SYSENTER_EIP_MSR); guest.sysenter_cs_msr = VMread32(VMCS_32BIT_GUEST_IA32_SYSENTER_CS_MSR); #if BX_SUPPORT_X86_64 if (! IsCanonical(guest.sysenter_esp_msr)) { BX_ERROR(("VMENTER FAIL: VMCS guest SYSENTER_ESP_MSR non canonical")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! IsCanonical(guest.sysenter_eip_msr)) { BX_ERROR(("VMENTER FAIL: VMCS guest SYSENTER_EIP_MSR non canonical")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } #endif #if BX_SUPPORT_VMX >= 2 if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_PAT_MSR) { guest.pat_msr = VMread64(VMCS_64BIT_GUEST_IA32_PAT); if (! isValidMSR_PAT(guest.pat_msr)) { BX_ERROR(("VMENTER FAIL: invalid Memory Type in guest MSR_PAT")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #endif guest.rip = VMread_natural(VMCS_GUEST_RIP); guest.rsp = VMread_natural(VMCS_GUEST_RSP); #if BX_SUPPORT_VMX >= 2 && BX_SUPPORT_X86_64 if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_EFER_MSR) { guest.efer_msr = VMread64(VMCS_64BIT_GUEST_IA32_EFER); if (guest.efer_msr & ~((Bit64u) BX_CPU_THIS_PTR efer_suppmask)) { BX_ERROR(("VMENTER FAIL: VMCS guest EFER reserved bits set !")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } bx_bool lme = (guest.efer_msr >> 8) & 0x1; bx_bool lma = (guest.efer_msr >> 10) & 0x1; if (lma != x86_64_guest) { BX_ERROR(("VMENTER FAIL: VMCS guest EFER.LMA doesn't match x86_64_guest !")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (lma != lme && (guest.cr0 & BX_CR0_PG_MASK) != 0) { BX_ERROR(("VMENTER FAIL: VMCS guest EFER (0x%08x) inconsistent value !", (Bit32u) guest.efer_msr)); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } if (! x86_64_guest || !guest.sregs[BX_SEG_REG_CS].cache.u.segment.l) { if (GET32H(guest.rip) != 0) { BX_ERROR(("VMENTER FAIL: VMCS guest RIP > 32 bit")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } #endif // // Load and Check Guest Non-Registers State from VMCS // guest.link_pointer = VMread64(VMCS_64BIT_GUEST_LINK_POINTER); if (guest.link_pointer != BX_INVALID_VMCSPTR) { if ((guest.link_pointer & 0xfff) != 0 || ! IsValidPhyAddr(guest.link_pointer)) { *qualification = (Bit64u) VMENTER_ERR_GUEST_STATE_LINK_POINTER; BX_ERROR(("VMFAIL: VMCS link pointer malformed")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } Bit32u revision = VMXReadRevisionID((bx_phy_address) guest.link_pointer); if (revision != VMX_VMCS_REVISION_ID) { *qualification = (Bit64u) VMENTER_ERR_GUEST_STATE_LINK_POINTER; BX_ERROR(("VMFAIL: VMCS link pointer incorrect revision ID %d != %d", revision, VMX_VMCS_REVISION_ID)); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (! BX_CPU_THIS_PTR in_smm || (vmentry_ctrls & VMX_VMENTRY_CTRL1_SMM_ENTER) != 0) { if (guest.link_pointer == BX_CPU_THIS_PTR vmcsptr) { *qualification = (Bit64u) VMENTER_ERR_GUEST_STATE_LINK_POINTER; BX_ERROR(("VMFAIL: VMCS link pointer equal to current VMCS pointer")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } else { if (guest.link_pointer == BX_CPU_THIS_PTR vmxonptr) { *qualification = (Bit64u) VMENTER_ERR_GUEST_STATE_LINK_POINTER; BX_ERROR(("VMFAIL: VMCS link pointer equal to VMXON pointer")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } } guest.tmpDR6 = (Bit32u) VMread_natural(VMCS_GUEST_PENDING_DBG_EXCEPTIONS); if (guest.tmpDR6 & BX_CONST64(0xFFFFFFFFFFFFAFF0)) { BX_ERROR(("VMENTER FAIL: VMCS guest tmpDR6 reserved bits")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } guest.activity_state = VMread32(VMCS_32BIT_GUEST_ACTIVITY_STATE); if (guest.activity_state >= BX_VMX_LAST_ACTIVITY_STATE) { BX_ERROR(("VMENTER FAIL: VMCS guest activity state %d", guest.activity_state)); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if (guest.activity_state == BX_VMX_STATE_HLT) { if (guest.sregs[BX_SEG_REG_SS].cache.dpl != 0) { BX_ERROR(("VMENTER FAIL: VMCS guest HLT state with SS.DPL=%d", guest.sregs[BX_SEG_REG_SS].cache.dpl)); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } guest.interruptibility_state = VMread32(VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE); if (guest.interruptibility_state & ~BX_VMX_INTERRUPTIBILITY_STATE_MASK) { BX_ERROR(("VMENTER FAIL: VMCS guest interruptibility state broken")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if ((guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_BY_STI) && (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_BY_MOV_SS)) { BX_ERROR(("VMENTER FAIL: VMCS guest interruptibility state broken")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } if ((guest.rflags & EFlagsIFMask) == 0) { if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_BY_STI) { BX_ERROR(("VMENTER FAIL: VMCS guest interrupts can't be blocked by STI when EFLAGS.IF = 0")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } if (VMENTRY_INJECTING_EVENT(vm->vmentry_interr_info)) { unsigned event_type = (vm->vmentry_interr_info >> 8) & 7; if (event_type == BX_EXTERNAL_INTERRUPT) { if ((guest.interruptibility_state & 3) != 0 || (guest.rflags & EFlagsIFMask) == 0) { BX_ERROR(("VMENTER FAIL: VMCS guest interrupts blocked when injecting external interrupt")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } if (event_type == BX_NMI) { if ((guest.interruptibility_state & 3) != 0) { BX_ERROR(("VMENTER FAIL: VMCS guest interrupts blocked when injecting NMI")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } } if (vmentry_ctrls & VMX_VMENTRY_CTRL1_SMM_ENTER) { if (! (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED)) { BX_ERROR(("VMENTER FAIL: VMCS SMM guest should block SMI")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED) { if (! BX_CPU_THIS_PTR in_smm) { BX_ERROR(("VMENTER FAIL: VMCS SMI blocked when not in SMM mode")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } if (! x86_64_guest && (guest.cr4 & BX_CR4_PAE_MASK) != 0 && (guest.cr0 & BX_CR0_PG_MASK) != 0) { #if BX_SUPPORT_VMX >= 2 if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_EPT_ENABLE) { for (n=0;n<4;n++) guest.pdptr[n] = VMread64(VMCS_64BIT_GUEST_IA32_PDPTE0 + 2*n); if (! CheckPDPTR(guest.pdptr)) { *qualification = VMENTER_ERR_GUEST_STATE_PDPTR_LOADING; BX_ERROR(("VMENTER: EPT Guest State PDPTRs Checks Failed")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } else #endif { if (! CheckPDPTR(guest.cr3)) { *qualification = VMENTER_ERR_GUEST_STATE_PDPTR_LOADING; BX_ERROR(("VMENTER: Guest State PDPTRs Checks Failed")); return VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE; } } } // // Load Guest State -> VMENTER // #if BX_SUPPORT_X86_64 #if BX_SUPPORT_VMX >= 2 // modify EFER.LMA / EFER.LME before setting CR4 if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_EFER_MSR) { BX_CPU_THIS_PTR efer.set32((Bit32u) guest.efer_msr); } else #endif { if (x86_64_guest) { BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() | (BX_EFER_LME_MASK | BX_EFER_LMA_MASK)); } else { // when loading unrestricted guest with CR0.PG=0 EFER.LME is unmodified // (i.e., the host value will persist in the guest) if (guest.cr0 & BX_CR0_PG_MASK) BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() & ~(BX_EFER_LME_MASK | BX_EFER_LMA_MASK)); else BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() & ~BX_EFER_LMA_MASK); } } #endif // keep bits ET(4), reserved bits 15:6, 17, 28:19, NW(29), CD(30) #define VMX_KEEP_CR0_BITS 0x7FFAFFD0 guest.cr0 = (BX_CPU_THIS_PTR cr0.get32() & VMX_KEEP_CR0_BITS) | (guest.cr0 & ~VMX_KEEP_CR0_BITS); if (! check_CR0(guest.cr0)) { BX_PANIC(("VMENTER CR0 is broken !")); } if (! check_CR4(guest.cr4)) { BX_PANIC(("VMENTER CR4 is broken !")); } BX_CPU_THIS_PTR cr0.set32((Bit32u) guest.cr0); BX_CPU_THIS_PTR cr4.set32((Bit32u) guest.cr4); BX_CPU_THIS_PTR cr3 = guest.cr3; #if BX_SUPPORT_VMX >= 2 if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_EPT_ENABLE) { // load PDPTR only in PAE legacy mode if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !x86_64_guest) { for (n = 0; n < 4; n++) BX_CPU_THIS_PTR PDPTR_CACHE.entry[n] = guest.pdptr[n]; } } #endif if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_DBG_CTRLS) { // always clear bits 15:14 and set bit 10 BX_CPU_THIS_PTR dr7.set32((guest.dr7 & ~0xc000) | 0x400); } RIP = BX_CPU_THIS_PTR prev_rip = guest.rip; RSP = guest.rsp; BX_CPU_THIS_PTR async_event = 0; setEFlags((Bit32u) guest.rflags); #ifdef BX_SUPPORT_CS_LIMIT_DEMOTION // Handle special case of CS.LIMIT demotion (new descriptor limit is // smaller than current one) if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled > guest.sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) BX_CPU_THIS_PTR iCache.flushICacheEntries(); #endif for(unsigned segreg=0; segreg<6; segreg++) BX_CPU_THIS_PTR sregs[segreg] = guest.sregs[segreg]; BX_CPU_THIS_PTR gdtr.base = gdtr_base; BX_CPU_THIS_PTR gdtr.limit = gdtr_limit; BX_CPU_THIS_PTR idtr.base = idtr_base; BX_CPU_THIS_PTR idtr.limit = idtr_limit; BX_CPU_THIS_PTR ldtr = guest.ldtr; BX_CPU_THIS_PTR tr = guest.tr; BX_CPU_THIS_PTR msr.sysenter_esp_msr = guest.sysenter_esp_msr; BX_CPU_THIS_PTR msr.sysenter_eip_msr = guest.sysenter_eip_msr; BX_CPU_THIS_PTR msr.sysenter_cs_msr = guest.sysenter_cs_msr; #if BX_SUPPORT_VMX >= 2 if (vmentry_ctrls & VMX_VMENTRY_CTRL1_LOAD_PAT_MSR) { BX_CPU_THIS_PTR msr.pat = guest.pat_msr; } vm->last_pause_time = vm->first_pause_time = 0; #endif // // Load Guest Non-Registers State -> VMENTER // if (vm->vmentry_ctrls & VMX_VMENTRY_CTRL1_SMM_ENTER) BX_PANIC(("VMENTER: entry to SMM is not implemented yet !")); if (VMENTRY_INJECTING_EVENT(vm->vmentry_interr_info)) { // the VMENTRY injecting event to the guest BX_CPU_THIS_PTR inhibit_mask = 0; // do not block interrupts BX_CPU_THIS_PTR debug_trap = 0; } else { if (guest.tmpDR6 & (1 << 12)) BX_CPU_THIS_PTR debug_trap = guest.tmpDR6 & 0x0000400F; else BX_CPU_THIS_PTR debug_trap = guest.tmpDR6 & 0x00004000; if (BX_CPU_THIS_PTR debug_trap) { BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_TRAP_HIT; BX_CPU_THIS_PTR async_event = 1; } if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_BY_STI) inhibit_interrupts(BX_INHIBIT_INTERRUPTS); else if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_BY_MOV_SS) inhibit_interrupts(BX_INHIBIT_INTERRUPTS_BY_MOVSS); else BX_CPU_THIS_PTR inhibit_mask = 0; } if (guest.interruptibility_state & BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED) { BX_CPU_THIS_PTR disable_NMI = 1; } else { if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_NMI_WINDOW_VMEXIT) BX_CPU_THIS_PTR async_event = 1; } if (vm->vmexec_ctrls2 & VMX_VM_EXEC_CTRL2_INTERRUPT_WINDOW_VMEXIT) { BX_CPU_THIS_PTR async_event = 1; BX_CPU_THIS_PTR vmx_interrupt_window = 1; // set up interrupt window exiting } handleCpuContextChange(); #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_CONTEXT_SWITCH, 0); return VMXERR_NO_ERROR; } void BX_CPU_C::VMenterInjectEvents(void) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if (! VMENTRY_INJECTING_EVENT(vm->vmentry_interr_info)) return; /* the VMENTRY injecting event to the guest */ unsigned vector = vm->vmentry_interr_info & 0xff; unsigned type = (vm->vmentry_interr_info >> 8) & 7; unsigned push_error = vm->vmentry_interr_info & (1 << 11); unsigned error_code = push_error ? vm->vmentry_excep_err_code : 0; bx_bool is_INT = 0; switch(type) { case BX_EXTERNAL_INTERRUPT: case BX_NMI: case BX_HARDWARE_EXCEPTION: BX_CPU_THIS_PTR EXT = 1; break; case BX_PRIVILEGED_SOFTWARE_INTERRUPT: BX_CPU_THIS_PTR EXT = 1; is_INT = 1; break; case BX_SOFTWARE_INTERRUPT: case BX_SOFTWARE_EXCEPTION: is_INT = 1; break; default: BX_PANIC(("VMENTER: unsupported event injection type %d !", type)); } // keep prev_rip value/unwind in case of event delivery failure if (is_INT) RIP += vm->vmentry_instr_length; BX_DEBUG(("VMENTER: Injecting vector 0x%02x (error_code 0x%04x)", vector, error_code)); if (type == BX_HARDWARE_EXCEPTION) { // record exception the same way as BX_CPU_C::exception does BX_ASSERT(vector < BX_CPU_HANDLED_EXCEPTIONS); BX_CPU_THIS_PTR curr_exception = exceptions_info[vector].exception_type; BX_CPU_THIS_PTR errorno = 1; } vm->idt_vector_info = vm->vmentry_interr_info & ~0x80000000; vm->idt_vector_error_code = error_code; interrupt(vector, type, push_error, error_code); BX_CPU_THIS_PTR errorno = 0; // injection success BX_CPU_THIS_PTR EXT = 0; } Bit32u BX_CPU_C::LoadMSRs(Bit32u msr_cnt, bx_phy_address pAddr) { Bit64u msr_lo, msr_hi; for (Bit32u msr = 1; msr <= msr_cnt; msr++) { access_read_physical(pAddr, 8, &msr_lo); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 8, BX_READ, BX_VMX_LOAD_MSR_ACCESS, (Bit8u*)(&msr_lo)); access_read_physical(pAddr + 8, 8, &msr_hi); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr + 8, 8, BX_READ, BX_VMX_LOAD_MSR_ACCESS, (Bit8u*)(&msr_hi)); if (GET32H(msr_lo)) return msr; Bit32u index = GET32L(msr_lo); #if BX_SUPPORT_X86_64 if (index == BX_MSR_FSBASE || index == BX_MSR_GSBASE) return msr; #endif if (bx_cpuid_support_x2apic()) { if ((index & 0xfffff800) == 0x800) // X2APIC range return msr; } if (! wrmsr(index, msr_hi)) return msr; pAddr += 16; // to next MSR } return 0; } Bit32u BX_CPU_C::StoreMSRs(Bit32u msr_cnt, bx_phy_address pAddr) { Bit64u msr_lo, msr_hi; for (Bit32u msr = 1; msr <= msr_cnt; msr++) { access_read_physical(pAddr, 8, &msr_lo); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 8, BX_READ, BX_VMX_STORE_MSR_ACCESS, (Bit8u*)(&msr_lo)); if (GET32H(msr_lo)) return msr; Bit32u index = GET32L(msr_lo); if (bx_cpuid_support_x2apic()) { if ((index & 0xfffff800) == 0x800) // X2APIC range return msr; } if (! rdmsr(index, &msr_hi)) return msr; access_write_physical(pAddr + 8, 8, &msr_hi); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr + 8, 8, BX_WRITE, BX_VMX_STORE_MSR_ACCESS, (Bit8u*)(&msr_hi)); pAddr += 16; // to next MSR } return 0; } //////////////////////////////////////////////////////////// // VMexit //////////////////////////////////////////////////////////// void BX_CPU_C::VMexitSaveGuestState(void) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; int n; VMwrite_natural(VMCS_GUEST_CR0, BX_CPU_THIS_PTR cr0.get32()); VMwrite_natural(VMCS_GUEST_CR3, BX_CPU_THIS_PTR cr3); VMwrite_natural(VMCS_GUEST_CR4, BX_CPU_THIS_PTR cr4.get32()); #if BX_SUPPORT_VMX >= 2 if (vm->vmexec_ctrls3 & VMX_VM_EXEC_CTRL3_EPT_ENABLE) { // save only if guest running in legacy PAE mode if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) { for(n=0; n<4; n++) { VMwrite64(VMCS_64BIT_GUEST_IA32_PDPTE0 + 2*n, BX_CPU_THIS_PTR PDPTR_CACHE.entry[n]); } } } #endif if (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_SAVE_DBG_CTRLS) VMwrite_natural(VMCS_GUEST_DR7, BX_CPU_THIS_PTR dr7.get32()); VMwrite_natural(VMCS_GUEST_RIP, RIP); VMwrite_natural(VMCS_GUEST_RSP, RSP); VMwrite_natural(VMCS_GUEST_RFLAGS, read_eflags()); for (n=0; n<6; n++) { Bit32u selector = BX_CPU_THIS_PTR sregs[n].selector.value; bx_bool invalid = !BX_CPU_THIS_PTR sregs[n].cache.valid; bx_address base = BX_CPU_THIS_PTR sregs[n].cache.u.segment.base; Bit32u limit = BX_CPU_THIS_PTR sregs[n].cache.u.segment.limit_scaled; Bit32u ar = get_descriptor_h(&BX_CPU_THIS_PTR sregs[n].cache) & 0x00f0ff00; VMwrite16(VMCS_16BIT_GUEST_ES_SELECTOR + 2*n, selector); VMwrite_natural(VMCS_GUEST_ES_BASE + 2*n, base); VMwrite32(VMCS_32BIT_GUEST_ES_LIMIT + 2*n, limit); VMwrite32(VMCS_32BIT_GUEST_ES_ACCESS_RIGHTS + 2*n, ar | (invalid << 24)); } // save guest LDTR Bit32u ldtr_selector = BX_CPU_THIS_PTR ldtr.selector.value; bx_bool ldtr_invalid = !BX_CPU_THIS_PTR ldtr.cache.valid; bx_address ldtr_base = BX_CPU_THIS_PTR ldtr.cache.u.segment.base; Bit32u ldtr_limit = BX_CPU_THIS_PTR ldtr.cache.u.segment.limit_scaled; Bit32u ldtr_ar = get_descriptor_h(&BX_CPU_THIS_PTR ldtr.cache) & 0x00f0ff00; VMwrite16(VMCS_16BIT_GUEST_LDTR_SELECTOR, ldtr_selector); VMwrite_natural(VMCS_GUEST_LDTR_BASE, ldtr_base); VMwrite32(VMCS_32BIT_GUEST_LDTR_LIMIT, ldtr_limit); VMwrite32(VMCS_32BIT_GUEST_LDTR_ACCESS_RIGHTS, ldtr_ar | (ldtr_invalid << 24)); // save guest TR Bit32u tr_selector = BX_CPU_THIS_PTR tr.selector.value; bx_bool tr_invalid = !BX_CPU_THIS_PTR tr.cache.valid; bx_address tr_base = BX_CPU_THIS_PTR tr.cache.u.segment.base; Bit32u tr_limit = BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled; Bit32u tr_ar = get_descriptor_h(&BX_CPU_THIS_PTR tr.cache) & 0x00f0ff00; VMwrite16(VMCS_16BIT_GUEST_TR_SELECTOR, tr_selector); VMwrite_natural(VMCS_GUEST_TR_BASE, tr_base); VMwrite32(VMCS_32BIT_GUEST_TR_LIMIT, tr_limit); VMwrite32(VMCS_32BIT_GUEST_TR_ACCESS_RIGHTS, tr_ar | (tr_invalid << 24)); VMwrite_natural(VMCS_GUEST_GDTR_BASE, BX_CPU_THIS_PTR gdtr.base); VMwrite32(VMCS_32BIT_GUEST_GDTR_LIMIT, BX_CPU_THIS_PTR gdtr.limit); VMwrite_natural(VMCS_GUEST_IDTR_BASE, BX_CPU_THIS_PTR idtr.base); VMwrite32(VMCS_32BIT_GUEST_IDTR_LIMIT, BX_CPU_THIS_PTR idtr.limit); VMwrite_natural(VMCS_GUEST_IA32_SYSENTER_ESP_MSR, BX_CPU_THIS_PTR msr.sysenter_esp_msr); VMwrite_natural(VMCS_GUEST_IA32_SYSENTER_EIP_MSR, BX_CPU_THIS_PTR msr.sysenter_eip_msr); VMwrite32(VMCS_32BIT_GUEST_IA32_SYSENTER_CS_MSR, BX_CPU_THIS_PTR msr.sysenter_cs_msr); #if BX_SUPPORT_VMX >= 2 if (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_STORE_PAT_MSR) VMwrite64(VMCS_64BIT_GUEST_IA32_PAT, BX_CPU_THIS_PTR msr.pat); #if BX_SUPPORT_X86_64 if (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_STORE_EFER_MSR) VMwrite64(VMCS_64BIT_GUEST_IA32_EFER, BX_CPU_THIS_PTR efer.get32()); #endif #endif Bit32u tmpDR6 = BX_CPU_THIS_PTR debug_trap & 0x0000400f; if (tmpDR6 & 0xf) tmpDR6 |= (1 << 12); VMwrite_natural(VMCS_GUEST_PENDING_DBG_EXCEPTIONS, tmpDR6); Bit32u interruptibility_state = 0; if (interrupts_inhibited(BX_INHIBIT_INTERRUPTS)) { if (interrupts_inhibited(BX_INHIBIT_DEBUG)) interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_BY_MOV_SS; else interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_BY_STI; } if (BX_CPU_THIS_PTR disable_SMI) interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_SMI_BLOCKED; if (BX_CPU_THIS_PTR disable_NMI) interruptibility_state |= BX_VMX_INTERRUPTS_BLOCKED_NMI_BLOCKED; VMwrite32(VMCS_32BIT_GUEST_INTERRUPTIBILITY_STATE, interruptibility_state); #if BX_SUPPORT_VMX >= 2 if (VMX_MSR_MISC & VMX_MISC_STORE_LMA_TO_X86_64_GUEST_VMENTRY_CONTROL) { // VMEXITs store the value of EFER.LMA into the “x86-64 guest" VMENTRY control // must be set if unrestricted guest is supported if (long_mode()) vm->vmentry_ctrls |= VMX_VMENTRY_CTRL1_X86_64_GUEST; else vm->vmentry_ctrls &= ~VMX_VMENTRY_CTRL1_X86_64_GUEST; VMwrite32(VMCS_32BIT_CONTROL_VMENTRY_CONTROLS, vm->vmentry_ctrls); } // Deactivate VMX preemtion timer BX_CPU_THIS_PTR lapic.deactivate_vmx_preemption_timer(); BX_CPU_THIS_PTR pending_vmx_timer_expired = 0; // Store back to VMCS if (vm->vmexit_ctrls & VMX_VMEXIT_CTRL1_STORE_VMX_PREEMPTION_TIMER) VMwrite32(VMCS_32BIT_GUEST_PREEMPTION_TIMER_VALUE, BX_CPU_THIS_PTR lapic.read_vmx_preemption_timer()); #endif } void BX_CPU_C::VMexitLoadHostState(void) { VMCS_HOST_STATE *host_state = &BX_CPU_THIS_PTR vmcs.host_state; bx_bool x86_64_host = 0; Bit32u vmexit_ctrls = BX_CPU_THIS_PTR vmcs.vmexit_ctrls; BX_CPU_THIS_PTR tsc_offset = 0; #if BX_SUPPORT_X86_64 if (vmexit_ctrls & VMX_VMEXIT_CTRL1_HOST_ADDR_SPACE_SIZE) { BX_DEBUG(("VMEXIT to x86-64 host")); x86_64_host = 1; } #if BX_SUPPORT_VMX >= 2 // modify EFER.LMA / EFER.LME before setting CR4 if (vmexit_ctrls & VMX_VMEXIT_CTRL1_LOAD_EFER_MSR) { BX_CPU_THIS_PTR efer.set32((Bit32u) host_state->efer_msr); } else #endif { if (x86_64_host) BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() | (BX_EFER_LME_MASK | BX_EFER_LMA_MASK)); else BX_CPU_THIS_PTR efer.set32(BX_CPU_THIS_PTR efer.get32() & ~(BX_EFER_LME_MASK | BX_EFER_LMA_MASK)); } #endif // ET, CD, NW, 28:19, 17, 15:6, and VMX fixed bits not modified Section 19.8 host_state->cr0 = (BX_CPU_THIS_PTR cr0.get32() & VMX_KEEP_CR0_BITS) | (host_state->cr0 & ~VMX_KEEP_CR0_BITS); if (! check_CR0(host_state->cr0)) { BX_PANIC(("VMEXIT CR0 is broken !")); } if (! check_CR4(host_state->cr4)) { BX_PANIC(("VMEXIT CR4 is broken !")); } BX_CPU_THIS_PTR cr0.set32((Bit32u) host_state->cr0); BX_CPU_THIS_PTR cr4.set32((Bit32u) host_state->cr4); BX_CPU_THIS_PTR cr3 = host_state->cr3; if (! x86_64_host && BX_CPU_THIS_PTR cr4.get_PAE()) { if (! CheckPDPTR(host_state->cr3)) { BX_ERROR(("VMABORT: host PDPTRs are corrupted !")); VMabort(VMABORT_HOST_PDPTR_CORRUPTED); } } BX_CPU_THIS_PTR dr7.set32(0x00000400); BX_CPU_THIS_PTR msr.sysenter_cs_msr = host_state->sysenter_cs_msr; BX_CPU_THIS_PTR msr.sysenter_esp_msr = host_state->sysenter_esp_msr; BX_CPU_THIS_PTR msr.sysenter_eip_msr = host_state->sysenter_eip_msr; #if BX_SUPPORT_VMX >= 2 if (vmexit_ctrls & VMX_VMEXIT_CTRL1_LOAD_PAT_MSR) { BX_CPU_THIS_PTR msr.pat = host_state->pat_msr; } #endif // CS selector loaded from VMCS // valid <= 1 // base <= 0 // limit <= 0xffffffff, g <= 1 // present <= 1 // dpl <= 0 // type <= segment, BX_CODE_EXEC_READ_ACCESSED // d_b <= loaded from 'host-address space size' VMEXIT control // l <= loaded from 'host-address space size' VMEXIT control parse_selector(host_state->segreg_selector[BX_SEG_REG_CS], &BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector); BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.valid = SegValidCache | SegAccessROK | SegAccessWOK; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.p = 1; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.dpl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.type = BX_CODE_EXEC_READ_ACCESSED; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.base = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xffffffff; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.avl = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; /* page granular */ BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b = !x86_64_host; #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l = x86_64_host; #endif // DATA selector loaded from VMCS // valid <= if selector is not all-zero // base <= 0 // limit <= 0xffffffff, g <= 1 // present <= 1 // dpl <= 0 // type <= segment, BX_DATA_READ_WRITE_ACCESSED // d_b <= 1 // l <= 0 for (unsigned segreg = 0; segreg < 6; segreg++) { if (segreg == BX_SEG_REG_CS) continue; parse_selector(host_state->segreg_selector[segreg], &BX_CPU_THIS_PTR sregs[segreg].selector); if (! host_state->segreg_selector[segreg]) { BX_CPU_THIS_PTR sregs[segreg].cache.valid = 0; } else { BX_CPU_THIS_PTR sregs[segreg].cache.valid = SegValidCache; BX_CPU_THIS_PTR sregs[segreg].cache.p = 1; BX_CPU_THIS_PTR sregs[segreg].cache.dpl = 0; BX_CPU_THIS_PTR sregs[segreg].cache.segment = 1; /* data/code segment */ BX_CPU_THIS_PTR sregs[segreg].cache.type = BX_DATA_READ_WRITE_ACCESSED; BX_CPU_THIS_PTR sregs[segreg].cache.u.segment.base = 0; BX_CPU_THIS_PTR sregs[segreg].cache.u.segment.limit_scaled = 0xffffffff; BX_CPU_THIS_PTR sregs[segreg].cache.u.segment.avl = 0; BX_CPU_THIS_PTR sregs[segreg].cache.u.segment.g = 1; /* page granular */ BX_CPU_THIS_PTR sregs[segreg].cache.u.segment.d_b = 1; #if BX_SUPPORT_X86_64 BX_CPU_THIS_PTR sregs[segreg].cache.u.segment.l = 0; #endif } } // SS.DPL always clear BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.dpl = 0; if (x86_64_host || BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid) BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.u.segment.base = host_state->fs_base; if (x86_64_host || BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid) BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.u.segment.base = host_state->gs_base; // TR selector loaded from VMCS parse_selector(host_state->tr_selector, &BX_CPU_THIS_PTR tr.selector); BX_CPU_THIS_PTR tr.cache.valid = 1; /* valid */ BX_CPU_THIS_PTR tr.cache.p = 1; /* present */ BX_CPU_THIS_PTR tr.cache.dpl = 0; /* field not used */ BX_CPU_THIS_PTR tr.cache.segment = 0; /* system segment */ BX_CPU_THIS_PTR tr.cache.type = BX_SYS_SEGMENT_BUSY_386_TSS; BX_CPU_THIS_PTR tr.cache.u.segment.base = host_state->tr_base; BX_CPU_THIS_PTR tr.cache.u.segment.limit_scaled = 0x67; BX_CPU_THIS_PTR tr.cache.u.segment.avl = 0; BX_CPU_THIS_PTR tr.cache.u.segment.g = 0; /* byte granular */ // unusable LDTR BX_CPU_THIS_PTR ldtr.selector.value = 0x0000; BX_CPU_THIS_PTR ldtr.selector.index = 0x0000; BX_CPU_THIS_PTR ldtr.selector.ti = 0; BX_CPU_THIS_PTR ldtr.selector.rpl = 0; BX_CPU_THIS_PTR ldtr.cache.valid = 0; /* invalid */ BX_CPU_THIS_PTR gdtr.base = host_state->gdtr_base; BX_CPU_THIS_PTR gdtr.limit = 0xFFFF; BX_CPU_THIS_PTR idtr.base = host_state->idtr_base; BX_CPU_THIS_PTR idtr.limit = 0xFFFF; RIP = BX_CPU_THIS_PTR prev_rip = host_state->rip; RSP = host_state->rsp; BX_CPU_THIS_PTR inhibit_mask = 0; BX_CPU_THIS_PTR debug_trap = 0; // set flags directly, avoid setEFlags side effects BX_CPU_THIS_PTR eflags = 0x2; // Bit1 is always set // Update lazy flags state setEFlagsOSZAPC(0); handleCpuContextChange(); #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_CONTEXT_SWITCH, 0); } void BX_CPU_C::VMexit(Bit32u reason, Bit64u qualification) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; if (!BX_CPU_THIS_PTR in_vmx || !BX_CPU_THIS_PTR in_vmx_guest) { if ((reason & 0x80000000) == 0) BX_PANIC(("PANIC: VMEXIT not in VMX guest mode !")); } // // STEP 0: Update VMEXIT reason // VMwrite32(VMCS_32BIT_VMEXIT_REASON, reason); VMwrite_natural(VMCS_VMEXIT_QUALIFICATION, qualification); // clipping with 0xf not really necessary but keep it for safety VMwrite32(VMCS_32BIT_VMEXIT_INSTRUCTION_LENGTH, (RIP-BX_CPU_THIS_PTR prev_rip) & 0xf); reason &= 0xffff; /* keep only basic VMEXIT reason */ if (reason != VMX_VMEXIT_EXCEPTION_NMI && reason != VMX_VMEXIT_EXTERNAL_INTERRUPT) { VMwrite32(VMCS_32BIT_VMEXIT_INTERRUPTION_INFO, 0); } if (BX_CPU_THIS_PTR in_event) { VMwrite32(VMCS_32BIT_IDT_VECTORING_INFO, vm->idt_vector_info | 0x80000000); VMwrite32(VMCS_32BIT_IDT_VECTORING_ERR_CODE, vm->idt_vector_error_code); BX_CPU_THIS_PTR in_event = 0; } else { VMwrite32(VMCS_32BIT_IDT_VECTORING_INFO, 0); } // VMEXITs are FAULT-like: restore RIP/RSP to value before VMEXIT occurred RIP = BX_CPU_THIS_PTR prev_rip; if (BX_CPU_THIS_PTR speculative_rsp) RSP = BX_CPU_THIS_PTR prev_rsp; // // STEP 1: Saving Guest State to VMCS // if (reason != VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE && reason != VMX_VMEXIT_VMENTRY_FAILURE_MSR) { // clear VMENTRY interruption info field VMwrite32(VMCS_32BIT_CONTROL_VMENTRY_INTERRUPTION_INFO, vm->vmentry_interr_info & ~0x80000000); VMexitSaveGuestState(); Bit32u msr = StoreMSRs(vm->vmexit_msr_store_cnt, vm->vmexit_msr_store_addr); if (msr) { BX_ERROR(("VMABORT: Error when saving guest MSR number %d", msr)); VMabort(VMABORT_SAVING_GUEST_MSRS_FAILURE); } } BX_CPU_THIS_PTR in_vmx_guest = 0; // // STEP 2: Load Host State // VMexitLoadHostState(); // // STEP 3: Load Host MSR registers // Bit32u msr = LoadMSRs(vm->vmexit_msr_load_cnt, vm->vmexit_msr_load_addr); if (msr) { BX_ERROR(("VMABORT: Error when loading host MSR number %d", msr)); VMabort(VMABORT_LOADING_HOST_MSRS); } // // STEP 4: Go back to VMX host // BX_CPU_THIS_PTR disable_INIT = 1; // INIT is disabled in VMX root mode BX_CPU_THIS_PTR vmx_interrupt_window = 0; BX_CPU_THIS_PTR errorno = 0; BX_CPU_THIS_PTR EXT = 0; #if BX_DEBUGGER if (BX_CPU_THIS_PTR vmexit_break) { BX_CPU_THIS_PTR stop_reason = STOP_VMEXIT_BREAK_POINT; bx_debug_break(); // trap into debugger } #endif longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop } #endif // BX_SUPPORT_VMX //////////////////////////////////////////////////////////// // VMX instructions //////////////////////////////////////////////////////////// BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXON(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR cr4.get_VMXE() || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (! BX_CPU_THIS_PTR in_vmx) { if (CPL != 0 || ! BX_CPU_THIS_PTR cr0.get_NE() || ! (BX_CPU_THIS_PTR cr0.get_PE()) || BX_GET_ENABLE_A20() == 0 || ! (BX_CPU_THIS_PTR msr.ia32_feature_ctrl & BX_IA32_FEATURE_CONTROL_LOCK_BIT) || ! (BX_CPU_THIS_PTR msr.ia32_feature_ctrl & BX_IA32_FEATURE_CONTROL_VMX_ENABLE_BIT)) { BX_ERROR(("#GP: VMXON is not allowed !")); exception(BX_GP_EXCEPTION, 0); } bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u pAddr = read_virtual_qword(i->seg(), eaddr); // keep 64-bit if ((pAddr & 0xfff) != 0 || ! IsValidPhyAddr(pAddr)) { BX_ERROR(("VMXON: invalid or not page aligned physical address !")); VMfailInvalid(); BX_NEXT_INSTR(i); } Bit32u revision = VMXReadRevisionID((bx_phy_address) pAddr); if (revision != VMX_VMCS_REVISION_ID) { BX_ERROR(("VMXON: not expected (%d != %d) VMCS revision id !", revision, VMX_VMCS_REVISION_ID)); VMfailInvalid(); BX_NEXT_INSTR(i); } BX_CPU_THIS_PTR vmcsptr = BX_INVALID_VMCSPTR; BX_CPU_THIS_PTR vmcshostptr = 0; BX_CPU_THIS_PTR vmxonptr = pAddr; BX_CPU_THIS_PTR in_vmx = 1; BX_CPU_THIS_PTR disable_INIT = 1; // INIT is disabled in VMX root mode // block and disable A20M; #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif VMsucceed(); } else if (BX_CPU_THIS_PTR in_vmx_guest) { // in VMX non-root operation BX_ERROR(("VMEXIT: VMXON in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_VMXON); } else { // in VMX root operation mode if (CPL != 0) { BX_ERROR(("VMXON with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } VMfail(VMXERR_VMXON_IN_VMX_ROOT_OPERATION); } #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMXOFF(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMXOFF in VMX non-root operation")); VMexit(VMX_VMEXIT_VMXOFF, 0); } if (CPL != 0) { BX_ERROR(("VMXOFF with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } /* if dual-monitor treatment of SMIs and SMM is active THEN VMfail(VMXERR_VMXOFF_WITH_CONFIGURED_SMM_MONITOR); else */ { BX_CPU_THIS_PTR vmxonptr = BX_INVALID_VMCSPTR; BX_CPU_THIS_PTR in_vmx = 0; // leave VMX operation mode BX_CPU_THIS_PTR disable_INIT = 0; // unblock and enable A20M; #if BX_SUPPORT_MONITOR_MWAIT BX_CPU_THIS_PTR monitor.reset_monitor(); #endif VMsucceed(); } #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCALL(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMCALL in VMX non-root operation")); VMexit(VMX_VMEXIT_VMCALL, 0); } if (BX_CPU_THIS_PTR get_VM() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (CPL != 0) { BX_ERROR(("VMCALL with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } if (BX_CPU_THIS_PTR in_smm /*|| (the logical processor does not support the dual-monitor treatment of SMIs and SMM) || (the valid bit in the IA32_SMM_MONITOR_CTL MSR is clear)*/) { VMfail(VMXERR_VMCALL_IN_VMX_ROOT_OPERATION); BX_NEXT_TRACE(i); } /* if dual-monitor treatment of SMIs and BX_CPU_THIS_PTR in_smm THEN perform an SMM VMexit (see Section 24.16.2 of the IntelR 64 and IA-32 Architectures Software Developer's Manual, Volume 3B); */ if (! VMCSPTR_VALID()) { BX_ERROR(("VMFAIL: VMCALL with invalid VMCS ptr")); VMfailInvalid(); BX_NEXT_TRACE(i); } Bit32u launch_state; access_read_physical(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, &launch_state); BX_NOTIFY_PHY_MEMORY_ACCESS(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&launch_state)); if (launch_state != VMCS_STATE_CLEAR) { BX_ERROR(("VMFAIL: VMCALL with launched VMCS")); VMfail(VMXERR_VMCALL_NON_CLEAR_VMCS); BX_NEXT_TRACE(i); } BX_PANIC(("VMCALL: not implemented yet")); /* if VM-exit control fields are not valid (see Section 24.16.6.1 of the IntelR 64 and IA-32 Architectures Software Developer's Manual, Volume 3B) THEN VMfail(VMXERR_VMCALL_INVALID_VMEXIT_FIELD); else enter SMM; read revision identifier in MSEG; if revision identifier does not match that supported by processor THEN leave SMM; VMfailValid(VMXERR_VMCALL_INVALID_MSEG_REVISION_ID); else read SMM-monitor features field in MSEG (see Section 24.16.6.2, in the IntelR 64 and IA-32 Architectures Software Developer's Manual, Volume 3B); if features field is invalid THEN leave SMM; VMfailValid(VMXERR_VMCALL_WITH_INVALID_SMM_MONITOR_FEATURES); else activate dual-monitor treatment of SMIs and SMM (see Section 24.16.6 in the IntelR 64 and IA-32 Architectures Software Developer's Manual, Volume 3B); FI; FI; FI; */ #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMLAUNCH(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); unsigned vmlaunch = 0; if ((i->getIaOpcode() == BX_IA_VMLAUNCH)) { BX_DEBUG(("VMLAUNCH VMCS ptr: 0x" FMT_ADDRX64, BX_CPU_THIS_PTR vmcsptr)); vmlaunch = 1; } else { BX_DEBUG(("VMRESUME VMCS ptr: 0x" FMT_ADDRX64, BX_CPU_THIS_PTR vmcsptr)); } if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMLAUNCH in VMX non-root operation")); VMexit(vmlaunch ? VMX_VMEXIT_VMLAUNCH : VMX_VMEXIT_VMRESUME, 0); } if (CPL != 0) { BX_ERROR(("VMLAUNCH/VMRESUME with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } if (! VMCSPTR_VALID()) { BX_ERROR(("VMFAIL: VMLAUNCH with invalid VMCS ptr !")); VMfailInvalid(); BX_NEXT_TRACE(i); } if (interrupts_inhibited(BX_INHIBIT_INTERRUPTS_BY_MOVSS)) { BX_ERROR(("VMFAIL: VMLAUNCH with interrupts blocked by MOV_SS !")); VMfail(VMXERR_VMENTRY_MOV_SS_BLOCKING); BX_NEXT_TRACE(i); } Bit32u launch_state; access_read_physical(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, &launch_state); BX_NOTIFY_PHY_MEMORY_ACCESS(BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, BX_READ, BX_VMCS_ACCESS, (Bit8u*)(&launch_state)); if (vmlaunch) { if (launch_state != VMCS_STATE_CLEAR) { BX_ERROR(("VMFAIL: VMLAUNCH with non-clear VMCS!")); VMfail(VMXERR_VMLAUNCH_NON_CLEAR_VMCS); BX_NEXT_TRACE(i); } } else { if (launch_state != VMCS_STATE_LAUNCHED) { BX_ERROR(("VMFAIL: VMRESUME with non-launched VMCS!")); VMfail(VMXERR_VMRESUME_NON_LAUNCHED_VMCS); BX_NEXT_TRACE(i); } } /////////////////////////////////////////////////////// // STEP 1: Load and Check VM-Execution Control Fields // STEP 2: Load and Check VM-Exit Control Fields // STEP 3: Load and Check VM-Entry Control Fields /////////////////////////////////////////////////////// VMX_error_code error = VMenterLoadCheckVmControls(); if (error != VMXERR_NO_ERROR) { VMfail(error); BX_NEXT_TRACE(i); } /////////////////////////////////////////////////////// // STEP 4: Load and Check Host State /////////////////////////////////////////////////////// error = VMenterLoadCheckHostState(); if (error != VMXERR_NO_ERROR) { VMfail(error); BX_NEXT_TRACE(i); } /////////////////////////////////////////////////////// // STEP 5: Load and Check Guest State /////////////////////////////////////////////////////// Bit64u qualification = VMENTER_ERR_NO_ERROR; Bit32u state_load_error = VMenterLoadCheckGuestState(&qualification); if (state_load_error) { BX_ERROR(("VMEXIT: Guest State Checks Failed")); VMexit(VMX_VMEXIT_VMENTRY_FAILURE_GUEST_STATE | (1 << 31), qualification); } Bit32u msr = LoadMSRs(BX_CPU_THIS_PTR vmcs.vmentry_msr_load_cnt, BX_CPU_THIS_PTR vmcs.vmentry_msr_load_addr); if (msr) { BX_ERROR(("VMEXIT: Error when loading guest MSR 0x%08x", msr)); VMexit(VMX_VMEXIT_VMENTRY_FAILURE_MSR | (1 << 31), msr); } /////////////////////////////////////////////////////// // STEP 6: Update VMCS 'launched' state /////////////////////////////////////////////////////// if (vmlaunch) { launch_state = VMCS_STATE_LAUNCHED; bx_phy_address pAddr = BX_CPU_THIS_PTR vmcsptr + VMCS_LAUNCH_STATE_FIELD_ADDR; access_write_physical(pAddr, 4, &launch_state); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&launch_state)); } /* Check settings of VMX controls and host-state area; if invalid settings THEN VMfailValid(VM entry with invalid VMX-control field(s)) or VMfailValid(VM entry with invalid host-state field(s)) or VMfailValid(VM entry with invalid executive-VMCS pointer)) or VMfailValid(VM entry with non-launched executive VMCS) or VMfailValid(VM entry with executive-VMCS pointer not VMXON pointer) VMfailValid(VM entry with invalid VM-execution control fields in executive VMCS) (as appropriate); else Attempt to load guest state and PDPTRs as appropriate; clear address-range monitoring; if failure in checking guest state or PDPTRs THEN VM entry fails (see Section 22.7, in the IntelR 64 and IA-32 Architectures Software Developer's Manual, Volume 3B); else Attempt to load MSRs from VM-entry MSR-load area; if failure THEN VM entry fails (see Section 22.7, in the IntelR 64 and IA-32 Architectures Software Developer's Manual, Volume 3B); else { if VMLAUNCH THEN launch state of VMCS <== "launched"; if in SMM and "entry to SMM" VM-entry control is 0 THEN if "deactivate dual-monitor treatment" VM-entry control is 0 THEN SMM-transfer VMCS pointer <== current-VMCS pointer; FI; if executive-VMCS pointer is VMX pointer THEN current-VMCS pointer <== VMCS-link pointer; else current-VMCS pointer <== executive-VMCS pointer; FI; leave SMM; FI; VMsucceed(); } FI; FI; */ BX_CPU_THIS_PTR in_vmx_guest = 1; BX_CPU_THIS_PTR disable_INIT = 0; if (VMEXIT(VMX_VM_EXEC_CTRL2_TSC_OFFSET)) BX_CPU_THIS_PTR tsc_offset = VMread64(VMCS_64BIT_CONTROL_TSC_OFFSET); else BX_CPU_THIS_PTR tsc_offset = 0; #if BX_SUPPORT_VMX >= 2 if (PIN_VMEXIT(VMX_VM_EXEC_CTRL1_VMX_PREEMPTION_TIMER_VMEXIT)) { Bit32u timer_value = VMread32(VMCS_32BIT_GUEST_PREEMPTION_TIMER_VALUE); if (timer_value == 0) { BX_CPU_THIS_PTR pending_vmx_timer_expired = 1; BX_CPU_THIS_PTR async_event = 1; } else { // activate VMX preemption timer BX_DEBUG(("VMX preemption timer active")); BX_CPU_THIS_PTR pending_vmx_timer_expired = 0; BX_CPU_THIS_PTR lapic.set_vmx_preemption_timer(timer_value); } } #endif /////////////////////////////////////////////////////// // STEP 7: Inject events to the guest /////////////////////////////////////////////////////// VMenterInjectEvents(); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPTRLD(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMPTRLD in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_VMPTRLD); } if (CPL != 0) { BX_ERROR(("VMPTRLD with CPL!=0 willcause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u pAddr = read_virtual_qword(i->seg(), eaddr); // keep 64-bit if ((pAddr & 0xfff) != 0 || ! IsValidPhyAddr(pAddr)) { BX_ERROR(("VMFAIL: invalid or not page aligned physical address !")); VMfail(VMXERR_VMPTRLD_INVALID_PHYSICAL_ADDRESS); BX_NEXT_INSTR(i); } if (pAddr == BX_CPU_THIS_PTR vmxonptr) { BX_ERROR(("VMFAIL: VMPTRLD with VMXON ptr !")); VMfail(VMXERR_VMPTRLD_WITH_VMXON_PTR); } else { Bit32u revision = VMXReadRevisionID((bx_phy_address) pAddr); if (revision != VMX_VMCS_REVISION_ID) { BX_ERROR(("VMPTRLD: not expected (%d != %d) VMCS revision id !", revision, VMX_VMCS_REVISION_ID)); VMfail(VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID); } else { set_VMCSPTR(pAddr); VMsucceed(); } } #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPTRST(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMPTRST in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_VMPTRST); } if (CPL != 0) { BX_ERROR(("VMPTRST with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword(i->seg(), eaddr, BX_CPU_THIS_PTR vmcsptr); VMsucceed(); #endif BX_NEXT_INSTR(i); } BX_CPP_INLINE Bit32u rotate_r(Bit32u val_32) { return (val_32 >> 8) | (val_32 << 24); } BX_CPP_INLINE Bit32u rotate_l(Bit32u val_32) { return (val_32 << 8) | (val_32 >> 24); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMREAD_EdGd(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMREAD in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_VMREAD, BX_READ); } if (CPL != 0) { BX_ERROR(("VMREAD with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } if (! VMCSPTR_VALID()) { BX_ERROR(("VMFAIL: VMREAD with invalid VMCS ptr !")); VMfailInvalid(); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { if (BX_READ_64BIT_REG_HIGH(i->src())) { BX_ERROR(("VMREAD: not supported field (upper 32-bit not zero)")); VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS); BX_NEXT_INSTR(i); } } #endif unsigned encoding = BX_READ_32BIT_REG(i->src()); if (vmcs_field_offset(encoding) == 0xffffffff) { BX_ERROR(("VMREAD: not supported field 0x%08x", encoding)); VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS); BX_NEXT_INSTR(i); } unsigned width = VMCS_FIELD_WIDTH(encoding); Bit64u field_64; if(width == VMCS_FIELD_WIDTH_16BIT) { field_64 = VMread16(encoding); } else if(width == VMCS_FIELD_WIDTH_32BIT) { // the real hardware write access rights rotated if (encoding >= VMCS_32BIT_GUEST_ES_ACCESS_RIGHTS && encoding <= VMCS_32BIT_GUEST_TR_ACCESS_RIGHTS) field_64 = rotate_r(VMread32(encoding)); else field_64 = VMread32(encoding); } else if(width == VMCS_FIELD_WIDTH_64BIT) { if (IS_VMCS_FIELD_HI(encoding)) field_64 = VMread32(encoding); else field_64 = VMread64(encoding); } else { field_64 = VMread_natural(encoding); } #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { if (i->modC0()) { BX_WRITE_64BIT_REG(i->dst(), field_64); } else { Bit64u eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_qword_64(i->seg(), eaddr, field_64); } } else #endif { Bit32u field_32 = GET32L(field_64); if (i->modC0()) { BX_WRITE_32BIT_REGZ(i->dst(), field_32); } else { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword_32(i->seg(), eaddr, field_32); } } VMsucceed(); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMWRITE_GdEd(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMWRITE in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_VMWRITE, BX_WRITE); } if (CPL != 0) { BX_ERROR(("VMWRITE with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } if (! VMCSPTR_VALID()) { BX_ERROR(("VMFAIL: VMWRITE with invalid VMCS ptr !")); VMfailInvalid(); BX_NEXT_INSTR(i); } Bit64u val_64; Bit32u val_32; #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { if (i->modC0()) { val_64 = BX_READ_64BIT_REG(i->src()); } else { Bit64u eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); val_64 = read_virtual_qword_64(i->seg(), eaddr); } if (BX_READ_64BIT_REG_HIGH(i->dst())) { BX_ERROR(("VMWRITE: not supported field (upper 32-bit not zero)")); VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS); BX_NEXT_INSTR(i); } val_32 = GET32L(val_64); } else #endif { if (i->modC0()) { val_32 = BX_READ_32BIT_REG(i->src()); } else { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); val_32 = read_virtual_dword_32(i->seg(), eaddr); } val_64 = (Bit64u) val_32; } Bit32u encoding = BX_READ_32BIT_REG(i->dst()); if (vmcs_field_offset(encoding) == 0xffffffff) { BX_ERROR(("VMWRITE: not supported field 0x%08x", encoding)); VMfail(VMXERR_UNSUPPORTED_VMCS_COMPONENT_ACCESS); BX_NEXT_INSTR(i); } if (VMCS_FIELD_TYPE(encoding) == VMCS_FIELD_TYPE_READ_ONLY) { BX_ERROR(("VMWRITE: write to read only field 0x%08x", encoding)); VMfail(VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT); BX_NEXT_INSTR(i); } unsigned width = VMCS_FIELD_WIDTH(encoding); if(width == VMCS_FIELD_WIDTH_16BIT) { VMwrite16(encoding, val_32 & 0xffff); } else if(width == VMCS_FIELD_WIDTH_32BIT) { // the real hardware write access rights rotated if (encoding >= VMCS_32BIT_GUEST_ES_ACCESS_RIGHTS && encoding <= VMCS_32BIT_GUEST_TR_ACCESS_RIGHTS) VMwrite32(encoding, rotate_l(val_32)); else VMwrite32(encoding, val_32); } else if(width == VMCS_FIELD_WIDTH_64BIT) { if (IS_VMCS_FIELD_HI(encoding)) VMwrite32(encoding, val_32); else VMwrite64(encoding, val_64); } else { VMwrite_natural(encoding, (bx_address) val_64); } VMsucceed(); #endif BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMCLEAR(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: VMCLEAR in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_VMCLEAR); } if (CPL != 0) { BX_ERROR(("VMCLEAR with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u pAddr = read_virtual_qword(i->seg(), eaddr); // keep 64-bit if ((pAddr & 0xfff) != 0 || ! IsValidPhyAddr(pAddr)) { BX_ERROR(("VMFAIL: VMCLEAR with invalid physical address!")); VMfail(VMXERR_VMCLEAR_WITH_INVALID_ADDR); BX_NEXT_INSTR(i); } if (pAddr == BX_CPU_THIS_PTR vmxonptr) { BX_ERROR(("VMFAIL: VMLEAR with VMXON ptr !")); VMfail(VMXERR_VMCLEAR_WITH_VMXON_VMCS_PTR); } else { // ensure that data for VMCS referenced by the operand is in memory // initialize implementation-specific data in VMCS region // clear VMCS launch state Bit32u launch_state = VMCS_STATE_CLEAR; access_write_physical(pAddr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, &launch_state); BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr + VMCS_LAUNCH_STATE_FIELD_ADDR, 4, BX_WRITE, BX_VMCS_ACCESS, (Bit8u*)(&launch_state)); if (pAddr == BX_CPU_THIS_PTR vmcsptr) { BX_CPU_THIS_PTR vmcsptr = BX_INVALID_VMCSPTR; BX_CPU_THIS_PTR vmcshostptr = 0; } VMsucceed(); } #endif BX_NEXT_INSTR(i); } #if BX_CPU_LEVEL >= 6 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVEPT(bxInstruction_c *i) { #if BX_SUPPORT_VMX >= 2 if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: INVEPT in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_INVEPT, BX_READ); } if (CPL != 0) { BX_ERROR(("INVEPT with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } bx_address type; if (i->os64L()) { type = BX_READ_64BIT_REG(i->dst()); } else { type = BX_READ_32BIT_REG(i->dst()); } BxPackedXmmRegister inv_eptp; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword(i->seg(), eaddr, (Bit8u *) &inv_eptp); switch(type) { case BX_INVEPT_INVVPID_SINGLE_CONTEXT_INVALIDATION: if (! is_eptptr_valid(inv_eptp.xmm64u(0))) { BX_ERROR(("INVEPT: invalid EPTPTR value !")); VMfail(VMXERR_INVALID_INVEPT_INVVPID); BX_NEXT_TRACE(i); } TLB_flush(); // Invalidate mappings associated with EPTP[51:12] break; case BX_INVEPT_INVVPID_ALL_CONTEXT_INVALIDATION: TLB_flush(); // Invalidate mappings associated with all EPTPs break; default: BX_ERROR(("INVEPT: not supported type !")); VMfail(VMXERR_INVALID_INVEPT_INVVPID); BX_NEXT_TRACE(i); } BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_INVEPT, type); VMsucceed(); #else BX_INFO(("INVEPT: required VMXx2 support, use --enable-vmx=2 option")); exception(BX_UD_EXCEPTION, 0); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVVPID(bxInstruction_c *i) { #if BX_SUPPORT_VMX >= 2 if (! BX_CPU_THIS_PTR in_vmx || ! protected_mode() || BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_COMPAT) exception(BX_UD_EXCEPTION, 0); if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: INVVPID in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_INVVPID, BX_READ); } if (CPL != 0) { BX_ERROR(("INVVPID with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } bx_address type; if (i->os64L()) { type = BX_READ_64BIT_REG(i->dst()); } else { type = BX_READ_32BIT_REG(i->dst()); } BxPackedXmmRegister invvpid_desc; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword(i->seg(), eaddr, (Bit8u *) &invvpid_desc); if (invvpid_desc.xmm64u(0) > 0xffff) { BX_ERROR(("INVVPID: INVVPID_DESC reserved bits set")); VMfail(VMXERR_INVALID_INVEPT_INVVPID); BX_NEXT_TRACE(i); } Bit16u vpid = invvpid_desc.xmm16u(0); if (vpid == 0 && type != BX_INVEPT_INVVPID_ALL_CONTEXT_INVALIDATION) { BX_ERROR(("INVVPID with VPID=0")); VMfail(VMXERR_INVALID_INVEPT_INVVPID); BX_NEXT_TRACE(i); } switch(type) { case BX_INVEPT_INVVPID_INDIVIDUAL_ADDRESS_INVALIDATION: if (! IsCanonical(invvpid_desc.xmm64u(1))) { BX_ERROR(("INVVPID: non canonical LADDR single context invalidation")); VMfail(VMXERR_INVALID_INVEPT_INVVPID); BX_NEXT_TRACE(i); } TLB_flush(); // invalidate all mappings for address LADDR tagged with VPID break; case BX_INVEPT_INVVPID_SINGLE_CONTEXT_INVALIDATION: TLB_flush(); // invalidate all mappings tagged with VPID break; case BX_INVEPT_INVVPID_ALL_CONTEXT_INVALIDATION: TLB_flush(); // invalidate all mappings tagged with VPID <> 0 break; case BX_INVEPT_INVVPID_SINGLE_CONTEXT_NON_GLOBAL_INVALIDATION: TLB_flushNonGlobal(); // invalidate all mappings tagged with VPID except globals break; default: BX_ERROR(("INVVPID: not supported type !")); VMfail(VMXERR_INVALID_INVEPT_INVVPID); BX_NEXT_TRACE(i); } BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_INVVPID, type); VMsucceed(); #else BX_INFO(("INVVPID: required VMXx2 support, use --enable-vmx=2 option")); exception(BX_UD_EXCEPTION, 0); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::INVPCID(bxInstruction_c *i) { if (v8086_mode()) { BX_ERROR(("INVPCID: not recognized in v8086 mode")); exception(BX_UD_EXCEPTION, 0); } #if BX_SUPPORT_VMX // INVPCID will always #UD in legacy VMX mode if (BX_CPU_THIS_PTR in_vmx_guest) { if (! SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_INVPCID)) { BX_ERROR(("INVPCID in VMX guest: not allowed to use instruction !")); exception(BX_UD_EXCEPTION, 0); } #if BX_SUPPORT_VMX >= 2 if (VMEXIT(VMX_VM_EXEC_CTRL2_INVLPG_VMEXIT)) { BX_ERROR(("VMEXIT: INVPCID in VMX non-root operation")); VMexit_Instruction(i, VMX_VMEXIT_INVPCID, BX_READ); } #endif } #endif if (CPL != 0) { BX_ERROR(("INVPCID with CPL!=0 cause #GP(0)")); exception(BX_GP_EXCEPTION, 0); } bx_address type; #if BX_SUPPORT_X86_64 if (i->os64L()) { type = BX_READ_64BIT_REG(i->dst()); } else #endif { type = BX_READ_32BIT_REG(i->dst()); } BxPackedXmmRegister invpcid_desc; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); read_virtual_dqword(i->seg(), eaddr, (Bit8u *) &invpcid_desc); if (invpcid_desc.xmm64u(0) > 0xfff) { BX_ERROR(("INVPCID: INVPCID_DESC reserved bits set")); exception(BX_GP_EXCEPTION, 0); } Bit16u pcid = invpcid_desc.xmm16u(0) & 0xfff; switch(type) { case BX_INVPCID_INDIVIDUAL_ADDRESS_NON_GLOBAL_INVALIDATION: #if BX_SUPPORT_X86_64 if (! IsCanonical(invpcid_desc.xmm64u(1))) { BX_ERROR(("INVPCID: non canonical LADDR single context invalidation")); exception(BX_GP_EXCEPTION, 0); } #endif if (! BX_CPU_THIS_PTR cr4.get_PCIDE() && pcid != 0) { BX_ERROR(("INVPCID: invalid PCID")); exception(BX_GP_EXCEPTION, 0); } TLB_flushNonGlobal(); // Invalidate all mappings for LADDR tagged with PCID except globals break; case BX_INVPCID_SINGLE_CONTEXT_NON_GLOBAL_INVALIDATION: if (! BX_CPU_THIS_PTR cr4.get_PCIDE() && pcid != 0) { BX_ERROR(("INVPCID: invalid PCID")); exception(BX_GP_EXCEPTION, 0); } TLB_flushNonGlobal(); // Invalidate all mappings tagged with PCID except globals break; case BX_INVPCID_ALL_CONTEXT_INVALIDATION: TLB_flush(); // Invalidate all mappings tagged with any PCID break; case BX_INVPCID_ALL_CONTEXT_NON_GLOBAL_INVALIDATION: TLB_flushNonGlobal(); // Invalidate all mappings tagged with any PCID except globals break; default: BX_ERROR(("INVPCID: not supported type !")); exception(BX_GP_EXCEPTION, 0); } BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_INVPCID, type); BX_NEXT_TRACE(i); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::GETSEC(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 6 if (! BX_CPU_THIS_PTR cr4.get_SMXE()) exception(BX_UD_EXCEPTION, 0); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { BX_ERROR(("VMEXIT: GETSEC in VMX non-root operation")); VMexit(VMX_VMEXIT_GETSEC, 0); } #endif BX_PANIC(("GETSEC: SMX is not implemented yet !")); #endif BX_NEXT_TRACE(i); } #if BX_SUPPORT_VMX void BX_CPU_C::register_vmx_state(bx_param_c *parent) { if (! bx_cpuid_support_vmx()) return; // register VMX state for save/restore param tree bx_list_c *vmx = new bx_list_c(parent, "VMX"); BXRS_HEX_PARAM_FIELD(vmx, vmcsptr, BX_CPU_THIS_PTR vmcsptr); BXRS_HEX_PARAM_FIELD(vmx, vmxonptr, BX_CPU_THIS_PTR vmxonptr); BXRS_PARAM_BOOL(vmx, in_vmx, BX_CPU_THIS_PTR in_vmx); BXRS_PARAM_BOOL(vmx, in_vmx_guest, BX_CPU_THIS_PTR in_vmx_guest); BXRS_PARAM_BOOL(vmx, in_smm_vmx, BX_CPU_THIS_PTR in_smm_vmx); BXRS_PARAM_BOOL(vmx, in_smm_vmx_guest, BX_CPU_THIS_PTR in_smm_vmx_guest); BXRS_PARAM_BOOL(vmx, vmx_interrupt_window, BX_CPU_THIS_PTR vmx_interrupt_window); #if BX_SUPPORT_VMX >= 2 BXRS_PARAM_BOOL(vmx, pending_vmx_timer_expired, BX_CPU_THIS_PTR pending_vmx_timer_expired); #endif bx_list_c *vmcache = new bx_list_c(vmx, "VMCS_CACHE"); // // VM-Execution Control Fields // bx_list_c *vmexec_ctrls = new bx_list_c(vmcache, "VMEXEC_CTRLS"); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vmexec_ctrls1, BX_CPU_THIS_PTR vmcs.vmexec_ctrls1); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vmexec_ctrls2, BX_CPU_THIS_PTR vmcs.vmexec_ctrls2); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vmexec_ctrls3, BX_CPU_THIS_PTR vmcs.vmexec_ctrls3); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_exceptions_bitmap, BX_CPU_THIS_PTR vmcs.vm_exceptions_bitmap); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_pf_mask, BX_CPU_THIS_PTR vmcs.vm_pf_mask); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_pf_match, BX_CPU_THIS_PTR vmcs.vm_pf_match); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, io_bitmap_addr1, BX_CPU_THIS_PTR vmcs.io_bitmap_addr[0]); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, io_bitmap_addr2, BX_CPU_THIS_PTR vmcs.io_bitmap_addr[1]); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, msr_bitmap_addr, BX_CPU_THIS_PTR vmcs.msr_bitmap_addr); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr0_mask, BX_CPU_THIS_PTR vmcs.vm_cr0_mask); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr0_read_shadow, BX_CPU_THIS_PTR vmcs.vm_cr0_read_shadow); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr4_mask, BX_CPU_THIS_PTR vmcs.vm_cr4_mask); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr4_read_shadow, BX_CPU_THIS_PTR vmcs.vm_cr4_read_shadow); BXRS_DEC_PARAM_FIELD(vmexec_ctrls, vm_cr3_target_cnt, BX_CPU_THIS_PTR vmcs.vm_cr3_target_cnt); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr3_target_value1, BX_CPU_THIS_PTR vmcs.vm_cr3_target_value[0]); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr3_target_value2, BX_CPU_THIS_PTR vmcs.vm_cr3_target_value[1]); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr3_target_value3, BX_CPU_THIS_PTR vmcs.vm_cr3_target_value[2]); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_cr3_target_value4, BX_CPU_THIS_PTR vmcs.vm_cr3_target_value[3]); #if BX_SUPPORT_X86_64 BXRS_HEX_PARAM_FIELD(vmexec_ctrls, virtual_apic_page_addr, BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vm_tpr_threshold, BX_CPU_THIS_PTR vmcs.vm_tpr_threshold); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, apic_access_page, BX_CPU_THIS_PTR vmcs.apic_access_page); #endif #if BX_SUPPORT_VMX >= 2 BXRS_HEX_PARAM_FIELD(vmexec_ctrls, eptptr, BX_CPU_THIS_PTR vmcs.eptptr); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, vpid, BX_CPU_THIS_PTR vmcs.vpid); #endif BXRS_HEX_PARAM_FIELD(vmexec_ctrls, executive_vmcsptr, BX_CPU_THIS_PTR vmcs.executive_vmcsptr); #if BX_SUPPORT_VMX >= 2 BXRS_HEX_PARAM_FIELD(vmexec_ctrls, pause_loop_exiting_gap, BX_CPU_THIS_PTR vmcs.pause_loop_exiting_gap); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, pause_loop_exiting_window, BX_CPU_THIS_PTR vmcs.pause_loop_exiting_window); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, first_pause_time, BX_CPU_THIS_PTR vmcs.first_pause_time); BXRS_HEX_PARAM_FIELD(vmexec_ctrls, last_pause_time, BX_CPU_THIS_PTR vmcs.last_pause_time); #endif // // VM-Exit Control Fields // bx_list_c *vmexit_ctrls = new bx_list_c(vmcache, "VMEXIT_CTRLS"); BXRS_HEX_PARAM_FIELD(vmexit_ctrls, vmexit_ctrls, BX_CPU_THIS_PTR vmcs.vmexit_ctrls); BXRS_DEC_PARAM_FIELD(vmexit_ctrls, vmexit_msr_store_cnt, BX_CPU_THIS_PTR vmcs.vmexit_msr_store_cnt); BXRS_HEX_PARAM_FIELD(vmexit_ctrls, vmexit_msr_store_addr, BX_CPU_THIS_PTR vmcs.vmexit_msr_store_addr); BXRS_DEC_PARAM_FIELD(vmexit_ctrls, vmexit_msr_load_cnt, BX_CPU_THIS_PTR vmcs.vmexit_msr_load_cnt); BXRS_HEX_PARAM_FIELD(vmexit_ctrls, vmexit_msr_load_addr, BX_CPU_THIS_PTR vmcs.vmexit_msr_load_addr); // // VM-Entry Control Fields // bx_list_c *vmentry_ctrls = new bx_list_c(vmcache, "VMENTRY_CTRLS"); BXRS_HEX_PARAM_FIELD(vmentry_ctrls, vmentry_ctrls, BX_CPU_THIS_PTR vmcs.vmentry_ctrls); BXRS_DEC_PARAM_FIELD(vmentry_ctrls, vmentry_msr_load_cnt, BX_CPU_THIS_PTR vmcs.vmentry_msr_load_cnt); BXRS_HEX_PARAM_FIELD(vmentry_ctrls, vmentry_msr_load_addr, BX_CPU_THIS_PTR vmcs.vmentry_msr_load_addr); BXRS_HEX_PARAM_FIELD(vmentry_ctrls, vmentry_interr_info, BX_CPU_THIS_PTR vmcs.vmentry_interr_info); BXRS_HEX_PARAM_FIELD(vmentry_ctrls, vmentry_excep_err_code, BX_CPU_THIS_PTR vmcs.vmentry_excep_err_code); BXRS_HEX_PARAM_FIELD(vmentry_ctrls, vmentry_instr_length, BX_CPU_THIS_PTR vmcs.vmentry_instr_length); // // VMCS Host State // bx_list_c *host = new bx_list_c(vmcache, "HOST_STATE"); #undef NEED_CPU_REG_SHORTCUTS BXRS_HEX_PARAM_FIELD(host, CR0, BX_CPU_THIS_PTR vmcs.host_state.cr0); BXRS_HEX_PARAM_FIELD(host, CR3, BX_CPU_THIS_PTR vmcs.host_state.cr3); BXRS_HEX_PARAM_FIELD(host, CR4, BX_CPU_THIS_PTR vmcs.host_state.cr4); BXRS_HEX_PARAM_FIELD(host, ES, BX_CPU_THIS_PTR vmcs.host_state.segreg_selector[BX_SEG_REG_ES]); BXRS_HEX_PARAM_FIELD(host, CS, BX_CPU_THIS_PTR vmcs.host_state.segreg_selector[BX_SEG_REG_CS]); BXRS_HEX_PARAM_FIELD(host, SS, BX_CPU_THIS_PTR vmcs.host_state.segreg_selector[BX_SEG_REG_SS]); BXRS_HEX_PARAM_FIELD(host, DS, BX_CPU_THIS_PTR vmcs.host_state.segreg_selector[BX_SEG_REG_DS]); BXRS_HEX_PARAM_FIELD(host, FS, BX_CPU_THIS_PTR vmcs.host_state.segreg_selector[BX_SEG_REG_FS]); BXRS_HEX_PARAM_FIELD(host, FS_BASE, BX_CPU_THIS_PTR vmcs.host_state.fs_base); BXRS_HEX_PARAM_FIELD(host, GS, BX_CPU_THIS_PTR vmcs.host_state.segreg_selector[BX_SEG_REG_GS]); BXRS_HEX_PARAM_FIELD(host, GS_BASE, BX_CPU_THIS_PTR vmcs.host_state.gs_base); BXRS_HEX_PARAM_FIELD(host, GDTR_BASE, BX_CPU_THIS_PTR vmcs.host_state.gdtr_base); BXRS_HEX_PARAM_FIELD(host, IDTR_BASE, BX_CPU_THIS_PTR vmcs.host_state.idtr_base); BXRS_HEX_PARAM_FIELD(host, TR, BX_CPU_THIS_PTR vmcs.host_state.tr_selector); BXRS_HEX_PARAM_FIELD(host, TR_BASE, BX_CPU_THIS_PTR vmcs.host_state.tr_base); BXRS_HEX_PARAM_FIELD(host, RSP, BX_CPU_THIS_PTR vmcs.host_state.rsp); BXRS_HEX_PARAM_FIELD(host, RIP, BX_CPU_THIS_PTR vmcs.host_state.rip); BXRS_HEX_PARAM_FIELD(host, sysenter_esp_msr, BX_CPU_THIS_PTR vmcs.host_state.sysenter_esp_msr); BXRS_HEX_PARAM_FIELD(host, sysenter_eip_msr, BX_CPU_THIS_PTR vmcs.host_state.sysenter_eip_msr); BXRS_HEX_PARAM_FIELD(host, sysenter_cs_msr, BX_CPU_THIS_PTR vmcs.host_state.sysenter_cs_msr); #if BX_SUPPORT_VMX >= 2 BXRS_HEX_PARAM_FIELD(host, pat_msr, BX_CPU_THIS_PTR vmcs.host_state.pat_msr); #if BX_SUPPORT_X86_64 BXRS_HEX_PARAM_FIELD(host, efer_msr, BX_CPU_THIS_PTR vmcs.host_state.efer_msr); #endif #endif } #endif // BX_SUPPORT_VMX bochs-2.6/cpu/shift16.cc0000644000175000017500000004044412020641453014722 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: shift16.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EwGwM(bxInstruction_c *i) { Bit32u temp_32, result_32; unsigned count; unsigned of, cf; /* op1:op2 << count. result stored in op1 */ if (i->getIaOpcode() == BX_IA_SHLD_EwGw) count = CL; else // BX_IA_SHLD_EwGwIb count = i->Ib(); count &= 0x1f; // use only 5 LSB's bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if (count) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* count < 32, since only lower 5 bits used */ temp_32 = ((Bit32u)(op1_16) << 16) | (op2_16); // double formed by op1:op2 result_32 = temp_32 << count; // hack to act like x86 SHLD when count > 16 if (count > 16) { // when count > 16 actually shifting op1:op2:op2 << count, // it is the same as shifting op2:op2 by count-16 result_32 |= (op1_16 << (count - 16)); } Bit16u result_16 = (Bit16u)(result_32 >> 16); write_RMW_virtual_word(result_16); SET_FLAGS_OSZAPC_LOGIC_16(result_16); cf = (temp_32 >> (32 - count)) & 0x1; of = cf ^ (result_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHLD_EwGwR(bxInstruction_c *i) { Bit32u temp_32, result_32; unsigned count; unsigned of, cf; /* op1:op2 << count. result stored in op1 */ if (i->getIaOpcode() == BX_IA_SHLD_EwGw) count = CL; else // BX_IA_SHLD_EwGwIb count = i->Ib(); count &= 0x1f; // use only 5 LSB's if (count) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* count < 32, since only lower 5 bits used */ temp_32 = ((Bit32u)(op1_16) << 16) | (op2_16); // double formed by op1:op2 result_32 = temp_32 << count; // hack to act like x86 SHLD when count > 16 if (count > 16) { // when count > 16 actually shifting op1:op2:op2 << count, // it is the same as shifting op2:op2 by count-16 result_32 |= (op1_16 << (count - 16)); } Bit16u result_16 = (Bit16u)(result_32 >> 16); BX_WRITE_16BIT_REG(i->dst(), result_16); SET_FLAGS_OSZAPC_LOGIC_16(result_16); cf = (temp_32 >> (32 - count)) & 0x1; of = cf ^ (result_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EwGwM(bxInstruction_c *i) { Bit32u temp_32, result_32; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_SHRD_EwGw) count = CL; else // BX_IA_SHRD_EwGwIb count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if (count) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* count < 32, since only lower 5 bits used */ temp_32 = (op2_16 << 16) | op1_16; // double formed by op2:op1 result_32 = temp_32 >> count; // hack to act like x86 SHRD when count > 16 if (count > 16) { // when count > 16 actually shifting op2:op2:op1 >> count, // it is the same as shifting op2:op2 by count-16 result_32 |= (op1_16 << (32 - count)); } Bit16u result_16 = (Bit16u) result_32; write_RMW_virtual_word(result_16); SET_FLAGS_OSZAPC_LOGIC_16(result_16); cf = (op1_16 >> (count - 1)) & 0x1; of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result14 ^ result15 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHRD_EwGwR(bxInstruction_c *i) { Bit32u temp_32, result_32; unsigned count; unsigned cf, of; if (i->getIaOpcode() == BX_IA_SHRD_EwGw) count = CL; else // BX_IA_SHRD_EwGwIb count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ if (count) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* count < 32, since only lower 5 bits used */ temp_32 = (op2_16 << 16) | op1_16; // double formed by op2:op1 result_32 = temp_32 >> count; // hack to act like x86 SHRD when count > 16 if (count > 16) { // when count > 16 actually shifting op2:op2:op1 >> count, // it is the same as shifting op2:op2 by count-16 result_32 |= (op1_16 << (32 - count)); } Bit16u result_16 = (Bit16u) result_32; BX_WRITE_16BIT_REG(i->dst(), result_16); SET_FLAGS_OSZAPC_LOGIC_16(result_16); cf = (op1_16 >> (count - 1)) & 0x1; of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result14 ^ result15 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EwM(bxInstruction_c *i) { unsigned count; unsigned bit0, bit15; if (i->getIaOpcode() == BX_IA_ROL_Ew) count = CL; else count = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if ((count & 0x0f) == 0) { if (count & 0x10) { bit0 = (op1_16 & 0x1); bit15 = (op1_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0); } } else { count &= 0x0f; // only use bottom 4 bits Bit16u result_16 = (op1_16 << count) | (op1_16 >> (16 - count)); write_RMW_virtual_word(result_16); bit0 = (result_16 & 0x1); bit15 = (result_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROL_EwR(bxInstruction_c *i) { unsigned count; unsigned bit0, bit15; if (i->getIaOpcode() == BX_IA_ROL_Ew) count = CL; else count = i->Ib(); Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); if ((count & 0x0f) == 0) { if (count & 0x10) { bit0 = (op1_16 & 0x1); bit15 = (op1_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0); } } else { count &= 0x0f; // only use bottom 4 bits Bit16u result_16 = (op1_16 << count) | (op1_16 >> (16 - count)); BX_WRITE_16BIT_REG(i->dst(), result_16); bit0 = (result_16 & 0x1); bit15 = (result_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(bit0 ^ bit15, bit0); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EwM(bxInstruction_c *i) { unsigned count; unsigned bit14, bit15; if (i->getIaOpcode() == BX_IA_ROR_Ew) count = CL; else count = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if ((count & 0x0f) == 0) { if (count & 0x10) { bit14 = (op1_16 >> 14) & 1; bit15 = (op1_16 >> 15) & 1; // of = result14 ^ result15 SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15); } } else { count &= 0x0f; // use only 4 LSB's Bit16u result_16 = (op1_16 >> count) | (op1_16 << (16 - count)); write_RMW_virtual_word(result_16); bit14 = (result_16 >> 14) & 1; bit15 = (result_16 >> 15) & 1; // of = result14 ^ result15 SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::ROR_EwR(bxInstruction_c *i) { unsigned count; unsigned bit14, bit15; if (i->getIaOpcode() == BX_IA_ROR_Ew) count = CL; else count = i->Ib(); Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); if ((count & 0x0f) == 0) { if (count & 0x10) { bit14 = (op1_16 >> 14) & 1; bit15 = (op1_16 >> 15) & 1; // of = result14 ^ result15 SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15); } } else { count &= 0x0f; // use only 4 LSB's Bit16u result_16 = (op1_16 >> count) | (op1_16 << (16 - count)); BX_WRITE_16BIT_REG(i->dst(), result_16); bit14 = (result_16 >> 14) & 1; bit15 = (result_16 >> 15) & 1; // of = result14 ^ result15 SET_FLAGS_OxxxxC(bit14 ^ bit15, bit15); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EwM(bxInstruction_c *i) { Bit16u result_16; unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_RCL_Ew) count = CL; else count = i->Ib(); count = (count & 0x1f) % 17; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if (count) { if (count==1) { result_16 = (op1_16 << 1) | getB_CF(); } else if (count==16) { result_16 = (getB_CF() << 15) | (op1_16 >> 1); } else { // 2..15 result_16 = (op1_16 << count) | (getB_CF() << (count - 1)) | (op1_16 >> (17 - count)); } write_RMW_virtual_word(result_16); cf = (op1_16 >> (16 - count)) & 0x1; of = cf ^ (result_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCL_EwR(bxInstruction_c *i) { Bit16u result_16; unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_RCL_Ew) count = CL; else count = i->Ib(); count = (count & 0x1f) % 17; if (count) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); if (count==1) { result_16 = (op1_16 << 1) | getB_CF(); } else if (count==16) { result_16 = (getB_CF() << 15) | (op1_16 >> 1); } else { // 2..15 result_16 = (op1_16 << count) | (getB_CF() << (count - 1)) | (op1_16 >> (17 - count)); } BX_WRITE_16BIT_REG(i->dst(), result_16); cf = (op1_16 >> (16 - count)) & 0x1; of = cf ^ (result_16 >> 15); // of = cf ^ result15 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EwM(bxInstruction_c *i) { unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_RCR_Ew) count = CL; else count = i->Ib(); count = (count & 0x1f) % 17; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if (count) { Bit16u result_16 = (op1_16 >> count) | (getB_CF() << (16 - count)) | (op1_16 << (17 - count)); write_RMW_virtual_word(result_16); cf = (op1_16 >> (count - 1)) & 0x1; of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result15 ^ result14 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RCR_EwR(bxInstruction_c *i) { unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_RCR_Ew) count = CL; else count = i->Ib(); count = (count & 0x1f) % 17; if (count) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit16u result_16 = (op1_16 >> count) | (getB_CF() << (16 - count)) | (op1_16 << (17 - count)); BX_WRITE_16BIT_REG(i->dst(), result_16); cf = (op1_16 >> (count - 1)) & 0x1; of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; // of = result15 ^ result14 SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EwM(bxInstruction_c *i) { Bit16u result_16; unsigned count; unsigned of = 0, cf = 0; if (i->getIaOpcode() == BX_IA_SHL_Ew) count = CL; else count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if (count) { if (count <= 16) { result_16 = (op1_16 << count); cf = (op1_16 >> (16 - count)) & 0x1; of = cf ^ (result_16 >> 15); // of = cf ^ result15 } else { result_16 = 0; } write_RMW_virtual_word(result_16); SET_FLAGS_OSZAPC_LOGIC_16(result_16); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHL_EwR(bxInstruction_c *i) { Bit16u result_16; unsigned count; unsigned of = 0, cf = 0; if (i->getIaOpcode() == BX_IA_SHL_Ew) count = CL; else count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ if (count) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); if (count <= 16) { result_16 = (op1_16 << count); cf = (op1_16 >> (16 - count)) & 0x1; of = cf ^ (result_16 >> 15); // of = cf ^ result15 } else { result_16 = 0; } BX_WRITE_16BIT_REG(i->dst(), result_16); SET_FLAGS_OSZAPC_LOGIC_16(result_16); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EwM(bxInstruction_c *i) { unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_SHR_Ew) count = CL; else count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if (count) { Bit16u result_16 = (op1_16 >> count); write_RMW_virtual_word(result_16); cf = (op1_16 >> (count - 1)) & 0x1; // note, that of == result15 if count == 1 and // of == 0 if count >= 2 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; SET_FLAGS_OSZAPC_LOGIC_16(result_16); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SHR_EwR(bxInstruction_c *i) { unsigned count; unsigned of, cf; if (i->getIaOpcode() == BX_IA_SHR_Ew) count = CL; else count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ if (count) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit16u result_16 = (op1_16 >> count); BX_WRITE_16BIT_REG(i->dst(), result_16); cf = (op1_16 >> (count - 1)) & 0x1; // note, that of == result15 if count == 1 and // of == 0 if count >= 2 of = ((Bit16u)((result_16 << 1) ^ result_16) >> 15) & 0x1; SET_FLAGS_OSZAPC_LOGIC_16(result_16); SET_FLAGS_OxxxxC(of, cf); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EwM(bxInstruction_c *i) { unsigned count, cf; if (i->getIaOpcode() == BX_IA_SAR_Ew) count = CL; else count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit16u op1_16 = read_RMW_virtual_word(i->seg(), eaddr); if (count) { Bit16u result_16 = ((Bit16s) op1_16) >> count; cf = (((Bit16s) op1_16) >> (count - 1)) & 0x1; SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* signed overflow cannot happen in SAR instruction */ SET_FLAGS_OxxxxC(0, cf); write_RMW_virtual_word(result_16); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAR_EwR(bxInstruction_c *i) { unsigned count, cf; if (i->getIaOpcode() == BX_IA_SAR_Ew) count = CL; else count = i->Ib(); count &= 0x1f; /* use only 5 LSB's */ if (count) { Bit16u op1_16 = BX_READ_16BIT_REG(i->dst()); Bit16u result_16 = ((Bit16s) op1_16) >> count; BX_WRITE_16BIT_REG(i->dst(), result_16); cf = (((Bit16s) op1_16) >> (count - 1)) & 0x1; SET_FLAGS_OSZAPC_LOGIC_16(result_16); /* signed overflow cannot happen in SAR instruction */ SET_FLAGS_OxxxxC(0, cf); } BX_NEXT_INSTR(i); } bochs-2.6/cpu/logical8.cc0000644000175000017500000001732312020641453015140 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: logical8.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EbGbM(bxInstruction_c *i) { Bit8u op1, op2; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = read_RMW_virtual_byte(i->seg(), eaddr); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 ^= op2; write_RMW_virtual_byte(op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GbEbR(bxInstruction_c *i) { Bit8u op1, op2; op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 ^= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GbEbM(bxInstruction_c *i) { Bit8u op1, op2; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op2 = read_virtual_byte(i->seg(), eaddr); op1 ^= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EbIbM(bxInstruction_c *i) { Bit8u op1, op2 = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = read_RMW_virtual_byte(i->seg(), eaddr); op1 ^= op2; write_RMW_virtual_byte(op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EbIbR(bxInstruction_c *i) { Bit8u op1, op2 = i->Ib(); op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1 ^= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EbIbM(bxInstruction_c *i) { Bit8u op1, op2 = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = read_RMW_virtual_byte(i->seg(), eaddr); op1 |= op2; write_RMW_virtual_byte(op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EbIbR(bxInstruction_c *i) { Bit8u op1, op2 = i->Ib(); op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1 |= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op1_8 = read_RMW_virtual_byte(i->seg(), eaddr); op1_8 = ~op1_8; write_RMW_virtual_byte(op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EbR(bxInstruction_c *i) { Bit8u op1_8 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1_8 = ~op1_8; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EbGbM(bxInstruction_c *i) { Bit8u op1, op2; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = read_RMW_virtual_byte(i->seg(), eaddr); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 |= op2; write_RMW_virtual_byte(op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GbEbR(bxInstruction_c *i) { Bit8u op1, op2; op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 |= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GbEbM(bxInstruction_c *i) { Bit8u op1, op2; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op2 = read_virtual_byte(i->seg(), eaddr); op1 |= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EbGbM(bxInstruction_c *i) { Bit8u op1, op2; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = read_RMW_virtual_byte(i->seg(), eaddr); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 &= op2; write_RMW_virtual_byte(op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GbEbR(bxInstruction_c *i) { Bit8u op1, op2; op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 &= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GbEbM(bxInstruction_c *i) { Bit8u op1, op2; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op2 = read_virtual_byte(i->seg(), eaddr); op1 &= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EbIbM(bxInstruction_c *i) { Bit8u op1, op2 = i->Ib(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = read_RMW_virtual_byte(i->seg(), eaddr); op1 &= op2; write_RMW_virtual_byte(op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EbIbR(bxInstruction_c *i) { Bit8u op1, op2 = i->Ib(); op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1 &= op2; BX_WRITE_8BIT_REGx(i->dst(), i->extend8bitL(), op1); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EbGbR(bxInstruction_c *i) { Bit8u op1, op2; op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 &= op2; SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EbGbM(bxInstruction_c *i) { Bit8u op1, op2; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1 = read_virtual_byte(i->seg(), eaddr); op2 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); op1 &= op2; SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EbIbR(bxInstruction_c *i) { Bit8u op1 = BX_READ_8BIT_REGx(i->dst(), i->extend8bitL()); op1 &= i->Ib(); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EbIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op1 = read_virtual_byte(i->seg(), eaddr); op1 &= i->Ib(); SET_FLAGS_OSZAPC_LOGIC_8(op1); BX_NEXT_INSTR(i); } bochs-2.6/cpu/bcd.cc0000644000175000017500000001135312020641453014163 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bcd.cc 10451 2011-07-06 20:01:18Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AAA(bxInstruction_c *i) { int tmpCF = 0, tmpAF = 0; /* * Note: This instruction incorrectly documented in Intel's materials. * The right description is: * * IF (((AL and 0FH) > 9) or (AF==1) * THEN * IF CPU<286 THEN { AL <- AL+6 } * ELSE { AX <- AX+6 } * AH <- AH+1 * CF <- 1 * AF <- 1 * ELSE * CF <- 0 * AF <- 0 * ENDIF * AL <- AL and 0Fh */ /* Validated against Intel Pentium family hardware. */ /* AAA affects the following flags: A,C */ if (((AL & 0x0f) > 9) || get_AF()) { AX = AX + 0x106; tmpAF = tmpCF = 1; } AL = AL & 0x0f; /* AAA affects also the following flags: Z,S,O,P */ /* modification of the flags is undocumented */ /* The following behaviour seems to match the P6 and its derived processors. */ SET_FLAGS_OSZAPC_LOGIC_8(AL); set_CF(tmpCF); set_AF(tmpAF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AAS(bxInstruction_c *i) { int tmpCF = 0, tmpAF = 0; /* AAS affects the following flags: A,C */ if (((AL & 0x0F) > 0x09) || get_AF()) { AX = AX - 0x106; tmpAF = tmpCF = 1; } AL = AL & 0x0f; /* AAS affects also the following flags: Z,S,O,P */ /* modification of the flags is undocumented */ /* The following behaviour seems to match the P6 and its derived processors. */ SET_FLAGS_OSZAPC_LOGIC_8(AL); set_CF(tmpCF); set_AF(tmpAF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AAM(bxInstruction_c *i) { Bit8u al, imm8 = i->Ib(); if (imm8 == 0) exception(BX_DE_EXCEPTION, 0); al = AL; AH = al / imm8; AL = al % imm8; /* modification of flags A,C,O is undocumented */ /* The following behaviour seems to match the P6 and its derived processors. */ SET_FLAGS_OSZAPC_LOGIC_8(AL); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AAD(bxInstruction_c *i) { Bit16u tmp = AH; tmp *= i->Ib(); tmp += AL; AX = (tmp & 0xff); /* modification of flags A,C,O is undocumented */ /* The following behaviour seems to match the P6 and its derived processors. */ SET_FLAGS_OSZAPC_LOGIC_8(AL); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DAA(bxInstruction_c *i) { Bit8u tmpAL = AL; int tmpCF = 0, tmpAF = 0; /* Validated against Intel Pentium family hardware. */ // DAA affects the following flags: S,Z,A,P,C if (((tmpAL & 0x0F) > 0x09) || get_AF()) { tmpCF = ((AL > 0xF9) || get_CF()); AL = AL + 0x06; tmpAF = 1; } if ((tmpAL > 0x99) || get_CF()) { AL = AL + 0x60; tmpCF = 1; } SET_FLAGS_OSZAPC_LOGIC_8(AL); set_CF(tmpCF); set_AF(tmpAF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::DAS(bxInstruction_c *i) { /* The algorithm for DAS is fashioned after the pseudo code in the * Pentium Processor Family Developer's Manual, volume 3. It seems * to have changed from earlier processor's manuals. I'm not sure * if this is a correction in the algorithm printed, or Intel has * changed the handling of instruction. Validated against Intel * Pentium family hardware. */ Bit8u tmpAL = AL; int tmpCF = 0, tmpAF = 0; /* DAS effect the following flags: A,C,S,Z,P */ if (((tmpAL & 0x0F) > 0x09) || get_AF()) { tmpCF = (AL < 0x06) || get_CF(); AL = AL - 0x06; tmpAF = 1; } if ((tmpAL > 0x99) || get_CF()) { AL = AL - 0x60; tmpCF = 1; } SET_FLAGS_OSZAPC_LOGIC_8(AL); set_CF(tmpCF); set_AF(tmpAF); BX_NEXT_INSTR(i); } bochs-2.6/cpu/avx2.cc0000644000175000017500000005016312020641453014315 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: avx2.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX #include "simd_int.h" #include "simd_compare.h" #define AVX_2OP(HANDLER, func) \ /* AVX instruction with two src operands */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C :: HANDLER (bxInstruction_c *i) \ { \ BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); \ unsigned len = i->getVL(); \ \ for (unsigned n=0; n < len; n++) \ (func)(&op1.avx128(n), &op2.avx128(n)); \ \ BX_WRITE_AVX_REGZ(i->dst(), op1, len); \ \ BX_NEXT_INSTR(i); \ } AVX_2OP(VANDPS_VpsHpsWpsR, sse_andps) AVX_2OP(VANDNPS_VpsHpsWpsR, sse_andnps) AVX_2OP(VXORPS_VpsHpsWpsR, sse_xorps) AVX_2OP(VORPS_VpsHpsWpsR, sse_orps) AVX_2OP(VUNPCKLPS_VpsHpsWpsR, sse_unpcklps) AVX_2OP(VUNPCKLPD_VpdHpdWpdR, sse_unpcklpd) AVX_2OP(VUNPCKHPS_VpsHpsWpsR, sse_unpckhps) AVX_2OP(VUNPCKHPD_VpdHpdWpdR, sse_unpckhpd) AVX_2OP(VPADDB_VdqHdqWdqR, sse_paddb) AVX_2OP(VPADDW_VdqHdqWdqR, sse_paddw) AVX_2OP(VPADDD_VdqHdqWdqR, sse_paddd) AVX_2OP(VPADDQ_VdqHdqWdqR, sse_paddq) AVX_2OP(VPSUBB_VdqHdqWdqR, sse_psubb) AVX_2OP(VPSUBW_VdqHdqWdqR, sse_psubw) AVX_2OP(VPSUBD_VdqHdqWdqR, sse_psubd) AVX_2OP(VPSUBQ_VdqHdqWdqR, sse_psubq) AVX_2OP(VPCMPEQB_VdqHdqWdqR, sse_pcmpeqb) AVX_2OP(VPCMPEQW_VdqHdqWdqR, sse_pcmpeqw) AVX_2OP(VPCMPEQD_VdqHdqWdqR, sse_pcmpeqd) AVX_2OP(VPCMPEQQ_VdqHdqWdqR, sse_pcmpeqq) AVX_2OP(VPCMPGTB_VdqHdqWdqR, sse_pcmpgtb) AVX_2OP(VPCMPGTW_VdqHdqWdqR, sse_pcmpgtw) AVX_2OP(VPCMPGTD_VdqHdqWdqR, sse_pcmpgtd) AVX_2OP(VPCMPGTQ_VdqHdqWdqR, sse_pcmpgtq) AVX_2OP(VPMINSB_VdqHdqWdqR, sse_pminsb) AVX_2OP(VPMINSW_VdqHdqWdqR, sse_pminsw) AVX_2OP(VPMINSD_VdqHdqWdqR, sse_pminsd) AVX_2OP(VPMINUB_VdqHdqWdqR, sse_pminub) AVX_2OP(VPMINUW_VdqHdqWdqR, sse_pminuw) AVX_2OP(VPMINUD_VdqHdqWdqR, sse_pminud) AVX_2OP(VPMAXSB_VdqHdqWdqR, sse_pmaxsb) AVX_2OP(VPMAXSW_VdqHdqWdqR, sse_pmaxsw) AVX_2OP(VPMAXSD_VdqHdqWdqR, sse_pmaxsd) AVX_2OP(VPMAXUB_VdqHdqWdqR, sse_pmaxub) AVX_2OP(VPMAXUW_VdqHdqWdqR, sse_pmaxuw) AVX_2OP(VPMAXUD_VdqHdqWdqR, sse_pmaxud) AVX_2OP(VPSIGNB_VdqHdqWdqR, sse_psignb) AVX_2OP(VPSIGNW_VdqHdqWdqR, sse_psignw) AVX_2OP(VPSIGND_VdqHdqWdqR, sse_psignd) AVX_2OP(VPSUBSB_VdqHdqWdqR, sse_psubsb) AVX_2OP(VPSUBSW_VdqHdqWdqR, sse_psubsw) AVX_2OP(VPSUBUSB_VdqHdqWdqR, sse_psubusb) AVX_2OP(VPSUBUSW_VdqHdqWdqR, sse_psubusw) AVX_2OP(VPADDSB_VdqHdqWdqR, sse_paddsb) AVX_2OP(VPADDSW_VdqHdqWdqR, sse_paddsw) AVX_2OP(VPADDUSB_VdqHdqWdqR, sse_paddusb) AVX_2OP(VPADDUSW_VdqHdqWdqR, sse_paddusw) AVX_2OP(VPHADDW_VdqHdqWdqR, sse_phaddw) AVX_2OP(VPHADDD_VdqHdqWdqR, sse_phaddd) AVX_2OP(VPHADDSW_VdqHdqWdqR, sse_phaddsw) AVX_2OP(VPHSUBW_VdqHdqWdqR, sse_phsubw) AVX_2OP(VPHSUBD_VdqHdqWdqR, sse_phsubd) AVX_2OP(VPHSUBSW_VdqHdqWdqR, sse_phsubsw) AVX_2OP(VPAVGB_VdqHdqWdqR, sse_pavgb) AVX_2OP(VPAVGW_VdqHdqWdqR, sse_pavgw) AVX_2OP(VPACKUSWB_VdqHdqWdqR, sse_packuswb) AVX_2OP(VPACKSSWB_VdqHdqWdqR, sse_packsswb) AVX_2OP(VPACKUSDW_VdqHdqWdqR, sse_packusdw) AVX_2OP(VPACKSSDW_VdqHdqWdqR, sse_packssdw) AVX_2OP(VPUNPCKLBW_VdqHdqWdqR, sse_punpcklbw) AVX_2OP(VPUNPCKLWD_VdqHdqWdqR, sse_punpcklwd) AVX_2OP(VPUNPCKHBW_VdqHdqWdqR, sse_punpckhbw) AVX_2OP(VPUNPCKHWD_VdqHdqWdqR, sse_punpckhwd) AVX_2OP(VPMULLD_VdqHdqWdqR, sse_pmulld) AVX_2OP(VPMULLW_VdqHdqWdqR, sse_pmullw) AVX_2OP(VPMULHW_VdqHdqWdqR, sse_pmulhw) AVX_2OP(VPMULHUW_VdqHdqWdqR, sse_pmulhuw) AVX_2OP(VPMULDQ_VdqHdqWdqR, sse_pmuldq) AVX_2OP(VPMULUDQ_VdqHdqWdqR, sse_pmuludq) AVX_2OP(VPMULHRSW_VdqHdqWdqR, sse_pmulhrsw) AVX_2OP(VPMADDWD_VdqHdqWdqR, sse_pmaddwd) AVX_2OP(VPMADDUBSW_VdqHdqWdqR, sse_pmaddubsw) AVX_2OP(VPSADBW_VdqHdqWdqR, sse_psadbw) AVX_2OP(VPSRAVD_VdqHdqWdqR, sse_psravd) AVX_2OP(VPSLLVD_VdqHdqWdqR, sse_psllvd) AVX_2OP(VPSLLVQ_VdqHdqWdqR, sse_psllvq) AVX_2OP(VPSRLVD_VdqHdqWdqR, sse_psrlvd) AVX_2OP(VPSRLVQ_VdqHdqWdqR, sse_psrlvq) #define AVX_1OP(HANDLER, func) \ /* AVX instruction with single src operand */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C :: HANDLER (bxInstruction_c *i) \ { \ BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); \ unsigned len = i->getVL(); \ \ for (unsigned n=0; n < len; n++) \ (func)(&op.avx128(n)); \ \ BX_WRITE_AVX_REGZ(i->dst(), op, len); \ \ BX_NEXT_INSTR(i); \ } AVX_1OP(VPABSB_VdqWdqR, sse_pabsb) AVX_1OP(VPABSW_VdqWdqR, sse_pabsw) AVX_1OP(VPABSD_VdqWdqR, sse_pabsd) #define AVX_PSHIFT(HANDLER, func) \ /* AVX packed shift instruction */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ BxPackedAvxRegister op = BX_READ_AVX_REG(i->src1()); \ unsigned len = i->getVL(); \ \ for (unsigned n=0; n < len; n++) \ (func)(&op.avx128(n), BX_READ_XMM_REG_LO_QWORD(i->src2())); \ \ BX_WRITE_AVX_REGZ(i->dst(), op, len); \ \ BX_NEXT_INSTR(i); \ } AVX_PSHIFT(VPSRLW_VdqHdqWdqR, sse_psrlw); AVX_PSHIFT(VPSRLD_VdqHdqWdqR, sse_psrld); AVX_PSHIFT(VPSRLQ_VdqHdqWdqR, sse_psrlq); AVX_PSHIFT(VPSRAW_VdqHdqWdqR, sse_psraw); AVX_PSHIFT(VPSRAD_VdqHdqWdqR, sse_psrad); AVX_PSHIFT(VPSLLW_VdqHdqWdqR, sse_psllw); AVX_PSHIFT(VPSLLD_VdqHdqWdqR, sse_pslld); AVX_PSHIFT(VPSLLQ_VdqHdqWdqR, sse_psllq); #define AVX_PSHIFT_IMM(HANDLER, func) \ /* AVX packed shift with imm8 instruction */ \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()); \ unsigned len = i->getVL(); \ \ for (unsigned n=0; n < len; n++) \ (func)(&op.avx128(n), i->Ib()); \ \ BX_WRITE_AVX_REGZ(i->dst(), op, len); \ \ BX_NEXT_INSTR(i); \ } AVX_PSHIFT_IMM(VPSRLW_UdqIb, sse_psrlw); AVX_PSHIFT_IMM(VPSRLD_UdqIb, sse_psrld); AVX_PSHIFT_IMM(VPSRLQ_UdqIb, sse_psrlq); AVX_PSHIFT_IMM(VPSRAW_UdqIb, sse_psraw); AVX_PSHIFT_IMM(VPSRAD_UdqIb, sse_psrad); AVX_PSHIFT_IMM(VPSLLW_UdqIb, sse_psllw); AVX_PSHIFT_IMM(VPSLLD_UdqIb, sse_pslld); AVX_PSHIFT_IMM(VPSLLQ_UdqIb, sse_psllq); AVX_PSHIFT_IMM(VPSRLDQ_UdqIb, sse_psrldq); AVX_PSHIFT_IMM(VPSLLDQ_UdqIb, sse_pslldq); BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPSHUFHW_VdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; Bit8u order = i->Ib(); unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_pshufhw(&result.avx128(n), &op.avx128(n), order); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPSHUFLW_VdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op = BX_READ_AVX_REG(i->src()), result; Bit8u order = i->Ib(); unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_pshuflw(&result.avx128(n), &op.avx128(n), order); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPSHUFB_VdqHdqWdqR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) sse_pshufb(&result.avx128(n), &op1.avx128(n), &op2.avx128(n)); BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VMPSADBW_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; Bit8u control = i->Ib(); unsigned len = i->getVL(); for (unsigned n=0; n < len; n++) { sse_mpsadbw(&result.avx128(n), &op1.avx128(n), &op2.avx128(n), control & 0x7); control >>= 3; } BX_WRITE_AVX_REGZ(i->dst(), result, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPBLENDW_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); Bit8u mask = i->Ib(); for (unsigned n=0; n < len; n++) sse_pblendw(&op1.avx128(n), &op2.avx128(n), mask); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPBROADCASTB_VdqWb(bxInstruction_c *i) { unsigned len = i->getVL(); BxPackedAvxRegister op; Bit8u val_8 = BX_READ_XMM_REG_LO_BYTE(i->src()); for (unsigned n=0; n < len; n++) sse_pbroadcastb(&op.avx128(n), val_8); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPBROADCASTW_VdqWw(bxInstruction_c *i) { unsigned len = i->getVL(); BxPackedAvxRegister op; Bit16u val_16 = BX_READ_XMM_REG_LO_WORD(i->src()); for (unsigned n=0; n < len; n++) sse_pbroadcastw(&op.avx128(n), val_16); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPBROADCASTD_VdqWd(bxInstruction_c *i) { unsigned len = i->getVL(); BxPackedAvxRegister op; Bit32u val_32 = BX_READ_XMM_REG_LO_DWORD(i->src()); for (unsigned n=0; n < len; n++) sse_pbroadcastd(&op.avx128(n), val_32); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPBROADCASTQ_VdqWq(bxInstruction_c *i) { unsigned len = i->getVL(); BxPackedAvxRegister op; Bit64u val_64 = BX_READ_XMM_REG_LO_QWORD(i->src()); for (unsigned n=0; n < len; n++) sse_pbroadcastq(&op.avx128(n), val_64); BX_WRITE_AVX_REGZ(i->dst(), op, len); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVSXBW256_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); BxPackedAvxRegister result; for (int n=0; n<16; n++) result.avx16u(n) = (Bit8s) op.xmmsbyte(n); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVSXBD256_VdqWqR(bxInstruction_c *i) { BxPackedAvxRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.avx32u(0) = (Bit8s) MMXSB0(op); result.avx32u(1) = (Bit8s) MMXSB1(op); result.avx32u(2) = (Bit8s) MMXSB2(op); result.avx32u(3) = (Bit8s) MMXSB3(op); result.avx32u(4) = (Bit8s) MMXSB4(op); result.avx32u(5) = (Bit8s) MMXSB5(op); result.avx32u(6) = (Bit8s) MMXSB6(op); result.avx32u(7) = (Bit8s) MMXSB7(op); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVSXBQ256_VdqWdR(bxInstruction_c *i) { BxPackedAvxRegister result; Bit32u val32 = BX_READ_XMM_REG_LO_DWORD(i->src()); result.avx64u(0) = (Bit8s) (val32 & 0xFF); result.avx64u(1) = (Bit8s) ((val32 >> 8) & 0xFF); result.avx64u(2) = (Bit8s) ((val32 >> 16) & 0xFF); result.avx64u(3) = (Bit8s) (val32 >> 24); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVSXWD256_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); BxPackedAvxRegister result; result.avx32u(0) = op.xmm16s(0); result.avx32u(1) = op.xmm16s(1); result.avx32u(2) = op.xmm16s(2); result.avx32u(3) = op.xmm16s(3); result.avx32u(4) = op.xmm16s(4); result.avx32u(5) = op.xmm16s(5); result.avx32u(6) = op.xmm16s(6); result.avx32u(7) = op.xmm16s(7); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVSXWQ256_VdqWqR(bxInstruction_c *i) { BxPackedAvxRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.avx64u(0) = MMXSW0(op); result.avx64u(1) = MMXSW1(op); result.avx64u(2) = MMXSW2(op); result.avx64u(3) = MMXSW3(op); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVSXDQ256_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); BxPackedAvxRegister result; result.avx64u(0) = op.xmm32s(0); result.avx64u(1) = op.xmm32s(1); result.avx64u(2) = op.xmm32s(2); result.avx64u(3) = op.xmm32s(3); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVZXBW256_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); BxPackedAvxRegister result; for (int n=0; n<16; n++) result.avx16u(n) = op.xmmubyte(n); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVZXBD256_VdqWqR(bxInstruction_c *i) { BxPackedAvxRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.avx32u(0) = MMXUB0(op); result.avx32u(1) = MMXUB1(op); result.avx32u(2) = MMXUB2(op); result.avx32u(3) = MMXUB3(op); result.avx32u(4) = MMXUB4(op); result.avx32u(5) = MMXUB5(op); result.avx32u(6) = MMXUB6(op); result.avx32u(7) = MMXUB7(op); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVZXBQ256_VdqWdR(bxInstruction_c *i) { BxPackedAvxRegister result; Bit32u val32 = BX_READ_XMM_REG_LO_DWORD(i->src()); result.avx64u(0) = (Bit8u) (val32 & 0xFF); result.avx64u(1) = (Bit8u) ((val32 >> 8) & 0xFF); result.avx64u(2) = (Bit8u) ((val32 >> 16) & 0xFF); result.avx64u(3) = (Bit8u) (val32 >> 24); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVZXWD256_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); BxPackedAvxRegister result; result.avx32u(0) = op.xmm16u(0); result.avx32u(1) = op.xmm16u(1); result.avx32u(2) = op.xmm16u(2); result.avx32u(3) = op.xmm16u(3); result.avx32u(4) = op.xmm16u(4); result.avx32u(5) = op.xmm16u(5); result.avx32u(6) = op.xmm16u(6); result.avx32u(7) = op.xmm16u(7); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVZXWQ256_VdqWqR(bxInstruction_c *i) { BxPackedAvxRegister result; BxPackedMmxRegister op; // use MMX register as 64-bit value with convinient accessors MMXUQ(op) = BX_READ_XMM_REG_LO_QWORD(i->src()); result.avx64u(0) = MMXUW0(op); result.avx64u(1) = MMXUW1(op); result.avx64u(2) = MMXUW2(op); result.avx64u(3) = MMXUW3(op); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPMOVZXDQ256_VdqWdqR(bxInstruction_c *i) { BxPackedXmmRegister op = BX_READ_XMM_REG(i->src()); BxPackedAvxRegister result; result.avx64u(0) = op.xmm32u(0); result.avx64u(1) = op.xmm32u(1); result.avx64u(2) = op.xmm32u(2); result.avx64u(3) = op.xmm32u(3); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPALIGNR_VdqHdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()), op2 = BX_READ_AVX_REG(i->src2()); unsigned len = i->getVL(); for (unsigned n=0; nIb()); BX_WRITE_AVX_REGZ(i->dst(), op2, i->getVL()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMD_VdqHdqWdqR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()), result; result.avx32u(0) = op2.avx32u(op1.avx32u(0) & 0x7); result.avx32u(1) = op2.avx32u(op1.avx32u(1) & 0x7); result.avx32u(2) = op2.avx32u(op1.avx32u(2) & 0x7); result.avx32u(3) = op2.avx32u(op1.avx32u(3) & 0x7); result.avx32u(4) = op2.avx32u(op1.avx32u(4) & 0x7); result.avx32u(5) = op2.avx32u(op1.avx32u(5) & 0x7); result.avx32u(6) = op2.avx32u(op1.avx32u(6) & 0x7); result.avx32u(7) = op2.avx32u(op1.avx32u(7) & 0x7); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VPERMQ_VdqWdqIbR(bxInstruction_c *i) { BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src()), result; Bit8u control = i->Ib(); result.avx64u(0) = op2.avx64u((control) & 0x3); result.avx64u(1) = op2.avx64u((control >> 2) & 0x3); result.avx64u(2) = op2.avx64u((control >> 4) & 0x3); result.avx64u(3) = op2.avx64u((control >> 6) & 0x3); BX_WRITE_AVX_REG(i->dst(), result); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/ctrl_xfer64.cc0000644000175000017500000003465512020641453015607 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ctrl_xfer64.cc 11356 2012-08-21 19:58:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near64(bxInstruction_c *i) { Bit64u new_RIP = RIP + (Bit32s) i->Id(); if (! IsCanonical(new_RIP)) { BX_ERROR(("branch_near64: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0); } RIP = new_RIP; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0 // assert magic async_event to stop trace execution BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE; #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear64_Iw(bxInstruction_c *i) { #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif Bit64u return_RIP = stack_read_qword(RSP); if (! IsCanonical(return_RIP)) { BX_ERROR(("RETnear64_Iw: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0); } RIP = return_RIP; RSP += 8 + i->Iw(); BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, PREV_RIP, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear64(bxInstruction_c *i) { #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif Bit64u return_RIP = stack_read_qword(RSP); if (! IsCanonical(return_RIP)) { BX_ERROR(("RETnear64: canonical RIP violation %08x%08x", GET32H(return_RIP), GET32L(return_RIP))); exception(BX_GP_EXCEPTION, 0); } RIP = return_RIP; RSP += 8; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, PREV_RIP, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar64_Iw(bxInstruction_c *i) { invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif BX_ASSERT(protected_mode()); // return_protected is RSP safe return_protected(i, i->Iw()); BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_Jq(bxInstruction_c *i) { Bit64u new_RIP = RIP + (Bit32s) i->Id(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif /* push 64 bit EA of next instruction */ stack_write_qword(RSP-8, RIP); if (! IsCanonical(new_RIP)) { BX_ERROR(("CALL_Jq: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0); } RIP = new_RIP; RSP -= 8; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, PREV_RIP, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EqR(bxInstruction_c *i) { #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif Bit64u new_RIP = BX_READ_64BIT_REG(i->dst()); /* push 64 bit EA of next instruction */ stack_write_qword(RSP-8, RIP); if (! IsCanonical(new_RIP)) { BX_ERROR(("CALL_Eq: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0); } RIP = new_RIP; RSP -= 8; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL_INDIRECT, PREV_RIP, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL64_Ep(bxInstruction_c *i) { invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ Bit64u op1_64 = read_virtual_qword_64(i->seg(), eaddr); Bit16u cs_raw = read_virtual_word_64(i->seg(), (eaddr+8) & i->asize_mask()); BX_ASSERT(protected_mode()); // call_protected is RSP safe for 64-bit mode call_protected(i, cs_raw, op1_64); BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL_INDIRECT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Jq(bxInstruction_c *i) { Bit64u new_RIP = RIP + (Bit32s) i->Id(); if (! IsCanonical(new_RIP)) { BX_ERROR(("JMP_Jq: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0); } RIP = new_RIP; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JO_Jq(bxInstruction_c *i) { if (get_OF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNO_Jq(bxInstruction_c *i) { if (! get_OF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JB_Jq(bxInstruction_c *i) { if (get_CF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNB_Jq(bxInstruction_c *i) { if (! get_CF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JZ_Jq(bxInstruction_c *i) { if (get_ZF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNZ_Jq(bxInstruction_c *i) { if (! get_ZF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JBE_Jq(bxInstruction_c *i) { if (get_CF() || get_ZF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNBE_Jq(bxInstruction_c *i) { if (! (get_CF() || get_ZF())) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JS_Jq(bxInstruction_c *i) { if (get_SF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNS_Jq(bxInstruction_c *i) { if (! get_SF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JP_Jq(bxInstruction_c *i) { if (get_PF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNP_Jq(bxInstruction_c *i) { if (! get_PF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JL_Jq(bxInstruction_c *i) { if (getB_SF() != getB_OF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNL_Jq(bxInstruction_c *i) { if (getB_SF() == getB_OF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JLE_Jq(bxInstruction_c *i) { if (get_ZF() || (getB_SF() != getB_OF())) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNLE_Jq(bxInstruction_c *i) { if (! get_ZF() && (getB_SF() == getB_OF())) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); if (! IsCanonical(op1_64)) { BX_ERROR(("JMP_Eq: canonical RIP violation")); exception(BX_GP_EXCEPTION, 0); } RIP = op1_64; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP_INDIRECT, PREV_RIP, RIP); BX_NEXT_TRACE(i); } /* Far indirect jump */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP64_Ep(bxInstruction_c *i) { invalidate_prefetch_q(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_virtual_qword_64(i->seg(), eaddr); Bit16u cs_raw = read_virtual_word_64(i->seg(), (eaddr+8) & i->asize_mask()); BX_ASSERT(protected_mode()); jump_protected(i, cs_raw, op1_64); BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP_INDIRECT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET64(bxInstruction_c *i) { invalidate_prefetch_q(); #if BX_SUPPORT_VMX if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT)) #endif BX_CPU_THIS_PTR disable_NMI = 0; #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_iret; #endif BX_ASSERT(long_mode()); long_iret(i); BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, RIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JRCXZ_Jb(bxInstruction_c *i) { Bit64u temp_RCX; if (i->as64L()) temp_RCX = RCX; else temp_RCX = ECX; if (temp_RCX == 0) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_TRACE(i); } // // There is some weirdness in LOOP instructions definition. If an exception // was generated during the instruction execution (for example #GP fault // because EIP was beyond CS segment limits) CPU state should restore the // state prior to instruction execution. // // The final point that we are not allowed to decrement RCX register before // it is known that no exceptions can happen. // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE64_Jb(bxInstruction_c *i) { if (i->as64L()) { Bit64u count = RCX; if (((--count) != 0) && (get_ZF()==0)) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif RCX = count; } else { Bit32u count = ECX; if (((--count) != 0) && (get_ZF()==0)) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif RCX = count; } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE64_Jb(bxInstruction_c *i) { if (i->as64L()) { Bit64u count = RCX; if (((--count) != 0) && get_ZF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif RCX = count; } else { Bit32u count = ECX; if (((--count) != 0) && get_ZF()) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif RCX = count; } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP64_Jb(bxInstruction_c *i) { if (i->as64L()) { Bit64u count = RCX; if ((--count) != 0) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif RCX = count; } else { Bit32u count = ECX; if ((--count) != 0) { branch_near64(i); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, RIP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif RCX = count; } BX_NEXT_TRACE(i); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/crregs.cc0000644000175000017500000011615112020641453014722 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: crregs.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2010-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_DdRd(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_DR_Access(0 /* write */, i->dst(), i->src()); #endif #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_DE()) { if ((i->dst() & 0xE) == 4) { BX_ERROR(("MOV_DdRd: access to DR4/DR5 causes #UD")); exception(BX_UD_EXCEPTION, 0); } } #endif // Note: processor clears GD upon entering debug exception // handler, to allow access to the debug registers if (BX_CPU_THIS_PTR dr7.get_GD()) { BX_ERROR(("MOV_DdRd: DR7 GD bit is set")); BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT; exception(BX_DB_EXCEPTION, 0); } // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_DdRd: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_DR_WRITE_INTERCEPTED(i->dst())) Svm_Vmexit(SVM_VMEXIT_DR0_WRITE + i->dst()); } #endif invalidate_prefetch_q(); Bit32u val_32 = BX_READ_32BIT_REG(i->src()); switch (i->dst()) { case 0: // DR0 case 1: // DR1 case 2: // DR2 case 3: // DR3 BX_CPU_THIS_PTR dr[i->dst()] = val_32; TLB_invlpg(val_32); break; case 4: // DR4 // DR4 aliased to DR6 by default. With Debug Extensions on, // access to DR4 causes #UD case 6: // DR6 #if BX_CPU_LEVEL <= 4 // On 386/486 bit12 is settable BX_CPU_THIS_PTR dr6.val32 = (BX_CPU_THIS_PTR dr6.val32 & 0xffff0ff0) | (val_32 & 0x0000f00f); #else // On Pentium+, bit12 is always zero BX_CPU_THIS_PTR dr6.val32 = (BX_CPU_THIS_PTR dr6.val32 & 0xffff0ff0) | (val_32 & 0x0000e00f); #endif break; case 5: // DR5 // DR5 aliased to DR7 by default. With Debug Extensions on, // access to DR5 causes #UD case 7: // DR7 // Note: 486+ ignore GE and LE flags. On the 386, exact // data breakpoint matching does not occur unless it is enabled // by setting the LE and/or GE flags. #if BX_CPU_LEVEL <= 4 // 386/486: you can play with all the bits except b10 is always 1 BX_CPU_THIS_PTR dr7.set32(val_32 | 0x00000400); #else // Pentium+: bits15,14,12 are hardwired to 0, rest are settable. // Even bits 11,10 are changeable though reserved. BX_CPU_THIS_PTR dr7.set32((val_32 & 0xffff2fff) | 0x00000400); #endif #if BX_X86_DEBUGGER // Some sanity checks... if ((BX_CPU_THIS_PTR dr7.get_R_W0() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN0()) || (BX_CPU_THIS_PTR dr7.get_R_W1() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN1()) || (BX_CPU_THIS_PTR dr7.get_R_W2() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN2()) || (BX_CPU_THIS_PTR dr7.get_R_W3() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN3())) { // Instruction breakpoint with LENx not 00b (1-byte length) BX_ERROR(("MOV_DdRd: write of %08x, R/W=00b LEN!=00b", val_32)); } #endif TLB_flush(); // the DR7 write could enable some breakpoints break; default: BX_ERROR(("MOV_DdRd: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RdDd(bxInstruction_c *i) { Bit32u val_32; #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_DR_Access(1 /* read */, i->src(), i->dst()); #endif #if BX_CPU_LEVEL >= 5 if (BX_CPU_THIS_PTR cr4.get_DE()) { if ((i->src() & 0xE) == 4) { BX_ERROR(("MOV_RdDd: access to DR4/DR5 causes #UD")); exception(BX_UD_EXCEPTION, 0); } } #endif // Note: processor clears GD upon entering debug exception // handler, to allow access to the debug registers if (BX_CPU_THIS_PTR dr7.get_GD()) { BX_ERROR(("MOV_RdDd: DR7 GD bit is set")); BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT; exception(BX_DB_EXCEPTION, 0); } // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_RdDd: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_DR_READ_INTERCEPTED(i->src())) Svm_Vmexit(SVM_VMEXIT_DR0_READ + i->src()); } #endif switch (i->src()) { case 0: // DR0 case 1: // DR1 case 2: // DR2 case 3: // DR3 val_32 = (Bit32u) BX_CPU_THIS_PTR dr[i->src()]; break; case 4: // DR4 // DR4 aliased to DR6 by default. With Debug Extensions ON, // access to DR4 causes #UD case 6: // DR6 val_32 = BX_CPU_THIS_PTR dr6.get32(); break; case 5: // DR5 // DR5 aliased to DR7 by default. With Debug Extensions ON, // access to DR5 causes #UD case 7: // DR7 val_32 = BX_CPU_THIS_PTR dr7.get32(); break; default: BX_ERROR(("MOV_RdDd: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } BX_WRITE_32BIT_REGZ(i->dst(), val_32); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_DqRq(bxInstruction_c *i) { #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_DR_Access(0 /* write */, i->dst(), i->src()); #endif if (BX_CPU_THIS_PTR cr4.get_DE()) { if ((i->dst() & 0xE) == 4) { BX_ERROR(("MOV_DqRq: access to DR4/DR5 causes #UD")); exception(BX_UD_EXCEPTION, 0); } } if (i->dst() >= 8) { BX_ERROR(("MOV_DqRq: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } // Note: processor clears GD upon entering debug exception // handler, to allow access to the debug registers if (BX_CPU_THIS_PTR dr7.get_GD()) { BX_ERROR(("MOV_DqRq: DR7 GD bit is set")); BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT; exception(BX_DB_EXCEPTION, 0); } /* #GP(0) if CPL is not 0 */ if (CPL != 0) { BX_ERROR(("MOV_DqRq: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_DR_WRITE_INTERCEPTED(i->dst())) Svm_Vmexit(SVM_VMEXIT_DR0_WRITE + i->dst()); } #endif invalidate_prefetch_q(); Bit64u val_64 = BX_READ_64BIT_REG(i->src()); switch (i->dst()) { case 0: // DR0 case 1: // DR1 case 2: // DR2 case 3: // DR3 BX_CPU_THIS_PTR dr[i->dst()] = val_64; TLB_invlpg(val_64); break; case 4: // DR4 // DR4 aliased to DR6 by default. With Debug Extensions ON, // access to DR4 causes #UD case 6: // DR6 if (GET32H(val_64)) { BX_ERROR(("MOV_DqRq: attempt to set upper part of DR6")); exception(BX_GP_EXCEPTION, 0); } // On Pentium+, bit12 is always zero BX_CPU_THIS_PTR dr6.val32 = (BX_CPU_THIS_PTR dr6.val32 & 0xffff0ff0) | (val_64 & 0x0000e00f); break; case 5: // DR5 // DR5 aliased to DR7 by default. With Debug Extensions ON, // access to DR5 causes #UD case 7: // DR7 // Note: 486+ ignore GE and LE flags. On the 386, exact // data breakpoint matching does not occur unless it is enabled // by setting the LE and/or GE flags. if (GET32H(val_64)) { BX_ERROR(("MOV_DqRq: attempt to set upper part of DR7")); exception(BX_GP_EXCEPTION, 0); } // Pentium+: bits15,14,12 are hardwired to 0, rest are settable. // Even bits 11,10 are changeable though reserved. BX_CPU_THIS_PTR dr7.set32((val_64 & 0xffff2fff) | 0x00000400); #if BX_X86_DEBUGGER if ((BX_CPU_THIS_PTR dr7.get_R_W0() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN0()) || (BX_CPU_THIS_PTR dr7.get_R_W1() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN1()) || (BX_CPU_THIS_PTR dr7.get_R_W2() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN2()) || (BX_CPU_THIS_PTR dr7.get_R_W3() == BX_HWDebugInstruction && BX_CPU_THIS_PTR dr7.get_LEN3())) { // Instruction breakpoint with LENx not 00b (1-byte length) BX_ERROR(("MOV_DqRq: write of %08x, R/W=00b LEN!=00b", BX_CPU_THIS_PTR dr7.get32())); } #endif TLB_flush(); // the DR7 write could enable some breakpoints break; default: BX_ERROR(("MOV_DqRq: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RqDq(bxInstruction_c *i) { Bit64u val_64; #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_DR_Access(1 /* read */, i->src(), i->dst()); #endif if (BX_CPU_THIS_PTR cr4.get_DE()) { if ((i->src() & 0xE) == 4) { BX_ERROR(("MOV_RqDq: access to DR4/DR5 causes #UD")); exception(BX_UD_EXCEPTION, 0); } } if (i->src() >= 8) { BX_ERROR(("MOV_RqDq: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } // Note: processor clears GD upon entering debug exception // handler, to allow access to the debug registers if (BX_CPU_THIS_PTR dr7.get_GD()) { BX_ERROR(("MOV_RqDq: DR7 GD bit is set")); BX_CPU_THIS_PTR debug_trap |= BX_DEBUG_DR_ACCESS_BIT; exception(BX_DB_EXCEPTION, 0); } /* #GP(0) if CPL is not 0 */ if (CPL != 0) { BX_ERROR(("MOV_RqDq: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_DR_READ_INTERCEPTED(i->src())) Svm_Vmexit(SVM_VMEXIT_DR0_READ + i->src()); } #endif switch (i->src()) { case 0: // DR0 case 1: // DR1 case 2: // DR2 case 3: // DR3 val_64 = BX_CPU_THIS_PTR dr[i->src()]; break; case 4: // DR4 // DR4 aliased to DR6 by default. With Debug Extensions ON, // access to DR4 causes #UD case 6: // DR6 val_64 = BX_CPU_THIS_PTR dr6.get32(); break; case 5: // DR5 // DR5 aliased to DR7 by default. With Debug Extensions ON, // access to DR5 causes #UD case 7: // DR7 val_64 = BX_CPU_THIS_PTR dr7.get32(); break; default: BX_ERROR(("MOV_RqDq: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } BX_WRITE_64BIT_REG(i->dst(), val_64); BX_NEXT_INSTR(i); } #endif // #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR0Rd(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_CR0Rd: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); Bit32u val_32 = BX_READ_32BIT_REG(i->src()); if (i->dst() == 0) { // CR0 #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) val_32 = (Bit32u) VMexit_CR0_Write(i, val_32); #endif if (! SetCR0(val_32)) exception(BX_GP_EXCEPTION, 0); BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR0, val_32); } #if BX_CPU_LEVEL >= 6 else { // AMD feature: LOCK CR0 allows CR8 access even in 32-bit mode WriteCR8(i, val_32); } #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR2Rd(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_CR2Rd: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_WRITE_INTERCEPTED(2)) Svm_Vmexit(SVM_VMEXIT_CR2_WRITE); } #endif BX_CPU_THIS_PTR cr2 = BX_READ_32BIT_REG(i->src()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR3Rd(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_CR3Rd: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); Bit32u val_32 = BX_READ_32BIT_REG(i->src()); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_CR3_Write(i, val_32); #endif #if BX_CPU_LEVEL >= 6 if (BX_CPU_THIS_PTR cr0.get_PG() && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) { if (! CheckPDPTR(val_32)) { BX_ERROR(("SetCR3(): PDPTR check failed !")); exception(BX_GP_EXCEPTION, 0); } } #endif if (! SetCR3(val_32)) exception(BX_GP_EXCEPTION, 0); BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR3, val_32); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR4Rd(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_CR4Rd: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); Bit32u val_32 = BX_READ_32BIT_REG(i->src()); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) val_32 = (Bit32u) VMexit_CR4_Write(i, val_32); #endif if (! SetCR4(val_32)) exception(BX_GP_EXCEPTION, 0); BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR4, val_32); #endif BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RdCR0(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_RdCR0: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } Bit32u val_32 = 0; if (i->src() == 0) { // CR0 val_32 = (Bit32u) read_CR0(); /* correctly handle VMX */ } #if BX_CPU_LEVEL >= 6 else { // AMD feature: LOCK CR0 allows CR8 access even in 32-bit mode val_32 = ReadCR8(i); } #endif BX_WRITE_32BIT_REGZ(i->dst(), val_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RdCR2(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_RdCR2: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_READ_INTERCEPTED(2)) Svm_Vmexit(SVM_VMEXIT_CR2_READ); } #endif BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) BX_CPU_THIS_PTR cr2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RdCR3(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_RdCR3: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_READ_INTERCEPTED(3)) Svm_Vmexit(SVM_VMEXIT_CR3_READ); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_CR3_Read(i); #endif Bit32u val_32 = (Bit32u) BX_CPU_THIS_PTR cr3; BX_WRITE_32BIT_REGZ(i->dst(), val_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RdCR4(bxInstruction_c *i) { #if BX_CPU_LEVEL >= 5 // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("MOV_RdCR4: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } Bit32u val_32 = (Bit32u) read_CR4(); /* correctly handle VMX */ BX_WRITE_32BIT_REGZ(i->dst(), val_32); #endif BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR0Rq(bxInstruction_c *i) { if (CPL!=0) { BX_ERROR(("MOV_CR0Rq: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); Bit64u val_64 = BX_READ_64BIT_REG(i->src()); if (i->dst() == 0) { // CR0 #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) val_64 = VMexit_CR0_Write(i, val_64); #endif if (! SetCR0(val_64)) exception(BX_GP_EXCEPTION, 0); BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR0, (Bit32u) val_64); } else { WriteCR8(i, val_64); } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR2Rq(bxInstruction_c *i) { if (i->dst() != 2) { BX_ERROR(("MOV_CR2Rq: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } if (CPL!=0) { BX_ERROR(("MOV_CR2Rq: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_WRITE_INTERCEPTED(2)) Svm_Vmexit(SVM_VMEXIT_CR2_WRITE); } #endif BX_CPU_THIS_PTR cr2 = BX_READ_64BIT_REG(i->src()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR3Rq(bxInstruction_c *i) { if (i->dst() != 3) { BX_ERROR(("MOV_CR3Rq: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } if (CPL!=0) { BX_ERROR(("MOV_CR3Rq: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); Bit64u val_64 = BX_READ_64BIT_REG(i->src()); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_CR3_Write(i, val_64); #endif // no PDPTR checks in long mode if (! SetCR3(val_64)) exception(BX_GP_EXCEPTION, 0); BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR3, val_64); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_CR4Rq(bxInstruction_c *i) { if (i->dst() != 4) { BX_ERROR(("MOV_CR4Rq: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } if (CPL!=0) { BX_ERROR(("MOV_CR4Rq: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } invalidate_prefetch_q(); Bit64u val_64 = BX_READ_64BIT_REG(i->src()); #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) val_64 = VMexit_CR4_Write(i, val_64); #endif if (! SetCR4(val_64)) exception(BX_GP_EXCEPTION, 0); BX_INSTR_TLB_CNTRL(BX_CPU_ID, BX_INSTR_MOV_CR4, (Bit32u) val_64); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RqCR0(bxInstruction_c *i) { if (CPL!=0) { BX_ERROR(("MOV_RqCR0: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } Bit64u val_64; if (i->src() == 0) { // CR0 val_64 = read_CR0(); /* correctly handle VMX */ } else { // CR8 val_64 = ReadCR8(i); } BX_WRITE_64BIT_REG(i->dst(), val_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RqCR2(bxInstruction_c *i) { if (i->src() != 2) { BX_ERROR(("MOV_RqCR2: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } if (CPL!=0) { BX_ERROR(("MOV_RqCR2: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_READ_INTERCEPTED(2)) Svm_Vmexit(SVM_VMEXIT_CR2_READ); } #endif BX_WRITE_64BIT_REG(i->dst(), BX_CPU_THIS_PTR cr2); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RqCR3(bxInstruction_c *i) { if (i->src() != 3) { BX_ERROR(("MOV_RqCR3: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } if (CPL!=0) { BX_ERROR(("MOV_RqCR3: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_READ_INTERCEPTED(3)) Svm_Vmexit(SVM_VMEXIT_CR3_READ); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_CR3_Read(i); #endif BX_WRITE_64BIT_REG(i->dst(), BX_CPU_THIS_PTR cr3); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_RqCR4(bxInstruction_c *i) { if (i->src() != 4) { BX_ERROR(("MOV_RqCR4: #UD - register index out of range")); exception(BX_UD_EXCEPTION, 0); } if (CPL!=0) { BX_ERROR(("MOV_RqCR4: #GP(0) if CPL is not 0")); exception(BX_GP_EXCEPTION, 0); } Bit64u val_64 = read_CR4(); /* correctly handle VMX */ BX_WRITE_64BIT_REG(i->dst(), val_64); BX_NEXT_INSTR(i); } #endif // #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LMSW_Ew(bxInstruction_c *i) { Bit16u msw; // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("LMSW: CPL!=0 not in real mode")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_WRITE_INTERCEPTED(0)) Svm_Vmexit(SVM_VMEXIT_CR0_WRITE); } #endif if (i->modC0()) { msw = BX_READ_16BIT_REG(i->src()); } else { /* use RMAddr(i) to save address for VMexit */ RMAddr(i) = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); /* pointer, segment address pair */ msw = read_virtual_word(i->seg(), RMAddr(i)); } // LMSW does not affect PG,CD,NW,AM,WP,NE,ET bits, and cannot clear PE #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) msw = VMexit_LMSW(i, msw); #endif // LMSW cannot clear PE if (BX_CPU_THIS_PTR cr0.get_PE()) msw |= BX_CR0_PE_MASK; // adjust PE bit to current value of 1 msw &= 0xf; // LMSW only affects last 4 flags Bit32u cr0 = (BX_CPU_THIS_PTR cr0.get32() & 0xfffffff0) | msw; if (! SetCR0(cr0)) exception(BX_GP_EXCEPTION, 0); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SMSW_EwR(bxInstruction_c *i) { Bit32u msw = (Bit32u) read_CR0(); // handle CR0 shadow in VMX if (i->os32L()) { BX_WRITE_32BIT_REGZ(i->dst(), msw); } else { BX_WRITE_16BIT_REG(i->dst(), msw & 0xffff); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SMSW_EwM(bxInstruction_c *i) { Bit16u msw = read_CR0() & 0xffff; // handle CR0 shadow in VMX bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_word(i->seg(), eaddr, msw); BX_NEXT_INSTR(i); } bx_address BX_CPU_C::read_CR0(void) { bx_address cr0_val = BX_CPU_THIS_PTR cr0.get32(); #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_READ_INTERCEPTED(0)) Svm_Vmexit(SVM_VMEXIT_CR0_READ); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; cr0_val = (cr0_val & ~vm->vm_cr0_mask) | (vm->vm_cr0_read_shadow & vm->vm_cr0_mask); } #endif return cr0_val; } #if BX_CPU_LEVEL >= 5 bx_address BX_CPU_C::read_CR4(void) { bx_address cr4_val = BX_CPU_THIS_PTR cr4.get32(); #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_READ_INTERCEPTED(4)) Svm_Vmexit(SVM_VMEXIT_CR4_READ); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs; cr4_val = (cr4_val & ~vm->vm_cr4_mask) | (vm->vm_cr4_read_shadow & vm->vm_cr4_mask); } #endif return cr4_val; } #endif bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::check_CR0(bx_address cr0_val) { bx_cr0_t temp_cr0; #if BX_SUPPORT_X86_64 if (GET32H(cr0_val)) { BX_ERROR(("check_CR0(): trying to set CR0 > 32 bits")); return 0; } #endif temp_cr0.set32((Bit32u) cr0_val); if (temp_cr0.get_PG() && !temp_cr0.get_PE()) { BX_ERROR(("check_CR0(0x%08x): attempt to set CR0.PG with CR0.PE cleared !", temp_cr0.get32())); return 0; } #if BX_CPU_LEVEL >= 4 if (temp_cr0.get_NW() && !temp_cr0.get_CD()) { BX_ERROR(("check_CR0(0x%08x): attempt to set CR0.NW with CR0.CD cleared !", temp_cr0.get32())); return 0; } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx) { if (!temp_cr0.get_NE()) { BX_ERROR(("check_CR0(0x%08x): attempt to clear CR0.NE in vmx mode !", temp_cr0.get32())); return 0; } if (!BX_CPU_THIS_PTR in_vmx_guest && !SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_UNRESTRICTED_GUEST)) { if (!temp_cr0.get_PE() || !temp_cr0.get_PG()) { BX_ERROR(("check_CR0(0x%08x): attempt to clear CR0.PE/CR0.PG in vmx mode !", temp_cr0.get32())); return 0; } } } #endif return 1; } bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR0(bx_address val) { if (! check_CR0(val)) return 0; Bit32u val_32 = GET32L(val); #if BX_CPU_LEVEL >= 6 bx_bool pg = (val_32 >> 31) & 0x1; #endif #if BX_SUPPORT_X86_64 if (! BX_CPU_THIS_PTR cr0.get_PG() && pg) { if (BX_CPU_THIS_PTR efer.get_LME()) { if (!BX_CPU_THIS_PTR cr4.get_PAE()) { BX_ERROR(("SetCR0: attempt to enter x86-64 long mode without enabling CR4.PAE !")); return 0; } if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.l) { BX_ERROR(("SetCR0: attempt to enter x86-64 long mode with CS.L !")); return 0; } if (BX_CPU_THIS_PTR tr.cache.type <= 3) { BX_ERROR(("SetCR0: attempt to enter x86-64 long mode with TSS286 in TR !")); return 0; } BX_CPU_THIS_PTR efer.set_LMA(1); } } else if (BX_CPU_THIS_PTR cr0.get_PG() && ! pg) { if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) { BX_ERROR(("SetCR0(): attempt to leave 64 bit mode directly to legacy mode !")); return 0; } if (BX_CPU_THIS_PTR efer.get_LMA()) { if (BX_CPU_THIS_PTR cr4.get_PCIDE()) { BX_ERROR(("SetCR0(): attempt to leave 64 bit mode with CR4.PCIDE set !")); return 0; } if (BX_CPU_THIS_PTR gen_reg[BX_64BIT_REG_RIP].dword.hrx != 0) { BX_PANIC(("SetCR0(): attempt to leave x86-64 LONG mode with RIP upper != 0")); } BX_CPU_THIS_PTR efer.set_LMA(0); } } #endif // #if BX_SUPPORT_X86_64 // handle reserved bits behaviour #if BX_CPU_LEVEL == 3 val_32 = val_32 | 0x7ffffff0; #elif BX_CPU_LEVEL == 4 val_32 = (val_32 | 0x00000010) & 0xe005003f; #elif BX_CPU_LEVEL == 5 val_32 = val_32 | 0x00000010; #elif BX_CPU_LEVEL == 6 val_32 = (val_32 | 0x00000010) & 0xe005003f; #else #error "SetCR0: implement reserved bits behaviour for this CPU_LEVEL" #endif Bit32u oldCR0 = BX_CPU_THIS_PTR cr0.get32(); #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_WRITE_INTERCEPTED(0)) Svm_Vmexit(SVM_VMEXIT_CR0_WRITE); if (SVM_INTERCEPT(SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP)) { if ((oldCR0 & 0xfffffff5) != (val_32 & 0xfffffff5)) { // any other bit except TS or MP had changed Svm_Vmexit(SVM_VMEXIT_CR0_SEL_WRITE); } } } #endif #if BX_CPU_LEVEL >= 6 if (pg && BX_CPU_THIS_PTR cr4.get_PAE() && !long_mode()) { if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) { BX_ERROR(("SetCR0(): PDPTR check failed !")); return 0; } } #endif BX_CPU_THIS_PTR cr0.set32(val_32); #if BX_CPU_LEVEL >= 4 handleAlignmentCheck(/* CR0.AC reloaded */); #endif handleCpuModeChange(); #if BX_CPU_LEVEL >= 6 handleSseModeChange(); #if BX_SUPPORT_AVX handleAvxModeChange(); #endif #endif // Modification of PG,PE flushes TLB cache according to docs. // Additionally, the TLB strategy is based on the current value of // WP, so if that changes we must also flush the TLB. if ((oldCR0 & 0x80010001) != (val_32 & 0x80010001)) TLB_flush(); // Flush Global entries also return 1; } #if BX_CPU_LEVEL >= 5 Bit32u BX_CPU_C::get_cr4_allow_mask(void) { Bit32u allowMask = 0; // CR4 bits definitions: // [31-21] Reserved, Must be Zero // [20] SMEP: Supervisor Mode Execution Protection R/W // [19] Reserved, Must be Zero // [18] OSXSAVE: Operating System XSAVE Support R/W // [17] PCIDE: PCID Support R/W // [16] FSGSBASE: FS/GS BASE access R/W // [15] Reserved, Must be Zero // [14] SMXE: SMX Extensions R/W // [13] VMXE: VMX Extensions R/W // [12-11] Reserved, Must be Zero // [10] OSXMMEXCPT: Operating System Unmasked Exception Support R/W // [9] OSFXSR: Operating System FXSAVE/FXRSTOR Support R/W // [8] PCE: Performance-Monitoring Counter Enable R/W // [7] PGE: Page-Global Enable R/W // [6] MCE: Machine Check Enable R/W // [5] PAE: Physical-Address Extension R/W // [4] PSE: Page Size Extensions R/W // [3] DE: Debugging Extensions R/W // [2] TSD: Time Stamp Disable R/W // [1] PVI: Protected-Mode Virtual Interrupts R/W // [0] VME: Virtual-8086 Mode Extensions R/W /* VME */ if (bx_cpuid_support_vme()) allowMask |= BX_CR4_VME_MASK | BX_CR4_PVI_MASK; if (bx_cpuid_support_tsc()) allowMask |= BX_CR4_TSD_MASK; if (bx_cpuid_support_debug_extensions()) allowMask |= BX_CR4_DE_MASK; if (bx_cpuid_support_pse()) allowMask |= BX_CR4_PSE_MASK; #if BX_CPU_LEVEL >= 6 if (bx_cpuid_support_pae()) allowMask |= BX_CR4_PAE_MASK; #endif // NOTE: exception 18 (#MC) never appears in Bochs allowMask |= BX_CR4_MCE_MASK; #if BX_CPU_LEVEL >= 6 if (bx_cpuid_support_pge()) allowMask |= BX_CR4_PGE_MASK; allowMask |= BX_CR4_PCE_MASK; /* OSFXSR */ if (bx_cpuid_support_fxsave_fxrstor()) allowMask |= BX_CR4_OSFXSR_MASK; /* OSXMMEXCPT */ if (bx_cpuid_support_sse()) allowMask |= BX_CR4_OSXMMEXCPT_MASK; #if BX_SUPPORT_VMX if (bx_cpuid_support_vmx()) allowMask |= BX_CR4_VMXE_MASK; #endif if (bx_cpuid_support_smx()) allowMask |= BX_CR4_SMXE_MASK; #if BX_SUPPORT_X86_64 if (bx_cpuid_support_pcid()) allowMask |= BX_CR4_PCIDE_MASK; if (bx_cpuid_support_fsgsbase()) allowMask |= BX_CR4_FSGSBASE_MASK; #endif /* OSXSAVE */ if (bx_cpuid_support_xsave()) allowMask |= BX_CR4_OSXSAVE_MASK; if (bx_cpuid_support_smep()) allowMask |= BX_CR4_SMEP_MASK; #endif return allowMask; } bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::check_CR4(bx_address cr4_val) { // check if trying to set undefined bits if (cr4_val & ~((bx_address) BX_CPU_THIS_PTR cr4_suppmask)) { BX_ERROR(("check_CR4(): write of 0x%08x not supported (allowMask=0x%x)", (Bit32u) cr4_val, BX_CPU_THIS_PTR cr4_suppmask)); return 0; } bx_cr4_t temp_cr4; temp_cr4.set32((Bit32u) cr4_val); #if BX_SUPPORT_X86_64 if (long_mode()) { if(! temp_cr4.get_PAE()) { BX_ERROR(("check_CR4(): attempt to clear CR4.PAE when EFER.LMA=1")); return 0; } } if (temp_cr4.get_PCIDE()) { if (! long_mode()) { BX_ERROR(("check_CR4(): attempt to set CR4.PCIDE when EFER.LMA=0")); return 0; } } #endif #if BX_SUPPORT_VMX if(! temp_cr4.get_VMXE()) { if (BX_CPU_THIS_PTR in_vmx) { BX_ERROR(("check_CR4(): attempt to clear CR4.VMXE in vmx mode")); return 0; } } else { if (BX_CPU_THIS_PTR in_smm) { BX_ERROR(("check_CR4(): attempt to set CR4.VMXE in smm mode")); return 0; } } #endif return 1; } bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR4(bx_address val) { if (! check_CR4(val)) return 0; #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_WRITE_INTERCEPTED(4)) Svm_Vmexit(SVM_VMEXIT_CR4_WRITE); } #endif #if BX_CPU_LEVEL >= 6 // Modification of PGE,PAE,PSE,PCIDE,SMEP flushes TLB cache according to docs. if ((val & BX_CR4_FLUSH_TLB_MASK) != (BX_CPU_THIS_PTR cr4.val32 & BX_CR4_FLUSH_TLB_MASK)) { // reload PDPTR if needed if (BX_CPU_THIS_PTR cr0.get_PG() && (val & BX_CR4_PAE_MASK) != 0 && !long_mode()) { if (! CheckPDPTR(BX_CPU_THIS_PTR cr3)) { BX_ERROR(("SetCR4(): PDPTR check failed !")); return 0; } } #if BX_SUPPORT_X86_64 else { // if trying to enable CR4.PCIDE if (! BX_CPU_THIS_PTR cr4.get_PCIDE() && (val & BX_CR4_PCIDE_MASK)) { if (BX_CPU_THIS_PTR cr3 & 0xfff) { BX_ERROR(("SetCR4(): Attempt to enable CR4.PCIDE with non-zero PCID !")); return 0; } } } #endif TLB_flush(); // Flush Global entries also. } #endif BX_CPU_THIS_PTR cr4.set32((Bit32u) val); #if BX_CPU_LEVEL >= 6 handleSseModeChange(); #if BX_SUPPORT_AVX handleAvxModeChange(); #endif #endif return 1; } #endif // BX_CPU_LEVEL >= 5 bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetCR3(bx_address val) { #if BX_SUPPORT_X86_64 if (long_mode()) { if (! IsValidPhyAddr(val)) { BX_ERROR(("SetCR3(): Attempt to write to reserved bits of CR3 !")); return 0; } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_WRITE_INTERCEPTED(3)) Svm_Vmexit(SVM_VMEXIT_CR3_WRITE); } #endif BX_CPU_THIS_PTR cr3 = val; // flush TLB even if value does not change #if BX_CPU_LEVEL >= 6 if (BX_CPU_THIS_PTR cr4.get_PGE()) TLB_flushNonGlobal(); // Don't flush Global entries. else #endif TLB_flush(); // Flush Global entries also. return 1; } #if BX_CPU_LEVEL >= 5 bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::SetEFER(bx_address val_64) { Bit32u val32 = (Bit32u) val_64; if (val_64 & ~((Bit64u) BX_CPU_THIS_PTR efer_suppmask)) { BX_ERROR(("SetEFER(0x%08x): attempt to set reserved bits of EFER MSR !", val32)); return 0; } #if BX_SUPPORT_X86_64 /* #GP(0) if changing EFER.LME when cr0.pg = 1 */ if ((BX_CPU_THIS_PTR efer.get_LME() != ((val32 >> 8) & 1)) && BX_CPU_THIS_PTR cr0.get_PG()) { BX_ERROR(("SetEFER: attempt to change LME when CR0.PG=1")); return 0; } #endif BX_CPU_THIS_PTR efer.set32((val32 & BX_CPU_THIS_PTR efer_suppmask & ~BX_EFER_LMA_MASK) | (BX_CPU_THIS_PTR efer.get32() & BX_EFER_LMA_MASK)); // keep LMA untouched return 1; } #endif #if BX_CPU_LEVEL >= 6 void BX_CPU_C::WriteCR8(bxInstruction_c *i, bx_address val) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_CR_WRITE_INTERCEPTED(8)) Svm_Vmexit(SVM_VMEXIT_CR8_WRITE); } #endif #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_CR8_Write(i); #endif // CR8 is aliased to APIC->TASK PRIORITY register // APIC.TPR[7:4] = CR8[3:0] // APIC.TPR[3:0] = 0 // Reads of CR8 return zero extended APIC.TPR[7:4] // Write to CR8 update APIC.TPR[7:4] if (val & BX_CONST64(0xfffffffffffffff0)) { BX_ERROR(("WriteCR8: Attempt to set reserved bits of CR8")); exception(BX_GP_EXCEPTION, 0); } unsigned tpr = (val & 0xf) << 4; #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { SVM_V_TPR = tpr; if (SVM_V_INTR_MASKING) return; } #endif #if BX_SUPPORT_VMX && BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW)) { VMX_Write_VTPR(tpr); return; } #endif BX_CPU_THIS_PTR lapic.set_tpr(tpr); } Bit32u BX_CPU_C::ReadCR8(bxInstruction_c *i) { #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if (SVM_CR_READ_INTERCEPTED(8)) Svm_Vmexit(SVM_VMEXIT_CR8_READ); if (SVM_V_INTR_MASKING) return SVM_V_TPR; } #endif #if BX_SUPPORT_VMX && BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR in_vmx_guest) VMexit_CR8_Read(i); if (BX_CPU_THIS_PTR in_vmx_guest && VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW)) { Bit32u tpr = (VMX_Read_VTPR() >> 4) & 0xf; return tpr; } #endif // CR8 is aliased to APIC->TASK PRIORITY register // APIC.TPR[7:4] = CR8[3:0] // APIC.TPR[3:0] = 0 // Reads of CR8 return zero extended APIC.TPR[7:4] // Write to CR8 update APIC.TPR[7:4] return BX_CPU_THIS_PTR get_cr8(); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLTS(bxInstruction_c *i) { // CPL is always 0 in real mode if (/* !real_mode() && */ CPL!=0) { BX_ERROR(("CLTS: priveledge check failed, generate #GP(0)")); exception(BX_GP_EXCEPTION, 0); } #if BX_SUPPORT_VMX if (BX_CPU_THIS_PTR in_vmx_guest) { if(VMexit_CLTS()) { BX_NEXT_TRACE(i); } } #endif #if BX_SUPPORT_SVM if (BX_CPU_THIS_PTR in_svm_guest) { if(SVM_CR_WRITE_INTERCEPTED(0)) Svm_Vmexit(SVM_VMEXIT_CR0_WRITE); } #endif BX_CPU_THIS_PTR cr0.set_TS(0); #if BX_CPU_LEVEL >= 6 handleSseModeChange(); #if BX_SUPPORT_AVX handleAvxModeChange(); #endif #endif BX_NEXT_TRACE(i); } #if BX_X86_DEBUGGER bx_bool BX_CPU_C::hwbreakpoint_check(bx_address laddr, unsigned opa, unsigned opb) { laddr = LPFOf(laddr); Bit32u dr_op[4]; dr_op[0] = BX_CPU_THIS_PTR dr7.get_R_W0(); dr_op[1] = BX_CPU_THIS_PTR dr7.get_R_W1(); dr_op[2] = BX_CPU_THIS_PTR dr7.get_R_W2(); dr_op[3] = BX_CPU_THIS_PTR dr7.get_R_W3(); for (int n=0;n<4;n++) { if ((dr_op[n] == opa || dr_op[n] == opb) && laddr == LPFOf(BX_CPU_THIS_PTR dr[n])) { return 1; } } return 0; } Bit32u BX_CPU_C::code_breakpoint_match(bx_address laddr) { if (BX_CPU_THIS_PTR get_RF() || BX_CPU_THIS_PTR in_repeat) return 0; if (BX_CPU_THIS_PTR dr7.get_bp_enabled()) { Bit32u dr6_bits = hwdebug_compare(laddr, 1, BX_HWDebugInstruction, BX_HWDebugInstruction); return dr6_bits; } return 0; } void BX_CPU_C::hwbreakpoint_match(bx_address laddr, unsigned len, unsigned rw) { if (BX_CPU_THIS_PTR dr7.get_bp_enabled()) { // Only compare debug registers if any breakpoints are enabled unsigned opa, opb, write = rw & 1; opa = BX_HWDebugMemRW; // Read or Write always compares vs 11b if (! write) // only compares vs 11b opb = opa; else // BX_WRITE or BX_RW; also compare vs 01b opb = BX_HWDebugMemW; Bit32u dr6_bits = hwdebug_compare(laddr, len, opa, opb); if (dr6_bits) { BX_CPU_THIS_PTR debug_trap |= dr6_bits; if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_HIT) { BX_ERROR(("#DB: Code/Data breakpoint hit - report debug trap on next instruction")); BX_CPU_THIS_PTR async_event = 1; } } } } Bit32u BX_CPU_C::hwdebug_compare(bx_address laddr_0, unsigned size, unsigned opa, unsigned opb) { Bit32u dr7 = BX_CPU_THIS_PTR dr7.get32(); static bx_address alignment_mask[4] = // 00b=1 01b=2 10b=undef(8) 11b=4 { 0x0, 0x1, 0x7, 0x3 }; bx_address laddr_n = laddr_0 + (size - 1); Bit32u dr_op[4], dr_len[4]; // If *any* enabled breakpoints matched, then we need to // set status bits for *all* breakpoints, even disabled ones, // as long as they meet the other breakpoint criteria. // dr6_mask is the return value. These bits represent the bits // to be OR'd into DR6 as a result of the debug event. Bit32u dr6_mask = 0; dr_len[0] = BX_CPU_THIS_PTR dr7.get_LEN0(); dr_len[1] = BX_CPU_THIS_PTR dr7.get_LEN1(); dr_len[2] = BX_CPU_THIS_PTR dr7.get_LEN2(); dr_len[3] = BX_CPU_THIS_PTR dr7.get_LEN3(); dr_op[0] = BX_CPU_THIS_PTR dr7.get_R_W0(); dr_op[1] = BX_CPU_THIS_PTR dr7.get_R_W1(); dr_op[2] = BX_CPU_THIS_PTR dr7.get_R_W2(); dr_op[3] = BX_CPU_THIS_PTR dr7.get_R_W3(); for (unsigned n=0;n<4;n++) { bx_address dr_start = BX_CPU_THIS_PTR dr[n] & ~alignment_mask[dr_len[n]]; bx_address dr_end = dr_start + alignment_mask[dr_len[n]]; // See if this instruction address matches any breakpoints if ((dr_op[n]==opa || dr_op[n]==opb) && (laddr_0 <= dr_end) && (laddr_n >= dr_start)) { dr6_mask |= (1<= 5 void BX_CPU_C::iobreakpoint_match(unsigned port, unsigned len) { // Only compare debug registers if any breakpoints are enabled if (BX_CPU_THIS_PTR cr4.get_DE() && BX_CPU_THIS_PTR dr7.get_bp_enabled()) { Bit32u dr6_bits = hwdebug_compare(port, len, BX_HWDebugIO, BX_HWDebugIO); if (dr6_bits) { BX_CPU_THIS_PTR debug_trap |= dr6_bits; if (BX_CPU_THIS_PTR debug_trap & BX_DEBUG_TRAP_HIT) { BX_ERROR(("#DB: I/O breakpoint hit - report debug trap on next instruction")); BX_CPU_THIS_PTR async_event = 1; } } } } #endif #endif bochs-2.6/cpu/fetchdecode_avx.h0000644000175000017500000027556012020641453016424 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fetchdecode_avx.h 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_AVX_FETCHDECODE_TABLES_H #define BX_AVX_FETCHDECODE_TABLES_H #if BX_SUPPORT_AVX && BX_CPU_LEVEL >= 6 /* ************************************************************************ */ static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_f30f2a[2] = { /* 0 */ { 0, BX_IA_VCVTSI2SS_VssEd }, /* 1 */ { 0, BX_IA_VCVTSI2SS_VssEq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_f20f2a[2] = { /* 0 */ { 0, BX_IA_VCVTSI2SD_VsdEd }, /* 1 */ { 0, BX_IA_VCVTSI2SD_VsdEq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_f30f2c[2] = { /* 0 */ { 0, BX_IA_VCVTTSS2SI_GdWss }, /* 1 */ { 0, BX_IA_VCVTTSS2SI_GqWss } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_f20f2c[2] = { /* 0 */ { 0, BX_IA_VCVTTSD2SI_GdWsd }, /* 1 */ { 0, BX_IA_VCVTTSD2SI_GqWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_f30f2d[2] = { /* 0 */ { 0, BX_IA_VCVTSS2SI_GdWss }, /* 1 */ { 0, BX_IA_VCVTSS2SI_GqWss } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_f20f2d[2] = { /* 0 */ { 0, BX_IA_VCVTSD2SI_GdWsd }, /* 1 */ { 0, BX_IA_VCVTSD2SI_GqWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f6e[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_V128_VMOVD_VdqEd }, /* 1 */ { BxPrefixSSE66, BX_IA_V128_VMOVQ_VdqEq }, }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_660f7e[2] = { /* 0 */ { 0, BX_IA_V128_VMOVD_EdVd }, /* 1 */ { 0, BX_IA_V128_VMOVQ_EqVq }, }; static const BxOpcodeInfo_t BxOpcodeInfoAVX128_VexW_0f3a16[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_V128_VPEXTRD_EdVdqIb }, /* 1 */ { BxPrefixSSE66, BX_IA_V128_VPEXTRQ_EqVdqIb } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f3818[2] = { /* R */ { BxPrefixSSE66 | BxVexW0, BX_IA_VBROADCASTSS_VpsWss }, /* M */ { BxPrefixSSE66 | BxVexW0, BX_IA_VBROADCASTSS_VpsMss } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f3819[2] = { /* R */ { BxPrefixSSE66 | BxVexW0, BX_IA_V256_VBROADCASTSD_VpdWsd }, /* M */ { BxPrefixSSE66 | BxVexW0, BX_IA_V256_VBROADCASTSD_VpdMsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX128_VexW_0f3a22[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_V128_VPINSRD_VdqEdIb }, /* 1 */ { BxPrefixSSE66, BX_IA_V128_VPINSRQ_VdqEqIb } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3845[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VPSRLVD_VdqHdqWdq }, /* 1 */ { BxPrefixSSE66, BX_IA_VPSRLVQ_VdqHdqWdq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3847[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VPSLLVD_VdqHdqWdq }, /* 1 */ { BxPrefixSSE66, BX_IA_VPSLLVQ_VdqHdqWdq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f388c[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VMASKMOVD_VdqHdqMdq }, /* 1 */ { BxPrefixSSE66, BX_IA_VMASKMOVQ_VdqHdqMdq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f388e[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VMASKMOVD_MdqHdqVdq }, /* 1 */ { BxPrefixSSE66, BX_IA_VMASKMOVQ_MdqHdqVdq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3890[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VGATHERDD_VdqHdq }, /* 1 */ { BxPrefixSSE66, BX_IA_VGATHERDQ_VdqHdq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3891[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VGATHERQD_VdqHdq }, /* 1 */ { BxPrefixSSE66, BX_IA_VGATHERQQ_VdqHdq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3892[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VGATHERDPS_VpsHps }, /* 1 */ { BxPrefixSSE66, BX_IA_VGATHERDPD_VpdHpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3893[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VGATHERQPS_VpsHps }, /* 1 */ { BxPrefixSSE66, BX_IA_VGATHERQPD_VpdHpd } }; // FMA static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3896[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADDSUB132PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADDSUB132PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3897[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUBADD132PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUBADD132PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3898[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADD132PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADD132PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3899[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADD132SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADD132SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f389a[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUB132PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUB132PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f389b[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUB132SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUB132SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f389c[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMADD132PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMADD132PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f389d[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMADD132SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMADD132SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f389e[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMSUB132PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMSUB132PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f389f[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMSUB132SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMSUB132SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38a6[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADDSUB213PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADDSUB213PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38a7[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUBADD213PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUBADD213PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38a8[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADD213PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADD213PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38a9[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADD213SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADD213SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38aa[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUB213PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUB213PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38ab[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUB213SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUB213SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38ac[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMADD213PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMADD213PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38ad[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMADD213SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMADD213SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38ae[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMSUB213PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMSUB213PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38af[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMSUB213SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMSUB213SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38b6[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADDSUB231PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADDSUB231PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38b7[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUBADD231PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUBADD231PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38b8[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADD231PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADD231PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38b9[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMADD231SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMADD231SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38ba[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUB231PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUB231PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38bb[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFMSUB231SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFMSUB231SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38bc[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMADD231PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMADD231PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38bd[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMADD231SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMADD231SD_VpdHsdWsd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38be[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMSUB231PS_VpsHpsWps }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMSUB231PD_VpdHpdWpd } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38bf[2] = { /* 0 */ { BxPrefixSSE66, BX_IA_VFNMSUB231SS_VpsHssWss }, /* 1 */ { BxPrefixSSE66, BX_IA_VFNMSUB231SD_VpdHsdWsd } }; // FMA // BMI static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38f2[2] = { /* 0 */ { BxPrefixSSE, BX_IA_ANDN_GdBdEd, BxOpcodeGroupSSE_ERR }, /* 1 */ { BxPrefixSSE, BX_IA_ANDN_GqBqEq, BxOpcodeGroupSSE_ERR } }; static const BxOpcodeInfo_t BxOpcodeInfoAVXG17VEXW0[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { BxPrefixSSE, BX_IA_BLSR_BdEd, BxOpcodeGroupSSE_ERR }, /* 2 */ { BxPrefixSSE, BX_IA_BLSMSK_BdEd, BxOpcodeGroupSSE_ERR }, /* 3 */ { BxPrefixSSE, BX_IA_BLSI_BdEd, BxOpcodeGroupSSE_ERR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoAVXG17VEXW1[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { BxPrefixSSE, BX_IA_BLSR_BqEq, BxOpcodeGroupSSE_ERR }, /* 2 */ { BxPrefixSSE, BX_IA_BLSMSK_BqEq, BxOpcodeGroupSSE_ERR }, /* 3 */ { BxPrefixSSE, BX_IA_BLSI_BqEq, BxOpcodeGroupSSE_ERR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38f3[2] = { /* 0 */ { BxGroup17, BX_IA_ERROR, BxOpcodeInfoAVXG17VEXW0 }, /* 1 */ { BxGroup17, BX_IA_ERROR, BxOpcodeInfoAVXG17VEXW1 } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f38f5_VEX0[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_PEXT_GdEdBd }, /* F2 */ { 0, BX_IA_PDEP_GdEdBd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f38f5_VEX1[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_PEXT_GqEqBq }, /* F2 */ { 0, BX_IA_PDEP_GqEqBq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38f5[2] = { /* 0 */ { BxPrefixSSE, BX_IA_BZHI_GdEdBd, BxOpcodeGroupAVX_0f38f5_VEX0 }, /* 1 */ { BxPrefixSSE, BX_IA_BZHI_GqEqBq, BxOpcodeGroupAVX_0f38f5_VEX1 } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38f6[2] = { /* 0 */ { BxPrefixSSEF2, BX_IA_MULX_GdBdEd }, /* 1 */ { BxPrefixSSEF2, BX_IA_MULX_GqBqEq } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f38f7_VEX0[3] = { /* 66 */ { 0, BX_IA_SHLX_GdEdBd }, /* F3 */ { 0, BX_IA_SARX_GdEdBd }, /* F2 */ { 0, BX_IA_SHRX_GdEdBd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f38f7_VEX1[3] = { /* 66 */ { 0, BX_IA_SHLX_GqEqBq }, /* F3 */ { 0, BX_IA_SARX_GqEqBq }, /* F2 */ { 0, BX_IA_SHRX_GqEqBq } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f38f7[2] = { /* 0 */ { BxPrefixSSE, BX_IA_BEXTR_GdEdBd, BxOpcodeGroupAVX_0f38f7_VEX0 }, /* 1 */ { BxPrefixSSE, BX_IA_BEXTR_GqEqBq, BxOpcodeGroupAVX_0f38f7_VEX1 } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX_VexW_0f3af0[2] = { /* 0 */ { BxPrefixSSEF2, BX_IA_RORX_GdEdIb, BxOpcodeGroupSSE_ERR }, /* 1 */ { BxPrefixSSEF2, BX_IA_RORX_GqEqIb, BxOpcodeGroupSSE_ERR } }; // BMI /* ************************************************************************ */ /* ********** */ /* SSE Groups */ /* ********** */ static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0f10[3] = { /* 66 */ { 0, BX_IA_VMOVUPD_VpdWpd }, /* F3 */ { 0, BX_IA_V128_VMOVSS_VssHpsWss }, /* F2 */ { 0, BX_IA_V128_VMOVSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX256_0f10[3] = { /* 66 */ { 0, BX_IA_VMOVUPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0f11[3] = { /* 66 */ { 0, BX_IA_VMOVUPD_WpdVpd }, /* F3 */ { 0, BX_IA_V128_VMOVSS_WssHpsVss }, /* F2 */ { 0, BX_IA_V128_VMOVSD_WsdHpdVsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX256_0f11[3] = { /* 66 */ { 0, BX_IA_VMOVUPD_WpdVpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0f12[3] = { /* 66 */ { 0, BX_IA_V128_VMOVLPD_VpdHpdMq }, /* F3 */ { 0, BX_IA_VMOVSLDUP_VpsWps }, /* F2 */ { 0, BX_IA_VMOVDDUP_VpdWpd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX256_0f12[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_VMOVSLDUP_VpsWps }, /* F2 */ { 0, BX_IA_VMOVDDUP_VpdWpd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0f13M[3] = { /* 66 */ { 0, BX_IA_V128_VMOVLPD_MqVsd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f14[3] = { /* 66 */ { 0, BX_IA_VUNPCKLPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f15[3] = { /* 66 */ { 0, BX_IA_VUNPCKHPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0f16[3] = { /* 66 */ { 0, BX_IA_V128_VMOVHPD_VpdHpdMq }, /* F3 */ { 0, BX_IA_VMOVSHDUP_VpsWps }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0f17M[3] = { /* 66 */ { 0, BX_IA_V128_VMOVHPD_MqVsd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f28[3] = { /* 66 */ { 0, BX_IA_VMOVAPD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f29[3] = { /* 66 */ { 0, BX_IA_VMOVAPD_WpdVpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f2a[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_f30f2a }, /* F2 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_f20f2a } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f2bM[3] = { /* 66 */ { 0, BX_IA_VMOVNTPD_MpdVpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f2c[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_f30f2c }, /* F2 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_f20f2c } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f2d[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_f30f2d }, /* F2 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_f20f2d } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f2e[3] = { /* 66 */ { 0, BX_IA_VUCOMISD_VsdWsd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f2f[3] = { /* 66 */ { 0, BX_IA_VCOMISD_VpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f50R[3] = { /* 66 */ { 0, BX_IA_VMOVMSKPD_GdVRpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f51[3] = { /* 66 */ { 0, BX_IA_VSQRTPD_VpdWpd }, /* F3 */ { 0, BX_IA_VSQRTSS_VssHpsWss }, /* F2 */ { 0, BX_IA_VSQRTSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f52[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_VRSQRTSS_VssHpsWss }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f53[3] = { /* 66 */ { 0, BX_IA_ERROR }, /* F3 */ { 0, BX_IA_VRCPSS_VssHpsWss }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f54[3] = { /* 66 */ { 0, BX_IA_VANDPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f55[3] = { /* 66 */ { 0, BX_IA_VANDNPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f56[3] = { /* 66 */ { 0, BX_IA_VORPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f57[3] = { /* 66 */ { 0, BX_IA_VXORPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f58[3] = { /* 66 */ { 0, BX_IA_VADDPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_VADDSS_VssHpsWss }, /* F2 */ { 0, BX_IA_VADDSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f59[3] = { /* 66 */ { 0, BX_IA_VMULPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_VMULSS_VssHpsWss }, /* F2 */ { 0, BX_IA_VMULSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f5a[3] = { /* 66 */ { 0, BX_IA_VCVTPD2PS_VpsWpd }, /* F3 */ { 0, BX_IA_VCVTSS2SD_VsdWss }, /* F2 */ { 0, BX_IA_VCVTSD2SS_VssWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f5b[3] = { /* 66 */ { 0, BX_IA_VCVTPS2DQ_VdqWps }, /* F3 */ { 0, BX_IA_VCVTTPS2DQ_VdqWps }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f5c[3] = { /* 66 */ { 0, BX_IA_VSUBPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_VSUBSS_VssHpsWss }, /* F2 */ { 0, BX_IA_VSUBSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f5d[3] = { /* 66 */ { 0, BX_IA_VMINPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_VMINSS_VssHpsWss }, /* F2 */ { 0, BX_IA_VMINSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f5e[3] = { /* 66 */ { 0, BX_IA_VDIVPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_VDIVSS_VssHpsWss }, /* F2 */ { 0, BX_IA_VDIVSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f5f[3] = { /* 66 */ { 0, BX_IA_VMAXPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_VMAXSS_VssHpsWss }, /* F2 */ { 0, BX_IA_VMAXSD_VsdHpdWsd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f6f[3] = { /* 66 */ { 0, BX_IA_VMOVDQA_VdqWdq }, /* F3 */ { 0, BX_IA_VMOVDQU_VdqWdq }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0f70[3] = { /* 66 */ { 0, BX_IA_V128_VPSHUFD_VdqWdqIb }, /* F3 */ { 0, BX_IA_V128_VPSHUFHW_VdqWdqIb }, /* F2 */ { 0, BX_IA_V128_VPSHUFLW_VdqWdqIb } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX256_0f70[3] = { /* 66 */ { 0, BX_IA_V256_VPSHUFD_VdqWdqIb }, /* F3 */ { 0, BX_IA_V256_VPSHUFHW_VdqWdqIb }, /* F2 */ { 0, BX_IA_V256_VPSHUFLW_VdqWdqIb } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f7c[3] = { /* 66 */ { 0, BX_IA_VHADDPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_VHADDPS_VpsHpsWps } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f7d[3] = { /* 66 */ { 0, BX_IA_VHSUBPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_VHSUBPS_VpsHpsWps } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f7e[3] = { /* 66 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_660f7e }, /* F3 */ { 0, BX_IA_VMOVQ_VqWq }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0f7f[3] = { /* 66 */ { 0, BX_IA_VMOVDQA_WdqVdq }, /* F3 */ { 0, BX_IA_VMOVDQU_WdqVdq }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0fc2[3] = { /* 66 */ { 0, BX_IA_VCMPPD_VpdHpdWpdIb }, /* F3 */ { 0, BX_IA_VCMPSS_VssHpsWssIb }, /* F2 */ { 0, BX_IA_VCMPSD_VsdHpdWsdIb } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0fc6[3] = { /* 66 */ { 0, BX_IA_VSHUFPD_VpdHpdWpdIb }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX_0fd0[3] = { /* 66 */ { 0, BX_IA_VADDSUBPD_VpdHpdWpd }, /* F3 */ { 0, BX_IA_ERROR }, /* F2 */ { 0, BX_IA_VADDSUBPS_VpsHpsWps } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX128_0fe6[3] = { /* 66 */ { 0, BX_IA_VCVTTPD2DQ_VqWpd }, /* F3 */ { 0, BX_IA_V128_VCVTDQ2PD_VpdWq }, /* F2 */ { 0, BX_IA_VCVTPD2DQ_VqWpd } }; static const BxOpcodeInfo_t BxOpcodeGroupAVX256_0fe6[3] = { /* 66 */ { 0, BX_IA_VCVTTPD2DQ_VqWpd }, /* F3 */ { 0, BX_IA_V256_VCVTDQ2PD_VpdWq }, /* F2 */ { 0, BX_IA_VCVTPD2DQ_VqWpd } }; /* ******** */ /* Group 12 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoAVX128G12R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSRLW_UdqIb }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSRAW_UdqIb }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSLLW_UdqIb }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX256G12R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSRLW_UdqIb }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSRAW_UdqIb }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSLLW_UdqIb }, /* 7 */ { 0, BX_IA_ERROR } }; /* ******** */ /* Group 13 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoAVX128G13R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSRLD_UdqIb }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSRAD_UdqIb }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSLLD_UdqIb }, /* 7 */ { 0, BX_IA_ERROR } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX256G13R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSRLD_UdqIb }, /* 3 */ { 0, BX_IA_ERROR }, /* 4 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSRAD_UdqIb }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSLLD_UdqIb }, /* 7 */ { 0, BX_IA_ERROR } }; /* ******** */ /* Group 14 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoAVX128G14R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSRLQ_UdqIb }, /* 3 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSRLDQ_UdqIb }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSLLQ_UdqIb }, /* 7 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V128_VPSLLDQ_UdqIb } }; static const BxOpcodeInfo_t BxOpcodeInfoAVX256G14R[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSRLQ_UdqIb }, /* 3 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSRLDQ_UdqIb }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSLLQ_UdqIb }, /* 7 */ { BxImmediate_Ib | BxPrefixSSE66, BX_IA_V256_VPSLLDQ_UdqIb } }; /* ******** */ /* Group 15 */ /* ******** */ static const BxOpcodeInfo_t BxOpcodeInfoAVXG15M[8] = { /* 0 */ { 0, BX_IA_ERROR }, /* 1 */ { 0, BX_IA_ERROR }, /* 2 */ { BxPrefixSSE, BX_IA_VLDMXCSR, BxOpcodeGroupSSE_ERR }, /* 3 */ { BxPrefixSSE, BX_IA_VSTMXCSR, BxOpcodeGroupSSE_ERR }, /* 4 */ { 0, BX_IA_ERROR }, /* 5 */ { 0, BX_IA_ERROR }, /* 6 */ { 0, BX_IA_ERROR }, /* 7 */ { 0, BX_IA_ERROR } }; /* ************************************************************************ */ static const BxOpcodeInfo_t BxOpcodeTableAVX[256*3*2] = { // 256 entries for VEX-encoded 0x0F opcodes (VEX.L=0) /* 00 /0 */ { 0, BX_IA_ERROR }, /* 01 /0 */ { 0, BX_IA_ERROR }, /* 02 /0 */ { 0, BX_IA_ERROR }, /* 03 /0 */ { 0, BX_IA_ERROR }, /* 04 /0 */ { 0, BX_IA_ERROR }, /* 05 /0 */ { 0, BX_IA_ERROR }, /* 06 /0 */ { 0, BX_IA_ERROR }, /* 07 /0 */ { 0, BX_IA_ERROR }, /* 08 /0 */ { 0, BX_IA_ERROR }, /* 09 /0 */ { 0, BX_IA_ERROR }, /* 0A /0 */ { 0, BX_IA_ERROR }, /* 0B /0 */ { 0, BX_IA_ERROR }, /* 0C /0 */ { 0, BX_IA_ERROR }, /* 0D /0 */ { 0, BX_IA_ERROR }, /* 0E /0 */ { 0, BX_IA_ERROR }, /* 0F /0 */ { 0, BX_IA_ERROR }, /* 10 /0 */ { BxPrefixSSE, BX_IA_VMOVUPS_VpsWps, BxOpcodeGroupAVX128_0f10 }, /* 11 /0 */ { BxPrefixSSE, BX_IA_VMOVUPS_WpsVps, BxOpcodeGroupAVX128_0f11 }, /* 12 /0 */ { BxPrefixSSE, BX_IA_V128_VMOVLPS_VpsHpsMq, BxOpcodeGroupAVX128_0f12 }, /* 13 /0 */ { BxPrefixSSE, BX_IA_V128_VMOVLPS_MqVps, BxOpcodeGroupAVX128_0f13M }, /* 14 /0 */ { BxPrefixSSE, BX_IA_VUNPCKLPS_VpsHpsWps, BxOpcodeGroupAVX_0f14 }, /* 15 /0 */ { BxPrefixSSE, BX_IA_VUNPCKHPS_VpsHpsWps, BxOpcodeGroupAVX_0f15 }, /* 16 /0 */ { BxPrefixSSE, BX_IA_V128_VMOVHPS_VpsHpsMq, BxOpcodeGroupAVX128_0f16 }, /* 17 /0 */ { BxPrefixSSE, BX_IA_V128_VMOVHPS_MqVps, BxOpcodeGroupAVX128_0f17M }, /* 18 /0 */ { 0, BX_IA_ERROR }, /* 19 /0 */ { 0, BX_IA_ERROR }, /* 1A /0 */ { 0, BX_IA_ERROR }, /* 1B /0 */ { 0, BX_IA_ERROR }, /* 1C /0 */ { 0, BX_IA_ERROR }, /* 1D /0 */ { 0, BX_IA_ERROR }, /* 1E /0 */ { 0, BX_IA_ERROR }, /* 1F /0 */ { 0, BX_IA_ERROR }, /* 20 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 21 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 22 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 23 /0 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 24 /0 */ { 0, BX_IA_ERROR }, /* 25 /0 */ { 0, BX_IA_ERROR }, /* 26 /0 */ { 0, BX_IA_ERROR }, /* 27 /0 */ { 0, BX_IA_ERROR }, /* 28 /0 */ { BxPrefixSSE, BX_IA_VMOVAPS_VpsWps, BxOpcodeGroupAVX_0f28 }, /* 29 /0 */ { BxPrefixSSE, BX_IA_VMOVAPS_WpsVps, BxOpcodeGroupAVX_0f29 }, /* 2A /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f2a }, /* 2B /0 */ { BxPrefixSSE, BX_IA_VMOVNTPS_MpsVps, BxOpcodeGroupAVX_0f2bM }, /* 2C /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f2c }, /* 2D /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f2d }, /* 2E /0 */ { BxPrefixSSE, BX_IA_VUCOMISS_VssWss, BxOpcodeGroupAVX_0f2e }, /* 2F /0 */ { BxPrefixSSE, BX_IA_VCOMISS_VpsWps, BxOpcodeGroupAVX_0f2f }, /* 30 /0 */ { 0, BX_IA_ERROR }, /* 31 /0 */ { 0, BX_IA_ERROR }, /* 32 /0 */ { 0, BX_IA_ERROR }, /* 33 /0 */ { 0, BX_IA_ERROR }, /* 34 /0 */ { 0, BX_IA_ERROR }, /* 35 /0 */ { 0, BX_IA_ERROR }, /* 36 /0 */ { 0, BX_IA_ERROR }, /* 37 /0 */ { 0, BX_IA_ERROR }, /* 38 /0 */ { 0, BX_IA_ERROR }, // 3-Byte Escape /* 39 /0 */ { 0, BX_IA_ERROR }, /* 3A /0 */ { 0, BX_IA_ERROR }, // 3-Byte Escape /* 3B /0 */ { 0, BX_IA_ERROR }, /* 3C /0 */ { 0, BX_IA_ERROR }, /* 3D /0 */ { 0, BX_IA_ERROR }, /* 3E /0 */ { 0, BX_IA_ERROR }, /* 3F /0 */ { 0, BX_IA_ERROR }, /* 40 /0 */ { 0, BX_IA_ERROR }, /* 41 /0 */ { 0, BX_IA_ERROR }, /* 42 /0 */ { 0, BX_IA_ERROR }, /* 43 /0 */ { 0, BX_IA_ERROR }, /* 44 /0 */ { 0, BX_IA_ERROR }, /* 45 /0 */ { 0, BX_IA_ERROR }, /* 46 /0 */ { 0, BX_IA_ERROR }, /* 47 /0 */ { 0, BX_IA_ERROR }, /* 48 /0 */ { 0, BX_IA_ERROR }, /* 49 /0 */ { 0, BX_IA_ERROR }, /* 4A /0 */ { 0, BX_IA_ERROR }, /* 4B /0 */ { 0, BX_IA_ERROR }, /* 4C /0 */ { 0, BX_IA_ERROR }, /* 4D /0 */ { 0, BX_IA_ERROR }, /* 4E /0 */ { 0, BX_IA_ERROR }, /* 4F /0 */ { 0, BX_IA_ERROR }, /* 50 /0 */ { BxPrefixSSE, BX_IA_VMOVMSKPS_GdVRps, BxOpcodeGroupAVX_0f50R }, /* 51 /0 */ { BxPrefixSSE, BX_IA_VSQRTPS_VpsWps, BxOpcodeGroupAVX_0f51 }, /* 52 /0 */ { BxPrefixSSE, BX_IA_VRSQRTPS_VpsWps, BxOpcodeGroupAVX_0f52 }, /* 53 /0 */ { BxPrefixSSE, BX_IA_VRCPPS_VpsWps, BxOpcodeGroupAVX_0f53 }, /* 54 /0 */ { BxPrefixSSE, BX_IA_VANDPS_VpsHpsWps, BxOpcodeGroupAVX_0f54 }, /* 55 /0 */ { BxPrefixSSE, BX_IA_VANDNPS_VpsHpsWps, BxOpcodeGroupAVX_0f55 }, /* 56 /0 */ { BxPrefixSSE, BX_IA_VORPS_VpsHpsWps, BxOpcodeGroupAVX_0f56 }, /* 57 /0 */ { BxPrefixSSE, BX_IA_VXORPS_VpsHpsWps, BxOpcodeGroupAVX_0f57 }, /* 58 /0 */ { BxPrefixSSE, BX_IA_VADDPS_VpsHpsWps, BxOpcodeGroupAVX_0f58 }, /* 59 /0 */ { BxPrefixSSE, BX_IA_VMULPS_VpsHpsWps, BxOpcodeGroupAVX_0f59 }, /* 5A /0 */ { BxPrefixSSE, BX_IA_V128_VCVTPS2PD_VpdWps, BxOpcodeGroupAVX_0f5a }, /* 5B /0 */ { BxPrefixSSE, BX_IA_VCVTDQ2PS_VpsWdq, BxOpcodeGroupAVX_0f5b }, /* 5C /0 */ { BxPrefixSSE, BX_IA_VSUBPS_VpsHpsWps, BxOpcodeGroupAVX_0f5c }, /* 5D /0 */ { BxPrefixSSE, BX_IA_VMINPS_VpsHpsWps, BxOpcodeGroupAVX_0f5d }, /* 5E /0 */ { BxPrefixSSE, BX_IA_VDIVPS_VpsHpsWps, BxOpcodeGroupAVX_0f5e }, /* 5F /0 */ { BxPrefixSSE, BX_IA_VMAXPS_VpsHpsWps, BxOpcodeGroupAVX_0f5f }, /* 60 /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKLBW_VdqHdqWdq }, /* 61 /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKLWD_VdqHdqWdq }, /* 62 /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKLDQ_VdqHdqWdq }, /* 63 /0 */ { BxPrefixSSE66, BX_IA_V128_VPACKSSWB_VdqHdqWdq }, /* 64 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPGTB_VdqHdqWdq }, /* 65 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPGTW_VdqHdqWdq }, /* 66 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPGTD_VdqHdqWdq }, /* 67 /0 */ { BxPrefixSSE66, BX_IA_V128_VPACKUSWB_VdqHdqWdq }, /* 68 /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKHBW_VdqHdqWdq }, /* 69 /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKHWD_VdqHdqWdq }, /* 6A /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKHDQ_VdqHdqWdq }, /* 6B /0 */ { BxPrefixSSE66, BX_IA_V128_VPACKSSDW_VdqHdqWdq }, /* 6C /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKLQDQ_VdqHdqWdq }, /* 6D /0 */ { BxPrefixSSE66, BX_IA_V128_VPUNPCKHQDQ_VdqHdqWdq }, /* 6E /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f6e }, /* 6F /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f6f }, /* 70 /0 */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeGroupAVX128_0f70 }, /* 71 /0 */ { BxGroup12, BX_IA_ERROR, BxOpcodeInfoAVX128G12R }, /* 72 /0 */ { BxGroup13, BX_IA_ERROR, BxOpcodeInfoAVX128G13R }, /* 73 /0 */ { BxGroup14, BX_IA_ERROR, BxOpcodeInfoAVX128G14R }, /* 74 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPEQB_VdqHdqWdq }, /* 75 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPEQW_VdqHdqWdq }, /* 76 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPEQD_VdqHdqWdq }, /* 77 /0 */ { BxPrefixSSE, BX_IA_VZEROUPPER, BxOpcodeGroupSSE_ERR }, /* 78 /0 */ { 0, BX_IA_ERROR }, /* 79 /0 */ { 0, BX_IA_ERROR }, /* 7A /0 */ { 0, BX_IA_ERROR }, /* 7B /0 */ { 0, BX_IA_ERROR }, /* 7C /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f7c }, /* 7D /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f7d }, /* 7E /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f7e }, /* 7F /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f7f }, /* 80 /0 */ { 0, BX_IA_ERROR }, /* 81 /0 */ { 0, BX_IA_ERROR }, /* 82 /0 */ { 0, BX_IA_ERROR }, /* 83 /0 */ { 0, BX_IA_ERROR }, /* 84 /0 */ { 0, BX_IA_ERROR }, /* 85 /0 */ { 0, BX_IA_ERROR }, /* 86 /0 */ { 0, BX_IA_ERROR }, /* 87 /0 */ { 0, BX_IA_ERROR }, /* 88 /0 */ { 0, BX_IA_ERROR }, /* 89 /0 */ { 0, BX_IA_ERROR }, /* 8A /0 */ { 0, BX_IA_ERROR }, /* 8B /0 */ { 0, BX_IA_ERROR }, /* 8C /0 */ { 0, BX_IA_ERROR }, /* 8D /0 */ { 0, BX_IA_ERROR }, /* 8E /0 */ { 0, BX_IA_ERROR }, /* 8F /0 */ { 0, BX_IA_ERROR }, /* 90 /0 */ { 0, BX_IA_ERROR }, /* 91 /0 */ { 0, BX_IA_ERROR }, /* 92 /0 */ { 0, BX_IA_ERROR }, /* 93 /0 */ { 0, BX_IA_ERROR }, /* 94 /0 */ { 0, BX_IA_ERROR }, /* 95 /0 */ { 0, BX_IA_ERROR }, /* 96 /0 */ { 0, BX_IA_ERROR }, /* 97 /0 */ { 0, BX_IA_ERROR }, /* 98 /0 */ { 0, BX_IA_ERROR }, /* 99 /0 */ { 0, BX_IA_ERROR }, /* 9A /0 */ { 0, BX_IA_ERROR }, /* 9B /0 */ { 0, BX_IA_ERROR }, /* 9C /0 */ { 0, BX_IA_ERROR }, /* 9D /0 */ { 0, BX_IA_ERROR }, /* 9E /0 */ { 0, BX_IA_ERROR }, /* 9F /0 */ { 0, BX_IA_ERROR }, /* A0 /0 */ { 0, BX_IA_ERROR }, /* A1 /0 */ { 0, BX_IA_ERROR }, /* A2 /0 */ { 0, BX_IA_ERROR }, /* A3 /0 */ { 0, BX_IA_ERROR }, /* A4 /0 */ { 0, BX_IA_ERROR }, /* A5 /0 */ { 0, BX_IA_ERROR }, /* A6 /0 */ { 0, BX_IA_ERROR }, /* A7 /0 */ { 0, BX_IA_ERROR }, /* A8 /0 */ { 0, BX_IA_ERROR }, /* A9 /0 */ { 0, BX_IA_ERROR }, /* AA /0 */ { 0, BX_IA_ERROR }, /* AB /0 */ { 0, BX_IA_ERROR }, /* AC /0 */ { 0, BX_IA_ERROR }, /* AD /0 */ { 0, BX_IA_ERROR }, /* AE /0 */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoAVXG15M }, /* AF /0 */ { 0, BX_IA_ERROR }, /* B0 /0 */ { 0, BX_IA_ERROR }, /* B1 /0 */ { 0, BX_IA_ERROR }, /* B2 /0 */ { 0, BX_IA_ERROR }, /* B3 /0 */ { 0, BX_IA_ERROR }, /* B4 /0 */ { 0, BX_IA_ERROR }, /* B5 /0 */ { 0, BX_IA_ERROR }, /* B6 /0 */ { 0, BX_IA_ERROR }, /* B7 /0 */ { 0, BX_IA_ERROR }, /* B8 /0 */ { 0, BX_IA_ERROR }, /* B9 /0 */ { 0, BX_IA_ERROR }, /* BA /0 */ { 0, BX_IA_ERROR }, /* BB /0 */ { 0, BX_IA_ERROR }, /* BC /0 */ { 0, BX_IA_ERROR }, /* BD /0 */ { 0, BX_IA_ERROR }, /* BE /0 */ { 0, BX_IA_ERROR }, /* BF /0 */ { 0, BX_IA_ERROR }, /* C0 /0 */ { 0, BX_IA_ERROR }, /* C1 /0 */ { 0, BX_IA_ERROR }, /* C2 /0 */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_VCMPPS_VpsHpsWpsIb, BxOpcodeGroupAVX_0fc2 }, /* C3 /0 */ { 0, BX_IA_ERROR }, /* C4 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPINSRW_VdqEwIb }, /* C5 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPEXTRW_GdUdqIb }, /* C6 /0 */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_VSHUFPS_VpsHpsWpsIb, BxOpcodeGroupAVX_0fc6 }, /* C7 /0 */ { 0, BX_IA_ERROR }, /* C8 /0 */ { 0, BX_IA_ERROR }, /* C9 /0 */ { 0, BX_IA_ERROR }, /* CA /0 */ { 0, BX_IA_ERROR }, /* CB /0 */ { 0, BX_IA_ERROR }, /* CC /0 */ { 0, BX_IA_ERROR }, /* CD /0 */ { 0, BX_IA_ERROR }, /* CE /0 */ { 0, BX_IA_ERROR }, /* CF /0 */ { 0, BX_IA_ERROR }, /* D0 /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0fd0 }, /* D1 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSRLW_VdqHdqWdq }, /* D2 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSRLD_VdqHdqWdq }, /* D3 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSRLQ_VdqHdqWdq }, /* D4 /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDQ_VdqHdqWdq }, /* D5 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMULLW_VdqHdqWdq }, /* D6 /0 */ { BxPrefixSSE66, BX_IA_VMOVQ_WqVq }, /* D7 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMOVMSKB_GdUdq }, /* D8 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBUSB_VdqHdqWdq }, /* D9 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBUSW_VdqHdqWdq }, /* DA /0 */ { BxPrefixSSE66, BX_IA_V128_VPMINUB_VdqHdqWdq }, /* DB /0 */ { BxPrefixSSE66, BX_IA_V128_VPAND_VdqHdqWdq }, /* DC /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDUSB_VdqHdqWdq }, /* DD /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDUSW_VdqHdqWdq }, /* DE /0 */ { BxPrefixSSE66, BX_IA_V128_VPMAXUB_VdqHdqWdq }, /* DF /0 */ { BxPrefixSSE66, BX_IA_V128_VPANDN_VdqHdqWdq }, /* E0 /0 */ { BxPrefixSSE66, BX_IA_V128_VPAVGB_VdqWdq }, /* E1 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSRAW_VdqHdqWdq }, /* E2 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSRAD_VdqHdqWdq }, /* E3 /0 */ { BxPrefixSSE66, BX_IA_V128_VPAVGW_VdqWdq }, /* E4 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMULHUW_VdqHdqWdq }, /* E5 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMULHW_VdqHdqWdq }, /* E6 /0 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX128_0fe6 }, /* E7 /0 */ { BxPrefixSSE66, BX_IA_VMOVNTDQ_MdqVdq }, /* E8 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBSB_VdqHdqWdq }, /* E9 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBSW_VdqHdqWdq }, /* EA /0 */ { BxPrefixSSE66, BX_IA_V128_VPMINSW_VdqHdqWdq }, /* EB /0 */ { BxPrefixSSE66, BX_IA_V128_VPOR_VdqHdqWdq }, /* EC /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDSB_VdqHdqWdq }, /* ED /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDSW_VdqHdqWdq }, /* EE /0 */ { BxPrefixSSE66, BX_IA_V128_VPMAXSW_VdqHdqWdq }, /* EF /0 */ { BxPrefixSSE66, BX_IA_V128_VPXOR_VdqHdqWdq }, /* F0 /0 */ { BxPrefixSSEF2, BX_IA_VLDDQU_VdqMdq }, /* F1 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSLLW_VdqHdqWdq }, /* F2 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSLLD_VdqHdqWdq }, /* F3 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSLLQ_VdqHdqWdq }, /* F4 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMULUDQ_VdqHdqWdq }, /* F5 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMADDWD_VdqHdqWdq }, /* F6 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSADBW_VdqHdqWdq }, /* F7 /0 */ { BxPrefixSSE66, BX_IA_V128_VMASKMOVDQU_VdqUdq }, /* F8 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBB_VdqHdqWdq }, /* F9 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBW_VdqHdqWdq }, /* FA /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBD_VdqHdqWdq }, /* FB /0 */ { BxPrefixSSE66, BX_IA_V128_VPSUBQ_VdqHdqWdq }, /* FC /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDB_VdqHdqWdq }, /* FD /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDW_VdqHdqWdq }, /* FE /0 */ { BxPrefixSSE66, BX_IA_V128_VPADDD_VdqHdqWdq }, /* FF /0 */ { 0, BX_IA_ERROR }, // 256 entries for VEX-encoded 0x0F 0x38 opcodes (VEX.L=0) /* 00 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSHUFB_VdqHdqWdq }, /* 01 /0 */ { BxPrefixSSE66, BX_IA_V128_VPHADDW_VdqHdqWdq }, /* 02 /0 */ { BxPrefixSSE66, BX_IA_V128_VPHADDD_VdqHdqWdq }, /* 03 /0 */ { BxPrefixSSE66, BX_IA_V128_VPHADDSW_VdqHdqWdq }, /* 04 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMADDUBSW_VdqHdqWdq }, /* 05 /0 */ { BxPrefixSSE66, BX_IA_V128_VPHSUBW_VdqHdqWdq }, /* 06 /0 */ { BxPrefixSSE66, BX_IA_V128_VPHSUBD_VdqHdqWdq }, /* 07 /0 */ { BxPrefixSSE66, BX_IA_V128_VPHSUBSW_VdqHdqWdq }, /* 08 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSIGNB_VdqHdqWdq }, /* 09 /0 */ { BxPrefixSSE66, BX_IA_V128_VPSIGNW_VdqHdqWdq }, /* 0A /0 */ { BxPrefixSSE66, BX_IA_V128_VPSIGND_VdqHdqWdq }, /* 0B /0 */ { BxPrefixSSE66, BX_IA_V128_VPMULHRSW_VdqHdqWdq }, /* 0C /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPERMILPS_VpsHpsWps }, /* 0D /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPERMILPD_VpdHpdWpd }, /* 0E /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VTESTPS_VpsWps }, /* 0F /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VTESTPD_VpdWpd }, /* 10 /0 */ { 0, BX_IA_ERROR }, /* 11 /0 */ { 0, BX_IA_ERROR }, /* 12 /0 */ { 0, BX_IA_ERROR }, /* 13 /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VCVTPH2PS_VpsWps }, /* 14 /0 */ { 0, BX_IA_ERROR }, /* 15 /0 */ { 0, BX_IA_ERROR }, /* 16 /0 */ { 0, BX_IA_ERROR }, /* 17 /0 */ { BxPrefixSSE66, BX_IA_VPTEST_VdqWdq }, /* 18 /0 */ { BxSplitMod11B, BX_IA_ERROR, BxOpcodeGroupAVX_0f3818 }, /* 19 /0 */ { 0, BX_IA_ERROR }, /* 1A /0 */ { 0, BX_IA_ERROR }, /* 1B /0 */ { 0, BX_IA_ERROR }, /* 1C /0 */ { BxPrefixSSE66, BX_IA_V128_VPABSB_VdqWdq }, /* 1D /0 */ { BxPrefixSSE66, BX_IA_V128_VPABSW_VdqWdq }, /* 1E /0 */ { BxPrefixSSE66, BX_IA_V128_VPABSD_VdqWdq }, /* 1F /0 */ { 0, BX_IA_ERROR }, /* 20 /0 */ { BxPrefixSSE66, BX_IA_VPMOVSXBW_VdqWq }, /* 21 /0 */ { BxPrefixSSE66, BX_IA_VPMOVSXBD_VdqWd }, /* 22 /0 */ { BxPrefixSSE66, BX_IA_VPMOVSXBQ_VdqWw }, /* 23 /0 */ { BxPrefixSSE66, BX_IA_VPMOVSXWD_VdqWq }, /* 24 /0 */ { BxPrefixSSE66, BX_IA_VPMOVSXWQ_VdqWd }, /* 25 /0 */ { BxPrefixSSE66, BX_IA_VPMOVSXDQ_VdqWq }, /* 26 /0 */ { 0, BX_IA_ERROR }, /* 27 /0 */ { 0, BX_IA_ERROR }, /* 28 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMULDQ_VdqHdqWdq }, /* 29 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPEQQ_VdqHdqWdq }, /* 2A /0 */ { BxPrefixSSE66, BX_IA_V128_VMOVNTDQA_VdqMdq }, /* 2B /0 */ { BxPrefixSSE66, BX_IA_V128_VPACKUSDW_VdqHdqWdq }, /* 2C /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPS_VpsHpsMps }, /* 2D /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPD_VpdHpdMpd }, /* 2E /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPS_MpsHpsVps }, /* 2F /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPD_MpdHpdVpd }, /* 30 /0 */ { BxPrefixSSE66, BX_IA_VPMOVZXBW_VdqWq }, /* 31 /0 */ { BxPrefixSSE66, BX_IA_VPMOVZXBD_VdqWd }, /* 32 /0 */ { BxPrefixSSE66, BX_IA_VPMOVZXBQ_VdqWw }, /* 33 /0 */ { BxPrefixSSE66, BX_IA_VPMOVZXWD_VdqWq }, /* 34 /0 */ { BxPrefixSSE66, BX_IA_VPMOVZXWQ_VdqWd }, /* 35 /0 */ { BxPrefixSSE66, BX_IA_VPMOVZXDQ_VdqWq }, /* 36 /0 */ { 0, BX_IA_ERROR }, /* 37 /0 */ { BxPrefixSSE66, BX_IA_V128_VPCMPGTQ_VdqHdqWdq }, /* 38 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMINSB_VdqHdqWdq }, /* 39 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMINSD_VdqHdqWdq }, /* 3A /0 */ { BxPrefixSSE66, BX_IA_V128_VPMINUW_VdqHdqWdq }, /* 3B /0 */ { BxPrefixSSE66, BX_IA_V128_VPMINUD_VdqHdqWdq }, /* 3C /0 */ { BxPrefixSSE66, BX_IA_V128_VPMAXSB_VdqHdqWdq }, /* 3D /0 */ { BxPrefixSSE66, BX_IA_V128_VPMAXSD_VdqHdqWdq }, /* 3E /0 */ { BxPrefixSSE66, BX_IA_V128_VPMAXUW_VdqHdqWdq }, /* 3F /0 */ { BxPrefixSSE66, BX_IA_V128_VPMAXUD_VdqHdqWdq }, /* 40 /0 */ { BxPrefixSSE66, BX_IA_V128_VPMULLD_VdqHdqWdq }, /* 41 /0 */ { BxPrefixSSE66, BX_IA_V128_VPHMINPOSUW_VdqWdq }, /* 42 /0 */ { 0, BX_IA_ERROR }, /* 43 /0 */ { 0, BX_IA_ERROR }, /* 44 /0 */ { 0, BX_IA_ERROR }, /* 45 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3845 }, /* 46 /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPSRAVD_VdqHdqWdq }, /* 47 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3847 }, /* 48 /0 */ { 0, BX_IA_ERROR }, /* 49 /0 */ { 0, BX_IA_ERROR }, /* 4A /0 */ { 0, BX_IA_ERROR }, /* 4B /0 */ { 0, BX_IA_ERROR }, /* 4C /0 */ { 0, BX_IA_ERROR }, /* 4D /0 */ { 0, BX_IA_ERROR }, /* 4E /0 */ { 0, BX_IA_ERROR }, /* 4F /0 */ { 0, BX_IA_ERROR }, /* 50 /0 */ { 0, BX_IA_ERROR }, /* 51 /0 */ { 0, BX_IA_ERROR }, /* 52 /0 */ { 0, BX_IA_ERROR }, /* 53 /0 */ { 0, BX_IA_ERROR }, /* 54 /0 */ { 0, BX_IA_ERROR }, /* 55 /0 */ { 0, BX_IA_ERROR }, /* 56 /0 */ { 0, BX_IA_ERROR }, /* 57 /0 */ { 0, BX_IA_ERROR }, /* 58 /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTD_VdqWd }, /* 59 /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTQ_VdqWq }, /* 5A /0 */ { 0, BX_IA_ERROR }, /* 5B /0 */ { 0, BX_IA_ERROR }, /* 5C /0 */ { 0, BX_IA_ERROR }, /* 5D /0 */ { 0, BX_IA_ERROR }, /* 5E /0 */ { 0, BX_IA_ERROR }, /* 5F /0 */ { 0, BX_IA_ERROR }, /* 60 /0 */ { 0, BX_IA_ERROR }, /* 61 /0 */ { 0, BX_IA_ERROR }, /* 62 /0 */ { 0, BX_IA_ERROR }, /* 63 /0 */ { 0, BX_IA_ERROR }, /* 64 /0 */ { 0, BX_IA_ERROR }, /* 65 /0 */ { 0, BX_IA_ERROR }, /* 66 /0 */ { 0, BX_IA_ERROR }, /* 67 /0 */ { 0, BX_IA_ERROR }, /* 68 /0 */ { 0, BX_IA_ERROR }, /* 69 /0 */ { 0, BX_IA_ERROR }, /* 6A /0 */ { 0, BX_IA_ERROR }, /* 6B /0 */ { 0, BX_IA_ERROR }, /* 6C /0 */ { 0, BX_IA_ERROR }, /* 6D /0 */ { 0, BX_IA_ERROR }, /* 6E /0 */ { 0, BX_IA_ERROR }, /* 6F /0 */ { 0, BX_IA_ERROR }, /* 70 /0 */ { 0, BX_IA_ERROR }, /* 71 /0 */ { 0, BX_IA_ERROR }, /* 72 /0 */ { 0, BX_IA_ERROR }, /* 73 /0 */ { 0, BX_IA_ERROR }, /* 74 /0 */ { 0, BX_IA_ERROR }, /* 75 /0 */ { 0, BX_IA_ERROR }, /* 76 /0 */ { 0, BX_IA_ERROR }, /* 77 /0 */ { 0, BX_IA_ERROR }, /* 78 /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTB_VdqWb }, /* 79 /0 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTW_VdqWw }, /* 7A /0 */ { 0, BX_IA_ERROR }, /* 7B /0 */ { 0, BX_IA_ERROR }, /* 7C /0 */ { 0, BX_IA_ERROR }, /* 7D /0 */ { 0, BX_IA_ERROR }, /* 7E /0 */ { 0, BX_IA_ERROR }, /* 7F /0 */ { 0, BX_IA_ERROR }, /* 80 /0 */ { 0, BX_IA_ERROR }, /* 81 /0 */ { 0, BX_IA_ERROR }, /* 82 /0 */ { 0, BX_IA_ERROR }, /* 83 /0 */ { 0, BX_IA_ERROR }, /* 84 /0 */ { 0, BX_IA_ERROR }, /* 85 /0 */ { 0, BX_IA_ERROR }, /* 86 /0 */ { 0, BX_IA_ERROR }, /* 87 /0 */ { 0, BX_IA_ERROR }, /* 88 /0 */ { 0, BX_IA_ERROR }, /* 89 /0 */ { 0, BX_IA_ERROR }, /* 8A /0 */ { 0, BX_IA_ERROR }, /* 8B /0 */ { 0, BX_IA_ERROR }, /* 8C /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f388c }, /* 8D /0 */ { 0, BX_IA_ERROR }, /* 8E /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f388e }, /* 8F /0 */ { 0, BX_IA_ERROR }, /* 90 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3890 }, /* 91 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3891 }, /* 92 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3892 }, /* 93 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3893 }, /* 94 /0 */ { 0, BX_IA_ERROR }, /* 95 /0 */ { 0, BX_IA_ERROR }, /* 96 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3896 }, /* 97 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3897 }, /* 98 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3898 }, /* 99 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3899 }, /* 9A /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389a }, /* 9B /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389b }, /* 9C /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389c }, /* 9D /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389d }, /* 9E /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389e }, /* 9F /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389f }, /* A0 /0 */ { 0, BX_IA_ERROR }, /* A1 /0 */ { 0, BX_IA_ERROR }, /* A2 /0 */ { 0, BX_IA_ERROR }, /* A3 /0 */ { 0, BX_IA_ERROR }, /* A4 /0 */ { 0, BX_IA_ERROR }, /* A5 /0 */ { 0, BX_IA_ERROR }, /* A6 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a6 }, /* A7 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a7 }, /* A8 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a8 }, /* A9 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a9 }, /* AA /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38aa }, /* AB /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ab }, /* AC /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ac }, /* AD /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ad }, /* AE /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ae }, /* AF /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38af }, /* B0 /0 */ { 0, BX_IA_ERROR }, /* B1 /0 */ { 0, BX_IA_ERROR }, /* B2 /0 */ { 0, BX_IA_ERROR }, /* B3 /0 */ { 0, BX_IA_ERROR }, /* B4 /0 */ { 0, BX_IA_ERROR }, /* B5 /0 */ { 0, BX_IA_ERROR }, /* B6 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b6 }, /* B7 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b7 }, /* B8 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b8 }, /* B9 /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b9 }, /* BA /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ba }, /* BB /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bb }, /* BC /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bc }, /* BD /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bd }, /* BE /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38be }, /* BF /0 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bf }, /* C0 /0 */ { 0, BX_IA_ERROR }, /* C1 /0 */ { 0, BX_IA_ERROR }, /* C2 /0 */ { 0, BX_IA_ERROR }, /* C3 /0 */ { 0, BX_IA_ERROR }, /* C4 /0 */ { 0, BX_IA_ERROR }, /* C5 /0 */ { 0, BX_IA_ERROR }, /* C6 /0 */ { 0, BX_IA_ERROR }, /* C7 /0 */ { 0, BX_IA_ERROR }, /* C8 /0 */ { 0, BX_IA_ERROR }, /* C9 /0 */ { 0, BX_IA_ERROR }, /* CA /0 */ { 0, BX_IA_ERROR }, /* CB /0 */ { 0, BX_IA_ERROR }, /* CC /0 */ { 0, BX_IA_ERROR }, /* CD /0 */ { 0, BX_IA_ERROR }, /* CE /0 */ { 0, BX_IA_ERROR }, /* CF /0 */ { 0, BX_IA_ERROR }, /* D0 /0 */ { 0, BX_IA_ERROR }, /* D1 /0 */ { 0, BX_IA_ERROR }, /* D2 /0 */ { 0, BX_IA_ERROR }, /* D3 /0 */ { 0, BX_IA_ERROR }, /* D4 /0 */ { 0, BX_IA_ERROR }, /* D5 /0 */ { 0, BX_IA_ERROR }, /* D6 /0 */ { 0, BX_IA_ERROR }, /* D7 /0 */ { 0, BX_IA_ERROR }, /* D8 /0 */ { 0, BX_IA_ERROR }, /* D9 /0 */ { 0, BX_IA_ERROR }, /* DA /0 */ { 0, BX_IA_ERROR }, /* DB /0 */ { BxPrefixSSE66, BX_IA_V128_VAESIMC_VdqWdq }, /* DC /0 */ { BxPrefixSSE66, BX_IA_V128_VAESENC_VdqHdqWdq }, /* DD /0 */ { BxPrefixSSE66, BX_IA_V128_VAESENCLAST_VdqHdqWdq }, /* DE /0 */ { BxPrefixSSE66, BX_IA_V128_VAESDEC_VdqHdqWdq }, /* DF /0 */ { BxPrefixSSE66, BX_IA_V128_VAESDECLAST_VdqHdqWdq }, /* E0 /0 */ { 0, BX_IA_ERROR }, /* E1 /0 */ { 0, BX_IA_ERROR }, /* E2 /0 */ { 0, BX_IA_ERROR }, /* E3 /0 */ { 0, BX_IA_ERROR }, /* E4 /0 */ { 0, BX_IA_ERROR }, /* E5 /0 */ { 0, BX_IA_ERROR }, /* E6 /0 */ { 0, BX_IA_ERROR }, /* E7 /0 */ { 0, BX_IA_ERROR }, /* E8 /0 */ { 0, BX_IA_ERROR }, /* E9 /0 */ { 0, BX_IA_ERROR }, /* EA /0 */ { 0, BX_IA_ERROR }, /* EB /0 */ { 0, BX_IA_ERROR }, /* EC /0 */ { 0, BX_IA_ERROR }, /* ED /0 */ { 0, BX_IA_ERROR }, /* EE /0 */ { 0, BX_IA_ERROR }, /* EF /0 */ { 0, BX_IA_ERROR }, /* F0 /0 */ { 0, BX_IA_ERROR }, /* F1 /0 */ { 0, BX_IA_ERROR }, /* F2 /0 */ { BxSplitVexW64, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38f2 }, /* F3 /0 */ { BxSplitVexW64, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38f3 }, /* F4 /0 */ { 0, BX_IA_ERROR }, /* F5 /0 */ { BxSplitVexW64, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38f5 }, /* F6 /0 */ { BxSplitVexW64, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38f6 }, /* F7 /0 */ { BxSplitVexW64, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38f7 }, /* F8 /0 */ { 0, BX_IA_ERROR }, /* F9 /0 */ { 0, BX_IA_ERROR }, /* FA /0 */ { 0, BX_IA_ERROR }, /* FB /0 */ { 0, BX_IA_ERROR }, /* FC /0 */ { 0, BX_IA_ERROR }, /* FD /0 */ { 0, BX_IA_ERROR }, /* FE /0 */ { 0, BX_IA_ERROR }, /* FF /0 */ { 0, BX_IA_ERROR }, // 256 entries for VEX-encoded 0x0F 0x3A opcodes (VEX.L=0) /* 00 /0 */ { 0, BX_IA_ERROR }, /* 01 /0 */ { 0, BX_IA_ERROR }, /* 02 /0 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VPBLENDD_VdqHdqWdqIb }, /* 03 /0 */ { 0, BX_IA_ERROR }, /* 04 /0 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VPERMILPS_VpsWpsIb }, /* 05 /0 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VPERMILPD_VpdWpdIb }, /* 06 /0 */ { 0, BX_IA_ERROR }, /* 07 /0 */ { 0, BX_IA_ERROR }, /* 08 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDPS_VpsWpsIb }, /* 09 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDPD_VpdWpdIb }, /* 0A /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDSS_VssHpsWssIb }, /* 0B /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDSD_VsdHpdWsdIb }, /* 0C /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VBLENDPS_VpsHpsWpsIb }, /* 0D /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VBLENDPD_VpdHpdWpdIb }, /* 0E /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPBLENDW_VdqHdqWdqIb }, /* 0F /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPALIGNR_VdqHdqWdqIb }, /* 10 /0 */ { 0, BX_IA_ERROR }, /* 11 /0 */ { 0, BX_IA_ERROR }, /* 12 /0 */ { 0, BX_IA_ERROR }, /* 13 /0 */ { 0, BX_IA_ERROR }, /* 14 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPEXTRB_EbdVdqIb }, /* 15 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPEXTRW_EwdVdqIb }, /* 16 /0 */ { BxSplitVexW | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoAVX128_VexW_0f3a16 }, /* 17 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VEXTRACTPS_EdVpsIb }, /* 18 /0 */ { 0, BX_IA_ERROR }, /* 19 /0 */ { 0, BX_IA_ERROR }, /* 1A /0 */ { 0, BX_IA_ERROR }, /* 1B /0 */ { 0, BX_IA_ERROR }, /* 1C /0 */ { 0, BX_IA_ERROR }, /* 1D /0 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VCVTPS2PH_WpsVpsIb }, /* 1E /0 */ { 0, BX_IA_ERROR }, /* 1F /0 */ { 0, BX_IA_ERROR }, /* 20 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPINSRB_VdqEbIb }, /* 21 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VINSERTPS_VpsWssIb }, /* 22 /0 */ { BxSplitVexW | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoAVX128_VexW_0f3a22 }, /* 23 /0 */ { 0, BX_IA_ERROR }, /* 24 /0 */ { 0, BX_IA_ERROR }, /* 25 /0 */ { 0, BX_IA_ERROR }, /* 26 /0 */ { 0, BX_IA_ERROR }, /* 27 /0 */ { 0, BX_IA_ERROR }, /* 28 /0 */ { 0, BX_IA_ERROR }, /* 29 /0 */ { 0, BX_IA_ERROR }, /* 2A /0 */ { 0, BX_IA_ERROR }, /* 2B /0 */ { 0, BX_IA_ERROR }, /* 2C /0 */ { 0, BX_IA_ERROR }, /* 2D /0 */ { 0, BX_IA_ERROR }, /* 2E /0 */ { 0, BX_IA_ERROR }, /* 2F /0 */ { 0, BX_IA_ERROR }, /* 30 /0 */ { 0, BX_IA_ERROR }, /* 31 /0 */ { 0, BX_IA_ERROR }, /* 32 /0 */ { 0, BX_IA_ERROR }, /* 33 /0 */ { 0, BX_IA_ERROR }, /* 34 /0 */ { 0, BX_IA_ERROR }, /* 35 /0 */ { 0, BX_IA_ERROR }, /* 36 /0 */ { 0, BX_IA_ERROR }, /* 37 /0 */ { 0, BX_IA_ERROR }, /* 38 /0 */ { 0, BX_IA_ERROR }, /* 39 /0 */ { 0, BX_IA_ERROR }, /* 3A /0 */ { 0, BX_IA_ERROR }, /* 3B /0 */ { 0, BX_IA_ERROR }, /* 3C /0 */ { 0, BX_IA_ERROR }, /* 3D /0 */ { 0, BX_IA_ERROR }, /* 3E /0 */ { 0, BX_IA_ERROR }, /* 3F /0 */ { 0, BX_IA_ERROR }, /* 40 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VDPPS_VpsHpsWpsIb }, /* 41 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VDPPD_VpdHpdWpdIb }, /* 42 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VMPSADBW_VdqWdqIb }, /* 43 /0 */ { 0, BX_IA_ERROR }, /* 44 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPCLMULQDQ_VdqHdqWdqIb }, /* 45 /0 */ { 0, BX_IA_ERROR }, /* 46 /0 */ { 0, BX_IA_ERROR }, /* 47 /0 */ { 0, BX_IA_ERROR }, /* 48 /0 */ { BxPrefixSSE66 | BxImmediate_Ib5, BX_IA_VPERMIL2PS_VdqHdqWdqIb }, /* 49 /0 */ { BxPrefixSSE66 | BxImmediate_Ib5, BX_IA_VPERMIL2PD_VdqHdqWdqIb }, /* 4A /0 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib4, BX_IA_VBLENDVPS_VpsHpsWpsIb }, /* 4B /0 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib4, BX_IA_VBLENDVPD_VpdHpdWpdIb }, /* 4C /0 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib4, BX_IA_V128_VPBLENDVB_VdqHdqWdqIb }, /* 4D /0 */ { 0, BX_IA_ERROR }, /* 4E /0 */ { 0, BX_IA_ERROR }, /* 4F /0 */ { 0, BX_IA_ERROR }, /* 50 /0 */ { 0, BX_IA_ERROR }, /* 51 /0 */ { 0, BX_IA_ERROR }, /* 52 /0 */ { 0, BX_IA_ERROR }, /* 53 /0 */ { 0, BX_IA_ERROR }, /* 54 /0 */ { 0, BX_IA_ERROR }, /* 55 /0 */ { 0, BX_IA_ERROR }, /* 56 /0 */ { 0, BX_IA_ERROR }, /* 57 /0 */ { 0, BX_IA_ERROR }, /* 58 /0 */ { 0, BX_IA_ERROR }, /* 59 /0 */ { 0, BX_IA_ERROR }, /* 5A /0 */ { 0, BX_IA_ERROR }, /* 5B /0 */ { 0, BX_IA_ERROR }, /* 5C /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSUBPS_VpsHpsWpsVIb }, /* 5D /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSUBPD_VpdHpdWpdVIb }, /* 5E /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBADDPS_VpsHpsWpsVIb }, /* 5F /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBADDPD_VpdHpdWpdVIb }, /* 60 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPCMPESTRM_VdqWdqIb }, /* 61 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPCMPESTRI_VdqWdqIb }, /* 62 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPCMPISTRM_VdqWdqIb }, /* 63 /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VPCMPISTRI_VdqWdqIb }, /* 64 /0 */ { 0, BX_IA_ERROR }, /* 65 /0 */ { 0, BX_IA_ERROR }, /* 66 /0 */ { 0, BX_IA_ERROR }, /* 67 /0 */ { 0, BX_IA_ERROR }, /* 68 /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDPS_VpsHpsWpsVIb }, /* 69 /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDPD_VpdHpdWpdVIb }, /* 6A /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSS_VssHssWssVIb }, /* 6B /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSD_VsdHsdWsdVIb }, /* 6C /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBPS_VpsHpsWpsVIb }, /* 6D /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBPD_VpdHpdWpdVIb }, /* 6E /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBSS_VssHssWssVIb }, /* 6F /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBSD_VsdHsdWsdVIb }, /* 70 /0 */ { 0, BX_IA_ERROR }, /* 71 /0 */ { 0, BX_IA_ERROR }, /* 72 /0 */ { 0, BX_IA_ERROR }, /* 73 /0 */ { 0, BX_IA_ERROR }, /* 74 /0 */ { 0, BX_IA_ERROR }, /* 75 /0 */ { 0, BX_IA_ERROR }, /* 76 /0 */ { 0, BX_IA_ERROR }, /* 77 /0 */ { 0, BX_IA_ERROR }, /* 78 /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDPS_VpsHpsWpsVIb }, /* 79 /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDPD_VpdHpdWpdVIb }, /* 7A /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDSS_VssHssWssVIb }, /* 7B /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDSD_VsdHsdWsdVIb }, /* 7C /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBPS_VpsHpsWpsVIb }, /* 7D /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBPD_VpdHpdWpdVIb }, /* 7E /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBSS_VssHssWssVIb }, /* 7F /0 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBSD_VsdHsdWsdVIb }, /* 80 /0 */ { 0, BX_IA_ERROR }, /* 81 /0 */ { 0, BX_IA_ERROR }, /* 82 /0 */ { 0, BX_IA_ERROR }, /* 83 /0 */ { 0, BX_IA_ERROR }, /* 84 /0 */ { 0, BX_IA_ERROR }, /* 85 /0 */ { 0, BX_IA_ERROR }, /* 86 /0 */ { 0, BX_IA_ERROR }, /* 87 /0 */ { 0, BX_IA_ERROR }, /* 88 /0 */ { 0, BX_IA_ERROR }, /* 89 /0 */ { 0, BX_IA_ERROR }, /* 8A /0 */ { 0, BX_IA_ERROR }, /* 8B /0 */ { 0, BX_IA_ERROR }, /* 8C /0 */ { 0, BX_IA_ERROR }, /* 8D /0 */ { 0, BX_IA_ERROR }, /* 8E /0 */ { 0, BX_IA_ERROR }, /* 8F /0 */ { 0, BX_IA_ERROR }, /* 90 /0 */ { 0, BX_IA_ERROR }, /* 91 /0 */ { 0, BX_IA_ERROR }, /* 92 /0 */ { 0, BX_IA_ERROR }, /* 93 /0 */ { 0, BX_IA_ERROR }, /* 94 /0 */ { 0, BX_IA_ERROR }, /* 95 /0 */ { 0, BX_IA_ERROR }, /* 96 /0 */ { 0, BX_IA_ERROR }, /* 97 /0 */ { 0, BX_IA_ERROR }, /* 98 /0 */ { 0, BX_IA_ERROR }, /* 99 /0 */ { 0, BX_IA_ERROR }, /* 9A /0 */ { 0, BX_IA_ERROR }, /* 9B /0 */ { 0, BX_IA_ERROR }, /* 9C /0 */ { 0, BX_IA_ERROR }, /* 9D /0 */ { 0, BX_IA_ERROR }, /* 9E /0 */ { 0, BX_IA_ERROR }, /* 9F /0 */ { 0, BX_IA_ERROR }, /* A0 /0 */ { 0, BX_IA_ERROR }, /* A1 /0 */ { 0, BX_IA_ERROR }, /* A2 /0 */ { 0, BX_IA_ERROR }, /* A3 /0 */ { 0, BX_IA_ERROR }, /* A4 /0 */ { 0, BX_IA_ERROR }, /* A5 /0 */ { 0, BX_IA_ERROR }, /* A6 /0 */ { 0, BX_IA_ERROR }, /* A7 /0 */ { 0, BX_IA_ERROR }, /* A8 /0 */ { 0, BX_IA_ERROR }, /* A9 /0 */ { 0, BX_IA_ERROR }, /* AA /0 */ { 0, BX_IA_ERROR }, /* AB /0 */ { 0, BX_IA_ERROR }, /* AC /0 */ { 0, BX_IA_ERROR }, /* AD /0 */ { 0, BX_IA_ERROR }, /* AE /0 */ { 0, BX_IA_ERROR }, /* AF /0 */ { 0, BX_IA_ERROR }, /* B0 /0 */ { 0, BX_IA_ERROR }, /* B1 /0 */ { 0, BX_IA_ERROR }, /* B2 /0 */ { 0, BX_IA_ERROR }, /* B3 /0 */ { 0, BX_IA_ERROR }, /* B4 /0 */ { 0, BX_IA_ERROR }, /* B5 /0 */ { 0, BX_IA_ERROR }, /* B6 /0 */ { 0, BX_IA_ERROR }, /* B7 /0 */ { 0, BX_IA_ERROR }, /* B8 /0 */ { 0, BX_IA_ERROR }, /* B9 /0 */ { 0, BX_IA_ERROR }, /* BA /0 */ { 0, BX_IA_ERROR }, /* BB /0 */ { 0, BX_IA_ERROR }, /* BC /0 */ { 0, BX_IA_ERROR }, /* BD /0 */ { 0, BX_IA_ERROR }, /* BE /0 */ { 0, BX_IA_ERROR }, /* BF /0 */ { 0, BX_IA_ERROR }, /* C0 /0 */ { 0, BX_IA_ERROR }, /* C1 /0 */ { 0, BX_IA_ERROR }, /* C2 /0 */ { 0, BX_IA_ERROR }, /* C3 /0 */ { 0, BX_IA_ERROR }, /* C4 /0 */ { 0, BX_IA_ERROR }, /* C5 /0 */ { 0, BX_IA_ERROR }, /* C6 /0 */ { 0, BX_IA_ERROR }, /* C7 /0 */ { 0, BX_IA_ERROR }, /* C8 /0 */ { 0, BX_IA_ERROR }, /* C9 /0 */ { 0, BX_IA_ERROR }, /* CA /0 */ { 0, BX_IA_ERROR }, /* CB /0 */ { 0, BX_IA_ERROR }, /* CC /0 */ { 0, BX_IA_ERROR }, /* CD /0 */ { 0, BX_IA_ERROR }, /* CE /0 */ { 0, BX_IA_ERROR }, /* CF /0 */ { 0, BX_IA_ERROR }, /* D0 /0 */ { 0, BX_IA_ERROR }, /* D1 /0 */ { 0, BX_IA_ERROR }, /* D2 /0 */ { 0, BX_IA_ERROR }, /* D3 /0 */ { 0, BX_IA_ERROR }, /* D4 /0 */ { 0, BX_IA_ERROR }, /* D5 /0 */ { 0, BX_IA_ERROR }, /* D6 /0 */ { 0, BX_IA_ERROR }, /* D7 /0 */ { 0, BX_IA_ERROR }, /* D8 /0 */ { 0, BX_IA_ERROR }, /* D9 /0 */ { 0, BX_IA_ERROR }, /* DA /0 */ { 0, BX_IA_ERROR }, /* DB /0 */ { 0, BX_IA_ERROR }, /* DC /0 */ { 0, BX_IA_ERROR }, /* DD /0 */ { 0, BX_IA_ERROR }, /* DE /0 */ { 0, BX_IA_ERROR }, /* DF /0 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V128_VAESKEYGENASSIST_VdqWdqIb }, /* E0 /0 */ { 0, BX_IA_ERROR }, /* E1 /0 */ { 0, BX_IA_ERROR }, /* E2 /0 */ { 0, BX_IA_ERROR }, /* E3 /0 */ { 0, BX_IA_ERROR }, /* E4 /0 */ { 0, BX_IA_ERROR }, /* E5 /0 */ { 0, BX_IA_ERROR }, /* E6 /0 */ { 0, BX_IA_ERROR }, /* E7 /0 */ { 0, BX_IA_ERROR }, /* E8 /0 */ { 0, BX_IA_ERROR }, /* E9 /0 */ { 0, BX_IA_ERROR }, /* EA /0 */ { 0, BX_IA_ERROR }, /* EB /0 */ { 0, BX_IA_ERROR }, /* EC /0 */ { 0, BX_IA_ERROR }, /* ED /0 */ { 0, BX_IA_ERROR }, /* EE /0 */ { 0, BX_IA_ERROR }, /* EF /0 */ { 0, BX_IA_ERROR }, /* F0 /0 */ { BxSplitVexW64 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3af0 }, /* F1 /0 */ { 0, BX_IA_ERROR }, /* F2 /0 */ { 0, BX_IA_ERROR }, /* F3 /0 */ { 0, BX_IA_ERROR }, /* F4 /0 */ { 0, BX_IA_ERROR }, /* F5 /0 */ { 0, BX_IA_ERROR }, /* F6 /0 */ { 0, BX_IA_ERROR }, /* F7 /0 */ { 0, BX_IA_ERROR }, /* F8 /0 */ { 0, BX_IA_ERROR }, /* F9 /0 */ { 0, BX_IA_ERROR }, /* FA /0 */ { 0, BX_IA_ERROR }, /* FB /0 */ { 0, BX_IA_ERROR }, /* FC /0 */ { 0, BX_IA_ERROR }, /* FD /0 */ { 0, BX_IA_ERROR }, /* FE /0 */ { 0, BX_IA_ERROR }, /* FF /0 */ { 0, BX_IA_ERROR }, // 256 entries for VEX-encoded 0x0F opcodes (VEX.L=1) /* 00 /1 */ { 0, BX_IA_ERROR }, /* 01 /1 */ { 0, BX_IA_ERROR }, /* 02 /1 */ { 0, BX_IA_ERROR }, /* 03 /1 */ { 0, BX_IA_ERROR }, /* 04 /1 */ { 0, BX_IA_ERROR }, /* 05 /1 */ { 0, BX_IA_ERROR }, /* 06 /1 */ { 0, BX_IA_ERROR }, /* 07 /1 */ { 0, BX_IA_ERROR }, /* 08 /1 */ { 0, BX_IA_ERROR }, /* 09 /1 */ { 0, BX_IA_ERROR }, /* 0A /1 */ { 0, BX_IA_ERROR }, /* 0B /1 */ { 0, BX_IA_ERROR }, /* 0C /1 */ { 0, BX_IA_ERROR }, /* 0D /1 */ { 0, BX_IA_ERROR }, /* 0E /1 */ { 0, BX_IA_ERROR }, /* 0F /1 */ { 0, BX_IA_ERROR }, /* 10 /1 */ { BxPrefixSSE, BX_IA_VMOVUPS_VpsWps, BxOpcodeGroupAVX256_0f10 }, /* 11 /1 */ { BxPrefixSSE, BX_IA_VMOVUPS_WpsVps, BxOpcodeGroupAVX256_0f11 }, /* 12 /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX256_0f12 }, /* 13 /1 */ { 0, BX_IA_ERROR }, /* 14 /1 */ { BxPrefixSSE, BX_IA_VUNPCKLPS_VpsHpsWps, BxOpcodeGroupAVX_0f14 }, /* 15 /1 */ { BxPrefixSSE, BX_IA_VUNPCKHPS_VpsHpsWps, BxOpcodeGroupAVX_0f15 }, /* 16 /1 */ { BxPrefixSSEF3, BX_IA_VMOVSHDUP_VpsWps }, /* 17 /1 */ { 0, BX_IA_ERROR }, /* 18 /1 */ { 0, BX_IA_ERROR }, /* 19 /1 */ { 0, BX_IA_ERROR }, /* 1A /1 */ { 0, BX_IA_ERROR }, /* 1B /1 */ { 0, BX_IA_ERROR }, /* 1C /1 */ { 0, BX_IA_ERROR }, /* 1D /1 */ { 0, BX_IA_ERROR }, /* 1E /1 */ { 0, BX_IA_ERROR }, /* 1F /1 */ { 0, BX_IA_ERROR }, /* 20 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 21 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 22 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 23 /1 */ { 0, BX_IA_ERROR }, // WARNING: ModC0 always '1 /* 24 /1 */ { 0, BX_IA_ERROR }, /* 25 /1 */ { 0, BX_IA_ERROR }, /* 26 /1 */ { 0, BX_IA_ERROR }, /* 27 /1 */ { 0, BX_IA_ERROR }, /* 28 /1 */ { BxPrefixSSE, BX_IA_VMOVAPS_VpsWps, BxOpcodeGroupAVX_0f28 }, /* 29 /1 */ { BxPrefixSSE, BX_IA_VMOVAPS_WpsVps, BxOpcodeGroupAVX_0f29 }, /* 2A /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f2a }, /* 2B /1 */ { BxPrefixSSE, BX_IA_VMOVNTPS_MpsVps, BxOpcodeGroupAVX_0f2bM }, /* 2C /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f2c }, /* 2D /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f2d }, /* 2E /1 */ { BxPrefixSSE, BX_IA_VUCOMISS_VssWss, BxOpcodeGroupAVX_0f2e }, /* 2F /1 */ { BxPrefixSSE, BX_IA_VCOMISS_VpsWps, BxOpcodeGroupAVX_0f2f }, /* 30 /1 */ { 0, BX_IA_ERROR }, /* 31 /1 */ { 0, BX_IA_ERROR }, /* 32 /1 */ { 0, BX_IA_ERROR }, /* 33 /1 */ { 0, BX_IA_ERROR }, /* 34 /1 */ { 0, BX_IA_ERROR }, /* 35 /1 */ { 0, BX_IA_ERROR }, /* 36 /1 */ { 0, BX_IA_ERROR }, /* 37 /1 */ { 0, BX_IA_ERROR }, /* 38 /1 */ { 0, BX_IA_ERROR }, // 3-Byte Escape /* 39 /1 */ { 0, BX_IA_ERROR }, /* 3A /1 */ { 0, BX_IA_ERROR }, // 3-Byte Escape /* 3B /1 */ { 0, BX_IA_ERROR }, /* 3C /1 */ { 0, BX_IA_ERROR }, /* 3D /1 */ { 0, BX_IA_ERROR }, /* 3E /1 */ { 0, BX_IA_ERROR }, /* 3F /1 */ { 0, BX_IA_ERROR }, /* 40 /1 */ { 0, BX_IA_ERROR }, /* 41 /1 */ { 0, BX_IA_ERROR }, /* 42 /1 */ { 0, BX_IA_ERROR }, /* 43 /1 */ { 0, BX_IA_ERROR }, /* 44 /1 */ { 0, BX_IA_ERROR }, /* 45 /1 */ { 0, BX_IA_ERROR }, /* 46 /1 */ { 0, BX_IA_ERROR }, /* 47 /1 */ { 0, BX_IA_ERROR }, /* 48 /1 */ { 0, BX_IA_ERROR }, /* 49 /1 */ { 0, BX_IA_ERROR }, /* 4A /1 */ { 0, BX_IA_ERROR }, /* 4B /1 */ { 0, BX_IA_ERROR }, /* 4C /1 */ { 0, BX_IA_ERROR }, /* 4D /1 */ { 0, BX_IA_ERROR }, /* 4E /1 */ { 0, BX_IA_ERROR }, /* 4F /1 */ { 0, BX_IA_ERROR }, /* 50 /1 */ { BxPrefixSSE, BX_IA_VMOVMSKPS_GdVRps, BxOpcodeGroupAVX_0f50R }, /* 51 /1 */ { BxPrefixSSE, BX_IA_VSQRTPS_VpsWps, BxOpcodeGroupAVX_0f51 }, /* 52 /1 */ { BxPrefixSSE, BX_IA_VRSQRTPS_VpsWps, BxOpcodeGroupAVX_0f52 }, /* 53 /1 */ { BxPrefixSSE, BX_IA_VRCPPS_VpsWps, BxOpcodeGroupAVX_0f53 }, /* 54 /1 */ { BxPrefixSSE, BX_IA_VANDPS_VpsHpsWps, BxOpcodeGroupAVX_0f54 }, /* 55 /1 */ { BxPrefixSSE, BX_IA_VANDNPS_VpsHpsWps, BxOpcodeGroupAVX_0f55 }, /* 56 /1 */ { BxPrefixSSE, BX_IA_VORPS_VpsHpsWps, BxOpcodeGroupAVX_0f56 }, /* 57 /1 */ { BxPrefixSSE, BX_IA_VXORPS_VpsHpsWps, BxOpcodeGroupAVX_0f57 }, /* 58 /1 */ { BxPrefixSSE, BX_IA_VADDPS_VpsHpsWps, BxOpcodeGroupAVX_0f58 }, /* 59 /1 */ { BxPrefixSSE, BX_IA_VMULPS_VpsHpsWps, BxOpcodeGroupAVX_0f59 }, /* 5A /1 */ { BxPrefixSSE, BX_IA_V256_VCVTPS2PD_VpdWps, BxOpcodeGroupAVX_0f5a }, /* 5B /1 */ { BxPrefixSSE, BX_IA_VCVTDQ2PS_VpsWdq, BxOpcodeGroupAVX_0f5b }, /* 5C /1 */ { BxPrefixSSE, BX_IA_VSUBPS_VpsHpsWps, BxOpcodeGroupAVX_0f5c }, /* 5D /1 */ { BxPrefixSSE, BX_IA_VMINPS_VpsHpsWps, BxOpcodeGroupAVX_0f5d }, /* 5E /1 */ { BxPrefixSSE, BX_IA_VDIVPS_VpsHpsWps, BxOpcodeGroupAVX_0f5e }, /* 5F /1 */ { BxPrefixSSE, BX_IA_VMAXPS_VpsHpsWps, BxOpcodeGroupAVX_0f5f }, /* 60 /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKLBW_VdqHdqWdq }, /* 61 /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKLWD_VdqHdqWdq }, /* 62 /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKLDQ_VdqHdqWdq }, /* 63 /1 */ { BxPrefixSSE66, BX_IA_V256_VPACKSSWB_VdqHdqWdq }, /* 64 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPGTB_VdqHdqWdq }, /* 65 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPGTW_VdqHdqWdq }, /* 66 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPGTD_VdqHdqWdq }, /* 67 /1 */ { BxPrefixSSE66, BX_IA_V256_VPACKUSWB_VdqHdqWdq }, /* 68 /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKHBW_VdqHdqWdq }, /* 69 /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKHWD_VdqHdqWdq }, /* 6A /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKHDQ_VdqHdqWdq }, /* 6B /1 */ { BxPrefixSSE66, BX_IA_V256_VPACKSSDW_VdqHdqWdq }, /* 6C /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKLQDQ_VdqHdqWdq }, /* 6D /1 */ { BxPrefixSSE66, BX_IA_V256_VPUNPCKHQDQ_VdqHdqWdq }, /* 6E /1 */ { 0, BX_IA_ERROR }, /* 6F /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f6f }, /* 70 /1 */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeGroupAVX256_0f70 }, /* 71 /1 */ { BxGroup12, BX_IA_ERROR, BxOpcodeInfoAVX256G12R }, /* 72 /1 */ { BxGroup13, BX_IA_ERROR, BxOpcodeInfoAVX256G13R }, /* 73 /1 */ { BxGroup14, BX_IA_ERROR, BxOpcodeInfoAVX256G14R }, /* 74 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPEQB_VdqHdqWdq }, /* 75 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPEQW_VdqHdqWdq }, /* 76 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPEQD_VdqHdqWdq }, /* 77 /1 */ { BxPrefixSSE, BX_IA_VZEROALL, BxOpcodeGroupSSE_ERR }, /* 78 /1 */ { 0, BX_IA_ERROR }, /* 79 /1 */ { 0, BX_IA_ERROR }, /* 7A /1 */ { 0, BX_IA_ERROR }, /* 7B /1 */ { 0, BX_IA_ERROR }, /* 7C /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f7c }, /* 7D /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f7d }, /* 7E /1 */ { 0, BX_IA_ERROR }, /* 7F /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0f7f }, /* 80 /1 */ { 0, BX_IA_ERROR }, /* 81 /1 */ { 0, BX_IA_ERROR }, /* 82 /1 */ { 0, BX_IA_ERROR }, /* 83 /1 */ { 0, BX_IA_ERROR }, /* 84 /1 */ { 0, BX_IA_ERROR }, /* 85 /1 */ { 0, BX_IA_ERROR }, /* 86 /1 */ { 0, BX_IA_ERROR }, /* 87 /1 */ { 0, BX_IA_ERROR }, /* 88 /1 */ { 0, BX_IA_ERROR }, /* 89 /1 */ { 0, BX_IA_ERROR }, /* 8A /1 */ { 0, BX_IA_ERROR }, /* 8B /1 */ { 0, BX_IA_ERROR }, /* 8C /1 */ { 0, BX_IA_ERROR }, /* 8D /1 */ { 0, BX_IA_ERROR }, /* 8E /1 */ { 0, BX_IA_ERROR }, /* 8F /1 */ { 0, BX_IA_ERROR }, /* 90 /1 */ { 0, BX_IA_ERROR }, /* 91 /1 */ { 0, BX_IA_ERROR }, /* 92 /1 */ { 0, BX_IA_ERROR }, /* 93 /1 */ { 0, BX_IA_ERROR }, /* 94 /1 */ { 0, BX_IA_ERROR }, /* 95 /1 */ { 0, BX_IA_ERROR }, /* 96 /1 */ { 0, BX_IA_ERROR }, /* 97 /1 */ { 0, BX_IA_ERROR }, /* 98 /1 */ { 0, BX_IA_ERROR }, /* 99 /1 */ { 0, BX_IA_ERROR }, /* 9A /1 */ { 0, BX_IA_ERROR }, /* 9B /1 */ { 0, BX_IA_ERROR }, /* 9C /1 */ { 0, BX_IA_ERROR }, /* 9D /1 */ { 0, BX_IA_ERROR }, /* 9E /1 */ { 0, BX_IA_ERROR }, /* 9F /1 */ { 0, BX_IA_ERROR }, /* A0 /1 */ { 0, BX_IA_ERROR }, /* A1 /1 */ { 0, BX_IA_ERROR }, /* A2 /1 */ { 0, BX_IA_ERROR }, /* A3 /1 */ { 0, BX_IA_ERROR }, /* A4 /1 */ { 0, BX_IA_ERROR }, /* A5 /1 */ { 0, BX_IA_ERROR }, /* A6 /1 */ { 0, BX_IA_ERROR }, /* A7 /1 */ { 0, BX_IA_ERROR }, /* A8 /1 */ { 0, BX_IA_ERROR }, /* A9 /1 */ { 0, BX_IA_ERROR }, /* AA /1 */ { 0, BX_IA_ERROR }, /* AB /1 */ { 0, BX_IA_ERROR }, /* AC /1 */ { 0, BX_IA_ERROR }, /* AD /1 */ { 0, BX_IA_ERROR }, /* AE /1 */ { 0, BX_IA_ERROR }, /* AF /1 */ { 0, BX_IA_ERROR }, /* B0 /1 */ { 0, BX_IA_ERROR }, /* B1 /1 */ { 0, BX_IA_ERROR }, /* B2 /1 */ { 0, BX_IA_ERROR }, /* B3 /1 */ { 0, BX_IA_ERROR }, /* B4 /1 */ { 0, BX_IA_ERROR }, /* B5 /1 */ { 0, BX_IA_ERROR }, /* B6 /1 */ { 0, BX_IA_ERROR }, /* B7 /1 */ { 0, BX_IA_ERROR }, /* B8 /1 */ { 0, BX_IA_ERROR }, /* B9 /1 */ { 0, BX_IA_ERROR }, /* BA /1 */ { 0, BX_IA_ERROR }, /* BB /1 */ { 0, BX_IA_ERROR }, /* BC /1 */ { 0, BX_IA_ERROR }, /* BD /1 */ { 0, BX_IA_ERROR }, /* BE /1 */ { 0, BX_IA_ERROR }, /* BF /1 */ { 0, BX_IA_ERROR }, /* C0 /1 */ { 0, BX_IA_ERROR }, /* C1 /1 */ { 0, BX_IA_ERROR }, /* C2 /1 */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_VCMPPS_VpsHpsWpsIb, BxOpcodeGroupAVX_0fc2 }, /* C3 /1 */ { 0, BX_IA_ERROR }, /* C4 /1 */ { 0, BX_IA_ERROR }, /* C5 /1 */ { 0, BX_IA_ERROR }, /* C6 /1 */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_VSHUFPS_VpsHpsWpsIb, BxOpcodeGroupAVX_0fc6 }, /* C7 /1 */ { 0, BX_IA_ERROR }, /* C8 /1 */ { 0, BX_IA_ERROR }, /* C9 /1 */ { 0, BX_IA_ERROR }, /* CA /1 */ { 0, BX_IA_ERROR }, /* CB /1 */ { 0, BX_IA_ERROR }, /* CC /1 */ { 0, BX_IA_ERROR }, /* CD /1 */ { 0, BX_IA_ERROR }, /* CE /1 */ { 0, BX_IA_ERROR }, /* CF /1 */ { 0, BX_IA_ERROR }, /* D0 /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX_0fd0 }, /* D1 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSRLW_VdqHdqWdq }, /* D2 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSRLD_VdqHdqWdq }, /* D3 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSRLQ_VdqHdqWdq }, /* D4 /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDQ_VdqHdqWdq }, /* D5 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMULLW_VdqHdqWdq }, /* D6 /1 */ { 0, BX_IA_ERROR }, /* D7 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMOVMSKB_GdUdq }, /* D8 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBUSB_VdqHdqWdq }, /* D9 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBUSW_VdqHdqWdq }, /* DA /1 */ { BxPrefixSSE66, BX_IA_V256_VPMINUB_VdqHdqWdq }, /* DB /1 */ { BxPrefixSSE66, BX_IA_V256_VPAND_VdqHdqWdq }, /* DC /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDUSB_VdqHdqWdq }, /* DD /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDUSW_VdqHdqWdq }, /* DE /1 */ { BxPrefixSSE66, BX_IA_V256_VPMAXUB_VdqHdqWdq }, /* DF /1 */ { BxPrefixSSE66, BX_IA_V256_VPANDN_VdqHdqWdq }, /* E0 /1 */ { BxPrefixSSE66, BX_IA_V256_VPAVGB_VdqWdq }, /* E1 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSRAW_VdqHdqWdq }, /* E2 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSRAD_VdqHdqWdq }, /* E3 /1 */ { BxPrefixSSE66, BX_IA_V256_VPAVGW_VdqWdq }, /* E4 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMULHUW_VdqHdqWdq }, /* E5 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMULHW_VdqHdqWdq }, /* E6 /1 */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupAVX256_0fe6 }, /* E7 /1 */ { BxPrefixSSE66, BX_IA_VMOVNTDQ_MdqVdq }, /* E8 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBSB_VdqHdqWdq }, /* E9 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBSW_VdqHdqWdq }, /* EA /1 */ { BxPrefixSSE66, BX_IA_V256_VPMINSW_VdqHdqWdq }, /* EB /1 */ { BxPrefixSSE66, BX_IA_V256_VPOR_VdqHdqWdq }, /* EC /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDSB_VdqHdqWdq }, /* ED /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDSW_VdqHdqWdq }, /* EE /1 */ { BxPrefixSSE66, BX_IA_V256_VPMAXSW_VdqHdqWdq }, /* EF /1 */ { BxPrefixSSE66, BX_IA_V256_VPXOR_VdqHdqWdq }, /* F0 /1 */ { BxPrefixSSEF2, BX_IA_VLDDQU_VdqMdq }, /* F1 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSLLW_VdqHdqWdq }, /* F2 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSLLD_VdqHdqWdq }, /* F3 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSLLQ_VdqHdqWdq }, /* F4 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMULUDQ_VdqHdqWdq }, /* F5 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMADDWD_VdqHdqWdq }, /* F6 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSADBW_VdqHdqWdq }, /* F7 /1 */ { 0, BX_IA_ERROR }, /* F8 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBB_VdqHdqWdq }, /* F9 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBW_VdqHdqWdq }, /* FA /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBD_VdqHdqWdq }, /* FB /1 */ { BxPrefixSSE66, BX_IA_V256_VPSUBQ_VdqHdqWdq }, /* FC /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDB_VdqHdqWdq }, /* FD /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDW_VdqHdqWdq }, /* FE /1 */ { BxPrefixSSE66, BX_IA_V256_VPADDD_VdqHdqWdq }, /* FF /1 */ { 0, BX_IA_ERROR }, // 256 entries for VEX-encoded 0x0F 0x38 opcodes (VEX.L=1) /* 00 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSHUFB_VdqHdqWdq }, /* 01 /1 */ { BxPrefixSSE66, BX_IA_V256_VPHADDW_VdqHdqWdq }, /* 02 /1 */ { BxPrefixSSE66, BX_IA_V256_VPHADDD_VdqHdqWdq }, /* 03 /1 */ { BxPrefixSSE66, BX_IA_V256_VPHADDSW_VdqHdqWdq }, /* 04 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMADDUBSW_VdqHdqWdq }, /* 05 /1 */ { BxPrefixSSE66, BX_IA_V256_VPHSUBW_VdqHdqWdq }, /* 06 /1 */ { BxPrefixSSE66, BX_IA_V256_VPHSUBD_VdqHdqWdq }, /* 07 /1 */ { BxPrefixSSE66, BX_IA_V256_VPHSUBSW_VdqHdqWdq }, /* 08 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSIGNB_VdqHdqWdq }, /* 09 /1 */ { BxPrefixSSE66, BX_IA_V256_VPSIGNW_VdqHdqWdq }, /* 0A /1 */ { BxPrefixSSE66, BX_IA_V256_VPSIGND_VdqHdqWdq }, /* 0B /1 */ { BxPrefixSSE66, BX_IA_V256_VPMULHRSW_VdqHdqWdq }, /* 0C /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPERMILPS_VpsHpsWps }, /* 0D /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPERMILPD_VpdHpdWpd }, /* 0E /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VTESTPS_VpsWps }, /* 0F /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VTESTPD_VpdWpd }, /* 10 /1 */ { 0, BX_IA_ERROR }, /* 11 /1 */ { 0, BX_IA_ERROR }, /* 12 /1 */ { 0, BX_IA_ERROR }, /* 13 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VCVTPH2PS_VpsWps }, /* 14 /1 */ { 0, BX_IA_ERROR }, /* 15 /1 */ { 0, BX_IA_ERROR }, /* 16 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_V256_VPERMPS_VpsHpsWps }, /* 17 /1 */ { BxPrefixSSE66, BX_IA_VPTEST_VdqWdq }, /* 18 /1 */ { BxSplitMod11B, BX_IA_ERROR, BxOpcodeGroupAVX_0f3818 }, /* 19 /1 */ { BxSplitMod11B, BX_IA_ERROR, BxOpcodeGroupAVX_0f3819 }, /* 1A /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_V256_VBROADCASTF128_VdqMdq }, /* 1B /1 */ { 0, BX_IA_ERROR }, /* 1C /1 */ { BxPrefixSSE66, BX_IA_V256_VPABSB_VdqWdq }, /* 1D /1 */ { BxPrefixSSE66, BX_IA_V256_VPABSW_VdqWdq }, /* 1E /1 */ { BxPrefixSSE66, BX_IA_V256_VPABSD_VdqWdq }, /* 1F /1 */ { 0, BX_IA_ERROR }, /* 20 /1 */ { BxPrefixSSE66, BX_IA_VPMOVSXBW256_VdqWdq }, /* 21 /1 */ { BxPrefixSSE66, BX_IA_VPMOVSXBD256_VdqWq }, /* 22 /1 */ { BxPrefixSSE66, BX_IA_VPMOVSXBQ256_VdqWd }, /* 23 /1 */ { BxPrefixSSE66, BX_IA_VPMOVSXWD256_VdqWdq }, /* 24 /1 */ { BxPrefixSSE66, BX_IA_VPMOVSXWQ256_VdqWq }, /* 25 /1 */ { BxPrefixSSE66, BX_IA_VPMOVSXDQ256_VdqWdq }, /* 26 /1 */ { 0, BX_IA_ERROR }, /* 27 /1 */ { 0, BX_IA_ERROR }, /* 28 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMULDQ_VdqHdqWdq }, /* 29 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPEQQ_VdqHdqWdq }, /* 2A /1 */ { BxPrefixSSE66, BX_IA_V256_VMOVNTDQA_VdqMdq }, /* 2B /1 */ { BxPrefixSSE66, BX_IA_V256_VPACKUSDW_VdqHdqWdq }, /* 2C /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPS_VpsHpsMps }, /* 2D /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPD_VpdHpdMpd }, /* 2E /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPS_MpsHpsVps }, /* 2F /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VMASKMOVPD_MpdHpdVpd }, /* 30 /1 */ { BxPrefixSSE66, BX_IA_VPMOVZXBW256_VdqWdq }, /* 31 /1 */ { BxPrefixSSE66, BX_IA_VPMOVZXBD256_VdqWq }, /* 32 /1 */ { BxPrefixSSE66, BX_IA_VPMOVZXBQ256_VdqWd }, /* 33 /1 */ { BxPrefixSSE66, BX_IA_VPMOVZXWD256_VdqWdq }, /* 34 /1 */ { BxPrefixSSE66, BX_IA_VPMOVZXWQ256_VdqWq }, /* 35 /1 */ { BxPrefixSSE66, BX_IA_VPMOVZXDQ256_VdqWdq }, /* 36 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_V256_VPERMD_VdqHdqWdq }, /* 37 /1 */ { BxPrefixSSE66, BX_IA_V256_VPCMPGTQ_VdqHdqWdq }, /* 38 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMINSB_VdqHdqWdq }, /* 39 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMINSD_VdqHdqWdq }, /* 3A /1 */ { BxPrefixSSE66, BX_IA_V256_VPMINUW_VdqHdqWdq }, /* 3B /1 */ { BxPrefixSSE66, BX_IA_V256_VPMINUD_VdqHdqWdq }, /* 3C /1 */ { BxPrefixSSE66, BX_IA_V256_VPMAXSB_VdqHdqWdq }, /* 3D /1 */ { BxPrefixSSE66, BX_IA_V256_VPMAXSD_VdqHdqWdq }, /* 3E /1 */ { BxPrefixSSE66, BX_IA_V256_VPMAXUW_VdqHdqWdq }, /* 3F /1 */ { BxPrefixSSE66, BX_IA_V256_VPMAXUD_VdqHdqWdq }, /* 40 /1 */ { BxPrefixSSE66, BX_IA_V256_VPMULLD_VdqHdqWdq }, /* 41 /1 */ { 0, BX_IA_ERROR }, /* 42 /1 */ { 0, BX_IA_ERROR }, /* 43 /1 */ { 0, BX_IA_ERROR }, /* 44 /1 */ { 0, BX_IA_ERROR }, /* 45 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3845 }, /* 46 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPSRAVD_VdqHdqWdq }, /* 47 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3847 }, /* 48 /1 */ { 0, BX_IA_ERROR }, /* 49 /1 */ { 0, BX_IA_ERROR }, /* 4A /1 */ { 0, BX_IA_ERROR }, /* 4B /1 */ { 0, BX_IA_ERROR }, /* 4C /1 */ { 0, BX_IA_ERROR }, /* 4D /1 */ { 0, BX_IA_ERROR }, /* 4E /1 */ { 0, BX_IA_ERROR }, /* 4F /1 */ { 0, BX_IA_ERROR }, /* 50 /1 */ { 0, BX_IA_ERROR }, /* 51 /1 */ { 0, BX_IA_ERROR }, /* 52 /1 */ { 0, BX_IA_ERROR }, /* 53 /1 */ { 0, BX_IA_ERROR }, /* 54 /1 */ { 0, BX_IA_ERROR }, /* 55 /1 */ { 0, BX_IA_ERROR }, /* 56 /1 */ { 0, BX_IA_ERROR }, /* 57 /1 */ { 0, BX_IA_ERROR }, /* 58 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTD_VdqWd }, /* 59 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTQ_VdqWq }, /* 5A /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_V256_VBROADCASTI128_VdqMdq }, /* 5B /1 */ { 0, BX_IA_ERROR }, /* 5C /1 */ { 0, BX_IA_ERROR }, /* 5D /1 */ { 0, BX_IA_ERROR }, /* 5E /1 */ { 0, BX_IA_ERROR }, /* 5F /1 */ { 0, BX_IA_ERROR }, /* 60 /1 */ { 0, BX_IA_ERROR }, /* 61 /1 */ { 0, BX_IA_ERROR }, /* 62 /1 */ { 0, BX_IA_ERROR }, /* 63 /1 */ { 0, BX_IA_ERROR }, /* 64 /1 */ { 0, BX_IA_ERROR }, /* 65 /1 */ { 0, BX_IA_ERROR }, /* 66 /1 */ { 0, BX_IA_ERROR }, /* 67 /1 */ { 0, BX_IA_ERROR }, /* 68 /1 */ { 0, BX_IA_ERROR }, /* 69 /1 */ { 0, BX_IA_ERROR }, /* 6A /1 */ { 0, BX_IA_ERROR }, /* 6B /1 */ { 0, BX_IA_ERROR }, /* 6C /1 */ { 0, BX_IA_ERROR }, /* 6D /1 */ { 0, BX_IA_ERROR }, /* 6E /1 */ { 0, BX_IA_ERROR }, /* 6F /1 */ { 0, BX_IA_ERROR }, /* 70 /1 */ { 0, BX_IA_ERROR }, /* 71 /1 */ { 0, BX_IA_ERROR }, /* 72 /1 */ { 0, BX_IA_ERROR }, /* 73 /1 */ { 0, BX_IA_ERROR }, /* 74 /1 */ { 0, BX_IA_ERROR }, /* 75 /1 */ { 0, BX_IA_ERROR }, /* 76 /1 */ { 0, BX_IA_ERROR }, /* 77 /1 */ { 0, BX_IA_ERROR }, /* 78 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTB_VdqWb }, /* 79 /1 */ { BxPrefixSSE66 | BxVexW0, BX_IA_VPBROADCASTW_VdqWw }, /* 7A /1 */ { 0, BX_IA_ERROR }, /* 7B /1 */ { 0, BX_IA_ERROR }, /* 7C /1 */ { 0, BX_IA_ERROR }, /* 7D /1 */ { 0, BX_IA_ERROR }, /* 7E /1 */ { 0, BX_IA_ERROR }, /* 7F /1 */ { 0, BX_IA_ERROR }, /* 80 /1 */ { 0, BX_IA_ERROR }, /* 81 /1 */ { 0, BX_IA_ERROR }, /* 82 /1 */ { 0, BX_IA_ERROR }, /* 83 /1 */ { 0, BX_IA_ERROR }, /* 84 /1 */ { 0, BX_IA_ERROR }, /* 85 /1 */ { 0, BX_IA_ERROR }, /* 86 /1 */ { 0, BX_IA_ERROR }, /* 87 /1 */ { 0, BX_IA_ERROR }, /* 88 /1 */ { 0, BX_IA_ERROR }, /* 89 /1 */ { 0, BX_IA_ERROR }, /* 8A /1 */ { 0, BX_IA_ERROR }, /* 8B /1 */ { 0, BX_IA_ERROR }, /* 8C /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f388c }, /* 8D /1 */ { 0, BX_IA_ERROR }, /* 8E /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f388e }, /* 8F /1 */ { 0, BX_IA_ERROR }, /* 90 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3890 }, /* 91 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3891 }, /* 92 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3892 }, /* 93 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3893 }, /* 94 /1 */ { 0, BX_IA_ERROR }, /* 95 /1 */ { 0, BX_IA_ERROR }, /* 96 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3896 }, /* 97 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3897 }, /* 98 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3898 }, /* 99 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f3899 }, /* 9A /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389a }, /* 9B /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389b }, /* 9C /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389c }, /* 9D /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389d }, /* 9E /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389e }, /* 9F /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f389f }, /* A0 /1 */ { 0, BX_IA_ERROR }, /* A1 /1 */ { 0, BX_IA_ERROR }, /* A2 /1 */ { 0, BX_IA_ERROR }, /* A3 /1 */ { 0, BX_IA_ERROR }, /* A4 /1 */ { 0, BX_IA_ERROR }, /* A5 /1 */ { 0, BX_IA_ERROR }, /* A6 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a6 }, /* A7 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a7 }, /* A8 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a8 }, /* A9 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38a9 }, /* AA /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38aa }, /* AB /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ab }, /* AC /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ac }, /* AD /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ad }, /* AE /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ae }, /* AF /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38af }, /* B0 /1 */ { 0, BX_IA_ERROR }, /* B1 /1 */ { 0, BX_IA_ERROR }, /* B2 /1 */ { 0, BX_IA_ERROR }, /* B3 /1 */ { 0, BX_IA_ERROR }, /* B4 /1 */ { 0, BX_IA_ERROR }, /* B5 /1 */ { 0, BX_IA_ERROR }, /* B6 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b6 }, /* B7 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b7 }, /* B8 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b8 }, /* B9 /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38b9 }, /* BA /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38ba }, /* BB /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bb }, /* BC /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bc }, /* BD /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bd }, /* BE /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38be }, /* BF /1 */ { BxSplitVexW, BX_IA_ERROR, BxOpcodeInfoAVX_VexW_0f38bf }, /* C0 /1 */ { 0, BX_IA_ERROR }, /* C1 /1 */ { 0, BX_IA_ERROR }, /* C2 /1 */ { 0, BX_IA_ERROR }, /* C3 /1 */ { 0, BX_IA_ERROR }, /* C4 /1 */ { 0, BX_IA_ERROR }, /* C5 /1 */ { 0, BX_IA_ERROR }, /* C6 /1 */ { 0, BX_IA_ERROR }, /* C7 /1 */ { 0, BX_IA_ERROR }, /* C8 /1 */ { 0, BX_IA_ERROR }, /* C9 /1 */ { 0, BX_IA_ERROR }, /* CA /1 */ { 0, BX_IA_ERROR }, /* CB /1 */ { 0, BX_IA_ERROR }, /* CC /1 */ { 0, BX_IA_ERROR }, /* CD /1 */ { 0, BX_IA_ERROR }, /* CE /1 */ { 0, BX_IA_ERROR }, /* CF /1 */ { 0, BX_IA_ERROR }, /* D0 /1 */ { 0, BX_IA_ERROR }, /* D1 /1 */ { 0, BX_IA_ERROR }, /* D2 /1 */ { 0, BX_IA_ERROR }, /* D3 /1 */ { 0, BX_IA_ERROR }, /* D4 /1 */ { 0, BX_IA_ERROR }, /* D5 /1 */ { 0, BX_IA_ERROR }, /* D6 /1 */ { 0, BX_IA_ERROR }, /* D7 /1 */ { 0, BX_IA_ERROR }, /* D8 /1 */ { 0, BX_IA_ERROR }, /* D9 /1 */ { 0, BX_IA_ERROR }, /* DA /1 */ { 0, BX_IA_ERROR }, /* DB /1 */ { 0, BX_IA_ERROR }, /* DC /1 */ { 0, BX_IA_ERROR }, /* DD /1 */ { 0, BX_IA_ERROR }, /* DE /1 */ { 0, BX_IA_ERROR }, /* DF /1 */ { 0, BX_IA_ERROR }, /* E0 /1 */ { 0, BX_IA_ERROR }, /* E1 /1 */ { 0, BX_IA_ERROR }, /* E2 /1 */ { 0, BX_IA_ERROR }, /* E3 /1 */ { 0, BX_IA_ERROR }, /* E4 /1 */ { 0, BX_IA_ERROR }, /* E5 /1 */ { 0, BX_IA_ERROR }, /* E6 /1 */ { 0, BX_IA_ERROR }, /* E7 /1 */ { 0, BX_IA_ERROR }, /* E8 /1 */ { 0, BX_IA_ERROR }, /* E9 /1 */ { 0, BX_IA_ERROR }, /* EA /1 */ { 0, BX_IA_ERROR }, /* EB /1 */ { 0, BX_IA_ERROR }, /* EC /1 */ { 0, BX_IA_ERROR }, /* ED /1 */ { 0, BX_IA_ERROR }, /* EE /1 */ { 0, BX_IA_ERROR }, /* EF /1 */ { 0, BX_IA_ERROR }, /* F0 /1 */ { 0, BX_IA_ERROR }, /* F1 /1 */ { 0, BX_IA_ERROR }, /* F2 /1 */ { 0, BX_IA_ERROR }, /* F3 /1 */ { 0, BX_IA_ERROR }, /* F4 /1 */ { 0, BX_IA_ERROR }, /* F5 /1 */ { 0, BX_IA_ERROR }, /* F6 /1 */ { 0, BX_IA_ERROR }, /* F7 /1 */ { 0, BX_IA_ERROR }, /* F8 /1 */ { 0, BX_IA_ERROR }, /* F9 /1 */ { 0, BX_IA_ERROR }, /* FA /1 */ { 0, BX_IA_ERROR }, /* FB /1 */ { 0, BX_IA_ERROR }, /* FC /1 */ { 0, BX_IA_ERROR }, /* FD /1 */ { 0, BX_IA_ERROR }, /* FE /1 */ { 0, BX_IA_ERROR }, /* FF /1 */ { 0, BX_IA_ERROR }, // 256 entries for VEX-encoded 0x0F 0x3A opcodes (VEX.L=1) /* 00 /1 */ { BxPrefixSSE66 | BxVexW1 | BxImmediate_Ib, BX_IA_V256_VPERMQ_VdqWdqIb }, /* 01 /1 */ { BxPrefixSSE66 | BxVexW1 | BxImmediate_Ib, BX_IA_V256_VPERMPD_VpdWpdIb }, /* 02 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VPBLENDD_VdqHdqWdqIb }, /* 03 /1 */ { 0, BX_IA_ERROR }, /* 04 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VPERMILPS_VpsWpsIb }, /* 05 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VPERMILPD_VpdWpdIb }, /* 06 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_V256_VPERM2F128_VdqHdqWdqIb }, /* 07 /1 */ { 0, BX_IA_ERROR }, /* 08 /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDPS_VpsWpsIb }, /* 09 /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDPD_VpdWpdIb }, /* 0A /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDSS_VssHpsWssIb }, /* 0B /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VROUNDSD_VsdHpdWsdIb }, /* 0C /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VBLENDPS_VpsHpsWpsIb }, /* 0D /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VBLENDPD_VpdHpdWpdIb }, /* 0E /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V256_VPBLENDW_VdqHdqWdqIb }, /* 0F /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V256_VPALIGNR_VdqHdqWdqIb }, /* 10 /1 */ { 0, BX_IA_ERROR }, /* 11 /1 */ { 0, BX_IA_ERROR }, /* 12 /1 */ { 0, BX_IA_ERROR }, /* 13 /1 */ { 0, BX_IA_ERROR }, /* 14 /1 */ { 0, BX_IA_ERROR }, /* 15 /1 */ { 0, BX_IA_ERROR }, /* 16 /1 */ { 0, BX_IA_ERROR }, /* 17 /1 */ { 0, BX_IA_ERROR }, /* 18 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_V256_VINSERTF128_VdqHdqWdqIb }, /* 19 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_V256_VEXTRACTF128_WdqVdqIb }, /* 1A /1 */ { 0, BX_IA_ERROR }, /* 1B /1 */ { 0, BX_IA_ERROR }, /* 1C /1 */ { 0, BX_IA_ERROR }, /* 1D /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_VCVTPS2PH_WpsVpsIb }, /* 1E /1 */ { 0, BX_IA_ERROR }, /* 1F /1 */ { 0, BX_IA_ERROR }, /* 20 /1 */ { 0, BX_IA_ERROR }, /* 21 /1 */ { 0, BX_IA_ERROR }, /* 22 /1 */ { 0, BX_IA_ERROR }, /* 23 /1 */ { 0, BX_IA_ERROR }, /* 24 /1 */ { 0, BX_IA_ERROR }, /* 25 /1 */ { 0, BX_IA_ERROR }, /* 26 /1 */ { 0, BX_IA_ERROR }, /* 27 /1 */ { 0, BX_IA_ERROR }, /* 28 /1 */ { 0, BX_IA_ERROR }, /* 29 /1 */ { 0, BX_IA_ERROR }, /* 2A /1 */ { 0, BX_IA_ERROR }, /* 2B /1 */ { 0, BX_IA_ERROR }, /* 2C /1 */ { 0, BX_IA_ERROR }, /* 2D /1 */ { 0, BX_IA_ERROR }, /* 2E /1 */ { 0, BX_IA_ERROR }, /* 2F /1 */ { 0, BX_IA_ERROR }, /* 30 /1 */ { 0, BX_IA_ERROR }, /* 31 /1 */ { 0, BX_IA_ERROR }, /* 32 /1 */ { 0, BX_IA_ERROR }, /* 33 /1 */ { 0, BX_IA_ERROR }, /* 34 /1 */ { 0, BX_IA_ERROR }, /* 35 /1 */ { 0, BX_IA_ERROR }, /* 36 /1 */ { 0, BX_IA_ERROR }, /* 37 /1 */ { 0, BX_IA_ERROR }, /* 38 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_V256_VINSERTI128_VdqHdqWdqIb }, /* 39 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_V256_VEXTRACTI128_WdqVdqIb }, /* 3A /1 */ { 0, BX_IA_ERROR }, /* 3B /1 */ { 0, BX_IA_ERROR }, /* 3C /1 */ { 0, BX_IA_ERROR }, /* 3D /1 */ { 0, BX_IA_ERROR }, /* 3E /1 */ { 0, BX_IA_ERROR }, /* 3F /1 */ { 0, BX_IA_ERROR }, /* 40 /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_VDPPS_VpsHpsWpsIb }, /* 41 /1 */ { 0, BX_IA_ERROR }, /* 42 /1 */ { BxPrefixSSE66 | BxImmediate_Ib, BX_IA_V256_VMPSADBW_VdqWdqIb }, /* 43 /1 */ { 0, BX_IA_ERROR }, /* 44 /1 */ { 0, BX_IA_ERROR }, /* 45 /1 */ { 0, BX_IA_ERROR }, /* 46 /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib, BX_IA_V256_VPERM2I128_VdqHdqWdqIb }, /* 47 /1 */ { 0, BX_IA_ERROR }, /* 48 /1 */ { BxPrefixSSE66 | BxImmediate_Ib5, BX_IA_VPERMIL2PS_VdqHdqWdqIb }, /* 49 /1 */ { BxPrefixSSE66 | BxImmediate_Ib5, BX_IA_VPERMIL2PD_VdqHdqWdqIb }, /* 4A /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib4, BX_IA_VBLENDVPS_VpsHpsWpsIb }, /* 4B /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib4, BX_IA_VBLENDVPD_VpdHpdWpdIb }, /* 4C /1 */ { BxPrefixSSE66 | BxVexW0 | BxImmediate_Ib4, BX_IA_V256_VPBLENDVB_VdqHdqWdqIb }, /* 4D /1 */ { 0, BX_IA_ERROR }, /* 4E /1 */ { 0, BX_IA_ERROR }, /* 4F /1 */ { 0, BX_IA_ERROR }, /* 50 /1 */ { 0, BX_IA_ERROR }, /* 51 /1 */ { 0, BX_IA_ERROR }, /* 52 /1 */ { 0, BX_IA_ERROR }, /* 53 /1 */ { 0, BX_IA_ERROR }, /* 54 /1 */ { 0, BX_IA_ERROR }, /* 55 /1 */ { 0, BX_IA_ERROR }, /* 56 /1 */ { 0, BX_IA_ERROR }, /* 57 /1 */ { 0, BX_IA_ERROR }, /* 58 /1 */ { 0, BX_IA_ERROR }, /* 59 /1 */ { 0, BX_IA_ERROR }, /* 5A /1 */ { 0, BX_IA_ERROR }, /* 5B /1 */ { 0, BX_IA_ERROR }, /* 5C /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSUBPS_VpsHpsWpsVIb }, /* 5D /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSUBPD_VpdHpdWpdVIb }, /* 5E /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBADDPS_VpsHpsWpsVIb }, /* 5F /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBADDPD_VpdHpdWpdVIb }, /* 60 /1 */ { 0, BX_IA_ERROR }, /* 61 /1 */ { 0, BX_IA_ERROR }, /* 62 /1 */ { 0, BX_IA_ERROR }, /* 63 /1 */ { 0, BX_IA_ERROR }, /* 64 /1 */ { 0, BX_IA_ERROR }, /* 65 /1 */ { 0, BX_IA_ERROR }, /* 66 /1 */ { 0, BX_IA_ERROR }, /* 67 /1 */ { 0, BX_IA_ERROR }, /* 68 /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDPS_VpsHpsWpsVIb }, /* 69 /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDPD_VpdHpdWpdVIb }, /* 6A /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSS_VssHssWssVIb }, /* 6B /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMADDSD_VsdHsdWsdVIb }, /* 6C /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBPS_VpsHpsWpsVIb }, /* 6D /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBPD_VpdHpdWpdVIb }, /* 6E /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBSS_VssHssWssVIb }, /* 6F /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFMSUBSD_VsdHsdWsdVIb }, /* 70 /1 */ { 0, BX_IA_ERROR }, /* 71 /1 */ { 0, BX_IA_ERROR }, /* 72 /1 */ { 0, BX_IA_ERROR }, /* 73 /1 */ { 0, BX_IA_ERROR }, /* 74 /1 */ { 0, BX_IA_ERROR }, /* 75 /1 */ { 0, BX_IA_ERROR }, /* 76 /1 */ { 0, BX_IA_ERROR }, /* 77 /1 */ { 0, BX_IA_ERROR }, /* 78 /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDPS_VpsHpsWpsVIb }, /* 79 /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDPD_VpdHpdWpdVIb }, /* 7A /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDSS_VssHssWssVIb }, /* 7B /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMADDSD_VsdHsdWsdVIb }, /* 7C /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBPS_VpsHpsWpsVIb }, /* 7D /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBPD_VpdHpdWpdVIb }, /* 7E /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBSS_VssHssWssVIb }, /* 7F /1 */ { BxPrefixSSE66 | BxImmediate_Ib4, BX_IA_VFNMSUBSD_VsdHsdWsdVIb }, /* 80 /1 */ { 0, BX_IA_ERROR }, /* 81 /1 */ { 0, BX_IA_ERROR }, /* 82 /1 */ { 0, BX_IA_ERROR }, /* 83 /1 */ { 0, BX_IA_ERROR }, /* 84 /1 */ { 0, BX_IA_ERROR }, /* 85 /1 */ { 0, BX_IA_ERROR }, /* 86 /1 */ { 0, BX_IA_ERROR }, /* 87 /1 */ { 0, BX_IA_ERROR }, /* 88 /1 */ { 0, BX_IA_ERROR }, /* 89 /1 */ { 0, BX_IA_ERROR }, /* 8A /1 */ { 0, BX_IA_ERROR }, /* 8B /1 */ { 0, BX_IA_ERROR }, /* 8C /1 */ { 0, BX_IA_ERROR }, /* 8D /1 */ { 0, BX_IA_ERROR }, /* 8E /1 */ { 0, BX_IA_ERROR }, /* 8F /1 */ { 0, BX_IA_ERROR }, /* 90 /1 */ { 0, BX_IA_ERROR }, /* 91 /1 */ { 0, BX_IA_ERROR }, /* 92 /1 */ { 0, BX_IA_ERROR }, /* 93 /1 */ { 0, BX_IA_ERROR }, /* 94 /1 */ { 0, BX_IA_ERROR }, /* 95 /1 */ { 0, BX_IA_ERROR }, /* 96 /1 */ { 0, BX_IA_ERROR }, /* 97 /1 */ { 0, BX_IA_ERROR }, /* 98 /1 */ { 0, BX_IA_ERROR }, /* 99 /1 */ { 0, BX_IA_ERROR }, /* 9A /1 */ { 0, BX_IA_ERROR }, /* 9B /1 */ { 0, BX_IA_ERROR }, /* 9C /1 */ { 0, BX_IA_ERROR }, /* 9D /1 */ { 0, BX_IA_ERROR }, /* 9E /1 */ { 0, BX_IA_ERROR }, /* 9F /1 */ { 0, BX_IA_ERROR }, /* A0 /1 */ { 0, BX_IA_ERROR }, /* A1 /1 */ { 0, BX_IA_ERROR }, /* A2 /1 */ { 0, BX_IA_ERROR }, /* A3 /1 */ { 0, BX_IA_ERROR }, /* A4 /1 */ { 0, BX_IA_ERROR }, /* A5 /1 */ { 0, BX_IA_ERROR }, /* A6 /1 */ { 0, BX_IA_ERROR }, /* A7 /1 */ { 0, BX_IA_ERROR }, /* A8 /1 */ { 0, BX_IA_ERROR }, /* A9 /1 */ { 0, BX_IA_ERROR }, /* AA /1 */ { 0, BX_IA_ERROR }, /* AB /1 */ { 0, BX_IA_ERROR }, /* AC /1 */ { 0, BX_IA_ERROR }, /* AD /1 */ { 0, BX_IA_ERROR }, /* AE /1 */ { 0, BX_IA_ERROR }, /* AF /1 */ { 0, BX_IA_ERROR }, /* B0 /1 */ { 0, BX_IA_ERROR }, /* B1 /1 */ { 0, BX_IA_ERROR }, /* B2 /1 */ { 0, BX_IA_ERROR }, /* B3 /1 */ { 0, BX_IA_ERROR }, /* B4 /1 */ { 0, BX_IA_ERROR }, /* B5 /1 */ { 0, BX_IA_ERROR }, /* B6 /1 */ { 0, BX_IA_ERROR }, /* B7 /1 */ { 0, BX_IA_ERROR }, /* B8 /1 */ { 0, BX_IA_ERROR }, /* B9 /1 */ { 0, BX_IA_ERROR }, /* BA /1 */ { 0, BX_IA_ERROR }, /* BB /1 */ { 0, BX_IA_ERROR }, /* BC /1 */ { 0, BX_IA_ERROR }, /* BD /1 */ { 0, BX_IA_ERROR }, /* BE /1 */ { 0, BX_IA_ERROR }, /* BF /1 */ { 0, BX_IA_ERROR }, /* C0 /1 */ { 0, BX_IA_ERROR }, /* C1 /1 */ { 0, BX_IA_ERROR }, /* C2 /1 */ { 0, BX_IA_ERROR }, /* C3 /1 */ { 0, BX_IA_ERROR }, /* C4 /1 */ { 0, BX_IA_ERROR }, /* C5 /1 */ { 0, BX_IA_ERROR }, /* C6 /1 */ { 0, BX_IA_ERROR }, /* C7 /1 */ { 0, BX_IA_ERROR }, /* C8 /1 */ { 0, BX_IA_ERROR }, /* C9 /1 */ { 0, BX_IA_ERROR }, /* CA /1 */ { 0, BX_IA_ERROR }, /* CB /1 */ { 0, BX_IA_ERROR }, /* CC /1 */ { 0, BX_IA_ERROR }, /* CD /1 */ { 0, BX_IA_ERROR }, /* CE /1 */ { 0, BX_IA_ERROR }, /* CF /1 */ { 0, BX_IA_ERROR }, /* D0 /1 */ { 0, BX_IA_ERROR }, /* D1 /1 */ { 0, BX_IA_ERROR }, /* D2 /1 */ { 0, BX_IA_ERROR }, /* D3 /1 */ { 0, BX_IA_ERROR }, /* D4 /1 */ { 0, BX_IA_ERROR }, /* D5 /1 */ { 0, BX_IA_ERROR }, /* D6 /1 */ { 0, BX_IA_ERROR }, /* D7 /1 */ { 0, BX_IA_ERROR }, /* D8 /1 */ { 0, BX_IA_ERROR }, /* D9 /1 */ { 0, BX_IA_ERROR }, /* DA /1 */ { 0, BX_IA_ERROR }, /* DB /1 */ { 0, BX_IA_ERROR }, /* DC /1 */ { 0, BX_IA_ERROR }, /* DD /1 */ { 0, BX_IA_ERROR }, /* DE /1 */ { 0, BX_IA_ERROR }, /* DF /1 */ { 0, BX_IA_ERROR }, /* E0 /1 */ { 0, BX_IA_ERROR }, /* E1 /1 */ { 0, BX_IA_ERROR }, /* E2 /1 */ { 0, BX_IA_ERROR }, /* E3 /1 */ { 0, BX_IA_ERROR }, /* E4 /1 */ { 0, BX_IA_ERROR }, /* E5 /1 */ { 0, BX_IA_ERROR }, /* E6 /1 */ { 0, BX_IA_ERROR }, /* E7 /1 */ { 0, BX_IA_ERROR }, /* E8 /1 */ { 0, BX_IA_ERROR }, /* E9 /1 */ { 0, BX_IA_ERROR }, /* EA /1 */ { 0, BX_IA_ERROR }, /* EB /1 */ { 0, BX_IA_ERROR }, /* EC /1 */ { 0, BX_IA_ERROR }, /* ED /1 */ { 0, BX_IA_ERROR }, /* EE /1 */ { 0, BX_IA_ERROR }, /* EF /1 */ { 0, BX_IA_ERROR }, /* F0 /1 */ { 0, BX_IA_ERROR }, /* F1 /1 */ { 0, BX_IA_ERROR }, /* F2 /1 */ { 0, BX_IA_ERROR }, /* F3 /1 */ { 0, BX_IA_ERROR }, /* F4 /1 */ { 0, BX_IA_ERROR }, /* F5 /1 */ { 0, BX_IA_ERROR }, /* F6 /1 */ { 0, BX_IA_ERROR }, /* F7 /1 */ { 0, BX_IA_ERROR }, /* F8 /1 */ { 0, BX_IA_ERROR }, /* F9 /1 */ { 0, BX_IA_ERROR }, /* FA /1 */ { 0, BX_IA_ERROR }, /* FB /1 */ { 0, BX_IA_ERROR }, /* FC /1 */ { 0, BX_IA_ERROR }, /* FD /1 */ { 0, BX_IA_ERROR }, /* FE /1 */ { 0, BX_IA_ERROR }, /* FF /1 */ { 0, BX_IA_ERROR } }; #endif // BX_SUPPORT_AVX && BX_CPU_LEVEL >= 6 #endif // BX_AVX_FETCHDECODE_TABLES_H bochs-2.6/cpu/bit32.cc0000644000175000017500000002314312020641453014356 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: bit32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_CPU_LEVEL >= 3 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSF_GdEdR(bxInstruction_c *i) { Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); if (op2_32 == 0) { assert_ZF(); /* op1_32 undefined */ } else { Bit32u op1_32 = 0; while ((op2_32 & 0x01) == 0) { op1_32++; op2_32 >>= 1; } SET_FLAGS_OSZAPC_LOGIC_32(op1_32); clear_ZF(); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BSR_GdEdR(bxInstruction_c *i) { Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); if (op2_32 == 0) { assert_ZF(); /* op1_32 undefined */ } else { Bit32u op1_32 = 31; while ((op2_32 & 0x80000000) == 0) { op1_32--; op2_32 <<= 1; } SET_FLAGS_OSZAPC_LOGIC_32(op1_32); clear_ZF(); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); } BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdGdM(bxInstruction_c *i) { bx_address op1_addr; Bit32u op1_32, op2_32, index; Bit32s displacement32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_32 = BX_READ_32BIT_REG(i->src()); index = op2_32 & 0x1f; displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32; op1_addr = eaddr + 4 * displacement32; /* pointer, segment address pair */ op1_32 = read_virtual_dword(i->seg(), op1_addr & i->asize_mask()); set_CF((op1_32 >> index) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op2_32 &= 0x1f; set_CF((op1_32 >> op2_32) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdGdM(bxInstruction_c *i) { bx_address op1_addr; Bit32u op1_32, op2_32, index; Bit32s displacement32; bx_bool bit_i; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_32 = BX_READ_32BIT_REG(i->src()); index = op2_32 & 0x1f; displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32; op1_addr = eaddr + 4 * displacement32; /* pointer, segment address pair */ op1_32 = read_RMW_virtual_dword(i->seg(), op1_addr & i->asize_mask()); bit_i = (op1_32 >> index) & 0x01; op1_32 |= (1 << index); write_RMW_virtual_dword(op1_32); set_CF(bit_i); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op2_32 &= 0x1f; set_CF((op1_32 >> op2_32) & 0x01); op1_32 |= (1 << op2_32); /* now write result back to the destination */ BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdGdM(bxInstruction_c *i) { bx_address op1_addr; Bit32u op1_32, op2_32, index; Bit32s displacement32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_32 = BX_READ_32BIT_REG(i->src()); index = op2_32 & 0x1f; displacement32 = ((Bit32s) (op2_32&0xffffffe0)) / 32; op1_addr = eaddr + 4 * displacement32; /* pointer, segment address pair */ op1_32 = read_RMW_virtual_dword(i->seg(), op1_addr & i->asize_mask()); bx_bool temp_cf = (op1_32 >> index) & 0x01; op1_32 &= ~(1 << index); /* now write back to destination */ write_RMW_virtual_dword(op1_32); set_CF(temp_cf); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op2_32 &= 0x1f; set_CF((op1_32 >> op2_32) & 0x01); op1_32 &= ~(1 << op2_32); /* now write result back to the destination */ BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdGdM(bxInstruction_c *i) { bx_address op1_addr; Bit32u op1_32, op2_32, index_32; Bit32s displacement32; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op2_32 = BX_READ_32BIT_REG(i->src()); index_32 = op2_32 & 0x1f; displacement32 = ((Bit32s) (op2_32 & 0xffffffe0)) / 32; op1_addr = eaddr + 4 * displacement32; op1_32 = read_RMW_virtual_dword(i->seg(), op1_addr & i->asize_mask()); bx_bool temp_CF = (op1_32 >> index_32) & 0x01; op1_32 ^= (1 << index_32); /* toggle bit */ set_CF(temp_CF); write_RMW_virtual_dword(op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdGdR(bxInstruction_c *i) { Bit32u op1_32, op2_32; op1_32 = BX_READ_32BIT_REG(i->dst()); op2_32 = BX_READ_32BIT_REG(i->src()); op2_32 &= 0x1f; bx_bool temp_CF = (op1_32 >> op2_32) & 0x01; op1_32 ^= (1 << op2_32); /* toggle bit */ set_CF(temp_CF); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdIbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_virtual_dword(i->seg(), eaddr); Bit8u op2_8 = i->Ib() & 0x1f; set_CF((op1_32 >> op2_8) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BT_EdIbR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); Bit8u op2_8 = i->Ib() & 0x1f; set_CF((op1_32 >> op2_8) & 0x01); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x1f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); bx_bool temp_CF = (op1_32 >> op2_8) & 0x01; op1_32 |= (1 << op2_8); write_RMW_virtual_dword(op1_32); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTS_EdIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x1f; Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); bx_bool temp_CF = (op1_32 >> op2_8) & 0x01; op1_32 |= (1 << op2_8); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x1f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); bx_bool temp_CF = (op1_32 >> op2_8) & 0x01; op1_32 ^= (1 << op2_8); /* toggle bit */ write_RMW_virtual_dword(op1_32); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTC_EdIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x1f; Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); bx_bool temp_CF = (op1_32 >> op2_8) & 0x01; op1_32 ^= (1 << op2_8); /* toggle bit */ BX_WRITE_32BIT_REGZ(i->dst(), op1_32); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdIbM(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x1f; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); bx_bool temp_CF = (op1_32 >> op2_8) & 0x01; op1_32 &= ~(1 << op2_8); write_RMW_virtual_dword(op1_32); set_CF(temp_CF); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::BTR_EdIbR(bxInstruction_c *i) { Bit8u op2_8 = i->Ib() & 0x1f; Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); bx_bool temp_CF = (op1_32 >> op2_8) & 0x01; op1_32 &= ~(1 << op2_8); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); set_CF(temp_CF); BX_NEXT_INSTR(i); } /* F3 0F B8 */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPCNT_GdEdR(bxInstruction_c *i) { Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); Bit32u op1_32 = 0; while (op2_32 != 0) { if (op2_32 & 1) op1_32++; op2_32 >>= 1; } Bit32u flags = op1_32 ? 0 : EFlagsZFMask; setEFlagsOSZAPC(flags); BX_WRITE_32BIT_REGZ(i->dst(), op1_32); BX_NEXT_INSTR(i); } /* F3 0F BC */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TZCNT_GdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src()); Bit32u mask = 0x1, result_32 = 0; while ((op1_32 & mask) == 0 && mask) { mask <<= 1; result_32++; } set_CF(! op1_32); set_ZF(! result_32); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } /* F3 0F BD */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LZCNT_GdEdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->src()); Bit32u mask = 0x80000000, result_32 = 0; while ((op1_32 & mask) == 0 && mask) { mask >>= 1; result_32++; } set_CF(! op1_32); set_ZF(! result_32); BX_WRITE_32BIT_REGZ(i->dst(), result_32); BX_NEXT_INSTR(i); } #endif // (BX_CPU_LEVEL >= 3) bochs-2.6/cpu/logical64.cc0000644000175000017500000001760712020641453015227 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: logical64.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 ^= op2_64; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 ^= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); op1_64 ^= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64 = (Bit32s) i->Id(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op1_64 ^= op2_64; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XOR_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64 = (Bit32s) i->Id(); op1_64 = BX_READ_64BIT_REG(i->dst()); op1_64 ^= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64 = (Bit32s) i->Id(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op1_64 |= op2_64; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64 = (Bit32s) i->Id(); op1_64 = BX_READ_64BIT_REG(i->dst()); op1_64 |= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EqM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit64u op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op1_64 = ~op1_64; write_RMW_virtual_qword(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::NOT_EqR(bxInstruction_c *i) { Bit64u op1_64 = BX_READ_64BIT_REG(i->dst()); op1_64 = ~op1_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 |= op2_64; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 |= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::OR_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); op1_64 |= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 &= op2_64; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GqEqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 &= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_GqEqM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = read_virtual_qword_64(i->seg(), eaddr); op1_64 &= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64 = (Bit32s) i->Id(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_RMW_virtual_qword_64(i->seg(), eaddr); op1_64 &= op2_64; write_RMW_virtual_qword(op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::AND_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64 = (Bit32s) i->Id(); op1_64 = BX_READ_64BIT_REG(i->dst()); op1_64 &= op2_64; BX_WRITE_64BIT_REG(i->dst(), op1_64); SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EqGqR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 &= op2_64; SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EqGqM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_virtual_qword_64(i->seg(), eaddr); op2_64 = BX_READ_64BIT_REG(i->src()); op1_64 &= op2_64; SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EqIdR(bxInstruction_c *i) { Bit64u op1_64, op2_64; op1_64 = BX_READ_64BIT_REG(i->dst()); op2_64 = (Bit32s) i->Id(); op1_64 &= op2_64; SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::TEST_EqIdM(bxInstruction_c *i) { Bit64u op1_64, op2_64; bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_64 = read_virtual_qword_64(i->seg(), eaddr); op2_64 = (Bit32s) i->Id(); op1_64 &= op2_64; SET_FLAGS_OSZAPC_LOGIC_64(op1_64); BX_NEXT_INSTR(i); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/crregs.h0000644000175000017500000002370712020641453014570 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: crregs.h 11272 2012-07-11 15:07:54Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_CRREGS #define BX_CRREGS #define BX_CR0_PE_MASK (1 << 0) #define BX_CR0_MP_MASK (1 << 1) #define BX_CR0_EM_MASK (1 << 2) #define BX_CR0_TS_MASK (1 << 3) #define BX_CR0_ET_MASK (1 << 4) #define BX_CR0_NE_MASK (1 << 5) #define BX_CR0_WP_MASK (1 << 16) #define BX_CR0_AM_MASK (1 << 18) #define BX_CR0_NW_MASK (1 << 29) #define BX_CR0_CD_MASK (1 << 30) #define BX_CR0_PG_MASK (1 << 31) struct bx_cr0_t { Bit32u val32; // 32bit value of register // Accessors for all cr0 bitfields. #define IMPLEMENT_CRREG_ACCESSORS(name, bitnum) \ BX_CPP_INLINE bx_bool get_##name() const { \ return 1 & (val32 >> bitnum); \ } \ BX_CPP_INLINE void set_##name(Bit8u val) { \ val32 = (val32 & ~(1<= 4 IMPLEMENT_CRREG_ACCESSORS(ET, 4); IMPLEMENT_CRREG_ACCESSORS(NE, 5); IMPLEMENT_CRREG_ACCESSORS(WP, 16); IMPLEMENT_CRREG_ACCESSORS(AM, 18); IMPLEMENT_CRREG_ACCESSORS(NW, 29); IMPLEMENT_CRREG_ACCESSORS(CD, 30); #endif IMPLEMENT_CRREG_ACCESSORS(PG, 31); BX_CPP_INLINE Bit32u get32() const { return val32; } // ET is hardwired bit in CR0 BX_CPP_INLINE void set32(Bit32u val) { val32 = val | 0x10; } }; #if BX_CPU_LEVEL >= 5 #define BX_CR4_VME_MASK (1 << 0) #define BX_CR4_PVI_MASK (1 << 1) #define BX_CR4_TSD_MASK (1 << 2) #define BX_CR4_DE_MASK (1 << 3) #define BX_CR4_PSE_MASK (1 << 4) #define BX_CR4_PAE_MASK (1 << 5) #define BX_CR4_MCE_MASK (1 << 6) #define BX_CR4_PGE_MASK (1 << 7) #define BX_CR4_PCE_MASK (1 << 8) #define BX_CR4_OSFXSR_MASK (1 << 9) #define BX_CR4_OSXMMEXCPT_MASK (1 << 10) #define BX_CR4_VMXE_MASK (1 << 13) #define BX_CR4_SMXE_MASK (1 << 14) #define BX_CR4_FSGSBASE_MASK (1 << 16) #define BX_CR4_PCIDE_MASK (1 << 17) #define BX_CR4_OSXSAVE_MASK (1 << 18) #define BX_CR4_SMEP_MASK (1 << 20) struct bx_cr4_t { Bit32u val32; // 32bit value of register IMPLEMENT_CRREG_ACCESSORS(VME, 0); IMPLEMENT_CRREG_ACCESSORS(PVI, 1); IMPLEMENT_CRREG_ACCESSORS(TSD, 2); IMPLEMENT_CRREG_ACCESSORS(DE, 3); IMPLEMENT_CRREG_ACCESSORS(PSE, 4); IMPLEMENT_CRREG_ACCESSORS(PAE, 5); IMPLEMENT_CRREG_ACCESSORS(MCE, 6); IMPLEMENT_CRREG_ACCESSORS(PGE, 7); IMPLEMENT_CRREG_ACCESSORS(PCE, 8); IMPLEMENT_CRREG_ACCESSORS(OSFXSR, 9); IMPLEMENT_CRREG_ACCESSORS(OSXMMEXCPT, 10); #if BX_SUPPORT_VMX IMPLEMENT_CRREG_ACCESSORS(VMXE, 13); #endif IMPLEMENT_CRREG_ACCESSORS(SMXE, 14); #if BX_SUPPORT_X86_64 IMPLEMENT_CRREG_ACCESSORS(FSGSBASE, 16); #endif IMPLEMENT_CRREG_ACCESSORS(PCIDE, 17); IMPLEMENT_CRREG_ACCESSORS(OSXSAVE, 18); IMPLEMENT_CRREG_ACCESSORS(SMEP, 20); BX_CPP_INLINE Bit32u get32() const { return val32; } BX_CPP_INLINE void set32(Bit32u val) { val32 = val; } }; #define BX_CR4_FLUSH_TLB_MASK \ (BX_CR4_PSE_MASK | BX_CR4_PAE_MASK | BX_CR4_PGE_MASK | BX_CR4_PCIDE_MASK | BX_CR4_SMEP_MASK) #endif // #if BX_CPU_LEVEL >= 5 struct bx_dr6_t { Bit32u val32; // 32bit value of register IMPLEMENT_CRREG_ACCESSORS(B0, 0); IMPLEMENT_CRREG_ACCESSORS(B1, 1); IMPLEMENT_CRREG_ACCESSORS(B2, 2); IMPLEMENT_CRREG_ACCESSORS(B3, 3); #define BX_DEBUG_TRAP_HIT (1 << 12) #define BX_DEBUG_DR_ACCESS_BIT (1 << 13) #define BX_DEBUG_SINGLE_STEP_BIT (1 << 14) #define BX_DEBUG_TRAP_TASK_SWITCH_BIT (1 << 15) IMPLEMENT_CRREG_ACCESSORS(BD, 13); IMPLEMENT_CRREG_ACCESSORS(BS, 14); IMPLEMENT_CRREG_ACCESSORS(BT, 15); BX_CPP_INLINE Bit32u get32() const { return val32; } BX_CPP_INLINE void set32(Bit32u val) { val32 = val; } }; struct bx_dr7_t { Bit32u val32; // 32bit value of register IMPLEMENT_CRREG_ACCESSORS(L0, 0); IMPLEMENT_CRREG_ACCESSORS(G0, 1); IMPLEMENT_CRREG_ACCESSORS(L1, 2); IMPLEMENT_CRREG_ACCESSORS(G1, 3); IMPLEMENT_CRREG_ACCESSORS(L2, 4); IMPLEMENT_CRREG_ACCESSORS(G2, 5); IMPLEMENT_CRREG_ACCESSORS(L3, 6); IMPLEMENT_CRREG_ACCESSORS(G3, 7); IMPLEMENT_CRREG_ACCESSORS(LE, 8); IMPLEMENT_CRREG_ACCESSORS(GE, 9); IMPLEMENT_CRREG_ACCESSORS(GD, 13); #define IMPLEMENT_DRREG_ACCESSORS(name, bitmask, bitnum) \ int get_##name() const { \ return (val32 & (bitmask)) >> (bitnum); \ } IMPLEMENT_DRREG_ACCESSORS(R_W0, 0x00030000, 16); IMPLEMENT_DRREG_ACCESSORS(LEN0, 0x000C0000, 18); IMPLEMENT_DRREG_ACCESSORS(R_W1, 0x00300000, 20); IMPLEMENT_DRREG_ACCESSORS(LEN1, 0x00C00000, 22); IMPLEMENT_DRREG_ACCESSORS(R_W2, 0x03000000, 24); IMPLEMENT_DRREG_ACCESSORS(LEN2, 0x0C000000, 26); IMPLEMENT_DRREG_ACCESSORS(R_W3, 0x30000000, 28); IMPLEMENT_DRREG_ACCESSORS(LEN3, 0xC0000000, 30); IMPLEMENT_DRREG_ACCESSORS(bp_enabled, 0xFF, 0); BX_CPP_INLINE Bit32u get32() const { return val32; } BX_CPP_INLINE void set32(Bit32u val) { val32 = val; } }; #if BX_CPU_LEVEL >= 5 #define BX_EFER_SCE_MASK (1 << 0) #define BX_EFER_LME_MASK (1 << 8) #define BX_EFER_LMA_MASK (1 << 10) #define BX_EFER_NXE_MASK (1 << 11) #define BX_EFER_SVME_MASK (1 << 12) #define BX_EFER_LMSLE_MASK (1 << 13) #define BX_EFER_FFXSR_MASK (1 << 14) struct bx_efer_t { Bit32u val32; // 32bit value of register IMPLEMENT_CRREG_ACCESSORS(SCE, 0); #if BX_SUPPORT_X86_64 IMPLEMENT_CRREG_ACCESSORS(LME, 8); IMPLEMENT_CRREG_ACCESSORS(LMA, 10); #endif IMPLEMENT_CRREG_ACCESSORS(NXE, 11); #if BX_SUPPORT_X86_64 IMPLEMENT_CRREG_ACCESSORS(SVME, 12); /* AMD Secure Virtual Machine */ IMPLEMENT_CRREG_ACCESSORS(LMSLE, 13); /* AMD Long Mode Segment Limit */ IMPLEMENT_CRREG_ACCESSORS(FFXSR, 14); #endif BX_CPP_INLINE Bit32u get32() const { return val32; } BX_CPP_INLINE void set32(Bit32u val) { val32 = val; } }; #endif #if BX_CPU_LEVEL >= 6 struct xcr0_t { Bit32u val32; // 32bit value of register #define BX_XCR0_FPU_BIT 0 #define BX_XCR0_FPU_MASK (1<= 5 typedef struct msr { unsigned index; // MSR index unsigned type; // MSR type: 1 - lin address, 2 - phy address #define BX_LIN_ADDRESS_MSR 1 #define BX_PHY_ADDRESS_MSR 2 Bit64u val64; // current MSR value Bit64u reset_value; // reset value Bit64u reserved; // r/o bits - fault on write Bit64u ignored; // hardwired bits - ignored on write msr(unsigned idx, unsigned msr_type = 0, Bit64u reset_val = 0, Bit64u rsrv = 0, Bit64u ign = 0): index(idx), type(msr_type), val64(reset_val), reset_value(reset_val), reserved(rsrv), ignored(ign) {} msr(unsigned idx, Bit64u reset_val = 0, Bit64u rsrv = 0, Bit64u ign = 0): index(idx), type(0), val64(reset_val), reset_value(reset_val), reserved(rsrv), ignored(ign) {} BX_CPP_INLINE void reset() { val64 = reset_value; } BX_CPP_INLINE Bit64u get64() const { return val64; } BX_CPP_INLINE bx_bool set64(Bit64u new_val) { new_val = (new_val & ~ignored) | (val64 & ignored); switch(type) { #if BX_SUPPORT_X86_64 case BX_LIN_ADDRESS_MSR: if (! IsCanonical(new_val)) return 0; break; #endif case BX_PHY_ADDRESS_MSR: if (! IsValidPhyAddr(new_val)) return 0; break; default: if ((val64 ^ new_val) & reserved) return 0; break; } val64 = new_val; return 1; } } MSR; #endif // BX_CPU_LEVEL >= 5 #endif bochs-2.6/cpu/exception.cc0000644000175000017500000010537712020641453015443 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: exception.cc 11330 2012-08-09 13:11:25Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #include "param_names.h" #include "iodev/iodev.h" #if BX_SUPPORT_X86_64==0 // Make life easier merging cpu64 & cpu code. #define RIP EIP #define RSP ESP #endif #if BX_SUPPORT_X86_64 void BX_CPU_C::long_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error, Bit16u error_code) { bx_descriptor_t gate_descriptor, cs_descriptor; bx_selector_t cs_selector; // interrupt vector must be within IDT table limits, // else #GP(vector*8 + 2 + EXT) if ((vector*16 + 15) > BX_CPU_THIS_PTR idtr.limit) { BX_ERROR(("interrupt(long mode): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit)); exception(BX_GP_EXCEPTION, vector*8 + 2); } Bit64u desctmp1 = system_read_qword(BX_CPU_THIS_PTR idtr.base + vector*16); Bit64u desctmp2 = system_read_qword(BX_CPU_THIS_PTR idtr.base + vector*16 + 8); if (desctmp2 & BX_CONST64(0x00001F0000000000)) { BX_ERROR(("interrupt(long mode): IDT entry extended attributes DWORD4 TYPE != 0")); exception(BX_GP_EXCEPTION, vector*8 + 2); } Bit32u dword1 = GET32L(desctmp1); Bit32u dword2 = GET32H(desctmp1); Bit32u dword3 = GET32L(desctmp2); parse_descriptor(dword1, dword2, &gate_descriptor); if ((gate_descriptor.valid==0) || gate_descriptor.segment) { BX_ERROR(("interrupt(long mode): gate descriptor is not valid sys seg")); exception(BX_GP_EXCEPTION, vector*8 + 2); } // descriptor AR byte must indicate interrupt gate, trap gate, // or task gate, else #GP(vector*8 + 2 + EXT) if (gate_descriptor.type != BX_386_INTERRUPT_GATE && gate_descriptor.type != BX_386_TRAP_GATE) { BX_ERROR(("interrupt(long mode): unsupported gate type %u", (unsigned) gate_descriptor.type)); exception(BX_GP_EXCEPTION, vector*8 + 2); } // if software interrupt, then gate descripor DPL must be >= CPL, // else #GP(vector * 8 + 2 + EXT) if (soft_int && gate_descriptor.dpl < CPL) { BX_ERROR(("interrupt(long mode): soft_int && gate.dpl < CPL")); exception(BX_GP_EXCEPTION, vector*8 + 2); } // Gate must be present, else #NP(vector * 8 + 2 + EXT) if (! IS_PRESENT(gate_descriptor)) { BX_ERROR(("interrupt(long mode): gate.p == 0")); exception(BX_NP_EXCEPTION, vector*8 + 2); } Bit16u gate_dest_selector = gate_descriptor.u.gate.dest_selector; Bit64u gate_dest_offset = ((Bit64u)dword3 << 32) | gate_descriptor.u.gate.dest_offset; unsigned ist = gate_descriptor.u.gate.param_count & 0x7; // examine CS selector and descriptor given in gate descriptor // selector must be non-null else #GP(EXT) if ((gate_dest_selector & 0xfffc) == 0) { BX_ERROR(("int_trap_gate(long mode): selector null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(gate_dest_selector, &cs_selector); // selector must be within its descriptor table limits // else #GP(selector+EXT) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // descriptor AR byte must indicate code seg // and code segment descriptor DPL<=CPL, else #GP(selector+EXT) if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || IS_DATA_SEGMENT(cs_descriptor.type) || cs_descriptor.dpl > CPL) { BX_ERROR(("interrupt(long mode): not accessible or not code segment")); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); } // check that it's a 64 bit segment if (! IS_LONG64_SEGMENT(cs_descriptor) || cs_descriptor.u.segment.d_b) { BX_ERROR(("interrupt(long mode): must be 64 bit segment")); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); } // segment must be present, else #NP(selector + EXT) if (! IS_PRESENT(cs_descriptor)) { BX_ERROR(("interrupt(long mode): segment not present")); exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc); } Bit64u RSP_for_cpl_x; Bit64u old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value; Bit64u old_RIP = RIP; Bit64u old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value; Bit64u old_RSP = RSP; // if code segment is non-conforming and DPL < CPL then // INTERRUPT TO INNER PRIVILEGE: if (IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl < CPL) { BX_DEBUG(("interrupt(long mode): INTERRUPT TO INNER PRIVILEGE")); // check selector and descriptor for new stack in current TSS if (ist > 0) { BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist)); RSP_for_cpl_x = get_RSP_from_TSS(ist+3); } else { RSP_for_cpl_x = get_RSP_from_TSS(cs_descriptor.dpl); } // align stack RSP_for_cpl_x &= BX_CONST64(0xfffffffffffffff0); // push old stack long pointer onto new stack write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS); write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP); write_new_stack_qword_64(RSP_for_cpl_x - 24, cs_descriptor.dpl, read_eflags()); // push long pointer to return address onto new stack write_new_stack_qword_64(RSP_for_cpl_x - 32, cs_descriptor.dpl, old_CS); write_new_stack_qword_64(RSP_for_cpl_x - 40, cs_descriptor.dpl, old_RIP); RSP_for_cpl_x -= 40; if (push_error) { RSP_for_cpl_x -= 8; write_new_stack_qword_64(RSP_for_cpl_x, cs_descriptor.dpl, error_code); } // load CS:RIP (guaranteed to be in 64 bit mode) branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, cs_descriptor.dpl); // set up null SS descriptor load_null_selector(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], cs_descriptor.dpl); } else if(IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) || cs_descriptor.dpl==CPL) { // if code segment is conforming OR code segment DPL = CPL then // INTERRUPT TO SAME PRIVILEGE LEVEL: BX_DEBUG(("interrupt(long mode): INTERRUPT TO SAME PRIVILEGE")); // check selector and descriptor for new stack in current TSS if (ist > 0) { BX_DEBUG(("interrupt(long mode): trap to IST, vector = %d", ist)); RSP_for_cpl_x = get_RSP_from_TSS(ist+3); } else { RSP_for_cpl_x = RSP; } // align stack RSP_for_cpl_x &= BX_CONST64(0xfffffffffffffff0); // push flags onto stack // push current CS selector onto stack // push return offset onto stack write_new_stack_qword_64(RSP_for_cpl_x - 8, cs_descriptor.dpl, old_SS); write_new_stack_qword_64(RSP_for_cpl_x - 16, cs_descriptor.dpl, old_RSP); write_new_stack_qword_64(RSP_for_cpl_x - 24, cs_descriptor.dpl, read_eflags()); // push long pointer to return address onto new stack write_new_stack_qword_64(RSP_for_cpl_x - 32, cs_descriptor.dpl, old_CS); write_new_stack_qword_64(RSP_for_cpl_x - 40, cs_descriptor.dpl, old_RIP); RSP_for_cpl_x -= 40; if (push_error) { RSP_for_cpl_x -= 8; write_new_stack_qword_64(RSP_for_cpl_x, cs_descriptor.dpl, error_code); } // set the RPL field of CS to CPL branch_far64(&cs_selector, &cs_descriptor, gate_dest_offset, CPL); } else { BX_ERROR(("interrupt(long mode): bad descriptor type %u (CS.DPL=%u CPL=%u)", (unsigned) cs_descriptor.type, (unsigned) cs_descriptor.dpl, (unsigned) CPL)); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); } RSP = RSP_for_cpl_x; // if interrupt gate then set IF to 0 if (!(gate_descriptor.type & 1)) // even is int-gate BX_CPU_THIS_PTR clear_IF(); BX_CPU_THIS_PTR clear_TF(); //BX_CPU_THIS_PTR clear_VM(); // VM is clear in long mode BX_CPU_THIS_PTR clear_RF(); BX_CPU_THIS_PTR clear_NT(); } #endif void BX_CPU_C::protected_mode_int(Bit8u vector, unsigned soft_int, bx_bool push_error, Bit16u error_code) { bx_descriptor_t gate_descriptor, cs_descriptor; bx_selector_t cs_selector; Bit16u raw_tss_selector; bx_selector_t tss_selector; bx_descriptor_t tss_descriptor; Bit16u gate_dest_selector; Bit32u gate_dest_offset; // interrupt vector must be within IDT table limits, // else #GP(vector*8 + 2 + EXT) if ((vector*8 + 7) > BX_CPU_THIS_PTR idtr.limit) { BX_ERROR(("interrupt(): vector must be within IDT table limits, IDT.limit = 0x%x", BX_CPU_THIS_PTR idtr.limit)); exception(BX_GP_EXCEPTION, vector*8 + 2); } Bit64u desctmp = system_read_qword(BX_CPU_THIS_PTR idtr.base + vector*8); Bit32u dword1 = GET32L(desctmp); Bit32u dword2 = GET32H(desctmp); parse_descriptor(dword1, dword2, &gate_descriptor); if ((gate_descriptor.valid==0) || gate_descriptor.segment) { BX_ERROR(("interrupt(): gate descriptor is not valid sys seg (vector=0x%02x)", vector)); exception(BX_GP_EXCEPTION, vector*8 + 2); } // descriptor AR byte must indicate interrupt gate, trap gate, // or task gate, else #GP(vector*8 + 2 + EXT) switch (gate_descriptor.type) { case BX_TASK_GATE: case BX_286_INTERRUPT_GATE: case BX_286_TRAP_GATE: case BX_386_INTERRUPT_GATE: case BX_386_TRAP_GATE: break; default: BX_ERROR(("interrupt(): gate.type(%u) != {5,6,7,14,15}", (unsigned) gate_descriptor.type)); exception(BX_GP_EXCEPTION, vector*8 + 2); } // if software interrupt, then gate descripor DPL must be >= CPL, // else #GP(vector * 8 + 2 + EXT) if (soft_int && gate_descriptor.dpl < CPL) { BX_ERROR(("interrupt(): soft_int && (gate.dpl < CPL)")); exception(BX_GP_EXCEPTION, vector*8 + 2); } // Gate must be present, else #NP(vector * 8 + 2 + EXT) if (! IS_PRESENT(gate_descriptor)) { BX_ERROR(("interrupt(): gate not present")); exception(BX_NP_EXCEPTION, vector*8 + 2); } switch (gate_descriptor.type) { case BX_TASK_GATE: // examine selector to TSS, given in task gate descriptor raw_tss_selector = gate_descriptor.u.taskgate.tss_selector; parse_selector(raw_tss_selector, &tss_selector); // must specify global in the local/global bit, // else #GP(TSS selector) if (tss_selector.ti) { BX_ERROR(("interrupt(): tss_selector.ti=1 from gate descriptor - #GP(tss_selector)")); exception(BX_GP_EXCEPTION, raw_tss_selector & 0xfffc); } // index must be within GDT limits, else #TS(TSS selector) fetch_raw_descriptor(&tss_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &tss_descriptor); // AR byte must specify available TSS, // else #GP(TSS selector) if (tss_descriptor.valid==0 || tss_descriptor.segment) { BX_ERROR(("interrupt(): TSS selector points to invalid or bad TSS - #GP(tss_selector)")); exception(BX_GP_EXCEPTION, raw_tss_selector & 0xfffc); } if (tss_descriptor.type!=BX_SYS_SEGMENT_AVAIL_286_TSS && tss_descriptor.type!=BX_SYS_SEGMENT_AVAIL_386_TSS) { BX_ERROR(("interrupt(): TSS selector points to bad TSS - #GP(tss_selector)")); exception(BX_GP_EXCEPTION, raw_tss_selector & 0xfffc); } // TSS must be present, else #NP(TSS selector) if (! IS_PRESENT(tss_descriptor)) { BX_ERROR(("interrupt(): TSS descriptor.p == 0")); exception(BX_NP_EXCEPTION, raw_tss_selector & 0xfffc); } // switch tasks with nesting to TSS task_switch(0, &tss_selector, &tss_descriptor, BX_TASK_FROM_INT, dword1, dword2, push_error, error_code); return; case BX_286_INTERRUPT_GATE: case BX_286_TRAP_GATE: case BX_386_INTERRUPT_GATE: case BX_386_TRAP_GATE: gate_dest_selector = gate_descriptor.u.gate.dest_selector; gate_dest_offset = gate_descriptor.u.gate.dest_offset; // examine CS selector and descriptor given in gate descriptor // selector must be non-null else #GP(EXT) if ((gate_dest_selector & 0xfffc) == 0) { BX_ERROR(("int_trap_gate(): selector null")); exception(BX_GP_EXCEPTION, 0); } parse_selector(gate_dest_selector, &cs_selector); // selector must be within its descriptor table limits // else #GP(selector+EXT) fetch_raw_descriptor(&cs_selector, &dword1, &dword2, BX_GP_EXCEPTION); parse_descriptor(dword1, dword2, &cs_descriptor); // descriptor AR byte must indicate code seg // and code segment descriptor DPL<=CPL, else #GP(selector+EXT) if (cs_descriptor.valid==0 || cs_descriptor.segment==0 || IS_DATA_SEGMENT(cs_descriptor.type) || cs_descriptor.dpl > CPL) { BX_ERROR(("interrupt(): not accessible or not code segment cs=0x%04x", cs_selector.value)); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); } // segment must be present, else #NP(selector + EXT) if (! IS_PRESENT(cs_descriptor)) { BX_ERROR(("interrupt(): segment not present")); exception(BX_NP_EXCEPTION, cs_selector.value & 0xfffc); } // if code segment is non-conforming and DPL < CPL then // INTERRUPT TO INNER PRIVILEGE if(IS_CODE_SEGMENT_NON_CONFORMING(cs_descriptor.type) && cs_descriptor.dpl < CPL) { Bit16u old_SS, old_CS, SS_for_cpl_x; Bit32u ESP_for_cpl_x, old_EIP, old_ESP; bx_descriptor_t ss_descriptor; bx_selector_t ss_selector; int is_v8086_mode = v8086_mode(); BX_DEBUG(("interrupt(): INTERRUPT TO INNER PRIVILEGE")); // check selector and descriptor for new stack in current TSS get_SS_ESP_from_TSS(cs_descriptor.dpl, &SS_for_cpl_x, &ESP_for_cpl_x); if (is_v8086_mode && cs_descriptor.dpl != 0) { // if code segment DPL != 0 then #GP(new code segment selector) BX_ERROR(("interrupt(): code segment DPL(%d) != 0 in v8086 mode", cs_descriptor.dpl)); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); } // Selector must be non-null else #TS(EXT) if ((SS_for_cpl_x & 0xfffc) == 0) { BX_ERROR(("interrupt(): SS selector null")); exception(BX_TS_EXCEPTION, 0); /* TS(ext) */ } // selector index must be within its descriptor table limits // else #TS(SS selector + EXT) parse_selector(SS_for_cpl_x, &ss_selector); // fetch 2 dwords of descriptor; call handles out of limits checks fetch_raw_descriptor(&ss_selector, &dword1, &dword2, BX_TS_EXCEPTION); parse_descriptor(dword1, dword2, &ss_descriptor); // selector rpl must = dpl of code segment, // else #TS(SS selector + ext) if (ss_selector.rpl != cs_descriptor.dpl) { BX_ERROR(("interrupt(): SS.rpl != CS.dpl")); exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // stack seg DPL must = DPL of code segment, // else #TS(SS selector + ext) if (ss_descriptor.dpl != cs_descriptor.dpl) { BX_ERROR(("interrupt(): SS.dpl != CS.dpl")); exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // descriptor must indicate writable data segment, // else #TS(SS selector + EXT) if (ss_descriptor.valid==0 || ss_descriptor.segment==0 || IS_CODE_SEGMENT(ss_descriptor.type) || !IS_DATA_SEGMENT_WRITEABLE(ss_descriptor.type)) { BX_ERROR(("interrupt(): SS is not writable data segment")); exception(BX_TS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // seg must be present, else #SS(SS selector + ext) if (! IS_PRESENT(ss_descriptor)) { BX_ERROR(("interrupt(): SS not present")); exception(BX_SS_EXCEPTION, SS_for_cpl_x & 0xfffc); } // IP must be within CS segment boundaries, else #GP(0) if (gate_dest_offset > cs_descriptor.u.segment.limit_scaled) { BX_ERROR(("interrupt(): gate EIP > CS.limit")); exception(BX_GP_EXCEPTION, 0); } old_ESP = ESP; old_SS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].selector.value; old_EIP = EIP; old_CS = BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value; // Prepare new stack segment bx_segment_reg_t new_stack; new_stack.selector = ss_selector; new_stack.cache = ss_descriptor; new_stack.selector.rpl = cs_descriptor.dpl; // add cpl to the selector value new_stack.selector.value = (0xfffc & new_stack.selector.value) | new_stack.selector.rpl; if (ss_descriptor.u.segment.d_b) { Bit32u temp_ESP = ESP_for_cpl_x; if (is_v8086_mode) { if (gate_descriptor.type>=14) { // 386 int/trap gate write_new_stack_dword_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value); write_new_stack_dword_32(&new_stack, temp_ESP-8, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value); write_new_stack_dword_32(&new_stack, temp_ESP-12, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value); write_new_stack_dword_32(&new_stack, temp_ESP-16, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value); temp_ESP -= 16; } else { write_new_stack_word_32(&new_stack, temp_ESP-2, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value); write_new_stack_word_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value); write_new_stack_word_32(&new_stack, temp_ESP-6, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value); write_new_stack_word_32(&new_stack, temp_ESP-8, cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value); temp_ESP -= 8; } } if (gate_descriptor.type>=14) { // 386 int/trap gate // push long pointer to old stack onto new stack write_new_stack_dword_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, old_SS); write_new_stack_dword_32(&new_stack, temp_ESP-8, cs_descriptor.dpl, old_ESP); write_new_stack_dword_32(&new_stack, temp_ESP-12, cs_descriptor.dpl, read_eflags()); write_new_stack_dword_32(&new_stack, temp_ESP-16, cs_descriptor.dpl, old_CS); write_new_stack_dword_32(&new_stack, temp_ESP-20, cs_descriptor.dpl, old_EIP); temp_ESP -= 20; if (push_error) { temp_ESP -= 4; write_new_stack_dword_32(&new_stack, temp_ESP, cs_descriptor.dpl, error_code); } } else { // 286 int/trap gate // push long pointer to old stack onto new stack write_new_stack_word_32(&new_stack, temp_ESP-2, cs_descriptor.dpl, old_SS); write_new_stack_word_32(&new_stack, temp_ESP-4, cs_descriptor.dpl, (Bit16u) old_ESP); write_new_stack_word_32(&new_stack, temp_ESP-6, cs_descriptor.dpl, (Bit16u) read_eflags()); write_new_stack_word_32(&new_stack, temp_ESP-8, cs_descriptor.dpl, old_CS); write_new_stack_word_32(&new_stack, temp_ESP-10, cs_descriptor.dpl, (Bit16u) old_EIP); temp_ESP -= 10; if (push_error) { temp_ESP -= 2; write_new_stack_word_32(&new_stack, temp_ESP, cs_descriptor.dpl, error_code); } } ESP = temp_ESP; } else { Bit16u temp_SP = (Bit16u) ESP_for_cpl_x; if (is_v8086_mode) { if (gate_descriptor.type>=14) { // 386 int/trap gate write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-8), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-12), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-16), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value); temp_SP -= 16; } else { write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-2), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-6), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-8), cs_descriptor.dpl, BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value); temp_SP -= 8; } } if (gate_descriptor.type>=14) { // 386 int/trap gate // push long pointer to old stack onto new stack write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, old_SS); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-8), cs_descriptor.dpl, old_ESP); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-12), cs_descriptor.dpl, read_eflags()); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-16), cs_descriptor.dpl, old_CS); write_new_stack_dword_32(&new_stack, (Bit16u)(temp_SP-20), cs_descriptor.dpl, old_EIP); temp_SP -= 20; if (push_error) { temp_SP -= 4; write_new_stack_dword_32(&new_stack, temp_SP, cs_descriptor.dpl, error_code); } } else { // 286 int/trap gate // push long pointer to old stack onto new stack write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-2), cs_descriptor.dpl, old_SS); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-4), cs_descriptor.dpl, (Bit16u) old_ESP); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-6), cs_descriptor.dpl, (Bit16u) read_eflags()); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-8), cs_descriptor.dpl, old_CS); write_new_stack_word_32(&new_stack, (Bit16u)(temp_SP-10), cs_descriptor.dpl, (Bit16u) old_EIP); temp_SP -= 10; if (push_error) { temp_SP -= 2; write_new_stack_word_32(&new_stack, temp_SP, cs_descriptor.dpl, error_code); } } SP = temp_SP; } // load new CS:eIP values from gate // set CPL to new code segment DPL // set RPL of CS to CPL load_cs(&cs_selector, &cs_descriptor, cs_descriptor.dpl); // load new SS:eSP values from TSS load_ss(&ss_selector, &ss_descriptor, cs_descriptor.dpl); if (is_v8086_mode) { BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS].selector.value = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS].selector.value = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS].selector.value = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].cache.valid = 0; BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES].selector.value = 0; } } else { BX_DEBUG(("interrupt(): INTERRUPT TO SAME PRIVILEGE")); if (v8086_mode() && (IS_CODE_SEGMENT_CONFORMING(cs_descriptor.type) || cs_descriptor.dpl != 0)) { // if code segment DPL != 0 then #GP(new code segment selector) BX_ERROR(("interrupt(): code segment conforming or DPL(%d) != 0 in v8086 mode", cs_descriptor.dpl)); exception(BX_GP_EXCEPTION, cs_selector.value & 0xfffc); } // EIP must be in CS limit else #GP(0) if (gate_dest_offset > cs_descriptor.u.segment.limit_scaled) { BX_ERROR(("interrupt(): IP > CS descriptor limit")); exception(BX_GP_EXCEPTION, 0); } // push flags onto stack // push current CS selector onto stack // push return offset onto stack if (gate_descriptor.type >= 14) { // 386 gate push_32(read_eflags()); push_32(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_32(EIP); if (push_error) push_32(error_code); } else { // 286 gate push_16((Bit16u) read_eflags()); push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_16(IP); if (push_error) push_16(error_code); } // load CS:IP from gate // load CS descriptor // set the RPL field of CS to CPL load_cs(&cs_selector, &cs_descriptor, CPL); } EIP = gate_dest_offset; // if interrupt gate then set IF to 0 if (!(gate_descriptor.type & 1)) // even is int-gate BX_CPU_THIS_PTR clear_IF(); BX_CPU_THIS_PTR clear_TF(); BX_CPU_THIS_PTR clear_NT(); BX_CPU_THIS_PTR clear_VM(); BX_CPU_THIS_PTR clear_RF(); return; default: BX_PANIC(("bad descriptor type in interrupt()!")); break; } } void BX_CPU_C::real_mode_int(Bit8u vector, bx_bool push_error, Bit16u error_code) { if ((vector*4+3) > BX_CPU_THIS_PTR idtr.limit) { BX_ERROR(("interrupt(real mode) vector > idtr.limit")); exception(BX_GP_EXCEPTION, 0); } push_16((Bit16u) read_eflags()); push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_16(IP); Bit16u new_ip = system_read_word(BX_CPU_THIS_PTR idtr.base + 4 * vector); // CS.LIMIT can't change when in real/v8086 mode if (new_ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("interrupt(real mode): instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } Bit16u cs_selector = system_read_word(BX_CPU_THIS_PTR idtr.base + 4 * vector + 2); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_selector); EIP = new_ip; /* INT affects the following flags: I,T */ BX_CPU_THIS_PTR clear_IF(); BX_CPU_THIS_PTR clear_TF(); #if BX_CPU_LEVEL >= 4 BX_CPU_THIS_PTR clear_AC(); #endif BX_CPU_THIS_PTR clear_RF(); } void BX_CPU_C::interrupt(Bit8u vector, unsigned type, bx_bool push_error, Bit16u error_code) { #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_intsig; #if BX_DEBUG_LINUX if (bx_dbg.linux_syscall) { if (vector == 0x80) bx_dbg_linux_syscall(BX_CPU_ID); } #endif bx_dbg_interrupt(BX_CPU_ID, vector, error_code); #endif BX_INSTR_INTERRUPT(BX_CPU_ID, vector); invalidate_prefetch_q(); bx_bool soft_int = 0; switch(type) { case BX_SOFTWARE_INTERRUPT: case BX_SOFTWARE_EXCEPTION: soft_int = 1; break; case BX_PRIVILEGED_SOFTWARE_INTERRUPT: case BX_EXTERNAL_INTERRUPT: case BX_NMI: case BX_HARDWARE_EXCEPTION: break; default: BX_PANIC(("interrupt(): unknown exception type %d", type)); } BX_DEBUG(("interrupt(): vector = %02x, TYPE = %u, EXT = %u", vector, type, (unsigned) BX_CPU_THIS_PTR EXT)); // Discard any traps and inhibits for new context; traps will // resume upon return. BX_CPU_THIS_PTR debug_trap = 0; BX_CPU_THIS_PTR inhibit_mask = 0; #if BX_SUPPORT_VMX || BX_SUPPORT_SVM BX_CPU_THIS_PTR in_event = 1; #endif #if BX_SUPPORT_X86_64 if (long_mode()) { long_mode_int(vector, soft_int, push_error, error_code); } else #endif { RSP_SPECULATIVE; // software interrupt can be redirefcted in v8086 mode if (type != BX_SOFTWARE_INTERRUPT || !v8086_mode() || !v86_redirect_interrupt(vector)) { if(real_mode()) { real_mode_int(vector, push_error, error_code); } else { protected_mode_int(vector, soft_int, push_error, error_code); } } RSP_COMMIT; } #if BX_X86_DEBUGGER BX_CPU_THIS_PTR in_repeat = 0; #endif #if BX_SUPPORT_VMX || BX_SUPPORT_SVM BX_CPU_THIS_PTR in_event = 0; #endif } /* Exception classes. These are used as indexes into the 'is_exception_OK' * array below, and are stored in the 'exception' array also */ #define BX_ET_BENIGN 0 #define BX_ET_CONTRIBUTORY 1 #define BX_ET_PAGE_FAULT 2 #define BX_ET_DOUBLE_FAULT 10 static const bx_bool is_exception_OK[3][3] = { { 1, 1, 1 }, /* 1st exception is BENIGN */ { 1, 0, 1 }, /* 1st exception is CONTRIBUTORY */ { 1, 0, 0 } /* 1st exception is PAGE_FAULT */ }; #define BX_EXCEPTION_CLASS_TRAP 0 #define BX_EXCEPTION_CLASS_FAULT 1 #define BX_EXCEPTION_CLASS_ABORT 2 struct BxExceptionInfo exceptions_info[BX_CPU_HANDLED_EXCEPTIONS] = { /* DE */ { BX_ET_CONTRIBUTORY, BX_EXCEPTION_CLASS_FAULT, 0 }, /* DB */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 02 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, // NMI /* BP */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_TRAP, 0 }, /* OF */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_TRAP, 0 }, /* BR */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* UD */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* NM */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* DF */ { BX_ET_DOUBLE_FAULT, BX_EXCEPTION_CLASS_FAULT, 1 }, // coprocessor segment overrun (286,386 only) /* 09 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* TS */ { BX_ET_CONTRIBUTORY, BX_EXCEPTION_CLASS_FAULT, 1 }, /* NP */ { BX_ET_CONTRIBUTORY, BX_EXCEPTION_CLASS_FAULT, 1 }, /* SS */ { BX_ET_CONTRIBUTORY, BX_EXCEPTION_CLASS_FAULT, 1 }, /* GP */ { BX_ET_CONTRIBUTORY, BX_EXCEPTION_CLASS_FAULT, 1 }, /* PF */ { BX_ET_PAGE_FAULT, BX_EXCEPTION_CLASS_FAULT, 1 }, /* 15 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, // reserved /* MF */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* AC */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 1 }, /* MC */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_ABORT, 0 }, /* XM */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 20 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 21 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 22 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 23 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 24 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 25 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 26 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 27 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 28 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 29 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, /* 30 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 }, // FIXME: SVM #SF /* 31 */ { BX_ET_BENIGN, BX_EXCEPTION_CLASS_FAULT, 0 } }; // vector: 0..255: vector in IDT // error_code: if exception generates and error, push this error code // trap: override exception class to TRAP void BX_CPU_C::exception(unsigned vector, Bit16u error_code) { BX_INSTR_EXCEPTION(BX_CPU_ID, vector, error_code); #if BX_DEBUGGER bx_dbg_exception(BX_CPU_ID, vector, error_code); #endif BX_DEBUG(("exception(0x%02x): error_code=%04x", vector, error_code)); unsigned exception_type = 0; unsigned exception_class = BX_EXCEPTION_CLASS_FAULT; bx_bool push_error = 0; if (vector < BX_CPU_HANDLED_EXCEPTIONS) { push_error = exceptions_info[vector].push_error; exception_class = exceptions_info[vector].exception_class; exception_type = exceptions_info[vector].exception_type; } else { BX_PANIC(("exception(%u): bad vector", vector)); } if (vector != BX_PF_EXCEPTION && vector != BX_DF_EXCEPTION) { // Page faults have different format error_code = (error_code & 0xfffe) | BX_CPU_THIS_PTR EXT; } #if BX_SUPPORT_VMX VMexit_Event(BX_HARDWARE_EXCEPTION, vector, error_code, push_error); #endif #if BX_SUPPORT_SVM SvmInterceptException(BX_HARDWARE_EXCEPTION, vector, error_code, push_error); #endif if (BX_CPU_THIS_PTR errorno > 0) { if (BX_CPU_THIS_PTR errorno > 2 || BX_CPU_THIS_PTR curr_exception == BX_ET_DOUBLE_FAULT) { // restore RIP/RSP to value before error occurred RIP = BX_CPU_THIS_PTR prev_rip; if (BX_CPU_THIS_PTR speculative_rsp) RSP = BX_CPU_THIS_PTR prev_rsp; debug(BX_CPU_THIS_PTR prev_rip); // print debug information to the log #if BX_SUPPORT_VMX VMexit_TripleFault(); #endif #if BX_DEBUGGER // trap into debugger (similar as done when PANIC occured) bx_debug_break(); #endif if (SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get()) { BX_ERROR(("exception(): 3rd (%d) exception with no resolution, shutdown status is %02xh, resetting", vector, DEV_cmos_get_reg(0x0f))); bx_pc_system.Reset(BX_RESET_HARDWARE); } else { BX_PANIC(("exception(): 3rd (%d) exception with no resolution", vector)); BX_ERROR(("WARNING: Any simulation after this point is completely bogus !")); shutdown(); } longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop } } // note: fault-class exceptions _except_ #DB set RF in // eflags image. if (exception_class == BX_EXCEPTION_CLASS_FAULT) { // restore RIP/RSP to value before error occurred RIP = BX_CPU_THIS_PTR prev_rip; if (BX_CPU_THIS_PTR speculative_rsp) RSP = BX_CPU_THIS_PTR prev_rsp; if (vector != BX_DB_EXCEPTION) BX_CPU_THIS_PTR assert_RF(); } if (vector == BX_DB_EXCEPTION) { // Commit debug events to DR6: preserve DR5.BS and DR6.BD values, // only software can clear them BX_CPU_THIS_PTR dr6.val32 = (BX_CPU_THIS_PTR dr6.val32 & 0xffff6ff0) | (BX_CPU_THIS_PTR debug_trap & 0x0000e00f); // clear GD flag in the DR7 prior entering debug exception handler BX_CPU_THIS_PTR dr7.set_GD(0); } BX_CPU_THIS_PTR EXT = 1; /* if we've already had 1st exception, see if 2nd causes a * Double Fault instead. Otherwise, just record 1st exception */ if (BX_CPU_THIS_PTR errorno > 0 && exception_type != BX_ET_DOUBLE_FAULT) { if (! is_exception_OK[BX_CPU_THIS_PTR curr_exception][exception_type]) { exception(BX_DF_EXCEPTION, 0); } } BX_CPU_THIS_PTR curr_exception = exception_type; BX_CPU_THIS_PTR errorno++; if (real_mode()) { push_error = 0; // not INT, no error code pushed error_code = 0; } interrupt(vector, BX_HARDWARE_EXCEPTION, push_error, error_code); BX_CPU_THIS_PTR errorno = 0; // error resolved longjmp(BX_CPU_THIS_PTR jmp_buf_env, 1); // go back to main decode loop } bochs-2.6/cpu/fetchdecode64.cc0000644000175000017500000032136012020641453016044 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: fetchdecode64.cc 11356 2012-08-21 19:58:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_X86_64 /////////////////////////// // prefix bytes // opcode bytes // modrm/sib // address displacement // immediate constant /////////////////////////// // The table for 64-bit is slightly different from the // table for 32-bit due to undefined opcodes, which // were valid in 32-bit mode #define X 0 /* undefined opcode */ static const Bit8u BxOpcodeHasModrm64[512] = { /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /* ------------------------------- */ /* 00 */ 1,1,1,1,0,0,X,X,1,1,1,1,0,0,X,X, /* 10 */ 1,1,1,1,0,0,X,X,1,1,1,1,0,0,X,X, /* 20 */ 1,1,1,1,0,0,X,X,1,1,1,1,0,0,X,X, /* 30 */ 1,1,1,1,0,0,X,X,1,1,1,1,0,0,X,X, /* 40 */ X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, /* 50 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 60 */ X,X,X,1,X,X,X,X,0,1,0,1,0,0,0,0, /* 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 80 */ 1,1,X,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 90 */ 0,0,0,0,0,0,0,0,0,0,X,0,0,0,0,0, /* A0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* B0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* C0 */ 1,1,0,0,X,X,1,1,0,0,0,0,0,0,X,0, /* D0 */ 1,1,1,1,X,X,X,0,1,1,1,1,1,1,1,1, /* E0 */ 0,0,0,0,0,0,0,0,0,0,X,0,0,0,0,0, /* F0 */ X,0,X,X,0,0,1,1,0,0,0,0,0,0,1,1, /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ /* ------------------------------- */ 1,1,1,1,X,0,0,0,0,0,X,0,X,1,0,1, /* 0F 00 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 10 */ 1,1,1,1,X,X,X,X,1,1,1,1,1,1,1,1, /* 0F 20 */ 0,0,0,0,X,X,X,X,1,X,1,X,X,X,X,X, /* 0F 30 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 40 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 50 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 60 */ 1,1,1,1,1,1,1,0,1,1,X,X,1,1,1,1, /* 0F 70 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0F 80 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F 90 */ 0,0,0,1,1,1,X,X,0,0,0,1,1,1,1,1, /* 0F A0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F B0 */ 1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0, /* 0F C0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F D0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0F E0 */ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,X /* 0F F0 */ /* ------------------------------- */ /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ }; #undef X // Segment override prefixes // ------------------------- // In 64-bit mode the CS, DS, ES, and SS segment overrides are ignored. // decoding instructions; accessing seg reg's by index static unsigned sreg_mod0_base32[16] = { BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_SS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS }; static unsigned sreg_mod1or2_base32[16] = { BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_SS, BX_SEG_REG_SS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS, BX_SEG_REG_DS }; // common fetchdecode32/64 opcode tables #include "fetchdecode.h" // table of all Bochs opcodes extern struct bxIAOpcodeTable BxOpcodesTable[]; // 512 entries for 16bit operand size // 512 entries for 32bit operand size // 512 entries for 64bit operand size static const BxOpcodeInfo_t BxOpcodeInfo64[512*3] = { // 512 entries for 16bit mode /* 00 /w */ { BxLockable, BX_IA_ADD_EbGb }, /* 01 /w */ { BxLockable, BX_IA_ADD_EwGw }, /* 02 /w */ { 0, BX_IA_ADD_GbEb }, /* 03 /w */ { 0, BX_IA_ADD_GwEw }, /* 04 /w */ { BxImmediate_Ib, BX_IA_ADD_ALIb }, /* 05 /w */ { BxImmediate_Iw, BX_IA_ADD_AXIw }, /* 06 /w */ { 0, BX_IA_ERROR }, /* 07 /w */ { 0, BX_IA_ERROR }, /* 08 /w */ { BxLockable, BX_IA_OR_EbGb }, /* 09 /w */ { BxLockable, BX_IA_OR_EwGw }, /* 0A /w */ { 0, BX_IA_OR_GbEb }, /* 0B /w */ { 0, BX_IA_OR_GwEw }, /* 0C /w */ { BxImmediate_Ib, BX_IA_OR_ALIb }, /* 0D /w */ { BxImmediate_Iw, BX_IA_OR_AXIw }, /* 0E /w */ { 0, BX_IA_ERROR }, /* 0F /w */ { 0, BX_IA_ERROR }, // 2-byte escape /* 10 /w */ { BxLockable, BX_IA_ADC_EbGb }, /* 11 /w */ { BxLockable, BX_IA_ADC_EwGw }, /* 12 /w */ { 0, BX_IA_ADC_GbEb }, /* 13 /w */ { 0, BX_IA_ADC_GwEw }, /* 14 /w */ { BxImmediate_Ib, BX_IA_ADC_ALIb }, /* 15 /w */ { BxImmediate_Iw, BX_IA_ADC_AXIw }, /* 16 /w */ { 0, BX_IA_ERROR }, /* 17 /w */ { 0, BX_IA_ERROR }, /* 18 /w */ { BxLockable, BX_IA_SBB_EbGb }, /* 19 /w */ { BxLockable, BX_IA_SBB_EwGw }, /* 1A /w */ { 0, BX_IA_SBB_GbEb }, /* 1B /w */ { 0, BX_IA_SBB_GwEw }, /* 1C /w */ { BxImmediate_Ib, BX_IA_SBB_ALIb }, /* 1D /w */ { BxImmediate_Iw, BX_IA_SBB_AXIw }, /* 1E /w */ { 0, BX_IA_ERROR }, /* 1F /w */ { 0, BX_IA_ERROR }, /* 20 /w */ { BxLockable, BX_IA_AND_EbGb }, /* 21 /w */ { BxLockable, BX_IA_AND_EwGw }, /* 22 /w */ { 0, BX_IA_AND_GbEb }, /* 23 /w */ { 0, BX_IA_AND_GwEw }, /* 24 /w */ { BxImmediate_Ib, BX_IA_AND_ALIb }, /* 25 /w */ { BxImmediate_Iw, BX_IA_AND_AXIw }, /* 26 /w */ { 0, BX_IA_ERROR }, // ES: /* 27 /w */ { 0, BX_IA_ERROR }, /* 28 /w */ { BxLockable, BX_IA_SUB_EbGb }, /* 29 /w */ { BxLockable, BX_IA_SUB_EwGw }, /* 2A /w */ { 0, BX_IA_SUB_GbEb }, /* 2B /w */ { 0, BX_IA_SUB_GwEw }, /* 2C /w */ { BxImmediate_Ib, BX_IA_SUB_ALIb }, /* 2D /w */ { BxImmediate_Iw, BX_IA_SUB_AXIw }, /* 2E /w */ { 0, BX_IA_ERROR }, // CS: /* 2F /w */ { 0, BX_IA_ERROR }, /* 30 /w */ { BxLockable, BX_IA_XOR_EbGb }, /* 31 /w */ { BxLockable, BX_IA_XOR_EwGw }, /* 32 /w */ { 0, BX_IA_XOR_GbEb }, /* 33 /w */ { 0, BX_IA_XOR_GwEw }, /* 34 /w */ { BxImmediate_Ib, BX_IA_XOR_ALIb }, /* 35 /w */ { BxImmediate_Iw, BX_IA_XOR_AXIw }, /* 36 /w */ { 0, BX_IA_ERROR }, // SS: /* 37 /w */ { 0, BX_IA_ERROR }, /* 38 /w */ { 0, BX_IA_CMP_EbGb }, /* 39 /w */ { 0, BX_IA_CMP_EwGw }, /* 3A /w */ { 0, BX_IA_CMP_GbEb }, /* 3B /w */ { 0, BX_IA_CMP_GwEw }, /* 3C /w */ { BxImmediate_Ib, BX_IA_CMP_ALIb }, /* 3D /w */ { BxImmediate_Iw, BX_IA_CMP_AXIw }, /* 3E /w */ { 0, BX_IA_ERROR }, // DS: /* 3F /w */ { 0, BX_IA_ERROR }, /* 40 /w */ { 0, BX_IA_ERROR }, // REX: /* 41 /w */ { 0, BX_IA_ERROR }, // REX: /* 42 /w */ { 0, BX_IA_ERROR }, // REX: /* 43 /w */ { 0, BX_IA_ERROR }, // REX: /* 44 /w */ { 0, BX_IA_ERROR }, // REX: /* 45 /w */ { 0, BX_IA_ERROR }, // REX: /* 46 /w */ { 0, BX_IA_ERROR }, // REX: /* 47 /w */ { 0, BX_IA_ERROR }, // REX: /* 48 /w */ { 0, BX_IA_ERROR }, // REX: /* 49 /w */ { 0, BX_IA_ERROR }, // REX: /* 4A /w */ { 0, BX_IA_ERROR }, // REX: /* 4B /w */ { 0, BX_IA_ERROR }, // REX: /* 4C /w */ { 0, BX_IA_ERROR }, // REX: /* 4D /w */ { 0, BX_IA_ERROR }, // REX: /* 4E /w */ { 0, BX_IA_ERROR }, // REX: /* 4F /w */ { 0, BX_IA_ERROR }, // REX: /* 50 /w */ { 0, BX_IA_PUSH_RX }, /* 51 /w */ { 0, BX_IA_PUSH_RX }, /* 52 /w */ { 0, BX_IA_PUSH_RX }, /* 53 /w */ { 0, BX_IA_PUSH_RX }, /* 54 /w */ { 0, BX_IA_PUSH_RX }, /* 55 /w */ { 0, BX_IA_PUSH_RX }, /* 56 /w */ { 0, BX_IA_PUSH_RX }, /* 57 /w */ { 0, BX_IA_PUSH_RX }, /* 58 /w */ { 0, BX_IA_POP_RX }, /* 59 /w */ { 0, BX_IA_POP_RX }, /* 5A /w */ { 0, BX_IA_POP_RX }, /* 5B /w */ { 0, BX_IA_POP_RX }, /* 5C /w */ { 0, BX_IA_POP_RX }, /* 5D /w */ { 0, BX_IA_POP_RX }, /* 5E /w */ { 0, BX_IA_POP_RX }, /* 5F /w */ { 0, BX_IA_POP_RX }, /* 60 /w */ { 0, BX_IA_ERROR }, /* 61 /w */ { 0, BX_IA_ERROR }, /* 62 /w */ { 0, BX_IA_ERROR }, /* 63 /w */ { 0, BX_IA_MOV_GwEw }, // MOVSX_GwEw /* 64 /w */ { 0, BX_IA_ERROR }, // FS: /* 65 /w */ { 0, BX_IA_ERROR }, // GS: /* 66 /w */ { 0, BX_IA_ERROR }, // OS: /* 67 /w */ { 0, BX_IA_ERROR }, // AS: /* 68 /w */ { BxImmediate_Iw, BX_IA_PUSH_Iw }, /* 69 /w */ { BxImmediate_Iw, BX_IA_IMUL_GwEwIw }, /* 6A /w */ { BxImmediate_Ib_SE, BX_IA_PUSH_Iw }, /* 6B /w */ { BxImmediate_Ib_SE, BX_IA_IMUL_GwEwIw }, /* 6C /w */ { BxRepeatable, BX_IA_REP_INSB_YbDX }, /* 6D /w */ { BxRepeatable, BX_IA_REP_INSW_YwDX }, /* 6E /w */ { BxRepeatable, BX_IA_REP_OUTSB_DXXb }, /* 6F /w */ { BxRepeatable, BX_IA_REP_OUTSW_DXXw }, /* 70 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JO_Jq }, /* 71 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNO_Jq }, /* 72 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JB_Jq }, /* 73 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNB_Jq }, /* 74 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JZ_Jq }, /* 75 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNZ_Jq }, /* 76 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JBE_Jq }, /* 77 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNBE_Jq }, /* 78 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JS_Jq }, /* 79 /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNS_Jq }, /* 7A /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JP_Jq }, /* 7B /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNP_Jq }, /* 7C /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JL_Jq }, /* 7D /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNL_Jq }, /* 7E /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JLE_Jq }, /* 7F /w */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNLE_Jq }, /* 80 /w */ { BxGroup1 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG1EbIb }, /* 81 /w */ { BxGroup1 | BxImmediate_Iw, BX_IA_ERROR, BxOpcodeInfoG1Ew }, /* 82 /w */ { 0, BX_IA_ERROR }, /* 83 /w */ { BxGroup1 | BxImmediate_Ib_SE, BX_IA_ERROR, BxOpcodeInfoG1Ew }, /* 84 /w */ { 0, BX_IA_TEST_EbGb }, /* 85 /w */ { 0, BX_IA_TEST_EwGw }, /* 86 /w */ { BxLockable, BX_IA_XCHG_EbGb }, /* 87 /w */ { BxLockable, BX_IA_XCHG_EwGw }, /* 88 /w */ { 0, BX_IA_MOV_EbGb }, /* 89 /w */ { 0, BX_IA_MOV_EwGw }, /* 8A /w */ { 0, BX_IA_MOV_GbEb }, /* 8B /w */ { 0, BX_IA_MOV_GwEw }, /* 8C /w */ { 0, BX_IA_MOV_EwSw }, /* 8D /w */ { 0, BX_IA_LEA_GwM }, /* 8E /w */ { 0, BX_IA_MOV_SwEw }, /* 8F /w */ { BxGroup1A, BX_IA_ERROR, BxOpcodeInfoG1AEw }, /* 90 /w */ { 0, BX_IA_XCHG_RXAX }, // handles XCHG R8w, AX /* 91 /w */ { 0, BX_IA_XCHG_RXAX }, /* 92 /w */ { 0, BX_IA_XCHG_RXAX }, /* 93 /w */ { 0, BX_IA_XCHG_RXAX }, /* 94 /w */ { 0, BX_IA_XCHG_RXAX }, /* 95 /w */ { 0, BX_IA_XCHG_RXAX }, /* 96 /w */ { 0, BX_IA_XCHG_RXAX }, /* 97 /w */ { 0, BX_IA_XCHG_RXAX }, /* 98 /w */ { 0, BX_IA_CBW }, /* 99 /w */ { 0, BX_IA_CWD }, /* 9A /w */ { 0, BX_IA_ERROR }, /* 9B /w */ { 0, BX_IA_FWAIT }, /* 9C /w */ { 0, BX_IA_PUSHF_Fw }, /* 9D /w */ { BxTraceEnd, BX_IA_POPF_Fw }, /* 9E /w */ { 0, BX_IA_LM_SAHF }, /* 9F /w */ { 0, BX_IA_LM_LAHF }, /* A0 /w */ { BxImmediate_O, BX_IA_MOV_ALOq }, /* A1 /w */ { BxImmediate_O, BX_IA_MOV_AXOq }, /* A2 /w */ { BxImmediate_O, BX_IA_MOV_OqAL }, /* A3 /w */ { BxImmediate_O, BX_IA_MOV_OqAX }, /* A4 /w */ { BxRepeatable, BX_IA_REP_MOVSB_XbYb }, /* A5 /w */ { BxRepeatable, BX_IA_REP_MOVSW_XwYw }, /* A6 /w */ { BxRepeatable, BX_IA_REP_CMPSB_XbYb }, /* A7 /w */ { BxRepeatable, BX_IA_REP_CMPSW_XwYw }, /* A8 /w */ { BxImmediate_Ib, BX_IA_TEST_ALIb }, /* A9 /w */ { BxImmediate_Iw, BX_IA_TEST_AXIw }, /* AA /w */ { BxRepeatable, BX_IA_REP_STOSB_YbAL }, /* AB /w */ { BxRepeatable, BX_IA_REP_STOSW_YwAX }, /* AC /w */ { BxRepeatable, BX_IA_REP_LODSB_ALXb }, /* AD /w */ { BxRepeatable, BX_IA_REP_LODSW_AXXw }, /* AE /w */ { BxRepeatable, BX_IA_REP_SCASB_ALXb }, /* AF /w */ { BxRepeatable, BX_IA_REP_SCASW_AXXw }, /* B0 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B1 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B2 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B3 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B4 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B5 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B6 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B7 /w */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B8 /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* B9 /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BA /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BB /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BC /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BD /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BE /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* BF /w */ { BxImmediate_Iw, BX_IA_MOV_RXIw }, /* C0 /w */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* C1 /w */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EwIb }, /* C2 /w */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETnear64_Iw }, /* C3 /w */ { BxTraceEnd, BX_IA_RETnear64 }, /* C4 /w */ { BxPrefixVEX, BX_IA_ERROR }, /* C5 /w */ { BxPrefixVEX, BX_IA_ERROR }, /* C6 /w */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Eb }, /* C7 /w */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Ew }, /* C8 /w */ { BxImmediate_Iw | BxImmediate_Ib2, BX_IA_ENTER64_IwIb }, /* C9 /w */ { 0, BX_IA_LEAVE64 }, /* CA /w */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETfar16_Iw }, /* CB /w */ { BxTraceEnd, BX_IA_RETfar16 }, /* CC /w */ { BxTraceEnd, BX_IA_INT3 }, /* CD /w */ { BxImmediate_Ib | BxTraceEnd, BX_IA_INT_Ib }, /* CE /w */ { 0, BX_IA_ERROR }, /* CF /w */ { BxTraceEnd, BX_IA_IRET64 }, /* D0 /w */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* D1 /w */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EwIb }, /* D2 /w */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Eb }, /* D3 /w */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Ew }, /* D4 /w */ { 0, BX_IA_ERROR }, /* D5 /w */ { 0, BX_IA_ERROR }, /* D6 /w */ { 0, BX_IA_ERROR }, /* D7 /w */ { 0, BX_IA_XLAT }, /* D8 /w */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupD8 }, /* D9 /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointD9 }, /* DA /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDA }, /* DB /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDB }, /* DC /w */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDC }, /* DD /w */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDD }, /* DE /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDE }, /* DF /w */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDF }, /* E0 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPNE64_Jb }, /* E1 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPE64_Jb }, /* E2 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOP64_Jb }, /* E3 /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JRCXZ_Jb }, /* E4 /w */ { BxImmediate_Ib, BX_IA_IN_ALIb }, /* E5 /w */ { BxImmediate_Ib, BX_IA_IN_AXIb }, /* E6 /w */ { BxImmediate_Ib, BX_IA_OUT_IbAL }, /* E7 /w */ { BxImmediate_Ib, BX_IA_OUT_IbAX }, /* E8 /w */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_CALL_Jq }, /* E9 /w */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_JMP_Jq }, /* EA /w */ { 0, BX_IA_ERROR }, /* EB /w */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JMP_Jq }, /* EC /w */ { 0, BX_IA_IN_ALDX }, /* ED /w */ { 0, BX_IA_IN_AXDX }, /* EE /w */ { 0, BX_IA_OUT_DXAL }, /* EF /w */ { 0, BX_IA_OUT_DXAX }, /* F0 /w */ { 0, BX_IA_ERROR }, // LOCK /* F1 /w */ { BxTraceEnd, BX_IA_INT1 }, /* F2 /w */ { 0, BX_IA_ERROR }, // REPNE/REPNZ /* F3 /w */ { 0, BX_IA_ERROR }, // REP, REPE/REPZ /* F4 /w */ { BxTraceEnd, BX_IA_HLT }, /* F5 /w */ { 0, BX_IA_CMC }, /* F6 /w */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Eb }, /* F7 /w */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Ew }, /* F8 /w */ { 0, BX_IA_CLC }, /* F9 /w */ { 0, BX_IA_STC }, /* FA /w */ { 0, BX_IA_CLI }, /* FB /w */ { 0, BX_IA_STI }, /* FC /w */ { 0, BX_IA_CLD }, /* FD /w */ { 0, BX_IA_STD }, /* FE /w */ { BxGroup4, BX_IA_ERROR, BxOpcodeInfoG4 }, /* FF /w */ { BxGroup5, BX_IA_ERROR, BxOpcodeInfo64G5w }, /* 0F 00 /w */ { BxGroup6, BX_IA_ERROR, BxOpcodeInfoG6 }, /* 0F 01 /w */ { BxGroup7, BX_IA_ERROR, BxOpcodeInfoG7q }, /* 0F 02 /w */ { 0, BX_IA_LAR_GvEw }, /* 0F 03 /w */ { 0, BX_IA_LSL_GvEw }, /* 0F 04 /w */ { 0, BX_IA_ERROR }, /* 0F 05 /w */ { BxTraceEnd, BX_IA_SYSCALL }, /* 0F 06 /w */ { BxTraceEnd, BX_IA_CLTS }, /* 0F 07 /w */ { BxTraceEnd, BX_IA_SYSRET }, /* 0F 08 /w */ { BxTraceEnd, BX_IA_INVD }, /* 0F 09 /w */ { BxTraceEnd, BX_IA_WBINVD }, /* 0F 0A /w */ { 0, BX_IA_ERROR }, /* 0F 0B /w */ { BxTraceEnd, BX_IA_UD2A }, /* 0F 0C /w */ { 0, BX_IA_ERROR }, /* 0F 0D /w */ { 0, BX_IA_PREFETCHW }, // 3DNow! PREFETCHW on AMD, NOP on Intel /* 0F 0E /w */ { 0, BX_IA_FEMMS }, // 3DNow! FEMMS /* 0F 0F /w */ { BxImmediate_Ib, BX_IA_ERROR }, // 3DNow! Opcode Table /* 0F 10 /w */ { BxPrefixSSE, BX_IA_MOVUPS_VpsWps, BxOpcodeGroupSSE_0f10 }, /* 0F 11 /w */ { BxPrefixSSE, BX_IA_MOVUPS_WpsVps, BxOpcodeGroupSSE_0f11 }, /* 0F 12 /w */ { BxPrefixSSE, BX_IA_MOVLPS_VpsMq, BxOpcodeGroupSSE_0f12 }, /* 0F 13 /w */ { BxPrefixSSE, BX_IA_MOVLPS_MqVps, BxOpcodeGroupSSE_0f13M }, /* 0F 14 /w */ { BxPrefixSSE, BX_IA_UNPCKLPS_VpsWdq, BxOpcodeGroupSSE_0f14 }, /* 0F 15 /w */ { BxPrefixSSE, BX_IA_UNPCKHPS_VpsWdq, BxOpcodeGroupSSE_0f15 }, /* 0F 16 /w */ { BxPrefixSSE, BX_IA_MOVHPS_VpsMq, BxOpcodeGroupSSE_0f16 }, /* 0F 17 /w */ { BxPrefixSSE, BX_IA_MOVHPS_MqVps, BxOpcodeGroupSSE_0f17M }, /* 0F 18 /w */ { 0, BX_IA_PREFETCH }, // opcode group G16, PREFETCH hints /* 0F 19 /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1A /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1B /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1C /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1D /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1E /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1F /w */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 20 /w */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_RqCq }, /* 0F 21 /w */ { 0, BX_IA_MOV_RqDq }, /* 0F 22 /w */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_CqRq }, /* 0F 23 /w */ { BxTraceEnd, BX_IA_MOV_DqRq }, /* 0F 24 /w */ { 0, BX_IA_ERROR }, /* 0F 25 /w */ { 0, BX_IA_ERROR }, /* 0F 26 /w */ { 0, BX_IA_ERROR }, /* 0F 27 /w */ { 0, BX_IA_ERROR }, /* 0F 28 /w */ { BxPrefixSSE, BX_IA_MOVAPS_VpsWps, BxOpcodeGroupSSE_0f28 }, /* 0F 29 /w */ { BxPrefixSSE, BX_IA_MOVAPS_WpsVps, BxOpcodeGroupSSE_0f29 }, /* 0F 2A /w */ { BxPrefixSSE, BX_IA_CVTPI2PS_VpsQq, BxOpcodeGroupSSE_0f2a }, /* 0F 2B /w */ { BxPrefixSSE, BX_IA_MOVNTPS_MpsVps, BxOpcodeGroupSSE_0f2bM }, /* 0F 2C /w */ { BxPrefixSSE, BX_IA_CVTTPS2PI_PqWps, BxOpcodeGroupSSE_0f2c }, /* 0F 2D /w */ { BxPrefixSSE, BX_IA_CVTPS2PI_PqWps, BxOpcodeGroupSSE_0f2d }, /* 0F 2E /w */ { BxPrefixSSE, BX_IA_UCOMISS_VssWss, BxOpcodeGroupSSE_0f2e }, /* 0F 2F /w */ { BxPrefixSSE, BX_IA_COMISS_VpsWps, BxOpcodeGroupSSE_0f2f }, /* 0F 30 /w */ { 0, BX_IA_WRMSR }, /* 0F 31 /w */ { BxTraceEnd, BX_IA_RDTSC }, // end trace to avoid multiple TSC samples in one cycle /* 0F 32 /w */ { BxTraceEnd, BX_IA_RDMSR }, // end trace to avoid multiple TSC samples in one cycle /* 0F 33 /w */ { 0, BX_IA_RDPMC }, /* 0F 34 /w */ { BxTraceEnd, BX_IA_SYSENTER }, /* 0F 35 /w */ { BxTraceEnd, BX_IA_SYSEXIT }, /* 0F 36 /w */ { 0, BX_IA_ERROR }, /* 0F 37 /w */ { 0, BX_IA_GETSEC }, /* 0F 38 /w */ { Bx3ByteOp, BX_IA_ERROR, BxOpcode3ByteTable0f38 }, // 3-byte escape /* 0F 39 /w */ { 0, BX_IA_ERROR }, /* 0F 3A /w */ { Bx3ByteOp | BxImmediate_Ib, BX_IA_ERROR, BxOpcode3ByteTable0f3a }, // 3-byte escape /* 0F 3B /w */ { 0, BX_IA_ERROR }, /* 0F 3C /w */ { 0, BX_IA_ERROR }, /* 0F 3D /w */ { 0, BX_IA_ERROR }, /* 0F 3E /w */ { 0, BX_IA_ERROR }, /* 0F 3F /w */ { 0, BX_IA_ERROR }, /* 0F 40 /w */ { 0, BX_IA_CMOVO_GwEw }, /* 0F 41 /w */ { 0, BX_IA_CMOVNO_GwEw }, /* 0F 42 /w */ { 0, BX_IA_CMOVB_GwEw }, /* 0F 43 /w */ { 0, BX_IA_CMOVNB_GwEw }, /* 0F 44 /w */ { 0, BX_IA_CMOVZ_GwEw }, /* 0F 45 /w */ { 0, BX_IA_CMOVNZ_GwEw }, /* 0F 46 /w */ { 0, BX_IA_CMOVBE_GwEw }, /* 0F 47 /w */ { 0, BX_IA_CMOVNBE_GwEw }, /* 0F 48 /w */ { 0, BX_IA_CMOVS_GwEw }, /* 0F 49 /w */ { 0, BX_IA_CMOVNS_GwEw }, /* 0F 4A /w */ { 0, BX_IA_CMOVP_GwEw }, /* 0F 4B /w */ { 0, BX_IA_CMOVNP_GwEw }, /* 0F 4C /w */ { 0, BX_IA_CMOVL_GwEw }, /* 0F 4D /w */ { 0, BX_IA_CMOVNL_GwEw }, /* 0F 4E /w */ { 0, BX_IA_CMOVLE_GwEw }, /* 0F 4F /w */ { 0, BX_IA_CMOVNLE_GwEw }, /* 0F 50 /w */ { BxPrefixSSE, BX_IA_MOVMSKPS_GdVRps, BxOpcodeGroupSSE_0f50R }, /* 0F 51 /w */ { BxPrefixSSE, BX_IA_SQRTPS_VpsWps, BxOpcodeGroupSSE_0f51 }, /* 0F 52 /w */ { BxPrefixSSE, BX_IA_RSQRTPS_VpsWps, BxOpcodeGroupSSE_0f52 }, /* 0F 53 /w */ { BxPrefixSSE, BX_IA_RCPPS_VpsWps, BxOpcodeGroupSSE_0f53 }, /* 0F 54 /w */ { BxPrefixSSE, BX_IA_ANDPS_VpsWps, BxOpcodeGroupSSE_0f54 }, /* 0F 55 /w */ { BxPrefixSSE, BX_IA_ANDNPS_VpsWps, BxOpcodeGroupSSE_0f55 }, /* 0F 56 /w */ { BxPrefixSSE, BX_IA_ORPS_VpsWps, BxOpcodeGroupSSE_0f56 }, /* 0F 57 /w */ { BxPrefixSSE, BX_IA_XORPS_VpsWps, BxOpcodeGroupSSE_0f57 }, /* 0F 58 /w */ { BxPrefixSSE, BX_IA_ADDPS_VpsWps, BxOpcodeGroupSSE_0f58 }, /* 0F 59 /w */ { BxPrefixSSE, BX_IA_MULPS_VpsWps, BxOpcodeGroupSSE_0f59 }, /* 0F 5A /w */ { BxPrefixSSE, BX_IA_CVTPS2PD_VpdWps, BxOpcodeGroupSSE_0f5a }, /* 0F 5B /w */ { BxPrefixSSE, BX_IA_CVTDQ2PS_VpsWdq, BxOpcodeGroupSSE_0f5b }, /* 0F 5C /w */ { BxPrefixSSE, BX_IA_SUBPS_VpsWps, BxOpcodeGroupSSE_0f5c }, /* 0F 5D /w */ { BxPrefixSSE, BX_IA_MINPS_VpsWps, BxOpcodeGroupSSE_0f5d }, /* 0F 5E /w */ { BxPrefixSSE, BX_IA_DIVPS_VpsWps, BxOpcodeGroupSSE_0f5e }, /* 0F 5F /w */ { BxPrefixSSE, BX_IA_MAXPS_VpsWps, BxOpcodeGroupSSE_0f5f }, /* 0F 60 /w */ { BxPrefixSSE, BX_IA_PUNPCKLBW_PqQd, BxOpcodeGroupSSE_0f60 }, /* 0F 61 /w */ { BxPrefixSSE, BX_IA_PUNPCKLWD_PqQd, BxOpcodeGroupSSE_0f61 }, /* 0F 62 /w */ { BxPrefixSSE, BX_IA_PUNPCKLDQ_PqQd, BxOpcodeGroupSSE_0f62 }, /* 0F 63 /w */ { BxPrefixSSE, BX_IA_PACKSSWB_PqQq, BxOpcodeGroupSSE_0f63 }, /* 0F 64 /w */ { BxPrefixSSE, BX_IA_PCMPGTB_PqQq, BxOpcodeGroupSSE_0f64 }, /* 0F 65 /w */ { BxPrefixSSE, BX_IA_PCMPGTW_PqQq, BxOpcodeGroupSSE_0f65 }, /* 0F 66 /w */ { BxPrefixSSE, BX_IA_PCMPGTD_PqQq, BxOpcodeGroupSSE_0f66 }, /* 0F 67 /w */ { BxPrefixSSE, BX_IA_PACKUSWB_PqQq, BxOpcodeGroupSSE_0f67 }, /* 0F 68 /w */ { BxPrefixSSE, BX_IA_PUNPCKHBW_PqQq, BxOpcodeGroupSSE_0f68 }, /* 0F 69 /w */ { BxPrefixSSE, BX_IA_PUNPCKHWD_PqQq, BxOpcodeGroupSSE_0f69 }, /* 0F 6A /w */ { BxPrefixSSE, BX_IA_PUNPCKHDQ_PqQq, BxOpcodeGroupSSE_0f6a }, /* 0F 6B /w */ { BxPrefixSSE, BX_IA_PACKSSDW_PqQq, BxOpcodeGroupSSE_0f6b }, /* 0F 6C /w */ { BxPrefixSSE66, BX_IA_PUNPCKLQDQ_VdqWdq }, /* 0F 6D /w */ { BxPrefixSSE66, BX_IA_PUNPCKHQDQ_VdqWdq }, /* 0F 6E /w */ { BxPrefixSSE, BX_IA_MOVD_PqEd, BxOpcodeGroupSSE_0f6e }, /* 0F 6F /w */ { BxPrefixSSE, BX_IA_MOVQ_PqQq, BxOpcodeGroupSSE_0f6f }, /* 0F 70 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PSHUFW_PqQqIb, BxOpcodeGroupSSE_0f70 }, /* 0F 71 /w */ { BxGroup12, BX_IA_ERROR, BxOpcodeInfoG12R }, /* 0F 72 /w */ { BxGroup13, BX_IA_ERROR, BxOpcodeInfoG13R }, /* 0F 73 /w */ { BxGroup14, BX_IA_ERROR, BxOpcodeInfoG14R }, /* 0F 74 /w */ { BxPrefixSSE, BX_IA_PCMPEQB_PqQq, BxOpcodeGroupSSE_0f74 }, /* 0F 75 /w */ { BxPrefixSSE, BX_IA_PCMPEQW_PqQq, BxOpcodeGroupSSE_0f75 }, /* 0F 76 /w */ { BxPrefixSSE, BX_IA_PCMPEQD_PqQq, BxOpcodeGroupSSE_0f76 }, /* 0F 77 /w */ { BxPrefixSSE, BX_IA_EMMS, BxOpcodeGroupSSE_ERR }, /* 0F 78 /w */ { BxPrefixSSE, BX_IA_VMREAD_EqGq, BxOpcodeGroupSSE4A_0f78 }, /* 0F 79 /w */ { BxPrefixSSE, BX_IA_VMWRITE_GqEq, BxOpcodeGroupSSE4A_0f79 }, /* 0F 7A /w */ { 0, BX_IA_ERROR }, /* 0F 7B /w */ { 0, BX_IA_ERROR }, /* 0F 7C /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7c }, /* 0F 7D /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7d }, /* 0F 7E /w */ { BxPrefixSSE, BX_IA_MOVD_EdPd, BxOpcodeGroupSSE_0f7e }, /* 0F 7F /w */ { BxPrefixSSE, BX_IA_MOVQ_QqPq, BxOpcodeGroupSSE_0f7f }, /* 0F 80 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JO_Jq }, /* 0F 81 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNO_Jq }, /* 0F 82 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JB_Jq }, /* 0F 83 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNB_Jq }, /* 0F 84 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JZ_Jq }, /* 0F 85 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNZ_Jq }, /* 0F 86 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JBE_Jq }, /* 0F 87 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNBE_Jq }, /* 0F 88 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JS_Jq }, /* 0F 89 /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNS_Jq }, /* 0F 8A /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JP_Jq }, /* 0F 8B /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNP_Jq }, /* 0F 8C /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JL_Jq }, /* 0F 8D /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNL_Jq }, /* 0F 8E /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JLE_Jq }, /* 0F 8F /w */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNLE_Jq }, /* 0F 90 /w */ { 0, BX_IA_SETO_Eb }, /* 0F 91 /w */ { 0, BX_IA_SETNO_Eb }, /* 0F 92 /w */ { 0, BX_IA_SETB_Eb }, /* 0F 93 /w */ { 0, BX_IA_SETNB_Eb }, /* 0F 94 /w */ { 0, BX_IA_SETZ_Eb }, /* 0F 95 /w */ { 0, BX_IA_SETNZ_Eb }, /* 0F 96 /w */ { 0, BX_IA_SETBE_Eb }, /* 0F 97 /w */ { 0, BX_IA_SETNBE_Eb }, /* 0F 98 /w */ { 0, BX_IA_SETS_Eb }, /* 0F 99 /w */ { 0, BX_IA_SETNS_Eb }, /* 0F 9A /w */ { 0, BX_IA_SETP_Eb }, /* 0F 9B /w */ { 0, BX_IA_SETNP_Eb }, /* 0F 9C /w */ { 0, BX_IA_SETL_Eb }, /* 0F 9D /w */ { 0, BX_IA_SETNL_Eb }, /* 0F 9E /w */ { 0, BX_IA_SETLE_Eb }, /* 0F 9F /w */ { 0, BX_IA_SETNLE_Eb }, /* 0F A0 /w */ { 0, BX_IA_PUSH16_FS }, /* 0F A1 /w */ { 0, BX_IA_POP16_FS }, /* 0F A2 /w */ { 0, BX_IA_CPUID }, /* 0F A3 /w */ { 0, BX_IA_BT_EwGw }, /* 0F A4 /w */ { BxImmediate_Ib, BX_IA_SHLD_EwGwIb }, /* 0F A5 /w */ { 0, BX_IA_SHLD_EwGw }, /* 0F A6 /w */ { 0, BX_IA_ERROR }, /* 0F A7 /w */ { 0, BX_IA_ERROR }, /* 0F A8 /w */ { 0, BX_IA_PUSH16_GS }, /* 0F A9 /w */ { 0, BX_IA_POP16_GS }, /* 0F AA /w */ { BxTraceEnd, BX_IA_RSM }, /* 0F AB /w */ { BxLockable, BX_IA_BTS_EwGw }, /* 0F AC /w */ { BxImmediate_Ib, BX_IA_SHRD_EwGwIb }, /* 0F AD /w */ { 0, BX_IA_SHRD_EwGw }, /* 0F AE /w */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15q }, /* 0F AF /w */ { 0, BX_IA_IMUL_GwEw }, /* 0F B0 /w */ { BxLockable, BX_IA_CMPXCHG_EbGb }, /* 0F B1 /w */ { BxLockable, BX_IA_CMPXCHG_EwGw }, /* 0F B2 /w */ { 0, BX_IA_LSS_GwMp }, /* 0F B3 /w */ { BxLockable, BX_IA_BTR_EwGw }, /* 0F B4 /w */ { 0, BX_IA_LFS_GwMp }, /* 0F B5 /w */ { 0, BX_IA_LGS_GwMp }, /* 0F B6 /w */ { 0, BX_IA_MOVZX_GwEb }, /* 0F B7 /w */ { 0, BX_IA_MOV_GwEw }, // MOVZX_GwEw /* 0F B8 /w */ { BxPrefixSSEF3, BX_IA_POPCNT_GwEw }, /* 0F B9 /w */ { BxTraceEnd, BX_IA_UD2B }, /* 0F BA /w */ { BxGroup8, BX_IA_ERROR, BxOpcodeInfoG8EwIb }, /* 0F BB /w */ { BxLockable, BX_IA_BTC_EwGw }, /* 0F BC /w */ { BxPrefixSSE, BX_IA_BSF_GwEw, BxOpcodeGroupSSE_TZCNT16 }, /* 0F BD /w */ { BxPrefixSSE, BX_IA_BSR_GwEw, BxOpcodeGroupSSE_LZCNT16 }, /* 0F BE /w */ { 0, BX_IA_MOVSX_GwEb }, /* 0F BF /w */ { 0, BX_IA_MOV_GwEw }, // MOVSX_GwEw /* 0F C0 /w */ { BxLockable, BX_IA_XADD_EbGb }, /* 0F C1 /w */ { BxLockable, BX_IA_XADD_EwGw }, /* 0F C2 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_CMPPS_VpsWpsIb, BxOpcodeGroupSSE_0fc2 }, /* 0F C3 /w */ { BxPrefixSSE, BX_IA_MOVNTI64_MdGd, BxOpcodeGroupSSE_ERR }, /* 0F C4 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PINSRW_PqEwIb, BxOpcodeGroupSSE_0fc4 }, /* 0F C5 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PEXTRW_GdPqIb, BxOpcodeGroupSSE_0fc5R }, /* 0F C6 /w */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_SHUFPS_VpsWpsIb, BxOpcodeGroupSSE_0fc6 }, /* 0F C7 /w */ { BxGroup9, BX_IA_ERROR, BxOpcodeInfoG9M }, /* 0F C8 /w */ { 0, BX_IA_BSWAP_RX }, /* 0F C9 /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CA /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CB /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CC /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CD /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CE /w */ { 0, BX_IA_BSWAP_RX }, /* 0F CF /w */ { 0, BX_IA_BSWAP_RX }, /* 0F D0 /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd0 }, /* 0F D1 /w */ { BxPrefixSSE, BX_IA_PSRLW_PqQq, BxOpcodeGroupSSE_0fd1 }, /* 0F D2 /w */ { BxPrefixSSE, BX_IA_PSRLD_PqQq, BxOpcodeGroupSSE_0fd2 }, /* 0F D3 /w */ { BxPrefixSSE, BX_IA_PSRLQ_PqQq, BxOpcodeGroupSSE_0fd3 }, /* 0F D4 /w */ { BxPrefixSSE, BX_IA_PADDQ_PqQq, BxOpcodeGroupSSE_0fd4 }, /* 0F D5 /w */ { BxPrefixSSE, BX_IA_PMULLW_PqQq, BxOpcodeGroupSSE_0fd5 }, /* 0F D6 /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd6 }, /* 0F D7 /w */ { BxPrefixSSE, BX_IA_PMOVMSKB_GdPRq, BxOpcodeGroupSSE_0fd7R }, /* 0F D8 /w */ { BxPrefixSSE, BX_IA_PSUBUSB_PqQq, BxOpcodeGroupSSE_0fd8 }, /* 0F D9 /w */ { BxPrefixSSE, BX_IA_PSUBUSW_PqQq, BxOpcodeGroupSSE_0fd9 }, /* 0F DA /w */ { BxPrefixSSE, BX_IA_PMINUB_PqQq, BxOpcodeGroupSSE_0fda }, /* 0F DB /w */ { BxPrefixSSE, BX_IA_PAND_PqQq, BxOpcodeGroupSSE_0fdb }, /* 0F DC /w */ { BxPrefixSSE, BX_IA_PADDUSB_PqQq, BxOpcodeGroupSSE_0fdc }, /* 0F DD /w */ { BxPrefixSSE, BX_IA_PADDUSW_PqQq, BxOpcodeGroupSSE_0fdd }, /* 0F DE /w */ { BxPrefixSSE, BX_IA_PMAXUB_PqQq, BxOpcodeGroupSSE_0fde }, /* 0F DF /w */ { BxPrefixSSE, BX_IA_PANDN_PqQq, BxOpcodeGroupSSE_0fdf }, /* 0F E0 /w */ { BxPrefixSSE, BX_IA_PAVGB_PqQq, BxOpcodeGroupSSE_0fe0 }, /* 0F E1 /w */ { BxPrefixSSE, BX_IA_PSRAW_PqQq, BxOpcodeGroupSSE_0fe1 }, /* 0F E2 /w */ { BxPrefixSSE, BX_IA_PSRAD_PqQq, BxOpcodeGroupSSE_0fe2 }, /* 0F E3 /w */ { BxPrefixSSE, BX_IA_PAVGW_PqQq, BxOpcodeGroupSSE_0fe3 }, /* 0F E4 /w */ { BxPrefixSSE, BX_IA_PMULHUW_PqQq, BxOpcodeGroupSSE_0fe4 }, /* 0F E5 /w */ { BxPrefixSSE, BX_IA_PMULHW_PqQq, BxOpcodeGroupSSE_0fe5 }, /* 0F E6 /w */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fe6 }, /* 0F E7 /w */ { BxPrefixSSE, BX_IA_MOVNTQ_MqPq, BxOpcodeGroupSSE_0fe7M }, /* 0F E8 /w */ { BxPrefixSSE, BX_IA_PSUBSB_PqQq, BxOpcodeGroupSSE_0fe8 }, /* 0F E9 /w */ { BxPrefixSSE, BX_IA_PSUBSW_PqQq, BxOpcodeGroupSSE_0fe9 }, /* 0F EA /w */ { BxPrefixSSE, BX_IA_PMINSW_PqQq, BxOpcodeGroupSSE_0fea }, /* 0F EB /w */ { BxPrefixSSE, BX_IA_POR_PqQq, BxOpcodeGroupSSE_0feb }, /* 0F EC /w */ { BxPrefixSSE, BX_IA_PADDSB_PqQq, BxOpcodeGroupSSE_0fec }, /* 0F ED /w */ { BxPrefixSSE, BX_IA_PADDSW_PqQq, BxOpcodeGroupSSE_0fed }, /* 0F EE /w */ { BxPrefixSSE, BX_IA_PMAXSW_PqQq, BxOpcodeGroupSSE_0fee }, /* 0F EF /w */ { BxPrefixSSE, BX_IA_PXOR_PqQq, BxOpcodeGroupSSE_0fef }, /* 0F F0 /w */ { BxPrefixSSEF2, BX_IA_LDDQU_VdqMdq }, /* 0F F1 /w */ { BxPrefixSSE, BX_IA_PSLLW_PqQq, BxOpcodeGroupSSE_0ff1 }, /* 0F F2 /w */ { BxPrefixSSE, BX_IA_PSLLD_PqQq, BxOpcodeGroupSSE_0ff2 }, /* 0F F3 /w */ { BxPrefixSSE, BX_IA_PSLLQ_PqQq, BxOpcodeGroupSSE_0ff3 }, /* 0F F4 /w */ { BxPrefixSSE, BX_IA_PMULUDQ_PqQq, BxOpcodeGroupSSE_0ff4 }, /* 0F F5 /w */ { BxPrefixSSE, BX_IA_PMADDWD_PqQq, BxOpcodeGroupSSE_0ff5 }, /* 0F F6 /w */ { BxPrefixSSE, BX_IA_PSADBW_PqQq, BxOpcodeGroupSSE_0ff6 }, /* 0F F7 /w */ { BxPrefixSSE, BX_IA_MASKMOVQ_PqPRq, BxOpcodeGroupSSE_0ff7R }, /* 0F F8 /w */ { BxPrefixSSE, BX_IA_PSUBB_PqQq, BxOpcodeGroupSSE_0ff8 }, /* 0F F9 /w */ { BxPrefixSSE, BX_IA_PSUBW_PqQq, BxOpcodeGroupSSE_0ff9 }, /* 0F FA /w */ { BxPrefixSSE, BX_IA_PSUBD_PqQq, BxOpcodeGroupSSE_0ffa }, /* 0F FB /w */ { BxPrefixSSE, BX_IA_PSUBQ_PqQq, BxOpcodeGroupSSE_0ffb }, /* 0F FC /w */ { BxPrefixSSE, BX_IA_PADDB_PqQq, BxOpcodeGroupSSE_0ffc }, /* 0F FD /w */ { BxPrefixSSE, BX_IA_PADDW_PqQq, BxOpcodeGroupSSE_0ffd }, /* 0F FE /w */ { BxPrefixSSE, BX_IA_PADDD_PqQq, BxOpcodeGroupSSE_0ffe }, /* 0F FF /w */ { 0, BX_IA_ERROR }, // 512 entries for 32bit mode /* 00 /d */ { BxLockable, BX_IA_ADD_EbGb }, /* 01 /d */ { BxLockable, BX_IA_ADD_EdGd }, /* 02 /d */ { 0, BX_IA_ADD_GbEb }, /* 03 /d */ { 0, BX_IA_ADD_GdEd }, /* 04 /d */ { BxImmediate_Ib, BX_IA_ADD_ALIb }, /* 05 /d */ { BxImmediate_Id, BX_IA_ADD_EAXId }, /* 06 /d */ { 0, BX_IA_ERROR }, /* 07 /d */ { 0, BX_IA_ERROR }, /* 08 /d */ { BxLockable, BX_IA_OR_EbGb }, /* 09 /d */ { BxLockable, BX_IA_OR_EdGd }, /* 0A /d */ { 0, BX_IA_OR_GbEb }, /* 0B /d */ { 0, BX_IA_OR_GdEd }, /* 0C /d */ { BxImmediate_Ib, BX_IA_OR_ALIb }, /* 0D /d */ { BxImmediate_Id, BX_IA_OR_EAXId }, /* 0E /d */ { 0, BX_IA_ERROR }, /* 0F /d */ { 0, BX_IA_ERROR }, // 2-byte escape /* 10 /d */ { BxLockable, BX_IA_ADC_EbGb }, /* 11 /d */ { BxLockable, BX_IA_ADC_EdGd }, /* 12 /d */ { 0, BX_IA_ADC_GbEb }, /* 13 /d */ { 0, BX_IA_ADC_GdEd }, /* 14 /d */ { BxImmediate_Ib, BX_IA_ADC_ALIb }, /* 15 /d */ { BxImmediate_Id, BX_IA_ADC_EAXId }, /* 16 /d */ { 0, BX_IA_ERROR }, /* 17 /d */ { 0, BX_IA_ERROR }, /* 18 /d */ { BxLockable, BX_IA_SBB_EbGb }, /* 19 /d */ { BxLockable, BX_IA_SBB_EdGd }, /* 1A /d */ { 0, BX_IA_SBB_GbEb }, /* 1B /d */ { 0, BX_IA_SBB_GdEd }, /* 1C /d */ { BxImmediate_Ib, BX_IA_SBB_ALIb }, /* 1D /d */ { BxImmediate_Id, BX_IA_SBB_EAXId }, /* 1E /d */ { 0, BX_IA_ERROR }, /* 1F /d */ { 0, BX_IA_ERROR }, /* 20 /d */ { BxLockable, BX_IA_AND_EbGb }, /* 21 /d */ { BxLockable, BX_IA_AND_EdGd }, /* 22 /d */ { 0, BX_IA_AND_GbEb }, /* 23 /d */ { 0, BX_IA_AND_GdEd }, /* 24 /d */ { BxImmediate_Ib, BX_IA_AND_ALIb }, /* 25 /d */ { BxImmediate_Id, BX_IA_AND_EAXId }, /* 26 /d */ { 0, BX_IA_ERROR }, // ES: /* 27 /d */ { 0, BX_IA_ERROR }, /* 28 /d */ { BxLockable, BX_IA_SUB_EbGb }, /* 29 /d */ { BxLockable, BX_IA_SUB_EdGd }, /* 2A /d */ { 0, BX_IA_SUB_GbEb }, /* 2B /d */ { 0, BX_IA_SUB_GdEd }, /* 2C /d */ { BxImmediate_Ib, BX_IA_SUB_ALIb }, /* 2D /d */ { BxImmediate_Id, BX_IA_SUB_EAXId }, /* 2E /d */ { 0, BX_IA_ERROR }, // CS: /* 2F /d */ { 0, BX_IA_ERROR }, /* 30 /d */ { BxLockable, BX_IA_XOR_EbGb }, /* 31 /d */ { BxLockable, BX_IA_XOR_EdGd }, /* 32 /d */ { 0, BX_IA_XOR_GbEb }, /* 33 /d */ { 0, BX_IA_XOR_GdEd }, /* 34 /d */ { BxImmediate_Ib, BX_IA_XOR_ALIb }, /* 35 /d */ { BxImmediate_Id, BX_IA_XOR_EAXId }, /* 36 /d */ { 0, BX_IA_ERROR }, // SS: /* 37 /d */ { 0, BX_IA_ERROR }, /* 38 /d */ { 0, BX_IA_CMP_EbGb }, /* 39 /d */ { 0, BX_IA_CMP_EdGd }, /* 3A /d */ { 0, BX_IA_CMP_GbEb }, /* 3B /d */ { 0, BX_IA_CMP_GdEd }, /* 3C /d */ { BxImmediate_Ib, BX_IA_CMP_ALIb }, /* 3D /d */ { BxImmediate_Id, BX_IA_CMP_EAXId }, /* 3E /d */ { 0, BX_IA_ERROR }, // DS: /* 3F /d */ { 0, BX_IA_ERROR }, /* 40 /d */ { 0, BX_IA_ERROR }, // REX: /* 41 /d */ { 0, BX_IA_ERROR }, // REX: /* 42 /d */ { 0, BX_IA_ERROR }, // REX: /* 43 /d */ { 0, BX_IA_ERROR }, // REX: /* 44 /d */ { 0, BX_IA_ERROR }, // REX: /* 45 /d */ { 0, BX_IA_ERROR }, // REX: /* 46 /d */ { 0, BX_IA_ERROR }, // REX: /* 47 /d */ { 0, BX_IA_ERROR }, // REX: /* 48 /d */ { 0, BX_IA_ERROR }, // REX: /* 49 /d */ { 0, BX_IA_ERROR }, // REX: /* 4A /d */ { 0, BX_IA_ERROR }, // REX: /* 4B /d */ { 0, BX_IA_ERROR }, // REX: /* 4C /d */ { 0, BX_IA_ERROR }, // REX: /* 4D /d */ { 0, BX_IA_ERROR }, // REX: /* 4E /d */ { 0, BX_IA_ERROR }, // REX: /* 4F /d */ { 0, BX_IA_ERROR }, // REX: /* 50 /d */ { 0, BX_IA_PUSH_RRX }, /* 51 /d */ { 0, BX_IA_PUSH_RRX }, /* 52 /d */ { 0, BX_IA_PUSH_RRX }, /* 53 /d */ { 0, BX_IA_PUSH_RRX }, /* 54 /d */ { 0, BX_IA_PUSH_RRX }, /* 55 /d */ { 0, BX_IA_PUSH_RRX }, /* 56 /d */ { 0, BX_IA_PUSH_RRX }, /* 57 /d */ { 0, BX_IA_PUSH_RRX }, /* 58 /d */ { 0, BX_IA_POP_RRX }, /* 59 /d */ { 0, BX_IA_POP_RRX }, /* 5A /d */ { 0, BX_IA_POP_RRX }, /* 5B /d */ { 0, BX_IA_POP_RRX }, /* 5C /d */ { 0, BX_IA_POP_RRX }, /* 5D /d */ { 0, BX_IA_POP_RRX }, /* 5E /d */ { 0, BX_IA_POP_RRX }, /* 5F /d */ { 0, BX_IA_POP_RRX }, /* 60 /d */ { 0, BX_IA_ERROR }, /* 61 /d */ { 0, BX_IA_ERROR }, /* 62 /d */ { 0, BX_IA_ERROR }, /* 63 /d */ { 0, BX_IA_MOV64_GdEd }, // MOVSX_GdEd /* 64 /d */ { 0, BX_IA_ERROR }, // FS: /* 65 /d */ { 0, BX_IA_ERROR }, // GS: /* 66 /d */ { 0, BX_IA_ERROR }, // OS: /* 67 /d */ { 0, BX_IA_ERROR }, // AS: /* 68 /d */ { BxImmediate_Id, BX_IA_PUSH64_Id }, /* 69 /d */ { BxImmediate_Id, BX_IA_IMUL_GdEdId }, /* 6A /d */ { BxImmediate_Ib_SE, BX_IA_PUSH64_Id }, /* 6B /d */ { BxImmediate_Ib_SE, BX_IA_IMUL_GdEdId }, /* 6C /d */ { BxRepeatable, BX_IA_REP_INSB_YbDX }, /* 6D /d */ { BxRepeatable, BX_IA_REP_INSD_YdDX }, /* 6E /d */ { BxRepeatable, BX_IA_REP_OUTSB_DXXb }, /* 6F /d */ { BxRepeatable, BX_IA_REP_OUTSD_DXXd }, /* 70 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JO_Jq }, /* 71 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNO_Jq }, /* 72 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JB_Jq }, /* 73 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNB_Jq }, /* 74 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JZ_Jq }, /* 75 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNZ_Jq }, /* 76 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JBE_Jq }, /* 77 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNBE_Jq }, /* 78 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JS_Jq }, /* 79 /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNS_Jq }, /* 7A /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JP_Jq }, /* 7B /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNP_Jq }, /* 7C /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JL_Jq }, /* 7D /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNL_Jq }, /* 7E /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JLE_Jq }, /* 7F /d */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNLE_Jq }, /* 80 /d */ { BxGroup1 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG1EbIb }, /* 81 /d */ { BxGroup1 | BxImmediate_Id, BX_IA_ERROR, BxOpcodeInfoG1Ed }, /* 82 /d */ { 0, BX_IA_ERROR }, /* 83 /d */ { BxGroup1 | BxImmediate_Ib_SE, BX_IA_ERROR, BxOpcodeInfoG1Ed }, /* 84 /d */ { 0, BX_IA_TEST_EbGb }, /* 85 /d */ { 0, BX_IA_TEST_EdGd }, /* 86 /d */ { BxLockable, BX_IA_XCHG_EbGb }, /* 87 /d */ { BxLockable, BX_IA_XCHG_EdGd }, /* 88 /d */ { 0, BX_IA_MOV_EbGb }, /* 89 /d */ { 0, BX_IA_MOV64_EdGd }, /* 8A /d */ { 0, BX_IA_MOV_GbEb }, /* 8B /d */ { 0, BX_IA_MOV64_GdEd }, /* 8C /d */ { 0, BX_IA_MOV_EwSw }, /* 8D /d */ { 0, BX_IA_LEA_GdM }, /* 8E /d */ { 0, BX_IA_MOV_SwEw }, /* 8F /d */ { BxGroup1A, BX_IA_ERROR, BxOpcodeInfo64G1AEq }, /* 90 /d */ { 0, BX_IA_XCHG_ERXEAX }, // handles XCHG R8d, EAX /* 91 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 92 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 93 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 94 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 95 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 96 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 97 /d */ { 0, BX_IA_XCHG_ERXEAX }, /* 98 /d */ { 0, BX_IA_CWDE }, /* 99 /d */ { 0, BX_IA_CDQ }, /* 9A /d */ { 0, BX_IA_ERROR }, /* 9B /d */ { 0, BX_IA_FWAIT }, /* 9C /d */ { 0, BX_IA_PUSHF_Fq }, /* 9D /d */ { BxTraceEnd, BX_IA_POPF_Fq }, /* 9E /d */ { 0, BX_IA_LM_SAHF }, /* 9F /d */ { 0, BX_IA_LM_LAHF }, /* A0 /d */ { BxImmediate_O, BX_IA_MOV_ALOq }, /* A1 /d */ { BxImmediate_O, BX_IA_MOV_EAXOq }, /* A2 /d */ { BxImmediate_O, BX_IA_MOV_OqAL }, /* A3 /d */ { BxImmediate_O, BX_IA_MOV_OqEAX }, /* A4 /d */ { BxRepeatable, BX_IA_REP_MOVSB_XbYb }, /* A5 /d */ { BxRepeatable, BX_IA_REP_MOVSD_XdYd }, /* A6 /d */ { BxRepeatable, BX_IA_REP_CMPSB_XbYb }, /* A7 /d */ { BxRepeatable, BX_IA_REP_CMPSD_XdYd }, /* A8 /d */ { BxImmediate_Ib, BX_IA_TEST_ALIb }, /* A9 /d */ { BxImmediate_Id, BX_IA_TEST_EAXId }, /* AA /d */ { BxRepeatable, BX_IA_REP_STOSB_YbAL }, /* AB /d */ { BxRepeatable, BX_IA_REP_STOSD_YdEAX }, /* AC /d */ { BxRepeatable, BX_IA_REP_LODSB_ALXb }, /* AD /d */ { BxRepeatable, BX_IA_REP_LODSD_EAXXd }, /* AE /d */ { BxRepeatable, BX_IA_REP_SCASB_ALXb }, /* AF /d */ { BxRepeatable, BX_IA_REP_SCASD_EAXXd }, /* B0 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B1 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B2 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B3 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B4 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B5 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B6 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B7 /d */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B8 /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* B9 /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BA /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BB /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BC /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BD /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BE /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* BF /d */ { BxImmediate_Id, BX_IA_MOV_ERXId }, /* C0 /d */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* C1 /d */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EdIb }, /* C2 /d */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETnear64_Iw }, /* C3 /d */ { BxTraceEnd, BX_IA_RETnear64 }, /* C4 /d */ { BxPrefixVEX, BX_IA_ERROR }, /* C5 /d */ { BxPrefixVEX, BX_IA_ERROR }, /* C6 /d */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Eb }, /* C7 /d */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Ed }, /* C8 /d */ { BxImmediate_Iw | BxImmediate_Ib2, BX_IA_ENTER64_IwIb }, /* C9 /d */ { 0, BX_IA_LEAVE64 }, /* CA /d */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETfar32_Iw }, /* CB /d */ { BxTraceEnd, BX_IA_RETfar32 }, /* CC /d */ { BxTraceEnd, BX_IA_INT3 }, /* CD /d */ { BxImmediate_Ib | BxTraceEnd, BX_IA_INT_Ib }, /* CE /d */ { 0, BX_IA_ERROR }, /* CF /d */ { BxTraceEnd, BX_IA_IRET64 }, /* D0 /d */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* D1 /d */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EdIb }, /* D2 /d */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Eb }, /* D3 /d */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Ed }, /* D4 /d */ { 0, BX_IA_ERROR }, /* D5 /d */ { 0, BX_IA_ERROR }, /* D6 /d */ { 0, BX_IA_ERROR }, /* D7 /d */ { 0, BX_IA_XLAT }, /* D8 /d */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupD8 }, /* D9 /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointD9 }, /* DA /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDA }, /* DB /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDB }, /* DC /d */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDC }, /* DD /d */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDD }, /* DE /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDE }, /* DF /d */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDF }, /* E0 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPNE64_Jb }, /* E1 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPE64_Jb }, /* E2 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOP64_Jb }, /* E3 /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JRCXZ_Jb }, /* E4 /d */ { BxImmediate_Ib, BX_IA_IN_ALIb }, /* E5 /d */ { BxImmediate_Ib, BX_IA_IN_EAXIb }, /* E6 /d */ { BxImmediate_Ib, BX_IA_OUT_IbAL }, /* E7 /d */ { BxImmediate_Ib, BX_IA_OUT_IbEAX }, /* E8 /d */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_CALL_Jq }, /* E9 /d */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_JMP_Jq }, /* EA /d */ { 0, BX_IA_ERROR }, /* EB /d */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JMP_Jq }, /* EC /d */ { 0, BX_IA_IN_ALDX }, /* ED /d */ { 0, BX_IA_IN_EAXDX }, /* EE /d */ { 0, BX_IA_OUT_DXAL }, /* EF /d */ { 0, BX_IA_OUT_DXEAX }, /* F0 /d */ { 0, BX_IA_ERROR }, // LOCK: /* F1 /d */ { BxTraceEnd, BX_IA_INT1 }, /* F2 /d */ { 0, BX_IA_ERROR }, // REPNE/REPNZ /* F3 /d */ { 0, BX_IA_ERROR }, // REP,REPE/REPZ /* F4 /d */ { BxTraceEnd, BX_IA_HLT }, /* F5 /d */ { 0, BX_IA_CMC }, /* F6 /d */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Eb }, /* F7 /d */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Ed }, /* F8 /d */ { 0, BX_IA_CLC }, /* F9 /d */ { 0, BX_IA_STC }, /* FA /d */ { 0, BX_IA_CLI }, /* FB /d */ { 0, BX_IA_STI }, /* FC /d */ { 0, BX_IA_CLD }, /* FD /d */ { 0, BX_IA_STD }, /* FE /d */ { BxGroup4, BX_IA_ERROR, BxOpcodeInfoG4 }, /* FF /d */ { BxGroup5, BX_IA_ERROR, BxOpcodeInfo64G5d }, /* 0F 00 /d */ { BxGroup6, BX_IA_ERROR, BxOpcodeInfoG6 }, /* 0F 01 /d */ { BxGroup7, BX_IA_ERROR, BxOpcodeInfoG7q }, /* 0F 02 /d */ { 0, BX_IA_LAR_GvEw }, /* 0F 03 /d */ { 0, BX_IA_LSL_GvEw }, /* 0F 04 /d */ { 0, BX_IA_ERROR }, /* 0F 05 /d */ { BxTraceEnd, BX_IA_SYSCALL }, /* 0F 06 /d */ { BxTraceEnd, BX_IA_CLTS }, /* 0F 07 /d */ { BxTraceEnd, BX_IA_SYSRET }, /* 0F 08 /d */ { BxTraceEnd, BX_IA_INVD }, /* 0F 09 /d */ { BxTraceEnd, BX_IA_WBINVD }, /* 0F 0A /d */ { 0, BX_IA_ERROR }, /* 0F 0B /d */ { BxTraceEnd, BX_IA_UD2A }, /* 0F 0C /d */ { 0, BX_IA_ERROR }, /* 0F 0D /d */ { 0, BX_IA_PREFETCHW }, // 3DNow! PREFETCHW on AMD, NOP on Intel /* 0F 0E /d */ { 0, BX_IA_FEMMS }, // 3DNow! FEMMS /* 0F 0F /d */ { BxImmediate_Ib, BX_IA_ERROR }, // 3DNow! Opcode Table /* 0F 10 /d */ { BxPrefixSSE, BX_IA_MOVUPS_VpsWps, BxOpcodeGroupSSE_0f10 }, /* 0F 11 /d */ { BxPrefixSSE, BX_IA_MOVUPS_WpsVps, BxOpcodeGroupSSE_0f11 }, /* 0F 12 /d */ { BxPrefixSSE, BX_IA_MOVLPS_VpsMq, BxOpcodeGroupSSE_0f12 }, /* 0F 13 /d */ { BxPrefixSSE, BX_IA_MOVLPS_MqVps, BxOpcodeGroupSSE_0f13M }, /* 0F 14 /d */ { BxPrefixSSE, BX_IA_UNPCKLPS_VpsWdq, BxOpcodeGroupSSE_0f14 }, /* 0F 15 /d */ { BxPrefixSSE, BX_IA_UNPCKHPS_VpsWdq, BxOpcodeGroupSSE_0f15 }, /* 0F 16 /d */ { BxPrefixSSE, BX_IA_MOVHPS_VpsMq, BxOpcodeGroupSSE_0f16 }, /* 0F 17 /d */ { BxPrefixSSE, BX_IA_MOVHPS_MqVps, BxOpcodeGroupSSE_0f17M }, /* 0F 18 /d */ { 0, BX_IA_PREFETCH }, // opcode group G16, PREFETCH hints /* 0F 19 /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1A /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1B /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1C /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1D /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1E /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1F /d */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 20 /d */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_RqCq }, /* 0F 21 /d */ { 0, BX_IA_MOV_RqDq }, /* 0F 22 /d */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_CqRq }, /* 0F 23 /d */ { BxTraceEnd, BX_IA_MOV_DqRq }, /* 0F 24 /d */ { 0, BX_IA_ERROR }, /* 0F 25 /d */ { 0, BX_IA_ERROR }, /* 0F 26 /d */ { 0, BX_IA_ERROR }, /* 0F 27 /d */ { 0, BX_IA_ERROR }, /* 0F 28 /d */ { BxPrefixSSE, BX_IA_MOVAPS_VpsWps, BxOpcodeGroupSSE_0f28 }, /* 0F 29 /d */ { BxPrefixSSE, BX_IA_MOVAPS_WpsVps, BxOpcodeGroupSSE_0f29 }, /* 0F 2A /d */ { BxPrefixSSE, BX_IA_CVTPI2PS_VpsQq, BxOpcodeGroupSSE_0f2a }, /* 0F 2B /d */ { BxPrefixSSE, BX_IA_MOVNTPS_MpsVps, BxOpcodeGroupSSE_0f2bM }, /* 0F 2C /d */ { BxPrefixSSE, BX_IA_CVTTPS2PI_PqWps, BxOpcodeGroupSSE_0f2c }, /* 0F 2D /d */ { BxPrefixSSE, BX_IA_CVTPS2PI_PqWps, BxOpcodeGroupSSE_0f2d }, /* 0F 2E /d */ { BxPrefixSSE, BX_IA_UCOMISS_VssWss, BxOpcodeGroupSSE_0f2e }, /* 0F 2F /d */ { BxPrefixSSE, BX_IA_COMISS_VpsWps, BxOpcodeGroupSSE_0f2f }, /* 0F 30 /d */ { 0, BX_IA_WRMSR }, /* 0F 31 /d */ { BxTraceEnd, BX_IA_RDTSC }, // end trace to avoid multiple TSC samples in one cycle /* 0F 32 /d */ { BxTraceEnd, BX_IA_RDMSR }, // end trace to avoid multiple TSC samples in one cycle /* 0F 33 /d */ { 0, BX_IA_RDPMC }, /* 0F 34 /d */ { BxTraceEnd, BX_IA_SYSENTER }, /* 0F 35 /d */ { BxTraceEnd, BX_IA_SYSEXIT }, /* 0F 36 /d */ { 0, BX_IA_ERROR }, /* 0F 37 /d */ { 0, BX_IA_GETSEC }, /* 0F 38 /d */ { Bx3ByteOp, BX_IA_ERROR, BxOpcode3ByteTable0f38 }, // 3-byte escape /* 0F 39 /d */ { 0, BX_IA_ERROR }, /* 0F 3A /d */ { Bx3ByteOp | BxImmediate_Ib, BX_IA_ERROR, BxOpcode3ByteTable0f3a }, // 3-byte escape /* 0F 3B /d */ { 0, BX_IA_ERROR }, /* 0F 3C /d */ { 0, BX_IA_ERROR }, /* 0F 3D /d */ { 0, BX_IA_ERROR }, /* 0F 3E /d */ { 0, BX_IA_ERROR }, /* 0F 3F /d */ { 0, BX_IA_ERROR }, /* 0F 40 /d */ { 0, BX_IA_CMOVO_GdEd }, /* 0F 41 /d */ { 0, BX_IA_CMOVNO_GdEd }, /* 0F 42 /d */ { 0, BX_IA_CMOVB_GdEd }, /* 0F 43 /d */ { 0, BX_IA_CMOVNB_GdEd }, /* 0F 44 /d */ { 0, BX_IA_CMOVZ_GdEd }, /* 0F 45 /d */ { 0, BX_IA_CMOVNZ_GdEd }, /* 0F 46 /d */ { 0, BX_IA_CMOVBE_GdEd }, /* 0F 47 /d */ { 0, BX_IA_CMOVNBE_GdEd }, /* 0F 48 /d */ { 0, BX_IA_CMOVS_GdEd }, /* 0F 49 /d */ { 0, BX_IA_CMOVNS_GdEd }, /* 0F 4A /d */ { 0, BX_IA_CMOVP_GdEd }, /* 0F 4B /d */ { 0, BX_IA_CMOVNP_GdEd }, /* 0F 4C /d */ { 0, BX_IA_CMOVL_GdEd }, /* 0F 4D /d */ { 0, BX_IA_CMOVNL_GdEd }, /* 0F 4E /d */ { 0, BX_IA_CMOVLE_GdEd }, /* 0F 4F /d */ { 0, BX_IA_CMOVNLE_GdEd }, /* 0F 50 /d */ { BxPrefixSSE, BX_IA_MOVMSKPS_GdVRps, BxOpcodeGroupSSE_0f50R }, /* 0F 51 /d */ { BxPrefixSSE, BX_IA_SQRTPS_VpsWps, BxOpcodeGroupSSE_0f51 }, /* 0F 52 /d */ { BxPrefixSSE, BX_IA_RSQRTPS_VpsWps, BxOpcodeGroupSSE_0f52 }, /* 0F 53 /d */ { BxPrefixSSE, BX_IA_RCPPS_VpsWps, BxOpcodeGroupSSE_0f53 }, /* 0F 54 /d */ { BxPrefixSSE, BX_IA_ANDPS_VpsWps, BxOpcodeGroupSSE_0f54 }, /* 0F 55 /d */ { BxPrefixSSE, BX_IA_ANDNPS_VpsWps, BxOpcodeGroupSSE_0f55 }, /* 0F 56 /d */ { BxPrefixSSE, BX_IA_ORPS_VpsWps, BxOpcodeGroupSSE_0f56 }, /* 0F 57 /d */ { BxPrefixSSE, BX_IA_XORPS_VpsWps, BxOpcodeGroupSSE_0f57 }, /* 0F 58 /d */ { BxPrefixSSE, BX_IA_ADDPS_VpsWps, BxOpcodeGroupSSE_0f58 }, /* 0F 59 /d */ { BxPrefixSSE, BX_IA_MULPS_VpsWps, BxOpcodeGroupSSE_0f59 }, /* 0F 5A /d */ { BxPrefixSSE, BX_IA_CVTPS2PD_VpdWps, BxOpcodeGroupSSE_0f5a }, /* 0F 5B /d */ { BxPrefixSSE, BX_IA_CVTDQ2PS_VpsWdq, BxOpcodeGroupSSE_0f5b }, /* 0F 5C /d */ { BxPrefixSSE, BX_IA_SUBPS_VpsWps, BxOpcodeGroupSSE_0f5c }, /* 0F 5D /d */ { BxPrefixSSE, BX_IA_MINPS_VpsWps, BxOpcodeGroupSSE_0f5d }, /* 0F 5E /d */ { BxPrefixSSE, BX_IA_DIVPS_VpsWps, BxOpcodeGroupSSE_0f5e }, /* 0F 5F /d */ { BxPrefixSSE, BX_IA_MAXPS_VpsWps, BxOpcodeGroupSSE_0f5f }, /* 0F 60 /d */ { BxPrefixSSE, BX_IA_PUNPCKLBW_PqQd, BxOpcodeGroupSSE_0f60 }, /* 0F 61 /d */ { BxPrefixSSE, BX_IA_PUNPCKLWD_PqQd, BxOpcodeGroupSSE_0f61 }, /* 0F 62 /d */ { BxPrefixSSE, BX_IA_PUNPCKLDQ_PqQd, BxOpcodeGroupSSE_0f62 }, /* 0F 63 /d */ { BxPrefixSSE, BX_IA_PACKSSWB_PqQq, BxOpcodeGroupSSE_0f63 }, /* 0F 64 /d */ { BxPrefixSSE, BX_IA_PCMPGTB_PqQq, BxOpcodeGroupSSE_0f64 }, /* 0F 65 /d */ { BxPrefixSSE, BX_IA_PCMPGTW_PqQq, BxOpcodeGroupSSE_0f65 }, /* 0F 66 /d */ { BxPrefixSSE, BX_IA_PCMPGTD_PqQq, BxOpcodeGroupSSE_0f66 }, /* 0F 67 /d */ { BxPrefixSSE, BX_IA_PACKUSWB_PqQq, BxOpcodeGroupSSE_0f67 }, /* 0F 68 /d */ { BxPrefixSSE, BX_IA_PUNPCKHBW_PqQq, BxOpcodeGroupSSE_0f68 }, /* 0F 69 /d */ { BxPrefixSSE, BX_IA_PUNPCKHWD_PqQq, BxOpcodeGroupSSE_0f69 }, /* 0F 6A /d */ { BxPrefixSSE, BX_IA_PUNPCKHDQ_PqQq, BxOpcodeGroupSSE_0f6a }, /* 0F 6B /d */ { BxPrefixSSE, BX_IA_PACKSSDW_PqQq, BxOpcodeGroupSSE_0f6b }, /* 0F 6C /d */ { BxPrefixSSE66, BX_IA_PUNPCKLQDQ_VdqWdq }, /* 0F 6D /d */ { BxPrefixSSE66, BX_IA_PUNPCKHQDQ_VdqWdq }, /* 0F 6E /d */ { BxPrefixSSE, BX_IA_MOVD_PqEd, BxOpcodeGroupSSE_0f6e }, /* 0F 6F /d */ { BxPrefixSSE, BX_IA_MOVQ_PqQq, BxOpcodeGroupSSE_0f6f }, /* 0F 70 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PSHUFW_PqQqIb, BxOpcodeGroupSSE_0f70 }, /* 0F 71 /d */ { BxGroup12, BX_IA_ERROR, BxOpcodeInfoG12R }, /* 0F 72 /d */ { BxGroup13, BX_IA_ERROR, BxOpcodeInfoG13R }, /* 0F 73 /d */ { BxGroup14, BX_IA_ERROR, BxOpcodeInfoG14R }, /* 0F 74 /d */ { BxPrefixSSE, BX_IA_PCMPEQB_PqQq, BxOpcodeGroupSSE_0f74 }, /* 0F 75 /d */ { BxPrefixSSE, BX_IA_PCMPEQW_PqQq, BxOpcodeGroupSSE_0f75 }, /* 0F 76 /d */ { BxPrefixSSE, BX_IA_PCMPEQD_PqQq, BxOpcodeGroupSSE_0f76 }, /* 0F 77 /d */ { BxPrefixSSE, BX_IA_EMMS, BxOpcodeGroupSSE_ERR }, /* 0F 78 /d */ { BxPrefixSSE, BX_IA_VMREAD_EqGq, BxOpcodeGroupSSE4A_0f78 }, /* 0F 79 /d */ { BxPrefixSSE, BX_IA_VMWRITE_GqEq, BxOpcodeGroupSSE4A_0f79 }, /* 0F 7A /d */ { 0, BX_IA_ERROR }, /* 0F 7B /d */ { 0, BX_IA_ERROR }, /* 0F 7C /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7c }, /* 0F 7D /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7d }, /* 0F 7E /d */ { BxPrefixSSE, BX_IA_MOVD_EdPd, BxOpcodeGroupSSE_0f7e }, /* 0F 7F /d */ { BxPrefixSSE, BX_IA_MOVQ_QqPq, BxOpcodeGroupSSE_0f7f }, /* 0F 80 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JO_Jq }, /* 0F 81 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNO_Jq }, /* 0F 82 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JB_Jq }, /* 0F 83 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNB_Jq }, /* 0F 84 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JZ_Jq }, /* 0F 85 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNZ_Jq }, /* 0F 86 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JBE_Jq }, /* 0F 87 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNBE_Jq }, /* 0F 88 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JS_Jq }, /* 0F 89 /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNS_Jq }, /* 0F 8A /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JP_Jq }, /* 0F 8B /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNP_Jq }, /* 0F 8C /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JL_Jq }, /* 0F 8D /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNL_Jq }, /* 0F 8E /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JLE_Jq }, /* 0F 8F /d */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNLE_Jq }, /* 0F 90 /d */ { 0, BX_IA_SETO_Eb }, /* 0F 91 /d */ { 0, BX_IA_SETNO_Eb }, /* 0F 92 /d */ { 0, BX_IA_SETB_Eb }, /* 0F 93 /d */ { 0, BX_IA_SETNB_Eb }, /* 0F 94 /d */ { 0, BX_IA_SETZ_Eb }, /* 0F 95 /d */ { 0, BX_IA_SETNZ_Eb }, /* 0F 96 /d */ { 0, BX_IA_SETBE_Eb }, /* 0F 97 /d */ { 0, BX_IA_SETNBE_Eb }, /* 0F 98 /d */ { 0, BX_IA_SETS_Eb }, /* 0F 99 /d */ { 0, BX_IA_SETNS_Eb }, /* 0F 9A /d */ { 0, BX_IA_SETP_Eb }, /* 0F 9B /d */ { 0, BX_IA_SETNP_Eb }, /* 0F 9C /d */ { 0, BX_IA_SETL_Eb }, /* 0F 9D /d */ { 0, BX_IA_SETNL_Eb }, /* 0F 9E /d */ { 0, BX_IA_SETLE_Eb }, /* 0F 9F /d */ { 0, BX_IA_SETNLE_Eb }, /* 0F A0 /d */ { 0, BX_IA_PUSH64_FS }, /* 0F A1 /d */ { 0, BX_IA_POP64_FS }, /* 0F A2 /d */ { 0, BX_IA_CPUID }, /* 0F A3 /d */ { 0, BX_IA_BT_EdGd }, /* 0F A4 /d */ { BxImmediate_Ib, BX_IA_SHLD_EdGdIb }, /* 0F A5 /d */ { 0, BX_IA_SHLD_EdGd }, /* 0F A6 /d */ { 0, BX_IA_ERROR }, /* 0F A7 /d */ { 0, BX_IA_ERROR }, /* 0F A8 /d */ { 0, BX_IA_PUSH64_GS }, /* 0F A9 /d */ { 0, BX_IA_POP64_GS }, /* 0F AA /d */ { BxTraceEnd, BX_IA_RSM }, /* 0F AB /d */ { BxLockable, BX_IA_BTS_EdGd }, /* 0F AC /d */ { BxImmediate_Ib, BX_IA_SHRD_EdGdIb }, /* 0F AD /d */ { 0, BX_IA_SHRD_EdGd }, /* 0F AE /d */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15q }, /* 0F AF /d */ { 0, BX_IA_IMUL_GdEd }, /* 0F B0 /d */ { BxLockable, BX_IA_CMPXCHG_EbGb }, /* 0F B1 /d */ { BxLockable, BX_IA_CMPXCHG_EdGd }, /* 0F B2 /d */ { 0, BX_IA_LSS_GdMp }, /* 0F B3 /d */ { BxLockable, BX_IA_BTR_EdGd }, /* 0F B4 /d */ { 0, BX_IA_LFS_GdMp }, /* 0F B5 /d */ { 0, BX_IA_LGS_GdMp }, /* 0F B6 /d */ { 0, BX_IA_MOVZX_GdEb }, /* 0F B7 /d */ { 0, BX_IA_MOVZX_GdEw }, /* 0F B8 /d */ { BxPrefixSSEF3, BX_IA_POPCNT_GdEd }, /* 0F B9 /d */ { BxTraceEnd, BX_IA_UD2B }, /* 0F BA /d */ { BxGroup8, BX_IA_ERROR, BxOpcodeInfoG8EdIb }, /* 0F BB /d */ { BxLockable, BX_IA_BTC_EdGd }, /* 0F BC /d */ { BxPrefixSSE, BX_IA_BSF_GdEd, BxOpcodeGroupSSE_TZCNT32 }, /* 0F BD /d */ { BxPrefixSSE, BX_IA_BSR_GdEd, BxOpcodeGroupSSE_LZCNT32 }, /* 0F BE /d */ { 0, BX_IA_MOVSX_GdEb }, /* 0F BF /d */ { 0, BX_IA_MOVSX_GdEw }, /* 0F C0 /d */ { BxLockable, BX_IA_XADD_EbGb }, /* 0F C1 /d */ { BxLockable, BX_IA_XADD_EdGd }, /* 0F C2 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_CMPPS_VpsWpsIb, BxOpcodeGroupSSE_0fc2 }, /* 0F C3 /d */ { BxPrefixSSE, BX_IA_MOVNTI64_MdGd, BxOpcodeGroupSSE_ERR }, /* 0F C4 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PINSRW_PqEwIb, BxOpcodeGroupSSE_0fc4 }, /* 0F C5 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PEXTRW_GdPqIb, BxOpcodeGroupSSE_0fc5R }, /* 0F C6 /d */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_SHUFPS_VpsWpsIb, BxOpcodeGroupSSE_0fc6 }, /* 0F C7 /d */ { BxGroup9, BX_IA_ERROR, BxOpcodeInfoG9M }, /* 0F C8 /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F C9 /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CA /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CB /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CC /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CD /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CE /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F CF /d */ { 0, BX_IA_BSWAP_ERX }, /* 0F D0 /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd0 }, /* 0F D1 /d */ { BxPrefixSSE, BX_IA_PSRLW_PqQq, BxOpcodeGroupSSE_0fd1 }, /* 0F D2 /d */ { BxPrefixSSE, BX_IA_PSRLD_PqQq, BxOpcodeGroupSSE_0fd2 }, /* 0F D3 /d */ { BxPrefixSSE, BX_IA_PSRLQ_PqQq, BxOpcodeGroupSSE_0fd3 }, /* 0F D4 /d */ { BxPrefixSSE, BX_IA_PADDQ_PqQq, BxOpcodeGroupSSE_0fd4 }, /* 0F D5 /d */ { BxPrefixSSE, BX_IA_PMULLW_PqQq, BxOpcodeGroupSSE_0fd5 }, /* 0F D6 /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd6 }, /* 0F D7 /d */ { BxPrefixSSE, BX_IA_PMOVMSKB_GdPRq, BxOpcodeGroupSSE_0fd7R }, /* 0F D8 /d */ { BxPrefixSSE, BX_IA_PSUBUSB_PqQq, BxOpcodeGroupSSE_0fd8 }, /* 0F D9 /d */ { BxPrefixSSE, BX_IA_PSUBUSW_PqQq, BxOpcodeGroupSSE_0fd9 }, /* 0F DA /d */ { BxPrefixSSE, BX_IA_PMINUB_PqQq, BxOpcodeGroupSSE_0fda }, /* 0F DB /d */ { BxPrefixSSE, BX_IA_PAND_PqQq, BxOpcodeGroupSSE_0fdb }, /* 0F DC /d */ { BxPrefixSSE, BX_IA_PADDUSB_PqQq, BxOpcodeGroupSSE_0fdc }, /* 0F DD /d */ { BxPrefixSSE, BX_IA_PADDUSW_PqQq, BxOpcodeGroupSSE_0fdd }, /* 0F DE /d */ { BxPrefixSSE, BX_IA_PMAXUB_PqQq, BxOpcodeGroupSSE_0fde }, /* 0F DF /d */ { BxPrefixSSE, BX_IA_PANDN_PqQq, BxOpcodeGroupSSE_0fdf }, /* 0F E0 /d */ { BxPrefixSSE, BX_IA_PAVGB_PqQq, BxOpcodeGroupSSE_0fe0 }, /* 0F E1 /d */ { BxPrefixSSE, BX_IA_PSRAW_PqQq, BxOpcodeGroupSSE_0fe1 }, /* 0F E2 /d */ { BxPrefixSSE, BX_IA_PSRAD_PqQq, BxOpcodeGroupSSE_0fe2 }, /* 0F E3 /d */ { BxPrefixSSE, BX_IA_PAVGW_PqQq, BxOpcodeGroupSSE_0fe3 }, /* 0F E4 /d */ { BxPrefixSSE, BX_IA_PMULHUW_PqQq, BxOpcodeGroupSSE_0fe4 }, /* 0F E5 /d */ { BxPrefixSSE, BX_IA_PMULHW_PqQq, BxOpcodeGroupSSE_0fe5 }, /* 0F E6 /d */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fe6 }, /* 0F E7 /d */ { BxPrefixSSE, BX_IA_MOVNTQ_MqPq, BxOpcodeGroupSSE_0fe7M }, /* 0F E8 /d */ { BxPrefixSSE, BX_IA_PSUBSB_PqQq, BxOpcodeGroupSSE_0fe8 }, /* 0F E9 /d */ { BxPrefixSSE, BX_IA_PSUBSW_PqQq, BxOpcodeGroupSSE_0fe9 }, /* 0F EA /d */ { BxPrefixSSE, BX_IA_PMINSW_PqQq, BxOpcodeGroupSSE_0fea }, /* 0F EB /d */ { BxPrefixSSE, BX_IA_POR_PqQq, BxOpcodeGroupSSE_0feb }, /* 0F EC /d */ { BxPrefixSSE, BX_IA_PADDSB_PqQq, BxOpcodeGroupSSE_0fec }, /* 0F ED /d */ { BxPrefixSSE, BX_IA_PADDSW_PqQq, BxOpcodeGroupSSE_0fed }, /* 0F EE /d */ { BxPrefixSSE, BX_IA_PMAXSW_PqQq, BxOpcodeGroupSSE_0fee }, /* 0F EF /d */ { BxPrefixSSE, BX_IA_PXOR_PqQq, BxOpcodeGroupSSE_0fef }, /* 0F F0 /d */ { BxPrefixSSEF2, BX_IA_LDDQU_VdqMdq }, /* 0F F1 /d */ { BxPrefixSSE, BX_IA_PSLLW_PqQq, BxOpcodeGroupSSE_0ff1 }, /* 0F F2 /d */ { BxPrefixSSE, BX_IA_PSLLD_PqQq, BxOpcodeGroupSSE_0ff2 }, /* 0F F3 /d */ { BxPrefixSSE, BX_IA_PSLLQ_PqQq, BxOpcodeGroupSSE_0ff3 }, /* 0F F4 /d */ { BxPrefixSSE, BX_IA_PMULUDQ_PqQq, BxOpcodeGroupSSE_0ff4 }, /* 0F F5 /d */ { BxPrefixSSE, BX_IA_PMADDWD_PqQq, BxOpcodeGroupSSE_0ff5 }, /* 0F F6 /d */ { BxPrefixSSE, BX_IA_PSADBW_PqQq, BxOpcodeGroupSSE_0ff6 }, /* 0F F7 /d */ { BxPrefixSSE, BX_IA_MASKMOVQ_PqPRq, BxOpcodeGroupSSE_0ff7R }, /* 0F F8 /d */ { BxPrefixSSE, BX_IA_PSUBB_PqQq, BxOpcodeGroupSSE_0ff8 }, /* 0F F9 /d */ { BxPrefixSSE, BX_IA_PSUBW_PqQq, BxOpcodeGroupSSE_0ff9 }, /* 0F FA /d */ { BxPrefixSSE, BX_IA_PSUBD_PqQq, BxOpcodeGroupSSE_0ffa }, /* 0F FB /d */ { BxPrefixSSE, BX_IA_PSUBQ_PqQq, BxOpcodeGroupSSE_0ffb }, /* 0F FC /d */ { BxPrefixSSE, BX_IA_PADDB_PqQq, BxOpcodeGroupSSE_0ffc }, /* 0F FD /d */ { BxPrefixSSE, BX_IA_PADDW_PqQq, BxOpcodeGroupSSE_0ffd }, /* 0F FE /d */ { BxPrefixSSE, BX_IA_PADDD_PqQq, BxOpcodeGroupSSE_0ffe }, /* 0F FF /d */ { 0, BX_IA_ERROR }, // 512 entries for 64bit mode /* 00 /q */ { BxLockable, BX_IA_ADD_EbGb }, /* 01 /q */ { BxLockable, BX_IA_ADD_EqGq }, /* 02 /q */ { 0, BX_IA_ADD_GbEb }, /* 03 /q */ { 0, BX_IA_ADD_GqEq }, /* 04 /q */ { BxImmediate_Ib, BX_IA_ADD_ALIb }, /* 05 /q */ { BxImmediate_Id, BX_IA_ADD_RAXId }, /* 06 /q */ { 0, BX_IA_ERROR }, /* 07 /q */ { 0, BX_IA_ERROR }, /* 08 /q */ { BxLockable, BX_IA_OR_EbGb }, /* 09 /q */ { BxLockable, BX_IA_OR_EqGq }, /* 0A /q */ { 0, BX_IA_OR_GbEb }, /* 0B /q */ { 0, BX_IA_OR_GqEq }, /* 0C /q */ { BxImmediate_Ib, BX_IA_OR_ALIb }, /* 0D /q */ { BxImmediate_Id, BX_IA_OR_RAXId }, /* 0E /q */ { 0, BX_IA_ERROR }, /* 0F /q */ { 0, BX_IA_ERROR }, // 2-byte escape /* 10 /q */ { BxLockable, BX_IA_ADC_EbGb }, /* 11 /q */ { BxLockable, BX_IA_ADC_EqGq }, /* 12 /q */ { 0, BX_IA_ADC_GbEb }, /* 13 /q */ { 0, BX_IA_ADC_GqEq }, /* 14 /q */ { BxImmediate_Ib, BX_IA_ADC_ALIb }, /* 15 /q */ { BxImmediate_Id, BX_IA_ADC_RAXId }, /* 16 /q */ { 0, BX_IA_ERROR }, /* 17 /q */ { 0, BX_IA_ERROR }, /* 18 /q */ { BxLockable, BX_IA_SBB_EbGb }, /* 19 /q */ { BxLockable, BX_IA_SBB_EqGq }, /* 1A /q */ { 0, BX_IA_SBB_GbEb }, /* 1B /q */ { 0, BX_IA_SBB_GqEq }, /* 1C /q */ { BxImmediate_Ib, BX_IA_SBB_ALIb }, /* 1D /q */ { BxImmediate_Id, BX_IA_SBB_RAXId }, /* 1E /q */ { 0, BX_IA_ERROR }, /* 1F /q */ { 0, BX_IA_ERROR }, /* 20 /q */ { BxLockable, BX_IA_AND_EbGb }, /* 21 /q */ { BxLockable, BX_IA_AND_EqGq }, /* 22 /q */ { 0, BX_IA_AND_GbEb }, /* 23 /q */ { 0, BX_IA_AND_GqEq }, /* 24 /q */ { BxImmediate_Ib, BX_IA_AND_ALIb }, /* 25 /q */ { BxImmediate_Id, BX_IA_AND_RAXId }, /* 26 /q */ { 0, BX_IA_ERROR }, // ES: /* 27 /q */ { 0, BX_IA_ERROR }, /* 28 /q */ { BxLockable, BX_IA_SUB_EbGb }, /* 29 /q */ { BxLockable, BX_IA_SUB_EqGq }, /* 2A /q */ { 0, BX_IA_SUB_GbEb }, /* 2B /q */ { 0, BX_IA_SUB_GqEq }, /* 2C /q */ { BxImmediate_Ib, BX_IA_SUB_ALIb }, /* 2D /q */ { BxImmediate_Id, BX_IA_SUB_RAXId }, /* 2E /q */ { 0, BX_IA_ERROR }, // CS: /* 2F /q */ { 0, BX_IA_ERROR }, /* 30 /q */ { BxLockable, BX_IA_XOR_EbGb }, /* 31 /q */ { BxLockable, BX_IA_XOR_EqGq }, /* 32 /q */ { 0, BX_IA_XOR_GbEb }, /* 33 /q */ { 0, BX_IA_XOR_GqEq }, /* 34 /q */ { BxImmediate_Ib, BX_IA_XOR_ALIb }, /* 35 /q */ { BxImmediate_Id, BX_IA_XOR_RAXId }, /* 36 /q */ { 0, BX_IA_ERROR }, // SS: /* 37 /q */ { 0, BX_IA_ERROR }, /* 38 /q */ { 0, BX_IA_CMP_EbGb }, /* 39 /q */ { 0, BX_IA_CMP_EqGq }, /* 3A /q */ { 0, BX_IA_CMP_GbEb }, /* 3B /q */ { 0, BX_IA_CMP_GqEq }, /* 3C /q */ { BxImmediate_Ib, BX_IA_CMP_ALIb }, /* 3D /q */ { BxImmediate_Id, BX_IA_CMP_RAXId }, /* 3E /q */ { 0, BX_IA_ERROR }, // DS: /* 3F /q */ { 0, BX_IA_ERROR }, /* 40 /q */ { 0, BX_IA_ERROR }, // REX: /* 41 /q */ { 0, BX_IA_ERROR }, // REX: /* 42 /q */ { 0, BX_IA_ERROR }, // REX: /* 43 /q */ { 0, BX_IA_ERROR }, // REX: /* 44 /q */ { 0, BX_IA_ERROR }, // REX: /* 45 /q */ { 0, BX_IA_ERROR }, // REX: /* 46 /q */ { 0, BX_IA_ERROR }, // REX: /* 47 /q */ { 0, BX_IA_ERROR }, // REX: /* 48 /q */ { 0, BX_IA_ERROR }, // REX: /* 49 /q */ { 0, BX_IA_ERROR }, // REX: /* 4A /q */ { 0, BX_IA_ERROR }, // REX: /* 4B /q */ { 0, BX_IA_ERROR }, // REX: /* 4C /q */ { 0, BX_IA_ERROR }, // REX: /* 4D /q */ { 0, BX_IA_ERROR }, // REX: /* 4E /q */ { 0, BX_IA_ERROR }, // REX: /* 4F /q */ { 0, BX_IA_ERROR }, // REX: /* 50 /q */ { 0, BX_IA_PUSH_RRX }, /* 51 /q */ { 0, BX_IA_PUSH_RRX }, /* 52 /q */ { 0, BX_IA_PUSH_RRX }, /* 53 /q */ { 0, BX_IA_PUSH_RRX }, /* 54 /q */ { 0, BX_IA_PUSH_RRX }, /* 55 /q */ { 0, BX_IA_PUSH_RRX }, /* 56 /q */ { 0, BX_IA_PUSH_RRX }, /* 57 /q */ { 0, BX_IA_PUSH_RRX }, /* 58 /q */ { 0, BX_IA_POP_RRX }, /* 59 /q */ { 0, BX_IA_POP_RRX }, /* 5A /q */ { 0, BX_IA_POP_RRX }, /* 5B /q */ { 0, BX_IA_POP_RRX }, /* 5C /q */ { 0, BX_IA_POP_RRX }, /* 5D /q */ { 0, BX_IA_POP_RRX }, /* 5E /q */ { 0, BX_IA_POP_RRX }, /* 5F /q */ { 0, BX_IA_POP_RRX }, /* 60 /q */ { 0, BX_IA_ERROR }, /* 61 /q */ { 0, BX_IA_ERROR }, /* 62 /q */ { 0, BX_IA_ERROR }, /* 63 /q */ { 0, BX_IA_MOVSX_GqEd }, /* 64 /q */ { 0, BX_IA_ERROR }, // FS: /* 65 /q */ { 0, BX_IA_ERROR }, // GS: /* 66 /q */ { 0, BX_IA_ERROR }, // OS: /* 67 /q */ { 0, BX_IA_ERROR }, // AS: /* 68 /q */ { BxImmediate_Id, BX_IA_PUSH64_Id }, /* 69 /q */ { BxImmediate_Id, BX_IA_IMUL_GqEqId }, /* 6A /q */ { BxImmediate_Ib_SE, BX_IA_PUSH64_Id }, /* 6B /q */ { BxImmediate_Ib_SE, BX_IA_IMUL_GqEqId }, /* 6C /q */ { BxRepeatable, BX_IA_REP_INSB_YbDX }, /* 6D /q */ { BxRepeatable, BX_IA_REP_INSD_YdDX }, /* 6E /q */ { BxRepeatable, BX_IA_REP_OUTSB_DXXb }, /* 6F /q */ { BxRepeatable, BX_IA_REP_OUTSD_DXXd }, /* 70 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JO_Jq }, /* 71 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNO_Jq }, /* 72 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JB_Jq }, /* 73 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNB_Jq }, /* 74 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JZ_Jq }, /* 75 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNZ_Jq }, /* 76 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JBE_Jq }, /* 77 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNBE_Jq }, /* 78 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JS_Jq }, /* 79 /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNS_Jq }, /* 7A /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JP_Jq }, /* 7B /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNP_Jq }, /* 7C /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JL_Jq }, /* 7D /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNL_Jq }, /* 7E /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JLE_Jq }, /* 7F /q */ { BxImmediate_BrOff8 | BxTraceJCC, BX_IA_JNLE_Jq }, /* 80 /q */ { BxGroup1 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG1EbIb }, /* 81 /q */ { BxGroup1 | BxImmediate_Id, BX_IA_ERROR, BxOpcodeInfo64G1Eq }, /* 82 /q */ { 0, BX_IA_ERROR }, /* 83 /q */ { BxGroup1 | BxImmediate_Ib_SE, BX_IA_ERROR, BxOpcodeInfo64G1Eq }, /* 84 /q */ { 0, BX_IA_TEST_EbGb }, /* 85 /q */ { 0, BX_IA_TEST_EqGq }, /* 86 /q */ { BxLockable, BX_IA_XCHG_EbGb }, /* 87 /q */ { BxLockable, BX_IA_XCHG_EqGq }, /* 88 /q */ { 0, BX_IA_MOV_EbGb }, /* 89 /q */ { 0, BX_IA_MOV_EqGq }, /* 8A /q */ { 0, BX_IA_MOV_GbEb }, /* 8B /q */ { 0, BX_IA_MOV_GqEq }, /* 8C /q */ { 0, BX_IA_MOV_EwSw }, /* 8D /q */ { 0, BX_IA_LEA_GqM }, /* 8E /q */ { 0, BX_IA_MOV_SwEw }, /* 8F /q */ { BxGroup1A, BX_IA_ERROR, BxOpcodeInfo64G1AEq }, /* 90 /q */ { 0, BX_IA_XCHG_RRXRAX }, // handles XCHG R8, RAX /* 91 /q */ { 0, BX_IA_XCHG_RRXRAX }, /* 92 /q */ { 0, BX_IA_XCHG_RRXRAX }, /* 93 /q */ { 0, BX_IA_XCHG_RRXRAX }, /* 94 /q */ { 0, BX_IA_XCHG_RRXRAX }, /* 95 /q */ { 0, BX_IA_XCHG_RRXRAX }, /* 96 /q */ { 0, BX_IA_XCHG_RRXRAX }, /* 97 /q */ { 0, BX_IA_XCHG_RRXRAX }, /* 98 /q */ { 0, BX_IA_CDQE }, /* 99 /q */ { 0, BX_IA_CQO }, /* 9A /q */ { 0, BX_IA_ERROR }, /* 9B /q */ { 0, BX_IA_FWAIT }, /* 9C /q */ { 0, BX_IA_PUSHF_Fq }, /* 9D /q */ { BxTraceEnd, BX_IA_POPF_Fq }, /* 9E /q */ { 0, BX_IA_LM_SAHF }, /* 9F /q */ { 0, BX_IA_LM_LAHF }, /* A0 /q */ { BxImmediate_O, BX_IA_MOV_ALOq }, /* A1 /q */ { BxImmediate_O, BX_IA_MOV_RAXOq }, /* A2 /q */ { BxImmediate_O, BX_IA_MOV_OqAL }, /* A3 /q */ { BxImmediate_O, BX_IA_MOV_OqRAX }, /* A4 /q */ { BxRepeatable, BX_IA_REP_MOVSB_XbYb }, /* A5 /q */ { BxRepeatable, BX_IA_REP_MOVSQ_XqYq }, /* A6 /q */ { BxRepeatable, BX_IA_REP_CMPSB_XbYb }, /* A7 /q */ { BxRepeatable, BX_IA_REP_CMPSQ_XqYq }, /* A8 /q */ { BxImmediate_Ib, BX_IA_TEST_ALIb }, /* A9 /q */ { BxImmediate_Id, BX_IA_TEST_RAXId }, /* AA /q */ { BxRepeatable, BX_IA_REP_STOSB_YbAL }, /* AB /q */ { BxRepeatable, BX_IA_REP_STOSQ_YqRAX }, /* AC /q */ { BxRepeatable, BX_IA_REP_LODSB_ALXb }, /* AD /q */ { BxRepeatable, BX_IA_REP_LODSQ_RAXXq }, /* AE /q */ { BxRepeatable, BX_IA_REP_SCASB_ALXb }, /* AF /q */ { BxRepeatable, BX_IA_REP_SCASQ_RAXXq }, /* B0 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B1 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B2 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B3 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B4 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B5 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B6 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B7 /q */ { BxImmediate_Ib, BX_IA_MOV_RLIb }, /* B8 /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* B9 /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* BA /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* BB /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* BC /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* BD /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* BE /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* BF /q */ { BxImmediate_Iq, BX_IA_MOV_RRXIq }, /* C0 /q */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* C1 /q */ { BxGroup2 | BxImmediate_Ib, BX_IA_ERROR, BxOpcodeInfo64G2EqIb }, /* C2 /q */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETnear64_Iw }, /* C3 /q */ { BxTraceEnd, BX_IA_RETnear64 }, /* C4 /q */ { BxPrefixVEX, BX_IA_ERROR }, /* C5 /q */ { BxPrefixVEX, BX_IA_ERROR }, /* C6 /q */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfoG11Eb }, /* C7 /q */ { BxGroup11, BX_IA_ERROR, BxOpcodeInfo64G11Eq }, /* C8 /q */ { BxImmediate_Iw | BxImmediate_Ib2, BX_IA_ENTER64_IwIb }, /* C9 /q */ { 0, BX_IA_LEAVE64 }, /* CA /q */ { BxImmediate_Iw | BxTraceEnd, BX_IA_RETfar64_Iw }, /* CB /q */ { BxTraceEnd, BX_IA_RETfar64 }, /* CC /q */ { BxTraceEnd, BX_IA_INT3 }, /* CD /q */ { BxImmediate_Ib | BxTraceEnd, BX_IA_INT_Ib }, /* CE /q */ { 0, BX_IA_ERROR }, /* CF /q */ { BxTraceEnd, BX_IA_IRET64 }, /* D0 /q */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfoG2EbIb }, /* D1 /q */ { BxGroup2 | BxImmediate_I1, BX_IA_ERROR, BxOpcodeInfo64G2EqIb }, /* D2 /q */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfoG2Eb }, /* D3 /q */ { BxGroup2, BX_IA_ERROR, BxOpcodeInfo64G2Eq }, /* D4 /q */ { 0, BX_IA_ERROR }, /* D5 /q */ { 0, BX_IA_ERROR }, /* D6 /q */ { 0, BX_IA_ERROR }, /* D7 /q */ { 0, BX_IA_XLAT }, /* D8 /q */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupD8 }, /* D9 /q */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointD9 }, /* DA /q */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDA }, /* DB /q */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDB }, /* DC /q */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDC }, /* DD /q */ { BxGroupFP, BX_IA_ERROR, BxOpcodeInfo_FPGroupDD }, /* DE /q */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDE }, /* DF /q */ { BxFPEscape, BX_IA_ERROR, BxOpcodeInfo_FloatingPointDF }, /* E0 /q */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPNE64_Jb }, /* E1 /q */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOPE64_Jb }, /* E2 /q */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_LOOP64_Jb }, /* E3 /q */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JRCXZ_Jb }, /* E4 /q */ { BxImmediate_Ib, BX_IA_IN_ALIb }, /* E5 /q */ { BxImmediate_Ib, BX_IA_IN_EAXIb }, /* E6 /q */ { BxImmediate_Ib, BX_IA_OUT_IbAL }, /* E7 /q */ { BxImmediate_Ib, BX_IA_OUT_IbEAX }, /* E8 /q */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_CALL_Jq }, /* E9 /q */ { BxImmediate_BrOff32 | BxTraceEnd, BX_IA_JMP_Jq }, /* EA /q */ { 0, BX_IA_ERROR }, /* EB /q */ { BxImmediate_BrOff8 | BxTraceEnd, BX_IA_JMP_Jq }, /* EC /q */ { 0, BX_IA_IN_ALDX }, /* ED /q */ { 0, BX_IA_IN_EAXDX }, /* EE /q */ { 0, BX_IA_OUT_DXAL }, /* EF /q */ { 0, BX_IA_OUT_DXEAX }, /* F0 /q */ { 0, BX_IA_ERROR }, // LOCK: /* F1 /q */ { BxTraceEnd, BX_IA_INT1 }, /* F2 /q */ { 0, BX_IA_ERROR }, // REPNE/REPNZ /* F3 /q */ { 0, BX_IA_ERROR }, // REP,REPE/REPZ /* F4 /q */ { BxTraceEnd, BX_IA_HLT }, /* F5 /q */ { 0, BX_IA_CMC }, /* F6 /q */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfoG3Eb }, /* F7 /q */ { BxGroup3, BX_IA_ERROR, BxOpcodeInfo64G3Eq }, /* F8 /q */ { 0, BX_IA_CLC }, /* F9 /q */ { 0, BX_IA_STC }, /* FA /q */ { 0, BX_IA_CLI }, /* FB /q */ { 0, BX_IA_STI }, /* FC /q */ { 0, BX_IA_CLD }, /* FD /q */ { 0, BX_IA_STD }, /* FE /q */ { BxGroup4, BX_IA_ERROR, BxOpcodeInfoG4 }, /* FF /q */ { BxGroup5, BX_IA_ERROR, BxOpcodeInfo64G5q }, /* 0F 00 /q */ { BxGroup6, BX_IA_ERROR, BxOpcodeInfoG6 }, /* 0F 01 /q */ { BxGroup7, BX_IA_ERROR, BxOpcodeInfoG7q }, /* 0F 02 /q */ { 0, BX_IA_LAR_GvEw }, /* 0F 03 /q */ { 0, BX_IA_LSL_GvEw }, /* 0F 04 /q */ { 0, BX_IA_ERROR }, /* 0F 05 /q */ { BxTraceEnd, BX_IA_SYSCALL }, /* 0F 06 /q */ { BxTraceEnd, BX_IA_CLTS }, /* 0F 07 /q */ { BxTraceEnd, BX_IA_SYSRET }, /* 0F 08 /q */ { BxTraceEnd, BX_IA_INVD }, /* 0F 09 /q */ { BxTraceEnd, BX_IA_WBINVD }, /* 0F 0A /q */ { 0, BX_IA_ERROR }, /* 0F 0B /q */ { BxTraceEnd, BX_IA_UD2A }, /* 0F 0C /q */ { 0, BX_IA_ERROR }, /* 0F 0D /q */ { 0, BX_IA_PREFETCHW }, // 3DNow! PREFETCHW on AMD, NOP on Intel /* 0F 0E /q */ { 0, BX_IA_FEMMS }, // 3DNow! FEMMS /* 0F 0F /q */ { BxImmediate_Ib, BX_IA_ERROR }, // 3DNow! Opcode Table /* 0F 10 /q */ { BxPrefixSSE, BX_IA_MOVUPS_VpsWps, BxOpcodeGroupSSE_0f10 }, /* 0F 11 /q */ { BxPrefixSSE, BX_IA_MOVUPS_WpsVps, BxOpcodeGroupSSE_0f11 }, /* 0F 12 /q */ { BxPrefixSSE, BX_IA_MOVLPS_VpsMq, BxOpcodeGroupSSE_0f12 }, /* 0F 13 /q */ { BxPrefixSSE, BX_IA_MOVLPS_MqVps, BxOpcodeGroupSSE_0f13M }, /* 0F 14 /q */ { BxPrefixSSE, BX_IA_UNPCKLPS_VpsWdq, BxOpcodeGroupSSE_0f14 }, /* 0F 15 /q */ { BxPrefixSSE, BX_IA_UNPCKHPS_VpsWdq, BxOpcodeGroupSSE_0f15 }, /* 0F 16 /q */ { BxPrefixSSE, BX_IA_MOVHPS_VpsMq, BxOpcodeGroupSSE_0f16 }, /* 0F 17 /q */ { BxPrefixSSE, BX_IA_MOVHPS_MqVps, BxOpcodeGroupSSE_0f17M }, /* 0F 18 /q */ { 0, BX_IA_PREFETCH }, // opcode group G16, PREFETCH hints /* 0F 19 /q */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1A /q */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1B /q */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1C /q */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1D /q */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1E /q */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 1F /q */ { 0, BX_IA_NOP }, // multi-byte NOP /* 0F 20 /q */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_RqCq }, /* 0F 21 /q */ { 0, BX_IA_MOV_RqDq }, /* 0F 22 /q */ { BxGroupN, BX_IA_ERROR, BxOpcodeInfoMOV_CqRq }, /* 0F 23 /q */ { BxTraceEnd, BX_IA_MOV_DqRq }, /* 0F 24 /q */ { 0, BX_IA_ERROR }, /* 0F 25 /q */ { 0, BX_IA_ERROR }, /* 0F 26 /q */ { 0, BX_IA_ERROR }, /* 0F 27 /q */ { 0, BX_IA_ERROR }, /* 0F 28 /q */ { BxPrefixSSE, BX_IA_MOVAPS_VpsWps, BxOpcodeGroupSSE_0f28 }, /* 0F 29 /q */ { BxPrefixSSE, BX_IA_MOVAPS_WpsVps, BxOpcodeGroupSSE_0f29 }, /* 0F 2A /q */ { BxPrefixSSE, BX_IA_CVTPI2PS_VpsQq, BxOpcodeGroupSSE_0f2aQ }, /* 0F 2B /q */ { BxPrefixSSE, BX_IA_MOVNTPS_MpsVps, BxOpcodeGroupSSE_0f2bM }, /* 0F 2C /q */ { BxPrefixSSE, BX_IA_CVTTPS2PI_PqWps, BxOpcodeGroupSSE_0f2cQ }, /* 0F 2D /q */ { BxPrefixSSE, BX_IA_CVTPS2PI_PqWps, BxOpcodeGroupSSE_0f2dQ }, /* 0F 2E /q */ { BxPrefixSSE, BX_IA_UCOMISS_VssWss, BxOpcodeGroupSSE_0f2e }, /* 0F 2F /q */ { BxPrefixSSE, BX_IA_COMISS_VpsWps, BxOpcodeGroupSSE_0f2f }, /* 0F 30 /q */ { 0, BX_IA_WRMSR }, /* 0F 31 /q */ { BxTraceEnd, BX_IA_RDTSC }, // end trace to avoid multiple TSC samples in one cycle /* 0F 32 /q */ { BxTraceEnd, BX_IA_RDMSR }, // end trace to avoid multiple TSC samples in one cycle /* 0F 33 /q */ { 0, BX_IA_RDPMC }, /* 0F 34 /q */ { BxTraceEnd, BX_IA_SYSENTER }, /* 0F 35 /q */ { BxTraceEnd, BX_IA_SYSEXIT }, /* 0F 36 /q */ { 0, BX_IA_ERROR }, /* 0F 37 /q */ { 0, BX_IA_GETSEC }, /* 0F 38 /q */ { Bx3ByteOp, BX_IA_ERROR, BxOpcode3ByteTable0f38 }, // 3-byte escape /* 0F 39 /q */ { 0, BX_IA_ERROR }, /* 0F 3A /q */ { Bx3ByteOp | BxImmediate_Ib, BX_IA_ERROR, BxOpcode3ByteTable0f3a }, // 3-byte escape /* 0F 3B /q */ { 0, BX_IA_ERROR }, /* 0F 3C /q */ { 0, BX_IA_ERROR }, /* 0F 3D /q */ { 0, BX_IA_ERROR }, /* 0F 3E /q */ { 0, BX_IA_ERROR }, /* 0F 3F /q */ { 0, BX_IA_ERROR }, /* 0F 40 /q */ { 0, BX_IA_CMOVO_GqEq }, /* 0F 41 /q */ { 0, BX_IA_CMOVNO_GqEq }, /* 0F 42 /q */ { 0, BX_IA_CMOVB_GqEq }, /* 0F 43 /q */ { 0, BX_IA_CMOVNB_GqEq }, /* 0F 44 /q */ { 0, BX_IA_CMOVZ_GqEq }, /* 0F 45 /q */ { 0, BX_IA_CMOVNZ_GqEq }, /* 0F 46 /q */ { 0, BX_IA_CMOVBE_GqEq }, /* 0F 47 /q */ { 0, BX_IA_CMOVNBE_GqEq }, /* 0F 48 /q */ { 0, BX_IA_CMOVS_GqEq }, /* 0F 49 /q */ { 0, BX_IA_CMOVNS_GqEq }, /* 0F 4A /q */ { 0, BX_IA_CMOVP_GqEq }, /* 0F 4B /q */ { 0, BX_IA_CMOVNP_GqEq }, /* 0F 4C /q */ { 0, BX_IA_CMOVL_GqEq }, /* 0F 4D /q */ { 0, BX_IA_CMOVNL_GqEq }, /* 0F 4E /q */ { 0, BX_IA_CMOVLE_GqEq }, /* 0F 4F /q */ { 0, BX_IA_CMOVNLE_GqEq }, /* 0F 50 /q */ { BxPrefixSSE, BX_IA_MOVMSKPS_GdVRps, BxOpcodeGroupSSE_0f50R }, /* 0F 51 /q */ { BxPrefixSSE, BX_IA_SQRTPS_VpsWps, BxOpcodeGroupSSE_0f51 }, /* 0F 52 /q */ { BxPrefixSSE, BX_IA_RSQRTPS_VpsWps, BxOpcodeGroupSSE_0f52 }, /* 0F 53 /q */ { BxPrefixSSE, BX_IA_RCPPS_VpsWps, BxOpcodeGroupSSE_0f53 }, /* 0F 54 /q */ { BxPrefixSSE, BX_IA_ANDPS_VpsWps, BxOpcodeGroupSSE_0f54 }, /* 0F 55 /q */ { BxPrefixSSE, BX_IA_ANDNPS_VpsWps, BxOpcodeGroupSSE_0f55 }, /* 0F 56 /q */ { BxPrefixSSE, BX_IA_ORPS_VpsWps, BxOpcodeGroupSSE_0f56 }, /* 0F 57 /q */ { BxPrefixSSE, BX_IA_XORPS_VpsWps, BxOpcodeGroupSSE_0f57 }, /* 0F 58 /q */ { BxPrefixSSE, BX_IA_ADDPS_VpsWps, BxOpcodeGroupSSE_0f58 }, /* 0F 59 /q */ { BxPrefixSSE, BX_IA_MULPS_VpsWps, BxOpcodeGroupSSE_0f59 }, /* 0F 5A /q */ { BxPrefixSSE, BX_IA_CVTPS2PD_VpdWps, BxOpcodeGroupSSE_0f5a }, /* 0F 5B /q */ { BxPrefixSSE, BX_IA_CVTDQ2PS_VpsWdq, BxOpcodeGroupSSE_0f5b }, /* 0F 5C /q */ { BxPrefixSSE, BX_IA_SUBPS_VpsWps, BxOpcodeGroupSSE_0f5c }, /* 0F 5D /q */ { BxPrefixSSE, BX_IA_MINPS_VpsWps, BxOpcodeGroupSSE_0f5d }, /* 0F 5E /q */ { BxPrefixSSE, BX_IA_DIVPS_VpsWps, BxOpcodeGroupSSE_0f5e }, /* 0F 5F /q */ { BxPrefixSSE, BX_IA_MAXPS_VpsWps, BxOpcodeGroupSSE_0f5f }, /* 0F 60 /q */ { BxPrefixSSE, BX_IA_PUNPCKLBW_PqQd, BxOpcodeGroupSSE_0f60 }, /* 0F 61 /q */ { BxPrefixSSE, BX_IA_PUNPCKLWD_PqQd, BxOpcodeGroupSSE_0f61 }, /* 0F 62 /q */ { BxPrefixSSE, BX_IA_PUNPCKLDQ_PqQd, BxOpcodeGroupSSE_0f62 }, /* 0F 63 /q */ { BxPrefixSSE, BX_IA_PACKSSWB_PqQq, BxOpcodeGroupSSE_0f63 }, /* 0F 64 /q */ { BxPrefixSSE, BX_IA_PCMPGTB_PqQq, BxOpcodeGroupSSE_0f64 }, /* 0F 65 /q */ { BxPrefixSSE, BX_IA_PCMPGTW_PqQq, BxOpcodeGroupSSE_0f65 }, /* 0F 66 /q */ { BxPrefixSSE, BX_IA_PCMPGTD_PqQq, BxOpcodeGroupSSE_0f66 }, /* 0F 67 /q */ { BxPrefixSSE, BX_IA_PACKUSWB_PqQq, BxOpcodeGroupSSE_0f67 }, /* 0F 68 /q */ { BxPrefixSSE, BX_IA_PUNPCKHBW_PqQq, BxOpcodeGroupSSE_0f68 }, /* 0F 69 /q */ { BxPrefixSSE, BX_IA_PUNPCKHWD_PqQq, BxOpcodeGroupSSE_0f69 }, /* 0F 6A /q */ { BxPrefixSSE, BX_IA_PUNPCKHDQ_PqQq, BxOpcodeGroupSSE_0f6a }, /* 0F 6B /q */ { BxPrefixSSE, BX_IA_PACKSSDW_PqQq, BxOpcodeGroupSSE_0f6b }, /* 0F 6C /q */ { BxPrefixSSE66, BX_IA_PUNPCKLQDQ_VdqWdq }, /* 0F 6D /q */ { BxPrefixSSE66, BX_IA_PUNPCKHQDQ_VdqWdq }, /* 0F 6E /q */ { BxPrefixSSE, BX_IA_MOVQ_PqEq, BxOpcodeGroupSSE_0f6eQ }, /* 0F 6F /q */ { BxPrefixSSE, BX_IA_MOVQ_PqQq, BxOpcodeGroupSSE_0f6f }, /* 0F 70 /q */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PSHUFW_PqQqIb, BxOpcodeGroupSSE_0f70 }, /* 0F 71 /q */ { BxGroup12, BX_IA_ERROR, BxOpcodeInfoG12R }, /* 0F 72 /q */ { BxGroup13, BX_IA_ERROR, BxOpcodeInfoG13R }, /* 0F 73 /q */ { BxGroup14, BX_IA_ERROR, BxOpcodeInfoG14R }, /* 0F 74 /q */ { BxPrefixSSE, BX_IA_PCMPEQB_PqQq, BxOpcodeGroupSSE_0f74 }, /* 0F 75 /q */ { BxPrefixSSE, BX_IA_PCMPEQW_PqQq, BxOpcodeGroupSSE_0f75 }, /* 0F 76 /q */ { BxPrefixSSE, BX_IA_PCMPEQD_PqQq, BxOpcodeGroupSSE_0f76 }, /* 0F 77 /q */ { BxPrefixSSE, BX_IA_EMMS, BxOpcodeGroupSSE_ERR }, /* 0F 78 /q */ { BxPrefixSSE, BX_IA_VMREAD_EqGq, BxOpcodeGroupSSE4A_0f78 }, /* 0F 79 /q */ { BxPrefixSSE, BX_IA_VMWRITE_GqEq, BxOpcodeGroupSSE4A_0f79 }, /* 0F 7A /q */ { 0, BX_IA_ERROR }, /* 0F 7B /q */ { 0, BX_IA_ERROR }, /* 0F 7C /q */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7c }, /* 0F 7D /q */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0f7d }, /* 0F 7E /q */ { BxPrefixSSE, BX_IA_MOVQ_EqPq, BxOpcodeGroupSSE_0f7eQ }, /* 0F 7F /q */ { BxPrefixSSE, BX_IA_MOVQ_QqPq, BxOpcodeGroupSSE_0f7f }, /* 0F 80 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JO_Jq }, /* 0F 81 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNO_Jq }, /* 0F 82 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JB_Jq }, /* 0F 83 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNB_Jq }, /* 0F 84 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JZ_Jq }, /* 0F 85 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNZ_Jq }, /* 0F 86 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JBE_Jq }, /* 0F 87 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNBE_Jq }, /* 0F 88 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JS_Jq }, /* 0F 89 /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNS_Jq }, /* 0F 8A /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JP_Jq }, /* 0F 8B /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNP_Jq }, /* 0F 8C /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JL_Jq }, /* 0F 8D /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNL_Jq }, /* 0F 8E /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JLE_Jq }, /* 0F 8F /q */ { BxImmediate_BrOff32 | BxTraceJCC, BX_IA_JNLE_Jq }, /* 0F 90 /q */ { 0, BX_IA_SETO_Eb }, /* 0F 91 /q */ { 0, BX_IA_SETNO_Eb }, /* 0F 92 /q */ { 0, BX_IA_SETB_Eb }, /* 0F 93 /q */ { 0, BX_IA_SETNB_Eb }, /* 0F 94 /q */ { 0, BX_IA_SETZ_Eb }, /* 0F 95 /q */ { 0, BX_IA_SETNZ_Eb }, /* 0F 96 /q */ { 0, BX_IA_SETBE_Eb }, /* 0F 97 /q */ { 0, BX_IA_SETNBE_Eb }, /* 0F 98 /q */ { 0, BX_IA_SETS_Eb }, /* 0F 99 /q */ { 0, BX_IA_SETNS_Eb }, /* 0F 9A /q */ { 0, BX_IA_SETP_Eb }, /* 0F 9B /q */ { 0, BX_IA_SETNP_Eb }, /* 0F 9C /q */ { 0, BX_IA_SETL_Eb }, /* 0F 9D /q */ { 0, BX_IA_SETNL_Eb }, /* 0F 9E /q */ { 0, BX_IA_SETLE_Eb }, /* 0F 9F /q */ { 0, BX_IA_SETNLE_Eb }, /* 0F A0 /q */ { 0, BX_IA_PUSH64_FS }, /* 0F A1 /q */ { 0, BX_IA_POP64_FS }, /* 0F A2 /q */ { 0, BX_IA_CPUID }, /* 0F A3 /q */ { 0, BX_IA_BT_EqGq }, /* 0F A4 /q */ { BxImmediate_Ib, BX_IA_SHLD_EqGqIb }, /* 0F A5 /q */ { 0, BX_IA_SHLD_EqGq }, /* 0F A6 /q */ { 0, BX_IA_ERROR }, /* 0F A7 /q */ { 0, BX_IA_ERROR }, /* 0F A8 /q */ { 0, BX_IA_PUSH64_GS }, /* 0F A9 /q */ { 0, BX_IA_POP64_GS }, /* 0F AA /q */ { BxTraceEnd, BX_IA_RSM }, /* 0F AB /q */ { BxLockable, BX_IA_BTS_EqGq }, /* 0F AC /q */ { BxImmediate_Ib, BX_IA_SHRD_EqGqIb }, /* 0F AD /q */ { 0, BX_IA_SHRD_EqGq }, /* 0F AE /q */ { BxGroup15, BX_IA_ERROR, BxOpcodeInfoG15q }, /* 0F AF /q */ { 0, BX_IA_IMUL_GqEq }, /* 0F B0 /q */ { BxLockable, BX_IA_CMPXCHG_EbGb }, /* 0F B1 /q */ { BxLockable, BX_IA_CMPXCHG_EqGq }, /* 0F B2 /q */ { 0, BX_IA_LSS_GqMp }, // TODO: LSS_GdMp for AMD CPU /* 0F B3 /q */ { BxLockable, BX_IA_BTR_EqGq }, /* 0F B4 /q */ { 0, BX_IA_LFS_GqMp }, // TODO: LFS_GdMp for AMD CPU /* 0F B5 /q */ { 0, BX_IA_LGS_GqMp }, // TODO: LGS_GdMp for AMD CPU /* 0F B6 /q */ { 0, BX_IA_MOVZX_GqEb }, /* 0F B7 /q */ { 0, BX_IA_MOVZX_GqEw }, /* 0F B8 /q */ { BxPrefixSSEF3, BX_IA_POPCNT_GqEq }, /* 0F B9 /q */ { BxTraceEnd, BX_IA_UD2B }, /* 0F BA /q */ { BxGroup8, BX_IA_ERROR, BxOpcodeInfo64G8EqIb }, /* 0F BB /q */ { BxLockable, BX_IA_BTC_EqGq }, /* 0F BC /q */ { BxPrefixSSE, BX_IA_BSF_GqEq, BxOpcodeGroupSSE_TZCNT64 }, /* 0F BD /q */ { BxPrefixSSE, BX_IA_BSR_GqEq, BxOpcodeGroupSSE_LZCNT64 }, /* 0F BE /q */ { 0, BX_IA_MOVSX_GqEb }, /* 0F BF /q */ { 0, BX_IA_MOVSX_GqEw }, /* 0F C0 /q */ { BxLockable, BX_IA_XADD_EbGb }, /* 0F C1 /q */ { BxLockable, BX_IA_XADD_EqGq }, /* 0F C2 /q */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_CMPPS_VpsWpsIb, BxOpcodeGroupSSE_0fc2 }, /* 0F C3 /q */ { BxPrefixSSE, BX_IA_MOVNTI_MqGq, BxOpcodeGroupSSE_ERR }, /* 0F C4 /q */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PINSRW_PqEwIb, BxOpcodeGroupSSE_0fc4 }, /* 0F C5 /q */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_PEXTRW_GdPqIb, BxOpcodeGroupSSE_0fc5R }, /* 0F C6 /q */ { BxPrefixSSE | BxImmediate_Ib, BX_IA_SHUFPS_VpsWpsIb, BxOpcodeGroupSSE_0fc6 }, /* 0F C7 /q */ { BxGroup9, BX_IA_ERROR, BxOpcodeInfo64G9qM }, /* 0F C8 /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F C9 /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F CA /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F CB /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F CC /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F CD /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F CE /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F CF /q */ { 0, BX_IA_BSWAP_RRX }, /* 0F D0 /q */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd0 }, /* 0F D1 /q */ { BxPrefixSSE, BX_IA_PSRLW_PqQq, BxOpcodeGroupSSE_0fd1 }, /* 0F D2 /q */ { BxPrefixSSE, BX_IA_PSRLD_PqQq, BxOpcodeGroupSSE_0fd2 }, /* 0F D3 /q */ { BxPrefixSSE, BX_IA_PSRLQ_PqQq, BxOpcodeGroupSSE_0fd3 }, /* 0F D4 /q */ { BxPrefixSSE, BX_IA_PADDQ_PqQq, BxOpcodeGroupSSE_0fd4 }, /* 0F D5 /q */ { BxPrefixSSE, BX_IA_PMULLW_PqQq, BxOpcodeGroupSSE_0fd5 }, /* 0F D6 /q */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fd6 }, /* 0F D7 /q */ { BxPrefixSSE, BX_IA_PMOVMSKB_GdPRq, BxOpcodeGroupSSE_0fd7R }, /* 0F D8 /q */ { BxPrefixSSE, BX_IA_PSUBUSB_PqQq, BxOpcodeGroupSSE_0fd8 }, /* 0F D9 /q */ { BxPrefixSSE, BX_IA_PSUBUSW_PqQq, BxOpcodeGroupSSE_0fd9 }, /* 0F DA /q */ { BxPrefixSSE, BX_IA_PMINUB_PqQq, BxOpcodeGroupSSE_0fda }, /* 0F DB /q */ { BxPrefixSSE, BX_IA_PAND_PqQq, BxOpcodeGroupSSE_0fdb }, /* 0F DC /q */ { BxPrefixSSE, BX_IA_PADDUSB_PqQq, BxOpcodeGroupSSE_0fdc }, /* 0F DD /q */ { BxPrefixSSE, BX_IA_PADDUSW_PqQq, BxOpcodeGroupSSE_0fdd }, /* 0F DE /q */ { BxPrefixSSE, BX_IA_PMAXUB_PqQq, BxOpcodeGroupSSE_0fde }, /* 0F DF /q */ { BxPrefixSSE, BX_IA_PANDN_PqQq, BxOpcodeGroupSSE_0fdf }, /* 0F E0 /q */ { BxPrefixSSE, BX_IA_PAVGB_PqQq, BxOpcodeGroupSSE_0fe0 }, /* 0F E1 /q */ { BxPrefixSSE, BX_IA_PSRAW_PqQq, BxOpcodeGroupSSE_0fe1 }, /* 0F E2 /q */ { BxPrefixSSE, BX_IA_PSRAD_PqQq, BxOpcodeGroupSSE_0fe2 }, /* 0F E3 /q */ { BxPrefixSSE, BX_IA_PAVGW_PqQq, BxOpcodeGroupSSE_0fe3 }, /* 0F E4 /q */ { BxPrefixSSE, BX_IA_PMULHUW_PqQq, BxOpcodeGroupSSE_0fe4 }, /* 0F E5 /q */ { BxPrefixSSE, BX_IA_PMULHW_PqQq, BxOpcodeGroupSSE_0fe5 }, /* 0F E6 /q */ { BxPrefixSSE, BX_IA_ERROR, BxOpcodeGroupSSE_0fe6 }, /* 0F E7 /q */ { BxPrefixSSE, BX_IA_MOVNTQ_MqPq, BxOpcodeGroupSSE_0fe7M }, /* 0F E8 /q */ { BxPrefixSSE, BX_IA_PSUBSB_PqQq, BxOpcodeGroupSSE_0fe8 }, /* 0F E9 /q */ { BxPrefixSSE, BX_IA_PSUBSW_PqQq, BxOpcodeGroupSSE_0fe9 }, /* 0F EA /q */ { BxPrefixSSE, BX_IA_PMINSW_PqQq, BxOpcodeGroupSSE_0fea }, /* 0F EB /q */ { BxPrefixSSE, BX_IA_POR_PqQq, BxOpcodeGroupSSE_0feb }, /* 0F EC /q */ { BxPrefixSSE, BX_IA_PADDSB_PqQq, BxOpcodeGroupSSE_0fec }, /* 0F ED /q */ { BxPrefixSSE, BX_IA_PADDSW_PqQq, BxOpcodeGroupSSE_0fed }, /* 0F EE /q */ { BxPrefixSSE, BX_IA_PMAXSW_PqQq, BxOpcodeGroupSSE_0fee }, /* 0F EF /q */ { BxPrefixSSE, BX_IA_PXOR_PqQq, BxOpcodeGroupSSE_0fef }, /* 0F F0 /q */ { BxPrefixSSEF2, BX_IA_LDDQU_VdqMdq }, /* 0F F1 /q */ { BxPrefixSSE, BX_IA_PSLLW_PqQq, BxOpcodeGroupSSE_0ff1 }, /* 0F F2 /q */ { BxPrefixSSE, BX_IA_PSLLD_PqQq, BxOpcodeGroupSSE_0ff2 }, /* 0F F3 /q */ { BxPrefixSSE, BX_IA_PSLLQ_PqQq, BxOpcodeGroupSSE_0ff3 }, /* 0F F4 /q */ { BxPrefixSSE, BX_IA_PMULUDQ_PqQq, BxOpcodeGroupSSE_0ff4 }, /* 0F F5 /q */ { BxPrefixSSE, BX_IA_PMADDWD_PqQq, BxOpcodeGroupSSE_0ff5 }, /* 0F F6 /q */ { BxPrefixSSE, BX_IA_PSADBW_PqQq, BxOpcodeGroupSSE_0ff6 }, /* 0F F7 /q */ { BxPrefixSSE, BX_IA_MASKMOVQ_PqPRq, BxOpcodeGroupSSE_0ff7R }, /* 0F F8 /q */ { BxPrefixSSE, BX_IA_PSUBB_PqQq, BxOpcodeGroupSSE_0ff8 }, /* 0F F9 /q */ { BxPrefixSSE, BX_IA_PSUBW_PqQq, BxOpcodeGroupSSE_0ff9 }, /* 0F FA /q */ { BxPrefixSSE, BX_IA_PSUBD_PqQq, BxOpcodeGroupSSE_0ffa }, /* 0F FB /q */ { BxPrefixSSE, BX_IA_PSUBQ_PqQq, BxOpcodeGroupSSE_0ffb }, /* 0F FC /q */ { BxPrefixSSE, BX_IA_PADDB_PqQq, BxOpcodeGroupSSE_0ffc }, /* 0F FD /q */ { BxPrefixSSE, BX_IA_PADDW_PqQq, BxOpcodeGroupSSE_0ffd }, /* 0F FE /q */ { BxPrefixSSE, BX_IA_PADDD_PqQq, BxOpcodeGroupSSE_0ffe }, /* 0F FF /q */ { 0, BX_IA_ERROR } }; int BX_CPP_AttrRegparmN(3) BX_CPU_C::fetchDecode64(const Bit8u *iptr, bxInstruction_c *i, unsigned remainingInPage) { if (remainingInPage > 15) remainingInPage = 15; unsigned remain = remainingInPage; // remain must be at least 1 unsigned b1, b2 = 0, ia_opcode = 0; bx_bool lock=0; unsigned offset = 512, rex_r = 0, rex_x = 0, rex_b = 0; unsigned rm = 0, mod = 0, nnn = 0, mod_mem = 0, rep = 0; unsigned seg = BX_SEG_REG_DS, seg_override = BX_SEG_REG_NULL; #define SSE_PREFIX_NONE 0 #define SSE_PREFIX_66 1 #define SSE_PREFIX_F3 2 #define SSE_PREFIX_F2 3 unsigned sse_prefix = SSE_PREFIX_NONE; unsigned rex_prefix = 0; int vvv = -1; #if BX_SUPPORT_AVX int had_vex = 0, had_xop = 0, use_vvv = 0; bx_bool vex_w = 0, vex_l = 0; #endif i->ResolveModrm = 0; i->init(/*os32*/ 1, // operand size 32 override defaults to 1 /*as32*/ 1, // address size 32 override defaults to 1 /*os64*/ 0, // operand size 64 override defaults to 0 /*as64*/ 1); // address size 64 override defaults to 1 fetch_b1: b1 = *iptr++; remain--; switch (b1) { case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: rex_prefix = b1; if (remain != 0) { goto fetch_b1; } return(-1); case 0x0f: // 2 byte escape if (remain != 0) { remain--; b1 = 0x100 | *iptr++; break; } return(-1); case 0xf2: // REPNE/REPNZ case 0xf3: // REP/REPE/REPZ rex_prefix = 0; sse_prefix = (b1 & 3) ^ 1; rep = b1 & 3; if (remain != 0) { goto fetch_b1; } return(-1); case 0x2e: // CS: case 0x26: // ES: case 0x36: // SS: case 0x3e: // DS: /* ignore segment override prefix */ rex_prefix = 0; if (remain != 0) { goto fetch_b1; } return(-1); case 0x64: // FS: case 0x65: // GS: rex_prefix = 0; seg_override = b1 & 0xf; if (remain != 0) { goto fetch_b1; } return(-1); case 0x66: // OpSize rex_prefix = 0; if(!sse_prefix) sse_prefix = SSE_PREFIX_66; i->setOs32B(0); offset = 0; if (remain != 0) { goto fetch_b1; } return(-1); case 0x67: // AddrSize rex_prefix = 0; i->clearAs64(); if (remain != 0) { goto fetch_b1; } return(-1); case 0xf0: // LOCK: rex_prefix = 0; lock = 1; if (remain != 0) { goto fetch_b1; } return(-1); default: break; } if (rex_prefix) { i->assertExtend8bit(); if (rex_prefix & 0x8) { i->assertOs64(); i->assertOs32(); offset = 512*2; } rex_r = ((rex_prefix & 0x4) << 1); rex_x = ((rex_prefix & 0x2) << 2); rex_b = ((rex_prefix & 0x1) << 3); } i->modRMForm.Id = 0; unsigned index = b1+offset; unsigned attr = BxOpcodeInfo64[index].Attr; bx_bool has_modrm = 0; #if BX_SUPPORT_AVX if ((attr & BxGroupX) == BxPrefixVEX) { // VEX had_vex = 1; if (sse_prefix | rex_prefix) had_vex = -1; if (! protected_mode()) had_vex = -1; unsigned vex, vex_opcext = 1; if (remain != 0) { remain--; vex = *iptr++; } else return(-1); rex_r = ((vex >> 4) & 0x8) ^ 0x8; if (b1 == 0xc4) { rex_x = ((vex >> 3) & 0x8) ^ 0x8; rex_b = ((vex >> 2) & 0x8) ^ 0x8; // decode 3-byte VEX prefix vex_opcext = vex & 0x1f; if (remain != 0) { remain--; vex = *iptr++; // fetch VEX3 } else return(-1); if (vex & 0x80) { vex_w = 1; i->assertOs64(); i->assertOs32(); } } vvv = 15 - ((vex >> 3) & 0xf); vex_l = (vex >> 2) & 0x1; i->setVL(BX_VL128 + vex_l); sse_prefix = vex & 0x3; if (remain != 0) { remain--; b1 = *iptr++; // fetch new b1 } else return(-1); b1 += 256 * vex_opcext; if (b1 < 256 || b1 >= 1024) had_vex = -1; else { if (b1 >= 512) has_modrm = 1; else has_modrm = BxOpcodeHasModrm64[b1]; } } else if (b1 == 0x8f && (*iptr & 0x08) == 0x08) { // 3 byte XOP prefix had_xop = 1; if (sse_prefix | rex_prefix) had_xop = -1; if (! protected_mode()) had_xop = -1; unsigned vex; if (remain != 0) { remain--; vex = *iptr++; // fetch XOP2 } else return(-1); rex_r = ((vex >> 4) & 0x8) ^ 0x8; rex_x = ((vex >> 3) & 0x8) ^ 0x8; rex_b = ((vex >> 2) & 0x8) ^ 0x8; unsigned xop_opcext = (vex & 0x1f) - 8; if (xop_opcext >= 3) had_xop = -1; if (remain != 0) { remain--; vex = *iptr++; // fetch XOP3 } else return(-1); if (vex & 0x80) { vex_w = 1; i->assertOs64(); i->assertOs32(); } vvv = 15 - ((vex >> 3) & 0xf); vex_l = (vex >> 2) & 0x1; i->setVL(BX_VL128 + vex_l); sse_prefix = vex & 0x3; if (sse_prefix) had_xop = -1; if (remain != 0) { remain--; b1 = *iptr++; // fetch new b1 } else return(-1); has_modrm = 1; b1 += 256 * xop_opcext; } else #endif { has_modrm = BxOpcodeHasModrm64[b1]; } if (has_modrm) { unsigned b3 = 0; // handle 3-byte escape if ((attr & BxGroupX) == Bx3ByteOp) { if (remain != 0) { remain--; b3 = *iptr++; } else return(-1); } // opcode requires modrm byte if (remain != 0) { remain--; b2 = *iptr++; } else return(-1); // Parse mod-nnn-rm and related bytes mod = b2 & 0xc0; nnn = ((b2 >> 3) & 0x7) | rex_r; rm = (b2 & 0x7) | rex_b; i->setFoo((b2 | (b1 << 8)) & 0x7ff); /* for x87 */ // MOVs with CRx and DRx always use register ops and ignore the mod field. if ((b1 & ~3) == 0x120) mod = 0xc0; if (mod == 0xc0) { // mod == 11b i->assertModC0(); goto modrm_done; } mod_mem = 1; i->setSibBase(rm); // initialize with rm to use BxResolve64Base i->setSibIndex(BX_NIL_REGISTER); // initialize displ32 with zero to include cases with no diplacement i->modRMForm.displ32u = 0; // note that mod==11b handled above if (i->as64L()) i->ResolveModrm = &BX_CPU_C::BxResolve64Base; else i->ResolveModrm = &BX_CPU_C::BxResolve32Base; if ((rm & 0x7) != 4) { // no s-i-b byte if (mod == 0x00) { // mod == 00b if ((rm & 0x7) == 5) { i->setSibBase(BX_64BIT_REG_RIP); goto get_32bit_displ; } // mod==00b, rm!=4, rm!=5 goto modrm_done; } // (mod == 0x40), mod==01b or (mod == 0x80), mod==10b seg = sreg_mod1or2_base32[rm]; } else { // mod!=11b, rm==4, s-i-b byte follows unsigned sib, base, index, scale; if (remain != 0) { sib = *iptr++; remain--; } else { return(-1); } base = (sib & 0x7) | rex_b; sib >>= 3; index = (sib & 0x7) | rex_x; sib >>= 3; scale = sib; i->setSibScale(scale); i->setSibBase(base); // this part is a little tricky - assign index value always, // it will be really used if the instruction is Gather. Others // assume that BxResolve32Base will do the right thing. i->setSibIndex(index); if (index != 4) { if (i->as64L()) i->ResolveModrm = &BX_CPU_C::BxResolve64BaseIndex; else i->ResolveModrm = &BX_CPU_C::BxResolve32BaseIndex; } if (mod == 0x00) { // mod==00b, rm==4 seg = sreg_mod0_base32[base]; if ((base & 0x7) == 5) { i->setSibBase(BX_NIL_REGISTER); goto get_32bit_displ; } // mod==00b, rm==4, base!=5 goto modrm_done; } // (mod == 0x40), mod==01b or (mod == 0x80), mod==10b seg = sreg_mod1or2_base32[base]; } // (mod == 0x40), mod==01b if (mod == 0x40) { if (remain != 0) { // 8 sign extended to 32 i->modRMForm.displ32u = (Bit8s) *iptr++; remain--; } else { return(-1); } } else { get_32bit_displ: // (mod == 0x80), mod==10b if (remain > 3) { i->modRMForm.displ32u = FetchDWORD(iptr); iptr += 4; remain -= 4; } else { return(-1); } } modrm_done: // Resolve ExecutePtr and additional opcode Attr const BxOpcodeInfo_t *OpcodeInfoPtr = &(BxOpcodeInfo64[index]); #if BX_SUPPORT_AVX if (had_vex != 0) { if (had_vex < 0) OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR else OpcodeInfoPtr = &BxOpcodeTableAVX[(b1-256) + 768*vex_l]; } else if (had_xop != 0) { if (had_xop < 0) OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR else OpcodeInfoPtr = &BxOpcodeTableXOP[b1 + 768*vex_l]; } #endif attr = OpcodeInfoPtr->Attr; while(attr & BxGroupX) { Bit32u group = attr & BxGroupX; attr &= ~BxGroupX; if (group < BxPrefixSSE) { /* For opcodes with only one allowed SSE prefix */ if (sse_prefix != (group >> 4)) { OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR } /* get additional attributes from group table */ attr |= OpcodeInfoPtr->Attr; break; } switch(group) { case BxGroupN: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn & 0x7]); break; case BxSplitGroupN: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[(nnn & 0x7) + (mod_mem << 3)]); break; #if BX_SUPPORT_AVX case BxSplitVexW: case BxSplitVexW64: BX_ASSERT(had_vex != 0 || had_xop != 0); OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[vex_w]); break; case BxSplitMod11B: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[mod_mem]); break; #endif case Bx3ByteOp: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[b3]); break; case BxOSizeGrp: OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[offset >> 9]); if (sse_prefix == SSE_PREFIX_66) sse_prefix = 0; break; case BxPrefixSSE: /* For SSE opcodes look into another table with the opcode prefixes (NONE, 0x66, 0xF3, 0xF2) */ if (sse_prefix) { OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[sse_prefix-1]); break; } continue; case BxFPEscape: if (mod_mem) OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[nnn & 0x7]); else OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[(b2 & 0x3f) + 8]); break; default: BX_PANIC(("fetchdecode64: Unknown opcode group %d", group)); } /* get additional attributes from group table */ attr |= OpcodeInfoPtr->Attr; } ia_opcode = OpcodeInfoPtr->IA; } else { // Opcode does not require a MODRM byte. // Note that a 2-byte opcode (0F XX) will jump to before // the if() above after fetching the 2nd byte, so this path is // taken in all cases if a modrm byte is NOT required. const BxOpcodeInfo_t *OpcodeInfoPtr = &(BxOpcodeInfo64[index]); #if BX_SUPPORT_AVX if (had_vex != 0) { if (had_vex < 0) OpcodeInfoPtr = &BxOpcodeGroupSSE_ERR[0]; // BX_IA_ERROR else OpcodeInfoPtr = &BxOpcodeTableAVX[(b1-256) + 768*vex_l]; } // XOP always has modrm byte BX_ASSERT(had_xop == 0); #endif if (b1 == 0x90 && sse_prefix == SSE_PREFIX_F3) { // attention: need to handle VEX separately, XOP never reach here ia_opcode = BX_IA_PAUSE; } else { unsigned group = attr & BxGroupX; if (group == BxPrefixSSE && sse_prefix) OpcodeInfoPtr = &(OpcodeInfoPtr->AnotherArray[sse_prefix-1]); ia_opcode = OpcodeInfoPtr->IA; rm = (b1 & 7) | rex_b; nnn = (b1 >> 3) & 7; } } if (lock) { // lock prefix invalid opcode // lock prefix not allowed or destination operand is not memory if (!mod_mem || !(attr & BxLockable)) { if (BX_CPUID_SUPPORT_CPU_EXTENSION(BX_CPU_ALT_MOV_CR8) && (ia_opcode == BX_IA_MOV_CR0Rq || ia_opcode == BX_IA_MOV_RqCR0)) { nnn = 8; // extend CR0 -> CR8 } else { BX_INFO(("LOCK prefix unallowed (op1=0x%x, modrm=0x%02x)", b1, b2)); // replace execution function with undefined-opcode ia_opcode = BX_IA_ERROR; } } } if (attr & BxRepeatable) i->setRepUsed(rep); unsigned imm_mode = attr & BxImmediate; if (imm_mode) { // make sure iptr was advanced after Ib(), Iw() and Id() switch (imm_mode) { case BxImmediate_I1: i->modRMForm.Ib = 1; break; case BxImmediate_Ib: if (remain != 0) { i->modRMForm.Ib = *iptr++; remain--; } else { return(-1); } break; case BxImmediate_Ib_SE: // Sign extend to OS size if (remain != 0) { Bit8s temp8s = *iptr; // this code works correctly both for LE and BE hosts if (i->os32L()) i->modRMForm.Id = (Bit32s) temp8s; else i->modRMForm.Iw = (Bit16s) temp8s; remain--; } else { return(-1); } break; case BxImmediate_BrOff8: if (remain != 0) { Bit8s temp8s = *iptr; i->modRMForm.Id = (Bit32s) temp8s; remain--; } else { return(-1); } break; case BxImmediate_Iw: if (remain > 1) { i->modRMForm.Iw = FetchWORD(iptr); iptr += 2; remain -= 2; } else { return(-1); } break; case BxImmediate_Id: if (remain > 3) { i->modRMForm.Id = FetchDWORD(iptr); iptr += 4; remain -= 4; } else { return(-1); } break; case BxImmediate_Iq: // MOV Rx,imm64 if (remain > 7) { i->IqForm.Iq = FetchQWORD(iptr); remain -= 8; } else { return(-1); } break; case BxImmediate_O: // For instructions which embed the address in the opcode. // There is only 64/32-bit addressing available in long64 mode. if (i->as64L()) { if (remain > 7) { i->IqForm.Iq = FetchQWORD(iptr); remain -= 8; } else return(-1); } else { // as32 if (remain > 3) { i->IqForm.Iq = (Bit64u) FetchDWORD(iptr); remain -= 4; } else return(-1); } break; default: BX_INFO(("b1 was %x", b1)); BX_PANIC(("fetchdecode64: imm_mode = %u", imm_mode)); } unsigned imm_mode2 = attr & BxImmediate2; if (imm_mode2) { if (imm_mode2 == BxImmediate_Ib2) { if (remain != 0) { i->modRMForm.Ib2 = *iptr; remain--; } else { return(-1); } } else { BX_INFO(("b1 was %x", b1)); BX_PANIC(("fetchdecode64: imm_mode2 = %u", imm_mode2)); } } } #if BX_SUPPORT_3DNOW if(b1 == 0x10f) ia_opcode = Bx3DNowOpcode[i->modRMForm.Ib]; #endif // assign sources for (unsigned n = 0; n <= 3; n++) { unsigned def = (unsigned) BxOpcodesTable[ia_opcode].src[n] & 0xf; #if BX_SUPPORT_AVX if (def == BX_SRC_RM_VIB) { def = (vex_w) ? BX_SRC_RM : BX_SRC_VIB; } else if (def == BX_SRC_VIB_RM) { def = (vex_w) ? BX_SRC_VIB : BX_SRC_RM; } else if (def == BX_SRC_RM_VVV) { def = (vex_w) ? BX_SRC_RM : BX_SRC_VVV; } else if (def == BX_SRC_VVV_RM) { def = (vex_w) ? BX_SRC_VVV : BX_SRC_RM; } #endif switch(def) { case BX_SRC_EAX: i->setSrcReg(n, 0); break; case BX_SRC_NNN: i->setSrcReg(n, nnn); break; case BX_SRC_RM: i->setSrcReg(n, mod_mem ? BX_TMP_REGISTER : rm); break; #if BX_SUPPORT_AVX case BX_SRC_MEM_NO_VVV: if (mod_mem) break; // else fall through case BX_SRC_VVV: i->setSrcReg(n, vvv); use_vvv = 1; break; case BX_SRC_VIB: i->setSrcReg(n, i->Ib() >> 4); break; #endif default: if (def != BX_SRC_NONE) BX_PANIC(("fetchdecode64: unknown definition %d for src %d", def, n)); } } // assign memory segment override if (! BX_NULL_SEG_REG(seg_override)) seg = seg_override; i->setSeg(seg); i->setILen(remainingInPage - remain); i->setIaOpcode(ia_opcode); #if BX_SUPPORT_AVX if (had_vex > 0 || had_xop > 0) { if (! use_vvv && vvv != 0) { ia_opcode = BX_IA_ERROR; } if ((attr & BxVexW0) != 0 && vex_w) { ia_opcode = BX_IA_ERROR; } if ((attr & BxVexW1) != 0 && !vex_w) { ia_opcode = BX_IA_ERROR; } } else { BX_ASSERT(! use_vvv); } #endif if (mod_mem) { i->execute = BxOpcodesTable[ia_opcode].execute1; i->handlers.execute2 = BxOpcodesTable[ia_opcode].execute2; if (ia_opcode == BX_IA_MOV_GqEq) { if (seg == BX_SEG_REG_SS) i->execute = &BX_CPU_C::MOV64S_GqEqM; } if (ia_opcode == BX_IA_MOV32_EdGd) { if (seg == BX_SEG_REG_SS) i->execute = &BX_CPU_C::MOV64S_EqGqM; } } else { i->execute = BxOpcodesTable[ia_opcode].execute2; i->handlers.execute2 = NULL; } BX_ASSERT(i->execute); Bit32u op_flags = BxOpcodesTable[ia_opcode].src[3]; if (! BX_CPU_THIS_PTR sse_ok) { if (op_flags & BX_PREPARE_SSE) { if (i->execute != &BX_CPU_C::BxError) i->execute = &BX_CPU_C::BxNoSSE; return(1); } } #if BX_SUPPORT_AVX if (! BX_CPU_THIS_PTR avx_ok) { if (op_flags & BX_PREPARE_AVX) { if (i->execute != &BX_CPU_C::BxError) i->execute = &BX_CPU_C::BxNoAVX; return(1); } } #endif if ((attr & BxTraceEnd) || ia_opcode == BX_IA_ERROR) return(1); return(0); } #endif /* if BX_SUPPORT_X86_64 */ bochs-2.6/cpu/svm.h0000644000175000017500000003272712020641453014112 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: svm.h 11033 2012-02-13 23:29:01Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef _BX_SVM_AMD_H_ #define _BX_SVM_AMD_H_ #if BX_SUPPORT_SVM #define BX_SVM_REVISION 0x01 /* FIXME: check what is real SVM revision */ enum SVM_intercept_codes { SVM_VMEXIT_CR0_READ = 0, SVM_VMEXIT_CR2_READ = 2, SVM_VMEXIT_CR3_READ = 3, SVM_VMEXIT_CR4_READ = 4, SVM_VMEXIT_CR8_READ = 8, SVM_VMEXIT_CR0_WRITE = 16, SVM_VMEXIT_CR2_WRITE = 18, SVM_VMEXIT_CR3_WRITE = 19, SVM_VMEXIT_CR4_WRITE = 20, SVM_VMEXIT_CR8_WRITE = 24, SVM_VMEXIT_DR0_READ = 32, SVM_VMEXIT_DR0_WRITE = 48, SVM_VMEXIT_EXCEPTION = 64, SVM_VMEXIT_INTR = 96, SVM_VMEXIT_NMI = 97, SVM_VMEXIT_SMI = 98, SVM_VMEXIT_INIT = 99, SVM_VMEXIT_VINTR = 100, SVM_VMEXIT_CR0_SEL_WRITE = 101, SVM_VMEXIT_IDTR_READ = 102, SVM_VMEXIT_GDTR_READ = 103, SVM_VMEXIT_LDTR_READ = 104, SVM_VMEXIT_TR_READ = 105, SVM_VMEXIT_IDTR_WRITE = 106, SVM_VMEXIT_GDTR_WRITE = 107, SVM_VMEXIT_LDTR_WRITE = 108, SVM_VMEXIT_TR_WRITE = 109, SVM_VMEXIT_RDTSC = 110, SVM_VMEXIT_RDPMC = 111, SVM_VMEXIT_PUSHF = 112, SVM_VMEXIT_POPF = 113, SVM_VMEXIT_CPUID = 114, SVM_VMEXIT_RSM = 115, SVM_VMEXIT_IRET = 116, SVM_VMEXIT_SOFTWARE_INTERRUPT = 117, SVM_VMEXIT_INVD = 118, SVM_VMEXIT_PAUSE = 119, SVM_VMEXIT_HLT = 120, SVM_VMEXIT_INVLPG = 121, SVM_VMEXIT_INVLPGA = 122, SVM_VMEXIT_IO = 123, SVM_VMEXIT_MSR = 124, SVM_VMEXIT_TASK_SWITCH = 125, SVM_VMEXIT_FERR_FREEZE = 126, SVM_VMEXIT_SHUTDOWN = 127, SVM_VMEXIT_VMRUN = 128, SVM_VMEXIT_VMMCALL = 129, SVM_VMEXIT_VMLOAD = 130, SVM_VMEXIT_VMSAVE = 131, SVM_VMEXIT_STGI = 132, SVM_VMEXIT_CLGI = 133, SVM_VMEXIT_SKINIT = 134, SVM_VMEXIT_RDTSCP = 135, SVM_VMEXIT_ICEBP = 136, SVM_VMEXIT_WBINVD = 137, SVM_VMEXIT_MONITOR = 138, SVM_VMEXIT_MWAIT = 139, SVM_VMEXIT_MWAIT_CONDITIONAL = 140, SVM_VMEXIT_XSETBV = 141, SVM_VMEXIT_NPF = 1024, }; #define SVM_VMEXIT_INVALID (-1) // ===================== // VMCB control fields // ===================== #define SVM_CONTROL16_INTERCEPT_CR_READ (0x000) #define SVM_CONTROL16_INTERCEPT_CR_WRITE (0x002) #define SVM_CONTROL16_INTERCEPT_DR_READ (0x004) #define SVM_CONTROL16_INTERCEPT_DR_WRITE (0x006) #define SVM_CONTROL32_INTERCEPT_EXCEPTIONS (0x008) #define SVM_CONTROL32_INTERCEPT1 (0x00c) #define SVM_CONTROL32_INTERCEPT2 (0x010) #define SVM_CONTROL16_PAUSE_FILTER_THRESHOLD (0x03c) #define SVM_CONTROL16_PAUSE_FILTER_COUNT (0x03e) #define SVM_CONTROL64_IOPM_BASE_PHY_ADDR (0x040) #define SVM_CONTROL64_MSRPM_BASE_PHY_ADDR (0x048) #define SVM_CONTROL64_TSC_OFFSET (0x050) #define SVM_CONTROL32_GUEST_ASID (0x058) #define SVM_CONTROL32_TLB_CONTROL (0x05c) #define SVM_CONTROL_VTPR (0x060) #define SVM_CONTROL_VIRQ (0x061) #define SVM_CONTROL_VINTR_PRIO_IGN_TPR (0x062) #define SVM_CONTROL_VINTR_MASKING (0x063) #define SVM_CONTROL_VINTR_VECTOR (0x064) #define SVM_CONTROL_INTERRUPT_SHADOW (0x068) #define SVM_CONTROL64_EXITCODE (0x070) #define SVM_CONTROL64_EXITINFO1 (0x078) #define SVM_CONTROL64_EXITINFO2 (0x080) #define SVM_CONTROL32_EXITINTINFO (0x088) #define SVM_CONTROL32_EXITINTINFO_ERROR_CODE (0x08c) #define SVM_CONTROL_NESTED_PAGING_ENABLE (0x090) #define SVM_CONTROL32_EVENT_INJECTION (0x0a8) #define SVM_CONTROL32_EVENT_INJECTION_ERRORCODE (0x0ac) #define SVM_CONTROL64_NESTED_PAGING_HOST_CR3 (0x0b0) #define SVM_CONTROL_LBR_VIRTUALIZATION_ENABLE (0x0b8) #define SVM_CONTROL32_VMCB_CLEAN_BITS (0x0c0) #define SVM_CONTROL64_NRIP (0x0c8) // ====================== // VMCB save state area // ====================== // ES #define SVM_GUEST_ES_SELECTOR (0x400) #define SVM_GUEST_ES_ATTR (0x402) #define SVM_GUEST_ES_LIMIT (0x404) #define SVM_GUEST_ES_BASE (0x408) // CS #define SVM_GUEST_CS_SELECTOR (0x410) #define SVM_GUEST_CS_ATTR (0x412) #define SVM_GUEST_CS_LIMIT (0x414) #define SVM_GUEST_CS_BASE (0x418) // SS #define SVM_GUEST_SS_SELECTOR (0x420) #define SVM_GUEST_SS_ATTR (0x422) #define SVM_GUEST_SS_LIMIT (0x424) #define SVM_GUEST_SS_BASE (0x428) // DS #define SVM_GUEST_DS_SELECTOR (0x430) #define SVM_GUEST_DS_ATTR (0x432) #define SVM_GUEST_DS_LIMIT (0x434) #define SVM_GUEST_DS_BASE (0x438) // FS #define SVM_GUEST_FS_SELECTOR (0x440) #define SVM_GUEST_FS_ATTR (0x442) #define SVM_GUEST_FS_LIMIT (0x444) #define SVM_GUEST_FS_BASE (0x448) // GS #define SVM_GUEST_GS_SELECTOR (0x450) #define SVM_GUEST_GS_ATTR (0x452) #define SVM_GUEST_GS_LIMIT (0x454) #define SVM_GUEST_GS_BASE (0x458) // GDTR #define SVM_GUEST_GDTR_LIMIT (0x464) #define SVM_GUEST_GDTR_BASE (0x468) // LDTR #define SVM_GUEST_LDTR_SELECTOR (0x470) #define SVM_GUEST_LDTR_ATTR (0x472) #define SVM_GUEST_LDTR_LIMIT (0x474) #define SVM_GUEST_LDTR_BASE (0x478) // IDTR #define SVM_GUEST_IDTR_LIMIT (0x484) #define SVM_GUEST_IDTR_BASE (0x488) // TR #define SVM_GUEST_TR_SELECTOR (0x490) #define SVM_GUEST_TR_ATTR (0x492) #define SVM_GUEST_TR_LIMIT (0x494) #define SVM_GUEST_TR_BASE (0x498) #define SVM_GUEST_CPL (0x4cb) #define SVM_GUEST_EFER_MSR (0x4d0) #define SVM_GUEST_EFER_MSR_HI (0x4d4) #define SVM_GUEST_CR4 (0x548) #define SVM_GUEST_CR4_HI (0x54c) #define SVM_GUEST_CR3 (0x550) #define SVM_GUEST_CR0 (0x558) #define SVM_GUEST_CR0_HI (0x55c) #define SVM_GUEST_DR7 (0x560) #define SVM_GUEST_DR7_HI (0x564) #define SVM_GUEST_DR6 (0x568) #define SVM_GUEST_DR6_HI (0x56c) #define SVM_GUEST_RFLAGS (0x570) #define SVM_GUEST_RFLAGS_HI (0x574) #define SVM_GUEST_RIP (0x578) #define SVM_GUEST_RSP (0x5d8) #define SVM_GUEST_RAX (0x5f8) #define SVM_GUEST_STAR_MSR (0x600) #define SVM_GUEST_LSTAR_MSR (0x608) #define SVM_GUEST_CSTAR_MSR (0x610) #define SVM_GUEST_SFMASK_MSR (0x618) #define SVM_GUEST_KERNEL_GSBASE_MSR (0x620) #define SVM_GUEST_SYSENTER_CS_MSR (0x628) #define SVM_GUEST_SYSENTER_ESP_MSR (0x630) #define SVM_GUEST_SYSENTER_EIP_MSR (0x638) #define SVM_GUEST_CR2 (0x640) #define SVM_GUEST_PAT (0x668) /* used only when nested paging is enabled */ #define SVM_GUEST_DBGCTL_MSR (0x670) #define SVM_GUEST_BR_FROM_MSR (0x678) #define SVM_GUEST_BR_TO_MSR (0x680) #define SVM_GUEST_LAST_EXCEPTION_FROM_MSR (0x688) #define SVM_GUEST_LAST_EXCEPTION_TO_MSR (0x690) typedef struct bx_SVM_HOST_STATE { bx_segment_reg_t sregs[4]; bx_global_segment_reg_t gdtr; bx_global_segment_reg_t idtr; bx_efer_t efer; bx_cr0_t cr0; bx_cr4_t cr4; bx_phy_address cr3; Bit32u eflags; Bit64u rip; Bit64u rsp; Bit64u rax; } SVM_HOST_STATE; typedef struct bx_SVM_GUEST_STATE { bx_segment_reg_t sregs[4]; bx_global_segment_reg_t gdtr; bx_global_segment_reg_t idtr; bx_efer_t efer; bx_cr0_t cr0; bx_cr4_t cr4; bx_address cr2; Bit32u dr6; Bit32u dr7; bx_phy_address cr3; Bit32u eflags; Bit64u rip; Bit64u rsp; Bit64u rax; unsigned cpl; bx_bool inhibit_interrupts; } SVM_GUEST_STATE; typedef struct bx_SVM_CONTROLS { Bit16u cr_rd_ctrl; Bit16u cr_wr_ctrl; Bit16u dr_rd_ctrl; Bit16u dr_wr_ctrl; Bit32u exceptions_intercept; Bit32u intercept_vector[2]; Bit32u exitintinfo; Bit32u exitintinfo_error_code; Bit32u eventinj; bx_phy_address iopm_base; bx_phy_address msrpm_base; Bit8u v_tpr; bx_bool v_irq; Bit8u v_intr_prio; bx_bool v_ignore_tpr; bx_bool v_intr_masking; Bit8u v_intr_vector; bx_bool nested_paging; Bit64u ncr3; } SVM_CONTROLS; #if defined(NEED_CPU_REG_SHORTCUTS) #define SVM_V_TPR (BX_CPU_THIS_PTR vmcb.ctrls.v_tpr) #define SVM_V_IRQ (BX_CPU_THIS_PTR vmcb.ctrls.v_irq) #define SVM_V_INTR_PRIO (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_prio) #define SVM_V_IGNORE_TPR (BX_CPU_THIS_PTR vmcb.ctrls.v_ignore_tpr) #define SVM_V_INTR_MASKING (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_masking) #define SVM_V_INTR_VECTOR (BX_CPU_THIS_PTR vmcb.ctrls.v_intr_vector) #define SVM_HOST_IF (BX_CPU_THIS_PTR vmcb.host_state.eflags & EFlagsIFMask) #endif typedef struct bx_VMCB_CACHE { SVM_HOST_STATE host_state; SVM_CONTROLS ctrls; } VMCB_CACHE; // ======================== // SVM intercept controls // ======================== #define SVM_INTERCEPT0_INTR (0) #define SVM_INTERCEPT0_NMI (1) #define SVM_INTERCEPT0_SMI (2) #define SVM_INTERCEPT0_INIT (3) #define SVM_INTERCEPT0_VINTR (4) #define SVM_INTERCEPT0_CR0_WRITE_NO_TS_MP (5) #define SVM_INTERCEPT0_IDTR_READ (6) #define SVM_INTERCEPT0_GDTR_READ (7) #define SVM_INTERCEPT0_LDTR_READ (8) #define SVM_INTERCEPT0_TR_READ (9) #define SVM_INTERCEPT0_IDTR_WRITE (10) #define SVM_INTERCEPT0_GDTR_WRITE (11) #define SVM_INTERCEPT0_LDTR_WRITE (12) #define SVM_INTERCEPT0_TR_WRITE (13) #define SVM_INTERCEPT0_RDTSC (14) #define SVM_INTERCEPT0_RDPMC (15) #define SVM_INTERCEPT0_PUSHF (16) #define SVM_INTERCEPT0_POPF (17) #define SVM_INTERCEPT0_CPUID (18) #define SVM_INTERCEPT0_RSM (19) #define SVM_INTERCEPT0_IRET (20) #define SVM_INTERCEPT0_SOFTINT (21) #define SVM_INTERCEPT0_INVD (22) #define SVM_INTERCEPT0_PAUSE (23) #define SVM_INTERCEPT0_HLT (24) #define SVM_INTERCEPT0_INVLPG (25) #define SVM_INTERCEPT0_INVLPGA (26) #define SVM_INTERCEPT0_IO (27) #define SVM_INTERCEPT0_MSR (28) #define SVM_INTERCEPT0_TASK_SWITCH (29) #define SVM_INTERCEPT0_FERR_FREEZE (30) #define SVM_INTERCEPT0_SHUTDOWN (31) #define SVM_INTERCEPT1_VMRUN (32) #define SVM_INTERCEPT1_VMMCALL (33) #define SVM_INTERCEPT1_VMLOAD (34) #define SVM_INTERCEPT1_VMSAVE (35) #define SVM_INTERCEPT1_STGI (36) #define SVM_INTERCEPT1_CLGI (37) #define SVM_INTERCEPT1_SKINIT (38) #define SVM_INTERCEPT1_RDTSCP (39) #define SVM_INTERCEPT1_ICEBP (40) #define SVM_INTERCEPT1_WBINVD (41) #define SVM_INTERCEPT1_MONITOR (42) #define SVM_INTERCEPT1_MWAIT (43) #define SVM_INTERCEPT1_MWAIT_ARMED (44) #define SVM_INTERCEPT1_XSETBV (45) #define SVM_INTERCEPT(intercept_bitnum) \ (BX_CPU_THIS_PTR vmcb.ctrls.intercept_vector[intercept_bitnum / 32] & (1 << (intercept_bitnum & 31))) #define SVM_EXCEPTION_INTERCEPTED(vector) \ (BX_CPU_THIS_PTR vmcb.ctrls.exceptions_intercept & (1<<(vector))) #define SVM_CR_READ_INTERCEPTED(reg_num) \ (BX_CPU_THIS_PTR vmcb.ctrls.cr_rd_ctrl & (1<<(reg_num))) #define SVM_CR_WRITE_INTERCEPTED(reg_num) \ (BX_CPU_THIS_PTR vmcb.ctrls.cr_wr_ctrl & (1<<(reg_num))) #define SVM_DR_READ_INTERCEPTED(reg_num) \ (BX_CPU_THIS_PTR vmcb.ctrls.dr_rd_ctrl & (1<<(reg_num))) #define SVM_DR_WRITE_INTERCEPTED(reg_num) \ (BX_CPU_THIS_PTR vmcb.ctrls.dr_wr_ctrl & (1<<(reg_num))) #define SVM_NESTED_PAGING_ENABLED (BX_CPU_THIS_PTR vmcb.ctrls.nested_paging) #endif // BX_SUPPORT_SVM #endif // _BX_SVM_AMD_H_ bochs-2.6/cpu/icache.cc0000644000175000017500000002136012020641453014646 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: icache.cc 11356 2012-08-21 19:58:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2011 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #include "param_names.h" bxPageWriteStampTable pageWriteStampTable; void flushICaches(void) { for (unsigned i=0; iiCache.flushICacheEntries(); BX_CPU(i)->async_event |= BX_ASYNC_EVENT_STOP_TRACE; } pageWriteStampTable.resetWriteStamps(); } void handleSMC(bx_phy_address pAddr, Bit32u mask) { for (unsigned i=0; iasync_event |= BX_ASYNC_EVENT_STOP_TRACE; BX_CPU(i)->iCache.handleSMC(pAddr, mask); } } #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS BX_INSF_TYPE BX_CPU_C::BxEndTrace(bxInstruction_c *i) { // do nothing, return to main cpu_loop } void genDummyICacheEntry(bxInstruction_c *i) { i->setILen(0); i->setIaOpcode(BX_INSERTED_OPCODE); i->execute = &BX_CPU_C::BxEndTrace; } #endif bxICacheEntry_c* BX_CPU_C::serveICacheMiss(bxICacheEntry_c *entry, Bit32u eipBiased, bx_phy_address pAddr) { bxICacheEntry_c *vc_hit = BX_CPU_THIS_PTR iCache.lookup_victim_cache(pAddr, BX_CPU_THIS_PTR fetchModeMask); if (vc_hit) { return vc_hit; } BX_CPU_THIS_PTR iCache.victim_entry(entry, BX_CPU_THIS_PTR fetchModeMask); BX_CPU_THIS_PTR iCache.alloc_trace(entry); // Cache miss. We weren't so lucky, but let's be optimistic - try to build // trace from incoming instruction bytes stream ! entry->pAddr = pAddr; entry->traceMask = 0; unsigned remainingInPage = BX_CPU_THIS_PTR eipPageWindowSize - eipBiased; const Bit8u *fetchPtr = BX_CPU_THIS_PTR eipFetchPtr + eipBiased; int ret; bxInstruction_c *i = entry->i; Bit32u pageOffset = PAGE_OFFSET((Bit32u) pAddr); Bit32u traceMask = 0; // Don't allow traces longer than cpu_loop can execute static unsigned quantum = #if BX_SUPPORT_SMP (BX_SMP_PROCESSORS > 1) ? SIM->get_param_num(BXPN_SMP_QUANTUM)->get() : #endif BX_MAX_TRACE_LENGTH; for (unsigned n=0;n < quantum;n++) { #if BX_SUPPORT_X86_64 if (BX_CPU_THIS_PTR cpu_mode == BX_MODE_LONG_64) ret = fetchDecode64(fetchPtr, i, remainingInPage); else #endif ret = fetchDecode32(fetchPtr, i, remainingInPage); if (ret < 0) { // Fetching instruction on segment/page boundary if (n > 0) { // The trace is already valid, it has several instructions inside, // in this case just drop the boundary instruction and stop // tracing. break; } // First instruction is boundary fetch, leave the trace cache entry // invalid for now because boundaryFetch() can fault entry->pAddr = ~entry->pAddr; entry->tlen = 1; boundaryFetch(fetchPtr, remainingInPage, i); // Add the instruction to trace cache entry->pAddr = ~entry->pAddr; entry->traceMask = 0x80000000; /* last line in page */ pageWriteStampTable.markICacheMask(entry->pAddr, entry->traceMask); pageWriteStampTable.markICacheMask(BX_CPU_THIS_PTR pAddrFetchPage, 0x1); #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS entry->tlen++; /* Add the inserted end of trace opcode */ genDummyICacheEntry(++i); #endif BX_CPU_THIS_PTR iCache.commit_page_split_trace(BX_CPU_THIS_PTR pAddrFetchPage, entry); return entry; } // add instruction to the trace unsigned iLen = i->ilen(); entry->tlen++; #ifdef BX_INSTR_STORE_OPCODE_BYTES i->set_opcode_bytes(fetchPtr); #endif BX_INSTR_OPCODE(BX_CPU_ID, i, fetchPtr, iLen, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, long64_mode()); i++; traceMask |= 1 << (pageOffset >> 7); traceMask |= 1 << ((pageOffset + iLen - 1) >> 7); // continue to the next instruction remainingInPage -= iLen; if (ret != 0 /* stop trace indication */ || remainingInPage == 0) break; pAddr += iLen; pageOffset += iLen; fetchPtr += iLen; // try to find a trace starting from current pAddr and merge if (remainingInPage >= 15) { // avoid merging with page split trace if (mergeTraces(entry, i, pAddr)) { entry->traceMask |= traceMask; pageWriteStampTable.markICacheMask(pAddr, entry->traceMask); BX_CPU_THIS_PTR iCache.commit_trace(entry->tlen); return entry; } } } //BX_INFO(("commit trace %08x len=%d mask %08x", (Bit32u) entry->pAddr, entry->tlen, pageWriteStampTable.getFineGranularityMapping(entry->pAddr))); entry->traceMask |= traceMask; pageWriteStampTable.markICacheMask(pAddr, entry->traceMask); #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS entry->tlen++; /* Add the inserted end of trace opcode */ genDummyICacheEntry(i); #endif BX_CPU_THIS_PTR iCache.commit_trace(entry->tlen); return entry; } bx_bool BX_CPU_C::mergeTraces(bxICacheEntry_c *entry, bxInstruction_c *i, bx_phy_address pAddr) { bxICacheEntry_c *e = BX_CPU_THIS_PTR iCache.get_entry(pAddr, BX_CPU_THIS_PTR fetchModeMask); if (e->pAddr == pAddr) { // determine max amount of instruction to take from another entry unsigned max_length = e->tlen; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS if (max_length + entry->tlen > BX_MAX_TRACE_LENGTH) return 0; #else if (max_length + entry->tlen > BX_MAX_TRACE_LENGTH) max_length = BX_MAX_TRACE_LENGTH - entry->tlen; if(max_length == 0) return 0; #endif memcpy(i, e->i, sizeof(bxInstruction_c)*max_length); entry->tlen += max_length; BX_ASSERT(entry->tlen <= BX_MAX_TRACE_LENGTH); entry->traceMask |= e->traceMask; return 1; } return 0; } void BX_CPU_C::boundaryFetch(const Bit8u *fetchPtr, unsigned remainingInPage, bxInstruction_c *i) { unsigned j, k; Bit8u fetchBuffer[32]; int ret; if (remainingInPage >= 15) { BX_ERROR(("boundaryFetch #GP(0): too many instruction prefixes")); exception(BX_GP_EXCEPTION, 0); } // Read all leftover bytes in current page up to boundary. for (j=0; jset_opcode_bytes(fetchBuffer); #endif BX_INSTR_OPCODE(BX_CPU_ID, i, fetchBuffer, i->ilen(), BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.d_b, long64_mode()); } bochs-2.6/cpu/apic.h0000644000175000017500000001675412020641453014223 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: apic.h 11203 2012-06-04 14:27:34Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2002-2012 Zwane Mwaikambo, Stanislav Shwartsman // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_CPU_APIC_H #define BX_CPU_APIC_H 1 #if BX_SUPPORT_APIC #define APIC_LEVEL_TRIGGERED 1 #define APIC_EDGE_TRIGGERED 0 #define BX_LAPIC_BASE_ADDR 0xfee00000 // default Local APIC address #define BX_NUM_LOCAL_APICS BX_SMP_PROCESSORS #define BX_LAPIC_MAX_INTS 256 #define BX_APIC_GLOBALLY_DISABLED 0 #define BX_APIC_STATE_INVALID 1 #define BX_APIC_XAPIC_MODE 2 #define BX_APIC_X2APIC_MODE 3 #define BX_XAPIC_EXT_SUPPORT_IER (1 << 0) #define BX_XAPIC_EXT_SUPPORT_SEOI (1 << 1) typedef Bit32u apic_dest_t; /* same definition in ioapic.h */ class BOCHSAPI bx_local_apic_c : public logfunctions { bx_phy_address base_addr; unsigned mode; bx_bool xapic; #if BX_CPU_LEVEL >= 6 Bit32u xapic_ext; // enabled extended XAPIC features #endif Bit32u apic_id; // 4 bit in legacy mode, 8 bit in XAPIC mode // 32 bit in X2APIC mode Bit32u apic_version_id; bx_bool software_enabled; Bit8u spurious_vector; bx_bool focus_disable; Bit32u task_priority; // Task priority (TPR) Bit32u ldr; // Logical destination (LDR) Bit32u dest_format; // Destination format (DFR) // ISR=in-service register. When an IRR bit is cleared, the corresponding // bit in ISR is set. Bit8u isr[BX_LAPIC_MAX_INTS]; // TMR=trigger mode register. Cleared for edge-triggered interrupts // and set for level-triggered interrupts. If set, local APIC must send // EOI message to all other APICs. Bit8u tmr[BX_LAPIC_MAX_INTS]; // IRR=interrupt request register. When an interrupt is triggered by // the I/O APIC or another processor, it sets a bit in irr. The bit is // cleared when the interrupt is acknowledged by the processor. Bit8u irr[BX_LAPIC_MAX_INTS]; #if BX_CPU_LEVEL >= 6 // IER=interrupt enable register. Only vectors that are enabled in IER // participare in APIC's computation of highest priority pending interrupt. Bit8u ier[BX_LAPIC_MAX_INTS]; #endif #define APIC_ERR_ILLEGAL_ADDR 0x80 #define APIC_ERR_RX_ILLEGAL_VEC 0x40 #define APIC_ERR_TX_ILLEGAL_VEC 0x20 #define X2APIC_ERR_REDIRECTIBLE_IPI 0x08 #define APIC_ERR_RX_ACCEPT_ERR 0x08 #define APIC_ERR_TX_ACCEPT_ERR 0x04 #define APIC_ERR_RX_CHECKSUM 0x02 #define APIC_ERR_TX_CHECKSUM 0x01 // Error status Register (ESR) Bit32u error_status, shadow_error_status; Bit32u icr_hi; // Interrupt command register (ICR) Bit32u icr_lo; #define APIC_LVT_ENTRIES 6 Bit32u lvt[APIC_LVT_ENTRIES]; #define APIC_LVT_TIMER 0 #define APIC_LVT_THERMAL 1 #define APIC_LVT_PERFMON 2 #define APIC_LVT_LINT0 3 #define APIC_LVT_LINT1 4 #define APIC_LVT_ERROR 5 Bit32u timer_initial; // Initial timer count (in order to reload periodic timer) Bit32u timer_current; // Current timer count Bit64u ticksInitial; // Timer value when it started to count, also holds TSC-Deadline value Bit32u timer_divconf; // Timer divide configuration register Bit32u timer_divide_factor; // Internal timer state, not accessible from bus bx_bool timer_active; int timer_handle; /* APIC delivery modes */ #define APIC_DM_FIXED 0 #define APIC_DM_LOWPRI 1 #define APIC_DM_SMI 2 /* RESERVED 3 */ #define APIC_DM_NMI 4 #define APIC_DM_INIT 5 #define APIC_DM_SIPI 6 #define APIC_DM_EXTINT 7 #if BX_SUPPORT_VMX >= 2 int vmx_timer_handle; Bit32u vmx_preemption_timer_value; Bit64u vmx_preemption_timer_initial; //The value of system tick when set the timer (absolute value) Bit64u vmx_preemption_timer_fire; //The value of system tick when fire the exception (absolute value) Bit32u vmx_preemption_timer_rate; //rate stated in MSR_VMX_MISC bx_bool vmx_timer_active; #endif BX_CPU_C *cpu; public: bx_bool INTR; bx_local_apic_c(BX_CPU_C *cpu, unsigned id); ~bx_local_apic_c() { } void reset(unsigned type); bx_phy_address get_base(void) const { return base_addr; } void set_base(bx_phy_address newbase); Bit32u get_id() const { return apic_id; } bx_bool is_xapic() const { return xapic; } bx_bool is_selected(bx_phy_address addr); void read(bx_phy_address addr, void *data, unsigned len); void write(bx_phy_address addr, void *data, unsigned len); void write_aligned(bx_phy_address addr, Bit32u data); Bit32u read_aligned(bx_phy_address address); #if BX_CPU_LEVEL >= 6 bx_bool read_x2apic(unsigned index, Bit64u *msr); bx_bool write_x2apic(unsigned index, Bit32u msr_hi, Bit32u msr_lo); #endif // on local APIC, trigger means raise the CPU's INTR line. For now // I also have to raise pc_system.INTR but that should be replaced // with the cpu-specific INTR signals. void trigger_irq(Bit8u vector, unsigned trigger_mode, bx_bool bypass_irr_isr = 0); void untrigger_irq(Bit8u vector, unsigned trigger_mode); Bit8u acknowledge_int(void); // only the local CPU should call this int highest_priority_int(Bit8u *array); void receive_EOI(Bit32u value); void send_ipi(apic_dest_t dest, Bit32u lo_cmd); void write_spurious_interrupt_register(Bit32u value); void service_local_apic(void); void print_status(void); bx_bool match_logical_addr(apic_dest_t address); bx_bool deliver(Bit8u vector, Bit8u delivery_mode, Bit8u trig_mode); Bit8u get_tpr(void) { return task_priority; } void set_tpr(Bit8u tpr); Bit8u get_ppr(void); Bit8u get_apr(void); bx_bool is_focus(Bit8u vector); void set_lvt_entry(unsigned apic_reg, Bit32u val); static void periodic_smf(void *); void periodic(void); void set_divide_configuration(Bit32u value); void set_initial_timer_count(Bit32u value); Bit32u get_current_timer_count(void); #if BX_CPU_LEVEL >= 6 Bit64u get_tsc_deadline(void); void set_tsc_deadline(Bit64u value); void receive_SEOI(Bit8u vec); void enable_xapic_extensions(void); #endif void startup_msg(Bit8u vector); void register_state(bx_param_c *parent); #if BX_SUPPORT_VMX >= 2 Bit32u read_vmx_preemption_timer(void); void set_vmx_preemption_timer(Bit32u value); void deactivate_vmx_preemption_timer(void); static void vmx_preemption_timer_expired(void *); #endif }; int apic_bus_deliver_lowest_priority(Bit8u vector, apic_dest_t dest, bx_bool trig_mode, bx_bool broadcast); BOCHSAPI_MSVCONLY int apic_bus_deliver_interrupt(Bit8u vector, apic_dest_t dest, Bit8u delivery_mode, bx_bool logical_dest, bx_bool level, bx_bool trig_mode); int apic_bus_broadcast_interrupt(Bit8u vector, Bit8u delivery_mode, bx_bool trig_mode, int exclude_cpu); #endif // if BX_SUPPORT_APIC #endif bochs-2.6/cpu/data_xfer32.cc0000644000175000017500000002532112020641453015535 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: data_xfer32.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_ERXEAX(bxInstruction_c *i) { #if BX_SUPPORT_X86_64 if (i->dst() == 0) { // 'xchg eax, eax' is NOP even in 64-bit mode BX_NEXT_INSTR(i); } #endif Bit32u temp32 = EAX; RAX = BX_READ_32BIT_REG(i->dst()); BX_WRITE_32BIT_REGZ(i->dst(), temp32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_ERXId(bxInstruction_c *i) { BX_WRITE_32BIT_REGZ(i->dst(), i->Id()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV32_EdGdM(bxInstruction_c *i) { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword_32(i->seg(), eaddr, BX_READ_32BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV32S_EdGdM(bxInstruction_c *i) { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); stack_write_dword(eaddr, BX_READ_32BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_GdEdR(bxInstruction_c *i) { BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV32_GdEdM(bxInstruction_c *i) { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u val32 = read_virtual_dword_32(i->seg(), eaddr); BX_WRITE_32BIT_REGZ(i->dst(), val32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV32S_GdEdM(bxInstruction_c *i) { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u val32 = stack_read_dword(eaddr); BX_WRITE_32BIT_REGZ(i->dst(), val32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LEA_GdM(bxInstruction_c *i) { Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); BX_WRITE_32BIT_REGZ(i->dst(), eaddr); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EAXOd(bxInstruction_c *i) { RAX = read_virtual_dword_32(i->seg(), i->Id()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_OdEAX(bxInstruction_c *i) { write_virtual_dword_32(i->seg(), i->Id(), EAX); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOV_EdIdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); write_virtual_dword(i->seg(), eaddr, i->Id()); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GdEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op2_8 = read_virtual_byte(i->seg(), eaddr); /* zero extend byte op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GdEbR(bxInstruction_c *i) { Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); /* zero extend byte op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GdEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op2_16 = read_virtual_word(i->seg(), eaddr); /* zero extend word op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVZX_GdEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* zero extend word op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit32u) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GdEbM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit8u op2_8 = read_virtual_byte(i->seg(), eaddr); /* sign extend byte op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit8s) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GdEbR(bxInstruction_c *i) { Bit8u op2_8 = BX_READ_8BIT_REGx(i->src(), i->extend8bitL()); /* sign extend byte op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit8s) op2_8); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GdEwM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u op2_16 = read_virtual_word(i->seg(), eaddr); /* sign extend word op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit16s) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::MOVSX_GdEwR(bxInstruction_c *i) { Bit16u op2_16 = BX_READ_16BIT_REG(i->src()); /* sign extend word op2 into dword op1 */ BX_WRITE_32BIT_REGZ(i->dst(), (Bit16s) op2_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EdGdM(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit32u op1_32 = read_RMW_virtual_dword(i->seg(), eaddr); Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); write_RMW_virtual_dword(op2_32); BX_WRITE_32BIT_REGZ(i->src(), op1_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::XCHG_EdGdR(bxInstruction_c *i) { Bit32u op1_32 = BX_READ_32BIT_REG(i->dst()); Bit32u op2_32 = BX_READ_32BIT_REG(i->src()); BX_WRITE_32BIT_REGZ(i->src(), op1_32); BX_WRITE_32BIT_REGZ(i->dst(), op2_32); BX_NEXT_INSTR(i); } // Note: CMOV accesses a memory source operand (read), regardless // of whether condition is true or not. Thus, exceptions may // occur even if the MOV does not take place. BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVO_GdEdR(bxInstruction_c *i) { if (get_OF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNO_GdEdR(bxInstruction_c *i) { if (!get_OF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVB_GdEdR(bxInstruction_c *i) { if (get_CF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNB_GdEdR(bxInstruction_c *i) { if (!get_CF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVZ_GdEdR(bxInstruction_c *i) { if (get_ZF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNZ_GdEdR(bxInstruction_c *i) { if (!get_ZF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVBE_GdEdR(bxInstruction_c *i) { if (get_CF() || get_ZF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNBE_GdEdR(bxInstruction_c *i) { if (! (get_CF() || get_ZF())) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVS_GdEdR(bxInstruction_c *i) { if (get_SF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNS_GdEdR(bxInstruction_c *i) { if (!get_SF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVP_GdEdR(bxInstruction_c *i) { if (get_PF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNP_GdEdR(bxInstruction_c *i) { if (!get_PF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVL_GdEdR(bxInstruction_c *i) { if (getB_SF() != getB_OF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNL_GdEdR(bxInstruction_c *i) { if (getB_SF() == getB_OF()) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVLE_GdEdR(bxInstruction_c *i) { if (get_ZF() || (getB_SF() != getB_OF())) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMOVNLE_GdEdR(bxInstruction_c *i) { if (! get_ZF() && (getB_SF() == getB_OF())) BX_WRITE_32BIT_REGZ(i->dst(), BX_READ_32BIT_REG(i->src())); BX_CLEAR_64BIT_HIGH(i->dst()); // always clear upper part of the register BX_NEXT_INSTR(i); } bochs-2.6/cpu/segment_ctrl.cc0000644000175000017500000001540612020641453016124 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: segment_ctrl.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR // LES/LDS can't be called from long64 mode BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LES_GwMp(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u reg_16 = read_virtual_word_32(i->seg(), eaddr); Bit16u es = read_virtual_word_32(i->seg(), (eaddr + 2) & i->asize_mask()); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES], es); BX_WRITE_16BIT_REG(i->dst(), reg_16); BX_NEXT_INSTR(i); } // LES/LDS can't be called from long64 mode BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LES_GdMp(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u es = read_virtual_word_32(i->seg(), (eaddr + 4) & i->asize_mask()); Bit32u reg_32 = read_virtual_dword_32(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_ES], es); BX_WRITE_32BIT_REGZ(i->dst(), reg_32); BX_NEXT_INSTR(i); } // LES/LDS can't be called from long64 mode BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LDS_GwMp(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u reg_16 = read_virtual_word_32(i->seg(), eaddr); Bit16u ds = read_virtual_word_32(i->seg(), (eaddr + 2) & i->asize_mask()); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS], ds); BX_WRITE_16BIT_REG(i->dst(), reg_16); BX_NEXT_INSTR(i); } // LES/LDS can't be called from long64 mode BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LDS_GdMp(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); Bit32u eaddr = (Bit32u) BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u ds = read_virtual_word_32(i->seg(), (eaddr + 4) & i->asize_mask()); Bit32u reg_32 = read_virtual_dword_32(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_DS], ds); BX_WRITE_32BIT_REGZ(i->dst(), reg_32); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LFS_GwMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u reg_16 = read_virtual_word(i->seg(), eaddr); Bit16u fs = read_virtual_word(i->seg(), (eaddr + 2) & i->asize_mask()); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS], fs); BX_WRITE_16BIT_REG(i->dst(), reg_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LFS_GdMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u fs = read_virtual_word(i->seg(), (eaddr + 4) & i->asize_mask()); Bit32u reg_32 = read_virtual_dword(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS], fs); BX_WRITE_32BIT_REGZ(i->dst(), reg_32); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LFS_GqMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u fs = read_virtual_word_64(i->seg(), (eaddr + 8) & i->asize_mask()); Bit64u reg_64 = read_virtual_qword_64(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_FS], fs); BX_WRITE_64BIT_REG(i->dst(), reg_64); BX_NEXT_INSTR(i); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LGS_GwMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u reg_16 = read_virtual_word(i->seg(), eaddr); Bit16u gs = read_virtual_word(i->seg(), (eaddr + 2) & i->asize_mask()); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS], gs); BX_WRITE_16BIT_REG(i->dst(), reg_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LGS_GdMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u gs = read_virtual_word(i->seg(), (eaddr + 4) & i->asize_mask()); Bit32u reg_32 = read_virtual_dword(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS], gs); BX_WRITE_32BIT_REGZ(i->dst(), reg_32); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LGS_GqMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u gs = read_virtual_word_64(i->seg(), (eaddr + 8) & i->asize_mask()); Bit64u reg_64 = read_virtual_qword_64(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_GS], gs); BX_WRITE_64BIT_REG(i->dst(), reg_64); BX_NEXT_INSTR(i); } #endif BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LSS_GwMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u reg_16 = read_virtual_word(i->seg(), eaddr); Bit16u ss = read_virtual_word(i->seg(), (eaddr + 2) & i->asize_mask()); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], ss); BX_WRITE_16BIT_REG(i->dst(), reg_16); BX_NEXT_INSTR(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LSS_GdMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u ss = read_virtual_word(i->seg(), (eaddr + 4) & i->asize_mask()); Bit32u reg_32 = read_virtual_dword(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], ss); BX_WRITE_32BIT_REGZ(i->dst(), reg_32); BX_NEXT_INSTR(i); } #if BX_SUPPORT_X86_64 BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LSS_GqMp(bxInstruction_c *i) { bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); Bit16u ss = read_virtual_word_64(i->seg(), (eaddr + 8) & i->asize_mask()); Bit64u reg_64 = read_virtual_qword_64(i->seg(), eaddr); load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS], ss); BX_WRITE_64BIT_REG(i->dst(), reg_64); BX_NEXT_INSTR(i); } #endif bochs-2.6/cpu/ctrl_xfer16.cc0000644000175000017500000004530612020641453015577 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ctrl_xfer16.cc 11356 2012-08-21 19:58:41Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR BX_CPP_INLINE void BX_CPP_AttrRegparmN(1) BX_CPU_C::branch_near16(Bit16u new_IP) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); // check always, not only in protected mode if (new_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("branch_near16: offset outside of CS limits")); exception(BX_GP_EXCEPTION, 0); } EIP = new_IP; #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS == 0 // assert magic async_event to stop trace execution BX_CPU_THIS_PTR async_event |= BX_ASYNC_EVENT_STOP_TRACE; #endif } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear16_Iw(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif RSP_SPECULATIVE; Bit16u return_IP = pop_16(); if (return_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("RETnear16_Iw: IP > limit")); exception(BX_GP_EXCEPTION, 0); } EIP = return_IP; Bit16u imm16 = i->Iw(); if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) /* 32bit stack */ ESP += imm16; else SP += imm16; RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETnear16(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif RSP_SPECULATIVE; Bit16u return_IP = pop_16(); if (return_IP > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("RETnear16: IP > limit")); exception(BX_GP_EXCEPTION, 0); } EIP = return_IP; RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::RETfar16_Iw(bxInstruction_c *i) { Bit16u ip, cs_raw; invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_ret; #endif Bit16s imm16 = (Bit16s) i->Iw(); if (protected_mode()) { return_protected(i, imm16); goto done; } RSP_SPECULATIVE; ip = pop_16(); cs_raw = pop_16(); // CS.LIMIT can't change when in real/v8086 mode if (ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("RETfar16_Iw: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = (Bit32u) ip; if (BX_CPU_THIS_PTR sregs[BX_SEG_REG_SS].cache.u.segment.d_b) ESP += imm16; else SP += imm16; RSP_COMMIT; done: BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_RET, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_Jw(bxInstruction_c *i) { #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif RSP_SPECULATIVE; /* push 16 bit EA of next instruction */ push_16(IP); Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL16_Ap(bxInstruction_c *i) { BX_ASSERT(BX_CPU_THIS_PTR cpu_mode != BX_MODE_LONG_64); invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif Bit16u disp16 = i->Iw(); Bit16u cs_raw = i->Iw2(); RSP_SPECULATIVE; if (protected_mode()) { call_protected(i, cs_raw, disp16); goto done; } push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_16(IP); // CS.LIMIT can't change when in real/v8086 mode if (disp16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("CALL16_Ap: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = (Bit32u) disp16; done: RSP_COMMIT; BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL_EwR(bxInstruction_c *i) { Bit16u new_IP = BX_READ_16BIT_REG(i->dst()); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif RSP_SPECULATIVE; /* push 16 bit EA of next instruction */ push_16(IP); branch_near16(new_IP); RSP_COMMIT; BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL_INDIRECT, PREV_RIP, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CALL16_Ep(bxInstruction_c *i) { Bit16u cs_raw; Bit16u op1_16; invalidate_prefetch_q(); #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_call; #endif bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_virtual_word(i->seg(), eaddr); cs_raw = read_virtual_word(i->seg(), (eaddr+2) & i->asize_mask()); RSP_SPECULATIVE; if (protected_mode()) { call_protected(i, cs_raw, op1_16); goto done; } push_16(BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value); push_16(IP); // CS.LIMIT can't change when in real/v8086 mode if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("CALL16_Ep: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = op1_16; done: RSP_COMMIT; BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_CALL_INDIRECT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_Jw(bxInstruction_c *i) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JO_Jw(bxInstruction_c *i) { if (get_OF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNO_Jw(bxInstruction_c *i) { if (! get_OF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JB_Jw(bxInstruction_c *i) { if (get_CF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNB_Jw(bxInstruction_c *i) { if (! get_CF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JZ_Jw(bxInstruction_c *i) { if (get_ZF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNZ_Jw(bxInstruction_c *i) { if (! get_ZF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JBE_Jw(bxInstruction_c *i) { if (get_CF() || get_ZF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNBE_Jw(bxInstruction_c *i) { if (! (get_CF() || get_ZF())) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JS_Jw(bxInstruction_c *i) { if (get_SF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNS_Jw(bxInstruction_c *i) { if (! get_SF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JP_Jw(bxInstruction_c *i) { if (get_PF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNP_Jw(bxInstruction_c *i) { if (! get_PF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JL_Jw(bxInstruction_c *i) { if (getB_SF() != getB_OF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNL_Jw(bxInstruction_c *i) { if (getB_SF() == getB_OF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JLE_Jw(bxInstruction_c *i) { if (get_ZF() || (getB_SF() != getB_OF())) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JNLE_Jw(bxInstruction_c *i) { if (! get_ZF() && (getB_SF() == getB_OF())) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_INSTR(i); // trace can continue over non-taken branch } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP_EwR(bxInstruction_c *i) { Bit16u new_IP = BX_READ_16BIT_REG(i->dst()); branch_near16(new_IP); BX_INSTR_UCNEAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP_INDIRECT, PREV_RIP, new_IP); BX_NEXT_TRACE(i); } /* Far indirect jump */ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JMP16_Ep(bxInstruction_c *i) { Bit16u cs_raw; Bit16u op1_16; invalidate_prefetch_q(); bx_address eaddr = BX_CPU_CALL_METHODR(i->ResolveModrm, (i)); op1_16 = read_virtual_word(i->seg(), eaddr); cs_raw = read_virtual_word(i->seg(), (eaddr+2) & i->asize_mask()); // jump_protected doesn't affect RSP so it is RSP safe if (protected_mode()) { jump_protected(i, cs_raw, op1_16); goto done; } // CS.LIMIT can't change when in real/v8086 mode if (op1_16 > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("JMP16_Ep: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = op1_16; done: BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_JMP_INDIRECT, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::IRET16(bxInstruction_c *i) { invalidate_prefetch_q(); #if BX_SUPPORT_VMX if (!BX_CPU_THIS_PTR in_vmx_guest || !VMEXIT(VMX_VM_EXEC_CTRL1_NMI_VMEXIT)) #endif BX_CPU_THIS_PTR disable_NMI = 0; #if BX_DEBUGGER BX_CPU_THIS_PTR show_flag |= Flag_iret; #endif if (protected_mode()) { iret_protected(i); goto done; } RSP_SPECULATIVE; if (v8086_mode()) { // IOPL check in stack_return_from_v86() iret16_stack_return_from_v86(i); } else { Bit16u ip = pop_16(); Bit16u cs_raw = pop_16(); // #SS has higher priority Bit16u flags = pop_16(); // CS.LIMIT can't change when in real/v8086 mode if(ip > BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled) { BX_ERROR(("IRET16: instruction pointer not within code segment limits")); exception(BX_GP_EXCEPTION, 0); } load_seg_reg(&BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS], cs_raw); EIP = (Bit32u) ip; write_flags(flags, /* change IOPL? */ 1, /* change IF? */ 1); } RSP_COMMIT; done: BX_INSTR_FAR_BRANCH(BX_CPU_ID, BX_INSTR_IS_IRET, BX_CPU_THIS_PTR sregs[BX_SEG_REG_CS].selector.value, EIP); BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::JCXZ_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); Bit32u temp_ECX; if (i->as32L()) temp_ECX = ECX; else temp_ECX = CX; if (temp_ECX == 0) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); BX_LINK_TRACE(i); } BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); BX_NEXT_TRACE(i); } // // There is some weirdness in LOOP instructions definition. If an exception // was generated during the instruction execution (for example #GP fault // because EIP was beyond CS segment limits) CPU state should restore the // state prior to instruction execution. // // The final point that we are not allowed to decrement ECX register before // it is known that no exceptions can happen. // BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPNE16_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); if (i->as32L()) { Bit32u count = ECX; count--; if (count != 0 && (get_ZF()==0)) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif ECX = count; } else { Bit16u count = CX; count--; if (count != 0 && (get_ZF()==0)) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif CX = count; } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOPE16_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); if (i->as32L()) { Bit32u count = ECX; count--; if (count != 0 && get_ZF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif ECX = count; } else { Bit16u count = CX; count--; if (count != 0 && get_ZF()) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif CX = count; } BX_NEXT_TRACE(i); } BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LOOP16_Jb(bxInstruction_c *i) { // it is impossible to get this instruction in long mode BX_ASSERT(i->as64L() == 0); if (i->as32L()) { Bit32u count = ECX; count--; if (count != 0) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif ECX = count; } else { Bit16u count = CX; count--; if (count != 0) { Bit16u new_IP = IP + i->Iw(); branch_near16(new_IP); BX_INSTR_CNEAR_BRANCH_TAKEN(BX_CPU_ID, PREV_RIP, new_IP); } #if BX_INSTRUMENTATION else { BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(BX_CPU_ID, PREV_RIP); } #endif CX = count; } BX_NEXT_TRACE(i); } bochs-2.6/cpu/avx_fma.cc0000644000175000017500000004067712020641453015067 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: avx_fma.cc 11313 2012-08-05 13:52:40Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2011-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #define NEED_CPU_REG_SHORTCUTS 1 #include "bochs.h" #include "cpu.h" #define LOG_THIS BX_CPU_THIS_PTR #if BX_SUPPORT_AVX extern void mxcsr_to_softfloat_status_word(float_status_t &status, bx_mxcsr_t mxcsr); #include "simd_pfp.h" ////////////////////////// // AVX FMA Instructions // ////////////////////////// // FMADDPD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMADDPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmaddpd(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMADDPS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMADDPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmaddps(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMADDSD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMADDSD_VpdHsdWsdR(bxInstruction_c *i) { float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_muladd(op1, op2, op3, 0, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } // FMADDSS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMADDSS_VpsHssWssR(bxInstruction_c *i) { float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_muladd(op1, op2, op3, 0, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } // FMADDSUBPD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMADDSUBPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmaddsubpd(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMADDSUBPS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMADDSUBPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmaddsubps(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMSUBADDPD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMSUBADDPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmsubaddpd(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMSUBADDPS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMSUBADDPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmsubaddps(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMSUBPD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMSUBPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmsubpd(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMSUBPS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMSUBPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fmsubps(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FMSUBSD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMSUBSD_VpdHsdWsdR(bxInstruction_c *i) { float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_muladd(op1, op2, op3, float_muladd_negate_c, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } // FMSUBSS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFMSUBSS_VpsHssWssR(bxInstruction_c *i) { float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_muladd(op1, op2, op3, float_muladd_negate_c, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } // FNMADDPD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMADDPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fnmaddpd(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FNMADDPS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMADDPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fnmaddps(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FNMADDSD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMADDSD_VpdHsdWsdR(bxInstruction_c *i) { float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_muladd(op1, op2, op3, float_muladd_negate_product, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } // FNMADDSS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMADDSS_VpsHssWssR(bxInstruction_c *i) { float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_muladd(op1, op2, op3, float_muladd_negate_product, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } // FNMSUBPD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMSUBPD_VpdHpdWpdR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fnmsubpd(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FNMSUBPS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMSUBPS_VpsHpsWpsR(bxInstruction_c *i) { BxPackedAvxRegister op1 = BX_READ_AVX_REG(i->src1()); BxPackedAvxRegister op2 = BX_READ_AVX_REG(i->src2()); BxPackedAvxRegister op3 = BX_READ_AVX_REG(i->src3()); unsigned len = i->getVL(); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); for (unsigned n=0; n < len; n++) fnmsubps(&op1.avx128(n), &op2.avx128(n), &op3.avx128(n), status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_AVX_REGZ(i->dst(), op1, len); BX_NEXT_INSTR(i); } // FNMSUBSD BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMSUBSD_VpdHsdWsdR(bxInstruction_c *i) { float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->src1()); float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float64_muladd(op1, op2, op3, float_muladd_negate_result, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_QWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } // FNMSUBSS BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::VFNMSUBSS_VpsHssWssR(bxInstruction_c *i) { float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->src1()); float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); float_status_t status; mxcsr_to_softfloat_status_word(status, MXCSR); op1 = float32_muladd(op1, op2, op3, float_muladd_negate_result, status); check_exceptionsSSE(status.float_exception_flags); BX_WRITE_XMM_REG_LO_DWORD(i->dst(), op1); BX_CLEAR_AVX_HIGH(i->dst()); BX_NEXT_INSTR(i); } ////////////////////////////////// // FMA4 (AMD) specific handlers // ////////////////////////////////// #define FMA4_SINGLE_SCALAR(HANDLER, func) \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ float32 op1 = BX_READ_XMM_REG_LO_DWORD(i->src1()); \ float32 op2 = BX_READ_XMM_REG_LO_DWORD(i->src2()); \ float32 op3 = BX_READ_XMM_REG_LO_DWORD(i->src3()); \ \ BxPackedXmmRegister dest; \ \ float_status_t status; \ mxcsr_to_softfloat_status_word(status, MXCSR); \ \ dest.xmm64u(0) = (func)(op1, op2, op3, status); \ dest.xmm64u(1) = 0; \ \ check_exceptionsSSE(status.float_exception_flags); \ \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), dest); \ \ BX_NEXT_INSTR(i); \ } FMA4_SINGLE_SCALAR(VFMADDSS_VssHssWssVIbR, float32_fmadd) FMA4_SINGLE_SCALAR(VFMSUBSS_VssHssWssVIbR, float32_fmsub) FMA4_SINGLE_SCALAR(VFNMADDSS_VssHssWssVIbR, float32_fnmadd) FMA4_SINGLE_SCALAR(VFNMSUBSS_VssHssWssVIbR, float32_fnmsub) #define FMA4_DOUBLE_SCALAR(HANDLER, func) \ BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C:: HANDLER (bxInstruction_c *i) \ { \ float64 op1 = BX_READ_XMM_REG_LO_QWORD(i->src1()); \ float64 op2 = BX_READ_XMM_REG_LO_QWORD(i->src2()); \ float64 op3 = BX_READ_XMM_REG_LO_QWORD(i->src3()); \ BxPackedXmmRegister dest; \ \ float_status_t status; \ mxcsr_to_softfloat_status_word(status, MXCSR); \ \ dest.xmm64u(0) = (func)(op1, op2, op3, status); \ dest.xmm64u(1) = 0; \ \ check_exceptionsSSE(status.float_exception_flags); \ \ BX_WRITE_XMM_REG_CLEAR_HIGH(i->dst(), dest); \ \ BX_NEXT_INSTR(i); \ } FMA4_DOUBLE_SCALAR(VFMADDSD_VsdHsdWsdVIbR, float64_fmadd) FMA4_DOUBLE_SCALAR(VFMSUBSD_VsdHsdWsdVIbR, float64_fmsub) FMA4_DOUBLE_SCALAR(VFNMADDSD_VsdHsdWsdVIbR, float64_fnmadd) FMA4_DOUBLE_SCALAR(VFNMSUBSD_VsdHsdWsdVIbR, float64_fnmsub) #endif bochs-2.6/cpu/ia_opcodes.h0000644000175000017500000110406512020641453015406 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ia_opcodes.h 11323 2012-08-07 14:38:43Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2008-2012 Stanislav Shwartsman // Written by Stanislav Shwartsman [sshwarts at sourceforge net] // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // bx_define_opcode is a macro with 5 fields: // - Opcode name // - Opcode execution function (/m form) // - Opcode execution function (/r form) // - x86 ISA extensions that enable this instruction // - source for instruction destination register // - source for instruction src1 register // - source for instruction src2 register // - special attributes (PREPARE_SSE, PREPARE_AVX and etc) // in case of complex /m form instruction (load+op) /m form execution function // directly calls the /r form. bx_define_opcode(BX_IA_ERROR, &BX_CPU_C::BxError, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS bx_define_opcode(BX_INSERTED_OPCODE, &BX_CPU_C::BxError, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bx_define_opcode(BX_IA_AAA, NULL, &BX_CPU_C::AAA, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AAD, NULL, &BX_CPU_C::AAD, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AAM, NULL, &BX_CPU_C::AAM, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AAS, NULL, &BX_CPU_C::AAS, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DAA, NULL, &BX_CPU_C::DAA, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DAS, NULL, &BX_CPU_C::DAS, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EbGb, &BX_CPU_C::ADC_EbGbM, &BX_CPU_C::ADC_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EbGb, &BX_CPU_C::AND_EbGbM, &BX_CPU_C::AND_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EbGb, &BX_CPU_C::ADD_EbGbM, &BX_CPU_C::ADD_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EbGb, &BX_CPU_C::CMP_EbGbM, &BX_CPU_C::CMP_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EbGb, &BX_CPU_C::OR_EbGbM, &BX_CPU_C::OR_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EbGb, &BX_CPU_C::SBB_EbGbM, &BX_CPU_C::SBB_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EbGb, &BX_CPU_C::SUB_EbGbM, &BX_CPU_C::SUB_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EbGb, &BX_CPU_C::TEST_EbGbM, &BX_CPU_C::TEST_EbGbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EbGb, &BX_CPU_C::XOR_EbGbM, &BX_CPU_C::XOR_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EwGw, &BX_CPU_C::ADC_EwGwM, &BX_CPU_C::ADC_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EwGw, &BX_CPU_C::ADD_EwGwM, &BX_CPU_C::ADD_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EwGw, &BX_CPU_C::AND_EwGwM, &BX_CPU_C::AND_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EwGw, &BX_CPU_C::CMP_EwGwM, &BX_CPU_C::CMP_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EwGw, &BX_CPU_C::OR_EwGwM, &BX_CPU_C::OR_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EwGw, &BX_CPU_C::SBB_EwGwM, &BX_CPU_C::SBB_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EwGw, &BX_CPU_C::SUB_EwGwM, &BX_CPU_C::SUB_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EwGw, &BX_CPU_C::TEST_EwGwM, &BX_CPU_C::TEST_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EwGw, &BX_CPU_C::XOR_EwGwM, &BX_CPU_C::XOR_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EdGd, &BX_CPU_C::ADC_EdGdM, &BX_CPU_C::ADC_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EdGd, &BX_CPU_C::ADD_EdGdM, &BX_CPU_C::ADD_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EdGd, &BX_CPU_C::AND_EdGdM, &BX_CPU_C::AND_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EdGd, &BX_CPU_C::CMP_EdGdM, &BX_CPU_C::CMP_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EdGd, &BX_CPU_C::OR_EdGdM, &BX_CPU_C::OR_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EdGd, &BX_CPU_C::SBB_EdGdM, &BX_CPU_C::SBB_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EdGd, &BX_CPU_C::SUB_EdGdM, &BX_CPU_C::SUB_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EdGd, &BX_CPU_C::TEST_EdGdM, &BX_CPU_C::TEST_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EdGd, &BX_CPU_C::XOR_EdGdM, &BX_CPU_C::XOR_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_ALIb, NULL, &BX_CPU_C::ADC_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_ALIb, NULL, &BX_CPU_C::ADD_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_ALIb, NULL, &BX_CPU_C::AND_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_ALIb, NULL, &BX_CPU_C::CMP_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_ALIb, NULL, &BX_CPU_C::OR_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_ALIb, NULL, &BX_CPU_C::SBB_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_ALIb, NULL, &BX_CPU_C::SUB_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_ALIb, NULL, &BX_CPU_C::TEST_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_ALIb, NULL, &BX_CPU_C::XOR_EbIbR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_AXIw, NULL, &BX_CPU_C::ADC_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_AXIw, NULL, &BX_CPU_C::ADD_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_AXIw, NULL, &BX_CPU_C::AND_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_AXIw, NULL, &BX_CPU_C::CMP_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_AXIw, NULL, &BX_CPU_C::OR_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_AXIw, NULL, &BX_CPU_C::SBB_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_AXIw, NULL, &BX_CPU_C::SUB_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_AXIw, NULL, &BX_CPU_C::TEST_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_AXIw, NULL, &BX_CPU_C::XOR_EwIwR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EAXId, NULL, &BX_CPU_C::ADC_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EAXId, NULL, &BX_CPU_C::ADD_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EAXId, NULL, &BX_CPU_C::AND_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EAXId, NULL, &BX_CPU_C::CMP_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EAXId, NULL, &BX_CPU_C::OR_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EAXId, NULL, &BX_CPU_C::SBB_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EAXId, NULL, &BX_CPU_C::SUB_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EAXId, NULL, &BX_CPU_C::TEST_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EAXId, NULL, &BX_CPU_C::XOR_EdIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EbIb, &BX_CPU_C::ADD_EbIbM, &BX_CPU_C::ADD_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EbIb, &BX_CPU_C::OR_EbIbM, &BX_CPU_C::OR_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EbIb, &BX_CPU_C::ADC_EbIbM, &BX_CPU_C::ADC_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EbIb, &BX_CPU_C::SBB_EbIbM, &BX_CPU_C::SBB_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EbIb, &BX_CPU_C::AND_EbIbM, &BX_CPU_C::AND_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EbIb, &BX_CPU_C::SUB_EbIbM, &BX_CPU_C::SUB_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EbIb, &BX_CPU_C::XOR_EbIbM, &BX_CPU_C::XOR_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EbIb, &BX_CPU_C::TEST_EbIbM, &BX_CPU_C::TEST_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EbIb, &BX_CPU_C::CMP_EbIbM, &BX_CPU_C::CMP_EbIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EwIw, &BX_CPU_C::ADD_EwIwM, &BX_CPU_C::ADD_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EwIw, &BX_CPU_C::OR_EwIwM, &BX_CPU_C::OR_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EwIw, &BX_CPU_C::ADC_EwIwM, &BX_CPU_C::ADC_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EwIw, &BX_CPU_C::SBB_EwIwM, &BX_CPU_C::SBB_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EwIw, &BX_CPU_C::AND_EwIwM, &BX_CPU_C::AND_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EwIw, &BX_CPU_C::SUB_EwIwM, &BX_CPU_C::SUB_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EwIw, &BX_CPU_C::XOR_EwIwM, &BX_CPU_C::XOR_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EwIw, &BX_CPU_C::TEST_EwIwM, &BX_CPU_C::TEST_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EwIw, &BX_CPU_C::CMP_EwIwM, &BX_CPU_C::CMP_EwIwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EdId, &BX_CPU_C::ADD_EdIdM, &BX_CPU_C::ADD_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EdId, &BX_CPU_C::OR_EdIdM, &BX_CPU_C::OR_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EdId, &BX_CPU_C::ADC_EdIdM, &BX_CPU_C::ADC_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EdId, &BX_CPU_C::SBB_EdIdM, &BX_CPU_C::SBB_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EdId, &BX_CPU_C::AND_EdIdM, &BX_CPU_C::AND_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EdId, &BX_CPU_C::SUB_EdIdM, &BX_CPU_C::SUB_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EdId, &BX_CPU_C::XOR_EdIdM, &BX_CPU_C::XOR_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EdId, &BX_CPU_C::TEST_EdIdM, &BX_CPU_C::TEST_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EdId, &BX_CPU_C::CMP_EdIdM, &BX_CPU_C::CMP_EdIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_GbEb, &BX_CPU_C::ADD_GbEbM, &BX_CPU_C::ADD_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_GbEb, &BX_CPU_C::OR_GbEbM, &BX_CPU_C::OR_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_GbEb, &BX_CPU_C::ADC_GbEbM, &BX_CPU_C::ADC_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_GbEb, &BX_CPU_C::SBB_GbEbM, &BX_CPU_C::SBB_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_GbEb, &BX_CPU_C::AND_GbEbM, &BX_CPU_C::AND_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_GbEb, &BX_CPU_C::SUB_GbEbM, &BX_CPU_C::SUB_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_GbEb, &BX_CPU_C::XOR_GbEbM, &BX_CPU_C::XOR_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_GbEb, &BX_CPU_C::CMP_GbEbM, &BX_CPU_C::CMP_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_GwEw, &BX_CPU_C::ADC_GwEwM, &BX_CPU_C::ADC_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_GwEw, &BX_CPU_C::ADD_GwEwM, &BX_CPU_C::ADD_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_GwEw, &BX_CPU_C::AND_GwEwM, &BX_CPU_C::AND_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_GwEw, &BX_CPU_C::CMP_GwEwM, &BX_CPU_C::CMP_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_GwEw, &BX_CPU_C::OR_GwEwM, &BX_CPU_C::OR_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_GwEw, &BX_CPU_C::SBB_GwEwM, &BX_CPU_C::SBB_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_GwEw, &BX_CPU_C::SUB_GwEwM, &BX_CPU_C::SUB_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_GwEw, &BX_CPU_C::XOR_GwEwM, &BX_CPU_C::XOR_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_GdEd, &BX_CPU_C::ADC_GdEdM, &BX_CPU_C::ADC_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_GdEd, &BX_CPU_C::ADD_GdEdM, &BX_CPU_C::ADD_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_GdEd, &BX_CPU_C::AND_GdEdM, &BX_CPU_C::AND_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_GdEd, &BX_CPU_C::CMP_GdEdM, &BX_CPU_C::CMP_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_GdEd, &BX_CPU_C::OR_GdEdM, &BX_CPU_C::OR_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_GdEd, &BX_CPU_C::SBB_GdEdM, &BX_CPU_C::SBB_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_GdEd, &BX_CPU_C::SUB_GdEdM, &BX_CPU_C::SUB_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_GdEd, &BX_CPU_C::XOR_GdEdM, &BX_CPU_C::XOR_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INC_Eb, &BX_CPU_C::INC_EbM, &BX_CPU_C::INC_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INC_Ew, &BX_CPU_C::INC_EwM, &BX_CPU_C::INC_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INC_Ed, &BX_CPU_C::INC_EdM, &BX_CPU_C::INC_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INC_RX, NULL, &BX_CPU_C::INC_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INC_ERX, NULL, &BX_CPU_C::INC_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DEC_Eb, &BX_CPU_C::DEC_EbM, &BX_CPU_C::DEC_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DEC_Ew, &BX_CPU_C::DEC_EwM, &BX_CPU_C::DEC_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DEC_Ed, &BX_CPU_C::DEC_EdM, &BX_CPU_C::DEC_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DEC_RX, NULL, &BX_CPU_C::DEC_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DEC_ERX, NULL, &BX_CPU_C::DEC_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSF_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::BSF_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSR_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::BSR_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSF_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BSF_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSR_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BSR_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTC_EwGw, &BX_CPU_C::BTC_EwGwM, &BX_CPU_C::BTC_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTR_EwGw, &BX_CPU_C::BTR_EwGwM, &BX_CPU_C::BTR_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTS_EwGw, &BX_CPU_C::BTS_EwGwM, &BX_CPU_C::BTS_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTC_EdGd, &BX_CPU_C::BTC_EdGdM, &BX_CPU_C::BTC_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTR_EdGd, &BX_CPU_C::BTR_EdGdM, &BX_CPU_C::BTR_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTS_EdGd, &BX_CPU_C::BTS_EdGdM, &BX_CPU_C::BTS_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTC_EwIb, &BX_CPU_C::BTC_EwIbM, &BX_CPU_C::BTC_EwIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTR_EwIb, &BX_CPU_C::BTR_EwIbM, &BX_CPU_C::BTR_EwIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTS_EwIb, &BX_CPU_C::BTS_EwIbM, &BX_CPU_C::BTS_EwIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTC_EdIb, &BX_CPU_C::BTC_EdIbM, &BX_CPU_C::BTC_EdIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTR_EdIb, &BX_CPU_C::BTR_EdIbM, &BX_CPU_C::BTR_EdIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTS_EdIb, &BX_CPU_C::BTS_EdIbM, &BX_CPU_C::BTS_EdIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BT_EwIb, &BX_CPU_C::BT_EwIbM, &BX_CPU_C::BT_EwIbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BT_EdIb, &BX_CPU_C::BT_EdIbM, &BX_CPU_C::BT_EdIbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BT_EwGw, &BX_CPU_C::BT_EwGwM, &BX_CPU_C::BT_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BT_EdGd, &BX_CPU_C::BT_EdGdM, &BX_CPU_C::BT_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BOUND_GdMa, &BX_CPU_C::BOUND_GdMa, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BOUND_GwMa, &BX_CPU_C::BOUND_GwMa, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ARPL_EwGw, &BX_CPU_C::ARPL_EwGw, &BX_CPU_C::ARPL_EwGw, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL_Ed, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CALL_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL_Ew, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CALL_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL_Jd, NULL, &BX_CPU_C::CALL_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL_Jw, NULL, &BX_CPU_C::CALL_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL16_Ap, NULL, &BX_CPU_C::CALL16_Ap, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL32_Ap, NULL, &BX_CPU_C::CALL32_Ap, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL16_Ep, &BX_CPU_C::CALL16_Ep, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL32_Ep, &BX_CPU_C::CALL32_Ep, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CBW, NULL, &BX_CPU_C::CBW, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CDQ, NULL, &BX_CPU_C::CDQ, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CLC, NULL, &BX_CPU_C::CLC, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CLD, NULL, &BX_CPU_C::CLD, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CLFLUSH, &BX_CPU_C::CLFLUSH, &BX_CPU_C::BxError, BX_ISA_CLFLUSH, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CLI, NULL, &BX_CPU_C::CLI, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CLTS, NULL, &BX_CPU_C::CLTS, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMC, NULL, &BX_CPU_C::CMC, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CWD, NULL, &BX_CPU_C::CWD, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CWDE, NULL, &BX_CPU_C::CWDE, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ENTER16_IwIb, NULL, &BX_CPU_C::ENTER16_IwIb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ENTER32_IwIb, NULL, &BX_CPU_C::ENTER32_IwIb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_HLT, NULL, &BX_CPU_C::HLT, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::IMUL_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_GdEdId, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::IMUL_GdEdIdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::IMUL_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_GwEwIw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::IMUL_GwEwIwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IN_ALDX, NULL, &BX_CPU_C::IN_ALDX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IN_ALIb, NULL, &BX_CPU_C::IN_ALIb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IN_AXDX, NULL, &BX_CPU_C::IN_AXDX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IN_AXIb, NULL, &BX_CPU_C::IN_AXIb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IN_EAXDX, NULL, &BX_CPU_C::IN_EAXDX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IN_EAXIb, NULL, &BX_CPU_C::IN_EAXIb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OUT_DXAL, NULL, &BX_CPU_C::OUT_DXAL, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OUT_DXAX, NULL, &BX_CPU_C::OUT_DXAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OUT_DXEAX, NULL, &BX_CPU_C::OUT_DXEAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OUT_IbAL, NULL, &BX_CPU_C::OUT_IbAL, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OUT_IbAX, NULL, &BX_CPU_C::OUT_IbAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OUT_IbEAX, NULL, &BX_CPU_C::OUT_IbEAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INT_Ib, NULL, &BX_CPU_C::INT_Ib, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INT1, NULL, &BX_CPU_C::INT1, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INT3, NULL, &BX_CPU_C::INT3, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INTO, NULL, &BX_CPU_C::INTO, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IRET16, NULL, &BX_CPU_C::IRET16, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IRET32, NULL, &BX_CPU_C::IRET32, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP_Ed, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::JMP_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP_Ew, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::JMP_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP_Ap, NULL, &BX_CPU_C::JMP_Ap, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP_Jd, NULL, &BX_CPU_C::JMP_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP16_Ep, &BX_CPU_C::JMP16_Ep, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP32_Ep, &BX_CPU_C::JMP32_Ep, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JCXZ_Jb, NULL, &BX_CPU_C::JCXZ_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JECXZ_Jb, NULL, &BX_CPU_C::JECXZ_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOP16_Jb, NULL, &BX_CPU_C::LOOP16_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOPE16_Jb, NULL, &BX_CPU_C::LOOPE16_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOPNE16_Jb, NULL, &BX_CPU_C::LOOPNE16_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOP32_Jb, NULL, &BX_CPU_C::LOOP32_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOPE32_Jb, NULL, &BX_CPU_C::LOOPE32_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOPNE32_Jb, NULL, &BX_CPU_C::LOOPNE32_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JB_Jw, NULL, &BX_CPU_C::JB_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JBE_Jw, NULL, &BX_CPU_C::JBE_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JL_Jw, NULL, &BX_CPU_C::JL_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JLE_Jw, NULL, &BX_CPU_C::JLE_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP_Jw, NULL, &BX_CPU_C::JMP_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNB_Jw, NULL, &BX_CPU_C::JNB_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNBE_Jw, NULL, &BX_CPU_C::JNBE_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNL_Jw, NULL, &BX_CPU_C::JNL_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNLE_Jw, NULL, &BX_CPU_C::JNLE_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNO_Jw, NULL, &BX_CPU_C::JNO_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNP_Jw, NULL, &BX_CPU_C::JNP_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNS_Jw, NULL, &BX_CPU_C::JNS_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNZ_Jw, NULL, &BX_CPU_C::JNZ_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JO_Jw, NULL, &BX_CPU_C::JO_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JP_Jw, NULL, &BX_CPU_C::JP_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JS_Jw, NULL, &BX_CPU_C::JS_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JZ_Jw, NULL, &BX_CPU_C::JZ_Jw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JB_Jd, NULL, &BX_CPU_C::JB_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JBE_Jd, NULL, &BX_CPU_C::JBE_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JL_Jd, NULL, &BX_CPU_C::JL_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JLE_Jd, NULL, &BX_CPU_C::JLE_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNB_Jd, NULL, &BX_CPU_C::JNB_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNBE_Jd, NULL, &BX_CPU_C::JNBE_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNL_Jd, NULL, &BX_CPU_C::JNL_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNLE_Jd, NULL, &BX_CPU_C::JNLE_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNO_Jd, NULL, &BX_CPU_C::JNO_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNP_Jd, NULL, &BX_CPU_C::JNP_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNS_Jd, NULL, &BX_CPU_C::JNS_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNZ_Jd, NULL, &BX_CPU_C::JNZ_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JO_Jd, NULL, &BX_CPU_C::JO_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JP_Jd, NULL, &BX_CPU_C::JP_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JS_Jd, NULL, &BX_CPU_C::JS_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JZ_Jd, NULL, &BX_CPU_C::JZ_Jd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAHF, NULL, &BX_CPU_C::SAHF, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LAHF, NULL, &BX_CPU_C::LAHF, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LDS_GdMp, &BX_CPU_C::LDS_GdMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LDS_GwMp, &BX_CPU_C::LDS_GwMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LES_GdMp, &BX_CPU_C::LES_GdMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LES_GwMp, &BX_CPU_C::LES_GwMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LFS_GdMp, &BX_CPU_C::LFS_GdMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LFS_GwMp, &BX_CPU_C::LFS_GwMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LSS_GdMp, &BX_CPU_C::LSS_GdMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LSS_GwMp, &BX_CPU_C::LSS_GwMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LGS_GdMp, &BX_CPU_C::LGS_GdMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LGS_GwMp, &BX_CPU_C::LGS_GwMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LAR_GvEw, &BX_CPU_C::LAR_GvEw, &BX_CPU_C::LAR_GvEw, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LSL_GvEw, &BX_CPU_C::LSL_GvEw, &BX_CPU_C::LSL_GvEw, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LEA_GdM, &BX_CPU_C::LEA_GdM, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LEA_GwM, &BX_CPU_C::LEA_GwM, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LEAVE16, NULL, &BX_CPU_C::LEAVE16, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LEAVE32, NULL, &BX_CPU_C::LEAVE32, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // IDT/GDT/LDTR/TR access - keep NNN for VMX bx_define_opcode(BX_IA_SIDT_Ms, &BX_CPU_C::SIDT_Ms, &BX_CPU_C::BxError, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LIDT_Ms, &BX_CPU_C::LIDT_Ms, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SGDT_Ms, &BX_CPU_C::SGDT_Ms, &BX_CPU_C::BxError, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LGDT_Ms, &BX_CPU_C::LGDT_Ms, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SLDT_Ew, &BX_CPU_C::SLDT_Ew, &BX_CPU_C::SLDT_Ew, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LLDT_Ew, &BX_CPU_C::LLDT_Ew, &BX_CPU_C::LLDT_Ew, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_STR_Ew, &BX_CPU_C::STR_Ew, &BX_CPU_C::STR_Ew, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LTR_Ew, &BX_CPU_C::LTR_Ew, &BX_CPU_C::LTR_Ew, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) // IDT/GDT/LDTR/TR access - keep NNN for VMX bx_define_opcode(BX_IA_SMSW_Ew, &BX_CPU_C::SMSW_EwM, &BX_CPU_C::SMSW_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LMSW_Ew, &BX_CPU_C::LMSW_Ew, &BX_CPU_C::LMSW_Ew, 0, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR0Rd, NULL, &BX_CPU_C::MOV_CR0Rd, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR2Rd, NULL, &BX_CPU_C::MOV_CR2Rd, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR3Rd, NULL, &BX_CPU_C::MOV_CR3Rd, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR4Rd, NULL, &BX_CPU_C::MOV_CR4Rd, BX_ISA_PENTIUM, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RdCR0, NULL, &BX_CPU_C::MOV_RdCR0, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RdCR2, NULL, &BX_CPU_C::MOV_RdCR2, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RdCR3, NULL, &BX_CPU_C::MOV_RdCR3, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RdCR4, NULL, &BX_CPU_C::MOV_RdCR4, BX_ISA_PENTIUM, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RdDd, NULL, &BX_CPU_C::MOV_RdDd, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_DdRd, NULL, &BX_CPU_C::MOV_DdRd, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RHIb, NULL, &BX_CPU_C::MOV_RHIb, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RLIb, NULL, &BX_CPU_C::MOV_RLIb, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RXIw, NULL, &BX_CPU_C::MOV_RXIw, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EbIb, &BX_CPU_C::MOV_EbIbM, &BX_CPU_C::MOV_RLIb, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EdId, &BX_CPU_C::MOV_EdIdM, &BX_CPU_C::MOV_ERXId, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EwIw, &BX_CPU_C::MOV_EwIwM, &BX_CPU_C::MOV_RXIw, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_ERXId, NULL, &BX_CPU_C::MOV_ERXId, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_GbEb, &BX_CPU_C::MOV_GbEbM, &BX_CPU_C::MOV_GbEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EbGb, &BX_CPU_C::MOV_EbGbM, &BX_CPU_C::MOV_GbEbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_GwEw, &BX_CPU_C::MOV_GwEwM, &BX_CPU_C::MOV_GwEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EwGw, &BX_CPU_C::MOV_EwGwM, &BX_CPU_C::MOV_GwEwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV32_GdEd, &BX_CPU_C::MOV32_GdEdM, &BX_CPU_C::MOV_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV32_EdGd, &BX_CPU_C::MOV32_EdGdM, &BX_CPU_C::MOV_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EwSw, &BX_CPU_C::MOV_EwSwM, &BX_CPU_C::MOV_EwSwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_SwEw, &BX_CPU_C::MOV_SwEw, &BX_CPU_C::MOV_SwEw, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_ALOd, NULL, &BX_CPU_C::MOV_ALOd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_AXOd, NULL, &BX_CPU_C::MOV_AXOd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EAXOd, NULL, &BX_CPU_C::MOV_EAXOd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_OdAL, NULL, &BX_CPU_C::MOV_OdAL, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_OdAX, NULL, &BX_CPU_C::MOV_OdAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_OdEAX, NULL, &BX_CPU_C::MOV_OdEAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVSX_GdEb, &BX_CPU_C::MOVSX_GdEbM, &BX_CPU_C::MOVSX_GdEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVSX_GdEw, &BX_CPU_C::MOVSX_GdEwM, &BX_CPU_C::MOVSX_GdEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVSX_GwEb, &BX_CPU_C::MOVSX_GwEbM, &BX_CPU_C::MOVSX_GwEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVZX_GdEb, &BX_CPU_C::MOVZX_GdEbM, &BX_CPU_C::MOVZX_GdEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVZX_GdEw, &BX_CPU_C::MOVZX_GdEwM, &BX_CPU_C::MOVZX_GdEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVZX_GwEb, &BX_CPU_C::MOVZX_GwEbM, &BX_CPU_C::MOVZX_GwEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NOP, &BX_CPU_C::NOP, &BX_CPU_C::NOP, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PAUSE, NULL, &BX_CPU_C::PAUSE, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP_Ew, &BX_CPU_C::POP_EwM, &BX_CPU_C::POP_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP_Ed, &BX_CPU_C::POP_EdM, &BX_CPU_C::POP_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP_RX, NULL, &BX_CPU_C::POP_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP_ERX, NULL, &BX_CPU_C::POP_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP16_DS, NULL, &BX_CPU_C::POP16_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP16_ES, NULL, &BX_CPU_C::POP16_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP16_FS, NULL, &BX_CPU_C::POP16_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP16_GS, NULL, &BX_CPU_C::POP16_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP16_SS, NULL, &BX_CPU_C::POP16_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP32_DS, NULL, &BX_CPU_C::POP32_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP32_ES, NULL, &BX_CPU_C::POP32_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP32_FS, NULL, &BX_CPU_C::POP32_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP32_GS, NULL, &BX_CPU_C::POP32_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP32_SS, NULL, &BX_CPU_C::POP32_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POPAD16, NULL, &BX_CPU_C::POPAD16, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POPAD32, NULL, &BX_CPU_C::POPAD32, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POPF_Fd, NULL, &BX_CPU_C::POPF_Fd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POPF_Fw, NULL, &BX_CPU_C::POPF_Fw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_Ew, &BX_CPU_C::PUSH_EwM, &BX_CPU_C::PUSH_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_Ed, &BX_CPU_C::PUSH_EdM, &BX_CPU_C::PUSH_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_RX, NULL, &BX_CPU_C::PUSH_RX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_ERX, NULL, &BX_CPU_C::PUSH_ERX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_Id, NULL, &BX_CPU_C::PUSH_Id, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_Iw, NULL, &BX_CPU_C::PUSH_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH16_CS, NULL, &BX_CPU_C::PUSH16_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH16_DS, NULL, &BX_CPU_C::PUSH16_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH16_ES, NULL, &BX_CPU_C::PUSH16_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH16_FS, NULL, &BX_CPU_C::PUSH16_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH16_GS, NULL, &BX_CPU_C::PUSH16_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH16_SS, NULL, &BX_CPU_C::PUSH16_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH32_CS, NULL, &BX_CPU_C::PUSH32_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH32_DS, NULL, &BX_CPU_C::PUSH32_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH32_ES, NULL, &BX_CPU_C::PUSH32_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH32_FS, NULL, &BX_CPU_C::PUSH32_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH32_GS, NULL, &BX_CPU_C::PUSH32_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH32_SS, NULL, &BX_CPU_C::PUSH32_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSHAD16, NULL, &BX_CPU_C::PUSHAD16, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSHAD32, NULL, &BX_CPU_C::PUSHAD32, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSHF_Fd, NULL, &BX_CPU_C::PUSHF_Fd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSHF_Fw, NULL, &BX_CPU_C::PUSHF_Fw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_CMPSB_XbYb, NULL, &BX_CPU_C::REP_CMPSB_XbYb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_CMPSD_XdYd, NULL, &BX_CPU_C::REP_CMPSD_XdYd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_CMPSW_XwYw, NULL, &BX_CPU_C::REP_CMPSW_XwYw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_INSB_YbDX, NULL, &BX_CPU_C::REP_INSB_YbDX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_INSD_YdDX, NULL, &BX_CPU_C::REP_INSD_YdDX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_INSW_YwDX, NULL, &BX_CPU_C::REP_INSW_YwDX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_LODSB_ALXb, NULL, &BX_CPU_C::REP_LODSB_ALXb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_LODSD_EAXXd, NULL, &BX_CPU_C::REP_LODSD_EAXXd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_LODSW_AXXw, NULL, &BX_CPU_C::REP_LODSW_AXXw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_MOVSB_XbYb, NULL, &BX_CPU_C::REP_MOVSB_XbYb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_MOVSD_XdYd, NULL, &BX_CPU_C::REP_MOVSD_XdYd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_MOVSW_XwYw, NULL, &BX_CPU_C::REP_MOVSW_XwYw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_OUTSB_DXXb, NULL, &BX_CPU_C::REP_OUTSB_DXXb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_OUTSD_DXXd, NULL, &BX_CPU_C::REP_OUTSD_DXXd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_OUTSW_DXXw, NULL, &BX_CPU_C::REP_OUTSW_DXXw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_SCASB_ALXb, NULL, &BX_CPU_C::REP_SCASB_ALXb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_SCASD_EAXXd, NULL, &BX_CPU_C::REP_SCASD_EAXXd, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_SCASW_AXXw, NULL, &BX_CPU_C::REP_SCASW_AXXw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_STOSB_YbAL, NULL, &BX_CPU_C::REP_STOSB_YbAL, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_STOSD_YdEAX, NULL, &BX_CPU_C::REP_STOSD_YdEAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_STOSW_YwAX, NULL, &BX_CPU_C::REP_STOSW_YwAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETfar16, NULL, &BX_CPU_C::RETfar16_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETfar16_Iw, NULL, &BX_CPU_C::RETfar16_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETfar32, NULL, &BX_CPU_C::RETfar32_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETfar32_Iw, NULL, &BX_CPU_C::RETfar32_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETnear16, NULL, &BX_CPU_C::RETnear16, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETnear16_Iw, NULL, &BX_CPU_C::RETnear16_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETnear32, NULL, &BX_CPU_C::RETnear32, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETnear32_Iw, NULL, &BX_CPU_C::RETnear32_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NOT_Eb, &BX_CPU_C::NOT_EbM, &BX_CPU_C::NOT_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NEG_Eb, &BX_CPU_C::NEG_EbM, &BX_CPU_C::NEG_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NOT_Ew, &BX_CPU_C::NOT_EwM, &BX_CPU_C::NOT_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NEG_Ew, &BX_CPU_C::NEG_EwM, &BX_CPU_C::NEG_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NOT_Ed, &BX_CPU_C::NOT_EdM, &BX_CPU_C::NOT_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NEG_Ed, &BX_CPU_C::NEG_EdM, &BX_CPU_C::NEG_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_Eb, &BX_CPU_C::ROL_EbM, &BX_CPU_C::ROL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_Eb, &BX_CPU_C::ROR_EbM, &BX_CPU_C::ROR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_Eb, &BX_CPU_C::RCL_EbM, &BX_CPU_C::RCL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_Eb, &BX_CPU_C::RCR_EbM, &BX_CPU_C::RCR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_Eb, &BX_CPU_C::SHL_EbM, &BX_CPU_C::SHL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_Eb, &BX_CPU_C::SHR_EbM, &BX_CPU_C::SHR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_Eb, &BX_CPU_C::SAR_EbM, &BX_CPU_C::SAR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_Ew, &BX_CPU_C::ROL_EwM, &BX_CPU_C::ROL_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_Ew, &BX_CPU_C::ROR_EwM, &BX_CPU_C::ROR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_Ew, &BX_CPU_C::RCL_EwM, &BX_CPU_C::RCL_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_Ew, &BX_CPU_C::RCR_EwM, &BX_CPU_C::RCR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_Ew, &BX_CPU_C::SHL_EwM, &BX_CPU_C::SHL_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_Ew, &BX_CPU_C::SHR_EwM, &BX_CPU_C::SHR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_Ew, &BX_CPU_C::SAR_EwM, &BX_CPU_C::SAR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_Ed, &BX_CPU_C::ROL_EdM, &BX_CPU_C::ROL_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_Ed, &BX_CPU_C::ROR_EdM, &BX_CPU_C::ROR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_Ed, &BX_CPU_C::RCL_EdM, &BX_CPU_C::RCL_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_Ed, &BX_CPU_C::RCR_EdM, &BX_CPU_C::RCR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_Ed, &BX_CPU_C::SHL_EdM, &BX_CPU_C::SHL_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_Ed, &BX_CPU_C::SHR_EdM, &BX_CPU_C::SHR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_Ed, &BX_CPU_C::SAR_EdM, &BX_CPU_C::SAR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_EbIb, &BX_CPU_C::ROL_EbM, &BX_CPU_C::ROL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_EbIb, &BX_CPU_C::ROR_EbM, &BX_CPU_C::ROR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_EbIb, &BX_CPU_C::RCL_EbM, &BX_CPU_C::RCL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_EbIb, &BX_CPU_C::RCR_EbM, &BX_CPU_C::RCR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_EbIb, &BX_CPU_C::SHL_EbM, &BX_CPU_C::SHL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_EbIb, &BX_CPU_C::SHR_EbM, &BX_CPU_C::SHR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_EbIb, &BX_CPU_C::SAR_EbM, &BX_CPU_C::SAR_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_EwIb, &BX_CPU_C::ROL_EwM, &BX_CPU_C::ROL_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_EwIb, &BX_CPU_C::ROR_EwM, &BX_CPU_C::ROR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_EwIb, &BX_CPU_C::RCL_EwM, &BX_CPU_C::RCL_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_EwIb, &BX_CPU_C::RCR_EwM, &BX_CPU_C::RCR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_EwIb, &BX_CPU_C::SHL_EwM, &BX_CPU_C::SHL_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_EwIb, &BX_CPU_C::SHR_EwM, &BX_CPU_C::SHR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_EwIb, &BX_CPU_C::SAR_EwM, &BX_CPU_C::SAR_EwR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_EdIb, &BX_CPU_C::ROL_EdM, &BX_CPU_C::ROL_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_EdIb, &BX_CPU_C::ROR_EdM, &BX_CPU_C::ROR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_EdIb, &BX_CPU_C::RCL_EdM, &BX_CPU_C::RCL_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_EdIb, &BX_CPU_C::RCR_EdM, &BX_CPU_C::RCR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_EdIb, &BX_CPU_C::SHL_EdM, &BX_CPU_C::SHL_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_EdIb, &BX_CPU_C::SHR_EdM, &BX_CPU_C::SHR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_EdIb, &BX_CPU_C::SAR_EdM, &BX_CPU_C::SAR_EdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETB_Eb, &BX_CPU_C::SETB_EbM, &BX_CPU_C::SETB_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETBE_Eb, &BX_CPU_C::SETBE_EbM, &BX_CPU_C::SETBE_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETL_Eb, &BX_CPU_C::SETL_EbM, &BX_CPU_C::SETL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETLE_Eb, &BX_CPU_C::SETLE_EbM, &BX_CPU_C::SETLE_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNB_Eb, &BX_CPU_C::SETNB_EbM, &BX_CPU_C::SETNB_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNBE_Eb, &BX_CPU_C::SETNBE_EbM, &BX_CPU_C::SETNBE_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNL_Eb, &BX_CPU_C::SETNL_EbM, &BX_CPU_C::SETNL_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNLE_Eb, &BX_CPU_C::SETNLE_EbM, &BX_CPU_C::SETNLE_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNO_Eb, &BX_CPU_C::SETNO_EbM, &BX_CPU_C::SETNO_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNP_Eb, &BX_CPU_C::SETNP_EbM, &BX_CPU_C::SETNP_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNS_Eb, &BX_CPU_C::SETNS_EbM, &BX_CPU_C::SETNS_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETNZ_Eb, &BX_CPU_C::SETNZ_EbM, &BX_CPU_C::SETNZ_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETO_Eb, &BX_CPU_C::SETO_EbM, &BX_CPU_C::SETO_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETP_Eb, &BX_CPU_C::SETP_EbM, &BX_CPU_C::SETP_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETS_Eb, &BX_CPU_C::SETS_EbM, &BX_CPU_C::SETS_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SETZ_Eb, &BX_CPU_C::SETZ_EbM, &BX_CPU_C::SETZ_EbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLD_EdGd, &BX_CPU_C::SHLD_EdGdM, &BX_CPU_C::SHLD_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLD_EdGdIb, &BX_CPU_C::SHLD_EdGdM, &BX_CPU_C::SHLD_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLD_EwGw, &BX_CPU_C::SHLD_EwGwM, &BX_CPU_C::SHLD_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLD_EwGwIb, &BX_CPU_C::SHLD_EwGwM, &BX_CPU_C::SHLD_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRD_EdGd, &BX_CPU_C::SHRD_EdGdM, &BX_CPU_C::SHRD_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRD_EdGdIb, &BX_CPU_C::SHRD_EdGdM, &BX_CPU_C::SHRD_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRD_EwGw, &BX_CPU_C::SHRD_EwGwM, &BX_CPU_C::SHRD_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRD_EwGwIb, &BX_CPU_C::SHRD_EwGwM, &BX_CPU_C::SHRD_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RSM, NULL, &BX_CPU_C::RSM, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SALC, NULL, &BX_CPU_C::SALC, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_STC, NULL, &BX_CPU_C::STC, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_STD, NULL, &BX_CPU_C::STD, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_STI, NULL, &BX_CPU_C::STI, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MUL_ALEb, &BX_CPU_C::LOAD_Eb, &BX_CPU_C::MUL_ALEbR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_ALEb, &BX_CPU_C::LOAD_Eb, &BX_CPU_C::IMUL_ALEbR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DIV_ALEb, &BX_CPU_C::LOAD_Eb, &BX_CPU_C::DIV_ALEbR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IDIV_ALEb, &BX_CPU_C::LOAD_Eb, &BX_CPU_C::IDIV_ALEbR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MUL_AXEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::MUL_AXEwR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_AXEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::IMUL_AXEwR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DIV_AXEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::DIV_AXEwR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IDIV_AXEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::IDIV_AXEwR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MUL_EAXEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::MUL_EAXEdR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_EAXEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::IMUL_EAXEdR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DIV_EAXEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::DIV_EAXEdR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IDIV_EAXEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::IDIV_EAXEdR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VERR_Ew, &BX_CPU_C::VERR_Ew, &BX_CPU_C::VERR_Ew, 0, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VERW_Ew, &BX_CPU_C::VERW_Ew, &BX_CPU_C::VERW_Ew, 0, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XCHG_EbGb, &BX_CPU_C::XCHG_EbGbM, &BX_CPU_C::XCHG_EbGbR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XCHG_EwGw, &BX_CPU_C::XCHG_EwGwM, &BX_CPU_C::XCHG_EwGwR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XCHG_EdGd, &BX_CPU_C::XCHG_EdGdM, &BX_CPU_C::XCHG_EdGdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XCHG_RXAX, NULL, &BX_CPU_C::XCHG_RXAX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XCHG_ERXEAX, NULL, &BX_CPU_C::XCHG_ERXEAX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XLAT, NULL, &BX_CPU_C::XLAT, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SYSENTER, NULL, &BX_CPU_C::SYSENTER, BX_ISA_SYSENTER_SYSEXIT, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SYSEXIT, NULL, &BX_CPU_C::SYSEXIT, BX_ISA_SYSENTER_SYSEXIT, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MONITOR, &BX_CPU_C::BxError, &BX_CPU_C::MONITOR, BX_ISA_MONITOR_MWAIT, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MWAIT, &BX_CPU_C::BxError, &BX_CPU_C::MWAIT, BX_ISA_MONITOR_MWAIT, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FWAIT, NULL, &BX_CPU_C::FWAIT, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_FPU bx_define_opcode(BX_IA_FLD_STi, &BX_CPU_C::FLD_STi, &BX_CPU_C::FLD_STi, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLD_SINGLE_REAL, &BX_CPU_C::FLD_SINGLE_REAL, &BX_CPU_C::FLD_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLD_DOUBLE_REAL, &BX_CPU_C::FLD_DOUBLE_REAL, &BX_CPU_C::FLD_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLD_EXTENDED_REAL, &BX_CPU_C::FLD_EXTENDED_REAL, &BX_CPU_C::FLD_EXTENDED_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FILD_WORD_INTEGER, &BX_CPU_C::FILD_WORD_INTEGER, &BX_CPU_C::FILD_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FILD_DWORD_INTEGER, &BX_CPU_C::FILD_DWORD_INTEGER, &BX_CPU_C::FILD_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FILD_QWORD_INTEGER, &BX_CPU_C::FILD_QWORD_INTEGER, &BX_CPU_C::FILD_QWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FBLD_PACKED_BCD, &BX_CPU_C::FBLD_PACKED_BCD, &BX_CPU_C::FBLD_PACKED_BCD, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FST_STi, &BX_CPU_C::FST_STi, &BX_CPU_C::FST_STi, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSTP_STi, &BX_CPU_C::FST_STi, &BX_CPU_C::FST_STi, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FST_SINGLE_REAL, &BX_CPU_C::FST_SINGLE_REAL, &BX_CPU_C::FST_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSTP_SINGLE_REAL, &BX_CPU_C::FST_SINGLE_REAL, &BX_CPU_C::FST_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FST_DOUBLE_REAL, &BX_CPU_C::FST_DOUBLE_REAL, &BX_CPU_C::FST_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSTP_DOUBLE_REAL, &BX_CPU_C::FST_DOUBLE_REAL, &BX_CPU_C::FST_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSTP_EXTENDED_REAL, &BX_CPU_C::FSTP_EXTENDED_REAL, &BX_CPU_C::FSTP_EXTENDED_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIST_WORD_INTEGER, &BX_CPU_C::FIST_WORD_INTEGER, &BX_CPU_C::FIST_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISTP_WORD_INTEGER, &BX_CPU_C::FIST_WORD_INTEGER, &BX_CPU_C::FIST_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIST_DWORD_INTEGER, &BX_CPU_C::FIST_DWORD_INTEGER, &BX_CPU_C::FIST_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISTP_DWORD_INTEGER, &BX_CPU_C::FIST_DWORD_INTEGER, &BX_CPU_C::FIST_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISTP_QWORD_INTEGER, &BX_CPU_C::FISTP_QWORD_INTEGER, &BX_CPU_C::FISTP_QWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FBSTP_PACKED_BCD, &BX_CPU_C::FBSTP_PACKED_BCD, &BX_CPU_C::FBSTP_PACKED_BCD, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISTTP16, &BX_CPU_C::FISTTP16, &BX_CPU_C::FISTTP16, BX_ISA_SSE3, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISTTP32, &BX_CPU_C::FISTTP32, &BX_CPU_C::FISTTP32, BX_ISA_SSE3, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISTTP64, &BX_CPU_C::FISTTP64, &BX_CPU_C::FISTTP64, BX_ISA_SSE3, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNINIT, &BX_CPU_C::FNINIT, &BX_CPU_C::FNINIT, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNCLEX, &BX_CPU_C::FNCLEX, &BX_CPU_C::FNCLEX, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FRSTOR, &BX_CPU_C::FRSTOR, &BX_CPU_C::FRSTOR, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNSAVE, &BX_CPU_C::FNSAVE, &BX_CPU_C::FNSAVE, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDENV, &BX_CPU_C::FLDENV, &BX_CPU_C::FLDENV, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNSTENV, &BX_CPU_C::FNSTENV, &BX_CPU_C::FNSTENV, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDCW, &BX_CPU_C::FLDCW, &BX_CPU_C::FLDCW, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNSTCW, &BX_CPU_C::FNSTCW, &BX_CPU_C::FNSTCW, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNSTSW, &BX_CPU_C::FNSTSW, &BX_CPU_C::FNSTSW, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNSTSW_AX, &BX_CPU_C::FNSTSW_AX, &BX_CPU_C::FNSTSW_AX, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLD1, &BX_CPU_C::FLD1, &BX_CPU_C::FLD1, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDL2T, &BX_CPU_C::FLDL2T, &BX_CPU_C::FLDL2T, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDL2E, &BX_CPU_C::FLDL2E, &BX_CPU_C::FLDL2E, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDPI, &BX_CPU_C::FLDPI, &BX_CPU_C::FLDPI, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDLG2, &BX_CPU_C::FLDLG2, &BX_CPU_C::FLDLG2, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDLN2, &BX_CPU_C::FLDLN2, &BX_CPU_C::FLDLN2, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FLDZ, &BX_CPU_C::FLDZ, &BX_CPU_C::FLDZ, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FADD_ST0_STj, &BX_CPU_C::FADD_ST0_STj, &BX_CPU_C::FADD_ST0_STj, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FADD_STi_ST0, &BX_CPU_C::FADD_STi_ST0, &BX_CPU_C::FADD_STi_ST0, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FADD_SINGLE_REAL, &BX_CPU_C::FADD_SINGLE_REAL, &BX_CPU_C::FADD_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FADD_DOUBLE_REAL, &BX_CPU_C::FADD_DOUBLE_REAL, &BX_CPU_C::FADD_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIADD_WORD_INTEGER, &BX_CPU_C::FIADD_WORD_INTEGER, &BX_CPU_C::FIADD_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIADD_DWORD_INTEGER, &BX_CPU_C::FIADD_DWORD_INTEGER, &BX_CPU_C::FIADD_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FMUL_ST0_STj, &BX_CPU_C::FMUL_ST0_STj, &BX_CPU_C::FMUL_ST0_STj, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FMUL_STi_ST0, &BX_CPU_C::FMUL_STi_ST0, &BX_CPU_C::FMUL_STi_ST0, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FMUL_SINGLE_REAL, &BX_CPU_C::FMUL_SINGLE_REAL, &BX_CPU_C::FMUL_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FMUL_DOUBLE_REAL, &BX_CPU_C::FMUL_DOUBLE_REAL, &BX_CPU_C::FMUL_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIMUL_WORD_INTEGER , &BX_CPU_C::FIMUL_WORD_INTEGER , &BX_CPU_C::FIMUL_WORD_INTEGER , BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIMUL_DWORD_INTEGER, &BX_CPU_C::FIMUL_DWORD_INTEGER, &BX_CPU_C::FIMUL_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUB_ST0_STj, &BX_CPU_C::FSUB_ST0_STj, &BX_CPU_C::FSUB_ST0_STj, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUBR_ST0_STj, &BX_CPU_C::FSUBR_ST0_STj, &BX_CPU_C::FSUBR_ST0_STj, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUB_STi_ST0, &BX_CPU_C::FSUB_STi_ST0, &BX_CPU_C::FSUB_STi_ST0, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUBR_STi_ST0, &BX_CPU_C::FSUBR_STi_ST0, &BX_CPU_C::FSUBR_STi_ST0, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUB_SINGLE_REAL, &BX_CPU_C::FSUB_SINGLE_REAL, &BX_CPU_C::FSUB_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUBR_SINGLE_REAL, &BX_CPU_C::FSUBR_SINGLE_REAL, &BX_CPU_C::FSUBR_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUB_DOUBLE_REAL, &BX_CPU_C::FSUB_DOUBLE_REAL, &BX_CPU_C::FSUB_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSUBR_DOUBLE_REAL, &BX_CPU_C::FSUBR_DOUBLE_REAL, &BX_CPU_C::FSUBR_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISUB_WORD_INTEGER, &BX_CPU_C::FISUB_WORD_INTEGER, &BX_CPU_C::FISUB_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISUBR_WORD_INTEGER, &BX_CPU_C::FISUBR_WORD_INTEGER, &BX_CPU_C::FISUBR_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISUB_DWORD_INTEGER, &BX_CPU_C::FISUB_DWORD_INTEGER, &BX_CPU_C::FISUB_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FISUBR_DWORD_INTEGER, &BX_CPU_C::FISUBR_DWORD_INTEGER, &BX_CPU_C::FISUBR_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIV_ST0_STj, &BX_CPU_C::FDIV_ST0_STj, &BX_CPU_C::FDIV_ST0_STj, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIVR_ST0_STj, &BX_CPU_C::FDIVR_ST0_STj, &BX_CPU_C::FDIVR_ST0_STj, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIV_STi_ST0, &BX_CPU_C::FDIV_STi_ST0, &BX_CPU_C::FDIV_STi_ST0, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIVR_STi_ST0, &BX_CPU_C::FDIVR_STi_ST0, &BX_CPU_C::FDIVR_STi_ST0, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIV_SINGLE_REAL, &BX_CPU_C::FDIV_SINGLE_REAL, &BX_CPU_C::FDIV_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIVR_SINGLE_REAL, &BX_CPU_C::FDIVR_SINGLE_REAL, &BX_CPU_C::FDIVR_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIV_DOUBLE_REAL, &BX_CPU_C::FDIV_DOUBLE_REAL, &BX_CPU_C::FDIV_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDIVR_DOUBLE_REAL, &BX_CPU_C::FDIVR_DOUBLE_REAL, &BX_CPU_C::FDIVR_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIDIV_WORD_INTEGER, &BX_CPU_C::FIDIV_WORD_INTEGER, &BX_CPU_C::FIDIV_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIDIVR_WORD_INTEGER, &BX_CPU_C::FIDIVR_WORD_INTEGER, &BX_CPU_C::FIDIVR_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIDIV_DWORD_INTEGER, &BX_CPU_C::FIDIV_DWORD_INTEGER, &BX_CPU_C::FIDIV_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FIDIVR_DWORD_INTEGER, &BX_CPU_C::FIDIVR_DWORD_INTEGER, &BX_CPU_C::FIDIVR_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOM_STi, &BX_CPU_C::FCOM_STi, &BX_CPU_C::FCOM_STi, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOMP_STi, &BX_CPU_C::FCOM_STi, &BX_CPU_C::FCOM_STi, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FUCOM_STi, &BX_CPU_C::FUCOM_STi, &BX_CPU_C::FUCOM_STi, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FUCOMP_STi, &BX_CPU_C::FUCOM_STi, &BX_CPU_C::FUCOM_STi, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOMI_ST0_STj, &BX_CPU_C::FCOMI_ST0_STj, &BX_CPU_C::FCOMI_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOMIP_ST0_STj, &BX_CPU_C::FCOMI_ST0_STj, &BX_CPU_C::FCOMI_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FUCOMI_ST0_STj, &BX_CPU_C::FUCOMI_ST0_STj, &BX_CPU_C::FUCOMI_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FUCOMIP_ST0_STj, &BX_CPU_C::FUCOMI_ST0_STj, &BX_CPU_C::FUCOMI_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOM_SINGLE_REAL, &BX_CPU_C::FCOM_SINGLE_REAL, &BX_CPU_C::FCOM_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOMP_SINGLE_REAL, &BX_CPU_C::FCOM_SINGLE_REAL, &BX_CPU_C::FCOM_SINGLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOM_DOUBLE_REAL, &BX_CPU_C::FCOM_DOUBLE_REAL, &BX_CPU_C::FCOM_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOMP_DOUBLE_REAL, &BX_CPU_C::FCOM_DOUBLE_REAL, &BX_CPU_C::FCOM_DOUBLE_REAL, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FICOM_WORD_INTEGER, &BX_CPU_C::FICOM_WORD_INTEGER, &BX_CPU_C::FICOM_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FICOMP_WORD_INTEGER, &BX_CPU_C::FICOM_WORD_INTEGER, &BX_CPU_C::FICOM_WORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FICOM_DWORD_INTEGER, &BX_CPU_C::FICOM_DWORD_INTEGER, &BX_CPU_C::FICOM_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FICOMP_DWORD_INTEGER, &BX_CPU_C::FICOM_DWORD_INTEGER, &BX_CPU_C::FICOM_DWORD_INTEGER, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVB_ST0_STj, &BX_CPU_C::FCMOVB_ST0_STj, &BX_CPU_C::FCMOVB_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVE_ST0_STj, &BX_CPU_C::FCMOVE_ST0_STj, &BX_CPU_C::FCMOVE_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVBE_ST0_STj, &BX_CPU_C::FCMOVBE_ST0_STj, &BX_CPU_C::FCMOVBE_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVU_ST0_STj, &BX_CPU_C::FCMOVU_ST0_STj, &BX_CPU_C::FCMOVU_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVNB_ST0_STj, &BX_CPU_C::FCMOVNB_ST0_STj, &BX_CPU_C::FCMOVNB_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVNE_ST0_STj, &BX_CPU_C::FCMOVNE_ST0_STj, &BX_CPU_C::FCMOVNE_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVNBE_ST0_STj, &BX_CPU_C::FCMOVNBE_ST0_STj, &BX_CPU_C::FCMOVNBE_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCMOVNU_ST0_STj, &BX_CPU_C::FCMOVNU_ST0_STj, &BX_CPU_C::FCMOVNU_ST0_STj, BX_ISA_P6, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOMPP, &BX_CPU_C::FCOMPP, &BX_CPU_C::FCOMPP, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FUCOMPP, &BX_CPU_C::FUCOMPP, &BX_CPU_C::FUCOMPP, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FXCH_STi, &BX_CPU_C::FXCH_STi, &BX_CPU_C::FXCH_STi, BX_ISA_X87, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FNOP, &BX_CPU_C::FNOP, &BX_CPU_C::FNOP, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FPLEGACY, &BX_CPU_C::FPLEGACY, &BX_CPU_C::FPLEGACY, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCHS, &BX_CPU_C::FCHS, &BX_CPU_C::FCHS, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FABS, &BX_CPU_C::FABS, &BX_CPU_C::FABS, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FTST, &BX_CPU_C::FTST, &BX_CPU_C::FTST, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FXAM, &BX_CPU_C::FXAM, &BX_CPU_C::FXAM, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FDECSTP, &BX_CPU_C::FDECSTP, &BX_CPU_C::FDECSTP, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FINCSTP, &BX_CPU_C::FINCSTP, &BX_CPU_C::FINCSTP, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FFREE_STi, &BX_CPU_C::FFREE_STi, &BX_CPU_C::FFREE_STi, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FFREEP_STi, &BX_CPU_C::FFREEP_STi, &BX_CPU_C::FFREEP_STi, BX_ISA_X87, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_F2XM1, &BX_CPU_C::F2XM1, &BX_CPU_C::F2XM1, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FYL2X, &BX_CPU_C::FYL2X, &BX_CPU_C::FYL2X, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FPTAN, &BX_CPU_C::FPTAN, &BX_CPU_C::FPTAN, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FPATAN, &BX_CPU_C::FPATAN, &BX_CPU_C::FPATAN, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FXTRACT, &BX_CPU_C::FXTRACT, &BX_CPU_C::FXTRACT, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FPREM1, &BX_CPU_C::FPREM1, &BX_CPU_C::FPREM1, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FPREM, &BX_CPU_C::FPREM, &BX_CPU_C::FPREM, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FYL2XP1, &BX_CPU_C::FYL2XP1, &BX_CPU_C::FYL2XP1, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSQRT, &BX_CPU_C::FSQRT, &BX_CPU_C::FSQRT, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSINCOS, &BX_CPU_C::FSINCOS, &BX_CPU_C::FSINCOS, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FRNDINT, &BX_CPU_C::FRNDINT, &BX_CPU_C::FRNDINT, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSCALE, &BX_CPU_C::FSCALE, &BX_CPU_C::FSCALE, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FSIN, &BX_CPU_C::FSIN, &BX_CPU_C::FSIN, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FCOS, &BX_CPU_C::FCOS, &BX_CPU_C::FCOS, BX_ISA_X87, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #else bx_define_opcode(BX_IA_FPU_ESC, &BX_CPU_C::FPU_ESC, &BX_CPU_C::FPU_ESC, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #endif // 486 new instructions bx_define_opcode(BX_IA_CPUID, NULL, &BX_CPU_C::CPUID, BX_ISA_486, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSWAP_RX, NULL, &BX_CPU_C::BSWAP_RX, BX_ISA_486, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSWAP_ERX, NULL, &BX_CPU_C::BSWAP_ERX, BX_ISA_486, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INVD, NULL, &BX_CPU_C::INVD, BX_ISA_486, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_WBINVD, NULL, &BX_CPU_C::WBINVD, BX_ISA_486, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XADD_EbGb, &BX_CPU_C::XADD_EbGbM, &BX_CPU_C::XADD_EbGbR, BX_ISA_486, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XADD_EwGw, &BX_CPU_C::XADD_EwGwM, &BX_CPU_C::XADD_EwGwR, BX_ISA_486, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XADD_EdGd, &BX_CPU_C::XADD_EdGdM, &BX_CPU_C::XADD_EdGdR, BX_ISA_486, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMPXCHG_EbGb, &BX_CPU_C::CMPXCHG_EbGbM, &BX_CPU_C::CMPXCHG_EbGbR, BX_ISA_486, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMPXCHG_EwGw, &BX_CPU_C::CMPXCHG_EwGwM, &BX_CPU_C::CMPXCHG_EwGwR, BX_ISA_486, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMPXCHG_EdGd, &BX_CPU_C::CMPXCHG_EdGdM, &BX_CPU_C::CMPXCHG_EdGdR, BX_ISA_486, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INVLPG, &BX_CPU_C::INVLPG, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // 486 new instructions // Pentium new instructions bx_define_opcode(BX_IA_CMPXCHG8B, &BX_CPU_C::CMPXCHG8B, &BX_CPU_C::BxError, BX_ISA_PENTIUM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_WRMSR, NULL, &BX_CPU_C::WRMSR, BX_ISA_PENTIUM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RDMSR, NULL, &BX_CPU_C::RDMSR, BX_ISA_PENTIUM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RDTSC, NULL, &BX_CPU_C::RDTSC, BX_ISA_PENTIUM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // Pentium new instructions // MMX bx_define_opcode(BX_IA_PUNPCKLBW_PqQd, &BX_CPU_C::PUNPCKLBW_PqQd, &BX_CPU_C::PUNPCKLBW_PqQd, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUNPCKLWD_PqQd, &BX_CPU_C::PUNPCKLWD_PqQd, &BX_CPU_C::PUNPCKLWD_PqQd, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUNPCKLDQ_PqQd, &BX_CPU_C::PUNPCKLDQ_PqQd, &BX_CPU_C::PUNPCKLDQ_PqQd, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PACKSSWB_PqQq, &BX_CPU_C::PACKSSWB_PqQq, &BX_CPU_C::PACKSSWB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PCMPGTB_PqQq, &BX_CPU_C::PCMPGTB_PqQq, &BX_CPU_C::PCMPGTB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PCMPGTW_PqQq, &BX_CPU_C::PCMPGTW_PqQq, &BX_CPU_C::PCMPGTW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PCMPGTD_PqQq, &BX_CPU_C::PCMPGTD_PqQq, &BX_CPU_C::PCMPGTD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PACKUSWB_PqQq, &BX_CPU_C::PACKUSWB_PqQq, &BX_CPU_C::PACKUSWB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUNPCKHBW_PqQq, &BX_CPU_C::PUNPCKHBW_PqQq, &BX_CPU_C::PUNPCKHBW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUNPCKHWD_PqQq, &BX_CPU_C::PUNPCKHWD_PqQq, &BX_CPU_C::PUNPCKHWD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUNPCKHDQ_PqQq, &BX_CPU_C::PUNPCKHDQ_PqQq, &BX_CPU_C::PUNPCKHDQ_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PACKSSDW_PqQq, &BX_CPU_C::PACKSSDW_PqQq, &BX_CPU_C::PACKSSDW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVD_PqEd, &BX_CPU_C::MOVD_PqEdM, &BX_CPU_C::MOVD_PqEdR, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVQ_PqQq, &BX_CPU_C::MOVQ_PqQqM, &BX_CPU_C::MOVQ_PqQqR, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PCMPEQB_PqQq, &BX_CPU_C::PCMPEQB_PqQq, &BX_CPU_C::PCMPEQB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PCMPEQW_PqQq, &BX_CPU_C::PCMPEQW_PqQq, &BX_CPU_C::PCMPEQW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PCMPEQD_PqQq, &BX_CPU_C::PCMPEQD_PqQq, &BX_CPU_C::PCMPEQD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_EMMS, NULL, &BX_CPU_C::EMMS, BX_ISA_MMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVD_EdPd, &BX_CPU_C::MOVD_EdPdM, &BX_CPU_C::MOVD_EdPdR, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVQ_QqPq, &BX_CPU_C::MOVQ_QqPqM, &BX_CPU_C::MOVQ_PqQqR, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRLW_PqQq, &BX_CPU_C::PSRLW_PqQq, &BX_CPU_C::PSRLW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRLD_PqQq, &BX_CPU_C::PSRLD_PqQq, &BX_CPU_C::PSRLD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRLQ_PqQq, &BX_CPU_C::PSRLQ_PqQq, &BX_CPU_C::PSRLQ_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMULLW_PqQq, &BX_CPU_C::PMULLW_PqQq, &BX_CPU_C::PMULLW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBUSB_PqQq, &BX_CPU_C::PSUBUSB_PqQq, &BX_CPU_C::PSUBUSB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBUSW_PqQq, &BX_CPU_C::PSUBUSW_PqQq, &BX_CPU_C::PSUBUSW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PAND_PqQq, &BX_CPU_C::PAND_PqQq, &BX_CPU_C::PAND_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDUSB_PqQq, &BX_CPU_C::PADDUSB_PqQq, &BX_CPU_C::PADDUSB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDUSW_PqQq, &BX_CPU_C::PADDUSW_PqQq, &BX_CPU_C::PADDUSW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PANDN_PqQq, &BX_CPU_C::PANDN_PqQq, &BX_CPU_C::PANDN_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRAW_PqQq, &BX_CPU_C::PSRAW_PqQq, &BX_CPU_C::PSRAW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRAD_PqQq, &BX_CPU_C::PSRAD_PqQq, &BX_CPU_C::PSRAD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMULHW_PqQq, &BX_CPU_C::PMULHW_PqQq, &BX_CPU_C::PMULHW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBSB_PqQq, &BX_CPU_C::PSUBSB_PqQq, &BX_CPU_C::PSUBSB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBSW_PqQq, &BX_CPU_C::PSUBSW_PqQq, &BX_CPU_C::PSUBSW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POR_PqQq, &BX_CPU_C::POR_PqQq, &BX_CPU_C::POR_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDSB_PqQq, &BX_CPU_C::PADDSB_PqQq, &BX_CPU_C::PADDSB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDSW_PqQq, &BX_CPU_C::PADDSW_PqQq, &BX_CPU_C::PADDSW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PXOR_PqQq, &BX_CPU_C::PXOR_PqQq, &BX_CPU_C::PXOR_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSLLW_PqQq, &BX_CPU_C::PSLLW_PqQq, &BX_CPU_C::PSLLW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSLLD_PqQq, &BX_CPU_C::PSLLD_PqQq, &BX_CPU_C::PSLLD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSLLQ_PqQq, &BX_CPU_C::PSLLQ_PqQq, &BX_CPU_C::PSLLQ_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMADDWD_PqQq, &BX_CPU_C::PMADDWD_PqQq, &BX_CPU_C::PMADDWD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBB_PqQq, &BX_CPU_C::PSUBB_PqQq, &BX_CPU_C::PSUBB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBW_PqQq, &BX_CPU_C::PSUBW_PqQq, &BX_CPU_C::PSUBW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBD_PqQq, &BX_CPU_C::PSUBD_PqQq, &BX_CPU_C::PSUBD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDB_PqQq, &BX_CPU_C::PADDB_PqQq, &BX_CPU_C::PADDB_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDW_PqQq, &BX_CPU_C::PADDW_PqQq, &BX_CPU_C::PADDW_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDD_PqQq, &BX_CPU_C::PADDD_PqQq, &BX_CPU_C::PADDD_PqQq, BX_ISA_MMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRLW_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRLW_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRAW_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRAW_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSLLW_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSLLW_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRLD_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRLD_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRAD_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRAD_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSLLD_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSLLD_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSRLQ_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRLQ_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSLLQ_PqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSLLQ_PqIb, BX_ISA_MMX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_MOVQ_EqPq, &BX_CPU_C::MOVQ_QqPqM, &BX_CPU_C::MOVQ_EqPqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) #endif // MMX bx_define_opcode(BX_IA_FEMMS, NULL, &BX_CPU_C::EMMS, BX_ISA_3DNOW, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_3DNOW bx_define_opcode(BX_IA_PF2ID_PqQq, &BX_CPU_C::PF2ID_PqQq, &BX_CPU_C::PF2ID_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PF2IW_PqQq, &BX_CPU_C::PF2IW_PqQq, &BX_CPU_C::PF2IW_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFACC_PqQq, &BX_CPU_C::PFACC_PqQq, &BX_CPU_C::PFACC_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFADD_PqQq, &BX_CPU_C::PFADD_PqQq, &BX_CPU_C::PFADD_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFCMPEQ_PqQq, &BX_CPU_C::PFCMPEQ_PqQq, &BX_CPU_C::PFCMPEQ_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFCMPGE_PqQq, &BX_CPU_C::PFCMPGE_PqQq, &BX_CPU_C::PFCMPGE_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFCMPGT_PqQq, &BX_CPU_C::PFCMPGT_PqQq, &BX_CPU_C::PFCMPGT_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFMAX_PqQq, &BX_CPU_C::PFMAX_PqQq, &BX_CPU_C::PFMAX_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFMIN_PqQq, &BX_CPU_C::PFMIN_PqQq, &BX_CPU_C::PFMIN_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFMUL_PqQq, &BX_CPU_C::PFMUL_PqQq, &BX_CPU_C::PFMUL_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFNACC_PqQq, &BX_CPU_C::PFNACC_PqQq, &BX_CPU_C::PFNACC_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFPNACC_PqQq, &BX_CPU_C::PFPNACC_PqQq, &BX_CPU_C::PFPNACC_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFRCP_PqQq, &BX_CPU_C::PFRCP_PqQq, &BX_CPU_C::PFRCP_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFRCPIT1_PqQq, &BX_CPU_C::PFRCPIT1_PqQq, &BX_CPU_C::PFRCPIT1_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFRCPIT2_PqQq, &BX_CPU_C::PFRCPIT2_PqQq, &BX_CPU_C::PFRCPIT2_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFRSQIT1_PqQq, &BX_CPU_C::PFRSQIT1_PqQq, &BX_CPU_C::PFRSQIT1_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFRSQRT_PqQq, &BX_CPU_C::PFRSQRT_PqQq, &BX_CPU_C::PFRSQRT_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFSUB_PqQq, &BX_CPU_C::PFSUB_PqQq, &BX_CPU_C::PFSUB_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PFSUBR_PqQq, &BX_CPU_C::PFSUBR_PqQq, &BX_CPU_C::PFSUBR_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PI2FD_PqQq, &BX_CPU_C::PI2FD_PqQq, &BX_CPU_C::PI2FD_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PI2FW_PqQq, &BX_CPU_C::PI2FW_PqQq, &BX_CPU_C::PI2FW_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMULHRW_PqQq, &BX_CPU_C::PMULHRW_PqQq, &BX_CPU_C::PMULHRW_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSWAPD_PqQq, &BX_CPU_C::PSWAPD_PqQq, &BX_CPU_C::PSWAPD_PqQq, BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bx_define_opcode(BX_IA_PREFETCHW, &BX_CPU_C::NOP, &BX_CPU_C::NOP, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // NOP even when no 3DNow! bx_define_opcode(BX_IA_SYSCALL_LEGACY, NULL, &BX_CPU_C::SYSCALL, BX_ISA_SYSCALL_SYSRET_LEGACY, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SYSRET_LEGACY, NULL, &BX_CPU_C::SYSRET, BX_ISA_SYSCALL_SYSRET_LEGACY, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // P6 new instructions bx_define_opcode(BX_IA_CMOVB_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVB_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVBE_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVBE_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVL_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVL_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVLE_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVLE_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNB_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNB_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNBE_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNBE_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNL_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNL_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNLE_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNLE_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNO_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNO_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNP_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNP_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNS_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNS_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNZ_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVNZ_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVO_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVO_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVP_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVP_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVS_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVS_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVZ_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CMOVZ_GwEwR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVB_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVB_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVBE_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVBE_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVL_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVL_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVLE_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVLE_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNB_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNB_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNBE_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNBE_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNL_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNL_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNLE_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNLE_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNO_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNO_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNP_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNP_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNS_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNS_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNZ_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVNZ_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVO_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVO_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVP_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVP_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVS_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVS_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVZ_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CMOVZ_GdEdR, BX_ISA_P6, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RDPMC, NULL, &BX_CPU_C::RDPMC, BX_ISA_P6, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_UD2A, &BX_CPU_C::UndefinedOpcode, &BX_CPU_C::UndefinedOpcode, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_UD2B, &BX_CPU_C::UndefinedOpcode, &BX_CPU_C::UndefinedOpcode, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // P6 new instructions // FXSAVE bx_define_opcode(BX_IA_FXSAVE, &BX_CPU_C::FXSAVE, &BX_CPU_C::BxError, BX_ISA_SSE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_FXRSTOR, &BX_CPU_C::FXRSTOR, &BX_CPU_C::BxError, BX_ISA_SSE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // FXSAVE // SSE bx_define_opcode(BX_IA_LDMXCSR, &BX_CPU_C::LDMXCSR, &BX_CPU_C::BxError, BX_ISA_SSE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_STMXCSR, &BX_CPU_C::STMXCSR, &BX_CPU_C::BxError, BX_ISA_SSE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PREFETCH, &BX_CPU_C::PREFETCH, &BX_CPU_C::NOP, BX_ISA_SSE, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) // SSE // SSE bx_define_opcode(BX_IA_ANDPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ANDPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ORPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ORPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_XORPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::XORPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ANDNPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ANDNPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVUPS_VpsWps, &BX_CPU_C::MOVUPS_VpsWpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVUPS_WpsVps, &BX_CPU_C::MOVUPS_WpsVpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVSS_VssWss, &BX_CPU_C::MOVSS_VssWssM, &BX_CPU_C::MOVSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVSS_WssVss, &BX_CPU_C::MOVSS_WssVssM, &BX_CPU_C::MOVSS_VssWssR, BX_ISA_SSE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVLPS_VpsMq, &BX_CPU_C::MOVLPS_VpsMq, &BX_CPU_C::MOVHLPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVLPS_MqVps, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::BxError, BX_ISA_SSE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVHPS_VpsMq, &BX_CPU_C::MOVHPS_VpsMq, &BX_CPU_C::MOVLHPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVHPS_MqVps, &BX_CPU_C::MOVHPS_MqVps, &BX_CPU_C::BxError, BX_ISA_SSE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVAPS_VpsWps, &BX_CPU_C::MOVAPS_VpsWpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVAPS_WpsVps, &BX_CPU_C::MOVAPS_WpsVpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPI2PS_VpsQq, &BX_CPU_C::CVTPI2PS_VpsQqM, &BX_CPU_C::CVTPI2PS_VpsQqR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSI2SS_VssEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CVTSI2SS_VssEdR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVNTPS_MpsVps, &BX_CPU_C::MOVAPS_WpsVpsM, &BX_CPU_C::BxError, BX_ISA_SSE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTPS2PI_PqWps, &BX_CPU_C::CVTTPS2PI_PqWps, &BX_CPU_C::CVTTPS2PI_PqWps, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTSS2SI_GdWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTTSS2SI_GdWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPS2PI_PqWps, &BX_CPU_C::CVTPS2PI_PqWps, &BX_CPU_C::CVTPS2PI_PqWps, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSS2SI_GdWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTSS2SI_GdWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_UCOMISS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::UCOMISS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_COMISS_VpsWps, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::COMISS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVMSKPS_GdVRps, &BX_CPU_C::BxError, &BX_CPU_C::MOVMSKPS_GdVRps, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SQRTPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::SQRTPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SQRTSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::SQRTSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_RSQRTPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::RSQRTPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_RSQRTSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::RSQRTSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_RCPPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::RCPPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_RCPSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::RCPSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ADDPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ADDPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ADDSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::ADDSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MULPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MULPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MULSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::MULSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SUBPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::SUBPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SUBSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::SUBSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MINPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MINPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MINSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::MINSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_DIVPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::DIVPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_DIVSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::DIVSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MAXPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MAXPS_VpsWpsR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MAXSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::MAXSS_VssWssR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSHUFW_PqQqIb, &BX_CPU_C::PSHUFW_PqQqIb, &BX_CPU_C::PSHUFW_PqQqIb, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSHUFLW_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSHUFLW_VdqWdqIbR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CMPPS_VpsWpsIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CMPPS_VpsWpsIbR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CMPSS_VssWssIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CMPSS_VssWssIbR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PINSRW_PqEwIb, &BX_CPU_C::PINSRW_PqEwIb, &BX_CPU_C::PINSRW_PqEwIb, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PEXTRW_GdPqIb, &BX_CPU_C::BxError, &BX_CPU_C::PEXTRW_GdPqIb, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHUFPS_VpsWpsIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::SHUFPS_VpsWpsIbR, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVMSKB_GdPRq, &BX_CPU_C::BxError, &BX_CPU_C::PMOVMSKB_GdPRq, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMINUB_PqQq, &BX_CPU_C::PMINUB_PqQq, &BX_CPU_C::PMINUB_PqQq, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMAXUB_PqQq, &BX_CPU_C::PMAXUB_PqQq, &BX_CPU_C::PMAXUB_PqQq, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PAVGB_PqQq, &BX_CPU_C::PAVGB_PqQq, &BX_CPU_C::PAVGB_PqQq, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PAVGW_PqQq, &BX_CPU_C::PAVGW_PqQq, &BX_CPU_C::PAVGW_PqQq, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMULHUW_PqQq, &BX_CPU_C::PMULHUW_PqQq, &BX_CPU_C::PMULHUW_PqQq, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVNTQ_MqPq, &BX_CPU_C::MOVQ_QqPqM, &BX_CPU_C::BxError, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMINSW_PqQq, &BX_CPU_C::PMINSW_PqQq, &BX_CPU_C::PMINSW_PqQq, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMAXSW_PqQq, &BX_CPU_C::PMAXSW_PqQq, &BX_CPU_C::PMAXSW_PqQq, BX_ISA_SSE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSADBW_PqQq, &BX_CPU_C::PSADBW_PqQq, &BX_CPU_C::PSADBW_PqQq, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MASKMOVQ_PqPRq, &BX_CPU_C::BxError, &BX_CPU_C::MASKMOVQ_PqPRq, BX_ISA_SSE | BX_ISA_3DNOW, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, 0) // SSE // SSE2 bx_define_opcode(BX_IA_MOVSD_VsdWsd, &BX_CPU_C::MOVQ_VqWqM, &BX_CPU_C::MOVSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVSD_WsdVsd, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::MOVSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPI2PD_VpdQq, &BX_CPU_C::CVTPI2PD_VpdQqM, &BX_CPU_C::CVTPI2PD_VpdQqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSI2SD_VsdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CVTSI2SD_VsdEdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTPD2PI_PqWpd, &BX_CPU_C::CVTTPD2PI_PqWpd, &BX_CPU_C::CVTTPD2PI_PqWpd, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTSD2SI_GdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTTSD2SI_GdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPD2PI_PqWpd, &BX_CPU_C::CVTPD2PI_PqWpd, &BX_CPU_C::CVTPD2PI_PqWpd, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSD2SI_GdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTSD2SI_GdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_UCOMISD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::UCOMISD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_COMISD_VpdWpd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::COMISD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVMSKPD_GdVRpd, &BX_CPU_C::BxError, &BX_CPU_C::MOVMSKPD_GdVRpd, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SQRTPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::SQRTPD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SQRTSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::SQRTSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ADDPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ADDPD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ADDSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::ADDSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MULPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MULPD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MULSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::MULSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SUBPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::SUBPD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SUBSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::SUBSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MINPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MINPD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MINSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::MINSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_DIVPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::DIVPD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_DIVSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::DIVSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MAXPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MAXPD_VpdWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MAXSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::MAXSD_VsdWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPS2PD_VpdWps, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTPS2PD_VpdWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPD2PS_VpsWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CVTPD2PS_VpsWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSD2SS_VssWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTSD2SS_VssWsdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSS2SD_VsdWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTSS2SD_VsdWssR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTDQ2PS_VpsWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CVTDQ2PS_VpsWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPS2DQ_VdqWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CVTPS2DQ_VdqWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTPS2DQ_VdqWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CVTTPS2DQ_VdqWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_UNPCKHPD_VpdWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKHQDQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_UNPCKLPD_VpdWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKLQDQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKHDQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::UNPCKHPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKLDQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::UNPCKLPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVAPD_VpdWpd, &BX_CPU_C::MOVAPS_VpsWpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVAPD_WpdVpd, &BX_CPU_C::MOVAPS_WpsVpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVDQA_VdqWdq, &BX_CPU_C::MOVAPS_VpsWpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVDQA_WdqVdq, &BX_CPU_C::MOVAPS_WpsVpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVDQU_VdqWdq, &BX_CPU_C::MOVUPS_VpsWpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVDQU_WdqVdq, &BX_CPU_C::MOVUPS_WpsVpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVHPD_MqVsd, &BX_CPU_C::MOVHPS_MqVps, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVHPD_VsdMq, &BX_CPU_C::MOVHPS_VpsMq, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVLPD_MqVsd, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVLPD_VsdMq, &BX_CPU_C::MOVLPS_VpsMq, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVNTDQ_MdqVdq, &BX_CPU_C::MOVAPS_WpsVpsM, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVNTPD_MpdVpd, &BX_CPU_C::MOVAPS_WpsVpsM, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVUPD_VpdWpd, &BX_CPU_C::MOVUPS_VpsWpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVUPD_WpdVpd, &BX_CPU_C::MOVUPS_WpsVpsM, &BX_CPU_C::MOVAPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ANDNPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ANDNPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ANDPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ANDPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ORPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ORPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_XORPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::XORPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PAND_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ANDPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PANDN_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ANDNPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_POR_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ORPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PXOR_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::XORPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKLBW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKLBW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKLWD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKLWD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_UNPCKLPS_VpsWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::UNPCKLPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PACKSSWB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PACKSSWB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPGTB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPGTB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPGTW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPGTW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPGTD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPGTD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PACKUSWB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PACKUSWB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKHBW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKHBW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKHWD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKHWD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_UNPCKHPS_VpsWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::UNPCKHPS_VpsWpsR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PACKSSDW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PACKSSDW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKLQDQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKLQDQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PUNPCKHQDQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PUNPCKHQDQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVD_VdqEd, &BX_CPU_C::MOVSS_VssWssM, &BX_CPU_C::MOVD_VdqEdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSHUFD_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSHUFD_VdqWdqIbR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSHUFHW_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSHUFHW_VdqWdqIbR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPEQB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPEQB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPEQW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPEQW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPEQD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPEQD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVD_EdVd, &BX_CPU_C::MOVSS_WssVssM, &BX_CPU_C::MOVD_EdVdR, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVQ_VqWq, &BX_CPU_C::MOVQ_VqWqM, &BX_CPU_C::MOVQ_VqWqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CMPPD_VpdWpdIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CMPPD_VpdWpdIbR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CMPSD_VsdWsdIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CMPSD_VsdWsdIbR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVNTI32_MdGd, &BX_CPU_C::MOV32_EdGdM, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PINSRW_VdqEwIb, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::PINSRW_VdqHdqEwIbR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PEXTRW_GdUdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PEXTRW_GdUdqIb, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_SHUFPD_VpdWpdIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::SHUFPD_VpdWpdIbR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRLW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSRLW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRLD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSRLD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRLQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSRLQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDQ_PqQq, &BX_CPU_C::PADDQ_PqQq, &BX_CPU_C::PADDQ_PqQq, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PADDQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMULLW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMULLW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVQ_WqVq, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::MOVQ_VqWqR, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVDQ2Q_PqVRq, &BX_CPU_C::BxError, &BX_CPU_C::MOVDQ2Q_PqVRq, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVQ2DQ_VdqQq, &BX_CPU_C::BxError, &BX_CPU_C::MOVQ2DQ_VdqQq, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVMSKB_GdUdq, &BX_CPU_C::BxError, &BX_CPU_C::PMOVMSKB_GdUdq, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBUSB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBUSB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBUSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBUSW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMINUB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMINUB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDUSB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDUSB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDUSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDUSW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMAXUB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMAXUB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PAVGB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PAVGB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRAW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSRAW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRAD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSRAD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PAVGW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PAVGW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMULHUW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMULHUW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMULHW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMULHW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTPD2DQ_VqWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CVTTPD2DQ_VqWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTPD2DQ_VqWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::CVTPD2DQ_VqWpdR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTDQ2PD_VpdWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTDQ2PD_VpdWqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBSB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBSB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBSW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMINSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMINSW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDSB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDSB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDSW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMAXSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMAXSW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSLLW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSLLW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSLLD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSLLD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSLLQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSLLQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMULUDQ_PqQq, &BX_CPU_C::PMULUDQ_PqQq, &BX_CPU_C::PMULUDQ_PqQq, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMULUDQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMULUDQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMADDWD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMADDWD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSADBW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSADBW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MASKMOVDQU_VdqUdq, &BX_CPU_C::BxError, &BX_CPU_C::MASKMOVDQU_VdqUdq, BX_ISA_SSE2, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSUBQ_PqQq, &BX_CPU_C::PSUBQ_PqQq, &BX_CPU_C::PSUBQ_PqQq, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSUBQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSUBQ_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDB_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDW_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PADDD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PADDD_VdqWdqR, BX_ISA_SSE2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRLW_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRLW_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRAW_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRAW_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSLLW_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSLLW_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRLD_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRLD_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRAD_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRAD_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSLLD_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSLLD_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRLQ_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRLQ_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSRLDQ_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSRLDQ_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSLLQ_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSLLQ_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSLLDQ_UdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PSLLDQ_UdqIb, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_LFENCE, &BX_CPU_C::BxError, &BX_CPU_C::NOP, BX_ISA_SSE2, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SFENCE, &BX_CPU_C::BxError, &BX_CPU_C::NOP, BX_ISA_SSE2, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MFENCE, &BX_CPU_C::BxError, &BX_CPU_C::NOP, BX_ISA_SSE2, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // SSE2 // SSE3 bx_define_opcode(BX_IA_MOVDDUP_VpdWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::MOVDDUP_VpdWqR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVSLDUP_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MOVSLDUP_VpsWpsR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVSHDUP_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MOVSHDUP_VpsWpsR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_HADDPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::HADDPD_VpdWpdR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_HADDPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::HADDPS_VpsWpsR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_HSUBPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::HSUBPD_VpdWpdR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_HSUBPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::HSUBPS_VpsWpsR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ADDSUBPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ADDSUBPD_VpdWpdR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ADDSUBPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ADDSUBPS_VpsWpsR, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_LDDQU_VdqMdq, &BX_CPU_C::MOVUPS_VpsWpsM, &BX_CPU_C::BxError, BX_ISA_SSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) // SSE3 #if BX_CPU_LEVEL >= 6 // SSSE3 bx_define_opcode(BX_IA_PSHUFB_PqQq, &BX_CPU_C::PSHUFB_PqQq, &BX_CPU_C::PSHUFB_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PHADDW_PqQq, &BX_CPU_C::PHADDW_PqQq, &BX_CPU_C::PHADDW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PHADDD_PqQq, &BX_CPU_C::PHADDD_PqQq, &BX_CPU_C::PHADDD_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PHADDSW_PqQq, &BX_CPU_C::PHADDSW_PqQq, &BX_CPU_C::PHADDSW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMADDUBSW_PqQq, &BX_CPU_C::PMADDUBSW_PqQq, &BX_CPU_C::PMADDUBSW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PHSUBSW_PqQq, &BX_CPU_C::PHSUBSW_PqQq, &BX_CPU_C::PHSUBSW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PHSUBW_PqQq, &BX_CPU_C::PHSUBW_PqQq, &BX_CPU_C::PHSUBW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PHSUBD_PqQq, &BX_CPU_C::PHSUBD_PqQq, &BX_CPU_C::PHSUBD_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSIGNB_PqQq, &BX_CPU_C::PSIGNB_PqQq, &BX_CPU_C::PSIGNB_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSIGNW_PqQq, &BX_CPU_C::PSIGNW_PqQq, &BX_CPU_C::PSIGNW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSIGND_PqQq, &BX_CPU_C::PSIGND_PqQq, &BX_CPU_C::PSIGND_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PMULHRSW_PqQq, &BX_CPU_C::PMULHRSW_PqQq, &BX_CPU_C::PMULHRSW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PABSB_PqQq, &BX_CPU_C::PABSB_PqQq, &BX_CPU_C::PABSB_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PABSW_PqQq, &BX_CPU_C::PABSW_PqQq, &BX_CPU_C::PABSW_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PABSD_PqQq, &BX_CPU_C::PABSD_PqQq, &BX_CPU_C::PABSD_PqQq, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PALIGNR_PqQqIb, &BX_CPU_C::PALIGNR_PqQqIb, &BX_CPU_C::PALIGNR_PqQqIb, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PSHUFB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSHUFB_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PHADDW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PHADDW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PHADDD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PHADDD_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PHADDSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PHADDSW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMADDUBSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMADDUBSW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PHSUBSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PHSUBSW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PHSUBW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PHSUBW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PHSUBD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PHSUBD_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSIGNB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSIGNB_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSIGNW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSIGNW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PSIGND_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PSIGND_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMULHRSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMULHRSW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PABSB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PABSB_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PABSW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PABSW_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PABSD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PABSD_VdqWdqR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PALIGNR_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PALIGNR_VdqWdqIbR, BX_ISA_SSSE3, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) // SSSE3 // SSE4.1 bx_define_opcode(BX_IA_PBLENDVB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PBLENDVB_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_BLENDVPS_VpsWps, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::BLENDVPS_VpsWpsR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_BLENDVPD_VpdWpd, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::BLENDVPD_VpdWpdR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PTEST_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PTEST_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMULDQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMULDQ_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPEQQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPEQQ_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PACKUSDW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PACKUSDW_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVSXBW_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVSXBW_VdqWqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVSXBD_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVSXBD_VdqWdR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVSXBQ_VdqWw, &BX_CPU_C::LOAD_Ww, &BX_CPU_C::PMOVSXBQ_VdqWwR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVSXWD_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVSXWD_VdqWqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVSXWQ_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVSXWQ_VdqWdR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVSXDQ_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVSXDQ_VdqWqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVZXBW_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVZXBW_VdqWqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVZXBD_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVZXBD_VdqWdR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVZXBQ_VdqWw, &BX_CPU_C::LOAD_Ww, &BX_CPU_C::PMOVZXBQ_VdqWwR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVZXWD_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVZXWD_VdqWqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVZXWQ_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVZXWQ_VdqWdR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMOVZXDQ_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVZXDQ_VdqWqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMINSB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMINSB_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMINSD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMINSD_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMINUW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMINUW_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMINUD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMINUD_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMAXSB_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMAXSB_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMAXSD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMAXSD_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMAXUW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMAXUW_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMAXUD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMAXUD_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PMULLD_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PMULLD_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PHMINPOSUW_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PHMINPOSUW_VdqWdqR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ROUNDPS_VpsWpsIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ROUNDPS_VpsWpsIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ROUNDPD_VpdWpdIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::ROUNDPD_VpdWpdIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ROUNDSS_VssWssIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::ROUNDSS_VssWssIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_ROUNDSD_VsdWsdIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::ROUNDSD_VsdWsdIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_BLENDPS_VpsWpsIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::BLENDPS_VpsWpsIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_BLENDPD_VpdWpdIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::BLENDPD_VpdWpdIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PBLENDW_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PBLENDW_VdqWdqIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PEXTRB_EbdVdqIb, &BX_CPU_C::PEXTRB_EbdVdqIbM, &BX_CPU_C::PEXTRB_EbdVdqIbR, BX_ISA_SSE4_1, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PEXTRW_EwdVdqIb, &BX_CPU_C::PEXTRW_EwdVdqIbM, &BX_CPU_C::PEXTRW_EwdVdqIbR, BX_ISA_SSE4_1, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PEXTRD_EdVdqIb, &BX_CPU_C::PEXTRD_EdVdqIbM, &BX_CPU_C::PEXTRD_EdVdqIbR, BX_ISA_SSE4_1, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_EXTRACTPS_EdVpsIb, &BX_CPU_C::EXTRACTPS_EdVpsIbM, &BX_CPU_C::EXTRACTPS_EdVpsIbR, BX_ISA_SSE4_1, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PINSRB_VdqEbIb, &BX_CPU_C::PINSRB_VdqHdqEbIbM, &BX_CPU_C::PINSRB_VdqHdqEbIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_INSERTPS_VpsWssIb, &BX_CPU_C::INSERTPS_VpsHpsWssIb, &BX_CPU_C::INSERTPS_VpsHpsWssIb, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PINSRD_VdqEdIb, &BX_CPU_C::PINSRD_VdqHdqEdIbM, &BX_CPU_C::PINSRD_VdqHdqEdIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_DPPS_VpsWpsIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::DPPS_VpsWpsIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_DPPD_VpdWpdIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::DPPD_VpdHpdWpdIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MPSADBW_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::MPSADBW_VdqWdqIbR, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVNTDQA_VdqMdq, &BX_CPU_C::MOVAPS_VpsWpsM, &BX_CPU_C::BxError, BX_ISA_SSE4_1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) // SSE4.1 // SSE4.2 bx_define_opcode(BX_IA_CRC32_GdEb, &BX_CPU_C::LOAD_Eb, &BX_CPU_C::CRC32_GdEbR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CRC32_GdEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::CRC32_GdEwR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CRC32_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::CRC32_GdEdR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_CRC32_GdEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CRC32_GdEqR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bx_define_opcode(BX_IA_PCMPGTQ_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCMPGTQ_VdqWdqR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPESTRM_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPESTRM_VdqWdqIbR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPESTRI_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPESTRI_VdqWdqIbR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPISTRM_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPISTRM_VdqWdqIbR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCMPISTRI_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPISTRI_VdqWdqIbR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) // SSE4.2 // MOVBE instruction bx_define_opcode(BX_IA_MOVBE_GwMw, &BX_CPU_C::MOVBE_GwMw, &BX_CPU_C::BxError, BX_ISA_MOVBE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVBE_GdMd, &BX_CPU_C::MOVBE_GdMd, &BX_CPU_C::BxError, BX_ISA_MOVBE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_MOVBE_GqMq, &BX_CPU_C::MOVBE_GqMq, &BX_CPU_C::BxError, BX_ISA_MOVBE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bx_define_opcode(BX_IA_MOVBE_MwGw, &BX_CPU_C::MOVBE_MwGw, &BX_CPU_C::BxError, BX_ISA_MOVBE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVBE_MdGd, &BX_CPU_C::MOVBE_MdGd, &BX_CPU_C::BxError, BX_ISA_MOVBE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_MOVBE_MqGq, &BX_CPU_C::MOVBE_MqGq, &BX_CPU_C::BxError, BX_ISA_MOVBE, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) #endif // MOVBE instruction #endif // BX_CPU_LEVEL >= 6 // POPCNT instruction bx_define_opcode(BX_IA_POPCNT_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::POPCNT_GdEdR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POPCNT_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::POPCNT_GwEwR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_POPCNT_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::POPCNT_GqEqR, BX_ISA_SSE4_2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif // POPCNT instruction // XSAVE extensions bx_define_opcode(BX_IA_XRSTOR, &BX_CPU_C::XRSTOR, &BX_CPU_C::BxError, BX_ISA_XSAVE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XSAVE, &BX_CPU_C::XSAVE, &BX_CPU_C::BxError, BX_ISA_XSAVE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XSETBV, &BX_CPU_C::BxError, &BX_CPU_C::XSETBV, BX_ISA_XSAVE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XGETBV, &BX_CPU_C::BxError, &BX_CPU_C::XGETBV, BX_ISA_XSAVE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XSAVEOPT, &BX_CPU_C::XSAVE, &BX_CPU_C::BxError, BX_ISA_XSAVEOPT, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_CPU_LEVEL >= 6 // AES instructions bx_define_opcode(BX_IA_AESIMC_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::AESIMC_VdqWdqR, BX_ISA_AES_PCLMULQDQ, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_AESENC_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::AESENC_VdqHdqWdqR, BX_ISA_AES_PCLMULQDQ, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_AESENCLAST_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::AESENCLAST_VdqHdqWdqR, BX_ISA_AES_PCLMULQDQ, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_AESDEC_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::AESDEC_VdqHdqWdqR, BX_ISA_AES_PCLMULQDQ, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_AESDECLAST_VdqWdq, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::AESDECLAST_VdqHdqWdqR, BX_ISA_AES_PCLMULQDQ, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_AESKEYGENASSIST_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::AESKEYGENASSIST_VdqWdqIbR, BX_ISA_AES_PCLMULQDQ, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_PCLMULQDQ_VdqWdqIb, &BX_CPU_C::LOAD_Wdq, &BX_CPU_C::PCLMULQDQ_VdqHdqWdqIbR, BX_ISA_AES_PCLMULQDQ, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_SSE) #endif #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_LM_LAHF, NULL, &BX_CPU_C::LAHF, BX_ISA_LM_LAHF_SAHF, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LM_SAHF, NULL, &BX_CPU_C::SAHF, BX_ISA_LM_LAHF_SAHF, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SYSCALL, NULL, &BX_CPU_C::SYSCALL, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SYSRET, NULL, &BX_CPU_C::SYSRET, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_GqEq, &BX_CPU_C::ADD_GqEqM, &BX_CPU_C::ADD_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_GqEq, &BX_CPU_C::OR_GqEqM, &BX_CPU_C::OR_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_GqEq, &BX_CPU_C::ADC_GqEqM, &BX_CPU_C::ADC_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_GqEq, &BX_CPU_C::SBB_GqEqM, &BX_CPU_C::SBB_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_GqEq, &BX_CPU_C::AND_GqEqM, &BX_CPU_C::AND_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_GqEq, &BX_CPU_C::SUB_GqEqM, &BX_CPU_C::SUB_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_GqEq, &BX_CPU_C::XOR_GqEqM, &BX_CPU_C::XOR_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_GqEq, &BX_CPU_C::CMP_GqEqM, &BX_CPU_C::CMP_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EqGq, &BX_CPU_C::ADD_EqGqM, &BX_CPU_C::ADD_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EqGq, &BX_CPU_C::OR_EqGqM, &BX_CPU_C::OR_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EqGq, &BX_CPU_C::ADC_EqGqM, &BX_CPU_C::ADC_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EqGq, &BX_CPU_C::SBB_EqGqM, &BX_CPU_C::SBB_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EqGq, &BX_CPU_C::AND_EqGqM, &BX_CPU_C::AND_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EqGq, &BX_CPU_C::SUB_EqGqM, &BX_CPU_C::SUB_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EqGq, &BX_CPU_C::XOR_EqGqM, &BX_CPU_C::XOR_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EqGq, &BX_CPU_C::TEST_EqGqM, &BX_CPU_C::TEST_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EqGq, &BX_CPU_C::CMP_EqGqM, &BX_CPU_C::CMP_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_RAXId, NULL, &BX_CPU_C::ADD_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_RAXId, NULL, &BX_CPU_C::OR_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_RAXId, NULL, &BX_CPU_C::ADC_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_RAXId, NULL, &BX_CPU_C::SBB_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_RAXId, NULL, &BX_CPU_C::AND_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_RAXId, NULL, &BX_CPU_C::SUB_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_RAXId, NULL, &BX_CPU_C::XOR_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_RAXId, NULL, &BX_CPU_C::TEST_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_RAXId, NULL, &BX_CPU_C::CMP_EqIdR, 0, BX_SRC_EAX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADD_EqId, &BX_CPU_C::ADD_EqIdM, &BX_CPU_C::ADD_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_OR_EqId, &BX_CPU_C::OR_EqIdM, &BX_CPU_C::OR_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADC_EqId, &BX_CPU_C::ADC_EqIdM, &BX_CPU_C::ADC_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SBB_EqId, &BX_CPU_C::SBB_EqIdM, &BX_CPU_C::SBB_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_AND_EqId, &BX_CPU_C::AND_EqIdM, &BX_CPU_C::AND_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SUB_EqId, &BX_CPU_C::SUB_EqIdM, &BX_CPU_C::SUB_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XOR_EqId, &BX_CPU_C::XOR_EqIdM, &BX_CPU_C::XOR_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TEST_EqId, &BX_CPU_C::TEST_EqIdM, &BX_CPU_C::TEST_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMP_EqId, &BX_CPU_C::CMP_EqIdM, &BX_CPU_C::CMP_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XCHG_EqGq, &BX_CPU_C::XCHG_EqGqM, &BX_CPU_C::XCHG_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LEA_GqM, &BX_CPU_C::LEA_GqM, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV64_GdEd, &BX_CPU_C::MOV64_GdEdM, &BX_CPU_C::MOV_GdEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV64_EdGd, &BX_CPU_C::MOV64_EdGdM, &BX_CPU_C::MOV_GdEdR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_GqEq, &BX_CPU_C::MOV_GqEqM, &BX_CPU_C::MOV_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EqGq, &BX_CPU_C::MOV_EqGqM, &BX_CPU_C::MOV_GqEqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EqId, &BX_CPU_C::MOV_EqIdM, &BX_CPU_C::MOV_EqIdR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RAXOq, NULL, &BX_CPU_C::MOV_RAXOq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_OqRAX, NULL, &BX_CPU_C::MOV_OqRAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_EAXOq, NULL, &BX_CPU_C::MOV_EAXOq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_OqEAX, NULL, &BX_CPU_C::MOV_OqEAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_AXOq, NULL, &BX_CPU_C::MOV_AXOq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_OqAX, NULL, &BX_CPU_C::MOV_OqAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_ALOq, NULL, &BX_CPU_C::MOV_ALOq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_OqAL, NULL, &BX_CPU_C::MOV_OqAL, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_MOVSQ_XqYq, NULL, &BX_CPU_C::REP_MOVSQ_XqYq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_CMPSQ_XqYq, NULL, &BX_CPU_C::REP_CMPSQ_XqYq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_STOSQ_YqRAX, NULL, &BX_CPU_C::REP_STOSQ_YqRAX, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_LODSQ_RAXXq, NULL, &BX_CPU_C::REP_LODSQ_RAXXq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_REP_SCASQ_RAXXq, NULL, &BX_CPU_C::REP_SCASQ_RAXXq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL_Jq, NULL, &BX_CPU_C::CALL_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP_Jq, NULL, &BX_CPU_C::JMP_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JO_Jq, NULL, &BX_CPU_C::JO_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNO_Jq, NULL, &BX_CPU_C::JNO_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JB_Jq, NULL, &BX_CPU_C::JB_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNB_Jq, NULL, &BX_CPU_C::JNB_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JZ_Jq, NULL, &BX_CPU_C::JZ_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNZ_Jq, NULL, &BX_CPU_C::JNZ_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JBE_Jq, NULL, &BX_CPU_C::JBE_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNBE_Jq, NULL, &BX_CPU_C::JNBE_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JS_Jq, NULL, &BX_CPU_C::JS_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNS_Jq, NULL, &BX_CPU_C::JNS_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JP_Jq, NULL, &BX_CPU_C::JP_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNP_Jq, NULL, &BX_CPU_C::JNP_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JL_Jq, NULL, &BX_CPU_C::JL_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNL_Jq, NULL, &BX_CPU_C::JNL_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JLE_Jq, NULL, &BX_CPU_C::JLE_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JNLE_Jq, NULL, &BX_CPU_C::JNLE_Jq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ENTER64_IwIb, NULL, &BX_CPU_C::ENTER64_IwIb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LEAVE64, NULL, &BX_CPU_C::LEAVE64, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IRET64, NULL, &BX_CPU_C::IRET64, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLD_EqGq, &BX_CPU_C::SHLD_EqGqM, &BX_CPU_C::SHLD_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLD_EqGqIb, &BX_CPU_C::SHLD_EqGqM, &BX_CPU_C::SHLD_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRD_EqGq, &BX_CPU_C::SHRD_EqGqM, &BX_CPU_C::SHRD_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRD_EqGqIb, &BX_CPU_C::SHRD_EqGqM, &BX_CPU_C::SHRD_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::IMUL_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_GqEqId, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::IMUL_GqEqIdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVZX_GqEb, &BX_CPU_C::MOVZX_GqEbM, &BX_CPU_C::MOVZX_GqEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVZX_GqEw, &BX_CPU_C::MOVZX_GqEwM, &BX_CPU_C::MOVZX_GqEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVSX_GqEb, &BX_CPU_C::MOVSX_GqEbM, &BX_CPU_C::MOVSX_GqEbR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVSX_GqEw, &BX_CPU_C::MOVSX_GqEwM, &BX_CPU_C::MOVSX_GqEwR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVSX_GqEd, &BX_CPU_C::MOVSX_GqEdM, &BX_CPU_C::MOVSX_GqEdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSWAP_RRX, NULL, &BX_CPU_C::BSWAP_RRX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSF_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::BSF_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BSR_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::BSR_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BT_EqGq, &BX_CPU_C::BT_EqGqM, &BX_CPU_C::BT_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTS_EqGq, &BX_CPU_C::BTS_EqGqM, &BX_CPU_C::BTS_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTR_EqGq, &BX_CPU_C::BTR_EqGqM, &BX_CPU_C::BTR_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTC_EqGq, &BX_CPU_C::BTC_EqGqM, &BX_CPU_C::BTC_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BT_EqIb, &BX_CPU_C::BT_EqIbM, &BX_CPU_C::BT_EqIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTS_EqIb, &BX_CPU_C::BTS_EqIbM, &BX_CPU_C::BTS_EqIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTR_EqIb, &BX_CPU_C::BTR_EqIbM, &BX_CPU_C::BTR_EqIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BTC_EqIb, &BX_CPU_C::BTC_EqIbM, &BX_CPU_C::BTC_EqIbR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NOT_Eq, &BX_CPU_C::NOT_EqM, &BX_CPU_C::NOT_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_NEG_Eq, &BX_CPU_C::NEG_EqM, &BX_CPU_C::NEG_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_Eq, &BX_CPU_C::ROL_EqM, &BX_CPU_C::ROL_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_Eq, &BX_CPU_C::ROR_EqM, &BX_CPU_C::ROR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_Eq, &BX_CPU_C::RCL_EqM, &BX_CPU_C::RCL_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_Eq, &BX_CPU_C::RCR_EqM, &BX_CPU_C::RCR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_Eq, &BX_CPU_C::SHL_EqM, &BX_CPU_C::SHL_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_Eq, &BX_CPU_C::SHR_EqM, &BX_CPU_C::SHR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_Eq, &BX_CPU_C::SAR_EqM, &BX_CPU_C::SAR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROL_EqIb, &BX_CPU_C::ROL_EqM, &BX_CPU_C::ROL_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ROR_EqIb, &BX_CPU_C::ROR_EqM, &BX_CPU_C::ROR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCL_EqIb, &BX_CPU_C::RCL_EqM, &BX_CPU_C::RCL_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RCR_EqIb, &BX_CPU_C::RCR_EqM, &BX_CPU_C::RCR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHL_EqIb, &BX_CPU_C::SHL_EqM, &BX_CPU_C::SHL_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHR_EqIb, &BX_CPU_C::SHR_EqM, &BX_CPU_C::SHR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SAR_EqIb, &BX_CPU_C::SAR_EqM, &BX_CPU_C::SAR_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MUL_RAXEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::MUL_RAXEqR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IMUL_RAXEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::IMUL_RAXEqR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DIV_RAXEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::DIV_RAXEqR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_IDIV_RAXEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::IDIV_RAXEqR, 0, BX_SRC_EAX, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INC_Eq, &BX_CPU_C::INC_EqM, &BX_CPU_C::INC_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_DEC_Eq, &BX_CPU_C::DEC_EqM, &BX_CPU_C::DEC_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL_Eq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CALL_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CALL64_Ep, &BX_CPU_C::CALL64_Ep, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP_Eq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::JMP_EqR, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JMP64_Ep, &BX_CPU_C::JMP64_Ep, &BX_CPU_C::BxError, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSHF_Fq, NULL, &BX_CPU_C::PUSHF_Fq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POPF_Fq, NULL, &BX_CPU_C::POPF_Fq, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMPXCHG_EqGq, &BX_CPU_C::CMPXCHG_EqGqM, &BX_CPU_C::CMPXCHG_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CDQE, NULL, &BX_CPU_C::CDQE, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CQO, NULL, &BX_CPU_C::CQO, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XADD_EqGq, &BX_CPU_C::XADD_EqGqM, &BX_CPU_C::XADD_EqGqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETnear64_Iw, NULL, &BX_CPU_C::RETnear64_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETnear64, NULL, &BX_CPU_C::RETnear64, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETfar64_Iw, NULL, &BX_CPU_C::RETfar64_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RETfar64, NULL, &BX_CPU_C::RETfar64_Iw, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVO_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVO_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNO_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNO_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVB_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVB_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNB_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNB_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVZ_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVZ_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNZ_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNZ_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVBE_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVBE_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNBE_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNBE_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVS_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVS_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNS_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNS_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVP_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVP_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNP_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNP_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVL_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVL_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNL_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNL_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVLE_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVLE_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMOVNLE_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CMOVNLE_GqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_RRX, NULL, &BX_CPU_C::PUSH_RRX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP_RRX, NULL, &BX_CPU_C::POP_RRX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH_Eq, &BX_CPU_C::PUSH_EqM, &BX_CPU_C::PUSH_RRX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP_Eq, &BX_CPU_C::POP_EqM, &BX_CPU_C::POP_RRX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH64_Id, NULL, &BX_CPU_C::PUSH64_Id, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH64_FS, NULL, &BX_CPU_C::PUSH64_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP64_FS, NULL, &BX_CPU_C::POP64_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PUSH64_GS, NULL, &BX_CPU_C::PUSH64_Sw, 0, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_POP64_GS, NULL, &BX_CPU_C::POP64_Sw, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // IDT/GDT/LDTR/TR access - keep NNN for VMX bx_define_opcode(BX_IA_SGDT64_Ms, &BX_CPU_C::SGDT64_Ms, &BX_CPU_C::BxError, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SIDT64_Ms, &BX_CPU_C::SIDT64_Ms, &BX_CPU_C::BxError, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LGDT64_Ms, &BX_CPU_C::LGDT64_Ms, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LIDT64_Ms, &BX_CPU_C::LIDT64_Ms, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) // IDT/GDT/LDTR/TR access - keep NNN for VMX bx_define_opcode(BX_IA_MOV_RRXIq, NULL, &BX_CPU_C::MOV_RRXIq, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_XCHG_RRXRAX, NULL, &BX_CPU_C::XCHG_RRXRAX, 0, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LSS_GqMp, &BX_CPU_C::LSS_GqMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LFS_GqMp, &BX_CPU_C::LFS_GqMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LGS_GqMp, &BX_CPU_C::LGS_GqMp, &BX_CPU_C::BxError, 0, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CMPXCHG16B, &BX_CPU_C::CMPXCHG16B, &BX_CPU_C::BxError, BX_ISA_CMPXCHG16B, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOPNE64_Jb, NULL, &BX_CPU_C::LOOPNE64_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOPE64_Jb, NULL, &BX_CPU_C::LOOPE64_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LOOP64_Jb, NULL, &BX_CPU_C::LOOP64_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_JRCXZ_Jb, NULL, &BX_CPU_C::JRCXZ_Jb, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVQ_EqVq, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::MOVQ_EqVqR, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVQ_PqEq, &BX_CPU_C::MOVQ_PqQqM, &BX_CPU_C::MOVQ_PqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVQ_VdqEq, &BX_CPU_C::MOVQ_VqWqM, &BX_CPU_C::MOVQ_VdqEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSI2SS_VssEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CVTSI2SS_VssEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSI2SD_VsdEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::CVTSI2SD_VsdEqR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTSS2SI_GqWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTTSS2SI_GqWssR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTTSD2SI_GqWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTTSD2SI_GqWsdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSS2SI_GqWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTSS2SI_GqWssR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_CVTSD2SI_GqWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTSD2SI_GqWsdR, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVNTI64_MdGd, &BX_CPU_C::MOV64_EdGdM, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOVNTI_MqGq, &BX_CPU_C::MOV_EqGqM, &BX_CPU_C::BxError, BX_ISA_SSE2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR0Rq, NULL, &BX_CPU_C::MOV_CR0Rq, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR2Rq, NULL, &BX_CPU_C::MOV_CR2Rq, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR3Rq, NULL, &BX_CPU_C::MOV_CR3Rq, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_CR4Rq, NULL, &BX_CPU_C::MOV_CR4Rq, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RqCR0, NULL, &BX_CPU_C::MOV_RqCR0, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RqCR2, NULL, &BX_CPU_C::MOV_RqCR2, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RqCR3, NULL, &BX_CPU_C::MOV_RqCR3, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RqCR4, NULL, &BX_CPU_C::MOV_RqCR4, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_DqRq, NULL, &BX_CPU_C::MOV_DqRq, 0, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MOV_RqDq, NULL, &BX_CPU_C::MOV_RqDq, 0, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SWAPGS, &BX_CPU_C::BxError, &BX_CPU_C::SWAPGS, 0, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RDFSBASE, &BX_CPU_C::BxError, &BX_CPU_C::RDFSBASE, BX_ISA_FSGSBASE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RDGSBASE, &BX_CPU_C::BxError, &BX_CPU_C::RDGSBASE, BX_ISA_FSGSBASE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_WRFSBASE, &BX_CPU_C::BxError, &BX_CPU_C::WRFSBASE, BX_ISA_FSGSBASE, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_WRGSBASE, &BX_CPU_C::BxError, &BX_CPU_C::WRGSBASE, BX_ISA_FSGSBASE, BX_SRC_NONE, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bx_define_opcode(BX_IA_RDTSCP, &BX_CPU_C::BxError, &BX_CPU_C::RDTSCP, BX_ISA_RDTSCP, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // VMX bx_define_opcode(BX_IA_VMXON_Mq, &BX_CPU_C::VMXON, &BX_CPU_C::BxError, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMXOFF, &BX_CPU_C::BxError, &BX_CPU_C::VMXOFF, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMCALL, &BX_CPU_C::BxError, &BX_CPU_C::VMCALL, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMLAUNCH, &BX_CPU_C::BxError, &BX_CPU_C::VMLAUNCH, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMRESUME, &BX_CPU_C::BxError, &BX_CPU_C::VMLAUNCH, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMCLEAR_Mq, &BX_CPU_C::VMCLEAR, &BX_CPU_C::BxError, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMPTRLD_Mq, &BX_CPU_C::VMPTRLD, &BX_CPU_C::BxError, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMPTRST_Mq, &BX_CPU_C::VMPTRST, &BX_CPU_C::BxError, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMREAD_EdGd, &BX_CPU_C::VMREAD_EdGd, &BX_CPU_C::VMREAD_EdGd, BX_ISA_VMX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMWRITE_GdEd, &BX_CPU_C::VMWRITE_GdEd, &BX_CPU_C::VMWRITE_GdEd, BX_ISA_VMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_VMREAD_EqGq, &BX_CPU_C::VMREAD_EdGd, &BX_CPU_C::VMREAD_EdGd, BX_ISA_VMX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMWRITE_GqEq, &BX_CPU_C::VMWRITE_GdEd, &BX_CPU_C::VMWRITE_GdEd, BX_ISA_VMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif #if BX_CPU_LEVEL >= 6 bx_define_opcode(BX_IA_INVEPT, &BX_CPU_C::INVEPT, &BX_CPU_C::BxError, BX_ISA_VMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INVVPID, &BX_CPU_C::INVVPID, &BX_CPU_C::BxError, BX_ISA_VMX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bx_define_opcode(BX_IA_VMFUNC, &BX_CPU_C::BxError, &BX_CPU_C::VMFUNC, BX_ISA_VMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // VMX // SMX bx_define_opcode(BX_IA_GETSEC, &BX_CPU_C::GETSEC, &BX_CPU_C::GETSEC, BX_ISA_SMX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // SMX // SVM bx_define_opcode(BX_IA_VMRUN, &BX_CPU_C::BxError, &BX_CPU_C::VMRUN, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMMCALL, &BX_CPU_C::BxError, &BX_CPU_C::VMMCALL, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMLOAD, &BX_CPU_C::BxError, &BX_CPU_C::VMLOAD, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_VMSAVE, &BX_CPU_C::BxError, &BX_CPU_C::VMSAVE, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_STGI, &BX_CPU_C::BxError, &BX_CPU_C::STGI, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_CLGI, &BX_CPU_C::BxError, &BX_CPU_C::CLGI, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SKINIT, &BX_CPU_C::BxError, &BX_CPU_C::SKINIT, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_INVLPGA, &BX_CPU_C::BxError, &BX_CPU_C::INVLPGA, BX_ISA_SVM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, 0) // SVM #if BX_CPU_LEVEL >= 6 bx_define_opcode(BX_IA_INVPCID, &BX_CPU_C::INVPCID, &BX_CPU_C::BxError, BX_ISA_INVPCID, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif #if BX_SUPPORT_AVX && BX_CPU_LEVEL >= 6 // AVX bx_define_opcode(BX_IA_VZEROUPPER, NULL, &BX_CPU_C::VZEROUPPER, BX_ISA_AVX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VZEROALL, NULL, &BX_CPU_C::VZEROALL, BX_ISA_AVX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VLDMXCSR, &BX_CPU_C::LDMXCSR, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSTMXCSR, &BX_CPU_C::STMXCSR, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVAPS_VpsWps, &BX_CPU_C::VMOVAPS_VpsWpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVAPS_WpsVps, &BX_CPU_C::VMOVAPS_WpsVpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVAPD_VpdWpd, &BX_CPU_C::VMOVAPS_VpsWpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVAPD_WpdVpd, &BX_CPU_C::VMOVAPS_WpsVpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVUPS_VpsWps, &BX_CPU_C::VMOVUPS_VpsWpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVUPS_WpsVps, &BX_CPU_C::VMOVUPS_WpsVpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVUPD_VpdWpd, &BX_CPU_C::VMOVUPS_VpsWpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVUPD_WpdVpd, &BX_CPU_C::VMOVUPS_WpsVpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVDQA_VdqWdq, &BX_CPU_C::VMOVAPS_VpsWpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVDQA_WdqVdq, &BX_CPU_C::VMOVAPS_WpsVpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVDQU_VdqWdq, &BX_CPU_C::VMOVUPS_VpsWpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVDQU_WdqVdq, &BX_CPU_C::VMOVUPS_WpsVpsM, &BX_CPU_C::VMOVAPS_VpsWpsR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVSD_VsdHpdWsd, &BX_CPU_C::MOVQ_VqWqM, &BX_CPU_C::VMOVSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_MEM_NO_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVSS_VssHpsWss, &BX_CPU_C::MOVSS_VssWssM, &BX_CPU_C::VMOVSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_MEM_NO_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVSD_WsdHpdVsd, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::VMOVSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_MEM_NO_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVSS_WssHpsVss, &BX_CPU_C::MOVSS_WssVssM, &BX_CPU_C::VMOVSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_MEM_NO_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVLPS_VpsHpsMq, &BX_CPU_C::VMOVLPD_VpdHpdMq, &BX_CPU_C::VMOVHLPS_VpsHpsWps, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVHPS_VpsHpsMq, &BX_CPU_C::VMOVHPD_VpdHpdMq, &BX_CPU_C::VMOVLHPS_VpsHpsWps, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVLPS_MqVps, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVHPS_MqVps, &BX_CPU_C::MOVHPS_MqVps, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVLPD_MqVsd, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVHPD_MqVsd, &BX_CPU_C::MOVHPS_MqVps, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVLPD_VpdHpdMq, &BX_CPU_C::VMOVLPD_VpdHpdMq, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVHPD_VpdHpdMq, &BX_CPU_C::VMOVHPD_VpdHpdMq, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVNTPS_MpsVps, &BX_CPU_C::VMOVAPS_WpsVpsM, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVNTPD_MpdVpd, &BX_CPU_C::VMOVAPS_WpsVpsM, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVNTDQ_MdqVdq, &BX_CPU_C::VMOVAPS_WpsVpsM, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVDDUP_VpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMOVDDUP_VpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVSLDUP_VpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMOVSLDUP_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVSHDUP_VpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMOVSHDUP_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VLDDQU_VdqMdq, &BX_CPU_C::VMOVUPS_VpsWpsM, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVNTDQA_VdqMdq, &BX_CPU_C::VMOVAPS_VpsWpsM, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VUCOMISS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::UCOMISS_VssWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCOMISS_VpsWps, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::COMISS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VUCOMISD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::UCOMISD_VsdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCOMISD_VpdWpd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::COMISD_VpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSQRTPS_VpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VSQRTPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSQRTPD_VpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VSQRTPD_VpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSQRTSD_VsdHpdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VSQRTSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSQRTSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VSQRTSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VRSQRTSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VRSQRTSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VRSQRTPS_VpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VRSQRTPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VRCPSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VRCPSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VRCPPS_VpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VRCPPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VANDPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VANDPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VANDNPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDNPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VANDNPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDNPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VORPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VORPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VORPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VORPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VXORPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VXORPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VXORPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VXORPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VADDPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VADDPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VADDPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VADDPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VADDSD_VsdHpdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VADDSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VADDSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VADDSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMULPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMULPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMULPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMULPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMULSD_VsdHpdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VMULSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMULSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VMULSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSUBPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VSUBPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSUBPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VSUBPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSUBSD_VsdHpdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VSUBSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSUBSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VSUBSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VDIVPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VDIVPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VDIVPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VDIVPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VDIVSD_VsdHpdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VDIVSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VDIVSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VDIVSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMAXPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMAXPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMAXPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMAXPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMAXSD_VsdHpdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VMAXSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMAXSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VMAXSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMINPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMINPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMINPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMINPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMINSD_VsdHpdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VMINSD_VsdHpdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMINSS_VssHpsWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VMINSS_VssHpsWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSHUFD_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPERMILPS_VpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSHUFHW_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHUFHW_VdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSHUFLW_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHUFLW_VdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VHADDPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VHADDPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VHADDPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VHADDPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VHSUBPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VHSUBPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VHSUBPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VHSUBPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCMPPS_VpsHpsWpsIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCMPPS_VpsHpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCMPPD_VpdHpdWpdIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCMPPD_VpdHpdWpdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCMPSD_VsdHpdWsdIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VCMPSD_VsdHpdWsdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCMPSS_VssHpsWssIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VCMPSS_VssHpsWssIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSHUFPS_VpsHpsWpsIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VSHUFPS_VpsHpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VSHUFPD_VpdHpdWpdIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VSHUFPD_VpdHpdWpdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VADDSUBPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VADDSUBPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VADDSUBPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VADDSUBPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VROUNDPS_VpsWpsIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VROUNDPS_VpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VROUNDPD_VpdWpdIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VROUNDPD_VpdWpdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VROUNDSD_VsdHpdWsdIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VROUNDSD_VsdHpdWsdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VROUNDSS_VssHpsWssIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VROUNDSS_VssHpsWssIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VDPPS_VpsHpsWpsIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VDPPS_VpsHpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VDPPD_VpdHpdWpdIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::DPPD_VpdHpdWpdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRLW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRLW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRLD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRLD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRLQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRLQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRAW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRAW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRAD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRAD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSLLW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSLLW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSLLD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSLLD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSLLQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSLLQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRLW_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRLW_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRAW_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRAW_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSLLW_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSLLW_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRLD_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRLD_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRAD_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRAD_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSLLD_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSLLD_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRLQ_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRLQ_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSLLQ_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSLLQ_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSRLDQ_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSRLDQ_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSLLDQ_UdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSLLDQ_UdqIb, BX_ISA_AVX, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMOVMSKB_GdUdq, &BX_CPU_C::BxError, &BX_CPU_C::VPMOVMSKB_GdUdq, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVMSKPS_GdVRps, &BX_CPU_C::BxError, &BX_CPU_C::VMOVMSKPS_GdVRps, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVMSKPD_GdVRpd, &BX_CPU_C::BxError, &BX_CPU_C::VMOVMSKPD_GdVRpd, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VUNPCKLPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKLPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VUNPCKHPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKHPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VUNPCKLPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKLPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VUNPCKHPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKHPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKHDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKHPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKLDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKLPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKLBW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPUNPCKLBW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKLWD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPUNPCKLWD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKHBW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPUNPCKHBW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKHWD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPUNPCKHWD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKLQDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKLPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPUNPCKHQDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKHPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPEQB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPEQB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPEQW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPEQW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPEQD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPEQD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPEQQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPEQQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPGTB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPGTB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPGTW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPGTW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPGTD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPGTD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPGTQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCMPGTQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBSB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBSB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDSB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDSB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBUSB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBUSB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBUSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBUSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDUSB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDUSB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDUSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDUSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPAVGB_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPAVGB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPAVGW_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPAVGW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPANDN_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDNPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPAND_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPOR_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VORPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPXOR_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VXORPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMULHRSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMULHRSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMULDQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMULDQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMULLD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMULLD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMULLW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMULLW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMULHW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMULHW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMULHUW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMULHUW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMULUDQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMULUDQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSADBW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSADBW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMASKMOVDQU_VdqUdq, &BX_CPU_C::BxError, &BX_CPU_C::MASKMOVDQU_VdqUdq, BX_ISA_AVX, BX_SRC_NONE, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSUBQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSUBQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPADDQ_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPADDQ_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSHUFB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHUFB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPHADDW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPHADDD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPHSUBW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHSUBW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPHSUBD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHSUBD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPHADDSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPHSUBSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHSUBSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMADDWD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMADDWD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMADDUBSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMADDUBSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSIGNB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSIGNB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSIGNW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSIGNW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPSIGND_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSIGND_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VTESTPS_VpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VTESTPS_VpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VTESTPD_VpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VTESTPD_VpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPTEST_VdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPTEST_VdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VBROADCASTSS_VpsMss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VPBROADCASTD_VdqWd, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VBROADCASTSD_VpdMsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VPBROADCASTQ_VdqWq, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VBROADCASTF128_VdqMdq, &BX_CPU_C::VBROADCASTF128_VdqMdq, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPABSB_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPABSB_VdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPABSW_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPABSW_VdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPABSD_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPABSD_VdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPACKSSWB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPACKSSWB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPACKUSWB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPACKUSWB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPACKUSDW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPACKUSDW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPACKSSDW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPACKSSDW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVPS_VpsHpsMps, &BX_CPU_C::VMASKMOVPS_VpsHpsMps, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVPD_VpdHpdMpd, &BX_CPU_C::VMASKMOVPD_VpdHpdMpd, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVPS_MpsHpsVps, &BX_CPU_C::VMASKMOVPS_MpsHpsVps, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVPD_MpdHpdVpd, &BX_CPU_C::VMASKMOVPD_MpdHpdVpd, &BX_CPU_C::BxError, BX_ISA_AVX, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXBW_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVSXBW_VdqWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXBD_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVSXBD_VdqWdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXBQ_VdqWw, &BX_CPU_C::LOAD_Ww, &BX_CPU_C::PMOVSXBQ_VdqWwR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXWD_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVSXWD_VdqWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXWQ_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVSXWQ_VdqWdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXDQ_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVSXDQ_VdqWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXBW_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVZXBW_VdqWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXBD_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVZXBD_VdqWdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXBQ_VdqWw, &BX_CPU_C::LOAD_Ww, &BX_CPU_C::PMOVZXBQ_VdqWwR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXWD_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVZXWD_VdqWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXWQ_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::PMOVZXWQ_VdqWdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXDQ_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::PMOVZXDQ_VdqWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMINSB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMINSB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMINSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMINSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMINSD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMINSD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMINUB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMINUB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMINUW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMINUW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMINUD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMINUD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMAXSB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMAXSB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMAXSW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMAXSW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMAXSD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMAXSD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMAXUB_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMAXUB_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMAXUW_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMAXUW_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPMAXUD_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMAXUD_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPHMINPOSUW_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PHMINPOSUW_VdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPERMILPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMILPS_VpsHpsWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPERMILPD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMILPD_VpdHpdWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPERMILPS_VpsWpsIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMILPS_VpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPERMILPD_VpdWpdIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMILPD_VpdWpdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VBLENDPS_VpsHpsWpsIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VBLENDPS_VpsHpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VBLENDPD_VpdHpdWpdIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VBLENDPD_VpdHpdWpdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPBLENDW_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPBLENDW_VdqHdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPALIGNR_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPALIGNR_VdqHdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VINSERTPS_VpsWssIb, &BX_CPU_C::INSERTPS_VpsHpsWssIb, &BX_CPU_C::INSERTPS_VpsHpsWssIb, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VEXTRACTPS_EdVpsIb, &BX_CPU_C::EXTRACTPS_EdVpsIbM, &BX_CPU_C::EXTRACTPS_EdVpsIbR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPERM2F128_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERM2F128_VdqHdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VINSERTF128_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VINSERTF128_VdqHdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VEXTRACTF128_WdqVdqIb, &BX_CPU_C::VEXTRACTF128_WdqVdqIbM, &BX_CPU_C::VEXTRACTF128_WdqVdqIbR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VBLENDVPS_VpsHpsWpsIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VBLENDVPS_VpsHpsWpsIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VBLENDVPD_VpdHpdWpdIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VBLENDVPD_VpdHpdWpdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPBLENDVB_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPBLENDVB_VdqHdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMPSADBW_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VMPSADBW_VdqHdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPESTRM_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPESTRM_VdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPESTRI_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPESTRI_VdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPISTRM_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPISTRM_VdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCMPISTRI_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCMPISTRI_VdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VAESIMC_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::AESIMC_VdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VAESENC_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::AESENC_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VAESENCLAST_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::AESENCLAST_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VAESDEC_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::AESDEC_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VAESDECLAST_VdqHdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::AESDECLAST_VdqHdqWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VAESKEYGENASSIST_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::AESKEYGENASSIST_VdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPCLMULQDQ_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::PCLMULQDQ_VdqHdqWdqIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVD_VdqEd, &BX_CPU_C::MOVSS_VssWssM, &BX_CPU_C::MOVD_VdqEdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVD_EdVd, &BX_CPU_C::MOVSS_WssVssM, &BX_CPU_C::MOVD_EdVdR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPINSRB_VdqEbIb, &BX_CPU_C::PINSRB_VdqHdqEbIbM, &BX_CPU_C::PINSRB_VdqHdqEbIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPINSRW_VdqEwIb, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::PINSRW_VdqHdqEwIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPINSRD_VdqEdIb, &BX_CPU_C::PINSRD_VdqHdqEdIbM, &BX_CPU_C::PINSRD_VdqHdqEdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPINSRQ_VdqEqIb, &BX_CPU_C::PINSRD_VdqHdqEdIbM, &BX_CPU_C::PINSRD_VdqHdqEdIbR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPEXTRW_GdUdqIb, &BX_CPU_C::BxError, &BX_CPU_C::PEXTRW_GdUdqIb, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPEXTRB_EbdVdqIb, &BX_CPU_C::PEXTRB_EbdVdqIbM, &BX_CPU_C::PEXTRB_EbdVdqIbR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPEXTRW_EwdVdqIb, &BX_CPU_C::PEXTRW_EwdVdqIbM, &BX_CPU_C::PEXTRW_EwdVdqIbR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPEXTRD_EdVdqIb, &BX_CPU_C::PEXTRD_EdVdqIbM, &BX_CPU_C::PEXTRD_EdVdqIbR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VPEXTRQ_EqVdqIb, &BX_CPU_C::PEXTRD_EdVdqIbM, &BX_CPU_C::PEXTRD_EdVdqIbR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VCVTPS2PD_VpdWps, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VCVTPS2PD_VpdWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VCVTPS2PD_VpdWps, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VCVTPS2PD_VpdWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTTPD2DQ_VqWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCVTTPD2DQ_VqWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTPD2DQ_VqWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCVTPD2DQ_VqWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VCVTDQ2PD_VpdWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VCVTDQ2PD_VpdWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VCVTDQ2PD_VpdWq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VCVTDQ2PD_VpdWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTPD2PS_VpsWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCVTPD2PS_VpsWpdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSD2SS_VssWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VCVTSD2SS_VssWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSS2SD_VsdWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VCVTSS2SD_VsdWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTDQ2PS_VpsWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCVTDQ2PS_VpsWdqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTPS2DQ_VdqWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCVTPS2DQ_VdqWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTTPS2DQ_VdqWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VCVTTPS2DQ_VdqWpsR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSI2SD_VsdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::VCVTSI2SD_VsdEdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSI2SS_VssEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::VCVTSI2SS_VssEdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSD2SI_GdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTSD2SI_GdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSS2SI_GdWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTSS2SI_GdWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTTSD2SI_GdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTTSD2SI_GdWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTTSS2SI_GdWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTTSS2SI_GdWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSI2SD_VsdEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::VCVTSI2SD_VsdEqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSI2SS_VssEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::VCVTSI2SS_VssEqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTTSD2SI_GqWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTTSD2SI_GqWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTTSS2SI_GqWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTTSS2SI_GqWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSD2SI_GqWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::CVTSD2SI_GqWsdR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTSS2SI_GqWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::CVTSS2SI_GqWssR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVQ_WqVq, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::MOVQ_VqWqR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMOVQ_VqWq, &BX_CPU_C::MOVQ_VqWqM, &BX_CPU_C::MOVQ_VqWqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVQ_VdqEq, &BX_CPU_C::MOVQ_VqWqM, &BX_CPU_C::MOVQ_VdqEqR, BX_ISA_AVX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V128_VMOVQ_EqVq, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::MOVQ_EqVqR, BX_ISA_AVX, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTPH2PS_VpsWps, &BX_CPU_C::LOAD_VectorQ, &BX_CPU_C::VCVTPH2PS_VpsWpsR, BX_ISA_AVX_F16C, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VCVTPS2PH_WpsVpsIb, &BX_CPU_C::VCVTPS2PH_WpsVpsIb, &BX_CPU_C::VCVTPS2PH_WpsVpsIb, BX_ISA_AVX_F16C, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) // AVX // AVX2 bx_define_opcode(BX_IA_V256_VPCMPEQB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPEQB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPCMPEQW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPEQW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPCMPEQD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPEQD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPCMPEQQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPEQQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPCMPGTB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPGTB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPCMPGTW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPGTW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPCMPGTD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPGTD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPCMPGTQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMPGTQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMINSB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMINSB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMINSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMINSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMINSD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMINSD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMINUB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMINUB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMINUW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMINUW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMINUD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMINUD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMAXSB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMAXSB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMAXSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMAXSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMAXSD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMAXSD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMAXUB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMAXUB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMAXUW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMAXUW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMAXUD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMAXUD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSIGNB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSIGNB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSIGNW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSIGNW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSIGND_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSIGND_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPANDN_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDNPS_VpsHpsWpsR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPAND_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VANDPS_VpsHpsWpsR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPOR_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VORPS_VpsHpsWpsR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPXOR_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VXORPS_VpsHpsWpsR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPABSB_VdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPABSB_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPABSW_VdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPABSW_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPABSD_VdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPABSD_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBSB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBSB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDSB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDSB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBUSB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBUSB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSUBUSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSUBUSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDUSB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDUSB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPADDUSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPADDUSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPAVGB_VdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPAVGB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPAVGW_VdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPAVGW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPHADDW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPHADDW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPHADDD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPHADDD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPHSUBW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPHSUBW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPHSUBD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPHSUBD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPHADDSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPHADDSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPHSUBSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPHSUBSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSHUFHW_VdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSHUFHW_VdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSHUFLW_VdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSHUFLW_VdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPACKSSWB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPACKSSWB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPACKUSWB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPACKUSWB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPACKUSDW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPACKUSDW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPACKSSDW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPACKSSDW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKHDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKHPS_VpsHpsWpsR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKLDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKLPS_VpsHpsWpsR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKLBW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPUNPCKLBW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKLWD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPUNPCKLWD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKHBW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPUNPCKHBW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKHWD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPUNPCKHWD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKLQDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKLPD_VpdHpdWpdR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPUNPCKHQDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VUNPCKHPD_VpdHpdWpdR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMULLD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMULLD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMULLW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMULLW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMULHW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMULHW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMULHUW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMULHUW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMULDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMULDQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMULUDQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMULUDQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMULHRSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMULHRSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMADDUBSW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMADDUBSW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMADDWD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPMADDWD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VMPSADBW_VdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VMPSADBW_VdqHdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPBLENDVB_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPBLENDVB_VdqHdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPBLENDW_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPBLENDW_VdqHdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPMOVMSKB_GdUdq, &BX_CPU_C::BxError, &BX_CPU_C::VPMOVMSKB_GdUdq, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSADBW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSADBW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSHUFB_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSHUFB_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSHUFD_VdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMILPS_VpsWpsIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VMOVNTDQA_VdqMdq, &BX_CPU_C::VMOVAPS_VpsWpsM, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRLW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRLD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRLQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRAW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRAW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRAD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRAD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSLLW_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLW_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSLLD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSLLQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRLW_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLW_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRAW_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRAW_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSLLW_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLW_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRLD_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLD_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRAD_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRAD_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSLLD_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLD_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRLQ_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLQ_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSLLQ_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLQ_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSRLDQ_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLDQ_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPSLLDQ_UdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLDQ_UdqIb, BX_ISA_AVX2, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPALIGNR_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPALIGNR_VdqHdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXBW256_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMOVSXBW256_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXBD256_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VPMOVSXBD256_VdqWqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXBQ256_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VPMOVSXBQ256_VdqWdR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXWD256_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMOVSXWD256_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXWQ256_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VPMOVSXWQ256_VdqWqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVSXDQ256_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMOVSXDQ256_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXBW256_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMOVZXBW256_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXBD256_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VPMOVZXBD256_VdqWqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXBQ256_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VPMOVZXBQ256_VdqWdR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXWD256_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMOVZXWD256_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXWQ256_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VPMOVZXWQ256_VdqWqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMOVZXDQ256_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMOVZXDQ256_VdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPERM2I128_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERM2F128_VdqHdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VINSERTI128_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VINSERTF128_VdqHdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VEXTRACTI128_WdqVdqIb, &BX_CPU_C::VEXTRACTF128_WdqVdqIbM, &BX_CPU_C::VEXTRACTF128_WdqVdqIbR, BX_ISA_AVX2, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VBROADCASTI128_VdqMdq, &BX_CPU_C::VBROADCASTF128_VdqMdq, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPBROADCASTB_VdqWb, &BX_CPU_C::LOAD_Wb, &BX_CPU_C::VPBROADCASTB_VdqWb, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPBROADCASTW_VdqWw, &BX_CPU_C::LOAD_Ww, &BX_CPU_C::VPBROADCASTW_VdqWw, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPBROADCASTD_VdqWd, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VPBROADCASTD_VdqWd, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPBROADCASTQ_VdqWq, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VPBROADCASTQ_VdqWq, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VBROADCASTSS_VpsWss, &BX_CPU_C::BxError, &BX_CPU_C::VPBROADCASTD_VdqWd, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VBROADCASTSD_VpdWsd, &BX_CPU_C::BxError, &BX_CPU_C::VPBROADCASTQ_VdqWq, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPBLENDD_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VBLENDPS_VpsHpsWpsIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVD_VdqHdqMdq, &BX_CPU_C::VMASKMOVPS_VpsHpsMps, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVQ_VdqHdqMdq, &BX_CPU_C::VMASKMOVPD_VpdHpdMpd, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVD_MdqHdqVdq, &BX_CPU_C::VMASKMOVPS_MpsHpsVps, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VMASKMOVQ_MdqHdqVdq, &BX_CPU_C::VMASKMOVPD_MpdHpdVpd, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPERMQ_VdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMQ_VdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPERMD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPERMPS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_V256_VPERMPD_VpdWpdIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMQ_VdqWdqIbR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSRAVD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRAVD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSLLVD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLVD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSLLVQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSLLVQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSRLVD_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLVD_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSRLVQ_VdqHdqWdq, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPSRLVQ_VdqHdqWdqR, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERDPS_VpsHps, &BX_CPU_C::VGATHERDPS_VpsHps, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERQPS_VpsHps, &BX_CPU_C::VGATHERQPS_VpsHps, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERDPD_VpdHpd, &BX_CPU_C::VGATHERDPD_VpdHpd, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERQPD_VpdHpd, &BX_CPU_C::VGATHERQPD_VpdHpd, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERDD_VdqHdq, &BX_CPU_C::VGATHERDPS_VpsHps, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERQD_VdqHdq, &BX_CPU_C::VGATHERQPS_VpsHps, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERDQ_VdqHdq, &BX_CPU_C::VGATHERDPD_VpdHpd, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VGATHERQQ_VdqHdq, &BX_CPU_C::VGATHERQPD_VpdHpd, &BX_CPU_C::BxError, BX_ISA_AVX2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, BX_PREPARE_AVX) // AVX2 // AVX2 FMA bx_define_opcode(BX_IA_VFMADD132PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD213PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD231PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD132PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD213PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD231PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD132SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMADDSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD213SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMADDSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD231SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMADDSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD132SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMADDSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD213SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMADDSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADD231SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMADDSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSUB132PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSUB213PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSUB231PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSUB132PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSUB213PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSUB231PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADD132PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADD213PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADD231PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADD132PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADD213PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADD231PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB132PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB213PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB231PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB132PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB213PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB231PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB132SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMSUBSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB213SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMSUBSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB231SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMSUBSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB132SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMSUBSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB213SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMSUBSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUB231SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMSUBSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD132PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD213PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD231PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD132PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD213PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD231PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD132SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMADDSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD213SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMADDSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD231SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMADDSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD132SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMADDSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD213SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMADDSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADD231SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMADDSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB132PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB213PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB231PD_VpdHpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPD_VpdHpdWpdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB132PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB213PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB231PS_VpsHpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPS_VpsHpsWpsR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB132SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMSUBSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB213SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMSUBSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB231SD_VpdHsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMSUBSD_VpdHsdWsdR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB132SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMSUBSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB213SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMSUBSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_NNN, BX_SRC_RM, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUB231SS_VpsHssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMSUBSS_VpsHssWssR, BX_ISA_AVX_FMA, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NNN, BX_PREPARE_AVX) // AVX2 FMA // BMI1 bx_define_opcode(BX_IA_ANDN_GdBdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::ANDN_GdBdEdR, BX_ISA_BMI1, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSI_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLSI_BdEdR, BX_ISA_BMI1, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSMSK_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLSMSK_BdEdR, BX_ISA_BMI1, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSR_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLSR_BdEdR, BX_ISA_BMI1, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BEXTR_GdEdBd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BEXTR_GdEdBdR, BX_ISA_BMI1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ANDN_GqBqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::ANDN_GqBqEqR, BX_ISA_BMI1, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSI_BqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::BLSI_BqEqR, BX_ISA_BMI1, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSMSK_BqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::BLSMSK_BqEqR, BX_ISA_BMI1, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSR_BqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::BLSR_BqEqR, BX_ISA_BMI1, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BEXTR_GqEqBq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::BEXTR_GqEqBqR, BX_ISA_BMI1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) // BMI1 // BMI2 bx_define_opcode(BX_IA_MULX_GdBdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::MULX_GdBdEdR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_RORX_GdEdIb, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::RORX_GdEdIbR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLX_GdEdBd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::SHLX_GdEdBdR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRX_GdEdBd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::SHRX_GdEdBdR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SARX_GdEdBd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::SARX_GdEdBdR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BZHI_GdEdBd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BZHI_GdEdBdR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PEXT_GdEdBd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::PEXT_GdEdBdR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PDEP_GdEdBd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::PDEP_GdEdBdR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_MULX_GqBqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::MULX_GqBqEqR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_RM, 0) bx_define_opcode(BX_IA_RORX_GqEqIb, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::RORX_GqEqIbR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHLX_GqEqBq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::SHLX_GqEqBqR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SHRX_GqEqBq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::SHRX_GqEqBqR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_SARX_GqEqBq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::SARX_GqEqBqR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_RM, BX_SRC_VVV, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BZHI_GqEqBq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::BZHI_GqEqBqR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PEXT_GqEqBq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::PEXT_GqEqBqR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_PDEP_GqEqBq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::PDEP_GqEqBqR, BX_ISA_BMI2, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, 0) // BMI2 // FMA4 (AMD) bx_define_opcode(BX_IA_VFMADDSUBPS_VpsHpsWpsVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPS_VpsHpsWpsR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSUBPD_VpdHpdWpdVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDSUBPD_VpdHpdWpdR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADDPS_VpsHpsWpsVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPS_VpsHpsWpsR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBADDPD_VpdHpdWpdVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBADDPD_VpdHpdWpdR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDPS_VpsHpsWpsVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPS_VpsHpsWpsR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDPD_VpdHpdWpdVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMADDPD_VpdHpdWpdR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSS_VssHssWssVIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMADDSS_VssHssWssVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMADDSD_VsdHsdWsdVIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMADDSD_VsdHsdWsdVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBPS_VpsHpsWpsVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPS_VpsHpsWpsR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBPD_VpdHpdWpdVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFMSUBPD_VpdHpdWpdR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBSS_VssHssWssVIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFMSUBSS_VssHssWssVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFMSUBSD_VsdHsdWsdVIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFMSUBSD_VsdHsdWsdVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADDPS_VpsHpsWpsVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPS_VpsHpsWpsR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADDPD_VpdHpdWpdVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMADDPD_VpdHpdWpdR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADDSS_VssHssWssVIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMADDSS_VssHssWssVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMADDSD_VsdHsdWsdVIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMADDSD_VsdHsdWsdVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUBPS_VpsHpsWpsVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPS_VpsHpsWpsR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUBPD_VpdHpdWpdVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFNMSUBPD_VpdHpdWpdR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUBSS_VssHssWssVIb, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFNMSUBSS_VssHssWssVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFNMSUBSD_VsdHsdWsdVIb, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFNMSUBSD_VsdHsdWsdVIbR, BX_ISA_FMA4, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) // FMA4 (AMD) // XOP (AMD) bx_define_opcode(BX_IA_VPCMOV_VdqHdqWdqVIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPCMOV_VdqHdqWdqVIb, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPPERM_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPPERM_VdqHdqWdqVIb, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHAB_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHAB_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHAW_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHAW_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHAD_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHAD_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHAQ_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHAQ_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTB_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTB_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTW_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTW_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTD_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTD_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTQ_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTQ_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHLB_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHLB_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHLW_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHLW_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHLD_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHLD_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPSHLQ_VdqWdqHdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPSHLQ_VdqWdqHdq, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM_VVV, BX_SRC_VVV_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSSWW_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSSWW_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSSWD_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSSWD_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSSDQL_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSSDQL_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSSDD_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSSDD_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSSDQH_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSSDQH_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSWW_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSWW_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSWD_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSWD_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSDQL_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSDQL_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSDD_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSDD_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMACSDQH_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMACSDQH_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMADCSSWD_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMADCSSWD_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPMADCSWD_VdqHdqWdqVIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPMADCSWD_VdqHdqWdqVIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTB_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTB_VdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTW_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTW_VdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTD_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTD_VdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPROTQ_VdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPROTQ_VdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMB_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMB_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMW_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMW_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMD_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMD_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMQ_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMQ_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMUB_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMUB_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMUW_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMUW_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMUD_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMUD_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPCOMUQ_VdqHdqWdqIb, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPCOMUQ_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFRCZPS_VpsWps, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFRCZPS_VpsWpsR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFRCZPD_VpdWpd, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VFRCZPD_VpdWpdR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFRCZSS_VssWss, &BX_CPU_C::LOAD_Wss, &BX_CPU_C::VFRCZSS_VssWssR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VFRCZSD_VsdWsd, &BX_CPU_C::LOAD_Wsd, &BX_CPU_C::VFRCZSD_VsdWsdR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDBW_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDBW_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDBD_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDBD_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDBQ_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDBQ_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDWD_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDWD_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDWQ_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDWQ_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDDQ_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDDQ_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDUBW_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDUBW_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDUBD_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDUBD_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDUBQ_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDUBQ_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDUWD_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDUWD_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDUWQ_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDUWQ_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHADDUDQ_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHADDUDQ_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHSUBBW_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHSUBBW_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHSUBWD_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHSUBWD_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPHSUBDQ_VdqWdq, &BX_CPU_C::LOADU_Wdq, &BX_CPU_C::VPHSUBDQ_VdqWdqR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPERMIL2PS_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMIL2PS_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) bx_define_opcode(BX_IA_VPERMIL2PD_VdqHdqWdqIb, &BX_CPU_C::LOAD_Vector, &BX_CPU_C::VPERMIL2PD_VdqHdqWdqIbR, BX_ISA_XOP, BX_SRC_NNN, BX_SRC_VVV, BX_SRC_VIB_RM, BX_SRC_RM_VIB, BX_PREPARE_AVX) // XOP (AMD) // TBM (AMD) bx_define_opcode(BX_IA_BEXTR_GdEdId, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BEXTR_GdEdIdR, BX_ISA_TBM, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCFILL_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCFILL_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCI_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCI_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCIC_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCIC_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCMSK_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCMSK_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCS_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCS_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSFILL_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLSFILL_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSIC_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLSIC_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_T1MSKC_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::T1MSKC_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TZMSK_BdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::TZMSK_BdEdR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BEXTR_GqEqId, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BEXTR_GqEqIdR, BX_ISA_TBM, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCFILL_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCFILL_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCI_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCI_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCIC_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCIC_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCMSK_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCMSK_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLCS_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLCS_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSFILL_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLSFILL_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_BLSIC_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::BLSIC_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_T1MSKC_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::T1MSKC_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TZMSK_BqEq, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::TZMSK_BqEqR, BX_ISA_TBM, BX_SRC_VVV, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) // TBM (AMD) #endif /* BX_SUPPORT_AVX */ bx_define_opcode(BX_IA_TZCNT_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::TZCNT_GwEwR, BX_ISA_BMI1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_TZCNT_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::TZCNT_GdEdR, BX_ISA_BMI1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_TZCNT_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::TZCNT_GqEqR, BX_ISA_BMI1, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bx_define_opcode(BX_IA_LZCNT_GwEw, &BX_CPU_C::LOAD_Ew, &BX_CPU_C::LZCNT_GwEwR, BX_ISA_LZCNT, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_LZCNT_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::LZCNT_GdEdR, BX_ISA_LZCNT, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_LZCNT_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::LZCNT_GqEqR, BX_ISA_LZCNT, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif // SSE4A bx_define_opcode(BX_IA_MOVNTSS_MssVss, &BX_CPU_C::MOVSS_WssVssM, &BX_CPU_C::BxError, BX_ISA_SSE4A, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_MOVNTSD_MsdVsd, &BX_CPU_C::MOVSD_WsdVsdM, &BX_CPU_C::BxError, BX_ISA_SSE4A, BX_SRC_RM, BX_SRC_NNN, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_EXTRQ_UdqIbIb, &BX_CPU_C::BxError, &BX_CPU_C::EXTRQ_UdqIbIb, BX_ISA_SSE4A, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_EXTRQ_VdqUq, &BX_CPU_C::BxError, &BX_CPU_C::EXTRQ_VdqUq, BX_ISA_SSE4A, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_INSERTQ_VdqUqIbIb, &BX_CPU_C::BxError, &BX_CPU_C::INSERTQ_VdqUqIbIb, BX_ISA_SSE4A, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) bx_define_opcode(BX_IA_INSERTQ_VdqUdq, &BX_CPU_C::BxError, &BX_CPU_C::INSERTQ_VdqUdq, BX_ISA_SSE4A, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, BX_PREPARE_SSE) // SSE4A // ADCX/ADOX bx_define_opcode(BX_IA_ADCX_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::ADCX_GdEdR, BX_ISA_ADX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADOX_GdEd, &BX_CPU_C::LOAD_Ed, &BX_CPU_C::ADOX_GdEdR, BX_ISA_ADX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #if BX_SUPPORT_X86_64 bx_define_opcode(BX_IA_ADCX_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::ADCX_GqEqR, BX_ISA_ADX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) bx_define_opcode(BX_IA_ADOX_GqEq, &BX_CPU_C::LOAD_Eq, &BX_CPU_C::ADOX_GqEqR, BX_ISA_ADX, BX_SRC_NNN, BX_SRC_RM, BX_SRC_NONE, BX_SRC_NONE, 0) #endif bochs-2.6/docs-html/0000755000175000017500000000000012020641506014223 5ustar guillemguillembochs-2.6/docs-html/bxdebugger.html0000644000175000017500000003376712020641506017247 0ustar guillemguillem

Welcome to the Bochs x86 PC Emulation Software Home Page!



Debugger Functions:

void bx_dbg_exit(int code)

When there is a situation in the simulator, where you need to terminate due to an unrecoverable error (panic), call bx_dbg_exit(). Among other things, this function will call the at_exit callback function in each simulator, and ultimately call the system exit() function.

Bit8u bx_dbg_IAC(void)

The simulator's CPU code should call this function when it is acknowledging an interrupt from the PIC via the INTR line. The interrupt vector number from the PIC is returned.

Bit32u bx_dbg_inp(Bit16u addr, unsigned len)

To read data from an IO device, the simulator should call this function. Pass in the IO address addr, and the size of the IO operation len.

void bx_dbg_outp(Bit16u addr, Bit32u value, unsigned len)

To write data to an IO device, the simulator should call this function. Pass in the IO address addr, and the size of the IO operation len.

Bit8u bx_dbg_ucmem_read(Bit32u addr)
void bx_dbg_ucmem_write(Bit32u addr, Bit8u value)

For memory read/write accesses which fall in the range of 0xA0000 to 0xBFFFF, the accesses should not be to directed to the simulator's memory, since these are UnCacheable MEMory addresses. The VGA adapter maps it's memory to this range. Instead, call these functions to perform reads/writes to memory accesses in this range. For bx_dbg_ucmem_read(), pass the physical address addr, and the value of the read is returned. For bx_dbg_ucmem_write(), pass the physical address addr and value value of the write.

void bx_dbg_async_pin_ack(unsigned what, bx_bool val)

In order for the master and slave simulators to accept changes in pins such as the A20 line, at the same point, the debugger provides a mechanism for pending the pin change, until it is acknowledged by the master simulator. The place where the change is ack'd, is recorded by the debugger. This information is used to run the slave simulator, forcing it to accept the changes at the same locale as did the master.

Initially, the IO devices call a function bx_dbg_async_pin_request(), not listed here, to record the pin change as pending. The pending status is recorded along with the guard information in bx_guard.async_changes_pending.which. This field contains a binary OR'd set of pending pin changes. Currently only A20 is supported, which is represented by the macro BX_DBG_ASYNC_PENDING_A20.

At a time prudent to your CPU simulator, check to see if there are any pending changes, that the CPU should acknowledge. If so, acknowledge them by calling bx_dbg_async_pin_ack(). The pending value of the A20 enable is stored in bx_guard.async_changes_pending.a20. Here is some sample code which performs this task, that you can insert into the appropriate place in your CPU simulator.

  if (bx_guard.async_changes_pending.which) {
    if (bx_guard.async_changes_pending.which & BX_DBG_ASYNC_PENDING_A20)
      bx_dbg_async_pin_ack(BX_DBG_ASYNC_PENDING_A20,
                           bx_guard.async_changes_pending.a20);
    // ...other checks here when they are supported
    }
The bx_dbg_async_pin_ack() function will in turn, invoke the set_A20() callback function in the master simulator, so you don't have to deal with updating local A20 state in your simulator here, as long as you handle it in set_A20(). Keep in mind, the slave simulator will never see the code inside this sample code if-construct, since changes are forced in the slave by the debugger at points where the master simulator acknowledged them, not as a direct effect of the IO devices.

Guards:

Guards are a mechanism by which the debugger requests each simulator to stop execution and return control back to the debugger. The debugger runs each simulator for a particular number of instructions, or until certain events occur. Guards are set by the debugger, and it is up to each simulator to examine them upon and during execution of the execute() callback, and return control back to the debugger when the guard criteria are met.

Guard information set by the debugger is stored in global structure bx_guard of type bx_guard_t. For reference, it's declaration is shown here, followed by an explanation of the purpose of each field. Information about the guard encountered by the simulator, and which caused control to return to the debugger is stored in the global structure bx_guard_found[] of type bx_guard_found_t. This is actually an array of structures, where bx_guard_found[0] is the first simulator with ID 0, and bx_guard_found[1] is the second simulator with ID 1. This structure is also declared below, and the text explains the information which should be returned in this structure based on the guard encountered.

typedef struct {
  unsigned long guard_for;

  // instruction address breakpoints
  struct {
#if BX_DBG_SUPPORT_VIR_BPOINT
    unsigned num_virtual;
    struct {
      Bit32u cs;  // only use 16 bits
      Bit32u eip;
      unsigned bpoint_id;
      } vir[BX_DBG_MAX_VIR_BPOINTS];
#endif

#if BX_DBG_SUPPORT_LIN_BPOINT
    unsigned num_linear;
    struct {
      Bit32u addr;
      unsigned bpoint_id;
      } lin[BX_DBG_MAX_LIN_BPOINTS];
#endif

#if BX_DBG_SUPPORT_PHY_BPOINT
    unsigned num_physical;
    struct {
      Bit32u addr;
      unsigned bpoint_id;
      } phy[BX_DBG_MAX_PHY_BPOINTS];
#endif
    } iaddr;

  bx_dbg_icount_t icount; // stop after completing this many instructions

  // user typed Ctrl-C, requesting simulator stop at next convient spot
  volatile bx_bool interrupt_requested;

  // booleans to control whether simulator should report events
  // to debug controller
  struct {
   bx_bool irq;
   bx_bool a20;
   bx_bool io;
   bx_bool ucmem;
   bx_bool dma;
   } report;

  struct {
    bx_bool irq;  // should process IRQs asynchronously
    bx_bool dma;  // should process DMAs asynchronously
    } async;

#define BX_DBG_ASYNC_PENDING_A20   0x01
#define BX_DBG_ASYNC_PENDING_RESET 0x02
#define BX_DBG_ASYNC_PENDING_NMI   0x04

  // Asynchronous changes which are pending.  These are Q'd by
  // the debugger, as the master simulator is notified of a pending
  // async change.  At the simulator's next point, where it checks for
  // such events, it notifies the debugger with acknowlegement.  This
  // field contains a logically or'd list of all events which should
  // be checked, and ack'd.
  struct {
    unsigned which; // logical OR of above constants
    bx_bool a20;
    bx_bool reset;
    bx_bool nmi;
    } async_changes_pending;
  } bx_guard_t;

typedef struct {
  unsigned long guard_found;
  unsigned iaddr_index;
  bx_dbg_icount_t icount; // number of completed instructions
  Bit32u   cs;     // cs:eip and linear addr of instruction at guard point
  Bit32u   eip;
  Bit32u   laddr;
  bx_bool  is_32bit_code; // CS seg size at guard point
  bx_bool  ctrl_c; // simulator stopped due to Ctrl-C request
  } bx_guard_found_t;

extern bx_guard_t        bx_guard;
extern bx_guard_found_t  bx_guard_found[];

bx_guard_found[]:

It is the task of each simulator to update the bx_guard_found structure. There are some fields which are specific to the type of guard in question, and you should update those when a particular guard is encountered. Those fields are explained in more detail in the section relating to the specific guard. There are some fields which are updated for every case, no matter what the guard is. Below is a list and explanation of the usage of each field.

unsigned long guard_found; this should be filled in with the particular guard encountered, for example if an instruction count guard is hit, set this to BX_DBG_GUARD_ICOUNT.

unsigned iaddr_index; This field is updated, whenever a virtual/linear/physical instruction address guard is hit. It is the array index into the bx_guard.iaddr.vir[], bx_guard.iaddr.lin[], or bx_guard.iaddr.phy[] arrays, whichever is appropriate.

bx_dbg_icount_t icount; This contains the number of instructions which have been completely executed, when the guard was encountered.

Bit32u cs;
Bit32u eip;
Bit32u laddr;
bx_bool is_32bit_code; These all relate to the same instruction address. From the debugger's point of view, instruction addresses can be only at the beginning of the instruction. Once an instruction is completed, use the address of the next instruction. Set cs and eip to the instruction's address (CS:EIP). Set laddr to the instruction's corresponding linear address. Set is_32bit_code to the size (0=16bit, 1=32bit) of the code segment when the guard is encountered. This is used for disassembly.

bx_bool ctrl_c; To allow the user to interrupt a simulator from the debug prompt, the debugger traps Ctrl-C interrupts, and sets bx_guard.interrupt_requested. Your simulator can optionally look for this, provided that the BX_DBG_GUARD_CTRL_C bit is set in bx_guard.guard_for structure. If you chose to do so, you may look for this occurrance whenever is convenient. Set ctrl_c to 1 to signify this guard has occurred. Here' some sample code to demonstrate this:

    // convenient point to see if user typed Ctrl-C
    if (bx_guard.interrupt_requested && (bx_guard.guard_for & BX_DBG_GUARD_CTRL_C)) {
      bx_guard_found[BX_SIM_ID].guard_found = BX_DBG_GUARD_CTRL_C;
      return; // some mechanism to return control here
      }

bx_guard:

unsigned long guard_for;

This is a binary OR'd list of guards the debugger is requesting each simulator to stop on. Only if the corresponding bit is set in this field, should the simulator examine the rest of the criteria for that guard. Currently, each simulator must be capable of recognizing the following guards, and returning to the debugger when they occur:

  • BX_DBG_GUARD_ICOUNT: Instruction count.
  • BX_DBG_GUARD_CTRL_C: User requested interrupt via Ctrl-C
  • BX_DBG_GUARD_IADDR_VIR: Stop on this virtual instruction address
  • BX_DBG_GUARD_IADDR_LIN: Stop on this linear instruction address
  • BX_DBG_GUARD_IADDR_PHY: Stop on this physical instruction address

struct { .. } iaddr;

This structure holds the guard information for instruction address guards (breakpoints). Depending upon your selections, after editing config.h in the main directory (generated by running ./configure), certain types of instruction address guards are supported. Which ones, are determined by the BX_DBG_SUPPORT_VIR_BPOINT, BX_DBG_SUPPORT_LIN_BPOINT, and BX_DBG_SUPPORT_PHY_BPOINT macros.

If the guard_for field contains a set bit represented by BX_DBG_GUARD_IADDR_VIR, then the iaddr.num_virtual field holds the number of virtual instruction address guards to examine and compare to the current address. For each, you must examine the CS:EIP values stored in iaddr.vir[n], in the cs and eip subfields. If there is a match, record this in the guard found structure, and return control to the debugger:

bx_guard_found[ID].guard_found = BX_DBG_GUARD_IADDR_VIR;
bx_guard_found[ID].iaddr_index = n; // array index in bx_guard.iaddr.vir[]
bx_guard_found[ID].icount = .. // number of completed instructions
bx_guard_found[ID].cs = .. // CS selector value
bx_guard_found[ID].eip = .. // EIP value
bx_guard_found[ID].laddr = .. // linear address of CS:EIP
bx_guard_found[ID].is_32bit_code = .. // 0=16bit code, 1=32bit code
// return control here

If the guard_for field contains a set bit represented by BX_DBG_GUARD_IADDR_LIN, then the iaddr.num_linear field holds the number of linear instruction address guards to examine and compare to the current address. For each, you must examine the linear address values stored in iaddr.lin[n], in the addr subfield. If there is a match, record this in the guard found structure, and return control to the debugger:

bx_guard_found[ID].guard_found = BX_DBG_GUARD_IADDR_LIN;
bx_guard_found[ID].iaddr_index = n; // array index in bx_guard.iaddr.lin[]
bx_guard_found[ID].icount = .. // number of completed instructions
bx_guard_found[ID].cs = .. // CS selector value
bx_guard_found[ID].eip = .. // EIP value
bx_guard_found[ID].laddr = .. // linear address of CS:EIP
bx_guard_found[ID].is_32bit_code = .. // 0=16bit code, 1=32bit code
// return control here

If the guard_for field contains a set bit represented by BX_DBG_GUARD_IADDR_PHY, then the iaddr.num_physical field holds the number of physical instruction address guards to examine and compare to the current address. For each, you must examine the physical address values stored in iaddr.phy[n], in the addr subfield. If there is a match, record this in the guard found structure, and return control to the debugger:

bx_guard_found[ID].guard_found = BX_DBG_GUARD_IADDR_PHY;
bx_guard_found[ID].iaddr_index = n; // array index in bx_guard.iaddr.phy[]
bx_guard_found[ID].icount = .. // number of completed instructions
bx_guard_found[ID].cs = .. // CS selector value
bx_guard_found[ID].eip = .. // EIP value
bx_guard_found[ID].laddr = .. // linear address of CS:EIP
bx_guard_found[ID].is_32bit_code = .. // 0=16bit code, 1=32bit code
// return control here

volatile bx_bool interrupt_requested;

If the debugger has turned on the guard for a user interrupt, and the user has indeed requested one (Ctrl-C), the debugger will set this field to 1. The simulator should record this in the guard found information, and return control back to the debugger. Look above at the explanation for the bx_guard.interrupt_requested field for some sample code on how to do this.

struct { .. } async;

struct { .. } async_changes_pending;


bochs-2.6/docs-html/00README0000644000175000017500000000033212020641506015241 0ustar guillemguillemIn the past this folder contained the Bochs documentation. After converting everything to the docbook format, it can be used as a temporary storage for new stuff before adding it to the official docs. -Volker Ruppert bochs-2.6/docs-html/biossums.txt0000644000175000017500000000763112020641506016637 0ustar guillemguillembiossums Intention Writing a bios for a pc-compatible includes the task of embedding various checksums. At least there is the overall bios checksum stored in the very last byte of the program. Depending on the number and types of services the bios provides there are others, e.g. -- a checksum for the pci bios extensions, -- a checksum for the plug and play bios extensions, -- checksums for multiprocessor bios extensions. All these checksums have one common point: using the usual assembler directives they are hard (if not impossible) to compute at compile time. You can either compute them by hand --- a tedious, error-prone, task, where in addition you often have to make unreliable assumptions about the memory layout of the entire bios. Or you patch them directly into your compiled bios-image. Apart from computing the checksums this is what biossums does for you. Checksums With the exception of the overall bios checksum, in a modern pc-bios checksums are not used to ensure data integrity. Instead they are used in conjunction with certain signatures to securely identify the entry points or the addresses of important data of some bios-extensions. Because these services are often invoked from x86 protected mode the original method via interrupts is not applicable. Scanning (even only parts) of the bios for (short) signatures and solely relying on this is insecure though, cause the found signature might not refer to the sought service but rather be some obscure machine code resembling the signature by accident. Since signatures are usually part of a larger header or table the above mentioned problem is being circumvented by checksumming over this header and comparing the result to a checksum stored next to the signature. In practice the checksum is often part of the header, chosen in a way that the contents of the header add up to zero. Usage biossums is very simple and straightforward. The only (and mandatory) argument is the file-name of the bios-image. The file is being read, patched and written. So if you want to keep your original file for reference, use biossums on a copy of your bios-image. For now, biossums can only rely on signatures to find the locations of the accompanying checksums. Therefore biossums refuses to set any checksums if it finds more than one signature of the same type. Example output Run upon a Bochs bios configured for 2 CPUs (ver. 1.29) biossums displays: PCI-Bios header at: 0x9480 Current checksum: 0xA9 Calculated checksum: 0xA9 MP header at: 0xD0F0 Current checksum: 0xC1 Calculated checksum: 0xC1 PCMP header at: 0xD000 Current checksum: 0x65 Calculated checksum: 0x65 Bios checksum at: 0xFFFF Current checksum: 0x00 Calculated checksum: 0x24 Setting checksum. If we patch in a second "_32_" signature at offset 0x9760 and reset the PCMP checksum to 0x00 we get: PCI-Bios header at: 0x9480 Current checksum: 0xA9 Calculated checksum: 0xA9 PCI-Bios header at: 0x9760 Current checksum: 0x00 Calculated checksum: 0x00 Multiple PCI headers! No checksum set. MP header at: 0xD0F0 Current checksum: 0xC1 Calculated checksum: 0xC1 PCMP header at: 0xD000 Current checksum: 0x00 Calculated checksum: 0x65 Setting checksum. Bios checksum at: 0xFFFF Current checksum: 0x00 Calculated checksum: 0x01 Setting checksum. Possible enhancements Although biossums takes care of all checksums being used by the bios of the Bochs project (as of version 2.02) there are more to cover, e.g. the checksums for "Plug and Play" bios extension. In addition it was planned to provide further information to biossums via map-/ symbol-files to verify the locations of checksums apart from scanning for signatures. For now this seems not to be necessary; in practice no double signatures have been observed yet. bochs-2.6/docs-html/memory.txt0000644000175000017500000001272212020641506016300 0ustar guillemguillemMemory access handling explanation by Brendan Trotter: For the local APIC/s, any read or write to a CPU's own local APIC is handled internally and does not go to the bus. If the read/write misses this area then the read/write does go to the bus (where other CPU's ignore it). This means if 2 CPUs have different local APIC addresses and one CPU tries to write to the area used by the second CPU's local APIC, then it will go to the bus and will not access the second CPU's local APIC. This applies in all cases (e.g. hyper-threading and dual core work the same). For I/O APICs, the device is on the bus and should override anything that is "underneath" it. For example, if you relocate the I/O APIC to 0x00000000, then a read or write to this area will not reach the RAM underneath. In a similar way, if someone maps a PCI device to 0xFEC00000 (or somewhere that overlaps the I/O APIC) then a write to this area will not reach the PCI device. This leads to something like the following for accesses originating from a CPU: if (address_is_within_this_CPUs_local_APIC_area) do_local_APIC_access(); else if (address_is_within_an_I/O_APIC_area) do_I/O_APIC_access(); else if (address_is_within_a_PCI_device_area) do_PCI_access(); else if (address_is_within_RAM_area) do_RAM_access(); else printf("Bogus address!\n"); For an accesses originating from a PCI device (e.g. PCI bus masters), there is no access to any CPUs local APIC. It'd go like: if (address_is_within_an_I/O_APIC_area) do_I/O_APIC_access(); else if (address_is_within_a_PCI_device_area) do_PCI_access(); else if (address_is_within_RAM_area) do_RAM_access(); else printf("Bogus address from PCI device!\n"); In both cases it is complicated by the configuration of the PCI host controller/s and any "PCI to PCI" bridges. Fortunately this can be ignored by Bochs as it doesn't support PCI bridges (except for the host controller itself which can handle all accesses). Bochs may need to worry about the "PCI to LPC" bridge though. For example, even though a PCI device can read/write to the I/O APIC, an ISA device behind the PCI to LPC bridge can't. This means for an ISA bus master you'd have something like: if (address_is_within_a_PCI_device_area) do_PCI_access(); else if (address_is_within_RAM_area) do_RAM_access(); else printf("Bogus address from PCI device!\n"); This complicates things for the ISA DMA controllers, which should not be able to read/write to the I/O APIC - for e.g. if the I/O APIC base is set to 0x00000000, then an ISA DMA transfer that writes to 0x00000000 should write to RAM not the I/O APIC (a PCI bus master would write to the I/O APIC in the same situation). I'm not convinced modelling real hardware 100% correctly is necessary though - it would only matter for very rare situations (e.g. when the OS stuffs things up badly). A normal OS will not stuff things up like this (i.e. a normal OS won't map the I/O APIC to an area that overlaps RAM or anything else). For OS developers (who might stuff things up), it'd probably be better to panic anyway - e.g. "BX_PANIC: I/O APIC base set to an address that overlaps RAM or a memory mapped device". In general, the CPU has an "address bus" which consists of data lines, address lines and 2 others lines. One of these other lines is the "I/O select" line - if you do "mov [0x000000AA],al" and then do "out 0xAA,al" you'd get almost the same thing on the CPUs bus (the only difference would be the state of the "I/O select" line). When the CPU does an access that is intended for I/O port space it just asserts the "I/O select" line. The second line is for SMM which works just like the I/O select line. When the CPU accesses a memory location normally the "SMM select" line is not asserted and normal memory is accessed. When the CPU is in SMM mode the "SMM select" line is asserted for memory accesses. This means that the CPU can use 3 completely seperate address spaces (one for normal memory, one for I/O space and another for SMRAM). How the chipset treats these lines depends on what the CPU is used for - for example, these lines could be ignored so that all types of accesses are the same (which means I/O port instructions would access memory locations from 0x00000000 to 0x0000FFFF and there'd be no seperate SMRAM area). For "PC compatible" computers the "I/O select" line does select a completely seperate address space, but the "SMM select" line does not. Instead, the chipset uses it to disable access to the video display memory (and enable access to the RAM underneath). Fortunately, access to the SMRAM area is also controlled by the chipset, such that the CPU can access SMRAM regardless of whether it asserts it's "SMM select" line or not. As mentioned in my previous email, for the I440FX chipset it's called the System Management RAM Control Register (or SMRCR), and is in the PCI host controller's PCI configuration space at offset 0x72. Returning to what I wrote earlier, this leads to something like the following for accesses originating from a CPU: if (address_is_within_this_CPUs_local_APIC_area) do_local_APIC_access(); else if ((CPU_is_in_SMM_mode || chipset_SMRCR_enabled) && address_is_within_SMM_area) do_SMM_access(); else if (address_is_within_an_I/O_APIC_area) do_I/O_APIC_access(); else if (address_is_within_a_PCI_device_area) do_PCI_access(); else if (address_is_within_RAM_area) do_RAM_access(); else printf("Bogus address!\n"); bochs-2.6/docs-html/random.txt0000644000175000017500000000074012020641506016245 0ustar guillemguillemlook at http://www.ao.net/help/software/lps/disktools/INDEX asbench.zip Benchmark for drives under a ASPI device driver ataid011.zip ATA Identification. Echos Identify Drive data atrt4mb.exe AT Regression test and most interesting of all: ext2tool.zip Mount and use Ext2 filesystems from DOS From: Gregg Eshelman Sounds good. :) Some Windows disk imaging apps are WinImage and SH (Schenk and Horne) Copy Star. bochs-2.6/docs-html/enh_dbg_user_man.txt0000644000175000017500000001710012020641506020242 0ustar guillemguillemUser tips: (ver 1.2) The main user features available from the menus should be fairly obvious to anyone who has used bochs -- but here are a few quick explanations, anyway. These explanations include a few keyboard and mouse shortcuts that you might not find through experimentation. Terminology: The Bochs guys call this GUI debugger interface the CI, to distinguish it for themselves from the "VGA window" that shows the display of the simulated computer. I will call this debugger GUI interface the "frontend". It's not much better of a term, but oh well. The text debugger interface that you are all familiar with is called the Bochs Internal Debugger ("ID" for short). The frontend is organized around 3 main "list-view" windows: The Register window: Typically, all the various registers are grouped by color. If you don't like the colors, they can be turned off, or modified at compile time. There are options to show or hide most register "groups", so that you can focus more strictly on the registers you are interested in (probably just the GP registers). Notes: Yes, the XMM display shows hex in the "decimal" column -- there is more room there. Deal with it. ** Doubleclicking a register attempts to change its value. Bochs may not allow you to change most registers. In future versions, more registers may be modifiable. The Disassembly window: Disassembly output that is autoloaded, or generated from the menu, ends up here. If the frontend cannot detect the "current instruction" in the list, when it reaches the next instruction -- then it will autoload a new list. Having a big list will reduce the number of autoloads, and allows you to see more. The list can contain up to 2048 lines. However, if you load more than 1000 lines, you are more likely to see performance problems. Note: There are two kinds of emulated memory in bochs: Linear and Physical. Emulated Linear memory is mapped onto Physical memory by x86 virtual memory methods (paging and segmentation). If paging and segmenataion are "off", or "identity mapped", then both "types" of memory mean the same thing. But they still work a little differently. With the Internal Debugger, you can set breakpoints to either kind of memory, separately. Normally, you would use the "b" command to set breakpoints in physical mem, and "lb" to set breakpoints in linear mem. This frontend ONLY displays linear breakpoints. It does not bother trying to figure out the linear->phsical reverse mapping to show physical breakpoints. (There are also "virtual" breakpoints that are also not shown.) All the types of breakpoints still WORK, it is just that you will not see them marked on the screen. It will be obvious to you that the current instruction is marked in green, unless it is on a breakpoint, when it turns blue. Breakpoints are red, of course. ** You must click a line in the window, before you can use frontend commands to set or clear a linear breakpoint on it. ** You can doubleclick (which saves steps) to set or clear a linear breakpoint. The MemDump window: As of this version, the MemDump window isn't much more than a display of the contents of memory. In later versions, hopefully it will be expanded into a fairly fully-featured hexeditor. You can dump either phyical mem, or linear mem. There are breakpoint-like things (that work with physical memory only, currently), called "watchpoints". A physical memory address can cause a break in the simulation if it is read, or written. The frontend again does NOT try to calculate out the linear -> physical mapping in any attempt to display the physical watchpoints while viewing linear mem. You must click a hex byte (on a physical mem dump that shows bytes), in order to set or clear a read and/or write watchpoint on that byte. Read watchpoints are green (on black), write watchpoints are red, watchpoints that are both write and read are blue. There is a hardcoded limit in bochs of 16 of each type of watchpoint. The MemDump window loads/shows 4K of memory at a time. ** PageUp/Down scrolls the display up or down through mem, 2K at a time. ** Doubleclicking a line of memory allows you to change the byte values. (Works on both linear and physical mem dumps.) ** Doubleclicking with the Shift key down sets write watchpoints. ** Doubleclicking with Alt sets read watchpoints. ** You need to click once on the memory window before you can use its "Find" function. The Find function is pretty limited in scope, currently. It can only find bytes (or strings of bytes) within each 16byte "line". Other windows: The Output window shows anything that the Bochs Internal Debugger tries to send to you. The window is scrollable, but only keeps a limited history of output (10K). The ID is always spamming you with "Next at t=" and disassembly lines, that would tend to fill up the Output window with garbage -- so there are options to ignore either of these types of output. The Input window is for sending user commands directly into the Bochs Internal Debugger -- bypassing the frontend. Results will appear in the Output Window. The Input window has a history feature for commands, using the Up and Down arrows -- it remembers 64 commands, 80 bytes each. No matter where you click on the frontend, you can always type directly into the Input box without clicking on it. When the Input window is invisible, you should still be able to type into it -- after taking into account the bug listed at the bottom of this file. ** Hitting Enter on a blank line will cause a Singlestep. The Param Tree: The bochs param_tree shows the internal state of most of bochs. It will be expanded in the future to show even more. You can see the detailed state of all cpu registers -- including the "hidden" parts (look in the "bochs" branch). Or see the current state of most of the emulated hardware. The Stack window: The MemDump windows do not automatically refresh -- except for the Stack window. If you leave the stack window active, it will update as the stack changes. If you want to update the other MemDump windows with fresh data, hit Refresh. The Breakpoint/Watchpoint window: Doubleclicking will delete a breakpoint or watchpoint. The Command Button row: Just a (hopefully) convenient way of using the mouse, instead of the keyboard. If you don't like them, or they take up too much space, you can turn them off. The CPU Button row: This only shows up when you are running a multi-cpu simulation. Click on the CPU that you want to view. All CPUs are always stepped together, and they all stop the first time one hits some sort of breakpoint. Docking/Resizing If you grab one of the two vertical "bars" between the lists, you can horizontally resize the lists. The cursor will change, but there will be no animation. If you grab the middle of one of the lists, and drag it on top of one of the other lists, you can reorder the positions of the lists on the screen. The cursor will change, but there will be no animation. You can set an alternate "docking order" at compile time, also, if you have a permanent preference. (See the top of the wenhdbg_h.h file, for compile-time customization.) Additional Notes: If you have a really big GDT or Paging display in the MemDump window, and you select a different display, it may take several seconds to delete the big display before it can switch. Uppercase text tends to seem a little annoying, but it really is a lot easier to read, especially on a proportional font. If you change to a fixed font, then you may want to switch the display to lowercase. KDE Users: The gtk-qt-engine drawing functions of Ver 0.71 (or anything earlier than 1.0?) draw all text as black, instead of in the correct foreground colors. Fix: Upgrade to 1.1. bochs-2.6/docs-html/cpu_configurability.txt0000644000175000017500000003401412020641506021027 0ustar guillemguillemBochs CPU configurability - go over all CPUID feature extensions and see how and where it affects Bochs configurable CPU engine 1. ISA Feature: X87 (FPU on chip) The FPU can be present on chip before CPUID as well, for example in 80386. Enables CPUID[0x00000001].EDX[0] and x87 instructions. Without X87 FPU instruction will execute stub FPU_ESC. Controlled by BX_SUPPORT_X87 configure option only, cannot be toggled in runtime. 2. CPU Feature: VME (Virtual-8086 Mode enhancements) First introduced in Pentium. Enables CPUID[0x00000001].EDX[1] flag. Controls ability to set CR4[0] (VME) and CR4[1] (PVE) bits. The CR4 controls enable Virtual-8086 Mode enhancements functionality. Dependency: BX_CPU_LEVEL >= 4 for CR4 support. 3. CPU Feature: Debug Extensions (I/O breakpoints) Enables CPUID[0x00000001].EDX[2] flag. Controls ability to set CR4[3] (Debug Extensions) bit. The bit controls DR4/DR5 (DR4/DR5 are aliased to DR6/DR7 without CR4.DE set) and enables I/O breakpoints. Dependency: BX_CPU_LEVEL >= 4 for CR4 support. 4. CPU Feature: Page Size Extensions Enables CPUID[0x00000001].EDX[3] flag. Controls ability to set CR4[4] (PSE) bit. The bit is checked during page walk in order to enable 4MB pages through PDE.PS bit. The PDE.PS bit is ignored if CR4.PSE is clear Dependency: BX_CPU_LEVEL >= 4 for CR4 support. 5. CPU Feature: Time Stamp Counter First introduced in Pentium. Enables CPUID[0x00000001].EDX[4] flag. Controls ability to set CR4[2] (TSD) bit. Enables RDTSC instruction (the instruction will #UD if the Time Stamp Counter is not supported). Enables MSR 0x010 IA_MSR_TSC. Dependency: MSR 6. ISA Feature: MSR First introduced in Pentium. Enables CPUID[0x00000001].EDX[5] flag. Enables RDMSR/WRMSR instructions (the instructions will #UD if the MSR is not supported). Enables access to Model Specific MSR registers. 7. CPU Feature: Physical Address Extensions Enables CPUID[0x00000001].EDX[6] flag. Controls ability to set CR4[5] (PAE) bit. The bit is checked during page walk in order to enable PAE paging mode. Dependency: BX_CPU_LEVEL >= 4 for CR4 support. 8. CPU Feature: Machine Check Enables CPUID[0x00000001].EDX[7] (Machine Check Exception) flag. Enables CPUID[0x00000001].EDX[14] (Machine Check Architecture) flag. Controls ability to set CR4[6] (MCE) bit. Enables Machine Check MSR registers and ability to trigger machine check exception. Note, that Bochs can never trigger the machine check exception. Dependency: MSR 9. ISA Feature: CMPXCHG8B instruction First introduced in Pentium. Enables CPUID[0x00000001].EDX[8] flag. Enables CMPXCHG8B instruction (the instruction will #UD otherwise). 10. CPU Feature: APIC on chip Enables MSR_APIC_BASE register. Enables CPUID[0x00000001].EDX[9] (Apic on Chip) flag. The CPUID bit is read from MSR_APIC_BASE[11] (Global Enable Bit). Enables CPUID[0x00000001].EBX[31:24] (Local Apic ID) reporting. Enables Local APIC functionality. Without Local APIC the system behaves as Local APIC is globally disabled. Dependency: MSR 11. ISA Feature: SYSENTER/SYSEXIT support First introduced in P6. Enables CPUID[0x00000001].EDX[11] flag. Enables IA_SYSENTER_CS_MSR, IA_SYSENTER_ESP_MSR, IA_SYSENTER_EIP_MSR. Enables SYSENTER/SYSEXIT instructions (will #UD otherwise) Dependency: MSR 12. CPU Feature: MTRR Enables CPUID[0x00000001].EDX[12] flag. Enables MTRR MSR registers. Enables Memory Type (not yet implemented). Dependency: MSR 13. CPU Feature: Global Pages Enables CPUID[0x00000001].EDX[13] flag. Controls ability to set CR4[7] (PGE) bit. Enables PTE Global bit during page walk and global pages support. Dependency: BX_CPU_LEVEL >= 4 for CR4 support. 14. ISA Feature: CMOV First introduced in P6. Enables CPUID[0x00000001].EDX[15] flag. Enables CMOV/FCMOV instructions (will #UD otherwise). 15. CPU Feature: PAT Enables CPUID[0x00000001].EDX[16] flag. Enables PAT MSR register. Enables PAT bit in page tables. Extends Memory Type calculation algorithm (not yet implemented). Dependency: MSR 16. CPU Feature: PSE-36 Enables CPUID[0x00000001].EDX[17] flag. Enables generation of > 32 bit physical address during regular non-PAE page walk. Current can't be turned on/off on runtime, controlled using BX_PHY_ADDRESS_LONG configure variable. Dependency: Indicates > 32bit physical address support. 17. CPU Feature: PSN (Processor Serial Number) Enables CPUID[0x00000001].EDX[18] flag. Enables CPUID leaf 0x00000003 (Processor Serial Number). Not implemented in Bochs. 18. ISA Feature: CLFLUSH Enables CPUID[0x00000001].EDX[19] flag. Enables CPUID[0x00000001].EBX[15:08] (CLFLUSH cache line size) reporting. Enables CLFLUSH instruction (will #UD otherwise). 19. CPU Feature: Debug Store ??? Enables CPUID[0x00000001].EDX[21] flag. Not implemented in Bochs. 20. CPU Feature: ACPI: Thermal Monitor and Software Controlled Clock Facilities ??? Enables CPUID[0x00000001].EDX[22] flag. Not implemented in Bochs. 21. ISA Feature: MMX First introduced in Pentium. Enables CPUID[0x00000001].EDX[23] flag. Enables MMX instructions (will #UD otherwise). Dependency: X87 (sharing the same registers) 22. ISA Feature: FXSAVE/FXRSTOR First introduced in P6 (together with SSE?). Enables CPUID[0x00000001].EDX[24] flag. Controls ability to set CR4[9] (OSFXSR) bit. Enables FXSAVE/FXRSTOR instructions (will #UD otherwise). 23. ISA Feature: SSE Enables CPUID[0x00000001].EDX[25] flag. Controls ability to set CR4[10] (OSXMMEXCPT) bit. Enables SSE decoding scheme (0x66, 0xF2 and 0xF3 prefixes as opcode extension). Enables MXCSR and SSE registers. Enables SSE instructions (will #UD otherwise) and new #XF exception. Dependency: FXSAVE/FXRSTOR 24. ISA Feature: SSE2 Enables CPUID[0x00000001].EDX[26] flag. Enables MXCSR.DAZ bit support. Enables SSE2 instructions (will #UD otherwise). Dependency: SSE 25. CPU Feature: Self snoop Uarch only, not emulation visible. Enables CPUID[0x00000001].EDX[27] flag. 26. CPU Feature: Hyper Threading Technology Enables CPUID[0x00000001].EDX[28] flag. Enables CPUID[0x00000001].EBX[23:16] (Number of logical processors in one physical processor) reporting. Indicates that CPU supports hyper-threading technology (not emulation visible). 27. CPU Feature: Thermal Monitor ??? Enables CPUID[0x00000001].EDX[29] flag. Not implemented in Bochs. 28. CPU Feature: PBE (Pending Break Enable) ??? Enables CPUID[0x00000001].EDX[31] flag. Not implemented in Bochs. 29. ISA Feature: SSE3 Enables CPUID[0x00000001].ECX[0] flag. Enables SSE3 instructions (will #UD otherwise). Dependency: SSE 30. ISA Feature: AES and PCLMULQDQ instruction Enables CPUID[0x00000001].ECX[1] flag (PCLMULQDQ). Enables CPUID[0x00000001].ECX[25] flag (AES). Enables PCLMULQDQ instruction (will #UD otherwise). Enables AES instruction (will #UD otherwise). Dependency: SSSE3 (3-byte opcode) 31. CPU Feature: DTES64 (64-bit DS area) ??? Enables CPUID[0x00000001].ECX[2] flag. Not implemented in Bochs. 32. ISA Feature: MONITOR/MWAIT Enables CPUID[0x00000001].ECX[3] flag. Enables CPUID[0x00000005] leaf (MONITOR/MWAIT). Enables MONITOR/MWAIT instructions (will #UD otherwise). Enables power management sleep states (can enter to sleep state with MWAIT). 33. CPU Feature: DS-CPL (CPL qualified debug store) ??? Enables CPUID[0x00000001].ECX[4] flag. Not implemented in Bochs. 34. ISA Feature: VMX Enables CPUID[0x00000001].ECX[5] flag. Controls ability to set CR4[13] (VMXE) bit. Enables VMX MSR registers. Enables VMX instructions (will #UD otherwise). VMX mode can be enabled only using VMX instructions. 35. ISA Feature: SMX Enables CPUID[0x00000001].ECX[6] flag. Controls ability to set CR4[14] (SMXE) bit. Enables SMX instruction GETSEC (will #UD otherwise). SMX mode can be enabled only using SMX instruction. 36. CPU Feature: EST (Enhanced Intel SpeedStep Technology) ??? Enables CPUID[0x00000001].ECX[7] flag. Not implemented in Bochs. 37. CPU Feature: TM2 (Thermal Monitor 2) ??? Enables CPUID[0x00000001].ECX[8] flag. Not implemented in Bochs. 38. ISA Feature: SSSE3 Enables CPUID[0x00000001].ECX[9] flag. Enables SSSE3 instructions (will #UD otherwise). Enables 3-byte opcode decoding. Dependency: SSE 39. CPU Feature: CNXT-ID: L1 context ID ??? Enables CPUID[0x00000001].ECX[10] flag. Not implemented in Bochs. 30. ISA Feature: FMA Enables CPUID[0x00000001].ECX[12] flag. Enables Intel 3-src FMA instructions (will #UD otherwise). Dependency: AVX (VEX encoded) 31. ISA Feature: CMPXCHG16B Enables CPUID[0x00000001].ECX[13] flag. Enables CMPXCHG16B instruction (will #UD otherwise). Dependency: Long Mode 32. CPU Feature: xTPR update control ??? Enables CPUID[0x00000001].ECX[14] flag. Not implemented in Bochs. 33. CPU Feature: PDCM (Perfon and Debug Capability MSR) ??? Enables CPUID[0x00000001].ECX[15] flag. Not implemented in Bochs. 34. CPU Feature: PCID Enables CPUID[0x00000001].ECX[17] flag. Controls ability to set CR4[17] (PCID) bit. PCID functionality is enabled under CR4.PCID set. Selective TLB flush on PCID switch is not implemented in Bochs (always flush whole TLB). 35. CPU Feature: DCA (Direct Cache Access) Enables CPUID[0x00000001].ECX[18] flag. Enables IA32_PLATFORM_DCA_CAP MSR register. Enables CPUID[0x00000009] Direct Cache Access Information Leaf. Indicates the processor supports the ability to prefetch data from a memory mapped device. Not implemented in Bochs. 36. ISA Feature: SSE4.1 Enables CPUID[0x00000001].ECX[19] flag. Enables SSE4.1 instructions (will #UD otherwise). Dependency: SSSE3 (3-byte opcodes) 37. ISA Feature: SSE4.2 Enables CPUID[0x00000001].ECX[20] flag. Enables SSE4.2 instructions (will #UD otherwise). Dependency: SSSE3 (3-byte opcodes) 38. CPU Feature: X2APIC Enables CPUID[0x00000001].ECX[21] flag. Enables X2APIC MSR registers. Enables X2APIC mode in the Local APIC. 39. ISA Feature: MOVBE Enables CPUID[0x00000001].ECX[22] flag. Enables MOVBE instruction (will #UD otherwise). Dependency: SSSE3 (3-byte opcodes) 40. ISA Feature: POPCNT Enables CPUID[0x00000001].ECX[23] flag. Enables POPCNT instruction (will #UD otherwise). Dependency: SSE (encoded with SSE prefixes) 41. CPU Feature: TSC Deadline ??? Enables CPUID[0x00000001].ECX[24] flag. Not implemented in Bochs. 42. ISA Feature: XSAVE Enables CPUID[0x00000001].ECX[26] flag. Enables CPUID[0x00000001].ECX[27] flag (copy from CR4.OSXSAVE bit). Controls ability to set CR4[18] (OSXSAVE) bit. Enables CPUID[0x0000000D] leaf (XSAVE). Enables XCR0 register. Enables XSETBW/XGETBV/XSAVE/XRSTOR instructions (will #UD otherwise). 43. ISA Feature: AVX Enables CPUID[0x00000001].ECX[28] flag. Enables XCR0[2] (AVX) bit. Enables CPUID[0x0000000D][2] subleaf leaf. Enables AVX registers. Enables VEX prefix decoding and AVX instructions (will #UD otherwise). Dependency: XSAVE 44. ISA Feature: AVX_F16C Enables CPUID[0x00000001].ECX[29] flag. Enables VCVTPH2PS/VCVTPS2PH instructions (will #UD otherwise). Dependency: AVX (VEX encoded) 45. ISA Feature: RDRAND Enables CPUID[0x00000001].ECX[30] flag. Enables RDRAND instructions (will #UD otherwise). Not implemented in Bochs. 46. ISA Feature: FS_GS_BASE Enables CPUID[0x00000007].EBX[0] flag. Controls ability to set CR4[16] (FSGSBASE) bit. Enables FS/GS BASE access instructions (will #UD otherwise). Dependency: Long Mode only 47. CPU Feature: SMEP Enables CPUID[0x00000007].EBX[7] flag. Controls ability to set CR4[20] (SMEP) bit. Enables Supervisor Mode Execution Protection during PAE mode page walk. Enables FS/GS BASE access instructions (will #UD otherwise). Dependency: PAE 48. ISA Feature: SYSCALL/SYSRET First introduced in AMD K6-2 processor. Enables CPUID[0x80000001].EDX[11] flag. Controls ability to set EFER.SCE bit. Enables MSR_STAR, MSR_LSTAR, MSR_CSTAR, MSR_FMASK registers (MSR_STAR is required for legacy mode, rest for long64 mode only) Enables SYSCALL/SYSRET instructions (will #UD otherwise). On Intel SYSCALL/SYSRET supported in long mode only, AMD allow protected mode as well. Dependency: MSR 49. CPU Feature: NX Enables CPUID[0x80000001].EDX[20] flag. Controls ability to set EFER.NX bit. Enables Non-execute protection during PAE mode page walk. Dependency: PAE 50. ISA Feature: AMD MMX Extensions ??? Enables CPUID[0x80000001].EDX[22] flag. Not implemented in Bochs. 51. CPU Feature: FFXSR Enables CPUID[0x80000001].EDX[25] flag. Controls ability to set EFER.FFXSR bit. Enables Fast FXSAVE/FXRSTOR functionality under long mode. Dependency: Long Mode 52. CPU Feature: 1G pages Enables CPUID[0x80000001].EDX[26] flag. Enables PDPE.PS bit and 1G paging support during long mode page walk. Dependency: Long Mode 53. ISA Feature: RDTSCP Enables CPUID[0x80000001].EDX[27] flag. Enables MSR_TSC_AUX register. Enables RDTSCP instruction (will #UD otherwise). Dependency: TSC 54. ISA Feature: Long Mode Enables CPUID[0x80000001].EDX[29] flag. Controls setting of EFER.LMA (Long Mode Active) and EFER.LME (Long Mode Enabled) bits. Enables Long Mode with new registers, new instructions and new decoding scheme. Enables long mode MSR registers. 55. ISA Feature: 3DNow! Ext Enables CPUID[0x80000001].EDX[30] flag. Enables 3DNow! EXT instructions (will #UD otherwise). Dependency: 3DNOW 56. ISA Feature: 3DNow! Enables CPUID[0x80000001].EDX[31] flag. Enables 3DNow! instructions (will #UD otherwise). Dependency: MMX 57. ISA Feature: Long Mode LAHF/SAHF support Enables CPUID[0x80000001].ECX[0] flag. Enables LAHF/SAHF instructions in long mode (will #UD otherwise). 58. CPU Feature: Misaligned SSE Enables CPUID[0x80000001].ECX[7] flag. Controls setting of MXCSR.MM bit. Enables misaligned SSE memory accesses without #GP fault. Enables #AC exception checking on all SSE instruction that previously required alignment and caused #GO for misaligned access. Dependency: SSE 59. ISA Feature: PrefetchW Enables CPUID[0x80000001].ECX[8] flag. Set if PREFETCHW implemented as real HW prefetch. Uarch only. Has no effect for Bochs. 60. ISA Feature: ADX Enables CPUID[0x00000007].EBX[19] flag. Enables ADCX/ADOX instructions (will #UD otherwise). Dependency: SSSE3 (3-byte opcodes) bochs-2.6/plugin.h0000644000175000017500000005236312020641507014012 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: plugin.h 11224 2012-06-21 17:33:37Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // // This file provides macros and types needed for plugins. It is based on // the plugin.h file from plex86, but with significant changes to make // it work in Bochs. // Plex86 is Copyright (C) 1999-2000 The plex86 developers team // ///////////////////////////////////////////////////////////////////////// #ifndef __PLUGIN_H #define __PLUGIN_H #include "extplugin.h" class bx_devices_c; BOCHSAPI extern logfunctions *pluginlog; #ifdef __cplusplus extern "C" { #endif #define BX_PLUGIN_UNMAPPED "unmapped" #define BX_PLUGIN_BIOSDEV "biosdev" #define BX_PLUGIN_CMOS "cmos" #define BX_PLUGIN_VGA "vga" #define BX_PLUGIN_CIRRUS "svga_cirrus" #define BX_PLUGIN_FLOPPY "floppy" #define BX_PLUGIN_PARALLEL "parallel" #define BX_PLUGIN_SERIAL "serial" #define BX_PLUGIN_KEYBOARD "keyboard" #define BX_PLUGIN_BUSMOUSE "busmouse" #define BX_PLUGIN_HARDDRV "harddrv" #define BX_PLUGIN_HDIMAGE "hdimage" #define BX_PLUGIN_DMA "dma" #define BX_PLUGIN_PIC "pic" #define BX_PLUGIN_PIT "pit" #define BX_PLUGIN_PCI "pci" #define BX_PLUGIN_PCI2ISA "pci2isa" #define BX_PLUGIN_PCI_IDE "pci_ide" #define BX_PLUGIN_SOUNDMOD "soundmod" #define BX_PLUGIN_SB16 "sb16" #define BX_PLUGIN_ES1370 "es1370" #define BX_PLUGIN_NETMOD "netmod" #define BX_PLUGIN_NE2K "ne2k" #define BX_PLUGIN_EXTFPUIRQ "extfpuirq" #define BX_PLUGIN_PCIDEV "pcidev" #define BX_PLUGIN_USB_COMMON "usb_common" #define BX_PLUGIN_USB_UHCI "usb_uhci" #define BX_PLUGIN_USB_OHCI "usb_ohci" #define BX_PLUGIN_USB_XHCI "usb_xhci" #define BX_PLUGIN_PCIPNIC "pcipnic" #define BX_PLUGIN_E1000 "e1000" #define BX_PLUGIN_GAMEPORT "gameport" #define BX_PLUGIN_SPEAKER "speaker" #define BX_PLUGIN_ACPI "acpi" #define BX_PLUGIN_IODEBUG "iodebug" #define BX_PLUGIN_IOAPIC "ioapic" #define BX_REGISTER_DEVICE_DEVMODEL(a,b,c,d) pluginRegisterDeviceDevmodel(a,b,c,d) #define BX_UNREGISTER_DEVICE_DEVMODEL(a) pluginUnregisterDeviceDevmodel(a) #define PLUG_device_present(a) pluginDevicePresent(a) #if BX_PLUGINS #define PLUG_load_plugin(name,type) {bx_load_plugin(#name,type);} #define PLUG_load_opt_plugin(name) bx_load_plugin(name,PLUGTYPE_OPTIONAL) #define PLUG_load_user_plugin(name) {bx_load_plugin(name,PLUGTYPE_USER);} #define PLUG_unload_plugin(name) {bx_unload_plugin(#name,1);} #define PLUG_unload_opt_plugin(name) bx_unload_plugin(name,1) #define PLUG_unload_user_plugin(name) {bx_unload_plugin(name,1);} #define DEV_register_ioread_handler(b,c,d,e,f) pluginRegisterIOReadHandler(b,c,d,e,f) #define DEV_register_iowrite_handler(b,c,d,e,f) pluginRegisterIOWriteHandler(b,c,d,e,f) #define DEV_unregister_ioread_handler(b,c,d,e) pluginUnregisterIOReadHandler(b,c,d,e) #define DEV_unregister_iowrite_handler(b,c,d,e) pluginUnregisterIOWriteHandler(b,c,d,e) #define DEV_register_ioread_handler_range(b,c,d,e,f,g) pluginRegisterIOReadHandlerRange(b,c,d,e,f,g) #define DEV_register_iowrite_handler_range(b,c,d,e,f,g) pluginRegisterIOWriteHandlerRange(b,c,d,e,f,g) #define DEV_unregister_ioread_handler_range(b,c,d,e,f) pluginUnregisterIOReadHandlerRange(b,c,d,e,f) #define DEV_unregister_iowrite_handler_range(b,c,d,e,f) pluginUnregisterIOWriteHandlerRange(b,c,d,e,f) #define DEV_register_default_ioread_handler(b,c,d,e) pluginRegisterDefaultIOReadHandler(b,c,d,e) #define DEV_register_default_iowrite_handler(b,c,d,e) pluginRegisterDefaultIOWriteHandler(b,c,d,e) #define DEV_register_irq(b,c) pluginRegisterIRQ(b,c) #define DEV_unregister_irq(b,c) pluginUnregisterIRQ(b,c) #else // When plugins are off, PLUG_load_plugin will call the plugin_init function // directly. #define PLUG_load_plugin(name,type) {lib##name##_LTX_plugin_init(NULL,type,0,NULL);} #define PLUG_load_opt_plugin(name) bx_load_opt_plugin(name) #define PLUG_unload_plugin(name) {lib##name##_LTX_plugin_fini();} #define PLUG_unload_opt_plugin(name) bx_unload_opt_plugin(name,1); #define DEV_register_ioread_handler(b,c,d,e,f) bx_devices.register_io_read_handler(b,c,d,e,f) #define DEV_register_iowrite_handler(b,c,d,e,f) bx_devices.register_io_write_handler(b,c,d,e,f) #define DEV_unregister_ioread_handler(b,c,d,e) bx_devices.unregister_io_read_handler(b,c,d,e) #define DEV_unregister_iowrite_handler(b,c,d,e) bx_devices.unregister_io_write_handler(b,c,d,e) #define DEV_register_ioread_handler_range(b,c,d,e,f,g) bx_devices.register_io_read_handler_range(b,c,d,e,f,g) #define DEV_register_iowrite_handler_range(b,c,d,e,f,g) bx_devices.register_io_write_handler_range(b,c,d,e,f,g) #define DEV_unregister_ioread_handler_range(b,c,d,e,f) bx_devices.unregister_io_read_handler_range(b,c,d,e,f) #define DEV_unregister_iowrite_handler_range(b,c,d,e,f) bx_devices.unregister_io_write_handler_range(b,c,d,e,f) #define DEV_register_default_ioread_handler(b,c,d,e) bx_devices.register_default_io_read_handler(b,c,d,e) #define DEV_register_default_iowrite_handler(b,c,d,e) bx_devices.register_default_io_write_handler(b,c,d,e) #define DEV_register_irq(b,c) bx_devices.register_irq(b,c) #define DEV_unregister_irq(b,c) bx_devices.unregister_irq(b,c) #endif // #if BX_PLUGINS ///////// Common device macros #define DEV_init_devices() {bx_devices.init(BX_MEM(0)); } #define DEV_reset_devices(type) {bx_devices.reset(type); } #define DEV_register_state() {bx_devices.register_state(); } #define DEV_after_restore_state() {bx_devices.after_restore_state(); } #define DEV_register_timer(a,b,c,d,e,f) bx_pc_system.register_timer(a,b,c,d,e,f) #define DEV_mouse_enabled_changed(en) (bx_devices.mouse_enabled_changed(en)) #define DEV_mouse_motion(dx, dy, dz, bs, absxy) (bx_devices.mouse_motion(dx, dy, dz, bs, absxy)) ///////// Removable devices macros #define DEV_optional_key_enq(a) (bx_devices.optional_key_enq(a)) #define DEV_register_removable_keyboard(a,b) (bx_devices.register_removable_keyboard(a,b)) #define DEV_unregister_removable_keyboard(a) (bx_devices.unregister_removable_keyboard(a)) #define DEV_register_default_mouse(a,b,c) (bx_devices.register_default_mouse(a,b,c)) #define DEV_register_removable_mouse(a,b,c) (bx_devices.register_removable_mouse(a,b,c)) #define DEV_unregister_removable_mouse(a) (bx_devices.unregister_removable_mouse(a)) ///////// I/O APIC macros #define DEV_ioapic_present() (bx_devices.pluginIOAPIC != &bx_devices.stubIOAPIC) #define DEV_ioapic_receive_eoi(a) (bx_devices.pluginIOAPIC->receive_eoi(a)) #define DEV_ioapic_set_irq_level(a,b) (bx_devices.pluginIOAPIC->set_irq_level(a,b)) ///////// CMOS macros #define DEV_cmos_get_reg(a) (bx_devices.pluginCmosDevice->get_reg(a)) #define DEV_cmos_set_reg(a,b) (bx_devices.pluginCmosDevice->set_reg(a,b)) #define DEV_cmos_checksum() (bx_devices.pluginCmosDevice->checksum_cmos()) #define DEV_cmos_get_timeval() (bx_devices.pluginCmosDevice->get_timeval()) #define DEV_cmos_present() (bx_devices.pluginCmosDevice != &bx_devices.stubCmos) ///////// keyboard macros #define DEV_kbd_gen_scancode(key) \ (bx_devices.pluginKeyboard->gen_scancode(key)) #define DEV_kbd_paste_bytes(bytes, count) \ (bx_devices.pluginKeyboard->paste_bytes(bytes,count)) ///////// hard drive macros #define DEV_hd_read_handler(a, b, c) \ (bx_devices.pluginHardDrive->virt_read_handler(b, c)) #define DEV_hd_write_handler(a, b, c, d) \ (bx_devices.pluginHardDrive->virt_write_handler(b, c, d)) #define DEV_hd_get_first_cd_handle() \ (bx_devices.pluginHardDrive->get_first_cd_handle()) #define DEV_hd_get_cd_media_status(handle) \ (bx_devices.pluginHardDrive->get_cd_media_status(handle)) #define DEV_hd_set_cd_media_status(handle, status) \ (bx_devices.pluginHardDrive->set_cd_media_status(handle, status)) #define DEV_hd_present() (bx_devices.pluginHardDrive != &bx_devices.stubHardDrive) #define DEV_hd_bmdma_read_sector(a,b,c) bx_devices.pluginHardDrive->bmdma_read_sector(a,b,c) #define DEV_hd_bmdma_write_sector(a,b) bx_devices.pluginHardDrive->bmdma_write_sector(a,b) #define DEV_hd_bmdma_complete(a) bx_devices.pluginHardDrive->bmdma_complete(a) #define DEV_hdimage_init_image(a,b,c) bx_devices.pluginHDImageCtl->init_image(a,b,c) #define DEV_hdimage_init_cdrom(a) bx_devices.pluginHDImageCtl->init_cdrom(a) #define DEV_bulk_io_quantum_requested() (bx_devices.bulkIOQuantumsRequested) #define DEV_bulk_io_quantum_transferred() (bx_devices.bulkIOQuantumsTransferred) #define DEV_bulk_io_host_addr() (bx_devices.bulkIOHostAddr) ///////// FLOPPY macro #define DEV_floppy_set_media_status(drive, status) bx_devices.pluginFloppyDevice->set_media_status(drive, status) ///////// DMA macros #define DEV_dma_register_8bit_channel(channel, dmaRead, dmaWrite, name) \ (bx_devices.pluginDmaDevice->registerDMA8Channel(channel, dmaRead, dmaWrite, name)) #define DEV_dma_register_16bit_channel(channel, dmaRead, dmaWrite, name) \ (bx_devices.pluginDmaDevice->registerDMA16Channel(channel, dmaRead, dmaWrite, name)) #define DEV_dma_unregister_channel(channel) \ (bx_devices.pluginDmaDevice->unregisterDMAChannel(channel)) #define DEV_dma_set_drq(channel, val) \ (bx_devices.pluginDmaDevice->set_DRQ(channel, val)) #define DEV_dma_get_tc() \ (bx_devices.pluginDmaDevice->get_TC()) #define DEV_dma_raise_hlda() \ (bx_devices.pluginDmaDevice->raise_HLDA()) ///////// PIC macros #define DEV_pic_lower_irq(b) (bx_devices.pluginPicDevice->lower_irq(b)) #define DEV_pic_raise_irq(b) (bx_devices.pluginPicDevice->raise_irq(b)) #define DEV_pic_set_mode(a,b) (bx_devices.pluginPicDevice->set_mode(a,b)) #define DEV_pic_iac() (bx_devices.pluginPicDevice->IAC()) ///////// VGA macros #define DEV_vga_mem_read(addr) (bx_devices.pluginVgaDevice->mem_read(addr)) #define DEV_vga_mem_write(addr, val) (bx_devices.pluginVgaDevice->mem_write(addr, val)) #define DEV_vga_redraw_area(left, top, right, bottom) \ (bx_devices.pluginVgaDevice->redraw_area(left, top, right, bottom)) #define DEV_vga_get_snapshot_mode() bx_devices.pluginVgaDevice->get_snapshot_mode() #define DEV_vga_get_text_snapshot(rawsnap, height, width) \ (bx_devices.pluginVgaDevice->get_text_snapshot(rawsnap, height, width)) #define DEV_vga_get_gfx_snapshot(rawsnap, palette, height, width, depth) \ (bx_devices.pluginVgaDevice->get_gfx_snapshot(rawsnap, palette, height, width, depth)) #define DEV_vga_refresh() \ (bx_devices.pluginVgaDevice->trigger_timer(bx_devices.pluginVgaDevice)) #define DEV_vga_set_override(a) (bx_devices.pluginVgaDevice->set_override(a)) ///////// PCI macros #define DEV_register_pci_handlers(a,b,c,d) \ (bx_devices.pluginPciBridge->register_pci_handlers(a,b,c,d)) #define DEV_is_pci_device(name) bx_devices.pluginPciBridge->is_pci_device(name) #define DEV_pci_set_irq(a,b,c) bx_devices.pluginPci2IsaBridge->pci_set_irq(a,b,c) #define DEV_pci_set_base_mem(a,b,c,d,e,f) \ (bx_devices.pluginPciBridge->pci_set_base_mem(a,b,c,d,e,f)) #define DEV_pci_set_base_io(a,b,c,d,e,f,g,h) \ (bx_devices.pluginPciBridge->pci_set_base_io(a,b,c,d,e,f,g,h)) #define DEV_ide_bmdma_present() bx_devices.pluginPciIdeController->bmdma_present() #define DEV_ide_bmdma_set_irq(a) bx_devices.pluginPciIdeController->bmdma_set_irq(a) #define DEV_acpi_generate_smi(a) bx_devices.pluginACPIController->generate_smi(a) ///////// Speaker macros #define DEV_speaker_beep_on(frequency) bx_devices.pluginSpeaker->beep_on(frequency) #define DEV_speaker_beep_off() bx_devices.pluginSpeaker->beep_off() ///////// Memory macros #define DEV_register_memory_handlers(param,rh,wh,b,e) \ bx_devices.mem->registerMemoryHandlers(param,rh,wh,b,e) #define DEV_unregister_memory_handlers(param,b,e) \ bx_devices.mem->unregisterMemoryHandlers(param,b,e) #define DEV_mem_set_memory_type(a,b,c) \ bx_devices.mem->set_memory_type((memory_area_t)a,b,c) ///////// USB device macros #define DEV_usb_init_device(a,b,c,d) (usbdev_type)bx_devices.pluginUsbDevCtl->init_device(a,b,(void**)c,d) #define DEV_usb_send_msg(a,b) bx_devices.pluginUsbDevCtl->usb_send_msg((void*)a,b) ///////// Sound module macro #define DEV_sound_init_module(a,b) \ ((bx_sound_lowlevel_c*)bx_devices.pluginSoundModCtl->init_module(a,b)) #define DEV_soundmod_beep_on(a) bx_devices.pluginSoundModCtl->beep_on(a) #define DEV_soundmod_beep_off() bx_devices.pluginSoundModCtl->beep_off() ///////// Networking module macro #define DEV_net_init_module(a,b,c,d) \ ((eth_pktmover_c*)bx_devices.pluginNetModCtl->init_module(a,(void*)b,(void*)c,d)) ///////// Gameport macro #define DEV_gameport_set_enabled(a) bx_devices.pluginGameport->set_enabled(a) #if BX_HAVE_DLFCN_H #include #endif typedef Bit32u (*ioReadHandler_t)(void *, Bit32u, unsigned); typedef void (*ioWriteHandler_t)(void *, Bit32u, Bit32u, unsigned); extern plugin_t *plugins; typedef struct _device_t { const char *name; plugin_t *plugin; plugintype_t plugtype; class bx_devmodel_c *devmodel; // BBD hack struct _device_t *next; } device_t; extern device_t *devices; void plugin_startup(void); void plugin_load(char *name, char *args, plugintype_t); plugin_t *plugin_unload(plugin_t *plugin); void plugin_init_all(void); void plugin_fini_all(void); /* === Device Stuff === */ typedef void (*deviceInitMem_t)(BX_MEM_C *); typedef void (*deviceInitDev_t)(void); typedef void (*deviceReset_t)(unsigned); BOCHSAPI void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *dev, const char *name); BOCHSAPI void pluginUnregisterDeviceDevmodel(const char *name); BOCHSAPI bx_bool pluginDevicePresent(const char *name); /* === IO port stuff === */ BOCHSAPI extern int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback, unsigned base, const char *name, Bit8u mask); BOCHSAPI extern int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, unsigned base, const char *name, Bit8u mask); BOCHSAPI extern int (*pluginUnregisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback, unsigned base, Bit8u mask); BOCHSAPI extern int (*pluginUnregisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, unsigned base, Bit8u mask); BOCHSAPI extern int (*pluginRegisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback, unsigned base, unsigned end, const char *name, Bit8u mask); BOCHSAPI extern int (*pluginRegisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback, unsigned base, unsigned end, const char *name, Bit8u mask); BOCHSAPI extern int (*pluginUnregisterIOReadHandlerRange)(void *thisPtr, ioReadHandler_t callback, unsigned begin, unsigned end, Bit8u mask); BOCHSAPI extern int (*pluginUnregisterIOWriteHandlerRange)(void *thisPtr, ioWriteHandler_t callback, unsigned begin, unsigned end, Bit8u mask); BOCHSAPI extern int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback, const char *name, Bit8u mask); BOCHSAPI extern int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback, const char *name, Bit8u mask); /* === A20 enable line stuff === */ BOCHSAPI extern unsigned (*pluginGetA20E)(void); BOCHSAPI extern void (*pluginSetA20E)(unsigned val); /* === IRQ stuff === */ BOCHSAPI extern void (*pluginRegisterIRQ)(unsigned irq, const char *name); BOCHSAPI extern void (*pluginUnregisterIRQ)(unsigned irq, const char *name); /* === Floppy stuff ===*/ BOCHSAPI extern unsigned (* pluginFloppyGetMediaStatus)(unsigned drive); BOCHSAPI extern unsigned (* pluginFloppySetMediaStatus)(unsigned drive, unsigned status); /* === VGA stuff === */ BOCHSAPI extern void (* pluginVGARedrawArea)(unsigned x0, unsigned y0, unsigned width, unsigned height); BOCHSAPI extern Bit8u (* pluginVGAMemRead)(Bit32u addr); BOCHSAPI extern void (* pluginVGAMemWrite)(Bit32u addr, Bit8u value); BOCHSAPI extern void (* pluginVGAGetTextSnapshot)(Bit8u **text_snapshot, unsigned *txHeight, unsigned *txWidth); BOCHSAPI extern void (* pluginVGARefresh)(void *); BOCHSAPI extern void (* pluginVGASetUpdateInterval)(unsigned); /* === Timer stuff === */ BOCHSAPI extern int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *), Bit32u useconds, bx_bool continuous, bx_bool active, const char *name); BOCHSAPI extern void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous); BOCHSAPI extern void (*pluginDeactivateTimer)(unsigned id); /* === HRQ stuff === */ BOCHSAPI extern void (*pluginSetHRQ)(unsigned val); BOCHSAPI extern void (*pluginSetHRQHackCallback)(void (*callback)(void)); /* === PCI stuff === */ BOCHSAPI extern bx_bool (*pluginRegisterPCIDevice)(void *this_ptr, Bit32u (*bx_pci_read_handler)(void *, Bit8u, unsigned), void(*bx_pci_write_handler)(void *, Bit8u, Bit32u, unsigned), Bit8u *devfunc, const char *name, const char *descr); BOCHSAPI extern Bit8u (*pluginRd_memType)(Bit32u addr); BOCHSAPI extern Bit8u (*pluginWr_memType)(Bit32u addr); void plugin_abort(void); int bx_load_plugin(const char *name, plugintype_t type); extern void bx_unload_plugin(const char *name, bx_bool devflag); extern void bx_init_plugins(void); extern void bx_reset_plugins(unsigned); extern void bx_unload_plugins(void); extern void bx_unload_core_plugins(void); extern void bx_plugins_register_state(void); extern void bx_plugins_after_restore_state(void); #if !BX_PLUGINS int bx_load_opt_plugin(const char *name); int bx_unload_opt_plugin(const char *name, bx_bool devflag); #endif // every plugin must define these, within the extern"C" block, so that // a non-mangled function symbol is available in the shared library. void plugin_fini(void); int plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]); // still in extern "C" #if BX_PLUGINS && defined(_MSC_VER) #define DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(mod) \ extern "C" __declspec(dllexport) int __cdecl lib##mod##_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]); \ extern "C" __declspec(dllexport) void __cdecl lib##mod##_LTX_plugin_fini(void); #else #define DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(mod) \ int lib##mod##_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]); \ void lib##mod##_LTX_plugin_fini(void); #endif DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(harddrv) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(hdimage) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(keyboard) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(busmouse) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(serial) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(unmapped) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(biosdev) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(cmos) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(dma) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pic) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pit) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(vga) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(svga_cirrus) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(floppy) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(parallel) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci2isa) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci_ide) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pcidev) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(usb_common) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(usb_uhci) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(usb_ohci) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(usb_xhci) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(soundmod) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(sb16) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(es1370) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(netmod) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(ne2k) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pcipnic) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(e1000) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(extfpuirq) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(gameport) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(speaker) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(acpi) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(iodebug) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(ioapic) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(amigaos) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(carbon) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(macintosh) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(nogui) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(rfb) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(sdl) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(svga) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(term) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(win32) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(wx) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(x) DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(user) #ifdef __cplusplus } #endif #endif /* __PLUGIN_H */ bochs-2.6/build/0000755000175000017500000000000012020641473013433 5ustar guillemguillembochs-2.6/build/macos/0000755000175000017500000000000012020641472014534 5ustar guillemguillembochs-2.6/build/macos/macos_defines.h0000644000175000017500000000067012020641472017507 0ustar guillemguillem#define NO_ASSEMBLER #define USE_WITH_CPU_SIM #define PARANOID #define fileno(A) 0 #ifdef __cplusplus #include inline long read(int fd, void *buf, std::size_t nbytes); long read(int fd, void *buf, std::size_t nbytes) {return read(fd, (char*)buf, nbytes);} inline long write(int fd, const void *buf, std::size_t nbytes); long write(int fd, const void *buf, std::size_t nbytes) {return write(fd, (const char*)buf, nbytes);} #endif bochs-2.6/build/macos/CWPro3_project.sit0000644000175000017500000462403212020641472020073 0ustar guillemguillemSIT!(rLau*  bximage DataÜr¹†ÿÿÿÿº&KÔº&L3ÌÙ3Z< bximage.tdmx.imgest1—šðTDATCWIEº&KÔº&Lh½w™å?Á‰•|²Ñx¾YÂéTÞ+ûS(­”k× ‹mÉ>Öå•ç )¿ÎIÞ¶ÊÏËì2:°ë\8•ÝÊõÊ:”¯yÒ—»Nö:`çñØÖ«A~ñE¯³‹÷ñÞk`P½…7Ìóà~¸ð«ãìÌ…ç-Ç/¯³<ÞÀëítKº°ð}]Ù$²É÷uÂL d Éd!·9¼³Žå¤‰Ù)ʇù±lÐi“Ô¼.¯Ø@®u–y±åuæ§5é¼¼Îk’{›ù}~Îòù™Ùù½—¸h“œØ0ߺú®ëûèöžp¿·€;ŸÀ‹,JÀ$JnÉW®@<¬¾l¹\H$ó‰ŽÃ÷æDLJnH$æ¿[{ïèìÐ2þæg²kGºF3ÕɨޕÌÔ3ÍV~¹ öÕÍ·Y¡~ä·Vÿ-߯ÿŽo¯ÔÏ·êàÛÍú_rµµ¨øv¤cø¶X‹íøv‘cùö-Æñí ZŒçÛßh1oß×bbø¦÷Õb{¾£Å|[ªÅŽ|{¸;ñ÷ã›ðÛ[µ˜Ä·Ïh± ß~¦Åäð͢Ů|;^ Þ—ßi1…oçhÑÅ·+´ØoO×b¾½J‹=ùö-ºùöi-öâÛ7µØ;|³V“ûðoÁÚä·Cµà›ðÛ´ØŸoýZÀ·UZȷ˵¸ßž¦ÅA|cíÌ·wiqß>¢Å}ùöE-¦òíÇZðî,Öç´]†ô>Ö'ë’õÈ:d­³–Y‡¬?Öë5Ízgí±æXk¬1ÖkеÄbí°fØ'X/ìì‹ì‡ìƒ¬köRöAö¿Ô÷¤§²ß²¶ØóØëØãØÛØÓØËØÃػساS¿úß?Öñ ]o(-ûŽºÆË\>k¶®œ´ª.?¸IuØ¿XRüÊMh²5ïëð›?2¼:Êä¢jíÈ#—L=v¯-÷áÏv„_¾aS~¦“˶oÐ<4·îNë±õÏËw +åj½+îOôe …r¹Ôµ:*T© ]ýÏê?òHßyb¦õ—sQW¹´)ªÖ£jb°Mw¥«Q¥ZÎFµZ¹j'ögjÙLÁ\›Ðº§VLôåkºÕÐY§õ¯œ»{ÿÀŽÏ(‹n]~ª¾MÕ++ûò¥°©Þ2·¤gXÉF¾‹M™j>ª­ Pß[.Ë:rY}ÊöóèER=_ŒšWjŽL;óº~¡µëOk^e±®¼¡\-ä–d+‰Äøt¾˜™Œ–dµz._Vñã$?&Ý/ä³]C¥l¡‘‹j‰¬RdJµüX%S-ÖtÞyµÂªBy¬o Z^˜+äk¶G¯Œ&ìšëòãlÀ—"—ßä'Ö«ùÒdØÈ/E¶>S‰ì»|(2µšj–ßã—"[.MäíÀNq¿ dάÿ³þCÆÍúÏqúŸõŸúŸõŸ3ô?ë?géÒŠIýOúOq®þ'ýGt¤¤ÿ¦Éd~¹þ'ý§x—þ'ý§øïÃ߇ô?é?Å×ô?é?Å·ô?é?ÅOõ?é?ÊÞ2é?ÊØ<é?ÊÞ2é?Ê´ÄÓj•IÿQkµHúÚ¨EÒTU‹¤ÿ(ÓX’þ£.Ð"é?ª­ÿ¨KµHúºB‹¤ÿ¨«µHúú;-’þ£L“Iú’v™õe:[ÒÔ­Z$ýGÝ©EÒÔ½Z$ýG™—ôeNÒ:ÈüØ Ø{Ø[Ø;X÷¬qÖû"û{뉵ÆZb³'°nY—¬GÖ-{${&{Mî[ìSìsìiìSìIìì³ì£ìì‰ìì¥ì#ìCì¬öÜ?;üøÎ|¾ßï²E·jëU¿×¨øŽ©Þ{Þ¹ýîÎ7¼çþùžù~¼+ïÌ{ò޹fy¯üž¼ïÊ{ó r­ÿSÝýòÞxâ¸D§¾ðüø…7˜è»ùeÇÄÁìÞÕ÷ðN“š·M“~ìï¼v ²¤Ž2yž¨gÌýS•E÷ç%\È›ùîyÍ{òí¹.¯9txrvöÆ C¿ „Ý~:¾:¸TºãQ‰Ä !þŽp?šu@b #Р|F¤š¿amŸ´ã¤ôPÊÿا‰÷›³jüÏ÷$5vÖ›ômúc{‹ãÞ&ܬo¾wÖ}ºí×õÍÙ¾zÎtsêôƒåB´²¿Q«—‹]'G3›ËÕ\Íù­gôdM”‡v¿yê×$ƒÜ@T¯K]¾ãŒÙùBÔ•ÊT*¿9af#_Èu L׫™_Ð7&'£*†¼ŸŸqÿ'ëÛÊhUTúÍþ¾|ÍtîóÆ ²)üÓ!óò¥¿ÝÞ_-ŸeýÑ£ÞüŽ+Ä#–dª¥ß”Cï`J½£–§Uë£Â¯vÏ]×µ¶"›üw\> æG*¢»¯Á=ÿ­’¸çÞJâž»+‰{`ìøÅÞ»«,zGî~@L~U„¯X®v³"R±`GºI‚×­1ïj†yÓ–˜÷ 7½¼k¨ÑåM[š[Þ×nhí=C¥×ޘʭ½%—Qý¶Ã jx[Ý”êm±ÕoZ7Ÿ¼c¨áäMÛšLÞÙn,í=?ÑVioaÓú>òÂCÍ!ojyÓÏ›@ÇÒ_ÔqÅI 8˜ª@Ktg·M·é‡~ÀjåÊ•Å|-» ·¶Ðêž~й­ õ,é W+SQ½ZÞU7Ö¤§-+å2Õœ¥/q{3\Ü+‚ƲR>q×;Œ5¸ÿ¿@RìlF­~ð[>èÝÕO¶ú ý@|ŠEwtbÓZýÀx?èÀÖîèòÞúˆ-—OÇÕ_öÊ·|‰V  #œI~:±ûšré÷ÍϤRé]"N‹N]ò6ÏmùuÃ?yÊ=.ùý=n·Ûz“2›2¿àI½éôð_ž±[=•Ê.ì­¼GïÚ ,íê—?äýñayFo¡VÛ5À=N:§:±Dÿÿã]Õ3Cr×õ±hd]ÿ®î!fùïƒø†bïüÉ=ÎÎþî·‡8ýêι¦^üc‘{œóûªþMÝwèäçýWûhÞã׌Âä˹GG²8}(gü¯:cÝŸž¯ þñü­,g¬1öÅMµêï›ÙïîÁßÔlAÁÿù®rs2ÿE§âÁå=ÚLáú_ïuÕVÄ–_÷®'ˆr~j¸ï?ÏiåÑâiï|ùþá?tª¹GÇ\Ø÷gÿ³÷oøÃ{ô—Çw ð*Èô×½¼Î¾«:ò=&³üÿ»Ç¯ä¿ßã—üÿ¼Ç=DðÛ{¬šþýƒü¿NJÂÖ=› À¯«£I°þE¡Å{ Ù§CÀ=Vü®Bî©æ]WLýñ¿ßcãïèýžw­ïÑ9@!Œ,?¸@?ë ´tžP6§ àÅV¨ú]h°ÞØEÀ=ø›ª"ùwå rÿ*Ñš€ª;³ë …¤Ã‰¦Ü9€à:Jh¯:ùo~÷z-÷Øå‡&ˆ§½óåÿUüÅ=:›¸C~¯ÁÝUÿ¦ÁÝ{ßip÷ÞãwÜ?ßã·Ü=÷èÜ¡ÁÝù®4¸_Ú¿jp÷ÜãwÜ×øŸܽ÷ø½wÇE:hp¿:#ÍøñÏ÷è@Üœäž7Û:YÈí¿ŽZÞ] íß´¼»I¦S€–7ÿ?cvè^?òÇ "étžpupu:qϬû=Á!G˜Î½&ÔwøW“Nç ‡uù¯_¼ÇvàšÜ;ÌùÒ!Ç=³ùV÷{Kò¥cº»,´úNpÚéÿ.òËŠþ=Ü{ßÁ½÷ø]'ÿç{ü¶“ßsμó‚–wç»vrÐò~QhÿJ÷ÜãwDpç5þ'Ü{ßkyw\¤¾Ç¯e&Üàð+ÏA¼&QºûÇK¬ª!Jü·{tÐòøë àã4LwÿZŠÍÝ÷Ø0n³œÝõ[8~Îî‘Üû}åì¿#ÜØÿ“­‚[üâŒÿ‘­òË{üÆ­rZÜÀ­ò_$5éü6ƒä—õÑ9@MÿYw½Ç¿euüò]£^ÿ¦îùû]ÆÆ/ßCîñÛlŒ_Ý£#̦Fà~Zÿ9sçhSñ9^@¼cïíkBª¿#F£”ùÖdÆAúdç§G¤Æ¦;úÜ¥öÿWebíŽ2³àw´úÏýœnë_½ß«>oÿÿëŽNÿyg3¿¨Çëìkb¬¯³Éùç8ãÜíõØw²ýoMžõïw,õŸµÈ™êœ)ìñ•ŠH%®ÙûGOµÿx†Çªã~ð·w”‘äî¼cšÕPf¶³ñëw<îíGÙÿ»‹‘3ÿÉé&¸óŽiD¹ëè¶ÿ¿¾cý»óŽyÒ4ÞuÛçt«æWÍÿïwL3+Ê]ÿßw¼çŽiF¹kç‚zL36Ê];¼cvqð® Þ1Í)wí\ÐWÒ¬‘r×Îï˜f˜”»v.xÇ4¥ÜµsAͧ™+å® j%Ír)wí\P+iFL¹kç‚ZÉïÀ»v.xÇ4Ó¦œÕ¹à󬜼kç‚wÌçó®Þî8?Õßßñ­‡¢ý¿ûŽ´Ûýò;{þ8‡fG±rî_»ÁÆæ†,8ÿM ÷vuí® î:KcVð®ÉÛ³ª>®fmX[ÖŽµgX—¬+ÖcXoÇz,ëq¬Ç³žÀz"ëíYïÀzGÖ;±Þ™õ$Ö»°žÌzWÖ»±žÂº‹õî¬÷`½'ënÖ{±Þ›õ>¬÷e½ëýYÀú@Ö÷a}ëƒYÂú¾¬§²>”õ4Ö‡±>œõ¬d}?Ö÷g}ëé¬f} ëcYÇúxÖ`}ë¬{XÏdÝ˺õ,Ö³YŸÈz빬Obý@ÖóXÏg½€õBÖý¬Of½ˆõëŬOa}*ë%¬Ocý Ö§³~0ë3XŸÉú!¬—²>‹õ2ÖËY¯`½’õ*Ö«YŸÍz 뵬Ïa}.ëu¬Ïc½žõÖYŸÏzëAÖ›Y_ÀúBÖ±¾˜õ%¬Êúa¬/e}뇳¾œõ¬Áú‘¬¯d}ëG±~4ëǰ~,ëDZþÖgýÖOdý$ÖOf}5ë§°~*ë§±¾†õÓY?ƒõ3Y?‹õ³Y?‡õsY_Ëú:Ö׳~ëç³~ë?dýBÖ/býbÖÄú%¬_Êúe¬_Îú¬_ÉúU¬ÿ˜õ«Y¿†õkYÿ ë×±~=ë7°~#ë7±~3ë·°~+ë·±~;ëw°~'ëw±~7ë÷°~/ë?eý>ÖïgýÖÆúƒ¬ÿœõ‡Xÿë³þKÖÅú#¬?Êúc¬ÿšõß°þ[Ögý ÖÇú“¬?ÅúÓ¬?ÃúÖŸeý9ÖŸgýÖ7²þ{Ö_d}ë/±þ2믰þ*믱þÖ_gý Ößdý-Ößf}3ëï°þ.ëï±þ>ë°þ!ë±þ1ëdýÖ?eý3Ö·°¾•õma­à~ÕÁ:ñ¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Áÿ þWð¿‚ÿü¯àÿ+ø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkø_Ãÿþ×ð¿†ÿ5ü¯á ÿkøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÀÿþ7ð¿ÿ üoàÿøßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ‘.׉ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoá ÿ[øßÂÿþ·ð¿…ÿ-üoáÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþGn\'þwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿüïàÿ;øßÁÿþwð¿ƒÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øÉ¿qøßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþ÷ð¿‡ÿ=üïáÿ{øßÃÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþð€ÿüàÿÿø?Àÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ/áÿþ¯àÿ þ¯àÿ þ¯àÿ þ¯àÿ þ¯àÿ þ¯àÿ þ¯àÿ þ¯àÿ þ¯àÿ þ¯àÿ þ¯Äÿ˜-¬xü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_Áÿü_]3 Á—ìC%ÍÊ»:“4á+ÄþžÑMQ©®¸ô%ù\´&šÌÔ#Íè2/µ*ªgjõ‘ôÀt½š‘}c^j$ª¯ÍŒ¢¾L-’ñ^H÷Žf ûdðÂþl5_©Ÿ’LgêÙ©Þ\NÓÓ*ªøôr¹¨IiW–7+H.òÀñœ]ã3ôå«ýÕÈ®í–è>³JõêÌúšÆÅCT!¾Ï­GÅT¦ªñ_¤cghô[9hÏ€™/pÀü™ç•K‘ò©±cOããúúºh"[.i‚t_:Ó¨Eë¢l¹šË—&%ìË»õôj>êÍzOXÚJ¹‘r£”KeJºø¦S£j-¯ãí¹«ó…|=ŠŸn×tߺ¨¤ÉƒfJY%Ià‹«™Ê©Q¶®ymõÕé¾ÕÚrj¹ÎT‹5?$,ögÁ£n(ô— :&¼K;03î†F5äÏÕ»¿]²~4_Ô÷Y^"ýÕ|IM~“,ƒ}ÑxcRÃç^6­LP– wåÄ'+óu½×œLm°\-fTUû¬¶b™[š(ËP'ïÝŸÑm–Lé5a[´ª¯{õˆî»l¨”¯¯ªf&”;>{¤ÒŸ©§Ê›TyEº/9ªSQP穜zjö–êâf…c<V&/ž“)å *ˆA9hz5k_´©¯Q¯—Kk+ò^ãQ«¬¨×j^ýêÁÑÞl=¿É»ÌŒþÔp¾VJ sh÷’…`ÏQ7êW©oŽ«÷»‰:BÆžHozý`!3©h!ù5¢Rcß ïÕ{oßïõ5»¿oÄ^9¥Nµ¨VÔµÏ ½l<js4¨±Áç&Õ?ã¾Ç«5m,×¢UÊÕBNSEô®³›Ì-åFËå‚U&甋j°ƒv4òeðΛ3õFmH­c¥ò×7T¢R®šW¯@È8+¢wªœÏFJ(”‚D÷¹Ä‹à“þ²yÊɼ”æŠZ%{;ž ÛÑðRõl´&Ö›z®ŠØ‡ñËËÓÖŽ3vø„ö-Ðó§š…USª@€çäFÔÐc]å;zúµS3UÙïß{ÕÞŠ¿­z¼úݪÈf<Ƥìú›„íR÷öT&ýåÂŒ"ýçYCˆuo>Ÿ.Ú Ææï7hZ1”ìR±ã­Ðƒ±\PFOSѯV‡#` vx¾¦›>/TBûIg}ùMZ!ºGCSò¶=…‚òž8NþŠlTQkÃCè»Ó Íj9PâqŠ’™êéQ¦*“ºñoX¥úëÊ”&U Å÷ Ú”‘DxÙê‘S»UW’òÈ[dŒÖ>|ÃÏYø¾éütTèÖPÓ÷)E›[±3?d¨Ï¨„Édj¨–ÊW«eÁÌÙk…TêU¾x*rj³ÆP _ªO¬ªZ±b¸ÅQ±2Z®¤¢¢¶ÌÖ%‘/Pêë['TÐI5øó„" ÊõüÄŒŸo>:´>•™uø¾êˆ,DzBäÀT£žÜ\R}a^L·Äï´hmÊ®8M㈈«& Ö×WlT*ªLj.Yh–RÊþÛ†e«Šƒj¾„%D~å˜ZÕ«Óõn¯¢B,†‹öT*«|02ò$r#è+VJã €žMæKë+9‡¤3Ò}©ÌÆhpd¤eýòf6z~#S¨…ǵ»ëôˆHýy•÷çÖ‰C65Ée­Ä$ I22Ë|^´)R;¹¬wÀiqS¦h]Xß8Ò?2´®¯ "k="aDLÉztU—©¢Á™-ªšUU¨Ùªö ´Á)+“™j!ò—>†S’©’1/ùb]fF~6VÅÚlÆZô†pÖžçseâU’ªÂŸ÷ÐJÈPèpußý(2j&ñAÍ&©O‘^ÖÕ*ý}J(”ë§ÈÄœ`_(HQj²ŸÝPU·.mÖ½²ª‡pu©…Ã%“¬šÖÈ}©þ©(»‘r Ûcn­‹èGáÉ¡aXë %Í<=×äÌð-¡¶@Œß/´µþ2åã3ö”¢t¥¾oúËVüÞzW°zPoAJF÷Á5b§GO£CÄš:Ö)Í’ÓÞºom¶Vwz;aq÷ªhò x³Rs›¯ WßmÀ8¿6iLJޠ4žªXY>$qÀT)L_3àMGÊç…Ê?ðè>©çKªûZÃBØ~ßÀtÖ ¾CìáÅAÒS Å~q^Ýa`*5èïéR§ö÷¹ HÕ€¬·ákk‚Þfh¸1™Ï¨GlÎgµã=½j=ƒ*;àÚð&•_”ÆÝsšýC6äî^ÙŸ’šÙnVi²¯M)ƒ"JXPšE¹jF’ñ±´ßS3…¼òë¼ç§6áOôÝ¢‰I)˜ýìr=¥œ-¡#%É‚¯šb»c 6+ìOÔ‡ÃIã ([EÒP *&¯—„…`®¶.~’398¡=æÙëD¥Ê½Q[ĨX^¤¥ó55kî2BÌJkÐ`c¥ô,SÔµ{êu)izÚ J—dŒŠ„íèûH‘Ó{Ój¸f”Æ£Ô*Šðûù‹t“vâxgž¡ÁA;b⃛ïÕ•fèƒ \#EŽ/1 ±…(bþÙÑŽ˜s ë‰ÉHH%@ßR/0JØlƒN’Ráv‡¬ì¯zPÀ‹@d®4ýZ-^ -MÙ<•~#•o^6’ÙÔß‹—¸Ž‡áAÓéFÝ{zqi,zŠA pòesDl.ò­JœØ“ îØŸlÀõ’P¥oG•Û ¾¯— ©E¦Æ4¾ÃL1šÄ#б$nòýXëHL‹¾3¯,4@£éÍd§Ä ó50!X[b²HïhßúºµH>/\ϱ6¦zÜû@eÒ¸ØÖ…‹/JA_‘ÊÔä)ñ1û ÷¸¿o}©(‚gAÓÏ4W2ÖÌXgaÊ/vÅm*A”»Æ÷³Ì)—¥þÄ »Ó×D¸Š94tIiƱô £@‚¾DÃq$)êI_DDÃd{lÖ½Æ6îŒ(¼õ?U–˜§u=ùÆá¬ÕVsò"9pfB%L‚—zLÓÚ}ªY”©Þh½‚§Fí±ÝT ¼Sù ]ü@š( O4>_ Çц@dÇX ”ý3r¨FÓ6PÃJš Ò«³NÃÅþ·¸ì¸‰!\%†×¯hÊŽ¬èe*<ò¾¦â ä%0l2ú•ì+oV•=?)16ÛEÂã\ƒž”Û¤êRKU@|½”Oó „¤FúÝ@€Â¥³ÞW?†Ù9¥”ÍTê Óõó¦âæÞ‘FM­üB†o§£’c¿ÙÛ5Ã娫¬mDö +­¥þ{6›È؈¡ úÔ¼¨4)­¢x²7ާÊ5Ä_Ñg9.i3Q+^sZOE®(n¹­6@¤¤ÄÅé‰ë"#… +Tªäѵ˜iPøè°oé·K׿s¾%6{ ^!‚ú•ßoõNÝ ¸Ä6Ë›»Cë‡uþ*Çôš×'×jñ€ëÍB„{èÌžB>S –‹±Ö‘yuyÕˆýg†‹BIËüKD&·6éETUZåyƒqÁ"7­M‹Rý«5OL*1>ãfÝ«_bJæ05bN’uµªÀø*c»¨ë‰ëÝã×–µµfjØhë—´ŒÏ»ûö, û«ì½¡<€¨ì`¢©å숳ÕA`šøÈèôè/€ 8Äkø@àaùb×é”n/wº\Ô«Wlw±sÂÖ²ÖÕZ7åEQßÚ”MÎ,úXÝ…žû/„~U{iŽñ¢J2³˜WHƒäñY«›9âöQ“I@ ˜­Hdn*kÇuµ¢AUÍ;AS”úê¼fÍ„ýGl¨çsûÕòP¢ÓN ˆÅÄ~5¨éEý·Z-<úm¦õI.=7¸Õ4œ‘ j©Rt ªAN;y¸7½®¸©wô¾GÌòò~`GºSíuJätEi؇îï­7©1 £ñ^©Ïµœ!½Éu¥×˜S«¹ƒö0µ]í"c‰ôµ4à/ÒóìÁ‚ü)OMõx.ŽªÅ“#IÅÅ;’vCšÿÔ-®OɽaÌÀ'aêè#³J›òz&èªÓ{DõRnöoZfÜ\XÄí’äÁ‡¬^_² Â`QE˜§ÆØÍˆä>+W0.n=Κr2J`: Ù eæû²%Y¢qã‡ÚJxkôÐ)ÞFäWu–‹€óÊ¢ÿ×jló*–cú3 »£Ø31V   MváD³›`´¹üIƒ‘hÌû\¦ÕenRc.D0J¦2³§Ö|+|(ð³‚i@  ØóM-n˜¬×ºtFÿ”ùzlë[З–z—5þ¨@EºÝ@(Ìu£K³S¢æ0:|¨Ö;êú¦ a_D¡ÌË"îJÉ““ŽF ¬“¼ S_Ž2vнqÀ‚Ñ÷/Fñ NtI댽º¢¶9€²Iôþ+Ô»Ž•£„Ú÷9+ÞÔ2!óˆŠâN÷+ àêÉ5[f7z®ì]*Îü[äÌ3#…jžº j~p‡ Ëu>æ…#MD”u+~åQÄÌy‘DÅâ\ÁáÝ‘™§Ù­×7¤Æ<m/ÉÖ8”ž³Á`–+Ì;Aý‚v¦$)ohBûœ;eׯu‘›‹@‰ÓÕP‹o@¢6^o0%-ö÷=F$†(Œ–m=¯%ևϧ«Ájcä'ï"¹Ñj‘Z7ªA£O§¢Œz|ô¼R¨È> õßšJ=re; ª«ªÁ¬õš¸É>0?Èd±ï%]ã8ï¨Ô¸Ý8\fö»T¾1çSû‹kæHn:Wõô ø"“8ˆG˜- BT}ÂÛ"©~zË\µ»¥&.”/TÌ],¶¦O‡óGÜp±èìÉMQEãp¥ZAõ`¶;ñ›‰Öj6y/.»¹Ðɾ¸.{j¾ÖM™Í'’¼«?\J|žv‚Ê7yœIVâê!Ò~­m¤ÅÑ}¸w¿·4-ûŽ 3Åq£4ûä|#«³³Íî4kW‰ÃÐMémšµÉ½þ¥ßWÍŒN –ÁÄÞ ¼G9.¾ôàÚÒn°.ÈvPüùT6Äì/¯eMOŠíÑvÔ¯WHˆY i')È~vD¦ódNâs@d)ˆ7DdfÃÛ*DŒý;Û7^V©äòNœmü}½}Q$À<^Q‹.)7šrqÇÊœKøÈƳ· ²/îçgö§Ô7æ®M÷Éåë%%Óú³õíZÈ!ÄÖA+Eáš‹½M9ÐíÓ4vP‘Àì[‰].Q|¿ícN¤0Æ¥×Ù£±øZ¬Ì‚¤‚”S³£Íí.‘ŠL‹OÄb¿`"G­˜GÒÃÒ_.À}+;.›ÐV׉6q4†ì-Pƒe²*{ËÐú¶”V,[¤/> <ì¯iÙΣuõ“^šH ±6šd’³§„ëgý‹Û~æØ¡èÜÇkÉ2,¶®Ád]skëd¥…‡z¥×^úÁDÅ$ôÉ- å ûHköœ8ƒ@œrê.•o*îÏ1ýÈë."©Ïx ‚˜UG J¢ŒùKäWž#@<8™ÚÔ¥ö6QA·çÑ ëÍ52œ‰‹™m ZA€Z¥ÿ²y«—5àÚâ–-4<-H hëÍw¶Zó«ÐO_»å„voÇŸ­’‡5­ bÄ)þ"æ LP›ò+Zv’ 3Ö>ê[1¯×)K伓Zœo=;:>¿\0çj—ÐÅÃ!Oá_gžß•AþCCK -P÷d=Áê’)ÓsT¹6˸°Ñ5£ì,Eh,9è&Ï“›ŒH”Ü´9uéè…¨múf2®p‘ÒV'˧ö º¸walØHxò¹'–bÁC=„j¿E_ûñ£ž¯¾¬°Œh‡Á œ"mK;‡¼¶¨w,¦íHüÝLTlBMÔÊa+G‘˜‹§Æå†˜N©ËV¾J¸Š ~v L–ÚÍìµkT•/tãnÌ øfìCèW,”óŠÍøÆ^‰µÐ0©?Ûó“)½n6Eúí]Z"‹¾Ýë.åIzvoÿ: 87ú [A'îq3Žºf‡¥%7:d¦ÊM#ÖšZµpÄ2r ÁÐÈ¡¶“[l8J ÅJÖµt mHŠPSwEH6+b|m£?ªÄâ¯WŠMxq9%´][S9¯Ï ¶>ÿÈ( œÛ )>ÐÌ\2ÛåqB_X5£ª{‹U›íòöcÍÔä» 7d€Ô{Gí9‘œц±Ìžà#Û1Ìz+çÌ>˜@£¡ºW~jó¯”,ÂúÙ+rÐLÿZ"A¾†¾BvÉûÂÛÃÜx‚Щ õmyV¸WÇz\2¢~±VoLLLÉëîî{´ì’r£ŽOW¥Ñˆl­¾ÒŸŠS5‚,ýÉ>½¸lžxíØµhKŠîYsvh}ÑW~Üì¯0 ò6Å·Á¢ò~øD@0 |¾É´^ǹÁržØ:šÇßå‡ô¸Œicbýå¤ „<&Yÿƒ9·êC¤â”òÇà ¨ínOêÿ™;P­7A;ie0ŒIÖºÎF¸<4,ûÿ"3(¼Üí~5†a„ôèžÄ*Ó»µåYaúhQÕÚVââ:×KÄh­˜¡‘*"¡º‡ê¶ð„û±ƒR/Å–W´R.RZÌÁ–•Én m¦ƒfUÜeª"Œ”M×y9çx)Róû¨dæ–*Øåe¾ eIà›[GW¤€¹yþÆ4GŸft¯ãš²0fgA¼\|ÊúÔÞAÎÎ+c—>slZxYœDT§«°< ºº}ØTšhñ‹*yÉf•ÕÝ6ÑE•øËÞÖ;à $úÔ±¸Z‰+E¾)Àå;¿9¬›”·'qSéAŠ“³æ(¢:)ý²Ajþ𦰣ÜBi† õ>G‡þ•-kÓ•c#Kݨ—H€ì¥‚¡IO) _Ïu§‹¹JØ È2B‹ÈšDú!ð³?§ºAâtíwóçʵGvÄØˆ5¨x¶é{òŒúë—}Êä£óì3z7€çw‹cÆÜ%mcC\æyQ®?S’J‰±å– ½ýÍ…è‘VßZ$QĽ ó÷–\°§†l'ò‡x•ÕCîkEc\ß²Ò]ÕÊ °ù CÖ~¶¨Û¸ÛB%çØ9’œ’Øhî³ÆQ#ð{O|ž»%Ù‹®l:¢AMæ(w-$[Q20Œ}ç~Þóš<º¿Wâ óì)oÀQôW™;k hE*覷Ä0½Dñ>ÏIf|_‹]N#f<RG8,$­5Ùfú© ¬´çDÜÀ·‰ÑfëêIö›îö‡Ÿ¦AÄi¼ˆ9"Ù†u¥dÓÔ‡ŠK̯ãP•ü)9€1»Ví?š©¤VwŠ´sàB"sž‘Íq¨ˆ¹ÖHÎÇLÉ ûÇAn…Ñ’ ~ÜyŒu†J[ús¹²£›À¼#‹µH¼Û^EÌ9ö5îWC;¢ô$##ùCSááGËu—ýC­ÝøÔQ¶{OÉÓ¨Vú«±ƒ¤yyÈSÝ\m˜ öÃÕÊ~̾õn¯û!ñÝÀšø!}±ç@Dûcñ{ƒû×ËK5 ¼X i9;Ô`Jòw„ЫhÚm%ÕoÜ2·WÖ_¶ðÅ®w„q#&|ÇûëÌóÄÉPêQ‡O)„6áÆ•ýd¿Mm“.¶cWnT-õ–‘Á¦+wQ`ý¦¹k%ëo(Ho–ž‡6"2ÍîJ´:¸1äÖ˜ &ƈ?…i¨—zÕœÄWQW¢Àm¿Ù+¡½ vuvËàã_RéÎZ¸“™´Ê¼`<¨ê©´ñ³ @ˆ~xûÞ@özŸ S‰_Ç=¢(þu½r¼®VÂQL¹e&é ®Û,x½9Ãaà¡J¾¸ˆ¦IC<ìât¾¤ÇÜ`Z L×õ;ÎÔ‡°÷‹7”—R<Å€ï€ù€ûĤ*PÍv·rC£0%’¡ß'àAOÀXÞ¸º¿PõÐÿÙddöðFoz¯‰æl:¨C>®°Å«h:¿íëZ6í²¼µÁõ±xWÏì‘V&FÔç‰<{‹0­v‚r$„§¬ny5Üm®:ÕavÈÃ@.)3Ž5¶"yx»w¿ªøð˜%íÜ1³ n‘ààOÅQ6 £•rÁÉ9ÓTÔ›zcgœæ.ìß™æ÷2¥˜-4nÂ(©µÝ3ªmrw÷cDL¸ qA ¬Õ7dº"%ÒÌ­›ê¯1”æ, GbÄÙ-jʰµ3ݹΞ·¨[ÒÕ?+»³YÝ„ƒ>…Õ®“‘YNÆ`|ú†ÑrZqÊðÑ SnÎk-ô#&,ÛÌ ‰×„BǤ™÷ ½bÊwK:v×ôy¤Ì%qEYµÂ÷1K¬g×Ò êŠuÙáÐ<>Ôl1Ø0Ú êTÕÇ©èIÐ{r¬Kžr`Qx‘¢ð0=T i¼˜ÂŽuàxØCó f~é¨\…ø=ZI8n™J€¦`Dè°Ôñ‰Ÿ³JªM‘ß²ZåITBÝ‹B¦Eq¹ùðbåù“üV³YÑ~¼'Ž?ò´®ÌŸÒx©pC‰yá3!¯. §x zÅC{ËÞ {) ûÆÂûÖX} y rÎÌcìõù1Žô¥ŽuQRV°ŸAR”3½Ló¢+„+Cþ ®Lߨ8{Vç³Ú„Ì%þòÜ (­‘­:éòæ/F¥·lMðqø“k¤² Q¬›zÒRøsÊÀµq{â³/·Â@æH}A/VRÇÙŽ°§ Õ!$ŸÃx{r>7$ȵdúrÆãW/P>žF¨ºùT²jk”Ÿ LPž¨aÙ"Býê —#‹w ƒâNÙ÷÷Bµ1Ñj¢í£0g¶c–ßìÁf„¢Ä]]'àrÖ­mI¸^CDð k·¦¾"ålÁ,âSƒÐ¥)®úbØ.p„éÜæc aJânÕ•ý²¦GI¿%",u®.³6h‚ØŸ=ï° •A<·N ƒx—ì™kµYÑ͵zô:èÇþmð ¦Ú o÷K¶2pܺ~=ˆb,rÛþØG6¤û©Øõ“á¦É—‡p{i*¡›TQѺýÖ!õ{Ϙ ¦$åaó)«\ÒI ã¨PљݡrŒ¡½ÐÌþOûD©ŸÒ—¢Ë}ÀQ«¦‰æÝ‹¬UoÚk%2ëDâÌBM‚#Å’ñ,;ø†aÕ)(¦Æ”Cµ§i¥Ñ½ ž,bÒëf–¥Áƒì™@›Óêì mßfÆ-.uY(‡)å '>oü"Qð·ƒòÜ´C¨ÍMJRÙ,bŽ!_4‚&övÇ[SŽ:ÉLHÁwKÓÛåÛ %á®ÈŸ(6[—p¯'Üý=êÅÐeMÐô“®hnpM)fÛc,øa56q÷¤+F×Ã…ÁПTÏå.nÖM¾Àú 8‰ô¬=O²º`¨¬ã ‹o…À¿QÖ›6Œø‰Çy¸J\áÓMNÏÆ&s‰=QD¼Ö°#ï0Ç#:¦¸’NÖ´;Ľb£<º©$>hÆ#A¡È©ÅO¬ ¬Ó;³ÏK—ÄpÁØÔÉÐdbPÀÇc5Ó=KPÝàÆpûH`”Ë Ù‚º ê,ü#ùHBŒv:Äy ™Om \ßî(AFvìiE… ݇‚Ÿ*Ê!Æ\,‹äé¬?nh}h©1­@i¨ÜtH*“‚…¨Ëé¦I9Y)W©Câ,—³i>GÃJâf¿å̶—C°Zs%l’3¯ohTS¨œÛrZ$™ÓôzŒKN}Û×=^ÍæsŸä^dŠHre½*Ö|ÞóÎÅáésÆž°5à„€P8(™Ÿ˜ð°Èïù8"6»âèîq/£¹˜âí"…DÜ<Ã5ã™{}Ì„disçØÔ Pš“Ú\|Æ\Š+ª>½#ˆ5ÖàÃb¨‹ùú“öU|hËŸ­5Æå²´o‹S¨c c‰9ÛSÂ(0û‚@ôI¢p¯ÛÉ{FTòz ÉÅ ‚/„þ·U!~1›3ƒÕhTÓàsñI=ê´rÕÁ™“é Õ%u­Ù¤Û1öÇ|vtÀSB…Á‹E†±zªºr·‰Iɹ2/Pk ß§Ï€Péúcv(Q³¦m‚IˆÃü4qÀšÆ.þn/¬\W1ŒWéúQÍ‹)Xƒ­kسb2ä$ Eçߘå2¹D².pÉŽ<RcâI(37í˜*œœ³¤DògJD-*§«ú Zެh6™Ð²¯fwg0%,èävMÉ‘r^°!„¤üé–üŒ÷r7Çá‰>.õ`‹¤˜Àª~I3jiœ±éJG/4‡JÒ§³TîõQ òš»õ glj7c!ã xúOñ²‘ ¤C8sö˜ð?Ö„.[3eµ¦Wx±Û…’jÞïc61†P0ÙkŽW5ݮ⦮Žq©ÕÃlÅÏ“wVè¡¶ ¡™„FšTñ}u¯”æðEbZsë3{„TØ4¼Å#MÕ{F1¯à= %ê3ÂÜÅÉFhù×o¹­/™Þ¬£ ŸWÒÌS\iñNßÑžöIk:’hlï¨?q1>rígˆ6OIßæt±•˜â’͹¡$ÿÍg“©S’ípŠ#8$Ñ¢Ï;ÙUГÏÒ¦ €dnÞ¨×eŒ™((]$ob.øtZâ‚C×VÂå핱‡>N9„’3ómîpñ1]ÀÁ­#‰ÐaN+I$¡›ý‹8ÙŸn†ÈÅ8?Zé·La5ÀO;CäĦ-;¼jp$˜ž]Èš¨mcêüX"· tG»ÖœCÒ=ÅÚ‚¸ˆdäG¢±°Ä:ép¢«GñyÜ,—ÅL§Ôò'rÒ¦+Øó²$ï G’‰ÚnÊQmšd4±Ekb¡ñf½É9K0ÓEPen!›GŒ\ÚL–J\Á”‹(¨­÷ÔsæX7©ò°U3É=WՓäZCcnù`ƒk©ÍSb)Ÿ_uo.?žÉ¹Ÿ³•H”ÀÌü¤ B¼µÙhê1ngÙ(Lí‰BP8óªPXú|L¬£ª5;!d¸=ã)òJ9þÖÐÌ áôáx£½\Ùâ#Ú{v²{¦éiaT]¤6(Xt¶½¯G“z-"jRÈHêZ? &IH'Ñ|{½—['­Vî|!¦=[y[išv^,:Éöã^þù9õ2ë%É·Vœ³z|fœAÃ^®èÔ:Ïó> Û±w‹Ë!µÎ©i­U»N#H˜yÀM2¸ù{ÛqxŒ× ªŽ {C³Ôà?3§  ½õ,áðœæTÑ\KŠm 1*¶˜`Ì"î÷*O )7*dß$¦ýú[R“†r¥£9šú[¶u'¯hŒyM舡pd’$í¤†S["ÎnÆégÚ-³Môžî”´«ÑÄ ¤¦€¸¥|ijt·Å0Å“â¨ZsŒ25WdjÒÄ‘1[,(¸Uš†Œ¥Ö’ôôgôä›3é²È)T‰QâÍ`]eŒ!B™ |}uŠÌ¿lpϤ‘äD ÇN˜Þ .ë/ùU³Ç®øB;,*ÞŸgQZ©ÇIq éyxáèjû’¹8¤jØÄ×µb^ØÔ¿è›( hj<îø`¢w a.ì&"bÊÂaƒk˜®ûRäD$‡ì-þû`2‰!1ßoˆŠ]èM±¡ó‚’òïÑ»üž›äÕÅlp7´S£“¥ ¨øý¡ÍI|"hÁ«Iπľš m¥Â£j®‰U•Ýî®4!`0^[Ø—³Ý¦þ oÆ™I²º¹pN›po6³§|Jûo€zO¥ ×ø»&2C¬Åµ²<҉݌‚»•¼ö4­”ŧ®Ù9Ð…ÄÌŽ÷Ú¤­8CV¼4­ÒwB"y=zÕ•†MYáx¢$nÉ„[8bÊŠØÔ¶X!â¼$›µ>×C|”¯¹ÉøFÅუq<Õͽ&#ŒV#°—b²` NɳöÁÙÌV6m?¬‹E½R²bœ€ *Z]“.ª¾g -ù&`d¶)SªY/†´ž‰ÅÿØÍK™yQ7¸“µO£r1_ôˆ£S|†FµÅ`( IÂ¾Ô KÔøÔØ,~ð‰—‹¡jAn².´q+žž0: Ÿ¤´¼$ƒ/v“§šp/”>6/“b¥“ÆÊ@ÉJß2+FQ “Ù4Á ²a¤AD©‚‘13“$ó<5ê‡1Õ"7 ÎK5Æ0÷¡æP ¢ˆ„û½="fÛBf&sQ“úGF‰yà‘¯h±Í. oC4cú™ÀÓÄñnT„9ÃÌËã†WlT?“þÆ­–Îz®:†'À»*ÙÓ±k_eZ^z„ðÆ ßI ‰„•ß SÒБm€q|2†d"£Q1µãßü-1Ñ®xéŽ ‡ä9Õ"£”ÉúqÓœ£dëî÷[áã@½–Õ<Žq Iå“ Qƒ–Ê­N ˆÞÙÓûSþ ^†_a;NN)æ¿8~´hÁI1>T6ð¦øÞžGFwY§nu+ko(Öè%#µ®“c›%’kóüuiX²„ž\b1O¯<‹Cš2§²ÆfîôJ2‡*Å£94]Çœ|H÷¢ž‘Ê3%© Ê’óÀ17RË1V¦1!ÑN=*k¦ÞuÛœªÑx•VZCió+|F†‹qig1p@ÿ@6â q)ý¬5ØFÜ´ÒgùÐ?Ý'ÊØÔ:Á+TÎ(jª‡Ò¼GîDùÚáž1ÏB|E±óŒ‰=œÄÚš'‡A”HÖ›(fœÙeN…[ç¥:¶5y\[±±ûÆébÌSE«¡ØÈœ'Ò ±ÉÁ€4EÃ2uŒ˜‡Öz¸xmQH9G£,ÊÔzá½ñ±99!|¢2$W+Î&¬È#ù G㑌þŸÂÛfòn¤ù+óŠ/ óú©Ë\¢‘g/4rTuJý¥IÐìX’Š%Ù#™qA«þ§ÃT-P#1‚'&®’Œ³:¦Þjà<é ùo[FªmÕ|ùN‚C0Ma“0Ÿzë3l4 xž¢™»O+V78UgNËþkRÌê‰a8Üc §7ØÎÕ†%2wgÓÕº4M̦ü@sú¨:.Ô~ÖÇB‹ÞCpÔ›¬¼úd|n?\§ßm~¹ò4_ä—ãíà~u?¶>¤÷ SÿHئûFö &úJX‚½±˜·¶•˜ƒÎŽ«£0‹ùgÑ%lôðVºëbjrbPÿO¡2É*¯Ùá(Àó·´|¬Hì…P•ô$̈y”$X£ÖTôqñØsÉ‹¥þ£“K™›< #ÑxX‡Â!!&ÿæêNA`”=Ýž¡4qÌ™ëû·¿möÔz˜³Y6`”mòñÛñޱÃM­¹‰Ù÷—-/‹=nusàÌxüçZî•80à}Ýv€šß$u*6˜v“Y¦£—AÛøH ¥#ó­üçc‹YÒâëN®5è*lÿIn?jVf*šqÝŒh¯Žhx !uzqQêD´Ž©»ä¸KsG˜“‚…%Eœ<7‡_–fÎió­,;'-•’;ämaÊ@@@Ëå®Ç3œýã×´2瘛Q| *id=r}‡Ã½Œ|‡±¢„NÂÅ'cð‡þl\°K†jÌàQ™±UGBñD™–ÀX 9/ ÍÅÑs¸* %ßQeJȈÆdš÷& \VrÑ“4±=%*&—â¸Etðb4IqŸŸÓžÞvi°A 0‰Ÿ âœùáQâ“À™|]°ÅG_iØËq€Á4è%y!¿ê·Û[=òŸy—¤`¼t¬Êpvº,ɺ=qêÞý)·_£y+×Zúch:£ãìÕä*¸d£ ѽ`§3^½²™+ZOè–Š’f‰ùx}Òš¾'o¤ÙŒôS$›Ì”.Êlõ°¸UìöTŸé•"ã£ä– Ú—U°5ؘ7-Ÿí§ÌOa ÅI<Ìé!P@<âû«¢Zšgãåˆ6ËÐÑkë•>ÇØËc %r=ø zûoâo‹ÿ‚ !»N1×ÀðÔ æMAV¹È“¯Í¸!qýfïÿ¥ªEôaƒ©‘Í™ úfŸ3/E`<›µxrš9U0Úäñ¶Ð`šuö^²ã¥Ä“d$ô6°KdÛÔÂ_Ùœ1êmç*We‘L½LøxT0œ³•{Z^Í\þ¤æôq¤ÉNjÆfsƒ‚¬hÔ;¯Ø(Á ÛSŒÌ˜lĘ4¨<×ûã¶'Õ)^ØÈû tïØ1жñ{èïȽ#&bbÎ*É¿KúÜXHNþnõ WQcfйîÇjæX£Ÿ¡ž]CŸ¯]š²'?¼ØRãÚ3{^©E:Œ®•f\Áb¥ç÷J‚->"cˆS­`”âëiPÖ½ÙìÆ®(6ýƒÕR+ÂÓ?®á3”ÝS0>ekDwÊk¦ó,n¨©¤Û})­i‚ó ?yþ ~þd†wÐ6Y6 ú5Ãä²R˜&ïÛÆÎt5Å€L†—xœd‹Å*Ì€%ÆÖ¬:Û;‰æÀ„8—gŠvŠ »kTÉbt­éCì•g++—qXÈ$otGH8£zçlìÖˆsÐüc­…³š%Ïôc%`Æô(˜41ÍskãhQo Sod/¨Þ&¶Ù®skA6 ª[]Y ²GØl kK?èð)!§†ãü0ÅÑ" \3ÄÄ‹·Kè§ýx’b’BÆý¬Ô01ë.›í#æSÒ­öñŒüy­¸!™ÆŸd7hMì§o Œ¶§.6¥“eÉè&·îÐÿâ󨟘¿05Ÿl0c¶I+hÅ&IüySÊ"è9ãC²ûä/µºøÆÜvqö½ëƒ›2þW¹l-¤Þ¨!©.¨—OÍKÂ-^¸“™hjX'÷›vžçÂ…!øjcr±]…«ÈL´ÒD[ãRììS9Ú= ¤™r÷«È·måÁ= ÄNYùËlD¸ã‚¸<¾`önª0q.<µ¿âÿÑ8ˆ{jÈæÈn³PYôÐõÏ#!ÓuÂa;ï2(BU¾mÃ!…Ì–}?ª£n{Ó£ÏÞà¡e"ùÁ.æV­<²"¨!æ{òj,º?Ö0P éSû¥½ÕaôLºB±ÄIßp2;ØûHN—ÑëŠùŸ3ÎCÇN1PŸJõö4cð¾.Þ^Eðj[ò¢¶ø4ï’=›2J?U¦ET¦@JŸ– æ¾Ú"‹é‹9ãDL9~[œŒ+úHXl€0FÍI$®3%ኟzš†Ã(7¨@Òèyââ?FJÇ]¤áœÒhMÕͰ£80P®fsŠ;Ð2Ý M:Ž€€ß('A O`¯/ôÎX×yòÄ ¯qdX‰M†ðNF+2Ñ™K (Ј´ GÆ ‘Ëh·­}±î…M™(¢}W3ƒÃ1mÓÖi›òEýíAWŠÏµS#«›u\Ζª? —‡`_¼è€b¸«åÄC„VCÏ‹ªñ ü´5¤’6¥!5¶¬¿Öd_(Ù²ûUëÿ9p˜6Úáz³Š Ž3Ô0Ûõ •Ùæõ3$;±,Qc$½WOÀwòqzN¢I­Ö~Óâµêil¯Ô o5¾ðü•bLŠceƒ°ql™·©ÐmF¼×ã—¬­ *ãž3IÇ,öÒ‹J!»}¹%ô§y®Ó`€1õå–¢,W„…1;RZ†õJGO±zø“JífFÐ<Ém L÷A+ž®Ù{ш“€uËúJð¶º÷»€Ã0¾è‚š»q&Ä1íÐ ïJƒ|éuP¸£wY£‡½àê[Ž4èØý¡àl5Â35@NöUažÔ8]BƒÁn”žãœŸ—Ä対"—õºIsÂ!Õ7> ohìFIÕ=è=J?*ÙþÊÕÃS _˜ô%K'Œ£¼9 —Ih%ƒÉägJAóôm–P@™ŒÒ9¿d7þ(1Õç=ÄJ¼æ.DàÖ¹n6$„# $fZÌ¡ÙJ%šÝ-‚µF§Ï»ô,ÅÁу’}fhüõƒUÞyêÉKTd¹Ü\­û5)uxâE+wóáýÆñ”Îo#ccÔÛB^mÛÜboÑÀY2˜'s30?TÎÑÏÁ/JÝ(öOyâ(•eSÛõ†¸»ÛÖ4ÇD û%ûÂH;æ_:1*}0oÈLpBèq1)ê-j‰ÑýBžH+NÅŸl f²¡1U¬—'â4!pˆ“Gò| Å|©åm[ó‚0ëP„Ý” yꦎ›+ʱ̌úΆ;1¶o¡«Ì~ùÓ™ÖZC¨Ùàe±ÚÓ¼R/±¸l2N:z}ÒÜlYݶ÷Yu²óŠœn唿+ô›®¸fú<¥é™¬ÍÛ7çjiŸÖŒø”R’?`wy…‡äl{‚›#jKÜ„GÝ´óÍnXü%Ú´»=xÒ³C?Œ #Çù&¡2ÕÖ´<õùv³dï ËãÁŠÝwdÏ_—ñà jÔcâIÒ¤bڌҊù­?Õ\læÆD´­)ÆPæ‰8Å^+àüÎôŠì¢ ß·ø7›jŽñØt5kc¶âž̈±-Eñ°=ÕñrùRNÜâ0{…c“/èÉÖÂá6J Ãì϶Ðù¨œÆa6NZë£[9MŒ0Ê(î3;œ¦Û+ž<W´-@ è’®ØL¬é.ˆƒrÓÀqfòV,‰~v(êØ¼žd/¦§ÅÁÎgRCŒ•n–"ʵ%OÒ'óØsî¿èʤTŒèÙhM è3"PHN˜ï0Ù 8•>ÖynX8ðÛ4À„ ðLÉb)ãÊ~cÇÀ®ÙÚjŸïóªe1œÙ NÃF½×w$twÇøPƒÅ¼٤îªQ…l.èÅ!ï(Dy°¥ä€½5ÔR$-6ËvÌîñqDq*Ìw2Í{ŒKÔ§Ù¢6g*žß²s´Í’*f„g;‰'cæL3dÁ‘(^Ñw ŽúÃß±*$7Iƒ@/“mƨÍÚAöø´4þ$ ^Ô4ä±ùÇ·£ôâ(-Eêlh°›ž:ý©s…ODÿóбkŽ J}¦¾¸l+LÀ˜'£ÃâŸzÓ&e¨Ã K÷Oòz ÍR6j`›«ÌG}®Œ¬ÍÅ<ˆöÐPþŽx@¬¬¶7CÂëÉùÂZ3ç´½Hª“¨ÒbÁžøUÒtÄöãñxàò¹uÅÐpV滑…Ïì 6 Höõ­èÖt#©[É.L1^î  (Â3)@‘íš/”:ˆ6û¢ûÂkÔÇ¡ iÿA;ž^þÕLdñfEÐ~£ŒžÜ°”O?Ó26ªãíR² ÷0 v2b¹/ú«ÖöY$ß5±ê' 1þ8âד®cqõx“Ä/ï3*j¿­vcTìkó­v!±ÉIþÃRÚ[Ô‡Ýæ¢2›`N­øQY‡ô—q?Ml&Š®èµ‚¹9Jç{1ÏÆœèŸš©É $~®‹¡ Èt5sÒ°¹21¯h h1‚ÏY&i&œªºŠãðÐùŸ­–±MÞ·™~’ }çÁ·‚*¹îàw…ÙÏñ>;~~Ä”rÙ;c¯pÕ}S0·bbÉ8â:L‹cØ1Ÿî3ä¥b‘ö\ïbky~<“u6µéb”‘ÖkŽ9ÔàWL&GÇ¡6džØzT°Yd;b¡ ²>;&òÍ?š•H,êãň,lßÓÌZÎÄ,.ª§¥»•<Œž…1´#åæ<õ d ÖØ Å?™i+>höj0ÀRÊ=dñ+GãX&ÿõfvA’á£5H2¾í¹QÉ“w‘½"aá‚ͯ%l /žÃ?d¿b‘èifž”Ó2µÒ°½©î¥áØ‚Š®½±1ý´„¸ çMÔÔŸ`±\®‘qúÍ^ YÑÓܼ1+ºÒÀ‡2tn,´o¨/£q'd>§,ƒ:ë%Vs,â4ëìh­ES¬§d1ç¨;Õ¶«%*ŠÝ”±<<µ«ûJsª¼â›pKÏ´qègÜ0†HÄœz ððÍvÈPı³â¯Ç÷±¯²>SgÚ5Nâ’Rù>±c$ßS4P '‰ þŸm”ÊÆt;lg(œ2#3ÌõP|µÈ*þû¼XD—6žÔ#‰Ìù—¸4̹¯¤Ç!…˜³ß2Ñä4—yü;ôúLTÓMJ¬C)Še±m¸X A2îã¼Ò±yG¥/oI\‚';­ÃÂÂ+ÚS Å6û0+3í‚“ý´ÙoØÎYvõ¯ÒG±ÛÌ^ÁÖj.·÷Íqîż0ùáï±Í%/}›Û ‰EW óe’IŽÅ!#Œºå£>ÒóXÍyZÇÃg…aœR½óŸ”³žŠéÑ>CÓ탒š§[Ôº¤@sºÃL-—8Ãjýx*X1ÔeA¿L™_‚î!›(î4 µ–g«‰ût/"7ÕØ éûXdMò„V6}=ƒ—y61É^g4{“?-žˆ4Õ2z†’MÌ¡ºÆl¬µÓÒR`ã°qMªÄù›¹p0Nâ,¦îþÙÑH=29ŠÝ̉9”Ó¦¦šY¾ÅüECëí­òdqÙfÂ<{vLQ*=òQ¤%lRTǾÙÛ¦LvhYýHý?œ’!r’õ?Ë v¨©מ5êëìšg;צþ$¢¾6°Mè†9‹Ø·-¡sqq±À%q;¼w-Y¾5(¹YÊlÊ1pä–þÔs=³Ìûà‰æÐt5àƒ¿ÊâQ9²V´-5Ñؑ06º'Ü. £q#>%24ïçK[¦Æv®_Òi%*@]«;%fuÈGI›ˆjý“âÄÔ! 'cÅ™t"V¸ÏÃtÎÀvÏlÚ뢲"•—Æ›‡ õû˜Ãÿò +Äô‹ “D2õò0Õ¦Ìñ²É¼q*^w">¡<[ڇݜ[O†q$øJi7÷$ˇÄóP{©Ìx«Û!æGfïpgæE׬Z =îSÏ&meÅIJŠKP?ɸ¡¿iÍ;Á‹×ª¼!cÀ;„¹ü²¥4©²%­7ª0ziphG×Á~­Öüs6ƒ=â\rêðSWIiz…¿¥Câtú—>éli}6eºtžiÜ<‚îmâO ‚Qô­‡9¼×ö+Cð/¼ÇÅx«UŠöò|£-† ¡á·b5–$S!·ºî€þ9afÌþ„½Pùz#ccª'¶;™Gô¸Ñe¦¾R‘§Í•]ì­¡%²Q­ †k¡ÌþµÖiz ¥P‘Éù1Qß^§ÿ ~³x³ÎõO¸okߦE¶Ô¬ kËÚ±ö¬ë’uÅz ëíXe=ŽõxÖXOd½=ëXïÈz'Ö;³žÄzÖ“YïÊz7ÖSXw±Þõ¬÷dÁGd½ë½YïÃz_Öû±ÞŸõ¬d}Ö±>˜õ!¬ïËz*ëCYOc}ëÃYÁúHÖ÷c}ÖG±žÎúhÖǰ>–õq¬gýÖ'°žÁº‡õLÖ½¬1-¬g±†@Ö'²žÃz.ë“X?õ<ÖóY/`½u?ë“Y/bÔY/f} ëSY/aÑ1dý Ö§³~0ë3XŸÉú!¬—²>‹õ2ÖËY¯`½’5Bžd½šõ٬װ^ËúÖç²^Çz¢¬×³ÞÀ#$Éú|Öd uZÖðšÉúÖ²¾ˆõŬ/aýPÖc})ëËX?œõ嬯`ýÖd}%ë«X?Šõ£Y?†õcY?Žõ°~<ë'°~"ë'±~2ë«Y?…õSY?õ5¬ŸÎú¬ŸÉúY¬ŸÍú9¬ŸËúZÖ×±¾žõóX?Ÿõ Xÿ!ë²~ë³þ#Ö/aýRÖ/cýrÖ¯`ýJÖ¯býǬ_Íú5¬_ËúO¤‡+5eâõ–'æ-Ë×vˆ…Nÿ)ÉŒp–õÈpXE¡ß–µÌB9%dm€9ÎVFÙne©¿²$áyùŒ4gœ°Å<.Ó[·Y­à;„áp£9RÖguÎ+ÆÆ’ƒÃckNÕ8škf*fÐêÙ™†Q=·êÍÖO$,‘γL²¥`½“¸ø×| ñýþ.òNˆ ¸8—ß$1¤ËÏUÆÏ‡7÷ÒäÍýªQñù ³ã~u±ªÕ_™®l6Þª¨×?*èP¼¨8U å±V;xéoÙ6áæ7÷n+2Üàd¯Cœò‰‰ÌxM&øC£3,/–s2]1¡,+Ð@¬¢õ› ?ä%Œ€êäà N–íG¸öØØöþÙ­þ€[_?5\½àÙá;ŠÔ <&dYèJ¨…yÍ ÆÑÓ`ÏE)ZÒ7Ü)i¯Ær¶•¬&‚7ƒ6Ak¶`ΤgzRóx¾ûOèýŠù¯˜(f”¸t³¼<Ë4µDªs{S6SU;}"——ÿ&[âí?Lõ¸7Ú©(Š]ý–EÇÍÇBÈ`¾0Þè¶’dªeÛðnßµ·‚] q—wª8Î[ª»Ô¤£Ô˜rc *¢Z¬ÖŠÎŸ6OGˆ5¡ÒKãägzuC‡›íý±«#è:7«¼˜ cJ·ÀsÁc‰¦«ž•ï϶JD¯qßðf\ÌÿbÉš»{¯•6^lLè"{[ÓA•ùÛt/¶ÕÙlôÅ‚« `Ëdgrû†铼mÆîe°®‰t²¥c•¬œƒšþòê©uæ¯+ð€§N¨‡À‘ªí“Ïñ {&ó‡Y?6Xyøµ‰ù[mC±`ïp÷é 54¼L.€ùÅüƒj6b¡;eîþ(©G[±[sDSÿDÖËÎ5Ëíä'YkVfÊ[Ö,?ÇÕÔõyŸ%á9ÜEög=2[Ô\žæA«SÛ°B@Ö½ÔN±à^j˜Q€¥…³>¬JÃxFGh‰LoöPlÚ0÷@ ~@} k—r_þÌ^/ö嬰FM„7¬,§»=…#‹Îû—”ßóÜÖGÄ¡ÙiÐoíË­ í3’šÐU¡Ñ8×ràÊS½WAï•VUÌ;Âú™+X'Âå®k]Eš‹o‘¼àN·"Áu0äÒÀÒ_Ç—ßN‡õ¯MÖuX²w´WËþ¡þÑÃvµRVM@KôÅH½Py!ìî°oGâ='¾ý¨Ä~¾>8±¿Ösºß˜8€ï{°O¾wó}/¾ïÍ÷}ø¾/ëýØ·?ß`} ëû°>ˆõÁ‰k=þĎľJ°ÆcMî¤e©Ä~aÇn­]aǔ֎ÝÃŽ®ÖŽ=ÂŽÝ[;ö ;öhíè;ölíØ+ìèníØ;ìØ«µcŸ°cïÖŽ}ÃŽ}Z;ö ;ömíØ?ìØ¯µã€°cÿÖŽÃŽZ;îvØÚqPØqŸÖŽƒÃŽƒØ¡´L^ü¦^&x_}x·äè±’â'K¦lØë·kñá?¶ñ¬_`—çÿfõçéëÖ­]·²KŽœîòDWÞ¢oŠòõv!ö Bò”Záw¸Pý(žŸï‚6U¯«ÜªmKŸ1”[Ù5®ñ#áüœš=jS×Ò%Këê>úèîg-]ú¬îå]K—®ì^ºò˜¥]Ùq¹·–gºäXî~FbþûqçüŸw^Ú¾3ï™ïÌ suç[tÆËž½Ë€ŸÜ/¾:ný/k¿,Òý?So€ÚÔÇ.J–»fÊ®Ír¬v×Ë]aÎÓîL—D•™®œfýëöªè.Wµ 6è•íM',J{2Ew]6³î)⦮‰Ü’®Ó§rgv%¢é<ïÂö‘ÞEÛ~¾Þe¢½Keµ‚wù©ÎxéDNZwÜGA“û~bûÖuÓ¶³{aß?Ú¾ºWÄ{ñLË7Þ+Ÿ‰þ$ԟ³>‘jbœþê.?ÖÖí…<±îúTÔe‘ì.ÛÊ¡.–CÔzº‹ò .·±x¦î¨ˆiKŽY~”VGu¥Ž"‹#=ʪäð%+V¨Nø•2ÈûŒoÕ‰Ù³ýž|Ÿ\¿¬žñV?Ò×Ù[{éùáÞ†½Gu'>rWš:â}¬öþÀöâ1ò™;pæ÷þ#UŸc>ÂÞÙû=ÛË'kÕÒNôâïÚÞŸ÷íøv¼ÃD¾ñ®cùÆ÷(ùÆwËõÊ÷ÍwܹU¯æ{‹YÊÌÃz’þcüðU1ï¡-»w^qQGb÷×4{ÝE™ÄiÛôŽàY:àŠŽÄê%z¶ì>ïŠ5Ûìtñå³^|þìwy§×lyá~Ó[.}úôE—'*[_|÷tû½6n™—H>í¡óN¸SÆ€êô³][ßöíæÇÎj”=¿›èÝ6ûM;»½矦÷î·÷¾Rw¿Rw¿Rw¿Rwz¾|ÅÓ—ŒOemZ­McPý§t£1Bî7684<ζëbŠÕLúÖ¥ÿý|Û]ÿ1|´Ô b@·Öˇíâ©^X#¹ç÷Ò“¾®ÒžsHmQÜ“\TÖW®cÖã‘ìc]×Þ×Ç>ÖǼö¾ÓØÇz:£}׳Úw]C?8éýॄ©°îr >Ð€†àG~Ö×¥þÑêíè‹ÊëéW=~ºzüj›2‘ 6è¢]'Ûï•ë„ý|_Þnþ/ÞïS¿ß+¿Ýý¿ZÏÞ},3{ß‹?!ãÔåûYo.­g?þÍ2L]»[}ö…'myZâj¥\z”ñ¢Ù{¶þôápÎ;tÎe:ça:ç¬p 7ÄçÀž¥n{ùÝO_«;¶Þ{F ü¢Øk‰)æëÇ‚AUž=ÕèBç¬Ø{~,\ýðýd?Mû0”ìû²ï[™¸Þy zÉ—l߃HÐ*ËÓÞ}ø!µ#$ v•Êõ®LI8¼YZô¦®ñ¨¾YîCrÚµRË©‹%4qYª—SU+ÇéÿGí>¬õwÞ5{{¨÷Ÿ^´e³øè¹OŸÞòÑ#§·ÜzÌô–í'L¿ø`Ê@Ó¥¼]Ý1…õƒ‡ßsm“}¦g+Vl.¸¹¹ç@=ûŒ%öXqöì¬ö<ßÎà^Ö%k¨uŽêÙ–X|±¨}… u³ß‡½üóýLžsˆÎ¹T’ÚâÄÈr¤FXxÒQªGܱk›ÞäÒÄ­â²bqøvs¢ç|±Û>ÿ8½õž‡§·F_Þú÷4ïüÀÙÙ;çjîŒo¯8h~ÅúØ[U C½LT ôÅ–(• †#á´ù|>§¶YŸû¶yà@úëüÈvŸËý}I›ßػֵïbÎf/xûØ÷žß¾Ç7è‘8aKT'Ú¤‰:¯¹ [«šsÇc=de>ç=i +¦Ô3.1å…*LD?‚Ã_ɰg¤=ûœõ£wuÌÞ ë^½eZýèÙ¡±])¹RU$½hP×Ïÿ䣽¨Xl|qg/zV³Awºü­-½¨îEhõ–ÇK¾|v·úQzU¹î}c7Ü)íJ\-½¤÷E‰½uî4}[¯o“µ_±©ò÷‰÷à÷¢ý}§­ý­^‰Þrœ¸¼½ ½åmzÿ¡ÞBÓ OôÞrI‰Î"ZTì%¬».¾Ñ‹”µ –é¾íºŸÖîÓÛ=&ëì1kÚ=fó/‰¦[ûÁ´žV?@=×:Œ“…ô%+®ð•9 0ñ´ {ÚEçÏ?Ãê[x>ÕôçÏoi‰/®xK«Ôtÿ°l×ÖO>0­;ÑÖKx—ɶ<ÚÞ‡> Å6õ'ê†CõHG=;y=¶”þÕš ëíÀvýLk×äŒvíõµk/kF¬½Üë‘{ÏxóíZêRÈV=æ«vóT‡¬½ÌˆçŸ‘Ô|~5QËÓ¯‘ÁQLiß§mßÍöÔVõ8¤vXWFc@/ËÍtI¬×–tuõV#wI0š}È.±)ädvçë;MÏï>½T–ÀŸî•¥x¢îþ)»{ò¯Èük°e¯àÝ8)ßí“vÆE‰UŠ7•³Y {kßßµÏFîʺÀ̰N·Ѽ$ÆIçbbøbû o™ té:=~VÎÚÿñö½FªbmÐvhÛfÓ^‰/r6FešéöÏ?³Ë‚Ñ@9ÅÂÐ axT7JOERÈöÏwÎé™ýf“».Îyž8çmGNoÍ~uÚ´–Ü“ÈÌJ[œ¡>wœé¥m¾á0´™Ø…‘©»°¢%]pzÐÍÐ3×¶9üŸîÜ>/¯¹ëÓNÜ–èYñ’ÙYë™—Îhñ–yß[¼eß/,–&ôQ»+Þk,ZÞØç\–è9á#³³vç%o[}”ô_Ñ+åîϤ²õ§-ÞzÝ÷Û]È—ß½ïôÖë:§·œ=o½ï;{ú6Ý·u6ÏÖ„Ó&ïðÜþ~íý©ç×lÿ6ÕåP¿§š‹t2èMçiއ¥ÞÐïO™––{=ûk7=šI0™ñÙ_3Ë?¬ÝëÉHY7&M¬d5Ôuìc¼´½ï ¾¡¼ïÍþxMûÞÏâlîxeûì×°ýïõm&y3ß ²ªùío™OÐT¬?àÞ*Ç=Ð'UÌ'¸Ÿª°=Pµ™QÅϾ n¹òüøA ™[Ð'k=®€¢O=ZÕ¤ëù܃"‚5Ö+1%µMG‡4µÖÃ\j=¢»{Ù²E§/=Zäñ_æ^‚>f÷Z1Sè:±kù²e²¥ýÖÿ1Únt}Ó WdJì œßÞen×f 4~±cvožZ$_S<›~@Þí¯ììî.ÝþøCr‹¥ûÇÛüeØ¿Fø5è'¤ý ÿ“µÞîGf¦rìRü·íÑ>ëñú?IgýE8ksYÒ>ñøC „±ØãYOÐÿÝuÖ‡vœ…ò:þ%Ý­Ó„Ë9󉯏8óϽ–Leê]µ)ç°¹]–n&ÅšÜqÎ.É'[ü÷$ý÷:L„äÞbc/{ŸLÝÿ™í…_aÚŸ}”–c)·Ú:¤«¢Dã>¤vðQVD’NÀB9¤Y2‡tÕ*u­K™îO‚x^>`÷:bùÑûôÍì} {ßo{êÖÞ®¿¹}ªþÓ›ó>Û{ØXÓ/ö4ÎüÓ°~1øæÓÞkØ çäë»ÇäÃ\iïÓñ±÷=¶7qæê\0Ø]P7©ŽwN™Î{†þï£óà+týÏÚMòãµ{ÍlÎ}¦þÓ—ö®¹š–*NÕŸÎyuüÎÿ]ÇËvÖñ³©ãwx­J×ïö8ýí¶7¾Ó²•]‡Ô([$jc†ãóž£ ì/àÜçêÿn:÷míú˜[°0Âu­¶¿Wb$î]×Òßú‹ó8Í ß0¿ ýy]:ë-qïÞTV±bePËØOÞÅ|Þõèôoöó¨¬ö|;(Ýü˜+e™‚ò–UE ŠÀñA³Õ¦¬ëôr8^¤NÞj‘†«ò$´ø†íÚ…kÒõ®É¿göÖ  ܲÍôwñO±P•ä¬ÄõÙ7E]lúuÚcgO›ÿÇnIEö×=ÇÕËWÞ™X¼òºÄsìÐ ÔŠË^8«³Ç¬¸+a>…­gPç|Pº+ôƒãnÔ;¬­]ÝÑ9zb¢ÿh­ûoÔÿŸ%v?|{g¢{ûÓÝ7ŠfvPs½¯¯•ö þÉŽÎÕ/îè6£Ë¥r5ឥipÙ6ý2Ío˜õ‡É¾eë;nÙúÈ#•9nç·¶ÞËïm/‚|ßûv|¿üëò›¼¯å5ik~ò>݉êŽwÃ{ñÜOÊûU×¶Ë]s÷‘·zAǯj ZÌŒxÿå ?9}Þ½×NŸwcë=æ(€óXUû±àcµáX §wÖ³QM¶õœV=‹–£¥¯ôkßNh-]úvˆöS/±ú~†¾¯Ó÷¦›ãÎêÎZw®´ç öô·÷Ì9açž Úsä£çì =ÝîÙW{jèÒîºeëÃÿ^·mo&¿·tù¾²¥iÖ­ô¬wwšw°Øò¦¥·l9ðè'oyIçÞ[<â–-Ów|û¿ê”ž•égð\jKì³>¥â1Û[H×ZqÐâ-9ý_!] ÷ ®•ßvz¦uvÒšë½âsB¯Éoð›÷k¿Å–ú™~~¢õNQ¿VA»Ò/_qPç6÷¥€†´«9ˆehWˆxiiNÙïGÏaöHJCúFø|£¿<{è÷Èšµ¥yœA­&ëXô9eí‡gd½êúÿ„ö·«ù†Ží*~{¡þ¿oÈn,>Å·ëÿ‡¹+õ››ùF­æûÜõÜÛ÷A£QmO£ŠßúËÏ%kuÐ]Tìå¾ì…Þ¢â÷æ¾ì…¶¢bß÷Æ·—èÛÞ Zèdñ2 5ß.åÐ] 5÷¸†}ÐVÔ¥|ƒV¢b¿t}û}¨½½™3 ™¨ëZZ£úûà£Wq­ÀC®â<ë:ö2£¦õ­;éØK½D§ù}Dçx?è!zš}Ð@ô|ƒæ¡/ã4k¼S~'húÆÖ{븦Q—úKí}7´êRßÓÞ÷V]ê¸î¹/×=êÒÄZ&ö™ÅìƒbÚþ_s"û }˜¸¦¡e˜Õ­:3±ö‰÷3gs4 {dPg¦Î>hæmíórÂËabý:FoÎxß@%&®WèæÖÖ;Ù¸gC‡°»·÷et»w{_îmðîÚÃÑ\™}:¢¹Ú3Ò-ÍD"^ööâ2>«WÂ,¿¥½ÌѨ÷ž`höÒ/^ïµ÷²w7ç`š½ìñ͹ ×´—,Мûšç’šs©ìqï†EöÞ¯ŸÛ›³LýÎo}¡G+¼Áà(ùÆßž5émgB˹ëÌè¿Ùv&t¤»ÎŒÞ©mgB«ºëÌè¿Ûv&´°»ÎŒ>ÔmgBo»ëLú“FÏ„¶wיѾíLh…w=ðÛ΄6y×™1GaÛ™Ð=ï:3fU´Ï\?ÏΤNgçÎLY܇Þ#gP=ƒûòÔGÏà¾|uËÑ3¸/ŸA-tô îËgPg=ƒûòÔiGÏà¾|uàÑ3¸/ŸAMyô îËgP¯=ƒûòÔÀGÏà¾|5ôÑ3¸/ŸA ~ô îËgPÛ=ƒûò$ˆÑ3„,f•ý 漌žÁ}ù Éi¹ý îËgH¶Íígp_~z FÏà¾|=£gp_>ƒÑ3¸/ŸAïÇèÜ—Ï —dô îËgЛ2z÷å3èo=ƒûòôÈŒžÁ}ù zpFÏà¾|µ¡Ñ3¸/ŸA-iô îËgPÛ=ƒûrMS#=ƒûò’¹tûÜ—Ï|¨ÛÏà¾üôŽžÁ}ù ’ýèBüé ’ÐèBHé ª £gp_>ƒ^µÑ3¸/¿«äÝ~÷å{Ð/7z÷å3èu=ƒûò]é=ƒûò=èÅ=ƒûòÌ‘=ƒûò]%Gäö3¸/߃Ù0£gp_¾‡ü¿ý îË÷`&ÍèÜ—Ï`žÍèÜ—ïJòèÜ—Ïü´ÛÏà>œ1ÁÎ 7‹>${*1ðÜ”îP]¥Ï̺¹ëg »!%Ú³´†ËО’ìì9žKwH1¯Ãä-I˜‘á±Bf†RÆ® g»:Îì·Tkø!Ý@¸‰ð ˜=ôñ;v%Ée‚³¿˜ð¯<õ„æ-饯b>² !ò×_áH?w¦ =g)x '§$ͪî¼Ò¿ sñ0% 7òËÂKøe­w÷ª¾»w—>Öð ð.þ•œõ$fj­æýSô`8"0@øÓÀ Árp“°Uk¨tÁt%ä•«¼JP«'(Ó¦â7 ?õw¥v+_O¶¯rMV Ó ãW¤8ÆÛ—F”0–”æ„Ã-K¹úÙQ*;·«ìñ¶•uTae&0ÐZu¥Ö ÈJ®:R{%·7£1–—J£—+”¶6ƨ‰sc¤ÂñÊcþ>¼Ö˜Û<³îAÍ×bÙé^·üJŸüƒ›_Y©¨¿ô•=„Ù~75ë½&Ö4_™¹„ù•1%Nú¢ï¦ýƒ ¥±¯vE\ÛéÕYÛ™Þ†oÛYåâµ·3=çmgz¨€í¬îPcñzŽµÞŒ k÷EŒ5&‚¾3ÖôÔìX%”°"Æ*÷«¿pœ ßé8ËÄÞq–#€jgÜv³Öl·°S“N¢Tÿã¤í*½î8i„JdÜ?„Êw“ãpå°*cu°Ø‹ÎþCå°Æ†{cS9¬*VÎ穜T+ã­óâ-ÆzÓxÏ<Àš™$¸çxÓxгǛö‹N9^>O²ôceÔÌ„C´†î2áx­á`·e†5UdLЬ :ƒµ1Áî.2á‹áí'|É{óö|Ñæ}ÙŸ›÷åÛ7/ʺà‹~vç‹N4…ýz¢Ìk|Ù‰F7èíE‘ 4ÑÔ&Üp¢©Ë¨«‰rvÒõ¼=ÎÚíu6«{ëwx­íW…—Úþ”öK±ßwøRñ+¿:â+¿TîZ7ì|©íÝßãY{;Ø©x©,\±ƒü½¬½”‹ÈÚÛÑj/µ£½jpGc$ÔÕŽÆ÷x©íeÁs; 5tõ,ƒ>Ô­¢_ílš':÷ÎòR#£¤ØGuÈ̲Iz¥3&© Ñ®?ééÁº4Iú®ýLÒK+›œRO›džTʤ…ʘô '͇ëÿZ¾7Y'Ö»;aÓÏ÷léଌ¿ñ¯¬ØG¦Ž•êd’ú inËkÅ{ír\¨ð]¬²ñ^»递v1ïêpóP nvQVëd²Þk²ñzÑä÷èýÀÄ“å `_ž¬öå]•W©Ä »ŠÛ˜ñµ«XK©wÕ[²v}—Öàdª¯ÝtW%ØM™J„´Û¿iûí¦ÌOuŸ~/­ÁSôÊZï6Eo õnSä‡Ðz“)Ò¼µ:ÒùõjlŠÞAëNS”©uß)÷hwìR]juª.é’ZõØ¥Òê]‡jºìÒ{iéI]z/­þÐ¥>¤Uq]æÂûw©kõá.iEZoÐ%Y«otɃ¥Õ麮Öºq—êAë}»ì]лîÖ}¥KoȬÒ.õ­þ‚ ä¢SÝÅ{Zu°»ˆR«v·û‚voi½åî"D­7Ü]Z½fwÕõŠ=Ô•êa½¹—í!ÍÑèÝ÷PF›Ñ{ïaçà÷”.ctÿ=µÇèÞ{š_ýlOQ¼Ñ=÷Ç1ÆžêV5Ò­fÕ'ºU V½¢[º»U=ïey«èS{í剤Ôb_¦Ô;ûÕø•¼ôª] UÒêZ͹t'4ç’ÝšsI3èé\ö·×è)Þè_Ijì’í+ò¨0;hM Ÿ«{4~¢¼ ¨×1 —;ÃTw5;$iÍf“KšÈã’û7;Po#;NÛJ¿åÔ¾h„ÍHr"jvS†w µUîÐì@9)­#;¨Îˆ~/·gªÌ·õžfìàIû$:4µˆ±¯ff¡?ŸßöÓ“»òmµÜ]øv@¢óÉ–­p›ßå[ÚÞï Ý…Y <ç`Ùéè7ç7Zus.1u~sþ:èò¢„ò½° ;¾áßÎñÛ¡WJõÎñY’ZÌ BûIïÈÑÁÏw`Måv´ëÊ7¦ÌNã®ÄC*f¼«ã̈ÀÞrûØ­HyÜÇ;Sãá>“vù ]·0râ7¾.»¿‘s™b‘;Ã7î?–oì\Çñêx¾¡{ ¯±.nöµ‘áŠGª(CÍäŸÊË4;¨Q ÷jaÃ= ÉŽ#;À ­þÇ—¸É¿ÁÝ+Qd›óß'/Üì@ßȨñäêŽ;>ÿØ=¨±Æ›Lùeý6;Àƒ#§"ÑiäfäSVl³ƒš  Ù¾9IJÒ ›à+ñ%4;Š„®×ީ¿yì…Ý"9¸Í(#7#‹Ó©Üì š6|W䥌œ„”‘{0o˜¬Ùäa©fõ’W³é%ÒÇšà@é˜Í*Tïˆ ‘‘îBsxô‘‘¾Euvø 䃌ì vDnlv€OÁ'ít¶ sýqïH—Ýð+Ò«7\åtü‘X›ô ×݇dfGÒš[;脾kRrã}RÏr‹Y88¦xŽ¢ó9=Ç%WÕ˜“iFÏŠÄnoÓ¤õ“qôô¯ÙÊVç¦rž£ˆ1Øfh¨ sZÏÒ¥‰ù÷û¾‚Y,ÜÓ?¯on0ÏíYÚ­ñ°c˜J:ÿôž¥¦íÁ=K•"0cé2M£6c©f‹{HÏÒã45t:+_¡¸€ ­[½e.ÛM/±o˜vk…On|VÏÒã5‰üo£ÃG–(.y$ú§N(¤S\ï0ÅÅK,©¤è|­NÀ[üª>êžëƒïï4®áœ7ÍŒåËš/„,Øÿƒ¹{Å=ÅUºKüdöÒ”$«ÆÂŠyŸŽÊb'ÍšÍ ÅÞžUÞQÞkïh]ª)§0 çXìk(Îfs6>¦Ø¤¸âàŒ~^|­ œÊâ+:ÏãëF–ä¥|då?â#f.<»äsK7Ô4èêÊøÚèxA|]”&G7ÿŽ…ÚÅoz?‹K_¯´ù¨VäUzñ›½ß‡k/®Ð\$qŒq•×|㕉s±ÆÝžÑ­vryO÷ŠÄ¼m=ÝêÏì9F-ëY=Ç,U涨êp{(5Œ¬rSØY9žÝsŒZ׻暕Æo2Ýs̱Pm[1:ØÒ±¬%"--Ú ®××tç÷ZÁ(›ºøG=ËõýÇ=Ë—&æý¸gyw¢sâ繘ïrê„J/ñÝ%5Í¿y8üzóó4`ˆ9Úf_1Çû#T@KsñdiïVN&³FCvŠ—úë%÷“žåê·'ô¬8.1O½EÑÓ³âøÄ‚{¶XS\QÔð¿¯kõ\ÿpøÂÆôщùO©±]·d`š7Œ©Å°Ó¡ì:æ~‰ù'ÿ*š1|ÝoÊ¡óŽM'– ŽÒøYXNOÌÏiytbþ Ä ¸ñ¥ZâˆË´ÄX+×òMd‚%ªñœŸGÁa¤Ë©>3b‘[R£¨Ã³–h´¸‚¦jx­Ušçì³ à‚•¾Î%²ÿ¦™«6jÆyŒ³:_Õ„«ÇMè%¯ÐMñ’7Uð 7jyÿÄü¯i‰÷ú¢–x¯›´Ä{ýTƒ÷ú™–8é-ñ^·j‰÷RZâ\­%Î5Zâ\«%ÎÒ³TþØýµÄ¹»k‰sQgÓu.êhú±‰ù]ZâöÒ·Ø[KÜb-q‹}µÄ-PI¬ÏãµÄ- %nq‚–¸Å -Ô11|ÄÞ¡÷Âæ™Ú…Û|N_qÆçµÄM¿ %Èì[KÆÆ4 ò Ø­W«Ápî•ÚµbS}¬V(ŒM¨ýØY½ -´Äó¼ÂëȬUÜW±àMÿUÌ;\¡`ÅÂ'˜+.š ìÛIfZê=ìEZÑù| Ô`“z¼íëüÁÌy£kû‡ý¼ÖÍÊ_öÿŠG›“}Ò¯:žzëÏû°ºìçý]_>Ö¾ò1ŒÐ¯û_Ì©ŸÛf×w^yiiý0«ˆÿÏ/ºÂ¼eÖ*ް•ø~øxVT˜JÂâÞã‡#„X:€SRh¥ªàVϪÀð¸ž6‚Ð@0| D%m‚G#ºÁÐ97¸¿xüœ0|s:èE”Ë +Cç@Å3¦aCËÛ*,´K ¨±H Š…¡d!x Mä0tœ•ÑÙ¹´xâ£m"Ï¿L²0t'Ó‹÷*Š=æ: Þmkã9ÚË£æÝ—^,ðŽ…‡3`è´` ‚tà¢ížz[ 9»”›nŒiž¸Bê¡8v[79vŒŠpœÉ…¸AîÈÐÏ~ÞœGާ¦1Á”Oeûš[ÄÒÃ>Ë=Œ¹ Òo»ö=ÚûÆ·ïÑÞw®G‡§‰÷°ú}úMÐy…íC‡ÚGŠà>ø”Úû&ÆçÑÓÓÞÇóú‹õœŠÅ˜`èwžfMÞ7Ñü(êPÒíw –Ý0^÷ã¾Öýèês'ëµGÏsöéí2['Ç…º?U̇ÙúM²<‚®òø99Ykz I–Å“÷µXíyGoŠ÷EOÜïLyÔÆVÙ‘*ÞƒÚp>/NÆ÷Ñ+÷‰¯;½½m»U4ª^òÝgê“øí¡þ1ñ"ßw衆 ’»ƒ ÞÏ xÞãWjÕküî'ÝA…°oÀ|õT‘y?xõÕnáG›ÖN=¿¥¢½{Ø7ÃüEÉ{í-_wr¸ÇSÌ!DŸ÷13bLØ÷ióXÄÜ3Ì0Ëzûmï ÏËõÆjaØ÷8óßP çyÌ:.ìû¤Ý•Z;÷Ñ‘îñnS¸é/Áo…\ê¶°ïÛ†³ô«â·RpiŽ û.³;ÃK'÷ s§ú¸Õ¼¾£þÿ CW Settings.stmgestñˆITDATCWIEº&KÔº&LjDé×ÓZ` Àu½Œ0?É1Â#GÉ„áɱ#ì$¶’•L˜„zä(¡x¶2 #ÌÓU¶22ad€'øÖ#lÕ@Æ;2`„‘cdÌ#(a„A#`ä™0rŒ#ÇŽ ƒ‘ #h ï“ÜÊÈœ12ÄL€ tx €L©§Dä‰]¢ÍKD[س!<ÑÖý4{„±VOdfÂD³Ègå oA©áó"Í'ržhUáé¢4UZËÜ„S=“†sÜVYµdnå{ >úz%¼¬ JT¥3™¤S ƒÉi›Š©Ú8« DÈIä¹ÝUt䧺Ñ;n7BïºÝcô^k÷Øwì+ö\ãµv„bÿ†èÈËõg÷HŸg ®í|ÃÎ+M8C³VÐÍ?ã lÞãð,îÜ=âÆvÃǸVÒñÍlÄqÔnäþ!ny÷¼ÏDÁ×Ú Âs¿ 8¡“«\þïb4׈Ÿª˜ËðX™yº|ñÏíñ%®õ[`,€7Ó-K£×\œxŽßVϪ÷sùš pvÁ-þp < z7_üÁŽ{‹á2sˆ˜¿Îî½ÃàÛ{?÷°s1ø€á‚å^^áŽûˆaËro¾cç²kð «g–› XPËmîsꬹþx‡eê?!! bximage Datašð†ÿÿÿÿº&KÔº&L3ÌٜÿH bximage.projj6QÉ–ÿÿÿÿMMPrCWIE¯xMžº&Lj>+møm{ø‹uF»íg^ÙÙƒu{9ˆ°È? #<¶)á—GÏ­ì´sÓ“åm“?<õä4<=|gÿqå–Ù~/ÙJ¶‘MžwdÛ„’M¶ÙO69N~“MnÙv’ã99Nžç÷äxd“ãäö{dFxä÷“ÛG[±Â+ûž°ë'û»­I6™l² 8¹MÉá×ï¼ zØ™'?3ÏòüÎ+~ ?/;{Úçõv6òs{o—^—ŸŸ]çw¼K—ã‹oÙóÞe ËérƇÖ@ßÒA ìØå _L/uR`,üYùyy6±”ǽná á·ù…ܾx^x8 ®ÓðZI{ž·Êóü‹<õ=à,ϸˆ˜u~Éç謥I;ܤi”¤åFš,„­ü@lPÊ’Ÿ³ÿ³ç}ðOžw¹á~2sÞ=dØ~ª³pýÚeÎÔW¤´¼ù~΋؛¼§U‡ËÙ›-ßZö¨ag³Çâ¨À¶°·XÜ%ì­†½˜½Í°ØÛ {û8Ò_Ëù]ìã-î#ìžÚksþûĹAÖßÙwñÎÖóŠî¿«=éäâ=Þ·l6ؤ¤H(Wín9VqPþ°±Ó9ìé‘P±çíå}:™{>Øä^AòI{[¾_ã°aoâ0%Z!Ø[Áöõ¼+æÁÞ6õ,ï4êK›ö—ïŸ8tpQ}#ùƒ«5¹‡]C¬sÝB§q8À{à}Ä…tÏéûöý…z] 6ÃrP3÷5ú(Øž¯Réµfy'Ýw Ø/Ä®ïú2çÙoÝÜÆ;\ÙõÀî›cwúGs ãm:¹ŸÖTè¯`óS„©Oë’~Qa½oÖËaaýº Ûġ۰Ë9ô 7“`¯[8±½µöÛâ–ÕÕ"<Ó[ZVY…Ê¡Oõ¢Ø'8/¶{<ÈáPïóÉg-¡>´Þ"Ô°u…ËYÇá0ÞOk)r%ØáRŠÁUðØyŽ0ì…Ž4ìzɃý.‡e†ÁIGöiã@°ïs8ÚaMÇF®†ÈáXÔ+¬-†]ÊAëÁÆàj ^\i< _ý‡Õ†ý‡ »›ÃÃ>eœ v?îöNrXó‡“ ›ÄaaðË)†)‡X1Œú^oõç€qøìLgFmƒÁýgv¥iµJý(>2\EýÀ#Ü]ë^yÐÑ&Ô&5IqjŒw Æ¨C¸}r¨qõ…vÛÐóŒ“à+tÈtÓ9,tïÞ$N2uç¾%µÆS»Ô õ öØ»ÃmhxsŠÕ LCMQûp¹jëC¦gfŠ0l>RMc4|„‚ëáש…®QÍ`4š}ƒ^¡®©gt:‡z¦Ž©_ê–z…ÓàBê•:§V©_Ä  ß G¨CÝ›owiâu™YܽC…ªûö{ {+{{;û8Åòò/’’Éžš¸T‘bëw·Q‚LÈhÂì“ÞÍ‹‰7r/Qr˜Ë øa%Ë]£Þ’ñú~*6Tã ˬ²ˆ¶Rk}­Q®o»ÆÑ¯¼ôíûoÒ?;¹) Úaš­[W ®Ìó›w,¬M‹Q[ƺYÄ‘+Γ+¢°Ó?XM£Ë­[1ê â*,§ê½»?ºÆróF™7qH¢„”!ÁèªáG7®ÚüГ«6ýæîÒò¯/-ïyÐÊà¡Òò7_"/âGæ{Õöêà,›mx ÖâïÚ:5=5\«Œm7U˜Y¶Ðä9˜óIþ=þš’äf£:ÅÊÁÂ9öà &öíÛýìá”v¦à·5Ìýï s’+PZf¦§Í>pVxbf«ùÖÀI³I?m…™’-¯MŽI&âC§OÍÖÊ“Ñ\¤Q‘&liZì³ó¸ÒÊ)õ õ¬ívnµ³k"+,Õ")hÛhƒ xìðÕ’á£ÙÒU÷Dƨ‡–z˜Î‡åigÏýï:œeÛsÈÈÈè¤ì¹„ýfâfËñЀ²’[دa»ÚÀrûUìjcÁ V…`# ùåö—²¿ŒýåìjwÊ]ì×±«½(w³ÿ û«ØÕÒ³mVµn J°×ä ì¯f ×;[ÜÙ’õ¬wµÈañ–,9½³Å]-ÞÂâ-,îlqg‹;[²XõÎw¶diê-îlqgK6"ï|+;¶Ý³c½ÞÂþv¬ÎÛØÿ”ýÍìÈþ6öï²[ñíìï`';öã»ÙßÃþ^öÛÙ±™±ÿ€;üìØØïúZöÙ_ÇŽm­ïm}‰ýõìXÂZu`}…ö&vlx,G<؛هô÷ØŸkò¯Ø±µ±h?ÄþìXÉw²˜ý¯ÙÿœýýìØ÷_a€ëö.vìÊ{Øïeÿ(ûß°ããÿûß³ŒuÿUö‡Ø¿Æ®ßvÄêü*ÁD€à YP‚f[2*l+M°Ü›M°áKM°ú;Q°ç[M°Ô«L$ ?ÉŽuе{;v8¶ógØ?ËŽ[ðìgÿû7Ø¿Éþ-öϳó5á‹ìÿÂþ%vT:ö+Vú—ÙÕ¶dÿ›K;ö;ìX‘ØXƒX¡®í‰}‰%Š}‰ˆÅ‰MŠ¥‰ÝˆUŠ­‰UŠ­‰mŠÅ‰%‰=‰•‰%Šõ‡Õ‰-Šý‡EŠˆC²]¿:X²é±3±Vù[Eýv¬C¬PýÒ`ÉÍâc_$Ô¶·ô äBv¾y\ÄŽNá˾ª ‚…ŠÅ­ß¬ì|ˆ;:ºã;BVQ,MœWÕQ“Ø¢X¢X§Ø¥Ø©X£X¶ØÂجأX£XžØšØ¢8HX«Xª¸[X°®…ìÚÆX²h4ìcle,e,i\¬[)ldìRl_la,`ׯêuíX׆Eå$­Xµ`n¸LàB#î8[àP¾†*pºÀ—|øTàQGøSàL3Î8SàLÿÞx\ào¿þø^àwÇ狊 !p¿ %^´…Àí· Ü.è ß-"hASšDÐ*‚†4Œ aøæ"è A¿úEÐ$‚†iµ®®8LôµE9‹ï8Bý u(ðšÀwß µ*Ô§(§rŸÀ}úµËòá<¾í\'pÀu× \'pÀu× \'Ô¸Àwß |'ðÀa· Ü&úÆ£u(ðß|ž}⻎֨Ào¿ \'ú¶£'p߀Ž8Nà8ãŽ8ŽoAÇ 'ªoå9ãŽ8NྠÜ"pŽÀ»¯œ+ðÀ?ÿ¼,p±ÀC $pÀ=÷Ü#pÀ=÷ðeIà{î¸GàsþøGìÇ•:Q5 ÎmìlœG­­«ÿéù­Ñ? ¶¸4éfI–ëý8¼ñ(Íòòl8ß »¹7Tl/5 ;j^’æåË6nñêm/ÂGqœ$Ýò¦0îyõmåê`uÝ:—h]¹d­ .Ð5á.¯16þbêÔ,ܸèq‡ ’mI·+-}úè¨VÈÓ1\´!ºncûýžÂŽ[ÓïæQ'$Ø ÙïàÏ5ïÅ\úÞ-6´¦g+±åX[›Þº]YìØÔ»¬Æ¤[|8"S$‰¿½ÍÛƒê~DÖñ¶W§Ç€7PvRóZ\0þzqtE7Óø™xñd1$³:ïéF >Ÿšý|© åÃMoè Ó9˜Qƒ³ó×pK#Sñ²3KU}.$“†êÈ…dÒðй$­\¼?©jöÒAÙT‘ʦxŒtÐÑA'Ô‡j‚. SªÚÃ%>Voî¥ ÎÿÖ$õF¢ RM…,žÍÛ‡žè8ïÕ˜¡D<3”ˆçñb(ät\²Æg­^áÛÁ Á½üÐ}DÝ¡Ã84ÿݸ q½À…¤;ô?–’¸¼™ˆ7ôéž) ûÆiZ¿Dš[ÉŹ,Ï{|Ô]¤²—ö³<é”·„7íLÒvæ ·TÍ*¶íȼfᢷ¶åQw>C~¡Ä6ôzzd?ŠÛå±¥< 2o4œëÏχiÙå´œÔÐW½˜œzMÖ/ú[ŠÔ+fÊÓ=^ï¹»ˆ5B$žËàñd¼|ttØ-°eQ¦_ÎÉžH‹s6Me£Ï¹%Œ%ñn¹¼Ù°°KQ'˜‘t±†öAOK½â!¾ \]®I Ñ€•¥ÿ•Mˆ ·ÅOìÿÜNV L Ä,ý6·Û«Öêã+þñWÿÍbMžZ‰ï¾Þ‡_]Ou”È/û'{rÑãY×ey®ðÐ?Mhðâþoú!óG‹N zÜÇúÜ©Rèø¡yøE;åx~Úî{<¿q§ÏÃOÝiÇóð›·ãx~ûžy0Oªüã æágp§ÂµßÛïå1 ÖvñýVZäÑÄ›Ò@ Ðøù»[o ÁÎ~6OÒïñKw)ÏÒŸY¬’~ïïÁ×'nÌïõ=ƒÞ)üâ =Ãu÷r÷ ëWód>Dh]…õ›{ïhi ¿6Ãúi¼ïG™Ý{J¯åhXöÍ×40ñÂú]?u$h-úþª‡”gsÞàjX¿É;™ ~‘ÚÎøQ« "çqïýÝ}"ÄÚ¿ÅÕ!èG7¿ÉéìA÷‚äi³{ó»\k4¢®ü2×úŠè';¿Ìwõýþfyô7u“~Qóë\ÏMú]ίsýiÛ4Å}æ¸ÚöI{ m ×N…;'Fã–»ÏEE}+¼y-dœÈÍk'@mÕ$NRßï¶•gK;\Z_D´ÕŠU6Ö2±åÙœ+Ï>¶´oíµƒYŸøš×ö7ךÞÞ]ÖoCm¦»]³T)¶˜Õ}ýÒÞyOœsG_}ž§0'T[}lj+îÃFuFÒ˜—Í6gο¡ÑУÖ÷g¢¶&غ#s±Ê½Ä묧zi¨ ¿¾4Êûõf]]?¬çiG¼•ƽ­£i¢i§ö/Æä4+ý»ía.# ÅÄ]L‡ÆÜlLÚÅDc:³•=H©ýGPç¶šU.&–²ç¸bJ+&f#&“¯é´SmšŽÅ4]2ã ô¾[½+ó Ú.M)8ë¼<ï .Ðùª3ëw+üèœÇäZçô[y6¸Ð^¼´ré`;ieƒA/Ò|…A$‹™Ž3—åxs¯û­ÍJë[¿ªè¥À´ƒuž`c:¯±¾‰gXÜZ;Ÿl÷Ygø)vŸSí~ëí>§ÙýN/ΰs=y¦¬¬à¸¹žì¥ŸÌXÝþJOy˜_«F6ë—Cý®©ñóëıíÍ×[7§FI,.çk’–@€{Ôä¿îqæ4õé :ÐÕzp1,­sáÆ¡ÿý¹Èc÷8§øÙò“åÜã¢7›v3¬ª}ìØÿ÷µ2KO19|í¨pMG^¶Q¯qþÐ{ 3ãc÷ØväYY:÷L×úòÒÆË^s£vûŸ"ЋT+úQE0rŠ`ä;™|û=v0yãç}×Ü|’©Eç¯1n¼GœÉ™y·²²ÃQ–oä= ûò“7î±“É‹×ø!“ÜãbM ü£wßã’c¼¨„¿æÈlÓÎ=ì9´Ë‹KlÎÌL¾3DWVn”ΡweýT™º£vÛS¥VVÂi©0µÞã¢9ÍNU^«æ޸dz…V¸Ùa‰¿<†I6Ej2“\|fX“\ŠÁùMr R#äâ¼ÖŤžšÎ¤˜Ã8wÅhwv¯L§J)gˆÏŽâeX^y`d'25•J.žYiøâã 'Â+gÇŸ\5ÔùbçÌLì ¥’K’™“ÅO1üüÉiZŠáN|,F3†K)Ô/Ô°.¹øÔü.¹xÛ)ªfÀ6®<~ÂU.F»¯gΣe¯ ´\£tø„Nt•ÎIP!sÂ}*'ºLän°Ïn¯PÜØ|‘ÛEQ!ðøÙñ9ò&Χn¢ËÄ.?Xž´ ¬S6)ª„Hà?w™¬ÝàZ™–ˆÚ¢éx`©|Š&Ú'h¢‡é™ø29»Á¥§Lsf„ì “À§a¢«4L‚ îÓ0Ñevƒýúv3xEáÆúEQ¡áø/Ùñ9&Χa¢Ë4.?Xž† ¬Ó0)ª4œHà?w™†ÝàZ™–hØ¢áx`©|&Ú§a¢‡i˜ø2 »Á¥§,Ó°Ný]£aø4Lt•†IP¡aÂ}&ºLÃn°_ßn¯(ÜX¿(*4<_à%;>GÃÄù4Lt™†ãÁåËÓ0u&E•† üç.Ó°\+Ó »±C4,•ƒOÃDû4Lô0 _¦a7¸ô”Yµ¥ÆÔ¨55bN5쩺A5fQÕLªºMµÝ¨ÚnUùfUîzÄ\µ—F ¦ºÅ4f2Õl¦ŠÑT·šfSÃnµ~æÏ¨ý3b5, º 4fÕŒ º´Ý Únù†PÃzÄÀµpFMœº3fäÔ¬œŠ™S·s†NÃÒµW˨Å2b²4l–ºÑ2fµÔÌ–ºÝ²ÝpÙn¹ø¦KÃvyÄ$µIF’ºU2f–Ôì’ŠaR·L¦IÃ6I Î]²0ÒIrt—ÎP ¼tòÒ)r¤—Î¥½\‚\=沤*2?Xx™Âñè/Ÿ#Í-™I LÇæH0¡Dƒé4",$©=W– s ¶—ß!æâ(Ñ ®Í-¦3ÔˆÑ7<ÒIjÄè›é$ub,é Ub¬˜¹,¥Ê, ™Â©cÙÉä(cÑIg%Fß )$©=W•+–H.Ëpù•‰±`ŒdTˆ±hޤ©3ûåÁKPåçÁ¯é༙ŸÎ‘5ôs †õEÖØO×Aõ•‹¬¼ Þ+—¥sT_9ÿƒ(_q²oÜø¾RùÀ²ýCFýKFíSFý[Fâá} /¤&Þ|/¤.ÞŠV^:CU¼Uì¼\–!,½LáÔÅ[ÙÖËä(Š·¢µ—Î0*Þ|{¯¤ö\UñV1ùrY†Ë¯,Þ V_6AE¼ Ù}™Ù7µ‡xÑË‘¢E/A†½ƒ¤èeHqb>ÓÊ~íüíöcåð$£–âS]Jb ºî–l¾ÜÙÔOg§| ‡K½Ð•z ’¯?ü„®Èób³4íeɰt%Gµ ’]Š)èC—Â!èrl¥RRôì%aç´jöR$es)¾ò¾I᜛uD yž^‚†>È:ž^†ª>°Tô}E_dìÒR|•NÒfi)¼Zn5}sJó) ú`È'õ ëƒ!—«œ § ¬—¥¡<6Ÿ£¢òþk)I¥ Kú c¾ã}}0d½z êú c–â+ï;¬<_ÍËQÕž«æå¨éƒ!O-Ÿ ¢ì+úú ãÈ•â«t’öãJáÕr«éƒœ—OQÐCVœ—`X yÄå9}P°ù¼, }à™|ù}·øJI*]Ò¯ïëƒw/çº{)†õAÚw/…»oy¥s é/GJx 2úÀË1¨¼ )}à%H|)>Å¥$¦^JáÕz$x?EœÙò)‚÷BSï%H|9~ø ]‚÷b³ïeÉ|%Gµ ’_Š)èÁ—Â!ørl¥RRï%H¼— Mð^Š$Á—â+ï›êË—Õbˆà½)‚÷dÞË1Hð^†Á{ ’_Šš¾Bð¥ðj½ ¼Ÿ"5¡}‘à½ÐÁéïs ’_Ž~B—à½Ø,Á{Y2_ÉQ-ƒÌðú#_JR)èäàûÃ_Œ x/AŠà½i‚÷R$ ¾_yßÁÛÕ~|Ðï3Æ>òp®??¦eGãö>±ñ¯2àŽË’Ö‘wàŽZj…p›F˜Ël\Š:<Ë qãRÊà ʨ 7nPa¸Q)UáežÜK*ŒdLŠ„’¦0“!nÄßvP1 †Åé1æ(ƒø›ÆëÎHé7(KÛnd’b“1ùMPi2úLáéNѤ”¢F7(OuËío~»3r‘åiÐ…p¶c@ó0"I¤´ü¹K8¿œ½iíp»ÍùÍìÍ T—ž?Ä IÄùËì±zMCĉF:jÉyA1¦æo­‡]vX[Ž`Qì|°v íg.w‚K²ûË}`ã£8ö° ³;’`_›¸)jë~ŒÐ¸K=¹,¤Açvsò…&ÀvÒ· ià„I»ÿB±_Û=Žô6¡ï‚íaùîÛ3¯6y¿Ð3`{åñÕ%À(J“£n•· Ÿ¶w5߯pXûÄýp CÑM‰×Ìr§ð§Àöm†ôa¶V}lêhª¡éÂMk¦Ã8„Öq2Š}l?ÞQçuˆ¼lÿn;¤¶" @g§vΊ1èÜôÒòž§Áq€w îz3 »õv‡Y†Q‹é¾”­žg»¸&.-ß˼M#`s¼Õmê§éz°¹–ãj†ý&‡yŽš¾vˆãƒ¦_Íw|Ф¡î8>h>¬ËñA³Æxèv|м¬ÇñA³w¡ãƒæÝ`‹4¬×ñAó#`}ŽšU—‹DWƒêø *ÞZâø z%ØÏ9>ˆ^ v˜«ï¨ÞòpÇQ½åÏ;>ˆþìWÑ_ƒiù¾#tø vØ2DZ`G9>ˆ©.—;>ˆ} ìhÇ±Ïƒãø ¦º\áø ö3°cÄž;ÎñA‹Úóïø å\°~ö_;”óJq¬bgr^帺å6Îð²ÖsË2g†æÓ‘ªZà û,çµâFžǙ·R~iÇœ$®Sl>ç“ç·ênëÄcŠ]Èùü­ÑVÕå©ðˆòD«êr½†³P ¾?MSñ(ö°Ó·x#¼_›ÞòŒ¸§7lÓ[žé&qi“ž8KcÂ(Æ g3æ…bZwy©¿¶=`ÿµýl“ã¿6Õå9nhÁ6q ýΗ!ö’6ÁšPŒº…bÔÆyál€ni‡O,i‡ ý³œÍðíßâ€î»ƒƒ‘Æí¿çÀû#Cà˜-{¯×8ZãÄ­y¥S|pw·zŸŸ=†6zþüPùq°—€]²··`œ8f«þ™+ön0ÒûŽû%Ø¥ò^û&Øeꙩ%K]¾@Í¢£./W[Åà‚+ôƒD1ÞîJ¹1ŠQ—/t÷/s•»ßøÇÀ®–-£Ø×À®‘'¤ÒIyÀºMþŒbè¸kõ ^1xáÅî½'H[ð†`pØ/ö6¿hÚöUèäØÓ†`Ýœá ­ÓÄ)h.°+9\gØop Áà­WF­ó¶`h£W9l—39 wÀÐFÊ6—ñV`—s¸Á°×qøuÃnçðjÃ>Íá5†}ŸÃk¶«†R¼Ñ04ùÁÎàÀ[]Åáõ†ÝÄcÇß2ì“à1°ïr Rt‡7†Þ‚·m‰ª‡7FÝlØ-œ­3ĵhI°Ïq@;tnyß0LùÁÖã`Ìþ@~0†?ëÀ¨g8Œ¼o1ìN·†.OÉðŸ¶qwéÅ·v ‡?1 í‹Æ£ÎA­3u7xìƒÐŒ`ðë;¶‡ôè; Cs¾Ë0øÎSn´~`õü^ø3u v7t˜Ò¯%>Aâ¨.³~l£Æ )À¸Ÿ›rOqÞû £þÑ`ÜÍgà?€ý'ÞS×^ÒÔ&ú†:ÃA·‚Áƒè>0jì#†ç†Fç uMO£ßÁÐÍ÷v‡Áó`ðÅßÆÛ©±1ôŸêÖÞ:|Ì04†ŽA€¡‘Ðò`ðòÇ £Î?a÷ßÀ¾Å®Öµô15¶„Ã}†¡¿?cú›7ƒïÔ˰1j Nãüy‡MшpèJ0¸Ï ‡€!ñÀàt¸ ^¸ß0Þè_ C;Rkºö•?W€¡³¿b|ÿ€a×pxÐ0ø½¿à°Usø9`ܯÏ0xÂÌÿv ˜ˆ·Á”;EºLõ„\a5§5ËšO‰t=5gÏÇ¢˜ú¸‚Ïbcꯈ´95g†=š…~i%0ÕibƒAÎBˆ v¼&òœÁ¨98LÍ/ÛëSïEÇpu0Õ…b#j„ÆjÓÆT¿‰<0jÿO×lxJ¤}ÀôÝÅæ2š} ˜=4«bÔþ˜ú"ÿLuµÈçS]'òLÀ¨9ü?]«¦ñjÀ¨9|Z0î§þŸ©pS/C¤IÁT'‹´˜j3‘†Ò5G5‡o †ž°‡UŒšÃgÃÃWÿÏÆÔ2iŽjÎ ®4ý,ÒM`ªÓĆõ™‹ßl.¼&ò"À¨93¤Ô\<1‘¶SIÌÿ›‹?bÿ;S-æÿÍE¿‰ùª9üC0å)‘¦ï.6–U'ž–Èû£æÌBøbƒ@u¢«Åfµé”¶0KÍSÍiÍÚ5­ž QsxY`ÜÏŒ5OzHqS/Cl’›yèd‘' ëi ´65‡†SžùÆ`Ô„™êÕœñÿÁóÿÁƒóÿAëŠùó¥-Œÿ7Í æÿÍ—¶0þß|iDãÿÍÿo>þ‘˜ÿ7_Ñøóѽbþß4˜˜ÿ·Nóÿ¨æŒÿ·@@Œÿ·@ÚÂø ¤-Œÿ·ÏBÌÿ[€6óÿºÐibþ_—jÎø]ºŸñÿº¤-Œÿ×…îóÿº¤›ÿ×%maü¿nt¯˜ÿ×óÿºUÆÿëVÍÿ¯›wóÿºÅýÆÿëÆÇóÿºÅsÆÿëA‹ù=h3û_ ˜j1ÿ¯GÚÅø=ÒåÆÿëÁwóÿzÄýÆÿëÿo!zUÌÿ[¨š3þßB4€˜ÿ·PÚø ©1ÿo!>™˜ÿ·ßÇ êk]†!æÿ-RÍÿo‘îgü¿EÒsÆÿ[$Ýoü¿Eª9ãÿ-RÍÿo¾Œ˜ÿ×+ž3þ_¯ô¢ñÿzÑŸbþ_¯| ãÿõ¢IÄü¿^ý?2þ_¯øÉø½Ôž˜ÿ×+oÀø½ÒÆÿëÅ·óÿzÅ[Æÿë“Ö1þ_Þ˜ÿ×§z5þ_úPÌÿëßÿ¯OÿžŒÿׇŠù}â6ãÿõQ«bþ_Ÿ¼ãÿõáå‰ù+ä L%Ý£ÃW…ëõÆ £~ÆÇ{ Ë-`<3ç·pe’Ñ=†Å Í?Yí#z½¾~r¥Ów›fö—ÊÆÃVs,³có÷ÝãØ…ô† ûSؿ­jþÎÓõ±föè€pÞÃf˜G'Ñ;2ˆãŽ9&ä·Uq Æ·­ó±ïÁ8µÏÔ}À“_¸ÀÎ=êEÿhï¸G €²X_k¼1Òf½Î¨ûõQïØˆcõª3èU‡ô[ðâ%Ù¿§ôÛy–Ž´©ŸòŸ~WûÏ ÞT§ÆˆV'ñ¹¯Â8òNk‚D¯„ÌêXyBQö×'Íq÷ר§Áà(Áà€¡RWO£¹¼G@…2 0–5pbÈUsð§µÐ0bgñ]ƒFì l–õ±; ‰ß#8À!ÙÚOŸgø,Ài žp6¶îˆéEm14¢;·æýîÁ Aô™"±ý†æM…$­+O8$'žrp€‚ ”ð^ƒ˜|l Í>uÅOPŸ¶øòOx‚þ=‚M~‡<êÁ•«ãInä;=¸‘{ìôà¶ßc‡׸Gp‡W|× Î/´'<¸Æ=vzpÅküЃ¹Ç£\á"A\-‡Ó¦rôŠû”êô1Gޏ[U¬µÀ/¯LhOzy%àåé°ðÿ^µqÖÒÉ­Ö»âÇ ¥<ñ»èY ¨ù“VX5?8€ÉÕGÖ7¿÷Ü  áÚÿÛ[Eoáçx¼·Jõc¿UnqÁo•gzĕΎ$ÕúpÓïÕQ~'{uTßu̽«{ÖÎÕ÷°ï±£7Fý¯ G௓凪öNâöøqij™@_½¨âL@wÙ½5ggú ºk2=Ïbv¿°õŸµó© ‰Øý’qMôð»_2.*cî—Œk¥olèâN/;·'¯zg'Ÿ?t¿qêKø—Iš¨‡ŸS7Ót¼úävöR\Œð£ê­fú}®¤ßg¤æânWOLÓûs•ÎVÏPÓ_³_½}úïV¿`Óks¥z#:õiª&MßÍñê£ç¼Sävõ€3|ôRêÀ¼Sä õI4êuœþã8ï¹U?Þ¼N=awŠ|F5gzRNPßgç"W«ÿéOyz’š:¦¬e½*¯SOgóN7Љ0^}!w ] 5}‹{élÞ)Tô44=Œcê·è¼SèNIÓÏx²ÞÃy§Ðˆú0šÞÆ-êóë¼ShL=”MŸãé*çäz5º={Ô£Ðy'¹©âö?¶ç6ˆ¹ú{Úr{Ƕªt»{×eêËhúÈFÕÚä{nv{FõN¾ð½ôMvûžÆÔOÙÉ9nv{ÇÔÙä»B} OÇ”wA·òAjÂíùÞ²©áâÞ®þ¦dTõçÔÍʶz!›Þ-êGÜëâ^ ~̦7dLu2ÎÅ]@O·Od‹ú0î_Ä­º\=ŒMÇVõèòÝOOg·×ã"q§Sg+¦–ܾ­ê×éÔÙÊßÒÙíy>\(îrŽzñš~—Ðÿ7|zwÄ#êglz@¶¨îc<‚A½u©úê¾²þuUì­{„*ßQ/FÓ3òDêjâ=.î&z‘»ý#÷ƒ_š‹ú ^̹½$ï£WæìØå»[ýJM_ÉYzû¨Ë7“Þ‘nɃ°BE}‡ßC͹ý&£ŠßËÝã\õÊ5½'£ê½nóVhðTõ(5}(cÒã]¾k©I·'åÁzËf÷A¸ÍíOS¿Ñ%.î%ê…izUƨ-÷g©‡¥é[9Þ‘§\ÜÞØía¹ÝÞàÞ£ëö³Œ©³SVkÓÛr‚xj£‹»Uucú\ÆÄ“\Ü©êùjz^FÕÃÝyïÎçÔ{Õô¿œ«^çpqW¨Oªé…ÙE]Š«›yW©×©é‹Ù#p‹Ë÷F8Õí‘Ù"WÕÖ¡ÊïpþÜ~™‡Ó¯6dï÷ú໽3câÃ÷è½í>š? macbochs Data­á¹ãÊÿÿÿÿàºù5ºù8õ{¯X CW Settings.stmÇÇÉ–ÍÃÉ–TDATCWIEºù5º&{­M$S"s ]½u¶a„y‘g„<÷$ŒPòŒ°#ì#Ï#ìÈQB­³#Gû•iyæ‘gkx @Ïk€†ÏØ€<#ÇŽ°#Œ#Ï;rŒ0ÂÈ3òìÉ1rìÈ€yv„MaO˜„FŽFa„aG9FØFØ‘%ìÈ”’ðáßõ€(¡‘cä™°#Çbâ  x»À9(Ó¶‡„1!´F!B$÷QyšÌ*M×h¬ YsSÆH»ö€4=##=/oõJ<e­Ùåd­^Ùk´ºvÑ1ÚòO¤Š®+-ÏèȺýÒª8Zl³8Ì®T%A?hmIeø°èˆŒ]tM™ÉöI*0ÙWºˆ e´ä³Cv”J±EY.5ÕÒWÏЗæ'­¦oExÖNßÊ𬛾UáÏ[ñHŸÚãºãZâÚâºSõ}°¸f ú¯£]gù 9ÚuqTÍW£OhíiŪi–n¶ÍOÏõ­eX3¢ÐtJê¸Ñ{ôÍtÇ1?íš6Êw…e[òWšf¥r. š¶““F³íå²Ã»ÿVZtüÒ–D¾T@0~ýØý¶åBD+ìh¶+ˆ§ÚóØÒiåȨ+jâ“ø¬¯µÕ¤Ó)#e÷ÊVi I÷g6èѹB âÇh“ Ü€#tgh“Üø…ñ‹t´#pÿqâ7£‡öÀ½Yω \’…ê|'ô¯å<%rŒžAÇ£D̆k†› ·Ž”[W·Ïö ~IPn;Ü ÜA8Ž¡\ÜN¸ypô3AÉÍ;wîÜ%¸pWàÖÁÝÛ‡^‘Ø w Žë[¹ÇpçànÀ]€{×÷î.Ü-¸‡pWážÀ]‡;wî$ÜM8Ιr·á.Ãqn”ãžTô§s7¸°oq¿SñðØ•œ÷Ž{ªrq¿—pà>ÀqîÕ=æÃÁq¿WîÜb¸pËá^Á­„{ ×7·Žc+×÷y} ÷ Žs¦Ï ÊqÏPŽs¬îǽV¹mpÜk•;7Ù¿¹§*7Ù¿÷ÁMöožüõ MacBochs.tdmstmêPÊãÉ–TDATCWIEºù5º&{Ö8ßÇÉ?Á³š±1²Ñx¾YÂéTÞ+ûS(­”x:k›ÖÑmW>³‹mºi£hƒŒ^oéÖܳ¼:;šyÖ¹¥o›:+ÊOë{¶ßÅcû¼ÞÞž•ƒìím’.<3¶ÓÞÒųË3ÏÏë,]Ì<{;¯7)V·½¼¢uNz·ß9Èòày·O<Š#øoÒgoo£Ì³ÎÞüÌQGô^~gooç5èíØu~çmÍÜz]öl{vÖ³ýv±}^ooÏvÚÛ»œ.ÏëØ[ºx.~Æ—··7Ï:{{{Þåuöž$À w½.O½:›ä5쳑åÙSÜ­8'æ×¦RQåDQÖˆ¨äSQÉúçEÑ~g?-+;‹§öwrMíÜù‰ªšÖ¥ÉöÄôšöšôË>V~~ &ð?ñ£açÇü.åÑb¯çÉbwð¿l±/ó¿bå4óÑ`±Y|4Zìl>š,¶•~{ ä$ö >ú[ìÏùÇåh±©|´Xì©| ²Ø| ¶ØÛùb1jjµØ_ð14ŽTÛ0‹Íàc¸ÅèÓ‹½€‘{#£,vûYì×øm±/ñ±¿Åþ‘1q¬¨^ŒµsÖf±cùg±3ù8Àbòq Å¶ó1ÞbÌßA{[ìC|b±ÏØ,û>c%ÍðD‹Ñ—I›ÎÇd‹-äã0‹1S,¶‘íP»†f°osÀ\2Ì!³Î,3‡ÌsÇ.`¦™wf™cÖ˜1f‹™b–˜!f‡™aO0/ìGö"û=È®eÙƒì4·÷ÌNeß²ûØKì:v»Æþ`‡±»ØYìi·¯þãÇϧüŸ¶•=5úâA?œñ‘C¾rJÏ¿fõ܃nËŸqÐmqíñWùÿþ˜ÿ¿ÄÿÇý‹¯çÿoÛ·zÓ¯˜¾Åßæ yÈñ§üÿþŸÅöܯðý«¶ïUG|”°™þŸÊÿ“ø4ÿð_û(‹ÄGó1ÿOàÿrþÓÍẢ̼3â95ƒ¿Î·æ/f^cf9f^cæWX0ÊbÞcåÑÌÇÌpÌÜÇ7ñÿ‹ü×üÇÌ}ÌÜÇßá¿f?f¶cf>Ö^`&éíøÿQþÿïã?½Ôίãÿð_ƒk^ÙôoßÂPq-ß³ù?—ØJÛ9—ìŒ{6ÿ/çÿsøÿ\Þü2ÿ…±âKùo–ÙþxÿïæÿoØ^K13¿Ã÷þS ;‰½®™þ·§ó½Èv{ŽYÚï¹øT¾Á šáx2ÿ×ðÿJþ«7‘f•™Síq ÿ_Ìÿ¥¼y>ÿÁ[äú]¾Õ£Hõ+3'±v ’ýÈÎdÏ€±4ÓµEªý*þS;øF8.fDÂ`®òÿE¼™É·f,ºŒÿÌŒf)V?ÉÁ¼Íá¿°Iü}þk¶bj‰Á¢`ÇøÕä˜Æ÷Kùþ=þÿ>±µü?Šÿ𡸠þƒ5³;,ºx;ßGòŸ>¿Œoj ?8`ÿÏáÿÓù¯Üïcv¼Á¸/çÿOÙnÿ<ÿµûböj ¾‹[‰ŒoåˆÉ¯å¿ú¿žÿ¯äÿuü¿žÿ¯âÿ«ùÿš ĺW0?̾ve$Lxÿ9SpßÐÞŠØ[3kðu=ÿÚ…±öõK„'båV­{-ú.ÿÁ©ÚÇ{9¶co‚wÀê‡Á;š½øj¾5[àûXóÈ{õ*¢W{0º<ƒ£bí$íÄ,ó.¾’ÿÄ4»±úÏLƒ^k8I½ŽÔkõ9Ò›‹yû,¾×ó_¸ fÅšYæ’™;<ƒïí~ÖЮ7˜9¾Š…«˜ñóù/|³wbáó×ñ­ýkÇ‚»ÀY`+°ø¼&Ì27Žùÿþ óÇä6˜Ì%œ³¿#Ý&¸%ÁíŒxIŒ ã—ð­=©O`íŸè|³7þ’ÿ_á?wá¨Hûýþ³ÿŠÿÍð:x‹9P Nü*ÿ¿FöíßòÿëüÿÿÿŽÿÏÿoòŸs9Ô»˜ÞÅô.Vï¨}ÿß̰°hÌÞÉñ.â]ö‹ç¿zk÷Åx£»L|>ÿßÊÿ·ñ_7•ø"þ¿ƒÿïä¿îñÅüÿþÿ,ÿßÍÿãȯ¼y#åÝcàø¾ÿÿÜDþ‰ÿßâÍ'ùÏ>û6ÿïãÿýüW‘êêè#VÍ5GÔ©æŸãÿ§ùÏ‹¨#bOÅ`&°yÌœÆÚŸÚ‘úöÒ΋µóÔ«ˆ^Eô*ROTKôaÞ‚¹¸wh"õLóó.Ö· 3DÌj>5X_¸#úÿÙ·ìbæ^û.â. '°sè;}&Ì €›˜‘ÄÀo¼Ø,7ÄÚ-z Op[†Š©‘»Y¬bvÁGïá[$V­Ä~Ñn |÷Yð‹Ùu¬¿aÌçâ]¿e•ÓóÛëÓžóœÄüй =waÙüªò‰Ó:ÚÚSM‰c’+W¤ZëÚ¶æYP[›lkKTÖ´/Û–Äk—'ÛÛš—nËs\Cc21»¦¥å,Çv44Ö%Ê;Û[k¶%Y”\Ò±ti²ÕNÅ{óQrLbZª.yt²ù‹ÚjÚÚ’MK“­$ZÚÐ|âŽËZS/IÖnëÉÂçéÅÂTS óð`)6ÍY5­ÍŒË³)úÁ™[QÉônL6nÍp¼ÄÜ–ö†¦†“¶7ÃÞåON2l–ûÇ&Žwß8Þ=:q¼[V>ãÁ÷N¤Þ-hkÚÑØÓ“'=<´——Œgu­N2P7koR‘†çØTí²¶[7}X]³é«Î½š>¬-ÒôYus¦¯:Weú0ìÆê£êhV_ºY¬¾ñÕu¹¶ß:Þ¥ -{g7XÖÝte¥Oª;*}Õµ”Ò§a U=ÐÛ|ÏTß°Xj:›]]é«ê®H_íY}þtu¹RWœ®¯rL,ÒMGÿÜ}Ç=0t™2Oýëb0/yÇ?dÖ/IT4µ¤ZÛlÃhjMcc*Õœ˜™ll‰f/LÄkŸ—Ç×4%µ”µ7.O¶¶³kLv²T×¶´¦„€.f[žÅbÜ\[ÓèRj‘‚µ´b£© mTUÍuö´¹3fôÖ®}Â'ÏŸ%„6…غMœÚàQúä„fÚp~MmÒ½×Ç%5­ I-´Ã/J AlY¦÷¤>½£ ²6]R–Ò½ôߦ‚ ©…©Öƺ¢ZŽ`àâJÓ.¤ïÒëSmí­Éš¦hbEsmcG]2jªÅ”eQS[ãÑ©%5m縆šFÍ©ìXÒØP›°”›£¦Žöd'9Ö[1€P[Ú¢ÚúÆTM{TÓÜÖPÝRÓÚ¤2Vû·ÑlÊ?E]”ìlW˜ç›ÛëRQle;ñ|^VSÝHq.Ášd}T+xuI{W|^G½j‰SLôÚh9ØIs{Q²)ÕºÒ¥Ü@¯×4,w5­®m_Ù’Ô³K@ˆQ“y®Ò]ÚÞÐØÐ¾2jN® #?]I!Ê{nãR†a³&Ã¥æÅ% íËš¢eÉš÷nMœ™Q³Iôêôdý´Óº¶®²½µ¬µµf¥†k \E3Lq¤º>¥©¦ÖO›–ÃîQ[lmmN1F¶Ótr}s}*òs|ž à”Ö¶ÖÚ¨6Õ\ß ú/ªih.ª­µ·¦KÂèn˜áÁúTüPƒB«Íp)pi3c·&°Ý¡Y|ªx³–$kê’­m47°p7³TÝ‹ˆ¼¦Astn#ݼ$¥t ¬°Ì›ÛkT¥ù´¥™ÙL'Lók›Ûµì·Mrq[]Rã¶F7‡ÃÝ—¢çuªxÕªØ ÏkcÓøµëŠ\[]¯6»E¨wSÇóøÏ”˜mqxü©ø¦Úê¶•mínô75v,e†ÖiS¥± L ¥<§íy~([ÿ]DKqKzypare“Ûë'—=Ï}QÈÅK? ¨í«YímÁŠä-Tt}‹jÜI‡ð¹- µî›4m|:4ct:tÄØt¨Ý-„Õà}®o×'cà>™ÃK«;ë“­q%iØV“†mEiØT•FW¡x°‚m^K¶µ¤a[K6µ˜ÙÞÜÞQ_¯hº•mpKÝ’L@bm{í²ºd-SÅ³ÝØáÐaàÊʦ†6Á aUÁåsôÅs¦Å {ŽnÚžë+˜SÏ2Ö³˜µëÙ÷Ä,lÑ8\ܶÌ帤3.T•¡ú0ć´¯ —ūۆ´°×´¦\°=¸´Eœo…/©µÝm€§ËÀfN.ªñŸ‚8âlUƒÇõµÒap³2/niY"ë¢e5­uu­®>¸ñPÄE,ÞaÍ?•þ—";¯Ó˜ ÿÚÑ'ê‰ù6#¨[o:¥™1ãÓ§sxuLHl/l#6ÅÛOl];έ4fž­\Ñ N³ÏlL8ï<[[|+¼º¦YØÂ Päáæ°¥mrW•V.ªi®s×¶6ÔØ¦5=ÙZQ—ZÑ\-p­å£§µ`p¡ÇMI7(iLÇ‘ \ÇùÔŠpGcõîdhÙnæ”ÁŠ2Ch¿Èª55g/¯mI“¿:޼Éòª‚ óÂa(×÷é˳›Ð„jK)2Nv×Ù¯,ìšlƒÙòsܪsQ»Î\0]Y.ž­+÷ ß<îE¾eü ³CÒ “ýžp/ÒÁvñ|`Ý »a]Ðm9½ #ÙÖ>zGs9ȃ¾ºÎݰ¾¬t©@›I’Fç$;kšZ“ÅÀŒ ¸Â˜y6‘HôsYß™¬›-Ô¼.š;W0w¥I7‡#«—¹\ÒÊX[EÉ>Ëq Í'Nëh¨=±®µfEols®øâå4Âd_ßv¢ûvÐc]4‡[íéÉ¥:R(gÛãZkø4‰.ÑA鸚¦†Æ•\GW/‹oBfeèj¡‰Úl“mF=æ0Jç3—Íœ ÒH5ÁE©wâóßÕÇÍkÕQÿ]}¼)µ"‹î»úxs3_ëR d¡jŠÕ)· Üg­´s9d¿;ò²IÏëhow§¯Žp-Ø”ªÏÕñKÒ‰«ÁõTµÒßçÔ§X,¬b›Ø?1$}rÚô¹õõmµ­É¤ XÜÚšjUò¨„ïeœ/·´»%pKäâ¶t²à‚Æ®­&²‰ ¶¢¦QÒÄÒrJª½¡ž³Š9 éñb‰¹°ËXt S¬oWmÁ‹Ø+”¸¶¹ÃÕoÏû¦>ö”=m» _o§t4-aÿ\ÜÊyrýÓòtn'—¶Æl¹;Q(»à£¹¼¶5Æ|‹Xÿ;lDE‹9ƒš–lloï¾KS+X°ìP½áA¨jaG+̃lO.ç~̸RçÅÍÖü“SË!Г‹j–By¸¨…½ä ËÛš‚3,yÂæê/<ÏõØ$ øXÁ Ú÷zKÛì-ÍÅ­™èÉš¸lÄ–Ñn7 gWL›Æ¹›ª¶û¦Æš•ªåL0e.J¶if9¯ÌÍf8uþ2®;è³&€¢º¥ÌñT-æc¥`÷úÍM@0]bˆ nQH-d“„k –ù¦Žjw×Ô;Û¬É2.=&²¶IÐÕDT¤°±má<`"ÜÏh±ôòKp‹»úÙÐ%®"¸­¬?šÓ«iïJ(wšsµóÚ”jt‡d}nL5õ¾Z9º³i”icéZec8ÑØÈf°lȾ¿$¹T5¯lëàêi¢05X:>*Ðw®Žnµ0hÅ„á¸Ç'M¨ nPó8wTû\d#[Ï….qÛÇÆ4Qk21’ƲԚÛ$òú¾o^ÖšéŽ}i›òìdÿ즕 ˜Ñ•K;Ü]ìÙMÕädz‰<Ë5oƒ. ÅÒËûwˆ›ÓNeOšèá>êk¡‰ —¾NÃî¹9&Ú§&djUÃØIÈRpõIÁ.uË…yئ¯ YÐiuYÜwÍCs×66å]j'~[]åâ8‡ÓøymJ¦ ÝœlóÓ6›¦VÛ—·*ëI^!åë¨ÅÑÃ}ú†yúÄœ%"ƒjV§Ú:=ùÄ*ü-È&ôcʵY´)Iz˜ÎfÏ®immHµ>ür~×Ôþœö=΋vU¨ë›UaÿøÁÊô{™r—bw¬1ÇÂ,è…î¿ï±»64ë¶kBÏvœ9uäb*Ìgö@Å=P@Å{Ñ Xƒ›Ü™°o Ÿ×,C“Çk–¡Ñá5ËÐMñšeè£xÍ24¼fšN³Ìhæ8Í2t4¼f:<^³ÌèÀ8Í2ôDRí&t)œf™Ñ•pšeF Åi–¡gâ5ËŒ‹Ó,3"N³Ìè`8Í2t‹¼fD^³Ìè¹8Í2´‘¼š/^³Ìh¤8Í2£óá4ËŒÓ,CßÇk–¡â5ËŒ›Ó,CßÃk–- §Y†æ‘×,C×Åk–¡Éá5ËÐCòšeh"yÍ24 ¼fY,-§YKÏÄi–ÅhƒxͲD³ê4ËÍ•Ó,K4N³,Q_œfY¢šfY¢\N³,‘’Ó,K¤Á„. 1ôˆxKL:GF£ˆZKhCMbhï ùB ]ôRˆ¡c‚v14f¨‘Gh…C3íbhì°—ˆ¡3ƒ¾1tSС!†N‰´XL ý#´iˆ¡yC߈I ]C#‡@ =ôžX‰ÌôžLŒ=…þ1vŠ4jLŒ™G†óÉ,cNÐQ!F¥3ebÔŒ6 1Þ£õD v,1i£½b fŠ4ttOˆ¡-ˆ61ômÈOŒ]‹ 1t‹ØoÄØ»hR“ö š@&†>sJŒÝƒŽ 1vOÄÐ:¢'ÄÐÚaÿCCM'bp•ÙŸÀv=šSÄØË`bì>'YÔÞAû‡óéÐ]Qó m,£_Ò$21j@ׇ:Aìgbè¡C m+v 1i8mbè$¡ãDŒ=áèüEí ö1é+='bh7IÆÄ¤£dt‰ˆ¡ÿ„¾1v0¸€ú1î)Ì 10(…ĸ5°—ˆ'ÀqÄØ©èKc£3H lŒö 1°+ûœ8“žï}ˆÓÀƒÄÀÌ>10;8M Œ†%1öz{ÄØËèîc?rÏ!ÆÎ[c 7FŒ¹áîAŒy‡cØ9Äè³CŒ\èËC Îim5Jç 9bàT°›~M©à}bà3°-1n:èÉã.C-ĸ°Û‰1OÒ–31æ }9bÜ ØÄÀù`"b`uæš8ìL ¼Jˆ1C`Ibìr°1ðÚoÄÀEÜyˆC¸}°o‰1Cô™˜fÈŸüš¤õæ‚MìôÞL ÍEwÿk¢¿hªñëÇ{´ÕL -DwÿëÇÎFSÍÄÐu÷¿~Òs÷¿~ÌŠÑ$¦YASÐÄÐ&u÷¿~Ò'u÷¿~ìi£YG ½LwÿëFÕÄÐßs÷¿~Ò t÷¿~Òës÷¿~Ò×s÷¿~Òu÷¿~ÒQt÷¿~Ò¿t÷¿~ÒWu÷¿~̼Ñ+%¦YB •_3½CÕÄÐEu÷¿fiœºû_3÷,4RM ýBwÿk–»ÿ5ƒ?ÐJ51a4SM ÍLwÿk–Ž¥»ÿ5K3ÐÝÿš¥eêîÍÒxt÷¿f醺û_³tbÝý¯™=bîŸúõ—ž»ÿõ§GF땘Þ-@bhnºû_é–ºû_i˺û_iºû_iEºû_iõ¹û_郺û_°”Ñø$†F§»ÿõ×¼ºû_Í«»ÿõ—Þ¥»ÿõ—N¬»ÿõ—Þ¡»ÿõ7­UN@“ÔÄ´sѾå7@óêî˜1ôDML=E×ÄT'£&†F«»ÿ žª»ÿ P_Ýýo÷£ÑHŒÝãî¤?êî¤ïèèî¤×ëî¤wëî¤ êî´{Üýo 4 Ýýo 4€Ýýo txÝýo ö»ÿ Ôu÷¿ÜÌŒ"1ö¨»ÿ äöcôƒ‰é.ƒž°‰¡wéî¥[éîÁüFã•Z¤îþ7PšÃîþ7PzÁîþ7Pz£îþ7Pséî…'Üýo Í^~-Òdt÷¿v´Ñø%†v°»ÿµHÇÔÝÿZ´ŸÜý¯EûÕÝÿZ˜£IL=2š‘ÄôÆhŠC_ÙÝÿZ¤Åêî-Ü€ŒŽ&1´3Ýý¯E½w÷¿í$wÿk‘^±»ÿµ€É /€š´îþ×"=dwÿk[¢¡ibÂiFX¿AÒ«t÷¿AÒEv÷¿AÒ]v÷¿AÂOîþ7ÈtwM ýawÿ¤¹w÷¿AÒÅt÷¿AÌ›á)Ó<½bbì0wÿ¤9p÷¿AÒÒu÷¿AÒ;u÷¿AÒu÷¿AÒÌt÷¿AÂUîþ7HZîþ7H¸ÊÝÿ ‹¸ûß íwÿ¤9p÷¿ÁÒ{v÷¿ÁÒ½v÷¿ÁÒœv÷¿ÁàtMLí_c&Üýo°ö»ÿ –Ƶ»ÿ –Ö§»ÿ Ö¸ûß`æÐhSºûß`íuwÿ,Ý[wÿ¬Ýàyêaí¡kbìxwÿ,lwÿÌ==YÓ]­X~@WÃ!Îv÷¿!šîþ7DXÍÝÿ†H»ÙÝÿ†€=Ж51ô‹ÝýoˆtXÝýoûÎpRˆ±Üýoˆ4ŸÝýoó†­‰©×hÒš½w÷¿!ÒTu÷¿!Ò×v÷¿!Âgîþ7Dwwÿ¢Þ»ûßíwÿ"àî­Ú…îþת]èî­Â©îþ× FE;ÜÄÐw÷¿Viw»û_«p›»ÿµJÃØÝÿZÙ×h›ýv÷¿Vá6wÿkeÞÐ%71zìî­|£QnbÌ´»ÿµ ߸û_+w£1®ßPÝKÜýo¨4–Ýýo¨4ÓÝýo¨t•Ýýo¨î"îþ7Twwÿ Î4úÌÄØgîþ7|e´o‰oÜýo(8mo0"bàowÿ*üíîC…óÜýo¨tÝýo(󉾶‰uÜýo(5.10»ÿ 㾃ƴ‰éžb´¦‰SÝýo˜zìîäéîîĹÝýo˜tÜÝýo˜0·»ÿ “–»»ÿ S/Ýýo˜n$îþ7L·wÿ¦]åîäï»Gk·—g.~ý£iIˆpùkq¯‰ I«uÿa´—e½Ê2ŽŽv·È¢h"\‡f=ÓrŸ•Ú›KÝA‰È{£b‹|,ÚÕ"wES-r·ë…"ºÒ "‡EOµÈü¨À"g»ltå“=vÙtåõïè¥yý ×"vÙ!/³=ÞçïyI/²~5'N´ÓVŸm?èýüôYrû ·mPݰBèë Qæû€ÛÒ#û ³M°{¸ûÑE_ÞÑ"‘õ¾Ø®Kù>(¸}ÐÛx`¸`ßrû <´Åð©ì>ÈäûtÛúL¤ôgÏI¹ý–>WÞN´ÁGP_*ÐgÜÍHh°aúé'*Ìž]9BD²gEù¢*Üf<üër¦Sû!}bêpº*½¿nÛ:»ë8±fyÍxXYe¥iûü?ÄrŒï Ž…sÏ0Ý›ròCcα°±ÍômþO'¾¤µ¾ˆÿÿ»¯ˆ¼pši4ýŸù8}þ<Ó}ú?u˜ sžÉõn˜`¸¨çgê¸àA¡ën{FÕ_º9×µ7ý¿%bêxæƒSýäÜ÷1°É/ú?ë#ëÇ£OKß­£OdñÔŠJÓˆûÿ挹jC‹i”ýŸy]“ª5ݪÿïÇ^4>Šú¨ƒß”ÚFlýŸ¾š:žYóЩ“‹ŠNjغÇÐ{WÍ-›uþÚ†ž@”'Ïžeªyþr§YjmOç—ÍzhS}·Ž>à©SŸÿð^¶ð¡~,›•2U»ÿÓ>*飻êXýÀ„<6Y_W/»3þ¨yiú_}Mëè;àB";T}ì³>.-}O\66/k|/ævéö."¨z}ÔÁo Cò¿ûêäj£ØFÛÿ™Ü<âIš†ž¸ôqrSî;Áõ)q{í[a“?ù{œk9fÈ› ZÛÓù¹ >XGŸì~o:áN yKø©'<õÜ L%Wþ1¤£ZÝä3ž.þ‚ò0ãrÔäBú?ßàöNÇ¿Þà¯ãû7¸Çëøþ î;u|ï÷X}wÜàzúÚ—Ã îÁAû—Ücu|ÿ×SÆ¿Ýà¯ã7¸ Hyn)÷»ö©3ïÒK×ïã†â½¸áQþžsïù}Ö'âÆèc»s·gÐî_Ÿ·¼½ í_oy!™¾ny'ÿVöað´Y ÌÂÿ÷éô=Á.ê;€Ô× {fÃNaîeN{k¿éô=ÁÂÁ&ëÿýÙ:þÏN‘û£€ö£ïöŒÜÕþ¿ŸLøÍ‘äàÔúoˆ@…<<Ñ?@×ñ}Dðxßßäß©ã{›ü±:úØä}/ÜòzúÚ—Ã-ïÁAûDðXßG=eü"x¼ŽÜò($­ãÑ3“êpx„s`ë‘á‡~±¶ÍŽûêèà–ǯ¾.“ú囇6¾ê¸x‰9yàwê’—žÃ̃‚Eê}|¿þkoIî¥`æÿ­Oç?¦D¡Y=TãôñüÇì(æ&›kü¤þË÷´$¹Š[è^õq%ÿ½iâ®~ê>úïÒ9ãœÿVã*þƒG0cùPGaF2Ù"vòXçòÓ§oªq4;81C‡ÿVãyüÇLª1àÝ]ã§ôÿÿÎÊjþcR¶ÏC5ŽÁœdbÆVÿ­Æ5üÇü*f7ª±Yf&™Å«q-ÿ1ÕŠ‰Î‡j< sÉîàóùÏi sžÕ8ddT¸Ök‹ÿ§/à?&`1ýY«¬=fÊÑúÿ÷ü:þc.Öw½¿¦ÿ꣰xÁL°þ[×óÓ²˜}¨Æ¡œüŸXâ™üGó£ÕøûñBþc²S¥õ?­ÿê!FSIØ«qÿ1o‹YÓ‡j< ³®ƒ¶å«ñ"þc ¨ÕØÌä wþ[ùÙ\Ì¥>Tc£ ð:Ó¦ÿVãÅüÇÄ.¦Uªñ?f~ÿ1Njևj¬Èlmfaò_j|ÿ1Ý‹ÉÖz¿®ÿ‚˜ÂÆ”õ­ñþcæó®Õ8„›°1Zý_k¼”ÿì$Ì¿>Tcfå43%üo5^ÆLc*ö¡ÿcæŸÍ$ö0+[¯ñný×SÚõ†™ÿ­ÆËù)bLÐ>TcA¦X{o¶ÕøþãïsµÕøðï1üø\þcâÓ¶õCÿ•Ó°Î$í¿õñyüÇ2fp÷Õ¨ýè ÿ[[ùédLæ>TcÓØÞ°ê¿Õø|þcfóºÕˆÑÜÊÞ>®à?<(Lñ>TãÌü•üç¦n{¨Æþ2}üïx~ÿ1õŒ‰ß}5bJößk¼Šÿb¸^ãoêÿÿÅWóv¦ƒª±E¦žÿ½Ûù42·¬‡j\^)oáütãÜÅ´ 1®ÞÏ×ÈK×ÇßÕÍ¢ø@Å-6Xëã›ù4&\Í®~ñRý× Qz/†{þßjüiþsWÄh{½¿§ÿÿwVÞÂÌýÃUÈkŒûkÍûQÿÉ|+ÿ‘û…ïýPàX0³úÿVãÛøÏ,ÃyÚSã£sò䬼ÿðQDé» Æ›ù?ny}_ÿÅ·ö›e†üÿmVÞÁäX1[_ñ?úx ÿ1¯€Yû¾ jüþo$„ñûæxe¿¯ÿLÿ…W¸ þ;×çgù/ô‘Lä÷ïë£Õ3ø¬þ‹Þ+í†a[´«ñÝüG/súiiÇŒ¸Cÿÿï¬ÜÊô¸½wõq螟×Q …‰Æþøôñçø–\æ®>|à7õ_0Vú+#¤ßð_küyþ£3´>ŸÓÿÿ;+¿À4àÖûèjœ &ñŸäÛø„5|·®[q·þÿß>¾‡ÿhÀpO¿“þëö¡{Áÿ¼áü"ÿÑ€wñPÿÑÇ_â?ܮӳ™ïwþ[/÷ñbÿkßË4tóÝÓÇ~úÿûø>þ£À=¶«ÆÑWœ¢ÿÚ)âøOÞùûùw³‡jü>~€ÿhÀs«ÏJ³þ+¼?ø½ÿµ·ó a«j|´‡OöñƒügÀíõqfa”½ÛéÇúø!þ£Ö}¨ÆÑänúO—ó €?x°Æÿ˜•;øØê±ÿýVûþ£ð‡›kì¯ÿÿ·¿Ì4>ÿHÿÞÇò ´ ºjÜÊKõ_4Lñþ†ü§Òüëˆg³§õÿÿÎʯð €/öÖhp·Úw½‡=ürÈ>Æ0 iÐÇó ¸)õ[ôÿÿÎü]üçvÉÛ=5>ÚÃ'ûø«üGàO†4èã'øÿRBð¤û.èã'ùOôëã¿×ø)þ£e >ݾç¢)5|Ë~ylV~ÿhüù}ü4ÿ¹óþŽ5¦;ø?fþ×ù–úxõ>ÒÿÿÛÇ»ù–\ˆ‡jlævX’ÖÞíãoð-ƒ¿Ò ¿É´ þzsƒõ_¸Nø¯òŸ™ßâ?\:î°Õø}ü ÿÑ2m_Íð Jÿ‰í~›ÿh|uHƒ>þÿÑ2øÚƒ5"‡Ö´…WôX—ÿhˆKЇA?Ë´ Äy¼Æßó¿Ç´ ¾±¹Æ!úÿûøûüç&7þ¡ÛàKT„9þkÿ€ÿhÀ‰è» Ÿã?ZÒôÜsG½RÿʼnÒûòêáü!ÿÑ2ø‡kü>~žÿhüンò2pð8qÿþk¿À´ þis­úÿûxÿÑ2øÖÃ5úO¼òEþ£enÛSã£=|²Ä´ àvÔkDŸõÿÕøÇüGËM«¾ jüÿ¥e`dsû.˜•?á¿´ Œ*ýž>Ú^g'”toý¯3ÿ§ü—–ÒÑûjü>þÿ¥e`D÷«ñ߱ݗù/-ƒXÒÊõ‡éÿÿíãŸó_Z±tVª± îTQXö¿öñ/ø/-ƒ8sÃõÿÿöñ/ù/-à |w ÷¤u‹=™ÇúøþKË –yß}ü+þKË vZá]Ë¿ß]ÿ•];!Oò¿öñ¯ù/-£OñPÿÑÇ¿á?º‹ðGªqX»4ö¿÷1–Ö2ZðÂîîɳ§MËè9Ï~žþÿŸ>ÆÒdà‡–L¹oæõàç&_0Rÿªm¤Çjôz@hÉÔkœ¤ÿÖè]"õÖˆ&?ø¬]5.nûtÝFþwÑdà‡¿÷ñ±Ñdà‡Fjßóˆ&?p[ß5ú» º¸}̼÷„.nß}ô~‘ÈÕwÁÌ{»RhÖö]0+^ë ¤¾ fM~è—ö]ÐGïßýÒ¾ æÑÛcßóè=l¡•ÖwÁ¬ø› šQ}w j<úÆŸèÿÿ­m ~hFÕkü[ýÿ¿5zãWÜ'ú.˜y´%øqŸè»`ý-ŽûDßXÂ[í‚CÐwÁîò^7¸ô]0Þ÷²¾ úˆ¶?î,}Ì#Úü¸³ô]°WЖÐ/´ï‚>:cw±Rô]0è KƒÌèãÕ5EþQÿª‘[õc}D“>r_©Ýµõà ÎÒ“5:} ô¹¢á˜H·àŠþ?T#Xý±Ý,źùî™Ç‡êûÁ<ÒjDc»Žíà,>Vãc}„ãLÜpê5Â'ü5Âq¦FnQ{0jŸ5:-«X¸«ï‚ß0&ê»`Và8Sã¬Í5î»ü F8ÎÔˆmß{Ž35â  ï‚á8S#žê5ÂSý5Âq¦Fôú.¨Ž35â  ï‚Yq>biêô]°á8S#Zú}ì.Ç ‹¥¥ßwÁ¬Àq¦Füô]P£ÓýŠ¥s?h£>æ`êIìôÞt½ÆÜÄ×ÿ¬ÑñxbêêàFçƒÉø;¨×¸ÛÞ©Ž35¢«ÞwApœ©Íó¾ jt>bqÈú.Ø+ÎQ,ÎRß3Ç™á}Ôk|̯ד5Âq¦Fø}Ôˆ^;5¢]¯ñ1ÏAOÖèt¿Ð°ÿŸ·¨Çjô^JØó}Ü»œws#ì»àŽê=o EÛgÁ5ñ÷`ôÈkwT3óßPù=qLü=NÆà{öÊßmñŠòã½’˜ÃPÃí³àöáÝEÎhŸX;Ñ^¤Fø}Ü>׆ËÐgÁm0ñwm¸ õ{ýDü¤Fw{7œÑ¾ fÅßÎáŒöYp'J¤5HpFû.¨­Aj„3ÚwAh R#œÑ¾ æÑi_Îh½F4žþ_NWÕpFû.˜´©ÎhßXÂé‘ÎhßóˆÖ 5‚û.ÀN'ÝpFû.Àh R#Ú}Ì ZƒÔ/µï‚>z¼Ô¾ úèy8ðRû.¨ÑópÐUï»`V<îkß7ÏÃ÷]ÐGÏÃ_Ûw–ð<øµ}ôÑópà×ö]€»<~mß»Ëópà×ö]0ž‡¿¶ï‚Ýåy8ðkû.˜GÏÃ_ÛwÁ^ñ<øµ}ôÑóp¸§ö]°W<‡{jß5z÷Ô¾ æÑóp¸§îá9÷ P#þ>äµ$Ö ¤î=ð—ô_åKS:‘Aý÷¨ÎR"òZëò¹ý‰æÿá+‘¿|ào¨[ËéWéÿ£óòجàïC>HbÝ@êÞ"Ã+OÖˆ¿Í[¬H^£óz¡]à³^=½Çføt#ÏC5åÿãßk¼‰åµÄp‘ë5:-ò³ô?<%ò"¯%†‹\ŸÇÇöü“óˆ‡y-1\äZÑ;OûØ€.\ª?òŸúˆ‡Íšá"÷]ÐG<„|¹<ÔÇ2¹cïôþ?õ!Ò®7\äZ©qôí¿õÆùdßIòsb¸Èõ±‚ŸŒX^‘þkßEòsb¸ÈÕXÒ¼»;â¿Õˆ̓á"wÍÊ~_ÿí=øÉYÁ ‰üœ.r}¯ô P#^H>jžÿê{þëq%i´þû¬à…„yæRŸGWã‘ø£Hþ‡`"Ÿ"ò^dxÂiÆc‹©ñsŸ×íÕiôÿkøQ †'üЬÄÝ€Óý_kħˆp®á ×gþ±{ד3Oy_1<áz¿×™ÈÔ¿ãG|ŠÈûŠá ?TcQ;úxJäSDÞW Oø¡›„‡þKàS{ð„ª±A³òïûŸ"⋞ðC5¶H;¥×¹óc5âSD|QÃ~¨Æ’n<Ž+ùo5âSD|QÃ~¨Æ~Âÿ¾ñ)"¾¨á ×±Äßé¿ÎTà¼;ý×ñ)"-†'üPé›öú5|¬F|ŠÈ_K,_gõ=ÿØýñÉ=O|´áë¬>®Æ¿Á¿ïy|ŠÈ_‹ÁêÕX’ç¼Þþ×ñ)"-±|=Tã¡òìîìÿV#>Eä¯%–¯³z¯ÿÂ+ørø÷>âSRÜHªÑxíùwŒŠOnYà‘‡jlŸ‚ÿµF|ŠÈ_K,_gÕ˜èÌýï{Ÿ"ò×Ë×Y½Æoê¿î]Ìɿ׈Oùk‰åëì¡Íʿ׈Oùk‰åëì¡WŸ¯Ÿ"ò×K ù¡cùàéõ®ñXø‘¿–X¾Îê5þƒþë-û÷ßw>Eä¯%–¯³:&¢¾Ç~a"|ŠàclØwAx‘÷ã•ï¡YItŸ‡ãñ_g!ò¾ËsY½ÆÔ"<¶ÿ±W ‡P#šèdÔ82ªŽÌ£<™'ô ‡R£ðg,Ì3d Æ÷ïõßr2ž¬q5ÊωÑä¨õQ^¿Ÿà=Yã¡Ô(¯%F“£ï‚>N¤Fyx1šÃk|Œßõd“¨Q^dÌ]£ï‚'S£¼¯Äò0ÕwÁ¬L£FyF‰å㢦)ÂîúŽ6Ê“5N§F½3¸ª>+qôŸÀ…1ÔˆH¼Xý×y|²Æ™Ôˆ÷´ê³ò˜vé“5΢Fy_‰å/j¨jÄ›|Î!ûý¢—F#²§FRÛ+z Yé`Ï·ÓGÍ\,®Z7ïãs×é¿JQ…ÿáµàõ%ðšTT fÍ(Ëpážs«þ?ÚK|ìë£÷VÁ¬ÔöŠ•¾ö¼×—wÕç±o€=ïõ%Øó}ÔˆT¸6è[ÛZkçÍ/Ÿž™ÇÙßÓÿ'v—1IØS£×èòšD¿ãõâ }¢‚×èòšÔ—@øüÔ?Ö~>èïôÿÿÎ#>?uwˆåÑè¡WÃ'Ú_7±½ûñ¡ŒÏOÝ0cy4z¨ÆChSƒ¼êý×ß]î/f%ÝóÖÜ8ÿ}½Õè~èä¡+Èþ¡44íàåÀÿÁû¼x!ð6àÒÀ­àÖ7î>+ñ(ɽ—{,wYáãK'àp8Qp–àÉÀ›€À-[·ö.>EÑ5Z—Ü[ÁÌÜD¹YŠ¿l|Vr¯5’ <.yy2ú›ø5C»›~7òŸºéûþÓz|áˆÛ&>[À-x/A'{$ÿGñp5ð¬? #áù øÃGo>þçñaO î±xË@ ›wxúÌ+ºÒè󢙌63ºÆðŒÐæö ^ŸÚhÆ¢SŠF4<'´WÑFÅ4ðè/> ˜ 8è÷iVŒb| ƒ3áÁ£I‰Qt#ñ‚¶#\6ôñ¬€F"žÀðèÚáiŽ?úsèá߆¾úgè“¡E },îÜ|ÐBŸ ý$0úCh÷ ­Gm´cÐ]ឌn º"è~À@7] t'àŽ¡Û€®º輡Æ. :f茡†NwîÜ Ø‹hÀ?C Ž>z° tð1øŽ5h8ÊpˆÙppáÈÂa…€ÖŽÖþÙ¿1û7fÿÆìߘý‹N}ÌþÙ¿øbÙ¿1û7fÿÆìßX^oµcöoÌþÙ¿1û7fÿÆìߘý³Ñ¢Ù¿èÅÇì_ðºîèc£YŽ6:ºâè~ÇìP´¹ÑµFMZt›Ñ F§}eôcvoÌŽÙ½hãâ Ýט‹6kÌŽ­Æ´oáÒ½S©ÀQ9®2˜ˆýýïØŠ_/Žâv^ʱ’ÁFn‡¥;ËÏ.8 ì¾B+@s]Åk9Æz _™žñ¸ýù¿wcŸ{Îì6°YŸ:رo ð0Þ÷ÁÍbçõ}‚}ѧp'ÅÁ``<Âþ«Â3Ó¾18Ùã+°˜ ,ÅÇã,±Žâ}÷ƒ—À=àð¸ fOŸÀ4à$°Ø\–#¥ÀT`&0¸l&§€EÀ àð 8 f»€aÀ2`f‚{ØŠ{w)0¸ ¼‹…ÀD`æ†YaF˜°\–¿€[À*Â(—€EÀeàn° ¬¾ÄÛ8L¶A“¬æû€ÁÀBÂD¿2Ì"–9g®À`'0X \¾g¹À^`0ð÷î`Vð#8’¹g° Ø ìöûçùîõû¢Ç™S‚9Á•àM°%˜“û´ï½ØE÷ Ÿ2?Ú1}h`T£•ÀLÜÇÁLÜ«ÀSà*0–v ·ƒ¯À¶Ü™¦bÿ×ÿs³:~°,n3³ý7Ûš­ÌwÃe‡¼ uÈFïcVúFû%ÑìšÚ©©ÚeÞ;O,?mÇwõôü•÷MÖÛïä…s§VVNó%­ð܉nÎpÏÛ‰`îŧí•s ×ë>r27–SÀúº#õQð[ Ú_;B¨ú¢XÜêì9'ö]°ï¢}—ì»lßûn°ïFûn²ï~öÝlßýí{€}´ïûd߃í{ˆ}·Ú÷PûfßÃí{„}´ïQö½Ÿ}¶ïýí{Œ}µï6ûgߨ÷ö=Þ¾²ïƒíûûž`߇Ú÷Dûždß“íû0ûžb߇Û÷TûžfßÓí{†}Ï´ïYö}„}ißíö=Û¾çØ÷\ûžgßGÙ÷Ñö}Œ}Ï·ïö}¬}/´ïEö½Ø¾³ïãí{‰}Ÿ`ß'Ú÷Iö½Ô¾O¶ïSìûTû^fß§Ù÷éö½Ü¾WØ÷ö}¦}ŸeßgÛ÷Sìû©öý4û>ǾŸnßϰï•ö½Ê¾Ïµïóì{µ}¯±ïµö}¾}_`ßëì{½}?Ó¾/´ï ö}‘}o´ï‹í{“}?˾/±ïÍö½Å¾/µïËìûÙö}¹}?ǾŸkßϳï­öý|û¾Â¾¯´ïmö}•}_mßÛíûû~}¿Ð¾_dß;ìûÅöýû~©}_kß/³ï—Û÷OÙ÷Nû~…}¿Ò¾¯³ïëíûUöýjû~}ß`߯µï×Ù÷ëíûFû~ƒ}¿Ñ¾ßdß»ìûÍöýÓöýû¾É¾ßjßo³ï·Û÷Íöýû~§}¿Ë¾o±ïŸ±ïŸµïwÛ÷­öýsöýóöý ö}›}¿Ç¾Ѿɾßkßï³ï÷Û÷ìûvûþ }Ⱦ?lßwØ÷Gìû—íû£ö}§}ÿŠ}̾?nßwÙ÷¯Ú÷'ìû“öý)ûþ5ûþ´}ÿº}ßmß¿aß¿iß¿eߟ±ïß¶ïß±ïßµïÏÚ÷ïÙ÷ïÛ÷Ø÷çìûíûóöýû¾Ç¾¿hßdßlß_²ï?±ï?µï?³ï/Û÷ŸÛ÷_Ø÷_Ú÷Wìû¯ìû¯íûoìû^ûþª};ÿÖ¾¿nß߰￳￷ïoÚ÷?Ø÷?Ú÷?Ù÷·ìûÛö}Ÿ}ßdžûã,ûvø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ±áÿØðlø?6üþ ÿdžÿcÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿ‰áÿÄðbø?1üŸþO ÿ'†ÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿEÃÿ’²·ßÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿ— ÿËZývø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿lø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø¿bø_xí·ÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0ü/[×öÛáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo0üß`ø¿ÁðƒáÿÃÿ †ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿üM¤FÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñ𿬷Úo‡ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿Ñð£áÿFÃÿ†ÿ ÿ7þo4üßhø¿ñ²r\å«hnO¶Ö×Ô&g5,áØ¿ ª|y²¹¹ô³ê’s’KkÚ1uÒ¬ÙG'ÛgÕ´µÏ¯,ïlo­¾±töüdû‚ªš%É©5mIˆ÷&ÉòʲªšÆ§BðÒûåµ­ -íÇN¯¬i¯]VVWךlkCªø©©TÓ†æºÔ ôˆL!'-©Sy²Ï°¨¡uZkRe—Ѝgqs{ëÊm5K“H*~B{²ivM+γžBÚãæ×Ö4’r³Ú ÏJpòʤš“èSëùÂTS Áíó’õµ©fÌ,¯œZYÓÑ–œ—¬MµÖ54/å°oú¶h~Yc²µ~ŠÒ¾¼¹n~ª£¹nvM3…_r\²µ­ôÅ“f646´'}ëFVN—l®iJÎ_Ù\‹’„ÊXÑZÓr\²¶=ÕŠ‚ó²©3yrfª±²¦µ©Í%© wmQS/nœ–j$M僼8=Ù–êh­MÎo8‰¾¿ÅzÖ‚ª†&â‹Ýˆ,kmhfÉ_epQrIÇRC»ÏíD”Q£aªÇ'kÚé×’š¶©Ö¦¦êÀ™–šëSêL¿—ÕPÍYËè¦(b§=uôÌù8Àz~EsCûÑ­5õèŽ7¿eZMûìÔr&/ªœ:½Š¬¨‹§mêe|fzÂe„‰º,Ù:³¦¹®‘Ø ƒf!vV%—OíhoO5Ïm{­>k4Öj¨×'Ù¯œQUVÛÞ°Üm™ùÓfÏjhkO6#ævÉD°—°–1ê[üô©¾/ÙIcÏ ÈÂÊ3k–"-dÂ'Ï^0fôÔºÿÔrÜücgÖ1mßž6›&¬m‡c²¨S'״̤i²À²|µ-ט¨›ËÚ[QóYáÖÜædëôšöÔª‹[Ûç0õǵ¦š*[Sµì´åÉÖ†šÆ9MK’ þ³Õ»- ¹­uñnFÇhÅüÙ³“Íó“ìñ&—Mõ3iÇ©²n>O_Jû?<+Å^[‘:º1µ¤¦NÉÉvæîR¦õ¢öd§š·©}t«êˆ^7­¦‘UâÝqÍÌÓÅÍ Ú—ÍgÔØ›•ÓïjúâGÝ|7mê|u¹2’Muz[û ʾ0Þecx5jKrFCc²b:ûÓ¾{)«iSª-yôÂTkc®"ÎS%'4×U¥Rš )L.I5±`7+µôeÔç-5ím¬Ž5è¯_Ü’l®km`WHdœ‰X¸,ÕP›D¡Ð ¤¶ÏsÜ|Ö…C¶,S“ /·å¡‰Z ½]-Ós-<7=›´ÄÎ>…"ö°ºq^ªSëØÃŽrÄ»Sh¿›YQ5ÍÀsZG²ƒf]ã^,˜ÚÑv\M+)—¹øÂŽÖ²×Ûø©ì»µÉfZ!§lw»TËWÂÅߟÖȘ,K5®DÒ©‚ûÂ5•Mê ]þå…Un)ˆ.e7ÞjƸhŒ®cèÏgÃ0$;|rª.ÙO’DûAg‹–ó%êó+]µ Ñ{’w¨µµÉV›‘|·²£uir~ %Dzӗ'kZcfnÊo=š­ù[¸¬¦y)ýtFcGÛ2!‰Ê+gÎ?n4seTòNÆÐj>|OE3¬]Hƒ«lèL6ަÍô¡ÍÉ€-»™¯6ȶ¼}%Ë ²tú슶٠­­)ÀÌsTuS¾bYÒ¡¶¢0”ƒ/§²'Ö¶jXen`E²©¥*Õ2;ل¶ÇQ¤t€lJ‹¦Î*$ÓYðENIµ7Ô¯tù WT,˜]³t>¨Ä÷eW€ÅrŒ•Ä —/ëhŸ¾¢™ùº„š¦¸šNŸ;[%N…cl!âÚúFíõÕ'¢†ª)33g‡lY¼,Í(—ÿE°lmÓ –/`I’_~ºUõîÊöÑnŠ"°˜ ]ÐÒÒ¨ÉF–ž„_‹šZÊ›— }lriCó‚–:’Ωœ:»æÄäŒùó[’µ®øBOò¥5mqs‹ÃÈn!Ò²ÆûóóÀ!7á‹äÒ…V ˆq€F$I‹‰ó¥ÉåIÖÉóËÊZ¼¤¦I[8¹jþ´ùó¦6R¡´Ö-$´ÐãädçÊVŠRÕ‚+t15k[ ŽcÚÐ6/Ó˜˪¨$]ç+ÇNŸ]Þ,Ì ¾ØP³>S±¾¶F«Àì†Ê‹ûðäàÉ/hÓk£«¡¬°¥l°K…xЧxøbQK{ŵi™-€dך0‘Œ×Ð9šaÕ$ý­]9Ü_ &›ö­AIQ¯OO?ÏíhCÁTká­‡ZÂæË¦ ¾2Lëß5 ²ë-U%³ -J–©™®…©dk­ì¼ÒÐ\Tã0‹9 ÈAÀÂÙi\8×!t»²%’ê•9ÁT>ï Ö2õ *í1Êd6Ýò9nÚl·¸äXæäŠé¼>µ¾€hN •K+šÛ\¤<£ž_Þ¸x©p£ ü,kÞº¼uú´r̰ƒ@Ä‹;“µíñõ¥ÙæsQªƒ¸©·3êÌ©ËA±²‚ãÏ~P—w´´0.}µ¸ËèÊ«æ·×¹œ•[„€ƒÑ¿Gk¶€u%ý£iÂLÁHé"Î:$r]/½;Ÿ>Ãfó÷@ùÇrTºÁeS…Ú„ÀÖ/mæ¤rY<«åÛÝ$ÛQ_µ”¾ªs3´1έmŸÞàõ¹­+ñ˜²°±¡¥l‰N"I¶[‹ºG\V½*.ø¬éªÇKœ™ÉŒ¿;'¹¢¼©¥}eæ>R\¯.kY/…¯V’òt6¢`®d¯æ.®ynf‹Æl8‡ýJ7t l²…_Fî4bAÂfÄæOO²EW'µeYh“Ö·Eþ¿oøeeܤÄ:·+ê¬iõKu;Qê#uÔ:·.Fëñß Ói Ö¶N]Ùž¬ZÙÂtr7‘K[À÷z'ç[‹fÛUÀ/ïøSAIâFk 1=._š©'Ç2̧šAÒ“{w§¡âIñ.[Ì„kÖ™}8¡´±¾}%[+\ŽôòðöÊÙKÓ׺ø!¡EŸÇ:^¹SUåeå¶JÀPÚpéÞ½ÛÎ\jÔ:œøhfÝ©/>¡r^²q^[Ë´©(€/oLµƒLù öÕÉžšŠ_ZØÊ¶\ÚB]þª'qu3 Ó9“¬íIJŢÙÓ–%kO´q1´r—Ç­éý}ÜrÝ¥j;”,Tž>AçÌÊ€ÚÄ”÷Š×Ú²”O¹F­4—.·÷ ÓR-î°R.¤¯ÂrÚA ¹Ⱥʰ›^r<ÙÂÎÔ\‡´,Oí`ÓþE|›M¯;§ºuÂp/dh¤ò`àÍšY &»p“ï 0žÜ¶Té+eñ¥ñLdei¤š¸\W)¹¯Yî–Ž9P¾)ž|áR/âúpyC3sŸÞ°$¶¿ljyg­»XлÃK‡Ï™b`¤Ø/o`;,_–5$?¡¨3§Mug@®`½‹Çh­éôAÃMÓjØ[jyñ‘2VÏfÆNpJkøÆÏžÆKG¥÷‡yà·GåµÓfsM×ÙnqóÒÆ†¶ehPØ–.ͧ'ëZk8ϵõ{fMcòƒóÜÎwk¢<Ù½6713 …½TÜ‚æ:}êŽäNL||gï!ÀÎxiŒ À4Ìú”±rátá ]¶¢é‚öbr',ͰæùšáèWu:' NÈ´ÇRuÇ^ªJoçÄfa”¯C*¹óe3[¸YÑ_zÊçÅ7X;) Æ!äoïÚ ÚÛ¹¤%óX7]µ4*$0 ]{_*#&û‚ŽN®³F㬊 E”÷r V”SƉÊ8Àa3f(Çħ¥ûµ(Ù¼Òöà©rÕ‹kuV•ï¹&œ8½ÊãÊÊ?´´74·²"+°"í1çþi£u6¿¡¥©ÉV¨¢ž»›ƒÉ>ÂÆ”k¸Èщå[€"…ô_æ\Ç`½lzHe}~½•°ã>ÌáÄ]*Jà Y d°_“LV d®Yúé 4:;&ä7å¶oÌä^9¿fyúøîNáÚp2²|FeeG»ÛéÑ9þè)*7d“?#bKJom¥ÀIqŠ!n»*ÏaƒÊs‡ªäz»Ê]ÌÞOŠ*X‘îeA7¾iº4©&š{ÄYÓãJ¾îoÓjï,M ´hÖÔ.+,Ôd‡ k£ƒuYX5uA»V$í•€ë3µÆâRÇ}à2«ÓM\ wáè«\ÐWÏ®iƒSRöØGºÇ˦.hnÁ3`ºé{tg¬cýŦÊÃÝÅSkʨÒeî= dI*ŵðÝ`§Àô ©”Â!ñ–4GZc;zº£èýÌq¸“½'ÝcàÀÑäle½PئtB2îõ_ÄWY`^By&ÆÃÊ‹gj–4€t–ÎtPINðÜŽÉV{yvz(Ýý¢vYííX²Ý\ y—/k¨§ð ÐØÓp‹ð‘ð…v4 »l5pö÷#îHÓRðO×d!fæÎìþ[‘ŠéªKFbWÃ'¯JŸ™ès5y¼®xË80\"ôk:¸(µ‚)Û5c¬§‹TžâŽbº'ù5'Øon ¸ƒoäòYø§øâ雩À@—¥jí¾´2³sFsmMK{‡îúþQôeåó;ÚH´fBVþ¥2Ùì`¡ÐݦÇ('¾XkÃb¿ÊD­4ÿ+tdÌŽ¡²„(àöÔÒdóRnÑnnq¿,ÕfÇ_ Ñûsœ»ÍØÛXôzÓ´ÀêÐÅM–ÛRò‡Ž”œ¸ìqºe^RHá2ÀÇjF<º^SG ¾6ìû¦©è”S8ÁxK,{/³ ‚ûUy¯™îÑ›õØô¼tbÅ‚Yä_k§P&®ŸÕègîÞlár.hl¨i‹)ÍÚÈ”±¡™bÿ–à¢AI纈…L¥¹Ó݉Â^UòñüœpÁéŽ ´¾”*p±l&~bÜØâS´DÔ ³c“Óu@ñ8,ž/&Éòyøõklgïz†¿uG ã×7w´Í©aŒ¶eœ–Þß=÷gáòÅê·.B\vähÀ̲gÄÿT§Ó 1>*Ýò D‡Ð\Çkñ@Äa|õêbg8¦Ë³§ùëëÎnNÑZÖ»kmi™Š´êRÌÃÓå‡Y’±ÔÀàk§‰þAAÚW)—fŽ*wf6$ÀÕÅtòøCÍÍ€Ft}•Î$B òVdÎÜ\Ö/éhgmfj>dÐT£~~^3Eÿ1´Íó…ÓXyѩǀ Ťø­ø*á:ZþAf…[¾ÍÔ©œK/ŒÙjO™U j®R0a6³‚tN;mVY弦åeUÇÊ|!˜Î—ó;f;¥\'w‚ü{J4 Û€ÃÒç„­/a1Õ ôa®Ïé9Ãì¦R¢rŽ0é5w³“ÒÕž-,ᢚ¥å®ñæô|ÜŒFø)×VÍž&à¹"ÙÚtL’Sqôîéªò_|­»OVϽ•je’ëÝG7/o Mº«¶—•ƒê͸ßCKÏ‘;‹a»¸óà3f.hÖɘ„½",e1ìzˆTú¤¿\‰¸¸xôb-eG”; óÚÊ ?…–d±Ä¿ã)à-»‡îçBÇù5~±;.MÊoc±ÜÁ°Ì™VÓ¡ =S¶ª´dO­OoYÛ1ÅŸ8#)Má#î( Õå„éØ\°ÀÈ‘Ê »ºÁ:Yƒ¯ üâ˜4`2(®ÖµDwCGm¼ÑÎàO¾çi}§L­äzçoüöeyÚvËãÁ\>ïÅ+ÒÇ{ó0š^ÑVVåîCrÂ^Ô ,mhˆ”Þç:yÚt„°NtK˜û²=cW¨[ N©*wüE{<ÔDz¤.tûüÖ†|y’è%쮹0J¸}ï³Â€·x¹ãŠRz¡+É<¡:irÙ ÎUñîTìñoT'ÎŒÔÂAñVÑ,‹/P¹Bçyä—_8Є…²¥’{9Šòœg‘¨¡8T܇ڥég«ê\c^d·=wŽ( ‡Â9Û“å"q'¸_@gr'åMåiPWú²cÊ®÷‘x-›g”8¾²5žÅ÷±·ÙÊ[tæäÑIÏ)E3,b°‡Ñ†pÏËõ•k*[cªM>©á.‚K%­fQë&´ÆqEçìd ;Þr^9TxžDüšô¥^ºŽæ9Õµ­1YëV¿ŒÌ;aºòþ:{úž»kÌs•·¢3†Ëq‚ý¥Ù ½Ì±xopÍÎM2O_aÀO×¹A‚ƒjÂqÜ`tÈÓU0ÁZÕ·gÈEöv·RÀSá…&Ÿr¬†-ÛÓ•SfÌwô‰‹Yf¯åH^’lÁ—›M¼Ý¾™¹µ–»9_‘räÂôÅ µÇ5´MM.­ücpçÝäË1K‰ž[ëD“k+y±NV†Õ¤ýó@„âXú›²rã{›¥Uü;–¯lZ"”VÜ­¡£–Üžfw¶Ö•ÃaÚ¦p›/wÜ‚òËcü¾veÕ2À²0qYMÞãg»¤{pJéª|^[u½bŽ]Ù$³ê’¶ZÝ“ìz,f7²¯Wsˆ²ÐÒv§ â—æÃaºríÐIQ0Üd‰@¦'¼M0B…9Æþ®à7e¨RŽåípž¥ñ/*›šL$äÇËžÁ,KªT5ÛwŠsžxö>»²¯˜æçOŸ6›½qÂÜÊ©°¼íb}N³nýžúv£;ëh`WT>ŽÂ)FŒ u4çÀÒ³ÒÄ.ò°±›"¢Ÿ³C Mîôz\•?¾F{€Ö9eg ñyÆÕzL³NfœÈ?ŠïqÚmº"]zUE¢³ˆÉò½ññ·t|XSÓŸT4˜&«g´•†q`ä"㎋Ñæû†¿¢#Gz (Ü]9‹û˥ƾ•]Å:h›Üæ»hâZ ž[Ïà(㯲߮XNiѸ™ñé‹–h°„‡Ë—ehç–ºúY7šR ±¼¦¼9æ‹”Ÿ>£ÊQHâ£áÑŠY ø.}#]I'OOzp¼hº¢höŽË6ŒmùDòÆwDŠÿÞ *Òbœ#J Lá¯ìüJ&lbGj‹ÏQo콸:>8b}á2g†Å̈¸é À­²üuq«V¤0¸¶"C ­ìŸ@´:7Šwv>þUà“ÙnçLèÒF‚÷TÉiiª‚!âD¯ö8Cj~EN'ù¢`Æú~ÞJá-d9 æÙ ÑjílËøüÛ˜s!¯ Ð ‡Ã´¢|¶8¿kâ󟚻РêžF ÎoÖeú„r&Wg -6¹›‘g˜‹Ð(9Ú&o‚M Œ"ht´æâsªÊmð$Rš~a©ŸpsJ;z긩³ªÜqï2OØpðäVØç6úƒGüëøÃí7ššoïùñ×˰tå4§m³Îu^ßD£N¥4ÿÒ[uTÌDM≳4ŽæÄíáÇM2f.s}•ʹ1Õ.Ó)‰„lŽmm¨[š¾Ë&ã2Ü1ù › PÐ;q°ªôrQé•Å7Z„r,á³ô’U<NÐ y’ë²ÔNŸ¥U šÍ‹8nÀQ¾P<Š‹])l ¹sëæ¸¹s˜Ê·8â®Õ ø+ÏCXÆœ óŠeüÅ2޵º ¸ý\\=}6Ýõ¤Èòdõ%?²$×»¹sz“ã½pÚ<8_tæB'¥·ûelïRò %×2d¦À¦1 ª2WתSç‹#tF³êÚ\Óè6V|c|XdŒä½™;¸L5Ú‹·•tøÍŒÔ‹NJU•»fWÚÝïsbè¬g6Î%PùNpÃ.%} B7«=þpn]ÊX(–¼S©V÷8mÆ'Ty®LKZP·LÇØèçÓ+tÛ…¢üâôåÊ}y£9fŽöƒa IÉÀC8Ãå0{–ÎB\<•‡)©ÍGe7®ÞFÇï£Ò™¦LßJ§RÑ•Ê?¹)ÍE8’²˜-p 7[ٳǽÖZ—x6+QKëcm·òe+%HäÄÒÏ€%ž [˜U'¦ßz$’ãYM3ã ?fݯ@|J1%$G¿@È_Í’Fð’XïGnÔ”9åáàmÚS,°"9ÖiDXÅø$6¢…¤²Îð3¼l+‡Qþ»×.»} ˆo`f&=œ*ü™ °§ç°ÃF,x£æ¾Ñ&Šï_м,ÕXgDÂZ´šVŸ¸4U³B’ ÿ`‡Æ™“Xyå±Ó§; ÛýZ,9$ýÃëe¨­!ò ×{h¹Ù±9%©~ùÅØðLÊÒ~iη¡GïR6ˆlbŸ×*.}åCŽÒà®Ü#“ëØV)×ÕñÔÍ&/¼K{ÅóãgAäЂÈß“Ü@ÉAкX™ÆãkéòJAR‰‚œ¹A(ÂìçB‰‡ÏÕ£­åGåB,åÏ2††&¼"5h»¾qÞXغ+¾ø[ü ‘PÞ\T$úXZs©p'­ñS[ET-½Ë¥JÉÇÅñ¡YÇâ|7à @&;ÇŒè9²HNPk(;–'¹Åáé…gË1 Ôª§.üÊMŠ?Šú¹ nÏA×êþuhDúÉ…Ð ŒÞ—\<ÔO$Ú`¦"þ8 V”ÞàïqŽˆúÇmíõõËທ~Ø?vîrO¨låFcÎÖñ7¦Íöª(ýŽ>½"%Έ¸vl-hI–=[X¯>Ë+®ü2½_E¤šè_„Á,r–ñÌýivÏבÖS9—(¦œ;lmÉãvI¸#°ÜÆØùó;(ù9Pç1³H¤õ¿¹ÎQõu¤0,†Óg£?&EJw{ù´v`¼@mw+aÌhhël2\^ÙôÿÓEPx§£û¥0LÒ-{R_”®Ëð„…¬ä>Ú\Õ•8Zïî%†hj©òŽ*,B-ýZ¨®K€§ò#£ƒr^²+/ʨ\8µ˜m1-Ë3’KåL§›Ut³®Š"vp6ÝàÆ9z‰Eîoåg12'4·tx–Wá_ eÁ·Rž—®psK]![ž”<º§rMþ0VDÎxyjÌSNŽ+›áì¢&aŒ‚;}zÙ´Ê+½Qª®ÂxdôøúYºÒXŠŸ½’§’lE´,ÛÆ²¨þ*~³¬Ü-Ë7ŠÇ[!W\‰Ò8/cW^1=¦z\‚Þž‘›r ‰¦f/kpˆÂ^'ÍþÐÙÀ-òeéÃŽ•v(ås3<•þÌŽ÷—§¬MŽÙXñUtÂäò¯ãQ‘iÒ3š¯:¦Pù]b•° À2:…FI- {èןýçâ:N§ ñRnï¸.€®"C ŠŽÔ}Ï´1ù™öå"4ù`ž]/¢wFØ%Üm3…›¹m\ìÇ\Ö™O¯›VÓÌ•R¶M•z—¯J (XŽtü …;Š”^oäïN]°WÆÚNàÃUŽït¼V-Æ*Ý5€bC|‡LùlönSúf<É^v®+9¹ccá‡Z)$¼ÕÛã_àØ’ì¢íiF´PSa¤c-8[Ô,`h÷Î,·ó2=º?BñC ó‚enÛkdùb±³–7iH tKº<˜>‹FÜé´G¿ÜæYNd¼òavê¨+­eÚf:ôsX£öDÜßLB&­kÁô©1Mw›z0}FÄ!^XOÃÚÎÙÔí¡èÍâ«Xy T9~Š`ô¬ÕâE*I¯;Ñ>Nz&èFIwÀMØÜ¬.¯'i/R†¢‘RÅÒÕÔ‚”·Î—Š‘œ™fúL²±“Š7Ú,•q;ãb‰´è«¥ƒ2 Ù(n‰ñ£—’Kæ}x–Ä ŒKV¤)X¥GV3ÂÐF`–ÕQºZNmm@Lü¼D‹4h4ö̙˥DDZ޴¼/îDóÎÒ=ÒÙ-ÿÐIѨ/hŽeÊîé¤iâCœbßz,ŠQëRZ¡Å®V¯¢ÿk[½[倸q¬fϘü<˜Â.øøZ´…¹e£ ÂíµØG'm/¸àLá."[¼¨Há.á4Ó |8‚îÏÆçV-Q(/qxŒ9Ó¤[–_ât†X–ý"³ï—£/¹&ɱÀ+lü®!!WDôr'bP¶KbsZ¡òÆxÄs9—™ âÒów)–MuãâëªÊT#_ºh…û©/|Çmrw)&+§ŠtÂܦ¾Üh*:5{’Á±€ w&‰YÚ¬ƒåsËæ6W,m†^h4eM,Ð1’xÅ—;*¦×ýˆ¿éÖ·ÉÜnèˆsIå¯+¡cú˜ŸÆánò¦I©CÔ¤§ ‡x@ƒŽ§¥wVRX•Zº”=lè(ÒQT‘¹¶Jù®ŽŠ(‹æé¢Æ˜B$a%§ar²ÃÉìŒh Hhä¶Å Ó…)ü"Þïº C¥Ô/eKü ÑO:þI!Ûñlj=©·Røž^GWÒõ±':>äÑñ0{Š_òV0Ž<•f„C/'x0^Y#¶lŠßò²cvˆOˆe žˆª EådšvÑ}K[¥h‡èÿÙË屩TPèÂåÃÂA Xyvü ÓZ)êÜ¿V¶e”èÓb¢KÔCÎ)žåòqEŸ”žÑÈpüP§C8½Öçå2º¶Õöl÷/É“]­’oyHóÊXOuKk‡j7íGÏ[ˆ/qs_=¾`™üPr¦Ó°ôÇèCêÁí©Q”7ÌŠ´\Ï S*ß‹^YÒn®T½5Æ-'”Aýe…¯p÷ŽÊ!&Ååbƒ8O,h9?Ò¨Û;¼ãHI´II2VöO¹jRštt—Ñ•³«Vü®ù3Ò¬ÜÓc¬J¹ ¦•>ÁYÿâFîÍfçI„ ˆ Ù=­n>1Ö­),Ô1ÆðSPCÝêæ,ÅI(¸šëŠ=po-ãP¬]`7@¼8Cð)ŸÞ2ºVâN…¥šÌK—Ä׊x[†ÌÐ!úŠØ/Œ‘}ò¬øNeø:…âùH ,›W£HÈk' GVåMºB"fÝ:aÁ7Š.Wò©ˆaTÁ$»¢¼²¡™f^¬[ŠH×iÅÅ¡èýæWÕK‰v V4"s¼CR¨´´T+ŽÎè†ÚÔ9–ŸÃ1ÜågNklu¢å/MOŠžÝ›~YGs–ŽææìÅñÊ’…žx]çvº³|Q ‚ýñH¬žãæg4¹dQŸŒ:x"{+1­  lÂ+ff¸¥oº«S*f'= MÑtN9ò8–ÑŠLã‹…Ó˜âéKŸî3§´KòB8ø÷¼”ƒÑ1º`Hr«+ê—Ê<3Î$+½nÚ5¿w bvªp“¬¤¦tO{m3µ—~iGL± U  k-ªÐÝN’ÒèÖMqݨj£•¤…cd ³Û\SjÔBIHë˜ëìLû$¾¶²õù©%ŽÙ_m z'V»"s|Ì AöµBI•Y1ðã““/e@Á‚ÊÊY1«ÇÊ튪nщÁ‡ëЊá{ËÞŽxVî !ƒ\Ý%ÚgjGCcÝÔéóAx›ë[8W[5‰ÆÚãó‰U^ b?á ‡gdÜ̑߿eÂÅòb¿¹ª ~ŸÙˆ&ìî»Q½´Ž¤F§~¯0J/Ñsg±Â _0~G ØG¢Ë6rô«Œà•ÑIÒ ‡Ò‚‰Ç¾«í7©âqmË’up‹Ãíé#‚ýâªT%rÊâà nÎÏIôÃ*,?/.¤º© J3¿ô²*ßùé¸tÙT')ó?Ñ›ã³j*<$÷VËPÏn´‘Nl©vV¼<>‘^VØÐÒ RUÕOyUtwÐû)—0ðBOÕñ‚E•³„ì$…'÷PN¤I~1 vLÇ+;ãÇ@2ƒð¥íåªòsWG®„SÇ@ –„ë$•Oü¼&)%Eþµf•L\BK§ÆšѹâáY)Êg5ºcRy•hVÐ*n;Nù9‹b™ðXü”ŒkÌ…[׫WQùûX¯ÎNÕ½"é‡÷9ñ[NÑžþð¾[V'ÙOܯ3ó"uŸX9Ò›¬³'³ H²çÌ2¤ysW¨¼/ÖŸQÉðF ³çü†Ú~šPáÍ®ó;2 Y¬jw—/¼ºŠ{ËnŸ’ñ“SHU<©aÕ±iA%~¯2p£`wøìO3b K¸¾ A¯@©ãaϨh‹‚ã9 PËi·NOÉœuÒâ N~õRôqÔ¡œèæ+Ý!+¥F•{bL¦­ìBG[©qëP~½;GFï¶;¨jò¼¿·°ÆÌ­ÆÒ>"1“ô\^~= +I'vuª€‹×ÝkAJ¸eLDÐÔ­™\8Ûa ´ £lŒÀÒ4¬úh– ˜¡;wáS’…ÒaÊÈÝÆï›5Ý’wÅHQ”uvÆ,3/6XˆýžóðA ­l6Îm #y—iZfý3kÖÜ Ÿ é©ÐOñý1_ÐÍVåWd®Sš7¶\ÜäÜÅižGV½ûÅ/SùŽ€*qSÇÀófJÏà&D¢—0Q–ºýþ>ŽPüIõÓê‚ÅœòôøŒ£ÝIÇq€†x©Psg.탗1,¾Î¥ôüÏâ.\?Í^²,÷åŽq`MþjêÐ|éT­êK–û[‰ñ:ápfE „¤˜#žy_ ¬–вª†Vå0ÞU·RË^ˆ)bf×›â/d­W«+–𼋌ãΊ‚rrÑhJ8þóà‹‰‚ÏÌ€sD¨ W£¤²ÄlE¾ ‚:ì]š ¥lï$Ç" %˜Ø-Ùn/IßΠ$Õ*ý‰è×¢uÜ[~¯ánÏï‰_e‡bÝe ñMßÝ Ÿw7%«m/[ðµk¬ÃÝÏ]Ѳ.‹ ýîêyž;n¦KU8üíAÃ$JzÔG3,Å„ÊTž0úA,Ø"dS¾ êM#åo{;®F®ðU:§{bSáÍj‘…x¹Ù‘Šñ¨iXI§áv¸G×Ä]"(dqjô+m ô™=o¶¤Ì¹#_#ÛÜÉ´d¬PÀoûkŽÜ=¡ºÍ'Æ%ïŽ1ÊókÙ&š³ÊM¿CJˆ–ÃóÀ0ouæ‹WŸ>l” Dv½É¥*¯s´8 ü’dc :ÄòŲ¢N¯Åúý+Ä+ÕªĘJP¥ÕSye)`ÁÞåg:Ҥɣ«”ÚXåN„þY¸ÒKÃÅÍeÒ8N“°D­8\3oQE.T.Ì0-Ü™³Pæd\¼êÛxÇñÊ ^"ö‰ßE…_ÇÇÊúó‘x‡È;—Ç­÷{åÛ3' ªì?½¡¾Þ‰Eþ­³#rñ wq,Ýâlj¥¹PñÓí‰DÜs†SŒWø¾³™à(m¥—Èuƒ.ÍîÚý½XŠFV4þBŸ«ÁçyPgõ ’Ï(j|ZËØÖ±–eñ|¯Bmáõñ”@ ”‚Ë·hçj‹qY«ˆeϰ#§ â’—>sF;-2$0;ž«À¹" ¾JØÁ(e’²È¤;²)¯(õ÷ü"ìeì¾®yµZ`B¡ÉåðáÖ›îKñ‡^’Ô”[~cGM$#»ˆN$êׯQf;™7:b“ ñÒš%R!°o¹hýFÝ0Ëlq†+ýÌ=6ZÒt¢—+Õ ÍiX|ìé‹ÍàJ(~ ×Ÿ¬ô¾+Úºÿ"÷š –‚ÙŽ/ÔdÖr6¥u\:öÕí½Ê b(Gñ¤$^ÒëÎÝãmx¥·âKuµn‰nÅ©´ˆH2lFKx^Ú™@§fe±%s)¶ŒåKS2q“?u8h´©bA,±ã–AœŠïž”—äsŠS¥V PÒkÄMs.¿™aÓ{XRXìT$‚Xñe1¢w'ŠÒÙ kœF”ãzE0ÊÑËb^ü·µ±ü¢'gV4£öš~´#˜žÔ ¥ZpÆ™ŽT]ÜÖIð&`¶²?…/U•;•PƒÁ£%ìô<—¹ª²[¢h)ç\ã(•5H>ÂŽG Ôlý¦¾KÔâN9H0 qòOc Ödtñ;Ü`ù¹²b¼ J]ß^ó¬ ÖæLÅ{dˆ“…(û=¢¼èLn$YOqxÄ3ò¤–ã£PV¸ºÏU8ÙkI™“?*éQÙ•Z>#ÃȲd“úªgwVt s K°]r¤ÉW‘ !3HåJùYý*ýƒßpèc«¶pQÕŸ“–Ú§]ºf£GøPq÷i*ª|ßY=Ò•·ð]ºp¿‘”E,Dþ'Âà•Ї ½ÈJúb,Μª=ú ¸•ËD—‹"eåîÞêèBîjS¹Äxç²]˜Éê‚É®9Šiê¾âFº®N·ÄVÍÃqÈÿ­SÞYM£: G$æ„Æ,©è§l/§æðÇ&ÓêW_açXÖ™·¸ZWmCψrÝpʇɋbrGÇAjå ¸þµ#°-š^¹£ „Ü=¦Cæ»pƒ;>º »ƒ2_?³Á·‰äèÜák™Ü@æîV5>¡ Úw#8ò%˜¿i ~y\ŒÕÒ»EñZ¨œ¬ŽØ·¼¸çq~PË ¹2ùY¬)ÉáDÞ¸käÚrGÆ~Žå‡m®r,»#‚Eï\zø³G´~–×E© »¨ªï@6— ‘xµzq©ã¢»ÝY‘x¿éTê¤èWüli8RO5ÚÔ<Ø}ørˆrþ1&ÁK’Ãê²[à {SîdëØPÉ›Œ, ü(B`T…ÚSìñ+[Øs1GǨÊm¼W8Zⵎ:â’6ì¤J”Dt+¾Ú+ûÃ@DÎÊùA¥ïtQÄÀOÐ9>MË®¼~Æü˜ô\е&RÚX¼ÚŸ [ÐlÇâ\1‡Ìö4ÔÉE8"¿ –ØÀÎÜÕíñZzÜŒË s§´0ÖŸðJ›¥Fµ— ฃX’±·]§3_‘±šTÀ±EîXh€¨7^géb#ÓY Šn!ËÃÊN®L+K9\Ê…=¨mtâ£z±®»Ê‹V’»ŸªŸŠjUmn•c\&H]ØÝŸò‰&eu KjêŸSÞJŒ”À± Ku¢ê‰zÚD¸·Ê{Ùˆtí±‡ Ê N«Jƒ•¼ oë¸êØ›±RÛcO1â©ôJ±¿Uõ¬Pyá,oÂhœ»lÑÄâ-°»GÓSc;8š:‹ÚtÁ‚ÙvgУq»V5NdÄm­¿‹I’:XòíݸerÒñÄ>ã VíyާòæjšÅt29ŠŸvãïÛ™ŒÓ.q¼µè%3çÀ3ÃFñ\¤SS=sù}€²w+R±j]©š¥µžuí,Hîp7ŽàVþ~ÃC^»‚Pµ-°òjÏ õ§†òß÷Þ´ÞŒ3†ÂëÒ®,¹›1¬•]1aÃî)½Þ)@ʵ²¿2™>öõ_RÊÔP¶;h®% =LàÂô~­¼Ù%x~´õ\Q+óê £L3(¥;I—:c8)%âœYi²äpUéi¢ovêNî¶PÄš˜în)HnÉ­Aµì6+¦x¢—ª-ŒASsu ¢æBšJiµÅ*·š¥al©å'½äïiù–šÊÈS*T£ØÊD]EÆ&Y2ß$”q,ð—3g›æŸ§”·EâvÔëÞ`XÖâJõ»è+A,ÊÖÀ™=­¤vRJWÄêyê°eµý‰XfjXâ2²oIß¿àMDQ‡ÐÜxJbírp‡6|ag ¦œ:KàZ¤ëE³1rbNž[üG1ÉÄŠÄ|µª¼a®º ý’'t^ÚŒþ½ÖáhWçòòåpuå îsÁTË…•ó/'eãÏM;ñ±@K\M8FöµPÏS.\VªæzUÉ bi˜»4I`Жm p9U;Zן(oDZÎÌ(«^×{›(½SXP˜ÝéSïdñf0Ùôþ®ó&3 õ1ú”G˜Ø™í¨JLÀΕ+»êVÊðÅ—m0tadf¸Ù„ƒϹUúj¬HžZ¯Ú.Øä//ãÄm4áN¯ËŠ¡©uR!¬ß ÍzçëÎÊ× Ó}EшU^žêÞ2È%††UØs2Y"P;åÙâíó¡™­IÓ~0Ö ÆØa‰_ËYÑ:àP5·ºL]4þ‰šãM~CÈì’šæ6íbÑISO,å_:ò’ǼšÇÏ9&ë"¬rbH¾BêN©Â™ÄóÃИ¹Žºíà–Í^yzU9uÚl×Ð2„_!àNg²D¹§ù¦Y Ž“ñá²iÀ€zªxð#“$4Å.Xš™Ñګʽ}~#«ë4O³”r­÷_çÌÊ$³¥ÐãGÌêé« ‚gÖ¤É!±æ”¿±nräÎq³·æm 1Bê^Üs¬)ï))~¢,^ìª^K-s4¦V!±¸¬ÿ¬év×ý½WŒ TyŸF«ª–ñ<×ÓX•¿‡0cŽ¿ÑngVp ù94bâœúYnl£Â¹ióò‘ü2Þ>öŒÍ­Sx…ËGMQõdøÈù=*M†×.öL{†Wd7O“çPà¤|HÆ5Ž5Â'#JlÈjœÇ9T¸Û/ÕÜŒó¸p±)îéÕÿ 1/nÒ ÙEVBqÂÙ°KN¤)2–¹cX8­ÖéàµÓc™gbeѸ֫|اõÊ •¿ *C¦´ÈIKWÏËå±³;ÀbºîOð’°öLq’c=ÒA‡£dSÈyºQÞ´Ϻø²˜,æTv“½ƒ¤øe1VÔÍD¼»€K]i“eŒÇXz5’ýÔ‚M›Ü@ß}AÒžÄKŸW¼Á”2Ùó†î\%±OC 3€½ø×àm3OÏ~‹#Uï Èp‡ÂÂ?8b½;W~l¾p,ÇdÃ¥àL^Wßé¢ÎTS¾‚#Ù&çq eµTæpuÄ‚ú.ÿáÖsøzƉˆ$d7ŽF?2•Kw§­$Ö4g±(VuþqJÓ«dBC©dÕ¹uGF ç,§p¦è{žÄ9MoC0I™œºPú¶ªÉ^ZSs3åᦼ–JC³Püu±x†‰vhRIuM×lËf-t"Œ›Z¸(Ƕ3ÿÅ#Òè›cDr„ÖèÈcôAfGÒò"·6wÃȧÅ?+öë¯s'ÓöËQÎêTüW:A³±Œ*ª=ÉÎܤqUÿ÷cW-ºFÊ‚§W³T¦¾ˆá<i*ÿ‹&Т:s[-üØÎwF8Dn 3…y·[_-k,Fà#´"óÝ— «k ¸êôjÙ¿i*f©cÌ=¦ÂÀÖ½A? ªÕNd¥›ÒÜp{­s~l¬6åÇÒî£R¹Ðâ—œ-4Ë=Žú%×"ˆÏ™àG)ÛU®±´òxgäéd̸ÎQد¥_êavJž»þ1b›¥ŠÍxÁÄò/8,‰ÞåÌÍ(æh³«t f”û¢øèâ ]‘Q÷cuLuL îÿNÔÀ8¹3‚Êëúà•¯ÍðX¥Ø«C•»'É ü(aô¦’ámÏéHr­¨;—*\í”0¯Ìõ¢pRˆ±Äð?w×L‚ €ötðPêpÌÓ û·þè©©™³ÅrÇÅXckM>þ·áh7ÜÀx5g²"ã7­<ì)ÍLδé?Ÿa¯XÀ‡9Úfþ® \±…i/eÚrÙG:•;2½*_ãÏXhI^·c­é®ÂúwçæÊéÉtCã$®3kÅx­üüiæ™i3–Ê2tºT)yaz+R†rþU鳯öüñë3šsèfD_3T’õ’X×·&îU€wh'Ê Ó‰Æb°Îʇ Ø{NE›ypÑQÙ*YÄ1¢xæ2mcerÞœ` [ÎáÚ:(ù*“i¦ÀX,ÀŒÉT·›ŒàBE#g9I-Á%ªœËÚãa‹$ñ ÏJ“D?ty‚{Ñ¥… œ€A%0â!“ã¦Ø–ˆ™ü†˜oy¥•g8"50èŒ^‚¼ýÕò]1í-µüWø §`uÚNeeqeŠ“upœzÀ´Ù¦@8h~+×Ký±’fZÆÙs˜ÉµÎpÉ&@bée˜ññkÓº¢©{ÀÒ(PÒb!Í[Ä­éϽò†óf”ìÎÙäXî¢h«Wö2¸ìá<½rd||a#Tûöø*˜+ë–ÏúIæ§ÂŠ3ò0O Gü`&*7PX8Ò¸–føl»£§Ô«ä%2°çm 9rj|0¾`«üm”÷m#!xÖ©| Ô\+ÞŸUží”¯ K‰Óžýʦ«²I1{þŠš€&ÿà|æ9 Œ«Ü²6œœÌ§Š¬Mvo#Œi¦Ú{ŽŽçO‘°,Ã.Ûº~KÚ-¢½·]ˆ®ÊézQøxAL8g•—m奘«<%í^ÀZ*1ÚI™m¶Ò @–%ê]ÔÔÑl8Pèö !3”Iӕ箹Á©NtzŒÝ¼¿cwo»e ¨Ë~ü¿;¬"¦|Vý;CI?Á’¿;>È]Q­fÐ…Ž•ùXƒÏz×HN0^»YÊeïüðr©ÆÏžÏ7¤fÑ¡e­dv£‰N¿×(ØjáKbÑꀔ˜Y)¾žm(«Jo.Ø+{lú ÍR.áY~JF§ªÝ™}ÊÜ¢æN™±Ìgt]}ó`¶ÝŸTâ&Øùñþ8ø•1ó‰ìyÂ`ùv%#·Q=Ó”§¨‚ܱ_òy£]Ð6…ˆ³,cÝä¾¾ûŸmOü+ñ Ýòñ3´Mr¡•ÂØØ9ˆÃŸ_š- z<Î!’½Â9IùÐÑ?õÚ°³Þ÷Þ³)Âÿ²›R¿ˆIªKÛSÇ5pÂNÞ€™ 5l€=ÆÒö~.J± ¾”˜ÝÅ Ú)*ÔgÔDs»š×)/]jrj ™ËÝ/Ûù6\J?Cñ—•“f£ÄOñãqèÝ\a¬/¼xoäÿµ0bPÚ#Öæðl³JËs Úx½—„tåTÝ ~墮Ê÷÷ÂpBŽƒ¾o¯£¥»Ò+xö'ZfN~¢‹•÷‰©ZÞ²š$¨u2ô"÷åcfE÷›1uEȉôÅ{UºU'ë-r­¹’±‘“þ+ã ;²Cñ‡¦œn¬×E¹_ÎÓÆv2P¿7»lZyZï/! ¨÷Æ(B™Ù©Ï`o‹×¹-¹`y •ß ia¯ SM€žV)&÷¥Y¹/Æã„U9þ€WÆ5÷5!aC1ê¸ùQtaì)I ˆ~ãÔüd#Š>Ï€8ëÞqñÏÆDcJ§´sNÎZ“‘êFìÈòÓ\8Ö1Ð<º‘š´µ _{NÒÜûäun3¦sîøV¤Œ&1ÓnZ1ŽÎJÓZD ÇØ 1"––n›òbK'§ÏDÚNkÈüj븭™©GÞDѲ`t%úrP!´X½ðÏ.{JÕÏÇÅë` ^¼¹Âýû¥k,:®xA²Õû`ÀøinR©4K—'Ô˜S‹:ûêòà)»_Öþ÷‚ÃÐhkóVD‚Úz¨A]Û©‘JOóú–$;>ÅQZ6’~™Ч²C÷J4ÎÑjÊ7ÞÈ.p¶½Ü.ˆÞÊxáV$øuŒ¢U²¶²«Vb$6®'K—7Žï6ãK¦T…¸ÆqÎŒ:fô :j1*øzæÐïü ¼c€VõåRQ6%ŠÂè)œÈxˆ_ë §¡z”'OGµ ¥œÛNÑÝG«¸ï½ZÄî€õí-1·µôQwÀAŒÏò£tÍÝ´2–cœïrF¾’v@áÝU]ã‚Ç?pF»B¯?óóEøt\xeß8ö“jÝ%¸c`E`מž­ÏÏçøñ¿ËzÃR1á¤êk£üϧvíIµt»;Ñkôí%»ü·èê©UQþÉÓÝŠ2†ŠÍ&´VÞJ—qÐÊ“ñmE#~ú¶p(àÆ éˆÒ^¿d”3d‰˜ñ5NÄÊpÍK±nªëVŒÂ%Pb5-–ز5“X& Ö:}ÁžÍp`=ÈÑgªö×'1ÞÞõäs2Y./|€ú2•ºCœâE®;-ÿpZ¿ÖžÒ³Òf¤­lL|~¬WÈ-Åk1œeŒy¢›!ÿP^Gß ¿Äl#»?M‹í©äH¹¶[ËÝÝ?'m©²×ô©±¥Â?÷›N´—>Ì«’‰, ï8«õ>V¢eWb=‘\N¥|Œ.˜Ž††ªXj—Ç âd"póÊ#ÞH”˵<КO‰½Y“”Æ— ÓR<7©Ü\”ògfÍ·'Üb[ôÎXtí—Ï›;ÓôÖPi“ñ2;íίÔÛµÏ]ꕎn›.6›¿n¨édóšsz¦4]X¦»þt<}ž‘æL¦äÇAi_-ë³(">§ÇØ®põœ]œäÈ)%n`?{:ßq’¿Ôš.]sÒ=C¿R=ËÎqå““4™ñªJ0¸%&«U™£÷VÆ{cÅ¥CÏßP;ß Wp£nòIœS±¦¥´¬~ë?á‹€e^Ðm7A*Žm(×ð„u±— |Îֽ³¨*?•üçm¡û›.$säΙó¨|I[FøbÏü)O˜6;–)§7õÏŽÝ»¤ÉÙB·d¯™­#–Å9(}é’Øè]òǵ‚qåçxc"Þñ{riÜ@Šù{©qQyCäÎmôCÞ-: Õœÿð·e:X|Š£Í¦wÁŸÃž‹Å-ŸŽ›?×CváY«Ì¥…´fÌÌ÷8äì©'÷À=óvÃïe:ë¢’Ž½EySb›(Þk>KŠt8>ù´ö!g1,ËÍÖ<†`t”Ç’ÚÌš!*߯…JF;51N ¹ð¢T9 êAqc .žêÚ“*¬ÜÄÑ$•˜HšØŠžá‘%óÉd!Ý¡s”>ºëËI ZÂ{3Áâœ~'.N•ïwú,ùž¡œDpÿ÷4ÊX6ݦm…‹Ed¹^×cA¾ôÈjøÅø#ºY“•g1‹yð-x–; ãûÊì8©ãýE“³Ý™§ünº²`Ü™F‰©(E4ÎÓ†£<’ŽpoýJÿºüŽš½Ü©¸¤¤uvšŠ…U^\ Ù5û•Ø+æv¡ý4Höc›ÎþìZ~U|úˆ >&z«µp®úëåÜ£œØùàoÇF_R¶èûÝXt 0ß8™Ä‡±0Z_Uî,=7ãó4•‡‰^K+ge¶ ½E9O3uÅôBç¡©Û(iá@I­hÜþ¶ÀÔyg˜Ößž6;¦bÄëâû¥Óü2¢t§Å©5ï­Æ¾KÊìÈÍ5¶‚û>†,SžHЦOí0”!Š&f´×‘fÏ´ñ§zG¤N¨éN6V‡êzјµ³+¹ÀZ³q™ª ¢ ƒ ð3_8²“¸Ø\wÞ´7,‘P÷HÇ`ˆ ÄĬê´ÅËÒZ¾QîN Ô+ï¬Àú‘Íæ{$`O¥3û ”°aÞrÑ[ð¦Íañ&Î~þd´Óû9N•¹žïvd¦yñj3 ³páͱ°¹±m‘ÊZèŠï Z¨ Älìa¤6óÎÁ+šd5¥a£fUöË©}•ë½®V|ˆÛÍv5/°ËFሊf%©Ù/¼ÎI­y;ß@ÕÈ`.q_k4âxAš,SÆœÖ0-çB-MЇð1¡ îTFiÞ TÛ½¹0˜)3/¨~ þ=’SÆDŽ£þû3C±"}-N9kÜ76¨Ì ®uûÉõÝSkBŸë¥ˆ­s´%mn ® ûuÃ%ö¹¸wùY>7J^eÞ”­àÈ·§Í>Þi–•q ,Ñ^ÙÇòÅ’GŲ–¥-eæHŠóc?ØÚžbóDYÓbH•”—8‡ê9ºÚ.›™ý’d¸ž`v“;ƒ8l]BϺNw·ÝUSYÅØ_«ç«EÑþ0ä ÏkNœÚêyNµ×«¼ɹd­(~ƒwM–]Ö ‘º3Â1ÆÔ¿e½¿Ó©Óe AÈ¿ª‰iwÝ&·U2³wñS4•—ÅÖ¸%Ÿ£©úý¼9Cj´bçÉY±:­‘ ˆ?AM³–΀G M$N›þqrbñÁˆcYO:V”®‰ Ó^»txš^g!«g7pãõfBËÏÒ†ÿ2y¥/Éô›3Œ;’ÅkbW›ÆÇË%â XW¼¥ÉÆòÞÒ>åȹ©‹0Ù‘ K΃[é™Ò׉ç¹ê”f¼ÏÑ!NNŠÞQzQèš©¤W=©7QK+‹¦ j/.ö‰çxXÁäV-oGÞÈxëŒ!î|ùyJ©»Ê6ØêµW˜dTÌж4®I®¬ÜÿÜeiaëK.ÑçºÊŒfñ7—Äš¤Köq§O˜-™Ñç›t—öžÆ wÛÝÏÒÄ_Œ,o½R Ã{CÕ44?évœ•·Z}"£X<·¡#œ@+ ã…ŸËjœ5}v¬[nÀòQ±gyÒ[]é^‡ía¹zbÝ?¢óªfÛ˜ÅßhS¢åÊû`ÆÔ£‘lŒçÄ„kƒ2—Í]8÷1¢"7Áüh!ö üï£à·€·ø$R½ù»KvÒgbßû.ÚwɾËö]±ïûn´ï&ûîgßÍöÝß¾Ø÷@ûn±ïAö=ؾ‡Øw«}µïaö=ܾGØ÷HûeßûÙ÷hûÞß¾ÇØ÷Xû–ñó=ξ°ïí{¼}dßÛ÷!ö=Á¾µï‰ö=ɾ'Û÷aö=ž·ï©ö=;§Û÷ ûžiß³ìûû>Ò¾Ûí{¶}ϱï¹ö=Ͼ²ï£íûûžoß ìûXû^hßrKc¾Û·øæûxû^bß'Ø÷‰ö}’}/µï“íûû>Õ¾—Ù÷iö}º}K5Á|¯°ï3ìûLû>˾eÃ|?žŸjßO³ïsìûéöý û^iß«ìû\û>ϾWÛ÷û–È“ù>ß¾/°ïuö½Þ¾ŸißÚ÷ûÖ=Ñ|o´ï‹í[’Ì÷³ì[‡ó­ë´ù×Ì|_jß—Ù÷³íûrû~Ž}?×¾Ÿgß[íûùö}…}_ißÛìû*û¾Ú¾·Û÷5öýû~¡}¿È¾wØ÷‹íû%öýRû¾Ö¾_fß/·ïŸ²ïöý û~¥}_gß×Û÷«ìûÕöýû¾Á¾_k߯³ï×Û÷öýû~£}¿É¾wÙ÷›íû§íû-ö}“}¿Õ¾ßfßo·ï›íûöýNû~—}ßbß?cß?kßï¶ï[íûçìûç˹WÞ‡Ë(Éë匯®nhCìL VwúßãÌ(fÙØÓZ%ø¨zPÈw–S*µHÈÇÙšdíh´Ôoiæð|ÞJnÎÊpp‹8.í™jÎGøŽD2· Š–peØXKžwUÏ(¯ž>cVuùœã°£¹ne‹š‡×·&;Ñ.#/ÆîTék¹~<²½J?ßYebEÉÙŸh@C©fDYçÖÂØŒÇ ‘ެ®Vä<®bůÓ>õû ­ªi‹NYV¯cþZ§Ñ%êýq¶>•çÔ'¡6øçýjÝó⵨DjÛ©4*˜ÑYRL9jÓÁÊ £ñ;|¤zA ¤aMÏ}ôlc}”WÄç\ÎvE›QïÌ þçî[WÄ_q}1}’lÀåu Ë9†Œvyãý|ûÔó2·ÓóòÇZ“M/íà0Ûñ«Ë™Öòûj;[Vˆ…·ÙÑõúïIªN »IQSvhvÔé¿VŠbäÈo¥K4dªà47‡Êò;õ5KÚx0Ð5Z›á¼¦T¤³mõhY Ø)Ú¸<ʿ԰tî&óô(ïh÷JQ*Q³õì\¸XÌ~PÕo¬Ov¸ë¹+7(‡*Õ 5SgYÝ•4 KÓ¬Š'Ó½yv ­OSM•ç¨kŒs±¥ÇCâÆËh“n‚-ò™ääLOLW¡öQOÿ¢ÜWÕ7Õ ¸t/\žsq-áæ¼xumM+ûí©õu âIŸêý§lzJoWV ÅHWe”uXºYô«G÷7s¦:·žc›úö5õJt1UˇŽ‹FÞÆ=X£V©F7FGEMërÍZ”ý›tvm;Ó2Íà:­Ì¯qÓ­;Üqn¿HÖáü¤ ]ûeuŒ&1ͶP»Ä±ÔRU@-Ðä—kµkJÿä–q”ûÕf-÷Ò‡5ÚêXS¼EÐÒÑ”•¿I]¬“8;½è£¼8h Z&›©´g\Q2Å­M»½ŠûhkJleu}K-LˆÍ¸¿ÓyõÌ6Ž’•×7ZϬg‡ˆá¦Pë“v¼KmRšŸ®u Eƒ5_å®Òƒ(¯0®£ô…zš:ãà7\Â(wÿ6Y,,Û[¿Fê…ÚOJ{¹–£–úïÔº±+¥ÇNëäkµ¬ ËÜÊZìò”ÚØúÔsVÜŽÒZ…•ëêÚ&|ynל;4Òº7³å½Ûš< 0ZÊõ)&MöŒfð)Mov¨]ÜÛ !~Žh‚>V«¢Jß18ðquEûÓZ`ˆšoX“jêŒ v·”Qö߸ˆÓïy}&(Ù -; ömq6Ô>-rк&E-ÎõVŠàÊ+ݮҽ׬ª(ç0í³R£6‘Š{C¦8 µfÎöFGrá…Ò 5$*çä…s§rÚm³ãŸ.Gryl‘‡£–{Þ.þ!‡¾¿$Vºâ}—é;áŸýú¿ØýE/çÿ[Ü‹¡KRµË`<–­nì¨KVׯ)CºÆpdäBª¬7ÝÛuš5½p švå¿îÝú5·Ã“ÜÐÁÍ|XË2ƒÿOsO[\ £(*mzÿ¯r/Z–tVC¨ÆÓÊz甸–é7ùÿ×qÉÊ´©¶ºÍ)ƒtdù΢‡ºý(fK’’D[¬%éGçúAÿׯL)k–ô7¥ß þ?ýhâýűw•ŽÛùÿfkœ›(\2¹È0}Ñ΋¹„¾<ÝâM Y ÄÈqD Àçó€dð†õô³o†…lqI#Y„v°Á=-«'=êÕQVÙÎéŠÆóJ0vRËz †Ã¤û€‹÷%M?¸/ž_^âiŸŠ²Ž.rñV ùÊ%ÈÞÈfÃÊåi›‘›ží©åxXØËb=,®ÜÌë¥æ¢‚kn´Ï}M=]Æÿ?kkHÜSO­¿#L=%Æÿü"þ¿3Òç×µ;ëÔÛ·`_ÈÖa9xYubÛÔ²2ƒ”æm~IÙ§ƒ§YÕ3*f•7ÄÈ®3}m|ÿòkXþ±€ˆeëÒÉ&ËG »ŸuÖzFm娱nÑä™k•þÕsñjñ‰z…’Ö8²g–uñ¶Ç]U«îéBÇÝuÔªÿÛ«£¬Û¯wqVº-Pû Âd–óè-O;+_6ª$!I'dŽo¿íÉ?îgQÂ¥mPçÚË®’™ÄZŽÝã{QÖoMC#W×y£Æošçð®«ÚYª¶š¹VêߟƒÀÐâþR7&GŸ¸©ÔðîRk™k¥þãшJÜ?GÀOü4å1›_î.wú(2‘cÆh.á§Î¯hŒö7¯´èoÆîÏéߌºXeÓ¶ÝϺºË^¬æ­Õyÿ9†ÛiA&W.Iëíí|ÛUñlruUP-;‰Áí«;ÃÒ¥u èÑ÷=´ø¦³ !a^@²¶ú ÒêÑ@‹*½@±#jo@Òi ÷!S¿c‚s6€ª4|ÇrÜr ˆa«·®¡ÿÈ÷-¿=s>ö3„ÌçÅ­{ÿ!¾¯¼9OÄL¦¡ÒÃO\´ ÷Mëí-‹€·:€MÂNkŸ·-z[Ô½ý¶Þ¢ƒär–ø_æÝ·ôî|çÝqr‚·ä+ó¿…·ÿ¤·»ûs™R›üÍ#gƒÅèEÑbf‚]½œW¨W32ñâéåS5 HfÞ6¨½ý½=aÎŒ¹Ü÷¶Ñò~SoÏ›7w^ÔRcoaHñöïõvYÙœŠiQÂ÷°Ÿõðïô¶§‡ä÷=¤NßCúá{hÎBnmn‰½ê³?ÿEøˆÀôÅí–}áÚ¬hØYû÷¬ï>-*A†§F‰nPö¼œ½zDt\gé©ÑðPùæZgÖ¨;+šY²TÚ5,çÂ9ݪƒ.´•uÇe.Šž]ä¼Y­¬5ª!Uožä6»#ÇbôþôÓ¡tãÎêÇ<õÒå6?ÅèOTŽäºë—ŸÅ£l_|™±;ñàöƒ“×AH´ûâhͰÞþ™ÞJÅç%š\ê2q FˆSß¶+²§ošËíôm;}«Î§Å%wE»¹›Wçx.nw¸Œ›`sª‹ªæÔ¾„Ì·w ù¿ÄbÜøWX ຩ¼Í±˜ÇmöN·~0mìxþ_o51›»ìÚ(âÆ§©K\üû j¶ð§÷’±{Ð’tÙ%nœ4°GÜ,û=Âl+fÖ õ5Ø~‡˜èYì‡?a%ïj¦<¿9191»lQõ¬¹GϘƒB{ºK@Ëäú’r)ÓúTLýlœb8JÿËë¶ì¹dßÆŽ˜ÌçüîhÑÍé×ì‹]Qi˜ñù%9¸…W®‹‡Oì:%»ðÌïFÓ›óMÑaEÐ(mC;‡}Ù¨Ñzçã‘Í#³àç^OµÙÔ6AÛÎÙiƒûúM¼›3fÀÏ Øsó¢mWNÁ’ËSŽL'9$aáy‰9š³¥åÇγ¼Ì\yÿHyÍ¥sÊ2?c²‡]ÇQy*Ã5cº¹çz›¯]©t.Yæ óWð;Ì]Çÿçô5|"³µ¢kÅ7 O;-š®]=ô+àÒÂwQ³¨7qR ÚËf.ýnn_—µ‹ŸË­]_-<óÀhؤOFY“^ÆþÎ,î¯:Ù\Çl®Òl¾Ÿ¾Tç¤&"n´‘/¬6Rçp®oðóÈŒ¶³ÔæQNûÍ<ÂHèœÇÏj™ºyd^ü<>…ÿ­ÌÕ™]hÖ×yäì²£+¦iOY0Ûçþ‰v&Ï=Ês87ÀùƒÈä†Þ¬Åõ6áýô^, ÿî{§s{eå¶zD@2ìõÎØÈ]£ù7(Ì€°)Ñ7ΰ\p‚¦‘KgÅÊ:T=6Ô5ÚžvJšrNâà¶‘ Qá.HÄik@Ç=¡C¿Pg{b%㪵cÓ¼âvñ‡kz~h{âÖIlí¹§3+ÂÇ9ÎíÜŧ¤w±ÞÌ=/Z;‰k{¥ËIÀg“QíŒUïrœ7YoÓwªÝ`¸öË3ïô=zÓ;ê¾î×QÉ™ßÊÖþ?›³L;æô´ºc ônŠöŽ1K¦sõ/¤÷n§°Ü÷÷Ù{a©á;v€Ç}´èl{ÇØ`ïäExÐÆ4A"ÙÛ:Ø7Ü·ËÞ1û·Ú;pÕ{mÇÁ-ëØqñð™§YOw<3v×0áw—¼qú÷¢iG;ñþ÷õ~BGó‰ÍxŸ?4Úå0Û`[íž|Ñøƒ^ wݹ=·§÷‡x~s¯ŒñÅ6°ÅC;dm×ÿaTR²_´¶ <§<-Âi;÷qø}<ï– ¾kö±0óóm§ÕÙ·gÕ›¢C¶Í~¸hæóÝöŸ{öÁ¼°…pŽÅ˜µ-c®¶Ù¼>s“|¨åç•óó(©™h$óø{Œå]öýùu‰ƒë5m‰Ö<:>m°AÚt;EÐÆÍ«H “˜€sš®zsë&óМ^š¾Ó€ùÂMG,DîbÊ9Úß]Ú?Õ·³›uï!þ}l~C´çÖ]fqj˜Å™aç…]ëï04—Z>fj½ãê÷1s·ÕfôYƒ3zgÀñÌ•Ÿ1ˆª5ù4w÷Þ Ûawÿ.8!: {7!sº¾s™äw§ë7öÎ>Ñwß'zãw tƒþìÝú¿¼}YC[bÿ#sÌÒ]Ãç Âäø]åà²&ä+·ŽåT“ãw”C'ÙIöŽŠ¹1þ¶Þ$Z­ ^÷ŠÏ¸wSGj„íÞŠqmnÄ¿¿m'—°†­"õˆœ¤·à2ûŽ«-ï~ý;[ ÷zj¹;~§Œ+²|o„B öþu½ms5šœÚLÑSy÷i½;zŠ»6Ï›œ—Ù¼,ÉûkzÏUÍͼÆ,ØXý_îî, z®²¹ß9‘M2ÙœWðÿíü¿ ,ôÓ™›Ëv²^Í÷\öÀ6&´¾wÛßìöîu~Lx†ÃÉï¯Oï—ÁܧY]9^•ÆáC„¼:Ë-§•¹¦*¦÷“‰sã¯}­¾¬W úÞÄw ßà´¾×LBrlî¢]“Jv=hÒPº+m]uNAûÌ(kdW² }d^tp܇xØš½pÅt”šµóŸ öV÷~-ïo¡ÞÑ–ë½,»ˆ­áMµÞNl ïæ¿•ØzbkxwÓˆB‡5šK˜'zÒþQz Ø1Ç$úÞåÞ¼‰·bl»Ž;”X¸Ûö`I¼5ªÔmkëçFv½;K½÷97¸œºgmûx_-+|}·ˆyƒuOpoÞÐ÷¦u îbñ¶ØÖÅ¥§Þ}ÍÀ{Íb›¼á~nò¼Š>übÿ›Ž9æ¸̱ÉÝÛ´Ÿª¸–Ôc¢}‹€ÿ]G6Á þ­6ÌÄno1vö‹±Ûý} “eXmYÀgƒGüýƒw[í/®ïüýC]Žî2l' ·[L¸#ö÷s¡ÑxMˆÝbŸ±|Âñ-áÝWì&2¾+ó.ñ| b­™ÜÉAáÝ{'|‘Lï–XÏ„/’»UÓu-ñýÆH<€¾—šÐd­á<ÈÂ8/¹^D‡óÌS‡M^ÏkÓàîÇüì °9{ÒǾї€WWV×n\µŠí#Ü‚ÑcO°ž^;ˆ]·ŒM}O_ï‹"ØuÈ>CôtÄ}=57Á®^rWó½D]¡³—[B/éŸïåOiï ªªþ!µCôrؽ½\?ØGn¾Ú]|£¼ôÎ÷ññ}½Ämkȹ¾iuÛ5=ÓvëìYµ_Vžpêæ~]úÕj=zå`ιËõˆ¾ø]ï™üÔ!_»Ö&ìëðð«r\¥hÕMãJWÃñrïÌÍëGs¸ÆõuÍÖ¾B¸ñ|¢ëÝ-ÙöX(ow¯ sH_£ò”ãĽšÿpâ>ň8•#úÈÿ‚Í.1í+‘ch“»÷/è¹ÕóB˜Õí\:·ƒå·ƒ²ü­ÂÌ€îóÕ{÷?cŽÖñÊ`òEÝ{m¬ÜñZâ틳g¦q¯öèÞ^—ÐVà€]'n»âÆ€“õ1÷mq&+/\”ý6sQØ“ÂÝâ¢ìïóoÝ󦢮Uß)\›ÃíB˜{î9Y)¿¸(·Ú^Jù(`ªó [R.Ä×s{©Ê ²|=‹ñ˜¿V‹!k0Âb7¸›qUü®Êø nLyðÀü˜Ç“pÈ6…{´Ç·à£{­ÃÉf–ò¾áŠÁËN¹b’ÿ¸ž?ËÓ<™ÒÅÓÄurÅØéîÑ.I¹bÔ×`;Fü6VN™~ »uãŽò› O2ì—¹0h®ƒ9ZÝ/BØa¿˜¸:’îöÏ¿ïƒÑwuô«Ì>¸?ìÕù} ~àøûöÁ²¾ý^Ý ~tñ•²09ì¿ØžSÈ|‡Šø@fVÕáÝÜæÜϪ!Ë»ùÔe+b»–?LKÆ=‚…fŠ0!æî¤w²>pÑ&·W .êÞ«¶ÏB½é,€–ZÏÅXÛn ؈>ûž37§åÛéù[ûnóâ¨ì|9{B;©+v'?¡ûF?5:X7úõ(†=2ü®gpýF[ÏÐiêìœß3úäoâÚŽæ^.á¡‘ÏaB¿§û~j?ÄcáléÿÈ>nÃm¶›kõ^qrö̵xzÕyþÿ¿Þαͷ>%瑹Qs?b \ª؉íŸãí[ñrõÜÏ«¾/‹›©Øbðz§/›@l4µ¶½6ìwÁ¾‹ö]âûé|—Õ}W΄ßõ#ŽO<ŒÝ"›=]S iÊí_fÌóá^ù›;Çã.M‘x[v~uÅß½ggÎ{ÛÏ({[óÙÀtì÷µ§áð!ë‘áÙ2ßâ¸h— Ç²»OžÿÿáJí ˜Œ._ã°)ŽU›22\½Rwá\Ñ0^yê{}ç¹ÑⵟŽêÖÞ-{}VÔøzn¯(‹Úµïw®ŽN'ÁíüŒ; Iv:3óÇD»oäØg…ÍÂÿʱiÒÍÑbðÈîw0׻حb=n»9:a;ÈìZ›+áVÐæ°šjûfÛ§£JPC訉{øh‡/¸Ï¿™bWþ ·;ÞÙñŠÎ\ß ñ‚Õu·æ>íw˜k™½c.×…w[,Æz¸ÉbïVt18Ï_±=ò3ƒ{¤=`£ÔãæZë*†ÿßë`ÿ{ùÒÿk®ŸùÈ\_r´lžëdp®Éæ:Ù<×äé+`®÷+‚åz1ê݃íü¾f[’…»g{^˜íÀ…ï, 4rÏ;e ŽÓ|ob¾·0ß—3ß[™ïmÌ÷5Âwšï n¾áVwÍîóÓ3´ÿÖù¾" ?Â\KeD¸pD÷ÛÝ\ºa#k®7ø¹6ï÷×ùÙ†Ôlº?éf{CßlÛ=ê¾ûtƭδ3¸œUŠ–És² ¹‘gSznĺ3=Ò5 l´Ð#òó£ÿóî™§ôÆ+ßΜ,ÍÚ:ÕÖ̇ïÁ¶¬\îãÅø>®PÝçFQ)ŸPû¬ë¦ÕÁ'Ã2åÂið<:ݦu ·±Ÿã¿çrónQxçùuìâ³3Ü9q ³ç½—ÿ[-ö>þï´Üšöóñî¶ûTˆ}%s³}ݺådz2X#®ÊÔ-^bŠ/ÄE´ù¤Vûºµÿc¯ïÀàF{§Ý_x‰·XLÔrh Æë-¦Ý_ÓÇoL{–réÇ7 ã|䌓”j¶ÆyÜ ¼U€tE>ì=GðCËñª…_Œ~™Ðîaï9¸-W„‰¢"Þ Aöž©Ò¶iƒ§Ž’(r&Ïnh_–@íYJ¸9áÉE˜…‘–Þœ¢“ÐG2µ¡÷Kmê7µµùÚ‚„.L~Ø{vRÑF“Á¼Õ­ÝÔ-å‚ÃÞ³‰MNࢻ­¡=ñ\˜´Õ5“޹Äpó.=•~h-öž›Îu«{nKßçÅþœ{ÿ5e~Ǭdt-r¬dôUþ8Zëµ¶ÅÜç”UÕØr9WÙ¼ #,ß™7Ô҉ת=ÐÇójE«+^¸=è½ílgª˜©c5¶È\ý`@{Éî6ñ×R¬€¯ç³¯VâVÖjÛÓÍ݇ڤ„>Vó…ÀΓë*F“œf‰—á–Ë‘Y*pÚ(¥²y8â¹~þÁe…w gbör¹G±‡4ù£ËÀnò>°£”®d JHÿ¼¢ÄÊTG¢Iè‹ûÚ:Ìdj%I|u†Êbuþín3xP׃…ˆF—-_Zãw²×hhnG—¡B.W¶;Ûèé è¢ ?º™[Áè²>=Ȱ§„¡¶‰/+•¼'xdípç«å ÷Ì`hÔ¼œ§QôzƒbHJËÒÆ˜ ¯C@O=¯>z.7}o;E:f»wŠÕ­±;…ÞÖwŠ.wf§¨®·´}§ ’muØe—èáÁ©oq“ã*³#™EéGMû®½'Ë›oðæÓånfÁ@N_ô°÷ð†<྅DÍÞƒï:ó€·œ.Vš‡û‘Ës`‡½áF”½±½€¿Ë·«xCyj'ÍjÊ ýÚ‰âÍšOfE±úsRú¢6§6ÁÞœvîºrJƒsoNvq=§ô<÷æt椷Âj{sZœÑ•óÏ·ç´8²+ç_lÏioM]9±Ñ›ÓÞà»rj—ìÍiq@WοڞÓòtºrbý¡7§åmu唈½9á Ös¢ËÙ›Óò »r~u{NË-íÊ)¼¾7§åÐvåüÛí9-׸+§¸·{sZ.yWNa½9­öAWNiïÍi5!ºrJcxoN«uÑ•SŠB{sZ®œÒ@Þ›ÓêœtåDwº7§yÖSÚÎ{sZ-°®œÒŠÞ›ÓâÅ®œbäîÍiõëºrbä¢7§Õ(ìÊ)ÖÑÞœV»swN#(Ò›Óê¯vå$ioN«Û•SoN«ËrnÌQ?ÁêÅÞœNšwºK˜àüzÞIóÃäà.PÏÁ;_7¨zÞùÜë9xçspˬçàÏÁ­´žƒw>7ÚzÞùð•ê9xç{¯ÛО¼óuÀ“ªçàÏ«žƒw¾Vs¯èÎÁ;ŸI=ï|ø.õ¼óý€ËRÏÁ;ŸŽ[=ï|¸íõ¼óý@—¢žƒw>‡¹…tçàÏan7Ý9xçûÆ^=ï|ôÅê9xçs ;VÏÁ;Ÿ=²zÞùž¡#VÏÁ;Ÿ-³zÞùZ¹¸ÕsðÎçàÌYÏÁ;Ÿ=ÊzÞùhEÔsX ›½ÑzÞùhÈÖsðÎç@¶žƒw>:§õ¼ó9Ð}«çàÏ&J=‡Ó79ÐJ©çàÏ?´žƒw>:—õNÿÒä@s½žƒw~7À#©çà¯øzÞ©ŽÊ.´@ž7šäåÇÏÖÝ•»Œ59Ñó+ɶpI~"唯ñ-ʼnÒѱ“„Þ%ôb Áo84lµoÉÌ.‚bIØDËÚåâ,•%S-¬²æ¤åĉ-¿=®¨üöþŠÄL¶¿²9ª¨¬‹šrù'qÆÊÓœO„ZÆeD¿â¢N©^y˜>´+ âŽTt¥ YÅ*¯ÀG¯Ö1œÿä*¸(ôë3ÓQé;F Óý3ÞÕš¥F.’êQƒ•4o R/2hâÓ5µAyT{ƒ®º7sîVN®›šqOÅÖºñª¸7ßïï šJš¦¨ÞE¥Œ%ý/«Ïlû¿–LLwÞÿ&ÔÅ&-Ð,4â[ ®Mºn¨GMRxZhzU¼,štmÝÁ÷¯Ä=húlÿœÑõõª³6§Mº¬jNû‰õ¦þ÷S¯Dé§+¤êë§ú4 ý„Ug¿‹âúú]⦩6Dz=ê&Ž>nJwÕrhXNàuí–fádu·ùëq5Í_ïïµ±½ìĤùûëÞ­éë/žƒ¦b€º¦Yp@<©&Å:@‚ºYÐTHp€nº P?tçø,¾uÈT‹kí‚þ†øfÑ.äŒÙœ©3æÆÕ‚ÿ‹˜-ì’­¡iAjÒ[ÄÉÔ £EytD 1õ bJc¸'ÅÜ1¥ ìÆAô#!Ç 6EBƒà$p'Ã1HeŒ1¤„-7ZœêÁÜÊ6Æ`0Q‚–Þ`&+aês{LÀ¾ƒ¹+'Ô4.c¦üÕxŽÓ9˜ÈæHê°*Fn*¥íšO•¦>‚™í¢LÄ‹ÒQŒ i›¸ÅN`XÓ<£½u@Ê¡Š!šVusˆPƒ†ìwcÈžƒ»>ÛAcÓup½¦&PŽ:Ä11u¬Ú„Ò^euÀ| úH¨RÇ­Ž7Öv–¯{HÚ2CÄ"Ñ–òËÿýh'ËÈ-[»¢UÓ¥Š[Ë㌭Uñ‘Ë8Tʪq¨.ÐR„ªM¥6¦m¨°†ú9T|Mø0am¶a°®@`ÃèMÌ^ö½¸ÒaßK÷6CRæ‘Ú®­{¸æ\µ BÒ¶Ž*Ã…,µi†‹…"œ1\×_Õ9b߸¾û¦÷½­O<öèœ>„Ó]íÝ|5#4ÙÚs#t»PÕ#4¡Ús#ÖYu?ž[]ŠOF{i¯ŒP?4Ó# ËŽ<º¿ßÀè³ÒýHÃH©ª«×#u1ÒdŽkG%¬§ÿ£t)ÑÜÖ¶%¥ðÏ(1u”s”®ÓÚ´ûá+ ¸Ÿp¦˜ãû=/Æ~û‰}"$°ŸTû…d.É ŽýÎŒû´ß×\g²>ÃÄut»‹>Û¹arÔ—þ¯›"¾˜v»ƒSd¸ß]qe£sû'€|Ún›¥0ÚvÒhyЄV‡ÔÙѺ³iÇßIyG‹[¡)Ø_øTÜ_PØfa~í·ý yïÿöþM@-Žà*ãGÔº¶¿˜º°¿ªTÆ}¨ c´‡Ô…1ÂûêÂíCuaŒöêÂÍ¡º0VxX];)îÂØIéÂXé½kWD9ÆŠÿ%TÛ&]wMå8PPý8ùµPõã¤Á§êÇIçKÕû‡¸úqÿÐ_=SU;¢»ú¤¨8€ÿÌÀrß¡8@ª$šÄÒÕ  ë¸ºp€?êšHuá@á$uáÀÖ¸ â¹ö?ÏÀâ) Œ×ÆÃF.m¾ƒ”SÈã ͽ¶âAº¦,Ì.Žä!‡ò-­öCtƒS¡[1»}žEbvİ)XùPnb1*2‡RGÌL*]eÕz(¸9¦ŽÉL~Ìuh²Œºz´Y0óaoˆ»zØ…i k»ÊõTd÷¸#Ã°àŽ Ã2'†e&ÅÛwÛ”-|5ýJzÓšßaBnÊ{˜Ø;Ú S´ßµ‹¦/h ¦H¡O÷)bÔ ®‹ƒº{¸HïêêT¹êÐŒNNP7§ia1Òa–i_Œ»:í‹ý7 z•uŽ^eKÑÏô‰q¦éÒáÔ}`ºîFÂMÓ¥]¡™Î<1³ÓÅWÒ›!®œ‘ˆ«ž‘pînØZsSµf8¯Zªün²2,â£a{H×?:|wÛ®q·™j(¿ž¿ù »›; ÂFToF õjrF:­=ìjyÛ[â7o:ÂG€bfX.&/˜±Ú øF ì8‘žg/à>ž-÷“0¨j9àa±!²ìƒZf¬öfY­2xp j›‡ìpvJÑÕ7"ÊÞϵöZ²Ï^Ó¥dÔÛóBÃ-6:ÊÞM@îwµÀd.\ÅRJ»åi㬄þ1©™>‘ƒ»1ŒÝß#¦"˜‘îè•^ü•‹=ÓUÇ¥T¶Äv¸xƒwt€>RÓ„•¥ñcªc„L œ|ÕÊõé`«ƒÊ@àm0û“wl$lÑñ6ñD{G=˜Á"F.01¾¹JCÐunÌÚŽFшÛ}ªÅpʃ3w‡ŽF[LØßÜ'™‹¯º/®À~š n"¸R×h÷Æìn7ÒT´Þ‡ôÿHËÍD´Ç|e:lØÌÔõ—îK(ËŒ“e9SÈCõJÒ–ÆÜø{ü`Û$T7Ä®¨ôt†Ëm{*Cn&=×GO#]@Õ¥$îï7\í_w_ð{kÛLC Ù ¸ÆÜþ²àovAö~®\²ÜTØ:Ù ®WÌCöÖ9; {a8ìÕÜžü~²/à¿Õ^pù­uþ×ñì…\ŒtTÆÝä–½€Í.É^€äàçe/P_€K‘½y mûÂà§ê ðU­÷r1Ñ.Ðx¨eE¢öÎu-+7”Ú4 åë#{Áýª–&F¶×xÁM­Ö!8{µéäJÀ.Î^p•`ƒg/PKag/àìqË^ˆ±oå\Òðõ¹f/¸³ÖP\}˜Ù TŠj9¸ÒÖæ´_ËÊÝô½€ Û&{†®U;!ûäM³kjQ-½È¶™Ó'šAì6Œ#ËCÍœ¦šZgµgNø’ížÂ·JÇr®/7.ʹ¡tîà?_:îü cÃpü8 ³ßS:nB”sGéøâ(çÎÒñ£¢œ_–Žåì{üYÛxиh0Æ.óúTTð‹-¡*o+ªwO£ÜJV>>ó²ém<ëDY‹(Ìz‰òdçé|\?¿ ù’9~I”¿ì†+Ê­‘G”õwñcãѨsÈVöíò˜b‚QÁ‘<6‘ÂÍKœw¯p /Ä­]”U¸¤¡Çé+é`‰zŒ3âoôÖeßDS‹ žÍQYµ3E9_H¦ð7Ùê„<£œËkq­çßoѕؔ–™Où\-MïÀÒô–ZŸ&Zއmc/[Vù}Y[ÖÍÎtòÝ$·£7[P–EwÁs1:½ÑŽ>߆¸ˆŒèeY’}~p¾Ù—+ŒâÜÿ™X²—Yz3ÁÛp”-Çv6K{£gcÎÐë–>³IåŸÛìSRŽòÞ‘jNá²t–ÿ•kXgÃ)Êîtßr‚‡Ýv£œ„_ÎùcFáxô>ˆrŸÏç‘Qî1|¶Gùo¸ÏÛTTð½",Ä¬Æø|åúx\Õ‡ã5Je¿ %ï+É9;_û½µ>_§Fð¥|ªŠkùœ…}ØG¬’D¹õ}¶@Ëïn<®¨ÞIIévø´¢åép__ß„Áî1„ãz=Æ0Wñ¯¨öˆ(»þaƒQîëÈ¥‹Qi«qâ»KÇŽ-Žò?xoíœwð~z”ù½ïµ@ßÅû™Qþûï³1eÏÕC¿mßM²ö(o·ºØìýJ]:'\fÚ{=5$ç?¾àQ™ýâ¿–ŽÏTÿ5ŸGFùßßF¹‡–ŽeTŽÙb0 TY$äå‘Hë`*ŸÚ3JÇOˆ >© Ø‹[ØŸR¤ÜÊòGÍÂËmÜŽOÚ¥ãFQû÷JŠGùg=¨…)oë ßiWÍÒ{Eé8vBñÃ\Ô±Ïpn˜eSº É…`VçsljAC1‹ëBqdé¸ÖÙa|*:…O­³ÃùÔµâ£ó+fGYû-o³MT8‹Y&^¹íW™ZÑÞ²Ö§/M:Ó¬å×Õ,‘½è"ž_€c-è cS8ÕXÁ͈jžJ•º†l4ß®:o¨sš.yÂ(¼TF21L«ì¥Ç½“9‘(ñé|*Õr>Õä|jKŸÁ§RLá~¢îÎç4œ"ƒb‚Ã̧êAZ.ÿÔ†#Šiý2N.º¹œú;Y·òkYÔ—¶cëø. óv¡aíkÍómX~vCöð‹OÇ”¾@úi”'«¹>y;º £a":Y©@–ÎHÅŽSh+Ìú?ÂkÇ=Ù¬õä¼,þ¢OgÐnè™|jDÏâS¸ì‡åÌĦÍüבW3ý²“+¼êß²]Q5wZ”õº‡;“õ¿g©ðœ?Îmröï–Ћv`‚’£B…kî?’$‡Þ»ß~ˆwÛuâ»·]mÊoØ|ë)6þç•ó7¹Â^¿»5•_¾l–fÞiKÜêP¸4÷>]9} øŽy—>òàQ!þåÃGñÞ‹KiÕ£g¼Âä<±Í~øªõÓOÕJ{Ýw‡,_¸ùôÝ'!å"“¢ŠÒéßßÞC !iÝUŒæ\”ŸÝ£Ý¶Zwô4 “¹‹¯ìÔt#T£E¬y ß.¯³â*W„ê…ñå=%=Kâ5üp®\=¢—˜z*Ò¼°}°a|EÁúÎ<ÛbŒ¢Ũ9¢é™ßâ°=¼4lân˜ !O59±§PÁA®'W‹˜g¦–&H*ýDh®Ö2rÛtùÅ‹2ùÑÅlÉ' wwöxáºjôßTƒ ²Á"#iö0SíóàNwéE®2鳊†ÄÌÊ~}&bÆ= \)â<™R†@õ"Šzg)÷:[²ˆ\d Ћ!rAÒYÀÐûÀK.†I/íØMîéÓ (:–M/NU«øÈªèŠüu¬æò°¥Žÿ¡¡N7)zZß R#ùÈM2_üC!ANM¨å¶Õ 邨릀a¬É1»£€ïÇVƒ=CªãnD윻ÿ)ûÑc¡ÆT ª¡­@üÞ‘†d âëò»ÈÛÕ!z§©c$¸f?ñà´æéUÿ^›-&¯è¥&ï~ðëFÇÞ +v&P1 \zøã¤ÍÒÞ? §Î§{Ú󽇗[LF“{PËXÑ(ÕzK-’ ë}^ALvñMö±PÞljæ§ìæj¢ì;Ñ0ÙÅ6ÙÇ/Œ7K9¾Èh6;aó‹Sjòsà0 hܰøíóàÝÇ¥Þ¤? M¸iâ‚_Øh߇dÖM£l›Nƒu8Í)ÜFÙitìߊ :Ml5×]ˆ«èyîâŠZ“Ïáèe-‡GbÛþr—¶%…ÞñbNp‰ÑŒb­~FÝîÿýúÀrikç Î/ÅÀ‘íœfîmQú¿|Dö‡K©kÝÍ‚½qMÐéà{n–ÎA¾+¥Uå.nGX MïøŠÞyWK<ðÎQáâwªu_ˆXEQÛg¼ðèõ”sæú»³$êùõ%YÎá^Ì÷)ü_ƒ›”ó×ÖD‹pœrŽÜtøþn«Á Jî¯[©|i4 º–q5ž*Þßj=ƒ_»ÏÕ}ò=Ãñ,oµÃ÷ûô=kTÏ ÿÒ÷ õ>ß3xôûzFŸ|ÏpÚ(½–˜÷?`pŸìÒ>ÁÅŽÚWgú´#+š„“†-Ïcc]…ë¬{zz LUÄÚ/â9„7›Î!jƒ^é’;{º#ìú(ÕA£¨Ëq¨WµÖ汪µ¸bò*¼ ÃÞœv^ºr¢`Ò›Óî…®œ@à'u]N£¢H¬[E1–êz]?¯Y…ª…:1Ât“FH7 ­ªËL«ê÷†B¯!SkAéÂëì¸:FIEP[}”ØäZbû]çßï ·CÐ0°ùAgt$Ië6¡a£ÀtA¾nª5®¶ý¤W¢ÚFë:¨ÚöâRmûã–êÿÕ¶¿óT§o4‘Ôsb‘šÄþºðh‚öÿn\똧º¼ þez@ä™bÌr§Káªë³CÑ5š.:)lþ÷sJès ƒÐà2¡é‚z‡&‡z©Ýr[å•¿uµ(³Õ Ñ;«Â‚6 º'­n.¼ê ?”TxC-( £Ã(Ô­ÿ( Ý{ýG«ÜYº˜Ò;mv-.²þ*­,ƒVL[Z×…Šø¡ÃB¥dG‹*é²×u¡TÊ;r£¶@ 쎮 uðg<Ô­n5úð7iT¦»Ú;=ìbÔbÛR/N‰Ñ¦¡Ë¨€ƒ žÎ.¾lfyxÇ^DÏ…{ Oo©EblÔ#­>fÝbÔì5W˜ ”™ˆÑo4W¨‰iå¨È»)®·è Ê2ÓáÎò~šÑòòóƒâ1úÉ=Ö鸕 ;µÖ‰×ÑA7Œ=D7z骶¼£W(š{ôżŽº‰ä£W¨œÓvHujþÂõÍi‚ibè—wzÂUU¿P‹"F 8*öÛ %_¿ü<3·~žÙ(Êú>ƒ°ˆqAµÌÏ0ÊÂÔÁ £DLŒ{ªðähâA›£xxé˜bP{ Îg4áÊè¢&¨¬’sˆêŠÒ„ÚOóZ "ÑÀ7E¹Ï!¿VÊé[JaAQåÔyD–¯„°œŠU”ÇÃLÐY\Ä÷óV¶C¾-ý»÷ç6E¯ª˜[é"¥½^:«¡ùDX]§•7Â1/½õ¥UN%âå/Î1Êתj›ü·RÓšêÊêêèû¸©¥Q7›?<zŠø¬£Õ­ -°£‚C—¦f7t&ëfÃk4T¦£³±YùÊÃZò×X³¶ú™­I„$’1 ãB>&Îí³Û’¸Iº¸µBçúâá–_þuuý-ßfáÓ“¸UZC—ÇZ?쉹¡ŽaR®©˜_åþÚ2ڲ˧ë}Þ¼è¾^ùÒ[Ÿš—lƒçe]ۚà/cãÆ†Ôqó’õs:àv+îa’lH•Õ¶ÇÁ¸ŽÌ·ir¢œy.vj<Çŧ—ŽE!~Yæ"Uü6£–Bfö‹ÃÉ ÝðséûN±¾hzkÃòä|‚—JãÅÏ'¹·•}ÚÚcí•òz"ë›S+9WvRØMùÂ(ÿ B—6ÔEù?$pÊ{\¢4•1b(Q™«¿ˆÕ\‡n$$^€BI’Ðy'ºlq ^\{"ø)f+³æL—ÊÏšÞº|>|éÒ í­5µ'FY?pí^Öš‚#;Æì…Í•°aEÉÅ´!Gy+Û`ˆKà’ºc]ÓujZs¬ gybݱ3æWL²sÚW¤æ“è8I%ljN&ëÚfÄ„¼cUÙâÖVˆÚ“añÏŠ nðsd ÀÂt~ò*HJØõ‹‘àyßÌBO·Q#œaè)™B«±ZÂQ,šý¤i$䓞[³H-Ù~$íÒ½ ¡ZºýAûcœb¿©Èž³ˆûå$‹)PFŽ–$°ˆ‡ŠJžèΨ"¾û¿“,du/É“~L² gß $‹‰ÿ¼•d‘YOê&YœˆÕÑ^’Å«9úöy@²¸8Ï(}žÕVÑ¡„ÓÁý6s œe—Ê_Í?~¾?˜ì‘ýÒ~ªüÕK¨{lD‹§µóS»Žäÿ„’îžžµïŒZû)ì|Åb𕻎ìªMvE‡®]Ä’ègAéʨ˜ÿ3]¦±Øÿ¾?š¼ö»&ø?~íª]÷~Ìzê Ñ^Žªßbdr‡·^Cï½uDx[µÖ™íNvé0”ÖMàO³øÂ´E{;£æö†Ìª¬ ›C>§˜N›öÌ“?är°³ÞIÞ¦=‡¬×kšöhhiK™8ØuÈÍ%ÇÉú“³i>”á4VŸ »Æ–M »N†q?ßó¯:ˆ€1or4­˜|íWñÿ[‰a#®¢ÃßÊŠº.g×bocìû6§7`ÌptÕ£îy;£ÁfŒƒ“·ùÄÁÉÛ*âàäm\Óso«ˆ#Ó ›!K»íaæ3Ä,ø¹àðÄaMö‰ú]´ö´]KdeûdÙŸK­’•F Úßíã8–Ì;öÞ6zÛr³¼µ!ÆcV,™Ø\”N7'1$N¶N˜S5ïH}_ÜœX’JµÏmIèÒ!‡[2ö}C‚®o8¾Ó¶¹hãžÅÎ7sYˆ2{x£ýœbÍ»=¶Ñ”îá^ËvÝ»òæ—¾Ó«æ×ö]Õ¦–X™Y¿#)ÓÛ…Tâí®Ò[o}¶ÛÎztF°wkØÍn j?ÄKû/°gôCëÝû±“6mjçf&9µ I¨ÙúÅ3oÁ©éÎ~±³|¿¬ýŠÔö¡é—º3`ÏÿÙ/cÙ¹·aé †~AÞôýâü°¯_Î:“ÙYPCÀ˜õðº²ÑÅ% gd^äöÇEŠ‘ðº-¤»íwï:¹ªÛÙŸápÆÃcv-u–®À z3oqÏm%µ¼»b×Òx‡Å“m‡µT–?¥ÏööÅ>´ëäôåߺ_TJ®ÔÞ÷ |7c땽¶¶¹f ê|çŽ.Þ4]™5|X½ÞþWoŒ]·ÎbÌŽ·z>ñ¶àøò¶¯ +vÎâ=¸ì›cs„YÔ¬ ~•›EéátÌ"’ïÂ: ä„Á¯Ú„¿.h³™JmèmûT˜£±»ú™kÎ66»õð |°û\êÊ#s”[çíÅ Öbv†ä\´]æBL2÷§DÓíþ4ŸûÓ|wµkñ]ûG£5/íÜ:ÚÁ—Þ&2¶÷fC?šM¥³¡å3õ˜µãј¢ÖäRÄTs¹°ÎéZ¶¼’ÿ+— gŸ»e‹únVvN°åí¿aNcÃvëÚw»ÆÌ‰ßYHæOŽe¯‡ÿã†ÆÌqNì.ªi^‰-Aûÿk<Ý\äóc™ü#]šÎüúCUHEÝ?¡q”«û®Éýìñ±œvon#‘&vs®^cñ ÀÿGÍù‡V÷\“¶Å¯9üÎåì<ZÜ\è„sÙRsÙäs1:‚mÌm»íº7Øs>¡ÕY Í÷æ®Æ~`ç;Ñãêï°S nÝš{Õ𮜯 ï*çv¡,øÛ]xßÚ‰ìoƒ{Û3võ÷˜Ý;lÛ‡Ù+—°Wïzû,êªeŸ”ö/\Ë›ÏØuĤҞžI`c)’68*žøÓhÄD.Ãs>øí’x„îksR¸¢íï ×B­ÜÆÎt5ß»š:¶ý”‡cYHó³µ Þ5lá]ûýÒïc‹Ýì&möm»E#º¯Fv}¿xx×UYÃÓ½²}šÐͤnûx”ÛU{xgWt@g×âœ•ì¡ îîGí’pV"[ÜÝO½P ë|Þm\s·A„ÛšdgÙ™ÏÆË¾v?½QŽbמ‰á]{õõg²³ *0¦:ÚºöÁûq½ï›'AÉ5óÆ(kâYÑô‰ãÿïðÿï£é“vç¿ä(Õ»Ñ]{ {Ü÷5×Gõskí5Ôð{Ù·ñüo›Ä Îa²5[fžTïä®g®+òó»­#š¼ú!S/µ^ß[ßý×tge±‡ãxk/T÷°ay$qK«­ŸGniì­pKóöÙû³Oý ˆØç2¸>¾Ív+â_6AÏÑÑØíVË¥°;N[úH ƒá^‹ˆc‹š;«¶ÂélOcÀC9RMšø %l[ÿí–ŒÚ6“ñÔ‰®r·Õ®íKÈäëµPì­È²kÕ¨‚n/7ä ‹m ‡=+^bÂ~KýÛmìÔ«°º{ÕæáÙßf¿}lµ?Xë­N°$êz÷ˆÂ®ü¬Â®ÏÎÞµ®lxÉMQ݃¢djŒ…zr•r:KnDàBqc¥ÛbÍñ]¯8¼Pö#Uo±ë”ÃeýµˆEõ[Ý `Î/ýÁ*±¬É/*9¯¥:Öøï:·ó{;Þž:ûÃÛ•‡ÃâoˆÌ¨çlpÓöv‹1âoGX™ñöÔë¶¹§ËÄÖ’˜g,Í`AJ«tòÙ÷Þ®ÁJoc_Ȟϖ™ÃÕ6‡×€Öf9;ãwíçîCã¬8>ÄiafVv´%%ìµ{Åæ3áo¬Ø-k·žEÖolîã®ÐãÜV/k¡ 'kò&‹EdÃEÒ¼¤=áuü­[ŸÝðÿŒMJV$EÇËGî¸õÔ¹³mîܩ̪͋mŒÖHHëá¼àÛ)-ÉVt€ÛRõæ¶MN al¢—F·ZO5û1X¢,놗ô¡›{®ï½ó™ûw>e0V±–: \4ÜÝ|F”Àˆ0<%có{t,íÊoþª;LÖ“‹²›,Ê´½í4€U `½‘_È`Õ¼ÝkÛº~•]Ø…‰mØµêº }–ü_ìÍßìp¢LÏ\wJ”{&µn{+;ç÷Ù9Ïe猊ï,ð·Öë¶sha×ÛØ=£ÁXËßÎ}§@ —N7ž·ÀOTÞ­9ÔYê«sD×˸۸zvò}êËï”ïgvªû 'ðbʽ£º‡Åe¦›_Á¾ðû èïÁìom•w×o·¶½C n¯±óý.Â&5æQd†cÚ÷74ªc ‰Jëö†¸Cز*s{Ÿö}w>·ç‡é½áìÌ‹ÉÒeþÒmËî‹”×– wM@ÚC·…{ïMï:™Ù {㣬ÑMùºšANãþ᦬Z¹Ûg;BwŽÂaûöf~ÝŽð9|;©o'uû©ÚÞ.uõVçÙJ"Þ˜ç=“¬¿·1ËÞv*ó0}{¸GûûÅÏ5³z—Í5 ªsÍýÕϵæ2k,-Ì:¶.ùàd»¹Æºžî°å¬c·pà _q 3 w+Ì´¸Šù¾ŽöÞY»ÂYcžú¯k œšÎVíã-2WëZ+ÊÙ\Í´™ÁNÑnRÎÙrvýR»ÖÈÉôÉO逹nϪæÒ12¯ñ¿Õ«ö}z«y`ßkÄÆõU÷Jªíz×cŸÔvRj:å›ðÎszØžƒÈ»-öŽßÞÝh1láÝc{»,»­êçØ@3žê|ÐY¸µöa5}ˆ#50e­7h®ö؇msÎÈ«ZÐÁuKk"gäUùüŒ`Gr ì“‘WÝ?#íý3ÒÉ3íž“ùѳ3ˆ—5#_~göÎ}a1zWŸ ìïì³ÍKoé?g=0v*X¸PD®ì-œêôí‚¢Ó]ÈÙ¶Õ¼ì:´õY¡Cc½Óå4f~zrÚYíʉüooNötgNú± ÞœvçwåÄžPoN‹‡»rbr¨7§½;tåDì·7§½AuåÄpÑ“6tCNÌ{sÚnWNÌõæ´wÆBRON˳èʉ¦Ij²âCe&ÏÕgLŠª†á¯ŒßÿZ,œváfê\“6‰=Ð/§­.b&3›p#¹œ_4bÌél¢`Ùa'u„®?ª~„L+k:FH.\ª—#õ^WÜ‘RkÔ.)¥>¡Gj¯ ŒÒœêJ7J—T!ÚQrÇ"ÖÄ~ÒQÀ*(RÓºðí‡ltÌFµ ¦®Ñ(dÄÔ³?—˜‰º‚59 ŒUŽ1+‘c®Ýw¤S€¬u6ȽgSÀÑ¿i+•Ù0/Ù0/Ù0!vCù ±£ïìŽz飲“ÚtIPïÇ)“zoŒsj— öx\°e°«z€z©žÈ&Á<ælürëÇpíxvdLãé½Ïv@Aì ͈®nƒ\cæé`5kf›$ôãà+ãÙ8øÊþ½‹t4ÆE7½i‘³7G&³=²Óó;Tê*ªeâ…nd“•bމ’KWÑig3LçY{n’Ѓî“5éšøÉºõ«k“ ÕM>ÙUd7iUt²L¨“?e™þq þ;L.e8LÛß¿A«IÙÑŽ=LG};LRð˜×äά©<\¯[Öáâ;¨W‡ÓGL,LþtLÞi߉k“¹Ú¥“’n˜l§PSm³šßt ¡«'Ʋ¦ítq£5+3dB½™ÁpÀ ™ÕÄÏ” ¼¶åLÝòusš)kš¡Yâyˆ¯0kVÜ›Y³vËz“nªt—g[¿ÖfÈôÍ4(Å|³dW;{–.ëÚi³„@Ô½Y?Ž+>"6ÚZÃrYÅ)^8BÖÔñ#T±ê8BLÕq„®ÚóGjIÉóHíkíù#…fµç»Fן#u½Ö©k¬& ]²úšäÙUqf##]íÝeod†_ÃÆö 3–à*ÄñÝo ‹vÔ@!Íá@³¶0Pù]Þ‘fÏq¤l(ÇÈ_Å9Finúö0sPë† jæ1)P³ð‰48ÆZø< Xø<0Xø,|,|Ügá$YÎZø<4Xøœ,|,¼…Oödfáaþš…Ï/óì{¶“µðɾóÂÕB¥T„ú“7¬‰‘oá“›‡·ð‰‘jegyóàZ¶ˆ·ð‰Åoᓉñ>±Xà­`±À[÷z Ÿ\ż…OLs‚XÈ;ÛbF˜ÆÅ@Ü8ˆÁœg1kqSFmç¡MkªÁYÙL wþYÚ䂌3ÜÉöôˆŽ¹cî½ÁQo"~!&9é†6¼áÎcâú耉g†;ƒ±lA€v¬}PcÊÂÕ ‚òöAGØbÙ˜YMTE¾dÛ`‘{ ºðÓÌ C~z@ Ìé &0©Þ`“jînR žu“ Þ·æMÕOsÔ\¤ÚM0n M2hºSŒÆ.„5t-âšÍg*rÖ)æ¬) Ru\~ˆ±°¦ . ÒÀš‚¤Šiö5…Aš6¬)cÚ°¦@LÓ•µ–)@g5û¡XÑaÏÔ̆ÒךÙÐÚ î–™MXŸ\k¯f2™ R~°åÈFLÒDk•ÀªY …ST³Ê ¶cjD¹ÇÔ ˆ²«DSlg«çz ¯åîV3 Ê]¦f@œ\3 >¨;Ô ˆ‚DjD¹;Ô ˆ‚!jDk;aÖ,t8ãåDkÈ .dú¢£…ëçx:ý 2'”1“sf¶··mS ÐààƒÆ'Ë;„’œéÏòUýý(5Ô[Ëò“ÙW˜‰ÐG]–®vº 2”±¾yAö!ŽÅ|¢ìË3"vQþ²XÉ!ʾ¤6ÕŒ(ù¥)¼=”ötëA@ÇËEFÙ¯ÇSD|vsG“ÛWÊñÆÚŽÖVg‡µ²(çý}qùª0ÅϋòF6I^S*õ(ûçÉ`2}­l’—çc¯¼â4,Êâq|Έòç<¨./ýå‘Lg’´æ×òQw¡…CÔ.g¬´ô¹õßSï—ÎãùXU~ÿAõô(rlcñ_‘•ÂPF{\¨Í_ZDµ²ðèüŽdøt¯²yÕçc|•¥šžyäKq '{"‹Y»l°ÂZenÃÚ-ßù y”»Þ'è*çR†L–Xû¤ÅÕáÎÿwzÖÅ+I&“Ö•iùâGuœõ_Zœ‹ 'ÃPñxŽÖ9Ozû:×%xú½ µ*ã+°pVyÙ¼¨à³Š-/¯Š²?§ÈйG-¡ÖÚiôë­bÌ5‡˜Å[ð€ª~[+¨qj›qù¯Ü jÌ­_Ô¢¿hìV.ž¾ £#ç5"Ó&ߤñmÿK£4ÚCJo7c=¥˜OW4ì—Ž•»L9•»Ìâ>uxØ jÔ 0å™¶„­ÕåF^s &H…1~†O]"®üˆc<,#pX:]5p•CeÅPˆŽƒ«¤Xü>FHÕÅ‹/Xü‚eyVG’‘ŽßÒ¶H·¸§½±à±|ÒŸtÇ¢Ü[iˆÜzÞø ¾^”ÿ3oM6#åþ€Ä3¢¬—>,€ç,¶wáS(ÂÚi‘MЙ²31ô a-Ù˜¥|Êíjô¨jÎEgN`Ö§áUM˜Î§š`¤:³¨Åïý^í§rTQS²I¦a’_»‚Oh®Kr´YJºÅÿ–=£9)íçR¤L¦.ãSÍFÕ}çøó­biVóå/vÞ÷ €+Ç»ñl…ð5TM’fѳ·:”¨yï çi¨LÓkÌ@.ÚS{ŒKí]wƒØ;Þ\Cý®oÌó0†,™ïú…AþõðP3ð9 nä,1û4?µBÄ ù¡vmÍÕç,PÔ±ZIËÀE«û{§W“wûy;|v̽ØáÑ WtÓ4,¢:T”mèÚχBGîO¼¿¨‹¢,E¾D0ð?~?6Då…*ûì0D•¾­¢òo» Q¥o» Q¥=ìËÀÕ3]¿&r„Ú¦e}&š4iBÜrknNçæWö+ZÒÑÐÑêt[L'è¢ ÅæŒ…XKB^xžú½–ºQ"kÉ UZ!%Û;„çx«¶ô=D@ïö÷½;#½VC÷º{mÜ÷ŽM»¯wV(Ïöi貎kÎ’pèN2u‹Ê6GÏô=‘§&sœ±Áõ‚´¯‰ÕG^ÉŠ4¿ñšØPÓÜ­-Dö<¾Uß²€aWŸqéö;eÑ‘û¿8=äé5‰ØNF°Ö‰Ó:ÅÚc€1×X0m„™)ú¿x‹ˆê÷çu*FkºÚàÄõÏCr1úçç°6·ItÎ-=òsKÏü pDŽ@ìþ_‹ó˹¶sÒßvÀÁm$jÚ‘çspÝN>'fŠØï¢h÷ÿ\3™D8ÊÞÒ ˆDÌîÿµxj¦à—>­X<%¦iû÷ª.8d9áys ŸKD"­*SÿÔ±Òåp3G…;bð@ÿ¯ ˜Š¸nuÏmikÇç²7çrë@”~BA4Œaß;›Û¼ð=QGŸ9 ¦?ÈuÙ Åc8©Q+½ïÆÝcb;}©Î¼ñº5»_œ*×Kü©Ãs€ç+íž“ïÆÂ L3Ëó,ÆŒzÃ̤7wžðÂÓÖ@Ž}‡7ÅÄŽÙd1æÕ›;A´óÛ1j:wÌ7Õ\·cÌ—›y !a!"þÀQ[gÞðhwýZ›yJeæ5uG )0óWÑ0óGÜ3óÆn`}è5öú6SßçÀÌKhhÏÌ3¯õ™W÷žyóÔÍ<’ H›Hj¡åÌ{gÞY}Îö}4Ïf;Ž2bn -gn1 ’Nн}Bþ3þâ¾Ç ‹ÄÀÚA<½óýälwû¸S6s½(nòÃ+Ý.ô|¶½ifÛÏ9³í|0™óÂl/ ³í oÁ8'Ìö‹1—^lžÙöF‘ꣾL€0“~¶ ž‹f ºá¡Ù¶{Ýc7Ì)I&áÎ0è†!fûº!f{îÖÙ~xu;¸Ö÷À|c¬ª>ßÌf}¾+íœï¯„ùf.ý|ÃBATI(CFÞ;ßΠÇ 7×¦êÆš w2dä&³Ù<³I8YœÙÈ‹µsÁÃD”™[eoGæ»á‘v„Ž4—ËTp~\ãŽÿ± äk£ÃæØš»n¦0Qå  ÄíÍ1wÞ€3ã\0w2hæÑÚι»+‘pB³fî¸Ç\H ­m6wþÀžÏÜý ›9Yñ!ÉhmÛdÆ¥,íà`3c²Œƒ¹™Çöâ÷͸¸’¿NÓ?Cvvò¹ñâýH½yÓÌ7ždÍpdsã æ¿¾™t¡÷ÞÈRº%Ó;ô}šsk Pß}6ĺo”;P1µ#(Ê%íÎ`¦›+"ocG-†€ ¿õÁmóFÒMôÆ÷ö†p4á©yVŒŸ7ļý¼!Nå1âÍþv€Ö”¿ Pèw’cþv€°´ßwHšLéxcPˆ]y,‚Èô‹Aô÷L\n1„¸¶ÚþƒB„—d•¦¼·¶¦ùÐö„3íªý"D‰„ÂÊv¿+øÇèˆøÊ%¸JnÀÐEYÛÙžØÿÈØ÷ÖgmOHô0f H Myï€ñ™9ì˹d™‹¯^c|K×í¹ "oJx15ŒÆn€`†6êw^Ç’Y’Ô@Svߟ1ÅgÌQÑ&Ö’Ù¬Lg5c\«ãZ­˜ÐÁ»ñ˜*®al¤oµ£‹ÀÅ-ÄÖQGÿgv#+åjn>f‰1ÚTp;¿AßÞlâüS¹™ý1õ|ÇÈÌøùv¬2ØË$ú}…•ß3ˆà{œ„É¿gXu~Ÿ0ãÞ„ØÖïp±ßàbo‚ƒ9÷»‚¬Þ ¹ý] –b§  z¬€Ø¥ß]ËrÍ„¼™ô6¤7ÅØv¶]!)˜#)‚)f6÷›a»µÏ ›¶Ù¿íá- ƒ=´þ(ì’6v»!Önp;¢ÿÍüoá?&ÇÌ~8kqþ”­»!ÛGÍgÂHzb7d&Iö˜qÓý}ÿ{wƒ¾ÌX…áÍx²ôøƒ½î•~_°üƒ½à±sìo—dõ7rû›âý{¡=yÓŒ§yg‰Å–ØøswÙb‚†YÝ$•áQk"ÇÏédZÁl93†­§õ0OfÜÝ&c†{]„·ÚLÙYZ&x™ù,y〘˜l½ÆA'^¾>ܜٳ1ˆ1#¢›_æhÖRµÀ$’q ãpµ-Y›ˆƒ b\^ÁÒsu`DeZ,_÷d—5{E«¹(Ù¾ ¡©¬ȦÒ‰Þ¹:”ôÇýÀÑ ïdxØì$¥;1×ç‚ùk ×rT?Ì÷ÀE ­ øÐ4û^Sa£ÒòaHíø3…5Ádk@“D*o*¾·†±ÌÞî0íck@æSé h¦é)÷ÖpP\ƒ`]WˤxÆKÝÉ/rÜ^î?pš%ßø{Ã|ñFBºyö¡U—§á {Á «J~ý«é 7̱7Ü Ý™Œ³o¸-ú7ëí wH÷¦üU{ÃÍÒ¿9ÚÞpßtoJï´7Æd„{S°7F–Ú¾)þ­½1¢¿îÍëì ÷Xÿæ™ö&7b\<ÔÞ˜;¯}Søþ#æq˜UoÈ WogŸvD=ç>#8†'ß‘ó1#8vÏuåÜgÇ⣮œûŒàØFWÎ}Fpì§+ç>#8ö^Ø•sŸkr$äÜèrrëîÍi9 ]9¹›÷æ´|‘®œÜà{sZnOWNîù½9-ß«+'Ü€ÞœæYwNx½9-O´+'œ…ÞœpÍë9á?ôæ´æºrÂ¥èÍiyÒ]9áe]ÏÁ;Ÿƒ]_7§bM/ÙZ ~í®ƒw¾ŽnÓ6¦Ž`ÚÆ`Þî:xçëè6vcê°Ænl'w×Á;_G·ÑSG0šc°uw¼óu€êuXãM¶ƒÇ»ëàÝCftLÖŒÎ^£0¦kÆÖƨ×aÍÙ: Æï®Ã,kW¸£^ï|æ~Ð]ï|`‘z¼óu˜ûBwÖä‘­|R¯ƒw¾s“讃w¾0K½ËW³u˜;Fw¼óuÀñ«çàϲžÃš˜²µÂ'¬çà¯þk=‡3lrÀ®çàϾžƒw>譞à:—ƒ«a=‡5~nsÀý­çàÏñ¤é¸2õÖ0š­Ízk”ÊÖÁ}´žƒw>‡¹Íuç°ú*6‡¹éuç°/6œæzÞyC?`ânC?™¡ÂöÄÞ_“³z)5g€¢ŸÔ^°çs˜Ó@²t8c ÛÖnKfχ)%?×/òËòëÑüÍq¾æµÎ8Afq'5¯Ò_¼eè¼ËpÁoôg0šõÍ–Ó…¶ÿ—-#=qö@¸‹¶¾aýËÔÈåÔ›ºÀéb4ð€8çÀ‘®7\¤­‰åÌkÆ”†•2ó&YO±§€ûV¦låU¡ª(ÕCU>P65Ty‹¬i¨ò³àÓòÚ¡*$­FmcPBæ&0':Ñ õ^µ úR\ù ëÜ]9«œZ³Ê÷ÕŠ^¦ù Ö&V­h"Rë`Í¢j,¹>Õ:Älƒ 9t(€Z‡ˆY"ô=Dú|Ò=lUFMT+†Ë©±µÙi_aÈÖÒÚ™®}­Ìr p ;Ë6 £óSvg¡ô”uƒÞ`žÊ› r¿VÝ‘0+×sBXFÑîj{k(já.sfëã¿¶FT‡²úS“/‡~!Î>YV;ÜïpYçP¥‡ëꢙ>ÜÙÖ7&TÇáÚ,ºâM• mi€› ót1þt™!»blÍÓ\ê!3dŽC¬ƒ™¨RQýLf Ó;3OŒkŸy¢Ó{Wzr@.·¤£`”ŸIGa,ül:Šå‹w§£XÉæˆ½v«±Óôséh:U3e@C½ž)›,šªY"רç³$¾¦>ÍÊTÏgéz­ý2K6L0+×öÙv]Ÿ-k{Ri˜­QïgË"ˆj£ë„Øs{=çp7{–Ì,ä`•åkéN'ú×éfýdƒ=ØO·³æÊ@ŠvÖ\8i®fWýœ+V¢æz®˜êëÜkâ~È$*ø©¶}ºçd¾p•æd¾ÔI4ÇóÅNОŸ¯¹Ñ^ eF‘†HÝB;r‘ÚÕ ´Cuõ>VW,]sŽX ÇJÁN3u¬6¤æéXþƒ.ÕÜh~Ê<’ÔIê*­^,”ÍÚBö F‰¢¼‡Q¢…wÇ}\x·›€¬sÙ”Ê]Gÿk²õ±ðµ¨»‹uƒÑD,oCÝ=NÔ&>NÖv;N·`AÝãÄiÖ&;Ž®p¯;ÎÌ÷79`ƒÌTOVj›¨©%Î×ä0»{s‚½ÁhŠãì5©O}sÉÁÊ7Ìt ¶QØú£ÉÈkvÞ\Ó¹,ïÐsÌ\ À: ·¿óŒ¸>:`,¢eöwþÂL y3Bز±öw0ÿãíïxë=¼;Ò6Óˆ Œ Yû;˜ðaû´¹Fb½›ŠøAÚ4Š—¦æ¿v5ÿUÚâøf‚»Cø=ÉÏ QW3„ ¢fîsÄØ¥°]‰± P#ÆÔsy ÆÔs wL½A°nêÙ« "M}nÈ[Ï©Y¤Áz9³XÏ©alæÐÚÍ,ÕlæÞ÷”_3žƒÍ¶OÍfNÍè 7¥š©læÐíšÍœša¸iìʚ͜ /x›9LLÍfN-÷¼ZîŒlƚ͜´÷}<˜Á‰ß ?!qÓ(çYñ›ªäi”Õá3eÚãE#´¢¡º´„pÐU:ê znQîõ¯ƒ"X”Ý> ’Ñ¥ å¼ds’j)…ØÅª&Þ¿ªŠ1Ey¿‰_uö2~Aú]TðO™ŽŸéÕsdÅšÐ)‹_Ô«Òç*g-8ºêøÊòj§•’ÇÎWe•ŽŸZYU1wN9.H¿9c~ù¼(ç}â¯ÇzÍs1ÑQ|oMëR¼ú¼KC/g/ŠÊ Çù”«ƒ§Y;HåtZô|Â2m±yŸ¨à=i_,7›Åµ©ü²8UTð¯öÆS˜£‚Ÿö¾P,Êý®½0të(ëSFçՙ׉gÙ<â¸7å žq¡ QÿüI%edȧJ—þ¡ >Ú¬ÿT~V]½œ~ò¯¸OÌ*Ê)½_‡ºj§ðÏß-ë[_:hB†”…:Þz£L¥ÔƒJÑ¥ƒ$å¬þÒBÆAäÙÚìIŠk÷ñeƒWŠGS’Î1²Ó£ŒõÈZå)¾î¿éñ–G/MºÏ Ãw1ÀBë"³-P›™®Jó7Tù±ü-c³_²¤“H…«µ³Š/¡w²s²£t̘qQþ‘ÿ]^6Êÿû¾ÞÙõöæ¥%D¹¯¢š¡·cÏg&zUÿŸj21Ó §&ú/ãdÚq3}Ðd ç<:)üîÿ§àY¬½·!?™Ó’Ó íœ_åóœ%þHŒ²ÃÓ7é“ûƒJ-CeN{ª–¢2£Q‰*þ Ó†±&„ÊÕ @þ³«›ëU¿ ¸| ɃÌ+dÐÝ^ÜS,}¶TÞ¹3Üû0IZ6˜Í¥•ÿ}#G¹ÿkƒnýÿôjÏ}b/•þîÁU §F3JX‡ò)OV¾ON°2º¨É‰=FyÏÐyfZ”÷L}Oò®Š3Å:]eä\Äåþ+KdS”ÿ¡xÙÛÎ~’E Yñ‘󫇅édk¦¼e½è^­µJ—l#­¦* Týû4ÖHü*­ì'n&â·ýÏËJGåƒ`‡ «K|³'O.¢ûý‡“€jñC 0¶:¡ªtv  O\r:JkeÓ;£ª¾´lâ'»÷X«çPþ'ÇlÚRè»Ô@Äw©«4üd`–Ó÷÷Cë1ŠZôX+¥á'ÿ§ÇûÇ3ÜÓb?Çô§Þc ×¾[hÛcôt¸ŠÏÐxÌüª2a?³\µ¥i–poz>îÞžŸ6z r#³b‰“îÞÓ7ß{î¾÷œŽ;{¿%ôÞ)íšÞó‚Û»T—šþ¦oyÏ¥8 RG›þfËî˘eNûvɦý:Véíö,NQì\èÿÎ}£ÜU7Œ+]ÍžÖe$}«Ø÷÷ð5ìag¹cÛù ·Þ!»Á»µÁý™ßø0Zes; snn ®R¬²°uG€~k¯Â½ÍcîÑ<õŽ ÔÙ½9íLvåD³7§Ýa]9I×›Ób®œ¸#{R±?ä„Ù›ÓbØ®œ¨N÷æ´ø°+'î zsÚ»GWN´{sÚ[PWNt7{sÚûXWN”¶{sÚ›aWN*ôæ´wÔ®œhñöæ´w殜a{sÚÛ{WNÈ{sZ>BWN\:ôæ´®œh ÷æ´¼•Óªy³…ëêÙÎ}ÝÊá6˜±žƒw>X½žÃ9¹ù¡“n@õ¼ó9¸…ÕsðÎçàVÏaoc6·ÑzÞù܇ë9xçsp#¯çpŽ(Mxõ¼ó9àMÔsðÎç€;RÏÁ;ŸþL=ï|8Dõ¼ó9Qï·êëì›nõu\TuÇ®ŸS.I­Q•”DÝ—Bc©,fù•æ¸ ÓjÄ©Öyɹ[Ô7î¿Èx£e¼qkF|E=M2þ¥eüË-ËÚ¥ÊXäVÆòÄ8cyâÖŒ 02‚lÈøbËøâ­q2AF«Fåßn¥ðú@ÆŠü?(cECe¬L‹3VpÕÜ“ÑiÎV¤¯MÆë-ãõ[3¢ŽLFˆ¢düËø'[26˜?Ù©¡*cÃø8cÊE=A¹d„GOÆë,ãu[3'=úFO”Œm¥$ú@ÆF²±QQ±Æ™qÆÆ™[3rsÔ6jÔ­O´Q :­4~Ô2ßÖŸyŒßaÒÖÁ£IlIip6 ]‹ëÝ$ÝWenz¡«2ËÌM’-fu­ÙŸè“{_®ª&Ý0¨ œHUðl©ê­ª_t ÓZU—¦õº‹é:Ðø”Æi“tZ5£MÒ?¾ì§'ÜÑOšÅº÷“~ªêê7êž>÷É¡ùÌ `QeÏÔÑ{5®8L}Âòð †,5ÛT ydPCÕ§†Œr-[ƪ!ïÔÇ5d¦Ò«!s‰ËÔ™ÃL BÉ_™F5Õ¡ –±UFæ¿Wiµ>R£ì`æØ+#£=í•‘´Z©…c¯Œ,k©22B2^5Z¯ŒŒbWFÆ1‰WFÓyed¸ò^^T€ÁèôC¡ÓK ]bö 1nèô³ZÄ_3½m¾ØV5mk4Žk:´ÒPN“¿â¦MdéÌ;Åd*÷û}¶U@= 9Pïñ‚ª 3s-AUYõ™ë Ø4SLþsSÚ¦^T}pa“éŽW/f¼bò,ë'S :‡jêRåç¿L«ŠÓñ×Tü§yUqß#ÕÒ¡ŽBv¶áxNvM$W{BtíÚÐ5Ía4k9/@º¦\{ríÈl¦šr­24k]D££†Ð@f«Õ4¹ß×4SLÐǃæ°SÌ,œv?Sýaå¯â %ÂeÖ¹$ÍgßV®½Š½N.ùÿî}T¶øŽ4á¡]:-*8q‹zÀ£Ò§‹I/É;«¦ZyÙ޾—H=‘O-ÇgmáºË9ÿŒQlÃÕ(J¶qÛÎx±Ž’г’«Iù6¾uªÇj…X+³…ºìÕN7ð9;*øÂ pñ4ÔHeîÿ|N >µ…J[| $ïgÕS+_ÚBIõê¦/åSørÍVJgñ 2hboB~T®ùïAnd”{y4šV5µdýܛ͉šÞÂçlŽ«ï’—AÚ¸Bb<P#ólªÚbGûOµtÜópËð—‹PŒ1Ú߯51ETú„ç@6BmJWòDsnµV“ŽmœµÇ4nxå T‹Ie×4Sg?L ‹ÙÃ^±ôÏÐÕT­¼U9Æ¿«uÂ@¸¼»_¦ ÝÄ{‹° †ÑÛîË«·Oůß;ÈÅç=° J×>¸[*ïÚ²¤Êgo^såWmÞ“å37/Úòi›7u¼tÛ¶/_½1”?¹r”?¿³”?¾%·£÷- Üèt˜Š²ŒfH!ÑN™ÊuyXԦꆿ$}ãÔ(Ês]Õ-s¯\LÕ?2‰¥Ø•Ã#™ ó'xß/qC,ëBöXæÝŽ÷‘e,ǃd6 Ààw¿Ìí»¬+n–yä¶eá’{³ûeNÄ•Xª¨Õ£ª÷Ê\T]íWà TäÉõÑÄéˆxÿúÌšUt4|4q:!Þ©~…»eƒü±<š8ïT¿{ 2V“&¾UB fT¿û- :ëIŽtÈ~+¸2¼!ýîÔ±W”¦ ÑAôa@âŠðVó‘„i”KuÑX9ˆ ï…9.­·”߈s˜&Ç~ŒvÊäÑŠx?¹ ¼ü&ødMb¼tTÐöHs…xùMyPšdš®è­¤õ^,è² ÒjsYu+dšJFÀæBw¡—q&§†€«9PÿÇïÇÒjÇ õ!­6Ð÷¯KZM¯ú°0'ŸI«5š±Ào·%—&ŽÄW±lÌŽµ÷Ðv }ȉyØ”¶dc²¶=ÕZ„s‚K“Êgœ»|œÈÇÇô‚ÒoâÝî¼?Úõ¼yb‚¼79¯¡ÜS}^x¤ôA$„Òo¦ÍŸhU¥uAUà½@é7•ßC="ªÊuO8lb‚þqž•{ö- žFóÐ凮UDåÁürÝî,¯Ftvs¢=¥’Ò@›b"èú` ¶€ó’+‘·oklhjh™h}Þ _TŒ‡Š¦òo5´•ËÆ•í¨ ™­¦ô›{eDÔÀXå¶}sfÅæ)“Ý»¿1PmM™ªÜÑ+ËÑŽ­6Cù² .¾«×ÀtoŽe¥¥?ü›mWDÝA†¯?ÒÆP~fÒ2¾³C±Î ì̵…þtå¾} dÅ*—bÔZß ß˜ø–)ÚøbEbôe ±–Òî¬5|7ðã£7ü¹Þ¥Ý=ÑØ®dI%Æøã®\´3‘LØ•”"Ÿð¯ý‹îÂ$z—¯/^åÊ\­Þ|™y˜Ï*¦^ïïáMód̽¶cÄJogªnÕ:º+wwÕßÚU·{¥ëAwÛ¢‹þÜŒØna'¨¯Sû:UµÎ+Ù7kq×~Ôw5FpWÑ—®:Flšoú¥^Òãb ¼1}þž¬DreTb'ìÚz\Y-÷Õ-tŸ6ž˜[ú’½ º=Í{ã²X­òf·ÁD^öºš7› òNyç &ƒy¼Ù[ÞySÉ`o˜w×#Ì;Ã;oøRÒ-Áüò]öúÒ§,ÝÉ›B%ß—3¦˜coZZùboÖ[ùbßK勽Afa•xMÈwmÈ—÷#¾(c¢9Ù9“/ñrBÊ—xyåK¼|±-!v­Éwpcèï( òÎ, ÁBÜ=°å#rØ» Ï÷ ]cÄn–¨d{ówA©¬~äÀ²"žíÍ¿¶3YÛA77®ôØ *º4ícî+C>¾Õ¸¯7µ:6¿nı1f«]º¬Onü…LM§lÁVU9Ón•|”º2ÕYG¨³+÷åköv'÷À²ÕÙ2àº">±«6*êj$U1Ñ}÷Ü£zÛíø~½ 1îId@L A#ìß6Ô@ñº¸Îøìþ:wcù-ÆŠgþ¹#þõF×ý©^aÀž‡?¿ŽŽù ¨þ¦0ŸÃïaÀ¬舘—ô_ `Eõ&lÁƒË€½hð 79^[ð 7ØÎ»5—yƒØ`˜ëŽóØ wSÈw[1õX\ÖpYkÀeãCŽM!‡Ç›äð˜Žß x­p™¯ Lç “#`7[…‡’ÐË$ô2 ½L>bÞ¨°bII{É­®ôùWÿòÿ%QÉÿ„y7ÿwÆÿ}žZÜÉÑ(o*MCLwÏ4¦{hÓ4µ„Xkˆ±Ñ!ÖbãClBˆM±©!63ÄÚClžábä:qñ ÛþÚ[8’¶Kýyü„rDÜ;d]x'ôø 2çÞ!WÄ;Q¡ÇO˜?Ÿ¾ÛwÈÅòN„èñ¦Ï޲w°…x'Zôø 3æGö©$Þ‰=~ÂÑó£U†“‘eÅNš(Òã'tà7I–˜äßCóM5mm„9–niåÑ„ÃöÞû«‰385‰L=~ÂQGEï4 Íþ¹¼€4Àø 2—˜Ã/F×9üf&Õpl-ÉÍÚ»ÿÍ:ެ곂77õ¿™Ï›/÷¿™\’›=²ÿ͈/Uì¤wJ4Þ"ç&jû£°$Ç Íåmš|3ç£-ÆlOµó¼ÈbÌðÙcn7XŒYÝf51Ÿ €SvZfïÛ?HguʪAî÷ûÇš¨´³)ùŽ˜I(À8ø°ÞûÆuçbÔüªžÛÒž% 6cxÜ9F×FÓ']·êS?(Ä|C„_aÞÛ‰ÍìÚÛaÊ[‰MîZüÂ5ûeí., ßvpUÞ~wWÕçM©Z|å_wõdv¿rXeÕâ臋¯ŽêV ;áä§Œéìþü°E’¯[µ›1Û¢â®õÑê[4ù`ËkfVv «ªŠ>|Y×éÙ…#`Fèí„nº©fÞOl4wŽèlØÛèl;i'o5çSUS;Ûcƒêž•æ·Û׊夞žé½æ =nÝÎLlg&ª»)вF²j7ÌóVÌ÷„±Áp†—*e7x܇\ÔW,¦›YŒü–™c#vS›ã¸N…»9²je ‡~ÈaN>þÍñÝ~Žì'äïr7³¾có;̾•´³¯nÇÂT×9*÷¡Ù—¨ < tö?”žý2g×|¶-=÷cúçþÃgŸgÞ_Ø7ï3Wç3ï•I¼;…‚¸+Q̼3ë#l®[ÖÀN»é¢oa,S ÁGñÖ–?ÍftæÁ«÷¸Õ3—Ñåãó›K¤:;çrf˜K+EhçRb=´®{â±ïû¿s¹+à­ëïŸË o½y>çoŸÏñ6Ÿ£×ÀqÓŒÆUÑÔ¢®Å9—dfü´oV=~Zõç=Ú20«=ð©wVï³úe›Uuq÷¬. ³jĔܬêîÄ£Qˆá/þï¬ÞÞŸnÙ1¯à§M›çõìíó:Ïã`Íj¡*oýÓùNªr»÷ÍÌï|7¿[»ù¿+§¾UÀCûæØã¡%ÿqã¨Îq/zôÆAùþÆtÚwã0.‰ÜK^/†Ü?xÙÈÿ‹ƒïXè¶ÿ¸U­Û}—Lþ6Ø÷…÷bßÉû¶­÷Þ¾}Å!3ï½WÝÁ^þνJt•žå©Ñañ,Ÿ>{áb¨{¶•Ĺ™gdÒ;çyC˜gk®Üγf9&ö‰ÏÎù¿óü™€¡îzäfuíæ¹Þ²c®WlŸëö0דװÙ4ÛÎzpÆ“7I»&ÿyÆmšñÁ^ÚÓÙŒ¶G¶·sÆ·…·fØSéz¸sÍ©WíÿgüÞ~ìuÏ#·«›4çÏß9ßÑ7ç×®Áœgο̜ë~dæüæü7ç&÷0çgÎâ9~>s®]­·z“Îù¢5¹à³2ø¬>+Ï4ߊeøLØlëzð™æç+™!3ÿª!Çkûv¼Çk­žÿUÑá÷Ìÿ¿`¶8æ¿Ýæi÷Îù¿1Ì¿•I·óX©ø=ýéþºò^îÇ 5Ñ Å¿˜w>s¶vf#²õ‰¤éwdE/<›V¨ç£»ëòvï¾`æ î¾÷Åè…Yi8›{ƒ½Û= nª¸Æs`‘So}F¥¥“GWÉ÷ÙÖNí ‰µç™U{Îï¸[k¢—è¶pÌÝôüÊtÏG¯ËŠ^¢žómîÛâæÁyÑû˜]5¾û”¼ÝK•Ýö)7 ³ð̰+æOº‚9a_d9˜— Óó’½]eoÓü½;¥:WfL¢«î«Ýû¤Š%üý“¹òœ:bž¯Lì¦m6 bGr©Ú(°ó¦X%Æ¹ÖÆó¶ÌÛΚhÙà¼Í¤çë4o|›{³æÌÆtoVÓ½¹åˆ3Ù3‡Eæh]˜Ã¥Ýûͬ˜Å­ù9ºë›\[¿Ÿ]¸i&·}{æ²ÞZ~<“_Is]ò=3é9†Än ±»l&±nÐ9“ãÃLš/7“²v™s§¬-Oùßw6a½¸Ê°Þ?Ä7šxúÖ;›Åzß$GƒÃô÷mÄô÷:L¿ÿVL÷äwlà)\yeÓ÷öXïf´ ŠgcûX¶#¢îw2Ó»œ–C|öÛ ÿ¦ÅÞ$áÍ{SoÚìM1¼‘ž…yS o¦Ú›rxÓno*X~°xR}rx²Áíøï¦g'õÜ}ÉŸñäùϺLæöZžD±æË!æù¤ŠÅËó¥:Ä·ñ>ü%w{ï}ø.ÛOw¬yg”5 ó!ØŸò³-½”¨kï;W}r¯NÞ'öÖ쥭ç|·³ëäÑ»‚½3»)W´wf?åïJöÎì¨ü]ÙÞ™=•¿«Ø;³«¶žÎ»UÿÒ¹öhƒÔvÕ·/ÉÍå»êö?ïª÷ܪ{WU÷žÂ6Æ!ö¹ûz&{ byîT¯ƒØŠ°§.÷ï¶§jïÄW÷†=eì¸=¥41÷‡öÔÕϹóî\5zÜ»ýSà^IŒ ÷ÞÈ mpøE9¶‘£Š_²7~ÉÞdø%{“á—ìM†_²7~ÉÞ¤øÅàëýïÅ× Oâk“«/|/º_w-“°GüÍ ŒãõZˆy}bžçOÌãbž‡OÌãqb~Í=†RL|Â,æùeØéÜ);f7OÝN‘=„Ûl ì_´V;åÃe=·Ú.Ù5‰[æ\Œ}¤7Ù…à•_-ìÞ3Ó·vŸdxg?‡w6ðVxç÷·ÜdÁéS﻽ǻ;œ>f+NÿæQºÉ¾)àô›Ò8£Çéw¯y˜ì0ÜÑQ`¢ç‰Þ؉^÷]/û–ÞÕ0Qö®†‰²w5L”½«a¢ì]&Ò»Ußê\{˜H ¿ë¾Í}˜½žW?sŒ””Àz©b$!Øö·õa¤º[i¯­Ò^ûs\ÝgÆüµM7á'°‘ß3` ¯Yô¿ñ1¯³6Ú0ü{maC¥÷È+€ÛcX[ñ{ û)ÂFƒÐK¸n+6^&Áµàö$l`æÆ`Má„öOÅñßÞ¸33KgÆc´èØûÆHwfÛ[°œ·GCÌßÓ1~±ûΜïkzëûŒ••Û‘ˆ’Ñ€ë§ü®Ïg­/8ÊÙÁéÖlq½o ÷æÍÿš…­ÑÈ{faDÔ%Þ=~&ÐKñ7fÂßxˆcó—Îù¸=Ì3áç±XíÁXžxÕíC(ì‡[¹¿ˆù=€˜}{€Þú>cíB{`Ï_³ó{à°ÁYxhtïfÂïb~`afß`&¼] ÙLÜkwÆæ±vgðé-ÒÀíèÍig¯+'FDzsÚ½Ô•K%½9í®ïÊ)û™{sZÔ•ußÞœæYwNÄ‹{sÚ[TWNéïÍiï¬]9¥w¼7§åtåÄ[ì“vŽBÎ×nÏiù;]9±ó¤¤SH|oNˇëʉfooNË“ìʉtwoNË•íʉ•Þœ–'Ý•S××½9-¾+'¸ž´´r¾y{N«Ñ•ó§·ç´š(]9…„öæ´z8]9…öætU»sbv¶7§ÕC 9­M4}ê6yx÷k?hÖs8Û‡?´ÿƒÎY=ï|´më9xçs ¡[ÏÁ;Ÿ­ÞzÞùègÖsðÎç0†OºsðÎç`ðê9Ì@ºèÖsðÎç@+®žÃÙ¿|ÒúÉÁ]­žƒwÞ{¢ÛÑaXÜÖ¢ ½çWÖÕXÓX‘…„ù0f„’O[R¶| bhû^̈TUÃGâMÞð ¾uEi É¥7ÈHn R®‘×ÛF1÷Åši–¢t#›¥’~R«“2h¿ããB?®P_臮aÌE¯uªdÚŒºÊpÍ\=bêl~7ߺh @:Æ,ê@˜äºVF»€|c®z©=†3PÖ]Ôõ–¿ç[à¿e³„º1: $™Aãø–âù nL 4&ôy0ýI¤Áx/N¨ßø¢QŸ‡p-OPãòáXÉ|ȇÝ}6_I›ãÁ6Q’¶ÜƒMNe\ø¶æRC@­²ó¢Ùk¥7i•åõf¨‹*'T8L(X=ÆÝ…kç0úÍb¸lĨ7Ã…24Ã5›âÉ ×u@Jy#ü§þðf¤®í!QÕ9¿ØböG{ Sï(ú‘tŒÝ˜ØOï5ëûÑAfp?±³…ª÷ãºSïh̶1“£ÙÌâhTæÄúŠö‘f¿ 9íW5˜RcˆÓò1Ì_ÂÝz óŽºßSBÆ‹™ƒÂ;³8–JØcW/ÛàQ'ìš6ͪú=ŽyaÇa÷ ¡îqh\$ô{}‘:p´?¦:1?wÀ—ùVý  ^`ÈŽ)Pÿ ¥;î@”Ï Ô=^Æu4Ëã1ŒQevÝfÙ™ /T­~ŠW­ãu½ót<û ã:ã¿ÏöxíIÍÁAÌ" oiohÖjRï’¡DÕp–¹®i+vö¬.E3\8–}"õîà]²Þ¥Ûå`ÝGÔ‰ƒß÷6ÅÁÚ.ªømfUtèãí1QÆg4M“t×ÒF,|¢í1f{2Û#b«Þˆ™¦Ã¦Ä•6Û)ÕcÚÌN•gS£ÊùÇué‰:›´¿íZãÍ;ZoÓt”®Û‰©`°ËFa#`À qÕi~ŒEû–I4}7Qñ Œy¯Ž{˜.êÅa2©¤)˜"œ£)˜¢KvÌáêˆæjšL»ÞŒ× êi—ȱ‰eô­I` f2st&»7fÎgRuL]³d–HÓ0ëÀ‡§A‰>³exÛÂ4Ì咮ɶ!Ó0KhMºGHÓHÛæH¶:èn¶Ó¥–!ˆvÂ\õVý™ËĨó¯z;$f£Îû|Œ$æý8ž†ywÿ~~{û4ØhÓp”.'êÅQºŒjŽ’Oo톣eBCr¾Ø¡º¾-ûN˜e®]šcÕ?íˆcµß4ÇJé@[ôØ7ÅÝ?öçÏà{›‘ýŸíB<ôö›·ÿÑïce{JÕ/”¡&õ{¡XÛê÷BÙ5Ò.\,±|íÂãÄ S¿×u\[àx™.R¿—¨êó]r…µ—|€oU¼äëqß—ÜòpßÓhúžn½>ú~6¨þ©Î¨ï'È™¶Þ‰2%¥­w’Ý4–Ânœ ögÎO‘$íÿSt±8EÆ’´1OÁéXàT™ÜTßO=ì÷}·ÛÎ÷Ýî·>ú¾L—xU¿LHO}_&û\š÷ӤХý¶œ{ p…Ì9 ž¡+¸öÙ™¦Äz–¸ê÷YšsñÊÎb>À>g™9²³~34<[DêÅÙâOi ÎV4OâÓä?Uü ýš qiúŸ.ÛZÚvOR|†8š‚•\BèþJ.J` •\Æb®«žO꽇Æ@€«Ä€P/Vá„iXÅ^cž««€Þž‡=nvá]hµû×궤p¾*WÎÇÌHÌÛ Ø ¿ t‡nXG×bn8ëd%KÓ°®ô"@:žmHo²Õö‘ÙèS`ÖéF¢™^'ä'<»^WJ!ÿõ² ¦Î?snÜÍg:_Ƽf9KÙéù=SÛC÷­g C)ó…ê•2_(ëZš« Ú&ºçlPm›‹d²M—–²ï¥ùÚøŽ¸ÂpMõ‚Ûä*„Ù‘í„´cu­Q½Ë Šê½XH^w£MÏ‹·é&Í·n„›4=ªu³˜Úb[¤¸¬:EÕ¤N“ œM[ZçmgMé±Í´'¶èF©~^*–€j¼L÷-í‰gËn›úøÕ¯=ñMŽzö\n—ÜsŸË‰[âóÄÞT¾ç1a°ÓŸÇUŠ[âó¾÷åy7ý~_üVCeû‚íA¹ðØIïÃ`{nåI/¶ Ai*¶ÊSŒ¦âù\™Š+¤y¥._‰Û°Ä6.‘ É«è˜8âÑj¦mº«4B`W1Í\»¯âZÉ¥õj3wõ! JúŸMC­ÿ¼íÃQ^-®¶ÏÕ—ñ­ ¶][HXj;½3mRÔUw»,Ïh l—=;õöê+½Ÿ$ „½&îó‹^ã*ÄäæÀ¾m”Ͳù½HXL˜k‡¸1ª{‡´QuEÝ¡½­œ/‘¶¾æé¥âk«\+d+Dû21j´•^Ž¿™˜íûrø+ÌÙO\bzöS ž˜íõS\B¸dÿÔ¹q_~ê’¶ÕfóÇnʶ=Ëö)³ÙÀ6ÂE@÷4^§-®i¼Nüa°ë´‹5]×ËŠœºx=毪]¤7YéM†Ï©ø…}[Äü®×žW×ë¤_%Urm¾WIa@›ïUŠñÇ«ìò÷ªPó«umWͯL5¿šë"}}Ó¨Æ×äPãk„wUãkÞ×xƒ¦X}½Au¨¯7覾Þð鏿>ý¿kîÛÃÞ ˆ;ËÁµ f¿Sy˜÷Ë^`*¯–•ËJíö¹6f/pІÌ^`)+|öl™ôÃÒ¦÷¬BoиðÕ;?1v¦7+HšµHHþ?³ÉœàrÑoÀ Ö1râ½–û›ƒ¡Ewˆ15Ó,ÆÝTD Ò1ýòÆÁüÄèHÒ¤j}(»íŽQ'zÄ\àûÈ“˜4•ΧÔK曵í=o¿do\=Ø ì­Çö˜œœÎéÍúY ·YÝdyZÝŽéÌãgÆÏ3ãg€™ñ}oqµ|ñ±š¿œžS6æ¡fµv­#*k»¾?ì7úÁXAò;Æì ò›oÆíÌ`škÍ<7+Þ°"?Ü1ù¾b܃÷ôÕV¤¯Vôæq°‚QÄÖ´…CÐÂ"— ;l-~8M¡jÕ’[5ôæ¹Ò×ÌRcÍamó‚ј÷š9ÂÚ nص˜#¬½àÖS{ÁÕ©ös„ÌHÍa–ƒŽþ¶‹©ëæŽå|/\DlàP ·»ø”¥6ëêÍ»uû$ŸJñ)>…¡ÿ×m2p÷%>Åû>µÜ~îzÑ)‹SDùyú„ˆr>TäŒö8•Û\”ì¬M:›rÒ ›)÷aˆÉLo©nîhZ‚OÁÇÚðEg}i鯇Ñ7¼C¨(ïÛîµêii‘ó å1èk’Qöí Qδ֖Æ(ï;µ5LMTðeRÊEâêÖ†Kú;Î0”N6›¢œ§Ö‘«r±Uì}ÆQvvlÅæÜ%r§xLmu².ÊÙZ½"Êâœ]|É’š6 ÿtlñ¦øV÷½²­¶¦‘<ñÒ¥Qη±k嬯YNK±Ï5½d|”Ýæd9V§:¨¶4ŠÆ(©ooá—ÃBÙÒÙr ¾´H,{[ÚÚ2y*OÓ«”S8;VY´õ”¿Lª,ÿóþçëxw„•TþÎ/hמ»´¥…™tÝûS¶ŽÌ^X:VÞ7ð©¥uŸ²(xÓZb)6S€ÖÝÅ|jݽ»tìX>oåS[ïã¥c1×§ý8S†ú~•O™üŸjÃ'ùT>ŧÚðk|ª£ï~ÔÙD”ûë¢ØL•z»1‰SÇŽ&ÏeQVžû^T‡¿¯(ëÆ–š¥Éùí5MÜðÎZ–jk/««Ãèã…–ñÔ„“ne9ÕFó‹íK*â•ó\-›BcËÙP:öÜ~ëQ«2¾7lIITðóÇ-(á¬âqQÞ»õP¬*7 …ÿð¨ô}qmé8Ü!–_ð¨Â:#:‹ñwþƒŠwñ'€*œõQèbQé¸ìîúƒŽ09(.ŽòªÕà-_çY¶le[+œ©·).J6iÅ¥ÙÜú(.Ch›Í¤Ì#¢¼›•¤-KÖiÁ3ÀÚiï|T55Ê»¼²÷X\Ò=ö Ìø;ܼ¬utG”û‘Òñ8o,ÿӣЄÐ&õ†Ñ Óߔޢj-|W„.Ê+¥]ò£X^:žm˜¼öb_Qî¥ãÙˆ¥¥ŠZ•'ºJ´$¦–ŽŸ °›îº?Ìïl†âוNŠrÇ“OóþÓ’*>£ô¶Q1ÿß²ZÇ¥¦G[S˜þo_þûñŠ¿ö‡É-}è±í`­7>^OyôcK®dÎÛ¢ÅÉ¿_ÒÅxàƒ ñ?ÿXsƒß;>T¿¥Jn†ŸÀB= þNù=¤,×=UK³ÅÀ¥óö¥›=g•Ÿú?î•[ÿ§ÿ³> lV– k ‘ нõ¾èŽÿ?ÛUsc9:ÕøØüáÁÑÑüz¢ªz·!à`”uʶ£¬‹ø÷fÚUâ½\Ìiü0’’J×òPUßÛ(®*ïóò0KfÅý騊յ»ª½¼æs– hºº7§šùCw/U{˜GѶcE³•ÊÌîÅ­aûî2w5yç˜ÇBÏ]Sj5ÙNÕjz´ÿÞTæè§ÆÊ߃W4Uß1®*ï8sdš³Dq’ŽÍÀ$*Å”«Í›Ò<›5³*&vÕf›ÖUÛ£Óàmk®‚8´NÄ.o‘s7~ïãÇÀ²æfs2/Ïtþó½CÑ®±ÿ{të ó7Ÿ‰VÓFéSì)Ìm‡ï¢kW˜÷À¹I´-±™šá›Q|ºxÃ÷®4oŽs »ây1ÿ¦cñšKÂîÅûŒ|Õ+çóà]-ÎNçBseÕÚcUI>ÌTu5|œ9MÈú øÒ¾waq¥áàÒ^!ú§D¤¬ïWY×Îy¬qøý£ºëhÜõH6yÌP½)9ÌðøÉÕ$v›©ézÄ^%ŸHn½W-1˜þYêÕVˆ²/¾ ªákœ…M‡õ:Úf'í}C»ˆª^Ã"¾AÂFÞçë›üog@Wãð`¶Rq"ò®ö3òc¡ÓŸµfû?6[*óg}{˜-vÝj¶4ËÛW„ÙR+ÆgÄûºÄøªôÔÚ¯O‚pä=gu¹o£ÞýC1!³ìd5£üŠ9Óªç!1>Ôîi³–tV4sh»ÔqóV¦!…?–ñWAÝŽB•[!6ð½Bü…¯‚€W£„²õlÁôéÕå+ŽFå`ú^1þÈ׈>T¿¿sÅ4ª‚ãW”Kbùtì{åøë^?$òúkÃeåÐ_κãÏzèù€˜õkZ½`Q…o5¡ïãoy ’(š)fafnlè{Åø#Þ ÔŒ¸©+FÍõÅú^1þz7„~·JÒ“¶Ù†¾WŒ?Úµ²¬†9èhØü©S}›}è{Åø+Ý0$oF8ñd[Œk³}¯–2ÎÈxšb\›}è{Åø+ÜH¤>ö‹Éá®Íi1„¾WŒ¿¼íƒ{l æ/ÈÌŒ }¯mËýí€øêaŠñ3ãBß+Æß×`xÝãgÆ…¾WŒ?ªˆøÂA–z¶pv¥o³}¯Kƒ8>ÁiåÚb\›}è{ÅøëÙv顱EiSŒk³}¯,; ´C˜sJào_ß+Á߯·O”9%œ…JÍ8¾¾W‚?~MDhJ¬ýÒ¸(ƒÓIǾWŽ¿zMA’cZ,a• #b•‰}¯É™r¦±ágÄÆ–s|(‡Ø÷ÊÑYÌ”3ƒºtȱUŠ`~Ôä„)f‡Îöøã¶qºó~T î9)¦é¦9ØJw^ºY~T =)fÅÌÓåI¨ò”ò£©@Þ¾WˆDL!ó¸%E1þª` ±ï"æ„)ä(Ô«æ£Öä¯ ¦ø^!±¦ùÈ0-”Ô„ –†ãìi3ÕU6ÖÄÞð÷Š;4Á%¦„œtÅ$6ͨpA9È"ÿr‹©È[ŠU ™a1¥¸È¿\cAÈý$´æ¯1kŽëÁ‡þåÓ…¨þò àÏ'kÊ˩ƞOˆýË5¦?2ZŽËË¡9¾œtÇ_c¢‡Õ"ÝMÍ|9&ö/÷˜–O‚ÿò˜ÁOŽ ýË=f0ÇÏÖx}Ù{Ì ޽Ç(ô/÷˜V-ÃÌî„iGÚhû—‹Ì0x,#¤6çO¶Ñ>ô/™¬®Q’°òÛhú—‹Ì(”Ìö“2ªšeÚáÆþå&³L¹ý%¼š6šj\£PŒ¿Éì:ÍXiÑyè¦Æ…þõ&#Žç±y{“qSãBÿz“‘¢ò1ØmtíðSãcÿz•Ü=Èzc`©m´ýËUæ ›‡HƒÎ_el£}è_®2‡ Þ6!f*6ºv¸F§±¹ËL€¤x¨sHårNî}þëeF×ȉñ·0m:êÏãøú—ËÌ$@í$)/åP÷ì©UÀËêþ—ûÌ$©&ÇSœu†¢ÿË•f2Ó<§ÐÙ ÉìwCúárðWš©È;N—xTzC2 ÚÝ~¸¡ýf:zV3¥}•ÞòrˆýË¥f&×É#A zð¡¹Ôɾh—¾UŠ,q¡¹Ö´33s$•nhSŒýËÅf„’yR¡õ7$•boHß/Ä_læ±ÆŽŠeÐì ‰BlàûWC1☘ôfoHbß+DPÙr ·Öcc ›ÝÌÆÊnH?\Zâ𚢎Eñ{ñÒ „*Ú—„ØØ÷Ê9`è fß²í̾mÿÎì›ô†!˜}²™ÜËì›øÛ™}Çmcö¨™è ‘Ù'øZ–Tº¿Üžw4÷{¹Uè_Ù}¢~7pDöÅ¿¤ÜCè_nÊ p…K\1 fUøbý+ÃOÀ³ŸTK=¬öm¶¡å÷I]¤¿˜?®˜´Í6ô/÷äþÚH'Ø“¶Ù†þ•Ý'(Ò+uØÛ£m³ýË5¹…µ0XúÓ®×fú—kò`îÜC$ŸëŠqmö¡¹%aÍ“~mÚæ´BÿÊîÓs„Pý‘ÄÍŒ ý+»O »#¥^êŠñ3ãBÿÊîÓ]c”@UàgÆ…þå’<Š þVÒóm³ýË%y4²®˜]ñŸ6ûп\’Dz¤Ûœ\‡-ƵهþåŽÜ†jÄx»ÖÚ¡é³;þ°Ñþ’<žkíÁòR£„ühÓøKòÁX`™ 3G)IWýŠIïÈòã21öYäÖVº~TŒ¿'OĶÔäøç–C:‚?*Æ_–'s’›‹ÚØÛžJ±·½ï’²ý$w}¸LKøÛ…ØÀ¿\‡Ä8-†’ö¶G!6ð/·ãi´u¦¬­‡ÛžY0Ùmï‡;fäÐLýÉì û.*ãð>ޝAñ8$2®‡T‚2„Æñõ¯|0©ÿ4Å·*•@ôõ/ˆ½I^‰,ÈV "›¨„“ÿ„ӛтê³£UüU}ý+:ëx`¼5NÌ‚¾¾ÉûïrÜ’œ(Yíÿz°©y—çT7¦R'vˆ NÆO2ËÿÏñÿþ‰7_æÿWˆÝËÿ¯óÿ›üÿÖÚOeÑË8wí;³†ñ¿™X ÿ[‰à{4ÿÛø?žøþO&6•ÿ3‰µó=¯„ ¹sUV©}/âæ!žeqÉó›ïk÷ËZÄÿs,¾Ê¾×Ø÷:ûÞ`ß›ì{‹}_nß[í{›}_cß;&±ù®ûvÖß99|Å;³Îš@ü«²ÎžgèÕYçLàHþŠ£²ÖM`^_±_Öù%Fvöd]TBþßκØòßÏxüÑxžãKíÝíÔxÿ虜»øÿ)zz7ÿ?Cì³¼ûµÞC_âûË|…ï{ùþ:9¾Éÿo½þ¨lêNr×öd[ûíì㽑0s 3—ì¾vUöÞÚ7Áø÷ÔYõÓiP¬ÜÐ퇀ՊŒ6󚆶š¶¶dÆ(ܱÇùä$4¢¼ÍÙ#zÿ­ø`ò^Cm·àÅù#®°¸ð‹ ÅÈs³ ÿÉ»« óÅuΓW¶‹»,†/ k,& Ÿa1\ÿ]o1­Zùu¶1üúÜd1Mb|±Å„ÃâZLØ+¾ÜbÂ[ñ•ÆŠ¯¶˜pUü5‹ KÅ×[Lø)¾ÅbÂLñ-†ËÀ¯[ ?úß²˜ðP’k1a dg‹ ÷$…ÖIö¶˜ðMrÅ„i’‘ŽIÆZLØ%9£¼ùišl|qó„S½žŒ;Ý^Øq²Ã½ÀpO¹ ÞâkÚáïÔLúâΊ"5 Wš›ŽÁ¸uH¨í+¦hÓÅĽÅÇm#oå*ʾ]0kd‚s‡|°Ì¥me°¤ä2Ú¾ÂKŸ—64ðîçõnS¬Òµx?·oÑÑá6$¤ÞŠeª§þ€0œ m_Iµ&|Nôé¨G®ÆÌ;Ó÷ÿG¼•ö‡«uuºV\rÑ¿í+m¸î`‰º·rhú®[ŒÞn¡XÜ[|ƒ‘W¼¾¶¯4ÆyåÉÒ¼ÅÕyu¹×[›×ׄÌ"yåtªí+Ë9ä¶E»,³·¸Ïã­®íæí³C/p\5’·b*µ}¥.¹¤céRx·m ÍÎI[ª¥6U§;‚¿¯¡IL-"0ªw¨?gùÞá…•·rµ¨·ë]ïÊöwo¼•Ó7õÎämú{‹ŸHÞꪬ·&ï~×Û[|òVÈH5]ÔFïäÏÕ¾…óÅ[¹îS^ó6í+N’˜iÆèí¹Œƒ¼ø¸·Ð•x«#¨ÞnnLDœÈÝ[¤Ýx+¢m_©mlo“ó'÷w„¼•^ZÛW˜î.~.p)ÇnÑ´í++–¸×Ãí-Ž™È+¶GÛWšRËmnÍÞÁÁÞ‘¿Ó¶¯¼$•Þ-¸c#§¾õn#÷ç>gs*—É©Üz{^:§ê39U/9õ0>Ñrª/&§ú¤·ÏMçT/MNõ–œz¨îÞjÌ[Íu®íÝ7š3{š%S«³oL­èôP«fPo7§kÕœšz4·äÔÃl Ü‘Só®·›Ò9aS;‚œz¸þ—[Ní“S»Eo5Æ.§öÉ©}DN=ÔÅ̽…xË[í1rÒÓÜ×Ì[í@ÓSíD“×4ܽÅsoµKµ‡Ö¶3é[ ±Q“îö­©ií·¯³š`ÍS“n…Ô”ö¥=jÒ=QsÌa'›c4¨IwGûÖÔ”aR”·¨I·Kõ1ëIŒ³ÃÉ)Ÿëæ-^ª¨I)ûÖÕ¤cjÂ5IŒšÒ>!DMbQp[ÐÞxÉ^à\ó]iÞJ¨†Þž¿øÄ¼…:Ëž’þ–›ß¬¿PìÉ+b®ß¨þ°kì-.¶˜m±WlÞsëÄ·1oq»EM"Q›¼z=ÓÞ¢ðKÞÝ™í>¶È+q1õV®›Ú¢Å¾^\hÑ Ñèïæ%Ñɇîmoa·ñVÂæívâj{Ë‘·òRgÞ>;ªœ¿ÐÞâÐŒz¥Ï¦ÛÜ¥íu^™½ÅÏou½±o9Ö¸·¸?ã­¤_ì[Δî-6x«Ë}ÛWÚ±ß$Üí- Á[QŒµ/ p›Wloñ¡FŸÄ®Y[“P%n摎dæåv·í+ÍÐtÝ;ü­ñNö´+Î[áßá„wrR¦wÏ®ó½A8‡úåNNïÎmìÅÌÈìP¿Ÿº?‹‹§ì­åÑ[É÷ÙY??Zá1‡‘ðÑ[É¥˜YÞé·¯½Eð‡·"jçžKÚó_¿ÞÞ"Ä[T¹¯éí=K:í-bBì9»µ¸J›ü|{‹ o%èaßæûÃé­4`ì[ô<Ž1²Fz+wgf¯R“ËËsóV„YûVyý[7ñVÏÜ<›…¼Áú{.¡Ü q‹½Xu]oo=—P*&ö­êr{>ÖÝ›·ÒQÿ/®ëíd9ÞŠlß*¯¸oæ-|BÞŠ#©šV×(/\CÞ¯ã­Ôfì[åux  Wˆ.ooˆWøÜpöx/‘û~¡Þ/ÞŸâæ=G{ÞË~Š}¿HïEùuïáò^  öý±z¿r…Í4^4Í{±ý]ýK–/DÞJh‚·SÆòÉÌ[)ò±3õ6ö7šXNGÙE’þS½kqB&CZJîn[±ø²Ì€¤!²÷ÑÒ_ØÎ%&Imúcèv’Í€rš·ªAo׸»Êûì­ê5{Eõ·}>ÿZíÞªO¨o·\ÆQÃ÷Cý5ýP¿m?ÎW»¾k\Õ˜Ù0·ÍJúÞ×c„~hÆÀm[ØÛG޲·Ì o5›æ-qwG™aóV3mÞÂéó5iöÍ[í½UÁVÙ3i€«/òï0pÃ;íÞy,³§L-Ú[ÂrjÚ£ö†f{‹¢3¡×ö•zwûi«±·8=á­ö¥Þš{Ù¥íöÖ¸µÓ[íZ½]jJDí>/âEÌ ö´}+4>ÑÞ7wz«¯·æðÑfÜX¾ìÈ+l`ßj/µ·8$¯0…Þ®i€X°å)öeò ‹Ø·Ê»ÔÞâ0Þ Ãè-§ËK>/ŠM¼EïGõj6Ÿâßâ˜z…™Ì[µpƒï/úØŠ™šÖ6Ó ÷3AôBŸæíjp¯I{¼÷ñØÔò¢¦¼÷ Í[òn¶·¨Úª÷'õV`\‹ÝcáNzx8ToÜ,ñxAÞ ¿2‡ëÚ¢ºtq+È[á^æþ¼¶¨=éñîy+¼¬·[ÚÚ£Dz¶±»Â[álz¡åsøÓ|M8%ä­ð¹éý´¨½u’½Ž7ý®7o7Œn|qQÈ[ÝÜÛµé™ÁK,½×ýÀ¼ÝÔ%–Ø[u“W7›÷‚Ñé¼wà­nöíÆÑéz1¡CŸtã0oŸÕ% ³ÇR>£^]4ôvzgÓ(–‚{‹Æ/‚·¼ÕJou`Ëßê–eú¤Û–«)w˜½EHˆ¼º‰¹þnåóâN“¼º¥±Ÿž…ÔÀ¥Ü8Í[¼,“W78Þªà‹ý­/–U%Þêv§·—4×I+ĽEÔ“þêæG^üãE—`å‡Õ­ÐÖXççwɼÕ}Ñà‹ÍQr…Ýccé5P“n“ôÞYtÃ4ouÓä­4î-œMÞêÊ[ hÜ[¸šôP7T÷6åìÄân’W·WÞ@ãç .'yu¯uoS®žUM^ÝzykÍéö®?yu#vo³¼ðýy«»²Þ^ª^¤³ çŸÕMš¼€ v;Åûç­nÙ¦;m+ì-Üz¡¸}«öúYƒÿϬév®·k›¢äŒö jÒÝÝà®ÍoÅÐ[9S^wW¥À[q'ܬe5¡@/Ĺðs˜ö­òŠ«a1µžzl…^oÅñ°˜Zo=N@3€·â†8ܼ)moÑ  ^qJ6ÎêE;€¼â¢Ø·zêï7èW‡³¼ÜÈ«K}«§þ‡Ž3*Όޞ§]r¸Çðh W\Þš}!] ó=ÝQîã*ågí\çÛ½GW€~ˆßýðâ–æ4o)ÖƒºÄ ²oõÔÝécñjé‡8Eöm[ôãÅâ^óV\$qÙVwBë÷{˹›zÅaâÆâ9­æ^B_t/¹Þ“yëû€{kvž¸RæfÞÍø’qšbqzy+Ž|')hd7x¼7K}°\ ÿÞ°îa÷ÁéJû 5‡ô½ãßçøÁæé nÿ~p?Þ~0ýX´ÈUþ«ö~03gøÁþ}^;xnÏGM·cÙÐùÕ\Á®æ"y5ב«AhW³®¦Wƒ®¡oçývÞoçývÞoçývÞoçývÞ_Å÷Î×E{ó¿mí£‘k¿åÿT¡vî•ð<ÿ'¬ýq4¹ëi9N³!Ž&Û÷|û^dßKìÛj‚èæ¼-,Á1¾j˜Ll¦Åf®á²§Cåýe«ºéË 8Â[k£¢®†œ çtç&J@@íLcª;¢¸-‰*ïÜñþ³;Þ¿wÇûßÖ«ƒR{ùýùÍÛsϨMo& ¾i}°ŽSoßñþ3;Þß¶ãýõÎÀ©í÷ç´¶ö{ú}êA÷ïŠÙïçÐÜ?Ú¥¬;rs‘å=å‡UQþ”x— ¨Û´K¨…VD?>…<•²ÕÑ[v΃ý>åôï×ìx¿hÇûñ;Þ|ò-ýq3ÿyüN§å#6}þæÖ¡fãäe;Þ/Ùñ~÷þëxßðàû¥·öÇÍþ(ŸÙÿyüæ{fcéŽý·Ôí¿‡Þ¯è›ùÏã3ïÙKÝœåñ–{rœt×à›ŽþŸäúŸÇïrûX* ôꤋv¼ß±ã½™ÿ‡Þ›ùè½™ÿ<>âÁ|':ü—Ç;úbÿOtýÏãó¢ë7øïAür¢ÃÎþ‰‹väß:ÞÛþï}‚ëÿƒùOرÿNpýèý£ý?aGÿOØÑÿvôÿ„ý_²£ÿKvôÉŽþ/Ùÿ—ìèÿ×ÿ‡Þ?Úÿ%®ÿ¾?~GÿßÑÿãwôÿøý?~GÿßÑÿãwôÿøý?nGÿÛÑÿãvôÿ¸ý×›Ýø_o6õç]õàÞ:®ôþºÍý0þ7¹¥®“å[ìðÿƒ=^ìî?½ßõfÛà› ýyÏÙQ×îû×f`±‹ÿh]³!ÿ¢õöfѺïw÷¿ã½™ÿ‡Þ?<ÿzÿèeÑý_M»iÇûGû¿Ðõ?ïìo뽉øY*;5:¡´;ÚX‘ï©|GŠ+çMÄ*¼ßJüâ÷…îþñà¬/tw¾{u¬»>ôþÑýwìGï¹ù»cþÝ1ÿÇî˜ÿcwÌÿ±;æÿØó¿`Çü/póŸÇou3(Å®ž|fþzoðÏCï—íx?uÇ{sÿzðýüÛv¼7ûÿ¡÷¦ÿy¼cÿÍïßó»ïÙóþiG ­§Æ¥;ÞOÞñ¾ùÁ÷ÇüðÁ™?æêûó?²ƒqý¯á½cºߨûŸTâzê°÷¿ß›ûßCïÍý÷Á÷G»û߃3pt|ÿìÉÿÈ }Æ=ý>zãýCoÌý¿5¼ž:Ìý÷¡÷æþÿÐ{ƒÿ|”»ÿ?8G]yþGfà¨5h²ÎH1ÛçjïŠç_Š=ùíü?øÞÎÿƒïíüï}?oÇüÏ‹ç¿'ÿ#½Ÿw½Ÿ÷~^ÜçjïçÅû_І=ùíþð½Ýÿ¾·ûïû¹;öÿÜxÿ÷ä¤÷s×ÒûEqïçÆ}®ö~nŒÿ¤ÚØ“ßâ¿ß[ü÷à{‹ÿö¾Ÿãð߃½Ÿ㿞üô~ÎYô~IÜû9qŸ«½ŸóŸÄÐëÉoî½·÷ß[þ×Þ÷³cþ׃ï-ÿëÁ÷–ÿõà{sÿ{è½í¿˜‹=ïmÿ|oûÿà{Ûÿ½ïÛãþ?øÞöÿÁ÷¶ÿ¾·ýð½í¿=ïmÿ|oûÿà{Ûÿ½ïŒûÿà{ÛÿßÛþ?øÞöÿÁ÷¶ÿbºö¼·ýð½íÿƒïmÿ÷¾?"îÿƒïmÿ|oûÿà{ÛÿßïæéÍîûŸÞü÷ F9ÂῇÞ7ƒC–Æ8dÖ­Ä–Yìs%$ضK´·æŸ #W-ΟÂûѼ¿ÝÞ· ¾oãýÎ÷¬øo`§Y1ÿçÁÚæ=¾ÿ=X§½ÿí½Os÷¿o¤Ó¸ÿéýMÞØ¦9þÓƒw¨iñ]pï­fÚô{nçÓŠ‡ ˜©îþ÷àìLï{ggjÌÝ;;ScþëÞÙ™ºãþ95¾î©ñýsïìLvÏìîðoÿÒP³txŒ ÷ÎÒáîþÿà,îø_ÎÒáŽÿõà,¾÷ƒ³4Åá¿giÊõÎÒ”Ë)nþÜñSÜü?ôÞοÔ@zÞÛùð½ÿ½|ç)ñý{ïûÃâý÷àûGù߇íà¶£ÿ‡íà÷ï-å°¸ÿU\}X|ÿé™™GvÔäXÿã¿ç¶ûï¿ç¶üÏÿžÛâ¿ÿ–{R<ÿÿ=·Á¿ÿ#w÷]|R¼ÿkoÕ˜4¨2i#ÿOovóß–D‡oä?èÍnþ¯ÞXü»wGMŒñïƒï-þ}ð½Å¿¾TÿcâAáöô¨È¡;øÏ‡îà?ºƒÿ|èþ÷¡ð¿Ù‡>ÀÿÕ{ƒÿ|?aãý¯ã½Á½¿}Ç{³ÿz¿›ÿÖñþQþó„ýŸ°£ÿ‡ìèÿ!;úÈŽþ²£ÿ‡Äø¿gÏ=2û‡8þëÿÈmï_ÿ-÷ÁàßGs›ûßÿÈmùOÿ=·Å¿ÿ-÷A1þýï¹o¼#5ü»&ÐAŽÿñÐûÝú7ïåßÁÿ¿ƒÿ=ÞÝÿó¸Á廿ž»Ñø–¡feüý£ñ;ôÜÁƒòø¿öÿkî™Íý/ª`6÷@ÿ°;ßÃø¿;ß¿ê~ÿwç{ÿwç3üÏ<þ¯ý=öžÙssªmtÌÿ¯¾Ù¯_ÿn¿øGo>ãæ\ÊÜ+㊪ÚŸb:™…²S³JÄ}Œ#ôàÎßoþßo‡þ×~;ô¿öÛ¡ÿ5jþµãþ=jþ5ˆÿFþÿ›™Q;î£vÜüGíÐÿ¹CÿcäFüßñþÑû×Èú§#ëî™™‘Òÿ¹EêÝì íì k z÷Є0SÿKp÷Ÿ<þ¨þшúW#vè?Ø¡ÿ4b‡þÓˆ÷Ÿ‰{fhÄΙ)œñï32|ÿuøÅUÝùGÁïæ;ï×?¾£ÿÃSËÑÒ‡eº_£‰ÅÄæ[jÚ`â¦Gkˆ5ÛÆw™ïu¼1·òŽú»õO‡¹ûGïæÿ ¼ sû/ߦ^Ù¹Š>ú»¹RÎnþ÷0Çîx³ÿèÍîý¯7Fÿ¤ãÍîûÞ˜ûWzgèÝ{íÝÐÁûßPwÿìx³›ÿ¡7»ùzÓ­0tPÿ`èFþ·Þ´ÿGÿvãŸ%QáÆû¯Þì¾éM7ÿ¿uÿߺqÿëM·þSkç={ºµnÖù¿˜»uþ²ÿ Ùÿ†ìÀCvà¿!;ô¯‡ìÀ¿Cºg¦† ×Ì8ÁÞÍ´½߇W;ü—Ç;ô¯ß1£ ™ný÷ìö_ßi:ÞïÞÿï;îƒwèÿ êïÿ îŸzë=37è›903w³aº„ø2°Z«pœb£‰Mæýå– È Äwc\Õ´ûþ¯7Ýú׃÷þ AþCKÿý«¥_ÿ¹åº¡ n_-;ø-;ø-;îÿ-;îÿwÜÿî¸ÿÜqÿxÎ=;aàšÿßÌ ÜÁÿ¸ƒÿ1pÿcÀþÇ€ü§;øOvðß8þK·ü‡öψ€1þ‹Ö~ÿþûGÿúoýwÜúïÐ?éïðotÿõß±ÿúO¾g¿ôwÀÿ:Í;æ¿yÇü7ï˜ÿæóß¼ƒÿÔìö_7÷ï<Þ¡ß¼ûP·„~;îßývð¿ûí¸ÿ÷Ûqÿï·ãþßoÇý¿iÇý¿éº{vLÓ•af&ÿûÌ4í¸4í¸4M7Í=\Ý}¿hê÷дƒÿظƒÿظÿ7n¼ÿu¼ï¸ÿ6fôŸ 줢vÒï^1TÀ-¿Ññòø£ü߆ü߆ü߆úç ;ü?4ìðÿÐPuÏj(µÛ ·”uý·iºEWÚ-åZâï%þèN©ì˜ÿÊŽù¯ì˜ÿÊZqÜW•~ýûJÿý«²ãþUÙqÿªìØåý/ïè9æÿþ7~oùùïš•ò÷ÏGk}ôþQÚK;ðoiþ- ÞÿKù?éÈ×Í(í˜ÿÒ ÿ£Øïs¤øC¹ÆÆ£Lw®÷ÚÛnnyq£Î•Þ˜ûÇ›k‡ àýûýwèwàŸÂüSØ ;ðOaþ)´ßƒo ‹‡ ˜•‚ÃyüÑý—ìØÉŽý—ìØÉŽûO²ãþ“̼gV’þô¦›ÿ)ŸÄ»ßıÿÚ«ÿW{cõjoªü_w˜ Þ\fü,°žÕ*ß«ý+Oʼ߫»ûO_Ò¿Ê÷ßùªÛ⤽uG;øÑþ_´ƒÿíà¿E±þ×^ÝSËÈãSïÙ ÑÞ¯;?ÛÇYÓ ME#j&ó² Ø÷â‘ùVyd~žªþ˜qÍKD9SÌÝë³÷ËÔVâei ƒi}E¶Z Ï–#,†·ËÑÃf›ÅðŠ9ÞbxÑœ`1¼nN¶^:§Z ¯ž3-†WÐv‹áUtžÅð4:ßbøW]d1¼ë.±¾Ÿ–Z ¿‡Ë,†O+ïÃÏLÞc3žÍ¼Çf|ŸyÍxGó›ñnæ=6ãÕì–¸¦X^{?{„Žå­÷ëS?äy=}ZLª†q"¼›i1©!Æ¥áÝ ‹IE1^lý“—¬¸%äØb1¹Wˆ»Ã»ë-&6y¼Îz¦-"_ÐYŽ[-&eù‚¶õÉk–¼@g9î¶wò™ßÞy/ÐÚròÿœ½ûf¦÷©ÿgåçç4G²{fRÏÏäðs@ŽöÌL$ÓC?ä8;3IõI×ðÄÏ9.ÏÌGâg:ü|ã†Ì¬$~¾5+‰ŸrÜ–™•d½Õ*¯\É5!Çg,¦M]ØÙvƒ¼ZlÿÅø¹*ø$?]…ºLîÂ2‹É V¡ÝrÈWWáôcGÈq½å¿®Âù!ÇÍ!Çm–C» W†w…Ÿ±òÙU¸%äørÈñuË!¯]ÅÜLŽâ°LùlL{_4ïÜ&ægZn²Š¶›cüq—YMòàU {«èû-o]ŵ–C^¼ŠëBßorÜj9¤TZ\rø~“Ãï0ùó*†Vôý&ǽ–C ‡¥°³K¾ßêqix¦¯%o¤VY*ù|¿Éçw9ù–eæ äw•`)쪒ßUòV:ÝrŖ®*ù]E?Ôç÷±;-·rÉï$r{ŒBŽ/[a—’ßÙäø–½S¬¼sæ]9ô¾ì± ±¼÷å铟²²ï7ïüž“³rÀ.e?ëònV^Þù¾ÊóY9ìಟiyE+û½Kò™.{,"¿i?ÇÊQ ý«„þU|ÿˆåóZñý#¶Ê0ðJ%ô¯âgW¾×*Ý67Â+•ÐËŠŸ]rx&¼R }­øÙ%‡ÇÂ+•€-*~ŽÉqÕ!¼R¹-äð½Wù;¶u¯4øÞ+GƒßÓäð;L=nsÜàw9<ÎŽi3Ýàq9ü|ß4„ùhóÑàçC{±!ÌGC˜?Ú‘ a>Â|4øù†hóÑæ£ÁχözC˜†0~>´GÃ|4†ùhôó¡}Öæ£1ÌG£Ÿí¶Æ0a>=vמk óÑèçCžêý|hç5†ùhôóAŽ]–Cû¯1ÌG£ŸrøùÐþk óÑèçƒ÷Xz“ÏG£ŸåhòóA,Ÿ&?¼óó!¯xMa>šü|Ãχ|æ5…ùhòóA?ò©×æ£)ÌG“ŸùÜk óÑæ£Éχ|ò5…ùh óÑäçC^ûšÂ|4…ùhòó!¿~Ma>šÂ|ôóó!¿ýÂ|ô óÑÏχ<ö óÑ/ÌG??òØ/ÌG¿0ýü|ȳ`¿0ýü@>û…;A?'Ð^ïw¶íBy$ìçoäðw aš~—ZòXØÏßÈáï@äølæ.Ò/Ü úù;ðJ?'PÍáNÐì画9Üšý]Pž›Ãí§Ùß~´Wšýmùí§Ùß~´Wš=ž–ïÄæ€§›;í¼*6û™àݵ™ùh>ÇrÈïbs¸5ûýAÏümL~›Ãm¬ÙïrxŸüšf?äøJf>šïÌÔÑßÏ„rô÷8[uô÷·1ÞMÈô©¿¿ƒÊ‰_ÿ™!ÇÒÌ ¬ÿ¢Ì¬ô÷÷$rlÈÜäúû™ G>ýýLЃ,‡|Eö;£¿Ÿíéþ~gÈ—dÿ°3ú‡Ñÿ:Ë!_“ýÃLô÷3A~&ä‹r@˜‰~&”c€¿1ËWå?ä˜l1a‚~>È‘ÏÇ?ÂyüÎÐ< ðóAÌß]ˆÝ™Ù—Âíd€¿[ ¸%³3„ÛçGQ޹™ùvÞ@?ßäðûO^2†ý7Ðï?rø›Š0ñ@?ßäËç{ ŸoÍÜ@?ßò®90Ì÷@?ßÚý|ËûæÀ0ßý|“ÃÏ·¼s ó=ÐÏ·fn Ÿoräó=ÐÏ·fn Ÿoùól óÝâç[;©ÅÏ79òùnñó­¾¶ø™ÐŒ¶„ùn9!s»m 3ÑÒe1á¼–0-çXLØ®%ô¾år‹ ϵ„~·\o1a¸–Ðã–»,&Ü6(ôuÐÞVz9h²Å„Õùþ©—ƒÂNvÒ ¿“4÷ƒüìR‡¿ƒjn¼2Èß>5+ƒFäocºK òs©wƒýmL³>ØnÕx>ìûG'vìg‘wþN¦™<+ƒ{û^’ÃÏ¥îOƒý­WžPû¾’c«½“ÔÁ¡Çƒ¾ìoê÷à€éû[ ú=8àøÁ›ªßƒvâñ¨ú=d¸Õ-ß«Ccˆ¿[«ßC^âw°ú=¤2Óï!¾ÇäX•é÷F«Ož[‡ø=DÃO×!¡ÇCÂ}wˆßIê÷·àßIê÷€K†ø¤~ X¤Õï$õ»Õóuä+¶Õ÷˜~?©ß­´úý¤~·z®ŒúÝê{LÓU¿[[,‡<Ͷ†9n =n sÜæ¸5Ìqk˜ãÖ0Ç­aއ†9êçXl‡†9æxh˜ã¡aއ†9æxh˜ã¡–Cþo‡ 14ôxhØÇCÃ>öñа‡†}<4ìãaaóûX~u‡…}<,ìãaa ûxXØÇÃÂ>öñ°e–C^y‡…»Ñ°Ðãa'©¯ÃNæq’ú:,à¤a'©¯ÃNæq’ú:|˜õUÞ~‡‡;ÇpßcõuxÀLÃ=fR_‡ÏÌôux¸ ÷=V_‡×Yù 8%ÃC‡®ÏðÀ›~i/\™á÷ /w¯áë /Ž·®¾¯Â‹#®áñ«ð⿇xçû'¼8"ðFxœ$¼8"ôoDè߈п¡#BÿF„þýú72ôodèßÈп‘¡#CÿF†þ ýú72ôodèßÈп‘¡#CÿF†þ ýú7*ôoTèߨпQ¡£BÿF…þ ýú7*ôoTèߨпQ¡£BÿF…þ ýú·_èß~¡û…þíú·_èß~¡û…þíú·ŸçÉûó~kîçï@ò ½_Øñû¯ÿüòõŸ½ó˜F·±ý®¶ò(½ŸßýäðøF7àý¾öôh¯Õ-st¸×Žö=Ví¹zÚ÷£ŽíûG9'l´ÇÊ£ýŸúrL9Úãfêóê }òX“:<J­÷\¨ý=ëýÛßsXå{ÿÀãÜßß°å{ÿ€]ö÷÷ÐMå Û3¹üïƒý|+÷Áaöó­»ËÁÅ!wŽáwÙƒÃìw˜n3û3¹snÄÁ~“{‡å‡þƒCïöºòÝpÀs{N¼¼ú8ñû™×ê`ω—×ÿƒÃ>8Øs›¾I,Çy{Ï?DÑ¡ïrˆ¿Uÿ#±|—â¹ÿD,߇ŒrˆÇ‚âl°à! ŠçtHÀ‚‡ø} nÓ! â± øL‡x̓oËwÀ!~ˆ«tˆ×<ø6±|—âû-ÒÏï¼X>÷üþ#‡ïñýÄòOð=V­Œß)ûÞш°ï'ø~S‡ãwÆ$™pä„ í1ÁsG„o&„Ý?!è|L:Â>˜t>&—1Æy÷„ÀK˜à±Ž´U&\o9ô1!ÜÆ&øY‘Ë»Åø?4ÜÆõ³".Ñ¡¦ãýÐp';ÔÏŠø@‡š¦KœO,ß‘‡úY¡Žs,G…XŽ_õ³BŽK#–ó3õ³¢:Ô¸žñSˆåóq¨Ÿrøùh"–ÏÇ¡~>Èá磱|> ·ÃCý|4GÑáa>&úùPމ~>¤O31ÌÇD?äðó1€X>ý|ÃÏÇ@bù|LôóAŽßOô3¡1Ñc팉á<ÑχvÆDÛæŸ aĉ<1àȉW‘;Ç“Ù÷^93.l\H,¿æ¹äð9C‰åñ0Ï{ ‡ßº{Veù†Ëy‡…;âa?é†tØË'M©Ã.ÊÌÇaæñ¢îO‡>f> øø0?ßäpš1ÌÇ”p3˜âoÊ1ŸÌÇ”0ßSüž#‡ã 0So`Šï79Ü Œù˜n`S|ïÉá÷½æcŠáEæcJÀ‹Sü> Ÿ¿‹k>¦nŽŸM,ÇÍSÇŽ÷%–ß›7~@¼±üö9Õî 1:lS˜ê÷¢ú1Õî ñþÄr 4ÕtÑbœúO  ©^WI¼Ò©~&Ôô©áv8Õߥ¯6Õt•ØmS‡fª¿#’ÃÝØmSÃŽœêw9üŽÔn›väT¿Èáw¤vÛ´°#§ù©ÓüŽÔn›vä4¿#É‘ëôLó7í¶iá¦2ÍßTÈçw¤vÛ4ÓɈá¿N3Ý,æcZ¸Ló7qX§ù€æcZ¸Ló7rø€æcZ¸Ló7rø€æcz¸L÷s¯Óý @ó1=ܦû~“Ãß4Óþ›î{O¿5Ó Â|L¸ºßäó7ÍÇtÓM‰Ñá›nÜ)æczд›îïúÒ#™öÜt» 2+3Â]p†ï·òÍû~†éÿ173<¶ãß÷äË÷ý ãH1C3¿†Ç÷äËwÿ ó4O3¾Ÿáñ=ùr|?ÃïxÍÖŒ°ãgø¹'_>3|ï5g3|ï5g3Cïg†ÞÏ ½Ÿéñfn¦Ÿiq—gzì®™›î3}_u¿Ÿ8ˆ3ýÓÌÍ Ä™¾¯äËqÌÌ€ãg?Ó÷•|9ž›i:.ÌܬÀMœå{¬|³ŽŸå±»fnVÀî³ü|“/Ç+³X¾ÃfýÐÞ'–cµ#‚~Ø£D,Ç(GøÞ‹#~„ßUËï¸Gø^JóòË!–ãò#<6%‡ßÇ’@="ð9Žð}%‡ßÓ‡Ëy*Gøù&‡Ó1Š'–ß¹ðwå8ÒãÑIÄr¡¹92Ü'Žô;›þ>¡¹92ì³#ý¬“Ãï6ÍM{Ømí~·)G»çTinÚ·Ýïorx,®¹i»­Ýcrø=§¹i{®Ýï9rø9ÐÜ´‡ßî¹äð»AsÓîoWÒRm÷ó=…X~wi÷;L37Û÷U;l¶é¬ÄÏ#–ßZf{ÜI>§£ËqØl;Éá÷Ü4b9&›í1™øý³Ã&–óxf{Ü)þålãÇcˆå˜l¶ÇåÔáñÙLb9>›íñux£ù˜íï.Ò˜ã9›2ÇïoiÓÎ1þe<ŽXÎÝ™ãïpäpüËx<±|Žç½–9¾ßš›9¡ßs|¿©Ã÷ûHbù~šãïg’!ŸæxŽŸcÕ7×ë‰Î&–÷r®ßÍsˆå»y®ßÍävüã]Þ¹kÎ%–c¬¹¾óˆåý›ëwóQÄr.à\QŽ&–c”¹~OC,ßÓs=/s>±OÏõw”Äò;Ê\WÔ¿y£HcxžßaÇËû=Ïïã…Äò}<Ï߯Ëõ0æù9XL,ç Ì3î]<ƒX~?›gúøhbùqžŸiÉ/Ï ;lž×>XΕœçq›´“çùÛá‰Är|6Ïc”“¢èÈ€QŽò7Ô¥Äò»ÂQþ†t2±ü†t”¿+ŸB,¿+å÷Á©ÄrÞÕQ~¯/#–ïõ£ü=é4bù=é(?Ú»Gy\.£L žG,ßsGy&½£|—GxÏríñŠríqØ b9;Úcrø¹—NóÑaîöØ…‡I,ßßGû“Ãã0i?pØÑ~’Ã÷XºÑGœz´Ÿ{røý'=é£Ãþ;ÚcrxŒ®¹9Úï~iKn*ÇøùÖþ;&èÀãñ™´Žñ»JZÔÇ„}ŒÇªõ#·ÇŽçË9=ÇøýD>¿§ŸN,ßÓÇøû9òØ1þ&Œ5?ÜÀæû˜ô!æ‡^Î÷÷?á¤ùáþ7ßc/òùÙÕ|Ì÷{úÄò{í|Ÿ^I,¿OÏ÷·.I¡Ï·®ù~מK,¿ýÌ÷xQ*óóÃígA¸ý,Ú± <Þ’&Ä¿Wt·X0Äû‘>ÄÏÅÑÝbAà¥-ð·rx^šî Bx\E“ÖÝbA¸I/ð·rx,¥»Å‚€¥xlA“ÖÝâØp“>Ö÷X9ŽõxBw‹cž8Öã-røû¥îdž›ô±þöC“Öëw•´1Žõ7ZÍͱp¬ß©ÒÉ8ÖÏ·ææØ0ßÇúJÏ?ÐÜøÇzÌAÏ?ÐÜ, üƒ…s(ÇBÛÓL, ·½…sÃc)ÍÖ€¥zÌAÏÑÑL, …sÃÏfkaÀ— =æ ‡ß Ú7 =ΖFÈBßÒ®]æ{a˜ï…áf°Èß tïYn‹|•o‘¿h/ ÷E¾Çäð÷9ÕYøv‹|u§Yä÷uû·†X¾óù¾’Ïï¼µÄò·Èï<Ýuy\¢ý±ÈϺ4QyÌt~•‡™^ìgZ·–Å~¦u×Yfz±Ÿirø™Ö|,3½ØÏ49üLk>‡™^ìgš~¦/ –Ïôâ0Ó‹=çf±|ç-ö;:|ï5C‹ýÎ#–k]/ö7?ñ€ó·áìãÂ-丠A~œ¿Ë gî²ÇyÜOÏ?Î>.Ü­ó÷!rø»µpöqán}œ¿…Ãï*áìãÂMè8·&‡¿gîÖÇy¬FßcáìãÂ]ä8·VŽãýMH8ûøp·>Þchrø¹×þ8Þß ä_áx¿ÏÖËïÇû{€æõxx&±üp¼ÇÙäð÷a‹ãÃ=àxÐLïïËñèñA‹ýx¿Ï6ËïÇû]®Z—øÛÏEÄòÛÏ¿×Éá±õFb9¶^â÷:9ü= Çù=l‰ßëäÈïšKü]PZKüMK÷†%á¶±$ø X<,ñÜPÝ–nèßcå;Áßhuo8!Ü?Nð=&‡çXl"–óKNð=ÏæÓRoN7­|¥{q‚éNÅ/%–ß>Oð<êðw>ú‘ßùNðwêð³®½r‚¿O ‹œf÷?»Ú'úÙ91Ìî‰~vÉágWXäÄ0»'úÙ%‡Ÿ]a‘Ãìžèg—žÿw ±|o4¡O 7¡ýMh3±ü&t¢Ç^Ò :Ñß„¶ËoB'ú›9üӋÜèç@9Nòsp±|Nòs@?Ï&–ÏÁI~Ä<É´ãNbùœ´`Oò‡â}žfý¤àâ$?ëÏ!–ÏúIz’ç†>—XŽiNò{Üù.<ÉïBr{-%zß'Nò÷ úä}'H«ciÀ²K=–•æÇReŸG,DzK=–•ŽûReÉ‘cÙ¥ËJóc©Ç²äȱìR4K=–ÝJ,DzKM™[feiÐÃ[êgE;–†YYêgEÞ5–†YYê÷ŠæciØ+Ký^¡&¿WäKciØ+KÃãdçG“Ãød¿K¤{tr˜‰“ÍOFŒWŒ“V8y‘½“¯‹“Ãýûdÿ–ÎÊÉÆ‡@‡ãä€ùNzT'/'û{¤ü^œðßɾßÂ'{œ$¿'œt²ï·rœâq’ü^œpÒ)~’Ãã$ù½8%à¤SN:Åã$ù½8%ôþ¿GÉáq’ü^œvç)'â±…0Ð)ž¡vŠ×Ö|œðý)¾÷âmŸâw¡æãŸÓ|œöß©~ÿ‰ÏwªßšSÃþ;ÕÏ:9üþ“ï“SìŸê÷ŸtnNõ:RÒX:5ì¿Sýþ#‡ßò¥qjاú~“ÃßräKãÔpË9Õïrøý§ù8Õ4Åcв0ßËü=R³¸,ìéÓüYïNó:ßÚ§þÙiþÆL¯ãNŽœvš¿1Kè4ÏSŽ9-ìéÓü ’:üÝ‚97â4¤Žœ|š¿A’Ûã`õû4ç4ǧy\»o–7ç¡}ÃD{NÜo¥Óxw\ÒÓàÆ ô4ðÄiç—ƒz•Ožôd¸dŽ8æÂ%sèÍæc.³;ºyC'`&<`å=igÏÎf—ÌfÏÎæ^2›=2›Þ̦7³¯2¡'Ò =9’ýz$óz$ûWã•°ÛÙ/íìßöî!z"=‘Г#ÀÞG€½`—ö>‚=|$s{¤49–™ÐiÕ„žÌdÇÍdVfrÓµ%Çýd32‹Ý;kÝ =Á;XÞ“éìØ¼›Á½d»d¹f ‹;ƒ=3³·ö¾ z"©Ð“iàÜiàÜiìþéàÜéà¦éèL«L:3I,ôd*i*·©Ü¦r˜Êm`·ià¹iC'ìüå=9Œ^F/£SèÅz1…;Åz5åŒ!z"ýÄГÉì²Éx™ÌŽ›Ì]ì0ijÏn:lñ =‘¶wèÉìŽØpC9€Ýr»åvËì–G ™Ð髇ž´1³ã˜ÙqÌì8fv3;Žý2Ž™wý =‘®}èÉX0ÜX0–çÚøhõOHÑ6t>‘?€Ð“"sQd.ŠÌE‘]WdnJÌMIö…ûNØ»Âl¡'f¢@¸À»3S`f”&ÊefŠÅC&ôD¾Š2ç{"à]äžSc–äÉL;¸DoJìá÷Ÿx®Ì¾+3;{þkžþã¿öX™=Vf^ËÌk™y-3¯epwÜýøõà?þ«ÿñ_ýûÿº÷ÿÇÍÎü×½£Â½£"¿cºwT˜»æªÞ6P_ïxßÀûÞ7ð¾‘÷¼oä}#ïyßÈûFÞ7ò¾‰÷M¼oâ}ï›xßÄû&Þ7ñ¾ïûñ¾ïûñ¾ë¨;ª·¨~Üô<Úì× ökf/5s§j–÷'a°f0XöXîý¹cõçöП÷ýÉÝŸÜýÙYx?€;×Þàýø´È1Ø@}+×@r $W ¹ZÈÕB®=ÿµ[ÈßBZäeHwvâ niƒèÁ ÞÿÇõä?þ«7ÿßÿ>0Gk ±ñ!pôä x(ðÚCl^ˆÍ±E!x÷- ±À÷9;ÄÎ ±pƒXbëBlCˆ®U˜³p‡ ¼pï¼&Äv„X¸ÍÞÔõ!vCˆZÀá#ø2·„Ø­!v[ˆ…;ÿí!xáž|Wˆ…Û÷Ý!ö™ûlˆ…{Æ=!ö¥ûrˆ}%Äî ±¯‡Ø7C,çÈ?dË÷_ö_ö_öŸüFf±|ÿÅaÿɇdË÷_ö_ö_öŸ|Kf±|ÿÅaÿÉÏdË÷_ö_ö_öŸüOf±|ÿÅaÿÉeË÷_ö_öŸ¼Sf±|ÿÅaÿÅaÿÉSeË÷_ö_ö_öŸE³X¾ÿ aÿÂþ+„ýWû¯ö_!ì¿BØ…°ÿä‰4‹åû¯ö_!ì¿BØ…°ÿä§4‹åû¯ö_!ì?ù,Íbùþ+„ýWûO^L³X¾ÿ aÿÂþ“GÓ,–ï¿BØ…°ÿäã4‹åû¯ö_!ì?ù;Íbùþ+„ýWûOP³X¾ÿ aÿÂþ“7Ô,–ï¿BØ…°ÿä5‹åû¯ö_!ì?ùJÍbùþ+Üeœy œ|5á§í<4PÑËB§Ÿ(èÃ[Oàç$Ühn´ 7Úî@Â}7Ó0HÞèðe'ýûAè6 †9žÁ`nŽƒáÒ –Ÿ9ÝùSË`xC¸Ãá>÷ê?b„!Ô¢3kT?¢NI+Vò·’¿•ü­äo%ÿPò%ÿPòå¾;”ú‡RÿPêJýèõ£þa´y½Æ-w·ÜaÜr‡Säpn¹ÃéãpjN/‡Ãƒb8½A¯GÐëôz9Fð~ïGð~ïGò~$ïGò~$ïGò~$ïGò~$ïGñ~ïGñ~ïGñ~ïGñ~ï÷ãý~¼ß÷ûñ~?ÞïÇz?z¸=ÜŽfNG“g4yF“g4yFsSÍÌí?cf`ÞíÏMxú¿?¹÷'÷þäCÿÇÐÿ1ðQÇ0#cx?†÷cx?†÷cy?–÷cy?–÷cy߯l@½0{Â8¹8¹;¹;¹;¹OÍã™»ñ¼Ïûñ¼Ïûñ¼O_bê zy³|0ù¦Æƒ™¿ƒ¹åL®ƒÉu0¹¡¿‡Ð‡CÈy³~\™C˜ÕC؇° !ÿÞN`M`M`OL`M€u(ý?®ß¡ðµ¥ÞCÙ‡Rß¡¼?”÷y?‘÷y?‘÷y?‘û¿d(£çпIô|û`}˜L“Éq=šBÝS¨{ ;âpvÄáìˆÃ¹ÙÎ9œù=œ‡Cp834•}9•ÜSéÝTrL£wәϙÔ<‹³Èq9Ž`Ž`†Û©÷(z{ ƒä]H®ÅìÝ%ì¯y{"ów"uŸDÝ'Q÷IÔt{á$zr³·”:–Ò»¥ÌÞRiHéíRÞ.%ïRòžLÏOfžN&÷Éì…“Ù 'ÓçS˜ÅSÙ;§Ò“SéÉ2z²Œ_FžeôjYïM÷ÿg»à4s‹M$êØ8✾ˆÃpTŽbpzܘ‡—²„|Ñ®==w£×øù]GTÌ9®lVÅôÄÜÊi¨‚õôô”Ÿ(¡ô#îºsÐ)ûü®]ò/\›…1íq=ë{=üËKÿ¼ôÏ——þª~Û† øè_ß¼¼¦±¡®:ÕR›ªKÞë§ÿ2Ó-7½ÉýèFiû+¯dý¥7iéUd}#¯îÉs¹¹~~©úvÝÍ=wYïn]{nÔ²öÓQûÚ›£Î×gE]¯ß?ê~}Ytú$”ªv®Ž»WapCßíäI{¬7il¬„´F®å[½?›Þ/Sï·Scµÿš4ý6EÑê•m-­ Ííõ÷6Y-jÿ¶ç ~Ïtµ1ù:ÓíÓö_ÞÌv÷ÿfŽÆ¾ÿôÜõ?Á£kçrCþÂî¾ÿ×}ºçÎ3Ïí¹ÝÏÁ\8Ú¹ˆÏEÙsÛÉÑÈ’2ûG#‰Í´ØÌ×0í¨·£BÑŽËF?gõüø”ûFO/;5:Ƚwû€ØY·äO)Aí7ßÕÙN¶Ó‡ê¬iSù¥<¨¨.évÄÚÎ¥÷ÎÊ ü¬ÈgšîÁ©–´nºÙÞpú§‰Ä .·"Qç }†£»›!37~†ä!ÈÌ8÷”ý¿:ë&楜™—¹ÌH>O3dæ­€º 3ùð 1Nßyï 1g~†ä•èábn<ÎO¢h8C>̾ø’ƒÛ&\\ÒéßBâ­8(æíÓn{‘+ÿCÑ.¼•V¸ÛöœÄÁÅ£;_õXù29䱚£=äg¯(òšhs p¼¸y¸ÞÒ²o‘x›æ”W/“S~õކ‡ì[yôŠvâ­fã‹/Qµ›'O>¸ƒ®&ù튲y/~Ö_B|^ᨀwÂ`¾Wi½òÐ=…·Ò"¶5Ù.§¹åŸË¼—†±{o:œ¾—®è©¼—ö±­íØEÏ™_‘™öïÅ7Iß/ ïå¥Ë¼—Ö²{¿¬/¿¶áq;ŽVœ–?¥«n|KU}Á)Ý/ø©ðÕ‚Ss/©zeþ”ë®Æ¼°º±âÊü)§-‰ ®©ú ï QnÙ©Y_Y€Ÿ«£¯•vcÚ[h^߭丅X¡´»àü™ðQ¶í…&åVžæ®¼œNji(AU{ÅzêQ—S¿Å“ûEc_EB|ø²ú^¹—óÅÁ¦Eâ“Õ3î7+¾?½hÁŒõO_8uß®õ9]7åtžœïê—iŸÊ°tžòð‰%ùY뺾ÅoË?ìþ=ÓEF=kàMKÕâá»^–]Ø}-¶µRûä>¥5}ìY—õ×tÃöšV=ÐïŽyx¬ÿgäÒ÷…Ö÷Uô}[Üû­{ætnêO;.mJ·»:VS—¾·½׸ØÌ5\Z¶žÂ®xþO©ê*8%žû8±aîKç¾t1s¿s ßgu?ë2ë÷6ßê>«;ÞÊÓ¦wÜ Vä1“%úó??QWߌè.QËé3”ÎÈŠ+™‘Âú§WÝfd׆i—˜þìrýѾsýÑíÂö'‰ÔŸ³>ïGß;Û¯âEû¿]ý¥þïÚ2g/…}I[ss:¾bÃùIèßYåq\½½½wô͹X˜!þbE5.Ä[Í'ÄçzYT/ÏÈŸ^Tu:»ç@æjû^]ŸáÿïÕ9‰Õw@_ý\.C°‚Ý!𙔚]¨U#J»³væýxâÅÒ‰5lÜ¿w¤÷Ñ=†E*e«³oëÆЊˆÝ¼Êõºù]_ü¾ZG¤#~{ü–þøýñkûãµÝ&„Ü½ÛØ]‰Û]eÆÔwöV†aŠ6ëIqmm÷ã•g"öøL3_ÿL¬ø'¿gâ¾Ù5ø&íþ&ëeöfÍà›eƒoæ ¾™ðÀLYüÍÔ[l¦.ÈéÜ>m™™ˆ®zp&ü§ô*pH*hZTŒ§h¸ާhbާhbާhbާhbާhbާhbާhbN/–½zb´ZÕ—2})Ó—2})Ó—2})fflžh/‡ž”€W%tEJèv”и(q§/Ñ›œ­’ñÜú6è‰á±ÈW]'¥¡Q‡qÇc±õÛ›1ØLZ#ó߀ÄÀ’^\;·‡v2L΋vŸãn,¥h§øÆ"¢:é(>€Øbg—à†(¿ßÍïº0}¿[ÑÿvUxÛÞÿv[x;ºÿí.ÿöQ^Þ{á¥]ÜÑ^Ýš\ZÝ\Ót+o=À5ÃÒçȸAÎk®y—ã)égdïrÿ™ÒÀÈÞå>y¤caçQ°Ý¼"Í\:Ì çè h8:ÏÁ®ñhGÊîûò­Gê»ëm笮x9÷ˆó/ìÎÉZo7÷šs7+e­lv–À±bv41ëÛ«—Ô´mžùéWîëEZ(¶çòÒ·»ç&ìzN/ý’¿>Ó×UôõµÛûzÏ`_ïy¢¯‡¾®o®Û|ÑX¿£¯*õá¾Ò˨ü%®¯òàsU9¦º™ž©‡ÛàC|Ÿo:3Ú­¨ºº­¡™ªk+í6³º6îY„§dÏ/ôå<ô$x ôw#hìï2ò˜bqFv÷Uø*í+½d^…µ<FgõöÕó}ç2·s¹'‹GɼN(EÓNBßç+o*Wº:®wþ ±ÐÏ¬Îø+ú­‰öbÖ´ofÛ¦|Sy ”fÉ÷ v¼íµ4ˆv÷úzmp×kú•7 ß1SI‚,£Ò3ʵ£Í 5óF~gôæâ4ÌXCoM9Ƴõ\†Uç(?…Â{ï¤>ÈÃÙÞœvtå”§³½9íNíÊ)½¦½9-öèÊÉ®7§Ã¯»sÊÚÞœ–;Ù•SžÐö洜ծœÂ×½9W¸+§<£íÍiùÕ]9åÏpoN§Iµ;§¼ˆõæ4;¹–scŽã„ 9/%ܼ.$‡Ù/9óÎç³t×aÞùÜuê9xçspg©çàÏÁÝ£žƒw>œµzÞùpßê9xçsÀ¡«çàϯžƒw>œ¾zÞùpë9xçspJ©çàÏW±žƒw>œÇzÞùp'ë9xçs@}©çàÏ—³žƒw>œÐzÞùpKë9xçsÓë9xçsÀu­çàÏW¶žƒw>\ÛzÞùpuë9xçsÀõ­çàÏ_¸žƒw>œãzÞùàÙzƒs]¸Ïõ¼ó9àO×sðÎ瀃]ÏÁ;ŸÞF=ï|øõ¼ó9à—×sðÎ瀷^ÏÁ;Ÿþ{=ï|xôõ¼ó9àá×sðÎ瀃RÏÁ;ŸÃ£èÎÁ;—ÃxÂêÎaÞùx¶ªçàχªzÞùxšªçàÏǨzÞùÜ ë9ìmÒæÀƒS=ï|<1ÕsðÎçÀ£R=ï|<#ÕsðÎçÀÃQ=ï|<ÕsðÎçÀãP=ï|<ÕsðÎçÀP=ï|<ùÔsðÎçÀ#O=ï|<ëÔsðÎçÀCN=ï|<ÝÔsðÎçÀcM=ï|<ÏÔsðÎçÀƒL=ï|<ÁÔsðÎçÀ£K=ï|<³ÔsðÎçÀÃJ=ï|<¥ÔsðÎçÀãI=ï|<—ÔsðÎçãuOÞùÒÜØ“ƒw>‡4*öäàÏ!­Š=9xçsH³bOÞùҮؓƒw>‡4,öäàÏ!nÌž¼ó9¤a±'ï|iXìÉÁ;ŸC{rðÎçÐ5~OÞùҞؓƒw>Ïë9Ì—=šzÞùºˆïÉÁ;ŸCÚ{rðÎçöÄž¼ó9ÄÝ“ƒw>‡´'öäàÏ!oŒ{rðÎçàÊ^ÏÁ;Ÿƒ‹i=ï|î©õöÎjsHyOÞùòA¹'ï|y«Ü“ƒw>‡F÷äàÏ!Ϥ{rðÎç€*\ÏÁ;ŸC¼¹=9xçsÈsëž¼ó9ÄÚ“ƒw>‡”ÉöäàÏ!õ‹=9xçsHYeOÞùbüìÉÁ;ŸC>…÷äàÏU¦žÃêÅÙòG¼'ï|y+Þ“ƒw>‡üîÉÁ;ŸŽP=‡åÙp"ê9xçsÀµ¨çàχ£žƒw>ÜzÞùpNê9xçsÀe©çàÏG¦žƒw>Ü›zÞùpzê9xçsÀªçàÏa8%Ý9xçsÀ}ªçàÏWªžƒw>ܪzÞùðžê9,Êæ€wVÏÁ;ŸžZ=ï|Žn~ŒÉ‘ócðå½'‡å¶Ùðûê9xçsÀͪ簜-›þc=ï|øZõ–ÇesôpzÌ;Ÿ~i=ï|y'ß“ƒw>¼ázÞùò°'ï|ù@ß“ƒw>&÷ê9xçs`:¯žƒw>‡|ìÉÁ;ŸC¾×÷äàÏ!/í{rðÎçèáN™w>Gwʼó9z¸SæÏÑÃ2ï|Žî”yçsôp§Ì;Ÿ£‡;eÞù=Ü)óÎçèáN™w>Gwʼó9z¸SæÏÑÃ2ï|Žî”yçsôp§Ì;Ÿ£‡;eÞù=Ü)óÎçèáN™w>Gwʼó9z¸SæÏÑÃ2ï|Žî”yçsôpžÌ;Ÿ£‡ódÞù=œ'óÎçèá<™w>Gçɼó9z8OæÏÑÃy2ï|4/ë9xçsôð¢Ì;Ÿ£‡eÞùhÔsðÎçèáN™w>Gwʼó9z¸SæÏÑÃ2ï|Žî”yçs ©ZÏÁ;Ÿnp=‡Ó[59 g×sðÎç€X[ÏÁ;ŸcÀæ¼ó9àÑ×sðÎçèáìšw>‡ÑöèÎaùÓ6$ÞzË}¶9ÐG®çàÏ\r=ï|4—ë9xçs üTÏÁ;Ÿƒõ|ø=œ9óÎç@ žƒw>ŒÿzÞùpòë9xçsªç°1“#ê¹/‡yçsÜ·9ï|ŽooÎÁ;ŸC¾IöäàÏñO›sðÎç‚ãž¼ó9ä{wOÞù=üEóÎçÇá=9xçsôpÍ;Ÿ£‡¿hÞù=üEóÎçèá/:m›£‡¿hÞù=üEóÎçGò=9xçsôpÍ;ŸCÞê÷äàÏÑÃ4ï|Ž?ßœƒw>GWÒ¼ó9þlsÞù=|JóÎçèáSšw>GŸÒ¼ó9zø”æÏ!Û=9xçsÈ+Íž¼ó9z8—æÏÑù4ï|ùÆÙ“ƒw>GçÒ¼ó9z8—æÏÑù4ï|ŽßÙœƒw>G/Ó¼ó9¤£µ'ï|ŽßÚœƒw>G¿Ó¼ó9zøæÏ!¯8{rðÎçøõÍ9xçs|zsÞù¿¶9ï|ùÚ“ƒw>Ç'7çàÏñ‰Í9xçsüêæ¼ó9ä1hOÞùßœƒw>‡|£ïÉÁ;ŸC®öäàÏ!÷{rðÎçRО¼ó9¤l¿'ï|Žî¯yçsHnOÞù=ü`óÎç{=9xçsôpˆÍ;ŸCž“öäàÏñÍ9xçs¼osÞùòØ´'ï|Ž_Úœƒw>Ç/nÎÁ;Ÿã=›sðÎ篤=9xçsüÂæ¼ó9~~sÞù?·9ï|yhÚ“ƒw>Ç»7çàÏñ³›sðÎç¿ò=9xçsHËpOÞùïÚœƒw>Ç;7çàÏñŽÍ9xçsH¿pOÞùoßœƒw>‡œAìÉÁ;Ÿã­›sðÎçèáß›w>Ç›7çàÏÑÿ7ï|ô¡ê9¬n”Í!{rðÎçç‡=9xçsÈÏÞ¼ó9äßaOÞùè`ÕsX},›£GWÀ¼ó9ŒßªîÎs‰É!{rðÎçLJ=9xçsÈçÞ¼ó9äõaOÞùòû°'ï|y~Ø“ƒw>G¦‚yçsôh*˜w>G¦‚y•§\ŽÎyçëèÑ]0ï|ŽÝóÎçèÑ]0ï|ŽÝóÎçèÑ]0ï|ŽÝóÎç~Þž¼ó9¤â½'ï|ŽmóÎçèÑfpŽ6Gî‚yçsôè.˜wšéä0o©—¹Å0Ø—?)È­~Å#Dyba£æ «[̸’ØøbXµ#h$l'TýÆî ¡Ø mç2?‡à/ºÆúJÆ9/úFAØú@U¢{ô¾âÈMŽÈܾà®ÈÔTçl<ܸpãÑÁ‚S9#\ØñtŽ.~ÛàzGãŽþxêD;`<}‰ñà^ô<ÆS;:#ã¹ÕÅò榻pÌŒ§17ˆñªWw¡ƒ"¼Ýw,ÆŸÊAp+ñywœj´‚¢6ô‰¢&( Q †øzÃËAÜrÐÑ:ˆ%úg‘]¶ƒà1$ôì`r¡uy0<&t æm” Ÿ6¡¶ƒy‹‡¼ƒéeÂèÌÿ„¾ÌNÃWÞÁ¨u&è·̽#‹Ì='‘w8õ5¡oscÅ{ÞÁpj?>ôg[`ÎaW¨ýðnI>„›¾w'ÐL<ùN£¨X·ÀüLËãÓw÷ËõOàV^ ç˜S¼û o©ÀâP´Ì ôáPø†øù=vžŠA>ŠÆ»˜ŸCÁÉæÿP0>ëìPîšEæçPîìEæÿPxxžþ(2Gáà™•‰pŠ‹ì‰Ìc‘yš¾-2GååWi¢òªo“Ðé(27“ø_Dÿx8Ä“˜›"s3‰)2÷“¸ã‹xü"o&3ŸEæ~2ü0¼O†ïZdî'3—Efx2|wüO¦¾¹&S_‰9šL}x*žL}%öÖdfÅ“É]¢_‡1_h3Æ –¨å0Þ¢Ó||ãûë0æ›-{˜ôš5‡q;+1w‡±KÔxs'áÃèS‰¹›‡«D§Àuçð¸²%ú8î6ž…§ !Q¢ŸSÐ4Á¿ð°y‰ù›BN¼ Oám‰9œrcìkx ü¡2ƒx8õàqøpê)Ó×Ãá¯ãmøpæ´L_çî‡Wá©ìÕ2{c*µâ[x*ZReú:•þ”éëTÕ£¾N)”éë4Õ#=êipžñ7< í…2}F¯ÑΞÆ[<O3íiÜ¢ÊÌç4nvø ž/ LϦ±wÊÌç4öÞˆ§3§eyÜÖþÁ'ñtöh™ùœŽ&C…>NG»oÄ3À!ú9ƒúñ:<žn…~Îd‡à]xý©ÐÏYÌ^„ Va^ ÿx >Îw…¾‰^ÛÙ§vt;;ßÀíh¾Tèk;8·Â ·³GñÜÎm®B_q²So´sSG¿¼>Vèk;sRaWÌföðŒ'õ }-]wõu6œu|ÏF;£B_g£ Ó@_gƒsð&<›»LýœÍ<6ÐÏÙàü Ï4ÐÇÙìC¬$̆o„‡á9pèß8¶ ôob<›ÌAË þÍ¡Îú7‡ý×á9àäú7/8 ôo»ÿÃs˜ûú7Guªsà‘à‰x¼¯ú7Wuªsátâ“x.œðú7­ƒFú7—9Â;ñ\4eé¾åéß\ð ~Šçrl¤s¹{7Ò?\á±x.¸­‘þÍ…ƒÖHÿæ3ñ]<>p#ý›ÇÜ6Ò¿yìU¼ÏÉ6Ò¿yÌg#ý›‡žþŒçqój¤óÀ¡ôo7f<σÇÒHÿæÁ½j¤óØø8Æ{~#ý; |ÓDÿŽ‹àíúMôï(´_šèßQhÛà÷ø(pNý; \ØDÿŽ¢Ÿx@>Šùo¢GÁj¢GQ#¾¦¦&úw4û²‰þÍÀ+òÑì³&úw4û²‰þÍ>Ã?òÑÜšèßÑìõ&úw48OÉGƒ›èßÑÌeµÍ\â3ùh沉þÆêG­ÇÀÇÅ{ò1à›~ôï41úÑ¿cÐüÀò1ì™~ôïæ±ý;ìGåcÀýèß1ÔÜþ>Á·ò1ì—~ôo>xËóá‚÷#ç|æ?Ëó™Ã~ìŽùì{¼-ÏW=ÚUó‰õc—̧§ø]žOûÑ»ùÌG?ðÊ|öd?éË»Øþ-€›©¶EeÜšéåöd3ý[€FD3}[€> ~™€ÏšÙí ØÃÍôms‚‡æÌy38w˜¨™¾-Kà«yØIæc© ÍÇRC3};M ü6Ë|7Ó«cÙ»xo>–½Û >9–½ÛLߎ÷áÇùXpZ35ËÌ5ƒ³Že4ó!sÁ)m!xv^ˆ@vÊBðlpîBöoj^Hoðó¼^ô§ Á•x{^Ÿ ?Xc!5ö'ÇBú‡ßç…ðû£%µœßŸœ‹ÀCx€^„.Bú·Huiî1×ø‚^Ä\÷gî±cú3w‹¸7âz}ìÏÜ-‚÷ÒŸ¹[?ÿЋàö§H‚@Q^ OÑ‹áñ ‹ÁSèßbæŸÑ‹ÙOèßbðÜú·˜žà=z1=@ÿ3èßbö:~¤ÃuÀü-¦x“>ÎõrÇ|ãSú8îèÓñªS»áxöÔz<÷žôéxðÉfíxöíöÄñìsèÖÇsWÈ¢8žý4™>¼8>-a²'–d ó¶Ü7>-aÇ dO,aG äÿf~ }ZîÁ+õæa ýYBÍéÏv+þ©O`—dÎN€Û?Ÿ®ÂSõ Ì@æìôƒÒ¿ÐYÂgõ h¹ dÎN` ¤–àà½úxB™³ØjWTÁ[üXŸ¾iaÎN„cßBÿNä‚GëÁ…-ÌÙ‰ÜAZè߉h"áÑúD8‘-ôïDö~­Oó¶Ð¿“ЮhaÎNbßãáú$öd ý; ¼Ò"/•Î×õIüo¡'q÷iaןÄÞÁëõIÜIZèßIàÉæï$f ÿ×KiV ý[ʾoáÍRp5ž°—rÿDÿ–‚#‘c)»ŸØKÁ4ƒèßRî?ƒ˜¿¥à"¼c/ ¢K¹# ¢K™/…¹DOažñm}*xpóx*àAôs˜e=\îÀ{é2öö öõ2°É ú¸Œø1]Ƭb—.ã¾0ˆ>.7áÑt\ÇAÔ¾ ü7ˆ>.ãžoÓÓØ«ƒ™õÓèó`úxó„—ÓÓØ¯ƒÁM§Ñ›Áôñ4ôÆðwz÷œÁì”ÓÀ™ƒéãiÜí“ã4êLÿN㎂ÔÓÀ›ƒéÉià'ü žÎ]g0};<‹7ÔÓéã`°ÑéìïÁôítp ~QOç®3˜}x:ó4˜¾NÏñz:3;˜}x:xy0};»¾ROgn‡°OçÞ0„¾-gã5u9ua.g¿¡oËÙãøO]Î>Â>\޾ÜîËÁ=CtAV½CèÛrp U—ƒ†Ð·åì[üª.· ¡oËávã]u{k=YACèÛ f?«+˜ñ!ì‘ì‡!ôm{«+¸Ÿ a¬€Û2„¾­àN‰äà ¸v­ì‘ÌK+}[nÀ ë î­ì‘3HÒJßÎ@÷¬g°çZ©ñ æ³¼zw»VvÐÔÛJßÎ@;­g€ñÑzsÑÊÜÉœã©õLöX+sw&ø¬•¹;Su¨g²OZ™»3ÉÝÊÜÉìâ½õLzÝÊÜÉ|·2wg²Oðãz&ûd(sw&ûd(sw&û®gQçPfâ,î/C™»³Ð¨Á·ëYà›¡ÌÝYà…¡ÌÝYÜM‡2wgQïPæî,ðÞ^Ïb.ð÷z6÷•¡ÌþÙÜ·ðúz6úNCÙwg³'†²ïÎ?áÿõlt‡²ïÎ&×PöÝÙôO°góv(ûîlöÄPöÝÙÜÙð {6xlûî)ì‰aÌÖSx‡} ÷aì»§0Øå§pÏÁOìS˜«aì»§ Å8Œ}÷îÃØwO¡Þaì»§€£ðûîÍøŽ}*øw¸ã©ì<È>•}3 ÜñTöÍ0öÅSU‡ú÷TøBÃÀO c_<î^eŸÊ=z¸ã©üƾx*³‡٧ѳáàŽ§Ç†³/žÃÓìÓ¨s8¸ãià±áì‹§)ð9û4æj8¸ãip|†³/žÆ çíÓ¨w8ûâiàI¼Ð>¹Àí9äΞ;‡ÙÄí9Ü•†3ûçp'ξ8Gu¨çp¿Ξ;‡½5œ}qƒ»Üú÷ îœ#èß3àŒàçöìãôïì›ôïìe<Þ>^Àú÷ œ Ï·âûöðÑURôbpÙHú÷ ö?^pW²ŸFÒ¿•ì‘ôo%{¸+Ùs#éßJöÜHú·’=‡gÜ•àù‘ôo%ûb$ý[ >ÆGîJöéHú·:’þ­d¯â-w%¸o$ý[Å]e$ý[Ŭã7w5ޤ«Ø‡#éß*Õ«þ­Rêß*öáHú· œ†/ÝUÌ’9«Ø‡£èß*îxÕ]þEÿV±GÑ¿UìFüëžK£èß¹ôuý;—¾âi÷\êEÿÎeç2·øÜ=—:GÑ¿sÙ»£èß¹à_¼ïž«:Õ¿sÙi£èß¹ªWý;—¾Ž¢çÑ‹Qôï<îòxä=Ü9ŠþÇEÿΗà›÷

Á‡ïjî`ûÑ¿Õ`©ýèßjú‹7ßÕìùýèßjö&>}W«Ný_ žÇ³ïjîû;V³ö£Çkà×àãw üšýÀkÐÛ½½†{Þ~×Pþ~×°¿ðø»–}4š^¬¥oøý]Ë|Œ¦÷çÓw¼ÿž¯|ê×ùàÓÑôë|æ?À烻GÓ¯óÙߣé×ùð)F3{ç3K£ÁGç³Gð |>¸l4¸îjMŸ.àŽ†à ¸o×]&MŸ. æÑôç4÷'×à¼_@Ýû³¸/àŽ†ïà ¸—ì>ºýýÁE°÷§†uì§ý™³uàR¼ ¯îOßÖíð)¼ŽíOßÖö§oëÀcûƒïÖQûþà£õìm¼ ¯gö§ëéÇþÌÙzö6þ†×£+º?ý[Ï}{æl=s‰çáõÜ…÷§†õÌÁþÌÙzîoø ^OÆÐ¿õ¼Ã.[Ïàø™ô ý{&wè1à£g2{ø%~&»b øî™à‘1à»g‚/ñPüLîcèá3éßðÝ3¹ à«ø™ÜÆ€«Ÿ vCÿžÉ>Àkñ3Ùcèß3Á?cè®ø/¾ÙCÿ.dŽ¡²ðd|!w1ôèBöÛúw!¸ŸÆ‚GÆÒ¿ ¹Œ¥²{ðn|!;s,ý»ÆÒ¿ Ù#ø9¾Ü=–þmà¾2–þmàΈÇã àбôo|ޱôo9ð}¼™Kÿ6€CÇÒ¿ Ì$^7€wÆRãEʧ}|û`,{â"xcÙ˱Ʋ/‚{:ü;‰±‹Ø1m쳋Гh£×_Úxx8©™Þ¾ncOlä.߯¬mdO´±'6²çÚØ¹™ƒ6öÅFî·mì‰ô¦]¿‘Œý›`†6bÁmÔ¼‘ýÑÆ^ÞÈݬ·Ã?j£3ßmôïbîsmôïbjÄßòÅìÂ6úµ‰y~ØDÇ1O›Ø/ãè×&pÌ8ðÃ&8ˆã˜§Mà™qôkwˆqìµMìçqÌÓ&îÇãè×&x\ãØÇ›˜ÕqÌÄãè׳èù8vųÀ㘧gÁ«G¿žÅ>GžþÇ>xs7Ž~= 8Ž}ü,x4ãØÏbcÞž~vyÿÇQã³Ø ãèß%ôæúw º‰xv¾|pý»œŽçK¸ÓÀŒof¿@¿6Ó»˜õÍì„Ø›ÙЯÍÌ×ìßÍÌÔÄ63CЯÍÌ×ìšÍÌ×ì±ÍÌ×ôk óu»n óu{l ¸ðúµ\s7Š-à§Øc[ØcЯ-ÌÂàˆ-Ôx {l 5ȼm§ÈÎÝž9=¶ü~ =ÝÂþ:¿…;ÕôïRæó@úw)oð$}){nå¥à¾éߥp{ñ)})Ü÷™·KÁÏÒ¿KéÞ¥/U]š·KÁ™Ò¿Ká?âgú2@äÌÛeìáéßeÜ!ð8}{ÿ@fí2öÀôï2æßÓ—{Æ3o—gÇӿ˸›à…ú2ô<°@v¹ál^Æ à‰íñÌܳ¹ Œ§Ïæî‡óÙÔ9žþ=›½4žþ=›û4>ªŸMãé߳ᫎ§ÏV½êß³¹§Ï?§ÏV½êß³Ù;ãéß³éÑxú÷læÖ—Ó¸ž—³kñc}9=@fðrîѿ˹ DŽË©ù æîræÏÖ—ƒŸ¢o—s×;ˆ¹»œ¢o—s:ˆ½q9||]_Î;ˆ¾=‡Y>ˆ™~8ú pÃs¸¯Ä~÷98¢Ïp¸ç9à'¸¢ÏQýÚÃÏa?Á}ŽêŽx½>ˆ>=usöê‡;úq<5gÏ¡~¸·ª.Õ´ÞØ!ÌÊVfoÜ[éÝ!ôq+w°CØ[Á»øåÞÊž>„ݽ•»ô!ôo+ó‚‡îçÓ¿C˜»çƒs¡Ïïã«ûùì…CèãóÙ§‡0wÏgF&0SÏç9ù{>uM`îžÏN Ï—Ëõï æoý»‚ÞN`þ®kàÏû ÞL W€ß&0W0wxö¾‚E8þ]Á¼M_\? ßWpßœ@ÿ®à^8ù»‚M`þ®`¯M_\Á¯ßWrG™Àü]I/àä^ fÀÿ÷•ÌÎvß•àÒC™»+™<_I­‡Ò›+Á¥pu¯ä>‚Oð+ÁS‡²7®„'s(XâJpÞÁ¯ät({cxæPöÜ6îø ߯]üPfn{ìPfcûáÛèé¡ì¬mÜïelà;|øãPú·Mœ`õo<¼ˆoc¥Û¸ßJÿ®b~ð'~xàPúws?‘þ]%®¯úw½˜Hÿ®HN¤W1?ø¿Š~N¤W&Ò¿«¸¿àmü*ú9‘œW¡#6‘þ]NÃïøÕhN¤W³'Ò¿«©äW“{"ý»ÞèDúw5s3‘=}5x{"½»š;>ɯ†W>¼|5øc"ûâjöÁDöÝռȾ¸š;²¬Wsç˜þ¼šþNbF·ƒ'±'¶ƒ{&ѯíìgü–o‡NbOlçÿ$úµ=1‰>mçž3‰=½¹Â“ùvz4‰ÿÛ¹çLb×m§G“ø¿ùÄ~ÛÎ>Å·ùvî “èÅvöé$vÇv|{L¢O×0C“Øk×pgÀÛù5àSµ#:| çùéÓ5ô23q ÷ üŸ_Ã=i2}º†Ý:™¹º†=5™>]Cÿ'3W×P;ѯa/M&Ç À‡“Ù»/à2™™|¸m29^À˜Ì½€<üðz4™þ¼€ÙŸL^À®ô Ù“éÏ ÙÿÈä¾=pýy!ûÿ0æé…ðc·¾¹„CýBús˜î…ì³ÃØ}/¤ÖØ¥²s?¼sû÷…ðc¦_Ä>; üð"xT‡±_H9 üð"Q‡Ñ¿±÷ñ»þ"öÈaôjü°Ãè×q·UËj: ¼°ƒ£_;Øw‡±¯vp?ŒùßÁýn ýÚÁÝ ûjû` sµƒú§Ð¯àì)Ìÿ‹ÁS˜«SÿúõbbS˜«³‡¦Ð¯3[S˜ý³w¦0ÿ/æž7…~½ü4…=ðbpÂð‹¹ãM/¼˜Ý9…}ûbqº5w/áö5…þ½„ùÁ»ûK˜ç)ÌÛKTú÷æ?ï/an¦ó%ì¼½¿„‡³w_Oápæí%ìMü¾¿”½y8{÷¥à¥Ã™·—‚—ðÿRî‡Ó³—‚7g6^Jø‚)sy8=|)3u8³òRv+^á_J‡³w_ ŸîpÞ¾”{Øáì‹—²§o/eNð-¼“ÃéÛµâžkW\ËÌÎÞ½–{ðáôíZÕ«œ×²§oׂ7ð-{f*»îZzùk™Ù©Ôp-}œÊ^»\ƒ7ù—ϧ2s/£§ø”ÿ§Ò¿—qçÀ³ü˸3LeÞ^®<š³—+zør–ûTæíåÜå¦Ò¯—³S¦²k^Î]g*5¿œ}7•}ñrrL¥ö—s™Ê¼½œ»ØTöÅËÕõéå𗦲/^Î>˜FŸ~Š›Æ¾ø)pÁ4úõSð±¦Ñ§Ÿ¢'ÓèýOÑïiôë§À=ÓØE?Åýs{ã§À»ÓØ?¯f{ø§¸ïLcoìd^§Ñ¿Ü;ñ_¿œ6ý°“»Á4úµ“Ù™Æ\íO½ByÔ›W°[§ñöì¥iì”Wp·šF¿^AÓÙ ¯àž6ùz÷‘éôëÌÜûWp'™Î|½‚{Ìtúõ f.þ+¸×O§_¯Mg¿½’2½ðJxaÓé×+Á?ÓÙ ¯„G4=÷Jî0ÓÙo¯äÎ8=üJöëtj|%xx:ý{%{/ù×1—Ó©ñ:vÈtúu÷Šéì±ë¸?!~»cýºŽ]1ƒÙº4ƒÞ^Gf°¿°[5ƒýu=±ôézðì fízæz3}=ÿgÐ'lfÍ ?׃ûf»ž}9ƒš¯gGÍ ?׳/g€Ã®g_ÎàÍõÌÓ jWºh óõ*jžAŸ^Žs½xs=ƒ>½ŠZg°·^ÅnT¢7³™I¿^e&ýz¸n&¹_®›I^Åd&‰^Í}x&ýz5³‡ŸþW3—3©áÕðofÒŸWs‡šÉ¾z53;“ôî33Ù¯¯Lͤ?¯a_ÏdO½†Ü3ÙS¯áî:“¾ݘ™ôç5Üïg²§^ÃÌÍd?½<£ÖEoæŽ2‹™y ¸}ûé5ì†Yì§×Àë˜En·Ïb‡Þi{éi)¨77À‡™Å,Ý®šEŸn Ï³ØK70ã³èÓ àÙYÌÓ ôyýºý4‹~Ýrýz-31‹~½Ü6‹~½Ü6‹~½–=4‹~½ÞÙ,æÿµìëYÌÓk™ŸYôþµìÃ#ØS¯enŽ`¿¾<|3£sr4žþ½ŽÿGп×qç<‚þ½ÞòôíuܹŽ`¾Ž»áôéõÌâôêõƒŽ _¯—6„úôzøG°^ÏN;‚}ôzîÕGЧ×ÓË#ا¯ç^týz=»ööÿëéëÌÌëUŸæëõÜ]`¾nd>¤O7Âï9’>ÝȰIon¤G²Oo¤Î#éÓì #©ýFxfG2»7Rç‘东z$sv#ûñHöéÔy$ý{w†#éßسG²ÞÀ.;’¹z8õHæê à’#éטï#ÙWoP^ÍÕØcGÒ¯70G2_o„'q$ûêà#é×™vôîíìƒ7‚÷Ûé×éO;ûêô½yz£4.Ô¯7roog/¼lÑÎÎ{#uµÓ¯7‚÷ÛÙ oï´³Þ¤ºÔ¯7±qjö&öR;=~“êÒ¼½IÎÔ¿7±SÛéß›¸#µƒ%wуvöë.0e;ó¿‹~¢¥± ü=›·»¤­¡Þ®œMvÑC46Þ ŽÍ>}3`a6ýy3÷çÙìÕ7sŸ› þ{3w¦ÙôçÍà­ÙÌΛákϦoæÞ3›þ¼™ý<›šß̽e68àÍÌÈlúófîô³Á?Í®A‹ã§™…ÙÌ×OƒÃgÓ»Ÿf_ ÍñÓÜ/g3_?ÍÝu6ûë§áO̦?ÍœÍþz ûn5¼ÞâöÀ[¸‡Ï¡_oa.æ0€oaŽç°ÞÂÏ¡_oá3‡ÚÞße}{ ó5‡¹º‰{Ïúvøj}»‰þΡo71§sèÛMÒòPßnâž0‡¾ÝD/æÐ—·²—æÐÓ·r'›C_ÞJ­s™«·Rÿ\öÕ[áÝÌe®ÞÊ,Î¥Ooå>—>½ü3—}õ6öÆ\æÿmÜ æ2_oÏe_½ûÃ\öÀÛè÷\úó6êK_ÞF¿Ðy;û}.}y;ó2 òvi}hϾœ?—^½9œËÞz;|¹ÌÕÛÙ§sÙ[o—ƈæêfî”8»™{ô\öíÍèŒÌežnf†ç2û7³?çÑ¿›¥ ¢}{3ú7óè×;¸ÇÌ£_ïÇÌ£_ï€ß:>½ƒ{Ø<æëÜKæQÃ;vóسï óÀ«ï_Ȳvôjœ>x';g{ëôosõNðÏ<æêôoûàÜ)æ ÞÉ™Çnz'{{8á]àïyôð]Ìø<úô.x7ØŒx3r5½ ‚É»àÅþz»ä(æí]쵣طp_<ŠþÝ›£˜³[è!Ú$·pG<Š}p øî(úw ûâ(öÁ-ôà(úw ý?ŠÚná.rýûðïQÌÆÏз£èßÏpï;Š9ûYús{ágéÏQì…ŸUõég¹Ç`™âgéïÑôég™¯£Á?Ë ;ýYðÉÑìÀŸ¥ÏGÓŸŸgMo~ÁÑôçÝÜ)ŽfÆß ž?š>½p4=7ûæhæêÝÜ-Žf?¼›7GSÓ»éÕÑôçÝལéÏ»Ù?GóÿÝð?Žf/¼œz4ýz78ãhö­ÌõÑà™[ÙgGÓ¿[Á-GÓ¿[¹óÍ^»¼x {íVö8Ú(·2ÇÇзŸ#v sösôùú÷sì½cèýÏÁ?†þýw¸cÀ ?Ǿ;†¹úyî^ǰ¿~žþÃþúyöã1ôçç™ýcøÿóà´S~t {àçá¿à ÿ‚êTŸ~\ ûë˜åcØ_¿ÀÞ:†>ý}:†>ý8DeGáî3Ÿ~ýwŽùìƒ_ ×óé×/Pß|úõ ì¼ùôë¨o>ýºYœOŸn—ÏgÞn£¾ùì³ÛÀSóéÛmÒjÑ>»¹™Ï>xµÍgß¾‡{Á|vÄ{¸Ìg®ÞC´YÞ£¼ê×{èé|æé=ð€çÓ¯÷›OŸÞþ™Ï ý"u/`Ïþ"øj{ö¹_É7bô×Üwðö¹£,`Wý"xmû÷Áà ˜ù_⻀Z‰Z@?~ \³€¹ú%fg³õKìÛà‚_¢Ï èÁ/ëѳ{¯´`Ô¯÷‚70W復ì×÷²?Ðxy/w‚ô齪O¹ß ~Bóå½ìÃcéù{¹£K¿ÞË}éXúô^îÇ2Oï%×±ôé}à±c™÷1kÇ2Oï£Îcé×ûø,¸ë}Ìÿ±ÌÓû¨óXú÷>æóXú÷>ú{,{ì}Ìã±ì­÷£kr,8æýàÍcé×ûÁÇ2_ïW^Í×û¹›K¿ÞÏÝëXöÖû¹g¢%ó~pá±ôëýì¹cÙ»ïçÞ¾¹B†w!ýúýYÈ\}€¾/äÿ¨k!ýú{|!{÷àÍ…à‚P×BúõöØBöîÀ! ¹|€YYH¿>À|-¤_fðÀíªKóv»´jÔ¿Û¥M£y»¾ÀBúx;ü4i>e!³òAø! éÓ©sõApç"æêƒÌÝ"jø 8dýú ÷ÂEÌÕ¥E£š>ÈYD¿>HÏ1S䎵ˆ=õAjYD¿>Äýesõ!öØ"ðˇȵˆ~}>Ð"öÇè!š6,¢_⸈ýð!æpýúûmóö!iÚh?|Ü´ˆ¾}˜]¹ˆyû°êRíç-b¾>LÎÅÌׇ¹g.¦_f¿.f¾>L3_æ>´˜ÜAß3_wpYÌ|ÝAl1ýºƒþ/f¾î`®Ó›;˜k4qîàþµ˜ùºƒÞ,f¾î`€Ó¯;¸Û.f¾î€¯²˜¹ºƒ»ðbúõîà‹ÙaVÓ¯Àk\Ìžøµ-¦o¿µ˜¾}„¾/¦7s,f_|„þGÿ~¾Äqôë—¹KGo~\róõËÔýúeúzµü2÷Ã㘯_†gtýú(}=Ž>}”žÇ\}”;Àqôë£ì¾ãèÓGÉy3òQøkÇѯJ«G}ú({ý8úôQðÑqôé£Ü½£?å|ýù(¼ÃãèÏð¼ŽcÎîd®g?ÜÉ^=ž~Ý Þ8žšïd®§çw‚ §wÂ3=žþÝIÍÇ„îäž{Îy {íãÜC–€>.’êßÇ™±%ìµÓß%ôïãìÃ%ÌÔ]Ôº„¾ÝE—Ч»˜«%ôé.îOK˜«»ÀhÝŸ` su¸z ýúUî‰ØÊùUî '0W¿ŠnÀ ôëWÁë'0k¿J?O`®~•ýqýúUfåæêW™³Ø ¿ÊLŸ@¿~Õ ÌÙ¯2 '°~•½rýú5@Ÿ>AO`/|Buª†O€—O _Ÿ`/œ@ ŸPš·Op·8þ}‚Ø ìßOp7>yú$8êDzüIŽ'ÒŸO2+'2OŸänq"óôIfúDúóIø'2OŸdHŽOr¯:‘þ|’99‘yú$w ™§O‚ÇO¤?ŸdžOdž>ÅÞ:‘>}оœH>EŽÁ–ŸbÞN¤OŸâ |";áSìªéͧ¸‡œÈlÿxüDúôkà™™·_£öÁç¿FÍ'2 ¿ÆüžÈœýwíéã¯ËO¢¿®9‰>þøã$úøkð'O¢¿¯î$úøkìÙ“¨å׸wD?Íì$jú4wÚ“èã§ÁË'Ñ£Oû8‰>~üzýû4ûì$æìÓÔ}}ü4ópýû4Øá$æìÓÌÅIì³O3'1gŸæÎr}û4½:‰=ñiæö$öç™»“ÀT¿N¯Nbÿþ:»`)³üëÜ«–‚s~»”ýûë`˜¥ì‡_§¿KÁ9¿Î}g)oܸ”ýðëÌÌRrü:ø|)Xà×Áh<ý:{~)»ê×ÙóK™Ý_§^4Ÿî¦¿KéÛÝôw)}»›þ.¥owÓߥôínîùKéÛÝ௥ôínær)óv7÷ã¥ôðnú¹”y»›;ãRæí7ÀE'ÓÃ߀Ä{2øá7Ø'3o¿ÁÝädúøàÜ“™·ß`¿ŸÌ¼ýw‰“éÛo²OfÞ~“úOf¯ý&÷Г™·ßä¾r2ûâ7¹ÏLÿ~“^œLŸ~‹ûëÉì…ßâ~q2}ú-pþɼý-út2;ã·À¿'Ó¯ßGŸÌþ-æàdæì·x{2ýú-bjqô5ðÀ)ÌÙg¸GÂ~ø xñfï3ìÜS˜³Ï€§O¡_Ÿaï›Ï0ó§Ð¯ÏÀ³?…~}†½| ýú xôæì3àÅSØŸá^/‡¢Ñ×À‹§0g¿ n;…9ûm–ÿ)ôï·Ù{§0«¿ÍÛSèÉïp;…}ð;ìíSÀc¿Ÿézô;Ê£½ð;ܹNa/ü8ýTúõ;ðANež~‡=s*{áwÀ¤§Ò¯ßOŸÊ^øøg§²~‡ûá©ôëw™ÅSÙ ¿Ë^;•½ð»ÜóN¥_¿Ë¼Ê\ý.½<•½ð»ôîTzò»Ìé©Ôö»à×SÁV¿ N8•½ð»ìÞS©õwU§æî³ªGýû,¸æTæí³à©S™·Ï2ï§²>Ë}áTöÂg™ËSéãgÁ¡ËèÅg¹/£Ÿå®³Œþ}œ´Œ¹û,< eÌÛïqw\Æ~ø=æ`ûø÷ÀËÀÇ¿G–Ñ·ßO¡öûì›e`†ß§–eôí÷™eôë÷ÙËÀl¿O—Ñ·ßï/£o¿Ï>YFß~ŸýµŒþü<§eôç˜d™ÿ^Çiì¯?€ß~{ëÀç§Ñ—?à.uxá¸F_þü|ûฟžFþ€»Ïià„?`ÞOc|ŽyG{ìsìÁÓØ_Ÿã>pûàsä< üø9rœÞù<ƒÓØŸãqûàsÌÇiàœÏ±·NcŸ}þ!w(µ0ºá;±ôçŸÉ1L¦­¹Šå%qQu:fâ\T=‹å3åBÕdÅr¦r¾‹¢÷Œ—ã÷ÅäUu.ª›±ÝRVŠ)'‹ò˜˜S-ç÷yÑ5³ŸgNXúüë×yýŠÕ6/¡éòðy¹{ÐÄ}ž ±µ¾°kœù »º&­ë([.gÎw¾aŒo5~_4Uü¦Qf½£o³ "¦ÑQ–{äšGoï™×uÏDu;¯KL„D}´3£ H$Àh£èokÂÜ\Büî‘ ½j¾GÎ ´i¾È¤QóåºH5Qn«Tóëâš¿X7XsV%5gÈjvóf_”’·Í© ÚX,Ç Ú>,g!š›/iZÔÿ/±ÕèÅ—ØD(«‰Ë;ªù_Òœ £&Ú¨"Ǜڨ­ñ?‘b·6÷Ÿ€0p õ§ EÜLý)ÛZJ.ÁÿÆ5®Æþ D€â÷ŸII\›úËÚDªïË ?”¿¿ ¢EùûË0sQèþs9ðøs.¾ ›þ/É—ÿ/ɇòö_’/!ÿ_r)NØœ)eoõø/Ù (m…K_>|…7úý.&fí¯˜œˆç¯@(iÿo ÔõW ‹uýH§@]%EmÕñ×싽¿ذÍ6.2ͦ,²_þFt¤ð7l²"sñ7 "3õ7(Cé˽lþ"=¸ô…’õ½07P°þ*³_dé|•^ XýUw(VU Óš«¯Â”@±úkÌ> Õ_é–˜£¯ÈP¨þŒãk *\Eÿ-ý,4þ–ùÄaô߈)1ÏK͸þ[úUq|™Âyô×™ùýù:op!ýu ÊÓß`¾Pžþˆš5ö æêoP Ó(SÃß±ÁQ˜þ;ŠÒG (Jÿ—6ÜWÿ½sk§ý=3†뿇qR¦Öo²´P–þ&È«LÎo‚¤Q–þ&}GQúظµþvI™ó䯹õ?€„ÊÌä?²åP–þG.#ezÿÌ ÊÒÿÈå°Â~ûGê¯0÷ÿDýfûŸ¸$àRûŸ`(UèÇ?Ôp¬ý-P]…~|‹·¸×þ}” ¿¥üêÇ·¥D­~|›K ®¶¿Mÿ*ôãÛìgnß'ejõã>jBú>P[…~ÜOQ„¾_ÊÊšëûéO{ø~.% ÐͱnÇë;’ߣlÇë™°+¢|Ìò¯™HäJÌúÖm6aòÊЮH„¦l¤ñÇFÁ¸+kòØ Çp ÷íê…Èb|ðQ¯ó€‚f¾ñ%0oÝõ„bçñæl¬áÅißøWÛÂ7¾¯å[“$g1)B qö³ã®ËÏ)ȺN@?‡Ò´G Î)ø®Û.XÊúÖ‡ðë· hÛ /˜ã‡Ëô`LÆŽ±þÁ(ì~‹ÙWç7A’ZÉîñ¤KöIÆ\í\Q >†@ ®âñÔ²¿å9C±£-¦—ä@¦†XÉuC̦½,`~ûÏ]ì™®:Ü!s¸$’Ç,í¦ÔVu}¤¢¬\ðMFuÌ^ˆ±Ë&Z­øÐB0„::E”¯‰ˆA"€Á;f_i¼CL j¼Qã[uâs5à‹ïg¸.Z¢ùL‹ßgYŒ v„ÅØÍGZLèF‘¿vs¡ÎëëË.ö·îK"Óü¢{Çtà{I¼cyÔfKáøË_U˜Uæžéáj²hw¹mp1G>:ÀMDõÑHxDhÉzõUWû½®^]Ì\vu1UUØ©¢Þ ±-Ä4¶º ˜.ª[0OÙþâQ{7¤Ú œ Õ^àû¨ög­µœ}j/pyT{!îAÇ \Õ^àé¨ög­µ\^j/ppT{¡KCþ‚iGâ[î%Øpm¾ø1~Rˆ‘üç÷èÏï!&Øï!în (öø‹{o€L+[€)'F‹m.©á8›H\ho³È5m‰M!>VO°ùÃCω6yÌÚIñÌ<µ4ž6ãõíäxÎŒ_ÀSâ 3Þ%OgËx$]O•ñÉzZ”¾çü¢{÷u÷…o¡:Ç¥îÛ²xªõB`žì—ÚÚýÀ¸ª¾ÀKP-+Îj/ð T»à ¨Ö!<Õràø§–ƒ+u-×œÚ ¼û€G²8õ©åÀ—Oí…î/ðåS{Áý¹ö_>µ €ZÏðåS{ ŸÚ <÷Ô^èîÜ1yxî©å€wP›E<÷Ôrè~Ø‘Ï=µÆyOõb4µ¸ç©½À+O­÷Æ1Oõ>xjYžê <îÔr§;ոשåÀ­NíÞtjýÀeNížrjS…ƒœZ¸Ã©åÀ N-Îoj/¸OÖ¶ ®|kuàó¦–4YË¿ÞZ\ÝÔràᦖ§¼µøâ­õ¼µx®©eÕ½¾cä¬UÃÝÚ,ÂØ¨¡ ÜëÖjÅ«n­V.´µ:­ÕŠëÜÚ <æÖ²â(·öÿ¸µ°nj/¸3ÔúÜZ|ßÖ^pa«½€ÅS«ƒKE­gøµ­åÀm­¼ØÖfçµµÂgm­.µ:ðP[«¯>µ:ðG[«7´µ:ð>[«Ã8 ­¾À×l-+.fkY—Ùê ÊÖ²âG¶–Õ¸’­¾Àkl-+ô²ZVã/¶ú‚;}-+ak/ _Öæÿ¯µÜýkƒ·×ZVœ¼Ör@°®åÀ¥k­2<¹Ö^À`¨½À\G­.bµÜËj/¸¦Õ^pk«½àÊU«Õxc­¾0NX«/ŒïÕê ÏÉ^p•­Uf8%Õ\tk9¸öÕ^à9µö‡©µ9C€¬ö‚ bíŒ‚Ú .àµÜÇa)f/¸JÖrp[¯½àò^{Á]¾ö‚Kgí7ýÚ œ˜Öö|€Ú ®§µ°j/à.Ô^ d\{ÁE¶öNDíJk“‡_ÒÚ .¦µ°üj/p>Z{ÏÑÚ .ǵ˜¨Í"lŠZ‡¸ûԲЍ½€EY›3xµ=„¯ÐZe0-j˜ >G­28µ0 j/`Ô^ ÕÆñgõ|«ZV83µžÁÙª½`Zj/èi­÷ô´–ƒ÷µ¼¯å µô«Ö!n‹µ\øku©M•µÊîÓ“jŽû6²šî«©ZÙ}b5U«¿O¬¦Ú XMµ»YM÷‰ÕT{«©öVS­°šj/àJÔ:W¢–ÎIíÌ“Z­0fjuÀ’©½€+S{ ©VÌ£ÚTÁ?ªå€mTËǧö.N­VX8µ°3j9àhÔrÀÔ¨½€¯Që¬Ú4Àݨ½€iQË k¦öÖLí¬™Zõ°fj9`ÍÔrÀš©å€5SËk¦öæGm`~Ô^Àü¨Uó£Öi˜µ¬0?j/`~Ô^Àü¨Uó£Ö!˜µ0?j/`~Ô^Àü¨½€ùQ« æG-ÌÚ ˜µ0?juÀü¨å€ùQËó£–æGm`~ÔrÀü¨"¿ûÄü¨Uó£–æG­2˜µ0?juìf~Ü'æGmÊa~Ô^Àü¨½ÀÉbß·‘ÿذz³ð?j†ÿQë+üZÏàÔúj<&V_G‰Õð?jýØÍÿ¸OüZ?àÔú ÿ£–þG-üZeð?j/vó?îÿ£Ö3ã×°úþGí…ñkX}ÿ£öÂø5¬¾€ÿÁe {ÿ£6gð?j/àp+È^Àÿ¨½ØÍÿ¸Oü*Ëç¾üûÄÿ¨ÍüÏiµ/àÔvüÚ,Âÿ¨½€ÿQÛ:ð?j/àÔ^Àÿ¨½€ÿQ›øµð?j/àÔ^Àÿà“½€ÿQ{ÿ£öþGíün2Ù øµð?j/àÔ^Àÿ¨Uÿ£öþGíüÚ øµÊàÔ^Àÿ¨½€ÿQ{ÿ#Ý É›f×Ô64·§Ú–%fNŸ8=Ùvb{ª%1#ÕX—lØTS»$U»¬mbøš²,ÊùV鸱¸›?n\”sCé¸ñQÎ¥ãŽ@acMSò \³n*7!ʹ£åÂ¥ãGE9¿,?:ÊÙ·1µ´1¹<Ùxи’(÷°Ò1ÅGDù¥K:«ëÚjÚÚ’MKáMœºáÁÊÚ(¯é 2ŸßÑ\ÛÞÂîH±½/\þyKk²¾¡3ÊMµ¯lIFyïH5§ê둜Pšõ©(ç ©L¶RqSÍÒ†Zì×ëµK\¡‚ÖDÙolk¯›8±zFŬò(ÿe5Íut¤XÓ”ªKFY?^Yß@Wx²9ʺ<Õ’lvÁ¨à ©8R¸yIG}}²5ŽÆW¸„64×áUú¼†æšÖ•Õ´¥D=ç¶óþ½uÙ7ÑÅÔbC…gÔ·&“ÕqEQÎ’):ÛšlmM½½vYM«[¼!DW¦–'[ëS+¢¼éÍK“íµ>M´¼%ÕÖ aˆòs|Y[ÖÍ '%£ìS,º©½5ʾȂ’ÐnþÞ‚ç66,mnJ6KŸnsÍòd/›,É>ÿÅÌÛ›}¹+[ZSÌÝW[“5uq,ÙkEkC{Ò‚·Õ6¦Ú,—40z6VÈg:£‚÷5WkJUÞåî{ecÖLJ£ãG•–º%ÕcF/ih¯Nµ¸.ÆÏL¿8·®®Õ½)5óæ’d …™Á¯”Æñ*Õ¼(óbmº74·µ·v¸µ±rIriCs”s|xå.iK.usvIƒæü}l-5ž¡©ü¸­•·šÿ©£ª[›ÆŒŽ >à_L+Ž_Ä_Lç˜Z½¤¦-©7òú7Ÿ™Ý›ÊûCîKšF >ÒW1/.é«X/Šï a íJ­ê(ï%K“ÍÉÖšÆê ÉÌ»òOü»iã7<üÿÐŽUú°°^}11Êü6«nmg:<'VëŠÏaïÏŽr§•ŽUåNçsZ”[ΧÞÇçŒ(÷h>gF¹3ùœåVð©2NäóÈ(÷>…–ò©*V—ŽMkøTkùTçó©*.àSU¬ãSU¬çSU<“OUq!ŸªbŸªb{éOçSU¼€OUñB>UÅ‹øT;øT/æSU¼„OUñR>Uŵ|ªŠ·”ŽA—¿x>Ÿ‚<·UW×¶Wk†:ðÌqË£‚ßø×f}ypÂËOµtÜópûñ—‹Ú’íB8»_¯r_ؾ¬dôVŠŸåçWW×mª®x!ïgDyÕ¥£Fç{•¾gFy5úžå-Ñ÷Q^­¾Dä‡ïö(/©ïÙQ^ßGGy'ë{Z”wо§Gy«ô­z¶é[õ\¥oÕsµ¾UÏv}«žkô­z^ oÕs#ßÒ†/½]ߪçúV=oÒ·êÙ¥oÕóf}«žŸÖ·êy‹¾UÏMúV=oÕ·ê¹ïÙÔóA}«žé[õ|Xߪç}«žè[õü²¾UÏGõ­zîÔ·êù}«õaF1õ¨3Š©G}˜QL=êÃŒbêQfSú0£˜zÔ‡ÅÔó6}«ž·ë[õܬoÕ£>°õèk>°÷è‹>°ùè«>°ûJŸÓ·êù¸¾UÏ]úV=_à[û¯t“¾UÏõ­zþHߪçõ­z¾¤oÕó'úV=ªoÕógúV=_ַ깟omÂR¤oÕë[õ$úV=}«ž¢¾UOIߪ§¬oÕSÑ·êiзêË·vb)¡oÕ3Nߪç}«žõ­zÆë[õ¤oÕs°¾UÏ!úV=ô­zæó-o ¥2}«žcõ­zê[õ,Ò·êY¬oÕsœ¾UÏñúV=Kô­zNзêÑþ›Á•‚ý7ƒ;ûo— öß íGí¿ÚÚ3´Ï×·ê¹@ߪg¾UÏz}«í¿ÚÚ3´µÿfh?jÿÍÐ~Ôþ›¡ý¨ý7Cûñ…úV=/Ò·êÙ¡oÕób}«öû‘½Ã~dï°Ù;ìGöû‘½Ã~dï°Ù;ìGöûñúV=ìö#{‡ýÈÞa?²wØìö#{‡ýÈÞa?²wØìöã¯ê[õ¨3µÕ‡™ÚêÃLíGõa¦ö£ú0SûQ}˜©ý¨>ÌÔ~|§¾UÏ»ô­znÑ·êQfj?ª3µÕ‡™ÚêÃLíGõa¦ö£ú0SûQ}˜©ýø }«žOê[õ|JߪGûo¦ö£ößLíGí¿™ÚÚ3µµÿfj?jÿÍÔ~üs}«ž¿Ð·êùK}«ž¯è[õhÿÍÔ~Ôþ›©ý¨ý7SûQûo¦ö£ößLíGí¿™ÚúV=MúV=ýô­zšõ­z´ÿfj?jÿÍÔ~Ôþ›©ý¨ý7SûQûo¦ö£ößLíÇCõ­z&ê[õLҷꙬoÕ£ý7SûQûo¦ö£ößLíGí¿™ÚÚ3µµÿfj?ž¨oÕs’¾UÏR}«ž“õ­z´ÿfj?jÿÍÔ~Ôþ›©ý¨ý7SûQûo¦ö£ößLíÇgê[õ\¨oÕ³Aߪç"}«í¿™ÚÚ3µµÿfj?jÿÍÔ~Ôþ›©ý¨ý7Sûñ%úV=/Õ·ê¹VߪçeúV=ìö#{‡ýÈÞa?²wØìö#{‡ýÈÞa?²wØìöãÏè[õ°wØìö#{‡ýÈÞa?²wØìö#{‡ýÈÞa?²wØ¿¦oÕ£>ÌÒ~Tfi?ª³´Õ‡YÚêÃ,íGõa–ö£ú0Kûñgõ­zÞ­oÕs«¾Uú0KûQ}˜¥ý¨>ÌÒ~Tfi?ª³´Õ‡YÚêÃ,íÇOë[õüº¾UÏÝúV=Ú³´µÿfi?jÿÍÒ~Ôþ›¥ý¨ý7KûQûo–öã_é[õüµ¾UÏßè[õÜ«oÕ£ý7KûQûo–ö£öß,íGí¿YÚÚ³´µÿfi?ö×·ê oÕ3Pߪ§EߪGûo–ö£öß,íÇS‹Ü%å¢{Ï*g4,h¨\PË©„=9‹=Z|ºò­lkiåÊ}þ½I—Õr¾º¢¨|ÉÑK6ßj ¯,*_~ôò-¯_Ptô’ò­¹·èèåå[rdz‹*¶dN>_”,[´%ñ7‹*¶UzUQCórî³k8„®æÝ›Gb–0†0Ä,0FÜTT¾bKß]ÔRÓÜP{ÏYj!ãú˜:‰?R4»mK34{ëû‹¢yuÓê¶¼~ ¯m}}BÑ´ºy[_ÿ\Ñôí¯¯¦²[_\Tµ-wüÚ¢çoìûX(½U½«hÑÔªù[^¿®¨bÛëøö¢Ù-[2_  Û[õX–ØƒËæï‹’Ó¶,Ý×Nßúø—Š’S·>~iQr~å–ÇdÞûø3d>aËã~4¤÷±ƒ“k¶­ƒÅ+æmYCqEÑó·ŒHé¹Zr"»lc´÷R©HYŽŒrvÖ¸í]ч+K{”3‚n,ßÒd¬:ÙÛÈkŠæ¯ØºOãq”ßûö·‹Ê¶îO•Íš»¥¹Å=INÝŠ„þ¶hî’²Y[’O,š»|¢)üKÑ¢%ÇoÝ^—-Z~üÖÂ):~{á_/:þþÂ_OËÏÞÚòßPËÏÞ:ÈS5È©º«Ìâîÿº¨b+ƹBãÜ;y\dfq±IêX/Ó¶$ѹf眤€ñÞ›D·œYºõè–3K·Ýrfqë‰Û‹Ê· ³ÒåMÑüªêùU [òœª ¡(g$_b ­\²ÎYò}®¬Mu@ð2Ç+Žl­8®q´Òq-Þ§h¹]V¢‚OQ"ܯÂÛê›ÈÉ!‹ƒÛk‹ê’î±¶siçÖ«¬Yž²¬&Kñ›E)¸1žv´'Ñú†(ÿ\z©V’Ç£áéPá£íí´‡ûw¾·û²/èÜR8í1w4î}ƒJG¡{Ö`}kÇÑ·vl«¾õ~¨¾µ*†é[«b¸¾µ*Fè[«BÀïHݳ„ŽÔ=kš¾UÏt}«žúV=3õ­zfé[õ¡oÕs¤¾UO»¾Uupï¥î½ÔÁ½—:ÀÔ î½ÔÁž§î½ÔÁ½w¶¾Uv÷‘ZÇZÏGjŸ®oÕ³\ߪg…¾UÏúV=gê[õœ¥oÕs¶¾UÏSô­z´*Ô½wŽ›È¨àõ צF±«ž)Ƙˆ†eßÜÖ,p¯u¯,_dÛ‚f×ìÚ#Ù‘…\ôrEUæu|sæ}«Û –­F]lBÉ73Êÿ`ÈgЛðµJ8;Ê?ºÖæ†fÒ)ÅJÛ2¼™|шV{–þGɪ~‰¦(.ä©%0ç.^ò’d-èç¨LæB'9öVP9Æ¿î$r%sõRÐæ¸JÖým*F¤Ü+ªæNc¸¿×Ü⵿šÂ ~·s“ïünï÷ûm[|壘áäßÝv‹Éß_C‹M¿?,'§o'õÉYÌû¥±’˜´×þo¿Øý iè?²Uâí$J癴᥿‹@‡ÀNgk¤J½¯k)…ÞÒ†¢Èç¥=$ý;óýîl¸BÔuSÈç@ø¼{=}ê ïΤ+Hâ¶ éî}qЯ_˜|i{?¹\1¸‡ ˜/È‚e“mzýäîqÕàZ‚jîAfí‹ñDújXqY5,oÉgä­”ÿ$ÉaÖús™R›üÍ#gƒÅèEÑb¤¸z‘ÿ ^ÍËÄ‹§—O]ptôÔçØ[³î¬-€‰WÌ™!QEŸIòJJkâÅåóæÍí_hoD™µ 0ñâʲ9Zl®‡H€ÐCÉkM”\L½‡ä÷=¤NßC³Ì]Œ¾ùy´¹míÀäý%ÖUüôᇞˆ›Kt4׃æ7/KÖ%x•Ÿèæ© ä,%qWüt×°ì ×fEÃÎÚ¿g}7ÂÒq4ªàÛØªíûG¥]Ãr.Äf‹rÑ™¶2ézè7!ÚçÁêâvŸéMs¹dT­‹ò–òæÕ¤2qžþ£'Q¹dYm|Ú¤¿’—*=+î/w̽ý¥þkO–žõúûйÔõ—ÞÔû‹€è¾þÚ˜í/ò£Ø;XV©ÁúÛÕ\òÙþ"`ŠŒ¨¤ZJ ÿ³¿£¶Ý­]oéK½·Hªvö–~øÞÒß[YÔ—ìWé–Š·Í5|ìr ãÚKÀ—n9¸mdbú¼ƒ;¢£÷›lýFøÙ'ÉC•néíw;ÒjÛ–F#K°×°³ Il¦Åf®¡…+ò|JU^Á)UÑ7®,ÊNv/Ó„9Ñ÷xÿfÅϺ¬$/k]×»£¢ªÏåOyl–®‰öºŸ¹¥>Ûyb…yZbïèÿÙáÝ›3dr;çŒ9ðsÆ\ø2"»V4¿R¬ù™œ8aâõ6CÈò*7vR*Åÿ6C%f¨üÇ*O©úsTfŽ>=9C1ØŸ!ú_Ÿ!®ûfˆ¹ð3„¼13¤ÓPC—öÐBí¡h—“l†ÔáüÓ冮'fHòm[×oA'õ;³ó+»ý*³þæ”Çfg«Û?{y…ÕÙ™fd¾½£ïË»56;HBwÎŽÁ¯nv˜?;\(˜Éò5ž®¹±û'Å,HP3;’·k<}¨‚ÙÑžúóó/{‡ÙyˆWùøìÐ÷úì ½ov˜?;Hx3;0l:£ÊÏÎñGža³ƒè·døn!MgüÛî.lØÝóOÅÿÚü)#òˆm»wžÚÒóôŸwøµníå™Vg)ÌÌ {Ǭ ï¶Ø,q÷éœ%ÍC:K̇Ÿ%DÔ™%I?ö»C;œyÊ÷²ëÌ’úÝñ_g)Ç’f–Îg–d èñYÊqågé!Vîã³ÄÔg !ú}³Ä|øYAÆ^²„ r¥ýk5+×ÝÜs—ÍË­“4/WÚld31µ™·êâJ›©±Ì”ò¹>G(—,O(áR™ÏÅÙÌÅ2ÍÅvê­ÎÎιÏÅäÐÿ©“¬²YàEç,ܬƒ››úïg‘ÃÆ¤¾|°wo|žÇ«g½<6תn¶Þ`W ³7ª?í¡ ¸Þ v'Ü…õ¢ß’`NçuïíMÞ 6Úf¶?–4„]çg¹¹÷ݳ¼‹=÷‘¹ºçêóŒô߆»Ææ‡+içüÜf›™ñóƒÄ nZ¤r[Þ݇ ègm7í›ñÉôò!ÚµêÍvîÆ¦Ovö‰ûšï½ñعÄQ±}‘Aãu'„`ßu(Lï.b‰Ió2hüÿ¼îw??OzS¿Rƾ;(=òýED’þJ’wÐ+Ô_$ºúûŒb믺hú+©ÿA¯øßý}H‰ í/½©÷ט7z¨¿ôHý5ü¤5 ±µ”!ûLÇöë;"œbƒ)Cö)›52ñƒÛ&\\Ò©¥çr ÝI ‡3ãv$øs*)‚[†ìæáÖÄöwsW^N'³ÑP‚¬ÞµÙ»Ë»OcçË~ÑΜh쫨&Äw j]}/‘ýj\¦ ŸL¼H|²Ã¼6½hÁŒõO_8uß®õ9]7åtžœïj÷˜aéý5îej[S’®écÓ‹ªnÊŸ¢zVäçöÞgSœÑ=ãßbÆâûk~6;Ú óÙfóÎLn ó~ƒ½cïï¾d{AÖŽ=À,¦{@³™Î²±óaÍ´¾±¼lÑÈD´Ë {‹ø+ü‰G·¾Ñ=Íò"Ûˆi}cfGLfï—å½D¥ý{öÃÀ£m?ÀR‹ŠàùÖ7zœxݧ{î´=±k÷¶mû†]16ÞsɨwŽ(aÛwÜ:ZÞ(Ÿß-ÛºO1<9†]¡1 ñ§὘KÕ¸ˆ4ŠƒM‹Ä'û:Û‘³~bǬ¸¿Vî‹®¶dcmîšuìšUÓng~ª;Ç0âÊhïT$ÂΙl»…½0?ì–Eöް"¼;ÛÞ±nï>gï´âÝ3ïâbÛQwî¨mê‚ÛQÈû]ƒ¼qslDgزô®Ñ:rïDæ½&ȿ׮1ï Ö1Z¬IaËØqþbË` –[Æ3]Ä_‹¹=•À.Öõß0v¹ÆØÍflzÏlí½[˜=“ÇÍì‡÷ì™gÏØH‘ødybÇ,»¿N³cl]I_]½û%»µØ›JçžíxÓ¹ºn,2|4úQ’°‹&Øaþw„Ýr“½cîï ï¾n¹5ïqÀÇñp{§yáÝxÛEð+;wѦpŸA¦Ûï cëÆšqdùü ÿpÞi[ëÝ¢ô;#n 8’tº}šwˆŠóN"÷#Ž$çü!?ŽÅ=ÝA©oëL›L;ÜŽB¸\sQfÃ8²ïÞðµÝ %l¾_·”€¡ØWzÛìc?¾S¬ÒæAm˜ kcÌÍT‹1+3-Æ|̳3á¹ ÌA[cg™÷ÎûÁÏ*sáq"ñÜ)d`dKÀ fE '[¤åÉ!Û>‡ÁʑΚéÁÏe0ÉÈ–Çn~oö}rËxH~hÏ-ƒ™¬ß2˜Ãú-CÓôð-C³™Î;æ¸ÙÉðÁ~ÙºÙ!QÔ}“<ÎæN²P_~ð~Ùÿûf÷Rz³£7õ›¦ öÝìè‘ï/– è¯ì+ì7OýEE©«¿Ão´þbÚ@µT°×²ß¼ÿÝ߇ĚÒþÒ›z±’°¯¿ôÈ÷# x“‡ýÞ¥þ¨®ûùÅÊý7q¿wýÏþšÛÈ^¹)ß_zSï/öõ—ùþ¹Âv›¸£ûýBý]ܶ•7Œ¹ñX±,¸ß/þgoGnÓŸr}¥'õ¾b7b¯–þø¾bV‚¾Ê Åè©®¯çní+V'è«î†£§þ}íei¸¾Ò“z_1_±¯¯ôÇ÷ëôUÍѯu}ݲµ¯¿ ¯âã~íÿ××^Í×WzRï«zôp_éï«æÔôUoFÓõuÍÖ¾bƒCu4ÀùýÍÿ¯¯½ì1×WzRï+Æ<öõ•þø¾b냾jFö?ÄõuÃÖ¾b „¾Šß²ÿ!ÿ__{¥Î\_éI½¯ØÙ×WúãûŠÉúªÝµ«ëë³¶öþ}Õ­bÿÖÿ¯¯½²j®¯ô¤ÞWL›ìë«å÷Ù^aùDœ¢niûªÿ†•Ý-¿«_ßÝÑr»Ò7ös©ãuíÕéL¹Pp¶ü}ØLë)fU:{j¹P¶§ôÑϪzi8Âc>¬{SĽŽÅ o…Mx;³3ºhYÍ‚.t18½‘{Þ˜÷Þ˜Ú¹lËKÏÃ5ÝI»ç–쮜Çͽ7¼ç®âÜ•×Ú]¹Ä·éûnJª{r×…Ù…aöι¿^s_¶õ%}õå÷¥­ùc]]å쪼ÇoMq.;i¯œŸÛIÌžçß±“vÚ;æîSáÝWl®Õ­Ý·%Í`:ךÉtWiŠÁõœÇ~£Ÿ—ׯŸgø/O»µwusò0e³ï¾@_ü­K7Ü …ÝÛFLŒò½Ãü8Æ0JÚF÷ó³‡Ýwý´§=ÜÉ%hxìUÑÌû:Ún‚ôjB˜ÉÉÖo¬ëtö{K¸ÅÓKßWŒïÈÒK#«íüM}ýw®èéÿ&õ¿W 4ï¿ç[f¡Æ›¶³€ÕŸÎY¸1Ìý÷³€™îàMà‡qçõa©®Ûo×uq÷-ø­ìê;ØÕ»¸×öó¾½¶†½¶W‡5ßÃí¡ÏK­ÏØÚwÓ§·¾Ï˜&foÂzØûnÜÃÿÊ}P€|? Gûø±ôÆ÷ HˆMèYÐý¶Í{–bÛõlûTzµÛóØëJû°-}ô=Åø³§›îíÿwöp¯âq?{ØpÚ7{ôÆ÷ OÌž¬Dxí³÷ÔüãwìGí›=úè{Šy)á¾~hæŒÿâF^ø¿âϽ{ºkça£jþ¤/¾G˜°Rÿúaõî CwÜsš‡˜»Ç¹í½s‡}¬}sG}O1ª›@?ðÈAÿ<´É]ÞÏÿ¸ËìÕäÿw,€í»Ëh&Ó›ÂÐøáQ妎îŒ<Ç»a²ˆÖz5È1¾UãíøÄKÄ»í¼8^.<ÝÉ}œ]í“O¬¦|Y µ½üã:µ*àõêööÛ+ŒŸrW˜ÏÁµØ/›¹UáÝå}K;‹˜8ëÜ•_<]fÌïJ ½êi3Ø|B/gžÜ>\7m/_Îñãj|8í°3fGFìHÝ,Ìžü“í|¸ÿsÙLJû’n Oì …³-ìÂ÷†wŸ²ùÃh[ç.4G#7š¹tbÓû²8=‡þÆmÂ(‘°ÙÄÔ›8ÍÍlšCÓ¢÷ÌÂäsñ#ÎÀ"õ~ï]Óö˜þÔo~XëÜ1VûÇö˜Þùƒ9q]š¹¯OtÜìƒqη[¦—çÛŽ-Ç;v[~z/á*ãõáônr×}Xªë}i#&Ú7 ;„‰ö@ÐðZöÀ9áÝ&›¬ÜíÓŽc.üŒ`O¼±f4E'¹;M§Ïî›uÞŽÁ&Ú<ßÑÑYãnkûpI¸g¥Î÷Åæ^g߯7Pzí÷&ùÀ‚âäMÞ_XPì ÿK}¼ϾûÂÏ‹ øI#!z¸eòþ›ùþ~wìÜtG~‚s¿W Àqÿ»¸þßÁ5kîÕ9z¨v³ëüÿñÎc|þ¶ƒ~÷þèµ%˜Ók¬ï 9Þk9˜×{39â\ÛØ'ìÄCËÂ>Ð,§s0¸n„ýáBÖ3x3kú7-¥½¦1öÜŠ±‚¸ï^Io|Ÿ0’¨mÔL0åECÜ+Gm³·ñèÍ û‹ýTÏÒ~ÒCßOÌ3ª×¸RN¨Î]Sïí{ÈqÇž;1V÷ͽñ}¤z8€½øvÜ+gÄóÏ~ps]ª›ëÞ»À#÷yìKî›;zè1æ'ÑÜWyê7„pŒàA´Ë2{]JÞë~Ÿ¾]`ó Íf¬úàF0µ—ã´+ÌÃ{¸¥ü'=ƒ}Ú=w™3¢ NYqú®ßÑCØñozÿ¯'OhõtßQW‰ß¶W“Ïb"æ{gÀMwØ;͵´L2¬ä±3:;±:=~whÞÓ]ˆOݸÀ¿š¾¾>¢Ò«7ò¯z":QIu$Ð4D<— ‘ñACdBÐxLO+¢û¸G̅߯EgHš3nÚ,~†°>*ëƒá»Î¸}3žhÖltk²4Û\YýÍÎÙèìóÚâg $?;èy]æÈë²0;í6/ôº¦1kç ¨ó¢ž§ó øyà…øEáî̼~-ÈFÎø}ÿ¢ëé´ {7òÿÔ‚ÄTë>-HóåæK®ºs¶ óyÄÕ;øé-§ÊaDÏtWô´0¶çÙƒË{æc[¬›ñ ù)×˱Izÿe&æM±¥!‡çB’ÃkcX¶snn s츹1 ¬máÚþœ¡pý£:ª=¸>V“ÂõvÈ\?a{èÞ­vÕæ~¶öksµlá¯î¹ÝÚf|ªŠ²õØ ,Ñ}Ó5ØÝôMOoY"Ë[–†Ìì,ŸæõÙbM@#K9³ÿ‘g~ðá ZÑúÙÿ8tÁ<ôzs²}7=ëžÓ³ú<à—aß<ÐSßwã³ÁÚgŸóâòééyÀ‹ó +îœóÌÏ~˜éÕÍyñÐóÐkGÊõžÕçžÕçûæžú¾ãÛy2žóÝò©éyÀ—ó ¨9ßåÙól¨“yÖÄœï]0½¬\ßéY}èY}°œºoÈåûN!̃4³æ.+Ÿ_éßa•y“lî2ž]bó€Õ2˜3·3Ó·À<ôšÎr}ç£>ô¬>Þ7ôÔ÷Ñ̃´áæþkùÔô<`8šyعÿʳÍ6X“fÄù˜û¯Cì‡GæžÕçžÕçË&ûæžz<€ûú«›×¼ 0} Ì{°ê­® /r««÷“ÙûúKO}±¨MuÉ×§›ßÇÞy¤¿ÜÍêýµ÷Ç®þb´{_éiTžÚI¹°éÝЛ˼5*ë.ÏeΡ.¿‹–ûß½9íìtåÄDxoN»Oºr2+½9íNîʉ¡ñÞœ×tåÄyoN‹ »râ3¦7§Å×]9±hÞ›ÓÞ(ºrbô¼7§‹íΉ]ôžœîvÕ•Óé½9í°+'ë¯7§½ÍvåÄ{oN{ÿîʉ”Þœ–WЕ3î½9-¥+'Z½9-—§+'Æà{sZžRWNìÅ÷æ´\­®œ˜”ïÍiyh]9á±÷æ´\Æ®œ¦ïÍiyŸ]9ñ¯Ô›Óòi»rbÞ¾7§åwåÄ~oNË ïʉ‘üÞœ–Ûß•;ú½9­^CWNLí÷æ´º]9±Æß›ÓêqtåÄ`oN«KÒ•›þ½9­æJWN¼3õæ´Ú3]9çmÏiuuºrµ=§ÕêÊyôöœV³©+ç1ÛsZ]«®œòW°7§ÕëêÊ)§P{sZí¶®œÇnÏi5ìºrb³¨7§ÕóëÊ)FÜÞœVÛ°+çâí9­ÎcWÎã¶ç´š—]9ßžÓêvåÔ‰eoN«…Ú•ó„í9­>lWη級¹]9OÚžÓêwåDº7§ÕšîÊyòöœVK¼+§4söæ´Zø]9ñÕ›Óz<èʉoÞœÖDWÎÓ¶ç´ž)ºrâ «7§ÕÚéÊ){sZ]9Ñ–ìÍi¾ºsž±=§õYÒ•P½9í¯+'~œzsZŸ0]9ÑVêÍi}ÚtåÄßSoNë‹§+'~šzsZB]9ñÒÔ›Óú?êÊ ÷º7§õæÔ•N]oN«=Õ•ßJ½9­«sc9 DZ؛ÓyÛâ8&œézÞùðrë9xçs gPÏÁ;Ÿ]„zÞùh¨ÔsðÎç@K£žƒw>:#õ¼ó9Ð(©çàÏl=ï|4pë9xçs ÿ[ÏÁ;ŸíãzÞùÆ8wÞùh^×sXOD6zßõ¼ó9Ð<¯çàÏa ïwçàÏaìíwçàÏa ïwçàÏǹžƒw>žê9xçsÀ®ç°¼h›õ¼ó9àš×sXºÍ÷³žƒw>ÒzÞùx!©çàÏ’zÞùxk©çàÏ¿˜zÞùxªçàÏǤzÞùxzªçàÏgªzÞùxÒªçàφªçàÏ6«çà϶¬çàÏ6®çàÏaxÝ9x'®Ì@á>ðœ1vcÞÈ%Öòãgsƒ¢{¾émﯨk»*)JaH ™’\Wˆe\ÚÕ‘8ð‰öuŒs;ó+éΫŒ%ÝnɸÖ2ʇ|OF6ÙfdüËø [2–ÅSQƲxºu–uÔͦ¬»¸neáEiùVžWRyŽËUÏŠuX7z禣ö‹$\gTeE—UÙ ¦‹ªl³EU6誯*VÄU6¬x J¾²*͈òkp^-ôæ¾îê êf³QÜOí¸ÆUqu«ú§ê̯ѹJÐ7×SUÐ(uUÐ$v *hze\AÓ+·TÐä| èÍGuºŸn%ºéõ“×!Ý&ú c©“ý„5 ý~WÔï§Ov<ÞfÇbÓ?.Áª¶YWlU۬ΫÚþ꼪è/—ªíÿ¢¸Úþ/zrŠÓjûËïHgýu‹ïg€øš’ºUiŠˆ#¤8à½q•ÞëœfUÂÿÒ”«.jRfû þº8@ ñÜ`ùÿpËÖbÓ‰ÚºêÄ@)“©žbf¨¥²¡~¶ˆÝ¨Š[tí„¡OW…[ÞWØò®G;Ô"‚:Ô"ÖƒØrƒä`GùåoéÐ Ý”qæ_›xЩ–ñê­s }ƒøÉø›–ñ7·d">ƒ2ѽT‡èö&¾ÜaPñ̆ÈgŠöúizkï´j[èVÝ*^‡ô¢Zׯ¶®íŸ*DcÃà¹l¿¶ê~¢ùl•N´êkÕ H|©Vj Î¡âÖ‰ÿ1Tü.m¡¡ÚJÚòCµý5Cu·Ôª(.åPmWmªaðøàÁ «û1 žÕ~À5ÌúÁŒšß0¡maðméû0q´ †I»W}&Þ‘ê.ίn-Ã…ÏÄ=.ü-]‘áܧà‘G·Îâúr؈ñq?FŒÜÝó1B7IÍãéÀPwõe„Єæe„´Æ5'#„5'#Åyc¤æQs2òĸޑ±Gï<²•¥BžWOÿm4Å!#¥“ ^Œ”ßõb¤îcêÅHiª#ÅT/F‰»¦y¥­§Ý0J÷/í†Q¿‰{1ê7î†ý¨‰z÷¢S½û͉óï7gËöÚO“î*ßh߸5£Ñ¦×7ü2:ì´ßO·d­ SÆÑb3+ãè)qÆÑS¶f4¾õÍ® ãK,ãK¶ftˆo´s¥¡ïß±Œ¿³5#¼H2Ê×%÷? θÿ[2î/62î/† 7ZÆ[3¢ŸAFößoß¿5#Û’ŒtGÇój ŽÑœj[¹8®`ÌÅ[*ã4³õ†³öèX½ÿz¬8ÚXc5éºc5d3vÙ¤Ûd¬X ªd¬&D•´=7ÎØöÜ-µ·‰Ë!,Ц{ŽvQ›°® mï´ÌoêÏœ¢ˆ6m2Ã8Ô†lSíB ãT‘PÌ8m;aéqçÄ•Œ;gK%㜿}ƒýÕóžg<àÙ[ºv€ØeÊx€XYêó/³ŒÏÛšÑø“Ñ·ñh¡o4½5¥Н¨)=0Wp`jKŠ)¯ :QÍ~Å2þÆÖŒF³JcŽRÍãÅÅUÍãuWUÍã?W0þ³[*/F+À UÍÙÆ;hëÆ;H-eHœ.Õ|Ðw­‚?ÞRÁÁRQ‹Ù­šIÛè`1¯´–º¾¶Ñ!vÙ:ä9[¶Ñ!Ú½‡ÈW›ðå!š õà]tï˜ ºpíáq'ˆ"¼9ᶸ² ·õWž5¿C ŸªûŒº|¨ØlÚ7‡Š¥é:TL9Mø¡wÄ•zÇ–nOÔ]R•LÔO{oâ’8ãÄ%[3²×È«Lûn¢Tqµµ& +éz1IlcÝL&ÙF™4°QÒëÞ$̓6è$].´{'IÃYÓ6Y¾E•y2žbؘ“u!PæÉb'i÷NV/Ô½ÉBº‡¦¹Ð$&Ü#Èa\¼Q:9ìWqe‡ýjKeS¤ LS„G5ýSŧ,Ú2Sœ‹7}¥}3{Ú8‡kº5í‡Wpø1[*8\\.Up¸æ_5þËøŽ­Ã}øQÍS…µµa¦êò«Ú§jë©ö©†˜¦n½M5Ä4Ívô4á ݦ ïËï‚ ý.ÞtÃÓ·âÀéNYŠrÜTÉ !{ýŸ!›z2C*YÚ3ÄÎ~™!Ü+ü2CÌVU8ãGq…3~4Àc¦S!Ñ7»H½@„=1S·Jõd¦Ø Úx3u÷VOf i^fê¬\3¿÷bæ7úïDkÕƒ4³ÎØê¹‘h;Í’ÆþÏÒW•³Ä±Ö¦<®¦GahS¡îjkñù¸ê#>ÿèuñ¡"Õy¤4ÔÝ#¥+¡®)^´&ëHåT7rÑf>R^^„7Ú‰ël?dËlUóÓ.†æí5:Ù®+¿fßÌËì¹q%³çnÙ ³_D}ËT%³Å+Õ·IÍÕæžý5«ä3[+q×Ùš.U2GWIU2GªªdŽ0±*™s|\Éœã·T2GÝT%st—¦îÿTBw©dO%Ÿ·J>¿¥’¹Æþ˜ëT¥ôͪ’¹ºÌ©’¹bÿª’¹v¡œ[»µã…Nß𒨄«.•Àa£nÝTòe«äË[*™§kª*™'ü¡JæéR§J扭Jæéª¢Jæ5Å•ÌkÚZ‰»Î3d3Oü5*áŽK%p=¨ÄÝÓæm½§Ev*9JŠ1Š%ÅUr”˜Áªä(1wTÉQÆã8jÅÆJâø¥ÙñÖ0/صè2•Ù ” ÙÍÙ v¶Ñ¦2»›ì–Z¸•ì÷ì׌Z°SíJ¦µÊСëYD|ÛW4‹áDØ /¸{€ö‹®c£ìýöµþ·EÙûÈ{±qQöžòÀKì€({w»EFÙ»íæbÔ‚µQ‚1L-û[žC¢ì½ k3…¦—äàO¬äºƒBx„îè•^ØÝóLWúÑh-‰t÷£ÓÞÚ6UÒG*o}`Or¢:f¥b ÏÉV+{‹E¨OÁÕÀU+;<Ç;êäbÁ;”~À¼s¢(âð°™*b¨³À"FÞY®‹ö ×zbàª#-†E»ÅÀ³-&T¥È_¹¹Pçõõg.¦Í§/1´LóÑøú37 4aÑd¦ÛRtÐïDæ–¹g:ðÊ…Þ ˜ãrÛ€"ÈGæÅõÑHøN˜3‰»¡+‘©”zQaf~F»º˜H‹Mí$Q ï†ÚbÙð)F¸*`0OÙþBÏ¿öìW{ò¯½à&\{ç£öǵ¿à"T{VKíláÚ nµ •Ú n­µp€²L¼hm©$ k»c¾ø¡"â÷×;bäfRýBÍÃï!T:üâv…ÓYöÓLŒ=>cZÙÜíÝ ':Úæ’Ú–ØDrÇ8ÁfRá‰6…0d¸71 Ç¥6yü?9ž9ƒ§`YhÚŒJ^sfK–ÅfÄÇN‹g ÷‹Ñ¼xªbÕ·<ž§Xõ­ˆ')V}gÄ3D›Ámf¦þÖ}¹»~Ž`l1SÙ îцøž¾@ņ[lö‚ë^í•Ú |ÂÔ^€œk/¸žÕ^p‘åf˜½ÀëMí*4lÐì8´½€ïU{w§†a¡Ô%¾zÐ Ë^p¨½€¡Ÿ4{áXù tejØ–|­g†+_}k¨Ú .rµ¬¸¥ª½@[Ô–½à’Së=÷¦Ú Mµ©‚V{“.eö‚» Ø){aœU_À䫽€ÕU{a|’U_p﫽àz[›NÜój³±v‡à¾UËŠ·Z8 µ\ÂksϨö¥™ÚÜ~õì­Ú¼¢5S˳¿–ƒ+h-—ÃZ£P}³¿–ƒ{Z-7Ú4Gò¦Ù5µ²¿¸mYbæô‰Ó“m'¶§Z3RuÉÖ‰M5µKRµËÚ&†¯)Ë¢œo•Ž‹ÝØùãÆE97”ŽåÜX: T.åÇåÜT:nB”sGéøâ(çÎÒñ£¢œ_–ŽåìÛ˜ZÚ˜\žl½èwÎñ‹/l_Ö€\ò©¯£¼¦ƒ(ûüŽæÚö†Ts[”ÛÞ.ÿ¼¥5YßÐå¦ÚW¶$£¼w¤šSõõQÞY¤YŸŠrÞÑÊd+7Õ,màxx6¯]âÒ´&Ê~c[{ÝĉÕ3*f•Gùû/«i®k¤1ç6É-xüwñã•õ t…'›£¬ËS-ÉfŒ ÞØŠ#…›—tÔ×'[ãh|…Kx!îê%z^CsMëÊjÚR¢žsÛyÿÞºì›èbj±¡Â3ê[“É긢(ç ÉmM¶¶¦ˆÞ^»¬¦Õ¿-Þ¢+SË“­õ©QÞôŽæ¥ÉöZŸ&ZÞ’jkÐ0Dù9¾¬‹-ëæ†“’Qö)ÝÔÞe_dÁ I|0ÿ½e£ü‚æ¦d3gñ·Õ,OÖù²É’Üèó_̼½Ù—»²¥5ÅÜ}µ5YSÇ’½V´6´'-x[mc Kû6K{£gc…|¦3*x_sµ¦Tå]î¾W66´µGy£ãG•–º%ÕcFËÆþÅ-®‹ñ3Ó/έ«kuoJͼ‘+|f¿RÇ7ªTó¢\Ì‹µ -¨7®onkoípkcå’äÒ†æ(çøð&Ê]Ò†±æì’ÍùûØZjŸT3´SfŽ¡=/ãSÛóå|jÈŠOõaä¦n‹kÉ¢ÝúåÒ±@vÍüL0{ñ|ª¬¿äSÛmâV\‹?$‹ŠïW:–¡,î̧¢ýùT+ð©V ä³=Êé¸ßjáÄd«bi²¡l!¡º²¬tìZxŸZ™{¿PÍæ¬bfh2ŸžCî·ÛY|.IÔßÃùÔ|ýýÖ5‹Å$Q'§ó©VüÆ60‹cÈ¢¾--Ç ÇíÛ|Ug“B“v*Ÿ3£¬Ols*©!˜%r:ŸGjïõþXœO õèÂÒq£‹£¬ºmn‹¤Ð¸oäsF”õîmþ‹)Rh¬ŸÅ§ÀÀ×·9>,¶’BË‘­¼×´™VÔ, Ÿçœ¤½ð |¶ƒÜôìWü()fGYwo³ÃW¼š«”šùi>gDÙ´½×`^”ûerV¶™°‹r¿FUüOÛŒÊoã¦ÅqÅýÞàŠ?%‰æáE÷oÓžœ*¼ü~§kZŸ³„w~÷~iÅB’¨mmómÆnl¦Î¸ßYqI4é/ßæ×K{óˆbî>µÕÇÞï.«xIÔ–on³gGÙOÙf !ÊýYéG0ŸÙf­ ʽ“êU¿mö¢Üg–QHüж…SªæN‹²>¾­ÐøÛŸµ­íñÈmCÏÜ6’ñû¶ x|Á¶u}fë¶)”ß¿®’UÛÏP…ãî_ŽÉ®÷{Õ9pëš–=½ÝØ´2ÄŸÙ†9’×m-É÷¶Ãždôý½¾¼†E¥Û²þñ¶jö)÷´­€4™{¿Ï¿£¶>MÎØ¨“gm‡äɸí >Yu¿eÈ[¶žäÎhïU".ßvÕˆÞµµOѺ­—•äK÷›]ݶõÎ#_ŽÇ"Y˜é½8E·õl%Ó;½·¯è[h…ç߈Kæm?é%ïÙ~Lþeû‘1i¹ÿ€¹öþ3i¡ýþ3lòÊí·Þ¤tû 99{û-:yåö£6 `ïù<êÞfjè[ É~Û Éßng&$7n§8$WlçJ$‹·“.’“¶s9â§l§†ÌydòòøkzßeâÞ'ÆÆ÷œüÿñ‹ù‹r!“–œuŽ(?®]¬Þ‡›à(æÊm (¡ªX2­Û[SÀCMv¨{¶U\rfò¢WþȇjéЦkºâüx뎭éô¡¹tÉG#%ǘvƒ3=$R…F]Éšx—\äO“¼ýÌÆXøU•/Œ+ß»K\r1†MòF$›œm©(WëIÉÚR.¹(¥&yš2ýœ¶7•¯ˆ+ß»ÿ\rý7Éû!nÑß êF¹Z©JþÐfuÉEª6Éû£‚7@|WÍîÉÐ#GlÝ×.±®&ñȶœ… %–ìãˆíƦLb •ÚÄb¿·8­jqY*Ô®}ØÂ&‹Ö$oR;(* ®(ùC¨Å%—X»I>…¤AR’Qr€’?„‡\r#MrInrv-Dº±ÉBZ.¹hò&ù´»Zv”+ð¦äa8—\z&y+"ŸÃœ€¾tÁ…"]ïÇ.½(ß&ý0”7FHÅEé èTú‡íòÛô(v’~#|´†F€–¡ÙgÔÞ$—œ…I>’Å0ÊyQ{EPYчݽ›äÒ¿0É÷Lì'Ù%„+ùöØMr›\Фû9%s&îìxâòœn’K«Í&½z¿x3qgÛÄ=èèܦ—|ˆM/m™ÑÒšÐj\¬º÷0á‹×nF|b´“)Wb-ÆÛŽ6±„lb©ÉvžE”X¤ÙÛ(6±xü6±¤"ö—‰µcFl;ÊØÄ¢û›Äûã>f§<®ÄZ#¶zlb©JØÄ¢ïï¤ü•øYJ¼÷xd#ÕjKý`ŒóˆnX¬‰~صI.e“| ‚cãí”ñzÄÖS—K,-“x,SÕ&]Ú¥šGü¶bét˜ÄmˆÛ´9¹}ÝÏCõfäö£œM-A;›Z ãÄÃ'õe.õÞ[ŸK-}2“zÀêgÎ'Ê®Øz@t‰5û&ñLÊÎE…€•.’«}^†Mri§ØäÍ:ËJ®['É÷6É%td’Ⱦ:Pz!̵®¨Ìõ>'¿&¹¶M.Á’ñå°KʶÏk’ËI>ƒüòcXò…hKÆ$>ˆ ’¸‹­ú°y\“\RM6¹”“‰ïÉóµŠöžª]b©0™Ä‡° &8S;LÙ nD÷Yu5É%Ûd’O“*],U?ä¯Ò$V‡LâC‘éšËÞ'ªyÄo+– ”I<Ü9)^ Éó•øA€M¬-kOb!Lv"ü¬"Ûç}Ö?MrÉM™ä“Y¢‡I5̉]EõZG#“ü0ÉG"çm® ËãëÂC&-MrM¥I>¿‡ËÛ‰¶¶ÚÚ’,\jA“úpDwVVDmCu?lRÒ$—`–M.“©mX€#~»þ¤`dOÚL7$¶@œy&6±Lö˜ÄÓQ¦™áœé$ â '}^ MrÔ)I>AÖ™’t¶6œaʇÝÚô:`˜ô3Ñ<:BJ=özÄ}áaO}&¹tšLò# j—&‹ë™pýc#©N“¾e:›Q5“ÆÀìe ¹Äru`Ïæ|:ÛÙÒ៎|¨ß³©¥ß4ǹ\Pj ËÜFkr©¥DeRÏá&8GÒ]¤ÆÛÛÈml)—Z·›ZjUsã“Sú©÷’°\jél™ÔsYûsU%¥–c4¥ÞËír©u*±©¥¬6[µI½—2æRK ˤžÇUa^|±QÕRVÕ½L4—Z¢_6µÎ§GÅ'c‰I½—ææRÛ›²RzFszv:Œ7•<ÌU6£Ÿ‡‘îÊÃ8ÈÃÈ”ça Xf8ó°4]B˜Ó}F{/cô"ã&#r–‡9ýåad|ó0Óš‡9åaÐ_Öµ'„5²!ŒühfØò0Æò0󚇱§‡Ñ¯ÍÈ:ça®yÛyÅÑ<¼M|€ǵGˆãp'Ĺ/‡8NBg!Ž“ƒÇeOˆC)qÔGC]Üç|â(x‡8ª¥!ŽuˆÿT àçŠâ¨Ð‡8J¤!ŽŠlˆãX!ÄQ–qLCwo!޶Gã<ÄÑ—q4€Cœ»Zˆ£€âœìB]­‡¹âèw…8*`!ÎÅ2ÄQ$ qtÍB½´Gc-ÄÑe q|ˆ£ÿâ(Ä…8ªr!Ž]ˆ£Uâhà…8ºy!Žú^ˆ£Øâ¨ü…8—¾GM0ÄQ qN!Žbdˆ£2âPRB½ÃGŸ1ÄQð q kˆÃÍ qÔ?Cœ;Hˆ£â¨Ôåñ«û÷ÍÕâ(äñíÒ”ÌãWÕG/‘Tøi™'¨tçalhäaiæaiæa£%Y¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤yØÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆB@âÒ€†8€3Äœ!à qÄ7CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä !Í〆84šÇ¯ZÐIh€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æa@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä !@qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀæq@CšÇ ÍãW-‹èéh€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æa@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä !@qhˆ@CJNˆHC@âÒ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CšÇ qh74_ÕÐåh€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æa@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä !@q㥤€†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä !Í〆84šÇ¯zIÔ ºbÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ< ÍÃÐ; >üÔ€úð91žW§Oh€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€æah€ú±;3 ùkh€æah€æa@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä ! qhˆ@CâЀ†84Ä !@qhˆ@CâЀ†84Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎ>+úÐä FF«¡ù(0)ZýBKF¿=Z ÓǾxºÏñ X韮ò/Îõ/ÎóÕþéÿb­œïøÀ:Ÿl½ †…xÿâBŸcƒº‘ÀÑ7þ‹Š&ð·X‡óÉžås\â³nö->Ç¥þÅe>ðlËz–¦bý§³ºßE õÿ˜½.Ôû™ð¼¬î»Éù\öêNŸô9Ðt(×û³èåû÷rtö).þÙ¼×÷ÝÙÝ?RàïwÏfÔÞÈS÷ÊbÀÞÿ¬Iy@(}ÏÞ?«ûƒÊ<áŽì÷e¯îrÌîþ¢ËÝ’ÝýCžÝý×.ДÝ}ÑWœ’Ýý)÷¢9»ûJ˜Ýý9x¯ ôËêþ{_Ço¸À ìîo¸Ààìît!ÙÝ7¸‚®ÌîþVü"îþ'šÝý_ýG\ v÷—­Ž«NöY¿ì^ Ë^íàï ²N;M ö¸¬ÓqsúwÑicm·½S-?å9ÙÝÿàÛðÛ>ðhÍ>íµqAñi¯ón,þ ›sP_¢«lä8OìãÊ„0œyÎ<ŒgF€3#À™‡àÌÃpæa8ó0œyÎ<ŒgF€3#À™‡àÌÃpæa8ó0œyÎ<ŒgF€3#À™‡àÌÃpæa8ó0œyÎ<ŒgF€3#À™‡àÌÃpæa8ó0œyØp†8œ!Žgˆ#Àâp†8œ!Žgˆ#Àâp†8œ!Žgˆ#Àâp†8œ!Žgˆ#Àâp†8œ!Žgˆ#Àâp†8œ!Žgˆ#Àâp†8œ!Žgˆ#Àâp†8œ!Ž`bˆ#Àâp†8BAο¹?Ž@gˆ#Ðât†8–BÁÎçNâv†8‚!Ž`gˆ#Øâv†8‚!Î8Äì q;Cœ{oˆ#Øâv†8‚!Ž`gˆ#Øâv†8‚!Ž`gˆ#Øâv†8‚!Î;Äì q;CÁÎG°3Äì q;ó¸ì q;Cü§ûãûçêóûãoëw죫ßÛW¼c?]ýÁþxǾºúÃýñÛúãûëê¿îw쳫/íwì·«/ëw컫/ïw컫?ÕïØWº?Þ±¯î߇W_Ùï˜÷«?×ïØŸW_ÕïØ§Wÿ}¼cŸ>Exÿæ¨P;!~õ†Pk'TãÚ Õ¸f¾‡ïâðýB\3]Ã? qÍt50Ä5ÓÕ8üÀ×LWãðC~Kˆk&«qøm!®™¬Æá †øO?íÔ÷èüôõOg.šþìvõû ì÷õÛ³N;Lßýiöi‡»ÀW³O{ŽL¶§W_ì“á^ümvæxuOöK¦Ý>ðÔ \¿Íz WľñX'nÚû´1öªû:ÛuÊíº×¦Ç]¸Í:ê˜vÔ·8ëhÚÈ´[i»Z›ÎÌ'\à²N=×¾–uê']àï²NÕÁ“§Y×_èkínÿ[£=´â×nZÕ8K4ÄY¢!.`UCÔ q–lˆ³dCœ%â,ÙgɆ8K6ÄY²!Î’ q–lˆCº q¥jœ¥âJÕ8K8ÄYÂ!Îq–pˆ³„CRnˆ¿m—¡ 6Hº/üÉÖ„_ 隈N}wÄô· ͰÏnË;¢u-ˆß°áZP³ÄBdâ,µg©…8K-ÄYj!ÎR q–ZˆëZPëZP³ôBœ¥â,½gé…8K/ÄYz!ÎÒ qeˆ³Cœ%â,Ág †8Ìôg)†8K1ÄYŠ!ÎR q–bˆëZPÃlq] ªq–h7 Íê|aumW-·v{ݽØR ¦íÓÇÂÒõØñá¥{‹-ÝWõ/Ýgé†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ýgé†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ýgé†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ýgé†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ý 7½éîÜ_ˆvrèâÆþíâl÷g»‡8Û=ÄÙî!Îvq¶{ˆ³ CœmX­¿ï‡!yÏ®ƒ—÷¾:‘£ÓíöÝÞüâ3†VèM× þn“~iH‹zï½yß½yÿð¡zópK>04Âð_Ø·iÐ’Ý·Èï1>=ÍÞÖ q@!ä q _ˆùBÈâ@¾ç âpBœƒMˆs° q6!þ¡§…°Œ^=ÞDÎê»`>܉;ž1”Át7ºÀC×ZìnÒG†4 ëìîÍÃøåÀæë[aa|th„ ø.jºsh„ÕõÝNüÊøØøø¸kè‡3ܯýЀODOuÈùú©!õ"Ä¡^„8H;ÄAÚ!Õ"ÄAÚ!õ!ÄAÎ!RñOFY®g·…7¿6dæùô(}û!(J àsFFj Ÿ<Œ€OFÀ'#à“‡ðÉÃøäa|ò0>yŸ<Œ€OFÀ'#à“‡ðÉÃøäa|ò0>yŸ<Œ€OFÀ'#à“‡ðÉÃøäa|ò0>yŸ<Œ€OFÀ'#à“‡ðÉÃøäa|ò0>yŸ<Œ€O6>!Ž€Oˆ#àâø„8>!Ž€Oˆ#àâø„8>!Ž€Oˆ#àâø„8>!Ž€Oˆ#àâø„8>!Ž€Oˆ#àâø„8>!Ž€Oˆ#àâø„8>!Ž€Oˆ#àâø„8>!Ž€Oˆ# âø„8>!Ž`Oˆ#Ðâ „8‚'!Ž Iˆ#`â–„8%!Ž Oˆ#Pâ’„8$!ŽIˆ#(∄8‚ª°gß’`³Œô>;ÁTŸ;`ô?Íí‡FÑi#ø¨I|ÈÒÉ É7Ĺ ‡8wìçŽâܱCœ;vˆ#!âܵCœ»vˆC2qHÆ!ã,Ĺƒ‡8Œ³‡qâ0ÎBÆYˆsGqîè!Ž„@ˆÃH qîì!#-Ä‘q$B GB Ä‘q$BÒtˆCšq$B 4¿ïØæââûÑ\`󸹆ø5v5~oÿÕ8ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒggäq³#Â{vHxÿÛ·÷ïŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3Bœ‘ÇÍÎïÙáý £·>Ö?óyÜÔàã`ݶ¶¿6vEü¥ Ö<Ì5s`ÍÃXó0Ö<Ì5s`ÍÃXó0Ö<Ì5s`ÍÃXó0Ö<Ì5s`ÍÃXó0Ö<Ì5s`ÍÃXó0Ö<Ì5s`ÍÃXó0Ö<Ì5s`ÍÃXó0Ö<Ì5s`ÍÃXó0Ö<Ì5›kˆs` q¬!Î5Ä9°†8ÖçÀâXCœkˆs` q¬!Î5Ä9°†8ÖçÀâXCœkˆs` q¬!Î5Ä9°†8ÖçÀâXCœkˆs` q¬!Î5Ä9°†8ÖçÀâXCœkˆsP q¨!p q¨!P q€bˆ C â¿ç`â¿è…8À.Äv! q€[ˆÔBœƒiˆÔBœƒiˆs0 q¦!ÎÁ4Ä9˜†8Óç`âLCœƒiˆs0 q¦!ÎÁ4Ä9˜†8Óç`šÇÍÁ4Ä9˜æq:Cü§bÀù'gpæagpæagpæagpæagpæagpæagpæagpæagpæagpæagpæagpæagpæagpæagpæagpæagpæa8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!@qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎp†8€3Äœ!à qgˆ8CÀâÎsdå]FLŒ§+Ú£èò;£èY´l1ìœÆJ—çý/å?ÒY*‘ÅÍyj„ÀiTÐÃ/ŠžÓܰ´9ÕšŒö¶`oïÓÛK’-©Öö(UÞ<\o‹ú¯·ßÖÛsÛNŒ,g‰ÿeÞ}Kïίi¯iŒªxK¾2ÿ[xûOz»»?—)µÉßl1r6XŒ^-FÏ|½«÷£èð‹§—O]ptÔÞjoTÞþƒÞž0gÆÜ¨hn½m´¼š±‰—Ï›7w^ôÜ)ö¶ÉÞþ½Þ.+›S1-jm²ö³þÞöôü¾‡Ôé{H?|雟G›ÛÖÞŸÿ'Pß7Hý³Gð‹ÊÎenéß›+¥må{FÝQyÊõø(›í/ÓÊ!GK¦O ÂúÑsÈ!ˆÓ¼xIguKMkMSõ²šæºÆdk¢¶¦±1Y—XÑо,ÑÑ|bsjEs¢¡.qp]ô”ò—¨þQþFi¡µ)ÿÖaÙ~jÿž[óh8kÿžu“ÊsáÉmŸÊñ·sÙþ(:ïÀ(¹GÖ1e§æ^\ÚÍ"6¿ìÔ¼aÄF›^vjtii÷°+‰Mã͆™Ñ°K‰WvjÎ׈·[\Ús:ïv;±´;7Aìzbw—š Çdboà{ßϧ–Ëù¾”<÷g±·òfÍÌ([ù¿H½·ónÅH:ºàÔa-Ý®âpÕÑÎ3Ù³HNfséíŠî—E•%½Íû™þ½ò·[þ©Ûó·Nœ^ù™t®êþAg×âœÎâÅ==]9Yërò§ø\ªqæªõ丆Å;‹™â­Ýû¿§æÊ•qÍ•Ë%`uåg²©+ÙPרü)êG{wÖw¬'š›¿àíjjH×nsýñ“¹¾ôd®?y2ן>™ëÏ~—kI”V½¥ëô¬³ºòø~kÖYU ›ÜuAäwÇøtͪ‡|í뢧ºYø•ÃãYØ•ÓÉumfUÞS,çÔtÿtgËû³Äú3K柚wP7‡¼víq\=ißUC1®¡x×¶obÎ+ሧ>õ[õYÍì›ú”ö¶Ö§â:«ñ†m}*vѧ–m}*ž`5¬ØÞ§vëSüÈLõôªp{\gá‡Ûê,\#|Ð9›Êý^Ë}뤿¹û5%‹éƒÙq£üŽ{NÙ©Y×ûwŸ°Šº£®ÚÛ†wEûïÊÙƒïè+äßDލqñ¦·ì§B¥ÛcoÈj²þd;eµiN;çÇå{þƽ§YÙ³#ßõò's½ìÉ\¯z2×s=°ÓßuÁ“uýÌ“¹Þó»\K`†÷Ù0“½óPŸÉÞ\õ™ìÍUŸÉÞ~õ­0“Ýø-Ñͽc,í³|÷÷”@÷P¼Y·„v–ë68íûGÜP ~‚Ê)ݺ©èט(ëvW&Ý,8Ѭ¬žQ9ª8ýjuƒ4w·ëÌfäwGıä0>F[l"m›ÄÇør©úFÙÜ-£¯…Ø×3±¸Ðb‡›Þ­ ±›CìöËkŠoÍÄ’(Ä|}Ä&‡X^k²(Ä6„Ø5!vCˆ}6ľ’‰rClDˆM ±E!¶&Än 1_ßb_ʼ+†úŠ#BlIˆmËä.žÞÝbw‡Ø½™XÉχr—J»|>Jí!öÍL¬<<ÄòÞ”'‡ØŠËç»ì{FìúË{V^bùü•ÃüUÂ|TÂüUÂüUÂüUN±M!–ÏM%Ìe%ìžJ˜¡JØ=•»2±†°{ÂL4„ÝÓf¢!잆0 a÷4„™h¸2Äò™h3ݘkûøpb-Óm¶ÑÏÇTÅÍ;ëæ*mÚhg `ûß6n°`úÅÒß67Ùô¾{„ÝÎ¥î2vmsª9UWO··Gòö Þê~¤öùæoù¤^3víüÚÖd²9Ñ”ªK&j@p›Þ’JÜU—Y¾¹ä;‚|âZŒ] ,ÚÜÞÚмtóA{mgK²¶¸OkÛI ÓöÊyå'ºÛö<ö–¨- t—±kuÛþÐêžkì¶½s7ì¹d™ ³-ô{Ì}[Xïjþ›{·Þý4¬…¹¥`>çíÑdÕÕ¾OÖ°®œH·ÿV×qu¹~Œ½ëǽîË.ÿC=3ouûè|«[Þ-Vë·êÓL¨‡ ÄâªÂü)%ßvßzfà¡\»ûZÏ¥Þ´Äs[öäÜroüÁÜžøç¹m}pn ‹­®“ÛB±ÍæÞž™·Ý3-®Æ×­Ö%ÿwnwÏÀC¹v÷õ¹MÅs›Tn›Ûdlɳï>­j÷ü)í^XíÊg=½å”e¥»r7b¿“uÖq×›|ʵ뇗 §Õ9`Žtö•¿"e>GÙ¾6ûŸs½¼ážÛ`÷Œ2Cóµ¸Yùw£;¢E{ïìªÍ.,ɉ꺺¢"ÕÝ¿g÷]ÑÖzé#µÆôñÿÔÊ ì]ï¢èkV»¿>º‹¢óÿØ+åÛòÀÌeo=æÈoóQI¼4·®ßíè•åïGøw»zï„ÂŒº ^Î]p“î‚ïVï‚Í ”ψÆdî‚5Àk΃G<^ÝPY+{îÎÀÀß¹øÛ nº f·Ä á–89ܧ†[âL»WÀ=ó7œ£ùÈo8Q¸‡Dþ¢[Vn2±¿{CÌ×$‡»PnAq¸ÃÄá‡{T|}&–„T²wˆå7¨$Üë’п¤+ÄüÍSýK>Þù»“ú—ÞÕ¿$ô¸nM…pÇ+„Z !–ßÜ áÆU÷ÕB¸qÃ}µn\E?OÄò^ýÜp“¼5¼ûTˆ}Îf]0+½IªÇÅp+.%B,Ü'—XnÝ€J¾ÇÊ]Zrä7½R˜§RØ¥pk-…ºËá–Xkµê~Tžeï¸Û¦}§;QÙßuu[+7Úmmá=·µò×´‹ÝmM7!s[#×"BpHßEÏqÕ~.ÇbË!uÆ=9¸YGh9ä¯ÿðö²ª2wÛÚ˜lLGeó,Çñ–CªµÓ¢§<År6˜¢·×rLÏä8Ára×r̈æT[ÏN´žI²»g†CjêpÜXS·ãÆš>9n¬é«ïñI„FR“®b‡·ÏhhmkOÌœþ¼iÓ©æÐnà\¾¥v÷uÿðöùÉÚTsݦ„i_O¶ú„ÌöÖ7-šV¹Àòbõéúö`}ùljõ‰­±·¾éÑÅc,±ÏöÖ7#JTú|ðÍ©OR Ö7#î3½\¸NùÄ4ìšéž§ÆÑ£?#,Fo[-Æ\´XŒ™ò;yô;Yö;=ÀN÷;©RõD¨ùðö¬Û²Z²n…Obxé‰ì½À]–tÄáíOß婾ø|YÂ;IL|§?ø¹ÚÎ~Umº€ý÷ÚÜlb>¦uèªsx{{²³é<¿ai4Ãê|Šõ]—¤¬N7äöuàZþºä8ooª©MµEcÆY O³$ݱ»òúžbu†¹—äÇsos>ÝrJ6ä‡9ñP@Ò#ß›—³5­ä•„Éy] ³)é“ÿ˜MìÛ ¦IªÞ>5U»¬-ÑÖ^ÓÚžh_Ù’l‹žr åÁ×Í@òHŠEûØÒ!$šj–&£Ù–³7Ï"‡ä[o¯¬i_Ö ‰ -UŸ¨wûÛ‘(LN=ÙÀÓKuŽò0%‘¨¨O¬LuÚšL,I¥Ú¹Ê´Õ‹ü`“NN´/ƒ±yYª£±.±"…Érîа¦°ÚµÍ®ÄeNL$+£Ùhõê’Q¾NÍz´ï5ûš…Sáe©›5˜¦Æ‹›š8·-iLÕfz§bjÒN 5M÷5i™š´“öÔdšéjrÚ,‰<Qµß\M—¼Ô×Ézµ;UÏéÇúJü{ü á½v°É}X¼7Ò‘ò;ŸGì íôž™²‰÷Œ”«oHì a‰j­aá‰~—dx„û™Í•öIàKaœj-ª|KøÒÏþ’¨Y¸©Ö_³bm<' #‡ðWm¿0,MëAƒü%ÌW­gõÊÆ†æºdk[Ô”Zn¹ðªÄ®n<¼}NGÓ&EUe©\<, "pnµ¦uÉšº¶hz±Ç)x[¢—ÂÌ¡›ÆåÀïxZø»6›Ú#ÏÝÃÜ@aýP‡6î–Tk[¢…ð–֌ˇG&ú£Bµ&ø¢§T-´3µÂͶ©P¢volk¬QFذzÛ’•.õè^ºÐêÀÏ3­ÛRVsžÞÏ >Ÿ˜Uݙ̾Ô]êRnÚdb>ºxⶨ{˜rdDW ÖøÁ ?·xƒÚ|ºÍ…;ƒC%J7µóàNú^áŠ|ºñu回Éç÷ Þ¢Ømº†|B ´b ™²9Åw¸B÷ÎÃÛÓ ¨vïñ!EÿuÛS§=¢dŸoRäÐÍ3Ë¡¾„ø•j"‡n¡&Ç%/¥JMÐÙö¿IÜsu=¼=Ãsí¡åó[,~”'Ÿn¨¾Çþ‘¡ŒÉo‚^ SÖW±ÚjÀ#s«ÛkýÞãÓîï:x¨G>ÝgÓ|]hÀÏXÛa~uÃö!¯n¹]yÍÖ÷9]Ðl9Å%07q ºrîÞð>ÿ–V_³ø &¿xéÅ#»o,Ù^À;G\…0*4`§#‚|âY˜‹ÏÎc¾Œ™M—±ýß#ñ7Ì-J¼Ÿ³¶õCZ—S¼ÃÏO„=¢E5af¥½¯$z oÅ39¼]wýCn;4ZÙìç]gƒ©ÄY1¹×§úMñ¦ ö‘—Ëaa™¿› }®7ƽwÃxx µ·<øé#‰ÃD;7¦*×å@‡ŒZÄé!G˜›ÉåÝ`dñÂÈ“A(›æp_3½ÀQâ’ jZ×Õ´Ö³|sG‹Ó±[l¹ðïŽ?‡ÙcËŠUÎö[ ðÖÑ@Ç›K¹z¨z¥ÉÌjÙ\DÉ~†åzÂìuñƒo×ÍÕ¤ˆZ:ì½ÜÀl ^÷cÑÖŒLLÓêY8ÝÏ´œR,&ž“ËÁiRã¶ã1Œ›¶¸TyžêÕtroÏýÞoë¿gŠ)jö¸x|â‚\ØÐ’°Ã–©i9j€fÚ¦-K2Ñ⺼x›G^qþlÞÍ ”ÂܹX°S;kjÆãðè+Ðô¸î0·<éšù—>¿­›ÓÚ©ñù,½‘àŒ½6Sy@4%›;Ø#çÛ{9Á0;Qšuâ=¬]ÊN\íq>ËØãÓõvA3­Íx~b^Ùlp@ÉÎ]²²C¾Ÿg¹Æ0{|šÃþk›R­+Ý!µšÍ@· ¿Wñn6†œâ…ù=~QÈ™\\4Ó1Z¦®ù­óæžÛ-/Ú¸#Hãðö¸FË%çJ·ƒÄ t¹¤Zhv”48„„.nŠÏmëfÚ{ü·1¿ôïô¹l"’1k8DYÙ–SŽ@Ìî:Èá™<ß±šR’šS…ïžÞ¸ŸŽ·p†ðo?aØAŒpÝ{¸é1Y1 ž½¬¡v™¤¬•„žd÷ðOÚÞ:@u¤½pŘ“ÇÔqÂB.¾â˜¡qÊgïâš>? m²g£k,—ŽD‡“K|åÚŒ¤y³þ8*=/iÿñ,Ç~lï¼<»:7¿nøkÌ@h+-ryð@7Ÿ<û?0CÜ;O¿a7€Ñ}µ“ZI;ÇÊåÄ{3µßæ™Ö‰þÉrý–Í”T¾3SÓï™)|Ý1S#;SÓã™*ZÞß¶™qßL¥<|â1SÃÿëLMß:S¿k35ìž™š¾e¦ð§ÇL ݼ}ùÒš4ÔtïñEKšÃµ9:óè²A¬yÿù–÷O kJ9.›rv`M?7ø-d¶¥íìo7îZâq´..—ô„ .Ù”ûÌE:»·ø4dþÄÙ<¼]õžÑRWÓžLTèŒr*Ò.Ï_Øý@düÀõ¸¨¡¶5S¬63`[VHï‰2.uel†PoóãÿÞxÄŽïp®;÷©ÄKã“A–UW[¼¿Ú¸¾büÅÒ»S¯«Òf¹/˜iyð–ÈmQŸÝ·Ž4£ÎtmírøI:P_ÌLc¤:æYBÑ¡Èp«Õ{Q·QF8‘\ÒáîÃöîf**ç¡K`rãgñä–†÷wrONÐ#%½«õKZ5¦mIËÜ$M.+ƒõlîmµ"nµéÑ”(ë«ù^jAÍÒ¯ÎÇ%ÉšF—YE•Ÿ¥¯Æ·©ûÐ ?¼ý˜d’[¢­Xw¶Íœ¬m­d6Uêê«óÖæšÚÖ†zn<›y¹©5U×QÛ°¤¡±¡}et¡Õõ5ê:˜º¤5žßÕ6BÐaÆ™:h+Õz€Geýåþ[rŸAniŠwäÖìê&f6Íͦ*vn;×O‘n7Ö´Ô.;±¨½³½h§mÉúŽFWë%É¥ZàæŒo+Õí.þ–ÕúõøV}j_‡·“UëhG[&ouª1ÕÚTÓ‚ž¢Í%e¯èKä’f¹n.k_êît[wUÓuü‚Š!3G-Óâ-‡Bµ“ö¶Èº‡µqÖpûªD%^¡‹žkÐ4ÏÂ&f˜FkB(ÌNɳ!\¼"& £ºæ)“iXGeŒuI¦ü¢ν¶¥=…œë›Zy©­jê,uíéÒq´=–®ºÙÒ^ÏxFŽÈÄ6>¿Ҝ˥Üï#'÷¼ bXÊ|WJ§íž0;à•û˜%Ý×Ö74'몗¬¬öy×FÜß].Í$¼²û˜Ñ½½!í‹h ù´?”o] @â0aOWØ´O°™juhg…îc‡Y,¤kø¦F¦i©vò%+}½Ú™`µûØ¡iÿëé|>ícS—ö³îÀ.‰Ùó—¬ìí£°B4<Â}tÉ\ßÒ{¿Å}ºÈS‘ïfrÊ«ÄÌ ÇxŒh`“W§ìVm4ƒt?½ìt8»rK½‰Óü= sð(îƒ ÿ-}Œ®Å5¾lAþÄÕ½¬'á)µÏÞ±%sírP¨0Ü}àIWÇ Ï››(‹Ávtbr¥åA_\™ûÀ§>­»¤þárËa< (‡ð­¸ ¦¥ËpïïûÀÊ€¿ÉvQa.å˜îr Ô*îÂ}àïÃÛ›;¡ÉM··ø ¿0}žßH-¼ ŸÒ½¸»Àáíž.¼°ÃtcHùdµm$³žfº|øÐ}ý>îïd“ÂSNÿ÷£îr£*%Ç}ÜRܬT—f:/x  ŸºÕho;jüà ãS@|šû¸i¦Ö×5ÄÔƒÓ·÷º%™÷º-‰¿.,ó~™ñ ò*ÀѽêðöY)TxþҩƳ+p3ùu#sõAMMÁ½×mͼ׭ÍÕgÞ/8ÚÞëfgêÓ ÏÖgž¯(7nh› É¯¡æîä2‡^/‰^büª÷E3+º7º¨ÍÊI–G·KøS÷qËÌúhX¨ém¶ÀÍÔàÝPk·‹Ü6øîû]¡[¬–òýws›=¼ý¹Ñ˯·:tÛ…x·^?û>wà¦uë– ë>n˶7Ž}¢Q>?Ö¶ytŸ68M÷jõÇ<&Ç&ÎöÚ@•6wšSwp¼GÜÇ]\Ú[NBãðouw7QwøÐ'[vÇNÒ-þí}ÜöÙçu,]JºŽAr¹Ä€›qüÚ­ñy³Qò9Ýà{±;[ux\^ñ LÅ‹@pu1‡ ¿=6¯lkO6ås‰ca°Š8>—nqæP$fLÖ q:Ì-AZÿl6{|v¹Ä ¿q\‘Z.`PÞfŸOܳ¯ÄE©å[ßÜÐÞš©K¼´gîƒç¢[æft'²ð ÁNGþ”õê{ôgÅ9¼¾åϪ&{~8K<óÞTN÷M9fJ!?‹Yç;öšsìLñ‘|.ú‘MŒÍ—֎朸C÷ÁyªçsS“­HŸWœ+n»÷ÁÁªçµ=ìè švÌ»¸^‡·ýÜ% ŽŽµTGãK¬óyÐÙc·‰CÆíì9KRâü¥$(añ¬â¤E§“K5ñß6q4»œc®nEæ ©-\PÍQIUo©9‘Ëìq)Lˆ×Iû, 6$Íó“ºûò!g¡fÛ¥pÊhç^¼Ü®®3ôßsÿ âýpß.ïá¦`ÚBŸ >˹ä—ï‰ú+ð¹ÿ‹8+®e¥­4oªËºÆ úºñÀAÄ/Lµ?¼†í‘î¶.—¸‰Ñ_“K\EÝ—÷ÌÖÅœN5[ç%9ŸÆ9ŠÙµ1éOÒÕ§³â¥¬ûsuè<·îy:c¬}^[2yâó’íµ#í*#Ó&qK{œO´“mO”ssª¶AG[êóÇ]/ìÐg7hzŸU<²¸¸Ø2%jõ½hv¾ø™Úù + cÇÏX”˜oZuÑ~ä>-^hýÎ}±¿·©†\ žÓY†$»N\Tÿ\8Û3 trw삤ZÁ6â¾ÖðGžÍ÷ÍiEߟýõíÚ:&Y\­ÌÊÏ7ZÑìqt…Å­ªS5‘MnnÝîD¾Þ©0™»´æîÙ5°I·¬HI´Ú^ð5ök¸f¬çŽÞ6®õnìš—›V]AšÓìq‡mïÓ=¤+ê&¤Ïk4M”‚ô¹™ˆ¯lö¤2dÖå@;“»—øÏù.5j$k·hj‚ÙÅ¥îÈa.€ýÛà#q³=nÉÖ{ÊFo‹Ž´|by˜Û¢øÞ¦——p§ß¢ëÒ:6Åj€½Ë#¾¸¹1ˆ?t$ƒžÃT[pq#$Љ‡ÇZÚøçS¹s–÷-ížÛóÑXKûooZ¢úÙèf_ŠÈÕd»´|5À«¸`]%}mýÇOÕuNÖ§5RWE•>6‡ëØ®(Ò‚Y"=ÖmY¿–Žn;•mÔ1;}QKeöâèª $}EMTêHcyã­ŽEÝôã=íªCÞ|.z2ç3Qî¸^oCUèŸÁGÆ#=Y¨ZÚ¹d´sÁUOš\O¤,ÓÙj{%ùC=s¹xNàòcêÑqFõ,võèÂòd=êGÙô½ÚWNÛÐ+ô…'p=2µá DºÕißu Wmýl~š6Õ¦Þ4ŸÉ†ßF_^yµi~™‰¼3õ¾…o½5qÍú6î Ûr£Üµ59-k³rÚ‰7o&~9ñ­Ý\Íô½©›~™÷껾/§gó{Öf=;>ݳ/æ´¤ûóœh$ڼɽ^(Ô£ A¼;®ÞUãêaˆ?º;Nر;Z·ìŽÙ\@&pA5󨣷jYòÇݱ»z£‹«©GJNªçÄ?îõcÄë¹þo£»cŽö’®µ¦6©H©¶“þ¸;Ô›Ño 7ÛèKº;3»Âïêf‡øwµ²ŠÝ°&ìuÄ7ØYÕÍ™÷ªQßëzwHÞ»6ëÝÒ°CV¥û´éïõ®W«ñZ/—Ñ£¡—g?§?ÇTÞÌ 9Ú‰Ï#ÞB¼•ø|⋈ >šøâKûk˜À›ÉÝÌš¾Ç œßõÔõkø¿3ë©-‰²ŽåûV¾Ïàû{w³}ßÄ»§ð½‹ï§ó}c 5èûâçò}½åÙIüd¾¯ëì·†<ª»ßU|«Ïý®Ä;Ï5½ó˜ï½ Ý5O½²›^lý :àÌÐUôCê,í7eô×Ûkr ]i†kç¡iO×ûüwìYÕ¼t°æñVç-~°·Úa…¤³J]Ì‘fáù·dNÜ%J¼ž+v;ŠTÖ¶ˆÜw‘÷¦®œì"v¢úM~ýþQ‰Õ¼+]³˜ í°UŽÂ Âìç;áš´öW|™}§Ö¥éZWg•ÔfG]‹ïnY[M¦f_ï=öõΩwÔ<ᑚç‘ë†5Ì_wo¯èíìÒh—þ'÷ÖÈ›ª_íætgS·f޳"oØäIßËJîÝ®¾vÌÖÅNúL´xÒYM“PnãÍ•Ýß)œ”Ìê˜TžõöIgŒ9ðLü^Ö_MülÖ'^uÁÄ—g½b2ëcì$íÕ~—SûíÌÎNí”ÄÚ™q½“·†b{ß®Ê0ÕxåÜú™–"‡­¤èäöTêà0²æpíÝöÒÇvR^›©IªS½;©µ¿9'Du¯‡mÖŽâYý>²ÿI Ë×ãî#f6 þ“ÒRõ>¢ú^qU~P›”¸:jÛ‹ÿ\m[ûkKßïž)‚õbjWˆþZê3Õ®~k?ÙE]R&{lÿºú6ý·ú¤”öýú¶ü·ú¤Üöýú.bÖ¤Wc=ï¨eÛ;A*u;!v;Aj‰=;áš'j“’^Gmŵíè«MoªXCêš)QÌíét—·£˜ã”÷ÊçMgŒÕ¥x¥%Êšß~ÎYüÿ‡ÿÏùB˜;ÿOåÿóøc4rÒ'ùþ<ß÷3ŸŽrÃß“àXRÖýë5%5Ù·{î8÷©½7Ð:vž¬\i)°9vm‰öæ=’Éðs±?_Å—+Ã_6¾3|é=$sm¸s€md†© Ûì¨yêú’Ú(ël¾53;ˆ ¶ÚAìZ½SìZb;‰5ÛIìz{w½p¥‹Ý@ìF‹ÝHl—Åv»‰XBì&b7k!v3±[,Ç-ÄnµØ­Än#¦;H¿ GjÆŠeÝwtšoŸ6ï(-1gëö6 J(ÇÖÚ¨h$;H‚«Wåíw÷¦žÏþ±›áò¨¶û¯ò7–—–1ªA8ÕÔ2·üÈ÷öØ7ÐÜ󢑸ÊhïzÇW ݽ†ÛI!Þõ âbt¥ñÏ—Bhÿ6q©Šúxž»9äm9›C¾fúÓ¢<Š-Q¾gÃzb>¾Öþ]ÃÝlÝģƉӢ–‰µQûÄӢΉçE]Ü4·qÝÁ=øšI0Ô þnû»B|*-uw/ßáù4¦ý›Æ´oÓ˜xciL,¹4&uÞ4Æ­ÍǸÕúwZËênVݯÐ1«¹9ÔÜjn57«f“7«×ܵÓXVo3÷æu}÷½çD]ýñ ½qípÀdðÀdpÁdðÁdpÂdðÂdpÃä‰óø?ÿ-ÑHvÊäë=&¸ï’Þ½*Ñ’Ùeß¾²; L€µk°”wuçüÕpOˆÁÕÛô+ÎËîêÃ\Yþ™–ÿ·¿POûiىףäÈŒ°—Ìœd1îÉûzõ;[ïq¶Wf¶Ÿ›}VÉi=w²Ç»ž’sáéñ}´xVLQŠr§F=·y_Nªéø/O;k²Ï ï—¾ßÞŸ6øþ¦ð~íàû›ÃûóßßÞŸ>øþÖðþ‚Á÷·…÷ëß¿7¼_>øþöð~ýà{ƒ[Üûg¾¿3¼_1øþ®ðþÂÁ÷Ÿ ï7 ¾¿;¼ÿÕÁ÷Ÿ ï{ðýgÃûß|G² Og{¨ÍöÐïg¸É9ét‘ý{¼võÜJÛe¢£óNªúfôíds'Íï¿p%Þ’uûëa*›Ý©ž¤{ÔÆZ&fe¯V%לiYwºïÕYw•Ôt;ï)êÓcwjp-^„æp£ÑûÝ-ÉßyOP¿¾¦{‡ÞÝ26¾ż“ _S|OÍçælêCơӣZÔ‡ùÊú³»ÂpêÁß–Àöî¼^ÑvRá`}öÜGFXÿëëƒÞ0KÏ¿é¤Âî×eÝ•ákÄwöݦ¥,°ÎÈ6®å‚ËŠé™[åväœÓ²®ìíûú‡f Å|V¤gQ·<3‹Rþþ\|PsqÅÑ̦ú•ÎÅræB,Üž}ݳY™ºyö?änIR»¨ÎÝLfNÑÿ7wℤswǽs§ÙðsÇM…7=õ¶Y½ööŽþ{UïÞ~ð.º-kìý¼®ÙŸÉºÊq¥ØËªßÜVÂ|gœ£vH¡ûp€å ͺ‡/Ñþ8ëjǙʹRæ~ccK6ïÔñ¶Ž|€—VÈúÚ`››ÚÔÝý“êðf‘[@õ­;Šj›ûÛÞÍ90ëº7 °mêS?ÒÞÙX­wÂjس¦wºÍ¨¾öz·0ëú7Ø=‡»ÎîÞ óM@ÙcwïŒÿ¤xòC½[uÓto¦>õ#íÕz~”Jˆé~¯¶eMx wÛ³nyŒgS›ú±»wì5qÚv÷N7)ÕvÔC½{KÖ­o@1ÄÔ§~¤½³±ZﺸŒs|}pã:.cÎû ½ ÜÕjï,õè‡z÷ÇY·9î*õ©iïl¬Ú»¼ÖñVß÷÷î59Y׸º´v§3¹äæ`7£«³«Öfe/"Þ@¼™ø9ÄWo!ÞJ| ñuÄGM|ñMÄÛˆ'¾…øåÄ'ŸL|+ñmÄÄ5JNïæ¾ ï1oMu®brBÌUT ú^#ÌcêÅÙž¦Ní2}oéfϘ: ç1éŠy³I÷Ž{Æg.Zñÿ»g\Z''ûò7àôÁp:kwø6µlàÉ&cÙ£í®m‡2)Ípm“éÄ—d¸¶É,âËlÏ´ýÝn{~ží÷ù¶ÏÙ>_bû|éŽ}ý{a_§^P¸¯»îê_|`wþqöâ×£2Ñ»ó«8Îîû?zˆÃjwþí|ƒß쎿Õk¬aE[ã?À%µó¾Îqr¹|i&ŒòûqÆ7  cpÃjn`½ó¥ÒÈqC»)Ô›ÝHÆÛ]äOú¹t-ýØa“n"Þ>þôÁÛGÒ®ÛÇ£5üÙ†>Ôjh?/»ó Ær\ Î}ØÊžöáhâmaŠžŒûp2ñ©¶[mް½8Úöa›íÃñ¶ÁÊ|OÞ±¿¬^š;ä³á}gîÆà¡iû8âªýÏØoÉŽÜŽ{äŽøÞ“\a×êUfߊÿaö¬ê°ûÕÞЩÃâMnZ|s«Ûw?ÿjfÏÆ·ýî~>ûÓY·oæÊ·Ùî;¬D5I)®—ïîN{¶?»ðë'îß[¯:/{­Ã1Ú+¯–OÞ‹TËõOÖò©}¹¡¿–}º/wÿÛå-ÙÝàŽßpó,ngî¸æÜñ›ÔðÇÙk6⎮~ëþ^“}Ɔ[l|=»ìžÌ-6Æo´0` ®o †‘‹r¸xíÀ/Å·UåŸÉ}—Ù¯$iߤ1&F=Eöo–ÏÆl>ËfxßþüLØŸŸëߟhÊtÞCÙ+OâÔlé&{J|Çô7Y»›Žy莹:{äëQRëÕùÐ4)©}꾩íóüLm…[7ß{§nº÷>Tk\Rû™ÊÁZÓàÞ>nÏ.y=J¨âø»¸…¾%»òõp&­áÓ~ÍF)NTÇ.<}“Çvá¯íØÉ+Þ@Í=ÚE#¬†¯JoØ[Õ[‡î {8gY-5Lkëúõ‡pòG³Ox܃žš|ÿîþ9ÑMàÆ7€S½£ýýýs¢[Å®7à̧:'Y #¬†Úœè FùÓ:¸‰äú jºuÞÁÑÕºö„»QÌ|÷ýÀOÊcU\ÙÍcù‡nˆœ}¾82íQîWß™“}‘øq.f¸Åú6b}ßÖ¸ŒtK¸?ÜJü¶Ìý!¾”øí™ûCŒ¾S|%ñ6âã‰ßEüSÄ'ŸL\~Y…{Šâ¹ˆgbî ñEv§¸%æ­Ä—ļÕi±Ú{ »ÝóX,—Òñu?s_Wõ›»†v¸½s|*¾o3þKüµ÷Ã? ¸ìæßßãG”ì¿sBž,߇ŽaÕ“¥z,­ÃÏD…òd‰.ìJ³&/–âD9ÿ‰øþñ>oñyÖj1uÄ{6.°±R_–Æçš‹áÍù²,ȃ¢÷e‰7ïËÍ_ïËÏsΣñqé<9äMÑù©,È«á2« ‡Î?p–GæÉÑä¸ÁjÒDFµ˜&3º´¼á³^äœ7É‚<"Þêv>"M_²ÜR˜ˆÍ§$µÆÖcòÅæ’|òâ`ói£Æ•!ߦÏy¥4ùvZ>ù‹/¶˜¼„ÅækÒäþTÈý럜<*Û|š-’éöN(&Yl1¡„Ä|Dð¶Tõ¥¼ÃæI>™ónYÀk“<*§^;ï¹o˜7[>ùwò^2 øJ. ïœJóî®Ð›ÏXMBÉmÓÅ4¹=3—‰ù@f.ås&í}aX¦Ž‚ß1ºbÌ2³"OšY>ßoò¹ùã[Áï ò¹™3ù|/Éçf¿nòª™ÎeÁœ™§ª÷fç”òØl{ ÿqVãÍ 4óÔh~BéGcØ…~ ¡6ú9ú\£ÍwYoô8@{®ÑÏ(u8Ÿª¦¿#uåk ;²Ñï!ù,k´þQG“ß=ª£É¼¬RG“Ç…ò×䱋<Å5ÍÌ`‚&ßKa‚&ó8mêp¾¯Mòª`rËc\Ó9“‡¸¦u™mò;žÜ9.iò¸D^âšl_⮟Ç|ÊÝÏÏŸr÷ ˜¯ŸÇ|ò×ÏfpýÌ/ªÉíq*¹w„Ü×[>]¾ú]b1]lûy̪KO¿K-Ÿ|®õóóGÎO«©ãË'µ¯~¾º 5~*࣭ÙcDÍb³Ÿ?ÕÑl^b©£Ùï±HšYLjhÍÖ׾ݚ}_©ÃcYêð¸J;¯Ù“ï¸þa—÷÷;@Þåú7föD9´;ûû9SMýÃëf¨ð$Ûßð(ûx€ßòQ7ÀæÒ¼Ëý½°Ûï,8Ðî%&æn$&æw¶Ôïú!¥½~çIÕo Ç(RXg1)ô;[Jˆ»,&ÿo=¦”ââ@Û%¦ÖÛCÌãly}kñw©>¶xü§K}‹õ ¯m-¿êÚÔâo3ºFµøÝ e¤ï‘V~ÕZ|Ϥ"Ùâï ò˜ÖÒ˜é_K§Åä­ÅcùBkñ7ù?kñ˜XZÝ-~Jß»Ån3ø6k¹Æbbz¶×¶×¶Üpp‹ÇÁÂÓƒ<žäq›öÊ ?gÒ4äû$ ôA# W 2lÁl ²»ˆÉí{&}õA‰™0ÈzVÀÝÁ ¿³µ;YŸL_·|RTìgTÚóƒCo{¼+¥ðÁ£K°¿¨7ƒm.©i°ÝÉð¢:ØïrùP<öøƒwnç™wð.÷&<Øã$Þ¹mÞùþéÝàçwˆ¿+ð.÷Û;Äï?ÞåþÕ‡ø]»Üoïíx—÷oHèßп!¡CBÿ†„þ ýú×ú×ú×ú×ú×ú×ú×ú×ú×ú×êq¶æ»Õï?ùh]o1ù:hõ÷ÝiZƒÇáV¿óÈíû'ÏC=Îo…¡æ™ :4ÜV‡ú]. Cý.—W‡¡Ö?“c]ˆù½(ïCÍ‹1˜l¨yÚ§CýŽ&zy“ 5Éì§¡þv%¯Cým€:üMEL‰a§êݰ°ÿ†ù;“êæ1+±ù™Z‡™·|îÃz9ÂÏ“z?Âï õ~„¿Ÿ)÷ÏŽ¾7bAŽð;@;i„ívÒßrû{¶üwŒð÷3ùôqu¦g#ünPÏF\zãïòÿ1Â÷šüœÉGÈH7’ÿ‘þƦ=72ÜØFzl-/##ý=^uŒôØT~HFz -¦×È32½é÷™z3Òpª©i—å“bÕH¿3¨Éí |ô{BÌþ‘~OÓ·ç¨c”ÇyR öÜ(ßW©’òý“ç•Qá6*ÜÃF…=ÊÏ«˜d£Âml”Ÿ]±ÃFùþÉmÂ(_Õ›Q†™L¾—ò3*ÜÉFù¾ÊGÌ~¾ò³_n¦7ûùý§Þìn!ûùƒ<Ììç÷jÚÏc)yŸÙÏ÷O>iö ÷³ýb?ßKy­Ù/àý|_åÑf?ß?ù¹Ùo}èÇRô&çUìçq¡”Ñöó·(jò·yÌíû'6Óh¿ËÕ›ÑÆe¡ŽÑ¾—b^ö·+Õ1Ú÷U~yFûþÉ_Ïh_WoFûÛ•z3Úv’©ÉsDÄ@íï%ºŽ·‡ý=¾”çŸý}>±÷÷¸A{zÿs2{zS$·¿¯ˆ)·¿ï·| íožµéñ˜ÜL?Ɔà¾2ÆÏî+c<1á>:Æß*ä¡hŒÇÇò[4&àž1vë2õ¹Ýlêó8ƒúr>Á›ówŒŸuùGão{ôÌÝ]LM9ãoÕr’0ÖúŠ/¬±~o©c ÷“{l¸Uõ¼%±âÆzÜ,õ™±~“ÛÝZLõ˜CþžÆzÌ!_Pc=Î#wŽ3Æ,5Öß–¤Z5Öß–äGj¬¿‡é.;6ܖƆÛÒX©6­åEµÍn–øŽjó/yŠj ýnóý–G¨6ßoùãh›e1aжÀsj 7ƒ63 n?»Ô}½“?¨6?ÇRœoó»M7×¶°ÛÆù{¤|=+µÝ ÿã<'L»mœÍ»m\À=ãl/âãiœç7ˆÁ8ÎïEÍÜ8à ôlœçÛó™ô1Îð¨Éí|³cÆŸ°ù0¹wf°Â¾Â„{äÁSü·àû'&ëþªšôüù:ÐïÕt`¸x'z>Ÿù*}ÊçìPKÄW>4ð>õœcù™:ÔÏØêw¡hχ>è¡á6v¨ß…Ôáo R:tMfþ 7¿C?4`ñCýî—bü¡á–y¨ÇßäÎwÿ¡a÷êw¿üMMôœQåžöýİï'ú[ póDãâàyj¢ßÙò85Ñã'I©OôûOÞ¥&ú9–O©‰ž³+þÁD?¯ÚCýΖo¨‰÷<Ñsk¤*6ñÎÐ'ÏwÔ~šdû›}6Éz~šäo±ÂO“ìNorø‰ê›dØOQ“|ÿ¤Ú4És¶´w'…ù›æo’Ÿ?yyšäq­T‚'\>ÉæÌäÎù¯“ý~Uo&‡Ûüd×¥Â<ÙnxkšìoªirØ£“Ãa²ÇŽò¯4Ùp*•&{œ°àä€?&ü1ÙãùRšìoTäsûÒäó;Rùó{QR ‡í™ËÃü=Uûã°p<,Üòó÷a—Ã<T·ÿÃ<7B8ã°pO=ÌïI7æo!²3r˜ßñš‰Ã õ°ÀG<Ìc)yN’÷ª´¯SÂ=xŠßyÊ7Åö¾“¦Ø-¾N wî)a—O »|ŠÇ²êë3P_§Ø½“¾N 37Å÷Rþ•¦ØÝ×Äÿ €ÁÏ9†˜vÉ¿KðìîgxW:<ÜH÷7<û 1Ë×n8<ÜH¸öðp:<ÜÒða—ÆÜî71K˶¿¥iÇO {wjÐN˜juà‹ij¸'M wâ©áN<õÒò槇 ÔZj–r~"*îŒÖÂ+»+º*ûÅYe”]ŸÕžÕžÝœuMÖ5Ù˳[ø»"'7'7û9‹sg¿6ç’œK²ß”»sîÎÙïÈýhîG³/Ì¿<ÿòì””dÿuÁÅg_1lø°áÙŸ{JåS*³¿ô”KžrIöµ;í¼ÓÎÙ7î´h§EÙÿ´Ó¥;]šý£§îþÔݳñÔΧvfßýÔ+ŸzeNþΉ9Oß¹k箜ݞÖò´3röÝuÝ®ërÙõ¶]oË)zƬgÌÊ_xMá59SžUò¬’œÏZÿ¬›ræì6v·ºœãv;{·³s^üìYÏîÊ©öåϾ>§y÷á»ÏY¾ûšÝ×䜲ûõ»_ŸóŠ=J÷(ÍyíçìqNΛö¸k»rÞ±ç¢=å\¸ç¥{^šó½ ÷*Ìùë½Ú÷jϹb¯köº&çs{ï]œó¥½ÏØûŒœk÷Y·Ïºœ÷¶ï°œÚwÙ¾Ër~´ï×öýZÎ/öÛ}¿ÝsîÞï„ýNÈÍßïœýÎÉ}ú~·íw[în‰ÆDcî¾ûWî_™{Èþçï~nÑþwíWîøN8à„Ü)¬;`]8(wùÁË^–{ÊÁ|qî+‰‰r_{HÕ!U¹o:ä¢C.Ê}Ç!wrWî…‡^uèU¹±÷ˆ½sÿzD݈ºÜ+F\2â’ÜϸkÄ]¹_:lÑa‹r¯=ìœÃÎɽñ°›»)÷Ÿ?èðƒrôœaÏ–û‹çœóœsrï~ÎϹ3/dÝȺ¼§¼häEy»üáÈæíûÜâççòÜeÏ]–WôÜkž{MÞø¢Â¢Â¼)E‹ŠåÍ(Z[´6oNÑEwæ÷¼ªçU彸x]ñº<ô5^ÒÉY^ýy|ã/|û÷¸÷ã—~|³Ö·ßûíóöðíëÂyà¾ïÎ>àp_¼·o¾Ï>nù6/úÆ ߸ä—õùòßýùAß}|½?èwg¿üwo~ÐoÿÝ™ÿ±y|lôö³ó»3ç·ï›ÿîœGS§´x.“­ÆÚÉ Bì¼{fˆ]bÏ ±«Cì%!öÊ{]ˆýtˆ½3Ä~>ÄÞb¿bŸ±ß ±ß±? ±¿±¯…Ø?fb…ìk ±Á!6*ı‰!6=Äæ„ر!vbˆbùüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÂüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃüÃü•Âü•Âü•Âü•Âü•Âü•Âü•Âü•Âü•Âü•Âü•Âü•Âü•Âü•^RÞ¼³üÓIÓGqîNdø©†‘ê;ÖÆ6Ü”¢aæ»Nz>EnXýàŠÝÉw݇kz~û®»ÿ’Ó`\n[•ñ¤X¦weÆ_—b™§¡+£ŒÆò•A{îÊh÷ícsažÏE Hñ/­zç7 »»‚ŽÚÖè K}%)&ï;.¿T4ÎÂëÌèÅÑ"¼ñD«ÞùÕ 9Ö„|ëBlCˆeþß¶Fí!vyˆm ±Ôã†b©÷!ÅR¿Æ›‘<µÎû¯¹¿¯Fx7jQŸ¬ïšûwï^•©ëÊìLϯÌÎôüʬÛC,õs¤Xæãʬ;C,ó#reÖU!ö©ûLˆ}6Ä2ÍÑ+³n ±Ô#’b_±¯„X¦÷{eÖ5¡—ÙÌ^™=3Äæ…Xª½§Xª ©Xæ«íÊìÌ,_™™å+³3³|evf–¯ÌÎÌò•Ù™Y¾2è@^™öZvYvYöW®~evØeIz—)¶3Ä®±B,Û!WfgvÈ•ÁsȕٿLWf§wbSC,óseöºË4ÿ¯Ì>?Ä2É+³ÓZ•Šb™¿‡+³O±EéX-*Ù?ª”¶áÀ UmCÒb·d¨´ 1úZ7̵þ<DbÒ3´1éƒI·0‹y­ bž[D>Ãççó\Nbž›@Ìs[ˆù{;1Ïm!æy Ä<—˜ç#P·ç¦ñÎs´Kõ ‰yž 1ßWåŽC_ãÐWyÎbžFÌó¯‰åý‹Cÿbß?êËû{Ž9ï<ïžXÞ×8ôUz†Ù;ßW½KB_ßWÞåóšø¾ò.ïkæ5 óš„y•FbËç5ñÚVÄýÅØˆçå%㱋myó$•÷Ç)Ý=ãÇWZ^Ÿþâè¢â"ÜàÎŒn¾è.{/-¾è¹¼—†™j¹´æÆ·êÂãæ;çÖò©iL]/JÖ&©ðicG&FËsjd7]"ô" !òé/ê&rÝÍ=wùé´öÍ]d¾»‹Xo^;K˜€vªF#6óî#ÙØÎ7ä¹ ­ä]Q¹5*舽˜é­r¶£Ð³/g½^a²»Àdw“m§WÛéU—á”Yº«VsV¾³7¶W/ÃgêÚÖ^ÍY3;ž,]Bá2ËenÇÇ1sa÷œXéz=Y3Þ ÊŒúý/ Ès‰¥3(¼–Õäw>9üÞ#‡ã…šׇºýÞ£îmÿH¯°sÿD·(£Û?̲ŸkéF²Ò£Yÿ½ËÐüÃŒàk”_C´_Q²¹ ¯¢+åÿ¿Ø›SÉêdgC[»Iôú½%ÍÂè0v´ÿ>÷\¡Z»¬Æ!÷6°9¸MÞx}?¤s£]8~ØçžÛ»g®;·çö3W÷àõÀÝá¬kï›Ì¨ÉóÑ·ºÙÆì§{œÝ1œ&²ÙC×dnx&ï6细:>«üø4qùÓû‚v›×5NoÜ×¶ÍZØ=|âªïâ·QôÙ]OÌýaB×eY}é­!ÿÝÛ«°ÿLn|êÆçòg·+[×î¾Ó×p£ðûp;3µ™ªîEM¡ÒnˆžÊ^¼¨¦¡ÙÏwÊ瓾²Ý9šS¯¯\@Û2ÝÒ›Lw ïÜރç;…yÉ‹«çóqiOú›…É—kh¿ÙH?RÚÉö¹=®c—åšdémB–‘×’Á7°çMjWÅž7,¾¯¿SÛë(›Ø|Û«Ò°ìÜ«ñ·Wµ»Ò=&ÍÊ-ähÂ|½L{Ìí­;„QvÊÈ âý£¹\Â\Î×\VçЖ89Ê+Òú;ýöwêa½‘.æî¯úÓÞп£…ã…ìhéy~c‚6gkßÚ¥~Z}cÍR¬Í>Í…/©53ÿ›_´ÓN‰Äs›~Õá|«cÊ–DçÛ;â$ÚÜ’¬m¨—±ßz¶gõ—õ¬Ž|Õov^t'´ØÐ²;ªì‡-K6¶„ìΉ¹¼ Ëõ¯y‹UaA•-;í4༾k»rNL%úg¡uWcÚjZ—vÈ®ûæ‘x76î›üPÈͰkÏ0Å+ãÓ׺t¦‚);Ýì&àü¶À“ÿÆ„¾=€ŸÕÑÚ>¯ ì‚©Ñp =@õR m§‚M½’æ[˜5Ã…~Gè–°{G¨7鎠W~GèaüFkwþ}×óð[~x–á/iõï¥ jÿû.oŠy®êYØÊñfçÿRì~_ÒÖžJÕE'sµù…¢éä׌þ}×|Ìþ¯v&€/®¯ïݲý¿¶¶†%óÀ¾5%žŸ¢ÀÔW´ôQ£QÔ¥ð÷]UøPV>4¾cüYÆ™©ÿKÚT-,ô.zÏ/–ÙîÒlc¬ößwiw}hÿž+m­žËEèjî>Û¹¥lGùb;Œšíì5ãGX{m»þ«ËòÃÉ·70°pûâ ï!xLPžØùLZñï_Ɇ2ùQý°ùñšò r¯XgËëY^g{_™¬Vçû*Ôˆ× m?źrñʫݙ¾•*eÀ糜ÿzà> LþÉMÞæà‰`GÀ9(ÞÉÏá{K¸^qÔ» »ƒJîÆ_¸_ïTKÒC0˜ŒŸßâE>wGÞæ‰ð‰ô¾}óûöíý¼kS?õý•͵Ìt>-¯r»žu[pÈøÍsßڵߺ¢µð¦»iskþKOöÔ-“×Ýêž,¯xnÀ?Œz ŸÄäÄo¨Tv¨ë¾™Ú1“ã=2³›ZÜ®I91;a É§b¤[r¤ïØs“ã=·eKo;oKš…»¨ þWÍÓȃ³ñ«›fÃx(j w$·oFÔÖ¾ØùÓHûænG7ƒKw —¾ PŦ†Ÿ\¼;¸«ÑúÊJîW“‚•¼^xËëã™ÝßÀu^¯|éu8À¢^G¯^š[N®}›zt°¾lLúÐQЊ<_‚˜ç„Ãs¤!­[‘ICZ·"²ñ·"î§±ñÌ}ÈÝÃLÌiœp—ŠMû <{>ƒ´¨c×∃^i|¶åN޽vuÜbï„“=wżËo]±qˆÉƒÍ'üœ?|ž£Â­+1Z0qb·7“#¿½%AXþ²Ü~nÔ¿ÄëóÎÏ|Z¤<il{îuxއ‰yÝ#!DÏëHÐ/)„™(ýÔƒ´ºÅß°¹…þ ÆÛ¡)CÞ…ÛL/DúÜQ‘¿{ˆhµ"j‡õ~}t;²§ÑkÖÃÜ7œ÷~ëù6ªz38Ö%|÷h·“kï4&áæ¾"îN¾©±Ùçï+Ü6=ß”ž4^Ú0>é·GY»¾ ¾t¾FÖ×¶:ÀÁm`ä]Œ9×¥ù!ÒõŽv!çÕÊ©Å{AGCâÈ#sÌBEÜåÞw4ŒW)KyJm­¿­HÛÛÜVtÂô‚ìK›S:ßQ-ﮌßÕÐ\—ZÁÍÀß10€®˜½ì¹Êé^v±üÓ¯®iVFQBRžÛव¦•équKGjoS+ØŠYì¸XÃ;”×þöXNé·žãå½9]–¶ Ë3_Ý"ô†*×>nœ¬*ó$¿å¶s÷J9cš¿=9ì-l‘ô˜kæÜa²”û V1÷¸| m0y_§ið©ç^EWdzÏ4ÀµËÆGӟϾ¹…ykö€×&oøÛ3éõטq¿¤ƒ/;63èñ »"¿ÑDžo+­|Ụ_¿{'|+ð ˜S¿¤i=“ù~v”uðg=çzÄAu#µ|éÝGO#Ïeʳº©ÎÓ(”!ÝߺûDèdy«r>ÂGz®óØ›ûþøsáÛÃAèÄâg~søDæs¦Ãº¤µƒˆ®,Á÷±ãöÝÆå‘8^£å ¸ØµÛ¥Ü}ï¿z’映ëÜÞ ·é¢™¼WßHqéûé[uî9%É÷O´‡ã¢jJÖVÛ °ðÍÆw³Êœx¼Ély}NvŸv×êd8¶™¯a(¿Õ9÷œræü›syØ=ç÷"œèçœyôó+^pô æ÷Ò(ëÐ×v¸)ßb“C5aÌ}ù ˆ&g‹òœ’J°é×7Afâ,Ø›’¨hK¬Lu´ÆŒ4±­L ¾¼¦±¡.qT„ú¶«G¾¢‘Ô#—؇¼Ö ×Õ´Ö­ÐH0é-L¸¹aisMc‚«ÐšF¨8~§È˾;Z'+Ç=g¾Ûì·CØ)†#ð£ÛýüI°h=bÏÞà“ó#´sâ‘{Æ{MκŒÏnÇw5ùVâÕ{Ê[ˆÖîƒÏ`<àwÜc¨suŠ÷ši©ðæMøsËßÌ}'ž àÈ[u÷§uc]ÒcéìÑŠºu» g=’Ÿ)zÔ]“áQèíöix¹–öÊî~s b·†Y‰WµïÕsÏcõ|é±z¾üX=_y¬ž{Wóèò}êwùˆo{'^®4×óÖ"8‡ºå7‰~é·Ý÷»À¡à–&Ýa£kR]»¹®If•¿¡ŒÒ}C3Ú'ž^ɽ¤7 bN7"ÜÐ ^ñ7¨œ#É–×ÀëJ74ÛpŠÓü0xÈó>ä?"å Ëg„îf©iz7ãæïfÂ1Õ»™ÇX–/lëÐX¾«²:œÎ­©#¿Æ^ÇBHTú%Y>Çw0ù<ß™|^§„|¹^·÷]E¾$ðSë ù<ïÃäó˜Ÿ|žB>¯³B>Ç—1> .1¯U+/žRÀ?EâçIWZyª²9„×ä£Ê¾“gŠÜLƒ5å“¢kf…›¡pZz€—£ëõÐéQÖsÝNÓy@ã‘ÿ üoæ ÿ[ù?‚ÿ£ù߯ÿñüŸÀÿÉüŸÊÿ™üŸÇÿùüoçÿ"þ/áÿRþ/ãÿ þŸÍÿsø¿Žÿ«ø¿fP#áòè™é=¨ï5K–öñæ#¼)¤ý㾦Ý0t?¿ØË Þ!ŸèÒ¾g™ž*®ïøl¾Ñ«¨q ä§_oÉ‘q¢:Ø™&UŽmž¤r«Z.˜­c‚½O5–ØÇM~oôtõÿ\"4ÜÐí=Z6ÄK¶1ùßОÏÞ9ý ónBˆ9bƒÂÎ÷zÄìv«”Ž(x ðúî¶nëæ¸÷cæ0‚Ý9Bô»ïšËtç0§þÎ Fcå’(ëÈWÙm"B‡Ä½×åÉpmž¥÷þ¹{+o†K½)¼ÒÞÙîßËK‡áÿ\¬÷ºg_èn âªw2l¸¤8þ޼uÈ„Äýw7+ç%QíD«E>;¢}xw‘Þ_çù+m‡’h­Õ)åiÅ/Ò#VklûH|­®ðPîâG½ÚÝ@âž›âôíu›niÜ4梾=þ”vÄí±?{ñmŇė? œ«»j‹Nßè„-%V ÆýÃj»ä7S}Ïtor|ªï6÷F÷ºü×騵†šVL»¿ÍµŸ›ñçõcR\×X=S¾ÄÀãØ#Þýò|ëßµ†š´gW,Î?J1Õ0ÂíGãýºá×½\–PoÆåO¸÷%1EóTÝ™r,¡4çÄœÉóáX­´µPåô³<ÿ„â±'»Æs)ÙK;.€ü“¤¼Gbþ¾GÌkÆÉkœÝ»ì¯…%¿%ÂŶ>íñS>Œ¼ÆÙòU’z“—Ï{ÄNª—¡[ínÈ5Ln¿jï(öL·ƒtŽ7ÃÖ°9Zv~þØ?æÆZóÈÝñõfo¡âˆÃwvwû›u³[–}Ĥý£#Ü.Ø–ÕÓ{ß7v!‘×ã4$Ì®¹u] [õË=>0Çì²ðÞq{Û\„rAó¤¸ö–5{G;k÷i¿ìð\ƒ”»+æé!÷·ïì ¼§ÄGálK€|eh7dsìç’9öØ_žRR]éËG¦'fb~pözYšií;Çòy²{Ž'„9†Kౌ| ôÌ(kÚ§¦.š?³l^¹ŸqéiŠ×=›­ºðSž¿á±ï\6Y>_2D™îù ›5uü{ötŸÂ±¨Î‘:NŒö,ZŠüÞyH`é&¼r9dB„fœòyð{–^zî\ª™6Ú»qãNª›úìçA^U n\e=úÀ†æÚÆŽ:‹òGgqz¤à¸uz/ùqVÍ;ùQ1ï.Ð;A-_¼©˜{÷ùz·:Õ–,KPc[GK"Ù¼¼¡5Õ,%’6ß^+±äêÒåÜÔµVù'G=¦fˆ'`Ð5z'Š6!ž#‘ ^ˆ‰)”‹j:uO7T;ÏÚè¡ ¯r>ƹ=WÇóü7igÏY]ÇŽíx?æ^)bªÑˆ†ƒ™iƒ§’NäýœX‡aô´´·î} **8Y{W|üx"ÿ Ó°µp÷Rn柽çßÉÙ¼wþÝS}¤”¨·S -î«¿›Ëv™óéì[&Þ,Èø¦‰<œã4%âé]ÏZ÷0ä_1uÑ_áKňÅU{æO!ÏÞçÍ—Á‹ C/Ro·~ì]ÂË­gË£üj§?—\ÁNL­W´WuçO‰ç¡<¦ôÔžëGæFÕàŒÏ¸ÔKê »=„Ž7ôbã𠺤­%̳µõMYPí;ÀU[»u“º_7¥yg £ g§õèþÀù·v¬ûXÚõÍÌq³aî–tÞ˲>àz½{†ï»ýŒè”7½åÙW´ý]¡|£wj,à7Wœ› `‡yÜ!Šì™T§µ!prV`õ늬"Ç5ížuÓ_øA»2Úºv7Ýã=sc°ÚŸä¤/s¸rÏÁý!»àŠ;>\(oå»{£7foýN”‹Þ ìªÏ¸]çዲä|Q¾ŸýYÅ-Fs]ü”1†ÿ #èRS0’ªšA.Â.¯˜îïà‡Û‹B?5ž˜Åxx™ôÜüNLè½Þ€_üÝWÚââYœ nqŠE)é9ï!·¸°yç´$©Iþ"í;æõ ÀJém©ÓÚ$_bE›Þ¤u_­UXÆk[R«×% y{´ïĈñºÔQ0-¤¢T+:ïÍ[1Jé1XØa.i[ȸ‡°ÑyQÖ±YÐðÛ ]ŒÓ`¢ šEÑÛ=´ÝüÉC]–,Šò,?ÎÆ“ÿ\ŸßQã}J#UeE§.Kß×*ÁQä^vuwÖ¨’·òï$ëH”–éî='ÙŽo’´—¸Ÿ¯TMç7¦ZZVÖø·8(óöz;½º¤D‹À½E·O×ÛiÕcÇM­°·(%”x{Nüvú‘nHÜ[\÷iz{äèâCMÐHy+ÆÓiYcÆ÷½ÅU\ü§è­t¶t´™| ]‡ ìr=DÃÉ¡;zšC¬~é&(‰Ë¡­of÷,?C®çRTØÒÚ°¤£=†Ç"Mš—_%ÃK¯­-.ù5K“–G~h¢qä9õ¾š}ƇJ¾¼1eµÈÙ{§döÞy¾·ò?cvÄÉvÄy¿Ý·Å7•¢4lÐ[ªü_º–ð¡OòuéíÙay§èírBñà^t¢rJnL÷›5Gr¼ÇÞ£7Àûô~=¬È5­£ôþKö®ïu^ðïµc¸ö=œ võñîý%/ÕÊõµs®dŽëí×aM5èd\ò¼¶Æ'ÅQožË/ß6Fn±òæ¦oi1ó'ÎŽÞÚšü[0)8`¡Ûã&­×H+Ч@MÇê­KÛ[¡ ³wø~‰2.¥ºõ¨Š^\¯æµIdc²‘£•EàS?‡º·Û‘ó5¢sÛDRv:-«}eKòHô .Œžú{/6ÑSyLúýê:x«èÚ™÷òfcúw´Þoªi_pŒ|ؘܚÁÓ²jWàÙG¥sË‹é¯ø§§eIVo=®’3«sÝ\ljïUN=äãæââºd#¯Ý[lô‚‹ÄÄ8-kICª­ŽÞêö#›SÈ»¹œÉÑÞŸcuSJ“C “ãÈþçv´§|iÇš]~„›Kjš™_Ø*¶Øl†èµÌȳaIz_rc‹ÌܘCë|m´“Ÿt0¨yÆ@žµ „(7]3'jê™>G;L‰ÒyH=Óò˜Fgyð‹py¦nÛëЬXÛÔÒ®Óé–ex’ñ¹á,ÉÍý}ÏÛ–Û]Ö)öÜd+b~]LFÈR›arNâ“Rñ;œ>­Æ¨­¯­Ï©Ô7ek}sZ]É0GcÉòXUÎõ¬Ì=ˆ=v˜j`Ž}‹^ÖLÞNöõÙÒzöíÔ{Ö­«Ÿ¼c©c’¯ÃÔù®ÀO/}™è°›N:0aoñËËŽ<ÔöëQÑü*ãdÑ-4y'ø~®‰ž7ż•ïÊh oñ}pøæí¼ÄêwÜôóàÞ~®¹¯Ÿ7YNy?2»û ×3 Änuö­¼ ™;üøô­È¼  —SþBÍ èú¼vy/N€®î: ÜHü[ù2yǹý~qŠ ¦×Þ,â§ÈðDI¦¦.²œòSjz76ƒ£Å˳9Ñ%ç××Èóߊxx5uîïç0zÏapðÌ[ùÁ43::= YïäG(šÅÛýü,У|¤˜¹@~a³ä^ì[;¾ õ) éNµZsèÈÄ¡µ‡juâê;$=7èÓ—Q®ö‹›FE==¦KRÄÃ\4‚·#}í¾Î”ázŠÏù<¢Ý=”Ü#23"æÎÅíH¬¬]–dmgu B®ánµ|LÿŠ™Vƒ<Êü:ÌæË Úl.åGÍÜ'†ê½T|ŸäQÉÜ%¥§bk×Û¼T°LõžâóÊÿ•©wˆÕ#¹ùó:£“Ší=çê²9®N¾Âl~¼7ssï³ó:–.E•ÆÝÞékÄK3šö-é½›çy¸ÌwéëÞ°{Ƹ}cCm´Ü4õ‹Òb¯ðõ™÷ ¢æÌää\Æ®íïv¦ÑNw­<™Z›õÖ±FM-öÒÔÚÏ×jÞ?P«¿qªfw5)'šÆùÎÇë4w§ÆÌÝøüÔŽ»^©éOCzæ¢Ð{1o™ô§Ò7k`6yï!gÙçL…>z¯uY/€èû–¶åÞÓCù]6·/i³iþtùZÛØÉÞ3#ì1bNËBÙÚ—ÅÉß”¤blvWâkyžèTEMßãóï韔ªLnucwîé;rsÎPo¿ÝÓß[ëáÀæß©·ß¾ûÁú:{»s½å‡EAßî¯qFôž_„òN߬qƶ'ùÁ¾Ð |û׿3Öÿ›þüc¸ÏùúŒ^£rüÃ`}3·õg•–O1ôç›æ¯Î¨t®Mn|?HŸðÛwøÜ—-­yd->c²åÇoG+ùÿNù•{eG w÷µˆŽJÇ÷/º‹~ûç¡ÎÎ\Ö›ÝÏð1!ŒõíÛï¯Câè!ÈøìúŽÆÆ•‰6ú¾A\ß ü* £†¿U &W.I!²ŽÆúšÆj®–çj ].è8ºÉ|û§¾Þ=ùšW^˜ñ¯>X‡Q§\¿ÎäÅK—íídúâEy~~ÿöm}=Û¤ƒ—oY:#xi˜N®¿ÙXkžïÁ–¥5£ßÎnøëêèlÙWÒùÑyfúö¿úü%—r ï­;íÞ"èõW­ÂÉû^?}šåÂW½þËþ[E5ß Ÿôú/¨£³×Íêµ¹gà)A÷Œoÿ³Ã¾›Ò÷j¼GŒãÝ—Ó¸wÓö¸#=;ø( ïŸù¼g•Í›S1çè¸q³,œ†ÂS¸c<›Ýöt÷ñ¿ÞøSåÕ}P¤â‹’Õ- à¬÷²xa`ýIËæylÎkGZ~4cuoûö->ˆ×Á/Êׂî ßþn¸ûøYÏÚôæâÞljESquƒÜ’î»T·ÁËß¾¹·ùîÆïõÝs/¤n’Í~t ÿö·3÷`óþÁ–¾ãü»™ÜxU`Þ¤’wZVzÖ|†wQKcR$fØ^é®Â×€îùß¾Ay7¯d-^T]Û˜ª=±ºmesm&>ÄcùöõéÛng®Gî8ø$ ÿôõ§«ˆÝrùÑ«§ý¾ò6–wYâÎ.×à´ßó}êεoú›~ t»ùöu1DgÏh§wÛ[<èvóío¤ç”÷ôßçÄøßFOw±K– ð­N5’æ\ÝG|ÿðgÀnûíô¬#×£7 ô¾Åùö×ö~Ü\ÛšLrÅqïñkÀûßrónÞÂtIߣ#®Ø·¿êÞŸ7J\ÿ½qfâ7ÜL¬¯kœ|è~ùíkü[ª:Š£¬{rÿºÞ?Z@ž­prÚ¿µ¹ÓyC?œžüšÝFŠ@6î-ºEäþ”½Ý\îh;¾6øµ¼ÿ¤Ûçx”¸(ÙÞ£—Á¾þD|¯¼DÄÂiÑ»×{Òøö¼YûÌ»ïÖèù ÿ]WÍ[\ßi<Ò賞» ]môW¿ýù4ÆRžãÍó”ᦷh4…©U®¬Àu«Œè¨{‹7ëvWëå7üËz‚Ö¶x*ßþD_OTL›^»y*èkÓ“÷;,»e«3í Úµ¼}Ÿ½54÷VšÃæí{ ¬ν•¯lƒU~)Þ©çÖ½¤¡}îü wŸGª/ð,¾ý×NB-×#w sw@ט»ƒ!辘ñhÐÚ/Þ¶¥6XAÝÃêïëèð‚s~Á;pÐ…HŸ¯mDÇÙ¾Gc—}óó®Çë›;:£zîz¾Ü#n[íÁ…Í©óþBߊÛ­ñŽ0hÅ¿E÷—™{·{+U³K2³Š¦,8ágûîc°Ë²ÚДe&~fã=‹<Ûj›54e¤’óm4©NËB*K7Pó½?Þ½+æÚJ›À¾Ó쓉vÚùi,+oÖ¦ïx¬FšV}ðÜù¹6ûåæ¾^ Ûn‚ÿEï÷¼(4qÅoüö»{óø4.z­ìÝ·Å{wS/7]WfJ*§eÉQÊJn—´×vèhïr I@/oJã»çÁ™ÒŒ˜üè¹²GÞb=ÒK9•è"Ò矎¹PèŽÙ/’þRÍð·ô[Ù£oN㦎\OÜÿÐl·êÛ¸âè©!¥[g"ÿ.7:€ÌÙ›ìæåeÛ™—ÍIðã'/äy¨Eé<  >|C ©€î9EiIr‹½1“Ûoÿn9w+£§ƒVÅ|î+#Ý­=žÛóQ¯EëuÉç¢v::W£xq5Lú«a¥z¿%WsÙ¸š­~ßWñ]÷f‚´©s}¥c®Ð,÷¾”'q~œ^;¨¦}Ìr{5Û\î}9W85ë½#Ù‘k‚÷Z§˜Ñfqž=Ìè?“{Oï’JÎñ„uÊ”œüí—vsWrº?¥þGžù@—ÖöÓ3oõ¦\ýïó?"ýÙÿ^Oóæz® õÔ|)ÕêIߺzúm®gÞÿèÏ€-~OþG=7×sc¨g@=ãÉÝÌ»¦Í¹W…Ü7çî™ ½ÏwÍ6UmßÌ»t"ŒÂÙï‡lÓ"¿'߯/Þ¼u›÷ã|Ûã7yùqÞ@:·;_–}5-r ¦[fF“îr ¦[©é¦!jºš–ÝWÓ¿íìÖÁ3âïìÞzþ}gûzÂΦžßÙ½ýù÷Ý[Ï¿ïìÑÿ{g“ûììÙ¹÷ììö:/[/Æyóz Žž¥ÓUäñ÷ðâó¢œxTÄl.ºqúž¤Á§í°5ºðiûš ïï¹fÁð°8@šíç:ÇíLêåí¨‹å_§S§Îãñò) Pd§9ÑßzþÝ- ¾”_òô(Ñõ²¨h`Æè‹ú!½ùhØ&m¼Gk¾Fy…Ë47šç%ĉ]NlžzÁ\«¦ÌSŽz¢^ŒW/zf~¾jÊs7õæ>㼃ǣº7¿úY ŸwSCó¿÷óˆ*oÞÏ¥¡Ÿó·ôÓõdÂŽž6ïèéÞüêi±tõøBjhÙ„9é鬛”Wµ§9Ó½`ëž¼i/(¯ÁìÑÊ ÷èU3õæ%ßuf›£ãnºo—>pë™5yâ=×(§õƒùp.ÓËN ©°ú„¼}¨ž™ë·äE³Q½ŒÕütžñ­§W|&»°d·¨.ÌM§žv;¹Ðnîæ§· ú=8óûÒ¬ö¡ÝcàÙ×F]~­™8>:}Ò›¢î‰ÇE—GíßµLüë¨Ay¾,V®: œŒç¤®¾i?ÞZ´Åç‹r7ïÈß·Ç _óy»qåè®—]T$W*ç®3Ý{.çL½ÕìU÷!»iëËÖ î¤BU¨¥¼¹–ô]VË ›jiµtbx_Ëî¹õekkI.ßÞÍÅ=~.ҷʹcÛ îØ>»I厼É}³›ì¾#oÏÌÇ7mË{ùö>ÅíÈÛ[ï¦y{ú«rþ{^ãÙ꡼…͘î®y‹›óîÜ–w“òöÞQÎÞ‘·÷†òö9üÊ ÷“ºDXgÿ›b¬#QÂÉ'ùÔ“¿ÕZ8áøò’:GïÜò¶ Å¥§>ïr¯ÛüžþÝÔµ×I…]‹O-ÄÀþ§~4œVíˆMýÓMiÓfìÅ-mËæ·m¼½ü¾>Lùè¦:—àßüÁÞF“ìݔśkZ²ù¹Ou͸î—ÏsþèéÞù>ìÝ›Íþ-ÊûX7¦;;Ü…:1xÛßX:1OÛoo=½˜IŸÛ¶î˜çᣥoèí†îwÒÇpÓ´w¤ÝN¹üîÈòÛûÌnì¨\~—„\{î)ÊåwKèËšmXg²îB½ó¾óßç}ÒíÏû$ÝÆúŒ˜÷IÓwÌûõÛçý†'çýÆ'ç}דó~Ó`_vn›÷‰›ùñÅÿ}Þ'æêÞùHŽCuÿ3·­î™fný¼WþP÷¡g<2·½oýÜͦÝÜ€›·ãÚtWõäíÅÑõuÂGœß k7Ï/»±8è™F½H4'=7É•»Ùü×¼ ;êíéß!n÷?TooÞväí¹­Ò‡·};ìP3o‡LßÌ1º'Ê®ò| :'ÂÜêxÛÍ{Øö²¬õƒó¿éAîN|å=Üxý¶ÙØ·O®Ûp_¹¿oá}öaÎåÁâø]Þø‡}}ÐõÊ —Áy€ÛÀìŽß¶c:Ÿ<ÓBžžþÔµ½î5žCЉ%¿ÓëƒFP÷Na…¼Ö–ͳóD=㯣žë7Ô3ÞÝþÿG=;¨Ç`™¼žM›ñÁšGêÁLjŸíc±ñŽg7û¼¨ „;Õžm|+éŽ)ç&õF¹$:ðò‡òjö»ó^óHÞz½K•wvÉò&ƒy[·ÍÀwý¯¹;ÀÝ¿þóÜàøÏOÌ]B]…{úyÀôGòvÏÝ;?’·{îÆ}mÇÜ%÷í‡qçl›qâý¹'¾Ð™»qÂOÎ]|ßܵ]ýPÞ=sÐvÖ#õÖóž³cîÈÛ½ïÚú¸µhÛùÍÝØô à_æn¬»<1wÔÕ=wc«ÉÛ½ïÆîýPÞ=ó:æ–sG½Ýs7æâm30æ¬Ís7óá;ÜÝ«öÜ]Ínt{¸ŒäÝÿVîwmº‘æüÆEߨ¾…ߨ:>uöß¿û~®æCy Wð¿ÏÑþnÿÿç9}ÝCWî>]ywÑÇÏ 0GŸ½oF û޼»=þhŽö»ê·sôÀ<ì§è™£ýÑÇÏ 0G÷Ü7£nÛ1G½yßû¿æh”vàÙG£´ÿËN¿4dÀ}ù¾yyÑŽ9êÍÛ{ÿzbŽFºûמ£‘iþÀ¿Ìш«èãW† ˜£{‹wÌQo^´oþÇ]rømÔu÷†»äpaŸz=;© ”ÝÜ—ÙŸÈxqóçéÆqÍg*»rá‡Ïºû6|ìæ]ûp†éþWïÑäÇ{¤ZK¥Ý»]²½FîÿÞøòõþLýC ·ÒŸ–m5Ý¢³âáþ ½|S´G¼¿¿|7 =ãÍÁЪÍsÐþ䜮)í~Ö°m5¶ Öï>OìºVé?Ôû3ïÉ]W(9ýi¥ñ®kÝÌÿlÝrÿxbV[Ýý£‡‡Wcþ6®Æ­·¿wê+ðû¹Íí«Ç{Óc= ¨ª%ä°]ïâäOqù÷ä,îÛÿÀQƒ/òoózzø_ÑÅÔcïéºôäåþw§Ásw”M ¸9)7:ëÑ ØâžZ}msÿ>÷pÿ¥9`={gѶÔ;ÿõ½CîžÝ1èwó¿è¾º[¶Ìÿ÷»E7ÿ2¯-ºôÎëTzµDØ|G.ï‹í%ç÷\#ŒÑÝ»‡îÿ-›ïÿOöu`Ìÿý·¾tóÿP_—>Ú×÷âWãžÀ‚SwqúÝïzîŸNOìÌÎÌÍŽ&þ:;wÒ^ÙÃ'MÊ6é…Ù…“Þ–½ó¤Odï>éeÙxI—.†œ;ôî®çû¤ûµÈ&÷0}ggó®ýJZ¯ç²îœð묻xÿ©Sªáªâc¾—«ÊÛ:WU=êîë—ï®þ"«¥6ïrº‘kdìÝkÆï·QüÆç{¸ƒ¯:sfôÔ-ý‚¯ÚOüÏÿ‚5úÀ'.Û†›n|Uòôô½éêmu7éþó?zÝÔùß{Ýä8àݽ޺½×ܧ}¯ÉÓÓëÆ›¶ÕÝ(þG½×OpÈu¬íöçeWeøÒÉ¢í=éå??qûjtüç®=žœpO ·ÜWga2ùVm™-ëÝØèôUÒ:}rÔÐÕ‹ñ7mðCû¯®§£w÷°®ÛyÑðz?Î[‰ñÿjx|{¸ Iݽº {µ5’e›µ5ì,¼9ª,ùtTUrs´hBVtÂ|Ï.‹êB¿ÊÎ|%ÏÆ%øÕ[&ÝàPKÖwñœ¾è»Á¾›í»Å¾[Ý÷󲕻¦£KïÑk•üxN˺ ’æt{oS¨mGné­ÿQü—ÖÁú¶„úÊÔ—`Ä¿×WdÄ`}—‡½Í^ìÙÛ¥ÍÜÇd¸Û™ÂüßÑž)¹û]SðѼÌ,;«°YƒbÛ6 3/åþ/ÚEñ¿ýÞþ1_©( ˜=::æåÆ®áýçeŸ¾UÓÆ¾ßÑ·Ÿ®Î‘ÖçÃûïú [ößµ™y)læE·=Œí$³ö ¦ÉÌízx†ûóPÞžÙN¤}¾/o¯ŽÞµjšî¹UvùHwõ¾7sGJÎá^‰/ʆ¸#Íwùä¥ûV7Þj©áyÝD{nBÒžŒµûê½\÷ðœÇÚ=zDq¬}Ûµãn 7ÌÞÛ÷ª‡k¾F-ïíåÆáñ•|d¦¥üÿÕ¼Ššo¬yÑŽš'ô¿ï¬Ë{M}:¿ÏU‘8>ŒJK7xˆ¬9ˆÄ`¸ó ‰GïßÎ7¤ñâü…Ÿ"Î_¸ñ42ÙbxqþñO’™ÃOI»Åð^2ÏbÚ8Þë/m÷~Ô¾%ÃCŸ÷ÑO<ç]Þxý]|;oÀƯ¤ó=k<›n±:ððè½,c×Ãy^59nµøt¼3äøTð×ú9Ë'Gç'Òäp^ûñ¼ïl94q©hÕç=õã¯16ÏÍx©Œ½ÿrù”‹½÷J¬ó^oùä¹1õII>çÃÒäsÞ+M¾/Y>ùpôþ)M¾oeò%»gò%~.åÍ11ÅäK̺ɗû“NN·|ò똜òÝòåþ¤å½Ò擇ÇÄü_š|_Éä(˜¯]<<¼§\å(xOÕäps‡Ç‚ŸÍ\a™½“ oÁÏ´æ¬`sSÀKQÁü^ãͱ`1 Ç‚õ©ˆÇë‚ÍzÏÇ…k,Ÿä. Ö3SÓ—35Ío-þ‹æ¯ššŠ;gj*ÚœQSÑïKíâ¢÷Ù©šŠ¶ÿLMn‡á¯±h=659¯¶¦&çiÙÔt¹å“£‡¢÷´LM;CM7[ùg,z?·ÔäæÀÔäü[›šÜžÃ#cѼ{ššü^ÑÞ*ù~kFKÞ·æ¾|o—üÎÖÞ*™Ÿl“ÏõÒä˽z—ÎÎì­’÷êM>×3“ïS!Ÿ›EöVÉï]å+›Ÿlò•÷Îä+{Ì¡½Užò9_¡&_&³·ÊÞ/ùv…wföVÙ{'‡óäMŽŠßòYñ³¢½U1ïÓø…¬„½[ñ{W~@*~VÈç1 ±—T »ÁvïlwñäÝ`ÄéGƒù£Æ;dƒá “Ûyû7¹Ý./âá»Áújr;<Á»FßK½kôB~#Ãl5úÙRM~o‘Ûá“ÛûFåßµz×4Ìjžk²9¦¦&ó«JMMÖWzÜ<‹7uef«Éö¢Éíð ³%o¶>òùy¥&¿çô®Ÿí9ÞõóE¾&ûùh/öóØW~Aúù9ãǯÔá{C«Bç‘/ß…ý>j9„qûù}Ln¥äQ­_èY?¿ åï¬9xn~Ù› ã_²Ùã9rä;¯Ùp&›mÏ17ͶّÍ~çÉËdsØyÍÖf±Ùö5õ÷s#?Fý¶ëöSÿ°ŸúŸ`ùäw²¿õÆäÛòåþ½ûû9–Êþ†çL>‡ièY×å…²¿Çê}ÝUÇóyŒÊa¾ :ÀcPIÀð”~O“Ããcy¡à÷ 9üþ&Çí–C{h€Ç4äð^äÉá<²ãƒr`ðò>0xyèo-ò@9prÈ‘ÏÓ@¿ï5m†LŽüÆ0Ð|Òã}r ¿+Ãc/rä8~`ÀÄÍ×;9ZüÍCx¨Åc/åh î[Â^lñžãµÃZü<ñÎ÷€˜Ÿcbjny\%'+ƒ 3ÞëÌ7ÈïBbWó7ù°ä÷.¹/n“Ãß3¨ÕÏ+µú%Ÿó:ßÊA~xw¯½“‡ÊÁjû9V}ƒý-M^*û=­9ìïaòF98à†Á¶cØmƒÍË:~'ÛÍüóZ»vpðé;Øã íÔÁ†·Ì;ç V?ÓÔšßf†œ7Äã{í’!{ ñ8çñ.Ç4Clÿ™wOðÎcYb÷X?äÕrˆßÍš›!O´zÔêñ1µæ¸¨Ÿ{b~'in†ÚNb††==ÔöŸy—c²¡k»C µû‰ù9–—Ì¡áf34àéa~_jn†ù}©ž ó÷]yÍæïR¼ó·XùÉî”Ã<>“—ÌaÞS:ïü-Š:<>£èA~æçF31ÌãWá†a~ÖÕ¿av×!ßpß'áááž:<ìøáþ~¦ ¯Ëô`x˜§áãÊïæpË¡Ž›ìf ¯›Ã}Ÿxw{Èí÷“|oûixØO#v·:äs„ÇŽÊ1"ÜÆFØÝ/œ#=Âãrø=$oœ#<.Q¿Gx¼+O›#BŸF„{ðHÃdì•‘~îUÓH?Cšû‘Ö“ÏÏæu¤í$“ÏïHyäéw’z0Òc&ùßðâH?ëòº9Êã!åå±£ükŽ w‚Qþ¾B>qÉçnfô`TÀ£|?È—÷cÔå6—ò¿9ÊÏŠú1ÊãZùßnù£üîQ¿÷ó˜C^7÷óXV¹÷ó7]±.öó»\¹÷óøƒÜþÞ#›û.Â~ž‹ Ç4û.Â~~ÖÉí¹ò¦¹ŸÇÁäö7¹ŒÛÏï{rûÙ’õªýìÞÏ ÎÍäíoÿÊ7Ú0h„פÑá~0:à’Ñv?ˆøî£Ãý`´Ý"Ü%÷ƒÑá~0úkñüámitØ£Ãý`¿Ô§ý=fRŸö÷s&ßœû‡Ûùþ+Ë{Õþ+ïïgNs°¿õŒ9Øßãfòå3·¿áfæ`¿3¨/Ç+ûÛNeö7¤ýà iŒÝ˜ƒ1á†4&ÜÆÌÊÌÁ˜pCnHcü I}ãñ“ú4Æßiä÷sŒŸ-r{|/¯Ÿcã1Ö3æ`Œ¿-)ߨpãk{Ž90ÖØ€±Æ>`Æz¼BŽœ#2Öü‚3c=^!G~;{efÆz,HŽÏ†ßÊô©-ܶÛü­N>EÛÆjó7ùek 7€6·4mÓ´ù{ùòûw›a/æ Íߪ©/¿[´y>>Ú<î'‡ßÇÊ1Îö.s0Îcnåø7ã&gæ`œ¿Q‘#¿©ŒóXA}çoTêÓ8›³dã–ç1|—Žó¸|ùígœ¿sK±jœÇ:Êq€¿ˆ5x€õŒ|xü­|ø}@>¿…W°;·üÂ-íëy—ãéü~’BŨüÐÞÉÿÖa?h·(úq Ÿu± Øë@Ï;Qÿôòå÷€ý¬«g®Ã_r õƒwãÃÝn¼¿ÛÉcéøpkï9²h6>ðÆîËxŸxçïêÓøÀëïñ9<¯K}o˜‰~äw‰úq¿'ñ.¿qäoœzqPàä1¼™8%…{ÿA»Kµæ €'òóªžðÄAþþ¡>ÐÁ†!èÍÁá¾{°õüËïC{¼+>ßÁïìñ®”kx÷`›QzpˆÇ¸bH0î!~^Õ³CìÎjòå·„CÌchräZí;©4Mñû^µNñQù¦ø¹'Ÿç‰Ù?%܃§xM ûuŠß¯šÑ)a¶¦„ÙšâgK3:%ÌÖ”0[‡‡Ù:<ÌÖá~¶ä%ôð0[‡ûÙ’ÐÃÃlx„‡û=J/!G~ <Üßu”cj¸ëLõûRžC§†»ÎTõå,oj¸ëL ÜŽ©‹#Ÿ•©áV=ÕßzÉ‘ó]¦ú](¢Ó_gšÇ”ò:ÍÏïü-D Ó `ZàÛMó7=Íã6aÁi†-LŽœK7-p ¦‡ûÇt›ê˜îïªcz˜‰é¶©czÀ ÓÃΘn=0uøûu¸˜®Ô1ÃÏ«ê˜á{ 3hFÀˆ3üíJ~Eg>ÜŒÀ©°ÔŒÀY™i³HŽ™6ôifÀÐ3íz¦ÇyÂ=3}Ýò1:3Ô=Ós¤ä]tfàÌ4Âïlå;"ÜŸŽð¼Oy =Âs8Ôƒ#Zì¼ø:Gø]¥9;"ð>·ð#ü•SÐ#Â-ÿÏ?ïÑ#·ãHω¿üÈÀ<ÒßïåwôÈpû<2Ü> 7³#mv Ärýƒ#ýÝH>G s|dÀëGzîŽøÄGÌ‘þ¢í»[y"m·ù&G{àçµ[o¸µ{ ¤>µÛ ±ÃÚG§ýR«I^JÛ=×ùˆyì(ï¤í;ÎüõÙgË+éìp·žíç˜|ß0¯³ý.!·Ÿ y)°Ål¿ãÉíïgÊ='Ô=ÇßtS™nsüÎSî9žçMîœÓ?'ÌÄ/Ó9á4ÇßäÃtN˜Ñ9WÛ]Dê&slÏ™ºý^‘·Ò9a^çz|&ϤsßtnØ1s=ßT¾Iç†ÛÜpœÛm9äŸtnà…ÌõXA|è¹O9×ßZÔ¹þFK>ÏÓ³³¹Aëb®Ç—Ê7ÏÏ™òÍó: š¡y¾gš¡y†oÌ»ÛÍóû@~Lç…}0Ïã ê˱Pæ…Ý0Ïï9Èœî¬ó<æ_ÓyáÎ:ïV›Kñ æ…Û¡< ¦3tÔA–CžLòû’ùíð¨,‡ü™°ÈQagåïòjz”¿g¨GùžÉƒéQ~gÛß9ä¹ô¨ÀÃ8*ì£í^În>:à¶£ƒVÁÑþŽ¥Y9Úß5+Gû[‹<™íñê;ÚkŠÈàÑaíw€ü•vÀÑþ^®úŽñØHõãoò\zLà ãyoòXzL¸c8©í’‡ÒcÂø/åô˜À<Æó‡ä‰ôçÈçv€©Éc_y=&`ßcìΟÑùáf3÷òæåWôóêÈâDWWÂbø÷¹þ”Ð@r½R¹Ä*ª3Ç}PíNÑ]–ãÏȱ”¯PùO?lÊ\™™=lÊÒd{bÄa‰)‰©‹ªgÌš[Yy|õœ¹sʇ"›êiæò,-›_å{ðeõTõíT}k_‚uU™›voÿœ·xPþ)½]ߌY‹åÞÿïñ*ür½÷­›ƒ¥Ú£8¸í€‘‰¶öšö޶#nÛI=×d*ç_¢U¤»ÂÔ9ʉïÕ—õÜj¾WwM‚±¿õm®œÄU;êQÛAZÛ™F£5¸_”åt·Ðú×%oïÛoàÿ=Oû\Zok4lÐ?@“|Oµ{m­D5]-çë­7/z ¼èÞvõâ“¡Í›{ѬÞêMƒ¾ëõµçôü¢*>QCß¶~ŽCñ· süYtÐÔŽB¥ ¶]°UÒû3UÕ++ TG-é¬^ÑÚ€ok;¯+ÙëSÍm’;mô˜¶öºqÕ3*f•7TŽ:‚Tµ$îî]V˜»‘äÙqpŒf—çr²sŽ4¾R\yþ ûÏsÌ5ñQàkÈ/qóØ]˜c±(h×Dþ†À>óXFû+6öwá‚Øó†´ÃbçTâRÃ;sÞ‰/QÑïh¥{ü^Bøh¾6Êú—¯Õ´×\7'ëØÄ]säÁu¯Ù_%>Ê_ª<“±SçiGwÜé£Ó}ô’—*u†©¾¦&*÷K”;ß§KÏÄÕŸŠ÷é¿üšöéu7÷Üuæ§{î<óÜžÛÏ\Ýs›íÖ['ÁÊ1žr¥Ü–kjg;GW‡v˜Jìš³>›ñªXÏåô ×ðv÷Ž›Kz·{§Íaé]qcÝøÃtu·ƒªÚï{Mï‚^£Ûsg³ç–iÏm§×Ûéõvz½^Wwž¦Ci‹QIfçi6{Þµ•£Æ’(O¡Ëö‹çv0ë^ω•sò¢Àñg½ºËü]]ào™Ôq—ÝN˜s¯»Ã»ÏÚ>úúà>Z¦f»}¤=î£oÂcôŽ(ë_ŸëöÑar& óþïx?‹÷/Ò{`âQ¾p$fÁ·,3è¶z%Ò¸ÖšœX–¬©‹#›±c­½ôÖ_xâO-C¨å…ªer¢½µ¦¹­7ã7ÙœjÎø7ÿ¦íÈÜ“gÃ’FÊåùápå¹f0|§ÞÿÑòl¿'ü¯K{G#þ\}Ožs;ÚShÚ<ß">å¯JÏÄêºÖTSßP¤x6Ÿµo[_5ŽÔw^Cª­÷å«Û­ý>¶šÉsåÆ<˜ÜÍ‚<÷[ž+6æ1íZYç1ç<ß??΃3õ ®MÑEÔb°y èN;\9 Ö>·ç‡†vNBuÀã¹°â„Cwïf»ç“º…ëœ~eÕÛf;ÌÇÝXᬌÎg«ððöóœ£÷b†­Q὘ak4ü^¬âêG+³©™š_Þ‡ ƒ}@·s^˜[½>«b“yÿâèŸC\~båûÔÕ–ë©Þ:øæÆÁ7;ßl|³jó¬à1qoGo¹ÔgpÛå¼{kÆ‹¢òßT›z¼„·¸™Ôèíbbó‰ìÓ„Á7­oToÛ€Fæ+ïO[ox×ë.×mr÷ í©*–3ë.ùh4£ËÉ7úúÚä6D'L7½8ÆtµT9óÜ3 ½çpÇðœ=°”×Ç异T{´ ãe1ss\—ó Ò{…°”ôCӱǜÂNqÀœ±ç‘ +ÅžÎ;W6н¶ï<HX(öºH¼Ë9üqà´ÄžÓ¢[Š´G³[Š¿} +ÅžsHy/cßKá¢$ÜU?gÂA‰Ý…Ì;ÏkÒO<·w^;Lú\‰ÝÁÍ­ÕsÉqM3'^'‹wòÚf.¡ËЉ™ ;KpÖbfð‘Çg%8 <õ¼(ëgW›kþŽ;Nš‹ËB3¹ž«\“õ Éz9Ü¥FÅÃàÕéÆù·WÜdÒ{Lîñ{lî=G·ƒqÄ€Iwmw.g|¾mWp# ûVï~pG©î]#o}4:*³wÝlônÝe£JHÕ‘Dá–â4rÍÌ9þ‹Ù‰Ý7B3káFèµ¹“xþ ﮵™wl÷¤QP?óާ`æX3j°öåHé~¾6ÕÔ?ïËgYžF»§<[y&'dWߌûÉ6ï:ÇéÎ$®%ïû™÷üN¬«ÿúšÆmãΙ¸–cý¦YgÖ›uæì'³ÞopÖ€õ³Î™ÔÏ:ºÎÌð¥QÖϿ縛—ŒO÷¾¿pžÞoÑ{žÎI45Ô5è®b_uù™œXQ³<™~Eм’Ÿþ Éåœ`x¥ y$Oø[š’­í4î+ÏW ,®ïâiÓÜ÷î[»Hï¸Ã¸yfióäªÃñÌÜ;ŽšÙž“Љßsyt"ÃÂf?8n¥Ãïv Üt—ñËï Í{ºcXfì K¢¬;Îq;hcrô‰™„&ùJÞ?Kïy:ÇXUR€vѹµG\<ºsâ–ɉdû2–”ÙB Xm®mmÐW„œù¶¤q£#7Ãõä!þÀ6톹¨sàéeïnVéÞM7¸Ûß»Û_/€]Ô}{d·ì؉ãÝc£<¾ç‘§Œ2žØ|b­ã^6ÂbK|àãì`½x¿(ëUGEÙ¯ªÎøp»h»hÛc<‚æÞ½Äl>²—B†=Ø—]xåz†‘qýÌnðÚä»ÇöŠÿûçì /€ùN÷‹´½ÍÍøâ(ëWG»ý³õ²¶µ'IÏ;:•ÃÉž½¬¡vÙÜùi.ÙQG&f‘wÆè% ísçÏjhîèÁíÉd§t46“lmN6úz¥A½©^Úá2ÐT³491‘Ò¹Ýá ¬Oypµ¾¹¡½U®‰}mw™´Âc4±f\§Z:îݻܽû±ýÕq×tûëöÍ9¹§²‡êoS¿ôº‹ZŒ׋›í=O_ØËó{qûgÜwÑnä½þƒ›U‡¹ÿê;½Ã=Óem6jõ{9a{nªñîQif¯Ùu°w³ME¦Î]‰"V7îb×ôâ®\?Â{60Ü1·ë §ÌqËÍ>òz÷ðÎr½¼(Ü,µS¸83)o\{ÒÖÁžñ|xúñMÛŸœ :÷ç†p#ÔNIw£´I òBìœÊ‚êv§ôM Ÿó™ö~Sk²¾¡Ó²¸BÆææ´^9Ö$—t,]ÊÄ¥Å,˜gyäw Úƒ<ë”gý”#˦UUW=gî<Çð\?yN5/"îl.ŸØ€†Çyò—‚3e™¯YÌSóùz»©¦¹’æ¹µŽCÍýžcy´=LžµÊ³¶µ5ÕÚ—'í!;dyÖ¸Þl¬Oõ§ñyäsÀÔ³:ÝëÎzìÞ–¿„~Ï,QžNè*Ýæ¢À¼]º]çy¡f§JÁ z÷rž-ô®vËÞ5ô¾Ûþbü“°[5¹ò€ÓÂw.DoâªØÏ9~;F¸{šTkÚ×e-¨é¬Òá»>Áç¬&ò÷=Pè}Ô =P“Ã7ƒ9vmç¡~&ß‹9.Ø¥aäå œÞ"U8-³÷ÕìLÇë,á‡!Å"ì휋à¹|f_‡›¤ã|˜ó*"¯ÅçÓi[˜ê5#Èáõ£Éáô7Ù§žJyÆHsx»4õ‰A¯S@ÇçgÆ^;†·vÑ¥°»${g8ªìÕtËŸBt»øÜ(«'ïÄäÊ%©šÖºê¦š––†fÖrvöæ¼´iÃ~–Ï‚-™)w¸¥·mnCbÕ‡ÞÃït7ÃåË꿆è0Þ=]ï쯖IÛÒds’øÚºÄ’•‰©ByÓ¦ -?ÞH$ÿ9Ê/òâúø†Bfs2ᔸ¶­M×Ä©ã:wÒÝäeÀ­O‹ëÖ]È'obÇÙò³`0ßS•ã²¥5™òèl1Ýùd0˜ï)éZòdM™^÷!ÏÙÊ£õ)¦mï×VËÍŠ#÷Yý¹§oϽÁr£¿@î3ûsÏØžûLË-ÿ &÷ý¹gnϽÙrË—C´¹W(÷EÉ¥ðqa”²ì=Z¼_®÷ç¥Ríñ`mn±÷òã`fût½w´|ÒlnXZ]»,YË­X$^¿Ä›Ð¬°yѦàŽpšÍíÊŽ–:ÈʆæödëòšFʼT«~‚哾ÙeË”/Ý Žà!Žé¹+ãŒ+-rùNíË·©¦ót7[>yt0ùN }õ梚æºÞ|‡·[>ùu07—“•o}‹ÆFÏu3qïåÕÁ웥nç­­iãbeKƒæGcíjyä×ÁÌÁIʳ%ÙÙ^ÝÖ\ÓÒ¶,ÕîLJt÷ßý9Ë'Þ™á ŸèæõâŽ66]’š¢¤åÁS '(Ï&4>®Õ\)å¹fÓ†”–SúefÆdH=9¶¸¾³­£E„©ZÂÕ–:¼ã]ïÔß©ñøz¤=h¸ËÇéýÆäŠeŒ ‘ÙS•rº¼ò»`z¼¸ov!?ÛåãgLªFGe‘òh.©fn.i¯í 2¥µ .—.5†G·P¹,‚±»æüšZ+K*6—ü3­”c•KÛkã/Ë:çµÖ´j •†Š4Ú¾¬\·ÝùNÛ@=sÊo®í Ö^-îJ@èhŠpÏðï¤3Â-¸Ï=÷áÑêš-y]|\­ò÷p1^»¤ØÄ‰ï]sQœ‹Já\p±âKÝ{ÅÕ¯¶®+/׿ärµ+ZÜÿ&æñá4÷“ü^´hÒ9ÑpxÚGFågL˜ü ¼àrîâåÊ™f…;óYWßËCsý¬y˜﷣ϪñîÍ5š™2˜_ê`áæÖS‡|í©Cþ¼Ó^}öñ^©üÔ?VÏ=OÖó¥Gêùò“õ|å‘zî}¼åò¾=kw—ú^zcÖÚé>ycìu<‹'.ß¶S²›yžƒ0:ÍIÐÆpô½5/§s nÕ²›^ïòìæí÷ä™üXž©åi,ϼÇòÌ,Ï¢Çò,y,ÏÒÇò,{,÷Y÷Ä^IFQέOæÜöÎλÑa›+²Çφ»÷P{¼‡äEòA¾L»í&¾ë»)Å)Ê>¿§¨ö÷nª«Ú;°ÍRi5m½ sWîÛÿ3wÀ¢~¯àðˆò¼æ6Z½ZÇWN·Éø¨rws÷ñwsî—^›Ž[Âä˜w[Þ’¿¢õåyû_ácEœÃÜ2=g—ŽÏcn™^k”»ª÷‡Â}ÜÝÍMÌiàý§égxùNÓXìõ«u“ñúFkÀé²r÷Œý^µJûÀ¾#‡Óá1ï¼v"u8Bîš·uûNwÌØëjòÎëN‘;ׇOl¶¸g&^¿WùRVÊ'íƒ,ŸÓx䆙ø[?ù¼¶6ùrí Äó t·L‚¿§Ôƒùr_‰y“áV)¶4_!øÊ)ø¹×M²`½19ÜlÁ‘/7uÁø pY Aã¨àu%ä—¤à56åyD>­Ro#ÓØä¾Yð>¨5÷ÚP0?Ü8 c+ŸVY§§Ê=³àõ]É‘kÈË›•Í¡fÑ{JRŽbÐ -zî‡î–ÅÀ¿,þ¥¼YÙºUz?V&GÎ.z^¦î“ŰçŠÁÃKÑ´ž¸QƒÖ“÷cer8­]î“ò`•åÈ}sMO››dÉsH”#õf¥%ÏuÑ=²ä}#×ç,y~‹î¥à?+õlE¿¿ñcåôALdžO*/WY>§ŸÏ ²ä90äsý†?ç}]ÁG)™nü‰RÐ ‘Ç«Tƒ´v•<^¥º£eÃ%è‹–ýë†Yž²i¸p³ôޯ̻\·¥ì{¬[e9ôØûÀ29œæ7ʲ×Ï$‡×p*{®üìtrE*ÅC¨ÛeÊñ?›h7ÏQö3}ýÒf.ëë¸oH·SøâVøz§‹tÛ’dm ×¶†v´67Úž¨­iä’ÛVù ­}Y’Du huq+QÝ¿×DôÇÕ*ÿ:†³1_µ.‡=¸`wcUpéÒe°6“r»­ÊWN„~÷‘(O7¿çñ{Ðaô·Uç¡ýž~s©ß=÷L}‡v¿®]®¿ƒ÷³-ÚMض6&‚µëŽõ˜þKîÉkû˜™ó:»à[Ͻb>r_)Òo³ó,o4»¹?7îó•ƒï[vÙ!^ωY\Âsí=òí¯»Ç¡ŸÜðù5D#‹ÚèçEÕñ¼®¬-–[:ÆÙµ|eí \\¸Úä['¢_GÒŠwüó`]E8u›“íp(ίéhlw¬9˵|¸Àõ ÖÇå—Þ1Üj•· GGà¥`ìä{k=¸ªÃÆö꘼°RÂhk««G¡ÎMµ Ä/]¢îuψðaD}G²o>8ûÞÚæÆ}tt¤6îà´QJeóh©ùyöŒÐÙ8À;Þ§;ýžYœUMýßfÆ×(_>«ìH´}?0vkÇm8Éd¥ì+rÙ´ÚQ£%ÏÙb5K«!¢¶#aÛÝR~ïüRôÒŽè-Ú0t1yû1»E:S7¿\7§=}œîfEŒãs›ª“ÍV‡Âú:«O¨¯-Ž·M¿·g³ÜÌ›¾iX =çááXpDqu%¶>i.G`¹vêºlø¤íÞþb³¾)‰°¡v׆†6ª4SÛTzjV®¯ Í`)˜´ƒ1/û¢p‘ÇCî®'/ÁîN'îIÀ3UcëŸíîêßSpŽYZ ƒˆ»ƒ¨)¡7¾OÒu6ó%Üñöoßia~¿7¾ãXl`1%í> L©€}nópt}3| $^º¤(±2Õ‘hêhk‡ü·%± …+3±ÆÁUeÙÔØ±´¡9:¦üx«IÞ‰ Ç dc<)zž^ì{¡N£õˆŸ²1Z&æÖ¹ÍK¥Wlç@È”'Ì›ûöÎë¶€] •b·ÓÑÛE»gw^4?»Ëv³LÃRÄ£™´Ø’žº{”„ÔÑ“¶ï(×s—ékîuD7X;ûHuÎ>·[?ûôÙc|$&ÁøÂkCÚ´D/JÖ5Ô8Dvi[t`K«Í†¼Eb2É«ã¶?Ά»Aï›ùÑán‡Ò5Gd„ÝxœÑ°Àp;7ÃÇçƒÞÖçC¾‰vχz›Î½vº¹%¼E9̇npƒŽœ9=j°¹þ°St¿t¤š·6t77ò Äw;7§AGöÍM˜¯í!m¯ž›inn:J×fFµßJGã ããoùÌŒ¿wRn«Ýãé·Ÿzœ{~IçýôÎùQÓù¡ç~¿S~¥n¡(£¤h/1‘o 3'º‹ üùsr¸a·¼ô§DºôåGsBës"O9Ï =¯ßäwi…ٺ鰵§E»ß‹ÇF»ÙwÌL­KºiÑ™ç®y$bTf“÷í'oÅv‡l÷ßq|Þ¦ú6`…㻦­ñ(k}³õ/ŸÂ#³¹ã X1ÄΚXtoéÝHë¼'q½­ãt|÷á,úìq§%< ˆ[0úÍð¨ý~¤*p„x £ß¬îàWû9æ¬ÀÌèÿè7ÿq?>M»ËvÇ85*ïDzìg†¾Öw"“±ofès}'’ƒ=&%‘·´õV6Ùí1¤VÖ!ŸüømÔΠÔò¢]|Oì->þ”TG{š§.}ñ]ŽTÏþ™îþM·nôo;g3C§á”Æ}»ûMgü‘¹¾<^TMç…‹jš«kÙn~VÇ) ÷ú'¥?¿‘téÜü–`{]”H\n§…Râ*ŸÞÈ)Ûq*"ñÂoÄäv>N"Ý=¿‚™ówtfËé —ðŠä}»–è¸÷êéVê8¦&k“`÷>ÑŽH÷‰Ù$n‡€½vöÎi§€ÉÔYðŒ€î× ?sWÞT0ß-z—âOžÏEXíÁL®IñVW·­ä*dx®·pݧª„ª¶x¶Ïò—´»Ï;§ÀâÊ ÂùŒÐ·ˆ}ñ„›y£üç7‚elß ‹ZÀ_R /ÿ>¼}î¹åMz“H—„<ºô;-~Ã~NÖ÷ôôàá¢ß {ÃÍtoTW¿Ñö†ù–†ÔýÔßôcj¤Ì­´nïÇ…Þ\ät<µCMç&­é«–‡A!½±õ @=òyÐô¢¸gfwæø~M»Zn£¡¨7ҸכÝF¾µ<*//Oí¤ùg|Òî‹âpós™J)áÇIÞ,lNÍÈÞœ·tå”?§½9-¾éÊ)_N{sZÙ•Sžöæ÷×sÊÏÓÞœÜê9å#ioN{ÃèÊ)_I{sÚûPWNyÚ›ÓÞäºrÊÔÞœöÎÙ•Sž öæä^Ï©¹7§½¥wåÿeoNög=§|FíÍ ¢žS~¡öæ„›QÏ)ïQ{s²Çë9±kÒ›“=_Ï)oR{s±©ç”¯¨½9áÿÔsÊ+ÔÞœð‘ê9Á‰½9áKÕsJ=coNø[9Ánrø±7§å‚uå”§¨½9-°+§”>öæ´zS]9å?joN«ÿÕ•_ν9­ÞaWN|=÷æ´£]9ñÝ›ÓêâvåÄWtoN«-Ø•_Ò½9­ÞwWN|M÷æ´ºð]9ÅYëÍéüWtåÄKuoNë!¤+§§öæ´w¾®œÌ`oNnNµœ•³ LÖ“3-»»Î‚8½9Ñ먳@NsÃX_žÏÀ ‹¥/VsíÈŒ1ït¿69¸Ÿv×aÞùÜ[ë9xçj5÷»z?ì=ÀöŒ™©ç°³dkåy½g扫ƒa¨×Á;ß{îÑõ:xçë0„þî:xçûÁ5µÞ{Þùp<ê9xçsÀó©çàÏgªžƒw>´§zÞùpûê9xçsÀ]©çàÏÁ‰ºžƒw~îásÔgˆw¾¸îõ:xçs°ë9xçs ÙVÏÁ;Ÿ ¸zÞùðê9xçsôì*óÎç€Ï_ÏÁ;Ÿ~I=ï|4ùê9xçspÏ®çàÏÑ3‹æÏž¨ç°8Ãæ@×°žƒw>Úˆõ¼ó9Ð[¬çàφc=‡ó`er  YÏÁ;Ÿ­ÉzçÊä@Dzžƒw>Z˜õÎ/–Éžf=ï|ô:ë9xçs ZÏá|Z™ðŸê9xçs CQÏÁ;ŸmÔzÞùè¬ÖsðÎç€'^ÏÁ;Ÿ-ŒzÞùh4ÕsðÎç/×sXms ¡[ÏÁ;Ÿ-ðzÞùðmê9xçs Q^ÏÁ;)ч®ã!Þù:Ðo®×Á;ŸmézÞùhN×sðÎã`´¨ë9xçë@sºžƒw>zÕõ¼ó9к®çàÏ~=ï|t÷ë9xçs ñ_ÏÁ;Ÿß õ¼ó9znæÏÿŠzÞù†3Ôƒw>Cê9xçsÀqªçàÏÁž©çàÏá—væàÏA¨žÃÆLã ©;‡yçsà/©žƒw>^•ê9xçsàƒ©žƒw>žšê9xçsàÏ©žƒw>^Ÿê9xçsઞƒw>¤ê9xçsà¿§žƒw>^ê9xçsàÛªžƒw>±ê9xçsàM®žƒw>zzõ¼ó9ðèVÏÁ;ŸOdõ¼ó9Ðú«çàÏ_³zÞùø>«çàÏ!y{rðÎç?½=9xçsÈçÞž¼ó9à$ÔsX®‚Í!}{rðÎçO¿=9xçsHhOÞùò ¸'ï|yÜ“ƒw>‡ü îÉÁ;ŸãS›sðÎç¯Â=9xçsȓូó9äçpOÞùò¸'ï|9äÙ“ƒw>‡X¾{rðÎç€óRÏa¹06‡ü@îÉÁ;ŸÞH=‡å“ØøÌ¨çàÏ!å³=9xçsH«jOÞùR Ý“ƒw>‡\QìÉÁ;Ÿ^E=‡å¼Øð5ê9xçsÀ©çàÏ¿¤žƒw>¼•zÞùðaê9xçsÀ³©çàϧžƒw>¼ zÞùðê9xçsÀcªçàÏ?ªžƒw>¼«zÞùð¹ê9xçsÀ«çàÏ'«žÃrµl8Xõ–›esÀU«ç°6›^=ï|¸hõ–£fsÀ¬çàϱžƒw><ÇzÞùð'ë9xçsÀˬçàÏß³žƒw><ÒzÞùðSë9xçsÀ{­çàÏŸ¶žÃê1Øðtë9xçsÀÿ­çàϯ¸žƒw>|åzÞùð ë9xçsÀ¯«ç°¼;›Þv=ï|øàõ¼ó9àåÕsX¾žÍ½žƒw>¼øzÞùðíë9xçsÀã¯çàÏg±žÃrmtê9xçs gPÏÁ;Ÿb=‡å&Úè/ÔsðÎç0<¼î–¯hs ¹QÏÁ;ŸŽzÞùhzÔsðÎç@¢žÃêRØð"ë9,_Òæèæ š9_?Þ{rðÎçèæð™9‡¯à{rðÎç@«¥žƒw>G7ÏÏäÈy~x ß“Ãê¶Ùp@ë9,7ÔæèáJšw>GWÒ¼ó9Ðþ¨ç°š 6Ê,õ¼ó9`ˆÖsX›£‡¿hÞùF_ª;ï|ôªê9œE“­‘z§eerôp%Í;Ÿý‘z«Kbs 7RÏauHl4Ôê9xçs ARÏaµIlŽî¦yçs kWÏáüšh—Ôs8Í;“£‡jÞùèÇÕsðÎç@§°žƒw>º(õNÃÒüٓüó9z¸&æÏ‘€Zç‰Îô£‡ÛjÞùèSÖs8¿¢&Ú-õN»ÒäèáÈšw>GGÖ¼ó9z8²æÏ.L=‡Õ‹±9Ð\­çàÏk=‡Õfµ9І©ç°š16Z0õV#Ææ@û¥žÃjÂØ=œoóÎçèá©›w>Z.õVãÅæ@»¥žÃjºØèzÖsðÎç@g¥žÃê¯ØÒnÞ“ƒw>:Ýõ¼ó9NÙœƒw>zõVÛÅæèáO›w>GÚ¼ó9Њ¯çàÏqÂæ¼ó9$_¶'ï|Žã7çàÏM=‡Ó¬79z8ßæÏÑÃù6ï|Žηyçsôp¾Í;Ÿ£‡ómÞù=œoóÎçèá|›w>GçÛ¼ó9z8ßæÏÑÃù6ï|Žηyçsôp¾Í;Ÿ£‡ómÞù=œoóÎçèá|›w>GçÛ¼ó9z8ßæÏÑÃù6ï|Žηyçsôp¾Í;Ÿ£‡ómÞù=œoóÎçèá|›w>GçÛ¼ó9z8ßæÏÑÃù6ï|Žηyçsôp¾Í;ŸOõ¼ó9zxáæÏ‡ªzÞù=ÜqóÎçÀçV=ï|Ž޵yçs ‡UÏá|r™=GOݼó9z8èæÏÑÃA7ï|ŽºyçsôðËÍ;Ÿ£‡_nÞù=üróÎçÀS]=ï|tÆê9œß:“£‡§nÞù=> ë9xçs sVÏá<š=|wóÎçèá»›w>¡z39 ›9ßæÏÑÃÕ6ïœ>AQzgõZ?VSGÇÚ¼suXÍή毣‡‹lÞù=GÇÚ¼ó9ð}^ÏÁ;ßמ{žyçëèá›w®Žî8÷äàÏÑÃi6ï|­=\dóÎçèá"›w¾¯=÷óÎ×ÑÃ36ï|Žž±yçsôpÍ;Ÿ£‡ûkÞù=\[óÎçèáÚšw>G·Õ¼s9’Í7ZóÎ×ÑÃ5ï|Žþ«yçsôð_Í;Ÿ£‡ÛjÞù=ÜVóÎçèá¶šw>GÒ¼ó9zxæÏÑÃ4ï|ޤyçv•Õ5îžEçÃÎÔÑÃ4ï|ŽÞ¡yçsôðÍ;¿;{8+毣‡ShÞù=\7óÎ¿yçûÑs§4ï|­h!×kåÏÑÃ?3ï|Žþ™yçsôðÏÌ;uz8s毣çÖkÞùùèá˜w¾Žž{°yçsô܃Í;Ÿ£gÎÌ;ß×Ίyçëè¹›w>GÏÍØ¼ó9znÆæÏÑs36ï|Žž›±yçsôÜŒÍ;Ÿ£çflÞù=7cóÎçè¹›w>GÏÍØ¼ó9znÆæÏÑs36ï|Žž›±yçsôÜŒÍ;Ÿ£çflÞù=7cóÎçè¹›w>GÏÍØ¼ó9znÆæÏÑs36ï|Žž›±yçsôÜŒÍ;Ÿ£çflÞù=Xм󘠇ïeÞù:znÏæÏÑs{6ï|ŽžÛ³yç1AF1ï|=÷ióÎçè¹O›w>GÏ}Ú¼ó9zîÓæÏÑsŸ6ï|Žžû´yçsôܧÍ;Ÿ£ç>mÞù=÷ióÎçè¹O›w>GÏíÙ¼ó9znÏæÏÑs{6ïüêášw¾Žžû´yçsôܧÍ;Ÿ£ç>mÞù=÷ióÎçè¹O›w>Gþ«yçs ñ]Ïá<1›=ºnæÏÑsW6ïüœ¡á_Ÿ3«íoëÀ/v½ÞùÔÖs8_³&G>œyçsàC¼žƒw>GN¡yçsôpvÍ;Ÿ£G‹Î¼ó9zøÁæÏÑÃ36ï|Ž®€yçsªç°1;¯=švæÏÑõ5ï|Ž„yçsôèÞ™w>GÏß¼ó9z´ñÌ;Ÿ£‡oaÞù=ÚxæÏÑ£gÞù=ÚxæÏÑÃ!6ï|Žn‡yçsôèç™w>G~žyçsÈãÅž¼ó9ÐÒ¯ç°û6žÐë9xçsôhõ™w>GVŸyçsüÍæ¼ó9þzsÞùµ9ï|¼õÕsðÎçÀ7@=‡õ`sôhšw>Gv yçsôðuÌ;Ÿ£G;мó9z8èæÏÑÃû1ï|ŽÞyçsôð~Ì;Ÿ£‡÷cÞùr³³'ï|ù"Ù“ƒw>~Nê9xçs'Ý9xçsȿɞ¼ó9ä{OÞùŸÛœƒw>ÇlÎÁ;Ÿ£‡ÏdÞù¿·9ï|ŽÏnÎÁ;Ÿãw7çàÏÑ£+iÞù=º’æÏÑÃÁ2ï|Ž]IóÎçèá„™w>G—˼ó9z¸\æÏÑ£+iÞù=º’æÏÑÃ÷2ï|޾—yçsôèJšw>G®¤yçsôèJšw>‡¼YíÉÁ;ŸCþ÷äàÏ!ï{rðÎçèá±™w>Gͼó9z4,Í;Ÿ£GÃÒ¼ó9z4,Í;Ÿ£GÃÒ¼ó9zxuæÏÑë3ï|¹RÝ“ƒw>GÎ¥yçsôè\šw>GÎ¥yçsôè\šw>Gмó9zôQÌ;Ÿ£‡ hÞù=\@óÎçèášw>G¦yç9=7QóÎ×ÑÃ)4ï|ŽN¡yçsôp Í;Ÿ£G/Ó¼ó9zô2Í;Ÿ£G/Ó¼ó9zô2Í;Ÿ£G/Ó¼ó9zô2Í;Ÿ£G/Ó¼ó9zô2Í;Ÿ£G/Ó¼ó9zô2Í;Ÿ£G/Ó¼ó9zô2Í;Ÿ£G/Ó¼ó9zx¢æÏÑÃ5ï|Žž¨yçsôðDÍ;Ÿ£G/Ó¼ó9zx¢æÏÑ£—iÞù=z™æÏÑ£—iÞù=z™æÏÑÃ[5ï|ŽÞªyçsôèešw>G^¦yçsôp[Í;?znÏæ¯£GSÓ¼ó9z45Í;_kGÖ¼óuôènšw>Gî¦yçsôènšw>Gî¦yçsôènšw>Gî¦yçsôènšw>Gî¦yçsôp‘Í;Ÿ£‡ClÞù=ÚœæÏÑ£ÍiÞù=ÚœæŸû\nÞù:zô;Í;_G¶™yçëèá+›w>GƧyçsôp¬Í;Ÿ£‡cmÞù=kóÎçèÑø4ï|ŽOóÎçèÑø4ï|ŽOóÎçèÑø4ï|ŽOóÎçèÑø4ï||CÕsX?Q6G^yçsôh¶™w>Gž¨yçsô艚w>GÖšyçsôhŽšw>Gæ¨yçsôhŽšw>Gæ¨yçsôhŽšw.‡ñäÓ‘Jyçwp·~žÉ‘ëç%›µKÍ;Ÿ£G»Ô¼ó9zôêÌ;Ÿ£GßÔ¼ó9zt Ì;ß×óÎ×Ñ£ojÞù=ú¦æÏÑ£ojÞù=ú¦æÏÑ£ojÞù¾öÌyçëèÑ@5ï|Ž TóÎçèÑ%5ï|ŽÍQóÎçèÑ5ï|_{tÍ;_Gƃyçsôh3˜w>G6ƒyçsôh3˜w>G6ƒyçsôh3˜w>G6ƒyçsôpôÍ;¯×Ò£s`Þ¹Æ7bwç'ÑÖÑ£+`Þù=úæÏÑ£s`Þ)Ç@roOøò³ïµé–?[žuŸ6œÃ®þ ëUW\hõºY—c±*úkŠmÖ_×±Cûs]#Uq1Ê`mc¸}Û+• •Å ®\cÐò*Ža‹ „•ÃDˆZi[~ õ$ä«”ÖÛšëg W ®²-\¸^·p…ƒQÙëÖÿ ÔR (•â²T@Au0×ÐùSG|Ch:®‡péÁÙòzX î!°üPIk…=òa+ʪ(2¶‚²Q˜m… †âz+ì;Tð‡ÂÖG(È×C©±‹k(—ð"첡0¨˜ºalÜü “ËhýrÅÒ0®½8ó³g‹Ã\G€ÌtŽ€Y_¢'#¸¦”Q“AmeòŽD£Ìä Uæú:’^–aÿŒB-¤ÌŒâZVaF1“æ`?j®°eöcÞ*Ô¹}©0£Ù*jÍu¤0&[}ß•XÇûsyj ûøk€i1†ú¨u ×ÁFØèc™×FöÀXz؈ªÅXzÒHŸÇ®ÆÝ ˜Ícÿ*ÂgL2Šà§Ýê%:‘ʈ¥O«â˜ª¢]\T* ‰TJ,m=´¬E6oËîµv|B•.“ÔjÑhõþ®erk¬8žt î©î!mT5ÛˆELm›nÚBmâ ˆÓ&nަ¤MüHMò8õC<ãqìϘnŒƒSÃæÑï5F§f<옉;€[IÌ}ô@º3i‚·b&ô@¦0†7v wÈ„ :Á,ãÕEéIg‚ÀœãÙ*à÷ñp<¸kއ¯Çø m@õé úè 6¼¦ƒÈ ßó x˜lƒàü‚F_§À=­9as¢ItÝ¡C¸y¡7v¼06àtÐQœ†DßñP66—‡r¯BÛöPxhüOä-¾ &¢ë€ßЉÌ>9&Â)`N„OSd³Nbóà¥f[E“˜/üúM–ooõy2›ß“és™~MAo¢LmSÐþ-3OS¸=”©a Ü€2}œÂ,–ÙLS¨­Œ–ÈáÌa™ù=<oœÃ_*{ðfãü†}mò|ãh‡šs¾‹¢ý‘í2Õv ¼[…ŸÑÍàw¸.ÎÚ*‡kKhê§ ©›SÅîÖ¶˜Ë Ü3ƒ«a ^™ Þ@ÅêHXÀà™#aÚqE?V9¸¦„Ët·3}Lu;¸Öc;û•Ÿ9LS;ÅðË<:‹[‰£aÕ0}Ç·h£Ãôà¬æúS¤ÇМú[·BóÙFe¾Ò‹2û}3S&ß"rU˜ÔÅà€ [á86VS»ÖE½]c¿¾œ¦kdKœÈ72ù'±…ɵ”+PoOß4±½N¡_MôïTÞ÷W,ã?ú}Û·“|ýhfÒ–ÓÏfæf¸°™þŸAmÍä=ƒ¾5Ó“3é}¶ÁYàþôç,.7ý™ã³`ì÷§î³éCê9› wæîl6ìæé)à“ÌÅSÀ}èÛSx;€môT”j²µŸÊ $þ gZ¨ó¶æ æd×ÇAÌÇ:¶Ù ê]Çì¢Ï똳AÌÅz6Ï`zùLjƒÙ¦‚“Z™Ã°Í[™¿‹™¿V¶éÅÂˆÚø—°I†2‹—°ETÙ ~F}›Q Æüm¡¦aäßã}½”m=Œ7—‚ˆÏ.eñ.c— §?—QËpvÙe¼NÞË™ G°GP×åäAŸÃvÁÜ<‡]3‚>>åÌåsé÷jx.ÌÊ`ùçÒû‘ì±ç17#éçVú0’ù{>xzù¯D©|ù¶ÁdÅ ];m?zq5L¿ýè×5 †ÑôåàÕÑÔ÷BÐÅþôõżٟÙy1ûlæïÅÄÆ°O^Bþ1ìË—2 cÈóRæx sx-Xw,Ûþe Œ±ôáåàØ±ÌÁ+ègýy%8÷¬¯bS?^:Çþx-—òq ¹×²ÇQÿëØAãèåë`\Àœ¾ž¾ÀÞ|={íúz#,½èù0Û$ÿØ'‚‹ß@ÆÓ×7æÆƒ–vq¹Ov1ûãÙ[»˜•ñ ]ÔyèïÍì·ƒèã›Éwï4uóÿæì`úüfó`êº •ªƒ©û&æóöÛÛØs‡ÐŸ·1‡Ðó·3˜•·£v1~ÝL?&°;ÞÁU~µ¾“{Æ¡Ìó»¸"J?nÕÊ\ÜB?'Ò‡Ÿa¯Ldßü½˜ªü9vß$êÿ9jžDžå0‰ùøyæpy=9™7·Á*žÌý"{b2¹~‘]yûã—¨õ0°Á/±£÷¿+ÿ0úø^pÂaä{/Xà0öÀû¸TOa?¼ÜSèËû…ÌÔ·÷Sßfýý À)ì‡÷púp;õO¥Gä^3•¹ÿ0s<•<†‘=•øðob÷áßq–àõô]B`1sW¨%úNÕ¦/Ô‘ÈpÏ#¹ôú»ï=î­¦ POôfEzYXJôí.Š'ÿuDßæ¢š‡BCº m—ÂKxûV÷V½)œHô&Õt—6:5Ô=—·oqo…šò·TÁ%Ü`È~º*m$ÓO+ ¯!úf¥3Ýå¢ÚW…¢orQMná¥Dßè¢Ú…V¢7º¨¶x¡èë]T8¤ÐNôu.ªÍWè úZÕ<‚9ÕE+D Ëé¶áýGࢂ.Ý #~wH5J=¼C×F¡ð;ä@»à1-4¿wˆÅ§Ù¿CŒluâ)^hæ?¢ „æ?¢;Œfú#º «âˆ…¨½ø1î5E‘fù—©)b/ü²˜¹Úƒ¿,†“°Ì/‹1®‰úe©âh’?ª«°vòGÙï\[>*<­Éù(ocús'{•ëËì˘þÜÉÝ-¦?w‚bö×à˘é¼|ƒÃ~…;\ øÞrùðUL_~…½ÇŽùö÷qˆ™Þ1\k>F?cúó1î1ýùW 6ÍÇP ˆéÏÇÀ/ ýù¸nXêÏÇÁ ýù8ø—ã?såù85Á¸ø881a~îR>ÍÏ]\‹¸úÜ¥ëæç.v,¬¦»À)\~w°\ÅÝóWuŽøUþsúU]‡„ƒü€jÃ'tnø»%•OÀA%çÜeÙCŸ‡ nõ ðªdŸ¤wlOrWäÎðIíFá¬Ojª†OÂ"†YøIö'þ·¦ÿsÒéÐý¡ôî´þPÛZUÿ¡®GÚ:Ÿ×vÔ$}^ÝѶù¼º£)þ¼t9´u¾Šb~+r J¸‡ÿ\›¾" _<ÅM‡*¯½w^ÏS£{¢ép}úºø"š²¯ƒ”Èûç)/®ëÝÕŒN£?z¿ÚÚß7ÄeRÞoÈÇ„&êïWÆùÿ^œ4WÛß랪MóÒmÓdý£øêÝ?jsª’d±Ùÿ‘ÍSË?‘‹;ê?q)ãŽúO\ÜØØßâb³a¾Eþ˜Íò-.J ›o¡M³¿OÁ·4 êï·Ø†ÜW¿Mm 5}›úñB‰ÿq6ñ·éEB}ßæ‚ÎEîÛ î­ßæÒÆ%î>úɆ½O—8ÕuŸ6óÝQ–n‰Ú¬±ørÂ~±8ïÚ¬±tò€Ÿè J-Þ™9Æ‹ŸÆ…IŒ„øiÂ_“ù^ú¡ñÓto]e=]Hm)ßlä­QÖ.ô³pßšØÂåQÖpÅ?Ë·6’6d<œ½ ;m¼+—Âušíf.Þu¡#d3ËîËf–®ÀÕ°xOúxéØ(CIÀFí†S'‰1ÙÂ7ÛG¬=2“ouJôøRÜØe=Sxøf,º÷òÍĆo©dh¢ãg±cã½ùÖ$‰ ?‹iV‹ŸÍ+®ä[»=^eíEÇ…Éâ½@átt¿n{¡a·ÛÓÛk?ß§ý¤L0‚oM†\çÇ{Keq>ßlÕ%QÖ>R#=;Ê:P»_u(Õ(õíÀ_ÇuŽÏïßv\ú³Éñ[2>H·aõq¼Xüªo¼ú¬þ—úؾQ`Ûe,l«ú{ß°›oä›»³æä Kãºú[‡ÒÑl±×hõ­ •;‡šæ‚886švá i¯izÖåYSx°¸Ü«ø&³º{°´vTýÁÒÛeª·ö wÿhßðNoáûʸ ‡¼ÊUjæß”Èy2›.ÝÙ,ííP:‡HQA{ãÍ™:4A_ó7AS¬ÎLPg®‰²Óå]ó~¨”Eoãe¬OñÊÏçøiÓM"(ò-… öÇ$œîÆì¡Iº©«®Iàqaûx$s' %ˆiëž³!ã]Â~8Œý$.Qü\Þ kÇEtS˜:.bž…ã"nlöÃé¾ÔÐâç¡ö!¥»x<Ìj)/ÆGOÌ‘3Ý^ê£ÍÉÉå‡|³¥Dåfc¶”áTËl©ÚMˆ²&êÞ¢^Α"ì<¾¹·hšçJñX»dž”55½óÄD¸)Ê:’ë5%¦©«é¨øÆ)N–j9Z,Kõ÷h1_5GkCY­¹T-GkokÔF8ZhSµÍ—"¦6Ã|õB{|¾òkç‹ñ¬yœ/ô)2_õ~…oT^¾Î·î BŸq©æP=œÿ³¸G ž*¤X߯ò+بål‹(þ¾F϶(ü˜´¼g†\oˆ©§Þ.Šz»@;\»w”ú4ËÇ óhÇ+<¯ž+æì6¾aðk÷«{•z~¬Ô]´Ž•r˜PÕBm¹;ù†I*T·PLtõxáÚ¸w /Ó!ßÍôŽ[€qö6[Ìo>Ý,ÔÉ ÓdÊ-f Ëû*ô`ûºPŠ|êë"͘vÚ"msa¬EÂB…Ç©¡Âãå[ý8þ¹Ê\ÐÖðÌWÉñÚªäxé-j2–ˆ#©ÉX¢I:Y"½ƒsøææ ²Dø@“±DÛU¨d‰4ý4ýK„+4'ˆ÷¨I8A¸ZÿNàRŠ;]$PÜ \œÙ¾'Â`ÚOîÖž ¤„¶ûIl0áôXÌ]ÔâcØBÂçñ1ô‰í¼î¤.iñ,n1[e)z.º¤Å³ØNßô,ÊfëŸÌ=E—´x6>ù’gsÁb‹ŸÌÆ•Þy<[Û\Ûí]¼T÷)ÜZt½çˆ¥úO­ŠIÏáŽÂ–?•þH÷-ž«;€ê?æˆøRñ\]¤Tï©lýháTôÚÀí§2õºÎÆ•ºL©ïˆÇ¹l¿HL)îLÙ†`“Ú¨öv¾!-JÕî½)J95š¹6WZn«E9s´;RX¢èá~ÏŸÊžY­8WD.c6/Wè"ýpyuë0×]Õ…¨(ŒnëMñýibüksœ¦[­&÷4í"mˆÓ´ 5I§é^ ÝyºÔbµ;OVÑ$nxàtmá€åtVœx>]Ž©g9W/]¥âùt¼¶\L9í¶å\\b6Ôrpˆ.;ñ|&X·Ùx¾.?ÚÙ+´9´‘Vp‡csÀÒe'®oÄìèp/cê=C\Rá³3t¡Ñf:C\QMêpØgp_H¨ó šn«ñð¹.;ñq0quKƒC!ÎU|œð ðΙpMØg²ÙØ gqžrÿŽg#œ%.©6àY` .8gqs-°ùÎÖf=›u¼u6»\·ÐxKÎÙbhÃžÍæÕ &^Ä@îŒããuɾzŠ˜xºð›½œÉÅ'0¯bìÅ'ÀI*²!ÏaîÅ!‹OPýš‡s¸U‹C¿ˆ¹ÜŠ_‘CÑøEÌ‘8­ñ‹¸É–@OQȹvü"n­rs¿˜9’KõøÅp¡äô:~1HA©ã3G%úÿ æ´DÏ`O–˜ç•lúu®ó•Ù#+ÙWeöÇJ8«bÆÕôMÜ×¸š‹¡˜ñbðª˜ñb.žeæy¶òY|‹3T¾„o]ÌÊÌ×*M™ýq.{µÌþ8|\a_˼VØçrw®0O籪°? ÆW¨÷<6o…>žÇu³BÏc_T˜çó@ææ<°hœ¼šu…>®foU@«áši½ÇµâÌj_¬»7°/Ö°Øwk@: ôm Êw ôm-ƒöÂZ8 ÌßZ°«Z'¹Û7ÒóÙoôý|nìôý|O#ˆç|0d#÷‹ àê6Rÿ¨517€›ØWë˜&æsÊMÌç:îòr/c>›Øëéoý[ÏG/n`¯4±‡Ösinb׳§úˆžÉ¾ïǼ?“½Öù¾l?æâBT?æáBú.N_|"óׄ·9îÇþÚmæÆ±ŽT3ýÛÀ\6Ó¿ ìñfðÆæ®™>^rj¦±OšÙÿ1gÍôå"ör3ó{s .`ÜNhf~7ÂQèO7r—ìÏ|mä.ÙŸùÚ(ºêº˜{QößÅ ÂþôûbpöÁÅpÄŒS`ìþÔs1ûª?óº‰=ߺ‰;‘`RÜ@]›à+  ï›P:@}›Øèÿ³ØØ÷Ï¢¯˜ƒg1w˜ƒg±'0Ïâ61€ýp Ü”ÌÃ%p[0×—(öû%\ÄAŒÛÀ/ZÁqyÒÏÍ0m2¯›AÚ©w3÷ÌÌínÙ[¸@¤Þ-Ìã@æw ÷ÄìÓKiÚ@ê½|8½z)ýÈÞ¾”Ëô@ê½”;Í@æñRîq-àˆË¸`·Pïe åî6—‰W/üpû¸…zŸ Žk¡ÞgƒÐ[˜Ïgs%oanžÍŸ…¹y¶xöÚ×—3WƒØ7—ƒ¬±§/g/ÿ<—Ký æá¹Ìÿ æá¹pW±ßž+.¥æùyÌï úò<ðá æïyÌù úó<.½ƒ˜‹ç±Ó§­ ‡8–q8j0ýÙÊU~0ó7q0sð|pì`êx>8e0yŸÏe}½‚yÂ]ÁÝn—‚+À5CØ·WÀ$¹’½0„>\ žß?^‹b{åJúÓʾ»’yoeî·¡~ÑÊþÝÆå´•ýµûZ+ûkLVæà*ò¶’÷*ú7ºš½7”9¸š{›nßñiÌéPöìvNC™Óíôi(ûv;ûwó„¸Ò0ðÈ5Ìõ0úx €dsy ó/®h|:\¦aÌý ‡Ã˜÷°·†QÇ à½ c._@Ÿ†Ó€S†³_nžy!8l8ý{!̃áÌõ ÁSÃÙ»/¿‹C¿¼0œ9øk8óñ"x1Ù׆ÓçÑïÌÇ‹ØO#˜?FÐï;Å1×0W#Ø‹;èëp÷8D#˜»àþô¸røl¸uû`wüìŃoGPï‹abŒ ÎÃàI/¦Oâ¤Æ¯bÿd¼„[ÚHêz 8j$}| xh$}| ¼¨‘Ô÷%#©ë%ìé‘ìû—‚kFR×K™Ÿ‘ÌÇKÁ)ÒIˆ×rñɾyœcXâ×sùžýÅܾ\4Š=óJpÉ(pÄ+™‡QÌÝ+ÙÏ£¨ó• è(ê{%L—QÔwûF: ñ™àèQôï:öü~Ìßuôq?öÑuàµý¨ï:æq?æùzæv?æåzú²ór=s½u^Îݽ{=ød?pËõì‹ýØ£¯‚ó¼ûýUàÖýÀE¯×ïÇy}ŽCüFøûÑßW×ö£¯¯fžF³?_M]£™›W³WF³?^ ‹EÜÜøÍÔ?š~¾œ6šº^Ãýa4{ä5ìÉÑÌÇk¸SŒ¦Ž×€#÷§7ÀÛŸ¾Ý íá¸ÅîÏ|¼–ëÒþÔóZðÖþôéµàˆý©çµÜög®_ ÎÙŸýñ:À°F7~+{ {ãupâÆ0g¯cÞÆÐÿ×ÃÆPÇëÀwc˜¯×s÷ÿ¼9üôz.rc˜³éÛ깑»ÂXöÃäK=7‚ÅŽÏáÞ3–½ðê yõŽe¿½çuc™×7€Dz·ßÀ\¥Ž7€ÓÚ˜Ó7Òß6öØéosùFúÛÆ¾ým£ž7Ñß6öÌ›Ä9V=o¢¿mÌá›èo{|õ¶±wwQï8öÕ.q’µwwÑßqà]ôwu좿ã¸Ã¼™¾cß¾™þŽcß¾<1ŽyþiêG=?ͰŒü4}=€z~š¹<<ðÓä?€zÞ¾>€=ø.µÐç·p>€yy ÷„˜ß›8À>º‰99\t|†™—›À72/7IB}~+8ï@æï­àµÙÓo…v ó÷VöÐà‹·²d/¼ r ýxûo<}}œÄñôãm¨ÎŽgNÞ^Ï^x;xg<{ìíìýñ쯷s—Þz;¸h<ý½™=:žþÞÌåx<{òfî/âPÇÑÿƒèÇ;¸_Äx÷”ƒèÇ;رWÞ¾?Üðq¬5Çïàžsûàôã æøÜ7¦¿ï„Cx0ý}'ŒƒƒÙWï‚ÿs0{ï]àôƒéÇ»àêÌÜÞn<˜~Üž?˜ýy ÷¬ƒÙŸ·p';˜½w ÷ÆCØŸ?C?aþ xíúû3à„CèïÏ0ׇ°~†ûå!샟å,.wüp‰¨ñЗ;þ{k{ÿgéËöË»¹ˆO`O½›;ÏúònØ£ïæ.6½ÿnæ`}¿•z'0‡·rš@Ÿn¥Ïâ€Ç—pãÀÞÊEz}º•Kú¡ì‡ŸÏÊžþ9î‡Ò÷Ÿã¾t(ûæçШ9”>ýû%ðÞdæë—ÀÁ“™÷÷‚ &³?ÞËL¦®÷R×döã{©2ûñ½ÌëdöÇ{©o2sð^qÞµwß ^G(þî“™ƒ÷)¿öøû˜—ø ¾ûöaÌ×ûØ ‡±wßÇ]ï0öÀû¸w®?{DÜøø2˜‡§ÞO‡Qßû¹ãÆ|¼Ÿ=ru¾Ÿ»ÃaÌñèûa쿈;¯9þûh õ}€½=…}z;w¼)ÌÇíàº)ôïvpäæívpÆæãƒÜ‰¦PßÁ™âÔÇŸ„1…þ}¹ŸBÿ>H½Sèßá³Nÿ>/àpêûûûpú÷!ӿÁ³:œþ}\x8ýû¼ªÃé߇ØS‡³÷?LgŽ? ÏêpæøÃࢩÌñà¡©ÌñÜ ¦2ow€G¥w¯çNeŽï`¯L¥OaΧҧЯ©ôé#âükŽ?Â^žÊüþ2ó:ýúQîÓèû¯°7§Qǯ€w¦±ÿ…»Õ4öþ¯ÐÇià¸ØÓØãŽ:~ FÉ4ð\ìéì½q÷›ÎÞ‚‹=½õ1ðÁtöÀÇÙ·Ó™£s÷˜Îø8wˆéô÷ãà–éì™s_˜¾ü8{n:ûå.xÁÓÁwÁw›Á~¹ ¼7ƒý{|{õ.î3؇w±çfÐç_7Ì O¿ ƒdûúW¥ó¢º~<6ƒyÿU˜*3˜Ÿ_eßÌd~>NœÉ\~‚½;õ æl&sù x 3™ÇOPçLðÅ'¹ͤ¾O²wgRß'™§™Ô÷kpñfR߯³f²Ç¹›É\üs7“¾}þà,úöi–ù,æâÓô}óði¸û³Ø+Ÿf?ÍbN>Ì¢¾_§®YìÅ_¯Íb_ý:ûh{ü×ÙG³Ø'w³¯f±Oî¦OGP×ÝÌñÌÿÝìÃ#˜Û»Éwûä7˜›#èÛop<|ûÔ{ûä7Ø+G0o¿Á^9‚}ò›ðŽ`~“}~ûà7ÙçG€c~|+hy$sü›ìõ#Ù¿þ×.þ:w‹#éÛïp<’¾ý}9’¹øpê‘ÌÃïpÿ8’¾ý8ûHúö»Ü¤o¿Ëý®yû]ðP;óö»ô«º>ËüµSÏgÁ=íôÿ³Ü…ÚéÏg©§½ò{ÔÙÎ~þ=öúlöçïñ~6óô{Ü·gÓßã¾6›ýò{ÜÏfSÇïq›M_~Ÿ;ÞlöÞï+ŸúñûìãÙÔõûh%̦ï@?gÓï?àî:‡zþ€;îðËP÷öéçÀ‘s¨ësÜ…ç°¯>>œC>‡†Âêú¸rsÿ9îçs¨ëÙÏs¨ëÁms¨ë¹Ïe¯þ!<–¹ì­ÏsšË|~žûå\öÖçÉ3—}ÿyî‘s™ÏÏ3Ÿs™£/à¤f.sôø1sÙ‡_ s™Ï/0WsÙ×÷p$›G¿îÜÎcŸÜÛ~}º‡;À<úÚóèÿ¹3Ì£O_¤/óèÿ¹×Îc~‘¾Íc.¿nšG¿þˆaŸG¿þˆ;ÀQÌ×±ŽbŸüûì(úöGÜ'ŽbÎþˆþÅ^ücöÕQì—?fÅ~ùcöîQì«?æÎrøóÙûG1 Þ=йÿ{øhöÕ—¸‡;úós4ýÿ¼‡£ÁÛ_‚ßp48ãO¸³Í^ýæõhêøîDG³¯þæÔÑôíO¸ÃÍ<ü)¤—£™‡?¥þ£™‡?e~aOý)xåæ÷O¹ãÃ\ü)øòöìŸ1¿Ç€;þŒ{Ð1à·?ãN sügìÕcÀ3&=&á¢/3—Ç€g¾Ì^=†ýýeîœóÁ Î~3þçʘiöç/ègšéÎjYažç]C+åy¯ïéùSAá xQ£‚â€a­Z˜júq4SX€ç–),“äQ2eª"Ï4ûs±55é!Ư&ñ/èL³¿oIMô_H—Xé/˜˜e!um€¿ü|<ùUTü!Á¿v%Á‹ƒWj'@UD—_f,jWõWÄãVô+r ¤¹ÿŠñ¿"­ÍÝ_i†4וˆ«ü«Ãû«„mz›ÎU¾ØfÐUùWÒtPoÿJÚÜÚâ%¦©¶Ö_‰®Þþµü) Uüµx“ÚrCÞä߈¯mñ7 Xð#¶¼ºô7R*Qþ{¹NÊ¿Wì9¡{Ù2RJŒoc‹Älí¯Šb¤íõU±á´U¾ Úƒ÷Uæ"aë}MüF¡Ö¯q=’ÞAüSãM~ 4"݃ø§l!Øq+=m©¿•ÁŽû[ØgÒ»‰ö©x*þö "¡åSÛµ6L¢²™˜‘­&ñëòõ#ñuIT©×_§÷Ìÿ×¥“¬ËÜ×Åñ׆üúWâš¿þ­þIôu=Ç×\Ò¾±ÓŸ2a¿!¹ªü†øËªòR\U•ßÊ¥ªü§Êo\Wùïl®ò²û«ü;15ï§j5_'ߘB•§j5W§ý§9üû×ÅUþý[ÄÂÌ«Ô ˜*7›:«ëï¥,§‰ù{ù Ñ^ø{)娋ߤ°ç¿)/TB ÿ81®ë§÷wÏï§M~wåœÏ´{ÿ(^´º÷Ò$P÷þQšêÞ?ªzuïŸD»ú'8DJß55®ö[³ú»èwî† “þ-Íšêû–øÌÚrß’ž¶Íd¿-ia5Ô6àˆÞÇ–-wŸ¶›0×}wÆõÞŸÝ_/¸†zϳýïê½_î?UÇýr%ªþÝÿqËÿ‘þü~:VõMsâíµðM¿fòÔ"¾ág/‹²³ÄÚ=‡o6×¾Ù-ø†e½•o”Ovð ‡v'ßè튲cº[ù†{߸¹;Êv.¾Ä7Èç›|ë6*vu"WâÊ&r)(TÈ™¥¶~"×åR=IrÁ®R;Iò˜ké%y`Uqb)'jë'ybA·EÙùÌ»8°I¾4 6EÙR1¼–o¸®ÊÛæÇ5ÆÖ’þO2LJZíQöS´Õ¥kÐÈm@\Öd'°µt~’è§8­‰4ü ô³7qU“§R’œâù¡™ì æ—SÕdgéž*_MŸæ@¼<8¥‰ÔOä?yš8¢#¢lxuè &»ps d²‹¸¡šñ×¢¼sø,]‰p êês óY¢o-Üš çWf' â¦S¦Oƒ¥_¨zÓç2ysK*“gðn$ÏÌuµD÷2­’vGŠ Kòšš±û3L *0{ÄmRûK`–±y’ByšÑÄ BÖ ‚hþ¨³#ÊâŒ(ÓÎ)ÑÏ·;…œÛßï2D—;‡ö÷ÎCâ7ït¿ìo,úg¼ëÔíÆo>(ζ«çߊ߼CqÜ›˜ëœCû»ÅÔ~nrqynþ›øÍÍÎ݉ý½Mªazó6i€¹<—¿¹¬Íu•èošRÏ€] .û®eÒåäLoÿç8ÃÛk"û ½ e åqx™R<#Ç©°»¼Cä D9†HÓA9†Üç—/Í1Hs¡ƒä:C9½/Î1HÚ.G‹¶)J;äh±Þ¶8åoûÛ4/~³éDá ÓÅTÏ6Vm^ÏÖ÷ôíÖSã*Äõ}z Ö¢§nN8‡9ö7Z6Ê1ZJÊ1ú—qŽÑRpµ½í-6èpÄq ÍSó¾â^ DS{aAU_ ÷À†Ë^  aœpÜÈ ü9ÕrÐ47²Ü9j9¸öÔ^à™©V³ÎÆÍrÐqu>ކϪm¡hU Âcs$¼`Ö#3Ó•1Qö~ûÚDŒ²÷ÙËbBF£ö°Ø8vñp‹eï¶[¼Ÿõ^ ¨¾ÁU|µ8M¯èĨ­‡¨>®»ä +¹îà4 ź£Wzñç.öLWW´a–H!WÕp»>RÑÖô!Ðà£:fU1bh´L²Zq9†ÖupaáÒÄΫr-àZH(óŽËZH¼£Ï8¹#FQÈ%F=L1rÍt]4šiÑ8‹¡çs„ÅЩ9Òb¨µ[Lœƒ™˜ u^_º]èëoÝ—˜ó¦ùE÷ŽéÀ}”x”ºP±·P²XLÝtsÏt0Ãà0:0Ûå¶@%|t`n\0oAĶ_uµ …š>ØYíêb’ì¥Ähg˜Zx×j[ˆiDŽ«€Ð«"8tá5d´£\~£–d±€ò€Á²­Fæ?²=²ÈU"õ{Di\¦¹ÝHŒÜÜLüŒ£êBŒ_j³ÆŒs·Á43Ædgè ¨ ºÐèhºj7ÀÜëE‘. ‹møç3q¡P¥ƒÃ21ªãâAŒ "ÔO—iƒ &¢ëÆ m 4µÉÁœ¢;EŒYÄ£1Ý·T©Cˆùl€¥ñJb§ê©iÔM{ÑåÁ#žÈ6¸=ŠJžŸ!\Æc†p¾GŒ9Ãu1êåVCŒAìÁϸÚϳä÷'Ž ˆÑ}¶„ߟL¹ßŸìW¿?q•à÷'.ˆ±?Ñ"ÆTp- ÆTpkð[—àÄØ^`_bìœ<ãÎ…óbL%×bLؘºch±cJÐu!Æ €á‰Ñ_.•|¯‹rLÙúšh§,í^Ýãc¡ ]Êc! 4€@(kÑU1µc¡4ú@bÊÅB \ñè´®H±Pµ®Œ±ô„t#¥ä$&'*‘nÞ\ÐÐbwëvK+‘k®!¾ Å4Šå37l[1ÿt“̯¾Ù³Òu)ã.–ê•”VPÿŒä*ÿb¼ÆºÏêŠkÓŠ‘‚>b$@6¬®X±¶+W86+J3L 5lTT>Ù¦h±…àu«×iEßìAÔFÙbÊÄÚb®è†/9^}³÷¤ªk牡KÝ —L§˜3±öœ_±®ºĺDêkbuÕŠµÕ¸’²Ñt­ˆµÍP)eŠu)2G]ÃŒ\‰îç±¶ÊzL´˜·±¶œ6ÚMl+®‰l*i,ÅÚRºˆÇÚPp ØNºÖ¢–qý‰µ•¤ k#‰)k‰‰ˆ{ƒnH¬-„‚H ßXÛG× \DÒvdëˆkãèúk۠Ȇ×”ÜЈÃ8–Ç]]céÒ‰™„fU,•!] cy2A5B1ˆ¤E0écùBSÁ…e T uÍ4ò R\‹Å)Ñe(ÛUW|¶ TÆ…ZÈ#–´'¹ˆs]EÍ3.dBm±üÆåź”ãbž‡ª±¨+–?¡ðX^!öXüTgñq#ÄËžð#üËo¼¼éGÆò±ƒ:-žw„¿b)•é‚mÄu$–ï¸ xôá:ÌeY·´/#)&áH÷™Xj„\ñ¤›ŽQüÕµ'–Ú^PÞŒµÃ[ì0¸ZÅÚb‡qÅb‡!7ÄC懦‹C¬†Â; Î ; yv˜ðc¬&þQ¬&t…zn,-0vr*ì0dNØa(ù±ÃpùÀÃరÄÂÐòŒ¥$ÅÓE Ö&‰µÃPïg‡IÑ"ÖC¾&k‡qg‡é"k‡!;ÀÓÕ6Ö‚ÃA #(Öƒ}ÀC[”&T‡Úo,î ; …JvZeì0èÝì0TÙaЦÙaxB`‡¡@ȃãÃvŠµÃ„bí0®Øa\÷ÙaÂN±vØaÂNh—‚bí0ÔŠÙaÐ#ÙahŸ²Ã„bí0a§X; Å-vškì0a§X;LØ)ÖvŠµÃ„¤µf°S¬&ìk‡ ;ÅÚa(v±ÃÐvc‡ ;ÅÚaÂN±v˜°ªÇ`§X; ì0a§X;LØ)ÖCÓ&ìk‡¡Çv’"£ÁN±vJŽì0a§X;LØ 5e°”°S¬&ìk‡ ;™›°S¢&ì”h‡ ;%ÚaÂNÒŒ3Ø)ÑvJ´Ã„í0a'TšÁN‰v˜°S¢†Æ+; Í8vœ)v·#vŠaì0a'´dÁN‰v˜°S¢†*3;LØ õg°S¢&ì”h‡¡ÍCC–†3;LØ)ÑvJ´Ã`i°Ã„í0a§D;LØ)ÑvBUì”h‡ ;%ÚaÂN‰vš¶ì0a§D;LØ ¿¸`'¼Š€ÐÀ;á'ì„g°¾@ÀN¨Uƒí0a§D;LØ #`§D; Í\vnØax™`‡¡ZÍvJ´Ã„ðQvÂs Ø í]°^NÀNø>;áì$öŠÁN‰v˜°S¢w†' vjÚì0a'<:€’iîŠÁ¶½‘K)Ó‚b˃ Øò (¶<Š-‚b˃ Øò ¨_w÷%|Ø_CfÝd¾t´5êyðtms7&¸dfCŒˇĈ±y@cÄØ28Ø"ÆFÀ‘íaøö:37m£TïªÖ×oºÚï»®ÿº»)Íyp•¡ná Ýh|¥™¼ øí®[Û¬¤C]“ŠÙ-Æ…½páLŒñ‹vmd?Üêê7.p¹Ù2÷(ÛÂtÒì+ò®CªZ_Ÿv±ßsÝúµÐ-œ´Ñ-\·9Íu×-p „ó%†Ví|xZtËëÓ-ßEºå;D·~.tëç]_l·ÐF—žôAõÅÞãŒF>ÝRôõI›µýû„‹©FÅ~ÕÅ„“ÚÅ>îbv?°eð7× Û=ÈÔ+íÇŸu•ÙØÇ\e6ãÕ8½©šÊlìW]eü¨ ¿ÜC–nœdø-(ü3è¼R/³÷‘óÀTcn‹»DßÓ z=[qÂô † ÷ñ›ôu…u€zé¡e>Ò{qwM6r¢zËM§ÅÝb·¦u›…°Ý ²Ù¼c7~ÚbâÃ)žgÊÅê«Õ¬ˆXÙ&yÀùTcꌿê^Û:?csϻ߶uþŽÅ¤  JïÜÑõüWöødMwüiÏYuóe«ÿ¾UÇV‡áCŒ­.V¶‰±Õ}§Ázâg›ÜLìçíû‹‰ ®³Ìåp²ë/¸{p <Û½¦o\J¸©›ëy,žŸ8XvâÈÌ®eo4¸œdæÖSÁföÝ$óŸ¦gˆ<Üfìžå¡*prªú ËÆeÇ8·4ÙàÐQ‰Ý`\¸íwõ µÜ¬W ß«÷ºÌÜ‘àaÌU÷¯…½‚11rH›7Îo„éü»0ðýtÂA%6ÚÕ‹.<Ì›f‡WòÙH 2Û Qì~!§6,wUÍ{” ßšî$¿‡Ô£dçL’§YL=Jžn1õ(ÙÅb–"œÆíÁî½D¸ÔNWu¿&b°¸9HÄ`±5’_HÛ„ík"F”ï+ŒŸÆÍON±á0™©MÄ®ò}…Ãds’× 0%moØ ŽŸÁÕÂó3¸\x~× ÇÏ ?Œ>nwÀÐ’9‡&è-H—ó+/f{³97Þˆpbñ¹²Ç¿d۫ߟÙÃ9äâÊü ÛU\®þ*Þ9æJuo¼mÌÅ žæË\_þ1´ !Ï;0ç·,ÆÂÇ10ç}ñ&7— /ïàåZo.‰RÚãL1á°Dx™~"`KÃÓCÉb°pÂÁ–Òõ,yŠm.] rpdƒë9\¦ŸKö3lªuuNÄvÓ ã/"‹Ž)Ö]"9Èú§l1qµAS?Ig ^ã‚Ðñ—œ½Àyü™ì8¦MöM6Mö‚K\’Œ-ôcRÁã!~sˆ“‘û ø¬®/µÜfj/¸Üd/¨ë-ýuq/B 9ËÉ%©Ö-nLµ\Ÿj9¸KÕrp±ªå€ PËO ËA^—f9Ú9püPƒ›ˆß`qp8ñ×X& ñW[æÂ\@Q$«NÕdüMØ5Ž'<ˆ,uá4"ôÅj«gq«`wñ—[.ñ—õ÷fˆ'«Î—Œìl˜)Ù xD³0@`/e/à†˜éN_ÀA{?{Ÿö~ö¦ ½Ê^p3¤»Ù Ø)µÜ k/ØÉp=³Üv¸¾d/`ÁÔØ±Ücj› æ x){Áý¥Ö3Ø60¸²ðpj½‡¡SË w§Ö3X=µêáû€â²0j=ƒ#T›<ØCµL/Ø1{㨖.R-,%¶OöþR-+Ì&ØÙ 8Oµi€ U›xRµ¬0¨j{ˆ X-+WSÐuö>Vm£p×­M.ÈšÙ Ø]µÊà}ÕvW z‚+V«Ym§Ã/«M9̳ZÏà¤ÁÌ^ÀV«M0<¶Z¹SÕz÷­†k`ÅÁÝÌ^À—«½€IW›8vµ™†}W«^^í™kLö._ UÁòƒá˜½€ÿWëÌ@îÙ 8ƒ°Ï³° k»žaí¸«Öi¸‰µ:`-Ö|Ʋ†éÈm<{²¶`GÖæÞdmŸqý¬m¸–µ°0k;~fm7Àܬí8µÉƒíY›Nx µýCÔ`¾ôÜÑÚäq  Þì|ÓZϨ¡6pTk3{µ6‹t°6‹ Tx²lŠÚþ€%[Ë–yÌ^À ®¡n'µû <øÄÙ vG­÷¼¯íE4 jF7¤Ön0µN[­ƒðüV›<ðd­Óô¢V={Ê»ž±/èr Ò‹Ú”3clžì¦¶óèW­V6r­VºS«þv­VöT­VpN­Vê¬ÕJ µZÙ/µZÙ‰µZÁ]µZÙwµZÙѵZÁÒµZÙȵZA>µZÙìµZÙ¶µZÙ 5ÌÄÌ×îðwj»ÛN­CìÍÚ¶0 ÕÜ,jûÌóà³DjØTn¸Ïëld/P4Ãf/P4aÒ³(šT7î}R4af/P4if/P4©â˜û¤h/({¢I­VMª»ü>)šT'æ>)šTqù}ÒYÈôKxºDu†î·¡:‹÷I£–= pSö.E­zôFª˜à>iŒT±×}bgT¯8÷IW¤:÷‰TÅ”÷‰RÝ(÷Io£VúU¤uŸø%µƵvõ…מÈ^à<»Š‡îÃ¥Šóî“jD­2ô!ª¸ó>1 j/`Ôæ¶M-¼§Ú 8Hµ¬0¯j9àÕ:{°Š°ï‡°6åpŒ¼zŒ}?—êâ>ñ¡ª(ü>q>j{FUûç>ù©©m/8zÕKÏ}ÚwU¼xŸØpUüqŸxbµ:`Õ¶¼±Ú6…ÍVE÷‰ÓV›˜mÕkò}âuÔ¦ Eªê%ã>qOj{®]­CpBjs“ªŠ§ïç°Š™îCªÖWxе‰ÁàìŽk;N÷ºì¬ÌZN(Ye/pá\›8–5!·*oî>1?¸Ãg/`~ÔºÈÕ¬†­a~Ô^Àü¨]k`~ÔrÀü¨½€ùQÛ:»™÷iû׺ó£¶?¸ÇÕ¶)ÌÚFù‘±ÿxó£–æG-ÌJ†ùS {ó£610?j=ƒùQà 0?j»æGm[Àü¨½mÖ^Àü¨MÌZõ0?j 4RëwÏÚtÂü¨e…ùQ›3nǵ+ ÌÚ•æG­26N-LŒZ­0?j}…ùQËB¨m ˜µÖÿUxÁ„×fšy®åù×vW×ZV˜µÌF-—ë*wõ>!1&={ó£zá¾O(º61à*¯â>Mxínç³`¼Ú y½É숮vQæÞ]«ŒÖ&QÃ`àZ­ çÚŽájVËá™ÝÙ *¯ÕÊ–¬å›ÕêàJUë+·$¶nö‚ËQ-+ø¶væQ»ff™ÐìW¼ÚÎ#cm»s'ª!-0p-+»£ÊظO»£†lØJµ› x©Öi.kµy¥†ÚäkYÙ¿µ¬t§6 F¡ªZÌj­Þ×8TU»£0-5ãÖ{f¾6Dj•À«/¾-æGµŽo+IµŽo‹ùQËó£–c7óãÛb~Ô²Âü¨e…ùQË ó£zkù¶˜Õ»æ·Åü¨âªo‹ùQûo‹ùQ½[Ìêæþ¶˜µ~Àü¨î³o‹ùrÉ^Àü¨uæGu^¿-æG­˜µ:`~Ôê€ùQÝ‹ßó£z;ÿ¶˜µ0?jsó£ÖW˜U”ðm1?ª;ïÛb~Ôê€ùQÝ:ßó£–æG±áç°£C0?ªÈïÛb~T1÷·Åü¨½€ùQ›{˜µ¹‡ùQݯßó£º_¿-æGe~[ÌÚ|Àü¨"ìo‹ùQ{ó£ºï¿-æG­z˜UÔòm1?j9`~ÔrÀü¨Uó£–æGíÌÚtÂü¨^¾-æG•Iðm1?ªWÉo‹ùQ›3˜µm ó£V=ÌZ0?j†ùQ½õ~[ÌZ§a~T1Ó·Åü¨í˜µ¬0?jÅ«ád/`~ÔêðÚ6Ù ˜µ0?jÛæGÑ~[ÌÚž†ùQÛ^0?jûæGm>`~ÔÐÌÚž†ùQëÌÚLÃü¨UïGf/`~Ô^Àü¨½€ùQ«æGm`~To?ßó£6»5>¾-æG­2˜µi€ùQ«æGmò¸ØV/ßó£Öxµí¤¶«`~ÔÌZ?`~¾…™^  Z›{˜µÞÃü¨½€ùQ{ó£ö懯Õ\£¿-½‚Dï£zýý¶ø՛ͷ¥0SÛð?j(þG¶qÅ2ùö_éT~x½[óãÛb~ÔÌìÂD/vüŠ{ 磶ùà|ToÀßç£Êrø¶8µºw«}|[œÚ 8µ:à|ÔÐ'œZep>j/à|Ô^ÀùÈÐ0=–¯öm±=jרs‚|ÏqùäËE1xµúàydSB¾Ë\¾¹×0D¹‡ó =Ê}Vû²decÇÒ†æY©¥økT1çw4×¶7¤šÛ¢üŸ·´&ë:£ÜTûÊ–d”÷ŽTsª¾ƒëJ³>å¼£!•ÉV*nªYÚP‹¬±^»Ä¥*HŽF^ÕÖ^7qbõŒŠYåQþþËjšë“QnMSª.‰:§}¼²¾¡1Y­'_·§Z’Í.¼±!G 7/騯O¶ÆÑø —ð†f æ´.ih®i]YM[JÔsn;ï¿Ñ[—}]L-6TxF}k2YW$ƒ@kSt¶5ÙÚš"z{í²šVÿ¶xCˆ®L-O¶Ö7¦VàxÿÒæ¥ÉöZŸ&ZÞ’jkÐ0Dù9¾¬‹-ëæ†“’Qö)ÝÔÞŠ nHÿÞ‚ç66,mnJ2³ÑçÛj–'ë|ÙdInôù/fÞÞìË]ÙÒšbî¾Ú𬩋cÉ^+ZÚ“¼­¶1ÕfÁ¸¤Ñ³±B>Ó¼¯¹ZSªò.wß+ÚÚ£¼Ññ£øÊ·HZҩ鹤½£¥º¾±firzOV²nÞYÓº´6Êý$Ÿ—E¹Ïa×ÌŽrëÉ´©¶ºme[{² ÿ!¼²6Êk:¨oû”®nohb„J¿hh^€›ÄòÑ-ÉÖ†Ëäv=\‘šÑÐÊ«u5仌ٺµ6ÕÜÞÐÜ‘ê ÷(W‡@Ü–e mñ¸½¢5qCsGS•ÊRŽ7Öv´¶NÓ~\“ZÑŒ…àj|™»{Cí‰mU©öšÆ(odSuCKëaɼc£ìŸ'›k–0L玆1µ¯•M5m'F¹ÓJÇŒbKÜí ‡f6ÊžGÙEQî»Ýgy2#°fÉRÔŸ ¬]Ò±”á)3F·´@gwbrå’TMk«†µ}q”ûúº*,,iihrŽmaÝŸ½¤mP¼ª¶‰Ï¯Ռd6D›ìÒ–v&ô-ÉÎÚdK™y2ÝžüZæÉ {bª³OfÆO ÿØ[‹/ºpwo9é«û{+J_5ôå_ïÔ«“¦N¯ž_>¯¢lVõôòYeÇG9‡ûgËÊæ3*öUq?ÿjÅñ•ÌÄg>nÖÜÊÊã«§ÍžîsïÈ<[À›3]²èí½¯l›/ï}b²$Gö>Y^UVµ€ÎýVxå¼-=6S^õ•-ïŠÞ'¶¼÷õ>ñååm<6Ê;BÑUeÅ ÿ) ¢¼ Ÿfñ“,>Ýâ'[|Fr}~Å}jÝâ}V,|BùÁHk]Æ4.žÃÍëíérÓ'oLWœ>ysºèôÉyéZN˜«éVÑËÓµ¤OÖ¥kIŸ\”®%}²º¿umE-z²¾¿=ÙØ_Ëô(÷âL-‚pÅË3uΦɄÏÉäW¸rRfYC§GùïL¿X>«ì¸ò¨à]™ñt)| Ó|Š?ÏL¬K±ú…KñÕÌ»ŸO¿p)šú{‘N^Z°ëIú°òòþÞd)ÍzÍz”¥Ùß«,¥Yϲ”¯ìï]–rƦ‹#zi¶£Å y#í–÷-I»h“ùµá[h“Ý4Ð?›Ìà”¼y6ÙŒÎÙdW÷·Í&;qãü\4~`øxU¿qòL²—ŒIöŽ3g’°Î${ÊÆi3Éü^JGWñ§z¶ðøYs¦—Ï/¾»¿qÙÓø†îåi÷·0Oûå>æi³ïN{ü@Gó´CúÛš=-èí’ò²éÊ ÓØ”öYéG=ué²^WÓÍè¥KçÁ“ï£Kwì@]ºßíïŸ}–®£´wË+±\u[çxTظÃMª¶þ®™TÙ†©<þñ3©Îè—IuW·xTö ÈzeakÉ B»ì»²¯"ë˜KèBÚ4—ÐfÖ7—ð­s §nìžKè‘VÚ@÷.Ûu.áÉs¹D¹ö·Ð>+}o ƒ.¹ûä té²6ÕÒyøíÛçÒùU˜vÏ¥û»þæÙg‰»'…Þ[1wþôòªòiøRKú˜¿M^1ÐÅøÀþV†ÄÏègHüÁþ¦†Äçt6$öë·7[ð :ç—Í!ÍŠŠ¹sБùãÂÑaHmÎ]$†Ô»w|5õÒÈR¿s#r ©[dþ8:KêŠæO}%·†Ì{82ç@ŧgR˜›–ybS¼Úâ32)^’~bS˜¢â33)®M?±`Ò¬eó*ŽÓ9ráÜYsçÍ.«ŒògèÙqœ:—O›W^>'Êw¥Ø [IæxpÂØ±Å3UÏ_PY9w‡sà;¥|á̲yœ^N8®Ü¿Œ–ëåÒ¹G;:È)e³¡„˜c(Ot8®ƒxCõ`QùÔGÍ—^uOYÀÞ8aNTàê¶ñųçÎ;vEúœ‡+›Fÿצ-ª˜íËÜLÜ]M—•Í+›5 ¸P™yzê‚9̼¸¶ÄæCÑ2sfâ§/˜£i‘im3ÞOa‘\=mÖÜiÇ<?*_q©,Šoݯ‹Ç{ú1™ÓÏœô{n‹rw˼ÐÍÞöLøä²i.CÅÝ@Ì“ÅU3Ù&QÁž½/tP ®H¿ÐÒ95ú2µdºuì¨ñé>Äîkžœ\1½ÂqŽbwñ4oÎb›7ÑŠôM·M3¸/µÙnñ}©ísö©—–ǬÅîškÞ,šÍv?™»½¦óÆ]5™ìÀlÛëúžº Ê5¢ø¾ð,[üEwCMŸùl–KpRùñSç²lWBÐâ^V1*ß•}/ÙçÅzŸÈg a¥n^BU p‘3ý`þ1Õ3æÆ'%³x+ß—Ú™󅥵Êw^YX¹À­œ“ÁoºÅâõ«G‹ËE9¯IG%júj¢ ‰@f¢‹ˆnÏdZ¹,.¯€q“eRÔŒ¤}«Lf„LôàÊ]^~tõ4îæíèÞRžÖû@¬ƒ²;ñù‹y`¨p~¹÷Áñ¬¿Ãz,^ÅÖœ©ý=ˆÓ…Ïû•SËæƒ ÜOß,­˜ I$v—Id¶múÆ&*ONwú¸Ye´ÁÙ²J&2QÇ›3™ŠÄñªŽÃIÇ£ÓŒ|Œ!¦Ž7§“ûµýo´x tãÔJöb6òöÕ©d7çÓüÍ"ÞüÅ@v½1°;³‚7“úß,çMsÿ›§òÆœBwõ&[8öÍ2ÞÚÿfáŒ(§Æ¿Y4&W:ÈÐ é9‡P-ŸEó`i^‰ŠÃiè 6z$¦é}t…2¥+lÅ<˜Ÿó›¨ †ua£ª"ݱ+TÅÓ}t¡:óŒLTY™‰ª3«2QÕ›vt!õÚÛž%Ô¤{»˜éðý>,,# ö>º`Á¢©QîBX師-á…Õ ”ÈG…"ƒ'æÃ'Ì©$õ|Ã%­Ä@¦••ås¦;äò´tÖÓ«ê4 P…'Óã7†+a ØS\jƒš——ÏâˆqÊŒŠ£v¶|,ž :/ƒ¤Ízì¼2 vqµ^®˜YÁâÑžYR^=‹[ŽŒYú—¡š%À¯Õs§>ß°´ŒWÄó#CøiL¤°“£|È>>®#€€øG2¶ÅçþZæÁòªy®mwëÉÒ ª.¾O¼_-qaW·68Ò[”ó–ödg{u}ªµ©¦Ï%âú`饭ÐÅk´,¶¨`BLM\ü¬ºz9üÇñQþ‹ê’pj×À-µ ÏøZKÒÛÝ“âÏOµòʦšÎ82Þ3îÊ¿®]–j¨…,ú娋ñ;Ò¤¹Íí­UFáØåPý š!¦žÛX­håM1Ý÷ PmN*á¶ÉqŽ7jòªÄ•K *ÆOŸW¶°zêñU`°ÂKÃôæ}h¾NgÄ5¹ Ü5f;µ¨™º¸>¦uÖeÏrkL°$™§³Èb€Ž%å׊V·¢ljõB¨§.ŒrŠ›˜­Ùt<Ê»/§ Š<|)-\å¯"~-,¿ªeüXjŒòh3Ú^Õ2j¼¥Š–÷}xË’Tª1Ê}É’”•ŸÆs#eÃÜ–šöeœ—N‰‹Î'TtÕÊì˜Þx^”ÓQÓ‹òsôAŒî8`.Œêͮ۳Ò=¢L ]tÕ܆TM]]+T©_µ˜N sZ_Љ)Õ!ª$“[l‰Ë²á´¸Ò·çB8¾:Ú©µ+aSÃŽ-Ïœ» :±h™;·­…67W¤k ÷SæŠpº&Ù#2Ê}íÜöÖšæ¶ÆšxE}¹VO›–ö™uðãsýJ*!2ÐAËG.²DûÏU׶у›–/­Q’8AKó”×1œÝ”lJµ®ŒòßOŲƮ›ë–XAó"R¬¸©Yµ37ÕÑ“rßÔ¶„;Me75O‘4Gü³¹M u .I\;w¬l‹æÎaÙ<ÛèRXZú}.…EJaèù2ès* YËiN.™Ëðn©ks¹rÈÜxü—7,¶,Y ƒxý\º½²£¥N”aÃåe“–Ÿ?×3‚ýxi"Ï]åšy¸©>µ{WÞ-óÎ2ø/¶R¥ pQkÙ%*þÝ\ñšKŸ˜ ‡|C $´ÊŠß˜ë Çææš–¶e)€‚iOùÓ챃ŷµ_ËzZ¿\ÍZj$Ùå?snƒ»/éÀQÆ’r:Xɵs?Ý‘¡·ÎUÝS£Ü“š“£OŒ >N:"iºÊå¶ÜtV;!ªœ87Ù¾Œa‹ ž­›¥òŹ1jŠrËç6'W̤ÿ‹4j¾Ñ?6RˆÙß§ÎË/½X ¢ã•hÈÑëæ®XÖP»Œ›nù»Ôoó7ÍÀ/»<Þe5ÆîŠ+çj!ôVy¾–62É{Øx–YmàܽÜéxú ·Íe²N®iiźò* °§·ëtÖÑÀÕŒÓ//­[·ü¼(÷â‚êXñl×ã8áF×`ønɹq,*^ÒÖ‡ ˜Û–A\Ü\ß@­ŸuQÌ7±64 Øû·^M"mZqXé˜#t¡˜’F!Ý­¬žQ9ª8ýj5m/ÿ•si~‚ ¿Ô¡t>÷„ÂYEÕâå¯\ÚØAY/,êÛ(Z4碭°¦ºº$.aeíŒ œ~¦ØN4›Ó9\J3/moiXÔRÓÜP[]=ÊIxã*§ Íþ]Œ˜ ?¾ü!ƒJåĈrŸBÃu½}w騱èeÜʧ¤ >^:v›ê.>§E¹_àS€ë|êÐò·™Ñpø6LÈ‘AóúÊÚ†¨à“EÄÑx¨t)²Z~áCENâÆŸSDÇô¶«¢ã*¡´ŸZÔÐ\ŸÚÜô3 ýoaí’–ÍŒr¿_:Y‘â¿ò©Vÿ Ÿjõ½|ªÕ•Ò±Gð¶Oµº‘Oµº‰ÏuÖ§Ò7ó9+Ê}ŸJ?€Ï#£Ü]øT-|ªŠCJÇ–PÅ>UÅ¡|ªŠ‰|ªŠ-¥ãF“â/‘=QНó9Onv+Yðs~ p„?~œ:Ói±{¿e«J/Ïk•ö‡Í@›’A™R:NžŠtŠ>§¡¢Ï³O‘RÊo—Ž*3:Ê»Vß3¢¼oè{f”w¾gEyÿ¨ï#¢¼oêûÈ(ï[úVÞÏé{v”÷3¾gB-ùº¾§Ey?×·êù;}«ž¿×·êù¦¾UÏ?è[õü£¾UÏ?é[õ|KߪgßÚ)¥B}«ž¡úV=Ãô­z†ë[õŒÐ·ê©oÕ3Jߪg?}«žÑúV=3ùÖ<•Æé[õ¡oÕs¤¾UO»¾UÏl}«ž9úV=sõ­zæé[õ¥oÕ³‚o-‚Ò}«ž3õ­zÎÒ·ê9[ߪç)úV=OÕ·êyš¾UÏ9úV=O×·êÙ·VB©Cߪç2}«žgë[õ\®oÕó}«žçê[õL×~T¦k?ªÓµÕ‡éÚ?­oÕó}«ž›ô­zÔ‡éÚêÃtíGõaºö£ú0]ûQ}˜®ý¨>L×~T¦k?þ²¾UÏGõ­zîÔ·êÑþ›®ý¨ý7]ûQûoºö£ößtíGí¿éÚÚÓµ¿¨oÕóGúV=¬oÕó%}«í¿éÚÚÓµµÿ¦k?jÿM×~Ôþ›®ý¨ý7]û1Ö·êIô­z úV=E}«í¿éÚÚÓµµÿ¦k?jÿM×~Ôþ›®ý¨ý7]ûqœ¾UÏúV=ê[õŒ×·êÑþ›®ý¨ý7]ûQûoºö£ößtíGí¿éÚÚÓµÕ·àz‹Îœ³Rí•\O ÙÐX8þ躵Ú^qLto*Gqsåx’¼Œ“ÎÆä?ƒk篸ۑ•†r©¢sI •£27l+Ùsœ¬¯«¬åoYm'³µ>Õìt*„ª¥Óñ$y–%#—%4T g)yJû¯ç™ûܱ%Í´çè²7ýJÝcŽ}ä`–|¨¿Ì™ø¦ÆjÊ•h¬p÷×G¹ßºgê,s O£cÝEET«UÔ§ô>_GgWò24ºÅº"ôÆ6&ûJ‘üæ+\ok”z‹³¬Qî5¶B¾rÊ_Ê<«î§h¬oQ÷|v쌷fjÈø ®ŽÂ1¡îŒÞà«\SÔÆ¹{c;ª^Ó´=U⚎–(÷ç®Ã9÷¥»½š×OÛ5 Éyùåú±-s¼>Ê9Ì•vÞJ—«¾@u׋ >¨6u~ ßê»ÿû•}I Ù¿Kâ­O¥²)ì2gO ßp$ˆÎPùr÷*KS~¾»Ñçy›3'»¼ÀçÄ$þ<#ÏÿÈGó KÜx@NÉ_•òGh¿¢#ñF˜Ñ'tÝ&tq­IÖ×t42Š"Àní{áˆ2…¶ &Ê=ÒE}=ñÇŒŽ“WˆßœÛÛ‰·:zV”ûW{ÜÐå• Vé~yNuuó\årwJ˜®SÃZFj­ŠµJÏ*ŠíY[—AAKßwn%×½`ºî àpîàpîàpîàpŽ ¯rgiÖÖJ{ þUâs±<¢¶Ú¸¢zÛj…¹Êµš¡g8MJ5ò´ÑcÐSœå8XlPƒìu¨,+J¢ùv «Âî¶›Sˆâ­ídDlƒ‹WòˆÇãIhO38>K™Õ44»$ñ³Ò@ts”,¿CÌÛCXš€gr/“Îãr¯2Še¦{·ÞøÔnǦի@b†ÄÍ"bÏþ4q†Î#‹T9OÌÐùBg‰œ-¢Åpi›ø f\ߪ§jã‹ùæRC Lž.34y”ÀäéÂ1C—JáRC^.5oÓ·ò¿]ßBò7ë[HþúV=ºpÌàRåy03-ÈlšE_ü©Úqܯ¦µ-+4hú'Õo-—bOW‚ó¡| ŒX¦‡ÿ/*©IÚIºÎøG[@ ’2‚ƒè«›ê Œ1ëã)|EQ¬é%!eþwcªµÖ‘¤ ÈXé£s‡4gœ:GéŒ3Cç¨O•r-Ôèü2Sç_fê|ó'úÖû?Õ·†êÏô­¡ú²¾5T®o‰~±È µÉ4>çØé-{ÈJ´®œUµ¨ÚZF>™*†@bÖDš‚d†®sô­swK s/E[ãkEmmµ5ÍõQAª½©E2õQΉ˜egxvZv†g§egxvcômÀ˜¾ Ów{TP^_' -­Ã`Ó1 6­Ã`Ó1 6­Ã`»Rߪäd~¬Þ|M¥»ój¼>&ÈÔ’È0îù´kE¬…PØgáTššÃ&aã±IØxlm¼¨'Sr.“ÑYﵕ§°Kˆeù+¥cOLÃoxb~ÃÓ𞘆ßðÄ4ü†'¦á7<±?Ò·ºþÇúV‹¾¤o óŸè[õhøá‰•KúZT“Üèj”Z5]d›numC8+èÛ\ õ­˜)°CÕ¢³¼e£t¬êH"6ýF΂%U£¶ã›õp€¾ÕÞ¥™êjJ]Å1ÓµÚUªukß`®Åú–™†÷†ºr‘®ª`¸„ QÞ • ViÿL×~Òþ™îxàYIA/â’B³g¦kµ 1LòbÐ †k´¾uýïŸ)ÍSkzŠ›.kÝúâ%ª T¹tÌ€Š¾5R˜! }@íáÄĤÚããõ=‘“Ð’Tx¢«Ù,¾×ôKäL˘±ýß¿Å0cËÑ™üQ½ÿßWÞœ'ŸTøÿªÄŽø'5L.ÆËÑ2{‹K+ÞÊ+ã¤æÖ¤“³ÜVÞ<\oénqåšqR³Ü¹œ8~+óNÞ'5׳’6DÏyoɇó¸ÞÊEã$91«õç2¥6ù›-F΋ы¢Å虯yÔ+Ž/vòÓzãÞ⸬Ä[9rœxqÅœÌÑÄ´·øÖ"¯¼9N¼¸|Þ¼¹ âqö7a¼•KljW–Í©˜=_3A?päEå×q¢üçÕ{H~ßCêô=¤¾‡ôÍÏ£Í-¹Yç® oqrùW¼¡·xÛr¢«¢á»^ž]¸®.zq ”…[õ­$·æEåÿ/^’Œ.%>hm^tuI2:œ²ÑV™‚?¢G$Ö?¥[5Ñ‘6yûâ·,:¸¨bδêy‹úXöਗ਼¡¶]#àÕQy»ÆÏxió}ÂW}’²ò1÷õéþžÍ}jý>-*ÿï}’´XßòGWùD×°ì ϼ¹ç®3?Ýsç™çöܾ6+vÖþ=—œ†+ÈöOE/î>n»ö²UŸÍ.êþL4¬j}öü²S£UÝ»]Ö•—]tIVT²ŽÿW®ûiaÜïa—­º §[S«>SpÊäwFûOŸ¹¨äܨ„7±ŒÔú|íx­ onÝ/:ë#ߎÞô‘OEg3ÉÚý¢‹'/Žv-©Ýu×µ«˜8ZT²TÙ5,çÂÓèÙvz¶žåó±@ó£ß]Ñ¡E¸xXY¾âhT¿žÍE6##ÊåÀÎzÝ`1<ðiÇ7kfp×ÌिmÌæÒË×™­tÎp‰/HyÔl|íýsfçF3öáìÂwßÀ̘³Â¶ÙÙzJvá%ÌŽfåz››W_²j€™¹>áfæøåå M÷Ìàóp¾Í > ;æ$º&Ì ³á秇ڛ1Þëú}©gÛ΋v.¹2zqÕºk/ëú'v§pÚŠuì›rvQ×yô^^µG¯¿$—¾ßd}/†¾¯‰NÜ™K3ýýÎRèÞ›8’•Ÿ¿,: [}¢G»@p»j£á]ëö,¼GŒêÉõôæ'}™g»jÁ¢ŠÛU¾/Ò㉡/$Ä|_{æÃe=·Ú~Ù5 ï„옹ŸbȬ°Å1¥§²WÆFkªö-QÞ¿[æâí²ý쟭ì£Uì£5ìüÛÙE»ÜΟZµ˜,ÚÎ?7*Y¸8wʪҟ®šöÕÂî½m÷/r»¿½ê¼Íû«#o;þ wc€+Á+Ýü4hŸ]÷íè¢ô iïi§­c§­ÒNû½®î2uÝéfjáÝÿ­¶Ëp:3`¸Ív®N;±€¨€éŽ#ägTÄ`<\'¤´ïÆUÌŒ¾‰•CÛÇfT³üŒî—ÙŒ>}=3ºÍÍh«›ÑýãUÎÑU§Ý7‡gMËâ°Ä¶Ÿvv@a÷^1Ùúöœ"f/ÃoÚ<‡rBýÄ~ÎæP;·€9_lµÙÓ¾Û={#ÂìiÞÒÙäü«&à°!y[pØ\|išü3(‚Õ,¸lö³ÓÞÃÞÙuC4¼êüÜ)Uës§tE{²[/áŠqë§À±šŸtv„ŲّëÈã²›l†þ>fhžÍ ~;qÙ=—1+~nä&\QàžÑzô¿í¬ýûw–fËà ¿³îdg}à>\q–fiÕ Ý`aTï¥ïàŠÎ¼{p·‹+ú¹}öáÿºÏÀ˧NâWàôp®Ð\¦3*Ÿˆàоa‡­WL±ê§… K™ÇÕ~~…+žß+ì½ÂÎáÇÌa߸'Žûp…æ-=|< WÁñ#:† Àì³m{V­ã»Uâ 3;ÿW0C}à \NîÃÌŠŸy¤Œ©"·ý‘—ÿ?\ñ–oñöyì©UnOµ;œá0Ã1Åê!0Å×Ó˜â_æ°S\0Å­6Ÿ8ÕìÜk"Φó©™LçSûŒûp‰ñÝ¸ˆ¹ûÉ}Xù½—þï}xù‚Çq݇q ºï>ln~nÎð*¿Ð%œ×Žm{à>¬cÖÌœ½5»ð<|5o«Mï¼ÖÞY3جgŸYlvoåæÛñÿž§[mžþ ·ãsl†pgÚ‰%¾fˆ¹ñ3„·SÝdËlÒžºñ&ûpS×M¶ôØM–~þûMªò:]†Bsà¿öÎöÃûó™ž38Ó¼ñ3=ÇïEb[÷¥çøÝæÆÎLÄNì+`fþýfFmzxf˜?3¸¦•’m×Íž©ý·+—ý§ÝçwÞÖöAÑzû½7Óúøï{_·ê_îÞ¡oéÆ§ÉŽœ¨º+*h¿$'zñ`½­ÑEÓ¦.|°Ôî:q”«Q®ðÿл}ßeNhœö€z×ê|ÕløVÅ8ÖQÿdÕJÿZ¿úã«¶v›øvwÃ8·ç‡ƒœ‹ŒKñ‡ìªÓ÷´™½÷48WÖŸ2 {+KùŠi æßo»’{[;¼¹À±µT±³Åz£÷\v§P/«;ÎÐó¢ëàÏœý8©ª{Ç™·̼Ãö‚;1s«Ì^»}§YKçÿÁºu6ÀœòÓû1ó[>ì<Ê£êó€ƒ¶ÓøFbS}g™öÜü]‡yYbó÷µ|*àcfÄÏ žŽõ¼i¾i;¹=ù7ö>vgváùùÑ‹»^x î› f¸ œ¼æ îÒ"ßããÿÔcß9oãاjƳ‡F¸þ‘îzW–þ æ-}ÿØ™÷Ñ[ åËü÷[ å-õep „_½ï¨™LçSvÒ 5XlÓ×ÁðÎôð_æ-ìèuaÆ<OÖ3fLH»Ó\¥3†ËhùÙoÄs{û%[îó5:=[W¶NoµYêÛàNtcúNôßw7qÈͼàs»Ó|6Ü<˜?/¸ä—«‰9gë¼|wÝ]“ÞEw>²‹”¯ŽEç.2÷Ý’4[ÌÓðÿ1O·Ãé>E.l½*ì¡-6Wx ¯‡¹b–ü\É¡8wÿ&°â¼™~®zfªÝÝáüLù;ÿU¼+ÂÅw±ôý ÜlÍÜ:[ÂVí8­÷øÌ¿ssuÿÑfÍrúÇ•g®º¹ò³V3  ÷ËñÿÉœµ„9[3¸ïñ{¾û3ÍV:gr‹næìNh3ïù_s¦ûÖ›3—÷;sÖ:$Àœ¡QзÀœá½}ßœi¶Ò9“s÷^y?.ó¿² 'Ày3óvEúf0ŽV'®zœS¾¾CÔµn÷J¸¯ÂâÓ*¾j‡¶“[‹x]Ü2Ö÷ëíý%µ»ôtE»—¬%®™ÛÏ\ù7kú¯Zç»Ø‡è¼x¸Ùc蛜ߩo-Ž¿ÆÍÿß}Ï{²¾H1Ó;MÏ÷0K<3zŽ0àÙÓf ·ü\šeaÖ¿b³ŽûÎYß°‹æ[±‹wR.œÜ7ôæ2oq”áó\&ƒö¦ÍEˉ7üÞœvtåÔE{oN»ã»rÒöÞœuåÔ6Ù›Óbᮜ¸åïÍiï ]9µ‰öæ´w ®œÆ¹ONîõœë¶ç´÷Ê®œ’aÝ›ÓÞ„»r>s{N8õœnÏ Ÿ¡žSyoN8õœmÏi9]9ÑêÍi¹3]9/Þž¾T=§8${sZ¾UWÎgmÏiyn]9enoNËAìÊ)Ö½9-¯´+§Ü’ìÍi9¼]9A ½9-çº+'¯{sZ.}WNÐKoN«[ЕS·½9­ÎDWNÙtß›-“zN]µ÷æD§¥žŦޜVç¥+§®á{sZ ®œºï͉öR=§®u{s¢+Õ‘³ œ`ÓboN§Oey ï¢äã–fß Ý,?~6p»<†HÕ^—»¥¯ÇÊbåN³kÁo¸s Çñ¥¬<ezœ¯ò±Çòý:47¨[@Jºš4|1ÞŠêž®"¯ˆëj\ãn%µºN×%ŘèPå‡"ˆ9ö­Øìö×ø‰¸æFØðš~×Öï N»¬VÛdþ'éj²JyakóomÝÕJ›qeýïz 2~YedÊ*ã—U–ÎÍ€ª¸²ßy`²ZüÛl:ÒßÀgÆ[` fOHh Ð¼fp f¯EÚÅ7ˆývšÃâÚíÞ_».Wyí£¶Ïâ~¾öAB¬ª}4j$=Õ>è[| µVo®áû䏿Á=ý5SIV3o{§’~˜ß±N4ÿC„¾…0‡œ×ÖzTml[[Wá¿dµYÆ™~­Bêgëûã~¶~6îçPÛcC_ÏÒп‹giXw\û°SûJÅß™¥tÛ ûh\û0gÔ>\ uª}¸X­š¥áBš¥á—Æ5H=Pó¾ —ÎÒˆsãY¡yÕ,øY\ÛÈ Î’­í‡³4òÖ¸Ÿ£„–ÔÏQBº،ÒRGý”oí‹ýÄÌ’Ùïæ¸öý¾;À,~VÜ×ÑBìÊ1Z¨Q³´ÿc\2æ¬xžÇÖÅ5mÜÃYÍßÅ%cß×cƒ™b¥ Ì\cƒY£ãÚñhù~ü.6˜¥YÖ¬Ìzm¼wgý ßb.ñ¯|ë2yäWã´¿+®¹ý}C`ƒv”Ø{í¨¤ò~¶˜êûl±Tûœuq­sÞó—­:ç›qusTø suÒ4Í…/Î-|®‰&m^i\弩ƒUf¥®ZGÍož®©ªlž©£Î{ßb¥ÛðéQ©š›£ÞWyÔoHÝuõí¸®£~×uôç㺎‘Êꚯnª®ù×5ÿ‹Öµ@5 ÄÖÐÔ,ÐÅU3·@Ø^3·à_ø¾ƒ3· Ý’êB'…™#6Œ?9¦F+šÆN€5¼ð[qý ¿Õ¿˜—ÊêÝbÙŒú¬UÏå…ô};^HÕ×T™½ž¯AÚÙ ©øšëŸeVð‚ù¯åËБì…:Ú‘C*»/¤­›WñâoÝëgFÙľf=lvY5afùº‰‘w˜uØp«´TÞA£k’¯ÁÕå¥êbØì?© Ôdk±;Ù×Èt’ÃÖxoºF¦~ÑOjô=±µhGD:çŽHë*ÿ­Õ2Èbäú¾ Ñô˜ê…U踋5ª[ÅÌà׳ßô¤+ó%? …o•‚‘ ×—âÖ¤pR£œ±€”Ê^ÖxÙr½¨r¶&¨QÎX@r~YŠÍ’¾ޠïx9:ùÌ£ÂÄ©[0<ßU¾>ð¼¸×¼$²Ý—%g§êZqã<2ٙij­.@/nJ¶×Tà®,Ê:§§Ïž­(«ÝÅÉûqòWuQöºŠ;&ÔX'.>m.ÅX™‹GæóÝtʪüOUŽx\=°ˆ±Ù;ª¼öq©¼"Žn令òkº)‹üBeéã‚dòŽ;!•Ù+n甎Å|TåmKZÉÀÑ÷ ŠÍ¥òžW¹ýqõ#m|õT~ý¸ÌP’ó°@P”Ýò°Š?”¯qfŠ£g=!àâ G7=!‡"ãžßWúÿà™˜üÒÿ¾T…³D\)y\ŸÁ9#.Ýö¨Añ9Ø#–§™CåÑŸ_*ë1¥]¥ƒË|1¦^ _ú#³¸x"Vå¦íÉœÖ_Jq·G»rÀ£½¾ã÷T>þ±É,þØÌ—?ðØ6©¼ç‰ õµÇ·_åcoÖ¸ãáE{xã—o} ?”¯x ™”oz ó”?øŒ*ë1€VþæcЯ¼ä1PY¾ã1¸ZþÁc@¸üÇÀvù’Ç`|¹ê±Aù¨Ç®åU:ŠOO~çñ3Nùï—úû Wñ†ßßûrÇÓPN\ 6½8qÓ¹¾D¡~´n¢ú%h]˜ òüúârÌQš?àDc[]t‚sHÑí‘!ä<ãvþß±6]I|ðu¢qp|xlS=☣Òx_ŸîïÙܧ¡ÿÑ'ôÿKŸrÇNeý!Eäs2ê¤Ñ "rTD¾vÔU:sÄ("û|A 7R–¹õô](ÍÝÄL†p̱æè¾ësŸ Ž9ú½øqÇ/º™{Hé‘9Á1Î!4+7ÚÜìb>þß̤Ž9Ö”—?44}8æè¿.8æ8Ç;æØ–vÌ9Ç;Q•×½EÇ]kÏ·¾ÿØ1Çšò‡—Â#Ž9~Ýԙϑ"‘T{cލ3«7RÿOú2Ïú²¨ÿ_û‚cñ qÌÑòÉ!sœ“qÌ¡Ÿ9æ˜;[ÈwþÓp½1¿×-‡Ùû3·¸Z9ƒâdºû¯d÷¯tsÓø?œrÜë'ÿuï?©8yËv§“·;åƒ §ƒïÀÑÂ9G šÍÝŽìlîs´`ðƒv·ž´gÆ%Ç󳊘»N,Ñ5ƒßSýü¬Í öl3ø˜KŽÖí.9¤B‰KŽÖ›‡p³ðÛõo`×ß„;Ž]‡Çû^{kç;™‹YÍÌü/ 7:, ýõ¯Xàî8>»Ý‡0î8†:t†Øú2nÞÅÂ÷1DÈù(†hþßÂ\‡û4ÀuWCtºâ†ÀLjÆ!$0D†XuMpıCtÍà0„9å÷9€!êŽ8†ètÄ! #ŽQ/BCHáaÛ'Á%0D”¨”‚¡ðÃà‡]ÌJ:3ÿC˜ýÕ'†¨;á¢Ó ‡¸è8áØïÂÿ§~½}ƒúõL‡)Rõk‡®øA?¤Ê×?ô(\†œ{ð÷Ç€þ³êõWÒøá;ã÷$~ØðÃÍÛpLxØÇþßBàÞ[uÀñĽ·CùºûÞ[ÀGŸ÷ÞwÀñ 8à8Ç;àØ~¯Ž‡õì2{˹·ró-øÏSê€ã_ñWß8NÞxc•Žîkù±«ÙÿãÆpT•ãÞŸÌô¼Á™æŸéy~/CÙÜáÂÿÏÇÿ¸gô à€ã 9CÌŒÛ}Ì9àè3`fþýþÐ'€ŽC–8.D‘ùÐîó;ŠÙÞ>é€cB<ûÿcïå8&ü@8nFEZœ¤skm‰o}ñ_œv f+}.ã€c“ê9‘žXjÐí¨–¨æ5Þý†uÔ?Aî7û$ÊrÛÔ[£¶ó7Œí³=áúì©Uóu rýA§KA8䘴¢_åüŽIߥ_ôLóšÞzäó/ßéKØ9ó·«‹/ ÊÓ”þ/;ÇÆè£Ç_ð&ý=‡l¡hܹ‹® ŠãôÙÏŠÉÌÅ_Óó?òÍ9aÃ\ÀÕd.>¦}Ì¥ÿ×¹ ÍZLûæÂpR]ÏYKºÇòz²Ã5=nI²ø‚kv»%q·”ÝnIâà–ÄÜUöº%1w•·$ÔS­%ÜYì]`¿ÿã–ä ùc·$¨ïsK¢YKçW ¸%Ñnê•÷ßW¶ïpKÒ'ÿ0sKòÄðÇnIPXßç–„ñó‚[=o@{lú·WWuKrM~t‚Ü’ àoðåMÜTÖ<Á[ËÜ’üKƒCz#¼“™ÎUÐÿæœlïâíÖp/¾’ýëö¨0󃜵…Þ‹ûDà¬q/¶œµ¾ îÅuGá^ÜéèÉÁÇ‘…íÙš3 ¸«Õýî[ñMv+Þ‡iú:¸§.IþuÞsIRwó\’t¸y€[Ò¢ý[[ncóUuI¢Ø9é»Xm–ú6¸%¦.IþÇ® .Iº1T]’X§ v^ÐXÄ%‰6ðœsIòÀ.ªº$ybu¸$ñ»ÈÜ¡toÔl1O#þŸK’ǦéÇ.IhÓ>—$Ì’Ÿ+¹†0î=„ç ܵêî=²™ò\ç’ÄÇÒ÷/0\Õ;[Î%‰¿÷š¥Ûù‡ÍšÕqè3À%Éçì1÷¸§ØçÞC³•ΙÖ!sÖVå\Mþ÷9Óô¿Í™Ëû9:t€K’>æL-xx΀~Τüh\’Hù˜…qIâpÕ㼃/œKíûŒ{cñi_y—$¸¥ý—$º#îvIbæÿ?\’˜Þý—$ÿ‹oUwI¢)yØ%‰æ;½OãÜc4÷ié*{¢5¤}êÄD]²­=ÑЖÀEøœÄ ¦ûÝ ¥â=ÞfîMÇžø[>§nN~ÎÚt³®Þ°Ãm‚<º3óíhøéïèÇßîí6”ŒÛOrû÷ò<·çµ¶žÆ}„=ý…x7ÀñØzzÎJvÅ9Ü»®é›eÅÞWF‹ï­ÿÃѲ°#=Y—ßóШ±»B=úѽ%>!æ Øñüg>ª1çSÃýÞߺ¸ßÏïã›e»åò°[>g1˜|Ýö îE:÷Ì áV£]‘ºqÙçZÄæ±®+p*ò¤»Ãºrîs b1NWÎ}D,þìʹψ½ tåÜç@$8’ 9÷9 ŽdBÎ}D‚#™sŸnàõœûˆØzWÎ}D,O¡+ç>"–SÒ•sŸËÏéʹÏHp rîs œÂ„œûˆ§0!§ÐÓw„œ¤{Ò)Lȉ–ÿ“NaBN¡ºï:… 9ÑsÒ)LÈ)ŽÔw„œ/Øž38… 9ñð¤S˜óEÛs§0!':gO:… 9ñâð¤S˜ó%Ûs§0!çK·ç NaBNœ <é&ä|ÙöœÁ)Lȉ'„'„œ?µ=gp râ,üI§06çFçœ]w Ã;Ý\L¸tõÖ]‘ͱžÃºú‘+zÓíJ¦Yšjø>ÙëJ¦\i.c¤Â®p—Ë{{Oó74Äù»Í×('%8„ÁƒŽ}Mò öGÓ[øRn’C ®gÆuõ[´ÙÑ„­Ë;|Èüy@€³oSý´ÕTs?ØÔpšÿ.®­ÿÛ~ïJ&ë ­-¸ý訴¿ù/øåß»’±Ù½÷ìmVY:7-#âÊZ.}`²ZüÛl:Ò_Ë?ëCV(g0(»h qㆠ¥D2XèJó:Øœ þéf7¶Zïð¢>‹©+™!º0©ö!Baª}ˆöªjò1¾å(bˆœ^¨­ÖïÖGÞUÆw¦2uÒ2F8ó?Ty…f‡.Žk¶ßfW2õY"S­»æ7LìWõs˜¼C©ŸÃÐX ŸÃ¾÷q¸.Fš¥ár6¡Ya®VFÔÎUýx–Fp‘¥öÚkª}„\S¨ö‘BPš¥‘bY¨#ß×PwéÌ(}am†åCtÐQq­ÍÜìŸÄÖèž‘ƒ„ITÝAÚuªî oÄÕ,®ê™WwÈ ›}ÅdÕuÏÁ!æ‡dÂ-[³wtªêJæ¼8û¡Úýþ .Y´ÃÕ®ÒNŸ¨ÜÂ<wsMÔîr¿Ihq’k’< (Ǥ/ð­Ë̤â\“npdÒ¬+8‰1?ã_F™ì™2Of2Èý+qÓ¿9ÖŸandfÞú@-]»¬†NÌo–nšÜ€GfiÎÕ¯YoŠñÈbkh/!†°ðÈ‘;ǵùô¡pò‘º†jVŽÔI»þÈ7ð­‹|»<ˆ!Ñ.6‡f¸ýkqÍí×€GfKEZõ4z?[¸K}˜-̧Úç\×:çëÙäs­º¹šœÐGΕÇœÐàÊ'4ÇUÎ{éf'4Y]Ýx|ž\3ifç}œoÍ缿ç'4αÌQbZ×1º k*ŽÑ½@SsŒP“fn¾®ºš¹ùb©hÇ,ÐåQLÓÚ=RÊZ`êÈ „3¤:¾€¼8¡9¶>®ÿØû‚wBÓ‰À»öAŠîŽæÒ:VNe´ƒꢭ©]¨Þ /,ÔÞvX(çUÚ‡ ¿Â·˜ï‹´/¾Ä7³'åöÅ4€,¦1½]|UÜ£ÅW Þ pŽ•ÝظY4géŽéSÏ­ù’BQ¤;`6›ÒæéxÁí‘î›}=LÞ&%qySý¨T0áqQúdÝ=6oÖÜg¥f½­ËçMw¶('½™A3¯‘Ñ‘ŒÞ(àÞ|é øò 6½ÙÛžšÓ›QÐ`ßï YôÊëŸPýþŽÕ›ßx\½ÚY½‰î|B²Ù{½ùÜãÕ×8¯7 ¨ózóºÇuq×›¨ô 1XoöƺÃyBâÛ½ù£Çµ7½Ù›3—tfo¢£žPo¬|ëq±CïöÆ*ä=Ù ëö&:÷ I½Â;~§ˆ—Üý°n]”û^LÜzù£N\2·¨x´²zÔhÙùÍîáæ•Ój“QþE šë’õ Íɺ¹Ò<Ö‚wÑ]Û†O¿ù£2[ñ$Õ ßü„ŒXñj<èhÚ~î !­â—Ȩ_ø„,Uå˜Ç•—ŠxÊѪ{åãÒA΄Žóôd‰ØÐ™åÝò¨ Lq&6t¦FyÏ{TפXI:ù®úÀ£òÅb\ëhÆŸýG¥‡âKq­#WJïâ~ 3Þ‡Ÿ`ýW~nöq,YüðP”µDøõˆ±ÕË¢¬¶Ø ÞBé² ôþÇ+·¦y’Iìòï=:A¯t.“ßO{ùÔǶˆuiód¢~m¾Ê žØ¦¿úø¦®”=Ž’ÉO‚ŒdÞ“Ø(ÿ0èJÆ=ß*Ÿx–ÿõ1¤Y~Åc¶ò®ÇqqùŸƒÜå’ÇÀ|yÝcg‚Êñ_ Ê£;n”×>~@9çñÛLù³}Ê]Ýš*kŸ¸_]úøQ¬²Û÷¹{[±¥S½^–^õè97÷ð3…ö\±±Ä ‚æFîècÄÒÒ/Ÿ+åMþû¯/-?Ò2‹â·ÐÆ—÷—ë>?EFæw£Žž7e¾æü¨ZšŸyü” ™¶¦j]ÁÆœ;r7äTü”³¦Ÿ< ý´ŽœÒÿzýg\Îù!~Êý;¬ž È›ö‹Ö¾íSÑëßöíè œÕãÿ¥W'¼—óŽ^ò­-ø!wZ †ÊgM †\§Ò9AÉêDØùß-–Ƙ[åmÕÎòÚjod¶¶õϰfé¥ç…y´ñS‚[{U÷=ó¸#gCNÅÍ o}{v!ïÆoÑhcÉaµÝºzqÃiêRüæu§Íî+Î~çs;Âæöø%åÿ6·^ŸnÛÛ}­³ 1øÂ§Žæ·áEæ¡`åPÊó©süþr£µg×Ñ盬ÏOz(°ý\0«âßúéû"®Vn #°qŸÿçcD¾E~´c2›žÜ1óªrò§,\—?eU)ú¿ Ñ 63º1ÃB—IˆƒÚ·øØö[¨+è kÿÌKc‡•n6+ÿÝC‰öµÓþWÜàõEaç{­50Ä×3"¾ÍçQ¼6è £Ë–û<ŠQ!ˆ¯nÎÞ®›þ]½gé©?0ÿ«ûç5óŸëBÿdþ÷yN8«6Šfuk7>X¶Pø¶U;0»;tÍ-zÐFwú{xä;ºìq‰ÍøÂõo¼×æ¤Î¹ÞtÙ­&Rê? Vo>ìÿœ!|²Ü^‘®ÀŽ˜‡›ò§T­ÏŸÒá—¥È\èÂp8í†o3gc3sö¿ü²Üd3ôŸpÇiÌ÷Ë˾cn¢›N ÞÄÍ%°î=ÄêØEŠŸröê³àiE7Ø%õÜÒòu±?;}¹t㡦ÿ‡ÌÕ¸O<„öÙ><¤™Oç_þŒÀCviËû6⡾æ¿D”w%Úêß¡w÷«‡ÕÝ'{#ó 4sãîpoÌܼñ{c¶Ç_ÄðKá0uÿÿáïásÞ/Åÿ¸9±vnóÑï´ñ;|41oeò蛆®˜7Í;—™³ó&ßF}ÌÛ¿ß¼¡3½oÞ¬¦´7|1IѬ,•Å‚ö.Ø“ëw-šþŠÙÞ>éÛÈöñß÷­è‚ñUôãç¡Ü]>€×®[Ýs[³9ÞÅ^>E³e|ŠOÞÛW] ïî'ü“k/FßÒÑ×Ü;9z}±†þtô¢µÿÍ)ƒ¸~äãq;3WÝW†ùŸ‘öÕó@Èç¼-`ûo†;tó6ÏQñU*þÏQº›Ê_±ètqÿmæ¥ü¨¬»÷†²ïî’zíži»g²»‹öÌãw—?é|r?ûðÿãïIõÍó.ÿe‡»Ë®pw¹ÍfmýÎÙlxÞêè§¾¨¸‰VPÝ=øC(ÜD÷ñát¿¼²ôCðáòº½‰Z^Õ¿‰Z>\_7Q4Î÷ÝD­ƒÔS{·ÿÞ=ÄÁÞMý÷ô°w;üùtïÝÿu;3{×Þ;ûØ»¨îÛ»Ö[ƒM¼eHѯ½;ñ¤-÷“޹tž\þõ6R›³¾ nQïMߢþûþã6²a»°à1‡ùñ³$oxËlDûprÚcÎCÞ}þó~K=ýôÀç¯yþñû ¾=öö?æðëÞóÏcSØ=ƒì¶Ânó~2ÑÛèÜm“Ãæ(ûæT³™Î©<™Åølâv;Íé<á9¨=æ¦ô%Àw‘¡•kÌÐ 1ÝrY,¯bFïGHBîE7þw?BéíÔöjMô¾¾Á»Ï¼ Mœ—/V¾³ý^Òœò>†LÏäcèÆ^Cÿ‹[å}crõþ—ñÓ¹?‚çCíŒÔ_¾fz½zØ<Ö«JÕÞß. zsÚÝÔ•ýÞœwtåÄÛMoN‹)»râë«7§½ tåÄwΓžgBNÆþIÏ3!'žxžô/râ@âIÿ2!'ë¢7'\‘zN|N=é_&äÄKГþeBN¼.ôæ„?Vω‚oNË?ëʉ7¢Þœ–[ؕǽ9-Ÿ´+'jë½9-¿¸+'šì½9-—»+'Êí½9-¯¿+'>“žô/rîó›¼È„œxeéÍi5Xºrîó¨üË„œû<*Y ¢®œû<*/2.çýÁ¯ÛL“ܵöúƒ)Ií 6"Me, ±è2S’Ë¥ëùF•]—ß²ÔÌä8±¬m¥+Lù¢XQ®ü^Wzi™/ÜÛX?hÌ㥼Á%A—¯T]– ¿xÍ¿pbEx@¼èŠ\ÜÄ7îa¤Ð ¼*x âªöWMYÕL‚U7\go|¶ËÐÛ3ï’ÃFß WKúkBÒd5Ê=“®r™£­Øøy¾õ¦QóI¨DÞ pk‡w‚&N`#ö÷¢2ÆÕ^ ¤ŸõoYõÆé¿~ªJÕ÷cB©¾3Bõýp™Iõý4WrnÐ,4#u[‘Ÿù‘8D‹¾Æ÷ïÇU¼~kôÎrZõ(Ûï£>>ˆ5²ìÌg6)¼Í:˜þFÉ?º´Ÿ²i/ì'µÍî~º  ôí‡?Î×Ö:8¯{º\¸´]ãqrÞ£nŒ’Ò½nœ|C¨ÓŠW¦95þd¾Ì·œ&QÝ_޽¨Žçv$_vÑAëâ.Œ½Àôbœ„zœNhk¤k†;i‹hgÄnÄOËAò!$p°*8øµqµ¯}[²¹kÕfˆ(Ý“:ÞÕk&´«ѱ]“pˆv´6Õ!tŸ]}ˆüx¨T‹võÃaÎÜÕû0ew&h'«ÿäxCý?T\ý?T;Yý7¾hÔÿCå‘CýŸØ×>±ã}Gÿk;º'LÔäk’'jÔ›‰æƒh’꛼,®urì(eßžë®n²n ªn²Ð‡æ`²:­‹Éaº= ¦›“¦ì0uAhdŠüh¨Ú){ÿ}LѶÒ,OÑUW34E÷q!Ê)ÂzÂ8̤ü9îL4²³å.Ã-ɬ¨àÔÇ„KïÚàÆ¤wz 7`ø$Ê}wéœ\T*ô­ìó„”ìCK¾R:f<þBV<.YZœQ:fÂè¨àï×ç,Î&¡*|ýãBå/;%2FñÆNßÅL¨ä-Ë–^Æ@‘ø nhbO}\;¯øÜj¨ÒU µy óW“‰‹™òsòÛKQGãúB ü-k=UòW7*¶à Cãñ­Çåyœ‹ŒÊ9Oèà,yBI¥ø3Ðú|ÞãúÅç–ŽÃKKåó HÈèÊrÆòöÇ• ŠóSÚÈ'>NÑ/¶¼fFyÿü(—¼øæÒñcXs>Ji.~µt<€¯´Ë£ÌÚ"PUXÿGBeñ¥G0#ÉnOæ´~=ŠãíÊ G{=à÷TžûØd–ó›ùò…m“ò³ÛS•>¾Ë/yl­–ñØÂ.Ÿû( ]”W=†[ʯz •wz k•_ñŠ+?ŽËÇ=Iï~ ì–Ï F—§=†ÝËG>v(_þØY¢|ðcû(óŒ1˜ ûpüÄÃ_¬ˆ†Y³÷$!¾ƒ¹†ýÇïÇž1¼‹ºgŒ¥ÿîÃÔÓ·‚g ÿ¶Ë3ÆqEè€îõŒáóv{ÆH{Ø'‚gŒDŒ-”M_U—¾»ë29vÄzꦟÿªÇ¸Ý° ¬ì¿í†slîaƒtjì s¯YOç^l3÷b;6&Ÿœûr<÷ÿïÜßÿ«¾¹‹PoîïÚÇi•ö0÷~ŽUçŽ8¯r‘WÿÍ,ëÞ6—jïÈÕÀÜÿwLàçvÒ¾¹7®)ÝÜ‹½„fP ¿«é’AÍ ;¼¾XN³<¢„&·ƒ{ÚÁR©žÒ•ìÅϺŒW:ðZô~žÑí-øiÙÙ´Jž¯¯‘/‚y Cû隟¶y¸Îæ­k†ÈgæRß½3)M"°Ý4·ƒ*ϾÛÕxxòc“S]6·ð$¹ÅÁ3øOH¿Š'Á¥®žOVÀ“¶žûK>'ÇÌ},¾3¨¦xÁ!?9L§rR׊ϱCômkÑqµ´ÃÊÿ/÷8Õ0SõUs*¾ï–€æ¬föMúóø]n椣Åñ O;®Ú—=Xwr\—rUûÑu·x=s“aní¢ÕÚE˜ÛÝè²[Ÿ¼±ýÒ̽Ïí$‡Å¾Ëe5cûÕîbS‡ÛEi·¹påVw–öO1*ªŠøv·½ïxöHJÜ=îG7— Ý·$ÜྜÙW‰×Á† ßyƒÛ°Ñ·‡½=·_¶ï”£Ùsh,pß4HPåøÍS´ç<.gÿª÷Ùý¶pÏžø±ÚoÛ‚ùQ¡Q$kôÈ /×ú:Áz ·¿£—μí%=CSŽþợWsÉæ±šKhjy&TžÔÄ 9QFzÒÓwȉ’GoN‹q»r¢éÓ›ÓÞUºr‚{zsÚ\WNôÏžÔªr9V<îºVï~âw›šºõ¬)=¢gÅK]ÊòŸ- YF!PQÑ%Rû½"e.ñ*r®.æy¿¯1£4e”ߥ)Sx–GŒ'׆a¦85Ò=<‹fJ8ïîP—h:êo^ˆ¦®á| %6HmFÚ €@ôͳtãb§û?«Ë.I\n«’Fº@%ÿWÒ¤\ª¤‰MG%Mæ`¹é}®ϳÏ+i’ª‘.ðMrH* ‰~ª@½î§ × 4“uÕæÂ¸’æXjÿ>m´G²^ãí§C)¢Y~εoûKçM~ ú3aòë= %§X~פ‚ƒþ_«ìÿÝÁ*Ñx€'c¿pÓ´Af€úPhh–H Kj>äYVº$¤¢ù v”X<Ð ˆ9Ñ(ÀµÇ@9 ’.Æ@Ô¹:´9øR7=¶¯¶Ë¦)`›á7å÷¾/Ý ta¼vú"^»å+¯ÝÀÎôÚ hyMï1·®;jÞOêB™Ïë;h®ÓqUÕ«;3§ŸÔè{’éN°Ë¬îNc½îD[Ððž×éÅAwâР;1e ݉äÓz2ɉèc„/ؤSðºûðùƒÊÑÕ7Õ KñlH^|bGK”÷Ìö¦–²YQÞ¾Έr_‰»Ô™Qö‹æ—ˆâ¿`VmMkëÊ(÷óFUÖcf'ê-˜µ$ÕÚšZ!©€Göå¨E$Ÿ’ì¬M¶¸pM1b3Ž+ûàÑ(V645± n€oY,GbZ”xøðå|®¦“Â~¥¦“„ßxø"å¾Åiiüñ“;OÅð_[ÏéE~½iÕXš{üú‡›ÿæáÎÆ¯x Ä^0ñe¯®øéïàŒë{,û,9×ñXtΆ‚Ø“Âä5†Fþã×—×—‹·ÒÒÅh¨Û»ûð̾4bðFß">…ÓMovºóŠåúëóúõ×ëš÷S5ï÷j°ßûÁ§¢CŠæ—WÍ}Hn¢GkÜûÏÞ¸tò†Š7x¦º ‰Šæ[¥âÿÍoû°˜3yÈX\5çáAc6~4k\V:g­!ÌW?kº™¦+Iÿ<1vÚwíÖ;k07öí4®è~ÖPí÷)I1°ah¿vnæ&ÇyþÇ|~˜Íý‡B˜ÍcBZÛ-þó|z~<˜c^˜Õ5aV?·÷"àŽçűÓÐóû·µ>gu¿ˆa§ÁY~µÓŠ(ñïóFõ_ç¬OŒöA{`§õÎZÝÛaØiÞ5›ð3Fó;¯p™GÛKŒùò=žDMŽÀ!xwöÞºïî¥[w`æ1n^¿¸> 0u6P1Þ…Kÿ¸ ½?70ÇüÀ)¨c꺿ÃyA7¨Ãß!Êò%Øá£œGξfuïí[bVí>ýΰÖöéOæõÿÎyæÕz¨±ó* U̬–à³>ïyux&Óðzüµ,ΓÏõþýs.‡ÉñÐ\ï¿}÷¹€šëÉñ\/ý/wH?×ܳü\3ãëÂŒ_›™ñ8×fEƒÎ_fjœŸq¹aÆËŒÍ˜†˜ñs†˜ñ¾#0ðÃ3nï—ßò>fß5ûf\sü4J§F–÷Uî¯Êw0O_²¹ÏÕ°Ë43ºÕžC·½ôjnæékîÒF)÷@UÕêòfµÇí4Uµ´–œŽ¬‡jYÝyŠj¶± ?÷ßúd]VwÑôðw\wž@}÷lêﮜèÅ—ìð«…”Ðÿ×_é åý¥–Ñ]§¨fë  ¿·ž½ø1YxÕ;vþŒê£——/ÿËýFmŒYÌøp|Ы^Rî7Á¿£T=ØM´à&´ ‰±›ÆÆ³{O¼&gvS”5$Ènèûk÷QÃäÌn*î?Ãn:}‚ÝÔíý¯º›:¼ÿé¹Ö ãŸK;«ý»`Zù*A—xÅ;¥êBû~‹}¯)-ªÊYÿôªõÝûJË_£%&æx·OÒE`Æcç/,ã~º`Ñ“˜Ñ÷ŸoôGª„ÓO´þ¬ª ? ÿÒœ ©?((Íø¦õgÍPýYô—þ øD¤u4«Âú³n¨‚þû—þàyþHmñˆK­?†*èÏòÊÿè›ÔŸ&Ögû¡ÖŸMCÌÏí|êæhö›¬?[†,˜Ÿþ£?êˆé<Ìͳþ\>dÁ~ü¯ý‘*g"ObÒ]:Ùéev`óæÃ·~Ë¿‚þã9xím®Z|íe«Ð=_±ÎáØsªƒa¥­¨¼g/¼1ÿî>ýɃª4%õ½M:®š\pâÖèv4T¹‰H×QºkÂÿò®~+ðøºÉ«ÀÀ«g.Z¸>Ûµt¡fî{Û³ «Î+8l|vû‡š¿@ÍR615ë{θËl«¡?wäßݵ87S·køè6s¦\ªç^úü ßç­Wf÷÷9)3ŸÒWïýÔ«5õê›§Þ]5ÑœªõxêF+¶»^åR½ÛÔK÷Wܘ‹Õâø.4A·F‡XÏ&wž]H¿¹iþ°ßÔÖýõ“+Ž:ÁëºÍìÃëÉpx&ÇVU—/?z\ïÖ«¿7`õ› «ãˆ¨«/ X]û)ÝURÊIPìV:«O¤ãŽmt^³»õQfùfùKéµ­j}zg-­úþ†5›;õ6^fžô½ ö"Z¤š•¥]ÑäÌ,äys4Kwì­QI±›/åãõ0©zoÊ*b¯Ý]uWþÝ~·­¸iën[šžõs©{Õ-ÅòM‹×‚+×ßTì´t©Oo÷ì„NÝrM“Ñô—ÆôÎpŠÕ;§É«¾àÓñ™YI÷ž›³÷ýnNtOZTõ}öN4eë¬ì:7šÞ;+ÔÆ›lV ÌJt~ÕM¹Sªö.#å;R&Kzöã¢ô­ìÜhúÂÓséïÁÅäwsÓææÆÔª÷{榯œÕûVê`À)ACö ·èî÷ñEZ»{y4šª_¶˜üÊÛ¿Ég`âsÈ?`2Óv,šN;öËG€wB¿cåÓ/A¦ÆÕ«†ÊرіûÙªßüeÇ~%ìŠ/³+\}ÿiÇŠóÒ³cçoÞ±× °c¥¾©yiß¼go‚`ÏRï*«·¯†]{›Ûµ§Q°k=¯‡]»Ìv-þ;wí½a×âƒÑïZi7'ø*ìÏíeÓŒ­rãY>¶}"½c&½ƒû<»IÜÈŽ}Cþݶ;ZÝ]b´Û³óŃšwŠí½m[÷yüÞ›ïö^©ànÝäMÞï½ùz;—ëófÏø‘ïY71‘rü9ýpï£t„òYßÍêÇVíaõAoÒZÇØìë»ýŠÍ³ó”P¿`ž‘žÑìÎ2;ëÙYÕ90;tŽóôÌ.{£í²Ž› ±|Ÿ‘Ïï³9 /Ô>;ÂámvêÖuŽûlκÕÑD׫]¹q¯¤Ïgz‘Gý"G˜ jÊæÂìÛ½ùç¹P­õ;ÙæËܔɚ݃þ~ÃÜ’ÙƒÑM™=ŸžÙƒñ¶Q¤î܃×]sí¾têEŒÞÛ@8[û|´tyÉ57ÈÎw„nŒÎ[îè4ŽÉ8B`NïÊàï„‹œvý#wÂkã^hÿt÷ÂñyØ}½Èöá÷nxóã^<|Ã{’s³Ìßð³ÐÓsÃ;'sÃ.²³þœAžâŽpÃ3_nÖå¸2¡'ñÀyõ•¿ÕDZº5fæ?ƒg;óž7etl~Ì ÃÃ7>4VT\µ/;Ý`b{ "·êñ»zt÷j¯“cësœ-pLVÏ“7aÿÌ;C¸D×ÄýÔÞèîçwy`ò-lû)ÌÝÑOr‡~ «O냣åðGZÏw1ù[ñÇ4€¾”¾}ý‹Çë€Ç=çr[À!^grí&”<;qH[ÐÒ>Jw“àÞ!Z¸}½ô­ì&py¶›¾ùšß0Ë÷î¦+w“â»w“¼el]<6`páH‹Áçéýœî/õ`Ïþúî{Þ½¿Tïîý•õ¼¶¿LÏ…±ÇÞ‹±Ûµ·löbì÷œú°gÏ}·ïÿoÏ%òònñv_{î³aÏyÎ#{înÛsøèÜí#"ßs«tÏ颖 É:O7¯úÛ¡"0˜Ûs}-`0×Ï> 0X¾Ãú¬Àa_NßEû:Àa;l?]9¸ŸÆ‡ý„ï7š4½'lëqâ*þ{_r÷±7§Ý}]9qÑ›Ó⮜x×èÍiï]95µ{sÚ;XWN¡U~>ßRÆ( Ð ¡”Õe!¼²ü§hê+ªDža+Óc× •éý^d37×U‡)a}ÕYQ½ª³"¯³ª³A­T ÚꪳAHFu6ÈI°êlø§¸Î†z´ÎFùcQBÙª³Q(Tu6jòTg#÷Qêl’Ê’êl2´M§Åu6öhMä¤NãÇEuö“ú¸êìGŒ:ûéÒ :ûÉËŠêìÇ-–:›Í½µ|º|·Îf¹ WÍr¾¬ÚšáôQgóÍqýå¥Euö—QÕÙ_›@uöÿÛ¸Îþûhýå™DuP½ªs€Ü¨«Îº~¨NãÍEu” •ê¨TçÀº¸ÎXáx²ÎBi:è ”óyÐm‘ƒ-®©ŠëÊТ> ýµü ßò]Óò%¾5;ƒv‰ë´K]>µÍoŸê„qêD-Ô9è{qƒ•Su–3?½¬ë‹êŒo*êü¹Gë,¿.š›!òÕ­¹¢+—æfˆæ_s3…yæ¦UÛZsc¼\knZñÄD­µÎM«±êlU½ªs¨œL¨Î¡rÍ :‡ê¢¢:‡~0®s(ìwê&ªsXÞ£uJTÄŒUç0)¨s˜æ_u£ê.oĪs¸|a«ÎáïŠëþ®Gë.ÏÁªs„êU#TêažpFpW¦Îòæ¢:G '¨Î‘3â:GÎx´Î‘ÂVâØŽîЩ½£=0J¨H{`”ª4[£„‚µFÉŇöÀ(sD3ê'ýuf¤«uî§¹ÖÛýtùSûiï¨Îýä¹Xuî'Ç8ªs´ØQªs´ür«ÎÑïˆëýŽGë-<¡·û ek.öWšQãûZ½Û_¸DÞǨ1FÇ€OðtïÕ¡Éš8uÞxœVç“÷uþ0m uþ0mZuþ0muþ0Xt~Š|™¨óS˜>:?ETç!ÐùÃqåNçÿPÜùÃÿ.îüT ŸÊÝŽÎOÕ^µM…›Lç§~7îüÔï=Ðùi-qeÓëݬ›Ø ä\žŽÒW<´¨çÑljß¦ÞØ§›#¢×þ¹ðZG-3kâZf•ÿ¹ÜgwÔ2뚸–#>úçZžvO-G×Ò~àŸktÔÒþ¸–Ùoøs-xàî¨eŽü?©–¹Y®…MÖQËÜ3âZæµü¹îTµœ"oWÚ¬§±q•rºnÚEË…™…Ï–ë%,¶üÛ| Ÿ¯†ã™\ªÁ0gpÂiÿä—£Âè8ù;äLùÞö9K.'åÜà,»5=í&sCe7¤ï™Ý¼oÚ éw©Ý¼…þíØ—g©_ÂbçèB¨«ç9ê»0óÓ¥Š#&ÃÓå2K}|—&+™ü{¯Ä}*¾½Wþcì*dÌ‚œu.“ÓÛsaˆÄà»ó@0½Îë¹àQ-¬ VŸ÷wõI®“µþr§±ý©2AY4ë=>i²Þs#¯í¯Ïk£àËl.È›Íïºçbõûâ*Öp˜‹õÚêq½0²ú÷L)âk.žùõx..¯2رÌÅf¹¸”Ä\\ĵ™¹Ø(&Ê·‘Î5.æ6”gø5aol*‹çbSÙà\€c³I¨Mɾ¹ o6Ù”ü—¹Ø$¶à¥ÚšëË´7„/Ó•[óýl15´Ïž}ßrÁs¹¨îŠ—Ë½X­Ï‘S2]ŽŸŒyyŽ0hž#¿eš›çJ½[óð<íAÍÙó`¥Ä Э"¶iGnâÔM`+µÑš­Ô)·¢Q×uñÜl½®nÀṵ̈ :Îu!‹ÖÑ&Q˜äÍö?›²>7ÌF67š…úÜ<Ÿ¹7\©[šææJÝlåb›X7ªe›<õë&µMÁ4KWéž!€^ÌÕô®,hê¿„N  ýRîÜ^*MþK¥É ÍñÒ7Æ~é݆ª]Mk]Ìæ¼Öo&»+S%qU0¿—Ê]¯ºÿSºyªû;µôz'{‡î¿‚Y¦û¯Ö×¼¾R73uý•BŸá_ôÚW¯”¿yíËWê2¢wð€:}löÝõtÒåõÌ—’WÑÕ˜;Û«Ø1·¼Wq{Š™ûWÁn BÓ0ë¬ýÌŠóÀ'Ú'Ï\á¿ü‚¢ÖdM]\¬Y‘j­»]¬ò~¹!Ñy6GùW¦ZFWb†—¤ZF¹@¤3×è…Å`& ÂÓ×z/þ¯öºÒ”žNONu$'/ÁßÖ%`µ‘É® '>!l^8>YKÂaO(NJÖ‘°ü„ôwaBr å -îÂüd—ã¿zB»0*¹„„Ï|B­º0+ÙÆµïž.œ˜¬kˆòßü¨°¥,€sëêZ£Üga¤FTð­ÇeO“uñþ9}ö‡—Uù½†™Íe»§ªÞÍVºi°¨ÝÉ”Gw‡5ÉÎ(ï7KÚ«„ŽÒ¶ûžêdej{²©¥ºÊÔûKÐý¡íq¡¾Ê¾.µ¼;ênKXÀÑçã›wdéàÍòí*¾Ey/Óî>Ÿ[ZR FþðãJ]ÅU¥%ZñŸz\ò¨øÍÒ,•ƒ× )î[ZrÄQþÍå³þË»?ÖòÓëtéŽRù£Ípùçí‰òŠÇvgéKîçÊç_ü•ãÇ•c‡+•7?Ž„*/|dUrÇo•g< +ß{„j’¿‡oËßz ®W^òø% ¼÷cG†ò·;_”¾òè]¤\ùØÁ¥4üÑ#Oyîc×£Ò˽XUf>~ +ñ±3[yÜc¼RÁ£GÃò'»F–Þðè´|çc§ÕÒO=^GW¼ï2X„ºÏ[€çü_ÌŸŒTŠEa„‚"Í ]Ïûûý°4UaJ©À6oÿEŸ¾óâ†ÿÐa£)6Å4ÐhcRÙö…q³}ù®±ASŠ(,¦”&xØÍòäèúbk1}ùQ1ø¤˜fDnúc•Åõ…½bûò]sz¦¢”Òÿó(uÀ”s}±µ˜¾ü¨q9L19#  Æc6¨-æ{¶ìL1"²˜bÁLwôkL/nÑöhΖ£ÿ¦œÁçZ™™ð‚™ïš43¥ˆDkJi…'7,f.™™±µ˜™ùQ1âʘb†.) Û€‘íËwv™R ”á°ÝF:.Û[‹éËŠAc€bFBÖ%âí Ðö廆¥L)ÈPÊ(¸Q£¥Ùäúbk1}ùQ1R¥1ÅŒfVÆ8a5SŒÁº¶˜ïYn2Å`®ˆbÆÀ€3"°nǸjÌŽùq9Zy¦œ6ÈNDìÕ3íÕ›Úî1Å`bb&pÄ*~ª)ÆL1ß÷IcŠÏ×3êßt'ý=%}ÇP£èHÆ–#Ú½)g:<ôÒ[ÉÊYÊùŽ[Ž6¼)gÒ³dr)+gQ(ç;~_l9•)gðŸy9džr¾cÏÅ–ƒ® åa¼]"/Š1!8ÊCÀÛDw·Æì»ó]x»/_oÞ¯ï?ÕÛ÷Bÿú>èoß'ó×÷Çüöñ1 ií &îÿ†ÜØX÷¢Ä´šŽ¥ËÚí MÉÄÈ€¶¤Ð P"—yLÇKXª3§²­I¬¨i¯]–°¤.'V&1'/¡Îœ†BXMêr"å¬Býß°0ÙÐZ·Ãfi«M5×5ö:É~dÞÊñÁºÿ+%Ùÿ¡¬žõ&Õßv ©~c™oì°½í{ÿ’Uù’Ìe;j[NÖØØ6Zy1ó[‘—߯÷¾ïV¾ûå¹¼únëÞ/o„ra§¤f÷¯|ÐÄUäÕ=Pµo]·*K2ý[»?•5éù­]`à Yi;N6gé6,>níF$¸}Õ°akk°…¨wW„å’+‡íLÛ6Q×QiY·SQ4¹É'©ÿ4×¶ý†žrÓßwS®¬âm¡Þ-U»;éÚ™‹V}û§…fófÙq7}ø²®ZìœÍ< ‰SÞ]}Þ̪®U.,á½Þa{F*Iï•åÀ¥z·-‡÷ÑMŠÏ[Õ}QI׳"ŦÊr­jÝtÚ‹‘éÕ·›‰{dIæªÕQ‹ï•¾?E¯|—‘s³4ïuäÝ@ÞØlV̼;lxWôw…Ä._xNt÷ªsÞ×Iþ%gÒ/}/zÃw©Ãökýšoï./AÆJ6wÖùºõö†Sõ&ŽÎŽg;1¹;9ërÊ+ËѤOGÝ%5Q·Ïyõjœ”¨Ÿ8Â2ßôr6›Ë¿ß±ß°}ýìc5+þíö}£a £¼&Þ6ó}(õž=)î|wW3§Ë˜©G7£tŽõf'ûÂïšm/Û5Q‚ÄÛνvMÄ=K.*Ïg³”œ½)Ù¹~a”ÿ1j½kb5–×tÒv}iÛX£d±LMÊ¡™•Ý‚_A®‚·Hçl,j‡Èzb”ßÊܭ굨¨9ZÅ ­Šë‹¿jH¶×`ì(ä5œC çÄ=×ú~)¦}wO<*Z²Žowq|¥‡·’ãû=dφúϦþ³­‡-õpE +¨a…í’Où~)v=9n·yœ?q?æE䇽ó( ƒ™GåðyTÃ2Þ_޼ó¨sö|þ óó^÷>j v+¹Ì›,çÔ{öˆìCæ{Äb™YŒ\¢eç!ÛSßÙKµz´GËŽ¤æë _YCLZL ±ëÙí-Äb¾±ˆt1ìI¾—^GÝÈoûõ®#º¿µëÈîOìšèÞk׃º.ˆ*ÕŸ­ŸQØõî¬4Æ2ö'…Û˜µÿ’;±ÜÛþ#wÁr/ò¹s;ÛØk ë­1¬·fÖ[pê/¯âí—± q,H¼ŒZµa8båKZàÈ»!•jé=ù®mFÄxn‰cÆ¥³ën?ÙrpZœjïŒø ‹Á9Øe1˜%Ÿ³R¨;,¦–%‘ÅD.HÌ®9’*‹I˜.i ïn²˜ØQÉ×2ï Ã,&¹ÂÌsv.MŽOeÞw±e™ųCÌYý Ö’Ù­0± Ö{¬ÐÞbï$˜UºÆÞévQ2«J¼+ïlïtŸ(Þ-±wºA”Û;‰W–ÍÎEŒE„ò±m‹Xö:l[”¯SÜÚ¶à.‘ÞA8E]¢ióΩKJøgW“ÍÉöD]²=YÛž¬K44'–Õ4¶'ÚÚkP%Ò•ßÝ74à 2f¾çãîé¹.m5Kûh;2ïØn1öD¯Ì;+EhŸÉŽc´ÖízŵÇ?3©:o䤣¢5“¸aÌùÍ®‰‰7fÉBò9ÝPSvhé†õ²"Ê{?;~]7„‡‘F ì>ƒÔgƒ ÄãIqðDºEÒ»¸ôÔžu¼ÁídªÕÙ,{Â~×cWI¶U°ÖÔ½_Îî]Ñ^kùæ=ö~Úé|ZrÙ]*Œ£~ÊîÏ©ùñ¼s«£¯©ÇÊw?ùn¥“­—Çx¯ô~bº÷ÍšeïVa‹vÅêÓ¢½WŸÉ:¿­CuÍéÉKœ M<2çÛy{¯¥ÇíHI¶#&׎ŒdŽ ªw¤ë¸´‘Wï§vﳫ³)iz>&«Òb#¨¹Ýjž™Æ©u“ÒÝ|j–W¡“ÈLcãdÅâœokž4C£eÝ„»ÄN zø+ãÊåbm¾vƒu]]Š5¬]•7Âlç¥v™ÞÏž©b#[—´Gû-«i®kL–µ­l®-_žlnïSr;K«ÜÒðɈ€aFÛ;väÖÌ.Žº3û=òq߯gbñÈ€aœ§!רãÞ9+F±Ä|;m–Ü$?”n_I·¯½‘ìkIü=õÆ–Öd}’3åœÄ¼ŠÊĔĴùE M íÑþk~hù÷=€|› ù.éhnnh^ªÕ~^jiG[¢)Ù”j•'$—ÑÍÙä•eŽWRNKRmí³“MehÄ´-O¶§kZA æØ:9Ñ¢—Gw܉‰€¢¿… ×!YYD¼ó©7>`QÍã…7q”,ê¶ý²f®Z·'÷¸²+‡ßUܸvãÝÂA¶«&kÏïØ/kâÒ\•»ŸlËÚzذUܸç^?ŒÝ£ûøÓ¢Ê{rcfŸ±'ò½0wò0‡w·.þfá$´cAçÊŠœ É‘oôÆ®9ÁèÂÜ—+eYöبç‡`:Ýȳ\gj¡NwÇÞ]ã6–=um=ý›…‰½¢]ºžB}ú6}óú\m÷rn/`—³¢jkÍIµ:[Á»k4_=V?ÀŒTw˜a‡Iàur‘Ÿ³ãÙC¶(í­Éî!vˆ³êkö™ßmì™–ƒ}á19nÎÜ—¢Zätýˆ}Ölû z_ç>Û¤»}†y¿—µEöR66ž`Ä’Ëš(7®M´­h·$PYîï±¢[X'²„xñFgû8ß)Æ^Ü\4.„e¢Ï3wWD¹] ì(vÍUØ•wskÎuâ|ŒïilEøÓ܃Ôá¶Ékß9¬ØúÓ¢Öþ9n;ovf—ÝE¸Y¬Û^ûRÕ¾ ~oûÝØj¾"êµOíZ:¢¨+§Øê…óz£u®Þ·B—z®³Îݳµoçõ[Yö÷–uôA÷~õB fkí]ÿWåĽÐÍH3ðYúðrÎëëÅù za¸/êE÷âÃé^´ÒðéEçå]œ,‹ŠŠê–,­nh«^’\ÚÐ\Ý Õ»r‰ÛUºkü=z?az<Éýd‹½ƒëo¢Ø#ºÝbÁ‹»jv.4¯ÎÛÈÍaçævš¹"™\Aù¹ëW³®âú<ûÕÃÆ®æ¸¿í‡Q. ô(€G]ß/-ìzJVáZÞì„…ºí©Yþþ×Ö ëU3{¨ã҈ƺs§a#KX~̉{{!o—PSquœ{r÷¿dèŠfï*(Þ•»?<¡è+ÚK;_‚ á— +]û^öó'†ÍD¥ÍÖ£Ù¤æ±Ûê-`!7k›ëš>…Ìü\T´¹`ªdJ òOtkú U»;bËóéíqC¸=®ò|4ö¸±Ξ_}Ï rÅ)ùS<Mß±qÓø6\sûÔž 7í¢%ì¢ù;ìÌßíéæaK͉Éê†Ö—Þ8vsf†[ŸÇ„Ð¥ýý+JÎnZk@êòêI›fÉÛbŠöQ0[¢ÜlœŸj­e86rฤ£¥Oä3âl›qVÍ,¬°Y@è»sn³Û‹u.Ôªk`ßnw7=? ¦·ä ê5ovæä°ý±ûžú]í³mòÞ°¦©fËËñ'ªw.vÀ„°œåäXv±:{mmgÙ^Ó_Ç[_vYáà ۓã(°½d¢Fœ{p[¢–;“¥I(¸¹½cIQbeª#ÑÔÑÖžhNµCž¸,™hLÕÔ‘d˲¤²ljìXÙ{±¬ ¡1 ;X#Î¥¿þŽ í=•w²–5âÜÖš†¶dõÌYÓé´fP—€X½t—hàŠ?âÜ3¨{¹-Ї±›A;vk¾?oó¸¥g宬5†qcîèo>s¤óœ梵¼MÛÂôÓaAÓCωáæ2Þæs<ógyÜüÑ[?ꢙ¡ò‘Wµ4ÔúwâáfaäUeÓü\è¿™ ™]yÕýsÑÞ?#ï›ùѳ‹(Õ …š‘EŠ¿öÎ}a1zWŸ õøá¹ ·QùKÜÖ^Ð Ååéìs:ëªz½NãûÞ>ÒûÑ.EÕÕmÜc·ÄÛ7·šÆÎõ\)lyŽvÅü] ·£Ëb‹ßÑsÃŽÆv˜çŒa'Ìc9 %´‡Üól^°Ö9/à?/ÌHTÞ$Í ÕY,ɾÖHãûËÝŽ¥®fÞˆ£7åÅV-3eŒE2÷kã<¦wä‘0¾Þ\,µ¹x» 17§ÆBT,ëaØŽ"çC–ÂÜΫå¤oY s8¥+çC–ÂŽëÊù¥0‡ƒ»r>d)ÌÜdê9²æn:]9²æn¯]9²æø]9²æ¸8]9²æøv!çFYÉ2{§ÛJ–y'“ƒýב²“yçs°;ëuðN8éIÛZ¦öt½VÞ¹: –«×j-ÞÙàz‹­m­<¯ç0O\ðq=‡ÃÍ&·ÅzÞùð;ê9xçsÀ ¨çàÏ¿ žÃÚ´³9àMÕsX‹u6<šzÞù@±zk»ÎÎwzk™ÎÖw­žƒw>ºõÖr›Í^F=ï|t8ê9¬ 7›}zÞù¾rǩ簶álnõöjrØh÷Îã³jföq·U³Ù@2¸½c¥§?Yù2b‚4µº¶Èì›6ý ÿД9Œo¡ö!"ò©’!2ƒ"ƒCeµJ|Ìaê¦$‡Éžå0n0ŒGHSS}Éd± Ga^ ô7 ‡ ¦ý@TØ¢Ùï |ë^¸j ˆµ)Kà°Ãö^Æ}„oõã@ì˜$Ô5•ñ„Í0¶¡.üÆÂSJ>ôŒ½œƒ¸Ëärtu&\‹Aú.¡O‡`.Á–É!ô#ׇ 0›|(© òCÙlæàPL¨ÿPdþŠ‘‘¼…‰¨ñèûD\@ÝAîÄÎ&ò¿€êÓDþ¨o"H»H®Iô®H&q)rýŸD=Eút¼†ù0ìÏ™‡ÃÐ^(Ê€“îEúvJŠÌÅaô»çu á"}œ‚]¡"õMáPQdΦKÀá_á[õN하ߩ0nJÔ=®@‰ºgq-ÖgqÉ(qñ=‚Þ–Ps9â¾5·G°!Êl‡#PÜ*s%9’J™9N™9kÅ•™ÿ9 æ2<ܹŸ0KE¯q”lkšD »øXžj¶ì¾‰c»E¼U?âØn‘3ùã29k;13åD}ÑS´VŒø©W1ÿ]5CkÖ‰¼êm, 52Ó¡/MVœ1ߤË;£­‹Ãd;ƒL Ê<\¬ÞÙDßà2i.ãØvѼ²Ï„ƒUžSÐn‰©ãT.OX :ýÅ@,gö8Ëy›°OVÐKŒÐžÍ.O¨ïll¿aEè)2–¬™ʪxÆŸò7zíL³¤†ïžJ—˜Î§©ÃÚÎçü+ßš¸§ “¨‚§ën¥ÿOÇD.w̧ËB‰º¼Ræy´)Wé¤y\%³@Òs;WS©í®L1©Sç2˜¦9×  û.ÕgìõÍ6QΙIó;W‰êõybßh¯ÖCX­+¥æv53Â̯:R—ÖêL l²V6Á´“×J#W;-Â^ÙùBÈš¡óuµÐ.¾@µ‹/øõk¯“ô©jY/E&umý§²°Ù6Þ¬ŒÛ/¾kvƒùhfIŠyÈöz”Ï¤Š—x#31!}ë¶ÔFR·/V—õß(jªËÏÒíHÛâY2¶¤mq Šˆl¡KÄkUW/Ñ,jŽ/a{ÐÝÍÔ¢ÛL”¶™¼ÌÚfæ•m´%ëR©Æjk\*n¡6Í¥ ¶Ò¥˜7ãŽt):ƒXÿº d Ò{6Ê–z6ˆ¥›g³1vt9Z… ¿ç€y1 õîé²°­Dˆ9aë=ä¨çžOÕs/sBÆlš$môHýpQ0ƒÙ&Šæ4ƒ`£ˆF{2æ­±j·=S…Å¥ÔOž „]‹bÇnŸ¿çé®§*ž§}©¾mÕ®JØÊ<€¤· -hË<_Ü ÍÅ6iªŸÛ``UûI]Y?yûP?ío›0“6Ï6õ@³³M(];ư®Aû÷êñqÍWOoöÌù]-›*¹šéÃðÏvíBmôíÿgÞþ™Ì©q3ó3gbíîkT³¦ðÝLÕƒkl‡_#³„î7âSq®ºO(߈ïÄ9FÈ~š›§‘ìrŒÔöUŽ‘¿ŠsŒR×ûæ0èÃ í‚æ#q/°§£.çYÁJ>«¶‹^p‹amLí ‡Î)º®Œ‰²÷Ê`"ÆFÙûìe±¶({O©,ôs6êd¨'Ùm7£ FL\Ų8Ö,˜E‡pŠA)ކ%½ÁQÄJ®;XX ‡p€ülÁkô}„½h牜¿“Þ4ÌØÖöž·¿mo\=ðzëÉæû3霼ñ½åçÍdÙ<¿eyZêêÌãgÆÏ3ãg€™ñ}oqµüæc5;Ü­9!lÐäº<—kz\l«¦ÂŮиØ6u×Å®R=̧éÌ`ƒ¤4ÏÍŠ½‰Ø†=}_¹9Y‹V™•8ú rðxí"uÌLuéšd öZ;§!dkñ»Àªnp[[ú†y„õ½Ï¹Ìºj[»ÃN÷Gxh“Ýfœ«–ï 2?‘Ü}}ç`|ù-“Ëo1®(~‹q=ó[ F•ßbôË#JLÕZDIO0Ї 2‹8¸zdˆƒ /–ÉÔw}q/6Î\Íp³1ö“Í+²a/”[óMŽßô΀¹åy´†¦51òÊL‰Ñ]]%MŒîr‘&Fw1£IŒîʾcÚÝŸ·Ð]±.ÌLcîó—Äè)ˆÑUÌ£{‹ëW®_‹1ž¾è³ß»ÌƒQd0yœ…T‡ï´Ìü0·HÌ¢D¼fˆâîqØNóø†1íü>¥ŠÒÚ¨Æb=_›u¬ak#fÑä¯á¿E \÷ýÖàêågì.U”Öæ,œºDmTàk³Õ‡ ÐÒ·øƒ~Ú "õÉÇ>ªŠÒÚ°ßÊ%¼Åኄ^ëN›bLzL‰*¾Ç”Á£j»K™¶×Å»\u̦³-â»Íñ;’-âw$[ÄïH¶ˆß‘l¿#Ù"~Gb«Õo‘_²°EØâÿ²EØ ¨»ÉÕs³í@~ÔE'í®¤ÿt$»š1¼ o?÷‚Ù©Ýј,^Ø Ë ;uþvÅ zéëhr/˜_‡½ÙýR_ô{&تŽOZßQ$64Ö³\sALÙ ¸í ˆì{›¤Ù ¶*|Ÿì;—½”½`#×n=ìkØY¶9(${LA† Ø>{ÒM-ˆ$}ÑǃEÈèj‰ûœ‹ˆçHõü¼ðÊ âT ­¥ž /öT2X0žäçw4;ÊÍP׫áòÏ¥:º¾3ÊMµ¯lIFyïH5§ê룼³H³>å¼£!•ÉV*nªYŠÆQ¼ˆ×.qi„ ’ÙÇWµµ×MœX=£bVy”¿¬wåÖHY2Êú»øñÊzDRWêÉæ(ëòTK²Ù£‚76¤âHáæ%õõÉÖ8_á^ˆVªÎ!ç54£Â¹’¶”¨Íïøç½uÙ7ÑÅÔbC…gÔ·&“ÕqEQÎ’):ÛŠÙÅDo¯]Vƒ|}[¼!DW¦–'[ëS+¢¼éÍH ¯öi¢å-©¶ØKE9Ç—u±eEÊ÷€6º©½E@4ʰoÁsñørкNoF‚k/›,É>ÿÅÌÛ›}¹+[ZSÌÝWå<KöŠ-åÙàmµ)4±l–öFÏÆ ùLgTð¾fVÅõ”w¹û^ÙØÐÖåŽß§ ì¶”y¼{•Å·²?\p%y~Ãà‹r&%[Ù•8x >¼ Aò9½ü ÌŒ²ÿºuY”}Yk#ó·¶H:žUqYµB•/7ÖW×7Ö,msz) hDÒÅe^5Û§®ê?\^ƒMLI¦œ9»º¶¦vY²¯d·TÓBO'[Z‹fIÑ¥7Ë#`{Úy^n3s”è=&Æ¥ö˜GÞ]bê71î²×ŠUŽtí“1¾R—“<ŒòÞäº 2–m¬¼mh^Ö ×~ɈM)ÙFÅlYJ›6'—jÚ][£o´%Q¥Ö *}Û½¶Q:~6¿”%ìl&w´7D9ÓZ[£¼ï¸ Ð)¥¶çêÖ†Kú;$]ÏzÜÔå<µŽ\•‹­b)#]egǶ=Ï]¢u|Lm5cTÙZ½]—sñxy^M:Öç.¾Õ}¯lC:Nyâ¥K£œo³Ÿ¢œõ5Ë©¬q)ku:6“67ý«QÆU ¦Ñ%õ}-ÜàâÂ’ëyb #Aâ(÷åímL¾ÏSyš^áb³p¶Û0®žò—IC•å `Þÿ|cÝY°´Žñ«ì¯í´!µ…µÙ*ÎhP‚âUdÓNŠø(ìR× šj©kM ªkM ®kk ­k¥®au­G06«É(ÐtI1u$-KY ªYÔŒ…Ñ×Ö4EÙ/^Ñenf¿ÅímQöIÞìßÄ›ÍÂMM¬[kK@nILN[^R\2ÞÅ¢Ilí .TعV}è_«> ¨UÖ¶r=yš«}¦æùÅôRÛymëqn–7µ±*€•²’([ä%5è»™ÙÞ†vßʆ1%@É_›ÑÒ1»©‹¤¦Á½ÚRõLÔW§vò4{W¸©v{@’¿ú*¶ëkX= º°¨¾–׿SŸûý~½0HI+^ã1[#¾©¦–1~F=pW·Ö©êŽ–:Mvò š–±µhÖHáMMQþ/§vö5#ž“>ÉR¬lY¶²­]ãæ7¾\ x?-Êú¤iÈÇ40_OvÒ§sé„,D®T~`¤¾pòìEÕÇ.œ;oz”sMÇxàö]m|•ßïÖ‹¦ö²e8wüeYgÙØÁŠ/Ô·ñUš'‰Þ£÷öù´ðAá°6¾J×ÝèùMz~ìñUåQö?u mû6’»˜é\¢œ»:›š¢Ü/2° ¸Î–©nsà¨øõjSܵZ%«ª]¾RÝ¿þÃj\Ü£Zm)vU«‡¥ë›:kÙI%%™ *|e|äx²¶I@ÿèšZç+ò²x¹–aÂÕ•ñ¿6%—ÖÄ,ŸÕ¶¬ññ¨àc’®”J¾N ›j–ò´PU¾×/syc*Êþ|]rI¼¼S8ªFþVr‰ÐßZ1§jF1.d?¬tW5ûY¬þ(gé@Qå*Иˆ=e€et©½°¶"yR^…íHÕŸqåýÂNàÿ©ÅÕ­MŒCå#éÓìÅ%þÅ4Ÿãoúr€Û~¶/‡^DoMç0-aò#äâÖÑéWí/Á ¥€¸¥lÔ¾¯¶£µµ:ÙY›lqпò Áö•,ÊÊÙÌV¨¸ˆÁ»Kâ& P˃eLÖ± 5ì¿—Yô,§ý¾\÷‚ÂHÞañeB.Ç8— F+M”½Ð¹½±ZÜ…l'̭À‰¾³¬©9·Ž”Žc@µ™ãcÝ·¬ä:¡¬tIuBµs|;ã+mËR+\§â׸ :ÊyÃÒŽzÄÎ%$ÆÊ°qîoÿN;ºQþ¥ 1XK¾Í”rõVÇ iÏ­ G¨>Ê?°¶½µ‘íTØ»jÖÔ(ï1Rסàòj8à^8¸±¥>Ê×ÂW²¾¦¶6ÙÖ6µU|ú2L0 LE”ÿ‘†i'ÏGvÝ„TZe‘.V5¬Â!nŠ¢ìw"YÞ^LëƒÃãna_­ä³Ò\á|é\g4y². •y< ÌÊÎÆšx;ÖÚ;%+[ì±àÔi>&\ñ Á4 Š>{6Å«¿x8GDJ>CŠ(· û·Â"ù<’û >¥½‰ÏÙXç|ÀtI”[Op£Ïa—«Ÿ‡H”sm;ëTä?¿R¢ü÷=è‡"ÊÏþ“зŽ8Mˆr΢ºÅé` 0]ùZQðQ2Éq—š¿ +žü'ùÿß,â¹EU›kÚÚ’M íJáÓããXB…UEns l´ÖOÛ;5¦o9ÿMæ5°—”ÖÜïüuö¸Êi €Â‹Zjš‘~ÝóºXøoÞñ‰1j+Ìòp›òtxÙ?…å3QÁ¸´†šn)Ÿ½auEÙ7÷’š6¨óÜ ‚wâ§SØHǦ¨¥a>x•ü…`h!Ê}eéXܯŸ[:V§ îòuYè@ÆX§¤áXGç6k´3!uÅiM4)¢Ü"jÒR; ß¾3…EÕâóøœeŸ[ÔŠÚØÆ>]Ë¡tc’ÃpÇtH —ñÌ-gØ ŠW™NfrEUÎY«.vQn1%j§nÁÿïl9Qž¥_˧®B·¹±86¾*Ç/AG÷e<Ôº>Z€öô|®læÆX8ïšÍ+›–¤™ù‹;Ú[:´f.‹²Þå&Pà›8kK­‘2¸m6ã§?<ãñÛvEaÞqGéÚ?¡¿Âä?b´RÝ}P±töƒ ´Ô~æÍäwjºTIÄo;Sz?CÄÉÓ¯ ¦'ü¹ÿøýØAÞÙÛä=óßäÝBξäMÚo«ƒ¼,o·ƒ¼+·9ÈûZçòlí0ïÐæBì°¬ÁëWLL8;4öHþÑØ­€Ñp@3L»£ˆÓ¥ÝÎ nõnÌpý"‡JR.7=ï3¸’û‘ÜmŒwã3~ïö9“Ù…Ã 9$ÙJŽÓnz®Œ®ÏÅy‡\MÉ…rµ¬Û/jîŠ~Zx ß8Â’û²În‹žS4¯¼J-Ÿ6¾ºbÅCF »œ2½SW7³t޽ƒí·*VW—–Y—ºú×3Žœ‚´Gßh`iWVÛƒø·•Õ~›Ã>f°c®ª3eµó¶F#ÂLýÈŠs?cæÉ)×›YpΤÌ< '˜y‚¹ß9OïÕ²sóD[ýœ âwV|áÆ…ÿegå3Ò*j¹ëœUÌÒs¥Y™£YiÇ9Ö.ÜÁdóVÛ_W®/û÷×Ñᚵ󿾺wŠÎÙ…™;çìÂÄün±¹ƒåÚ9wß {ŒYós祱Q››îÝOJ.Ç'Õ™Ëç-ug¦ï™ÿuÖ¾³§®‰ÍÌÎ÷¾ßSÌŽsÐeæÅ9¥©Î³³Îfå¿ÎÙ¹#ì,æÅc´pG!ݽÈÅÊšåÍÉÕÈÑéÂÊÕU3+æWWVÍK8ßÓxµ¼üèêyü_8ÿEæb)›G¥dƒ[\0àÉÏ%.æ¢vpÝ÷˜Ë’›Ëøl¾ç^;Ù“;™–UWf.¼1wJw^zVgvçäÐHØaB Œ„ªƒUÑÓäö¨štnŸ/ÙA»õƒú¾Ã­Qun­6Ò-Ñ!EÓÊfͪ.ûþóΘ+çüËà çüË(-^n1ô%œ«‘Hš3û%‰¸™e¦ü|!¤1 š7èyÛÝ9Õñî×=ï¼h8˜C.Ò¹!ÌqÖ¹SÂ.lŸôNv®6þÍ5«¢.;k]î¹ ÂEPÀ+½óõ€&éULp3¦Í¸ ï‚ô(†s®$ cÞï@æÉÏ1çbÆìÆ6g¸,蜳¯d\.™qñ»Ñ»[Ô¬ ¹ÅíF]UÁǺ(·¥ê1peqòf‘ëÝlŠU^šìCny+›yÜvÎé¶eÏgG³{š«¢Ý.ëZ•]ˆ»g\Öl®:­à”ɨŸl;}æ¢>W:Ù ·÷cë ØÚìÇNWc÷Ëeb¶#þ~×Üí÷ãâ?ìGip"p޽cή »Ò¹ˆ3»òÆ0Ï·Ø #áÓ1ñ¨p3ì ˜F»Xés ;9nÖ¦‰ ˜Ím m‰,B9~ÝWm~å´wÆaØÉ[°‹q Õ;Ëû3Ë‘›å.ç[¼-œrÔ·£á§¿£ŽÝÛmìR9Jx›âÐ|ÆGË1—ðçœu!·¾çMú»:wÍ6÷ÛÌõýs-¥ Ÿÿ±}Ý…‡4Né®^ü§]mc̢ǮFÿ)ß~osŽÍÌnwÌÌüßbw†Ýþ9Û h¬vî…yCWºn/ ÁŠ‹,i¸Œ|xÏdµ[n6ë}sϊ÷û·Òj+ µ3òu¿Ã¶}àÙŰ×G=veõó{qìÆ°ÌHí&–íå 6sèßvâ©O…™³î@ìÌ¡;!V7ÞoíKRÕ­ š88ß;µ§'Et˜ö[{?æõŽ~¬Å7MaΖ­ÎMÈEËŠhøÄ®Ú¨HŽœNéæqì˜<[ŽóŒ‹"9ÞY‚ÈH¶W réÕ#’ëÅÔ5—sÔ%j²uPÈC>ç­•É[ÁÙZáœPÛÎûr<^ÛÙÁi¤Ë[nåÝüPÛÌûrF7ÎߊÑó7HbþÆ‚sïeb÷X Ç Îq”‰ÍËäð®Ñö./Í;_ï¾d1©Š'æ†ÒÄ<ÎG)ñØž˜söfrø¨O…ÜÌ»‚ç ðÎßÔ›ÂY“ÆWÁ\Á¡X^ð7r%“»èïNêSq„Í N0‹LðmqmßÏ7Nó$“uéÍJT¡Q7–ž­1È‹F™tÖpÿ \=àÙŸ&hçx¹ÁÂ5±ÃSƒs›cbâM¥1ñ©Ò˜xVi¬%ÄZClDˆ±¶bBlrˆM ±™!ÖbÎÁ‘Q€ïÀü%‰¶yÌoûkq;~ÒÕ/Ád>à’­÷4ÙÅéŽÆí®uœÚ²ê3vSéÜÑþ¦òäŽþ—›Ê{£ƒŠžÿ‚‡×sý^Öa{fÿ¤\î+ε¤¹¯ì´YCU¿ó¾ro¸¯0_~ÖPÝgÖtŸ:hÂг¦·}AÌš°Ð) [Ÿ³†S}³Æ|ù[Žø‡×ëÏé~¸—Púàb›Oh>ËÔ|Èç~Ëûßœ€·|Z<€ÿ5£ºŸfæS÷ÅÇ(u>#·ÞöŽyò3É|zœÈ|^oóÙí”5º-p˜/?Ÿ¸HÀy…t<'Îs Ú4â°M‡7›à7•RF1zâ¼Çïþ}6ÜúG{ޤã¢ý—[¾ô`ÑÜ~÷”_¿å3_ÎÝ—™W+`¦ý˜˜¿ Ië1;7û[m¦Ñ§í¼Ù·„kÝ1Ù•"¸5Æï°ÄcüÊq2àBàfQ1Ý Þ)kàýÉE_aæà»pç>àn`çj>ç‰kG»5îsû½½Ê èHƒ3»÷jî4’ß%ϯ„/è\üš˜ÇCÄümˆÙôsŠï ?§hëîæÜä»W³™r¾×^¶ï”£cgoÆO†n!ø€¿1è:/¿­î¹ç=îìm¨ôFŽ­ž;cƒ&A—Ã5sÿš`½ìv:jÝé¸^Ò3çLθà âÒÿÆÝ÷õÏÝ,MÿÌÍòßú·üáþáÔÃ÷>ûúGÏ|ÿð ¡·höþæ¾÷õÏÝLÿj7€Çû×jr<µöÕû÷ý£WûúGÏäø ÷mÆ¥ES3—Ç853.œc7ãà¢7§®œÜôzsÚ}PËIq-Ö›ÓîîœhCôæ´X§+'NEzsZÌÛ•}ÞœöŽÑ•ç#½9í©+'ž5zsº;çîœxÛèÍ™»‰«æ„_Ü›Óòººr²yzsZŽ`WN^÷æ´ÜЮœl­Þœ–·Û•ýíÞœ–ŸÝ•×(½9-¾+'º+½9­vAWNP\oN«rZÇr=ÎÕÌ;ïjŽO=ï|îíõέ«ÉÁ-¯žƒw>ܵzçÎØäèq®fÞù=ØÌ;Ÿ®w=ï|ô%ê9xçs éQÏÁ»»d3sYwÉ~C…<õ·Õù+ ÐKޤ«³:lÔæ•¹$HšÒ²ü0ªž²tÔÅh(K^Úæ±×¥X_‘?©íTº\ƒ~=íõ •ò&ïAÊè£[÷©³¦Š¼O¨y ÐݯA<q}„„Áä3I°´Q+UeãêÞ`iØëí`¦ˆ:ËK¦lˆæH›cÈ·ã:‡|{°«tÏîT¢¼×‰¼êVÁÍR«¶±f©Uî4;­ªRs=TÓ Ù*ôªî•sU=Tît“&â¾|z “KuaêÒ»»€£Žý2Lî:4MÃäú@3;\êùšªár]£.×¾Ñ<—«¹!¤¥ A¨ŒÐ5M¼°ô6ñ9Ñ…lä«â>Œ|Uÿ4ÐÿZ²‰Og|¤ü”¨+#ÍÓ(asUU‘^£î"þvÆ;ð¤7nF‘ rÀûâù8à}ýSÈDdóÁLZïw~vÌïùÒ ·š–åpC8P4}ã5¹º8fRõã…ê5EÉ‹•ª>hlÿTÖªN§ò æUçAò…¤:’ŸÕy°¦Su¬m :–Õyˆ`¢ê,ä@Ì\@p`‚—ŽÔ¿‹ÉãyW0TÂÞò~ƒppæ}d±·½‡-ïMÅúaÁ¯GêßÅ쪟ԅ· ï@ˆ‹Œ¯,šùwù›^ÿ.ÆÆOjô=±µàDdÆáJ$W,Þ‰ êoÄÈéÝÔÐ \³áŒŒË,701¼Éã\D1v”™Á¿M{wÃOI6­89«yÌÀIÍkø™9Ë^x—nÙ —€Ÿ³ {övö<ŸúñèãÁ‡F±¢tŒÄñùj©EòëŠZÒì ýHš÷ã>8T¼ãã¼´µ‘±(¯º¡IZõÅç39R¾ t "³Ñ-OHû—‘Q ÅŸùƒ@”[§XR‡ dÔ –o*’-dÜ5ÿÕ|G Xš áskÿ?—zƒTŽ_T:fÌØ¨à kÁÏ+3ÁÞwò)#SÕ"{\ú/‹Z:Ú–õïu«Ò!Õ·ÅLdñ}T,°9ó e®øÎ"§õÃa¢¯Ö"aðµt û¶ø/¥cÆ#×{꣚RQÞ/aãe5Àá±JQë·tœ5…ÞåFñ‡(äKÇ”pfzùZFŃÈ(eøÉ|ÎŽò¾ù¨ Nqzé˜ i¡îÒw•tpÜÑW³êÔA¡óèd÷tᦧÊ£¸ªõE÷lù¦bþÆ=]6ø´´Ó}¼»ÒSîã³Å/­M5×ÅQ¤'>³œTþ=…¾ø¤Á§Ey7?JG { Õ›PŸå]ù(5YòÖ³¤é¿aqéZû816^Xô’¨ß?ÙzÅ×S¤ÖÁ/?Êî,æa eõ‰` ƒVÎoM5U//ùmÚÒâ¢2þ 3QþÏŠbß,Ö9JXí騽Ô}T0yV”ûÝ'!¶ á?Jä¿@vÍþ§@ÙÚ§¿Î§0÷¯mZLVœ»øÍ{÷Iñ]÷®Ÿâ-¿Ÿ©òÜÇæ»ØüèúXõûÝTø—ß/¼Õ„·ýƒTn~ã”òE]•¦Ç1aé™âÕòÚÇðp<üø¾òÍǯÉ÷þ(Ëü¡÷];}r^÷RêÔûÅü»»ñuV ­@ˆàDZ‡;ÕcŠªp©nJŸi:æÿ`*\9ê¯)§iŒfgÀ9zjB]÷4’®$ŒyQR3ìÙ±;¯_„Ø ?ÔÉ5ÅàÌ‹b`ojdrÕy·uĈøÞþq¥`“ŒR¡<­g{j×ýPÃ#†§)æ0H²gaºbñ®ºò]àë Ø“ñf0™›ü¡ñhƒSÓ ³m¨9©,Šu`ìÒýï_ŸZÞ F™7ƒ?êõf°º¦ùÐö¬„6†ïó=†ŽwWqûjù”%ó`sÁMÆÕ,ž±»k»çKò:Òælø´éÂÕæn^Qé¾à¨&2^þH®éù¡éXìÚ¢©?wUÖ9ÝpKœ¦KóiŸrÚ÷ ç}*j–ÞþÜwæÌ’ž {ÿutŠýÚW]š>c³ÎèZüƒB4]ŠköËÚŸÜ®ÊÛïîèÛo?YmíÝÿ¡Ë|Ögr§L:-Ê•¾öã}ñž ²~KÛ;j슾ã5ÿWÄšÿä4ÿ_ÔçÏ +ÿ“¾Ö¡ ²JÚ `«ú fÕÄçdðUCxŒ:WaÆæy­±mC'xŒx.ä³éu¯8Šx½PÍWê €˜×ÀBOÎ{Œ¨{.#¬~Gæ¹@Û ‡Þƒ?:$€Çˆ™µŸxŒøÎZ«ã,fÇëÆ2/^?,̳ã=F Í¾ÏcDðQ`”0,·sèžiûD¿•ÌÍ~ tM8Å Ýóÿy‰øßºëh`þ Ë›Ó>"åáTñ†1;~w¼ž/xÖã Ô/¶Ù\¢¹×9—÷,Á<ùï]\ÚžQ†§}üÄGÄöÍ>"Úaë‡}·ÏGÄuÌØÿõq‹ùÐæû¡‡fÌë„rãô;ŽYò:ÃÄ<¾c÷y¯Ý>¢[ƒþ-såg ½!ÝÈ °ýGåÿ??ŠCîø˜Ð¿Glº3…YtxúI¼q{ÚûÃvšÇh|ùÆóÌÌÛ 6ch9uÎØ×¾p:N_¨}Æãƒ˜â£¿¶ÝãÃOÙLJK En)£¿6¤ƒÇ‡"oSØ­û9¯ûÛPȨÎoæñ!«í?{|Ð.ý¡Ç»KmŒYôؼ⵿™y¿WQÓðú®ì^ïñù÷úÝļÇv¯÷ø€^ù>N'Ìì4ñø ŒÓv“БŽMTÙvÂ_<>ô©àïa§÷÷ðų[2÷0«Þë;Ùã|t';÷ð]aÞ¬£7xø{Ã3þìïAwxEøÌøÿkü=¬ð÷Ðç‚·‡Oyo?ÆkÞÛÚµþF Ï߉yýf8¿žo@Ìs^¤ƒ–z{ æõº•#õö ÕÇÔÛï|¼óÞ¤›z{ æñ½©·bÞÛ9|Ô§ÔÛƒÞ¥ÞxçoêMêíA|ÄÔÛƒtnSoäöÞ”;õö >¥Þ„E‹¾—¶©ÏaÛâ:ãÔ1O}x{pZÁiÌ{{ æ½=óÞˆyoļ·bÞÛ1ïí˜÷ö@Ì{{ æ½=óÞˆyoļ·bÞÛ1ïí½ÖNoÅpÛôÚØN3JeÖç¡ó‡ ðö°bÀoBŸ ^n3_­æú …Iï5;ˆß©ÜU¼Îº½uÚ9C·¥Ý{4ò™3ñ¬'}zÈ_}=Ì™óôðc ôïs†÷¾9c¶üœÑJ©ñ•áæN=È­º£ÏûAA÷§òŽO'n•áÓé{×i}|ˆÖÔ0ó®îÅñÞý>Rõ‡¸QÛìÎ÷8Á¡›…€¥á–zŽÍúþ³ñÞÀ¢Eþ¶m%8i‹Ní~ÀïDÆÝAQÊq.ÔS»ÿÓïÄ“œ‡íC2øøñîòsÈ Üû`ž¼ß v—ÇÎì.ïw Ý}~'˜/?ŸxÀ¤ÏhyÄï„Xùø¨À%œÑ2ä‚߉ÿÄ{íyžÎgÃá5x¿ߥ5Ôy Ì—÷;Á¼úû 3íýNÀkðx„ëïì\Ûû@Õï„æ2iWð/ ‘#Þ(…‡£aËYôšÄŠeÉæÄÊTÇ¡­ÉDsª=ÑМXÞ$oÅm²7Û–jM¤¥ŸÌ‹)¾&´Á£&)“¦5]T³Òq^2ÑÐÔÒ˜”ˆò^Ò°tYûÈ.WópK¢.•lYŽEWŸ˜¨i^Ù¾ s£SXø®6”¬Q›6Æo¬ŒIýV¾¡­}YM»úÕ¶ ¸mÎ<­–’øþ*‡4òP齯-œ81î‹zfw•n2±à•¶Íoܼ«vö·ÆÇ¸®Îó~¡ï¹WÄübÅ&tï{¯÷‹›xW÷~qm È¥Š‹Ÿ¥oô½ÏöS·3ì°ùké\-ï£êv¦>Ï‘ríåï´˜oŒÇY ÝÜfü,ø{:«,{ÈóàÐ ßbïØ%·ðî{Çð^zØ•~Â%õ\b·„Ø{îôü}<,|Åö&ZÖ{sIØ›Üí¼®Åæà?`íÜF{û`ðŸÁly=n´Þÿ¼þ}þ'¬Û?ü=Ð?)÷Áà?#ôϾ¼Ø×?ëIÂö'ôOû¤ÿ¡Ü|ÿ”ááþÑ3ï?cŸ·›ÇzaÀ9€÷’±Ï§Cðkrîóé`÷A-çc>ì>ìÊ©[õÞœ{våDœ¬7§½AtåD·»7§½+uåÔEaoN{§ëÊIº'ýt„œ¨x?éõ#äÄù“>DBÎíÛsZžbWNvAoNËyíʉ/ÿÞœ–‹Ü•‡ ½9-G¼+'.žôÆrâ  7§ÕWèÊ)ÿïzã9ÑEëÍi’UsZ¿àÔº— ÞyOÆãFwÞùàãzÞùÜê9xçspzªçàÏg¥žÃúZ±9¸‹×s8*“îg=ï|ãM«;‡õubs OPÏÁ;Ÿ ”zÞùh©ÔsðÎçxÄû†ÍþO=‡ó½úCŸFg¾;ï¼ÏvI·ÏŽFatÎôÙÁUD•”´i´9ËÒ†º,Emù²Ð~;@^Bre©Ùá·•|ùˆ@Ý1‚}Ô RkkÐ$‰åÜ9¦3 °hcùßÐ5%æ°ÕÈM)¦ÎFò\Òš¨'M¦*Ô3¦¾¦›ùÆÿÆ”X™­_‘»¿¡gôµ´œ¦$i?ˆ.f~p]ÐáÑ¢ŸÐž5ý.Œ{Ü,—U€|.:Ú6ÍBêu3ŽôºYî%Ô‹þªG½î¯¼be ÐN¬¬ÚªR Ÿ bÅ ]±JQGÕsÍÖÀÓãÄ_ÓC]Kû4QŒHNØç-š5õi4öÕ§AšMõifS¨wØêÓ ùlÐÌ0Òx:¬YVß0®ðgˆ9É| y˜õƺ`°žÜo°ô(ÕÓ!ô‡ ÙÔx=ä+ñL ‘&¿zÔjδZ¥Î‚ï ´þÕƒ¡ÏtõÔzðxÕCuÛÖä&UuĽTÝ0yqÐÖ&—š€áÒ Ô W;¼ËÍV­ZœtLÜpù=Ñ´ —w¤Þ×7â | »æ›6ÂHM”víHm9ñîF™[…QYƒ]Å»K¶p†Ó±FImI³4Jnw4Kû銣îî'§"šëýÌoÉ~Ü_Yºåác´.AÚ“£_W?ú˃]ÆD6S¶ <ÖázƒY£Ö•aŒ” ÔÝ1Úåšž1Ú#ªsŒÜ hŒÕB‘ÒßXm.ñLÇ’ ¯ c….Ô›¶ãâ>´×?ô½Ö;ÕÙnþWWÚ>w/¦`œ6‹fo3ã~Wy@Ù£3}9™é„Ç5Ó¨uθáÐvæx:;‡5ÃtIgTV_Û¬Ý30ƒ ˜µߊ{?S½Uõ3צš%9Íý,áHU=KWåœÅ¦_̺=bmÜ…#Öþe¿¡¡.!§š¸#µY´çަÒäµKUÝh×Öĵk4ír‘¢î´Ëû‡öèlqÈÕÙÚ^Ú{³…B„f …Hm6[B^Å¢ š\éÍ•~©º67õ‚¸²®eø“®eøsþ.NFpð‘åÐ41Áù ||p¹ÈÜŽÜÜŽdŽA¨•-áÕɽï>Ä;Oáƒà>Ä;9ÀòY÷ Ýçvo?©‹ •wÊð5â¸(s;òW}nGð\ý“}Ol-øan¬Û‘‘æ^Ä@óîN|_àM:W#Ñæe„Z6¸±nGä,ÅTçŒd¾S¼“¸›5'#t¿æd¤æv„Rs;‚“‘šÛ6kÍíˆ8ž™Ûó‚[JJÙ œÇ€²båAŸI®Á ‡ü¼€O9žy!ŸJýgÔŠÍ“üÎ3äâ£f?÷ó;&)þº¨¦¶6ÙÖV݈B‘䈻 Ô/ÃQÂû‹ˆó:0û±§ŠG­vü¶ssÒAÅÓÃ>8üš$‡™ÿ#_û‡íIà‹çï&ÖÛHñJœ|h°…O‘;ÚŸPZ-~ŽŒ3¢ìº?èö•`á¤R–4'…g$eâäOð2=*8çq±Mçj¤ø”Ò1GŒò¿ñ¨d”ÿ“Ø¥I­>­ŽÜ¥I%é(ý—Ohþ7—&¿©õ¡5šY)ŽÀɬ(ÿíêÿEù/ØàÓdÍ}FMTê52j"8¸tl1ÎI–”Žŵvÿ'é~` E&mfŽ¢Î JÇŽ.Žò>õ¨‚š|ÆÌÍv;!GFysÕñ)Î'î}™:YAƒe«eõïµSŠ…ÿ‘éQÞËUq~CJÏ{Tüâ¿92±6DŠ·hUé÷åŠ?!€O XžQÎ|\\ ¸+ •wjé8–hqŸŠNçS+å‹R·ûL0…RøPQ²µ56®cß Ì2ÊÚ{<£8ÍN?rÇÐbá ÿaådî Z½ËøÔ¨j¥Î>bhã(í¿Ÿ»òËòÒ£;ä¿_jÅgý~U–ý~ÿþÍ£¨åÒßC¢ÊóŸ€f«E‹•W=ŽfK§?¥/ ªÇrJòýãCå¬ÇOÉwþh o):üõsTËÔ_ŠiEæ/廩ùKé‡^ø@ñŽ3)Bu©¿”'4È«þRB,ód©¿×"ç/åÇòþRÃR*®Uê/…9)?è÷—2”ÓüðØ£‹ó—"¶Šó—ò¸ZXÍ_Êpø^£â¹6.N̪s.N¾+`]ó—2ŠÀh™ûóYœîÌã»Ö•âý¥Œ†CÕ&vfÖ™Ô_Ê÷tsªþRÚ Úà¬Y:)jŒõ—òý¾x)pÇ>Ôq—¿SÈ“(Æâý¥ ™e’è5Î_Šê0þR¾_†÷—2 6îÇKvþRL?ž„h®ï/e ijì ÆL{ÀLÈ–€÷—2îÖ Ç·…°L!?XÞ[Ê :pÄëã¥é±®5ªòã€]Š9VÛ\ç7ÄUaÿ£*?ؾ-Á¨J Ù.íB=ODïp&UÌÏ.‡ÿûë£Ê¨Š%Úb~Ñ>µO×|ûâ õñ@ɱW³(³o›€Ï-"û‰aÐ9+AÆ£.ÈzZ÷=¶o0†ƒy K _RÛyRõK–<¨èNn+܆èÔ4öÇY›5ÑßöÄïÈÿ˜„4ef•”ÞvåEKÄ‚“0ÔªIŸEÀMÂF\ÿKÙ…äú{Þ5,ìÁˆx§ÐþØíBû¢Ú"ßß¼³ 'N[Â?ï÷f¬ç.Ó2(Ðx@öþ¤‚Ù)Hõ¥ ôèÄKÌ<‘n5*ê#ÈÀ¯}@d_ÒEFLv´9µ³9Öfsl´d,„H½¹ö1±Ù5i±ÙÑ&6kë²sÜ7€¡ô¬O#0T°ª›H{NOÏZºn̨\-Q\fTÎû“`w¼;†–Î[9§ü¡é¯_n³9‡Ìê Ã0»^К]àðõ;l@ðíº[˜­i_» 98&©˜¥]ðÄ*ð»@¦vØ1btf ° ”§¯]pˆÛO®‚Çv³ûØ.àȸoh†«f‚Àiº‘ îÑ.ø1NCH4ä©‘Á=¿ß72cÛ¶î‚U3®\}bÌ·ä„vóýœçÅù™?/èË<{aLæÙ úÖþŒólÅͬ âhOŠ aÜÆ‹ !žÙ›ÓœÈ0 èÁ%ŸRéÕJvMÐ’þ^;Xð¤àF0î'=%Ýy¡‚î‡)x”£Á“zæ'Nˆâ‡ØL –V›Ý°«Íß{WJ1Ð7r"yšÝ ¤ï&v˜Ó›ÖBcËïúü~LZ¼¥Sò¢G}½n¨zÔ«vÿïô¨ôm7=ʼí;…FèQOÙ ="Û›G™(ö¹8ú+»uåZ~䨉‰ºd[mkCK;n0ä`à¹KÁ‚¹—FtÌé»jXÓÒˆuÀ…•qvù¸Ã¾z¾Mq{|.N+øèðïÊ\ º|\Òœ¦ZW¾Kîé'êÓáÞ;2Nèòá£m?ºò­˜?¿H9çm¨‘³,ô(öåÜŒçÈÕŒÙÚ$Ÿ‘67ú£3Ź;æ…“ÎÍɺò¸`ve¢=•XÒѶ21c* ­£¹­£E{ym¸®SôLçÓž:VÌu%ÀÄo;º¬ªum—›cÐØX[®+÷5íÉÞ!q99¡m'õ¹‡sV‡ÄåæÈ4.Ö©ëʽ`a ð“’ÖÌ1¼R³ëÊ+NНµ­¹£1ö.`órxÃ;¦4ïºò.˜çLcÎqË’›…Ê0ú].—åã"–µËÏn›^9˶Q>§Õ¦ÅÚzÝ»~of :sS@h["ÒÔëpééé¦Öd[ÜNŸ›ƒ!G8éâvÏŸôìÒ¡ÝÒp䨨gËËqì¡#øžÝ– à¦G¹Ínu[§§iíèB²§tºî™ý ¿tîJ˜ì)Qºr¯uàbu[Ñ|Á¹šýªÃü£ûuÆû•“ã¡Ô!íÓö][ûÊ–dâàŽÞüf^-=JGÌ~Ú³ÐXŸ"zÔ‡Êz®Š)Q÷­ŸˆJöÕÐ=®†Êz5J²W3ÕÛA¼Û™–íÈ_lçΰ÷ÛyGèS+ÎÌjòï(OK¢*KèFûêèÊà'äNâwà£åvã§Fùæ1cóý|©3Ãíoþí¬D%½y= ´Cí£uÏëë“”föÍל²è–uÌ‹ò®é«óÑýêfª} 41ÿfW,¼-‰r/Ý´?¿³SŠÝÿ¾Sгþ}§wg§Üc{âÓ»0Ž.³yß³»Ïœž;qC…k˜ƒ_ܱ[¶„ÙÜöÉ6‹ÙyÓÕ|_­êÍ5äk$ßT¾ãÇóªÎË{÷AGOû äsýÜr/›µÈzÖ,\b¨ÍWF§dðI²þQ|’œ}6INÿ_X$™ùï{CôúÛñMCa‘mC`‘mi,’íò8Ï{õ+Fò$v’'ïçŽU¥ÁòsÓ×¢Qÿ.£êhðܽô wNï5’Û©÷RÅMÖÓæ -ÕŸ{ÿvÜ™'[Œ{õT‹q‡›üýx/hðæ™ùA~Å{œdL½ÇI¤ÖY "¬§îC]ö~•¬DCæ+Ù{I†þ|w¨ãKÁK²÷ú¥©ß>åˆG†wÞ‹'?àŽ— àïΘ±ïø±¯›|Ÿ ù¾l9´ï±Oµ&ÞÛ²r$ÞCï¼-Þåó‘x©ÞyOêArvFæ ¹Ôbâg¤ÞþÈí=’û›–CÛ´àgB9 a& ~&t%.̲|â`ü\ªO…Æo›åï"õHM¾7âQ¤~Éí%5ˆåóZð}Ò»¢Ÿ½+úÞ¨¦¢÷úÅ;?¯¼ËûQôóªýQô~§´?оÚEï¡ZïÍä.…-‡wÞ;)ïüðÎï'ÞÝÞù«7¥Ðã’ï±f·tg&GÙ{7T޲ï1'1ÞùóÎû&ä÷n¥~—ýv(‡T;©|kf&*¾ßš‰ŠŸ3õ²â= *_ÅïfÞy/w¼»ÖjÕE½â}%ªÖŠŸ3rø9C\á³–Oœƒ¿ÿ”¯Á{R¾?Ä1hðóG﯑˜÷(K>¿yçgwy?¼_UÞ}6¼óó§w¾š¡F¿5¾nÍG£÷à¥Ü~îÉíëæï7ïòùk¼=ó®)ô¾)Ì}S˜û¦Ðã&ßcíŒ&ïåK܉¦s2sÙäûM¾÷Ç ™)&z‚ßD  Ø28Œ¸ÿïß7Ðï†R“,îeDˆyïŒÄ¼wFbÞ;#1÷ÎHÌ{g$æ½3óÞ‰yïŒÄ¼wFbÞ;#±©&Ý‚O•é–~»Ë슓n±½³|<Âu’;›c®Ù ¸ÿ0× x/Hr®]y×7/¯il¨SþŒe“åÆQ Üœ_ß”[<§œKèIRinœì@òÿô¦ÜbåZa§@IƒìÉ™Ñÿ¾µßm–N ~,4û{rŠ2$ÆÐØ;WY>üïÍ"Ÿ\¤tå3 è©'9c+î’Öáq'•󶚺ºÖhÕ=·ŸMp€äñ¤«Ñœ‰º”}e™Hß:ê.Ë7.¸ˆò¦Ó•¿‡‹ˆx 3)q‘}9«4»àý.âÇ·äîàWáG ~•|Rwåëáâ>  |ü<œ³Îdo±ã$pÓ•û! ãà¯I”¥;ïnþZšþ1ü51¨öÌÓü5ˆÚÌ£ô{{zö UÏ|Ij¥+w ¿+̈¼¸tå„hƳ~§3•÷Íï*Ö:žD$ÓWßå)-Ð׉”¸AÒÆÝ{ÒÏ…¶›áº9Ðár«[ÑHrKX¨7·¬2-™%éóƒé•$…º{µvE‚Ñ4»| «©ä{ÿ¦|ùÓÁV‘¯Ä…3ù¹ÙSƒMX/à›«<ALh&5ÈiMwß70±±:`°Ó(òß ä›á§J¸éÉ:2B§Ëï7vð/>‰q|nØèä–K ½˜æÙ riüÛÜ8¢ÿº&ÿ ¶jw”Û´DÑ©C>’þ¥Ž™êÀ/\ÏŸ¸—è›ËÚ:ð'ýçîÝñÐM¯Å?æ:r6ôË“šú:ø™Í3¬~|³k÷?ð5vŸ§ŽGäy&;¬Å¡ú©¶ƒâ«Å‰MߨO×Ñ‹mYÙnÌ?u§õò)YÏ£×ò-.ò­Ý5xbÖlî¬ÉZ»6+ë,ââÇ׿øÄ?§£ø.â7ÿñ/¿™ø-Ä¿Bü^â·¿ø×ÕSÅßKüvâßRýŠßAüNbE¾ïâ»…ï—¬ËÊ.¼$+뵓ʲ֭%bù­M¹÷ñ[ã³wð[›îÙ]W³«~êÏ9o(©Éz5ó´“wýº?ÍÿbvzÏÔø­›vhÓ —yÿçÿ6ü{4Ç×oÇ »w®rî:oM«÷×dx|ñšíæ…¹ÆEÌÏ55 b¢%½¦Œ'Wõq k<ºÝµª7ðûº8†æUU>Zçltæ³ýת¾çVf>º#*nÇÍgí€=En™£kí›ýþëØ£+îéïó_Ïéöo‘œ-ì··:ë"Þ6+¶ØYÑ“Ùìÿƒ‘Ù7öû*Öêp¬›‘^î¿°EËà\,<ÿÔÜv°õgÖpñIëØ–»˜_D/Rß§»j²¦W-ÞªïÐ=Ã¥¨!ó‡znVɃ{0º+ì²£Ô‡«§nªWs»h §âyRVVîØtÿ%÷-p¿åw®æ£!Ãߌ‡Ûa/°ØOj[F^‡=÷ämÞœwĤšì¨›¹ô{UïÙ% ÂûùžÁÌÜTµOþÝ ×=í®® ² ÉÑšy3ô2½×ò[Ý«33íðùûQXãpúèí»÷@¡ê]=YpU…¡U¯ïãÕߎo?ýmnWfqÞ·ñ›÷y»á‡·€ò>/H?æÀE½¢öÃ… ?ì8¡“»ÚÞUH݉zÕÎÕ¿ÞóÖï¿K3`z0çcQÖij¢ì®g­GÜÿ5Þ-quÈ#Ÿ©ã6_Ç+UG1Ô1¯ëûoØPÇéQn׳ֹ:ìN‹îZõ5ß«à/áæÃc¥ÏÍŠIºycú>¡+¯ÏyÞÍó·•p NgJ—åàøÌïæfx°ùÛ<ÿÌ…ËŸ2)Ëq¿G—<«§§*6¹«3»(ÓÇû{FÀHœjÏ-¼™jùðnëòéÞpyto¾jŸtÝL{¡«mÖ§xñÂÏ„>ÕÞ.ÚrÓòwÕ¶hóMkݦ]Õµs¢ÒûoQåÏwÜw1^Þ·¶í÷±ÑݬÄ6;A±¾þçf]ŸéO‚üwâä¿à:÷¿®ó¿™¢rÜ88)Á²çÂ[òœf¸ÈžÓ /,çÞ¥’á{.\dÏ †‹ìyp‘=’Öæ¼ÃTFž:n·ðÁ<”ž‹IŽoY]Ìâ™)GY9bÏŸÏ+|Ð8ðƒcÏÔ9=ÁØóDÉá=»ËõŒ8ÊiI”É‘~p¸°‰çÂjªSŽ21ÏYTM)_™ÜÞï;¹}?xç½óÎs¸%uxŽ&±œ/›r—%Ê]ðó$þWÊVM…0O?Oâ{U9Äžß©EßW1ŠŠ•_Å)ŸX^zŠa¶Š~¶ÄëJùÄÔäù¾ä¸#ã·¸x}Èá9Ùäøºåå§ä}Ò+GÉÏœr”üÐî)ù¹O«ä9ÁäËy¢%ß'í§’çk?•üÜ“Ï{8&_Þ›r˜û²× /«ìw9òPö;@sSö~”ÅÅ*.lÙsÁÉç¹òâ^•·ì{@?beT<W9*~>”£âw¶¨%ß{røÝLoåBsSñ\y¸Î~÷Àu¾ÕêϪâùßÔ‘ótS^²ÓÚ4Ó†g§ëεYÖçÏ·ÄÉ(ükù/­çÛŒz{ªç™‘LÆ]~ñ# ÏR ¼zþ\ÉSžÔ'‹];îHõu’åÇXYYZ¨çïÈ}´Rœn¹q† ÷[×ÎjϹŸ¿Òrâ5”ù}Ó}9Qº|~Å‘5|e1Âê5ØV˜Wsj’G~Þ°øŸRì°znÇâ ´ÊZ |0'J±czæ¼CÍÀåÅfyŪçÝ=éó-/>Eg“W*Uß™sÃÔwR­U’zÿ]°zðA ?U VÌ}ZËÑ÷òÝÅû6ûCš{ö—££†]Îî™)PÕsòzu†ð¥J^)Pí©Ùª,¨÷Vo!} O°{tý Þ)½ãW¥6§ûãÔ.ÜÖSƒlvµ¯·¼xn"¯T§^ñ:” ¸÷Ò'0œøWÞWW“~æ.S§+ã-K¥¼â3ާû‘žëÌ–J4‘ŽÏAá×ss·í–æ|¶s‡.÷ß¶Ó[qΣ:›<ÅIñ}¦bOäOž„œÅIÜé·Á¥I9îVÿnõsÊ:Cœ¤­]{v-ÞÓñ/<_Kù0£{pUÞ~wÃõGñ›QôU8Ÿðñ¹eÑ—×p1ɸG².Ôyswñ ‡ø­q›¢¯ÞÃS)/.=5»Ò½µ\­î>—'Çù½˜÷h^¿žÛ|yÙ×»AÍsÿÐs3œ2§çf¸ ½<äzTÛ®L¿rN@›mgšã¶§O¥³”Ër–³\r½ºë£3¶sÄ«ÏPiïãnʲêEð†4ŸßÙņý4Óí†Ußq|šžòõÝò%›óÍIï8šÈŽ\œ.¡··Ù<Ô{"þ¥™ñ½Ü å\"}¹|·µb÷fCWôÕ˜¯SL`ûf£âpvo ½*N{­ãa…™g¥Æs÷é³–«“ÇbzÕ‘ë–÷UAZ³} ì«z6î&q[ÜMɶ›ª¹˜Å~uº‡êïo 3¶õ¸_`©Gè¶}ïhç®Å.쪋1FÎͺ;Ýk›§!ä .ñ]ž|'åïÃÚê.?Vwqsž”û¨¹ng_-êÝqyžÝ{MénãZvÏ üÛÝšÙûvÂÒ Cú«ÂP^+º‡ †¸û<Ãa³Ú•–y®/ûeU†-Û6ãÑUô`…Õ^sл¬¿ßñðÎêüÎïÜ÷nV–jò·^Ëuµ-æÙš“m8ÀôsQWt™áŸ3†ÖdäøWÂëUþ•1îV¹þÕ¿Ùxu÷hn\^_ž•çÛààÛëEr‹õwpÚçµÕȱÆrpkõ÷zrø›8ÎÔ=^ÖW,Ÿîª±çlÀwò|ÝNã ±˜r«ŸJwÓªæ£ç'ˆ¿‘ê?Š¿!ýG›OwÓØó7Ä‘ˆ#öü ÝFSGÕ”ìlïtóL¼®œr'AÓP|*›C·Í$è-&Aß0ÕÔ¬ˆOeóé®™x.µz…f%ñüÅ ž § RóWðó'^AÁÏê+„š ¾Ç¼Ë¹CÏÛÑM²¸EÏ…Ð ¥<+ÍPqºåÓ-²è¹"äó|Ý‹G'ž•}§›a1p3Š_³wBש†#ï<‡GýN5‰y®1¿Wˆy1_1Ï7Ó°øce¿KÐ[ôü(õ8åD©ÇÒm´¹uù*ûZ5ëå (~”Í¡+YªÏH}^'Q·>q¢²w¾B]•ÀÍ“n£}§^%ð+žÇ¨™®xžž¸7¿K¤™VYg< Ëwð(ä€Éó(tçKo…¿ÉÿÜ eHñöïÉ8âœÄò&n¥[ŽŠžþËñ[ÆWΠϱbž»k¹¼´ì"¢=÷Sʃ Ö9œº7ž˜¹õ¹±¯so´ù~›ÿØé’—ŸïQ•±kÒ=ùþ£'Gñ>w¯ºXÚ ?‰Q|?F•|ÎŽ[¨˜.ö£¸¡Êò‘Ïߢ甯méò☃¼¹û¼gÎÖ<µ¡hrNÍcܑřù¸9eÐÓçt¼ƒÝ§ÿû½~NÇázhøœþà¼׸«Q!ƒøPSrRÎØòãQ¼üÚ5§K0ÍW\NÌ;¡…%ÏÙÁé0³”ÉË©ŸûRp%´7oÿÞˆ¦Úe‡%â N«fª<Í@i§$<ºr„/B­«KOƒ©C|(߃Àðs˃)4Óijòy̨çZavä]>y½ˆŠÈ'ôžîñG¦?otñã<Ü_ãEœ2_ÃnÞŸ?¼c“Kk:Ë•é©Uu ±÷/G×…¼®=ü‚ê´ûý‚—mf]ܵ¼Vo%ïP>¯8âÆ ’8qyÍù¨!Bíxò)Òn KÜþ=Ç8·çjón±k"ìf¯é…‡ ¸sz¸HIX÷ÅÕègI«ÅÞâ¸}vÞP¶í—íµ¹ÌÛ S¿c¿ìëðõV/ÉM¼›@¼1Äím³¦m¯oõæõòÀxyï­F÷!ß—=:#ºM½|à6¥»ÎøóÒÑ]¦ª-¢›ÕU¼Éo`ù ‹ÛŽ¿aÕ½Lì©Uý9‡œýÈ9Sàý'¹óÛVMoo£Y¼iîþ4ýübÖý¥ÝsÜã­â+ÝÏLßYGLZí<©;*œÈMtîbwÓnåM™7M¼IxÓ°ðëܰ…y;nØõvk14tMü6<©[§<’•Æ#Y d,<ôZžû® äx$V旅ï›î}ÖÃ].ÿª¯Æ\ƒ=y³/¹ÄgЭØÞ‰{ò¥)šÙùUQÎÛ©ózËõÀÎÔ]r×ê¬}»ÏÍä—f[èM²¹Vt7BotO¶sГ/»+Ÿ›µ/{oX:gíküïk³”oBÃdXØùý8ÝÁs‰×#âæëü—˜=êµøzîÉêKGgÍÄÕY{­'¬8-ŠôPRÿ%Ûþ­ŽÑx]øÒ\ŽŒó4¢Ûðk(]§üêŸtÉ¢¯aëÏôáÁûøž®žzx6{òž£þ§½¿:kqØmÒ3÷îoör~¾ãŸ¤4,žëêìš8s¦šæSï1n¯÷»[Þ ,6|û]yØÆä]ôì»~ˆ«òò§¸½sO”•©/Z n›÷ï})¶ ôE˜gžï‹jjÿc_ÒÞfØÂñxÞéy$g°Coøï=LÐɲ\¥‡vh=37õâÁ:ϧæ92Ügsˆ{ô ŸHß×ôâ»<Ç^LWç¹âíθAó7Èr„§hþÇÑ­¯FÕÂïâª÷ Ïszeš'xvó[œÙËg&ÿ+^˜÷_jÈuã´ÓÄ-«õè΀=e4¶¢éýÝúÅÑÉ84¹îLâ{çfåÓ½?ñ|òå>1¯·ÿæ+™XÁ×Al…Õ¡û!𜠾&ùÀ*x=òybžï¢Ù*ú™'àq#¸8~†àâxíqR¯äε{¤mdsèþ_ Ú=©¶QÐ3”¯[9JÁbiÉ{Ák”çi.K~Ž­Ÿ ›/S~—P‡×î!‡ß+¼ËõzÊžk%¾KÊÑ‘ÿ®²çQõú¦ Ÿ¯I^¿Ä³Ig½âùjºõWÂþ«øý§:R"Í¥ô†l>]¬S½!òåÚ[•°+~/ê¶_ ž=*Á³Gå® %äç-!ïÃD·þ†ÐãT‡H¹|?tϯz¢ÈµÉ¼^•î÷ a7K‡(Ë‘ëø4zþ1¿Kˆyýbùþkô;˜X^_SÐÊI5†4‹M~Î4»M~h.›üÎ¥ÉkñˆÃÔo¸q˜0/ÙébƒÌ8“8)ÿ@yá ŽÄ*ãà“7MtkÉùÜm¥)înx-r‹)ûª÷\’]·¦.ë£÷¼/¾$7ë|Þ~sðí½¼ýòšºìÉþíRð›}›Œ½$7{dÀsó­e[£ýŠCJd‘b.¨nMn0ñNŽÏ¼-U¬\öZ?¥×Þú)¾ý¼]T,böæ´³Ò•£™½9-G¬+'v5{s:m¡Ý9±XÙ›ÓùÑÈsZ{©ðOêÖQyç-¨Âk©çàÏw¦žƒw>\œzÞùp{ê9xçsÀ!ªçàÏV¯çàÏÇ©žƒw>|ªzÞùðµê9xçsÀ«çàÏ׬žƒw>¶zÞùpãê9xçsÀ»«çàϯžƒw>üÀzÞùÜJê9xçspã¨çàÏÁ¥žƒw>7—zÞùè¶ÔsðÎç@û¥žƒw>º2õ¼ó9Я©çàÏ6N=ï|twê9xçs ëSÏÁ;Ÿ ¡zÞùèÕsðÎç@©žƒw>zKõ¼ó9à½×sðÎç@;ªžƒw>Uõ¼ó9оªçà϶V=ï|ô»ê9xçs VÏÁ;ŸݱzÞùh˜ÕsðÎç@­žƒw>ºõ¼ó9ШçàÏ>^=ï||KÔsðÎçÀ#E=ï|üXÔsðÎçÀûE=ï|¼eÔsðÎçÀ»F=ï|üqÔsðÎçÀ‹G=ï|.+õ¼ó9@íõÍ»\sê9xçsÀE®çàϵ¶žÃÚª¶9ðqRÏÁ;Ÿ(õ¼ó9¬çàÏ·•zÞùè×sðÎçÀŸK=ï|ì£Ôs8/;&Þbê9xçsàY¦žƒw>>hê9xçspz«çàÏ›zÞùh8×sðÎç@“°žƒw>öBê9¬§D›ÿ<õ¼ó9ðåSÏÁ;ŸçzÞùP<ê9xçs M]ÏÁ;ŸãI ×xm¬çàϯÇzÞùø…¬çàÏÉzÞùPÁë9xçsp­çàÏ—±zÞùx«çàÏ÷±zÞùx"«çàÏW²zÞùx(«çàÏ·²zÞùx.«çàχÑzÞùø%­çàÏÓzÞùx<­çàÏwÔzÞùøQ­çàÏÇÕzÞùÆ’twÞù‘ë9xçsw¿|ßò›TF•sÛeÔMŒz7W¡é².zº‚TŽá[ £]Ru9i6”.^ bt‰Ó€ê&WÖø~XónÐ¥T®cµÄ.hä So#׿˜­ÝˆÃ¨3ì\øcˆM2º/7Mèaz¿ Ú˜~6q%Žep\&ºc® ¥ý.¾Õ~\[cjnF]&¦/Í\üb._ýA±15ö—š“®Ñý¹òÅô£?.scÜÝÀ(¦w r™Ð—Ô’€np™M`¤ $–П Ø„¾ äj,â[u'ÌÉ@Ø ýi¡%ô¥Dœ0;-pÀz1_: }Ä%!Aex0 ¡8êÂ¥5¡­lÔ„9i Áàh¥&¦¾•«f~ E˜“¡ ·}J ÌÉ0`˜á¸Ý*€V‡sÕ/0§Ãq8[`.FÈa›ú0cì8ûÁ%¬@FpyÄå×HÕ£™É•¨ÀÜŽÄV¹)æ™ú1Ší[`NFqÕ*0·£`1ÙJ£p„[¤û‰á¥ÙØ‹VÆÜ~ä/ÂXÙüEú2šüEæd4N~‹ôgü•éÏþsøVöG¥¦È®CŸŠÌë®:E.Ëc‚",·±ªC‚ÇÊM¬ênC §Šic.JÌå8f¡ÄŒ£®{kjA%ĉÀýo‰Y<€zJì¯Ø~%öÖ ¤sp ÞiD]¥DÿÇSo‰þ§%ú?žÙ(Ñÿƒè!¦ŠB™Gd3×ePÝÁRÁÓê`r–é÷!,2{á–o™úR¦þC˜2ýž E(í… ô Ìÿ \óËì† Ìk™}p(})3#‡Â”)ÓÛ‰ìá2ûa"ý,³&¢Ê[¦–‰Ê§}5‰ýW¡“Ø_æp2Æ«*ÌÁdf¨"ÃêO…r{¹Bÿ“º“zs5Wø?…~Tèÿæ¢BÎ)ÔYaîÝT`ÎÕ¹Bÿ§Ò× õNÛLs8ûó 쥩8üj½M…%™iÌ9ÎЦ1O ˜dŸ†ÒQs1‹ï"/G£QUn`þ§³/˜ƒébéz9ãX¾Õ›\ŒÁ 3¸ô703@2 ôe&³„…ú™Ê¯y˜©üêÏLå׌Íbï40GÐ Œ !,¡Ø/ä[{é˜bôãÈ£ùV-G‚™ÇvêhdÛ¹x7R÷lf¥‘™ŸÍþodÌa虇9ªKû`×™Fæpû¨‘¹˜«z´çâ³£‰ý<—}ÛÄ^˜Ç»&æ`¶šèÿ<êËÅÞh¢ÿGqÙl¢ÿGÃTjb/Í5 WmÇp•h¢ïLjñ¦ù?æÕ±cècÞàp¢¦;ÚÉ™‚åa?qQp¯6»³• pÐ>4î˜í[¼˜ýAÚÞüéé(wÑåDÓE¹|/MG¹ïci>«{öÖv<œM–‹Â¸8'>ÈÓÓjVío¾îHšø8£;ÇêÞ¡My¬î9BÇÊ~™Ó±â·hC-Ô;m¨…l<ìÒ/dºéÐB65.ÒíJ¨l‘nÍÚ‹ÄcRŽEðÒb¦c1w™ááÅLIÌô.&wÌ&8Ža†¾}ˆ,¦öãà ,—7lÕt<[!f2—€ b&s ž¦ñ†½×Ý1ý_Bob¶þ¶BŒ&þÙO9’oÍÖSØÐ À§0E6íSäqše¤ËHð© ‚sõTò”@žOBÔ|? ë³x;§Äæ=‡y,1WçÈO…úr³Sy<¤S¢Oq•˜ïg°CKÌÓ3„5Ï@ ®ÂxóZbžW²ËÌÃJîÆ À• ”2ó¼JQó°Š:ËÌó*8seæà\zò;—^–©÷\¶y™y>¤ËUå<.e® 罟oõä<ñ‘5k@)eæy û¬Lýkð]¦ÿk…àTÿZW¼V¼`õý|.)æð|v%Èï‚ |«† È[a.×±·*ôcwê }X‡N{…ú×3gæp=—ˆ ’gâÄw!»B½ò„·xsu1¤Ý°Iü_Õ· äØ@Ï7¡õ×@Ÿ71¿ »g ñi‡>KïÕßg±¯@r—pAh`¾.M60_›™·æ{355P÷f¸¨ Ô½…¾42ß[˜sÜæ°‘š/ÕµHý¼ ˜×H?/cŽ™§Ë˜KÜeà–FfîÙBlš…g³géë³™ýFöö³åBûåÙp™¯ËAd »ËÅ=Öœ]ÎE£‘9¹š˜³çâã ‰}ù€¾³{C,N]vo`N苾3]lŠw¥ó —D§kÒÆè˜ ŸI¿å‘Þ0ÀäÙ #Ñ…ýg}M\~íï•:&)z½fM[íUê :ü*6⧯kLÈïUR3Ñöx5÷8®*¯sµn*Ú¯ÖUD½yµ˜îšÍ×hš53¯GÜ{^£ùÑ–½{hÄÖº”Äõâîº1Ý-[-fk½–07¯åîËÕâµì˜>¼Žéˆ¹]q,á.þz¦>f»¾žMÊ]üFP8wñA'1(ã º~hK½{] úzwÿ„iy#»(Y¼‘ž&ÔýFîã u¿‰m˜Ð÷7Ñ_®o¢n®»¸Ž$ô{(š;÷.úÇ•b›#¡¯oæž™ëÍ &®of.¸w¿4€~zßÚ&?Í£šùi¶ozßÂ:,Pï[@YúûÐ%÷í›ôN(ë&êA4î&T^¹kß¡À•æ&d>¿]÷sÍÔÛAê~;µrå¸Ywp¡¾›AEܵof¹g¿ƒmDzx‡îÓÚïd>Šì™w2wÜ·ßÉöçÚñNî{Eæî]°êŠÌ×-ÔãÐv‘y¿…{i‘ùþ]G4û?{“ëÆÏ€6¹jü,},Ò㟅ÑZÝý,¨¯HÞM¹n¼^«öݺF¨ï–ʉ꾕ãŽýsºO«ÞŸƒ—Áûçàc”¨óçA_Ü«žÞ²¾|\)~”TfžosRõ­k׊۸¦”™¡Û¤f¢~¾gR|§~ò)÷/*ŸêûEf‘ëÄ/Êéúú‹\ÊÌÑ/±Êôï—øÏuâ½Ì=wé÷êî¬úß ½Â@½ª°?ßÇžã>ý>PX…>¼y­Pÿû©¯Fx?(Ÿ«Å˜o®`ö+ôáÔ˽úvf{õíÌ÷êÛ™û ó}ûE1ʺýӎד¡,p—F‹²@6ºT[Lbn `¾Ì/›ìåì² –ÉиÃ")Þ‚l,Ê" –çÁe;isç¨'ÃNÜ9SL6È”¹¦(ÄôOW:×'Mùo£†áÏïƒê­&ìƒâ‡k¢>$쥾}ˆMBù0χQ0çùaU,\ûaÝw5YÖ]UoîÔæ¾ƒ7ôõå¼Cº!ÚàÑ­XSóîl0z>Âý¡èî©Ð/SHå£ÌE Jù(wJÐßGéÌr‡™ÜɼÅÔx'ˆ´v'}à®ú+ Œ˜Mù+¼™ƒ_¡~:ÓWÛûcl*0Ûǹ€L>.Žêü¸:Ú"É}+azÿ’M•Ð÷¿¤î„öyVU¿¿B¿júŠî±ÊùW r˜8%d¢­õWäH¸yü^?@,%FØ_sï`àþZEõþ5÷Øóô7 Èß00mîؘ÷:_»úV¯A"÷RŒš¯‚È ôñ«Ì'÷Ô¯Ù¹§~M÷Pmįq¿a| Ï=õoŘÑÜü-÷î©˦åŽúu¶`‘º¾ÎÅץˤ¾}ƒÜE¶ÿ7èq‘ü f Dñ 6ˆâï@K0fþNŒ™¿gC–ØO_KÌé7Å”Q_¿I_Kôî› 4Æ7A'%júæ–;é?0×%öÂ?ˆI£9ù˜[ÜKÿ;÷Ò$g‰¹ýGùÜWîbß•èÃ?±ÕËì©â=ˆä[bʨïß9•ARßâNòø6äñmú 3æÛì˜1ß²:»¦H™ºïÓT}½Æ ô¾+lh|aVèïýð*#£,í˜J)ßš{ÝCcZ*u|ã÷hߺéçpm¨œÍ·Tn…,b¡Gyˆs„dîà[û¤r5Ôõ¿r=ß¼û ß굘0q{ªaßê[C‚ﯹ{iœO}b¼ÄÌ”î£q|©Þ ¬a- _ÈKì¸xuë>£î†«øÖXL—ø)ÌuÃu|s7ý2ߺDè(?tÐHÝÜ,‡ó-$ÛXeíÄn¬Š²žJ’ÆN¾5]|k®ÏÁþ€f£‘~6³•;~·(1Xâ§üšv޲žÎü‰Á?¤{gütîˆMôq 3¦{g¼‹îž« íi®›Îç[H¶‰yó¬é6¾Õÿ&êÄÎëÇ< ¢º[Æ»‚tåÅ?~†´Üïçû©Ž©š!6ø`{}"ªí‘#¶¿êClŽ‚ØÀ"uÄÆ­ |“!6±rĦͯdB(. U»ß]ŸÀ}ººæ7³ŒAšû»4b3iϸÎhò"6þÈ*CÕËwŸ ƒÆºLe·6.S)BŒ…rS„«O)BŒÕ'~ñ3t[bòèÌø(ë™bªk¢‡ˆË©ÍتLÚŒ­R 8‡o”s¤)>Tê{Ú CßOìP˜%QVŒ·Íêel+îW­Ú T 8¨d/¸2ÛÙ XªôÓ2øyÖ¬å@± ø’½`¢j9èkí¡ZeÌ/WÄ,ó ‡({Áü³1²ìðuö‚ýÁ®È^°_jYÙFµl+¦,{Á6ƒ±›½`ÛÕ²² ¹ g/„;²j»šûröB˜Üè&f/Pê‚M•½@ïªöu+\«e/в&Ï_ \Åå:{NZ[Ù T©`ñg/РªÍL­ZÑ—ªu5©ZïÑŽBÒ¾Hxñ{¶‹&¸Í,œî6­èt.ÆüÃd&ÆVc§Šo`bì q(LŒ½¯ ™‰±-@ ÄØ¬Â™&†¶€®m&6Þõá³Ö‡rWX “]°Éu¢ÅŠ.çïZÎÄõaÑoÇÞ6¸z¸÷Öc{LÎßNçäï-?z›ÕýËÓê¶jg?3~˜?ÌŒï{‹«å·«ù÷Ós F˜£ÉuyŽ×ô¸ØIš ;YSàb§ª».¶Lt±ÓÔtfP c[Ís³rdèØÑ÷U·󞾂"}_…ÁÍ;vÁµÿ?çöÿo󩄿çöÿïò©ýÿY>µÿÿ¦t<˜¥xŸªâ«|ªŠ¯ñ©*þ–OUñu>UÅ7øTǧªÔ9‚*„uŽ Š¥ã Š>UÅ >UÅ`>UÅ>UE+Ÿªb(ŸªbŸªb8ŸªbŸªâðÒñ%T1•OU1Ïéíþ³­Ö‡É)X—¶õ¯ÌúŠŒòRä2ͽaáGùÿ?œ6~îˆrGÓšQöÜ¢œõìþµEKq¹°|~uùüÊêúÖTS5æŽj.èÎ⯋jjk“l9IZ[³wì!žÓßÄhByþšˆ¢‚¯÷J”»×¼d[ªqyrvª®µ)*Ø#^×êÝ‹›’í5ô6Ê:¹)U7oö üEYí.¶Höþ’¿ª¨ƒ°x˜á¥h*Œ¶Ø0j<„Ú·»ÐŒÑ„6VtVtºÜ¥ÉuMM+£œïV°ã 3*Vðõ–Š%ì»W[Šø¯S-²ös:¦è£BÑèDŸ— foI¶V»Íå×g^ØKÍù—FÀŠä0{°ˆ“œèƒª&>Û‚ çGYoµ˜L7R®& ß½ø•ÍÉdX¤tņÝ_øNïâ.½Ú ¸&muKcug”ûaÆ< W:0¯oúPºÃA† ƒŒrñ¼°Rjò*ü¦_ǰu´H¿Uz„–åÒ#´,[ùÔ²ʧVî0>µr‡ó©L#øÔÊɧVî(>µr÷ãS+w4Ÿªbfé¨bŸªâ>UÅ‘|ªŠv>UÅl>UÅ>UÅ\>UÅ<>UÅQ|ªŠ#KKŠ©¢Ïipôþ³³òÇã}qKÿ®äýÖ]@?ÒŒùM‚eUœ¸D/ªS8›&kFž^:aŸÏàS£²’OÊ*>5*çò©Q9OÊj>5*køÔ¨<¯tÂhFe+Ÿ¸çó©*®àSU\ɧªØÆ§ª¸ŠOUq5Ÿªb;Ÿªâ>UÅëK'è‚t#Ÿªâ |N‡ÿ/Æ:Êo-ŠÀÍÉ–Tõò’ PÇ^ /(’÷¦µÕÉúÆš ãçá héo-KWa2%ˆþWM—i-FY§h)šDQþnŠmn‰ò¿®ÀúøÐl±QÁ \Pï+{¸ˆĄ̈›ÙxQf~£¸å­lv»`e $£nO0åý£üze?C#^{Sž*ÁUîŒÖŒ(ÿ];–Pᔪ¹ÓX¿ÿ<€ÑþëžÔ1á?áè›ÿõz]ñ¾ËÄöKŒá™ÿãóå!¦rŒÎâ:z×"ÎËî¥M¨.SÜ1R¸áR¯âj¢âþóÄØâÔuSÜ+ ÝîìDÃVåýç¶åAŠ¥¼Û¿Ç ‚_«ÞÕÖ‡Cÿ²Olah•ò7ødH²vâm\_:õ?îÚÂTS꩜»p^<ÈÃ!Žå?"ÕÃElñQ'3äЇŒ0ìÿþ-ú/vÒðQÖe‡ø>3êŪÄIÍ K›S­tÀ½…”È[‘~'5·&[R­íQ²¼y¸ÞBŽAøHôßIÍœ}N(>å˜<©¹ž{ƆhìfB×ï,x’4¯öÇŠÛò!ó¸&FN™Ê51z!³¹&f–¦«ÚõŠP<ñâéåS ÇØ`oíjñÄ‹+æÌ˜Í(n´·ÈýW$㉗ϛ7WƒèÞB/á­èÆ/®,›S1-:l’õ….z(âñDQ‰ê=$¿ï!uúšâbôÍÏ£Ím͈0ç E´(~gÝy˜Â}CfÓ›‘ñ5Ù…—œ½xÐ,ÈèèТÙs«ž·¨bÅCËÌ™1BÅ®n(,ˆ±#«zºj–Éžg¬ƒp’Ö^Ê.º„Ö¥ñä öar4¢hÑ´™GÓˆ‹~Ûˆ¼¾ÿ} Ùè\Þ[fМÔ;º¡AÙÚç²®—g®Ë^Œž@;oªr N™ürfåš™‹0†”™’ öý1ä#Ó7ÞÄ=÷æš ¥zCAPægÚ !!Ð9C7  »bü^Bdq)µtÀ™}û›þ:ü)fg¦.ß5únÅ´V¡¿°Û5C·²«ÝÃçØþX°hî#û#Û¾÷ļÑ&æCf©MïDèì=„]ß{úí{`½µzà¿nì½ðË®¼ 8üsðýÞŸºâá3BØÞ¨Ä"æ{ˆÐ¾ÞÓoß{„F„WST1€Û„5ZúqÚn|öqØš4û—›NÀaK­ï¥ìÆ«yßéµï;B*È3êL:xÙc8ÌaòŠpSãK­îF$L¶#'ª¦ß-!~ÊÙ;0ÚŽÿ…ñwE‡ifžºH(ÿ¼G ÌÅ­C7B33ˆ›tÎÌçÎbNüÌ ¤‚u‰?´Nº»þ¯ÛÇ5½sñØ6Ù‹Eí\ Ó9w„¹`ü\ ¦ƒ bCo¢a—èýÖÜ‚öÿ177Ås³|h€}‚¨NçÜÜæ†Yñs£36ûaÀáe±Oì\üß}¢v<¼O˜?#I° Aù‘ÇöÎÅuçöÜžž ‰hp—˜{%ý|>ý]uíe«îÎ.êþ$³²+¾[¬XÌœŒá¦ †Û?ž›+ïÎ)¢ªÎc^®¹g^Â}ƒ‡6¯f犜¢Ms³žTgÇŒä€Ýü_ïÎÞÈ‚PÞä¶<¶ØIˆ}÷}IêVnŽ˜BljP,X6zlmSjyõÒÉ 1zDùÒÓcó&ÑpÊ(Ái=vë=¨çôÄg³°Ð޲?™ë¡~§àQ×Ï·ž 6’Ü=Û­‡{ódÐ@z͆Ù<ÖlrÎÞ ²Q½9íÌuåD`ª7§Ýw]9¢êÍi±CWN«zsZœÖ•þIoN‹y»r"èÝ›ÓÞºr"„Ø›ÓÞaºrBçêÍiïV]9á;ôæ´w¾®œ’ÏÞ›ÓÞW»rJsoN{çîʉyŸÞœ–CЕ“ÕÚ›~G='fƒzsZC1]911Ô›ÓòYºrrŠêÍi ýtåÄtQoNkˆ&ä´jØûus4¼ó&k¸×sðΛ¬yĬ5YCÝÝ&kÓ5â;ÕuÿJ²€,f]i¶“ÈÁ(ó7ìI3–$I¥ åÝb72Õ HªY:º`~eá ÍDY{C·…òe–ÿýƒù3ÊdUmþ¯ÄùÈ} #•Óâ ‡nÉР]¯›hƒÄ¸TY£¸rÊØËf‘<êîA£Ä£ÔÃFITa²;%"´ì¬ß x%%&ÉÁIà¨éθ¾¦;{Œ„[G}ý´7ÕqÙ‡ý$²¥Yé'aIa›fI‰[Ù,\(!&L! %ÛÿÒ¸Îþ—>ÚÇþàÄ ‚žêáÇÒ·þÓϺk¨î’)S]þª¢Œ1%~ÔiMĉ| !Ôfb(,«j2T2ð[q%¿ï:Q›/˜ vô«ErWª²E¸OÕµHP¯[$ƪ~ WQ³0hj\å ©©rz¦*I`KS1X›TÕ 2Ñt^W7xÉ£ ãA°.ße"'—5´¶wÔ4:ý¡Ý:qÚÜ {QÊQ2?Ì(¸;ÿ@ˆþó?ð—¿þU¸ôKTy¤õX㊳è×ì¨àˆÇɵ•ט~D”{bé4j*ÍóIË7™¢•- –í'keDåÌã-j΋KÇHñ-¥c>,?óQòå£"„åŠ Ðv>Ú[kæºEòh9Åó)vYÀ{,–ÖÔÕ¡Eó)'jÅRx'hŸú8{°ø¹Ò1ìùÊéSí¤8Hÿíxf¥wmØhætmåyžV›´ˆ¾R:í·øø?P¶ŠÃJÇ »6~­TQ:«xéˆ<ÅòÒ1¨YE¯}‚¿‹[úì…-ÈÒMN&°$Õ2Ê ûÉ´CšM‡”ŽE+zßL’‡õå43Ñ¡ªìóx5V¢¨òž'8=_zbà¢W<1ÎÑûžXQÕ««<ö±µXŽ[¸åw?¶ÛKß}ƒ”z½ñqàõ¾Ç±_åÊJõã(µò’Ç1seúˆüÄÇÅaú$¨*rb-9bF4Ì·AŠ)?èHMªC«ì, Ê”ï¾8,?©IPáìªì\™FOIÊù¡.LMrªÌ%¿"^/‡y÷å"t¶þœp¥hLL)Ðù(¦‡ë ÀÅõ建 ¦]PM1qƒ3@_ pÉó]¡S ŽŽ(f\ Áî•¿t­~W1À£;«)f0´¦V‘&Õ¬ ŠðC¤è ÒN0µÂ ÛÈ R²‚¾ß! ¹›‚†âc¸t÷mAÛ‚¾mA:T›‚†£ß5R̆PëÐ÷ѹ-HüSÐHÿhGtÐÄa‰Þl9:i›rFÃ:À™‚ž’>E¨œÒem9ƒƒÌ\+Snˆ¢µÊgH0x&3P %û¾Õdæ{CfîMîíœî>¹·¨hmŸÜ[|ŸÜÛD;ž¾¨ü·¦[î Š£sØU®ì”»Ûy^t½rwNM„ÇÅ»¥Èr™¹Ê~÷ËÌmËNàm_2skŽþc¯ú™«|&H½K¼E&3·g®3™¹éY·Ì\à 7ÔNÍÔN®ýø:ªÿ?2s£ÿSfn[¿4RkÿIfn ßG‚ÌœÅPÌÔWÓ³¶K}gsu©/Ñtšž54Ô—›™J}­ùw©/zî定óR_ p/õwŸÔsàw&Òj’ƒÂ·V¿gþ?©/õ×H}íÌÙ0{ä®Ü¾ÕMé;;ãGR_ÈŸí“»¢ß¾÷\è½<5_°Iêk[Þ,Ô‡€Ô—íý©u!È–úªK¼…Þ›kW.ñ&Ì€?Ëyƒx°Åõ=—ú2ø Kб©¯5ÃÙǤ¾ èî“ú òn¸E‹Ç'ÙÀC††úú1ÎÊ¥¾ÖüEš úmÃÏ·/õU—@ R_ôØK}ÁH땲y¬ì²_^ª‰±'%¸BNè`OJp…œûdÈ,vèʉLÑ“\!ç>é2‹y»rî“. \!ç>é2{‡éʹOºÌÞ­ºrî“.³w¾®œû¤Ë‚WȹOº,Hp…œû¤Ë‚WȹOº,Hp…œû¤Ë¬ïö®œû¤Ë‚—Íi嵨Çué,Þy .î³õVíG\ÔÝ-ÁUD¸æQ ® &Õ)—CFÉ21#ó+/ÎWÙs«@ØC3Q‘<î5?d?´YÐȺLy*&¼Ò°`K… kâ ÏÝ’¡Qò_øÞEH•5)‡2Ê™ô¢@=À©4´µ&áqÝñ’ȼI¾¤ââ^¨ýž×Õïi[¤«ú©MC?Üõ‚øúÉ/š¦»Ÿ¤tTQ³ØXÊÑ,^ª¤ùƒ¢RÆm:‡ÖElµ_Írç¦*›%ý£êú«_zÝ_ýW¿úË“šæ²ÿÝq•ýïþK•œ°º¾AšŠrÕ¦êÈ3ŸÒÀD\ÝÀÄ£“>PèJS:P ;<¥ãöM½Å¼Ã¶˜G»–Û§Ö:•«Ö3H(Aõ ãGõ ’Pšfk°² ù –§1Õ3x@ Žz“ê”Ö› ê"T«z† pD†È‘úÓzb\OëkíO«Üº©¼«SÏP!Hõg¨ü©?ÃFÅõ ;öÑþ)-5†IMs8\[Ou — ¤«FÁ Œ85®kÄéƒÒUˆ°esi§´ºÁFÈå›váy{ÓÔ1¯pcÌiߘ¯q*]•¼øÎ>=Ô«Ê•R’ïœèú?G_úo³òó~õ*k}k·ÈÌüDÒøQ#¼|Uÿ?-ÛÿÀ‹œø±ü‚ âD{;çô«ŠõhQɸÏW%íõA uå‹Öf%¢žäËy¨§ÅämGëJï—ž 9u¬Jíã$­âÈPÉb×…`(ý›HÔ¯ C¥ yî{dŸ(•ekŸ¤Ævì§þˆSü´«”ò ?pFŠhWi¤>A•HÖÝ£*õàÆ}ç ¬Tw6¹ÑEWŠqÊXú<„Oõ埞 -<¦+…ÞVeåãÕ8]©§>A )=1rQã÷Ä~‰Î}bÛ•³Û¤•XWê‰%]yÃ㈠´ç£Ð¥Rö8ˆª¼íqdVÙçq¸Wi{}þÖã6žð°ßG”hDØÐÖ¯_脈?îKMªÌõ²¢ëŠ—\b ¼äÒ“(¿&Uá0X‘³/‡ùóå<¹„k‚P¸{ b¿ør|_Γ˜¿&Õ‰¤QDwWŽÙ8®œïÞj‚Pò€Ì*+gq(ç;4­š Tç·~2^ée—Ö¤e—ßµ®/Õ·–ÍŽµì憵îçæI’|Mªëýu2tå<áÊù.ï¼CJ4ÐÉÙ;é%á/½ô$ƒ»& %QÙΔ’„Ÿ2¥¤' ZMª…{ñàXÓ,+(—^zÈuˆCi¶:™‘T))íÐ÷Ad‡8”üx‹5‰²‚ré¥vÈ‹C ƒ,6Bö8Sé%»fkÒP#ðð9&ö¥ë¤—„ÖSé¥'è‹¶œ– ½#ãeœÀÖ8Ò(éÏЛþ߯*é%K_3º.úš¡.x›Áh¹/ŠI4{+‹2ûvT¶Ö“hÎ@ò(a§ÃùæÇD¤”¿>Æöí#ŽÚ¾¸&Y£w;‰±΋ªïwÔ¶´âatÛ㨺qÔvææºvò¶ä¿× Å™DáÕÒÕ[܆Uå6$s¶#7Èmظ‘Ûø_²gÒ²gçýP#»%m ®0Z?´½NZ?=ö´~Kk¶ýG" ™I[•—»™û(=¿£¿çš?ÍdÖs?¥j}¿I¾òø)ƒs›J8ÿ§~¹6,QëìPyPŠgŸlYæ^Œ޼ޗP¹á4×ïÖþ7§·5<u¯¬«­¤BÊ/3–_:(‰‚(e‡DHY‚-BÓ :è:Z±žT[*®HÖJò®èÔQù‚ð§¾?i™?9(&Ò]yƒ†M•7ÈU«*o8)ÎßpÒ–ÊÌ6~ƒˆ@Bºà  £Xc*Þ¨Ÿ‹+iüÊ èŒòå¢3HPuô¥IQUÙ¤LúßtIüºéæK4IRBŒÉ~&dÔoÄ_ªì§í *û19LG?U¥ùmÖz‘ÔKóĸºæ‰Îq³¼ÜjÛ4Ëä¾f£dÏLô¸U×úkûj+oM’Áé/{M]±È´³ú_×Ûÿ˃ÝD´6«y°‘¦J%ø5@ÄJU8@d7U7à+|Ë9í@I1ʉß@¡3IܔӥÏÒ0ˆŠš‚–aqõ-›K‘ÛWß§žÐK_þƒ~áqªJ_ .•î'h1SŸ ž”?دÛÒ«ºQ¸IŒ(÷h$PO~ñLg9è ÒÄ@¼|Éè •]g8­”ò'œVŠDFÞŽI*|òÄYÝ©’T>üø¹ø=ôB4øWþîøšœ û-›Ò6J%¤Ct…~Óg¿xç{¤CöJ­¬TÙLËás‡D¹¸Ñ‘¾Ç¥·Âr“›i|9ñØ8•Ï~lPËS[ •UO¬c2æÉUWÑû»û³RòÄ*GÒäIxP^ò8­¯o u°0Äômð^hžèH‡Ý?JŸŨù¾˜'ÙƒU዇’2~(ôsš¹Tøâ ¤Óá„F—ÎJ,‘`ËaØ}9O§'4:(Uè/ÇlWÎwi5á‹ „b®¨/'íÎw _5዆ÕÔF¥DÖªÄïÒ°ªÒß0{®–¹+滼¦ªðE?h[ÍÎL£-áŠù.¨*{Ñ  ¿soå ´è`þ]ÆLUî¢?Â-fB'EJ©TÃC¿ ­°ùϳÅ+Tø"ñ.kÄË"*GëäüúÀâzÛÚ¹ÎênrQî] t]Ž:¸¸¤3‘(ŸšŽ,LGÅ‘è'Ç_jùáY_·B“ye:Y^‘Îo#¶~3×hßâkbñÆiK»wÜy§kbñÆ9Óè¯}gøö²X¼±²3¿\äT¦˜ßæVÎ:òàQ‰ƒÛîý}Óò"{yŬ#ïòò£mÉFœá_ÜšÐ:¶¤¾7445´'ŽNˆwäwWéÃÉ-`ŸæÞÐÞ:¢YÃ˻ںZ[ÛR…«œ<•pÊ«ڦϟxpñØÎ }måkZ¯ÔÉC‰i÷Ø;­Ã×w‰¾`5,þ ÿU5|Þj8î?j0v"cxÁI½9æÐ›£rT:G¡ànÞ7ûâ*Gpo›K¸rèMƒ¾'€¨Ìk§¡Aß@SææÉ¼Ñ÷ofèä ß@Kæ6¾y£ï«N‰Ö,Xœ÷~÷Nß¼Ó·Þ\èj²15é{¨Ê¼ÑÌš7úÞ _wçêhòÚš¨ÔÏéÉw_10»½ñmûfi'ˆ3ßÄ÷<ÿ~×Y篻1ëÂ5wg]ôª}³Þ³zJÖ5«_œõµ×Zk“U¸!otݺ£o®¹;ºþUûF7·HÞ†LÞ$çMê¯÷ËÔûÔûêý«ÕS² W¿8{÷wå]·!o2rÝÙEkîÎ.~Õ¾Ù£È{6y±ôâûtƒõéÆþzWQïyÔ»†z×Ò§kéÓÎw…òÎ’µH{¢#÷hr!w¹ÇM¼;kæjÂÊ¿t`Îæîuu³…µ7·Ý³O ‰X÷ÛîÎI÷+»ªûÆœôÞÆÞÙºøW…%«³–•œ›Õ˜~g5 Äh/\Û}JÞî¶³¶u+Ï®hxɧ³f¦saC’îôƒwí7Gé·sAsáDιÙåkSÚß_"ëiާFYºö¼ª´¬»ç&ß+qÆÓ: —¿sÇÄY•쟵N<ð÷ƒAªüosP,® ‹ê’K:ú /JÙÕs½ÁPÞNz#,ÆÝ¨­Ï:PÆ ŸÞ­nì/·\ë-†Âƒ·ý¥Œ ùxXÆ™r<²¼M§#_7ÏbhÏ-²˜>âJ‹aìl‹éþ×YL7Ÿ¸ÑbºóÄÓm'î9ñÓäÇgYLH#>ßbÚJñÅÚˆ/µ˜PF¼ÞbB ñÕÓí%þšÍ‡î-ñ­™ùˆo³wº§ÄweÞ%~þ4¯‰×‘à]‹½Óý#Þ-±wB6I]x·ÍÞiË$~æx÷^{§ÛCòµðÎ÷C÷„B¨»0ÂÞéFP˜Þ­³wÂý…öðî{§YXÞí²wÂñ…‹Ã»÷ZLú…k,¦Í^¸Ëò‰×ZÌÍè ½FŽr'[aúâ¢ðnUÆòR±%¼ó–Pàéwh/•È\Õæ’½ ÀÏ?˜›Ào1¸*•ÌAÍÁ!Ô³:’mí‰z®^—6ŸØœZÑœq õÜë2veb¾c¸'cœ£óTß„^èùC2°lutŽp‚ÑqXu5H‹¤˜è®s6‰®ç{ß×ò 6¹†ïu|oåL²…ïM|oà{ ßkøæNpß[ù^pÂ’uuY{ó=Ÿojjçû&¾§®«‹®ã{ñ/ ‹ìªËÉ÷ˆT6ªXVj¦|6Ú³¨nÉÒj•ºÈñD³Å¸zM ô.·wÌß h ÜnwqòI#ý/à>£×ÀcÐ-1Ú…m3™_ÀÁ0îˆý/qžq0ŒæUtñk)iL·ó4¦›zÓ­=µ„Xkˆ±Ñ!ÖbãClBˆM±©!63ÄÚClÞ6‹3ì«8™Åøñ¢àø| *ô@³ÓV×4»«ÖºšæºÆd"YßX³´-±2Ù^äscöb:¹ÅïÉ­m--ÉÖĨñ‰% ím‰T½UÂл:`ºFâÇôÔ!ªìúú•‰9U#Ýezr‚=»bF‘H1®ìËp«ûõ5\ …dujisÃIX·ñK¹­b:§ÈKãžhw³ Q…±„k|þ& 1Y0Ã*ÑiÏó»ºP¸iW_÷íèvc<Ì£Ø*‹]ClÅ.'¶Îbˆm°Ø*b›,¶‚Ø‹-!v¹ÅæÛj±©²’vòYë£ýds¨ó»Zù°ž³°¨ê³y?ªº2wIÕúÜ »ºs:»ÎÏél[ÿ“¨+7*Ý–?Y_òN0‡&F·Æ#Öò~ŒèLó°ê…¾˜@=¨ôPC±]¢£»ÖçtêýY7Þv…rÏ[Çaç­=»tE#J25T.ÝVÃÐËî«áÞžþfn«á ñ÷Ôõ”\°K åK¶Õ0óÙ¾yŠÕðUzÙYÃÆm5ÌkéëùÊy?¸'ÏI?ì«Õæ¹ùž<Ëßëóع,LÉô¡TïÞiwµÎZßç XÑýÂe]ë,¯Íen OñÚýòFÄû%º¦äÛ#.âŒ8o0âÌ’o;Œ8™8q|É·FìÙÚ9csªìNvùG>çÞÅkë£aü§æèì|¬‚ŽÈ‹ ¹7£î†µùÔ¤žï¼›˜Í9žÿ®OŒçíäÉô²ýôžžµ¯ˆŠCl&ùÚù?ÿóU‡ÃªOèõnÃÊs!:ùÍéM 3ÚbèOv‹n ·¯Ûìxé®ðîSöNø'½qé]ì±°0MÁßЄy hªÌK­ó‚uÁPà\¡ƒq±wƒ%ð­¦'‚3VàVWàÞUà&UàÞSàRðXÒº?Ïbó󘗘ǼÄ<æ%æ1¯u•ŸÅ<æ%æ1/1y‰yÌKÌc^bó }ò˜—˜Ç¼LIç §-è"ÚþZ¬GvÍH“©O“¶œÙ Ü|‹»–ØŽjX á}[^ÞHÅO–…»üíHbz› ê΋ös{C· KVV·$›ëšû¶…ç»ÃÇèPC°n%˜<¿iÏr÷âÕÑšÁZ›mGqW±€º£Ðj#?‡ÿÁÈb-L;ñ@e^“l«mmh¬µ²qÄaí+[’‰ƒëæ–±ŒõmËð9õ…ë4cî±Ex†ÓN¸_m£*póÂþv{ÿ½¼i¶™Ml|Un÷¾|O€crt×i9ºM]/×ÉyQ69–J/M1ò ‡e ñF⋈]‚NK¶XA=­ªKv¾FXMóßLöoô="Ôß:PÓ£7­¯DcÒ³&h7ý6¼–TŸIæÐïxæÓkáÁÊÜb^C  Î{J?~·i.Ódz83.Vì£f|ÝÖOw£Ð[¢ë딿ûòЬÇw—YÃT³zï§Vå]*½Î™U¹—<ƒoiÓíÚ L<¡êÆœ}ù.V}»3±æ3hì}jÙAUÿ²øÞ´Uý]iߣ«¾0s$ß#ª®ª<œïÖªÏ/Á._U=½ªöSº>³Wg×w÷ê<9‡ÿò!ÿWóû^«xw¥ÞGüç¶ñÍy¼sØ3k÷ÌçlÏp'½{pÏ|Š«òéÚ›Åe¹}RxÅ”ªu¥E]‹©“Z?êvʮռ=£ zú@Î3ò »oý®Ë¹au-9Ÿér¶U=ÅÍÎøªaÌ ûªÂÌtÖ¢9Ø]Ë=9's_z~‚ÿ Þoâàø¶ûöܺÇ÷»¨ÆIw[ìõS‰}Êö+®cÏ%%Ãi7¥{J²ÚT%x)óv{À✱b”Wº:Iæï}z4}Õw(\·_tÝ%°2t×»gÕg~êx3ÌÉΓ£ÜkÀšã=k±±ÆýáÇÖvDÏIÏÏæ^²ghnôڼܢ³Bí®`çƒÝîõ1éÿÙ6+`ûŽY‰® ºŠÌ‡Ÿ•³Ó…Jlî£Þý>æX¬*Š¢ïu|ù^Å73°†ïf¾7ñÝÂ÷¾[ù¾œï|oà››M¼öðòب‹øøuûeí}ɾшIŸÊ:ÈëYêý䛊E¸ˆ\3ɵŠ\íäZÞÏ ±ù–k¹n"×rÝÞ/ ±e–k…›ó1Ñ¢IŸŠn ïÏ ±U–k u}™\ë¨ëÞð~Cˆm²\[Öí—=’\—OúTöØð~kˆm³\×k¹vkGxmˆí´\דëNrÝ@®O…÷7†Ø.ËuS÷~ٚǛÉÉ<ÞBœy¼•8óww·¾ßËw3ß·óÝÂ÷|·ò}'ß#ø¾‹ïÑ|J;RõÝÍÿÏðÿ³üÿÿïá}ï¿DìËÄØ_á›Ýp/ß솯3óŸáû›Ú“‰tuýžd;V×ät[“Äslv$7“Ua_n ûòÚðÎóŒxç¹$¼ûlxçygz{ž‘ÞÅ£óÎëón^xwNxç­çñnGxw}xw[xw‡íõŸÄ@w„½®]žb}ÙS Áúò~|ÒSË[[S­áj`YMcCÏó üGyM¬ÃÎ<ç¶´46ÔÖ8R3‡´6ÝÆ¢=È)öagN+l÷7—uJz!Ýê4ßòÁ^è½é…òuæÙÛ õÀäTOÒœ‹vä„wMNõ>͹xGN͑ɩ¹Js·#'–·È©¹Ms¿#'š‹£É)½Ê4çÒéUó\ÖÍ+á§\'tùÐ`O¾wäË`·Égòë¡Ï++ÏF}ïgCÞî*ïÿ¹åÄØä“zgÈW¯rÅ|‰‹:|)#áá—¹IôÔúû3ífÔÃ8Íå©U‹s¿¿=ÇøªÅy‡m¯ _4ýÁ:ÜDŽùܪsÀåä𜅠ĖíÈw-9Ö„|«vä;‡[B¾M;òM&Ç5!ß¶óõ¿‹×[¾¥ÌÕNÍՃܞþWW-vúÒÜÇzsÜLM7YM+¨i׎š.¯ª¥¦B”EŽñ|s_ë͵”Ú¢µÜô]ä{ß |¯â»™ï5|·ð½‰ïV¾±«9‚ïËùÍ÷¾Û?I͵ð“ômøNº­¸.ˆ¾u£ŒÄù^‘gš;àÂü ¥?yN§Þ¯ˆàäˆç•r”~^ضq”öÖ ŽÒžÄQªÕ0s[ â(í®Áq”ª5ˆ£´·q”ÒIJ5XŽR­†ÛjG)ÔÀ÷ÛóGÞ“gQÑ=yÄeÚG\¦®<7ß“G\¦G½Zq|&z&ýЧÃgÒ·çU­È <¨›à3Ýy`§Þ›Ü6ß.õë.ì:ß¿×lñýÂÜu÷ÔqÉ»2u¤y ©–çê}{ë]‘ïÞ63k‰ã)ŸíAá›]§ÓSÅv~Þî›rfr4;¼ý9•k™O“KŒTÞiŸ»úÊSÖ¾3gVº—/Ì9ûž¼â­¾&Ç ²¿*ž×ŠèÇçuó×Ò;Ž] Ø9žÓ'ÀréV²8Ú¥‡·Ë¤KÂbšvff•¾Ýüœ§˜›Ÿ5qÌÌÏZaQåËošù§(fæ,£˜™ðŒbf~À4Š™ùÙÇÌül‹cf~®±|Äv›gósm˜½ß=?zSå5ó³sCŽêü(næç›ÅÍüÜÇÌüìÚ>?ׇù¹žùXÂÌܤo7?oSÌÍÏÍqÌÌÏ;„Á•ó–›ù¹5Ž™ù¹-Ž™ùyo3óvWÌÌÏqÌÌÏqÌÌÏ]–اˆiךù¹;ÌÞïž½©Îòšùù̆ÕùQÜÌÏçl~7óÃB13?_Ú>?p-ýü|–ù8ûnÚ|Ûù‰¾©˜Ÿèú8ÆüD7è&¡OºG0?Ñ-qŒùÑ-×ĘÝsMŒùÑM×ĘÝuMŒù‰îŒcÌO¤ûùè==Çæ§æ@ïwÏÞTçGyÍü4lÈQÅÍü´Øü(næ§5Ž™ù±}~ÐòóÓÌ|¬cç|Yßnÿü…bnÿ|%Ž™ýóWºÑ('ó ûŒÙ?̃bfÿ0Š™ýÃ<(Æü$ê‘bÌO¢{”bÌO2,Ž1?ÉΖúGâù‘ÅÜlô~÷üèMu~”—ùIvߣ:?Š3?Òþ±ó£8ó“×)Æü$#¶ÍO"^‡›ŸD¸ñòKà>ðmç')RÌÎORǘŸd”nVÊ Ô½ŠùI„c~áAŘŸDxP13?àAÅÌü,‰cf~¸)fæg™å#¶‚ØV›Ÿ³ÃèýîùÑ›êü(¯™Ÿs6ä¨Îâf~ÖØü(næ\§˜™Ÿ Ûçî´Ÿpãff›¾Ýü\­˜›Ÿk☙Ÿ膧œà»6?Ü3ó³3Ž™ù¹>Ž™ù¹Øµ67†¾êýîyЛê<(oq =ÙElWUÎç§àOãéÉ ¼¹Sß®gSÌõì®8fzö«ä½‰~€©vYÏîŽc¦gŸ‰c¦gŸ={UöõºêîÁ^¸ÑzvOèrå=39L¾ÄL“¿“3}Sí³©Cy¿´!Guî?U})fæ,p3ß`÷[è¸ýVâôâ6âàõ÷®…w£ïÛùfÏßÁ7;þN¾Á,wñ=‚ïOñ=š;*½ô>?¾Ìî_á›[è½|sý:ßÜ@¿ öú 9ïõ9áÏïÜo˜ã§í\•7âQžûÀsŒwÏý'¼¯ýÿÄkÁWjïà›, ïVØ;8%^‡w[ìÜÏ‹áÝ ö®ˆçéðîv{Äk'ñî+öNœ¸—cè¹ùâuÄ^«ˆwKí¸Ò~ÊÞmµwâgÄ…w·Ø;ñ0ÄUÌÞÝmïijH5›ô.ÕlŸ"ñ¶ÚyçgEWÏ%û1ï F¬ÚNîÏÀëÿÑx«sœ ]@ÑÆjDwêõYƒüðb´W‘MðÆŽÆÆjyV>¯¦öÄâêj'ëåëpö_᜿þó÷Ö1Ó×!®°Ý%›ª“ÍËUʲQGø=á \ÙÞPY)(–S‚Æö@8%ÒxËçZZSíHƒJ‡E‚.Ø¥}—r\VR\2~Ã{|k4ñþz/ ú öÜ¿Çl,Ú¸ïÐû…ó‹êª—$ŽLÜ!ÅŸã“–CÞ—Þò¹ù9ì, {,]ÞFœ^¼ås6ž-7²0Ëã»Nƒ¾gò~Ùö÷­o¶qtùš¹ç¶Ùݸe0Ï¿Ïse¬q÷„¥è»Ñ{;·=ÙÉHïÕ ðc̰÷8d-CÛwÌí¢ðÎk1¯¹þVt‚½cN=7w^ŒÙôû–wž§‡î–ô…ÍnüµA¾ë7ƒf×ûˆÁ,n¯›ÇúG‘VPê9mîÞœìÈzN|ÆzÞùp$ë9xçsÀ½¬çàϧ³žƒw>\ÑzÞùÜê9xçsp¯¨çàÏÁ­£žƒw>w’zÞùÜXê9xçspŸ©çàÏFC=ï|ôJê9xç­hƒÂê9 :su ÜÝ9xçs ãVÏÁ;Ÿ­£zÞùh-ÕsX{ê?²á¾`=‡Ó179Ð&¬çàÝ÷ì|ÛhQ×sX¯H6:¬õÖ’EÎõ¼óu Ÿ]Ïam›Ûœê9¬Ms›ïzë;Éæ@O¼žÃúL²9Ð-¯çàÏ>z=ï|tØë9¬ås›½÷zëaÉæ@W¾žÃzV²9¸©ÔsðÎç@¿žƒw>Úûõ¼ó9ñ·ds Å[Ïa=3ÙÝÀ]§žÃêDYŸLàÔnŸL‹hŒ=à»Q¿’îÊ:X–ä'SŲ4òJTAÍ*æ²ÖÀ&KxÓ€åqœ\6¶:û³qM‚ÜP*Ì6KÈ׊ QEÏáT\@±k8G¿ª#`¸äD™·@¾ÑRJÓ…`4—©·EûЃ"ÜŸ Œªãþt´Hc˜¨"$€1z§¾Ž¡«E®}c^bóy3®ýqç“?CIÚ´9V0¬¼¨».Šcƒ£HûçBOZ±¢è·YÆFwLÅF«ÍFeÇÅNÍX3 :Öéÿë£]=V–B”o¬ü²©’±ÂÙš–±x7`Û4‡:ûµ‘mÓ6y:Ò”´ÑI4NÛ¸§2Æmº9‰]jV—¦gœlèKn÷T´OÇÑqôO`2Љ;€;*Xó@aݾOÅå®ã¸³²Sáûmç@ÛÏe1]:sâc€þWÕÓñò𥾗Yr±-Æ¿1î×xÝ×Ô³ñr¤-pö°úsб|‹ñzV‘úrÌŒëFpÜ)çÁz¯;×Á²‡/¿‡àíÓCðqSÿ!ä‹Ñº› ½gÕ?ÜcŸt6ïcòNxC¼…&pãHØRðŽ!-’è0´¨ê=”™J˜µCa'¼=”{;ôPêGKo"{=½‰Ì)šz¹Ë «7‰þ¡­7‰ûWý$æ¯À¾˜Lú0™Þ˜µÉÌhùüN¾U÷a81e»†ãÖ}: Oútø7âù›:ÌM\6,nômm´p‰¸~âyÃMãTm*uyª®qêÒÔwð­®LÕtjËL3§NÓžî2ª'ó<í(ËÀÉÝ¿QØYÓÌßÀ4ÝB5_Ódø]ÕM“g'õßBÔ4]ΟÔãÚêñ i.k¶g讫]3Suè6;K›V›|–¼d¨æYS]7¶üHz瘞×z4K7MÍâ,骳ä@K{qü võ,Ýuã=R·:Í2JÆ1½h×ÎZh7ßÊ3;ÿ1;iî+ùÞ™‹/ vÅÜ;ã~ÌÛõÑ~ÌcÖ™ºyÎÆ€¾™õcžv£ò%¿ÊqÔ ãºŽz—«;îNpWÜl}]G骺Žbß±CfO0WÇèÖ Ø1oæ[º"ó5ÇÚ•ó5_ʵ OÇ y¨ïÇ²×Ø‘ ÑÐFKn‘ô˵«áÌ *Ábz$„•3ç1óz܉| ‡Çí(fV¯á[;øøóãþï›—ü m#×±“´TéR]p4 K1ËÞYªÎ©â¥r3¢Mq²¶™&âd9QgOÖA8Y{Kèàd¡uúd4ñéôɺÔjƒœŒó MžÌT³INºQgN*ÐF9E“ ©9åõ|«ë§ÈI¬\ŠœÂ6Á©Rq×DœÊÖg"Ný+¾µÅOÄlñSÅR¿N[Æ\}–”c¶÷2ÊcúµŒ:AvË IÅü_ÖŒéÓ26“³Œ™œÓ¤"/”uØ7¦O§b&ô4P›æ4Ü¢Äôétæ&¦§§s‰éÕéàG°óéôì|:}IØX§s1Ä)áé8ÎHè×r&9a’—³Yfn¹P‹ê\Á,½‚  YAfé tÿ ÌÉ ÜužÁ¬éÿàƒ"yÎ`[™3éGŒ}&>^Šl3ñ/À¨žIý%¶Ä™\¬Kä> ”Ub.Ï”éçJz_fó¬b^ÊÌÝ*6qý[Ç|6зu¸\i oëÙ Èg_™§gQk#ó 3Ö|57RŸKž&æçylÆ~Ôw5Š;ý¨o;B4ý¨o;h e/e_ô§¾kùߟú®e Ÿ×Qß6ûõ Œä{5s5ýs¨n sûºCãMöºV·ÓÃ&‹"PAºáý¾¯º:{=ʺdýߺ½—¡²ÔÛgÇÞr«äWôÖíö(B7ZšÆtæ÷øFÜRÞB_AX7±?@V7coÞ$•oÍÈMº*h^nƒE3÷VõDsÿV¹Ó~yë‹ãºßªöÍáÊŒx<æ2™å`{×^p=`Ú²8«½àrP{±Ú ,ç×^`9¿öB®`:^€*j/ð¿T{!0/¸hÔ^hÛu¼ã—Žl„Ú Pwí7¢Ú 鼘+hö‚ Ã}5{s:XÙ Ð÷¥ì…®+/„@:^p[¨½¯Ö^€Äk/@tø´É^Àà©õÌáßü…aU_NRõÌ&®èÙ az³o³°¬¸Hg/¸›qëÎ^påÀ©Dö‚­ Ç'{Áõ4«ÿlpθ­•ÝFŸú *;b ]Rÿm\Y‰I«TùÕ¶ö—‹‹‚÷S%žzy“Îeê¿ ¯Gĸü"îê.8Äp·ÃŽÓ$lgb¸ÆOg@%6ÞõÁ9Ïsït0=â‡7>ßÇ‹,Vt9ÝEU/™|ÿÙÞóÖ¹ÿSǨçYÛë±=&篤sòÆ÷–½Íê¾Óò´:üÑ™ÇÏŒŸfÆÏ3ãûÞâjùèc5"=§ ©§kr]žgjz\l£¦ÂÅ6i \ìu×Å6«ƒ.¶EHg~Žç¹Y±×dûãÞáûÊõÉzÁSò¾‚yÇ.X©Ž™ ¡.îDXQZär-·­Åï)Vµj1×Evܯ¹/øÊðNœ&½øˆ{÷I÷…›Ñì55r¿–J‘ª§G8pð{¾€ïÜ&§3éûkýâ}ØÕõ!W˘Él_¼ÿ±Ÿ3¢Ü>gF¹Ãøœå>…OUÑħªèǧªhæSUX:¦„*Æó©*âSU̧ª8„OU1OUq(Ÿªb"ŸªbŸªb2ŸªböõTÅb>UÅq|Zó©b ŸªÂ:Ü+>ŸOUqŸªb)ŸªbȽÎkR¿‰ÉÜ¢Ü#®¬5šé8¿£ÙyPÚ<£rZ-æ7Š$›{êŒY5'­ì§òÑ=]¾éé·ÝÓ§nzú÷tÁ¦§ãž.ÛôôùîéÂÁ§ñ»œÈÈåÈ ¬llhNÖ´ŽnYÖ—Ï€üÓaÜä:?Ù^»ÌÉL˜$2kåRžÈã¹mmÉ&‰Ð–æ¹°²M¿ám–V’åñ±ûÁ(ë%/‰ò^ÝІ#AªÕËjZ«—tphüª³ødbQ¡Zd–®l‹³™V û²Ò±£&DÙÛl­D¹KKÇŽf!ù€EƒÂ‹Zjšjïì ԥj/I¶w´6WÓL®£0­˜¿(;žÝò—|j·|…Oí–¿âS»åx—(þˆ,GF9ÇRP”ss5F³H¡ÀEx—29u ÿ]oâ+Êû¶{m£zZZDæK™:ÁÙôвïhoˆr¦aÕ+ÊûNmMí²dTðåIø¸¥%Êyj9*[¥QnÊ©ÏÆl¸$h ª­Æ‘@adkõŠ(«¦&Ê}‰ìEy_rî¿dMÀ|¯lCqDyâ¥K£œo#ç!&à¹Ë)°q)‹f:»:i[‘j­«®MuPmi QRßÖ .î6B´¾/q$Žr_ÞÞÖ–ÉSyš^±ú g×…zÊ_& U–ÿ€yÿóutço˜/ÙÊlû­ˆb=ÁMµÕ±o”ó]$Åùc…¿ù‹¿„Â‡Š’í}`ŸÄu¬°%¥cT¦—Ž+ÆøûýQ÷/Ž!¹Ztð¥í‹oV(ÊKö=Œrþ‰9‹òö¥À•|Ò÷º¨àT÷|cJ»vÖ(|A.{\¼0\€©øÉ F&k:£œ 埬åKV`ô5-¹„µ´4ÙÆ»0YÇ×òd[K”¿{¼­£œg$Z¢ìo×¶a5r3÷×ñ16ÉÇ1õ|¬$Gñ*¦þŽú(–-U¬8£AŸ…]êZA·-u­ ÛAu­ ÛÁu­`ß¡u­l‹au­¬áíz1³½¼<«½¼|D»^Ù®×ýjUAs­*è_« Ô*ßÀZòmh^Ö€|ÍÊ&v—œ Í7ðšÒñcÀ”7ð)°òîÒñcø[ùlø9>"~žO¡‡_àSeÜÆ§ò¾‡O¡‡_äSÈô—øTïåSUüzéøqÅQÁß?®UšW4?ÙŽ—³\çaÔl%ˆkãÒ~Û˜Qî5©>Ï¿_¶¨øÿ&FT|oMëR>?ȧ6ïß•Ž×=A×î :?pOX:^÷„>5)ϸW§¸+¯5…7ozl=iNøKƒ’·lozù€ÇÆ®üžÇÖdò'wwò×ÿ’ÏþÀ¼ü~¸\^³Q®»øÆ¯Ú†× s6`ú&ð°)ªÌ˜˜Pr%ËŒV½ôŒÀbÒŽOs \/éž—wQWË{êJð5„b?5öiJpc"³Zû†ÆáiNEm`𓲉vÝ8ŒjÓãæWªÆ4§á·kš"äÕßu¥w¸:¼#Íi0Qf9mž¨pÓÖe翹5©úÔœízžÈI©|½ÈïXå¨úל‡ë°£tg« lh)þÙGFÕÇæQâOr¶³åJŽyÂsCÕÊæIœ”_Lj†M’Õó]-Áª«Í×ë¿%¸ ½éôý°’]uþjÍ[DC颉‰vþß$íj•¾âÎ[«]¼ãA-ó=’j]¶;§CZX¤ƒ½ÈÌ3 t ‚=D6´X6<ùæþú °Ý9ùßmwbÕ³Ûþm—íÎI“½=ͺíNo׳Ûv§±ëÙ×í΋]}‡°ö ‚kIÄJúþÛm“Å|¯½:Kz-~†—¶´8 ƒ[œ‹½Ú¸³oX™X’¬­éÀ<åæ–dm|/m^ÁÝve[;{­­¡M½|MH`ÃK´ÙjMsËc?—è%Ê€×)UY¼(ŽD3Ÿ.«¥Þ®'¦ E´-¤bzUQìØRYd‘ËÁ„<"òØ<Öá%yŽèŒÖu—åÁÎç´˜”›÷Ä7ä¢<·—L¬hh_ÖÐŒ§¯ wC¶>1 Fqu€Ü°ù(*où#K°î`uo±:.&õ>Ð÷£:èÙVæ5AÂþ˜ˆIy9Ûš³ÔÖ+4u° ]X †»ë˜¢+9VÅÚö?2ñ²q#Çí8º|Ø Å†‡ˆÐ¦G+Û[kZª5?äL+@¦5BºS¥;úϰbžš95\…3,'²ì ‘©;rºTU#˜ÑÓ±“šÚ+eD¹îÈ«9£²*Q5—à)åó•ó*Ž«˜U~tytÍõÁf)½A»#(ÓÞiýRrŠ\·;çø,ͬŒªRr ‹tåd‡t焆FouÛêê ã€h³–×Ó™JûÁ›Yבëü~œr›¤ä°º:\co×{-‘Î;ç|íŠDŒ„Ö¤’m͇ÊìÜeÉDk*Õä¬ü!+ÏÒ‰Ü)ó/ªz}çw,§,/b&ÃbB{ù#ÐFjÍš¬n¥¹ b¿K%µ]¦Ä»WÆò²ÙåacäöH±å*r|çžz ßѰ§zk¥v±8(}箢»«Ûz¡otn§Ë)"ÜWg“ŸeÒx‰)°‹H¢åˆ÷s”€e–‰Mcž¹è;­Ê=¸\¤}åÝ\ä·¯£.’f`kÑøÁ|¡ÖÈŠ cÞÞq>/äÙ?ô?>4ƒ ±òÁº+¡Ù»å8»§Wõ\cvO·MäÂ5Úì\î-s¡8ogknG´ÇXü*d9[,F6Xò%5Ùàþíköv±–³ù6Rߣ†í¼vϼƒÖî}Íç; #íLݶ_å9 Fäž{YÖÞ%—´”¼½çNò6t=%çÂÓë*-F¹g%±VRŠr§F=·'Ö0ñWY‹Éw[É›Í7÷›ØNIJɨaÑÄ·b¿DˆX±b÷ž±Õ·ù§>õªã®Ý§³d·¨`ÝeÙ]X¤‹°á´a Ç>¾í²ì´¥ÕÞ{ã«¢§•¼ ¿P¢2§ý…$»ÐëÖÅ.Ä GQoÛ¡Ø·ßœ± Êûv˜[ï9#³íynÖ,ì|.ÁögjMU–:½­±b#,6á÷}ùbÖÞkûÅŸàìgà»ïÑ|—øÆ²\ ±bX7êë’m“£ï¯mIôÔé#¸(¨óÖÔd®Ù3kÿ®œ¨”:&ÿ®7Ê_¤Ÿ-ñüîég¿œ;^±Øõ’¶ª‡ª¿­´[vN/‰ûØxQÜë{]ç¼kuV¢àо:º2]G]esTïUÓq§çNÜЫ¦E%5Ñ•X2]Êl.ÁBJÓ=3­ÉÌl´&3³©5Sk;²FÔÚøCús9±0þÆÒÌrß÷)Zû~ÝŸ¦7ù~q¶d'wï™–o]xZnzÎÙò’Ö#éÿˆ\ËÜ\_õ”ª{çZOí༓5£ªo>ÖZÞunÖ§íŸuï›{ ±3×åNÚ<ó»ëi‹©ŸŸHÇÏþ.ÌaÿÁ9¼;ÌáÝ~öûœÅÚˆ}É÷GMt]zw]ußî’»šOTån˜5ÕðÛ]õœý6åœóilpèŠfó»&žKíêo¶;‹Ëjá½ú }MmŪ¶k°”Ð;CM3´«†ü²Ž›Ïм» t¶þs£²5ìyúÓ»/M?:z­¼Kÿ’Wse,ëAqäeîGcg± Ù©«¶Ï^o]K¶çl¾·‡º†¹=6ÙvgóÄõ‘¬ê6ðÝ þôý™?ñZg9¸=äѧ)äAž†õŸMï^u— , «W)NoÕËouíáöÕwwèÕ\=ÞÂöjoA ÛÎ4} byM—̲m-ÛXÉPìÖ=£æxïF×ôæ¼Ò|F>ú¼nâ[±í!Ü•î¾÷cƒD»,Ŧs°å"aç4þûØLqVØR«£²Ç^â°~|Û%ì}ßr‰,úŽŠn¶X´0'ƒ]„­ƒ‚ê÷Yç…<ŠîÀC×ôc -¡­çK²'OÖì-”õÔ\ÅYÌ,mÜïì)röÿ‚ï(y+–’Œ½òHgÃÄ ßTÌØ'{.6FaóÇÍ­±T9*gÖÚ“r*ã\Ž3y‹ë“5Ïk'^Æ{͓߭{1ŽÅ*ìÜÑ“²À*ê½n7ãÖ°K ^¹[1£2–®Fn†÷Óoe_tâ˜lOŒö;Rµ²3ÛøfWŽï¸E`=¡\rÝl]a/Ö÷^óÀÞûO{2ïQŠR •Ï3¸¸cž—õïî*{ókÏaÝhï>Hwíû³öص?ÚvÞ¸3´›ÃÎÁ5[ïgÂ";¸ï€É´û훣ë‹UÛn ¤ï¯÷µg]Æ­¦°nOnxÌùU÷ìßÝs%¦Ä­YÑD0îœ`m„7í¼iÏàÝèÀ£«Þ¥û›¹+Ùû[–C½jW$Ê£>$v« ¹ÒÙï»V‡øs™Akoô/2VG5i¬[21ͱ8k v™·9»ÌºáVíS1mYùƒ(‹; Wi³«Eœ=£Í¬MÀƒi³ü˜ñCDÎÛ¨€ËåmÄa}y¾½ã˜¼!cƒYÖ í;ì.{ËÍzûš°¾ì­Éñ®ÝÞaƒÙÛ´à·i%foË™wgÛ;ä’½udÞy+sØoöö$?Ýbwf¬Ç×YXkö¶HT‡l‘¤u$Þ¢&: =H¼…:rl²B;ÉÙ!‡·¯LŽ[-‡Oâ­™Ã[G&‡·t§•ZðMuõ•ÒÔFrjeYù ¾£z{(êkÁ[É#Ÿ·nG>oé”w÷fÞ¥6•%^ôö9$DZôuK ³è­±ˆï”ZSV²¦œÕ±Ãr‘½Ejrø™#‡·°§½5õ¯ägNý+ù™ï©f®ä­z¨Ž’Ÿ9mï’·­Gß{rÜ”±0]ò–¡Éá{ DTò–\„ŒÊÁ®s9X¹.{û~êYÙ[cQÏÊ~>Ô³²ßIp*üLP‡ŸKêØ™±B]öÖAÈá-¸’㮌-êJèG%ô£â÷´øHoÏ…~7“ÃÏ«8HoM†·[L¢²o F¼£Šß=äð3!QCèACèAƒŸ ß5xë¯ômð½×þhð{—˜ï11¿ˆùý§X£ßļ•k1O Ã;_71oY†ØÌó¸A\¦FÔ¿F´Ï}Ÿˆy«'¢æ7ú]Â;o›˜ßåļb~ž4M~æ›|>í›&?š¹¦[3v²›æè0G?¿ÿÄoêç÷ú×Ïc&røÝ£ùèç÷¢zßÏÛK$æ11¿‡ˆù©~÷óxE½ìçûDÌï'b~óØE³Þ歷íf_·zÙ\—±±Ýì±ï¼µoq¢š}xç-õ¨¯ÍÞÂŽ8QÍ~¶ÔûæõöNœ§æ°«š=†P/›=¦QŸšïÌÄúû]BÌãQaÁþ~†ˆù>I8»·YyÁZF‡•—NÕÔYyAÖs±°ÏY\û £ôóœ)}p,¶j:¨xtgb™ˆs.’ò3b!ÎjíscZëp½æ0¬0ºW†‚,²¢ú²9ÕØ¡'iH¾‹xnµ°lÞœŠ9GOL”5¯L´54u ‹FþsëåJZ4æÍ1-–ž­N5µ4&Û“jïÅK;z-S#£ GOœ½ÙÃMTËók:±ê¸Ñ©U­mE(+åÜ!¼‰µG r‡Ü³I~ispëkEœsD,èòMGB˜™—,'Ë…x'\K±›:ú"îóÍâè†DØêGzÝ´#¨z½ÍcS¸«ù{¬'H¼²£éŠï½v ’öþJ\è)ÀIÔ…½:ï—R ´@›žº-<­™¯ÀÜ0J<¾—õÜj6€vMb#Î¥IÛ™’ƒþ?–ãVëaÒÿî†ÞeóuÝ7²?Þ“³#Oºwºkk»woº÷gÁ©t&[z{êlmö{‰ÝF ì¦ÑpÎ’ÅðBv!öǧxÞÄë?UÐálÏkwݰ_AǤҘÿ w[¼mí´™ŽgAõ·Ã2§'¨ÖÎ﹜žãÐÒØ—O\‰uXyZ¥[ôÀ!Õ[´‘Ë.ž…èÖtH8mvµÁ¡Þº·ho+Ü¢ ÞÎoÑËc3ÉßaÀÏù]"òÖÿ…—Sˬ؊ð÷7¯´ݨm>aØôþL>o!Ÿ¿)‘Ïß½%ÏŸc1aØ$Ü ßaÕ‚¿Eè]Á߯…K ¡Ö‚¿+ cüM›wþ–"ÌXð7Þí²wXèþœ½Ó¢èïcêSÑßyç{ûËMKFý“ Ïôê#ü‹ñìe`ø³}ÀÜCâ “þK(­• Þœ Èœ "ÆÂ7÷lMÐÚZMnMm'ó¾‰y ßļ…obÞÂ71oᛘ·ðMÌ[ø&æ-|ó¾‰y ßļ…obÞÂ71oᛘ·ðMl^ˆÍ±E!¶ÄnGpwÚü¾S#w;²3`q<ÝBoDcæ%7;¼PÌZ󣌕ãfíR}÷´=Ö.~‡§.Z’DQ3¨Y¡1[•KÍwª¿9"V`û¥Õ¶¬£½.µ¢Yxy‘üNa¤&Pu¹GoEÒÕä®Þhl¯_Í!ø&îÛ/ý«MÖÅvãnw·è|÷„u°eÑžE½m ÓqY˜oŒYð¶Ü´KSÜAŸýí•w3mƱ0Ò1ãQW°úE¯½Õ/DÍ{­WÙ<Öz•Ú©]+™ÊÙ›“QÏùúí9ÝÞÝ=¯ÞœöÆrZ ?ÌDÝžï¼Í橞ƒw>X£žƒwÞ Ð#vlÜÎê9xçsp§«çàÏÁ]°žƒw>wÆzÞùÜ.ë9xçsp­çàÏ®çàÏÁý·žÃÚ'³9x^Ïaž¸`êzk©Ìæ@s¤žƒw>Ç#ÖltQê9¬ ±¾¬HõÕe3 }«zÞùèfÕsðÎç@«žƒw>_õ¼ó9àOÖsðÎç@Ÿ¬žƒw>Zgõ¼ó9ÐQ«çàÏV[=ï|táê9xçs 9WÏÁ;ŸͺzÞùèãÕsðÎç0VZºsðÎçˆÖs€êrÀG­çàÝ÷ljYÜÉm žÃÞOln’õ¼ó6µÀÍÝ6µšdíYHN{~! u¿"kB:„TdÓA™+²¡‹[EvQ„(›d¡FªMb,Im¬ V V&RÆ¢&ÂJÂ"Ð$1iu9š„%‹˜‹Ü$nS&aÀ3I“° % ÉhˆÆØk˜Ì8Fáó0™.ÒEï0„ï¸üã‹?‡ÉÒê›ÂÃ×áhF%\{Ç>I×ÿpîÆ ×ž© –Ô?•ÿ o¦rqHèáT,¨p-œBH¸0bÜ)> +% WÆi²¤·Ó¹ÞbPjÆñ|«3¨‹â .“êJi¹š‰y,ÍB‰³@­³˜‹s1 ãꜳ©€å‹#P¹Ä°Ô  jGÐ}=‚ž¹*AíEæîH®,E榫@EêŸÍ.Rÿl쬩6:Š\îæˆÍ*¡¹9\Ѱç5‡y+bµCš\½£I˜—(Ÿ‹_‘~ÌãTdÖŽbîŠôåh¶N‘9;´PdÎŽ¦¶"×À£éC‰9;Ë$%æl¾¬ éí| KÌí|DKÌÙ®%ævjo%ê]€a‰:ŰU‰~/D9±D]‹ÄxÕ¬,¢œäÓË2}f'•AÇQæ¸ã"Uf¿Jh™:Ç:G™ý°„^”™¯% 2=\3­ÌÌœ’.3Ï'ˆ!«zO ?±èù¨V¨ïDT1Ùe'1ê; ›&˜v'¡2Wa~ð*Y¡K™Ÿ u.Ea¯B_O¦Þ 9Of 6{2ýª0W'êP?–š*ÌÕ)¨ŸVØ §ˆ«p æ +ðNŪL…™¨€¾c}‰e»Œþ4Зe(¾bíè4€&Ng†Ø!§³èûéô©AûZ<ˆú°\Öd¹dȸúWÐÃú¿‚ž4ÐÿìÞöØô³=v—œgÏB1³‘ÂÏæ#èêl±ZU÷Ùì…F.lg³/0¶y6ªÔôåQÓžÂõ¡‘~<k,ôã)Øid>ž‚ºm#ýx*{¹‘¹x*ÂÒôã©ô§‘9x*{¹‘9xh¯‘¾<¹ldžÆ¾jd>ŸÆü7Ò«sP„mbߢib‡Ÿ.hb>Ïa75чsP¤kb>ŸNmMÌý3˜û&úÿ zÑÄžyWº&Þ>ƒ»ms°y¹W‚+šØk+•Wu¯dï6±ßV±t𨻫Ä~Uý«ÀMÌç*î¥Mìßs¹ô£÷çrêǾ;äÔY:½ÛžŽèÇ^:ÕÇ~ôj5û²ó¹ZÌTÍöj.yýèÓj¬¡ôc.VS{?ú´š¹êG/Ö0óýèÓ#ýèÓ4úÁÇYþêÓ.ÙýèÏZ¬ïô¬åŠß¾œÏŒrñ=Ÿ}ÒÌ:Ÿ}ØLΧ§ÍÌÇlfw\€>N3u¯w5³CÖaü¬™:×уfæp žÍÔ¹\ÐLîõÈQÿ×3«ÍìûõàèzÔû³'žÉ,ö§ÿÏdô§Þg²/ú³/¤ý©óB®­ý™³ fBlÃaîn¡íå»8䨭Å'°fÊŒLª?ÚÉE¹‰`Ô©)m s6н8ìZay®ê…3 ØÍ¢Ô{²3DÔŠA›_wQíL´¹*È„‘庱њ•*#ei«çbŠp£µ`Ã}‡K¼r9áNœãònßÒíËÓÕsÆÜŽíŒö‚1…h3ÑÑÓo±šóÜt^ Â<ÏGc]œ1-gúdLÓiƒ¸(S`~dºIz‘ŒØi.’Q'½¾Hæ ´-.–m(MÂ&IÊ«×›Ä ÐÖÞ$3Jª÷Yš mŸgÉâc¢z0üu è Ã_΂†µ™[?(~ Û ¿…IÅo7Š¿”-wç2$|áï\†5žgcæ4ÿl¶\žË…îµå.çÎ §ç9L¼žçPÜžçR3üžçbå%¡¾çñ®Ïó`lÁ÷Ù ¯ÿ|V¼Ÿçƒ¸\!ó{Ú+WŠ£$}%( .Ð6¡yõí*æ[qWqC,°Õ®¦®¹®f®@ïÛ™`Ìómgæ ôq»ìÇ©ÎíÌO~^Ã.+€"8»@Y/%a¦ï $ ‚½©,²!^È,ÒÃÂ×(Rÿ‹a<ƒÞ_ JÂdßK¤Q!ñúÉ)ç%ߊ·éK¾å¶ÛÔnLî}ÙÆdf»•L˜ñ±ÆØRÞŽOn1í¥ÚIš°—j›ª3/MÅ•¾t˰“àíÌx½”2±¾¥^«¥rí¼8óµÒiï»Ã,†x ·ÃLŠ·ÏÅõºÙ½öf¹à:ÕÌrÕŒLa–‹;bÍ,Wí;˜»]Í,WÍ|{›{vÍ,WÍFFàÔÌrÕ¬_a–«fÊ{@섚Y®Ìt’7ËU³×ƒY®š,q¯™åªõ ³\µÊ0ËUËŠ¡Ú 4Ýk/0ËU«|RëÖˆj/0Ë¥kJ‡Y®Z‡0ËÆ©™åªYìÂ,WÍòf¹j¶·¸~ÖÌaá¨6‹˜åªÙÂ,WÍ´f¹²˜lõqµF¸°ýé @qJò†¯°uèp±‡3#\¿Ög„Ëžâ‡á)oÒÉžb yãnìC¼x“NÞDûÄ›èõz]LŸ7Ñχ²F¸>Õg„ ¼ék!ëîûˆ)§ÌÖ'ûŒpÉ^n„ËDzF¸Öî­'3,åMYcS¾·üèmV·7íepuæñ3ãg€™ñ3P3Ì|=Vó§ûŒpmö²ø­ Ʋ֛±,~š-~ã\˜åòƹ@uÖ85b³ SeÖ¦Ê|/0UæûêM•ÑW Sù¾êâázª™flu[ ;^5d„)¯š-5î°£³ø—°¶/ý ÌqÕö*Vk6£°UU3³†àڞǺ,ëìVj³ýÌ,`é ÛYÖ¼×+mÓò»Î&Åš÷²–¨>ྰ~U3·†UªMõñ`ü)Y…sŒÒ~ê1båá‘Gö]çSö]¬cïlç>eßåD>etæ$>etf)Ÿ2:s2Ÿ2:s Ÿ2:s*ŸªBnްàtŸªb"ÞvTÅ$>UÅd>UÅa|ªŠ)|ªŠÃùTSùTÓøTÖP³Æ£²g¢Š¥|ªŠ“ùT§ð©*NåSUXc;*{Ö(ª8OU±œOU±‚OUq!~nTÅ>§¡·øˆÜ\æ*ºˆÀ5­u‡*^VÄ(ë){žo~@S øë¢šÚÚ$¬£§Žæo–\þ‹K—´%{]tdêvERzeMm'…œ›cË#¹%¥GŒ4Å»Å~¢.©Y±¹Y7Rò*’1¤•mÈû¨‚})w·ÑA”ÿ“¢–޶eÕcFø»úËøá´ñÚ+d}[-¯.Ÿ_Y]ßšjªÆC§_ªÍtHž“¦ÔÖ4W»:všbZ!ÿVR5ˆ"Uý´<ÑI Âð8õêO/+B:Í}N^¶Äo»Ÿ–o²f‰a¿ÛóÊn >ðïLȧ|}ì{"Êû `„±Ä„›‡(ûe½Á7àí¨ðêûE7àÄi“¦Nôkü ð^3P?ñBõ!g“Ðí‰ÊûÊêKÅUå G3^•7¹È ÚKÜ’c*75VwbNI«. —ïR¢…ó£ü»À"ÆÏªhF)íP²8ó$mN¹U½Ê'0úš@µ¥ã†t”/Ä¿(7ºÆNòOtṋdÂsˆ8GFÄ9š0"ÎÑ„qŽ&Œˆs4aDœ£ #jÀˆÀVaD`ëL>u ?‡%·qéKšX»·L ß–¿ŸefC$#Ýî7™ ÔúMfþAºâ{Àœ¯/)`ù >å€ìæm*L éøCÛRX¿Lñ»žìÕ3¥/=ˆû°s„ÛUI°ìR–7;e;.:шDÔ?'ßéb¾œ¦} ñ}-ù> Fâû`DM\̉˜> ŽBD]èÄ'žè¢+¾Ðg| :ù>@_ò3 À÷„S½ï‰á21Žú¾'ø ¦'"OµÈËç“=:ê{‚X’ï $R߈‘¾'D}O1ð=¤à{‚3mß(ˆ|о5ØùV¨P÷|ìb‰™ ÁRƒ`ö`çåþ¡Àm¾²¾è±Ô ú×73ÕÝÏ×`<Á»ðRC "Œ ‘»Ê}5@Gò5ò®IÔ ŠYkŒÐ¬Â’¯ÜêkÿRƒHi­r̹¯¨,¾È,¾È,Ô ¬;Ô µjæræk&æk†´OÍ"Žsb?} ÔŒËX_31_3ôj=uœ¨À} ÔŒp_31_3×"jö€Øýz_5#Kàk&ækF À™t:0¾ÿçš‘ò5#çkF¨Á×lDè\͈ÓQ³H¼ãåâ½o>_¾yÌ׌L5‹&|¨÷ÿµf”|Íþùšô5¡AW3—hjù`õÿ¿ÖŒËt_3¢‡¾fp§¯™~úš¥fQVè[`¶•ô5ƒ«|ÍP6©Ydê »} ÔŒó`_3΃}͈DR³èڇƞ û¨‘J_3⛾f=©Y„ð‰N°ï¿ÔÌÝÂ׌ð—¯1O_3"¾fÄ7©YDØINTí¿ÔŒÓøzŸ‰ùšÙþf i˜šE¸$É…ÿZ3NŒ«‡Æ¾fS³pÏd‘òû˜gœ(úš‰ùš¹eQ³H݇IH£ošq“ìk&ækÆÒ!5‹<>å?qHoÍ8Uö5ó5ㄘšER?\÷›¾j6¾‹ó˜¯‡ÆÔ,2üÔÿÜÏø>ö5ÃÅð5ãÙ× fõ53ÃÔ,Òý4'ðù_jæÎêkÆã²¯™Û•¯̾fÜ3S³îiÓÿs?Ãoð5ãØÙ׌Ÿg_3’~¾fîÔ,±!Êÿ\³¡ÍwÏ3|_3·o_3d}j–¬À Iµüך#lC À׌|€¯q_3ÒÔ,á‚™ÿy#EÐÀ׌ܯY5¥5«§iÍ3P³rÍòŽÆÿSÍÜV}Í@øš†ð5#ákFH‚šÕ«#þóƒ0…¯™Û‘¯Ñ_3b ¾fDM¨Y3v¤˜þ/5÷b$T|Í`9_3ò+Ô¬Ç:@5#öâkF Æ×ŒP 5kÇÌÖ ¿oš‘¥ñ5#ZãkFÒ†šµãælå üšÐñ5ÃGò5§úVfc®ã/õ)P3»×׌¯Ùxê·Bóé­Oš%ò5#YäkFЈš…MæI©oš‘Oò5S›¯~&5 åÏ÷P3BO¾fd |͈DQ³pÚÑÂÁ} ÔŒ$•¯*±¯9+j¾<Æ È÷)P³½s1îé¾f„·¨Yøv~lƵ/š‘ùò5#ækF"Œš…¯ˆkÔ·@Í’ùš0ó5sG£fáûcÅoë[ f#–¿ó5#²Fͺ/,t"Ò} ÔŒ¤[½fÄߨYw‘…ÿy;ì­©9_3Bt¾fdê¨Yw™E»ÿµfxRq5Œ@ž«ù|Íp½}Íð²©Y÷©yü·šcñ´ë5ÃÙö5rW3\&jÖ=óÄÿ¼Wµ{”ï;quW3œGjÖ=õ¤­üÇGûÌÓï-xä¾ÏF¾ÒÅŒ½«~85 Ç.ý¯rb‚œO;}W3ÜsjÖž\úÍŒí\¿jÿc‡Àe÷5ƒ®f¸ìÔ¬;øÉ× 9P3Üx_³1@àj†óNͺñŸòµ!j†Cïk6\Ípè©YƒSuëë[`?ÃÉ÷5[N¾­™›5‹?±l+úÔ Çß×l :¸š½Uñ7N¯ªošÑð5®fp5‹›‚Üx5£-àk6+\Íh P³¸1ËÅ[ï[ f4|ÍhøšÑ  fñ~Vlå¥?Rs¾±1´ |Íhtß&bgäE5‹wt†3–Ч@Ÿáøû>£‹àkFŇ:cÈ{H,ý_3ú ¾fîKÔ,×™º÷-P3z ¾fô|Íè1P³xdg‰ŸÒ·@Íè;øšÑwð5Ëd˜©Yü¶³‰†¾jœ±X7|_3\&j/ï)±å—¾úŒº¯m _3ÚÔ,^àS‡¸WÆÒºð5£eákFË‚šÅK|šöLß5ƒ1|Íh_øšÑ¾ fÍò9ÎGŸóœóñbéjøšÑÍ fñ2Ïѽ´o>£Ãákæ¦äkFgƒšÅ'}ºx+} ÔŒn‡¯Ý_3ºÔ,®Ï3Ä_ë[ ft>|Íè|øšÙUÔ,>íJq„û¨]_3º ¾ft?¨YüàUÒdè[ ftD|ÍèˆøšÑ ¡fñ“ÏÕl÷-P3œ%_3º#¾fxÖÔ,~ôyÎpÈ®9–‰ÇÏè‘øšÑ©ãg4F¨Y³¼Úi5õ)Ðç\³$–N‰¯¾*5‹o¾Z÷ò¾jF¿Äלk–Ä^³D˜5â;õ-Ps¸Wæš%±×,Ñi­¸‘} Ôœk–ÄÚ‰¾ftE¨Y<äóÅùîS æÀEŽƒfIì5KÄ%¸@} ô9×,‰ƒfIì5K¤Ÿ°NX¡ošsÍ’X:%¾f´D¨Yú ë‡ÀÏ̯9׉½~ˆt'ž9ô~ÎyÞqЉ½~ˆt/ž9ôÀ} ]_³1ŸäjFW„š¥»qáZ±t:|ÍÆ\“«-j–îÇñÂû¨m_³1åjV­¦f½¹hÈ>^4Kâ Y{Íõdãú!±´L|ÍÆØ•«^5kÆ.޵6û¨_37|_3óDÍšñMº÷-P3Ú(¾fî¾f´L¨Y;æYCàg´Q|ÍÆX—«Ù˜SÍÚ™Ïg®ošáûšÑFñ5£qBÍÚÙ—ˆÝ·@ÍÜy}Íh¦øšÑL¡fa†ÍÒMè[ f4X|Íh©øšÑL¡fa -š³¾jûšÑRñ5£™BÍÂ`—9À—¥ÁâkÎuRb¯“"|yÙÐ÷­p—EÅ×Ìý€š…oŸí̃õ)P3z(¾æ\³$öš%Â×—;óh} Ô ‡Û׌–‰¯-jÖ½àrq¾û¨- _3Ú(¾føSÔ¬{ÅsþS㢷f°±¯Í_37gjÖ½ä¹Ú-} ÔŒ‹¯-_3¼\jÖýçyþåþ_͹6K´Yb¯Í¢ûÓVÝ…û¨Í_3:-¾ftZ¨Yxàùâõ-P3º/õ[0Z.Ô¬{ÞNK¸Oš¹ú>£ ãkF†šu—¸B|þ¾jFk¦ÞgôcVQ³n¥ÛvÚʯì3 æzNÍÙC§f©ÅŒ¥C‡BFM,×›‰ƒÞLôfâ 7ƒe/ÓSÝ‚¯ú¾SÌíÓàçêGŸÆ÷}ßSøú¾§èÓøž¢Oã{ ÇÔ÷ÔvqÛt®Ázж =Õ­{ûˇLè)ÜßS4g|OáÜùž¢ã{Ê-Ä÷ßS§ébzj Ÿ¹ž¢ïBOÅ x3d×'BOÑ‘ñ=E÷Å÷„ï)ï|OÑ€ñ=E³Å÷Í¿{Ðlñ»z*îà ·j ÷9ÐS´\|OÑrñ=E{Å÷”w¾§è°øž‚É}OsÝ”8è¦`’ÉôT¸aÇÕÞù=EOÅ÷=ßSôT|Oyç{ŠŠï)ØÉ÷-ßS´K|OÑ.¡§â¼øÂÿÂ+ÿ=…?à{Ц‰ï)¼<ßStG|OÑñ=EÄ÷Ô˜TÊc¾§è„ÐSq}^е‡¼!Ö×@OÑ ñ=E3Ä÷.“ë©‘Dp=5n¡\O=t=M¤ýázjb®§‰:GOÅezÙŒŒ1(ýB¬ž&*®§‰ôA\Oéyøž¢çá{Šž‡ï)¾§ÆkAó=åöFOÅýú)g¢°/„}j0¿ë©‰¹žš˜ë©‰¹žöÞi€øž£®§è~ÐSqÛd‘¾†žbÜ+S¸ï~NÑñsšëz$A×# ºIÐõH¤ëAOÅÝ{åÿ±¡ñ?zŠÞ‡ï)|'ßSv†ï)ú¾§èsøžæzIÐÓH¤§AOÅu¼N|•>vO"ý ßSô7|OÑßð=å.à{Š^†ï©1ˆézо=¯óUÚC}"ô4‘ކŸSt4º÷i" ßS4 |OÑÀð=Í5+’ Y‘H³‚žŠ·úêÿÊSúïw¹D<ßS´,üœÂ¿õ=E“âQŒPÕÀÍo‰xHôT¼Üþ«6O_»çßpOæF"Í z*¾òk·é%ôªcÿë»ZO5øË6ôÔ¼ƒë!󾡧æ¼™~xNÑú §âc¿~›‡¾ z ¯¡ÞS8õžÂ÷x¬§h–ÐSñÍßàÌ„>Þ£'Í{ò¹¾pÏ?Çbð :zvÉÏA¦ŒM žÅc=E{…žŠ‡ñ&gî³/„}šˆëë11ˆuïÓD| {Ðmñû4×YI‚ÎJ"z*ý]âkõ‰ÐÓÿ„éµøžó=Íu\LÌ÷T×ú©²õ%}…·d›Mcûë•ù€Ùž¼y=Y_ˆ=Yߪé?Õ×÷Aÿú&¨ÏXCî“§¾¾«~½óæøÉXØÕ.¨ÆZ±ý÷·OÆþ-aŸ1£:ècù|Tßåóñoû8`Ç'cÿ©¾¾~ÿ¦ÀÝó ŽžˆõŽt±^<ôŸVÆwëë› Ö˱é3 f”6»c{9J½{(ä8Ã[rìü=Éz‚ûUÝÓOÄþ[ö¿o-OÆþÓ"úOû6T=ö÷^ËÏOüzï ½xô_ç¸ï€ß¿í‰¾'ðV﵎> b}Ìbõ÷¿wgo}*ÌG ¿¾ðMß±¾æ»ï› Aî÷]\ÕwÃNí­µ÷ëûc?ùë½3õ€MŸ¨ï»·>棄~ä{½Š›Aï¯o&ü×7Çü…ßÿïSÁÿëÝÿ¿cÿ¯ÏƒûJ±ÿŸ?ÿ—é ~§i=J'þðÛ,¦-xø-“ÿŽÃ¯³˜ü~µÅä?äðõ“/Ã?j1ù/9ü"‹ÉÿÉáçXLþS_k1ù_9üt‹ÉËá“7•Ã-&/‡/¶˜¼^z¶ÈÞÉ+Çá“-&o‡[L¨‡d1yg8ÿã&& ‡›§x¼î52¥¿>åv‹I{Ê­“>ñ”ë-&¶Ê”k,&­Ë)WZL^˜¦\j1yqšr±ÅäjÊ:‹ÉÏÇ”³,&/TSÖXL^¬¦tYL^°¦´XLz§Sê,&/\S¼&©¼xMAÒĤQ9Åk’JÓrŠ×ï”ç¯I*]Ø)èBš˜ôs§˜ÿ¼¨M1õxa;ÌïiöC‹IÛø°›,&&Ða_ËÌßaôžXB?£÷&&ÿ^‡Ñ{SÏ£÷&&¿]‡Ñ{“ß®Ã轉©Ç‡Ñ{“ƒÃ轉É×aÖ{´zóÚ¥ÒŒ> íR“Æôa~H“ú0ôXMLšª‡yíRiûfÚ¥ ³u˜×Ä”/®ÃÌÓz‚/®ÉôÞÄ4‹“齉ɻÖdzobš×ÉÖû¯Y“¯²Þh†&³ÿüLL¾$Än²|ò£5ùl‹iL>Ãbò5¹Ûbòb3¹ÝbÚ“—YL~¯&Ó{“߫ɦۚ°c&Ó{“?«ÉÖ{tX'³ÿÌ;ù/šì{OÌy~OØU“ÍÛ{‚褻,&ÓIì~Ón›Äî71éÔNb÷›˜tx'±ûML»p’õÞÄ´ûMLšÊ“Øý&&ÍèIì~“&ö$v¿‰i§Nb÷›˜4Í'±ûMLší“Øý&¦<‰ÝobÒÜŸd»?ÁSÀ¤™ÓΞÄî71ÍÜ$ß{y^˜Äî71íøIæ}>Á³Ä$ó8ŸàÉb’×’&˜Èî71i\Od÷›˜pÃDv¿‰ÉóÇDv¿‰ÉsÈD¿ÿ„3&úýGÌï?b~ÿóû˜ßÄüþ#æ÷1í¿4æun‰y[ù;™èµ°å/e¢×„%‡×„%æ5a‰ùýGÌï~éÕÊ01ù8Ôv;ìPÛ&–ïþCÙiìöË÷ß¡~ÿ “Êþ3õI½ãPÿÄŽ:Ôã?]õ5ü‡>ò¡†ÿÐ>ÔðúÖ‡²ˆá óPv€‰Ék¡†ÿðÄy¨á?Äðž¨1ü‡'ëCØ&&ßC‡ØHðpsˆßÄüþ#æ÷1¿ÿˆùýGÌï?b~ÿóû˜ßÄüþ#æ÷1¿ÿˆùýGÌï?b~ÿsø]u°á?søÏÄòýwp؇ýwp؇ýw°í?søÏÄþ31‡ÿLÌá?óøOþöøOwŽƒ=þ“'¡ƒ ûâ ü`¿ÿä»é`¿ÿt_9Øï?yŒ:Øï?ùp:Øï?ÝTöûOõä÷Ÿæã Ã@ôã ÿ”ï ÃæÇò‚tÇò¢tǺßäñŸTÉòøO=8ÈðŸ©Ãá?søÏÄþ3±üösá?søÏÄ\ïÑî>Èï?a£ƒüþî9Èï?a»ƒüþï÷Ÿðâx¿ÿ„/Çûý'l:Þï?áÚñaŒ·ýgbnÿ™˜Û&æ÷Ÿî[ãmÿ™w~ÿiFÇûý'Zãmÿ™~ÿéN6Þï?ùÊ4ÁÇûý'YãýþÓo½Ç›Âxn&¦;Êxn&¦{Ɇÿðƒq ¿È“Ãþþ!Yúû‡nxúÝ/ÏWÚþKØ=ÚþK¸ùÈþ35‰íz ¿ÿÉëÈ~È»Õþþ¡v`ØÚþ31¿ÿtS<0èÖèïòcu iñ'à’¹ý˜˜î‘úû‡üSèïÂ1úû‡î—øû‡Þà{/ïSøû‡¼Oà÷ŸnŸøû‡°Ñ~ÿÉ«Ô~ÿéVz€ßÂRøý§+ì¾÷º­àïÂ^øû‡üàïÂgøû‡¼;àïÂpøû‡<àïÂyøû‡¼6àï‚øû‡¼1àïòÆt€¿È»Á8ûçïòE3ÎßÿxçöŸyçw€¼/óøOtœÇòB0Îã?yUç÷Ÿ¼*óøO> Æùý',;Îï?yKçñŸ<ŒóûO^Æùý'/Hã<þ&ç÷Ÿ¼óûOÞÆùÛ'ýsûÏôÏïyhó÷?bþþGÌï?b~ÿó½'æ÷1¿ÿˆùû‡°{›¿ÿó÷?b~ÿó÷?ù3hóø˜ßÄ<þ#æ÷Ÿ<µùý'Gm~ÿÉóA›ßº%´ùý'ŸEm¾÷ò?4Öï?ùë÷ŸüõûO7‰±~ÿÉÿÐX¿ÿäh¬ßò?4Öï?ùë÷Ÿncýþ“/¡±~ÿÉ—ÐX¿ÿäKh¬ßò%4Öï?ÝHÆúý'_Bcýþ“/¡±~ÿé¦2Öï?yë÷Ÿ<õûO7˜±~ÿóû˜ßŠñ÷?bþþGÌßÿˆùûŸ<&Œñ÷?ùã÷Ÿ|ñûOw 1~ÿÉwÐûÑw ;ÀÄtÃ01ÝVǰLL÷Ú1~hWñûOw¦1~ÿÉпÿähŒ¿ýk&Æøû·f} ; }ç÷ïü&Þßï?b~ÿóû˜ßÄüþ#æ÷1¿ÿˆùýGÌï?b~ÿé~¹¿ßÂèûûýGß{b~ÿóû˜ßºÃíï÷Ÿ|íï÷Ÿ|íï÷Ÿîvûûý'_DûûÞ˯Ðh¿ÿôn´ß¼sû¬9ÚöŸ‰å÷Ñáö?Úï?Ý Gûý'ßC£ýþ“סÑ~ÿé¾8Úï?yí÷1¿ÿˆùýGÌï?b~ÿóû˜ßÄüþ“¢Ñ~ÿóû˜ßŠíç÷1¿ÿˆùýGÌï?b~ÿ Wíç÷1¿ÿˆùýGÌã?bÿóø˜ÇÄ<þ“ÿ¢ýüþ#æ÷1¿ÿˆyüGÌã?bþþGÌßÿˆyþ‡¼ ÷¿Q~ÿé6<Êï?y:å÷Ÿ<òûO·äQ~ÿÉÓÑ(¿ÿtçå÷ŸnÏ£Âýo”ßò]4Êï?ݪGùý'ßE£üþÓ={”ßò]4Êï?y-å÷Ÿîߣ‚‘Q~ÿÉÑ(¿ÿt/å÷Ÿü²ý™v¤í¿Ê#mÿPHiû¯@’‘aÿ´ýWà®3Òö_P1Òö_»þHÛÔkFÚþ+ ´1Òö_ÀHÛ>FÚþ+àMh¤í¿·¨‘¶ÿ xýiû¯€¿‘¶ÿ x¬iû¯a¤í¿¾{FÚþ+Àiû¯€ïž‘¶ÿ øîiû¯€ïž¶ÿ øîaû¯Àml„í¿Ò7#lÿà°ýÇLŒ°ýWÀÏÛüðŒ°ýW€«4Âö_?<#lÿðÃ3Âö_›ÜÛX¤#lÿ`厰ýW€ƒ5Âö_¥™¶ÿ øÑáoÿâ-°P€¿5Âö_ûßÛ<ãŒ÷ïáÿ7<ðÿ†þßðÀÿøÃÿoxàÿ ü¿áÿ7<ðÿ†þßðÀÿøÃÿox¸ü¿áÿ7<ðÿ†þßðÀÿøÃÿoXàÿ ü¿aÿ7,ðÿ†þß°ÀÿøÃÿoXàÿ ü¿aÿ7,ðÿ†þß°ÀÿøÃÿoXàÿ ü¿aÿ7,ðÿ†þßÐÀÿøCÿohà@ ü¿¡ÿ74ðÿ†þßÐÀÿøCÿohàÿ ü¿¡ÿ74ðÿ†þßÐÀÿøC Ôלÿ7Ôö_oD­†ÿ x#j ü¿ÖÀÿk ü¿ÖÀÿk 7€ÖÀÿh5üW`¶Z ÿðXÔø­ÿ×ø­ÿ×jø¯€'£ÖÀÿk5üWPrþ_«Ç@òPÔê{O,çÿµþßÀÿøCÿoHàÿ ñøOÊFC<þ#–óÿ†þßÀÿøCÿoHàÿ ü¿!ÿ7$ðÿ†þßÀÿøCÿoHàÿ ü¿!ÿ78ðÿþßàÀÿøƒmÿØ©ƒ=þ#æñ1ÿˆyüGÌã?bÿóø˜ÇÄ<þ#æñŸü/ öøO;r°Ý?Lwÿ01ÿˆyüG,çÿ ü¿Aÿ7(ðŸ…Ý?(p_þÓ °ÿþß ÀÿøƒÿoPàÿ ü¿Aÿ7(ðÿþß ÀÿøƒÿoPàÿ ü¿Aÿ×ø-ÿ×ø-ÿ×ø-ÿ×ø-ÿ×ø-ÿ×ø-ÿ×ø-ÿ×ø-ÿ×ø-ÿ×ø-ÿ×øÿo`àÿ ü¿ÿ7Ðv@?Rýþ#æ÷1¿ÿˆùýGÌï?b~ÿóû˜ßÄüþ#æ÷1¿ÿˆùýGÌï?b~ÿóûX~ÿîÿo@ØÂþö߀°ÿ„ý7 ðÿ„û߀Àÿøÿi@àÿ ü¿ÿ7 ðÿþ߀Àÿøÿo@àÿ ü¿þÿ×?ðÿúþ_ÿpÿîøýÿ¯àÿõü¿þÿ×?ðÿúþ_ÿÀÿëøýÃí§àÿõü¿þÿ×?ðÿúþ_ÿÀÿëøÍÿ×øÍÿ×øÍa4þ_sàÿ5þ_sàÿ5þ_sàÿ5þ_sàÿ5þ_sàÿ5þ_sàÿ5þ_sàÿ5þ_³çÿé†Ú/ðÿúþ_¿Àÿëøýÿ¯_àÿõ ü¿~Æÿà `¿Àÿëøýÿ¯_Øýÿ¯_àÿõ ü¿~ÿ×/ðÿúþ_¿Àÿëg÷8²_àÿ5ùû·Þ5ùû·pgSàÿ5þ_Sàÿ5þ_Sàÿ5þ_Sàÿ5þ_Sàÿ5þ_Sàÿ5þ_Sàÿ5þ_Sàÿ5þ_Sàÿ5þ_Sàÿ5þ_£¿}ŠÓøþþÇ»œÿ×èñŸðzcàÿ5þ_càÿ5zü§U£ÇâQ5þ_càÿ5zü'ß^ÿ×øÿ×èñŸî ÿÉÛW£¿}Ò¿œÿ×è9òüÕàïÄþ31·ÿLÌí?ó½'æöŸ‰¹ýgb9ÿ¯!ðÿÿ¯!ðÿÿ¯!ðÿÿ¯!ðÿÿ¯!ðÿÿ¯!ðÿÿ¯!ðÿ*~ÿ 3Uÿ¯ø•Àÿ«þ_%ðÿ*žÿ!¿a•Àÿ«xþ‡¼‡Uÿ¯ø•Àÿ«þ_%ðÿ*ÿWñüÝž+žÿ¡ÛsÅß>u{®xþ‡nÏÏÿ æùÄ<ÿC±²çóübžÿA,çÿ•ýýO÷ìràÿ•ýýC·íràÿ•ýíG·Þràÿ•=ÿO÷×ràÿ•m¸‹—ÿ¯ìﺑ—ÿ¯ìoÿš¹ràÿ•=ÿw9ÿ¯ì÷Ÿn%¿ÿˆùýGÌï?b~ÿóû˜ßÄüþ#æïßÄüý›˜ÛÜ/K¶ÿ¸_–lÿ™¾÷Äüý›˜Û&–óÿJÿW ü¿Ràÿ•<þÇ¢ä{/@Ñï?½+züÇ»œÿW ü§b¸Ãí¿øÅÀÿ+úý'¡¢ç?‰óQôü'ñ ŠžÿDÌóŸˆyþ1Ï"æ÷1¿ÿˆùýGÌï?qŠ~ÿóû˜ßŠüþ#æ÷1¿ÿˆyþ1¿ÿć(øû1¿ÿˆùû1ÿˆyüGÌßÿˆùû1ÿ´# þþGÌï?bþþGÌã?bÿó÷?bþþG,çÿ%áþ—øý'¾Nø‰ßâm$ÿ—øý§½žþ_øI¸ÿ%~ÿ‰ç‘þ_â÷Ÿ8Iàÿ%~ÿ‰7œþ_øIàÿ%žû%ŽHø‰ßÒ‹Jÿ/öûO˜#ü¿8ðÿâ°ÿbÏÿ$ü¿Øã?qJâÀÿ‹ýþ¾‰ÿ/ü¿8ðÿb¿ÿÄA‰ÿ/öûO|”8ðÿb¿ÿÄM‰ÿ/ü¿8ðÿb¿ÿÄåŠÿ/òû¯þ9ÿ/òûßþ9ÿ/ ü¿(ðÿ"¿ÿðöŸóÿ"¿ÿðöŸóÿ"¿ÿðåŸóÿ¢ÀÿóžáÿyO€y÷ÏùÞ»avÁ»¡çÿyO€ùûÏùÞ`AÞüÛðøTèvxu䇊z¼³ôíÊ©·yø?˜ðS”óüd{í²êºdmª.91ÑÒš¬oèLÔ%ëk:ÛG&Š;.-“ö.7žÿ§“ûìtnŸzùüòDªE±¶ íËí+R‰Tk¢)Õš´²Öʈ·«ƒ¹k¢Ž³TÇy£+jÚ‡:ñü¿ïÏÜXçú¦¦ê&UyTâàŽ¨§üD)òt÷Å?g›òm–}á7÷\¿6+vÖþ=-“¸ÌÍåZ2fø6®×W±!·0·qYÙÆoÛa;ïæ–’}tÖ¢®§ätNàúý ®+ž:blÕN‰ñ5Ï N~ÉüN¾£×¿8ö®és?e-8|æÈ“_6¯p¿§F;¯:ðo‹N½;¶ð9¹·žò//ì|ý)Š•?Vzj4««öo »s‘c¢Ü…‹ Ná»y›hþ©ÃNèÞ7V•“ûÕ…‹—Ôµ8§“· ÝÊ=ÿÒá>Þ¾˜Åít'õü}Ù©Ù§Ü+ª+;5ëÎÒîh,±#ˆÝHl4±)Äæ—vgO'v0±sf‚1;šØ.b“‰ÝK ͖S£vòµ;Ÿ7m3ñʬØßòî®Òˆ}w×òîÞ l7M=m /8"Ê®ˆçž)|ÍÅÇŒ=î‰ñšædëžwÒ‹hçIl¨“z>Fôqjœ«üÓ \–Òz4g<äí›sïŒs7ÞN­Iœ¿të—ÌnÜœo•廓|ÅGòMµ|×»\'F%Ìz<˜‡Y$φÇì„Zžoßdy…<É`ž÷ZžÑ!Oa0ëÃí!Oq0Ï:Ëó©§4˜g¾å¹©ÿÝ{wm Löe;J,:XA ìí&ËÙ¦œ/­Î.œ°¤ž«£Â%¿ÎŠŽé¹ë‡–kÑqÿœ?ú¸ùñ)ÇÝTpÊqw¬Ûí wG;³'›O¹ã˜N;£³´è”;?Óy&{q;ÿ¯Ü=ÇÅ&<%Z¯šØ‘_óµ —D9W‘£aáîùcmcÙmëÈŹF{}EÞð‰]Ž(Z˵uÛì×_)8eD^TÀû–ªÏÒÆ·F9¼m w©ôԜΒ=9fD®§óÖpѽv€u]ÓÇ®Þ×ÇèõŠhýÓW ­Ì@‘žÌŒû]©¢ó©óœªzP*)¢gQ7µ®XGt¸ÔÛUF%]—O,ìÎË»¾k}¼ãÝL^Ëœ·Fí¼£>íþäkq}åÛ«ë[¾®¾z›,²Ú/·µú™·½‰v¶÷gÇ3þå»»™éy‹éúÞsTG³âg~ï´oˆ7Œ÷q7»‹„ÇLßJ»fwDÕ笿oÍß»ë³.·›áø£Çôôìn³×îæ¿Ìü3#Ôp‡Ÿ‘ûΉk˜ÈŒ”'ûÑ^¿f{Î;6ç¼9=ëä®lÊí{FîÒ9÷Ïú­éYnç©4Œú¶QúÇê»=̼j25Ž÷3ogÛÎý­ñlCÖÞ×Z<ç³Wê ³WÖ¼ý¸^·+Š#&ò~ Ƽ½k¯y…Yš»j³ »Ï‹†íýEb¥ÑE«&ät:Ü–{«ÇÁg%òG‘sÉ‚núÔÉø.û¬â1ŠpjCWrt\‹pÍÖäiì½5ïW—r}‰Z6SËdŸ ¬¡2®Šö»Ûõc-ýpy•ï6—'‹ßd½Xæzq3½Ð §«QW_·Ó“·[üúž÷=Yf=™Ù—sõ`ox—õbD_>÷î¬ GnäÎÐX¶:»Qw޳ôj5¢Åës.œÓ›ðûœ=tþÑpÃC&kìýÔ5Ü;Ì"ÒýA¤×U›´hž‰iwùÜ“-÷ÒoiÀ íª%Å «IcŠí<ÅÕDçÅ5Åw†=Ó–©c¾«ãÖ8_¾câ«è=Øàí¢Gs»ý7Zîk­˜ÿ¯ñîVSØ“»{àòÑ?·ÿãÞ=þD¿£ëè·°pt‘õÙöØâZËu‹½¡÷kºŽlþ£5}{½£~ÍýLËIþªî½ø7b{ù7?¸{mËŠÎ.Ù?ZÛ5,çÂ˸ëÂ,˜Kgc¢¬ÛyJëwKô¼"w&\ä΄+«K–tV×¶tT×Ψ\P[9jܒΊæ¶öÖŽÚö†TsuíA·ë†nnš£-fî©6é®<Þbøþ`1|BOŽcx²Š-·ô tǵ1•'®ƒqr\€ŸZ¨²ÜBoâmؘ´Ä¿±1q7+%™|•;3±†Ó­&é4în18”×Xiô;ÃÞénÚïìLî~ëìN¬ÜÑNšî×P#Щ.K#œÓ&øEþ»‰ñì¬ëÇ­ÚÔ¡Ûªf%‹‰{‘ÆÄEHcºÍ§1ݪӘ¸ iL·ü4¦Ûv×!/oÞY=_Sw‚´gÚ:¨9Q9¬à´/ö^,>gt ÷âe¬üë¦v–·¶¦Z¹g#oÒ·Œ:’“öåÜm^q?£§’÷TåÝØLÑš÷^àhïOÑû³ÊæÍ©˜sôÄDysmª£¹=Ùš¬KÔ4':šOlN­hî+wB[ÃÒæšÆÆ†æ¥‰†ÆÆäÒšÆÞ÷‡Êа»]‹gÁ‡¬ì®¹]_wsÏ]g~ºçN»_ß1 Æ×vîÕí°³Ù¡fo–Þ~wz·fïtsùø”wi\Lït÷ÆÑLvê|íÔíÔ»z«{ÕúlÚRdãTÝ©»j¾ýŽb&Û2;ÊïL3s~×ñn‘½cÖ–…w+,†‚U¶ðrܱ¢KeÚÜífÉÏ®®þÑáÌîÉQÖ®ŸÚ9/Ù–j\ž|h5¤s‰ï~…+K”Ÿ¹ôóØNe`i3s¥ ³æª:O¶]íÑs™§ÐŠGÆÊcæªÅbôµ5³ã5cv6Ä3Þ=´ÓÏýŒÊS;)—xÈÂZy®|ÇÛ<—ÉyA>¯‹–Så½9FèÌiø5½9í¬†œ¥Kfú[ìÍi¹1æfÛä`WÔsðÎç`ÏÔsðÎç`GÕsðÎç;ÕsðÎ瀯RÏÁ;ŸƒY¨çàÏ­çàÏF­çàËž¬ç0ï|ðm=ï|po=ï|<¦×sðÎç3×sðÎç0þâ»sðÎ÷Ø^ï=ï\ƒÉ»s˜wÚ¦öi½Þ)Ç@å`'±Cí{M×òãg³æ+èDòÞåÎúWŠWËM} ßb*Fuå`mâ›\e½5™è’(ë•z÷9¾¥ Ý·6\|ßbüÅQÖTëbòí™Ççð-(•·øUL„\~ǯ‚]_÷z_Ç7ùïÁ(ôö~2Œo©öÊÙ~ütr俆z¥6¿–¹¦">¦œœ(ÄgÀJ“„ø ¤ÚŸÊ¡T@â¿‚%-eŠø¯)?Ä…Z« â×Â\“R@üZØ{bôǯE@,ðøuL†”Uã×ÁJÃ7~*RFŒ_†ÕÓx-÷&) ÆkQñ[.^K¤ð¯… )5ªøõ°%¥4¿žþ‰y¿žþ‰1¿Õ!1ã7À /~,ImØø ªC}z%l÷}ºuÀ}ºNL×Ï0BR¨(0_×Ã0.Ü†ØØÝúñ*Ô~4*ñ›ý"}x5ü°âÈ(ëÍÌIq,ßÚ`Eê õ;Ì“â–Fü1†UçkQ¦(2¯ã¶U¤ÿ¯ƒ_\ÈžT‹ôÿõ ²"ý=sT¼‹–²m‰9|ªe¥½ùk°T…@Ÿ¶N‰¾¾¶i‰¾¾‰þ•ÚùK³ÔÅ·]JÌû›Áœ%öÅOÓ×}üiT2Jôñ§Q\(Qß[`¢–sYb–éç[á—•™£·¢¼P¦Î·±ÊÌËÛag–©ïíì2sr3s_¦ï`Êó ûýN¾¥\¾šo1eËÌÑ;Ùkeê~' Ö u¾ ¥í ý|JIæöPS…zoAÁ´Â>ù8êýöY…z–}Va~~–ù®¬‹²>Èþª°GÞM}öÈ­@Á sús0p+·GYU6PçÏ£„"¢AüQص ÔyóÐ@}ïqÚÀžúETYد¿È¼ lÆg?6Ð×_âÈÒÀܼU‰úù^”2¨ë}ì‘FöÏû˜£Fú÷>Ô[t ‹ÿ†{e#sÿ>öBãô(ë2”†t!‹/CE¤‘ùy?ªÌç`¨6Rï`Ý6²>€J#uÞƒ®hñå0¸ÙÛ·Cxl¤Ï·ƒ™Ÿ¢ìÑÈü~fyã­˜yל %ÇW ¢Ð´3ßÚM…QÖ§@WMñú‡öÏÌ£®rñzTZšèÃ( 4±§?Âm¢Î_f_5~Å¡&æé—QÑn¢ße_袆½ÓÄ>º“½ÙDÿïDõ»‰}q'ªÎý¨ÿNêîÇü jwýØ¿‚‚.€ñgQnèǼ} µÊ~ÌÃǸõc>Æ•°ó÷qTAûÑÿ3Wº(ÆŸWêÇ]¨„ô£wAÈ 5¾êµrjW`‹FËDbÿoæé.ªi-%.*u›ê8’7á'¸Ðrðº¢?Ê«âܹ} ½‚˜PQéå8l'\à¢ÄÕÕ<ouwvE¥´ãêÕÖ+ µ£¨¯BsìÞ yå!o-*-r¦ñQm¾¨ÆEu/ °“W(ÄåÞª#!V"(€ò¼Â0ù[鄹¨ØÐvò>iÛ»¨p@˜Õkqï]r§¯ýõ«ts),Æïô%=âŽÂH/¤eÜñBJ/„XóÔý÷î¯C\JÊ*,š4æX,nEÑ´8Ÿé×"ÛyBLŠHqíìòóBzÒ/„ÿ:^H“¯ã…µ;^u¼GÇ !ôŽRêx!½Žº;/oÙ ]:^H‰¤ã…tY:^Hµ½ã…XÇ ©u¼~LÇ áËŽÒžéx!eúŽBÙ/„ë:^è2Óñ‚[Sí…4x:^çu¼Òíx¡ÛFÇ ¡ÖŽRêx!„ÙñBرㅮ /¤HÔñBzE/¤fÔñBןŽRBêx!Ÿ/¤ ÐñBW¶Žà–Ú ]¬:^H½©ã…´:^€j/t1èx!÷ /t•èx!|ßñB¬ªŽb”t¼Ð¨ã…Ü9t¼Ð%©ã…nz/¸}Ö^è>×ñBša/¤(ÖñBzc/t—èx¡ËBÇ )Ÿu¼.ZÇ ”0j/tyéx›¡ö‚{oí,‰Ú 8µ°%j/à)Ô^ÀZ©½À¥Ví,—Ú øµ°j/à2Ô^€µk/àQÕ^€Ýk/Àöµ`ÿÚ nµÜj/¸-Ô^p{¨½à6Q{Áí¢ö‚ÛFí·Ú n#µÜUj/¸»Ô^p—©½àÂS{!õÄŽÜ‹j/¸ÓÔ^poª½àªU{¡ËZÇ Ý;^èšÙñB<£ŽÒãìxQ¡öB쯎ºßu¼àfU{¡[vÇ i‹v¼Ð±ã….²/`Õ^ÀBª½€T{«©öBjÍ/‘©½à²X{¬ö¶­ìÜ©Ú Øµðšj/`ôÔ^Àß©½€­S{?¥ö¶Ní?µ¨Õ^ 3T{"QíÚEµ¨Õ^ “T{A´öB¬ŽŽRoêx!&AÇ )Eu¼¦£˜¿¯Á^¥Ìm•º¤.Pv1“ÒU„Ê\þBlsŸÊ^ˆGÀ-ҽࢵܮͺ¿´•œ_Ø‚v1.¼l4*!ƾS.ó\ݵ Ú•äkpuž®KWEqMþ¥.¶µ­%ÊÑ.÷5²éÉak<-]#—_ÂOjô=±µHŸ¬ Í9ÂÍÁ¥vÍ£–Ë2—½‚6²ïËåšwg¾Rw±kÔSä 7wºÂ®­uLšÍ£”߸Lç/݈ô?{!nD„R¿}‘¼ivMmCs{ªmYbæô‰Ó“m'¶§Z3RuÉÖ‰M5µKRµËÚ&†¯)Ë¢œo•Ž‹´Ýüq㢜JÇrn,wkš’åÜT:nB”sGéøbˆ>óÇŠr~Y:~4’]RK“Ë“+º’21§Ÿª+Žò¿Ø?½éˆìÌò»úñÛ„?ÓŸpÖožÕŸpæo¾¥?áŒß&ÜÖŸpúožØŸpÚoÞߟpꎄÉç6Læ´TëhèSO¾3Ÿqâžœh¼øžœMi¼÷=9ÔøE÷ä|lVãýïÉùظÆß»'çcÿÍ=9ÚÊ×ÒC;ct¼N }ñ'ÖéÏ÷'||~µ?áãë´ÜŸðñíxRÂÇ·ãû>¾»?áãÛqü†A³ÛqäÀ“'¶£ß¨yÎÇ·£ß¨yÎnÇ<çã›ÎoÇ<çã›ÎoÇ<çã›ÎoÇ<çcXxwÿ¦;¶¦ÃÌ›7¾yl£§lLùØüE—nLùØøE·oLù6‰¾¹1åcíµ1åcó-ؘò±q~¶1åcÓZ¾ôžui¶P³éÙc3[ظhŸÛÂÆUûää6.Û'‡·àl5ëcó[ظ¤ŸáÂÆ5ýä6.ê'¹Òë‹n.›>½º|EÅŠ(ÿo§vÎuoNh®OU·G¹óÊÚÛ[£ì=Ë;“µíÉJ‚ūʚSíË’­e­­5+£‚÷¸ôÇ“ÿ±z¿æ2Qéc™Z{;³¦¢.*xA\¥båþÕ¸Ê'2ݪ<~ª•\ ÿP‡~Ç2-~(Ó+z«\SN//µÐñuh˜eZüP¦ý¬Ê“çW}ô’ò%QÁ* ¿ä·¹O´L‹Êô‚Þ*ÍÄ ¶Ðw&æ}–é;Sê­ÒLÌë-ô‰Y`™¾31O U.^r43Á…Ž'öXîv—‰¬eº³·ÊgÍĬŒ«Tì±ÜÏŒ«|"Ó¢Þ*×ÍÄìW©Øã(ÀVùL¥Ë<:8¾5ÕÑ‚@ñÊâúQÅHV¨‚åó«kk[ØÖöÛcËG•lÉÖ,lûmÅ…“ìŒJJÛÔ¶°å·¥•>±©?Ó·ýQsÔ¢Çú“ÄýQsÔ¢Çúó Ö5G-z¬?·oêÏô(ïÚß+BÉ(ˆª]OÃÉ/ým±ÜTì Ü’¸"N~é#ûЦ"fF¹‡,˜S9í˜Y•Ìñ¦º…¿íEñŸ-äÇ[÷áMUÏŠráÊXòxÕoµt߯úŽMU$¾Æñ©ûȦ"ŽÄ·š+â»S÷GƒEL/A^E,xbþñ¦*ÄâØeU|ogõÛTŹQîó§W5¿bt¼ö[Ń,YüßIw=é–UŒŽ'ý´‡Ò}ÃÒ™Ñ8í¡!mÞÔÓó¢Ü÷2§TiJ×ünLûo*Cï¦Ðóçž_ý"*-wùù|ðVå[6}teEuåK¶<”ï]¾å>ßãý°©¯k¢Ü¹šá¶µøJ¥ûaW‹Ùšá6µx§Òý¨§7õtm”{ñ‚isgW<ŽG‹OÓ}ë– DuU}>Î|Ñ‚1·ºð1_ów×þÜÁšgGy/e¹<ÿVêâºãæ=¼5Y¾åŒ¯ò=^÷¼Mu‹(öÌùÇÎcm|ob ?sÙ~pø‚²98ø9z§Ëöƒ9:jS?§G¹¯˜÷džÿÖ¥ûaÕGoªZ¨ýÏæM«|âÄ2ƒd?¬ø˜MKlæ+Ëæ0Yk^º°î!@5S ³€ÎÔpÊcE,ØT„¼çL¯œ;ﱎÝT‘U-[ôD 7ÕÐŽcGb8/W²ïo±ä«$ûÁKº”ì³½hS/gãîð䳞è囕ì½ÜH²öòR%ûA/7lêå¹QžG¥tèIL¶Á`)ím“\JŸžhjé{L‚'ûzѦ¾žåO2Ô¾èX·¸¾Sxû'ù"ò-:ÖŽ&O,Æ›¥)~ÍüSŸX&“”ìËd É~¸L†)Ù–ÉÅ›z¹K'WÌy¢—[•ì½<—d?ìåqJöƒ^nÚÔ˵QöØé¸ÊoV²ôò·HöÃ^6+Ùzù¬M½<±Ì“Ë=ÑË_R²ôr1É~ØËYJöƒ^>m°—âÏ—Ž©Œ¯áÇ.t‹úñ3ö™|Ë^úÐ-´t¦²§EyÿdeœƒúÇË^šÉ÷dÙOßT¶¸ +¬ K/û73ùž,û›Êžå.­,›vÌüù §þ¾êÂÓéTôãHh妢¥ ðŒÊi³+®z´æ$×g{²äU›J–\Õqß[%ÉzŸíÉ’ÏÝTòQîËã"¾Jþѧ{²æó6Õ|d”7Vóy†çÇ‹.ìÎ÷dÕ«7UÝåý}¼‹–<¾©Ÿ“É÷dÙk6•=;Êóeü`S7eò=Yöµ›ÊÖ!å"+ã›úy™|O–ý²MeŸå­‰Wï¢xƾ3Ún³+ß“U¿|SÕâ0?Ë`Æiu»ôºM…¬‰òŸkSðÃBvn*Dl÷¡ÜÛÍÀ‡¹xKµìáL¥×o*öü¨`*|olŸ7XÁ‘ÅQî¿VΟ¹`Æ,¦V=?á·4Èâ3\º%¥+ïÒyˆñx¾Âg\>»¾SÝ•›z*VÛ A•ÅÇ>2’ŸútOÎѶM5‹Óö²¸ˆïo¿ä5>Ý“5_µ©f!¸·ÅEüÁ-÷鞬ùÖM5¯ Žw‡él» qÛM$•Ç÷à+,Ó²‡öàÏmêŠöàÛ\WN{iåC}M+X d³‘^¦¾³ÏU:›úNº§‘.½N}'Ý •Îß§¾³ ›z:]vÃ;Üw8ÁÅM5h—¾¢’ãèén­‰Šÿøÿ”¥Ô|§q¥MEk™^]Y¾¨êE7Zºï]ÞTôQÞ‡=~4¤¥S]¾Mé¸Áº×Àjuâtá¯'wxtqœìÉ ~À¦z§Ã¢¦„ïc™S7Éž¬÷ÀMõŠòt»J° ú;õþIœìÉz¥öÓUïLlÄ.ƒZóƒz“=YïA›êÕéîÙ•Ð_~0Àñ¯-Û“¼©b©º]$´ã"WQøºÐÕi£Õä3ç=„Ú^èÔY/=î¡î²©;ºñÝP3u„ÃÇ'¢ø†oÙC *ØTv; ÐeGΘÿ8èÿ¦O÷ä º©æÙQîsã"~ú_âÓ=Yói›j>íùeJÎx¬Íñk-Û“Ÿ¾©bÉi¼È1Ÿ¬`ù¦ 4â/ЖýÑlþžO÷dÍ+6Õ,–󂸈Ìæ;|º'k>cSÍNúõJˆ%?œÍ –íÉŠÏÜT±dP_33Ÿ,¡ÎË\‹êÇ +ËŽ;ú±žE¿‰“=YoĹ¼{oÁãxw}œìÉzë„ϵàÝO¨„àÝÅq²'ë­“2ׂw?­ùAŽ“=YïâMõêB³Ÿå’/ºßñ鞬ù¸M5 ó6»"~€yÿʲ=Yññ›*Ö­ó‹Ærü¾fÈí1ÛŒü¤´ÂÑ&Åðƒ|K6uéÈ(÷[îâ¦*PžøÎ`¼Ö¥S¶'—'l*Yb":A‰ŠùÌ!“íÉQÝ“5Ÿ¿©fÑîg“,šn´ºïÔÌš2鞬ù‚M5ëæº²r~Ùt#~g×°lOV¼nSÅr:Sœ]6ÿw»=CU?yJk)¯'N©ë7U.‰Œ7 ²ýà"ô…8Ù“~æ¦z%cqºJøÁNÞ'{²ÞWnª÷\LøRÂvòçãdOÖ+ƒe]õž‡.1%ü`'‹2G²'ë½~S½Zx¿-l÷ƒùý­8Ù“õ¾jS½R[x›JøÁü.“=Yï«7Õ+E„sUÂæ÷ÏãdOÔ[¾ic½Ç]Œ†ôOëæ ct—åúNªò=úpÔ+Íž{íêùd½°\OÔû¥{ë="ÊBpÃàÜ'ëå1ñ¯w†æI;Ü°Šž¬W˜Øäz¢Þ?½·^ÍÓvÕ}²ÞÓ,×õ~ùÞz5O †ãŸ¬÷óÿ÷zgjžÄC1¬©'ëÝd¹ž¨÷Ïï­WG†W»™M艂Ë?¼· MÉËíúðd×>h¹ž¨÷¯î­WÚ/p“ö½®%in1 ÊÇ*_RÁUðTx™Ò˜ýNŠ:S=™¨Øûn¢ÛÅÁy2QÓ|Ðø“‰ÞV6}ÚñX/‡:Áæï$ŠvíŸ- V?ÅMÖw¥Ë n²žH4ÑMÖ‰îu“õD¢óÜd=‘ègÝd}'QiŒîîé\íæ;âØå…n`žHôn`žHt¢˜'íróD¢~n`¾“¨ô‹G{)ÏNa`¦#£]Üs~™ÖØc'´ÍŸ9ë‘4ÛæÏü]5¯›7íwiVÍ›ö»¢Ÿ1ÏmâÇÒÜ9oî#ÕDÏꟑgãéÍÌÈcë¨8ÕÍÈãi~ÎÍÈãi¤rødšånFOs©›‘ÇÓ\äfäñÅ›ª¸¯ð]nFW=ÑÍÈãiÎr3òxšçºy<ÍnFOó«nFOóT7#ïÚôÊcfd†$ëÿ¢±°•e³ZBåg?–¨’¬€8ðÝ’N},QñésÊ~d®3·êá4•§V•ÏWžïÀßèiÉ+˜³ÚHåªÇUnŒ扒^þX¢âz70§iwóxƒÎˆæ ø›ÞõÜÀÈÚÏun`ÓµÇÕEÞóx¦¨ÀÌw‹Zóx¦b¶šÇÓ|Æ Íãuއæ L];`‰©sÄôrÝ{kÄ Š9¤©¼²¯¼Y+^¶`þ̇ç¾<÷ù³+G¯.oùm'6’è‰=òÅie³fý® R¾2=±À†¹Iy<ÍnRïOÊ´“²vRáç13F?2)%7)/Õÿ' *ÕÆ“òøÖú=7)§y½›”Çûê™I‘$Ë Ç•#ëòøˆ•>Gž'QÿŸÍªz$M霉Ÿ@0ůÍÿ}9mó_NùÔ¾ö‹MüµŠ9X<8þ·õ ›5ZåwúðÕùæ©Ìª _'?$ŒùÔYGÿ>ÏæùÖsËüßד¤•ÑÍœ´—/×i~ÄÔ*VŒBMÙ§jhŸHÔjÕüß%*ý`*ÓýDA×ôõmvTp7ܳ§Í<ºdêo7wjGÁ¤–׈JŸÃÑN¢‚Ïlx1ϵ³¢¬Î9s+ÛοŸ_5{Ñ´ùó~›gǬé¿Ï3lÆ¢yó«¸8=ºMïš±h~Ùqå¿…_ÙÐÔ#¢üVÎ+ŸQ^5mæo+¼¡7uTðyhé ÀM‹*~[óS,“<<šé4ËtìoǬòf_Ó㙞æk:û·™ ¾£gl™>”éO,Ó‚‡2-XÛ|ùŽU‘¯Ä™¾c»$Ê“‹³eåñ+цtªÇ7ñ7¦²¶Ž_^¾ü·‰þ`êü¿Ot[ ?Žÿm¢è<ºôÔGúætªÇzó¬£ñwpÙìßûòìY3Mô&=ÞÐò¤@ÿDEÉ$C;Onˆd·t²ï,‰ÊÝÝNsòøâùsÎíß]Qå1ú{¼ÿñYóæÏþ-ð8¡Ø¥ }Œ{nîBçI&ûá8AMz4Ùé>ÙÙ'«ÃZøî|”¾ä@ïããQ8sZ傊鿿Ѐh3=Zô7 穼d~yÕœYåŸ1Ë{“黉þÀ•ôD¥¯¨¢' Z¦‚`>VP ‰žÈSž«‚´³/èy$z"Oe¦ :öwÃñI2}7Ñ,•ôÔGzT!ÑyÊŸt=z¢ WªEOôMtê#}DOä)þøùÓ¦U?ÿ¡éÐç3§),{þ#Y’”ÏžýÐ’|Î4ïËè±¢/›7}öCwžÂÇæM¯š?í·Yþrἇk)ÿ@­YQ7ï!˜†tìÊyuU%z£-z¤¢J´ð‘DËãÒ=”è„8ч­šœÑ\—¬ohNÖÅgªÇvƳNåBü¸Jê~—äãÓf=Kž5·lº˜vüE³æƒÇ/{øä}Ê,ÈtO$ŠWÍGyþÑ÷O»>šcÐ|ôpÍñ3Óf=”ãÞùÜ{Íñ±i³Êqß´Ùå˜1sVÕoÇ÷7+æTýÖ]Xe—¹ ªª§/J>tÊ+_gZðФV1§šz?8–ÊI´`ÖCyŠ¢²|.=Ci<Äc¹ÆñXaÉ#“±1ÎôɘOÆwèŸq“ñá’l’¿ìaüðí2´JÍñв²‡.”íóÊ« †=Ú“ÀŒS[Ë[I¢ùhšdiÌr'm9¿¦õ¡ÎÄOI'zœOZ˜?«üa¢I4§|NUù<Êù³¯aß%e¶¹DOhi¼cÖôGïôsg•ÿ>Qå,dcò‘QJ¾“Éôø,UþÁuôôE÷~ÆÊy3îýy.ÑwQœ˜?­ F›PÖÙñ.~K¹ŽhýPY÷Íš+eÄï–õ åú^YgC‚RYOYþ0ʌީ\ÇVÿ0ÎŒîˆÁBš£Ü.ÕX3ú¶ì œU½hùñMÀŸ*Õ±Õ‹–ÿPUøÓû~U÷)Õw«ªDZ§Ö=LP*ËÁʹÏTå n©-X4÷¡¥† MÔ©¡WÌ*›9ã¡Í»üá$¥B¸ÇUÏxˆ˜sœÈO$*|bÆÂ²ŠßÂÑÊ«Œ<üøÑ%? ‘¥G;=kÚÂé¿E`ñ„˜tú¢‡g»xº$ß¡£y]ŽãÁǦlQÇñÇ€³½+/^1ÿ! ôÔǹO•Ž'ˆO¯75€ïÔ´5Îôš¢\ZÒ‹?;•êX¥z¼S79EÞ§,˜™øU2|Ï/JÓ¾¾#”8æÐw ÒGËæUJ"àq«†ÑñSç.@IÐûÜßÿ[ì¦ÓÞe-ŸùH¢ÒunÙþà™îºþD¥Sÿ;y^ìˆüç‰'”•=Ä?ù€S°z·–_¢LOÀÖò¿*ÑŒ–ò/\"Ù«|,N<¾Ë|³Kôý_VVVöÛÑ8×iv=9ªLOŽÆh%zr4ú¹DOŒÆRפ'Fãw\¢'FcÀô‡·ÆO;•²'G£E™ž?W¢'GãJ—è‰ÑhwMzb4^ì=1¯˜þðÖ˜ìtÙžÓ”éÉÑø–=9÷¸DOŒFÉ5é‰Ñø”KôÑ()0¤kécÆm zeU«_é8Ùýkæs­›ò¨UíòEÒ¤‰¢Ü§Q¤0Ï™QÞϨÕMó“%‡“V&_žúoY §TÍå_ðçÍö¡÷]ö/¸Høãg¿þÇ/vÑN3¢è©Íî…Ì*»NÏ"›çI,Q¿–(Úù#îÉà ‰0~_ËÕü±(zÚ7û‹²Vÿk‰ú_O†‘ýE¥nòk¹îEù'Cú‹Âv~-YË ðíðóîɰ{ ëÊ7x*ÿßw¬Óž~-Ñí”?óžD¸Å¯&‚‡à!Ø˜ÈØ—¯%º5Š GÜ“òÕD­‡óÿ§û¥¶ëk‰nÂ.Áè{í.}è¾üõ=‰v—>ôlæ¨ec"ã_¾šhØ3øÿ’{aA¾–èÚ(zvî=‰p_M4êÆ(ÚësîIj¡f¾šn¿«¢ho&ª7Ý´ éF³#öí¶t;hÿµQ´oã¶t36¤Ãb;g[:»GÒtc+£(÷sOºYҵќqOß–N (¤ÇüŽûá¶tòðSM÷×QtÀÕ[ÓÉz5Ý_Â}ß-ÛÒÍÞî@6ãøs¶¥;wCºñƒ_³-]Ç:询èUÛÒa¹"Owðê(:4µ-]ÇF:ä¥Q4âÅÛÒu@‹ ‹£è°²méd‹-¤;tZ~ðÖtòÔ]M7ñÐ(zήÛÒuì»IÏäÿßnK×±ï&ý<ŠF~e[ºŽ}7ù¢è¹ïß–®cßöÁ(*Ú6Õ²r]M7…©><®=é:öÝáK£¨xÛÜÉ u5ÝTænÚaÛÒuì»iÏÁ"öCs×±ï¦3w3ò¶¥ëØw3 øÿõmé:öÝŒ_DÑX toºŽ}7H5ëÊmé:öÝ,Ð×ÛV»LWÓÁj?ò¬mé:öÝ‘àÏöέéd]¸š®ý¤(šp¶tûn6{zNé¶tûng€¹nK×±ïæ²§çålK×±ïæ±æ}w[ºŽ}7ï{Qtäg·¥ëØwG}vïØ–®cßý¾(:ŠÚ›®cßóº(*øô¦ëØwóÛ¢¨lÁ¶tûnÁB<°Øö¤ëØwÇNŠ¢i»mK×±ïîÎÿAüÔÖÒ ô,úûmé:öÝ¢/ãÃï¶mé:öÝ⿎¢mM§«g5ÝqãƒÊžt+æxÎ*K¶(t©¬¦[Ââ„m ¹v­¦;ʼnÛ0’ ·VÓF:)¾íI×1'q;Z?©§“íÕjº¥œ?—^·-]Ç®^Ê=òäk·¥ë¤“©ì”¯nK×1H§|-Šæ^³-]Ç JeËâã`=|–VÓ-ã u“Ý›®c2Nã uúK¶¥ë˜ŒÓÙËgnK×1ËŸ¯ÖÞ+÷¤ë˜Œ\-ÏØe[ºŽÉ8L}ƶ]-ÇžµtÚÕg~}[ºsæ7¢háÇ·¥ë@1gýM-zó¶t(æì· ³#àÓ›®Å<^ÇS·a$9Ѭ¦{*éiqû÷¤ë@1O£—ç<{[ºŽ]}Wøs¦Þt»úœ;¢èE\{zÒɨe5ÝÓÑg|h[ºŽ}÷ x+œ½é:öÝÊ×GÑâ¦mé:öÝ*N}çÎÝ–®cß{l-yÞ¶tûNœ–¨ªBoºŽ}·zþ{[ºŽ}·º'ŠênØ–®cß­ùv%?¹-]Ǿ[û©(ªû¶tûîüwFÑÒø®¿']Ǿ»`e-c‰õ¦ëØwëŽÇOçƒûN«éÖÓËgnÛw2€XM÷LöÝ3·á ¹7¬¥Ój¼pÛ!TV «é.d5nàºÙ›®cm`5^´í#£„Õt±7n»WËç`5ÝFÎ6³ÄzÓu,°‹çãºÌösOºŽ¶‰æ¥Ô2aتšé¥Ë£è¯àntgê¨þeP*Fˆ™:ªÿ©=Q‹´ÙôûRªæÙ á rýÄs¬Lª&z%·Êë^¹)QGå×qê}›zwåÛäU\Ô^Ÿtª¹n`û½6ž¹ZM ëµÜ­^?}°™l¹×3poxÖ¦D»ô Lå›â®w$ê¸7AwÛµnS¢» žäO3]‰:é-ÙQVw¼’š{¹,Ž'»í½QÖUñAª_à슓ô¯ ^ýø¯ÂM]we}!¾aWŒâ,öÚ÷Èήߢ_½>Êú»øš¨é \dñ²þ™œì +ôTÎ]8/žƒúO"î`¾Å¦ˆ8w§? qÿïo1l­Å/‹‹}ÿ!¾¯¼9!¡»QA?qÑ66,mNµ&£r{ ñ†·÷éí%É–T+ÌóÅÍÃõfi‘·º¬Mj®i;‘w&'¬2ï¾¥wçÿß:‹·ä+ è­N“bFtèÏeJmò7[Œœ £E‹Ñ3_¯x\¦Þ„©wËôò© ŽŽžú{Ë•x«kÈÄ‹+æÌpsäÞ6ZÞoê­ÜBªAtoý¼Õ vâÅj>aóïzØÏz(BØÄ˜²ÕÕCòûR§ï!ýð=¤oQyjÕd³Ð·­a €§Ì]i¿8žXS…^hN;^p÷¤Âì…æÒÌaöBÓ‰CBžóÝ ÍRGîI´-{¡¹éÈ¡iéx¡É*KÞ4»Ń-©¶e‰™Ó'NO¶ØžjIÌH5Ö%['6ÕÔ.IÕ.k›¾¦,‹r¾U §±p})TÅ (D97"”6×4%‚Y¸©*`áŽRxl…;K¡§~Y 묰/b’Ë“Á,´rQfß>=ŠvéY„›Á·Ñ\Wš *Æn×ô©°oýÞ©ïÛsþ}ßšzúTØ·éÛ®}[ìºõ¿ïÛ´‡} ì[;6÷…®ßÚ½1ŠìÚâwºÿþã £¯áåŠ(¿¸«`JKÉ…ÑéÝ”0oqô“’Úžž®h÷’µÄÛë£5ÝL‰òl\Ë÷¶ÏðF…L Ò§FÈÅUÑä–®õ9zïjº¤«`|‹«çލ§äs»PÏTW«åÖmµÌüp-×UpˆÕG%Ÿ»­¿–ÊØmµ4¾¯–JÁݪcE”=>“?š¼-yʆ^TNêÊß-îÅ6zqMÏ.]Q¢·ïuµl·Z´™²Z†^ÖÕ×rJ·Ã<šâ¶˜ReXôˆ ¾æy‹ã‰ ?§³­[FŒž@›µô¦®aÙ~ª¬çÖµYѰ³öï¹ä´ï@/ý0³­{¹úsLé©Ñðîý¢5UûÜ øjá ±<šDÿmŽòé£ NêË¡¾Ú¥ç¥sì—ÿ‹¾j’ÍQØ/cT~q_->›£xh:G!¿•÷Í>ÇÚ¬Ùifvæó†ŠFpN3oVEÝîM€2`Þlsõ5ð@³Â¼Ùåº7ºôL@¢Â¼¹#Êroîà´»*§S3¹u]N'¥$šõö‹^ÌhŸ]²TÙ5,çÂO0Kù¼.èÚ»æõ kÕym)çà¥g´©7®°,ðË-ÆùF‹‰ò­/oÞY³®cq´³ÇÐOÇkE’rGJ#ãàö3FI¤èrª›#vÔ5n÷éûšfÎï>ý'Ñ»)Pô§—î½±–²D8,¿÷‘úãíõ?î;¦»~N´OhúËßÓ^t;ñŽnNÜÛrsf‰|¨0uM]ÖþݹêÇÛ¯èʉJKWG•ì–þÚ%í¥ýNÒ÷"ò.³¼“}NÅ ÄGoÎÙç)ý`-ßÚ-KØ-óµ[ª{Åöú7kú°É{Ýl;‚[Ú¼ÛdûMœŽ}afÂï sÆvó¢íé6'ŒÝð!æeÍÌËTâ;º¹¬Xœ÷~ðAÛâÅÙ‘ÃXÅèknOèLµ37oÄŽyz¯Û} Ì¥Îy2Z(nž˜!?O(çÐV]ºú5ÚþcÜÌžÛ1¸çZÝì?ªlٽ焤L[©ó}¾ÎU<}¨ÎÇ}u×)ެÙ\ ýpÝÍ=wùéž;û°æÀšÊTÅš‡5Slgß è»ýÛ̺0•ÁúÞaÃìU T ‹ã°´ÏŠnp¹0›É—cµíôc;ý¨î+nµK³õ˜ç ¼ç­«Í´Ù;8ûŸ€s³Ï|øY¡~íÙ>ó¬Á]ºg'ÎïÞºç3Ó ÌÀß“s¼7¯;ú 7ˆû»j%!WkˆÙy{dGîŒ-zÌ4Gφ]Ùn±qü_f1¨1½r3%úHÌþIÀ•†Ý»tך{Óì¯wï›Æ*7„¹™_Rãn f&.è‰ZsJÖþU‹óµ§j{Š£ªÚü)ì¦×,XͬíÉvó§Üó|î]Yìª8*}$¿Þ%š¿ùÜCV(§j¸þøù_çó=:ÿ¡#ú¨oæ„þÌQ­®wKCîѹW÷ŒVÞ¥;DùÛãüÓûz·Üípuó½òÄîω)ú½y“îý+2]º[$Öµ‡ó¥LñÒqÈ{ Ç;g™'¬äö˜¨óžvº¡,¹ýƒ¤¦ ņþ‹ß?~¯ƒ}„utßx÷¸›V Kï~îL+õ–H,ìhf©:G\µKÍðqsD{oN“­çÒ¦Ù½soÔÙõœ>‹³Ñ¤\œ¨zs™·š€4Ïe*-«h9oÏiç©+§^{sZ Е““|oN‹ÅºrÂ7éÍ Ž®çh‹8òª´ExE¶h¥h2Z4ÅÚ*-â&ªÒAÂ@êÎ ‘Æuû´†oé’ ’@&dÓÄÙ,­86ƒ¥× õÈÁèhEp2KB7Â!ºŠƒ5D šð!LA ìRÍ·6ËòÆLîòÆÜHZ‰ÅLD+ú10±•-3­¯â[ýj…+Ãù*þ‡ú5ôñö “C|’èYß‹'cè÷Cª6Gñ¿ÉE Y¼E…”£)üO\¬ÌV±Î5Ì ø êß0ae¦þjÓ ÎPŸ†÷a½ê›ƒÑ'°~ÏÏÜëgFÚ6_³6»¬Ò¦Jt5­&F^¶ Œ-bìArc:xà†¸A¾W×WÓu1 ìÌŸÔÅ–³µ˜í–Ö¡™¶Æ{Ó52lÄŸÔè{bkAW$3½?ÄM‰ýM°9‘ùò}™¨éqèoš:îbG¨36Æ–23øõ¡˜”ã~GÇÊ·ýž ôü¢¥Éöêi3fÕœ´²7—0ñ߸§Ë6=}{º`ÓÓ/º§Ë7=ý¶{úÔÁ§ÅÏ•Ža’<Ìꉲg>L½‰²_ñ0g%Êm+JvÖ&[\8OuFÂ6íÅÜÒ1Ht'ï~˜®åV:¦Åõ™Ó%¢ìw<Ìuˆ²{˜åÎ.3ûº“?–ÇËŠZ“5uÕÉúÆš¥}ö~/‹òRÔÒѶ ÅòÚ,èÂi“Ösþeœ³f³áŒ6§>Þdž˜|ñ¹¥Ò))¿éÑ»°Ž)SZR-ýòŒi)¿Î=¬MÄ2F¢¸¤hEkC{²|ÆÀißhZV¹ù’ˆCå‘r|r~í²šæ¥ÉÙ¢ÿªtìÀÃ[~wq-¾¯tìØ±Z׳í>ÜŒ}×QcŸ%n"û0™ÖÇ€0¾ÕÓÝZˆWºxQ-/æÉNTõ=Äë¿0.‚f«ˆï²Oƒ²‡H ú/z•~¦JdïÌ–+Aç[‚n¬å›ã4¼*á;#ìJÐ-À– Ã]ÂÁ¶ º­« m W‚N¦„Fª/ÛJøÎBr%èRaJèÇ)±_,ð¥.誦.<¶÷\ :ÎØ$êØ_ÕJøÎzu%è¿)¡™Z`‡˜.œì&òñ-îJйז À€¸ +è,óC>—)F·SÌ‚CÿÉS1€¢Ãá÷ Š+EB¦”¡ìÑaHgٵǶÑÚûÁºi’1 :sHÒ¡­c}³hARüÞnG¦ÿøýX¢m¨ɘ¾$,&þóvɘmÛ$,^}Ó6 ‹?ºm( Ñy­„Å»¡HZ¢Pò¹U_¯û\tP×+‹KJ>SI·æ–tv-.)é:ЍŽâ+ºsÎ)IFg8ªy)gfšz©xûgs*E#EJ€Ü¼5”ÓUðÅVåOY›—3Krѯ©êÎûñlèȆz\Ê1H­ÝíýÀÝ¡.ßÕ„ˆ•¿ê¥Š¶GOûúb®îÈ¢~5,æ^<±±ºaqJWnN§èeR<—DûÆ}éº+q};£Áhb̘§»B꤉Ñ'O£oê/Jt†ÆgoèáÉ_‡e2~K½D†r$^zC±ø±¾ž%ÎöµëÈF[í}Êú»Äú «³¿FnÞõ×Ò§l¡nhoLjFô{úo©Ïn¿ì4*`Ã=Ôg#±ÑýÎÈjt¿32ÝïŒÄF÷»äÙß]餞¤Jßí¾õö—§YB›i1(tK-¦N¤ô_È"[-F½×ºð-6Ð…;çñ[ŠÉ úy„ä¤yLDëY2Ê<ŽÜvGîÓ`¡iï›GfÐÓDñÑKõ³y,Õºˆ§ÊpÄÞœvÖ»r2ÊOÒCN(½9-†éÊ AðIê¢ËùCê"ùº©‹ ‘ 4÷+‰T¦SY":T´t©HÍUd¯Ê+ãKEå•^eBw U6Ê[FØn¢ÐmÔÛÎuš¢v(Û¤A5jK4èÚ¢ l¿Ñ…¤Û-0Üðë¸ö†_§koJ×9,«ê2¦/) Í®=ÑÞ©½QÎT{“¶„joÂVíMˆ S{“Ž¡¢95IùUÙ›¤®®M"jNš¤8«ÓXÓ?ǽiúg×_(jÙ\ìë s%/2*6Êu"ôÍ<*„Ê¥ úI}Y}ê§K…Èpýäÿ@¤Â~š%nŽÍ4¯ÍÚ"¢ 6kãŠF9`¯¸ODÃr5 PA8"RÓQªTÓ@]KTÓ@mwÕ4P´,Õ4P´JÕ4PD;ÕÔR×ÔrœjêsGJïQIÊü*e9TVcÄÿØœ\g“lsG‹„æeùgÞa¢œ¬¸Ž•s+gEY7ûèqØu›?f4-{êï.É)öü’šQÖ«­Š3gGYÙ;ж—ŽÃâzrÔcíAZÚ>2Ûo¸§§>-~2Û̸V24ã0›·f°¤œÊy[Æ 9è‘‘+}iÇdîË`ßÔ15*b+ wäµ ^?܉õ¤¢iðEØë¶ðH»]ž|ÒôjúA  Ã0éîóÝ^•†ÒŒ9 –8oÊ̬àÝÞ=Vã  *—uÐ/,¡¾½+ÂUP Ì„! šÉùI¼•£å =9ºŒ>¶‡øß¿3nÛÎL¨ü3!j™00w3!ºýWqÍç]=3ÁÎXž¹’·ƒÒ§U.ðWJ.?lNÝ/J_Œ™‹ l_5³R¢?óÖ!óVw)´ïüWFÃ×æÌ¬ìÊËé,¡”­OɹprwBâ“÷w­:¼píi3«ÈÙöÿ½96깤ŸCíˆSe=1B\#{ãOˆÔ|6zFQuum{ßöt×E.CAXkry›suÂüÜo‚ˆï-o~š02ÃüåLC9©Íì »3BÌ2cK¤`p|ÅŒ7 ü¸™ôWL{{¶>M ñ>‰%n3™Ö]ièÎÍ í‰ƒ*ê&&ˆL©­¹<1ªhìØÄèââÑÏ5êy£G'Š'L3~âè’D[Û²5­ím‰òΖÄA¶ŸbI}°—Eäº3;¢í`PƒÝ1ä¨DR òš5tçÞköuçöÜî/Ú싹\µŒÀ[˜S}øØ\¤¯ûT^'³ú̵«òJø?¯d¿¨uí~y¥ü_TòμεïÌ›Éÿ¥Ä—ñ~¹.ãûlò<—7ç[Å÷¾×ñ½\›ø¿…]Pà{+ÿ·QsÂûkø¿ƒøµüßÉÿëùÿoäÿ.ÞÞÄÿ›‰ÝÂÿ[‰ÝÆ÷{ù;ÿï ~'ÿï"ö)þßMì3|–ÿŸãÿ=üÿÿ¿Ì¬Ð‡¯ðþ^â_çÿ7ùÿ­µïÌø_äÃÚýòw^»*8±Vþàÿhþ·ñ<ÿ'ðv2ßSù?“ÿíüŸÇÿùü_Äÿ%¼_ÊÿeÄVðÿì3¿·;s1ZsÖŽ—ìj_ÚÖÐøª}Ï›²ð3ÃÓ‚[ó>ÅŽ^Ë—hÉ•_ȹPb£Eíwí6Þn=mTQÉç¢\víWÂ^_±‰°¹¯îVsäOvŽöÂcÜú¾ÝºL¡‹’MAø ‘1ÕlŒ=6>Þ§±„N&X é›™–C»)>ÃÞ!JâØè¤ÆÆˆ%hÔÁH&ëHj÷(;Ìc±XBF`1Ùœ˜W[ÞÉÆä­ÝuÉXÄ y^í sã ÑÎů‚lm߸ïtñ+ùø•7ŒcÖZô.äèÄ*=ìŠ-¯¬éÇ+Ù·=õ³ÃM¶"'Nd,–HÒ2›uì‰2ì 3~&$"®®ÏûÈ–ý¸}ßùŽèþ¯ãÿ*t*"D×ÛÄÿ-ü¿œÿø ;&)¹;Z³ÔÚ~ì7]$ÚOÉ™©]â1$dÜ~cÌ€«²ßœÈâN„ô¶‘߈—êÛÆŠ{gb…oºúè‹êËkCä,VþïÈ©´\7¸\Â(;¯ˆ¾¶öмƒ0ŒÙ÷Ò¯­ü߃/*¹;wï ûæ’¿(¬»õ•£ מ•V1¶®ÉÄ´K[†&x«ý¼³$Ú¯{í¾y…qî.yGÖÞ“¸ìüÂÝYû¾íî¬ÿÇIHxçYññÉ|O¥·…³¯ÈK¬ýÌ»³&ó=Ÿÿ‹t´ß¹oÖLë÷ýkß‘5+Ä–‘kÿÏæÿ9Ô¸ŠÿçQÓþ¯%ÿ:þo ¶‰ï-Ôw9y¶òñkø¿ƒØµ¡ž!v=ooàÿüßE]7ñÿmÔr3ÿßAî[ø+±Ûø~/µÝNž;ø'ñ»øÿ)bw‡z>bŸåíçøÿ¿ô‘»£ëøÿûo»;ºžÿ¸öÆè&þ‰Ø—ùþÊÙWD·ywt;ÿ¿Iü[Ô‘·êi±fÞ¶ð¿•ÿ#èÙ—ùÿôé+üÿ+rßËÿ¯S-ñ]g_‘M-I.ÿÖÞ˜½3ÿ•;±ù¥žd÷ÍÛ6þçÿ„Ü=’ÿSÞvwv1ÿ§‘[ó›”Óü&¥Ô¶ˆ•ÿ3ùß®=¿Éæ\¼YXÖä>‡ÿšމU§f À,”ööØìº»‡Ñ›zÓ0ümwÛ‡ÿÚ© û¥ß(où¦þ—Š ¹þË0b§–JŽãFF“9–âuÓù°x§á5ñi:ñZiVÀ·Âh)¾ÅÅxð­Ø¢W¬iiM-iL6µ%:Úš—&¦.ªžW^6½ºd*ÞâO/?ºsÄaûû¼ðpÈ+§0{óNo‰ó¼\ªÇ’W*W¬9pÄÁ‡Õ46&Ú°$¹ee¢vY²öĶDK Ž×À&r˜R8Aˆ_±F˜òC5=W–\u*˜zÞâž—ÔÞpõ¤Ÿ'uÛ›·øï+©}ËšIÿ-^ ~ž·xE}Ií‚é“>¾|¾â3(©ÝµgÒ™`OU5oñn,©½úÞÔŒÌ[üÞ·–Ô®Y1ñÀ¢º—Ï[\¿ ¤vú˜‰—jÞæ->à øë‰g‚QÅ–ñ˜¨öU󣥯j‹NœôLÌhØæ¶EKÖp_;?ª_óV¾gD/YƒÌ‹Ÿ‰@¦,­ø<¿ %¥`Ôm ClUWî·ò¦±To6,x~þ”Õ°¢Îx ošfêÍÙ N䨇ó¦_¥Þ,ªÚ)JÕúÏ‘CâÕWGc%ܺâ&âˆYK`wÅiùSDéxkÕyÄÛ⸰m+^'«7‰]\Çß ŸøÍÈ[¾y~Ô¼î™Q뺶hùº3£“ÖÁØÛÆ i۵Ë#TÏΪÊÒ `þfë‚|ÞH|/³nÁ!¼‘ÖAþfÅ‚¼‘H^þf~UoÄ6?º+Ïõl²ØáÛàp›7¶#ªNãeþM½—>NÏ…^ofïÒ.~?{¤ºƒÍ5©â6e7ÒÊx#uÒ'ò]Üb1íQ/ÊKäîl{§=™$2ïƒÑLL8ŸLRb»ödçmê=r»Û˜}t{‘»—n »ûû¨Ï;ëòFz1ñ=bÙË„,N˜S5o^„ž:&l¬g=ÌQS»cŽÆ’tlÓX<¿Þœ¶w]9èÍi±JWN {sÚ{TWN8½9íͯ+'¦Wzrº{{ȹQìYƒqºÙ³æpÉ~ªçàÏ6«çàÏÁ-¯žƒw>÷úzÞùÜVë9œ€®ÉaÄM»s¸+ØÌA,‡o‘æfjíç¢eѰ7 |áí¬,¶©4 Ê7¥ÅGÉ4˜à×]Ê”+1T²€B\C±ô€ áP²Ã-Žd ¢“2ÛnŽ&KÏ…»$ò‘ªhÞBÇä©VW}‹Žñ™§--ù¼÷ZÞ[ú;azM&Ym¢óÄ~ÓV;ú[|Kfó±sÅ|=F£’â<s5Èd.©Ç Ë„¨‘¹\€Ç¯„øéXÖ+À©8ZŠäØÄ-¾ÈÍî9°=˜¸+‰;qũޓ8cì=Øz+$Ÿ|íÁF¹R“¢ú·1lÖ«$O!Pt®p¿Š%0½®F1!Ç À\ èáÏŽë}Á³A q;Û‰GJÔFU="ž™g,ÑûV_±üAÚ(Š?’ uQ$„€f6Š&ž¤,‡[=ŒåÉÇF©r€R¯:¨¨¯v·}ˬãWËF©žÙ³QUo/Xh}}±›h2ø9ê›CÜ“ØU«õaJŸÃöU.6ĦÍü%û övÑõà€({¿}­ÿFÙûŸ[;0Ùs‹„緤춛‹Q ÄH£mà$3“ýö±<Y.£-†Ô¨—â„'N¬äº#Ufѽҋ/ÁR *°o—8Æ;À³KÛ¬T„€'}€ñ·’ê˜/ ëp«Ý/^ :Áæ;”ƒ™ …ýÈÄðT()ïЕ`§£ç)"FG½ )µµ».Ú¼³-qfŽÅ`L͵h¶1!+EþÊÍ…:¯¯?s±¯¹/©[™æÃ×û37x¯Òí&™é¶Ê^:˜¹cî™æñ¯¬G¹Ü™ü®õÁbBÝzÓÙB]Ã÷¬vžÈù;éMÃÜÉøªë=oô¹:F=\zëÉæû3霼ñ½åGo³ºËò´:ÔÕ™ÇÏŒŸfÆÏ3ãûÞâjùÍÇjþ½ôœ‚6ir]ž­šÇâþؤŽL‹‰¿q¿·9õuÐÅ^¨¤3ƒËanzóܬp©ó½àäûÊeÍŠ9iò´¯ מ¥Ž™ ¡.ÄÉÁû‹\®µ¶µø]hU7¸­­kI,^{ýs.3.õxl:p+‰÷¹Én3‡ Žš–€éD"5ï;‡n‹ßbÔï·R÷~‹‰ n±×‡-†ï[(qh%=‘•ÎH2îq y™!ÌE¶¾ë ££Ö×S€¸<‡8º4ÐeÃŒBï7¹Ë%V+=:D‘Ç£5®gÄÈ‹=EbtçÈÄè.ž—‰Ñ]„ó‰Ñ]T(}wÑz@wÂg¦±)†š 1Œˆabâ£ÄCì-®W!ÂÔ ãé‹Ýâ÷.;ǰ×Mž_îC‰wYf~lab%Љé¢hµn˜o˜/¦ßݪ(­ÍÙ#p(‘Ú¨Â×FÌ¢Iü¨bwÀ"ÐO„­AÿýŒ}J¥µ}¬o_S›uµjk#f7Âûdµøƒwv£H&|ìãª(­ kñ\Á=Õ÷Z÷Ô³0SÒs)?jUÛ]J_Ù"hÜ媣¿hVf[Äw›-âw$[ÄïH¶ˆß‘l¿#Ù"~G²EüŽÄ¶ß"°°E@!ÿ²E˜xnŸ7¹zn±Ⱥè¤Ý•vZÂÕŒxu©~î=¯ÝÑ>`/ì†åÕû:Êî½ñu4¹tÎ×!Ä©lǬúÆÌ‚ÅZܰ5â~³æ%£è›Ö~`ýà÷9ë¿?´ðû¼UÏï V·í¿ö‚¹{2åvà^ϽĢ”@씓íL§4벦ÚLì ò3Ïå–Žt»ºÕnEü¸½pS`º¹¯ø›×&€¸Hù›Ú—]Åö¦†ÖÏS½bмÇÕ®Jõu««ÝNûÆ_môN_l¦Ú ö–y‘N!Ȩö}Ú vIí]µ °Ú Zö‚n½ÍuËn)‘ÅÚzôFïôÚË. L“ø¼±výxw+7Šhv˜`øëªIrpÕô{Ö_©´gc§f÷lìTÂì$ƺâY,J½Úª¦'-®.£æêEiÒ×Ë}ÑíxÌ>¸Oµ‰Í>`Ÿ¼ÙUô–ïè,@.ÇÖµ7ooì5¡€y´Zo¸€jѱsx%×cþëÖ›™:x}¯ …Xf~RWfh!ÊÒMØ×ÈM83¡àìrX ±¿ ÿ Fß[‹p,…AcB!»’0µÀX!FNt÷|_¸ss9ÀÙuÜÅf¨3&F]²ÍëRÞæl"ß#nþ¾GÄp¸ïMnsØ«ºòëëµnYÄ+ïëÐ 1Íb°˜Šf¹L&w_ÃÙ!ä¼Á&Åv—Û³ïFZ|0mịI‡cݧÝ>‹eêÂî3êBIn†¹6¹»p@p—è»éX»ærå.¢Á¦šÔÆE󀘘8Ñ\»çr5Zn7[Œ‰­²ø– ù¸ÁQ!ÆuL–Ó¸Aa˜#’–¡î‰.\/¶½—Ä÷,Ø>Ñk,ÎÇ"ˆê(÷¡¿G ÜŒsbôÓ…ÄØßô„Û‹'Äè÷+ãkVAÓ®ù5ïÀÌ)1îÔàhbÜ¢ÁÑĸ4³™‰1+Ø@$?ç¦øUÐ îíñõ© ô/JHÆR¤[ªÐdQ½áV.YRŒ+½®C%õ f†j*©OV'Lvûõ ·ƒ~1мblzÄØÎðˆ±u1œ!ÜWÒ^ÁÔ†_I½d;ƒ™ûzŒûJšûoĈ¯¤íùw1Ö+ Kÿ}ŒòJº5~3Æw%1zþ!FveõìcLWÖNB/R®¬YùVŒÝ*ºr;žéŠê¾ÏbÔgoU^•ÌÆØ{N «A{=BŒ½ç] Ú{?b¥%Öe‡84¡ÿ ÂqFJ11‡Q061ñeb§7¥7wéi`æb]¾¨C3kÏðN3ë¶CL(&~zŒ@ăç£ÐÀþˆÅ#YKìHmxmaÍœ±Ó†Ñ«:dØ%Ùm…›iEÅEµÆlâÞÊÈ^p—­½À‰¸Æ¼èëAañ¸Ò1¸Lžs^TTð{4m4)Ïïhvñ›õò˜"ÔnÄÈ ¾„Š®ËðzðË¢ìnYÙ‚•ÊŽ×2šñ´öe ð+.öåFyMõæˆrÛûÂ執´&ë:£Ü”JŠòÞ‘jNÕ×Gyg‘f}*ÊyGC*“­TÜT³´ã góÚ%.PA2Tñª¶öº‰«gTÌ*ò÷G‡qMc2Ê­ÁwÅZLWÚÇ+ë“Õz"c·§Z’Í.¼±!G 7/éÀÆë%q4¾Â%¼°¡¹ŽëÄy Í5­+«iK‰zÎÅíEüóÞºì›èbj±¡Â3ê[“É긢(ç ÉmM:¿—…ËÑŠ¼Ä¿-Þ¢+SË“­õ©QÞôä$·Ôú4Ñò–T[ƒ†!ÊÏñe]lY77œ”D›ÒE7µ·FÙYpC¢Ãß[ðÜFdí.J6ƒ >ÞV³§—±d%S—üuë²(û²ÖFæomp<«â²j…*_n¬7 C&TæoË»›svum Äû5Qþ¸TÛI5-ôøt²¥µh–.Yå½9Õ2ªº$Ê{Yªe4ßÑBt3.ml'Tž©§rÄQ¾RoˆKí1®Ñk•ZŽôšš·ÚkÅ*Gºö-œN\/C2,aº Ɖmìæ–(÷؆æe K¯ºHÚƒ¥dMÔ"^J›6'—jÚ][£o´%“µí¬ Ò·Ýk¥ãgÓñKY‚-k’Qöí(k.lmiŒò¾ã&@¤”Úž«[Z,éït=ëqSK”óÔ:rU.¶Š£¬ŽŽ(;;¶Fr.‚QîQµÕŒQadk5Ê©çÖD¹/YRÓFÅŸnlhjhgðÍ÷ʶښFòÄK—F9ßf?E9ëk–SYãRÖêtÙSÙì¦uªƒ2K£èˆ’ú¾npqá L´¾‘ q”ûòö6&ßç© –r›ˆ5RøDSSg”ÿË©}͈çd O2‚+[–­lk`׸ù/WÞO‹²>écZÇò1 Ìדôé\:q!Љ*üÀH,áäÙ‹ª]8wÞô(皬å®jã«ü~·^4µ—-kˆ²¾§,‹â,;Xñ…zyd)Í“DïÑ{û|Zø p˜Ì´”®ºÑó›ôüØã«Ê£ìê(‰²/lãã[ ÌtŽ QÎ]MMQîX\gËÇT·9pTüzµŠ)îZ­’‹UÕ®?_©îˆ_ÿaµ .îQ­¶»ªÕÃÒõMµì€¤’’LH>È¥@×ÊT ¯4¥¦¶\¹<^®å_X pµpeü¯MÉ¥5qËgµ-«©ÞV>V·diu]C+Â&›j–ò´PU¾+/sYö©“Ï×%—tÐÁKÀ;…£jÚV6ƒ .Óß*Ù(ûìÙ+ÝEÍ~V«?ÊYºPT¹ t&bO`]j/ À1OÊ«’M-ÔŸqåýÂNàÿ©ÅÕ­MŒCå#éÓìÅ%þÅ4Ÿãoúr€Û~¶/‡^DoMç0-aò#äâÖÑéWí/ij*²”5÷Õv´¶V§ þD¯l_É¢¬¬q‘Íl…Š‹¼»$i µ‹MêÔI|‰Ó}J6ï‚û…¥ ,jáõêû¦&ùyZø¿ÛÆÇíK¸C|À‘\¹„»Q±Ž/ÕòqÛNq_¯ãã3µ|\_ÃÇ{—4FÙwÖññÙÚFïü©ü›'ÐÊÇ'õ÷·éç7MLü¡{F1¹}û¶ˆÿõž[yßÊñ%H¸ÎçÛO*>Úu°øšXüPèóœd•¶ŽÚ(e‡k«ñóx1OŒBA«+úªîœ—ØËÁσêx…dÔ83f"7íѬ©À_OéâÖH•ª:ºêÚÃRfU3B/€5òÜvóÌïÉzìÕ 3ÉËAF~(ÂAcDã>e¨:S?£Ü)kþÇ¯ÏÆg…ap§°Ý£ñs¿¶]F~С³!oü·î‘‘)` ®ïò¢¹m¿´©eøŽ¼Öd|G¬Y…OW|Hf>]§®[ÕKÞ7x’$WÝw¦<úâó=Ôµ…÷ø¾¼ºcû¹/œH-ïz'5íÊÔt^9É×™Ëö¢t"õ´v#3ÒžƒdªÖ§Þo‹ãRÔ²ñMVïs×=Yog®Pï.«÷Ö¸¾–8e)þ#©ÑxM4¢¨bÎü©ÕÇ/™¾è·f–rs.£- ÙIÚñª {ï ¹@IÞ|ßÞ}*‹½·KåˆMâÛ¼›g^°NÒémóÎŒ¤©3²bwVF"Š¢(žý>4°{®[D³Ý?»z÷O¾šO{g$Ã> ç½3:ÉÞá7ôgž(Æ7ïÞQx7~|G1÷í5÷‹wDZÃΚhú½¹d”V±›Õ§[åqô?÷IÊQÿܧÔiÞ§´†[å±´žK’ûù¼µ‡Ý6O¦—ã#6¢/ËðÆKÍKÒo¢= íÍÌþœÏ]g9oß·¦ß('o´×±W ìÅíìƒên4ÒɈx7žU}üòÛNªÞìF¿ÇØ;Ânôö ˆ¿7ìF¿yçý *wü5ÇÞå±ß·ìLï%•w×Ú΄\Þ)%ºFv;“uàw¦ÈëÆÂŸ’¥í2!„”½Ù“}à³7²¶œB=íà­9Î4æ¥ È·›½¼íQ»ÞhÏ\Æ>I=¾"«ÏîÙÁç‰Úò;fj^» ^ëê™Ç…×l|rÖ’¥ƒµÆFËÖ2qa-Å¿ïv~tXÑÜU­E‹-Ù±LòýádžÍþð>tÙ,†(ÁÍa÷Üjï(ð«§ëÄM[ƒñ!hÔ~ˆ®èc½ý°sµ>\ÓóÃ4VbþE 7;à æjU˜ÕÑñ¬ÎÅVƒŒfY ¥™2Jóâæ µsì¤íÕŽüA ³¶ñF{!­Ãá¤k‡0ÀGY/2Ìãz±‹7êEZ‡ÁBÙžêÄB[±}ó ºl Ù7ÝXèÌxug™³N|›í¬³´³³ËV5îôÀþr–ª–8H¼=ì¬ÏÌãsƒy¼(>—dò ÿ؇|D'Ι¬Yv; ¿ã—¾À-ðÄëzÍ}í¨Íx:GJù†º >v» {MÅ ð sªËfUìXê¹ç_'íæÃö9‹ŽþÑ£´ôÌ÷‰FI‹ù>©z“oß§aþ4÷WŒüwz7¸2:Aû ¼¹u•óˆþ˜’sðÕ¬^¯-[ôÛfÓ«¬Çþ®Ãí×Yް—®÷ÈKvöþ†àß—~ûÞ#©3li£¥ï˜]fvÇé·ð“>¡§ÒOí·•KÊfý¥ŸÈ_ûùEr²³‡œ‹}é›ï¡ÚƒdG‘ùɇx©Þq^ÿìJª}ÛénfS?Ô¼ÙuzôâÇú¼‚;†í³F÷ûw úìýPãØÏ-œ~n‘Zéì¹úšöœ>ûž#;"š\‰Y?åðM; l•Þ?¯ü½äv¿{»ÎtÏ.{ØÏ.ò/}ÜöOnmÃÈÃH–¢mâçM¿³avCOýÞ o¾¿wÏNïÝz÷®¿C±w̼ñ3ÜÙ÷ëCßéµï;R1Úg%„»NýàÀÎÚUÇÝå?ïÝE‹þ´wý> {yÆ}{×JÇÛÂOÑ~*Óâec7öð&nùìÊ`_4°wyó_öî¢EC ìÝnkÕ½kx8Îø²½Òõ65~f¤è]NDg{sæRüÕœp¤zsÚ=Ò•ÛÞœ¹|5'b·½9-Þèʉ(noN‹Ëºr"åÓ›ÓâÑ®œˆìöæ´ø½+'b¼½9íÍ¢+'¢½½9í-¯+'ëª7§½wåDÚêIÓp.瓦áLv\=‡õ]mÅQS·…€²úø°'ê²Z"RHY"wº•%•¦íT–¨–hYL÷j°–¶f£:)!§F!ÐÛF°^I{¤QBЙjrž2õ-I5dñšÁBv®Ÿ.UBµýøœ~?ØÖ€ƒ~Haj¡Ÿ'ñ}‹ãz I»VÆì½±"ň#ÙÁ2ì}Ë3RáÍ’cÓëfÉâ#ùNmÇfIóªÎf‰diPúkÓë*Ôÿ•|‹Í5@ å )V?HÜK‡$Co"ñˆC KK` $CÌ% D\ó ‡ €…‰Cè?¬€ ØŒA¾˜%„uesÅÜ;U^Õt(Bi õL”´¹ú=q‚ã¿Õúì5µ‰rò²}v¶i·ÑÔtÖDá:É^M”™vÁ$ñÑ4“tûS&é½&{’$¡4í“$D« Ÿ$Y}ul²&KRU“%¯§ÎMÖ®”„Ûd‰K.u2dR&3Lþaê˜&ÿ0ö0³Y½˜?xÇ `o÷:ùÎÅC¿[—¥.LqúÁa½N¾Á1?©Ñ÷$sòà¤uò=48ùFºÐ;ù6æ]/°§à|cMÇ;ùF€µ¯ 'ßÑ?=AØMF8å°ËPWÉ„9âáEÒÔx6¢z6÷3µ]þ y5¼ ý „‡êȳ¾rºw¡²IY|}p¨²”§96)<¾¹±Ž&>A ­ü¼`¬æÙî‰Ñh}«?Ó‰¤?ôA× ôþÁEԑ⬆æZdŸ¤Ž¥nÄ¢ÔîÞòÂaé]±ÛÄÇÆº¸¾(ÕÑ~ß\«‡…YI”I 7£Ð†´ÌÌQÅQÖçÿ@!+¿`CöÎJé—õŽJñšÒ±lÔòþR´¢œ_hkµoØŠR»’ðCñÖÒ±,äÊ÷g@?¬Z:ì«%¯Ö³ÝŽÇ“ók:£œ=’|+ššØ5EÁšñAS”Ê/q³ÙÑ=†öo¨D¸aü$ Êá®”Îæiò*'º—ý£±M¥cå/y”’åîL¾Y¨iý€Ú"²3KŠ£‚×?Α«ö™%âþ„aDtŠE¤,øxV«–S¾ò±¶”ŸûXÃKåNReéãs]n~|—Ì|lË•¾öèfJž@ÑÚ'`Kåü'pØWÇÌ}ˆaïÛé¥mÐeý-q' ¯Iԉ뉎Obʱý·å|Oª ¦R4:Ëa:Ûé°’Mžý?CWW/: ¦Á‰±)SzWÐ÷V@M×èDè'‰Ä£#˜[7:}ñÔÄN‚;³TùzæWœÎò?dµV=—/åˆ|²s ó‹UÅüRZu_~2ê&§8;½ÑSÒû\SýCâf͉ù)fO‰]ºÛ™aEØ™ùÁ‚ðŽÌOAªûT™^Hg†ZÜÌü ïÈüT4Ù—9’’“›™ïÒ«žÌ—é΋*Œ›ƒÖÜÌ|—t×åÎ|'öáZú"d–3oíî²€,`üPØÞý¯ßÅ«nòÉ9JØ_ØäuÒè¶Ü´xÄÙ2dâk(ö‰G´›ÿÐNñˆ¶-â:Ѝ‰„ð®–æ}‚0¼ ÿxõ+SÝ]5¤;/(ebå€dpyjºÆÈ§œÕ;ɧwÒpaÂOt3¥(ϹßeÇ,­Ø1K3Í3eç,Þ4KúíæHÎú^î”^áï{ª¼Ïl=g¯Q¬l¦œ83S›ÂLyQ,|2y‘ÈG3õÙ ÐÂù™‚ÔÁ^A­á˜!öR§ÀÊöRš÷G{i÷Q´o€½1dß^bnü AÑ^‚îØxé{©s–ßKx2 â4ÿº—ºµ}ì%Aûö’¡å¹™‚0¤½C°ì÷±!öR§pÔöRš÷»{iȦÃ{‰Z÷í%æÆÏD)Pîþ{I°—:gé ¼T^Ú;K{÷Ò°û¸}줺«úÏ„Ä ù›·¹é±¶Ïöœ§ ‡MLTÍKÔ¥’m͇¶'œ´v[{*Q“p¦ Úœ”u[Õ|q]8ÎÀÿšheuLqê÷m“£Š!¯º|×c¢ÙÀgW–'ÚwD?.¿ÄÞsæã½gŸ}Ül{/ª{ÏI«)&¡ |ö´ÊY–àƒgÙ{F½_LLølùêv |ýP¿y/Ÿ$ê—t“Ý{Ÿß8‘±^Ð>Ah÷ü„9öÂ.ÞßDþíì÷Hc(¦·M>Òµ<ö5Cë;T«å¤G'Ô¥9‰æ6æë¢š–D^26&ë]9¢ø0¿µpÁŸ°n>{£™nvì?·í›}µí¿–5ûf_O¬‘Øhíº.?Áñ“®È¾ÁA†ç‚ÒnÄ<:òÌ}GöMÝíZ‹|áÒøwýb”JÚ•MQþ«£ó}þmWäÌìóiË›1ñ>V9WEûÝ ƒ:®ÊË.ù<;®ÈÚ0÷Žª¼w_1ðî¬dîÆüÁËog?w­Ž¦¨ß[s虋¨}áɹSV·oKWmÖYÝ º­u{v-Þ³°RÒ]ˆ“žµ®à”®Å¹ÅLÎ[õÏøQW5Ž×[‰ÂÝ/ñ7W_kÕâ»NQùýoâG„Ǿí±¢˜cˆcÏ·V€>ÏÞ±·½@"‚k,x‡å`W{qRr{1=v´*åÝÝöŽÝü¹ðîKöŽq¿7¼û–½Ã;KCæDNí;D=âó„ÉîMÅÕ3 ŸÙwÆ­ažÏc&õ2{„0ß)‚ÖDМÀ†÷@°WÜÃæ±âxAÄÚzsZÜÕ•¡ƒÞœûvåDС7§½9tå„Ó›ÓÞ~ºr"Õ›ÓÞܺrBŽRÅæ4¾* 6ª žðÎy¯4˜«žƒw>¸­žƒw>دžƒw>+¡žÃ ÁØì¹zÞùìÈzÞùì×zÞùìézÞùìøzÞyaCŒïÎÁ;ŸãQ#>c„wºÄg rœ×å]Ó@ûY2olÆáÄJò‡' ’üË!>CIf”uY“DIYžñµyBìB\žúÚDÀ&“I0¿²d@ÔŠ6‡x3É>Iæ¸"¹uÕ…+ @gµ#SÖ 'ƒª¯aF}l^èï¾Z׿I¡¨ r¿¤ä7Jýk”ˆ„ú×(g§ª³Q"3ê_ã»âú?2Ø?OÛÏû×(¯êQ“Üÿ¨M’EPÿúIîGuõÓ¼¨ýäÌKýëwI\_¿K6÷Ï:µLû×/öK=Uî’Ô¿fIO©Írߥþ5Ë¥“êlÖ¼¨ýÅ.Q}ýwìÿ;d0ú;wQúFªAý@môo€\”©®’Qÿ ¨wë¸ëæþ™…õo ¤èÔ¿’)škÑ ©-BȪ·EO5·È±’=-¸NBâföÞ KNr/ƒäJîA¢m©×ƒ°>€s$€xÑ`öâEƒ™ä^Ë­¬ê,×|ªo0÷Z\u–Ü‹ú8„cê‚[¶‘¤!Ì1Òî8Æ#i¥g1³Õ*©õ»5áøCY¿¹Î/]ét!\ke`@ˆÐt­D ø =zˆžt5Ë(s½@ˆ^Rö ŠÚ „(Œ øôl4ØOÙ üPÕ^ kSËŠP['{ÁdŸô áœéR|ߊU Œ}ªÅÒØÍH¥5Ù.;.ÖÇC|÷G¤¼¯Ÿb¯hx@  4jÑo°V6äÝ_CYÇØ#PP|#UhŠÞQ:f,zöê8OVB|ýGàI£ŸÊÝÌçì(÷ÀÒ1pì‹ñ)[ñ©æÌç ñïg”~Ÿ³d£c=’¸ÔxÄÃFñ×E±ß9RÚ˜ÄS‡ròæá<ÌH,¤øÍ–dkSC[5 {ñ>»AÃðÇ)PtÇÖí`¹ù¥Öû&"yïà4•wÛ<ƒ…‚M#\îØ¼ ß´Óú$ —eéC ¸˜’…Ëꥃïíº7iË`¿ÉÖ*d[(¢Å^–[•2Þ n”•­I*îâuÕˆáHêA^÷“·wØ\jO[fãÃcqð½„*Ù»?·Â zb€®z,—Ø»Ri«;hFÃüjѵyï–qé+G<nÙ<¹D›[üԵ̹欨S˜SøßyĆhâÛÚ¹ ‹ïÅïâ+L¦²æ$æÎAYå´‰‰Žæ›S+àß@K7Ÿýï²¼Ü#¹¦èjåõùV;P)oL÷ú¢Sá*ÿñV¿ýb²Ïývt:ü)ÈV¦ˆP žFÃLŒ^ÉÏ÷-#ò¢1e«sN÷kźá»j£¢® ÛkVEoX³_´V|2ÃiÙ—»É»1ãÖíÕÿn2f nBþÆþw­âåíx'µ\I-ÅÝKQÊ ¿ c7{.ïŒgñNV¬Ï?ÊÅÄCYñIñg’kTƒDôo öëÿG ×:Êèчé‘<‡›tð­Ö`½ˆ7”`ÄEæl â´¬8ÙÕ°D=ÔL¼bC™¸ž™xuÿ»ÌÄÔ·«ÿáå¹Z^©·êÅTÕImêÅýÔÝúÒPrÁÛõlÅÛÕøRÕáj¿¡·z1ñ²ï×±Iu¸^ÝduÌÔìèͮɘ^ØS‹øƒ+Öm¬e¼vÆnÔþîmƒöÆo£jwô¼½?ù€ª»Ø#;™›WȘÃÖîüâª} ˜§èvÃõÌÁ«ûßÝ€qˆÕCû®èßm³9k€Ó%ÓÑZ–hC×âtÞUVïÙñEÕ‡9Sž–§ÝòLõs®÷mâH¹÷#ôNkà`Ù]œŒ_Ë·x«;dê@šódê`óÉit·Z3cÌ@„ç÷U9z™êꬉ™ÿ‘”b"Ú½(†KkNZÙï ÇqŒ¤®‹qåœo1a›‚çN‰óZ8?ÃÍ*ÜÞÉ“¾ÁZä¾;ý(È­Úm»ñvϘë¹ñmË…[÷XžuyŽÁu¸Ð9È_ÿŸpÙO¸ø/y} õüä¨5ÄXô¿®Úøe,toàN¥1áÃ4&ܘƄ'ÓXKˆµ†Øˆbm!6>Ä&„Øä›b3C¬=Äæ…Øü[bKBliˆ- ±!vvˆb«BlMˆ­ ± !¶)Ķ„Øå!¶5ÄÂ,^b;BìÚÛb×‡Ø !vcˆí ±›Bìæ»%Än ±ÛBì½!v{ˆÝbw†Ø]!ö)ãüÁêàüšm•ógo °ƒ¸Eˆw0®\KÁý·ˆçG–.@ÅNèÈÛÖ儳ÍýBü…,gÏýBç¶Dz :bŽ+à~ñaîÂC+¢Ïë~‘”š5¶´;{±N¯nIiæ–]zï-ÃÝ v_•ÝÙÕÝYµoþ/ÀO7ú»‚Áïµ·ÛÀ7¥1|ííá\ÝTŽqxu̳…÷– ßv¼‘±¡èœôkÇ8\Û6‰†Á‰úÞÕóy‹³à&ßÛÓäÃTP†+cûð¢°d†ŸÆ‹âV wÏd>>52/z&9603£‰ "ÖNl ±¾G/+6”w—¿VøW=þùL?ǪŸ;èñ{ûßl¡Çwö¿Ye¹™ÙáÝËßù£.Ô×:¼ëó`6þ–N.6,½à1,Íš^j1ü|zž0¦‡šívoÌ%#ìökÒÞIoÂ`ljÊ1¶á[ÑJ‘ñ#ý¯1ò×ÿ¯ÆèÐà‘4ä†-õ“ÿ½=Ø“ÏáCÈccó›˜ÇØÄ<Æ&æ161±‰yŒMÌclbcó›˜ÇØÄ<Æ&æ161±‰yŒMÌclbcó›˜ÇØÄ<Æ&æ161±‰yŒMÌclbcó›˜ÇØÄ<Æ&æ161±‰yŒMÌclbcó›˜ÇØÄ<Æ&æ161±‰yŒMÌclbcó›˜ÇØÄ<Æ&æ161±‰yŒMÌclbcó›˜Çذ0;yõŸ Ûî#‹{aø¡!–ÞÌ9OÝ‚±³œpÚñÑ*_GÎΔüW Ϙœ0ˆÁ×búe9{ðµPO­c?3ût¸Ä×o7|­/íÎêÎàëXøîpøz…Ã×Q?¾Ö;½ÝZÜ6_7éŽ7,º©ÿÍCø.ê)©Ýeß•/ñøî¬õÅ£ûñÜç¨ñSô¬;Õa]a¥ë 8¬»ŒXW·ch„ðjwß;ØÃ;‡<èáÿŤñM†IŸú&…›ë1)»Ì•BÓÈkch_ÅËVÝ`ïÔÕ8˜ûŠ/5LJM9&5·]Z‰G^¼ÿ§ùëÿÿwMÿ3VÓ²Hc“󘔘ǤÄ<&%æ1)1I‰yLJÌcRb“󘔘ǤÄ<&%æ1)1I‰yLJÌcRb“󘔘ǤÄ<&%æ1)1I‰yLJÌcRb“󘔘ǤÄ<&%æ1)1I‰yLJÌcRb“ 3ê1)1I‰yLJÌcRb“󘔘ǤÄ<&%æ1)1I‰yLJÌcRb“󘔘ǤÄ<&%æ1)ôÄNLÚ0©ÝG+¢™åôœŽÝK``ù6Lší,0©Xâ9»`lÐÉ“ŠášåìÁ¤ÒÿÀ [‚cùc÷z“¾ÈcÒ¯€I?0é§&Ý´“"碌ëÀ޻늛n3®Qõm»xlóôÖs¶jï÷a½¯–à»ëmÜvœ×Ò«mØŒ_ç;;à× †__Eœ~ƒ_{û-»·ßwåÐï>î¯í†u—?†uÑ©ñX—yGÀºwf´¥boª L{[F[*ñF}ô.nX—šÖÅFÌÿº¿šüõÿÿ»¦ÿs8Äj÷d1u‰y¬KÌc]bëóX—˜ÇºÄ<Ö%æ±.1u‰y¬KÌc]bëóX—˜ÇºÄ<Ö%æ±.1u‰y¬KÌc]bëóX—˜ÇºÄ<Ö%æ±.1u‰y¬KÌc]bëóX—˜ÇºÄ<Ö%æ±.1u‰y¬KÌc]bëóX—X˜iu­&ZóX—˜ÇºÄ<Ö%æ±.1u‰y¬KÌc]bëóX—˜ÇºÄ<ÖåĶÛÄ^Žu–Tª}Ö•в2S¾¿¢ŸÖ•ªMGα.º\`]q³œU¬ûÁSÖ<ÃÃ:ÞØ—•=Šu/0¬[X[Ú{Në1Oç±nÁétvcÝU9ùÅ|¿¢*×}¿íÁ©âH‹ï{´ŒŸ §Ámn…³«Ø¨•“IçsÅŽÛüYÇ]*ä&ø~uU®û¾¡*/7×P¤†b¨Øî®w\'A%}ïªÔ½wTyjØš“Pî–®u ä='ôÏö >ñêü)®ŸQ~1Ü+rÚÞÙœã¸ê.ÿèÐ;Û3“¿8ÅõR|×,¿ú¶;¬›±ï›í—å…ï‘Ôåïwâ@Þ›Œël1·¹Çkc޳ÃÚöÍVqÈæåt»¥–¿[ó¿bõ>rÌ|˜Y~NjDžá»1Tî ÆM69«5×rZ™>»zêrŽw=y÷ßòÞÞ×Ï[N³9-pݘŸžXÖÏQ79‹û‡œ«BΡ?Ò|t“ÓøQêäϹ÷Þ)VD9S6Ü'JõÛîO[Ö™î1›¶ó ®·{Ìâ;]¶ŸbÜÒãS°ª7Æ‹I¼ecÇÝØg†×¾Ó‹½&µÞ‰SgßiWÅ‹_iX•š·@ÊœFG Š­ÿ)Fþúÿÿ]ÓÿŒ9aŒÐå1U‰y¬JÌcUb«óX•˜ÇªÄ¯çàÏî¯ç°æm°V=ï¼8˜­žƒw¾î‚õ¼ë›A³ýI­õ¾tÔm¸põ¼ó9àt×sðÎç@£ žƒw>ÚõVçßæ€‡^ÏÁ;Ÿƒ•]ÏÁ;ŸM¢zÞùhÕsX?6:Jõ¼ó9Ñ¢·9Ñ¢·9Ьç°^ì>cáÖs˜Eì4íÙÇuC•蕚9Úýóšö¨|r CCzÑ%Ý%ti.¡†²ZYvš„ä+²*~ƒ4Öõ¶Q#µyú>POë/#‘jÀ€¯Ç*j¥%ŽV9v¥î2˜+ oCˆ£à6ÉWT܆IGJnÃÀ¨²„ùŒÛHn9\KFÑ]”ØFaY5¶Ñ(¾@c£A*,,ަnÚöç-—øýÑM- Õ>†Õ"Ú£¨Æý0ßRmS]RµiC½µ€ŠÇ86¬!\O‰UUÇå&CU:õÞýý¤Œ£ËL ”på8ÓÆ9@Þz3^¦UéÁîæªs¹”Žbxòdð»L²G³µ­´N÷CÝ=³§1‹SQÖÇöæ2ð7ãeω;µl²ëŒªêìÔ2]¼”é4u@:MZýêÔéBêÖéR-;d9S±KW½©êÛÏ<ƒ ̳Ùqs9¶=³óuHz*³ #äi"G©–s˜nØ'ÏÀÏ [a%K“–¬ÄË;À9[) 1ç±1Ht ¼0JV3¸1YMMl‹ÕÔ Ëd Ћ5LTÂ6[#ÕDÍêùÚßš¬óÙVìé @±°Q.'°¯/À cm´ŽI-p_G àŠul>öôzúÀž¾ÉcO_ˆ±Ç“·»&oJÃêÙð ö²&ï"zW¤ž‹èI‘:6²k0Ò³QŠ»Ú7Ó§";eÖa‹äØDýE6À³0AY¤OÏz3ßÚ¾Ïzg<¹ÏºÄéýfD¹žh†\`eœ ˜(ÀÀ:àG{­“ŸÉ:ð™ÔÜÑ<2c–xŽÈ câ´Ã{Op{ãYÌ0{ãYÌ0¢K¤ø«9ÙâÃQ´\»\-Íås…>47ÏÓFÔl>O†Q57[©ï[™#¼leÎÙÁÏ—QÍË8U‹aª^)çÊ¥ ¡jî®ÔæÓ¼\iFuG§3šÊlÃõéáÕ=šWöqÍ«A-^ @"5¯µ¬x5¨¹.À«÷šWƒZÖ¼Ô²¢"_ËŠç‰ZVÜVÔ²j†;²ŠwÓ‘LWË*ÎL–µ¯§'—Ž™€OƒKdz…Ÿ¿Uº6õŽ€mÀ©ó°%䫵õr60³»Ö.añ6>Ui›‚ªô=[…ýŠÃÈ0-Ê~C %4S ¯(7‹¯äS ®ãS`÷Û[u˜Šg‘av”ý±“(á]LŠ,Lgä¶`Ÿ³À5úBøâVy‹â82e­Ž ¦+=B% çS%ŒàS%üÆVÆeq2¨„å©ú(ûí­É¶ŽÆöê%c0½xXªetycªe”‹$5>Á4L~Õ% ržK H¼Ô'82Êÿ÷^‹ÝsÍÄ(jU‹¾Qz„æåïø”Ã„¿çSéo¶‘n>EpS >)ŸSݘJØÑåÞIRùQØÒBãÿ˜ "Ü·%¿µƒP9kËT~²e¾*¯Ø2¼•ïmÙ •çnÙN}¸@eq‚~‚˜YÙºã÷ö@¿`a‚™ríòÛ†ºüõîºüÞÂLì$ë©6¿—¿>7.¿7‡p,GÈeîoóÛ!tù÷ºÔ",ƒœñ¬Ø\‚ÉoÇÛåßC0®™ExçFg_Êä·ëÃåß³‹lþr0}0œåÕ&2‚N Ã9—4๿;¾«H\;§^pÿý÷cÓžøX7} c}_˜>Hßv™>xzZ˜¸ÛôAj¡Ûô1‹Ðg‚y<ŽŠÆÁÝ/ø!OÏè>-Ú¹ªûÚËV}6»¨û38¿#{>¤Æ UÝ»]Ö•—]„y¦vŒGµwíóÓNˆ‰ÍUÑn—­º GÊ©UŸ)8eò;q ÍÌE%ç:¦7*eò9‘øôÍ­ˆCü·£7}äSÑÙ@Òƒ×BL•xÓ ’Ú]wÅ¡ú5 Gêp}HÑ¢¹óªËW½âqçÖ´SfüËø!*h6 ! BK!+Î „¬`0ó*§¬î<ÿþ9cƘ53goÍ.<£3Ûj™µUnÖZ{gMó2ºªvÛ\]ù™ìÎK˜+ÍÑõ6S¯ÆÉûÿ›§[mžŽ_Qþßæ ͈sl† uÌPôÃ0CÖÄ‘!ÈJ 4M‡8SYwF/^Ç–ß…£þ­y{v^ÂðÖÜè¬KêèóMÖçbèóšèôÐO‹A!ÄÙ~ÊWå?÷Ó÷“SÀmû=õþÙ~Ëg˜ÓíÌò67ËS! ?ÃïÉ­¹›÷çM¶?·á°?ïLïÏ™°?½'ûs«Í>gàÎýiXPnö-ÍÎgm("ˆ4ß0TÀŒýíŸgìo;cûÿŸ;¸è÷#öãùâøß¹[¿æ‹™òó5@TƒòÕ€÷8Îßvó´Ëæé¦0Oó£;Óï^àæirÕyÌÓ5›ç©Ýù˜;ýmÑÁEsæV1nŸ|6¼à5wLðÙÙ€üÐ9œül0~6D0§ Q ZvJ#çû绹ƒýs—ß?Aäããn“gÕýåÄÏh5¢Ç úñÀŒ]·ºç6?gs19âÄ,žJQsÕbf홵Ó;_FÞ4kûŒüÐ^¿ò39˜‰ÓþÎe]'ç båÎÕvúT-{E»#ž­ïÀå|¶ÚV–¶™'ˆ7;ë›*ÖÍ3äç Zލ6hD­§Üƒ•÷Û„•÷ÿ=V6½üTîÆÉ*‘[SâßÐÚ¡öè½%Ú£÷–ìØ£mÿ÷Ö´`Îô!nMÂ÷ÝšÔ¶tθë +C-™5ÔÂ.•Ý#»ô‡³µw—ÚùúO·§ú>…°¿çûÔ’õS¡nOEèƒûyÏ>Q2¸OÛ»=ÑÏ¿=‰‡àÏàûŸ2TÀ]$ß§ß½‹ôq°O¹=Ù}Ú×Àí î>ljìŒAE±ž7lÐìæ˜å›íœÁ›-oüìÌñ³Clkt›f‰:ðw3ÔmpsW4¢¨ª|¾Ž'ß$Ý&BÙ—+¶ D×C›Ì‰ŸHDÍ,}•Ö¤}¹‹»Ñ®œh8»ñzöä«»Ö±'ŠÖÛïìÉ™¾O.Êî=‰¨€h©eÚ5þ£[f¸cGŽNïÇ+³ éÝ3Òó[Û‡}Ìï™ùý羇ù]fó‹ÀË>“¬Fxá a›ÇЧ æò¤H û žsŸH‹Ý']95n{sڽݕ¾Ø“‚8!'NÅzsZlØ•Û}½9-FïÊ =º7'wœzNì÷õæ´w ®œX ìÍioq]91®Õ›ÓÞH»rJ”`oN{sîÊyÚöœ–Е.[oN+lÓ•¯¬½9-פ+'zºO©t9hÞ‘|u¡¸j¬åÔÌaç¯ä,é›í ­RR/Dˆ/‹U(”Z‘º. ÍfªñÙÁ#û†ãèS2:–â…îŸ52È–‚¨oßA&~ ï‰knøJ¼15-Ú\b ŠÜßø–¸Ö¦ØPa­Vä2 …Yå¼°µú·¶ÕÊ›:ãÊúåv’LÄ ëo³ž¦¿~šu±_Mœ»ŸD7$åÐ,±;l7²ó%MÐüõ¸ææo 09ýÅÃSÍýÅ9PÍý‘y fdf¨y€DmTó€ âš¼{(€šÈ^¤vÓÉ `.Ž¡Ýbì:bX©ÕÞb¶"[ò]5½5{ɦ¬fók±ijqŠ…ú–¡aöÐ åÒ¤Nk ú~\å   ³ƒ%šÕu`0·ÇàËøÖò¶¸ÖVüñWkUÎÿ´yZ¿×2ô„¡6ÏPD+˜•¡b™¨Þ¡’{Ь òÒ¬ŒÐЬŒøi\óˆ_0+#…œÔ÷‘2­©YùÆxVF"ЬŒú`\ë~5À¬ìwk\Ëþ+èÛwgeY˜•ýåÍ^s¶¿¶•6æX¡nm­6É{ic¶ý2®y\öP³2N¨YFã„Å\'Kòº‚ŒC¬†9=Ð c¸ïà¦Ìª£CÝÕØgÿ­ÙkÓ!ëgF’ÃüÆ#ÝCoÆSƒÄšÔ<„@+sqðûãêþëëMß"(’ —À ¯ŸesÛRX‡¬°ú½D1]êòrØ¥ëÞ–8¹¼]ÞÐØ¿äkpu}5]³ÀùI]̽­ÅÊÌù¹î‘ÃÖèäiT#SÁNûI¾'¶d`À°#ÜûÁ&ÃoˆÅ¼œï û a.£MÆ[dó(fgŒÈLR*•;§og>ýál=&\ö¯÷§>„ËF½øž*×J];uÜc÷'³/þÇý).}êP·‘ \öäm¤ƒ}š —õ9púÂem»l.«a–î¶óï¶¼ñ³3ÏÏ1„¯g†Æ \ö é«@¸ì€çº;’½µ°od/î’p™¾moŸ.;ÔúøÄ¢|D¸ìÀ+¶ÌpÇŽ¬ —)vNz~kû°oƒù̈́˞X€}¿ —•DýJ-ëZ¨ë_ùoc¶]ùÊÍÂ>ÞÏ•·É¤Å·ñ_ܯ,Õ\Ñ mÌ u²¹*b¦I¸¬bâT ©ß —eþil­A©£ò†«âÊ_³Y>*ói“õÍKöØÊÒ_£| ©‹r¸¢ÜMš3Iÿ4½‰oáÕ&yY’$R¿âšû½x(€Éég’UýÄ1PÍý0îAÍÍòû£š›q$DÍýÍoRÌ ü¿šû‹Ç©ÝÔ_ëEwõþê¯vËIתó$Õ>àõqÍ^¿Y¸,s½S«ÙüümÜÙ"ÜëÕ@1º´‡âäˆ=4P\kí¡–Ž¸Ê–-z?îl‹8å0ÐÓu`&XˆcP¡vèàÃãZ‡ Û,ÆõãÍ3dq\KëClžVØ¶Ì loêm•s&ÍÊP BôfÍʈdz2BÛ@³2re\ë¨ECÌʨƵŒ>ù¾}wVF ž•Ñ’ßC¸ŒlÚ˜ctÐÖ««ÂeH+©æ¶§ 0+mÎKž¾Å䃽Òö¾uiӞќ ÿ‰ªõ€C6‹ƒÙꨢ»ºlÒ¼tköÚtT…ËÔ~UoÆ‹á«Þ»Fó<^„gÍÅA—ÆÕôéëMšÂe_yœÂ —%ëî.[sŸÒÖú(ÿ½ƒÊeÝÙúä.ÛjÒeÈ{]#é2‘¤ËðÒeó8£»ü‚ Òe{'ªª]}÷ †uy'‰—©5•®ÇYÇ^¼lÜ£ÚT¼l壴R/^6èQ†d*^ö–GY^¼¬2úqf]å¬Çùe^½ì«¦œzY4ý FRå°ÇÉ9^¾ìæ'Ø(N¾,^òÞG4ÿ ®„×/ýxB«_ÝñD3*o{¼Óåç?6D•‘fù®ÇfÞJ=Ù¤q-¨Òn¾ÒêÇ6êg~¿¨rÚ3T^ø°¨Ô.EÒgˆY~úYu/µÁ«{=Ñ‘šˆY9ß.q¾šïŠù.3³*bÖÄm”‚¸>Ó™ㇺ5³FüàõÓý;m4Õ¸Fÿ /cÖÔýÑÅJ†™ZŒdØKñ2fýáå ²—1S%VÆìû…x³Øk‰åèlOdÛ“̱—1k¹9DWE[ŠcJùÑ{³!RZ©ÌhXfˆþÓ {!³V#ÃmYy€â¾~Ød/d6œe5êøL1nYýF\2Å }´nøjVŠÆ´¬~Hâ­I™†Ù+I»F›©ù!åµ*eÖ éÇbòbaflœXØçÆK™ñê@Ì2JìÕúG€¼&fvà,8#YÌìüàØ%f†ÊDâJšÌ-Fˆ ¤?Èk}üú¨3³:C¾ë"Й3»Ý©»‘p_”‡>Nïîê•íÛQŒÛM@^F±wÀV-ñ! ¯ ñ@½íÓcßfo»÷íóde½wßúö (Z”¼çQ»·@¢ßõù)ð–ŠØÆnuV¸ß”]øšó£j–uKˆŸÈ÷kªÖl̹#wCNÅO9["c~`‚J9EÜýg\Îù!~Êý¢;¬g);}sÖü_ÿ©èõoûvô8dý/Q ™9u¢jç½ä?E-î ¢Ÿ5‚?ä®NQ‹s6‹b%¢¶¨€å¿Ý2¿s? Äl{‡„-:fX³ôÒóÂ<Úø)ݧ¤…/fVuß3;r6äTÜÌð>ACæïÊó³;»÷ÕŒwõá†Ó6Ô¤ø)ÌêN›ÛWœýÎ!f¶Õ žWþo3;Úæ”³Ì 6§Ð¡;çtY˜SkñØÎ)”Z„5» u&<³r e‡ Þ€ðÌ ¹ÑÚ³ëèóMÖ绵[Zñoýô}ÁíºJ¡6xÿþéQu÷îé}»=DìÞívÿd»]ûçñÝÞ!˜˜îö/°Û?üÿö„„—ünÿ—¹ »}WØí·ÙÎ@¡sg´o´XogSâŠ1Q¬7= ìÚÀlz!»¾f³&t×=›£ÿÏlZ¡»ÇGóÇs‰ Eç\Î s©YLçQFQ+pWó;ú„Ú‰¿>2‡/èŸC·s˜ 0vä\›ÆFóBœ9œìæð›çðGïõm»Æa¦vÙL!FÒ)TcÈÐn¦˜#?Sì9a„Óò€g q‡øË!îùÛ;ÄÿÚ‡ºC¸}øØâÇ7Äg:÷áÙaB]÷³+™Œcyà/†Ê¸AH0òÿÜ þ÷¼¶š˜äã'ˆGïÈÆtÎèÒ0£ÈÇ䢯Ÿ¼ä ~ù=÷‡ý6ÝF?é€ïñóC÷íA¬º…ÙÑ;mÞK윷A¨ÑìÑ\ØRü«2]÷*íè`[Í@ ûx'»ùÚÔ·ííO>±œ»w3$‰Ñ”©ç€Ý2ÿ{yïŽ}x¶k{¶oƒÙ~of¶ÿy&Âlo°ÙFX³ó¶ùõ0ÛÌáD °WxÐæ±Âƒo>)¨„;CÎ}‚šv×tåÜ'¨iñ@WÎ}‚šA¸3äÜ'¨i±jWÎ}‚šöÑ•sŸ fî 9÷ jÚZWÎ}‚šö6Ú•sŸ ¦½…wåÜ'¨i9 ]9÷ jZ~IWÎ}‚šp—ê9÷ jZîSWNäóžát9(ÂI¾ºç ?"ÂIÕ ]¤F•±$iêlIÊ ²úaÄ8%^–,—lô—µ™eË¿låOn–\„}j%Än³ŽòRÉŲÌã«êŠzˆü&xBü‡Šdë$XÁ…¸DŸ£IçIp²A5ˆÔ`‚– /:³ª™Äõ:ªn¸8Î޸ϠÐý·Ù.›Ý¿Í:˜þµÕÁF1kµU½ô&bl’îh£F"Mð{#ä:›þ1®½é[›Eþlµ^ä/ë\Ö‰LŠÓ\;ôÍ6Óÿ~ÚDª½Ÿ\©ö~2â¯Ú›U—jo~S\{óÙCÔÞ|U¼©še·_‹ÍÚ¬ýágõ—ÛDý Æ­z0`—¸ö» î I²‰ÅÐDÇÄnS§ˆ“ð'S¦nXÛi pƒ¶Ó@aLm§bøj; üQ\õÀÛþ²ZäkIU·¨zm' ~šíÔòWñvj‘=m§AïŽ·Ó qèµ/«¼ê/Ûi°ù lÅfþC=ûîvj}IÜÁV ¤jnZ×ÇsÓzm<7Ã4š›a’ÈÔÜ {_s3üãq†¯ÿËÜ —Ÿª!¬ ¹!D®¹1‚š›ØôanFÊq’æÆ8ÔÜŒªˆ«5ï/s3êü8ûè§07£u[PG i³Ž~u¼Y÷ÿD¼Y÷—°®¶Ú˜÷Å›uì‰qícÛ‡جcµM$m8÷•±?1s›8ðÚ¬mÂÂÚ¬ãNŠkwšcæwÉdÚ*Í…€ß¸¿óðO›e5;ç£&Ú žQWÔ®Öû¥@ƒBÜ=ŠQ3ÞdÇeku¾¡ç}hŠv>óq‰ƒÌm`ó=¢ç­D—s·Â¤äÞV jvîN¶z(ÉÎòÕ±d§FPzQî244gE+(½kƒFgïn@4Ê}7ò–’AüøãZ…F¡3*˜ö8ǽø]ô-§Fùë%^G¹ˆV΄Úó=Rq´0ž–•%QÞ›™}ŸƒÒd{”¿öQjk”û\” Œò§?J­Œr›JÇŽFtÝ£ôŨàÈÇùvÅ”Ž˦ý«ÇÉ^Å-;§‡ÛgSU~ð8?¨xXéØîJKž µç–Ž•ÝÀ¿ü}äýO°*Š£KÇ*ú=žÐÙ œñx/*]÷¹|ùc#T>ö±©,ßôؼ—¯~l“”¾ðèn*}ÿ1Pñ¾ÇvéÚßoíÒ3åÜÇPFùŸƒ/å§>£Ê×>.ÐÓ7T'4ŽY^ÁRmð –Ot¤CªS‚{ A“æ»b¾Ë'­IubQØÞL1Œœ+æ»dΚP§î|MkÉÚœó]cU¨³ ZY³4û(¦©Åˆbþ°/ÔÙ ÷c€®W^¨S•X¡Îï’ uåΉÆ÷„1¶=ùÁ{¡Î\ÔÇ4J±CL)?ša/Ô9øåÜ”ì˜RìSÊ&8•éÓkø§ã öÐÄ«Wþ°Å©LçǸíA'rŸEõCâsM¦S×óÑŽd‹q‹ê‡¬ãšH§N”cc*ŸksZ̶‹é‹ Âq˜W`ŒRÌ™Š`þpj¼Hç8ˆ |?”c;mËùQ«½Dç0`ÆcÚ&ïNVΚ$:oä˜}5@Ù¾*À$Ê[Ž0ûÙ_»jÿ×ïÇ’^Ʋ.xáP’Ï[´U2ðoß?v›dàÉí’_JA2ÐP‘ <¼kqÁØ‘QO7tßæ’Å=ݢ݊7rå¬ÕQ¢dq´jš<>Ú£h~M{GkM{r!ΖW¥¦rÝ\^]=£Í×…ú§öMé³#sº£¸¾mðÈU_aUO\ß•=ƒõµE{¦ë[$k*ÐÔ©×[}@ z(BNe%=œ×'.¨ê±=¬ÆhS==<£·‡Î“JQ¬1w$Û!Ô8OÜûkzzºr‘ê9.©íÙTëäÍý¤Øõå/qµ:ÃÞ1“&gèÞKRí¬‰­]Á·ò×ÝĶƒbíëÝzÚîò µOj~´OÑüdc²¶}vS§ WݳgÏ^T}ì¹ó¦cÁÑ£köôUHRz4ýòûZ5$9Q"ûŸ=ûຉ‰ƒ‹FolìdK¹Y‚:#ºÌð~ãÕß×ôüÐz¼ËyßÁk.·–mlŒ¹§åœí¾WGk»ÎùAa7(E¾³ŠÌB;9ç•°Óä›**Q¾@[ÿbÆûÑÜ£¬IŸŒ†ÜŒ¸­çJfc³±J³ñj®Î‡Y“jíØ¢–Vþ×·µ'[ÛzñìVG'§×-C>p´Å ØŽ·9‚ˆé½:uûë‹>ªapsD(øëÓ¾qíÒïž²ï÷€‘k›3Y EÕÁª”PŒ¼àež¯Ææ”†÷å÷vî—Óyö~¹Ãɵ¥%ú|ñ-½ûú}uF JmÁŒ¬m©iMjsÔ†#Ÿ‡›h“Cl©Í$¬Îy¸E ¥ÛŸÎÞÈÓÄÈÛö?r³¼È®I¸¶a6èñÜo³7>(I‹?ßõ¼Be{c ù–vŸœ–°Qµ®ÏOÔ#>µwV,ž1ɃùH,å{AÕâW(~,ñ“ù^XµøsŠ/"Ž4ÂâªÅùŠGüT¾ïÞ‡¾DÖ—sÊ%鼊=–Hs¨/·ž–ó¦ÞÝõ¨4MKôÜ¢Ês*§3kêÂêÊ—û˜7+»Ãìœ2{ÞŸ™±qîf‰}R5Ð^ýÌJZ fÞƦ岡 föš)—0³»¨CßÇV-ÎU|ñSø>n¨ƒ™”T^:“gMr`&‘cèœÉ©a&‘xð3).é¢(¢ê·ÿß™œO¾Eÿs&õ^9æy0wŸÉÌÝ¢c‡˜;ä):ç®5Ì7?w’¥ˆ%Ù&I®a9C춪u‡Ü;›Ýó7ßÏßÍ5N)>»&:ŠØR‹MìD‹El‰Åæ;Îbs‰Q±9ÄŽµØlb¦>ÅÚû皻ļ!0ÎÌhdQeÙ´cæÏ_8Ucý¬Ç$`zç„­ã&¶#Ä®1/ÅDì–{oˆy)6bw‡Øçlop«êÜ[ÂÞ@ÂÄï Ѥ¨îî)£ž64ÄÞÃnÍ)hçûø.gI–4*]Í-L76åhà;ã#ìëò·=ÏÑÂÌ.ÏâíyŽÖvymÏ3÷'Yž…ÛóÌåý‰–çØíyæðþ˳`{žÙ¼_byæoÏÓçÁ^L £çUN›]ytÕ£kñ{{Ñî-¸{+© { J¿ß[âŒÄ\›Šø3ôÀ½æ⛵‹ì\¶ø›©™M%¸5Æ>Kɱh{pЉä8v{0ÑrÌßž£ï|´&½Ì¨=€@K'~¹)ìÃr{@A1ùJÜǽjhˆ= Y[ªC¶ŸÝ\ê­rÏãýÞûÙí|ß÷ÁÜfûÛ\‰ú˜[ÙƒØ=·a#çäçö¬ø^QB{|íB÷Š3†$¸WÀñ÷ bþ^a廳˜¿Wó÷ bA:Öß+ˆù{¼—}÷ íŠtoHP…}_f×Lh2â^1_¸|îpúëÝàX»œhw†…v—8‰ïc†@Ø÷þ>¹$¾Õ?¶~¼ï‘Û·ïý7·O‹í à!hÒ††˜[Ýåçs—oç{ ßsø>–ïy|ŸÈ÷ÑCÌ¥ä2Ó¹´÷ú>æ‹ûì hÓ¹”ù®fRï” †ˆÀÏšKçK•zæ y0‡_ÊÌ¡½ß÷)0‡yuÎáø0‡Æÿ½›C‘õcd¬*†¶´`èˆ;1îVŠÜ«÷ ƒu›CÌäëáÞTLßã=zpú1¾…?êñ-1oƒ42±[l®ι^æÚ/¸¹>—ÿX¦‘ääÌ›¤q½ä9s”Þ€2Ióѱy·Õ^?±&ŸfLRÊÙÎ^››sNz}ŽlŸ”ĽIÜ“ç'¸òMùüy©iæÏÏ"<ï ]Ùº<¡çò¸ÌŸ'8äÌ“äŽøðoç)Ÿ£ñqϵ™ ÍÃ6æÁs<æõ0Oß…ÍûÌÏ"šûæÉððÝÏïâýRÇãyàý<ÞŸäø;¼ŸËûoç÷sx‚ãë<ð~6ï—8žÎïû>ÀÊŸ±ÿâc‡"àè •ÚÉÑ œDíštï\stšÅžÀ7?íÝ÷ü^ÙÃÑQŽ¥ä𻣞c9N$‡ßõsȱ„~ôíÀÑY|ìPdPöqt4ûé¸(¾Ù7!Jµ°uÈ ŽŽÛÏ{9:õ÷}'pt;Gš}7{Íj:·ó_²½ý¸ 7g³FÄÃiH0WhD\ôŸu"®‰,*Ÿ=©–ÍÇcšèŽtÞNnšÌ„Ÿgñ_rÐýwZrèC·¨p›è¸?Uï}WÏo~;Os,ûüƒ?ykÚéow‹ë*ÿßíî͉›—̓óò©pkbFü¼àY‚µýЂ:áî‡n¡fFüÌÈöP§.K>3n^„ÈÓ»}·Õxr¦nó÷»Ó^Zùÿîw|]o3…LçLÝfŠ9ò3¥1· f4aNúÌÐz »r¢‹#Ó=3¼±7ýeÙ¢rZH‰fKŠ™Ý¯XyæÇêÅLbÀÆs¨ Ýx‹ÙFX ]³Åú<Ðp’îz'Ì™?O0Y–ÿß]3^ÃñöN¼µ.à-óåfY8MžfÄÞO-|Oäw×krÎY³/3X*¸BïWÔåN‰sÈ—¿Ãßßk4‹Uýeê»»å<›Âvkòä»ðó°•6ê?þ –}``·]·ºç¶ÿ»ßê·ƒïð„½„Ѥ6í¢;Ž<Þ·tåî1¼kӬߠ®êX¤z•³[à1îæí]¬}gnK6†6Œ´LìXw+²±>öÝvæ¤:ãLV”UŠ·úeóçÍú/œ@¿ã˜o¯AÅ}A–Í|ã’²sßmUñn¾5"é|_énTÑÓÐ\þ7CRÌ÷ØGæ»MómnIš]S¿›ã¾´gzæx‚Íñâ>6ÇŒpç¯ s¬ÙMçøªxtkÎü«!)æø˜Gæxôšs™cÇ)¡éà™·}"Ìðx›áÿÄ?|p†3½;mžeg÷<¯ ó¬NçYæ4ÐÕÂ>ÆSÆ 9pSøï³|s÷f·[Û™Áy]ÉÝ »r³ Ýüö… ñôuÍç‚éCðC„ݧ«¥9LgRú½fÇJ‡ôiÎF\÷Lî|l&Ï&ß9;fr9V Îä²À¥x˜õÌ®œ¬k«"§uv oÎáÍŠðf)ožÊ›ÓÛys6o–…7Kúg˜ûûÒGførfxÓ#7žñÑáE•³Ìú=àýñ ¿pÓ^ÍgXs›Îð‹\¢]¸1¯ìÓ*Ùsßùf÷¾"wtñ‹Ž©ŠòG1¿ ‹O²ˆâ ñ£B¼H\vðÒxñ¹!ÞB|Nˆ·Ÿâh¶‡ø¶ªuÿõ®d¸Ö:˜ž<ÿ˜©¸°]6ïÉ]Z»+ÙÙ“I’.~u~KÒ¼¥³'ÅäDòÅe8oÑÐÏ5Ñÿv°ç©UçåOY³::ºª;ŠãHfkîˆJLJ{s4ÇÞ7øþhÞŸlï¾?Š÷Kíý¢Á÷óx’½_8ø~.ïO´÷ǾŸÃûìý‚Á÷³y·¤ê4Þ{N o£„Þö}À¥ùœ¸4ËL]0(.vW:¹p£ÃîÇNŒß?/¥7r •~å‡ =±v¹ýRœ²Îí—bßü¢…¡÷Úæ½öÇî÷óx¯ý`Þk?ì~?‡wš½ï˜½íû`þÏIÏ_8tÌ;ñÇaþ5óéüË Ú²ƒÐw~æ•CCÜT´“ÑNÖ›ã× Mlær[4ìl«Þmo|{”½]<øvž½]4øv®½]8øv޽=vðíl{»`ðm{®à·¢¾ø"·º[ süRüxŸ¼|pŸ|%ìítŸüT|£ ÿlㆨ¸Ñ½e÷’®nòöp£›ÀNæ úб3)ïßè4‡éL¾‚Qîø0Þ³Žb‚g¿:»Ðk›¥ÜúìMƧÏÞdúìMÆ›ÏÞd\ùìMÆÏÞdœøìMߨo‹°Ÿî¶} `ÿL¿,Øõ ÚgŸ ±{Bìë™X<,Äüm Ïè{ç¶°w´kÒ½s]Ì£¶¼¬bˆ ž½›õ*¯>{“ñè³7o>{Ó÷ÁžŸÞ} ÜlŒs¤ßÄüž æ÷±OÙÜËnVï&Ÿ{Íz:÷¯Šo ­pæžóó!,n Wm¿)do»n ÙÛ®›Bö¶ë¦½íº)do»n ÙÛÚMw}'Ü,zঀ´}7ítŸÈb>TCå+ö2B n‰´Ä÷ù¦³»ËA÷„ü¶`î—}hÄ}ËñN™>gÈþæßöY¬Ô<¦³)—31vʆ¢«¿íÜ!"n Wq[87:º$‚g1»°+zz‹ã*\Å}AÚ¨ïàœÌ»ÅýïŽâÝRÞ-ê7w'ñnaÿ»¹¼;‘wÇö¿›Ã»x· ÿáèÝüþw}`ÊëÝÎ8óèß_~¼3¤w½{gÜv†qÃãvÆëá¼èF=Œ‘½fãÍù¿ð2û ØÁŸwBaª‡8ÔÛä›AܰqÄš½v޹#¨îÝÚ<â—=ôÏ%Û߃e?³îfj¿ËçO`w݊›÷f| ñÑäKPAz3·‹ç×å—PÓ­0õà8l}y~ñ%àáßsõµ­»âûÔø±žžÄ:zü+#Š»¾÷œÎK0EwÆÁ–ã/6ç™Ò3’–ã7çÐÜŠWas·ú~jµt-ŽŠ»ºs:‡àX<Àa•½iÃa]0ôŸ\œ™Ý›koU;.Ýwo`Å`ËO÷×—ì>džëå”sOÐ^‹²´ïR½!‰Ñ:1;«ã­åï°¯Ö #¯ø,ûjÕÈâ’O3Ûr¦CέÑHñÐåMÃäÝ [Q¾kîOäÉ·ŒÝ>—«ý™ö9úHØ!Ò ³;¤ï.;¶.;1Ó=a‡ho¤;DN_bø™Ã¹«½|ˆVíuxµUÌo^¡}z oÎá™c÷f)ožÊ3Çî͉¼9›7fŽÝ›¾8ðK†àÀcTs^™ú7z+ÿÆ¿‘Ük½ö¯à‚ŸRulõl䳿$š:ÚÚK’‰¦dSªue¢5YŸlM6×JÌÖÍ¿ŒGc€s$ã÷Ú>‘}¤†ª(žívÔJ°Iœr_s«Ýë²QCáÿh„ÝÀÌåmþáÌÕøîö³3ÕÞas¦ÅtMŠJƒŽØå6—º íÖZúLàÇ3O~¶dÑ3F›m$µ¼~î¾ ¤küŽœêüެŽ÷®á° Oóö”þ·ð6¤ kÞžÜÿïÒ|4o—ö¿ÅŸô`ÍÛ“úßîí‰ýoñy Xóö„þ·xA‡Ä¼Õ-¦ú¶ïÜ}›v½xÏߥ¾ý«w™Bì¶Í^d¾’‰¥ü6bþ>CÌï,b^»bXâÞ€%´§Òõ3ñª…ß]åCFxÈ8LwŠŸsçùdo–†7xÇ8–7'†7øÆ˜Ï›%áM_¼7·#úÀƒ™V¾ç¼óœ7bžóFÌsÞ~v~Ôœ§3ÿîXnXå-?‚óv3¼¶­§ŒåÍqÅ\2¼›5\—LoçÙÛEƒoçØÛcß¶ëmêñ…w}!pÐæ¯½/}`ç[ú4áòùÖL§óýs1¯}?xkoîP¼öý:ÝM¼ï^û!E•ø4ì{àî&ŸóÚ5‡éLþB|Øí©wl¹»õõà)ðÛ;}!ž{§¤Àwïôxïžÿ½ÓçQàÁwz; |øN?G})ðâÍm@|ç¾7nÒVxø6 =•î¬÷Ä«b4ØãgObÂRΉOý eo2ÿGÙ›ÌïQß œx·#ú|¸ üâŽÛ€æ<ù_Šoûã£ä狆°¸ ˆO¾÷6½íº dok·ÞõpX°hèÛ€´Ž¾ h¦Óù~_|ØÆä{‡ª¸ Œâ6 ¥pæ ÎYûмyÿŽÛ€æ0IYýfçŽÁCÈ/}y(æA£ÙÄœF³‰9fëKA£ù{’•?áCÊÓÁÃÍšét¾?sçÆ`Ùöýÿ8ˆFóˆ Ñlb})h4/‚@£·Àû4š5»é8±0Ù?øþ!|4š—A ÑŒÕ|¯ÑŒ©Þ}Íšátžå¥Cø Úͧ;æ¡Õò‘hV ¬\£Ïò‚=®íÊß}·®Óá—»¶«ž¸8Ç}%赈fhùªg<ªØüÏØX ÃÝ3:?`cÍe:£wÆþJÛðÉõËÿO£¯¯ÍOéxnƒP9´蜼´i^óxËd¾ÝÞŸ¾YnϺö"òZïzâ«2ËÎ'IG-ókaßS‹½kRKê_/­¥ïƒ°Éí4¿ç¶ëŸw¯ î„[ÃNÐHw‚ü.Ç·P†<ì—à0iФ{/·Û^xÃ={?³ÛºúwC-Ï“ZÇ;^…ãŸñæÊ÷,ä¾RSN[þn±ãSt½Ã—jÊwËß-t<Š®wøZM¹pù»Ž?Ñõ-ê”'çßµÞéˆݽ·íúß»G|ŽÿŽov¼¹Óo¨í ,xÅ>øÄn ±»BÌëûf&{o+Ä&„Ø|ÛS¿:¸§¾ð¥vSº§äÓ-Fûr›åס-g¹=xFB7úxâðyðòCü8âpxð„D|1qx;x¼!¾ˆ8\<_H~~ˆKÜx·sñÄñtÇxß÷õî¾pÆÔ¡ô¢>98ó;6Ñœ§3/-Y¼`€—ÆO?khˆ™—ÖzOfÆÍ]Öê;™™6·Y«çdfØÜgU“Ó˜&Þ÷Á̶ÚÌö= mòkƒ3¼]iNÓ™ýt̉8¯»¯"‚¡uÞŠÐÏXdÌÌdß ^4“}xêûõœÍa:“Òé33ùµ(ú‡QÁSY=‚ûê¸ø¶Ú—ÂLö=àŸâ7v̤æ0Iyψ×ÈßþÜx–{Ë1]9Ù…†g¹³H;ßÄÁ³ÜW޲8x–»Ê<‹ƒg¹§Ìµ8x–;Ê‹ƒg¹ŸÌ¶8xÖxxpñ>ð¬Îm}àÙßÚgy7óÒŠÏOâ÷¢!#ð,Ü"3ãÏÂ/23íð,#3ÃÏâ'ÚÌlß x–iŸ3ûÛ;ð¬æ4Ù߉±Óx|rüÁ§‡ŒÀ³à&3£Ï2wf&ûTðžÒ÷žýÝØIs˜ÎägÿÆè üN|¾Oè1_J×8=¥lÎvœ ‘ígµµ×„òÎt{Ñúâæ3ÏbÜ{æXŒ[O»ÅÀ±ßõyõ}¦»‚¢Ç /=êKä÷g«t—4Oélý~ìÍo<ú ÷¼ô‰Ùú0³µ–Ù*eöޟ䵌ÙÚ¡›ÙC§Ì×¢ªÇîÐP¿CCõn4Tsú©ãÐO•+¼7—EÓOžF\õÝŠ;¸7ããù§÷é§Îïzú©òX¿âŸ\mmç>®Ê=Ô÷gèQÞ7ìO‹‹OÎÓy —ì3fXŽ~›sèòyÆ+,‡ÆuOÍÖwõSý®f'3÷vM|]ÐJý»æîÙ5IaØ5Ú/鮇“=~: _úöP{ÜpdÝ71·ÇMÌíqë«`[Îìÿ›­?ܱÇ5Oél}žÿÒ =xÏ(ú~Ö³5vp¶F;jy«ÜXÍ ñ¶Ïº5xŠú3ô…{f¨êE“¹ñ3$í^ ÷Á¤øò¿>1Cêí5§1CfHÂ`¡Ï3Ce7C÷hç2CÂ1{uu׈gºµ{lqÉÍÌV%ö&»5ëfn3fôr¥Ä×Þ f(£—» ̰ m —+ÕÔÕ=awæV˜ÃÌ­ðÏNú÷q…óeôsÿßÜ~qp÷­ s«YMçVÉî;û•â!BvŸåjÿ¿’j÷û¹ñ3$N ÞøÁËÃ_ï½ùîukïÝËÞ”¿êÛÌÑÎ+_6GdŽJÑQƒs4ÂÍ‹´Gzžr¦3$]ÌÔQ»[=2C=w«Û‚§­ŸÌQýn…­56S28SAˆ9ò3%n´™)íª¿¹}‘™²ôÿ7SðÎýLI‹õá™bŽ¢òÔNÊ%EûhXo.óÇ‚>Ïe²7ý3ÿ‹–Sz-{sÚyíÊù—ÛsÚ½Ù•SdoN‹WºrþÕöœ›vå”Wþ½9íM +çßlÏio4]9µ»öæ´7Ä®œ_ÝžÓÞt»rЧ´7§½ÍwåüÛí9-£+ç×·ç´\®œßØžÓr®ºrÊËîÞœ–;וóï·ç´É®œßÜžÓri»rþÃöœ–'Þ•ó·ç´z]9ÿi{N«#Ñ•Sú~{sZ-‘®œßÞžÓêÈtå÷}oN«-Ô•óþí9­FÔîœÆ$hoN«Ö•“¤½9­¾\WN.½9­ŽbWNÀYoN«‡Ù•“9èÍi5R»rJ=loN«¥Û•SŽöæ´šÑ]9uñÚ›ÓêwåÄVioN«ûÞ•SŒ€½9­æWΦí9­÷ƒ®œbìÍi=GtåDÛ°7§õåÑ•s“½9­ÿ“®œèãõæ´~^ºrò 7§õ”Ó•“SUoNë?¨+'^/{sZ¯L]9¹ïôæ´ž§ºrÙžÓúîêÊ©ûäޜ֫YWΡÛsZq]9‡mÏiýàuå¾=§õØ•“MoNëç°+çÈí9­§Ç®œâ4ìÍiý\våÜo{Nëñ³+§üÙíÍi}’våÜ{N듵+ç˜í9­_Ù®œc·ç´žp»rr¿ëÍi}övå·=§õTÜ•ó€í9­箜nÏi½cwå'soNë)¼+çAÛsZ_ç]9¥?±7§õÖÞ•óí9­Ïú®œXîÍi=òwåäžÚ›ó)›sÊ›íÞœgmÎ9i{Î36çÄnmoÎå›s¶=çi›sNÙžó”Í9¹=÷æ\º9'¾Œ{sž¸9ç´í9å fONÞõæ¤oõœø—ïÍÉ^©çœ¹='X»žsÖöœ&YwNùíÞ›“ÛA=ç‘ÛsrרåܘCNãG¢Ø›sñr›Ì;ù½09ØËõ¼§Àä`?ÖsðÎç`ïÖsðN9*½1ÆUÍ).?~¶¬Ë{$ÜË]«ö³>¢£\‡Õ|8óG͇kO¨æ©¥qÍÓFPó4yLWÍÓT£jž&/3ªyºú­š§³¨yºô›!ä¥\3*â}0Cg탿Œ{2sÙP=™I]\fŠ&TÊiT:ë8¾uÚ¥%¼pDI\óç9´›Õ ¾=¯¯fó;BûVu)<­ºŽÔS(úHáÕu¤ôàTWû¢¸®öÏ]×nuõôÙqWObÐedù”¸ÞåïÜ&ÏO#z—m“ž‹Òr±ÍÕ‹šPõb…&M½X!G_êÅ mQõâ Í„zq†nŽêź” œùŒ¸gž2@/ÎÔT«gê¤^œ)V³zq–îÁêÅYB^êÅÙºCªg‹) ^œ-6…¦üìKã^<å MÓýXõOÿE»æ)Ú‰Ú5O‘O5íš§j"´ÓŸ*Ü¡]öÔÏÄU>íu©òiꡪ|šz«*ÏÊT•çh›«Ês4ªòcâ*W>xId5«Ž¼f&ÕüVj®´cVJ@{k¥˜ÒÚΫÄQÎUBNº¯’+q¡€UºþèÍ*¡|ÍÝ*¡mÙUBBò«¤ )Y¥í.ÇsÅHÐv?W—(ís…5ŸçŠ"Ô.µ\ÏÕAJç^÷ö¼Šþ êڗݘà<6tžð½&è<*¢‹«…]ÔµÕÂfš Õâë 7¯Ñ5Z]X£í-¼¶F×jm‹5ºÌJ?a¸Ôʵ}!8°k¹•µ\ —NÒZn^p_Ö‚ÿcæm­ü«©Þµøˆa5¬E³rç³Acê>ŸË6÷Éóßwù‚g€ù.ÐMC=¿@ü>õüm õ`Ý Ö ‘¨öuò  ž¯ÓvQÏ× «çëu÷UÏ×ë–¡ž¯'S=_/ŸYêÎznJðeŸ©¾¨gÏüØP={¦z ž]¨©VÏ.H=»PlõlƒXêÙ†câí±A[^Ûcƒ<|k«oïZ[csÒØ Ý a¸ ÂtêÝEškáË„ïÕ»‹Ø\ÌíElæö"xÁp°.’/)ñ?.’–¡ºsý—å¨úF[âžoüö_öùÅbVªË벩._,,¢._LÇèò&q%ÔåMq•Ïšú—*Ÿ%|–تòYºeªÊK¦ÆU^"´ª¼D3¢í½_Ýìͺ!i†6kókþ·Åi{oÑþ Ø‚v³s)ø~ä¥WÇ]ºlâPóÙʸg—é.«ž]¦¹WÏž­¨gÏÖ]={6= g—‹ó¤ž].ü¥ž].¨ž=Ç&ç9ÿ4@OžKèÉs¥½¨Øs…ùÔ“çªêÉó&Å=yžö¬vÒótÿ×Nzž4 ´“ž'ÝõæyÒèЄoÕôk'mÕ”k'mÕžÖNÚ .`®¶Êƒ°vÒVy¥ÓNÚ*Moí¤­h™°“žK„ô|øPì¤ç3Ïì¤çŸ÷üŠáÙWè^ ._ÁUŽ._!•º|¥p³º|¥®„êò•‹«Üö†¡&k›ñ_¶ ªæ«„ UóUºi¨æ«tÓPÍW×|ÍãM¡î/Ð…KÓõ1Ôt/x”!„ˆ^¨-¾Pó 4ôBmMí …Á5¥/Òô ¿ˆÝÍT¾ˆ\\-wÀ¢Ax5Ä\”vȉ«®x;äxFÓ¿CÊhšúƒSq8ùb!E¡’ÿé%Oq\¬Þ[_ÿÚé—è6¥N¿DH]~‰]êôKÅ2R—^ê$ŒõNƒ:ýR]Ô¡ké £k¹]Ðéké:~{ o±/S§5¥/ÃÉ&{ùè¡:÷rã½\NIµ^.Giªø§t®W7JHD{á§nˆ;ðŠ—°^ÁPó+tÅVͯªj~¥.§ªù•ÚUªùú½âš_µj(€Ë«tEPͯ’ʘj~•YÊõjMªj~µXªù†ãš_»é^ö¯5¿VwMõk5íBo¯Õ­NÓý:aQ1¦^§[Š*yۼÞ!¯/¼Sr­è¸´¼^½SO_/¦…zúzñçÔ‹uMPOoÔµU=½Qõ -½AèI(é R–О}ƒfA¨è†Ðß(×íÚ^o„aúyìÐΛ¾÷e×ø¡f—®êÙ.Û7»lß¼ÙöÍ›mß¼Yj’B?­¢PçO‹Ù¥yúiÝf…:ßÒ÷ä-7 Г›4_êÉMºP©'7‰Í®žÜ¤ZÕ“·ª7êÉ[µŸ4Gobê|«³æé­b¨7o‡Psõ6±Š´Ýß&Ö®Þ¼MûAsö¶Æ={û¾Ao×5P]z»t'Ô¥·ë>¦Ên—G]ºY7vuéæ¿Ž«|Ǫ¿TùÛ“ï°=ùÛ“ï´=ùNÛ“ï’ê€fá]b*hÞ%u)õþÝÕë[˜vÊ-rF¡ò3Ì;ågtýÑNùYcyýlÇPóû³Â“êÙÏJIX=ûY©¡©gïÖ®QÏÞ-<©žÝ*Å í”[uaÔN¹UªSšÛŸÓ•@;åç>÷äç÷  '?/ޝzò󺆪'?¯}§žü‚jUO~A½QO~AÊJš£_zšvÊ/è*ªyºM lõæ6174W·‰¢r›Ô&´SnÓW®Û~÷ì=/úË´¿G:;êÒ{ÄR—Þ#êÒ/ŠË£.ý¢ø§êÒ/þ"®ò—Öÿ¥Ê_N³÷^©hh¼WûTý|¯ðŠÐñûÄÓœ¼O{Rxà}Íñ ¼O¬&õúý/Ž«ÿß Àaø€¹zñ]„Ô‹+©ЕZ½¸]s§^Ü.¯zq»XêÅíRÖÑ~ptÜ‹¾c(€^|PøW½ø P/>¤k°zñ!Ý÷Õ‹ «;F½ø°¦R½ø°îFÚW6NöÓÿ2•whº4ûwØþ»ÓÄîô±;ýGn‹«üåo°?jHë£âû«æê§š?*NŸj¾SU¨æ;u›Ô†¾Sü-]vî·NÓ÷+ºÞêFò+ô†ü SÀ]ôc]q>öƒ¡zôqéQh*?®Zû¸ø~Âôw© mí»´t½K7]mì»ÄgÕTÞ%ÍBõãWµAtÃþÕiq~&ÚC¿ª+•nì¿*^‚ªýÕ_Å=ûÄß÷ßt@)ôû»ã\üK?©Ìªø“TË”}RWhMÙ'åÆGSö)U¨)û”©,|:ÿ/ûãÓô—*?-N±ªüôËâ*?­û¿ªüuq‘Uå¯Û­ôîÏÿ¥ÊßÐ<«ÊßÐíPUþwªü áTUù›b˜©ÊßEUþÖ¬¿Tù[Ò³R•¿Å®¡Êß2T•ŸÑ…FU~Fl+Uù™‰«üíÿ¥Êß6¶ÜïˆÕ©*G 4ªòwÄT•¿+ì *w~\ågò—*OhAUþž£ªü=!FUù{º©ÊßW&UùûgÄUþÁ‡ÿRåhÛ©ÊÏéÖ¡*?§[‡ªüœÜ•ªÊ?T)ªòYùù#þRåç…¨tAû¼4ñ´ç?/´¬=÷mEíä/ˆG!„ô…«¼çøAÆ’Ee]U¦w´{tÏQ•÷h“«Ê{tãP•_ÞÒÆÿ¢Âd_ÔVІ0‚ªb üÛöÀ‹Y¤Yþcø€°lÿTÃÕöuÕU—þ˜ú¸[ÿ±6¿˜ ,†‹ns_zaܵ/}~)\ëZ tOÊŸÐzø'b|«‡"6•zø'BwêÁŸè>£IùÓ“ãšÿôŸÿ2)&Æ£ªü3ívUùgb*¨Ê?“©ªü3]/„\¿ÜWùå¯ÿ¥Ê?×DUþ¹î¤ªòÏ…ÄT埫‡ªî/¤þ£ÝòbKißü…p´Ðë_êjª¹üKÝÄ¢ùË‹ã.ÈÀ{óõ•Ç=ù uÓ“¯È)¼zòê£ó%¢zóWgÇ5ÿuî_:ÿ×bäi«þ5•°UÿZŒ?1ÿZœañOþF·>½ýãDýÍõƒ[õñ*ïÕNUÞ+Ĩ*ï¢U•÷JKGUÞ+–’ªüªr«Ê¯~ôߪŒã¬‘.-¤«¸¨‰Ô^pb.³ G0Pö;ÓNžóÝ ø+µ\ÕAÐÙ ø“µèÕÖ^pQÈ*Kx¢A'"v×wfÄ+ q·¢wb>*»‡( yFXf~ã-¦ af™«Ãü[D/yý‡yίM¥µ}Íj+¦k£ _1U­Ü=î vË€'-'Sò,îúÄo´*JkûºÕÖ®*|mÄTµ™c³é”‡:ÀwFÊJ?°¶ WE&Â4Áâ¥/y¸ÿ_\ì™®¢¿°Ê›ÝD¡,ä»׌S; !Ê'1ôix‡þ)x|ê¡Júót]L'»ú'u.l-Èkä®A[ã—Ó5²c@U?©Ñ÷ÄÖ?À*ñ~–›û;Âbä„gçû‚6Û¦Ô1긋-RglŒ­lfð+î ”ÏmÞLbò¦Ù5µ Íí©¶e‰™Ó'NO¶ØžjIÌH5Ö%['6ÕÔ.IÕ.k›¾¦,‹r¾U:nl”s}é¸qQÎ ¥ãÆG97–Ž;"*(m®iJ4nL”sSé¸ QΥ㋣œ;KÇŠr~Y:~t”³ocjicry²ñ qà€‹æ×´w´Ö´'¦ZëæW¥¦®lOί®žÑå-Z^ÓØ‘Œ²G¥s,Z'1¹”d=fUêœá H޽71×Gy…Eó“ÉÚöÙMz¥G³gÏ^T}ì¹ó¦/à^5£¨ººmYëèŽ(çMMQÖqéçQÎ5ãiÿ]m|•ß_§âTîeËèÇŸ(Ë¢8ËÆŽ14üü6¾Jóã$Ñ{ôÞ>ŸÖ1й9´¯Ò5Kh›žß¤çÇ_UeÿSGI”}aßjLEyÌèšdg”ÛX:fô„(÷ŒÒ1c&D×µ´2¼jâéÉ¥ míÉÖ¶^ûË¢üaq0*¸¾ºº¾¡QEŽ+ªwY…iF55EY Qîy¥cÆr ÜJ=k[jZ“êCµb[Q²³6ÙâÄðó—g4,hc^Šï¡5r~Qå‚9•ÓŽ™{xÒ\=¬©_~AQk²¦®zyCk{GMcµ›¥ŽòÖWR_åë©‹{ÍK¶¥—'g§êZ›¢‚=’ÉÚŽvN±/nJ¶×T4×§¢¬“›RuófÏH‘ nw±E5í5Qö_UÔEÙë*VDÙ¯©€Z5¶®¡­¥qÔxøáow¡Ì}Ô\ÑYÑér—&×u45­Œr¾[QÇHW±‚¯·T,å¿ÉRÄj©MÕ%™C­Ä‹[xú©Öd[œèÂõ©–QQîçKǰ4KËü„XßlMHñ{¥cØ›¥›|ZkÁîñ´…Ò1GG¹?ÁëÌÂcæÏ_ø{Û@åÚ0ŽÏºoµ†úQ^{”Ó^T9mvåÑU¿¯®xtéØQÀ¥–ô»®xН,;†¤/°¤ßµmS|_騱cY¦ûg<ÖýâJÇŽcÔ>m£¶äQZÅï—Žå” |Úï¢+þ˜´íQÞ}Úïyë+>­tì°ì.´Áþž· âsJÇ–€+o‘unÚ³ø· $yQª%ÊY:v° Yi¿×žSȨöÜ‹¯†% fÄÍyÜZCi{fmk”ûÜÒqÅ€Çýݰ/>öѱÝY:n 8ôK–ô{q7ØUI¶¤ßÙ¯u…jw•Ïž }$Y ˆXgÆ7Æ#·¸®ò·#WùyÑŠÖ†öäÃh¨8²t\ B:Œçò´‡|GSûk{pµÏ ¶vz=¥ãʧkš×=<Áÿ°9XTY¾¨êñꊣÈ:ýÔQÐã³ZšÝ¶¬¡¾=Ê­âø0+ÊúEÚ€ËwÆü2.G¢€œúíøNÊ×”ŽÃ=ã2g-é{)ßS:ÄœP¥œ5~¯©Å(/ y$9O=nöüc¦V]W9ï¡´ƒKÇÁZ½Ó™;ã÷.…£Ü±¥GŒâlóKú½]VzÄ4N¼d{úŒG ýzéG°Ìþ˜Ù9åÑýµ‡§¸iûA?G•QÅd±%ý^?g—1a\”ý!gÕöûý|]i 3ôÕÏS~Ÿò½¥%cGáƒP)Ï<úÑ*ï åì(ëµiãCßI9¿´„Í íiæ;)Ÿ^:õÁølטïUù¼Ò £ì›Ü^[²àѤÛIªS×Çÿ`§?Ê=·t æJ'pºJŠþà ?Êž[ÔÀ}heõ¨Ñœ#Ïïhv7Ϩœ†;þòE ¸µßМ¬›ën:VS¸¡•£Oñrú0-Êþè\ÂG¹W’sv”ý‚?¸Fr¿S:Skrœ…G¹•N`aVž÷¸óíâ´Ò ,Ëä½°5åÖ”NЮý›ËQÞòÒQÅ ; ýâ(ïR’NZë¸õ}³¾¥kIÉR~Öüß–î$çL ã?x-íINMg|ç¼­F»¸Só†Ñ\¥ç‘^G¡Â)´[ZzYu*øGCž¥7“u6£ø¾õÊ(÷ˆ¢š% ø¿jO6µDyg—Žš?þ§¥uÊ)àòpzXº‚œÓ˜ªÏýÁ‰`ézrjIĺD}ß)_éWädKèø§u¥ÝÉ vû±Ó·RB95 ÿàD­t9Ù,ãÿબt9ÅQˆõw\¥õäœ J|Ú\_1ÓÓ‹™µßüƒË©Ò'É ´üÚ6•î"ç fíø?8J*å(§ú9øî‰Jû‘S÷ãøpÄêž>Ž[éŸHY8¥j.L¢MOô%zýmŽ}bª¢>1´Ñ¸'vBô‰'VNt×-úç'f4ÿ‰}ýÃë>:þ 4ÝøX‰šŸÀBÑ·Ÿ€Zñîvɨ'¡crÜÍüHX›èû@;ºê _ù»Ç¯ñ¸?!â×üáÊÿôW”ò[;Ѩ¨Þâƒÿp_ŠùÃý*~Ënnñ¿þá´—\ûäí0šòÄm2*âò5%x„Q•Ì’«•¼æI6XòÓ'ùf…Ïü‘ÚV™ú8u®rÓãܼÂÒãþ=ïOæ?ÑŸóodÉÂÞdd ªüˆô™¬’Všä>I\-¼ñ$ÚâWÿÄÔ]ú'>ðÿF°®¼n ¡»|ÄêxüWÛèóѯ¶Òîã¦mtýè›[éþzßeR7°Š™‚ÂÿøK/E¤hJ´’XE½n©,ìmGG)%t*±w»¡÷¶WZµ½VL鲯¸Áõ¾H8§Þ;]¥4¢Ñôám}Q-{ú⦸VLÂEý$>!/UqÉ„<"–Ϋ©£RÔý$=!¿.»wŒdNÝ;N×B…Øj$nÑ_rjP¶Ë¤.Ò»Ø\~uÄäï8H‹$DåP¦¶:¥´úÏ»Ô&ÉSX ÎJ†8^ian…g…}o§»ÂŒÃ66ë/C%±’æ DVØ÷°…+L²$¦°a´n¤”J4UD#$?A8®,)”˜²F!,5ÆÙ:ŠvîEU2jòcåŠBЙ¢Æ0¶ã¤—eq]ZÔ÷n6¶(ý7ECÄm¼3û䋲È2-êûVæMQ˜  ¨ñ¼˜à\TÙ©JÁ­›ª€]W–4bLYœä ßù-à!vº¾¹]a’2…MBÃiŠs–æ ~VØ<ݛ¤0c ›‚Ôú4‰‹e…¹“CVØ÷ïg¶0DÓ(l:<3c¸âö–»|¤{ëû<[–4ÔMY3tGHY³œž^ähægWŽDL9G€ÃÚã@SŽï<åü¤éRœ2å´cÕa®3¿¨¦‡ƒMÿñÊ•…UÊš œš/í&·ýÑË­ÀïßÀ\QÒ3EÍG k¡3,拪.ëï_á\Q’85E-Dø¸X]ÍU]Öß¿º¢ÔqSÔqÈ¥/‘,¦«tr”Š×—GW„„®LKP2¡[œVýâxâÌêÊ‘‘SÎIœ%öCe ò‹Ýô“ÍŽ& z éi˜0¥” ú!¿À$é8SÐÓð9²2ÆÊýŸA†‰~Ìn°%¡ÁMI+AÊç9KhÂrUFXî' W˜íLaçqº¹ ö3ÓÜËë`«ÿˆæáŠ’Ê¢)êîCÏ”TtZT†?~D4qEIàÏõL°ÜFçr”©J©-fª~@tq% ™’6"‚÷,‰ÇiÓ§¼múpl\94å< ¯6—IW޶çœÚþ#Š+J*¦¨Ëw~Ž$âÒ¢²YúÉÈ¥µiŠzç¬+äÙËÌRJk2³ô’“+I£nJº‚²Ímd‹zR•Ù¢ßgX¹‚æLAò/ä ]¦ °»lAR„6]ÃyI,èppd2 ¾Ï,³aN‚‚^"öÀb Ðæû¬6[”’MA/ç°ò Yzq-Ï:ôCF-Hô¦ WàQáU±a¸æ^ ËãÇŒ>[”ôrMQ¯ÂðÁkcDgàã:xó=F¡+I’ׂé^Oó))§0ª¤]IÒR6%½C"»$ÌH—2%]ú!ŸÒ•„H0%íBKò-òPâKÊÿC:§+IÄtSÒ[}»ÄE¨ÉKú!›Ô•$ÉSÒÛªwÄ3ß๫ZÓß§±ºbäáÁófýgc“|ýi–þüBëJš%ý,z¼?;ÿµ%e-ÿ!ƒ×•$r„)éçú÷Hî×Á™0E? »’$cbJzŠØ¿$Ÿ4@CÏW~Ÿ»ìÊÁ åü9Þas ²‹€ Â¿Œõ*ô~œ3|ÐùAµåØã”m[´€MADÒü‰¥º‚ò³Êèâ¶ ÌúPÐó~9Æë{x~ºÃ? «Û¢¤ÜjŠúeûÇb V•1äMQ?$Ì»¢ÕMQCøÎk/{=¥è›½þ¾+IJ²¦¤Op)þt,@¬iòfš¾¯à íÂôiŽwËc€+(_ ?P*HõxMAwcÞç·dãÅ”/¨$Ø‚dÇÁô[xðøm\ø‚òò…[n̦ ßF¼ý³±²¹Ë倨CØ‚0#CA˜Íøçq×”Ãë(S¤Úæ ? |>é6e3ôCUŒTÀØôy@ë=Òöί¯\tÓëëιrë` º‡n|)½6¼H~óøAAB¦ /áûáO¥oœWДHlAò_c ú3þÙwÎîÃiË¿§‚b BÚŸ‚¾Œ‹¯Ä”‚ô*“¶ü'av›‚¾XÿëØ d µÒ–ÿ¤ ]òLAÍåùoä–%¿`§-ÿžòŒ-HaSÐß ëýÕ˜±b·´C?)褞ʹ å¡|%#ƒå“E ¾?K`*Þ±ÄÇc~Üÿù-Æ‹ÀâøN_vÈï+oΣ™†»X1G–6§Z“ÑEö}sÞŠ¢1©ÂáÅ­¸4XÜ<\oéG1V©ŸÔ\Óv"ïLNF·kÕOj®GoË?zK>x-±jý$y©õÇ:ðä£Ùbäl°½(ZŒžùz}Ô+Ýû‰O/Ÿºàèèð¶·†þgð'^\1g†\3m³·8Š$¯´ð'^\>oÞÜyÑ›n²·œ-y+Uü‰sQ=aZôÛ¬‡èÒÓCéãOŒ‰•]=$¿ï!uúÒßCWÝ<ÚÜÖe:|2|OèfS¼q‹Ët¦ÏýTôâóØkÛN‹†UugÏÇþœË ú°ËºöÉ.º$+šÈ]uZÁ)“ß ï>}梒sÝ ÆD ?“;e9¶æd][•súl7} ¤Š[WEõU‹sˆÃÁUÑ~wË ÔŠÜü)%ŸŠÖt#0ÝÝqw×b\¬«6®Õ§Î©~Üî›\+ºèŠììZŒ3}òŒN¯ŠrƯåûÇÕï-âx±²lQùЇVªs¨ŽÏïž¿P+Ì•:þ+:èO®Ô­+U;ƒÜ°q˜ F•­Nßý ¾kÛ þ,3ˆ‹÷Îä™Á+?S0ö"rl­eWÅó·uñ+ZJ˜Á[iç.Ë» ¨ØÏ?5*^Ç{Íé8êß½*Z“žÅ±Ìf>cªofØçœ@·çw?”sjÉ;yƒ7DŸCÓ Gý2ÕÖåbÿmŽåùbBQÅãƒüèãªsŽ7…9¶niíség–åݡ߭s|ÝêžÛü,oÃ/ËÜïEõë8¯ÈíÞwÒË£¯7n}{Nç½³=ÚíWÜÚÛÙ~Az¶ycf[»µ]ÍÐ Ž(áA;~bÚñéÞo=9çMÚ¿W®¿µ²êäÜ) ×åNéʉJUk=ç/àxç¸ ôÎÞvzZ?‹¿Â]TqÜÝ£Þé=ó·ÎbøíÙb·Û\⥥s.'¨n.­ûZ;—Ï™Kék‡˜KvîÃs©}Û.€Õ;—¼×\þNï\^¹®`,s Æék`.µ0˜ÿc.ñµo.5‹é\BЕ?á1äè-¸g.}û{¶tŸÌ ®r38º{›Á+³ /ʉ^œžÃÕ}Ø'›Ãs£’U뙫·€}nÊçÿ—ÿÖӢ̳\™·ªg(ì"—qcìrüŠò;¦´gF϶YÄwIç,Î ØÅ°›Ü,ÂeÐŽ,ðøî½³˜Î¡˜®Ìá¶S ŽùÓ Ú|š¹7e^\½Øí¾U{ÄXT]˜œc3X*a«ógU5ÌŽôó÷?°ã2›?J»w!&GÜüiæ³ñ9kô:X¶y¬ƒeÜzxWù8ÞèÍig»+' ÆÞœv7wåÄAGoN‹³ºrâäI‡Ñ!'nBžtñìrgÍÌ^ÝY3ï¼³fòu;k.ÈA/ãèý™ìþ•̹‘qØ,ÄYD×÷²&RÎ\Êz'!—Šùªü«»9tŽ“ýç*™CG¼«dž…ñ×gI‹¼€÷œ9êD†%óœd~ òâ~4ˆ §~4ˆô ~4Š]§~4Êã©ÜñôÓ’£~ò*ÖF?ÉȉM?ù!”ë‘~8×ÂS¿ïÄ}ë÷×›Zßè” ß›~.Â6 7Ö1KÚ›fé+7¿$îI³h­â÷×T×­þrl¥#_MÙýåøP¯ºÌм9Ð# |õà  í Å+–âçEvNˆ"’MM6Q©Ûšrª¤>µÈÝ•úÔ"χêS‹œÌ¨OƒDVŸ1OôifJ}¬YUŸ†ì÷iHÙæ>e3“yƒö}²3ãû”MP6]iŸ†hïiF[Ø4ë­Â ÚZ­òf%05T[T‚†É7–ú4L^ÁÔ§áš ”†Ë÷´ú4<ö›õ‰ê³ÙfY"Côp/†›“ÓšqÕ=Â4ô3.ÍÎH]šµ`geõd”œ¸É Ð(Y3Òœ2÷×£~æêÊzA½½{¦¯ç:øùÛàµÆ;ȱ^kpoãÕ¶poãýÊàKÓû•aÞ½_˜.Þw•c½Ë|µÏk ²~R—õÁ“ª¤5BVͼÖxg=Ök Øã'5úžØZð¦Ã”X¯5ƒ‚Û±Z·;FŽ$íK«¹åùá<·=ļCëµæn¿>ă³šÊ˧ ¤a~`á¿0}lØq‰'H­~e}cÍRœ¾ʯ},Qª‡² X‘Ù&Aß]G~H"ªŠïUÀHýäóP‡œ´ûbýÊRÓâCp ŒËꙟ:õæ‡ÄŒªþÞ@. CäʉÞdÕò CuO|Îá±0V¿°gD·ùÑÖq%y½½áòÌnPÙé¡?=Osm9å@’ìÏ¥U&Õ­œ^Ê$hpÇKýú^#IröY ´ŸÈ®éù¡#v9bÞ•Ñ §¡¸‡$´_TD®‡‰ys±Ë¶m5ļ+ö¿¶kŸÄn]µÙ…]ûüäÚUoßÿÚUçe–`﬚Lûº(¡œíœ>®ì†ð ݬïŒêDˆüÒ“'Us¼ðʇȓë M¬iâô¼J˜0#ƒx¢¹~,<®Å–&Zab©Å¸îkò{¶“<1Oº ”höpŠÔ©»aÞf"‘Ó/0§2}¼gNǸ9?8§¼±Ê]w· ]4¿ëü»[ºƬN°YÕܾ¸bÌæVͦké¼^Õ­åP»˜—#¦%XŠƒÃÈø‚庌Žr΄€£ü¶HĽ> H2é¼?J²<;:,¾A<9ø{I–6‰d§Í=d²Î¹¿>– dú¹G´Hçg,´7ŸäörÜs“Ÿ÷¹”¼ÃvÒu\ÓhÛ\éøïfrî]Ñ ô>Zu~T¸jÚ?vw¦‰M#ºw·0Ö턌Ôtã ©éQâåvÞÏezÚ±fÚŽÚ¬êJ `˜h.ç*_ý­Ô2Íž.ĵÕ_í\ÕýwÚÑÏQÚQ5nÇ,h;ú{¾ÎëE½N»-ìlÍCuvA;QÖÞìl€ûÚÙ­6¯&‡9Þd1(;-ÁáV‹AÖüTÈñÍíµ³¥BéfšA ¨©Í Wƒ–]þsÖ!rn]ü­Î®=!tþ¯yßGèdÞ¯Üãî–ôLkF÷Î{xëæ`f~þÝ-ñÜ'~î[K„çdOù¿Ìüxíë ý3¿%Ìóõƒðv›Å ÜÉs03«sæW…™·d7;ói·'PH†|h ®óÑíÛ ¢Â,礱]œ˜b;ÍÐü®õ?¹¶—ºó3ì ðžpß•Ÿómûɵ]y·íÖu:˜¯´Çµ]IâÄîàíêÑ]6«Ú }7à²iéBôG ¤ø:guEÀbÐÔü¬"=$â{Ajá[þB ýîŒz©ò]£Ùdfÿ4ëÚµœM™A3«oÑœ ‹—ÁæÌf™9=Ÿ8±{4§s†6˜Ó'H¦2©éI¦šÑÿK2Å0mçŒ. $SH•ždÊší%XÚ<–` Г29úöæ´óß• Ý“dÖ ²½9-ìÊ -­7§½tåÄö“$S—ó‡$SòÕI¦¨J?B2ÕÖ$CIr˜:$”%Ý©kcY¦k…~Ê’Ý’¬^E·|‘8*âËpÃ1éÛm´™‘M¡,šf2Ôºì-NKD岉\IF©4?3$M±B,ß(äÙÓÜM!SèêÖOvLÕ£~"£ Ëö“­F´šÉ§Mg¡\O›Ûã¾5ãmwß²NùÞÒ†?éMF£´ƒ ‘•Ú þ©7ýEpÕõ—u…þ²Ü/»§4šê±±è„Ý"£Ê$éYÂV¿:)^}ß÷¨å)ý³èm{„©K„l”®@·¶óMBe6MÙ¤¥„Ê!+õ¯EšªêŸ!ŸŠi0H†BÕËA²ñ¬^’Ĺ•ƒ$(…d—nÍÚ`¡n¡âÁ²µ¬kù` #cÆÈ©qÿ†¼ï?úggÌ÷/›¸lÓþ ‘ôŸjjÕÞTÿZ¿Î·¶ÝPõr*ö°!£²¹5gÃÕ'±†7ÇýÞÜ¿¨jº­šÞ1±6 A±¶Ìo¸ö¤TfR*³¯×#4ûRMãQ"Œjoî§‹”fe?³õ½_i¨3ë\€Þ=T’„šê)f´\ÌS:=½:ª§w²'±+7ú‹ÛÆDžÚ‘Í9ÛßrŸZßYŸÉŸ²†[OC1q[îóúæ%æ_€¥³rJŒÒTÛ¸@±Z›*ô*׊u"™OŠIæäÉIS·¾3zñcê|ßô ½K˽î&1BœÚ`Ä)Žû»ÕsâT ˜c[Ü#}ÐÊ„! fѪ'×f1UO–rïfqNWTÐ.¥PÊŸá{õENn±©ön£æfSâí›ØÖœVÞ}b@Ϻòî’0ŸÐ1‚ò.ÎDùhšv¿Âëö¿…ãqJÖr׋´÷Ïi«›Í+Ül®LϪg{‘€7Þ³7Ù™ûágžïÕ5¦úº-QYU›;¥êä|yËRäÝ«üúú+¢ê·©wÿ¬üçzEÞÝ›zyP{½!Ä>có ½¦s^çoT䵸 B8^Êe£ÿ)A^iNâàâ±#™ct»žLçIš¥½1~âkÖQC2<ýO)›éó-˜eiüŽÀõ† LŒþ§ünG¼kȃ¡]~é–qåéc-Ç–Þ=±5Y0¶ê“ùSV½›w: ¨/ËJ„ØùýÊW´ûüí7²'¤´È®ðïw@Ûí†4G_ûe~ZYø_öþƒûÅæ`Ox9µÏÚ;fþÞðî[™ÜñpÛG`çÎ}´5ì#pž‹A/)Ôæ±¤PÈ«žH ÙýIUÔsŸÊ«Å3]9¡]>IXµ97:Â*óQ'¬Z…W›ƒÙªçàæâ‡ÄWêî¾&˜KÁ³ÔCÄW窄u(¾¥·òª*ïtÏ-‹Ú,‚fùG¦®:ÃÝ„zÕUy ÝÓÞ%=ýÕzsòº–å 4Æ × :PA«’TtMT¸ÑQÃ$ÇÐ(ÍPåhÒ G†+š´[ô¶irÜ™¦Éƒú©@ÀLÛ•^XË ¾•´Ò«ù5‰ šnÓÇãÝÕOS iê§I×xõÉÑvÅ·ŠzÒOtõ¢Yg5‘ŒûWŽèß9¨Kšé̪BC§Î:ƒ°ƒÞBš´QHrÝ3Ó_þ¡”©¿ˆqêÓ‘°Õ§òÞ¡> Ð̨OÕ?õi ö³î˜-"˜‹6Ú"š–(¼hÐz]Ü·AÙÜ7«Lêûf£¾ov¢|ßlÔ÷ÍÎW{*¢æK7 ³í²ÙDàšÌ‹¾”Fþñóg¦4úÓØœçao°‹Ì)wž}|08/͈‹jÌÄqÔ˜‰¹)Ãbk AŸõÄY2yWGK ‡§óÚñÞübèšGD—<~={LbôáØå\î\QÎEáÄå~â¤hšeô>gD¹| lÝ÷Ä•åa×ÝÅa”3+*øÁãÕX–JùÙ¥«$Ÿ¶òÜÇõQ Þ)Ø\‰=8ZõNµÁ«w>y(­©wjË4Iþ Uï4Õ8õΖãÉ‹M0MúKÄ«wÚÞüðˆ[¥.öç8Ù Ó›¬§ÞùÃrŠ8 6^àWg‹QœU›(q€€›N±LRzÌÿùëËxð!CeÐÓšºiJ¯¦dkç˜4Ÿý–š¥ ÍK§Í+ž¶¬¦yi²nDqçÁ‰çNIèûЉþϹå]cg`Ns‡´¢æ¢ã1oqwV ØôÊ+w/IÇîÙ½ ¦EZ8aÃ˱ÚPÚh:Ñ/Õâ1ÚRÄuönGMT¥ôÄ­ÓöNÛówPvDû ´³7GA·r¾¦9O,±ªg‡s÷9–³è:;SsÌé8SG—š ³âgƒ ³¦CÇÜvßœ™Î‡æ^Dˆ¹›t¹ÒYÛü™è’¶›¢KÌJß³uy˜-ß¾}³55ÌV{˜-?gÌ…×e¶¼~Ç®ÎÙº%̳ág “1ñ±hÞg¦ÍS]ëú2á°‰‰úÆŽ=+fMMÔÖÔ.ãöásrœÂ‚ŽJó>SY³4™˜ÞЊuÓ‹[W&¦Ö´%! ´3w)…ƒ(¥ˆ3ï3[fÑh¤Õæmt/3o)uÃÅ™¿@çð±ë¾Ã¶üþ,Ž,Ê´»6…žªaÔQòm1ffj˜»™ö޹˜Þ- ³ìÕp$ìœÍ›Âl2+~nè:Ÿšç£#ÍŸ—êŽÊû]í³-oB´¯íœ£7íóËB<…„cegÔ‡´G¦F×#lbLgî£_ìfSMZÃ,·fXeÉb´Þú”œ Ñ£›RrA4ü?¿\ï£ TS›jZ±ôÇwW%︻ª¾çîªewW-þ~hK[ F”bª¤…z¹-o×ÒUD%%hçùw¶ ;!ž×hìq§ Ÿèæ™_“Óù†U9'Hx'×Íúéì¯ÚÁNݦú~vMuŸÂ^ÒTT×ÞZÓÜÖˆGå• ÍÉšÖÃKÖñMTen±š _ɼ‹ýÎE²ÀïVåˆ/·wºe'^ï] ’I"³[«Á)pÇnM.aÿùÝj0šÛ­gÆ÷€"¦¶-軸™xô0>: ¨á·sàzDÝþpÖŽ{}ñ=Ò;ôp‹Pô®Z£}¸¬çVëÓNi@£÷<«ÓÛuëÙ/ç Û[­gJZÉÑW/ï\xztÈÂwæ¡Ó/üô<éä‚Ú„F»ýýºs-×’<çÎI/d·£1ýzWÛªªçŠ ”O{;Ë—zÐÞœ'\À¾[±8:d°~sà qÍâåÌâ&Íâ˜ê<ª¡TB-ª[²´º3Œãô–e+7Œ¤$çô¯w7y jbwڼʴ`—6.üV7¯vví¼ŠöÉ>)!½ò¯;¼ö枯¥çUÌhwK{{.´ê¹¸`‡ƒÝ&ìeë."éÈdR¼&Ñû³ŽÏ›V1s½àÔ¬–®=¾Y8‚óÙ‚ÕQ¬ ŽŸiy2Wó> ?+9“ý®˜0óΜ™ÔÅ>ŒCiw‡„ۿűü,.‰rÎÙñ~ë@­G›Z/›yBbáÑ”bÃgÖus Ý]W9E}:s}HŽ:Š>ŒœÙèÞ>_y s÷˜¹x-—M×£¥Êðä6´l·æƒ[TÓÖ»³ ӻÿWÛÀ=µ^%× Pǎ̬Åiž®›ÆlÉïÂÎϤçêË ±ãé&q@áén§Þ¡šÎ[;–³»æ)y&ëçÊwPxæÞêz{5ç³»–vƒÍ®ÌË`Æ9—;a-{iW~·ß—¤{çr©/þËs™¼x$;÷¶ˆ÷#ÜNµ1nlKñêž^ÅÝ èqû#=ŽgJO›+˜«/¦g¬[¿—éoû9ôW{€¼g¦7®O¦g>ÿõF×iÿ½¦<ÞIÈŸ\ŸËN2ž&j;ÉïFóvTváÄϰ‡4GéÒ»êþÐN|xh¿tíÍhŸuÜó~°D÷sqxüÜÚÚd[ÛV,.Ì#x†££ƒþ™0ꆀvœ~GÈñÙL,Ø)® 1_øÝË|óºþÊQÅòþÎOÌû@ Çí™ÜÉí™ýõ®P—ÉWð½!æó)G1ä+N6\'Ä܉ëŠkæ®ÃºSTÞèøOÜ‘·9Šo4n±I*Àhë•T°¹­¤ÊÂ^†ÚGoN‹#»r"/ЛÓÞ ºr"=ЛÓÞ@ºrr&yRŠ"äÄâwoN“¬;'êÙ½9b¨ç¼p{NËŸèʉ¤AoNË éÊ)ç{sZžOWN8}½9-漢ÓHb°ƒë’¼óÒÜ’ë9¬&½Í\ªç°æÈlvW=‡åFØpmê9xçsÀÓ©çàχªžƒw>Ç£r &¸¤žƒw>‡:èÎÁ;/+ÂÌuËŠTäwžé^Y‘Ù«”¨Ç fˆ‘3GFÄ”y®Ø`ÚÔsµ)dôkn*f‘ÎM9~¦ HuÀÚ³‰Zÿ¾úÍ«Uïä%Ã\.çIøD tž6©ê›'F£€ß¼+âºæ]áê¢WY]H1tÔ5O‚ªkžä T×QªK}; ûþhÂ%Á ¡’£þ5®ë¨_;!ªÉê2¿£¤™¾ÙùªûèããŒGŸ™Žcä@{÷q‹Õ­c¤¤¯Y;Ff@Å–¯ý#ùŽùRœ—ºÿIªèªµ@¸R( p"ƒ‚þ˜M—‹ÿÌ·fòXÉ?IôXuMœ‡c%"BÇþßâÇ,ÔükrÊ—­æë¸Xøý¸G ¿Ÿp±Üg“ÚEaŸfþ¸ZU}~äÍü ¤{a‘úh .–]|ýŒ½u±½CŒ„ù:îÖ¸òãnuód+¨n•ã…4™Ç ª‚T·ª8AûW·ÝÄÏÕF9AØP˜åøð,OÀL)®NT]š¡Å©Õìœxu\ñIÇ+ø×6ÁæSEiÞÙ‚ÀÄûÁ:y/d=7Y*ºP•hú.¤¦ïBy“«ðÍ‚˜¸—à(šÍ X&›Œ´Ã/_J~±,ßiK¼V ³øb ²¨:ã×[y_Âf‹¼DÎ Ôñ—jƒ¼TÂ9êøµº×ˆÃ|­œ¶ÝËt××¼L“ mõr°:ÛîÕº_irn`²å^‹UÌÝè¸(ú–KÌÖ|ƒœ’+ÿ¸æÇÔüFœA°ÝÞÄ”"qü&Ø Só&x½ ½x³NûÂof¯‹C½ <•àÊ᧙Ȅíùú‘PçMô?¡_7ÁµOئoEn+¡_o#%H½M‘PçÛ¸2Dogò1Üxóßñ­Ù{H²@½´µÀ†z'3QW¼“ P`.ÞIÿ Ôêu¼ÄX$ÿ{_Ç·æé}ã 𾙎õŸmv#l”ý—í#¶C¶‹Ùª.ªKoÐS6óÙ”ƒÈzß‚y9fÑsÃfî›C‰º šƒ/ ²7¬,+¾ö‚]Çe/ Ÿd/"ª½à&Àéɾ@¢è+AÊÙMtrPÔy9ïCà àyI%÷/Õ„ˆ]&¯ô}rPÏý¤.¤Ì¼ì>*| ŠLêÏûä ûI¾'¶™A62`VjŠ›û;Üb^èÎ÷eš¦Çâ5#@é•RglÌ>1ƒªœdæ.âAö)9¹¥µa9ýµµ•#i4€óyŠèk[éÌåÉDŹʄ¢V *C£Ui”_ßœ\¡@qm2‘XŠ<,èPžëj …gº¤n´ºtÌhJ¹€OE×ñ)g åmz¥EËk;0ZO*™Ç»úAJ”{"yÚ£ü1÷QÍ£ìO·®¨®íhmEu)Ê>­£-,ŒÑË‹›–ÀËXå,×SE*ËÙª+§t o}”§\> hrO竌S’ÕÿÑ“êcC°«x(³¢1Ÿõ{j©Ôé–-[¶²­¡¶¦Qê6ËEÉ&ÍJšÐqdÊ­hmhO>‘°XσMµÕm+aé«S/(ZšlŸ™jkŸl*««³žÔ“Gy95dˆ²OjiŒ²?Û ëdP Í4 #¼Ä¯‹•1Ã'Ê^Ž•°X%ÙжP튢ߴ°læ_ $‘ëMŠš”ÏK¶¶¦ZÙ÷ark”;›\rxñÓ ^Žæe”w-+x}]”ÛR:vô„(÷׿g0•јl^Ú¾,Ê}eVMts{ã’ ×ËhB\½¦(éf¯wVÈbæÐÓ ßÕçdô¯¢™ñMÏHáU¿[TÅŸþ~õWþ~ +s8)í÷ ¸‰~¹'EBcѸ‡àcß’kè HÏâ,4‹sð>Ç´¾>“cö¸à‡Z˜ÎéºòÔ[f›Ë%PüÂj9~*òr”š0Û<ä7ŽÒ!JÌæO7ˆ‡±&ÆÆÉãèØ¼ëG6à:À=:ó5 Gs«[¨Û¿žù%¢ƒúûÄåö^1r9N71ÓÕ$®Ô^›^—“þ8Î#'‰b£'vНñÝMè щɲ”ÿWÆ2žƒ6î[1B¾+X`KÒSÒ6ĶqT¥¤Ýk^²>ßYý® ÒMAWqí}aì´¾uÄmë‡ÈÕ¦ë–)텃ߧ¼hTU¤£Ö—jËé´ùΆٱQ 1Îf; åæ}P¼%¢¸½[ ÿñëËB„­Ëæ¡ñåºô–þÓUÇ—¢Ù¥mɶDúÈÔ6>úÉÓ+M^î®ð½øÚ> §k….| 6Tå½ýî ERÞ¨-ôˆÇÒ¨èOw1dž£Ùô¢¼.çž7Ì ¦ñ†á“uêwÐ_϶£¼jÚ̇íØÙ†¯vX,N\IÌ,›U•hÈ$jK6צ:šQŸZ[Ç»¶öeÉÄÔŠ¹óóæŠ#åk€ë7 ¾t«†¥U»órTA³j||M¯$–Í›S1Ñ*%«Öûì†öe‰ŠGït¬àæDlˆ :aVÇÊït3ví—µ÷ˆKhžtjLåúS“§?¥ï™Ø•ØQå½S=ÛöË;¨ŽißÉ·Ñ)›7b@¯º—,·ëff\þ·]ÄlŽzS‚&•çË£+åµrØQ^'’yóÞúÈq¹í.x»ësÝöCß?f:ô[YÛØÞ61±¼¤¸d|‚[ïÚDGsÇÂ_ÜÒœð7Ñ&#¢ßÊi³ªæ‡e0Îfšµ€#1±û­Ü4Ó¹ÆXß3m5/ÆæL¦®6´Å.#ÖöÈÜ^X¤þÀêD˜]f§>»Ìǃ³kg{3zg˜Qk­Àά°Ÿ.0ýgföôûlë¾§ßÇœú™eN¼F s×fï˜ ¯õÊ;¯]¸­±y„‰¶OS—¹ñóS ßfâ¶TÌž{\õôºyuà%Xm‘WJ9Y^0Ó%M‰ú†dc]¢9Õd Ñõ¹‘ Ǽ€¶n¨9ßÛ6§bzóÅ yÍ{áÁ/:Râ²ëèŽîÄk€Ê%Ma“ÞíäÕ¤‡¼öœØÖž¢‚™þòsà‚éQÊòr ¯}{óÎêÍû Ë‹6y… CÞã§'PÑ7sNPÛJ¨¾¿èÓÀÔÓ2ä5<ž¶T½“Ïm«M5·#’¿9Q17±JÐ…-)xxi °§§Rƒn OÔp©¿2µÍ*Ÿ“¶Óy"5H™ho “óž·ðÈââ%ʬ1*—¦-ìCi(„üT}Iª1½t1á¥-ÕÑ®¢t‚†7àw¹¹VTÌÆn©¸ßžŠ÷»¹kËæÑ­ßBðš{Ý·Ùÿcs¼¾ðwô>å©4h oû$VXvž-·Ë‡¥Õ+^a5Œö5¬¸àóS°¢úÒ\•ûù)xЭ Íu‡ò®èF·quTÔÕ Û`1vqT·ñ--Åøb¾[ø¾‰oé.Åç»H_'п5UÑÝîžI¥‚Xû;sv—–Ó<é®Þå¶®œÝKÚÖß´‹Ó{Ô;Õ³”zJ×sÖúÜ 6ÍÛY7¼ò éÀ1?g­_zs@lôÂõGûXËÂõ‡º˜±üÒ­ß|Öõ+®±·¯á¬PÑ¡†áÔàt°š©ƒï™ôâÊ«¾ÇÓ?Rß­ô„ï6êú°Ó²ì®ÉÎÎá=«ÖK6¶¨{Ìh§qÙ¹sþÙ2Œ<ÊÊ‘[•?¹Óxnóx;×—yLÈ»ö̵-¼»&àFo7†sÿ­{ÝpæÝöNíŽnµ˜pVn±×˜ÕY:˜6Z[¾VrxYr\o9Ð-¸)Ó›ø"{‡nÁ—»¯=M¯ý¥w‰×GGƒkkxw½>I. ïn1þ½l 8Y< ´Ydã}f|âJÌ;]$”¼F1qÒ˜¸ iLœ…4Öb­!6"ÄFvGí£»†Û6¶~‹»ÐA_Î3Û^£erzÝô ØÝƒÕã+}NCÀíRÎÈr>‚Ûïÿ®åævŽßCé>„z-nï®- p±TcC¾EóîpU®ojiL6A7v¸XömL^T7È+jPÈ»¿ûzQ5!¯txzóVñ»Ï‹®øUZ=!ï?ãWqÐÐHÐ;h{ÍÚöný®¶´×·Fï´Wß:DzíÿqgþÖüjüÆ–>?¥ÏlŠ_£u›ðë¶w ¿FgóðN¾…_eµêM¯Q÷ïñ«ï«ð«¾¿‡Q³œà³Ë¥ïÕ÷à·V~¤ñOûÄOš)«±~‚Õ¼.0{Ú{Kù›+ØËã$ö²÷Ç>[•ÁIÒ6´9Ø¿A—Û{M¦Ž›1û·ŽáÐôñN»öq §½/ 9¼F"9.·Ú¡)¶«]k‹ZÃXÔg¾2<¾<æ11±ˆyŒEÌc,bcó‹˜ÇX(µtêâ~+ÜGmý ËÌmLÚ7Çì‰Ë–ÕÕµí­X°Z:{þBQ‹öJ]~t‡“ÿ7”Ÿ¤/µíd¢x¤"GÌÌ8 !}eüÙ:Çìù{íû}7° Ì[ó©¬ý«ÖåEljæ6UNïõ\pͯ²]öŒK¼§óšWáT'y—é$s«Éµõ›ÑN•{ÿ±“EÌð[ Ñx½ÙZ›ÓyÿM¥{?Ž)Òh­ü­ËùîÝÌ|×ï(Ì­ßÇV'?ÛµÞªº—ïµsßÚ®»¼"ìt´sÝe¸)EÔ”ýb/Çp›°âÇsfväL¯Ê6™ïyU¹È­WrJÖ»tß·®ãÿ9ÌP{°ê5¯ª;ÿÍì®ÕÞ¶—æö‚óÀë|wëiÑ‹Óv½^t¯çë}üÅ›™¿åž¿f›t™¼÷q”—vóH̬]S»WÑ^âŽ!Õ·ãœ-ü-ÿ@n\nZ ÿà×{swóPm:€bØHÚ\yR#}_€äùd_ð•ÆXîpy8Op×<ÔóÏw i¸¢VbÓç´æ÷Þ5²;Ån,’ãƒI”£%`—ÿz³ø>Ç›«º37øÝŸŸ"A}Õ°TöÔXÚì@Å&ï&âEâ׿¸±–×sý@ÝúÞ¶ÅwHî3„}z¶ÝO2u"µzÇ÷Çë÷ä'oרm‚Ñþ¯· ö¨¿M€ü-•xÌÏ;ù1þŽ æñ7vå=!ß—ì»ÐëÃKþ¦½S;âÜÌ»xXæ~‘ú)@#3¿›¤w ±ïcÏEÄ"Ä2˧µû» 7χBt Ýð:Å~g¢B®øUÎ'?}>ÎkBÈ\!¥„,w7®€Æ>Bg5O/®x“åEé¾²LÌÕòBös9ÐF9+9пN¹ ý¹\X.#—8­¹@HT¥¹$KhÛ‡\ÿŒ%žë–àØžòºÍ~Ö-¿G, ƒ)âñô)€%>{^OñÃ’~ü€‡úë ?l!¾Ãi¤¿)Gïvnº3*v9xèÁÛÌ›nX±#Ç*gS±ëÝš­÷ÍÜó»»oîá¤tûfß–¾q.|Gpkô^h7…Z¿©°ó;b¦°9ØÞ+?¹=¾0*Ÿyî¯Û;í»Øë€§äSÙ·\Âlíb>VD¹“œ÷îͪÏÏâ®xö&q»Ißî .½‰G ŸOu{žJg ª íœHuS/}d&™)æyÌç`„ÍÁSæ©òÅSåöeùFY>|ƒø¹?û’ý¢SBŽÑ–ãÌãLfi›³B«»A³ô‚8fö™öN»*9ýl͉‰›½`Þj&¯¾Dûy´ó35¾×'kø-ÿ¯§¦ø¾ñ’ý²×©VòQ‹øãËBVlß'gnß'gmß'goÜ'ò-´uñ”õF{pÇZænÅâo«ï;ñ|Åþ»~-ó(îÑÑì¼Îf>Íþ(Øþ€û®^²;ègnW¶k/«¶½oUc'“]׋QvÐÏiOó©öy~eÖ÷1Ö÷aÖWLªÎ:ÿ’x﯈g=~O3³¾ÂÞÝÇ»›ã˜™sóîÖý². õ-Ù>«'nŸÕ“¶ÏêÒ³º{îâk4wúþŒë=˜llÖÕqì¾Sd6w׿wwn~wǦwíï̺T»ºû-ós[û»+úk¹µdUÖŲ_zpš9ÆÛ‡ëÚl6Nó|:ó¼ÊæùtëÇÚ8fæùt{Ç<¯‰cfžÍ;Íóy¡¾c·Ïó¢íó¼xû<÷È<_kó¼3ÌÎŽÍóyÍæwÛ6¿Ûzï<_™ÕîðÛó¼ió°býÃŽéêî沿י$æý¬ËwXÿ°Ãú‡6 ìªaW =ÐnÜ-©¹ur·Ü|±‰Ë’rV…2ðõÓ¾×[¾ç}MsÉ•ð+…  ¯.‚[°Ž˜ŒüEÒ¿1^Ö°z?oqGsImòh|‚­›¼¸"YRÛÜ@lÍäÅĶ4[%²* _|¤å·FÝ‹/(GyÏT~Þ“{çùQò¬\Œêø¿Šÿ딣[SùF¼u-¬\Pñ`hŽc<ççÍÆ£’Kž÷,/Ÿ1«ìèùEÇÍ>rÔHt•Åñ]Y)!7â€ã9¦œ«÷,ßÂé5š%_ÈIœsYœ™%Ýl+ÝçïwfÅâîÒ¸Xu‡¾å¹ðoô-í/軽jñ+õ=³jñ }ËêýX}O®Zül}O¨Z¼‹¾Ç/>ŸkrZ#­ ë…,ãÛdž ÇFglå1¯â;ÍÝeüçö>“zbê™ìëQ Þo®kP˜¥|.ÿ §+;éÂusp§FÏ*šŸl‡Q÷€Ñ ã*½T·yõ;¼è1•üŽë$ÞÙöÚø\׳×Õøer»àj¹vÁÏa¸èÑöšP Þ4iæÄ„³pÑ[ž[Ñ™¬I]N€*vñŠÙÚå<¹Nñ;¿^âœ7£÷qÇ_? õ(ôÍÖ¹çåÔ†RæêžìhU÷+Åï6ûX,ÃàÁµÎñ¾òœ;Kœ¯@Íæ¶GfóÍ>íT7Ÿ3·Í§ç@37‡ ¼T¸Î^W£;“`%a·vr®ûÆÌø™”A£ù)¿Mã¼ù³HË2<¹¦ Ûð?²ö^57ƒïŽkjf?þÆ>ÝÍ›å9H¯£G¢[f&ZájÅõ_lŒ^úÆîòMêíîy°3`çþù^j7Eè³7£}×ñ[0È6i à;riˆýýÝkNNëÈ+ŸÙñKGÐ}/ê¾p×ݯØudwý®‰îü]Âî2é†n==*ìJþ¤pÒM==]Ýw–àñð<7<àâ–›_×qû!éñEó¦WÍŸövÙ—ç½3[þ.­ ×ìuv°ØÞ9[_ ûŸyò»Fœ×è9ìÍÛ'’ó¦Ïž?ob¢"¦~¶­XÖÐØÆ†}ÙºënK³˜Óüâ×gÍyšßb´IÇÙævŒFC;0ÍqºD(s²8¿5Åz[>¯º¬²bÚÔ²ùå>7žšàÑÊ?BšûŒæ›S+š3¢—×î ô¢¥1Ð}§O$·h3»;ßÙ§¯µ[oAߟ Zõ÷·t*Z<2/Ú•÷·qO,á»…oî»Èq9±bèÜm ¶ŸjQ í‡mª…ú¿êºn|§àSþFÛ'};:Áù‹Ä å` egdÂiÏ1?_†R²¬®BŸküìBáû4÷¾](DĨ3’¿[²õv£,¹fz¶;tÒõýÞ £^C÷nÜ…;y¿Îvá5Äα]ˆ†$\«M“®ˆê„ݯ`¿ë>ßà .+ü²pí;r×Ì×.樛›Su÷ÕõÝÿ'V“WÝñEnÔ~¼ÿíʉ»”Þœvå”FÓÞœö>Е[,½9í}¡+§tÖöæ´·²®œ¸¬ëÍÉM¹žSzq{sÚ›tWNiÓíÍi5HºrJ÷noN«çÒ•Gv½9­6NWNi^îÍi5·ºrâïIo’!'ûzsZ­Å®œºéïÍéôGwç”ñÞœNzwNiïÍi}tåÄé\oN륡+§ôœ÷æ´Úc]9¥ý]ß”!'> {sâó¤žS¾öæÄgJ='ÞIzsZŸ*!§õçö©ûjä÷ðnªçàÏþªçàÏv«çàÏÁý¡žƒw>·‹zÞùÜCê9xçspK©çà÷ɰžƒw¾î±õ¼ó9¸m×sðÎ瀓PÏÁ;Ÿm™zÞùèÔÔsðÎç@󦞃w>ú9õ¼ó9Ðä©çàÏP=ï|ž×s˜'.ZEõ¼ó9ÐAªçàÏÖR=ï|ø„õ¼ó9à"ÖsðÎç€ÇXÏÁ;Ÿd=ï|¶x=‡Ùî.Údõ¼ó9Ð$¬çàÏÆa=ï|4ë9xçs ?WÏÁ;ŸíºzÞùhàÕsðÎç@?¯žƒw>ú\õN·Ëä0¾M»s8]1“ ´zÞùhxÖsðÎç@ÿ³žƒw>§µzÞùè‘ÖsðÎç@›¹žÃzе9Ðu®çàÏ6y=ï|¼ÔsðÎçÀw@=ï|< ÔsðÎç@¯½žƒw>Ô»zçkÈä@K¾žƒw>šôõ¼ó9ðÇPÏÁ;Ÿïõ¼ó9ðRÏÁ;ŸãI_±ø%©çàÏ“zÞùp$ë9¬¿\›)õ¼ó9ðHQÏÁ;¹ÑȬçà¯oõ¼ó9ðuQÏÁ;ŸOõ¼ó9 vÕsðÎçÀ{L=ï|¤aë9xçs 5[ÏÁ;ŸÙÀzÞùxªçàÏ `=ïú𥋿¥zÞ}Ï»®Ý pê9,×úÀå¾Õíw€nèÏïõ[ÒZÕ–å~SÝ+Ë…¥¶EYlN9+—:gè]ãÌüÊÍ–!÷VÙ+~SqžyÝv˜x1 Ä‹¨ÈW¦n9×T¥ š+aŽÍ©0^ƒ°—°gƒn¿Âè º§©µMòW¥Úú9loýt'RmýäSµ5kŽU[3žF©­Y74ÕÖ¬Ûžjk–7RÕÖßü—õwûÞþú«òšÐ_¹Å•è¯[–jè¯Û¹jè/pªa€æWX}€ü!è62@÷fy"pc\Ó¹‘u¿ºAª¦º­jº 7©¦è&€êî¦ù¨»¢jj™×Ðâ0ýµhn¤ Ö¢Û­ê$ †0È Ý>Õ—ÁºªƒU£æe°ð›ú2˜žàÛk°x|ò]:Æ÷Ë!º±¨–!ºIWu7D¼6 Ás~Zå§D=k徆߆¡x ç8z÷Ù˜º‡âµnÜxÒŽöζj)ÝfyDÉÌá'u”¸$âgŽ"à ÚÚc¼€î'¨ò6h xbüáu {ú5ön˦;F‚îdÛ+â™h{…s¡–m"\˜ZW®üR¿mê·ú7Î6Ú8ùPãtÏÐlŒ“±>ÍÜ8Í“6å8Í«æfœ\’Šÿ€fT}<@Ø]|ÁÄPà-ós€nõÊ}€îÕšŸå§Nós µ1?2 ÌÏp˜Ÿñô•ù9ˆ0?i¾4ûqÂÓÄÁ¼‰éÍÁð ðãz°æLó{ˆ<äiÂŒá>÷êg¾YÏÃ!±ƒÚl2—²üR±Çc«Ç0KìùòPªšç+Ÿz6_ØPó0_ÜÍõ|͇jž¯9RýóÅéPOçãÅÉxf·k 1Ê,SSÍ÷±ÔÆû¹¸?Ç~n°?8úkJ»¨5¿cå!Us³ˆYc'⚎›Èbö󹨥÷Œx.›×'oqµú¨*«Ï U~Çéæªþ/‘70íƒ%ºêõ½Sÿ—ÈI®æo‰ÜõiþNÐÞЬ œ¯}t‚ö€PÒ‰Âê÷‰ÚÝÚ½'jÿŠO|¢üØÊ›êIhšÒ‡“¸AáÙø$êŒÙÕ'Áÿ+:os¸ ^ >fþ—¢oŽ÷ý“Ù‰h#œÂ\ÆìñS¤U­9<åÕqŸOyõsžî½S„uTï2í;Íâ2ös¾Lw{õ÷4ùŸSO&QO¾VOÖÐ<Ÿ¦='~Õéâ¨Ï§‹·¥¹>¾Ñçåâzhß-s3çËÕ_õy9¼+|å.‡g@ŸWàÂ7f¾VHK@õŸ¡|šç3ð…o3Z㾞ñ²öyº¿Îg‡‚ñÎמn8_û@øìyþR ïG¨©gè „î”yÜY+ó:M¶2¯g^‡Ò2¯Ó}T™×ëf­Þ®¾ÖL=S˜[=}¦v€zúLæLx¡z$ q¡n(Ú•*¯f…³/³qìZ0ÀEpê˜ùô8û]Œwæœp1þ&p|1œ¯„]x±#kç]Âà¡ÿ su‰Þk®.—€I.³$Ô±™¹ÇKïf°s®ڌNy oÃ&àíKñ]`^j^z/¥?æþRvS{™Þk<›V §—ƒAŠàšçàW¼Èä<,V¤ïÏ¡ž";ê9Ìb‘ºŸf)²3ž‡²B‘>n…wTdn¥Î"ýÜ /'ϧ?%ê>ÜŸóð|úXbG<Ÿ^•Ø W0W%ðÉ•ð,Jà+áì•èàËôa3S¦Ÿ×p}(³“®á~T¦¯×Ps…÷×€%+ôéÌ_ÌòBúT?¼ÝZaV^D_+ä;®w/s4€e^ vn ï/¥O ÔýR¼À5P÷µ`…Fj~9¡‘ùx9û ‘º^ÎNm$ÿËÑhâÝ+Á*MÌý+ßÄ·æô:êl£\‡·&ú‰šD?úþ*Ý(4ÿ¯âöܺ^EŽ~äܪfÞݶBÞì ¸|nf¯¼]æföÊàQ5ƒßÈ4S÷yƒÃõ^=x¾û³/ÞæèOo¢æþÌÓ.<öSï ôgoìbžú3¯o† ÕŸ™y3˜¦?óùæ7p¯Ð>øifdûà-ì¥Ôøb¨û-/7å[¾íüG¿„ÿå4ºzi: C ‡€yá+LªsœÇEÅF¹y‚/m„Å•ÂF¹Ï¾"•¨;. oîºt”˲±‹â…èUé(×M£‹rÇy´ri×ä¹(ü½×¦£\s^—ŽÂÀM¶rAÓ¹(Ìh£\2Ô ö2¿›tmÖx«.îÊñ.õDä6œÒƒ÷¼4ž¬÷¼Ôa°n‡3ï÷¨~íÍ_d¯1]ïÇV™ß/ü£|`gsŸø€ú¨ùý€p³fûâ‡j7 ­füvv.xíî>Ü%î0Öw¼Ía,ƒ¸Rü,œ’û¸Æ‘t†2Á“ØìÝ@„}>*î“&ýcš MÙÇÔOMÀÇÄ£Õùøš¸æ¯qUf5ƒ›pnžUÉ óKm~W+µå>®Ë‹¦á®ª¸š»4³îw—: i¹Ks*tp—¡h‡üªjÒ&üU&‚ùû„° ¦èøµ¢†O,vá6bˆ‚¦·Ú®ù4rçÈü;›ß'´Ñ4KŸFަü“rî­þÒn+ŸÿR›è“âÇhú?)oÚ«ŸÔMEú”n›š‘Oi£ Ï}Js£Z>¥[‹&à×u›Ð,ß-Œ. s·p¥ðÎïc ïü.³ÏméwÇÄ]üÝ1ýH6Ý"¿+fæâwÅÐBø]]qÔ¡ßrÕ||–j˜ØÏÊ €:ôYíkMîgÅúR§~O›Pú]4%ŸÓ@ïsº¼k¦þHޤՙ?&ׯ?^wäueìÛÃÃ4WéÌWôׂ¯è¯öùŠÆýº÷üj\Ì»JØÞ›3wïÍ™ë™÷üÌöË|:ßÛç+š½õ“ºØ–Þ¿3ê¾F d¾¢ÿ¦ÏWtæ#þ{5úžØZ¸—q“³¾¢qëÇžNˆ‘Üèû‚ZWØ 8oÄÑ51\àåÚúŠþºyÄæ ´ÄÝ.›VÜLs…É^°ÉÀHÙ üØ‚_²8˜Îœbó‚k>SŸ½!Ô^ÀàZ–½`{²ë³º†wTÆ=©Ë^ȧ„a0g/¸Åƒß²r¯×‘Äf/teéxÁíºö¿ë0)²Ü)ád/@mìñì|m¸Ù Xß5ÞÜËk]„ÎË^€Ðjý€ _{§¾öf~­zøýµ¡À®Í^€•jý@± 6Up7tÃÊ_€Žk/`Ààµ>{’Cí8¶Ö!T%jÕ£MQ«…‹Z­ÜkÛ T&Í^ »Q{¢G­zn³lÖì —Ú 8%µÝ “¦¶cà¡×r tÃÎÏ^€¾k³¬õ•›q­g°ÎÁÙ ¸.ܲ áÚþk×&,^{V¯½@å§ö‚›w­¨ƒpoÊ^ VÛ‹¨ †’½€TÛî(°ÁòÊ^p±¨u‘‹F­4ÜjuÀ‚‡I”½à–ÖÑǃ“òâá¥cpwðo>¼S—äÅËŠèÓyKïóIþ¨_oœƒ÷µáÙ{ó2;Ên|ØëlT0îq³Î4º·¾†ÏiQöʇ½¶F9ÄñùƆÚû¦ïa ëÅ$eʱ¹µ„^läSûâC¿3ŠZ<­tÌõ>Œr_ç*¸–OUpüïl‰Ï+3– Þɧ*xŸÒ7]ý¨;ÎâŤӸZ:¶Çíù”òI|ΊrGòyD”û\>UØ>ÕšÃùTÂãñø­¢—ð9-Ê­àSý?‘ÏQÁêÇݦNá½ðò~­Äxæ(:ðÎÒ±ciË»øT[náS~†OµågùT[ÞͧÚr+Ÿ³£‚æÇÍÄ?_:v ¼‹O5ðoJÇŽ§Š{ùœå¯~ÔòX”÷Kg$}¥É’­\‘jÝhòzÙ‚¶(oÞ}Ú£…—5µ­ˆr JÇýù?}Ôè—4“­õÇË.§0Íê2ÜŽ«¹§ñ©èÄÒqÅ4~Ÿjüd>5o‡ñ©A›Âç̨àÜÇmO=l¨þ…÷ zjƒÌÒv¹¸tœœÙoâSÑgñ©¡¾„O õf>Õ±-|ªc/-ÇŠ¬d?n¢HësÖzûr>µŽ¾ý¸‘ŸâëH¨–¼‚Ï#¢‚Ï?nt§øªk— 5D›ùT[øTc/åS½ŒO¥x6Ÿjìå|ª±?U:^»'Ÿj×+øÔ(¾’OUqŸªâz>UÅ«ø”)ýËÕOÿÏçÿÖVÊù5KÛúVØRC[^í­Æ_¼›8+G©Æâ{éK M؋ݣi㪋aZÛeßRËG±Ž;—ðñù¶–(ûò%|ün[C”ýó:*zy²­ºµfE”R­FaHÛ.¯‹Å«d0'Ê~{CK”—åz£³¨^ßÄÊ?†#JvKkryu ¨ñwé…–Áß–Ž?6ÊZ®f¯_ôò\W„’”Öÿ•Œ»òkEè•{Ÿz´¼ôáûß~T p kنѠ$Öç/—×Z¿/,ÿ]· ûÝ,Åg=2#îÃMÇÞ‡!¯ûÝ ,}øQàP~ýc˜§üƒÇ@UÙ¹–}µ•›¥Ÿ<Š“K»=ŠâËó»”ßñØ]£¸â÷Ç—¤îwI>þÈ)óð}«üÁÇNhqçùҮ:rö-à÷ß¹›/AC,ÇRû›¡óü¿´ÇQm¼¯ÿ2ìÿ²S±Šr˜Ýÿ¿3®ï忌°CE‡i=ós'™‚Z1¯úú¯À)éçÔ#£]ýøÎ¸»¼ÿ~PËú;1Ÿ(W E\„ïÚØ®úúï£t€ø4*‚Õ¥"¾ë›ºêî€l- £(?^“b"}w_ºB¼»ÿ‘mN»3æ³Fì‡Îo«¾þÛ æûú7Å\1ßµ&Zõô \cÅcQ³ïå{hÄ•â=ü+#ŠFì**0Ø£R¾€\)¢A›RŽƒç~ŠøÇ®Å@-×âï:4Åà-”bN|†¹óó²03/OØœ3Å`r”bÖÂi»@, W °Òó]ÿm¦1„L1@èYçlšùάÈtæ Ój¦lRÌ:xÙoq>)5ÉA3ÉßÅÒ®](å-ÞÞ#+tÚ§²‹ÐõÝë•-ò*e¼‰;Ä×Õú´Ñxö\\b± Mâ;  }\ >±¿6qç¥Á%eÏ$þ8<ñ»œ¶[”ÃõBèã;7 W.T)á.¤|?áäêt çL¢ÞW…ß–¡‰6e|d÷»N‹2t“1e¬.ÝQŒ>8ÅÜn¼ÛØβ`OÁ{÷¿Órî?8æw7Þ=«l^õÑËËWÄF/IÖ¦–67œ„ Ù$€°àºÜpQGÆLðÆ»kZe»“ÄÐ:6Qf›œñE?úÒ%¶ÏðŠã´¢ïÜg›=7×}dzßËã·xJ¶Þ •;v!¾:w!o¼ÿ·kª;¿Kíÿ¾W’¯•¬ÎøXi¯‰J‰ÏëݵλÆ­íòn¼únîêIý/áÿÁù]ù¯5'¿Ÿ«{ˆ“öõG‹­®xy[&ò×1#!-x7Z¬˜pÁ©9¾ä¿ìxëYÖàŒ6úÒ^•›]”Æ+ÎC§ê:;~[ì{k=óÏ[g#ÒH ›èÛbe¾ÛøŽùV~ã%´?±f¾ûñ½ä¿ô¶Û[ÆC ÌNÔ>TÁìhOöÌŽÞÝ6Úù 6*\…—K#~àåÒb#cÕÔ¼WÛwàïÉ…wÞ‡Èûm€?ï½ ÁÒ÷ÞŒPaø¦ÅÐÆ[b5 ¿$Þ‡Æ4b_2ì…ÊPö*æì£Üc ü$€Ÿ„ZZ_6kþ¬Gñ“ÅCR+*p†M8¾·¾líj%çìÀCøíêÄC™¯s£çÿo<ÔþI=v -> þ£ÿ?<_ šWõòw^QÕû}jø¬y fÇO°_äûZÛñÆ×8»]ïñ~´…Ý6Ÿw´pÕŠÅ9ûÊ«óŠÚlù@ÑŒ¬:d16@v¬bw—vw÷¹Q…bªåËÿѯÖÿØ÷`²ùU9¹Sªºén)+NÛÐÓ»Õy‡ÈÙY»`Ùæ~ýW¬±¦û!çvr^IÎ7‘SGðµäÔ7±Uµ` bì™ÕkŒ Ö\U+1ªz ¾ oäOl±l±j¶h¶p+¶olÁÿ?ØÂâ¼QwzÁ_pêd7 O†÷y©ÍìÿÆùøÕ1i~V§:ÄíÀ ªØatÕu§, ó±¿óôÐM°OÌÍ\·~%k·>ëS;ǩힻâ÷îjÒ¾”/m; ßõ%ôäl3g~¶iE}¶!ì²futÌptg˜a§kŸúºF1I\Ž±ßž_5oÇ?½Ëf¨.Âûí!føÎ!fø ¢xÝÐ?žaæì±ýfM·}3¼Ò¢ÕÇ ‹6îËPÃÁ@^¼§à GºOã¾<‹¥•ù„Okƒõ‚—x)Aù›“g/n-joˆsÝ|LsKÕmÔ÷áx%´þœNĤx•sïÒx¶•‚”Ï·&•lk>´=Ñ’B®Ó9ç6Ë lîy6÷lë=MKoÊç¯å2c Zùføêy^„Tñ ,U*Ÿ×¶5ýi›œ8"úÉ3Ùž¯£@E°Ê¸/oö«³Êù‡~t×áåéºo;Gî<9¨Èo·<ä+Z®Ò‚ßosW}~¸äÞœÝ}„{nç~ÌüþéÆëî#­—àñÔ{2u·Ô; î~ÇÝß|ê1Ïžø&â[ˆO >™øåÄ·ŸJ|&±m|·;ÿiÚ’Šß ®Úõ°w¡ÂXyüW|ìý^3FuïNàŸºw!àÒËÖñÒÉqÅ`3û›÷ï P× ·mna y¼Nñwì½n)·ü¡§þ³Å{IëK=¡“Ã{÷Ƕ÷EÌûÊãž{OƯv2×TL®ž*Ó¾¢ïÎÍDÌŠÎÜÆ£fà˜_Þ–ž Þ*ÜÆÛ†Dà)ß2dO¹OžjA·ê'yË}Ôš|t3.÷X¼o€ÁµžÝ7@=ôÇq£ã*ÏÖ܃ûI†›ÛUg|¶¯§¯€¾Å3·óû¨ïŸy==Îò G?чØÓ£ïq åÓãà"ƒ“}ðØÀªßã(¦ž{S´Îãi{3H¹‹ñ°Œߨפ|±÷óÈÍ`]Æ[oêO˜·eüñ&Þ«£üQÈŸpêq7ñ^ˆy·!ãS7ñ·ÞÝnï„' ž+ w)îÇðçðÎßéñ<ìýëòÎûÖK}‹×]ô> ñÂÑÉë>'ðÂŒŽ•Ã‹øŠà6 ‹Ô±I†i¬ÜðÕÁm@Jð6wÏmÇÜt•MóÔoxñ€&ÕxŸÇÝ@¾º½[}º4n=ÀÔºÚú|{ïxù˜«Íû\¨¶.@7¸ØZxÙÖ€ê•^‘¯!Mí‹ñõâÏ“R®ßË”™æ³X\n= `ñFöÓ±›üö9€Å“!%°¸áõ™€Åã°¸Óñš }Ô»h¨\Ýð÷ÍCàÈC`ÝÓ*úïX´`Xô;Ê~?Æ¢`£Ÿ`QðÐO°(¾âÂD±Ç~äðØOØ'ñwp°¥÷ú-œ“rºx·ÕÞ »f ¾á”BÀ´!ñ0Óy_w1ëàpl%þë ·Í‡Î»rvÛÄDG›³`œ<]߆4“m‹­ L‰ö»Ûð¾h¤ŸÖÂ9á¶ÿ©b´_ ¦yŒ+¾TÜRᜥÝxBWK\îBÁ)GõDÃO§Ã;©wwÿVúQÉé˜Èªa‡'4ämTœ;}ì'æîI¾ø‹áùå&›oüätrÇ¿æ›yôó/müÅÊaÅ)æWˆ®ýÝáÞ¼jk¶ñtÊ„!f{«ÍöåC'̶ƢoÙfæþ}¶ñ³o¶­ÏÓÌS7ÎX¤¿wú+f9*~ªënî=Î îÔ¨úm^c×Ü6ä¦Ãæl[šlN¶Ö´‹”ú¬hïobìÅÜ~ú¡½vú+6óúvþw^Ÿ¼ûÿ¯/úaàõ=ʯ֛ÞßRÝBŽù6ûãnd;bÛÔi÷GðØ/¯þòš/>ÞóõnS™ð®:Rÿüo‹½zBŽK¸ì?Ïüåí½î«îËÙ_›ñ‹»CœëÅ'ñ¿Ø-ò¿lv‰÷ÔNϳf]Ý0¶÷"/ïB)®Ö»”ÿEÌïQ¼o-±]ˆë‘N}Á;OJ['Ý…x&AóAb¯gwÍb¡#ô§í7áàŽÃbº±“¸\8.aÊ-ŠÍõè”n&åšÑÐ<»kóÜåv .±¹ŸáÖ_À¹ça¿ç­¹"kÿªuùG9þ¦Ë·â‚üôþ0{|£Ëj¾ÛîêÛƒuvìÁûöà}ƒ8Êï¨n¥´ô’}³»t Û¹o¶|C÷P‡°àѪ¥ŽÑzvÜ:í¸Åií8vFØqžÀŽó·v…ßkä¸1츛Îó\vœ×Êd¯y~¿ÞÅÅÛ|™ÇëÂ^3:­Î³,žbz=ËÚ<Ö³,nd¼ÏY¼Êôæ´;³+'Žgžôr⛦7§½AtåÄ}MoN{—êʉ‡›Þœ–Ñ•'8½9-¿²+'~rzsZÝ„®œ¸ÒéÍiù]9ÑËíÍiµ›ºrâ§7§ÕìêʉϞޜV°+'n}zsZ=×Óú’dGÖ=GòÎ{—d×ÖsðÎçOÖsðî'p¹¿ÔsðÎçàþVÏÁ;ŸH=ï|x%õ¼ó9à¯ÔsðÎç€SÏÁ;ŸŽM=ï|ø:õ¼ó9¸u×sðÎçà~^ÏÁ;Ÿ¾j=ï|ø°õ¼ó9à×ÖsðÎç€Ç[Ïa=L÷ãý·ï ?¾h£ÔsðÎçíÖsXÙ?òõ ®ç0ÈÛå@¦žÃzÓþ‘?`tê9x×w…¯_4Þê9xçs ŸTÏaý‹Ûè0Õsðî'þ€Ñ;¬çàÏÞe=‡õFns í]Ïa}f÷àÏÕújåžTÏa}c[_­Æz—¯Öþò †OP´ø÷üJr‰&×%ù"TÕ%y.“߃’\³áfQ™ ²˜BEey—ÓE²"µ'Ý5ÌMyîïð[×(G¹òшs÷kRÒbp#À=hã/c¿t÷Mœà}#íSùr{¸ËÍ4wÃtùÑÜ “…ÍÝ0Õ¡¹N-ÌÝp¹zЬ ×6Vÿ‡ƒæ™»áx±cîF`aWš#°3‚óÔ‘ì,ãäUsbœ¼ÊëŽFRbòBq*áš»¦PpðºŸUÔáýð‹˜0¿£q÷–ÐÃÑüǵæhàFsœ2ûs•Hèåþkã¹Ú­ó¢P›+ö£åó°”³)c®²)c®²)ÓŒ?ŽÙÀ¼ò Û•¦÷¹TÝÈq¡°ëB2ªù@¶·‡ñæGr<¹Ù2ã5?º…öÔ¶¯;‡t_ÆËÙœ¶ÎAšXÍÐAÂîšúƒåãEÛç`iøh–§EÕt0¼u¶Ñ!z/dqˆ¶6È!`u|æÂö6~hñPª¾OÀ«ÞI'01Þýe7ãôPî† ›éP¸& ˆk"x‡í4dÅvš(- Õ5QJ…&)¯êšdþ‚']Ò¿åq¸oËg;¦¶°(SÛùæ7I®c4“ÅCÕ MÖAuLÖEý9L7;m±ÃÌðaÌô0¹%TŸ¦hjþ§¨/šƒ)â)×ùó<\qÒs=\œ圪½¢¹›Jnæn*¹ð%;•ºð9Ms¤9™&}Cui3Ó‹ ?ñ¢1ì#PÀLIќϔWUÍùLj‡G6“XLí3ÑŽ©{–¬°µÎbW€ÎfQwBݳ´õ…Ž`%ôèÍ¥PÜ‘Ô*8T)Þpthªíðb L[;¨¯ªíæûVJ¤}Ìg»öºöÒlÝ ô¶î7ªj¶æT}˜­{ºvÞló”<[N µŸgËc¢fû£ °9æñr޼ …ÍzSŸçªWšË¹Büz39`ç uiïÍÓÔüÏ#oL=Gij–ŽJÖÎ:Šþ0wG‰W¥y? $öÞQÌF¦9Z|bÍõÑòS¬Ù:šYdÏCï@ÃÇP#ûîîšx†=Ä„]0w… ³7ŸÚ™Cü 0‡ó™m<Â.¢«»€U ¿ ÄUVÞà…}8\S¤Ç΋çôØÅC åcuÿÖœ.QŸ 5«ª…âu¨× ÅãМ.”£AÍéB9QÔœ.”‡GÍÕBÍ£ú¸HIsºH¸Osºˆ=Æœ.Ö~ÖœÿÁÊuWæô8r2§ÇQszy™Óã™;öåñÂ5š‹ãAíÌçñ°iÙÇ3[ ù—°¯˜Ï%X:IèÛi–©_K¨‡¹ü¯ž£[‡öÈ9ò”-ôt.^`Ö§ë ª-ðtzÄåêê¸úÿŒ]û§›þ?8Ý}søSÅ!©¼‘*fݨ~mÈ7ª™ËÕ¾ ܨfŽWûp£Ê¼æF•K;?4‘ˆÕݨrÓònT½3Utƒ3Uöˆ™AëI•mVóü‰?U.è5ªt̾ 3Üñƒ[vÀÎÝä‡Szbt¼æ;Ëö#Vrùÿܦd‚ËÅÕÂO ®÷ý”°±}g±¤EŒn‚Tˆ±ApâNŒ»0»“æ]W³¸ cjA7ÄÆ»>|Ùú`±¾†é‘iyOMO+9ÿÌr&nÀl¶÷¼ýS{Ûàꑯ½õØ“óOÒ9yã{ËÞfuÉò´ºÍÒ™ÇÏŒŸfÆÏ3ãûÞâjqxûñšÿ"=§lÌcÌc,¿¥æ.–ß2ók`¥sËOàE~g˜‹X~gšX;38Oà ð<7+à9ß p®ï+ÈÎnYõ!ï+wì‚抶5íG¶¶Çð#[sé F«¹>å’Y{ÙšÏQüÈÖ|»‚u³ ù ÙZe\ÙjþV¹3Ô¼´âG¶æo?²5¨\1¸‹ÔüÈÖ²âG¶V=7¼Ú4àG¶æ?²™k`ïG¶æ(—S Ap寽xÀlÍu.׎š»VüÈÖ^€­kN^aÔr8_ã~dk9¸°Ôv~dkSž¯u‘ëh­‹Ü³k]äJRÛø‘­UÏõ®æ}?²µ\dk\áIײr™©yr…³]s ü€ÙÚÖ…ÞW„K×èåOØJ¹Æãb›Ÿ§Ï^ø°ÕÏ{ÌIåÃÉ6ÿ»MØ>8ü½–OOµŒ’™ÓòLd³|eªe´ÅWàoU7O,#s'ñ)ƒrî*s•»÷$ôˆa×z3}*U\‚{M¯øXÔe£ÆMߊðº¢úd{í2Ô\™Ñ{ž¾¡Yµ¤ËTª¬:þµ•š¥ÝÝÚÞoù­-ÜrcZ«1»ÐtPÿ]_y”÷í Í+-B\òR†CûW^E¢ì;ÚiËÂVÜ[&oËT|y  ¥k,¥Žö›¢œ§Ö‘°r±é1ËÊ©1wtDÙÙñ2²Å£j«Q¯,Œl­^eÕÔD¹/‘OÐÔ6hñ­î{eE•'^º4Êùv]õÔAÏ]NKkÚ“xPˆ²ÛÜô³.QÞ(£¤¾Ç…\üâúú¶$ãyG;®ÖHå¾¼C¡ižÊÓôJÖDS4“âê)™4TYþæýÏc“$Êý&8~‹Oõî3|ªw ¨Tï¾Â§z÷W|ªwͧz÷7|jDîåS#ò‹º ˆw½)|(œA÷¿J©êÔÅ X5eŸjʳøTSþ‡ÏØò *?êuع•ˆÍSu¦…OEñ©Î æS§:Óʧ:ã ¡ãóÈ(ÿÌG%.£Üg“O-”eÔv,ù®{Ty0*øyÿú³«~÷þ˜>É™–ÕŽŽŒqËp*žSÕÖ!¥GàŽ·¼ï£šx´úHÙè=s©ú<“O-ôò£jdQþ 6@Õ½-+½kC¢óVÒèÝy´yž¢ÖNM[©«›Š9[9¤·!Æ÷,Z¤}méòRü:>5›?ó¨´T”û6òÉdråÑtÖFkéNC©íÑ™+]üèF(U<ºpJŸ{t;¿ÿûí_úÁc8ç3¿Ç[¥Ä£à°üÊÇqé)Y*ŸyÂ?_Ÿ.O‹œúE ÒgÚñ™Ø“š³ÓFxJ­±ºXƒï¿µ?tÁVõxÚŠ`ÌþNtHŸ©£˜ØÞªz<ݦâXÝô1úiG£ŸßzWŠ÷z:V™8ãôÒ,±Q¾»e\!Þïé8¹dŧž¸m¦ž|o¯¹R¼ëÓIœ€ÛX”ïOõ介Ôâ]Ÿ¶Ã<6¶’Y±…­ž|ou»R¼çÓcéÇ "ÙRœ·Òï¡WŠw|zܧSÄWbz-,az¿ P\)Þñé)™NwÒH*Å"!Jù.&r¥xǧ§Ã2=Û) i~Ó®|†¹R¼ßÓ³!S?CT1JI»ò=üçJé|sVØUbu‰P‡^œ øÚfïÃê²Öiÿ×ïǾ9oÜî›SÚ8ÿÉ7'9ûVðÍ9ñŸ·úæÄ Ò^ßœ¯Æh¯oÎ?ºmßœ¶vVx7_¼xëïýPf¹ÑAÓY,F“›s lÆþÀjg.’I[å¼¹UåӪʧ»RÆíŸñIjBÌs,޺ɶ”S—˳|éDnåS*|-¸9øýü²×Bu¨w<¤-¶…ôÏðÉ:çùö0ÏÌ“×o…±Ö«§ióX=M¸w^ƒžuoN»+BN«aF¯êúd¼ó:gô¹žƒw>;¬žƒw>Ç£Zh&óUÏa ´«ƒÙ¬ç°:£¶ÃeïÎÁ;¯»Ætë®U3(½¿’º¡JJš-m›’˜€Ú‹%q Å-«R*(« ÕUÖ{ÝÊ—ÇHº¬­é~eñtUKE\gÕRÑLµT¤j«Z*b»ª–Џ²ª¥AÊ•ª¥áUq- RÄì›Cc€¨žÔ0ìk JXõ,ÿì|úWV}Êœíã/YœY:FšøQ@Œ=yqÿ®}ú”>ùO¯<™4k–,ÝÁ:G÷ïÏ,#zË…|Šð¨Aûb#iD¹þ,–¿éáŽöQpߎ,º®àq½:Â>јûâ"78ñÙh—þÖë°öð0¸J’pªëTÈ *ŠÊC\°È¹§ì,•éY›õ÷¿ŸêüɪπSݤ‡Z8Õ¥o»Nu… Gn;Õm½uÛ©î«¥`qÙÈ—ròúc,vÕE/Y—-ïÊÉ.¬Šr§L–±ÂÌEádx¿¶èyEÆTž6®òÔyM}vµ³ê{ü¦ˆ‚zðÜÿÞƒié ˜Z—Þf=¸äÍAsø{=0–ÿô_²A¥;BþÇÌøK8!fªó}y¾Î_²]sÙäÚ­u·ÞSwÕyøêæXAÝ’H*_du?÷OuÏúKݜĨ{wߦæVÕþ/uñǺ‹V7ö¢©[G—J•õû™ªûÈ¿ô›#lÉoTÞ+»o».d×¾0Z®ÞoÍÍ.ìʳ]sþÖ^LˆF÷õbLùÇWw/¡¢Ù4zñÜ!zñ(èî¢+êEÌjx«õâ’!æâQ(ÐÝ NKôBx¨ñ¡}ÌÅ£ »Æ‡z!éÌÆWË"Þ®—gfÂô`ívLRïÁ£ð »X :(6þÆzÎÂëÁ£P¡»H¨ÐÙYij±\òzð(lèîVwé³Mßµ<óÿôàQQí=ßs#ê=ßÓ¾—bEzòGб7'sUω0QoNöA=§öåÞœì±zNè}OÚˆ9¡¸õæ´òì]98ëÍiåÚ»rB™ëÍiåÛ»r"˜Ö›ÌYωNkoNðq='Ò[½9- ¢+'"]½9¹;Ôs"æÕ›ÓÒ$ºr"úõ$Å$äD¬7§¥‡tåd·>i'Ãåü¡Ô>ùº)±HôÜ,åú¯dÂÍ%M§³ÍÞ`œÉ¿ùœ½ñ€ú•Kâ7e ý›ëí ÆOü'Âgdúݯ2%~S©täd­èdÚ©Ê-ƒ¤zÓ7¿iØwKÖ†zËðê­>gh|ú– ’#à ·føtÚ0@O†&IÄ)CSãÖ ·Y†/lÉÐïÐ8ƒ,tfè‹D|Ò’'R@øòr|€½€%‚cAÀÒ cf‚™]⛈Óý¤.¤ë¼¬!Ô_#"´½â›v~R£ïI&¾ åÌŠo"¬éw,F”½ø¦õ¤‹óâ›gõâ›hw‹oöñ@ª|ý¿œûSºPåæÿr¥¯ó_nê•üÿr¯\õ_nוŸü—«såÃÿå^܇(\%翜¦“ïýû9ÊÞÿß/½Qö‹þý$+Qòÿ|;•{áÿ|ì” €ÿ|”“ˆÿ|NŒ²÷ø÷ûŸ¼fü眎z×öï-Šÿû,Ä{ÿûÐÅ/ú÷éŽ÷ÿ÷5ïß÷Uü7ÿ¾Ë_üóú-¿ëϤüþ?£žòÂ?«òyÆnåî?ÃÃòóÿŒ@Ë=ÿ…ÜÖ7•TŠÇ%Nu|él‡®çÿF¿«rJK\=KÎÒîâtƒüϼºªR µù’Î!]ʼnðŸ sUa¥÷©2„óîâÄøÏL¸ªÔRîr|¨ì,NƒÿLw«Ê/•±P޵¯:‹á?sÚª‚LeN„i‹w'ÒÂ&®UEš*˜K¨ÈBAWqb7ügvZU¶©‚ƒþD9èF@:Šÿg\äJôrN \â+xw‰ZxÝ%~çy™§èA±*Cw‰Z{Ý%~óyù§FØÎT½D-¿î¿¿ÿ¼,T#4s'ÏÖ]"Iþ3æv%âˆÄ”¨EÕä,#ÕKÔ"ì.ñû»Pl SbÖ&)µï)Që°»ÄïoDM¸-Qଟäú÷”¨¥Ø]â÷÷bK ëÄ©Ãrs#Ï£x,»‰ÑÓLE?q¥o5²>¤aKÖ·ÚDç­ûKŸCâÝ}B|€>É7HÿÎÿèÓ†¿ôé± jwŸÝAŸ®±>iŸØ÷{úôØ…¡»Oˆ,Ð'aýËþcž¶üež»Ht÷ aú$_J-/ü>]þ—>=vÁèîbòŽTà)þr¯{Rü+ä„î÷¤øWȉ/È'Å¿BN|Ï=)þrâoñIñ¯¿{½9áçÔsÂÙéÍ —¨žO™OŠ…œx?~Rü+äÄ-ç“â_!'ÜÊ'Å¿BNyü®ø—ËùCñ/ƒG»Ä¿ÊšùmçÞ<ËÞ÷ºîÍ‡ì Ž·Ü¯üÔøMÙɽ¹7gÛ›g:™§Á÷HZ•?hp‹åß|+~ƒ ÿ«Ì±7¤z ’Ê,ÃǶdhxzœ¡á­6Z+ôUÏà„¾þiK†Æ¢8C㌭^nÞ¶5Â]x†EK³Ø$G€BGM§Ç™›Þæ8ªµÌH'Z¹ˆ´Ž& A©Ž~Úª£Ÿ¶¡êègû½öÑ:úÉ?›ê0KIu4 ù©Žæ—Äu4¯~´ŽfyJ£D¬TGm*ÕÑÿEqýÛ­£¿›©Žþòû¦:ÕªŽò§: ÿd$°®:È›ê(´¢:N‹ëˆäÑCu¤ûi |¨ŽrȦ:Z$¦:ZJã:Z>Ú¹ U-òŸ¦:É‚ê4&®cÐó­cyŸ$oiªc°¶¾êüܸŽÁL¨ï/z†õc°õ·Ô1Äú1äÖ1D®ÆUÇÉ«ŽV ¡©ŽÖ q­‹­£U¾ÓTG«|Ç©Ž¡gSCåOu ­´Ž¡ò¯ :†ÊWêæ°ë{q\Ç0lo=YÇ0ù{SÃäYAu ×5Bu ?&®cxë£u —)Õ1\TÇ]vTLjcã:FàÈëÉ:FÈGê!ß„ªc¤.kªcäÂ¸Ž‘§ì¨£/A/“ǯ^Šd奸èóR|^¢.=}½2‚^bðuq+ör}ÈýùÙ`½2‚Öiòj¬É¢›·2‚Þ·£Y¹Œ Ý÷yA/#8&Èâ™¤Ï Á%ÿE” “|ãѨ$ÿ‹"@åÄÿÂ寜ú_Xø}qHü½ý¿þ+Uÿ…ªŸüó¿“ë£ì‘ÿΈ—¹ÛÿLcÇÊÆ¿qÏ£ì/ý;a<ÊÞåßYÞQöqÿNÍŽ²æý;Oºø¥ØÚÝÊØm^<ñß)Ìñßþ;8þ§§öÆ/üwšm<áß)¯ñ/ÿ~ŸöïTÐâ=Ûä»ÛµOžœÒâ=åÉA-~â¿ñ‹Óþ5¯ø/ÿW<ø¿ÔŠ+ÿG¬Póß²!ÍÂiTÁ wþóT¼hç?`ÁËvþó¼¼pç?/—‚—îüçMVðâÿÂb~ó]ÐÑSþ+ˆ.ý¯p#ºý¿¢šè›ÿ`Pú 9÷)>5ÝsŸ}À XrîS‰¶w¦Ó:Qf6몣VQÙæÔsX•b›lZÏa•mn#õVM÷GΘqêl ô¸›pQ€Žj,Ø=¨”Š›FIqš´ÒÛãMQ¯1(J³·¬jñþµ|!”Å€Ç(êò}«lê[!*âJIe³ò¾¥ÜÖ ò->}†˜ÞèwSGÅíëN¹ºa7¹1‡hÚ(ªh'.ÊþÊ2y­òh˜:¢6ˆ`¢â;‰\ 8W ƒ _;ب[¹:ب½¡6jCªƒßŒ;ؤ]ª╈6ÉÞ“:ØîÑÁ~º³«ƒý†v½Äïu0Ë”v°Ÿ:¢öÓ쩃ý~çê'·Íê`³¶¿:Ø,®£:(•RÓÁfiͪƒý¥£§öç-ìnÜÁþR)UªƒfÆ0s°ƒhc÷v0{K³~¦ êš:8Àô,jN•k ð:8PêßêàÀÓâ”þ¥:8PV[Ä;Q[d®Ql‘Ž©:8H \ôÒ¸ƒƒÌÀã îÁ¢VÞÛÁìmO}(îà`S˜\ç,†¬:8Xdbup°7ÕÁÁšMupˆ®’ê๿V‡ˆò¦¶JQl¯SlýtÜÁÖkâ¶^3ØA:ÕÛÁìmgûöð’ÍôØ(2~-¨_f*•} ˜hÌ”)û20Ñø7C ˜hDß²f¢eK~^å²n¢Ñ+^b¢Ñ)^ì[«~ùuóêÍ—ù$òÝÕÚ öZíijôE_¾­yïʺÇy2©ˆæÃž¼Ë-@×ïü†ædÝ\'ÿøXYO-Âvöšêå ­íØÏ^³"ÕZ×›óŒ† • ¢¼_nHô@žÍpî¦4¦È³9¹CÛl(ÿbzx~·Íã-$ìƒCL3Ù/I›ïTÿ4ÁåH£½sg‡¼²ûã$•G¬˜'=umÞ[yñ5¥cÆ Àú®Ç9 ÉQõ$¿–¬r\~K阱¢‚O<~„Nª—’ü£¥cÆ£N4 ë¬ò¥Ç¯Œå=ÛÚª[kVD¹·yZ”ÿƒÇ[’hù¢ÇšTžýØ(”ßóØ8–'=N\ë›@J ¦!–;jðmû!•®ªúÔ ûŒñf b\ó)æÜ©ªÊS?Ý™¨ 7ró²LUÕiöƒt¢7èóvDUÅi²&­ߦ·d(æçpGr͘ćrÑ9oMDû‰àÿþÜg[¹ð+ê›kÛü~Ì$¾q¨rö­À$žøÏ[™Ä0ö2‰_í庙ÄtÛ LâqÆ$þó^P;'1þÄDsrE5l—K“‰#Lë@áòr›«€wæ=~zÕÄÄÁmN}wÂÁÅc;/y·%¦$šÚyqDça¡nØ£â›Jg-K§WQ†áÛX†8ù¸>â$BW–Z¾¶6ªVJWº/Ø÷š;×~ñ¦–wÂa­-‰ýLL«œù:ÁÄ—š®|¦'mKڵɚÖdèwá‰ñU§+ïÆT{bEkC{Í’Æd¢Ž…ÕfÇ‚,?Lú¤ûOWþ5÷ô 05:¾=Pï¦Öd›*tù¸[M‹oGOÌîƒs‹¶;–…;æpMÛÈä}£øAË-‘3#bB<Ð33·Â¤:·ÎÍ §‰lF¸¬QûŸßÓÃÓ+g%Ñ€XVÖyÉÄä#ÓüÀ­`®åM©3·›ÅêÔ¤5sídn¤UÖÕ3Ï óèÙú¶ödk¢¥¦­-Y·ôÙÏ~Ö˜`º66žÁ7Ìû?ìC«{®1XËDDç’e;¦Êa}6ØØœJÅòºá#LŽÎÐ…³Ÿåáé)^»"Æÿfâ-|·–ì—µw׳£ÒR˜cŠîÞ/kQUt'®¼Û¢É«œ·œ"/¨†hí³£½å³jç›a™ §)>žÿFŽç{òdêk¯í顎©!6“|íüŸÇ±Ì:éÏÒ¸?•«'•µ¸ëÙWQáê…þ^±gî$z1y#‹mUô4ÕÞõoTËä®}öm©ÚûŽ»«ö*¸bawþQä¾yáÇr§÷ÑÝKJ £‚w};¯U·F¥«£é%pEÒzÄŒñ5¶Ãwh1Ukÿ¤îIVkeýÄOe·t³ ·.~W!½(ê};žÚoŽº}Þ··G¹]‹÷ȱ5SKti÷~Ùk4ê×õáÑÚ-üè^ÔUY·_öº.ЦúùÀŒtån o7 з³jó§L|gÖþk@êÁ|öË÷{P>½»&ê†-¸Æß5éšãèt›SG;¬ÀGë˜GζÛF»Áò·ÛÕ;OõdGMtFèãwsªÆêÌväkÈ÷ ‡_øTÖ’·½3«îm«²’%ïÌZÆ\£:v¢¯µ3F˜ú@Oo ÞLüzõUñâ­ÄoToA|4ñ›ˆßL¼øxâ·¿•øⓉßFü½Ä§ŸIìv¾Ûñޝ½Òõp+«9?lµ}9¹ûÙ- Ïc¿èƼµ.ÌugדçÆGòܦ¸I˜ÂÌÕØè:‹æÝ—-ÖR²_öÈw>êöþH·÷ÁÑ%ÏŽ²Á'EaÅÀ¢…K»ö²]¿Øõ—±ë?ïú·Tk×ßýà®—'’v®1Õ9íÀž)|mû®ÏدîÌ”Åúø®ïªýì…ííú®Ü£·ïúî›öÈ<öu{38ŽJØ×»û‘h·9¬gv׊˜WþvÞÓ[Ëwz›”’›:Øõg[î% ×åOa—/éŠv/-[ _³_ÖþŠýhfâ[©gÑö^ôÌy›põ/À¦xý›£Ü·}Oêç„V_w{|‰z¯x qöø2â+ˆŽVülÍ€âmÂÑŠ¯"¾†øaiÅ×ß ,­øL⛈o!ÞNt9ßóÝ^ÿ]´çF%U‹ó~\zjÖî‹»ýÞÞ·ßWß»·ÃžºÇí÷ïäyïÀŒèû&ØÛº#h:?œšûÀجƒø?A¸ý†wf$6•ÿíkß™5™ïùü_änc³f¦ïWfÍ ±eäZAmgÃ,ˆáóM¾Ý÷‰ñîΑß7üMB±VÍ”æå›0ÇïsüýÜOªŒqÃÓmœý‰§ã˜âÜýF 2Èa†µõž¯ó–ؽÃ-ε˜nqiÆ{W\™ÉŸòm²˜úŸb·[L̳øºï+V“î ÉðLޤ0“#‘©#ñuÛb¹u MÎ ¹}Ýä¾ÅbbÕ%W†÷„_·:të,øZ•£02“£à{¯{fÁ÷›«Bß!÷Â!‡gÛ“ã¦LÿŠaVоgš³ÒH«CH¨49SGif¦Ž’ïr—N±›C>ßoò}ÖjÒ³tW&G9Êä(û™Se_71ßcÍP¹=äÎûZ>ßêC¢ÛÏ79¼¢9wV¼zrT¼zrTfZ]'*^½€ëBŽ­™Þ4„}ÐÐi¹uÛlX“ÙO g˜’¾½:” ÏFpJ0'½6\é ‚¾Y.!²¢6wJ×â}[.ɲ«ßq÷ÙÜGV,.¸‚ïÒ ¿µñÑs¡‰]Ò–d/oHÖ¶§ZûÈw›+Gq;Û½MïÙð,¸‹|Ä„¸€5ɶÚÖ†Òp›]VfÛÁ(vl„4¸¾m™Žõ®gšÏЦHK˜àU9Ü-öŽIߣ‡/øÜ”ªu_¾{í~ôn×·¯8{?/v}_qù.¬L!Þân©ÚBÛxc±±€á®+GkÕº;ô=¢j]¾G““ﶪŹSøžPU{ú”ªîS÷íZœÓI||÷*ÞlËñqÅ’]‘=¸*Úïnâª(_y§ònùà»™¼ûÝÁwíÔ5¾ª;zzºNÕàpü|b­†—Ûˆ°w­Ä&TE‹!ßd0oM|U´K½iÖb,}ÔBV¬Ï—ÿ¹e«³å‰Îx {kTÔõžœ çt纻˷®*i3°Ëõ¦U³q+}ÈkZ4cÛ§ÈC?ÌÙRÕ7ó©·×èí°{rD?´·­áÍg«^=½·Þ­ë­Fí³|6GlžÍ¶Í3È̵ÙlМå³4Úfi„by/–nìá5ѾêãÖî¸y®6çOV8~Ågó§¤ï~7ÅÑLðò|¯´RňêžÜ±ý›­ÏÝôWèeá½(Z^mEžØâE¬œ¬·˜ösŠ#…-’«Û¤|Ú=)²ˆ¡nÅÈkÇHœ›ï»ù/~‘ùæ¿Þ'R}pß žûLLß²Va&¸W!&þS/*‰/•ÆZB¬5ÄF„Øèk ±ñ!6!Ä&‡ØÔ›bí!6ÏðÞÝ:ðV¡DD.‡·l-îÁ³Ü-éIˆÐÍ¡cC]»<Ù|ÂÛ:eÁ¬YûÞÒÙð…t9íÈË÷GÔi›œ8Âã:yv‹O«ÞãRÊE×­î¹ÍðÒ­“¸éÌ…Ïge`E߀·Û¹_v7oŠ—ì—}z¼“’5ì¨O`#(GëÀ jî·³× n„ÂPqí)äÃm]jGŠ7o ÞL¼…x+ñâ­ÄGM|ñÑÄÛˆ'ÞF|<ñ Ä'Ÿ@|2ñ©ÄgŸJ|&±v¾ÛúÅÝV{»Â²ÚÝ'³…°¹aj¿.P2ÚÎ|Tw-¥sXTߦ¹Úaªrë 7¿G·»Àß7¸G­²wšõô¥wñ0Û3xªëT(ºFMr{F3Ÿâzé ÇÒ¢¹®ßÓ /iv~ÖÞºÛíd1íÊaF¸+þiÖAÝ`~õ·¸îçÎæUÅ›‰7o&ÞB¼•x ñVâ#ˆ&>‚øhâmÄÇo#N=ˆO&>ødâS‰Ï$>•øLbí|·Ÿ}aÖþnÅrÜEOVääN¬âŽ NSo¢îüÀ:?¾1vß>ågruÛŸ&òŒŒÇFfÒïgܰ¡ô 6ÒÒ[\a›Û½íÒÆFxb¶Çó9Ñ%AiL²ÜÕœ½Ì¦=<¬x[Á”ôMC^ñbi‰±ô–Þ}íïìçöogɯh´–¬™á2Ëú ðYü ûëgØï\?Ã~çúö;×ϰ߹~†ýÎõ3ìw.3¬{ç²’ëè…à »÷ì6v¬»Qt½íÀ¶ìÞêε¼õoùùoÿÏw«Å˜o£eçz¼Ë û{ï¤4lv.~ü:wî‘RÝÎÕܦ»C¦ Çõ·€Ï¿ô܇>/ú8pG¥®têÇ}O›âH˜KÏI‘82qpGš ÉøÀ/¹üÔ/ÍÀ?“ÄåÀœÀ¡ä?õãõÉöÚe’=È'ÄñFkLÏ oê*a<~É[o~1EO/rî¨âèó–æ:ãO?××=áàÎÃN—o¦v'j«%(ô”é÷©×Nüðþ=·¤U÷n gf.žï¶£¯½®íÿ¹ó-°`R• /iMT0iRvû:®­ŽËsm ¼j¸b)&Tœýdr–ÈùVŽ´o¥µÔù&ÝgÏËðø:k;ë»ùS¶.æNìç°4ЗMÝê˪6ð€ÄšOk÷Åô¥@_:y!äû>«IܳýÒ\§Ö>íºž:>JoÛôOp›J%š‡©yìYTEÏnŒ{Öчÿѳ (øf¼Š ^^™gmZ'ƒ£# àv<ûÙsA,·û]*cû{<ï<×Á´)·ÃÞ±g='ƒwžß 5ÒÈs xw[æ®]¹åG·gb±ï¶Xìy àÏÉÐn}ox—sbßêðÜbŸ1ƒý“LÖMÇáíÚôv°^õèt"lsÆ·6«^Þ: í¨rqogoìwºsùº}m‡®eÇáÚÛ,?Úù»&ÏÎS·.>¼o'¤û@êm¦†ÞÝ!%ŠœpÞÒ_³çìùšWPóC ÔÜ{;êVÁœ †­ï®7õåÕq7ÊöƆËùGRñÏf¿Ùf_ö.vcØmAÙRU¦Ê–ØÎéU‚´y¬$’^=ë½9í^éʉ¶GoN‹©»r^¼=§1GÒM”Þœö^Ö•S y{sº[õlÏ Ç¦ž}ÇÞœ–£rZ•Kðu]Á’w^ ì^ÏÁ;ŸÜRÏÁ;ŸƒUWÏÁ;Ÿ¼TÏÁ;ŸÜUÏÁ;ŸƒûK=ï|n7õ¼ó9¸“×sðÎçàîZÏÁ;ŸžC=ï|8Lõ¼ó9П¨çà϶E=ï|Öu=ï|ô9ê9xçs ÿQÏÁ;Ÿ­‘zÞùè—ÔsðÎç@¥žƒw>º+õ¼ó9àvÖsX¯6‡ÑCìÎaý¼Ú,ÓzëßÕæxD!ÖæxÄoëÔhÁtõömÕhÙýÝj´©¢´Ídϯ$uTu¿D6´tK¯ç[ȪŒ,US§â@¯¾1'$M‚FîË¢í[Ÿ©ŸC ŸŸR[é§ #¤~ Ÿ˜îõƒ]SW?®ÒwŽv¦¶˜+]Þà<¿?݃ Ôg¶1„*œýÄ`hTcê4 ªR«ÀÖŽ¹˜ÀOsŒŽxã€94PF™Tï@ß&Ô;~{BMßË·jˆ’K‚~p °8õµ€ÖêD’µ|s5T½ƒ@˜ÉGù–zn‚ß©Ap jDmÉu,é¨&ôW¾G£l”¨ã¡¤i¾¡ÿê‚2lj¥Ç8Mo}ßšÃÖ3ùVÝCÙŠÔK‡‚x ¨—%P}Ê-¬Hm#iœ~ g‘|#È_¤?#%«¦ûåH@‘9EÎ"s0Jê8êÇ~W0³š©ÑÔYâ°²?èWØûs§+Ñãýéi‰šö'w eš1è²–PMCJô} ·Ê³5–þ”èûX1eUßXPW‰»ÍXT‡KÌÂX4WÊl‘6îíeæ¬ Íé2׃6 Åmø<-Sç8eú7|Z¦ßã˜á2µŽãj]¦w°ýÊÔúµezr šÖeê]˜Ó ÌGs:ÝÕÀ|JÝ ì¹CÙ?€ëCÑ$n ïDöN¬³‰(7з‰(=50“˜›FvÜT‘9ˆMo•Φ·»Ï üOÕÅ.mrQ¶"²sV9Vy+çL›·§œÖÅÅË…ud ·ÅYeÓ[mZù³š4kyM@€¬&õ3¯‰¼½5Q¯ùÍzUÜ×#žë´ÑðÜl;I=è™þ¾‹¦þexmŒŽ`F`ÉLƒæR-û.;(fOÌý˜»pE“å&HŸ'ö’ædÊÉ0ýŽB·Yw¡€S…¹µOÕ½@“q*Ó‚^ò©çÄUžzÎ_ª\¦½¥Þ.“&¸fa™.ƒš…eRÂÖ^>M—0í¨ÓäOI¸ë4í ášÓ¤õ-;Еӥ .Üuºº&pú‡™í©å² %°¼*†]4ÆþX®}¡:W°ßcöÿŠ·ñ­}°B8Rxgû:oœ!©=pÆãnŸñE×ÑÚ žHô×Ò3xB:Ê5žþÙÞuC­ß™ºiß©«¢z¦|iž)Åj½=v *ŒgIƒ_=?Kw3ßêwÄŽ:[¨\y¶0ƒ0æÙ¨6ÆLéÙ?{ô”xïd=¢Y`±tlñØ(÷9|ΊrGòyD”û\>%ë=…O¥8œO‰i_:v²ØKøœ&-÷™£œøÌQc¢ÜcøTKùT'ó©*NáSUœÊgû¿k¤§âÛŠ’µÉ=é§Ø Ç©œW„ô1E?Rp”û뢚ÚÚ$Tà ÉŸ»Qè‚¿eË£œ%[[Å ¬7£ð£¿fn¦:ìîIô ÏÙŠò¾½AꦴÈÉðFyl<í&w´7D9ÓP­ò¾S[S» ªÚ¯Zº6VÎ[Z¢œ§¢\lG¹©ö•-É(«µý$žGf5Ê=ª¶:zadkõŠ(«¦±÷óωò¾Óz‹ouß+c‡½QÖÒ¥Qη몗D9ëk–S`ãÒšöäè’ñQv›“Ï_ê ÚÒ(£¤¾½…\üâúú¶$}¿£IgG¹/og$Ó<•§éÕ Ê)œËöÛzÊ_& U–ÿ€yÿó()ÈænªXå7ºŒR¸¿Ð¦!î–G”[Éžšå½àOšCňx—6¨ø÷¥cYÆÅ/ñ©Ý÷WíɦnÏ æU/Y©vþ:ï´Rÿºtìxžÿ ŸBx+þ§ôCñ6*Æþ?… µìâ¡¥cKXîø„û›ÿÉ‹/F“Jǃ&ó©èa| %LáS(áp>…¦òyD”µëÿâÞ>l ¡øÌ¢ºä’޾Å/@P|A.lLE¹£è‚÷ëþ'‹RFfÆ'ÀmÿY€óˆ¶üŽAåðÿœÖÊÛþsmT>òŸ++¹ñ? Rñ„[Ê¥3þ„5û(ð5 Sžôkîí†n*ÿÚœšÅúh¼N1â5Õ†Bw›žW˜·;Ž8ά¡vލZùß” ªŽƒf´$>:5¦·‡Î]ÿS÷¦fŠ` ÷¯¥ñ ¬bkÍ÷_\jÖV—Šô€ñ_ÜætqÿU=¤fmõTx`gÀ£Ò¯u Ðð‚Wª7ºz‡¾§8ٹׯuõòÉm© ÁWÂ(˜ é.x1ñIšäÍÇ7,4n²{9†?øýØW‚×/©ûJXøï¾Œ_ƒ>|%lMl·—xù6_ ó.ÙîPÏ{cèËÀW‚Õ}Ѐqet:¿àôVÎíùaZoEkÊèÚ?Oî¥Þp÷ÜœIë¡ù5o‹†ËÐKßÕ.<'¿§ìÔì¨j±sA5º{/9‡æœCI¯è—d9ýãÑr&5ïh]³Á \û·qõrîÂmÔùÙEëÈ·¡uhçí`çªón*±w4]‡–’½{nëꎊ»js:«N9} µz÷U-Uëv»lÕçrЍ«¥M¤´¾7¡û­N+Ïèq£G½#Ö²•.¾¾·IÓB›¯mï(±j]nq+Hõ4ð&vÚTh *z€~ò²¸–ÂÕbë(Õ»:t)—&p´ŽÞžµžÞíÊîD#IšÈè k’fðŠõ/\ÖuS\µÌ[õ”\°KOÕYMåKz{£zމëz3óþ7®Ž¯–\Ð3PÇÆþ:ŽîŠNyi¦†y-jxñ[{vI× ÞÞYëŸuY×ùQQ\OåR—K:<+ÖñmCâAËEû£ª‡aWèÒhDÑü™³¦W—¯8zÅo}pdZ¼Òp²PÝøgÊ]ø}*èã¶lsÏg5qœæ…åaÛ½'Q ŒÊvNÓÊGöÞ-÷í½ø®!ö^9»Í£«NëÞWûoëÉ9ì½/¥÷»Éï=4XúØ{Ú©÷ß¿÷ú`ØQgGÝsߎr;xéÖìj03M¼gÿšz´ûJØyKÜÎ;}ˆ‚çu^`uî<ãíÀí<ë–ËîüûðóSһиGûÑ.œRyqý8¯ë´ÛŠûFûºó‹»ºr:ƒÃ64#Óº~WjfçiÀózM·Ó¦ÓÎÓwû§ØyšE³óô½ þ9Ú@g½’]{í;éúÈ™›ÕiUõÂîS‡vŒ¾m Ú1y {wŒ©G;ÆÕó¯z“;"ìäŸ:‹•ñèÂÈ÷E[Ø^/Ûî »#8JvjÝ4$Õo·#ĺ‚©p§h­raG …Û¹#R}\·#pXxt×i¿°!LôÿvD'.R_ÑÍ·;ÂÏvª|Œ›q ô~…ñ.©ïŒ€K\MÚÂßÝ;ÃÔ£áêù×qƒÛ§1°3àvÃ΀çw†ˆ) lÿJ#^²}gd®ùþyg”ïÞ¾3ðÈй32'™«¢]»öÝëM]Ñ×®ZÛ±àõklVg¢á| ØŸ-ÄvàŽï>ò6ûÜšÕùUѰÉ]{ïÕÉ›mämqþžÈ»5÷é-U‹;]çä(÷¢‡rÊÍŸöÙ ®—ƒy®¹­¸d_0ò*v›0ÄÖËÿ´ß\WÄ5ké[;oG¼›´ØMâë›}$ï guKû½ûVv9M=Ú™Õz´3;ê1{yU~æžv%¹zœ>°Û’Rí¶…Cà!<¸y7€Ä¾™‰ÅÞ ö_̽¶×ÑdÒöŸuâg÷Ÿ¸Ø±<Ê莾ÿ”‡oInç} çé6avÞ‡Ùy ;¯ë®ô·¿í¼]·jç5OÒ-Èèc;(¿=ÙZµ+ôÝ‹Áw}û³ç‹ïo¸ÊÔ£]¦ï:7wÍ;wXôf#u öÍ¿`©p¯¹<ì˜[®ú–í˜Æ¸êËá^c]Ú½". 7¾ÄrÜ‚ßêy›³µÇÜþØŽ½qÇà;£sǤ^44—`ñst:Ûºï­ÅäÏvC^K}7Súø×äSÑ›>òíèlÉïSÜ‚÷ŒA%µ»îºv•óéòüÛÌÌê¶ÜGþ½c»ëÌEaÿ£³àçT-dNË|ÅPsú×ÿoN"`Nû ¸Sø9EÇaßœZg’vN¥óPA”Q™ð×C.Ìé#÷O3§ÉX¾[ЮŸ©;èŠîÜý©¥Í{21xlµðØ_wâî ºÞñ£b¾ÛbÎŒÉ×r·“¹èkÐÝQÀb?œyWÿ²Ç°þ<‡ßÂúªkMèÍÔ¾º:ïnú¯ÄŠ)ïäGrEŠyžƒæäþ’ZqF¸;~–³/.íè©?ÀSÈû÷9?Þ¿É-Ú¿b¼÷ °¥3›qä ­×Miaï°‹ÑYyÒM©Íó/nJížÿ7¥Ãý‹›R‹ÏÿÅMi¯kS4qzsÚûjWN¨½9í¿+'ú:½9-?¤+çâí9-ªšó =N›ã͇ݘ6èLB-º1¥3ÊP’6—²•>_²KRÑä–¤zƒº<e;î¾ÐÇD£Jo*ºÎh·7h2Ŷlо“¾W£º"m¯FmiÓ4rÇF®‘ºÐÃl„RŽ^Y“ôð”·I—éU5Í™®MmŽ9ˆà7œ¾º5Êëøì¨áHùÒEénæy2ówÊͰLçL¨Ûd¾6ÍÏ8/UwúIïOÙú1ALA¿¿Š§ ªjdk/DSÐ ˜)hÖ´h 𥫥)è/•0us€öЦ`À_ÇS0@j]š‚ò›¡:q%£š6ð±Úß@¸ª¨´µ0¨z¶HISÐÒ5Áx%¿î)h‘–©jj‘‚‘ºÞ"í4½$Õ[u}¶²XЃ¤M'»Adš‚AÒ'Ò ÚÐ~¬E¤}2MºÍ!ÚŒš‚!¯Œ§Ç¢h¤¶ªÛ;­t4fâZ»Þz¼»=d]§—Y×éeÖYf »—­¯‰ß¶Š‹®^¶JiL¯[©^•ššz9T³ ^•¢z9ô²¸—äS¦^“2·z9LxL½®ZÕËáRP/‡Ã@Ž©s3³1FHŸSÝèåtDþG/™&ó¡ÝLÒz¤—#l'жQ/GJqX½i:Œ#µ‹ÕË‘òM¯^Ž«[½%]Nm©Qbß(4VÑ…SÔHšªŠ¡¿·¨TÄh/¶GŽÑô5¦ŽÑr±¢ÙMÐWLÎý¥M©¼û÷|ä`þGÏSw¬ûkkSî¯Í‹®+›T}Ø_ÚSšÙý¥.§lc´5c´£Ôû1ò«Üc¤&¦^•r•ægìÑ|Kø MèM¶ 5ö˜.µ¡‰S‡ÜRÏÇ¡ðÆF7;îå¸Ùý½¬mà®-ÛÝËqÒETŸÇ¡åÈüŽûûx~ÇIGL½3béšß”_=<@èAó{€Ô4wŠ•®ù=Pªêå’BÐü( &”1^Ì#í¤ñ]qÏÆŸÒß3fì{=K5>ǃFÈ;Þ°ÀxÃ8ȰÀA†’J¹zvÅÔ³ƒueTÏ^=;Dh_=;DÞwÕ³ ªC=›paܳ   g¤˜¡¼‡J9[=;ThM=;ThM=;TªíêÙ¡šGõìP镪gU£z6QÔ3£ žMÄÏ@Ä.˜(¥9õn¢t"ÅØš$•táŠIoŽ÷ç$í&í–IÚIbµLÖäk6's'Äíd0{õ0a]õç01h„þÓñN»ê0ö1ûõ°7ÄЇ1h?†ÚÚ·±çú5Ì<2…ý€Á”ÉñìL9áÎμ!:T3Qœ“XŬsÛ¯õ9·Õ”¤ª7Þ¥¬×÷îgA^?’î]Õ29™ÚÌ.³Àäü¤®Ì®Õêó552ç¶™;\¦´ò“}Ol-àá­s[ü/£jà°‹yÝzßïî–+.Ó©‹[ç Ò9·ý†›Á¯ñ îÍxB !•Û‹ÇŦgOŸ½ð!ã³¥›Šä]ríƒÉ´©?ETBëÛWV7¦R'v´ Åa¶”KÍÅ]ø€¼´±]þg+äïF$.µWØ£½3Õ2Ú–¤ZF)P|~du¬{Õ<ýâð{$ëí{,m©2Θ06Ê»ùQ‚nqYéØÑ£¢¼O?ÊyŒN.Zšl¯ž6cVÍI+{s]¦>Í?&Ê[þ(› …HútÌ£D*)IÎBe²ôªGù<2‹;kL1҄ߣ R‡èÝüßg³2mÅ=Ú‰cíïŒG§fùïÇ´Øñèð_ôû•RùÖ㻪rËŠ+}è¬Iê¶É‰EOI÷Aàý‡=©É«5q kÁg”-Ç €)çû5QµŽÖ­ÎDF”® ß?WˆOkå3Â9¡ÆÜòļ»B¼LÚ6ûÇçŸr¼V(ä»0 &‰¶?·Öqºý›B|GžÜg®/6ŽÓÐx—ôÄ®MÅ¿»?]!^ÜlðŽY‡~J#6JŒVKÿ»þC ìÀÑý:éN|h>¡]ÿWé }Y,Òý+ìÀ*ÿºÏD'lÜ…?ÐA»ãÝQùÑ@Ó.ÚC{çÿh¡íôZh-Žž½á}r²7î¶]c®S/â®°+Ðô»B:y0щtÕŸðR»âa·+¾Â®˜ßuÚmWH¢ƒ]±oÆÿÛî˜ÿçÝñcÜ!æ™ÓDëS`wÀdìÜŸ »-F¿;ÄÖKdÿ6î'þC­e Z+öíßVÍî½­ë¢}ww-½xÖãZhÌj®…ö¸ž;I:`ãº^vù±žÙu§Ù~êÒ3;»OÏ,ÝQõòGØ)Oèœà/X½lëZîÿGÓLÄRËïù¿» ˆ÷†Ø—ƒ>ÇÌm:~IIØYF°>×ñôÛtÔCUà¸ÒðÅã:|fgï<¥jñQ×;Õá3{kí-4Ц h?ÁU÷ƒ«tq6ûEßûö‹ÕÑyp¿¤˜ÊÔ£¨ïªžŸøÿ†©þóÞ*zm´>ö–÷gÌÞj·½…~ZçÞš·YOJ¬˜Ó1§ÿ‡féÿÃZhpYÝÒs˜µö®½o“Ñbr ›Üxæ·£ug¾¯ÏêõÿÕàjñZi}àâ;mVÑÄÙí—2ŸU”ü¬JaÅ̪çã.êbV¿þÿfUž«û˜Õ¾n~VÑ<Ú7«(àøY•®¬Êü?èsCUÜJã³t+•¿àX5´/v:i†?°µ;æ(_C×;~¸Uûnvû—Àj õ¥Á%è{B“l‰×$ë`Ç})pÄ3ûBe'ŽÜö:^“ •^Í+›Çj^¡Oæu²Ð<ëÍiwiWÎ}Úg+uåDëI}±sŸ^š½ûtåܧ—fï›]9÷é¥Ù{zWÎ}zi–¯Ñ•sŸ^ZÐ$s9ûÐ$£¦º'?Îh’ö¢¾Ù7ê¬ñ䇙¼Ì± Jr¿„]—žKYÓ$>qAE b=Vð²‡ó³Šô5¤ÛÒ Ç  ÞɤÇÒpAìůMtW`K⡯Q.ž”³ñ9iÿdê[(qXõ-ïÏÊ®mtq¨ mõ°É”štÅÑ44IKï&| â­éC|K­Ÿ?¤ñÒ;=lÖ–S›y‹ÿÀf´§PcàÐ’1~å×®¿´dÔûþh;Ű[û_÷²ÿÏÒˆy¼—ôFyñ$H/P+½€n ½𾸗¤¦ž TH… ÅÅ£ ØJ›I½(½õ¶{èé´ÈC˜Ø#è‹¡6“-èƒ B7 ­¸Aëã^Zÿ?{™êƒ ’ê‰òÖ\©—ƒÙ#ôr°t½ÔËÁòާ^þ`ÜËÁÒ¤Q/‡h]ª—C´›ÔË!Ò S/‡HÓI½lÕÂS/[Á–ôr(®§ÑüŠóôÁ†¾:ÖÐú™¸—C?ó?{™êK Õ)ï01ÕËaz©ÿÃä.S½F¿èå0îCôr˜üœ©—ÃU¹Þ—{Fõr¸z­^‡í…NØp¹íÒ®AÝìšh;ÑË‘ÄèåH{âeo$ó‹šïHö3;h¤tôŸFÉ­¯z÷Ñ©¹ñ÷cZü£ÃÿÔ߯”Ê??¾«*Å㈾ ¼t2ktG¯à¥6¤ ^ßi‰ƒm^Á«žBaãTÁË—ó}yˆš‚W ý ‰ýz/Õb¼¾_ˆWðÄ•b¨.j^ÁËòĸ»B¼‚×пï#¿NÁËò]PSð…ˆî˜XëÌ*xÙB~Ô¯à5FÖ18üx/ ùîút…x¯q\yâ d qùîºv…x¯ƒ>Ç yj¯àe y$¸B‚‚Ü€D÷_] ð 鯑óÿûõQ¥àe9†ñÓÅÈI¯WÝ ¦/ŽëaW,g€°od™/ïVŽÈû‹¬!jÛP îÉSñÃöhŸjò{ØD0ò{÷ü™~G¿}¤»-GIÂÐ~Ûc we yŠØi­Š†OxGNTM¾–?åìG-k}}MƲVàe­™[j~ýi®æ¶?åÙÙ*`gkGÚÎVyÔv¶îðNçýwzï® !;ô†Ò !¤“ÂþÍ@é ’w"‘a4¢JÃÙCJì–£w o‚ ÒŸ7Y ý݃9ÝRvÉÈ ý‰,b.e—@²CÊ®¥cHŽÝ4áO»)µ°¥î‹`7=iokÇö¶”ÓØÛz›?¶“¾â%œú,ØIÝyÉAa'uHä¡R…D^ëÒ¡°y*-óŸ°ù“A—ƒa;åœþSÏ ûEkßöíèõo{gô8„Óþ¯|Ð"/õÔ–]6;ß=tÞ^¶n–“Ãh‹:\$6¼y¨Žùþ»¡ æ{ÊóÝGÀ½#o¤döÍ·‘Çwó-»=¶çF-ÿ³\ ïÌNW¾ÌìtµÇrMÿŠ'–LfòÝ@-S……ë§ÅòQ‘ä£úmv7›]£™aÉ`š\좺Ů™[zõý›=ù®ý.nOÚïÊ{Ög„ý®òö»ÔçhÊPö»:dãSé«bTT…©¢ºüwöu¡ÐK]õ pŸœg9$ø’\¿M†¯0+ìn7¼ÔÒT½RJ6•RBPÄË/!Õ›Óâ‚®œÈT<)Arî“á T!'òL½9í¬+ç>é.{×íʹOº+HP¹œF^ Qžº¼”•úú‘5uÞJRxD‚ vŽnK%M ÒS’ñ¡“%É9ƒHO•°N€THI²MØâBüAÒ eIVIŽª,»J²qQ–܉¤R*È…B6¸Ôý]tTOƒäd$5Ò€5#Eµ3f[5¬u¸.Q&w’‰H œ©ÌVyƒÔQƒd°ô¶Qã¡^6*«^7j:T{£hŸêe#–˜èe£h´êe£"ÔË&-~õ²Iž¡ÕË&ÉÔ¨—ýàŠÑ“~̽l¦.,4533Øj¦Lm5¯Š{Ù¼êöÒØ3 Cõ0¹Í²z$ÀØ, 6iÿ]ãÍÙ_W6I¹ô­Q½í¿oõ¯ÿ'øSn€.ÀôR°s5‹$Ø€ˆìr?‘qAîg l6€u ’@Hµ ¾SsKsÜË–æþ^"2’õÒ‹ÒØ^zQÛËTî§E,cõ²EûÕËëP/i%½$Qe$¡^’%õrd¶ÔËÁªY½ÌÞ —ƒÕCueÈñq/‡ƒ^ÁœW¥VÙOÒ<·êÊ$iªÖ긗­ÕCô²UûN3Û*v¹jo•Í'í˜V‰¨wCňӎ*dÀ7(G;f¨,8©'CE)ÕŽ&„¡&Æ£æFªJÛz¸$qžŒ{6|éÿÜ%© ÐpIHé­‘»RφKvI=®¢žÔŠz6BHM=!¡?õlÄãžÔ>UÏŒÝ.õl$sGÏFJˆE=ÅLÓ›QqÏF ìŒÿÒ³Q²„¥·FîJ=%™$õl?¤žíg¶Æö3[cûI^I=ÛO»[=-t¤ž–•,õl´,Qé5ZxL½MŽ“'£%ý%y«ýeÓJ8`Í€‡ûKúM¬Íý%a$–Øþô:¦Ö1êµêƒÌSLýc´{$_7æSñþŠÙ­cØq˜¥k ƱäE@{,ûáԱԇ኱0?ú2öeñìŒ}Cÿì0?ØQ}‘H 1•žTìåÈ ¡ß˼Œ[Á˱Ý{%˜£ŸÔ•ÉY9$_#'”^ $ÜŽý¤Fß“L €d% $/‡DN¡¶´/Cƒ’Œ;§Hㆠ@*ýìQâgæoªùý£óV"q´[þhu”W5(´;Ùê¡<¤Ž¢…&u¤Az”ŽÚ£ÜóKÇŒE°çk’‹O)sÄx¬~ƒ¶O‡HÞ ¦‹òÚe¿X:– Rú›GÉ'ÅC‘-’7(cä‰tS‘-R[ßðè)µ[þªøc–ÚÌ(wÏßउ¶=Úœ=Úò×=:H«~?¹Å?ºîüý:î›@FH§¦T¼PÖ¦êy|zkB `owà¶B=¶'×@M:¨ÚôXM!fƼPÏ÷ ñÒA-ìúV]½P-äGñÒA­œ‡ëŒç…z(ä»ËÄ⥃†ske­µ;Ë õ|¿/4Š#ÊXy^ôB=¦ïî\[H%h}4!x;PWÄ‚u‘)rY-Æüsy±rÌÿû×g€Ö‡Þþ'­T'£Ï­çÞ¾UëC/ÔúHßöÕ õakçVî7Hõ¥%@Ý5˜rkkêhkO,I&š’M‰Ö$#— ßÈøRR¼eêÜs¦OLÔ×44¶%\ò͉öd€±ç¤‰'K8-‘/mä9Ã3ÀpÑ2^_\%ÃñIµÄð±mo'϶ü;ȳ#æÿɦø[Û±€°â´‚SŽZ ?ým8f¦¶BÁ)XxŠJNr{uCŒE ÝûtÃMCsC1Y¼¿U=hGR:·ñ\Ï«;££ïjÞ…ýëŽÌÙ܃¤—ãxåic/ÊŠ&v±uèƒb튩~ׇ'xÆð«hÆuåÑËg×ü‘klchFXŒá-Zƒ¦ZŒËÙ<‹qÝÞb×Z ±àÛ,Æí.‹!+úõL,žÉ'nUš/®ÜnýåæÀk†Ÿåw¼&1bîšÎF‰Û?wt¡vä ;Œ*žÍ7üív¸‘Ɔ¿ì9æóµ„ùš¯ùªÎ–-}Qt`QÅœªQÁ°|–šƒÝŽÉÛ¬¡Ð·^k(¦§bÃ4}}GO â!þ÷žÎø=í¶ Ríi‡mØ1¢öÍã=5í«ðÀŽ\뫾_ú]öu1§R3/,·pGUôî+ˆàlŽ ïýö¤Ù¥Î¼Áê<B€ÚvæaeÅc\AæÁï0öÜÒ0k¶YÏŽ.h«Úô°¸ 67å¿bµÝÒ–ªo¯æŽ<'±¼¤¸d|‚kèÚDGs[G‹0óZg~.³ŒÎŸn.˜)p׎ýl¦ô½m¿ô<µ`0Ç?žÑz(èÕz˜ ìb9»Åÿ1c;ãsêwN‹Å˜CÀ$3-SeE˜½-ÛlJGW…Ù 6$öqƒ ØEÿÉRDÈùK!ç,E„œû,EXÜrnt|HßìæCZËÆ6Ç#œI›ìXÏa¹š–{Iñõ¦)Ž{Ioº¹—±¸`̹— Qì?è¦aì? £®-QOî%œ0q›Êšlɱ—eÞWœ¡²¸9Ø~@ò_2ìmY8—p5%sYÏKW¨&"†mÒ +âP5p½5L¸LâÒ5J(ûû»› Ú›ækÁ_ãâcH° û¥Zp m”}ïÖöØg*¤y™d²Ñ”A×(F–f¬Ñ ë6]w¡IL/÷kCI9ú‰q¦Í&ßlü̘²ÊaHbÊAïš%¸¯*û«fÝœ¬NpÌxë€ Ýõ,ë²òw\*X=víh‚¨k€¸Lêí@ ú«—5]š´bÓ 7¶×Õr,ñ¾9˜W¼Ð­Íð¤²ðŽ`%Ù0†¾ØYÉʼȼßžá[Ê3œ˜+ÏpêÏØNÓÇÎ âñOÖå-P|8_#jp;ë¯ûØY€ËŸÔè{bka·Ãé²ì¬ƶâÇE’˜g£ù¾pÙt,,#J‘fb‡¨36f™p¦:¾„¯Í”˜Iìã¯UL–Žœúù|Έ²*þp¾K\…µÔ47ÔVWMiçw4»›gTN«MFù-h®KÖ74'ëæ:ÂÓcu=5&„=.†ŸÌ-j€³õ@ÙŶ¢dgm²ÅUK¾™Ü¥_n(²×QkL²Ôãjüiw*_ÙTÓ‰6‹­o ú0òZ!ÓwU,—0k[’­­-íÈvLŠ¥Ø@5ZBûÝ=¯x"ÉDqü豫XÙÐÔĪz!’ÿ3¢Ü ÄiÞðû+Îo8~Û©›ømo£ŽH?Q†£ƒ½õ÷íJæ=2ÉWwË}ÊÛ¸—ÈÓFhA°)k„ðÕºÒ!/Þl“Ì5«6Ú/¸ôÝ‹v•ÅÕ„sšfw¨2EèÌEß9!W\ÍÜOȲ‹P jAÍïN·+Ä3¸p¬i‰éNtC2tã;ÇEGãɸRgRÑ3A§1(ùLxSCÞ DÄ0 S+º0ÿŸß¹R•í\© ‡ÄàJØÊ•ú“Î߯•º ¹+ÿªÏ]d”0 —iô¦[ºîçóì~ÿ ²‘§36§4¼/¾_S}ª‡ûï¿sCßGôMìƒs[“óç—oÀU×ã¹ Ü{=—‡˜ç)Û`·rÃí踕ßnåAß—K—®£ÜK/íÕ Kµå¤ŬÐÓmè艪뾩Ÿí“±Õ^K¿£Ý'ØÌìætX›_¥ÂMZmÕù°¸ëšè¢YÓg/š6ÞƒH Ÿ•6ôytà:y޳rÎ6-äèr …›ks)ÕBÆà Ê•§>4+êñ¦¨çS¼mß17OÎÁ*æ`yÕPsÀ:›o½ç ÝÙûBïƒ6¯îŘø1*Eg:^à‚ž[­ï;'açk;º?ÛNÎéÔ¼oÛ'§å’¬hß[ø^Zµ8ÖW[uz–;„ÛXbÅk±–k ±ù!¶-ºduô|éÈÍ-‹f~­™ë>Mçÿ|x/fîŽ9ùŽáuߌrù¯^• éã"ô×â’ZæUºp>¯ãþµôæ ·o.šsǼ(>é3e«ÐæÒS¼?Yˆ< °ä9k»>yxa:çQÖ¤É' ´к[ÐÝsõ$æd.Üz3÷e¡]šÛß­su¼?·pcO†SC 5ÜÍݱÉñ5Õ½a.ö2/PÑŒEóËŽëÃßÓ+eÄn1Ï÷S,b›lŸÀsèäø}Fd·Oàø}‚©|ÑÚ8/ƒs6î·G¥gùÝyL53üº 3,Ù¹SÖî—ÓÂ÷R¾·¬«‰ž_µ8ïÇÚ «?åû‹5»ÐbS‰j±;ªç~?Ž"bocÍŠ­ŽcSÇîˆÎü:¸®'Û¸,tî‡íØcÅ’ ü*4ý^¹rÝî+·`¢ë>•W¨^ÏE—g.ÜYzmv‹¯“ÝòzÛ-·³[>vÂÙ Ï#ßìqVÍn¡ÙB‚×jv‹¯£s·tÖÁn‘=¼ïï–›Á$Ç-š7¿ `¿[à½xþ±;6ûfæl8f±­¶gàPuî™{ž1\#·gàNé.QÀÈý¸¯<„Ù®`N¬fæLfF<áƒÇw½;ukr »ssw´“wñÑÄÛ„zìÙføÎÔñ§qÊgy'õì¤ö„⋈&Þö|o4²höÜãTί>®¥maKÛ“¶`ë˜Ö‘¿À%êÄ„ß ˜yò÷"hï3¹ßü)ÄûhÈrú±¹ma[ÛÄ·Œ¶†LÚÚÚÍ©öDCSKc²)É |ŸQÌYéNWàHzàݽÜX3“º'Vyð`§FÏÑl¤­ø71›‡æ¾{‹Ñc¿³0ì¤{˜™Ô×:çD=L焞úþ¢º¥^‘1:hÉowPû§Ø5~g¼@»Çhl3»G\Àb´³ß={vyÓ]#¢¦òg»F2‚ÊÿðÎúÞº=³‡´„´ŠþïRùÑ96_8\霯o…=ÄLù=WŽ=ô'œ,fÆÃ¯É×üÿë’ê"3\„xÈØ!ömÅÿÛCô¸¾‡¸kïÛCôÔω š™9Ñž0Ÿæ,ÄÉ/ýóœ`œ9ËrÂü¡æ$mÅÿ›z\ŸT-÷Í =õs‚é0æDW­C[­9'¿”öüëœÀydNt™:´u(91­øsBës‡bßœÐS?'¨ Áœ¹L|ý‚9•ÓŽ±1>뉒b$Œ¡1+{ųrXцv8ù[,=ךÃ)¨S2'Ââ“¿5TÀþM[ñÿö/=®Ï ¦ãöÍ =õs³9‘šða¿²æüWœ‚<æDÿûÕPsÒGN¡Çõ9ÁHã¾9¡§¾¿Ô °t’Ïjä¸`è€ 7X¤eûn€Ì“Ÿ-cuÛBC{Ú7†"¹m1_}ܶàOøÛ–6ê÷-fÊïxV$¸Q ¼3.™v\UeÅèxäOûwÜHH;²ÌÍhÆ%CàÆZ;þn¤Ïõ=/&øÃ{ÞjçØYA!„YùC`ÑoÓœå£ã;ðbDÒþuV0uȬHQdfŸ^Óÿ7+y;þϬÐçú¬ ¸oV詟©ƒG‡1+Ò<"ŸEwJ•Ûš=æbr·®”žÜÚÖd3ZÙ|<“ÿRo.Ãb9"ÿ÷¼Á^­¸à %à¤GñVŸœº›™ËZëÄ‘ªíxûŽ™òœœxî ´ÝùáÆ½ÃæÞnç¼~9àfÌÏ+Š”G2¯òuuäWY&êÙôÊŠêÊ—‚N~¸ÜÜì²ô¿Bìȯ°Û¦h·…v<Êzd·Ñçún“χw›ÙY‘¹R3+b÷µÿJÍY>ôüŠê£ëž¤¦øYÁÔ*³"zQûP·;+y;þcVès}V0¬¹oV詟²ƒ™~úÞtÿe­øYA‘ŠYÑÍfNŸnßÿ—?X+a&^×g…‰Ø7+ôÔÏ ÆY™¹%˜{´ÝY+~Vä4ÁÌŠTñç=d¾üÁZylVès}Vž»cV詟ØøÌÊïrZÚ°`ÚÜÙÿ•–Î úƒÌЏüó‡¸wWÛñf…>×g×ûfÅj*ÚYŽÆ1+2Ê{Ôë}oÌQïG£âg.fE·ó£†àQL.êkÇã7°Gf…>×g…r÷Í =õ³‚‰Y°¤KŽþàýäùÇ€Þ¯;nÞ¿ã`Mu6Я£?2$¶ëhÇ`;ú\Ÿ©><+ôÔÏ ZlìñöùÖücçéÎñï{ENšÌ¬HÙ¸“‹úÚñ÷ }®Ï f™÷Í =õ³"SÉfVäÄdþoÔœÿWü¬Ó™YÑ›ù¿2`V~Hh}tVès}VdúáY¡§~V0ç ¶“aÝc÷›÷?‹›•—Ú¬ÈiƱû €íjíø?ØŽ>×gE\ò‡g…žúYy™ÍŠ´šNwÍùÿp0îH˜éµ,œ>tÀ¬ô€ƒés}Vd®ûáY¡§~V´ ŸI—‹æM«ü¯[ÅÍ V ˜ݧ5 Àg ­ø|&z\Ÿô9÷Í =õs‚©æD ¨‹×МçÝãR56¢w¼xÍPsÒ‡ïž×ç·-û愞ú9yµÍ‰Ü¦÷î²éÓÿsŸ¼ÆæD: ǽ{H€9 ­øsBës‚NѾ9¡§~N0›ÎœÈ´øñŸ£9ÿ¾O¤†bæD|‡ã?7TÀœô!°Oèq}N¤ðóðœÐS?'âš9‘&ï’ïÍ^àÙÅÿ¶Op_ÜhF—|oh¾eÞŠÿ7'ô¸>'˜uß7'ôÔÏ N†˜“O"[P¤9ÿ¾Op·ÃœHoëÄÜ¡æ¤}BësòæsBOýœàŠ9‘ëÝ“œ¿`ê3'RÎ=éÀ!æ$´âÿÍ =®Ï Œû愞ú9ÁØ:s"åï¥Siοï”ÁUcŠÌK§0'}ìz\Ÿ”5÷Í =õs‚o æDÊæ'×Ì®˜óŸûä6'…“k†Ø»y+þßœÐãúœ`¾}ßœÐS?'8¦bN¤…~J7Íù÷}‚f%s"¾Õ)ÝCÌIû„×çägvÌ =õs‚³/æDŽ“O}çôŠãþsŸ ¹ÊœûœúÎ!æ$´âÿÍ =®Ï ÎÂöÍ =õs‚Û3æDî–]Asþ}Ÿü¼Í‰î Ë®*`NúØ'ô¸>'¿°cN詟´X™áùÓn˜]¶è?÷É{lN¤épÚ CìݼÿoNèq}Näçâá9¡§~N~ÉæD êÓï¢9ÿ¾Oä̓û¡üú]CÌIû„×çä};愞ú9y?ÿáVȑ̊½¦ÍÎéOXòø¤Üßc³‚#8fEºH+ö€YmÇÿáVÐçú¬ Û»oV詟•ڬȑÛ¥4'äÿ2+²Y‡ñ f o€YÉÛñf…>×gEÎÓžzêg›æp õ}frþÌ3þc±ø¬y3³¢»Å™É!8†íøŽ!}®Ï ÷Í =õ³"ŒböŠæë¬¿š]6ÿH§AØ^6ïßõI°/î@?øŠgýÕ€GšÏÉdé:T[ñ#]?'ôÕkn3­6Âø»gC=Kgƒú~ên‚óÁ~àÔ³ÿaÀßgUëVWRz;÷7h^| Œ]^#ÕÇYB¾¥AgñAgjÕ:¯Sôˆ¦Nªó†AÝŒ«ðÎùfê’Ç"iê,ê:o÷|3·“{¹—ñ~ ï—ò¾÷óÂû¥¼_Ò¯s´„´y–·=6Ëg“ïœ0—«ˆ¯Ù1Ë{æ¿{–—„¹Š™[Ó•ÜýN|w~“ø2â+ÂÌ.¢t“ÎæÝ9!ÏâKCžy¦aÞ­aõ€þ’b;˜mÝDŸíyܘíS~?ÜÌãæï,ó½5Ì·f:oqŸŒKIqZŸñ·Cuìêý:á½»:}ß×Á®>´¨=èïNógçœûvµæ7eñ"™åþpÕÏ}ËP³<ŠYM¶Ïrú¾ÜuöcÃüãYÆÃξYÖü¦^Žð¸Ñë}Èæ±Þ‡´·S¿DâðïÍi÷DWNüìôæ´8¡+§4(öæ´Ø±+§4>öæ´·ƒ®œÒPÙ›ÓÞbºrJ£foN{ëêÊ)  ½9í-±+'Î>{sÚ[mWNiXíÍiïà]9¥S¶7§åtå”ÜÞœ–¿Ñ•§›½9-7¦+'n^{sZÞQWN«öæ´œ®®œ8íÍiùr]9¥À¶7§å"vå”îñÞœ–çÙ•SšÒ{sZmWNéuïÍiùÉ]9¥5¿7§å~wåü³í9-¯¾+'î[{sZÍ‚®œ¸/íÍi5!ºrþÅöœVs£+'îdzsZM“®œ¸¤êÍi5cºrâ­¨7§ÕäéʉK£ÞœVó¨+'.zsZM©®œ¸DêÍi¾ºsâ8©7§ÕDëʉ‡¥Þœö&Þ•ß¡½9­¦_WNEõæ´º]9ñ%Õ›ÓêÑtåÄÝToN«;Ú•T½9­lWNœVõæ´Ú¼]9ñkÕ›ÓêwåÄõUoN«)Ý•ïX½9­fwWNhõæ´šè]9ñ±Õ›ÓêÍwåÄ WoN«åß•¿V½9­O‚Ý9ù˜ÞœÖ»BWN’öæ´¾ ºrgW=9­O‹®œ’zsZ!]9™ƒ'½H‡œ˜ÇéÍi}¿tå4N¹žð/msZmpIêþØxç}¶ÁÅ©çàÏ·©žƒw>\±zÞùpïê9xçsÀc¬çàÏ'´žƒw>üÚzÞùp•ë9xçsÀû®çàχ¾žƒw>zõ¼ó9Ðv¨çàÏNF=ï|4Gê9xçs ßRÏÁ;Ÿ-œzÞùè ÕsðÎç@£©žƒw>šWõ¼ó9ЫçàÏ&[=ï|4îê9xçs XÏÁ;Ÿ ÆzÞùhZÖsðÎçàR]ÏÁ;ŸÍÕzÞùhØÖsðÎç@+¸žƒw>:Ïõ¼ó9 ÄÔsðÎç@C¿žƒw>~ê9xçsàí žƒw>^ê9xçsà=¢žƒw>>.ê9xçsà‰£žƒw>þMê9x÷ïèà¹nÿ‚ý¥‹#·Òú,Šù 4Y”ËœHq1‘£¾¢6¡Þu¹ÅÍ+~1öÈUGŠ¥gÇN²JrPç~8ÀdI.þTKI×6ÕW–Ÿ;MOYh_—ŸòÉqîòO¿+|1[ŸÔÞ u²ÁGvE®UWE ÕUÑ5LÝm82®£áÈÁ:ð>ØQ‡Æêuƒ¤^5êê©þ4ªoxKçêjT¯Õ¯F]šÕûF]¿´š5Mô5ó&]Ä®l’ËÍD“.aÚØMÚÚªµIHsÔ$5©ò5‰å‹GuX#bS ÐUZ—›Äp®ÔB=1JÎ-ò¥­~´ꃘ±˜šÑ|júAÜ÷A?pº²¾ãu'£V?gxvÄ£–uØ…cIe.ðcø7|V>MÈ`i©kBë>¯ŒÖ­U)Fëþ£ Ø_“ IÞ_“  Ø_6ÍtoÜ_þlÔ©ýµOuOÝŸLÀþÂ(êÜþÒ¼Ôì¯û¹îáû kúö¯^÷þýÅeÑ›ýÅÁŸaÝÂÄ“# (ŽÅÝ×55cÕaÝŒÇâèΕ‹tQtÚг%˜ž˜ ncJ¡0µQOLÆ1!1u{U¯¯£ì^À öu4¹\Æ|‰{C9«ƒžsAâæÛâÞL·ñ›a½á‡J]á‡{úÁE&:Á%+zÀ¯Ýªç7Ûê¶¾|¹\€‚³þÃή½àš^{¾¯½ƒö³ ˜Ú ¸ïµ¬ìúÚ xøµ¬°ùk/¸¶ÁBÈ^€‡¹§d/@¬µ¨Ôêà*S{ÁM¢öÝü_g/P¨UÆuª–%ŠÚ .xµÊ¸Ô^p1®M¾ö=”Ú prí…󎜿"sÇ øµÜÄj/@jµðOj/¸ Ö^ ”U{Áå¨ö,^{Áµ­6 (\Ô^}¶ê ðzš£ÀQb«ÏÔæï£Žz‹G—Ž56Ê/ÔøælþöÁaÁ7¾³9¹¢º©³¶­5Ê=†©hòßù¨ ΨàçE+ZÚ“Eéz«p5^z§Fy¯zÔ0eé]qgÆõ-:Võ-hÄ÷ëÚÁ2•O;iM²3Ê9µ}I]”“Û¾‚¯ou65E¹_$™+[“K«Û£ücªÛ–¬d‹_¯nÃpq×ê6¹ ^QÝ6žµð•êŽøõVwèõÈê½ÞZÝÁëâJǰ»ÊÕsŒrc÷Æ?èaüC7*+›0)[œY:fÿù¿yQ,-½§àz¥É‹R-Qî!¥c‹‹£Ü|jQûGg‡xi.FIr@ü¥30XþûÁ‘¯wO+|æ(wŸjÜØ?Z,>Ÿ¤jÍR>…EúýÑ_q6IµNå³=Êyæ-ã+I:÷ƒóÇŽåÝõ' ur­Wñ¤UÍ·ò9;ÊËú“¡¬âçKÇŽc}’OMç²?ÙžzØöv¥ý—ËkGib?E74ôŸæóÈ(ßµôdžŠ_&¯ªø³Ò± òòβÖåÞJ^þ_ð9#Ê;íOn“ŠÿBZ ó_ñ©aþƒ?ù/*þˆ´æ{ùÔ0¿øOބХc`˜ùÔÆþo}Š;‘U袙ÏYQþ2­å>¼ùÔìõû77Åádœkgòþéߌ̀ØÚi÷$>µÂNý“Ó—âHÒj×LáóÈ(oøŸ¼¯ŸGZµ{IéØ @Œit„œM·OâSG¤þÑ% ˆ} Ÿ:HÝñGç `ÀÙì˜ÓøÔÙêtÓQ<¼tœp÷d>_·ýÑaFñ¹$Õ‚9œOÁ×_ú£ëŠb1Iµ]¦ó)øºúN$ŠcHªå²´tÜ(Nsù£;ÁæYàtÌ,o…þѱ‚`ó,pzqŸ‚®÷GÅù$Õ^¹°t‡§Ât6 È< œ.È< j¡çjÿ‚̳@éÅ—ò©½ròð‹­$Õ^Ù§öÊø?ªÂ_S:Œ^ü+>§Gy§ÿI%]°{–\«ïäsV”÷±?é†_OZí–ëøÔñ©RÒ–ÙQåÕz¹…3±®#üI`Z NÛ“‘Ð1Öúâ–ïç0pŸ~/|àZ¹å«[“míQî?½=ÊZøeÖâO8e?å €ÂYGŒÅ"ýRZ7ðÑè'ú’üèɈ¿û‡i+î÷o]:õÏëcÕŸ–Õ ÿm3&kž\Âɸ'·}2öIX‘ìü$~I¾ö$PJf<‰È’7? ý’ݞĘÉ-O‚Ù¤ãIÔœüý“ð<ézò|ÿɃC2æ—þéˆòËÿv±)¼äÅÞûÇÚJ»þéêUøØ¿ØüéœwêŸn‡ßü·CeéÏgÑÒ ¾Â¾óßNÉÅçÿéný;’Öýñ _xêþÉõOò ’ý‘ÀðÖ?q%þü߈IדäÔ'É&ÉùO²Z 2k÷C¢MrÉ™>?ÿo¤a1£îz”ö÷ÒÑJk%óU>²…>]ñ¾ËÄïMŒIíùÔÿãóåBÇF°~M™ºÅŸÞÛËQVj“¿„-ËrLÆ®X¥xô½N»RÔFSJ  9;WÈ”JùÞp¹RÄü7¥4 H7(¦B—ã!ý»Óì 1©*d0‹u!*¶5Ô“ïíWŠØï¦”qÐ|”´€4ãªëJJI?Y_®,áMY¢hp˜óâ´‡•)¦vAnŠ’€)ê ˜œ‡HV(ë•ÝÚY¯¾ç‰Ö–¥ÿ¦¬C`úNpZ¹¾W9¤½ú¾SnST£59–C³)*Å.¶¨ÙÊ6EIŠÀu(º"¥•eÐSVÔ÷¼ ›¢´×LQx™ääS£§o@pÒbúgHç “ˆ)lÞr&‹Õî K‘¤/ìÐÒ&eSØdèô‡IÆÂŽAŠgíüÈ ³)JÆîMQ‡¡qx¬iè‹ÊgëG¾‘V‚-êp„t¦9©S³±2Po7Ö\Û²$Å`Êš†À §T›–áÌÛ²¤ eÊš|ÏLIh*j÷ ÍÜ?<\aƒ­°™hÌŠ–Âò;‹-ìG‡W˜T7LaG€7Ž”, «Ý{TØ?€\a#3…‰B{ܱý‡'­Š9E¹Ò¤ûdJkgÑ̉…›Liù Ì•ö£«˜+M#¦´9hÌ•æ›àÐ43Àÿ©gèORØ\<ç9‰x;À¡ef€ÿSÇ„íMaóPr:*F4×I0ÂOΕ®0©¸˜ÂŽÕퟣ§õIQü‰wP[–aLYG£$xLŒiößj5¼ÿr½u¥ %›ÒŽÕÌ—¤:V=«cÿìJÓ–¥ Š)k>JBÇJgÇ••˜)ë_çK•˜²ŽE g¡D?5¸µû¹÷Ÿê®0É&™Â¢·È9 p……ðχ}W˜e [„ÐÞb‰8 à6Þ?i4Ei›¢£mzœÓñ6E…;Ç?»NôªE¦¨ãÑ:Þ™îˆvîeT¨¨¶hèåLQÇ£„²Dº8¶¨Ð©ö3hŠ2ê«*j b<'Æ¿æ^V  ù'æÿLQc2EÈ™ë$fÁU½ýÄ)Ÿ)J*®¦¨“hÙÒXµ¹—Y£¢þÙVž)ê`+j) ðdç4Á:õÏìLQr`Š:±ãSœŒ¸ÚŸ³‹hÿO Ë™¢&XQrÑÍu9LQÕ™ú‰»7S”´LQ§"<¿L²€**0¬TÔ?[a3EIúÔµ }ÚÓ¤—d‹ úgßh¦(¹20E†HÓé±pes/ËŒöÿÄd™)J¢¦¨Ó9›®j˜-ª:S?q$fŠ’–)jpðŒøÜ<`פýò+LŒ¦°3X~gºW¦°œóg û Ð& dSØ™(òœål„D»ô“ÕÖ¡#ºÒ$×jJ; õç³í:P£ArÞù /Ò&å2SØÙ\¹žß3ú.¦VÛ˜™®$Ý£MIOãØð ç Ú¹— ªmðÏ>’LQÒï5E=Ù©s%<ªpÆEETùÄTWNܦ sQK]Ãx™ÆgtXÿCr¬+iVOåÜ…ðø}ez”u0¢¸1rm_áŠØŽ@âK$h§ß.¬ÖrÍÿþ-æ$°Ø'ˆ².;äÀ÷™Í/°gÅDž7"tqk2*°·.òVT„IÍðF.nmÞPÞ<\o‘¸+Æ2‹“škP r9,Çb‹“šë‘’Ú½qoɇÈ_K,»8IÉký±Òü|4[Œœ £E‹¼ìêEèz…M&^<½|êmÇÙ[CÓ°Ž/®˜3cnôc× ÞŠf`òêD9ñâòyó €œs½E¸·’uœx1»ç˜ÌÌý@КJàq¢³ÓÝCòûR§ï¡a ¸}óóhsÛÚ3DðO‚æÅ±'´L7s´Fç§ÿ›]a„\n1gÀ¢š±§ô/öËfÊ*^Þ’XÅcyûeˆß¶ZŒ^{»íˆ$Ž6Iˆ,wZ1£ÞF’µo`çEr3/’’,7GQþ˼ EI2%P:hˆy±-ùóB¯ëó‚øù¾y¡¯~^OF8RÜ®r¹‘S4Ï›êƶ޾;1n^æ¤N ú–ˇ˜Yø®¶ä{–ñzç…^×ç’ʾy¡¯~^àÐ1/­4çæßç…Su ÛU6Úÿßó’¶äÿÌ ½®Ï b®ûæÅœpܼ@Yc^$ÌÚp¦Q^LsN{r#»yAè–:ÅOi8sÈ€y©µäÿÌ ½®Ï d}óB_ý¼ v̼ë7^fLƒ¯ÿû¼ ®KÂÞ— %0/yKþϼÐëú¼P÷¾y¡¯~^8k#v+ݦ›h‘§äüh`ܼ l¬:cn¼M70/Sb©³¬%ßµqØ;/ôº>/ºÄ?¦×õyAzyß¼ÐW?/®`^$V=à…ÿ²^ü¼`‰yÑ]mÀ C à—¬—Çæ…^×çŘ xh^¬µ%;/Hî3/b±<-æçýç Ÿ›Ì!0/’¹xÚÐ÷„jKþϼÐëú¼`þdß¼ÐW?/œÚèyËÇ}otêøÉ:öó‚ìºêLˆµ||ˆ€y™K4ú–|ßÂ}ï¼Ðëú¼ÀØß7/ôÕÏ ÆEÀ{†t£Ñ)U—‹NùoxoæE}tãx¯£%ÿ÷èu}^fß7/ôÕÏ ââì‰çæX—ÿß~Aºœy‘a”!Æ Ø/Õ–üßýB¯ëó‚ņ}óB_ý¼Ì¶y‘Á€Ö‘jÎ%(¸y™có" hëÈ!æå‡…Gç…^×çóBûæ…¾úyÁ$üñz†VŠ|ú_Ö‹Ÿ r0/ÒšZ9d?!´äÿñèu}^`ãí›úêç³Ì‹x±Ã^Jsþ7ÿ¶*ó"[ Ã^:”À¼ô!À¡×õyÁÈ˾y1,\7/0È™YxþQ†ÿ×~Áôê,ÀËþ†¡ø/yKþß¼Ðëú¼`gß¼XKXv^w`^Däñšó¿÷Ëq6/ÂO#>2”À¼ô!°_¬õß®yÁLÖ¾y¡¯~^Ô:sOý‹‘_3 æ9uwýã{ 6/š¡‘_Jà~Zò÷z]Ÿl‡í›úêç+Ì‹ÌqŒºÛ޵°wÿy%»yqæ¸ èߌº{HyÉ[òóB¯ëóbŒÞ<4/ôÕÏ v ™a´Ñ#ìX«æüËJvórªÍ‹õ£G %0/¡%ÿ1/ôº>/¼Ú7/ôÕÏ 2[Ì‹Œ•ì?Ï„cÀ ©‹ðÏ ÜcæE·¯ýç )0/yKþc^èu}^ŒQ£‡æ…¾úyÁhó"Û)cºh΢cM‚I4íÿ4/ðÈUg¾å˜®¡æ%´ä?æ…^×çwûæ…¾úyÁÈó"½‡±ÆàjѱŽÖþŸñƃ˜Ý+Æ^8ÄÞK[òóB¯ëó‚«}óB_ý¼`_Ã5²,ÓvÉZýç¹ïSÝ63Oã¿ø´EdÚ®"`f÷ö¾?4ß¹+ÐóúÜ`;°sn¬ C;7ôÖÏ þ–¸ÃH¨dÜo$ ó¿îV˜­bÏÈÔ¸ß p‡ -ùóB¯ëó‚ð;=C_ý¼Ð6æE¶wÜ—æüï»f™)$¸ïPóÒ‡ÀÝŠ’ëó¢®<ö ½®Ï FööÍ‹µkkçÓqÌ‹„$^-±¦ÿµ_ÐÑa^4¯2`^BKþß¼Ðëú¼\¸c^¬%^;/Nc^d·éwÑœÿ½_.²yÑÿCÞ5”À¼ô!°_èu}^мÙ7/ôÕÏ F™ NøŒ$¶þ×~AE—y‘MÈ Ÿ:`ç-ùóB¯ëó"U¥‡çÅÚ4¶ó‚a8æEV­½…æüïý‚INæE6«½e(yéC`¿Ðëú¼0ûæÅZa¶=Vö©úG“ g{Ÿ>÷ý`}GV´ôì¬èh¾Ïâû8¾Ïç{1ßgò½ˆïµ|/äû ¾å{ ß ø^Á÷|¾Wó} ßËù>šïóø>ŠïÓùžÇ÷¹|Ïåû4¾çð½ŠïÙ|/ã»ï«ü›¸k.‹…oŽ]èntß³äÎNð–ÜÙÞ’;jîÒ¹2;»¹;!¾$Xr7ÝNµPõ"Ê¿LM ±v±neèûL¾ñ½†ïcù^Á÷|¾Ïãûh¾Oç{ß«øžÃ÷2¾û.˜é©™™>+ÖÃëK`¦áÁŽ™ÞfÚZ,·3-¹:윖á×̸x茙֜­!Ç"go_3¬oêœÇ7¹û.˜Ù–Ì̺[y_3‹UöΙ]fÖZG¶3ûú˜s_ÏqÄECgÌìÍ5Q½ÝPM|MˆGü¼_L|Uˆ/"þŒ_Hüœ?–øSC|ñ³C|>ñ3CüâôËÇ&~zˆE|YˆÏ#~JˆÏ%¾4Äç?1ÄgO{¯xß;é^49–•M;fþü…S·’¢ßï$ÃLæ-!v{ˆ}*Ä>b_ ±oebñÎ!æë&69Äæ…ØÒ;'Ä6„ØÖ»6Än´ŠoÇNMŠÃNÕMwªŒ¡Æ'm`dçýlèŒÚjkÿt´¨d5÷%í[ºž’sáþÑ.]ù¥èÊ+hïÊå;â[²’óWG;“ã~ò7ðuå”} äûQÖÔ¨çš! öÓ<4–¡~{|Õ£ëé{ûÉη1ÓÖ0ßšét¾et5ç6ÀS>æê¡50ÓÍÜ-¶2šÝ–É‹£¬’Úžx~•àÖ7­!ÇŠí9ÀNç‘ãôí9ÀO«È±l{0Ô3ÈqÊöà¨sȱt{°ÔSÉqâöੳɱd{Ž> 0U2<½³¾{mûçeLw`’€óµ§Ò%ƒØÜ`1ŸºhÖ·í#î2nn…7ÜÌê­¹Ù¨n½÷{¦óý|ÞŸÃ{¿?:ßÏãýÙ¼÷{¡ó}_7Xál³¾¯^ýã€)Þ}7Xít'È ·Ÿ&47ÿêp·Ý#uû9Ãß~ç‡ÿèöó¶pû!æo?Äü퇘¿ýó·bþö£Xzû!æë&æo?Äü퇘¿ýó·bþöCÌß~ˆùÛ1ûÁ&ï¾Û±ávªŒdƒ³ú1 §ì7¤×e¥q]N5®Ë3ŒërŠq]žn\—“ërŽq]–×åiÆu9ɸ.O5®Ë‰ÆuyŠq]N0®ËÙÆuY2D×eÉ\—wìÀYÚéNQeõ"z*,®åÇ ©Áuy†q]N1®Ë9ÆuYj\—§×åD㺜m\—%C$p]– AÀuy×®‹æ8ié†Âué‡6ÿ™ßRƒërŽq]–×…ºáºPK_\—%Cp]01¾ëb|¸™• °Y3\á§üÃÐ70ãF«xzÏPœXz¿PüXâé½Bqn`é}Bñ£‰§÷Ź¥÷ÅçOkïËà.j±™áš,Š¡YŸ÷†w‡{1o æï Äü½˜¿7ó÷ÅÒ{1Ï}5ÆÉÂ~Æì‘Û92š£×=ògì¾yçì|rçìÙîœv·ã³œó…ºwN{À ìEä',éßK~ÈvÀ2ÇËvÀåì€Mì©ózÜiæêGØîsº(Ì©qäæTVÐï:’ 7©çÎÖþW®E†ç–hŸ+>oˆ<ççvÉs‹¿­Î¹5îÞÝÜjVÓ¹}ÿÅ+ïÏÿÕNWÌÏ­›Ù]nfÅÔIg&›ÁÑñ| »¬kóQpؘhçíM÷ìEÏ;`ÖÌ^T>3³µ9ssU,\››»{f_÷&ÞFls&­’lΪ3fúÜ&ýbsâøŽ‚l¶ð‡ëïû>à/>v(þðÇwp´Òpÿ¥ç<èŒ(:©é÷·×0ÙÍÁðò›ƒsËQjï»×^ågÊÞlwžæ¸/{ïµß¿µÞˆo­ò‰ñÜZ•ÿ×Ú,}bðÖúåpke~¼¦Ü'ù?M9íÜ­Ç:§d\þ³Ï éÈ¡U7I["@OÎ̆mÇÿõ8AëZr¿68'VoÏÎ =õsòiþãiE›åù ²Øæ…OXò_=­ü:ÿ¥Y7nÎó†ðSmÉÿñ´B¯ëó‚‡Ê}Ú{ôÕÏ‹£šyÑýኵ4'ü/ó¢²™y¸bíPó’·äÿÌ ½®Ï .9÷Í }õó"MÇèæE·º+?ãLiž€'Íã‘v¼¨£­=±$™hJ6¥ZW&Z“õÉÖd3æõÓù~&;}0xêJ§}Ù‡nõxH¦¡*r˜¦­dÕ†™iÇM` /ýN?Åä.lÅ;g3oòëñ0Þ¹6:<öîo[ûC^‹1#žo/Õ¨ØbÒ§<÷´ÁæO:¿»çﮀƒ˜?CÒPÖ 6z»ïª…w†ëV÷ÜÖ‡-¿wkpø2½|¹c_p£ N ørDÕ:påó³ ×å8îsÆêæÈ틞Õ?%pæw–St(Åüž;ç1ÿn| æßNŸ«sËdß«S*Ñ&>Ý‚?²/³ÙõXŸÝ9ÞbÒ÷ŽÎ²•¦ünÜ?_ p3jltº•^?˜l9¶ÿà÷¸ßÌån®ÁÜoæ2*8eÃ\%EUëâ=æÿ>®¿Vó²xQÕ_楆ííŒÈ×Áî=ö©°Ç˜ #ä™ÁxÐMÿmÎWáªnÞtU¯ %¼ mÈo-ùoôºŽ»äKãaÜE_}µ-bpŸ³/ܨ™ï}ËkÉ{=÷®!¸²7b®7³Ã®ŠJ¹ù Ô-X܆–®Ü=†wíóÏÃû á Õ?f™ãÓZ~õº5hט{z´w1XãLw7·±î>nc§»;¸-s÷n;Åݵml©»_ÛØ‰îNmc}ðv{°Èõè /›?OL¨ïÙP|‹pƒ¼Éö†üÅìÆ"Ÿ XD»"Ýòn£yÔŠž—œ5dÇÞûäÞh×Þ07m͸é‹ÛŠ1Ïf'¸û©Ù}ð·{öÀÛ?ôaùã= C»÷ÀMahöÓ= Hfè>ýr燩OŽ=pÌ÷ÀKW³˜Ý«¢ª\¨PÏNbä13~U4+¼3yûDØ–ÞwÀ°1q ¢Û31i2Øý ßYïí„t?ÈÓ<Ø¡øÉxÅÔ!4t®b&ßìv¼Ñcؚܽ°+7«Ðíö½xvzÏ®oçý¼ð¾o݆©šu™Sú¯³þÿÇåûx°šãt¦å.æ>”ËuÎS_÷L¯zr¦/'çÖ0ŸÛˆ_³c¦×‘cCȹ‰ø–Á™^xt/£_Ö•“umU”;œ~>o®áÍ–ðf o®æÍ%áÍy¼ÙÆ›MáÍ*Þ\Á›áÍ3x³•7›sxó\Þ<3¼y*o.çͺðæìþ¿éœ°3àK­ ;ãfvÆ®GvÆNé`ÊpÒ?ÞòÏ·{gÜv†öDz—“7Aóßúµg:bËY/=î<›û{l÷È"•aø;{íP~!φvü_ž =®ßãðøºgCOýn•§Ê˜ïa´îuÎßcŸÜ®*_ßð寿tž½_îðîýrÚ[¢Ï÷ßÒÇQOùs…³×ææœ3™!o?½§'C·á[OËyÓc·á;ÙGp¾N-Oºg>ìI÷‘Û0³²{ÃmXóäg+–)WyHÆ­óÆ/þûlÎî¦ÿ)žtØÏc¾ªFÉwfªo­’ÛâY:Í\ß|Çpú£³„wÛÎ=õõÌ,™ùñ³„Ý|ùÕ†Í7öé[trnrý—æªÅôÿÃôÿì©{J\3K/`O•ØSºÇ0CÌÒî,+NÏþk Lü¸Oˆ/ñ"ñE!Þ@|aˆ·?6ÄÛˆ/ñùÄç‡ø6âÇdâ"‰^…†BO?*/*>/oP|n&Þ¢øœL¼MñÙ™ø|ÅÛ3ñmQU­x£ ×Â?ú¿HºÒ>±æûŽuîʬíUßƧ~Çn}oØÖß®ÝXú—Ç»pÔÞ²ñ܇…n‚ÝÙ ùݽµ §s‹–Âóg”~`Ayþ”“â» Mô¤_¼õ)•p™S…ÏYÀ?^â42Θº`þ: ±ó3Ü1ë;2XžùNg]þˆc¸Ç#À÷oûÊ#³Þ Yo+€Õ0lòÉ3¦-(ÏeÞõÝ–Û?ï ‹†<ÐÍXšž÷>4bù2îœ÷kükÆÓy—ã¿ #Ñ0gîÐ7Üvœh®ÓýÝ–‡ÊѪ>“?¥äf8–]¸c4¶EÃΆß~Á½û»ï€ûídw‹;a΂ÇÖ÷Oæ™wó¼!̳õÓlçYõÄøÛ…‡Ø[®Õ<xÿž[lŽ7¹9Ö -ãRao¿þž½=Vê\jËŽžË|8‘9~ÞUèÚ›ÿ«³ }ž­'á“^€ÑÛQÑð²îžëÿ¼“o`†Å­.\ø f¡:»寻;‹¦ÿ{µ†Ùõ8›Ù½!hmßas ¼îœã³…]ÜSŸc‰‚H?<ÚݾwÿÝz6ùìV5ljï2ÝšÚ»L«¦ö.Ó§©½Ë4ijï2šÚ»L{¦ö®ïm‘[Óû¥o¬gb±¬Þ³ó%Xòª!°ä‚EC`IÕÜš7îîSt7¾ ÌõÇg~ ëå3?P’‹ArvaWôtx?'|`°(kèƒ÷ÚÛ†,À×:îØ™G?¾.~²/º½–ÇW‡}a½–Û}¡gù€Ô-éýÖ¾øÐÍ=×§orñ¹[vº'¾Éžxÿ“{â¹ÿ{OÜ0¨cP\ÀÝóácÑØyS‡k57{}2ƒgÕ÷î=6ñÊzÞÿªíïñðŒíïñpÎö÷øxêö÷ø 8{û{a£ø|y´z ý¿27¿˜=zÜ%§9}Ž5]¯ .~í­(íút´¤ë*â_Œ¦~Œôfúúüò‹'ÀÉú9\u¾¹,zñɳˆ«g?÷âWE'œüæüâIŸŽ&ønØoŽ^°êãÄÅŸøyPÆ[˜ý+Wäøft@†»þ´½ §§2ÚOÚ½§çÀD4|ÕWŸòË/v~Ý+N‹s¼Øž»Ô!cëi»¯:p¯ÎK’Yñ™8Ç.GtæØz9ä îŒË! {rÈAÛÓ,‡ ìÉ!7mgX?v¡,º'‡thÎ:ÏrˆG¼'‡–ÏYµ–C¸Ôϧ–~K×⨸«;§ÓiuŽúï7°÷³“«Â\ÿ ëb®ñ‚¿hžÝuzn±8\+ÎwµîÖÝc{H»cëù‰â®+ì\ûJvž°®y/u¢Ýï_ÌûEö^óºû=µj>WÔZî0«Ü®kó»®ïÍ¿8öI•í½> ´bùËïÔ‚¼>Ã¥g×¥{O^ ¹÷ŽASìW_<„ƽ÷*dz>“£!lîÆß†p¢Þ­è·ˆwð­Oïw,ïà\/ë7Ÿwð®Oéw4ïà^/í7wð¯Oì7‡wgónIÿ»¾ î½öó_±Ôc÷˜ýwÜcµGÒ" >¸ücñýk—ÕÁå¿fËoÞtpùÍ›.¿yÓÁå7o:¸üæM—ß¼éàò›7}pùÅ—É‚¡ø`cwFÎågO¤;C}1;C¾L~ëÛCgì ùùy!^¤ÌÎØ½B»ý|Þ\ó3Ü›5¼¹š7fg¸7çñfoÌÎpoVñæ Þ˜áÞ<ƒ7[ycv†{sožË³3Ü›§òærÞ˜áÞô} ÿ€¬zßh_Ÿë²™¾úyѵÒè‡ÊCÄïÿ,6ôüoãâçå`›q³ßùbë@?´Ú’ÿÐ5½®ÏË!;æ…¾úy™`ó"ŸÛÓ [™½‹ùºy9ÔæE»îs{%0/yKþϼÐëú¼LÜ1/ôÕÏË$Bó˜qÿPš§Ð©’> àæ…éØÜÑÒ’je64=mµ­¯nIÔ¦šë–v´Ö¨[~f&ÛÌñýáP¾å‹µRÓ¶üŸ™¡ß~fÐNõ3sØŽ™¡¯¾ÇSâÖµ¡‘úùW™Á›]oâì4ov?8³|äÁÅOÞêŒ'þìâ´?ÆŸmÅ@ðá«=Ɵŧà]6χbÒU?«NçY̸§Ž£ý_t^¯ûÌðav&·ƒó{g×yÈ[Á»5ýïð]v:ïÎë‡ß²e¼[ÕÿŸe§ðîýïðW¶”wçô¿ÃWÙ‰¼{jÿ;ü”-áÝÙýïú2¸§ºýÒÇÀ#ó&äø³»½ 9þìnÿB~góšÍÄÖÄ<vÚŽ{­öTº³¦ÃGvÃp0ÿt˽¶ þìÍh÷l=­`,oμ!ãûN𠷾ܽ]doW ¾=ÖÞž>øVúÄæí²Á·GÛÛSßγ·Kßα·'¾m×ÛÔÏ ïÐì«€ßû)ÓŠèk`ŸÙ}3csÒövLºo¤³Æð+$§ Ñ¡±óîÕŒè£óŠÓß÷æµój†ÓyÏÌ{ ú=½ÅÃL_*;4#Rß”µw™WÊÚ»Ìeí]扲ö.óAY{—yŸ¬½ËüNö áöKŸ˜÷ȘW{*ÝYZe`Þñl÷¿­âóJb/æÍÞvaÞìmæÍÞvaÞìmæÍÞvaÞìm óò®ïÌ+Õ}`^$öa^à’ß7Ò4Gÿ øïø%}©hâšø&æ4ñMÌi⛘ÓÄ71§‰obNßÄœ&¾‰õ… ‰ÿ#‰ÛŸðsçâ”\Ÿ]‘îy±úAø_û§ µ¢‰?"h⛘ÓÄ71§‰ob}!h¡/š@?>rpäšçÌ~ºŽŽ÷ÀÁ|ßðNšøK‡&ÐÄ‘ñšøÄ¼&>ÞIÞÚé~XÀùÝ;ø«QVvõžŽ¤ÑŽâ»fsE×+ö¸¶+o÷ݺN‡'_umW’¸8ó©¾7;|K¶çéÛÀ'ß"ãIŸñ¸Rþïò^²{ί wÍv:çR3Š™˜Cf l<õ‘¡¥iš.ÏliKÛlÞúîHÁkdµ=wýðq·nQÑäœîh N£»–öÅ›»>{|‘°AÛNæm]öº ø¿=ëÚ’9¸ö.4º ¥ã‹&ÆÁæÄ(=¬ë‡,ØÛÜŽÐñÔ¹í[`GÈwäîqGØÚ éŽXÌmSÞ“¹ ¹å?qüŠs{~˜Þ Ò>©ò+>Àn¸ÝvÃÞ sQÚš‹K”m]ý;¢–ûßxÂýgɧàv]Ù³g!ïÎä]•›æÞÁ»µƒïVð®ÊYsï–ónõà»ÓyWå²¹w§ñîÜÁwËxW帹w§òne߻ϻw§ð®Ê}sïNæÝÓß-å]•çÞÄ»§ ¾;‘wU®œ{wïž2øn ïª:ÞuSîás£c¬xÖúÜ)NÛ˜ý8Úö%3þã}ùöNuOµ÷ätÇ«[0ÝŒÜöÀañº”òÑ—êRóº”ļ.%1¯K©XªKIÌëRóº”Äœß`ÛbÎc°‰yõDéV=}ð­§ÝÓ–ÿù¦çužúÒ{æ†^¦sCo}ŸOæ¿<ý:iÜ^Ïv}Qè… õ̬zSÜü§pÑ^PÎÕÿ¢¼¯Íþ@ÉçÀÁ}¼VÞ5d/c»§1uhíÈS±òÍ+kþÓ]pjì…îÐKœíCC‡\ú@hAâßo™ãVXíG¼Ñ_A­G|ù?8ÚŽšk_F-Güö?…8Úx£#¾”8Zøè#~"ñvóÌG¼ï®Î&Û }èWÉ£á>/tìt'œæz¾2£¡á/F;Àùã³õY\nfÞp'4ãÎÿñ¥†ãÍL÷}à/F3ý_ùÍôéƒ3û‹aŽÓ™^n3½YȪ·Ø>6<ã¬gbÜð­žq²÷} xÆÑL÷Ià߾ϴæ8é3b?ñ;H~uÈ _Õˆ®áoîÕu\þÿ½ëûÇëäÝ7Ž?sŽ×ü§»à¬ÇOªGV®×óqß8^äqxŸm57r‘ÅÁñð#µ88Žä|‹ƒãáImqp<\I¼ÔÇ×”?^Ç/!Þnñ>p<4ˆ> v‚Íq:ÓO‹5'Fúîë~¦S8Òì®ÞªÇš?žíÙ…§;CÎäŽUÑp·‹­ß6îk‹,ÆmíX‹qW›o1njG[Œ{Ú<‹qK›c1îhí£?ƨz²©Î!Ž—ðÓ6Ѽº-{ćr6wÞO’G;wç Î]› Ú¸¹Ó¬¥s÷t´ºå¯a2)y¡ãÅ=7¥9E*­:w#⹻͊k^ÆÜíöçó˜»ý2ûS†`Zà7 ,]5L7͇ôá™É;ôïOß¡¿l‡þý);ôï—îп?q‡þý’ú÷»ÎÛ?:nÕA}Ú÷âFVµïOï×¾_Ö¯}J¿öýÒ“ÏFëþ‹Ñä Èú–OGÏ_uñ7G?‚ªï[¸!]Éû_`?UbºöšçcÕg£}?íû9ׯÚó:?Ë,Õ¾e·öýÂ!´ïåkOy²<Ë÷Cn«÷äx>9|û´ïýþ~û[;-ÝßÚiŠ×¸OÚÕýÍbrFÆû[z÷}ìoyùÞ­o¿N¤a·¿µ³Óý½2ÆM‡¡ª>å_‡*ÀMF“Áá&s¸ÉÄn21‡›LÌá&s¸ÉÄn2±¾pz}Ìc²7iÖÒ¹;—´‘û)’l©ξæÎÜ ¬/@nÿ—:Ý~ƒE½§,ë`Žn3ü¹hH€9RÇws¶î sÄìø9ÒI!ƩÔR¤ÆÒû}ê±ë{s´ç~³c?‡?Ç¢CƒOáË=ž˜/aǽ> „ ÷ú$æÛë“àÎîOƒï>Š'æPû*æïù_Àœ?“¸î=ÏOšG‚·8Îü’® ðH ›ÑŠÏš9ék_^Ù…_QÜõ½çt®å2~ÆÁö^Nëv¿—ÒöI{¯ùÙýžZ53©GÕ[õH°Ë<|g§T}‡uíñÙ-&ê`§¨ »wó·ÂNá4åw v_µ›ÇIBûØ¡ v³Ñ'q»ÙÄÜn61·›M¬/ÝŒVI_stþŽÝÌìø9šÇ·ÿáó®™~¯o³žYºò3ÌÒÌÒ˜0Kº§*žÎÒK{˜%fAúVí`|§÷a8Êff¤C•¿³|e?Kò½±“ÚÒYRmŠïž¥½¾ý-Ö‘«¸ž'ï­6hà{qUˆ9éâO<ìáßÌ–Ÿ3]Dðrt8\Źi„a çs¾f3Ö0Ð:f¬!` /DÃû¼Æ9O[í¸¶ô\•¶üاξ¥SÙF\\“…©• Î@4<×äËéùSwwRw:ª[ñ'0|;/šrÑ÷ácFÙgBR»qAKØgš­tÎtUbŸMåÆ|tŸŸ >Bö6}ì3£Yãö™‰ù}&Fï3fËÏÙEñ>›º–>3ôÃ>K÷˜všÙm}ì3a³>öÙÆûL³¥ØÅ;)×Å„zs™·00|žËT\™(×r>k{N;Ã]9/ÙžÓî×®œ›·ç´Ø§+'Zê½9-.íÊÉ4õæ´7®œ¼îÍioS]9™¾Þœö.Ø•‚Þœö†Û•ó9ÛsZÞFWÎçnÏi96]9uéÞ›Ór­ºrJÖkoNËÙëÊ© üÞœ–óÙ•ShhoNËýíÊ)6ÀÞœ–Þ•“t½9­–@WΫ¶ç´Z]9¥¬±7§ÕýèÊ)†ÈÞœV¨+§tÂöæ´ZS]9¥Ü¹7§Õ!ëÊùÂí9­¶]WN9»Ù›Óê"vå”GĽ9­gWN9ÄÙ›ÓêÄvå|ÉöœV¹+§8{sZM쮜ÒQÞ›Óê¶wå|ÙöœÖŸ@WNù¥Ú›ÓzTèÊùSÛsZ/]9wnÏiýVtå|ÅöœÖÓFWÎWnÏi}ƒtå¼n{NëO¥+§|"íÍi}Ðtå|ÕöœÖOWÎWoÏi½+uå|ÍöœÖ3WWζ紾̺r¾v{NëÍ­+çë¶ç´ôºr¾~{Në?°+':æ½9­Å®œoØžÓú”ìÊùÆí9­Í®œoÚžÓz!íÊ)§p½9Õ®œoÞžÓzƒíÊ)ôÞœÖwmWN±Döæ´þ~»rJÇtoNëó¸+ç[·ç´Þ¡»râ°7§õÝ•SŒÅ½9­Çñ®œbÚìÍi}¤wåëqoNëϽ+§;{sZßõ]9ŜܛÓzåïÊyËöœ¿¾9çÏlÏ)/w{rÊ3íÞœòÞ¿''úð½9å{ONéBìÍ)Ä=9n{Ny¥Ú“SÍ{sJõcOÎ_ØžSnÎö䔿–½9ß¿9§<ÌìÍÉÛzNùÄÙ›“¾ÕsÊ‹ÏÞœÌT=§<ßîÍÉŽ¨ç|ßöœì¯zNf£7'»µžóÛs²÷ë9¥J¼7'8¦žSÌä½9ÁXõœì‡Þœà¿zN1KöæÏÖs²»zs‚Ïë9?²='·ƒzNöjoNîõœRïØ›Ó0(ºs²ó{sÂG¨çó~oN뻹+'x¤7g/ïBn×öæ„ÃTÏ VêÍÙË¡k¶½9áPÖs~b{Î^>Ä'·ç„¿^Ï ^ìÍÙËmøµí9ÑŒ©ç”çž½9{y àßÞœè‘ÕsÊ×ÖÞœ½œƒßØž­ËzNð|oNtEë9k{NtRë9åcaoÎ^Î÷‰ÞœHÔs⩨7'Úùõœ¿»=g/@žÿöæÄSF='7šÞœ½\€ßßž¿6õœ°=gï]ÿsÛsâY©ž“;UoNägë9?¿='þ«ê9¥½7'·ê9¹»õæÄcZ=ç·çì½Ñsì͉—ÄzN±÷æì½·i{N|¯ÖsrãìÍÙuߘ£œhå{s.^®³y' a“ƒ}PÏa÷„ÍÁü×sؽ`s0ïõvØÌw=‡{“Ãø]ïÎaÞùìzÞù`”zÞù`¬zÞù`ÄzÞù`ÜzÞùp#ë9xçsÀÓ¬çàÏ¿¶žƒw>\ËzËÁ´9à÷×sðÎç€YÏaù’6ôÜzÞùpë9,·Ñæ@¬žƒw>|ÃzËC´9ЬçàÏ7°žÃrm4„ë9xçsÀã«ç°ü>›»™õ¼ó9àöÕs8­o“õ¼ó9àa×sðÎç€wWÏaùx6¾Vê9xçsÀ‘«ç°Ü9›OHõ¼ó9à³ÕsXž›ÍŸ²zÞùøT«çàÏ÷·zÞùø©«çàÏG½zÞùpÇê9,§ÌæÀ§e=ï|x^õ–ÿesà­·žƒw>^Œë9xçsàß»žƒwâ’›€ÌzËߺxá¨\ã’¶¿ñºÜ(×x1_•k¼®XÊuЋâ\¹ ˆý$\¡\‰q¤\Û¾=ø”8×ÁR;p¿ƒÅ¤R®ƒuéU®C„–•ëwƹËÔý+@¹ùMœk‚®Ê5½/rMpÌ4û›ð³8סB©Êu¨®SÊuèÍq®CuUu¿‰†Q&F™h»yRvœkR¬9c~“ŽŽë$Õ£«á$)hOOÖåR}Ÿ¬«“ØT“/ŽsO}ºôa¢ËɧЗýµHB(pú¯OG¹¤¼*5\~S¥¡š§jnT³TfLÍÓtÉUlšz¡š§]×<ã­CÔæùq/޹,ÒÔÔzÁî´» Ôò¯9F[V™¯Û¸þÏçD™/žš:³@AY §í½€Í@å @âLÙ±ÜÝcj;VS¦›î±lzôŽ¥kð>ʦ:·hâPS´H›Q½Z$.²zµHA½ZÌtÓ«ÅâÄ«W‹…>Å‘9N·4]NŽCýãls¿~(€^,Ѫ¦%B2êÅ]oÔ‹%º¡«'hâÕ‹ÄÓœ@Œ-vŠNl±õ^[ìDÍ•fåD¶[ìD®*l±“˜;æë$éGk‹‘-v|!¶ØRnel±¥ò‰ -¶ý ¶ØRø^l±“A*l±“ß÷ü”§ ÐóSÄSÏOÑFVÏOÑu@=8•7ôüTi0©Ï§Ú5iù„¡j^n3¿Üf~¹Íü ›ù6ó+¾×|æg‡¨ù,¡!Õ|–<婿³„UóYâÅ©æ³u™QÍg§âšŸòé¡j~ªnŒªù©º&¨æ§ ¨æ§ê2£šŸ¦Ë†j~š®OÚ'O“V€öÉÓ„pµOÎÑžÖ>9GiŸœºeŸœïƒ}òt4!Ø'OW'Ô³gäгgˆ×§ž=C×JõìºÜ¨g+5?ꙑSÏV¾'®yÕ«]þZÍY•ÔœUIÍæ·JS§*Wé¤*ÏW•çêÆ¨*Ï•:„ª)×z]sUó3ŇPÍÏlkÞ  æ â¦ªæ š*Õ¼A×UåºH×RÕ|‘.Áz{Ñ»ãš/n  æ‹uÉSÍë:«š/ÖÕR[c“hڛċÕÖx–®+BÜÏîÕÅûYÒ´ò~Öµq/.9zèÄ}‰v‡:s‰Ô Ô™KĆVg6ëÎ¥Îl³_Ù¬½÷¹Th ªklð-Lˆ²8ˆûRˆûRnà îK¯Ž;wÙW†؃ÏÖR¯ž­¥^=[P½z¶¦J5_NoèÕåRjâ¾\7b!îç€@ÜÏ™÷â¹/  ϵ›äsÅaÐ5ôÀ]â튪Co×Kz»6:ôvñ Õ¡›u9R‡nÖÞS‡nÖ%Vsw³:ªÍó8IÌÝ;VÇzÇO‡èÐ;uU‡Þ©M¤½SBz§p:ô.Ý#Õ¡wé2¨¹y—fG›þ]ºmi[Ý¢j´9n©Š;tË•ƒÛ>ëÝ{aüŒ˜Ú2?£í¤íò3â@‹ö3âÛë"ó³ÚÅÚt?«Û¸.=?«^©'ï>:îÁ»/}`JPZü×)y·P€¦äVU®)¹UhWSr«.š’Ÿ7LSòsâ h÷þœö¯æùçÅÃÑìç™*æøçቡù Ú“Ú¿€r+®Å~A ÕsÛ«âÞö«¡n;ï>SÏޣݢzߣ{’j|n¾êÙ/Š;«žý¢¸®šê_ÆÒý¢Øšì_’J¢&û—Nˆ{òKW0ÙïuJâúf~Ô“÷Š%¯ž¼WŠ êÉûÄÁSOÞÇõÜð>ø…à†÷Š{ðþuL6{ã_§äýÒûЮù€–vÍÄôÕ®ù€¥vÍí*S»ævÝZ„ n†Oçv[L½¤h`|Pž Uã¹ý¢çÿA4¶Ð¤ý \ ´?„ßO4´>Ä›„êM@raó$ ·€¨¦ô# Ã¤ðTÂvúZ[&ë#ìÂ}üe&­Jþeê,0A¿ ç¥ÀŽÿåoÇ“ôÑ9ý“ÄV¬Ýþu’>*nvÛG…atù¨8‘š„;åàHXõN]#ÔÑ;cÐ_×L(ìW`¾€%vØñcbU¨cƒÿ îÇõ-lûqøÊ¨~\XT“øqÐ*Qw™šÊ]t ÂwqÙK˜Ì»nˆ;ý«³wÆtúWÅŠÖ¬ýªØÅšý_?I³ü mTMÁ'¤ƒ¨™ÿÄÏâüÚ{‡Øæ¿&Ö¨jþ´îoªùÓ´ªùÓº;ªæ_×þRÍ¿Ñ×ü[?ÀÕå3’ìWÍŸawQógÄoPÍŸ‘&“jþm±jUóï¾6®ù÷>7@Í¿'¤¥÷ûBZÚ ¿¯Û±. ¿[\ãïë‚ï~ þŽrý|)×让\Ÿ{vœësB_î÷9ç Oßðj”ësÆØýÃ)q®?túÕö÷‡º'*×jŽ•ëóÆ\þ|gœëóén)ƶӜ|^¨I{÷óºÜ?|Aíó/ˆ™)üpùÙz÷¨Gº¸Üc ä/¾dè¬úEuMSûEÝã4µ_RSûGRµÓÔþ‘ØOšÚ?ÖO8õ¥A üõÇâL«~‰XõKLXõKð­ÁªÂ°êŸÀP«þéĸƒ:$ÀvûSݧԳ?ã?=û3± U㟉+¤ž}Yªg_–j‘PÔ—¥t# ðe±„U¿,l¡©ú²xMšÀ/ëÚ¯MòçºKi‚ÿœ+×Ö?‹€1þ\¼õóÏÅTOÿœ)æ.õçÔzûs8ºð@þ4ˆòû_˜³Ò¿ø`Üó¿Üï/—Ó¿/Q»â/Õ5튿ԜkW|E÷w튯hghW|ExBü+í[uõ¯Î«þë]‡Ø-Ä¢¹øk]ÆÔ…¿–â¶æîoT‹æîo´34w#¤£]q¯®×Ú÷êî¨]q/ìvÅWÙÄ슯2+ÌÕW¹Ä3W_“+lÕó5ãŽÿí±C슿•®€zö·b#©g«ŒjüºØêÙ×¥ü¬ž}]È^»âªX»âB šïoÉkª¾!¢]ñ ݵ+¾Á®aW|C7Õ÷ »âï˜Xzúwܵéé߉ª]ñw pvÅßqcWüìvÅßi_jWü½]£þþãÙ/F¶&ê›Â BÓ߇LÕ~“*AÓÿ l&4üB×Úÿ ýn¡à@c;Ä?ÇÕÿÓ;‡à:ü“øêÅ·¤£^|K5¨ßÒîQ/¾%Ì£^|[J½ø¶®ÇêÅ·áÜ1I÷÷âþgЋûÅ{S/îWêÅýR1YÇÍ´ëùÜÂ7ª1wó­‰z;/ôßä›Kܾ­âJœ={ÞEœ­­©š]ý&ðÍrM”•#Ž‘|m´©næûïâšKG °ãPÍ%1´TsI×;Õ\–Æ£j6*7ª¹,Å™»"gvåµ"EÍA% éûÇøÉAñQ—þ¥¿ó5Íêï|±ÔßùºS¨¿óÅ*SÍ©¿ bõ†¸ì»Cô7Žïb†·G)÷}¨Ú 6]Ê^À’ Âì×n‚Vו°ìk9¸)һ엻ZðbíŒæZe ;xƒY®lµLè0{Á½ ö–cíìŽÚ ¸ÞÌMö#Ü{t½æãs-FN|_¶jzLõ’ž ã.¶C±1pŒ™A¹†×w#¶}6›°QxAMýÜ ntÜ øÌ¼ æîl"_GÙ½àÎâëOs½àšéëHÜ tH²:è9<-Øí-î͵Ö!~(‚Ð~0Ðè ?t6é?4è?î“ô€ß+­z~×YÝê•"hL š™õÕ¶r€qR{Ó \ìd/¸Ç×v.·Æ¬2z‹F†©›™ˆãI±`FŒ{“ç}¶C7;g6y SŠàmdhYó F{¥ÃÌ®ýQ |[Û¬¶bº6ªðµSÕŠÀm-]m I¿ÇÀ™¼á‡¾(Œ8[Û­6m/WUøÚˆ©j£™ ÉC`I£$¬HÓÇ`O âdç”ëNm¾¸צ’ _íwtîÙ ÔN¹/˜É›f×Ô64·§Ú–%fNŸ8=Ùvb{ª%1#ÕX—lØTS»$U»¬mbøš²,ÊùV鸱QÎõ¥ãÆE97”ŽåÜX: ´¹¦)yи1QÎM¥ã¸uý}éøâ(çÎÒñ£¢œ_–ŽåìÛ˜ZÚ˜\žlŸÏ#£¼WÄÙ—<žý$ÒjjV—Ž]ååM;®ª²btœý´‡:·†´Ó¢Üz>gDyŸUöå£ã±[üPö H;3Êmàóˆ(ÿ e_Q9}teEuåK¶<”þ™ä=2Êmäsv”¾K¿|úèùÕG?2óÅÓJÇŒA/æ|NòþÚuþGÅ¿´3¢Ü5|ΊòuÿQí/&íQîkølò&-˜6wvÅãÛªxiµkn*3–á;§È'×¼§qo%«–ÍÛùœåÿ“ÕÉóaà×7ïáô7“WÛæ|jöî*šì<Ææûµ¿‹¬Z6-3ŽÉï’ÿ°ëw’UíþŸGa¡ö‡…œ¤Ú4¿Ê§€Å[•û‡u‚¤jõ§øüø£¢Ù üjþNÝ\:´RüŸ*/PîÖý§$Õ†ù2Ÿ³¢|·a–Í7óæ…-m¿MÿçäÕŠùK>Û£ü™~½-¬s_!¯vL±tÌ£¢ü·ûý¦ôßm^‰¼Ú2>µežïÒ/Áæ…m5¯¼Ú2M|åPúEÇÆÍÛü°eÞâSÉ«=s`阒â(¿ÁFG†ñpÜûÑO^mšƒùœ̈qÉóBbm›CùÔ¶i-Âàõ7†àk;Ûf2ŸÚ6Ú¯gL}bc|ÎfÛǧ¶Í¯Í®˜óDÝŸ³Ù6'ð)þNåþaÝ‚ž³Y5Kùò>»hzÅqOÔ}2Iµg)[ nþ#åþaÝHª%3‘O¾‰Cþ³Ÿ¨{IµaãóÈ(çéÊýú§T;õÃE•1Rw6Û_KÿPÔš¬©;®¡µ½£¦qú±+R­ue K›“}ŸÑ° ¡r^A×7D_ßXÄ~ó’m©ÆåÉÙ©ºÖ¦¨`dg²¶£³~/nJ¶×T4×§°€wQªnÞì)Äí.¶¨¦½&Êþ«Šº({]ÅŠ(û5ÍÆÖ5´µ4Ž®ÔÛ]hÆhB+:+:]îÒ于¦¦•QÎw+êX(ÇU¬àë-KFGùo²ñ_§ZjSuÉyÉ¥Qþխɶޯö(÷‹4óò¦¦êÖäÒêö(ÿ˜ê¶%+iQñëÕm£XƒªÛ€ÜŪê¶ñ€ƒ¯Twįÿ°ºC¯GVwèõÖê^nHµPôçR-,ä“KÇ’ \âçî¬ØBóãswaéXî åïù¼n‘?ž÷Å¥cu(`×yá1óç/Œy?–6>§h~M{GkM{r!¾¼*5•ö.¯®žÑ&Ø=s,+Zî!ή<ºê±Šžù’(÷K¥cC/µÌß_9SKÇ‚#J,ë÷=GÇ”ŽãšU~¡ëü¾óç'mjýqëO/Ǫ<ɦpÉã[sSé¸Ñà«|ÞLýËKÇq¡)Oñy0õ·pˆä}‡Mý¼w'£Ò½_¤Í®æ›Pó×G¹¥¨ÙQÁ8¿‚N{¼¿ÉATWÐÏù.þ0ñ½ÜPgAæÀc&æñ{\ùŸ¬\”•ujc2Yåݰ¼¬e¿(ÕåîÌ™VóòS˜²\²`†ß0û²,-½ ÕaPi×¶F¹Ï¤NËNŠë”ýà3™‚ÇËÔœUÂ…niœvÉãiOáØ¬Ý¯®jq.>ö±X<‚ë´öí,í÷wGñ’ÒñìœR«¥ýÁš¾·t hAs]²¾¨~ªÃ»ßÙ:GpBÒ5~w”ÓÝXüpÿJñ… Άs3wúÕ©Žf€v;ejÝüSQeù¢ª'Ê,Ž.Ïr+ŽåS¸ø9EÚŒ?žÑYäÕ‘è}fŸü»»ª4»mYC=-Yz„..÷˜÷åï-ºy¥GŒâvˆ™ÈýnÒhLQuuÛ²VnÅöÒ#Æp^úg¼ýûù‹]$å45¥’³íú\|k麌ßȧöæªxožõÒãJü ¥Gè*>Î-óÓFc-öYÇÍ{uŽjâsæìÙ‹ª]8wÞô(çw6¹ËV~Æ­÷ÍQöòe _"Ë¢8ËFÝX õºÃ”æÇI¢÷è½}>M—˜ÂaºÖ”®ÑuFÏoÒóc¯BÓùO;J¢ì ÛøøVc*ÊýÓ:ù‚ëµ;“žöP¿‰¬êÑÆËPŽ…:q漇ltéÚy׳ Θº`þãÈìèÒöNéí–öã¼µ´„ëC‘Kˆ.¢g<^ìûKKÆBˆYìöÍzôùÒÀ~éï,í.§Ý{yàì"÷­ÒîÅÓÀ‹žhàÜÒnߺ!/+;îèÇ“®,-ÁûFál³eþ½¤÷—NÐÂú²ù–þ˜¸´tT1§ßÂZן@ëÈ: –Ó·Ñ—,x<ïë•W|‚Ö8ïÒ¾´"6•>¡oÝ‹S‚ò ŽQér%Öªû ß‚/¥g‰ãù[yµàWßb–àyß㆕®S^¡ðß×·öÒ­1žVù'×½”x,ÿ(¯ææ­nçþ` –žEZðÄïÅi0n3I ÙF76È ?H{#iE[Š¥ûÃ&i¸§‰´73Nûƒj5ŠÓ ÚQ-Œƒ¤OZ‘ ×™óöïe½œ¬:ÅÞg^¶¿—õudmg·Þb—¿¶:°½a4×A­­iÜJÏrëòŒÇñvéí¥Œ†ÖÕMšEÓíÎû¼Ÿ'¯è‡EAˆÓí¬üÄ©nJÍN)Óžl‚bPú‘¾µd¿E5,Ûûô=k¯¢†,?Æaò3TÙµÔ£Ü5b*hƒý`¥HVÑã —¸¬?òcÉ ©íw]ÖÌÌ*²»¦¸¬?˜Ð+Ȫ£žè2,½ôõ§É ªÍeýA_ï «¶Ha™Ëúƒ¾¾¹tÔvHr¡Ý¦ž°gå] ¤GDÙ»pýnÒu$³.þ3üQÞ©$Õ%ŒÂœßëˆHRµççþ`í=Ê»¸tÔX.Ñ 'åøXò>GÒic¢lm…ï›5×µ‚¤‚ý?óG—á¥&«Àqò¯ðÑ-&ޒг[¸æ°K;+«FáO&-œR5wËÿGÍIÞôdûãçþaÀâa˜àøÊ?¬ˆ¸ù;(žú‡%ßö‡-¿ëk:©y$>‰5’¯? g’ƒžDLÉWžeɼ'q_òŽ'¡¥¨sÿ êÿ Lßÿo½xÍ¿]’Â'/Iã“ÇŽdï'ï)…Q¼Ùþꇡ˜?^Ÿ”íÇ'®Âð?ÞÑ 3þx¬+~ëßN‚Å›ÿíY¼üOÏ£ÿt`-ìüÇ{nq¯»'_zò4üÝ“×ïdõ“÷õäO^ð _þ7’À‚£)_þodˆÂÙÿƸ þ ­ã–#”èÅO8*…¦?2a _ÿ#ã§òŠÇE…$.% ŸäF%—?IÄJÎ’ê•Ìú#©ìçÿÌ\»úO<¹Wü{/>ûtÃbÍŸˆOû7eåøÇÙš•g>N-^ø'nêËþÄ€ñ'žíà?±yÿêß8Ã¥ãÿDe–ËÁr¬û3»üÒ?3ÆKkþÄ[/5ý‰_Zù'~éïÿÄ÷/ý“æ€`åO¤ «þ¨ŸPxñuŠKÿM(¢Tõ'=ŠÒ?ýI÷¢tÌŸôI’?)‚’”?©¶’´=)ë’üÓú1IדB5IÍ“Š8Ésž”ÞIö}Rã§<éÏ‚B¥WþIÀ¨ýI/©4÷OòL¥Æ?©A™|?Ÿ*}ïOZWɹOêj%ÍO x%¯}R),ùê“’d…ŸýQü¬ðí?ꬕ^ú'Q·Âžÿ¦ wËŸÔêX^?–ÆKþM‡¯´üOª¥Â?‹ Žÿ“¤áõÒOü»?‰5üoÊIö“"”ÉgžÔËüÐû.“´URÍ4LÿÇ/æ/ÊE´´äì+G;÷vBv8Ü'z«zLQ%¹˜5>º}QvÒ¢¾;®(uÙUÆHSÅHž¾aå¥ãŸÔ¦Î›Â*¸îh _Xº|a?X®0<ýPXfc±Ûö“ ûç…å î…5¢lÛä¼B›Âò=i ûÑât…á€Âšín–ð¾ˆÅ [f…ÿe…»Ò$lJkFÁ·¿óMlK˱ƒ+íGh•¦ÿ¦´þˆop6›íœ…¦™9ûO=Ó˜Âàof ¸Ýœ…–™9ûOÃ… ÄI‹~Y9UTÇÊù Ìs…i¸La-( ’>º¦¢ .eYõ'`Ó•%…mSÖ dÙ‡ÄòÎû1®†÷_P¯+ ;š”6„`«ó¸=­l«c?ß®,¡PV+F†:«Ó¶¬|ÀLYÿ:_’q6e ŇÃ0çf;Ú¹÷ê dóã#„+ o65  1<6eLQƒýø ⊒áSÔp¼ÅŒg 0X~yƒýè㊒ SÔ§GJÈÝUE‹?:¹¢°7DQ#ÑÏ%åo‹ ÂÊ"ƒŸ¤\irÂcJ…tøhI›»Òò[˜+íG×1W6K)m4î}ög¸ÒÂYΖöãC+M^cLiûcªqŒ ¹Òò ¡+íG7CWšÌD™ÒÆà‹q,~´\iáXiKûñùÒ•&‡¦´±˜ƒjs¦Òý§wÓtŒpIu¥É.–)­ ãb×Ç-7\™Èÿ׳®+N.‘Lqãš?Ъvî½&k§ýø¸ìŠÂÎ Eˆ7”ñÎd†)*,ÊŸ·]QjŽ)jDönTT`¨¨“ \Qؘ¢¨Cp4A^lQ¡S?¦9¸¢ä`Ê5ƒ‡Ê¼íÏ™´ÿGD W”Ìv˜¢Å1ŤØUEUgêGTW”Žs¦¨I€š©±€ýíסœ¸Ò0ËEiS™†ò®™•æ¹.Yißg¿¸Òt4¥atåˆ7÷•æi7Yiß'â¸Ò°´BiGàaf^<º6€tDùgF+L@Ñ6;ÇÄFú÷ñ4„?á%¹²dÍ”u ÞÉ­AZV:¾®¬^\øQÖ"Œú¯Å(YŒÁO8Z®0Ùu4…Ð?Ež÷Ý7ŒÑýg¶˜+MwSÚ)ìôå2Øšn…”¦–n…×\iØN¦´å8::3vGáKÛ½Ë~À¡s¥á¹†ÒÎÄÈSdŸ"+m÷.ûÏ•†EFJ{ Þߟ{¦0³–óݬýˆYèJ“³SÚ3d•ÏœFeùWš£+;R· ¿b«å9&-.cX¦ÅýtéŠÃ§5Å­æ²66MÑ”azjóýöé ÂÜ­å<±.¾›ì§š2eÿB>µ¥áYŠÒÖaþeClî~ÀÒ+[ø',XW˜N妰 €´‹årΖ’o}a?`ãºÂŒ{\v1N.‰mêÜ‘€nø!+؆M9 »—‡—ÅGBWX¶Ê\aÿ²ÉðáFa—a;æ¹2úžÖt~È’v…É^‡)ì¹Ì×ÖØý{cš—-àö޶+‡”³ã¾Ï—Q}[Ž%„Ûr¾KwåHÆÔ”ó|Ü_!¯E°ªttX?᧻¼LaWps¾ÒX5Z¼-ìG åâW™_T iý@ŽÊ¥[ƒ)êW!†üšgºö‡NýH˥Û)ê×°9ô[1§gÀ.vÀOd¹\aؤ°ßlü^ìgÉ ­T Ì¡­ˆƒ¹²äÂДõ{Xgú}óÊø«^“,ã¯~_¥Ì•†ÕiJû}0ÁçäF.%™f•9’鿆›O ûD¤?Ù»Âr•6[ØdÛ\aº”˜Âþ}óù•qa5µ8öÏòq®0¹@4…}z_”í|†7ˆÖ1¼?±sea³™²¾7íOã fË ;áÇJz®,‚MYÊûK.wUËú±œŸ+KVtMYÉUã¯åB•²‚† eýXSЕ¥³¦)ë¯9÷þ-ë7-+tëdž®,P4eý-òïc*ºÁ\µ!ø‘º¢+ W»”õ÷ìÛ2žWPt4Hæ?Ld-ÐõO°Vï—WSWTýPbÒ…O>Šºÿ`|iY>°)ªzˆú‘ܶ-J–õ(*ήƻ¦õÇmàQ¦¬éàÑ¥6]aº šÂJÇ"?‹­4SXPø4…ýXòÓ¦€)¬á{x¶Äýٱ¹Ð¨Ù±?ue û˜²>w‚–K0øÉS1:þMÕ(5¦À–ãñƒi¯2ßL€ÕŒïôXmQxèäo‡Ÿ2HÀº¢þetï7E‰ï3bLQÕíõCMZW”|ªš¢FÎÃÎ%öé\QÕíõCU\W”覨ý~‚ÃJK 2gÔêÁ䇺¼®(|Eò7³ãdºÏU=CüPØ%ŒiŠ:·cããã¿)*ÌÔ´‰]QRû0EÇFé!±HI¿ †,’´‘]I¢˜’y!&-ó…’¼³-éûÒÌ®¤VÒ”År$¦ÏLI©´)éÊЮ$ɘ’¦-Äw¤%ß™Æ;)j×øï S»’äöÝ”4ƒýÔ.sÏ®ñÕ’¾¯‹íJÒP›’ää)ž{`6%ý@–Û•„kZþæŒÆ)½r›Æ;p×øï©‚»’Äí0%ͽÏöàdIN‡Ü“&¾'KîŠÂ“/Gc°õ˜ø¤kZúôYtWÖåù;Ï äãÐcêЧª³»¢.멜»0¾QDO¢ ÁÜ,SÌÈ– i—h$¿XV1Ä÷¿Å «Å²¨‚ÞÈï+oΓÝ9c2ÏZ´›ÔŒ™§‹[“Ñ:{ õš·R˜ÔŒÁ¸‹[Û£kÊ›‡ë-výб-ÉIÍ5m'F–ƒƒåØœä¤æzl;mˆžóÞ’哖ئä$sG.Sj“¿Ùbäl°½(ZŒžùz!{R¯ èM¼xzùÔ&*öÖhýXË“/®˜3ƒÙšøöuòÊÎÞÄ‹ËçÍ›Ë go1ÌÇ[±x&^\Y6§bZôFÍýÀ@=6›(ó¡õ’ß÷:}é‡ï!}óóhs_èú1CÁˆõÅïv ˾pmV4ì¬ý{Öwc[q[N´sUÎð‰%9Ñ‹»ê²‹ÄâÀ³ý¶¬hfÉþQi×°œ çt+7•·•ÉE¢~íÑ!PH—Ϭž·èÁÍ´¸Ý±í±Þ\ÎÎÓâr[yóÎê úVÍV“ù)F¯¢rê¶½ó}Ä®+Æ5V¥ùêãu7÷Üe½¼u Äöš¨Ä÷o×ꨤ›%ºm?ú ŸØU›]xÉiÑ‹éëÙôu™úºüÕÞ2©Ð,*ªœ[ùPk#ë'VšG„>·Þ¢nÒÙÛkeÈö–~úÞbKƒ‚’†)ý£ïíuŸî¹3Ý_÷¶C©=Þ¶o4¬*'{~Ù©ÑÞ®ßcÔëa—u­Š{­<çTEùã}ûÚ3ÿÔ¨¸ûr¬*˜G½H¼­jñ»}¬µÞéU˜<­ÕW9eò;£áݧÏ\Trn¨½c޶ӫê,Y ´Ûm–¯øí,eó3"ÌU›ÅÔ¢¨ÛbbÁGçØŒaεsƾ.`ãfŒ¹ò{]dñH¶teý³a/-¯#›˜hk¯©=1Q—J¶5ÚžXV³<™H6§:–.K´¦RMN7ÂåÇDþ Ø(hÃ^-mËjê&&’ó+“¸Â‰vú{›eèÝXô~hØkp–ïÐoÛ/ë5U³ÙÜýΨ‘¹jX÷Ψ¹{¿œYönQɪ¬e%ë"ïÌ̹Ö;å×îöïÚG;—Ðøväcü}o‘ /íf®;ò½åÛQóºUn?Ø]ye´$Äαg¦kÔnÈßAOö±ËBì¹›ðÃûAÆie&ˆQ\4jüC7ß­¶ 0׺ÈÞ1ßgÛ;Õ£,Éq“å`†w„×LrcˆÝb·…Ø!ö©ûlˆ})Äîµ=… àŽ=Ï {J;#ÝSÛOíwZKª¥ºfb¢9Õî×’1Ô–jŽ7W¾w cC•B¿Óð‘Ý9én™ÏÎèÜ+“Û+7‚AŽKç87šbdžØü;:Äæ…Øœ˰[͸d¿è$¾ñ}ßÇò} ßGóýL¾çñ}>ßsø>ïv¾ŸÀvñ0áÖS9M>¶nò]ÓbóŒåËñöŽm{d^Ø5Ë~YbBìò»&Äv†˜ßGÄü>"v›íè ;e~À—Üx<¾äì­ÑJ0³9ÀaEvÕföÀ£˜‚Çü'ìsùþk±^‰¼§Q²ï•9Ë»^qùs%Á$í€7Þ+Þ&Ýc^s»ï®É.\ÇýâVö€z9ºê<0ë5÷`Ö]½Øù‘^¯ó½~ ¸vß7D0&Éf`™Í´ûÎ0 7æâ½8µ“ra¹¡7—yË5Ïç¹Ì Áì(ZN,š÷æ´óÕ•ãû½9íþèʉ1ïÞœÇtå÷æ´½+'<ÌÞœövÒ•QoN{K 97æ('»¼Ø›ÓÝÓx'Lfr€ë9xçs€?ë9x§¹69Øõ¼SŽÊaØ:>Çb®¸ËŸÍ›‚ö=vä½)ÖÝ¿’¶º\ùM@¯4'¾Â–æ8ª ~ÃÁ ´‚’Lï †–^Ç·v`éý–ñ3î"šeÄŒ2F÷›úL.GùŠŠVýR—uÖ- ®kæ+Òþ”µÜŠLäîà›¿ÐdÃnq »õ׉qo$';êlÐ>T º½ 5ˆý¬¹2&à…¿Œ xq1e&]„ºF‰ñŠÕ(£¯ª¿Iý‰±IÖéuCl’¦£xêM2ج~ôÓÜɘw?°ÄJì§Û ÞöæÓí¼ŸfR,Ÿ~0"e>zªÔnuçíwJÜÇ~§¸>bÃ6µóŽNŒ¦:óë'[õš·fuVóÖ,›ýš—fÙªnhÖýWdÎf™ñ°¿LRkô×T·{#ÓªÕÐ_C¶¬ûÃv™èèiº‹ªýß÷±?Šô±ÿeqìæePòɨ±B9á¿ÂiA ËF1ßÏ e!žg£ :ÞÛ(=-k£Vddp¾ÑgÒžðÖ“ßÛ²•ê­Œ5’ب˾¦d ¦B[¥EDMIËÁq%-÷o*‘.CÚë¾9 Qã§÷oƒYå¯õ™UfOy‘iv 7| -Ç>f'{ÃÇ0€¼‘d±šsóÇ_í3«¬iû纤U˜šBfçùÙ·™Yå{ûÌ*£Åô“}Ol-\É™kV™{¬%Šßèbä'ù¾´šIlðVè!k3cØÖ¬ò7Ìp¶7‡Í•¹f›]\3‡M'û‚0ø[nz”Š‘9÷-ÿK‘î×+7Ád£¯‡ÎÜpiñ£Œ yrä ÚqüSã“ϵvF¹Ó°þ+7l?ý(e¡p¿6µ·V/mìÀá·ú$îµ*øf¼BbëÓzv†yÞʉŸÃ .ª­i®vsÜ™ie]²­¶µ¡¥=ÕZÝ®ºój¼¹(ÙY›lq¥ÕZ¶™äÉmprþPvÀV–ϯŒr_M¯äèïm˜×•ŸÌ]^T£üÇÓVk”–s;£ì[jù(Öñqç’Nœ nijÁUËy|ün9¾Q‡u;çÑW?y‡ŒrßC>ù#Eîî‰[ÞÝ&–gâ¾T[$Êý,xe•lУõYU¥õv¯tûcs%ß]Ågþ~¯òû]Zõ(êè›ÀÈ^¥Xû¥bMÐyê{íp 05D Ý“’Œ£ oÚ¶ëÀôÝþ»B¼ ‚,膘k á¨k y|Þ\!Þô@JÅýbÙß?Ø"“ý%S5:ЧqW*¶M˜”ïîWŠ·60€¾ yw?tÂtnè_e®of`‚@-±ø·-…a±¥ü`Z*é:©ËiºÂ¼Œ*ô¸´?HLWÍfA׫!ý¿~}j1]¹qÉ~ö_X”ÛúY”;O‹NZ‚Eù˜€Q7‹Ò²mm êƒgQrCó,J.ûûX”…ËÚf·rÍßÇ&>§«.ú›Ø²W–?‚ºº70H<£‚[g/é—葉—Üø¸œK¶¯¡ê·Œb³:Åì‡ï2Š ëì;íÍg¶Î(®³]£˜~úÞÂ:!,Ô/Îi;íïÙi­ëê²öì¾–Þø£s»Ä³¤bê÷_YRvfm ÍTë1 ¢Î›°ë±eÓØÃþÔÛXÌwïèñMý=Nã?èñ¢¡z cp_é«ï1ŒBz,TÑtòƒ=Ž®ÛÐã,þƒ/J Çpaöõ˜¾ú;VKŒjd¿cvÌñ—ûç8ÿ ÇÇ %ÐãnVoµÇôÕ÷6™Þ& ºæâ{œŒÜÐã,þƒ?”@aîë±eÉÙÖ¢ÇbõÖŽ9^Õ?Çiü=–…‹¾z j_é«ï1¬)ÙH^Air/Ë:ëóø>¶ó•Yçƒ!Ó¸¾Ûzñ%ïQqè½ tãÊMvx šÌìÙÌ`Ìñƒû5Ób0¿<{•w+lF`}uÎÈÍ{2~Fà„1#ºc ÌúÓŒD×=8#ÑuÿcFƒ6}ÌH7#»:#ÌE`dkF H µìóç=òå{äËÿcFƒF}Ììå}3˜à0 ™1ÁÍýÓŒ$#œ‘däÿ˜‘Ç Uß3RgЇa.üŒÀŒÓ³ˆZÞàÕÞ#«vì‘U}326úß…µ|£§¿s¿¼ÌÍ567Áµ¾æ|çÜÜæ†Yñ·o˜ïc®_ë×brÅ“r0kª-?,x§Óúµ j0rœÍ'¢Íú_„EÜúµ!Ô`Úþ·LÛ&5˜íߎ»W¹;·ó+£ ¿2ª ±u›Ô`ônSˆm ±Ëÿ§ÌŒÑQƒA1À«Á0ß^ U¯mÈ«Á0Ã^ †^ †;Wß æÕ7ˆy5b^ †˜Wƒ!æÕ`ˆy5b^ ÞÊ>5Ôüž?): 曎8Ø©ÁhÏ<$ã÷ÂË£%¸1#îÇ»Õ`:÷ÊOÔ`V—e!¶4Ä–lVŒ *1A&`³`ŽËù^Æ÷¾—ò½‰ïE|¯ã{>ßkøžÇ÷*¾Ûùæ.¿Ž³êwj0­›nl"õéT †õj0ì¯îñj0`¯CÌ«Áój0ļ 1¯óˆ:‘Ý)¨¥îSƒÑ>Hw* ­2*£®ï»ÓýW5˜GI)ùþój0”·O †þø^IÑ•”2êû½óq5ÅÎ!ÏÃj0Ûþ¢óX¯»nŽbŒ¤X•ðj0R§xX †¾{ €c‚¤<1ú_“ÍíÉÖ‡%V4´/K8xÛ”DqQ¢jPõ¢ŽÆµ¢-UŸh_ÖЖhÈ´§­©f¥Cç%µ©¦–Æd{²(A^¥yvMksCóRŠÚШ÷›Za³¯­WlXÉÇj^¬mM8æz[kGsQÔ²ÞH¨U‰ã9ú_ËçT•Ïëƒ' æŒ‹¨Î͵´n‹È WàçþWÍõ‡nî¹Þf{çD¸7`”à­QAx¤E7‡ˆóÿ¥ßˆ u¸n¿a;/¼1ÿnåqX¦máúü£ø1€_^OŽóÜ¡<ªkB÷³Ó÷‘–u+¨ó-Q.9—Y,!¶(äh[ø™ü)%9==â9ízv4¼ë¼ìÂ’ ¢aÚ5ÙÛ†Éámq ¾Ówà® ¿Ã]y?Z{ñ·¹¥çêls©{Z ®ön8˜1ðWóºý¢fÅì¼$#&}*ëœIïŒZ&­Š'UG­“ŽŠšgFYcC­7t£÷àjYÒžŠzý­µ°+Õ£¤¤©ýšb¸mðóÌ{ñFÍ{9îïõýÙux©"Ç­lrìz놻É7ï¥_aÞ¿vc ×öä¾þžd{Þöä¾þž¤ï™uדûú{’æp=¹¯¿'éû¹7öôĻ徫Âì¬ s8¹„° `æCÛÐôBL4Õ‘bcz«<áñØpyvÝ“gC¨m¦p±”°æ‡ïë¯1ÅÜúžòùZïë¯5Ív¥ÃßìžfWƒÚò>ŒVýìÐmÔ²5ì®oåáêÔ»]öŽZ•ÿrð×&á¯÷ƒª̸ž+F‡9x!¶ñãr¸ÕÛÐf't+EqêlLÊшðnrx7ßrƒ¹üýµŸsBŽ5áÞô-ˇ ¸¿ `|Âߤð+1!ƒÿâÒ ÿ$ö·ÄåýýHEÆ?̼K|Mz—[LgžÄß$šxN'ïn ïîÌä.xÅÊ0Þ&p×¶ô^›uVW^TZ¶š›µ0Ö£w­>ßüÕ1&{4ßÙÖ 0Ö&ö"Œu {qc¸Áî½s¹›½ѯ€ˆ¢á%(Žˆ*rc÷ØÁÔí)æµeðvÊÝÊïîV[Â;‡âß/Üž>îñ_·ÝÁ†è¼C- w(“qq£ãÁ³{]·û†ýÊ·¦Io¬ª›¼öªºÙz¬ª–*¼.ÝzsÚýÕ•FyoN{éÊ)Ĺ7§½cuåDu­7§½ÓuåÔÅ}oN{/îʉŠDoNË…èÊIºÞœ–wÒ•#†O*†œÚæ{sZžTWN Ëôæ´ü³®œð»{sZ^_WÎlÏiùŽ]9ÅÜ›Óò@»r¾h{NËíÊ)ÞýÞœ–7Ü•óÅÛsZ>uWN9 Ù›ÓòÌ»rbY¡7§åÝw唊ÝwmN«´†©«(Zž¿ÍÁ]²žƒw>¿žƒw>·ýzÞùðHê9xçsÀG©çàÝOÔ!™ƒnuÈ&)-¢¦ö :$l¤œWBÖ¨CÊ!ˆÑj„{#Q–jZÒ4êh ãV¸g¡pR¹Ñi‡ÀyÊ´Ñ£MúµWMnƒ4ØTgÃÜ8Ã\‡ë²üi§„St—h@ý|Ûð!Ëøý£*‡:dGÅÚúßH h½4ª+¨CbÎKYß×Óø¾-h”® H˜ÆT€^œ*h²UM+ã šVn©  ž"4I×D4É‘*è§ë•*èwt\A¿£·TÐO;Oô“Õ%UÐï«í9UÐ<2® yä– šqÀBͪD4k‡«‚f,¬QAåTR•ì© ¿c°:}IUÐ5$*è¯ÝA_° ¾°¥‚š~ÍáM¿fy€¦T 7O: ¤4ª*¼?Þ:®à[J—~W6à7®–Ze™þ$ÕµÀº¯Ðo ”1Tõ@! U=P(ZUÔ5AYʼŒª¨§ªjÞUuËqÕ-{ ViYR5ÑŽª[„¡Uu‹nªºEPU·ÈUŸ²´ÜWÝ"ÍHU=H{JU:&®zÐ1ƒU£©™UM´£êABªzþ¥¨zÌèêAê­² ÖªêÁb¸«êÁBÓªzðÉqÕƒO¬:¨eÚhGÕƒ5AªzðãªË‹ªü½8ËM ª¢9WÕC„GTukc\u뗫椘UM´£jã‡E˜e¨.’ÚêCå‰LU•Ç,©h µê‡)«f~˜t]uÃÆÍ,3ìJ¾u¡&EG]†ë(Ý×áBþÂ6Ã¥ÿ*½Ôá²ã)ípôÐ}.E0uxø÷ù–îëpa#±oFHÁHªG#¤©®ŽH8„‚ÙL«Ô&’ï£NÝ×Ê é•-¦g¹Á^#u¹Ñ®)¥SíÚ‘všš‘ò8(l7Rfœ„jGJ7WoGJ»Rˆy”ô`…ÓFQ}%ưú8JûZ}Õ÷gÔ7¼¡¡3¡›Ím”ݾ­‚˜ae6A6J×Ô%¥·r³ã¢æ~Åo?©4iãí§«xû½5îÉ~oÝ‚öÃ×GK°Lèc´¶¹:ܶӷ¿Ü~ikìo(`Œ0Šú5Fv—´5ÆhÚ4uc¥V¬©k“ά¶G›n$BÄmš m6ÞÂÕj“Ý/á½6KÑÖ§|Úãt'Õ¶§ -=ªqX•bkŒÃcVL‰'õ÷æ+¦ [††Í ,¸ÂPWLŸ¤©1ý8PNÈTór·£~¾‹a¶vŠÁ¢b”‰‡'m­ñ¨ ÇÔ=ž­S÷Al‹„ <Ÿ) Sq}H¨÷`&zÓÁðê<$‘ÐçCØ[ [æ¶dBa‚,2Bo“ëõš§Ë"¸k%Ô>™(Ðû \ç Ô9¼S ¾CÙ ¨VJ¿ ôõPzS`+O7èãDîüú7QùÔ¿IèVÀÍ“˜ûó4 ôcdþÎ4ÖþÎm³lÞÙ`ü C Œ–í¶Ú&V÷]”£ .3¬oZv66ã2…ci2ä[Ðü&릠2Y7;íƒÉÂtÚM‡IW•æœ(èNˆú~˜¬œjGN–ÒlMÑNPϧ½i“OâÐŒ®i“®íªY;\·Gmòõƒ4SuÓŠ™*N¹fpªú­œª¨œ*<¦œÊ¾‰ÐÛ˜F×bº=MJ·š™i{¹Þ×vä¾™áv৤/Ýd6†W DcØk{}db(zíaƒ×4®é×t“Ù!?©‹K–×'†ÑákDQ¸W7ÍûŸÔè{’é&£ ou“‡Ýdô‘½n²×•¦h´{Ýäýƒn2lôu“¹Ï=¦› zÍ^°¹¸œd/Ð Mµ•Í ±‹Ìµ¾/µåRÑ£R|™Øòo;ÍáŠ9š¼UýàÊÏûõƒ×ܧ>»~(‘æÒ (K£8 }åÙÌïÄþÊ?‰uªk³£(Ö¡<-ʯ~TV/Ê™””¾³U\–ôwEë”É.žH!Þ~Ê£ÊpQî+LVá/}Te-Ê} ùTß9*–¥JÌ/|Tý+Ê}ùTß÷•´¢ÜÏ!s<#Ê{Þ£jS囊SÈ(oN.­†ôWËv1=¼»y¼…yzP–ûþ:¦í“T¯Å{×£:NÉ~Irþié˜ñtlÛ£ºFÉQõäüKrªÎuêü$ÕKÉY.suþé£7ÉÍE.>•œíQîôÒ1Šá´èsZTðÚÇ•OúTþ.ÌOö+G³ì"Ÿï¿'Õ3Tþ.ì‘Dú»p|íïÂIIÄ¿ ’¨ß‘”üwaTýï¬$à…“R?™Êg3¾§=åZ:¶ °ß£ú Qþ 6(€ïaåÓ%¨9Œ Œòÿµ¾¡µ­½º½09IúâÑ¥c“§í|NàsZ”µòæÂ‡Š’­­ òžÉý¡TùdéËÏÔ”Kº\©€:[z—Ó–YÙžrË&Ê;Ñà('»¾È tUºÂQé(Óp(}Öç”ÒqÅc£Üo>JMý@¼`ŽeÁNbôå¿ËkåÔ£9OŒTénRö£Û¥ôí¿“ÛíÅþF+~PŠ?ø=ø)®ý=®*ù{ðWú𣘲´ôQ¬ZÚ÷Q \Zö(¶.u?ŠÙKW=z$(]÷è ¢<ú±£Gñôßß—ú&ÐÕ/AÑ6M¼†½HVÃþûνª~ý–†Ø‚¹Ñ°§íNÃþ»ÏUe}1ç£a±sz4ìm-hØÿ¨”T[_ü›ÆXyÜ Ï/„2a…çtWŠWÖoäðÞ[A·¥,J—òønq¥xeý&øàÆaŠ/eqº”Ç×™+Å+ë÷ƒrÚìLɸRŽK—òøu¥èœmJi†™Ò?¶ÑhK9>]ÊãKÛ•¢ÿ¦”þœ•ûÇ&ùl)ËÓ¥<Ž\)Þø_Ä@p+Š©3+êC—ý×ÿËý®ó…ü`äRcÿb€ r |[g ùÁÀ¥VþE,š¿+„y3…ü`ܼqÿÁðñ[¿œ)„i3…ü`ØR«þ"쌈­3;+ H:+ OHôU ú@e~Ì·Æm-ÖŠÂJñ¶üGö‹ ü:+ *Ί¿šñßàhôE³Ý›–òÐã-ø†Ú0)¶éÛ”9I 4óƒû„+ÈÛïŸgfZì]¡äî!â€|÷žâ}¯db@O"¢…vT0ÈéÏ:©ø¿¿>ª,2XÉ#£Ð%º~}r¿úx ¹Kdß'™|y$‘yFÁÏlB ±Q¼]öÖ¦EŸ Ë{áöå­¥ùŸ–wÔ4äÂòöo»–·ôZÞòÑ»¼Ûʆ@ð·akg‘ãyI®¦Š75 ÑbBm©Žö¶†º¤)a­Íb’ºÜhˆÌŠy€Åæjk[ÖÑÞ.ÍÇ5©͉ºŽd¢=•hTniGÚ"6·ÔÔ&G&`~uä¨(w§Ë­´ŸfƬÁÿT‹-Åé}qwØ8S4Nϼ6òuçöÜîu¿n­‰^Ò¯W{“´ sÝ¿fi£ÿ…³=£“,ÿÒJ†Üü_5mïâ]RòŽž»Ñ¾Kðåõ¢¹¸ÁéêY¯Ð\ܨ8Z_N;Ìë=¶Oú:|6wìütô`×?S‹rlG1Bïf’sãºí9wYÎ[ÉñrÚ~­¾¬_ÝÞB¶3WU 1ý£Ýîcº90£«â´¾`s®°wì£uöŽK¡×´…Wï5éàÄßôƼ¶ùîµwÜ›¼/½‹½æ·rÇ3MW æn§®Øõºd8]1#äöÏØ“b¯6¾ß„ìÉ$íò6-N¢ÄvMsÏq+ð â ‘¹<œaU‹ ›çÉÒø'1Ç+~f“þ÷ΚhÑi ºð›Â¾[¢†n¨vÚ¤a§-Ón`öÝiÐÈÛ0N·DmGó]@o÷^aȇé†ní’kzîbŸœÞ':M½JñŠõfwŒžéÿê´û6>ÖŸë¬?+NÏÒÛ£]Ö£[éÑ÷5ǯñ»¯“dêv»Ä{1é܃^×—×g÷y}qvÉõaßÝ`14¼Ž8uxpêøV¦éIÚ:´kb¯ÙÈ~ôZÓª#^dûFyç~¼%hŠÃd÷»‹óµ[®ˆ™—¬Gqô¤y¯x[}+ª½NPÜí1œPr©–6EËXíºÕ=·¥}³H-‚]¶£uhÿ;N3¹ î‘æÉƒ8-Ê6œ†6®pZ”í4{ðÑvzYÝVÅåKÚu’j¾<†ß¾ÌÞQ‡× e¾=^bOlµÌþë·y±‰wVnŽÍ9ÞÍ1šj̱ÏCJc’ùÞ9¾4ã4”9N8i a7ö10Ç»¿o€96ø×Íq±Ž‹ÿ{ŽwóñcfÍÏ1»¼>ÇŒ‚ŸctöÍqp&ŠvŠB:O“{í$ohD…{}s²ç†Œýµ½nFGÇʵœËç“O„ûõu5(xOéu/:‚|>±îM­É6Ù>lØ+âEÔr‰|TñÈÄŠÖš–šÖTGsªX.'ú'è€K1©#çåרká,]Û·"UüPTç#>’Âè9ÔH5…ÁLÍ3X&ÇIÞ#xeExwvpäêý/ðn«½ƒÜÞÝaïÀ^w˜w÷Ø;íê87ó.fï„Ò{"ï&Ø;a€T›wþ¦©={cÞÝbï´·ã«28^zÝ©ÔT¯›wÞãškø]œâ?î> Èþ“¾YÛ SJèÇøœð?Ðx’R]5g'üóùPvCéGįŽ|SZGu\4ßPE”fd5…FºožÏ».ºUàJi uÖeqT^šq£È%m«j.l“ÎÈn°øEø›Ûi‘Ë@Û á——õÜš¾Oˆp“ÝMS,Óu_Ïnª-§qÛípFËyÜ”Ï=§§‡ëÒ˜¥ëfAìë䨰#ÇÝAo|Q×>7•ú\÷Oƒ¶ž|S%7 ºÝ]pÀµöþšI«²ÎêæjçjÞÝ×Gë[¤Ü[÷qúå½ýjë:™ûlWÀ UþÀ˜»*^0ÊiævºGØÃíFvIkÀþŽÊ¾›vøT{ÇNóÞù;*»Ëkó.ÜT=.ÐêØÿY¬Írhÿ¤úû¼[d»õÂÝ·SÀ¿ÛÕܼ3W|vôêÛ;¥žƒw>û¢žƒw>»¦žƒw>{ªžƒw>Ç“îa¹ùÔsðÎçà¾TÏaµÃmîVõÖoŽÍÁM¬žÃê‰Û¬¶zÞùàìz«1ns€Ñë9œ›å>œÓÚÜê9xçsp£­ç°Úã6¦žÃ`—nO=ï|¸õ¼ó9àŽÔsðÎç€KWÏÁ;Ÿã]p›.V=‡ÕP·úâ†,Ûƒwž,l< t‘…KRÒeöá)îù•TŠ:[’ê¹&×xË•¢déÓ|K³$-]*þ+QÖ{ý²/Åj-KZŠ˜eiäJ]µ¢‰ú¯H]¼€ŠTÂ¥ Z‘ªµ”0+RØ–ž@ƒ°¨.Õ Bfbl6p˜‚áг•ÕØ’1ýh€ÅjœÂA*ÀeÄjS–㌢|Ø”%˜ˆÛ ïKÕª(š_£(ób¤5iKªž&zb´ÁÑ’ÖeÇxÃU_û QéàÛO^l¥øÙOúÌÒ%n;T}m–’¨r7 ªÍ‡¤Í"8‹Ù_.(4‰ýé·Ü=DOC)”>âáµØ°Epö3€^欎û8à3ŽdF¿×GÇÖxëæÏmjv®0Ç )¡*û )«’ArÕ‹>5ªÇªh°pŸt¿›ãöÁšhMè`ùîì`ôcñe5D\VuwˆjÖ~b~l‡Ä~l¹ÌÿµZBíõ‰"»Bz;äSq_Z•L}iU>õ¥UûêK«ú¥¾´J¹^}i•f¸úÒ g€¾ U>õe¨&P}*µrõŨE«/C/û2ôr×< åÞ¾˜Gº•³þ´A†K0A9FÐ&~„øØêÓj¤?#˜^6Û8h¾Ž^QŸF ¡ÞŒ*3êÍhƪ_#ÑùeÔÛ_Ô›©Wa”ð‰j%OA¨8#+£þ’¾°6Þ(9ç•âõ(mmŠý„åµñö“ñ÷£”²ßLJ¦h/æ‰Í±÷Ę-:ZŽÔµ9FË!¸6Öh4jÙ £ézãÙ18|4œÇ˜ ¶ÿ›'4Úç½|kÆH¨Fs6†Y‰éÛôqcú6uOt‡ÇÀwŽÙhcÅãÔ¼eNÐ!+}cIuŒE]7¦_cÙtèeÃ3rmâYj.ÛŒý‹+xOZ£–Ù+Äb÷«‹‚2˜;³°3Û&θz?N˜H~œv–z=N*DšÑqÒÉUìÝŒÔëħ׌ ^më˜`ÏBš‹EGcY³‚Âöº­h6šÑlޝU³9^;D³9^8]7ãÕõz¼Ðfs”ÝŽÃQ€Uê¶n)è ¹ØðV÷˜œ`95úbk[iÞþ¾½mpõ wÓ[í19Kiåäï-?z›ÕýYËÓêö]g?3~˜?ÌŒï{‹«åw«Ù9²Ðœ²½çjr]ž%š[ª©p1œ€[ï®BAt×ÅNS]ìtu dàP\žçfpß œ–ø¾â¾ÍêU[0¾¯(‰óŽ]p”:fwÏìù‡°|—Ž­É‚ëCöÂ]]ò¸™àÊ–½@¿¶YQOõ¡]lD+xv”{’¾Ò½†Oé‘ö* §ªÑ}*¨¼þP"´òIxE—&e!7—„}•âç'é•'d«Õ[¼šOÉ´öê7's‹¤~ ]?R®üÒ5„òÿí^—•ãÝ«'¼Wˆörª…/Ø wåP®dNeBº Ø^¡ïŠÊžfý´ÕM¢,ÍÒÅ¥c›.¶ð©=ò¢Ò±Ú#;ø”$Ë‹ùT÷_§¬D¿”OµãZ>å(úe|Ê¢òËùÔ`þŸíQöÛ2»#*ørÿ.‰ò®u̱(«ÙÝ~u-QÁÅ&Ö¬>lYÙ’Œ²::0±iÅÅÏ]ÒÈv9¦¶:YåŒl­^eÕÔD¹/YRÓ†Bí§c6Wñ­î{el6剗.r¾]W½«ç.§ÀÆ¥Õ¦—Œ²ÛÜ\¬†h¦NL£1Jº¶1Y«^npñ‹ëëÛ’œÔîhGVˆÄÚ?[ÚÚ2y*OÓ«”S8;ž3[Oùˤ¡Êò?0ï¾±®Ý$ŽK×8©Û(나Q»Rœá•Ö¿LŽï¯KÇŽgŽþ†OMã½|êQ¥tìLcŸšÆF>5M|Jú››5VTòâ'×{é÷-–Ò?Þ·æJçÝ·vKkïC}xtäk”‘0Wµ.°=õ×ÔCa ßÀ§F)ЦÞÝR—Úk…¶p;K.dzAæ=Câ2{iÐ!œ5†~2“ÙÖ¼gì\f¯:œój›2zæ‡Züÿ&ÒVõ@Û¸Œ¬ëŒúïvˆzñÀ6q©ËA.lù`nÑ”FÒÕþ[ Dõ!£“Úù÷ßåÂ<õ³ï¹0Þö!–½­Ë…ù·ÝraiûD°Ãëð¤Kù™Ž>{nÏû, n‡Ö¿­àîÐQð·æäȲ#ôÏBU·³¼¼Kp[Nã¤$[p—Ÿ†-'3•Y5ÔGûÛ7¼‘®Uè…+‹ì°ÍýdLíŸ{#tÛFYgRÏuÔ¢7«¨ë²óˆ©ÎçžÇ»³Îw’>ÕúκrÛj}ªM}ªz~Z‚ÄÐû*…ÕŒŽ, Z4{îqó§V/Zrü“¶Ò‚EMO#‡óè%Bxwkxw§QM¡ltRM‰âÛmµY"1§ÝÂÌÁÏïŸßÍïmó«wØ[jsœYqÌæ8}Ó1ÇßbÖ¾ÅÛÌX‘YCîe‰Õ‘ÙxÌêHßtÔquÜgû ¡Ž$ìƒ[öï×Ù ßRÏL¿Ô+zF¿\™ÍѬŽ`u4ÔqŸzæöK¢žåû%µ-׳_n¶ýrVõ¢åÇ/ÿ÷ý½ÑÛƒ^äéÑP¹vY º¥—“R¾”ú¬|±—« vã”/®³}-´s})ì#dlü>B2[·2µá„ÿ'®g¾·œÆYZó}ùicÜþ˜=¸?ÒyÜ5¶YÑ„®Ú¨òìý¢µÄÚù~ÅÙ«¢7p™ž€,Ð-“G»–ÔîºëÚUÑéáÕ}=ЛëéÃeçW_ž{oÜ~¨ö£s?ЋЇ´?²³§øwzRÇ,ªýèØe;eáìÊ!0 ±€Yî 1oé­Ûr|QØÁî*–qD ÃÆÍækûwĶGwD¼÷ÀŽp`›íŠÔªj¾+2™ºë—c£sø>›ï]ؼ<[o˜MÅob6'îØçì8g«ÕžÙÍj?%ض[†$Õõ|ŸÂ÷«×ÕDsô†Ú¿ÚÝQ{6JwU¼ûÀ®òsávVf±4ÛY–“ô‹› l2‹ôæ‡s‘á©OmÝŽËæ„¹˜gs1ÇæbŽÞüp.ê,Û—;Ø—Û¶íˤÓöeߌXÀ`Ÿ ±/ æmó–NÁ`^*F±„;Ù¯e:¥bn û5Ø– g¨š%Ò½hÎýòm¹õ_p×&¿K_úí¨:ì®tF_ÿm‡gæ8<£ï­ÑmËLÚ>›šGƒc<®RlƒÃîy­nGô1P«›ýK¿‰ {hÑüie঳=‰›<†yÉG{ß±ó Q®¤Þ4³éüŠH—€Ë˧^î$¹zæ×âéÕÌï*7¿ŸEöòòÓ¸n+ÎÎ_sÚ;£Â§Vk¯{§ÛñX¤Ý¥ï­ÑM~¿¶c¶Øíë ï¬:ïÑ‹C}Çùú~ánçö¸¾©ÏíðÉ;êc3»É™ôQ±ÏÐÓçž®J{úḧgŲžéýèºO¹žbó–žÎïŠn}´§7ZOo´ž~8î©«/ÝG¿ð©€MÌ>úò£=½Ñzz#xD}ì´œûè>º7:Üí£³ª“e‹í&Ýû,²4à[æÈmŽÇÝÛìi'#Þ‚äìiëÂ…¼7^·Ešyîy&¿´g ið¼ä!Ÿ»f¿¨úlpžÙ#wãêÙ[Hƒî ¡–묖_ –É‹R¯=¿b.{þ)KÊfýûžç^»t»]íÏÙá»Ú’DІq_û¥ñ›g¦s¯ï@êùrÉ>»8¹Àºî¢03õ{,3Ãn›o8¼«™Ïp6N³¼õû+yíΆ¾.–›¾†\{ç¼;+©{kÿ×ý»Œý˼ÿ'Ìêç=ÜÒÀ¬Þr7ïò[Zº!åwîkÃpö),2-½²d6•%CÀK™!EÛ›Óœp¿ž´Hr"Cò¤EÒkp½9-VïÊ õ¬7§½CuåDjåI‹¤!'Â#½9- +'ò$½9-Ϥ+'2šOÚu9h£“|Ý2WýÄXE´`¯Î²¦Uʲ)ÖgY¦G¹èý,ßrAv ¹„†/jÓiu"^ âb£„fe€RW‚FI3€ZûЕ¥ q#,£› ²PÉ­¤B„£wI¬E‚DkSJåàr‚Yìøð3ƒw7Yù oÒÓF AÅËÂXi´L– ¡+ºÁMš´}›NÃÁtî ¡®ƒEÓU÷–p‰º?Yy9›ÁLÕÎ;AÓ!r‚$¦Äøœ‚\r:§€nP´|&|_,>S¢`šÆ  ‹éå…p™¸Ùl .0äÝ×%ͳaa<]ºÉ©M2h™}>U›ÛçÛ7yY^.qY^0þ©ìžÃ ASß7H KUnŒæð"íUv±¶ºs±•ú~±ò¨ïKGs¶I[Hv'1mHÿØ(2$Ý“±Å„î¶HþC5oѬi2¶H–M“ñ\ ꨒçIH|¾&Iêù’iÓ†ºBèN“qwïÓÒ>¾Rû^èJ™T•xÐ66›æ*¦ƒ ¹ ³°m¯bG3!WÑƼãÕHª°i¶Û†ÙŽ5͘z¶3e1ÛîmMï5H–`ÚñXÐ ìÞ2qø"x! áàÂtN`~¼ˆ-’ õ¢Šxò^Táî&µÉcRì¦A …I±Q6/²½cE[¼ÅË}›ÕfÎjÙf5!:—Õ¤~ý§Íö"*Ö6z±øÌšÛK,MÈþ%ôÜôRU¯9z©ŒðJVï¥âì A\«:5Ã/“L æóe_â[Œì—k#j“½œš˜—KþMµ¼ü0ÇïÝX];*ÛCtÛî!ßGó{¹ddUåuÂBêÜõšKMÜ«•Oüj 7©s¯Ñ~Æx°”ä¿^#Ñmœ× Ók{¼–· ¼×J¤G|,d(ô:|Á:¯£¤Ã^ÏçÄózamšeÑAJ7"W†\Û…‰´ÁÞHŽ˜ÝþF½Óæyãçø–dÙÿ!ž„7þCš‰þÈñ“M;»ÕËþØ·Ù(²*{ʪàmVw›¬ ÞÖ&ÏüÞ¤iÓág×»ãéÚ¥¹×L¾YŠªóͺ hÊ~QsªŽÿ¢,]j*~Q¦?…|~QÒBš¸_Ný%Õ¨}òK£â)ø%ä{ªSPÛL9‚L:6¿_*PW> ÙÖLÞ®›„ºñAÉ©’ä–ºñ!:A7>$IBÍè‡ÝíKߨõk{}XÝ”¤ÞšÍéÚr¼wHòPøì#êšÐÂGt«Zø{ƒ]ñIˆiWü2d7ü2J‹ü¨ìch9OvÅG1ó€æGׯÝþèÚÁ«Aͬ•çz×f™ØY¦’M7ãGu%Д|TS¢.Ü©}£9½SxÕú+’þT%¿¢©‚ø˜.5šÙIÐQò1)Õì~Œ-Æì~\HZSóqMŸ¦äãñÓý¸Dׄ>.¬ ©¹kç¸ÛwÅ*kÝÎÐ }ªá’lÒ™„n”r—ú®ŽÞ¥û„:z—Њ:z—î"Êù)‰T)ǧ$'„ôif›=ði¡uô×uõÒùu]y4»¿.  ½·ê>¿[÷5]„îÆ\<½[×"uô7Ôíðßt§Ðèo× íü¦¤ì„~“~ÐáßšÔ>øMP#{à·$ù¨>ýyA­¿%¹Aõë·ÖÇò[ëcƒU?ܵéÙ·D|}‘Ø Í$3«¡^Ø[ôDºÌ[ôäFá­"{Ök/,ò“º2ëŸVôÏ×È5¿×^(R€?©Ñ÷$³Ê²öBöôöB½ÕPrr õ}ì…bdÃÛ ÅDÆn{¡}:Iýˆ©‹ªq(·²jfÅüêʪy‰öV$€W/KIͶíÄèÃGÊ¢Œ0Pîn®_|´úéÌÊØÜ”ÚZœìØ÷ðMq<£ã¥}¿²mEC{í²‰‰ªØLMîxÆ8³ÇÍj.\Ϩxo²Š».'Ôãh5_[í²šæ¥4¢mÚ¼12W7µ3¶•äòBf#¯4ì;zr^M]bÖôª„WÈm«ªÀ€Ï‹{)\äÈÉAOÞó“„Ó|pqÎ$5ü½uZ¹`\NœUàúFt•îœ çû}>Žè̯€xG>åJ'FÞ—¼15ç;ƒãõäX¿#ÿÆTóskSœD/ib”¨g ÇãŽäûôÊY½îáð.!½þŽü]¹y9ŽsÔnÙÝ·)-G©ÓZpG.Qźz|Ê‚Y³¢âÆÅ– bó#âb÷üÈïOÇü@ "ŸÈ6ù”+Û8ýžcù8ä³£D+z _‡;,Ècb»óMimiLì¤:Îd¤=„@N‰0tåÔ‘ÓfÏr‚ó˜)ávõÅÌH´ËS-tz.Ý3²hãŒ@v ŸTî;ò)W6#›FZ>èOôOtãÝùLÿºç Š ý=¯+§ÙÆÉiŠ~ˆÒÓݿž›. ÎÏÈ'ZPG>åÊzq2&Änú'Zïî|ýKg ªý ±+§éßÔ·ße¹5¥ºt÷ï8ß¿t‡pË!ŸhOù”+ëEêÊÒ;ýÓaiw¾Žþ]…ÐÔ!ýñ¯+§›¿àŽŒ~è$ÔÝ¿ã}ÿÒÙ€¸F>Ѽ:ò)WÖ‹ª;2ú§+Ûî|ýKsÒú'*WWNÓ¿~¯ì NÈÀ¢uvbÒ¶%˜p’h:6¢6&W85'd¸‚”[X›·ÍçÝ”jsŽSçmw$jêÛ“­À ‹dìiS B·'Ã"Zë(‘wµ·‡~A2,*ë¹*–_ùvËDŽshîܾìütöG×Þœ}éiZ·Cïõ.ž`™íÜoØÎk÷Ë;™“Ïx “9Ÿáÿ‡³¯_’ÔRÂàÌ*ÜHʤͻ_j‡@ÙÎöl¿)ú¸Ï»}UöM“Ñsˆ7[ì‚5ÏŒ†[ ­§Í áNz×Ï¢ÝÉÑbñ NýY´w÷3Ó.Æê.æú­q¯È͈ãÁôÝŽg¤sŽ ê˜në³×˽W½Ž¦MuÌéÉ9¨ëò¯(á.b\Óír|“cëËþ®pàM;â îê¶žô·qžüM6I19ð>Qýíøzi¿9{lF:&Ëü¶“£eGŽyä|Ž5¹”çòÐÇòœMžaäYAžäYFžQäYJžÑäYBž1äYDž¶GòÌ'Ïýy2IÍçFõ¿=6¼=¸ÿm&ÅüÜhDÿÛ£ÃÛ‰ýoH¿Õÿ[³²'ò¿}mVöt¾§ÏŒ²‹ÃNosR ùS‰$ö­ÙåÊíúŸçÉ¥—m_ÃÛÐszÞf²¯Ïe—ÖÞ¦ò¯z;µÿíŠðvfÿÛLÎõ¹ì¹ÚÛTRQoçõ¿Í¤VŸËìÖÞ¦s ·‹ú߆Ù\²}Þ—nŸ÷eÛç}Åöy?»ÿm*¨·çô¿ 3ºjëžxnT×ÿV{¾Pí$ì£ïfðÐ9ÝïÌnY·_öçªrv/™„C¼+sÁ%º_vìt®¶eeÏD®ê/Ø!KúòÜ…<«¯á¸ks×eða’؆ãÚôþÂn› ¾Ê0­/ÝÑ?ÿi÷>Ã?ï­äɑ៮çYŽ ûtå8ßrd¸§+Ç3-G†yºrl´ÞéÊq‰åȰNWŽË,G†sºr<×rd§+Çg-G†ovçˆ÷¶ÎéʱÊrdx§+ÇM–#Ã=9„cæ#…¶ÕíÛ·={啟vï3|ÒñÞJ$šNéʱÊrdx¥+Çˑᖮë,G†_ºrl°ŽéʱÉrdx¦+Çˑᚮ—[Ž ßtäÈç>Ã9Î}†wœû ÷<8÷þéÊñeË‘á Ý9’‘–#ÃC9¶­ÊÙ»$ºû½]‹£’µûåì þèþ˜@î;]n{ƒÙ“Ûåj‘Œß*”¸›ä8‰·' FñG8iÎiQî)§¿«°„+[NzoÀIïÅ<'Xû½}ylíiáñ˜~IÚ³ Þ@¬­›ÛÓNú¦zå¤3¹ª‘,î^;We_Í»»‰7o&þâŸ%ÞB¼•øçˆßCœ;×hâ_"þeâmÄÇÿ ñ{‰O >™ø×‰“øTâ3‰‹ú©•* ·IåÛgóínS¸Ñ«Þ¶Õdî þ޶íÜÌÍ”jÑ^u#mÎ~‹uójGz¤fC‡<ü9&¿Šï|¯áIáu&¼ÁäÒ7™Ü㓾|]Möä’ÕÙ{†ùÅ»Ïr˃Ìâçx,ï'‡÷’Ž÷æýÔKöËJð~>ïïæý*ÞOäýÞÍû¶ð¾÷7ñ~<ïoæýÞ·†÷­¼ÿ2ïGðþ+¼oçý€ð~³7™÷ƒ™ñ©¼?‚÷ á½vAÒÍûfÞ_ß`“5ôôêÒ6^Æÿ[ø/ïf’c×r¥w Ž›æœõÜ4ãìñUÏÌå¾Ðïz“Z¼dý§–Ôd£öÛJÎÍì%çõ±:®gþoë^ÍŽ{sT—îݹQò«5ÝBOjͬn²;l ò—[‰U¸¿>VãTòzˆ­ýoÙyš‰ä jf7l"¾“¸úbvÃåÄo ~#ñ­Ä·ßEü&â×ßAüfâ·¿–øNâ·¿øõÄo þ^â·»‘ï;ØÓËlÆÖá®wôºÕát%ûâªp÷¹’ýpU¸õ\É>º*Ü“®d?\î=W²®ÊÜx–DO¹^ksz+s:ùÏszl<'?ÌÌi|ufÇÄW[/5›ñuŠo²y{¬®ë»WcKº뜹¦&ëkì iؘ¿}ùÜg+¯òTóÊãcyÛºk²®ÙÞ÷~™\ ·«Çf_^™5‚¼ŸQŸc÷O%þ9õZñ™ÄÛ‰‰ø—‰KÎ5.%þâ÷Öˆg§žo‰+‰‹=V‰±³à„6Ö=ôÑ6œ@l¾Íõ.æúà?Ïõ|«£5ÌõÎô\+&§Æfÿª_Þe%3~“ß¿ŠÝ²cÆ]•K˜ñëmÆë¹šC®k˜åÙ>ß rMz,ׄµŸó¼)«‘¹»A}ÕÜmbÞ¶—ü||>ñˉo%~³ú«ø6â׿•ømÄ…b°B|)ñÛ‰ +ÈÍå¹Yë‰ßI\XA®z㬫øÞµ}Ž]OÊÈÓ'SlޝeŽÛþ<ÇG[KçwqõÁ»çdŽW…96xH1a£ØcªGk,ݺ&+«Ž\Í`®ùÌé9é9Ý 'vÛ¿â1_‡,JÄ‹vì_ŸKÌìFfñVò ßÇ‹‰ÝÆ›÷¾×L_É,ŽeÏe¶ÕOÅï$~qò Ù~7qa8Íô•YÜ=âëˆ Ãi¦¯ÌâîßDìZ¾¿DýóÂLŽúóL΋{W¤?éLÂCò3éÒ2“ãÃLN39sÇLúµÿâa&Ûúgr쎙ôu43 £w̤ËUМŒpw„+£[ÈÛ¦>*öeÞ' '©—Šë® w¥ç‚“ÔOÅ¿Iü[ÄÛ‰Ïcætˆs‰Ï'¾ˆ¸î±ú°„øRâ-Ä[‰é~ïNýsÂL¶þy&çXï¸7ù{ÃçÂíès™™ŒnÍÌdt[f&£;w̤«1YÏÍâ+™™ŒnéŸÉ‘;fÒ×q97„{v̤ϵT=4·œ+Á˜ª™>*¦™Æ<—¹T/u‹à¤™Ó\ªŸŠs#ÒÌi.cæñÊlf.j.cæñÊlæ<Ù›x3ñâºY%Óm*Aýía&üy&ÛãÞÅkÃL‚™üLî 3i°¦›Ic¡ÃÍäí;fÒ×8™™¼5ÌäÍý39dÇLº:ØwrüÈLú\ˆ‘nEÜEuˆÀ”8&á6 ®Â¹˜2S&Ün&Ÿ0eÂm á6)#0eþI¿‹ø§ˆëΙ,&~7ñÏ_CœûægùÞî¬èÅtø2÷3+«ºá^®Bc¦½—F ôOßíú{euÞAo¨Ž¾æß·#Vés´£ÒŽlcû‡{o¯ÉÙ%ûg¯•Ìüûá†VååßÍQ#¢Ò¢@_­)‡Ì æe V¶ßç¥ KT™«øÔ}°q…˜»–Ÿœqõ+÷±VvIWoïË3Þ‰0zÞrè^¦žSéW2îfc/q¯Ü©íFÈ;7—ü©Üšg1o#…˜wKOÌ»›•@jìóÖlK¼ÓYbÞI-1ï°˜˜w¥MÌ;&ö©ûz&Vð=#æç€ØªËk*x7ëļý byMÅPSÑ»V'–÷©è­²óvˆÝbw†X>Eï–]±’Ÿ?b~æˆy{ ÄüÌÛbù|”Ö‡˜wšLì›™X9ô²ìçCs_>'¼Ëë(‡žUÂìVF„˜·%A,Ÿ‰JØ•KC,ïMCbÞí2±%!–÷¾Á»é%–×Ôp]ˆå³Õèí„ËwC£wAN,ŸÝFo}Š˜ß—Äòj »¡É»ò%æíËg´ÉÛ!æ÷±býv±|Wõó¹Eénö¯ÒìsHO¨Ù÷O"ÜÍ~&dç¥ÙÏ«býýlós@Ì÷Œ˜¯‰˜ßåÄvYÝbÚô÷Öo„!úßf1I>ðî„Åà÷–r ð;¯§çXé¯ ð{—~ßÈ”À@¿S‰ù"¶%Ä¼Ý b~¯óûOýx•Õ*6Î@¿cTë@?êGK®åVK‹ï™ö_K‰½s§Åï0åniϸéoñ{wÞ]µ´SZüž ŽÏfœïò{KïùšÔ§A~¶¤2ÈãÕ4Èï3õiÐõ–Cš(ƒ=>PŽÁ{Û;iŸ ˜oðL{'“Á~nxw¹½“ŽÉ`o»Šw7e\Þ s0ÄÏ®ú4d™åFÉŸÔƒ!~O¨OC|Ò%âçŒ:¾dï¤?Ò걂޵zü*‘V?÷¼óøRu·Þe9¤-2Ô[RÝC 3uõó*=‘¡¡ßC}¿¥2ÔcPÞy·Í: õv‡xçw›ê¶ÖrHd˜ß+ª{˜Ÿ{Õ=Ì»ç–ÈpoWKu .‡{ÜÆ;¿¿¥é1ÜÏïü ©îëKËc„Ÿ?Õ=br¦î‹3îÂGøÝ©:Fø]"Ž·„w_θ égHïFzWÓÒÝn#¿–q>ÒïxÞyÜ£{À¨ÍÚ2ïÖ6FuÁƒóÖ6œóc£Ó—܃ÑéRÆ ¿°4Ù^=¾Ü7®”Áÿ•(z &eu­¼ûïè§–K“È-™¶½¹ÛÚKRK;ÚNkÂÁ‡EY¦ëñšXF¾»ø…N×£×rÒ\DÆç·›‹òºÛöÉv¼ã^[~Xà iÇ'³¯‡;ÒÈÛ­ Oƒ.®c{WT@Î/?g´ÓÇØ?ûÊ}Œköɾ‰\Å®Å{nÐ’2›Ï!9Q×âïè}Æ›”ª[~ú‘úcê¿fáiÃ'R¢šTï—«?y¬þì}®}€-ݹɷ{6þÕÖÒ5ш¢Á±®éÒJ•ÖXÌï^þÆnñ;’»—ǵܷò{Oj7˜¿m#¿¤¶ƒˆÍ·ú° áq ·±slÿ!aßiíäŽ`GH{'µv‚‡^ 6µ‚üº·‚Þœv·†œÖE3»²n„wÞi3óRÏÁ»¾sœZ£ÿTÏam ØhJÕsðÎç^ÔsðÎç@ûªžÃº(ÿ‘sl4ºê9xçs ùUÏÁ;Ÿ-±zÞùè“ÕsX‡é6šgõÖéùÜn£ÍVÏÁ;ŸÍ·zÞùèÈÕsðÎç@›®žƒw>zwõÖz_ ½eÊî¼ó9Ð,¬çàÏb=ï|ôë9xçs ÙXÏÁ;Ÿ=ÈzÞùhMÖsXGò6Ç#ŽÁm@T=‡u߃ËñGܶ[û7`¾nû7ÍÒRÅàÍ^—ãÃdT݉-ŒkŒ–ïxöÑ’–‘˜mž0%‡p O˜„Cè vRAY5¡o|MPp€Oê¼CÉ• Z{(7ƒ}8Ó êŸŠ+0/›øVÞ‰ä+pߘHß ”˜‹¦@þÉ ýjŒ“野š¸"S5¼"õÆT¹È†Á£"}8ì|Kçç0®TE.c‡Q{S¸ž™“)ó)ÒÇ)XÅ@yv 1”€§ñ%æãp@KÔz8FrJÌÅá(¡–˜Ã© ý}ÊM¡„}Œ©Xw,¡ÈF€W^j£|æy=,Ó™ ô2ý‰ºk™™…qŠ2õÌÂFH™…q:veæùæ°L=GPc™^2d…™94X¡¦#²¬0»Gb´¢B_D‘·Â|¶³]p®ÞÎÌVèC;Ê{ ÌÅlB(z6W‹ cÌÁ6P÷¬m40«sÅÈPþ¹ÔÝ@þ¹p«˜¯¹¨p62ó@é8[ŸGŸ™ÓyÌQ#ý; …ÞFæé(Œa4² Ž¢¾FöÍQ¨›“Ïš&æñh ù4±a›èÝ1(36ÑÛùè37±·æ3OM¨;.­4¡N»›BýØS‹¸©õ½-¦þ~Ô¿EÍ~\…Ž#o?æè8*ûQÇñì‰fì`œÄÐ5Óß“´m5÷'ѧfú´”ýÖLŸ—¢2ÜÌ<Âög.NáŽØŸºNƒB9OåNÖŸºNe>û3CËP¯îϾ[ÆÎéOÞœœú£b¼¥áä_ÁÌ  O+èùê8ƒ=8€ù<k!˜÷3jøV?Î@årú„g2³˜—³@&˜ó³˜Ëôÿ,”30wg±· ²x6s=üOÝdÞžB/òÿ)à‚ÌÏS˜‘¨!>•¹ˆÑ“§²+Ò‹§bd ûèiô{ ûíi\`²7ŸÆ>H]OcN2gO£—ùÿ4Õ¡~žÃ~ÃÄë9Ì{ ý{:¶uZ¨ÿéØÑi¡Ï o-Ôý e[¨ûÌk u¯d_¶ÐÇUìüú¸Š]Ù.XÅ~m¡Þsa©´°GÎE¡¾…ZÏ¥ÖAÌ×yxVÄÞ:Ïꃘ³Õ@¨AÌÅjfxó¶š}=ˆþ­fo b.VžoÕ³†z±×Ö‚Ä3wk©m0ûe-½LÎÇÒ`úvHk0}»€%4Ÿ^ gžžÏÿáÔy{n}¾‚9Án»‚AŸ¯$ßæçJpÉæçJ¸¢#˜±+Q ÁžÙFŽä߆5¾ê·éú~WÝ쎫ÁÏ#èÝÕØ àps5wô‘Ô¹Åð‘ÌÓvó] ûd$}¾}Ñ‘äÇNÑHæúìõ‘ÔñBpÇ¡"¨?Š>¿ð±Êû ?ãléKðÓÎø \tÊE¹© Éj=¶+oÄÜ[ýØÜÄŠ‹ªæˆÊÂôMÕĸ(½È¢Ü«°\e-¹Ðµg¦ßrƒÂi¿µäÂÅ‘åì­6Xnì%úÌܶAnå…Ff ƒ=™ŒsÙ¨&2Ò•ÄF5ëžÉí!ÁÈì!q·½àžÆå?ë¨öŒ‹2úÏa*?éò2‘ÏMG5õÑËÒQÍ|Ôå£8­NNGéÅ騶l´*ÅËÿ6¢¿¦(œ¢Õé(Wª«ÓQ&o{:ÊR¹&å®ú‚t”ëñ ÓQnäBUÖ(M"&–l”ÛÔ‹ÓQXØ’²Q&–k’¾®sQ&VÍE1"ùòt”ùÅæ•r‡¢ãfòM3Öl”iÆÖ”5:Šá5WW~/ÒfÔÆ}‘v†zò"Mµ2¿he<å/bã²YvÈë„È]È´Ñ_,B0/־Д½XÀ„<^,3@B1/‘};!—€l°*ôRî†HÚ¾”º˜Øk©ü×J?YûÚ}ÝáF˜Ámenǯåé.ÊEúuD?ì¢Ü°_Ÿî%™Ò™3›0¼íÛÃ#ÍE;fl¸3Ö<ò3‡5ü5Ïì\.kŽõ±ac‹é <ò×^·u8vÇ);¦Üe}°¢žfýââõ=Å.Xæéÿã–3q³Z³sÀÛÙÛWÁÞzlÉù+霼ñ½åGo³ºï´<­‹tæñ3ãg€™ñ3ÀÌø¾·¸Z>úXÍŸHÏ)ÈêdM®ËóTM‹=CSáb+5.v®ºëb穃.¶ZHgû}˜ ›çf3*¾XJô}åra 1YK€¾¯Øïâ»àTuÌîE>åöÍ'Ý—¸†!–í7¬Às³/È'NÛ{0©‰%C<˜Y*ŽÄÔŽÌþƧ,ã[‹;Åçñ)ËøSù”eüi|Êêüt>•pŸ²:Ré8Ügñ)«ó'ó©*NáSUœÊ§ªXƧª8OUq:Ÿªb9ŸªbŸªâÂÒq£©bŸªâ">UÅF>UÅÅ|ªŠM|ªŠgñ©*.áSUlæSUláSU¼“=ªâZ>UÅËøT/çSUX>rm?K&ø_Á§ªx%Ÿªâ:>UÅõ|ªŠw1Q:!O@q&5ý/‹$­­o¬YÚÖ[ËeQ΋°–¿¾¶ºzÔhòüŽfg€eóŒÊiµÉ({nQæ2x\l+JÛ0è°›´™ò‹ãŠêÚ[kšÛ±¾/×ú“5­ýièRñ×E5µµIÜò÷¦Mø²(+¿!+á#RQîeEì¨ó:–Þ×§Â ÌSWÿ}*¢ôá’¶df²BžÍS§sÎç¾aekÍŠ0}5[ö£j=~d¥æCÛÑ”®¡–ZË”ÆS,[!+[ù_­óW§ñ8boÁîSñåíL•¯>Êûö†–ÁÈ¿4å±ô×$;£ì;ÚiÍB™Ý(·*sV}Tðån”®5/›Z¢œ§â"*¸Ø • ]?ÊêèUd†H¢Ü£j«“uQÎÈÖêQVM FΫi£ŸnlÀºC”ûV÷½²­¶G-QÖÒ¥Qη몗àÛúÜåظ”M2»LI›³8µ:ÕAµ¥Q4FI}Ÿ 7¸øÅõõØ‹«5Jâ¨àiúœAþÂÙ±é*[@ùËt›²Êÿ@À¼ÿùÆ:ÞýB[ª£•R>Ñ¥›å7º€¶ú‡—¦RuQ^NcM]]k”ý²dk+cǬ(÷™­¸1å7aobqEe”u(HjñŒYeGÏÇ’!l¬üYÅUDùïV`9k8¶÷–æ…×»gGù_sɸM…¶( >¥0{;M…[|ü"Ùú ªO£åëipðÒ™,Æÿåú ñŸOnˆïªÛÿІ…QJÕöÅ‹çªàlFr³èu›E_C©Yô(4‹þQïF+ü†"Óh|hc“3¿•9ÝŠÞ§õ\­½²ROBý•“õ"ô ²Z/B*/w{>¼hÒ‹ÐÊL½=)iž nÉwU¾Ø¬GäÚ”EŠù„ -ø>ÅþXû„|Brë7¹¹­-Ê™Ÿlk‰rD¦Íí5µ'ºíTüpùÔ¨àõ×c­_U~óÿhŸ¶¥†r’ya|ZéÚ#fàÿk–;·x;S/¤Ðk×µŒ$a*Hd‰òß4´&Û'&Ž›='E›cÆ'ä¹n³óࢵ¶£,ØmŽÚ—%î1•Tþ›ŠyåU¤n;®düs±S·vbÂM8vY.miÁ!Ë´ñÏÅuËæhÖÈ„‰èˆB ›cqùo¼óÏ…,;ÊÌ\ÈxƧ°Ä½yù©Þ`~ª7"H3¾_4³n*¥yÀð –g-Žö£žùÎzYîê½vÕúŸ–œâr?`fãŠ(¹‘+LäF7®0he„ʯ0[’¹bÀ8Iæ×Áœ^ÿ_xgÖÞg®ŠºÌs±„ù£)ãK@òåãóA||Ç2€À?3æÅwóßktH‘}:méhm®nOU//Ϲ+ôbwàyAˆÒ‹\!ºà…¼ ZyÑ0ö޹‚ÖçÜ &xAÈS?Æ/ª†p:}=Ww™áÇÉ/êÌ »Ì ìŽmV7m–ï¶–ŒHD¥ì.AÇ “²Ï¼¨ûïœðîr‹A£ð‚ļ8!1/<…`–„hä©Éï<Õ”î<­Ø‹¶óû˜ï“jJw¡iÚ…{}ŸÇ— hºýg}ì>ÓÞ„ˆ™@ò/Ý22$ÒÇÎÏ#výñ¬Ìcáìw#týñ¬bþ›ÝùJ„­?žUÊÿEë ²ö®Šã×dÍÄF\eçÒ¬Y!¶Œ|+ø6ÿÏ¡–qä]Çÿ Ä6ñ½…w[ù¿Ø5üßAM«¬¦kC;CìzòÝÀÿù¿‹:Ö®ýjÙ?©Ñ÷ÄÖr€@j}Ôbc>¿Ã,æå}_7Z>hé#ä›kT|ë£ök1Å¿¯êé’Ò1⇞À§8`¯{ôˆš±+ËGâvcuKªeC–G©•²'a^~3ù}âãß=ÿ+{ˆG¶¶¡eßT9ÇU›©‹ õ$Ϫ‹Uµ›yÿNÓʘhWyë…8NÑ "TÁ¾‰rŸÏäŠF{!¦m5Î¥ÿv9|”CZþz‘|Æz'kà?±2˯s•LÛÐþ­Mk×°j!¨Ô>8¬ö–²\+£ü“Øë(ûíl‘$aëhK+eAÒÞž¡# ö Q©_ÿÀJ²µÂ¡ôÒUî÷¾ <·Je {ú l‚ÎÓßkƒXžªÖ‚ÈÝ Œèþ¼g"„ìþÛ1½æÇuãp¸î÷:ouL§ ôÃóê*) \=…’à¸NDE€2ZÞXÁ6âÑÔnÿû×G N¡ œ¥)pr¥.(hÏÐqO5ܥ눆»£áx?ƒÆ/T;‡|´]ù…œ Grö“Fú„ªÜÒ¢ªœSÖPúÖÅÙUÑð‰]ûEE]ÝÙ%DYS£ž›ÐSÿæMó*%Åh¯žVTÛZ+(¸¶š¹ÊèR^_œSâT£jpÚí jDë:ê¨öÔüLOÃã9Úû ßïˆÊŒèc³y-ªFC Š#[ß“saшZ«Ö›Œ÷ä,‹ö‘¯ÄÅ·æçtº¾~´¬¨äô(k°(wò÷³¢‘¹YQYwÏú{Nÿ:Œ±¿o,«:ïkTÞäv€bÅØöv”w²æ9ûöžæmoíiž–ëœÿäIÝœËÉ×}.t&dÕ±•ù•µE”½¬ó’Nuèr‚«H WT¤^¤åÜ ÷’Úþ ‹ÜìѤué5ÄBZ± ú[¦Ogp¦TÓ43JœÌD\kÔ™TgÄF©Çkº¥Ü$¥ŸFàtTn²jS–«Æ·ÒÝ1ÔÅqÞF‹C{^ |㣯]™Â3âÕf(JwmXá• ¬¿Â;–tÔG9W7&›£œ)¼3îDc·6~ÉKÜ!¦xm_%Î-ußG@·†¬«´¤µ¢õzY»,W5HõH¹LíÔj:. šâî4e&@@d7°=Ì€{üvTûtÍ­<“˜x×^®è‹ìÐ1È|îը÷ßÜ7þ;pß”j¸ìyÜ]À½­>µ ¸oñy»ûêö¡¸ëÌU,öP!·¾êà¶èÒÐÇ’WC¶R`søª~í­kWcðÍUû†þ¾u¾#l¯Ø?ê~}YtúÚx¡«rÓÜSD¤Åm]‡±¢Œ-hk®­­Dæ~$ôÞ†Ø6ÎHíK_êª3¢`ü¬ú»ø§âõ .ª[²´ºöü–z-Q-È%(çL•Ä’›[RÞ&ôëhµÌbÌ†ã“Æ©[r8ã(±äì6Å`;–ØãœÆ’»6>"ÄÓë<"|*Ã÷4³æöK,)>vöðˆÏ?·­¡I4÷èË[ Ù·Ó£]N´·èNŒu’`z{VMk³3¼1•h­MÔcm¹­­%YÛP߬+ŠÌDn,±@Ì&kúF|ŸËmmdM3rpÛ¡E~O 5‡äC®öèG?²wð§x‡4ïÇÕNWò…–œòˆÏO«Á¬.nI6'Ü}þ„ „ð²B}^„1,iàŸ_àúÑ•P{Êçƒ6Œ|ïW¾å MèTa(VžC.éhÖD2’kzœØê€;‰¿¹l„#þ׈ÏËÍìòŠ£+æT%P©ZÓHÝRc0j#ð V··6ÖVÛK6¬«!Hö´øe#>?'ÙÙ.ïÐ[Ž<¸±Qæ¡íNÕu·((.™ÐŸ×Nýà§{.µºl"®†¥v5“5]ÝêØËl;ü®íìA Í"X|µÞ(»s³soŠ²Î¤³³™¸W|}ô $ͪƒÓª4¯[ò¨öMœ6¸wÝO²fñY âº.ßèô[ x¾â§Ô¢}vÃ38\IçäLuï^·ñ݈‰gEY“z8‚ý Òrc9šmë¹\ß2IuÛ›†O<ùŒbuפ£â½¿¢8»PùÏúñpqÚ'tµt Ö9sbÛÆ:?KŽe›ú¢ÚÚCMã]M»{zÿéýõ|NóÉÌjF£nf{''óö•ÒÄFÔ\¦ù_ûˬœ×ÿ2+w ‡(yV¹Ô¾•Xq‡IªñþÍ6¨˜Mg]\QbÔ:û3Ùg«‡ÂPUmõürÿüÕ1çlzË|Ó7w´mK×ÿ³ük¦>}Þò6=ŠîŠÒ&;ÂÌ•ø°¹C\Â5¼Jß dTõWMýÒ5^áâ±áÅ–,¹»ÝGòºSc®³™Ó œ©;IU·wc˜K{· ]¯æi¨Í̵jwuÉ¿]±8ÿ(gÔk³ž÷­s¦µÇ£’ެ½KÞ8lrÉÇÐvøía¥%?Ïš9áYæO—µh‚a3×1Ÿ;Á h…ì亱 ±­9uÙúßÉ5ÀôúwvÑý×»Žì~Ó®‰îÝv=¨+¬üÖ¨°ë¿tÛsp׎›§ê]˜°÷{ÁÞ· {¿ SÅÞÆFñšè™EM‚ßÕ4À;®¡²RÀÙaeÄuÑ£]3Âbó:E±d{¥X"Õ΄ÁÁÎ`ŒÁËΰP¬óíT‹Ážži1ÙvˆÌŒP,aj§‘ :#1»;³F±ŽÎä’‰yLOÌiGÄ’¾Ëîšoâ+ÖÙÚ™–!›!"sz,&æÌϘ˜ÓZ1±»­BñíÓ.ö5‰™˜&˜?1ƒa1ìÍÄ÷[¸>ñ½ä¯[üÏÄÌ>Å ¼ÄŒEŰg“ë¥p~bZô#9ÃÞ ç{£_1„Ÿä¢Ì-$¹$Än³ú´Í3Öˆï«ð}b&”LoœÉ±©^oŒ9+˜ÎFÌÝ«àgH÷±‚ikÄà肟uÝÛ f2'æ.W0=˜»_Á÷^÷˜‚éÞÄ Ô‚™}й'ü|ëîX0=œ˜ûdÁLgqþ“!1›[È\†Äl¿µñ f z|áÊŒ9´‚!3uß¿K(ÄKxP¸ÓjÒý¡hƽ˜‰â0{§›BÑߟt#*ÚÎH@E›Ñ„í_\›™¿¢¸J@E›×„Û_ñ’òæ§Q"¢Ìo'.Q¸„^Ò«pS4š¿4 ¾_%"PTïWîŽáïW†µ¶x…ø"¦¾†ø&’ Lå&"ënÓÏìh«YŠ˜ÕAm‰>— Ó¦šöe/"Ä…«­¨¨(aÁéqP7CªIDÀ¯?q5p3q÷’;Æqø ½á‘ùÂ#U,b›5!ÚÕcÓsw3IšÃwš.æ&×jý‡èÑy¿SO|ÿMÜ' D¼ÿ\2ý×½ýÚ³éÙäh/ß3/×¶â“}‹ã sÆ48ÊÎ6DgR,™Ç÷ ͆Ξ©/iÏœ13§(:pwÃÓL-ÓÝ÷é;pß“ÒÄŒcµ\NØö0ÈeUcƱºêÔÈmbGÛÒ†åút6;$®ægë[7³)ÞH"š Bø6¿¹‰#îdSšbÚjk:ÚO[ÛÙÐNj?cÚy1ÄÃs9ãX§w6®ç–´Æ“»•UÍëÆâl<¶q—r8ý–ô<êîkìÝ—{ç•]³ƒw“scCµ[»Ý]ft7ô"tåçŸÚsI‰Ý­Oêé9¿KIí\$;îFŸU[s®ùw-ämS-úƨÔíº­ÈˆI¼*ñwÂç “&à½ESœåºÿ6åÒ÷—¹í¾Iq÷I÷¡ïËU=»Ëà·Ç]Åç=©ç §çìYx6 _“­ç¾›25Ü÷µí5¼·÷^Ÿ¿Ã8ƒÝg†yŸÙgéKXj›:Xh‹oŸÖÌ^pøÖìw#0;Êß°šàoàvGÜÇz(s÷8˜3 •ˆ¶Êö½ì™ø›¾Ùs÷²û=öCOäÆï–sºh¦îof0Dlû˜:¤•½sæéÌ;×'°Yì1¼ðy<+äsâL>Ç70ù¶dzàÍýbÓoÄÆ=H¤—Ó©5u—æÞáCq;ýžfv².q³/˜S¹ª›’ðïÑÝšÎ{]g_`Ãü¬Qìvok[–êh¬s§~KRžœXÒ9ø-‰:™o±:ÐÝI²£2û‚z878Ì®Å>@@Û~Ãô‹,Ú\ÐýtMœ}hè’=«yà¶5mX‡2ÁâEÍwÂe­mpöÛ …Ýw‰pAÀ Û`0ŒþlÖ°®sFv×eå–ä°hŠY¹#™£«&ý4v`{~Vn×åQQï½±~óÃ\-F½,>ÐM5ËsW‹ˆu3Ž)×–´™ì]Ù™[o­S5¤¹u‘Ql^¨±E¤}u¬ófr Tð^þ#z{æëVÎ]Ý`•ѹ¼ß­Éqx„~´ƒu áš þg¦ÝµãMŽ;õvîi˜íÔæv“m’8º-ÊÎÑw|&s·“÷Êw½Ç¦&±ã:ñ¹ò{äÔû¹BúnQÜÌ­°”ÁlÊÛµF»·ê¡°ŽÅs«„çî¿S™âÅ™#K*ã'²nV±Œi‹Ç)Ü/ý-üâo™àwË4û×Ý«¿ý€_ü½Š˜»ñp _+Ã/îÞ–HÇa“D¦·>øLÎ8œÁ8Î8\‚&Œ×²ÃHHl·ÃEá‘ô+ý:Û'á-Ko{±ÝÙ½Â,éÍ5ö7EpÊõ–[»?6Í=ƒkœ9=v|l&îÌ;§ÅgðŽë±©ãŽÌ­+¾2ÓWÝMSžV|]ÈáoâiÅ·„:î 1݈}+Kv7 ¹C%3iS:žTâTy„UÄÕ[T%ß*àЃƫæbQ•îR›É8Q) J„AÐ͹u—¸xÀ³2ù¡(ç’‘›??“H]V`HÐiK*[jmKãJ?SFÜ;KPžUÝOÌOo%ù^÷š’þÖAßíh¾7tÃh‡à¬¥ÑÄájDïMÎå@Dz¿Å o„§ Ø^·ˆIÎ{’æ¹"»ðìÓ²rÖžø1Áÿ3Q¡v2¡Óáfùö;™=Üfû“¹õøA ¿“™Ûöpôwföç"ËÁlú›9ü¼AíÙŸy“&Üñ7„y;¯sºôºSÈÕ€l °›Ó{$Š]R÷+ƒj¿aË:Ì’ãÐì»ÿ¶GÌ 5g·1zóà­:›‡ÑÖwÙñÚÝwõ)í;}ó}GYl};ÝZCߪs·z‘%MÑEÖk4ëÄÌBvvIÝÀ.iç®`öIØo£.ü§·bê–÷bÿÜïö†÷îïì”Ë£aÌŠ1oîyöˆç±ÜíÐôÙïv÷<˜r¼ sƒÌïp“›NÏØÌ™3hÌðtÎÙõa¿03~ÎÐî;ƒ9“Þ!a)qàÏmô„R'ö-(§wm×%–$Ý œšn]m·ýÓ&õŸ¶v,9Š3çU°qË2Ǩqš¦V”¤V)ŸðŽiW›<Ü‚ — àÒnj÷4×)̈qtcÄÉ*cè„wü3æ÷ôÎX{x{O?'n´nbWº;Îdÿ.ß—UîÜcf»qá{íþÜEâ…š–ÝlàœÕoËÜ]ü–˜»‹˜yö<*ôÜýÃÌžçñξ…äïÌp€Ò;3JŽ¢±Ú¹O¾œÁ‡f>=ö ¯ðM>ÚÒË ˜[ÚΜ¬âA¡˜ãä™8eqá†{<9¿;Ð#‚W-铳8ô ­å6aöÍ´j2¢ŠµÖv¡0Ÿ'gÝ‹/»o†Øýc¸›óŸq8Ï~ lІ{žM²Ãs=wŽ9÷Üzíô›]%7ó‰,¾¸™OdòÅsÙ [àtq‚öá«Á`ç C0MÌ—¶è)un¾Nã’½c¤ÍÆÕò z§8œUÅ”³äù™cJsé<ÛWwŸ3Ijúãywì/gpÕôp¼õ#3ý¦¾ßÎÜ£é7>Ðеý”VµJKæ‚l!‰ Ì½Ôæyòº«ÚÞ œòѾރ “‡íë0å51gýѾόv÷}—¹ŒÕÉj £uôžÝà{oz•c>ét˜~côg_¿é›ï7:+p¤{ꑾßRã«5\Ù]Ï1 DÏ5§9Øóè¿ö|dÏϯO7½»çô«ÞsîûzNß|Ï1â3Žž‹ûsêUH®ç(yÉs· {†a0¤I¬`ÂçÔ«6ÏûØëýè ½GµñÑ™§wõþ£ÊÜÙUöŸÞùþcÚèú¯«è²%û¿{ø6Zÿ‘ü¡ÿÚ¿Ë–lžýéÿþƒýdþé]½ÿÈníë?½óýGs¹?ý‹eÙÝH¢^$¾§ÀøkîØ¶×puÒj€#»ìî¾^{œøqxëo‡·þ"xëxë×D•ާöÖÜõØq×íÿ’øÆHÿM:ûßÜ÷ž…;ÚLë;*Ü}ççûn¹”K£'y±p³þ« ÓÿþßoóG ï b¶,^·y5á9 u¤Í¡ï¶–l&pÍÇ­ …h©I(_šÆd1\õÍPç8ÞL¨ëhil¨ÅÍ¡“ -”ù“bÅòç9”?EÅž× k­±Ì.fo_»©F_ß”Äôdc{ Wäƒ^í;»’«ÂÆc7ñåÏÛnÖv×ji–0Ïü×Èów®ªßuÄêWì:ru>³]Þõ “‡Å³ýüK »žšU¸ê¢ÃW­ß_š Íò«X ËHàäßæßzß×dêPºuحû†ýdxWÎÃWcm2 Êp¤R¶ú6û°ž;óûÒÚ÷×5 ½ÃOŠnGÑÜð'ÄÖoGU§—üòMzÈ”¾_»êÕ{®¦ WC}o[ÒÙÕý‚ήõ9+7ô3úZ×Îô¬=k¬ð=[2%ñ³þ…¾½ÄÕ2¾ëï^PØ-íˆQˆ®ýŒï•ôJ.Œ†u=¥4*E¯dçå¼³œ¬ ˆÊ‹@4ì4ÃÖawÒóû[Þ´{I×Kàs¼…<ºÓ„Þ*gû„b bõøÞÓïvŒ ±îÛQ`OøžËœ½ÕÑ-œÛóUò±®‰vKã³÷üâw»ÞÈû¹;Ûñ±•ïùX`f;~¿ÁάrB'S.”:Þ¨x—ö¦!±{{Ùë1$ðp3Í.ö¦ÊÉ-=‹=ÐíäÝøFF6Îís öMcŸ‹ßñ”꺆úúç6%›R­+m¸E‘€šÀÂÅÍ+uî]²[1úHÈ»6EU7Ü`»}4¤…÷ŸR=poú>g}BFóƒN¬Œ;‘ñè•çªcþO|PÓopU'Ö²·ÛozãûÑ;ú- ‡OÛ¯mesí¿õ;æfoû 5‹~‹+ú´ý†è7ØÝozUï7÷õ›Þø~c„o ý–k„söpý–ï÷š½ºÆzMt›DÖòœ=þg¯Ó»ªéµºö™ÕûÌiyŸn‚ÉèúÌ ¸Å2:üô]ëkÚÚŸË™äÙ5­0!žìuz_Ð<›¹–ÚÓwýŸ½Nï¤tb¥u"í7½ª÷›Ñß7×ôÆs²ð¥ ˆÖˆöÇy5Þ¯‰å«N(î:=§S‚±×‚§òxK|D_\ýé¾ù/å´:Õ¼¼zlçÔ†ö’éQ+ Ip+*éçO½0ó‡ ÏéRi?LÂõvä² ôç/1·.èhu3hÈPnþ¤´@Ï›¸¬=ÀüÑ„•j‡dòÓù£WõùÓ½øáù£7¾ßB›æ6#å©g¾¿b.œËÕXŽÊ‰˜ð2×J»Í棬6òÉÊâ3ß_.ª‘ÉÀa/åm"ü®éû*rê‚ÑÄð™ïàE ‹¸#¾? dôÂàlûÙºjÏÂ3àÕ¹÷Íî¨öwr¹^_×\;εå[9m§”íâOp(nÌàh;)Ž: ©.¸0or™Í¨º"ÍcÖ¼^"8Úv73åuxwͱ|Zìžã;‚¹‚oK.¸]îövQ[¸½ac²•°”í.zkecÍÊ%H§[Ö”%´¹<œ„#%k“½µÅçá| ÁµÂ—A²%­»dº¼Êgöò_ôÖÍûÀñxÓ} ^࣠ÎÈEoí½Ÿ¥;ÁñçvÄÚv/|ž½óþ·ž²y/(G¯^›vÂ2·Ü]E·&skÙ‰^ þ›Ø¶oswý0w×7q[Û«6ÛÝ\wóì³MuŸp£©î+P{O†ƒá§l÷=Þê€e;fjàæú; ;æl{';¦žwkbþÎÃì{¾<{ÅŽOd{s›Å˜{ǽ29œW"Þà­–ƒw7“ãNÛOhˆujj4« n?iÎSœõÍö„z²i–Q ü[Œp6òV;lÓ,OÀã…{ó“á¼Wß6Ír@·-¶ÆåÎÇ&ÙnÁ ¸xý¸•lšµ‘/TˆÎÐp:¸*ÚïnŽPr¿Yž²6gØA%§ Kˆ?´Ãð;GñølæÒ¿§åøF úNuÁq—gpÍë¼ÇUù̉¿©1N§ÌÌ€ç×1ƒklqÑÒ‰ŒæŒ›Ag˜ÜÌ&ι«Ëé³Î>tŲd+ŠD]ÈvSkʸ‘ö¦æÇ(ú#Òí|ÖÙÍ©æçž”lM%œƒ6™?kŠªŸjšª wusƒ×ÅùYg8¸î°DqçÁÅ%”#¾‡Í¡û¼¹Áëêr,[¶²sþ†„³@mŽÐÚ6bj%7þVZn|©pÒ¾s¹¦5WRŸ~²˜…¡Œ6ή†´ŸèPS¿pÖõŸ Üò=dsc–úuñýqý¦†ôÖ(ä ŸSÑS™ƒg}?Àè² ç 3ËöS¸áOîÎÉr»M;*¼k=í¼¨¥û¼¨Ëá"-ÞÍ•¯+ô&¥‘"=âÔ“öØ|«a‘óÅû]h|$ãÉñZ½_&ø¯F‡,ä´KôÿÆþøµÔ[ ÞöûêÜíúíâsÏa@FG£¹×7ÿé–.Û×)‡Æ,ÌÙsž'Ë÷Ú&ˆÏ»[ºÙ»_íïáìS3à]àW;½„Dë½Þ{Ýi†˜»™Ó4{Ô™Å7¹ï²wìH¯Â»Ï†š¾’©)Õ¸6j°wÒ%0:èÚÏ>ø„ƒÓXRúwhúŸ}ðäÌþ>:Z» ¹Mi‡D»’CP9$Øæ¶nxGc$<¶ýŒv ÎÄG{öÁ›ùß»úøßì MˆÙSv¿Îgߥ~³´{æÙ¾Ûdûn¾ó´Õµï­aß¹ØÙ% ŒÝùSºö>I೺wèm›×:r;oBˆ3z$.Ö<é“N›mÏÕ»»¹ã_Ïð ”øJüuè®Óy¿€•îDö ç—0ëA»Ây×2ûÈ鉘çoÌ¾×ø!ŸÓ3³ï58yw³ÕÇì;½óÎïGæ=Ü/œvŽÑ ûñ3¶¿¤¯µ{¼søá~ßH÷ÏhJîy0K—ڽż2:åÚ«z«9 Úeœ½•Æ É«[¹Þ"fp€øÄæ­4M^ÝÉõV‚`*éí-¾x«Nè­ÈŒzëëÅ3oÅ7Ð[+°o;”Ö·Ù—ê6õàsJÏð¯Å]Ð;öa®iMÒ7÷a]ŸWQ+“‰m $F ü<”ȱ¿’Þ¥snú*î†êÑ‘@óðL{+F“Ñ$«åüúÁbþšlsŠfzªµ§z.[Zà ùz¤€Íà­nßÏ«X€S‚Õ©¥Í 'QÕ¹­É%Û1áPMä!‰C>}1fúÔDéËõú’­M8û—ÂæéÝT¼ s7Õéyt{6¬ÅÍ'JO](Eg —3ªè7ŠÓSÏ39QÛÈ@-á©1CÓÝm¹±¶ OX<§çU<ª˜Ãêœô­à â±‡ÑÙD¥”Û¡ëhA¦tS^E¿Ï½[ås¯S÷q›nÁ©Ùu½ú…¹fb ·Óm±YR¹=Ç–còö÷Xކ‡sÄ·lÏá´Ñâõ[s8mÕÚ¦úÝ.‡¿ƒ|ks—Sk¼¥ý/ò¿ÿÍüoá+ÿGð4ÿÛø?žÿø?™ÿSù?“ÿóø?Ÿÿíü_Äÿ%ü_Êÿeü_Áÿ³ùÎ}¶¸e{/èCŸ ½ˆ¶Ì ¹¯l; ^©pô'F£?15ä½ÅaÝ\ï]ß7ôê×éÿŽn­Ò8™¥»é*¼2Ó!÷÷îvX÷¾9‹Vݘœ™ñwÏÖéÙí»Ño»qØä•®Þw˜ó‘´QðX›áÙ˜-݉g¥ÍšjdÀçðú›Ü{<Î5¾]0¡¿ ƒíô¨ ô÷{Þy^XÐk¤ðÎk¤€o ïvÙ;0 ¿÷ðÎé-üç<Ú™w_6LÃL§çŒ‡erxNrľ„±as“ÃéJ¥S—ò¤Sgß óI›.Ëw»½ÞóºÜäóºÜ`ºT—[ù<ÍóÄôIÑI-Ÿp^bóaêðÜa4érg¼Q¯­'L&-îì×”ÎfbZåøU“·IçÓëoƒÉ’  XðR#î¸ NÈx5“¥Ü/ôÔÅ·€f÷ Û7i?Ê=»(MñÖ ©;8n¶Þ`œxß+÷øÈ²q?0§Ìª¿ðj2lž¶ƒ;#—ÀëÆA¼—¿´^])_·îþ 1ÀõD'ãÃÒˆv¦ñ86£’[J3/¼:æÝû”ºØÙ@Ïÿ^½ýæ=¿ÃâMb8Ów²Ïè­Ñ‡ÐâŽÖ~W”öö ,ƒ·EËÓ­Íá’]ÜÝÚ»¹Ë¡ º»ôÖÏŒ~rbÿák? îÒýÎòæ§Â{|ì/‡w}fjçɉ©]‹×¼Õ{Kp¸g™êG'TlïκD_úžìïÑô°¥ðvµÁ ¯r¿Á6qt»áŽÇîÓ3¹OË•ä›Ò¡°Ø·nŸ‰[‘r½áýøû4xe|à ù=/2¿§Ùî¾›|)àvD®Éë9Ff'Ýn5ÁGóÚ›x–óÚïho:=öElzïðÁ…KÒܺIÛ݆'‘Î[Ü9á– OÉï6¼‰pûçü%-M6ËzïFçb7ËOü¨'/9hAó‰Í©a±y_»Ùü½…¾Š•:Üò’ƒ6ñ¯p7†^Eß=m0tðÑÉO4žà%n‰ö-bãDþ¾ŽØ0ø+Ûg,·ùbrß)VÅ[‚ÇwVÚæc6Ák¼1c^ã|Xã¦ÀIdVü¬aŒí,!é—îœH¸CVÛ õõtgŠ äsa«óñº^uå w|åô·Aü¤p?Óe9•MFˆ;™8¤7Éγ4éµ7£áœt_º³æùC7£ó`çy§æ9h§{!âפ~Qu1~Qw5OByLo¯]u;ô~ÎÍQo¯/áêëø.ém_óÛn5œ#<àø. ¸%åÄ8\3ÁñÄ.§ìàýÔ¬WD¥E]ŸËé´}1ÞiSƒP½{ÓânaÊK|î ?œÍÿð£G8½Š ôàröË&í—÷Ó÷ê~Á5vr¦QîïüUš¢ÇÌŸ¿‹0¿^[¹“ÝüÖÜüƒæøm}\–À_±;.˜`&ýö;Hóîx¹3Ù­—Ÿ [{‹,© ™‹Z“ò²¦Û¬W³zvYå‘źó~->^¬%$Õaê3~rL}¾VmsK—¾ÆËoìh>±(QÛÞÙžá{á¯Emký½üÆÞ»ÀîZÎã·O£Û|ÿsÞªÁ Ö –p¢¿ƒ=rGX‘ášn^Ù´$…RNÎ!·X ß0NK3‘ç˜ÑáׄåÇŠÌAÎ VÌrxÝHæ`¾Í*~`:ñ‚ »Ye&üÝDs¦Ò è?åxâ~>¸ãÂqÜ¯Çø–“£ƒ·ô]pI¦quK1ÖÓÜþ¡^ãØp1Òy²l¿ÀÐxm”~æÎ ›8þßyR^¨íSÊ Íf-×ÐOùýà·}zôÅï$ôvÁ`º¹¼ùZ£Rœ4ALœ‡T[};¸Ò‚Ú+C`Êèò¡ÏKmÒÆzóµÎíÝîÚ~Ï9&—|v˜Ú¤“µ;W½6xÏøß‘×›¯MkF™LÏ®úë%£4šcÒ){óµó6¤A½ÕÔêur܉«Fú"m‚¼NÛ j¡.ö°àÉK'íÍ×.ìOS/Ôí yöÀ«Ã 6Û¯u˜óÜž«m_làkÔ}ïL†'|pïD®žs¸ ÏYMbÇœ#¼wÅIï-ì–w‹%Sß²KŽ—§Þï87š¸·G¾5#[JäÁEï‰Ï¹–ÿïAgTxs+n „w¹šÅ4žsn4!]ó•ïê­¹“¿6Þá[[sû\Vì®Yø¶ZóõÔŒ×W³Þm26íÝì5ÅZúuž–9%pñ* ±½.«(¼)îAwÎÑ.§ê49ߔɩ]½ƒ]½ÍábÍfu_ hñE˜fó\PfÞã`ô"½V3{Îcbö£ÇÄødñw8ü³ø[;;×s.ÙÕ^s‰{÷ónö÷9ËË0AÀÍÞó9œo[óÎ{fQL÷~[Ÿök4¼Åé´ï´GÅãÌÞyþ9úö¹–€¼7ØwÚ‡ÒzÊÞí4Œ‚³Ý~ð›æ0 ÆËüNÅÌ‘Ò^|û3Ê ƒå‹W+ÿ¢ÔrmÒg6rï6ù°ƒÆ–åÛŸ±0³}mªNtŸí`Œ¥‰»>®Û۟ч״kÝ~/|mµckßÞÿÛIÒCKwY³=Š÷Ö`PÎ{¿Øoô–BOýlæÚ»fWøýÀœø»sp¸çSX±A¬µuâDõ?AæÁφ|¾{0÷½›q½­î¹ÆßÄÀ'æ–c”¹§d˜ôâ¬âIS²ÆNÊ6râw‡ø™aû(Ïœó¢Ê‰ûÊ·E¹ü‡Ï#±Ìb´–okˆcܸà¿JÝÀÝG3 zY;àMä•0 _ß¼Öh~u/¹–ëž°AQø`çËø¯?ÁwÐ0ÍŠÅy'2÷“½×õÍàñmÑmnåûhn0b z;ü$ï!7ZïÐóþ^ï¤ÄÐÃ¥ŠƒOˆkÀ?Š%e§Þ½>öæ,o!áf§¹¬îc7/>?sëáʵ¾¹#CU÷;×¢^÷7÷d ûyNÜÖšîsv3öx°×«!¶3ÄœwS×ç2ï¼ÿcó7fbîˆK=yû0{« ~tb‡»5+noiWyìPÏ´A¤UûK…NF–¶$[æà,?üœðÜŽ+pT1žeÅþ¥B·ã>Òs]šÇ­«•1eÞÖ¾›KÁW~曫nú¦ç}i<[8}æÝûˆy6ûNß6¦}§ï¹ˆçî5bâ]YÅ¿9lä¤ +-å|æÙQî™ì¤ëèñu}®;‰87ä|gá…eë¾WÁIù½á]ûü³Ó6”_ ã£#ð¸ßO_«;¨ÌF·d´ ̈ÔuP»÷€™±ný‚nýçlöŽ s]msÝm"1ÞYD%;×Ìg:×xÍy3s-må{—%kÐaåì§$kÓ‘5éÈyéÈæ–ô›4²¹!ÑEšjë<¸#Q㾞ë¾6»¯‹Ý×&÷µÅ}­w_kâØÅ-úÖRÑ×%îÍeM|5EÓ*Xßð“EºÑ÷.qpÇaE/Åê鉨£Í|ÎäUN³nv6G[”j³·x×ÅÛ“ôöi± ÂÓxÂÁm˜\HyÊÑÒÉ']î®|3Óù¦·|øáAoAšÞ÷.;ø¹£Çµ%&%¢I‰“í=þbðn§•¢÷SGwFó_PfoáË£&ðZo9ê¨Äˆ¯âÌàðs—×44JÏG—½³« k² ÄçnÅOƽËÜŽ{Ö{Þ×Ö{­œDãóŒ˜ó‚î”ß±Vw –r†ãþ~¥ûäaÓáYlg±)ð,6Åx*Y×}rÞîp$¶H7­Í ¯>÷EÃfvƒç9¬´ïÛ¹ÈÏv;ö¶_\KÜ2éäèôn¦`ET Ýþøc;ªžUp7ùR]¾Qœ£ô¼tŽÖïoÈN¨ÉQ<4cÈ76ä@ÛÜä(ì—Î1øËràáÇäHžÎ1èƒrÈùŒÍQ>"£p‡r¤šóò¾²ƒw—3ƒío€oòJ¸r¯Ä£ù+Ë¢™oØñ¹QeU÷çïæýŠªîOéûìªîëûœªîw_Á÷ªªî7+¾¦ªû•úÆóËÞ¿`§7ÀEþ`´¸ûx}ߎ–­Þ'j\}dÔ²úEQ»ú2™Í†'5rµ£ ²íp~Îï/š¯·šòÇFv½;ÖCN5¹”Ï`"m3‡«gv¸*ç¼)ÝâÔ|0ËyQo÷š_ÚÛ> oXŒWÇ„nn¦»Þžåt¦{ó˜ZÅŽ"†‰ˆ90“ ¬ö†Ô±Ì»þO·µÜYÊ]óËA£cê{xïg_VñAN…ÉQ"£;º¹¦­-ÙÄæ]YÛÑÚ*϶²z0{Þc=¸}u¾Žå¦¾´R¯ƵqÎãqxÞÜÀ‚< 9ÎnA>"œ_°‚<¢8NOAž‚œM^zš¾§cÛù‹v÷È›L~Ál}ø«÷>¹àøº[ø+ñ^xç¸Å`®Ôÿï\Mp?Ä-¶9„½Ä-Îr¸»œÄ¸×à-yþ ÜbûN¸* #©ç/bŸËèn±|~ÙܼËo´óPÐêêäoRÜÝA Ôa3¼Î e%Ï ßzžÃ”Çfô¬êéÔ(ÚFèkŽ>r¬‚¼ÑpO•·ï‡r‹ ÌSbÇ÷-ˆ+ÊíE 8—÷䚥 µAI›Û‹Í…¼4ÚB,.×ÂšŽ¥Ë èÕ´·¥:í5R òMWY™o=oyCk{è¸î=á[É{Ä·ž—V-Ëúz¸áUi€Öj¾¬é9Ûmyµ)º¦{VïfK Òµ:2:Š•0wü³Cn4ûÐ2¨åÎ)&ɧ Ï- È-ßßzžÝ¶L –•wAb¬R¦ÜÜÑØŽA>Ÿ£×šsºY¶Dՠͨµ(gî ‰› :÷CÑ~þ–Ó/ÿÐþ=Wz.ÊUàî«À%ð’¯bû^%®™Ó/7šwŽ{'åjýw÷2xÍs™´9c¸kÍV<é™ÃJ'þlØä‰ÿ0lúÄ Ûgâ™ÑÛ†í>é§»&&}u׃&}x×§2gŽÖý5žÎ÷¡|Ï;ntþ(ðÚda,ôÊFmÇ2÷ö·FEÝ\™¶Á¸Š-ìt=š;0ïÇä› |Üáɹâs»—s‡ÏéðÖ=äúåòy¶±µWä»\ŸëÏuÛT&ä¹»ïÍ|ï[ËÅk¨éÿNÞÅîšÞÙ»ËyWæÝänPŠçŒ¶ËQŠ8£í¨µƒÃò|KÈ—oD ¬{Ó)H¸·“y[poÅØïxÛR‚rŒ¯#¿!Ϻ£~£í!]uáì¢4Ö¹½×}˜›Š¯#ð`´ª8Óxc“?£±ø¡ÕMTõÒav˜»9›]èq;ÕáO³§ý­‘îð§Ùÿüà¸1w8nŒÁ.NŸÂ` ïýÞ¡¿S‚i½×=0­÷º‡7>ç]ÇÜ;s-³ªÞ¹×Ô°>¶²X~MoÚÄr-×8èWÅ×*ÏFô@<>e»¹0fÆ‚'ª€1VoA>‹:ùxš¯t0o~îuk2û£=ÊzÆ)6³þc€ÃЩ=2Ôá÷‡S§í]i/ðöÃþ8"Ôб?–V̹gàýGZ1#.RÞêþЭ¨{lKöÐþX‚¨A{WÒíƒk6î åÎßïèÖ]†}ÁŽ\ƒÁ·ú~t_ܘÙväžØÌk}_0õ}ÁLõî 磧 OCûí¿/˜/?£ºÝš}!_ÏCße3ºé?öž‹ðÙ53Ôá÷EÊðéÝ®|±/f„:öŲ™Çß³/ðPG¢V2ô]í‹Ï<¹/ŒïćöÅçîÙºsüó¾°#÷ľ`^ëû‚ù«ï fê±}7£}û‚ùò3*~™ÑùšeíþÕ9M‰ª•-H2¤¿Eæ_í¼DY¼5¬O›­ 8bbµŒøêÁc:iî-~‰ðÿ;Uos´EM>~‰à¿®âÓÍè9Ù·x¢¶)zû%ý\šU}±Ãôª›Hn^UÜé@äMˆú'+G¾½CýxüA‹~’¯ƒÜ[|ü_˜wÄWÃ4ÛüvOɈt¡£=Ö(G'Wº×³pàNûýdt¤n'ÀÜ•æ;Í„WÅÜ-ïÕÒkqË5ßâ„*GC÷Çbþ–ÓkhÖ­YÚ ÜRnOë5|ØÝ†L]WV£×ðºh«ÁyœÜ]:¯‹Nš Ý0jºëâÆcë:†º^]ïòkÏì­ëµ‘¼ï©ë ~óÙíaã…â¼X “ãlç×Řsof/ø{3{Äï[ö¿7³—ü½™=æïÍì;¯ÅÀ÷÷fvhmWïÖÎ2±Ü»jÕ]ðü? ãp‡®i|Ýâ4–j;vÞªs¬!Ç,¦‘Áø>êäæîÈp®ÙyéŽÆëÑ,v¤œÒì®á;¤ùíÚi¨ÉAô!›Áæ¥-sl—â+IeŽZ¢Zª7[qî„ÓÌÒÜnå$`kÞïuÚƒ•Ì“bÆI {y¾ˆòødzåô”Ñß5zÊ¢¬}¨kªñ³_"8Q‡è›-5'ÂôY¿g㑲£çsá½t°«ARÉöæbêã õ¤·ë[_êsÒtnƇúV¨>ã¶‚iÓU|m+쟋uß/׿ O‡Bi£.QÞÝšÁB‘sªWÔ.MØuÒîÀà7øסy .;ïRî)ºû[÷¾N;þ^§k%ÆŸ»m߬™Æ)Xá±xìÐ]{æyL–×Pòšžx½ÿïh¾JË<Õ|eÝ0ºòÙOõ°b9ñDÎ1qûrJËÍæÄÃ}Ù?®sýæ¾4ùÛÞ}È'+€ô½7_Úü¼Ð“ý\¾õôÑÏ.þ¨q”Ëi¤Ô÷ôäõ–_>ä©|«3¹z{‚òé>7î¹{óù~àï‡|ÕoÍÖ|Þ—AAþyÈ7,ž©Þ|Ó}}l:ò U¾ó·æ;`™åƒ–F¾VåËg£kWY̤툷èý^¡|Ƨú›{>j¾Y7 #]VºJz®pWÜ= ƹçFÓ'¡É8·&ªš~.üù¹Yèá|1:aâ§£Ehh­B»kÓÄš¨{bY´vâþѺ‰YÑ%U©‚ËcÏ©qB^'ÄÁùVÚלó>abÚ<è×â“Ç`©’:_‰6.Õåj\º¸Õ¸Tœ«q©=WãÒA¨Æ¥*]K}º—Yˆï‚7YKõº±—ºv5.5æv¶eÇ×9º?.>9ö"žiÄYgãUu§óà­ù¬b=ãH9¾8Ã2·#Ù@3–ÔÒë‘ÃOì;b·øÛ˜Èß ÐcÚb8 :^În³ùÀD^·›wÎÛ©Á>ÞãvîOÁ`œš¿û,“s’„íì;ðŠ×Ö±üDûLâøôæç—ƒ=‚XÑÞ¡á<úú~ GÄæмó71á…TÜòí;Ⴊ–˜ãT²ÿ«¼Hçk…=Ÿúfå]~“®Xs>~ \+½®Xa“·ŒÏÉH‡Ã²æËí{üFÁ¾e6Õ/zë¥ÇοÎSòB-í—¶Úe èÆŠH¾Z4‰ÃFq?IuVð"FÙÕ²¬5µ´µ¦ ¡¡‹[Zd7a øËŽºæòáQ¾{å;žD–*?*““~Y¼ aûѯVÎ=z’ß?ôgöž:KÛvß:˜“šÎ¤}GϽ~0ïüý”ÞæûÁ{¤+ÈgÅCÚ™¦¿~>¸©ÀÝ—ƒ´‰{HßǺjH± 2xßϽ—Â}ÿR¼Œš÷?cïeÉEï¥ dß§õáá‚÷î½´‚ìûtž¥oÞ‹+J}›êê0ï+î½4„:êJ1ïËq}þ}zÀ3ïÅ'¿¯/ÍGt‚ÄDÑ{ƒÕ] ñC]üPƒ)ʱÞ×°Mzóßh $z¿ºmbÛ‘±åˆ5>°ÎÆÞ„Q*òÚx w¬Ü›ͽÃrã?€Üÿ‰{Ô=šÛ÷Ê}.Ÿ˜‹· rß§Üç?š[:´&7>7ÈýmåÖ¬ý¤n‡oiúÊ;µ´šô½‚oéªÄ•|Kß,žÅ·tæã™|Kw0žÎ÷gøžÏ·øcÒˆ#ü»Ç%|ßÃ÷Ì çF?œðéèÖI7G·q[ü:·Åor[üÖ¤š¬hRYVî¤ý³†MÊÊÚyâÍYÃ'~:«pâ¹Y»O\µ÷Äš¬ÄIJ¬ƒ&îÖ`œ5rÂÍYŽ7D§eeâ6_ß ¦<þÙþøgúãw÷Ç?Õ¿«?~güŽþøíýñ[ÖßvnÖ%Ý\|¶}:ë£ø4Œºoκ4í™×æ¹Ñòì²<7Yž›ûó\kyvZžë-Ï ýy¶Zžm–ç˳£?Ï˳Éòl±<—÷ç9Çò¬²Hì ïH9_/6ONܵª:ŸµwšÊ8Ütã[íîXq¸éÊ£·}§û••„›nª£¦›TnºÒQ³ït‹JÂM×{4áΔØ×¼sžQ¸!%á./&öîCIà0%¾ßºýT5Ò¼.n1…pc.œmïtg)„›}Á¼¯qO)®Ua½½Óݤ4| žƒ¥{I!xJ*øùÖ¤æ»àoöº̧‹yw¯½ÃãO®oW¸ËÞéR´}û¢Ÿ{ÝAŠaî‹þ–/tP \Ç¢ŸÝ=ŠanŠ^OI÷ŽbЕ.ú} ;G1샢¿ñë¾Q ºIEó½Ç]£8°EÓçžQ úåEó‰Ì£ø°EÓç~QôÞhxç÷ŠîŰWŠæ73F½ôˆ‹¦Û‡~qÑójyççX<¿bàÒ½VíoÜsË. <åJo8x‘ç¥û¾eQ•ÀŒ–¨âþ-Ь¶Êœsbî¬Õõ’L¶ åŽ1å ÐënÝãùÊóDèyàB;í-Óï Sî|‰ä£“7 Þ§³Æ,øyÂgóô%Xå^xpÛ‹&fôñ£!>í}ßÕÛóRµË  ø;ž0¤+pßwôïΙǰ·T¤Þ~Qo/gx\N´YÄ»GªíO4ŸÛ„fʹ¼&Ç) fÍ ·H)­¡©pß·7æ[ßì.»>ï&isBÏ}fúއ§ éüÜ'—ƒµÜ‡<ïP¹‰2’Wë!öЦ"ÑÑUl1ªâb«/Òz¹ï†5\’lIR·QÄn[Š•Ã‰%(‚¨,,Ü­·:‰£å/`ëií{?3Úé”Úì‰m=×èýÖî‚vj˜ ðiæ{véêžëÐZ4½´=ŠvÁí§Æw/Μô¬hØk‚séåKP‰šƒÂj¹”^œ­:¥aöF¸ÕÃð?Áa²Ÿò‰¿µAx«˜˜ß9GOÄYœ¾w÷–ÞÌ™Ç F[òªž‹ÞF­¯£Î+ã~­§NúµyC_ —œ’pï/èwâßÑ$Ðì\.@z¿Žü“…;Oó£q–#ÇY~@Ë»t °Rÿîºvé˜poð7î"î¦Ëçƒ×«AÊëÕpñ>ûÐpRæ6â5¼y·Ìô'¸‹ø›.ú«,w‘\;õ Š'v+Å¿Kà4»›¨Éáo¢Ü<òÛgêI‘ž»¬›F•Cìï‹âa{~°y—÷@:«6‡nq¯v«¿©ë.Q½{/<èpç5%k,ŸîUŸaÞg‰Ø‰¯U7y Ër¸{0ÞMï»Qªš‰ïü ü ^7…B¸­¦ÛüéžP½a;¿§Ü á†ZXfïtOÐ;{çõ×5»ó‰bbnv¹«é†m{ ¡;´éþ {sZG17ÓŽsÚbà讜öCwåì×tWt?ÎbÞ†úáoº&ænº|±èFkcÜqó;zñ–Лœ'Q¼=ô&ïeÉ÷R½)…^–ŒçL?Jv71§ãB?J¶ M,ïYÉîÖ&¶%³KJ¦yoê»û 7õ2Z”¹u–@ÏEvA îÈwÿK k÷!”"þQ|\ó’¹áS)C¬!ÄšC¬%ÄZClDˆ±¶bBlrˆM ±™!ÖbóBl~ˆ- ±%!¶4Ä–…˜tñÌ̇ò™+¢0TÜ4G=ÿ‹œGv¿‘Vg‘¹óqí˾ff¿;ùÌ^ŒtÔ~0shPì~£rÐ8Jã¡g}ÃÌÚ$çdf.–·S]2Ìi6˜ÿ¼ñïü›ð¿óÏïß™Ü}ÈÌ]sÞW‹©¼¡Ïe<;¸™1·ü"ùŒ.ÀoDY f¥uR·´À=๬%lH6/m_&U€K“2¡Ÿé7¥bv ¹ïÞ”;3À¦'Žò09! XÑF2WÔ7•ö9WDõ4º+ïTM»µøÄ<›œïüômp7V)_¸+9Î&®kTI¬íìØóÚŠªuùSÎæf¹bÝçôw¨ùé7oùÛ)xƒ4ïVÔ¦csª»\x›²þèä`¯êñV:€í(–tzŽânÿ}ŽÓ§2·572»okf6ó[<2g^œ®/êNå´}Ì<M¶÷Ú>ÀQ['·I3æ÷™9Ç)ІäÓQÖÂ4Qü;)¢›w¿æÞ­N¿C“wŸrïÖ¤ßáVŠwŸtïÎK¿ÃWï>áÞmnñïpuÀ»_ó¥ï8dðî®8Ÿü’Ùwbw˜wëN߉éaÞIá]ïÖ«³«`ÐÂÙú÷Îh°ÇLN|ÞÀ½ºSoWgÞᣆwÕ;ùUóïðNû_Ö»5™wø¦áÝGâ^¥ïðGû;ôîüÌ;|ÐðîÃz—÷_$ôP:ê‡Ì½»â}Fº°÷ážVýó÷u­©æTG[uFû‘{€Éqû@ŽL¿±(/$Èñ×'±¶ GÓI-ð»$ðœÞ¯çvàT=·s"‰§1S”ò¼ÏÍB–b¥XT–ßfò°ÿ&‘ç½Êã°Bgº¶¦¨eç%£Æ' CÍ çÉç—4'ïûxȯÅ9ÊVî¹ÕZX#­Ï‹Xøp¿òÖ ‰Wâ2ê•&µÇ"òzRoޝRîÝz•¹V¥<Ú¿èÝœ¤ÑÜù›z=Š¢s)OÃö|ýîÉW¸n{¾æÁ|7oÏ×0ßåÛó Ì·d{¾ƒùFlÏ×rO¾äÖíù æ{ïö|ƒóíP¾nÏ©ä2˜ïìíõµæ›°=ßÐ{òÅwnÏ7l0ß]Ûó ÌwÃö|#ó­Ûžoä`¾öMùŒŽàsÖ&# N˵˜õå3& ì.`þ/9—’çS[æùºS²Jø?ÿóù¿ˆÿøî¹qKÔ·Û/“ò˜™èÎ9•œ-â®é»ïÆ+«r£¯Ãã§÷ŒíÞŒ¯ÇsårOøêÆêv<ªW[¸Ã·_ƹqü{£;"æ|_Ó‹5±"L@Ý¡l°~Í#l–c“å÷ûÛ9·ÃäØe9¸ø{9œŽ´Éá|¯š{@·_XrÈç¸Í¡Û€tÓ^GÚäp¾ä¹Hó/ËáôLçå™›AªíGÇM19vZݼ¿X“ÃñTLÇ×ç–{}r8nÉq¯Õ¡›Bb¾BÉ!mŒ4‡¼ÙøòÚÝäp|u“ÃñŸ¸5$^›Îó¨É±ÍràÈó<Èá¸A&Ç­–Ï@^+‚Ž'drÜc9ðäõÈñÍLŽÂpË¡ÛDªu¡ž?Äm"åñÎñº¸G¤| Þ9Mn…0gâÙwº;Âlyí î Ò™H߉dßi7zNOЊà^PÕ„XjïtDöÎù¢(rϬxQFŸ˜[@z3kÙðŸßƒlä~-Éæ:ý[RJSニ·mÓg—I–ÏßLðCŽ_èÍq¼cãۃͧn4?ß›+Óùm2òLt߇”ÃÝ6NëHâþ!n×@âU'sÛY³×½^R»0+õ£uÖM=΃¨Ã2а7>i­ÞB3ÌÓ‰uó™º3ãíYjm‡_43‹Á_ªÇø¶ñ»‰™ìö­`æ°æ}ݾcö‚^¾ç¢Ç´ónˆ™Ãœó&ÏQv§à)§óîúÞŒOU3‡~oàE4i£¯ý¹iQnèÌÌ:¾uxÿn÷ÞjQ†÷xÜáýϺ÷V‹2¼Ÿaïƽ·Z”á=^ox/ÿ6ÔgtÃ{üÝðþ]î½Õ¢ ïñKÃ{Ýí©o÷{|©ðþqþÝõíÙ‰òé¡÷©¥Iásà‡„ÞîrX-ÊP¾H&òþmzïµ(7¤EMĨq2‡:2ùñOB~¹~Yûs¯Gùãüx'!¿Ü»¯ý¹×¤üq~yl2ùßÏÈ¿åÇÛ ùZù½6åwò{âüƒÿÍÊïõ)\?>C&“_jkžÑ¨üN.?~D¨ÿMÊÿ£ìéÅ‹ˆônï{‡ë_Ð$a*<©•‘å”,“ó ÊYÕª|0'žHØCr 9·zŠ&{¯Þ¿>~oôÃ{üuðþuñ{£§¨÷éⳃ÷¯ß=Åð¼—Æïdx/_uæýkâ÷F2¼Ç£ï_ÏÙîúðÁûWÅï^cè^$x}üÞèU†÷ø–àýuñûÝýÁãï_¿÷ýIó㇂÷¯p{¼k¾ðNÁ{©Tð~÷|᳂÷?¿÷ó•¾Ç“ï_¿÷ýOßãß‚÷/‹ßïî?>$àX\ëvFM¯ÒçÀËZ?/u3(Ü®öûþãýA^¾îCcyíÏ=Â…ØÔ‘HbY"9keÙÝHÇdžŠòÿ7äÅÊ}ê1^禇ï-÷á$­iñÜ}µÈ=Y(s}s l,ù¨^[Ó”®CÞX£ Ôñ¢P–χ'±%¶KŸz±~°úeo òåÚy9äùª'x­vö·:/"ÎÛ%>ždN aÕ•Q‘»'ËèW;êg5_§MîÖOÎv4s vé~F%Ü+䇫iÝöü†ëГžå_µ=¿¹u÷äŸoùÍÝûüîÖß“Qœ¿ñ¦íù÷õ‰å¨ÿ÷÷©å¨ÿ÷÷™å¨ÿ ÷÷Eœ¿a{ÿîïÿÙ–ÿ¡þ7Üßÿs,ÿCýoèëû§ÑLýbVÉ´RC-·¢«oiÒÊ[ ôTAåÐ÷j”—³Ê]Ûj¬|í±7Y[¬ÆË­Æ­V£å}C%óå×ÃkT‘£ä½˜’ÃsüÄç(/ÔäpÚÖ&‡çõ‰³QòškäðýS޲éÊÁÑ(ûú”£æ£lšÚp2ÊÆG59ü\’ÃéhÃË(ÒäðsI§y 7£b¼MrT ULÃ~FÅ÷€~OÃ÷Cë½úQ ý¨ø~ˆ§Q ý¨„~T|?ÄÕhýhýhðý_£!ô£!ô£Á÷Cœ†Ð†Ðßñ6B?B?|?ÄÝh ýh ýhôý£1ô£1ô£Ñ÷CŽÆÐÆÐFßñ8C?C?}?Äåh ýh ýhòýŸ£)ô£)ô£É÷C…¦Ð¦Ð&ÏM§£ÉôM·#‹x¶j2_4p;š‚Þ_Ó­Æ›o£)ønm2mAxMA®Ÿç5ЇÑ/øèêgž,‹òéÔÁ)ìW¥ §P|‹”§‚dö¸òt÷ȵEÛ ÊmeÓ§Ï;Tz»_ÍqO³z€›h¨¼@õ ú‹®«{+g†Ó"÷‘לû¨ã”#"oP1Ú‘“ÑÓ¾ÆùïúàÍ=xœ°šÁòý{óÚÕx¢x3þ&>}ô·¾Ö®>7ºèTò]}stÉ©äk‡xsÅg²;O¹)Û{¨ö^ ª˜^ºæ4Š‹î{!Ø\.q¤ ÛŽ.l~wŒ&›÷«[OÙ:atj[ºa»· ÄÛœ—6òãûX*’¾åÅm‡yPÀçïl\‚l¾fÀçïù_394³Æ?›Ü@º¼â¬5…§|,«°ùüî¨ù»ÝøaÛ5¼«vÿá]uü_-o×÷ÝÕ«ú>f³z£Pÿ.Wê?¯êû·SÓˆ=áôÿÍ>ñÚ¡hÞx-Jtq¼v(7¯ж÷VŠ’÷VŠÿï­m+§`öŸ×óÇã¼ÛõFÁyø5¾LýÞÇGpð/ï4ñ,-‚àQèkíÝŽÐàeÞîqüuzú¬Œ±»=Ž_.ÏùÂSœ¯«£¬W}–mêw.žŠäEï¾Õz׆ù$}H£ër·—Mn´TÉ­ò^üÙ¶Ž%>7>­È}¥Ï}Ø=¹ñfEî+”㢎FŸVä~¾Ï=ñžÜø®"÷VåXÓ°ÜçÆ_¹ŸçsÞ›ÛâMKÌ= <ðâÏörÆ®;·çö´þŽvBî3VÚ¼6{ ¦b󱂼ÏfvgÕWÔ=¶/¡_vîË ÖrûÒdt»G¨Éìžçr.\v0¶Ý;!%w¿ÿî•z—ù=,‚¬ÌNºÜ½Ó&:¸oŸ™‚j&dz}Ž­÷äÐäG;“ã2—ãŠL÷^hÐhe]êÞÛÐ\ƒTƒÔð”B¨ì˜×ÞbûO׿„Í6~èµìi迹.fïí”·ï}ø×èL;o#òdÈNjÐ÷ÔF$8 }šûo/aZÂŽ¢¦ ¼G¡Å½Õ yo_潜`ÌE‰„¶FNã} ÷üv´ö&›ÞÝizî»SXZ±ÉähåÝ Ów>ñ"ñĶò×°©|ßËûMÄ®$ö%bwžrÝe…î/ÅÇváT牘èû³§|c}¥°uÏû÷žrÝß\ëöðïo8åºO\ë<Þ=ðþòU»]ZâðöïÏ^µÛ':…»{Þ·¯Úmý»ó^îCò·£ï/´ ¨Ï¤ð÷µ}öÎÃÊœ›¢ýWž§¬¿"£îfß`)ÃhgžrÓn-±ë†yt©æÔèÚ«æ¶Þ|sîpúâ·\’ybÔªâT‚äO;óûmñÈÚÎ]{äh¡Óã•ÙŽ£`ö©ã(˜ýëoáàSø0x$`™É†/Øõ¹WaûŽ]ïu‹€ îæ]\í°ÿ^’‰åÚ1qÀA±Ý³M,×÷^Š©OZÒxß,ôÀko¯ ”ûfT}³x>‡´ƒ½oô ½f‰­ 5åžRÄQ°¸IŽÕvûŽSdq‡›´eSü"•K£…°%Ê:s}Zcï‚j|J8ÝN+שÓÝÀ£,§”0.ßæ 9qÚh%Ú Ç·Õ6bkbmðeWÔ©c0y/QÞ :Î1{àÖ(¶¿¼˜ü²LÅ_ÖuøN¯jÕÜŠOÒhÊå:”ð|¸7g‹›³57öêØáç ä™Ú}.z 7EOçý¼ªœÓ§T­;5öðþ¿õW±þ§÷×Ó»õj®Ïø~¼ltZ”+»1cùÍÈcõâ«3·-3SùþOǾcfò׳3.G=»ufn:3ÌŸ;] â³¢¬7M±y]ß oÿR¬u¢Á¡vm³®´¨É+„›E¸DºÛOE7âÕSîõ†öˆæéøŒnYVrM·Ìô§æÍöXN|v÷X½H{Lo|åà'JÐãMÈÞ­²oHÕ „Ôi3õýZäÊAo¥3zÃâMšH;Ð4n:@Úsø*ŸúݲuÕž…g äéÞ7ë®zí¬ÏEÏÞXíægö*‹ÌË€Ç?ô·¶ìŒÉíž‘kàǾßB‘œ§á‘õõÿ¬;øÎºè þOôOÝ’ñ)¹&…ÔE®KȞΞVï_GYçxßµ«[k3öSdxä™qù°3C¾Ê'O,S{å9ΛfÊÁi>9~0„‹”Ïèr4qS²=•“ íßhnnìónÛ–F;xk^1wñêþoWÌp¿ø—ÏÄR¿Rì¹   Öwa3#UïrÙMÛϸ…q-6ÐÕ?ÅÌKÍ¿Œ}Ç\äwæT š;vçN°{ÀîfÆÏÖ› á]fC”õÎÒÁìlé„¿ïih=¿é„›ìu«{nó˜Œ;³2…î“'ÑãíóÛìÐÌz«»ß8O¯‡÷0U[¼zNا4‚» ¾ù7ÑíÔZ9ã@_(%Çò™·_Ò©X˜›úë=t2k‡ùª«Ìîy¹ÕÝ í¼0~^ð 'Ÿ¥÷ˆ$ù£Æ?w*HwÅüù‰–Kz“Äw7Ég*×ÒéU¾üêƒ×ÔplGÛÊâÙs-ŽÜ×…< kG״éø„yA+šg½û–*Ï 4i\_/žõ†ñþüPÇ Ò‡¹¤£¥½?þõ¨ymoo.©i‰Ó´ì2Þòh/˜9X£<3Fgz¸ oL.<éÑïÕ¹l¿Ómw›ÿyôóܧ³Ÿ>~ó¨I.W²ÚÓ~ÚÚÙxË›Ož•Ê“¯‚ÿö[¼\¢¦vi¾›=“¼‰ÑgéÅ›³!yc¦¤5obÌ¡ôèMŒù•N½‰1ëÒ¯71ë#ÜÆØ)Ò»71öŽtðMŒ}U´YÀ_?zü õxr¢¬V~×ÖyO¥EùÜCíéñû…)–ê%X¹ ªXág?{ä8G9w&k;Ú“Ï›—¬êô{ŽåÀ·9žr6·¹qe˜a¼é±³žªc‘ŸÍÑzóW”ÿØlt|×å#êsöLæøÄæç@ƒÃœ73ð–÷V 6ªz(É{ TMŒ¸ŠÙ;çl#ÝdŽÂÆ´‘ãà7Uz &w7 Òc°1á‘Øk@Ëùô”³·XL¾>c¯MLŽÛû»,†¿¸O…Ž#fÞyÍb90’¿š,‡×_æÝ7-&v­¼Ö¤9Ä·Hß%^×X[Ðë@þ„ócò9.*¸Ék4›ÎZ_jÒ‡°1a¥T¯™ž_.\$NFðu“ñ6‚¯yL57Õ$nBzEH@X ¸)áFm¾‰wþ÷ïÖÄž0ÀVÞ‡‰9o&æ¼q˜˜óÆab·‰9o&æ¼q˜˜óÆab·‰9o&æ¼q˜˜ów]Ô­“‹ò9ñÝmÍöËâH¼¯Á'?%ÊúðªÌAgQ­®Ða©mDl?ëP,˜¥¹ñ‡&Ï­÷ÍVnç½ë„éUóžSr8¾Ø¬iï¶öTú$í<è{žúA-¡|¤q¿Xêú°¨ê…±Ý®§uÇz˧´³Èq’r<%Õ‘@/QEÉËÂzt›/k¨ë€/XI†‚qB/c:§´!7*ûf';òý­©Ž–M¯ç(ƒâð²üÝÄp¡f€²~~•ó¤÷àÓÑh)î\[“µf->wâ1q'þS^ Þl¿9kíieø‘<7’þ½ÕrÖüø+§ew® üø¹\Ÿ…{¾UÝz÷¤_ƒŸFåt’+tíu ÿ¦ê8ë-»—à-ø›©žná¥-Ý2·.þ»Bxó‹àÍç:=Q©ño,ÞÒeMÜSƒÑÖ·\ùEpåz}uŸã½OÂÖßµ¹Ï [Õ}wK#¶\¶î} |õÞµŠÿâ­‹çx¹õ+èíËÅË}€¹©b9ˆÒÏ<š;²¦p7nöÞ«U¯ÃþÊ÷½÷èk8æÞ¯{*x+÷Z9÷ô~qñ–ýª¢-F¨.Q©›+ÂÉÔ·ße;Tž¥Ø¡3¹Ûý¢ãúôi°C¿¾c‡Â}õ;ôÞÿ±CM }ZìP áîÊÜ?¶CÙOíPvÑ¿ïPí•=;OXûv¨öGº›ð»‡g¾EQÖeûÏJIïd÷ yqÜîY»ð»'ç³À˜ïß?Ã[ºoý€_R7âÅ[¸GSûgO2Üu˜é ŠþÕ¼ÚÀ7_'F=Jg€žùÀ÷ä…ôï"sô6Üõ›Ûý–.ÍûÿnÈ~oiëõãßÕozUï7žúöõ›žùþá±OÚYøyùÀâµÒ¤€ÿ_P¥mĶeñFœ§he*þMâß"Þ@¼y_73Ú¥¨Ià7v4U;~\6[è“ )p,µþÞ´yÅ#KùpøôƒO³@ïñ½ìè#[j–BÔÐ]Þë÷à¢<ûq——k:›gáô#kkj± \‹¶”I§èò¡£øŸï”…GjžŸ-†ƒ¬Kë\qÁ2—S&9\N¼áUñhŸsÁì#€4;60Ù&ašNôä(Ÿï¬Ê#ãúäzK²æéR. úä›—îÉâ#™µ­ µ±(µÉ—zW.Êsý˜ëó-®:2ÙÙžl;Ý(!Õú/.ê›ãó­˜d»(T›A”ÉÍ›t>š2ä›®ïä#9÷¶%ÑJ1LÚŽ|_%4–|í>ßÉ•G6¥°œ(¤°:ež¯]=Ö–—L3‡G¦ç{ñ‘64ÑÒtMÆ•åæW¾(®(·³#â1] am¢¾¦£±½‹§Ûd\±åþºí›Yqîû漇?<3Ý-ê;¬'9€æ;%ëÿßBßF:÷YU½¹Íìër ¸¹¾øÆxH{Çæÿ{ëÍô¸73zƒ§!<2Oóõ9»üÈåu8¬¤¸d|¢I¡tlîï8ï’⢸þœYá‡mmÝs]rWN~n0E¤\¸´?<³CÙÞÐ/iKMSˆÉp9u0|å)>ç¢ò#ë’K:–jw¶Ëåc2ÚŸœ‡¥{µœÅÀœ'=Içl^˜‹°0ß§Éé¼ ÈÛ)Õ•¦¯öé>«yRz-,?²‰×N‘#̵µ'öî£ù‡zì!¥*33Åõê‚øè”guµ£+àêC3{F9×¶:»—k“L£_œFÞ¾^ƒþGÏ¥† ¾†SÍX4Þ‘sç{k—Æt¥Þ,8®üy3Í›_5wÞ†P’çÑÔpHº†å‹fÏ._4­²j ŽK›q$¿¼böôÄŒJ¦hu²EkÚ/‹KјûÝ,\,~àïÓ7ºï’^,¬»ÓèÓ>uÐiçf9>KêŸC±³nÙ…Cœ ±±!öì{Qˆ}!Äþ,Äþ&Äþ>Ä8úùX%ƒ{“Ærß¾gjº)®I=´ªªy²ZÎ:?ÔxS¨Ýåïª+ïáMß±_±‡Ø‡Cì—âX·kþÒ®hÿ¾{Ãêw}¹¯‘‹¤\‹)»;x]p|M§Ä¾¿o"žS^ïMÄzþÊÞ9O³{ç~üRo"`ìÜÓ¬ô#ì;°tí¶fß™»=glì=ÍòÎyÖ5¸Ûg¾ÁºÁŸ¡×tÏZ·Û;0kîUXÚPöx´Û¾Á¡ÎwÓ‰²ïÀ˜¹þ¢î~öØ1÷²›ò¥„«Ún^‹EX°îK|çýç8ý7ûNNõÃ-ѾN“G gß ‡ÕýꃱªÚ3~î1ºžÏ½täÌ;p’xZA«Æ¾v‰ÃÜË÷Ž}'<ã}ï˜wÛâûœ£Ý7ÏÏdôµÀ,)&¢èñ`¢ƒ£¬Ï4§|tqqq9—°Ú„›ÐNN56Jò¦u{$¼_9è¿é‡ êÛ½“£O´{²éI·nHIþÈ:ïz*5í«ó>fúÊõžëAQÖç²jjeYV=“X΀»Œ¼¯¹;IIžÊàNŒW.ã¡«­ÁAQeÁËM~»)õQNHÁÍ0P·é#ÑXøXÖ=~(¤5‚Ö–®‘ðV‚õL¼Q²Jì­Õ²„{ ¾Äækçz]×y@[:jöHÏÔ¹µæ ¿½ëà©ÌpÔ"y=r8ÆÌH~3÷ÚŒÆc’Ó¨0³áö™ÑW 8ÆéRà!q÷\îÊ蘚9ñs‰$îËFY_\70k FKhÈ §›1<%I_ñHüœ}rÝ€ˆ›¯áiô}üü<±ƒæg´¸Ï]Ü;/ô+›wo6½ó<f!ÇžW’÷µÎYPÿÒY Ÿ~|…@ _ÁlGε/I‰žü8½5Ç´,/¾ØfñVÎZïþáÆ}uª»üWöæ~Ä£‹[Ž„3Îhy)?_xi“†È‘Ü/îþaï|͆Ÿ=·H³ÙªnÎ _Es6Õûš äêî’jA;¬Ç'fpM´wzg]¼ae™µæÐqjÍܸ]eæÄá03^;”ùt^+æ¶ó‰¸‡4TÌ<ø9ÃÞ…ÇFY_}ÝÀœ1ÍYú}|ÔÜœá'V²40~óu;æÌh[õA0g)¯ùÒZ:WµŸÌ³ñج9;gM3Î3ág XpÁ êÉ·M”Ï&yÔ©^…õmÒm\ydqZk¨$Y´Êö¿'ßi‰5æoyCG§þÜrIš”Ü/eM¥3ïyõõ/^®c0Pw‰Í®”nd,*Á‡Þgf;ŽÙ‚ž[ÓÚ¥š_üÃÍEWl.¬hãEúRÛ嵉½'߹߆K¿Kyà½kH÷äÙ†ƒª øIÝû^5H7-^Kr©Q#ºVež9 ÞJˆ¯î¹½/¾Kˆ¿¥ç.Wßöac»ÏVÒûvçyr‰ÿÒѯæÀcË<Ži.ª»Ç òø hŸ´æÔE5ƒ›Çíô&¾2ûÀù‹éŒðh¸·e¾^÷ÝìçgÕä«y~Êòù› {Àé š|¹Ž`ÊM#ŸÓD5;Îݨ äÓmÉî8ü÷uÞZVÈÛq£t÷hª nÛúûn<Áz MD'Î3žr‰I4øp”j1j{Üú̾2ýCp6z|ŸuXãƒx÷Üžy•¾=ž(dÍŒ1G|Ðí&¡T}j¾›¿í|ê§œTsåm7š¸ Ò•x8>†7c£BÓ¯þÔiˆ¹lGÅ};n¶3Z[÷¼¤ÔéR8ßl[÷¸¨7>ºëÙ.ìÚ‹}’½Á \4‘ ÜØ€sPIpXhé\˜¡'‘ë`7Ðh›"`¤v®¡†;ùSès¢¡:fƒD\ί%ê9“ÒØÖöˆ‰£ø:ÿ7³kÕÿ­{kÏÝ_lõ§Þ“éÏÎý˜‘ £½Çã}ܘÁ¶›RmHI¤Ëo3ÛOœz·‹˜ec`G¸û¤Á[Þû»Ñë]Ïœï4£±›ûƒ÷7UƒÛr/¼UmLçŽÜÕû¤ÓÍ*<¸Ón ^ÕÙ—~§!)Ï cd”½ëûë[SÒ,vš5%žGèí–”¼t™œHCqs®w*nl¬›˜˜o¼, âxʘ‚ðtṘ—/ôâ†)ïâNn"kè½}‹G |œ uo­I"Ÿ‰Ô¡¼mí­Weži,¢pŸÂkØr Q®&ŸlqiDeZ +Ç·jsì•¶ÆØË¸`i²µ»NýÒ™ÞvR‹Õ5Åø6ƒ{{ÐÖ–ªo‡}$§ªcôxš¢×ýæ Ë‹ï°éäÔ׌ŽÒ6Ây_´uº±´¯@<;¶ôÕ¿#H9ÛFhŠMèÐ2üüc`ÈÐámpĤã•U`/áOÒkÆÒüxËÀgÓå7žA B7¤r#‘[ٜ˔Ãàìq=·xý  ‹¼í”œ™^3F»ùl¿£Ñ2ÀéÖmëÙuD÷§vÙýÎ]ÝûízPWnT9Iþºßv½ò+NGÜßf¤•g•âPoLþ1ÑzÛé!0­Ûéîøºùî nýŸ{JÎânXÕ[‘TV}†c³»¦k¢Ja‘­$¨)ŽkU6“ó3“Þ1ì0iô­ˆœ†ÕFüÂö^˜UØ}ã°ÉÝw+]½ï0ç{—Ò¿'ÿüªÅ/£Wÿ½Ûô•æý—ü/ž2l„ÃjY?ÑIº[ót]Y4ÝzþÞÜ8éŠaÓ»…ï:¸ös§ +íKn“´î4äÔ,]x´dµcÚñ¦ð@o4»fn_ø•BÍ7W vvz3o5®A®zQúþæùü)¿¾ªõÌÆÍ·É4nÁ¼MzãúŠ®“ñ”(Ïç÷‡\]2¹¬^“zs¹ ôfräšF`_Vq( yùËüX‰ëk«cZ·…¡^ûÍ:‡CͽÃkÃkò˜-;£û͌߬çîß…{ ×5&·ómb[-&}ÏY2Ïy1˜Îù¡6.h8]f“Û陘ó霠+äµÀtUþ¿g “UýøsÉ“nöÎñ—ÀPÞ"ïRß)ø¶öž4ÄöfÍ'Ì$g;ò$(O)©–txV‰ï·0R¦MÌù°f†äÑÞð”×q(4j'¹;žô¢ò—8‡·IÍý[¤®-ŽËî¥;7ÝKÍneÛž9Ùm=Sšî*Äùµ¼}a]tÈÂSò¦Tu_ù×]'evç «ìŠ±fXaXUWô³Îµì;“SµÍy)¢ª¦UUyä^•œØuÞHï@Ëô‹Á¼|¯Xç0ÅRŸsÅÊ÷žÞ|™g áa!ò®ZâêÖþÎ{Õâú©7Ä«ûùûhk4¢È‰¯o-dŒÐX; Û˜Ã9£¡2üKoô¹æiI~ýܾ2±»â™-oºã, ·IÍ©Ççeç™ñþžß|<Ê>`j,: ‘ðóýí¥¬]Ïû_Ô{|¶ÙcAúž±Áû÷è½y*ÆVÈAq,ãv—…Ä·úöGÓ¹²ŸÍ7CeKmŬ©Ò¶yÁ3Èû ¿ÏÛV©#Úõ7ï¿ÿþé[FY¸buüü½u¤¿j1Nþ#½Y˜‚ì¾ÃßAÂ…qÞzÕct¿Øs}zßi\ëÞ¶í—Ùu/:ï"7:ú¦œÅiü*¬+ñ$üóû…¿}éÂÈóUT:üê0¨çBÝÞµâšJaÛ­{€_­¶^ qÏ5›'à úž<âÙÎwñx§á‹§þ÷ßætó¶>{De×/³Ý]Ì-¹}ðvVíVÃøîOQÕ­ù#Tg«»±æ^ôÃ{£ÌnÏßûÞ*~ÎéKÞÎç;?Çþ¾¶y\Ê'D·)Oó¤ ŽÁ¿îÞZwŵ¶=û¶¨¿ÖL?P3^Ýå0åð&ÒêvùšŽ¦–êví G(³{Û쇫Í>s÷]³Ý}×ìÒÏ̾cG;„ñUï¸8f7{üÉ;çWÄìwÇ5ï¼gzÅRGÄœ6µ‰9&æýþûŒa àC§îÛ‘0-¦`¦{–›¡ô ¾ý!,ÔÞ½,ÙØؼ,µ"Ö{’+Œ Î#[ãFÀåæ^8Ü·¦s`IðUèC$U÷JµX¥ÝDó{nY¸\ònÕ±»Þ6”)$†årq—‘ëg}Í“/íh@ÁõY#µ#}XÛÒÀ'ÿÒ—œ+žoïB¾¥¡êB–ŒL´Xl1Jkd&O¦ÆŸQz½&Ù˜lOºo}LNtR—´UhÕ} •Ã5o”‚½"`hÂ6`<ºˆÍêu+Ê€ôñ×óÌÁ …x©þÉ’æôÂÅÍéÈùõ4 y Õ¦Îl^R3ÖìêT+mÙÔX³rIMm¦xÀ”Ž×·ß§Ræaˆb¬¦çÏ™j2 .€þañÝIÃäNvW÷ó›—òõ™©çéyG÷Ò–{_Lñ ¾ýÿ>Ÿq,Ôðöf½eb3BY>0åäÛïvoS~eYþ.Åûö…z'.ÀanÔ³ÄJYë$ŽÝBqõ eF=oU^Lɸzðk)ý˜oŸŸ®5õÍível\Ú»—ðg)þηÏS>³Y¢åÒ‹ä-ZBôó§ýÛ¼ŸøªÔuðÛ纷à û¿”ôe—{—Õ‰'Ê#y÷&ëËÓáèéôǶEb+éÍ«ã¼Ñ{‡¿JæöU.gÔh:Úeùª<Šw×û¹ø¢ }Û­ó:'ÛiçR¯’ey±¤w×ÅXà‘öéNéKû öÖ¿Ã%ýy…{—í|WНùíµÖŸ4Æ–¤Þ„ÁqùðaÉíæ§,ßáÍõ¾¡k;kP#—elc¡ UêÎæšdú_KúñrÕqyfŸãѼø²ß×Wú¦Œþ}Y~.Å#úönZæ{ˆ_Ëå¼}iïYƒÖ·‘éÑYÈ gÚ=Wð¤äÌX òšTiN +Z3îúÊzŒ¥fñ%c\RëëÇÏ¥ôÑ¿ýªPÿ4÷5Ýcb\6 _ÓÙ£DfN)r›2³ƒÏ(ðÆÕÖÌqŠüP™=ô"«ÙŒ¶¯–\’ð1½=?!Bã—¶Jë)ßh%méМl5¡Å¶„š^h5¾¦´sˆ Ù·ë¡ZM^BF™C{yW‚·`ÓtψîÓ·_nµ‰JvAkMSïÐ*Û¦q úV.CÆ•*Ë®8`ß>Ýjð®ÂAuþt±m0uw­°böÔ¨šÖë ÇÒÎlŠ-?ýÔµÒvàv«ë|¼vf¡6öH%¬NQÒÞúö©Vê²éDzuÝ\ Þœ¡š¢3L7ª\cw™«,?š.¿qêJîgî÷}LniôùÜF^M’õé,ÇëJ˵ڡ»¦¦>wl¦ÛÒÜò»ˆÁmø +Ö:I—× ”ä‰ýÎDù|ÛÛ¾xoîÛ]VÏxrËÉ]Ö«—¹µÈ,û’:VrÚ— ¨Cvj¾ý2_ÇnÃëG9 ´% .½"<{`Ã[h1Yž6j|טÑ/R™—¶1WK¬>QËÌnx®ê{ö2Ý¡ÂÒg.!rå]S„2e Ñg°Ìµ: ñŸBÏñ}êôûîú´º†2²F©!‡_ã9¦lоr§ÕøLëÕåªQmáöbÐÛ Ã3êpÚ¼ôȫ·[b¼æOzé{Î?ìЋûêfæ74‚à.»¬tÏ&`ÐÆqhËT`nbÓy/nIlÊ{q‹Ò¦õr%¦Þ‹Òx‰¹Ú×<#±ü¯™¼PÏÈ»!ÕÀ‹»óšg¦`——K3{ãBåõgÌ|>Ðê’VÜ·_’Ùù´Ù…å®_ˆå+.«kòûðí†Pãùî=ž„äUãÛËúj¤>’¹cŸË…'"vÄÊe.¬ÑOβ·x'ZÌÛóÓuØ)ðØ,Ö (cž'i !Öõµ'2™Û¹6G¯RiÆÒc"<qsZëv¡›«ïRÇónÇßkñ+q˜Fa-Cx› ˜ôêb‡žÏïÀI®Å‡¦f<ÃVÇ5Ÿëk†2 ?Éß^âq#%>T²pOR,‰×#nWç*¿½J§ýijŒt¾½Øãj©Um¬qõÙL`èÍ)·iѲUëH‘æA–ÒׂŸ4vËJ7«îêï9èAæÛ/¾§VŸ­V¬aSw”ëj1~ŽTËÓûoèþ=þ‚ñþDSöÙôs³î·vO0ƒé3uvSbÔxgÓÈ>@ULYiÝxb=ÍaM®ô©޲| qxêæ}dÒY]ðô²ó9Ë7!yÔûöñ½øA ‹ÏlE k l!¶¡BgmØøJºÙß@ñQtõœíïþ¢®e{±£b™ÒLƒkåUÛÔQ^6Ëx«\H}g¥q˹uþf˜.&ó(”Ó}ž4ßMhóÙºäëÀìô3­.«ƒÛY˜}õ½Ê&u±Õö2÷g¨6DZðýÄ;xyEzv/áúw¥ë&‘ª‘ýåñhÄ ,œŸý'3à{‡#fàôM3ö“Èæö„¤3ÿícU[ —ä9ð˜ö^æw§½l==³°Ÿž e•RC›Õ°gag÷üCNU]–Æ’ÖŒŽw¹SÒó·%µti#WÌËš¼`­Õލ^Èznž¸Ãžì°“î]Ñx<6Ú·x<’™oÏòýʤ{¾HKŠros›mCižó¸oi-JM_ÑÕ„w!öÅI™{ˆJОu»Þä2\Nd@¸¯žh9Ð{OÉù‡å›ªûnwÔ€¿!°à ¾AG ÙSÛ{]M ®éG“ŸCÈ¿Äç§Ëð¤ž/Fà›ã}n)`tÖ®'ÕÔþžƒi1{†Ï­ Bn?€ ׿/ï¹RMÝ‹}n‘³¶áŤFËÌÌËìÙ½Wjè4{ºÏwü,±ªîÌ<ïoÐr1¹Ñ×çæµÐçÖ=7eÐÝ^sà­Þ—ÐÛ—FÖ·§¦÷Â¥Í'6“Ï!aŒ='!Vª…XÆQÜ¿£÷Vκ"ÚU΋ÓV4wøpíû ¾Ÿ™x¿RÜx¾Ú!ï~» :¤É¨o|ÐÉïÕý·êíc9Œ',©öTëQ½[[®Uê‘·ÁN“Hýð¾Vê=rþ[¤ñ`õŠ'oÊ¡Gë]ÝË`½Î%Ѱؗñòݹ¹nÑï~g}C÷ЧÞúþSÅ¡ê¨\>TÃTÒ¥û*¨¯|ËŸóÝöç|×lÞm½ùVü¹¾ñ›ë»ûÞ=Û'Ç›%ؠ뙉5ÿ¥®ŸäX‚¯Š™Ý¢ó%þã|Æ—rïnþqÆ—zw¾³‡"˜Å‚Û?êMáÏû¯àößó™ý÷£}™üÿ%÷⿇ò]ÿç|kþœÏàžî|†JØÅñ–ù_ôë:çOsüS¾Èù’ïë'I÷£ûÝ÷4³›ÎÉøáã Õém¿Ž©^z^/ß8NÞhUx/I¼s:XF{Âë+òÎy?4:ÎϤyçôß6„÷'É» ö=¯óÎ;çwÖh0x“¼súþh)¤ºözçuíÑPðZø7õZöÜî¼f=Z ©&9VÄZPè(¤Þ)yç{#…ÔCµ:/Lè$¤Zä»ÑòI'A^¡²|ÎC*zÒÙÊò}ÊÞI Aþ ²wÎ:ò•½sž ÐA¨ô÷]‰Bf71 04 ¯UF¾EV‡ô ?£¼ó3*=ù€Êêpþ±Ñ%¨,ŸóR…&A².¼sž Ð$¯ì¬Ž;ìô¯çI>§ç‰¶€t¼²w_±ú¤+ îNúÎëx¡+Pð;€w^[FºÞŸ6u¼†Œ´ ~W‘ÏùÈB à= ðÎi¹¡ Pð;‰w~'I à½%Pß q¾j†Þç¶Éç4ÏÐ(x¯äsÚfðü ^k|Î7<ÿ‚÷ÞL>§ño¿è5N•O~¹í;qö‹Þ òÍ7û¢ßÙäó;[û¢ßäsjáÈÃþ+úý'~|1ì¿¢éÃq/šÇoóÎï?ñÓ‹~xç¼4À9/zí7ÞÝiïÄ/ú}À;çµxÑ{càóÆ·»è÷¢Þ•¼îØ%¯Ç;¿ÅÑ.…ù(™gExØ%¯¹Ì»y67âY—¼bÍAÉ<-À³.y¯\äóó!Þt)`—’iìÁw.y¯\¼ÛiïÄ_öÞÂÍ;¿/Å9.ÜP2]@8Ä%¯G?œVÜá’÷ D>ç«~pÉ{‡ Ÿßâ–Ã|”ý|ˆÿ+ïâi¾²Ÿ±~ÊÞóïœ5œß²÷ö@7ˆ³[öÈ缄ÁÕõ^ÇM>áÄÅ-{üÄ»]öN/ʇw~Ä¥-‡=Zös ®l9ìѲߣâÈÊ'y–ÏÏx¯•°Gå™Ü¾ßµöDÅϸ­•°G+~Š×Z {´bÚÜpR+aVüž‚¯„=Zñ8R׋JÀ‘¿GÅ'•÷ò,ŸÇ‘â‰VŽ”sûN׊Ǒäû²½ß³pdżdÀólð8Rù¼N—8› G*_ƒ¿ˆ«Ùàq$ùœ—K¸– G6ø} ž¥üœgù<އÒ{;7ïü>²!샿Äalû ÁïqÂ>hðû@üÁ†°ü>wP¾Ð³|~ˆè=¢óNÑí;ñûáÑßÄÍ“wô´¾Fó¯1ÜB=nŸ®1àËFÓ΄K×pC£Ç âÈ5z|I¾ëíøqWyßépÜ®’uûN<¶Æ€«=®7­1àªF«Ä9k ¸J|2ûN|2ïSݼó¸A\±¦°/›ü¾¬)àª&¿/Åñj óÑäçCü­&¯eÏ;?âh5yÿ°¼sþaËò´Ù¡ÏÖteÆ‹·Å`¤Gùç]VxÇpø[ÚueyåÔ-çX¼ë<èk©Râ[?vlq}§Ô¶ m7m ׳Mµ Ä/]R];c¹ÕöÖË9ðz«M*Ÿøo:íÒ˾Øë}áªÓ¢½WŸí¾ï u>êcPò¡¨Âgªpùj¼ÈYmRåÞ#TŒƒcÝìì<ȃÞ>/P¦7µy°8üU¢{£;Sóâ‹bgÔ§×S+q/vQâ-0‘×Õ@h5n_n Y65vÀ¹Œn¸á« ÿ–pË5SÍwœ˜\¹$U‹÷vNðz)\y,J‹ÍwôÎIêûÁù\o§«Nsz÷­³{fæE03«ÛðZ¶*¦:àÇöŒÛ+ôÈïøÜû†™‡’Ø3›5¼»8زÞ7'ô×擄GÑ7V+rã¼ýµòѽ§¢‘EØ¥~%Æ®ÄÛ^Y=ZÃîòr±h¨µç#háv¦­ ígÝúrG{ÿDj‹î­mV‘SŒY© ¼cIþ\þh‘®Fü‘ê®·[Îgß‹1æI²Åi:­møáʦR*›ñW§¼ ÊÛI4›Â/öz|Ìê<´¨5Y·|]5È廽Ãç)³'{û'·ÎÇaš½gSŒ”Ðð/ð½Úð“JmÂ"o»¨dqOÏæ¹f6Öã”IÎ}7>8èÚÚŒÿUÕ&_‘·”ß; ‡IùÐlŒGKò5áiRwó…ø¹Û½5M²=! ©?TÕ²iNCqÃpéF£oªo´“]Ïä ~£˜e}GÎsª}Ãì|ÃÎì|öë|Þ oT/¾ MÝÆGíâ&ùçIÄûàX"oþ¨½Ág‘8ø÷sÃ}ó+ì žŒx£û훳7ø7²}ŒÎ-±7x=òoFƽHä_Íö"zíq/yusuëÍÍnvož[ly˜ÿfˆ½W¸7ϹÃÞ0þÍ”7ÊóM"] }Gx•¹h6oȃÖÈ:ú¨ûÍE[nôI„ÑîÇ#݆÷Z/€Q®ËŸÉêA×L|üû¹mœþêQOñúŸHzPœðá ì Þþåë~¼W÷_Sѳ¸/wCëÁßD\ÇáÌÖ[ãºcú±ïÇó`ë‡í ®CþÊÞèÖ„öéýßàÍr«MiÞŸÂÆ»âÞÆZ;®·ÿhoÐ6³{ *x±½A+Í¿Yd}Ô ˜ÞÊOåp{£`”å¯9Ê¿;îE$¯7Ô(ìWþ”½ÁCŽ›Çò{ã'÷¦tjyj'íXü6ôbDƒ K³ÓøFùò Z´œø³íÍ ¨çÄ«hoNpI='^G{s‚“ê9ñvÛ›“_ωoÛÞœ`ÉzN|ÜöædÖsâí¶7'{¶ž¿·½9-~ïʉ·ÛÞœö6Ò•=åÞœövÕ•SûuoNî|9¹Ià ·7§½våÄ“HONç +§ñ+ú@Nç+¤+'þI{ë´þZºr~b{Në;§+ç'·ç´¾€ºr~j{Nëõ¨+'8¨7§ÕáèÊ)<µ7§õ=Õ•ó×·ç´°ºrâ­¡'§ñJXω?ÎÞœÖkaWNüröæ´~»rrwìÍi}eë9xçsà“·žƒw>zÞùðEê9xçss‰Ý9,×Òæ0ú#Ý9xçsÀªçàÏ'©žƒw>ê9,Ææ€ÓRÏÁ;Ÿ®Y=ï|Bõ6frïòÝ9Ì;ŸÎ]=ï|¸|õ–kjsÀ¬çàÏ÷°žƒw>œÆzÞùp%ë9xçsÀÛ¬çàÏ´žÃòamx¦õ¼ó9à¯ÖsðÎç€[ÏÁ;Ÿ¾m=ï|x¼õ¼ó9à×sðÎç€w\ÏÁ;Ÿ>s=ï|£Õƒw>üëzÞùðºë9xçs©î¼ó9ŒîTwË÷·9à·×sðÎç€ß\ÏayÏ6|üzÞùèÔsðÎç@w¡žƒw>ºõ¼ó9У¨çàÏ7ºžÃr¦mô3ê9xçs 3RÏÁ;Ÿý’zÞùè¢ÔsðÎç@o¥žƒw>š9õ¼ó9à^×sXN¶Í.P=ï|ô†ê9xçs ?UÏau©l4•ê9xçs ÕTÏÁ;Ÿ ¨zÞùhKÕsðÎç@³ªžƒw>ZXõ¼ó9ÐØªçàÏvW=ï|ÃÑìÎÁ;ŸݰzÞùè‡ÕsX]1›ͧz«esôpÍ;Ÿ£‡›hÞ9hq+ Ù¼óuôðÍ;Ÿ£‡ShÞù=Gμó9zøpæÏÑÃ3ï|xûõ–ÏosôpËÌ;Ÿ£‡[fÞù=,óÎçèáW™w>Gwʼó9zxQæÏa|½uç°<~›£‡dÞù=Ü óÎçèᵘw>‡ñæ×ƒw>G¯Å¼ó9zx-æÏ¶L=‡Õœ±9z¸/æÏÑÃ}1ï||ÖsðÎç0»sX=›£‡CcÞù=óÎçÀc=ï|<5ÖsðÎçèáâ˜w>GǼó9z¸8æÏ®O=‡Õû±9zø:æÏÑÃ×1ï|üVÖsðÎçèáô˜w>G§Ç¼ó9Ъ簚D6¾4ë9xçsôpƒÌ;Ÿ£‡dÞù=Ü óÎç@¢žÃjEØ=ü!óÎçÀ?h=ï|ŽŽ‘yçsôpŒÌ;Ÿ£‡cdÞù=#óÎçèá™w>GÇȼó9z8FæÏÑÃ12ï|ŽyçsôphÌ;Ÿ£‡CcÞù=œóÎçèᬘw>Ggżó9zxHæÏÑÃk1ï|Ž6çàÏ1nsÞùè0×sðÎçèáИw>G‡Æ¼ó9ð½_ÏÁ;ŸmÎzç‰ßäèáâ˜w>Ú›õV“Óæèᚘw>‡þïÉaõËLŽÂæ¿yçsôÜøÍ;Ÿ£ç~oÞù=÷{óÎçè¹Í›w>GÏmÞ¼ó9Ð «ç°zb6ú€õVÃÓæè¹ß›w>‡Ñ°îÎÁ;ŸÄz«ýisôðÌ;Ÿ]ÇzÞùèEÖsXÍP›£‡O`Þù=\óÎçèá ˜w>žõ¼ó9zøæÏÑÃ'0ï|Ž>yçs ÏVÏÁ;ŸýÙzÞùèÚÖsðÎç@/·žƒw>:¼õ¼ó9Ð÷­çàÏÑÃ0ï|tîê9¬þÍÑÓ0ï|Žž„yçsôð$Ì;Ÿ½çzç«Ùä@ÿ®žÃêâÙ=\ óÎçèáR˜w>G—¼ó9z¸æÏÑÃ¥0ï|Ž.…yçsôp)Ì;Ÿ£‡KaÞù=\ óÎçèáR˜w>G—¼ó9z¸/æÏÖz=‡Õ`·9ÐV¯ç°šë6ZêõVcÝæ@;½žÃjªÛÆs@w«¡nsÝ9¬fºÍa< tçàÏa< tç°:ê6G&™yçsOÝ9xçsàQ£žƒw>G&™yçsôh›™w>þê9xçs á^ÏaµÝmŽ}óÎçèÑ×1ï|Žn‡yçsôèë˜w>Gÿüó9zôuÌ;Ÿ£‡#bÞù=ú:æÏÑÃ#1ï|Ž}óÎçèÑ×1ï|Ž}óÎçèÑ×1ï|Ž}óÎçèÑ×1ï|Ž}óÎçèѪ1ï|ŽóÎçèÑ¡1ï|Žî‹yçsôpVÌ;Ÿ£‡³bÞù=œóÎçèᬘw>Ggżó9z8+æÏÑÃY1ï|ŽΊyçsôpVÌ;Ÿ£‡GbÞù=<óÎçèᑘw>G·Ã¼ó9z¸æÏÑÃí0ï|޾…yçsôð-Ì;Ÿ£‡oaÞù=< óÎçèá.˜w>GwÁ¼ó9z¸ æÏÑ£ÿaÞù=úæÏÑ£ÿaÞù=úæÏÑÃ¥0ï|Ž.…yçsôp)Ì;Ÿ£‡`Þù=šæÏÑ£ÉaÞùrý¿'ï|G¾…yçsôèI˜w>Gž„yçsôèI˜w>Gž„yç{ߣ—`Þù:z4'Ì;Ÿ£Gs¼óµöpDÌ;Ÿ£‡#bÞùZ{´+Ì;Ÿ£‡×bÞùZ{t)Ì;_GGļó9z8æÏÑÃ0ï|üQÔsðÎçèáI˜w>GO¼ó9z¸ æŸnžGÏß¼ó9znüæÏÑsã7ï|Žž¿yçsôÜøÍ;Ÿ£çÆoÞù=÷{óÎçè¹ß›w>GÏýÞ¼ó9zî÷æÏÑs¿7ïüê¹Í›w¾Žž¿yçsà9¦žÃù´29zt¾Í;ßž›ºyçëè¹s›w>Gö¶yçsôho›w>Gö¶yçsôho›w>G¾…yçsôè[˜w>Gv…yçsôhf›w>G¾…yçsôhf›w>G޵yçsôèX›w>Gþ´yçsôh]›w>G¾²yçs_áÝ9¬G»‡zôžÍ;_GN†yçsôh›w>G—¼ó9z8æÏÑÃK0ï|Ž} óÎçèÑ·0ïü|ts ~͹Éf}\óÎ×Ñ£kkÞù=|óÎ×Ú£³kÞù:z¸ 毣G×Ö¼ó9zt;Ì;Ÿ£G“üó9zx æÏÑÃ'0ï|Ž®€yçsôÜøÍ;Ÿ£G›Á¼ó9zî÷柳MóÎ×Ñ£—`Þù=wwóÎçèÑ00ï|Ž]óÎçè¹Í›w>GÿÞ¼ó9zt@Í;Ÿã Í9xçr‹qÝ9Ì;_ÇøÍuðÎçèáÖ›w>GÏ­×¼ó9zîåæÏÑ£=iÞù¾âç¦ÞWëÉìx³ö›yçëèá ›w~uëAŒbõ Më«««óÎ×ÚÃS7ï|ÏzxóæÏÑsç6ï|ŽýEóÎçèáñ›w¾g=7HóÎçèáÖ›w>G·Þ¼óýè¹a›w¾ŽÞ¼yçsôðæÍ;_kÏMݼó9z8æÏÑã‰Á¼ó9z¼>˜w¾g=º€æÏÑÃõ7ï|ŽlÞù=>Ì;ß³¾©yçsôøœ0ï|­=ˆéâq5rÙ8–̓QxÃÕÝÁ¨p?D.p5‡À”Lذ‡00\¡o”w'PlŸ  .˜e‡Â@+ÐßɼÅuÒdÞ¨s2sËv2Ès3å€êv“qžR`ã’\ oSäªV#4…™·Ãé=ê?‡Ëq¬æy¹Y&Óè ®°¦ãˆe¿é¸–*2Ó¹0¹O—{Z]Ô§7Æs>ýµ2“Еh©wM—H]Ø\¢"4>Mä2†}Àˆ²™d•L"åbÕ–I„ÓLö7ÝyuÔ7|rMáô;­ FûÖþfh§)Ç a~Õ1C¼EMÒŒYq®³´{˜am&ÚÉ 3Zý›¡®Ù˜!††fm†1šå™t3âR7S]g‹˜µ™º€jffjgjæfŠ5¯2Kï4ã³”_³=‹]@ÅG01sŠéÐ0 c”}Žàb3÷G€¢ÙeG’#f·©<Ú½G2ç15 3=&v$sÓ‡vz3»³™qvÜlvMLf¿#îøìuýXÝ´½ÖWB½n‹O—H{Èàòˆ‹B¢ J3Ùßl±C4E³ÅüÃuŽ.WêÅ9nQÍs5OÚ)s¥´¦=1W×Jí’¹ºÂkÇÎS…Úsót…R– †úw´£ø1š ÕwŒö´öú102èý1ÌMŒÊÙ|æ3÷óéwLýóQ=‰QÏ[ƒ1[,`Æà‡šý_{$ÆeÈ.ìùca´ÇÌͱ0bDzcús,jи§YH­ìû…ÌD kk!{“}¿Æ&‚Er£¬»èèx¦ÍÕ¼$EÆM‰ò'är35Æã›EÚ)šERœ$?5Û‹ÄJQ?3»àªÅº©Ç‹uUUËíŒpËb±<„Ž“BÕ}Ü?¸ºA_v{é’”Œ‹Ý†y=Nl9Õvœ6£fýxá'í–ãu±VýÇ벯ºÿT\×ñÂf®gÇ ©kƒ¯ ‚z·D PõgÉä8×wùµ¿%r*¢ {‚.QšËÄÖ,ž ªýpÂ[âœ'¼Åm]^Û¾gcüN®ŠªÐ|ž,f‰æãeW7NƒXÝ8¥$®á”W%üí‚›6£èÆïu\SsŠ8.š¸S¤¯ªÊNùe6Z.¸˜\l?MÖ©ã§:Þ³ýªÛ¹rœ*9~År—ô¬Ë´»•cYuœc™»[Øß2M:9è 9þÉrî¦ý¦í §ió«£§_ç8Ýù ²¿åÒ3ÐÔ,ŸK‚ÛLË¥§®m¶B!mÔºi»¯×PùÏ6Ô6:C›U5ž”s†6´&ëL¦¤~¦6·6ß™l¾˜my&H™[ÏYà@ÐÌY Q6øYÜçcê= .û,° û,¶cp¶Ð&ûlôA9gƒDÂSè1<‹§œ÷ö)'HR>QWé: tQÞ¢a7ªmŽGÕÑ< †5¿§HÅUѧh‡h£=MN%UéÓÜ%×þž&ÅFåxšXÊqÎnqŽsÓØþÎÑ D9ÎÑmE9žŽ‹Vr<Ý]EíïéÚKÊñt:KŽó^ç8O»ÙíñóÄJR¯ÎòSÝçý«åøuÎ\cÖ¥;Ÿõ“Û-:²E5~«¥Á¡ŠW Õªâg¾7®æ™ŽcfÏÔÝM³w¡f^³w¡xáÚ9ª+šó µ#µU/TN¡Ÿ ÅyZ0²úØ IÑ~ß ] í€ ïŽkÜðn‡zÈnу.5U׊-Tq­Ð¼úü2õ]U¾L(C³÷2¡ÍöË„¸ÔÅ—QèáåÚªš—릷/—#Y½}ù2w/'Ú+ WàlïuíþlÛk‡›}ynz'ri°Ûž&0Ãtø§ÄéÒ¼ÿ”áПbFÀ?%L ZJÞ TÉO½)îÎO©›>7“¯Ü;Ÿ¿Ýéôtío§Ýzv Ïišw¾Ïrž‡ýý´z¡IúiMŒ:ùÓº4i6ZøYxã§…}µùÞ¢[’¶Û[ÄÿÐV{‹0§0Ä[„?t)½IøJ[÷&6cL=7±õغ7±Ùº7¡ þºIxLu¾\ÃÅô­b0¨ßoÅ'÷•·j‹ëþñ6ñ2TÿÛè{ÌD¿ í1®Èo£/ÜYÞ¾KÜË·ïâð èÑN*{ ”E/\”™Æ~nMt¹‹êŠ•ÏmzÙx»ö—¦æíºhšß.ü"4ûvm?UðvM°r¼]W-uîfºËÄÜ,6¡îÍËãÎܼÜm¯jgìïfÝUÝ;„€„6Þ)N–¶Õ»è3³õ.mm­ŸQnméŸUeš±w • ãÞ*þµ®½·Šõ¡ßÊ.¦S?'‰þ¿GìÍÞ{ôNzâfõ‹l;fêÅrÑLÿ’ÍÐ/í¢9)d4*U& ž´{Љª^ } ûû%í Íý/IŸ\ÓòKºíiÎI{D=x¯ôg´ãß+ߢªýýºmu}@ÚtÚÌ·«&MØíω{rûsTaA\{éâ.FlO„• b ¦{Õþî*Vî¥"6èWu…P¾*„ºðU¦ýª”8´m¾&ˆ¦îkä`»ý­”P„¢¿.ž‡&êï…á„ÙþF.ö¾)ÞºøMíuMÑ7¹+Øÿñb4Áÿ« ¬÷Ošáªâþ…2È?áB u”»²þ‰IF¹æŸÈU`|ëð¸ëß:\¸£ +»ÝRÿ)ب:b®}¶ëêsAסdè[S^ÿÃ"E¹Eº¨aŒóû–xƪâ[ÒõÓný–îÚßßÖdiF¿-©ºúmÝfÕ©û„¸µóï“®º{¿¦Gøã~qԾ¶³7ÔX“%ô‹Q¥½g1MÚGq\~ÝTã,¬˜#±øŠÂ±(,gƒÖtƒ‰ÅWk"ÚÖ-&–†„˜#±¼bŠ-çÀ΃$Îf¸‘o0Æ.¾uÇÐí5Îe+©ßq.›[l©XžÄ–Šótø ßÚ â Æy >yÉŒóÐtÔ-6Îÿ¨›B}›Ý“m@m¡‚xÀ÷„I³QψCEUQѼ¶ñ ÖV·+RÛP·+ºd.RÃNSwt±’§î)lâ›ËÖV¾¿w¡Á1>mmBuÍ|ƒº¦ò­éÓ^‹wÒmDÒ$F¢&¤I·”|³ÿ4ýØ&ÚgñSµ?Å7èí³¸ÙÆ÷ò-^—ÐZ¼³P•zÖÌ.J‹wõ1™ýÙML`vž®añÓ¸·0‰tS}@¨º¡ÄO×íä¾á­¨Î¨u0iÄ_Q½pôÂÄ ,Œ{;°P¨-{.ÅiùfãºÐ%S6}ÖnJ¨K€&d 6¼vÎÀ˜ß’vÏ@a©™4›Ë:Û¢+¸vN‹.šÊ–«âÎ ^éfÕþôÞkïexÕM«,uU?X— U?X³«ê‡è¢ê‡È…–ª"g{ª~ˆ6¦ªo~Rõ­ÇÕ}»úZ«¾ giõ¶Þ¡bB«ÞašoÕ;L<)Õ;L7Õ;L—qÕ;L 6ªw¸¦EõÎQ½ÃgÇõŽøûÁzApõŽ¢Öž)7oªg¤°°j£„'Îæ¾”vÙ(ñ©´'FéJ©6J—í‹ý„®¯çl}ß\uoãD« ½ŸÔ¡ïä›ûöÇhõU{c´…,FkZ¿Å·&QìŒxopcv©o¼×%ÆþÌûk±7Ôïýß÷yÿ·9,ží öã}bŽK¼n=¢¬}GÇÇŒv³€Zƒ½Î˸ÇXž¨öaAÅj,¡x_ítÍÉQ´óÇéÏ盡¹#Ö´æfŒ”Ä„Æj57cn}“o ß\Æ„tÚ¤þ¦}Þ&Å |£ú ÄÓ&¥ ÍO›òj~Ú´í„pÚ4ïwó ÖÐþmÓö»'ÊÚÿи«ãuû t`;§kA!³……ªóñ|xePWÇ =¬á–ݾ¹€±À^nŒÐML]:@ï„ÃT·„ÃRwÆ §kªÇ‹êûe¾éÎ7£¬ƒ¹Ši /Ìtêf‹ N\±ãÃÄÀÑž8T× mžC…´y•–€6ÏÄgƵNtlΉšnÍÍD6….ÌñáÚJBIŰԖ›RMŠÒ–›$|¬-7I×Õ: M:é+Ä#a¶‰ÅQê2äþ“°E&ë²,tv˜ØÚ‡ Ç íM¡^]âç 9©žÃÅ®U¦’_ºŸñ(XŒÒàÅ¢-°M¦³­¤×•H÷;ÃUK^{ã1àféÑÇc¸IIÛ?C¯ àû™Ü!B3AŸEú4“ûd‘¹Éœ©s&÷,ydˆÇÁ·‰xú¨ò¤c[ÉKH<¾w‘­7 ŽC‘=ôÈ!ö¯úxhVìÞx<—Ó"èòHæD>˜ã#ÀÿEúräÜxÖŽŒÙM²Ã#…ZÔ§#…"Ô§#¥;¤>)\§ýr¤·Ð‘ºþh>Úãû³¾A ]¬Ê}¼¸D{Z“=[Õá9BJʹúvŒ¸»šÌctTÿŽ\“9Ÿ‹›xéq©6±6ê±ÞÔ§cÅ’SŸŽÛF}:VZ}Z¨Ë‹6ÜB]Z5± aŸˆ·Og⤺O×]A›n±.•ê×búÍÆ[Ìfç³Þ‚XÚq¹8šÌÅÜÄäÐ4žËG÷·x†XrêÏqÜ9ÄɈ†Ë*%¥øh6 ðxñÙu:ž'.F|4ש„~-ÑžP¿àˆê>Ïä¨û\<$"VC<“yecžÀÍG|÷¸BŽÛÕŸ¹'J¥3~>÷B¹Ža£‰×C¿Ø¤'QG |w=©ÇÇp™—zs| xV|÷øðlþ,©ˆ÷Ϙ÷¥°| ÌÓR®R&g±é¤àÏ‚¥(¥ûx¶øòêÏÉàd9ˆgsW,0'§p!+2§0§l^ØœlÞSØÐr9ÏÕ%7ñ®ÄrÿÏ…­!7ñ\æ‘M|*w ¹U‰çŠG¯y?•þ²—±Þä¸&®^ýZÆ~’ûœ¸RyÔ¯elH9·ŽeÉñR|¬âÚ;§±‡ä*žÇ–³«xžú£>Î&—3¯x\]ÝâyÌu‰>ï_Êãy0Jåü,žÏ^ŽÔâù\oJÌÕrîP%æ|9H¦Äœ/‡5Pb®VÐLjo÷ƒsµ‚ a‰½º‚~—˜÷3Ø%úsWºsFÌÖ·á\Àj¶xWè å‚ çÄ¢_]=cíWåò ³ØF¹²s-~DÝàë==w5ÁóÙe-ÑCäf«œÎÄ*å~SÁD…Y bþ¦×Ü‚˜¯Ù¥—‹’ñjn¢8ÿ²WE;8XOEƒ‚x¯ÙÞKz93çã™–·EµÖFé¨ÇFk7MIQõh7^ V–&ý ábmš3ìÂu¦øBšä3uÒ†>K=ÔF9K:֚سt™f=K·aгĉІ>ëWñŸõ+w)ÌæR=1ÜE…“[&½ÇÁï¸ïË~Ú´+sƒíÔÙ1w(^$å+íÆ³…µ{λR»çlu^»ælM£vÌS¤$¥Ýý)\ig?E\!a‰§èF£Ýý9Ю~ŠnXÂOÕ}W7—§Šk®øT]«µ Ÿ* ¥ºŸ* íè§‚¸n<´,–Fü1c4)OÓõCõ?ë¼Øñ Aí\7ž&&±ê·F0ØÓÄ<fx(¬uް”°Ì9ÒÑn>ŒSÿ9`6È4ç°ëÅiˆO`zêºØÂÚ½O—Þ…úÿtnÌ`«§£ MøE ]àã)¿ê:¼9nŽ_ÄM,õ åWýÏ«J+$~1ü°Ó3”_õ?CÜ a¨g€ö¥¿˜ü`©•Ú¤+a9H+$^LŸ¥Ž/F[ µŠë j® lŒU̇4Bâm]õý\íMÕ}.Ø”+ÅyL=׉ó軜•ÄKÀÌ`¡ó˜/i‡ÄKtEÐFZÍN•󛸌À5b5XXN‚âZæ,´š«–4FâZØEæoMÌyÖ7»£¨«~ªÄ‘ïu3ß2éÍl¾¦}®„š¶5ºyiÚÖˆ£«n¬oJûq6¹ÙZ±5Ô…µâ¸¨ kµuk[«{¶¦a­¼çj¬U~!´µ·ÅÝY{›îì¢G—¹¤8Âöã|]u·:_lMÁùÒfÒœ¯úUïb1©Î Ä?Õ¶»@— Mýb Q] ž¢öôÚŠšöuÚnÚ:ëÄM"\§û»à:ØÜêC¼LÊšúu°_¸Ð®yÀýX/î…ê_ ‡›Þzq=TÿzØ7\Ö‹Ë¡ú×ëF¦úŸ)^½ê&[8¦þgŠ·«úŸ©‹‚ê¦8Pªÿ™lm. ‚(ˆ a4rI¸PJ7ªÿBm%Õ¡¶ ê¿[ïBn†ÜÐ6ˆñ£ú7HñFõo€qÀÖÛvä’° ·µ º(¨þ‹Ä®Wý±ØvÁœÇð¸¼É­m#ý’¶yÜ æR°‘ùáæv1·N)ßÄ).õ\.†›Çàb0£ø+q ·Lyv‰[à€rkÛÄ¥F|–ø¥ì¶Ø³`'±µžÅÄËTüRÝÚ´¥/áR]d;^–-‚£.a®å÷+ncNAì›áÿ–ØŽ[˜'øvD‰-¼…~—˜‡-\ŽAØ—rÙ(±_.åÞYbû^ Z)q±¿„[âqWÔèæ2!zõý2æölø[eêz6L2}67AyƒŒWp)+Óÿgs‘wÒ¸“y”ß׸“ †üÌÆl}ùô;¹`”©óræ±Ìv[½Ìœ=‡Ë”<õÇ+Akò¯Éx¼” |[»Â|<‡‹B…¹{.¯ªx.¬ß }}.—ú {õ¹ÌY…úŸKŸ+Ôÿ\PA…úŸ ¯Pÿó@#ê— õ?Q¡þçqy«Pÿó@]êsZ¡þ­ 4„o¶‚&¨+(­ú·r›m þ­ì‹êß S¢ú·‚æ¨ÿù°Ò¨ÿù %ÙdŽOæžÜ@ýÏçrÕ@ýÏ…6Pÿó¹5Pÿàåê¿tÖ@ýW°7¨ÿ 8Y`ñ)ðç©ÿ Ðg#õ_ÉP4Rÿ•ì‹Fê¿’@#õ_ɰ‘ú¯]5Rÿ•\ЩÿJ._Ô¿ËW#õo·4R?lèFêß“£‘ú·Áèi¤þm\d©wµ&^ þi¢þ«`^4QÿUì¯&꿊ýÕDýW±¿š¨ÿ*.„MÔ5·ã&ê¿ÞDýWƒþš¨ÿj˜MMìÙ«A}MìëÁGMôájæ­‰=»]y…ö¶sAkbŸmçžÐD?¶ƒâš@™Û•W}Ù~hâµnA?öÝ5\†ú®¥öc?_sVŒ›®9Ç©eT¯Å(LÙˉn¥Q®ò6—ªE¡3ÕÅE·ìüÊP”"ŠÕ×Q´¦RÿUZÇx™]#%4MÆ ÄÊÕd¼@WiÝ´^ ‡6ú …Ü„<^(f¿&â…âÖh"^¨Û³6ò‹ÄÖÓ$¼ˆIq½HˆH›øEâji"wèž ä¹CJ›xHˆ[ï± „ v€,ż׈¡+ôbÝ4‘/~g<)/~§|q)w•íŽû‚ª²‹™(7¦Œ“¨h~›Ú­`ûÿ¡Ô¯—Eks¼DúDêÓKT•ÎKÄW2y‰XñB&/Ñ\hs¼D7vÝC^ª¼š—ŠªÍñR]–4/Õ-\›â¥ºi>^³èõmæ2» ÂR€io{šË¢4|RÞ·íÒµâ`k\+,v­t…ß_¦nkš^&.¥¦øeªD8ýeR5Ñ¿LW%ḗkúu{9y`.½Ü~¹8ºÂI?%0£®Ãùf: ¼Æ4þ”.ôÂ;µìUÏN]u4;¥^ ®ïçExïàNðð+ô^{òÂÇÂg¯×R{ñl .ì¯$Ü’Wr‰çôJp´@ã3ÙßpK®'R}½NJpÂÅ׉±ª>\nàâ~¦_SxÝ'âiºîn;ÀæµÓ¤KwÑ)˜¹QÔ\CíÔ&¿#g\ÛIKßš)4Q㌹»N÷RÍÝõÒS^½^ºÒº§\¯9Ôü\/þúö*qñ„ç_¥ Œ¶Æ«¤U¢9z•˜¿Ú¯ž÷ëÕtÏ,Š/™xÅ?{“M¯'0–³){ð>É« tƒXdšå^×và uú(ê’YÓl‹ÏÖQ]¼Aj'êâ Ú]šº×ꮪÝüZé/-½VükuñõÂêâëo‰+{ý-›•e:n›7ÖÇùn|»:‘3»² \7Õ»¥é¤»È´}Õ‰7ˆa¦¹zƒ˜'šÿ7hNµÞ í©N¼AÓ>xÓ¸Â7-tXÞYz{-Š“Þe‹R¯è`Q½I[TU¿I:ŠÚõ»t©Rµ»TµªÜ%þœ¦v—¶§¶é®X—Kß9ÓÇïl.ÅäË»»K.œ4g»´…Þ¥9fz½`ÛÞ¢oÍÛ-bšéúò3l7¶éÏH­@ù~Ô0Ñï†ÁôÝl$x(靈\‹ÞͶ†yõsº2©??Öc+þœx+Ân?¯[ª¶ôÏ‹_¢º~¾+îßÏw ,¥û“jûxŠºà¥ºME¡e¯ƒˆlT׳­l”K*Û&Õ™‰…Rm” A»ÁFA5¸F¨)Æ–+íŸ—Š„°à/Ī<ñG47êç/èê¨+Ð/H¡@ý¼MûI¨ã6ͧæê¶XM&þ˜x¬Â¢ï;NXë=Rú*œ ¿Æ8<¤÷ˆ'¤¹zôò4‡¿ø¢x>~ñE:æde­âµDODŽp2T)Ô[‡3›¶^;qEG×Q3£®ÿ¢”TÔõ_fP×I¬Muý—´¥Ôõ_’Ž©ºþ^m)uý½B”êú{ÅuP×ß+Fˆºþ>±°Õõ÷IEO]ŸX¯êúûð¡@×ßÇÖ§ëïƒED×ß¿oÜõ÷ﻹ닇&èúû…‹µùß/';B~ïwTÝyÿç­5ãºøsïƒE™? T¦ÌÐ>RæØô~àE3[u’ø[†Ï¸nJuËŠ3¦àO5"¨Üßã\dýva:Õ{»nÂ(·‹ ,¬w»q¶o×Dhჺ]ë‚ñA¡aÕŠ™¡9þ 0‹æøCšomû‰Í«Ó‡¤Ÿ!Ç´…?,ŽŠn]Ö„hž?¬¹n±kWsýa±t4×wÀºå¶}·*°üº°¨?‘6œúóݲ5ß‘^úô/7î_–‘úôËbp¨O¿ lÿQ±åÔ§JE}º3ÖÙÒ7óQÐì§»¼ ÙÏ¢ìåt³„»2µÒî þq]Ô±_ÏPøæWØ2Tú+Bƒ.ÇÇtÉ×ÛéÞ¢mõ1Ý™t™ø˜¦@ícÒYü¤qª?ù6a±’”R-æS'b¹ªH‘´­ë“Bêªý“Ú¶ÚŸÖД|Ê䧺¡ª²xlæßPG”ù7„JÔ‘ßkRsô›¯Ž3ÿæ« 5ãq„¥c£º˜”„KÒªòk\jüM]ãTãojW¨Æß¾TŸ™×ø™™CÔøq(„J?£9Uç?£IÐ~ømcåÿ¶T„C~[Y¨ò·51Ú¿cìÑß1Öè!tù;ܤ¹ô}V¬NÕõY›‡ÏÌš<WJ¸ÀðDl´˜õÊëÅ×iÚUÓï©'êÕï W+ý¾î•êÉïkçª EõâÔKa¤?ÐTk·~NÓ«Ýú9é² QN>Œ´c?'Nµ0Ój*tŸúCiBé:÷‡ÂTâü!›ƒúy1DUÿÄíÖ¥à ô¾È¤]£]ú0!_¸"îù¾©‰“Á_4¥X'ÖmÀ’.°ö­j*ì3 €’”VlT÷';þþdg%ÅàÙµ…©23–¢­À™·È'ÙU -|ÃÛ›Œ¼=žu|sÙÙÆ7Øã¦(û™Êwß°Ó¿É7 Í|£ü<“c×Úù|ƒ9–ñ –¼&Ê~Gl°äYÔ§N%»‰/óÙ(ûÙÒÉQÝ#À¤R®Iv‡Ç Ödw6½ÔÈ’=Ũ½=ÊÞK¼Á;ùF¡Fù÷%\™öƒW ?0É^Ì·”j’½Ä W=£Ùóbo%{Ors—ì}š:žkÌ Ó”iÌÇD÷óYù÷×Å o¸ÖKøf.ÖDÙûé’~9­"Ï.¾Qʸ©_*»›oãÅ‹¯sNß?®ÿ€£"Ý`„uî{šßu¹R»î½$úBZåÕ®+ï—ŽjÇ–騶S9³=„;Ëñöp=-ÇÛÃm–rf{hêJêhM2‘ž7Ý?@¼KMáꪦù@ujß($¬à›ËÞ*¾QåÛÊATµƒoPÔÍ|îz/ß(yiÊÒÕÖ8H[ZÓz8‚E¾Å2Óu99X¬«ñ|£ü¤º–΋ê>X÷/m‘ƒµE6aJA}ªVr¨íN¾¹ƒi«[EzãÉ)h'H™G[c‚4ô4þ>žÂ ï& \;wÚ›eqØÓ½YÎpÑ´aËñžö\Øl{0iôºg—”uqH·¯­ ºƒ©×‡Š«Mw¨fS½>TLSÍÖ¡bÊi¶ÓM›f¢tM¶ðÍ;mÐIºf\Ï7Wõ|’¸öÚ@“„lÔëIâujCNSO³6I !bÛMÖþ׆ž,5omZfk2HF") ¥|ë>ÉlM?S³u˜4JTïaš%ÍÔaRIºƒo6»ê•èç‘°KÄOŽ`§ˆ#žB,1ßG2/%v'ÇsÝÎͲ﵋á¦>Ïfc•˜»Ù죻t6;°DŸÑ#/1ß³¹ÿ—©{¶˜mª{6÷(í­d;¼ÌîœÃ<ˆÉ–L)—Ats`†‰É–Ld׊ɖLbnÊì침n•©w.óRf®æªÍÕ\Õ¡zçœÇ½¥Â\ÍT¨w7Ù }žÇ »Â\ÍÙU˜«£Ø;ú| +1Ù’#Ajæê(åÓ\ ƒQL¶d ˆ¥B¿f߉Á–LáÚYa¿ÍͨÂî>š+t…>Ã|U˜³cÐDh`ŸRo ÏÇÀ›“-9ŠÛmûç}}Ÿ:“-)¡5°æƒ5Ä`KJ¹VˆÁ–”«èû˜ ôMóú~,E ¶d*sÓ@ß%/Ô«c™G1×’iämd.ÓL{k!×·Fæ{!ÆEQÔ÷ÆøBld¾e™ïEì½FöÙ")b®%ÓAÜb®%å ŽFöÉbî‹ì“Å ‰Fú|K¬‰¹>Ž}ÝĜǰ‰9;NL3Õ{<{¤‰zg?6Ñßã™—&0Òñì&öíñ1#=AK.BÆF)éîí=#¸ßØZ—Oß :µÆËteÓî²ïÆo/ãJì.ÿrƒF`aKeêoÚ™ýçÄû;ÿgö7Z÷jå-v‰rŒ>3Î1Z÷MWñíïßÜ®K¼{ó~댹»ßOß|Ðy—±¿_Dã€7¿(•v_ÏZ=ðGÜ›·}1~ó6çéÁþnáªÍ›[bO¶nË(Ó7¹mÌh Xå^ VP{a¼W_€³Á|Ù ”Œu3…¼€¥\ËÁ ×H_€k9¬RCxw)«Ì_§‡G;e‰•Ç•´Ë}œ 2©r}€­B䆆.Q¸¢#{eBTÔPvâŠÅ¿A……›'âÀí€Xê p4×Å5‹u n†…ˆvt,í.mÆX \Úä±´ëÑ8Fi ÄÉíP=27Kõ(ÖåA=B{…ÄX¬9õ(Ö%A=ŠÅÄQÌ-L=Š…šÕ£X{H=ŠÅOWÐL6zš\–Õ£X{I=Š¥4kuü ªåN=ŠuéPbÝðí=Üâ|î;Üø¸ªG±î?\%¸Õ«G±n¾êQ,½zKùŠ[ \Mõ(KS=2ÌõÈxáPŒ9lLõ(ÖE=еÕ#4FQ6têQ¬í­ÅÚW\K,IDt}«G±Ø êQ¬‹Žz„ž&ʳ±6¿zKX=еS¹¦à)P=Š¥z¬ÅR<ãJGD=Âí…ÑIäþ©Å⾩G±qðÐUb]%Ô£X÷Aõ(–²›z„ªq«ÁM˜›(×zõ(–º²z„ÓqcqYÔ£X{]=2>@¸ÃïRb1±à-p{Vb]˜¸9‚oÔ£XºÑ\6ЀTŒ÷õ(g¢éÑ£XD=ŠÅQŒÿõÈøQbñöÔ£XØD=Bñ Õ£X Gð#¸ªG¸ß@5cA=ŠuCWb±@Õ#i­ÊX 4õ(Öm]=Š…-Ô#Ü4 "‹7¡ÅbS¨G±Xcên:иŒÅQbù4Pb鑪Ghøãß –ï(.4hîrwç~«é‚c´1c)Ø©G±®EêQ¬ë’z„²4Š¢F;›.wuõ(–®pè§«G±´ÑÔ#sQVbq[¸qÿRbá6n½x$QbùÍRp×0.Ô£Xž·Ô£XÚlê®!P2¥L¨ÅbªG±<{ªGº8­ÙX\õ(Ö]V=2ÞM௠0©¡ÕÑ£XÜ5õÈÜÁÕ#sWŒWõÈø‚Sb±ÌÔ#ÜJ ‹5ÂmuøP(¯ªGR‡4Z¢ÆŠz‹‰ÂUVüX¾êQ¬ë›zd|°¨GÆ3‹zdü¾p#‡¿¡Åbþ©G±´IÕ#ã=F=2>e¸j„[€B£zd<à¨GÆSŽzK¿^=2þqÔ#ãɆ+*Ì7õÈx‡Qb9LQðr€nz,ÅBõÈø†Qbiß©G¸²@a:–¾zd|ΨG±8cêQ,L å õ(ÒTbaPõHœ]£ùk<ݨG±­z ëªGÆŽz «G±³z S«GæXÊE,«?;êQ¢ ƒz$.°Q¼N„‰Õ£D¸W=J„¾Õ#ã•D=2.IÔ#ãD=2ÎHÔ#ã‰D=2nHÔ#ÃPq©Ô#¼- QœH G=2þ~Ô£DŠApà>)”ˆç¡@"–:wxêê»h'ÂÖê‚bz”[s6[«GxŠuN[«G‰°5̰µz„g˜ÁÃéQ"l­ájüÅôïE1=§zµbôDØZ=J„­Õ£DØZ=ÂU šË‰°µz”[«G¸ëˆÅ [«G‰°µz„G¤XÜ °µz„7ü $ÂÖêQ"l­áI)¦Gœ/ÑpÆÇRLakõÈhäªG(Ô£«[«GøfŠéÞ5bz„r=þ%ðÜÄNÜ(’iîŠ/`*·Xç\(Ø \(Ø \(Ø \(Ø \(Ø \(Ø \(~=’Z4»Íø 4ë½ÇÝ‹Ÿרwäa÷1÷mŽ…,™ÉÕä o‰K1å0×b(örñ ¦i5W6ÛƒË16×½&NÕéÊh«Ö×_º;Ž6š¾Ä‡7(™ ø3w2º\憡—憡Nš†zªlV."í®sƒ­—¤ãŽBõìn%tˆÂ½„ûãDW³½Ã,r½°7n(ìYv~_Àš2EþÂuKUëëO]ìk®[ºÅ%…nqI¡[Ƶ¹é–ö¼¹ûÌ×µÚ­n*l·¸Ñ9ºå»H·|‡èÖâЭã\_l·ðwRb;¦¾Ø+"íº¥èëÝœiË*öG.¦û¢‹i;+&ΗžCÓC07 '+ÃÈ:Ð%ÈTfcOu•Ùì{ãFI1\s×IŠÁN5ÎM]à.°ÈÒ“|Œëž ®QÔËlp‘rÎ,ÌTc`ZÕl¹Tyîµ8 z¾#£ñq ·~îïù¹›©BèK˜Ð`5; d=çd†O(†Áؘ/Ì-*Ùg/‹=H4Òb—†[L—ëa±rµ€H¹L5¸ {1µXþ”aÿŒ6çæFþ#w*b%×Ð7í¡;eW˜–M»DÝ*8»9B{À8]R좸v³Ë¹xQû›«1MbÜaõ¡»Çõ‹:Øë\À¸¾±×¹‚ñ´Ç%ŒwÌ)×0ç&Å\Ĉ±Ã¸Šcf¹Œc‡]asÊü^i1vØ6‹1ËWY äÄ5Ü͵QlaÄЗóI¡Ž€¸¢ùþsI#Fÿ¹¦±áé?5b(xpU#¸†Ëšs_`®kl ñ!TwnW ýš1öÊæîÑæÒÆþ—ª‡2è&Ѥ{fƒËO\/¸º­r“7€ŽR8ĨâU£SøKp~â7[ŒîÜ`1¦EbÔô:‹1Üåè&ÓÉmŽIe:ß`9˜Nœþx<À2u«Ë§óÍa::Lç[ÂtÞ¶î[-Æ-ømãî‹'bÌÄÍãžû‹q»Å 1±šáÅÕx•›&Èù‹Ñ<¤*àn‚Œ¸› .zÄÄÈU:î]l­få7U|Úª÷¤ÊÍ2Û ærÆÕœ þ´Ëü©Ç2[åB›YÌ}ý¦möñEq“ô™oµÑ9n¼ãNûë7Yn¼ã>‹’úìD8¦‡6ØÄ°½]]ÜýDpƒ´aï~ãq‹´Z>Ñ×ÝP‹ÏcQ­s¿¡¬ÔÆÝ²^3wL_3·L[3ù¹æq ]ãÞg#.ÿÏjR\~î¬ÚÀÜTÌ­•ž°›¸·c7Ý® °W‹X²¸–°k>ª.$N½³~È(Wºz=‡˜z=»˜žxÞ13âú[eèÒi »ŽP]¦:«SÇØ€+­¯ŽK­¯ŽÙRn·“˜ ˜—ÅñBS”£N^p½f/¸ר0ÌeíÓ ã){ÁììÌ^ø)Í^øYÏ^p͆ñ”½`îpD’½`*QÜÉ^xNSö‚«9Œœì» Ä”½`"ªì7øëÈoÆìžkö ƒ5{Bà.š½€À]-{Á.F={s€+Zö‚{}m:aÔúÎtö†Bm†à.Ô: «®ö¾·¹ìLî Ù 8°k³°'j³¯‚qöÆEmÀŨõ–|ëìü 8×Ù ˜\™³p>Ðüà’3нq¢ò‘åâ*{ƒ¤VÜô»²°N¸‡f/à£Ô^ÀT핽€ÃR›rØ-µð^j›û­l_À™á¶’Ý‚ÄLIt?ÐH‘–ƒeà¯Ò‹Ð+nèPdµp)¨Í,LZ½px˜¡ììn‡Ù .pݲT^›,®µ FÏj³ÆE¤6kÜKjsÄ5¥–¶R-‡ñ\YÅ20œj=ƒûTÃ2ÆÍeõ|©Z‡¸q!Ì^pMòøÂÖÊ­©†¸DÕ0wªZîµܸj/¸€Õ^‡ÝÕ\Ïj;–ÛZm«p¿«UÏu¯¶óá¦Õj…µ0{ÁÕ°¶Q`ºÕð¸Úö†C${oíÜì…Qª¾àV”í=^pÿ¬M'7õ ir•[ëÞ½Â}‘½†Gàù¡Y’½€XëÜ@¿ÿì|sÿ÷å€OX›9î¼Æ}´ÙÀ¼€ƒX{;±Öx‹µI…ÑXË×±–ƒûw s¯á#îÔµ¬ ·Úî‡#ÝqyáØù x5tw3«‚®L…òijŒ3F­cÕ´QTQAÛïL–r´›•£ )RŽ‚öƒ­žE [ÀÀ%f/àfÔ6ÌÓÚö‚O.Dö¶jíüJàêRcÃô¨¡6vb ‘À—­ÍLÚZaUÔ6.œ‹Ú^„—[Û+lZõpykÕÃs©í`X0Ô’½€#SÛs0hj[ ~ Låìì›ÚõnN-+ÌŸƒTË [¨–•hí è–•¾×P˜»6ÔP»äÐÁÚ& ;µ¬\ƒjhƒ+N­´yj8|[ËÁ­…Þf/¸@Ôð“YÛLo­Ct¹–•I¨mtöKm{ñ¾ö‚ ¯½Û×^€—jˆhí{ª–,Q{©eå}-È¡ö‚ÛOí³Q{þ©½àŽP{ Í^pc¤ ë¹tY°Î¢ÝÜ ‰þÂê”füExPßåÙ*ûÚü°•³Ë3¬'óà*ËÀ·´Ãä÷!Ëã9(ôƒ‹ƒï÷wñÅ£çtËp<˜‚.Ä4GÝAFšøÓÂó`Zàà–¥öRáUCeu0b¸úx©Å„+ gX T«rj˜ …×ZLóSxÅt+¬Õä(†'ŠWj:×-z Û+^M _C\ňá2„›™óœUÐE˜n×ò@acº†ts¬ƒ‚nuÄÄa)xf‰Ø¶r+bcø¥0Ú£ú/¾—QÀ#†C«;jرF'˜¸oFA˜8ŠF[˜XZïÍL*¹ê*XT“혭5\ ­á;®¾54Ú«½ Z{­½…Ô^€¦k/Àµ žÚ F 5s«å ç5,I¤ö‚%V}qŸžÔ^À<®½€“\{[¹z­¾O<æZÎÕ;Æ}â>×^ÀŠ®vñ>ñ¥k/`R×^À±®½€W{;¯ö~`í¬ÕÚ ø®µ°^k/àÖ^À¯½€›Y{û²öfíÜôÚ ØLÕæ}â–Vï÷‰¿Y{‹³Šï¿±–æeÉÞ'þekß'fõîzŸ¸˜U4g¼CU‘þ}bîWo÷‰íV½3Ü'¶?÷ˆìLCîÙ ø†µÞÃ.䦓½@U Öiãù¼ú%‚Ú ãaµúõ‚ZèÔ^À,ª^ï襁óPIàÊ“½0žÏ«YûjãÛ¶ú¸@¯¾0~Ϋ/Pp¨½€1T{Ÿ¨öÂx|­¾€]U{¿¨¶-`iÕ6Án~Ñ}âÕ^À/ª½€_T{¿¨ö¸@¯¾€_T½ÞÜ'~Qíü"]ö~QmÀ/ª½€_ĵ({¿¨z½¹Oü¢Ú†ƒ_TÛ ð‹ªøì>ñ‹j/ÀöµÁ/ªÞ│†àÕ^À/ª½€W{¿¨ö~Qíü¢Ú øEµð‹j]„_TË¿¨Ê¹Oü¢Ú øEµ ôÚ 0|í¿öü_emݧë@-·ƒ*š¿O—…Ú îµ.r•¨½àfQ{ÁE£ö‚{Gí×Ú n%µ\Rj/¸³Ô^p…©½€_T{ÁÕªö6QíL¢Ú ˜Dµ0‰j/`Õö+L¢:„IT½fß'&Qmss³«^ïÓEÛtö‚{÷ëì·Àþ¨1‰t£“¶4®Nè’îV‰ÚÞ謵ÙÐdü"[ 7¹êù>ç½ú‚{^-×¾ZnµÆzõWÄZøEµð‹ª\ÀûÄ/ªe…_T{¿¨ÊM¼Oü¢º_TÛ{ð‹jè~Áìü¢Þ_TešÝ'~Qí’¿¨ö~QmŠáÕnð‹ªöû4½µù`¶kbîk†_TÛ`ð‹ªlœû¤mPË Ë¨V=,£Z­°ŒjYaÕ*ƒeTËËÈ3ˆŒ‚Ý}º6W#÷‰eTÃV°Œj/`Õ^À2ªu–Qmª`ÁPÉ^À2ªaOXFµ~À2ªU˨¶½aÕ¦ÓøY¯¾€eTÛpÙksS¨zƒ½OL¡š€)T½ÜÞ'¦Pm` ÑÛìL¡Ú•¦P eêUÆU©VL¡N)T« ¦PíÒS¨Ö{æ°¶§a÷Ôv ›¢6 Üj›¦PíòS¨–¦PíµZVV-]®½à2Weß'¦P­ÌOm^­§½ð‚ÝQC0…jh¦P-+L¡Úm¦Pí~ÈÔÕ:ÄûF)TåMݧËAí^Çí§–ƒîÔ*£µ)‡)Te¥ß§ª˜Ðì³QåDݧI¨mAÞ×6ÑÚþ­Õp7ýªí{ú^å2ݧÖî«ð}j•1Ï5,ÈûZïa Õ*c›ÔªgwÔ:S¨vÓ£ïµiAÕÐ!L¡ÚU ¦P•‡|Ÿ˜íUvÜ}Ú¤µ ‰Uyw÷é’Q»ò¥k/@Gµ‹XÈk…Ü úÅK9«÷Å8 ŸûÒ šPѽãF¡n–äx‰²•´œl "Sj+•šŒæµ„®“r…”’×uÂ#׸>R¤•l©äê„ÈÓš©”zqßÅ6íêòš[4Ì;ÎàßMo鎼5«8Iä×C‘ ‰Ñbö¼'ÞªVó֨善͜K¾’›Ýäñ:°EÕ[s\®’°1òK% š‰ÕˆºO™À[Fw¬„ׯû⺣¼ Ud[¨“È®c Êüm›v,eO™Ž}›K¢†íUNµo£<Ï•5l¯oÃn) û¶ —„‹}gA–n×ɽ˜Q ˆ›N2MëmIhÝO–õžc°M)vžc¶IɳÎð5`]çF˜¯=#Œžˆ;ƒ›IUEþºAO¸}ø)â2âtžJº›X'ò;§ÀâŽ)—–e½çºãl%Ý~ƒ­¤ËëWÊŒS¿RfýâžäúeÜŽ8›ñ:âl%]¡,ƒ>üõÁ(•pãò}äf牜ßHoæŽ ší=o‚±:F=\àzëÉæûo`ýeu­O çv`6š™t˜qßw£…óퟄSQ,y¶$Ý•—éÝ…iÁLë}I< bâZÈ–é}Iboq½ï«$†0žQÝÏö.Üë+Ž<_ìE‰E”²Èl@ñ¯[Ì ÄoÃ5+ŪTìqX8ßÀÑá.Iìýª(­Íi¬[”hjsЦ6bM~®[Iì‹@½òõÀÛñ3ö‹ª(­Íê1ºdjSimÄìF×®$FŽÅ°uë $.ý¼*Jkc¯$fM‹pEɳnÈã99Ì”gì0óžÏ¦”¦U»] -"&³ê¢:qKâäd[ÄwÛsnýñ;Òsnýñ;Òsnýñ;ß"Rd3=`‹ÀÓú—-"VdIl©û+"E:v éuÁ~´»’kHõómñyA̵åÛæù;»Î|[|A^¤*Bß_Ð×a.5ß_Ð×Ñä^Àôu­o‹/˜ÕAßp-s­ÅÍÏG¬CôMªa¦7ĤfºBìNë19h7 &-1Óbòicª'&0S·í?zÂĘòÏ»ˆ±XŠù~ ¯ f³ý¦ùÓȺ,^¢1휪<~6£ÜžKG:œ)WñÜŠLåà>n L7o¼"£Ç¶ ‹N‘±¤}R·Ôzzªµ¨˜"rf+Õׯ»Úí„Á‰tWÞé‹zj/è‚y‘N!7…Ú :R{ÁDÔ^XO2á ÈÚ Ù ºõ+¦iÊk4©¹_Ò½Ó—W¨Ë¦ ׋`óñnd^£<¡w¯Ùæ•ß”#ÕD}Ñ_©´gSoRìYï$‘Iô>åßAõj÷”bOìòÌ—H”'f¶ßñÞ"=ñ¾åÀEùÅÃ4û€}"úBíN9ôJ]Å£9^±N°È­Í]ÖuÐU[6¬Bµeχ'ÆýÞÝ¡ÊbQ¸XÙûh1×Éoƒæ\]x4ñ[øuqÕuÝ-ëæëkä"lïÔè\ù«FüÆq;þI¾'¶¡ÜrìXˆ9(½M¯uIN°¯ï‹ô¿-”¬šÊxqþ¶¨Ä¤ümm£Vñms9žmaȲð¨ï‘ÛHÖ¡£í€Ã}rˆD9M~ªoV&FA$ªÀL0xŒ*P‹ýBœ¯¬»{âö9Ñ~´J†t”»½¯œ«¾Ÿnþ¾£0V,‹/àvXYl»ÃT×}B’GFÃg¶È©A@FšN°Ó¤Al.¸ºŒrãý¶:!Æ\I\ j®•WLÃGç5ñ ÝŠNЏӢð_ª±˜ÐwIì,¯1áuÄå.ሂ»“јÎ§Dš¥sabNƒ–<˜] CÏÂé_ wäõ/ðŽìõ/äž&Õ¿(H×Ãé_ÈMMªQ ßÔQ¹`á½$†%ïÄ`*‰IL½.™æk¦•×¹À£®×¹ÑTçB^¥sa/Pîn%õ?¢Bl%T_A×ò(å}*F¸f.¡µi°#1i} £á0Ês Î\‚æˆÑ'XïÄ@}Êeb >Õ`b >p*1±rJ¯ÄÄô)¡¤ Ö+‰Çð{1Êãj^&‡f®ô­ëÉ‘`”w}Œò¸G”p¡¾ã²Tº1Fv%puéÛ1¦ó”nŠÑ;©Ä WOâbÔVÖ^ѼVáJ[Âk3-w€Q÷£>®)êð¾$5bà'6:1ð·bl6®fš±ÝH¸WðŽyBãó„„vjƒzƒ>1íË’Ô#ˆá'm bbØ”t%ÆÌW¢Æ£I”§k.ï˜9®¼ÄÄ?*qu6hþä[äÛpíåáDÏ-X¢˜4E¿})[X3‡‹ذøK[•cõmqÚk/¸UÕ¿­ËY•ôm]Õ2þ /À²°Î² Ý*ÇêÛº’U¿­ Z­V8íìþì70§ãî^p!«åà~Våè}[×µª*Ø·uy«²“¾­{Ví÷³*÷Ûâ´W¹QßÖ%«–ƒ;W•7÷mË^pi­Õê}_e/ü•6{€q—½à6WeK}Ûß³Üõª ßÖÕ¯–Õ_–³\ kµ‚ajYA8µ¾‚juxu ìØ ŽbödU« N{•=úmQÏ^pm¯2×¾-ÔTÛCSå/@\µ­³[óÛºòÃÊ^À¨õ†@•Kûmñj3 » Öi¸ð§²»Õ1¿-ÞB•Ëöm±j}…ýPåK~[¼‰Ú~å\Û¦°×«ú^ß{½¶ËáÎÔ: {½Ê›û¶¸7°¶²°×k‚k,{§–ÞOm+Ã^¯uþLm:w³×¿-ŽR µxuûìü¦ÚTÁ~ª2¿-özm`¼Ôö=ܘZ84µ°×k}……Ue†~[­*«úÛº°Vùãß¿«ÖE¸_ð³Þ\öîMU çÛb¯×fšûHU/ãÛb¯×v0̳*ÇóÛâ¥Õú G§Ê'ý¶8mµY„ñ71{®ÖWØrµí—®ªþðm1íàlg/œ‡˜ü,½Ú|Àà«íØëµî¯Õ§¨VŒÁ*üÛœµÂŪ6ClÀÚž»ÖPìuΰ٠vk­Cð%k(I¨M0¸rö‚-P›ªÝ:—ßV—k9˜Õ*;ûÛu.¿-äSe[“PÃ:ô´¶-`¯×öÜ×T yÓìšÚ†æöTÛ²ÄÌé§'ÛNlOµ$f¤ë’­›jj—¤j—µM _S–E9ß*7ûÚóÇ‹rn(7>ʹ±tܘBÝXÓ”¦1µ´1¹<Ùxиì<®I5´G7Õ-YZ]ÛÒ3âÍ MÕ­ÍÍ ÍK£‚qK:«[jZkšª—¤RÕµQÁ”ƒÒO6v4ñ¢<¦ÿAáöLŠÕ˜¹ÊƒÅ_êéÅK^’¬mW¦£{£Éëê¸yꉾ£Û¦.ª¬ž³`Ö¬¨`‘B'T²¯>­Èéåe³ª*f—WWVTE_Õ“勪ªçÏ)«œ?snUõ´™åÓŽ‰ ^¥—g]V½ rzYUyuÅœªòyÇ•aYâ:½™y2ÝžüZæÉ {bª³OfÆO ÿØ[‹/ºpwo9é«û{+J_5ôå_ïÔ«“¦N¯ž_>¯¢lVõôòYeÇG9‡ûgËÊæ3*öUq?ÿjÅñ•ÌÄg>nÖÜÊÊã«§ÍžîsïÈ<[À›3]²èí½¯l›/ï}b²$Gö>Y^UVµ€ÎýVx$Ä,zl¦¼ê+[Þ½Olyïë}âËËÛx,—z¢ ªÊŠþSÀwñi?ÉâÓ-~²ÅgÄñ(×燣îR çù¬Zð>¡´%ÓZ—1‹ç€ÉÞž.7}òÆtÅé“7§‹NŸœ—®å„¹šn½<]Kúd]º–ôÉEéZÒ'«ûkQ×Vô×¢'ëûkÑ“ýµLr/ÎÔrú±˜ôÍê œM“ Ÿ“ɯpå¤Ì,²†Nòß™~±|VÙqåQÁ»2ãéRø¦ùž™X—bÿô —â«™!v)>Ÿ~áR4õ÷"¼´`דôaååý½ÉRšõšõ(K9²¿WYJ²že)_Ùß»,åˆ =LG ôÒlG‹òFÚ-ï[’vÑ&ók÷Ð&»i 6™Á)yól²³É®îo›MvâÆù3¸hüÀðñª8~ãä™d/;“ìgÎ$3`' œIö”Óf’ù½”ޝâO ôláñ³*æL/Ÿ^|wã²§ñ ÝËÓ.îoažöË}ÌÓf=ÞöøŽæi‡ô·5{Z;ÐÛ%åe˜U+f0MiŸ•~4ÐS—.ëu5Ýü^ºt<ù>ºtÇôÐ¥ûÝþþÙgé:J{·¼3·õwŽG…;ܤjëïšI•mèÊãß1“êÌ~™Twõw‹Ge߀¬W¶–Ü‘ ´Ë¾+û*²Ž¹„(¤Ms ýhf}s ?0Ð:—pêÆî¹„i¥ tï²]çž<—[A”{a í³Ò÷:èÒ™»OÞ@—.kS-‡ß¾}._…i÷\º¿ëož}–¸{RèݱsçO/¯*Ÿ†oΤ¿ùÛä] ‰ìoeHüÌ~†ÄìojH|þ@gCb¿.|{ó·¢3#“â%é'6…9 *>3“âÚô &ÍúX6¯â8#Î5wÞì²Ê(†žÇ©sù´yåås¢|WŠ ²•äkˆ'Œ[ÊwcW}wJEÕ¼éQÁ9ýÅïæÅ±sçV¹ÖËÍsvÕ[^qt|.½2>êž²€½qœ¨ÀÕmã‹gÏw®[€ðøG2„¹E;üZæÁòªy®{wëÉÒ ÿ.Ñå´GÖ$Ûj[ZÚRÍXµØ’ìl¯®Oµ6ÕàÈ´½¦íD,½fÜ–†¦dÌh‹ &$›k–4&뢂ŸUW/oioÅ’ÖÓë’-Éæºds{ucCþÉßJk‰@€{£{RüY[ÃIɨà•M5qd|Ê¿9Êÿuí²TCmõ‡- íØÀycš@·¹½VžÊ(»¼¦1Ê™ÐÐÜÐÞPÓX­håMËjšë“­x{ÛœTÂ-©Ö(û8²»¼*qå’†ö6¬ž^¶°zêñU@±ÂK™Æôô}h¾.hÄ5À ÜQf;µ¨™:¸>¦uÖƒhÏrÛLè$™§ëÈbp€n&å׊]·¢ljõB§â§}jS³5›ŽËhl28gbu-\å¯"~-,¿ªeüXjŒòh3Ú^Õ2j¼¥Š–÷}x‹8‰R8?¯¦1ÙNMk’K:–V·ÖV×»¹®\ÜÞÔR½¤o£#,²’•ÐŹ­K—Ã1 /H¶VCŠŒ²ßØÖ^G/ ä/ïS”[Ó”ª£¾OÄWÖ74&«õDst{ŠI7Á¨à ©8R¸™:ϧ&›÷C.á… ÍxYj]ÒÐ\Óº²º!…€ÕæöšvÞ£·.û&º˜Zl¨ðŒúÖdRSEQÎ’©zôKÖ¶¶2Û…Ëk—Õ´ú·ÅBtejy²µ¾1µÔK›—&Ûk}šhyKª­¡EWÎñe]lYÍ.JN±(£’\dÁ IXáoÁs–67i)DŸo«Yž¬óe“%¹Ñ翸 ¥=_îÊ–ÖT-pâ’dM]KöZÑÚÐÎ.5ÁÛjSmŒK=+\ç[s*µ´s;ÚSÕu m5mmÉ&v¯ <æQÛÂòŒºd}MGc»mj¬YéxÜå^Êê´ÉŠWú7çÖÕ±z.jÖú?¯%)×PQßÕXÃòÞ¼²¹¶º¡6ˆ Î¥'ë›ýÈ®>1*XÑÿb%Ó¡I€˜W߂؞ÝHå뚓͌ÿ»òiA¬íŒ žªnCÆ=·±q‰*‹Ï衚ⷷ%Û[–­lJ6áOãíbQsg#[C[zc²¦u4¯¢‚_“jek2ïß‘ÈD¢ËÙìMÑs˜¿•ÃôˆHáµu ­í+ÙÐ$«Û—4ÚL¾á•,-«Ô˵‰/}iG’^ƒz kxd²3YÛ¡E6¼½æÄduC+:ê²Bkšj8:\’ôUG_†YéšwfcŠÕ ¾jTð½_€IãÊaŠœ2»yD8Aê>y…bB:pŽb´WSãÆv¶â¥-´ãµ­µc`'ÞÌà\ÐQÓŠàćž¡qDy%¸Þ }áP‘Ëhð¥Vg‰²¿] ÄœlÀ<ý™ugG¹‡”Ž-ØÂç4ˆú'õP>gD¹‡ó93Ê}ŸÊ;™O]ãóÈ(·ˆOUq8ŸbÍo,²¹¨¦¡™~­¯¬„èÞÀ#vV±^ðu5ˆ@#|f: @¹ Ð.ø>}i²Y`²rTcÊÌ%£T0øšŽ<-O!²º‰ÈçbÌ'õz³±¶ee”=·Ppquõ¨Ñq~Gs­» Ø*~D…ldqxä Érº‰Wþ|Pù¤jafËS‹êO£œµÔ47Ôn.ê|¯Í"VYÆB/—«¼iGlDfâ+”V^muSÖ!sbÞ–ÎÑ[SŽéšœôö²(ÿó<3›~]Ök5$•µ3*KâºpÄsŠbЙ㌆(ÿ¯Ü6_ÏÒšÒÑR'À³¦µayŒž/m‹ni§¿+«UŽò(ëe\'lÍ›A®Ú¶îVÒ‘$~)Ósnk;M¾È=ž6¶wÔm!ÏskÌn±â·J½`娥„ãô`}]eme-ÐOH'V3«}ùŒŒˆ5Çm®u=+­ðÙÌëó8ø\ïÿjÏ]Úå¶Pƒ ØÎÒqcø|R'¤z <£(¾3ØU @a —'¸Uá^êAa¸Ãf¯ &-‡ëøTǯçS“{ j)Ù ~ܶ´Öp2ÐMÊ\ñýdн›Ï™X‹íHt~}&Ó­¤PÓ~žO Å'6dÒI¥ZÖ/Emø$:-bÉ=c0Y(íS¤Ñ8~šÏ¸ðÙítqN³ü:ÏcGéÕy-1TÑÆra”ã·ô†Ýk*Z0êñ4>5ÇÓùT3øœåÿSº56oº‹ž[TÃ4^&e*Õ×ê7!£3tÎ W[é>ØI«1¾ xw·dSо²–-¯äÿÊå*îŒ6‚Œöž»¤-Õ¨ûRñ«J.»¨ÏĤ»©Á?‚Ïö(Çan‹¤4a”·r ûR‘­ìâ¤ÑbX†0Žàµ>›9¢¸lZ‹GŒb^–ó)Edzúr˜]³‚—Zgò©U0É'8_çB]—|5®gñºuà)µ©æåÕc;§6´—tTsÃT`ÆèA…3¸rþ…[ñÏF¢GûbH$éÀqi­ñå¼VÓÞ]:~,àV>§Eùô¹.IÖ¦8k¥“;/~åL6Ð&¸Øœ~Ž´ÓñºÀYÔzàˆNòiÜ.¥9R{ ÃYå._[ô7€ÁKÝ8™à®£i23Åξ88•ãfñ+¥ã«~“Om ßâSƒõé=çsú2KË‹(Qé;zSü™5x÷–ŽGרø>UÕ×øœ„mz»Ñù=ßdÅŸñ^ O ¢iÕÚµó©‘ÒjÚi5 Ú±ZZ³ÙÃ)b}ö²$— _Oü.wãê<¸”¢}eþÉ‹¨Éu>wøuîÀa’0{S9t5YØŸ"Ïpßp:¸6¾ócrùÀšÜlú7»ô¡ß9|ªsùTçñ©6./=‚;añÃé‰bÛ¥´׸‹u²ÏF×-Õ¦%ÌÅÃ^0WP€€Ò87Ó«[Çp¶ã-‚Ãg\ä²&ÔÌ\—ZA›ODäeþhMižDlJÃy¤¦ò·ùÔýŸšõßåSÍû,ŸÜßãS=ü}>ÕÃ?àS=üŸªâoK8‚*¾Î§ªøŸªâïøTϧª¨ÚULÒ?É Ùš ð±r8ÑÌaWIøH©gE+Êì=‡3XÿJcb¸ +GØ}\qRîÅ_QŒÙ!G² ´CŽ´ÁœM…_+jk«­iæ8zûæR‹?(‰rŸ’~oèÙ E{i‰pýl>Õø§©hÞ¶ ³=»´Dó}9ŸJñ>EC{ÑÀ´‡Zþtó P¸*†y ‚Èffþó|O"½jzŸêž¨Ã+g:ÍŒógŠÇº²|ËWÖ7´¶µT"¸~™ÔõJKư#RxºyeÓ’T#÷ŧ¼– ‚‹·dЀ‰ÁcÆSZ|éfFù]ÒesýÞ22×uËy¶îÖæ"¯jçëa•„gQÍ@ª¨€õ]Í"åâ,¨zEíÚx.>»´D+hŸ³‘|jGñ©qÙOËh>5ûó©™Ãç‘ødH‘UérA½¢†¤ƒ1–<ÚtG—–”õ>%Ùv‚Ï*€Í;Ÿ‡Ò¼×?ôɦú‹EBöî—á Ý+–e:¨xÑ[„®¹›@ÀÙ û§´“˜\ Ž¢Bwå_ϯš éûT ¬-G:¡´»{`¤ÖŽåˆè§B¹\±y§‹ l¯˜6ÓÞ•¯qïΚWºAõá»ÜCIœ0­¯’øŒs ‰‰Æh =Ý‘ïGÆÉįæªåÞA°\‚þò /¨‡X¡ýðçjd”»ªt‚ÙK'ßþqz›lI¶ÌÉ@ÊRÌÆ(Í©]Y+vׇH§±~zé!¿gð©Y_ɧ­âS˧fý<>5µ«ùÔ\Ãg{”_ê ŽŒTš[d|–\õm†õtéŒN.ÒyráŒY5'õaF÷¸§ 6=ý¶{úÔMO¿èž.ßôô7ÜÓS7=ý÷tÙàÓø2G!.ávXpí߉j1É$ÌŽòö*UŒ¢`io}+>“oÁÁÒ8}O‹òÆë[ƒy¤¾«Ûõ=Á5¾gaÐ…o­ù¹ú÷.Ð:SÕœÍõãlΉna²‹½í–¢ÒQ£8õ•O÷‰Ö$û’ù0œD:Ÿ”öÓ·úÕ¦oõKý˜Æ‘®°ÀpÙ`öèõŽ®s~x]›Æ¹®T¦op6ß4ü)úÖQé_ȆM…|¶Ñ£‚Ò ”P“q9ßÂ¥•úVaÏÕ·^ÊFÙ´©oºs)äyJ¨Ñºƒo-§Ò§õ­Î¼¾tÔhNÆ¥sô­ÂÞ oüF}+ß›ô­QÜ¥oâ›õ­U÷}g(KÃOÒO+`ÏMúkfuzåf‡wY6ß4 ¿æ›FÛßD­ ™ŽÐ¥[øÖ1«ôk¾gÿ–¾Õ›oë[½¹OßÚÁé9ÇÐÇRLø´ôL\ÌQB &Sä$¿q§Ï8«-¶$™y,rUÇÖÛÈf»_µkžÁ7ƒ¹RßêÝ*}ëݹúÖœœ§o­¬ÕúÖ ¬Ñ·æn­¾ÕÛ­|3ÐÏ×·z{…¾UÏ•úV=Ûô­z®Ò·ê¹Zߪg»¾ŒòúæÏL³ ¬TºN:Þ^h䲘5cE=°ºÔ@¡ q¼ßõÊâ]o^Ú›ÎûòöHÂÛ-L€ï埄ÒR8)YÇ×4NlbÁ­mãÐra²Ž¯åIŽ åÝ“õ5KÙI†!ÆNPmò§mÉÆ(o_è³+ù¥oÙ¿ý"ë+éáL‘ì!*9ªž•¤/^ÕX'jÄG±l©b¥/564Á:,ÎhP¸°K]+[»¥®••;¨®•}9¸ŽÃUáYu­pû‡Õµ‚%f´ëÅÌöVˆ ³Ú[Q8¢]¯l×ë~µª ¹Vô¯Utú*ìRK¾â± ÍËt®0sQ¸A¬ÉÒéšPM:µ g£¶3álÔvd¡orEç¸À  úÍÉÂmg,*5†h©\ßZÇé[ àx}k¡,Ñ·Êæô¬S§eN íšIÍh»fR3ÚÎI¦÷9%ÐÕåŽô–>}öüë¥2Õçoè[ƒøwúÖ:ºÚ§“ôCVüï8!˰SCuíwo20(~¡ž¯\УB¡ÝÙê·ªœ£o]s¾IN…ÿ^ÅjË ç‘ƒ·öy¬:Fz–½!­“¡-£|”Ù°ÖÖÄéUkç+k®¾ Àзú6C§Y0ôm†¾ Àзú6Cß`èÛ }€¡o0ôm†N¼`èÛ }OGsÛ0Á'٬Ψ’oò’#Í?è[ñÔ·*û'}«²oé[•}[ߪ¬•oiÑô­Ê†é[bLàÏÑ~´–§¾UÏ(}«žýô­zFë[õì¯ïÙ¸R©QX¼4ÓźݘA¦²i¢@¿VouÅÇñ HÐè’·¦¥1Ê^¾¬­´Í¥Ò§i]hXt¢6âë³]ŸÍ°èÒ+qæê$뮘mœÆ”ÃÂ/Œ±ÌL×4MïëùŽÞ¨oÅß oõøú¥úwû Óý2Ü•Bí³¾åÛ$½ú˜T:{f©ÞK Àëûõ-81³/ÕUiª(…h{‹ŠštßÎ TÜÙ©5¬×½ë[µß¡oCзFù³|ƒjOßš“ß×·æäô­6Nßjóê[mþ¼¾UÏô­zîÑ·êù¢¾UV‰a4h•FƒV ŒV‰!*h•LªÕ*™&T{Ÿ¾UÏýúV=‘¾UO¬oÕÃ<w´J¦ îh•LÖÔ*™$‰_×7Ц.áða®Úé„hÝè$ 4ßGDYiÍ“scrô‰â†è­]Ê|f)Oc…ÅéÕ´¾¦ÖžÅVþÅrl, )s´’©™Çê[ûÌ(eT.!©i›áe o•{ ¾ÕîñúòËér¹þçÕšŠ“Áz¢E†O±Pßb“µûœF&¦;­ŽÎÊdX Óc+ß çë›SK ½RVE5ÿÊ£¡Óðvƒ†vCeº£ ®Ì\÷Š—Æ;s,8dÉŽqR£$}ÛÅàÅït!1Y0$Š…v³2F%¸«3æ>®os×·¹ëÛÜÇõmîãꌹëÛÜÇõmîãú6÷q}›û¸¾Í}\ßâäüoÇT¼¸£]ʆZt²ÈLÑáG=áùB41z%@{¦¯ý'†¬èíçÖUšÐ2'‚‘#Î<¯Іu± ÓÞø^ „(·½/\þ9§ƒóØåoL5sŒÕ¥Gï¥ TxGC*“¦TÜT³’R¼ˆ×>ãU¢3@ÙéÓ¼«Y¢gç£×u¹û¶bu%§À°1*Ø #U|«“Ò0A]J_©¡4Ê™”l…Ñ]‰ƒê&9úsÉçôò/–¬„¡Ÿüu+ôŽ÷·"n2ž>\V-9¥Ê—ë«?ÄI¶H”\EÚ®Ì?„]¦-77í™ÕË8W—Ç¥ÚNªi¡«§“--Á´Ò›S-£ªÙÏKµŒæ;Z³*ÏÔSíò•z«@\jyt^«Ôr¤×Ô¼Õ^+V9ÒuM’•¥.wßÐËt!Š’q?Åv)%uçt)}ÑÕÄœ@l£oÀwqÀà îµÒâ³i±è¦%ÜÀŽOîàÒ^˜Ö „-}ǵ\ƒbd4R,AŽMŒÏ-Vc”Õ7/‰Õ¶ 0-U[­3ÿäÖêQVM ÓkØ2+¡$#SXX_³©ÀÆ¥Ö§ƒ~’67¸îÂ>R•Ê7¬pƒ‹û“ÿí`Hå¾\˜3ÍSyš^Aä(œí–ƒ«§üeÒPeù˜÷?® ö×FÙZ‚OÇ´\¨=xI1¡¤£E¾»ka-j^e¿¹ÅäÅ+ /O‡tdqjLöúÒþȹ$°òÄãÏf -Y[7Û)ï¶¼„Ã…‰E“ØÇâÐÓ\35/öœª3Ý$–7µ1§ H`™P›5rÑ«kZjÈ`ô¶öeÆàªTþ~FKÇì¦ÎyV6õ m©zºþÕ©<ÍÞnª]Á䵵髨®¯aõlÁ¢z ŒýN}ŠíýûõË+iƒŠï2[c¸ 1RϹ5.nNUÇZGQö'Z›¢|tÊ ªð‰¦&ÿajg_3â9¾d)R]27jñåJÀûi¨Ìû˜–߇|Lgµ¯s€”²©:!n×JUáF"“'Ï^T}ì¹H®éà*P¸ª¯òûÝ PþD Å 6v°K õmÂËã÷Ñ{ôÞ>ŸÖÁ".Ö&lw·pƒžß¤çhTFÙÿÔQe_؆¬Çtl²D9wurS,~‘1UÀõ³|Lu›CůW«Žâ®Õª¶XUíºò•êŽøõV«ÖâÕêH±«Z+]ßÔYËä'Ò¥4!Tø “ª:9-IUš‚ŠÆn¥ýø_›’Kkân•Ïj[VS‡ÜbåcñiÛ+å©[˜S‰ þÊ)ë蜚|>»‘Œfë˜X·M0WƒZ|«“´KÎ>‘5 )T—œTœø°ç4*WwžudµüÞk/ ˆ0OÊ«’¨='3«•÷»«®1¦r¸ˆþW>’~1Í^\â_Ló9þ¦/`ègûrèEôÖtÓ¦ü7ÒI.n~Õþà”²X”ÿ7µÒ|u2Ö\­¼B2’+Ù‡•5.">`Tà"ÆhfÒjy >¶¡†%ó2‹žEû/^1_¬€ÂHÞ'©eb ÓRÆiAZ‚¤‰²öÒÿ“XœÈEßñ:¸‘¡ˆT¬'Ê~']•'I±ûhæX‚ÑŠ_ãB Sù+óBƒÐÔ£§¤5ÍVÌýN}Щ£”FÀk0b§ÂO*å%¬„ÚëèªYÈúþùpx·ppc º¦³ZøJÖ×Ô¢Ž¶EÁË ÄÒlúå¤ašÃ’Éó—tV¸Jª,òÁŪ†í6ÄÍI”ë&,o¯‘FÝo“Æ\õ­|…l÷›—D|ç²$XJ0$zUS²½¦‚ËY”u2Ãqúì·¢¬v[k"Êþ« 0Ü® 0ÜK+p`4ÖѼ¦Gûñí.$ WžÐYÑér—&Cò»ˆÿqE{㸊|½¥b ýÕ–"þëT‹FDpG~vX³g¥{¶">оÙi­øNm³2ÏKO ×b6Îa­MñÑ)®ô j!¡Ó|Lààœ§Doù$Ÿ‚-›âu^Ù¥½q‰ÀT”µ\K‚/|¬Eb­¿Ð"Üù+šR'çùµƒÏâHŠÏ¬UonŸE} {”ô­[TYßÂ?}ë¶Õ oAž+Þ‹²^«´Pwò¼8¦C”ðý_¸ÏÒS”MÕX:z¢E"êÛõ­*OÖ·ª¡oÕóI}«žOé[õüš¾Uϧõ­z~]ߪçn}«žßзêù2ß\Ðÿ\ߪç/ô­zþRߪç+úV=¥oÕó×úV=£oÕs¯¾UÏWõ­z´féȪùž¥ z“¾UO?}«žf}«žþúV=ô­zê[õ´è[õ Ò·ê™À7ôCõ­z&ê[õLҷꙬoÕs˜¾UÏ}«žÃõ­z¦ê[õLÓ·êÑåu–ÈìÈìÈì.çìÈìŽâìÈìÈìȧë[õ¨Gè$®>!æ†ú€h}@µŒ> [FÐ-£È~‰€©oCÀÔ·!`êÛ0§×y\}@é‹> êEŽÐ~TP÷¢hyч#´—ëÛ0õm˜ú6L)¦¾ S߆€©oÉ<Ó_’×%3ÚS¬Å#X›ÑŒ'½>­¼\ÉñSyN¬]¶²çKOÝ©•Ž·µ úÒæöŽ%ŽLY:ñÉ%|9°Ñb<˜«B£9I§Ä–‰tSÚfµQS!Jdlï#ØîÉ^¤Ü¨ãFÁ2—ûÂäÊ%¾-h`ÝÙÒØ±´Á‰£²îК?B0@kþ`@rbZ„Éê†Ùþ^¶î°-DÇr°ÀÒ <°È%=»Î û¬­²SJ³U˜¤«¶y¿Tvºku©6äÃy ³œD²''› À¾ŒÓF)•Í£3Ûg`HÂ{3B*ëÛ¡÷¨¡ÏöGb”MÎWü¡ëŒ‘5]“’†æCé¤ ÔRäd&™˜G2ÖÛ¨ˆ!žÃC¹ÐãKL½ñ»É §T͆ãÇtâ¤?v¸8ÿßæ‡£ð÷G39êï€âÿûâ™ÿÇõ¿îáÍÏ}xMWnغý÷QR˜³ %ROî¥Ø¸M=¨æRtÒþ{ Iåw0ž Ï»ŸFU~öfzV¤ƒÛd¯èúœ±è⇨gåÚ~N^å [x|•U[È€? »…•Äcù_w0*ãÆmLV«]ÜA­-¼ÿ^z®´Voü¬m áDRúLåÊgË—.p/c;ñÃ\'——ÿn3¾øµ{… â—oQ(o(×nï¨8©°º†IAä§Åb¼‚NPáã›’’cµ˜ ×ܯç”,Ø.3•¼]Ì*yévɬÒoäªüão5¯‹u÷J¹Uª·ÊãÝ? ¨ç÷› —:7+ ü{ÁÂÊ®›ÓDÙ~ëRŒ¥¿~P`²ø¡{ÅN Í›Ä. ûÝ/ñiê»$KÅ­Ù#ZñH§Kõî—-n¨-älRÀ­,Ε¢x—ÜnòêAÅÞÒñ÷ɯºO¹ô€ÀraîýbÍ‘ÇO]¢Ï•³·GÞ¶IÁ»âb*¾ž|dP»ò·iÁí?7Iîä'Ûåݓ˶k§'²ÒéY ¾õÑï»,vnê¼Z›¯ÿñ‹ÝŸ1¦ml5‹%kÚÊÜë2FD˲F-N7XM_–[ë¹_¯ÿÀZÙŸ­È~~¹\óúQ-¸‚ûÄŠüêÓ[©%ÝÊL;ªàà ¤–D>ñ˪_)6 R}ÞˆåÆØäwsŸZ™ua¬]¤F6B’!ò^†#Oy$ît–Q!ù°è¦î6QM׊#ÕV¹zµuU}eÔÉîëÐØ 6w뚢ša(Ö$‡ÇZ6º‡¨6s8wîá²)“‹~!jyäžo¸Tù«yŒ¿—løÝWýš2ÛLSÕ½Úª{)ÚS´ÓeÔÍž[ŽQôŒÁUÙ‘{:öL§Ëx²¦;˜ÈÚŸyÈ–¨M-oµ3äxÒi×ÂŽ¢=·/òŽFÌÀ×Ólùd•m†°AVN4t”3뮋dâÒN]î‘ÀŽE—i‚jo1ØÇÉ ¯MŸ;Ðbª»“èÈ„ý_3GUOZC{lt”p=v„ÞÜgû –EÞŒ—Ë v–źA¨fYŽGìårå*Õe¡Ú½åØÝJŒ’=é¸Ãì}W+ä)¬ë§ÉKi½Â•çGµž†ñÒsdà:Ë®G<ª•pþ„Ÿ»’÷K4=Iu¿¨%:–»Ï‹Q‡_ Õ+WÏ«Zç•Ï‹OÃ ýò°O„,´ ö3eü8«¿z‘ëyUëÊ3q—¼A>³qî8÷í}W[-¸ólét™†­ÙK¨ÿ‹ðÙz‘ü¿ uºN¨æ†¾(ÞqƒM&Ôr©«É«±6êï Õ“ÂE`‹å0=1»OŸ½¬Ï&Zù,®ÍƤ㾺÷]­gÑ¿gËSo† j÷ÛÞgµ2žÍx='†Øí9?úº6ÚÏÁËýsäò]¢ÔBuŸƒÛ÷çÆè£â=#T<àñ\Ù¹õ `ÎWèÀö\¹ÉÕú¨9L¨ö÷y˜À}a¼üv«žÆ{^ÕŠx!Hú…rL/´Û¦¶suƒÎ*äØû%rJ¬ÑÜs¼ï}V+ã%˜Ý~©ls®´™Î{ÔŽBjð×”ðRÜ¿<¾øcPƒðÈãÚÈ¿œ›îËckÿ­÷šC¨®Ô—ßE¯‹‘ˆ_œ»é½¬ ÄOHv"Ÿ¦ßþP2¤*ô]ÊFG};9¬ì”ƒîl5wPAö¾«ÍÈ›”o–al%|ÀžB-t‰ÞC…Öû\+T³É×ñ›å”Z·²ÎÂ:2Éaõ›åG\8¶£¦ŽDºë¼9>ß Ùd}¡:%oÆÛúÛc§õþjrî×Ò¾p³LN»ÃWÎÃézPK}3«)®Ø¯ŠÝ䞇^ÖŠù%l©ß.³ÈnªˆzŸÕʸ—.}ë9}›µ›©$]‹ÇhLu}ëy˜&ÄgzçR®zv%æG =Ô.qþe(,c_vÌ÷Z&ÈÖj‚Ž¢ù?ðY}û¸‡ÍõøûÚ¸rÓØèΆ`킇×J| |C¢gY÷0xøq­¤¡ïвvÇÀ}Õ}%íy\+iÄWqI„Gõ †ï!å=úºVÔþçbáÎÂòôÖyßßý¨V˜#¢¬ýå§:ƒÑU^aÏ«Zãž‹é?LNgë ‡¼øøûZa‡N²g­wNM'gòÑ×µ¢&²ƒŽŒ){´“¢ùÐËZ1Gâj£=†òýû„çíôu ÑwìÙö§GY äh;ãztÒH|XkÄC<+¦øŒTÕÖJ9«'ʪ‹O¯Rt3b~[+hÍ^QVR¦ÿ3VcÞö>«•±öçQÖér~_ídm:÷>¬•r ›óŲžßò:7üžÇµ’^üYÄ ì…Éw³ÆUî}V+ãÚJ,CŠJ¢ŸG˜{IÑOd¨wÝú(ëMò›žaƒ@Ã~àQ­„WO‰²Î–Ùõlt³¼~[+è†ÅQÖÛ¾×w›é “ï}W+äõÿeAZªlõžWµ"nú½Iܳa<øÕJxÓ QÖº˜„”MA—`ô¾·µ‚ve}XŽõóu±¿ólÐEùï¨éçW¡ª…¯ù¬¦Ý2½¬ó‹Œðûe”½#eP+xèe­˜÷ïÏQ~:‹ ¢½ì(æQÖ'Û´zY+æ´ù_wñýÊ]:Rÿz8öXUmØ£ñdŠZy¿rÿ×Å=[1Wªè~RKÿ1þ2>Nxª{¦‘1µºu1ju|r]”uu¼<}™ÈF†Ív oÔª¸û‡ˆ4¿tC3½GŽôëÚ•üæëÐãÁB~¶ûƒfH¶4{•D:êù ÖM?wÆ÷7“(ɘbÈ–tÔòYzóHa©wˆ¡äŒºLJµœ({×3ùoòÍ}jÊæçÎöÉ®ï²÷>}†® ´d ·®ÜRëb²7å ü*:ˆ%Ë=Ó´“k'‘䀩è—ÚÛÛ€ öž4Äu¿Où'\eÏŒyË~櫺4=¯Üïþʹ èpV7ä&ý>Hì+ ÷ë™p€ù,°Û+ù¶ øýC_Ü<<—ˆwryE4n¸jŒË›óÔUQ«“õôôÀµi‹‡"Š:"t0£—òu ÿ7G)þ6G…QAt¨‹wþí=5Hnù„WîMщÑK¢&²‹“þ†E1éŸ8’QL¼óÌ|e“2`c;韽åg¿ãÜWSd”ñü'þŠùM¢ë£Æh|óËü?ØE Ñ„È(øúŽb€9Æ}ÉT”H¿ËBÚñ½¿Qü?>¨Xú†Loé¿£ž§?{õâg—¿ ¢˜å”ýΉbH~"ÌG§?q¸£§D“m²ÃO¤¨hw9 2F•ûY&˜¶Kþ㨺8ŠÙ›bÕê7×Ñ€ìoiTÅü)QÀÒŸ´"±‰ž½(‚Ƙþì¥1ûõœ–)Ñ Ü7×ÿéQL§à¿ÝME^r? ­,à[Àÿ§m¬f?þâöödgj»E‚Êr-äÿS¢y‘@ò¹vcI;EQŒØb£M\›ügÚåù¯ÿ©ozÃÖac=–³bßÌn£Ûˆ¢y»ïÎÿlFþ難ɭÿg+wþgÔß=ù¿³nö;ßl¶"ÛŒû<Ûb˜íO¶›hR&?»—0šÿìw¶7{œÝÍþ…KÇÞc§°ÃØü‡¸mú@ý}Àýw˜®àM`‚oAøýÜù<þûýíÿg—ûÿÄùÏîöÿC>þw¾é̕ƞöLî¢o_\9Zh|qÖû³ÞÃÿ·¹p»pR´OÖöæÁY¯?NÌzHìèh|ÖëA¥'g­Îz} oψd–õάs²àOê‡Æ•Ñ+_ÃËY«¢"*Û-ÏzUV7‘­ü¿”¿gñý,¾&kEVs4&«%«9ëD¾ž—µ,k9±ç» gÕe-ÍzaÖK£ú¬eàµí¼8'k1/&ZC¾•Y5Y Y ³æñê ¾Vf½ÀÕÎÿÓȲ*k6_ggOŽôVÇg=?«<«ÊÅVdÍà븬R¾ÈtTÖ,ÞŸ@þÓ‰.!v|ÖܬQY“È0'k,‘cøj'þ3Ñü¬Ã²ž›UÄÿŸáŬ¬ñ|ÉÿéYc²ÊÚ?krÖþÆdíÍ«¡Y{òr’{yˆ«|XÖÁYONÉz™u/Ú²žUH¶¦¬§ò:qo²ò³r³ž îg²²xù3Y{ñ¿9úMÖÓyÙU <ŠþLVnt‘odåD=YO‹îŒ~ÝAü¯£ñõ7¼þ±¯DwfeE¿pÓóµè;|ý‰Þë{qôkÞÿ©«ùg¢ïDßäëËÑ÷£ëùÓ«èzþÿzüZ‘/D7F7G_‰®ÕËèêè¢/G×±>Cü·ùû5Þ|4ú,ß¿}Þe¼+º‚¯»Ø¢¿eOÜE„7t‘_ ßû£+‰¼4ú_¿}R™ôÿÖècѼ}cô.þ^Å‹—ðÿ-ÑêèÌè´èUÄ^ÄßÕÑò(Þ çò_“¯-e2™7£íûêü¥èòèÓT{—íC]nÌ>üÛ(š ï2F³RûÇþ=;«3keÖIéøþžÍÿËÙeÏeßÙÏÿ*úø{Þõ÷QõÇ® nЧ^¸˜}ø5N§bƒ –À¢îFÄš¸5»¿¢ýõçJ2«Ì ®1C¸Ä åÍ0®0#¸ÀŒAŽæê2†‹K×–x;Áþ&º¿I ÃK¹ñM²¿Ã¹«Næ*7Ëä1ÜÝær%>‚›ñ‘àÎ…\ÛÙù³¹F.à²y7ºã@¥Çƒ^NŠNçú¹$ë î¼KÙî'p•\Æ tmÖÁ\ô~+«•›äÜZWpQ^½9º’ûóÑ٠ʧ€Zž½ K7à§qWuýz»8:+ëHî—ÏÙ¼*º-k6—hßµK³æ„®}5z Ñ×Až­‹Þuf-ŒÎÃ^”Õ–ÕJ}fVCtNô®¬v°íYõYɬEÑAYuàlÿwpV-—'ÿwˆýšµ$«†ëù¡ÜÉýßþ.Šš²óeÖ‹³^ò}Èö)YÇ€WdÍŸ–U j]šu H÷‡bñ.Êš–55« ${LÖ윬 àÖ#Á­³À´3À­Ó²Š³žçíd°êDpéÐêÁYfJmËÚ4»?u?ÐìȬÝÁ«Ã@¶­àÓÁY»f ÏÚTÚ?kgðkˆtZÎÊ¿@©žQOtwô›è.°æ?F¿£þ}ô‹èçÑíÑÏ@£þü+ê_F?ˆþÙaÏ?~)ú.hô‹ÑMsþ!hó¢oFÿÚüÝèZæo‚Bïe~ÚaÎOF}¬ùñès Ï_çÝ} ôøA0ßÀï‹.ÿý"ˆò6àÏG]¾;ú@$dø®è½Ñ{¢‹¢wGFDçƒ0ßæ|Cô&pæ+£×Gk£×E¯þ*:„ú’èUÑPç £—ƒ<¯Šº¹y\uE/‹NŠVFíp#69VÃAÜŸ gál®Ë's‡žŸ@o´} Cìs·¿uß6û[d×ÓÅØ³Üœ¾þšì¯ŸýõÏjKc‚fÐÀ@¾ZøhLç‹ÿC@Ãù^Äÿ~Dó7¤0˜ÿ¼\^Æb ±—ñô0*JðbTôެ&¾Æ!Fñ~ ³ô2¢£øºxcÖ‰\«Öóbþüþ>8«žÛÔÁîÍþìú;²&óm÷÷ÄhQö¸ý»ƒùœÄÿYü=CßqEôb¶ô®M«ÙÁ«²ªyõ ¢vß>•­úl®JÏNÿiãë¿ÿ{Žý=×íäçò÷¼ôßVþžÏß þÛ]}*—§¥lj¿¥ÙÑÇp‰bCévs×^>„ëÑxÛËÙVÆ.Î61{Øn`v/›·së~5º­ë²sÿ¸ßþžÛµŸáÊc·mç¦ý¨Û´vÏúÛ»ao¶íúÓѹ ¥7Š^nz-Hì5lÚWEg…më÷ì ÁvÛÝ–õöÙ ­KÙ²›ÝžÝr[çÐÝZ6íjÞ¹ µ• ¹§‚îÎó-ž<…¼¬x"øp ¸ñ8ãB¶ò|°æQ ʹ`Ë#Á›3A¡SÁ¢S@f‚ZÇ‚b÷Ѷ‚r€…KClo³¿¹Ãú™Áþ¾½¨WÔcgcC¢kÊmÒPߘlM8ýFYwnsŠ‚‡=·9•]Þ‹›fúc1V -¦¿øaâ9\üú®aÙ^±Ï•k³¢agíßÓ}*B;W¿‹ÿ¿Ìÿ?Š¢Ó@ÛaBl‡)³ÎÕvÞoçývÞoS\9¶‘2΂S£FÑv÷oæŸí̛ؽ»ò„Þ4¬EHsŒ o.ɉf®%N^÷fD79Ú»KE ¨U]ª×Ç®¦;ÈuL9]ÍÛÄVDÃ'v½=*:nñ°É]{gÀú2þ ¼%9•Ä)/;ü#Ÿ™µ¢¬;Ú¹ªûY—u½5*ªêΟr\’œ—þ®hϪb#÷ü@,’ù§ö\sÊŠ=?0ª¦®ª+~?ïvºøÄ5YêY«úB/ü»WÂغëÚʵ°PèÏ ôŒ¡oôcBn´¼lõS×i–VtÓ»ÕQQWCÎ…sºs¾¿¾¦“zzÎêæ:“΃øí‹³rgFOm|wïV ¾;wóßçÝøÁwSx×<ø.žítûໄwŸ|WæÝ›ßÝ2ø®Â»z¿y·uð]ïÖl~·tð]ïfnÎ7zó»âà»æ™ÑS~8ønï>3ø®?ïn|7€w7 ¾È»kßµðnËà»A¼;gðÝ`Þ-|7„w“ßµò®uðÝЙѰ»ßµñîKƒïy÷©ÍïnÛüîÆÁwýxwÍæwõý7œwõýÇ»úþÉ»úþÛwõý7zfT°iÿíÏ»úþûúþË»úþÇ»úþ;ˆwõýw:ïêûo9ïêûoïêûO¢/•MûïLÞÕ÷ßÁ3±4ÔýîÞÕ÷ßÞÕ÷ß¡¼«ï¿‰¼«ï¿I¼«ï¿ÃxW߇ó®¾ÿ¦ò®¾ÿÎæ]}ÿ=e&~úßMã]}ÿÍà]}ÿMç]}ÿÍä]}ÿÍâ]}ÿÁ»úþ;’wõý×λúþ›Í»úþ›Ã»úþ›;gÌàÂâ¦ý7wõýwïêûïhÞÕ÷ß1¼«ï¿ù¼«ï¿¼«ï¿cyWß yWß‹xWß‹gF9›ößÞÕ÷ß ¼«ï?ÞÕ÷߉¼«ï¿“xWßKyWß'ó®¾ÿNá]}ÿÊ»úþ[6^T÷»ÓxWßgñ®¾ÿžÊ»úþ›Ì»úþÁ»úþã]}ÿñÎì¿v ´£–о.3WsGŽ©–#¶Âù»s˜ýçÞënàÞ_mx›ãø™ØØ“#­!¾j°G£xwkÉbå‹/Òûhl­-h'~ƒâÛÞèꉻ‘´ô¹Oêùy.9Û»a6o]¼¶rbmO¿qKÚ–d÷·6b-þþ¶v)÷8r(6¾›{žÉ';MÜÞ¶ædvåF¥e«£™®¶è­…ÊMísè ßWsÓšLº«VþöÜø¾·õ9ÊqRÏíºYéûKʧ\1¹ÚJ»£áÊ«ïu¼O¬PÚ};x$êôwCßcWßxõÀôN=jÏéééÊyzKWmÖY%§EË©áÎÌñooÓ½0›‘¿½iSÿÌ-MýÓûÏ ôý<_O(ï”óÚî¬hMÉþQw×°œ /ãnzJ·i=4&ʺžsÿé·.³‹ÛÖ‡*‰†[ µ„V‹¡™0Âbˆ«¶mC“`¼ÅÔh„Å—ÉC©`ªÅPh˜i1Ú-†ÿ„yÓµ4*-osr(@, ±CÛâì[g1îÐ;ËcAjtn ïn±w‹ù«½Cb÷½cLo5Ýe1¤Ý¿l1T)¾’‰Å•™±ïêˆ[2õÅ]ÖWéyÄkBŽC¾OÔq³õéxb·…اBìK!ö­L,) ±É!¶(ÄÎ ±-!vmˆÝb·‡ØgBì+™X!7ÄF‡ØÌ[bkBlkˆ]b~^‰ÝbŸ ±¯gbÅCl|ˆÍ ±!¶!Ä® ±C,Ÿ¿b˜¿b˜¿b˜¿R˜¿R˜¿R˜¿R˜¿R˜¿R˜¿R˜¿R˜¿R˜¿R˜¿r˜¿r˜¿r˜¿r˜¿r˜¿r˜¿r˜¿r˜¿r˜¿r˜¿r˜¿J˜¿J˜¿J˜¿J˜¿J˜¿J˜¿J˜¿J˜¿J˜¿J˜¿J˜¿†0 aþÂü5„ùkó׿¯!Ì_C˜¿†0 aþÃü5†ùk ó׿¯1Ì_c˜¿Æ0aþÃü5†ùk ó׿¯)Ì_S˜¿¦0MaþšÂü5…ùk ó×äçOP³é¶L¬ŸŸ9)ÚôóýæÝÙ™ÜýZ,v"±[2¨ßÕ|Öïk“ŽI?·x÷Í –jŽ2ïšs3ùšw9|樓Ó<Âb’o.9<¾$¶$Ä|ϤØÓ¼ØÞI/©Ùïé5¯ ùý¯Gú_~ hpMPXϹÚ(À+¢çSä6QäVP¤_E4 Š´©ˆ²‘ÞéM‘ÞéM‰Þ”èM‰~”èG‰~”èG‰~˜ÿêI‰ž”艑 QOÊôDÔ(Ÿ”éA™”éA™”éA™TèA…TèA…TèA…TèA…TèA…TèA=h  ô 4ЃzÐ@ý Ôß@ý ÔDQ#õ7R¿¨"ÑS¨¿‘ú©¿‘ú©¿‘ú©¿‰ú›¨¿‰ú›¨¿‰ú›¨¿‰ú›¨¿‰ú›¨¿sÜÚû±Çú¡J×O*tª¹>Xú1Ïý¨©ß¥å±ÄœÑtÉcÅk±æk ±Öb£C¬-ÄÆ‡Ø„›bSClfˆµ‡Ø¼›b‹BlIˆ- ±e!¶"ÄαsBlUˆ­ ±u!¶!Ä6…Ø–»<Ķ†Ø¶»&Äv„ص!¶3Ä®±BìÆÛb7…ØÍ!vKˆÝb·…XØ·‡Ø!vgˆÝbŸ ±»Cì3!öÙû\ˆÝb_ ±/‡ØWBìÞûzˆ}3ľ•‰ÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿé™Åòý‡ý‡ý‡ý‡ý‡ý‡ý§{fË÷_öŸîœY,ßqغf±|ÿÅaÿÅaÿÅaÿé^šÅòý§ÛiË÷_ö_öŸnªY,ßqØqØqØqغÇf±|ÿÅaÿÅו7ï, ŽÎ_sƒ ˆãŒÑŽÅ±ù‹Ù,Zæ¢xÔE—ûZvÀÛRõ ¼Ï닜]uW z„“©å¯3µ˜¬mÏ åHŸÔg¿x96Ù6àÍsñK[wfvÃ)ÊûÃ5=?4.ö.q¬ ¿žõv¬§Á™†¯_aÕw áLÇâjÌ_MïGÁq?ÚŒû1Aœ“¯Uò&v\ki‹;ò^¾ÅÕ/IçXUN:¯§gÕ{r.‰"žê±…¼¹/cQH%o.ZÏÇF=·~IB=­ž»!> üšÏñ¶¹ë䨲䴞â׋7¾íe1ÏâÊÓ¢Êî½¢BãeÏç]sÕâaGÂ7i­Z|ëÝŽ‡±G#ͳÞÍSÌä~=}»FýÒ2Sœ÷¦îýx«ÿ)\“dæ@o¶Fßqœׯ´'†«}UOãHÎ#êqCIwÂç(v-þ¼×ŒoNÏW¦%pÚgºùÿe.³äx$)÷Dß#x—èÝuµ¼êhq;cÑ\Oà Uù'Û³>Ð_]xöiéy.®…»ÓŽ# ñOÖÁ?Y%þÉØUþ‰ÑMJ¢g­\™qxgWSÈu·,ö–ç¤ÀCi <Ž»1>s+K¹'ìOóDuÓßúÈí¹$äöüb[CÇ£&ÏáÝgC¾{¬>©v ÿ¥µ Ÿ¥9R>ˆr ‡e1ï•ÆAÊQ­Â@Yìúï†ðnW†##ì’Þ…W²|þÞH¾{B,¿©ÆþÞÈ;_Õ»ÄßWõ.ÞµŽAq´Ç$uÚmÇ'O; Lª»Yºœû‡3oî¹ëÌO÷Üyæ¹=·¯#\ÅÞ¸ æÑUh7\¥Žpš `ˆí·ÄûH»iëL\m=¿ ƒ}ÜRu>z/LÀùg/FY“®äà³-ƒà4”c¼öâuÔÞۺì™k)œuå³.[õ…DÑÂ+ó§TLÎwýà]§^Xõrb/AW¡À¾•–ÂÖÆÃ?0 [÷ƒg¶­çôÓèÝvz·Þåûl¾;êíé÷.‡×§:b«ÆÆSΟjü)¿ÛàOy¾ü)Ë:x¾ü)Ï·‚?åw%¿óØ‘“Ã~š¸Kwi“Í&Žrdo¤‰›ä'^Ø7ÒÎ`&g—²Û5‡`œ­¹ fë¼7³µöùéÙ:£ôY—<#*ZPÊl­'çŽç£Sq@aU.±ÊÌ–Õ©`¾·Ö2«Ò!ÙÊžYí×3î|ÁêlÙߵѳ4[y9eÁ,¾Ïm– öz˜%c–Ša–Â,åü€tö˜+%˜??̉ç«1· K£wÜ–þ«(úûU}ˆ|SGÛ²çÊsÌnüŒÁ19ejÂÚÒ¯­~{Ðáè['aØk.ûÝÑvc·½œãx1ÊîÚ ½ Am8†âŠ G5w­; °äÞ^³§ð`ó¹==çäõô¤q¢áHÞÿîÜ•«>™]¸ª'»PÓã`å„Ñ}})FÓ q×}—~¨h‚\§~ÄÑ"°Ý2a»ž¸€ù}.z:s{©s×¥q]Væ¯-ðíü.c¾üü»f[Þ]Þ]k3Ê\î x聆s®IÊó£·žA½ÏDwI„×áæ×Ïò3u‹ÓýÕQô•wm™eaŽ™¡h{tl :Àä·lâ³Â=5º+Ê£Ü!í™+×%*=w5ç©Nм.a^çûy­Î)Ó„Ný(øÁrÃaœóÊ}Ài£Ç´µ×«žQ1«<ÌÇ­Ìl[à܆Ùô8”X»åÀÉÒüÀÅ]b3rñà.Þ)Ño7#Ì…ŸÔzo"¾?û!͈Ÿ{ÃQÊÎ[¤a_š]¬ev˜‹í̆…XK¯vSª•ÏJuNl{ÖE‡1'+ÛV4ÈÚÌg¥‡¬e£ÆZ]ØœrÞZŠE°ß¸÷ì]+ÌS¶ÓVØlaªs¶4?él1O~¶¨ßB²÷ö¯1ö3ôöY¢Ù!£µ}³±{¡W÷O¸aØÞ£Oî烘Ç8Ø7꜃Æ¡÷~˜qüú£mþÅ{wM: înäwÁu\™Üžh³1wµp °7·áw»û)33»Ž¹`TgÃúØÒlƒ¹MFuD6bhNlL-v±ó€Îgç<¼WÓäæðó@ ìqYþè+½˜oB|ã˜I´ö<îâ¢ÜÀîuß±ã'»˜Ù(D{“c¼qNØFOåQ¬·*:X½?¿‘Kßp^À¸K­ßÚÖ]óŸã0zì¹;ÚZÑá`ùÏü“CîÇ*œ!3¤2ðU6/”)ŽéîÄrÈÖÛã[Ø!º¡ —$4»­ë䟮Éé¹ÛnU-ÄîWÌÞÌ.Y“Æ3n³ýí°}ßž»á‚4Ÿù©(—ÿ Ê)-ÅV§§¨wzÛBl„›E©S*ÖÆÿñiœCžÝïŠvs<›ÆR6IªØÄbæiUÀ)žƒon n>u Ø=Ÿ÷†;yêæK»Îöó—ßÖ»ŒÆŽæÊp€t/Ó6^÷ÅÎÔý·mºÅtïœEܾ}oá8cÝÒïT8À“­o/ì›q¯âúF¯ü^g9:Œ½"„þ±‡÷ žíµVŠì›ÿÅüC~y,üó-©©óܱî¤é¬Ð+v‘v÷Ÿìw¸yî …WjÏžŠà¾Uå‚q{Pµf椗 Œ³uÕ ¹ÃŠÏñçÐ~iÇèÐÞºì^j½õàê»Â¼š°ã*®BÀÏv1ƒ5Ž’1Â×XæÌëAã›uÙíÚQ9–fÖ4ë-šÕ—ó_Ì€ûá¥ßûƒÛvò·lƒÓeoC“pïwúv—ö–ãì,a¦wÃÅûîÞšs6 Ûp¥cú½•iýxýú3ÂzŒùPñ*"ýÓoüÂtöÛ¸asý¦—¾¯Ì˜îá×ý‡½}ý~ïÆGÏt½»c%æO/®õ>i\_dtT÷;ÛyšÙÝãÔÐõ…^ø¾àîD}ju~ãMÿ­/†3gú¢»ë̲彽‘WÚ›× öÆÎ‰í ýð½1÷ õFü™¿ïÃÕ?ìÍàtodÛx½Ìz¶õ=yí`OŒ«×úà1  ¸ÓÉë7Eas¨cLŠÁò<Ö°¨J_Â~³xý`i"´€¾ù«ûo'ù-}¼ß{Ü„ó½/ÂÎA~#Þšs§ãf‚!Ì N9Ûá©¥¹ìmj™ãRZ,ñäåÆhWaˆŒ&±LøÁîÊc­“ê¹_ÌÊÔ°C½ ;ÔóhðB³ÄÞa=wixçq0º ž+F­[BÌßñ°ˆÕ9Ãw„{ sçgPè Þs 8óíÝ+áÖî¹ OÜ`fƳ!Ï‚2gÄJâgƒ>z}úëñ½ó/{«ËîQmÖS¬ŒuöÔø²q=¥Qy£óD=|kZÏ;ÐÞP;ßâ!û›ò&§¹ÂÚ½Yy›åWæÞ<ã«öÞ™ó.ôŒó-7ºh`6Óó,{Ãm;{cssßw¹G\loàº7Ãio¸…»º‡¿ÉêAçÍç9Çòpo÷o†ðÆÜ3ÝÜȇɰ;-qzq?Öe>ZžÚIoð\ÛÐ;Cff,ÞÎÏeN|N,2qôlN!ͽ9íéÊ g¡7§Å½]9eâvoN{éʉŸ”ÞœæYwηoÏiïz]9qÚ›ÓÞ>»r¾c{N{?îÊ)³¡{sÚÛ{WNüPõæä¦YωOÈÞœ–cÒ•ÿ-½9-ç§+çÏnÏéôoòœs”œ„ÀPžÏÒy'Üirps©çàÏÁí¦žƒw>·ÆzÞùp+ê9xçsÀm¬çàÏW¾žƒw>œøzÞùøªçàÏ—§žƒwQyÊå@O²žƒw>‡ÁÝ9xçs Õƒw¾ðsë9xçsÀ®ç°Üa›Ãp‡»sðÎç€S\ÏÁ;Ÿƒsc=ï|xÇõ¼ó9ày×sðÎχÁ‰Ý9xçsp'¨çàÏa°ewÞ)Ç@å`ZàÃ]ß–\o´«¼'áW©ëgù4QJ3ÁïMr¨¤ Ô&M”8¥›dM×™M°ÐA-›d…V7ÝMøèd“n‚eÍc“lê2ñ,U)E¬g‰%(V̳äSŽR/QgtÝÜ,Ù/9ÚLJß‚C¨bͦ*æÀ³…³¥¶àô-¦—‚”9@\ÊH¢åʧ:/£_(£=›ºbÜ„=›+*i—SŒÐËÙ(¦]NobXd—ƒDPO{õ'LÊs˜”Ôž³%A“ä9\#PU{½Iè®_QU{.—­„káó5Öž‡Ë/”VžB@míy7ó­yx(åµ­z¯‹ãV½×Åb«Þ mmÕ{ÍÃóõ^<Žç뽔Ȟ¯÷bª=_ï5Wè½zpï¹]ñM¾å”ê z‡‚Û• …½»Rjmš+õ^‹+õ^“¾ D\ÀÏô6jDÕí*n#æ÷*®Ž(¼]…›¤üjü( öv5èµÀ<]Íœ£üv5. ÌúvŠGn;V‰ Ìïv1ŠpÛñ†W^nvP‡»Önæü5®C)îšÏò-·T×poC5î\bŠ\'^@(Ƚàoø’}óšÜ ÙÊE®/¤g(˽Pïñ1Ë{Íû‹èmõ´Ñwç^Äí®ÈuáE˜xE}n5™ÿ8‰A‰nLJøÖüïør¬J÷bJ‘ù1*(Ô½TÎeåÅØèF­î%ì»óÿ6-Êu/á Rbþ_‚µsTì^ŠnM‰ù){ E»—2Û%æÿ¥¸‘FÝîZf³Äü_‹;s”î®e¶J世½„âÝ˨©Äü¿ t†úݢ±³ù2¼C£„÷r4JÌÿË©U¼—ƒrKÌÿËÉŪü)öP™J*yšÿŸz5ßšÿŸ¢”ó¸[–™‘Ì*z;Wó­YÚIQÔÛÉ^.3ÿ¯`/¢®÷ f«L^Áµ¥½WÀô(3ÿ¯¤FT÷^É –™ÿWâ¾¾W2Çeæÿ:–5j|×1«eæÿ:r(ó]Ç›2óÎÅPé»ocæÿzÐ1Š}×3‹æÿzÜÞ Þ÷*zƒQõWÉ´¶æÿU04+Ôô*fU¿W£NY¡G¯†ÑÂß«ÿžoÍÿ«aW¡ö÷z\aþ_²Fùï5ì› óÿú„ à ÌQ…šoÏuÍÿ ô°Bm7 {:àk¹ä50ÿ¯Q£øZæ¬ù-xÕÀצ˜ÿ×Ñ_ÇÕ£ùÝc5Á×ãšµù=}BYðõ\­˜ÿ׃OP¼Ç_ Ìÿì=oÄËeóã'bõÁ70à ÌÿØ{(¾yo`þß >hþßȾi`þßȾA¡ðÌf#³ùFX¾¨¾ ·aÌÿ›˜%” ߤ÷šÿ7é½fcù™±]ʯùßEýÌÿ.êGÝs·Ì?oQ:|3¸ ‘pZ‹êáOsŽidþš½‰âOÃXjdþš>£†øÓà”Fæÿ-pyPF| ø;ðo¡Tß‚VóNÍPL¼IJ‰šÿ›Ø'¨'ÞÞibþo¢”ßÊ,51ÿoå.ªâ[™Ó&æÿ­Ô„ÂâÛ˜Ó&æÿmÔ‰ÚâÛ˜Ó&æÿmÌÊ‹o§×MÌÿÛÙ'¨0¾ý«|kþßNoPd¼™›˜{\Ø¢Îx3vû1ïïÏ¡Ôø”rú1?ï`Pm|ø¨sóNø¿(8¾Î@?ææÌjŽï¤o¨9¾ Ç|(:Þ‚jN?æå|yôc†oag òx‹òiNÞÍj|£áô¬™ºÜÚÌ<üyšÙ3¿Àm&ö à¸föËm\_š©ÿ6æ¡™}rû±™="û‘R+Õ·zÚÌ<þšäÍÌã/á,­™ýñKÌA3{î—Ø-ÍÌÎ{Ùcý™Ã÷2+ýÙïÃñ^ê~ßêø"ü¾óg/<ÜY†_¸´Q<¯á±b¯ÍªÏ½%Šƒ9ë+—l¸8²Qü²árÎWá® ïGmƒëÂûÙÖÜ×?@¹g~€ ¡²Ûu?Ôôß ›ûãé׆ʉ¤¶é‡t»Ñvúú¥)ûhB<®èSÒ×Ü¡{6ÂG¸ZPòG¨)¦Þ0A1[ó#ºhÚ™»LÌÖüeP/²_殌VÈ/Ó˜éÿåâ[}ø(“/¿FÑg^Ê·úðQ¶tÌ–¿“zc6źVh*ï¤ë1ÛýNÕ¡-p§iµÞÉ&™Ò;ñÅ3¿‚û@®¿òúxú>v²sI‡ q;)Ú Ñ‹ã·úá&Ž Èæ †ò§Òq÷* Ú·¸ÃàE2áeÐFGûYü¸¾µ’>®{¡fñã f.úäëã.~J, Mâ§tÕ$~ŠýJW>%×ïêÆ¯ˆ«ýµy®S‘)¥V;Þò²ÚPæ÷k2¬=`ì%jÛ~Z{F¨ã×Ùð¿îÖŠÖ<ÿ†2jÏüÆ®qµ¿q¢« ›­–ÞšÝg¢ô6›7æ4›7NsÙdò•õe?¿Áî¢/¿¡=¨YüMõC»ë·T£fþ·ÄÒþûmñÑÕŸßf·p]ûmP{ð·A9r]+NˆÐäï辫š~G<Õô;7Å}üÝÎ1¦8³MaºšvÇü~Wõhoþ.×x=Ÿ%Æt~V<4¡ËÏêJ(DõÙ³ãº>{¶ëäF‚ßNO„ùýžSÒÒ7luø÷tTE¿Çæ`Î_÷EUò•q%Ðê*y–¢é\›ß|3Îð9m77¨û³væŠß }þ‡šUú‡2›©êþðÛñ}^×GÍä4ßÚ&_P?µM¾03®é ó]—¦ûdž`§)ɶ²uå¨ßp.Ï”|A7Peü‚n B÷È ºq¶²ºq¦XݸGlrí´{Þ×rÏÛ\Meµ©ù¢ø,Bm_d¶ñ øÅOÇó÷G qæ?ºÔÍq–™ždÝKëøcÝÌÕó?vºeú7©_âÚÃÔ}égq=_úY'Òýü'ܘÛ?OÓÃ?ÛAü©–&ëOuÖ†ú3!Em’?“+BmÎ/Wöå7YºF¹]É,1Y2Fîú–MÖX_õŸ«ƒêÛŸ‹Ï¤êÿ\ˆT±?·ªþ¼Ëõÿض*jÔe!EJæQý@XE“ù`0&ò/P\`"ÿRnÕÍ¿”ÖÐö_j#j/ü¥NæÚ/Éeß~E¾ …à¿Ò×ý•79 Û›«›=aêN{[Ãd\Í-SN Eåh(ôÝý¾*ü«¾UýÖÜUû^}ûêYq®¯žå: V²õ—|§¿!öˆ2ãEq¦oàº:iéDÿ<(*Óß¿*Îô÷ã:$•¬¨.=KY^Ë•Öï›ô¼ß_A»ä›eqþo–¹ÊB~Wé?Èñ¢2ýƒ˜ Ú‹ÿ í£éûåŠø±©´Cþ,(ì´­µKþA¨^hì÷Œ+üÇc\OÌô¤[oÄvꘞlöS¼ðNCGßôR;䟜~™¾O«ú'ÜU«’²šÂ_à"‚5V/;1*ø 5ø¶u cJùë÷¼\­q*ß½¤³f‘‹RR½YåçfâfԊ奣&L€¤cÍÃDùóù¾¬¦3Qvm޲¿ð°°X”5{› \qßÒÑÅÅQ¶š’ÀÚŽå-ED¶¤:£¬fRÕûÕ»Ee¯Ý&¿å½÷>ýØÊÝ[4¨+õÿìÖš6Õƒ:ˆ"q= rRúWM%5¹Mÿ‹ë‹p¸¶¥:U/·á«—±9ÍÌ¢Áò»Ýäk_®!ßå}@ïÔú-ÐØrŠû1!Ó¢Ü5¥£ÇLˆrßY:zlqT°b‹8H|õ=rñ­™½¥–œÝó(kÉ’(g¼,XKÇ]-ËW—0ÌwŒÿòe¼= Ñó‹@QþGÚX³«iÈ;ÁDjå.:¡¾T:ºd<þRjê¯QV-z§óöÈ(÷K}* åñÖ‚âA¥cŠGƒäþ³ÈXòŠ€çŠ#¨ãˆ(kîÄ“W6'W¤ÕâÒ1£FcÉIŸ³£œ·lÒƒ)¾;.õoã͸ºtÌèbÌa}O:.Ê>ô½”(÷DŠhÇáÔ÷tÆ*O+ÂVû–ö•Qî+JÇŒ™QŸÚï,3öæõY¬(÷%DßGUû®û¦J¯¹Oɨœë°°ã§„ùŠ_(3n<<ÈùcÆSz¡tÌŰMJ-ëQÎ;„ߊ¹<Ôn(ó©s¸¢zg´\öò¢d'©pbSÛÒ(·€÷3£‚ÑEMnԢܧð@ /ÙV‹rþVФøTÞ©yËŠ4>Qî¥cJŠ£ÜÃø<"*ø¤0Ý©$‹³ZÝ‚®Ì?5ÕÐN3«É"ßþgß#%RÉSÑ ^ºñeᔪ¹ð8_½q•¿{ºoªlžÉ³?òÿe1–nt#ÅW<ŒÛ¢ïm…mѪ'VmÌí…T3cdù¡÷]¦ûPb÷ÇÌ}ôùYë*ÑÎY:Pv‰l™.Õ0®ƒÃcçÏÍ}À¿še8·ÏáºWévNÕºAw ÒQ¾Ý ªMÎÝz8üIWƒ?%Ôj¯e¸x!ºo¥†jZGÄíjHªFpÔ—°ßý÷ˆjÒ1ðÇĦ‹îLQíœym½I—âë…ý•ãçØíž(i/¹³£Fú'ÒÓ¤¤£ìöΑ>ÅðôXv‡v›ÓGú׿óâ>ñØ™ô1h™P/Ü$}‹ÔÓ‹yËÍ$}‹ÕÌg8yó–3JÚægpV}ÆWÜÛá[.+Õ©y¬–gp¡ÕoØæƒK5ßJVÒÊøÊ¬ anÕ9;—·ç‰õ »{íÉᘱeÕ¦ßÕ…)¯âÂ.Ò ¿ëLb›û€‡à']¶Dãƒr¤å»çD£Óÿƒ§›Žb>Wì×ÄÈÓE¨ó¤£Sûž+OG ¿Éè7bSïZ æ>¡Áª]*:Rþ«áwãùPJ £§öɘ×þ.Ëí³¢2j÷¥PG}~ötÌÞgáMþA¼'°ÛÞ «Ä(ø!Øê¨ì`}Î)ÙD…›°œu«ßñj¥|Žñ…xÛâ3¿ …ðŸ@“µz¾ÀT޻觞*dÏâ{(¶£¦/²ÿÙ¶b 9‹9òoPº£¸?|I¬Jñp:лxßÃóµŠþÉ—Åì´íÊïÚž:*ø2Z#.Eݼ{€°ßu‘è(àÏ¡5~EÒÚŠÕÃFž¿zèèÈ/ôׯJ†P ¨Gí‚v,ϯÃù†ÓHb-çg7‹Cºd«Ù¿žþ{ñ 5“÷P YO¬Öð÷Ìõ7cd úOtönÐq³ëÈýMxQÿè £2§"»Ñjw£Ž¹ùGˆlÿdÐf÷ñ©þÄýrÇý' IŠa³ô–rwK½´Z* ÈBÆüÿøÇýDÇ—ràûL©‘¨Ä̳IÍðC.nMFÍöNoŬšÔÜšlI„.1eRãÜr¬&5×´è•+xËF›ÔìFTÛnN¦ ×ÌrÑ&õúî·ý±ªE|ÈÙ‰‘SŽLŒ^È ‰™¡uõÂÍ£^ÍîÄ‹§—O]pt´²ÚÞÂñ’§ ¸l/®˜3cnÄævoat“W×¢‰—Ï›7w^T9ÏÞÂã­Ø[/®,›S1-jÐLМËÓCÙöª÷ü¾‡Ôé{H?|雟G›ÛÖ­_Ì ‹Ï®h®O%š;:£{—xD̋Ϯ„j³¶­ ?8°–æ$NÄXÎÚFT4m.¸†°ÅëÊui[²u§hVƒåBnmVÌ+ëÊuÌQG% õlI¢Þ¹æÈQÈunIt°V§–6s¥X“˜6§¨#q¸Õ‡î˜˜‘ÖU ûû0ö¡àôf÷dr¢©få’d¢®Ã ‚ž—Jµ'Ú’/íH6×&™$§Fɉ œ˜iñÙ÷(‚Þ·Þ;ÙÁMCUôÜHj¼w+MjØ«ÖeE‹!÷µ8—5wD'¢òYUÕ÷2ÞÐûηÊw)±©|3˜wï.x7yߨƒú¥ÿVEônçàaeÝ’¥†óSÕn¬¬M55Ansª¡p3½ƒxœÞûûy€¿èÕÿq©ï]‘°C¼S2øçØ;ö…wÔÆ;ï0Ýà]ùñîz{Çœ{·{¼»Å99eívå‘«Œšs§Û¨H Ž9†ƒž1¹£ùÄæÔ ÄaŸXÝÐ8EN l‘Ùåº,z†cŠº·°·y+â gÔ§ZO„†ùI{+Çjæ­Øˆƒžá˜1Yí°ÁÙóâ%zFLFZ^aoÁäCqÐ3DÌóÂ'¯TA=Ãà¢cÛì-®4x+½,ÕtnC{KCÚÍlnòJAy9°d5¡îK½Ò+ô ^Ž«ÿpo{ O¦ 7èÍîµ]Í[ð#o¥ŸÃ\¬­…܃ÃtÞý ½•ˆê]W× »£{Ëñ‡zűôŒö†&wÏpoÑ' ¯Ô$=£‰‰\õ\ioQ«à­t¶¨I <Ë‹ú½²‰z¸z“œ¾E‘•¼RbôŒ%ôž;m™‘ÖfmCî+ÁyÏÕ´9™ yQŸ ^)[ zWHFÍ¿E”¼Ò S¡oeyÑW!¯t4Oö±Ÿ5éC™·R˜ô xM—†šÐ^á­t„L½á-+žzu2U^7Pî-7pòêº<è\Ï…wåßr1"¯îƒžQÓXÓ*ÙP÷–ûJ#o¥>`æâ|7Òªqï=rKÓLu ¢Ërâ­Nùêq­œÖ™}ihÑ+‘¢ì§Ú[8¼•B‚zÌÛ¿þÑì-oú(Í+õJwñÍ\–Ü[Ž"äý„ÞnlP‡Ó·¸#¡Ò†Ð~6½x¢½eœÉ+õâ9Íô<}Ë©—·ÒôŒayJÅÞ¿eLè…TiØë’¿_³·ìjꕪû‹½×ï9ö½ÞJEy/ÒÛÓgÛMî7 ‘M=CÜE—Sj?¦R+Òœ­oIFO¹ÔÞ²R©GŠvnŽÚ=¦æ L^é3)ï%1GÃÕÊ:¢VéÖ±Óû hо~ÈöÏaÇp±â­4èÌþáí { ²â­ø&Ê«CŽ/>/÷oö«¸*&ïZ-.÷ÕnÞêîfßR”{‹ÚýÓÖÌû–èôR_/— òŠàwètŸ‡äý%·³/®Á§sË}“yùE½]ŸªmoÌÌ&ŒÞꌩ=±º™·ä5óbYõVJCšéM¾V`&}N™™—M¡¨Œ0Ò R644}ŒS½ÕµÞìVý»Ô-÷eaz!UúË…K²2ö-JÅÔ%-"0Ð%\,ÒYCƒ„¼Ò•T^³°Ó·¨R0ÒŽ3ûÅ*tÚ·8@ º)Y,“ãFnx+E_ûö‚Öôn‚@/¤lú¿9ì tIšx+mC³¬]ël¿¢F¾î†Þ«0Ûæ4?Z¼—2²Þ«8û>Í“ÞKÆÔ~‰[,Åô'{êÂîõKR-î=*ü¼?Àbû~àIöº ;@jd¼ßÀ™.ÝUzcv‡r€¯.rÇ÷Võ˜ùT}fnp몸Ëkì=„Þ«?övb’ëràÞ«§¦nõ˜]·¶±4ëÞj&Ì[͈ê~vM ‹Çß05Oæ­æ‹º¸ø¥y5‹¦_šM[3ͽE½Šý©¹¸Šwq—3ì-0jÒNÐÛK›õÚÏJåôQûDí’ŽæZão¸÷¨o0_ÚGàSŸ`à{åŠÚ´ÏÀ%æè1ÞÞ¢ÌÄ[íBó–›G‹½EQœý¤=j÷ö% )®LÏñu£wÃ{ía‹]:Þ£NmÚã?®oLÏŠà¼ÕþßÛ^ß–~k”¿õV¸A=qÝ[nÖäÞmJrpð©Pòfß §¨&á6)Pè —Î ªÝäÆa—lnL-MãOtÙ˜!a#ÓK©G\õ寶÷ÂQæ½p•™÷þu§Û{Ôæ˜má2ÛO¶¿{‹Ö˜JxŽS "ÜgÞ º^gs61s/ìhö›xpƒiߣFÍÂf6Mº·Â§f†„W=c9ª"dîµ&¯p®ò"7’å….G^ác彨d­^¬èd—¾.ݲMͺm«¦Wé[Ô™OÝÄ V5¯Ý[ÝÎÍ è–îò2`/]y‹½×ÝÝìOÝáÓÜ£¡9÷ºákÆŒV ÈRÎ;.JßGÑU#‡¼ÏÁv19|(±!‡8y& =wI4Ãòˆw`òˆ‡×’åñõ ¬Éî—ÁçyNC2ƒÄ{ˆ¤š&D^‡xÅKxE(ÀåB“\âS< ¾»Ë%†á@‰—ás]ÒêÒM!RÒ\âs˜™¿C7ìs›SmÉd ”/÷µ*ö¸!š½K’º1ø·h[‘[œwë2Ë/}ïÅG±·$ûþ0ÏA? L).‹ÅTäÞ¢¦À Å~ᄵð¤ÜÈêC£‹üâÓhw_¬¾EÑ‹!^Žúz>—¼K– iø÷h€Ñ±d}ïXÌißQ ã½4×|ïxŸæG˜]' î”–rÄ3½'S»V{7}~ôýÈ!ñŸÃ*ŸÝ5–åQv–4à|ŽÚù:àó‚ˤMæp'ÃK’–µ5p™\ø@Ì5‚ã¾È!§ >‡¦îÒ¤án“CÜ@S«ôé|¾L{Ns!mqæÂ’Ü[ôõØ%RâÔ[K>òwôùÈ+1îˆFãó=B½?ÔÌâê™{)ü8ÞJåSyÏmáyú•ÞJżE²Ç¿E9Ý,f‰½ohç’a£v¨÷Òèc?l¬sê9^zBüžÏHÆâTä`Ü[óV·nõùÒ¾·°Ýè³4~µó qË÷$ÁŒ%@ݲ㬛ãØñIõ^ÊËö¨ÝÜÅ"X’[ÎI²{ßtϽ‡‡J¿¥›ßû”À½‡›É¬ˆskoQz*4æ-Nú)Í?w‹Êò®§ÞJÏÝ¢xkø‹1LFtô¹Ÿ z†s£àÖ¼9oízJÎ…]§V„Ó¤âÐßrOt«ø„rLeœêéÛ8fÓw³}Ç™únµïö=Ú¾ÛìÛ¸­Ò÷ûžlßSíÛ8ùÒw»}ϳïùö½È¾—Ø÷Rû^fßÆÕž¾Ï¶ïsì{•}¯±ïuö½Á¾7Ù÷û¾Ü¾·Ú÷6û¾Æ¾wØ÷µö½Ó¾¯·ïìûFûÞUßdñ›íûû¾ÕÞßfñ÷Ú÷íömÜÌéÛ¸H×÷]öý)û¾Û¾?cߟµïÏY]÷XüKöýeûþŠ}ßkß_·ïoÚ÷·âïØ¹ØÑ·›ÿØæ?¶ùmþc›ÿØæ?¶ùmþc›ÿØæ?¶ùmþc›œ·ßnþc›ÿØæ?¶ùmþc›ÿØæ?¶ùmþc›ÿØæ?¶ùmþc›¹”·ßnþc›ÿØæ?¶ùmþc›ÿØæ?¶ù—#zûíæ?^gßnþå Þ~»ù—³Uûíæ?¶ùmþc›ÿØæ_íí·›ÿøšxÎc›ÿØæ_nŸí·›ÿØæ_ðí·›ÿØæ?¶ùmþc›ÿÄæ?±ùOlþå6ß~»ù—³Hûíæ?±ùOlþ›ÿÄæ?±ùOlî›÷Äæ=±yOlÞ›÷Äæ=±9OlΛóÄæ<±9—ë~ûíæ<±9OlΛóÄæ\îýí·›óÄæ<±9OlΛóÄæ<±9OlΛóÄæ<±9OlΛóÄæ<±9OlΛóÄæ<±=ŸØœ'6ç‰ÍybsžØœ'6ç‰ÍybsžØœ'6ç‰Í¹€Žývs^°9/ØœlÎ …÷¸ú+wÁ57'î•£ÆÙ9w¥.ö›«ÛÓîGáh{÷Wð°×Y Þõ&‹Á³ö|qxÕÛ,z‡ÅàMï´<é,/Ú;c…}³Åà=ßj1xÎïµ¼æ;,ù.‹Á[¾Ûbð”?k1xÉ÷X ò—ƒÓØ{ƒcÙoZ W°¾ß¸|õNDu?–ÓdÓYî’mL÷h9J¶1Ý®å"ÙÆtç–sdÓM\n‘mLgb9D¶1]oä:ÖÆtÏ“äÔ§\ÇÚ˜nür|lcâÈ屉7 gÇ6†»M?:£ÈÁ±áXÁÏîüüá<ÁÏŸ¸r&k]6é¢)Æö.üüé’+Dz©«ÀÔ±,Ü ?â“Ƚ¬‰w"÷Ä6&nŠœÌÚ˜®¸r2kcâºÈɬ‰#'³6&îŒîó6&ŽœÌÚž\üü‰³“xgPxfñó'&NâçO|¡ÄÏŸ..‰Ÿ?q?â+%~þÄkJüü‰•øùW*ñó‡‹r?â^%~þÄÑJüü‰Ï•øù÷+ñó'ŽXâçO\²ÄÏŸxg‰ßb=%~þÄeKüü‰ó–øù7.ñûOºÄÏŸ¸v‰Ÿ?qò?âï%~þÄõKüü‰˜øùO0ñó'^ ¸‰6&`ÁÏŸø~?â÷üþŸ¯àçOü½‚Ÿ?ñõ ~þÄÏ+øù¯àçOÜ»‚Ÿ?ñì ~þð+ãçO<º‚Ÿ?\¨ûù?®àçO|¸‚Ÿ?ñß ~þÄw+øù¿­àçO\¶‚Ÿ?q× ~þÄS+øù'­àçO´‚Ÿ?qÎ ~þÄ1+øùŸ¬àçOü±‚Ÿ?ñÅ ~þÄ+øù¬àçOü¯‚Ÿ?ñ½ŠÞ—ø]E?âtýü‰ÃUôó‡÷?º/ýü‰‡Uôó'ÞUÑÏŸ8VE?âSýüáÑÆÏŸxRE?âCýüáêÝÏŸ8NE?â2ýü‰·Tôó'žRÑÏŸxIE?â!ýüáÉÆÏŸØ@E?âýü‰;Tôó'žPÑÏŸ8AE?âýü‰óSôó‡g?âôýü‰ÃSôó'¾NÑÏŸø9%¿ÿÄÇ)ùù÷¦äçO<›’Ÿ?ñiJ~þÄ›)ùù7¦äçOü—’Ÿ?q]J~þÄe)ùùW¥äçO\”’Ÿ?ñNJ~þÄ )ùù§¤äçOü‘’Ÿ?ñEJ~þÄ )ùù¤äçOœ’Ÿ?ñ;J~þÄå(ùùw£äçO’Ÿ?q1J~þĹ(ùù·¢äçOŠ’Ÿ?q%J~þpƒïçOˆ’Ÿ?qJ~þð¦ãçOœ†²Ÿ?qÊ~þÄY(ûù?¡lóg¬¸ùƒ{P¶ùƒkP¶ùƒ[P¶ùƒGP¶ùƒ7P¶ùƒ#P¶ùƒP¶ùãþ_¶ùãÞ_6®®RŒ.“< Yk‡”¶ƒqöm JÒPÌqÇ@ÿ*ªeÈF‡°[_~àJiáÊxr^ôY\Ê¡?TÓ4²n›«Ö Ÿˆ«î)8ã<;Ú·ÈI>ê¶S¿õ8Ç ±´~œ®éé„Xß'–Þs«KW¨SßgGƧé¯çD  „³y#h=Ù !î³%Ù”ˆ'dsbÄ׿ßÅò˜ rbî4­'g\ÇÝ·^:NÌÀU§G{÷:ºÛ¶:Öw ÎɳíÓ}ºO©îR·3¹³cç‡è-™e¼F;x?h±9Àë‚Û;±4•œÖ’é¹ßûÌŠß;ôß;§%6ßfo 3dÂn†˜çð/–ß„%>WÕ-í÷œ×ÇyÝJJœùlƒ%ç÷Ð9¯ƒ£¢>ÛþàÑá!·¦'QìFŽ òë ¹¬Ö•7º¹gÌçT‡¬]ŸÅrƒÐãúÌõÛ¸>‹åàÂ9E‹ÕËÞœvÏtåıLoNz\ωJkON§Wr—_f¶»w™wΗ™¯zÞùì—zÞ9Gaf×sðÎç Aõ¼ó9à(ÕsðÎç0:uÝ9xçsOÝ9¬®Ía\ltçàÏÁƒz>|£5؃w>‡ÑìÎa²Ë߬žÃé šFÛ°;‡u¶ksªç°1“Ãpæºs˜w>¼»zÞùðöê9xçsçÝ9xçsÿÝ9xçsÀ;¬çàÏo±žƒw>¼ÇzÞùð'ë9xçsÀìçàÏŸ³žƒw>¼ÐzÞùðKë9xçsÀS­çàÏßµžƒw>|ÙzÞùpnë9xçsÀÛ­çàÏ÷·žƒw>ÜázÞùpë9xçsÀa®çàϺžƒw>‡ñ Òƒw>\ìzÞùð¹ë9xçsÀ¯çàÏß¼žƒw>üõzÞùpàë9xçsÀ§¯çàÏ7¿žƒw>ÿzÞùhÔsðÎç@o žƒw>šõ¼ó9Ð<¨çàÏfB=ï|tê9xçs ÛPÏÁ;Ÿ݇zÞùèFÔsðÎç@w¢žƒw>ºõ¼ó9о¨çàÏ~F=ï|48ê9xçs ãQÏÁ;Ÿ-zÞùh‰ÔsðÎç@‹¤žƒw>Z&õ¼ó9ÐB©çàÏžJ=ï|tYê9xçs ïRÏÁ;Ÿ˜zÞùhÍÔsðÎç@¯¦žƒw>š7õ¼ó9ÐÍ©çàÏöN=ï|´{ê9xçs TÏÁ;Ÿ ¡zÞùèÕsðÎç@Ǩžƒw>úHõ¼ó9ÐWªçàÏ>S=ï|ôê9xçs UÏÁ;Ÿ}©zÞùèSÕsðÎç@㪞ƒw>Yõ¼ó9ÐØªçàÏFW=ï|t¾ê9xçs VÏÁ;Ÿ­±zÞùè•ÕsðÎç@ﬞƒw>ziõ¼ó9Ð[«çàÏ^[=ï|4 ê9xçs WÏÁ;ŸݹzÞùèÖÕsðÎç0ΓºsXwñ6úyõ¼ó9ŒSÓî¼ó9Ðï«çàÏþ_=ï|ôë9¬SY›ýÁzÞùèÖsðÎç@±žƒw>:Šõ¼ó9žt¯ŠŽc=ï|´ ë9¬ q›=ÉzÞùèRÖsðÎç@ß²žƒw>™õ¼ó9ÐÙ¬çàÏVg=ï|ô>ë9xçs ZÏÁ;ŸÝÑzÞùÆyuwÞùèŸÖsðÎç@Cµžƒw>:¬õ¼ó9Ðr­çà]ßîgÑ¢­çàÏ–m=ï|´pë9xçs ¥[Ïá\p›hñÖs8Wä&z¾õ¼ó9ЮçàÏÁózóÄå@§¸žƒw>:Çõ¼ó9ÐI®çàÏÎr=‡sor Ó\ÏÁ;ŸMÚz§Ukr ³XÏáôMØ_õ¼ó9`MÕsðÎç€qVÏÁ»Ÿ8ìE»žƒw>úÝõ¼ó9ЯçàÏ W=‡Ó239Ð%¯ç°nm´Ùê9œf›ÉV=‡Óg69ÐU¯çàÏ.{=ï|tÝë9¬Ks›]øzÞýÄí0šuõNËÎä@&­žÃy709Z¬çà϶~=ï|´ùë9xçs@!­çàÏ7€zÞùx ¨çàÏ7zÞùx¨ç°®«m¼ÔsXçè} 8OFS¥žÃºð¶9Ð`©çàÏfK=ï|4^ê9xçs  SÏÁ;Ÿ ™zÞùhÎÔsðÎç@£¦žƒw>š6õÖÑ»ÍN=‡uPms ™SÏÁ;ŸzÞùhòÔsX÷ó6>õ¼ó9Ðü©çàÏFP=ï|xÅõ–ols ATÏaµ‰lŽެyçsôpdÍ;Ÿõ¼ó9ðÐQÏÁ;ïÌx=ï|øõ¨çà¯õ¼sŸ /¹Ûás¬»2<¬½.¬b±-ÄèŲ’⡱ù(QÂDî¥ø™hÛiS%BøB`‰Xª/kDjA‰˜r*¼ ·®HyrE5†ë'j0t@l„¢º%–DËñ±Û˜–ã]OÈj=:ÂGAáÞ´[Jó$Ç êÏ ! Õ?H×5Õ?Ø|¦ù+ÕKïñPïW2Ö¤Zו©7Ð!bzh 3KjCÌub«\`IųuR\Oë ë¡wÖ]¤<~­ºÜjJ[ÅK½U¬0ÍÏP1 5yCÍKèЙ®|1fPCŸñA¨<ÆLæŒpí…aW_Àï…K½€Ík¶ ©–FK´š¦®§+ÛLB-,ÜÚ £‰Z­ †-nh²ðiá¬g/`φÏ^À•Åwöf,n²ì œ<Âqeû´¸jqæhXûúáÌѰ¸õgŽÄ`¥3ÃÖÉ#ùÿÚ&Jn-õ…Ë¿ýpÃhó“ç¯Ë/݇o¹®x‡“ü¼ÃIúáNÒïp’-Î^#Æô°¥½›J” ˆ11(x7•(ã=Î%½›Êñ6ô}bðò8Éb ¥Éyf1®8S,Æ%ïp‹qñj1ØÓÌ $ûz¦ù€„µÃ´ÒNìvb¨Îã%•¬/ú@ Fûšl9|¦ƒÉ‡W~b° quI $~ЉÁÎÄ‹?1 ;¬VÔêˆÁ¸Å<1ØÀ8="SOäĘV<Ñc#áý‰˜¼r:/“௚—ÉÚ>4ZÌÕ°“k/¨¾¶!a×rÀ3®å+±²t´–Æp­øÁ5,¸ö‚)©ÕÓ·V¼ÞZX¼µL^­2ºµ ÅZaßÖr0͵:`ÖÖr€˜j9ÀfµlˆÚ ±µ:à¿ÖrÀv­å`ë q‘½€ÉZËa´ñ«/`©ÖfˆMV{µV=|ÓZØ¥µÊØŽµ0Gk/à‰Ö*ƒZ«ƒ[{a˜ Õ õZeÆ¡Aõ[¼–Ã08«/¸Ôú ³ödP{aÜ+T_¯ Õ0,kÕ ÕÆuCõ\ÉZaFÖ^~dõ¬ÇZe øZÏ`4‚ݲ ¡Ze°kYá&ÖrÀD¬õ Þa­zãÖ¢úÂx»¨¾€AÎ^€Òjû v`í\ÀÚ ˜µðüj(V_í¾Ú4ÀØ«õ~^íl¼Ú ¸wÜDz0íj/àÕÕ²rGª½àòR›rµÑÖ: û­ö®[­˜mµðØj/`­Õj…£V›riµ¬ðÏjÕÃ6«õnY-+·®Ú xcµY„%V{'¬–Õ¸„©¾0žbª/`wÕrÀåªm˜[µð´j]„•U{«60®j›’ÓeíŽoj¿ªVlªZ÷œê ãT§ú^T­Vã‚§úÂx橾0Ì§ê øLµ:`/Õzo­ †°—¸Of/Œ‡ ê ˜IµÉÛPm`&Õ^ÀCªmXGµZáÕrÀ(ªå€?ĵ*{[¨V+W¥Ú|Àªíï³7{a †pzjý€ÁS{_§V=ìœÚ ¸8µ0ojµÂ³©½à¦\{‡¦ÖEã2ªú~LmÊaÃÔêàWë=L—Z‡àµÔ¦‹‘K_ÀY©½€¡Â=:{Á…¾ööIm†àšpkÏ^À,©½€GR»Ö©uŽHm`„ÔrÀÿ¨½0½ª/¸VÖLŽZ|„Õæƒ[^­2.}µÜk³È•°V+7ÄÚ .Œµ9ãþXÛ‹\'k{‘Ûeí—ÍZVîžµ~p­Í7ÓZ.ªµÜ[k/¸ÆÖ^p«­Í=¾šk[‡Ûvm3qù®½Àu{­xu®Í"ëk9ä·¡#~ÌkýÀÇ^­g¸g®U³äÚ Ýý º‡[ö7y]Ác*Ó+e‰åC9ø)r¨Ë9Á}Á`¶³Z¸á×X \×¹¼›É›f×Ôâ äâ¶e‰™Ó'NO¶ØžjIÌÀÇÍÚÖ‰M5µKRµËÚ&†¯)Ë¢œo•Žå\_:n\”sC)¦Z 7–Ž;"*(•¾æøqcž?;²_:¾¡ßùãGE9¿,?:ÊÙ=’Ë“+ñVd‹u|ÊqëZ>eeö|>åö>gFÙ­Û¼Áå^~Ë£—&1‡"›Ã§¢ï®D+G&|>^'pÖ±Yö eCvY‘*AtuKGuu ¥XáÅéV&q¡ØÌö«óÖ\ÎË(÷“}i {$1jR˜\Â×S’µ|Éž¾¦%1Æ[˜•lkÀ.ìÚ:¾–'ÛZÐp][ßX³_ȃ“ XöýB-î“•Ü”´ÃPÔô§XK’ÏbÕ]É÷(}¯‹ò®Å»‰\ˆ$7ãB,é©ãc,}OŽÂÑLRMEÅ«ð•#/ÌŲ¥Š9÷´¥/Å^2Š3ôª°K]+CÙR×ÊPªke(×µ2²CëZäau­GD9cÚõbf{+c>«½•1?¢]¯l×ë~µª ¹Vô¯Uj•o`-ùŠÇ64/kX"9¸).cŽg¥}ß¾ˆOåØÁ§½˜O9²} Ÿ²ÚûR>µœ5Ü·àùV»á&>µÞʧvÃÛøToçSUÜ̧ªxŸªÂzÉu^q‹ó©*>Šç[Uq'ŸªâWøTãSU|œOUqŸªÂ¹ÃýŸªâ“|ªŠOñ©*þ˸ªâK|ªŠ?áSUü)ŸªâÏøT_æSUü9Ÿªâ/øTɧª¨:ÎõþrK|ª k3×¹É-ãSUX+¹ÅøTÖ@nqg>U…ó+ÿÁíÎÁðŒª8˜OUqŸªBž‚Û©ÂZÌur‹ÏáSUXÛ¸Åé¥c&P…ÜϦŠãøTÇó©*–ð©*NàSUœÈ§ª8‰OU!ŸÁ³©âd>UÅÁ¥c1À¬²gÊåñ>UÅ¡|ªŠ‰|ªŠI|ªŠÉ|ªŠÃøTSøT‡ó©*Ž/;Š*–ð©*NàSUœÈ§ª8‰OU±”OUq2Ÿªâ>UÅ©|ªŠe|ªŠ JÇ K¬ãSU¬çSU<“OUq!ŸªbŸªâ">UÅF>UÅÅ|ªŠM|ªŠ•ŽC;øT/æSU¼„OUñR>Uŵ|ªŠ—ñ©*^Χªø)>UÅN>UÅÛKÇjwÝ̧ªxŸªâ|ªŠwñ©*náSUü ŸªâgùTïæSUÜʧªøxéXí®»øT¿Ê§ªøŸªâ“|ªŠOñ©*~OUñi>Uůó©*îæSUüYéXí®/ó©*þœOUñ|ªŠ¿äSU|…OUñW|ªŠ¿æSUü Ÿªâ^>UE¥t¬vWŸª¢‘OUÑħªèǧªhæSUôçSU àSU äSU´ð©*´(Ø]Zì.- v—»K‹‚Ý¥EÁîÒ¢`wiQ°»´(Ø]SùTZì.- v—»K‹‚Ý¥EÁîÒ¢`wiQ°»´(Ø]Zì®ÓøTKÇiwMâSULæSUƧª˜Â§ª8œOU1•OU1OU1OU1ƒOUqRé8í®¥|ªŠ“ùT§ð©*NåSU,ãSUœÆ§ª8OU±œOU±‚OUqaé8í® |ªŠ‹øTùTó©*6ñ©*žÅ§ª¸„Ï#eÍy¯™‰(÷…íËÚ¢‚çõ?r–lxaW⛺r ŽMÇÓ:|yé8V^ùùªh‹¢:¥Íp2šµg±"K?ëË從gGDyŸ»OwºòTª=ONl g¡à,ë€+—6vÈþ3eD¹o  ™a~º³–ê,-Ü?½·>kˆ¹ôþ[/Ý6Kñ¸mGˆ¾ü;‡¥1tŽ'K€ÛÞÂ~[+¨NT‹ÓÔŒvXÑÕÕµ›û®ì ZÂÇ ¨„Cb§ÄÅØÛñÈm3ã®ZÞÍï(!­NŽ!æQÌÑG׋­A\dSC+ìÖØDhÿ ¦ÚíVxCãÞíZ½ÏÜ/7ªz DStàT/ŽL9ºêPÈQÊ´T¸0jÿígŒªZãAü‡ö I·éˆ[‰ Aù”jU4!1bj²õDÌw=ç°Dñèçõ<ÐÎâTžÖ #6!&Q<Àeï[àwÐàŸGû·£¡áo£87Ž„ú;Joíï÷w ôÞ§Ô2çHþúþøcÉùƒì^àÞskûÀA»Åý ‚ò:ÄþZ±:ŒÃ¿ÿ;RõÔ‡Úì@wgvD7ü]ª ý?Ìsb²%×»#{K&ºkÿüÛmÛñ"ù}¢6îßð"Ԛ嵕û#4UûŒTgë,YNû®VGÉþ¨ÂÖžØìè<,ЉùÜ€^?Þ¶wô„íÁ¶ð;ÀN¿|?óì¡QéíÄ>gûç 'jb=ìZú8hËÊ<ô³vN3³—:)-#«Tý-€¨í ǘ´ hög$< }ݚʆªÉ=ûM‡?"úŽt^ûítòo×Åâ.æ÷4'–#gè9±ŸÌ'ñP ä&(OÏqòXÈ®@¾Àt5‚b× NöB„ΠÇ͆Ö>Úú<èäÇ9¹ýAs[sbôD‹D}àg± ýA <É×<y£ó‘J‚4±ìJl³¼ ”“JYË·DÅ‘Hþw–ØÙ€Ø©Ñó€œ/E0îeN î"Û5PeVÄ’crÉ t+ý ³ÒNm¢kÇ0ƒLâBú¹˜ŽÏÌ@N¢'Ó…S™¼ÓØË™%õÍÕ)ЇÙi’{2qÏ]=y=¿é¹»ç—w±gRÿx÷M=OëÉf³ܓՓ۳OO~OõªÚûŸÒóÔž¡fÈ•6N%îþ~4½çéÑ1={÷ìÛ3¼g×»ÐóŒ»o¼û®z¨} ü BíI8!6„V÷ïÉtÍ|=•Mq3Úψªð…ŒG)ËAlŽb¼; Y[FæÜ k‡ò ¿ {mD$ z{ï’¨­§Dtžû':âÓ^rÔ/¶ÍóÜ„^Áüל&œÞs@´ºçèž™=§Œô”ÛÝêÅÑ«UËI¦¿—±k~*–5T¶Œ‘S4Ä3ëá9rDµð³Þ ÃïÄ%_ç„*E¼5´ºü'âÝ›$ár²§¾giÏ2G4£VŠÔeAtÄÈ—VQµ—nAõgcqWC‡ìü‰lív0™Ù5’(9øNdbßÏÈ×ö±ñûûÛ÷3½}ýÜ®áŒ~’øÍaºÁR#%Ñ×@"ß%%uŸÊû5$æÏÚ1©ñ0ÇJvøÏ€G^ƒ°úg0n°Äñ26rŽ5„V=Êx*ˆûrpÆy ×׃¶ŸF×.cƒ[DqâÑÏu›öVvê[ÙÔog/³‡Éñ#ÈÂ63’¼ïCöú›Xvxh÷j‡wA¾7‚3w€d^ Ú|B¹oAø¶ÕmW¿1íÛÝþÞw þˋ߉hú'`¿qùßDðþ³ˆðÿ>‚þŸÃÀç1p¦þ_ÂLÁŸbÌà˘<ø #| ÷bˆák˜kø:Fþƒ‰oajâ>Î1qVv¦Å⼬ü¬‚¬aXÓ¸?k§¬§fíœõ´¬§gí’5áj$8®V\´—«‘“ÚÎFßsc;ï¯âÍvrl'Çvrl'ÞÎl'r;¹¶C©Þ =úA#i@›¦ÙÆÝ÷çõÍ›ØÌþÅÑôI?Êù'‹YCxq4ù¸]†MîZyÒF’oþ©—S=0ÁçcVÇ›ôÙ‰t‡y/ãC°ß©ykgœS†Íwvs¡ÚZ{À³pµsÍÈœ¬ãËVG]UIê~øº˜5ß žl…^=¿»ð„Sv;ü˜JÖú>é×~Z4|-ò1ÛêØö,؉b«ì„ xñfâ ÄU¿íù6úozrUOiIo´=N‚T¿µ=Ý—©¡/ã­/£«jÕ—Q¾/Í]Ë÷ü}þf7ùMß1•®›³ïý6f­=wfÚ<.G9¸•9(¨æm\èn¦–u]žíkß0¶6KF‘ÖXÝçøº'=UãÒ®\ÍÂÊSvÛó%p¥ÿë,œÔs÷ô.ØvóW?³Pó¥9¸o-Âw¦†BÏmÚš‰U~¦œúŒúùQ԰É2itÅA'} é°¶]£¬ª(1¾ëBŒçIPf,ÜÊw>ƒÚ_@í%j%µf =ÿ`CÙê]gÊìЊ(6¼´µAF‡ŠéÝA/¶ÕöÜ–1á>hwvXÜÿþžmùZnÕÎûq¾÷þ¹¾®ïìîúÞ·óþŽô{æxMÏ5ݧ÷åheÄ̱·SMlà]Ä‹ÝëvŒ}‰XÑbŸ%V²Ø§Ô»m¯è¹­ûž۷ôPynÒL<‘g+½KûôY8ëÏùFÿ)߀Îfxÿ©?×sãŽz¶n»jûÛEÛßN æ–íïîïá’èi·j?°ce 2*iÚ`^ÿ;=ï‘vÍÿÊ¿®d1ª'ÖeToŽEähó;¨#ÇÝÛz߬ùÿO9Ùÿf'þ8ç5ÿ‘s™æ–ž·Ã(ûÑ<5ï.ü@^íâ×Ûï&ËæÍðÆwê¸a[oú=°ÿõþœí¹ç«7ì×~{kÆöá­%ÑNwÒƒ»ÉsÏ磫֦K† ¨cÕñÙSΙê±p|$ócÕÖlûíîûgzIô”[|=ÖÒ¸~ó®Ìg«ÑáŸGë¸ü‘:Vüv/+ÇÔ?ÌXcîr5\÷'|ßpù’'óÑÿ“ù–<™Ëà_ÍÍ×™÷ov®ç®?ìíŠöÿ¿ç¾éçfÿý{îɘʓªü5‡7»öؾœ»úî2ßÇíÝNÍ×p5ìêÏqë\Õ´çTæþ£›œ¹ç”î*áÚݾŽÞêþÖŽ(q;²Y®ÒõÝH›âùì)™Ùüýíz –0ø’\µ÷7Ú{‹?»Þ?tÿ(-~–J·çï±Xû:pÃÇèz‹¶ÚvIÑá_ƒUC;²¸íôo6,Øí€â9äŽtë4Xš'½¸'ÊìE¨} 9² ¨™? wç õNÞŽAs|WÌýÓ«ð5»=ü´ÿÌüühæ ÿQgfî¯ëícø'¯]æZÿy&döõ_òíüs¾‡÷_w¾©ÎÇNzh¿Êtî£ó«·ÿnßtç½æäåþû_ó¶þ÷¼Ñõš)B~ôv£ïÛóoØþÖÜÿ~Ü îŸ{±Â™ÂÅwc+æ› ‡C¼’wÂ+9óÀÄønxæ¾·ÕD“O9Ž‹Ä-Å#¹f$üC}oE¹ršã€ôòjÀ}âq¤\’KàsˆÇá¹$?àý¤y®þ—«ÈsÓqÓ·s1¸¸úpÏ}™ÜU{ê}œÛ³fq^”»™¼‹NÉG.ŒÌHÿ¯þÔó/%Þt#½s7¢w×£‹0á¸K&ß«jÄÑXµzV4 Á' ØH„ÐÜÄî7µ‰Ég¾ÒðÔ¼ÁM´JF[LÓ)Ó‘6—t¼Åàz’ÈrN¶<1oBT“µ˜¦_Æ$m žé<‹¡íã͉ÂC]d1d<½QQÄ2×X µ7Š&…7Êǵƒ?z½™ D‰á½“ðfüQË!í™”µï$Ú™Ün1¤?‹¨PÞ±™!Ç¢ðnEˆ­±˜ìBÚûkBÌ÷‰7…w·…Ø!ö‹I´´pKxçû'ySxµ1­4™gMsÈ0köngx·Ëb’O•ÖìÝ!v·Å¤<"s«Ù»{31™Xµ1©UȸjöΙÖ4±©!Çüðn™Å$ü*ó©Ù»M!¶-äÈû'3©6&E“ÒÅáÝí“à¬L£fï>k1IÓ–Â •ü IĶìw€Þ•ýà]¾Ê~·I·ì÷–u2ujsH0·öAÙïb[Bîk,&^gÙ÷•Ü~7/ß e¿¤NS}-û¾ Ö”Þ}+“¯æ²æ²âçR¹+aŸUBÿ*¾Ôáw ïv„Ø ¡Ž|+~‰}Êb:3UÂüUÂnðó§ {‡w“Cl^È‘÷©!ÌYCØ» ~ï V6„ýÑà÷‡TÂþkðûO"Ë ¾g¼ûœÅ¤+Ôö_£ßz×pC£ßRòiô=ãÝÒ;'Ä6„|9Vh û 1ìƒF¿¤gÔöA£ßľl1é"Éüjú®ÉïÞ9ó­æ7‘*éê¦Ð§&ß'Þ廹Éïf1|›BŸš|Ÿxçqï|Ÿxçç‰w~oI¯©éÎÌ»~Óa1‰q÷ û¸ŸÇdÄü“ŽR¿°ú…ÝÐÏïräsÖ/ô¯Ÿï9rLÖ/`²~“I@¼_ÀFýÂnhö3'õ©æ°ÏšÃ>kö»3ÂÙá]ŽášýÞ•¼^sèSsØ;OFoö¸wyoš}o$§ÞìñÞõ7s®&æû$öþa7ô÷»Ø‹I¡ªØaýý#¶5Ä® ±CÌcêÈqgÿпþ¡ýÃl ð³¥ÜüÞ•ÊÕ/‰yLIÌï*b~÷Kóh@À+<^‘:Ø€°ûø]%¥§~§òÎï*éš ó=0Ì÷@?ßäÈ1îÀ°GúÞãæðÎïNÞås0ÐÏ´ÔZÂŽlñ;R*T-av[Âì¶øÙ•JUK˜Ý–0»-~vÉ‘c¦?7Äèú`j@Ÿèûúm¾…û Ê:€úÐôtýÀÔ@jÈ»0­RK ùZ„5TK Jj-ÌÑ jÄÜ ¢GƒPÔDþAôg0u&ÿ`jLï3CC˜µ!Ô;„ëüæq5 a&Z‡™)b, yƒÄÄŠ!r4‡XKˆµ†Øˆbm!6>Ä&„Øä›b3C¬=Äæ…Øü[bKBliˆ- ±!vvˆb«BlMˆ­ ± !¶)Ķ„Øå!¶5Ķ…Ø5!¶#Ä® ±!v}ˆÝb7†Ø®»)Än±[BìÖ»-ÄÞb·‡Ø!vgˆÝbŸ ±»Cì3!öÙû\ˆÝb_ ±/‡ØWBìÞûzˆ}3ľ•‰ÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅaÿÅ—Äæ¹Ñ¯óÜC/‘#kžÛa§‹òÄn+£ÜÂgëæñ®Œ¸9…[ck\ë&Xx?-±¥®u‡ÙøBþͨ،·5éeÍx­ÛÉÞÓkÖ²×wÙcrMÿÖ/¸ÍÞSkîÍí1¨æÞ|ÆÞ Sçß|<6ÐmŒöèvX‘6X³Îüz¯uck¼óÙŒíî¼óÙzLd›w>G©móÎçè1ˆmÞù~àÝ9xçs VÏÁ;_+¼¯zÞùØ9©çàÏÁ¨çàÏÑcŽÛ¼ó=ƒoVÏÁ;_GéoóÎç`OÕsðÎçè1!nÞùðÙê9¬s›£Ç`¸yçsô˜7ï|ølõÖäºÍñˆ¹<›N]=ï|ŽG èÙг9ž4 ÷¨¹<îFÖäc—q¼f™6¦Z×Ϫ[/N£ºÿLe‘Ú3¥O¬«Ô3¥Û+ûVÏ”M0]±ž)›rº„m€¥„eó‹¸8c[ý"”n!QnÔEP—§\ðcêØˆkÌêb¶J̵ìbzSÓÅØ«Š¹X]ŒË€˜z.ÍÄ\ª6±1zð,”½&öY\Ä.›a“%ð87ó?¡Á›1¢•УKaö%€±KÉÏåñ2ÌL%ôè2Lh˜ŒË¨Ÿk䳩¿@=Ïi¸À=X á³a&p©|6—»²gcbª@½ÏF×·@ŸMϹb^Μ¸ž]ŽÉžu_›¯@/‡•Â…órø§æårôË ô÷r¸þr_Î5ëçåô§@ŸÃDP|[ŸkèsÈ]¤?ÏAQ–‹ès1‡ÅUô¹¨r}}ç:ú<®“\HŸ‡I/®¤[A1\J·ÂB)ÒŸ­`3–ÃVTŹžnŶX‘¹ØŠÂg=ç糑¸¨>Ÿ™ç磅WdþžÎt‘KàóQ åÚú|,Ý™¹+˜ã"×Ä+`mN¯àjÍ%ö xµ% ×\ÁÜ–¸4^í†ý¹ôÁ•öJf©Äƹ’9-qñ¿ÛQ\n¯ÄÈX‰Ù¿’úJôr5•¸fnƒiÉUwˆ³D¿¶anªD¿¶¡€Î¥½‰»å*P@‰kèU 3®¿WÁ(1WWÑÇØ«°ÅEø*Ì¢•˜¯«˜·{àj¶,âj˜8eúw57ì2{àj®À\ޝÆZ™9ÛNÿÊôo»†êávØeú¶=ë2{`;º eæ;æá¸4_«µÌü_ƒVO™>]þ)3÷× «ÈúÌH™þ¼@,Bõç0¸L¿€>•ÙS/ÀY…ýù̶q­~!V*ä|!̯ sõBæê…˜™â’ýBì‘U˜Ýb(®B_^ˆªv…¾¼4•ûEÌZ…¾¼}“ ½}&º*ì–±'¹€¿ˆY®0G;˜ë s´ƒ¹®°ww0×\Çw°·*ÌÍlªU˜›ì‚æe1.ç/æBÞÀúÅpª`j¾˜Ùm`½˜YåªþbåS_^Âü4З—£yy û©ù~ ûœËûK0-ÖÀœ¿’r¿M®ñ/eØK/…åÒÀ|¿”9åBÿR0C}z)Fᘟ—ráj-LÙzz-û»‘ù¹U\ò¯E§¼‘ù¾–ž62××’ƒëþËØ£ôëeÑjä’þ2TÕÙQ/cÏ4¢cþ2ö €—³,é×Ëa52ß/gg5ÒŸ—£éØÈ|¿Ûc°^ÎÜ62ß?E­Ì÷OÁ‚mdŸÿ”òj¾ ³_Môå§°ÇÖÄ\ÿø VÁÎgñ­~ìdVšØ3ðåaìd4Ñ—ìÓ&úò ðìƒW0ûMôåèK61s¯`_ÃHxöæšèÏ+èoýy%5ÂRx%L¥&úóJŒm4ÑŸW20^Éœ51?׉٠þ\§º”û:nX€®£¯ý˜óëØý˜ÅëÈ ÓázpC?æèzðR?r^ÏêÇÿë™qX׃súÑËë™~¼¹¼Ñž¾Š}CâUàÀ~ôëUô£ýz;©ýz=‚=ñ*ôæû1W¯†¹×y5û¨»äÕìu˜¯f¯öcÞ_ݽ~ôëÕô®™¹z 8 ÖÅkÄÔSŸ^C­Íìœ×°_›™§×°/ad¼¼Ñ .½œØÌž¼'Ǽ`ÒÀָ̈́fúr8±™¾Ü@­ÍôãµÔ“ãµÔÒÌ.y-ø®™·¯eO6Ӈׂ `y¼•ØþìñסÅÓüö:±>Ô×Q; ×Qcæýuôº?óþ:ökææuàØ!¯ïögÞ_OýÙC¯×ô'çëÑ1€9òzúØ5ó×3ýÙã¯Gïµ?3ª–EOcOÞHm°KndöúÓ§AúýéÓìØþôéFpöfþ ôÊÀ0PÞN@Þ@?°gÞHý°QÞˆç‡ÔýFðÌ|¿ `O¿ &),•7±Pÿ›ÀÙÀoÂ|Ì•7á0c;c38€=³‹ÞÂfÙ…¡µìÅ]ì}Ž"»Øû\*ÞÌ~Èœ¼¼6œoÆpá@zðÓàtØ/? Cu }ùipÎ@öß[H>¾¼f;̘›èó@fê­ôr súVvl™·Ñ°ôãm`™ÔÿvvÖ@æàíì(˜4og.ZØsoçm óp3s»æfjoa–nß´0§7Sk sz3½‡ys3=maNßÁŒ·0§ï·¶0§ïßÀÊy8·…ÚÞÁÜ´óàƒðÌ;èŒw‚÷[˜Ów¢ÑÂ~{'û¤…½“ý›ç*l¡Oï$ß zò..~0|ÞDÞżbNÞ…óX?ïÂ”Ë zv xký¹…·ƒèÏ-Ä`ÝÖDŸn¡ƒèÓ-ôc{äÕ§>ý ýÄ>ùr bž†¹Äüü 8&ÑÏ€W1Ï?ËžDï6Ø vïÏ2—°Œ~5˜9þYöË`fâgÉ=˜>ý,¹` ½›ÙLOÞ kt0}z7æÕ`%½›ûÆ`°ê»Á#ƒ©ýVNX0•ne/ f/ßJŸÓ»[ÙƒÁ ·²/`1ýûb0óôsà½Áôç瘣Á컟C †Óϱ‡3G?Ïžà”õóàÜ!ÌùÏÃ,†ýôóìµ!ôåç1Š8„ùùyêB?~úaFýõ¡/¿ÀÞB_~ aïü;ÖÔ/0«CØ;·QÖïmä†Iu8eó~w£!ôç6ö5ìªÛ˜Ï!ÌÄ{˜á!ÌÑ{Ôõë=è aFÞ£ú4Oï¡Ï­ÌÑ{ØÃ­Ìý/r‡h¥_¿h,¹_³´²»~ßÊ|ÿ÷€VzòKbÒ©¾÷‚;ZÙ+ï/·RßûØC­ÌÃû˜é¡ôÿýÜ©†‚ ßÏn(3ùú=”~œ8”>€ú‡²'>þJŸ?ð½Ø¡Ë~âîíê–³^Š˜K-Š› kÊ”«©zã¢|i:]TúÀ¶"c{³j‰4ö¦?ûyK¤/´¯f2; œ_d/äd£#‡6\Ç í«Ž¬º¶%LHþB¸5ñ°o¸nõsÅ0:Š™¶–´ÍU¯æ¯Ù21ÙuIQ÷·fG5›Î&ª]JÞ<7VŸ¨U§ŸáyX£¥ÎJiAÆ4³iæÇÊy‰e‰ð»Ÿ5ëk˜þäB½Àú'î5²Úe¦öÅY+1ˆ³º ÷]¥µK:—áÙk"ßk1 wè’κd}k/b¯#tAª3Ë«—tâOhM’íxù’NÜ™Ðæ%8 "Tùû%í5K1$vÎ’ÎÚeIUÎU%çu, ~¹¤³‰öÍXC8¯“ŽÁ¢ü}”éÜÖ(o'ª“•°Ò/–t.绲÷ñÇϯ:¾²+K›ñ&wM—ê³´ª£QßÉS^ÙZÓ¼ E†ñM><£¾5Õeÿ†®•.¡å+ϧµ¦ŽÏ¨Ð(w¬êÄ•Ùt¹¥º€OÙCZǧ|+]Y:·TÑ¿¦e~rGf_âÑ5þY¬ä|±›|ò 6Íû@ZÓP__Ý”lJµ®D‚e ƒ$£e×ú×’«_í_G û^/f“ü“ókÚÚ«ëS­+jZëp^[uŒvn]]k’>–ÿÉ?ÛÒЄ;³Ô*Qùƒþá%ÉÚTk]úaô-ÿpScÍJùRÊr6û§xCË‹)ªÙ¶MëR+ÒÏJeéR¨>+qBº)—ÔÔ&«SÍé§ñÈþ§šÿ¶ðÊt9Ú.[ª\~öúÕN‚ß(ðëÑÆvL ndŽÖJ¯ñéM¢¨ ÂÇ/mŽ_”»2ÓvÑ’Tc¦‘”N½.ÙšidñÃѧ =ù>ßëŸû~dýqºÔ-É–9™.®N¿Ã®›{•|»÷UGs üãË–´&kNôà^Ÿã_oØôzcºÝ¯‹_éÛ)ç¹×›3Ï }Ï7µ¦–¶Ö4e¶Åú¾ç²ù¶ž^_’ÉŸ\З`MCkûÊÌì¤ûÉ<–‡·ìéïö=•é·ìé»úžÊ\ötfßÓ-m¡ûÜÖůë{Ì$_Âô©YñWûrlLŽÚ,*jª91pGôú4¸´‰å‰;?+פŸ®m¬Þ4Š?í<«ëQþY%Ýïµ5M Í™S) +cp"[=éÒzVG²53qÅôvߢ¾¥…¬ëÛHyÓ é×4´Õ´µ%›wÙP}+3Ú‹—6%C;Ë5é­tq –û²&Ü‘®éâÐç©éMz 0ÈwòoÓxäÜöe™qŒ~¾áÝÚÎ!9âË :;½4§gViñï6  y'¥>ÏJñ%þýºdcUJ¦u´ÎohŠ ŽSo©iîm_¹²™¶>geS”ûrðáQÁ<œ´Î½ú°ØåÌ9 ä¬ê‡çØ]ŸoÒ€j™Šö“u"ÒÃ@H0–;ûÁ²ˆjJð÷‚Ažp¢çʳÉàÏ!N^—XªÉà® Õ òà!ƒ¶¦ öèPM s#QilNI ì-¢šàx=È„®m¤9QÔèxwüøšörQK ÆÆºÃˆø‘4j)t¸¹@§+qÜ£ö^‡®u±•#çêóu°$×9(ϹŠÔž‹Œ¹.¶ØÄsÝ6jÏÅ|X°VñæöQ{¯ [ç ŽG¹î$R{­ [gÔk]J¢‘O ] íõJÃᤳˆûå†Ãš9]’c\íŽþÐЬˆ’sÈ¯Š¬µ–ÿû3†Ã¬‰©ø²C|Ÿ™ð0†„ì!rRsÃÒæT+ýqo©›·ZF“š[“-©Öö(YÞ<\oédk''5Ëð¡ËÉq´Ÿ('5××´»©r¢(ðÍ8Ñiâ'ùÍÚIÚäCb)yU")‰Wâ¨lê…”K½:wN¼xzùÔðeVÚ[HÏ¥øð9ñâŠ93ÌeºyËV!¯N /.Ÿ7o®ѽ…|Ë[C'^\Y6§B‹ÒõN=ÔYt¢\îÖ{H~ßCêô=¤¾‡–Lœ™ÊòfG ­ÂaÑIº´»ÌŽ\wsÏ]fväŽIÀ„9·åä”j±I´…Ø<Å$ŠŒÊ€‰‚v >&ñÎ%ˆwΗxçvꪊwZÂëšèÀ¢òùÓŠ7¸¤”ºˆ5¶*Wê‹gzñ+ˆ»^tˆ3î @ ³C( :GÃà„,Q×öŸc8ýW—ËùC9ôÚÐý‡è¿¯ÿôÜ÷'Ÿô_,ß>”Cÿ§-Ð,œíë?=÷ý§•ô_4°Êw†rèÿŒ¡úoó}ý7ÕõW¨ê?„Æ’¡ú?shþã}u_ÿé¹ï?zÈô_´Ø¦C†rèÿ¬¡úoüÁ>ÔzîûÅ6ú/lÙ¯p(‡þ1´@ÿ±‘¶¯ÿôÜ÷¶ô_tæì¡úäÐýÇòܾþÓsß\êªÿ ošoÛÞßóñÄ 1ÐÿñE3–UTýv~ܼøîë?=—P‡ØÁÉo¯ÀŽÍcvŒhŒË‰CàÞœv¶ºrb±¯7§ÝG]99öæ´;¼+'gÚÞœ÷tåÄ9qoN‹»rBdëÍiñuWN\÷æ´7‰®œ˜ìÍiï8ÕœOЏòu ´$ºC£´W÷î_ÉÿôGf$º‘tQ¬$gï"*—fYŽÍ9r»û†[uÖF˜~eÍ»*(k¿¨‚²îȪ ,_ëTð7VÁßl© " UPÑ6Uy°VYÎS•â *7l© A7CUРª ä@Z4@v¤‚Æ1qc¶TШ¯ o ‚FùYWrȯ šœ=-¾{+h’ECUФS¨*h’3UÐ$øª ß.qývÙRBTÐO3© úÉ˸*è'wôTðm«àÛ[*hÖNTÍšI0çcUÐ,oðª ù_â šÿeKý\˜À^ Qäë^ ´}0ðž}à^v8w†ŠQ{¡›w‡GrÄj.¡a51%ý—IV{¡îÈ¡»t‡l¹µX5¬½Ðå9¯ r¬(¯Š=3&äº6»¬Ps=mr®³oiȹFzJÿ™ryY+ÞÎ ËZ yÔõÕt]ÌrY?© I0oGIõ5²/Éak¼7]#SDØOjô=±µˆBnÇ#ÜûÁFAæ7Äbä„ìëûâ Ç ˜Ñ1ÍØÄØ›â©³ägªëãÁ?uaÎïNôe¸A–0»¹(ÙY›„‚ªwyÎ3´-hˆ²o!z)±µµír}¸(c÷·^÷š—lK5.OÎNÕµÂòiÅHþæ¢d{MœÀ(ëd8³§Ïž‘"AÜîb‹ ‡DÙUWnWÅŠ(û5Ü6ÆÂ¥ÛÔ8jô»—7X}ÖïBÎkuá¿Kf ~ÉKéB’ýH_“Ÿ?2)ÉÓ™½dÅ#Óœ|ð‘ýüâ‘“ÿŽlÓ'×`´ÊÊq!Eµ@xë»´oYÝQ[•…lºsRÄw¸3U‡À¨~UP1rEèCß! ˜"ðqK8ºÚ"tq¤ˆï°8LB‚¦ˆF|MN™Ò¡r(â;TS„ «)¢‰k‚Q®ݵ(â;|S„æÉÑ`Ú/æ€R„œñ£¼)EAŠhfš%ia‹Ð=„"¾sÙ6Eè¿-Bã=0Þ%·ÙEçúî}Ø–Ñ8Žçs™z ÷Ë©žó‘à:1’…À5CáÉÅ÷ 1þø÷cŽã²íÇ–!18Žþm7ÇqÒç¶q³nÇqîØ! 8ŽÍ—Þ‘mµs÷•(„zånŸ£ï|žÍç\sß«P„YŸ{ïéé)¸)«» ñ›Oå&²ºsoúͧ\üñoò†ÿïþAÁMw|½à¦Çßwð½má× "Þ¹žpw¥'#Å3²ºñ{8?«4·t×İõYÇ/~æ°Äâœ\ΚIº'÷÷ä&òÖÅ=´&®}Á©ñ÷U«ãïq§Çßk·öäÞÿ`—[ïøú³¯üñ=uá×Îúà^i33™)X@ôG—+Í ¼ë6žÝøñÝÆZ.vß 3Ã}ž ymÖMÌL3sϰİ3Óö”a‰›¢¡ffp˜¤…è.y±Ënb%}“d³Îü:˜KÑò›=ë!§|$:è€OGí+Vëÿõ¿ÀÿòAdí¼swV‰\<ëÛ¸y®·²Ç&¯ËŠªdE¿7‹Úò½i{Æ¡'‚UÅ—ñ`[öM¥¹wî—¶sñðáù‹‡%ò ß¿>ûŒîOgt zÂÿ7gµ¯z=ýh䉞òz—õd~N´ó:Ü%¶<%Úyͮ؟‡¬í‚(7kutFwVVUiV6=)Ò“zÒrWO”\°q·ÙÌ ef$VmúÃŘþˆ¸ïfFÛEgý–™;¾k滎ÝïgO9¨ì3›¿t³ãÖìþ±Ï%<Ýä^fí>²~ÿQîìü?ïï#Ï·¼òS>3¶?ÃC¸þÒñÃÒþ˜óòø¥õcÏñ†™o½èW¹§Ö=%·à¼'$Ý –¸Úî oªÖ¬Šnºé¦hñM룖›ÖgßÔ½ñ?ïxOò‘—ü¦ê©õgdètú#q©˜dm¥+þéG?|ýEïš÷¦‹/žwÖ{/š÷ñ}àjw÷¾—çRݺËðý~U°®hjÁºÊórÖßÔó£ŸÊúå;K³ö¹t]Ï÷ÞÝÓsÙ zz|¬§ç¯ÞÛÓ³Û‚žžw½¤§gßïäûÌ=wà%«¢¨Ô~ù€D½ñKÐmG0&Úu®?ûì…¶wlݜ±ÚÀÈn[<'»{í<÷?J½–&'Ùw•=,±>ëVœ ôìËåë3bíPìÝ=9ÃÖEÙw~ê \WIƒxǨAøõÃïȉ֖fGk†ñî>÷V“±—ÇÓ7óÏáƒýfÈ1ø@÷f£;Ý„ŠyÛ[ÏÌIÔwæÞtÁ?$ÂÖègÏÌ™4Z’ÜzT´þ´Oç$²Kݽÿò\W’ƒóÿ›Går(&n}Ž}O±ïÙ|ÏM¬Qìðø ¹”óŽž¡¢q‚ÃcÁq0íË}ã/ø6TE€À·V­Ï¹«çÓñÅ®)XŸÓý_ÿßSÐ]pÛ.Ý-Oï.(Þ9þßætÚ½lïÓ—½:ûô‹.}úˆ×Prè«cÓ ¶?ãB oÐÉÑÇÎDC´˜3P Š£þ?q~Ü_¸þ×ô‘g#¨AVégg'¾÷îÜuϘ™·öïæ?¥òàówª|ÖEþë oÉA.r’›L-ÔDmôÇöýz"ÑÒâ+ÜÍoÕÓKs‡?#1lø3†þ nËÜtÛm°Rû#Eû_uÿhE¦'§??îÉ[/Ø©rÁ{wªwqÜý/ÍôdÈUyë¾÷î<åÜõOKó†ïqö°aß9zxîÎʼnìÛvé½ùgfJÖôi褦cw³¿¦ó§çž:Ìýo'&7Ãú_îœüg$ÃýØÌ!\J£Œèîžž£xÐöÞ÷~¸¾mì‡Ï[°ëÁñwÌ÷ÕqüÃïu9ÈÙ±sÜü¦âáaHq¬¼öè^+L­>”×nÒJHuTäÎý0#,-„ö`ØÕÄ·E»õÆŸÐH8'zFQuum{L¹ £ Ìe¦{€f—77‡íþÑåmŽ D½!&XÑÞ¨‘*–fÂÆ§i†$Åíæ9ð´©ØãÒ{aw†Ý ÿ¬5u1z†é+ÈÚ@M_ÁÍ…×W0µx…£ÛScƒÍä¯ÙnñsÊ·úù¹îÓ=w¦gH"ÙsežÀUÀ˜@fŽÆ0Gê`0({åMãJWãòIïÒYR¬s–¶S[už,±hƒ›'IUVç)›!o¶K’Ö2¼cc’sNõ%0‘ß©/±SSçúOŸý.–$¹HI÷÷ mWÉkk®A¥p¤ïüLÈfCY7zI?WœÙèïßs‹ÍîIušˆÞóL@¨mõiÑÞ«ÏpÚú¶ÿšxÌáÊ$e›Œgº÷™‰OÉüÉpßäÇòL},Oûcyæ=–gÑcy–<–gÛcy®y,ϲÇòœýXžMåYõXžuå¹ü±<×JÿeîÑänÄ‘ÙÁ.OfÚæiÓ÷¶Ü(aÚ0v\þمË6Ñ-]ÞÌX¬Í;“¸ÝI×óÑ\®ñ挷ŒïïA»«ë·Ö…ùQ߃y¿ÍeòPç5ì åÚÆNîɵ´»+{¦½áß:£3CÛ\Í2¬ÑS&'m/m¾k~›/ϵŒ\ý¶÷hEÈuöŽ\ç„\—ïȵ5äÚ´#×–kÝŽ\B®U;r­ ¹®Ý‘k'³ºhó¬NÖl—‘Ia°y룷”|îMÝÎxª®Wq ÌÕ)éé¸h±0éÀvU„á&ËzÈ~3^X_7ñEX¶q÷lìhÇ&pÿö›ÑŸÙ©›_ç}f.‡Õ¹G^Vw:±ê„SŒïîŠvÞŒ7¨!^Xš?Eæeü»M5õbß¼žÑÕ3žþœ­z\¾ iü¢Ë^þ.»HXiB7šF2ï1þxw¿|¸ü­ÑHË ž÷¦Y…¥Ãµš<Ò¥ =AG¯jZuåµL¨ÅÕíq½¯{>¹Ú7×Ýú纩eÞæº'ô×½”\+†ºÛÂ{û³Zb0ó¸¨eL*£ÃŠ:Zê+_Y×Ú°<)Ã[:Úª—t´·§šÛúΕ²»ê¸Pø#Å…`ÁÓ¤šyÄrL SkY,ÇR2‚–ż©A°”Ç—Ú|2@fc3—¡±,GŽd,Ëç÷7ù¼IJrxcà$¯ógq˜ÝëRìÜëÉa¯k_§w|YêˆrØë²¶2îÙ+,wûþmÂyz'MˆqÏN¾$YÛž@ù瑉æä ›¹¶†¶ÄÁuº|»œ²WíGNÙ÷lö×¶nOê°ƒìˆ`½)ÁšÉ¸g÷Þ»¯;·çv÷ú›®¹³½%ûÒn.Ð{|¦FtÃXZµ£þk¢¢^NÛk7+¿vž0B¬Ý‘ÿÆ>°-ºfÒàÕç5]ã}îïæÖ¡}ŸÖîóɸówó_eŒuk'^÷‡W–(&ŒaÌôêNgÄÕ;ŒÞÆU‹ó§`7£ÌS½ÛÐÓÓõwî´fj ¦}z6ûtYï­;sUÝ«fýÉÕþEõ©––•eÕË0°ÿõ]ÊÎôû“é÷'{5ìϙƱ`¿x£Ž¨ß-³|hÇåØV¦ó²Ø–ƒäw¬¬Éä]×-…ãw/9î±w²J$³uöza'ûÛŽö LÆÙ)ý“Ο#b»Û™ÚSéΈU@~ü? ©°³NxdgÅì Ÿì¬ø‰÷ÀÎ"§ßYãÙY±í¬ñC ì¬c‡hÙY²uôðÎÒžJwÖÏÇVÆ Xqšð:w£9·ç‡žCSÝU«¹{ˆÔy÷˜ 5ï·³ËĨڽ˴Ýewè¶âvØ{{ï)èn_Òû]0ƒzöÜêK;;3ßqézÏÎÊòy\öH¾v30?]‹t4Ìs7³çî`ÏýJþ”Íwó a·ewnÍ_u§yžøŒhï¢Ú:¬À,ºo¥ùÆ.òæÙiþ¾aw]¶s¼gv7|Ê»¥a×y#´ìºpßÎožÕ[‡ßcìºÚËr|+³ëÒ›¶rȈbºëd>1Ýu2œ˜í:¿cÙu[â]K1µs×Ý®ùs»NûÍß!¤z#}Ý!~™ïMm˜ÛXÛ”˜W>¿¼*Q[ÓØ(÷0Ò̰{1ÆüÀ"7Þø;%zžÇ]ðªû!7‹.|Óo“Žsu®m»–F{á÷CnEk?×̲»³›>ºûN,ÃàçÐÍKÌuÕscXÂ0v^¤Õ¿›g¼KØy1}÷ó"Ži´ó"«JS¡ ¶x^">§µµw´6'ëø ±úË6FÚÉ';SM•&Wµ ؉¹ ±$Y[ÓÑ–L¬Lu$œÅ°eY2Ñ’Z‘lµÂ¦`<ØÎŸ8Áhká‘NYÔ7ð®X¶Éw[¥¾wÏâj8)o,V6û qöcó¹ù4úñ|27~á^{CÜà8·wͬ¸Û~,½@Ï5`×8&vnцëœ[ÍG:·Ì‹ŸôlĉÄòÜá=›ï»<_t.˜éºsÁ1vF–•¬†§õf0ùGÒ÷áì–}U4Y˜ 3ãí‹{zxw'fÆÛKr¢ì®º¬k™»lŠÖŽ›âÛ˜±ö®‚¬k«ò†M6ãømÔ2¿+oja×éÑJ`´'•Û³>0MXò­À¼óÖaQiYwÏu]§.,9ÝÕÛ\ò¹žÅ&Sذe ý w[Ù©=·2ßM½µ´ßa«y]®Ž­ºunÍõµºå 9lÍÉéìÅ^ÞæEÇ6i¶$;q¶#BªU™G"-ËðŽÀ\žGÌ,;ÃÉèåËX©kT„;ñË– Vg–ÓýŠñ¡ìW1g¼¾6Õ²Ò¯ãókðs´fdBN‡ÚšS퉆¦–ƤLÌÈóŠØ".?ªÆðie¹ÊæŸÒÞÉžð7ßX:Èèñj3ÌxýŠhåå¶OPLÖ¦(³Of¼¾Ÿ»}«îíÚÚ Ì¾3Î>BØ6ì`}opo®b k¿¸Ý0Üæ¹ýç5:úÔLj½¤¹Ý£—¯ùN¯ÞŠºyáïö,ÒìYëùNw#3‡î>dæÐq þʹGþ&dfmUŒ¥Í\9,KÚaéX¢‘KÇRs\1C´¾1Þ‰óÒ±÷¿”Ñã7³éæ;qZ…š_]mf½QëIti3âv¾áᘛ¾l†Ízc+sæò èÏ;]0f½±*ÙÖž¨”Cž5ÁëABɱ¸ûêñ¬7ÞÃ?ÿö%%5Ù“KVg»tw½Ñ¬vnvI/F`¶Íîó®íã8ìgç_s¯¼â¶¾z^Ó¼ñ•£c—ŒØ„Õk;#q;Ë‘ôÝ»ùï_‰ö+Jo~ãŦ¶;–9L¸{g˜Ùt;#‘£Û Ì÷„™OÇÿ0{™ÒND¥pæÍžp;#‘ö£çx±«n¶Z™gw_4øÓñELïÍÄß+±ƒ´e8ùÌ~º+Ë8Œ]¡Kב?öƒð]rþY ”ÖJ bùãù5Ë“‰t!ç¶ùZáI²—d2«Õ,´¥if§aOŒ¦æ‘?^¡f÷ÜH]*Œ÷‘?Þ´¯,nI¦³³ q¸eô¦¡ïÏéÝÜÏpã´·ÊÚS·ÂGoœKÒ7ðõ.äÕ´¥Û™fáá¢Ý$võåÜ/MýÉ{p6»r¾v]ºËˆïÆJê©Ý™ó·a¥¬®ïí½xl´ofï=ˆ™ÌÌúÛû/pjÝíÃìwûÀ&gzûàéM™[~Uv‹ô\(n‘Þ=·Ç5;%çŒú»¤iž3möîݶkÙŽ‹iv­»QLæLE³ký’:d×îKÙ_ܽ/ׄ}‰–¥ßah4Ne?ÉUÁÜ‹NL®\’™¬>mjÑM /Rò{¤•¹9•hÁ"ÙZN‘µ9Ÿjõ¶‰õ¡‰ν(ÎÒ±\Ût“[DZM6ȶà²LFõ\nN ƒÈ- Š67eT—X²²hšV·/Qçש¹˜{Ñ&ŒÏþ ¼Iƒ¯º0þ&½ÑŽk× ÉíÉc¥¸¬+o»Æï¸ÛÍì¿d÷¨ïàüÛu¿cdž¸ß¹t"]H·Ã9+p÷U3Ëñ·ºq¿™U‡õMŽuöŽ9ôŽ›Á¶p#òf¾©c—íd2;qÿW2¸ßÌ«Ÿ]g$kÜÏý¨é›nÕ9 œñ™ÇnŸóÄ9¸¸¹¾Xq¼ùnz(œgzH==46œ\A]³§0ä»?{JözO{j) #u/^™l¶¹1µ‚Í•÷¾¼n pzÏ&M‡Ù–lÂl[ïµ²ëÍåªgCßñÂïåOIψrߣßñ=Íœk1öf[*/rYK÷p’À@9wS÷Ãl?9>½™ÇM¤W•sFeÞÚÎ^ÝÇУXS¿vö¨ ]jÙ÷<º¾9Õì\O9| ôœd ñèúšFÝ’LN(䔘éÑõµí­ñ\Ûœxè!§¬]G4ÿ¿¼“-Ù£ë“mµþžsÀðâj]_2½{‡OމϤw’xwïðhCâ1]a.ÿŽ{ïÄÙ;º~EC³ïžfp ¡=qtý‚æY$ÙKÚ1¾Ðv0,£3¾Æï‰‚Ø3 èþ]¯½ò¡O÷\g;e[š¯®Ùöü¨9쌹%Ü2þwvûþÑÛÀøÀåû‡ŽÓaú˳Ï? NödÐÅüÕÙg¬•l :ÊNÍî.°”å­'Ë—^îTæp‰œËžZ/æŠo]VXÂަ…þ>Œæ>>¸k÷/Mzý”wÀ9w(G|ºËiùRÅÁœQNåˆ+wÔyò`£wäl¿'gtkÈ™ æLús’ã¶9Kƒ9·íèÍñƒ½Yº#çùƒ9 6n‡ÙÑÎÅÀçdÆSÜ2|÷RnCÍ#÷Œrʺï.f÷D“öÆNÚßñÓ&tÃÕngO¨ž¸*bç¼6*àTn}ö5Ügï¿nâ==!÷äLîû{\î‘QQn`:ó›=´­çkàŸàŸmÂ?ïgGV±‘>+G‰" Ï%ñ…ðaiö´Çàà‹ÿÄÍo÷"‰¸ypªç´‘ïr«•:n ùnŽë0Øç3†³ðäîEÄÄW³9„u<ß¼[dï„u<ß¼»ÜÞ ëȸwöî{'¬gμ»ÇÞ ëH_%}'^¿}'¬“Oȼsú*Ü’.‹ÉžCn ‰7Ô¯XagÉøñéÀ‰…:¬·xœh=ùX…Kp”xy‹gã¿`ƒl•\àH\×¶-ihç²µÙã( ¶Så,ž½E³ÎÜ–:îAîþ?A|ÊvШt!vÀ Þ6¨1¾?Ç59Ì>Õ}Ö½ËïžßÅî7㱨z‡Ðу„kzW˜(?áŽäïEÌ‹ÛO§M!Ï#&–ë<èdç_Aøýž€ß™-?gø R¼ Å”%…âì†_1: ÖHÚ Ð•ÑL·„k¢®ÉÇDzá+¬|„F8¹~^Å㸾d]"ƒQÀ¥œNÇWß·>%çÂn.<[^¸ö´ÄÙ% gÒçBüب§›^Äê×ΜÄYèE~ ¼ÓP¼4ꗰЪüŽ32~š,¿ÖÎ7^‹üÝ }ÌÎûðˆp»ÓŒ¥³ËŒêvÒÄÝùD§±µ öìŠÅ¹Sº’Ù…gŸÆŒ)ù6¼ãlŠZ&[íúË}_?8ïíÌ{µ‡{«ûjó‚ÚÐC¿ß±N?L<ÅŸê“E-ë»ì=®àcˆ¯{âS19s~G³³±9Z»KgìG"Áªl4ŒÂZ'ŠŸb~Öc„Éï¼W$XÎ6\%é'dyò\Ôása¡‚šÄÞ]=ó1j’%r-ʳɩiªÕ×·ÀÏÕMœÖ'§áM“­cáP“Å^í|“kiX¥ÏdÖeûޏƒ] v{‚Í\©ˆFOÛ5íÞ=>Ñ͵±ZsîJgl4Œõ´QziŸm±šð‰¤}ÓëÃýÿA: Ýu5pŸ¼€º<>¿ ÷I[¾üp‹$+¶FßÛ£E¡Ž¼0’íù2ôlåÛÃìLÅœ ³7ßÁ)&¶ø ë›u—ÛÜÞ±¤È†/ꀕéaèBƇ¥e+˦Æ|5F0á\MxaIÁ¢ùϹˆRƒïdÞË6®ÙcR.h¾ci²¹º Ò&to_n}Æj­¼EõÃÛZó}7uÇ…ðwãv¶{û‡7õ˜µ¬ä•Õ£pïºR]’Î¥Kštø‘>:Nq‚…âô6ÂÌxŒI/k\c‹A4Ÿ»ñ£ñÜè0ýõóxþK>g}Çt®ÚØ,ú±âøîÙÇ/àÒÖç!EîŠÖ¶ÖËfæÊÑjçæ†¦˜(·†—ÂN kG®eX¯™ÚQ]û@à .Цÿå1qÃRU\d-½×~î}sy ñDL¹Ýc)ä§æoUOÎ&½¬Ï¦l™ïžMËõ³Ië³) Åb¾EOÅfñmÝ:›Ó‹´»qx‹S¥Gru„åÕ æÐÜÒeaÛÜÒ¥µ°ß™Ë—ÖøÝŠ[.:‰5¾ß™ U.´ÅµôJæ&Ðè‡çýÎÜ¢ŸÐΜŒ,ÿpN§8¬ÒAÁž6†&«Mé°jZÅÄÖ¿|Fý¼2£þŽFŸý¼ÒÛуóJ[ÒL0½®Ï빆ç„ío)¿+Rä²j:žS³wºfÔXYÖ,Š8èÈ™ÓÅç43ªé2üJlP匰Šq¶¶®AÓÖ–ŸQ¸4ún†ó5èÈ?ΨÑóydNçG£Ví(]mžJ›u“X“Öis 'åÍïUúíg•×gîJç¬ZMi;«–?Ô5«X\V{›¹‡¾o§­8ÙîžóZ13lÔXÛËñ ®Jñ°ƒÕêͱHQŠ[å¤Ípõtýÿzˆ¡4ùRëë@û§™›Â¶?b ïέ½1Ô†vÚxšl»ÖÍ"=} ÑÛ:¾~x·Òëú¼¢μʷÏmÕ[±Ða ÉÉ©¬þî›TY"’kßú}^»‹ãwkø{v©—f—jêZ®‚`—îöÎvi†SŸÜ¥ô¸¾K5[ïRzîwÖi™Ý [{—¤»6û9á¡2š¹Ëµ4A0'µýìJß;'ž³üäŒÐßúŒgH¾ ®. ûK·Öàù3â|¡ö1€O&¸^?OÒø$>¡·u|"õ”‡ñ ½ŽÊ›ÜÍ™[:7i,•'áÁY@“©Çƒ¡Ëm<&°oCrj‡îÍig³+'î{sÚÔ•ý Þœv·wånÝ›ÓØîΉ…âÞœßuåDƒ¸7§±£Þ=×Þœ÷wåDó´7'÷›zN8b½9í-¨+'F•{sÚÝÛ•½ÖÞœöFØ•î[oNn»õœèµõæ´w⮜ðzsÂc¨ç„Ñ›žB='|ŠÞœÖ#p-';ÅÞœæ6ÐÏÞœ–¯Ó•>aoN8Yõœèáõæ´œ®®œè†õätúP]9щìÉét~»r⡲7§ÕüÞmñ½ý´º1]9ÁT½9s Õœ`¥Þ°H]9Át½uZý„®œ`ãÞœV×£+§ôÞ÷æ´]9¥+¸·ŸVƒ¯+§tè÷æ´úo]9ñ>ÐÛ«ЕŸ!½{Àê)våÄKAoN«7ڕϽ9­®n׎2Ü©žœö6Õ•S\ƽ9­ß’s£|š{@·RóN7/“ƒ›P=ï|nkõN/Áäà6ZÏÁ;ŸƒF=ï|nâõ¼ó9à8ÔsðÎ瀷RÏÁ;ŸÞQ=ï|82õ¼ó9¸ÁÔsðN~SMn6õ¼óuÀµ­çàÏ¿¼žƒw>¼ózëåÕæ0wžîŽKir ÑQÏÁ;ŸM˜zÞùèÉÔsðÎç@—¦žƒw~†Ð´©çà¯í¦zÞùÆÍhwÞù,ÓzÞùh”ÕsXz6ê9øp9ŒÎ^wóÎç@¯¯žƒw>zœõ¼ó9Ðõ¬çàÏ6k=ïÜ,Ðîæ«ÃhA×sðÎçànSÏÁ;_+7ŠzÞù:¸›ÕsðÎçÀ‹M=ï|­?ÕrÞùÜCëuðÎçà>P¯ƒw>÷€z{Sµ9º1œÉa1œÍÞ¯çàϾ¯çàÏž¯çàÏ~¯çàÏ^¯çàÏF}†xçs€áëuðÎç³×sðÎç£×sðÎç@“£ÞÞùýQ=ï|nýõ¼ó9ÐŪçàÏÏ¥zëCÊæèÁCæÏу«Ì;Ÿ£Ùw>‡ñMÙƒw>·¥z§%gr !QÏÁ;Ÿƒ›N=‡Ó{29zpžyçsôà<óÎç@7²žƒw>Ç£~’MŽ<í´ løüõ¼s¾”Íý¦Û—rÍ"ÌŽÔƒ`ús¶úÊBCÒ—*£6mÜ$ÿ‰¹Hþ—¿Uê}»Œ²AEãß3d0{ˆ_E×MKE S]+R*×¥¿A ]ª¤ú¬+m£Xª»QîuÉl‚Iãׯ ÕØXl_â0žqÆ(ÆF3Wïßf®µ¨B÷ç€êK˜H\ªû㲶éÂh“D­0A‰k ×÷äj¾¥ñ“ :Ü‚GÞ›µ…:°LØÂÕ±€RË zV€á2öAÿ­ä/ Þ :-Po+yŠlÒ¡LbPø£¹f gê‹ ¸á\¸‹ô¬" Z#¸L–È7’Á,ñf½*ÑÏQ §ùF‘«„ŠÛ~ô«Äì7-ž¬ý¦9ïÙd±™a¹\”Ef¾ô#Ì”ÄE™s8'6j. üö£óLä~ò ¥Üûái}šÑ•šˆÑx ºho#'øaœ¸ bD ›¸&òñQ´9ÐÍ_“y ôÔ¤—w 8¯šœµÿt¯8~ÐÏé/š½ãá!¹;^C>þKq?ÆÉU®W®ì.n¥ÖÏ]êên<µÐñº³«I‹\ý8X.ŽÕƒµ=Õƒ¥-¯~¢—úqˆîsêÇ!·ªátÜèÇ´ èÇæ„~LxuÜ ¯~´ÐcŽ' WÇÖž û‹æs¢8 ÚxÑÉäž0‘9æö;g  ½}ºDÚ&nª³gbÌï0Ý´C·|{])ºWjþ§Ìk2߸RuQ™áˆð›¢Ëµ*8Ü©RêÆ”6Æáº| g~W\ÁášZ‡Z¦JUEž*&Ž6ÛT]·Ä š*…jMö416ÔéiR°ÑdOƒ›Ì$Mƒ¥!¦IUÎO¦ãpµÐéèQÚt¹RQ/¦_×<ý.y!‹ñ¥éö³&$–cèù½˱³ Õlúk£*æ6ñÝŽåÿÙF5±¼BÛLø¯eƒÛ(–nq[m¸ad‹…§äãÙN…ýͰÍ1ãz­-تq¦®Íªn¦°™æ`¦,îjòg Wh£Ìb¾˜ƒYê»6Ý,›ÎYóU_"—Ñ ;ÓÙDý8ßw/ÑwÚ=û›…~Ø–æC]8B¼,å:B¾Ó´ûmMðÒ Š=By„žŽŽU7Ž$'üˆ#•ÝcnpBhGŠ—¦ýväeqw޼LS‘wGS˜0¥nFè(¼åž^ÁDÊúhùOüÚ¥|«Îµk4íbƒhºÚÙ®àævM®öÆl1Ú´yç¨Sz;Gl1!¥9B*êÔ9bû,ßÆÙ†¾…YÙÄs˜nØ\jÁŒsåÖAœûìþN‚œª7ï¤ú‘w’hÖI£@ÄoîãM0WŽˆÕ¥yÒKQ×ç©sê÷<ñÒµ æá‹M0Oœ¡Ö£4š·£4šÁ£¦Ä:jŠöP¢ “Ý9LÛÞnít‚ާC3x”øš £Î·üpý|y)bÊŽº6ÆGK£M;âhi‚©G×Ä9®ÑòMäþ½-¶¯º{4sÅ<­¹ÔMàuWóyŒ.|ºpƒþó9_—yÝæ‹„«½>tÂ<ÎÇÈm—!D½_¢‚Q™’:¸uñ±L_̵øXnBŽaÇl¢c…¨5aˆ4Á[ˆRýZÈæb«,„û +q!{–ê"Ï%ôgõÁæ\Ä¥6a,b êYÄ&ìîE ¾„>-¦†“²u£³·xf<‹gº@¶!¸‘±Q|MYDåß‚ÐìV”²f"oÊUðv%ýŒËÑüëȤºÓEAS|œÁš‹ãt5Ö›ã…Áti]b>Þ—8/Ø›Dz%:alœá„س}'VÓ{‚8¸ªîq¡4Å'ÈÛ»¶è æ½üÄ|·sØÅëüMÄ!©ê68q¡åû˜Ë·€'M.Q“ƒÝúpèo]ë/ïcÿ_Åo¯—0¶jÞŽËÃ6Ò~믯ÞõŸcµÀïtµ|`uüæîÎìò:ç ÍØÓjãêãò¾ÇÐÀ{‡ÆþFKÇ[y ©òŽ––”rŒ–›ûݲ4~s‹¸R®–AB Ê;H· åô¾8Ç Ý\Ž÷Žß¼OæÞ A—¼C„•wVwÉ1D7—ã6ÜIðæ6ma_/ÓE½hÝR/úÔËNp9Z×\ßà?åhÁZ'9ZØÌ>ÇeÂ!ÊqÙwã·—Ý•¾?¾ÖfÚwЉ S\èÔjëì´¾9ÜÓó¼Ïî%GÙ½àP{Á½ öôS{Á¶©½Ö^8Ô¿À«Aí—¸Ú í³H³ºóv¼@_ –öfí—™Ú ®\µx<ñó¡¹× XF`;Cx¹‚‹ðµ­ÌßRqïÄì @ÝÏbíÁpzBl64·i£‰È†¹µp5É6¸Š¢»É#ô;ZʠĸyŸ÷\^ˆ•\wÀÒÎ$¯ôâ÷ƒ~6ªK…²à®°buý¥/ýìXŠðºGÅÚ—r‘«#]ÇRs–np,¼¡Ë{,´!W$\ý#nR±“nc±.oº¸ÄºÊËu 7°ˆëm,Ô.—;±.rºgÆR{« 9„‰"nå±®êI¬ËÐ{,L¤ëM¬-ÂM äÂÍÔ¢þÆ:©ó±6‹f"RÑ´ÄB)š£X– ÛF“ ™h2c¡íòXˆD»¶J¤› B@±®.BK±”2¸å±•„6bÝ»…báa‡X¬m! n{‘XlXíõXÛU[7ÖfÕ>޵½ÄòˆµQq Ê6RµIqñÊFºµAq%ÌöĽ4›W:l9Ü`³1q­Í¶ò޵)á7±ù`ß°!qOÎvä&Ìf„ÍÂ6ÔU ÖFÔ½ Ö6Ô%!Ö&Ô›dÄõ!Ö„?ÅöÓÅ"ÖæÓ-6GÄ•#ÖÆÃÝ…¶K$ÇJxV±nÏâ6á¨8†ÛÄ4Fë'Ã@Û'Û1(÷­1wÌXüq1b6[ÌÆÅÉl +-Fu6Æ;¼ˆýáX7Rmáž”ì~ÇÙ1W(îݱxÜXµ™cPkŒ{ÒXF䜧õ±î©º°†vr,¬¡ ›Œ kh'ÇÂÚɱ°·u°ì)°¬%°†vr,¬¡ kh'ÇÂÚɱ°7{°†vr,¬¡ kh'ÇÂÚɱ°†v27{vr,¬¡ kh'ÇÂÚɱ°†vr,¬¡ kh'ǰ¹ÀÚɱ°†vr,¬¡ŒK+v2,xv2 'ìdœp°“q+ÅNÆ©”ÙÉ` v2Xƒ Ö`'ƒ5ØÉ` v2Xƒ Ö`'ƒ5ØÉ` v2Xƒ Ö`'ƒ5ØÉ` v2Xƒ Ö`'ƒ5ØÉ` v2Xƒ Ö`'ƒ5ØÉ` v2Xƒ Ö`'ƒ5ØÉ` v2Xƒ ÖÐN6Ç/”øÁpÀÚÉpØÉ¸ýa'£pÀNÆ;Uv²qᣌ“v2ÎpØÉ8Áa'Ãîa'Æa'ãìÆ¸èkh'£ÒÀNFÑŒ v²qKƒ[G°†v2WØÉ(H°“Q›`'£LÁNF=‡Œz;—$ìdø/ìd˜/ìd\Œ°“QÁa'Êd'£‚ÁNF†Œ:>;n;÷ìd5ØÉ81`'£ÂÁN6® ´“Ëídãª@;Ù¸(ÐNÆ5;—ìd>ØÉ¨ ±“Ãíd°“á°“a~°“a ídܰ“Qa'Ëb'Ãä`'£ÒÏNFí‰lÔóµ“Qƒg'ÃÍ`'£ÏN†ÄN†ƒÁN†}ÁN–Š9W ¶ùopaÚ¹Œ°å¹™ðŽk [ž›[n[žû [ž‹Þ¯»»™^Gb1ݺy¯]GøMŠkÔ;ò({ÄLérÆõî-3Š«!È›mÄ­’›‡›*1¶ 7Xbln³ÜlØ\q‰qcÍït†Éíæ×Ü—: ·&¿éhŠ"i2e/4_æg_P\]™îñZÓhî“Y>ÍiÇu v“¿7Ûšmº—¿ÐÔwÜ›`bÂ&Ë^hSDº(e/`hpQÎ^h»td…ÙY«LÉܳ0Uq‘½Ð37ììÜ:˜dÙ ¦»Æ¦€•R»µ1ÙµÚ£9`CÖ^Àç«õ /yµ¨9ղ«­½€yÅu6{«×sì£PV˰6Á¨¥eSÅÖz‡± ØYÄo¶8SM\&ü«ï#ÕÜ]©}<®sY0ïjU£ÕW›e˜•µ½†Z­ç¨¥À8È^ÀȭͬôÚÞ€µ^ãÜÀj¯mXﵬ(Df/د²Žx¥ëyYµ'â9)K"ßѰ¿¸ý (øõ„vÍJÒnˆ€4Üàé¾]¹t²ç…Ìy¡&&–¬2ƒWr1¸çÚm‰îÌôSH*Ï ý¡)E®w»Îuè¡C°ñé—h:‹Ûv¤‹J×|ÍgµCÏv·ââM·èïò]¡CÏ Úêza;ôãiÃÖ|¡úb¯þмÆuKÐ×O¹9†Vìå.¦{™‹ {+vmØQ z£‡Æm;‘Rеe¿ÖUcc?媱±®c63.Ñ$ö» ¤ÎêÒËEöó€R õ2(Âc˜^bô}vÜ%zN²î\‰XéŽéh&†¸Á}QIº•’7Í–õ-©¶e‰™Ó'NO¶ØžjIÌH5Ö%['6ÕÔ.‘ù»9ák ¬Ø?(7³µóÇ‹rn(7>ʹ±tÜQA©têÇåÜT:nB”sGéøâ(çÎÒñ£¢œ_–Žåì‹Ùˆ ÉåÉÆƒÆ1©y²xYO˜c®DæÄú°çÒŠÊi¹Øs«—ð8Ê+/Œ­Qû.úìÿ)ö<û¹tiçY±w…y±åwýbA•Zz'…™ -¨ò6âSáEùºÿQ¢ñ(H‰Ÿ $týìÿ(Ș꣠¿¦ ´ÅÏý¥Át¼‡š|ÜÍÜ‚ÿQ–ñI·C¿*‰˜kû‹ÿ³íxL í¨íÖpÂÿíFœ}ÂuQþ¹®O¼q;àþ³0ôíר¤÷ª$µ%?›y¯¯Â1ÿ£Ò̃öjŠã…´—Å2ÄšJ‰”šêsRlï —޽Äó:£ÜTûÊ–d”÷ŽT3N£¼³H³>å¼£!•ÉV*nªYÚ€)¹³yí—F¨ 5¨=nn¯›8±zFŬò(S2/ÖÈa‡}ö±±Ú`LwlæØxq æ.ÌûÊRq¤pó’Žúz:jó~È%¼°¡¹rÇy Í5­+«iK‰zd_WÇçP—}]L-6TxF}k’¥a*Šr¾LÑÙÖdkkŠèír{âßoÑ•©å¨ÝoH­ˆò¦wà_fK­O-oIµaÑñâæ(?Ç—u±eÝÜpl¼+,º©½¥\”¿‘p\ðÜF¬ÅàEL¼¨ÍXôЦȲ$7úü3ooöå®liM1w_mMÖÔűd¯­ lD¼­¶1n±YÚ=+ä3QÁûš«5¥*ïr÷½²±¡­=Ê?ªü¬ºz9ýå/òþePyùËÞª{P:Ôœuºxå'>#+c¥éþE¶ïxW9Ï¿[·„QãÅݾ¸4÷7ý‹ŽÜ“ý;Ÿ»ü|ëƒOQü{{PË\þº=ó‰K‡g”‰ÇÓ÷C2ˆÍÄÿ1Žû÷Åò4²1á;]8Í~W§Øa°qÿ>º¦j™'“ÓOÒæþA@%æÁAö ­ó… jä7{¡«ÉPŽãiß–¦‚ ¿Ë…ýëÂé2„á<ÜD‹,²2¶‰¬tïvûÑùù$uÏå”'-"#/ª˜_Y={îôòêisç̨8:Êû‡Ì“å³£Ü/–Žá6‘,Ä¿&µêœ¥ò{4Íí&Á‹[ Å |À³mñKØ.œE“´ïW.mì±Làéšäò†Z@YaöýÆY“·l·÷™¬ÚîÍ´ð†ûͱ•vyÀ.Ÿœßf«7ɨà~맪XOpSmulq5ÊÿÙÊ…EXP½ô¤—[šôÞ:Ið%˜4Ëø¿r¹F[¾JÖF¹ï­i]ÊçùTÇ^Û\}vC]û2γÄÖ%±³%Ê=ˆM1 ©¸ùcG‚ø#—Ö•®¢¶öÖÚ¦.ÉS¦ãz±PP”[A%ÓÑœ›?vô¸(·‰Ï#¢Üf>ŒòVh+¸xQ騱´úæœÚ–¿äaçE.nò©kÓ?¤xž|ºG÷F“× -‹ÍjD·M]TY=gÁ¬Y`B'TBü´"§——ͪª˜]^]YQŒâÉŠòEUÕóç”UΟ9·ªzÚÌòiÇD¯ÒË3.«^P9½¬ª¼ºbNUù¼ãÊfA>ãåÉsÌ/¯.ŸS6uVùô(÷õîÍâÙž§–G¹­®ÒSgWW–U¡Jð^0}:¦jÕŠoùêÒ$ÑôäÔÊ*^L³'ŸÌ<™nO~-ód†=1ÕÙ'3ã'…ì­Å]¸»·œôÕý½¥¯z‹ò¯ŠwêÕIS§WÏ/ŸWQ6«zzù¬²ã£œÃý³eeóûª¸ŸµâøJfâ3 7kneåñÕÓfO÷¹wdž-àÍ™.YôöÞW¶Í—÷>1Y’#{Ÿ,¯*«Z@ç~+<ŠrÞ–‰›)¯úÊ–wEï[ÞûzŸøòò6å¡è‚ª²b†ÿ”QÞ‹O³øIŸnñ“->#ŽË†•Ë/F’O-Ú¿Ï*>O(I­´ÖeLãâ9_ßž.7}òÆtÅé“7§‹NŸœ—®å„¹šn½<]Kúd]º–ôÉEéZÒ'«ûkQ×Vô×¢'ëûkÑ“ýµ¸Ü’©åôcq‡ŸÕA8›&>'“_áÊI™Yd å¿3ýbù¬²ãÊ£‚weÆÓ¥ð5Ló)þ<3±.Åþé.ÅW3CìR|>ýÂ¥hêïE:yiÁ®'éÃÊËû{“¥4ë5ëQ–rd¯²”d=ËR¾²¿wYÊz˜>,Žè¥ÙŽ7ä´[Þ·$í¢Mæ×†o¡MvÓ@ÿl2ƒSòæÙd3:g“]Ýß6›ìÄógpÑøáãUqüÆÉ3É^>0v&Ù;6ΜIfÀN8“ì)§Í$ó{)5^ÅŸèÙÂãgUÌ™^>¼øîþÆeO㺗§]ÜßÂ<í—ú˜§Íz¼;íñÍÓéokö´4v ·KÊ˦(3LcSÚg¥ ôÔ¥Ëz]M7 —.O¾.ݱ=té~·¿öYºŽÒÞ-¯¬âßÑ96îp“ª­¿k&U¶¡C*|ÇLª3úeRÝÕß-•}²^YØZrG‚Ð.û®ì«È:æz 6Í%ô£™õÍ%üÀ@ë\©»çz¤•6нËvKÈ%yi”{a í³Ò÷:èÒ™»OÞ@—.kS-‡ß¾}._…i÷\º¿ëož}–¸{RèݱsçO/¯*ŸV…zJGó·É+ºØßÊø™ý ‰?ØßÔøüΆÄ~]øöæo Dgxðô²9¤YQ1wrY°0\¸c#: ©Í¹+€Äz÷ޝ¦^:CêwnDŽ!uË€ÌGgéñB]Ñü©¯äÖybGæ¨øôL sÓ2OlŠW[|F&ÅKÒOl s@T|f&ŵé'Lšõ±l^Åq:G.œ;kî¼Ùe•Qþ =;ŽSçòióÊËçDù®d+Ia‚'Œ[óÙ,—à¤òã§ÎeÙ®„8 Å½¬b*IWö½dŸè}")ÂJ)ܼ„ª.à"g†{ÁücªgÌOJfñV¾/µ…3ç Kk•'î¼²°r[9'ƒßt‹)ÄëW—-Šr^“ŽKÔôÕD5€ÌDݞɴ ¢h]^¹2ˤ¨IûV™Ì™è À•>º¼üèêiÜÌ)Ú?н¥<­÷XewâóóÀ Pÿà8ürïƒãY‡õ>X:½Š­9Sû'z§ ?ž÷+§–͸Ÿ¾YZ1’Hì. <:!“ÈlÛôMTžœîôq³Êhƒ=²e”LšŽ7g2‰ãT‡ÂSÇ£ÓŒ|ŒšZÇ›ÓÉýÚþ7Z¼…ƒºqj%{1yûêT²›óiþfoþb »ÞØ¿YÁ›Iýo–ó¦¹ÿÍSycÎ?¡»z“-ûfoí³pF”Sãß,š‡B:ÈÐ é9‡P-ŸEóQ¸ •Ä‚¡7Øè‘øyðÑÊ”®°óf°˜ßD%Ð`X6ª*Ò»BU<ÝGª3ÏÈDÕ™•™¨:³*U½iGR¯½íYBMº·‹Yá‘ß¿áÃÂ2Q®ë%Ñ Mrú°€ÄÒ(Ç]m /¬¥D>*y.>aN%©ø°à‹.i%2­¬,Ÿ3Ý!—§¥³ž~ì(XU§¡žžLß®„9€`Oq© j^^>Ë£9v¶|,žB!?H›õØye@íâj½\1³‚Å£=³¤¼z·©CY˜!³'À¯Õs§>ß°´ŒWÄóå­KÇD ;9ʇìãã:ˆ$ó@`[rt_Ë5tSï™å>O1a§ò©„ÓøÔ€LçS#8ƒOIBmzØr¤°Q_ù¤B¬•ÒG”v¥·o-ýHMÒ¶t¸8–êԜӑRÉ/ü½yß±ËkÕÐ#FLOØ,¯ÈJ»Ä­$ݺÒ«¼¦ÞKr\‚žÑŒ(ûëû³ Vh¯¯mcè_cú\dN”\³ŸGFù§UWÏ«ªªØ(·ƒ÷G ¿éßçê÷lµæú¶‡ ÀÆ¥Ox•8n—À@ñ¸?ËÃè¿ô`’Åð<+aÎï™~±Í ìqO¶h=%_©MÅ×—Žx%ŸÚ;×ñ©U²ßÃ^_%0i Ì"jR<‹¼³¢¼ÿ<*r5™Ú™T3Ê*ÀŸk”ûfú!|üÞßyc-žM2¹8íß ¨F¹*/hñó|Έòwû“ÇÓ(÷#ä ÜOiñ¯I(ðòK|¶ssÿÏ^E‹—’ZZ-²å~¥tü8:ý›| ŒûƒÛÎ(÷È93Êû×?¹Ú,^KZé¬ýú1‘Yü‰íþ¦t<ª!å12WÉ9ä4Ü¢m5'YÖDçO¢œÛ¥~àµÊ/ªKr€Xƒ¬÷‰/à5=.¾Ã=)þÌIU^ÙTÓGÆ{A‘ò¯k—¥P‰ò.oohG¸)~Gº8IYצâÙ{ëz@ÀÊ› HfysR©4S2Óˈٌ*n%ºU’z0¯laõÔã«8Ö^ʽ.%Eš/Žqø8ÚÎv]+¤ŽT¹Â:˜ÖQXçá,wïÔý:™'þÌb.ÅbÕ”_+ý…eS«Â1=u!nʵæÕ2õ:Ê— D>;RŒº”®ŒòW?–_Õ2~,5FùG´Œí¯ja·(Pªh)q߇·,I¥€¾Ï\RÃU§øS&Vèåë|"ÚøC§•ÅŸ“ñˆ¨àc',œR5wZTpÖÍPrÞr´kʯù/»mÛ¿íÐø=XÓ¥ÿ„¤˜õŸÀG9û1œSºîO@*þè¿c·¤ìpXúáPˆ4žû¢žñ»ëÊc÷›ø'Ÿ %¿;/Oúý=8úÎÒ8ÑÇ·Ê.ÅwÕ‡Þw™ÜfI÷ÙÊ…:=èÿö‹ÝŸ Žê¿1û'v“SèË3DùÈ‹–eJ2¨éý)ÚõžÞ8­^¥´y%ñ^‰-¬4žÒ—¸óžä«™&qµãýb?E ‡$¨÷ΈKê:©÷CÒœ3Zíµ}%+û£µ¢ M…ã»/Û’`í(’òÃ’E®u×T2Að Î蛯$#J+é‘'r• )O%¢=ÌÙPŒž¾A¯Hc°OÀÈÕa¬©ŽÃ¸¿Nq6A£§õ1;d´ç!¦‡«BÿMSh>\vcTE•‹¡*âf¸*ÐçŠÃe>ÊV1øž«éùÞ"¶E!®OQ3Pž7¸¹—.!ÁòÙ®„ù©ajÅGJÿ[*ØÌÑ%C¸bÐ]§˜#±30׌ˋI›²ÿƒÌW ¨e®L,aOƒ¹ ¼æîAƒ«Tq‹÷(Ik³KªÄvÉCLWþL2p´LaHh£›³ ãÇ™ ®"té©èh«Ë.‡6Bß@>B¾CB0õà˜€zÛZâÌÔEϺûÉwÙ“˜Ð•…ÊZ‚Zó r"]ï:ì„x‚”`kÂÌ5€v÷‰±ûµ–°«Æ?îrßVƒ¨?Õà¢þDiòkvÃkµç;Û4´§rîBgS¼ Ùø%L)ð*ÌÌÂpÃĪ˘}Átb®ãÿücSÂZ–3„ƒ|_leØ@`lX /Ljf¦.nMF_³·`óVæ&5·&[`–D?Œ-wÉwLÙcLjæTâì/©ýrlhRs=l ѳÄo-êX£D“dH¤Ökcf‹‘³Ábô¢h1Û]½Œ5õÊ€ÄÄ‹õ0{kà¢5]4ñâŠ93æFGÏ.³·Ý“WF&&^\>oÞ\ ¢{‹¯CÞÊìÄÄ‹+ËæTÈ•Šë¡†ßôPó9QÂýõ’ß÷:} v1³ŽÜ<6_Vø‹_YíÈícbIÆ+в@`OùkªÜÙÓ³Ÿþëóß=ÊýÿègÜÿo~ú´ýn[Ÿ³K´ž1yè?9Èåóú:|]ÔH­i?mП?³þ ´»IÅX½ú»bõ«W_ð–Õ«%²NüþoaAèÏzz,.çEWò;zïô>kØ{JoxÄäÉßÿþ÷wßÝ1ù’gq›Âb>ú ßŸ}æ3èì HÊýü©SëãtæÑGßòÉO¾å3öþòÅ-‹öÃÏÏšWÏoÞîhãߺú®ù ØÅÌòÝ÷¹»?ÇïO¿¿Ô\Øý[“¿?ù[–/Î)Øe¿UûíR{ñ“o°M]«º:[›Õ6µoÄâ©\ýôíêûƒo}ëÆëô3á£kó÷_[;~ïâZ9¦ñ?F¦£7O6ÎÏ·Çü²‚õdêªâLTÛ¦¼*_Ò_!'Ǫ³°ëˆUã!G?Ÿ£§Lñå›^=eï̼vü4›óÔ ×µBùïª3ÿm·Ž®–3eñâšÚ)¾ƒ k‹wß9¿ÖYNÖ!çˆñ{7Ob^-^ÐhÖ¼+*—ùpvy•`D±ûÈtøüÉ=“mÚ܈¤Óž¿ÉF½Ó&ð‘ù‹Õ7ïêÏêÚOÔĺ<£÷µ ´ñ£kãt«­&ÅWM^¼x±ï©%“ÇYEÃ0o@éÆcÂûÑùÄWósñ+Éo{îëÑÓü=±+È?5m¬Ìt.o¸‹ûv›öhj0¤ãV¶ùçæ-9Òú¦†ù6ž÷²—Mʱú4Wª!6~ àhm<{YѾ]H‡ ÓlAGûâΰú{þŒÝöÝ-F½Í‹‹—óÍ8‚Éÿ¼ÚÚzgZr„ú™r]½,ósõ]î¶A¶ï/ Ô1ûR´±‹+8£ÒôKë]½bÕ*Æ9­gõÒÔª—µeâfÖòy3ý¥×÷þ—M)vf³Í{zìêÕûòÞÅ‹Óù¯8å}ýòåù÷.z„_¸¦¸ O\µÂíOâG°fè2|afÀÕsem†w¡ß?óâuÙ¼³ÇSB0ö.Iã•yñúœZìÞ3Í=‹ÞØÒÞíz7¦xJz_Gùùš6 AúþèZ€ïo;•Š'˜æ3ïµÓýwÄ!ùnFÝ|é·QéfL)v#­úŽhV}n¾´—F÷ÎÓªÅQ ëP?Í…Íg€Ëg“eùô;rva¦ïs ²eýÉç3}¯%àZäûãWúÜæú¾þñRx×°óÎGi7¤MÊE.}>¦¼ÏÙàæŸø{ïÝ;§vc\±¸Ø¯ÔÂSnþ7Ñêê·ÙN/ZÐhã¼%Çg]TÍ4ö­ÃÏlx_ŽÛçZçS»ŽJ¹4ôæYÉkûAùB\h£ ®ªæ£b°Êõ ª¶/4!N=Õ÷ã°F€ Cœ|!¾:h|;BXte}>³ïñ-ÝØxÊ^{Ŧš£.–Û•šc Þõ+ì÷Ú>±ýÊâÍûŽé›'ÞW÷ƒò§ó®}¸: PlþÕi@aãê+ˈP[¯>³Çn žÍ³ßc^F½v¿lºNÐÖ È~Ú @˜Oæ½:_zúI¼Ú?í—|¿*š.;ìGŒïêE£œä±-û ë$PèÝÇCçîü¢UZÿ6¤UµZëp.¨S`.~~ÛÊ®8…݆1ÒôÆï5>f‡ØŸ¢G`ó‡ßŽ6ü½sÁ†¿ühß¿±ýÑ4¾!þ]lß¾ WöÅ;ó]¼8¯óçÆ¡öþâÅéÝå^¤qßPë׈Ýea/Ë7b÷ÌÑ!ÅÎ|>!ÉZþŽli>ן¯ôõï+;;Ûãéï[;oxÿ7™ú\µÓŸ?ÍçÞ§ù\þ4Ÿëníý†ÆúÒþùc˜öË÷·š?ï·ïhGþ´7-óÕ9¯i=öJšý|üo`ÿïÞþ_-­Çãs÷Úk¯I¶Ï¹­î7†õ‘4–Íj¡ý°9ÿñóáÕ`š Ÿê'ð¤ŸÃŸþ aù6Nê›+@4´¤ÁÀ33`•re’Šß圳¶:@Õ«l1îXLü×Oñå¶ïœ/xWÞÙãóô”öÓÿKgÚœý¸óY bܹÍÇ7]'DÕù ýW1WôÞïI)*7xh÷¯ë¼é÷ºÛΑãÇOŽû¹_ï(ê7`¯óŸ¹a}ÿºªÔÏñllcžxÿ;!cYM²UD‘÷Ø[Œ.ù·¿¯’ô--roû »ÚýÒ·ØaòoçþÈýÌ[n°Ü1Žm6¿¾¡*⤀.HÜ–@ ãÒÆd¢¦-Ѿ,™˜*ˆ¶£T°î\n̯5Å6 ›_˜„šà½56‹<82“Óüú®aÙžysÏ]k³¢agíßsI7ì¬mlm Ú†-"Ü!ÛtŽÍÅÎׯiÁ©Ñî%¬ÿn]ݹ_´÷™Øþ"F-;Ù8í<Þ–-*Ù?ªì–sáiÔ{Jwì0zJ¢Œ·ü¶Fû56`öÂul嬪EÕ±v†HÃb|.nwë‹›C‹Å˜“£ï£ËeÙÚÙk³_“-Æýb‘åcw.-osŽ—±¡¹"Äζ»Î)o~šæóAƒ½ýd.—ð'NÌKºY=v…µNm×åÍ;kÖØ$ÍýÖä ¿fq¼¹™EÅŒ[fêk°ÅcVOÿ›_fÅ[-nŸ•óYf6¼,_YKNÑÓœy%÷cAïè14bøOb¡ö¿ ël÷Æù0-çó àm”miûn v{÷sqÏc5´ž§ãöË®níÙ´J÷Ìö¨µ‹NÛ^Ž·¤´â«¢™äZêöÌ,éçûvÞÏ»(+z¾\ÍïŽ »±l¦Iºr³ ×rÑ¿yu4¹‹I7ŸÍì:¿`lWÄuÅä’¥­yì!r‰ CîmXkÇVºÇâh»j•vUuO9,=½hFÂ]ëR+pÍq™í lh6[ “š~Ga©Õbp‹fÆ»ãuÑEñž0F«{B1k)Ýì 3O‘Í7-ŒÊ×pöi:[w°gï*!qÞÇ%ôqþæ>NŽžV„ͲXûLüB×vL«õ#ƒ}¡vßs_s}Áì {K ïáݽ}aÖÛk£¿ó}éüô¾}´‡gGË*À+P¹8/ÕéÚèp‚1]Øl=…8Þj1Ì:œ` Ž·»©SùQ‰Å`—ηyÀaç<Ðs?Ì€ãÛÓ†˜æ”1¯û±©ç$P58¤=Q‹ÚÙ–dbéÜúú…©Vt·\>æŠ[†ðåž|+Pmð³†Ù<Ìô ŒØO³öášžú»yÛÎþÜ~Ûήݮköm2kõiÑÞ«Ïpî­Í|MfT„ã¾RR•”°7Ó™®Ó.i(Á Ù6Ph;ÛH|Sa›÷[Œ#o««Kµ¦ójóVã>¶“IÙÆÿ qÍHFÛzãc7ïå/fªx>¸5)mPb·[…[,½‰º±LæscNÐ0{FfºÒºÔÓm¡§ú^¤]ÓŽY®›¯ˆò/º1Ê¥¯ «©¥Ú#ð•9ßú[­)Ç`æª;ÉP e8o`Ñ47³L¬]I~'1ã`ÊÊãlQz‹}ÔÑÃþj›åÆì£ßU~ô8ÓK-†ñÇ ÇnµÜì¢m–Jè5Cááz‹Aße1¬½½×b˜„¼3SS<,SG<zÁE°•†~i/!o;Æð´×åmíþž çÙ ÁtÎUÛNHüòò³m-|‰ƒÝ³–-¥Ãaq-8@ß“ýÝŠï›Ù)íÑȵ`êÞú™‚±%9¿é®zö§Lüxv÷Eì€öœ»U»uÖMé^íŠ K¾í¶±?b?ëÖ—ÜTðéMýÙÉfØå%à€¯L}²‚ÖŽ%¼v̶ƒ¾;óc'“¦Fmßm\ë ®£Mh;›`ó°õsÙ…ÝÌÃÖïgnífÂÔ%û†³AÐi]ÚdÛ¸…õöŽïm\DÓù²X1íKÀŠÚ¹—³7i¿Ÿ}QÝdžå)3†ƒmÛSŒÙÈ7!dàp–Ù‡gaØã, ;œeng™;ÎøpÇ™n7“ÃMÇß 08·,Æ;f'¯²wž»Üòap›Å0'|“Å0|K¨ã^‹a6rDÀPS­O˜•ô¸<åñ„rÇv¿¤ÂYY[C_+ï>êûŠÕ‡ JßêûºÅ´A⻬ga,Ú;™‘K<î‘jM’0ƒÑº“8*’Ã1Ú8)ÁBzÒ¿Çìø”ínÕÆ¸(&°µiÆïÑç¸u쪹t“ôÎѹo´kÒ¢Ø/`þ¯Ž Ù]iûãöN §ÇÚ} ìÔ–ÞzÒ·2ÏØÎN µwÆB/Ø©7œ;޼aß(‡X‘ÿqïüû‚ ±^ÔÖ’¬m¨çng5¦IŠ#;×䌉›oŒñùÛ7[`ýmã},Æ=Ëï™åKo˜Ñk;l¾½Ã2®Çµò[a1 ®²|˜aÞvÞŽp÷ØÞÝd10¯ß[X%¼ÕbÜü‚}r»Õç;ìf ï´¤Éß}s˜nÚ5éNÆ5zšì©û,@B¦ Ñ2‰ócYn7aSútD¦îãï×}ºçÎ3Ïí¹=ÞQ÷­Õ^b'±›æÒ­‹_Ñ¢{´n×W—š]¥›´bÛÄ¥PlÇLNÚŠ_SÚ]®¸qÕ:—+æ}ñyÚY_Þß“¾{¨.‹Ñâ¤÷‹J¶âöîºvL)¶ŸUL™Æ”ëŽ 5Ç1'¤ºWc×ÍNcÙꬵz¿">±«6*êjж˜ Þ|ÿÅÝL ³¦šÒý©wé P±%Â;r¢æÁ<“C¬ÍããŽ̇߷ßÒþž@Í¡m½u)Þò/R}7§wzö6{SëË®PçõVãîüÕ7µúW…ü+<â¾GcCl‚ãD¸|íØl½_ä…h÷“OŠ6ÝÒ·ee¡c‡¡¹img7mg7U1…Y™2á>´h¦â¶µÐéj Noðœx$7ÃñLìo]ØX÷{Ûå;,†ÉKc7û½ŽÌÛ,'æŽp·üœaöð=ánù%{‡ÝÌoÙ;Làz Š\oà ®ÇÇÂõXS¸£c ÷r‹a×ßE©Ãcr|&Ôñ•L}‰¿ÿ)wŠƒU_âï˜Eõ=ÀિÓbrÕqŒ0ò›ÔYL2TɲÌ7ñ7[̰^kõ˜ÞOÈàŒUb2Ø|k®¡]LÙr3Åø¤Þ©>ÃܳÀSJcÒíIcÒóIcÒùIc-!Öb#Bltˆµ…ØxÃ^Ø'í¼|Vä8‡½l_,®ÂT¯úV‚q0wì?¯ðÊü{ï¼ó'5R[÷‹JÙ¹óÙÁ-ܦZ×rïR-ól.ƒ+4žPûEŸŽ¦\ts4Ùømaï®ê¯eò@-ÜÐØÍí§G—õíëZÞŠ»úÀv]=Ëûú¾œŒ'*Zà S*Ò²’£[kê+Q´r{k«#2÷™ãc‚ÕázsËrX“´â¾eƒp¿º&ÜÊn¶n½5`ÛÃÿT¨ã³òë—B?îµýÀ½®›·‡»·vBºÔ‹2P©Œ¹Î£ÞíîÉ_ì¹Þöê{rç-ùjµæMÛ±K¯›æ9Üi£ÌÆú¹[±8ÿ¨²Ss×­ËŠN ÈJÙêܳ6áÛ¹ûGõÝ\&gFœps ×–o‰1t ž+V+•vçÎ$×{»Ïeÿhî·æí®½bon§[9€·æätúwêÅ3«¢¼;¾&KoݬåÂé›-þeáOñÛ¨ktßmU½²w¨Â•Gj’\žo.§Æö¥æ{êÝN—sMtyŸÊޛϼ-êæVp«ßw·f±oϥǺéÎî4Õ±Ä÷!»‹ÆôW>_þÑú9"ŽG“-Þ°†ùÖýäRÝ—!ûî$nnhúžûéèÅêÿŠœü)“VG/YÇõgEw\W­æd=ï~†w£»_Õœ¸½<>=sº÷Ë$ÅŸ…~wwä(r ÈA¿MOŠŸ›¢»|º÷5'nnLîUÌcO}ô©M9æuw c<Þ+ò<Ø«øÊPËî~éŽr“nÌÏ­ì‚|ÞZÖêÞÙ=kÎY¼Èæ¬OþUkùŸó¶&wk}ôkŃóeW>Cœ³­9n·‚'Ï ïÍLézOÒ{pÄn΄Þ°äÙÝÜùj¸F;nÇðHc§úróÛáÉÆÑ ºN ¿9Zt˜­D•ݰÓ:±°ßï¬I{wV)êÞtô&Í'€¿36Ò¾'¬‰†}ùìhؗԧμà]ø7ê[ÖÛ8º ¼Ëq@„ñªÂ(ï¶è"—ØíÒ§®ßÂ=/~³çßÉLvÊ Á„¼»o ìï[Øiö¼îÊžÖõ¼ð³¿9a|y‰ÕAnÏÃÀ¢³¿-qK»ÓbÜÒ>—áR¤:,?û¦ÀýÝ]ùÄ­Ëbçd0y¼,Ã_‰Ï°÷÷6õ8ö÷6 —;¬n̘ßk1Ì`G™w‰çú‰+xN€r'žûÂjYˆù»±BMþ~/ÛÓ‰¿ß“ÃßÕˆù{žb?Ä–dúQXœ©©`<‡@}*œê¸=ÄüMQ±â°LMEÏ VŸŠ¡E?sÄ6„˜¯•˜ç"ˆ_ô÷Ý-ŠþÞ!-Ô¢¿ê.S¼3s)y>TÉs*Åî*…”ìFÈýµä{ ›Ø%g;­äלּó÷KêCû”Û‰ÙgÙ¥(~©6¶1¦.nTAfÔõ]$®^Ù;·3$æo†Äü͘¿ó7CbþfHÌß ‰¶Û®2·Ÿò°ÝíÇÖoo?ºþ¡‰PÁXõ¢ÃïÕEƒ‡GÙ|Ü‹l2¢1köìâç pJ ¨ã–¸'¦âµ· Üþžà’®‰.’Ÿ}RŠ÷=íò÷w0†ß ÜÍü-]¿#dª=Å'h’xL‚J»çðp»ó\nwKleÀ}7ïôÆpc^ü Š¿“àX¦±‹%ç»û[ܳÞfgÓD®Ïs°w>FÎÔèæ€Óê|Î=œ?‡/Wì~ëÝ]Ïüôµ]…Ù…U{ ›Üµûêk'‘`Èf~·qÿŠ˜O5NûŠg ã'žÃ~W ßO•öÈV®êŠ_þÙÁ4xl½eØ_'®[È„×ÀnÞ†¢H/~ê){½ºðŒá SüÛÀ9e:¢+ç–€Ó×ucÿZ7²h :£+¢};»jáR¢˜c×åDOç.v\æ½òG‡´T!¡’ç™gyæ3#Ç\ŸÞ¯¬{zK×éYguÕ}æM]9ÌH”¨¬Êß½¤jib;T$ƒ£ƒvÔÿx{¸ü:a‡ž¹ÜNÿª³©Žë÷YöñLyml“钇粺ÑAð8,nÙnÝ6=Ç“4ï®ÍìE—Í;§g•HÛ®s/ŽPóÜÜjVÓ¹…+¦‰èÇ¥æœø~~êΖò—Í~ÓlNÖš¬"÷¾Jol®û{Ñ›;'znQ¬]‚Sãá…¶Ð6šÃ,ìw‹K¤˜ê5$P—w|ÇDò…ÝÓLÏ}ÿÅz€ÐŒ½ò «á­]¥›Šú~•4ôtC3½E«Œ½ÕÛÝô¾í –Ü:lÿ¢®[(\ûn8‰v‘íÄÎ/Ž„ò‘G}·t£ú ]´ÖòŽyØãÀÄuÉÛÆÿ«ç_ËÝfF½ä§ÛáûF†qY6;É~fŒû3ZrßU7ä”ëõÓÜ,ÙùPÐJë–Z}Œ»,è¹5­u4®zo¶=wÚ¹ åÜS¢ÂI/vÜš5Ò?·…ÙiÿÅhJi*ÉsN´[וp^¼^ ¼ÁE pUÊá-x=­ïÆ(kÒÑÞ“^ÀÿçÁ‚[£Í° »çì¾þM)õ¶º«¬Bý—£C‹ðüñìêÌö^ŒÓ9c¶¼ ³4è'Ôãr`•ÇâÜ’Ý=ÍÜŒ=.çfì¹h4øÝ?ޝiÂ|û{u|Êv"®::1Áxp;ÑôÜͪ·(: qrœ%šûã›,ßI~?1O~†¸7L¶ëbÕÙcþ¥=Îuü4M¤)í &^÷‘½¼œg•ò¾¾ßÛyhC®íÜ* ’r à!y}<ñ×SM<•™â˜Cûiô„]?é¡ï'í²îR¾°ªû¾Î…ý´ºÚî4zsy¼“C®öÚšÜ9;ÚÃ8Ч/…D¡óål¯NÇí¶Üìå|+7«Éa™—înöϢçîîó5z®ÏôÖßD¥ ¡­Úmà »nâŽÔõ =ö¯ö»“;ð‹°¬áÎÙï”;pÃ\n:įÓ,­ŠNK×± ãBºûü˜ò^´Í–4Ô%+SΞQÐQtœ¹T‡ ¥Ãúoz;€)üý]<¤/ˆŸ$¤ŒK·)h´l Ú^ó€š-)âãF›ÕÃgõs«Â|úY•Fü¦þ †‹Æ Ìj>G†KÒ'Àé$1e>8­6GÙ^õÜC«¡‘õÙï$úìwШ³Ï—‡>Ó[ßgéRp[ìÏ\]ô[n‹]z]ÜÇ‘5š)†ÏÒq§Òw›Ï]ß1?žÛs§Þ×nw¢¹Ê~Bç3è|¡¥å¹Phuù;#3åwx×ß}eW,剀 ‚«¿7sÓòú ¼óÜBjr»ÉÌ©çþéŠ"ÝD;³r„½ï^iæÔÏ,:$úÀÅgã/6á%ð­Ñ 3Û9£häÂ7èÑî÷U>Bo¬cV»çºªÛÖ1×Ob·/1ÓìÊΙFÍß*˜i?ßÌq}¾™c¯kÁ¼zŽs칩¼s\ÜDî{$ÒXöúhìdÏ¥d¦=w4׬1sï9´äpÚR‰¬ýtÞ6ŠüȬ§sžŒ´rÀ{ÙôÊ~ÞËíÖ§ä:·Ò•:Î4ú¥ªaîh5À…™áÜÌ·áw² á˜Í“Öº~é\KÅr›nÓbWvj³¦õÁIÑÿv´Ò2¾ÔŽG vneÕZà˜t×R½Óõîn¹¹#{ÏßwëÜÁ‡°p©Ãe·¶8.×F ÉÚr,ŒÇ+áÄM÷ün¿§,·5ì)»;ßô8äÈ FF£Çs2%טñǹ»9Í¢d"Ž?žH%ßí&s—ð»‰ÜN—Åäs|gé$¦<6“Ûñ‘Mn§õgp‘ã#³cÏG†cîû Æ÷žŒï%ù?Ýs:´—c¯w¤9ˆMW†*.Ý›èGwîÍ›Æhí»½‰>“°ü@î.›?´Qó¸wg‚Ðñ ·vhÚ[—µ[—:ç5v~Íbb»9ÀynS/{5Ôòwbq]ÐÌ®ó{OñNlÖ‹½ºe<¸Ð1ö·ŒŸìA0—߃ì>wã0»Ïã5v¥ã&›ÝçyXì)§˜ˆsàõºÔᔤzþW"mrCâæäù)h­"‡ÓÅ<¦#Ÿß›Ôí¸û¦î;ÃwFf?~&paüåãš™=èo=h9øù`æ·ž8Üz¤Of÷ úä{ðò MÈ}ÖïAéˆqƒm!ÿ¥?Ûx7{®6ÿ•¾[Ì#7ä%†â|íb/bkbxNý÷ºg뀓§ZoÑ[è†lúé{+]4ž·¼«g>Ä˯i÷9»=ë Ãw?xä¡Ï+5z옣Ž7m|ÑÔF”î}àŒýö™¸ï”²IG|ôÜTg>tàG¬‰æE/"²¶6Š-î-|1å´u¤+V–û”dÆM¿~r®µtNåì¼¹9Çf×,Y\™W|B_tõxöAÛx¾E[öP/n]™À@oÛdËìFÛsÒIåöׂ†Ù³Ø°çî+ö·>igý|Éi=wÒ¼¶®§ä\xz]4 Þ_ñ¬d4lm^”;5ê¹m]n4ì’<ÞÙ|S-_Ëoóµ/ÎzÅãºÍÂÁïwº»²4Œ׉7×de³k¯š“ŸEsòîí»öžhWÓm–9ړżÉ8)p?nbz\iv€ã$ò`pyЙÛi9˜GÏÝG+ÒßHоwú3&æovpwßìòݬMq º³â|´ÀAÛæ¼-|èÜž¯¥5ÌÝíй°÷çH x3& 8?W|òÃ…kéÁ6þ¿ë@Ì-˜ŸÆìâÅÌyÎe¯Üûo '¢Q·#è(m=åo>‡,>县+Ä^ñw3Nÿ…°ßFù]»µP1ùxhîÚã›>ÖäÞoµëñÿ`ßõ­›þÒZÄuŸhs—ݰԻê¬YgYwE#lÖ–5tffÍþ-«U<-Õ˜j­ŠÍºùcUµ‡ùs:!fþüÌ1þ6û><ÿT¹SpTr»ùô|9v¦¶Ê`¸/ú‚סD°ì¶¢®àîD~TÐÕw]ÓYU{÷)ðMã¡Þ îÒ;›ç»5Ú näeØ4ÜÈ‹[!œ27«­o@`õn¶£ã^ ¦öÍ®ŒSÕò^®eŠ õ!àiŽïè¸'UT`yðÓ†×i–ïèè³Il1ýÒ6І‘CÚç;ÜÄš·Æ¯žÉïkÆûN#y¤nj¶•Š”íê"I´3ï…7²:òZ¨Ó׬É25KwÍÔäcÔT´œx…j%§t{kõuä7µu׌÷/j–ïËÝ53O>FEóÃV:›œºC¥KsD ·âÖüƒ>Þ0 -¹ÛÈíúøæa±5½tÜú•ŠôÈÜ8>‰é§×º{Ž:<¼Î=Ä>÷{ˆ{ŒPÎæ;zæF7:\ÎLhžð•4„ýÕ|Ç3qÀÃv±<V»¡k´cvσñEçæþÖî ÝšëOèmÜ‹®€õC;uacC-8á¸qŽÖô5Ü}ÚéAžênÍõŒ]õ â¹ÄÂë)—˜ûÜMáöäu4x' O3ߺì¾1Îèh0Ç¿0‰<˜;SZn—o嚆˜Ùƒ~'²[ã91}õ;‘^úÙ ;ßû0‚õ~agæUøHýœõÏòäØÊþ¼ì‹½½w;etzâä‘~O3öú¡ö¼1æÜyo*Hë´³gƤ뽉ʇ“Ëèê?©KÎç Zgøµu^R9ÆòèÞèýZéÍENV»+^Ïü‹©;ðmö­“ù¼‘"ÕÀ{þs5x½a;Þ½6öŒnóN±7ð¸]ݬnÃóî|Ÿ¿ó ZUoЬ oôm4%œw­ì ÞDøãaÀþ–Ž ßºƒ x†åA—ŒÛ™ôûÿ½½Ag1¼!§æ¬({*Úñý?boÐ7£nñû¿ÓÞ wÇqÿú¿ÚÞ 1ízÖ©½GIicô¾½a‡7ôΤëcó–^yÄ6iþ{ÿ²óÑìíx‡±ó ¸¥ó ·ŸìÙ!—ðFsÙ<­<µ{² }؆~ŸcN3Øí©ËD))HH·G“]ÚÞœvwåD§¶'§Ã=]9Ù½uZ,Ü•ÓÌ~ON{OØÓÞ+{rÚ[XWNî½9¹“Õsr/íÍɬž“{koNn]9ÁLÜY{sÂèÎYp{´''|‡zNôezgÚò%ºr²Ã{ë´—®œ`Þ:-'©+'˜¢7§å‡uå›ôæ´|Ï®œ`œÞœ–Û•¬Ô›Óò…»r‚¹zsZ®}WN°[oN«kÑ• Ø›Ój tå”7à½9­ÖMWN9€Ú›Óêuå”ÿá½»ÃêZWN8 ½9Ѭç„ûЛÓjvåä^Ò›Óê9vå4žözrZíήœ\BzgÚê©vå„Ò›ÓøïÎ _¤7§ñ2Ù~GoN«ËÜ•“×½9­®zWN.<½9¹ ÕsÂIéÍé4üwïBð3Rïï|Ïð”TÏÁ;_‡¹ÿwçàϦžƒw¾g=óaÞùÆ·fwÞùÆÃfwÞù¾âªÞÞùžÁ ©çà¯Õp ºkåÏþ¯ç°w[+°#\QóÎ÷¬W™w¾Vsçﮕw¾Ž7äz{[¶µr­×Ê;ŸÃð?ºsðÎç0|î¼ó9 ?¤;ï|ËèÎao%¶¯øu¬÷Õzà´uþGw¼óu ;R¯ƒw¾Ã鮃w>÷õzÞù†Óƒw~¡}Rïï|ô²ê9xçk5žîZyçsîOwÞù†{Òƒw>‡á¢tçàÏÁ ¬žƒw>·µzÞyœÇí¶žƒw>·Úz˵´µrg­ç°úïBsS±"ѼScùñ³E“Ä3ü«Ö~Nªùõ±máf1àܯþ¦õR=Œ¢gé2%²Ú0§œ¦o˜$ªp˜®èR.õj]ڇώk>Ûé„ðªŸ^Æüj-ŸMGÑ?²Qu,A”Z Ìþ†;Õ}Ãþ»tøÉV›™Z—7yä ãä€U í‘áR—2óp¡YU;\—O1°‡k»¨ÞrWªZF³À#¤Ä©ëÀ]­ÄÞq.ߺ܌ÐV×{¤Ð¼®`#¥²¢Þ”æ“z?R—]雌”K<õp¤‹I3u¤Œ…:GÊŇ/F±‘p™0Š71lQ À˜âò*Øÿ1,½ýäD¬ýΈ{´ßš‰XÚ"vž‰>űäü,=•èÏ»hêâx?çCOßrÞÈdì§IUÕ£å~HÚ¥£å-’>;ßIó¹Y©m>܇";|šýEî´ èv‘n.€•€o¥ìj°ôr–@ ä—IûòXTJ ¨cÙO%ê;þn‰Ýs,÷†{g!7èûr!Ú•%öÍBvR‰=³ð#ñt,üˆÛÝŸMOÈ–I² *Âñ7˘·šƒø[Dß⢆ÍoÑ{ãZÉû GöO‹çgñ‹ãi_,þ‘¦}±8 š¹ÅB šÅšKå^L_ýïq”ûD)k"OÔÑ;Qüê߉â°h†NÚÖÌ-Õ½C3²”š@­K…V5#KÙ‘19Nf›Ä\N–‡`¡ÞS´s5³§°IðdsŠ´~5{§€niû©x{†¯uêØ¸7§ŽU7b^G'º Âîç¶f£º3ñÑ€é¸ßÙ¨¦/~·QªàdgKÓˆW´ký†sËíò›ÓQÝ5â_ô]"àøYœ('" ÕüÄÂu6 ~ƒed5Àìlûv?e9õ•Ös.*þÍŸÚºìÞœ&Ž úyšP€fó4Ý}µN'D³vº¶·öÌráPí³åÂGÚ4˹TÀUXμµïYx]Nmø Ya¸j…&@s»bq\ûŠÕÍÄ1Ê=ªdÖ\T}?»(œ>8zâ|èöÈ)ˆÔÖd~gŠY¥ùE³¨ÞºXä¦F¦z"&?›G%0è WXÿáÏéÀñ.·íw#Ͼ8!®DB#bbáB¯þÒÕþ®^8 €Ñ®.&CyÌ„D-¼ãêh´“ôÿ@WÓEºÖ4ßâ Òi–ÉoòýÂi[êÅØ°ÖºÀJN¤+[‹žðãúE.f—Ëù)u ?»à*?»\üìrÕô³ þ$Æì‚~‰19\6ˆ19\iˆ19`>bL.ö‰1Y wbô61êäFŒ vïanƒßÁbˆþ¡öMŒÞ‚[‰±—PÇ"ÆE‚<ĸJpÉ"†’ÊÍÄÀr(Bã¢D-Ä@+pòˆÁ´fš‰q©ƒÓG v(õƒ·>žcnâÚÑæ]›bÆÓÜ&Ū ñ?ÛÍ,X¨_3Ë܃ £Ýl—{Ýø÷%§ð‘tŽ2ŒÅµÎP×S䢛]¤›¹E\^bûƒþ¼Ô®­ôä§,FOvÚî '°)ˆÑ‡ëmo€Yn°˜…‹&µ‚Y^gùÀ»Üƒx?› ,10‹<ʘ™„Àežwà.çÄ@ƒ°C˜k° œRÇ>ŒÄ, –A>°  ÄÀ70fÁ`nXÄÀ+¨8‹Üì¦Çà sfŽÄ¨ÐW4&¡ÁÍ ³âçè÷ì>’¸lèz0ýhiþªËÌÝ‹šZ܆`:<6fïúMÏtXtE×fê0ªš¶ ¾PªàÒ>Ýiï|5˜Ëšy'N[$\CŒ)ÝÒ®BK&ÆýDEŒ[)8œ|pXÀêĘ~v718·\2ˆ±¸|ìg î÷n'¼“WsEu4×_fæ÷Ü—©›wä€uÃ%m´Ûí\ÙüÌÁ>áË,rÕa~¹ò–˜vy¬ ë|¬<¼ƒ¶gÚ´ùe«”/ù­› ÂnîÓbÇÇRB'¦=ïd1.£ý,¦Û@,•cbº ÄR'¦=?Ýb0ZLûT‘;Ü~ØÍ|iîˆÜ%àøQ~ö¸Fú­Å­’c.¸dò޹àÎé7Г8ãŸÜTš¹ˆµ ;*Oå Ìç[ÂqŸŸõ}?p+nñÇn?ê¾ü•Ûêâ2¡b(ź¾Êx³"ÜAŽbÜGAvº†Æ»[Œ-¤R]Ÿâ=­&]–ù UD¥ŽQfö°}ï›-köp¬»‰ã&Äb:|;¦›s¡w¨v½CõŽh÷¢åšù§jxMtžêÞ窆y^4׎X×Q·b±ï²kÇ/Z6¾teˆu›½Ñ±r¹Ì²ÇÈÉ•™üx…g›2éx€ŸEL—½X^vˆéz‹EL(q±m'¸«\x‰‰—K˜Ô4bݵ™-aíX›ˆœpîÍðP’àÞLà>q&‡î9±¸,0íÑ à:ÌÝD—¬X—_¶Š.Y&sòKîË8Ø«^¨à!±I³ÜAˆf—|Þ³qTU¬ûœC¢±îs=Æb¯¸Š"·Zf¾tq‰…7 ŽÕ=«·!Æn†ùËÆ—8C±Óý59aMùœÜ沜ï²l|á;Ÿ+äÑŽi;ô“Ï ÒÝÖbÝ }ÏVºNY Èåp­ë†ÝCÜ ¹±‡Pû%{h£á7¸ï:ô «Îô ®Ô³lãñÆbb’C8$ýŽ:´9bÝ9‰Ïàì’› Œ® 1M,U rk¯²í6ÓÊm)›V^ˆådnMÙ [6›qp(<{ʨqHÀ žûao—B(hMèÈ«€»£Åº 8”ë*@Œ™2l7S\È7ÀU"ÙY\ £2¤"4•(£¹€$¨FáJ1ð¡Ã‰zMLø!F¥Ž&WÌpUL-T$앨Æ6Ǹå:à6D¢» =Qõ‰P²Ëm8Þ63_7ƈÆÜˆ¿Þ*†Ý 36›"¥yN#®†2¾/¸‘ÖîÆ\Pá‹d/¸®ú©¶Ó–¥vs¥µŽLÌ]2ËÀ– L q§zd2ç2GÜpÎM‡÷\‡‰ƒH©Ë1Ø"ë Wå¬f^ïÕ0 k/Œ¾dõ÷nºd_piÑ]*y{´SJ {¼•H§A3aNÁY‰¸­Úš (:†s˜h?is&Òk®JØi`ªD\Qá©„=–JØà¨„݉fK"¬ž‰¶<È1^nL¤ÉÓ_¨L•é€Ð"M„7„xi´ˆ=“ȳœ®‰<˜‰™˜L.‹ÑÓI„2u%HÀl1º” wk¸¸‰0¬ô.pu̵ B$-£–”€¬ÑXMtgOÀ»Æ ¸î\h$\(bX ˜?‰|j‹í‘À‘D{&‘êX‰ü¨‰á‘È+¹Ø‰ô+4Û 7ÃVGÂÅ–D:ÂQ‰óN®oíâ‚Ôµ´‹ B×ÚÅUh­tõÓ..HsG»¸¶B¾2C[¾À…–.>(„ȵ‹ RñÒ..pçZs HTJ×..HÿE»¸ ¤®]\sp{*­kämM»¸ ëªvqÌÖOA^»¸æˆÙÅ]µ‹ `´œ º4jÀèŸt…Õ..€9ðåYfvq̃‚nrÚÅ0z4)»h¤•¢]\еV»¸æ@#ªæÀ'{AÞÉ´‹ ºàjÀèØ¤!¥]\¦•vqAêlÚÅ0x¿ »ŸvqÌÒGŸ”_s ]Ts€î ò‘¬]lü±kÀèãÀx\-ÈK“vqAz@ÚÅ0ž, R~Ò..€9ð]sà» M,íâ˜OØi&iÀèèÀÆ»0Ú90ª90z90J9©²iÀ1»¸æ@û¦ í.íâ˜V{ÌÒ zKøË.€9Pk+èÞ§]\ЭO»¸ ;ŸvqA˜ƒÃ ˜C»¸ Ì¡aíâ‚0Ú…`íâ‚0‡vqA˜C»¸ Ì¡]\æÐ..sh„9´‹ ÂÚÅaíâ‚0‡vqA˜C»¸ Ì¡]\æÐ..sh„9´‹ ÂÚÅaíâ‚0‡vqA˜C»¸ Ì¡]\æÐ..sh„9´‹ ÂÚÅ0ù0º$0Z,0zûi€i¤¦]\s Ý_s jRsàùµæÀ@ÌgÖ˜Õ»˜Ï©0~S `Ž„]\s MVÐH»¸æÀ7\̿т®9ÚÅ0ë `¼eä¥_»¸ oþÚÅ0Þ# òä¯]\sà-±æ@ë¬æÀbÌ'Ęˆ0¾÷ `Ž„]\–švqÌ'Ø/|i£iÀøê+€9ä£+†&³ð1®„½Ä>ä¨Þ)6ZA¼¦v×!FgW¯à P%ûþ`wÀ$Æž@oƒË?;á.b0&™ø}Üò˜õ»Õ Å4ïŠ\á®KªZ_ò–v빡[°#éyºÅ½ÖvK{¶ ½“ùºqU»§n ÝB}•ÎÑ-ßEºå;D·~5të®/¶[Ÿq}1¼“Â×ÕËÁQä*×-u@_—»»˜6¾bF³’»ÌÅ„»Ô»XQl‹‹Ù ŒQó«A·Ò‚®·F}]±?t•ÙØç]e6öW™q¿uާ 7»ÊøQ˜‚»åÒ“  †*³ƒ„z™ …ʦš3ð©¸Kô=p!Ø‚˜cNÇLóðÂì7á\׺qj›9}âôdÛ‰í©–ÄŒT#þ»æàÔé¼Tí²¶‰ákÊ2`þ¸±4þ¸q´}þ¸ñ4|þ¸#¢‚Òæš¦äAãÆÐèùã&`zbþøbìÌ? óÇæô »\°ùµá q%¬Â/£Ksj1uä»Py—‹¬Œ­oo‹rŸõd=çã=n¾o¦ÄNŒUPr~쇗ꫂDd#ì’8ÅÊö(÷•¸þ=7Êû›%˜8¼ýÓyGOufÎ4Žr•å}kik2ÙåþbIcG2Ê[¿bYC{2*8¡)Ywt+bXåUíqàqØt|Gˆ³ÛiX¼ò Œ°µéP©é >»aÅö¾pùç-­Éú†Î(7Õ¾²…òߘjNÕ×Gyg‘f} à·>•ÉV*nªYÚ@­góÚ%.PAk°£³¹½nâÄê³Ê£üýcÇQQnìOé¦b¯¬—-sžlæ®sq .“ÌûÊRq¤pó’ŽúzYž2y?ä^ØÐ\‡öÜy Í5­+«iK‰zä•M7…P—}]L-6TxF=³µ2®H`mŠÎ¶&[[5}·kLýÛâ !º2…©´óS+¢¼éBÛRëÓDË[Rm †(?Ç—u±eÝÜpWXtS{+gnÜÀ€GwXðÜÆ†¥ÍX!×&ÿxþ©Öø²É’Üèó_̼½Ù—»²¥5ÅÜ}ÿAkâX²×ŠV… ÞVÛ˜ÂÄ”ÍÒÞÀèÙX!ŸéŒ Þ×\­)Uy—»ï• míQÞèøQågÕÕËé×ø(mßÔ²²Ì Ð¥ì‡_ë”­­kM5M÷ñÊO|Æó´ïÖ³Ðùk_’¬mO¿«œçß­“KO^Üí‹KsÓ¿èÈ=Ù¿ó¹ËÏ·>øÅ¿·µÌå¯Û3Ÿ¸txKjó•–|pOßiMÊÕWúþã¸_,¯Mµ¬Ì”}§ §Ùïj©ic*³a°qÿ>º¦­¹¦‡ÜYÑÈô“´¹@9¿ai¦‹Ùƒ´ÎÆ®µÒùÍæÔ†¥ü8žöm)ѬíÅ÷¹°]8]~–Øz,²ˆsê®tïvûѤØH­éƙۓzË¢Šù•Õ³çN/¯ž6wÎŒŠ££¼ÈÃhWÈÞü*¨-PµL–ä°æz¥EùgŠònTWäßòü§m œeË£¼oëM{”÷ƒ­:ŸVé¬úlœEµG·ÖÔW¦ZiÝÏÕ%—7Ðhv qù(ÔJ=8¶S(É‚ójÚ’euuàŠ+ZS+¦®l•Ÿ³$ÕÑ\R»r‹L'oÒ(wçÆd=õ°$ÕÞžjŠò®mÅÕ™Æm¼ê2‰ÊÅËÚp—­Cwf-»RÖº´y¾€IåKDŽšêŒ Î¯mlhQ¦Ò[–œXYÓ¼—/Ù€ÞÈAw“â­à© zYZßÒ< Q:?¶”/çâ±nY”ÿ¾–¸¬ò-ͳµJ=-Í.ãð–æãèãçÛ;eÖ1Ê_@@þÅ£üQí.Uù»íqO>ÐÖRÞÙŽr^¥º~iŒŠ+%KN´ÈkS­ ‹è3êÊòöV˜@ü––†Úùনà\5—H´sKªq¥ Å£—jú~No^ô _¯”E6Ç´9ú›VÞØŽhÕ†°Ï^‘Z^ÓèB•ýkZkãG÷j|죫˜)û躘PáGµ©&!VM&1Çkkâ§É-àãe qÉK[:ÒÁÊOÚ±$ÆB¬|­¾£ÑE¢õK8‚mŠò?»¬¡®N¸øæù©Ž†Î…¾¶}~@S)«m·ñú+ž˜å4°¶=κ”Ëq…å-b|t§)ìÞºtI”wéÒ*.Q~ilÛQd¢MMÇÙ∎o¡Ù+tV‰¾©)«xò²y¬ùâºåúT>­ .I<ÌÅL–h|mSK¼0*W2’à3oc2Æ •™-MÖÑŸoi¢³}¢‚»Óç¨Em­µUl= #¦+ª^™hü¶ÇBšÓGÿc¦Íœåv.Íx¶×±i÷Ë*ÙçW4Ôµ³ñgY<“•/ÝÐ\ÅWæ/]Ó©Hé§Kg ŸÄÏX:·¾~aªµŒøÍii”ü@0ÅÍHá• ¦S2UûúÌšVZ:§vY ’SìX2£µ†E4”²¾Sà¢\iÊ[@fjʧ¡¬Ê_X¤[[ôm"g»P|ƒBgrrÑhü­by-!2Í%HNaŽ3쑜GðXƒÑw4¶Ú¤Éá!ŒŽæQER‘j‘C:»/¯iN®PDº‘—6®lYoÈèöN|ˆYHG×Ò•üÅ:nŠŒ–Ù1ÙÌõŠê£å5TwU ®ìLÙ® 2 (Ì^r'\ÝP Ðûåi\¤æÄés™›S:cÒ/#t¬{õ-…Ìdïð L¸|)ÅЕæo´¸«+­¸´³®¡ ås.Š ²ÒÅd¥Eâ9™‹WÌm±ÜP4Ãíû5)ÁõË`ÙL™ÍÉ;ˆò+X/šØ(ïŸâÕUZ¾"þžÖ¾¬¡yi”÷…iq*˜ŠgkŸˆ«*„¡W'ñ\¶aβ†FeºP.Zš*[Q³R{^,½Í8[3J7›Û[;j*'Óó-E3¾}œ|U\Ú¢¤–¢šèå¹±ï:q€¶4´7&-š¼ÛEÏr;³ð"UsIªq–ÎmÉþÍlc×åø«qIBKQÁõ|méh¥Y­Â¶|–ˆÖßEl¸_âÒ*ÿ‚Ø:CÈþ@é{E üe5Ír¨ÉaãÈ¢ù àðü­$3a9Ì.ªàz‚-¼óRqžW¾”µün÷ŽÕåÎt1Û­³y.Œf”·»à¢†n-ZF;]x¡C_Qî3éÀåe--/H5ƒÊFªæéQÞ¾uÛ/¥o]÷?k¦F¶Ì/n‰ÏÉ…³¸Òèî¸r©U²´èèdûÑ1xH.)š“\aÁ‹Zâfï9ü[4?7º3S„ƒåK‹æ¤*;Z—ÊZéZT‘ ×-€D£‚'Œ—Æq:Cˆ£­…5¯RhQ|â©,>Ú"ÑŠ¥uó’õs:X‹?»´®b:˜ý‚ºÞ@ÜVSt‰v­çÓ‚ÐëV:ª {î¯Z„$Ö2®?·´n~о.¯š¯omÁ¨ ¯¹³}>¥](œgß'¯XZ7-ÕÔ'k™–N6Šd<” Šp½}_¹kiàû–ÖÅá]®lžèÈ¥usX^ÇÓÊ›ôŠ{Ó™KݹDæ:Tç奮 Š-J¶°ýâåŠ9ö%3p#ÙݵÔâÕR©V…È7GÙšícaÁOk–µ8ˆòǘóšhù3EÓ¹:êæíönù#JÆsÿà׊ØOk›U*Ï¢ÜïMÇ߯ ø„çU¿('¥“ø>’ö<}ÏÀ‰ß3£¼“õ= .—ë[–¦CÑ›Õ3 É,-,·Ü Í :”åíEi ˆ‹Gë”Õ,J`ùyK`N_[Z± €Ÿ+T·Vé6}·G?(J»Rå*ÚcŒS+ku¼»t¬\^1wÁ"JÕíHs]ùR×™®ºš%U…•7Ñç˹»Åëî1@œ4jÐü1å§â Y_Iö=6}Åz7sÉE&Ê}!NÈâ5­K©úƒ|*ÁkÛöƬPÌÝ ;õÞ#J«5³£‚îÛæëª3~Ô¨&÷u¼lgrÏ-嚬³òo›#F&}á²YÐD½ÈÖ‰…4Qîq Î55.¿Æo÷ r½¥ˆÚ“M:¤È¡ü”¹¬XB j¹§Š…Ú¯Rê ËE<€‰!ms.5~dµ&žæ<[‡'基,©¥ü(ÿ‹<æKˆªËÜû‚{|Ž_{ýí±bžgÈ,Âä­Ú|v2tê©h‘€ýëjæoÆ œ§”MgæÕêð‘è.LYàÐpŠÚ—•¤;Ñû5(&Tœ^4•ÃóÆ8™¨¥ZQö.hðA`ÿ†Æx[^WTÞ\gYÊÙ1–#9!UèD¾2Õ”ÞY:jLqq”ÿ±¢˜N´ØÆvæ£ÇjùТ…5 ÌøåíåÊå­¡mÏBµo¬³\ü碭,(¿Ÿÿ†}ÌÕCóOo³TYøˆ üž¿´He³‹ú`¢Ú•QÞ°">uHÞØÖ¨_Pä–±­ëÔæ¤µçÙEiNL—CSòó‹Ê_ÚÁ¹Vhë¸NèõÜÆªÔÑ©%œI*ÅÌ‹¹€Dctµ÷Îyîª|¥[ÝЈŠkjö7“ß[±Lg´“š’mm5KéÐòË8Æ–æò©CD<>‡À†ŽtQÞ«4D³£ü³éÖ¥Œ[ïø•^UTÛ>•sP(mæùù"HpÇ¥ZÙ[\ÚJk?– ©‹ÿ4k£'ŸÔ rýAg@Ÿ¢¾c¤ôÔ¶lA-ÿÎhäo3¨øE•M™:‹¯!œ•Ï*šwÇ2 ?漡‹¿sÑ|Fj¥Ê•j±Žs.´>¾=¯„²ùL iÔ_ß wCSò‹˜%Õ=¡||³¨2Â[«–ØY1*‡ïf+«¼%N¼ Ís¾®P£|QÞÅ¥œmÄnvæ+¡h£¬¦öÞvÓïõU6>d¿—Rð0Êÿ1• õÆèÙktØaÉ Ú>‹¹e­×íú¥E Tø€Ð 1‰ ðÑqnm¹h‰òÖ$;9ë tèQTð,ÿ4þû–¦t}Í-Mº×l„ QÕÒäèñ³Ý<™Xé…µ , W7,p¬pamCˆGKW¸¦8µ¶!ÔPºšéš¿tZçæMËjÛª…5_'¶ýï,⬭33\ü°2‹~9*Ö+W‚@¿DqÓGEù󊸮mÖ]û‘ÂüXÝV¤cŸC•×Öô-åPÐ »³ˆMJî¾ÛÓ¦…Ö§x‰ƒãæÔ[ÊS Ó!LÉàè‡Ë „e3–Ws¸5MNûÖ²%ÜÚÊSŠ ©=»:SMï~OÞ\TÙ˜ò}XDf1)ûc¢Tü¡ñÇ»œ‘&º§ôB÷KŠt’xSœ¨qǤ)¶Ä­­>%Ÿ]Ìqñòõ÷Y¿¤[¹Ä#£_ŠcîôbV1ç´ó=­8*Ø·HÖ†¹’¾o }—ž‰¸1ÀµÊŽóÃá®]¥××¹Ãfñµ1ž×Bf‹Y£ µÿì4)‰þOGÙ¥PÈt¦è+úžåŸV]=¯ªªbà`åý«¨•­ouž°‰ÒÓA”÷/z;3ʽ<]DwÙQÁM[½!¿í!Êqéæ—£Ü/>`æ¹øÝv{å¬ÿ9TSÿŒ+ÉÅÞ/z Åœð¢¿û¯­8óßbéWBª¥—þé`Pìzô´qÇEi꣇?®þ3ªþñ¿”ÊGþ—#üW´±­kº}_%*ŸªGž{\a•ëP<îÏÊúBŪ?xÔæÆöøÚ~±ÍPöqO¶h=%_©M¥ÕeaÆþú¸ ï#£ÜæßÛ³Ž¯ŒiØÜ±K»(µXR‡ð-"T²×Ãn¦¥bA2pŠâ³êŠ”»²J…jJe{EÌÑ(Ud€÷$} ªéR0 Y“ò1úCŽòf+¡º|áŸgysC“ãœ~дD?Újи¬Úó'²¸Š.ˆ}!´{M©§/q‚ Êtto4y½®/Ëx¢ïè¶©‹*«ç,˜5 ¡*Qû´"§——ͪª˜]^]‰ù§ÊWõdEù¢ªêùsÊ*çÏœ[U=mfù´c¢‚W饘!+TN/«*¯®˜SU>︲Yèäñòä¹ æ—W—Ï)›:«|z”ûz÷fñlžZ嶺JO]]YV…Q‰/øð‚éÓç•ϧßòÕ¥I¢/èÉ©•U¼˜fO>™y2ÝžüZæÉ {bª³OfÆO ÿØ[‹/ºpwo9é«û{+J_5ôå_ïÔ«“¦N¯ž_>¯¢lVõôòYeÇ£†çŸ-+›Ï¨ØWÅýü«ÇW2ŸQø¸Ys++¯ž6{ºÏ½#óloÎtÉ¢·÷¾²m¾¼÷‰É’ÙûdyUYÕ:÷[ᑲ豙òª¯lyWô>±å½¯÷‰//oã±QÞŠ.¨*+føOYåM°ø4‹Ÿdñé?Ùâ3â¸Î¾.¿¤t}ji¼ú¬bûù„â§µ.cÏA3ïíérÓ'oLWœ>ysºèôÉyéZN˜«éVÑËÓµ¤OÖ¥kIŸ\”®%}²º¿umE-z²¾¿=ÙØ_‹¤nÉÔrú±œƒ²:gÓdÂçdò+\9)3‹¬¡Ó£üw¦_,ŸUv\9zJÙxº¾†i>ÅŸg&Ö¥Ø?ýÂ¥øjfˆ]ŠÏ§_¸Mý½H'/-Øõ$}Xyyo²”f½f=ÊRŽìïU–Ò€¬gYÊWö÷.K9bCӇŽ4ÛÑ↼‘vËû–¤]´ÉüÚð-´ÉnèŸMfpJÞ<›lÆ@çl²«ûÛf“¸qþ .?0|¼*Žß8y&ÙËÆÎ${ÇÆ™3É Ø g’=eã´™d~/¥£Æ«øS=[xü¬Š9ÓËçßÝ߸ìi|Ã@÷ò´‹û[˜§ýò@ó´Yw§=~ £yÚ!ýmÍž–ÆôvIyÙte†ilJû¬ô£žºtY¯«éæôÒ¥óàÉ÷Ñ¥;v ‡.Ýïö÷Ï>K×QÚ»å•U(XutŽG…;ܤjëïšI•mèÊãß1“êÌ~™Twõw‹Ge߀¬W¶–Ü‘ ´Ë¾+û*²Ž¹„(¤Ms ýhf}s ?0Ð:—pêÆî¹„i¥ tï²]ç¢Ä´4ʽ°¿…öYé{téÌÝ'o K—µ©–ÎÃoß>—ί´{.Ýßõ7Ï>KÜ=)ôîØŠ¹ó§—W•O«B½£ùÛä] ‰ìoeHüÌ~†ÄìojH|þ@gCb¿.|{ó·¢3#“â%é'6…9 *>3“âÚô &ÍúX6¯â8#Î5wÞì²Ê(†žÇ©sù´yåås¢|WŠ ²•$¼ËƒÆŽ-ž±¨zþ‚Êʹó8˜ß)å g–ÍãôrÂqåþe´\/—Î=ÚI#žR6yDs 剎ÇU, •O]pôÑÌS5YéÍ®o'Ï÷­|s:~Âì²£©æÂô±¢ ž—·`ú˜ÑS+ªxwÖÌŠitÜ\QÂ;SP)gàÙ Ãñ(Îì~wJEÕ¼éQÁ9ý£<‡éŽ;·Êµ^ž»²«ÞòŠ£ãpé•ñQ÷”ìæD®n_<{î¼ã‘*N_˜óðqeÓèÿÚô#éÈIþÖÜLÜ]M—•Í+›5 ¸P™yzê‚9̼¸¶ÄddÐÌ™‰Ÿ¾`ަ%Ê»Ý÷SXd'WO›5wÚ1OA;ø+.Õ‚Eñ­ûuñxO?&sú™“~bÏmQîn™: ÙÛž Ÿ\6Íe¨¸ˆy²¸j&ÛDbá…ªÒ{J_héœ ý ñ²L·Ž5>݇ØrÍ““+¦W8ýÍØ]<Í›³ØÁæM´"ýFÓmÓ îKm¶[|A_jûƆ}ê¥åÇ1k±»æš7‹f³ÝOæng¯é¼q—GM&;0Ûöź¾g§.¨r(¾/<ËÑÝPÓg>›åœT~üÔ¹,Û•´¸—UÌA\ýʾ—ìóâ½O$CX)…›—PÕÂ\äÌp/˜LõŒ¹ñIÉ,ÞÊw㥶pæ|ai­òÄWV.p+çdð›n1…xýêÑâ²E(x§Ñc‰š¾šèB¢™è"¢Û3™–!´šF—W NšeRÔŒ¤}«Lf„LôàÊ]^~tõ4îæíèÞRžÖû@¬ƒ²;ñù‹y`¨p~¹÷Áñ¬¿Ãz,^ÅÖœ©ý=ˆÓ…Ïû•SËæƒ ÜOß,­˜ I$v—Id¶múÆ&*ONwú¸Ye´ÁÙ²J&-¦Ž7g2‰ãT‡ð}Ç£ÓŒ|Œ›Ž7§“ûµýo´x tãÔJöb6òöÕ©d7çÓüÍ"ÞüÅ@v½1°;³‚7“úß,çMsÿ›§òÆœBwõ&[8öÍ2ÞÚÿfá Tý›E¸¿,¤:B!=ç ²å³h¼ç 2Q):zƒŠZlŽÑDW(SºÂVÌCÚb~uÖ°.lTU¤;v…ªxº.Tgž‘‰ª3+3QufU&ªzÓŽ.¤^{Û³„što³Â#¾Ç…e¢\×K¢ ,šå.ôa‰¥Ø8ðá…Õ ”ÈG…"CIÙ‡O˜SIê>,ø"†KZ‰L++ËçLwÈåi鬧; VÕiز O¦Ço W @°§¸Ô5//Ÿe‚«9v¶|,ž"Á*~6ë±óÊ€ÚÅÕz¹bf‹G{fIyõ,n9Í·0#¿VTÏú|wÂÒ2^ÏO”·.)ìä(²ë þ‘Ìm¹XøZæÁòªy®mwëÉÒ ª.¾O*àZ ÒÉ0ª–°õ oqôÌóSÑŠlÝ.&¢ –^ÚŠ2¢¬–ÊL0jp”ÿ"(Ú}[ÔjÇÐP"ðÝÞèž攚+¯lªéŒ#ã½"Yù×µ±,Nér'ã&³)_Nq¢ï«ŒÂ±H@Ê: PI­T´ò&cDJtsR ‘ãLŽ#»Ë«­äxüôye «§_ò*¼”áK/=чæë`F\óºÀÝ`¶S‹š©«€ëcZGa=ö,·¼F’y:†,fíëDR~­Èt+ʦV/„0pêBüRˆ?¨–©ãÒP¬1%Ÿ})-\‰Ð¸âçÑÂò«ZÆ¥Æ(ÿˆ–1£]àU-£Æ+Pªh)q߇þ¸1Ê}‰4l%±Q‚o¸…—X8¥jî4NMß#JFã¶*ðÄsfsÚ~G-!^—¨¼ë A¸—nÒ&ˆo¼G+µQH«rì€LSåZN•Ñ‚O•÷¨B•¾±A8ªôš ÊR•÷ˆOUöبPõ®­¢qû6å§âwïUÚŠ¯¸G*­òWònåýûµ+W –~¼A(²¸ôùåâ‰èHGW¼ï2ùÈ“+ë¡À9xøo?l¸ÊâA†#šdIK|C'ðŸ>•«…~òÄ §VÓ?}ÚÃýdI|D/óŸ=–ï‰~r9¤NùŸŸ}+_ýb/“ƒõ¢½cÕë²¹õ¯„½.SL3÷ÐfY¿S¡ÎY€Ÿ û^æ2š™÷hïëÑçéï‡e™q~ìy^eÉÄEs<'5¼û±ñ§.ùh§JÜ•Àa ÒbÅ»à˜L¢(©†qWãy?Ê÷ÒÆ»ßãºK¤ŠÇµ rBÒß¹ÔžÞ/„\ÍÓ‡!ýå—Qy:ô‘»òÈaŠ~ý7È&×ÒÈ|JÙsb95å®Ö­ZÙD–kï%–×_Ž‚´•ºµ—k¹´úË£—Šõ’̵²Ò_Æî´6­¸rí¹nç®?*ðJǵ26Ñ_F—´)ƒrWã±Þ&ñºÈµ$2¶2 ÇÆŒ\r5Å&l€³£(2-*ʵ×rd2 öíÚÜ'®\Ë"ͯLÓå4—kïuõ OUà#“Øõc†¬îeaÞÛ-_ñÂÍ] ¬Ã %°zÎ] ¬ öR,ó\{.'äÞPc’©?×RÈæÉ™*ÊŽ»r`WD#tkIäcd€ªÉóUr5ß@¼º ”/ù¡îUI®%Ô ” ƒO®% ”ùoT#:‘«(§',Ãc¦i«R´Ðh8¶n†3N@/É©ÝQUçìL)"#b§Þý|V£:ÁtGâ؇ÙOv¢4“WW;PyGÚýp 3:ö,Ò/ zÕÛ‰ï;ÆXÉ8YÓÓTϲÖÙ­¬ZK>o4‡Ä>[û÷)°È¿×¿*²0[9È=„å6INõ4§ö˜~c´w:ÆÅcÚ¨ hkÀò‹ïÎd„¦ÈË—¦ ãn¥9Û{Éê¨b ÔÿÃåFT<®5ÍFû&„ýx„ÔSYG²pôk¸Èhí9ÒtLØ‘@®¹1¦ìçsýs“à{W›…ÎFÌEØ{Zô0œð±ÿ ~h­Gág¡\²iÖ«ê?r'ú=5 7âxq¢ EÚY$ûhÂ/FnH²Gd‡\˜x¢€Å8ÝY»Ýmî•5Ò^ú®Ê‘+/P”³s<§Æ ¤_P Òÿ›‘«Ìø'Te§%OO+ƒï²ÒzùOêV®>\K™úd#èÔØÚà{„µÄúµ-Wþ›êNcÞVÄ‹iÀµ)Uö/òS®2ÜUQÙ™Ø:;6âÓºI(Jnßþ«~”-ëVùŠ|jŒM[ĵÔÀÑÛrµa‹ÚÎÁûÓÓåêKNÐùøøgÝ/Wö²¨k%Ëâ¼ø.Ö2 9¦}ôo*d®<\kQÞjÀÕÚø40`ƒLšÜ¶}_7Í•„.Jº€¾.†6ªÉÚíÖlUØé¢ªu\•ÖÇè§è”¯£½P¤séqáEú áh^ÛônLÒýöÕ; Ï®Ldó ð•æ“‡úZâ‹€ÅÀ¯_¸ò+qçÍ¿3±)e›ØëéÜu #éFœ[m’çY%M9JÚ!\]Kº ÓE›e ÖõÖQ\o«Zֵěñöti 6Lo³Ä»E°k‰/ÅxÖeL¤¯Ø*\ÅU©ìZâËpÉu™œ,¹Š³ÄLŽÄÏÆÊÔ¶x}4÷ò)$W½ÜÞb¾‰·²<6©tùdGyóp½Å¾F/e‹lR³|¸œœÉ0Щ£Ö¤æzÄO7Dÿº–·ä3¦–­¥éI½(Äöç2¥6ù›-F΋ы¢Å uÆÕ Å…zeÛlâÅŽ™Í«²·æìaíQO¼¸bÎŒ¹QËžÃí-¦É+ÒÃÄ‹ËçÍ›Ë Vì­±›k-SO¼¸²lNÅ´èð´¬Ö<õDÉ­÷ü¾‡Ôé{h®:.f¨9nmn[;à²-6=ìiõ5œÖ$jÚ°«—¬í€ƒÛHÔ´'n›xpÝN>'æD'Ç¢‡=­¡.1åH§Qƒ`^Û!‡$x1Ï=ØÍ·tù1MOE0ö´>±?Ù p90ö‰­j™³ö4r Á® "Ü!í 1kTæAÑäòÝÜb&›²¢' {Z×°ì ϼ¹ç®3?Ýsç™çöܾ6+vÖþ=—L<ÎeËmÇêÕYës§ŒÀæá‚îhç0AõÝÖÅ®m\ø¶aðl6ÄÚoŠ^%ïrxÑÜvr”XøÙÜ)%ywÿCU4|âªÏDE#0§6ÿÔ¨Ðçõ¹Ú¹joËŠ•ìUv ˹ð4z±^l§§P§•meݱ­Í]ÑNáÐr-OPdҔРg9UÂÅí.ö"Û,Æìγ39ßbÌ×¢ò˜ä€yÔ¥öŽ™Úbï°ë~yyóκúa_¬YΖýO±Ï,Ž-z1[n.±%=7¶:|ÿLÓÄs˜ppÇa‰ÚTGc]¢9e3znÂ=_+”>ïæÅV7 _‹2ÖQƒ&zw Ú$[3µÈGÄ–e‰v4ýµ¢ï.Šw á]Õ7|ÿÞàæÿ?ûWagíª3¢„Ÿ× Œ‡æ8æÚ1óÌe}晵5áÝ›yL`wÎü§ÂÌ3G~^17%6U:ê­™†A‡~lâ5—¶ÌvV>ñmîaÏ´;¼‡}I3ë²8ê­CÌú§†˜õC¬Óݽ“®¹{dÖ™Çú¬3cõY‡»oÖ ‘ÑÍ)VJ™uÈGÌ4L·ÇÇÁ]Ôl5`ДY—MÈÎö̺yØ3ë—Ø¬ÃÛÒ¬cEqôÈ! f½ïW›uºûÿÍ:óXŸuf¬>ë²Íøð¬þ››SÛÌ­Jàý¯˜V5OF‘#›7íTìR'Ô¹ÿ[n)Û¹0sšÑ~N¸¯L€%lÜRõï®Ãö!ñp#aÎÚ»£ÃÒqÝRŒCü«£‘Ô4ó¡št5ýñå½ÑE;XsáädÍn1;"Ìäh›IL¨·|#ws13´ÔÞa†v™Åà€¬ ¹/·–ju›ì/6†kÛü¬êÖ2Ÿ¿Ì_¯àKºeÙ>û^¼ÜyzÇþ`kˆ¶¹Ç@|uîíü¦sÏ<+f<ÑRwƒÍ9ÌOìŠG>æåÚ_;ik>;Ü‹ì\hÓ¦KZBãs)>Oä$›"Kqsaü®Fz.ËžX^³þÞÝ-ã¢Ì´©_;`.Ù®»;Æÿfþ·òÿ‹o»;*–Qå˜@|t V¢ÏÞ_•3|¢ß ;O‰%°ªÛÙ9zÓÚMüÊïVTr:VñÞå*ßV:³ »çVê¡æÉv¯{r¿ßín³Ð¹Õ5nΙ+·G°µšîL\Ÿc3 )¼sWßv5sãgHÝÄ 5¶OÇÍØ2Cs™xî‘Ú“óü,Ñ{0Þ´¦±ŒíyÛª› Æ•®f§ª÷wË'çàr7Fë¿{²Þû½‰Õa‡e°îq37s€!íÎ9¸)̽÷˜êøTf5Ç}«n‘¼æÉ: 9 ¯oKÈÇ .9$eˆ’31G"7Kš#¬“c¹tÜ·°Íu«{nKߊ…%Á•s1õîÅÂ'͆×ì¸ÿŸ+7ÞÖ%ªö>±+ç¶"aæ²óvLŽ+ÏûI‘aÎ=øf;}ªÎ¤ñ£­Æ"ÍÆ¢{Š×’+ã:!Ü–—…ÛòŠp[>;`ÏU6ëÌæŽp[¾Öæ+ÐóSãÜ|kÓ=‡‘hYq-`Ñõ@öOr¡ßoél仩Ú[Úxpе/(³½`pŠÝCX™n¶>É’éî=¤^¤}¢7¾O°kÕ’"xñÀÓ»15µÒÿùƒØ©%:ØÝŒ%Eœ'\Ú˜—wwWÜއ«®“py‘š¼Æ×¹¢›ý±:»Ø"Å»kíß ŒgÉ®b×÷Õjw«¬¦¾…¤"ÆÏt4>²Xl›7ǤÓ|˜ØÆÂ´î2ãgzÇ™®o¢²E˜I-²ÆÏÄ+·v]ñœ•ýÜþÝhº°‰†¹eä¾Qniw4LxOÂxǰ'¹ÍŒp9µ+Û×e¥ñÌYëÉ¥›‡†Mû²»\Þ`>˜ÈsÏî6•ωÇs̉ãS˜ð˜ ³m—@çîÜ%·LÃ|ø9’M`cªU&UÇ%öþ ŸÆŽž ÏK¤§ïÛp†ìŒañY—‚"Ø~üW4c®éù¡Í×®I̸e.œÇÉëF‹·ÌÛdÝV˜¹ýš¹é™ÛÏÜuŸq9–•À+r··ìn#æÎ\¯ø½oý¶c ¶C¿.×üt®!¡Œ¾S˜ü³Ìð:fx•føô´:¿Vážè góâ‘ùÕçóëojÌÛ9a~ý†ù]np׆Ø{m®1NÛ‰eFǹ¹ÖL¦s¹Ú‘̵Œ×¼Ô#˦UUW=gî¼rG‘ÒBÕ‹èðýÎÄ„­0r +§¹+ÿl}ç+Ó»qìCszF/éÍY7iÞ£¢\_+Wê¿Û‹n¦P©ë¬l/Òã™a–<¾g–< Þ› ævîÅ]"©¹ùa4?ðý°¿ll¿ŠcyðIGEcζ9+©Ö–°p|ðI¶ÛFóÍL´ªßv¿EEêo;ñn|4Á¸6ìoz[ízh8x‹Û´ÁM_Ú¬˜ÙUM%øSÿ#x½8Xkƒá?iÑåõÖñŸÝèÆÀÓMî=_Ú_+E{Û ½?—³¼X±›õ=š}¥Ì™è³N@l\ú’¦–ässvWí—$pns)Þ']-˜íÅz¿Â!{Kæ6;ïAÿã4(üŽÂî·Æµæ8dχn'BöþFÜ}ã˜lw©6nÀxOoÂÕ<³8¼ð%ÿnÅb·÷Zã{`iÿ§ g€eöðñì½Æß~rSùl´w‘¨=ËÐí?¸³c„;Š™ç©á.2Óv$G2Ïá¦âð‰¹G»;¿Á![,3»+ä»ÉrÀp¿Õv-Ú`ûî.šåôΠË}±Lß&¾} ¿b.lÏtž4Èloa÷÷ð®M·CwsMgnë;~Uxv®‚¿wSÜ®cW®IÖ×t4¶W·ŠÓÜ1qËj5s¶ßÂVém“Çó­÷Ú÷Ýé·ï=Æþe»ÌYhÒ¼Þ›S;ïß&°#ŒUÙ–ö é ñMÐ~êì‘úöˆ¾øagY·¨2øprÞ@Úak}¿O“¹ Yµ=“åú¶Õú„Yå}w1zãû„¡eÝUËp0'·ôÉÜF¯É^Û}:G¡^MwÏÚ v2¶w÷ôÍîEÕ­ùÊöçG` ¹³‡FyÅõ¾ù¢Š§nU¸­LþEo-IÖ>Ù»©Ñþé;Eoï<~ wÍÖ;´5üüa ¹³wFˆÈõŽ~ùÞI6%BÏ ‚¼Úa/Ú<×ÿ×ù³;™öÞíN~duõÙÝG#"æúHï|‘~‘lQîÚaßœÁëÿmLÏàƒýËn½s(VÊîþm:×?zæû‡ŸDÃ*Ü;¦€3÷Ìá ÿu'6:¯c)lØGb­ŸõyÄìtg?Йë'=ôýÄ µöe…)ÿ487üÛ>:“pœöíuúæ{(ôÁgkÀÎùáÕê·#ƒ_…eÕ¿¾[º5Ÿº%íDëcg\¡5Ü”‹ÑÎĈÞG÷g~4Ñͦu·ç _v_ –:‚µ4y]¯°ÔËŽ˜lÈþKÍÛ‡>Ýs¿íÎ曋Óvú8—.¨Ÿ›DWÎzqþ”}}áQùSöÛ/Ùµâo Kr¢e]/‹Š¸£ŒæŽ2ÂÏëä|m]1“îúÞÖµ×e…]Ý[HßWÑ÷5k¹líÜÛÍÁ:âˆ7o&¾‰øâ-ÄÉw9ñ­ÄGM|ñkˆ·Olß<ï¬õÃ&wí—]¸–¸fŠûÏä‰×öôLš€µÜ¶|x6ºßÖS:éÄç»x‘x›í—ô>ü~梺c ÆEYESÜ</ÌûÆqºX0Ò ±¦ }¦e½xÒßX3޳„ùÝ·•-ˆº½Ãüú;06嶇xÓ~Ê!I"s×_loуƒ)»ïÓ~Ú˜ª©‹Š¾›koegÞ¼dÚO“uˆ4]ÚtP|Åâ¼ÑBÑ]{ÚOÑÊSÒ Áò¼¹ŠŸ2 [úµŸÕ1¹Vˆ©Ñi…˜^8­Ó3_“ìÓ} Ätiþ¬?²Soú#ÞÌô¹Í²Ešõœ“8oů™>wTÑhæÂQ5oe»Þ̃ø4¼9vvš'Ž{óVœ¡ésG•”ÌŽvÁ9£y+{ö¦&m½és],cð¾^É0˜·b‘Û÷‰ú|Ÿèï/¾OÜeü q_n¢>qšg¾N³Ý†…2t¿]^nÚìñŸgŠ]Ÿ__/µø¼â§õŠÏ©=cßÉ€©G<ë™èPýpo—©Gö ³½%çf7‰‡=k^MG{*»Ëx{+ØiÞŠÏ0k^mÔ[Ó¸!iæJ=å…Ž;{A~?WÔYŸ¤Ž}_àûù¿€áÄÙŸõ©Æ%5~_ÂÃgg‰«¯wòŒ °roÑ•ã­î³>…ßéuZš®NÄwÁÒ ˜%^Ê>ŒC¯<®¡&k¨Ý÷Óô§»Ÿ`(×Ï#$ä÷ðwõëfwD©ü4XU(oÙ딹sñɼœ×ûÒCe·I‹ÐȹþÇ <(8Îâ?5‰w«ïð—ǧù—Uîm|Uš[&í¬ãAMè½çгÉP9çÃó?Ø«“㘙‹©;ëø†·át Fu©D»f7w!ãH™ùð³"§"p¡©åˆ;ÖžÆmæ-ÑÎ÷ò÷q77Én¬¯_Y-2¢îÝ7Y°[vÄÔN§y»2‘/»´f1@¹{6Ò–#W£­Ð°–Wúnæ>V¿µbãÕð_¯½·xUïvÌYÔs4;Fš%íÏŽ rÌ¨É 4Ø%+"*”QËMëlóN!ˆ{n´€²n)¶Ÿp.´ÿᕵ?»÷¶©[YÃ8F?$ß1œ¢Þ5?Æ¿XÆ —foI!µme}»çÀ7>½á:}»+˜¶x‡$æöüzJl·‚Eçq&¯å™Øþ£U¡·Mh«Ì®ëß·»0âû™K²¢’µ«£égŸ•®ý4ý1š¼EíöÕü³Ü¬ô&o¸Wù®gÇž7Â0¢7ÊÉéòzþ{Þ ­œg½E¿bwoóýH?ý¾@#cûBWÌyŽ.ûÍmû™pÖîRݨDúâÛ4q˜W0ÈÚ%}….Zª1Ïu³ =Ñ‹EàG9í…ÊW5O×Ý•:¾T}~ÎE¿¡c~zøR7ÂÁ'È“ºqVÛ$›'Ïóg·x 9pË"Û3ÌÎ’€[œÎ‰Á-+BNC.‘æGç\Þá\™ós‰.·+±‚£Û¿ñCrøž7Ù<ê¤n´hï¨1Ûy†«<Ïp.lº¹¨´×D%%ÝYÏÕìÍFÿÂÏÔêž(›¹Z·ê–»[ÄQswðt†Ý\n*Ñ®‹£Î6†fsÓÀljïméfÖ9j©pš6WE'”€|Ží\úl /ÎÖgwâÍÌô®Çx‡_FGˆÙö㱇汬¶—ëaæÊáË„{›æ:›ÓsBìËÉÍCgãöX›&áŽ=Ãϲ³*ºX“‹ýAá(›[lôt›ÿÝ:v†ÓùGûÄiИúl »p»@zùǼzªt$ÿ™®mYM[b Bã’£¼QÊ-©„x˜S¢çÔb{BwnÀD?vË1¯À.ìeÍõoißîÙ³q4Ys,Þpû&|fWU¿÷áV˜w;˜”­X׆oÊXì$®ïøl¾©Gœ‹XoTãtaHêp5ÜÒ§ÅB¾ïॻánJ¶â Ò(½îÕžéÙífμ&$7»%6÷p㽆¹×Å<çDÚ›,†öŶðnGxwmˆ]ê¸%¼süùžÃnÞ„)u;¨ֻû: ð¿ue^´¢5Z~¬½ƒgÎ;aµE+”Öíi*Ä\o›¹I-Z±UÿÓé¹L€•®™œé0X>óˉ£2Bóša}³ËïØ’Ïñ`ïãÝ“`²é{ÞäÅ`¼Õ€Ï1»kÇ4OŠ1BóQë¢ÒIŸìéQ}g?sdɺ ÿùÊn«Dû"*[Ýse¼w”'ÏÍm£Œ¿sµwöêÛÄZ7¼ù‰VV,Ž–ÓYçØ»²¡ £¨ ô3lΙ×ɶSàÿ;Îs‚Ô¸vÍÁì:br8í…Dz·†ØÝC«ážPÇ×3±ü`vJ]“aCF»”½îô „û^–\¸ñ¶¨Y~”o>•9Êt””Cøâó—PY¾Û¾xìθ>®(‰’¬Y§ƒP×Vϱ{kŸ>\¦-æ5xçôGé(ì»!2~&ÄQŒ÷f&¤§pâ0Íć³znJc(eØ–FÇc.쿹°Ú÷ˆ]'ßË%con™Dpn5»ìé_-ì>)ªÈcn)Ï– ¼sÚUã»rÖ—²ÓFï½w´¨ëäì½÷‚ÃfõnV‘kò¤—EYðÂ&ÜËqÄvI;dnO´îXËH¸jz³j€'özZ?†wç]윶{ÑÐÎ9aa=Ÿ¿cË>´™Eøÿûi´Ž£nÑÄð³ht©[züÓ?[äx•+—мîk¦}”HCÀi%Òxˆ‹núâo7èè¤~?/—~ÁéXÏIÄ518Qlu|½¨Îî²î,+µGP–Xƒ{m`×stÄQjé6ÝûÝ^½§w³ Æ^­íÇì-½¸ç‰¼†ÐÝ¿‡yüŒÊhÃÕh.ø[?³áï/(ͻ݌¾^zßG³à! 3~ÖàëŽaÖ4¶'Ÿ»DNÓݨ™ƒ:v#œ@×—³0äTå'ŸËå14ùˆ’öÇåíqöTÕ#ú¾å”æSt9ur>ù\x%kðªßqNâЃÛvyžÍ.¼MèZxò¹[î¦Fÿ£{V…~[·™ºvöÞ»²òè7¿;èLø;œr.oÇþè†z3X÷¡z…{<óïwóê°™™w‡13énqæö2¿³ÙÌ ×ô$Ç&Ûu-‹/…»*3èw)šÒ À%ôÔ¢ûuŹíƒ8÷„s¯»%Ö ìœM}w7NN„×D„‡vñÞyl³y”}ÿnÒ.´€ ×ø¹îþ`pq˜1w7³ê4°iql Ú„ò`æ =‹Îyû\˜·\—#‘N†¸rái/ûܛֵŸÿ,ù¸¥m>9?¿ai¶¹ÐYʵH»» -fÚhÎ~-m©n!Çín´+fw‹ vÚÕ`ª¥élSZÛ ®©PŒÅ}Iù¶`Ù§‘[ò½§]Ý+ŠÚV—J¶9ܶ¹£E6 Lj „ˆ¾{KTst»ÕÁìG²s©@þꣻݡÇQžN»zEg”²9’†38åiW?¤+äôýkïÎ.³}„Pzcè¼/l{G4«j1ºýwÂgÝiͦz¿·¾[œæ8Œ©Ý7zóm¸ ’Oõµ¸›ðh×›fb‘b†_°ÍÝFèÛ—ƒ.Òˆ.÷W“Ù¿ôÒå[;oŸÏ€xqe4©èë§¶zR®A•ïÆžÐÇÕÉbNCÒì© ?ï4qé9ì´ì#§edrÜlwCöÆí!ß¡>w$¦›`WÞìst,:ï/»2:HìžtŸ£‰!n[ m^ñãÿ£³sH‘ƒë^*÷…:¹ôÉî1hU8]‹D¶xÒ1}ò=û3Bº{·pÇ?£OóE»¢hü5t+¸!ÿ€§Ö7k}›k“=×ìÑ+Ëf°Íú&ܹOÃôÊ÷íϵ~Õ7õú̳/q3úÂÙhqïÁNûyÍÝiÁ´s®£mk’Æ05 BÍâÌ=û´{kA .¤!uvÔcDQ½íÓÑ9é™ÉL‹™¢™þ¤›é§ Iýœè 3ߟù7ÑÈ3ÿŽß?DcùžÏ÷<òDkß‚^«Ÿù‘ÑLâm®˜§âtìæ¤émõ†­UgÚšm»•9p3ÝiC/›ëË;;=Î`æülË9ÌžÙþzÿìÌ-æ…ÑtaQ£÷(kmìÃmÂsýXF|º­ž7/ä¾ûz”xGŒ½wNÃ=ÐöQ~bv÷Q½JûHïü= _B'q£’_˜g<Ÿ’D¹Ó9+×?¨ÍÝÒ4_Pjl„|.Ã{«—9 rÑ.®O´Ê™yësø91éS AóàÏïç;Üê8‹ÜgÇ2/ʤy™¼öSì«ûÁ–‡—€/Ûa[^õÎhzïìø<Û¾Íÿû£ÒÕûE­>*ÑøÙî¨)§;êzJÉð®ÚÆw%ù¿:úŠã+¿)*¦ÖÉz_I ïÊÛcxWÿ£è+Ô>ouu4rõ*éîßßsrmvçÉ¥Ù]‹sVjŽ«\çãa]œ×t?EwÞö¯“QÅ«]|Œ8]ù6°ùl{}YD·Ûîgvï ÷#Ï#c§}9Þ]™;ïAS3ü S“ŸU‚jÝî÷«Ú¸ïN`_ûݨ˜;ïä{ñƒÕû3ã_)—/‡ÙÚÀF­P7V]Kmà’™|Ïçûlb5s–=3b÷1=jE£æÜY÷û¡Ù¶OzV·Â5ÄçÌüî·G“»ÖÝÝÒU{xgWwzæ[É5Âq-¤9¬\qÕ§ò§L‚á¤!™Z›ØÏùÖœ[K‡2õh›·sod€å¥Fxl|—8_Ûz®zÒÇÃíàAg)+…7Ðzp@A&A×ÙÝ& BϘàë7ÈüøYe=¯¶‚ÔÏ«îÇdæó8/«ÍÍ®wnÔÕ­TÓ4ூ¼ü<ÄË2}ñ=‚ļ ëœ÷îTp@t‰› *澟]7íâZt”£]7e‰Å“oêŽ&”öôL@ýeöa1—ÝùJ÷†høÙûF³ÞvE4[˜ä¬óò§,ìΟҕà ogÀ{]uw ^Vo~æýû­Zž-õ· n’–ÂM[çqcY'n¿RüÊ Ây(H·Ùq" ÒdÛ=ïÙ-ÊÌŸ¥!„ä†p(wà5/`–¢®Mf–¤"Ö'ÃÝÇé‰9<Ñ åsän÷fŽœö]¡ppŽî sÄìø9BwL÷’¡Ü–Ö:ÏΑ0£é{>GGQéìaà_]c‚P=ûùñnê“ažnt/­ØKŽëeæÉùÀ(p«Þ=Oß óÄ ùyß-‡£.Xö_öÒlŠÒûy¯ß?*™²hçÊËNꘟ¶!æç–Çö‘ |~œ‰™Ÿ¥6?@¶Ý7É|~˜??²UÈ^†¦ñºŸýq~nÜG³ézûMì ù«z4[}4ìõïî¡Í{¨¾×ñª¸o¯3;~ŽÐ±Óy8÷‹g.ÿãíÚ¼‡Ž*²´Ïûd˜¡[ÛEfˆòrÜ3CËl†Ä£ß=C_ 3ÄÜøÂ׋ðúpxØ¢?ÎÐfhkNAû=ûèþÕñ>ŠV Ù°Þûè,-g’ª³TÇëº =Œ×­/;KšpÑÚ|Ñ)ÿe–ÀEÑÀ.jRuÎOukÔVq3ãnÞé½çæ­+ÔÆŸv4çSðËjZe-~Ö¤£ÿ>-—?}Àg™î‚s¹Fíød4kd^”ภØ>šX ±™ÄVk0o2+ˆq3œGl ÷Áy¯aV¯¼± }Õ·ïnñoÞ¥76Þ®øöL|‚‹ë~®7Å´ŠMõâdwGw·JÝ3—u2ªêº"QÒµßî%«ßžæ)L•¶<üj_iΛÈYØ]7ïfÕã4ž~ ±2N›ç0ìöÌK¹oßhóÍœÖø‘&VޝãGšçWl Üyë>'sãd–Ó¹–ÎoB{G¢[û¬âœ(ÍÕ\ÜdÍEÓhN3Ûº†zŽÁÅ/÷ƒ»äŒÚÈ1˜¿c0¾…0Ï/hç2Ú»=ð v|*½[n »e ’É™Ý'l·|ŠX+üˆeôdÅi«ðt&D& §-ÔqrWNQ±vøÖwì^Òuã¼ɦíÅ®Ö+o<°sÕ'÷ê|ìSÅïé­áfjøAþ_ˆóïêÍ¿íÉü×ÅùW½fU4û´£È GìµÌ†_Ì>K]¶}¶?²@‹FPƒð¡{ŸÖñ{p¥œcü¹ó3¯ÄíÀÑiÎ ;PÎ7rÇ£¼4éóŽ4Çîí&DðØ”q7œç³Ûœ¿‰¾Ø´ßMÌéЙ˜ËW€¾4¼ûLf_Æ·ejŠW8ÙÝv¤Ñu®íÈdq†ÓÆ^Lw$zÐÒò n¿tìØŒ©L×}:šŒÖ_{æ¬;‡º•bËý™1‹3´›4gÄzù€zûcžÄNø"9–Ì­‡U‰)ïé´Â N-çÖôÁìÜ YÚ‰/ï Ø‚Yñsƒ¶ôßF¡“pYás#Õ tü®ýsç srÝ Ñä·ý&šõç9X•¹‘‘YD»ÁÝ,˜Þ9ŽdAÚÜS­çhcwöüÆÐsúì{Ž>µ8٣МxöÁ›´¦ò=ë¹]àœyÝâw‰G0ŽÙ âÛ°—¶ž>¢l.ÀçÈ<õyEnÁÝ›<ŠuëÝlEGÎãή¨éÈ9-ö«÷ÖQžsç ÜøSV—ÛÎúÞâôïÇûòcËÞq}4 ïW¶Ç¼³¤ëñ]ËðŸ¥4hvÁíô[‚È[»wv-†3%v4Ì lì”-i'døÞ5^°¤É4ÿí.3ʰL×Ä8pGUsÄóŒhgç¼|6Üa˜?/ÐnįØÞÉs^æ0ø‚ž[û0¸”›ÍíJ—š¹( m?7:ûLn€×¡—3[^ toá¦Ϊœ±i,÷kzs]5{TŠ‹F+GNᙫ‡¡¹ü0\æ/À͵{eWÎnpÀâ³ü}këÉ»ví›U¸¼®š&»š„-ñö³¯tèÀ~€^Vg g8ì‡ ÷àc›­ºžá0W±ŠÓ)-HƒÝk‚Uœ–àÛ§ ]ÓÎ;H«DÂÝ Ïü ¢þ^`©Öúó®}ÈG¤ðˆá¾åºœîÇîDK»¢;Ó3¤÷#Ð)+‚ûw–û¯–vȱÌ60¶éV.Yéõ¨wÏŒÕÇÉ´2¶ açzoÀ.ôÝÏZðÒMW·¾rv¡×[“{­”®¡ÓA6ú–[Ï¿[š©µ= í‰'pÉÙæÓã±ÖzŒF¿‚›Ó>.8=úõMoýÝ úÜ=ÅH~þî±Co?¯E+ô!›EÑÞ°rŸ¿û½>›äÈo.*—é®Ý]‹ß¥mÑ—ôÆxÒ‘7!°Hîi.^xE4¥woì|Jµøç…íŸÐø|IÞ;M)ŽQŽÎ7š7ƒ½vŒÓÕ›ÉÂÜ" ¦r¹í¸™-g]_:qƒnMS½o§´6Å¿ãÏI¾¤ÒŽßªÅÅêVϼÜ]w *Ȁ׸f§;‚‚4þ=ÆRWRbbÞ'\·˜‰Ý4¡n¶ú˜ûO,ñåà-D> ÐÀ-H#?ÕÀ6ú âÊ‘ÌvHæÃÎià“ݸVÛÞrJÑäu¸¦>çî ¯Ú·û£ëeû–}ëqœ0ÿTn‰iÒÖ1×c»V¾£ü|"`ç3î˜Ð\O¸ÕæOAKz¦Í ^07a~Ú¹íüiH^Ø9¶A˜£<ØæïsôÊÍ|ø¹¡F77F³X{yt ¶¥µËòEw¹çsÈÝøÍ¾èÆóvÂæ·x;ÕÞŽÐüu¼Ÿú=ÕÝÆmÆyªëÞ›©¯:³ë¾êˆ¹XO§·düÖ9 ‚üìÓ“³~ëì^Âk€˜cÀGW9Nqªéo|-³òfâ­OèRÌŒöIëkìip—O™Â&?¹ÿÓ#ß/üˆ›2=è«GÁÍ®sôÌ A¦ÍÑÝ ä9ºžIn{}u¬Ùdëe· ¡áÒ{uÏooøgGeê€.ÙŠÅ=îVÅžx/çšè{Ħwâ©LN߸8G`ÝóÂm ³c+rö“Ö5XéáßÇ=×£°ö¥5²T½gl²›V˜›‚ü/¸¹) _œrž¶‰›ÍŠ™ÂË@Tá gJ ǾE¯°ð"¬·b<½pf”½Ë‰6_â1pÛ +æ…›üíÙùbßscóÊ%´;æ×õÆcNñ',ün¿‡ÉÿŽ!·Á»±Ø>Óöq€^;ÜâGz>:ÖÖ3=ö·n0NÓ¯€‚sºŸ¸ÁxŒÉ­Åsph籟»‰Ï3ã÷“æI{2JÀxQ¤:?âÐô©07—ƒzæÆªºïTÌH÷Ê̈ßKf¥º:vÎÈÍaF˜ ?#¸xmkãN²#ÿÿ›ãQƒ={ß/Ì­ûá_ÙÞü¿ÄÜL MØè£\i¹(#ºöQDî¶®œ{½t~éÌݧҷ¨=s‡ïL'ë_gÐi˜™”ï3ƒºetùbËgÐÞì JNzDòÜE¯zùýxÔÝ—v…ûÒ^ßz;ÓÞŽ·;R<€Á\®™äò>é:ë˜nQo÷Ý¡žÄ°Ÿ‹žiw¨|&3Nª™¹úýÉjíf7§m!æï°ÄóL™Í½ãviÎ?&ûC´E¿P§Í5ÁÝs}.£éë²M®ýÓz\Ÿ!6Yü.}·ómöH]O½ç–x[TXT‹÷D±xj "Ÿ_‡Ù æu{Àhu¹ÛW!åð›_ü(¥\ Ý™_ËÅèšQÏÅÀ—}'§@3–Î"3çg‘úœ‘ZØÆ[£î/»ª¦®.Vþú²”üÒfÊUìQwLtøCr×›ð\¿ee"ÙY›LJaÛÍ5=ÔènØ/»jÇ»ГÐüÕ´õvq‹ÜÅ¥)½C [Ï»xPÿã,aò ÛsoEV­­Ng ggülσe.‚w!ÏłҾ»3àñ·5<¦jO¿ü\xlk;ÓVGmtž›ŒæØü°äçæ¼Å¼|“¿3?xãÔÌ´¸[ûP,¹|Ø”¦õÎP¯¤ž™Ù=#¾ç3ãýaæsb<Ô8Oœ¦ßíÁC÷Àü,²ùáEçü\æÇ0ªÜü±ðb¥ûÝËÏM·!jågÞ“|«û§yï…ÉO­ø»ÃO˜n¥/w»“Mn_§TŒ7.ÝWMn+p‹6uˆ9jêÔ5«#¯Åúȳ¹pœOͺ_ï®™:}Œšð¾FN´9[É)î@­¾Žü¦¶îšñÀNÍg ÖÌ ùuc½ZsÓÀ'šøÔÜQ5:ÜQ·vy¨21ü²«'&ÆX;¿Î…ÕÚ.¦­$þ”5¼›¦nqWòYó§ï¬§x9g&„%þÛLà霙_f÷LУN?ðŒ˜ q†¾;Ö7ú#3÷t?xw3aø`~&ð2N¯ÅaÊg"#¨ùžâ]œþˆ?öÃþ8ß[{ç¿ä̉xf»ç„¾øµ3'šÇ£ÒÃún¨ñÌIAžÀýœàKòêeæ¤ÊLÏ÷9¾¿’G}ÊçÉjÁ!¦ïxgæÄµûoûïgÌ Öî¹±¾ÃmŒ:ǽ‚8~x,2ï‹kŸ«ËÜ’”C7ØïÎ}xlÆñðM¯´ßv÷ÊòmŒÚ=&ÁSÕxrŠ;úH:ê¡ÖOöÿRôF<æÝ½aÞ}Œ~ø=F½®üçÞX¯Tv¯à7[}21ëÜÆ¸©øý„‡'¿“ð²æwÞŸÚ,fýnÛùæÏ|‹sö“]<®ßÜ™oñóú˜oøTÌ0÷î²>”lŒÚý ¡Å ‰WþÏ3D­~†àNúùà.îçãÉÙ¢f?Cxâ÷Åh´ÓÝþ¹/ÌÉc}Á³µ¯Ö£ß/ƒyŒ/üÆIÛýÁ¾äsê{÷'ß 0ŸïE²;_QÜýåÇÏì̃BÔ}¥åÀc^‹¥a÷LÝ z¾ð°Ä~Ðy~÷~°>¯mã [ytßsç Ÿ ïJÔ$=Ý5ÑC£&·sŒ?ò{É)¾ã÷f»o‘Ÿ›ëùÉÎ=^¤¾l1¼oÉbø†ºÇbøLúœÅð“ôY‹áóè3Ã[ÒÝÃ7Ò§,†·¤»,†·¤;-†oç;,†ÄÛ-&qUl ŸI·Y ÿD·Z ¯E·X /?7[ ŸÈ7Y ÏÊ»,†7¿-†7 ,†Çžë-†7ŸÛϵÃ_΋áç‹áke›Åð³ÕbøÎ‘—8Ãóî‹áAg“Åà›n°>eÖYÌú‘±1<Ƭ²~dα˜ñÎëbøiYa1¼í.³~Z–X ¿,‹,öÛ|,µsç[ Ÿ ó,†v‹ád¦Åðì1ÕbVãÄÆ¸ïO°~bÇ[ ï±çàÓÕã<½zœƒOKð×áq ¾<<.ÁoªÇBøIýJŒ…Œßý¯°ÇåO²¯•=^ÅAv.ð.âw8~?üLjßáøËð;Ξßáx´ð;ŽŸßá`M¿Ãñ”áw8ž1ü—®oºÃ¿v8< ¿ÃÁÒ~‡ãÂïp|MøŽ? ¿Ãñáw8¾üÇ÷‚ßáèµûþOa‡ãÁïpü%øŽ¿ÃѼs;ÜM¹^”J‡ÛáE±Ü/ŠHàvxQ Ý/jÝ/JUÉíð¢”øÜ/JÇíð¢tåÝ/êÃíðb¬lcxúp;¼(’ŒÛÕE|ú}^Ü%³Ï mÏíðâ®™^”îºÛáEiƒ»^”ޏÛáEi\»^”¶ÛáEi7»^”d€ÛáEi»^”n±ÛáEéëº^”¯ÛáEiź^”zKC¹»H÷»ì¯‡k¢ŽÇzü¶xÛ&OÅhœãõ/Ø2P³EN‘VŽ–ÿžsÃq•eGWW6Š D}hwê6zûëm'I÷i6ÅdÇ11ܺ5Ž?õPð©lmèxª¶Ùo»h{mÞ?ÂwjC—ÇÖ†¶¨æâ@æòmÿxï\Ìt=³·Ûõx ¶æöMÆúÊL}xÄÓMõ@tß¾èÞú¦ÜãéßT¸ºÐ>¥oºç½ýã›}û6à“#ëgÉ}•9·1®>t!Å‹8>ÆÛ¹µ¾0ŽÓñD‰¾F4åè¡8Ë7—m­qz¨ÑÜοS¡«ú7õ‰{só¶î©®¾Î¨ñE©ºŽÆ$2 ßÝKø¤e¶uó¿yÛŒ÷Ïys~x)¹ºÐìdßéNúŽÃ·ömÊFÿûj[oµ¡ýHmº ½£áÞ}tøFïù×eüÚÚÐÕdgèþòŽ÷míÛ¬>ä?¨Ó׈.'3­›Ç;þùÞþÑç§å?Í—̇põ;™½ž™¶³Wõ‘¿¯8W<õn<öµ;vv§wû'gÉ?êf|çù;ö]‡_ûïî;¼ÉªŽñÌÈ-å÷ÎÞ!ÁKü#ðËׄ_z&nÇ-[{vøFßìûð—õ iëCÓT;z<\»[.ÞZß!ë–ÕÄç¾åú­uü¨?Ú1W€‘ž_àgöÜZ×aýžÑ¿WÚ¦Ô&ÎÎÏ,Ú£¿_[:è|2Çâ<üÌ_í˜ãàUüs …ŸÞé6ý3_ÞŽ‰:½?\Ÿ« }Lá–ñÜom=µ±ÅŸø#-t5¢ãIº½þìÜíØ¨Ç;ø#CèjÄÓ±PÅxn|?»mßëå{ß¶®Ûúö5ã}Hˆþ ŽO?ûí­5Ÿ°É¯öÃ%÷Z×öuÃCÖ<ĽëÝ3¶b©›}î~› Á©Ê£üü îÅ;'Þç;wß´öZÐu5ãfžÄüùwÝ[óÒûüæî«ù!ë¹¾×ÔÇ<‰;ý ûn'aëN·ûêö…ºÑ&Õ?m‚_øâvü‘ú¦ÝW›³PëûçœÚÄ=¾­z;nÊýÄþð†æª°ÍApÅnûèÖÚ¦÷ûY}XíI[zªã ¸Sï9q3®Î¼‘>Õ}Ïà63Ïâæ¼çUôìÛ›ñF·ÎG§Nf!]F¯T5Šó‹½>Õ³¾ÚçÿòáιšÐ ¥&ñ,~é«÷Ö41]ÓeKk~+E·T3v\†÷^voM“‹b½D»Ô~pÿC·Sµ gà};í¸Y–=Ù38×Ô¦Û÷ûNÜZ›õÌok[‡àÅ÷vÞ§UÃÁÜÞ÷ýÍ3VõYùD¿´Ù‘Ó·÷»·¦÷ùüþ½]Tí³ƒÑ-yÿÄ­ó0k«×Å'w:­Ú£òþ¶{{8©Ï»á#‹2ëZ¥Ò`9Îûûß{o]g=âð‘j{múhvÀ²ÃåúZM=æ¸mÞù)¿Vº«íRv‚øX»7uyÉ{ø4ÞmÐNe'ˆOxûáè¡·`VmƒÜì–©Åè—U/±Ñ\eë|ûk¥õ݃Y;üä}?  ªÿ‡pþàì{÷ÂÜø´¾­¥±f¥Ø â´QJeó/ƒ†d®fi†°ãáF\~ÏV Ù‰ƒ\ Ýæ -ÈÕ…~§nA‡°ÿËw¢M3úÞºÆ ðº}÷ÙzаTÞCБª<—>Þ¼ó›Í“ÖC5¥x=Mí‹CàÈWšJ¢¬çÊÛw;¾Ý÷zûvÜîÏîI€ðãjD§S\óCàš6=o@ë-™èùÈßyÝôâÑ6¾4ñe}à3sWÖ>i=Ÿÿäï|âVŽÅîáp¾_á ;]ŸX¼c¯yרy+JwÔù<-Jcó!¶fœ>GQºex6Õͼé츩0’ ÏKÌ©.›Æ2¬Ø¡§)Nâ!Ü2›ÎÞ¢=¼õí®”AüR¦sµÿ¶¹2^veõé?ÂäóPÞ‘}ó¸ }ª¢Oõ# â÷Êùæ2ó=mæ±-Ì©×Òe6×!3cÞï'ïv„™uÚØEiuÎì73ZÅfæü£ÍÚ½àz´¼»WÛì§íQ¥÷u]FCý¾CƒMñeF—ÁŠ3·ü- x­Ëæ íGÝ&€—F—mœ/§íÕîµ½ÄÆþþŒÍÃ3yµd7eÌm®8Ÿ¯E§OébÌGk¬3húêü¿š^:ªF×ËùÎ,j=uΡú™Î¡Õ¶ìŸèªî ÌÑ ƒ6õ}·¯ÑÇ4×Ç Üîº1¥í¥ÑǬzܵ½d<äGÓôÌ÷ DaŸ ph;ÝZß?tN¿ë•íÀ{îùFsÁùe+23»ûó}¢7¾OèÒ CO ÿàÚþ>YMÝïxz«Ý÷zò®öˆð§7Óß#4 u‹˜À­·õÕ›ïm{n7]¾þu°ÉêbÍê1{oë¯×ÔFÅ÷Þ"ÐÍæÙœRÖ6¢"glËuv¸›G j8þõ³š7ßêͽdlØÝ~-O=¦­½n\õŒŠY:лš8ÕèNv(ü½g½iûÌÔÉࡪªAWSª9;”ÿ—bǶmæÀÙ›Á£žó›"¡ü¬?áOar¿Ž³õìó<%¬sž?§„=^Ö1fÞ»0zAÞ×4zN«°èô;v× ­BÓoß{ô˜ØÂGÏ:pë=ÚîúÝ3¦7Ÿ'ôu~8¾ò&y¯qoMV?óÚŠÉxçªlp(œ’·?sëN9&swþ)¦*¤ùÆã…FçP¸'CÿjÆóºÎë¥Z¿cÛ©ƒ÷ÐέÝqíÁ~Çëœyv3oºëpÀU—í;âë1‡Ì¿nTÍ_ÛÌ¡èêU;­º ƒKy­KÝ8ÍBa‚‰èTÜüòßsã‹”rãõŸu;‘šÞ~òÖú,Ïô?ñ¥Ð!Ôî™È½ï²/ö{¶eÞG§÷¼®ÎüTüRZßÝ@$Ÿgç-·(]Á}Ùj8Ú>¡;È èîuû'·Ï@'N|„Kr‘Ó5CëEßøà¬±åÎ2:2úŽÐ-9æÕ¼!z\äÑ’Ò“Ûè­rWç ¾ÕÞ WÂi¹Ä[žÚIýC¯±¡_X:5¦Ïì'Å0)š–£Éiô{rÚ›MWN£)Ò“ÓÌKwN4Izs¢Rω¦IoNëå«+'š(½9Ñö¨çDS¥7'¸©žM–Þœh|ÔsrZíÍÉþ­çD¦7'šõœhÊôæ´þ®ºr¢IÓ›]ŽzN4mzs:ÕÝ9ÑÄé͉>G='š:½9ÑܨçD“§7'zõœìÙÞœÖßUWNôæDÿ¢žM¡ÞœèYÔs¢IÔ›Óú°êÊ Fè͉öD='šH½9Ñ“¨çDh¨7'õœh2õæD¢ž:IoNtê9Ñ„êÍiµê»r¢)Õ›=†zN4©zs¢³PÏ ŽëÍi}RuåäxÑ›úJ='—±ÞœÖ TWNpioN´ ê9yÖ›-‚îœF¬7'ZõœhŠõæD žM²ÞœÖ TWN4ÍzsÂ˯çD­7§¹!tçDS­7§õïÔ•M¶Þœð2ê9ÑtëÍ §½žM¸ÞœðÔë9Ñ”ëÍÉ™»žMºÞœðÊë9Ñ´ëÍ o¼žM¼ÞœðÂë9ÑÔëÍi½uåD“¯7'·çzN4ýzsÂÑ®çD°7'ìzN4{s«®çD“°7'<ézN4 {s®çäNÖ›Îr='šŠ½9­_¢®œh2öæ„G\ω¦coNxÁõœhBöæäÞXω¦doNë¨+§ÑêìÉ Ç·ž­ÏÞœðwë9Ñ íÍiy=]9ÑíÍ ·žíÔÞœ–KÚ•íÕÞœ–ËØ•mÛÞœ–;Ø•mÜÞœ–Ö•mÝÞœ–§Õ•mÞÞœ–7Õ•½àÞœð«ê9ÑîÍ wªžíâÞœNÿzwNô¯{s£ªçD?»7§õ.Ô•ÝîÞœ†!Ð ðÞœÎçÁîœxèÍé|7ìÎi´¾{r:»s¢Þ›ÓêÀ×rÂ{x¨7ÎcEWNôö{sÖ÷ 9ñ:ЛÓzéʉ'‚Þœõ«œÆCDoÎ:O:GƒžœÖ÷NWNüôæ´~…ºrâ› 7gwÓx2èÉYÇQäÄAON燪+§ñWÐSgK’ó¡]h<‡ÕsÝüžœu N·ö´óÀÖ•O=9߸®œx7è­³~_#'×½9ë÷Br¢oß›³~ge¯í«³~&ç¾:ë7mzƒ„Þœuþ9™§Þœu>½?Ù›³Î=!'þzsÖy>ôÆx^èÉi½Þvå„çÙ›Óúëíʉ„ÞœÖßpWÎ}3`}%wåÜ7ÖÓsWNü,ôæ´>ª»râ{¡7§õ²Ý•ó! î|„wÍô><`}œwÕùÐ}ÀùSïʉׄÞ: !¡;'»ÞœF™£»ŸûfÍÅvç|hÖœÿ®Þ¯=9¹ù×sⱡ7'7ÿzNãß¡''7ÿz·n>‰nþõœÝ–Œg¥zNü/ôæäÞ]ÏùÐÝËøçªçDG¥7'7åzN|7ôæä¦\ßûúÉ}¸žs_o¸ÁÖsîë ê9цéÍÉ ¶ž½9ñÈPω‰Þœøm¨çDÛ¦7'~ ê9ñ6Ñ›Ïõ™Þ7hYÔëÄEoNnÊõœÔÒ›“Ù­çÄWEoNç%£3§ñ–Ó›Óú]ìªÏ½9‡”Ý9ñvÑ›“;M='0zs:.»s2·½9{neÆSFoN<Ösâ=£7gÏÝËxÔèÍÙs÷2^6zsÂu­çÄóFOÎXÞ,ê9ñÆÑ›îG=':zsÂã¨çÄkGoNügÔsâÉ£7'^6ê9ñîÑ›³ßàñ£7'Þ;ê9ñÒ›ŽI='¦7g/&Â[HoNfªž“Zzs²¿ê9ñ*Ò›“^ω§‘Þœ`…zN<Žôæ/Õsâ…¤7'X®ž“¹íÍÙ‹£ðVÒ›“E='Lzsö`/ã·¤7§õZÓ•_&½9¹!Õs²ó{sö`¼âvÜëæ_ÏùnuW¯ç|·Çæ7iw?Ùß½9Ÿ¦Ý9á<ôæ$O='žYzsÖy>äôæ„ÏSω—žœÑ ç€[¥Ñ¤14Y>¨:æ´äLô×ê9xçsÀm©ç°œ[+zfõVçÌæ@s¯žƒw¾Vtë9xçë@s°žƒw®ã­;‡yçsÀE«ç°5›£g†Ì;ŸŽ^=‡åîÙèÙÕsðÎõÕx(«ç௭™z«AcsÀ®ç°gV[Åæ@›¥žÃj¶Øp8ë9,·Óæ@K¦žÃjÌØ¹7ÚlÝ9x§Éan3žÇÛêâÌm+#©Te=£KðmоŽqê‚vÇ8ÝžµóljW ZÆ]×1îºt|.óšQ) À*8@jfªà)O¨ÏHRÛì@)†‰‰t íÖìßjä¯MÓ[5M~ïÆb_¥;ÎþtÊÚúfsjÂÔüQ.)]ü½á²ãތdz,oÆ—ëE,aÁ=Mça¼ÓºÔ7xLû`¼íy—Qª£,Ýÿm”)œ+Jê—ºU?HÊB.‰©-ôqÊaÄXõЉfã í 1£#UW¦ƒ¥æ¯ªÞ×Ý ²YÑÝÛf…“´#±ª³óNGB\·–búsð"«÷Ùn.²*²Lï³ ¿ã2dU§“sH~œáÇ®voPÁÒ|¢K9ŠÑ<Òv™ „¦Ú'eèí)Xhâ2Չ᯲HøWó±X*·êÕb©âhN«SêÃbÍ­ú°X—hÝ Aëºrœ.¸r{{œP‘æíx14Ç«åX"uõe‰p–XKTŸæv‰fP*„Kt¯ÐÆ_RÄøðlÌ<,Ñ|«KÎs{&›FæÝ‘!{Pa’žFƒÐí!HÑ÷R„ÑdÈöøñީܣÝy‚îïºÎœ Îéúp¢<Ë«òó'ÈìÒÆ=Qˆ\õœ(®·º|¢niêî‰âjrNRm¡“¤C¨I9IœMðI6)'Q+¼T]So–Äõ/-tçi»ËU \bݰÙaÇÚ(½†_k;/di0²)Ìo)Õƒ"–Ú%gé™V)jO>j!êæÉ*Yãd!)MÇɺ]©«' ¹©«'¿#Î}ò;hÎNkº›OÖõY5Ÿ¬}¦=wŠÐ¯î §‡iêNò“ÂØ)º jœ"uSMÉ©vï9õ9÷\íjˆÀþN¥ê<Õî*§ŠUª:OÕCT¶Í]¦½«:—‰ #|½ì¦¸Îe7õã3ê„¡ìûYÛîwZGœý´/Üs—ŽuÁMñSòõ4Rdº¹-[¤Xö“rºtˆ4³§ë2¦‰;]¼Duìté«hrOw>uÙ‡Ô©½¸\šYÎ6îrñv4mËuu¹.gºŸ¯~6í x¤lØh ÆLøŠâÞ­øa?ö½’è¦ô¦Em/Ý­¶¯éöa~ +<»ƒž!Ö“öÍ£â Ïxf8Ñ-?½&$b_°íž¡{/y¹ië¡+îbg|ÌêøíþËkzû=s}œá̤·ÅŃwétnϲírÖ¨Á|Cˆ~nn>KœÍäYÚVÚNg¿'Îö{Òso¯³µË-³“mf‡mÚ±!Ïþ—¸–§LvS‚B«ÍÀFå¾ÍžË÷ñ¼Ô‹§êŠ,ôõ´ qþ§M5½øK—¢Úû¼\U²^€Ÿèã@•V}¢`£ÜÙ@6šÎøÓÖYÕ÷¸Kz>­ø®%™»?¿sìzÎ!é¶]J³œÓl¾œžÉ4CüËÞ;‹ý=]ûRÛâéÚ—ÚOŸçúü{ò'¿&zdž™~ºó^¡o¶›ºütñ¶…'žQ×ñŒ£û;e/Iú=C“£Mú U ä÷ Ý#„5Vò +u Ómg¥0Ž0ð*1_•c•¸6Ú‚«ÄŠÑœ¯j‰+]ÕÒß1¡ ³(íÌ¥·¤U´|¿•Æ*Y‡³ù_dóËN0¿sŸg?·bp¾² O«=WÝÓ\+ºœ«+¤ÐÕ¹BøÂ%çÉ€ÛyÒÓNXB¿.¥ÿ õ\j—“KG¥‘ží[  ©tWõ]tSt©®ÖŸ—êb¤^&Gãªæ²]Ó—žŸäp>:Ëõ+ÀeçÅ•=û€4+ËNû?W–op Þì^Ho$Ïf^˜ËgK£^óñlÝctå{¶ôð´'.^܇Ëç¤ç<Û:°설·ƒËuÕº\÷eÝR.¯B÷¶çˆg¡ýòœÎ¸žçt¦çÏÖÃÞª"ó|þRÔù\íqž+þŽîÜÏÕí^Hùyz¯-õ¼ˆ«{Þ?¤ùMsN~t±aÚ šö@>º°ÄmµQ6+£`œ]̶*»6íVõJÛm«c”g«”W´É¶JÅZ›lëʸW[OOO‚íuÁvNo[y•éÜnÕmZs»UBªå¨ùÝ* ªæê¬+óóåóZU>ÿYýU2¿Y•šˆ‚œ'Ø+Az7|¾˜šºè?_êaêÂóuÒö¾B×8Íáb E\¡«¥fò ñBt¿‚[3%\i|+_šÞbô“ô¯ûÑF¹™q%éàÞ]©‹¬ú³­&®w[Mº^ËûùçùÏëBËëmðõnÓÕDÈh›4eÛ¤ú¡;Õ6©‘\¥ šæã*mW¼u¹ùUb*hC^%®‡nåW}5î×U_K_Äì|¤¸é*uVwš«4ÏÂUWů.êϘ^—®^e¾•ÞØ6CçµÏõr»P6Èv9ÝP/·ëƦͿ]L$õm»v€vì5b,kƯ9>®ïšÚôF±õ±·Øò=lFû»Fz º7]#†„&èM‚¶â5b)hR®²^x4ˆTí ^Wû‚—÷w“½˜U›îÅH§Qõ½@\Õ÷]Ã5‰/4VÔ Ë­ã…º@j£¼PMô‹„'ÔŸâ{Ñ®éîÛëgzÏöFZÕ‹Œÿ"ñ´G_$ü¢îì0ŽÑŽœ4Žì­jßÞê®x‡Xïªx‡Ô4Ý;tgúØ!–“æìź1j½X,ymîë ž¿Ø˜â/>5½IÿKG I2Ý“æ³vsÂ_¬7šÓ‹c¡þ¼X{@›ôÅò{‰n ÚB/á-ýz‰îâl¼D,)Ý^"}c퉗gênñi̪/•v‡°ìKŽûøÒCÓû2ë£ù½T¸Gã¥æfì¥âÓˆãr­]ÿ¯ýðÆÌ®w×êV¢Íy­˜0šæ—‰u¯ž½Œ3õ2u_¼ì³éc+€½P½ÐÚßËÄPP'^&Ý#ÝC^.,­Yxyw\ÇË3Ì ´‡öî[›ù—‹-¤:^.4¢^¼üŽ8ÿO=õžü–ñ^ÛÑo[ç{›îÔ®¦·{ìmbãù7Ÿ´7Ìû½Ý˜÷o‘»}ãîÛµ[\î·«øíòâÞÜl·™›…*ýǺ9°ío6^ÇÍ!÷;ÄVÕ›wˆ³àß<ÍÞàÍýÞñn{ýËçq\Íw8-Nû{ç!ñ›w†zÞyœ½a§ú7¯±7Ü;ü›Ù£i·,ßÜ"ïòÜbŒ¯[¤-èß|ÚÞpËwo~F¾îõægÄð÷oN´70]ý‡ü~F·}ÿæ#ö^«óñ›ŸÕÕÆ½ùÙ2{ÃÈ¿qõül¨çg¿boÀîÍ»Kâ7ïÖ&õoÜܾ[së~?oýþyq™ý§?òóòçárÿ‚ð…Þü‚0 {s›á®Ût9ðo®±70úÝ›÷<;~ó§SæÞ8 ùi¤ø<_°7F÷Ùþ~ñöøÍ/:Ý1ûû%cü’Ó®¶¿÷[ü½Úû®ž÷«ÿ}b¢ø7;íÑൿ÷Ë÷“Þ¼?}1Sì{w¹ß_koŒw÷æMöÆhDÚߌSóÝk]î˜BŤ;äß|ÜÞ 'ê~·7ÅonuxåÿÚÕp»Ø®äÃC‡û}ÐpâG)û+_¿)ß~“±¨úêªØÌVÛÂB«ØF¨4ÜS‘½[ÕL•‹,ßç•/ÑÌYæ…2$b£ÚhzçjªÔ5­ÉîGMgõ+O¤Ø¨IèP˜¯éq¦~SíSư¿Ýét—”ˆó ºA£g=}³ÇÐŽq,ÒÑE:H]VŽAR§&t¡Õ~s],Þr ~Nüvpõ–y,åK2¹Í8øÒ™Ü¯õª8C«8¾.ûPSÊzø–¬ÏËQž%æ®Ëú,CEÏ*ro.3FÓem¹k>ë)–ÕèMÚß&S[ØtbzXÌ…‹»MWé톕ÞîcÍ¢´0cͬ.ò±æUwÚX³*>U¬ù.ŠÅÃÑ9Öý@7“XÊ B´±¦G·ªX7^Ý|cMX(±8,ºDÇš9ø‹uoÓ6Žu»Ð­,v¼}3eºWÅb°h—Ä ÒÐ¥´¤ki¬É“ÞY,¥ aØX^Ÿä‡'ëAþa°Pq¿ˆ¥|!öC,M\ù؉ucÒÕ8ÖT÷âXzºíÆò¢$vL,]Ýá}Eà¹XZ-b ÄÒÄAÕB3Á•µSQ}ôÍý^·ÒX·mÝŒcqÐtŠ…%u¯ˆ™™ŽXw&Ýkc]t#ŠußSÞØÚÓ9sG·æX×{ÝÂbf&’ªFº±î‹ºµÄÚ,b†Äºñ ËÇÚ¿â;ÄÌ 7êXfù‰™™d ÷ ãÇÌ JT13¡åëæ#±8rbŒÄÌ |tsiÃÜØ¥KÇ@Z±Eº1ź×ê®l0°nl13q+ŠuwÕ}2ßX 6£: B¬û²´VŒF£îºFÏQ÷t£‹­»‚ñâžn”±nff3Ãý‘™ÛÁÌÀ»af„[cÍŒ®V±fF 5ø±1:b±fF·X3£b¬™ïÁœ2tí@~"æ^hftŸH43ºM ŒÃyAÝ“D3#,›hf„eáÝ‚eÍŒ°l¢™–M43²‰fFX6ÑÌË»Ë&šaÙD3#,›hfP{bf„eÍŒ°l¢™–M43²‰fFX6ÑÌË&šaÙD3#,›hf„eÍŒ°l¢™–M43²hœeQúËÂË&šaÙD3#,›hf„eÍŒ°l¢™–M˜°lÂÌ€ef,›03`Ù„™Ë&Ì X6afÀ²hYƒef,›03`Ù„™Ë&â> Ë&Ì X6afÀ² 3–M˜°lÂÌ€ef,›03`Ù„™Ë&Ì X6afÀ² 3–M˜°lÂÌ€ef,›03`Ù„™Ë&Ì X6™æ®lÏgrŸbÚA´ #-ÈD 2Ñ‚Œ@´ #-ÈDûëî>ƒ×£ßmÖa–ùûŒ­QïÈ/Œû@›»Ñœj™ÙP^5‡mdØgöŽcÐ11¶ ™”Ì݇ía®Åîzæo’Ú ªNê+¶j}ýžƒö † -á }ý½#÷]®!3Uu$};Ï%9Þndt»•’ƒÛˆëL¤;59¸ëq#!µr'¡KÜõNv½1w(ƒïyÇòdçÀ·‚ŸÃ~ósÕ.Ñ«?r½R—ŒZ±/¸/W¨ìj–ò|û”åY&öø‹ng/@f\±²`6îIÙ Ð\-8¯–X»@ƒ kYAÙ]Æ/HõHÓßéí 0(ú=٠Щ¿ÚÚNÏ,¢åš–½ë2›öóô!÷î#n7ZMݲc$pƒAqAq·×¶3:v³©2öÕ_Ù–#arº)çÒΆ`Ê 3ÙM¹áòº)ÿ[W¿™OPž¹­‚Pçí !("…_S5²êŒ¦CF^HÿÁw†/c¯¢tˆë ·Ðù‘0\èнaqcõ{ÈwŽù®Ð!¸U¾Cßp½°¢ àtð=âF!\¢Èî±: /ËO.Tì—lûEžTì=aos1‹tý™jÆô6uª§¦2kt•ÙX“«ÌÆP&1øàUS™ ™I7^Û¹szÿÚuÏ̆U²³aµƒÜ<U7ð3¹Ñ€ÇüTƒGáK0KK\½\¬` ,s[¤ñàõ ,N0šaÌÍ/»œ\µ` ´8tçÒ*Š c»Ô»D*¼Sñìˆ ›(ò+®–;]-ºF°U%Û,¯_‘ŸsynuyPÜà¶>Ys™è²Î,P3—unY5û^¨æDÌ ö„öo"F1á¡DŒbÚ¹iÐSƒ×Mnf ¶ï˜5øŽs¥È/¸þˆÉ«/®k5æ w·Úà"W{a< T_pÅ«1i¸ïÕ²rù«½à&X«žkaíwÄZV.ŒµÜÁƒYõ\% 2M±ªñ¥UÍÊ%÷žÙ nœÆÿ@Z×ϯˆ»h­z.¦µžqK­MWÖZßg/¸ÌÖ²r³eçe9¸æÖ^pç­½à\«ƒÛ0ÊËY®ÆµNsO®½àÒ\ë47èÚ ®ÓµZ¹[×víZï¹u×^p÷ójëà>×#ËÁåÜ3J-wD7öä:+ìpë©€n=Pu­§ÞN¸õT@â ·ž =áÖS½'Üz*àú„»BÄŸpë©€½e…[F†¨pßH¸õT¸$Üz*\`x ®2 W•ê‚.ÿ‰n:†Í•èªãxM‰.;Ä,~S ÑMÆâL.2Ì?)¸È#?˨"§Ø‰ æ"”è~áB‰x –½C±]@l2ý3‹§T…«G,†D ‡f‡Æ¹{½9ÏÝ]S S¦h"å‰q oØ dØT Û®'ú†í€B3 ÒdšÑ¯eÎA9líÞD»A›)ÑÖ{TÕŠo‘ˆk!¼ªØ»tƒì»}È£.&ÚP†Ù˜h{eÓà˜œêµ£øG¿x|I<‡&Æ”8¦n"n£3¶ˆémÜÐ(k™y±u©»‰ø2Ve™›}ç1·>ÇŸJÄ$f.ÔgEv¸Ýõ"÷ÇþU¶Ó˜âaÆá®f/˜ÿÚM†I¯½àâ“){Áq›½`ËÔ^°ƒPgÉ^°Ÿ<Ëß¾à¢Hϳlµ q°!´ó’ëm¯¹‹e¢‹$“É@½R–‹]öÏ»/n¡ž]o¹‹š ‚ðÇÙ爺 äÏ–¢·j^ú¯ËrAþëbªl¹ºT…¾. ’gºX“{ ÷žYVµ¶|Awï¸2H×éåÉsÌ/¯.ŸS6uVùtܘš7‹gWϯxA9fM¥§Î®®,«B0à >¼`úôyåóiÅ·|ui’è zrje/¦Ù“OfžL·'¿–y2Þ˜êì“™ñ“Â?öÖâ‹.ÜÝ[NúêþÞŠÒW ½EùWÅ;õꤩӫç—Ï«(›U=½|VÙñQÎáþÙ²²ùŒŠ}UÜÏ¿Zq|%3ñ…›5·²òøêi³§ûÜ;2ÏðæL—,z{ï+ÛæË{Ÿ˜,É‘½O–W•U- s¿ɶh=6S^õ•-ïŠÞ'¶¼÷õ>ñååm<6Ê;BÑUeÅ ÿ) ¢¼ Ÿfñ“,>Ýâ'[|F—mj—_Ç&ŸZ·,ŸU€Ù'“=­uÓ¸xÌË·§ËMŸ¼1]qúäÍé¢Ó'ç¥k9a®¦[E/O×’>Y—®%}rQº–ôÉêþZÔµýµèÉúþZôdc-‚A·dj9ýØ(÷òL„³i2ás2ù®œ”™EÖÐéQþ;Ó/–Ï*;®<*xWf<] _Ã4ŸâÏ3ëRìŸ~áR|53Ä.ÅçÓ/\Цþ^¤“—ìz’>¬¼¼¿7YJ³^³e)Gö÷*Ki@Ö³,å+û{—¥±¡‡éÃâˆ^šíhqCÞH»å}KÒ.Úd~møÚd7 ôÏ&38%ožM6c s6ÙÕým³ÉNÜ8>^Çoœ<“ìåcg’½cãÌ™dì„3Éž²qÚL2¿—ÒQãUü©ž-<~VÅœéåóÀ‹ïîo\ö4¾a {yÚÅý-ÌÓ~y yڬǻÓ?ÐÑ<íþ¶fOKcz»¤¼l:€2Ã46¥}VúÑ@O]º¬×ÕtózéÒyðäûèÒ;ÐC—îwûûgŸ¥ë(íÝòÊ*n@ãQaã7©Úú»fRe:¤òøÇw̤:s _&Õ]ýÝâQÙ7 ë•…­%w$í²ïÊ¾Š¬c.¡ iÓ\B?šYß\ ´Î%œº±{.¡GZiÝ»l×¹„'ÏåV §¶-´ÏJßè Kgî>y]º¬Mµt~ûö¹t~¦Ýséþ®¿yöYâîI¡wÇVÌ?½¼ª|ZÒ Ìß&¯èbH|`+Câgô3$þ`SCâó:ûuáÛ›¿-xáÁÓËæfEÅ\ÄÖ ÀÂüqáŽè0¤6ç®CêÝ;¾šzéd ©ß¹9†Ô-2¥Ç uEó§¾’[Cæ‰=™s âÓ3)ÌMË<±)^mñ™/I?±)ÌQñ™™צŸX0iÖDzyÇé¹póf—UFù3ôì8N˧Í+/Ÿå»Rl­$Yœ0vlñŒEÕóTVÎÇ!ÀøN)_8³l§—Ž+÷/£åz¹tîÑŽ\pJÙlæÊŽ«X„Ú •O]pôÑÌS5YéÍz»pöÜùqßÊ7§ã'Ì.;šj.L?à;5Ê;6.oÁô1£§VTñÓ踹¢„w¦ RÎÀ³†ã£|7vÕw§TTÍÃèÅý£<‡éŽ;·Êµ^ÌÔ쪷¼âèø\ze|Ô=e{ã„9Q«ÛÆÏž;ïx„TÒæ<|\Ù4ú¿6ýhQÅ|èJæ~dâîjº¬l^Ù¬YÀ…òÈÌÓSÌaæ Àµ%ž0‰3g&~ú‚9š–(ïv7ÞOa‘\=mÖÜiÇ<e“¯¸T Å·î×Åã=ý˜ÌégNú‰=·E¹»e^è€fo{&|rÙ4—¡ân æÉ⪙l“¨`ÏÞ:¨FW¤_héœ ý Éq™n;j|º±;äš''WL¯p –Ø]<Í›³ØÁæM´"ýFÓmÓ îKm¶[|A_jûƆ}ê¥åÇ1k±»æš7‹f³ÝOæng¯é¼q—GM&;0Ûöź¾g§.¨r(¾/<ËÑÝPÓg>›åœT~üÔ¹,Û•´¸—ŬveßKöyñ€Þ'ÒÔ"¬”ÂÍK¨já.rf¸Ì?¦zÆÜø¤doå»ñR[8s¾°´VyâÎ+ +¸•s2øM·˜B¼~õhqÙ"üħÑc‰š¾šèB¢™è"¢Û3™–AUJ£Ë+ ÷d™5#iß*“!=¸²ÀG——]=û€9Eûº·”§õ>ë ìN|þÁbêǃ_î}p<ëï°ÞK§Wq£5gjÿDâtáÇó~åÔ²ùà÷Ó7K+fC‰Ý%G'd™m›¾±‰Ê“Ó>nVm°G¶ì’I”¨ãÍ™LEâxÕGÇ!ËÕñhÁ4#Ÿ„Dò Ö¯ÿÍéä~mÿ-ÞÂÁÝ8µ’½˜¼}u*ÙÍù4³ˆ71]o ìÎ߬àͤþ7ËyÓÜÿ橼1çŸÐ]½ÉŽ}³Œ7‡ö¿Y8#Ê©ño̓ї2t„BzÎ!dËgÑ>®#€€øG2¶ÅýZæÁòªy®mwëÉÒ ª.¾/¦¶­ƒY¹ºµ¡ÅQ oiOv¶W×§Z›jÚÑ0;·íD,½´µ£¹½¡ š T¶¨`B²¹fIc.ßOuQqCª6¦5¿ýÒ(q«Sðð.'ý7Vt¶%£üï·&Û—×4F¹Ka ÎŒr_^:f ¤™ò9#ÊÿXànìØÎ¼¾¨Z„É•K; ƒ¾zi²9Ù Ï´øJêPUo)3~âM|NCw-¯J}Zß¼tkaÅ H©~¼‹Ïvµ>å@i[(à¼Tªq[ú–ŽGá¿Ê§ù'ø‰wHH¿öþ¶¿HB•ýç¥cÆçB5EÏ`VY¹+g,GC°q±3£‚߃°“/yYT𥢖Ž{.ƒkøËEmÉvíœÝ¯%[ð_PGŸ.‹r@oŽDóneusp\%Oþ’'ⳤÓÇnab*”€€üp’(ïãqŠŽâå‘ÖôüܸéqC×µùcŽ@q¯?×ÜÛ®ÂyzºA9Õ)Kó¶R:¦„]qré˜ 0Â>Å3?á®.UøœÉ¹ ,7ñ½×$¡D\:¶Èô,JÑp±{k¹,Ê;@Óm]ìÖïf7ÙÅ1=Ê{¿[†† µùÒÆ$ï»ÊHÎÝ\Þ3Þ0†`Ý•e}”ó}Jˆrg•Ž5NŸÉ¹¨Pï’Rß¹nò»+ó_32ç¶µ%[]ŠókàM‹¤z¡£œG¹s(åÈ(÷Õ¥cYßÅ×j§nAï¾4Ã7l5OK×ý`6 ÄÌVW‹ÍõyK—Šžÿp›‹Ï!©%ç» ¿›4Ê}.9@:Á*ÅM-+3èa÷NZæF¡–&Ê«ªkmXô¿#ÕÑŽxmW†¨~n]r¹»GTHÏ’A®R8Z ö ¢¯ŽòUvxP¸=“BÏŸ^—D·aÈöFE ¾€×Dô¸ø÷¤ø3w4¨¼’Íl#ã}3Ê¿®]–j€ø_º¼½¡…ˆøÇ;Ê9V7…ÂåõôŸhåM±¤Ä%ºnN*¡€¦L̃;m^•¸rIC;Êæ•-¬žz|—ÙÂK9ΤLèCóE¨!®{ÎÇÑØN-j¦X®i…õ¸ÏrÇ-+“y"K,æ,( Eùµ"Û¯(›Z½B᩠ѤWËÔñ(_œÿ|‚$Pq)-\å¯"~-,¿ªeüXjŒòh3Ú^Õ2j¼¥Š–÷}x‹nQîK–Ô´1A_‹çFß0×Á„RÎÜx¦œ+µ‹K™­§¹=²º®5Õtÿ™.È+¡mUä3-c‡mÚôPT½S‘«0—­¹Ù è9¿ :¿oníÊF!çKèÄ’¹Ë€#Ú÷;·­…î7Wzšé§Ì]Òj«K¶£‘ „yj{kMsGdiîŠe(5DùŠ|UŽÍB¦KKÇ žÌ§î9§ð)€z*Ÿ‚Ëøœ…v¶UH\ÒdԟЃ­ê«â±$Ô=çt>… —ó)T¸‚O¡Â KÇI cŸº5­¶]j.+6{é—}oV¶ÑÉ‹éyáWàéÝÙŠM¢ŽmäSGÕñ–ÁN¬¯èÈtæê»bФêï&>…óŸÅçQÞ—,•ænK]'=›¬ò²t/‹­$VŸ7óÙ|°1Å€KäÄ—Dg‰Ú›b;É4 /-7†i¸–O‹ÿàÄäÊ%©šÖº¾yøjsõ¦wÅ¿"©:wf¡ä¯ËÏh›&<ütæYu¢ë{3Öå唪}ðS| ‚½5“&[6>Õ?ôVÑõ|'%hÖ^Á§6Ä+ùÔ ý¤Ð©l_ùþŸÛ×ÉÝï‹B HzÒÏëyiÃ÷\C~žŒ:4rPrcª½¡~eF¢¤ Hêüµìˆ©åN%p›åd€ kZÛŸ /§· ºI#ñ V)×–”4U¬îJW>o”ó¡"'¹ó€LéVW@T°4ï9Y!xSüEu5Ü´•P¦N©š_=µ|LˆÌpÌ–Ì›;Ù“•ÕQ”BóD‰VT]ž>´‹™”½ƒ¡dßE°T³w+*`×>Óû!H¯Ð=PØ¢©Ð„N=» z\ùµ›»³À¥”ÔšÈ,.H~‘$ãX}bt[¢|bù£åéáøåiËÉóvdâü=áYW+&u˜3`f.)›s´È`b}åWÀ38¶ ÒÝܾgâSŠ'˜¿á¶oî\qG"&ÚñR:¶ó˜äÊxNË_dâyUüPkÍŠê¶Úšf—®ôñ¦TµøÎ©³±é’ܺN„{׬Œ N[ÒÑÞîåßÅôƒâ´©•Џ ðª²æ•.~¦îç·#*o“BªJå—°E.j[*æôå³RKg·-µ´êUe};ˆô¼mÚYÇ\ǶŅËý¡ZçÒH}É6£ÅÅJ¸"ýÂÔ$ð|Óg^ÅÎTÇ£cqÏ?Z8¡I‡Dð EF”®EúdÙÜ…Ðþ*(-d™O­D8Otî, $á(šbúÄ‹Ɇ@55ôY¦Ïßx] ¨ ½·¿:fHŽR³}Ñ«V7ÕEùŸ›Ú9]Á…©¦&®-QÁ]µ)~…Í/ÃáCuÁÞ<ȹÐ:_Ï].Ïcø?C>ȯ¡~v$îN§ˆ|òˆŠT´‡{ψFZaò¨¦ÍŒ Ö¸ìœÑ€Lº¿-«åCОéÐ}4´e’ˆT•dQS²É]?êùÝIu }‡/<Ê_ÆyG±(ÿg¨k©SQÎ5íË’þôåeÕ7Ö,e“´Ð7Á¤_¸¿®â®$ÑÝþ ‘ºª¬ãè*JÎÚÖƒÆÁÜL.W½c*Ÿ‚£§µ@ˆ¹¸ÎIlí>o—'èr+Á3ݦ-éà5í H[G‘](v*sBÇÓù:~UQ-Ùuä5'‚õ(ºÕ'J³|Gðc‹ê¥Ò<¯¨ÞIŒEù{Õ·%“'}¦ÔÃFÑ qpúò‡Dd†àüÄQTí¬(ÿM\®]{×ß{š?’Õç¯ò)îáì¢?\+6*è‡b5 â)}£ßL«0æqüqB޲žâ¤_Öó% ª¸àJZa)¹ý]™ü}ÑæA7>Ëlz€³L“|†æ¼+™}]|/}~Oé×)N÷Ê×ml¬OôÀÒñGÀDx¹‡5Ó‚ÀœÇM¥»;‘#U3r“'#Æ;{ŠJN TÆ@€*ÿÄWš¿Ê‘“Y86WÈZ|&mš‰Î‚ã>Ø*ëší#0Yx šQÞû|¹ðÇò“y^òå\Ô¿`Uw¤‰ò98Øj¹’w'(îFkŽŒòoëkÍÉ@É4c{u½;ëç\ŽˆÐB‹0t[ü’ËñÜâJ¬‰zîÙEùÇE-lK ¥KË&ïêHÜÈm\ø®¨ð.A¨#ÆÞ›˜Õ΂o-=6Zt˜Qk:iÒ&7'W8FçPRÍÀ‚I¥«¦‰»'æòå¾áräl=¥%?poe¦Ïºu&{‚.u{?’k{ôW‡c¢v× ÓèYdš‰·¿7Ø›—ÕÔ¥Vl\Ë:Ô.—}ÖvGgª¨àÖ/ŠËkZc¥< ýOxÅŸ4q|:<üT]<Í~6„”Ö5,]æR<…¦ˆÆsâ‰¡+Å’SŠÏ0_Ϲ>N¹¹ôirÒïËt9/%§øV·ý.çæ8å³I©;Áë~_¦Ëùrjþüw9—“‘œÏ#§8doø}.çu¥G#ÿbéÑ=>½ñvçúœAa›—µŽîˆ Ž«íhu$Ý#‘æŸa pw^‰£ty7Œæœtˆ• «Ãß´ ^/=B$Ó?èíY ÁÜ¢ j¾yB‰Ò©]Ó¶û:ŽÈôaw!f–%1íŠÙJŠ·]O†e8[îIùì*59Ê݋ⅮJOOWõºŽü·Š(·¤ôˆ ,ƒ™6/]™´þ,-'{ÏPX’Yè%xΜJ:Ãf’1 ­ÖK!fÀyŠ[˜¸£(N7¬!E1sò9ž5±»Hs×8*>°E¹/*-)ÖG³ÆÍ@g—–ˆ÷sŸâCÞÔu¹‹ >©cWÀâ*’i¶ñ9¾ÿ›4=Yv^ pLõ\Ò^¨¿J¾™™é´ųKK æß§È6ŸÓ)s-¯/¦åkWT×´¶Öpá¼½´dì¸(ïYilûÀEòC¤ïä¾~”Û  ÛõLWØõÕ Jo‘ÞžÌtÿˆK;o~‰hõÿTZÇ5ZZ”|iGM£pn=­æ´r—;ÙjËÀŠ!Ͳ’#Òë`:¢´äæ`$ŸÂ;³Y̱¦@-õŒG/‡Û… PÌí4O§qE-3Äìî©ÅŽrqoÒÌ’Ǿ4Ë6ðÌãw¹z-Yr~i ë¸p³]¡k=8¶tB1Ü­U¥Dõ>—OMÌy|êÑj>µ~Öð©XSÄ–Ëbµ€rSQMX:TkEñí¥´9ÞȧŽÄ?ͧJ{ Ÿ*í—K'°$ƒ0[×Á;ùT¡Ÿ+0nT”7ªºz^UUEÿɉ©ž=Žz>ϧêÙ”ÎR-úx-([ö¯óaL‰Y·ç’<=è¤aÃ¥ ¼Ömÿwá‚4Pmüi£Ç >Ëñ?«Á(÷2—Ñ\mÌi®_]3úš)PxŸ:úOw¼åÙÁ(ª¼ CbZwßl¾6“Áòôë3þ´øöb©µ{tbʇ{ZÕeKQÃéJPzñƒ¼«øð?°À §=À>3;ù r^|ù#À;¦þÑ“ÜcñÃþç¹ü¥ÿË®\ú8ñ»´ÓÿO¿!þäÿÒ‰ÿA·$ùç'…Q’åH®*§âµ?¤¿ûaEšÒ›TÂ)4> ¶séïÔ~ -÷‹ …ó¿£[TêzT)Ù·—Üô¨T|qoÿN&7Oˆ7¾þ;™¨Äí¶G{SúŃÂWÅ¿ÿ½ŠVÙí§'ÚÊï}L .û„æ\iÙ£¢wñЇu$YHÒ&7~"uÍÉ”¿žeç^«l=°"z‡§wOõÁŒ~®jJ!Äy¢ª2‚Ýå.8/âV=k‹\rÔ=W•‡êj–âüËÃâv…Òþ[ËÃÙJß{vy(§½ÀÄ—Üsy(©9Æ”~¸õŒ²¯ÞÝw™òì‡ï2Ôs¢I°G“h)A:‰½×š‡.¹áÞÃ;b…ß×wÃy¤À7œsÿ7^vY.oê?ò<œ->¾ïÞóp®hRïéçáTÅ#¯@L«‘¸-sz¤m·m¸ =<›îLTìg¢‡zíÐIé‹Ñ£cÕ”º6öeÍ4lþéÞ;Ҿܔâ5÷ž”† ½×¥$ÿ¾ëÒ>!¯„݇¦‡Aǃšaßtsz¸–úù©¸bóùé‘u^úÎæKÔ#›&ÊûÁÀQê‘:Ë;pŸz´À›áõHyEw‡øa÷¢–ÌëÑTå³Ò·¬G;|ÖÀYë±Ê’Ì…ëáeSùÌà±ë³vÓÝëá"K37^ªÉ×oËÉl_Z­»±[®g—[n¸‘=\¦úóÉsÙ#}‰â«Ów–“æñ®Á#Ú#0îs÷´ïà²xãií ,gNµ+Ûw²FáÚ÷ýæΤ|"]içg¸‡ç¥\1p‘{¼ÆÚq®0wÓqnßBæNW8¦ÿN÷ð(¼ªÿd÷È¥à¼{®wûúáy¥Ÿ´ÏuAGÃÄ^il9é*è¸ÈÿVwñ¯ù‡ÝýJZÁâÉÑ)– ðÍgù+÷(I?²we@@ý‰ÕvÆ <úwÒ&§lEbóÎÙ¤jýHKïêÓ¶~4}‡ƒ JþFÅêÇ`–ÕúÏx.îÓ“ùQ‹Ê/½GûáJ¥ño`8½IûṬ jØÀG[Ü/•¶Œ|õ£×Ù‘êÇN8¿ß/>ýh>IÂÿä$SyÍFaéÇ"OÙ(.ýèÉeòéÇZÿâ-"Ó^ËZïšþ·c]üÃMBÃÿý~X³Yõá%$™¦¾N¨ÅܧŒú?®»åÏÜ£ŽúÝ#s±##®øä-û¯zEŸ€x§õË(>y¯ì¤!@¼w“°àwÈñ×ú$®1ù—t®ïð Š_-ú#Å¢˽ÿ˜ÁQ ç‡$ûlÐ#|¤´æûd]ï¿´U,ð‘jïè |”­SyÇ#"ÿ4Tþà6À¦5%ûêö=Æ©*ÇGÿ™ÀU6xÛK£ûª¥K—Î{X7Aïª#XÏ/.º÷òµ‡6˜||ëm¥«°Òn>1 Ø©å}­tT1BG¥Ÿó-aÌB¬9÷}ÎkéÊ*AÇ7lÀÝü Nª¢ÿAi¥Ý}Ü“WLa¥µËã/˜ÿ¤Ú£¼»ô=;Ê{&ßHß\XÄmΠwl˜ ³D/èÊæöŽ%š!Mä-ì1uWØÄ’¤—ÁÈÇÕ^Æ ]S5U$•RÚi÷`›®´¥Ý•M—Wõ›îT£”JÒè}ßÒ|@l"ù„6å£ •ç=¦Ú‘<#ÎôÏš ξɓz0÷x]àMœÒ†@J,…gÜWRM²¨xE¿ºa‡fÑomt,ò¯¤èöA`ñˆâHåÓˆ„Yß•‹{ßEcävÆXóZ©¥È<Á•fé8š/©­âq¾ðë¿öb²x°YíñÚê=iÿ ¥ôëô‰|ÑL´¬k”^¨^KDé=÷×#Çîùèqᔪ¹¸)ú©GPÁŠ{d4KozPå«ðšMâ`ÉçeÏâ«þ cV|æÒhÑ7¶ª°UÆÿVí­0ïûy@a®\ñ%슿|@*/>üZ•ç>®Iž”<¢VXøÒï”+'?.Æ(³Ë?Р,Üô;ÙËxÞ=ãÿA04^øAÒèeOèÆ£ÿ §}ó µÖ¸àb°Ñ—ŸP³-}èQaàÂk'ɹ…ó°¸oôêÿª^Ÿõ*ÉWl“].½õQíæâë/&]üéïUªK?¨„]tz«n'<ß+Ý]™ý¸ê}¥j‹…#ÔʾãÓ请zOúÐû.ûï˜:sŸýß±û‹²d°ýÏÜ‹‚s°[},íÆg»üï¶§ ‰òñ|^þ¹eê8zJÃúGwPý°Mñ¦.9†¯îêêßw•¥Ç¯¤®‰©¥‚×ÿ ®¾©¥z=U-ßQM±µ`¦ÛÔrÿ­óùÁ÷\YeÀýGŠ-¶0¼PSXÓóø±sé?p’Õ8ýèV몓i[Œ¦÷“cU÷ÀM6ŠòXëÊ“}jS^ ®ÞíïÊ뎷ò}üè)×Õ!ã঎AøVD-Ljõ‚ªI}ü¢êjÁž>µ ¦9ƒå¬ZjчUyâ~RâÍÖ#óÞ¶aÀÁò­/'ÌáôEŽn¾ïë*‘5kSI+ÁÖ/¸J† ^fÝ$~ÿ^ëj“…k[Û?aÿo’«mÀ†;˜,/ý@úÚA]—meÚÙG®Êœ±;´9¢hÊÿåvõêÂiê=r5\(ísêíÖ‰¢Ò!tÄ]Å⋘ŠÛ™ÑÙ`W6p‡\GúKœÛº¦X]³%Ëô7ñé‰ë?®ªîªÐ4Ũ5qT ÝÓ"#º?<¡àn ц4……¥cÖÄ÷‡ >"ÜþOW¶ 5Ãt Wþ…[xæ•I´êö)Ô» 1M‹VDÑÌócH³[±DPùGÂø®0µØ¶Lz"Ìýš2’&Z©Hñ»*dÄTq"Á¥au°ÃüN}‚3æ z3…-ÅUØÒ³\aý‚‰ÎqÚpuÞÙ:D/9ùqƒºUJÔ *p…Éò§)ìdo§²‘a™h:dìÀU×nÕʆ\vs<™Ü‰N‰™IpuȤ–©cÙ¢èØ¿su´ýV%ŠŽbÀP•íÄëÄiWãkßÂÜá[0çÛvpõεzW+Έo‰-ú*Úçß7ኚgEÁQíŒk]QýûdT4^[pµeµœ Â>SdFm¸àI%Ús;ÓÕ ôkkÐ@Tà™'xêú]®§+åCÕg±ÒÏŠ9Z”»­W N}ÇU޶Ïb£ŸýÞx… û?ÈSuMT7Uœ}qÏÀè'ßfÀ Œ|-—ï±ô]Qr%nŠ:ÀyWföƒ÷dí÷[“3®5Å¢[ðVíîôxBlÀU%·©jÍ PfþÍÍUú¤Ü-Kç~SÖZx ÄwôÿÞ,§Í`«7ÀTuÁ24‘ïùÿšU-KäSÖºŸaRäãÿÙ,§Oa«Ò ÙTõLVÁ…¡ÿ¿fUËÒ±Ù”óý¢˜œþßËrÊ®,ͨ)ë¢S¢¨9&‘ünUËj1em„.ò,Ž49Âu¿¿/›ý Ëþ,.Ž—Æ¸ÝBŒÛ~ÙÌ4&ó¥zU×Ϊ9¡èÀß)ž¸‚β‚.ƒAòlXæN²Û™—_OXþ²eme=âÔ嬷|>ö»ß.K¯«ŸI9Ëæ9+ÀŒÜæCÈ¥Ö¾7©Ÿó2U, Ë&Ä9öаÄô}¡[”H¦¨çɶÂáâEÍÜ“7®šs¬š­¯Œ¢“¡¶zè”c˜d.úh-‚s¦–çÆ¸2æê ´ðäþ¸œ+ëVÖ•ÌÜ6Gªž¹É‚Sº:ŸÐr¥ /šÒ¶¯úzŒþáw¶l¿ NÚZ$g`j¹ ìxuL†ñŽÑh!¹üE&ÿÕ\ê¯þÍà‘ÃP6þ—$“«Sdë¼?ŠNwç;¹h7]zXÊeW&û5õQôòW„m¸ßýjS.¹ª5É_¡á…1-¹ËX ¢?¦gåjÐJ25¼Ç‹bÔÑŽ.#¶ù³ùÕ7“ÿE€Œ1"äý  —­Aw1SÃÈ /ŽÙø¡·‡žs k›‚^Ì>)¬Fýš´‡|Eƒms¹ÔjŠIýR´ ®ýˆK]Ô-FI»ÅÉ\RaZ“ôÚEÑ_}.ÞUFàL«µ.tæÒŠë`Ò¾ìª(zmÌ`( ›¦ê#êi.½à´Iÿrx ? žØÍc¨”5A6—ò¢ ž Žó{5×é_‡Ö[€äô&·=;–WˆžÍ›8¦ ÿ¯ßb{1¾?ÍÔL%ÄæÒºnhþZ7 %h3í@mfknô*$ÂæŸÚs[Éyöö­¼y™·jÄçÜ[poNéVl‰6ÎÈæ·(z~ÓÖâ}×ËThO.n§8'!äúFz 'ƒò›º†e_¸6+vÖþ¿Y¯Ú¶æçtŽÌÍŽJWSÿ¶ì¨äôžž¬íçF%ôdf ÙÛ?eœ—õWÁHš<,:¸ôÔh÷®üDTÚ ï}ßþý(K9žt”í¬ º{\í«£’®ÜQ ¦Xª-Û²²g–ìŸ]Ú5,çÂÐÛÝqooˆžUT—êàØ¶ZÑjÇ¿2b1˜õS•QwyóÎê/k ÙòšŸbô;*‡eäú•7çi%I=«§§çnÆm”.ÎG9ª8ÑÕ•°ØQñ.M– ¤äjØSôKã˜R«m´¸y¸rHQ$Ê!Ç·”ã Ö˜{'IóNr-zwyÔl5I×#šÀ»Ô»§¤:Z±§è¶·–XQÓ–€àÖVÓœIDæ¶%ÉöÉdsâà^­ásÊN;EÍWWÙl#ê¡vÇ,ü†=5Ûº¹çúx¾ÿií$.æséÉ\ Á\ˆQs?ÏI?mg;l‡éÞ¾7Ž„ãÜÉ¢çLÞ/Ú‰™má»…ïÍìŠ(ÿ(Å4³#„šÙaíë¢ønGå ö?7š\Ò• £ãßL`i_4—,îéáÍ.åàívLž#Ö.¹¦e;ôîrõÃäõ{“Ú©ï͹.?y'“w+¬—Ñ~w þÐ/vÓ6zº5º®”eÒÜÝTÊnk+‘ÒÚkøÿþ.SûI==“×"†@ÝÊ{yÉþ¹-ÚIïgŽª{I:A¦ÄNÁûR'Œª¤+‘þt,Þp»—Ÿ`1 šD#-Æî9Çbì–U¶Ë ;¯³¤³Ë-Æ)åZ‹±;n¶ÌÒ[ËÛ´bÌþùŒÅøøœå@%âË™šâ‘¶+9‰uìʸ[”·+ v»J¢fW‰Ú¯úßvÕšxW­Ñ®ŠžúÛUˆˆZ–°ZúUkW}8«ç&ÛU»&1s©x.'ó¹ì¹“¶£a¶ý;Ìæ(·§ÚÝ K«"ß7ín߈oÛ³ov*oçÆ«¶o´<ܾYçjaǼ9×å{t¿´wEWmØ/w ;µ•€®Ø…ì¾öoöí—¥k‘qûeûe•öËè}u¿¦x˜Žýâ׋´J–5ØÎ`LJ½2!ìŒyag, ;cCØ[Âθ>ì‰C÷Øž€Û¹'& xº=¡YN÷Tœ™ì áê;mÜkêÜž‰iõ2öÂs©úŽ}]’Íwò˜‰£˜Içý;LDYöNŒóN·é;Ü&,eÞ¡´”ðî«z§Eãñ.8^­+ð~ÀN½¹çkÍaÌß1ÆÃ\á\º—§g-Š5gEÃ'®Z˜]XÂ\lCÓéÇûæ³ìÕæöÍ­“èÐ\–‹bS»V\WÔ‹£´w¨©åLØç.ß¶IçPÓó¢Ü®½/¦¾{ ¢0Z¦à³V¿{|þPÛdvöSK ø-í£b[ß|]Q:_Gm!×I=wßÕ‡‹4KÕ½%e2¥:¼ÎÞ¤º]\:8#ƒçö;¢ww- »ëì°»¶„ݵÕbPSo ¹¿b; †€wší¢­áÝh{§Ý ïÚmïqtÝtý÷{ÏH¯¹ý#¶ƒüÞß%sÐ!+!æ»wp¶ÙW"“ :¤5·'aFŒå؃©äp³9™g±-ÙÀ>¼$A m©V–å”"™à5 /!ê :Äa¦q=·Ä»ìþµ“@ss!¶Íåæ¶ý]™=6®íD4bêÜaªZôƒÚ>Ónx?éF¹{Ÿ‰GàñÓöÌVüMOf‡šüúÖ»f0ÓÑ]ûF`pŸ£]¥¼“‰m$6‚÷mº=Ð+WG›¾wÂuP¬µää>5³;+bEn}€9¨î!.BšõhW·‡ž#ã¿ s!s¿ƒ˜¿Ñq#J„}4Þö3Ýn1æx~Ø5Kž:'ì)×ÙSÛB¾¯ÛNAº£s§ÈmfºS4ãéŽÁ;z&;BTÂÖìàkºmÿ#©Žv°Ý ðµu7([³µ®»¹ç®3?Ýsç™çöÜ~æêžÛ ïÜ:é3ìɂͽ€ù}kéà=ç·Ò8@\­×sí2xâÆ{pÏ6vLÏžXšÞª·cOŒÖW둪=0ïÞÞ­bÙÆ¹‹ÀË4ãÛéévzºžn§§Õy·w÷¯D…nÞó ¨eܺÙfžf†›K{¸¹„Ù>;ì‹aÎ=~f6w„9ßîþ.Cì›yÆ»sæ[Õ<7óšßtæÅjO–3ób¥ýésø5M•,OÛ´^>ùœÄ욆æÄlWÓŽìMUËÚ tüÝ]J[…§¦ON¬’¬M¬Lu$0•Þ†¡ÕÕ­ K,ë’;¡(¿ÕŠÛî2<»¦¹=ÑžJñ|mQª[Ç‘è\gåî9ðE±Œ½¶.£¹­f§>N|›X6m#@Cë¥ìñjÞϲͩ]R[ÔÞÙ~˜»)õ›5‰†öDC=_ªâÒFÒ¬¥¨K›ë¨û¬e èɹto3Åm®o á³XöêÊžœXšÚ©fí1ŵ#“%cÐë„¥“†™QKÔb“Ãô%+ê°—&b&36´è•Ðhx3L+JÌÃìÅ´DÃ¥ïç0Pv¯WûÑ4Z‰Ô [ÍæD=2PSŠŠvS”ÀÀÿ®ilQb>F»Ó<[RÊ2«(1UyûšÆ%ŽEËM¨òÙ;íd S—Ùoƒ£1'ñƒë^”ˆÎzØ•½œo]à†roÑŽº òÙQé¾B‹à:ö•.É#¾µuGj­éÙKMÅjõ–ŽV73’¨¸¬ŸòfbyŠ7;aNâà6Mq«Cf^hŒIvDU²<š ò¤ÃÞÙÐȨ+ŒGçs‘ÜÖ/o¨ƒ5”fÑÀœœlÒˆúa;²(³ÓGít@ê$i|6)ý¢²ðM¯ýµ!Ñ’bYøÓhùr­©¶©5Ò£h5>óXM?¥|tqqq¢™3êÅ­'²s.Io‚¦Q Á©îLà_ì™æ© 3wfXü}?Ë#²LgYó›Î2² Ó˜e)Eº~ë,Û®¹‰þÏÃÜÙô97;"5£}rÅôŠ„dç$FLh´Í ¡]é¸á>œé<¼ ÖÔbMùYÚ}.%cmâÕ„ä[ÓÖ¢i^>•1cOIÄ9‰Ñèô‘M·yɨñ2þbÆúä²D•œÌIŒgUñÞIûÒ.e³†p“›µQ° ÒY3*nÖ$ÐÝάIÆnôKy'7´Õ&kš“š¥‡/Ë«Q;ÉT¼ü2Z”D¼W=ŸU¬Q;Ω@ su ‰y<‹¯H D‰‚%¬´9Õ”¬ÓC ïHÍÇhÒLf+Mç ü5c4.–O_Áóµ#ÆŽ-®ïlëhѪ›,Ç S·Ž‹›ÎÈnVF;A7+̇ŸT->ϬèJ»ÿÓ1l¯¢™&ÃõI¡¶b+£iYLkkOL›>oîl*¦3+Ùí› Xö@;f&@0{ ý2A'ïõM-I– Ä˜ÕfÙN„ž'@ˆ3.K,pÒ–H-AU¯qâdV…ÅBà…tlÒæõãN*uù ÌÀŸ×ÑÞhݼŒÙ]ÝÑ'VÃOhæžr©S÷5%ÏI¶¶Ó(BW„- ͽÀ¹‰úôl{á¨q‚+~/›Ù û0ìíÅ.ÎÓ[1š¢ì‰L¶Å '~n§èRjø\bû¢Pç[ÿÐ(ÍùB°¡‘º¢ŽûbC33¢á~¸KÊÞÃ8mà½$MÆ}1)=wo¥´ ç­®hã¾xpÛH†á¹É#iÁå€jS"‡$æÇ}±YlÉ›Óý‘PF”ÏÛÏë­5ÒŸ¾E7£ÂÛ?Ô[¹!×ܧo%]a8mÂêëA‘u«ØRspÝanŠW—KꦃêŸÓ¶po1 @ïÅ^÷EТSÙÍQ7è'­Ò‡õž›ãÏíùh|güÖð Üýf£èµóÜÜá§2=žc¶©Þέq;·Æp£žCo¬Ð9e9çLÜ?笉Y9gwslÿßœ³v5÷æ«ÎˆÄM²|ÁsݛѼánìypÄFs{\ÓUûÖÂÞ[¢¾oîfFºsö#góÄOº an…\}ZtP7¤ËÎ|íô¾¸~ìH¿£ß_ŒêNþ1uëÆ/©ý£ü—_Ú3Õµ­6:Èñ=ʼnTÝ6WÎ)™s-\¸ÍQ÷ÈÝ¢l¸Ñ¶ÇœÅYó°Ž¹ØÆ|l"×ÝêÁ·äOa6Ö”|:Zlý¸¦—3¢ÛnÛ¦:>IïœlPŸzçd6<æd6÷}æiÛw™“8Z wõ~Ç-°\¿†’KÝØÖ'ž9¶æ?½¥ësYgùšfÿ8îõ7åO°Q¤ß“ÝÌoËú¥õs‚ÏuuuÚ·Óí-Òæm½¿ôâjö ½àÛåžÿÛܳA.×´ßæjÏÊ÷¢}-<ÄWþæhú²¢™%Èòm[;¼ääøHTWrstË„¬¬º ûgÝ2¡,».Ãy-ÜY²Îmºm¿ÝY½gsyŽrfF-éhhDëØÛTv§ÀM1)Ìð`í½šÝï9 `ÏiKx¾ ˜ÃóÁ(ž–™j1p¿“ƒ“Ú-†Ö…ç–¡ñìoãÄ<'‡»÷ áÝ­!vOˆ}Ób(®ŒÎäŽý^9bc'vSÈwGx÷ÙÌ»ddæ]â¹CÄKsž‡8øíTëÞ¶öa†mŽ+rÓiWPƒ¸Ý{7åwt¾WÔßµŸ¿\u§}On£‹—§± uôöI¼ 6°†8#Ñcœ‘x&¡5)OUst9ÿÃïPvßø°¿<_ŒX¾kRž±°o ±Oű”$Ž®©Ï샯nŠßÆÁ@¾ïFÛ®bÝÍ)Ùá”°;<2–f­RU`þz•ß#nwÜñÛÝafíÑÇÛé¬iÎÄÙgŸ9«Î´` Õ铺áÊg«5ÌÖˆ0žHl¾õ'¯ßÐd]¿é±ß­!t»U32ql¢’1÷5PC,–ã´Nèë[Xp4²Zt¡ˆö§m›‰cËçÍ›;S¨–¼f-SžàªSZ4q<œx1×ðQÅ0Ÿ8¶8j´›Q,5±fÞ½_ï¤Å©ƒ]Û”#žÞ_áý¼’NëM 4ÜÙüØuœoyÝN^픉cí§K]¸ÁÁA3¹ÄüŠÉ¥1q¬#´€?Ú$óϹh73Æpº­Dø¹¦)v˜¹ÐÞš8V´Ž»¤¤Õ2&/V8È+¬4q¬¤£,NrHw•ÕõIê:’º¤t2q¬gD Yˆþ™¦ˆGdïÉ´V»º;Õö¬ä?PX¨ð=q¬»‰}±çòxÏþm±ø™Wsóºtuöð1ðÒxbëfFŠ7–šÛUÚ]0ŒXï„·Êw^ðVe X0êæ¾¶-àvþgÓ»,(@áÞð•É«ûÈ?ÙÛ©Ûï0Ÿ /£©¿Ø¯~l-YeóÝ·ºÝå©·Ô+lZ.¹yçNFMªÃáNÇ+,­;kçNø¢Å²S³šŠi"z}øSõÇ¥ÄÊäQÚ5–x±iûÚp‹S]ÿFoèyW_Õ“OЛÝxY\è­›êpÜÕìµíîªíµ}rsmp_™“øßsû–Þ(þâÌ^Lì®-³mg¬ÔâfÅilûôνB}_ÌÏÌ‚Þ2{šÁæ݃;«È=¢¹“ûfsÙêèRí¹è l­Šº¤uStç%·ÀUYÏè·"öI‹ ö)‹©¦0×ÿtq0ÒøWÈev¸b÷û=‹iþãoZì.b`±Û‰}Õb·û²Ån"ö‡»á‘}ð§¡ëÜ.¿ nö®\›#ÅìngçÜ6+ÉíÝç2+%4g®Êëfe׆Yq» =¢u÷p̛ݜ€§þJý?>îç?¦÷߿ְ“–Z ×8ìtÕÎè#}›:æqçm¿ïÿ‹ºÑ)yàFý“ã:ħ¾&«cãÝ%Ûífw{Œâò½õÏù~æ÷ùàv¯ÎJÆ}þ‡s6ì›8cþù‡.fbšåÚDlºÅÖ›o±³‰ýƒÅ–º]òоšÚá@ì4=¬€Ÿ¾<ðîÜ]êj{%y´C²ú¾yÈ×#K£@ßM¡zcô[ü±½8»Ë’=ÓuQÔÙÓúÑ7²;õƒ;?i{Ìqâ¿zäù(ïÍ<°ÁgKößùÇЭ zCC9ˆV(ânfï1A-M3w;ä†ániæN2ÂbÜZÀÜkÜ-ÓܘÀÜ£ÀܺÀÜÐ –ÏÏàVçùÜðæ…›å|‹ÁËrº3± Èx~|ÏÔļ>‘åXÍtÕýMm+Ç ˆ±{Íå‹=çžX@ì^Ë-3ñ]™w‰çs7]î8‰×!éäl²ò“˜¾ƒÉ—÷8±~Ч䪸—Ü“k27Ý*—À÷Cï ¾R£¯ ÍQðý Çš#¿7¼>9¼. 9n·y¸pe†/QøZf¶ v{Ž‘.šF 7Õ¢Ÿ b~þˆ-µØosóabŽÂý¹hZ&vMˆ¹Y11Ç»01?7ÄÜž017ÓÌSñºÌ<=ŸDý.zí]ÕŠþv.¾E)7Óã’ßRN-žI)ðXJÆc¡îR˜é’Ÿ'b¾äð3Ä;_·be¯3CÌëLsscbyÝe«ÛÄrÞ@Ùê¦Öòå™9+_bnÏ1—eÛ£&öõL¬bkÎÌSÅãÝ+¶oÌ;¿ûu+®Øî1ï¼î‰zS1Í2óÎ÷O³X¹4¼s}bþ*¾7z×°;÷Wn¦šÅhzæ®_±VB€¸m¦‡1üG[¶ ^)“³ 糌^c­½ 4€ŠêÖ™¥RZîÔ%ÙÉpFÓX1ÄB¬9ÄZB¬5ÄF„Øèk ±ñ!6!Ä&‡ØÔ›bí!6/ÄÄ}03‚Ä÷ÌÌŒE—“6M‘}^N™—"wç"Ê—EÒÏà¿æ§³x ÿoâb&,¿C<ÓN~GC|j8~‡í½Ù£_×ág Úÿã´ŽÖVñ†¿/ž‡xHFÌó-ØsÈ%—Gÿ*1ð³ºæwBs}Ê^-nm…qmËjšjwŠÞfõˆsM¢žw©ž¦ÇEÀÇ6ÙÄ4éC.Ö„–Ÿ­GüÞè(ê‘„£%zz["ÍT1<1éæÝ8aµcw…,çëÁ•;ZÛèØ]ëaðãÀ½•á³ßµ‰ÝÕÐŒ £K@¿pÜÑÊ{É"뮈?×?ê¾31êî31z"a„”Ûk~ÏŽ}ÝÄü͘ÛC~ý”šn 5¹û¢©)çÄvï$–„û«t,†ÄS†L:†ÔîO1)P~×N %nç¤òºµê°„pŒd“¤ '™¦É±’ç!’t9¤ÈàŠ« ï[Rª甆SÀ!·JaÈ×A/M%ìRíOÃ[Ã4 —¼Ïá’s{~èu ‡»CSe‚pÄÕш W²ªŸç¹)w(Gûêì’À™;§ŸûßZRÃû\+ÄàÕÜàã“ÛjÄwraÖ8½È<¯Óñïŵ§ü©Þvüpˆ«ÓñQ¯éÕˆü3QݳF2(NDõgS×pÆA‚̣̼۟߫¿£¨Ä޽šíºüžŸîLt/¶†ÝëøFÛÑï1ôjÿÅíOw ±;Jñ»ï‹$†ìv”ö@º£tûŽJÙ%RX9ñCN°¶›tÐx¶+æ˜Dbó~jêÛO…CMbŸø¡…­)¤¢vŶÒjг-§ôó£#É)vÓ‰Ú !™m7¯ühÄ¢6‹T}Y²ÕÙ°“tã1ãj‚ô©\M2NMb`ø!ŸŠ[‚ÉO Öד•KãüÆò7âëâ>Ræù54cMh ×G—'ÆÙx'~ÈíÖ=·Æ»õ×¹ÝÚ­[Ä~Õ›×íö_aòöÝ9¡¤†÷ù=Ñð y£œU¾u¼9+U³=ï\R“ÕWC¶GÍ›¯Ä}P]^\R­·KÑ%7œ:_cη»edNÏÝxLØ*Ý×ënF“–½-”RÍÅxroÎÚ´ë×uge•hW-8}Þ¬ž³÷½~X=ØÑ›Þê.ð¹î¬<î©¥øžª9­î{ãî þ(šÚ÷™Ç?¾Ûñì*¿ïÙŸîû °s¶ïÝ4‘Ú…¿ƒ²ïýîgßïêã»ÙºÙ±Ž»dðµç¾s=nEë9×ÁˆÍ+{1¶Z n¸<~Ǿ‹ÿåøqO$z܉'>+ac‡'´û<žHÈgôÈäííÔ¯ÈÄkTÙhû8’êÇ[Y„;õ+5+jV¶¹ Ÿ‰ï˜‰&;¦L„žú•º†¤¯‰9áŽ)NŠòž§ÓgZ/WÞ¾Ô儊Á[£í–Èa7L¹ ;Õõ覩ÁÝ0M­î†iúán˜¦wî†izìkDæÃÝ0—éþQ²¾ b.hyÿ«xwvÁ‘Cü𢻭>§¯òG=ÚT¾šÃó•Qî´7FªPøÞæE#zòj•š¾²É|Þ5M-4W‚¾TzãõÌÙ‰hIÇä¢Y†lüøWX-hI£O£ë¡éAFBÊg„Á°t«Õöf›¢W­±ZПæÞ.´µlÑ´´ ¢g:Ø;¸¦ä¼Ôr'ð Ô÷³…߃yä–‚r«ðKR¨ÔJcT’ÖZ‘^6j9NƒÙ¨Ûsº¹!T<¶“dpt['£7ïËmÀÑ÷¯“6½ÇÎso˜ÿc”»Žûp{ÞE±>B¼þ^}5içžQ®üeß »A÷¤ö+îÑ$r9®}Í[£a“À`ê*×Èiï¹#wäòñm—E;¾iùÿjê?Y˶oÞÓÎx{Ðfß]£ÓÔÚÆfGÃ=ÝÇžoÐl §·p°x®ûÔž™Gaxû=Âãõ0‹UîÓ¬®txÑFrûn_ÁÅ_z78Ýs ØëË'òÑîÝì¸.ܵ=_š7Y°™ç“ã½ö<æ¸ÓæÃò‡yþ-ïjw6NsƒÍ›íVqî•yçî`(ýÍ»p7_d9àï9Ü}|“ÞÓyç{ŽØåñ \âïì&Ç6ËÙpCØiïp{ƒÅð5|£ÅpKìuù¸Å;ÎW"#­nVLìnˇ‹XÏI¦¾oÆ|%;¯ù‹ Üc„Kb8¾{þ‹£”Å,Ÿüáù­&æø­&æø­&æø­&æø­&æø­&æø­&æø­&æø­&æø­&æø­&æø­&æøk ¶¨vsÎÉÜa\ïì=ÍѽZàg}zÆ£Íý¡Ñæ¼xœpí&M¶n5ó¢}îÕ’°¾~dË'ß«~GÉ”•æ"Ûiã­ŸòVÕÙOz–Þ•è¡Ç™Ì3ü7©>eÝÁ0¯äÆqãÜPYÖ³o§vâ¦{¸Å”XžÒ˜ bÏ>eÝ€¢›‹[¥8>Õ¶}¢ãûã…GÁMzCCé{[ì÷C‹ðùÑÌXïEZ!…ßzŸI®OÏÝþäÕÀêÛàj©×WÕi,nû¤#nû™Ý£WX_3–ÑmÑsŠœ3=Ëí¶ wÚè1míuãªgTÌ’ˆgg!ð:Í\z¯ ௠¦ñÚ›Ü=<`Vý¾Ïµ<²{Ahs÷½qª nÏižÓ½ ýnö‚ì´<­Èí…ÍðFíÜk‚b¾qÿZÑ“s?³6¥õ¾aqqƒ¾»÷À¢-³›æ×íÂä×÷ÿå;£‘fy·¡±Ža®ÎræOcIð§á5W,G×Î,3tZ4¹w„Ü^“ƒÜ»l–Õáݳ\ ³¬IIgo èNë„{ÎÍ’4”[htý6&&;·3Z´K‹Í¶J“Ë`ŽÖçìq¿®©ŸïÎyĈîѪwÞÝ O`þǧ¾×5"I½5÷¦á]µ‡ ïJòuôvòrL%Çd÷~tbxWÞûrø¹÷hÐÅUëïÝñFËÌö¢YªSaBW-5F¿^µ˜[ÕMQ‘öˆã[ÿ-ÕB?Ù)ºÿ<¹SzôLçoÛ+Þ`ÙÞ½âøáf–½6.XÀó—ÀŽÏ`öÄgÂŽ w{3;F8.Ý1Õˆô?̎ѶËcK¦cÊ®HwŒ&Éàñ°Ÿ~ÌÁm† ëvŠ6ö|3=O?f»’]Úsa[.ïç˜ç­QñÀl®Xìô¬w‰sCMô|ü¬Ì<l­Ø æidéH|"ÉKM3|4îdS8~Ì6êÚšÛªòó§î̉â¹y]4³Ç>O³GG <±À½U92¿$…»¨o„tÖì.*¤±ÊÜOGÏï>'½s¬w)»ä{Çèð’wÛåÜêÄàÏöIæ;è‰}2/*Ú°OênÊÂFq;Y ¼‡YÌMÜkáØÖÝ›®‘)W†›¶Ó,2:ªîÖfvQ®¡T½»ù[7£°gZmψ˱{Ïl {Ƹ.s{Ƙ©×žÑ¥eÕ áR·þÚÞŠ«b¸šÊU3ä.ìi /J 7»]$®KŒBú'WÍØxw>¬RŸAÙM9Ýùs¹íÌ9Þ;¸w·uåܤyª‹œj5ïÊ98蓵K¦€/Gˆx¤\‹L3ƒÝ–Ý«ŸÜwtzôêEUÇâƒp°oDTfû ]æm=íßt£[Ð-;#ø8«‚7³Ì”ça1ãþʺâô+²Ù÷~©r®²‰Ý˜Ñ‘ð&÷m¶ÄOÚ½F‡;œf7ÝØ!†C('uç}1Öؘ\‘@²÷Ò´YŸKœ)Ã›ÔØìÎ%ýܶeIÌŠ<íàNR^\k{BûAû5*äîzžóP°÷Æ!Å63óùlnÿM4|¶»5·ææ'¢sÖwçDçù‰[•4íÛÅÃ3Øúƒ`g鸊Ü' Øx‡3ÄÉ­k‘ZŸS?¼‰|=ï LÜð„ôØ{ç\ZãoÛÙVÎGf;a¶“¾Ù®Îµ¡áF—FGôÎõ#—®Ý7Ìln–€™[ÇÏ4óäùØàÉ\×-ÕeÇSQЩñÜHñ•»î[TëæÖxóus+>´á*Ê“âù'A3;*ͬ°·â_œ îÓù' â„0ßÒåB_i(ÿÏ?iëÎGÿHj1f¯‡9ÿsÎÝlçñý‡3sÎ,£ ²tÖÁ­ÉêT÷ÁÖ$÷´±ÜDÞÄkÍîܸîv{àÃèZ~,àß_S<¼kÝaÃu7ŸË-nëéQaWÞO ɳÔã…Ž}2Sú¢Ê?¡+'»^ÛÝ£ý²õü»[6ùøvŽêÙ1õ«×C;¦†ìŽaösíÉÔû»dUÈíü!™›,7»Á{‚ XïXùÍ,½SH‰¤Kç(ÇƳ¶Û;bg›;…œW­‹¯a›ZJmÏàâ^<¼a0××µmââŸXpñðƒ ëÇ•ðí&ÃÖÁØë¹¡ŸrlÔs§Þs3Ûúí‚vf}†é·ì€ßµuqA{W„Ε¼ *†Ï¿%Îü¼\§ÁxCÐ}îØ \F”mkÏaw†¸kŸëtc¸Ùpãcw†»¢=Šr9ޤ³œÏiOJ@ÅX¢ð|o3#Þ[ct¹Ín;ù+_wæÇÏ™& ܉»ðÌ%¦/”mx#…y”Íž¯‰êPª-dtløØ_LâQÏÑ1{È߽И6xÐr³Ã¼×êp¸ ¥ØtQ6½÷‘ÈÂýnì‘ïDíïw-aòŒ¿ñÃ6>ã¹ÑäKmÇISÐ`ñÝ6>ƒvMѼ%ì\óVz„ÑÞ¼•^åÆglw‰ä÷%Þš©E>6>mQË®³·Ò_4üxùïØøŒÞ Ì¡éÜÒ{Œöà½nŸ±ÕêÔŠòù¶?¥%™ -4ÃùŸá|â}¤ç:ÃKÛ<e.ŠI^fÄ™y*>X öüWÍLà«àqÆÜn;òàùeën7 ÷|Ùáav«Ô^Ó÷ßÏÞª'{n¼Ú¯+T|%«<º¿·÷f<ÚíUy€ëäVSïœ;¸‹³•‹¥ê¾®õºÍµ²Ë[}?C/]í×»Ú —n¸k;ü¡»ö{únxßûÅŒöxwß&ë¾·tÌ…Ñ]áPôC}]78O»±Œî"˶÷¾Y73à Оø w“D•ÜE–õ놛[5ê²lûuxx›óݧÝTÅ*F1A»wjÀ*½W÷NþÅìSwgïúû·yï†Ûü„€Qj’wÃáƒràô¾ FÈùǺ¯fù‚†d¸å×8Ù{4ÄÅ«ÎbN£Ì{­jåNuÇàC{MjÞåšËÒOëöúb&‡ãž˜Ø—29ÃR¼K¼ïÀ.mqÛá’Ä÷@÷ä$h®%h:†Æd'Wø+j¶ÃaÂ*нÖäC„t+ 6¼äõ½\áÝùSä‰B»h;¦E{’o4¹Ã{…Ñ)òœâï{º¸K^½Ÿ³³'{ωž¢˜ÛWû¸È7FûÉÛz øïv»žkÈ{o:p“·?Üâü]­`‹#æuȉ]c3†ß–ÎûÕÖ²3Æ\y,‰—nöªýÒ)ï§QaG|¼ˆ‰6 dxé”-|m§µà9Û™w‰ïÌÊ"fÅp´Írï¶ݼ›»Mßœ>B‚Ša‡Ç;RàØ=Ʋ›zëç@jІû$]õK§ øNv9ðO .—§“#õüî¸þø–Ás”ü÷\*Ÿdæç´yÈíëÀÏ 3'OCy­«Á¶!TS§|euäµP§¯YSgj–¢Ý5[ß06FMNÇ4‘ÿüùhLóúm«µºðK€F‘|ÕzÐQ£©¿»/pÛ苼íî õûuÒrâ×€ŠÛ5wÔA^©·øA º ïî3ïcÔ^4í$üÆŒ'§.‹ô¡£jU ÀšÈ‡ŒôL  ÒY01|+HÁÄð³ ž™>¤Ý`bNÜÄð§Ðbs V`Gé:“Ï­ózíú †d†ä%¬;0C’“Ü=CV ÁƨÝϺV̼®ýó YœÒÀ ¡+ïgíË–r±÷£ì¯]vÈ׃mÄÉLdbZ{aP/–iôÜZ$ÇÅÛ™78ÅÖ%³ÙZÿØ­xÿ{k*F ‹Zñ/ˆ¹1yœÔ_@>ÓU¡³¸sqkxi,>˾t¦\ÙPz cÕøoçYÍ÷öà ÜתëþN‰­I:‚8·Eoþ÷Ötb‘œMï–¸Ù×Ê ³2Y¶Üj–¯™QÅn¹^œŠ=3zhQFo_±øÉ²u¡É/œ6ŠkÙ-[ë:Üfß÷¢ºtVÐ'§oº‰ÜrñÖúa8á· ËêBßœ¾iW¿ãŸïÁ#Ü úžå’ëûJ\ß`õtÕ'½Èw4Ü[ßᮾÖ•ÏZëôNú6ï¬Õm`ÏLLs3G}ÆÇ 3S¾¯F_ºñÔ'íÃwâó¥g榺ú¤Ú׸¯<-UWõšý8޽óð­ý›âês³ñæ¹ÚÐ1¦6yß}µõôÎÖöŸfZLXvÑ~ÐÙnþåÖ¾êj³Þ#¿7oèÖkÞöãÿÍ_Ø1o]×deñÒF1™¾;ohЫgûѱM‡­=-ÚýÞúF»}ä,Þu|¤ØZŒ´j_õg‡míÕ¶ï­i*¯­}W#ò̃x'?óW;0¥=1kUL^=;Bw«ŸÙsk}‡¥ë{²u¾6tñÙº=¼}ѽ{ X…Iªsóõð»ºÐÞg&´;o~ùÖÝ3=Þ=ÙÍm_iÎk—­Õ±|À[Ê7ã\Ì_QË£[-3ôÈÕ³Ñèo~o<=s6½h‰<ˆúr߯ò ìêÃ_õ‰™ö¬7m¯/çfíEçÕ «Ýtd2DozûÉ[gÎî‰ïL²÷fkCŸ]{t4»âíÛ°ÄÌP›w,û}hÃ3ÒpzûÇwàÄìó£JW {õ£ÑôúÙoo¿\}«ëÛÌ$ìðéšRÙY°Òœ>)ÞmÝòïlfGgèwÏØÚ×®îóaË•¢|§³ƒ—UÝ|FÃï¾Ìé.ø{½ã;d^®4Þæ§âÏÇúÜï>vå÷vÏéÝ÷võ"½·[Ÿ­¶OÚ×Ü’Fs£þÙmXiqï,|o ±–ÑóIÐÈ?Û÷ÇðÄjØ™?Ê~7Ø÷ûmßõ»àÔh·¢jšà© ޹°Úû’Ç'ç^¯±™OÝ(mŒ»h«Å¨Ë{vÆæøòÔNštÛzgÊÔe5ø˜!ÅÂM¤õ®Û«É)žßÞœì zÎØž“}YÏ)>îÞœìðzN4à{s‚-ê9ѲîÍ Ö©çD‡º7'ø«žýìÞœ`ÂzN´Ü{s‚M»sšýЛ¼\ωwoN°{=' ½9¹%ÔsҜޜÖ#GWNÔ”zsrw©çäØß›ÓzéÊit¯{rr‹ªç„3Ü›“»X='ºÛ½9­“®œhz÷æänXÏ 9¡7'·ÌzNt^{sr_­çD÷µ7'÷ÞzN4{s:ß·»s¡ìÍé|ùîÎɃޜÜèë9I½9á Ôs¢ÝÝ›^C='š8½9áWÔs¢ÕÛ›^HCÀ[éÍ G¥žLoNçg¹šS;º m©Þœ– rnTNíëÍiy„]u¢ƒÖ›Óò;»r¢Þ›Óró»rÂÇíÍi5.vç4ܪޜV¤+'\¢ÞœVG§«7èqôæ´šI]9–oON«ÝÕ•}áÞœV÷­«ŸpÊzsšgÝ9áPõæ´Z™]½‘âÊÞœV+µ+§n¢½9înWoÐñí­Óé&ï®SŠo{ë´¾ºrJhoNÇ[ÛSÊU{sZO&]9¹5õæt>§vç·=§ãîÎ)¥‡½9­Çήœr[Ó›Óy@íÊ)NËÞœÖzWN<+ôæ´>â»rŠÇ·7§õ³ß•¿þ½9éA='²½9ÁŒõœòç¿7§QcéΉ6@oNãB´†×¸Ã¼†Q®<Ÿá@òN|N“ƒÙîÈa¸—væm4Fê9xçs «PÏÁ;Ÿ½…zÞùh§ÔsðÎç@W¡žƒw>Z4õ¼ó9Й©çàÏ®R=ï|´¯ê9xçs ­UÏÁ;Ÿ·zÞùhöÕsðÎç@㯞ƒw>zõ¼ó9Ð¥¬çàÏþi=ï|tvë9xçs ­[ÏÁ;Ÿ]îzÞùh}×sðN~8L0b}/òÎ×–®×Á;Ÿ\_ÏÁ;_+·ÀzÞù_Ïáüa˜Ü7ê9xçsp7©çàÏÁݧžƒw>w«zÞù`›z‹ylîlõ¼ó9¸ßÕsðÎçØÔsðÎçàÞXÏÁ;Ÿƒ;f=ï|î£õ¼ó9¸»ÖsðÎç TÏac&‡ñ~Óüó9à!ÔsðÎç€ßPÏÁ;ŸÞD=ï|ƒ»sðÎ瀃RÏÁ;Ÿ¾G=‡åØp(ê9,·Âæ€RÏa¹!6œz˱9¸¹×sØ[¼ÍÁ½žÃÞÞmnêõöÖnspC¯ç°·u›ƒ›y=‡½¥ÛÜÈë9ìíÜæÀS`=ï|î•õ¼ó9¸9×sðÎç@[¡žƒw>wèzÞùh7ÔsðÎç@롞ƒw>ºõ¼ó9Ðà¨ç°Ú6‡ÑúèÎÁ;ŸÃè’tçàÏŽI=‡Õ718ÏðÀºs8~˜Éaõ¡òò™Ž°Çÿó]j"Î1e¸ÿ6jµ¾õ+«vÝÊÂ’ª®¢Û†îúÝ¡ÅË® ‘͎æñ›‰6®¸²飉[Ñ-V¨H£HÚ§•¯ÆÝ¨|5SqÚ øj† hú•Éö»2÷¤‚‹«§Fuê~‹º9h@—0¢; rD¡-× öºÒ ©«Q×/9OhB²A#мWàFå“ I£‘X b‰ ]7‰! X*™8h’km«&PlLúIYSìwˆë ü ÛIê俱‰;ÂUæ¿ÂÝÀ¯Ð?¸(¬ þÛ €oÁÿ¬ç°)ìtr7Ãß7Ý[˜¸0 Eå7ÓÍC?\X3ýĈRßšµA4Í Õd6ÃŽØ3ÍxÉgNšÅ#«Y,21{úkê4'ýµéÅ éªvC³¿ÀÄ<íÿݸÿ ܤfýç‚HÿmyGÿm”wôßFyGÿÿ.=½gRèø7Òoé¸ÉTLo€x ã¤õ®©ðÁ—N¨—:=P]~ÚÀ#ùi üMˆ35PùÔñ⳨Ë-ꈰ}‹òh*Z„uµUZ^Ì·8Ë-Üþ)½>OÌîjKs‹la:b6ð öc=‘ç‹hWuP3è@·é²‰as–ž .žSø‹2ëÙÄ0[ÙÄPÝ‹~~º&æÞ [r¦^ý$۞ڃĹÕÞ¬Z¤#0XØXûz°xMxµ€¥m0X8@Ûs°î`ºÑ Qµš…!â~kKQ>Ýㆬ‰{<äÕn·g=&’m>&0Û|ì¬sd¡s_ÙйV¸xÛªë<"¡rUÅkÕžS§Zu}ÓþjÕ¾×TUÅbC Õ…]hd¨ó´ Qugª‡¾3îÔÐ÷ôwŠLl”³d£D²N‘‰NýEz+™ß™š±Ä ‘ŽîBhÚ;hvÔ™ÅïÑž9œÄž/ HeîF¢q©Ò±Cþ&îè!ã62ÎÌmרüꃋ‚LqºSÈÒöÏÁ°jÝ\¥qcw0ò Ù~a/Ñíßsq©.D‹ˆþ®¢¢ñ‡‰~ØEwú™=D›TtˆX¦ÂøÆ§ª ÚšÙ ¸Íaf'ˆM¡¹œ Í-&̱“…ÉUµmfÓ¶9_ÊlÚCA™LΡŸ‰;~èg]ÿ¤¾pÿW=~Œ5 æZÆÔÆÒP´}[Ná-*oö-ØÔ¾ÕW|9o ÃÕÌ·ùª~hR \[s¢¦F“7qT\ÿÄQË×êÿpº~)«Û:&j¶4õµ‹´U'¢Y ò˜¨<ÚUu‰ò˜$æˆú>Iì!I°Ücvÿdj–S¾h¤Ükˆ½5™¼1Ûc2j13r¨G¦™£çrˆÉqŽ}b¶öa¨&ÆìÀøÒr9žÂþÅçÕ¡}9†,)\Mj8œK@,‡ÃcÃŽ‚3Ž+‡ñ«åpT`æõp&Fçál%¤‡£¤ût*H …Ô©LŒÜ©ô6üTÀ`ùOcp™†»XuÓÐ3.0WÓ¸È5tW`ËMçÊP îéÌLú¦Ã,° §sM-°¦3{z:ƒ}ÆXÏÀ‰Y‘ÞÍ`?àÀvæqa;ƒ+®pb4æ?Žlgpm)Òƒ™0>0f0¬_Í䢇SÛ™ ™"{j&óƒkÛ™ì§"›x&óˆƒÛ™rm«9˜É\qØ™ >.23¹îãìv&})Ò¯YÌ,.ogÁš+2ß³¸`âøvW“"·‡YlzÜßÎÂýY‘9™¥¾iþgÁ<+rÅÅÿ"Xe–êâ<¤Rd^`g–èóÌk‰ù?FE p$›g¾G‚JôëHæ­D?ޤ%þ k×¾G2¯%æèHöM‰Þµsa+±gÚ™y\üâ)¯Ì\Îfç—©g6¨±LͳA$eòÎѽIó7‡Âíï\Pj™:æ2¯8ÿ‹jc™=3—¹Äð\f¹ *žËÎÃð\öG™>â™wÀs©¹ÂÏ5§Àó¸ÂqišâÁ5ð<]’ÔyôÁóðþZažç¡†^¡gó¸ÝT˜_ùw‹ @úGqGà"uŠ%úvóUa>’ƒbõí(öL…~Í\V˜«£Oä[µ¶bõÍÌ4PÿѰ¯Ø·Gÿ<ÞóGß¡[X¬ HvÝÈð0ÅD\ 2LÄýÁhÿ¼‹j§ÅbÄg¨ãwxûsŠõöw‰ÞªhYÑÏ}·¢  Tñ³Š6é-· KÌq70w fe2¿ctÇR/ÊÓŽ8†Y‹#L¦Ùž/v¦vœ<%˜¾Ì³]³2_ìí¤BÇš™ì°×Xv`Âbêøv®'¼?ž‘ïwýD“Âv—›NvËùg˜äo~Ç Ÿ©KÇŠã«.+nª[(=!‚…º/êÿBÍž6ïB!4mÒEÏ‹¯x‹tÅÓ¦\ÄÆ)-fóÑÅL9Xz1‰éîqt:Ç {ks'O:êöñBDÚlÇÓ|&b¿„´„«<£%M –ì8ü ¤%ÅÝ^r‘º‰Ã-·è=Ú4v#(“™×7¸¨zKÓÀö^»#–ÒP5™nt;€L¨âØ·ô,­©aCÌ8ݾ]䑿!JÍÓñW„p–è:¢ y‚óv£o®ÄÚr'ˆÃ©9:Q;Dst¢nÚè'j“%œ¨Û—6÷‰Ì 7¯_o/Žû¢ÛD`Hw]ùþO_ë7bü+¢7(š¤o9':×Ê"b°[„ÏNÒÐ.:I;J»è$M»6æIº>ijOÒ SØa©v‰ðËRuG¸i©®Uz»Ty„;–ŠE+,±T×*ÍäÉêªzs²Ü‘)t2¾;¸åžBÍ\æNa3àîå„§¸¼@|ˆÁ*§r¡a;œ*ü¬íp*ÿÁѧ^wýÔ/iÛÖºn¦÷•¾ë‰*7›˜-Ôqa`>^á"`æc§¢…ôív™”"4Ëäö@}Y&v€zuššÞÓ¤«-vÚGø®;]—IíèӥȠ98],~áìåÔÀEryk|/YŽÒ}_¡îiÎV0ý1õ¬‹Ðç3¨/f¾ÎÐÕ¦=“\1u© §föL6"ÛñLp>îÎÎÒ]Asv3GÃÏ–KfÍÇ٫ݼ£ßû¼ô½™MqR¾Á¸°™ßÙ¸)_-®öïSˆ«yŠn½î÷ñº´ßŸ*ÎŒr<ÕÉùë[ÈŸ yª®Øšà§êº£N>U(Kûí©ÒÕÑvxªp…&äiωk{Ús\§žFð×ý…/9èEé[ ¹£¥HÆüž¦k§ºð4]‚Õ…§ILóô4a'œrf4OOÓ-]UŸ³[\í9»¥«ýèª=GS¯)9G|#Mä9ÂvTÅ•H“~޶£&ðÍP÷9º?+ôt!¡×§ÏŒ«úL! SýGªž©db3vˆ½¸W'öéàp¢O×þ.yºX\ÚWO—ú“æárt¤‰|†:£Ž­Ô}QÝZ)¢}²R W[)í–•bÉiŸ¬ä =Y¥=¥ÝºJŽéTçªiq'WMÓÝtò.¥Í;I__@tm•gˆ“‹—ã‡ÅMs‹Šó•h¤›šW~ë5¿Ulvó*!+Mã¹ÂÉêýyb;iöÏS½šÌóÄ—Ð>>O³!duž®ÁÚ©ç‰å§©=視—ç]•Þ ¿ãweÞKQÖ=ùð°]X­¸6ÐjéB ͬ֬ M¬–föájÝœ5«ÅïÔ†_#|©½±F;D¸o6—º²FFáÞ5ºDj2×c?®ÑõRÝYó…ôÎÈöã+úvFÊ=1“Féþªâ×¹µÚ%Â$kuÐa­ø(š£µÂlšÇµBBüçë½¶ûùªQ<Ÿ›su¾ä›/&ƒ0ÙùMq§Î_!L–ïV&=ë”ß`Y§˜ûgdPúc};_XKw¾MêÙùÂXÊ|X‰BÖh+kþ/SìM¢úu­zs®ÿÚqë4©ÚÐëŒ9±NWí¯uõq×µôoiõ#ïãî{uƄ阿1¾s뤮µ^(U[/®œ:·^ú#êÜz1Å´+Öë ¯í¶ÞÐË3É †z¦:¥ëå35yBÝÏ\wê™Õnâ4ƒ‡+ag<¨„»nÆõ‰¥;QqQåí˜Æî÷LÕ¢ Œð,GÂT=ëÃ|«ŸÏ‚韰7/úÒÝç°u¤^¢‹›öæ%§ÇÓwÉkµ#rœùÙ^$’ÏbçÛF5w°ZªÑür έ¾MÄó<7§—èÒ «Å%âºh»nã™ÍRíP_7k‹©Ÿ›…Ä´•¶ ü²Ey´e·|>îï–¯¨¢¤Šà2»)¹ /ÕCY/U%ªðÒ[㌗JGÁå¸LˆQo.ksUdx-er~ 8Îðá-÷{Öâ7ÏÒFt¿ŸGüæçµ»]u?#zó3š÷æËs‹nnþͧíQ¢³¿w¿y§XOî÷ŽwÇoÞ!7!.÷;ßlyP°ño>foÀZþÍ™öæ©{óõ›zäŸ'}¿Œ7ÔíÞÜü/ñ››¥ ê~›æÅo6¨5e&çWÒ—\³ÁkÓø³eq¾ŸÕíÑÏÇGl>¸Nù7'Ú˜Wî÷ö•ñ›·ënâ{âX[7Ç\!;GØa¶Öåù€í‰HÕ˽y–ÍdzÂ|¼Ýfëí«¾FÇSºY×\ŸçÏ-³àÞ¼»$~ón)·ú7—Úø~Û€œ´‘.3èewmÜ:~Z~æí‡£ ]÷÷‚-f\¸¦/Ðþ€³–½àjÇ&Ë^ ¿Z{Š«8 îEÄ‹p±Ä½¾³féÒ|ÜTkùþÎÅÔ;Ã4íÌÇ=¶zöÂ_ï³þª™½ànOóÂü•Í‘ê TBju  ŠÌ^ þjì×¥/¸ñÃ_Ï^H¹µ£V]æ)oe/À\²°Í𛘽@1•þg/„µvHö¾5Šb–SÎ n®µ9[q×É^°I`Ãf/Œƒþê ®‡F$"}Aåܲh”p Ë^ HRÛ+ì Z­(sÖúr†Ÿ½ÃÆ€(ùL×ë_pòÏvÊ7WW¨XÜ]ø& n˜pR„DðÄ Z4³¤MÛ…0ÖÝÆÛ>HP ¤XLkÝ_biÉ ýˆÄ@`K‰)KY9ž¤ÕoÙ‘.ûlu8£Üi„4c1e¥j ç8bÖc]Ît¡–U,Ë<‚- k'‚5ëž"FA, XîÜÖñvÉåA¼šX7C݆bibh6b!®°2ÅÆuƒG§D÷–XW]±Œb!m]-bÝ„¤bX„ ÞXWf]†a*FèqÅb£Â*‚ý#F•<àq}ˆÐýŠÅà•FX¬«;~ì`îÃ>‚“"äë¤ 릉77¡˜…F†¼pé™ÅºâíL³‰A ‡U7©X¨QL¯XÈ^׬X¨ ¦œ-¡à˜Yp.3«ÜÁbf5â&S$’§+Íj$¿NšU¸±X­º¶ÀÝ`pÄbØ éÆÌ*Wð˜Yäy‡{rÍj${Y÷©Xl1 à+Eà´…]vb±?`rpÿ×%Ö…Yh/J™Xw<ì1Ý´b!7®70§u㥧)½˜YÄw‚¦kI¬ “îbõêf#$‚ëŠÏÕí4]”bé¬éZË5(‚y3«W¥XmâÅÒsƒ™Ê%T×î˜Y¸ìǺ2èRdІ®ç±¸ºžÇÌjrŽÅE+ –öœz0Q"1OДÀÏ÷Cø\h¢âœË#·:î"º¾ÄºXèÚ3«‘-\àNs?„›«Fû=Ö­[[=fV#@¬Ëª°m`Èr•žˆuÙÒˆuq‰uÁ‡™Àeôh ÑÄb}p Ó¬ráu%¡!ä‹Ý¦Ò¬r‹…̅øžE ´˜YÀnFîfá½X¼!ÁXš‡Ü"¹Ë⥖ËŒ_¸pBœ±î»Â¢FS(-fV#ð+̆§ÑñÚ5š?ÂÁƯ£tÒNL.ÂÓFHHÛh ƒ]#¡s£ŽY1« ÀŠÁ¶èûÀ%G×¶†ñ^gY…ÁÁ¬ ›¡Ûw ½ÐX¾t™U®‡Ìªñf~%³ÊU’Y~„ãËŸ/³ £‰YåZɬⱗY…!¬â‰YÅ?/³ÊEY…Ƭâo—Y…}ǬÂûcV¹O3«\c™UîìÌ*×Pf•‹"³*> :_1:¥Æç¾îŠèuŰ,Ñöâ^ŒVX sÚøÞ…IÆ¬êÆ ç‰K+¬¿˜Û4 ¿Xþ•˜U¼ù2«ð™UaJøe`ÊX³*LkVa®1«h0«Â”h¥)ÑUSÿá”æì L‰ä˜N˜¿á`J|vƒ)ñÞ ¦Ä7˜Þ`J|{ƒ)‡`aJã+X˜­80%Œq0%t`JôêÀ”ÆK±0¥ñN,Li¼ S?Ä”Æÿ°0¥ñ;ÌÕ—Y¦4Þ†aŠ3«Â”Æ‹°0%Ú·`Jô Á”Ư°0%|L0e¢Y¦L4«Â”‰fU˜2Ѭ S&šUaÊD³*L™hV…)¹Bƒ)ͪ0e¢Y¦L4«Â”‰fU˜2Ѭ S&šUaÊD³*L™hV…)Í*ÌvfU˜2Ѭ S&šUaÊD³*L™hV…)ͪ0%`Ê„YS&Ì*˜2aVÁ”âKL™ˆy+L™0«`Ê„YSÂCS&Ì*˜2aVÁ”‰8«Â”0øÁ” ³ ¦L˜U0e2Í]1ØÊÏåŠÂ´ƒ(Ad J¶<ˆ’-¢d˃(Ùò J¶<ˆò×·4®ÞàíbFÁ^þbÝ:¹U&.,pz›»À<Ã2“T òfL‰±y@§ÄØ2 TblP*¶‡gX°)@« zmUw·¯Z_Ÿr°E[I±Oº˜6˜bŸ°+™è.xµÁ1;A¬F¡Ôj*°±ëÜ•ÐÆ®wÕØØ«\56öjwy4?E~ÕÕøLW#“f^êf€‹=SAΗ™æÚ"p%©–ì/blÐ51¶ÆOÅ3sîæ 4®9F?HÿµeÂ÷«O»i·—â²^Ü &7ƒ ÀÍš_%¥ƒ¶Û7vìOeìTð=ÓÈþ¤+ÄØ•¾t륦°Á4¼׹׫Šiç)r—ëª6ZÄ>ãºugèènÞéèÝv n'· ùõb·ì<­×-ßEºå;¤n¥z të×Û-4b@Çlâ]ê‹93­të·]¸pCXêúô¶xÒÝüÔåùe—‡Û 7…e®ysaàê$ô£Wq9åùÛh ˆôjº„zÑSÓÚ$º^˜êìÞäæÊgo¾ÓúÇÞ|—õ•½ c›{®>1ö&rƒ¦Þm¹™ò[ísós›àzÂ-ˆF‹«ý6{KO|í=ñ56»Îr§`“e7V.\?³Ü6ÐÏ^põ¨]Ò/®ê .%0}²ÜP¸Óf//ÁÝ¥V+™Ú n5ÜQ³L—Úì…î;×v]~:غ u¼Ðµ¨ã…îH/¸0ÕºÈí‰{pö‚«—áì÷*nÁÙ ö Œ¦ìû¨vIçúU«ƒ»Xí¶Î¶«½à–Vã0°§k•±ÁkÕ³ÛªoÊàf/ËÁ5¯6‹à•Úä ÉtLž0NÇ ®†`¤ì¸uŒì…°OÇäéÙñ‚ë$—õìwKWö‚‹¦çÚØÜ:QÚÈ^p­Í4·ìZ­Â¡Õ £v¼ÕØ`2ÐBö‚ mm:Á¡µéäª[{ZªM'—`Ï{²9@Ý5¶˜¼¶•Aì5xUúìh¿6‹Ü2~/¸Ô6wˆZV.¨Le/¸]Í^pÕ¨¡ îµ­Ã%~…}&Õ^¦&!.LèÇpaªpãàÂ$ECsaªp×àÂT‹raª€R¹0UÀm\˜* :.L®›\˜*\7¹0U¸nraªpÝäÂT‘¦‚°i…ë&¦Ê{qÇOÒàØj0J¬ú‹¹*™˜ÅÆÜ}à• ÍeÉlR°9‰‘† 3osr;2_Ì[&ͱ¹49Þ#y¸-1™¦¹Î•½K¨ W»Ii€ãáFY•1s¡ò7®TîæÃ”q×ZDmÄé™ê^ ü2x)t^ ]5º¬ú†—gšÍ¤ ñR`êÂKA'^Š.‰x)pHá¥ôsâz+F7*} . úMÍpVìV%W7X+†˜8-µt.YmêµÃ²4.q›Ï¡™ ¦Ä:ÍѽÎΆ‰Á&TL &¢*uu‰íÁeS˜éáš„ÇVIÃöþpuÀöY‘ç¹Ýõ\÷ ¥†Ñà§dl'jäêK¦èæç\þˆáèGñûYl5§WÔMˆ­á,‹Zbk9ÙZe já’É £Áõeµ8fÒÀ©-bÊâ6N”Mõ&VrÝeãñ}ÙUÄ-”›á±Ú±{ü®[÷ÎTožª˜te4 ‘$båÓõ9i¶úpsÈ\PÈ\ ËGw¸ÇæZlÞi¿'šNÞi—'šZbÚÛp”ML;:ÑdÓ]!YnW0Ôùžm1®îì b\Ø™fb\ÓŸ›¹ß)r‘›… î‹Ô&˜ùªqÚØCµ°™jˆLWÑ, ª†.dþÖT Ÿ²)j8—Ëo ir/¯ÕÊ×p%¼­Ze\ñjý€ë¢É^pd/tËïè«®ü/à”Õ®FÜkµ²Ïázg/Øõµp×j¨„‹?Cˆp~Þ×!Jçnfà¢d™¨ ÚÌ€Oj³rɪe.5”aø‹Ösa^ߨä%~BFPSvu#Ãñ–MHü¸‘8>h‰3Äõ¿wj,æRM… ©¬dp\é´‚ùý8½ ³[»¨ ¨ò¡å|Va®ðâêêZçꢚä$6G9ÛÒÞ ßas”wfQ]ª·d+[’­µ²]GÎõQÁ÷ЍauËʨà©ÎÛÚfxÏ„s±~†¤^~¿tÜšÌ?bþIæ1G$ó8#ó(ÁµÈ|É罺H†µ.užòTÕ ú[¶€*×W;Gb›£œaéܶ¶d«sÍu~ ¯ÖD·9/zçGù7ÕãûisTðIu„>T~ZÔÖV[ÓÌã¿mÁ‘Õ¦v„åÂ>Ê™@«¢œkÚ—%½ç9I^ÜÑå¾d ÆX£ª3nt£¼sÜ Dù9K:êë“ ÃFò·—–0O/0Hdšç{'ïrònUxqé„ñ¨Î5z\”[ç¢çñyd”[Ëg{”÷}—{¯6¯œ~‘¹Òåæé¢®¾«1è*SX›£ü_Ç $*ûlt çËçJG+FÅPŸÓ š™’žƒ¥03D (ç­Õ¸:{6¶Ô˜éâ'I4=ÊýVé¨ñ¤=ÉåËWQîõ¼žåÞÀçô(ç½mí5­í-q«ÜoäñŒ('ÿØÛ¬òï¿Àû™Qn£¿9ÕÝÀÎ,÷EkaPºÄõmµ“|‘$ÚsZ;šÛð´úý(DÉBy™?zÓvŸš¶ãùlGwRŸš—•¥£GÓøU|ªÃçò©i8ÏšËé£iÙ>gEyÿR´¤£¡—}®êZWÜ´h¾>:¿b6r™ÚMÚ”+—bXĘ)m¶”â]‹Úšý‚:664弃Uåþ¬­á¤d”×äÌ‚EùŠ €E?s.fZ7mrå}{®š.Dêg5ʹý ` 39=‹¿ÔÓÔuf¡Ïƒfòz Ž•*ÍIÙ½SUV;ßî•E P 4û´"§——ͪª˜]^]YQÅñ'+ÊUUÏŸSV9æÜªêi3˧¼J/Ï<º¬zAåô²ªòêŠ9UåóŽ+ƒ«q^ž™y2ÝžüZæÉ {bª³OfÆO ÿØ[‹/ºpwo9é«û{+J_5ôå_ïÔ«“¦N¯ž_>¯¢lVõôòYeÇcÔÅ?[V6ŸQ±¯ŠûùW+ޝd&>£ðq³æVV_=mötŸ{GæÙÞœé’Eoï}eÛ|yï“%9²÷Éòª²ªtî·Â£(çm™è±™òª¯lyWô>±å½¯÷‰//oã±QÞŠ.¨*+føOYåM°ø4‹Ÿdñé?Ùâ3âx”ëóënàSëìá³ û„¢€§µ.cÏáüðöt¹é“7¦+NŸ¼9]túä¼t-'ÌÕt«èåéZÒ'ëÒµ¤O.J×’>YÝ_‹º¶¢¿=Yß_‹žlì¯Eæ–L-§ Ìê œM“ Ÿ“ɯpå¤Ì,²†Nòß™~±|VÙqåQÁ»2ãéRø¦ùž™X—bÿô —â«™!v)>Ÿ~áR4õ÷"¼´`דôaååý½ÉRšõšõ(K9²¿WYJ²že)_Ùß»,åˆ =LG ôÒlG‹òFÚ-ï[’vÑ&ók÷Ð&»i 6™Á)yól²³É®îo›MvâÆù3¸hüÀðñª8~ãä™d/;“ìgÎ$3`' œIö”Óf’ù½”ޝâO ôláñ³*æL/Ÿ^|wã²§ñ ÝËÓ.îoažöË}ÌÓf=ÞöøŽæi‡ô·5{Z;ÐÛ%åeÓ”¦±)í³ÒzêÒe½®¦›?ÐK—΃'ßG—îØºt¿Ûß?û,]Giï–WVq íè w¸IÕÖß5“*ÛÐ!•Ç?¾c&Õ™ý2©îêïʾY¯,l-¹#Ah—}WöUds =PH›æúÑÌúæ~` u.áÔÝs =ÒJèÞe»Î%­ Í‹Žæo“W t1$>°¿•!ñ3ú°¿©!ñù ‰ýºðíÍß<ˆÎðàéesH³¢bîHX°0\¸c#: ©Í¹+€Äz÷ޝ¦^:CêwnDŽ!uË€ÌGgéñB]Ñü©¯äÖybGæ¨øôL sÓ2OlŠW[|F&ÅKÒOl s@T|f&ŵé'Lšõ±l^Åq:G.œ;kî¼Ùe•Qþ =;ŽSçòióÊËçDù®d+‰PŃÆŽ-ž±¨zþ‚Êʹó8˜ß)å g–ÍãôrÂqåþe´\/—Î=ÚYê<¥lvy”<ÑQชEȤð`QùÔGÍóÙ,—à¤òã§ÎeÙ®„8 Å½¬b¼Ô+û^²Ï‹ô>‘´a¥n^BU p‘3ý`þ1Õ3æÆ'%³x+ß—Ú™󅥵Êw^YX¹À­œ“ÁoºÅâõ«G‹ËМ}i:z,QÓW]HÔ2]Dt{&Ó2˜ityE”ãµ6“¢f$í[e2#d¢'Wøèòò£«§q0§hÿ@÷–ò´Þb”݉Ï?X̃@ýƒãxð˽ŽgýÖû`éô*n´æLíŸèAœ.üxÞ¯œZ6`à~úfiÅlH"±»$ðè„L"³mÓ76QyrºÓÇÍ*£ öÈ–=P21w;ÞœÉT$ŽGP}tºRL3òIHt2XoN'÷kûßhñèÆ©•ìÅläí«SÉnΧù›E¼ù‹ìzc`wþfo&õ¿YΛæþ7Oå9ÿ„îêM¶pì›e¼9´ÿÍÂQN³häµt¡#Òs¡ [>‹æÁÝ» ËÐlT,>sŒ&ºB™Ò¶bÞØ('Æü&*’—a]بªHwì Uñt]¨Î<#UgVf¢ê̪LTõ¦]H½ö¶g 5éÞ.f…G:|ÿ† ËD¹®—D,X45Ê]èÃK£wµ%¼°”ù¨PäqQnʇO˜SIê>,ø"†KZ‰L++ËçLwÈåi鬧; VÕihž…'Óã7†+a ØS\jƒš——ÏâˆqÊŒŠ£v¶|,ž :/ƒ¤Ízì¼2 vqµ^®˜YÁâÑžYR^=‹[ŽšËS|K³A¡°Õs§>ß]²´“WÄcå­KÇÄ ;9ʇóããº$ó@˜[lÚ¯e,¯šçºw·ž,­Pñï’3]í‘5ɶÚÖGj‹rÞâl ;‚\R"^¢ –^ê)x†ÑL0×ÎbÊ­¬^ën|”ûGý«¼Z§aÕUòl¹ò˜~¯òåmpe.2(~l××4V/‡ïY8V_eQâò¬s&VwðNìW?hùU-ãÇ.Aͽ|D˘Ñ.ðª–Qã(U´”¸ïÃ[d³=*xÓ2¼–o iéòö†öÆ$"PiyŽ}¹ñ´ÍI=‘9]ÌÓ{÷R\I5’š0¯laõÔã«s…—2Ïéñ(úÐ|Ýàˆk,pgíÔ¢ëÐàX‚i…õ`â³Ü>¾Iæé¾²$¡«Kùµâç­(›Z½©¼ÌÅoôfWvˆ«æá+S2¤C;[¥œ¹n™T0Ã_ù©§²–†Ím©iG±à}skW660ˆ—0¥Kæ.ÃÓøfX‘§¶Áë¬8Nè–^7ÿ×ķÌ]Òj«K¶C]Œr_;·½µ¦¹-öÐ,EMkÞW¬Éxï{¬üFõs!QšÖ“ð;u¹xSéè±Åà.±š= ×ù=N~ûž¦WÊ*q¹‘þi¢¼Zµìò(ÿKÖ âk”^ŽcTœé|MœZÛú´¢Ò/âÕU|9Ä4}ké˜±Ð¶ÞÆ§¢oçS¼Ó›ùWø|ª=ïäSìÕwñ)öê-|нúÑÒ1bûÞɧث¿Â§ø`WD‘ÎHpn^=‹F¹-b©µç7Ö,eø~ïÞl,@¥”|Ƹ¢z£«FïWªÔi:ñøíz’™fçMñs´APì¯ôÿØ©ábu øyÏŒò¿ßšl×Z'¦ëbÛQÁmļin³*;ë5‘ò÷¼uO{¾‹B4…Ò1G0E>5%>5Ge>5G>5G |Ίò¯S?L+ƒóñ-B¦Óŧ7ˆ^| é4oM| ˆ~µ·ƒ–ê«:ûñXSØÌ§¦ðÀÒ1¿‹ñ©·ñ9{Zf Ý/ºä;™7)“[6ç…j6D¹¥cGÑ»ùTïNâSv+»eýò†ºAqÏ¢¼] â7ú¡ð/£ƒZ/ÅYd×p¼¤tìjy)ŸªåçZÙÇ;š“+ôýëL–¾‹gðV™þ¢t,ìíâ¿ð©‰ù ŸzôW|jþšO©Ö¬ }£xýq[jy²ÕM}”ûc^kîåS£P)«qlàS£ÐȧZÚħ¨áO cœócQ¬ 3†{±¸tl %-);’4³)Iã1›’4³é—ú<›~̧úu Ÿêש|jS.ãS9OU1±t\1ULâSULæszT𲢋o·éü`,?Ê}.‰gDo+ª¯oìh[åÝÊ$‚….ð) +-²Â‹¿«®æH½’Ûé)Uó«§–Ïh g™có’ysçÀ^YåÁ-0O”hEõÑåi¨­eöŽS¥}AWÉÞ­¨àÌ^øLï¨à·B÷@a‹¦r/¯¡¹¦ueuC*Ê£žshñÏ{ë²o¢‹©Å† ϨoM&Y#Tå|!™ªò “­­œ —k}ù·ÅBt¥0 ®*ÏŽò¦w4sYíÓDË[RmÜϸâ]lÉÌ .9Å¢ìÃä" ¢ËÝaÁs–6s>‘ÇÇÛj–ãÄ?Ï’Üèó_Ìáâ;J`¹N_u— KöŠO6x[m#‡—¥½‰³±â‰¥ã¤ýq-z4„§mêÎãVçT¿Œ¬¢?W:N×™[’ÛkWgòŸ'« ê½¥ãÀÙå«7$ÇyzíØ‘>:-†âº…FoLÖÔ.[²’9N¾Ä¹Ð¥Œrãf¡!9›#‹HŠ?¡RµIðU· –aû,gUëί[Ý:œtBÙ§”Žô>•O¡ù{}å?¼kÕ”n¬oqº:˨CUM)0¯œÙ[Î#³·»;GÒÏâS#uŸíQAÏ}åÔ§±£œ#)@÷‚W–Žçt7‘XˈȔqÅ2:/ZïdA õ]ÙÆ%ºBA³åŠg’ZýÒñRÖùM>UÈs{òØ„wŒûEÉ—rRí{2/¤“ŠÚœÃúú{ÝZ_/Nµã·h‡š3¤ô M+Ÿz4”O]S†ñ©·ÃùÔ5eŸ.ü|h\ïŠè¡kë[T’œŒç›ëvqj9’Cý”Ú† HkÚh½° m%Kኾpô›iÆÁŠ?NÈ‘÷RœøËz¾dA‡éS¢Ü ¥Gˆ6—Om€W¥MÕס—Eùßüm3æQ‰VÁòÒ#Îàsz”7ªºz^UU³Æ15ÕÍ)ÇsÍÐY|j†6¥³`æ?UÞ9›×­§ð©Ñº<¤c4D(¾"¡s‡¬Ë6a¨`e¼ :—òå| §1ö^'þ•¶xô¯\¯zÇ¢;ƒnáÏRî‹bO)åÿc-–þ¾z*ã#0ð4>åzkÁàyÆÂßlœ"÷²\ñ?Iáð?âÈÒ‰³k lIµ-KÌœ>qz²íDˆm38Ï®mØTS»$U»¬mbüuAGÃĶôÊܛ‰|ˆã&<1{•wµ&—òZÚ.ÄKá–€Ÿó½8]yUâ¥Ð(.n / ÎX¶qI®l¨¤²Il¾ò:ºLs8e÷Íe_Ùá³2QÙñË‹2̃} J7ÝÆÄÞ˟̸™qqT‡‡SEùY®©¾¶ü˜½/1Rve—ø‡ ¥Ÿ·Ýµ1§ˆ9õHVÙô39_šw_J­ég¹”þ$ÿËG§ûò½ÖÇW¹„öòùXç¸\]yºx]иߣ ,^á&+Ã,a%©]“mX®‰)ÌÇ_ /M÷ù‰Ö‘±ôÍtÆïVXþ k‡Þi7ºŽ=Òê¤ ž¤ íËçøG•áE/í+ɣ×ì_´Ô ]H›àñÙ–j¡¬F„kÇ^8Єþ)4ò‰„|^²ð;iãφ´ß—ø‡.§‘áËèLOÁtu}·TB3\-ŽfÄ5Ÿ\âí²Öq´7“m¨ë{M2ç¢ZFD”ráæôíÄNVs“øøõN©š; ³ÿuNB` £þ¯K Pý—uS<úß–Z<ýßg|É¿oèröcû?¾þßÑEiç?A˜â{ÿ‘~ù¿`°?úïh¯0ì~Y¹ê¿ ÒhÙ˜·ôÅ?áéÒÌ?öÊgþËM Jþ×ËC¹éÏçÒSÿû!¥|Öã§š³þ|ŠZž81Åk†8m•/{ì Vž=dÁM¯ü;Îç•ñÿ…ýôQ >¿•†Q*þï<”b߈í%¿”¾þ'nNrÇ©aŸz{}ÝFruåÛìäÈAšuåó[(àñØ{ØèÑ;6RÞ‹<*vÄ&^\1gžSÖû¼8À!¯Î/.Ÿ7oî¼h—F{«½aÞÊÜÄ‹+ËæTÈ*¢ë!nSè¡üM”û¨zÉï{H¾‡ñ¸}óóhsÛÚ)µ!öYYëª]•ŸèfØ…#,üíê–}á™7÷Üuæ§{î<óÜžÛ×fEÃÎÚ¿ç’I8Žš‹C¯öÅÑU2ÊÎÊŸ‹×» ¸5Zpj4¼'HþÝ6¶ùu¼ußm%8@jÇWT;Þ¶¶áçËçQ-QwV´¨dÿ¨²kXÎ…§Q÷vêÞNݧt«tº­¬;vJtm´WQcÃëÞÊYU‹ª[;IJX;*=±¨Ç[ wCóÊÛ]xwYd1Ü-µ³±Êò©5Q]yóÓ´ pÈ8X–— ÆÇOÎ|ÍàKº½{äÅË5’ÆAØ€òæ5K8«iö9ÝÙŠÊcßBâ.^!›ø¦¾›A<ÚàXRѰ>ôÿFvgõöþ|šŸÍ9>~ØMòµÔ¸ŸôÈ£ÃN,µ·øÉaÿhï7îwœ{¼¶ÙêלG•£ÆývÀu«{nKï9‡ÚÎ og“¤ó®iÙ¹w´·ÿÖ\Nïí œé›¡=àß]Ç. ¾{MZ‡vH{wlÄÞìýW=›~_|í®G^¤ºë¹³ÿQ½{g;½®îky§=⤴ VŽ Vôsh¨S‘íãÀÎÅpáãw¥O°wøþ™j1\µ‡µ(ä;Çr0Ïì¨y“Å8šn ¹¯¹o±ÜÌûí!÷!÷ݶãp8t¢ßWjúþ&RÅ*œžmÁÏåDúVæ]ìûªñîáÝhÃ8'ëÄX>˜Ë¤ÛM¸lÅ¢ÜÏ ˜pïc¤)dt˜ødîFÈuË9Åð̓é¢Û¸ŠÃ¶8&¾©óF[‹[¸ç¶'àæPɔڑ $ˆ×&®‹®oµžèjP` àÔqÀ7µ/ÝŽ¼Cî*\Ç]Å7w«É¹yYe§fç–vGÅ#ss‰E³ˆµ‹ø¾qf”}9‹oçò$º•Ý0y1;nuÏm]¹» îàÝ­ä)”šu5±›°µ²¢4Û~ZÔÒ :wør)ßËʺ£Á–§®¥SàHòhmêªÍ.<û´(¡øNårnçö± ?íD ¿ÛÔ“Ez»57§3¼™ÚWÇ[¨CþL·-åÖ"‡Æ; ¨‡÷µŒ(p=X!|{CN”rõ*ï„\Äy¯&ï޺㫷¿½µj]þŒž5•žšu¾jÛZ;±úÆ>Y߆ío—Ù<ÝùØ<Ýió´ÅæéÎnÐk^Û–LmÑíz[›§è¦¾:ÞBvžî´yºÓæéÎþyú¨õûÎìÓïëÞºýíªÌ<ÙÚܪb"(jRMN÷|÷î^¶<&¯f‰]Ýî-áNÑîµ#ÊÛ-„ïoY8 ¼+Ä>—É{|…£âùáÇWjY|BxçïäÛÞÝòÝžy—윩;ñXˆØäÃßMTS²6¼Û•©)¹8¼ûRÈwoæð|𝰳a-¼v`-°KеðZèñÎûÇ^=|³wa:¸øI$‡Ø|¾ ÃîüŽfG±ÛÕí²Ò¸ ¸P„; É€˜Ukî{†o@~_ þÄÞIM½ªÕH¹«àWžmµàz¿ãâ;eµäõP«çDÀ/¦nñ®v×M­>FMEˉóÆÖØ/j­¾Žü¦¶îšñòHÍ"í®™yò1ê,–§\Nîim±7Ïj:ýG‘£-Ii„ÅpÌ*¾‡‰á™µÕb8=n±„Ñú€ÃGnvôAŽOØÃá~´â}íx¯ôµ‡þo‚ŽwòêË ï¶¦'ø¹Þ/°qšŠïÅû#ü=ãÙÊà âjÀ©25ÈÁnÓì{k•¾tqFƒÕ€ïVy,è†Ýxo Å}¸( 1¹³Œe%Äy¹Ú÷w›Ô#êVSûæzœ,цLZ#Æ[o²«ÿœÔ#ÞVÓÛ¬áÜÇëÁ…¬æ¦úküAï Ðß6æânu.'p³6žêîÕc¸W[ÎDv¯¾ÇîÕzçß ˜Ðß̪ØÐ2Ü60ßîNÝ=ßÙ­Ùs%¸5{ Ç­y‰áÜÔvàžèl!%‡{èwTÞäö1x™œ&7æØp¥{Óð/ö|É9D®t—§vÒܰßúù;Úæ“]¦˜±®k\ݺœìÇÞœì®zNvgoNvU=';¹7'û¨ž“Þ›“Ó™“¹kôæä~WÏ &éÍi¾ºs2¹½9-ŽíÊiðNONË7蚃MzrÚ½ÑU'¾X{sZJWNܵöæ„ßUωG×Þœ–+rnÌQNn'ÅÞœËñN8Öä`ƒÖs˜Íêr/¡Ý9xçsp#®çàÏÁ}¹žƒw>·ézÞùܵë9xçsp¯çàÏÁ=½žƒw>·øzÞEå)—ƒýÔ‘Ã`]ƒ8\Æsw¼óu<Òƒw¾x^õ¼óu Óƒw>·ˆzÞùZÁ[õ¼ó9àDÖsðÎ× ·¡žƒw>‡ÁXÝ9x§•ƒÝflá›7ºé.?~6P³ » ŽY­²Møª—P›ØÀ3M1^.ˆÇ Ÿp\^v“°’f¶IÚ1êv“œ6kç6áhœÞÏxÓýž²±"÷ë'Ø=8´U¿úI#F5ãt–ž5ë#TÚ¬wòÈÙ_žùuì¯k|•÷—§s Íyæ–ÇyiUÅÆöWlx}üÔZ†œ¹?P³©9nQ_Tu‹\xê.6H¼VU?HŽ„…¯Á´¡úÁÚ›â8 –×åa0ŽÒqì>D^¹ÕÍV¹Å×g¨øõr;” Äñ÷Pòâì{¨ÜïkN†Êu½ðó0rá~˜\þ‹™<Œ®Ú‡KTA×ካÎárx®®7TÝ'Fà\ï¸#ɃKð‘rI®“ùHøñrÖíÉ aí'?«êß~r3®)Ú àxy?®ã õîÇô'Ô2šÝš°‰F#ÄRÀíçþâ“iVößݱK˜Ñ5nš8v N‚etËBÇ…¯²Áª6êœÜj'8Ÿ¡M±Ü†}³ÉÞX7³öÍd{cÕCìcóÆÜ-Ü›Ù\BûýÄ „7r ë¦ÿc¶'ñª—XÅÛïx!¶~‡b6sÍ—ªØùÆ¿hæwXÜúŽšÔg¨ÈÕrˆ=ßñÏàµÊØÍþ…øz!÷ð¹ãUÜ‘¢Æ~3îlÕëÔ­ØÝ©;[ݳRw¶ò3›º³;6¸³•wyãÓÔ¸³•÷âÔmtHÆ­ñ@ìÜÙâq6wg+ô¹;[œÊ~98×î2¾ÅS[ãZÜëQ}¤¢­€!p€sjk|1;§¶Ñs¬Vm6ãÌÛ;µ•bïÔ6’ÿ]çÔ6npNm«kçÔ6’Ê‘sjy—ÄÔã]“ L®‚Õ>ËbSް®‡´˜«ÝbÖ©í_¹¹PçÍÍŽØ×Ü—X5¦ùö–ÇtÈ~ÄeX¾…ÙIHÝ8_ņ×ÉÜ3̰œä›Ìv¹mÀ0ä£sãúÌÝÅy2–[b:p¯«ýo\½8-f–F»º˜$ëVX@ÆÕÂ;8l!¦(Øn„Ë/úÆ)¬6 ê*⇧ië±j…\Œ:‡Ý ¼¢Bþ‚ZþÄ6ËÍ®fü¾’•ý¤>òá–Ü8±µ~Œ£è|—_ù#Q©ïroànÐ~G«:;ùæBJý_w_ 9§0äœÙ~ˆ¼™à™â±¯¼¸¯e>ÀÀ¸ü >ö†ÝÖtA*’Ëä%NÕÂàt׺ç' G¸Ä¨uç^>’›\ç^>ª²úØig„=sfØ3gûbzÏ|Ñõä÷%TÜ>PH©a ñ—ÍÌg/`ZÔ^ SWsœ+¤ØáÉçélÛìX½æ>˜»@íÜÙ2Ù DkÕ#HÜd/ð‰_óø{wæ>{šWö‚©üt¿Ã]Ñg>³Éð©~O¼Ÿì÷Ÿû‰~¼¿Úÿþ®4Ʋñ‡8³ù1W÷ßf¿éIæKÆ ßƒG”s}).‚ 7`#ʹ±t&%æKÙv¼ ݃C ™í“!Œ(çÎRÐ~Y*´c Añµñã°m»ϸ­Ån]‹Ÿì#R•ÑÓ«J#úãÔǪ*¶÷…Sw0΢U驿T=M®'LžÞÑÊd+7Õ,E<)^Äk—¸4BÉÅRŸ+ÞSR¾}\˜P)ä3QÁûœŽôù”w¹û¶ Ž¥Ññ£Ìׯ‹‹5Z/bmn«YšÄÇF¯D@õ’åK7¤ˆ÷í¡,Åi¥cF±Ø6ݯ˜“¼ nÎÆˆGk­)[NÛiÖÎÕÇŠâN7eb»õem[•_?²žék•׎†8d¤àÕøUÎZp´<ˆZ÷¹y|á\\›Åg¥ã2W+‹‰2”[Zš~cÜáÞg.¾4õ´}gMëRDì­×°âeD5Iäó²(ç…½=/töêæiFN+ÊδÈÇ9P•¤”-¾*¶‚g`Ø©Py¿ìN¥Y/ñäM6ƒå)x†ü¯åS&¾¬°û5X¥ï˜=5J¶cÜ»ê$F_*j鸧T‚Y†Ìtu¾V­Cb=ݹ¥#·Ð±ŠKI03*¸`‹°Hå˜ôËŽF&sõÒO΋KÇŒÁ©ÉKù”©žkù”Í’·`iK6KnâS“ñG\•Ú¢³P>ã1²qùï3–8„IêYÝV3Y‘ʶ™Wòm|·XW^ñÛ$ Ї•Ž•¹–‰|jv~þq"táƒX‘8A×4/Ê|àV <׸­GöãÇÑ¡wƒ*+jêêh]æ§\Î €sd•j¦lÀLæS³:…ÏvL¤¥VJª…áÂf¦lÓñ,¹¹yC:Mçâ:Œ/nMÜ6‘ÿYmòŒ“¸fL©×YÈgöš\ú]ÚÚLjCú0™]^HÂccª×Œ)s©SšÞmXt¼ g>¨-QÃ?#B¢Ë‰h(9Eñš1e.v.HÔ5´âЫ­¦–+îf× »•Óœò“»fLihnK¶šÇœ94G“`;´94(JW²:*ñoÌþ»::¨/¿D;wžvY{U”W4X*ü7Œ§1^Gú݇k⺣©Cɺaé7®‡óõ¶o>Ö×Ó¾ãî¬akJöÖýà¾OÃd#ý æÌÄżhxÒ ¢²½/xf¾Åhð;Ù ñÚ|ìÈ­ö¡/øEoù¼#;Ò‹—!²p‡½czñ/êþŠ½Óž‹s3ïâaÑ\¢‹)Žˆ=ŽP­±ÇÚw±ÇÂñ"à ¬ìN‘ÆÛ^°%vï=xÔýçøÏÜ‹?¯Lã­Ö¾9Ëœ{.ÂvèÚØY[ïØJÈ(ÃKmÖC^tbžË¾tÂ%fïsûC KW»_¾Œ5®žC Ù}h™âsRÅ„˜Àyâ 3Éž“êhM &¹¾Í¥ÜÜÑ¢‹˜@Ís’íä¶3£yAL ávwâ 53.ë¹5-¶ª%4zÿÜ ø/‰â¹\"¶íÅ ±l4Cí܃ª»u¿è ½•@äµ#÷DÉïw ËÚ=¯†¸áœ(›ÿ…I7ÁäPž«ÿÓûº¢\övëÙ{Gy¼/¯Vn#ÖÀÿFÞ'¼o"w3ñ~Ô>¿ÕÿôÝ\:ÚέhnO”µê„¬Pß0ßÚåâï싇\ê«ï©«ÿœ¾÷ÞT².:¦ëŸžó&ú9¯kéoê­ekÎþ×v-.©ì{S9Œ7SûÞ¨ÆEUu3¦¤ßܘõªºWôÇ?¶!¾:?§oWöÜ]µøsS˜‰¨jq¾¾ã3¹r‚G˜Îí¯ÿó^ÝuFÄ!¾ á.¿Jöà“3j+¹ ëÎh÷7{Ë `<.‘ÈjìÄølÀŸ³ýÈjìØ ¤«t?ƒn×!KqpLD¾ø¸·_,¬t·0<`÷æ×˜{‚(˧„|É‚<¨±#›p¹¸@ @dæ‹Kv¶°õUR¨sK*±$ Ò—ƒ¡- -ìå‹ë9¥Í,ÙPâìfQ Uó¹-ði¶¬|l73;‚:Lù]¼é†jpü60®Ý¹ÑY†m;±õØÆ.ǺøÜ›£*nrUqû­‹_ÜÒ½qE´hDW´ûp«·u#¶Ö^ÚšC®ÕYg¹ÝÓ•µ{„‘£9º)Ú·È˾»”isŽ“ýÝë±%;ÃcKvÓÙöŽ}àoTàX/TÌì{< N¾ÑÞ1Ëï ïnß&n¡á nyhL€ßQÖ‹ïÎkLÕž81ÑØ–LžØš=co†)îV¢ËïÉŸ‡”^zÁn— J¤Ûd»ñ޲ûo“ìç/¾é¼tÍ;ûF’cá–Ân™œ7ì¾ýð½{äNî#YO{Їeµ³ˆ¨¦¿‰0_~0ëþ&‚”¨f†¼@59Ä£0sŒ¸å¾Û¤Ü´hûêl+€†øMÛ'žgwDWÎ}¢vuåÜ'jgo ]9÷ Ô¸sŸ€ ½ãvåÜ'Thïì]9åRioNKz9­3^ðr¯&»¢žÃ ¦ÚìüzÞùà…zÞù`zÞùà”zÞùÝân&Gwc2ê9ÌĸÜ—ë9xçsp·®çàÏÁ-°žƒw>wÄzÞ}O$ÎÖÁý²žƒw>7ÑzÞùpê9xçsÀ©çàÏϤžƒw^$θwé‰+ªgHuýœ¼Õ4m‰MÓ6Ò…nš6´øUÓ¸ÅÁ¢˜&Y ªébfIRkº$äÅŠ›þ<Ç7ÃpÁ×Ó²qÊÕ»¨³¢<°2n¦KþQlú§ã:§Æêø¨ëDVÇXß™é'Rg¦K(HgÔ“(šáŒŠèáé’IR%¢Ñ×*‘@—­d†äÅŸ™!)U4C©âØ›):£Gl’c%£ÙYˆ­"¤Újr„> ©‹Män±:#”»X]b(‡~„XÐqÌGsî8Ée«çÇ! €Üñ"Iê˜q<2U1<ž@õxä…‘n;þƒqÿ¤ãùõÎsŽÐÜçëOu I+çÄ×4'ÀCÄù`RE9©Kt§Ðôˆ•iä…NïK3u¢d€Tù‰ ¶Lá‰H»QÁ‰êµ2žG¡ “ÞOßIz§í¹T¢Wâw,U¿$Ó·T¨MÌà“ÅБ,ÜÉß’¬õ)š Íâ©ä‰¹%žÊÆD¶nÒ‰1µ.c¶b]±`³êNp±‡êÐÅÏwÜÀ¬C}!¸.-þ÷<Þ~6-̧8¹8¦ÁÔ‚‹"†,º½0-ꈛ¢´ëR71c“˜¼šàMÚ’Ú›ÔuI&m’È›&øYe|k;ý@™²"xµKEð "xマÄíR<‰Ûuˆà!ìeEð "xƒûÆ‹àqþü‰SmEð˜hOï‡åáEð "xˆÚyDðÀÐÙ pDmË"cW`C씽ph:0»'{Ü\í2ràëlË"#‡êÀLweC:Âï.ºKŒ)@gÓ¾qN9ÐòŽ=†<ºßWÈ££‹àa?5HóŽ©mï÷7¿¯Àñäc_!ÁLLîø­À Èe¸£–šÀUØÌãg]Ì¢ ¤í@…5i»Ú¬!mÇN¬IÛe5yi;„,kÒvé<öñ ç£ o¹Ÿëþ ðÓÿPrJFÉä¾üo­éhñ²N•ŽþÊûÈ“œKŠ™ßâYâ~GÙ :D¥6å|TưœøY9³ÞWqï¥zµ„O‰HÀçQöó· ü‡¢UñùÔ'¿ÏÏDŸìÈ(û¹Û8öQþaEn,¢¼Ê"-‚j–]HmZëßÑ%sš`…¿ÿó¸ô6ÏF–×ïiói‹bíÜm£Ÿ+rz^¾¢È‘ò +}Ò|„‡HÆV‘²—É[Ù7kf£–×YOÊo ÀxG_%°#4Fùº†å¸€@å=.QšÊ‰˜u‘óPiëEªæ¢8t#!uC¡{äb]è²Å=.(Ê‘üàþ*éòihdÕú+Ó~‹Ÿ+ “yšG WâS¶¼ßõ(‡²ü¼¹n7ŒHùìÝ X}…—4µÕG9§:ûŽ+Û[åÞ­ü~ߺO9¡´2P?*#oíó©è!|j3LàS›áP>µ´qÐ~<ŸÂ‘?õ;êUù¤"GT‹r^Œ[¸(«Sõ°ZåŸ=¹è‘"¬ Véš[_Üï÷#ýú¡M^ÿÈê‹)³wKǸë ÉyÛuŸ¶?§A ‘ÿs~t´çJ6UU+ =F£˜Œ×¤¹­É.·×³š%|†”¨uä¹bcFn$W‡—·šÁ!ïx)»ëpFT—ÝïÊ$Tõ®Ž‡Çxbl½±_X º=¾ \%Þ8á‰ðÞ.–¦‰žù¤CÎ÷ÖQÍ'áÅ4d‡d±ô̯;Ý5Ù|®o‡p'Æ—‰ Á¦l»jF¾K•4¥4¯eðžÅ…5‘· FÄ8y„c»‰T§»¤#\ü¯__8 ^Gt a±¶=Óe¹_Em“cØxÖ0l7q„¸£ö«xÄb_j-éûûæ!`±o„ôné^—>¡cúÂ.õêOlõº½>XàÞ^sáíõ¡åU¼PWyÒ^Ì.o¯¶x§‚så™Å–Uh¼¨ÏÛƒcyún^¼Ù†Nwß­ˆ¢›oÎÎZ_óši³qÏ7ï„«­>Íœ/XÁÍk6)¦T­ò¡’ÒñíU¼ªvÅäí(‹×?^Ô†®§ä\صêpÙ•jǦS<4AìØ¨g]ItèpzÓÆÿ ®?ßQvùJôL»yã¨ÒŒ“³F–±Ç½½'§·IÆË[•ƒá•‚\ ÏH‡+±ÔöœˆT N‹z>š1V .åh¦»΄WƒÛm_ÎͰß%±º]B^ ~…³QØ¿CÊeS¢ÙÛqÐÿþ¿W.s¶{¼²DØ.ÇŸ#µ•×MŸÝÜrfèœÛl&ý|²çý|KkðK¼¥5æyI˜s¯ïÄ+EÀ;ñjf0;î ŠκKj­ž”˜*ý/ j|jšã›1&-Æ7õ‰ñÍ3±xtby+ò :ƒÔÔø`ò7Æ<—þ—h¯·Í+N ¶ëx/Ö‹¿"¶Á’) 9›yý/™ÛŽÊù ´u/n]YÕö+ ‰Óÿ’ù<ŒÚ™0oãb½úDdPYi¡{êÔ#îHÛ΃›‹R…X4ý/io]©ÔÒL±ÚljzPM³*‚6/JäׯöM3rqGcJ1Çå ‡…Ü© ¼I[ÄÈñyó I¾®ŒU|‘DÛ±‹q?¹Z‰VÎ+?z~º2jmâñø:ÌÁÛHkÐDÓ<[ú)ÁÂ>1}ú_ÒÖáTÝÎïh\ér¶ÕgDcÒn£ô–Ùx êÓÿíÞ}ºç:Û»Ë&J©M†T°¼w5};{o;¬æíp̶³{·³wQrC¥¥ŠÃÔ‘vtÚÑ"l_=6]$zÞ>ëÞ·êÈÞ¼ömWÞm¨4¨WA9Fø¼m$xLŠm3KØ&ä'‡ìó ,ùÜÔÒ,L@\ž=)ä•¢ÈÎ:,ŸÙüþGþ ¦ÌÞLžxwö ÝÔqÕiÑÞ«¹ä '15bswNÅ—mΠΙ¹émž»U}ÄÂ_˜‹öÚŒ½Kÿ=G7ñœÚsÍ$áfÕåßn]±gáÛÎëéé†É×.Knšõöóý±{ê ¾ëΣ/Wd/ÚܳÏMÚ7»ª› -ì6~2r5í§w§•ý¶®Øk%j/FùŽ:·1ïÛ.ˆJÏ:sx•; †šLŸ;Ô^6@Ô›¿é-50#í§ƒÛwE¥¡–½ùª{¥»/úžÏá`½—…¸c‰%[¨ïןMçÍ6{³Xß;r¢YäNˆ/¥_ïsj.¼Œ\Å›†Ö‚7íyü¼IÈß à²{åQUšÞ €‹ÞZ!ÎãS¸á^ņۓǪܤ¼õN0ìÌ`ƒÐßÀ°^éFü9!v¹ÅP#ñ¶áˆÝš±G˜Zìäþ{§½CÕÈ«ü¡Añ­ŒzNìïhzûHõ&µ+'EžØ[þäWäÝM!æëÖY[j`6†öÂW,&†{|»Å¤Î“x»uÚ‰WÞ•Oâ±¼Ô6ßÕ—,²˜”w’.ËâÝÎLÝÉ9“ÒŽìÍÙ IèMâgB3ñ}â·¡(ÅäNË:o·N9 Ã-&ýŽ‚ßBK…пÂX»'È¢Ïn›tï•”`Õ&Å(HÙ á61Ò):¥ö…ŒE@]?t›ªoí¹…$ú)· í»Eîv£)ßvz4bò:ðÔ[ÁS²5¹Oc3-ãÝ»Ò&˥̿¿¿`T S@2û26Õ 'ç ¢­¸óàâ± hnº7©W6ï/ðÿ€ØÌØ”»w™Ìºj¹ µTa²OïŒvñyÑQáÆ%M˜±pQlJÑx×v&Ä?Q¾#‹‹LRóÏÔNXÇ.7Ö¡°°$“1c1ÞžÉøÙ—mÞätíâÚÝßçG•„»‘ôWºóÛä®ëGÅ]G¿íîúÑÆ) H>6uïÍNƯ˜Ò¯8ñº³ŽðØ;¡“¡;ËhÑØÍ­‹»ÂäÙqATœÆæcU¹:Ém`±M|78{X}UÔãßí8/*³L…–Þ`ÿ¹QqW]vák¾•P{3ûx‚³Y4l²UPÕèn)Î?ë»ùSœíÇî^:ÞÈ·céÿ´ÅTÇÔÿ@¾%­÷׳ý®d?y¥wèXsÃóœv‘¿£çmñ²k¼ý]Þ]cïØ#SÓÍûßTî¼ÕQöÆ7vÖ>1{öƒƒ{öìpÖÎH÷,„;ö¥l*Ôɪ2$m.´¬Ù4¯¶ƒÙY²ªxP§[­™çøÔGùeësË„1Ï$›ŠunÚ—¦”®…™VÒ¶?Rm-èU¡-½§ƒ:kkZ›ºA·Å˜gúAÆ9é..7*@ô^–ÕÃÓË&"È}Y d_Ï}úâæöÖTãF¬ k¬1#%âãAqÛ9H_ª]}AbêÈDLüGÐû"”I×6Ë}®ÇÅ!måòOX&iPÐYú›Î²üÊ=—üªÃçW›}·: NÛ­·ÃRÍxÁÍæW½3ê*ꥯ!O<5O¯ºîòiFLÏ53u➦­xƲÅŇML´-ëh¯K­hFÆn·†Ôš½o«œ;¿*ºÐòk>£ùä×¼æù§‘ÿ’äK; `›š¡Ý]‘^fOÎW‡,CÁ^ñW/KB€<ÇêÔN‰Q§vL^çôÿQgvÄ÷%KÔ5µè«ÝgjÕ.Ìk1DA­ÚÏÑoe]Ó!¯ðmclqÂÇ9< ~i‹Úàz€!*úþ¾¾Ìþ÷Û¹²´–»Ç?e†S¬Æ_Æš:€«->ì½ ïæ5Ÿû_öÑ¢…sçM—ÇÝ™ÅÇ¡àêC-‡ú„UóúÎ{¼>+0:꓇«}ê†Îë[ýäÌœ?Xßü× önêCÅ?aú‡0®-å‚ÄŒ‘‰Úš¶¤a®qUº:ÐBÓQ7ƒ§¹DsÎO†°'s³w!ñ­ 0õ ¯=l)ewîCÜFë7"mã½7¢Ïä½Ýh|iwN!1w#* [¸>ÿ ã]螔ܩ؎ÏDÅUŸÅþ­½põäµ(Ïݼ=²luöùz»bÝð‰]§GE]¯Òº˜¨ZŸ?E¶u_ÿÎÝb“·Ã®$ÏŽwGG®ù|4iÍ÷£ ¡–kúòYî·ØiŽ£¬<ºùÎ$Ï9!ç²…Ÿýþ)ô QŽp¿R?¯ð<Þ(×ø…ë ^vOžÊ'¹kíæ³l¾1ºƒ¨½ØßèýOM£7ÑÂÓò[y{IWÌ…Áþ¯™9sÖÝL÷úàta²îuº+[•ÎãïÊù=_¿·AxÝ ?sV·¿jf<Óq]¯%pÞÚyˆgõöMñÉ77½AMÍÜÉ¿¬·g­ß0§µüѬ³w¼ÿTüöþø-ýñûã×öÇ·öÇ7ôÇÏéwô;šÜïî¿Ý]ì²°¿ÜŽ™šÞ9ÿ|Ã/\Œ v‡A›ÝÊ`MXÕV¹®žKÄÏs‘¹-Î÷JÏuå¦ç9CÜ%×Ù;îu·„Ü·Ù;´Ò¼kîp÷fxHºEÚ˜x¥²5ls‹Äžë¡:Ržü5–C›/öœr\nïtëŠÏïkït#I-óîËöN·Äs¤xçyHºOüLè]a˜½ÓÍ àݱðÎsÔ„ë ž×Å;¿?„ÇÅOÊÞy®´ptÁÏïül ÿülÁò³%<[Xòm1} Íœ¸ŠéÅ:•&â5‰‰}I,K&Ô”€i´|Q^Æ®¤ì;«/¦V µ>¯ NLºiLziL:iL–€Ó˜¬§1YNc²œÆÚBl|ˆM±É!6Õz̾¼'ÓãXûY<üúwõ¿t°ÄŽ’¥ù/Ýg¬^†ŒøOºÞôq1Ylfˆµ‡Ø¼›baÏ, ±¥!¶,ÄV„ØÙ!vNˆ­ ±5!¶.Ä6„ئÛb—‡ØÖÛbׄ؎»6Äv†Øõ!vCˆÝb»B즻9Än ±[Cì¶{oˆÝbw„Ø!vWˆ}*Äî±Ï„ØgCÌ»Î@µ“kù¥ÀI³ûËÞÔÐO.s;ñT‡ÿ…N°h.^àî%i›ëG]dž—¼o€oÕ†žÉ-UäN©Z÷¹)ªW÷¦óe™ÜÅ.Ô„Ùí]䘛;0JƵ ƒ¬œß|Ñ•NuîåIíå’~Ÿ:>:¤… ™?“â,œK6-þCÅÖ[Gã¶“ïiUÿíÒß'òŠÅSó.ÖÛ'¯Cânzð+'[Dïî`Nê|²=®“º{{v´Ï@o÷ð)ÏÕºKÊx[roazm~;zmÝBØ^Ó_ßkôÕž2:S'/þo39¡(ÕŒÖèZøAR,{h*S”ý\¢²ÜÙ«`Ùœþø^)/–g+(¿œü³M\DîËðo·Á¿ÕîšììŹ¥‰këï°º“Þœeøw/-7Ë;Ý,_¹yŽ3~í{Èy=9â5Éh®X¦£CpoZy/©Šº«6ð>âýÜþ÷súßÕÿ~^ï{ç hïèÏ®³ùÞÛŸïñ§FûÝ3·=zì™šíø”Ÿj°<_±x¸Í7Zâ\Á5+È.ðó­zb,aW¸}-¿l@'ÊëM‹mr€$]²­¯È¹¶êå‰ñ]§g]Ûuzqe×vê†}ÃùÜC?ån?‡÷ ÛßÏë> ‡)w‚•^˜ó¦Í9ަ†æí–5Ìï>>öQ]×ËÇðvÚµ]·Œ¨ìzeo¾öÞ| À­]µc®Å É®—“g;yŠä‰È»*§ÓxÏ´ûð3‰]ü°F•ü(ìWÔÑR'ÿzFy§w'°¼æšò£mÞQõïœ÷‚ !ãTÂqOð€Kñ¶Ÿò}Ç…1ê=Ð+!sÑ„.ß2Ñ¡g.¶}qT­Á=åû›pZ¯+”n3üåúNÄ{ùþ¢þƉê÷›ÜìÃ4ôÍÏÞ š˜[ÕôÞì=®° /þûS¾ß'UmsAJý°e/¾üS„§ÌÏéñ‘ßÕ+6fű7µæÞ/]oµ€p_&N~VKV©Õ×ÍP·näu›Z}Œš° O˜ô tÈú½¹½c Mø”ÕERTïu·¯õ £FSw_Ðc¤/º×ïî õûÎ,ÝBøªÒ}x æŽ:¨Qwćû`Å0ïïAoc÷\2÷¾j÷vùÑ›JNùïx¤õ†º¦[,Fg[?Ö‡³­;ý|³<CÐM7NÃ…œnŸ&†õgsoÜ;M ÏÎò~,ÏÞn?gôQn(þg™±ÇúˆOßôé|/òþ];ͧy‡/ß;œø¾ãÌÀ÷5þ6ë#« RŸüNó}Ð'@ßbù)lˆµ4ã=/+¼Lmv(p¨ F]ë8TÑV×4ŠK*©‚ìÒ)r~$ËHb‚ŸÖ!ªÞ&gkJ"›Ždq6T3l€7v•,··ŽCâ}%,@g—?–Ÿɺ40Ó­ãúp˜<ÇZílÏn}Í}¸k>¸Ë•+]Ù™A®ï¢’<îŠåtÂiô˜YpÜÓC¯/h|ŒÇb)vâ1k›Ýà1Ó_?ô‡9ÐåµõU’›Éç/Ìni­¯úã<:ó¸Å¸R÷Ì@à_=9ÔWŸ|ªì›úë{} ëK4 Øzƒæ¸ûÜ€¶³›æÝ½ãægç g èêz1tœ?çõâ ‚ÙÒý{è¿í˜Çgë€;uW—~<[ô±>[xzØ7[ô×÷«ÛÒ[màNÛT¼You¯YRWtJjÎoÓì{kµÍÿ¨Ã‡^¶÷§X=áÖ)­,Xº¾«ö€Â5µQÉ`]Íѳ3ûº¦Ä”ö#Ô¢ýQN¨–ÎÛ\ËÈÌÞ«ÖÂÞ·µàSDü«F4±ÊMì€É÷î¡QöP8ÜTñ“­ 9õ¦=§¦§Ü;;=jÕÕƒpêÑ §©}s=ßµ‘êêA‹—zÄIkzÛƒõ6¾xÜ>¦·~ðªÂhŒ\‰Í ñjÖÛà_…9нoäÊ!æ -÷ÿÎ=¬Ï~[öͽuzÝq ú音ž#w‰ õì²/ööÜñ 2ƒº <~[áö³E^›jZkšª›Ç žÉø­qÏàfîãê˜Þ¸•H?ð&Ÿë MáyC"è_®q¶ºq·¦37&ïVÌè5YÅN¯.‘6bçLÜ”áQ˜9ðsœcDN´Ä©hB—¼ñÌÇÔ! fb; ×ú®Ÿ æÀsƒ™Ïf–ØÀc꜃ÂXç]¹[*wMpÜÿ”. qES.uùµ¤E̽E{.};_þf²·hÔ¥oîBrÆŒ±»zœƒ¹]eœƒ%Ú˸ #'‹zsÚÜ•'F½9-žÙÓÞÈéf¥+'÷ÏÞ:í­¬+'÷ÓÞœö®Ô•“ûkoNîOõœÜo{sÚKWN9¹ÅÔsrŸíÍÉí¥ž“{yoNî+õœÜÛ{sÁÝ9Ùk½9¹—ÔsrWîÍi‚uç4v{{rró¨ç4¾zr#9Ùé8¢ëÉé¸2]9÷9£³£®œ¼ëÍiyh]9÷¹©³<ÊÝ9 ?¢7§1ïß]ç>vV·²«Nôæ´ú¥]9ákôæ´º¯»s7s½9-?³+'x´7§åÚvå$]oNÇóß=ãÞœV‡°k O¥'§åDìÞk–CÒƒ£,öîšé}ù¬‚®œûòYYWÎ}ù¬ç‡Ó¸Š3÷¢nWqæsgnkõ¼ó9¸‡×sðÎçàPÏÁ;ŸîF=ï|n_õ¼sïÌ­¬žƒw®ÃÛëÎaÞùè…ÔsðÎç@o£žƒw>úZõ¼ó9ÐòªçàÏžX=ï|4Íê9xçs «VÏÁ;Ÿ½·zÞùèÒÕsðÎç@/¯žƒw>š|õ¼ó9Ð ¬çàÏ~a=ï|ôë9xçs ïXÏÁ;Ÿ­ÉzÞùèYÖsðÎç@#³žƒw>Zœõ¼ó9Ðû¬ç°îm4Eë9xçs WZÏÁ;Ÿ¦zÞùè9ÕsðÎç@ ªžƒw>šRõ¼ó9Ш­çàÏîm=ï|4së9xçs ·[ÏÁ;ï0½«zëÃÄÖ¶o=ï|¼>ÔsðÎçàÚ[ÏÁ;Ÿ¿õ¼ó9ðBQÏá…šø¬¨çp®Yû p igOõ¼ó9ºW®§½iÚàòz‹×môÌêµòÎ÷Œ+t=ï|<¯×jž¸:ðaP¯Ãºå´ut»³4uw–p¿ëu8N¸É·®žÃrîlü£ÔsðÎ÷>r=ï|pê9xçspÛ¯çàÝ÷NšhQÔsðÎç0wÿîV‹Æ8¦4·nÇ”MâÆ°÷Œ±•êÏYêÏC6ýä¢@ÙšËc—AÍ/tþ}N!øÅ´ Å¡D¿ö\h~Í/·|l!WS3ìb<å5 µH}«YjšÓ¡Êþr棜ý±P¦ë~#íÝÐ; 3Nm=ýuM[¬ÿE–÷îe–7íFácÝ+èæ¯þЮVå„ç4Õñ¢ʧ0Ì@ááîÚGÒÈ‚{t 9¹Õ´ 3‹ƒ¹Ó£?îFLƒáV í1\ÏÇ!܉c:;^ ~‡€}ðû8„ Hà[ Aï6×JÑ$kÅçšdC¹Á*ŸâC ÅHÇ|zt܆qÏOP ÆT$ôiýL¸!C£"Á;à0òÁ5N]êΤèýpx©h½ /êÁÁ¬@ŽØ.*Ðó‘òÔ¢I9Ù99Ê& ÃõDÕ…‰f9óó¨Þ¸( \uZ/€DÍo¤âš ‘B@šýýäâGl§ýšãŠ÷ Ž’öÓ¥OS¶Ÿ.b¸–—PMÇhí$åÞ_ Üʽ?ãZ¸¿\þhz÷—*‡Ø‰cté×TŒ FÓ;æÎ¸Æ1wºý  ©/J·IÆ ‹?Ѧ½xãäPó1N›G3?N^$5ãäËQóx€\¼ªK(Ÿz ø/ªë@Ý!5ïãÅßgÃñÌ3ž9ÇsOC¯`üwâNˆÂÁ׉ê\ ˜í‚ÜË¥Ô—]}ͺùÎ=‡¤Ûš¦ä`uYSrˆ\j·"×›ÚI‡¨ñ‹Ñ=B|¢ âzh7M`Àó9”=C]‡Êï†rªû¯¦e¢f«W“˜rvÞahXÙǾá”acfcŠôo4ÓÑ `ÎÀ*»px¿Ÿ3Ø­èíµ³cð¾ »šÙÎΊéªŸìÊvæ%f†ä—,ÊBËb¶v¬n:sàÇLñp~ KiŽv°vç\6AÌLÍY$ôg=Iš×÷Õóر8°ž'Jå:Š}žÐË£èšG“+¡Æ£á±k&Æ®=ššàA£ÁÓlCÐMœ¯¬ÙžO¯Ø½ ˜„yYÆDOñX¶MÂÍðXvÚŠ µ»Õ¯…ðZÐY\Hm ®Rš‹‹˜Æ}~wÀq‹™¿Ød1· ´£Þ5G½ìêãé]NÉñì4—0Çìì%l‰ý]"båXß @O`3èé ÜÐ<¾»ýDI«iwØï »ÜFéÝA\¤å®gïFÒ¦p[”Lø]ôèÌýNÔ P˜ãDù|Ô8I;Qûè$ù Pý'}Ðe„f ¿ÉlQž÷-i~'Éí™æ|©øUš¥SâüKåXÒý– ƒ“ƒ=®ÙYª·váÉ/Œsì\÷ÚßÉò·ª\'놫zNþ‘åÀ!¥û"¼£·§ok×"Ç”š5|œ‚@NçA7¡eâh—-oQä4q.´ÃN"ÑŽ=M÷'íØÓ¤¥=wºøºÚi§Ëõ½&ètõKxm¹0»ðÂr!íˆå øiË?÷fùGRQ&7eÖ™†~Ë…¡µ=Vˆ%«m±âä8ãS¾ã¦”Ù±¸éR…ù”ÒS%ÝÏ¢xÉ´QT[î¥$sýË&ó©b ªkO•?KMÜS§Çu?•)ñ¨ªUþw•£Uh[[·ueœ£Õ]¦\.†äÍã÷,}uu µ1T=v¿¡r¥¦¼CuURÞ¡–Ã\êì¯IÊäzÓäØ!î *ó¼yéê+›ƒ²òÞýwº!1»õÒ™+›ŸØ2¶ëɇZM¯åµ–ý¦þkE:[MrÁAÈîß¼ÆÞ¼&¼ù½±vß,ÎÆ‘8›þ*ÿÈCô–cjsHýÄä`ûãNËÁ%Ýué2±—”ã²ïÆo/»+Ý­×[·\¦&qOé‚í0^äéöÙᣢ5׬ìÊškVÔÀÀâÖ5k[pÍ:.¸f•›ÖÔ5«Ü´¦®Yå¦5wÍ :@Yúf=$¸f\³‚ ¼kVx–™kV 2׬rŠª˜uÍ £Y׬Üë¼g>:F©ˆKØëÞŸ+3àý¹Â¨Ã-µ‚r¸±x¢°$½kVï¦•Š½›VPÞM+Œ)&É»õnZ©Ó»i¥†#Ì›*ïq¹A 1uÜ´zϪ¸i%Æ7­Ä¬OÕ¯¸¹Pç“Uë„ÖùDM]³þ©›púæ\³Â#ö{x”Í=ÓÁ<ƒžè^]áQÒþ{׬h©>:`Ü´f®YÿÆœ×R/^X™Cëš•éñ®YÁÇÞ5+»-Ä4²3ÀcÖ5+Y™Em&ÑUÄÃ8X(ƹk…׿6—Uë®Õ;a¥cv_íK¶cÎvSàý·òßywªÞ+]¡Ë¼¹.û‚ë“ß Ç[­¶sµæÔ{¹{B=â7ßüºjO;=²î^ážf]>qŒûÖeTK?@ÑtÌÃ¥ÎL“ºÜ¡yg®l»Ûé÷œä-qÞîÌåÚulïçté;³jw½4N¬‰Ñé§X}tú©a+qsð[éók÷ÀÍQ¬w[Ã*\TjÈ„ûKÍÕ,¼<úVóáZ{—˜ÉÏ^ÀÔ«ùj5ÏÕàïÚ xy5®°ðj>gáÜÁ-Ïp ;|‰[Ÿ³¸ ÷häê7‰n[©ÏYî1Þç,wVïsöõa“è¶’úœ•ŽKêsVZ/©ÏYîšaàÃÚ# Ю÷9Ë9ó9 Ó~ÖOnBèGe/`ñÕfεd/`èeSÀ øµ:¸e×rÀµC·${³.sË nhµ:`ÍϲpäÀƒÙ p< ùìü7æ%{Û­V\6hö‚Ë1/{ÁÅ ö‚Ûû7{o¶qö‚ëu­Cܹ‘e/ܵ:Áe²–ƒ[·œìÜçÚ ¸%µðß@¢Ù Øn\³­' 5ÞíR’Ç?` @0x¯Íl-.ÄØZ܈±µ¸>ckq›ð[‹Ë1‹w~ÁõäçÝÞŽj~wa+™¼ô‘Ø­Y÷~ÖÐ}! ¨4dn± t‹ø»ú3â*à dx‡e ÄÇÆd$þv‹ÓOâoëÿV‹›{€B7õÇå¿ÌÄ«`«òÉÔeÖgö¶s×é^°Õk/Øù5ô"¨Ý’À µ Md/@•Â&â24Iß#ý¢/!¹p£˳·.±xê^ ÚE“(é¹ø¡Kb¬a/Åløå±8?âÄò…wB·d|‘ÇøÊC/%ÖW>1cÐhŒã¶X| ¼b ÕÆLBÌV¹#Äìälƒj‡¼„Ó#aTÓ#xôH{ÙôH&Ó#]_Mtû6=/ÀôH;ÕôHÜÓ#1qLàgÐ#ñâLàÐ#q×LàeÐ#ívÓ#á`Ó#ø ô¿ô~=’_BÓ#i ˜‰`z$Þ„é‘?¦Gøœ GÚþ¦Gp©è‘ø¦Gâû™éÒkz¿„‰Idz¤ë²é‘.¿¦Gâµ™éönz„‰az$ýÓ#ñ#LðjNÄM1=çËôHjW¦Gòwfz„î=ÒõÚô¿fôgôofô^ =Â_=ƒ=Â=¿ÃôHÚ¦GèAÓ#ñCLÄÕ2=ÇÀôHZ ¦G⤘ ]› [›±»è‘0µé‘ð´é‘°´é‘p´é‘¶žé‘ö¡é‘6¥é‘v¨é‘¶«é‘ö®é‘6²é‘˜^¦Gâ蘉Ýez$f é‘48LÄ{0=‡=¦0=Â[=ÂôŽ=oÉôHxÆôHHÇôHÈô®=óÀôH¨ÍôHxÎôHHÏôïVôHèÐôn=¢4=Ö4= 5=‚ÏDàÑ#aZÓ#¡]Ó#xKôŸô/ôïôHxÛôHHÜôHÝô=®7=â7=Ò-ÀôHWÓ#¸ôßôôH7Ó#]#LtA1=ÒmÅôHWÓ#øOôH—Ó#ÝpLtÝ1=Â#=ÒEÈôÎ=ÒÉôOôH—'Ó#Ý®Ltÿ2=ÒeÌôH÷*Ó#ÝÞLtÁ3=Ò…ÎôH7NÓ#têéü/z¤Ë°é‘®È¦Gº,›é kz¤û©é‘nª¦Gx §GºmšéÞiz$nz$nz$nz$ômz$ämz$Ômz$Ämz$´mz$¤mz$”mz$æ€é‘8¦Gb˜‰‡`z$JÌ]=‚®AУDÎjÕ£D|õ(‘¥Yõ(‘Yõ(‘§Xõ>'=JÄùT&=J¸mÑ#¸jô(»Ó£„NñãÔ£„ë=J¸îÒ£„+;=J¸Ó£$NîÄô(£D0+=JtÅVnØô(‘tõ(A7„% uz”À G œ.z”pÑ£G‰xkêQÂe„%ÜèQÂ…Œ%ÜÕèQÂ…Š%0èQ".ªz”È;=ÒýÂôHÓ#xpôÞ=¶6=‚7G„­M„­M„­M„­M„­MàùÑ#akÓ#ø{ôHØÚô‹‚ô=¶6=¶6=¶6=¶6=¶6=¶6=‚ƒK„­M„­M„­Mð B„­M„­M„­M„­M„­M„­M„­M„­M„­M„­M„­M„­M„­M„­M„­Mð+B„­M„­M„­Õ#®B[É"nÈL;Lf\´ÀÁÂ5 8\² 0ˆ+.k¸`¡Šëø¸¿î.3`4Õ­+ /ðžsĵÜ^tɆã:ݦ›L,öƒ2›Ÿ¿˜³Pó!Ææqï.é‰\ ºKz"v¼»™ÁÌLof£;ÙuV5¶ª²2%ò Ê>D€}hôL.\¢Ðî:oƒ[3iຠœáhÑ v,db쉋íŽÏNx&1îÑÌ?WJXÌú³Ô Ë\Qä•ªõõS.f»õòÐ-¸pt žÝ2ª¦[øt¡öùºhU»uë¾éŒUï>í"Ýò¢[†nmp}±Ý‚ †:[è2õÅò y•ë–: ¯kÝ]L_±—š§wb/q1!Å^|¿ïp1»àÊÂo“!‘Ò–ê0=¼ÂUfcWºÊll›«ÌÆ®r•ÙØÕ®2R„;v¥ô:'—]ð ˜ Ø–ÔËl BŒy`ª‰qƒ[§.Ñ÷tÂÙì¸xd–´ÅÍô0ªZ_/r±¯ ñà5¾t1Šæ QØ\äqu ËLT¾P¿Ã€ò-"¥È”FôÇûÄó _ùYuõrú5žs§6Dc¿ãò0Êÿzú™±MPµÜ˜i-ÜèÃÃf¬|Ë­¥Ìgv¢ÓÎü^”¿‹=vîµDQª/Nà ¼ÐÍ»¶UN^†ëÆ8{?£1Ê™½Épb;PûT3ô±¢8½LŒûvvÑêˬÈ(ÿeñsIfú:ei½!±.}®rÖ‚£«Ž¯,Ç íÒY½ñ…sç•sMã§VVUÌSFŽ ÒoΘ_>/ÊyŸ9ÂÕ–;ûwÖ´.­Å:;hAþéÕä}OÙXZo¿ ½v•‹Ç4ã?-ÊΘL㪞›œ·®î£woµº\\Š ú™QÁolfv›¦/}‡=Ð¥påk?t«KñÉ>̦/*øRQKÇ=ÅÉxò·K7ÕùZ½yZû²0L—Ñ&Áîo• .6A–Ü_T:f ¬u“¹áG-éÿÀ9þJ”ø6á§öÛ–÷Þá+|Ê-|ŸÊÔȧZÓħLí÷ãSÆó›ùüô&W¬ÉùD/n1tv>ÁM(h?‡MuQ”ýéG¬mUnþ­?ÇâYHéÛå'ð$¹únÚè̲4)—YÚ•úаDùß—¾£%{ó«}S@áŸCF)¼–Óf)}õ÷Þx¢œE™jl"§ËíÇ&íõû&VÞù¸Ë›RU‘ÞG9g±„ŠV.ÅBÜ£NýËEf•ZÅÈ<àšŽ–¨à“ED ª;•Ñ??u_ò‹îw¬Rº¶H89Ê¿¢ÈÙ:Žò>é YFù‡9ЧÓï‘Qîs\ŠÊ>²ñ€.ËÐÿúæT”ÿ9©)*°±±¡3üã ]Ú@)_!pÊ{\¢4•1ˆ6ê"r®ën¤j.ŠC7r=—<9k¿Ðe‹{\Ðzìÿ làé´ªë@¥²½‰Ö9?ýS£¼÷Ùa•MV\ä]æ¬Ô§Û-¾øÊmîM£ÿr„Ñ€'êñŽü‹|j‹ŸÄç‘ ‚”pÎoE=¡v!·rKsà GF¹³H¢å~JéØQ¬úSùTtŸ³µfâ;_Pfæh.Ê+²ÐYž¬xl¦C„Ìõ ²" –³wÙ#Å72Qªr=u œV:vÅN,WL±“ø:™Ì§ÞƧÐÉ>Õ×ÃùT_§ò)t2Oµl:Ÿ*fŸªâ¤Òq ouuȲ8›OUq ŸªâT>UÅ2>UÅi|ªŠÓùTËùT+øT–ŽSã7ð©*.âS¯_úE·b3ÉfDy?{ÐÇLáCEî€óÀ.-¦(bf”·Èÿ“ì­®T—UO›75ÊY\W àÞÄ{µð£˜*ü3£üKuëåù õ¥âÚÒqB‘ïâd¨ÛÆ3Ÿ0œT™ô[CÅ÷S“&ì#ÎÚçJìt®^åÞÎ=r6¹3·³v+ûj”Ϋe/¨åötiëÊ(g|]ÍÊ(ïŠ&œq*ë½+“5­Q^©ò­$¯\.*^ùWwbÛµO†ð©}Òʧö‰¶Yû¨(ÿ´êêyUUCoÖœöBè{ŸGFùï{ÐCH”;ž<B§B™åÿäA«€ó#œ· :&¶5€ätK;¿¦6ÉÔE?Úju£ìŠÎžD9·‹|b_è¾{M©§/y ÆLÉtto4y=§¦R%OôÝ6uQe|V¯,Rè„JxqŸVäôò²YU³Ë«++pmù›z²¢|QUõü9e•ógέªž6³|Ú1QÁ«ôọ̀˪TN/«*¯®˜SU>ï8nðñ™zyò\ð+Ëç”MU>=Ê}½{³xvõüŠ”G¹­®ÒSgWW–U!ô^0}ú¼òù´â[¾º4Iô=Ñ¥_/¦Ù“OfžL·'¿–y2Þ˜êì“™ñ“Â?öÖâ‹.ÜÝ[NúêþÞŠÒW ½EùWÅ;õꤩӫ!œP6«zzù¬²ã£œÃý³eeóûª¸Ÿ_!ÊýšÂÇÍš[Yy<ÖïùÜ;2ÏðæL—,z{ï+ÛæË{Ÿ˜,É‘½O–W•U- s¿E9oËDÍ”W}eË»¢÷‰-ï}½O|yyòŽPtAUY1ÃÊ‚(o‚ŧYü$‹O·øÉŸÇ£\Ÿ_ò>>µt}|V‘æ|B)¦µ.cÏáùöt¹é“7¦+NŸ¼9]túä¼t-'ÌÕt«èåéZÒ'ëÒµ¤O.J×’>YÝ_‹º¶¢¿=Yß_‹žlì¯E'—[2µHõ°xy¦ÂÙ4™ð9™ü WNÊÌ"kèô(ÿéËg•W¼+3ž.…¯ašOñ癉u)öO¿p)¾šb—âóé.ES/ÒÉK v=IV^Þß›,¥Y¯Y²”#û{•¥4 ëY–ò•ý½ËRŽØÐÃôaqÄ@/Ív´¸!o¤Ýò¾%im2¿6| m²›úg“œ’7Ï&›1Ð9›ìêþ¶Ùd'nœ?ƒ‹Æ ¯Šã7NžIöò±3ÉÞ±qæL2vÂÀ™dOÙ8m&™ßKé¨ñ*þÔ@Ï?«bÎôòyàÅw÷7.{ß0н<íâþæi¿<ÐÇ+ýh §.]Öëjºù½téšyª&+½ÙõMîämßÊ7§ã'Ì.;šj.L?à+ÚÞiqy ¦=µ¢Šwgͬ˜FÇÍ%¼3•ržÀ0å»±«¾;¥¢jÞô¨àœþ‡QžÃtÇÎ[åZ/“쪷¼âèø\ze|Ô=e{ã„9Q«ÛÆÏž;ïxdÒæ<|\Ù4ú¿6ýhQÅ|ä\ÌýÈÄÝÕtYÙ¼²Y³€ å‘™§§.˜ÃÌ€kKR2fÎLüôs4-QÞín¼ŸÂ";¹zÚ¬¹ÓŽ!x Š._q©,Šoݯ‹Ç{ú1™ÓÏœô{n‹rw˼@cÜiLøä²i.CÅÝ@Ì“ÅU3Ù&QÁž½/tP ®H¿ÐÒ95úQä¶åò©£Æ§û»C®yrrÅô 'í»‹§ys;ؼ‰V¤ßhºmšÁ}©Ív‹/èKmߘðO½´ü8f-v×\ófÑl¶ûÉÜíì57îò¨ÉdfÛ¾X×÷ìÔU®Å÷…gÙâ/ºjúÌg³\‚“ÊŸ:—e s_‹{YŤ€®ì{É>/ÐûDZb„•R¸y U-\ÀEÎ ÷‚ùÇTϘŸ”Ìâ­|7^j gΖÖ*OÜyeaå·rN¿éSˆ×¯-.[å¼&=–¨é«‰.$j™‰."º=“iityºY&EÍHÚ·ÊdFÈDO®,ðÑååGWOã>`NÑþî-åi½Ä:(»Ÿ°˜úÇñà—{Ïú;¬÷ÁÒéUÜhÍ™Ú?у8]øñ¼_9µl>8ÀÀýôÍÒŠÙDbwIàÑ ™DfÛ¦ol¢òät§›UFì‘-{ dcêxs&S‘8AõÑqÈ‘uÍß,âÍ_ d×»ó7+x3©ÿÍrÞ4÷¿y*oÌù'tWo²…cß,ãÍ¡ýoΈrjü›EóÐÁI:B!=ç ²å³hê9d¢ÒÖ1ô=2ÊqÇh¢+”)]a+paPˆ1¿‰J™Ç°.lTU¤;v…ªxº.Tgž‘‰ª3+3QufU&ªzÓŽ.¤^{Û³„što³Â#¾Ç…eD ÷Ñ Mrú°€ÄÒ(Ç]m /¬¥D>*yìf>aN%©ø°à‹.i%2­¬,Ÿ3Ý!—§¥³ž~ì(XU§a')<™¿1\ s(ÁžâRÔ¼¼|GŒSfT°³åcñTÐyü mÖc畵‹«õrÅÌ öÌ’òêYÜr$ef9`Fg(~­¨ž;õùî„¥e¼"žŸ(o]:&RØÉQ>d×@@ü#™ÛÒ\ûZæÁòªy®mwëÉÒ ª.,Ckhukƒ؈rÞÒŽ|ÊÊúT+Li‰¶Ûv¢–^ÚÚÑì¨Ï†ÃLH6×ÀóãÿéuIÖÀš¶º9ñt’D·7º'ÅŸ9õƒÊ+›j:ãÈx¯éQþuí²”¤J—·7´#¿#M”“<„,êŒÂS‡Y)úbåMF—Îêæ¤RmA±(9.–– £Š[¹¤¡Å”óÊVO=¾ °Ux)ó–w¢Í׌¸Ft;»l§µQ‡×Á´ŽÂz0ëYn_ $ótÿX̦×U¤üZñçV”M­^GàÔ…˜Ö€ü]˜@¯£|ÑørR Ä˜.¥…+£üUÄÏ£…åWµŒKQþ-cF»À«ZFW TÑRâ¾oY’J5F¹/Y‚Ë(§G :OßæB¯¸R;û‡­¦ìÄô? ‚Ê [茅SªæN‹òxVYJí`iþõjÉÒíÒåÏþ–Ýß)ÅT{½t«þErÞ .Råo·HUØbÈ-EW¼ï2ùL œ•esJ€ÿí»?ižé¿1?=mƒúYH=½Åfç›0zöÖö<ø²VL3r…Í2óñ@J3½ì(Fúuý[¡è)ÁóîàÁ™Ë„­Mæþè÷G“V¿¦S6¤ÞM¥w©5q6µ$jGJH[TDÛáÁƒ¤|—iS’ŽDOr?ù€ÑÄ’¶´Ð]±y_åÝ²¹ú”-‰7îÝ8®4T)`,EÉhî?ÑËÇ´P\%¨°RÉA*žè¬½EOë“‘€þ²"®´\©æD„•Ob’¨¦J~WÏönËÐSÆIè/•Š¥=< ¢Æ}O=ÄU†4$•-å”|r¼õl(@r™À[ê´r2ïdÙ‹ÐÔö ŽHnæ‡æ·muhÞšê$Œ»ÜЊ†” Õñ¸5kS ¹³µä§ÈO„ž¼$«{y6E ºKØÛ¡Û N “ipi®=•sÊñkLÚŸ Rœ—âdIÚ½Ò£FÃÕüŒG«ÿ÷[ŒÖõ;)±èƒ|Ÿùe_9×*“šQº¸5½ÝÞ¢bÉ[iOjnMÊS´áGR£Œ÷ é Ojæ¬áý7ãD¢û.™Ô\_ÓÎ4l\g~û³ ëÀdRpiäúc=Gñ!?¿&FNçÙôB^õMÌ`BW/ú©Ô+ý㉻cR4˜æ­ÁÖÍÉÄ‹+æÌ˜µìq¥½E럼ÒQžxqù¼ysÄŠ½EÑŸ·ÒZžxqeÙœŠiÑáÿb=Ä_=”óDyœ¬÷ü¾‡Ôé{h‹Ñ7?6·õh¯”nÑ“=jÀÓ÷\vVê%SJîßñ§-¥R|dù½ÓæM«>:ÙœtçÜK(œ—Pãd·ëÜvð'O^¼…htâ—ôzå¼îÜžÛÏ\Ýs›õíÖIh¢ÎEq{.êÛ2z• Â.¯ö ¾—+¯úªËZ¸µfYäÛ~Êí+0Ã--“ç~º¤vŸ“¯AîVtÃïù¨Nå“ûϪ&ò©¦Ô×ùN ÜÜ$^?¨Ïب§¬»g 3q6ó²¬×{çvzµ^UgÇ:´¹3øÊí¬xßÄvØáÁ¤sŽî >ö™?GäEÅWšêÉûÕ_ù«Þ?e.ÚQžoÇa131ywõ«¢DUwAæbk>ÇwEÅ]µ9U§ßyJÉçœ7ý/ z ]"±k륈±»®«­øVÁ{€°G¡¹ÕZÍÓøª‚¿R•Ÿ?e ÚOÇ\ÀÙUÑð‰]9QQ×MÙ#Xiíøt˜jÏu诫íéìÁ||s£øÝ=X¶ 6öÄk}*â¤×£!=r MÞÛ"N,zs2cõœxâèÍig´+'N?zsÚýX͉2; ]þÉÐùïöNf/?ölŽ¢;ºÚÒ¯Ž¥áŒÒ¼|©¼ÙŒ(“ ßRtFÛÞ¨ƒEЧçÚ˜F9/Qò2€÷¬ä½qeÉ{ÚÊ*S-ÆiLÁ½Ã¹ ^.¬¯±¾O‰Ë½â8 ­ä‚|Ú(WAΗ´ Ò—>ráEq•…xßà)sE„˯²¹ U‚ÑñîpÛUp.S•Zó&sñùqmE„«¤ œx­KWŠFï§ÈvX3éÞfÎvx‹c)ï$ªïB:žHÇÕׯˆ–”³Ã¢uj2ß4}<èTGßÜ[ïÛŠÊœ¬kidßCé2¯n­3ºº] ô g tTþă€H˜ö™±@ì3‘çs¤“1/ Þy¹¿Êë‹g ïLfYRÌè)f"ΟR¸ôÊŽF²Joñ±2,w`õƒ «¼nË\Tê·Sß÷vw3¦Cì:í¿a£goíCínŸŽ$¾[»ãóð­H¼v¶Np\QpŽ£môGÇ•àØŽSÅØLQÅS0àqäjj(†£Þ«0añ1y$÷_ ›Š¬üÌB<6È4D‹ŒTÃÛÿû÷㣞?˜ÕzÎøôOŽzSC-õÒ·]G=Á؇Žzþm÷Q/ía_G=;WÆ,¥5™SZ#b´;¶`î«>‚Ì¥5: }èÜž¯ÙÑl“Ž}Ûƒq󹟊–•pÔòñën0CÎûG{Ozg´FG°ôíçìíhÞ^]TBOÒ·`o÷ãíÊ誶Rúö÷íí(ÞÝZ‚pfúö÷ìíHÞŽÍVÂÜ¥o?koGD{OìÉQ‘+}û»öv8o¿5³„•¾ý{;Œ·ÎZVÂ!-}ûÛöv(æšuìl‡IŽŸ2Û<ÄÇ_ùíh„î;÷‹Fòê™ïŒÆžY•œ¹_4™xÛ™ŸŠJù^Äÿ%ü_ú†ž¨òÌ£¢ª3WE‹ˆŸó†OE‹ù^cGÕ8îÔ‘ðýÌcõ0ȦÀ\Êð´¦yUY4âÌ9c¨Õƒš{ÏÎb,6„üñw‹ì‡›eáÝ*{‡µ¡ áÝV{‡ ¢áÝ ö»D7…w·Ù;ŒÝÞÝmï°`ô¹ðî+ö³Fß̼‹‡Ù;L¤8sÝì¸Ø}ÇTŠ7&±”™åÍOÓ~ÇNÒ{ýLn&ów C½›Mkø»ž Ù6lÐÝÈßV¦ã½9ú k83ß-ÊÚK³F`~G¥J·N^gº˜1>ébÆt²‹±£]ÌXŸó1c@ÕÅ8‚ù˜± áb¦¾Æ1‡ŒË<Ì2-±VšVX £M«,F},†I§Ë-†…§k,†Á§ƒ£v£Å0u³Å°u›–1U=,; áËÖ¤é³ÝM‘yk0üƒE)ðÞ7d•w6´E¬2".˜áß5pÈOø²F3—жsNœÀ‰lÁ©Y×8Cça/G‡Ÿ|2î 9_»OÖ2ŽÔbŒŸnñgþ&ëô’“Ùõ¹Yn½]r­±8¹ÖkI® !×"‹“k¹&ôçj¹Æ[œ\ãÉÕ°!WtkÈU´8¹Šà®/÷çº+“+ºÅâÊÝB®»úsÝrÝiqrÝI®›ûsí¹n²8¹n"׎þ\ù|EÌ—‰“Kó%¬˜ç7†ø•ëÍœxŽ'‰õ$ªȬ~pYKû0P›ÅXH“-Æ.òÎ1þ53ƒ'R܃E° l ï<¾¯ÜÞÝðÍg»{3x(öÄ ½‹÷Îà§xdx·$ƒ·âEáÝ– >‹Oïveð\|Ix÷©ó¸ c;÷Ú.Ç*YI$™®;·ÛåÎd°Ùß-ÃB‹pVÃË+¸…µTQ71as7¥¶väòĨ¢±ã£‹‹G?oÔ¨ç•uÄÄQÅGI,oíhË·%QÞÙ’8(ºÔjÂΙ¨%X2lxùôd}MGc»¯ógbC[ /Ÿªën[C[¢9Õž¨M5µ`cMbECû²„´\ÚÚ(C’Ë•´± ­†—Wò°mÂèe‰ùNÿ¾ û[Z!_»\QëÛÓjxy¦›Q»aú) `ÊRÃË…M>\Ösk±HÈe;W6n%ÛÁ#àƒãs\rÝ ÜdùhÞ98Oº){-ì¡díy9kKNÏ:«¤6û,ñ Øì„±œsýùÑÎgÇÿï·×òÿšhgÈ7wL¾)޵Ùg¸½\Ê>]{wç˳רæëjsâw…œÓמ–³¦äê+õ¯Š åØŠ\µ›GœVí ÜíÚ/€$Òj»W=lyªÆù¶Ö.¤—×Cþ)MSÝ»)i[”,a6Ú±ˆ”b†¾*ÞÿÄ»üf6ŽÉý¾rmëŠf™ñÿ–ô›+²+íÍÿfr\ÇÌÿÒ7Õ×¶±¾­¬®7íƒoæ ö&ÚÜ›}=öý µ­ØøÆÞ!§†ZWm®µu`o² ¬\mc¿‹÷Ê.ÓO¾UFûØÜÚ»t;ßcà¡ìÐmVÿøt>ûvo“Ío‡/<%Ь¦ö¼±pqî”®hFKÕ^ä¢ìÉ3u{ ÓîÍ›÷r~M… F÷¾iÏYUíõ•+ˆ7Lâ«eæÂdþ”ÍuÎJ÷ªt_÷f²sÌåøëÙ?çk#¹ïhN'ëî“ÏÞš¬Ь­†Z–0 _s7ÙÑYkø-ÿw¦kÌï ÏUï Æfhéú(ái>Ž?2Åtg0xÓÅ0?èq=ø6ÜÆ[ ,íñ>÷‡©ö+…·X C†wZLcùû*ƱvY óXïµ²î¶&²¾l1ÉJüÍÓþ,CY‰¿ˆIžÌ´˜î“I•ÅÄIÚ-†!ßmÃd–ïF³n ±»,†ñ,ß™Ï*ø(GÁߥ‰M±y!æï0ÄÖXLìþ‚¿{ðî†ós#BpÁ÷Cæ¶ —‡þάÛBá{'ã[…[í(hgA­˜kïd‚«è{&ŽFÑß™Åå(ú9V}Åг¢¿“»6ÄòY)úy%ö•P“ïb¥39J%!vNˆm²>‰wRZc1ñSJk-¦GÉÏ«8-%“g¦´>¾*bÇ-¨<\÷Ü- Ž7“ ƒm˜ú}lï½6%Š §Íeól;%C[Ó»—›íêmXT9'ˆ ½;ïÑÈÍïÚ6¿›¿ù]ûæwó6¿;ÇðöˆÍï—m~·bÓ;0f=ÖI¦çöYÅ%†¡¤T#Óö:mÅä;6åx€GüžçÝü[b—‡ØÎó÷Mbž³Aì³!æ÷•bñðs»=7ÎñLbš—ÚÎ1‚µŸ¡c›Ý9ìŒEpÂò” ÌÅ•’½éÍI4¤ÒWi«oM5%Ì?JÛÁÅ%#0:¸ÃçÕ'¿ŒÐÙüJoSK& %ª +ýqmÝþûïïó©[Q»‡µÍœ;|mê¾ÙvX· G<,õ`ÆÓ†(Á2v…8aýÓœ$ CØ9Ì!7mõ©Žf ÏÅ­‰â΃‹Çv>ïຢĂæ¦Èk”ÍŽaMàéCŽñ;©]0‹@üƒþI;¥§xnUuo¬êééÅÕ¶mĈé×cΛªØÂŠÀØ¢ÿîNef¨ÍfˆqéÄÖ`¿!zêg‘ŽÓ˜!f–sV׊‹ús7¯åÆ©XüÐÜø;G`Õ]îøf¾—ÙìrÇ03ã¸æÝ›]ìévήўt³ËìøÙÅ6ï4æNHeò©}³+ÕUí–T¢Û8æ·­o~uû²u`<;Óº ü°ŽÉPe;Â÷»¿Ç6jU‹ÝµL”£ÒÎëh#ì»09‹–x“Ou\½s{~˜æêéZƒÕzsÙÏí… é;ˆ˜™í\¸»÷ÃÎÉ98“\3|âªuž¾O¼„ÆäîÈ{6¶ë“I7朵ê3?-älø*·î¬~ñnÚ¹ÔnÉtÔÑâ° ÂdvÏd¼õ¶ºk¬aù/Ge†í¡mÓ½kØþfîxÌ·»Ña 7½‡@¸Þr0·îVlrˆãiö†…;ïmš!·4³é>B²ill˜wÊMí©T¢©¦ye"½PÄÝˆÛ oÊêrbÁûÀØRï”›,œçEB5ç¶éH{ì¢ØwÀ©2XsÂ4Dƒý½CÐ3bã½SnÊì,Böðc‚n‡&jÚÕÿø E°ò]Xý¦gO¤~Ÿ—â]׿h[¬EånÅpK00[Æx甛ܞ×s‹í©]Ž;!6mǹè«À-]ñíÜ)“¢y§ÀÅÜžuVwNöÚÀÕ-Á¸­Ñ5¥e› ÇÔqA¿¢|&×訔}·Œ|­|‹{ÞqëëˆÏ{y×d¯u8¹˜½vï½£»ê² Ïœ–uÖ™f}fmÖ9]§üªðŒœ,íÃÖÒnö’«¡¶tg]£/vž,é[Éû¡E%ûeÕµoô½×óN¢qíŸãÝçïÁW¯‡»½·Ž½·Êí=ÍJuïÕi2Ìû?®ïÂ>ôwmö‘ãE˜æoìÇÇ2{òZ{ÇNñœk¬7ÆÞ±#îɼ‹ý­ÓÔ»q‡ö½ãÜ ’å÷ ÏfÆ&gVnßWænT_Xn÷`6V¢knl3Áÿ¼{’’Ó²Ù=…ÇwOârýçÝ“t×Á6»§vOÂîIØ=É9“±d¿u±öOâ÷Ï9쟮³Ù?ó¾­“°ƒ¦ú$Œ¯·ÿgͦüÿ¬ö °ƒØžWÆúlØA9çMº)vÉÀëî´3ì ÄÜü¸èÔØvôœ_?eàø{ê¹ ?§°rpÛ¡þv#ƒ°Üš*ðç|èÑN1îá3ÌEÝä˜ï2WÂiÏ÷„ÃÐmþƺíSÙgôÏîhúxo×*vÇ[À-ÛÁ-Í:gG?!ÄyC453×þ@ûÏ#›m8¡ž+~öÚ̼Óß1sæ9 Ìð2›Uy;o;_ɈzšÙò³Šr6·Ùg=jÿ0«µãwï°Þ´K§Í+jÅ©l@›å¨ýŸœ×¤{ZÏkaû¼j×og×4û¿Ïë¢{çõ'û8`Â'g–y«Ï,\‡„XÍ|ù݈P©´t`hów[up4c+^zûá…kr³Îâ ÞÜU›]8ù3ÌÉùYgO‚»ÑÎ5nÏU¯È:+ÍC+ØÞ±ãR»qާ§=®J`wˆûþ€·s#œÄõÍ-÷š6oà$:]Lëmç [þžç…Pç¬Ü82̇Ÿ”¯Åãmd|õ!ñ_]8™‹¹ ŽÎ8ë¼Ü)&—ÀºNqèhÜ~ßÄœ­: p 8ÓÌÙVæŒÝvAöÙâÑ33W½2;=cÿº§nŽö.Ju´ß787ÆÌ‹ã›yYfj›ÍŽnI»gç³aÏ0/þ€•&¾t¿ðŒ‘gæ±dø íÝYŸ4.DÊÅïáí6kOäï C¯ƒ{(ã›Qx—@¹ó±‡‘ñrn©¿SšX»Í2}3°+ˆGÓw?â³›ÐÑ1;fàkCÌÀÁš|:è¨ùÐüxTþÃ3@ß=FÄ^þÀØð¢c¨xcrô‰Þ¢¿“Êüsô´Ø¦ð¢cú¼(xËY±~!¦ÛŽl3/RÌü¬&¡ÉïëEŠQ\Ùp6õæ†Mj‘Á ã”=笖¼óÆå’ "S·lï®›Z}ŒšŠ–S&¥£ÂØ"r­¾Žü¦¶îš%`lj–¦æîš™'£N‰/—@ņ;÷Xö•¨¹§ÔêôÞ0*/.!+9Âbr#®—ÉߎöƒÉÁz‘©VœziÞÉl5|:3Ø›feôÙÌã¦Ú?þi¿á^1/ºþ·yAv™y‘]çÝóBý>F~^ÐÛâÎ$}ïÍKw?¨»o€ÙA[ÏÏ´'[ Ú,†Döx‹aGÛÏ–´™/Ùt6óuÙÒ?_—Ù| «Í|IOá¿Íðƒù’ éÝóEý>F~¾Ð-ƒ¯#»Òÿy¾:j¤þ¾æ ÝB?gØëži1ìuOµkÉÏvºýüa¤ÃϺ¹~þtÁ6Ü} ’›ù“ÇåM-+ýñm†ÐXdÅÉøo3 “”Q†Ý3H|Œ:ý ¢‡¾™ ~§ùõ °/toUß âˆÏ¾¬ðŽá6óXÏ?Šž«¶Žƒ¤jEmÄŸ…±ÊìOI¬Lu$š:ÚÚ{~_½†Œ ‘Å™I·3NMº%}|aáÖqZ"щ³/¶·Xùgþ•¯uœ™å¯ù¦¹xÅ’c¯½u\/§|m¯·àyüÛ‚.=Ü¡Gù÷ó£}´¡ëîëô®ÙbbŤz̉çHÓC§ÿfxwãíîŽyšÎ»»ñWàøô×÷Zl q4qo½Aýë6+Ò€þàc¾vý̉Ç=…¹Ò}¤ù§‹µÑ¥»$í½øÔæ†¯[Jó)M)lÌ˱²1ˆÕ¦¬'â‚ ÒÄͰù”?Îßãz0ã‹zKvÌáÝq ½\zùØ ÒÏú Jàa}zìgFŒ 3ºu5ß±cþ›kkšk ñ'íLˆiev’ºÞ|Ç3q³•Ü=g4<9ô²>R¯xx'Ñ_?ê ™ÝûÏ“¥ùt„nÜ< QÏŽP]ýç 9°#BÉÝó “ÿ²#èg}&¤¿õðŽ Ç~&¤åe¸(ª¼ÿå-5Ð W.YÙŽÉ~7Ä`t§êùóp îÛÓr÷ŽÃOæ^Öç¿ûæûyžÁÿºcØ7nØ;ç®4‡TÒð°s!=\Q4¡û9`ß!æb‚ÍEµìîùÈxcOÎ}­Ï†´wÏ7F?ôÙÏ«†1º÷XOçòÓ‘îQé’SG?4¿¬b`>&Öê(½{BÎ{r>èm}>¤Íþð|ÐgçA#Fã]ÆlïïŸ1ðð™0=ÝÜàMïâp <ܼ7'Ys‘õó‚§æEÚŠï›—0+BwÌ Ú??ž—Ž’WV.ÞtN9ẍŸfÄù0ýõóBOGÎ 7 }ób½3عÀÿw­'9 *Ò§róÀML8®|¤' 10cMó¸w2ÌñäÐÃúpS݇K鯟îáø†PW^b–ÎüÀY`t§xÉs0Îk¬ö Bv3zrèa}à°ì›úëç¾Ð`æ@øs†œoËfÏfn—¾ûÑõ?ÿãL|÷Žv¸»IUKpFV;k3?žz\Ÿø€sÂMÕÏ =÷s׌*YK£šu~C«œ z¡?'òBýà÷µ4A0'SÜœt”ÞG¶ ¿õQ—vψ »¡ß~F¤òbfDl¹FR‹.JÖ5ˆ‰tn{Gú¾v‰8Ã-× Y°K:Jß·qÿy—ÐãúœÀ…Ý·K蹟¸ŸÌ‰¸“ƒŽè™¸‹únF[t3MÖÇÀœLsîß4'ÿ‚Mèq}Nàî›zîçØD·ãAŸXÞкAù3Ã&ÆwŠÊ’¦Í O I°Ov—þÈ”üó>¡Çõ9/µoN蹟ø6C˜q„ášU3ø÷›x&*£®öà#†ÀµÓãéByhHÒ;ô“3Bë3‚˜}Ø„~û;þbð*$NõÐõ#ýìàÙ„],ÞõÐõ^ÜEviÛ§ÑÆIü|ØÙÁ³ˆxPÍð熮‚`ÇÌNëÊä¥{;–)“S“#)™3jQ‘qŸ©ÞÞÞ9¢ï~Žèu}ŽÐîœ#8_~Žr¿&±|§ÀsÔhØ»BÓ¦÷“íeyB13#˰w A03szg&-¿wh6ÇCç×LúîÌÐïúÌt{\©Î ½÷3ƒ/fFÚÃ_“QTÛüÌ Þåh›4ÄÛlf"†¿f‚™94h8få×gæ'{…þÖg¯-ût•鵟¼NàßJz Ãï€_9-7xic$•áwA0£Ü½`…sÀU›‚Çî'aè_}ð·Ð9vGÚ ·~ðTMú#*ÎáQÙÍ.”·?Ä»C `·1î RëkàqœfÀzÔèšèa}>Ô‡çƒÞú90s žêÈ•iï±ö”÷3¢Œ\9äÀÆ¢·uîNU÷anzíg“›Ì‡4¥†´ ö̇ü®˜ùÐ4 i‚`>&:üùÄ|¤»õÉù ·õù@Cqß|Ðk¿[±ŽÈn_~ÔD–üÜ Ÿ Sú_£æ myIÍŠj !ë½ùzë8Ÿ£æ 1€=ææ•–ëöo¦þä.«cúêç„^Öw0ú¬ûø›ôØÏVá‰KmÔ­²°Ã­<ßx©ÿhò£n‚à~³‘/¹>á‘0 ô±> Ø•Üǧ¢¿~0; .•Ã~“ÕsÏf{”Ì‚vÊ~“‡Ø mnL¹{6Cª;úÝY õYÀðå¾Y ¿~°‹ CzûéDp½¹¹¦¥mY ³×~&0š©<JÇ~g10–/U-»k6–qK_Æ•øŸ÷&½­Ï6:÷á zíæÃ˜eA³Iú~£Ë°4pÁRÎ Îú¯› ãå“}!ÍÑeC ÌÆE}%wÏÅc7¯|L/»ç!ÑÇö…鯟 ‹¡Ž~³@¡³,³žk[e@ØÍ„ê‚ß:þãè710í({¬øñ.5}­Ï†ñù o×ôÙaÑDžgÀ¢Ò"Ý¿ AE?3(„×Nëþeiqb%ð4œÍѹ—ØÜ ×)-ÍÜc÷ÿ·]ò]v\F9”ï¯D©¤D–»L¬]Èh•¯~ˆ›aæÀϽ¯Ï±Î¹RßÓ¹²¾nìL d#Í”ì©1»U3el$&Á«˜nïj¨å|ÙzpÒH=ÒÁÓ³½žg·>ZÆk©GØyìäÁZŠÜ6áe]BÔ3Ç×ËÙ:»kwM—Y=F[ZõHzìÅ÷Ö3Å׳±>eÿ\Àõ¸ÊcGik¯ç±¯oh°ºð?CŸt‡lzʽusÀ©»}¦çæ·\=ø¦¡ñú›Ú7×ãøÂ(UÛ^5°îêayPø[Mo{°žÍÈ=TÑ;JvÅ—èç¬6<Öèö1=¬›Ë¶Îüt‡E­yvlº‹Çlmnhêh”áR‹7ί¡«gŒãåú:«¯8ªc ›ù='ÞÛ»CŠÒ–¶÷Ueî³A¯ÉÖ‡!]é]DG iö½õJ{ƒê˜af‹Cð¡Ã HzÐCÇyàTâjÄ{pß@x‹CÿM‡é Ûa8¼KÑèG:L¦ÝwÃDpöáXúë1Òâðx´g[_¥±Éô¨y¨at‡m}Õs0Öa×^-ªÀK}rèa}ðr³o¬‰å®‰Gq/[Ø•—}±·ïNó:óý¦Ëáã~vF¸]Z·£tá…‚´R;{f¬¡»žÑ›î½X®ªöb‹4µ¦Þ»3#Õ0ÁÍ{Acw“¯}Ÿ§± 8Ô‘Ö÷<ç+o ÇüธÑÓ>'ï1Ÿ“Á;“bß÷gu9ºúÎãd'º¾É/f"?€e3FÆOfM¿}3Áø™@÷öæ!(fb??]•Ü#(š#?™ 0Tç\Üæ‚YðsÍ­ï‹ýY%…å¾m2œÁ÷í æÀÏ|¥>/f"°IÓ™@‹ç'3gßLä¼­‚²ß2ÅLŒµ™x\ Êhÿd6HÝ9·„Ù0ÝlðBú†-p›Ó†ôûšÀå5á¹ÜCñOf>Á¾}a¾ÜL mÝçÅ­¢&TšûMþÉL Û½o&˜?\…Äh‹4þà‘™˜:dÁlèǵ[SÖ{ïO™Þ{Îô~‰õ.ÒnnDÞ{«þLyÙ(HãûœÞ}ø"ôÐømÑUúû7Ê™Ñ3é¡ 4éd–ºÐèð§å}I¢Yçî’¦Ä{x3Fô‡·‚´ÃG[_)ñ¡ŸéeTÞèxôÅùñžp%o”ßxÓ7Þ½õæ"矻?ÔÏÆ¦âKÇ”7:_·Ô÷SüG½¹x'í´Ê{Œó»Û¢1Î_`ZŒÙ~r¢cÞ›“{=§þïÍi}ÞíÎi5šÈéf½+'úÒ=9ÞpWNô©{{coÂ]9Ñ·î­-ãzNô±{ë´7ø®œh“÷Öiµ{»r¢mÞ›ÓêÛvåD½7§ÕíʉfLoN«‘Ú•möÞœV;´+'Úî½9­žfWNtô{sZMÉ®œèð÷æ´ú‹]9ÚkN«°+çCûÓéöuå$Ö›ÓêØuå|h·;M·®œ¤ëÍiõͺr‚ezsZ­¯®œà¢ÞœVûª+'Ø·7§ÕyêÊ îÍiuŽºrrwèÍiuºr‚ÔzsZœ®œ¼îÍiueºr‚{sZ –®œÜ{sZ]’®œÜt{sZ ®œÜy{sZÝ‹®œðzsZ½‡®œð5zsZ „®œx éÍiõºrB}ïÍiyó]9ÑèÍiùå]99#ô洜뮜x@éÅ’–—Ü•)½9-_·+'Þ]zsZ.jWNn½9i„îœx‡éÍiÞwçÄ{LoNnõœx½éÍi ºwçÄ7BoN¸£õœøNè½]ÿòÝ9ñ­Ð['<ÇzN|/ôæ$Y='¾zsãø9¹Q=„¢®œapç;©+'ž3zw¡õëÔ•o½9­?ª®œÆ÷FONë?«+ç¾;„õÖ•ó¡{‡ó‘֕󡻊ó?וsßýÆú ìʹïNd=1våÜw²(»râc£7g«¿½3`}ïΉ¿ã½uZœ]9Á~½9ëwIr¢Ð›³Ž‰È‰Ž\oNë1´+'7€ÞœÖ×i×ÜAWN㓤'§åetå4>ZzrZ~KWNãw¦'§å uå4þszrZÞUWNãû§'§å¯uå4þŒzrZ.`WNã©'§åTvå4^¥zr:ßC»÷€ñ•Ò³ºîŸs´oÀÌÅÞœÖs‰y•§”Ãì—Ž@zóNrrþuwæÏW½žƒw>õ¼ó9 VÔsðÎç TÏac&‡ÑÄéÎaÞùè ÕsðÎç@‡©žƒw>®žÃy[49ЫçàÏŽZ=ï|¸äõ¼ó9Ðò«çàÏîa=ï|´#ë9xçs ³YÏÁ;Ÿ=ÒzÞùè¶ÖsðÎç€GTÏÁ;Ÿ]ázÞù`zë!ÕæsÔsðÎç`÷×sðÎç@£½žƒw>üözëGÖæ€Ã[ÏÁ;ŸŽb=ï|ü*ÔsðÎçÀÛC=ï|üRÔsðÎçÀsF=ï|<{ÔsðÎçÀçH=ï|ü¡ÔsðÎçÀSK=ï|¼bÔsðÎçÀM=ï|t-ê9xçs qQÏÁ;‡ÏŒ&F=ï|¼óÕsðÎ׊wÃzÞùxr¬çàÏmÊzÞùø°¬çàÏÐzÞùø¿¬çàÏwÌzÞùøv­çàÏÿ×zÞùx‡­çàÏgÝzÞùøÝ­çàŸi| ×sðÎçÀçp=ï|üôÕsXïݶpâê9,WÎæ€ÏVÏá´fL|a×sðÎçà]ÏaïÔ6‡Œz{ÿ¶9¸Ó×sØû½ÍÑso0ï|£eÖƒw>ê9øp9ðŸ_ÏaÞ¹Y4÷Ìî[‹yçsÀC©×aù)67ÎzNÓäèÁÜæ¯ÃhŠv×Á;_ºéõ:xçëè¹m˜w>GÏÀ¼ó9¸©ÖûÁ;Ÿƒj=‡Óí69àtÕkuï&GϽÁ¼ó9zn æï“zË=±uôà{ç7Úæ@Ï¥žƒw>\Âzç Ää蹘w>Úõ¼ó9à:Ös8¿&&GϽÁ¼ó9ШçàϳžÃyd19à“×sðN³8æöiM7ðF¬œåÇÏ–½d¸½Ì¬ÁWÕŸõ(åᘤW¢»8P-}VµÔ3+¿q>Jð]ª±>cƒp˜26ˆ¤Œ /ˆ36¬êÏh8&#N{„r…P„–ÅFQ½QP×…&™õÔµ¢I—W]óšÅŠ“Âi3s*iFÕ=†5ÔÌ–Ç}\.«0à<ga¸ZÂìHg¸ Dõ×eZ›x × ^¹N%°ÎÂVIèC Ìå‰PlÛ­…Ú˜ù-Ô–PW‹ò©®A ¢„ 1ˆk@B]ƒ`+'Ô5ÖeºÃÔ.ÀÊÌå½€RÕ`.­Tdž0%œ y†bÈêÓŠkæ}o…ÉWà²ÔÊÕ£‹u(L«ÌÇ¡0å Ô7ŒKY‘‹õp.ðEfdÄa|ëJ0%„"uàúW¤®‘°ÊŠLúH^‹ôi$Û HŸF¦-r‰IÝ%ØC£`2—èó(Ô©KôxoK0ŽöÃp‰ëÕ~(ã—èáècâ‰}L¤E“M4Ì“oýS…ëÁMÙ€H {õ-ªw˜6ëÊC“µ‰Ç­)'¯fš qâ0¨_ãÄ3¯tÜWâºÆýLŠ‘®{k\ ŠÆâú%Yz'a,æ­Òàk~Эˆ®H‡˜†ñz®½1^›U¯j5ãuYÔ¼Ž×5\Sq\€k$½=¨+îÂA]N;¡· ÒÁb‹º.h;W{â:°.gzw°˜‚Ú91®íàÿÒáCÔ9½;Ds«Í;aB\Í„ [«qû¢^ͱWôn‚ùêä„OY5vÝ«Vã2r¯WÆC¥q¯nNÔ|h/LRÏ&Êǧæb¢&IÓ6ñËqEå#ÁMÄ$çK_ßl?mÊIòÝ%ô0IÞª´&É›¦u²îwªc²n†B“åñ_µL>Ùõ#Û9Òñ‹…xÒîÆìõ¨ÞE+¾êÉbä3MÓHU¦]¡j“ÓKí‹ÃĆ:LÌbí†ÃÄ¸ÐæœBu`©)bÍ M‘âª6ç”Äݘò­þn0yY7´·ónÈ#­íÆáÚ×êÆáҗІ2Véµ§Šëª9šJ'˜£©Â¶šiš§iât ™LÓ{aÚéòªnÌ £Ü?fp{g'Í£Ãk›ñë¸K3+ÜÔ×öt6ß\ç^ÇÛ?÷8$Æ;Ôžy‡Ð ‹CÒ~Δ>¿ú9K÷0õs–î×êç,ͽú9K|zõóñ ÕÏ#ÄûS?·Jýµ§CÕéÏûÀ†ËúBÈ*—'k[ëQºƒ(ÓÑÚ‹ªõhÝrTëÑâ~¨Ö£oˆk=æ´¡j¯oÕ9"Ìçi¥h·.X׸àŒ~„Ê6cvš\” f†#¨‘:ìì 4Ã$•]_Ì Ÿß±ºêª7ÇŠ!<~¬TF„‘¾*®xá«îÁÄyÅÔ˜a,My^gÅ®Ç Å?Ñ.Z¨9R¯ «hÃ/oU=_41®|ÑL—TmñMŠVIåA,’J†*X$dB`U°8+®`ñ.[*hÕ¾P§ZßJ}?'ÎØ*®´Ë1ôàøÍPy~w¿fádåmÖ>UÞæŸÅ9šÝÕþúk×+GyÅUŽþsâýÿA—þ.9àÙã½–ÃÜÁ\ô”c€&T9ìçà8§ö7@þ‰ÉR$ÇfËaø•.0äà&JŽ?°†‹k… •c ´ï”càò8ÇÀ˜uhs€ ÈA=ä¸År0}>8‚ wr|ÕrÐK7W-â†(G‹fP9ZNˆs´ˆ[ïs Dîä¸ÃrÀÛr9ïq8Ê1è¹qŽAòîsp'$>éÈñ.ËÁr9 UX9 #+ÇàCãƒ÷Äå€ÓLò’ã–làê¦þ)Ç0͉r {Cœc˜¼ºÃÙNä®»r Yœc¸¸ó>|1rÀó#Ç_[¸Š.Ç¡ å!ÏíÊ1Âî #ÏÞåÃ’Ž9Þ`9 ŸÈå0^´ôÍÝî:B~9Üo¤0­rŒ”®ˆrŒìˆsŒŒ³lÐ9¨‡wZî ®g#¥qBø äøÇ8Ç(!E—cˆp‰r ‘Þ…r ©s Ñ~ó9Œï4}»ž ¹Ér^¤ýÒÞPŽQ–cÔ-V+š)®Žýœ¦–¾ÁaʱŸü·*Ç~il¤\`r @ŽŸ²péÝo´ˆr`÷›£åAR9F;¾•Ëa4YõÍÞ'Çu–])ŸƒÝF.äøËgÄõlŒt”cŒîLÊ1æÃqŽ1ê·Ïñ7ö†›¡{3Öz;6ôv¬ÍÖXçÕ½¹×Þ>‡ý5Yî&Çro^coØÓþ͇ìMÞ‹›mWÜ,¤æ~ïyyüæ=ÂZ>·»W69Mg‡¿¸ ª×Cu«RíC; ¯Ç—Àqø"Çýžá8¸/®—9ÿ3úþãøíew¥ïö 7\Ïš*¬ \\öæE†ðž’Îú™ ˜½IþÈZJgø#ŸÁ¾DñÍ)¿ñ‚›oí…a0W_àwÂïEû‚i6Œ*ý?ß½Ôr°) ])}Á®­å€Í\{–E­2ØElÇ,þE|9Ù× 0ÉæHxÁþ—]ö²÷Û×ú?&ÊÞg/‹EÌ{¤ÅÚ –·Ø8„Ôp”p¿«/.ð.\Åã©eËsP”½÷ÞƒigX]úÏõ€˜¦PÑ5áîAwôJ/þÜÅžéªrƒZIó.»/i±»>RÑÖt!¸ÿQ3^ ×m¢Õ ‡R÷v%x›ÜCÞ1Ü×x‡ þ÷yǽîĨ“{1j€ÛHŒ÷3\Ñ3ÔcŸÏ²~ê°Ú)GZL7+EþÚÍ…:¯¯/»Øßº/)BY–½yÇt°ûÅ8Ifº-ÅõÁoHf•¹g:F¸šlp‹* }“pÉQ}t ’ÊŠøIܯºÚïuõr;a®F»º˜*åI¡9µð§al!¦·\F¸*¾äÞûYç…˜í”ï^P#ŽŠrKGºžâ Ö_lPŒa"™NÜÍûé¤?pütë*¶Ó¹ÐÕZTL‘?uµÿ‰«Ì׆ë¨gë(M©^‚ÉùE—“Û=ÌóSü÷ö î-œ7îIm®§ðU¨Ðæù¼Ëó‡Î"wÚ5ôœ‰@‹ÓDVôèé.¸ª¸¡v4ÞM9 Ï\{y$Á ›¼Ô„¯m/L!zbüç–ÃN5p#'/Žû-1˜PhKQÜN´©ˆ1÷øº&Æäsí'æS&ÆŽæàw+\Þ±[Á°ôœm¾ÞbìsUä ~´9ˆ1áàp‹N¢HØž·iôÁ©Oó¥*`<’ —ã¿ë&<Éd§›‚0ÏË-Õq¥ Û¨dÙ]×ºŠŒo¯?QlQ]ƒÄâ¡¿§YüÐ9¡ îHÜãè ¼6n{ÔÃLÌÁâCîpÜëxÇ}€Û&102˜™7WnOĸí£ËG ηfbt½VbÜl¸#cÃÃX#F@;*žb÷‚õ‰±#¸¿kq=çâ¨+¨˜ß[ñT›»?çfæ\NàÕ7ßg\žßry`&ÆÝy~Óåù —ÆóYÏs·Ëóë.Œ'T£êy>íòüšË_ŸîÎó)—ç“.—c®ˆõ<Ÿpy~ÕåÃU¨žç.—çã.Ê2Æ‘owž¹<¿âò¸Ë©663gnæà€Ø½N6”(Á<8ˆ¸Ã½à–Ǿeg%®–_¶ZÎv›íµ–•ú¬ÔBÜɽÈåäši7V}æáÙ™¿ÓÕüQ÷õ!»­døív«¼ÙUÎåÙwÑ0,\—`¯µ@S™½‹ë0é nÆSúZë"<— ã’È¥1{Á±V=ضö‚eíÌZÜ7¹ëe/ÀË5ŽwÒZ\Q³ à n¬µ`ð{„ûlm:¹ÞÖP!·ÝZõàzc§<}†míÏZV\­zÐ^ KÂ%¬½€ùX«CÖ:æžûCm£à+½Ö.àµ9ƒ©“mu^p¨M•¼KuTÏ ¾¶Q¸ÕתçN’M·uáõäx¯ÒïL¤¼! ›€²ÐhM@Á1|Ž<ŠC%&àô©8#hY%( {•ÀA#+À¦M¨%†Ë—P úZ µÄ0)jA“+¡tjjAç!¡ô¼jAó6¡–XýQ-èæ&Ô‚&ª1Ñ„Zà'ÔÓÙ„ZÐäM¨%fj‰™“„Z¸°$Ô3[ µÄL]B-xŸO¨%fRj‰™aØøzO¨%fîj‰Ù µ U,‰Ñ9N¨ä„ZÐWN¨mæ„ZÐuN¨%f%Ô³áj‰Ù}¨• P :Ó µ QP úÖ µÄlß„ZbörB-X‚H¨Íì„ZÐÛN¨­î„ZÐùN¨ð„ZÐO¨%g$ÔÂU)¡–l’P šå µ wžPK ÒI¨%¡¢ƒŽjAC=¡ô×jA»=¡–˜~B-1£„ZPtI¨=ø„ZÐ’O¨ú„ZPzI¨ýû„ZÐÎO¨%æ>ŸPKÌm>¡–<šP zü µ åŸP >jÁC@B-øH¨ï µà{ ¡< þ‚ß‚„Zb8¨ µpIK¨ÿ µàá ¡ü$ÔÂu-¡|'$æY!¡ü.$ÔÂÅ-¡|ï'Ô‚_ý„ZðÐP —·„ZðîP ¾jÁ3DB-1×â„ZÐÆã2‡Ž^B-hî%Ô‚ˆ„ZÐÅãB‡Wù„ZðîP ú} µ õ—P ^jÁO{B-è&Ô‚Ÿ†„Zð•žP ƒ µ ¬“P ÞÊjAŸ0¡|1$Ô‚Çð„ZÐ6L¨ï µà¯;¡tjÁßj:øÊN¨o± µ ­˜P ^jÁGuB-è2&Ô‚_…„ZðP šŽ µàI!¡|6'Ô‚dB-øNH¨_É µ ”P ÞjÁKqB-èP&Ô‚„„ZðŒÊ– µà!¡¼ò&Ô‚þeB-ø@H¨o¸ µ ™P ^jÁmB-xÑL¨ýÍ„ZðuP >_jA»3¡¼$Ô‚—Õ„ZÐýL¨ µ d”P š¡ µàÁ ¡<&Ô‚ÞhB-ø,H¨ŸŸ µ UšP ^ jÁ÷&êExL¨½Ó„ZðMP ¾/jA+5¡¼$Ô‚Ê„Zð ™P þjÁdB-è¯&Ô‚VkB-xH¨Œ µ À”P ~jÁûaB-xsK¨­Ø„Zð.P žjAg6¡ü $Ô‚ÿ?T—ШM¨ µà…/¡ômjÁg@B-xÀKT ‡jÁµèA¢Zt1IT ººÔ¢ëH¢ZP{¢áúDµõ&ªExØx²/¨] ªE¸½ ZtÉ1½ÂßÕ¢»TAµèSP-º …Gµà/¤@-èᨽàµàŸ£@-xÝ*P ZÃjÁ¿GZð~U <¨%áR\ –„ëtZø[jI¸á¨Å«‚0ºt Ô"ÌåP ˜½@-`öµ€ÙQ±³¨Ì^ 0{ZÀìj³¨Ì^ 0{ZÀìj³¨Ì^ 0{ZÀìj³¨Ì^ 0{ZÀìj³tKf/è– Ì^Ð-A˜u-0{A·aö‚n Âì݄٠º%³tKf/è– Ì^Ð-A˜½ [‚0{A·„…îŠA¶9ÜÁ4¡*Bq»@E¨u¨¥ï9Py)P ã*ŠØÌ*Šbv”^0gº«°ÆÅ×óÃy!ù-cH™O]ÙcãÌü¬ú‰© Ê¡CŽ_åH±„[† 16 ÖÛƒû 1¸5>å\«šNÃJ½?V)èþ¥VÐeL+èf¦Þ)SÆÅªÝu–1]¦@îOTÉ>áÊE'ØÜÀˆ±'N7Æ;¦Ýcþ¹¥q'cÖW¨ŠiF™ã®KªZ_Gº˜íÌ]ß-î€t‹ !ݲ·CºÅìsᚯkUµ[p†˜gºÅŒÎÑ-ßEºå;D·àùn¡P‚Š݂[è)ꋽ_+r”ë–Ítw1miÅf¸˜jTlº‹i»+6-°a¦º˜Ý ì=n¨ ºÆt_5jŸŠë*³±ó\e6ËÓ¨¼*¶ÆUfck]eü¨‹;,’¥'n»Ùà2K½Ìw[bÌSMŒ@ÉJ]¢ïé„küÝYh¦‡y86ûM³kj±;wqÛ²ÄÌé§'ÛNlOµ$f¤ë’­›jj—¤j—µM _S–E9ß*76ʹ¾tܸ(ç†Òq㣜KÇ”6×4%7a¼ùãP ûûÒñÅQÎ¥ãGE9¿,?ˆ²!µ´1¹<Ùxи’(÷°Ò1ÅG€Y¬9¼íD¹?Îål¯ÔtÏïh®moH5ó|K_¸üó–Öd}Cg”›jÇ`”÷ŽTsª¾>Ê;‹4ëSQÎ;R™l¥â¦š¥ØÂñÚ%.PAk8ÂÈ ßœ‰Î¡_”¿¿T/ÖÈ1®ö±\¤Ë::O6sɸ¸%Ùì‚QÁRq¤pó’ŽúzìÚ¼r /lh®Ci輆æšÖ•Õ´¥D=²Ê'ê²o¢‹©Å† ϨoM&«ãŠ¢œ/$St¶5ÙÚš"z{-> üÛâ !º2µ÷z2\åMïhÆôÛjŸ&ZÞ’jkÐ0Dù9¾¬‹-ëæ†“’ÜÐ\tS{+ Üä´÷÷<·±aisS²™ëÝÇeûo/›,É>ÿÅÌÛ›}¹+[ZSÌÝWãPKöŠ]wÚàm±õ›¥½Ñ³±B>Ó¼¯ÂÔSÞåî{e#ž£¼Ññ£ÂqA(~aj‡°4¥¦¶½’—%k±óåÿÂ…«Õ£ø_›’Kk–¬lgŠËgµ-«©cT*«[²´ºGÞÏÁÝ<~ÕÒØ±´¡yjCªmº[HZUIQÁϪ«—3)ã£ü‹R5²\ØŸ6F‚»ã–Õ6Lmm¨[J wô9eŠ¿¡¦Âaé”Ó+Új,maIKw¤’Ë ’¦d3z¾Ï™ØV/ÀOÅ^8ãë]ûèi,êÊ3jSr4,J¿š3ÑÙ¼Åö£ËªX|1wAUKCs”—çž‹yqG;¦W/‹ >ÚÐGŠ/1ϱîáé­+â}ý`‰¼±JÎjîh¤Ÿ¦Šø[î{å¬ùSãœkÙ‡oߜޔ/ë-LŠ“ã$vu :û¦Y…Óâb—eñ7¡·jˆ­$Ê¿’¢5êQþ{©”@åÓñ‹•¸=ÜÒЖ¯\?Í^$Sܦ²••ŽŒ›@µ[´ãž›ÉßTà ötIÔ¡-Õ œý2Qa¾6ËE©V³¶°q *«SÍí­©Æ©Öº(ï mI0„VÝyɦ¶¨ ¾­%Ys"C)3çV³¦“&`Š|$®«fC®>‘uÙè(÷7äÞEü«ÆÚqi[²6ÊýŠ‹™º³Ô5[öþí©vâ–LF_Q®•Ø_\É÷Å€“(á^†'ñ?Ä)©*®rU™RJ_v1 0ÇõM5VX±£5+D U¶¥Bƒ-Ávæ<>±«SÑé¬jSIú¤ð¾¸+¢ðÕ ¯l¥åqñ–< ¿_ã‡,ÊÿÌ÷_QAgœaQSßÞØg(M¼›á8çGÎ%1;µêPNW›g!>º\–ò-|uéÞes,ÇRä¹–¥ø[år[¸¡1韕ÿ.~vFsSMK [®²OüàÌ¥éVÖç/*°,k¨õžÖç.*È3,aÉZ”›ÜäM×שcG÷=¿,~rJùè}ŽÝ`rPG¿ Fáj¨ãâZšz^M퉬€ó£Ü72ÞZØgµðüfñ«—v$ݪ䑔3¨†9ŠrwW(ßÒõ gÍ«ÌV\³질¯û7;­QÐùÒ%LLTPçÈÞiôqEèb”ÿÙ%'VÌ™jk/««úüEüà´Žšæöަ¶yÉ—ª3‘›6¼\ÑZÓ܄Ջ ^Úga=/¾<¢¼=Ý…A">[–5°Bœ‹ßñ9ˆˆjŽÓÆ<© Ûš ¾ïUY´;•U_ÉE$‰Ãe~·LTWë+^T:f츨 §`«åvlzï EfÇJß§vÙ “ntš1œU”±,dÛm -ÊŸ†}[¼.~ø€E¹(ïz[-áÒgû|ŸéÊfßív åRæK²tNo)9Ä>(´,ì´Ê—ŠZ:îéþ2VÍ/Ë&Èx÷ëõQî 5èQî{˜:OÚj ²òº-î+ßÚâ1ÉÝî”°2b‹]À Q0ÍW>ú·ÖñNÝêŸ.zÕVqå|{Ú¹9Šïe,ŽŒr/SÂIð‹Þ[çN*^VÄñ¼Yï옿…Ê1éÄ&sõRVPå‚6Ê}eê’xqéØÑ|nâsv”ûÊÒ±cŠ£Ü5|N‹r_ŧÀø0ï;³Ö‰ÜFkr>¡‹[âca¡®.Y_ÃA ºí»Ò_æ|‚–ßï³Õöúé”°ø™¢Æ†%WΪZTƒ0™OÕ¥§Ð¢ççqzRîݯ£÷éµÈΧ•·ê)`÷ËSõ’­±û¥ék¨óe²\/ÝÚÝ£×ê1+eMë==*~]¯Ù'¼®ç—–6;¸¼2Ù\Ã/Ò["¹]U¸45”÷T x]?TEñN×zŸhw#¯g£·­\ÚØÁæ¹Í%ÓºÞ§Ÿ½œÞÐvϬD_u­:oÔø{5'>Ô‰Âç–KÇ\îÔ‡ŠÜM÷EX¸èwû§xVÆIp@íNi +­¼ËMðB ÒŒÇÖVùïûê|,«/Ô86•––™µó‹Rº…o¬>1³ÕóVZÙ¶’uÕý½ÞSW½D‘>²–xWÎÆãª/"í=ð¾^D3ŒvRuSzgsr…NÉås>[Û\Ç.ÉútÄØ£Ü êþ±ž| (Cd’SÒ®okbFÏ÷o³é׳x'u¾ô­(¾»gÂQîûøœå^Ìç¬(÷ý|²RßÙ…µÔ4ËÜîž­ò|7†ve®¬]<84B•Ï®a·¯åÌY.gÚ9ž?@ï>Q:žGñ‹|ªAŸâS ú5>à*.§ÆßAç8ÿµwA¼K‹p­Í\üõ©ö»ùʉùà!´â÷KÇÂF)þ3ŸÓ£‚¦“ÿ WAb xÿ¢‡6’ìîûE´‰|…*4)÷ùSóø±ãé¿áU{”ó™ù³£üaÛ›:¢ü¿"pA¥÷+{Svh騮¿ùÅæÏÃ&6¶ú;k®£áYì{'šDfÕqréØ ôà>Uû©|å}¨¨£ù‘‚„¾Éå:hßZÔÖÞZÛÔåVR•ùòÒq£ø\Á§&öÂÒq£Á | —Ï×r‰r›ˆª«?§HŸ?˧öÊ/ðÙ{0ë±×F7t¬øQjQñ¿]IÍ_}oI?2¦¨»©ftcMæ{Fe3 #ºÈ/×Íâ­ZñLL÷6¥Z©óø(ç­GµfA”*®/‚rñ@M¬¡¯’ESÛáJ3|xé8MôT>Îç‘QþiÕÕóªª*f4ÊÃ{MãL>gGoO§é8 G‘@—­Qé—³âI¿÷ý\¼ä÷v£cØ=N™u×îu \ý{oÔ¥þ›5ë(wÔ5-©“ùœôô I~U,}ã÷²£üoî°­]îØá“»ô·C˜gáÏšÀŠ=•ÏQÁ} dƒK7t¿î!;ìQÞuÿf'^â1Köŧ?`^¿”ó{¿ÿ@”Yاñ9 p:]çø=šˆ‹’u *Ã0”ºÓ˜ÒD$³÷ÇsE¹ó¨\«\I¬òÖ ›&;…—_QQ6mÓÑ·t$¿­u§Eùœûí”ôâ×-‡DØ (Hæ–Q”ÿQ—³†kJ óŽ ¸!ì™})˯Ñþ(e”w¦Zª›ÒÚ¾<Ä#(Nùà{4›€‰fòw ö=؃ò'cô··èøM1sÔ^¡yú`.¡ä#ŠÁ?Óø9ûÄ>t¨,ñךR"«ùƒ²%ð6:2·$*X P“.ÜyîÊí™tÊ^g2ÄÓî Z8:œ!FÊæÚšæZ lo–xîRhƒeᨰ9nâE)GÀíÊ±Þ é ƒ@Ð >E_×7÷ïöcô¨à%ê ZÀØ•¡|å¿åÅ©„ÞQÁ[ýÜ÷$‘]®ß×.¿Dg/Ž£ù:+Á§ÐБ|ÎŽò.wÒ½ˆ¯Œoµð“…¨•ÿ—r_ÿùŽÅyk9ŸšºE¿ŸÑdÓuçL>Å–ß*þâBrZÌ:¸ír<§Ç¶ŠØ3Gè.w Ÿº/¾—ûñãûªØF2uòR>u1úœåüÎ6,.'£†îr>g#±ä&áÉ•[|]éxÑ{^Á§Öù+ùœÑ”'‘ÀuäT×^ŧîÕ#e<˜ïÕ$R³nàs6^QüÿAàRü`éxðŽO]›ÿÖm†c£â‡I¬EqŸ³ g˜ü?ÂbÅ‘W§…_â³=*ø²KÿcìW¼”ĺ™Þ]:~JƒÝ™þŸáfñ+¤ÖtþŸ¢ [ôg„[ü‰µô~‡O-½ƒâüÿŒª‹ß ·–àß”Ž×áÿ^>ÕËùéûï¾|•ÔÓ¿åS*àÿØ[É¿Þ#Š·SƒÚûw|JHåâp|ô RDTC\â.¥ã(†wlFûÛŠŽÄGÁBÌçŒ(ÿ#nŠ<ÓŸImÅ¡|åW=xõ)îF-Å|jUè<Ò^å¿Ï²î½9 „·ÓáN‘Ê?)zð„0åÀ-ˆ¦‹tåð¢Í§0À›NßÅ>Õ ©nÔc\£'nq: èÜK¹º&û»QùÞÁOçô#tGT¸æ >êšW>†åðÝ+¤:Æ npé™J7=pÛÔˆÉJ#z¤N¿ä²=|+F&5gŸšéa1Býá1¶¸y5Vûñ)”vaÑÃ÷^Б€aMì‘£`]žç&éÉc²èHaãv>µgó©Ž}-C×ø?Çï9Ô£+먢×öÊëa/=œ¡<§è±Óÿ(Ÿèû܃Ò3c$ú8§aì¥'ˆ¥û<ð4J'>y<#iN[C“›åókj“\P’SÜ^`yQõ’TŠŸ®f+Í¥HyˆÚ˜fS½³x “~dr:ÂÀQ{(.g?“&ÕuDŠ'”¡ „¢‡TºV©ËÁ¥| •ÛÝ´ïu‰´gÿÚµ×&±M†—oFÜ }ö$ʹ]z.ö…ØRׄ`ñ—zzñ’— FC¦£{£Éë‰Re<ÑmSUVÏY0k’-„N¨D“ëÓŠœ^^6«ªbvyueEUTðU=YQ¾¨ªzþœ²Êù3çVUO›Y>혨àUzyæÑeÕ *§#–²²bNUù¼ãÊf¡dÉË“ç.˜_^]>§lê¬òéœR̛ų«çW¼ œ ©ôÔÙÕ•eUéø‚/˜>}^ù|Zñ-_]š$ú‚žœZYÅ‹iöä“™'ÓíɯežÌ°'¦:ûdfü¤ð½µø¢ w÷–“¾º¿·¢ôUCoQþUñN½:iêôêùåó*ÊfUO/ŸUv<ºvþÙ²²ùŒŠ}UÜÏ¿Zq|%3ñ…›5·²òøêi³§ûÜ;2ÏðæL—,z{ï+ÛæË{Ÿ˜,É‘½O–W•U- s¿E9oËDÍ”W}eË»¢÷‰-ï}½O|yyòŽPtAUY1ÃÊ‚(o‚ŧYü$‹O·øÉŸÇ£\Ÿ_rÕ>µtª}V ¨ù„¢Ã¥µ.cÏAýöíérÓ'oLWœ>ysºèôÉyéZN˜«éVÑËÓµ¤OÖ¥kIŸ\”®%}²º¿umE-z²¾¿=ÙØ_‹.C·dj9ýXì½euΦɄÏÉäW¸rRfYC§GùïL¿X>«ì¸ò¨à]™ñt)| Ó|Š?ÏL¬K±ú…KñÕÌ»ŸO¿p)šú{‘N^Z°ëIú°òòþÞd)ÍzÍz”¥Ùß«,¥Yϲ”¯ìï]–rƦ‹#zi¶£Å y#í–÷-I»h“ùµá[h“Ý4Ð?›Ìà”¼y6ÙŒÎÙdW÷·Í&;qãü\4~`øxU¿qòL²—ŒIöŽ3g’°Î${ÊÆi3Éü^JGWñ§z¶ðøYs¦—Ï/¾»¿qÙÓø†îåi÷·0Oûå>æi³ïN{ü@Gó´CúÛš=-èí’ò²éÊ ÓØ”öYéG=ué²^WÓÍè¥KçÁ“ï£Kwì@]ºßíïŸ}–®£´wË+«PÜëè w¸IÕÖß5“*ÛÐ!•Ç?¾c&Õ™ý2©îêïʾY¯,l-¹#Ah—}WöUds =PH›æúÑÌúæ~` u.áÔÝs =ÒJèÞe»Î%+}o ƒ.¹ûä té²6ÕÒyøíÛçÒùU˜vÏ¥û»þæÙg‰»'…Þ[1wþôòªòiU¸ éh`þ6yÅ@Câû[?s Ÿ!ñû›Ÿ?ÐÙØ¯ ßÞümÁƒè ž^6‡4+*æÎÁ@',ÌîØˆCjsî 1¤Þ½ã«©—@Æú‘cHÝ2 óÇÑYz¼PW4ê+¹5džØÃ‘9*>=“ÂÜ´Ì›âÕŸ‘Iñ’ô›ÂŸ™Iqmú‰“f},›WqœÎ‘ çΚ;ovYe”?CÏŽãÔ¹|Ú¼òò9Q¾+ÅÙJ^æÁ ÜÚ[T=AeåÜyÌï”ò…3Ëæqz9á¸rÿ2Z®—Kçí®ê§”ÍFÕÒCy¢£Àq‹¢¬géÁ¢ò© Ž>šyª&+½Ùõíä¹ó㾕oNÇO˜]v4Õ\˜~À!V¤ÓâòL3zjEïΚY1Ž›+Jxg *å <;a8>ÊwcW}wJEÕ¼éQÁ9ý£<‡éŽ;·Êµ^N²«ÞòŠ£ãpé•ñQ÷”ìæD®n_<{î¼ãO_˜óðqeÓèÿÚô£Eó`6÷#wWÓeeóÊfÍ.”Gfžžº`3o®-ñ„ù4›93ñÓÌÑ´Dy·»ñ~ ‹ìäêi³æN;†à)¨{Å¥Z°(¾u¿.ïéÇdN?sÒOì¹MÜ–ì…hö¶gÂbP™ w1OWÍd›ˆÿ^è \‘~¡¥s(4jô/dÖÆtKR‰ibwÈ5ON®˜^áô‚cwñ4oÎb›7ÑŠôM·M3¸/µÙnñ}©ísö©—–ǬÅîškÞˆ Æ(ÉM„¹¦óÆ]5™ìÀlÛëúžIÜÕ4¢ø¾ð,[üEwCMŸùl–KpRùñSç²lWBÐâ^V1›Wö½dŸè}"_ „•R¸y U-\ÀEÎ ÷‚ùÇTϘŸ”Ìâ­|7^j gΖÖ*OÜyeaå·rN¿éSˆ×¯-.ÃÊÑKÓÑc‰š¾šèB¢™è"¢Û3™–! F—W ¦œeRÔŒ¤}«Lf„LôàÊ]^~tõ4îæíèÞRžÖû@¬ƒ²;ñù‹y`¨p~¹÷Áñ¬¿Ãz,^ÅÖœ©ý=ˆÓ…Ïû•SËæƒ ÜOß,­˜ I$v—Id¶múÆ&*ONwú¸Ye´ÁÙ²J&{Ç›3™ŠÄñªŽÃšBÇ£hŽ[´™':+¡oN'÷kûßhñèÆ©•ìÅläí«SÉnΧù›E¼ù‹ìzc`wþfo&õ¿YΛæþ7Oå9ÿ„îêM¶pì›e¼9´ÿÍÂHÅû7‹æ¡ž2t„BzÎ!dËgÑ<(Ùd¢Ò\7ô=2ÊqÇh¢+”)]a+æ¡Ôn1¿‰J±Ý°.lTU¤;v…ªxº.Tgž‘‰ª3+3QufU&ªzÓŽ.¤^{Û³„što³Â#¾Ç…e¢\×K¢ ,š }݇$–"ïà «A)‘ EÇ݇O˜SIê>,ø"†KZ‰L++ËçLwÈåi鬧; VÕiQÖ¾½O¦Ço W @°§¸Ô5//ŸÅã”GìlùX<t^?H›õØye@íâj½\1³‚Å£=³¤¼z·ÙZ°0£Á¿VTÏú|wÂÒ2^ÏO”·.)L a"ûø¸ŽâÉ<Ø–•¯e,¯šçÚv·ž,­ êÂ2ìW·68¥KÉ8>èù©Ö¦ ÛkÚNôÁÒK[QñEuÙpØ¢‚ ÆÏò_T—Dþ~¦{|$ÑíîIñgNR¾òJ¢md¼×,ÿºvYÊÉßÞÞÐ. ë7¦‰rR[ß¼”2 ÇB•û(‘È?­¼)­{f[R ÑuOŽ#»Ë«‘ß–@ÿ€ye «§_ä*¼”©KO<чæëRF\ƒºÀ_¶S‹š©s€ëcZGa=Èõ,·µ„B’yº‚,fßë6R~­Xt+ʦV/„)pêB,Oˆ©–©ãQ¾È|95P:ÿ—Ò•Qþ*âçÑÂò«ZÆ¥Æ(ÿˆ–1£]àU-ÐŒ(U´”¸ïÃ[ħ””ôy5m(¸]!»4^Ë´KKë×¼nj—mñ¬Ò#ÆÂxú'Ÿb7cµø2HÇa@o†ª>­ ŽD ð&Ÿ¡®S[ü’¨ŒöZåk¦ôØøÑ÷{3Ôèå¿GQ¾ï± j|½ôXîñŽï›øRyœ¢ƒÚZz¼ôè—} ©ê 'ƒÀÔÓɰÙ_*Î&¦¦Í2·ñgH—R˜/hL-aXÖ§aWÃjÿÃ-ìÒÂ)Us§¡ô}žlüÞgá–`ë?)¡ZxåïäZ /¸_».:~«X^Ñ®¾TùâÛ‡ ,¥•¢þ»Ài!ëÿb-.T…ñC$©4mQ¡ŒvÚ*RZ™ò[•äòm›UÆ?ô¾Ëä8R>9¬« ç©ä¿ýb÷'ªþ[‹ŸM™j«YŒ)êŠliÊvI舟{•™c24迵ãÝÿ”ìÙꮵØV A£åJŒX«<ö·Sä*À/Œæ~=VÞ ÕO3›’ƒß;£.7†yÉ=–~Œ“g; @U™>:ðw¨®lzúÄ¡ûÖw!ˆ+HNgLAS04SÖ]ÌâzÉGçÿÆF®b¹í1ÏÄÖÌlÙ±“ʽMöÐþœsEËÚ)z^–Ž’/KÍþcXSÖ;û€£®~cORõ…—Ÿcä(R‹úqÄ,Ÿ} j×ùØ1-8³= d«NèEx^óþ ®Íl|Ÿ+ó 0-”-Iaîr¸ùð¹Àf—k"“}!v«ÄÎà7hã-BXçÉû„+IŒLI‹€—‹é+OºÏ ‚.ß;ޏ²Z{*ç.”í4ý–Ó­ eèKÒË1²4»6ÊfœP[£ Eýotl~‹±éµX¶7UÌû9ð}åÍy±Ma#k“nR3N]äÇCyì[ìßðVhy;bÞ¶è­úbl´ÊLÓ¤fnÀ>'6äʱ©ÛIÍõØÙí’â-ùŒ©Xkïv’lÖÕúcïóÑl1r6XŒ^-fN®^ŒQ¯Ì>M¼Ø]Þ³·§Z«¸/®˜3c®,~º·`#¯fmâÅåóæÍÕ º·qã­ŒEM¼¸²lNÅ´L±Ge>jb0]í!ù}©Ó÷Рp£o~mn;WØ b®dÞª|Ψy½ÁÖ+eë§|D×°ì ϼ¹ç®3?Ýsç™çöܾ6+vÖþ=—Lª×\ cûâ¬N¹QÃoÐ\ì[MÀâÓ‚S£á%Xóï¶aïì:Þºïö@|;–ÀÚ±ÃÕŽõ-Ÿ§mYÑ¢’ý£Ê®a9žFÝÛ©{;uŸÒ­~Ðå¶²îØ8íµÑ³·8JP­fl ·¶„æ•·»ä˜¤[d1L--osÛ–™XeùhÉšòæ§i`çop|‰±NÂõ§Ù{I·³¸hæ‘Q4&S”7ï¬9Âdj³Ïé~ÌUT. ©vÎùŸ©¯Áæ+ö‹TåèÐwgñI9ê}?ŸÆg³Í0ÛBæ•fhy~¶™,Wê}¥Ù϶›é;4¿é̪ë;÷‹öøf®ÛèéÌßåõÆ5ÃK˜áù~†«³káņèfðƒÃ­ZqsÇW«Í&f´Å˜šñÃxëd›YzÝn¹±‚8Ïb˜p]jó‹ñÖa~µçc§RûÂôüæ3̉i°Í0WÎf~ü 3O~†©±Áöº¦Àìu)«¼¿¼³¡½(Úï—6ƒ”ÃÑF‚Êû{÷k:‡²6 d°x¥]ºÊÍÞfPûs¨w[˜?—c‚Ï¡˜UÅÚéžf3ÍuåMãJW³›õ.WÅ:ç•[Y{0½ÑÍ,WÇ0³Ù<úÙd·N¶s0Óæ«ía–—„_a9ÔYí\“º¨ÓæÃBu»CÓïæÐyµµ!êÀ„8œe¶­r‹/ù ¥Y“X²2q°¾Û »£­:ÄUnÑnøpMÏÓ˜K¸.ÝËæØŽe¶ {ÁÞ¿*JtkçjrÚ±°”b[ôv췢®Ó~ZØ-“óK³#È·È¿kÇj\Š´#ϪKŒïZ|@á™§e•(nboÉšLÞØÅ·ý´pm]´¬¿}€ÞU÷ˆµA|W4æ>¥Ël­Ô5.5#Ù~ñ˜€YŸlû;œ3í³{Nx·ÆÞ1‹[ì÷žm¶_ŒqøÚ~‰‡kVÜ~Ñ\¦óŒ-Ýé±ئ—mÚ|lÁ¸:ÀÔ!Sv½uì[0±Ç‹˜øÃp¢ðdÓËðúu«{nKïmѹXꛋ<³?d zAw´3ß•¾="ûz{a›ÞžÕ]pNÀ´Kí’{ûvIWÎ¥þ]Ø%gSp…Û'ר>yKVizŸ|4kºÛ'² 8zoê¼&[;åÞ-7íô¶º_¬aé¯Gc7ëŸv.˜%ö|¿L°³>?ìY †Îßm ûåÚ°_n°ý"ƒ…»÷Ë<5ÎíÍpº°)Œ)}Yƒë?#à…©Dc íáKrÈ0¶i1\(S|ýghþ=ŽlÇFá6î+`Àm˜,›åR®Šž}7s¼£«6»°jÍ´b;Oc+OÀ—fs|X7ÛÊ5Ñ›EbüÕöw‹Åèõ¢0/Kl^da¹%ÄF[ϰ“܉ÉÜ Û„é“ïye¢kC_ÕM·…AcÝFܹj´°æ|Å]lQˆ- ±¥»ºø §E BlEˆbg…üË1 n¾®ÿÛ‡U£ò”ÃfXn†£"–Ñð¹Ùòn™aE :cl_ü™á?kHÁÀ:·.QßšjJ˜O¶ƒ‹K:G&0ªsÔÁ-—«Ï`Búþ3—”|G\<–‹ªËAèc‹×Ãn<ì`P¨Éuq}+:"ËÈ‚\JúJób5ú°ØJ¶­mN9…Kjr‘—¦k+îTµmÍm VñnÌiÁ×ï{‘BZ¾†<‘o®íWl³/Ó¥®×nfö•?¢ ÑNUÛ¹O˜[”,æWoP²Nšï6ùÏ-ÌÚôvò>Ñú²S³ŠK»£‹ˆõ/;5{-±³‰y7‚Øb1±[ˆµÓâÑ‚”ÉPÅ Ä®§–{‰UȱÃr”ùþÒ‘—k,íξ”|ÍÄvX}ã‰]c¹®âý"Þ_OìEÄÚ‰m öSäZB|+±kù>›wíÄ>AmäžOìWÈq±ÑÄ>Jl±5Ä~™ïo‘wqcÓ»d,±ó=™~ÝCì×ÉGäþ5b­Äî"ö)¾ÛÈ]$öûÔº“Øoð}/=]4‚™±w wËI튼ü)%y8Ý•[\•ßçF_ ==±ðôœ¨Rw¾ù§ÂÛ±ß Ârå9,gïʳ¢;Š¿#íʉ^\•“?…Zoøcέ93Zȹ†þüòý9/îOtçsÚþDWÒŸ»]JûÝ­4:^è&zm]TUµ8üÙlÁµ®¾üÎRÎß÷9Û/È`5‡á6uòƒÂ59=«\=®æµQoWèêÞ?Û½]ãÞ~…·í›÷%±Ñ[ÞþˆcU¸Äa¥@ ÍpRÊzvX |TÇØ`#ÏÁ4¹ç`}<–{Ÿmï„w ¹™|ç…g ž¢|…F{'ŒRèùv^Å z^-Ü"o£¯b×Ü㬤c·TŒ¶Cß~3LÔ¶öÔ}ðíÀ¹>¯Œá|$ÆÎ¡owIçô¢6çJ¡é͉̀©õ)±IûCßžHĈ®M**m Y[mï6¶û2&§I¹›¯­Ü@È¥†¶8ýQ´I@ÌåЕÉäÐ5Éæ ²Ž˜®ŸËß× ã™¯Ú —_W.Ñ‘Á]׆fuª©Ié=ÆœÁÁºÃ8douÊTBÖO±¢Ãbsù‡¾ÝcÜ´žKbK|f5•`uÕçWÞèPgH?Ï/ˆŸ¦–dMÚAY /Å]³Í­ÞEÏq6åóÜ«“ÈîнùcË¯Ù‰ÆÆö«µ¯l’`‘ke¤³cb<Ô<Ûí…u¾‡pÂØAšÛ¬T^Ò¾?íàŽ¹Ö6‘Iz—W; Ú=¶ËßÑ¿¶úƆ–çIÇר=+6VŸ×ˆ3µ–”ùLi§E{;Ëõ»ë2 L.Ÿv§É§]Ú9â)ÛœF·Èåú7»S{Úæ›6±ÿ4¡Uäºísb‹Ÿœ2jlsN8'ÖøÙ·2yœîèB\ ØéÇúªHö~ÏY³ZLÖuV46Ëý L· âEÌ&úvw›_ÐskG‚OÛ¹™÷ùìr6߉0­¸9ýøž*ÜÖÎEó¬r°ð1~toâ…å›~#SïÝÄãÑ»]½ïÚaýú·“÷Öí¡²Œ»Ágˆé†Rº†Ø*beîÜ9&Kˆ]N¬•˜x?q#·ááJ1qn-çps gSÙ©X_°yÊNÍ©*íÎ9ƒ·‹ˆ7sô›‡émÄtK)_Oòë†bò ¤ö/—vçs{)u×=¥\Å·zP¾ÉÓ%Ätï‰nswѺ±”ëx{ 1ÝXÊÔiòé~ØõÄ~“¨nÝUFG_$Ÿî!¦æÛbuëS¦ÿñ:f‚œ¿Jülâ;‰_C\·–2·“K·–òdÞnáí:⺫”¹Éèæ3:úGÞr“™@ìw¨›[L ±Ï[B?ŠÄ>[Ú˨t'±?¤ßô’ºþ€Ø—x»ùXFü ÌŠzX¼ŽP»×ìÇø÷m#‹«öæâæú¬W¸›CÊÙû2ÝH~¿,ïo$ꦡz·ÖPø‘iÜÿ ×â÷ Å¿RüäßârìRމº{œ³pziQWt`ç%IJ|æí3ìÝ3º‘QiçÚ oáÊ^X²gtB×…ÙEé~ÀõqÅðF‘÷­á-5mûf¡öÙ5¹é^5¹§½–mª9¸‡9¨Ý…ú˜ƒUýspÞଠsç3oϳwç ÎÁªíspÞ¿ÏAAûÀÞŸöÛïî°ž´G¤w»PhZÞŒÞ+æy½~Z´€Ü7’û7}î³NÈÌ s0ÁY¥/£®EéÞÂÍéQ•zÁ|µçÃIYwuçtÂYÑ[G†9žÈ¯ÜÖî¨dK íèdõ$×ӿϤûw\ÁIUëóŠwÂØx'ó§hŽöŸDÍÑó ]pEÕ­Ã'v-žê8WÁiÇ.º¯sÅçò§œü”©…%âғwŠÒ³ØQ÷êþtÝ‹¾ß ÿI5Î)¤ÚûBö„vøg/œþí»ãý0Ç¿yÊÂéßxóÔ…ÓïpuäožÖ79?HwQößg}öÌ \‰|æá?(ïÍäµ·ÇÞ¼®×ʵ•\Ÿ{¨Fzÿøþjxî^jxYlIˆ-Ý0Oq!u~þþ:Ïš^àæ%ÔyÖ î<Å¿óõv¿Y²pzOo¼£öèì®—}§pÍyvk-Å·VíÇ5é>ä{Œçò=»?ßWÒùÞŠ7˜ZΙ÷aðü&ÛÁ«¼iÝ ª·XÔL¢ac£ì vcÏh°›(·?7åVèyP]7Z{7Õ­"½Åó|iÂíör{ÇÝsG¸Ý^oï0Ûîõ3ô.YbßÌÄ ž¯%´R9 ¾VÅŠžDÌ÷O7º¢¿«EÖ4Ï ïn¶wº o u|ÅÞéæW‘yWò¼/q{Jþ>-¤VZrÜrx~—nvåÀ+{}ÝäÊ^Ó€wçØ;]zʞ̻ë3<«ò:Ë¡»[ùÒãŽLÝ•\Ë¡[[%‘ÉQñ½$Ç6Ë¡ûZÅ÷Œ·Ú;ÝÐ*×…w_²wº“Unï¾eïtûjØ93[ »Û}]¼ØÎûzÃ2uÝ}=âïgâ2 ÝÂNà¸lÌM8,}M=:!oÜ.—øðæ^'³öy®” Ï… ²È[ѪÔVb«y„æ­!³ƒ¨AýJk°ÇTã*ÙÞMv—®‰ÎÌò÷Té4˜»¹ø'Ôh»¦·õöôÝ\š¦Ÿâd9¬µ\Ÿéõë,—t(L=â/Ø\—¤ nÕê‘Nˆ¹/Šûpwg{s–ÕæοÕq8Uikä49»/bô^»ËÌÖ 5Zí0°Ì=±â¸ýé} Ç`·óÖòÁÇ<ÛᥱWkýEaÕ-`æm`f0ä[bNÖÖÏü pï\°Ï ÷ßèHè61Âa¡Š¼®5Uß/¸®9ï§®yEŒùÛ úñ~™w¹‰òNÞ˜‹Û‚òpSÙšÿƒÂý^)Œ-,Vˆ‰¿3!G¼®¨ÞÎ1|O ^à»M÷ú²õ“ß)„7tv×…Ñzo"[s~Pصž:ÊQ]Un÷¾ëò¹UE·w½<§“7O±Þ¶òn•Þ]™Ì.$K:¾jDåähUËy’7« ö£Rj?§×ênAy/j· nÝŽôZ°5ï¶â^–=XqƆ[Fd]ÔƒøÃ"¿7ȧô;´+Ó½I^íÍ }[ñ‰^>-Z ÌÞUþÛßUí}û°”øûåHöÁ|ö‹¹µ™û^®«£ï[JNtoŠâÎ_uZ´÷ê3¢ôìêûÚôÀfÃe~þÁž|Ì…ž•’/öÜî°¡ÌÞÓmzëºhu.íÚ©´ÈvQgíáÆ65ÔÖÞRòý(kÂ0,ñD=ç<È Ud¬Ø•3v‡›G]-¤9´ì<þãvÙŽ^…w~®y÷Y›Ù?¼gf™ËtfÙ1‰->Ò”œu2BjÉYŽ…áN!Üœ)>/âžpgÅA;ëäeu5?Œ‹fÛÆ$Ú |H„p}³nGhZ‘´j€ErÖÉÚútÏu¶'v:ÇÛ`_€³æ2Is÷`5ƒ^§`.h­Ít&þÛÿ9º~ÂS¢«Òó.¼ö½ˆíbÞW¹yÑ5¬ØÏ{3žó™ñ–I/cG|ÌÍîÝèýðöÕ¸ó=Ñ¥“ÄÿÐtQoûw£ª 9ì”ÕgvCG}Eø£¹¶î{g´Æa¥?¾¬°ëóÜnÏ+­+Ïí~õúâ®ËöêTÎZN¼àÉF—ak-ù¸õ®GiEµ6z1ºñ%|eâ:è;äÔ»óìÝy1æÔ»óy·:Z23ÿªeÍš Áˆ÷p¨üã늻ÎÛ«óìúøn¼ó»èAbøŽ¼os=xªõ ¥«žýqTJýmÔyÎ`í«\Ýè¬åå_>MwwÍL\zjÖÎ#$üvutúÂz´kÖŽ†OOö8í5ÑÄ’ü¬É'¿É¡[tk¨Q¨¿úý¹þ„úÅEé¬?¾ÄêO4ã»>É!œ~=9à&}ÅæaË=Õ<í¨µ¨_íÖ¯n^ŠY%½ýÊëÏú/H'ÖôAÈhw˜{£ö"š&äD·±œ0KîÃ=¢~¯¡)=[ío“î­öºI½Z»IwF“N¯î6&=_í{“æ¯ôyl %ý©“†°øô&ftXZ-FPsbb¨V6Ðg´#Ù„ôYZA}ô™Y|´Ï±–·ï sæzRí?}Лæû ÛÇõ9–ú‘ë,M_7/±´~ݼÄúh³>£¥ÙFŸ¥ô>çû¤O€~ÆÒ+nˆu†ã/+¼cx¼ƒc‰£EO„B‡®?¸ 3)î¬‘Ž¡‚,ã)‰•©ŽDS”Ëȸ,‰ÒtÎDíXýas"ָͰEŒê¹ÙÙÒ{º~PL’;žæ!F\:ÁÑNðt†®ï»õæZªí £“'ס“±OGi~4á9¶´øÎh}º[ª™“Ö Cì°°éõèpƒã¾ñòÝzLêµÇ}¦÷~^$UnxÿÒ»ö®M∲my¼ÍŒ4ÈÍÌ#{×3“§þ7oš?žú]Ÿ™Ö3CïýÌ µ™‘¾àð×l8Ìgf¹DméÇŽþš!fæÐ?˜ðüñŒÐßúŒ œõ6zíg94±¤×8üîXX1ºØfBW)éRÊzxè­Ÿ©PGOe¤ç9âÜÌÐð)˜T¶•»ŸÜc¼yÈ9xØ êç€Ö瀚÷ͽõ}– ´ÛûK›ŠïÕn±Õ ¯AЦq ›fß[ƒ¬‚öºÎt5èf#z*¸·é)÷ÖpУ†>]=ã­q±šÚ7×ó]㟮žƒ¬iÖ6½íÁz1êê9˜œ7ù}BS}Þzé—3ë½rü-wÁzÞùÜOë9xçsp‡®çàÏÁ}¿žƒw>7«zÞIŸØä ×sðÎÕaøÐÝ9Ì;W‡áçÕsðÎ瀷WÏÁ;Ÿ>_=ï|?àùÕsðÎ×ß¼žƒw¾ô3ê9xçs ÃQÏÁ;Ÿ]zÞùèƒÔsðÎç@¤žƒw>Ú õ¼ó9Ðe¨çàÏ6a=ï|4ë9xçs ­XÏÁ;ŸÍÆzÞùè@ÖsðÎç@[²žƒw>Z•õ¼ó9о¬çàÏ®f=ï|4<ë9xçs ZÏÁ;ŸÒzÞùhÖsðÎç@Wµžƒw>Ú­õ¼ó9ЪçàÏ>T=‡õ*cs Y[ÏÁ;ŸM¨zÞùèIÕsðÎç@s¼žƒw>Úæõ¼ó¸­«zÞù:ÐV¯çàÏNq=ï|4Žë9xçsàí¡žƒw¾gÜ>:ržï|x¨×Á;_÷zÖC…­ïõ:xçsàÏ¢žƒw>^8ê9¬O›õ¼ó9ðÎQÏÁ;Ÿ_'õ¼ó9ð„RÏÁ;Ÿ_2õ¼ó37¶žƒw¾.Ïõ¼ó9¸XÔsðÎ׊?…zÞùæ¦ÝÃyHs ±ÇÞHqùñ³9Ù7ëþÒܪ?g÷©¬IÔu£¬É»¥"Uh]0+S¦s þžK+VÜﺨ¹«ð«œhù¤Eãkªhrñ͆“{ÑÊ{-Ç;]†çü†K56<*HåËô…þLc|¦9vÑe£AÎJt½oë[Œ’±Us£Ø‘º5ªêg£|a‰}Ô(¥ ]Ðo+lÂ>Ÿ^¼”ÿ‰++е<ý3å&þ²t”ÞK;2ªwÑŠïE?±” ¦=è«[þ‚¢§ê’z6ß HÕÞ|$ߺº5ã?Öa³fN¬óæ3ã^ô/ëïÕg½ ú¬L^w/úkøµú£´Fˆý®Úìî2dµIOßfPfÔ)ÿ §épß’” »§öÈ@qd'n Š6oJûO·ìÚõâE·À[âÞÔÂåÆÜÂÎEâ¨ü‚G™AòƦ:É–&bÓ±AèNÇLÆ îP11˜{a <–oÝ1ã}"æv2˜-Sï`XÆ SÜ ÖM˜¤V°|¶iåv’€[‡JÏ[=ú7QÙþ`†ÄÓwðXŸªÖE™(é( A]³¿¡ÔÌD Õ|hCMñ-žÀÐÓ­FkzÌæúXüfØÝnºð€f§MJe6ü˜PÅH]ú5-#Å,о© ÓdJ›Q\b.Ê£Ù_1ŽQöçª3qûÓ Úµ?Ž„®Ð´„)‹Ò@žkc𦷓ÐÛq ‚ä<ݯ„kØ\jhïA0 0u:žoí¯ƒéAÿ‡Ð³õO@Ý¡À„N›±?¥ÖS~¨X×êð¡;]Òè‹ê¬ÃQ¤cûÍœI+ÛEÉ$õí|êØC¼²Î»¤æí¢ÖÙ•~‡ŠÙ¡M2QÊš“Irr¥Ù˜¤k¾f`’ö½ðÍdM³ú~˜6“z˜v¦&ò0¡=m„ÃÈŸ°y¦h.ä²êpTlŽÃÙ8ÌÅT:U`Ö§1[ô:µ˜Ÿàú=CÎ;¤P>“Ω׌"szÛ­ÈœÁ5ªÈœÓ¢H]G²“Qü–Ç(—MÔÊ+²gÓõ"Ì“ÙÔX¢ÞÙR˜Rl6sÒÔò•È;œRbóÍåJQb«ÍcîËÔ}4ý(“ïhÞ—Ñ©:š¾–™Ëc¨¯LŸçs*ƒ7æËÍ—®2<+ÒúV¿*Ìî±hÆT˜§cQ©0O áfVè×"°H… º˜^Vè×q0¤+Ô<Ž#+¨FÿÏ|kÖ–àH¦Y]µ´¶’\¹FÃØ'œïƒNp>Ãz÷S© \vmïveÛ¼Ú~.j¿ô;A7 uóqbÔ…µEÔÕuäÐ$¨;½¦øDÝ£ÕåႸN:Ôä$éÜkºNÒÍMwÉeâ…‹s±Œiˆ™–ÓЄv›I¶ ¢yÚšºÓÑ~‰Ù"ËÙ(1u-ç^³VÇhÚV€tÁ'+`²ÆLÏŠ¿Ž§cÅ_§·ží9³ò;‹… `¥ÿnß<€Â²Ýi~+àÈ‚JÎûH»è 1/Ôù3ä@L{â ácí•3tRçÎÐÕTûò ©¨sgй¥·g ›kNÏ.ÖDœ)v”&â,ù™S'ÏBG µœ³t­Ð8«3îèY®#¦ké¼›þZ ïûtj$LêYºFk’Άï >[—yí¯³U¯úq¶/Ú·O™À·&ê)rÞ¥O‘Ú†Ônžª©Ð?UX[}x*È/f/žÃôÇìºsjbLçh5éOoâ[}|½9><ÁD®b‚ö×*z•ЗUà‡4·Š'œËÌ$ì÷sA° ór.{„y.“žÐŸs™Ú„={¹¶ÇyR¶Õ†:ݙПóèW¹\ÍȱÖam´šÜà­Õ° Ô¹š=]`ÖÀ)PçúU Î5ðÁk¸ˆÀ'kÀú¸œX Gkñà[`VÖÒo–ÞZá õs-x¯H½kÙÏEúy>=(RçùÌxå|0Q‘99ŸÍYd&ΧEÞ^-R÷¼-R÷Ü$ŠàÆ `gÙP‘þ®S½Ú먓%´Ž¹-Q÷z9˜Ò>X?Úmç?ãS?³uË.Š Ælñ…+\®â_¤£`ƒlìçqó0f„}7L—í»ao0¤Í­ÅåNÉ1\*©Ê1\¸_9†ëäsÀ0 Š8äøkËþöÔ¡#$J«#&Ä9Fà×ÀÿFˆ9Eö'9Þ`9Øw>wrÀf!ÇYÃ’±¿¦ŠøMSìоÙdopç߸{\“SHto^coÌÅÖ½ù½•àúÙ$&,oì͇©x¥¿¦Ù—f_[{¼€QX{WŽu“½`_3ñÙ xn†ƒ¤ÿç»ÌT-¨Þ’ÒìÿZ."µ ¶Ze ÿB·½@yjF:k v (§è*nî÷ëö¸({Ÿ½,vÆ¡FZìÀ({÷g[l|”½›~ïwµ°­àÃIES_‡P j½ä™eï-%'b0”é9¸ÄÓÌé1›FwôJ/¤Éi.xT‡‚;g‰üšÛ‰·(JÇè#¡gLà s=¢:f€@Œ‹'~o¨~œ;êÛÂ¥cƒ²y‘hæ å›wp¶§Û;8°L1ЖP¥‰Q§Þš5áºhßi1¶>:KÄ„>"mNb\µæXLèT‘¯¸¹Pçõõ§.öU÷…z›¹ ™wLWê[‚Õ‡ü•§TÌ=ÓÁ<³Óé®­„ÔMøO>:€ ¸Yˆ°Î©]"9Ó¿qµÿµ«=$æP®&Üô(ùÁì£Þ±ØBL#;ƒ;Õ—Í/fQ‡ItñãjŠ© y©Ð+8Æ6· Pˆ&³v„" ¿ß÷¨æU_À!Î^P‘»šëoð¼é/&²™îTì £;2dlbr¢ÔŸ·ü­nÒØ=h´ò“cwã5‘ºNµyA\ĘE51þcq‘÷p„XM­-®k0 ÉÊQž§ôõÇVõç`‘k´ÇGdž¾/´Ž³©˜_¿…ÀdTÊ:Îbl)Ì9“Ù_î &žoуv× !ZÃÜ¡>˜nüu£Åõú,ÛYüζïžb1úþT‹5»ŠP¸e×0Ïà*â‚5ÐËáÏäó›wÀô”+³zŠ+ËhÅèé™qM\Ñž5~Ý}^dŠx¤z¿®F²Ak^±gøY0þ³ÃøÏ=ç—ŸûûÝ¢*:ʼnûÌ7‰†åá:Fð›Ë7Äè½a ¸9‡ùAŒyÚ`õ±=/ x`cÀãêd7ð﹞|Ö}ÁZ¯¡M®E5Lkô’½€£Y{#“»pöþ%8'{Û²ön%WˆìJ÷æf/¸Iòqú‚ëf-+·I¢åêĺƒÞ 9¸ŠÕꀃrAöþ%œëì…qÎR}·]…ìwŽZ.€`Âì,I¦5{'²ö‚È/{Áe¡6g°Á¾Ù îªh•d/`.‚Z³ðÙpÙ X‰µ.ÂA³f/`‚òð Á²Ù Ø„µxªMœƒÚ îSµùàF Ï^pÑ®m.Þµ¬ødà*›½€³P›*¸Œµ:`.ÖrÀA¬Uãtž½àº[Û°ÙÞÙ X(ðijËÈ[ ã¯ÁV¡Ó0ò o± ìuâ?ÝŸžL-ã®4v´ß2£Å™Kâî^–¾¿Ñâàwâ¯ï¿Îâ`%:ÀÝ >UÖgøTŸ½à.VÛè:Ô^à4¯vëBÇÁ¹0v/àÄ¡c_€V^éÞ}-ûM³kjñ.}qÛ²ÄÌé§'ÛNÄžwÛŒTc®‡.ª©]’ª]Ö61|MYå|«tn­?W:ËëXŠíÂ¥ãŽÀ§ÁÆš¦äAã0­~Oé¸ QΥ㱺þÍRìh~Y:këcdÝ\žlÊ;‹4ëS˜Ø_ŸÊd+7Õ,m@föl^»Ä¥*hM”ýƶö: ˆ?ÿåýc9÷(·Fˆ²þ.~,s£’Õz"óä·§°wn‚QÁ1k"…›—tÔKÔÝæýKxaCs’ç54cœAþr£<ꑎT”õóÞºì›èbj±¡Â3ê[“É긢(ç ÉmM¶¶bè¼p9*ó—ø·ÅBtej9¶7¤V@칟†[j}šhyKª «èò´^Îñe]lYõä‹njÇ4úÍ”Ý(Iϸ  E^ÐÜ$'èÑ祉µÆ—M–äFŸÿbæí;ܕ-­)æî«Î•‰%{ÅBlð¶ÚÆÚi6K{£gc…|¦3*x_3j^ÔSÞåîÛj/ŽU~V]½œ~²Ú0£~‹dïŠßœ^6í˜(÷'r{$ëíP2&Ì£ì_j¸.m“åð(g‘Y„²Q9›4Ž'L´ôÁ´§5/þ+3¶é«Ô½E”u³™£ÒÊZÝštCQy{MG{ÊišY;¼QÞ-}RÿQîµÎ¤…KL4wSé‹dbÆÅE”w„nãÑ¿È-’íÈ«œÇâ¾Nâ.ù{4ãe\H~™ {:“¦ÓÒ—¼AÅ~ÆžMeÿÄ¿S°8­t̨â¨à­[\Ì&/C7kãŠêê ¹Lwf•eÀÜ{vésEqöÓ½T¤y¨/³Õ£ü—ÅÏ¥BåË”Óó†8Ä„(\ú\å¬GW_YŽŸû¥³zã çbŽ?>+?µ²ªbîœ2r\~#Óñ§G9ï3_ôZlš’wÖ´.Å>ø»n¢Üˈ N|O™2Zo» ½Vf‹Ç4cÒIÊÙyh?1)^b\ºXÎ“éø¡ïuA[œE‚ÙQÁolb¦¹…åáˆÆ¦ô6W—Y”÷½ï2¸T¹<~—Ž^T𥢖Ž{J[ÆNýe 3šqê|­Î<­}Yí_]:f4“/齋ñkH0 {+úœe7Üã»U“4y^ÇÒ{š°4X9Ærîn~2W/ý,m/3¦>gG¹ç•ŽKô&>…9‡þŦiáƒE-5Ír_o‹Š_ß\ŸÚܳ_1QA•íLÝ.ýÆŒr/ -ÓÑ@Ÿ?Ÿ÷ÅÏò©è—þ›×ÏâçÈ>#ʽŠO¡ðoþÎÀfñ $ÓÚ¾ý^™,Ù€ò“ùÔ$\:ƒcÉ‹îq­(‘±Ç]ÜDùxuØu[ñ¬tßÿ«cíòß÷¥ÿÏî³ã—¼$Êjhˆ²°˜_<”fk"7ßk+±ýÖmañ0òëêñl²F¹ß¶% ð¾–ÃÝ¥c¹…¿_:–cHñV>UéŸó©Ùÿ >gD ¿µ(WøP‘Cï¬èP-eƒ¼++<,—3 ëÒ ´˜…žþ¬5ÙŽµ(÷_¨zf”ûeî7ú¼›ÏYQîWøÔnøM>ŒrÿOí‚Ïð©Þý%7õî+|ªwŧz÷×|jý Ÿªâ^>UÅWùT_ãSUü-Ÿªâë|ªŠ~܈TE3Ÿª¢?ŸªbŸ3¢ìW?l (ÊNmsöå-rݢܗöW“À±êS{¦p‰Rí‡ó©Ú§ò©Ú§ñ©NçS)fð©ÎäS”‹_Üê>¥p¬†(:Õ¡‘V÷OåŽ#»>)7ÕV·­d?]$\K1¦iÓÆö>µ½+œ Ñô®\ê:¸³tüštYécèγùÔ‘yð6W 7¼ £¦µ.ÊFhuKG”ÿùXÿ4Ê¿ ¬eËV¶5 [¾L'“Þ¨£Z¡Te\Yë«åÐ"ÕvÞRWŸ5² ~7#ÈœÍw»ê‡õÄëê0¶½rEŠöÄ«\켕`¡Ò[ÝUbe²³¥j:|nZ¶Ò2¢ÜNZ®I|ŸÚ%Ïã³=Ê?­ºz^UUÅÀTïµ]®+=äWy{:M4.žEÕ«øö>`Cž *O¢ž#£¬ûf.žô{E×â%¿’-Žþ½~mrò#È®Pñ ™Œû <>yx¬¼x˺¬¼hËâ*ÌÝ„¶âªAÀyÛ=çƒxÊV ᨠ‹Dqi¿Ä–£¼“¥VÕ{E»ÅQû¡Èyü¡ÿ©!/‚ÓÿÔ쯱UÆö¸'yëI{Yü%6@ñÍlTá§øœ¥ýÿ³_Á8ÝßB9Úþ¯ç³=ÊþÕÿÝ—¯*Õ „p[éœ]âÔ´è‹#¥€â/ñ93Êž°M±]RÊ!Ðò~>Œò?ò ¸y”û òÿVé ërŃàñ#Þ’¡ì]lÉû·IjGyÏ|T+»4îQ ìÒ‹ն޾¿U?ZG#9D¿Üª¬\¼ƒ ¢™\Q5—óôolƒþåëwœgâëî9<—¿·ùöZ¾y‹%÷½ï2ñœÅT5ŒBÏpþo?<ò‹ŒS–8 Te•j\˜<̉µƒä’(W½ÍÙû°VJViÅi¿×3šxðaG)¢vTœ\]¤³ƒ…ÈÑ®÷ŒZÆF²yE&«8ùàè)§ô%î„x.1DR“XLÓ¦ØÊMŽ)¢ÑÿÍ”·©QtPScºLý¥p¤ƒÄ—јÿæÌÚViDˆUex¾œÂuTx¯/‡è€ßû‘6E‰“kŠÕnbHú•ÍÈBôÌ{­BÛ¼b£Ú¼^‹2ã•1èîr¢~EΡ|‡:9º(Ï-_3’ÝŽ|mZý·iåJ`˜8pb vîlѵ÷´kŠi´Ý9÷ðØ"Hsßŵº¥†CU>Ô G;÷YM¹ÚB5åŠ n 9]Œ¤á¤ñ­Þ*ÅøüÎíÒ#ž)æÄHV8éɨÀnˆž½Õï–M.*£I¾&êYÎGYôÔ€Š¤,ð Fr%À⦬•¬qGS¯Ù…á[Œ6ÿ€žÊ¹ Eg¼DM$X ¢Q\T­ûA±ïà·ª·µce]vÈï3K4/,[h‘LjŽMl¦–m uóV “Ø \/yÛ¢·²eȤf±»\NHíXÝ— Ȥæz.”¢]dy›|F¢ÂJƒLröMªý±ò…|ÈBЉ‘Ó[›¡E‹°èê…¬I½™xñôò© ÄôwoÍB·2#/®˜3c®$ŒÜ[H±ä•àÈÄ‹ËçÍ›«Atoœ•™xqeÙœŠi™Bü¤‡!™è$H»{H~ßCêô=4¨ÅÅ蛓i´’]2†ÜJ-݈·/¡–>ȱöîÑÇÀÑ¡ïŠå-l{—÷{þ}yŸŽ×ˆ>–wiëò¾Ðõ¢gy‡`ïòN=õM·¼o@j哘Ì(°n@ðb:Âó%)£ÆBtY¸>–÷]Û—·–ßZÞ_¼~¨…åý뉭ËûÛÑS¶-ïIÏ‚ayÛy´¹míˆÚ0s’½iø'‘Ô7qrð¸ù >¢¥ÞðO[MŒËöÄ\¤WÚgßž6r/{‘¡’–Dý;ŒÎ\Ç[÷=¯„’1y/LÏüwƒÖµ%´í^çùÚ™(A¤Ç›+A¤ÇÜÈ,²Gí¥c.¼ñ1ÉÊ èÆ§ip-ì¾Ñô§ù{ †ÚýLüƒtã3'¦ ¨™6qså͉™ÛÚâÎÇ‚5Deç”H!išöÞl‚fOß¹µ»½‰81{SRAMGϘ>ÝÏ63€ä‰n[MGûÙNM±hFÓ™U×wîgaòoæº=p3ñÜ”a{tèðµûeߤw&Yª3lú¶D{y¦ú ]OW·· Ä!UÅ©Y6Œ±xƒl{1\•'›¹úßn¹H÷æ ‘C\j3Ña~>µ4ç#Î¥!~az¦ó¹–)Çè6×H4vε5bçšósM ¶s1Ûľ—XSÓ•å íEQSÊæ‰n„•$XÓtå#†eVyÃ2ÁDŸA—cÂFontókh8=ó›Í¦ŸSvïd‹1Þð ²­ÞD*s½$Ì»7”Šl¸7ÁŠæå6“˜ é4Hó©ŒA3_û ›Žž$²úPVh;¨/Ó¶wSjkG.OŒ*_œ]\<úy£ø7-1jÜıã&Ž*N,©KBxN¢¼³%qPtÔ»GZMÈä`N"[ý˜á*i›ÞÚ°Üñq\Äu“ìV?Xâ‚{£U}nÂÉt¨ë.Ò<˜ê— W¿êëŠ'&=¸íÐDkêȃëF&–éK޺׌lkÑgV£ù±²]5žטåB"ˆµw¨Q´¿W#bCDz_ý`è/nq|Ú)sýô;}ѱÎ])³§—Fï»Îöœ¤‹$Âgæ„=÷ᬞ›lÇm¦4#%¶*1†íLòwš8Ýv ¦eZp›7Î$´ïÌûÉ~¶Ç”£Ük"pn”óÓ>…BÀäÞmQ‚\oç"$?aw.8Wõ¬?ýgb³%˜ÞŸÁ@¶_2Tÿ™®¼œÎ®üœNr5ñÞ˜ \±.ŠL6ÞpZöc³¾ÓeÖ÷r™£—!ÉÑz/uºbYwÏ×¼±a½_gß›ì{‹}o(A–ÉÕkŒüî<-û–nn]_F¤gF‚¿7ÔQ³rìÈÉþ!ÔÞŽ1{-CÙHá„0wÝL¬‰7Êw“1íh:ï6PÇmÌ3Õ20k+’Súߦó :æmÍ»ª` ÂÄ-Ûs3ëûr·mË]¹#÷Ôí¹wìÈ={î¥;r/Ûž»¥oÏifwäfÿ} sáz»&úZ ²¯2Dý™I˜ ßk©sÎ'ç¸\·Mš &Ò]§û=ÆÊ¯ß”[5»ÙðÛNr†­ßêŒø[\i˜¶²ß¬ÑÏBö-¼mSÚƒMÚUý6@ué §Û¸~l»€º~¯×µ¯~JÔ²ú°hÙ€‰gí´kìûZûÞiß;®Ûf»îËì:?G»î¯l×ýÕP»®<þ¿ïºòxf?þï»ÎäNþû®3¹ ÿ}×™ÜÅÿ¾ëLîÒŸwÝ_mÞu#vìºÑÿ±ëZûw ¨ïÝu_þ»îvÝNvݵìºkúÌî :œ+lFZ7ÎКüË]®Õš…û{ª¢âÑ2\žïŸ3ÌUûÖzÖROO^ۓ䦑Üð43‹º»²Kf¦;”1Ö)Œ ööæn¯³‡9ÞY—}Ó½ù…ñwcù˜½>.êv¦~u¨Þ™¸fGÃöæÎäìß™0Öäï„Gñ¦:1âo†Üj¼Q_n¿á.åÍÿr#ò†Ä¸KÍ´wêzz7F~}‰åPÇ£EÃVÅ‹!éMOkZ"oJš|Þ<§b±7‚MÌÝ$æzûV&–x³nÄü“˜ï1'æ vó¦@‰å=H~˜‰¼É]ݬ »Û;Mn!Ô]𦹉ycŸÄ|¿u-„~®·štÛ*øZeµ¢8,“£èï|Äò>½ bb_ÎÄJ!wÉßù‰yÓ¡Äü=Ÿ˜7qLÌ1&æ†ó&‹‰}Óz¦»ZÙ%Õ”CÝe[&æÿóæ‘5©ÙmÞÝe5éþVöµjÊÞ@©rTœUœUü^!æ &óF’u?®xsÊ’C­x#Éâ5Tü I8µæ¾â Éøvºó¸÷™Û*LýN³ÛKEFp·UkâÆÞ÷ ê3Ë3fõ¦;¶¹åq¯Ó–܆’ÌóÎÓ÷ çqO±ßO·ïgØ÷Jû^eßçŽÈu˜n جٽ)DseÓëÂú÷ŠFrߘåµïæ ¼K6¿+lzçênÖÁðu;,‚¹ˆû\z{Z:¶=Zàc¯ÿLt|oÍ“öäÑ9´ÙQܤӼcƒ@Õ\ì’ž[‹úÛf™+‡Œ¦´3ÍøŽÉ‡4òØXÀú€‹]‚©cêÇMÄÁ§jÞÜÑØîRSIt”åD`ÏÚôƈÖÍÁ|óæŽU »Ÿ¾GS;]¹nŸJª ûp±®[Ýs[š%îÀ\P„¿—OØA«úM×KÒ>p²àQy“ÀuÓö“÷Îù9o—¸›Ù蜟û±Éľf7³Äþž»Ú•˜¹á)ötb—»X!šc&œ'ôâ/׺å\HÎEkN‹f—äFY¼;¹ª››ùöìÂלM£Ž§cLû—›ÑšhöšÜhN& åޱ˜1?¬:›U›îGÜäöìCÿ}ÖyùSˆÝíû§;퇸b²|<½žJL%FŽñܵÔsqiVÉ™Atñ÷o&êZ¾ |_CÍg—pyhG$ÜÕ=3}‡Yíê]õ@ŽççŸbssj¢ŸÆ˜³ðˆz?uÕ's:­gÕ’K·½QÝçlš(»2ѯ&ؽֽÄÅ£÷v±¿K`ÎßL#÷\;ö®ÇæÚ\Ñ2{Ç~õX9óp'Y0B~+¨ÞL¾luhç¦wÕ‘˜©Ic«S\«ap˜yt¿ë‘n Ñö0…Ñë`»ïÅ]ü¾×$ŽŒäêûJœ´TLN8éÁ£dÉ>zês,7’òbaûþ‚†Kã(˰t¹¤£ó÷ç¶Ô,ihDfvm[¢®¡M‚¿k|¿¨éJG¿¬ºåÒ\ÐG[õÒn4±1ÂR./R÷#b¡üþ’À-þL…_Ü<2Q'Ó4±xÒÊ'—$ô»sMí˥Ɣ­r’ Q¨Ai7`±—S=0õ©'äWø¢šFXFk[kD4ªæRŸõÝÔGV¶%qÇ_Í£Y2&24[‡}eaÙ¼9sŽ`Û’Hv2 뛗ƹÛâܨlh†£âXØ¿:Sb·ÑŸ3ªë| [8 A*CbPh‘8›&öfÆæ¨sNÂÊK’µÉ†åjÐÆä œÿ_Ô42]·6a^þ% ¾†¾VŒ̈-„~90§]í¦(úôT?γ:°lpxlD »ŽõÍì®õ[jØe5`êR¬©í£Í'¢¼–´^²ÇÌSÊ ÇR”Øà@È˹áô¿³Y£GôMÜÀR«>%»P»?Ô ’ÏoXê+ÏváÀzË‹å «°Sf'ŽYÒ‚U?÷“ ¼NàýŒ÷Øjà½ðï§ëŒH çð~Zb¶{¾Çº}>ÊúÖ“æu4°-7jéíM¼Ò’ÌQ‹ÇØW·n\Ï-vØ5‰6ks2÷Qý÷m¦vlUôÜjyd]Â發—nñ%îF°ŸnÅ;¹\KÌÝŠ·^.Va°ýsÄ[NÌÿèÂIù¿X8¥ dázg0¼u€pÖ‘'-œ\p…ÞµŸÍÓGU9'½ Δø¢…ëòr†FéÕêÍ\Þ n;N²PHŽû'«ð=u¨žÑrkåïŠÝg1c(¼ÊWpñ³Jó‚fwpU´ßÝXãª<‡Çk9Tãã9~eðÍ[ß¼`Û³ì&âùaóOÍ9«·OK0îÝÙ;½1üA3ËB|”©ñ¼'{¯9/ ‘ùhU®ýýxýÑþç8Up3/Û£çðÎ𵘣É{Dåì‡Éì‚uÄ[Fl&± µÝåöÆH¸ŽWG‹w¥X7;¹ÿ¬"ÖÈ›³©ûVbCÈ-“öQ!±b ¼ÇÛ]ÄGÿ›äœLì|bŸ"Ïb'ÛI¬…Øñäk¶ZNæÝbß"ö1b7ZŽ_áЗˆý)ïàë|–~¬Ÿ“©qñ$Ä6Ä£;mˆ}eCîèúþ\Ÿ"^ñÛ‰7†ø-ýñ‰CÜðã:g9¿§M&fxrŠa@ßï>cÿ¿äÍMn’Ýä&¹›œnRìw‡›Äžž¬;œöi¶‡S•5Ê_ÛGÑM÷«å´Ÿ]ƒ‡þ€KÜnæäoÞˆÚb¼ Þ´Ùݬ»]sú´7Ü­S1î눳OV›Ùß“¥ýñyýñÉýñ½øH7¸uÜàV9n“ðXõîfÔ9JçDÏаÞ{x3‚lù½Ísš¸SM÷6Ï£çÞ6ßbܤüÍŒ{Û*{ǽé¶Àuòü¸T9'(º+Ã1‰=ÿEú±çXaÛÌsUT‡îsöî8±¿óñîr{'4{cñ¼»ÑÞéf”rxw«½Ó](ö<ÞÝiï0¢åo„¼û¬½ÓÍ'¾3¼óýÓ='Ù9ܽ!{Ýho¶^ùËÔ]&ñwGÍVâûª;KÊcR¾Ô½±Šžï JÑó’TkÑÏ(9|MØ'ófèu/)z^’j*®³wº‡¤|(ÞÝ–¹¿¦&éáFùÞëö‘ò¤Èç9>ºm”¯­äymºi”¼é^Þù{­n¥0Ó%ß{Ý0R^ïÖØ;Ý.Jžw¦~‹oeo®XÃé4jò7Wg2ÓÜ?0Þ3(¶—rü‡gÌš[Yy|bÚÜÙ³ËæLŸèv§Ëƒµ(ÌG‹#rü‡_¨[ÈÓþ-6w°)¤;ññnN5'tGE!6ø\.E‰©ÿá s8ºÎs—>{#„<ârcÑãIâHíÍí²>»¡}™?–Ê/HV?–°Q¤»ÍñnK6·qìI¯½Ö9Fš ¡Øo’–ã?_².m帶¡-¡Ÿ¿ *ã2.'6{È)ÞW-çù õ©¾œYO°ŠDN±ª9EqÙĹ.Ï)|—ÛIä>¨æ¤Ì-ËZûêŒ-'†xÈ)öøÔÍNmÓ¹üHþ±+¤ïsü‡]7Ý‚’…~WÇÓF½(Q—J¶5Úž`¬^wýü†dc]äg1AìOI3¨ºsòqt=>¨cä†Õ'bOïF+îò<«ùBx(Ò'Ãum`—áÃÉ#Ì|ü‡Åñ` ´µ>oE¢¥¦µ©Mv¯Ì»\ÀH¨…~ÖiH]Dcæ"´Ù†2lÔ"¶ä¤wô_úùG)'‰{hû”n çW¦mÿ#æ&}5Œ»ÎòS¼)ieÙü˜ã »ê]ŸÏÃÉÚ¶èÄÙ[^˜¥ìkémÕ÷…W4êÚä¢\8þ”1S JÚ[ÇøøTG¢mYªÆÌF4/I k­É¹$¹¢¶IÇ¢p Ýbúqש¼@¹áP|hÿž+½>ÑÕÒ%BŸHè¯W—hÄhÅÚJPZjgkµ?#Ú¿ë‚èé÷§s ÕElGwÒÁâ+Þ±qgçqƒ´ïfÝu«ŽñÝÀ-þábÜÈáY´ãF.¾eÓUÄ*ܵG»˜näîâ&‡´LtLšÎ'¶¸´;Ÿ;zÓÙÄt/Ï2ÝÁ‹Ü㛺‰éV^8[ˆéö]Á;n¤ç{ߺ— y¿‚ñ~§¡>wÜBÝwS)y¨Ú«àŠªèŽ»Ös+^;ºÛìêóèühï®dv!œƒ­Æ1i†C0Ÿü |GÊ¥ûíUÑð‰Ô3¡+úV§t/4'çêÖ¼µÎ½?Íxž-ÜÏ%OËÙ|g=h¼Ü÷@ßâP–'’ÿTÏ©¤&Ã÷üе8ºuŸºpeþ”ø [»ó‹Õsj­Þœ-Åðg©Éô@ßzo8-îM›«óù÷qTÚ!ˆÔ9*^G5:½¨èXÝÒ·FW¹;ºj·¶áºî¼h²Ÿ½ßF¹Ù¯X“ŒJã²ä@Ü,hžÁ ´ë½Ù5/ˆ^ìjÓúY3s¶-Gsö »éÏ—îˆæjþàíÞ}7h'|wÎ?Àíƒg©§/‰÷}w ÅOû¯sbfbG˜‰Ê•~/™]UÊoMϵúÞñö¶íoÿnÛÛJfW„·Ò|éšÊؾ]¨²5ùw½½·3“ÍHmf´‡æ`²}×¾=ÔÖÏ¡N¹KK¢ü+»Nû»À ²žvgA£ek9Ò¹i'3þŒÿ˜½P÷Ò'ö»u+»UzS½»µº/ž«}ñ›é™yéѼO|å9˜Ø±Šm=í«÷ô>çFŸ•pújðBvóÎL-o‰Êö>ÙþêB¸ÑëºÐú2zDyÎ*enĿږ›}‹íßezF[ëèE†cæwEßus¦¹9Èæf%±iƒ‹âvF‰>šú=>úIm‡ë ™#Ñ:ûlÉúléw¡KYÕÔ| èÍî W¸»ÒÕNCñy'Þ‹FìwNù¼L¿ßr`˜{²ïxYÙŒ*üxn™j{J6u±¾ÞŸ¾ìx™»;œÛóC¯fö^T^}½´væe_ßõò´;>Ëœy]ôÏáw[d©øt·ÏF\‘Æ“h+Çuçe_ïnõ×Ýl£Ó4åïÕþ8ëmì±5ß ü;ËÝ¢q:VÚ÷ªþ{Fª÷ô¿)àÝÀOlß+ZÐËGîx{Úö·Oé{k5äá|ìÕfÇÁg‚;h´Ê>ÏômÑñ€ÁÑ]¯Ì.\ ·nG~tlU÷eGÖµÄÎèŠÊ®í:=»°ëôà Kp°²"®ÊÛ7pUªšJšãêŽ3¶gâ¯EIlÒÞºö`¦3jïÙs±Ì‚{ß!pAr=o¹ .wzÛf/yþ¸Ùi™]”cVÝ5Ó»{ä5Ýyçyè6x^×ó*tw=~åçUèî{^ïr r³Ínv·v0©´“ìÞÅÀr'~mÐ~q{W»2ݻ؃FÇT¨à§ëÕ_@qÁœÿvK.¤¹q †î…:ðS‡ïßh"¬–¹UË…fô¤òS‡ÅZF”3•ƒ©Qß©€A´ß”s,?¶·§‘_÷áŸ:¬½µs©T¬Bb“FîàÙËh•”r:Ed+ÅÕent:åÍì§›x¤$<2íڮπG>v@aÉçzzä]hÅ•}˜¤ŸÃ$¶Î†Óð$âyÔø/)uÚ÷`xñŒ duKȰà_ÆXÐñêÄWñíšåmIp+>)À­k÷ÔLVýÝVƬŸZx¹ð×Åøkô þZð—é·ð—úßhÏñ¼Í¹à¹*¾4wÕVåIŠÏû].r\¼e¦R|­ƒ¯Wg_ï–ž¹ŠnèC:G`éÕ†©WÿoLsÈ«ØxôvL=z;¦ýï˜:hz?€}‹§Gû;ìk´¼{ oÐïö\.p°ãºÜwSÐà¾ÙÞéóÅ“éqÎ ÷FÁËÇý:b†33 ï=WÄêm%ø@Èî)¬ïR¶Ø}§¾>ÜéµÇçsŒãô,ìw¬oh6ÔRüæ$ •¢ 5M-}w].ªájèæFû‚]5þÝzïñ†{¢½ln{e´ö¹1¯Áoƒp•0ÄS´[·Þ4ºðŒWFÇï#íšUSc®¸p¶ø2»4S7 çI z×nØb‰Õq†Õq†«C~®£(ÌÜy™¿È½Ýæòfù„íuW¶5¤o¨‘7×ÛZKVÃWÑ©@¤gsÍ0=¨qZöq ¾Š·’Ú(=泄¹ö| fÒs…¹iÝcsmüÎû.8ÁÏ5·6?—2ÈŸ€*Ò½Ÿ.¸Ïo êiêmADôš…—´Jô=‚w#Þ¡/pÖÛÁ„/üÓëØº—Ó¨0& wƒ‰_(-¨Óôk›Å•>Ý¥ŠïÚ¯‹çsÊÜg¤#«»èš®úŒ¾@{7˜Ùpð_žŽÖ8 ÿ ââ ØÞqh–˜ÎÝl´d¯€«ÕýÖÖ¾Í=k( ÷ß²ºZºß?@~fô¦™X«b£/§ùøÙzááižÃÌ[œnsWÆ[úmò9c|ÐØíyßÓ'ðì 3Kñéäéo}¿¹FÃéÅSIŠG_ÏN{ØXy¶æ ±S̺–\ 1&ñœž¼Á¬»xÎN…Ü^ëžÜâ:ÚÜ®©¦Oο"·Çøñ1üw¾˜b<Ïy­{S‡çc Á¥Z÷p#=¯Lø´z÷Ü0å(øº“†¼Í'LY´~“¯è9–ð};oÊ÷ïFÖ· Å›ðŤë>˜kÛÏé»ÂÍ×eÎóxݽòd¾ïÖ;£ gߣ/9L¶ÍüTàáÿV1|ÝL&†Æ)Ð3ë“.°ôN£°Oƒé.u,ÿ÷rÜkÚ¨xñB§TÚ¤&/žÖ€oïŽuJ#y†¸3Ö155¼·¿çƽ0wÛd Gº™Yv–“s7×EªW¹*sÙØJb‹,¶ŠØânÜà™bk½<)©†r4Co\ü âLJøSˆ/Q/Ü<`<LJî¶ñYÑaE\lÅãµ®ƒV¶,ƒ ýˆ–½Ûf]§ÏËžpç­V» ÝÆä«ÛâÃ= ÷àW>vƒ<ùT¦„]ðôøög¼tÄzc|bP›íñ$ûžlß3ãÉõƒ÷©³¹QÛ^¯‡ÿp§÷ܧäTÙx Tò¯|b itÍÜ«-ÏJò ;#¦Ó¯|¢Ï-ü²“ñšˆ7O…ð …’_‘ïó³~;M~_³œβ.4¦æÜRüÀ¬]\¢É¡ÎgµäõP«óKŠ…ºõ½»njõ1j*ZT—é»Þ„¾;ÇòYmê‘ѯVµ>tÔizÐÝÍ‚éÞìîõRccÔIoÈ©‹ö&§fæš;ê Æ–}@ ›>hÞw÷àcÔ^,O)§ñ&‰^´và#}èî õ:˜±¬YŒ¶¾CGX ?˜òijbp`Ú,†Òx‹á Õbº‡ÒgÓ=U}¾8O~(ùOŸ„éþ­OÖoÂ#}§&íø¯iòþœš;óŽsªïvÁÛ¬Oøµäü´ßõ)Ÿç>ú Ù4Ä~Wãå—Þ1Üö (Ï—Òõ’ÏuYRäH*IE^A¶á”ÄJ”Â/ê@Ùfò:Ü©K³üÜ:’È^9Y¬ÉÒèÒ]üýù-v«œsq¾¹Ãñ<ª$Ï…šÙX†«ÅmŒvÛü>\ñ´ì½Knºý°îãîÌènŸy’÷¸ˆå¹;º¬z~–™Çy0½õÚhÒ8ïL±&«“«¥Þ¦<zíñ黤«:掠¼¯*×4\†´ A0q?roõ?žz[Ÿü¿î›zíûŽ?Xù|ª©ø^Ÿ¯#¶š¶÷58¯°CæPÃÉ›½ÂîuwïjÀ+«ø#C˜´¦§Ü[ÃAšÀwõhRM=êRSûæz¾kßÕž a¦·=XÏ#¦òæo´gaûlbK}³û ˆþÙ™zçHŽ—t¸>à#VømŒ‘‡÷í©°£¼†•”2¿Ï¿›íë9•—¼Ôú¦¶d›)ßE~/±MZMlj~ú½D=W)ì%|Ïvî%cæÞí%zëçCºf>Î@¾á>ˆÄ~>ð2‹7 q‹†ßm>á'Øl€ ™ u~øÝœïîðQãàFÞµÈÍn8ÏtïlÐK?ô¯>»ýÜv̽õ³_Yô —ƒçŽœÉõÖÍþb‡ðN>›±¼¡µÝ”G¼Ó÷ñ6'èŪ¼!è¥>bˆ2½èž²WV.f^ÖÕ´âÆÕZãÊÐÎã{…^ûÙ¡¿õÙÁmç옰›úíg¿¶ðžä7~Ð'\³ª¶êÅ«²3‚—[}·è}b‚]rx<'5£k ýûÑœÐãúœà'²sNØÛ~N蹟üIrÃZFY'x÷n6ð«ÝÔŠFˈŠ!0Hj"¿sÉ>±+ž¥õÀÓî¾=Koý àc,&Cé#W6¦Vèð+,v¿4X˜¼ë2Ú·#W90i¹ÿ‹ÑÃúàŸwßÐ[?xkD;Uø¾u\mSªWÿ¾ {âd½ ÉʘßxßÔí° Þ:n‚›Êþ©\MÈL&„Æä‡&×z÷Ø…Öï(øõìœn¡~Fè¯óµ¿ŸáŸ³¾ãÉS÷ÑVêºì‹½}wÜaùäp}†'ÿHŸ§r¡Ï¶Ç€=·©õ#wɸ¾­qÏyÃÙ§·Go|ÏòÛd"?8̱¨­¯ÒÎæØ­gŽÅi}Õçøñ=7ÖíûÞ¸ç‰96=ìžãD~sšcÓ_·Ïy˃ ‹¡ë½-7y³iŸNÛ˜lô3a®Vtd‡®‚Îæ^¶»ô:&Z&••ËýçB¯©ò$F2½îƉ<ítÎ øÒÏ ½÷s€·›}®'àÍ\àÁ§s.nÎøÀ4³àç¿=ÂXCáÿ4þà‘¹˜:dÁ,l?¸Yè¾ßf½÷š8ôÞsûèýë=ž€:{Cè=ýŽÊ›—η;ôÝ_QžÚIó ˜|"çùM>†Ñï“Ë$ ›HƒNœ“@½9íÎîʉg žœûtåÄCPoN‹ñºrâ)¨7§ÅÎ]9ñÔ›ÓÞºrâ¨7§½×tåÄPoN{ ëʉ' ÞœööØ•Ÿ?½9í-wwNËé™i»CºrÂëé­Ór=ºrr£èÍiù]9áóôæ„'QÏÉi¾7§yÖ®PoNxõœpzsÂu¨ç>÷ædçwæDÓŠg=9 粞U¦Þœ–³Ù•tÒ›Óòwç4¼µÞ~¢7RÏ ¿­7§Õ+éê CЛÓêuå÷ôæ´ÚQ]9!õæ´º³]9å®voN«ùÜ•‡w½³f=tÍ \ÀÞœÖïlWN8ƒ½9­?ßÝ9ñ¼·ŸVº+'˜¬·Nëá­+'·¼ÞœÖkiWNðboo¬>iWN¼9÷æ´Úi]scø•=½±žñwïvËìÁQöѵPFè­LRÏÙ¸=gßdoN0I-çFíNs‹*öæ´œLóN·9“ƒû^=ï\sËíÎaÞùì¢z»£lîæõ¼ó9àÔsðÎçà†RÏÁ;Ÿƒ¯ç°³osÀªçàÏ爵ƒw><ÀzË´9à]Ös8ÿÁ&WŸzÞEå)—ƒd=ï|èÕsðÎç@£žƒw>ZJõ¼ó9ÐmªçàÏT=ï|_Ñ©çà¯]zÞùhÖÕsðÎç@ ¸žƒw>ºÃõ¼ó9м«ç°Zx6ºšõ¼ó9Ðä¬çàÏît=ï|$“ê9xçsà žÃy49ðƒQÏÁ;ŸOõ¼ó9ð­QÏÁ;Ÿ?õ¼ó9ðÚQÏÁ;ŸOõ¼ó9ðRÏÁ;Ÿ=šzÞùxj¨çàÏ«çàÏ—‡zÞùø€¨çàÏanÃÝ9œN†É‰zÞùÜhê9xçspcªçàÏÁíªžƒw>¡z39Œç¹îæÏÁµžƒw>·ÛzÞùÜ„ë9xçspk®çàÏÁ »žƒw>·ñzÞùÜÜë9xçsp˯çàÏaîÝ9xçsÀ#¨çàÏW¡žƒw>·æz{ƒ¶9à{ÔsðÎçàÖRÏao06|šzÞùp ê9,7Âæè¹‘˜w>\§zÞùp'ê9Êäè¹µ˜w>\³zÞùx¬çàÏ—ÊzÞùx´¬çàÏ÷ËzÞùxʬçàÏWÍzÞùxà¬çàϧÎzÞùx÷¬çàÏ7ÐzÞùx ­çàÏ÷¨zÞùxŒªçàÏ7äzÞùè6ÕsX='›Êõ¼ó9ð¹\ÏÁ;Ÿ¯Ìõ¼ó9ðá\ÏÁ;Ÿ¿Ïõ¼ó9ð]ÏÁ;ŸÏÒõ¼ó9ðG]ÏÁ;Ÿ/Öõ¼ó9ðt]ÏÁ;ŸïØõ¼ó9ð¦]ÏÁ;ŸŸÛõ¼ó9ðÍ]ÏÁ;Ÿ?Þõ¼ó9ð÷]ÏÁ;Ÿ¿àõ¼ó9ð"^ÏÁ;Ÿï¹õ¼ó9ð­[ÏÁ;Ÿ¡zÞùx°¯çàÏ÷ôzÞùøV¯çà»Sõ¼óuà‘½žƒw>\ñzÞùZáqtä0ZM¼ó9ð;V¯ƒw¾V¸sõŽnrôÜæÍ;Ÿž=ï|8wõ–‹g{ÖÃ'0ï|ø(õÞ[î Íÿ¤žƒw¾=|óÎ×'¥^‡å6ÚpPê9xçkE ¢^+ï|8¿õ– lkíá˜w¾£uÓÃjOØðÑê9,OÍæ@©žÃêŸÙ~À«ç°Ú6GÏ Òiõ]¼ 9 7Å\x£ —?›ûþPñ~Àzæ¦YýÙs`ô1ÑtYnó@U7eÁ„Õ°éÙ¼FQ3Áßu©ä@(zÑßvQ±€í¯išåƒqàjjCH,…&1ý¤|Ót–åøˆË°ƒà7\ª±éŒÜ„¤MÔoÏ8S¿½û3¥õö£®"o?m1âúé¢"’q³.»b^6ë.æG³Ø¦ÚŒÍºLe4+ÐO1„>Ë7ýÖ…­?J6\Öûs-‰ñQ5€K3 §¨hÄ rë¬ËÎ@ü<Å\œZŽbÚ”§ÆG‚˜x ŽFêGq:Aa\iK¢c ž$1 õ‚•àUk.p9ÄĨ{0L„õ ¦—Ø ƒa{˜„Ál¿u ¦î‚Ôo¤Û\ÀAÉzRuášRd†2—E†¡W¤Þa\Pа‡Ñï"uGQµDžá¨ï”¨{8þþJ(«Q–¤–"¦%Xö#`ý•Ø”#äLY(zè¤D#¸®BâÉ6(³iFb§L=#Ù.eØÛ#aô”aAŒÄ]q™ºFRw™=2 F`fä(p™žbvÊ\|Gó®ÂæÍ§Bßö§þ ì¢ý™¥ ýÛÆm…ÞŽa†`€9)ÞcNrdÏl#°T³ÙRfƒEL¢i•ç·Åq@Õõ1ºShšÚÄ1QwÆé±ÞŒ“ÝxÆIKOUCó nÑ8¦ŽóT³= aÌô0.îÆã\ݰ$’øÞîê·Ý(ù½v z&µþñÚÕšîñ8ʘ’ñÂóêþAÚZÚ6‰'¡i9H+\õ,Þ¦¶ÕÁÚ ºùÌ`k¬ûªî°‡°…ðªt181r&oø¡¤“«;ÿèØN`ŠÐ’’ÙÅÑ‘ljfâHç;Pjêa‚¾œœXâ£@¶Âõ­zÛ¹3'ÔÛ¢@||Ññ9ìœ;i=+°{æò¦À¬ÎEÉ»ÀŒÎÓæ×l΃k 8Š!ž)°Žièå|j.Ð,.éÃx´Eú¿äQ¤ï P÷(²Ž¥Æ"ú‚ÇÒ·"=?–¹’ÿ‘h|ò"`!›¿HÝ Ù5Eê^(¯âÐ.’v²vÒbvû‹åéFó¶k$µ˜X‰‡VU‰]tœ‡úsâ8ŽAÇÁ_-Ñããäu[;ù8îË%úý8æ%ˆäø÷Å»åø÷E:ôîM‡Ù&6 *Û4¨RkšÝ¦!ú»é(y5=.ʆ’õ|'É?»‹²¯Ø¿6š"Ñã7FY$Ö,±ÛO § Òt§Ôž:Q{F;à$â쟥òí¥=žx·+öÅÓ˜À"užƒîT‰~= Ásðtê.±ÛŸÁ¤¹ d_b"W¼Kì’Uìö{e·aç¹h†–™s™—2ùÏ›”Ùe«™ù2}^ (ƒmV³›ÊÔ±FHTøf-X©Â¾^ËÝ·B/Ï‹UèÃp+ôñ.úwý‰®ƒQ_¬ƒ;RaîžÉ^¬€ž Ú¬°gŸ †š|!u70‡²ïØ{¢!ÑÀ<\(ï†Úk˜‹æú"pBûì"½W¹5ПÜäØù󦑼›à#4Ò‡Mà„FvʳðÒÈyZUìÎKèc#øäôÕ™ÇK¨±‘=±Þm#5l6±W.¥ïMôs{à2]u”ë2uý}6sÕDŸÍœ7‘÷r. M`»ç°/ú1Ï¡fÝ_¢•xDïÇx.Ø”«ËsÑí~x.ûº˜ò¹ÌG?r=œÒ9|Þâ}ý¼/DÜXbGu6‹RskwÚýI†¿ÂëNÈ7´¦)Û»±-Û×Ú Ù¾ŽuÉ)»]@v†¾ ŸßV!ImŽ­lîQ[u±WåmTë!ŠNV-BÈÏ‚Ô6|¾T µÁž¯Z´‘ž/æ‚&ô & ÆßlNXWp%f£_Açc&ÿ ¡cMî•l%Ô¯Då…»+Ù8\®Ôf×ÄmCÝ›Ò6XÇ8@Û&|mÆmlž˜Mµ ʾŠM³ù®b„ÙðW±QØìW´@W Yjâ®æj‘°®æòŸPçÕ6WASbgÇà å‹uòÈ0÷…u#ÅÜ`24S½ËË”©~‡ÑS¤¾]³­yØ.gš‡í/ŽëÞîÔ¢].š½íºrkÖ®QêÑ5bh‹]#¦¶× @5x8|¶ë ¤¨¯Ð Ùž¸­{!¬iPÔ Ù` ùj¶Ô“RìÛÊ¿fð…°Ü`F¿§V\<^;%y€1 s;tÉTv,Wyù^IoE;ØwtìźiÚ^,> öçK´H…c^ªû¸¦õ¥ê”:öRð1¿ŒI@æèeÂwšþ—Ñ pÛOWüSi/Ñ#7qš£¼~§ùý<êß)‹"ʶSuðB¿Â¯ l§Wíj‡¿B<m“Wˆ¿¦mòJÝz5=¯D§›ú®#ζ¹ŽœàÉët©Ô»WI2_›êUà‘„ú^­‹¥¶É«õN8êÕìcðâ«é5ºE7 oÎEòµLl~¿–mÆÝâuà±Óõ:xpÒëÁÖê=[¬~»¯jàÂ7衹xýãÞð†kã¹xõÎyIu.ò-ÎÛ C¤û,Eäæ÷F½Ñ̼Q:Rªäò'¢ÚÞ¨ö9˜#ÍèÁÕÜÞÞ¤ùQßv¹{¢¾Aê÷.qc4'»´™ÔÇ7‹S¢ôÓòR®š~zLØu¸+ßO‹= .ü´î‘šÞŸGóÓbU o¼E˜F•¾E /!°·èB¥ ËMb )ß$½ª¿Iê<šº›˜X.Y7é"!ÄÿV6¥¾UØI»ð­ 1. o¥N. oE6ÿÛ´Ë5eo££¨Ï¼ ·ôì¾·q©àÊ÷v]ó´7ß.|¡ õvÔ-Ào×¥Axãf¦+aRnæ*šÐÏ›Ùïܸo~y<7ã“ÆM@z׋¹ç—sõh!±FNE]yݬÜüݸ–w OO“¿ º ïT~UÿNÍ¥ºüNé©ËïÔÍT]~§.:êò;ÅÿN~—xúš®[¤1¢.ß"MšªŸ¶Ôm÷gtÔý,÷.ÐÛÏÂI¼}Hö÷»…êTÏ»ÁãLÍ»uÕ>¼Õ´kÎ4DŽ»ûôç„Ö4­?Çôöóº­ +ü<È„ûß/è¾¢é¿M7Rí™÷ÐPÚ{˜nï᎒П_äž°·‘]žÐ§_„³È¾ý%¶ƒ9q)†Ê{¹«p‡yu˜ƒ÷ˆØ¿ïcW±ß-°UÞÏ®*П莣ûÂíÜû¸~ÎðCx(Òﳑ¸~´[dÿßÁ¬qÿ»c·x2ï8Ôa¢ì¶ÍÖ1“œÞÔžB¢g¦ñb!Ƴy»ÞÅÁ+æw‡öÊÆ ùˆ.ºêàGàV0¡¿¬ Ô½_f 3¡VG~åÒ¸#¿réÌö+wÄ>®ZÝþâ: ¿ £'q7þÆÕþ×®^®̡ܦ»é±XÞbCjá»-Ä4²3`(pùÑ`µq˜DW?Ð$7F»®9rY`bì.][LŒÂŸ;V1fƒ{³È p ¯°ÊÏ‹'Ò0†¸ê]¢+ »IÛ–L”Œg4º=?žNX3ÑÒx.u¹aÑjÑÅZº³Ô†ƒ£ÌB/˜V;;Fc–yþºû‚}”¡K€o7Ñ5f[ }àú…BÙ¿ÜN.pùѪ—X4H¸ŒqåX"†eëº.pOð›{61¶øœªØ è¥c+€×©­Óã˜ç³•|*‹~×õäwÜwJFç°†eQß`–³hmÀSÎ^ ¬ÁvÍ^ £Á¶É^pS­å`:k9Pĵf/àD×r v¦Ê^À7g/àƒ€ ³0I؄٠Ø_µZÙÌiö‚Ë}­zô&غ٠¸*µl#6pö‚ L-·%f6{Á-š‹Oö‚ ÇÖÍ^p%e/Äl1x6{ÁÕ<»+ð‚­É&Ï^p}bÿg/¸³±ù³\gk½gƒP²(\Ö^À©½@]‚-—½@K¢V|höŽ{/{CE´ìz¡è™f/`€e²ð`šg/¸ýs±È^èšÙñu‰Ú ´$j/pÕT{¾lm‚Q?çÆ’½Ð­·£C\éj“« 6(ñsÍÈ^p-«Í4—¿ÚÜ£QÛÓ0cjÕ£7Ám&{ÁE±61èqÔ®k\Kì{úöP튵è_Ô^ @Q{ND­Ó\Lk}årÒÍ^ .^Û¦èQƒ€³¨^r1Ê^ 7Q›NÜrÔP\…ÚÄ ŒYC hßéÈ^àH¤¶óЭö×û‚ k-ºµ[#*Þ¦¹}[«6Ó(;×ÜôÚn@eºÖE¼¼Ô:ÍE¹†ZÐî¬íüÔºˆæf­V”³kÛ ¼ >{š­õ ¬[Cc áÚQ׿¬Í-"{ ¯!$ðy­‹\zj‹×$:ŵmâsmO£ýQCQ¨ÝrÉ´/@ÛÏtïþС~X<\Yfj‚cÝXÜÕV‹¿dÅâ ¹KV,Öh æìKw B9À_²bÝXÜ-(ÖÅ)ĺ±ðNŽucq—Ò6˜¿”ƺ«‘½¿¬MuãÆZCd¸JÊ6ýäÊb´Úye½@åsN†5–«qÇðH3Âã̪$ù–mN|UÈH|¥Å¹vwŒÆôýÓÓWn?§?þ4‹›ù·ž‰:®ÌG­óLOí³U»›0yµÍÈ\Ör0µ5ÅL×ö;Ï-7{Á>Èv /Ø5lÌ.©UÏž©a n}YV®XØ>x+B2Ú²1øÕXŒYøˆ0|ð“)´ ó/Gã­7ç]{þ;ú­±¼3æ^G6É£!‹6ºÔ1èïŸ1w¼pÆ\ С…Ÿ…‡Ê˜+̸˜û~×b.0ÕàAÂeйfÀ½ÅàÕ…0æ‚Ö-¼.ãS f>ÓtOA“7æÒ‚~/¬9´~c®3ÆV:ø]ƒé‹ö†n=ÆÃœü«é>3!1—#v4¬_6t,Ææ-æÅfŽÅIƒµ§Û9æªÅ6޹w±‰c.alaü…±c®glߘ»›7–J ¬@سڸ±ºcÇҲР;æN‡—«˜›#~»b.—pVc®™øàŠ¥n£­ _Q1×qX´±˜ƒÚ¿1WXüP¡ƒ¬˜k-\ט‹/ºý±¸qÒü¥¢#´K³@8&†}€¦}ÌÍv”tÐ]Å¡CoCœ< Äðð3€Â^bØ °wc8x0ˆÅµ–ƒfs,F5Ú&°~aÃC§CwXü6ÅèkÂá‹¥ã"˲°)<=¼ÄðoÐüˆaæàa †³ƒ/ôð‹ÛïO ô¨cv;Ìé^(bz*ÜòÑ´NÄ|CáÇyãIØ‘pñVu!HØÏxY€‹ÿ›D yÝ1;u‰H@cø}‰w"$§»FîÁLöDËV&~éµè~’ˆÑ©ËJ"?麹$BnºÆ$b¬ëN“pÙŠ¥OÂ.F'4‡GJ8}º%bŒêR”ˆÇ§üÅX¾ÍáÞëî”È/:º&hOh—'B}Úå‰ôp´Ë9»<£~1HP»<á^Å.OÀÞìòDžÇµËa“²ËùÛ†÷ˆÞŒvy’f—£cÁ.O„´ËaíòD˜A»]vy"Ì ]ž3h—' ÚåðšÙå‰0ƒvy"Ì;Ì€>˜A»<fÐ.O„´ËaíòD˜A»<fÐ.O„´ËaírxìòD˜A»<fÐ.O„´ËaѰËaøÓ`íòD˜A»\ܳËaíòD˜A»<f€ÝfÐ.O„ðx fÐ.O„´ËÑõ`—' Úå‰0,0Ì0l0\0¼R0ƒvy"Ì ]ž3h—' Úå‰0ƒv9êìòD˜A»<f€‰f@wÌ ]ž3h—' Úå‰0ú6`íòD˜A»<fÐ.O„´ËaíòD˜A»<fÐ.O„´ËaíòD˜A»<fÐ.O„´ËaíòD˜A»<fÐ.O„àÕ‚Ð?3 ÓfÐ.O„´Ëax3puî ìòÌÀ.‡Ï.OÀ ìòÌÀ.OÀ ìrøñìòÌÀ.O¤î¥]ž€Øåð|Ùå ˜]ž3À 3 fÐ.O„Ð 3À3h—' Úå‰0ƒvy"Ì ]ž3ÀÓ3h—' pÁÀ Úå‰0ƒv9*ìòD˜A»<fÐ.O„P$3h—' Úå‰0:1`ír”ËØå‰0ƒvy"Ì ]ž3h—Ã_f—' XŸ3h—' Úå‰0ƒvy"Ì€5k0ƒvy"Ì ]Ž®»<fÐ.O„´ËaírxÑìòD˜A»<fÀß0˜A»<fÐ.O„Ð+3ÀV3h—£oÃ.O„ðG fÐ.O„´ËaÜÀ hY´ËaírØ?Úå\1Ðwû ×D¦V[¾[&[Ž[ö[^[ÆÇ¯»»{žk}Ñi@Ü_GÌvŽå[‘ÀžÍÝç~:Îl~ž¡Ã6‚[BŒÍóÄ1wñRsF¹¹ý°=à´ƒ#’qî¸.²ªéôw»2š(ÕqÉIÄ8cZ.¹˜X<í®C»âžñKÄÉ¡Jö Ì:Áî€?DŒ=ñÛÆb'ü:1á8(‰KÜ®˜õßU/Ó¼+²Ð]—Tµ¾æ»˜íÖ1¡[pøèÜ.ºeY~t Í-X?óMèÖ§\÷m·àÑ9ºå»H·|‡èÖÝ¡[¿áúb»õ®/†g™\¯¾X†”"ǹn©ú:ÊÝÅ´ñ›çbªQ±¹.&¤ Øœp×íbv'°¯`Ô5覈ÓgîƒýÇu‘ØŸ¸ÊlìO]e6ög®2û²«Ì„k¶»'ù®{v6ààQ/³7óÀTc~+î}O'\³•ˆË,i×™éaNr_°Rk7FXíÇ‚|G¸w_Ë~ÓìšZ3_ܶ,1súÄéɶÛS-‰©F<*Ïiª©]’ª]Ö61|MYå|«tÜXlIÏ7.ʹ¡tÜø(çÆÒqG ô´±¦)yи1QÎM¥ã&D9w”Ž/Žrî,?*ÊùeéøÑQξXWÜ\žldaÍù†%+©®|ul´3Ê}ip})œgaӖ¬ésçE9Ï©šÎAëdoD;Ê=^þõ¥j VK–í¢š†foIËW…T&¨}¾)Õ^V&ªý~I&:#澆 JÅ›iÕ=BÛ1ž—º¹º…Ù¶Py†½‰òïv/4ðoTc6GSÓÃílñ—_#»[›;ZZR­Ä- XÏ-d•úu´´/îÆ"y¡ïÇú¦ô£Ò2×,U©ÑÓ”Ž6ë~ Θ^1/ÊV:fT1¯) K¬†¥U‹ªcŽ*d=~Þš6®¨®ž± ‘-«àêÍNÄuܱðDUªu+ŠË8Ý»¼2õeÐK”ÿ²ø¹ì^øz5ï qˆ)\ú\å¬GW_Y^=gÁ¬Y½ñ…sç•síNã§VVUÌSFŽ ÒoΘ_Î~x—Ú¸ž½ü\&­øÞšÖ¥µQîû„ì¢Üˈ 6}ÏË¢œöö½ÐiÑó G¹Ç4';éÏ"f, Ù’W­ã*—cîEO¦s{`†lö¥ä˜üÆOÙÍyirJßaIwù— vïv{¼ÿ©ë©ƒ—•/µtÜSæ2 Ä/ËŒ˜™®Î×êÒÓÚ—50 «KÇŒf)·ÛË*Ö‘cZ”Ûȧpñ/ZÑJ·Bñ²"À÷yò?ÖÑ…µ ‰“|òΡHæê¥³í¥cÆG¹‡•Ž-åÎçÌ(÷9|ΊrGòyD”û\>Œr‹ølrŸÇ§zsŠ·ö¸gcÝÄ£‹[bœ¬ï÷ô×rÙòØÑ_T0ƒ±½½¹tÎzÜ#~¼·RØê{sÎb„ãV.mì`ÿyÚ=™3P7=³{­k2ù$+ž²\Üoů#ã2,3[©Ò—ÿ¾/}çtôæWú¦€Â‹Zjšqu·gò“Ëÿݽ0Ka}s}꾊Šõ¤ß„‰¼çг‹¢Ü·Å€è‘!•Çý¬Í6¡3"ç I»K_ýpKkêêZ!2iq_:UZ˜v€Yo£ôCଶxbéØÑ¬·_+Ë1ªø%>µ×~Oíµ»ùÔ]îo(ö{ ¨Õ½KøT÷6ó©îmásv”ûšÒqÚæ×ò©*^Ƨªx9Ÿªâ§øT;ùT¯àSU¼’OUqŸªâz>UÅ»¸Û©Š[øT?çªøY>u±»¾èÉm.Íûs™…Ë´ŠzW€Kïö/À¥Ü"ÿÄPÈSùpSJ^ðu 2¶§q©½P—W›cƵ ¢¼oì/«nÖådf-'.WÑ)÷<ù„Ð…½î¨q—t´´W'›k–è‚÷n†E³6³t| ³6‹OÍÚ|jÖŽäS³ÖΧfmjéø taŸšµé|jÖfð©‰UúÙT¡ô³©BégS…ÒϦ ¥ŸM³ùTƒK(¦Š!|ªŠV>UÅP>UÅ0>UÅp>UÅ>UÅH>UÅ(>UÅ~|ªŠ¥G°oUö‘€q•}$\e9Š*ŽäSU´ó©*fó©*æð©*æò©*æñ©*–—Î-Vñ©*ÎàSUœÉ§ªø#?¸—ë̲g¡¯ð!lV>FUYu¦þ£œÓâ€;Týn2ÅÄ®p,B…í(w!ÕªY[zÄtâë|ªßàSø;>Õ‰¿çS)¾É§úù|ªŸÿȧúùO|ªŸßâSýÔPµS…†ª*4TíT¡¡j§ Uûب «¨­½µ¶ ¹˜ç5¶%“0¨î,ª¯sÈ0Êû¤ƒQÁQEØL+’ÇfFùoŠj”?ž2¯K×èX§›â¢º†VÚÍ®)ü/ðfxµOJÕE¿`Åc-OÒð³Î*-aêË×z§é2ëI{6ù4¯)-Ô¸ÏipƦ< µ+¿c®nMêŒë&º§Æx•;§š£eñ-T¨‰›SZ¢Á›Ë§oŸߣøÔøͧ˜ ‹\> "•š¾€OÍöÓJ'hã皸î6û£üÊÜù8ÊÿRœJèiSMû²(÷oK'Œ…Hqû~ôK'•Ž*f—^¦ïö(¯Kß³£¼3ù_¯ïiQÞõ==Êû º‘ƒþï‰ fëÇ^è£iµPo”E‘3˜/.ŸÜ6uÙ1/*û´ÑÈåõDÖSLù tv 26rô½0Ê?ˆÐ¥ R¿Bà•÷¸Di*$bÏØ[‰éð©š‹âЄ´¼J’„Îk<Ñe‹{\ðbw¹}µªð×ùÔ,ýBߊSß³¢üÓª«çUUU ë(ï—JpD”÷+}‹Qò†t¢ŽK_é×Ê ™ú–¾gC°K3uÝþJw(ÉLX‡õ$î X<é÷^m‹—üÞ"nqôïéVV<¾LâÝÿ°ÃŠ_~à°’Üuÿ‰¯eûm2ž²Õ³oT¿Åpüž'œG{Ü5r刭{’Ô´ž´—Å_¢6• Ù³ØXCõ-²äýO¸XޝŒOØpLJ»)½Þ}ËÇĸ?˜=ŽòöPRHÕ{]'ïßfž8Ê{森ˆKãu;\zñ£.†KGз#hz»¾gFùï{Ð=p”7A‰„{çê[8iž¾Û!›>h«7Ê;RI¢Îà[ð¿tœ¾E(8èß}æêIrµì)úžÕä?™°-½@™…XÎÑw{”ÿ‘íÊFy/R"õïR¾ux(ÿäA_¯QÞr%:¼\ß3£¼•úÖÔX º×ìªAŸBÏ¥ŸÜ†t4Llkhr·‚ókj“¬ÄèG[ͦ–]·²'QÎíbàÙbO\‚Å_êéÅK^Â}€LG÷F“׃AK•<ÑwtÛÔE•1¥²H¡*aÞZ‘ÓËËfUUÌ.¯®¬ÀÓûoêÉŠòEUÕóç”UΟ9·ªzÚÌòiÇD¯ÒË3.«^P9½¬ª¼ºbNUù¼ã`»ÄgêåÉs¡º¬,ŸS6uVùtN¦æÍâÙÕó+^PÎÖTzêìêʲ*d@¿àà ¦OŸW>ŸV|ËW—&‰¾ 'âÔèÅ4{òÉÌ“éöä×2OfØS}23~RøÇÞZ|Ñ…»{ËI_Ýß[Qúª¡·(ÿªx§^4uz54ŸÊfUO/ŸUv|”s¸¶¬l>£b_÷ó¯`Éì áãfÍ­¬<¾zÚìé>÷ŽÌ³¼9Ó%‹ÞÞûʶùòÞ'&Krdï“åUeU èÜo…GQÎÛ2Ñc3åU_Ùò®è}bË{_ï_^ÞÆcÁ+DT•3ü§,ޏø4‹Ÿdñé?Ùâ3âx”ëóK®Ç§–6–Ï*ª­O(Iö´ÖeLãâ9hH¼=]núäéŠÓ'oN>9/]Ë s5Ý*zyº–ôɺt-é“‹Òµ¤OV÷×¢®­è¯EOÖ÷×¢'ûkÑ ï–L-2†\¼ºtÇôÐ¥ûÝþþÙgé:J{·¼² †xGçxTظÃMª¶þ®™TÙ†©<þñ3©Îè—IuW·xTö ÈzeakÉ B»ì»²¯"ë˜KèBÚ4—ÐfÖ7—ð­s §nìžKè‘VÚ@÷.Ûu.áÉs¹D¹ö·Ð>+}o ƒ.¹ûä té²6ÕÒyøíÛçÒùU˜vÏ¥û»þæÙg‰»'…Þ[1wþôòªòiUDìh`þ6yÅ@Câû[?s Ÿ!ñû›Ÿ?ÐÙØ¯ ßÞümÁƒè ž^6‡4°Á¥¬Õ óÇ…;6¢ÃÚœ»H ©wïøjê¥1¤~çFäR· Èüqt–/ÔÍŸúJn ™'öpdΊOϤ07-óĦxµÅgdR¼$ýĦ0DÅgfR\›~bÁ¤YËæU§sä¹³æÎ›]VåÏгã8u.Ÿ6¯¼|N”ïJ±A¶’„¤xpÂØ±Å3UÏ_PY9w‡sà;¥|á̲yœ^N8®Ü¿Œ–ëåÒ¹G;é‘SÊf#?bŽ¡<ÑQà8ŒÅÏÒƒEåS}4óTMVz³ëÛÉsçÇ}+ßœŽŸ0»ìhª¹0ý€C¬HL§Åå-˜>fôÔŠ*Þ5³b7W”ðÎTÊxvÃp|”ïÆ®úªyÓ‘£èxå9LwìܹY¨õÒSË®zË+ŽŽOÀ¥WÆGÝS°7N˜¸ºm|ñì¹óŽGz+}aÎÃÇ•M£ÿkÓUÌGÄÇÜLÜ]M—•Í+›5 ¸P™yzê‚9̼¸¶Äæ#adæÌÄO_0GÓ"B”ï§°ÈN®ž6kî´cž‚ÖW\ª‹â[÷ëâñž~Læô3'ýÄžÛÄTÌ^è€fo{&|rÙ4—¡ân æÉ⪙l“¨`ÏÞ:¨FW¤_héœ ý yZ1Ý:vÔøtbwÈ5ON®˜^áômbwñ4oÎb›7ÑŠôM·M3¸/µÙnñ}©ísö©—–ǬÅîškÞÈü8£$ sMç»óÙ,—à¤òã§ÎeÙ¢‘¡Å½¬b²bWö½dŸè}"FÂJ)ܼ„ª.à"g†{ÁücªgÌOJfñV¾/µ…3ç Kk•'î¼²°r[9'ƒßt‹)ÄëW—-Šr^“ŽKÔôÕD5€ÌDݞɴ !£4º¼ñŸ,“¢f$í[e2#d¢'Wøèòò£«§q0§hÿ@÷–ò´Þb”݉Ï?X̃@ýù×*ÿmïƒãY‡õ>X:½Š­9Sû'z§ ?ž÷+§–͸Ÿ¾YZ1’Hì. <:!“ÈlÛôMTžœîôq³Êhƒ=²e”L2voÎd*Ç#¨>’:ÙŸö?Z€ÖšE›y¢“1°Úñætr¿¶ÿoáànœZÉ^ÌFÞ¾:•ìæ|š¿YÄ›¿È®7vçoVðfRÿ›å¼iîóTÞ˜óOè®Þd ǾYÆ›Cûß,œåÔø7‹æ¡&”2t„BzÎ!dËgÑ< .ÈD¥8fè 6zd”ãŽÑDW(SºÂVÌC§Ìb~•^™a]بªHwì Uñt]¨Î<#UgVf¢ê̪LTõ¦]H½ö¶g 5éÞ.f…G:|ÿ† Ëȸ‘.X°h*ÄmXŠ‘/¬¥D>*y>|œJRðaÁ1\ÒJ dZYY>gºC.OKg=ýØQ°ªN‹²öí}2=~c¸æP‚=Å¥6¨yyù,Ž§Ì¨8:`gËÇâ© ó2øAÚ¬ÇÎ+jWë劙,í™%åÕ³¸åHÒrÀŒÂRüZQ=wêóÝ KËxE>®#€€øG2¶¥êúµÌƒåUó\ÛîÖ“¥T]X†àÚêÖ§bå¼¥¡¢•±¢–ä.Ïm;ÑK/mEnKDgËa‹ &Ä*¢M?½.)½.øîF<,¾€NèöF÷¤ø3G‹®¼²©¦3ŽŒ÷Â9å_×.KÁ§…oKC;²ñ;ÒD9¾JX”s,"QÎScZ©håMÆI”Nõæ¤"žGv—W%®\ÒÐŽÈÀ€ye «§_ä*¼”©KO<чæëRF\ƒºÀ_¶S‹š©s€ëcZGa=Èõ,·µ„B’yº‚,fßë6R~­Xt+ʦV/„)pêÂ(§â Z¦ŽGù"óåÔ@éÒ]J WFù«ˆŸG ˯j?–£ü#ZÆŒvWµÀ‰U TÑRâ¾oY’J5F¹/Y‚hˆåÏKbÃðæ%®QY⸖½ H80륿Qz³¾å-j~ZºFw„öiŒÓFØ«ÝLMÉלQ[-ó)›ÒÙªAxâÕƒêM=õ Ê"½™Øj±¿ô–ÒQ£Ðñˆ–üÏ^N©š;-Ê¿rGû+7lan_ô wô€œÔç?Hr-ôÏ4ÚøuÿNÞ§lg _ü õ¸|ÕcÒBÑ—žP¯‰§þ»½ïœ‡ñ(Ï©HGùa —ߨ±Vþе>Lž ¤×‡”º~¨=g+ÂX†jüñÎÙ~ô´>h"ÇM?Q˲UaS€ªŽGOûyÎpôô Vוïn\W~(èyÈ*_Ô/ìwYçøÉ¶wEé¿)êj”ó·Ë‘z_U%R“¾«RäêAšz¶Sáç^†É/ß%û ŠKo\¹)ý¶ÊOÉ ‹*J‰dƒä;êD®ÌPÈO¡¤þ9êÑ3¯*$1æÇ†\xG Œ7`à$Öo`?2“‘˜ïa5W6(élŠŸvÞÛ£á¨PK¾]QxZ ¨ŸF úf Q«¨N 92ù‘¦Œ« Ôu3‚ëïp†Ñ£á )Z¸?PµqUḪÞ$ý²û¡ÖÀ´¼¢ügtíªS›Luw šÿ+²Ø#S]¨^ªä?„ú®0ŒAPد lÿqyýP';ï šÜœlQCz*ç.”•÷ž;‘Ž‘E„ây8sж¹kÖÐYü (ó¿ýcaqŒØâË9ð}åÍy±8ºà…µ[2©…æ‹[“Q»½Etœ·²z0©¹5) Þ¨¶¼y¸Þbš3]²ƒ0©™[ªlúšœØ)ÇFÎ&5×£¶!AÎ’òkaÖÒÙ$Yw©õÇÚðå£Ùbäl°½(ZÌYx7õó“ÖÚÄ‹Ý;1ÍÞ„gí¡M¼¸bÎŒ¹QEU¹½5v'­Q´‰—Ï›‡`ò²Yö“&¼•5†‰W–Í©˜U%¬‡}¡‡²Ï01Œ]=$¿ï!uú ëbôÍÏ£ÍmkÇPClŽ©u„.bkZ—Gå'ºYÀ<v“$(ß:¢kXö…gÞÜs×™Ÿî¹óÌs{n_› ;kÿžK&±¯ç‚óÛ7\þ(ðÐ5¹û UXpj4¼ó þÝ6 G\Ç[÷}v FÚ1©ÐŽ5ƒm|žv>¶eñ~\TÙ5,çÂÓ¨{;uo§îSºÕ:ÝVÖ›þº6ÚKš¿®{Ýç’Ųcm+·Èe^y»+{2‹,†Í¢¥c6VY>ì¬)o~švæ•{»ÆºäÌçO3ø’ngÇÌ%#ilV(oÞY³„)¦æ^Èn¶¢òºZ»ÌÏvN©¯Áf{M@7MÄУCï1/`wVoïÝeÇíOŒ;aÀ@S6´uæôè|«Os`ŒãhL†¶Ìøu«{nKϹLR¤s¬)عw´÷Àw{W”èÆTE;SÔ¾þY]%79©v'È’À\æ\ñëå#`k× ׿D‰µ9;]GÞ¨„¼éüßæü˜ú}°#]‡l:LÀ …Ù-2xáßQÏuŸ‰ÈÕtݤüÆ|ðY] oÊŸ8,–u÷,Sí½»g;óPÝ?LV~Gy=éYîÊB_n`¥ªÍö — ÆÕT‹ Û-†…«E–ƒW+ÊÛä‰ÉÌñV{ÇþØf1Œbí {îF‹a~â¶ðî®ðîÛg¡Xäw“š{6[pÅßxìL~Išºcµ/ìÎ߬¿É÷_›Å8'Nïf†wómGjZ;w¤ÙM~GškƒÛ‘ô¬Á0 †-ÀOz3òÛå íEQpû +7ê–?G~[ûíÃY=7ÙNÛ5‰Q›‹E† ,q툻ÝÁ>>ÙÆe†]–îí´¹gG‰I˜™»ˆÝ!ûsA£z¿´›Îs\P ­Ý/‹>çuT½ cÙÛ¦ëÒo… ç~’ýóÔguMzÿodíJï¡[­'|O³{V±vz ý˜öæÊDÁ¸ÒÕì8½Kw¦bÚcëØc«´Ç>@ß«» teåºÝeΰݻ+ÛK~w•üîbî¦Ú>ÁÐÆL‹ahc]ˆ]vÝmaÞa90½qwÈ÷%Ûà¨îƒmÌ2ÀÇíg)Þì®”GÇ6ËF?­Ø×vPEÝÄ„á¢)µµ#—'FM]\<úy£ô¯mTÉÄ1Å‹Ç$–@¸Ú˜\™(ïlI¤Ýak‚Öÿ„ZF?+ÙÅË’™V¯LÀãjãÔІ›åÝ8˜J×§FYÜypçH"Ótß—¼ôȃë¢ X=X[cOi÷Ž~ÚzL­Ÿaf{Ú㣟–ÈôcÔ®ý´™tó°é m'&R͉v´ò×¶SûáÔñ¾¿±|˜nà  0Ãè§Ñ#ó¼­–>]ÜÎ4\–Lœ”lM%¼IƒÍ#Î Áä-uF ¨WÖÞfƶÒ\M‡©ã2°¡.¡º5£ÖæVG[&Ö&ä¢íЃÛõ3Ši8Œ“hŸ¨—‹ÔĬ“裟ùŒå¬æµ3F?mÚtÇv÷<í¶EÆÅÖ˜Swmã꺙œâ{©ki•<ÍúŠú!lFÝýÈraÅ‹Â_£Ÿ6[wÂ63tÐÖМ˜6ý¹êé~tå•–{$˜8†W}é´HÊTÇF—s2c$.àÆHvm+Ú—%ÜÒ$rF¾—ˆ ¶ùäiv÷!í¶P¦Ç6ÜF?mÔÄD…nhL`M ­¸³ž¼[R h+ÌÿÅÍu6Èl36YØJá¾¥ûÄè§5§š“Ñç>÷9{k 7[o£ŸÖ¨1Ö¯·Ý†IBnw²£·çÕø}€y?lÖÊ&Ìè§±t6¶5:¡ì0ˆjÊ–ý {ã(#bóo£Ÿ65ÅXIÛÖóX:ç¦sa.…\ºõäZÎ…ÌÊÎLo®5­©&å3}5F­¸ÑOc`ü; —pk‘MšÑOCn×ÏvP°í)5£Ÿ“„Ú !nI´qÕ1û’$ˆbm퉉†¶ÄÁm1#ÔãX]ÍZuÌ–™•ÑOŽýà¹=5;u¯¯¦ºíàÃí0e¶c¼e;ö* Þ\Í÷ÕįæÝU m¬ýnçÝ6noßÎ9ÍÁ¤ÎLçHvªYXóŠu§vwD‰Õ§E{¯>#ÚÝ皌YÍù§Fåíø·Ûàûlí~Wá%uÏ:‹÷¶¿5ï'oyCݳÎV¶žö®Âu¹Ï:Ë0ôhb¯¶XËšÜg­˜z±ìäœw–`¸çÌÏæOYwÕ³ÎZwë³ÞôªaÏ:Û×¥ïÉÂ̦¾UÔ¿þd±WûØ §=ëì‰!œsÖ³º&†·ÞcòûnÓŒÌf«k>n(©‰Kà}Qoµw«Z ×äÄ}Q&+OŠÉu+5÷%]ûÚŸþ¬³»N>0{WNº×Û&Ò/꽘^è]µÍ<µ´c.¨Í¾­¸5ÿÔ¢®õï*LçèÍ'QÏ7ç,ŽY­Øm¹ªçìt?V?ëMU‹s¢×ò­Y(Üf½)‡Þ¼zh…Þds|IáÚÓžµVó:ûKÏê ³ºF³*‘ÍÖ‰Ümæ`¨èÌ+éÕšhÑDÝuØm«ÞZ¨ï­‹÷,œ8~5î›û¬® °"$Oó©tÑ©…ñ^ˆên‹êw¡fµ¼ÆåÚÄZ½ÓŪi掶Ä-t‚Ïu&÷ÑÑN—ž|M¶ú:Z9Û›ã|áþÞù7r¢Ü…îžðѲnØ õ>Ì?5k‘ßëí ­3??¥„ B:g: t÷tÓ@-ÜMõnËÆwÜî7G÷îljÒÞVÏÛμ2ÊÝøæKѰ7;ë¢GÆ÷ÙÖ‘1_ 9î£f#ïcè!»ÓÌ™nÇ[뢢nv0s¦žDô$½›:¶Ñߎ:¶aXjÛ÷£ƒÒõ<ú^Â|ó7Ï›0PÁÕ׎᧞yKæÛ·Á5«y³ú]ÜÀ›Ú{ã7äì´¶?þ†þø7Ä“JvLœž‹ÕÙ•]¹» r]ÁÝ]¹{|Àå*Ä3·#7»R¾Ì=\¦¡ò>uìºÞš^¾¹¦äÕ4ü¤Í5«©pOMcJ6×4â÷5­ÊììœC0B¿ovï>å§àr·d̪wŸÌýà­êèÞ'ýØ{·ú^Φ–­u-E½w^aú°ÔÕ(X½{}çi;µÄ;bSѦ½³n§.Þ­suÈTVï,˜:Ô+ÍX“õ+½më{‚Ë/sZûò.Oµöd„|œ™>_ÛkxSÌÙ_“]Üÿ~fÿûöþø¼þøüþø¢þø’Þø ¹Ù³úâk²g÷¿_Ö_ÑÛÓ[ë²ëßP·Óâþy;»?¾¦?¾®?ÿfn[ß››vªéÏq^ü¢‰ãn1-9qÿ7óÿú.æ4ûyÛ/‹…“3ŒüÍ[cžC²è>,ÙØ8é. ”ø[šëÁôÃï¬*vÚ‘$L1ÿÔì}®Î]±bqÁ”ÅyÑmýï³:컑ÔxøÆ·êÑìó¢ÙoïìÓŠdþË½ßÆ¼õ|«r‹ºòf´XÎÑ›kݲ)7·—wÿÍýCÿîßüvì½o»ëÔì5p 9¸*z^ 3s‡å÷7¸Îº|ßÓYËû4nsNß÷zÎ6Í„¸0»1žóÀûöBÓõ¶F÷ÞÜåñô{àŽ1jûޏqÇŽð·ÊŸìˆƒ6׺kÇŽ8xsÿÙ¾#&üqGˆïÓ,Œ 7 ÚÍ®†C7׿{_Ÿù‰›súÞ×sNÚ¼'nÚ>þÖÛYçì{±…};gÓ[n{Ç”âîÆ¨t&¶×f“#½ï »˜ûžpÑÌË™Î}R ç+jŸÞÒU›uw£ÙU{äO™„ñº90uçÀFQ ×t·l¹í%'Ä8ë•`Ú—pÛMñÎ"r>p;Û4x;Ó}JïvïѹºGnŠÖ ¼›Mg\˜?å”ÅôM›VDÃ&wEgwßåìª]†M^`XNwƒk®×m¶•­ŽZØ­X4œØˆ…îfE¬y‚»‰êýGs§(ÇÖœ¬k»¢kJí-þøŽ©ëjjî†S 7£­Î$¼i(á;½éfëûF.œ¦éN±‹û[+1s;Ql)wóâÅÒî,Ýéîì†uÚÎmvÏž©½ÍïqÑÕî­î»óêr\έÝQqWÞ^ýyB ;Ü[Ý>ºkH6Öå 5,rou‡é®¡°±†,OZÃì÷ ¯7] Ï`ò‚4NÿvçœþíƒbÌ‘$6cækžíËÃz!´/ô¿ =lß’wU.oOÞÞ>h?Ì´œGéÖWÇ… êû†ÍµÀ/ µ$Ô²ts-ì­©¡–Âokqó6~Æk|.¸k·Ã¹1{³›{#žægáiÞ-žæûàõTyš?žy c1,ˆN¶6D=ç+¢·Z ;¢Ÿ ï¾e1,M¶eÞ%¾,N. ïnùnï¯ý*3¹û…ºû5†ØŽ»)ÄguˆoÛ²Ìbâ×¶t†Ÿ¶ÅsêÅ¡m9#³çZB}-[Ëwÿ 0—ƒJB,ŸÅAaþyq}‡ø~“ïìL_‡„yÒbùr¾Í¢8ÀC>j1ñ~‡\nuè:6ÄÏ4õÝeZRŒÈ´cnˆ Ö¬1í£¢±G;FzHºpSÌez] êóÚ1XZÖůŒmÕ³«ï×vÙN·æ’i.ÊÜ>t«\ÑÚÆÖºôrYÛºÅÑÜ?æ­vÞ>æÞk©ˆ+…~ÅÒP‰ÖF{§í>p ç•ßôv×1— -4tµªÖ©2ƒõŶ)G&Æá4+ ô¦èt“:ó¢Y°¶9Õ±tY¢­+@FNƒ÷¾?(“[^Úû™ÉÃbi Û$}ˆ&¯¶nD·m½ÌÛƒ;F&j–0¤’RHç=,ú mö´÷g+Œç² ‡Ý'Zás³ˆ™Ý*žö~3–æ«5¹Ýãr¡Ó5#6Üê4mï)SmnúB˜âFƒ@ÚSO{ÿ<µû\´lê¦'¦’os¢¨¨Èçcé·Æ&ÞŸö~EiœÌ,ILDÜá NŸ‡½‰Žˆ˜‰®.³n¬²†ïÔs=sù0‰:66þþ´÷ÏÒ*’E¢E çÃK çÖ1€ÏsÙŸý½å“[ƒW»ÓM@ÍABƒò€©=4]–U]~TÿÐüÐÅþiï¯,›vLy•Û‡ ÉæxCÿaË…ùmrI­ ÍŤÔsqA›ÚûÝ YÝTÇtL-IŒÀ«Â ÓÊiîòòªÃÜ ¤î/uKµù1¸ F=ßjþiʼnóʧ•95òå飹–_€Í’Íßjþ飕_c²t²»Ü˜ÛŸ[ ¯åžr·Í™KWÌ;~ Ý©]˜f?<6N_«c¦Õ±yôSçÍOàz©³ŠØj@´–9’áZ ³¬ÉM×ómùŸ1:$bù×òòŸ¶ |Aùô{Ûð;V‡•¢‰±ûZGZ§àäáÌò¶'Ṳ́R½igÙz°i?56ƒ_«g¶ÕsòÌAI®¯^…«í«)±}üZ ü|­àódµ¸³‚â׬”r©Av’k5»¡†es7öòkVWfTÖ”k5—ÞÇojã½–»É±¡ýjþ캳æ¡gèEϳgÅö÷kù§õçß»³t°pµ`E©Õ¡Ý)ôØÎL<&’èh2uHZ¹V‡0ÕÂe‰ sqÖó°ÐV>“=ýåÄÎÑ©¦Vv°­eßÎfU"¼çùÔêÐv=Ù»ˆÏ·d…ÚÔ æ{­íáj õEìj"¬™w1}j5hûݳg»üÐæ˜S]ܪùg:Ì©=~&~ Ž;~Ë6ïÆÖ!¤Ñ ’òg­íãî:ö.íÙÀŽÆS¬w×êñX¶£žú°­YÉ6XEv¾«µÌ¢Çò0"?&mØ®YxÌ\Ž®s*¥»Z~õÖšˆ8cžŸÕÞ9•S­è@jÐe°ZÑô`yyùÆÚϱ¼rY`ö±Ôu«yÛÙ£ì?ïÇïÀ^L-_Q uèT­c6õ/^Tޱmv{£§†ãçÌ_U1móÎ@'”YÛ°V‹æÓ3òä j¾œÌDFg9¬Y¹6;YºËµz4ë²åpŠ¼Ó´Í®˜6oî4üµtV¡­«éuð“Ħku?É’Ê)Ó§Ÿ¨˜=“(ÝWWF££YG¯Õ ütÂtPÁÞ2l€ôÊÁÔ êµ„¡\öb@ X³'de½–[óNý½; ×ì()ÈÔò‚“0”Ó†(óây 9”é¬áMV¦°ÑI»°Vƒ°ÑòYåå•›g=gú-[îÕ¼ ˜_Ù­` tfž#ÝarcP›¬ŒiVs«½x26b´Ž–ËßLÛÜJp¾ˆº@ˆ«“Ùÿ–]øZ-ÚKnùum i›K!-*lìtÖÔßj°7;EÌ€jM éû×`ÍGoHI‚ÑdE¯Vƒ¿‰yÈÙ“»ãì$]›kùSLß[€4Ä] Rf3}”ÕòZ ì$ð¸G½õájÀÔ8w#I‚×jð÷°ì4°{D7Y øG@›NOj5hOùv\nYÿ0=“½–ÛßϨ¿Xº0.ÎTì“Z )nïn€Ëwv¬´Ük¹ÞséÝQ{G7ST–Z ‹zïé4>tЀ“bkÂ<\™¨Ö´HøÔì~YÚ¦aé§MÕzú‹Ású+;ÿµ:4ÇkG˜*¬Q®Î¤­kjé"sK{ú@ ‹#âüõm«ipù1ÑV?g ¿î6ÿàÁ® üUæYÌŽxZþÅÂßÇ€r^eö­¬8Ôjß>Œ3,zªa¢§ Ô&zÆ'Yîe†ÏÈ­{b.°¼øÃ8k ¯ÇÇ.˜1£|㉠=4û™ÿ3ò g<†!FrŒû!ƒ!å.°V8ã! ‰þ2½Ów-¯°Åq³ÌŸÉöRv÷Î×­zÍÞPýµüÂv§ö4ßåWÏ ¶Ñ Ôòk÷åõ?pt5hîL5‡µ´ÛíîZ,s8»áÍÛ,¿æÝôPó_˯ÝF;®œÍ«‹ioµk Ðî©æ?޽%„zcÀÁl'™åóη¤¸:° Á,hÖê0xÞÕñÀNonÚ¿æ>¯}\«A;,­Á‚gY³ÂM×XùZ„ÌRØ V wZ-gp~ê,¤ét«C˜ÄÜÒ„Qjuh¿¥u2·4á¥ZK»:üÙâÑYàwNa¸Z-wqLöîè‘Ì­0f­î7µ›ûÞ„mM x,ú™ Ýé”jè¼B·Ü™èh5|Àj¶6œ.aíZ ›—‰°&Æ âʈ\‹yárâOOÂøO{,/œ¾¥=èëvð´÷Ç®ÆÒ·ºEÞ nO{ÿ˜ÑÏ• sbØv$Ÿí‰—ÜÆ‘ÜçÕÄäÕ]äiï5~K^}Öòêc4 u“yÚûK¶¤niÅÆ°Ù˜ÛÏh8¼eô/žö~qd?´ºçãÅÆ\˜^3÷jþ£±{5:ºFoWßs™n öªn¸³g-FƒhÛ³ºº’H7õú®ýv/-ëF7°€ã㱑ÓÙ¹â´;+É7Ïr¼ÚrŒ9Zºj﬜xZ$? ­“^€Q]NþF“¦Éióýë«ÀjŽä°uU”@+ÕèîìÉÑ=»lõžgˆë{f÷ð‰]µQQWCÎ…sºsªol鳜FáÖÏ|µ°;ÿYk÷^·Ó¥]¯8¼°;7»Äôv­ÏƒÒN‹».ÌhØ¢õ·$Úk–ôr:ß2[“ÔS i n­Í.\S»Óâ’œž;©é«e«w[§~¬ˆ6ôÃôS}lg£töÑôh;5­¦k²‰5-e ÍTKŸ¾ñk²Îèf&—ùŽ-¹ÛÈ}ź/¾™š«ùÉݾ"k-ž"ùŽØú¬¨M£†7HFñ+Þ’uíÄg­AÓ8ꆅµµ;Ôvµ½`§E%§g/êzù…%(‚§u‰¸5BPß&ïª 3²-g§Eî½¾ÑVÞ[ô=y(‡>n£-Ä$xMçí&b%bë¶ÖÂܲ_X­ú)gåt{j•{4çSª¢Ò"Ëyöù¢¿sýª¿¿†wv>“;'²y_)í_±SÒyèÎùÊïfàoz{]Ú‘äœÚ½<»k³OÛæZf:]ÞꙩC|OÞy›ß-ÙôNóƒ){´™íèb}EÚU;OCײ;ŸÞÍÔŒ´¯ŽÈ•i*ÿÙ~¿o;7ó–\¦Ž]ÔQ¢Žm;]Z’Ë>~Afk¯J_uØGùFIz\ÃîœèöÒðRÕ³,³ý½ñ[E ^s7ŽJªrgŽ,Aßéî¦Þ?œîî ß—®ž¨žGzÂÎ÷=Y÷dØÅñ\(·Ÿ‹íìš5ø½ÐNm_—íûê%OÎÉVŒ~iç|¤oèciæÈï‘tÒ ]o=jØØ#³´÷óýæòÏ ù·Åù‡^µm_Åç8Ý`YÖPßjê[³'{VzªèêÖß¾…Ýø@Ω›óÍÜœoÞæwKúpݼûãÑ…§¿R˜aºôxÏ>å´ÄJN‡à§~ “µvå$>àq„{–¿³8dkÞW »¢Ñèí`¸ÃbåKÖÂíÅ÷­Ð¬¨7í`«fÛ³SïÛÃFË9l#ך´O‹ŽÝegvÈšÌ̹:žÙÖBWWÞón]ŸÁËø×ìÓ{ Wo¿¬w^}%½6ŒÞÅ•`÷V‡såJ¡†s]N°ø5‡£gÜ´’àÍê—ôôF›@L½‰wîʹ MXðzS‹õ¿†eÍ,¨? oa~ÖîÔYòòìEÝì$MÉò˜ÛÔ ˆ×æîÔ½ùý5`úûyÍ=ó—çªÍߊ0KâÛƒrUoM§‹©\f>rÝ·v‹¸†yKõŽÑˆÜ†*ÌÖz«ùê(Ld§ü|ákOfÈv’ú C·ÛIÒšs;ijWΈÌN*3Sù£Sƒæ/쥷FÙ]o:¼ÐåX5QºÇûÖú­uNWt¸°ñ9›gðœî¼ÎïÊá´-»KzÊ;_î1a­ÕØUƒ¿›˜•›©a3xó¦}Ã{3KWe 3:zMnzuÆJ籺; Ö"ÆÖºP÷³³7j„Ó»ú–Œ¸÷Ý[è³ÁÝu•¨kzæ%4½ësµ}§‹ÎÏÉ>®‹‹7™[¥µÙg94{7õâ1íËÖÿ:èm?Ü+ͽúýÔŒX¯ ç—núƒù˜±ô¾°ûÝ’{0ꀳ3xgÀõ1Þx¿Ã̼Ú(×’Í9ÒrôÖq@ÈmÎq`&Gÿë7çÈ5.û_º9ÇA!Çõ›srlÚœãc鿇†6ç˜r7瘔ÉÑ|Óæ‡‡·oÎ15ä¸asŽi!Ç–Í9¦‡Ë6ç˜rLÞœƒ»›ÏѰ9ǬLŽ~·lÎqDÈqÇæG†7nΑފ”ãòÍ9f‡+6ç˜rLÝœcnÈѼ9Ç1™M·nÎ!-ä4Ç›s,9vmÎqlȱus8 >ÇÙ›sœrÌÜœcSÈѲ9Ç‹29¸9ÇÎã®Í9^rÜ´9Ç+CŽm›s\rœ³9Ç«BŽöÍ9^r´nÎñšLކÛ6çÈ=Ž4\½9ÇkCŽ›7çøéãšÍ9n 9VmÎñs!ǼÍ9î9RnGGŽ;39*·oÎñ+!ÇÝ›s|,ä¸esއ;6ç¸+äX³9ǯ†ó7çøDÈ1zsŽOer”ïÜœã×BŽÏlÎñ!Ç­›sü~ÈqíæŸ9ÖmÎñ…cÑæ÷„m›s|1“£t׿r|vsŽ?9nÛœãK!ÇÎÍ9þ$䨰9ÇŸ†½÷? 9zï_9zï‘ÉQÜrÿø«£÷þñ7!Gïýã«!Gïýãk!GïýãoCŽÞûÇ×CŽÞûÇ729 [îrôÞ?¾rôÞ?þ!ä0÷sãÿ•m7~åYJ^ËwÆÞÚt»î¸µÙ»´{Ç]zõD çÙ@ qUw¾<×4‹Ë úZºò¹/붬»óÒ®gåtº¾…ZÿOMˬ¦EC Ô´"®)¹íÿÖ¤»º­‰û­ õmuý¿þWëÚÍh±ºæ»š"ãjp_~ 5•Œ³°={6Þ&ÎS]Ö§ÅØ»!‘Š?0óËs¢uUëã»Ãx•j‰o÷œP» ØÄ ?Íò©c<À©yKviÕû†Mæ{^Õ{‡O份ê=»—ð=³ê¢Äx¾§V½{ÄX¾'T]XRÌ÷äª ŠGw}ö9]ß{NçÉyü?ˆÿ‹ù¿–7CŸÓIŽE%yð6 |«Öz?tƒŸ¿éz²ˆ>5Á•À¿ 5ìÉ£ü‹œGŸ«£»ºWÀéÐýºF𧺽|–žCо{Gu7Ìòlïí›Mø9¯!¿Ý7—ÄÞÌJpèkkGý>­G*IŠíúÿê9ó¹iïGgžæbËþO=òûÖó|kÄQ'º›¤¡û~xÉUÝ\”B£½ÏE7·jBs·|nêAÓêæÞ¶ó`øÝNO7V ç ÀèËzoèõ{ohîzohŠ:oFG×ëƒKç=2d£ëõšyw½“4mL^Ó?Fo(öšÔÒ«,‡4Œân‹á¢3×/²wøàô>Òx÷{'-ÚÄk^ë4ìl­ÒSJL=FŸ©4¯ ¦ë£÷T<ßê.mñÒLŸŠ¦I£'U úã%óB€ö¬×Ð'_Éô¦ÉW ú×¥+-ŸôfK6+&ŸŸiË–LcݼsúæÔQ6­ù]¬rÐ×.›Ž9z² ^ ü|ülIC¶ÁëÎóÎiå£Û`s`ÞÝcµJÇ«ÑtÞщmôZùª¯ñb{'-ØF›óÎ÷X¯ývϼóZùô¯Ÿy*@ÛµÙÞ‘£Ù´ÔÉÑßï0iºö7ígf¢¿ßš‰þ~þÄØî?+äð³HŽU–C¬ëþ¦ÿnr8½o“Ãi¬£ÁÚßtÕM§‡nrøÝ#}Õþa7ô7ír“ãS–Cú©ýý^!‡Ÿ'rø](Ôæ%€LWÌÛú§^×Þäðs@çÉMÓ¦ûorø9 Ç9–Cš¥üþ#‡Ÿrø]+MÒ¦{nrø9 ‡ß‹B‚l÷›~Èq—å®è€°Û¼n¾Éáç^Øf€ù Ç@?Ê1p¸å2…×Ö79üÃy“@÷s ùL09üÃé¼£é9Ð<ê™~ȱÕrH%b iÓ›~ȱËrHb y$09üÃïL?äðØN‹ÞGÉáç@9ä©Àæ~â`Y•c°Ÿr8\Ž>â`ÃÍ&‡Ÿr8ßèz&‡Ÿrl²Ò9l>(L?ä¸ÞrHÓp°ùa09üã½–CR ƒÍŸƒÉáç€Îßú„ƒ®ìç@9†xœ'Â!†YÉ1ÄÏ9Ü}}Á!æ=Ñäðs@ç÷½@y<Èrø9 ÇË!=À!v09üÃcbéË ±ÛƒÉáç€ÎÛ"š~ÞûÉá瀟µÒÅbÞUúsEÀýˆÀM d @‹?ä€7É0àÁw ñà½Ü¢U?ñB3?1-ÜéZÀ¦-ÌcÈß‚v{ Þ[ðÁÓ‚_›ÿÚ¿AÜ$Ãÿ÷ üïÿƒØy}Ô¦5ðxùÕ„ßÓAxë!>˜;ñ`î$ƒÁƒ¡Ó †_0_©½ùè_™:kþ— á>„;Ñ¿÷x˜ª—öø¼Z AmD¢B8Xžj ò¾–I+¬±³/§ÕÙŠ2Vˆe×åþ7T˜¬¨8õ¥¡øÁ"Ä0öî0vë0ö"ù†±ùfV†±#ÍíIó­]9œ]9œ=9œ=9œ=9œÝÈÛáìÇáw–;ÏÐhãáG%ÉKr“Çä4&ïÉi¬%ÄZClDˆ1ùÃMcãClBˆÉ7n›bò›ÆÚCl^ˆÍ±E!¶$Ä–†Ø²[bg‡Ø9!¶*ÄքغÛb›BlKˆ]b[Cl[ˆ]b;BìÚÛb×‡Ø !vcˆí ±›Bìæ»%Än ±ÛBì½!v{ˆÝbw†Ø]!ö©»;Ä>bŸ ±Ï…Ø=!ö¥ûrˆ}%Äî ±¯‡XØyßÊÄâ°ÿâ°ÿâ°ÿâ°ÿâ°ÿâ°ÿâ°ÿâ°ÿâ°ÿâ°ÿâ°ÿÄÊbùþ‹Ãþg*‹åû/û/û/û/û/ûOÜ«,–ï¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì?q¾²X¾ÿâ°ÿâ°ÿä+‹åû/û/ûO<²,–ï?qʲX¾ÿä1+‹åû/û/û/û/û/ûO^µ²X¾ÿÄ_Ëbùþ‹Ãþ‹Ãþ‹Ãþ‹Ãþ‹Ãþ‹Ãþ‹Ãþ‹Ãþ“_®4–„ý—„ý—„ý—„ý'ž]Ë÷_ö_öŸüxe±|ÿ%aÿɧWË÷_ö_ö_ö_ö_ö_ö_öŸ|€e±|ÿ%aÿ%aÿ%aÿ%aÿ%aÿ‰c˜Åòý—„ý—„ý—„ý—„ý—„ý—„ý—„ý—„ý—„ý'OcY,ßIØIØIØIØIØIØIØòL–Åòý—„ý'/eY,ßIØIØIØIØIØIØIØòj–Åòý—„ý—„ý—„ý'Ýø,–ï¿BØ…°ÿ aÿÂþ+„ýWû¯ö_!ì¿BØ…°ÿ aÿÂþ+„ýWûOÞÔ²X¾ÿäS-‹åû¯ö_!ì¿BØ…°ÿ aÿÂþ+„ýWû¯ö_!ì¿BØâáf±|ÿÉO[Ë÷_!ì¿BØ…°ÿ aÿÂþ+„ýWû¯ö_!ì?ùxËbùþ+„ýWû¯ö_A¾ ¹™Ã}^•¹™ÃµÁ-n7¸‘ÄFr Il·ÄQÜ÷ãÆø_ÿ›ÜáÞÔWÍ-ÏzÆb;±û£ùÄAûhw¬M^ÍT•&w9¥`hôÌÅmûh·é w%õ2èh[cyÅQ0yÅ›ûh·é®wåÍd×}½ò¶cü_ˆ÷ðÑîŽæ›S+šŸÛÖpæ§÷f÷~iä¯Çx¬çï£Ýcàšëë”z«ñT%áG»7Î<5_Ì Û\âe¿ â$fu=d>Ë×(ïBÆïx»óî1ŸeDãÇZ~y'2~Ä©ühwÜ›ïzκÅòË¿‘ñ{ ÞæG»óœU5ƒåêÐ]ÞÔ!Žh¨Ã¶óÇuÈ×’é§xÏ‘µRµr>Fa¼oíŸMF“_œWõ ÜsälYEÚaN³ÚÚpgŽß€Ím–W>ŸÌ.Òd~´{FÅ¢ÙåóÛS-2¾Úµr}SKc² ¯bJ}Å{wÁxW7Íkë5%fé¾ÐàµUÍæ{-SÆß‚8í~¬®Ë†Ëñ¾!Ù¼Ó[Z4'—O›Y6§bþl³Í‘vC\äßÜ×j‘ç*ãAÜã´ïx¬W‡Sð´0A>Ë•ó5I ¿w6´meò‡ï‹¼_E¥Ô¢úêµ,›æ,Ã/cŒÆåLÞXÏy+͸¯IÓkq¬èϺ¥;ÚsT`µÈ—™qqWöÔ²¦¾±=SLÖWùï2ÚÅÿh÷|ç#ÁTš;IHsÉ×Wôr‰þÑîãªÊ¦&ø!ÈïÞ‹'íÊ{qØ?Ú]ÕѺ$å ­“'zês,<‰ß Ê,l4¥Øi¢¸·ò7fú(>ýG»§Õ°â×·¯tØüÒÞ쌈Ÿ`*Ôç•2³sÄÕÿh·óG&ç'Î"Yê°½se¹Üâÿœ"-€vÇî ´‘MÌHµ6±ŽUí¾0äÍxòwG5+í„QÅfθa×bö+k*í/ôy¥¾k¼Ià U¼ µÀGúŭɺÐWù^3»_𮝛;–<××7µ.ïXrìÆÖÞnùÑ{jŽ?Ú=¸ô÷,=—[Þß îÕ|~´{AŒ)ëÀAóx¨Ï)‡ ƧŠô"jXåacsY¿åÆÀ`QiR€Í]e“?ýÍ1[\4Ói\|´{ ‘pÞ¥ ¨N\.ßv¿Š+õÑnC‚fjŠpª].yÂ3½GškcGÓÆ:KærÉž¹)HÛC3íÜùË9Û³ ?¯‹³ÉâÍ'b´ù¤’ç[×®­&ôõÉ‹¼ÙQâ6æ}Z=Ö8Èæñ´ÎQúwÈæ•·ùè䕾ÉG»“òÇàZ:µ,Ñà®oóÈ3½ñÕ"2ÚG»Í6½³n¯ý÷ìe µxÛ»kn€_ÞÐÆšh´Üâ^š™—ËG»Óîó5înÌÙ½Ö'ÿ%©F4Žde¹<•øÞʾ魸•šáóóZe°ßAãÍmì%õK …Eϳ¼òov£´dvçãzÙÐ~ü¿ÿ‡×ßJ¯æ£ÝÎm†1«§eX¯úë»äX^Ýö F‘ŽÛÉÆ¥ÆÔçñ—|û£}¿ä»ßà=q&?Ú-3¨ëñ£—¹ÜÈnm)¬ý_\¹üK›ëÚÂ…âoÖþÐjÁ_"ÞM¤ßóÃE^È‹½¿9¿5½”V¿•ì‚s/²¼â$šý%í!Ÿ×õ{Nbêüãº[i¤þuÞc»ZüMí—õ5Íí µ÷%u9¥ LNé')§if–yó¦ödó—l7H“ÉΚ›†M5­5MÉö$0rOé¾vq3gi@¥³Ê5mwÝ]¸Áj3aã¿Jwà®lƶÉÚÚ#æe_mN6ºè:‚ù~|?!|óHkOnº{ßé}*}ÀnQÒØêíE…XôúøÕÖ?¨nÿ#Nceq_ÍME^{ê {$™2ÉÔѶ?ÐfM”jµZ>h;A÷ÛvO÷ ¦Á¡,l®­Møú¥Hg0·Hí쑞Æç›Îå•:›ñß"=3°œº{Âôò9U²:æ,LMP‡j/f™f 4Jc[q„MïÓ­$7Ž&Ï1˜³z10§õ óe®–ØLë³£ƒéÝ7/Œ9 ²|/Ƚ ~`_.K¶6Ôë\²{'É[¥É)WÊø¼OšºáØt~â(QþÔÆ%¢ÛÞâ}d‰Ë θµ;77u—hš™œ>ºf'íկĻü>¸ËÔ¡¥àQ8´Þ±ók,7Þs5ó÷ý:sÃX#ÔÓ™v!¥.ëjŠ®Þ×>n½þG嵇ÑÃä$ªvÍÉò‰×Î>ºWÑi¾‹© 5--4gÏœ_%çrJ“À÷ÆYóÚ}’y—ÇNøê¥Î¿ةôÚZvÑ¥½û ¿¾òØsß/z±#`™y9®³:ð,\tßÏÝ>­øEE\îCS˜?Œt®l™M{þÿ¼å—ÿ]“_: äŸöx~‹–^îQ÷á—½§£W› `©5E‰D²µ5ÕZÝš\Ê}Á^YÈýË-?¼fžå7×å^Ï`]ÒÚÑâNJ¶Šèyã½oJüut½sV[Óp Òý£K¢«C^z¹o܇fD­Ž‡ @f»oÆìPùîÈÿ]iø=–«ûð#ÜQÇ& ] øG–g²ûð@ÜQã& ]~¼(³‡¤ÿБÿ{& =GËò:w^;êøW®¼33ëòyÜQÏ“& ¿~¹ßÒX÷߇7åŽ:¾cÒ÷B¾oM Ò¸è¨á #®ùÅ5s*˜Ž5éòËc.Xõ>´?kùdä1åQH£>Î}x‰î¨åa#éLÉ ®ÙÒ×èÈÿ=#¾R63.Ç9u uÔñ˜™Ç¯•yÏSÒ÷àžržq;jø¾¡GW‡ò›ÙP=u|ÏУŸ1õÿk÷ÑÛŽ:þ“¡Çc«½ï1Í™Á-š»Žš¾oêÑÕ¡¹7¸E{ £Ž'L=ºŒmÕ ]ÔQæ] èà2÷Ú5µÜ™Ewàܼuntk2ØF·§Žz (ö–”á|Ý¿Ì^Ð=¬VÓw (f½Ñ=Î` Ýç:êxÌ„"¦Ìl ºšÑ]°£†Ç(¦s¦û£¹9èÙQÃwL$ú™ÐÝÝ}ÜA;jxÈD¢Ë­«™'Ý\;r?i"1›KÝxÍ­M7ߎ:öIœ“Þ“º/›}§{sGþ'Ì$ºð`}45èöÝQÃ6“èû‚lqîãþ^«é‡f£¯žbµ@ ÇºÿwÔò„¡D[²îæ¦#BG Jô=Høo°¦8ù5”èòÓö…xµüß5”(Ôìê@ÜÝ)^HG›Jüž¾M håƒËÄGé¨áAS‰ŽÇ—È‹5¸L¼˜ŽÜ=¦]^|YsG/§#]~üYƒÉÄ êÈßk1Å ‰üYS»øI¹1…8ÞòãÉšÙGª#ÿ£¦]~|YƒUÄÑêÈÿSˆŽß•ȯ5=G¬£†GL!úྀ},^Z-ÿMwú¹Õ‚‡kú)N\G-O;t5àÅ€{­øx5üØØ¡«ï×ÜÅì¨å{ÆZøÁæ–#ÞbGß7vèêÀölêo²£ŽŸ;Ìú‹wlnfâovÔócs‡®¼e3»â’vÔò„¹CWþ²áa‰ÇZå<é8ÏU^XšOÙì/qg?Ú]S×qöáψzÁD>à6å¬YCžóù'‹·Û“?'áLXt˜eOóã'[¼àûà{ή¥Í'ÝÑZã'òŒ-â÷Á?†ëj[b©6ÿœÈ6xR¼æZ=ò·˜ÊƒäµgÉÂØÇaoz1<üÁS‡ãz®4‡«&ÊÇ¡NæÂɹuî«aÃ_2.ž·ßNìjTZŒ¿Cç…Þx:ºU˜e41ðo{i÷nÝÄ¨ã³øzÜBl¿²SsÀÖ›„Ä[-Ÿ<®"ß2bá™®HŽEÄ–ºËÕ¼‹ˆ[Ú]¸Žw“‰=µìÔÆ¾üXö %°s}÷nêƒvÁÙÎûÞo÷`+aßgãc´çí+xû´Ío_ÉÛs6¿½Ž·OßüözÞ>ƒ>5mîÓÊÍy_EÞU›ß¾š·çn~ûÞž·ùí ¼]½ùíx»fóÛ7òvíæ·7òöüÍo_ËÛ 6¿}o×m~ûzޮ߰7fŸ¿i¯ï8=û„ªîž»«N/¸ÛîY3GÈÛ¡|bV=!åµtÔµ´7¯vÚò¶Ú|¯Õ{ëF˜cJî}ùÞÜƼ¼+™ñ Ù»ÇäÝqÓÞÆ»©z߾ϳÖâÕq ‚R“»’ø;,D]]íQ{´É<3µ¥ë×­hŽè]{fíxk1eÀ÷«³ëöâsÌÁ‘È™¥¹Gmº;廽ḹSúö¸»q™νjÖ3ÌV{÷”ÍùÝÓ6¿;Çy‘¬¿} {ûœÏØünå†y9rçÁyYÙ;/í°›{v×S»ºÇ·TžEU˜³„ÇÌ«sGº›ªØ>ö¦ZèÂãØíÄ‹¥Ý¹àºâU¯pøt"ïw&ìoØŽ;¬v@awbÉ­ûKr1yÙJ®á]˜Ï–ªêŸÏú-äšÖ8ºšçöÅ;‡šF?Z“ö‰­itØ7ã£U¼µ8±ëí¹ÎŸVýí[îÃ@z·ÿèÝê܃·TçÚnØî[ëíó ¦}¾Åö9>ÁwÛÕÜ®ÊëÊÿó ¦ÜçoǨàU+é›Þ¾•·k³—QÓ/»ûí¯ðöm¼}+oßvxáÙyÙ ÷¾{AöKî}·6ûÄÍï6l®ã¢Íù6º=öÞ­µ¸ÖíÄ‹7÷wÓæwÏÚüî’Íï6oØ93Îvwr©æUqǶ(}úëȹ¦eÍç›öìÌûöl¤[Žöl¤{ïðŒÆžlÿ÷þL¿òOý™~Ö#ý™jý™Ðßëƒ5ïêYôçúÍíÇåHýMÖrL»mƒÿÖi7¬0þ±ÛOiûígÛæ·OÙŽ5ŸJíã6cÁ§ñvìæ·çl®çßð#Ø|k^`ÅÐýÓgu ;l}JÎ…kPG¶ý[¸~²‡XƒƒÞŠÐï ý=·/„ퟓA¡û»aЂ³¶æçtZ¿ŠôkÝ#uö1#í—ØÊô‹^=Ú#<Ü>V9’GrÊQÝS¾Ö{+i‡Eö^Ï ÛÝâÜSÚ©Ëípñ`μo&®ýííqE[n¼»k9ž:pÏÝéÉK£;/¯Ûôƒ·ýŸ®·é»Ý=«y]Ízvà噞xIÜ3åúo=;°e`–ÎzùÔ¢¸oêÙ®œÐ³¬gù»ÎÙaþø¿óÀåmÝÑ:r‰ŸŸë7ä9Î:ýûwû¾Ž)U__ OlèÚ‰¸C8ëô»Õ½Rw“3±þyq_^ÙßëOU}½°ûâС'PåíŸuú7îÎÔÑd¼bC÷¼¯&ïUuœ»ÿ®¾pIÑçï¸Ñà‡ÖÝMjoñA»$Úÿ|ÝÖèùXíwcóžËÅü\×Õݯûýñ’zÍ=^R¸ y7?«;<ïZ˜‡†IÜÒÚ÷øWËVï3]7üÑ-†îsf¸ËUk{€÷èç&º\w*q–n¹‘É?ëæ‘ãÙÿw{8ßÌ]õ~#Üߎë7úxÖgó§8>âÇ2Æ%XN5øü-Ù³6ÕsëyÙÇ !ÐËíîå[6ôrI´ŸÃÍëø÷©Æäù[ßvúN‹ï«!Ý©K¸Ïžl±yër³óxBïVXìÑ:Ç\l©nw/™4Ò·Ýù-‡û½†e;ô&Ü{©ÕgùßÑdHoh»5òþå: ËtjuïÖvŽÏÒMïäEw¨öƒ™§îwæ6Ôý®}só6¿[rß»š~Ä’hï{uUöâˆã™ú^Ô=gÕö;üž=þè¾~`/÷hX°—x‡VË~†ÿ¿ßßÏúwÕf®€ñåüÏ=4øt¿Ü¡ z•溓\er}‰ºô~Ç»³+×|?{v:Ô·.ÝŠ)o(Á™a»}<ðÏûÀ™ßÇ`#¯Ys7·ÕQ¢û3ÑÎ]yÅ¥NSÂõéáY¹‰ÛÆ5但;ÊÜ“mîÚŒ÷ÑÐÓwu·gwÙÝ!ס1üŸ÷Ü”öÌ+w¢¶>’Vå#ûÜÛ£ƒä[Z¹gÞÓ»°Ôˆ™äEWŒº·W C¼gã߭˜LÎöÓÿ¥pÓû[OË>ÎnÓhƒ¹Ú‡_í0HßX®íîÙ?Ær`¶^L¸ûÕ0^m_ »úaŒ=ì¢Í:^¡Ýu5ûa‘Óy‰¤ý¡I#þ—fY1ð3Z_çx±OiŸ(Çbï4>pê½¾ƒpQ/ »/©ÿÉ;ôºm;2ºô¿`£¾ vþÐaÏpë-Ûµ¡¶i†õ †™Çwß3ùnÑ ë»oú_ä{´ö´×Þ 5öpL*ÏÎÙi«¦Âÿ˜¡=8gßl-‰žyéƒØ(Îê3 öü×7‡7×lŸf½xíùÙ#6ÏþR¸W¸›óƒsuòfÕ²ÍïVL¦æö ÀƒÝïÍ=ø'3W:àæ–À—T5È÷J5Nô>›×xßâÎ{\:8oOÜvL®Þ(ÀØš©‡îP{fXïþe×â/¿ç&ø@>nr-1ÿW•lVZþyhV̽*Ë7ð:«á§Ã›;‡~Àªñþ-÷ŽÚþèx9½XK»Öè“TwËÿ¼ß¸xè;77 î†7¹ÿN˺.Èܤҷh{îÿ¬Dß[f²Óéî ^/ÄÜ’Yw†¹Æýë÷ý¦ð>å#tä8 ä0Ÿîfr4;þWwŽÜÏ~óu›srܶ9ÇÁ!GÊÿìÈqHȱasŽCC3³Ý9&††ÿ×cRÈÑu±9ÏäèwýæÓBsêÎ1=ä0üÏî3BÃÿëÎ13ä0;´;Ǭã̶h|ÈaîÿÝ9ŽÌähºisŽöÃð?ºs¤;ÊqÃæ)oZ9ŒþEw޹!‡ÁíÝ9Ž 9RœÒ‘cAÈñÀýk[45“£ñ–Í9Rì£wlÎqZÈqãæ/ 9.ßœã•!‡áuç6fšÃÜ!ºs¼*ähÞœãÕ™ ·nÎñšãÎÍ9n9vmÎñÚÃèPwç¸5ä0üùî?rôr⥚æhÙœãÎLŽÊ7çø•#å¿wäøxÈaô»sÜrlÛœãWC£ãÔã!‡Á¼Ý9>r< }¸-úûLŽòm›süFÈñÀý[ôÍãæÍ9>r˜û_wŽ/„†¯ØãžÃàúî_ 9R^rGŽ?Êä(ݾ9LJwoÎñ¥ã–Í9þ4䨱9ÇŸ…†ÿÞãË!Gª‹Ý‘ã/BŽÑ›süU&GñÎÍ9¾r|fsޝ…†ÿÖãoCŽk7çøzȱnsŽo„½÷¿ 9zïßÌä(l¹üCÈ‘Þ?¯½ëöU¸dá×à¸oAÇÞpX_Wˆåš®ÅhƸûÜWFE _^pÒZú™z»ó¼gí þöt|ûN¦3Kl¨ñ´UCMÃÅs­šu;3ü|ﺻó®ûm^¼è&è¸Â½uÇ¥½9çà+aŽ_Æœõ¬®‰‹ª&>ël´"í 4zWaW÷e…kë¸óÑ4§®áÍ5¼)rßËã7ÔíÔØÿ~j_| w¿Úûöþø¼þø’ õ¹äj⫉Ë[@ˆ:}!Çöjúsž×Ÿs~××;6røç\eM¼c§KGîfÛÝpÉb»]ÖfK7÷ 6[éœi~§/Â\qs]ˆf”4i¶¾*çBi¼ØžHËénš_bþî`&Û;ýüÙø ·øùSü¦= ×¼œÚ‹NcaÞÙ߃OrÝ ¢_Ñ¿õ–ìãèÏüßåMy!ÿMðït•öT{ß-vÈö[ì ·X}§øg·…8º¨dÿh]×°œ /ÃSÅ)ÝðkL”uË)HT¾8:¼Èy´X‰­È5XÍXY=jÜ’N¢—ÔU;+kgT._Р?ç'hÞÇ?žÒÚ,†OÎñÃoÆ‹IõXÞaml=SãX$ONΣ|$¯’Îÿ}$?$Þ?^cœœ¿È{¶}‡Wç¿ß¼ó>ì5òmßÉÿ!嵨æOVù"N{#_Äö<±Ê3púNží;y^•ßìÝš879?º6v1T³/[>y\-¯ù¥à³¿äýßË«Ti±å“§ÕR{È·-ä»)äû¬å“wÕÒC¾ofò•÷¶ØFbÞ£ÿ³°º³Är˯jÅúG/+Ëì|¨6XŸ˜§†ãX‚tvãt‹ÉËeã ™š—Ù;ùÁl<ÇbB[ýüLË£j?ïÅ_}êgóMMý|ÿTG¿;-Ÿ¼©6fò5ïžÉ×|P&_sqx·ÌbÚ›Í67ÌJ³Ít‚·ÎfóâŸàL¤Ùz`êp=0uøyÕ»þÃì\Vô÷{Q[¿¿ÍsÓßf‹Þ÷·y¢÷J2¹جc ÍV‚âÌ@Ûgäèó‘ãìÃõ’ƒüÞºtif>ÙÞe.}-Ó¿Aaº-“c°ßCÊ1x¸Õ$7Pƒ­njl{Îäó;‰|~¶TÓ`Û¯&‡ÛO&Ç­V“ü®¶Ä¬ ‰2¹‡ ÏäfzˆŸiÞå{kH•Õ$/¬CÂâgNs3älË!¬­í“ßÕ¡~ËÓêP›æiXK&÷°µ–CÞV‡Ù.§OîÊä~q¦7ïÌôf¸Ç ò·:<ìûÖoòðûLùF¶0ïÜÜ›w~¿jgŒXg1ù]êé÷ºò4 AÿFú=¤>¬ ïÜìònT·õI—¢QgdfhT˜ãQeêõÑL?FùÝ)w/£¬ÇäÛol&ß~¥™=ºŸß%¼[cuË‹«¼2§³µŸï u8Ü`ò¹пýÂüö»S=í{¯Ü£í±ï\Í;¿äëu´ÕGFû™VÏFûJ>7ß¼Û?Ìßþ†Eȱ¿í-óî†ðî&«U„1†ŸØcÂÎvÞ¿óÔï1³2ýãqùÜܘ|[­>añ1¾ÇÔçð´É—Ïñ˜Z>y…c}eîÇö5ùr<4Æcn9µc³N¾±…öNŠªcmn˜¡±~ßë’8öÖðî^{'?¯m7´­±wRÞgóÄ»qþ>!Ÿ®ã<.çÝgì|ëê8À×!ß;x|Ì;“ä›çÀPßþ"?>†`n´^<ÐcwyþoóJïÇ[ï<ïŽ÷·y ßrä3zÇò,tíHzpíx“Ãχ<ì÷ºúq°ápüÁvƒÁÏêÁ§gê8xMÈáwnûÞK9ì`Ã…¦&·GM>·Ëé÷!ÿɇÒ!~')ß!¶_Éwˆa“oƒå“?¨Cü}‚|~åùéÛCæÃ1¦Ž[3½ŸàóÉKÓÃÌЄKí|:Mðø•w_²wòuh¸3z¥½“ǨC Ç›w~¶ti›ftb‹½“‡¡‰67æ»áu¢áîF}}ºvN4 M¾I† èå$5åkR¨i’¯I—úIׄw9FŸl¸Ùšìï@º¨Nûu²ß¯òÏ5Ùî(æ¿h¶&{Ü©Øav£¾)Öû„³í”N«CWÊ)¶?¨cŠÇÊ=Å÷LWôà »ãp¿”ãp»âôðp 9Üã0rø™S_÷79©‹fýp?ëRs?Üãjõ»Jý›êï‹òy6Õ°9¦Ú½‡Z§ú]NÌÏ«TÁ§†}0Õf—š¦{l- ÇÓmÎÈ=}½åÖÜÏð¸G±™~Ö•c¦ß—òÐ6ÓÏ®ê›9ËÞÉ—ÛLõæŸEåžå{)ÿo³<æPŽY6+&‡ß©êÓþæ$ÏqG¤Gø9Ó¾?Âïcy›;"ìã#>8Âï$å>Òã'b~ÖåûîH¿ox—ß6Žô· ùÊ;ÒïrÜcïäYïÈpƒ<ÒÏ™ên,‡üðµ–"G»¿…Ãã$ùík÷·rø»9üÍR¾þÚê=ì›v?òØÞrä7Ôvã‘_ÁvKÈáoWäðXYÞÛý#ÇOíþþ*†í†wMŽ|·ße9äópv¸Ìös ³=Þ•¯ÄÙv09üc‘åòål»ë˜~Èáo·òÌ8Ûïrø9 ǵ–C¬ƒÙþÖBŽŸÍö8Cêš³vœí瀋Ëoäl»ë›~Èáï¸RZšc7TrÌñs s<3dŽÝAM?ä˜o9ä¿rŽß÷äðs@[’£¬9áv>'ìÝ9kÊMÈ•Éáç€7ËÅÖË'‡Ÿrø](Ÿ“sü½„~ÈñuË!ÎÄ\gU޹~”cîî–CØh®ÇÙäðs@„æî19rÜ3×ãEyŠœëoäðs@½ärnÀåsýãfË!_sÃ]y®Ÿr|ÊrÈóãÜpËŸëç€sËÏã<™”c^à=Ìó7$yuœî ó½až¿¯È‹ã<&‡Ÿrœc9ä¹qžÇOäðs@ï^œg7N“ÃÏ9ü­Nþç659üÃsYä“qžÝNL?äð73ù`œnÀGìx”ÇŽòµx”¿ñ#ÇÖGyl-ÛQþVD?ä8ÛrÈ“âQ†#MŽGåo„òœxT¸å瀞Ÿ!O‰GùÛ 9üÃãi9ð:Êß-Èáç€þf&_ˆGy 9ò›ÄÑ;[y?<:ܺŽ·®£ý­K.¿Ž¶[²Éá瀞 ¯†G{þ 9üÃß9¤êw´ÇÁäÈïG{>þíoäðs@wÀGáÑv¿19üÃÝ¥ðJxôí!GÎÅ9f˜åÐÇ1þ~¬Çø9 ‡ÃúøbŸ ±{BìK!öåûJˆÝb_±o†Ø·2±8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì¿8ì?éd±|ÿÅaÿIÇ ‹åû/û/û/û/û/û/û/û/û/û/û/û/û/û/ûOÚ Y,ßqØÒdÈbùþ‹Ãþ‹Ãþ‹ÃþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþ“ŽDË÷_öŸô%²X¾ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ’°ÿ¤‰‘Åòý—„ý'­Œ,–ï¿$ì?ihd±|ÿ%aÿI[#‹åû/ û/ ûOúY,ßIØIØIØIØIØIØÒôÈbùþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþKÂþ+„ýWû¯ö_!ì¿BØ…°ÿ aÿÂþ“nIË÷_!ì¿BØ…°ÿ aÿÂþ+„ýWû¯ö_!ì¿BØ…°ÿ aÿÂþ+„ý'}•,–ï¿BØ…°ÿ aÿÂþ+„ýWû¯ö_!ì¿BØ…°ÿ aÿÂþ+„ýWû¯ö_!ì¿BØ…°ÿ aÿÂþ+„ý'm™,–ï¿Â•v3—¦MtBæfžp·Ë t,·Ð6nÏã¸[ã.}±¹'.æ~÷_ÿ/è½íô%sÇÛ¸³fPw[ Ϥ3¨C›¼òꕯ3c}ô. ¤Ûê¡•H\&½×ÝÜs×™Ÿî¹óÌs{n7?½·z¼sa}ë8m4æÚ÷Áˆ|³8_ ͽújÒþ즷øàûÉgu/¼ïEoêlô¦–Ioj;µo§öíÔ^Õ2OÑÚèà¢ÚÆT›t§.Á0BSÝÊS—×ÅhByÍãÃ>ùY‘àÎY‰®’‰a7+̇÷,,‡UÆCõÛ‘m¸¸¶¦±¶º1µ´Z&…ç$Rí‰T}bIªém#®{ÞÁu‡EŸþâ×ã9ƒÓÏCߪÜÌ™›­;ªçOÙ'6žóú¸õ¼ç;û—îtéÉyó × ‹}¨à`ÇUÙUk†eÏ®Ê[ÿôuÃäg~‘|îlýlN'36sÍ­ÙU«—E‰Õ¯‰vVž­ëk®]wúìý-e]Ûµ3ÿ߆ި['–\€ßŠÂó »ÖÏ+\(Æ—™ƒ»ðuÓ@®2y>ÎüXÈûpUSMŠ5K«ÏhÙÅÑLæw¾æ·:³vœ>.Ò¨\Úˆãdæe=Q332v\ŸÞ3j+?dæ×k]0{9/P÷Y;¿‹ï™_æÌÏ/sçwúSp’&î‹$ÅÀÞ]öó8v½×*üZF‹î&´è^€†x±§ï†Ö;ExŸ{†Ñ¬nE+Üèo«@^àxC×ÿ¹G›·å®é“Ÿ¿¿óÞ÷ø®°ï½·ÝùWPïWÖÔeW©Þð&³;Ï[² Ïxyv•ò¿üz‡­Ûä÷êØ|»sÊŒj:Ùjr^„v×tr¨©A5io½5íªCÇN5ÝŠŸšê{|v¾G¥ìãäõÈÔ´¯z²Q©ššKrzz.QMݸ¡ºŒeuqÞ'54×¶&›’Ííî퉰wR]qì®9þž]“Êô¶Û5Ú/)VÐ(FÏ+ÈÑÞ{nHWUÌoZHEŸøÜW,× ê˜rݤ\ fUÎ,•HD—}ö{¢0¨Þ¿EïϯihLÖ%jÚÚ’­í ©æÄ·¨iOÜ6ñàº|ý'‘³?9Z9'Œóœ,]•}DtÙ•_¶â*EO%Ç›•ÃBªËŠjk£OÚû“­©RÑVÃ̸‹¥[ѶŸøZå`§~èæžëmŸîr~«¥´Á^µžB^°¾jûu¸í×UÛ¿ã¢CäÓÏÚ…ŒÇ·<óâgr½Õ|Wþ¯÷ÒQÜÕMŸä Éè Ž¾Ãù‹+©váŸŸíŠ Ú«rÁYkGË»D¬øÖÓѱßãpºêšƒ‡ÁäÿË­žì`&ì·ÐéVºýù›÷õp—÷ܹ÷½óVðÀ{¼pÏ…‘ól¿u¯«2}{Þß ö­³ŽO¨Ž“ÎÛÏfvŸ—ÁŠ+ßyJ×ÞÂ÷_\²wôl°‘|õjŸs#ús‡ªö›žr¾ÏÉÎ…UFïËzÍÛèKq§‹«rJ‹øþ™®Åx½*F'øXl¦œ©ÿ·¦‹ûüÔe}¹‰¾ìG_ßÜ—wÞã{U»$øŸ(D§g|t¼}Kô y'êykôŽ»ëyÉæwF#¸ûÝË©¿°¹Æ0G7h§m}»ÔäÐÞÉsl­eïØÚ;ÿï=»T ·°y·ß”ñÿ°ûíÛèám÷¾}KtÑæwï¤V·Ûv×sËæœ?«û…Ýz›c÷[ë¢K6¿ûyfŒÓ`½‰·/àí5¼•÷UíœÛ6¿ûÅ{ß­ÁËïÞ¿ùÝíèÕÞ°÷›Íø¯€‡s/§ÜqnM2{÷DoÝñþÆïßxÿ{ûV½Éß ƒÌÍË.ÞåžW•ï®Íï>±ùݧ6¿ûôæwwo~÷››ß}fó»ßa72ÛCÒ8sý÷9JàŒ]ì6æƒÝ÷è{í¾;2X­sűOÒ®wÂgqöÞßp˜sì6O‹U¼z9络'ø]Þ¾Þ«/Û†óÜõsÛý}ÙE^ü áxëé3ÌclWãò¡úÿSêÓ&nG븭rǺWTïFRÐMãöè9E uÜŒÖׯ¬.«*«¬°KQÏéÈë+pSqÚ*ænãî—îmßqòººýˆkgïÒâ?‹{fßé~#>X¦ìo×äpZ)ÜgÄ5Êr|ÆîT§Ýs§jÀvzÓÖÍ&½SNènU”hhnho¨il8‰{Óü÷Ϭ‹-üßo·ÁæFt&]¥ÜÝ÷Ô;t÷®›_u ÞíÞèo>5ÿuÂdo|§›â¶¤»%ÁVÝxÖUŽÜ³®pçÄïÞºgœ{u4ŒÝl}’<𾹪væHrL)Yo½³¾âïé¡üÊ= 1`SîßW˜GÞÞñ¾ÌZ’?¹‡óx|þÐ{ƒQ¸<0‡§¸[Åo—‘×y¾Ûýötz4eï»Ùù©÷—îÛ–æ\yœŸ—½ï§ïxï|‰õ¼Çkí”Áy„×väÙݨdw£RtBßý8Ÿ¿öÌ„½ =ðö…nßÔß~4Z³}×Ù»P׎²w¡®w/ß\‡ñ›Ò³ÓŠì´WîØ©Ö³ãƒ;ñÕßÿ ï/ˆým;=¢:¶&÷€‹2òÚªór§\²4:»êB¼ø?ÐÇ×É nÏ[ã#ä_k}ãöZ7î™ùéÍïnb'ms»o…tGk<¼£û2xo<©îŠò7ïžmß/w•¬/Ý2gŸØüÎøÞè~÷éÍïŒWŒîÚss¾Ï0_·Ú|5 !1_wdEïhž¶â KzñEŸï]_懾äw¡¾úò˜—Jö;þ̞Ǔ‚phÕÃ|6¾qŒ›Rʃ{Ô¸;Æô®´ï¢Tå"mËHÆ|àuÛ˜tÅŠ^wP积Ñ(½žÓéä¶Óàua¥wÕPi÷¡3î¹5VfxLÜuÒûЙ„Žæ>ôFd÷FÏ­«K,YÙžLÔBsÜ’QÜÉQèòÃí©„;‘éÝEMX‚hÓÃé#m ÍK]tfgtà VÓYÔt 5½A5Õ?»¡}Yâ¤dk*Ôù¼Òö‰v#¯XÊ»¡¦a@mH6/%í¼D±j´·)é—d±þ7•‹ÛÔ‡Ëznõ<¿¹(2ÍÅÅ\œ9ÌEá{7﯃«v“óüx¿¼®¶L†óØ^Ûs7·y‹•>J.çeië+Ø×ÀËÜæüd-íÚ;Á­[„Ç¥3»þ)»Èí6Õ{Ö üÜýYOÏgu~œ¸nªÝîÏ×0÷!Yõ¢5™®ã=¾Ó¿‰y'ßiuîà[äéŽ{…ñ½œ¿½ú«³+»rwÿ@åº].ïÊÝãîÆm|ëuç)“g[ÁÝ]ù{|`S™ç­Žw©Ÿ«Ýù–,\ç¼ÝŽ/˜ú@ül=ÐWÞf7ùÝo·éÚ;|¥n®ÓÜ6|„Íú`Ž{ââ8×s¼~ÚNë6½ÛEny#¹©k/òÃg”Sã]D*o=}º¹—ëøöXWH]‘Ûo4žãúöê¶ds]uM{MKCµ-ÕÆµ P¿ÎpÀfççšÜÒW²ïØÛ¹º4‰ì;örî­ACg<íœQØ.3´£Sœ!½¯èyìö×#MùLkßEuÕÉÖÖTk¢Ÿ!“G T´˜\Îm«uá»óå ÖîT fçŸÛóÃôÎ×,Ï…³<—!ûÞïdz’ùS^Î>÷ï¬Ïg¼TŸõòÄø…`<ÇÖo)øª4ügváÛ/D<áö ´ '| r1;³|ØÌÁ¾<ôî.ƒ÷Ç·“ç­Æ³¹éðÂ’Ï’çíŨÌ{öI]ïõMºÓÛÓ˜¿êu¬é}»LóYÝeâõ¿Ó‹úWÀ;ìm»Íɱլ‚|9=g³Sr]_é/ؽÄÚëäŒß+,åö’öHª ÔóÊ31ý²Ãoz°¢–½°š½ 5Æ­ïæÞèçõ-½óªÙg^ΡÙW<É\Eµ[/Ìs3yþ„Ù¿™Z´¿¶~–a6ÿ„Ù¯¿+1ûÔ´‹w9ïIùÚÝ»U¼ 8ã³g†YDC‚ß—¢ƒÂ,nLµ<Âö³#F)«tÊXh-éÕ<àÎ3ûà(ÿä3Z„»GGÌ’¼Nný.¼ l_\°gá[¸¿œ1¾ûoŸ2͹ž·Oåm´ùíÓ6¿;gó»§o~÷ŒÍïVºwåwë?{UW}ðŸý°f‚öÍ´Ë]”ªKÆ+n¥)6ߊ–M[ÞÐ;^Û\^`¤ëfwž®»w­ð;O³šÎ­ÐN¤¹½Üzçö{ý‹ÂÎ%Éšº•Õí©^<º§y™¾¿úf{¥ééìýH{Eâ¼#á}Ó×¶E³Õ5:Ô4wÞÔÔ®œïÀ‡'Ôl5lv{Ez—®Š)ê_1=;-ó3ä5æ¡z­}v‰Ã¨Õ» »Ìû Ò½Vš?ö;ÊûxàÓ7;Éûðàó`ö÷,Â;ç“Àø%ò¾ÐÀqùìi)f>‡¤lö°t_wc†28Ùìl¿‡…5ŒFÅõÈY¾fI m -=gk'a»ÍÜ.“1>JŸ®œ½ÚCsqxÒ¾eŸého´Ý÷Ð}|‚.¿r×îÎ×Uí]̓aÇÛÔƒáîwKW®^'^|¨Óù3ÜýÎy¢ÚýÎù6ì|§{çóã~ÿHW)nD#Åß Íè®Ýr3ÔÆéÚ[f·yÏì<§‹ovB®á-mÙëI—Óî4S:wÌÍý%vDºcÐbÁ޹ó7/M¶W×%—7ÔzRઃê<†%¯4›?C¹êÜÔvÔÛ¥#ãt— >úw@Ý¿VìË·Å&foLØ/ÊåV;bľìùr=ë¦a“uó68b{æ»Ü¨\¼»m½×Ùî{ýw÷,3Oþže°s^¾-ð9ì Ù¹¸$Ƈ_Ìû»Ô{sWÿÛÏãÆ¾z§ëéé¼5̅ߥ+N{Ú]ê¥t@ü›½i¯²ô®ýtñ!ÄÍy볺Ì.º^wh.ºïIk¢ÃÜ œßÐÚÖ^][·} ª:^¾›……$±6 úáÁ«ÁiiH©ÕÏòŠî»ÝM‰»–¸÷¥=ô¯Þ©e°'í6—êÆEɺ†šê¶öšöŽûT‚œŸ-Ó“ÛKêG4‚½ôJä€~±ížBÚâÅ‚²ñýÔ4'ì©©‹•Ûèç|¤ç:ÛQ;'Ê÷j‡é·á­-õì%W é~ž™ƒ%Ü,ϼëÎSŽûuÁÝÝh™œõf0Ó‘ÌBñï v;›Y0z*M-]»¡ý&–†œü—}É{s5>ØL-ñ5±ïµ¨‘|[ÒÙt÷ÖÛÛºV~µ°$g§NùÐÎ=9GÝ\ö·FGê7Å_Ø´÷ŠhÑÞ»G#5ƒºQlí:Îõ®h§{p}\ªšæ~W5}³hßoD‹ºöùpá¾w’[^ÙäyÿSixðT?îòs‘÷ è9¶ÖÞ™¹sø÷Ò‰ÙY·SW×òËz{ÓO}ììÞ”]^iÞÔ´·šÖ¦ûÞõö ›ß½±¥rjÓÿ%ƒ=Ü=G=Ú=?Ô ¿ëéî3ü…|÷ §\NÙät´gªE®Ì.›\4¸ÂØ…9Ä—™»oT1 »1`ï/‰º½·)nž?"_Ò‡¶uÈ‹ôž³»„¿QH^zÌinég¸Òy‰ØŽÒ÷MsKß7Í'=]‹›PNìÔóº A›LF·ãy1œÿ ÖëÍõŠ ‡%Z“í­Ím GQ‡ö¸ÝéH-JÛrÚ Êå±§ÛéÛ&áü¤”lõ°dàØÍîÎUN' Å<›ãavª×Ë}èÅ«¹æb ³½ƒÙÞæ1hu¶ÕAý¶F{¥Z’Íæ5ÉúšŽÆöꆦš¥Éêö•Ó¨ÉÍæs¶·±çòἯ˜¹ö¾/˜íáüœc3%/g»±è-Vð3Ålxì#gÜu§ÝèÈ>~ÀjÍøvW]ÉGnÎS£½L²»¹ ºë§üŸiOÙ^É«ÂÃwfúã{%¯e<§é{Ò«— ôêû=šÀümhK&OÜÔ£ Ú¥¶GòT¶4=’o±Ý=RÒÑß#ù3=–ó“ÿÙ£ýÝí~ÏŽ¸lA£ï‘|¥=’O±‡{D_|tÍàåL¿3þÓþgÆšÿ¼=‹Œ.¥³$V]Ú'yþÚÝ'õ"í½q}Џ³^§ÿ¨ÒªûÍNÖžÿn‡ ªï­ƒ·„ÑÑEÕÕµ: ϬM5ÃPÍ·ÛBå©^Œ—Ò©µC·Ð(Œ±ƒšk™ÒÖ®c{+_YÑsyû"½ …eê†:.\¢£«E%D9¸íPhž'Zþf<]5ì½·º[ë\nòÜ·ÐlÝáph¥£ôÔžÛ»ö½µ´lu¬•f|ÛDûM;×øù½ö”ž§©¼>÷öú­ýQÍ׸¹§¥ÃݳµlÓ½ ýÏ…f¶¼w4z¼'°‹¿W2cÞ+Xu‹í yëÚ½7î±Ì•ŸSyìŠ ™Óbóî}šd°—Ï#Ÿ]ÑaäyÁ@IÉ*M›‹IÓqr¢¾î…×½H¼•5ÜO—_>2¢ÉòŸúÂD|VÜœh[–êh¬KÌ+/›5ëøÄœ¹U‰%I˜Ø¢’võaÏM6‹ sX[KcCûs—Õ%*“5mI‡q~ÃÒŽÖ¤Oå˜3i.ñlýòô¢þíª3A¨ß*Û…Ö¹‹:ÚÚU÷Eìæõ-\gõ|֨юֽ9:1Ê·$¯_øAœQ¯:Ìý몞kl­šÈíËvöGീŸS½@)Ãvrç²Eæâêdnræ|‰Pl'ÞÞúÆË Ϫ7« ¥sÉP›{Ø*ÇÍþÖ™ÏrÞ‚fE;蟑í¸û˜óæhø)o|Wa7—ˆt§éÒÑ× MÁ|÷ÉØI©hD”óixü ¬n]<§¥ +°w.ÝS| gµX¾°Í¥ÛÜÖy­Œ*Ï<můœÀM;¬TFž¹»Ëge”Kou#¼ïNÝõvvDÝÏŠ†¯}VÔEl[÷Ñ÷‘®­â×ßÒçRóXÝËR!0¾íöó·„Ý»˜S‚Ç7ì ¯áËÎòXì?¿§Ù¢ŽK`ö·¿É'’÷iöª¿±›½¿;nþÄ;ï»Eî/.å½X~rÓ­ÉæÓ—?»ïåël7'áSš7·ïµ³Ò}/¯gFçU\¹Cö½¹GD—ç̰]§«­`”:@fŽüý‡{ÉL› ù†Ùƒ¶†Ûýõs!ïjß\…œÄwôh›9=F××salk†D×¢ä¹ûZ~mÚhòë$7aDÿ\™r$±}hÔˆ'›O̱¨˜|WnɇHÅÚšÖÆ†dk Q&CÉ[“ìt·x[ƒ”ëÌÿŠûk0º¯¬¯¿kÝrÓœù×ʽ‡{ŽÆªÜçy sew§oÇ×½ÑWñó~Üù¬ÎÃ8w——œÖÓSõòáKð$Š>Êd:¢cÉ·º^v87gñà”Kñ¥kßuVuŸØõ2îÁöÿ~È]ê½¾·u¿ÿ«ÁÚ5[sáï9/ºFõ‘ôÅ=÷ÓÁ÷oí¹KXŠ_O?®qý¸Êú!¥âŸØýk‡Ÿ6t½ àðIÌvŠíÝÒµÔµbÝý—^Øîcè/•JèóýêÇåUQº®©«ºo:–þ·[f³Þ/ªÞe-îkÇ[õn¡—[ûžžÛEOð^°‘¿óuî^Î|±³ê<@v§¿uƒWü ƒèuV^?2¬ãôÓ¹/ʇÝéܹ:oàm ¯Î§;]̨h_öãó£ìçîÜ¿¹šµh~z'ksÙªœS ·FÏKÖ§¸1ÓïOù·ã65ëRåé¼M]·ºç¶ô.•ÞFUÇÌ$sÇMI= ;ž§ÙÑQ»Ãøõýº•Û‡|=÷©íô¡:ï\ áSö7ÓÝXØ#ó÷þVYÛ2W~Þ™e§bvr™çšÛëå6¿B]·)äæ—¹òó+o{Ñ~Ìâó¢ì¢Kûç×ÜSóöó+–œÁ·ÏUÎŽù59#´YÜ k"#vΰä¦\úo3Ü9“}ÌëµÑ¾éûq×ñBÛ5¯fv¼'3꼑™ù·Dïý”»³×'_çŒÞf”¹ñ{P^þÄ‘‹Æ³/üŒÓä7÷æ(ŸïXœ ¸¸)^"^ Vä‰ÿeþWïÑ3Á"î}D¬¤Á•ï²d+ä|Ë‹°uËW'eñŽ({ÂÁâú¡ÿm´¿·çtÖÕ=#ÞyÓÆ/A©`%ƒ#΢­Ež8uˆÆ¯§–Ík>ƒ¡†SJ®ÕuÇÓU× ØM{—;ÿ ½·ÆÉ¾Æ£Cv/ɳD´ {érÕX›átßÉÛ Éñlåp¤KŸC·]ãWC~£aä¸L9ü|.^. gòS yäi0Ú™<—öæÉsQ‡Ï…¿]jÒgwMôÍǨ©Xžr9áŒ&çæú:.75*i+‘·^y×01ù'ÄÓ†‰É'!^7LLØ &&„â\œ'»p¨û’Çêö}f¾ä“0NîgÅóUåaøYOB37›™ù—2ssñàÜP«Q“ŸqÄLÿ6>Ö?jôs#ŽX:7òO˜Î.¼éÜÈa:7ò=˜r5äoÐôþ"ÕÝÁŒóó!E!ãŸ`ƒrÈúÄù͵,SŸ6ZÏŲ0=¿p°çä÷µˆ=<Ï´zµÎPÙ@µéüHeÈÌÚúͳF­>—gLÝëë¦V£&iˆ˜Èû Á‚ÜÓóÍíK\+|}Bu÷ë®ÿÀ\ºúLºû£k¨éÏÚÁþУNúCN±eÍ.XóØ. FÍùÃ}¿BÓ‡Õƒ}`øµ»é~3œçý¶ý\môÀï,x–ò¦bbð&ýþ{ú=%†xM11nèò bbòTˆ7“—.<«˜˜<âeÅÄä…+&&σéN”®VºÑ“'“WA%"݇éû¹Côùüqß#ÝB4Ãæx¤é ˆ¥‘΀ü¦3 _ƒé È¿`:òP–΀$é Èw`:ò¨°}çîö…xwßé{¾oë­|U¤µË‡`Z{˜uyTÏ¥»¢Øý—Þ1 ®ž˜û…¤ÖŽ`?6bëb´{¬1´rÔ˜>8ÁQÀÕ“€4'M³ï­aø¶ðî"Ä“7˜¡ 僣˜•`ž‰·™$Nïâ6‰°vé’¢ÄÊTGL‚°®ò ©š:’lY&T[KcÇ҆ୣ æ‚½ž¡š: ÁøÞ±‡Å5=’!xxÏ0çX´{îš6ì÷¹‡óÐ ØíAfzñ&4äy ¼óœhæÁëyÂ3q|ÓSÏ¿`¾ÇÇ·£‚Ôý:oG–CknG¦Ï~.ä¡0Êc.žNÏŸ«áŽPzwóMC:Gémó0ÖöHïПÍ=¬Ïªüs`u-ìÐ_?,Fx”âv¼Ä-(ÞÚ9¯C3ÒFxÉs0ÎïžAYþÇs@ësûjßÐ_?Òˆ5ÚVÒaøóÂ#ÙLpçÔ÷‘ŒêÀŸÿq&Œ—ŠGæb~ô¼Mš'½3"á“Ùô¸>'8UšŸ«)bç„¢¸U<X±aPœÄω¼3RÆ‘0ëZ‡ ˜“)÷é¢ô €-xPŸù|Ü=#&ìf„~û‘ßG3#O¡÷wŠ¥ø‘¿³Kto¹fÈ‚]²[›âÁûÏ»„×çD%Þ%ôÜω˜fNÄtä †Ÿù˜4s"|>èÈ!ædÚ}{çä_° =®Ï ”è}sBÏýœˆk°‰4e}byCk;¼]úíÖï=±91ÞÕuáàAŸ’`Ÿì.ý‘)ùç}Bës‚G®}sbýYÙ9[-z&s"MÞÁG¸fU÷§ÍR•Ñ~¸òô1€k§Ç3R-ûá!ñIßú[Ÿ´÷a«Ñjî^…ý¸{ ´9 Âýís ª?[A»òÑ^·qÛéÞ(ߨžÅÒæsº•|ÝïÓ—0½ñó*ß÷h´ãƒ¬¦ÕñÝ>vïL>Ð(v»å$Yd¶Wð}Ò>1ýqóU½+¢*w>í܃›žrïMPúöF»tmÓ=gÁe%Äy)Ž„­Gžâ©g6=ijß\»p4PÞÖ«îõ‹4½íÁz6sj|¨žÃµå5‚šù#oiðÜŽ‚è†M¼“Í‘‡›(ä%/?Áú€Ç1ÿði:r¨ûã¯AyÉK­ojK¶Ù½¦Ÿ~÷ÒÃúî†Ø½ÔËt7äþQ ϱ9XNŸŸÓ˜ZÁb¢,›h|Ìø`#W90i¹ÿwèa}Û1ôÖÏîªæöª»bë¸Ú¦”㸷‡‚C"_.­ãtÀ¸$¹Ôï+äÐñ)­e븾ùðÜV?#ò àt-„o÷w÷• ÓQBcºî‘ôÎÏóâü˘yñ3B½OÛ0#xÚÚw¤¿~¦Ûh´¾JŠ|fØHÛ¶õUœƒ'îÓ®Ô=30ý“s@ës OzÏýõxuÖe‡x½õýˆ¯â×ö²/ööÝi»NÏ;~ÓÀáæÝöySMkMSus`Ëp:2­5q{éYQi÷áUzãæ³¸šÐVŸkv³‰ï éþJÏ“;¶oðw¿£W±ËS=môF;Û dÚEªõÍ"ñèÝaïÓ¨0}ô=Õqüêiûª–©ßïáLn¸®‡3¶÷ðÈø½´¸ίÓ$+¾|°[BÿìÈöOî%äsª£Aãt.¬å¹0Ó¤[ 7~žÓ¯íMl´µ£¯ØÏë•7ŒCÇ¡EïÒV쇧c™5¿ãƒ¾˜ó{l8Tž_ GÖóá™6/œ[2:§fºoE¼ëJG*šÏªñÌÉÔ! fcûÙÎFs•Í׿aœg3Kl^<87„9 ßQy“ã"ÂsÐýâ~xoCzÊ‡ë œ ¾Õ•†µö^‰ó”òÔNšvlCo¦.Øï¡ËD³(¾Z.çK·åtx¢+§<þîÍiqSWNt{sZÌÙ•=¿ÞœËwåDÿ¦7§½ƒìÎi9y=scg³+'ü¾Þ:]lwNø½9 "éÎ o±7§å’uå„÷Ø›Óò®ºr›ìÍi9J]9á]öæ´|®œð6{sZþJWNxŸ½9-—£+'¼ÑÞœ–×ЕÞioNç[swNx«½9íÍ»+'ßÞœöæÜ•ŽpoN{ûíÊɽ£7§õЕ“{CoNn¿õœða{srßíÌ &B˳'§Ñ£¨çD;³7'÷ñzN´9{s‚Ѻs}†ÞœVû£+':½9­¦KWNôzsZŸ®œèBôæ´z^]9~DON«Ö57×mÏiõ»rŠÑ›ÓèsÖ{ƒ¦CoVß³+'Ú½9­viWN4"zsZMÖ®œhIôæ´Z³]9æDONËîÊ Ï¿7§Õ4îʉ@oN{Ëîʉn@oN¤Kë9ÑèÍiï¥]{ ÜžœÎ@WNæ¶7§õ­Ð•]¥ÞÞXÏ]9uWÚ›³Ž‰ÈùÚí9áCÕs¢±Û›³Ž ÉɾëÍi½×tåD·¨7§õ…Ô•]ÝÞœõ 9ÑéOËõïÊi´r{rZŸ§]û­ŠÞÞXo¯]9ѽèÅrh³''ú½9ŽEgNyky°7õû9IÏ ÀE«÷Æhtôô¦Ž?¹í-rº;k×|â/£·Nf·^'šv½uÚ[}WoÞ^§¼ìÉ)†ÑÞœì¯Zκ…™û§!Idù å›wâ´ÃðA:r@1ï|¸3õ¼ó9àžÔsðÎ瀧TÏÁ;Ÿƒ]Ïá<]™`Œz‹=l¸«õ¼ó9à×sðÎç€S]ÏÁ;ŸƒÓu=ï|s³îÎÁ;ŸÃ gwÞùèKÔsðÎç0“î¼ó9¸è×sð.*O¹<¨çàÃÕaôãºs˜w>Úsõ¼ó9Ð ¬çàÏÎ`=ï|4Pë9xçsÀ·©çàÏÁ^¯çàÏNR=ï|tië9xçs 1\ÏÁ;ŸíázÞùh×sðÎç@‡¸žƒw>:âõ¼ó9Ð#¯çàÛF®žÃb)[8ºžÃjÌÛ°Bê9xçs ‘RÏÁ;ŸŒ]Ïa±·Íç“zÞùøÝ©çàχ™zÞùP÷ê9xçs€‰ë9,V¶9ð]SÏÁ;Ÿ^\=‡åËÙx¨ç°^lZûõ¼ó9ð9\ÏÁ;Ÿ›šõ¼ó9ð]ÏÁ;ŸÃð¶»sðÎç@‡¡žƒw>G6ï|t/ê9xçsÀ©çpš&Gž6ï|´Hê9xçsÀa©çp:%&G.7ï|ôaê9xçsÀ±©çpÚ1&G¾7ï|s|éÎÁ;ŸÃpÙºs8-“£çN`Þù†ëÖƒw>¥z§¯drôÜÌ;ŸݪzÞùp¨ê9œ¦•ÉÑs·0ï|´Âê9xçsôÜ$Ì;ŸCÿ÷äpZc&GÏļó9zn$æÏO­žÃò×lBõ6frĺËvç0ï|xyõ¼ó9àáÕsðÎç€wWÏÁ;Ÿž]=ï|xuõ¼ó9àÑÕsðÎç€7WÏÁ;Ÿž\=ï|xqõ¼ó9àÁÕsðÎç€÷VÏÁ;Ÿž[=ï|îÖõ¼ó9¸ï×sðÎçà6_ÏÁ;Ÿƒ›=ï|¸+õ¼ó9àÄÔsðÎç€kSÏÁ;ŸO=ï|xõ¼ó9àùÕsðÎç€×WÏÁ;Ÿ_=ï|x{õ¼ó9à/ÔsXS›Ãh©vçàϧ¢žÃr-l£ Ûƒw>Z²õVcÖæ@«³žÃjxÚF'·;ï|tuë9¬Þ®Íöl=‡Ó¤59ЮçpzÁ&Ú´õV³Öæ€[VÏÁ;ŸÎZ=ï|¸põ¼ó9àØÕsðÎ瀻WÏÁ;Ÿ½çzÞùh<×sXíg›ÃhHwçàÏæt=‡Õ¢¶9àBÖsðÎç€cYÏÁ;Ÿîf=ï|8¡õ¼ó9àšÖsðÎç@;¼žÃjŠÛF›¼;ï|´»ë9œ¦·É†z=‡ÓV79Ð9¨ç°Zé6ÜÚz˹µ9ÐÙ¯çàÏß©žÃò lŽN†yçsôp2Ì;ŸU=ï|¸¼õηÉÑÃí0ï|Žn‡yçsÀ™­ç°\Z›žp=‡óarôpDÌ;Ÿ£‡#bÞù=óÎçèመw>:"õ¼ó9à2×s8Ï"&G×ļó9Ю«çàÏ­žÃrÓlŽ_Øœƒw>\êzç?Åäèᾘw>G÷żó9z¸/æÏÑÃ}1ï|¼òÔsðÎç7ª=9xçs¼ksÞùðÆë9œ“£‡‹cÞù=\óÎçêÔž¼ó9Þ¶9ï|9@Ù“ƒw>‡œQìÉÁ;ŸCÎxöäàÏ籞ƒw>\ÊzÞùð:ë9xçsôp•Ì;Ÿ£‡«dÞùp1ë9,GÓæ€£\ÏÁ;Ÿîs=‡Õ°9àT×sðÎ瀫]ÏÁ;Ÿx=ï|¸åõ¼ó9à¬×sX ›.|=ï|tê9xçs ÇPÏÁ;Ÿ­‹zÞùhÔsX ËcC³;‡yçë@¿£^ï|´xê9xçs £PÏaõl´ƒê9xçs ITÏÁ;Ÿ­£zÞù†O܃w>zNõ¼ó9Ð ªç°zB6úXõ¼ó9àn×sXN·ÍY=ï|¸ÛõVÊæ@‹­žƒw>G7ÇÚäÈ9Ö±xàõ–ns ËXÏaõmŽN¡yçsôpÍ;Ÿ¢õ¼ó9W¯çàÏWÆzÞùÈ¡×s8¯&~fë9xçsœ»9ï|äÌê9¬.¬Í!{rðÎç/ƒ=9xçsÈ£Àž¼ó9z8—æÏÇàzÞùÒuß“ƒw>‡tÍ÷äàÏÑÃï4ï|Ž~§yçsôð;Í;ŸÖõ¼ó9¤=»'ï|é²îÉÁ;Ÿ£‡KjÞùÒ.Ý“ƒw>Öùê9xçsœº9ï|i7ïÉÁ;Ÿ£‡ÛjÞù=ÜVóÎçèá¶šw>G·Õ¼ó9z¸­æÏÑÃm5ï|Žã7çàÏqÜæ¼ó9oÎÁ;ŸC.¸÷äàÏÑõ5ï|Žc7çàÏÖJ=‡Õ`±9Ðh®çàÏqÌæ¼ó9ŽÞœƒw>ÇQ›sðÎçŽôž¼ó9ænÎÁ;ŸcÎæ¼ó9°+\ÏÁ;Ÿûªõ¼ó9ŽÜœƒw>:ŒõVŸÑ昵9ï|4oë9xçs ßXÏaumŽ óÎç@g¸žƒw>ºõNƒØäèÑb1ï|Ž-óÎç@ºžƒw>š’õN7ÚäèÑt1ï|ô¸ë9xçs ³TÏá´ºMŽmóÎçèáÍ›w>zzõVgÏæ@Û¯žÃjþÙècÕsXÝ,›¾z«Ïgs WXÏau mŽž¤yçs •XÏa5mtÀê9œ'e“m­zçwÜä@³«žÃjyÙ=:=æÏÑ£a`ÞùhIÕs8Ÿ &GÎyçsôè˜w>GÎyçsôè˜w>GÎyçsôè˜w>GÎyçsôè˜w>GÎyçsôè˜w>GÎyçsôè˜w>GÎyçsôè˜wî6o|ˆÕsä*ñf-óÎçèÑB0ï|Ž-óÎçèÑB0ï|Ž-óÎçèÑB0ï|Ž-óÎçèÑB0ï|Ž-óÎçèÑB0ï|Ž-óÎåˆ6sšÍ;Ÿ£‡‹lÞù=\dóÎçèá"›w>GÙ¼ó9zxÆæÏÑÃ36ï|Žž±yçsôðŒÍ;Ÿ£‡glÞù=GÏØ¼ó9zxÆæÏÑÃ36ï|Žž±yçsôðŒÍ;Ÿ£‡glÞ9Ü`´ »µñÌ;Ÿ£›ëorä\ÿh3Ù¼ó9z¸È毵G{À¼óuôð•Í;Ÿ£‡ûkÞùݼUÓWË[µýèá­šw¾ŽÞªyçsôðVÍ;Ÿ£‡gÞù~ôpøÌ;Ÿ£w:ÿÍïB£h˜ðF*ZËŸÍýzøÌp¨ÍM¡ú³Þ¢B1ƒt)hcI¬œ¡#Q¥—:ËЩNÈå§ ~Ì¥â"§½÷_颿fÂohÊò¡6æj*žØ ÄDÕ‹aºÚ«¾abŽ‹}7\ŠB"#ÄÚ’ÊHÈmäõq-#qA­—&ø W—XÕ%Fûù:G Yêê;J.±=F‰¡£ÿ£´¤@;Jj,RJÛOWM Ç~RÙUÍû‰‰*Ûh<,Rïè¼þz¹œdõšÛi—F] F‹©)6Çh±LUïhmWõw]ì4Ýûã=Ç}û q¨Ïc¸˜r}Ë&â*<Ô{§ vNŒZp5ÀÐjƒÝ ;± >¬Ûq\½QGÇåÕqôõ˜¸P£úz³˜Ÿ„„õ‘PÇ0ÙX…ãñŽbáA\^P=?ˆ©üD]¸Â9f ááÊ¥ýƒèY:æQ ÿÁ 3{lõª¸¼PÓ™À«ÈLN`ŽŠôsLõ"ý<¦L‘~ÊöBùûP”\Šôo"®ÈŒL‚eU$ÿ$Xµ%ê ë¼ëã0úYb÷FŸKÌíaô±Äœ¢-Áö= Õ˜2o§ÂB*ÃZ™ ã­ÌœLc˰o§1×evÊt®Åeæc:9*°f°þ+Ô7ƒ‹l…¾Ì`*ôx&Švær&}ã€1 V@s= –JszýÇèñ\[˜¯#ð®ÐÀ\"Qs~$lê?’· Ìé‘ Ï&æi¨¦‰y˜‡ÒKùf4±ÿަŸMä=ö\yáúÛÄìÃ^l¢oÇ úÒ9œîi?j𝏿gì¤~Ô·ÔÕ9<–}Ó„cQh¦Î…ì¾fæf!Ìóffn!ª/ͰÇÁJi¦Ï‹P+hfҟþ.†™×Ÿ¾rèãÑãûý8ÔtúÓã™ýþôãxöææs ìºÌõæwûàfi}8éÌó °I9[v õ€ŠÉ@fòDæn s|"}HßO„Y8½x¢Þ«Þ“¸¢¤§'±?RÇRöx ;j);®…¾žÌ¾la~OÆßE õœÌkOœÂþi¡§²Ï[¨g±…}r30ˆ|§1Ÿƒ˜ÓÓa¢OË™—Aì­åôq»h9j ƒ©s…\ûhVÀ|LOW°ç³[Ï€%0˜ºÎ€…>´ws=˜:Î` ¦_gПÁü?–ßæðL®C¨çLú?„ù?\0„ýq—é!ì ³ø?„~Å^ÂÜŸÍ< aÎÎ~AŒ;Î~ÐDŽ;&›,î ŠÆSÙ-mØ$¨BÙ·`?t¤ ÀtU†Ñd£ %¸K6 RÙ¼Ü!ÉkÍ+ðE^åVŽÆ•ÖòrßE#ËŠ{qÉ­EÑØjq™avfØÉÜŽù-„ªÎœ-&³˜g i§?EØL3ò1a´3ž2!ž§Lp(Jl•c<ê;GUjnÎÑmMðéÒ Ðæz†Ð—ª[4f¨ÚZ+ÅñJX)~¢¶ãJáam”µšuá|ñò4Õçù…ž.\ @Gpœ.AÂ[Ç<Áq\Ç‚³½N>>µ-ÖS7š ëáU¡³] 4Ö³yÐŽz&œ,4õžI ñ ™Ö„-q!¨ ˲ÑóÜÀFgô"¶6>7ræÕƒ?ñN±‰œ6Ê&øÐ&åYlüÛîæ¢@m›ù.g6ß,²6 …©®- ˜"ÛþR&­Èö½ Îu‘­v[²HÞ˘ƒyŸ Z/1‘ÏFTölúP¢ßÏf^J²·¦­]¢ß—Ã×*џ˹u”˜Ÿç€–JÌÏs@ ýs@1eÐÌs˜2óó\v@™ù|.|Þ2u<ÔU¦ŽçÁYªðîùða+ôéù Œ }z>[®Â¼^ÁüTèÓ•Ì4híJzÝ@Ÿ®D‹¬m» IýÙÆ[ÐÙUèáƒÎ®Bótvh»üWÃOl ÇÕèa42‡ÛéS#y·s§j$ß5p™»k¨½‘­ÿ樑þ¾€Þ52Ï/@Û«‘y!œÓ&ê!ýk¢ŽÒû&öÏ‹ÐÐh­í §M ­3 ýèÏKàr‚ê^Â>½] ×¢ï¯Íö£ž—±a›Ù/ƒOŽMÒ—¡1ÒŸú~Š:ú“w':ý™ù\ú3—;A… ·W0ÇýA‰¯`~úƒ._÷´?3ò ´@u¯@Û¡?èùì—þôå•ôª?»à•ì­þì©W‚®@}¯úÓ|%è¬?½|%ý¹Ù¾Ý´þôð• ¦þôé:å×~¿Ž9À¬_ÇÌ o×1sØ3×q›À~ºŽyÀÌ g0€~]Ï®Àn½¾êr^/Ô¨~]ÏN¿ž+Åæïzöøúõ*j@ï_E€z_¥¼ê׫èër¾Š¾`_E_ЯW³¯@¡¯Ó `®^ z@¿^ ÊȽšþ d_Í.H¿^ÖÛ@öú«Ù³™Û×€¯үװ÷Ò«×€ê‚D^#´ª~½†[ð@öÒk@©å5 3Ðì p#²_n`¯doÜ ¼ê× ìý`‚Ø! Û˜¥ôëµ\2¯¥öÌÔkÙ­é×kÉǓׂ‚A¿¯šU¿^>ha¼Ž½~ךúõ:f¤…ܯcƒ†_Ç> ¿ ÄðÀë@M-ì×׃ãZè×ë¹r´0Œ¯gŸ·0¯7´Póëá´Ð£×£¥ÖÂ^º‘}×B¿n¤¦öä âpÁ\±Zè×ÌtšÙσØ7‚Iѯ70ƒØSo`±§ÞÀ ¢_oà1ˆ=õvÌ öÔ”_µ½‘ý7ˆ=õF¸KƒØSo„C9ˆ~½‘¾bO½‘¾bO½‘¾¢_o’·0Õð&fy{êM̨þMÌç fëM\±§ÞÄ5iýz“ú¢=õ&vÀ`öÔ.fi0ýÚÅÎÌžÚþÌŽÙL¿vq…ÌžÚ—a0{jhw0ýz3œÕÁä|3ýÌžz3ûa0ýz3=L¯Þ >äJðfô«Ó¯ŸfOý4ýÌžúiì`úõÓ\ÓûŸfÿfOý4{ŒëÁOsL~š{ûzû޹Cè×[˜‘!ì©·0CØoaþ†Ð¯·p}žz sËUá-ÌùúuÜì!ì©›tUОº ÿ Cè×M\9†°§nbOru¸IyÕ¯·RÓöÔ[¹baO½\4„~½®o¥—CØSoåÍúõ6n CØSoc†ZÙSo£­ôëmèS·2[oÃãs+3ù6®½­Ôö6ðI+{êmà¥VöÔÛÙÏ­ôëíà VöÔÛÁ)­ì©·s­k¥_ogF¸>¿9jeO½+I+ýº™}ÒÊžº™+[+{êf®†­ôëfnô­ì©›¹¶²§n7·Ò¯w°_[ÙSï œ)ÞAíCé×;Ð^Êžz×™¡ì©w€W‡Ò¯wrOÊžz'9†²§ÞÉÛ¡ä|'=Ê ¾ü:”=õNô]†Ò¯w2¯CÙSïd^‡²§Þż¥_ïâz7”ð.®†CÙSïbÏ¥_ïb eO½‹=8”=õ.®KCé×-ÌöPöÔ-ྡì©[ÀÑœGna/cÆnáš4Œ=u ÚNÃèÉ-àÜaì©[ÀÃØS?Cs‡Ñ¯Ÿá°1Œ=õ3ì¥a쩟Ç £_?Ãl cOý |a쩟Ç £_?ËLc¶Võª7?Ë~F¿~–Æ þ,øc{êgÁÃè×»U§öÔ»ÙgÃØSïfŸ £_ïF?e8{êÝôk8½|7¸w8ýz7— áì†wƒC†³§n· §_·‚÷†³§ne®†³§nef†Ó¯[™óáì©[©q8{êçØ)Ãé×Ï¡ 1œ=õs\y‡³§~޽9œ~ýøk8;éçØ×ÃÙS?Ç}`8ýúyæn8{êçÙƒÃÙS?a8ýúyößjúyößöÔϳÿFЯ_àš8‚þüWËôçÀ#èÉmàŒÔyõd'¼|0’ùúEöÉHÞý"³;ŠzÞ >E?ߊQÌÙû™³Qì¯÷SÇ~Ì뇨c?êú}Û}ò!æq?æòCàãýØ#w°§÷£ïw “ºýþWàýè÷GÀ­û±G>B÷c?|„™Ü~þ2»h4³ûËìÎÑÔõËìÑäýå_ƲӅ0– 5î4¦cQ̬9‘^¡ÀX|æŠåªÁÞÒ´Áb©ÌÛ¨–P…ñ¦.eÂX^¾åj×Þ c9ø¶™´'b¹:J¯€1S‘Eó+ m¬«\– †„½OÕdæwFóû¨sªCŒ#m½_çBSô11ƒÕŸ©›šÞéF©íöq©YhZ?.%¡…K=OÛâWJøU©³iª~•í㌌O€QûÛ ÎÅ'AE(â~’1\‹Or­IØŸ¤Î„)üJU Sø)¶]ÂÔþ=ÅÍÁ¯±q‘ûkl!\¨ü[§ ¿Ÿfkñø4מSýi&½@ý¿:)°%~Ä5ïnPj­x7Ê?6ÁoÐ÷ýøM8Efå7A E6Ãoq­ÁÙÅgè_‘ú›™.ÒçßfÛéÛïPG‰mý;쇽ùê+&~—MUb ÿ.µÂµø]r•¨÷³ÌC‰þ– WbŽ>KŽõ|–ÿ\÷~wŒè¡~eÐÔïöàdüyÊÔó9f¤ÌÆüCf¯Bì ÌG…÷_ ö 5|ëd…¾A×>åûè¡B¿ÈÜ4°{þ.@}þ#®: ‹?b~™¿?b+7²Uÿ´ÒH=Äu¯TñÇìÀFêøcÙ~¬+ŸæòKpAú1×Áv†Cñ—Ìc?PÃW@'ýèÏWØcýèëW¸&p•û s÷+Ì‹¯pl¦EMÍôá¯Ø_ÍÌï_±±á^üû¥™9þ+®£Íôå¯AKÍ †¿¦¿Íì§¿÷Bsõ7Ìe3ûàoP l¦Þ{é%œŒ{¹¦53{÷‚:úSï½\/àh|tÞŸº¿ Êàú÷U]ñ”ókìóþôýk ]®}_c÷qmû‡kÛ7ìÊö öÂÐÝßqõ*þ;ÒØ¿‡6zþÎW¯¿g>’÷›\Q¹z}´Æuë›ÌK ûö¹&p}¹OסÚûQ_ãúr?ù]Ï-^ó©ëKq­Óõ%–“AwBŠU­º¾ÄYÔ3óìÔÁ{ó­ý ëJœÃ5Kו8•]UâöÈà5|õ¸–¼æpðÙ| ¾Ò/ו÷ò-”7ør¾…Äu=‰ó¹èzç³×t=‰ àˆƒèŠ1b²–Õ¾Õë!“ùÆÐõ$ÆÕ`È |k?îÏF¾µï†´ð­käu¤….[éGÔ7t=ˆŸF?‡RGÐëЯAúÖNzߺ}ÇOW ëä[ó#ë¢8Œ>£Ù'ît®½3ü£ØÅáλÁ\w†_ ñ]Jïã[8a8ó5„¼Ãïâ[Œ ¡Ù¸ü%²cFŒà[uŒ Ï­ìE¡Ú¸Ý6bD|Íßú<´?‚~oŒ8oíÛAæFÁ¼çŒηpÈHú;‚ý1²˜oí®‘cùÆI#˜‡‘ÌËHöþHæe$uޤ¿£¸ÒŒd÷c? Ç{±'G1ÇûqMÅÜŒf¢ÿ£A·£Îá[s?ê¾¥z6Š9Í^µžoíÀQÌÑþBÇòɾ?פýèïþ0_÷cÞÆ€\÷›É·ðPu¼/b¿*¾…X÷£c˜?¡ìx_¸Oûч1ì¼ý0†?t¹ßZ¾µ…®ãý`‰ìGýc¹rìǶ±F³7ÆnG3ãÀQ£éÿ8®X£éû\iF×ñ-îÐhæèú6ºoá¿ÑÔw;}ôY^ˆ{8š}q *?£©ó@ñhæû@®Ð£éï\­G3ß²ÿGS÷xXõ£oã[s¼?s=±?}Ï5aÿBRÐØŸ¹>ˆyØŸ~ŽØŸ½y0göË!`…ý™¯CØgûS÷!°ögOÛŸþN`Ï¡®C™1ìÃCÉ3†zå 1†}8‘ú5CñáÔ?†ù™(§‹êó$ú=†ú&)¯ö½1ÌóaÌÕæ÷00Ëê›Â^ÃüNaŽ¡¿SÀ4c؇‡s½8¬0æv¾…›Ç°¦Â2ËÞš &K§Ñ¿±Ìñ4ú0–z§±‡Æ2OÓØ÷c©k:Xk,y§³7Ʋÿ¦ƒId|=ÍÕ©¾Í`O¶1×3ÀbmÌß ö[}˜Áõ¸½6“«Ê8òÍŽ£ï3Ùcã˜Û™\}Æ1/³ÀWãØ¯³`QŒcïÌbÏ@¾Y\  ¾#xwõÆ;€úŽO@ÞvX"0×íÜ2d^ñ ó5Ìv ûs68ã@æi6W¢Ù³Á˜2—s¸È|ÌÈÜϯŒgß̃½1ž¹˜Ç^Oý󸞧_ó˜¿ñÌÇ<îãÙkGÇ3'Gq‚Ï>= Œwïá*z{êðãAÌËpìAÌËBúx0u-d.¦®…ì÷ƒ™ûEàäƒÙ§‹¸ªLŸqÍ;˜9_¬oõ{1w…ƒéóbê>˜=vxó`æñ8ŵ·Žo̼Ç}áà[¾ÒBÿÂ\ÏuôöÕñÔ{xd l“C¦ó­{Í!Ìßöô!ìç%ì“C¨÷xg‡€GN':{Î!Ô{xqïOÇN`þNæ~1¹;œ=9?™kêúp ì Ìû)ì!ñMãJp? |(ûö4ðÙ¡¼? –À¡ÌÇià̉ÌÍéÌãDæj9xe"sµœ½>‘¹Z®›HÞ3¨k"yÏàî4‰=z&8j};‹+è$öÔYì¿IÌÇÙàÅIì‘§pÕŸÌ>•=3™ýñTî“™ÿ§‚k&Óß§Ã'Óß§«&ƒïÎáÎ2™ýxó|xçöÆaÔy7à ùø0ê|:õÆ|>}:…ùYšÂ»Uܦðnûn ó±Š=4…~¬¢_S¨wxñpê9y;œ}røãpæþ<æçpær58ïpöýjpüáÔµš;ÀáÌÁpãáÔ³†~μ­aÎ<­¥s8ó¿\;•y^Ë^™ ;Ÿ¹˜ .9ŸÛÇTðüùàÊ©ÌÕùì‹©Ìñ:ðýTæió;•yZÇí`söLØYÓ˜‡grQžN¿.?N§Þ‹ÀMÓywûdúU|ë¾3ü;¦“#8}û “P3éï³À3Ù?Ïâ¦1“}÷,®ï3éó³À-3éÏ%à‹™Ìã%ÌÙLú| ý™Éü\B?go·pE?·Àæ˜E¾-ì¯YôñRöþ,ò] ûcsq)ýº”ûÏ,p×¥Ü% ÿ³™a„x,Á#˜ƒgÓ¯#˜«gÓg¹„;ÁCG°Ç.‡…sûérîG0§—3§GÒ×­ÜMŽdl nÚÊž:’>o…ut$ûj+ø¡>?F;xã ðP;}¾‚»V;s}÷vöíì‹væú öe;{è pf;}¿¼"oŠñ*nIíôóJæ¤~^)7ªêç•ÜÃÚ™Ç+•_øîJ欼r%Wævæww—v渳ù߯àÉ?bÜ Žjgÿãÿ±=¶yKÐx5÷‰Ùôë*ö‹\~Æ«a}ÌÀÊ“ÛÎx5s7›ù¼ŠþÌf_¥¼ê×Õôs6xäjöõlöæÕ๮ŒOe.g³ç®æ†7›½t5s%’ñiàŠÙìíôu6ûb;}•KÇø4öølæj;xPØ+> ¼?›~mgÎwmçÞ£B|:ømýº†ý=‡}{ ûyøíòΡ_×p™Ã\_^žÃ^¸Nñúõðøî / ¿sØs/wÌ¡_/àN1‡½òöèæýÜæÐ¯Âü¿;ÉöÛ Áwsè× Á‡sØo/ä¶6‡ù‡E8‡~½ˆ›êæÿE(qÍaϽœ¦•¿ü<¼ø"öÇ\pÖ‹È?—~íÏÍeí`¿ÍeíïÎ¥_;ÀËsÙG;èç\öÙæ`.ýÚÁ\Ïe/í€=1—=öbî•sé׋¹oÌe?½˜y˜ ¾±ò«_/fÿ̽’oÍÃ\ðë‹ÁMsé×KØ;sÙW/aNç²§^Â~˜K¿^Âb{ê%Ì÷<öÔK˜ïyôë¥ôe{ê¥àêyì©—²æÑ¯—rOœÇžz)øe{ê¥ÜìçÑ/$!æ±§®ån<=u-÷ÉyôëZæm{êZpÛ<öÔµÜ-æÑ¯kaoÍcO]Ë=g{êZæ|ýzør{êeàyì©—qŸG¿^«ò(öÔËØ'G±§^ž9Š~½Üw{êå,‰£ØS/çntýz98é(öÔËÙCG±§^®¼ê×OÁš8Š=õSÌÑQ쩟E¿~Š»ýQ쩟bÅžú)åW¿~ üt{ê§ØG±§vr78Š~í„Ås{j'ûá(öÔNpüQôk'8áhöÔNî„G³§vÂ^<š~½‚{ÁÑì©W€¿ŽfO½6ÏÑôëÌÏÑì©Wpg8š=õ æöhúÛóhöÔ+™¿£ÙS¯dþަ_°=fO½’»ÌÑì©W‚[¦_×7ŽfO]Ç~9š=uûùhúuøìhöÔuਣÙS×1·GÓ¯ëè‹sñ™°ŽaO]Oþcè×õàÙcØS×s7<†=u=øéúu=uÞºýº;À|öÔ Ü?ç³§nà®7Ÿ~½œ2Ÿ=õZðÔ|öÔk¹û̧_¯eÏÎgO½–==Ÿ=õZöô|úõZöì|öÔkÁ ØS¯“÷IõëuÜ…°§^Ça{êu0åЯױW°§^Ç^YÀžz={eýz=wäì©×sÛ_Àžz=¸oýz=Z! èÓàÖôéFø' èÓ˜·c™Û7ñþXêÛÅKþ]ìÝcÉ÷föݱìµ7Ã8–}öfðãBæü…ôó­Ü©2o厰ýõVæmûê­0´QÏÛ¸-bNÞ¾YDÞ›¹Ï.bÜ ~ZLßÁÝu1s÷NðØböØ;_êXNúŽ˜´½,'mßDz‹6ªPã<%ÒkL¹K.ê8O‰ô-ë5ôZ½HËV¾2oSm…<Ó¿DÕGW…0l"eËRº3haÚzõ"’ -M¦O¤¾i;ª D"õÛQº†Âgª‘׫ݓH!Ôö54Eˆ5EÝF‰Áhf“…E}MY½ÊžHÕf¢kè¦f„Òj½âtLº­)÷,‘Òk’΋6¬­IÙËKÓîÎyidªv4ç¥A¸ÌxiÚ­‰jÓ·{+4ZÉúÅïM{ír¼ öN9£NxW¬c¿OŠäÚ·ïjˆ÷×»Ò:¾f«c¿Oo´Ùß%Ý-!£[ä{Fãg5—B’嶺b´Å—H¿JÈñVyÏЦ½õ†¸²ŸÛIób+ó›1™ŽÛ·¹(o‘À°½Uí®›nvm~NÚÄÚú?'XêÞÏIkMèæçEøŠúБtãÀb“þyüQØ@òo þž|nÄ».îÅ{®suÖzAméîµõþ¢ô&UÏ/JËX(åå=Gõü’´…† T!­øã\S¤Vt¼ãKá˧E|)ìùýˆ/åj-ßCñ¥ä‘¦F|)ì±óâKáV&ÌÎû@à ùÞÇu<µ¾vU”ó±å”÷ Vi[ÄWб}þ(ªÌŒÝA½ZPñ§™±×âOƒÆ+ÌÃG@[Ò¦ˆ?M½Hjý2¨V,µøo¥ $4úQ6}èù£Eñ<|´ÈÍXmÐÉnJo6”µíîD„ýb£ìUv‰[£)Êä|T{Eÿ®œhÇ~ž“ñ9iJi2?GÅcŒ¿ /@•â›á—I *þ\.¹à‹¿«—}‰ ”fSü/à{©~Ä?Kk)þ)Šue:ý÷àRi)ÅwpG`þž ­PÇ7¹OUÀßä®ÙÀÄ}“;¥´‘â_²?ÀíÿÞo /ÿÖÐ0Ç¿’V˜&áŸ=8 ¨œ§LÔŽ¹@%{›MBº³þQž´CþIúîÚÿ$í6u⟴»4ãßžÐnú63*ægüyQQG¿-½=MÀ}\(¤óß­}¯ý{ŸÔ¹t©¸ »å~ ò´“DÌ´¼#%Ò– J¤ä%¬’Db~žÆ²Nó-䟜ƒ}¦#\Ç“œ¥÷t܈bبæ6‘z½µ‚Ê샆l”ˆú=¶Œ3ݱ$‡YTÇ“\r õ%¹SãJËßsµe•ªšèå<½;'xàu}ŠmIeo¸"ƒLÒ>™ Î1º¾µ£4!ÉSÏŒ3ö;³¿^fÇ™ƒÞ4+®—~^“§J ‘*ÐŒlåûo­š¿ÝR³pú ¾q ±…o8¾ÛøFsèLc¡z¼“oñ­|Ã^¾ƒo\EI;n€8Âßä•eMð6‚Ô‚“§skªHžþqüc@-TÓ5œhØÃ4™~ ”ªñ¾á0¯á[œ ©ç'»ž×1ˆé¯vR“—_%J†ø©U0ƒÕÍñ`©.«ŽÁÂiÚ(ƒ_×3øÂþz@ŽÌ€íÒj_Ï`©(ª/C¤Ì<žoÔß'óËm¬!ÂÄ‹øÆñ†êbýò7ý˜TÛÐV4DÔ€%1:£ÓÚglýË€B”íiš¥2 ÕWÍCåN@½*$½„oÜI\ŽY2å5ÃÄB¯å}=߸]Ñü ¼ãeÜ74ÓÃå6òN¾Õ%•šìÎ=\[;Ù]ÈSuŠ«RLöêؘ҆£œ${JÅI³¿Ÿp¿f?ꕃ°d/!Fõeô¨¸£âòѹ¬£ SƒKL”;A¦~Å&ȦEèÇö~´6šz?Z®”&`ø´¢Þì/ä+¤°¿8èêÑþÒÔœ‹göǘÃâŒëz ý¯û°g»ƒbüvwUŒÕŽUcm®Æ.¬‚ý“aÔ!;6ãXy;¡ ô&©â©¢ÍXÛ´tÏ_¶Y´iž4%mº©hba2±mºâhCŽÓ„nåûãJÆýµ6q¢[I6;~h,V÷·œdy»Ò&'ÏY3£ìt_Óä£Ô(lš -¨-u€6†¶àR]ÛÁ7GHæ@ùÙºk¢xøofóS|óî3QöÁB ¤ Û~oÕÉ6<˜úA6Ãnž~r,:ùŒH…­«@rh¬¦–ú×óùDpä’ðÝM“_ý4º«ø(V³¯LÔkŒ&‡JÕWÓpˆÜ™iÊ&¨HMÅ©Bh/N88îÊ„ƒûçÔ+{&#„ˆTÁ¡K2¢½*ä6As&Ì}¨ö³æéP¡eÍÑ¡ºði~•!À‰ÚŠr»=QzÙ_á›ûÖ½|s9*˜ Mw­äp)ªC“¸‚‚"&ÁJwÕä9\ûcæt2“"g2RTœ›ø&ï{ù–î_ÉÈ¿;yØSÞÍ: ®Ïv'¸>ÛìÚ5\qÝ&,7šoFhS~aˆ)º jSM‘žž:6åµq¦|,½1m¨9Û˜ÔœmÌtoM‘¾ ª<\P•‡ËǘöÖTmuí­©Ï«›ºà/Õµ/Š³ÏŽÙŸ³ƒÌ>Æ2<Ó<*Zןᵖá÷7fp¿¦ —Aßþ…b›ìñ!kuq;a Z\—Å9ÆnCm|ÍAä¸ÅrD.Ê…äÀ;9¾j9ð¶f» ×µ]9Z´Ÿ”£å„8G‹ü-úxÌ!(‘wXO\ŽAæ{."Ê1(žÇhW]Þ}<¹Dr¼Ër EìrÉ|å0å|hœc°æÞýË9ÈKŽX¼A¹:Æh+ǘ+â·cþÕï§`Ycg€+2>†¿EûiRUÅXM¤ø*cAT3ö‡{«©^UBm™3ùN¿¸É¹ypo^co˜8ÿÆu°IÓç~#u»P_Fjk(ÿÈŽ8ÇÈØë·Í#rààŠwZ4‡Ý”´jê•£Uw)åh]çhuNm\7I­R.'‡½Ié;«ã2Ý”ã²ïÆo/ã¾êöè©}[2ÚI^Âé¦ÅÂd˜ëw±}iðO*îÞúj/ŒÃ¾ê 4=™«ì÷7ã¦À`>^ ZËÁÕ„IÏ^ ³YËáuL³àZe°!ü õY/Ø·ì+›5áhÐ8ˆ0ÀÝ`Œuû@®.ûYL—±Q{Xì .Hö2-»®NÃbt¡œ×¡ Úà*>”Zö·<¹ðŒ¶{˜Î‘ó{4szÌm«ÝÑ+½ø3{¦«\Åv‰ãÛ˜«“[mÖG*b+ÓD‰a Q3À…˜¬ŒÃ­VVºç «¹…‚.¸`pCãì&†w¸¥€Ä;î… bôœk1: û‡µµ».Ú¼\ˆqyšc1®s-†”y»CÝÜmçõõ§.öU÷%¾‹i>;ëOÝtp5á.¾Äí$®mÝ1wÌ=ÓÁ<¢NŽr¹mà9>TtT\0q]&PmÒ«¿qµÿµ«¤†ÒÔhW·{Á°W@jáÝÛBL#ûƒ[ŒnGŠàt9Öå…ésñãÊÉ \˜Z¯¸*1³â2±.³Z¢®Àö-®VŸ—Ú½ÔÅ;1z€¯bBÊ/fƒ© sÜ!,5¶•qZ£÷Xªc%.—¡fîøhr=øƒô†„“1/$uœ÷€[ŠïZº®(®› FƒßD bl".Ñ~¡¿KLS£²ßj/ºÏeßú}}ûz”ÅVsáõ»[÷¬šI±Jô!œDCܾ¥"ËEâUr?öÝD›Þv“å[Ab‹]oA“ Î nªÂfò÷=&‘<ýÀàz®l¿ãfë·Ý>±lÂpÇ€»'ñ†ôuµå°ûŒ«:nöí6Ëfßr„ÁÙæö»Aô®+Á»=Ã=Æø×ÏßcÏpÛsšÏ‘®ÄØ3\ ¨z„Û°{^HŸ¨Ä8«ÒOTc+"7³²ë­ñÒPíí¯§÷o®µÊ ˆqÃPÍfï~!9l6|+У,Û'-›Åëd#‡ Ø1x0èfðw\÷^ª®¸:^¦š]¹øá±Ç.6sÂíŠßÜrˆ p5âêkds†‹äj„Kåñ~ƈi‚•¯\³.r £éR7¡Ç9 b\ñŒs ý_# Sáiñ¶5ŽI/‰÷@“˜nÛã¾›ëÜ+ãþ4ɼwÕÝM)L ¿Ùt©«  ¨»èÐ.7â:’Ãü¸ ¢ëIE\"µ}‡jÏÀ+ Æfº"f Õ‰“qènh—«‹ê` ˆw&wa¶Ãoü`L)ûR‘o¸üb’é n™ß‘·‡¸Ýd{r4¨§q`ü"°w¹.^àòãKÐø¿1/éê丅[âæÛ8np]à¾çg vV%0êªbxn»òg¬>våÏÄþî€Øo%†C‹‘?æzò+î ‚ßböFÿ´vµúÎ^pó·Iû‚ûZ-+l6)±/p(h<é nŽ0³06ÀJÙ x øì75Ð|ö‚[&¢ì®kYñÈm&{Ãþrö®¾u²èIrgÉ^àí¯vù‚ÛTë½ñóW}K?ðföO~`çìS]{Á̃ä²l„Ze~_d/Ø;pç²l$nªÙ vîr²l±ÚäÁ²`ke/ØXÜN²ð»jÃå´–—Ü›²øÒ«å€X« ÏyÙ8ê¨M»ž½—½ Ôv 8K\öá1}ÁŸ¶Q@Iµ`(î‚Ù Vmª@_µ¾âÖŽ›]ö̆*@öDW« ¼WÛ:8¨ã>½À/†ì¢*Ü"²x¡«½×j5sÙÈ^€§¹f/@Úµ‰Á±\­C\½kýïÖ*Ã{\m¦a5Ôêàò~É^€k3Ä¢6C(ÍÖ^pC¨UÏ…¡V+÷‡àNÂ4{Á¥61ÜXjµr‹=š½‰Ö:Í „ËOöäZ«žëI­Ó°XjSÅ%ˆ«qö4Œ7’ì—°Z?¸“ÕzWª†H¸CÕêàJUÛÜܰÐRÈ^páªuˆûWmò¸”Õzz­e9×v˜º†cà‰Õ²Â¤«m\<ÕÕ:ƒºÊäÒWÃ:ÜkY¹Öv—ÍÚ&àîYëWÑZ§¹™Ö¦Š‹jm:¹·ÖרZ?¸ÕÖæ•Kn-+<ÃZ‡àºÔ¦ Ïpµ¬ÜjjY¹&׿ƒ;s­.Ð5”g­¶_qSÛ‚\·k[Ûwmãr¯Õʽöîm Õá­­ÆuánZCê°íjh—lµÜèk·.(5LÉ䪚½à>RËÊÆ©½ÕÔöÛ¿†øÁx5Ì¥¶-˜ŸÚ³£kÌDÕ&˜Y­½ ZËʬ֦y®u|RÛ¸lÀÚ&`sÕfšée޲lÉZV0C­zºS»âÐw.fÙ v4þìÝ©Í=SW«Œ\ë" €ÚœY¾}xÁûÚU€ªj3Ä´Ô¦œMQÛl®¶à2UÛè:Ô²rû¨í84µ¬ì©Ú®âÊCžìk¦*˜FÙ º\C-Ìa­g\^juÀ–©MUÕö³Z›E®˜µM€'–’À K-+÷ïZ_¹ŒÖ&gBÌuö¾F­Cl“ÒâÚZCáàŠªãÞWÛ¦lœÚÎãNWë‡c`ä/¸Ö ‘Z Ôª¿OOªèç>1ýª÷¼ûÄô«ÎÐ}búU§á>1ýªý¸OL¿Z0ýª]¼OL¿ê%õ>1ýj9`úU‘ß}rãõæ/`ÕzŸ¯z¡¹O¾Zõ0ùªûã>ñöj/¸Ã×j…ÕVòûÄg«¢ºûÄE¨õfD­z˜µÝ£º™î£V¬´êEä>ñ:j»£610ªj/`TÕª‡3U½ÞÝ'VTõ†tŸƒÕ¦æP­2Bµ.ÂyªuVPmà"U·é}b.Õ6 LœÚ΃‰S«>NmSªUO§6Cpƒjý€¿S›Aµ:`íÔ¶œœ*6½Oü“Ze°9j;FI­‹0Jª¼ûÄ©"­ûÄÿ¨e…ÿQÛCð?jó ÿ£Öøµ¾Âÿ¨MüÚäÁÿ¨!øµÉƒÿQËÿ£Öøµ‚ÿQË ÿ£Ö{øµ¬ð?j[þGmwÂÿ¨m&øU6Ì}âÔvüZ­ð?jþG­gð?jSÿ£ŠÔïÿ£Ê¸OüÚÃÿȦJ û.t1ø¾OÌê•å>1?ªW–ûÄü¨!<˜`ðìÌwöæG-ÌÚV€ùQÛR0?ªw…ûÄü¨Þ]îó#›'1²îƒù‘¼(fd%ºëê誫#ý.3¡‰î¾s\~X!µYƒR›¬Ý¬ûÄ ©^Wî+¤–VHmR`…T¯4÷‰RÛð°B²ÛŽb÷ÁIÄO’”"ð׌ƒ<ý<ÇSwå‘jªÉFN±Dq#fjêñ&3«Â10q.Ó7#ƒ™ÕíOažé›ˆÍᘾ‰¸Žé›ˆ âø¥RàóLß([,Ç9OÄ1qœóD òi_ã§ÃĤª^ñ’9I™ÿ÷)oíUe/è°jH´Uvˆï¦"9×j¢{Ò2ÕàÖã-V‡®Ü8ù0c"ÑÖ#†ï'øĘ,?]b‹$bIÓ$%Ú¡Ä4%ªèe®?†ÁxŸæ ÊÿºOSRÃ}ÌPmK3aµÝÎüÁ¸È^05œÅìÖv5“]«ƒ¹¯ÝLØ 5”_¦¶àËÔ®:ðej=cÕ0 |™¬LÆsôN¬`^3KÜò²|LZö‚‰vú,†ãHÜ©qž#ñ-ýï7[œk(q§>N…ðc¸(f:•˜´"çe.­ÈªŸeÀŒÉ*à̘ ÇóÂPàÅp£Ì2XeЬêuýáÄd“C†ó-3G|mŸÖôw~uÿûó,n”V?·?§¸A'Šƒ†j ðR­ó°`ª·ôûÄ‚©m;X05ä ¦¶9`ÁÔ^À‚©½€S« 7åì…qæ[} †«nöLí,˜ZaÁdŒ^^À‚©r|"/MrωŸÜ¥@ª8Q-H [ø³§‡«X#¸a-H§NWªL\¶äéG_èÚéúP€·‚Ó׌\ÁàºàS¦ ·±ø%Á™lÚq1[æ­æ·Ûw´ù–Q ÒlTp †{±ýÄÍmNãü¶À à·Àtà(·ÀÜà>·ÀDáT·À¬áj·Àâz¬À|â–·Àä⬷ÀLã·À´ãØ·ÀÀÝo à»×Àx›ÁapAz|êA>Î… 0µp9ŒÏ<`wី ·eêÔ3+ã\1`‘áö¸ …3õ ÂE2žipcV`'ãN¹ 'Ën¸^Æ! ¶>nš ðåpÞ\€I‡Kç‚ÐzP€}‡ûç‚”ÓÔƒ8WÑJL °üpÝYÏàHºÒ‰éA „‹éè(¦éªUL òꧤh«Àgxb)€ÜP³Æë ÚFÐ:Fp } DP'pÐd+€PQî-€ZÑ8.€dQ7.€wÑ5.ÀöÄ[O„«ž×üôàŽJÁ,Êá~€#ë—Ü[¤rªàïÏî8È.pÁÀmvÛδ \=p±]à‚ãíWÜq¸¯à¤»Àå±þ7z¸Öàæ»ÀçßRÛ5.Á ò4¨¸ áP¼À½7ã7.Ú òߣäºM=(€¦q_^àV…ÂW,\¸oá½Àå ·ènb¸o+È·zP2±zPà†»u|Åà„½ÀU×ìîu8l/pÉÃ{ÎÝ RtS rí¦¸â¾À-_@®Œ¸’/HgW=(HùM=(Èý›z€6+.ê Ü9q\_àŠ;û‚t+ÕƒWS\߸§â¿À¥7ùxûÁy~AŠsêA»-Žö \tq¿ïBœòäQ=(pÆË1ný Ü”qö_àÚÓƒw蘤qª¤ ¬¸jÇô À½;¦.á1=(p#—Úm$ß58„,pWéAAÞÕƒ‚ðÔƒWú˜¤”§¸ìÇô ÀÍ?¦Ø1=(ÀˆéA«KLð‹ˆº¬ƒ˜à#Äô S!¦8 x[,ÀnˆéAÞCL RßU p%bzP€EÓƒ‚¨ÕƒÌ‹˜àx—uØ1=(HQ=(HY=(ÀýÀsNVHL ðEbzP€IÓ<Iå7Ê}Óƒ¼”˜`¬Äô —ÏX.1=(À‰éAfLLðÁˆ»»lš˜àÙÄô ŽŽé¢êAQ êA‘»WLŠÒ4S¤Bm|&¥c¦¥Ð­è²ur‡ÿ¤¢Ä”Õƒ¢Üç©E)a«E®Ò7r¥ô¨¥j¬å J=(êÚ$FÑ]=(Ji]ŠÒWð’$í(WJêAQŠøêAQŠúêAQ7=õ (Gõíá„¥l¨àÿQºªQ®´ÿÔƒ¢´ÔÕƒ¢4LÕèáz¯¨k«zP„£•Ѓ"÷Û„uTŠ\ŸzP„S–Ѓ"7à„u#TŠ\°zPänÈk‘ÛlBŠºªE°wBŠ`ï„ÁÞ =(ê§ÁÞ8š/‚½zP{'ô öNèAìЃ"Ø;¡E°wBð5‰ÇÊ¢®ÃêAQž+Õƒ"ØE°7úþE°7nŠ`o”œ‹`o´ý‹RçWŠ`oü‹`o´û‹r¨ÁÞèõÁÞhóÁÞ¨òÁÞ(ð¥Û­ÁÞèìÁÞ(ìÁÞhëÁÞ(çÁÞhæÁÞ¨åÁÞhÚuÕTŠò„©ÁÞ =(‚½“iîŠ¡ŠŠU\l˜v®'ÚòEÝU´å‹º¸hËu‹Ñ–/êJ£-_ÔýF[¾¨Ëί»Û7ã¶Ú\£'Å×ó“v 5êy¸À…hÓ-¥€‚™ÍÏë—°¸!cóparº&EÝŸœ®IQ×)§„ëL㊞ioqm<Þª¦Ó(ÅÜëcÅwg:M¨¢8òFê>&±(†z»ë´Ïè¿¢ª¢Jö ¬v:Áîà¶GŒ=ÁÝϱ¹ŠÜçîSšùçBKY—†Ó}âkÞ9Î]—Tµ¾¤X›vËêsÛnÁû§[N3©(­Û-퇢8îóÅǨvK×?uß^ß}çè–Ñ-ß!º¥ëbÚ­ \_l·äÀA}1¬ì"·ÔûÄˆÖÆQä×-u@_òa/·ŠcÜbG»˜‚bG…+°¼j¤;½Ä%¸AwâôŒßbÅžë*³±ç¹ÊlLw}UfcÏw•ÙzµÆÿ·©‹;,›¥'Y—OuÏN2J ÔËløë3óÀTct«¥Kô=pMpQwsfÉÎÀ©nTµ¾æ*vÿO³ß4»¦¶¡¹=Õ¶,1súÄéɶÛS-‰©ÆºdëĦšÚ%©ÚemÃ×”e€ëùx“)\_:nÀzþ¸ñÀêùãŽÀÌèÆš¦äAx*ÜT:n uþøb êüñ£¨óÇŽrömL-mL.O64®$Ê}kSMguSGc{CKc²º-YÛžjmÃç×êŽÖÖ{ÞÇ´/Kάi­›ÞÚ°<üÕ’Îêe„WÖ)¾²6Ê»ð  O6·w,á]1yï³r¤tk’Ë›RuÉFåŸÐ¿è Úu~Gsm{Cª™lé —ÞÒš¬oèdIoYÙ’ŒòÞ‘jNÕ×Gyg‘f}Š[ÓúT&[©¸©fi¢ègóÚ%.PAŒ{U[{ÝĉÕ3*f•Gùû/«i®kL²h„ÎöñÊú†'›9©\Ü’lvÁ¨à ©8R¸yIG}}’Ñ1y?ä^ØÐŒï‚Ö% Í5­+«iK‰zÎmçý7zë²o¢‹©Å† ϨoM&«ãŠtßY›¢³­ÉÖÖÑÛk'ÿ¶xCˆ®L-O¶Ö7¦V`ÒòÒæ¥ÉöZŸ&ZÞ’jkÐ0Dù9¾¬‹-ëæ†“’È9»è¦öVàêöêêQãúñÇq˹%Z,˜@Ÿ¦ÄUœnÛu‘{¨/Ó§(ÿeñsìÀ¹r5Ç qÈŒÒç*g-8ºêøJ&óŒY³zã çÎ+‡\‘ÆO­Ô. Çé7gÌ/Ÿ™‚.®û=—EV|oMëRfî]:6D¹—òø Ÿ—Aû m/tZô|Â:I²ÅtÑÔÀLƒ”³²º®‘‰X¶œã¦žh >¸y†lú ¥cFOˆ ~ã§Ç@ï5:¥ï€y8cáx]ünzñ½WˆJ…¥íœÆ(¯9®ô´ÑßÎNEfö÷Õ5Á,Û•ì­sWF_*j鸧MËÀ»¿\’0ãÙùZ&`ÆûöΤ¢Õ5 ‹4Ugñ…íËØ÷¿bÅG¹§•ŽSåÍ(ím0‰¯!Ï´(÷ÊÒ1ãFEÙo¢DòÕ÷Oñ²".Oçu,½§s …VNUn7¶•c|!£Xü,•Nr/áN5+ÊýŸGD¹æóÈ(÷#|êötŸ³£Ü/rÄšå^ͧ:ôk|*ï§ùœå~™OyŸ¸›OUñ|ªŠßäSUüŸªâ3|ªŠ¿ä¦*¾Â§ªø+>UÅ_ó©*þ†OUq/Ÿªâ«|ªŠ¯ñ©*þ–OUñu>gGÙ(ÒÚz`0â·Ç(ÚÞ†.Ù”dÙò ú‹òßïN§ŸX/n‰T…³']2V.mì—¿»¨¥¦ܳg£º¢¶–V–¼Ä@§Q„vÏšŽh0S<¶’<êûŒÒ næY.vg‚¼YµŒË–WZ·Vêƒôå¿ïKß9½ùU¾) j(¢_k[X“÷)¤=|RsF:•9êÜÓy-ž: 4»µð÷¤Þœl÷›Çd)?¯Ècëz|zIC{Û²†z0ÌÒkѺ¶´Ö4·56=µ­Pýsq—£œœ(ÄäFùGÒEÀdñ©œdµ“šùÔN:ƒ™á€Ð½ ´ŠE¥ãJØUG—N(asç¢óùÔæZÀ§6×±|js-äS›kŸÚ\‹ùÔþ;§tÂj}:Ÿªõ|ªŠ•|ªŠU|ªŠsùTçñ©*Vó©*Öð©*Öò9;Êk+U\\åµë{Z”סïéQÞr}Ïà4À÷Ì(¯Sß³¢¼•ú>"Ê;IßGFy/Ów{”×¥oÕsßÂÆ¥³ô­z^¥oÕój}«ž×è[õÜ oÕóZ}«ž×é[õ¼^ߪçF}«ž_à{:õܦoÕó}«ž_Ô·êù%}«ž÷ê[õ¼OߪçýúV=зê¹]ßªç·ø~*}Mߪç·õ­z~Gߪçwõ­z>«oÕó{úV=¿¯oÕóúV=ŸÓ·êù[¾gRÏ×õ­z¾¡oÕówúV=¯oÕóM}«žзêùG}«žÒ·êù–¾UϾŽJ…úV=Cõ­z†é[õ ×·ê¡oÕ3Rߪg”¾UÏ~úV=£õ­zfò-˜T§oÕs„¾UÏ‘úV=íúV=³õ­zæè[õÌÕ·ê™§oÕs”¾UÏ ¾µâJ ô­zÎÔ·ê9Kߪçl}«ž§è[õÆ÷ÖÞSÅT~VGMs{GSÛì’,t@IWÙ¥”Q<»…¦F¿\^¦Õj­|ÒE´äËÓ\DÓj¢)}»t”0Ié&}ëÝõm¶êt‡J¾®o³Uõm¶ª¾ÍVÕ·Ùªú6[Ußf«êÛlU}›­ªo³U§;TÒªo³Uõm¶ª¾ÍVÕ·Ùªú6[Ußf«êÛlU}›­ªo³U§;T2Kßf«êÛlU}›­ªo³Uõm¶ª¾ÍVÕ·Ùªú6[Ußf«Nw¨ä }›­ªo³Uõm¶ª¾ÍVÕ·Ùªú6[Ußf«êÛlU}›­:Ý¡’Kõm¶ª¾ÍVÕ·ÙªúV=ÏÑ·êy®¾UÏóô­z¶ê[õ<_ߪçz¾A%¯Ò·êyµ¾UÏkô­znзêy­¾UÏëô­z^¯oÕs£¾UÏô­znãTò}«ž_Ô·êù%}«ž÷ê[õ¼OߪçýúV=зê¹]ߪçƒúV=ŸáTòÛúV=¿£oÕó»úV=ŸÕ·êù=}«žß×·êù}«žÏé[õü¡¾U{TÂÞ•°w@%ìP {G¨ÄìA ³w"ÌÞa¯±wÕK¿Ñ·êa﬛½#´nöŽàºÙ;Âëfï°›½#ÄnöŽ »Ù;ìGöûq}«åÜ6y“M^Á[“W°Ôäœ4yM^Á·(o_}«ž±úV=múV=ÚWÓ´µ¯¦i?j_MÓ~Ô¾š¦ý¨}5MûQûjšöãÑúV=Çè[õÌ×·êY oÕ£}5MûQûjšö£öÕ4íGí«iÚÚWÓ´µ¯¦i?>Cߪg¥¾UÏ*}«žsõ­z´¯¦i?j_MÓ~Ô¾š¦ý¨}5MûQûjšö£öÕ4íÇ+ô­z®Ô·êÙ¦oÕs•¾UöÕ4íGí«iÚÚWÓ´µ¯¦i?j_MÓ~Ô¾š¦ýøF}«ž7é[õìÒ·êy³¾uE<¹è—B–Û4Ý?ßWSV7‰;³i Æ\Òx Û舘 1³ZäˆB2>kê‰P¦Mï0çXsuCÞ*.t(RÌÒ²Ìô%þaQò%ÀÁ¯n—Eù¢ ^ÐÁ‰{RQG \“µé35Ü%ñȶ´ƒÄWV—Äy,âE1–6žƒWç…ªvrÜPü¶Ñ¢¯m„ÖØ³.gÐÞ²%¥‹j/cu‘}jœgÆèP0Ðcš Î5Ô‰×ׯ´úzøS3yT•UV<­´È!á(ûõ °„–V×@CBÌY9·$¿~PéÒ6.úÏBD*Påjû÷É·Õ^ŒéfyjL¨‰ò¿Ï”]Ò.Ö’ŠúTxISZ¦µ&—“P|P©n‰Ø´Fµ!>c93¯õ¢XtI% „…bI%³+§q†[®Z¢Ü_ÌJ•¿$ÊûIßN‰²[ W^FØÐ©t\†Lh›&8¥(&ûY–GÏPˆË!6M P j ­|—]@SÓ@oÏpò'ƒcP£¼ JGÑž~›¾µ§ß®oíé›õ­=ý}kïßÁ·Voù™íɦLtG}CkÓŠšVAà†,¾ËÊæŽ¦%ÚJŸV.-€ƒJGÆOç¡9€èf²Lù ë±¾_\:zœ€ÉKô­øKõ=šý%É—úé,Ö6Öœ´Km¼UÓîâÄ+{kÙüiÕsŽƒ‘ºxÖt"+§Íž^]Y6í˜r¨ø«õúäòé f;ºÕ²yå0ªV@åáò²ã*æM²ÓËf—W•Ï›ïr,_PY9w^Uùtf,Kç]1 RÖ±³æN;¦zîÜyQÞÔ1…¯lk…#ð·ŽZÚ‰G çf}«Q§ñ ú<]ßš¢I¥£Ç }NÖ·š~˜¾t¾…žtÅ8B(pß ÀÍú> ‰)pSOÀA¥^8bNGãk\RéfA‡Ò 9ü™Ë¥,%ëj<Êxàü^z:ªËÅO‰šó½¤¤¨´j2Í׉ øõ"G V¾5IG·LÙ;ÐJ׺çQþEõª,*xSš¨àõL£³E 4T+™#QV·’·°ìÏ þby=‘õ×Êo  d[P'/ĈµB—²ÊË?$pÊ{\¢4•1£uÁJ©æ¢8t£fÍ„’$¡óOtÙâ4 D3ôZ‹…FÛîÝ xhüZÔ]Ò‰„pQtR‘Q»Óm¼<7~å‡Õ Š(ï»bY²Y‡ZÝÜŽÐMeZŒÖêwT»Ò'Ý{1ÁšR^Ì-Í&».0•†Ô÷Ì+ùËoŠ3Dys•rº£Z²ØÌþ1-/÷k´­(ÿuý¢ê¡K í\HjeÜ^÷¨xc \¸ô,8ú¢ˆF‡ºQyvM[uc £wq ÜN¸Áÿ«¸ˆî¯\!ÔuGWÈ#¹î”o lËLéæ–Áœ‡ø¤¨6¹Ãå‘:é`s¤.›øæàò,}kÅ_¢oÑõþÄo»ÝåhÙÅÓüÞÒ^|ioŸ 8R—]rŽä“|:½6ºHoœyŽÔ™æ«|sÎûš¾0t>R»Wç¹#&…—¤—IgÚ%ïŽÔ±oßñë[ ÿ/üÙÝC³?t+>R7>ÝØŽÔ-O7¶#Ù;åKÒ›£«÷&±ŽpGrì+Œõl¥#·ô–!åħ“Û‘œö¢¯VWÏ«ª‚¸{¿˜¡Ô0bÞ|ŠŽÅRê|°'…Êû[|aûøÄ/Û6 ÉEÛ·GÄ#uD<¸6ݾΕ+OÄì|YÞ{Çž.žù (|ç~œ‘Ôm-…yÑi?´ ýê–Ûê-Ÿ–no•^b޼í‚ÃZ$í)*oO'ê`«²bÚu¦Õig‘—ñ™zø«Ü“ÛAÞñm™Ñêd²O²u‚dƒÕ—Ø]9´Í[-Í(Î¥™ŸßÖêÒ×ñz™®w¼TÑ[ÞÀÒüêN¡ñQ.ÝcÌ“«ðÆ?Âôø¼?\¢_=qaˆïøÃ£ðËûÙñs¶ñN‹÷ûƒYüºmœÞøu›±‡-ì)¬· NãC)‘©Ù¾”å×Ü;—{SŠP¸g8÷òžËŸœÐÞòÓè6¦ö üÉxV÷¿iãÀ>˜ëh¿:Ö¨ ­äÛRؽ+Gجï~ÍxRMh=i/‹¿¤)$UÒÞz“÷§¹«]mâÓ.ºˆíÐE”ìÇý¿3fø£ónÏD`¸~I¥À²7;à²] 1SÚažˆ;ÿøøÂ^i;E,«vî‘•ŸmºCîÛ\4ÛÅc«þJyÌ}GÉÛ&BL»/"´Ct©|ù¾KåCMu¦]ÔQfÚ¹ÐÄϸïl¹oùrSm×UGt°v1óŽ-úóƇ@Ö®3Ž.4ím’ƒã þgÀÞi‡“<õ¿n.'¡Ý•”oê]ïÑVü vñ~éÞvíŧðÞÚÅbì“Gáoi\ÑïÑtéÅ>Ï#à~R»x â'µÃk(Ãh±|PÃó'ß&äò-!S»ˆ".µCx(ÿ¤Y¨T ;¡˜xíbö‰×.²†xíbôÝî”xðJ;“´«›Rm½yEbjãO$v˜~•%nõæ#£¸{íâ^øäÔ‹4§­s§#íZþÚuÆV¹©¦µ¦IŒ ‹ýL³'RòDm̾“êš,þRO/^S˜¤Ñ¢¥J¢Ð`2ÖP©,Rè„J4?­ˆän–VUÌ.¯®¬¨Š ¾ª'+ÊÁ¹8¥¬rþLÈ g–O;&*x•^žytYõ‚ÊéeUãœ=ãLWâ3õò乨­¬,ŸS6u4âëݛų«çW¼ i=S驳!v¬ÀÝ|xÁôéÐ?ÔŠoùêÒ$ÑôD².z1Íž|2ódº=ùµÌ“öÄTgŸÌŒŸþ±·_táîÞrÒW÷÷V”¾jè-Ê¿*Þ©W'M^ÒÌ R•Ï*;>Ê9Ü?[V6ŸQ±¯ŠûùWˆÓHýƒðq³æVVï2.÷ŽÌ³¼9Ó%‹ÞÞûʶùòÞ'&Krdï“åUeU èÜo…G’6΢ÇfÊ«¾²å]ÑûÄ–÷¾Þ'¾¼¼Çré%*ÚØT†ÿ” \Ÿfñ“,>Ýâ'[|F—P„Ë/ÉrŸZÒF>«}B9 Kkõ¢èÝérÓ'oLWœ>ysºèôÉyéZN˜«éVÑËÓµ¤OÖ¥kIŸ\”®%}²º¿umE-z²¾¿=ÙØ_‹Nü·dj9ýØ(÷òL„³i2ás2ù®œ”™EÖÐéQþ;Ó/–Ï*;Ù«ŸÎŒ§Kák˜æSüyfb]ŠýÓ/\Нf†Ø¥ø|ú…KÑÔß‹tòÒ‚]OÒ‡•—÷÷&KiÖkÖ£,åÈþ^e) Èz–¥|eï²”#6ô0}X1ÐK³-nÈi·¼oIÚE›Ì¯ ßB›ì¦þÙd§äͳÉf tÎ&»º¿m6Ù‰çÏà¢ñÃÇ«âø“g’½|`ìL²wlœ9“Ì€0p&ÙS6N›Iæ÷R:j¼Š?5г…ÇϪ˜3R ü½u4.{ß0н<íâþæi¿<ÐÇK×QÚ»å•Ø±½­¿s<*lÜá&U[×LªlC‡TÿøŽ™Tgôˤº«¿[<*ûd½²°µäŽ¡]ö]ÙW‘uÌ%ô@!mšKèG3ë›KøÖ¹„S7vÏ%ôH+m {—í:—ðä¹Ü ¢Ü û[hŸ•¾7ÐA—ÎÜ}òºtY›jé<üöíséü*L»çÒý]óì³ÄÝ“B˜;:ÌÞ…8#Oú˜¿M^1ÐÅøÀþV†ÄÏègHüÁþ¦†Äçt6$öë·7[ð :ç—Í!†L¦ÀÂüqáŽè0¤6ç®CêÝ;¾šzéd ©ß¹9†Ô-2¥Ç uEó§¾’[Cæ‰=™s âÓ3)ÌMË<±)^mñ™/I?±)ÌQñ™™צŸX0iÖDzyÇé¹póf—UFù3ôì8N˧Í+/Ÿå»Rl­$é|œ0vlñŒEžZ¸ß)å g–ÍãôrÂqåþe´\/E97 ˧ÀKòÝ1”': W1ó¡z°¨|ê‚£fžªÉJov};yîü¸oå›Óñf—M5¦pˆÕ û´¸¼ÓÇŒžZQÅ»³fVL£ãæŠÞ™‚J9ÏN`ŽòÝØUßI´ôôéQÁ9ý£<‡éŽ;·Êµ^Þϳ«ÞòŠ£ãpé•ñQ÷”ìæD®n_<{î¼ã1¾0çáãʦÑÿµéGF#8r÷#wWSØþ’Y•»ÓÉ™§§.˜ÃÌ€kK/ÐûD¾3+¥póªZ¸€‹œîó©ž17>)™Å[ùn¼ÔΜ/,­Už¸óÊÂÊA`BnKü£Åeû~i:z,QÓW]HÔ2]Dt{&Ó2XúityçY&EÍHÚ·ÊdFÈDO®,ðÑååGWOã>`NÑþî-åi½Ä:(»Ÿ°˜úÇñà—{Ïú;¬÷ÁÒéUÜhÍ™Ú?у8]øñ¼_9µl>8ÀÀýôÍÒŠÙDbwIàÑ ™DfÛ¦ol¢òät§›UFì‘-{ d2îÐñæL¦"q<‚ê#9IøÓþG p”`Ñfžèä(ë©ýoN'÷kûß 8rÐ@7N­d/f#o_Jvs>Íß,âÍ_ d×»ó7+x3©ÿÍrÞ4÷¿y*oÌù'tWo²…cß,ãÍ¡ýoÎÀ€Œ³hrÎé CG(¤çBA¶|ÍÃiÁ™¨|zƒ‰y]¡Lé [1½‹ùMTº„†ua£ª"ݱ+TÅÓ}t¡:óŒLTY™‰ª3«2QÕ›vt!õÚÛž%Ô¤{»˜éðý>,,#“>º`Á¢©x½ða‰¥HÛûðÂjPJä£B‘ÇaÈÀ‡O˜SIê>,ø"†KZ‰L++ËçLwÈåi鬧;JráQÖ¾½O¦Ço W @°§¸Ô5//ŸÅã”GìlùX<t^?H›õØye@íâj½\1³‚Å£=³¤¼z·ÙÞ°ô/£ÙŸ¿VTÏú|wÂÒ2–Úó#Ù¯4&RØÉQ>d×@@ü#™ÛóÿZæÁòªy®mwëÉÒ ª.,ÃWÂêÖ',•Û-R|wêMIIMÛ‰>Xzi+"&Òc±ôµ¨`B²YJ!Rwyz]±”§¬G‚ø:IŽÛÝ“Ê+Q 1.•ƒ¼ðpù×µËR²-]ÞÞÐŽæHüŽ49ÎI†ˆw*U²æá”ÀW*Zy“Ñ&eÉgsR ‘hJŽ‹õˆÉ«WJJWŠI§—-¬žz|X«ðRÆ-½íDB°h±‹kB¸«ËvjQup Lë(¬²žåÖ•àG2OçÅ,zEʯ}nEÙÔê…PN]åK¥0ŽK¥©F”ï†KiáÊ(•i<•_Õ2~,5FùG æd¯BŠ@©¢¥Ä}Þ²$…E€âK–ÔHÇFŠƒí(–«Mäã1¡ðÒ™–gÆöI¶#‰X.öþ ±´ ÛÑJ¬Üd Ý’‘%ŸÒŽZbôKËÔM<•Ða;J+…SªæN‹ nØÊ¸¼së³ø¢i¤ì §^ü ß5Þëå¶xß{äã’‹î—dùÒ£r9Ñ?l•i¯|ùqI×ÒÚG]c§Üò=)¾èŸÿ«6^aÞï´ã3þ]z0iùåÁâ?þ^d/¹ôI½Êg—ñgý»Šo# ²]9˜´¢œ†O#Œ‚DyD|ÖËŽÑ¿á}W$°(²ßÙüÇJ©\÷A[ùÇ×[šì7ÙÒþ³W8úTµ§ù‰üÞñÕ$oX¦¤7â ƒ,úÚE»ò—W”Œf™¢‹é,üªÎÝr@€ }¹Âä\Ë6ø}¸Ø²zÈ JL6ýPnÌU&7S¦²!Wà‹ s™®²ñ״ÙÒd¯Ë”Öú×XæÂA”JëÖ’ÑžŸ¨¯¹âäÙË7ú"üwa£oU¨¡F{ݯ°ç²Ëé—É>åØ1²Ë(8iÅD£=·«÷¹ì*6ûKøµWe·Ò¢Ñ^÷+ºô²fÓÞ#·Ô:#+íý€ì K/7b&ýØòC§ªÞªŠFûîÐ5tÈǘ©  +—m2†%„Щ*:bë=Ò!»[¶ˆã0:†ßQ­éÎ[§–ò÷ÏŸ¶&*35ûÌÙšÜPÚ. é’Ë…™I~É'È*p6Ó#·ÉMºä²nf’O­2¼f#=j»¥Ë.[W&ûa;cÆ §§éDÛrF¦Ë.›h&û”Kql ÷P‚Ó i¦€#?ƒg3Í£¸ÛO´çö3µ+DÕL!³æ¿ZBÏÞ3]×ïÚ+™€Y¦Ùraë3[êƒË\½¥ûßý•sÊ#%ÈÙ^"×»¸å€£ZÿÃ+X¿Åì¤År©bßÈï+o΋}éPcÝHNjÆ‘Ôňv·Ù[üvñV.ç&5·&‰¨¼y¸Þb·®È[9¡›Ô ©FïLN¼=–y'§t“šëA¸¢ç¼œ·äã|‡Ë¹©›$Whµþ\¦Ô&³ÅÈÙ`1zQ´˜¹ßºzqzF½rj7ñbGeÒ÷ÖÜÊôVnî&^\1gs4ñj{Ë޼r|7ñâòyóíNkb òV®ð&^\Y6§bZ„Þ·í!w,z(çx™Ù==$¿ï!uúšc ‹Ñ·¨<µ‹j—&ÆFm ºÝ,?~¶œwãÓnäÎŽÇ4±.»5§/4õ5—ù5Æi&y$dog©#‡&¨Ãǵæ¦#‡¦¥ã…f$«¬f–qÓÇ ïŠå}ÎöåÝòïËÛ,Å>–÷×m]Þ Ñ®ÿ}y§=ì›ny¿‰Áþù¢”sÂ7oÄáà\ùzÕ屿–xBìCayß°}yoû÷åý¾‘C-,ïÓÚº¼7ÞñµíËÛ#öîå=ñÖ! –·G›ÛÖÎ-¨‘úäq³ñÜ‘—âkÞ_èæÇ‚ø¦Öbo<¥kXö…gÞÜs×™Ÿî¹óÌs{n_› ;kÿžK&átt.[£}qÖ0ŠÕ2‰&á~sg¶§FÃKð1èßmƒSqoÝ÷Ì\¥¶ã¨´ÚÃ6œƒú<í|lËŠ•ìUv ˹ð4êÞNÝÛ©û”n4Ô’¶²nMjí-÷_¾ƒ]”¯ÅñEˆã-†Äyåí®Í"‹á)x©Å˜U–éYSÞü4íœöHèw>šÃ—t;Âf6 Âsò€òæ5Kò¯íìsº³•kÊì¬)†Ñ_S_ƒÍ¨ü®FÏbFåW´ßñ¾Ãm}ì³~ϱy•'ÖHã£ÿýŽ×¼º½Có¶+Ü6ܹ¦³G3™¯ùš¯êLÙÞLÝ6S¶ê|vš-F¯Zm^Dÿ‹v·Þã/ºÚ{Åhï=}óW6ÜI³ëåÓ´ßû ïû]ļÂf‘ŸØ~ïó»È÷—}“öUºs¿hïoöP{迉o‹žÒ3ÁΩÎÝ‘–LôL#Tφ²Àx8†…ë;~«[mè×h‹áÕz¼Åpr=¹¼MXÓô»ÝrãùzžÅp„½Ôö<ÉF»ùùÑbŸŸh-˜¦÷M¾sð¦=ØæçÚ;‡žø¹c¦üΡF¿s È€I䙵ßoÊ;Ú‹¢]&Ûj[Gòv®Ëw¿ßôb‚tåüu.®W'p£×þ_åæo sؽƒ\Ž >‡bv^kÇi®æ3ÍuåMãJWƒ'ô.YÅ:gœP[ ›ots e²sn³™ôóÉN›l1fa¦Í$þÁÛÃS¸¨ª¶áœwçùÑé%8‰Å8êÖ§ä\Ø ÊÝÚ=±ðìó£5%ßÇŒoŸ ñc£žîЛìûFû^GŸbÅnÈÝ›bT7‚‘9ùÔ(Ñ%¿çEëô}CNt>¹úYì­a~CÏèÎhßX¡Ýp¾6Ö4ÂÊ'ùŒ†0»ßâ {>{L·Žo® ¶TQ71á1Í”ÚÚ‘Ë£ŠŽ+¨ÃG?oLqbô˜‰ãJ&I¬¬91µœ“L[ygKâ _L¯‘Îc¶j’‡é‰c<(ËM6.Ùå9–?ì“O¾tÌ×6¢rþóF'šR8%ÄN·Ûxư$¾Y»öÃe=·¦q·DÛÙ©ÛÙ§ÛÙ.ÛÙÛqŸ»M8&à»Gãüv¼iî&oõP@;·¯—pméy»æÞ·r ¼7¯}[Íkñ@2rõiÑޫψvOç~à-yéOûM˜“Öc6>LÓÜÚÄ;ë²r¹` :N ï7œ]èvŽb;s¢‹Ü÷öèâ\ë]ÙíLa¦­‹/$×­%«Ï…¸Ù™ôÐöèûn³ïñö=½jûø–h¤}Oµ·3í»Ý¾çÙûù_dñ%ö½ÔÍF!ª´ïÓìûtû^nyϱïUön…ÅÏf¾ÖØ|m"V´Ø³Ü÷[¢VÞ4͖ٛór}ßšbßÛô½µ6»º¾ä{»µ–¹°ñ¤?^蛚}ÜÕøû¾×¾¿nßß´ïoéÛí—©éÛỔ®9êY«½móoWa¡¥ãíøp/IïQ`W1¦¡éËï´Ó÷ïÁ˜øç÷·鎰˜Âß ¸?µ,ã1)XfrÀ¡S-Æ]Ðß®À‡òîl‹áöKˆí´˜¼DG‡Ø]V‡¼EGר;ù‹Žn²wòýÐbÐG¿n9ð;]´ØuD&w¡4ÄÎ 1‹åOº.—]x‡‹…R<$Ó¸§Å³ó§bÄbô,ïâ¡ =vƒ­7,&¯Ð|`ECcc¢;4k²Àz.þE/iKp¿deâàº4HlkoM´0ñ¥-ò˸CüeqÍÔ¸Fw­99ׯ»)Žº¹y¶Cû«m»€#F÷]®çµ.:ƒ‡êœˆÅjVVÓ?¹uõ0¬|‡´„¹ö÷9æÚïæbQ¸ÛéîdfSÞ°wß,nÔaÙͦamºÙ’ìè`fK~¬Çßzâ`öúTBDÀ¶öTÂÄÚ..é™À£ÎQwDÌ€Ë Éy,¹åézü­òÿ9áàâч%FÔã´Ê¡â¶#É>½3šd9…( —Säñ·¶á„.õ´zš$ªæ(Î’}ÜZ“O“«5º²¾²·åJ6yäHyü­’'’‰O(­›•‰ã¸Ë#ÜÑä)wü­®Ï¦YðÚÆ/K¬hh_–Hu´/Iàð ¦./ÿÃÉ+Ìãoíh>±9µ¢9=ë›{§&»öRÔAѶƒðÜ7hÆß:p—¿nuÏm鮥í8ïö· ùv¿*ÚÝßÀóé-nt´¸ôÔì½µ—¶åEcÍmîKì¨Ó^ÃV³ {yÜj1§pjÀŒºÇÅò®[Nkr{p8ÜæÜçT®¥–«7«ìÖ×Ú•< Üâpß5äfOþ XO·¡v¼+oÍJ˺{®_ æÚvJTEÞæ¬–îÒ¼Ïg]ž?¥¦Cºål]*ç·Ðßyâ¸^|å5D•êµzê{í{lðqÞã­ôxIèñ9é¯îï1¹Þý°‰ëï=}·z!¾mu¼WÿuCûŠõ=þ_}>šÁÑéyC|GmTIüöÚÒS£ºÕHÂ\u8}nŠJª† Ó÷̪‚áùžZ•¿{ ß“«òãùžP•;b,ßmU9%Å|¯ŠŠGw-Îéìêæÿ.þßÁÿ{r:O>ÿÀœNê½i7íãƒlgßU1R†!¢D¿ÓÃyq™s‡Ûï‹iüm^þÖ£€eã-¦Í{L÷¶ F‹í~Þ?Þ}.SGâq³êHâ´šŽÎD¬ß’N†ŸEÝ¡L´ß«y¼¨¦ŸwššÈ#|pÄió“õ‰*æÚð£Ì{Tn¸9otÏa4Ë÷­…AäÑ]&Ïã«Ív„Ð^4’<ºÏqZﺶka&ëÓÏËNÐbD—óPŸí2ú¡»P÷^‹Š|yáŠÉ£»\^çÔÎñc'¦ <Šø¢1#â§æ”c®"i­93÷Ý©afŠP=QÂÕ žŒé·î»k°±tX\…m—_ÞýÍýI7͇z`w¸Ï©kJô4rê&zÄim+YÓÅk;ŸC±Ò"ÜÊßÎëCõqƒ”/Óìç/Y~±¨¢qä×ÝîˆÓz÷|¨¥óJ4Ù ‡ßÑ÷B¬!ƒãt祖Ýw§Ï™èJ›pX4â:»7IóªxXà6xÄiއ2®ç»1휄jß\ªÛŽwwÏGÙçj+†¥u/hu·ÅõŸÍwzƒÒÂà|m½ôÞ¿ig3øw“÷`û_=½´»`&±Uº§ÈÇ̼n.±íuÑ|n)î~ß”¾S©Ýl¦ºšÄ•°ï£á}÷ ½ÝqR»ò§pXþMòo)íŽö&Fã9¸^Nì7xs/·¢ Ä>CŽÉ¥ÝY‹‰Ï\ø«oܽð¦;î¦Î™ o*¸Ûj^²ð¦[ªÛÅY7}¿‡Yhð|Ó8ë¦oo|çúåoc£‰ù[\‹fH5©vñD²ÛÒbó,Öl9ÎéW'»ñ,Mßù¤)Ä\úY u_7-ªÃÐÀ×Ý ¡¥½'Býý )®Šö»{Yn¦_z§–ÖÔ£:néåþ*~£q.ÓÜz³ÃÞ„<[TÇŠ ¸[å;@ïÎq»¤Ï´á­ØY™¯Þ›žvö­VÿèIâÐg¸4ú~ýw£y“@®&öÑhþÈý¢õe§æì̼o v3³þ^b3‰iÄ'k!ÖÆœÝŠ„MÄÞÌ»UÖ{;{aïÎ&vKÙ©¹•äk%öNrÜUÚ=™±ƒøÏ²Ëv”vçÂIIÿCj¾\íÄ´ƒ g¸46º†<ª¿0‚ØGɧ>JL;¨0‹wÚIæí=Äo´Þ|w[y÷b÷ébwmšõ|gŒp­|n”óÞÕÂÒ27>í7sãËf­a(ñ¬Ï<ž7kªòp¡ KÜ#ÿž9_Ñ=òöMw¾Ú¼NßԟןÍçíº{öJ¡ª—ÚýÞðÊzowßÃýOnSpÓó7ŸÛØ'áaúÝæöÊG¹ÍÚïyŽÃV`+Çõ coÏ œ±a>’ºGòÏì×äç$ÙùÁ9‰]/©;¾êžºãþû¾‰»…1||E;GøŠnÈ¥hrU”ïnÇÑ‹™«ŽšçoÛ!ñAÛß6l{kg¹çíÝêW­ÑåîÃù››Ó˜¶Úïhí@m¹µú…|«ÐS¸ŸÙiåû^HúãùþvÙjðáõYÜÛ¥õÝ…ý⨓Ûú&Çm¶¯ÞÓzDåÖèÀoª»êF±ÏÝž¹óy~¼1Ïoã¾ÞfÜwÝ”uw·1݈ųÎÞymîÏKà Þß¶¹-{møpìwã;B¾;-ög´Úßï¿Lìl˧[q|I¦ŽøR{§»p|µ½ûsbwÛ;Ý|ã[B¾¯Xì/¸¯7XÝw“½ÃÝÝs$æ’xÞžøcºßg1ßÝwÏ'÷&{§[mrN¦Éùû+b·ZÝb —fzS¸<“¯à9ªµèy뺣=GPùŠ'Ø;ÝM‹ž/¨ÜÅÎÌÜ×XÝH‹g…Ü7„7[ÝG‹ 9|oÔ×bo?îµ|º“–¼Ž‚ò•r3»¡´sˆM1?OêSÉï ÕTZ–©µtFx·+³J~nt-ùY¡n¿?Èáç^·×’ï9îÉÔWöÕWö;O7ØòˆL¾²çn’Ï÷鯉yN$¹¯µÜBÖe?ëäÞeïto-‡ù._nï´ÝËžçÁ»ÏÚ;ÝEË·…wž¯©]Ubžû¢;hÅk¨O¿ƒuë¬øžéXñ\ÉaVü¾—˜ßÁº{VÂn¨œcïtϬx¾)õù]«ëaåªðNŠu†§ò·÷ðTº9žŠÑâu÷MDhወߺê_pàjW-IRÇ^‘+¶´&j¸š0œ‘ù®±Üß°û¯8³«þ¥Ÿê™V®hMš;XÔDrŠÇksJïrwÖ) ™=á¿­A™™:Ⱥ›ªô~bîÂÚ»ê_ú¹ý»xýÛ˜|qŒ¿n7Îy%páÌ]ïmpœ?ݰÝ×ÁÙ×p“hàÕŠÞÆ×WMK|Àéìswêóèn1.YTÂõ¬òü)¡ŽÝ;©‰ðn[Àâ¢'sÿ›õŽPžÝ\i½QžÞ©î5¹Ý÷¼­Õeú²æôÁ<ÂÜâÂ}ËÝVŠôŸš¶ó-Þ·ãΡ3òõÀ»5u~xŒ&Ÿhñ6wÜol÷úè$t»½eÃ\Œây`ˆyÞõØ—´D<E®Ìãá˜hMÈáq|]¿#-';‹}+‹½¾‘4ªbx#ìÑX ({4¾$p¬‘Bs{4V£†±×Ä%¿à8qj6C²ìšÍÒ²¹ØcÓÈ%þºrɹïzxŽS-³©†£%bƒDÿ!1µ©6äæ ­[ ¸]K¤Jx ù¨ ŽÛª3% ‡¹â²vk\°Ÿ²ý÷íÇ2{AœÎ*Ç1ßÄuþzÐd0ººá™½úcª[¢}Œ—m¥v!Á8yõbbfÞrœèugÌl- ;ÁãtÄîü®`n¯µ7Bå\íÏI™Ñθ™1?ãè„¡)%Mõ£—¢µ Ïm5*àm76ÂA¹<*yú/-¢BðÍÞª\?®šÕÝ|“ÈÆí¾@Ô†$^<Ä[uµ gÎÒ$×êž3ÍÇਵ”\Nf—È¡~NQ ®´XG‰²,/¢Fû‘Wªž÷’š–Ðí ɦ'|7°÷Öîç¸ìš„pr'&»Š­vѶ[wÑ}Õ®#»/Ú5Ñ=l׃´sØ)[?7¢°ëÝY…%Lnuénînå5NŠ«§¶X•ÿ+lãðßxb7[lÄÂÒ(K\•³Jó§ â7¢ë”ìÂ5èí¬àÌŠÞÆöi|„AÌûUÑîé·…ìÂU/ŽŠ¨ÅôA5l›D±s¹tÌÅòr®Xƒ|µÞÞKšy»7í _–?¥kŸè«j_7í’|æíÚÌ[SÓ磬Ixl‡iëßµž:¢Ý…×ÄQˆ*ÅÃpuO^_¾Z›pèŽÀz´ž;ûpÞž{fü5ôÍ ꔌp»Úì‡ëÌ.r¸.FßãºXÇ(¯ÙÁ­³›Klv®¿U±çݽÏì×MáÝ{Ç®ÜÞ9LKË>Ç ±ÝcÉÑ»[’ÉqMÈáns&‡¸‘/HS½/$¹™Û û0½Uè±³¹\üì>]9x:«òòf–ØÛÑõa¦˜%UšÎ’ÅÏÒCºh×ÛLu¶ußLùÈlä|÷Ç2k[lÖ¤?¿{Ö>tϘ?khÂw”¢Øæ‘² À »)BÔ ƒÝ:Çвc6KÍÕá9¤Ño‚¹yä½:-Uý³³Â}@ç³ÇuX–€÷kmê8ui°˜{n3#ýP3'RÂÛ='—g´VL?ýœ ú7Ž9Qþ-{哵ÍÇšªÉæTGkmÒ‘¾ó¼ôo4yuAÛWó剨ã|>xçðÔÅJéÈ÷,åË_œ–¨ïhlÜ_b˜nêžã\¢‰{ñ–½~«Z݇ðþtïìÀÊž;Ô…•³·¢¾mŽ€¡–'ÕÏ0»ó+]u{Âã1:RºóˆGuK‹Pûs>ï–õêyä»Øë€˜}œó/‘çj˜Gî=Z y >wUûäG7¦x2÷ÉÚèvlê\×"Ü™ØáÎ4ÓÞQŸ¿ísgZfï˜}ÏGãôšbyté¼%nÊÜ™˜ûtߤý¦ý¡ËÀsnôº}aÙ’°ÍæhÑÐÔ'Üîn Hÿ²#òœûð¦n/Û^în!ܸ[˜óð;xkш³ël†µßͲç;´XŚ뢽Šâ½~F d×µuëŸÚ~ç33ÁfæÁÝ®þ¦»~û™¡Ehèâ±õµé…=ý¯í=ò€í¼×5ëk˜©É1gÄäS¬WËDjAëµV«X2ÒZÑd‰|¥¶ÀèïLÛ8~Žî#ªAýÜúZ¸ë—c]à2ê’¢"´ìLs“ÐŒõãb³õµ÷ã*øX@*û>}r„÷ìñÎ7n÷ß Á=lëâCZº¢¬³Ÿ0Ú}xW]¶°ÀËsa„kúqõÏ}…›°W/çG·â¯GÏNï—}»Åߘ(Ýï«ÿfß±üí.¿¿™mÏ-"Ÿç”Íï°̮縑ãnÛWPZ;w|[¸%k–Ó»éa1ï {ÿª—ß{ï¾CÀàléQéÿ-%¹QENe†›ÅƒggÍÈ:[y¸Å?yÓ¸œ›†‘ˆ0Óµ©¦öÄI8Ù-é¸i8Lñá4vLÌÍ–‰ùû‘¼¢îÞç·fnf&üŽ•QV£á-mßí;§›RÛÃ3Éq49¤AërHeÇ/\ïÙëöí”ÏýfOç’~‰‡ÒüÕôûVú™“áÜ÷ìÛ³Ùg÷t­; ¼5µ+ïÀk»¢ýù?¡R»V{õVÛ«·Ø^½¥¯¢]`8ãhü—=ú©h0ë›´{2õ=Ê ¾…縱/o¶¹—…öÝsÿͰ™9?ÓräÆLK'xÇÌ ô*~Èf.V©¢Îº^ hï§Üòs2àÆ#má39ÊPeäþH8}\q¢i~bDG3_s˜:ìòζ¼Ò¡îÎ;«xCÞ¬^L‘WzÔÝyì¯7ëó\ãgHã»;ï´âþ‚Ó¼Ò¯3ó!Ì’å•îÿZHzò‚f•¡¦ŒªOÔ¶´eÒÏO÷Kj°FãIÚá;fbv°-¶“*|6‹þ¼™ÿÉp4…ÕÿQ1im,² ý7/Q‰›ÅÉ/|ø¶Þ;üŽ ¢ k(¢ ½NüLWƒÑOFÿñ¬uùG?‡Û-³4³„-åfaC]î©+‰±h¦Õûûíýµ¦¸¡ogîÍå#÷EáêèjêOì·Ðh™ïôZÆpwVoÐyQŒ>I &)&ö×Ävòn<±¿"×&Þ öwì]Ä'û[bmNÃeLôS¾w¢Mñub߀ˆ ížX9ċщ‰¯'vß7ðîË™~Æ× ‘ûìÍ]ž{“ç¹Ø_[ìf÷^³´[7<ËwMï;tMæž—=¶Nq§Æíd ´z´ÂçîÉ‘”žšULŽw¹9Îh­ŠÊ¬nnCÛ-–ò^ìSt½Ý’bÿ&h}¯ž½÷wy£Þ±g¯ÌWÕïÈàìþ7K6õJßï´žMýíùùŸí‘{Hñêh?wWÌ¡Ñwï‹Ü+êw³jóûâõöŽ;ƒ×RàÝMöŽ;‚×ÓàÝmöŽ;×Uàݱ†mL3®àãsöNÞD¢[í|›ÆÃ2ï¤/mcKùï4Cb<2ƦWÀm!7Qi}d¼¸5–C÷ƒ8hĦ·`r8ý u8ýr$ž¨;t;3]§¯lr8n”‰9Þ·‰9mmîþ‰i‰˜Ø739 ¹VŸî… ZðwJrxn¡îÏ-TŸ Æí@ï¹àõBÑÜv7-“Û߃yçxæ]Î3,Ø|›Ø-V«b!ÌqÁôUL×W4À½ÞˆyçzlÞ9®:ǺI}USÑ󣔯hº&Ÿç¬è! “,ŸóëÁÍA&™ÆÈ*{§C±1è8¾¥©ikˆ9Τ‰í´Üº9¤Ú&h¡ä3Qô\J ïtÜK¢ByNŒné]vYmS>›ú4r¥ÏcçCX¾—3þ„f7šb ¼éV/Äñ·馣HmÀкÅÃü¶Õ×®£¨C†{ꨪ‹ï«iÌÎV“né†Ï$”ÖU¨î”»9Úͼf$3ÞÝ›6êuwÞâ÷i'î{[㈋¯‚þ˜î;ùÞ–›uÁ_çq/¹É)o ç8~T1Z\ ›Üu úlùÆk{ëîu¶ø§ŽwÚ¼ð3©ñé]ûˆsí,ln´­÷ß½R1÷ÞøFú„îÝÒÀ§Ùaœb[7òöŠÑÙâèèž¶Ë‚/ïS_nP_èu'·ÇÜ R^ÑÎö¼Ï»ƒ:Àíïõ·ƒœgäy ;‰Ýbý©ÝBlî±þÜJNè¾ oP7¬{œ†ùv‡ÿ§våîOb$ÿÛ*Ýý%åI˜>yž„ç Ž tk·?ÍÒ¸Ic´{QK²µ!U‡ùÍøîî&`1µ á{­®ź dïÚ-v–ãËØ~Æ–†w+»u!æùîèWl  ª£íî1&…Ómí÷ØãPrÜiï´£A¬F¶Å O¿ƒ$gî8ÆßŠá|“´ÀDº¥ÆûV¹ÌâR´þÜ-ô Ð†r48Ia0µ—ì1Ï3Œ+pöVÍž‹U”ü†c0Š!ø¬Ks†¤Â=œjéÏ,N˜0¢¯´Þå`E O¬MBŽ „m¹<ç’Ž»úmòtPÁøí¥pEÞgù4†+¢ëÞÏ,~¡ëÎÓókz±ÒboèŽoc–œ$0——Ó<)¿dyÏ0-ZÝþ/nì«Øà³ V ]©ãe9OÏäò|èRŠ–üŒ ÛEMѯ,?2Ál¬élyù[ıS¶AÇ|iS›º¥D‘ÕýìÖš#"%'xV¦Ü{vñè¢tÝÂFD,”|Fdñ‘œ®iÓ&ŽJ÷ÿŠäÓ6Ú›ozȇÔ³$5¢,ßÉúFÂè [ÑL.n.Šž~™åÄã$<M~gδ³è›‹Ç”âhœÁÁþ¡œªÒåÃ?}‘eŠÎ|ò†w±îìËEäDsH6Ì˃‰µaSy€Ÿ+¼<1ÏϺ§>¿­&„Hçùb㎈“Þ™7<¯%Îvr½ÕϦfrQì¼os”H÷R}1|Xõ©«ÿšc_“zmx8êýÏ,NsþÄ^Y/â‹_o+k[Øe>§fÊÌ–f,«íxú`Çž6•7ëæÖð…5ÇYγjZ›Ù+sâ![0]cN |ÃÊDZnÚsxÑ/,ƒ)Z`aÿ ·hiäœÛóÃ>îŒ×Èq£+ÖÉ¡©é.d2µw©^qÇ;ø2)F¿*«×Ÿ„4Ï0Mgñ*¢Bøwû21| ÜïdÓfîÇ?z}bé·ëíä<Çá™ç8<º‰8·µùÄá´»;¾rªþg›I,±ïŠM¬Áb5}‚W…÷Ýý(^äu‘3~Añ¬Þ¾«¯gXÿ7«ÿšþÒ4?†ûa;ß_Ñ lÛ+}±šÉaЊËjž¹ð|æ·Ø³'ùF–­ÎuùVDÃ'vu½JÜùb¢·OôÞqp.¹‡#Q¸åÉ\ÜdB.sWQ.™n/œzX%ã#ÈæÙ¼a~ Ë23Q8aK~ÇÝÚ2˜ÂŽœ›É¹…úûßWrëöž5oÎ W'›%ó±®yIÖl›—¤Qï¤{pyšSÒ•‰ùÞ09ª“ûÇêÚ¤Ýæj|–×½œK¯†[bu¨)¾zSMÒ„2¹¤ÍMMÖcŽêŽ·×m³½r:¼Š½3sÞÂzê=g ÇºËmB«À|6뾩÷h Íί¡*1¶ Í+åHÈ»¦åÐ>7o¯‰v®ê~öIŠ­è.¸\ß¾Ft°Üžx–¸ìc§5¾ïô¿©Ër'k0­°ÆTòSǾ½Ñwï›|U-á¼·â°áÛ§gžuSí˜õh+íFgonÄ=s¤;4üßí-áÃêҨЕGFû÷q”,{w;Ö9Ëëoq'«é*vñ•¸‹å÷?ïÑÊ´&׺7Á¾ãöô·.·wܸ¼v0ï¼Nú&Ÿ³šºTSX|iqÙwºYI{1Ííu¹È›F*w©8è«Ä]öNw§Øë<Â9òœr;>17ŸØ¸B¼çȾÓÍI^A²Û§×œ%Ç|Ë¡;“üd9üLÃ÷F·¥Äk檉ç‘Ãó€tKJüL#ïSb¸¼ž¯rˆÓ”æ(xCÝ2R@äÈ5‘ ^[–˜ŸQb~Vt)3Ï]29¼~.1§“ËíÈó•L>?gäø’åЧà9_äðú¹ÊQ4ï_܃ŠaÇCÏÄÊby¼&2÷¡bЛNõ‘É‘÷£äçC÷À’¿‹ëfTòõ¡kìùkäó:¡Ä<çN÷¢=ºÆäpzÁhU”L™[QÉïô”½®¨j-c¤OzìqqÓ+zÂÆ/`ÂÎ+¢à—ð´„þY‚Ÿ‹2òU š§|ÐW0ßÚ?òÉåˆw†Ay÷ãݾÿÅÊrUmîOø\Kcò·—Æä{/É_k ±Öb£C¬-ÄÆ‡Ø„›bSClfˆµ‡Ø¼›b‹BlIˆ- ±Ðû!vvˆb«BL~õ ÷ °îCy±îŽŸfçÊr•àXh? a^ï:»O{ b±ô……=¦YÚâû^>¼â=`»›s£n0ðÖŧƒ—WÇZvÏÏÁ·›rmå[¹Î&>ð}xÀh€Dz_¿?Ü«øýÙäIßk±ÜÇíûvÞ¯8 \º:vr.õˆK¯ï™è“Üþˆ nFkfë­%•—ð ׿W=2§õè}û÷{²ì}ûÈÜžˆ:F+·êjéÏOÎô]û÷³"½ÛšçjŸÀ÷Ln€Ô>º+/§³Eê›?/›S+/)pz™k|Õ?nÐý>G{>=°9tG4=hS ªµm°rÓ‡ôm{>½°o«º8]ZVñ¥ø…’3[)jwKâœwf"Ø >ßvˆ®)»5¬Ö—åσÙîæ,‰¹m #þú1i»kN¬Æ‹MèÆÌiÙï]ð¬ÕІŝs¿nâÍûF§˜ç†VÝ#nÆ[˜ßG)_[ñ[É£ÿÆwX¯ïÁ‡¸[‚†aìqY¥+AU1å)yÿfro>©†£Ôɉ¼%p"™?OâNpùÝÓü Qç‘^­äËçQ— ÇAëîii‚Š·˜b») ´ÆoÎNÑSv12±Œ£Ÿ®ÂÝÓª–¡W¾yYª5àó’‰ú†N™NÙ˜À™yÛÒŽÈÒ“Ú‰›]q5c´Ý[Á}wOëçÜ: dˆnó\°Ú¹sQ¥w¹–lÖX%Ýî©Üâ_írÓÛX4– |ÃÉ{9)Í«^öô–U/Ë:k$ÌónŒ½û<ï>Ï;)P‚?œ&ƒÕ0Â\®1èr çÀw»«{Ôµ°»à iŠëÍø¾¢÷w°[ôF7Ä­Ü£…§‘-Z|rÈ¿œôè¨ ÐÀÝî~ê´±;ˆí׃p!ïîè¡Ý†¹êÑn»¢+úf¡óÑfãÂ_S|›¯Ýþh9 1Âö!ošõÆÔ£x-­ªµ=÷¹ø£xí Û¢ºòÖcó¡[Ûoa^?î¯çj³»¼NûÏߨU¹'¦ô¦Ær¼óÎÝb÷ÏîNé¿ìÆ"_ÊàYöQº›´uða9-¬ßùÙVî­Ô­ÙKh•qÓÜads{ø/­á­ûÝÊlÝÿÃ'u©Îa†¤¦÷€¾0bà\÷ÛWiòìÆ×Ž"½ô»^8)Ú…}­{áï¾&-$$ ú¸øÈÄ£ŽnyéïDëv)²ùÐlàgmüËß}Í&_•Õ»²×ºÖ„É·V˜ô3o;<[=¦¡ºœµ¼fyr>òMC2­˜vêÑù r»íö}÷ÜsÏÅwåCÞÖÌ\ø‚§KfDîÏ;dÃŒ,MÕÔýeFð&YŸüKÖg„|~FðD¹oF˜ ¿ð®‰n¥ÝgM7(ª_fï5;féÞþÙcñ:{~G3,Ù‹›¹QÊ[¦½-J‡2FMÅg×ÞûŒ“[«—ikÁ«&ÜWÝúM­²Ýeoõzã»±|p6“Cœ¬–¼jõ¹4Û¦nq„w×M­>FMEë¾0Ù¿çôö{s{‡šþM« O—àva—Z:j4õw÷üC_ÄiÞÝê÷1ê¤/äÄ&|Mñ£¨¹£jÔôá>àc“>ˆ—½»̽Q{±<¥œÆO'¼CñÀéÃ=¢~ço4–NÝkMLŒCî¸&†~·î¾&&4Ç-ÖÄðM¨­‰á³Pw\Ã+¡n½&†Ç@ÝtM †ºûš u361üjNL … ôœÉ¥ÏÂO}ô™Y|¬Ïø4ô=sûž„þ[ümcèÑûþãÙÐ÷Y^©ÒYÀƒ¡ï9 Ý\/©¾Ïà8êâþ§Ïù>é ŸølˆýëÆ¿¬ðqØÁøDãCÚͧŒ‰*sSäP¥ »xJbeª#ÑÔÍ/ëÀ™òqnI8e)‹µ4›c <¿S¤YÒ|Jï$:àªð ·.ü Š+1 ß(ÍÎoz#Oý:n©6Nðµû¨æð¼ôÍÑß]¦Ý-Ìõ%½9ré÷ÚÃø!ôãÌ…×h§Ÿ^KMb¯7ŽÂNlg½kYlGýLà‰™máæ;zMDûït¢Í~Å‹†ãæ;†˜‰ú}잉ôõä<ÐËú<à˰sÔÏt诟üÑ1Úƒýçõy0íæÚ4OÃQäë?oÈQ»+ížc5ã';‚~ÖgB]yxGËÏ„®óoK7£ÿåÁ‡Ÿ<ã2ÒbêùópàÏ=ãð“y —õyÐûáy Ç~ä=Ï`iC ØwЬ¥Ÿ ¼ø‰Ÿ3®Ä€}‡˜‹ ÷yÄÜ=™Ÿ•'gƒ¾ÖgÿF³a½ØÙ Ï~6ðw„ÞÃ)ôüÙ÷’,ÈeçÿĠnzV 10·ð;vOˆçÆ<9ô¶>øUÚ7ôÙ÷K²ç2¼ÞT|¯ÏÑæ3uÚ˜¾ó—™e[©AóÚ4ûÞFy¯¤EOÙðF(-½áàܦ§Ü[ÃAq.J"ßYƲâ¼—×Öƒ_Bê‘öÍõX }+…Ò5~æÞÙÕdW> UÏ;Mo{°žÍ@ÿ‡ê1Þ£cy+Ä{´´GÞÒ@ßì¾Â'!·Mi¶<¼µ¦¥!è…ÝÖ<ŠÇ:O#ß⻺]ÞÐv³¼²ïí(yö庾©-¸×ì"¿—ØE­¦©D?ý^¢‡¹'©t/áÓªs/©—é^¢·~ð]ÈHqäJ´„¤mÄÏÌ~ ™i@Ž\9äÀ¤åþß9 ‡õ9Àóá¾9 ·~ð}ˆ×siQ¶¾ª¶)¥ö8{‹×Cn¥Ò²l}•Öë%I§Ç|àóP7…ܤ[_5Ä–ë<|¨T‡^hJ6¹//Ó»Ç0 =¬cü'Ð_?#xPd ÓÌ’IŽ|ð—Ȩӭãþ8|‰îY˜ožÜÖzÞùÜóë9x§»žÉÁý¿žƒw¾4ê9xçs »PÏÁ;Ÿ}“zÞùh£ÔsðÎç@W¥žƒw>ÚCõ¼ó9Ødõfùpë9œ×e“mâzÞùh×sðÎÏ";µžÃîZ[Ëõ¼ó9àcÔsXž†Í&t=ï|¸áõŽ3nr _]ÏÁ;Ÿ.Q=‡åÙhm×sðÎç@ûžƒw>tŸzÞùè×sðÎç@üžƒw>:éõ¼ó3 ã žƒw¾tÚë9xçs@ ­çpÞ·M$@ê9xçs íYÏÁ;Ÿ]ÐzÞùÐ5ê9xçs GZÏÁ;Ÿ]ÓzÞùx¨çàÏç‰zÞùø«¨çà϶®çàÏÁm žƒw>·šzÞùÜšê9xçspêçàÏÁm¬žƒw>7·zÞùÜòê9xçsp#¬çàÏÁí±žƒw>7ÍzÞùÜJë9xçspƒ­çàÏÁm·žƒw>7ãzÞùÜ¢ë9xçsp¯çàÏ_¥žƒw><˜zÞùðÚê9xçsà…¬žƒw>zÿõ΀ÉÄX=ï|<ÀÕsðÎçÀ[]=‡óyorÀõªçàϧ»zÞùø ¬çàÏÃzÞùø ¬çàÏa8ZÝ9¬× ‹9–ÕsðÎç€zVÏÁ;_+þ(ë9xçs SÏá|Z™ø²¬çàÏ¡ÿ{rðÎç€lWÏÁ;—Ãø…íÎaÞùøˆ­çà›ã/¶žƒw¾¼ÆÖsðÎçÀ|=ï|<È×sðÎçÀç|=ï|üÒ×sðÎçÀ‡}=ï|xvõ–gsà)¿žƒw>ÞzÞùðóê9,oÏæè¹õšw>¼ézÞùðúê9§Úäè¹›w>GÏÍØ¼ó9àº×sðÎç€3XÏáxð&GÏíÙ¼ó9ШçàÏ×°žÃi˜=7lóÎç0ú Ý9xçsÀ3«ç°ü3›þZ=‡åµÙðâê9,_Îæ€oWÏayx6<¾zËï³9Щçàχ°žÃr m4Žê9xçsÀ­¬çpúG&GÏmÞ¼ó9ЗªçàÏÑsw7ï|ø¡õNŸÊäèá˜w>¼ÕzÞy\ß²žƒw>|ŽNòÎç€Z¯ƒw>žz¼ó9àìÔsðÎ÷b½VÞùpë9xçsÀ‘ªçàÏæ`=‡Õ"´=C÷¯žƒw¾¸ùõ¼ó9à­×sðÎç@糞ƒw>G¿Á¼ó=ÃÏR=ï|ŽžÛ†óqsñ.ä0 ÃA7otI_~ül8G# ˜ûEõgõ=£§ JèµéÙ|‹ÐOnïç{…8õQÁ?p©`ùáDå÷\Ϩæ×OE«ý4­¸¬¼Ùò³\ýÄÒÑUµŸÜ ЉßïW–ã]†×ü†K5ÖglÖýGwÏæÒ8SóÔþLiýÍBèº(õ×åR*ýŲâ §‹ÃÀµq׺~Â7N\\G`ÄZ=ãÌ—ß@mSMK‹Þc®‚‹±Xû-bâêº>H™ä"gîòPb¬kãƒÅÆ’Œj'W§!(Öqé E€V.Æ0§[Q^J`B‰¨@žýžÉ·f耓ã>p²ëHÖéQé>¹ŽØßï±|†ÝçÞ€lÕ»týМøÊ8Çê•›¬ƒTúr°ÄTuñ¸­Áí-6%S¶CØÕµ({v{šßºiFbU¿ŽÔUL=kV<‡ír¨¦~µ‹)-–Ól±ÄŸ-¤¬ý6Gs«ý1G7퓹0\Ù7xgfÏ…B5,£`Š2_GsÙñp´\+)ÿÑt¶Û1RµÖ<ƒróu ×0æk¾a¨'óa´&ôiP#,`f1²fH3òXÞ2gÇÂxL`K¿˜·…r™¦\ Ù? }XÈþáÃ"ö@Âî[“#¡/‹`Ð'¨t.æ™0÷ÇÑÃfÜq줤~sZ`ÏÕ§Àü-Aá ×K`«èÓ\?`ŸÛ§H½'/Ró‰ô¡H½'Á¾(2ç'Á"<$Çùb|.eW™±¥°NŠÌÃRrAKQ%)¢”°”Úp±”½Q¤î“™“"uŸÌ¬y{2ý(R÷É\E‹Ìà)0À‹ì½SPx.ÑÃSPw.1/§ÀZ/ÑËSaö”˜áSAa%ús*×¹µcкD–±ûJÌùi8dFíô4f£Ò< æ^‰ý{û½DŽÓ˜õsr:{¥ÄœœÛ¥DONgàzât¼KÌñé\]JôçtúT‚ͽ†I‰þ,¹—éÏr.efwù¯ù^[’*³ÃWÀž-Ó¯°àËôë ÔVÊôë XPeúu½)Ó—3Q'-Ó—3Ù¿eúrû¥ÌœžÅ<”™—³ÉYf¯žçì2»î)Ô_¦Oa.Ëôá)Ô]a‡=•žW˜“§²?*lÕ§²—*ì•§Ò¿ {ñiô£BžF¿*ìµsèU…>œCŽ {üfµB OgçTØ+O¯T˜ëg°K+Ìó3Pø«ÐŸg°+Ìó3P­ÐŸ•ÌM…y^9'Þ÷+ç<°ïÁ¡_MGa7tm«º"fqÛÔf~犹¯y;Wû]}=Wìeõó\áSõî<½S_Ï×>X-¥í€Õb&«Ÿ«¥–£¹[Mÿp©°FUk?®sHs¶FÌCÍûp¬€5\mÁ_k© 7­kµçµŸ× WiO®å¢ƒ/Ö^÷í\Çþ‰ ¹ÿÐãXíµ¸%íãÂ%š× Ĕ՞¸@3¢ù\G-àÅub°©ëtiR®õÏë[ÿ\Õ«šuþŽ C6àøõrÉ¥9Y¯ë£êY¯Ë©êy¦Tq4ÏÔeEu=S =ÚÛŠa¤y¸P¬oíŸ •Ws½As¡}³Aj$ÚÏQ+Õ/Òh..¢péErÇ¢yÜUžô”ùØÈÞ€©¹Qø]ûe#ìO3lä.€‚ÇŦt}1ç0pÔÅrت>_<Üéµ Í»í É¡^7Gx‘fWبºkî ã1›±‹Q·ã–r±X©šµ‹Á4Ü$ÍÚ&] ´6 ßkîž…_3j¾Ýž’3 »‘bÝsì.²ûI¿g‰¦ž•zýn]´Õ›wÓ¶÷­ÂKÚ2?'„¦Þþœ¸³ºÄýŒ-þs\Ü@~?§ ¦¶ÉÏëb,ôóóhVpqþyp<ý_ÐeTÈþ¸s€ìoSÏ5S·ÁæBzºlù÷0ÝhÔ¿G—|ÍØ{@Kl÷÷è"­ºô³Ý~QÛXÛöÙ¢\H‘Ü uÿâoâÙù%ôÃ0Ð/É“zõKl.¡¿Zàý^¦ÏBï¥/ 3ý^¶'^ßË–IØNïcÃàeè}0 ` ¼ÿ ƒ÷1Ë ³ý~¶,‡> í¬‘ø÷¶üí\¸Ðä» Ž>Ôíp ÌîA÷êÿ µ²õ?š*0¤§0>Dîs÷!z‡O¢+€ª>ÄE˜íÿam{õàÃÌOóa."lÿsÁeÛß¡>hÛß!¯KB'w0·EvÚ/ƒ‹ÔÿËô…Kí/ƒÊØÊw23\`ïDK±ÈìÜÉ|™»;©‘ ì¯0ò”}–*Ñ›_áÄ%ôWØ\@?†ÆÐqQàú1PгƒJÌÅ] ä2°ã.v^Žîb•©ù®7Æ;è®7ºÕXÝúöw—nIšì_êÕFùUÃÏŸ ³Ü ùMýI±j4QŸ&ÖDR˜YõI1ö5QŸ¤ÛlíOJqAÓôIrpËû¤”R´m?©‡&ë“RNÒ=íSRœÓd}ŠÎ²á>%Â{Ÿ§Bü5mYuð׸qÛû5q(Ô—_nU­Ÿ†«Žý´nWªõÓàHnVŸf£°Ý{\‹_?:ž€_?Z¼—Xèá\‹ûaÙ-Î= UÖ~‰å§y²7Õf¶÷‚4¯¹%Ô®O¿®;°À¯KoFÕüº®Lš”_7mÚ»yt÷”-\Ÿ» )Ü-¶–úþê•æñ7¥Æ©yüM9ÇPßS·IáÂßÔ­H›ý7©Šùû-ÝC´q~Kj6Ú¬¿¥Û¡6Æg¤´¤yûŒ.ÚŸjÑ&û õ€0>Ãå–÷¶èé·Ùj¸‘ÿmÝ4‡¿­Û¢úÿÛBêìo35Ü\›ÍÍ|þ6›nÆo³µpÄô;šíßá®úúp/7Åßù×x~ç_Ý 1möJªë¡™Äôfj¦4e¤Ø ö×[ûû]©jWü.}`‡ý®®.êÑïR?S÷»Æ7úÝ—»©‡!dï³T®™qµ²³wŠ[W—MÆï:ÿúfƒ©ÒÏ Ïj×Öx[Ÿ=Æ!ߟ"h¯ëiŸÕ ª‚Ïê,¤ >+f!° TÁïÙmó÷ž¾±÷k–>”¶t³®@šÂæŸÅ›–Á–ýg|}³!”£¿]ýû Ýû\–ÉŠ'Ç{-‡Ñir9@ Ê1@—Lå°gœc@úv«Ø›0§È±Ùr"—V9à;“Ã])8>¶ý5ÆnÒVòo6Ù£!äÞL¶7F§Ì½y½1ÞHÜ›Ù㵿‘ÂêêÃHÕ£ü#;â#c…^›ƒû#9`‘ãNËa´Ií¯U3¢­ºŒ(Gë?Æ9Zuit“Þ*¬O®qäxŽåàFár\¦‹‰r\f“ËîJc€ã ™¸LÍ‹lÊŸ’Î0ö¢ËÐ$­^ú]Jg˜î3Ø—†íg•y³¢öBÞ¬²ÚüÏd/t#3¬Jòœï^pß­åà‚a¤Ò°¶j9P¬½@“¡VZÀþ…&A/ЪäÚi³&¼à¦kT9LÅmQö~òëH·ÇEÙûÈß%±¢ì=å·“Øœ-ð¿Ml|”½›|1Üïj§‰zdƒ«XWÿ±ònIž 2ñøB 4EçÈÁM†˜fNQwäÒåx$zñg.öLWñ=f.f°%@ö*fFÒG*ÂM}€ï†¢ Õ1l;bðjà˜P«î|‘”8©Îèn†À¥¼£b+︶xB`’ˆÁA@†urG&F G¸.Ú÷GZŒË \ˆ³f[ ü?ÇbŠ|ÅÍ…:¯¯?u±¯º/±.MóÙYê¦CXž¾Éh; þ‘GÐ`æžé`žÑê¤s]nÛþ“àOEõÑH7yÝg¸GéÕ߸ÚÅü1}IÕÌu1=F?K?ÔÂ;v[ˆidg€¹F¸üpž˜Em&ÑUÄM"ô±F»< 2ø$mnÀš!³Z¢ˆÛúº2±à(¿ÐY"Fè#1z+—htŸˆ±Љò[ÍEbÔ–ò[,HŒ-ãÆo´¹ý€uä·X‘ÃÀo116 ×bl.6ÄØ$þʦÀ016 Ì.jbfÑ('Ƽ¢aNŒ™E㜽F‹}„5CKݼ \‚únk$v.WX{k .Ghx£n(Ęg®Q~osð3…¾ï˜)X.\z`¡_F¬Åm Ç_u»n|1 èªi~cnù,’±ï˜LTÜüd²ýd¢G˜LnìÄP&B…Ž,TëìÄÒ 4S˜Ë¬_°n´»j;»A¾Ð™® TU¥ÉHü)gÞ‰;¶Dúþ¬ôuÌÆÏìŸaq³­¿±ŽMÊE³†_¹wÖ^p ­½àZF—³\Rkó̵¶ƒ¸ÂÖ®8ÜhksÇ·ö‚ûnua”ô«/Œõ†>ÓŸE;I7v§q )þb1@…ôcî÷ð¼pŸ û-ï¶)ü;ؤºŠÃ<¹”Ãg¹„Çpúb1G…ycî{Ʊny(ÛÆ( ‚Ãø@17† o,澇o,v®Ða,+,UqN`´Â1G98¿£2‹ÝKÿà­ë:f¨ºCC9Ñ^Cw‡» :7=f&ñö4- w±˜9JÄÔ„ÁYÇJ">¡¦2‘Ö…æ5á ÏÖ«q–ÏõRÓŸHƒH{!aWá´Ý \¸$\Ypè’€épï’€¥P{F¯ eèD%¸f×Ôã&#ÑìiçÁ¦Å5{"m(ô†ÐÒÐöLăÓÅ.=j؉øÚĉqÚ≴KtÃLØ^¨w'Ò>‚õ.Ì]\è ×§¹BÆM®.+('`øÿÆd±pK"¾¤M"8ùÂgð*Ñ?Bñ=ÑŽrJ´#Ð9bGm¡C…Âx¢!„–hG»%Úè±#ÐMbGÀågGÀ"fG=ÂÆõh¢!Ä™hG‹&ÚB©h ¶ŸhGÙ&Ú¼‰v„Ð0ŒmœJ&ÚBЉv„°u¢!Ô ljô „Ôvnv|QLãX1aGàh1aGÄÜ ñqÜ«s_HظYL¤™‚žìq4 ´#py˜°#pr˜ˆªÛGÂŽ€ï˜°#pù—ˆq­KJ"=t¹´#pn—°#p˜H³J›„C½Dª±@/LL9P©ñüŸ‚8CŽÿSÐDZà ⚃–q¹ÀcUÓéyîRe”‹ v‘-˜UA7RõN мàÊÔî:ôGqÏø¨ÚTÉ¥ 6 Ðî(èžIL{¢ Ö#ì#í„®Ä`¢’ÁEš®jÖ »«–y ˆ´ lÕúšëb¶[°A}·Üí³ û&Ý¢¶[ší‚îfóŧªv v³ \gúÄuËw‘nùÑ-x˜¾[C\_l·à†Æœ^4œÔ=E¸n©újww1Õ©Ø‘.¦;ÂÅ4ŸŠÍòÞ©‹.Ý h ÁhÛ "ê0=„Ñë´t ‡¸Êl u1”/ˆMp•ÙØ¡®2~ÔÅ®ÝÒ“Œ÷C4³˜ .ñÔËlÀ~ Æ<0ÕĨçcq—è{:áÚ[1e˜%]?Ìô0ªZ_3\LÛ[_Ó]ìkÙoš]SÛÐÜžj[–˜9}âôdÛ‰í©–ÄŒTc]²ubSMí’Tí²¶‰ákʲ(ç[¥ãÆF9×—ŽåÜP:n|”scé¸#¢‚Òæš¦äAãÆ Ÿ4Ü„(çŽÒñň©Ì?*ÊùeéøÑ, WÝ\žlhôØ1Þ}ñÊZž™LËÛ[;jÛ£œcÚjšZûK\Ý‚'Ç‹;ÜêXÝÂ\T>GÔÌäUñÒ1 ¶üx%G{^G{;ÙØœ—¶qú1~/•gM'÷Ÿ4øDè˜J¡¥µ­Í5é:@®ñä›Å&˜ñ”elª(çÕ™þƒ/.ªi>¢Ì+­€•n‘Eys]‘QÎw[“-˜ ·LÞª ®)ÑQ–Êë×Gé)ñèîîÇù™ ¶’Óõ7zÃvSÑ÷äâŽÖZÀà gvSED¹Ÿö!³˜‹oN‡Íj?Ø…mËŠ—ÄûƒžÅ¥cX_ů56,IOìÒªEÕ±MX5k};`™®Û¸¢ºzÆi?‚«7X)¿Œû–sr)0ð±¢8ýéÉ¥lïµ­ÓÝC}¬å¿,~®uçëÜ‚BŸ 1| —>W9kÁÑUÇW–WÏY0kVo|áÜyåüÓø©•Us甑ã‚ô›3æ—Ï‹rÞ§ö­g™<—ù+¾·¦uim”û>Þ(÷2¢šþòyY”óÂÞ~:-z>á(÷˜æd'ý9ŽQ"?ÿy…eˣܣy23Ê­àóˆ(÷—[†È”‘ÌÅ9æù)œë,ã‘êq•Óæâó)áHVÁü1£ÇD¿±ëHuY”÷ðO—û½(ž½ëp9Á<̆5*ø’³Óº»Âf¿,Sf;_k žÖŽGò(w)-B`z¯Áâ22ÌŠr_Q:f —…ß6Ã~ÕuQ¼¬ˆƒÅyr¬Ø=•c,éîÐåó÷"Jœå?7öõé«,±æÅÊcå„y©¼´úyWé!Å/ð©©ýŸG¢?éü…Ö¶Ú–¹ÚmyIßëeËe3’ê¾í îƒ9¢œ¦Av:?—Ó3ÛÒ´H]—8]žåb[(ª#ã²å•VÜJ}¾ü÷}é;·7¿*Ð7$ç“âbð$÷“ÂYÌ™ÐÃÊ¥¬§óyº û™Ï¡gG¹'–ŽS¦ |ªùñ©æoäSÍ¿˜O5ŸªâY|ªŠKøT›ùT[øT/-7†*®åSU¼ŒOUñr>UÅOñ©*vò©*^Á§ªx%Ÿªâ:>UÅõ|ªŠwqT·ð©*~†O×=²\‹ot>?;4µí å1Ø¥é¼Ùt¦)|¨ÈÔz@Ø9®—úÜÑŃ{KEÄ»¹vlim¬n×-PßQhôÌ¢Ù×6ÛŸØpr_Ä:»õ|çwóá~\å_\4O s9§:ºRQ9m>9Êë7+6eW·tÄ‹µ´ˆ­ÃŽ¿V ®i:) îþ,Sª!¿—s±¦û«|jº¿Æ§îçïcP.q.caj›.~v½¨RÚ¯€×”µÕ64LÓírå¨Qé×®Õoq°îÜו^Áeæ’•ŸŽ]Ĺy± VÖ,©iÓõ9Ê?ØK ôåÕ¼Yª­]/Š?'â(÷gôIëgWnõp Ÿ39§Ölw¸“ò®q£ü_°Œ/h_å'¯zWqs$ŸÚe§r7øŠÓøÔF|f¿cçüy”¿³iÙ´³üâïø\›£‚ïºEе$¢‚Oµ±€¿Å«¨`F’´›døy>?ÛÿMùC\¹/Û¸(uöx‡|µhgéxVxù]š®ã¦ö÷Úí×ó9+ÊæVíËîM*„õ*Òh|¦t¼ ôoó©èïð©Ýÿ¢ºšöš(ÿ#v¨*~ƒgšŸo”Žg…ZÒÝ^ß„‡ÞŽ=þw$Q ÃKÇAÊ|jä/_ÂÈMåS#7O5êyi3ç±…VŸ8WëO¼ÇÕ«ÛùÔÛß*=…z~äx°ÑgùÔ|üŸJøû|*áð©„ŸãS ÿ¶ôˆ#Høu>ÕÜoð©æþŸêÈßó©*¾É§ªøêÑHœá^åþŠG*æ".”Là‘ cÍã‘ân ¨máRó-2ÌŽòN-z­G/(jI¶6¤êjk{«üýÖd»Ã¤#J(¡'5u4¶7p»„&e?^µGù3jS\‡ÏKÖ§Z è½Z;«ôˆ ôt[i‰ äkJK%oàSc7°¨¬­mìÏÜ»'øÕ³«ùÔØlçSU\çªx}鵿F>UÅøToäSU¼‰OU±‹OUñf>UÅOó©*Þ§ª¸‰OUñÒ  Üòd]ZÎcBo'®;h`&öƒÄµú Œ‰ÓÚæ—²IòS¶Î^¿îZ½’Mÿé8"¶ËQ¥´õŽåS…ÿÕ ÏÕÁ)N#Û‘QÞ?”Ž*¦±¥¯é{Z”÷u}Oò?ßoºèÐ;Ê[©Dº¥=Oߚ̭ún –üÖºvédeÒéæU|ë‚RºüAƒ×¥7)Zsá“;ò‚ކ‰m MŽ4s~Mm’Eýh«Áê²ëoö$ʹ]t^ûBÀüš,þRO/^òˆsd:º7š¼¾*Ü2žè;ºmê¢Ê˜ßUY¤Ð •hµ|Z‘ÓËËfUUÌ.¯®¬¨Š ¾ª'+ÊUUÏŸSV9æÜªêi3˧¼J/Ï<º¬zAåô²ªòêŠ9UåóŽƒ Ÿ©—'Ï… ¶²|NÙÔYåÓ9rš7‹gWϯxA9”S驳«+˪>þ‚/˜>}^ù|Zñ-_]š$ú‚žˆr¦ÓìÉ'3O¦Û“_Ë<™aOLuöÉÌøIá{kñEîî-'}uoE髆ޢü«âzuÒÔéÕ°àN(›U=½|VÙñ0Íý³eeóûª¸ŸqN'DÂÇÍš[Yy|õ´ÙÓ}î™g xs¦K½½÷•móå½OL–äÈÞ'˫ʪÐ¹ß ¢œ·e¢ÇfÊ«¾²å]ÑûÄ–÷¾Þ'¾¼¼Ç‚Àˆ.¨*+føOYåM°ø4‹Ÿdñé?Ùâ3â¸Îo.¿$¾|jéºú¬$ð ef#­uÓ¸xªCoO—›>ycºâôÉ›ÓE§OÎK×rÂ\M·Š^ž®%}².]Kúä¢t-é“Õýµ¨k+úkÑ“õýµèÉÆþZt½%SËéÇréÌê œM“ Ÿ“ɯpå¤Ì,²†Nòß™~±|VÙqåQÁ»2ãéRø¦ùž™X—bÿô —â«™!v)>Ÿ~áR4õ÷"¼´`דôaååý½ÉRšõšõ(K9²¿WYJ²že)_Ùß»,åˆ =LG ôÒlG‹òFÚ-ï[’vÑ&ók÷Ð&»i 6™Á)yól²³É®îo›MvâÆù3¸hüÀðñª8~ãä™d/;“ìgÎ$3`' œIö”Óf’ù½”ޝâO ôláñ³*æL/Ÿ^|wã²§ñ ÝËÓ.îoažöË}ÌÓf=ÞöøŽæi‡ô·5{Z;ÐÛ%åeÓ”¦±)í³ÒzêÒe½®¦›?ÐK—΃'ßG—îØºt¿Ûß?û,]Giï–Wb&î¶þÎñ¨°q‡›Tmý]3©² Ryüã;fR9Ð/“ê®þnñ¨ìõÊÂÖ’;„vÙwe_EÖ1—Ð…´i.¡ͬo.áZçNÝØ=—Ð#­´î]¶ë\“çr+ˆr/ìo¡}VúÞ@]:s÷ÉèÒemª¥óðÛ·Ï¥ó«0ížK÷wýͳÏwO ½;¶bîüéåUåøG‹³û˜¿M^1ÐÅøÀþV†ÄÏègHüÁþ¦†Äçt6$öë·7[ð :ç—Í! b Òbì„…ùãÂÑaHmÎ]$†Ô»w|5õÒÈR¿s#r ©[dþ8:KêŠæO}%·†Ì{82ç@ŧgR˜›–ybS¼Úâ32)^’~bS˜¢â33)®M?±`Ò¬eó*ŽÓ9ráÜYsçÍÆÅ\y†žÇ©sù´yååØ?3¥Ø [IRs<8aìØâ‹ªç/¨¬œ;C€9ðR¾pfÙ®lý_›~´¨b>£æ~dâîjº¬l^Ù¬YÀ…òÈÌÓSÌaæ Àµ%ž0‘:3g&~ú‚9šQáÌx?…Evrõ´Ys§CðÔò¾âR-Xߺ_÷ôc2§Ÿ9é'öÜåî–y¡š½í™ðÉeÓ\†Š»˜'‹«f²M¢‚={_è \‘~¡¥s(4jô/dzÒtëØQãÓ}ˆÝ!×<9¹bz…ËŠÝÅÓ¼9‹lÞD+Òo4Ý6Íà¾Ôf»Åô¥¶oÌaا^Z~³»k®y³h6ÛýdîvöšÎwyÔd²³m_¬ë{vê‚*׈"òôY¶ø‹î†š>óÙ,—à¤òã§ÎeÙ"!£Å½¬b‚vWö½dŸè}"VÂJ)ܼ„ª.à"g†{ÁücªgÌOJfñV¾/µ…3ç Kk•'î¼²°r[9'ƒßt‹)ÄëW—-Šr^“ŽKÔôÕD5€ÌDݞɴ U´4º¼%±,“¢f$í[e2#d¢'Wøèòò£«§q0§hÿ@÷–ò´Þb”݉Ï?X̃@ýƒãxð˽ŽgýÖû`éô*n´æLíŸèAœ.üxÞ¯œZ6`à~úfiÅlH"±»$ðè„L"³mÓ76QyrºÓÇÍ*£ öÈ–=P2Ñã:ÞœÉT$ŽGP}tB•à,Í¢Í<ÑÉõíx#/…ñ[úßhñèÆ©•ìÅläí«SÉnΧù›E¼ù‹ìzc`wþfo&õ¿YΛæþ7Oå9ÿ„îêM¶pì›e¼9´ÿÍÂQN³hº‚é CG(¤çBA¶|ÍC3è‚LTü7Co°Q题c4ÑÊ”®°óP8´˜ßD¥thX6ª*Ò»BU<ÝGª3ÏÈDÕ™•™¨:³*U½iGR¯½íYBMº·‹Yá‘ß¿áÃÂ2ÒFòÑ Mrú°€ÄR,ÞûðÂjPJä£B‘Ç!ÚâÃ'Ì©$õ|Ã%­Ä@¦••ås¦;äò´tÖÓ«ê´(kßÞ'Óã7†+a ØS\jƒš——ÏâˆqÊŒŠ£v¶|,ž :/ƒ¤Ízì¼2 vqµ^®˜YÁâÑžYR^=‹[Ždb-Ì(7&À¯Õs§>ß°´ŒWÄó#òn)ìä(²ë þ‘Ìmé€-ó`yÕ<×¶»õdiU–¡¯±ºµÁiE9oiGÇk%ì{i»I÷ܶ}°ôÒVèëRI°¶¨`‚—Å(¿¨‰·u’¿3J„ñt’D·7º'ÅŸ9•¶Ê+›j:ãÈx/£Tþuí²dDQø¶4´C.ß‘&ÊIÚy8äf›ÌÏJi-TÞdB Ò°ßœTª-h@&Ç‘×eTq+—4 ]?}^ÙÂê©ÇW¶ /eÞÒãNô¡ùº‘׈.pg—íÔ¢6êà:˜ÖQXf=Ëí+ádžî‹ÙôºŠ”_+þÜŠ²©Õ ᜺«g¢ ªeêu”/_N ”¼å¥´pe”¿Šøy´°üª–ñc©1Ê?¢eÌhxU˨ñ ”*ZJÜ÷á-KR)4&ž)}™Ï„Ë(e×[¼X7aõ Ê!Žë?ø]ôÎ×–Ž…‰ÓÊ […SªæN‹r_ô³²|åo©šì ^ü «´ðœßIöú|B¼÷Ã’QñCÚEÅ+аªì³U.ä·wE?ÚªÅRhùšKù'›•r’Ù.*Sy×oµ˜ŠW< vSxïïÅ¥NùRUå+¿•N*]û š]BM»õ Ï¿_{°Ð|¿¼ã‡Þw™¼QIGÙª;-íÿö‹Ý_ô¬4:3ÁÑS{5ƒCšè)øè'GJr²¯?¾®Õóýbsº½iÍH<úº£()ð÷“ó.5-“Òˆž18ˆ™Á ›YZéͱŠyÓ)RïV‡p©£"¥nƶÀ@Ùi‘}ÚFЭú‘á*Áw• ÄàÀ ›~Åxf*V¸¤˜´ é¸78 öfZrÕJ%}ü…Ë‹© “W®”ÇͺäZå;*®$üaPÒx„ñp¶“£{úäÕä1½>W 3¨ä¬(¬”©ªÏ©oO¨Ñ¹jŒ?U³Šµ¹V–´dìg÷VWsÛô®D×)çüH¬——­\ñA*ôk–¸*0ËAëaì^,ŸA– Q¡·OÛÄUÕª¸­ùg9·ïQá&X£í¸ª4»¦ªgѤÍÎ;¾­ªR¹ªCZ®*l€PÕf”Ö·Ð/e Çitv®|„PÈüŸãl¬GOß5ÌaHW ^D¨å9˜CØ*ó9š©›Ê’ÒCHÕÕ€jØŠÁ‰«dG Ìe•U•ìrkòMî«°B°=¶Ý2­5fO¢mW.J¨h;S¼#6Zà”ŒM?FlÅô.?îKÈ¿úÔe±HCÒq(1›ÇN¶œP˱Lñ&gÈ>zZŸº™&þµ3[P¨ãM ‹[bS˜ þ¬!ç?½—ß(d¿£?#CdÚµ›‰Úðˆ¨-ã)ò38¹ËùvÝxŸ‘ÀïèMÚz0°B=wádã×7¦¯û&$ öĥȖ„JúuHBwË ‚†g:L¾Tö‰<¹²°ÖBYwƒGÞã‚( î#BN®¬¹PÇïà’àwÕ×hç^‘Õñˆ`”«k/Ôñ»x ù¬ÜÞhÉ¥77µöÉû›+w0”òY–ãïÅ&ÓG>•òäÁÏ•2¦§rîBùÜÑÏ8DÁ!94èÖO¾ûYHû‹ñ¡²Xž‘Tìû9ð}åÍΞ%÷ JìÏgR3"£ùSûß ¼•ŒI͈¡KÆ>º¼¼y¸Þ‚ñ—§ ȤfŽí>'¾/ʱ·ÁIÍõè*bÌHoÉgÜöY—ƒ“Øý±þÓùh¶9,F/Š37,W/ ˆzåfcâÅŽâ½5‡ ë˜pâÅsfÌZŽ˜ioñ‰A^¹â˜xqù¼ys5ˆî-¾1x+ç/®,›S¡ë¡ñ,gýNdf÷ôü¾‡Ôé{h0.fÀ›õÙn=·wùl7.2¨¥ë×'‡çľ¼M:@·Ð|y¤8Z–odÂã l¶ŒÀšI³Œ·©ñEÙü w̾–÷ŽíË{ô¿/ïÝ>ÔÂòžøÏ[—·väƒËûôªmËûuC,o;6·­5ÆVþÊ]"¤è þ‰ÊOtó€a) Çi±—»º†e_xæÍ=wùéž;Ï<·çöµYѰ³öï¹dW”¹˜©i_-’g"ÜÎÅˬ,85^‚!ÿnû:Þºï%%˜÷iǸN;¦m¶aÐÆçQ-QwV´¨dÿ¨²kXÎ…§Q÷vêÞNݧt; ¡Îµ•uǶ¯ö–ÛßÁ®«üâØÒ'–¬Æ[Œ]8¯¼Ý Yd1¬]-µó±ÊòaKsÙ_ûêÀ`€„~çó§9|I·7fºx¹ÃA@çåÍ;{³…Í>§û1[Q¹ ÙYS ç+¦¾›Aì|aØDQù`è=¦ýìÞÚÛ{Kp;£`ìPÙÅ©| r•Ÿqæ“nš’Ê·üŒ»Ù¾CsœÎ®:¿s¿hoÿÍ\·s–Og–ø¶è©é¸þ+Ï2½Ó,/a–çûY®Î°µ,º!ÚÝûLðên¦Ÿæ@åfÐØs³‰9²ÑÃ:Ùøò6a7Óç©–]6ÓbX0[dó‹e³a~µ(Ûi¢ö…éùÍgÃgƒm†±ƒÖ9ÃÌŽŸaƒ¯Ü S£ŸaŒ¥1ë²XÔpDïMçL¦„ærAœ"ÓÎ\áfl ³vET9‚ëM³Ÿ+—ÃΡr´Ã¥ÐÜ¥sxåMãJW³wõ.EÅ:g}ZC /wº9LylsæÍÎ6ÚÚÃL.±w`ȳ-Æ×›!UQ›!Ån×äºbV<>áÅ1±idžµlò¶ƒ*ê&&|O¦ÔÖŽ\žU4ztbtqñèç*~Þ豉ѣ&1qì˜Äx’“+å- ¬Ð¸š0¦’¢†µ•VI[%p³m”Ï 9 ¢ÊrQÃZ_m› iÛ¨DM{¢¸sŒÁÙn…[ä¬D6¬]±$j±:@\Ø3••£†µÓRu‰æT{Bþ]Ú=¸íÐD{*ሴ”ò¦%b‡&«smw`s û˜²“Ô°V»ãÃY=7ÙÞØ©½±‹7Û±#´Lµ}¼£OÛAtÛ´wóý¼­+ëÎÕ§E{¯>#ÚÝ¿™ìvK<Ëá°mQA æšÒ|ùçâD#Åk2ãÔNWÛA×éû8‘sRéêžëÓydÞ©}=yó<oŸÛ÷V¶Î©{çiÑAö=A8ÂÄ ÑH{3Õ¾gÚ»vûžgïæÛ÷"{·Ä¾—Ú÷ŠI{gÝÕÍ&ØV”Þ«vÏÎ÷ï¶ÙÉÞ¶/»X±ùÚ½n6¶q=ÙvA¦íØËÙ±›´c?ÀœV÷+ˆk\#zµI÷ìWMHŠs`J°»Ëcu JÌ:>`Ù cz,ÄÊõX‡ßÓê¢p­ÍÇÞÛdï°¸Åb˜ ¼Þb˜Zº=Ä>k1ìs­0 †U¯ ö;]›¬>¬{]kï°×uƒaŒv`‚ø&\‡ 0èñ*6 ±–&\Öÿ‹÷âáQ}¯ù€Ñ`{ó†˜/’Õªþ¿–˜~[C[®ðúº‘ 4ÐÛZ`6‹ÌÆ+™ú‘û—µÑgYýXAÄúœf¢ÿ¯ðrºw Ñí í“-ݧ±7”Y±¶5µQ¢o¿®Ž*ûâÚUʳcÚt#ÑûÚËno§¹ó(3ng¢±¼oéÛùßÁÝ·E-ohmï€*íú¾g5ùÝÄ~i±Æ(£ß)Øh 7”s®ñóÏÜù=‚Ù@?ÿð ;1áW´.Ýü3s›aòqlln´å¹"ÜÍI`ŸGC ÝÚÀ«Í-ÂR@\N¬Bb¼IV»|N댦Í[Q`KGksÐî âÑQÑgXnŒG²+Dpð¹ùjoòtWaíL¨üÖòÜM¸Ÿ}1»ÀóOÍj™›³’±´´;Nìr¾[ø;‡ØóJ»³¤÷ôuÛK ‡4Çû$žÜ;óºÉÙ_<¢›+ë¶‚è ªüÝKøžP•—Ï÷äªÜcùžY•SR<¡,%ÖÑŠ›ŠGw-Îéìêæÿ.þ>§sWCÕ(`ùÓ0>±Ÿ2ds­ð¹L ÚOnOL·Âc©v œ…{…bkôö*á;a»Ã&ó=¿*øD¾UåÑWÍ‚é§ú²"JŒO÷O˜sëM9'ï›Ó¹¹¶»1>qÙå ~/& Ò<óéñûÊïBvÞª°#ï;òKöN»*Þ;ƒÙbë´‡âÎðN·e³;1áÙ‰¾î)ÚAéä¶Ï”µág¸ÃÜ„ƒ?öê-´£2«ÌçÆ(¦‡ecmøi€ÄM&3st§åÂN(†»d}-˵1µ"‘‚ú-0åkˆhkl¶#C].F1ó%kmÃÏ@¼Àîú͸&ZíּσùQÌlÉÈ™ê=R½¹ŒuRkAvø1Ì`DšnÒäK-æK1Ÿ,ž„Ë熦§>¸…˜ú’Ù´tÖ.mNc“DHu¢-¦BÈç“à Ø÷Ã~œnþÃϸ÷^(Ór;”µ_“ª;$ýØ!™c‡D¸ÐÜS^ÿö¶Û·g}6Šß‰ÊÕ²p}Áݶ¯M®kØ»gL¶ýmv¨þ›û‡{O¾fwëÕ{Õp;oðæwpU´ßÝþ.£wÏå]‘\æ£Üó­6ðCÌ­&`Ú'¸;Nв~¥= ŽÎЗÞ˜;‘r,²Z—ø>v×cnK.õŒöõtærØf‘úsÖúü_¯%Ô >úA­Kí­UõÝF޶PŸÇ~OÖG®Çê›ælÝØãïâ"Y œ0`›æ`E2ÇFþžYîS'÷¯µØl¸§ÙÞa{Ðß—yw޽Ãá5áÝ{‡-Â;û»ì6 ï ï¾nï°ÖèoÜz—ø›V—…w+ìÖ×ep^âïݘ¿íÀgÉUŸaüÖc¬ãbrNFõ†ŸÑ7GY çö-?£Ï¾Å{w9ØxC(N4Ä&ˆ‡ëæâø † D~_ ‚ Ô+˃¦ÞÜáÅý‹­ìób.Nöð²Zòz¨Õ“ á(Q·ÐÉÕǨ©h9±ð ƒ¨V_G~S[w͘¦f]Âw×Ì<ùuËS.'ü…¶Ø¸ñ5w×Ož‚5áÑøð‹akX\,Ãôp«Å°DÜb1 7Ðnªð%èƒ,*þ°†öh°iìkÇı¯=ô^KƒqÂ~é²Â;†ƒ=é Æu_-Bkj*¾÷¾Z½_×lQ¸°›L ’BhšýȶjÂÁÕ€‰e™Ó+’³é)÷ÖpУ^\=Ød¦ñ¸šÚ7×ó]O®ø<Ô#¾QÓÛ¬çïncõ³ê²-9råÁm \§‰·®£DA$š¦$V¦:MmíîÊ¹Ž¢ÚÔ)%‘¨ Yœ±ò‚—‚¡h8_b×\‰Ô“¯Uñh§ØpôÈ•iÉ({·¤·êÜ©"0~äJÝüÝÁÝüì½NHÎ^;&븱ŠíLÌ‹ö}Ц„ÃRÚ‡ÚS6Æ\´¯€~zìHý —ñ†·Ô‘Ý·dËi´x‹Þú9ÀÊ5s Gž–ÆŠ*[l0Í#Ž<|È9xX‰ëÇs@ës€•í}s@o='ôcpt?g=Ç&·ô’м¿ì‹½=w7ÞÑé;ªŽ]öy*X¡WñÌsú¸}¶Æ=Ã>çîž©iÏèïYŽY°Û ¯ˆtCãá×M²€;g9Œ=–QrŽœ¿+À‘óü ¾Dö7s€QÇÎ9¸!s30ýŽÊ›–åžÂŽ—Îreyj'Í‚úyŠÂŒù ]&)숂‰MNDzsÚ]ѕ˙½9ížÝÓàÑÞœ`ÏzNðloN°f='X·7'زž Ý›üXÏ ïÍiù½µœÌ7={sZ®ËîœæžÐ›NT='w‡Þœ–SÕ•îYoN{«êÊ G­7§åtå4wžœ–Ú5kæfñ@N·»f ¤½uZ¾nWNŒC÷æ„]ωÝìÞœ–ÛrntÆSÁnÅÞœîÆÃ;aT“œ[ÏÁ;ŸlXÏÁ;‰v˜`ÉzÞù:à,ÔsðÎç€QÏÁ;ŸnE=ï|¸õ¼ó9à}ÔsðÎç€CRÏÁ;Ÿ>J=ï|ø-õ¼ó9¸W×sðÎç€/VÏÁ;Ÿ>Z=ï|xCõ¼ó9¸ÖsðÎç-×sív;¿#‡¹òÎç`Ç×sðÎ× ´^+ï|8Eõ–kdk…ÛZÏÁ;_H¸žÃ dWwÞzÞù:Àãõ¼ó9Шçà¯>W=ï|ƒÕ»sðΉë|Ð-®Sü—%h£ RûY§ì›èC(¾ŒÂ—žÊY±ÒJå½NÃSã_t©@*°³¾à¢±5¿Êu–O¼n_SE=ºr6¨z©Æ4çhˆÍÎn$ø —j¬ÏØ 2ÑMVZ¦—ögJëmrV] d¡ÆFMˆ:ܨ«ˆú×($ ”Ú(¶€¢IÖdµ›„ÅÐ$£ôºL4I#O Ë&×MªY†ÅµMú˶.býeYµô—åYÕÚÿsnjAÏÞp¸ƒ˜_ÿ_X>dÜo€¬¶«gd_šd×\—îÚ^êáõTs2å.W…ôõv Nl@õ^½øñ¸¶˜]ö“Óâ.aÒ\c‚tY$´-…»A0îPÁ>5 Ö|h/!âÁB‹ºœ m‡J@«È>b(·Ê8º”qZÉÓÕ¡2®‹üPú†Aó¡2~­ùÆECÛÃ¥£ž /t4àÖ¸Öp¶Â´?n›­Nš6ÊúÂô¿t¶‡c ™^ŽPOTïH‘yµÅFÊ¢®ft¤fZ= ;Ž+ØH‰® áÒ\©£„N4/£4—šƒQº@‰ù0JÂNêñ~Ú¼šùýè_L£eÚ[=-3Ý"=–kÍåh™ŠÖ\Žf7bê|Ií©þýe†[õïÏü°+ö§6LqÑ;ÍÒ™­VcàØaæzŒÌ¬ë~8–Ú0'=–þ`"z¬Œy«î±ìLL1·Ñ?Ì/·Éè²f·MÉ5³m2­ºÇ±{1¾=Î,È[øÐ¬Éžµ‹2]Ùä¡od~Mq-M2øîßl²7\Lü›ÉöF; }ó{CÍþ͇ì Wf÷)ä.”2RWåyeœc¤» º\SÈAÍä¸ÔrpÙt;î2™VŽË¾¿½ì®4:¸Ýúï25é¦IÄŽvn¶)è“CL̼êô…ú¬l=Afm¹/ðYÑU<c¬Ûc91í—6¦Ÿì)î*±q, x¹Äàô ÿõ~W‹ [³{%pCÅQ f—És0'.L0“%lÓ9r@-$¦™Ócá(³×éŽ^éÅ—]ì™®:Äÿ@7K$©‰òa*OFeô‘ŠÀ‹ôýÏn§:f,G iØIV+‡ÝD\ód>Û¨ù€È¢å—9™Ð6︾kçšwôY®’LŒ.‚‰QFŒ\3]­¢Ò,‹—ް&¦´Lžv‹i—+òWn.Ôyc˜™Ø×Üֹ;6ï˜tx1ý-WÀ!·Ù ¾tsÏt0à %:0ÛL8Ó I“Ìë£æ-Vîm7îuµÿ«W nf–F»º˜$å1?¦“ZxÏŽ-Ä4bb[¨FÓE~ VkÐÚ,L¨«ˆŸl\;óÙäÁÞ6[£Õí'&ÍO½5ÄmëDuÒ7bÜ80+mê3µ8  ° ÐAôµ &èkÕøZdÁ>­E  ®ƒ¸ÝÖ .L{£ *ƒln†ç/Äí5['Ã…wÙ®d¶É‹'ËIwÝ2OüWBFâ±›®ÿhÿû_NcKÿHˆS1|°@Ö%ÃL¨¾àbÀQ8{!{Á.„ãóéh§,M f*ÖÔkÚb!<Ía,t§ åz1»±P¦:¢Ó¼ÇBsÚ\°"vD,£äڱ̓såÁP¹6N,L¥]Ë丶T,L¥ýËø¹6 W¡ˆ-«§Ú¯±Ì¡këÅÚf\}؄±.Vh¸€o´ïcaá±X¸Fx-¦ÑæŒ1IéòŽâE&!ÇÂ/è]„1bá.•`¡ÄXW:®Kàa³X—-a¯XœaXš…B!±®+âxź'ë¶KPW‡X–tˆ…t©ˆò­F,œ¡ëF,œ¡»G,œ¡‹H,œ¡[I,ä ùŽA g bˆ Ä …X¢ÿ¢¾Å’ì—ªt̔ǺŒ¡ª/Öc,)|a˜XBö\‘ ˆ¥/~L,õw!ôXúíbþÇR\×==–Fºnï±$Îuá%O.]¾XãÒèŒ%.ݼX"ß\æëÖ _ '(ÖõNzs±$¯uEc‡Ä\—¸üÅ0mbÉCëþKÏYW½XzÌâÄÒSF“ 1d4¨tI‹¥«ÆET‡˜Ãcˆ1ÎÃ1ˆQT‹u5•…÷˜«l¬‹©˜ž18"F©"a ÿ³Çc4°¸8ÆÒ¿Ò…#–Þ•®\VcìôÇ\0¹ºÆh\±ëb¸Z캎».†ïÅ®‹u±Ô®‹ÑQb×q‘e×Åh#±ëbxìºXú0Úu±ô`´ëbi !¡"».æ’Ç®‹¹²ëb®³ìºXMíº® ».–®‚v],íºXº Úu±t´ë¸˜³ëb.ìº~».† Ä®‹¹Ê²ëbî“ìºv] çž]Ç5•]ÃÕg×ÅðÿÙu1—_vÒìº^>».†_Ï®‹¹³ëb¸x캻.†ÿÆ®‹á´±ë¤£fv] 7]ëÒ«]sQg×qÅe×ÅðÙu±Xì:ñøÌ®7Ïì:!³ë„]Ì®ª1»NxÇì:ñ£Ì®Ã×ì:]ÛÍ®ÓåÓì:ñlÍ®“>‚Ùu\ÓÙuÒ^0»NXÎì:¡<³ë„ÿÌ®24»N˜Ñì:¡I³ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDì:0»LÄ®±ëÀDh|€‰Ðô¡Ç&Ò®K„‰´ëa"íºD˜H».&Ò®K„‰ÐVi×%ÂDˆ¥ƒ‰´ëa"íºD˜H».&Ò®K„‰´ëa"íºD˜H».&Ò®K„‰´ëàH³ëà;²ëà ³ëàü²ëà±ë`%°ëàè²ëàœ²ëàC²ëà8²ëà-²ëЂf×%ÂDÚu‰0‘v]"L¤]—i×%ÂDÚu‰0‘v]"L„V˜H».&‚í&Ò®K„‰´ëa"íºD˜H».&Ò®K„‰´ëa"íºD˜H»6».&Ò®K„‰´ëa"í:XìºD˜ö˜H».&Ò®K„‰´ëa"íºD˜H».&Ò®K„‰´ëa"íºD˜H».&Ò®K„‰´ëa"íºD˜H».Á4•® Œ?å¢Ç´sµeËs?cËsËfËs÷fËs gËs1gËsiüuwc»lu·Y7¿f×~ÜøT£Þ‘¾2W¢6w­ù¤eæçï|l#®ÊÄØ<ÜŸÝýMêïlSsyc{pá%Æ4»òró»Íª¦Ó?çî@ee2ÄýgÒ1v!½SÐ\Švס_µž‘fyØ'ð/è»v1öÄ}v}d'|“¼iæß³<4ë‰ú§[ó®È/¸ë’ªÖ×­.f»õîÐ-ÇÇ`#›nY?!t ÌÈew¾»§†n}Ãußv £[¾‹tËwˆnýCèÖ?º¾ØnÁ€M®-”HÞ—6Ž"¿èº¥èëgÜéE_±[\L5*ö.RPìv;#ö³; ¡ š7õ4Aü©¡vCŒ‹µSOvq•Ù~k§DÃTfBŠÀs×>×M½s’ÿÖuĮ̈ÆÔ«ÙÙ˜óÀTc;+î}O'\—Œ™%] Ìô0ªZ_7»Øßñ ½7¢¦âu­Uü(ï]Ęʑ<…?¼Îp~¿è >i¦b{_¸üs|OŸß€Ÿâ‹¥Ò;RÍHÞEyg‘f} Ÿ\ëS™l¥â¦š¥ˆ·Ä‹xí—F¨ 9 ~U[{N‡Œe°òþÞHÿ¹j„p˜}l\<È»þ®ãË¥>l‚QÁñzn"…›ñƒr>º,6ï‡\ ±É­ÛÛy Í5­+qñ.CéÖrüóÞºì›èbj±¡Â3ê[“ÎaŠ*Šr¾LÑÙVgu\ž¿dÄâÿ¶xCˆ®Laõû|äa¢¼éxµØRëÓDË[RmxR’‹rŽ/ëbËj<.É7µbf=¹È‚xÕŽî° Ô]/hn’å¤èóäYãË&Kr£Ï1óöf_®Q/fî¾ê´M,Ù+Ö;³ÁÛð…‚c “¥½Ñ³±B>Ó¼¯)¡ ê)ïr÷m=;•œéâQÁÏ0ï~ç΃­»bVâàÉYÖžcÞ‹Ç´5Öâj3›¢pî8$tr^G¾œ /T2[*+R¿‰§‹—0†û×t´§ê“òÐ=ÐißW®PvéàËÖâ6¥;Ã(º—šþMå1ƒ/§Î3d'ü›¨é'/Cädã Ü‘ËdrtÕVÕöÄ–¢6¨†êcEq §›Æ¤]­ú2;3ÊYü\G__¬&¡!±$.}®rÖ‚£åÕÒºtÍã çân+>+— UYñ“ñÖÒÒôü°É¬Zîb>Ê}oMëRL&½KAºÕ²þ Ÿ21ô´Þ¦:{Eõ‹Ç4ãÞ*ÊμL㾈]të½XÎyñ€(¿|ßÏÀ$}å7~xjàe»èX]:2jyþ.G$•/97¿…,cIý² Þš ê|­>IgS“¹zéåÂÒ12½ý®Ò1x“–û˜„.~ÛýZ@wò)›Ù¿Â§î>7lÌ®Ì{\~·ÌO¸&çóÌûå*^Vâ<¯C~«ºÚ΢Zà+—ʱ|៑4³«Í©:MϬ?#êdˆqãò³§aókêê€qcNgDÙª¿Gx;ʽµt æÓ ?üØtùµEõ¬3uäõE(Á^Ú¼Ä,ÿŸSüøM.#«çZ˳Ù"ZÅøžù¨vot¨v¡A•êëZ`Y¹œI2‘ºO?Žª´à¶t,Þº‹äSëëV>UøÇKÇj}ÝŧÖׯò©LŸàS~›?ɧ̇ŠOݰÆ?!œ™Zâÿ52«ÇŸæS…ßÍçìm^¾‹ß/+ëï_æsÚv'ßÅ/S‡VÿKúäÈ¢‹ÞqlòiÏ&©<}+˜¼üw«ÛÿËåuߤ‹?fOhÝ˧öX¥t,¬7Li‡‘SK¯‰OyuÌÀtñ©ä‘­ìÿŸÝÅ$ôi¢Âö1cºø4!zÐtq8f?dú1“Ι|NÖ>°®ì·Eµ¡pÑýÂ…‹ðYØ'yã2âpeg Úõe–LÅj³ 7ø)~°M¼®UAº§"ÁÒÓfŽ|ÝQîóP®”Îg‡ÏŸá[Ó«ººjˆMã —ãŽz üÕL7 ¼ÖßñVŒ‡oµ&W3qÜ«þEÊüÜFÙvɽ™ãþ(E Œ•®öï*iX׌ZÕäq bÃå™d·#ãñ2ÿk±â3Nò™]¶ŒyÂí’-©\w¶£¢·DJïRkG“k *rCxÃXTä¡Ó<Æ¿ý~캳²Ýuç…CaXf=âê­®;ǵã´×uçÉ!,³V]wš¹Bù•¹’ ]é7-¸¾u®¿P‚e+J_«ô›‡ÝvÒNl¾ï¶sB¯ÛÎöÿÏmçp'n³ºa;973¨Ùz—3(ÚÖv¢p»Ôí0Þi'Š·Þi§9¿ë´SNvb–ªÓ¥¥uc]ä0gÞ¥%õy—–èß¡:¬i¨<í^GGõ¾;xçfDÊl 0VÆVN«ð³Í àþM#RûG—ºíL]aþÐeç`“BK‚V O¹¹CÏ»–ÃåŠwšˆÖ¾w!G«'ÛÌÒëvË[ŽyÃ]ÇR›_\w§ó™ú^§àï´÷œ3Ìüø¶Î;ì Scƒíu¼'°×¥Yi+ïlh—¬´›A .¡b-ÜUi{Ä%Ъ´ ÏÜíQ‡ Ï >GŸŽâêɶ4&”ŠeûúïìsôÙ¶ó]}ï…jªïUÄ=vîésü‰3Ð}uðþ¡:¶ NUžmÞU•´Y¯bv: 4³$½ß®YJöÞÐë¾âf–6ÚC7ädËqÝ6‹íOìH‹!6Øbc‰•-vX`X`•sªWÅæ’ =ØD…ºp÷#ÝØÃÞÎT=Žo{Ç `ÏQ‰öΉÝ`1T£ï±{2îDã»2îDïlJ;>ñNíÔÕÄ\]‡W¢p½÷Â:¿±ûåi”w…õšßäæ_ÚÌÛ@¦;ÏË.´ïnnÓÜ´¹ï·dïÏ^ÝæbÛ³à}bï´÷‡Ú÷$ûÞà\sÚÙ›–ÿb‹o²ïgÙ÷%–o3¹[,¶…ÛÉSº¹zm]¼g!9FjüiýñsúãOï?£?¾²7Þu—ú}«W”ÊC‡ã>Ñpu:Μpnïµ£xÂ\|<ž‹•´‹cŸ³òÿxy´øé¿¶¹D}WMdËiý÷‹['6yØÎw9Š ;ß)WÚÕ7ö4,µFçÓM ¶ÄÎG½¿qòb”3å8B±Î±æÇ³ Û?ÓÝ39§Û™ P¾eUŸÉŸ¸úÇÖÓ² «ÖnJ×ÒìÂ59QBõ,X휖¶RcâÅÍ]äßVŸ5bõ+²ÒXAß-%8Ÿ°®/ïïéF÷{g]¶\ЦN^ÛÑðÎîaÊÑqë¾¥|3Ú¯_Y.¿ô²\u„™îÆè"{Ç;N^\Þ[«ÖåO¬ú ;nÛ «Ö±ã”cÇì8õG;n'»Ž·£ª; 9‹Xlkæ»Â]©ÍÞ4«¿úîÏ7oðvæÞyìÄ?f'^5B.H¯zeVÚ¥éYëv/YµÞÜôÜ>œÐï$rDz?Jë>w7÷ý[±”û:ì\’©Û9v¤Ç§ì4ïD—ûÕåÁA¬Ç§¼»9³ScãÂe€¿k)‡\BÚw¸ðq2 —ƽîcã«$Šîv­vNÕ},>zð4·w×jÛu.\#Ûh‚íßâðJŠï&j̤;0{‹Y›ËÍÃa›sJÐ¨ßÆezÅMùSºÀLíµÙ{w½'çBÞGÌ÷hpÀùÔâU=¸,F…øcÑ0n_QNjYñ½ü)ª!܉Sô{ñõ¸ÃeXÂ9«ïÁ9™óUÓgV½#J¡uÞ?°sÁeæ ¾ šå`Üè̼YˆðàÀ9çªvæð6¤É*¢y?nt¿ƒæ]“˜£¹xز5ŽJGº¹Û2‰»Ã\ü"°[·î…›ØQ9ÌÍŠUÑ-ÅUùùSFîåöm;;¹™X™ØdwоZصø…g&ÛaóZñ¹ŒÛÒ¹ŸÄšÅóøc4¬kŸ«J˺{.î»ÿìqŽ,ÿK»YÜ·O5Œé>evüˆ¹ô.™Å­6‹xwêœÅ/çÅÌŽŸEœÆ2‹ò00þ°Ö:)Q®€Û6â°D¹¤Yç$f'›R­+î/ÄËëÆÄþѯÿaÍ"Ž$ãP„W3þ°>G…º÷­8í‰%9=rt:ü²îî+¢á»j£¢®9 ,&º9ïÈÉ^^•Sp7óôÙLüÏ¿Ëâ϶÷ïÍÄÍû›-~¹½¿!7ïwXü9öþòLܼ_gñçÚû³3qó~‰ÅŸgïÛ3qó~‚Å/µøÅ;Üû>êªPnCFeƯãè“Ï»wŽˆƒ5«4é›R0œBÎ9¾öúýzçÿ£Û_k†«qr„8Ž5BœûQˆãè"Äqâ¸ûqÜv„8î7B7!Ž;ŒŽ;§vÖÉ[—+‰ã•ÆÄýJcr×™Æäº3Ég“KÏ4ÖbãClBˆM±©!63ÄÚCl^ˆÍ±E!¶$Ä–†Ø²[bg‡Ø9!¶*ÄքغÛb›BlKˆ]b[Cl[ˆ]b;BìÚÛb×‡Ø !vcˆí ±›Bìæ»%Än ±ÛBì½!v{ˆÝbw†Ø]!ö©»;Ä>bŸ ±Ï…Ø=!ö¥ûrˆ}%Äî5¬‡#¾Î;.r<Ös.öRÇÅ`=ùÖ8ô-+ð…ð#¬÷Çc ëáªDõ•àú–ÿÖ»¿ë}¡ë™÷9Ö3ïs¬gÞçXϼϱžyŸc=ó>Çzæ}ŽõÌûë™÷9Ö3ïs¬gâÿŽõ²ñûÖç™Çzšá=X}Ã`=ë41‹y¬GÌc=bëóX˜ÇzÄ<Ö#æ±1õˆy¬GÌc=bëóX˜ÇzÄ<Ö#æ±1õˆy¬GÌc=bëóX˜ÇzÄ<Ö#æ±1õˆy¬GÌc=bëóX˜ÇzÄ<Ö#æ±1õˆy¬GÌc=bëóX˜ÇzÄ<Ö#æ±1õˆy¬GÌc=bëóX˜ÇzÄ<Ö#æ±1õˆy¬GÌc=bëóX˜ÇzÄ<Ö#æ±1õˆy¬GÌc=bëóX7–û°žÝ}™SmøºK^"ÞæùÓRÍõeX ˜c×ëè.Ë…'ArIþ!äZ„ @šË×…s=œÉɹŒÏµ µµf¥Î³&™®´÷VÄ%³nê%t/ÙÂëð7Úmâ¯;,µíÇ#²¼„Ú;ø æn¹OéæÞgËÜc僧}îè‹>Ð{“¼O´˜[ìgŸäÂß%ŠœPÅʸÁ^a?g襷qæ¡vMC d·Ù©öŽY›ÞyÇþá–ŽÃåÎûíÝ»À\çиM–Wi%í©T¢©¦ye’ºã÷lÆl°Ú‡íà)>'¾`ÆÇN¢§•$í þõ͵°6ËZù±‹œ, J@ý„iÈùä΢qš.q‘i%²& Amc{¢¦ÝŠm;¯ý)“è XIãï8„¿Œc ié]Ðé°Å¿p—ÿã®)€#ÿëêèœ Ó²‡¯&ë„§D…è*—¥Óá6Ø[± %¸õi „CQйßï(|™UÏ/\{žçð*öѬƒÒ±í8«7±§žýÝŒ›røcϯ߷eÁÒ‚4ßG5bjÓøn®Åç¢ÒŒ –‡;ñoÞpã7¾-tç—ï 2.VËÂEÍ¥¿1÷ž›žÅ|{Çl/ ܳeöŽÙ½)ä»Ív ~v:1ÅÔÀÛ0Ê;nþqꃟH9Eš–n^þ7³øÔKkZIŸq ½vw ã^Ö:Ö9÷sÚä÷µàן;bb™Zswi-8ÈÅŶDVK^µú\Æ¡®ue½»njõ1jÂÅ6=À«=¾@Úo+ɔՅü„Rj=è¨ÑÔßÝ<ѱ¸v÷…ú}Œ:½»n¼ûàÇPˆçš;ê FÝ8îèƒá»ûÀÜûµ{ÇÝP„¦Æ>éÃC½q|V„jOo«·©ómÍFêp[sÆÅÄÐ}ÐýÅÄ4×Ü\LLû€‰i¤®¹µsR×ÜÚQ©coôè£zû?ûè ?ÜGíÍ´4ù^„þ¢—¡ù41ùžâÏ÷×P¾ï8Ïk³>¢ýT/¾ÓÇ|ô Ð7Oyç῜‡ã§O^‘ÊðGÇü­0S·Kƒ8·9÷Å 0¥ËÖŠM¹zpìG=r&6¦g{=Ὰ¯<RtˆÆN¾WFü¬î[@gM—Y=¸έàüë:-׬˜äÎë:-Ç!¡úZA¼®§åx0¤¹€ë#Ài9.©G^·úpZŽDœ– 'í_öœ–g·ŠÜÅ„Ãö/»ÄG»`ýÄ뢫U¸ãì_öGWáßá H_ç¸-7„Î5ôÈ%ÁݾóÜæÆ;G¯Éß²è½çrGðÄñý¸ÛŶ™{/`üŒãò&Ÿë mžyC"èî\¾ÁÍwØàé%h#©¦=»COg…Í~);g⦠§Ãø™Àm%{B<Î>0\Ó{¯'Bï½ö½w®ÆqݸÏÕ¸éw·«ñÒ·ÌýµÁ=«mnã°W©cl0ooN»ºr‚™{s‚Që9Áܽ9Á¡õœ`öÞœ`ÍzN0uoNðd='˜¼7'ø±ž¼Þ›¼XÏÉ 7'˜°ž“;BoNp_gNïð¾7§½AvåäæÓ›ÓÞÈ»rr?êÍé¸C»srgêÍ鸥»srwêÍ)$¸''÷©Þœ–ûÞ•sŸKsËóîÊ¹Ï ºåéwåD‹¨7§ÕRèʉNQoN«uÒ•ÓÜåzrZ]²®}cnf=9-öêª÷­½9­]WNü³öæDg°žß°½9­faÈiiƒ½ë޲yçÝkƒÛë9xçiƒóë9xçë€PÏÁ;ŸNA=ï|øõ¼ó9àÊÔsðÎç€SÏa]ÊÿÈÑú“nÕŸt¢þ¤ƒt4ê9xçs ÛPÏÁ»Ÿ¸CGW§žƒw>š=õÖ…þ\¦£×RÏaéÛhÕsðî'®Îq¢þ#GëÝnÕMŽàVí[ï‡ÙÊ®°K½Þù:Ðc¬×Á;_§æzÞù:¸7ÕsðÎçàSÏaëÛZÑ‚«ç°NõèVÝ`‘n·êqPpП)«×ùnÐuL„ t‘j‹J]k$†-¤Ø(Ÿœ:°5Êcª^£ü°j@p±ŽÒ&ùûÔõ I>>Å®jR]‚šä9Uõ4ÃIf1û‹W¯M°¿ÜÈjéxM¿-î÷þ} ßh>jšrïçY÷É[ë¾í· 7¿c´Û4¿cµ ¥©:Vœ9U;V·Í-ryø‡nÓMD=lS¥óØö¦¸?mïuSÖÕŸrº?µyÌvÚ¾šœ3ÔcaÉræ¬}5C›µOgð<1S½UgIïYÎz~ÿ– 7?ÃÓ?Ko¨ŸMGÉ„'Ól—á‹ùü4ÒÈö©|L»}ú7qcäsÕ½kžê‘rõ¿±òÏÍÃwµ¿><Úûþ°µ#ƈ§«üc>lýÊst¸ª5þâ®êq7[sU¯Õáª'¶ ëª^×SWõrOŸºª—{úÔUýÁUýø>Wõ B†[Wõ‡Wõ‚«zïužÞë¼uU Öš«z9‰W̺ªÇ=¸ÌºªÏ¶FÛG*‚YOØTòÓ›ºªgkxWõ¨÷P+(×»§™{÷ôà$ïžžŠ¹£xWõÞ==JÜÞ==B•xîö®êq/á]ÕãžLÄ{ÜÓc#âžÞ{š÷þæaíͱ˜u˜þ7ê¼q:oòó…Û^³ÇÍ;¦ƒ „úæ\Õƒí¼«úQ6÷LóÌÍx÷ôt€ÿÞU=ü?Ðh|‘¹ªÿsæO½¸åe­«z¦Ç»ªÇm„÷ÝÎn` 1ì ¼÷ZWõÞ•½uUþ9ñÃexæª>s_Ï&ÈÜ×Ó ÔnLÌÌ6Ùþ(íôœk³Äo¡ÅœŠ©°ÁUÓyzþÜ |>×ê¥Bkpuyßõü¼ïzê:)έºÈùŸÊIÇ[ÖI®óN_ØÛmÝà~~ÜW³kðd¯îàÁÛûÃÇû²ñgcM]‡¿z®Áõ/·9™ä1¯@‘ô?ä˃é™Z ]XõÜwjþêaåá«Üú«7×F×)®“~ÎqPîýÕ´hñ–ñ`ïýÕ?ÝêcW<#l¿•aûáÁ¾šÝ7h>ê½/ú¶‚£VC@\ojˆ GÍ™<Ì)ùvîðE/çξèñÂ^óE¯ëe‡/úšÃyîlÿš/úšs{îhµø¢¯½€ËW« ¦^í<¼šO{n˜ì‰ìw PJö‚ IÍï=ü·Ì?/`ÕüÕ{wôÞ_=œ¬š¿zïÞû«÷þè}F®‹µŒîw\ï0{ê¸þƒ}¿½ÿý,nPšBïï»›uêО›{Í¡=ªÙLeî“¿6ăÃââWäãeuÃTó~ð•´>Hù$çÐ2ÓÎ(­ßïsÐxqyE Èãî³pMxå¾XõË©)½jöãòì“åÒxcvV,üåÍu[é|•qᨾÖµÄÒ%„^–±fë)ìW>ºÅXIÕsqòÞ{<|ôñⶸrÉc&θð1Z|cx—# Þzx—‰ý_ëÅ«±A¬Éÿ©-JÅ:ÈWë>gGÙwÜcä1ŸÂ?0d¼½tÌã~3¿iŸâSõn¸Çr„øJKºË8ï£Öú~0;œóˆ®yé“¿Üî°‚7ÐÞ?Æ‘°¦ I¯.kÅÃ1*,äü;¿5ðˆÿâºOá; “ܰð$jÕ@_P:–ES\ƧÖÉz>åŠô™|ʹñ²‡Eú3Â’SF†_V:v '€7ÿ^þ‹ä¶Ø¨øZòÊ¿°uE\>õQIsyw3Õ«ÎG±õGÛ¤°‹;“bVÚ¤²õgUœS:vÂø(ë¨m²ªÅ¹¤P‡–ñ©z§—Ž+æsŸrÆ{Ré8€Zôª‡Tÿ„¶ü2h¼œÏ¸©æÉaS±ze®}˜Oá§> &G7lÿhêÖR9ö·S_9óÿ vaÿM€!ž2ý þw£Ë¥oü^·*Êÿæ­¬rÇq®Òß NôUñÿeÚ¹‚VÖ#í«¼þ·jaå9j€õÅáúg¹þ ȼ›Ï™Ðµû ™ªYˆ¾•Ú„Žþi«ì’Àß, vï3Ùöi2èm¬´ÅàæÎ;YyÖæSQ¹q‹©©> \­• ˜”D¡ v ÏóÈ–îöPtÆïmÎÞ‡µRdy$*¯kOF3>ì(E4¯ŠX‰†e¤=Ý3jžáóJª"ÁÑ1Œcµ4q'Šq‰½Mµ ê=ÍNÙÂÛTtr9½AµfÔ2ZbõoPmȽ&ijÖÔZ£*"Ùn+ic²úRõ¤6LŒoX¹]&ÒÆ=|kqÅxGjc ê´ÅÆæZ®-âì|× ‡)H$SÐ86Áxñf4J»ï/âÏ|ï&ãŠÒSÔxH‡Š:-~i†£Ä…Û‹§]Úp¦€Cq£q¸8„* ƒY*àA¬n ܆)àp(Óâ߃ÂÄ}\ªÙÖ#h¦¤1ga5T¿¡÷‰úEG  ØkKnNádI.µMýS­Š-ÍbõjKÅLÂpÛü~ìλi«;…ÓÛÿäîc·µànâ?ou ‡úü^§p§£Ø×ëî¸SëûÀ)œ©]^·ŒÒ®ø‘å}Ù&ÓÚj¼« ˦Äþ*ïû°[¸ÌõÍ÷ÝÂMîu ‡åÿt ·Ÿ‘3èÞƒŽáà«zAx uÇp(,µ³áÝÅÈBeê¾ç“ŽáàƒzÇp°<;ݦ ê” ™5ï6ú¼c8¡À MDåù÷*“öö¾æ6©s„Wé¨v Çx×p—þÑ5\[¸©v ·Çsž7cñŒé£EJnö`¿zÇ7¨QxU{éÚhž­Z(ýõʘ¨‘xuHZ±ÈæV[§ê®æõ:…5y§pp}÷9…c†üìR£w Ç©…½.&ne½9…‹mî`ó2ÿ8…»ãåÍ8…ë»@¥t§›QKïéšÑ0‹].á˜?‹(†xE̱w€&ÀÙceyç8¾ëTó¼=¨y¦¼›5áˆyÖ »UVT,#Û‡µ§ž[1¿Ì{€s³'l›H M¥aš½—õÜšÆ3ÚÄU÷oÞ¸F“nHî­aê ®ÑÌì)u»}¸ÄÚóö¶¿½wÛÛâ5Ûßþƶ·Í¿¼÷­4Ï÷öɾ} OæmO/ìÛzaÞvôBjUíèúÖœ¶Mt.âälÎ9aëK!^sÚ¦78?#¶=ÚŸwÆéÞám“ÅtnÏllbÆu[ôË;¥Ï~€}SݳF-(ébϺƒýÞ=‹®‘ÇBÜ4¼B2ûÏã"0lÍ…›¡Ìã?÷~ZƒóïÒØ¶»1ÄÞbŸ ±{3 ½rƒ’żûb‹BÌãkbÞ1R·#Àä"QÒÝÞ7·)·Ëa9HÕ«…4{•nN¬7äFΜ‹d߳ϻ¥]Ñl» —»¢‹m´\óf›½±ßwF¯²øNÞ6[ìÕöýËqƒå­}ï²ïŸ&gƒåº£ï»ý­}Ô¾ï´ï_±ïÙ÷Ç©a å¾ËÞ|¾?iߟ²ïOÇßr!¼xCNÖþƒÎÞÆËé‘c‚Ô–NÍý‹ÇYLàØX½bÈé ©Ø–Öù­©¦ØJÙAÅc;G&` up‡î%&'ÊOhÅHµbÈéJ8'QV9;Q›jÂFnj %ôÌ.Üs8¨ÇÙYVЉ(I¿"ÔÀU&Ò*ÁåG)qR¬váó˰°«õûÒû=ƒk=©(Ä(R9ý^¼Î Ì9B“£²¼9“>’Ç:“÷ͽFÎåêjôÈ}£›Oìrb?Ï78rÃÈ}wþ¥0¿â«È÷›|ŸíÜßt8ÌÐ÷üÁ7“õfG­s'7Þbãz–u¸{òð¥è ~"iǺð…n÷!ìŒÉ—Âö{a«½C5s[p¸3¼»>8 ¼=¼»c›û¿xïp'0WO·Ô}£s$“ág°¿jNàªë«êhoJ¬‚2ü —ð‡ ,­e`v tSª5|ge5 |Ï”ÒJZÃq,1#¿ðÄD½kB¬Ë’æ_< wÏmH5H•asìC`c*‘D0au{onôîÈ-—jîéäF£Ž¾Ië%ÍýÝåëv¯tcÝl¤3üŒ­whiÏyGv»÷¯tÃÓý»¿Û¿ÛØ©pãÂþ]êÜÛíïöïdòÜFì^Þ-!vóÈ}Ü.ÞÉÛÉÍ.¾žw«÷îÖÁ7ë߬X¸>ßíra²ÔÝIþ~fÛúèF{?nð}ëÀ›»¥›:@ÄÞ³È;·ù{ûÓßYÙåþžÇ޼6ìæö޽·+¼»ÉÞ±Ën ïÞkïØQþžÀ»ÏÚ;öÏ×ûoÚ;í–Ô’Þá@É`T;1Á†àZ-O¿ŸPFCP÷ÀÑk7Þ¿c¼Îï)´UC‚ØèµÿÝyî_}+8¯›0ȬïZ†ÝÕí¾Ž¹ñ÷n»þn‹úónÇ8¹‹§ülf]Ë™±ÆÓØ×lœ½'LعÙã¯É*0c_ó˜»u›Ø- ìº]×YG6ßw]÷ÞG\×튞³I¢`Ï †½ÌìÔÝ×1‹Þy œÆÎY¼'¸¯³<;‹¨íã˜FêZc_Ó[; (—ÍUrHokìkúøüïÝå`ã,AЃS$®±NÛÔhyHäÎûÐl“.—©·îªEJå¤Ô•Õ’×C­>º«Ô- ¯Ýu[es£&ï^wz8¦‘ÊW­¾Žü¦¶îšQ¥fi‚í®Ù¹01êôNeàJàŒEªaÔÜ]¿Uo·ÜçöÍÄP~÷ÎXÐLõX´R—,(È{—,Öy–uèƒ>5ÿ°Ö]Ç#}@ÕÞ׎V«¯=ô‡÷]Þº ¬¯So‘óÍÿt¬‚‚?5ˆ}ú?«àØAªzENÈ}8VÁEõH ºÇ*Æq‘Ò vôàX÷(VêŠÙ€cíVÃ93n¬ÒÝþeÎ…´­š1Š–Bc½NVÕYŸáwæzÞùܨë9xçspß®çàÏÁ^¨çpÎ{èhƒ›|=‡uöbst;È09‚ƒŒn·&Gp«g§žÃ:‚ù‘Ã0AÝÑï|sKèÎá\1™ðëµòÎ×ÑíŒÃÔœq€ê9xçk5ÎÛ»k寃Û^=ï|`âzÞùhÔsðÎ× Ï³žƒw?qØaœ®u9ì(Ê•*âöJ~ÞaÛ‡ø"ú«<ÏýÈ#pmPóÁ¨yŒ@!ŽÉ´#ÆcƒÇ9AH=FÈ{Dê1BÞ#rø|@ËzŒ8(xŒ88xŒ8Ä:G6wæ1o5_#@`ë1¯%^ÑŽÊè#ὄ>€T¼› fÀ»™ÀלmjÅ}ÛÄ{Œ@ëß{ŒðÞ#P¹÷Þ#¸U{ïôïÞc„÷A=Þ{¹à¡Š@‰³,†„Þ#ˆá²ïÄ@_x f]ü•› uÞú­0øºH=Fü™›Ü;ß8øð#P0aî™f™8:àMÐ9–xïê€y›yŒ¸×Õþ7}!¬Ç&É{Œ`:½÷XPl!¦ xy°#2ï42óa½Xøˆøóî`}Òç0?ºg´çô[`±¸×Óƒ” ¨6xz8ÚUh¶;ü:à=Âé:¿x„À­ E^.á(Ž[ ~˜ÜåX¿¸¨ùuÀ](Çúu0· ×n~fð2äý:È=Oêו5ï×a¹ÕÇÖZ6Éa“œéÕï£5 ŸèwÞð«ý>îê÷Ùðñþ÷ >ˆÿJ¿o. 5ß hìÕæÿ55' qïþvˆ' Ñ›bíÐém5¦ZœÓÇ ísÐ0.rÛ ¥;“µ­£P²å[2àÖÆBá©÷+þU­,T^·E`®o? …‚ûe‹Ï'‰À¿yZ(^n荒öÿ ,œD7Ú· r; 20éûÊ[¶¨Õõàba=eJæþ…˜Y ý)[4» ·ýN0§¼à19ŽÊË×jH^ø¤š@ÍWBžþ¯çãkáE –|h9{_âS& þ„OÁ—?åSçƧ¼|™OµñÏù<"*˜ñ¸2Kê“á/H¬Æ7—Ž9²‚õîÿä†(ˆaõæ„Ò1¸ÿ(?‘ÙdH϶3^NæsŸÝƒƒKÇSò!|>l÷@»\žÊ7eê¨B‰¾¼¼xë**ß²yý—_¸…üwÿËt@>¦°#´_çS{ôøÒ± þ¾ ì,¡6Qû?‰ 3‡0•`M”¿µå"qÄvPž˜xþ"Ç}8Ð)¾,‡Ù»¯€!—ä¡u³4´ÃhÏû›ôðãZIx»EÎÿÁ’ÌP<ò¸£$ITD#Ò¡·Š)"¥OµÀLp‚d¹!³ŠRúÔÃâùÑ¥Ï_Ñ+žßþÿ‰çw—`]Âö ç[qïL\½.œOéKMð†™ðÂp2¡” çCW}R8:¸ÎvН3W^Æ’æ­ø:õyá|Ú©O})ò^¤zßk¢ùtÙyªü½J¶Š«p¢ùåïýQ4ÿQñüþÏß=£×¦“Z‰õk;w H/ÔǤx1V„¼ ´Õu3KÖvË jòvÞÙxKm~^ úó!Àõ èCBöúêæÃúÌ“Ÿajô3LJdÉÿˆÐÑ’`ÙyÂö¯qó—Z qó—Í–Ÿ3fÎ oÓq?[×z{ôˆu¬²yAÜ£Séæ ˆdžæÂ²áE竼°dô¸ -*=p3$Á‘‚È"âW^ø¸Ø}*Ö.áT f·•€w ¹Û·ã¶¿Ýµýí›ï}kç¨×¾} ^ûözíÛZ½ Q&îÞw߆X†`ï´o#¤¬ïƒì!ñû]ì£Ñ¡öf‚}jß{Eàwæ Äe¿WØ÷Ùö}Ž}¯BÜ»âr¾%qÖ›5öm„dUËzdEç·GMÄ‹m´÷Û·¦–}_b½Úlñ-ö}©}_fß϶z˜­¾wÙ÷Mö}³}ßb}ºÜâ·Ú÷m]yi¾Å·Ö^È›™!¶ }3c}¼•0êÎGDö¿ÎÎέ½Tw6Ò3±W½h"?±>jâúv#"ä÷:1ohØ–óÂÖˆXÝbw…Ø—2±˜=ß+h[Ø=ˆâ[a!»ó=•–U7äk÷bßÖ>ÏXfŒÈ«Å_!ò.BpkË‘wŸÑWì'Š2ÜÚR17ä$]”ug|E’@DâVø›JrQw=aþ¼Ä‘$“¦ë¡– ŒH.QŒ;ržÎåëG®‚\ºÉuä:9ë™– QT¤DKv¹67JÏ0oAU•\",×re-xhG%—¨Ìµ\Y Òº…î/’s6cÒ!wt";5nž%‰“@`¹7´¶üâóõ7ÂÎm`äf¾Ç•"ForwÀÎÖ»©%îÄMà’PÓŽÚè93ñ¿ vY-oµÜjÙ0XË­ýµ<›Zf"ˆO-»L(±M¥ÝY¹ÄÚxÓJÎoûib÷»«›;ØŽ¼èp«u| wQz½ã‚hD}Ä?ÞÚÿžømª'ÏqHâ;­æËkÞÒŸøªðþÒþ÷Äç÷×¼¹?ñÑ›f¸SìòÁ›ERí·ÉšéÁ¿[ÄLàEü‘pñ"þì}oCÁJo$I%{¯ÝÞÝa1D ?“3Ž}}ª#öõ ÄþF»öNû>n ï.·wÚí±çÝÍöN{<öuóî.{§{¼Å»¯Ø;íç$7ÓïÄ ‹#€ØiNbM¸Í8 ÕfÇ#ˆD‹d Æ\ø Ù€C–‘Ip„ Æ\ŽJs’Σ— Kd[$y0æÂîÌA²u}{ÚšÀ´D}ªæúä§>Çrb*™ú$Î<æÂ„ý.I¾´£ØÑ6V^êëCãLÈr­®i«EöµM©9‰i&:²­¡倧«‚´^„11 ñ¤¬G'L[8jb"Ng ©‰ÿûúÈD:K‚ι@A[[²YätA¬î"Š»`u š‰Œn`u¬…ËÔÖÞÚ°ti²)[SÆæd#Tï7ȦXäY3yú±zXª%Zó² žËLIÐÙ¾q-B¹~ %UžÎ,’bH»­¹pÃB˜^¼Ì¸¶^.–ËÂë™ñé±%<ìªê:šÍ­4°[pT¢bNUœoÅ<ˇØ"5êú×SãŒ5"CFN§êÉivI5'B—p1D£Jûrní_<C:6²OÈÏ ¹vËE5z®ÒTá%-íQEU…åBꌛƒPZO{qgÉx7Ç‚µ.wàr]Ó<ìŠ4\÷¡Âé¥ÝOYOÌ݇?JL÷¡Æ‹g"ýxVwþÜh¾µÑ<…‹ŸuvÁÝ%l¼Ýï^[pùƒï<%Ü­ŒÑÇ¿Ž;¾Þ˜;¼Þœ#~‰»É[^ÀvãlsædìÝÞ÷·Çœ½=Øâë0§À-i·É‹³º &ðn·‰“=†04Wç¢þßLÿ¿Éª»ÜÎ…§ûŠ…§\±°ûŽÕš÷Tw½†®ªÅùSÈ•‹·ž+1‘zFð®À»–^Ã;hȩ̀ZVQËÔ8_ÈP£Þ¥}i¹·3Ã2Ÿï~ôâ67ÏbU*v9D§ˆ5ñæZn‚כϻ¯pÜFŒ»¥ÌxÄíĸî°ÜÛˆÍ#Ç9ÄÖñ½‚z?EìÞàû.ÞPïÄïq·ÆÑÑ­¼ÁüÇ×GP»Ô®Šö»[Üy¹þ=Ús0¤Ø¶jóåÛ]-º’åoîq7Ç`Fi2;£{Öu-ŽŠé×7»º£’³ó2·NåºÍåwÒý5ºÇõˆ¤ö†¹–zô¾ýœžDW”ˆëY×ãö³áë2|³“óºôn‘Ý{WÄ÷Ðx:±s "˜Ç5Îd ;Âìæxob%fN±¨›ÝÔN?0WTèåÄtÖØqÅÔŒ«½tÕÆ\¶gÛm–}UT]Êu£fý­ØÎ¼Ú³$Ÿáû´s­ìÜûpôÆšÀÐŰ›St05°WÍ®†£Ù¹«Û‘3í¾ƒÓ=ؤ³¯¯[d5¯6ló•!°áýÛܰÍÍÛXÑvãm:¶±œ í1‡Ho ÷HñÛþÛn|ó¹Ç°Œx…K6c™Ë6c™Ë6caÈ‚8ÊW8!Ô¨wi_ ©en›eŸµa’Ó{ç@q3Û³Ñe.7,cæ]XæòmX&q8¢†e’BÃ2[6c™”C¡¾~y–‘q“øJÃ2[6c¿«”+­kç}X&v=~ذÌÍOb™‹–1œ¹G±ÌE#|k3–¹©ËÜÌû» Ëì"vç`™Kv`™Kþ–¡3Ã2Ï%f§Œ‹à8.¼ŒR•¿b\J6UFÜë$6'°Èćåpp÷õ>nÅžËÂÙsø¸I{ž.wü ãæïM¬Áƒñü]8žïf‰½ƒ·±"ð`VÙ;87…wžÃàáÝöÎŧÂ;o€G<Š”£ºãJ{'ŽDì {ñn½çAœ˜´™ë²ïŒD¹{'NAìMûh³&žË¨MQð¦zô®àû-ÎBÁ÷˜wÞïnï|ÏÄu(ÜšéMá¶Œ Žbàô=§G¼…¢ï%ï6dŒuC/‹Þ(”n”ÅKÂ;oJŒØÝ!æM‰)V*Ìô£äg]÷ÞR˜é’×4ÐݸTr{N§z\òs¦ÛtÉÏ9®±wº{—<דw7Ú;]1K…w·Ù;¡ó²7I¦”ýîѽzSö½Ñm¼öMÙ÷F«ìû­9®x3Ez×à ™i^áŸEÞùùã7k¤;zƒßUêAÃåöN›¼q÷LýNÕM¼Ñ›Dâ7‰¤Ûw£7Æ;o´PH¨ÑÁâßOļé4bÞü±{2ýh¼Ýê@²ß÷XÛ;Ý´›¼éånò{N=nk¼.„ê;x]M§ƒK<¯ yVÃÇ$:rÉÚK+^îø>ë›±À²óÅýñ¼Mqž°PA?cÅË4@®[ÝsÛ€øÈÜÃÇDºFøè¬ë‡Oì:ï;…ÝyÑXÃz¹˜²æþ¨ðÌóÀ\›skŽ»¢Û2ø·/ݽݑÊ›ç€åos·âÙ»Ï[œ‘ÃÔáù|¤;úû±Êú±©·âŧýØùŒRYŒ©ÃøczÔ‹€ñ/µž\JO6[OÚÖ^u9}‘ëœÁ¾Ô\d¯¶Év橊¢lŒ(Kr„—¼t#ßÙîæ9˜ô{üåq‚½ãhRSSSäð»H<¹¸Ôö 2Äû$>KÍqû3~Ÿ b çIøçìö}²®a©ÍýN—0æÜPAúìö­º2Îl| iɰKÎÆÀ`´ð7šÝ¿Hï8ºèÇäFüân´40º´S»DxŸ}±uÝÅ]‹s:µC‚¹-jÓ~XÅ7û¡³F³­q•ÕxiÉ~ì†]ì[gÆý‘¹-¡ý)­5 ¨Ð>8ëÌš¿Xc[]ÜUøªž»Ê;ÏÓ‡¯*="3߈SwÎ÷ä`0KsšÎ,œW™_h€ÿ´kNã>v'ÉÊnv´/ÛAñ;¾KLEl]3¢¸ë¦RwU®†“£ÒxW¢aê9'çYníþ­yÅÌØýWòüÏ‰ŠŠj“¨ ³DÄH”®cÑU¯&>´ÅörÝp€„ߟ®|r—&#@›“­N¼Ï’ÚH8Aªý.'¢ßȤë†òôö6„©d êÖÙ„ƒ;HäfA³si1<}ëþ2†á<‹w \c˜Œ›¬éù\á iiØÝ"eâ“8Ò<)Æ!È;;î1¼9GoV¼£\Ú;z;B&­ÎZêÑ u>°vq+¼#bîî¿IõnÍu÷Ù;Fäº<#ú97 ªËõèPŒzÒuzÔi5_»ðFî¬Úmퟡ/ÊŸ²ð"ê×lcìKï[× E±5úEqr]Ú‹ººÁi÷¨vAžNn·ò¦\!aµêíì£âÝG{Oº‘`±š™­û"­tuÏYOîNJ¥ÄÛ9áU•Œ*/ÜßÕØ~?r»ÕÞ¡æo-ÜŸüÎåþäoÜŸ<þFj¾sŸÞö©5@ew Bõð[u£[Ûhܶî•{³ÚÛ±n’Û_ÛøÈι|óÎÙj;g2±[wΖ!vΧÙ9—²s6‡sƒíœ[Ø9[Ù9ËÂÎYd;§ab8Ú3F&Çã)¿é¡ý³ãÉý³]¿ÌHw¯ŸŸì툎ý“ato< ;çö°sÀ{·H,fjûaŸá¢kØ!Ü»ü&>Õø ‡j.¥1 \ø ‡šžÄÁ†›G“kB:¸Øò»F€­×ùýÃ{½óœŒIžïÂÌ£E¦»Ê¸UŸÉ7~G´67­í3Oõ¾ô‚h5\´ê†ìBê½T½aWuôæRëÍ%¡7[ˆ?;ô¾½¹-ôæÙ¼3|‹¹¿‰÷ ó±-'«Är´.ü »êKmNëG¸ePQEÙ´ ›¢{Op¿ñ;À=É0}ŠGÀ¦þV) ±×óëTºvg`È¡sgì ;£ §`û]Ýâ7i+ÊÀª) M­ýZØ‹ —.¹6äœ¹Ä èÌuÉ@.lEK¼‚ݹž•Îew6*t‡îÇÕhó˜];³Ûz5Qjï2½•Ú»Lg¥ö ëo=iÞíˆö.j[–Záf=økîÆ¨þþËúÙ×;½õ1sÞï¼®!ó•ßÄÅë°ï˜%ç7¼‡©N½¶÷Ã{Ì•ŸG l ×¦‹ïf§Lߢç^mï±óÁ:ñF6éSÐþf}¡iZbÓqâœl–A ós:•ä÷µb/Â-¦Ö\f{€ô˜¨s%¬zÈjÉë¡V¯¥iÌš(—.v»ë¦V£& ÖÑD‰é.Ìi¿c{£B]ØEáž®Y­5šú»û‚Mú¢]¾»/ÔïcÔéßa³ííüjedîá>`ì„>èÞ·»̽Q»7ƒç £>Ò‡ž¾P³×\IJ‰7d‡•oÈ»&ÞxfJ&X «%m“¡2íEÞŒ7p‡yoàk3Þ<²ôM˜û¿õyz¬o˜«ñ}ÀzïCè':“šEðï-vn|?1{Óf}c#czO:=ßé[>ï}ô :ÞôÞýÎôžÙ‘Ø`¾NšC#ÿ?æë$eêj¢(4kÄ?yxú(UÇ&âdÉÅX_êžyøÕ=jªn^´oï Þ꣧;ƒ}KÅúpféLÿ½Y:´cf7=ô¸ÛŽ3K‡¤ÝxËšO3xËôÖa XÌHÿiäÊ4„÷vPTîfrŽ\9äÀ伓ÿ˜zXŸ4‰÷ͽuZ¶F-[éc¼Šƒ‰ï?¬Jú/{”#¯º¿ÿh ÿ›Á¾áñm¦³ûÙ-ïÑþ›˜é]½ÿF·ù¡þƨë3:ÐX¶’¬ü¿KŒT5ˆÏõïÆc‰ÜÊþM3Ç}KŒed†z¤]Ù7€±ÄXF¨G¸øÿK´õ0À7ù}BÃwÞº½—o0.X[LÝ:Él#D³×ó1ÑìuwÁX¶:wÑM]83~&°`$¼ß µ ‡tÏßJ齿—Ñ{wGe#é!‡¦ßu‡o1s|?`@Ïå6ô0þ•êÓ÷æ´ø¯+'7Þœ+uåä¦Ð›Óâ‹®œàÿÞœàzNî½9­Y·®œÜzs1íîœÆâSON°D='7Þœ$ëÌÉNÀoBONwÝÓܦzsÚ»zWX&êÍiù]9±\Õ›Ó-Ý“oNø}õ~r_ëÍiù]9¹Ãõ洜ѮœÜëzsZ„]9¹ëõæ´ZÂ]9ÑGîÍiùÑ]9ÑNîÍéL¹îÎiîŒ=9ͳîeî€=;Êb¯®™ÆôZoV“¾+'~8zsZ³Î]91@Ö›Óú9@sóé6îgÞ9“€æ>VÏÁ;ŸƒP=‡“€æSÏa ­Ãpºs˜w>¼‰zÞùp.ê9xçsÀרçàëüœ=9xçë€'XÏÁ;ŸÞj=ï|8fõ¼ó9à×sðÎç€g^ÏÁ;Ÿý½zÞùhûÕsðÎç@3°žƒw>Z„õ¼ó9Ð7¬çàÏnb=ï|´ë9xçs ÷XÏÁ;Ÿ]ÉzÞùèVÖsXß6ú˜õ¼ó9ÐÛ¬çàφg=ï|´Aë9xçs ;ZÏÁ;ŸÃðìÎÁ;Ÿ›zÞùèßÔsðÎç@§žÃšµ9Ѐ­çàÏñ¤ÁOôjë9¬y×5†s»sðî{¦Dm´ê9¬‘V‹?Œ³î¼óu ;\ÏaM¼Úh×sXs°6ÊõÖt¬ÍnP=‡53ks 9TÏÁ;Ÿ½¢zÞùhÕsðÎç@'©žƒw>øõÎ`³É¦~=‡3mr Ñ_Ïa 8Ûhþ×sðÎçÀC@=ï|< Ôs8#Õ?4¬Šnz=ï|4×ë9¬1Y»‡ºÍ¨®Q0£úˆÑT[G·ñUS‡5¾jsô­`•Sv=ï~lnÔÜTºÍ6K¿+œÖSOøys£\ 17ÊõF¬’ò»b×5åKŸ™ó~>m2õ–Ïm0Z¾Ùòqýð5qé–É¿Š.R+øç¨ìï2l47ŠéA2œÑŸ!­WC ¬èÚ¨ÚdjTSÒ ·"p7ÈjŠIx4âl”5Vu¿QHWŒÈ&Y æ‰II0×7˜ËWB¿‡ÀO`>AÉ&á:3äËq'†|Ùõ?ë1kbS•º»ù ù•åãîºÙªëƒê*7"€Óìˆm2lß2S8Ln_d$s¸*Qï†ËŽ6ëpz‚ÊpM­® #t“bÓ¡õh„.:b ŽDg„KíHÌÆÔ7’ yL}#¹ª"Ä0Jlo1‹FÁ`Y ûa1æBºˆ#¦¾Ñ0Q'E##F‹õ¯šGcº0f¾ö§Ï4æ8¡cdöO=Säz¯ rãX?ÎŒ‡ªâNó¤cUŠ&w¬´/Ô¥6Y/д閡MÕ¦wšÜ6*7“´µº3N\Ý?€s7;kt÷ &?Æ—ÐAF9ì3Mmñq¦@;ÿ`8èRŒ:dL}ã[¹æM̆8„-Ñ?ŽÝ?Du¨ÎC¤é¡)“Z³™† 8§¢…˜Ô„>NàæÝÕ šiŠEùM|¾u›šÈ–a“Ld¢8“à¯1(“èiü“xƒW•Éô£À™Ì ïh2Û==Lùdâñ0ü±˜âÃÀSú<…-V`ÛŽ‘ÈÓ<oæe*ÓµMç6] îÜZ °jf¨.ݘg°Ù pBf2ÉE0ÃL ?éýLæÃÙ³¸mÁ-G0SEê;K˜®>‚ù+2GŠÜ(ŽÄ¤j‘:¤ÿEú|$7€"óÙÎpÙLíl¹"sÓNoŠÔÝþ‡ ÓÎÛuÏæø[bgÃe(Áљ͗¨O4~•èÿl¶X‰¾ÏÁKO‰~Ï¡7%æz7±9lÀ36—\%jœË]½Dæ1o%¶Ø<ê/c‚óæ¶LaÖÊì›c@eê:†ZÊìc¸Å•©ïxevÍ1ð4ʼRw™m9Ÿy(3» @evݶl™þC÷+³7p‡*Óÿô£Œ¿„c±Z&v,ÛºÌÜËý¤Lÿ”™»…ð†*ôk!Üó u,"_…~-bsVÈ¿k³ò/fgUÈ¿˜;issóÖÀÜÇl60»ÇI“N{ãxêi`'OØ?K„~„²–Àµh`†O¤§ ›aà6ðv)V.¨{)û¥ù=ù¾µ÷N^È·æ÷dvv3z2 ªÏ)ì»FfìT” ™ÑSAÔw*³ÝHm˘ÙFæeh¥‘Þ,ãv×H§Ñ“Fú|¨¢‘{ˆ­‘ù mžÃ®Y…©Ó¡sdÊV›ô¡6m¡sĈÓö>GW9uî) j[<]÷MÀÓe'Wx:Ý`ž¾4®ðéKÝ ýÁw¥§Ìný91WÞfhnøéšjõ÷éÌ –8Ÿ!cÈÂLÏxaÜïgi+ïJ¡}U»R|í¨U² #̰J\>íÕUša›UNßNߘãÔn:W·íÆsuÖÝü\Ýéµ›ÏÕ$hÇŸ§žhG§»²pÛj°W„ÕÔÍÍe s" §Q´vÒfŽ9^î• q”d¡‚U×ÒC°êÚúxÖbùÑõßn&‹¡6Ê´cß4Û6Ùl‰éíØDkuT•kÅÖФœ¯ …þŸ/æš”óu…W覠Ž\ õ MÊ:mMÊ:¹‘Ò¤¬“óMÊ:åÓ¤¬»A“²^ê|š”õĘ”õĘ”õbHhRž) Íš”gj#iR.$Τ\ÈUšIÙSŽIÙ€‰Ò˜>l 'r‘&D“q–fcúq‘н¶ãEgÄ“rÑCLŠ»Î\$MÊF]t´Á6JÞMÝÝ(Ý íÊ‹é|²‹µS„c.V§µ;/–Ž’:¿I3®JŸE·ñEv x†+Ì%Lv™/q¾Nô­3—€WØ ›©—«Ìf³³»¹Èíxú•õÒÛ^Íwüfpº¥!λ%8~É>â8R¶„ÕË‘qŽ‘1{Õæà^Mv%9î´è¹™)^9ऑÃ]µF¥¯8}%Ø"î°< þyÅ–‡a•Ö,£ R³<ÌFqYËÃ2 ›Z–µáÔò°¬ §–‡ –‡e!7·<Ì^—ʳ<|H°<Åd<'Ê™Šç&©mJ\ýÞH™—ÍÊÞisØê-S­Ä×í_/YÉ^ÜhWž³Å‹§³výŸh—>Þåà©òOñ»tôþŸ9íÕ¸ÁÖäOØ"(W¬#Á´(û3÷XÅü¡ãì ” 'Ä/Áõ‘Qö{î1°e}ü!S,âf>jüîÿš·îÀ<¶qýRš,óÇwÜëP±ø/8žÖë¯ð©(`|Zž¢‹|Êbu‰OY¬.ó)‹Õ>e±ºOY¬näS«þ­÷½Gla?j ¼¼ßŸì6èÚõ¸ç‚Ê̇dñq£ÝDçeÏúç8XȬõÏó©è/ð©1ºOÑ'9chŒ>ŧÆè×øÔ}šOѯó©1º›OÑoð©*~“OUñ[|ªŠÏð©*þ’3ˆªø Ÿªâ¯øTͧªø>UŽ|ªŠ¯ò©*¾Æ§ªø[>UÅ×ùTý8£¨Šf>UE>UÅ>UÅ@>UE ŸªbŸªb0ŸªbŸª¢•ÏÙêïxĉrëõF›ú9LÞEQþ7µìWOgºgö¾µ»G+y}s}ê¾Ñ÷–¼+ùnÁÈ^ñ9¥ãä±{  9?¶Õ…H‡ó¯(ÃÆ”ìOSîb·#QvŽßêl£¸€ :@æ°ûD¿{RH¬ 9BÓ3„Ï™QÁùM5ª"Ê:·£Y(W€D¬œB3­$ÑlÍ-=ÇíÅÉ|ÎŽ²>yÂ~tÁ :jZÁÆ·i³Ÿ·´º¡¦–Rð×Î5ãï–¬uy)¾©ôˆ±4áF>5å¿Pz„6Îm|ªÅïáSSþ¡„Ý‹MUðK|j ¼Ï#¶Û ?ïµ>À§¬Ã?h7üv¨!¿UzË«òÖ¾<9l,^JžYH«ù~ì«Á‘øG7Ždåš-¢²xëîyû&”90WÜ_ÿ»“ñò+6k—x@09ÊK= ,ýAüÿež¼øu6ƒ–Óïð9#Ê߃âÖ5wá¿KN­ªßãS«ê«êAG¹ß$VÖçøÔÅcâéd¦#H}o¸:^±UsWÐäH Ò>æÃÈ £º±O^øÚý8¡|˼\ùøo1wiØŸ`|¼öžs^ùÎÍ­òu[ì6÷M`á\¤’“Ø‹ò=Ó Ï kÒzh¤ó"ç.½Þ–½k¥”a•d=£iýƒ;JÁ³"rŽH")ÌŠv½gÈFTÞÝfÌÇîáã‡+Æ[0_äëÙ1U½1ˆäßꜨæµülšÿ´ùqúÌk@ôì­f|lzý7éŸÅõéÎäPôìÍ›Wt²=­ÙQ Ä§ób­XšâÀu­QÜ÷>cë©ÈÔ£|ÔätØ¢]7â çãVVL5¢Æšj.b÷lŽ—BAÚüÑð{.6£hY&#Þ¶ˆ+*6V ‰Fý°?[Gÿàe=†Õ–ˆw-®úMVûÔý`ôöðû±—uç‰a—õ{†Âð²~Ä9Û¼¬ÏÀCl¯—õÓÑ‘ïsÁ˺ÑdzZy]úx†mg]Þ}qèMôñÀñ³G‹>Ð}¾¼ç³¸Ÿ*qEѱ@›Éà¶9ÑCMâFp³Ï„åý¥íËû=ÿ¾¼OÇèC FôK[—÷…®=Ë{ä­C=Ñ7µ³ÈÅÆ ŠwT¶²íð´ÿ°Â³yÁâ(BñŽZ=ŸƒÕ°hÅör/uH"Á½_s0•F{&5ö‹ìy$xáòÈéìàM›'­—%Lß% ‘å9uA•Kãr µ ‚öUñqÅVÂÌ se{C“êYÝ=¡ØrAa'—Ä:Šw”c~Õµ¸ÍõüâŽöè–§ÿÚ í@½th'ï¸ßhC0Úd 4(.“:ÅÁ7)ª¾ÙÑkn,{ƒÚUgîÌHµ{Ók|§Ç°ÃmÑø"xI7H+«'´p§j=mÜØóމNíSÀ_«z¶H`oØŽàÍ7óΛofx³¼óf™}o>wçØ;f}]x·ÉÞ1ßÞàï¼I>fÙ›äãÝõf¨‡+e§¡ˆo“Í̵ßÈp`èE‚åS¦âkÖïñ‡×v:÷vb6v4y£CHvPžøÊ§ôšiç^šÀ”+oR(7;eÞŒîÆìõ5ÑÞ]/?ÀíƒG¬ÀHÖ…êОQk³`úèf¡oº‚^{SqÜÈ:ç„Ý\ÐW?\ÙfÄr•Ã4Ÿˆ—¸‰%I¼ÃˆÔ¶bY²9ÑXÓ^»L(aM͹ 1ú¹-5xãå9%ú¥ÕÁ‘ Ù" æšHTÁ5kk‚bv.|ŸÝÐØèÉœ—$ë¦$Û_™£¯±Ü˜8#é•Ãæ›™\ʳ—)†séü©ÕMÑ]Nn6˜Ž–àHÖ7k藿Ʊo˜i ÷°«Âý|_äŒA!ÁÊa÷ïýûE»š¡©ol±¯%ƒ—2ß±B&/3F<œñðÛ‰‰ÉDgT‰Ù½bU”;å’ý0ä¦Âo ½»yðÝ g¼û˹ctךA¯ñáñ¸ú¥:Fm¯¯õ¿ã‰¶Qäfíàv‘7oÈnóf'Ù-Þì$ïî¶wìÏÙ;ðþ=öN»!žÉ'ƒ_v/"äÜiÊjkÀ ÚénàÊ-)£XXögŸe š\iˆF92 `ê:}ž¯¬­csŒÐGóô^l±b]îÌw¥˜òQÌ09ëz`!ø÷»`ŒîÙù@JÙÏçðNÜ`ÍJØù°÷Û?²ës§h¾ó`½éÄ«bÈÐåÖ†œ7¡eÙÔ•3íM]QÙµ]Ñî•U‹a׬ÑÛê»riQ×{ˆ—ˆ¯šYÙ•çßN¨¬ŠãelëzþߓөÙ`dܰÕÇ:ær[49Ì„äœ:Ä÷§#í1³!MĉzÜÞ} »óžwOÙ{}έUß+˜RuÓ÷§ì½8Ú©ê¦ÏOA¿dMWNvaW4º°+/[=jµ~}¬£_K­_®MjØ?OsÚ/Îö’æIØ—k{w µ;̲(ôqôd™m\ý–·¬…´ßº‹ú£½35~wÞå1Þ¶vŸÏ|ëêår=†i/FCüZÝš”ªÅñ€ÝM|­±ÝÄêÜMÖ8„ÝM†²à°!w%îkºu¶¼§²¢ª5oœzÄä$BÕòž­XS}u3õÜxG'È=µ¼G3õÁs{>jsµiâaUl%„!ã5‡õšz»!+š\²K4žœí>›ðeŒÐýM´Ï¤/Gc'}0:|Ò뢒I©è9“æF‰IÏ‹Š'íM˜øãhâÄ/G#'~0:lâë¢#&¦¢çNœM|^ô¼‰»D“¡WÕZ­.&Ü${}”ŒTÞ*ºA]%*ª^ÏFÜè6Ú œïÄÂÊN,©Ü€Üæ ÈJÞ€ô LÜ lüƹ)œ°4°“ëÇŽz(âý |Ï4qÿOçÿfþ_Ïÿ÷ðÿwøÿ÷ÑA“vçÿlþ?•ÿÏãÿüÿ ÿ?Ïÿû£ƒ&|‰ÿ?ƒÙXõJ5_Ë÷fD;©PÖÝ3R3³s—è öÊ ì•Ú+ïc檻Å\v$ÍîHŠa­äðØÞÜ—PoBÌïM²üm éoKEéÄŠ73*~ßh/¤{WÆ]¦€¬âÏbÃ\]:£ÊDŒï'L¬Í£¿–ÍÖÙ_Û/ÚãûK?´ãú ‰#Ú;Ì÷NGáñüéfüÂîŒ,qjÜ9âÁÖsmŽZÏݽÉ÷œ>+f¼PcƒõƒxÞU®!¿¸× ÒPÏ4 '­õ~~0ƒ8»æµõÀ­f5ùѹ±¹¨˜ÈlíÚo÷R e¶ñ½ ãC­«zî¬t†@]ý7Fª¯¼éÎÊ®œ8Gxb2§‰Á[þ`*OØð¨€m8O­oAçG <Ç9ÞT&_þ6ʨËl¥™M 6t⟯CyÖŒÅ8X:À2‚ZC/ówo]ÏãsK*异bLÂ@«uCñsøbp"ûÂôC/{Àˆª6Å\¤Åæ"Uç +Ú;¨6kíšì.Ͻê®_w߯l¢ 2Žà~¶Ÿ'.`Ɖot¦–Uƒbˈ­"ñ=‚º>G¬Ä»;‰ßMüFò>½¹ƒØH‡#dX•^´#ÆìMRêÿ®Á7×’s´aãm¡–-ƒ¹V…\+B®%>×YŸ&lF®™áý„ÁZZÞ\yãm•|ßæ`‹H¦÷-¼½ƒX™Ø{»òn+eÞv×¥›^[×¾QåZ¾]=;Ó9ÞÚÓãs\¹þ¶J÷.7ôªï5uù~v×Õž®K·€y™<=µ5(/F¥æŸz÷ŸÍ¹&2ivÕ;öŒÚ`Ü”Ý×n…Þœ!ûÑ߉y3®ŠÅÞ .1Ÿ›˜7ËKlCˆy3Áļq^Y~ˆ½‰a½K¼1bbÞ–r$ÓmŸcm¢cŸ'—ã¯ÚÅé>ǜѬXsô¹ à+ˆ -OoWzÑï¹eœ‹ï· õÞ÷›S¢çL^kµ@FE`Zrš£Ïu¼¤9qÙÑo•àj¿¾’õÎWœfÌžÓ§ù^`<„;¿Ä7GŸë°ÅÉgÀø«+-7ÆFÓÅ*Å›g{?ÿë›h”!|̰ˆfS%píèsïÇ„N¬r1„éj¤ò5‡A> ùß®Ù×ï×BIgÄ»—vgË ‚ÕÓcœQfW0&YK^‡U¢ëˆµXìl!w]í¤šõ6ÝûºÓ·^0æÁ…?áöŒÐÝÝÅŒ nb|ß@]z³-Ô°Š˜Ç4+zñªÞ¡šNmSU§¯I1ëk÷ùœÁPþ÷õÒ‡<ÖÙÍ@ùœþžc„œØºž÷ô¹Ù÷DõGg_ÁÛZÿL_•ó÷NX"Ç ›6÷zÑokÍû?y°ÿö¼tQ¦ç¤®çÔª˜Á~êÿµû¯[D;â¿i¿Ý,ïÚ7Ú‰œ±3‰Þ±—òž¦7 ß§|6ìÛ|6\m£™ÔlO,í—Î~¸™ í“nŠ²Î¼›e5›œ¯¿ÛÕôè|×dæ#Ù9ÌÇh?nVÆØ MÍô(>(=7š‹y¹3bÏÄÅgQÜÝòŠh?zC=ûû™¶»î›§ŒEœ³cÈ´jºWÇ[ž+·î¤'gô mVåÅ[ƒ+:vɽUÚBïÃ,wî¹ÞYcó|g˜ç›¶Ü©zæb´ëwáÎSzç^ùZâ9øÖÀn43Aíù;ÌÌÏß\Ÿ1þïó}gO$Â-~²öí:¥¬™ç>°Ô£³G?™»kBkúgÍïüù›1Ö’y÷½É÷ô1W<"`®¯ì˜ÇÒžýýË|løóLÌ{d&‹O:xk&ït£¤j·£ÚÉÈß‹¸­xÓÁÜŽü­†Û‘7±ïÉ›1×M6å–‰#{£âÊ{â¼óÆÒUGz"÷·29t Js'Þø¹î3ÉU™Ü‰¿Y‘ï+™w…ÜLMÏÉUŽÂâLM©ÁvÝld’=Í]lÉä+zî1oŒ¾ª¯è{¦XÉßµ”¯t]¦ÖÒí™ÜeoŠUùÊÞ µò•ý )Vñ3¤Üß?宸>)weMÈçͤë†T¹3äû–ÝÓ0ÖÔqOk¨ ÷q¬ùF¸CIþÈÆËAV:ç$µ+QÙ|$Dò¿²;‚ÐÚbMì•#?ø[nxÕÀ¶3aè߸xÜO|üûÜî-ѶÏÔ²Ý| ;#ô×ó·á´xŽ07Eß$æ9ÄdÔÌ’Ø<ƒ]#éŒP™9BP{B,©ß~¢ç8iI]W§Z[‘õS¤­¡Gv¹‘熣 ñýöáhµÍãõXúÛ[S‰…©Ö:žX™P(»>/fð°>!‰þö•³­¾5ÕÄ Óæ}¶òzyQs^t×Ò)Ñ/fŸ`5`¢ƒù—¨­vÛÁƒH¦ù·¹ ü`gBü¯ö3·W H Ö^^!Ž]Ú³ŒõTcwQ5‡XÛõá˜`4õ`®³Ì´ŸxÿìdÏuN2f¸±‘Ô?¦ýÄßò2¶#玡óïä&:l·‡—ŸîîcïvÇõ¡\çøwa¿^•áuˆ³0ÄcBÏVl<±Q†/ë=°÷åÞ±*Ú™w_÷¦6ÐQU‹¿zêˆ믹£†GmkŸI®‡kµ¹Lܹþ“Iù¯D…±0m”õ{ŸÝâµàõxcšìé'¾c/ 8ÁfÇzI¾5ö޽yyÈ·ÍÞ±#k¼í,‡ÇŽŠÉô|óØŽØ-†=0«Óɉh œˆ`î[[l˜ÿ¡‡±‡‘: 8BÓiÌËùsÔqVœÊåÁÎ †ÕeÓaþ‡æ•—M¯žZ6í˜ &àò Ÿƒ…1¢²~,íhKÌŸ&ly2: &'ÆbàuˆÕ–å\ÖšZÚZ#DSÍ:91o¡û<Ù};mºJùÇÑ—X-˜8€×*4:ÿC[q¼V›`7!õõ¬D}C²QÔ”ÂQETn|\nL%LŒ FÌÿ—¶ŠXÿÛb(Ç(YÛêZeb4+ζüØT88¶#1ÿC®´\#í}hº—k6Hήź¶ æHXèÃe=·¦ñva;ܲ/û” ûˆùYÃ…‹JOÍž~ö^Ñš·;^­©êúþU§ôœRurÁÝUÉo\áê¸:ºt —îèÑ$4Ϻ>ʪî»arn˜soà®ÚVDߎïÓÊ›ÞÎÌ»?Ó»ÜÑ fRl ±Uùwó= *o—É|÷¯Ê=ä¯ùŽ«r¦è†ÞRou<ømüßóáu ãvÆnÜÚX<ÛÉû‰s 7Ø;öNFû§_.ĺыèè£é»û)çµþýYoźTAÎú|l=¿áôUAq‹ñ0ÿ‡\²*Ú‰ïýx;úm/ÛxC ¬P½ø¶oûå´2æ;^Û(ÕÉØD ŒuÄmìÅg£ø?’7+ߣ]áßÏ|o°—{ß:ð^†Úé“نϖÝ÷M.÷Æß1#qà„]׸قSô?M×´bÏxfrŽÇHÓôAf;›—›>ˆf5*9Å¢®è:/!fð¦òëíªÁ·Ì| ÿ÷SnÓcå2y„EÏ*EOA»¢;×îþ³s´‡*ðhwÊÌïŠhøÄ®Ú¨ñù‹â6d7b·Ë:ïºÌe~^ÞÍ ±©!ÆMÜÇF„ÜfŸñ.`ã°ã«xؘ–)܆q`«aÙADÈaSpâ„€M'Û;🿿‚S½fxÏßGyçï—hƒÜb9Ôý”'~õCåˆgYa»”?HŽ ¾yì寮ûœ½~‹ý]“wßÊàøÄóÖõ.ñ·já·$`úÄ÷€;±¯›˜¯[˜-9#Ôqƒ½+„: þ6 »!P….Ó'Ó;ÍfŠÐá|c¦­@}˜h+ ÉP“Û¸3/jM*f1i”¥1i—¥1iš¥1£Nc2LÆd¤:¶»:iwƒâÞòŒâî¶~‹=1k2)6¾²l×~ntõl`–I›HëÇ—U•§'±‚Qv1n•ù1€6)t7Ê62d«Ê< †åp»[¶ëýÆvñÚu9X¹ÿyŒÉš4—úÛÜÜÄÆwü£faaÚuÆU2qñ³ 7Ñà’_|,ƒá„ÅÐ4òœ‹!Dz‡Sîq, #ÏÁ¾Øg3ÜÈDdq#ãëK»³n ­0 µ)ÃçŽêˆy^å XÜt'ï<§Ž´ç6Nà6Vã¬Ø|×;~‰íøkëæúÖ„gÇ}‰+3}‰§‡\íñÜ8.\Žýò¸múžæuFwerD·Yë`®¸ú\ô¿^Ï-!Ç.?#äx ÏQ—ÍÜÒP·WÏÍé™§hzfžÄÍj¶º6Öæ1q^›Åezÿ#îMr \¿@; št,Î`{ž øÌëgÏú[£Õ‚˸59$¾Í0Öm:0@axà8C¢f‡cü )ê³ÿéa `®hÒxŠ<'+9RIùìêÓnÊyÈ]wôh8‡«ñ]µÙ…kj£}vèæ,Át³/¼÷ÞK=6dv<ÂüÎ>'gÕÌÖyàƒ ·=åcÍ‚Dn0ã£ÚZèßS>ö?faôC³02ž…îEâg>Ögû@ûfÁpµ½Ä|ž·°Wžzê_z)#äóêåø"lìŒ9<E¡Jò•½3ÞÛW¬íÓø³em_QnÂláÞú´<€Cil4k –Ñ­ÏÄuUvqyó®;ZÓÙ-]ûÞ©{^C qñ웂»ñ5 ½uåät>©©²3:À͇‘÷ìËlè±×B$æ¹{ļ"v–:çä΀ ¬!\k(3L½ŒmcÀØëu91ÙÔ›ÓÎ`WN¬:õæ´û¨+§&poN»Ï»rjæ÷æ´x¨+'æ£zsº;ÎîœX˜zÂ(u5'F¨zsZŽYWNìTõæ´ü¾®œ˜²êÍi56ºrbíê ÓÓÕœÄêÍi ´våÄfVoN«µÔ•³Z½9­&UWN,oõæ4_Ý91ÎÕ›]¼zN¬ôæ4›¹;'&¾zsZ½Á®œXëÍiÜ tçÄPXoN«ûØ•ûÞœVCµ+'æÆzsZ=ÚóGÆŸ4lÜw€Ñâ' ÷]b6˜û=ï|¸õ¼ó9àÔsðÎ瀯WÏa¢Ûpëê9xçsÀË«çàϧ¯žÃš+ïkÀhñ“‰ûJ0?lsÀñ¯ç°¦×m¸ÿõ¼ó9ú06Œvq=ï|ø›õV¯Íæ@·žƒw>šºõ¼ó9Ðø«ç°Ú6ÜõÖx¿Í~w=ï|c¶ ;‡5ßnsê9¬‰|›ÍñzkNßæ@¨°žÃšÞ·9ž0‡l “w™_[ÊØ Üû+ÉÜœ®×%”¬ [`¿ ~%]ld|°$#ƒš²²:« Q–aBm¥²¯Ø°å—™9äç9OèÙÿuÚÀ*Ö’­™äTÕ±,ô¥Î•e(NGɲì("‡]|b*f°rP\—œÔê¢õØß(»hjŽ´"Ó£êcE¨WÆ +2Fˆyd Dªo R'”CƒÞ‰ÓÈ­ e“xZºÚ4Ɉ›Ô½›dãUjÛM Ò˜>õC  ýЦ£ý.x´ÏÍb®*_óQi“Í6“£È¶3¬ÍºÀ¨Þf]‰Toó-ÿ'^¢]ÕXK¯i5ýµóTMYñÐ-¹¿¦L“=ÀŒbØÇŒ¨Õa~´Q•y€Ô3¥Ž9PF,µI¾8Î<ðÅ[2NSæfèu n‹š¾ºÓh£´hÇÊ×C‹ÎÒÚP-çǵœß?Q]6¿Ýý´ƒ[dòP7Ù™ÐÆ¤|ÚHƒdQAµÂê#†\‡p Ànê÷ÇuYß_'-PvÏóE‡ÈÆ£&pˆ (ªC~bùe ³š?õV©ö+ƒ!‚û7\l4­šNíÕVíí¥V±@¤Ú=TÛ[ûu¨™²*D­=5T×U-ò¡kúñþùÇü_6l rwXº*£êáPÌPÕÃ0”ÌV†a¦y˜†˜Å1òN ZLj7 cd.T30̈Û±²Œ­ZÇJc^½Kм0g Ub,Ú©Ì`›fV; M3¥ÐÆ=[¶mpŽ˜Á6ö+&«ÇÉ)Œú3Ž~Å2o-ëšmÇÄôg{9fWÀüÇ수)LVÀ[fózÇlÀM”|u1›²1ér ÆzöìÒR¤ÿ ý:{(TŽA†Ììxæ ¡_ã'ò­1žö¾ÇsgJè×xðFBŸÆ£Ó›Ð§ƒ0™PûAܽúr¸ÓÖÑL[¬÷Úƒ¸ ôã`êÀ´õÁp, ôã`òØÓ;ÌZ¾€Kz3Q îCè/zÀ‡Èœµ6öæžéæ©@-˜x¦˜ó:ä)>ptرIëC¥a¤½r(3,Õ¡ì3L[Od~Šì‡‰Ò5RÝAâ²A=‡9,2û“`…`æzwþ"½˜Ä±ÈmkLL]Ob'bæzsS„35›˜¸ž —ד¹¹aâz2,ð"½ÌVÌaÌ#&®c—èÿa2i­}u»³ÄÆ^äJ0…Á¼õ™ºVýSØË%ê??%æîpr–À‡³OK¼=œù*1‡ƒøKà…ÙÉóp8³X¢‡³»Kà”©Ì@™­;ìPf—L•“æc*ƒ2o§â™¤ÌSzPÐûu9¨°+f⹤¾˜Å}®"ÞÂZöÄ,ö+f±g¡ý^a^g±* Â#˜õ }9‚›M…}u³S¡G`³¶Âœ‰¬±‰Å#Ìcùb¾5'G¾7Æ,G¾w)Ö.%JI­)ħ®¶Ë™‰¶o»®Sêf»Ð†:Ò.­šäv³µÜŽÔÝ÷€@Šn—Ú•&°]S[­]h]SÛ®KÄN©ê›-c®ªOºñÏaZ¹XÌÒäÌÑ%^[e.Ý ÍÕµ\Û mgØ)s…§ÕÓyBWš’y2Ùª)™Çô`áx[‘;Î<¶hè(ì‚L‚í*:JÔ£„Ž4µG3C ¡£¥–¦ t´¡¡£Ù  c0‡2=¦Èt¾ò©ÖùÔˆÑöùÌuþºx^æ_Ü?• IiÛï™Ê;bPœ[Ç|:Ê b âjŠè–§®-ÐÔ¨Òº«k ĹÑô«é†>VÓ¡é9V7íæ…šY½Y¨ë˜&f¡xEêÖB½W·!_”,W‡ ÇkZ«›ª{1˜,¦öÅ2E­z³5°ö|1 ¹‡ï%<9\0àñpb°éñšMã “&ôz u¢µ„‰ó-a:Áå'°Ó0¿{¬wœHðø ð‚Àz'0 Óx;UZËÑó•O[áDú°NâŽ0+'qŸ(°É–bâ^ûRîÞê;‹«ê;™{îdnËê9,v;YšS ÷ŠúdÜΆ'ƒëónR°EÎŒìtSÀžfRù-²|T/ˆnÃgÔíÙÌ«®Æ ¹3Õnð01kìÊþËЖ°3,á-a ·?n »fڛʯY®Ù]†{Íî¯YÂfG×,a³}k–°ký€“^3/ cªö~|ÍÊ5¿ZõpõkV¥aü×ê@7$P³„]›4 à¦Ô,a×ìC£§P³Í%±fm‡Ú4<` »ÖWÔ*jÖ©AüدY®™Ö† S3 R¯åɧ³ØÇƒ‘¶âá¥cPš“±ÒÅXö´–{©\g$·8ƒO™=žÏ™8iþïn¹±zêŒßÆOgï+Ïpó`[1QÁ¢ôæ˜3±oïÛSùhCmÂÝq)Ï=—Hd© uTðQÌ…šHñ%±>õJ{xzëŠxž£,©5“ÍÉYͨ‰Û*âo¹ï•²Üå4­£¬wÇo¦öoÊ—õ¦Åɽ>࢜ªöÖ†¥K“­®Y…Óâ±Ë ø›Ð[5ÄVå_IÑrÚå¿—J T>¿HŸDWÇO³ þR½Îm”wdܪݢ~N}C«|Ξ‹ÝÝž.‰:´¥ð°_&*JÆGÅE9+L Ü(ï mIv¤Fù<üŠlŽ öÒ‚_Íj)ÎGÈ­õxœ|l›‰³(çCEnåõ`†)§÷‚\\ƒÇa•õb>å`×Ú:vƇ˓ÿ»Ó®Ç¼ Ï ƒF¥Yÿ?ƒCåɱ¥q0ç-f>?^:G¿Ñ¿>äç¦tà}¶ŠWQvãrà¿LÓZÛÃÎÛpñ8>µ"ÏâS€‹¹ L²>·Í/A±…*æ·JÇË,ðgøT1¿Í§Šù>UÌïò©b>˧® Kî`Ï 5ËÂòZg”1švŸÉ§î gñ©úÎæSõ=…OÕ÷T>UßÓøT}çð©ú6—1ƒÁ³·èÚÛI èòÀ£¬Ù³£ìsçAöø™ùӢܞªæ¹¥%Å;O9nئÀX<’jÄÙ¥%œFd2ºWoPk×Õä|‰S…ÅøŠÕ¤P7oý½Æ]ñ¤ÒÆ#ùÂÊoQÞz4=Ê{¾µ±^¢oÝî—ÃâÙ¥%ŒEü‡ qæpOø]ƒ"N=®¼~Ë´D»m¸rÓæ±.}¯®ÿæm›‹#C×v¬œðÛ½Z<ûÿ,ôâ-÷â„äýƒ¨$yî Šïþw„Uøéÿ 'ÿ°ð…ÿæ®î×þ+|.½ì¿úøƒÛ® ¥ëÿûa³o¢Î‰lòTYò7"_T›¢3öo’£zxW¿eÔ0*ºý‹õ‘M„èއ« µ÷«»|?§q=­oÕ¢ÿ>›®@ï¸äÑæØYÅöƒ(Cÿ¶)\UÞ*p3TfѤ»“î*5þÛÞª™n†=1 f³\¢â:ý‡Í¾š¹à¼ŠìâŠíØ÷®Øÿ鑯fEx Óßâ´ê¢§¤‰8cÿœ¸Â¼IáèÂCD³H="¾×¢\ÕvðøCÄÔ“42ï1ÿV5<b«˜*™½äÖ{šËë­·Â~* YUÙEû”èŠõ.„‡Bí„oÀ§bÇÅiCFÃÒúÕrÚÜ{³°Ù "ûSà?5G»o½†¸ü¢1™üOE#ùiâôéIýÎ"òÝwÏ/¶*Q\MUOCóå§‹=sðÎ#ÆÖw®?®¤aÁïl(kgBÄCaXj4T§Q‘T*R²•6üß¿¾°¬ñš¹B:–¹vØS±…ã峑 @BdÈaO´t«ä±±¡–[ÿÁâRf¨ÃŽ©d´ô[À’üÿ!Ñ×/ÿoçÿmÊS—Íî¶tMô ;ÿ[×Z¬’ÈÎ,ÛzùpD½- ä1&”·9ÕEúî%ø‘"óv ¬-Ak)±ì ^QY'ó7"ñR%¼Ã‘š)&Sùg1éKÙv01¤2µŒ47rÅv™3/ÍÍÜy»‰¼ðv™\òh7Ÿ|¿%#'Q¾d,–£ô=Ú¾±·:ÚKç3™Æ¯¼©`Rï-zr|ߢ‘ÇÌKºÇÌz¤·jAÌ[eBôcÕ6ë‘ÑEÁ‚‘Ù\n_‡cºôp@ŽúY\™}!ÊÀ¾ŒÈÇÃÕŠ92Ôr‰3c¯.‚„Ô!A “Gü©sc)eû^ÌX&)ØÕqzùüò*W0Ëx4r¹°IÍ¢ ÇŸý¹M.“åÛ4‘˃(#ÖE"^½1Ëɯ÷öp‘ܦá4W;nà7ËkQµ‡ˆY Œ ÇëÛàG‰öui[²VÞc|„Ädr˜ZW6Ô¹Á>#z‘’Óu†I}üÁ~ 2~¾öît²ÅœÚÛC&Œ0¼Z;ìC7÷\oûk—ìmÒoǯÍv®bWƒ-ÀíÌ¿±%ùt/ñ˺±´¯Ç ŠWÏÛÛß»ýíÂíoϽ÷­D>öö¾} öí½°oè…}[ë…6c·˜[ÀV·ÊæÊ¶ZÜlö^}†³frl]|wˤUY…k_†/.Ñóçbe+GþýÜOE톞?¬fì3Tÿ6¤}Tÿš¬ÕÍ]^ÅÌúœ;e› ³`‰`g©ó}^³µTŸÐMO¶!v4—«Ä•¥w·tÕ~+8I'6_ž#Œ³ý¨èúS{¢›zsËÆgºß]×µnk»rwß­ëlÉ¿rm×éÄ×fj´³-S«œyîyÝÑ.%§O-íÊÙÿZ,À.©{CW÷^o*µaoƒ>lÍK ïÚsá]»z8©ƒ>4ÿZß«Þ>mßï?ú¤íïúdìI>Þ'É ù9Ól~wÖæVGW­UsÜ7§'Z¿öÍìíš¹ÔqÝ·£køÿ©tïP¿ÖÛãuôa`IíÔÒµ«¢ëÈõßÅï!þ9þ™ÿ_:óÛYÃø_ì­7ôS»ê^ò|…üãKj.[»*Kõ‹\ÍämáóÆ~ºø6·}#XÓöïDݯ÷KÓ{kÑ®Ï-O`Ul8x•pðûÁ-U ÌÕ%ʽ lïÞ]7 dN[‚ý¶ÖŒõ5Ý l \ë­Î ÷,h{;cH…û»‚xÞ® 1o#˜·Eì¦ó6¥%÷6’‰y6ŠÉ:róö"ˆy›7ˆ_y»5²­{‹Û²Q{9ºÆÝ“”z¼.c³*ö—…¿SËpp}ÆÞiúâ[B}ÞJœ›dÇæÞN¼8åH­g"ÈåûGÌÏvÂ|?xçmáó½WŽ‚·Í£w?gÚxo ©NßcÕ]ðVyÈçë“ Xá,‹is-7òšÞ–r§Û;aø¢ïïü< ·½-VÞùºUk±+cß®è{IŽöiNoÍŽw7Ù¹þNÛ8_–¢LÕ2œÅëÈÿã†FBd,¾×â,Ö¼ ï"[xÆ–¨Í¯¼rVdÄ xU¯µïÛ|ímÇ +æ RVç2îÚ®¿H6[œë¼#©iíÔr=Y9P”9 ò4î¹MÙò²fʰ¸‘H‚åÀ§Ökç¢ÕŽw½ê#ÇkÞ~€ã…³ïêÅ»ÛnÄÁºåäo²{ý>üá誰¯3 ¬=VÝÙæÔ-YäQEñÚ4«°º²ëXlëñ¢‘¹Õ§Ô^=ÖH¼m)èk{jJe]9ÅŒ²*•åóveù»3ƒu»Ìrx³Ôáñ¦b±ÇÚƒ±·rÏ;oŽ˜·¨Ho÷͈Af˜QV¥R̘Ú^«z ‚äóöã„“ºÃÛÃL¼=|ÞyK@äöXqÉ]!ÇM ˜ø9àÝ{ #Á#è´ d”¾Frö1 æAy3‰LM¹#ãñ"ù|H…"Ó%¥Ë·>g2–áô´\<¶sd±™£îðya·Å$Tõp^Ÿ.Œ³aèò]ÚÜÖÑ¢<œÈ{r[L&F[ '‘¤öä¬j²æ‚Ú FëØ|OØÂÔUG™·íìÝvØé¾äæZH[YÑ›Ç瘼O4Íl&¶€m—ÃNVѾBì\ÞaíííÀÛXQë,NùwƺNþLÀ;ca'w«½+ô¿»üy«³é'Üè¬4{ª²Yu´°¤ÇyÕšœ%+Ý ©¿oƒMjuO¾]5kë…½:±ÙtKU4lrW´WgWÎϰ›[›£`7è_-Þí«5ì9œÑàˆŽÕÛš±ë¼-Kð¿}±ý.g¿ùýÅ¿¿±–ãï6ì2«ALÚ[z‚šèífóX„˜¿q)û»†äÈS›eÝ®²ú´ûboaS=ˆÏ¶½Ž=†NûÞß Vݳ?¡Á²o%ú6eÁ†½n=èuÜ>_E€Rœk—O;Öf’˾®µîó"„ÊÍDÂq.oWÒ¶#ùœ®›‰Í‰\ê”XZÎåìØí–0àNÛñ’f+Ê¢™D§,pw—7÷|ÍöúÎI ²9 É9FÍ FÜ…}w˜+¹\¹xáÁñ»ï0’Ã3wÝ£ºî0wp‡ù½ôfìš ÏîÇ ê”ç#tc†jž3ƒ±É{Ü0:à†Ñiܰ‹˜Ç ×{ÜÐŽvŽaü»¸ÿÝV:Þ­ñ¸¡ãÝRõfÅúž»Å7IsëÚ¶b½YÜuöÀ\¾½}ÍñE†q„=œ]Ý6î3+ôÖñX°î•ÖÔñv|/†àþueΞ«‡ûWíŽãï_ïýËýkÏík,·/IÛmiÎe_™ÐMéÿãöõ«ÿ¿Û—î„æö¥>˜Û×Hn_£¾²áöåzUï“î^Ÿ;­úÏ}ÊðÖû˜¸}ý€R»}]Ýän_ÂUÜ KWšB²qe‰î{ç áö׃{˜·î^Ë9ÂÙ=lå£Ý°©¿M½?ð˜ç€€MýKS“Z¼%æyÄüŽ˜¿½ISv6mM"ÈëŽ=ßÌêñ.|Ï7!æ9ܱühâϹà^å9¹Ø±ðÜx9÷$9!Ôá¹ļ]6xÞz ïò;_jõO9Rîï<ŸÞ‡·` ïÃ[ÔUÝ?7äó–suÃ+xOޝ‡ÇôzW \•¢çiëýÜ“Ã[õ‡Ç‘ÏDq²a}Ô6:y×J}Àa}¤I=žFµ_,Ì:{/Ç—5|Øô="ªð`%ÓêÞ¯Eî2ã »ª,Â.ž½×&«ÿõÝÙ~:øjWVšg¸{ÇÚ»N•[\Ý©V®}Ut`Ñ|4*—;Õ°O§ÇJ†(of÷zíïÉÈznUØ«HÍNµwôÞßXÈç-”!kÛÉ#¹A„z7_Ì„ŸDq5%$eg_7$Ã|,Åöúôsêóp}>Èççùà}óÁLøùÀn#–>$.>woÍLJkz~è90ƾ­½¯ÖîšW`+ó àg‰m{E”+.ëÖpé5`Ò·ìÙÙuÚ^Â¥_vo²øL0Ûgº¿].ý\7ÜЭ‹'\ÛµwÉn²*·uïý¯í:‡¸b“ŽNcÏÑ{‡#8”‘¬ß~j5ò WLýêÍÖ§ÜTصlÿBêûVwOVÔU€í·28zÿö8zDW9ö/\‹HâNr«Æö®‚™äY΃]Eê£þ+_U2¼kبáƒy½eÜ %=Y;w£§±í•Ü”®!ÏjøºŠíÔÍ3Ò=óÒ³?·Bž0 6 ÌÄŽ¾™˜7y=s𱩥®æ?tlcF®aFÞB® àüQ…]K³®íz%ñµ{¦­qj^¶±E·}›Ù‹¸1h6ÌÜ^@ÏÊôÌõ¶}U–¬ï.é&¦|ªïþ•œþÅKnêéézE‚›Ùìµ/sa‘nÛg\ޝ–œþÉõé÷ÛyÏÛ}U;Gâ#G]¹Ìe…™Êæmu©#»;täXpjO;vRGëþ&K­+èÏÚÉé]Jwgõ®¹ QfÝð&év§Á¯µû/  ¼{à†µ ­yÛ}Ú9˜›£ûsf·­Î|Ú›W¾ý¦J¸ êÃý¥†#RÞÎؽUaåNv`+t÷ß‹ëjè|áVî±v ½ =ìÎy¾©øéí@ïR{ØÄrkÖ)_Lî9*⌤X]õ%·eî…PwÊÑä¿ÅóÎÛyFj½“ßr›î©›X»f›¨_X³)Ã<õ%›Ä=7¥ùyh€Õ¬åÁÚÝjûþ×Nbïé~ù·Ç´Û®œ¦;±öÉêk⻯ÛwW®ãö¸ðéÛ£ljn™49º¥|³4Ÿb;y“î_Þ¿/ìßUìÛû—½]úçk»^N\1¿ç­ƒ3ýֆ˺®QØuÞ?NÚ›},eÝôŠ`›á%µ[ØU·{aW÷?³G ïÊÛ+ƒ_õØ¥¹„‰0ÖÄerK¹;»²¢µ{Gwù~ÐïÿÔSÿ{éñ ÀÑÃ=Þºò úч9%2ù¬M@¾»ÐùV7쫢£ѳ'MøÛÂIÜÎÍý°žG¶j•§eÒ„%ŸSžë&Ã7]ß·»çE·û¾m½Àúàæ˜žîí! î~©YúÌZæh'=°!™¬Ü©§ÐÆØúÙ»[&w¯ÓÜ­Ý1ÅåŸÏ"s¾úŸ ™3“ƒ”ÀafüIm[O§®Â?ºþhÞBïw¾…7ºýV1€v\ܱ0Ô†pªäŸ×Tw´ k¼¶šsû|)èåð¡xæõvÀÞ"3ûßßÛ0F³Ítx°ýâ9m¼»ÙÞIE™Ó;hÊW²›òÍ“€R;°äð7BÞùÛ$ïnËÔ$›é/`ˆ¤/ŒÉÙáÌxí¤?¼¬ðo‹»œú¹òà¶D-ŠjFŸ¥àæöŽ%E‰•©ŽDSG[»s彎;V[#Ç%Ù²,©,›;ðÒjouF ë è1é¾4re R÷®V¬J4ņF®D—K^ŠR›p š2Xœ´[£#Wör­­î‡»9 ålãÔŽŒïs°çEû¥Ë•–ò · V#<~éÝ,¢ÚÖl1æ¢Õæ˜~úy¥‡~7pŸöšH˜Ôè¼%Y[pvþè­ŸLo0êâÈÃ[kМg žcÔY3241òð!æ -÷ÿÎ=¬ÏÖ?öͽõ{èÏÐTûœõMi¹Udà“½=wø!ãùêªûhŸ§bÁJûÊQcÕásqe½R*¢v÷§;U}5=Kd¤³gêEÚ3zãf3‘©|®'4¬&›nUß:U뢽L§ê´Ñi\sD›q¤Å¾ÇèTyþ:U‹¬ßœ³vß=3*ÓcßoÌ’\ûd¿' 9Ðë5Ñ3­×r€y=ß‘»Ûn";=¾6ô˜¾Få/Ñý$qæhBþ5øöí÷÷ìL4%Vâd/ɵ²6c ¬Ùl=cí; šÈÞ‰çR`zÄé¿%2açì£&²¼ôЮ2½ŒÊ›ò¼ôæÌØÈLËÏÊö .lÉîŒÞl®<˜I­O.(^ò¹ª¯_jo±’½=âo ¦¼x'íÌðôX¦tóe,S&J‰ÍJrb_¥'§Û³]9¥¦µ7§Å]9‘ìÍi±X-'³…–Þœ?wåÄêJoN{£ëʉ)–Þœ–sЕó,½9-£+'’(½9-?¾+'f\zsZ+•]91íò„½ÓÓØ—ìÍiõMºr¢9Ô›Ór…ºr¢MÔ›Ór‰»úÉîÍi5üvػ -žêªƒ3½uZ Åó»¶Éaúבa óÎÛg¿×ëàÏÁ­£žƒw>÷zÞ¹~˜{B=ï|ptê9xçsÀû©çàÏﺞƒw>üÁzÞùðë9¬\›>c=ï|4ê9xçsÀµ¯çàŸ!øõγɯ¿žƒw>úõ¼ë{Àþ)ÚŠõÖ¾íì{¢ýXÏÁ;Ÿ ÉzÞùèQÖsXk¸6»¼žÃZÁµ9Ð`©çàÏ–K=ï|´;ë9xçç¾Ûþ©©±öOmîØõ:xçsèμ'ï|?x^Ïaž¸:º-™š~XK¦6G·µS“#X;E'®^«µÏkëxÄFªÍñˆUPcÔà§n q“½ ¤ÚÏÙì&ƒ=r½1LÖ{TÅ0]Î$23ì˜Xýy8†Kôâ2‚_0{b.óðE–á©[3 ¢«ƒÔp©Æ ™ —¢È¯ÃeVK¼ÖºHín„L¼ -Œ2»u¤ìI)6’­E)#a aNnfâ°‘6 $Š ¹Qx²Ý(Tž±‹¶H3rû¡ž†=´ýô^Hn4W3 )Žfë0£eM}Íe3rûÃ9ÁØáþØ*pmÛ.‰˜VÆxc ƒ)¥‚ 8ÊX&ÛÐTÀ°a›Œª¯ã0_„aÃq2v¨~Œ!`Ôp*Ø3<Œ1Ã*ã‰9@6›Üï€WسÅÝc ÛfD·ü@©N+DZ¹7ó;Y`¶”Õ!õð@æ QÊÖ‘fã@]€0Ëç]36^W)ÍÆx![ÍÆx]±Å=H1+’µ(]ÑÒeI{à`æ +lc3 #vËêšzzõ$lÂC «byí1ÀÄÿ?äcqù˜1¬*Ø#CvÆœ¯1Ȫ¨Û teÐLªºUë¡b¡h–ÕÅBWª‰ÚKºúMT5›•O n¢–œñÅÖ®˜¤Ë¤z:I»FjA“P¹ÅŸúd©ªO‡‘ e¼Ã.ûsØ Nè ûÂkÒöÓ°®fm bpŠé³Q£ÍoŠL±jÚöÓäOÕKugªnšø©Â{Ò$ž*¾îîÓ´ã5Ó„©t·™&;dêÌ4& s‚ÓÙ1  éX™d³M§æ˜-<]ÜÕ7 Pû­fŸ¯f3‹@Í vFÍ>_-+6XÍ>©fŸ¯VÇöùj9ÐËSÖìóÕªGg¨f;+·Õš}¾lΘqw£B`ÆÕ?Œ4ÙÆfŸµÖçíôÁ†¬Ùé«]` Õl[ÂÊ^€~°Á÷7ÑNYº§iCÅB›ÂF±º(¼ ejãpsâ. ] ßÇB–ܨÀðº p‹b«Å2ô§;B,&1÷v_º=pÇúi,|§{E,V*¦œÁuÂ☀¦)±ö»1ìΘiˆA˜aÅÉ ÑX÷0¼ýyŲÝ#ÔËP ìmÅLW¬+:ƒ²bæÏˆbæãѰA…¦bíU.¬l[¡(îl1*–¡§XNd°–ЧŒÌâ †«n^„cvc,»·š.O\jc²Š±³½bPUÌ>ÂH3Ü4ƒ¤b™dŠŠAQ1;{«XaÁ@1fxbMŒŽe š‰uµÕ­-f‹Å ˜‹H±îº_Ä —X|!®aqb‰eÖVh%æ²€mV,¶Æ f<ÖEY3ƒN˜qnˆÌx *aÆc 3Ë"«f«»ÌxÌÍ”eW3ã„ÇŽ+3Ë6¯f<†»ÇŒÇ²îªÇ"¯™qiW˜×Þ̸îõfÆ1vÍŒÃÁ`Æ1†ÍŒëBnf—Ì8÷zfWÌ8F¯™qLL3ãpA˜q¬À2ãbF™¾43Î…œ‡ÂŒcßœÀÌ8&§™q1kÌŒsUdÆ…,͌㜀ÇÉ3ŽKfລèëçÝ J3¬ØÏ¹˜jTìVÓþPìÝáÂú³.fwüFnf ºC³5oH›ÓTfcÓ\e6†¡_nÎÄàfþ:›ÔTfBÎÜ*³¸tã$ÃvËÏlÀõ ^fƒ 1æ©&Æ  Û®.Ñ÷t±·ÏÅŽYÒõÄLópÇPöWåCrêQþÄXÑGT/íÓGžÿÔ“ÑÉ~eÌ™ËAÉ[¾±°Qµ3Û§–UÕóÛZ’5'2”FÅP+ibc˰Œ< nk–cðòÖ^‹1:A¤ª¢Ü¯l²4åìÓžÂgš‚«O¤ÌßP®•h§®Œµ…¯ÌËð$þ‡8%UÅU®*SJéË.F¦â¸¾©¦Ó +"(wlkp“µ‹©Éqq ¶3çñ¹’±Òˆ©Œèôdc®JÒ'…ïôÅ]…¯nxå*µ>“ºÇQÙC.K{\™þw·§Î8°³*œ\³]¢íA[§Öàp2ÿ#bQÁ1öhwVùÖK9áÃQŽ7!ûvŒµÊNèÍ|Ê»è;ø”eÐwò)ï¢ïâSˆó>å]ô£¥cðvZ¼’Oåý>µR>Ƨ~œO±°^w)¤(·^AÉ>§­=ÙÄ¡ñqßQþÓwxÚHFðbMryC-à²ðÏXณ*7Nϼ6‚…²>åž²\¬½Ø‘qÙòJ«t¥>H_þû¾ô=Ü›_èÛÔÿˆ1Ûä|*¸¸%ÆÞ…³TÊ•K;Øo{¼ÆÊï÷ TX”i—ÍãTý¦]¢?i“#ìÀz§f{ó2OZ:Üvð%bhÑ#eÙٿѹ 2Ë¿;‹œ¢®p p ;Cv^ϿטQñÄü%ÿ°ÍºM”ûE*ÓÞ;K¶Zxãùœ¬ß"]ú×0`ÝÚ:ºf†x”{0éµ(Æ ­Š9„OmOg—öP>gDÇýÖÃIáƒE-5ͪ¼¾;Ê“µ}Î[ºÃ°ôÞf÷Ù}}È3lt¨PŒ¹|dîhËå¬F.rÉ;S&eo.;–n¿ƒOuû| +¼‹Oa…ë6ñQÚ}ÆgËoª[^£ÍYZ Á̺ùY>kÞͧ¬ö^ø;·å´讀 É𘹒´ŸoQÇÓË4rßäZvz¨§øîøóVz cßµ¿s4PúB<†½-ˆêl²k/i€³Ó=¤v¼ÏGorŠÛÆXÇŸÒzs±³ñöNå<5¾Ø—•op3¼,Þ®S«‡ÛÓJÇN˜åÿLXú2.ªsÍZ´±tœLô^ÌçLø,¦ -{®f¸J×s£”“ßYxëfýB›éš,þRO/^ò’$w e:º7š¼¾£Ò2žè;ºmê¢Êê9 fÍâîGè„J8~ŸVäôò²YU³Ë«eB°òU=YQ¾¨ªzþœ²Êù3çVUO›Y>혨àUzyæÑeÕ *§kAŸ0§ª|Þqe³`‹ñòä¹ æ—W—Ï)›:«|z”ûz÷fñìêù/(gNM¥§Î®®,Ù@åÛ>¼`út< ªßòÕ¥I¢/èÉ©•U¼˜fO>™y2ÝžüZæÉ {bª³OfÆO ÿØ[‹/ºpwo9é«û{+J_5ôå_ïÔ«“¦N¯ž_>¯¢lVõôòYeÇG9‡ûgËÊæ3*öUq?ÿjÅñ•ÌÄg>nÖÜÊÊã«§ÍžîsïÈ<[À›3]²èí½¯l›/ï}b²$Gö>Y^UVµ€ÎýVxå¼-=6S^õ•-ïŠÞ'¶¼÷õ>ñååm<6Ê;BÑUeÅ ÿ) ¢¼ Ÿfñ“,>Ýâ'[|Fr}~É.øÔR:ðYEDñ ¥Ú•ÖºŒi\<¶êÛÓå¦OÞ˜®8}òætÑé“óÒµœ0WÓ­¢—§kIŸ¬K×’>¹(]Kúdu-êÚŠþZôd}-z²±¿Áë[2µœ~l”{y¦ÂÙ4™ð9™ü WNÊÌ"kèô(ÿéËg•W¼+3ž.…¯ašOñ癉u)öO¿p)¾šb—âóé.ES/ÒÉK v=IV^Þß›,¥Y¯Y²”#û{•¥4 ëY–ò•ý½ËRŽØÐÃôaqÄ@/Ív´¸!o¤Ýò¾%im2¿6| m²›úg“œ’7Ï&›1Ð9›ìêþ¶Ùd'nœ?ƒ‹Æ ¯Šã7NžIöò±3ÉÞ±qæL2vÂÀ™dOÙ8m&™ßKé¨ñ*þÔ@Ï?«bÎôòyàÅw÷7.{ß0н<íâþæi¿<ÐÇ+ýh §.]Öëjºù½té–Í«8NçÈ…sgÍ7»¬2ÊŸ¡gÇqê\>m^yùœ(ß•bƒl%ƒypÂØ±Å3UÏ_PY9w‡sà;¥|á̲yœ^N8®Ü¿Œ–ëåÒ¹G;jì)e³¡Fšc(Ot8®b 9<0~ŠgžªÉJov};yîü¸oå›Óñf—M5¦pˆå—·`ú˜ÑS+ªxwÖÌŠitÜ\QÂ;SP)gàÙ ÃñQ¾»ê»S*ªæMGý¸ãa”ç0ݱsçV¹ÖË—TvÕ[^qt|.½2>êž²€½qœ¨ÀÕmã‹gÏw<ýô…9W6þ¯M?ZT1is?2qw5]V6¯lÖ,àBydæé© æ0óàÚOÀ/äæÌÄO_0GÓåÝîÆû),²“«§Íš;í‚§ ’ð—jÁ¢øÖýºx¼§“9ýÌI?±ç¶(w·Ì ÐìmÏ„O.›æ2TÜ Ä/ÐûDÚ-„•R¸y U-Ä#wÑ ÷‚ùÇTϘŸ”Ìâ­|7^j gΖÖ*OÜyeaå·rN¿éSˆ×¯-.[å¼&=–¨é«‰.$j™‰."º=“iDû4º¼rz–IQ3’ö­2™2Ñ€+ |tyùÑÕÓ¸˜S´ {KyZï±ÊîÄç,æA þÁq<øåÞdzþë}°tz7Zs¦öOô N~<ïWN-›0p?}³´b6$‘Ø]xtB&‘ٶ雨<9Ýéãf•Ñ{dË(™N:ÞœÉT$ŽGP}tò/L3òIHt2ògoN'÷kûßhñèÆ©•ìÅläí«SÉnΧù›E¼ù‹ìzc`wþfo&õ¿‘^o¼sÿ›§òÆœBwõ&[8öÍ2ÞÚÿfáŒ(§Æ¿Y4‰t¡#Òs¡ [>‹æ¡NqA&*í Co°Ñ#£wŒ&ºB™Ò¶bŠ󛨔/ ëÂFUEºcW¨Š§ûèBu晨:³2UgVe¢ª7íèBêµ·=K¨I÷v1+<Òáû7|XXFÆc}tÁ‚ES£Ü…>, ±4ÊqW[ «A)‘ Ei͇O˜SIê>,ø"†KZ‰L++ËçLwÈåi鬧; VÕiÈÝ…'Óã7†+a ØS\jƒš——ÏâˆqÊŒŠ£v¶|,ž :/ƒ¤Ízì¼2 vqµ^®˜YÁâÑžYR^=‹[Žä,Ì9$À¯Õs§>ß°´ŒWÄóå­KÇD ;9ʇìãã:ˆ$ó@`[úq_ËoM–™oÉ76¶8ÎE6ßšĹ1ÓˆeÓ¬w¥³«îïÜ‹…î{îݱ}Ã=V©¯ŒJB ¦•Ý ÷_½%çÜ»X¶µì|uX•°é¸l÷ïÜ·xýÚ}GUòÿœ'í}ÙÙÿ2 ]ÜÞ% ™Üì#é-©i†R ªH¾{[ušYÎbÞÆ41o玘·aJÌÛ'æ­ó‰yÛÖ̰·‚ˆ½·ŽŠXým¶—$Ö]æwŒ†zÏ``–`¾aDZEVE±É²)ZŽ©±­˜)¸–¿×aâà ïÜÌFÒþ«Ä{ Yy36\\Ìü^رÞ)Æ;cê‘S%ú´½,Ž)ÃÄ%íìö'ÂýdžØ)!öT‹aàüðî‹aàŠã%!Ç«-†É€Ÿ¶ÝøyÛÕèØÕfGú]mm,Ù]ÍÌù]ä-æ$1ÚtÄv©5,3nGŠÚÚZK–¥÷ëÖìá–'cÔAXªM6‹ùžÊÛ ÄŠÄÖ8›˜ÂRÂCãÍñ²`—rQüvêåÒ35ö?WãЦÃöœ±LžÕÔà,\¦»kváÿîÉ„m=™V5ØêèìÉ„=±ï&Û»²gìòcÓ7Ï1mrèãˆÁ>F²šìêi¨sæ¾G,#>¾ä”#N/éîéÉ`á•<>sßâ«ã´†vÅÓ°Œ2;üî?¿®µ}át%89ëüms1ò=£óyéÉ Øµzz¸ªIëÁT –…uæï?_«{JS‹ÛD¹MHÞKÂÛ½_Ó&k=Üy ÞKÖÛ½¿¸%¶Úhßc“dr,Ý~•º¹9lõ‰90 S·Í·òëÛߟ$°o š .ôŸïì‡/è¹Êpr›pòÕ`ä«™Ší`c?\òôÛÙ-;ÏùföÎÝ€0kn+,ÚÖ}Röî²WÚŽ­…N ±s.ËÞ½›IèÁ‚«|Míáæ´ { ;ë¨ËbÚ6³ý>ÓY7Ô„m» Ójë­]·Í¬âšO@¸ÞXxÙv}å´h¤Õ;ÙêÝ2ñÙûÉÕÓ»fê×vä¯ì½™‘³·'šcEµþvWw¹^üßó¶@¯ÞK¯Šª»g–Æ÷Þ,”or]=wÔ´§¿íˆÀ§u)ooõ=aKU{Š÷ç0 ÛPºÞÛïÞÒï[éwÃö~O轇(ß9›kÙÓçm½}VÞ‡ûÜÓ¿ÐçöÅÃûû3m²Î~ôhgΨRû^O½Üî5ó¬w+þØ»'ûfvn¶ š'‚z©aën9짆¾·²bÞvo‹á-€¢¡k÷nô@æ²oë{†z?çÈ i÷ÎÀùueœ[˜ vzÕ'm6»|6Z“³±0öx{­n7QiÿÝwv¿Ñ h÷݉tÌ®¾á¦Ô™‡»SçnT»ß莕½ ¶}KïKs°d1ÈÔ«Ø ±b7äŒÊíÍç0ÊÔ‰Ì;±×Õ±À¾ÏœKÁı0]Ÿvc=fsN[ÔûfNivÂYœ‡‚Ev]pÚaò{êæ-6ß;ÞÎAg`Â3²‹Ëº{ÖO,Í)þÿÕQkuìø¿u\«:®Â¦Šf¨àvú;£â’õôùžœb$]w¬><»úùî{y[nñú‘ð´Û&—ÀÔÀ&hûú¼Ý°ðOeiáâÚŸº>Î;­òž¼’ýjÇ-NWÞi•–÷œÁ¼Ë\½ä=g^Ãf¼Åbo™¾¿}œzÿlÔ ‡ÇS¯dÝ}™å=ÎF¼nÕ»$Æ2¢a î’NÛzÏ]{?Þê(–<‡[XÞJ;÷ÏçwLøþŽ 'ÈÛ‹ç¾éí®Biõ·Hî•kBlkÆž¯8ööµn°:¸ÛyËïãðwIrßøJþ.‰io‡]9â«“+Þâ<†R¼_rl ±põ–߉Ýi}Â$‹¯[}нýwåHmc®ÄßsUkz%G^wÒb1Lø›,ï¼½`b·eêN¼eaÕ|-“£àçX÷¿‚·«º žÃEŽ|þdkÚÆd²¤à-ÎËhI!ÌAjS“mÞB55ù[09¼åzÅŠá¾\ u½õybÞ>¾îE?ÓB‚EßW™;)úy"æëS¬ä-ºó6±‰ù9#æïæÄ|?ˆù9“i”’¿/‹#Xòü!q Kþ¶.ÎaÉ÷XÜÄ’·_/cév‹ ­”ýŽ—²ì¹MÚØeÏg⯛w~xç{Ï»Ïdlþ–½=mÍYÅ[þ¿³â÷«n”Ï'´b¼eTi ±É” 'h×¾£Jì&ÓÖ}JšÛ“ÞŸ >äŽD]²"$ÜÙÊ`4ð†û_{÷éØ<ß•æôN7GÞ·ozÿ}Þß碽uí^éïðãáñøÏc cp+Çjžbñ_†s¬ykçÄn·Ýaøº5îG¼sÆ:03é9š˜¬ÂÈ`‘‹ÒÁoèµü}«ÀãÙºº÷ìÓæ_üaÛVGo¨?í ýp÷Œ^E2“§Ëä!«§Ï¯LÌÓâjo»ÍÑöÛœˆ~ÛÁø}Nl³`?Fv]Y=³aé²4dõÚð7Î]Bj鳸\Œ6ddçÅÖwòZmÒ «¥óù°ƒ3(¶übó™Eº®È”¢À{Á€–©K\½<ÏG¯bŒ5ü‘×…LÖÉàQ5œ‹¬–Ó Üe¨ã2étÈêx€ÚyÛaI±[ç^ÁÍY·ïÞP¸7 ‰¤ó/›Kíu£FŠ í¸t‹tK1¶ï\S¶_ÕS\CkÅ>þal“>¾…wͪÓñù²:¯¸—³øhñÙéýVh°Xü +úÂSlßÿ·útËÒ»Åfié_j0÷RÕ¡ûyKß}Ko¸¡ºï’åh°ïf{Wö¹Ý÷ûm߆¡oÃg¸5gT‰Å'Û÷|}s®ò"t3îˆs/~gÀU oû~àgÀà¨0k†›ü ¬‘ßpÄ›¶X,‘ß²R®49®µ`ñÉ‘cüèvË¡¨–LŽØsø”#¶;ž1¢æï*äðœcï3ÏçyÙÄ|0(•÷ µßNŽ»-æ¥üíŽî‚Ñ5Ï/Äìš¿™˜»Ña~-9ß°¶;-·›t7LCzŒ‚£60Š4"û®0Ê"´0,C‹e²0‹¼Æ´)4æ°%vĉ.¡yØw{±¥vÕýgg±½tí&·o[ý¾¸¡ÆÝ©[ݹ*ܬ¼ìÙ™;ÎÍäÞAMâÙ°&np»ÚëLiì¹ÿ²gÜìcÎsõ1 §»m¶—ü`‡œmóË,y ÏžÙjóˆUÃNl §ÜccæÉñ!1!gøÒŽ8\œW?§0áÁÌÚ5‡eÜÈKßTšf¢>Oóag¯¡òùÚï}ïž/4qöÌœæÝì ±)zk_QKžBÏ]숿.[]°XûhE4|bWmTÔÕ LTtœKÓë¢)™ù­tozדkÅ“¹Ì¡'7„|‡”ﺯ†ò-á]ªÇ ýy‡òï:~œ”Mò|·=”ï7Ó>ß5äk ùVðöN½ÝÛg×£žß_ÿÌïkù[Cÿ·eÞ•zûúp×}}.]Í[¸|=}(]nIº—ÎÙ4_ÂÍù¬•:ïÍGSª¢Ò"»-Q½óºw™Zrzi´.9j¦\$nÍáîSÌyÓ%y£fQÇÔø¶¨:®Q<»¿Í[LÞÕä-ŽšÕU›ó&ŸûÖÜQ3ÿfÈ{b¦/Å›™QvªÏwë#ùR>ò…ý×›Läó-{$_¿¯mp'„úÉÝù>Ï_¸·ÿ=C\ÝÂ%ëà*ÜÊf≺ÇÌYWM®Zœ?…X{×â-|ÏVM»˜ç­‘‹Ï¡…°l;wÕ‰ï—÷àœÁ¥7J½Ÿçûßó~ôÆ}U}ŸÜåw]ÏûÏù}ÆSñOOBüö0#Ç â’ln:pÓò¹™ ·ì î¹Išo¨·ËB/JÄç‡-ñ©ý¹s޵îµ·ùÞŠïÜð6Nßaõösz»ƒúìm]·„mŽsÛ ™ 7[å2ûïšL»Ô/îíyŽkûsḻ.`•3Â;¿ÿx—ö/“î.wo€Ç³ï&bî ]wþèV_Sç½ ?F~þ;oÓ7mz—c#sCß‘sÄBÞÅgóòà dÜ€À“ ßÛûI7¾XþÑ{ÿç»zÓ9Ñ>é;§7²T¿­ËÔUk×m›c÷m££^{ ³£ž«ŠáQ¯1Æ=:Z.1Cêz` –vßÜ1JšØ;Ì’&žã¨:<ó¤‰éìQSâ¹}ºW&^'H5%Æ549n´˜¯¾-s×õüQs÷wbâ’f1§%dbŽ¿ebŽãH¿=—Ô¼s¼CLŒ[‰±Ó‚é±™wŽûhÞ9Þ§y縆¼+úss`bŽÃJÝE_·r}ÝäÈë.÷€ÞxŽ)³[ôsÉ;ÇéÄxjÉÏ™j*ÙMÛÄü<©¦’ŸuÞÝÞùyâŸ'½+{ƒÞ•gÞ9Þª‰¹}cbyÝ)gT; ¼.æs+/_b~žðäãø²ÔQñ³KÌqFMÌÏ 1¿Ï4•K2uWŒcÍþ¨ø¾’ÏϨŒñ4ø¾ÊõOƒŸKÞù}É;_ŸæµÁÏx ¦]eb~V”£Ñ×DÌÏ 1Ï#×4ÿ„[{£ç.kç56Ú;ÝÎ=WD–m/š:¯ÚÄ|¿‰yΫxž‹¢Z›¬&æû¡™h2N7ö&¯Y¨4ù9–ªE“qc0(ÛÔ듲ƒ —g8‰Ì‚ŠWßÄ0ïû_çTð­s®úN¨Ê|cy]üðμÀOc¿¯¾ï¨gw~™M­¾‘h³ùïßKë¨ú_׸‡ë‘Î@I{VÿëïK(>6 }Kü/1Ê%ø–%f¸¼9G~±ù¬-“ï×[a‡T´szßËJeeûLWÐ)~¸¾Îyï|/ó¯}<ü—¿Áz!M‹h{¤Ö`{£þ60 ð½ëýk€Ûßh±Fø>Ôô_ç°ñòr§ _¾{“~p“®p“Þpk ±Öb£C¬-ÄÆ‡Ø„›bSClfˆµ‡Ø¼›b‹BlIˆ- ±e!¶"ÄαsBlUˆ­ ±u!¶!Ä6…Ø–»<Ķ†Ø¶»&Äv„ص!¶3Ä®±BìÆÛb7…ØÍ!vKˆÝb·…Ø{C,ì;Bìλ+Ä>bw‡ØgBì³!ö¹»'ľb_±¯„ؽ!öõûfˆ}+Ó]+‹åûO,Y,ߺ}e±|ÿI·2‹åû/û/û/ûO\Õ,–ï¿8ì?éÀd±|ÿI#3‹åûOœ×,–ï¿8ì?éÉd±|ÿIk3‹åûO|Ù,–ï¿8ì¿8ì?éÒd±|ÿÅaÿIË3‹åû/ûO|Ü,–ï¿8ì¿8ì¿8ì¿8ì?éƒf±|ÿ‰×›Åòý‡ý‡ý‡ý‡ý',–ï¿8ì?ñ†³X¾ÿâ°ÿ¤WšÅòý'­ž,–ï?ñ³X¾ÿâ°ÿâ°ÿâ°ÿ’°ÿÄWÎbùþKÂþÓ7‹åûOÚAY,ߺg±|ÿ%aÿIo5‹åûODY,ߺ'g±|ÿ%aÿ%aÿI·5‹åû/ ûOºFY,ߺWg±|ÿ%aÿIÿ5‹åûO÷í,–ï?iÄf±|ÿéžÅòý§{xË÷_öŸ4—²X¾ÿ’°ÿÄ5ÏbùþKÂþKÂþÓ½=‹åû/ û/ û/ û/ û/ ûOPY,ßIØIØIØIØIغÿg±|ÿ%aÿ%aÿ%aÿ‰/ÅòýWû¯ö_!ì¿BØâd±|ÿÂþ“žUË÷Ÿ¸ Y,ß…°ÿ aÿÂþ“.VË÷_!ì¿BØ…°ÿ aÿ‰‘ÅòýWû¯öŸt·²X¾ÿÄ¡Èbùþ+„ýWû¯ö_!ì?ñ/²X¾ÿ aÿÂþ+„ýWûOÜ,–ï¿BØ…°ÿ aÿÂþïÃê ‹×¡ ÐtuF§ÁÝÔ,‡W"hüŠ!|V½drÁÜ)‰iM1q_Ò¹ÜØlq^àú“EtßD ¯£÷MÔ#•¾³ê—¡§cät²÷¨ñ÷ç½ÌŸU3þ¢šÆXq'¯Ãûè‹ý}V}ú\ûF†±°XTga Ô¿NßËH¶É-~ýYõ±trú*|MH%ð,L)˜§þ­ g›¼ba«f9rY‹]v÷V*¿Æ³‚ žŸUß„Õä¼^)xF“x+§n~63çäcÉI|mŽÿÛñÑÄø’78¯%þ¾´íyi}jÌÏ}i™K?«ÞéKÏI8™è¶æT»“š®©B)l£ mõàüH_ ‰'gÕ; ã/ö\ošÛ&ÁܘËw.^mæ¢Ü•êý\P^,~ /pÖðͤ+yÖÛùwü¬£s§,Ü;ÊX.>÷7Ò!¢Ÿô¶D¬ðÚ1­ž_©Ü·ÑÄ½Þ o=ÎpÊoÊ5Ëk¬¶G‡ÃV­ã ¦tuïÛ"’—Ë5ºê´;î–Ö—‹·Tu÷Üm± ×}ÛÇŒNxãM ¡…X[U4l²¯÷¦zþÂuß÷ù&ˆ«·«Î(æR‹£]µY×Â…¿^qûÂîtžÉž§éµnô½Èr/UÞ+̺M¢Ýú¯[s¾ø&Ë73è4&ÚÒÌßz‡·ûN›Õ¼Ó·ÞN¿7×¼ÓwÞãféUóŽïGg\S;ãW±EÑ“½n(٣Ʋ?æ;ÌwŒ*\÷…Q³JPz™ÌU‡>ýP_ Û³N?¤¸;9jÄÂî]&w-ÎéìêÎé\›7ÊsW}¿¾¼¹¼ý”å2^ ß!_ÛÞæî5ÑA¼Iú§>Ÿ­zöjù>Ò÷=ÚÀF§!Û1Z)ª£âzB&t/F®{%óýöQ…h‡ŽG;t·ÞSεÜ×r›ÓÕ>®ò+qH"<èù•a–%0+eöŒ6lÂþX»Lø•A{Óé‚Ót#´1èòwZLØK7?ÖÒÏÆ´tó1á(Ýíl £îE‹iSé—Öª›}'Œ”úP?t—ÊräúŸº©½Í,ætSÁFº=¤uèöåð<8qâ„×-Æ K§^üWƒ±oîq“òFhÉ÷ƒïrÞ¾½ÚC†·‹~ß/@#ö­£ÆJ·öûzwóL×ÏY}ê˜îL×ÏjÞ­XÛOÚ5ÞúyÂ=ý¤gi?é¡ï§x‚X‹ïwç¼omì'»\8pÛé£Ò(íãL¿Ÿœ ÝÌ{çûHO=ßöD>F[enw-†·}¤w«Ñàápú¿ºCž·ïîÛ>ÿüýLÛ¯CãÎjh—|]òdü‘c‰tЛúÎïÝjßíÙ$ù¾ðú¡ì” êy¿Ì}Îûw,ÓÍùÒ)'_zmâaeï<~däz»â7Ù$wM»õF—J\Îí í€tHg4’ÝÿWEÑÒgŸ^B»WËw–FKùij|8Ÿ”Á¶¸“šqs½v¿ÎŽõš¹d]ðì~Üp«Óã; ­ä;g›ö…€Æ·ÝÎÑÛ‡÷‡Á]õýñ£‘ߤµøpÞ=Šß?°Wºñɽ¦m'§`ÓÆ3<û<—´ôá”à_èMòËmG0ß^“œ‘ër‹çgs0ÓŸ 9î¶="×»÷H[À2šåt<ÕöÂuxÐ=E ²Ùm€Í-Ò»ãÞ}z²½£Õ™ùØŒ™º¬º½ ^èÒ6Ã]?gO>ªGüÈ,ªí°dŽáÎgpƒnYÛˆ{ âݵŒ~ŽôŒ·>%çªõ=î.ªî˜º¤älj¿˜­9£>Pò9dîGߦÅß&>jz§ü>ýl”pó/§iÜœ7±:45k÷ ¿Ø¹Î¥×±73è5Ò™ãE6Ç2+Ö¥?œÏ±q@ææ˜‘ifŽ_ ,2¤?7§òŸㆠ•¡ »ß»¿œSüT¬ þq¤-ûljåKg‚î›Û’Ü"_Àü¼uÔd«aBØÇ_ïFÍ}[=Þ%ÔÄm’çc}ï?“ÆE\ÇI_R½™G¬ÁÝXucl_:jÖ:ÆEÖè*sZJ³K^É­Q]Vl^÷ÒQéæ­ØQÜ%§VE=§HÈ[=œìzñÌôPztâ/(F¸·ȉ–Ñbè8Ó}ÝÔrŒêS>üð¦¨7ÚYô³YNºuÎçÖ™éSÕvÊ£˜">=Ú?ƨ2¹·w©|w§d1‡Uc&[œd»khבn‡ø¢v×èâ³{×¼7ìít— Gs-tÕrñ̾šîÛ^Aï¿DÏ¥D99ÏiŒ·rO›ÇŽ×âƒakÝaè®w;}¾4ÈuH3æR½³mó¡»¹¦©¥1)ÌŽ‹pífh{Lßü>å–ÖyãQÓÓWßc¬¡ÑcaµM'Þ‹k¸w¬¡ÏÅQÓÑTËúÈ.|Á¨ÉÜúκnüó»êvÿÀ#¸âlúõô¸W؃&X5Y]=Î瘾zÌ çgæµ3Š^:_ØoKkMs›®ˆkRÍ(œ:…m`Ÿq@êóâŠû×O)ï¹í©çÆÀ1¥H‘qK*CˆŠöOߥ»£…п=Ïr^b:uìÿ]Û³C×Óó)®1}/0Ìån>¨‰\F—9Ï·$x]š°ÊÔmZpÚukfØÆÕäñjk¯ö•r´X<ùVUGËꉋ«cp µŸ³…“ó“9rzp©Ö¯ã{ýðÎ=ý n|u´§çm°Lj[¬û&bïoA³ßâvT®íï&f¯{¯ äË=LTõ¦½žnígÃèG{,åŸ?ø±°ukÇ¥~,T·xé©Îxæv×ÊïÝnÌôÍàÀ8ås;óBB³3_E¯™—¬Mr\[“ȃP¤·K’M5ìQ-Ð ‹ˆË€^ö¦óÒ×<ìý@XÔî|ø¹Ï| C¸}T ó¾¦+w¯k»¢=øßv,ûcÉ#·š” e4¡åH \¿ës™}áø]í~÷ì0_SNÿP^î×}f7æ{È—´KD¬à4Õ¾ÁÁµa—øû-÷µp¿õ><Ø1A¯Üë61›ÞE~k3xÐë–1ËwÙÜãQ¯sî[ÂÜçÞ‹bq"ÁX²'øì±óq|ùý™×Ù”š ­ôì±CÌ|ÇLòîæ²„]ð¿g^7VͼÑÔÛ=ô5þǃsogÌ»,ì€àûáÛÌ©÷îÆð]aîŸ58÷­aî5³éÜË!Mt(s¯ÂåßLïûüð~ÐØÃ¿Ôf_ºÞè{ D¿ëòo>9ûø¬èã`ßïzdßïBnEN¾Ó³%¶5gFËÿÝÿ_·]Àþרí Ë÷vÁ#€yíÅ^玘Ǔì…ÏÚ^àEç^öBÐi‡p {á%QtÒGxd'x< JÐ “è¹Ýêñð'{¡ ‡Í÷YççO©Z<½HÕ[™á>vÈ»áüMz†ê ¢ÊëÉöC®s)]ª +x-=bÞ+{#p|¼¶%óìöƒÙ¹¾ ôì~ÇŒÝûajàõ˜/·pþ8Œý ÷ Ïßµ¢÷ vQCg²56Èaw¾`àr´ #øü]·Ü(wäŽÿœ›Üaïí:=»ðìºñ_¹\G|»ºïÞC7ñO»š7w{¯nCUN†ãÃ[‡k± ÅÒ­‹/<û´ñ_/¹€™ís!.ǶŒð_Ó½¾×_J÷Í}<¶F‡´PSCÙêø>Ðé‹!Ÿ f¡ägA±²ÅàäU,ÖîóuÏHõ†àgÓÌHÖW}§;™ôãlLÛÅë‹S«tÓÒš¤}–åþ’å{©Ó³1Ýa¥–æÎWš[Ú^YÌÏðRê[KµJ{Ëê(«Ú)ªLàä'`ý„;ŒùÖ&7ßþ¿ÓÔKy½Vsze&æôÊLÌé•™˜Ó+31§WfbN¯ÌÄœ^™‰µöŸk·¾Ç ÚKûÚ^X\ø Ã…šãk?<»r"€ù› *¸ö^!Ž)ºÝƒÑ¿öÃh8 €ÌzÚ§ó7û²:2–GåùW©7÷ýçŸ'Z´Q§Âj üÐëÐÿ§- .¸õnõ_´Œ^Eð&<Îxî&Á‡§ó1fæÖëýÛ»£}ñ¸wßF‡[£f7}i˜[£&à嵚ýÕMucóNF—K¶ÍÓ\Ò0·#a…<×É5îô`Lµ¥êMvËç”ÆE´'9Õ“sN¢¥5YßÐ_0.1RDôôOZ>éiŽ”¦:¯Ñˆ †iR÷0~c¹u§0wu!x“[vðOJ$ÍüƆ3=s>†0£§ÚC~ºŠ|[¼¼ö~ïÄ~Ÿ¹ƒ7–°sÎx‡ÿ‹­ûD¥¼5~:r‚îVx÷XÜå¬;ìYënžÂN`œxï W{¯7É=½J¾¶©Wº[|_øs;y7±› .‹Ø1ñm8¾ØýÄn$ö¥ûµzóïâ/FÛ÷­žtt©ásñ²ï§ÎøjãFõ ŸóS®æÛÔ㇃^lçö-íõ¦¡÷έw·gb-!Öv9÷èâãyt·vžIvÏzŠe:1“‹ï ¼ÌÜsŠfç¡Þ ƒ™ÞgsòÙÀcŽž½/r{^‘°sÊ!·ó¹gjòÚ0¹‡@°Z‡‡ÀŒËš{W“îqû”åv“æp–Ûû^ÀÏ”÷ü@ÌûU æ5ˆåwiæ}’v«­O8Oº¬Ù­$h”y/Ê'íS›O8Oº¦á¶’yºÈµP¤Wfó ÛI4ËçoRš3i~ZÜ+]ÈNÜ[ÌÍà^p^ŠeÅeˆžVÔ–zÍ·…3w‹æ\¸Ü“KÚ–FE·› ª…õ…F ä‹ç€07¦â‡:Ë[”ékÕuÑxXg¤#íºòv[‘*î\CÐyzÍ·¹é]ÅúI‰.ñúN©Ç3§Ó$2â?9Üd8@©îNÛ>Ìþ~2»=÷–åv{ï}çáÝ. 2ã³å¥7?„ ÓÛ ºyê+ <æSËêl<À3ô{9¿Û8‘v±oÂMÕsÉñ¸•ß-¥åcó±sò}ú‹d§{Þ‹öJÊ[g§{Þ‹ô]wß® \Dí—tj3˜›‰øi¯{GlO\Ž%•qNÒ¼º>XÏQ^Ò-´ÓŒŒi]Ú§q3uHþábXk©Õ,suÉj—Îm4•T•­Áøëª†œUvš’(kkëhn}û¡m‰š’Ñ·“Ç’?­ðô_÷Žî9™ÎDË¿yÈêä…tÝ‚vlºÅdx÷?{³é©ÓxÊ©boy’"¦ÿÆ–0ï-i°º¸Ø’ÿì7¸ÞÕ×âcÿ‚¿…mÄ[sûö1¿4[mÏlOú=û+÷@â9ygûû)¾hÂýt—åf‡9-&·»¥,îýº€Åý?z–ìa¯Ý¤=–zfû®òy¼Ã‘»ŸµyvïçÛÂ}7ìHréen®zùFõÄþÃbô^ýï·½*ÏeÆš Ë“a玻éFÂR–ÁÀÚºI2s¶Õ—ñ“6%zÏ­|ÕO£uÐÕa0AuAOöÚ—(æ5lgi¢¦|8<Ósc–¤´«£Ãz†×\.¼”¢ñ,Æn½w»;çzvÓZÛýš3üª´¢oùÆÃøj†­ †“ ¥%_ÞÛ n û{öâªwQ-“{y»H9;ßãE­ó žžü›à7mÂ^¦ïÛ‘Ïíò[ºOÞ~os¸@ßþÞöp2_cy/¹Ëé á}µã´î-·3ooµp¡ÎZÿ‹_u]ÝãW©Úc{x¨Çاžxð¼êÞ©~\Wo_Ý^¿cÍ]{Ïj¿<”ŸžÝÜ-ãCÏáCmÜ/É禹MJ»âmI6u4Ö´CwùÑmR¾:ÍmRº&ù;˜__ɯgÄ åÿÛ>2 !˜éËËr×-?b†·™ßùˆ™;_Êô†×­™vy´{‘ZghðOh¥qssÁf~r¯¼©N8sQ»+ØÙ”¿›Ýœò›‚¶óágK¾I£Î°7㩘¯Wq”eïuß5·7éÎÜ<6}{ëÂüöö-Ë+çÑòŠšuóØtº*Nv„©Ôb¡´:mnÝÅ ¾¾hkîɉf,'pÞò2~–ü§›Û‚îxÊy²¶CžM³¦U»›Utuˆaë sãÓTºK7-÷Ùsý8]ॉmrÉMñë.­­›ÇήiI,©i>1]iv‰8¿5Õ¤rõÏßõ/ʱ¤{=‡„„l ›ZSK[kšµËjš—&«0%Ùüò!¿4ÁnË­Ó\!ŒH˦û:7:üüÈÛ|´uHÓìæ±ó§ÂÓO›#ÈcSµËÚvŠ:ïžiùä¥Þ䓦ßÍcÓWP9‘oA¾ÕŠºStâÛý¬à{Ò-¹y¬w-ß$>¿}¯Kž¹Åˆ£zóX“™ÙÔÂë”jÔ~›2³.ôm´´Ño›Ñ м­ìà1½ŠmUü_Æ£¹‰²ºÆ†%‰pÃŒÎÒ}‡› ÇTáæ±mÔ+?ø§VÎÁ׌´ƒ{õ2ÛŸRt5;B:o9gHK6—K>þw Á†›ÇÖ¥:(ÆäRÝ…m±&ŒÇ iªÞÆMã\Kø\RÁ0šOò)uóXÚ´¾¹>…ÿ+m)®âS‹ŠÆq¼’M ³Ù7ezø1r%·´o;•w¸_R錮nL2~Zç>çÇÇ"ýØ›ÇÎÐFÈÉ›2º&ºnÍ…ÿMú(m`íܰ6YÝy#s¿÷òªÜÈIr±›û´Ç:¼XîêõF›b¸•øïÀ‚×âS¶÷”†œKðñ¥w%ÿžÆ•ë¾S¸†›ÕÖÏôóåä‘\Lˆl¶­l|»n øgú6~]} õLw¡ÊUï²[öÆÜ{üìö™ç±wÅ~ø†\v¯>B§îŽ«agΑëjù^¯Ë·:]ÒÒ‘ëF2âó»ó¯+IqúÞÝQ~ÉéG¬ëzùi¿¨äá-¹Üû7÷¾Ÿ»ÑÃ-Ð{íT4j^ÿ™#Þ5˜÷-;꺩ï}WMo ½¬úÞóyžŸƒ~7+;.:bÝš«Ž8wÍ­Gœ÷ªaGœßçCwÍ‘ëœkñHÞ‹·Üš ûŽ;­÷ÀÙk“ÃûO†átŽáh§ ønž¿FÌû&„׿=cü=n†ï™î»ò-–Ö*¯bYïâW—ÍÆtÇM½7“Ïù›§òӒżFx¾O‚lž“NLžµ²˜ç~óœzå–¯*[·nÂ)']uËßTšOž²XΔo%›[·`ùMJsËWR–ÏsWK}@ËkJ}@ó½!æf”Z‹gY­º=¿WµÍ«ƒóþhsè&œzO äýêö[òüAÞù™ÓE,õÉ;ßW]ÀJ~7ðÎû™Ñ·ä5Œyç½OkSË+¤éÖZö:Lº¥–½Î¡.{eÏ•ÐT^ómL7ÑÔC¤j*{Þ„îŸe¯ÏÍ;Ï¡ÀCä†ó:«ÄüË{sÙú}•˜ãê˜9W§ìuó>#M,÷éX Þ**žý[Ï‘ÔW =¨}ƒÊzë¥î±_·f·vƒüèÛº¿6vƒŸ åhðûRw׆ Ùà÷½|ü7ØL°3¼ö¹=?\h¼ÁïNñ…ü‹/Ôp¥qDµ…ñSFJ ϲuËó·ñ¯÷Å27é :~•ò^’ °zÌ÷ÞT›Š˜×¦"浩ˆym*b^›Š˜×¦"浩ˆym*bÎK—‰9/]&æ¼t™ØdãÙ|âžMãîÁO·í—½k’Ð`îÚÒߺc£˜c¶³•“åQï¯jyæ¸cÍ|È)«—™K%õpÏáˆã‹í®9-¡½1ÎÓkî瓃g½.ÃŽó¸©ìÊŸ²ð<4€d©yÁ©¹·çƲ”{2ØQwÝ×Zx=µé®wÓóŸuAþÝžv|N¹Ó;näts_¯soމžQÖÝãxªÔê|¼¯2X«qͨ´?ÛÜçÄ*bM[7bsûéˆ?)~ëi£êœ¯€Œª£'qwÞ¨e]Ò-&ÝÚ•àcxúaur¾VxægFµ‡Ø!vSˆ¡×ã4w9MÌå41—ÓÄÈÙjØb×r;I5|²·&vm¨Á½31r6oÉiæKû !<Š˜·Ñž…]Ý£ ßvå¨+yc5mko’Á7…Á7¶Wµ7¥oVGùè ]“ÑÉþ6¼#_ޕíN»ÓôF\<“wמ…k¿7:žè€Â®u·óãâ7|oôWÕ·tVÌ;iUóL÷yòØy{$O!=Gåñ=ºõ{£?úõ^òßïã7|vôúðöÎô»?}UÈwx÷;%§ãGXZKÇFwß9 Tçú†ñÑÆŒþ“fᣣÏéÚ÷9×êX°õÜýü»íÖ«m »ëFŸÏ]YúžÓ/Ò>mÿ>w¾ÿ›_ó»Íík‘AÕ“D=ٺ画ÜucváÞú'vçŒY´6gôÅ!~ñ[UKß 9Õ¯5Є¥º½(ÕÒˆ(Ñ’€bÕSÛi£3Áiã|èü¦jezL¯©ê¬üÂç¾ñ¥Ïbs€ý‚ž3ük|8ÝJ¼<ÉodêßIš,·RGn-4ˆ„%S.-=ºzŸn,Ÿx¯ÓÕž?ÍwÑí)nn½éé-]h?­Ø ~Кy…x˜¹QZo[ÿùé-'–uւÆM>ù°’á]ëf¢MOó­§Oe‡Lë’®ûÎÜQ]^ž—|­m]ÌÛ¨3Àg[]|5G3á0IÑœQäŸ@žvòßçUžÂ¨óÑŸJî›ØIñ„aNÇìœAmê;Ðø`ž qírÆú;ÚÔx¯Ço½|ïüZ– ¹Ó¡”:…:fꌃ8k–ÞÍî8Ìî(êøµ¬-> ^Oí¬õš¡¤ð´ïŽ:ßs¸c;®˜SeÓ³ÿ¡¶:í`ë}§z| Ü„v$sÒ­YÕAñZC½>ø™°×¼Ï¯ßä+ß´€˜?Kòcá#l'“OŸê4nÅÔ_ÑÍ̼ »pmݨÆ{5ÈG¹þ­o®KvöŸÇý}<ÌøïÂ7Š|.}ú§ =çYÃ>"kMŠ\´JF] ±.÷gí~#=ÌOÿ´¢-1 êîÆd£óŽwj‹²*°¼cIJ«"ZŸæ}þyWÞ™L^(¿6/þ>mŽß'\lùrR_ÎuF‡æ$ª’mírM Òè›-¯T§ 7YÖXò¼–̪Šr‘sáü…Ï›“jO>·º½p¥¼‹™äïÂðlå?ëÓ?-ÃÿE-®P[…/Ák`î™í;Ãb–áfâ^õéŸö{ÜÛ5ñ»Üw”Åܨ„ÙÎÚƒÙ^õw…§}fTã¤u==“Ð*š+Ý>4‘ÂË‘*Ô5‚tUGßÿsi®1‘Þ›ù~9[ù¾‡øWøþºÐ_ZxCÁ)#÷áàmôïGó+.Y¸>ÿNaÍ+?™]ÈÛAáíè‘»ÇÚ®s?=ƒº ]û˜…]·Vжõdpªpó•ì+´Z¶æìÏû/W:o,W9ÍŽè=0º›£÷Ž&‹“'\óer©­yÒ9=¿™ô2î/ô¾¶ÿu‘7z*Bw9Oe}ÞE­kø¾‹~Ÿ³ðú‚)êž~Ž÷´4·›;Ù¿ÖìshfÐî¼ .ÚºX{<¾Š~ù¤·O'†÷xkï…Ÿ&o ù>(—vËó[¬»Þ|çÑ_ºõzó^¾ÛÈó9òÜBl±»ù>“·è~¢úA꺙œpãÞÁ7ü·W›ºü$ÄâÓáqpWiw6Ü«B±÷‘ÿ¾¥/šà£ ¹¼ÇêþUÞR˼½‹·h¨ÿoä¹&^Ü-ø47†Op'™Ö~Üùhƒ*wÌKMKFŒ‘œ/׺oƒ[ñ&Œ|_Uîð‰þž÷Êïfn{Š] GíËìT]~ÐÏ6܈0T;Ê„Y]ÉåÇ}7ÿŠ7§;jïŚ㻩€>JGËöJšZI—×…QlÓˆg«îdÙÿês2r°G#FÂÄçã‹}²+?[ÔÒuAÖY%ôô”€Ð²\ñ-×<Ÿ‹ÛÙÿ”?:Ý©‡hÜéÞKµîÌïõö?¾Øò·…ü¥ãþ©à”cÇH\Œ)Ç9š»Ñç°5{»rF´*Ê-º„o?¼Ù}¢³÷vèíÔ!íÓ/ç*.Q­y}¬¾M®¾ÛUßD«¯<%]Ë6Þ¬ýÑãnšþ#iéßšëkä®ejL25jf󉱣òݛռA¦/¹Ÿ›º×¸Znr·4Ý!´KîªÊ)¸›=pŸóP fVJ£Ïï:=*ÒUó–ΔÃ@+6ôX\‚Ýí éö»ûôÛR^Ü> å%ÚÞ*ºõ…öÞ*œÿ–ª‡6nÁC[~ƒ“všÍ¡îx§)ŸåðÞ …ë¥#Ÿåpür¤º¤ÂõÒOsÈÿ©‰Å Õ”¦Ë÷HÈ}N~B³˜÷õ¡š Þ»›0!xw+xN®wEï9ê‹Ä\ïMÌë) y­VóÎó|„Ì‹Æk"&®Wzs,y#å+yþØ—ˆåý.y>’n å _Töþÿüž;P¹1ø=zMï@ªï„ûãqü/®Y-ÿºvŽÎegU²áL,<#wÔ•]Qq4›½~L0£=­;°·vœnEo}åà­h^´¯ÛVråâ– ×.ýºïEIs§FÑ¿|³³3ó¹ÜyR륾wšeøOûúøK盦ªÿ–k>>zßÛ«hnðÜîÇ丛ø•ÜðçvqsØõ |†<·ÊíïœSƒþW5î8+‹èö£×½W|poR¿#ŠÃ7{¿£Ã µ˜ø(>ýÞ:l̼½Óø>eø>“Ö“ÏH{×Õ-lfªe㡾Šz}=y!³ít´ª¾ž¸³{.%1Ïi$ö9ÛgäëÔPÜ4²´Ò¢{´+;DZû3V:¿Ò²Ñ)ouM£èaqäu ¿j7@ù<ü›±s’+îx-ñ•Í':qžÝGh—÷käm!¯| üÍØùhÈI$“<Õ…ù[Ë!䏨鹤9ìî&I8ÍŽÙS9ÌîZÐskzwÉ)æ\.³h­p›eUš¯{ý²îäè°»}sÖb鎰o¦¡—WµMjÝmðù¼[õ½»qÒ˹jïüð6%æªÑ9ØÔ9x@IuÏ*/øe\íw·ÌU­È…“f½qnYõ­°ùÖîì•ô÷<€×ü±iŸS?ÓNp¼øÜŸfî¥koÎþõÕùpÕªy®îTñ* fkó;Õ,N6J9.xÈ øº—ïâù¸ì¾àwÔóPƒö^ð¯ãý‚µ=÷W;ÎsÁ ÖöhZž{)’l›Oû.Õ$'Ÿ×¼ƒ+s›ípùiïÜáÉp ù®}˜bRáÝ™µ1p¥¿öMÇMøšÿQ0΋FÃ_™~þ„xU;Š‹œ¿ÝæÐWÐíµ…8w݆’Úžßìs ùÖÍ,2}…™îsAæƒÈÖ¥Ï/äγËa&í­‹‰ '1·Ê[œ¥[ÖÇG]år—£(ïÖW>_=¸%ý&âMoç|8vå{5·µ2µ¢J8]{jëÀÊŸÉì,ÂÖ§šû¡VCcçD7ÖÏXÆè=XW1:À×%ÆÄꎶ¶ºÎ¨m°Z„0"0ÍXVÚß}œÝi½¡I™ÜãüÎ}í`£ ç«ÆËR(¿uý¼oEÃGøÑ@çLûáï?1ã¹s:šb·Àҗݪ=1æš²x·i'Ÿ|Ÿþý'„ÕÎoM¾´[ŠÏI\4¦^ù.LZÛ˜HÕ¶Kpë ºI¦‘¤¬”s­+î- ^«Æ¢*ú÷ŸèÇ]»œ®XI˜h,üÀ­‹¿©™u~~?¾#îŸwEÕÞ?å1ÞD +é¶ÐÎÕ&Í3Ò™™·8z^ImÇ»NÞãÚo¶ž’+“gßQRû¶„½kÕ;ß‹ë>3úRyí€Ç1aßý~L½;¨C»ïŸ~Öµïî¥Ä'ÀˆW­ÿaqúÜä«z~8铘®ø•ªF—ãËrló9¾\¼ê“Ñ5%ÝåoQçž1£”skWtà›ºÖ¨Lç,¹º¾ärìêùUÉ>Q>û±¹ëÏyü}<‰ùãY¹‹‹ÔuŸŽ&OަKçæ.þ%1lÄUܨ¾•t]Üä7óÿ#ÑAÒ¶½µI‰¸}¯ÑW|XŸ¡ôÖكɾi¼&í06Kmƒõx0ôølåõJÙk^÷ óÖéu´Ë¤•aý§àçéF‹éþ˜z9C¹ÛG"æX'np“öYŠt3Á‡RSﳕ».f»ç¦ÚöSá™OÉ»†p÷·ÖäŽ^Ïm_V›ÄQäÞ—úÂCVqT]W4Åß¿¦vþÓ³oƒ‹Ç«òvWI†ç]†nîí_+\{þè+Å#‡ÐîS½ñµªŽküõâNÓœÉ4qg{GÎèõò©ï»Ðƒ™}6]ë̿͜ñÛ§÷ʹMyØ¡.¾ÓòþŽËùæh¸¤UÍ­iš/µ»˜@‡LPŸ_¿aatjš›™NôÀqKͪóo˜huÞ¶¶}pî`n¾M j÷¸Ê(+oÞv¼îq¼7$6;ö™Ñ‘H`žšÕñQVþÌÙU²x(QŒ+—ÃÜ÷•cqœã’hÁ¨çØœ‚sQÏ¢ÜÜì݇Yoà¶â3f\«ruhÅîìó‹jý^.ãí â Ä›‰ŸMo@k˜Óå÷zÃÌrÍ'.=i£BâKˆ/%÷…äž[Bm`ní­ÚIÒÜJõ ô¶ÝÞx«ù¿œùß´]{ö.¼#0PÌ×ùø"ÝçQ×a3gî6jæÉßRðhéoÄn±}èäp~3øÈbÎÜ1Ù•~[޲žò7}ÞÁŒ˜ºuÁ2%£“g÷Êaoç¥%Ýy“÷ŒnÎÒ7zø-â.ž“Ù•î¾Û±+3L­Ù¯îJ6žôäñËpZ é6_²¾¡Ï×_Ï}3y&Áã¨÷^{¹3{0x¹ ¾Ý‚7H§ÁÄLý@‚µs?¥^“ÜÄòû©×71W_"o›îÖ™H÷ÊáwóÎkri·Ë‰ÝíbøíÆòóµsìng¯¦;–¾‹ÛrÀ…QÖÓßàðþd~¥ø*y)Ç®tÞéš»óН\ r/µŸÇ{üÏn/¾²kq¢r-{§'ÎÇÛêXÚvM²2ºÑû°ŒÇÀR8ÙóŸÊá‰ÊX°f¶D•3¢µw"æ9ÙÉZ5Ê{LœµÛåÉÆdmûìùS#Æÿ½§—_ S÷Ñù—’¿«îô"ýõëû€ë”·†Sî[7‰å“zVrüˆª–ÿócþn§?¼n©¨ffÏé>Ê£@®' þyÔLJôêMð¬ãÑ‘Ã-`ƒ³ÖÅ\ëL\N”3^»½ò›ö^­NëÑé]ê­©å{½š›ˆ{¥ïÔÿ@¸™¬8%ættÖµ¢«ï]Ö ôrå"Äô]wP8‰ÜíèÿlÜú?Ðÿë”îGáØ¶é^µ§ÇøeøOóøÚûç1rý˜Ë6Õ{ïéhg [jî ÀKÒÂÇwßC¾tÛºßy{¯Î²¼|´ão¹^ÛP~_Œ‡0š÷û"_†ó Me¸¡¾3ØÎÕjr8Lfb¹çiÚÜšà$xËK‚¾›|}¥þ¬ÏWSÿäI,½é%†5åó÷[].wû;0^¨Ý}?1ç0«ãÁ9ó¢¬gGó¼X»H ›Û[¦¾c¦¥Š+ª^83Þ¦¼F⪞küímNÐìæŽzæÅõzgáiç ¿ü4|+m¯_h—ÍÅ-ý\¼Ÿ÷æè’%oŠÖƒ7uÕýüËîBWÁì {޲woîŠnê}×lï~º ËÌÙ»èvÝöÍCJ—A“×å{‹Õ7ÏnÁ3»êÞ /§år»í¶{=rÝÀ61A:›[OúN¡îq`ⵋ§X›]µøsúžø7Û«Ù\?Ò‹R½hGí#xÚ™ Œ _×ê/ÄâTtÖ¨›™Í/ƒøèìÃã܆ø„è‹iɘqí$€ OšüŽæ4·Í¾É½Å¤»â¹Õàw¿ÛÁm^g›ý”k”xÿXf‡ÿX^£Dùbï=Ø|Ûmóñþõá&¥½’â4é(GlœCØó‡^×ëÕìG8ì€G½ŸÎÄ»ŽÅF{6tÝË™y1½;jp/Û›¿ÝËôËïå£ á[k:ò黿±Me{„çv“©Ö3¦’ܻɂ«²P¢{HÊ™£4*¢†i[jà$w³-˜úç7n^ŒÏ%{SÐ-ÿ^‡LT ÕÒëvT´'À7{ÉùãÀWA®š4·’"r|.ö¢Œ &½­ŸüÉ“W’ ¶CûY±ƒˆ]OLz^Ésˆ¡Fމ|£‘/í¯ä¹Än%¶ud”3†7Æ5Љ9¯¸I1ßÒÆBo¬0šØ6§wå¼Ú<*Ga 1<;Jû« \xúðÞ±ÖÙÿF7AÿWØ÷Rû^d߯ÿžþ/¤úo|˜ë¿Á߯·}ÏŒ<²wäï»­ÈYÆÑõtMc¿ÙØeˈ¶éïjì ¯¯À>õ·nô½—:b~Ï MÄ^?^(DÞ‡lLÚ"©î¾ô½"<üJkÁƸEûúðYé=É[Ž÷‚ÇŠƒvŠnàvн±{kϤwss{LHÐø”Š´ø—c-Æ=‹Ì‹ÎXŽã"°¿­e1µ axøµt-GwGHfÄ:F‡Ü©ZvïFé>¸Ý¸gîµµo’‘h’`IoÎ켯Çzxf/Þëᙽˆ'b4íäë"9ˆ˜nÜšwf—n±]wßßâxfOrÃdï±?kß™Ý(ïº_j7ZÅf/¢Ùs³íE§Ãgö"½aݤÝh{ ßÞºWznŒþߨ¿Öâ~oníoPÜÅV…ØŠ[bóBljˆ±›fìѽz“çù=´XsŸ…fÕw+z¤Þ?”ô©R½]½óü<óÎó3àÑ{®ÝÅäð&XcŸ²€—ÓÎдŸÙmà<ã7H{ïÐÓa.|Íx\Íü/ò¿ÿuÞÂô÷VV×BÞŸ6Ö7ߺ¹â~lëBSG\…Cáˆ.¼i‹ò\˜Aø¿óœ ?‹×ÝMÿÆD;WåDÎCov’Go‚§Ýh-9øûZÇÛèŸØÝ?é#عDÐßÂÐÕò¾(¸÷8ÿt :¹]\…LÓØÌ€›“W¾&>¸ü}XÒΜ™·ïß©¦rG66Wë˜û¾a}’&ðî>©éMÞø¹E§Ylƒ‰ðhWß?·ò)ÇÌóëfÓÌç•7ŒãNZã{3Ëß›Õ-n׬ټkì|Ê[„ç$˜¹ÕýÚô]Ê»û¾+Ì'½öó OAßO¥ï÷ ø‡CSãHš»¯÷¿‚§€"ž‰NîV¬Ùiê>îù;ZÄßxÍ1žk[­ŸÄ:ûyMðüE}?ñ["NÀÄoFY3Üm´wŽ{ú:Óq„®€g‚/1Qîª[öøoмi¾Û—é­ñÑð½yVÚ)(8twžSæE×ßT¥ÏÝÅuÈfØôÙã[éµ.ö$`vÿ ÕÉîí¥ím#K›M.f³" ŒÀ¤”÷ß°­vØVý߯&v†àѦ;‘yëÄ¥UìÂÞ`·!5ãü«ux¢Y#=÷ÝójßÎt|‡+m^µ®<Ÿy}óªTçUo•Ó˜É{Õ&ýÅ—¢å:yç¾ÿlÏ=>©§ç‡OêÏL3jݾ,ÆÆ»Êû†÷µ†_eÏ)ˆ¤Å¸)`æk 3Û^Û~‘×'aWì²]!ïY»q猪W£9O÷#yå‡mÒ—‚[Ú}÷2qøÜ<Äê«tú˜Á¢x}[sžÃìÊÿ•]±®[š‡ùéÆÈ‹ØsØÌ|#ÿoÒ—<<Ê:æØ'wt{÷Ö¯«àxÛ=®Üýý}úÙ³åÅÈÎw{:Ýç ]¹»»÷z×0¸Óá³ü`§ß޹à^4 Ï$Ã1~§ËWØîþÙ°Ó=§“‘¶ ûaò2NÖÝïyd.ú¯=»ßC ÝûŒ¶ŒÑ4 ‘Ód×½5pÕÿ5?\÷ËóOíþdzN—u£…Fszå-Nljú=ó¹4lÕ-»€7 ¼©Í¦ÞžuzÑÂ×n¶¿9DCí}*Ô¼ œtÖMÓ‹œ¶í;»éû˜$&Ñ~zö½ J^ð<îdGyî1¯}LÌëF*–ò–ˆí´&On»õSÎØÃk±ÓÄñ3;í¯AÏJf§-*Êa§¹Úû`ØiÒHù÷6Úí´i[–ZŸ;MôÞipUýN3µ‰Ò¶%ÊšûKz$þÉn<]äpçwñóLçwjSûÊ{oc¶fx°Zg‡ý5¶,?Nmæ†Ú]K3µœßØÑ¶l[-FãC÷ÜÃÐã9­…{~²ººÑõ_½av·&£ Ö8^w­µIè–õ›²í|i­‰)èñOÎ>ÍizÉ/€¸Æo‰v¬©5Ú¿¨9¹"­ƒÒ}2Kkƒ­¼SfDYóÖ¬©†Öƒî•ÓVz°&£¯dkâ†L¿„½Oÿ'§ŸPˆ†»~¶öËÜW«Ž.S^ ýìêßÞ[ó;ÕnZͦ­k|í;^è˜7è~–¿kPÏRšÎ{mÁážçéFþsôf„Ýß‚îÎî;u÷÷Vø{®åkRͰFëC•{îò÷\ùIÜ}ùR¸ç2#~^È+n씯±j_ÄNj½w¾ÇaGö»³?Rêù;êù$õÔç¹Aól‹Ù{¦ö\Ü¿v·úèy¸B8cÚýól´ÆÂ™ëö¦Ò=[óà3;®É‘ªýâ:kUápeäw?Ä«£×4„“ìoNðp;gmKР®—‰Î”â*z„1Õõt =íð°ô¹ÀxŽûÐÝû”lúì¹gpÕ¼o2¸òoiú/e¶Ýý¿1ss3=÷ýëŽÝpøKèÿû6ã3vó36ÆN{äêAÀ“z® žoo¯ÇjË|§¸Nâ,þ`,ØZÏ!è®mVM®‚6ˆÑù³uÉ(czøG©ëæ­uM.jÃZpU ª^˜ä¥ˆ « ¿Ñê™ s¼PœãÞž­nLµ9]Â}Ms{œºäŸÔÔÕJ]?¿c˜×Ìvû9iHsãì=îŸlPئƚ•KUÙ; p˜mmº»›ž‰ksö [k;ÔÍ™)Me™ór½°\GÞaM]?e¿xk]èÙÅ-·Œýjë’§YS×Ǩë]¿ÝdžÌÌ®å«pzÄ/ØDÕµ;S–G¸Êx =TyÄ9<¿£‹¤7+¿×Ãeããt‚rø¿x¹Ì2˜ü>åãöÞ_æó¥a¯ ³ú²0«/w}¼8Oó€ïVú°ÿ“}`ëÃO…Úw†ÚóþDò=×P® e¿þ²Â;†ÛMQ𠾩¨Á4ß«‰=ÂóPgô­ ‡=¨á:«A÷‰¦Ù÷ÖqA;Šî–­A:<àïi\šžro Å}¸(‰ž[gËJˆóÒà,ꑇS¸wMí›ëQ’gZÙ˜BÖOQ\Åv7ÙÕ#Ïþ¦ÝG›Þö`=›AWÕcw±<ýGG² Ä#ö®ƒñÙd v`À@ÁÍíKŠ+S‰¦L5¡$a\ÐÒ)%Ù² G›-K„=/^ÎuŒÖ˜îÄÃÞU×TãkÅë?¾g¥­1ì]Þ Ó¢Ùe£Æ›+¨6¾ë3ÞëµË¦¡á1ì]½àÀ÷k—§ôÛ¤/è§ŸzXŸ|Ñw·Ýv>è­Ÿ¼Ï3âú\‰Õy‰¡Tçý8æàÓzßçÀ¤åþß9 ‡õ9€Ë°o¬6ž4m¹qHGrD…`ó¢yÇúànÀ Hïa„Ó8éS`\©õUùø „]Iÿê3ÐíÕ¼:æ&ân?sÙ!^o=Ç_¸´ ¦³/ûboÏ;}ǶK7ñ1]м©Fò°;8dü£wâø/y'yH—ÂôÆÍfè&Ÿë Nƺ±ð1ô=nóèÍú£ù?Áò‘§o‹›¢ÃËQõ˜†Œ·W´”W·{í£ká}KóAð:œ>nA>þ:gèž ¯ÃÌŸ!)öù1C‡nš!îS&´¦­%=BAä±’‚ÐÃ3ÄÜø’*|œö8úÄ ½—Za³±ból¬àÿ*ò´[žöÍyÚù¿hȉ™üúŽ™¼¨¥ã‰™$æ½2ó~e™Õ»mVï¿gVãâ0«šÏçä·X#T,5›bã†xàtðœ®î›¯Õ½à–ý(Ÿ«(v\çκ!3¦ßQy£n#±8 ä“BèU¼1úÚ.‰º¢7¹[¾ñÁ#l,Ý1ùøÚ8z>`Ä—t5.tŒ_ssá-Ø#};ÿuñ¹vqj'ÍÝNßúŸõ×êpÝe»¨\..ÉIzsZüÚ•“C~oN‹û»râ%¥7§½™tåÔììÍiïP]9¡öæ´÷½®œ8\ëÍio¨»s^BoN8õœðzsÂ9¨ç„óЛŽA='\ŠÞœðê9ábôæ„+Й“û¡Þœð·ê9áõæä4VÏ ç¨7'¼¶zNÐHoNË1èÊɳ7'œ¿zN¸N½9í-¨+'œ¨Þœð!ë9áNõæ„›YÏIºÞœÆàMwNpKoN8ªõœ†³Õ“Ór\wç,ŠÄÓ“Óñ‚»öt¿m9 ·ºž|Õ›~w=gÿí9-?¼+ç€í9áô×sò 7'ÚõœÀÍÞœhÔs⇥w>Ñ`¨çÄNoh@ÔsâQ¥7'Zõœx èÍiµ.ºr¢×›Ój¾tåD³¬7§Õ>êʉ?—ÞœhYÕs"ÕÑ›ÓjauåÄKoN«µÖ•,½9­&]WNf½7§Õ#ìÊÉlôîi«µØ•SNöæDû²ŽtÚ›ÓjgvåÄKGoN«ûÝ•“ÛPï Xó®œHw÷Öiuÿ»rⵡ7§õYЕS ý{÷´õàЕï½9éA='ÞzsÖw!9Þ>7Ö³HWNiìî­¬PÏ &ëÍiýðtå+õΚõÇÔ•¬Ô['yê9Á~½3`}Yuåd÷æ´^½ºr¶='¾Üê9Á=½9ñWωˆÞœºÊîÉ &ëÍi=Ûuåd¯öæ´^ »rNßž’õœ3¶ç´'»r‚Ézsr®çÏ÷æ´žz»r‚™{sZOE]9ñ€Ð»×¬—䮜Рzs:Ÿç»sÊiÏÞÞHw~ON¹ƒÙ›a='vH{s‚ê9ñ¦Ð›³~» 'žzg@Zß{r¢ñß[gýžKN¼ ôÖ‰÷·zNö½9áfÕs.ØÞîõœÇn¯Óò“vçŒÅ…í­ÓiCìÎùÐ}:6½ŠÝ9º5ǛﹱÓIèÉÙsg-ÊAoÎ^<}oÎÞ[&þzs‚›ë9шï͉FU='ºó½9Ñ÷¬çDß¼7'°õœè÷æ”o…=9ÑEïÍ)ß {r¢±Þ›üWÏ)OŠ{s‚ÿê9©¿7'¸ž“û^oNî'õœò©º7'÷ºzNôÌ{÷´¼ ÔsmŽÞ:SÓîœhxôÖùg›w.ü¥Þ:¹Å×sò¬7'ܜøc½9#ÃîœxšíÉéütåü‹í9­7Š®¹1z'=s#Þvýþ‰¢ÞœŽÚ•oê½9-²+ç'¶ç´œ¼®œF7圎¿Ö•ó®í3`õÜ»öú÷½9ë\ r¢ß›S*Ù{r‚GzsÂ]¯åܘ£™æ^YìÍé´iœ÷*“ƒÜõ¶&›€zÞùè,ÔsðÎç@¯¢žƒw> õ¼ó9à¯×sðNA“¾{=ï|ô¤ê9xçkE¼žƒw>سžƒw>عžƒw>˜¼žƒw>·˜zÞùÜxê9xçsp?«çàÏÁ]®žƒw>wÒzËi±9¸[×sXîÍ_¡žƒw>زžÃbN›ŽI=ï|¸+õ¼ó9àÕsðÎç€oTÏÁ;ŸÃð^»s8y&üÏzÞ¹Æ jwóÎçàWÏaot6}ë9xçsàI¢žƒw>|zçÉ䀓PÏá¼<šhò×sðÎçÀsH=‡õ"bsàQ¾žƒw>þçë9xçsࣾžƒw>íë9xçsÀ§®çàÏ?¦žÃù“29ÀØõ¼ó9ÀÔõ¼ó9ÀÃõ¼ó9À¿õ¼ó9>¾9ï|9—Ú“ƒw>‡ÜÿìÉÁ;ŸC å{rðÎç€gUÏaùW6:rõ¼ó9àÅ×sðÎç@ÿµžƒw>LJ7çàÏÆ¯ç°Øßæ¿=9xçsÈÅÓž¼ó9äbrOÞùr µ'ï|9Ú“ƒw>‡ÜñïÉÁ;ŸC®Ì÷äàÏñ‹›sðÎçxÏæ¼ó9~nsÞùrf·'ï|Ž_Øœƒw>ÇÏoÎÁ;Ÿm‚z«Y`süÌæ¼ó9ШçpZD&GÏ]Ǽó9ÐxªçàÏÑsû1ï|t ê9œF”ÉŽA=‡ÓÙ29znHæÏ¶Y=ï|ôâê9¬G$›£ç>dÞùh"Ôs8½9“Ãh÷uçàÏÑs¯2ï|´ê9¬&ͦA=‡Õ:°9ÐJ¨ç° 6Ç+6çà϶B=ï|£ÚƒwîÆf¸69 Ä›w>ÜšzÞùZ¹ÏÖkµz¥¶ø6õ:xçsÀ¯©ç°º¡¶VôHëµZR›-€zÞùèÔsðÎç@¿¡žƒw>‡ÑÀíÎÁ;ŸŠz«Oas\¼9ï|tê9¬^ƒÍ¦B=‡ÕZ°9ÐP¨ç°Ú 6ò6õ¼ó9ð]RÏÁ;Ÿ¿'õ¼ó9zî¸æÏÁ]¾žƒw>÷þzÞùpwê9xçsôÜzÍ;Ÿ^W=ï|øoõ¼ó9àÕÕsðÎç€RÏá¼t™=·góÎçè¹=›w>¼ÅzÞùð!ë9xçsÀ³¬çàϳžƒw><äzÞùðÏë9xçsÀk¯çàÏW½žÃrØmxøõ¼ó9zîåæÏn@=ï|Žž{¹yçsÀa¯ç°Üv›£ç^nÞù=÷róÎç@÷£žƒw>‡!ºtçàÏNI=ï\ŽèŸîËaÞùRbÜ“ƒwSB«cJÞù:à™×ë°üs[¡z6fë€K_¯ÃrìM†gÖ]‡yçsà«^ï|­pðë9,7ßÖ?­^+ï|øhõ¼óµÂu¯×j9ð6üþzËû·9àÙ×sXþ½Í¿žÃòúmxôõ–_osôpÌ;Ÿ£‡s`ÞùùÀ³W=ï|=weóÎ×Ñsç6ï|=wnóÎçè¹ šw¾Ön™yçsôp_œ·â‹w!‡á«¡/gßë‚°üøÙð¦¦Ë·!‹Ïà‡êÏ®Ã(_ºub씥´%ftE޽¥àW)’î\t1Á_q©PiBô£.ŠþŠùUY>ØÁ®¦F]œt%l”‚™TO¥¤¦kzã‡ã\M¸•Ô‹ü†Uã27‰Ÿ'/Mº ê&Õ¤›·n\MÒ$•†Z“ö¡î˜ýÄ1Òm¹Ÿ8¼ÊÑO7ñ+ú½„oåê'/|âöƒo“«¼0]3 ¬Ù –D_§™›6BšÑëâ®ÐŒ&³ü9F;s—QSm†ÂM«Î+·Èþ̼‰þGÅì—òŽNº_©† mõ×eM¬ÝþÚ š¯þBêè1½ÕÉR+SˆÍ£jHuA9r½Aqj ]æ’Ó‚êîÜ[è8hÑ{)0¶À„‰E»2á(ž ’#]?qMÈ1VÎ:¡8‚Â× ¥¨ûu&tr0—ÈÐ`# =ƒA ¸^Âu—CØ%&c{¢@lj X÷C`PèÇê)\‚`¬ØîPX+Œ–Ö0XéE˜<ÃPã)ÒŸá s¶Öp®I%ØôùȖèïƦÄ5b—„s2‚=T¢_#`2”PŒÉDã`$×Ù`$ü31 ³õîÇœ•˜ýØ9%˜¯ûÑÓ2s7š9(Sçh˜eXtû3?eú¸?è¶Ì®ÚŸþ—™ôý¹ä—©sØÓe®»û£4Zf.ÇЗ2[` ›¨Ì aó”™“1ô³B]c™— ›d,5W¨« ¥ˆ õŒãÚQ¡_ã`U¨ç¶P…Ýwu*('ÓÚ–ºýZݱ^X Êt_øËÇfóoÞcoä‰VYá·­q5Xïsú×~T—ÆKŸGÓuî4Ú«ë¡é?X÷:ü—âAsðëâŠ~êÏ+¢+±ÞdØn‹?#üq°¶šê<ø_-ÿ_eºtˆx»ªÿñ24Ѹ猘´ Ò%:˜ ÝMòÝøµ'(Ÿv÷¡Úù¢‡RsÌ*™wÍ­‰ÜâØá™ôÁ&²áØÑÙ2heN”¿?Õ3IÕÓIð+áìMb·ÃœÄ[6ßaÌz͇±‰Ðd>Œ»vÂ; nlBŽÃÞ÷ò°÷»éBÕ+q³ Ç̶³S •É%Ž1/3Eªb|®éˆb —Ã_Wr8j\%e7£¼7¿Ã¥k«ÞNÕ=N½œ*ætªðºz:M«’iÒ$Ðö›Æ[fg1ÐÃ4ñ>Ô³éÚšétƒY™'‚Y™Ž¾ <Ál[fa&ŠTG¨×êâBÚGÀ7„kz$[È#™ï<Õ— tÐÊH˜ÉvåJ˜æ]îÏŘ„ÙÜ7 Ô;›ú àªÙB êòl èa6Ú ÐÈlîú<‡ÍY`ÌaŽAsØz:‡š ì¥9ð Ìæ\f´@æ¢õX`ÎçÒ›ý˜Ë ¦@_çÑ;4<çqóD»oµ  5Üh)ÍC÷M‹£ØÊhA…ÆH‘>§¦HŽb:‹ôáh&·HýG3‡Ej<Þ@‘p4}+2_ó¹»Ù)r£cPÍ|ÞAóáôAk Ð]+‚ CQ¢ ék‰\ ¹+”¨g!¼Ç=YHŽu-ÂëK‰z‘£D?ÑóµäRb¾£7U¦Ÿ‹™{ÐÌbÐP™™Y ª(ӣŠ23w¼gPÌqè­”éëqpËÔ³^¦¶ãÑùÕ/S÷ñôŽå¾„»@…ù_¬U˜Û%ô4s± uÀ¾Š<½Q¡®à%V˜—„vT׉†rN­rN¤‡ÐÒ)Ü+ìïS˜Á hövv…9=…žTèë)ì•ê>…zèï)h76ÐßS©½ÚO!7°‡NåÖÒ@Nå–„å¾SáÌ60¿Ë˜éú½Œ7 ôcž®@¥ËРo`Ž—1oÐû—¡çÖ@N÷40w§èÿiBaÚ'§qj`_žÎNnEŸÎÝ¡y>¹o O§Ã{l`†–Ó£Fþ/ç^ÐHŸ–Ãíi¤WË™×Fú³œýÚÈN^Q#õ¯@c¡t(³‘ý|7ýFæâ 0F#sqoAƒg(¯ê?dÜD}gÒÓ&ê;|ÒDìLøÈMÌÂY`™&fç,ùî×®:k¢†I¢,yé¼)+¸„4¹¨ö„±Ôl1̘Â5@Ä"FsNâw–øzêÃS¤3¢ºŸ"ΪzòT!õñ©ÂêßSÅ­Õ|?Uš#šŸ§q{oœÃFOðÝUÔë§3gøŽX 6Kèÿ*æ\± }«„Þ¯b/#V±· ôë\f¡À\ËmÜp.„óp.|—s}.óU ç~+ž‡s¿åz:*»y™.ûé°ó`¢àBtì[!‡XÊo“×üÎÓœ¨ƒç½<®ð<ÇÂroQÖP‡ð‹"7QQí˜8Çj]¡6\-–&hµ˜}Údk´n…ˆÖP=næÖ,Žs®iq˜´£[Áq’Õ5ºy)óZñ04kuaÓü­•΃vÛZñwµÛÎ×E±ó¥· Ù:ìE)ç"®ôü«û+•ÿ[éÚêÕrð§}Ô\UÍbkû¬Ó…Qý\§9Q?×é:'±îœ¸²uÁÅÉz1¤TËz±©4sÏÔ]Kú™LyĆ~¦®ºw¡.Ú”JQO]¼P®‡ÔÅ ß×tá?k'qƒs»‰}‡s3£ì´Çò¼e£V‚„fÁyQõÄÅÑ”m¾žðÜE╟\¤½¤;G9öÔFádMùFöwÀšíè·pÜNà¶p±´¶Õ•‹÷p3Ħ}ű”®4';w3ú†¬Š.ÖO³´Iw>U´ir\É&Ü™û[€»Ù¸iÜ伫è[ýb7‰ç­mº1Îü,wì·¿gIûXý|–®·ÂšÏÒÞVߟ%MMÙ%ªZõ\¢¡ ¾D|:å¸Dy´‡/Ñ-[{ûie ÷lGG¹7³I¹¹lÖ=T½Ø ]ÕÍܬcfe³´õ5µ[Ø’pW·P#|Ù-üçö²åëq¯¶8û»TœdõêRÝó5c—i i¾/×K½¹L÷ý¿LZÚ_Ï6àÏ6Ìól¼óª:u$Z¶áÆúl]TÙ³µ£UÙ³¥>§ix¶X%š‚Ë¥Ö§Ê.³S•].4£Ê.ÿF\ÙåߨRÙs„wTÙsœE2}³ùÔ³çH«N={®ôŒ„ƒž«Ý«ªž+^Ÿ6ãsõ^Xø¹Š+|î‡\…[¾tC…ÏÓD»ðyz¡*ž'•Mëó¤’-Äý<í!É­RØ*U9]¶j7kb·~-®pë×ܾ¬V«»!yËeßF¹á›ßó…ÿ4ßÏrÒÖz¾øÞšœ+´/´÷®þ“&è ñ„ƒ¯sO¿’.±¶5ÄÕokp÷ ÖvwÉï¶mgZ>Ã=wo˜wmÎmÚYÚ§W½4ÎqÕKûïnéUó*©ž«ú«ÄøUÆ«ÅÒÒÖ»ZÌBõüjÝᄯƒ[(ñj©ºjC©ÞlWWµ¥¶‹Q-Ä´]líƒk´-5µ×èJ*ŒwØÚ×°A/ NØ/`c¡‚ö âÿBzÁ|¡Pƒ® /¤£¨W¼HùÔÕQ' ©/b“'äßó Wy;À<ÜäwÐGÉw°APߡۼ¶Ë‹éÉ—°•¶ôKØÂ å—°Ua„¼”½W`j_Êí¾À~x)×u]+w=š kné¶®êQ…™a£ûù½V˜^éZínañk5Ÿšª—‰V¢î¼L¼a“—i‹ê~ú2i”h3½|t\õËñ¼Þ3Ýïåê„*{¹.Áªì§´Ô÷ŸÒÅWÕý”¬æt§¶æt§*ÕÞÞ)EMmÙâF¨ÒWhW W½BèD›ù\?áF¼‚<1ù_ɬ¢ÚðJðóøJæ‚ëæu¼CÁü:ö)*ë×ÑEæí:jEí:rq¥¸NWNaÑëÁ®ÌßõÌpÂ<¿ŠmÏ•âUš;m¬W麩^½šú lÉWƒ¦¸Z¾¬_ o¯9:žˆ×íæ0ÛdLDõê’ïÊ¢ŸCCyö¸Ayêò ÂzÚÍ7?ijn¿J[絺Y¨s¯Õ=]z­¦LÛëµè)PÊkÙ~Ü^'7êÆër»:\¢,Ý:nÒ¯“N˜¦æuÒ+Ót½ž^°^/„¯Éy½pªvÀë¥#Dr£ü#Ü(SÕ£°¡ò¿AÛ@˜ñ 05ØšoÐÖT¿ß@ÿà8¿áçq_Þð›þ}Ÿî7Òuöý…}„ˆß(54íå7‰1©ÊÞ¤‰P7v íklÞ,UPÍí›…ê59?/ðÓT ªÿiØtâ-°žÁHoáúÄ xfÿM\¥P„¹‰½³onêÑÞ½‰÷((½•ÊNoåŒÀ¾x+×K,¼7\·Þ&F&ãm­qgßÖÚŽÀfÜLìü¥›÷mÚ¼êóÛÄ,Ô>»¡Î·39ÜÞ®m-üðvá[MäÛ¿×÷ö;è›u?ÑÖ¿Y¬ý{³áäwHRùmm–wH‰Cû옚§wêF#¼ôN]–´£ß)|¥}øN](4ýïŽÒn~'s:|—XU²ïÒ5@u¼‹­Äµà½®¹EøIóy‹6‚ê¹—¨âüŒnqªëgxŸ0?a_ÿ¬¸IÚpï>z7=OÀ¾·ÒÙûàV®Šp‘~ŽëlŸG¶ÀÏÃÄ/0¿?OŠ`©Û¸ÊÉÿf–ký{`5p­ø®Ä>ùEæƒè¿Hý%êþE®–pŽ~ åÆ}û%îb%úó^æˆký{Ù\ßßÇ~(Óï÷Ñ8Eïgr?,ƒ2óó~öF™ùù€¸FÂ%`®Ëì—À²(ÓŸ躯ýò0×ø°Õ¹Æ€úáÝÎ5«Âžº~ru¿ýUaßÝÎÞâê~;7‚ }¿M_aFn‡íÀÕýƒ((WèóéC…ú>ÈpÐø sÝnü» =ð!öWöQûàCà.®éÒu^óûapWõ3o äø0*— Ôÿaæ­^}˜yâºþa]ÝÕßÃhm þÿ*ÞOþUÿþyfiï*ZO~ÇRáR_>" í»h©ïÑÞWý¿l—¡_¦¯àÁ_TRu®V¿Ì.âÊ÷QæŒ+ßG©|x§©2Ý B‚år',\¬ÿй+ÿqæÔ¿_ýÞûû*a~>ÆLsuþ˜®ÔB:ç¶ ÇíãÜ“ žÓØ#¿*®›v¯¢U¤O¿ r†Ûö öj‰^|¢-ž‡O´9<øi‚à‘N,vªE€BV·÷'ä³D]ý„ð¸:úIé/«ÊOÑ%ÐΧ´ÍÕ½OÙÍéSñÍ)C–3~Mû\•üý¦¾_¾Òþú5©‘hÿýšX]š½OË}*ùô³ÝürE)¤ñ ÝHцý}ú“–ï·¯AYöôZûëRDÕžÿu)שO¿®K‚æìnÝÄ´oSˆR{å7¥î«ýù›RœÑüþ–*ÓÜÿ–”4§¿¥»µöñoT¹J}ÄÌü†9„õ!Mí÷߆•‚âÁosIïý6œ>c¿Í}€»ÁosŠ©÷wtÖDý{1fþ‡¹Ïý,ØO¿ ²-°§~W¬&ÍËgµ´_> Ž;ÀgÁƒì‹ßƒ½W?üȬ@?n"÷ßãª\ Ÿ¿‡ZX‰ý=ú ^ù}j(Pçï³/ ÙY=ÆiÉ Xã…? ß8EøµàHà °ÄP†þ}Aø‹°R`7}‘k¬¦/Ò÷"wŽ/ê½úñGÌ}‘~ü1˜‹ýôÇà¦"ûûK°6ŠôåO¸iÀvúú_d¯ý }ÇmÊŸˆƒ)àð§ÜŽJÌןR_‰yý3ö8éϸ<ÀÑü3ö1¬§/S¸é˰“àhþùñ| ÿ9÷š{ãϹ2‚Ÿþ\øJóõçÌK‰ýýìä2{ò/Ä6Öù‹‹Ý.Ìöˆ"ù-ráµÛ(JþšeIŸ6»t©N宀/M/±©+¢þÿ¥¶‰¶â_žwá/ÏÕ0ÚjÒmfªñÛ,óÞF¹åÐ/µ×VÀ ›L“óyжýŠt „*þJ49%¤£ÿ¥‹—ÐÌ_鶦Iùk]4•ë¯Ù*ð•9Ós‡ÿùþVoþ&ÛÕ·ÂV ’€{™Mf+Ÿ‚ ¤}ÿé`«7£-«éûU£Mt¯æA½¹WšÆÚŠ÷J×F=ùª*Ö¦ø*¨”-ûUãJ|•mWâ«âX«__ãÊ 'àkB_Úr_ÓÝG}ýÚ;ãÞ}íi”`{/'›n£ÒÎïoå«C½ÿ[]eµÅÿV·uÍçßêJ¡ºÿVú êÓ×Õ'm¹¯ë²¢Íù C[߈ÑÌÕl~ÑsÏx%v7Hg´ùýMØßí–î’çiìÁ2/·xÊ÷÷3î©Ö¸˶\©t[¸ììÍàßëò£ÙûG!3õòŸ˜'öÂ?é’¯­ÿOâ…j£þ“f\=¾OÕ ‘Ü'Ö€6ö}Ìø>ØÑ ŸûtÔ¾¸ŸÏ î~ñ@µîýlð Š´£âMmy7ˆ£ø¢¤o³yk3ëÉ">¶<žl¯Ð·t»ÆÌˤ-cé[³ÈÓ¼æ;Õ ¹ÑŒ¥ÐýEÔE|æXÁ7|$9M¤ w}”•#vÏ|£8~+ßöïä›»²XNai9Á/r×Ò=*Î VŽõKâí¨»¥#ÜÖf”ëfzwLòH´Äãï*†v=+½Éj¹Á¡ìZ-&CYÚLò‹\V•¥Q]–_ÉÆî8sãF"'‚‹}¥É.D͵˜»¦­ÃÖTG“î{“ù†£!½&í¹í'v–¦¢ŸÐðí|³ÿ4ýt •GÖ~♕ q—›uõÔ”5ƒ¦u‰woz ߪGh8~š<Îkºú ýÞÌ7œ(ÕÕt©«hü4ù¤W]ðþ!vCüô’¸ŸJÜ6„I’îsúK÷y¢Mn6šýDE<1TG=(t"ÿ†gƵ ü¤2äÓ)kÑDÓÑ"6˜f¼EWqíŒAR‚×Î$4w ßµìˆAšmºÁ`Rw°º*G–ƒQ1öŸI>Ý$ãgŠÑ¤ÒLjŠG‰;¡|ûÅu‰÷Ö ü¾uÓÐí6ÞtÈVØ?¾iëÛ §lïiÖú`vèÜô Kó–¡ÒHZb €ïá»é6ÁÍz3ß0«´ Æèö§­56v:ï'~¦¶×Xaƒ­|£˜*$Ó¶kÜŸ¶ý„RÌÆÈnPÌÝ?\ü$Ñœ4êƒØy«nš6i$h7µi“È»e›0›:bd¤4)ãö‹+‡cÙÝ•gõ0ñY­º™>Ìî»õÅû‹§§i'ß‹ªñaouý]ÜUëº#làÚ>ãµgµ½ÆÇÜ©ø •[ÀæKÒûd OÛ=#ØÖ9^— MÙx] TÏÁ5qþƒkܾEðˆ 9DQuæá%é·¢(ó!rA$.ë!bŸh_"î•öàÐ){öPæ,v¨0™æùPqs„fÕ N=ôЏòC¯ÐüY”虼‰v¹%ö ßN1˜‚«@zUÎ(n.%ÍèCqvŸ¦3}¨´œÕÿC…mÕ•‰Ï‰»0Qóå6ÑDm嘤«¨æ²XbB“5£šÍÉÒR¾:LWTmÒ)\¶èøT¶ŸNg³N×Ê!Ì-ß—3ØÀRv‰Çh󪞙t\6ôÊž¥k—̬˜c[á6IUå#N²ÔOu7‘JyŠÇ‹é¬î©=«î)—ª=RWÍï‘Ú«_¡pyÂ9íâ |+Êš•îÍæ¶©kO<±:îÞ8Q È¹b•«{sÁ;Ì1¨uc'q §‹óĉSçCĉ'sÓw.ž ^—ˆx »‰ ÄÑ`xpÆ1ìDPè1âÜ·Ã¥I®.â£ØLº&Å¥¨<êf— Ë ¥ÎjžY0%žŽ3¦h:ò;"¦{VhÛj6ˆ©*l±@w !÷cÅ¿¶;V¼Ca¦cåàNî~ýL\û±ŸqÛ6úìpðù®vmG[ßÂgÇùÞV š¼áf°HwB¡ÑEÚcš®EÂôêÈ"¡XMÑ"¦t»HzššEºthZ]W¶èº´šŒ­Œû‹aš™¨¿ÔÇÓmï-ÒÞÓ.Z|Bœ15utÆõn±¸µÚ‹Õud±: 9_¬½¡¹^üy«à·ú+H±ýq³ڃlj½¡JŽ¦Ðæ8N¬"!ëãt%S‹ïƒñŒö÷¬ÿÖã2W´7fæx!\Õs¼øpÚDÇ ½¨Žã¿98Ì—½çy¾}YâÚ&' oh:NæþÁœ,N˜¶ÀÉÂ…ä‘¢÷…S™vñÍDÓsÊáqݧ,rsÕÍnÅamÊrN„ëìO»pŠiªîqÊÕ…SÄeUNÑK]8…ë%]85æ(Æsé]8U(G]8lGN}}Ü…Sÿú/]X¦Ó€¦t™\ÜhÖ–i£hó-ÓŒkæ–½&®n™Sªãe?Œ3œÏm÷Ÿö6Ëð±þùÿ¨›wêxÞq¾Ó_ÜßQò¡k·¢òÙ]ëîÔ®ÚÓ?nÙ?¾¥cËå’W–—oéØr¡'ÍÞrÝQ4 Ë¥«¯iX.´¥[Æ ¡íÕ±¶Z\5€IÒùZñQË ;Ûµ®øEœáŒ¶d8c¥exiz~þ$½•åÝ©ryVn¼ ÖÜŠ|<]‘Í—îæ3n² xíqoÎ<(~s¦øöþÍ‹ìÍÛô"‘®×ùj=Ëfé¬z7ܲiÎ2ìÉU1ÛËžó/|£ÕÂÔù7ߌߜýì-8{eø×®PYÀ$YÀÈi Š±Ñ´Oy^\ËS^ì&-ë•eKwÍS^kù`‡û7ç>Åùk°¿¦ S„ àßl²7ÆŽ{ãךœÏ-÷æ5öÆh‡»7ö¥ï´îèÙB5º³wž†õí½†ë&èr “^³r /Z9†½!Î1L¬_> ¨ƒë uüµÕaüØßHq~”c¤ñqFvÄ9FÆÎmÐ79`L’ãNËa¼Øß±t•c„îSÊ1”UFϺ~\&n€r\öÝøíeàU·Õ†lP%i2”¦x>•᾿÷ìKðÞy#¤öÆ{#{Áõm‘½`gÍZ³_xÁdÔrÀ5â³é y-›Ú ?µÊ`úê³^põ>•H ¸–\l‹®â1Qö~ûZ·Çr¼ßÏbm˜æi±qH Ø;ÄþtæbÔÂ­Õøî2D-û[žƒ‘‡m1¸ëtޏÚ"¦™ÓcT*ØœtG¯ôBWGÅžéªc£pý_‰ÏÝÞ:uõs}¤"nÍô0¬Kªc`„C;˜(µ¢=È®¤®½\“Ùq(÷À.àWE.À¼ƒ/†J ïè3þ­ˆÑEsÁuõ0aÄÈ…ÿhØW(´p¯!Æ]è‹q…€AŒ» \§¨£È_¹¹Pçõ% D}}Í}ÁÅ0ȼc:¸Åè"/)ì$Ã9ókÒÍ=ÓÁ á³]nÛnÌž©ÌMYõÑó Û Ý~L¥Ô‹·fi´«‹I² eºZx‡"[ˆiÄ5.—æ.?øýem&ÔUÄ…#Xa£]8\2÷å¡7âzó%—¾Xi´›?ÕüPšð½Áe1zc°šE VcËm w~;x= ]ST£p òݪ{OÇ ±¯ótÞ¯ÎyS׺ÞÃý¡Wü–YŒ}sšÅ˜ÒÓ-Æí{Ý7'†N·Sbpè¸ÀãvwVÜ'#—‹z-"ö”¸7mŠ¡‹¯®¡¨$CÉÕñ9¦êþ†ª‚jšz†ë!ŠÆ8~šoóŸmƒ—]¿á†ùéâJí§‹I´ ‡¨ÝtÍítIËŨÍàl·{Ñ/"Æî…a‚N»ÔN]ì^fƒì^Ôˆ±{Q„ 3Åm‘˜Ó 5±y®·p«¸)]ëÞôΧ¹"¹ZPf"gƒ;/1êòóÉåRHŒíºÆ&ˆíêæ u0?‡âBÂ×AïãÙÔÂ$1Õü@æ !îšTƒ—Ý3hC3gÙæÁ}Jí^SjXg)µ¨ÐÔ²rU¬½€_{W´ö‚mí o­–Ý Xô¤ì^ó6_­ÆËJš•ùD©…ûü¼H÷Øü~÷ ÄìwϵV =€­Ã,³WPò˜¥bìît‡½‚§ éPcá{f„Çtp”¨‰½ÂÕ‰>qÅ{…º§+¹q†Ú§]÷Б‘²‚äôÔj”¿óM@÷ØÜ~srá R6'wl¿9¯´©gs¶dÞéêE6étò*›qºtµM7[g»Í5˜ç›h¶:€Ì2›ÿ…6Åà+®xL+›˜kì±A?‡ÙÉæ“K'Z¯p³Â]ÆsO^gùb—.W£²{ŸUA¿)¸£8ÑĘ|û êƒÙAìkS[åã®Rüʈ*-Q²õnt.GÊm6:—uUY.qùÑìÒ®9ê|·qà²ú˼°4„K.1æn¾ÅØ 2µ¦‹G&Ì¡G&ð—<í8È †gÄxdª¶ 2miârÑÓœ¡¹å6® ú1ÚÅÌ€ZúBS/»!)¸Ìý¬a ”4˜mn¥`9®€ÞpŸrËn´×$&Ë®R–Dâð…t7 ðÔýöBwÏo/x¼TÅö‚ECŒíÅúØ^ï w÷…;Èû‰¡Šb/¿âz"f’¾Pb®]ÇðSãïFöWC®?Ù n0+³°ÝèTö4܉²hÓÕ^ÀÐf×g/`¬×î€p2¸e/à[³Ìs”½`Zj/˜¥Ú &]’½`báe/˜eÐNö‚)ç^–½`þAïÙ ˜åµÌ:w¤ì¼¶]v=|—ÝôÌ)K§Ö nÛ\`²°ˆàd/ðÃý,{JD-+[9«l~?¿S‚ jSjð–ì 0›<{â¨Í/x¤6w`•Z«>^ ÝRË7˜Ú¦BíVöŒTÛ0à'dÙ n÷p²² ÍZ”A2Ù PjmW€a³̯»à› MЯ‰¥3¾«U r®u\ w#{ê®e…ûÆå×¾`§¿ÔÅÄ[Q $ÊO–”Ã8{Á%ª¶à&Ôv:üÆÚv†Õ#<{Áµ…‹wöu…Ú ˜¯µêáÀÕªçbÆ=:{«­6`öZ_Aôx Í^€÷ksÊe§¶‹¹ùÔêàTÛ܉¸”f/`Àӳ좂fmmÓÂ¹àŽ½à"Vë=÷²ÚŽâšVë·¶ZϸÄù]b_p§«u‘+(3{Á¯V+w‡ZϸÖ ×Ãââ¶è9ÎöÂŒûÀ n”p)³ ÔÚ Ðq A€›kóÁ}¯¶c¸Ö6 wÂZϸ"֗Ǧ@ó$½à[CwÜk²ÍÊ ®Ip̲\k[Îe­n Üñ³hÔ×å¾ãö\CÜ’jY¹[ã£${¨¶ ÐÈ­M0Œ¤ÚTq¯aîó5Ëõ¾Vw.®Ù .ÿµðjs€‹LöšÞD-ºvŸtz˜ªÜw±åÐ/Ñs£P¾DØ’¢7‰¾ÝÿDZ»öÚGuÆñMµ^.Hð²z[½#\g¨—¬õÂã$·x¡Š€j¸…û| p©Í0¼¾ÚÆGŸ¢–íiŠÏ:ÆU‡›X–ô›q|xa×T_€ákseXxåy‚î^˜x6‘r%žMäÙwö^HEì‘ Pü*å*¢û†ªá´˜B]§áb0k¸ÕÙK2;kX÷µ=LöÚÆ ¶j£r¸FÙ îƒ5 Ë^¬mB2Ö6ªUÂøZŒSsáä‹Þ×fŒUÛöÜË2<ÂŒL°1»D¡Cµ€øÁýï²8“@EL~ ;±™³¾‘Ó²u³šÆõ×ä”~­z‘BVƒ${ïÙjà\âžqf°ºBà˜BY@©5–Û°†ŽÀTœ½+Õr€æju€ ký&cíUeˆŽ»,NnC¹_õ$Üq”pıqÂÝ'–h®¢r•HL(œ`&Ü'qw‰¦#ú 7M\5'\;q£œpÙh‹¢G™HëFÛ5áúŠ£¡Dº¯ÚÈø#A70‘¶…¦%ázŒ£„;=nÐD:‘VÐBÂ%ÇH‰ôqR{!ÖÎé ù$â ˆï”H!Dø)Gƒ¬©t s%RîCóÝéD.V„à)†Û%ò|"Ô‡V%ê^ <œ3%ppÙ”HUèç¨~%rÆ!DšH"±œpõ„¦!z¸ l¨ä›p÷ÇT­‡ h­¢ž’HW;ÿ†ú~"1¡r42Ñ×L¤Ÿ($ŸÀ0ŒÁø‰t°…þѬF.û^ƒDšðæÐÕÖ•!‘^§î \¸˜ËD"MÝ,)ÉéšÓ Üš&r‚‹q9ciïŠå‰Ûªþ'P˜¡1—–D UºÁ$°Iq“šHAw›D¬]t©×ëÖ“° q¨j@ˆîCБQI/HñM7¥qŽeÜéUî™.T)évUR®ZhB£#Y7] rƒ-ŽEt=C+ýÛø7_éPêW`·Å\é ÒJÑý® ÷ ºì¤ƒ¦·¸‚¸ö*H[I‚·t;,°IÑñ.H! J´u‰,°—qVB”Ø9i)èªY~Ž9ЊB«ýNÝH Ò ÖõÇx‰)H±O×·I\™¤×«+-ã¸=+pÉ@W¸²C«­ ¥0]ƒÑàE×·FÂZô„›Û‚t—Ñ$G‡U÷è‚4_t©.HF7ì»mh—£X`wãÈ» %ÝÊ ò8ƒcínt9 ìnœ»¤M…SœèVÃô: ìnÜÈØÝ8…+HçSœEàJ  . Qêƒ0DÝS:œFàª]9Øä0E¢ÀîÆÙ]AÚEÂv7Žñ ìnÜåØÝ8ÑCqôèp¸Wþ(Zà¨ê Cà`ã‚\C¤Ò‡Ó ínœþ¤>ãt‘ÑÅ5'´»qX`w£G]6™0DAš;Â)´ C AŽNuAšfÂ)¼ C¤µ$ s ôZ ìîXÚñÚݸ.HíBíRt— ìnœäH¢ÀîÆñ!NMp‡X`w㈸ÀîÆµqÝcüà๠=g|ãàÌE¢ÀîÆ­rAšbÂéµ C¤õ# Q`w£«‰v3Œi CØÝhjØÝ8WDSË‚”è„! ìnt- RP†ÀA îV ìn3¤Q$ Q†‘0ÎRÐá/°»Q,+HKH¢ Ýia´ZqÅR`wã² õüì X) †+ê‡iV Cäç)èˆ CàDƒãBAb„! Ò«Öƒ»WÐéÍ C¤;, Q`w'`ˆ‚4äЊ×îæ"U`wsý*°»¹|ØÝ\½ ҩLJv7J vw†(È7€0DAÚr¹y†(°»qVY÷aˆ»'Øvw†(HÏV¢ ?ÂhÓ¢_`wãì²ÀîÆfAºùÂv7þ ò1 Q`w£NW`w'rè~¾0DÝ€! ìn\dØÝ MîDN_´»0:\© ìn.Tøâ:U`wãb³ÀîNÀvw†@+7CØÝhšØÝ ¢ÀîN¤õ­ÝžsÝÍ­ªÀîæNU`ws£Bc—ûTAnf„! r3# Q`w£5‰ö.zîv7êbv7ºbvw"ç!ÚÝèDäH¢ hkwãÍ^ô£ ìn4§ ìnô¥ ìîdš»b0­ŸâÊŴýdËÃÖdˣĖ‡Ê–‡MÈ–‡aÈ–‡uøëîz£Oœ{B£7…/ ãÑK?øf\Ž—G; Ï©ÍÝPqÛä®w)çŒmCŽ›Æ£ã¢Ä„t\´‚’ŽƒŒïš”ƒ\c—÷³ªé´ÕŒ6ÊÞñçÙ‡°Ö؇ÆÝ–ÉÅ–ƒ{Ýî:tkÜ3~±£¹ þ!`wÀû#Æžø’1áØ ¸â€SÏüÃ%t>K ÿ¤^XŒ"–G£ªõe/M¶[0!}·PP [°é–U [L|Òùâ=U»…ÿîÒt þªã_§]¤[¾Ctë ¡[èÄ8žlá®/æ¦^øõE1mEú»n©ú²º,šyŬ2‡jT,q1õA±8Ü8íÍîp‡Õy àvGág®2ûº«ÌÆðeà4$ ÒÑqJ …;\eü¨ ¿Qðå–nœäßsݳ³þõ2¨c˜jbÌÀÅ]¢ïé„ y£°nfI(ÛLó ªQ 1±¿Í~ÓìšÚ†æöTÛ²ÄÌé§'ÛNlOµ$f¤ë’­›jj—¤j—µM _S–1ºóÇehçǸ·ÎáçKÇí5MɃơxOé8tÿ¾t|1M˜?~T”óËÒñ£9ŸlH-mL.O64®$Ê{Qû²äü©£ÆOO.o¨MrÀ8¯³ºmɨñÕµLÚx‚k’Ë›RuÉF”FôÇ/:ˆZÎïh®moH5·E¹í}áòÏ[Z“õ Qnª}eK2Ê{Gª9U_• ¥YŸÈ­Oe²•Š›j–6ÔrÊÓk—¸4B­‰²ßØÖ^7qbõŒŠYåQþþËjšë“Qn¡[ƒ}¼²¾¡1Y­'›¹w\Ü’lvÁ¨à ©8R¸yIG}}²5ŽÆW¸„64#Ü׺¤¡¹¦ue5m)QϹí¼ÿFo]öL\l¡Â3ê[“Éê¸"§µ):ÛšlmM½½vYM«[¼!DW¦–'[ë1ÜRšÞѼ4Ù^ëÓDË[Rm †(?Ç—u±eÝÜpR2Ê>Å¢›Úñäp³7$9Hü½ÏmlXÚÜ”lææðñ¶šåÉ:_6Y’}þ‹™·7ûrW¶´¦˜»¯¶&kêâX²×ŠÖ†ö¤o«mLµY0.i`ôl¬ÏtFïk®Ö”ª¼ËÝ÷ÊÆ†¶ö(otü¨ò³êêåôk|TðJ½Ð,‰=uQC]Cºu]2¡òôTG{Kj‰¥tqGs]uüB«&9£¶£µ•¾®o})9\ÓTƒlïïg¢ÓÆGù?kjé[< ?]é*›3чôVó{IGm{”ÿ–ºšöš¦m§íö)Ëüõ|C”ÿ fç‚öeQÁ]µ©¦&v:¿Ž®¥Ñ¹KV¶'Ûš“ɺd(KÓbuñij6‘è:jZÛÝîI^Fµ¡Ö44/ò«OµÖ&ÓK?jãÙ†t}•ò%5Í'6¶-‰ *¹H‘—0‚´Ö4!tf‡d}sC;ú÷[šp·!KûÚh¬tÏ¢‚Ï6Ö´µ³Â7´×¸'Z0kÚZ¢¼w ŽŠúQ‰§·&Û’í-©Öö¨`u[K²æDª‰×уÍíÉÖd*Ê}•ºœ¶°°ŽaŒòn~ ¬Ú%ôå/]ÒМ¸·¾¡˜Ð´¤0ñ1«4zfC[KN£ﳬaé2Ú¡Xy*CtQ ‹çSq¯Kyµ¬ÅWÔ.ëh>‘ùÖ¶_ÛÉÆm†âÉʸ²¥†páKSµ'ÚÐ'W·Õ4µ4&[ÝΞjiŒò– ¶U}û’ëߟߣŽò•ñpGy 5u K¢Üsê:j£ÜgQÁŒ(ïˆx€/éhnÖn(îí¶‡æyc²)øEu­MŽò€t3½¢-Ù\³„ªâI.¿Y¥Ú›jÚNŒò>Ñ^ß(ïIØ’l­u]ˆÆ×®\¶¬9EOË?VH £êdùý•ÊÓå/ïœ/¸pGsŠmqTsmM+¶-ÕÒÜÑåþ$ô,ܹVŸ«¹ªã{§;Û‘•Å»9zg‹¿W!¢ÀylDÝíB35*øœ^–¢Û•¦†N-±©›ö:OýFÏkM.G£p!Ñ×6u4j/Gù» fçuºë„=/ªiq ¦²ÊgXßÜVÍ+àËýNFYÝ·tN^Óœ\‘Îò" š,MÐe)_ç*Õ¢[X:f7•ß,b!˜r—V-ªniì ‰ª\£œ¼¬¨ººyEuõŒLáñW·WWOH·ò¸åì7 Î…âî>V§?A`qZx¯/ƒÝ£ü—ÅÏ¥ îëÔlˆC€u…KŸ«œµàèªã+Ë«ç,˜5«7¾pî<¯OÇO­¬ª˜;§Œ¤ßœ1¿|7TÚ·Tú\vtñ½5­Kk£Ü÷éFå^FTÍÿ Ÿ—qíý.tZô|Âò̾1ÙI1&²QtNuu]#£°l9æ¶õD·Ò_Ü496÷ù¥cF‰ ~c33ÍáRuÐÜ”¾@åጠǨ9~— ™®î¾ˆ™£Ê¨|©HHµ³¾e@×_.;™¡ê|­ö<­}YCp]Òé8ZÛSß‘ö´Ö&½Œ‰_ž6:Óªi%÷^R{ª ™)U|ì`ª4”/Lå*.£{ºC]Íx³¶—n"zqK|ä)œE ]V.mì½³H3ºy™?t¤®<¯¨ÞݢܧX¦ËRµƒ‰ ç©ò 5ñRˆÿÅúP£“üÛÎ=Ìu5¸½ò—¥cÆsZ˜X:¶dL”û>gbÅMŸ³¢ÜçòyD”[ħ¬Χ2Mås6.ÝæPŒ™|}Nþ>§³¾ô©*–ò©*NæSUœÂ§®v7iáuô³XOtSmuÛJv· þ®øcQý%}É–-_Р?%s¿y0GTðÉ"F–CPyjQ½dâ,Lq«®½µc`ùt¿ïŽÜx‘9®2,ÆÂ‚"×!•P-|½+£ðw®Ç=Cž|Ù½îìÉ÷0Ø>ÑõÍõ©ûšÿ“MÒî©—»§o¹eÇ(”¨±(iIºkKçëø¬"íEsÿè|›|^›}%§s½èhÝ;‹bPjŠ‚Ã:K¨¼¿7 µ3Ct|‘n :â¬mÕÒ¯¾¯nçY·†âYEéºu·¬í‡i£3xÑìˆe¶'VêC#åÿ}_úŽ´7¿*Ð7DOÑ`ÙƒFm‰ô•Õæ˜¹M—^ZÅøŽFØ¥hOMѱ”=O‹¥5uuÜ6Neéjg/ãS·ï™ô {¬ã_»…ð@‡¯™lq•Û ½Ý(žXåÝÒÒq­vŠ÷d*]˜y«›‡®uhàJ~øÇ~Š_ãS âÓ|êѯó)Pq7Ÿ¿Áç8¤ôY“jÞ¸o¿ä»Þ âS Åv>=ƒkÿÙËk„ÚŠ_¥H ÑWaÀœתÍeöKÇlv£Ôó:©.âÞ]í2Ê-þ”úTæ7JÇSfñÚÒ#ÆÓîßåSíþ,Ÿj÷ïñ©·¿Ï§2ýŸfª}Cö¬ûøïÜ{n{Ünk9Ôê#ÓmÛSC匢e5miÄÐ=H…5EvzÝ—%¾¥ˆsЃΨeÿÿ^‘%°ÃÜ]FRUä.Ð{¯g,D9C³¦ R÷°é^ôi¿1:FA›5Œ¿à²OÛœ¾üíÿ Ä™Ûi jw« >¢¼Sã:×·éZÙšŠ§¸÷ö˜Ù©¾¬õTïó2!ÀWÕ6&kZdQQ}cGÛ²{ÇyMœ6Ï]åOsÛNÈþoK8HEiÉh–Ì•|êÑ6>÷_SZ2†·7ð©ÍüZ>µ™_ǧVÕëùÔªº‘O­ª7ð©UõF>UÅËèѦ(¿9^Af=r_.¾“ç"Q -ªÚ^Æ“½àÈ¡þ⥥%ce§pJ]ò‘œ:º)ŸÙ£í㊣‚.7nv µ\ÊlU'.þnQ}G#W‘îq)_ ¸´‘ÃÜg©Fý¿¯´D{ø~>¥ÅÿWÛžª’¯€Ç7µ¯¼oaEä×lÍ+-ÑÑå(>u[šíªÔž6¾¦Á(åÑ$ÑtS:¡˜+Ú{ü†‡[²‰tOm]ßå½SKóXhI|/#*»&õi¥8ÆÆßŒÛ§‹ôÞ**{Õ»½Çv˜Í•Q3?›}Å[ŽUõÄPÇv‘IÅF¥db>ˆ ÞVTï¶S”›ÍÒ¸Ò G€çþ¨H»Õ¾ ߪa¬¾¯Ûô­<í| B0[ÓÀGÌÖ´#âŸvÄè¨àfÀA;<Ó…iG0…æ›Íq‡¾UÉGô ˆ2]á£ïYhŘbºw’Ž2öd¯¬ ͪÖ$•{ŽO13Õ²ñp«ã±½ê=¬¬Ká´‰‰Y;¾¨Õ—»$p¨.H¦ZúkT•åt¢H]ÚÔ_¤$?ò `euô Úß?Vƒ.mäÙÑå?UÌ-Û‰&oîX“¾*Wé‰üxcDJ_×äþ…C£¥gÖÑ#ù0“î†@¶¸™L¬?·fq˜Ri™œÆ7Kèt}k6—ë[³¹BßšÍ3ô= "£KˆÐf+ûs¸ –4VúD騒Qì$¡ÆöQì85¦]hS#Þ>š»Ç‘¬%KVû0zW¾=UÛÐS[Û{ƒ{\Ì­wmý wÔ2𲬚ÌrS“óvS8Ä*øz|ëEëÝ=¬øŽ^€¢Û¥*d·©oi?üŽ£)BÙ¨¼¾­©ÞѨ%(r ×:½$f.B­”:%¼ÈÑÜ /sIొ2—”ª .Xš¤Lšµ×ò ~¾ û“¥á‡RY†)¿:îéïµÓ˯-ªçê!L|C:‡píB¡M³á‡ó-_Ú]ß:¡§ög7q£r2g5 Ž'ç¯sV*qäY):±§L¢(oU¦q¦}~£¾@ƒá_oi{jO™Êh›ÄMäß–>Õ¬oè[%½Î%޲WÄÐÃ,ºø3MÉöO£¼_+‘@øÖ¢z1bë½»¨¥¦¹¡v3ÅfdQ}Ý—]63°ŒzñÅ*Ç„áC åª"ÍM+ßÂ-Éë>ñâi6«a->DùÐ /lc1Ä;qŠõó>LyµCçò­fi²¾Õ¡k,Aå ­ *)|8F¦®÷G)‘ ?ƒo`öm|ƒߣo¡Ýçqy”rôlñ.®£ür($Ô¨‹²k’†ò-’”iXR…‚x¹<ÂrÒòP65s?}«™£õ­“é86h¯[0Gñ´¢å>-õb,ù ®|³"³;ÆtdL)×ÕÒ¦oõûh¾cJר<•8èáúÖ»7ð-¤^]ÔTÓ4yÊò6+¹|$uZ÷•Fé>Â7@{^]GSÓʸLQÆاuD”?x,åŸ$2€ˆâ¥wòR:TjbýJ§bF#Ê;O©tÆ{·çµuåâúðAÒèX­H×LÆ–ãëž\q®í܇rTn×6+{µ'‘ØåÅ÷2YWYjc]ªçheWr8æ‹ú÷X‰æ K/è룽(^ NuRmj¬Y¹Ä]’{š ¦ÈyB—&›kWr£0Ý §à=y |x.e^Üòp•êÝÄ]~¬yšàÏ3Á¬Í{ô=3Ê?­ºz^UUŬˆò¾­ÒÿhH'è^å‹«»²þñ^F<1!…¿úã–ßöØ|—ßüØÊ(<ý«¨üø®‹f>´8£«Ú¿…Ž6ù5Þ´¬o–/é»=*x{zÜ;ˆÌ¥ï(ƒÎ0/ñræfñ¤x=¯”XˆU6©sŒ‹—Xš )߃i¦»KÈE°Mv¿^&ž1/U4·án:åÎA*lòANq<Å è,ÈYŽ«èêN4ãI¡õ¤½,þ’ÜŽ;{«JÞŸæÓu5£ôÌ8ïcQç‰+½Øçyd^KYÌ<—Dß‚‰}‰¶dÊh0¬…ñýÊ—`$8.]B ¬Ó|Bt¸3&Ö£úRÊUA±ÂßÓK ËÌï-¬}G]«ãºøT]`òé%\Æê[°÷â@ÏP5cÀôtQ;з} ¾ªßUÔZÓ€jåmx7˜<ñx%Ruä˜e»ü“"DyR¢GwB]¦ë^1_ß3¢ü8òï¢yå»CÂJ¤Ö\øäÚ¹ £ab[Cé¤tnmR»ç¯KRì4Àtû³9Ӧ쉮ŽH6ÙbŸ\‚Å_êéÅK^’„Ñ­LG÷FK•DuVŠn›º¨2–{¨,Rè„JT?­Èéåe³ª*f—WWVTE_Õ“勪ªçÏ)«œ?snUõ´™åÓŽ‰ ^¥—g]V½ rzYUyuÅœªòyÇ¡ Ÿ©—'ÏEbeùœ²©³Ê§G¹¯woÏ®ž_ñ‚ò(·ÕUzêìêʲ*ÌÎ|Á‡LŸ>¯|>­ø–¯.M}AO¤@¡ÓìÉ'3O¦Û“_Ë<™aOLuöÉÌøIá{kñEîî-'}uoE髆ޢü«âzuÒÔéÕˆbœP6«zzù¬²ãQõÏ–•ÍgTì«â~þ:º›>nÖÜÊÊã«§ÍžîsïÈ<[À›3]²èí½¯l›/ï}b²$Gö>Y^UVµ€ÎýVx$ñÅ,zl¦¼ê+[Þ½Olyïë}âËËÛ(ÎÝ‘Š.¨*+føOYÀõÚŧYü$‹O·øÉŸÇEqsùeÂÁ§–·Ï* 9ŸP~ÓZ—1‹ç Gúöt¹é“7¦+NŸ¼9]túä¼t-'ÌÕt«èåéZÒ'ëÒµ¤O.J×’>YÝ_‹º¶¢¿=Yß_‹žlì¯EœÓ[2µœ~l”{y¦ÂÙ4™ð9™ü WNÊÌ"kèô(ÿéËg•W¼+3ž.…¯ašOñ癉u)öO¿p)¾šb—âóé.ES/ÒÉK v=IV^Þß›,¥Y¯Y²”#û{•¥4 ëY–ò•ý½ËRŽØÐÃôaqÄ@/Ív´¸!o¤Ýò¾%im2¿6| m²›úg“œ’7Ï&›1Ð9›ìêþ¶Ùd'nœ?ƒ‹Æ ¯Šã7NžIöò±3ÉÞ±qæL2vÂÀ™dOÙ8m&™ßKé¨ñ*þÔ@Ï?«bÎôrÙáwã²§ñ ÝËÓ.îoažöË}ÌÓf=ÞöøŽæi‡ô·5{Z;ÐÛ%åeÓ”¦±)í³ÒzêÒe½®¦›?ÐK—΃'ßG—îØºt¿Ûß?û,]Giï–WV¡&ØÑ96îp“ª­¿k&U¶¡C*|ÇLª3úeRÝÕß-•}²^YØZrG‚Ð.û®ì«È:æz 6Í%ô£™õÍ%üÀ@ë\©»çz¤•6нËvKxò\nQî…ý-´ÏJßè Kgî>y]º¬Mµt~ûö¹t~¦Ýséþ®¿yöYâîI¡wÇVÌ?½¼ª|š´v40›¼b ‹!ñý­ ‰Ÿ9ÐÏøƒýM ‰ÏèlHì×…ooþ¶àAt†O/›C´Ó䫿 wlD‡!µ9wRïÞñÕÔK cHýÎÈ1¤nùãè,=^¨+š?õ•Ü2OìáÈœŸžIanZæ‰Mñj‹ÏȤxIú‰MaˆŠÏ̤¸6ýÄ‚I³>–Í«8NçÈ…sgÍ7»¬2ÊŸ¡gÇqê\>m^yùœ(ß•bƒl%‰ƒóà„±c‹g,ªž¿ ²rî<æÀwJù™eó8½œp\¹-×Ë¥sv2µ§”ÍFªÖCy¢£ÀqSª‹Ê§.8úh橚¬ôf×·“çÎûV¾9?avÙÑTsaú‡XñN‹Ë[0}Ìè©U¼;kfÅ4:n®(á)¨”3ðì†áø(ß]õÝ)Uó¦Gçô?ÞÇÎ[åZ/߈ÙUoyÅÑñ ¸ôÊø¨{ÊöÆ s reñųçÎ;9õô…9W6þ¯M?ZT1óæ~dâîjº¬l^Ù¬YÀ…òÈÌÓSÌaæ Àµ%ž0ãfÎLüôs4-QÞín¼ŸÂ";¹zÚ¬¹ÓŽ!x úæ_q©,Šoݯ‹Ç{ú1™ÓÏœô{n‹rw˼ÐÍÞöLXd“¡ân æÉ⪙l“¨`ÏÞ:¨FW¤_héœ ý ÌM·$Ìœö!v‡\óääŠéN 9vOóæ,v°y­H¿ÑtÛ4ƒûR›í_Зھ1‡aŸziùqÌZ쮹渌’ü˜k:oÜåQ“É̶}±®ïÙ© ª\#Šï ϲÅ_t7Ôô™Ïf¹'•?u.ËEI-îes0®peßKöyñ€Þ'rÖ@X)…›—PÕÂ\äÌp/˜LõŒ¹ñIÉ,ÞÊw㥶pæ|ai­òÄWV.p+çdð›n1…xýêÑâ2l]¾4=–¨é«‰.$j™‰."º=“i¢×ityBÑY&EÍHÚ·ÊdFÈDO®,ðÑååGWOã>`NÑþî-åi½Ä:(»Ÿ°˜úÇñà—{Ïú;¬÷ÁÒéUÜhÍ™Ú?у8]øñ¼_9µ ³”‰ƒû雥³!‰Äî’À£2‰Ì¶MߨDåÉéN7«Œ6Ø#[ö@ÉdM ãÍ™LEâxÕGÇ¡ØñhÁ4#Ÿ„D'ã-¹ãÍéä~mÿ-ÞÂÁÝ8µ’½˜¼}u*ÙÍù4³ˆ71]o ìÎ߬àͤþ7ËyÓÜÿ橼1çŸÐ]½ÉŽ}³Œ7‡ö¿Yˆ·ësý›EóP…O:B!=ç ²å³h\Ò 2Qizƒ‰½]¡Lé [1}z‹ùMTN†ua£ª"ݱ+TÅÓ}t¡:óŒLTY™‰ª3«2QÕ›vt!õÚÛž%Ô¤{»˜éðý>,,#éR]°`ÑÔ(w¡ H,EiׇVƒR"Š”aÛ‹}ø„9•¤àÂ/b¸¤•È´²²|Ît‡\ž–Îzú±£`U†;äðdzüÆp%Ì¡{ŠKmPóòòY1N™QqtÀΖÅSAçeðƒ´YWÔ.®ÖË3+X<Ú3KÊ«gqË‘±Kÿ2Š ðkEõÜ©Ïw',-ãñüDyëÒ1‘ÂNŽò!ûø¸ŽâÉ<Ø–C¯e,¯šçÚv·ž,­ êÂ2ÄùW·685X¾Ø‚¬ïJÓíNJ$¢â‚¥—"€mÔ }-*˜`’pQþ‹ê’NG&Ñh4ÇÐI"pÜÞèžæäò+¯lªéŒ#ã½mù×µËR¢£—.oo@-DNPRŽœåí«ŒÂ±h¿IrÌi¯T´ò&Ó%÷˜Í0œ¥×&¡ÿä8²»¼*q¥Ó-Ÿ>¯laõÔã«€\…—2ué‰'úÐ|]ʈkP¸ãËvjQ3up}Lë(¬¹žå¶–PH2OWÅì{ÝFʯ‹nEÙÔê…0N]ˆ qÕ2u<Ê™/gÊÃÀ¥´pe”¿Šøy´°üª–ñc©1Ê?¢eÌhxU˨ñ ”*ZbÕ¦Ã[–¤PÝ.¾dI ¼F¬@:aÉdÓxRX’@ÓÇ ÿrSÒt‡%W$I'å<èœUYãÒ©ä”ÞGäëì&ľ@)¤Ùð‡[¸”…SªæN‹òNÞAê<`Kôâi§Ñ1OP[£%ÿ“Qè±|KÈI?©ù½ð!m­òÞ;T2+õ¿•¶ŒÞÿ°¤ã (mF‡<,´9x« Müëí¢‘·I~|¿jfrÌvEÎø;Û¤Q£mÕdLRÛ2£K¶Š»Æ×mãøÛc£5[E—£Ê­béÉŠûå¢?x¿ÔwiG•Fc'&ð@ ÅÒdÇKG?¨rT<â÷*Bå³vHÅ—=¬Ø” rI±gSï“A·E` "žÏÙ&× Úr'í×ÇüvØZ´}L-Ûpÿ¶Moµrk×$mý‡ÏK®\ì™Bdïì*Y+Õé¾]ÉRë-WŽø¨é*,Å]+ëš–üV¦IxðræJÀL%\˼¾\þ15³Ù%ÎAÞ}ø~ðrÖÀkdŸS=Èï|š }W?[þ¨á5ذ{Œ† ƒ„C¢+âÀ‰ý?Šx¾àÞ ßîBZÕc%ƒºïxéêЙ:Þˆ‡··¹b›áO¢å}RWæ©âm8]{»¼i§'W­ÊÞó«KgAÒßÌ6þ°ìÄk,³k®ûÁÓ®«·ƒTp¶î>߃ú÷]’e7óß/Ë®DMª)ñ8¥ûT¼ïl¸ekä>n»BpbH!¿ÆÿOÇ—±¦Ì½Ü]<öÏ]X8¤€OãyïÓ1€2ç‹iäöü-YJû ™"Ö3èwõ? Ÿš7éÿ÷s)?ÂÚG =û(­ÀÖåDêøKÔßÄÖÌDet7Q{ù ®<+RÈß°?¾&óÃÂèÌíÝÇÈ®œ/RÍ×hË7â]2h##+g/;ÕƒFÊùøþN;³r2ò‡ñw!® œ8RÐßÐþ¦©ßu)ÛÄÍ߃ìWV)äï?Á—½ÿõ ”·IzDôm ¸€ä/Þ!˜‹u«À“fÜïåи20É_ ¢}Iþ‘»ù9nJaí¸’ð#É_­¬FY/VgH(ë!z+3“ü5þ üV<¼j±t2„~ž #¹‚´ LAÞeí"×*¨“ë$”ù(ýɃµJþZpÇ7LΪaóí&Wih¾Ã¸raÒ’?nûÇh°e€ÏeŽ S¼\18½äoÿ‹¢¬„Ì«ª=]2a·ïÉÓÛ¢´cLQmÇEYûÇE Ø@\Óö{„Éæ*Ñ8›JÆÕDYɲ*©1ä´¼¦Ì¹Bp®Éßø«£¬Cd“Xk4§ái>HÊs%`z“¿ƒ_‰‚N¿µÒ«Œ?ÁÏï1]A¸çäïÐë jbrWU †Âõû‡® cW×aÂÕº¶oîU¿ zL ßU‚}OþfÝŠÝVZªÊ÷~>¢„ïªÁ( *0튋s=óäJ-ö‡x–®ÜƒòwìOqûŠE~ ‡ºh÷­LNý°wõPþÞ„W8üʧdÛø¡65nEù[ô-ÜÅb€9£lŒÜÎ;µÉ±8ÊßâjþãR¿”_’w¯Ç –«ƒ¤¦Šû°H‚ŸrµÀJÿG{l£Åºä¸*åï8öËñ±åû‚\ìE»o%ÛºÌø0åo &OŒÉErªêQ÷“xmr-“üD”HN’£]%‡¬º÷’ƒ]jüžòw2'˲¢:¦ã·šý娦Æ"*'Œ…[K+*’TNFGmç2»äøJåïäôOOª%eäÝï~ž´KUþNý%vq-»¥ä¨×æ*ÖKÁvÉñ°Êß²ÏãlÌÚ…,ÅVk¢=¶q»]rŒ¯òwZ ÿq·Ï Ó#¶RÆ]j¼²šÔ‚§],`ë•1Ñu¼ü-Ý‚ÙVþN_ÃÜìkM×xï‚ Oám9xv5åü){­éæ^¦½:ó8ñÞ•‚íWþ–ŸŠM_»ÀûZ¿€Ñã$[¾aù[ô[!kÿš•L@@`ûQ5W¶cMŸÄ.°]«Í}.;ÔÚÇ” \)8—åï „ÎÉu¬º¼D?¦˜`6hMQ/ã?nòu 0˜¥£ªýî·àjÁJ­©EW™3ðøª_cÚ`€ý¸ÙWVlMßFÞت#õ2 :¾ãkÀÖ•[þÎ,ã?ÎïÍ3˜'ÐÑ÷n lI¸Â5%évr–L âu¸7ÐÙó'~\aØÌåï¬eüÇoª ëð f}ßQ‚« ˺¦¦ŸGýÊ´Mÿ3ó ®ÿO¸Yp%á~—¿³÷à¿åÁ Úèž ø±£W†zMiˆ?1 NŒ1†@µšðÛ¶(Üùò÷”ÅüA@¿– :ÜÿÐU„­JݱU½‹ÿ2Ûku²¾ïiÂÕ´ª§rîB™UgRm•‘i1QžÆirœ ÿ»ß YýîෘݵXæïUäû9ð}åÍy±½Uñ­­íIÍØš¼¸5ù·x+RË$TcŒýÊ÷–7×[0l‘·2ô;©YG}—<-XIÍõòuMú!oɇ-×ÞŠW2Iæìký¹Ìøh¶9,F/Š£g¾^l¿R¯ O¼ØéUEóªì­aÆê­L O¼¸bÎŒ¹Qó—Ø[l²“W™‰—Ï›7WƒèÞb+–·27<ñâʲ9Ó¢Ãï¶èè¡ OŒY‹]=$¿ï!uúÒßCúæçÑæ¾ØÕnØžªOF‹KOí™VvÔ‘“&/ª›>µtÊ.‡Ÿ,9¼eŸáÙ/¨éÈýöÝ5ç…K‹ž›xF^î Ë&eUjÚ]'ÏÌ*_8çØçQ1£ª{õ©eU/Å+×¼êÕ¯9ã¯^ûºµ¯Ùg½ñMo>û-o}Û9oÇ;×û®óοàÂw_ôž÷¾ïâ÷àƒ—|èÃùèÇþúã—þÍeŸ¸ü“W|jý§ÿö3W~ösŸ¿ê ÷Å«ÿþK_¾æ+_ý‡¯}ýÚo\÷ßüÖõ7Üøí›nþÎwoùÞ?}ÿÖþÁ¿üð_ôãÛ~òÓŸÝþó_Üqç/õë»~swílÐb–V{·éV9ßwïŒe_½“Iå¦[qgìßa‰–wâÔ4Ý*Oäî6~±­+#·M·ÞV-±wX®%Ÿ¬Õ6ݪ {‡…uòÉ~­òé¡{‡]ò‰"ÝtëáÑáÝöÎÛH—Þ¦[=Ü;ŒšóNy›n}Fôœ³í–ΩODÕ§jÝ;¨)䡵éVyšwït¼“à¦[?-¶wœßx'âHÓ­l—{ƒ•úd$Xõé¡{‡IuòÉDtÓ­Ñ3'Û;쬓OF€•¯ùwŒùdBºéÖÉ™|˜õçèÚM·^žy'Zy'ÂM·ægÞA >YV}åt}0É'ÔM·î’É'.›É'L¤|šj÷£ïäÓµ¸éÖ#£ÚeöKð¼“}à¦[q«ìóÁìãÐkÓ­Zâîë©OWSÕWDæÅ¾Ãh=ùÄ:jºõÙÑU7Ù;,à“OfåÓ”ºw˜›'ŸØ«M·Ê¹¾{‡ zÞÉrÓ­WDuI{‡azÞ‰0ÖtëÎQéAövõ‰ªúš£õöÎØ¯×;˜›nÕp¹wµ'Ÿ,.+ߨ¨ÝÞ!Þ@>Y`nºõ¨èÈb{‡ù{Þ‰ßt«¸ î6ñy'üÙtkN4w–½ƒÎK}²Ø¬ú„ÀÜ;ð(ùd¯¹éV†åëör:ùDW>=tïl Ÿì97ÝZM¿ÅÞaDŸw²ïÜtëúÌ;ìèóNöž›n}jæ¬&êÓmNõé¡{ˆ|ÂÐM·ªùîè &ŸN¦Ê§‡î+•|2"Ýt«¤Ü;Q5Ì;•nº7ÓþÄmÞ‰ÞÐtëiQí‰öŽQ§>V}²»íÞ‰aòÉuÓ­j¦{Ça‹|*MùŽŒÎ±w´€|2RÝt+|Ÿï4ªM·RL‹½ƒ.Ë;±–šnØtïÄ#0õiõ©¾¦è×öNóNF®õNÝq︻R‡Œ^7Ý:-Zè÷(¤ÞÉvÓ­Ÿ‰žîç–-ïÄ$nºÕfßé*oêÓ1Qõé…{§ƒ»É§[{Ó­GƒkÝ;]ÒM>Ñð”ïøè9öNGr“O6«›n=Õ¿ÓýÛ¼±ªéÖ+3ïtÜ6ïDumºõ)™wºU›úD U}éý¤£³É§c[Ó­s3}E„|¢^(Ÿ²»wœÈ'ƒÎM·r¢ôïtá5ïDhºU¯Ý;kÍ;ñ8›nGǽÓÅÕÔ§{껢‡}§ë©É'£ßM·—饒ORùÎŒ~nïtÝ4ùd¼éVÝ;ˆ¼“‘ð¦[E¡wïta4ïtmº•»˜§+¡©OFÄUß3¢l{§SŸy'£âM·Þ´Ozn8ªóNFÆõî éw”Ä;×;¡_÷ŽS·!RõN@ÛÝUd”ÝÜcd”œ9 ´bºçb»š^‰3Út«€{‹‹w2[Þtë_GÅÜvÌ;î}¼éºéVÝhÝ;luÓT£ºwWȧ»Zӭy'³çM·²ðü;.½Ô!3èªCÃæÞ‰°aò‰Ùt««{ÇQ“w2“Þt+¿C€w2›ÞtëŠhׯÙ;Äa¨OfÔUŸ,î4&ŸÌª7ݪS¡{'²ŸÉ'3ëÊwYzgrG#ŸÌ®7Ý*€äÞɨ°y')—¦[YÌ~ÆE 6ïd–½éÖ=2;=ê“xŒêÓEÁ½C1€w2Û®Ynö¶wÐbx'3îz§Ý;Xº¼“Yw½Ën&R 0;A,v ÿŽÓÉG4Ý* çÞi"L¢A¨zèÞ±VÉ'iÓ­:@¸wb ˜wb7ÝÊRðï òNfã›nÕýãòF}ÒeQ}zèÞÉì¼É'³òM· 0»w2?oÞÉÌ|Ó­âh¹w2CoÞ ý5Ý*ÀìÞɽ©OÄpÕ§‡îÌÒ›|’ÈiºUÞ½SܼÓû¦[?汿ò›wª§éVJÜ;ÕkêSýªOÝ;õÇäS¿šnMD¯ð7õÓ¼S›n]UWÛ;õß¼Ó<4ݪÊ{§y1õi~Tßé¹×|™|š·¦[Y.>¼^Þi>›n=(³W ±P‡æYuèBãÞ!ïC>ÍÓ­ÿ– ï´/šn}N¦íS‡ö‹ê˜”Æ Ú?&ŸöQÓ­D³gØ;í+óNû«éÖwqQuïGâö]Ó­,ü^Ô>4õ!1õåÛxèÞÑbòiŸ6Ý Ðñï´oÍ;íߦ[uqï´ŸMÚתCÝ;ís“Oû½éVÀ€§ýoò (Ÿ½{G ò ?4Ýz~t¶Ç Â&Ÿð†òé’áÞAÕ&ŸðIÓ­:x¹wÂ/æðLÓ­dæIxÇÔ!ü£:tipïàOx©éVÈÜ;Ϋ¼¾jºàèß±jy'<Öt+À¾ÍÞ ¯™ú„ßTŸºwhOx¯éVi7¸w¬ò #*ßœ¨ÒÞ!j@>aʦ[u¨rïEÞ ƒ6Ý*öŒ{'ŒjêfUJèÞ Óš|¸M·îž™ZÉ;aâ¦[5\îä!ê†V‹¢:{'Œmò Y6ݪ¡sï„ÉÍ;!Ŧ[u°pï8S‡0½êÐC÷N˜ßäÓ  éV¦Ý;8¼ÓÍ éÖµÑMþÚ¼Ó¡éÖgE#íDDêÓMBõéÒìÞa*ž|ºa4ݪƒµ{tánM·j‰¹wŒït#iºõ¹™ù`D©OWÕ§K¤{‡‘~òéÓtë;£Ùeöò;ïÔé¦[÷Š~ ÷üÃ:?uèÆ£:tvït2ù´!šnÕòtïàgòN7¤¦[uuï ¬Q‡nNªcrt¾½ÓMÊäÓªéVÖÝ; =ïtÓjºõMQ›ÇCºy™:tSó"ûÒÌä´oºõƒÑ'Kìçdò鯦|£5öåòis7Ýúúè ¿·8¯’O›UùtAwïtã3ùtókºõýѧ×Ú;ÎäÓPùˆÎ°w:û™|ºÚ5Ý*áÞéæhÞéÙtë¸Ì¼BÁ¦Ý,UǬèt{ÇI‚|ºq6ݪ%ãÞéjÞ I4Ý*€{Í”:t*QzèÞAý$ŸyÓ­qî|Iòé¡|š÷N7\“OgЦ[EÜqïtó5ïtêiºõÔh”¿…êFlêÐÍXu ‹üm‰1Þ ™éݘ¨ÓÞémêÒjºUà×½ÓÍÚäòV>÷N7n“OÈ éVb÷N7q“O_ù Ü;ÝÐM>]›nXvïts7ùá•O_î$pòiS6ÝúÊÌ\¢)E>­2åS×Ý;DcÈ'N@Ó­Ã27LΊ¼‡ éVn÷Žóuˆs :4åî¤wò‰£Ðtë«2u‹Ã`òé¯|G§÷Lqòi2šnu1ŸÜ;q],šnÕÒvïÄ 1ïÄiºõ0¨_î8$¦ÑTÇ¡Q›½çÄäÓ ¨éÖ™›¼8*æ6nÓ­kî8-æ.=M·Æ\/óNSŸ‰ê;=ò÷EqfL>m¾¦[vÜ;ÄYȧ ™òi‹»wâä˜|âè4Ý*äÞ!JÇ;±EšnաܽCÜ“:UT‡ºwâ™|BrM· 4¹wâ™wº²6ݪú{‡L#u⩎Ó¸Aœ%“O¬¢¦[fÝ;qœÌ;]æšn+ݽ'ÊÔ!(ª:–¦ï‹âP™|bß4Ý*"–{'Εy'VÓ­:θwp#y§TM·.ÈÜüÅg3õ‰ß¦úÎH×'É'^]Ó­:V¸wâÞ™w¢74ݪú{‡¤uˆW§:ôнÇÏäÓ¦iºUàÚ½/мß®éÖeö"ÚVÔ!N¢êxzúž‰™|bK5Ý:?zº¿½‹çhò‰>¤|X4²ïü"ŸØ1M·ê¨âÞ‰OiÞ ò4ݪƒ»}ÇSS‡ªãiþþë!ùôÙtëé>Å‚Lzw›n“y§z©ã>êW§DwÙ;õÇäS¿šnÕQ½ƒtÈ;õ·éVçÜ;8™Ô¡yPzèÞÁO$Ÿæ§éÖצç vÒ¨z§ykºUÇs÷ž#uh>U‡ºwÐSȧynºUÇ%÷%ï4ÿM·Š¨àÞi?˜:´/TÇS=÷!6à}ŽøS™~ÐJòà½O‹Œ»ð>Çd¹wœZxg8€Ü;hÔa8€÷òнsÀûb ¶¬{§ˆyg8€÷€nÝ;8€¼3À{>îï±8€¼3À{¸Âºwœ*t¿Ïqï¹­Ë¿ƒH>üwazð>Ǽ»wŽxŸãê(ì÷ŠãÞsõнsÀûpeú>𾘸2:!ænHUÊpïsÀ/îS~óÛ¹(¸œœácÞ Î優ÖÈ;Ãübኛo+„éÀqÅæ…H P‡Bw;Œu榆x/Ý;ǼÏñïĹwœ­ygø€÷|Õßbñygø€÷´xÌë<ÊÌ>à=·µø:8wÒÄâÞÁ¤Ã¼w©Ç ±ñïs|À{æGvˉÅäáÞóQ­½ƒÈ;ü祑ñ@cñé‡áÞsÛK}Ýœ½è‡á®‰3l‹H†xoÇô±ñïs|À{¸x¹wPâxgø€÷|>½ 7ðÎðïiŒ®²wœYé‡áÞs[£¯zý0|ÀQÑ"{Çù›: ðÞæ¨ÕÞ9>à}ŽxÏÜè{w†xÏ—áDÛwÐ~xgø€÷pávï ÐÑüç¶ÿº ý0|@¬Ýí!„: ðÞdz.ð>Ǽ'¹cñygø€÷P{w†xŒ ÷> ý0|À{n;Ù¿ƒH? ðâè3í|@ê0|À{a¸wŽxŸãÞÃEÖ½ƒÈ;ü‡étïàòÎðï™áÞÁ¤†xÏm'ùwðé‡áB rï𾘨‡îãÞçø€ŸŽfû½âø€÷9> ˆއ‹H†x/Ý;Îä3|À­ÑQ>g ò>  Î§ì|@ò> C÷Îñïs|@;îçuê0|À{_ýÌÞÁäáÞË1нƒH†øëÑÛËð>Ç„ÀåÞ9>à}10ÛCŽxŸã.‹Úý|8>à}Žx7´J÷Îñïs|ÀK¢·švBl|Àûb> *îãÞçø€j {w†øÑxã½ÆÆ¼Ïñ!:¹wð©Ïðµü;ǼÏñ?µÿ=Öy‚w†xaT9ÕÞ9>à}Žxï‰é9ƒH>ÃüµhÞõö> ï pK4ÿ,{: ðÞöÈøÈ±ø€ä3|@ÎîãÞ縀âÜ;¸€Ôa¸€‚%þãÞ縀K¢g\nïàòÎpïŠù}㸀÷9. Ä4÷Žsõ.à½Ñ•ö(H>ÃäÐíÞ9.à}Ž øü †f•P‡á øý縀÷9. ‡e÷. ï ‚ž{Gë©ÃpS=~e•“Ïp+šìñãÞ縀ϊ–Øí<: PðÒqbãÞ縀ÞÝ;¸€¼3\@ˆ~îãÞ縀÷òнs\Àûb.à¯?𾘠xW„ö†yÇÈñÎruïà‚c ðнƒ H? awïàR‡áÞ[›ÞOpyg¸€÷°åÝ;V$ï ðžkÒùð>Ǽ§Õó¦cqé‡áÞâvïð>Ç\=Ý×: ðÞÅéúð>ǼçkŒÅäáÞêuï7ï ð¶ƒ{§ü¦† x Ù½s\Àûðž4Ç(‚w† x(ܽƒöÀ;ü§ÝßbcѨÏpïaQ»wpé·á>3šìçZu.à½/‰Rö. ï ðž4·26.à}Ž xÛ×½ƒFÂ;ü”âÞÁ¤† xÇ@÷Žs3ý0\À_ŠN6ÎM,. u.à=\Ü;¸€¼3\À{@“î\@Þ.à=ÏOÏ+\@ê6\À{8ª»wpÉg¸€÷¼0ê²wШxg¸€÷p=rïð>Ǽ‡k˜{‡ú ð„Ü;Ǽ/æ¾42݉X\@Þ.à= 2÷Îqïs\À{¸f¹wÐÒxg¸€÷¤ubשÛpïA Á½s\Àûb. ¦Î½ã\Ë;üçEiÜw† xÏ žs‹ È;ü'­·‹ H݆ xB î\@ò.ཕ¾KÁd¾ ð3™ý |† xÏŒô¼ÂäáÞó9Ïiˆ xŸãÞsJzÏÁ¤† xGQ÷. ù ð¦Í½s\Àûðž¤ë†^B† xÏm%>gwò. žùºð>ǼçŸÓ÷Nè ¼3\À{0ïÞAÓ¢>üç¶b_\@ò. žùwŽ xŸãÞÃô»wpyg¸€÷Üšî\@Þ.à=\3Ý;¸€Ôm¸€÷Ü6¿s\Àûb.ோÃ;ü‡ ·{ †: ðžÛfúwŽ x_Ì\’î\@Þ.à=IqïàòÎpïù^zžð>ǼgxdœÈX´"ê6\À{nîë† H>ÃÔ3ïð>Ǽ'Ã]€ È;ü‡K¹{縀÷9.à=\äÝ;¸€Ôm¸€÷ܶ»縀÷Å\Àé~ÃäáÞ“æˆÇƼÏqïùp:\@Þ.à=\3Ý;¸€Ôm¸€÷@žuï𾘠(áÞÁäáÞóÀ½ƒNÀ;ü§4×9ÍPŸáÞs[©Ï|† ¨g7Û;ǼÏqïÙ?}çæ´Ç;ü‡-ïÞÁäáÞóœt¿9IP·áÞéÛ½s\Àûb. ÐŽ{w† x$Yí;ǼÏqï=àÞÁäáÞ“ÖE‰Å¤nüÁ÷Îqïs\@@½{縀÷Å\@=tïàòÎpï¸wŽ xŸãÞscºßÐT¨ÛpïA ƽƒ H>ü'sçp\Àûðžï¦ç . u.à=|H[ ‡!â/ôÁ;ÃTŽÿ¹âgõzá8÷;(ÄÚ,¦[[¿½-¦{_¿Ý-¦Û\¿B‹é~×oxÈí´MÌisûëgÚÀpËûùºáþ~+S_Óƒãûu‹Áë½×bpy¿b1Ãßu18»_²<Ý{,7÷sq m£¦ëìÜÜÏX >î݃ƒû)‹Á»½Ëbpmï´:¸×ÞaïàÚÞn1øµïµœÚÛ,ÿéV‹Á©½Åê€÷v³½ƒS{“ÅàÑî²ÜÙ-_ö‹Á‘½Þꀿ¸ÓÞÁ‘½ÖbðbwX .ì5ƒÿºÍbp^·Zð2/·wp^·X žë&‹ÁmÝ`1ø¬ë,‡uÅàǬ²Ös,oél‹Áa]a1îÐË,‡u©õ¾ý{‡u‘Åà­Î·\ÕyƒŸÚn18©3­x`SíœÔÉ£ß,÷Ôï?îô~ÿÁ=uû-Â&¿ÿØ%nÿ¡!Øä÷ÜS¿ÿà›úý‡ŒßhÀøý§ÙmôûO|žF¿ÿÄùiôûO¼ F¿ÿ¤›ÐhûýÎF¿ÿÄMi´ý‡fP£ßb!4úý'ŠF¿ÿÄMj´ý‡ÖI£ßâ25úý'¾S£ßâD5Úþƒ7Õè÷Ÿ¸U~ÿé6ßè÷Ÿ¸X~ÿ‰ÁÐè÷Ÿ8]¶ÿà}5úý'nX£í?4˜ýþÓŽlôûO|³F¿ÿÄIk´ýo­Ñöº“¶ÿЦlôûOœ·F¿ÿÄ‹kôûOܹFÛðëýþ“®D£ßÒžhôûOF¿ÿÄËiôûOœ½FÛèã6úý'ŽN£ßâå4úý'Z£ßâ6úý'a£í?x†~ÿ‰‹Øè÷ŸøŠ~ÿ‰ÓØè÷Ÿx~ÿ‰Ùhûþd£ßÒiôûOZ!~ÿ‰{Ùè÷ŸðJ£ßâh6zü'æG£ßâb6zü'þe£ßÚµ~ÿ‰gÙè÷Ÿ¸•~ÿ‰OÙè÷Ÿ8” ~ÿ‰7Ùà÷Ÿ¸’ ~ÿ‰Ùà÷Ÿ8‘ ÿ O4øý§ÜàñŸøŽ ~ÿñÎí?óÎï?qüþ“&Jƒßâ>6øý§}ßà÷ïüþãßâ>6ØþC[§Áï?qüþÓNjðûw~ÿñÎï?íª¿ÿ¤MÒà÷Ÿ¸ ~ÿ‰ñÖà÷ïüþãÇâ>6øý'm•¿ÿÄújðûO|Ç¿ÿxç÷ïüþ÷±Áï?ṿÿÄqlðûO¼Æ¿ÿxçñïüþDZÁözÉ ~ÿ‰ãØà÷Ÿ˜C ~ÿñÎï?Þùý'Žcƒí?´üþDZÁï?ñüþãß¼óûOÇÛh;6øý'Žcƒßâ56øýÇ;¿ÿxç÷Ÿ8Ž ~ÿ‰×Øà÷Ÿ¸Œ ~ÿ‰¿Øà÷ïüþãßâ2Vüþž«øý'ÎbÅï?ñ+~ÿñÎï?Þùý'ÎbÅã?Þùý'\XñøO¸°â÷Ÿ8‹ÿO±â÷Ÿ¸‰ÛhrUüþÓìVüþî©øý'|SñøOø¦â÷Ÿ¸†¿ÿ¤ñTñûO\ÊßâVüþ§°âïâVüþw°â÷Ÿø‚¿ÿ„±*~ÿ‰XñûO\ÀŠ¿ˆÿWñûOœ¿ŠßâùUüþ·¯â÷Ÿø|¿ÿÄá«øý§{@Åï?Ý~*~ÿ‰ŸWñû€~ÿ‰‡WñûOÜ»ŠÇºsTüþÇ®â÷Ÿxu¿ÿÄ¥«øý'þ\Åï?qæ*ÿ‰'WñûOܸŠßâÃUüþ®â÷Ÿt*~ÿIHÚš6&ý ŠßÒªøý'¢Šßº[TüþÓÝ¢â÷Ÿn{¿ÿÄü®„û_Åï?i*UüþÃt¡ßÒfªøý'œ]öûO8»ì÷ŸX§eÛhö•Ãý£îe¿ÿ¤3UöøOZTe¿ÿ¤WUöøOwDzßÒ½*{ü§RÙï?áã²ÇÂÇe¿ÿ¤·Uö÷?íû²ßÒç*{ü'-®²ß¼sûϼóûO:_eÿÓl•ýþ“.XÙï?i‡•ýþãß¼óûOºceÿ¶.ûý'²²ßÒ2+ûýÇ;¿ÿxç÷ŸtÐÊ~ÿé£ì÷ŸtÓÊ~ÿñÎï?ÞùýÇ;¿ÿÄ¿,ûû‡ô®Ê~ÿIÇ­ì÷Ÿp@Ùï?ÞùýÇ;¿ÿtC*ûûŸv^Ùï?ý/{ü'­¸²ß¼sûϼsûݺ²¿ÿéY¶ý‡Î]Ùã?áõ²í?ôòʶÿÐÔ+ÛþCw¯ìïºÙ”mÿ¡ÓWö÷?ÝÕʶÿÌ;ïƒwÞ‡tàÊÞ‡îÄeï¥nÿ¡-X²ýgÞùýÇ;·ÿ¸Õ•üþÓ^)ÙþCß°äñŸî%ÛæÇ¼sûýÄ’ßÂ.%Ûè-–þ+Ùþ3ïüþãÛè9–üþÓ »dûýǒߺC”lÿ™w~ÿñÎí?ô%Kþþ¡û\Éöz”%ÛøZ(Ùþ3ïüþã¿ÿI®äﺖlÿ¡ƒY²ýÇ}¥dûϼó÷oÞ¹ý‡ÎfÉöwè’í?ô:K¶ÿØs%Ûæ]¾ÿJ¶ÿÐ-ùû‡nZ%Û臖lÿ¡‘Z²ý‡~Éï?ÝŠJ¶ÿÐ!-ùý'Ì]²ý‡niÉï?ᤒß¼óûw~ÿI½£ä÷Ÿ0wÉï?q§K~ÿ S–üþãß¼óûO¼’ߺ1”üþ/¤ä÷Ÿ0eÉï?ÞùýÇ;¿ÿÄ)úý§9(úý'^HÑï?Ý“Š~ÿñÎï?Þùý'îHÑï?áË¢ßâ‘ýþÓ-³è÷ïüþãßâšýþ®-úý'ÞIÑï?ݳ‹~ÿñÎï?Þùý'nJÑï?áÚ¢ßâ©ýþÓ½è÷ïüþãߺÙýþv/úý'^KÑï?ÝP‹~ÿñÎï?Þùý§»HÑï?Ý$Š~ÿ‰SôûOœ¢ß¼óûw~ÿ‰+SôûO\™¢ßâÊýþÓ=²è÷ïüþãߺñýþÓ­¥è÷Ÿø4E¿ÿ„“Š~ÿñÎï?Þùý'žMÑï?qSŠ~ÿ‰gSôûO¸¤è÷ïüþãßâÜýþw¤è÷Ÿø7E¿ÿÄ(úýÇ;¿ÿxç÷Ÿ8:E¿ÿÄY)úý'¾NÑï?ݤÿ›¾+øý§w¿ÿÄã)øý§›DÁï?qz ~ÿéžQðûw~ÿñÎï?ñ~ ~ÿéÖUðûO ‚ߺÓüþãß¼óûO<¡‚ßÚ¿ÿÄ *øý§ù+øýÇ;¿ÿxç÷Ÿ8C¿ÿtS)øý'þPÁï?áõ‚ß¼óûw~ÿ‰?TðûO7³‚ßâüþÓüüþãß¼óûO\¢‚ߺüþ—¨à÷ŸöAÁï?ÞùýÇ;¿ÿÄ+*øý'^QÁï?ñŠ ~ÿén]ðûw~ÿñÎï?ñŠ ~ÿ‰£PðûO¼¢‚ߺ×üþãß¼óûOÜ£‚ßâüþǨà÷ŸxE¿ÿxç÷ïüþ©à÷ïüþ¯¨à÷Ÿx¿ÿxç÷ïüþߨà÷Ÿ¸#¿ÿÄ7JüþÓ=>ñûw~ÿñÎï?ñ¿ÿ„“¿ÿÄCJüþÓÍ8ñûw~ÿñÎï?ñ“¿ÿ„Û¿ÿÄOJüþÓ­1ñûw~ÿñÎï?q˜¿ÿÄ×IüþŸ)ñûO·ðÄï?ÞùýÇ;¿ÿÄsJüþÓí6ñûOœ§Äï?Ý3¿ÿxç÷ïüþ*ñûOÜ Äï?ñŸ¿ÿt_Iüþãß¼óûO¼¨Äï?á›Äï?ñœ¿ÿtKüþãß¼óûOܦÄï?qŒ¿ÿÄsJüþcnüþãß¼óûOü§Äï?Ýw¿ÿÄ…Jüþ£ß~ÿñÎï?Þùý'ŽTâ÷Ÿ8R‰ßâH%~ÿÑ'¿ÿxç÷ïüþG*ñûO÷ƒÄï?q¤¿ÿ)öûwùþKüþw*öûOÜ©Øï?q§b¿ÿtßýþãß¼óûOœªØï?áþØï?qªb¿ÿtŠýþ§*öûOœªØï?qªb¿ÿÄŠýþw*öûO¸$öû°~ÿa/Öï?ñ¥b¿ÿÄ—ŠýþÓ}+öûO÷­Øï?q¡b¿ÿÄ…ŠýþÏ)öûO÷ƒØï?œÑúý‡ÕZ¿ÿÄŠýþÃ-™ßâ9Å~ÿ —Ä~ÿ‰çûý'žSì÷ïüþãßâ9Å~ÿéþûý'žSì÷uûý‡±.¿ÿ°îå÷ÞÀüþ˜ß8óûe~ÿaIÕï?,¯úý‡5¿ÿ¨Ûï?§ùý‡‹5¿ÿpÇæ÷öÛüþÃ՛߅óû÷q~ÿajÎï?üÒå÷¿Øï?¼Üùý‡ü¾ß¸ËóûÏÕs1´týþCo×ï?4yýþC·×ï?´}ýþC÷Ùï?´€ýþC/Øï?4…süùý‡6±ßèûý‡Æ±ßè ûý‡V²ßè)ûý‡æ²ßè2ûý‡v³ßè;ûý‡´ßèDûý‡–´ßèMûý‡&µßèVûý‡¶µßÌßhdûý‡Ž¶ßhmûý‡·ßhvûý‡®·ßhûý‡>¸ßhˆûý‡Î¸ßh‘ûý‡^¹ßhšûý‡î¹ßh£ûý‡Žºßh­ûý‡&{¾ÿä‡)Ý‘ßè¿ûý‡F¼ßèÈûý‡Ö¼ßèÑûý‡f½ß¼óûw~ÿ¡wï÷šø~ÿ¡›ï÷Úú~ÿ¡¿ï÷ý~ÿ¡ãŸßÿðC6PšeÆ$B©æÎòãgkj>âØíbçOJôÆF¬C4^àÓ öGª0÷üd/p‰@ÇÈs¾{Ÿ„Zœ'xª}G…ZÜ,Ô^à{¡V™-<7e÷Âxi¨f5®ª/Œ?‡ê ãä¡úÂx~¨¾ÀD->"j9Œãˆê ãM¢ú¸˜¨¾0~'ª/Œ3Šê ´çj/p[Q«_µ8¸¨å0^/ª/Œ+Œê ücÔ^à4£V‡ñ¤Q}aÜkT_ŸÕ8⨽0Þ9ª/ØPµ:ðãQËZ_-º~µÆ Hõ…ñ R}aT«/Œ‘ê £TX}a4 «/P?¬½0žIª/Œ¢bõ…ñaR}aT«/Ðs¬å0.Pª/Œ_”ê £&Y}a<¨T_·*ÕÆ×Jõ…qÀR}>fíJšµ:Œÿ–ê £ÎY}a<½T_ øY{a|ÂT_Ñê £7Z}2i-«ñ3S}aœÏT_]Ôê 㦦úÂh­V_ ÊZËa¼ÜT_×7ÕF¶úÂ8É©¾0:³ÕÆNõÚµµÆñNõz¸µ:Œ‹žê £±[}aœùT_?Õ(üÖ^-àê Tƒk/Œ¾põ…Q"®¾@³¸†2Q7®áE㉨úÅäÚ ã³¨ú¨0W_ïFÕ(;×^ ]Ëjœ#U_ +]{aÜ(U_­êê ãp©úÂè_W_×LÕÆ_SõêÛµF§»úÂ(zW_íïê ãªúÂè‰W_RÕF£¼úÂ8›ª¾0¨ª/ŒBzõZêµ:Œ«ê ãÕªú%÷Ú 4ßku§XÕÆSVõâ´µF›¾ú¨ØW_ï[Õ(ã×^ ýê 㼫úÂxôª¾0n¾ª/Œï¯ê \Ô^ÿÕ8 ¨åÀ“@í…q/P}ÏZÆYõ…ñNP}a—U_ofÕÆÅYõ…ñxP}aÜ T_ßÕÆaBõ…ñ¢P}a\+T_ ÕÆ Cõ…ñÌP}aÜ5T_àá–ǵÆÛCõ…qW}_ˆZã,¢úµ¬Æ½\õ…ñ5Q}aÑU_¯Õ¸ª¨½0þ+ª/pjQ«Ãxº¨¾ÀýEí…ñ‰Q}aæU_/zÕƵ^õ~6jYóê 㙯ú¸뫾0>üª/ŒCê 8µ¬0j9Œ_Àê ã,°úÂx©¾0n«/Œ‘ê 〰úÂx#©¾€=PËjüV_§†ÕÆÃIõ…qX}a|"V_G‰ÕÆ{bõ…q¥R}aü«T_ç‹ÕÆ#cõ…qÓX}a|¶T_‡ŽÕÆ»Kõ…qýX}aüAV_'‘ÕÆsdõ…q#S}w¡–Ã8œ©¾0^hª/Œ‹Êê 㯦úÂ8³¬¾0žmª/ŒÛËê ã§úÆC-«ñšY}a\iV_À¨½€ Q«>D-¬ˆZã±§úÂ8ò¬¾0Þ=«/ŒËÏê ã´ú¸ª¾€'QËa܈V_ߢÕÆÝPõ…ñBZ}aU_oEÕÆ…Qõ…ñkT}aœU_HÕÆ-Rõ…ñ•T}ÁÍ«–ƒ[L-ÑZ¢µDjY¨åÀ-SÇ øÕ¬8dêÈa¼?U_—PÕÆOTõ…qU}a:^ÇÕÆFõüZ­»ù81êȱ›ÿû¢Ž¬ð?j9ŒƒŽê 㻯úb7ÿEYÓê øµ¬»ùø(êȺ›ÿw¢Ž»ùø%ê¨c7ÿD/vó?ðEÔQÇnþ^ˆ:^ìæà¨#‡q¥X}a<«T_w+Õ»ù8êȺ›ÿ«¡Ž»ù8ê¨Ãø¬¾ØÍÿÀ·PGÖÝü¼ u¼€ÿQË ÿ£–c7ÿOBYwó?ð!Ôñb7ÿïA/vó?ðÔñþGm+Ãÿ¨ÕjÜìT_ß;ÕÆ-gõÅnþ.‚:jÝÍÿÀ9PGÖÝüÜu¼0>‚ª/àÔjÝÍÿÀPÇ øµð?ju?¥ÕÆmQõ…ñeT}±›ÿןŽÆ!jõüZ­ÆiRõ…ñ¤T}aœ¬V_Àÿ¨Uf1U_Àÿ¨½ØÍÿÀ¯OG»ùxôéx±›ÿ/ŸŽð?j•íæà§ã…ñ:[}ÿ£öþG­2øµƇUõ…qlU}a¼ÞV_ìæà§§£Vã4·úb7ÿ÷<YáÔrìæà•§ãüZð?j9vó?ðÄÓñ¸ÿª¾€ÿQ«l7ÿï;/àÔ²îæàt§ã…ñHV}±›ÿ¯ŽÊàÔrìæàb§ãÅnþÎu:*ÛÍÿÀ­NÇ‹Ýüêt¼€ÿQ«l7ÿ?:/Œ3·ê øµ:ŒÛ·ê‹Ýüçt¼0^ãª/àÔ*ÛÍÿÀYNÇ‹ÝüÜät¼€ÿQ«l7ÿï8YË»ê‹ÝüœâtTf<æU_ìæà 'ÏŠ£q;ŒšBƒºëŽ þ WNbE—V숗“bŽôS=#ô:yÓìšÚ†æöTÛ²ÄÌé§'ÛNÄf}ÛŒTc]²ubSMí’Tí²¶‰ákʲ(ç[¥ãÆ"Â6ܸ(ç†Òq㣜KÇ„ïÆš¦äAãÆ Ö6Ü„(çŽÒñÅÀÍ?*ÊùeéøÑQξ©¥ÉåÉÆƒð’\9²½µ¦¹­±¦½!Õ\RŒráSU,åSU¬.3š*Öð©*Öò©*ÎçSU\À§ªXǧªXϧªx&ŸªâB>UÅ>UÅöÒ1c¨â>UÅ øT/äSU¼ˆOU±ƒOUñb>UÅKøT/åSU\˧ªxK阱TqŸªâ­|ªŠ·ñ©*ÞΧª¸™OUñ>UÅ;ùTïâSUܧªøhé˜qTq'ŸªâWøTãSU|œOUqŸªâWùTŸàSU|’OUñ)>UÅ—Ža<‹·ð©*þ„OUñ§|ªŠ?ãSU|™OUñç|ªŠ¿àSUü%Ÿªâ+|ªŠBé˜#¨¢È§ª(ñ©*Ê|ªŠ Ÿª¢OUÑȧªhâSUôãSU4ó©*,SBãùTñ©*æSU§ª˜À§ª8”OU¡EÑNZíT1™OU¡E1›*´(fS…ÅlªÐ¢˜MZ³©B‹b6UhQ̦ -ŠÙT¡E1›*NæSU\:¶˜*áSULàSUʧª˜È§ª˜Ä§ª˜Ì§ª8ŒOU1…OUq8ŸªâøÒ±Ú]KøT'ð©*NäSUœÄ§ªXʧª8™OUq ŸªâT>UÅ2>UÅ¥cµ»Öñ©*Öó©*žÉ§ª¸OU±OUqŸªb#Ÿªâb>UÅ&>UÅ‹JÇjwíàSU¼˜OUñ>UÅKùT×ò©*^Ƨªx9Ÿªâ§øT;ùTo/«Ýu3Ÿªâ|ªŠwò©*Þŧª¸…OUñ3|ªŠŸåSU¼›OUq+Ÿªâã¥cµ»îâSUü*Ÿªâ|ªŠOò©*>ŧªø5>UŧùT¿Î§ª¸›OUñg¥cµ»¾Ì§ªøs>UÅ_ð©*þ’OUñ>UÅ_ñ©*þšOUñ7|ªŠ{ùT•Ò±Ú] |ªŠF>UEŸª¢Ÿª¢™OUÑŸOU1€OU1OUѧªÐ¢`wiQ°»´(Ø]Zì.- v—»K‹‚Ý¥EÁîÒ¢`wMåSUhQ°»´(Ø]Zì.- v—»K‹‚Ý¥EÁîÒ¢`wiQ°»NãSUL,§Ý5‰OU1™OUqŸªb Ÿªâp>UÅT>UÅ4>UÅt>UÅ >UÅI¥ã´»–ò©*NæSUœÂ§ª8•OU±ŒOUqŸªât>UÅr>UÅ >UÅ…¥ã´»6ð©*.âSUläSU\̧ªØÄ§ªxŸªâ>UÅf>UÅ>UÅKKÇiw]˧ªxŸªâå|ªŠŸâSUìäSU¼‚OUñJ>UÅu|ªŠëùTﱪŠ[øT?çªøY>UÅ»ùT·ò©*~ŽOUñó|ªŠ_àSUÜÆ§ªø$ˆWU|ŠOUñk|ªŠOó©*~OUq7Ÿªâ7øT¿É§ªø->UÅgøT bV_áSUüŸªâ¯ùT窸—OUñU>UÅ×øT˧ªø:Ÿª¢ˆ[U4ó©*úó©*ð©*ò©*ZøTƒøTƒùTCøT­|ª - v—»K‹‚Ý¥EÁîÒ¢`wiQ°»´(Ø]Zì.- v×L>U…»K‹‚Ý¥EÁîÒ¢`wiQ°»´(Ø]Zì.- v—»ë >UÅ®ªâp>UÅT>UÅ4>UÅt>UÅ >UÅL>UÅ,>UÅ|ªŠ#ùT§rmPËøT§ñ©*NçSU,çSU¬àSUœÁ§ª8“OUqŸªâl>UÅÅ\+TÅ&>UųøT—ð©*6ó©*¶ð©*.åSU\Ƨªx6Ÿªâr>UÅO•Ž×îÚɧªxŸªâ•|ªŠëøT×ó©*^ŧªx5Ÿªâ5|ªŠøTï.¯Ýu+ŸªâçøT?ϧªø>UÅm|ªŠ÷ð©*~‘OUñK|ªŠ÷ò©*~½t¼v×Ý|ªŠßàSUü&Ÿªâ·øTŸáSUü6ŸªâwøT¿Ë§ªø,ŸªâoJÇkwÝ˧ªø*Ÿªâk|ªŠ¿åSU|OUñ >UÅßñ©*t bwéÄîX:^»«…OU1ˆOU1˜OU1„OUÑʧªʧªƧªΧªÁ§ªÐ¢`wiQ°»´(Ø]Zì.- v—»K‹‚Ý¥EÁîÒ¢`wµó©*”žÝ¥ôì.¥gw)=»KéÙ]JÏîRzv—Ò³»”žÝ5›OU1¸ôí®!|ªŠV>UÅP>UÅ0>UÅp>UÅ>UÅH>UÅ(>UÅ~|ªŠ¥GhwÍäSUÌâSUÁ§ª8’OUÑΧª˜Í§ª˜Ã§ª˜Ë§ª˜Ç§ªX^z„v× >UÅ|ªŠ3ùTgñ©*ÎæSU<…OUñT>UÅÓøTçð©*6—¡Ýµ…OUq)Ÿªâ2>UųùT—ó©*žÃ§ªx.Ÿªây|ªŠ­|ªŠëJÐOUñ*>UÅ«ùT¯áSUÜÀ§ªx-Ÿªâu|ªŠ×ó©*näSUüBéÚ]·ñ©*ÞçªøE>UÅ/ñ©*Þ˧ªxŸªâý|ªŠð©*nçSUüVéÚ]ŸáSUü6ŸªâwøT¿Ë§ªø,Ÿªâ÷øT¿Ï§ªø>Û£¬ï´ÕÖ4צê’PZžçc::\Ts"Ÿ_[Òš<1Ê9¥j.ù½ï2ñlw1¶wãÿù‹Ý_”'»ÅJ$Â×y5­&Â'ܱbÌŠE›wÌü»Pô ýfBeZÕ?’2ºñÊ.:µ¨âEÑ¡õþÿüC‘Y,:’ZóþC|_l1× ƒléŸÔܰ´9ÕJWÝ[ŽÞ¼õ{Rsk²%Õ ¡ÈÙ3æü}‘À'5×´ÉJ¥É I½KNj®¯i¯‰í‡bŸÎøµÄ¢€“DªõÇJòáå Ééå é…—74ìê…¾L½¢•O¼xzùÔbr¸·ÐìK±ÀàÄ‹+æÌéÄ¿…ÒL^ÍÖÄ‹ËçÍ›[š6o¡ðóV¤ó‰W–Í©«ÃõÂ?=ý|¢è”õ’ß÷:}é‡ï!}óóhsÛÚ¡½1s"4NhK¶60@——Ÿèf’ÔTÉ=4Nè–}á™7÷Üuæ§{î<óÜžÛ×fá×e\Ï%“ PÎ…˜Û¾8gˆÖ#ê\hÝ„Xpj4¼j›· rÓu¼uß‹J ´µC”l‡~» â®ÏÓÎǶ¬hQÉþQe×°œ O£îíÔ½ºOéV?èt[Y·¦yæQE Kâî­œUµ¨º¥±ciCsuCsC{¹hjÖÿx‹AœWÞî’#º°ÈbP —ZŒ¹Xeù ÊN|횃½¼¥˜óùÓü½¤Û‰~š™d-ûåÍ;kŽ ~6ûœîÇ\Eå¢ÙÙ9SŒV˜úlþ BEÑ44½8ôúŽÝW=}?ŸÆç¶îÙ›XÞ1¿|^dµ1ÐÖ±ä¹Ã϶›é;4¿é̪ë;÷‹öößÌs;$ÇtV‰o‹†§ã²Õº“\Ìp{tèð®U{®Í‰fñEÉ⬱âɲ ñÂ9}qÕ¦=°„=0ßïêüÓa$ï‡UW×¶WWµ¤³ÚæaõŒå6¿Ðu[m®!ó޶TßñåmRë0s2ÕòA ži1(Ë,r².jöäa~¦µhÛ þ Ó{ ßЗÛ.€Üܹ ˜C¿ ˜K¿ ¨ÑïhÒôQ›¶ß‰½»8YQáç"°0áíÝyn^ÇD{³³«X;¤RÍj:»WÞT0®t5;ZïÒùU¬sæØ½Õ¹³ör7wkç.ÌW6w~¾ Ï·˜FÎÍl@ ¯Î†b»4yn6˜[ ŸˆE4›Ÿ7ßUÞV `l›Ë倴ÞËj6?/îΔvq]Ý{hî¼—ÈBúþ’NgÏÖ¼‡?:–Ül~^kriC[{²5Ñš¬©{ÞŠÖ†öäÄDqçÁÅc;}=Pë‡Å‚œÍÏ«M5JÔ´“bF}ÉóJ ­/MŒ•]x;Ï"æEŸ“lFóó4Ϫé¹ÚfyçDh¡W3=Wƒ‰®Fc;ó¶´¾rßv°ÓvöïvÞoçývÞƒ§¶Õf­_}Z´÷ê3¢Ýý,Ofôœšs¾Í}± ÿvÃ¥7q7ûjëâw®=-J„Øx{åi¤ÉbóBl~ˆ- ± !69Ħ†ØL†[:œ0ÿÔhl „æv(çíÈ(´3µíªÌF”g6$Âw=ZÍ 5¬ØXƒdÚzhgÂfs е®^ƒ0G5¾,Än ±÷†Øí!veÅÝ ‡­§/FWúØ uÑU!ö«ék¢«CìîûLˆ}6äþ\ˆÝr|)ľb_ ±{Cìë!öÍûV&G!V ±†k±–k ±!6:ÄÚ2³bvg˜™ŠãacvgؘÝ6fw’Ùdcv'Ù˜ÝI6¶$ÄìÞP솺¬ô¼+vZˆ>±;çÎna[I)´#¬ð‘Ù/ä0;J©Ýo%ÍÑùvÎYhÓ·æô”®î¹Xum ZxërðÖ&á­÷ƒªXË@Áb!X‹sF/ÖR‡RŒ«ê%ëmcøx§Íbê^ŠÍÀI,†ðÈd‹q£˜j1ðÖÌp'i÷KAØÄã:dO–Y Q” “dŠdù³Ø:‹a÷ã&‹aä‹a'äsV–7¾nï´Ùe-ÄâF$_:pcq²8û7"‚âïÆè¦‚5µqûÞ{SQÔšlKn´3œ­lƒó¡9(–Y÷Ɇ”C„mõ­©¦„N–NN,áÕ†dó‘«c+-7¢6ä– Ï¸OöaJ[Á¹uu”¿ÙŠh{n"º})VñMn$r¥›Ç}²£¹­£Eõ®­KôõÀUpT\âm¾oˆî€™%ô3î“ËÌG%\Ó;£½n²ùTO z0éÆ}ràæwÝêžÛÒw?]ˆÛé¦Ç @×-a„ßmíLwºßºß´ï}×0 ­”­Î-~] ŸØUu5ä\8§;7ár¢;ÉÁ=£ù5çe;ŠèKÏ‹._|gNÖp‡½”G·"Ÿo¦ò›`± Ä&[lt÷)`>-‡•ÇgîV¶Oªeª}ÏŸ‰å“mHKmË}x[Ö<ÞÝÈ›;ªòv/áûöªÜá»ëÁ‹åèÒ*ì{m]œÓÙÕÍÿæt’k“õÆôC5Œ¦ÖÂÙ9ÑU¡æ;éÃ6rL 9’Áçø»ñ`Žvßoå¡·äÈß§oòù¹Ózdêÿ¿ó3Ó¾u³½wäE_¨Ê-ÝŒ®$vWz>Þ ÙHªV#=°í)ÑUÃJŠùþzU¹£ÛªòGŒåû+Uy‰ñ|¹*w÷’5 à߯è·+üŒíâÿü¿'§óä}\MQ7ì‚mY;Wå“»’5ÌÍi%+×ÍéàÝJû&ŸSjøC厯\”ƶ²FV=…~4e¨F?š²ª* MY WSSÖÞ®¦¦¬Ý]MÏÌ~úNY…kò}‘ —ç™Óéö–N‚v>„…»fÎï¯ÿ4sì»FÖÃ¥ÖÃ%ÖÃEÖÃùÖÃyÖÃvõpöKÀÚ’GQ|æïû(f‚룛warû=oG_ý^y²¯“í{oM…–=‰kè>¬qÖ'ó§ôÞ»àôr ¶ƒkª˜$$š[t Xðܺêe5ÍuÉÖH¸lù‚ÁÂ(àb©ÁÅSƒÛ ·"Ž6ßÞ—fð¯î ö’jƒ£¿”‰ÉÒI“uœ4&;C67V‚<ŽV­²fdßa7è½™ZeýÈòK¨µ-`g,›è6Øà%àÀ„+\o,™È¹é¶ÆÄ1Ic➤1qRÒ˜ìD¤1ÙŒHc²‘ÆdóÞàyÄê:ð|i„†Óáy[¿Å´HÝ[˜ó4p°9̶µ§€t Ä]^DóÈ+A»9OHê»Èënkó"¿×Üäy·t&–¡™!îý³—%›Í©öD²©¥}e”“Î ßØ$Áœ§-©é ç¹Ô ƒƒ°þALœËƒàÁ±u‚¼Î ÍäÚRÓÞÑ–©Õ²¨”ÚçFXðØdAžûä¹ÓËgoKîr#SØÛ1˜ó´þC瘸Ãä·„K“éaço-A,û)pçžó4Ý>\Ös«¿qÏEÌf.ܯpÇžËÐï¾#h»í¾#èM;Œ¥t·ò·„ÒúGn «ÞV›uì¤fœšw‘nwqWß‘›5¯*§´ˆïÓ„}VD‰ñWqsßÀöQÏ–Nަó½ä*þ ›}ßÊŽ‚t6æº,îàq4Ûï’™Øáj×í\Ýwµ~Éa%Å6r8M·Ïÿ‡·u3µ|ÔðöGÁÛê¥îÙ÷¯Énb_ºçWEùSV-ŽJÎÎ>$¡nŽÊÛ^ ¯àíð >@w¤¿l®è®µ¼µy‹Ä–X¬ØR‹ÍïŠv/e>ZÝ|T¸¹¸=cg,žÞ%2ïÓÛJú^³3Aï›ã÷Ù;‡ZGä¹}áÞÛ›ŒÞ/튊{ë2y³üé>¼!ìÃk­Æê>Ô¬mq˜†y°³²È¾—Ø7ø`ÙÇAß¶ÖÚ³Ó„ÌM§ß~ÄÀÕ[ ,_Ùí‹)røô‘cÍ Ûà9ÜmY4KsÈÞYZŸ¬§Ùú° ·"܅αwº?È®_Z·lüÙwº-È`úNÖí;Ý d=0Y´÷%f¢ó¾$Šz™›@™Ç"üÓüó2¹°"hr žìïKÄü}‰˜¿/ó÷%bþ¾DÌß—ˆ…šü} êŽûRyˆ¶î¾dë·7 D¬%“XB®ôé§é†áîw„Ý”r%«{É–6žâ–Îêö†&VÒÞÕD½vvÑn¶>!²ÝÑ'z‘ö‰Þø>)/7»™g<µ·OÛ¸¯\?a&Ãí3ߺEØow˜Ör¶u±Óª ¾Åï=ŠÎ W›á 3Z•cGNô!°æ­™Z G#r1åtup«¡ŽE†‰CÍS­æùÖð¯}u~4Á{}ÚG²ûõ¶-æ?>€…™OÙ¸•™Ïn˜Àï9°Â½a—mV‘Hï˜Uæ1UæÚÏ*ëšã2ò’kžñ?vÊ%Oî$ÞýNA˜bßN¡7¾OäÕ•½Ìž^óÖЧ[ݼ‰%m¾«¸~÷-é‘»Ù›¹…\Ÿßç»û¾…YMûþĬ‚ñ«—9*̰°·É‰X|oN»“ºr"9ß›ÓîóÝ9 îíÉi0n='¸¹7§ñ–ÒLÝÛÛ¬Þ›Ó$íÎ ÖïÍiuÄj9Ù#ˆ÷÷öÓÞœºr²òzsÚ[ãîœæÖÑ›]„zNn"½9­®BWN´(zsºÛþîœhVôæt|ÓÝ9ѰèÍiï˜]9Ñ·èÍiïé]9Í-¨'§Õ$êÚænó@N‡ ºf£½uZ]¨®œØEè͉~X='gÃÞœV‹,äܘ#œ ~-öæÌl8ƒALÔsXŸ‹6‡ÑÕëÎa@×â”Ëž®ç°v¦Ã+éÎá´´lc¹¥;ï|¸²õ¼ó9àâÖsðÎç€×[ÏÁ;Ÿîp=ï|¸Eõ¼ó9Œ½—î¼ó9Œ-—î¼ó9ЩçàÏæH=ï|xìõ¼ó9Œu—î¼ó9ÐϪçàÛ [tä0p”w>X¢žƒw¾VtqêµòÎç@/§žƒw¾V0H½VÞù:Ðש×Á;_¸¤^ï|ø õ:¬– ­žzÞù:Ðé©çàÏalÐuç௕I=ï|të9xçk…SSÏÁ;ŸÃÜOºsäÖ# ^é¶YãžaÈÕŸ…þÑSd|EbŽ2Ò¢ë[Ó´X¡´éx§ýy-Áßw©°0 Bäý°8e~M/·|XFq55I½O—ç&M•˜>M2Ó£õÓµFuö[çì·ÌÕøV‚ßp©Ñôföørõô{Mœ¯ù0÷"Ë—v¡™*éq³ìoè>0H–_į¢A‘ìÝY(UõC1G…5ø¡Ì2Vé‡ÂUˆáå “ÅXqFs/*0c¹=èT§î^mÔS‹·ÁK+p¥kƒ·Qàö<kUŒè¸=âÛÃõ.ë&ª0ác¯o˜¬òfmlÔüÆmÙU­ïù‚¡2‰u€l"ÉÜÅt‡ƒßx!AÍÒx]ÐÔ¹ñ²~"&Äx©nªsãueP®ƒ„€…ÒÖDˆÝs°L¼ªU‡ÈØ«*?FÞ‘ YÕu(W*LñŠùÖÓ¡°=˜ŒCÅÂT]1}Ö˜(ó­Úº¹'Ç ˜‰\bç$™~UðÒê› rI DOF± 5ø(¡¨q8êS¨jL%,Șÿ( ”0ƒI,PßL¶Š3eÄY}9’ÿE&úHr™äv梈ɚv”I‹ô¼ÝRÍfÿ‰Í~u™o»éÌoŽ®ÑÚ*sél‘yÌæTçI1S38^2ƒG)¯fð(ÙûîhÝuq:D…ÑúctµÖÖ™ÏNÄèÿ|‰ÕlËv`vŽ¥–˜­r¬LÝ*ÿ±lš˜üÇríK˜ó…ìgfj!›œM¿Eß„í´˜™NèÁb6Ûë8½W=ÇÁNMxs<M ä?ä[`‡,‘¹fÍý_Öö;+Œ§œ€•½>A&5“'Âa+0+ËÈU O˸T²íNC׸È,Ÿ®YÓv=ÆR&Õ r•˜“³d\ý> k8%æå,&¬D gSw‰¾Ÿs‰s6FzJÔy¶ ›k¦ŸÂ”ØO¡%úúXO%fú©Ì[‰Úž*Ãäªÿö&£vŽ ÓkºÏÁÎM™¹8›9efävR£gOg'²}zw¼ žÞí´{w6ËŒeNņYm3`°Ênl¶†7àißzƒVVMÙø´ Àüôx(6ÖD>]\3uî¦ý wß±¿gHF@9ž!Z®¦çºkZW ãhŠVʶ6âJñó4µ+u¯ÑÍm•øØššUºÝj*Ïտ׆>W×{Mñ¹ÂÜêÞyšm™Õêú°\„5ý5âÙ©kžî0ˆ·•å·"Ã-2aÙGÝ[ó&ËÚò9P¼ÓŽØŒßnˆ•»-.<Á°"6aü›MöFû }3ÙÞ0 þÍkì öŽü›Ù K¹ßH‰K«G#UòìˆsŒŒ9 6(XŸ"Ç–ƒ‹ŒÃ_—i:”ã²ïÆo/»+=ÉvˆG»pè‚Ô\†·:í»ÃÞ+ìGÿB}v–[1“Úp1vZÁßEWñØ({¿}­ÛmQö>{Yl\”½§acÙÇMv¶ÅŒ²w“^ìý®.ýX¶kpL-û[žCpìŒ-1èÐtŽ…!¦™ë°íªWƶ+±gºêà¶²Õ—84îפçúHEã­Ü(0&Cu̶eˆau޽D­¡ó–÷@ñ¢At»1Þ. u²Áy%Å[íÈÂõÄ訷éÇ®ÃÄ 1òÎ2ó±¼9ÂbÊ´ º¨ƒÑ7Ûb§Æ­3Ak ËZóµÎª¬i>;ëÏÜtÀTÅ÷·“è G+Ì-sÏtŒ2“µt`Ž™ ¥Þô˜×GŒÝb] ’¸÷š‘[ê…ÊüŒvu1‘ξ™$jáÝPÛBL#{¼4Âå‡%Ë\jË0•®"~ s¤ ¤ãìÕ‚€ìN óÙiqz Žü¼AGÞa߈•{sÍ.ÿ-ƒë (Ÿ–‘ßL\âìf"ç=–³ÕmIoL’Ÿ·-INoj‰š½åIî;0좖/X-£Ý¤Òi̼ÝJ»Á³Z¼UKjñF.™„Ûüîò&0ít}¾¯_ÞD&?îL¾Fo@“½=MjsÙ©åÓx€<Þü&?o“Z¼q*rx[ÔâMwÒ/8e¾_Þ°'›ÊÛùíêý\_½Þ(?o”z½•Pr`4Ë×ëmˆR¯7)J½ÞÂ(õbp+«- ®h3ÝÅÈ[ä‡%_¯·)I½lF_¯·8I½`òõz{”ÔëÍS‚%ÀÌÄÀÞx%XÂÛrKxÓN` ,=KxÃO` oŠMÎ~$Æ&?Ív&› ÍnÁÌ6¤ˆaul…™æfü³'Ì ìéfL†àj³$ŒÑ¸ ÍŒ0JÏ2ÂlòçÆ„cõaÜé×jb`%îÉĦ{CÅE8ñX7wLlwI”R!“0пcâ|LŠaZ{ÊÞâp†¼ f_øåÔɤbÔŒ­J×Ù¨tœmŠí³ ÒÖ†½!¥ó]àbÞl‰»0™û¸ëöÑ<šñæbÙXO£*vwbÌ÷ êcÜ0ÞkÆ{™2¶¨ê÷Í’±·X\» pÒ|tX,†XQ³X\{‡mS³XŒÈšÅbÐzÍbqí×T0zÍbq­\à°\Y³X\{g§V bPcÍb1fŸj‹±‰Y³XÌÆ«Y,fk‹áTd7ަŸ^9ƒÅYÉðË@%Äï‰8§lÜ]¬Ò÷Lc¿=Ľ©b°tÍTqmÒaYÔ¦VLö‚='¾¢®þMYâ?ÈüeÌõ"fªc]õy£«E â` ǘÌdÇÜEµ}£,YTו¶€°N”Ú‰1 sý‰±¦ÃÚˆ1­Å¥›+wŒîrÌ%Ó;¡'Ó;!'Ó;¡&Ó;(ÑôNhÉô{êôËêôëôkëô»ëô ìô[ìô«ìôûìôKíô›íôëíô;îô~ ½Ã¶;½ÃÊ;½Ãö;½Ã <½ãÒOï° Oï°Oï`8:·éväéåé¶åéVæé¶çél z‡Uzz‡­zz‡Õzz‡ýzz;ƒÞaÓžÞaÝžÞaçžÞÁ¡wØÁ§wXħwØÆ§wXɧwØË§wXΧw0èÖôévõéöé¶öé,z‡½Ã*?½7½ú6½ò6½ê6½â6½J4½ƒIAï„MïÄ¥2½ÇôN,Ó;qFMïÄ£2½[ÄôN, Ó;a6Ó;±LLï„ýLï„ýLï„ýLï„ýLï„æLï„äLï„âLï„àLït•6½{ÁôNFMï`ÑÐ;yÛ0½cÅôN¾8LïÄÒ1½£ÄôN7}Ó;]¨Mïà)Ñ;)™Þ m›ÞÉà¡éØD¦wb\™Þ‰`z'¯¦wâèšÞ‰Çoz'„nz'¿¦wb‚˜Þ‰`z'~ŸéÌz'éøÞ‰_`z'>¡éø ¦wâê™Þ y˜Þ “˜Þ¡Eï„cLïн§wâ*˜Þéroz§K¼é®¦wâL™ÞÁ2¢wâh›Þ £™Þ ½™Þ ×™Þ ñ™ÞÁœ¡wB‰¦w¦wB–¦wœ¦wB£¦w©¦wB°¦wÜèP¯éì'z'¤lz' mz'tmz'Ümz'änz'ôoz§»€éÚvô½;zÇÕƒÞ¡gGït1½ÓÅÄôNWÓ;]VLïtm1½ÓeÆôN7'Ó;Ý7LïÐ>£wºÇšÞéR`z§+µé.Ú¦wºr›Þé"lz§[®éwº›Þé:cz§Û«éü8z§ÛŠé®.¦w€§wâ˜Þ‰U`z'¾é˜¦w°ÃèØ ¦wâ5˜Þ‰ñ`z'.„é0/½3G|õò ½Kx@ï®'ô.GZ½K¸NÒ»D"õ.áªCïqYÔ»„k ½K@Áô.Ak„ÞÁ¦¢w 8ŸÞ% yz—À*£w —z—ˆ%§Þ%\ªé]"¦–z ‹Þ%ÂÐê]" ­Þ%º áaj©w šÞ%`hz—€¡é]†¦w šÞ%`hz—€¡é]†¦w šÞ%ò©£Þ%`hz—€¡é]†¦w šÞ%`hz—€¡é]†¦w šÞ%`hz#Þ%`hz—€¡Mï„¡Mï„¡Mï„¡Mï„¡Mï„¡Mï„¡Mï„¡Mï„¡Mï„¡Mïî§wÂЦwÂЦwÂЦwÂЦwÂЦwÂЦwÂЦwÂЦwÂЦwÂЦw ÝÃr ˺áÑAÔdè Ìn:ËÂí¢ƒð¸è Ü>:(umn,àEl,Ej£æàîwÖ$(yÀ –iÀVi`˜Öù ‰æ¦JŒéÕTøÛ“áo{L‡¹ÿ1Þð÷ÝŒ±À=ïÝV5¾ÅÝÊÊ”è:ÌNq—a15Lï¬ít&E—-:Ä Ôð¼í|™*¹#q‹£Ì—ibÌL_.‹ì„£Íx;óÏ•š+)³¾Ø¬¬«³Æøº3»nì¬[#îtë¡[Ü£é·hºe­%Ò-á3ö.™lçЭ¹f³ âÒ-ßEºå;D·¸ðúnÍ7Cît ~Š5l¡Í`»ê1Fß¹wc©»˜¶¦1ÓîÜíÄ´mvçxÈXg·îè¡°i¢«yƒnÓ‰ì7ªÓÃÓͬ;±åfÓ7s8¿ÄÎ0kîÄÎ4Sîöî岸tã$Ãë™Ïlpǧ^fƒ;>1æ©&Æ.útÜ%úžN¸&:ñ¶$µ=Ìô8cõÆ<±¿âÁaù‹íí+«ꢂO#fMÍ,rÚdQÎê^ÁrtÐÀÒˆþøEõiÛûÂ執´&ë:1:¶eeK2Ê{Gª9U_åEšõ©(ç ©L¶RqSÍRTÉâE¼v‰K#TК(ûmíu'VϨ˜Uåï‹QF¹5j„À»},?B’Õz²™ÂÅ-ÉfŒ ÞØŠ#…›—tÔ×#´eó~È%¼°¡¹Žƒíy Í5­ŒÅÅQõHMà5ÔeßDS‹ žQßšLVÇE9_H¦èlk²µ5EôöÚe5­þmñ†]™Zžl­Gï+Ê›ÞÑŒÖjŸ&ZÞ’jkÐ0Dù9¾¬‹-ëæ†“’Qö)ÝÔÞe_dAyð žÛˆÔþEÉfp—ÒÜ_6Y’}þ‹™·7ûrW¶´¦˜»¯: &–ì‹Ûàmµ)TÚl–öFÏÆ ùLgTð¾f4ò.¨§¼ËÝ÷ÊF4ÿ£¼Ññ£ÊϪ«—Ó¯ñ7G9oÈ,µh*:›Öº@tò¨6Tœß؆§&Ù¸¤£¥iõ…¿IÎ<üOäÍÂ…«•[£¿¦¡yi”3]©Óèו96+±F#d’Q~gZ¨U›a-Ûky7¥ã¹/ÏL‹ƒÚ÷…¿æÁê%Z r’ïGUXT0ÕÅ.^×ÚéÇ|{»%£sÊtî¶YiJkgÎ²Òø/·wÊí—onít-Hük,<ˆç©œõunúL÷¶üM=;a:~ÿÎo¨OY6í¼ºðêæöÆ(ÿVC¥¬µÓ‰1FW¶ûÈ©uM¶j?ßÚÙÞÚ°t)Í‹“M›¾ðü©VöÂFf[§ãKÚ@3ç5´³džƒÎÛzà†ïÙ ö†\ʼnmí µ'JNOeåpìÜ㪊”tî’(û5ª]:q¦ÒKêØ}…/¶R\±"ÕÑ.ƒúœåÒ˜B&Q»HµŸ[‹M²¸Y+ ò_èÆ‹-÷œ(ïEÚ×t4WÇ»øZß(.-®GžNÓãâqOÜM’LÇùÁ4ëª|b;3!¯dÙƒd]/‹r^ØÛòBg°°%'Š“ôÇ:O@´oÓ mcç´w|lvkò³ò?8øxX«É)}Ô¥¨¥éÞ…I‹ ¾TÔÒqOËÀa¿\Ä66ÓÓùZ]xZû²vÊzBÖnhåˆ-âƒÎˆhù½÷ÙªŠ Žñ;[™ÌÕK?Î¥èw|‚–_xŸ© (ïå¿Ó×Õê ƒ$Éß<¢VÜòˆLz±ž›Pà|»í"t?¾¸%>SÎb„gW.ÅŒF”óÏH×ÚèÔ;§gÖ¤ï\6I?;“ÅËJ L_¢){ÿWZÇÉZ¼¬ˆsÐyKïY ¹ÕÏ ¥_ì`MÞÒZlq¶ÒWWþû¾ôsØ›_è›´ Ö7ƒshÎ|™÷ðQ£é[Íí³ ZxÁï|±>XÔRÓŒ^ê°6F£CµÍݤ²Â|…Dùå4ž»HáX¬…¤VGk1¿c ³üŠG-!¤Þ1çLçÓZÏŒžUTCß.“,pïŠpe>Tä°å /-r6ItO½8^æsM»ÌaÉÊ ˆŒjãG•Ñbe:›…ÏÿÎL@ò’m’ö©ûMë*³Ðò;%ùD¾ÈöäiÖ\gZ»™åÓª«çUUU LD‡ÍÊÛÓi: ˜s¯YêJ'¨b²âI¿×n.^ò{Éèâèß+UWþyËÎ,-ÜŒ¦4ëx.ž²U^;*Èß*ß}Ü“7êõ¤½,þÒ¥Z|ÑÞª’÷oÓúŽòžù¨ˆwiÜ£âÜ¥?*º½Çvhù}ªS‹dfÏA½GQkN´ü“½{ÑÒ‰OŽØ Û¸I ±_S›ÔœýõVAå²+:{¢ë'Ç|ûBàíš,þRO/^ò’$÷ e:º7š¼¦@©’'úŽn›º¨2>×T)tB%Œ×O+rzyÙ¬ªŠÙåÕ•UQÁWõdEù¢ªêùsÊ*çÏœ[U=mfù´c¢‚Wéå™G—U/¨œ^VU^]1§ª|ÞqÜvâ3õòä¹vV–Ï)›:«œ‹å+ܛų«çW¼ hf*=uvueY"*_ðáÓ§Ï+ŸO+¾å«K“D_Ð]ôbš=ùdæÉt{òk™'3쉩Î>™?)üco-¾èÂݽ夯îï­(}ÕÐ[”U¼S¯Nš:½š£Ö e³ª§—Ï*;>Ê9Ü?[V6ŸQ±¯ŠûùWÜÁä4“ðq³æVV_=mötŸ{GæÙÞœé’Eoï}eÛ|yï“%9²÷Éòª²ªtî·Â£(çm™è±™òª¯lyWô>±å½¯÷‰//oã±QÞŠ.¨*+føOYåM°ø4‹Ÿdñé?Ùâ3âx”ëóKƧ–Æ…Ï*º‘O(=¯´ÖeLãâ9p·ßž.7}òÆtÅé“7§‹NŸœ—®å„¹šn½<]Kúd]º–ôÉEéZÒ'«ûkQ×Vô×¢'ëûkÑ“ýµ†ß’©åôcñ*šÕA8›&>'“_áÊI™Yd å¿3ýbù¬²ãÊ£‚weÆÓ¥ð5Ló)þ<3±.Åþé.ÅW3CìR|>ýÂ¥hêïE:yiÁ®'éÃÊËû{“¥4ë5ëQ–rd¯²”d=ËR¾²¿wYÊz˜>,Žè¥ÙŽ7ä´[Þ·$í¢Mæ×†o¡MvÓ@ÿl2ƒSòæÙd3:g“]Ýß6›ìÄógpÑøáãUqüÆÉ3É^>0v&Ù;6ΜIfÀN8“ì)§Í$ó{)5^ÅŸèÙÂãgUÌ™^>¼øîþÆeO㺗§]ÜßÂ<í—ú˜§Íz¼;íñÍÓéokö´4v ·KÊ˦(3LcSÚg¥ ôÔ¥Ëz]M7 —.O¾.ݱ=té~·¿öYºŽÒÞ-¯¬‚lÖÑ96îp“ª­¿k&U¶¡C*|ÇLª3úeRÝÕß-•}²^YØZrG‚Ð.û®ì«È:æz 6Í%ô£™õÍ%üÀ@ë\©»çz¤•6нËvKˆU¯¥Cïh¡}VúÞ@]:s÷ÉèÒemª¥óðÛ·Ï¥ó«0ížK÷wýͳÏwO ½;¶bîüéåUåÓª0<ÐÑÀümòŠ.†Äö·2$~æ@?Câö75$> ³!±_¾½ùÛ‚Ñ<½lià>‰)Þ óÇ…;6¢ÃÚœ»H ©wïøjê¥1¤~çFäR· Èüqt–/ÔÍŸúJn ™'öpdΊOϤ07-óĦxµÅgdR¼$ýĦ0DÅgfR\›~bÁ¤YËæU§sä¹³æÎ›]VåÏгã8u.Ÿ6¯¼|N”ïJ±A¶’ÄxpvÕ[T=AeåÜyÌï”ò…3Ëæqz9á¸rÿ2Z®—KçíX̧”͆ÉlŽ¡<ÑQชEèEñÀøý=žyª&+½Ùõíä¹ó㾕oNÇO˜]v4Õ\˜~À!vj”wl\Þ‚écFO­¨âÝY3+¦ÑqsE ïLA¥œg'0 ÇcZi÷»S*ªæM Îéå9LwìܹU®õRPήzË+ŽŽOÀ¥WÆGÝS°7N˜¸ºm|ñì¹óPC7÷óœ‡+›Fÿצ-ª˜ô¹™¸»š.+›W6kp¡<2óôÔs˜ypm‰'ÌG$ÊÌ™‰Ÿ¾`ަE6¤Ìx?…Evrõ´Ys§Cð´0¾âR-Xߺ_÷ôc2§Ÿ9é'öÜ&/ÖÙ ÐìmÏ„O.›æ2TÜ Ä/ÐûDJF„•R¸y U-\ÀEÎ ÷‚ùÇTϘŸ”Ìâ­|7^j gΖÖ*OÜyeaå·rN¿éSˆ×¯-.[å¼&=–¨é«‰.$j™‰."º=“išity:Y&EÍHÚ·ÊdFÈDO®,ðÑååGWOã>`NÑþî-åi½Ä:(»Ÿ°˜úÇñà—{Ïú;¬÷ÁÒéUÜhÍ™Ú?у8]øñ¼_9µl>8ÀÀýôÍÒŠÙDbwIàÑ ™DfÛ¦ol¢òät§›UFì‘-{ dgéxs&S‘8AõÑqˆ!uÍß,âÍ_ d×»ó7+x3©ÿÍrÞ4÷¿y*oÌù'tWo²…cß,ãÍ¡ýo΀Yîß,š 0dè…ôœC(È–Ï¢yèŽ\‰J•ÄÐlTÔ?sŒ&ºB™Ò¶bZ&ó›¨4M ëÂFUEºcW¨Š§ûèBu晨:³2UgVe¢ª7íèBêµ·=K¨I÷v1+<Òáû7|XXF„T]°`ÑTœ­û°€ÄÒ(Ç]m /¬¥D>*y¢'>|œJRðaÁ1\ÒJ dZYY>gºC.OKg=ýØQ°ªNCü1<™¿1\ s(ÁžâRÔ¼¼|GŒSfT°³åcñTÐyü mÖc畵‹«õrÅÌ öÌ’òêYÜr$gc9`F·%~­¨ž;õùî„¥e¼"žŸ(o]:&RØÉQ>d×@@ü#™ÛÒ'úZæÁòªy®mwëÉÒ ª.,C»eukƒ£ZG9oi‡–¿²>ÕÚTƒJA;vÌ}°ôR” ŠZ[T0Á‹Z”_T—”ð…40¬I|$ÑíîIñgNM¥òʦšÎ82Þ³»Ë¿®]–’Néòö†vij¼1M”ÛŒò…!D›mª+E®¼É­RyÜœTª-è>$Ç‘×eTq+Füôye «§_Ø*¼”yK;чæëFF\#ºÀ]¶S‹Ú¨C€ë`ZGa=˜õ,·¯„?’yº,fÓë*R~­øs+ʦV/„#pêÂ(§Ê Z¦^˾^(q›KiáÊ(ñóhaùU-ãÇRc”D˘Ñ.ðª–Qã(U´”¸ïÃ[–¤RÐ¥Ÿ¹¤¦ ‚õ2¨ŒCú‡­^‡d^ö+7lá*Z?ó¥äL–R;è˜#·‘‡ãwmc*—î¼Oð"Þg›æCüËmr}زo@¯1¿*›v“­Í½oD†®Q‚hضït ¥È_»ÄjQS—âüƒ|øm­ &„I›œÉ’ž¤f\~ÛQ”9ûůúõR°£gÝ7¥^1إi³,èóŠüun´Ë:ù›‘¶'“¢Ú~½kíò¢•HÞqôsF좼X4'zöVÇ65òŠ&µ4.gËŠªr’gþ®+XS 3Á§KF]òÊUQ‰FO¤À„Ø#=EÕgèÔõ:5Ô¡ïz4¡IAÏ@ômM¼Ë|v-ˆ÷³Ë¯ÿ&ÿä×ÄÆ$Z4™6añˆY¿yÞ¬Ÿbvîú"0îwùã~óÖ5WÌ›Ÿ+IÞœ>–Ptx0ó%”N7eLü™9ð»‰#8D¢ï•;x"Ix73ØHÁ‚”Dì+wÜC¼ái³‡d%À˜tUUÕýÔýîÇXcÓ˜{f…~ú}žðÆwu«M ’U½ñì¯,²w`Õ¥6CØ_霡ums3Ä\øÁ &%4Ñ yÄtfÞ8n´s(s Æ„·Dø«zMjŸ0wÀŒ¿±ñ=aÚÑe‡EuÕË-?6\Œí—<™?,»`Ê[fÈk3'Qò\èybgÜOss·À”· „ÜÓÆoIž×ÍÄ‘[¦BänïŒ*-7gуbK&!÷1GmÎ}y4|—›UM/Bߘäh¬Øg×aš=ÝiºÎÌEÔ›6aïì›pÙÊ÷ß”­Žvžä ¾Æ;Ü;ûWi–ëרräÞÑ?ƒn#6šØË‰ÝHìKĶ»†}÷YòýoZøžÃ›[xs'±oòfß_áû6Þ\?roîSÛ¢b¾¿@žu–ó>¾¯çýÞý5±|™ï5¼ÙJŒ÷ÊS 'Q#o–ŽÜûÙŸ#¶È™ì×þ}égœ‰ÜƒD°„^þ9ßó'aq¤n>^ßã·¿mpo1¥YˆN0c»»Fîåð½~´‹‰ †ùÞ ÄKÖ³E oÌŸÒ[WÀú>{á¹÷¿·F x›oîxë°ÙMÓëÈ~Ѐ8dÇw‰ü¦áñ¦5¼IeŒhxl‚‰ ãx×nï0©±ÄbÜØr\oï0¼qsxw›½Ó‹øÊðîn{‡!Ž{»¯ÆÑ$tbœ¤2˜’7_nçjšŒ¹x™ŠòÔùË:ÚëR+šž˜“hóáK’/íH" ¹&ú¹Ì2“—ò0 %SCžêÅXʹqy8$ìs˜òÔ ’:t¤ßñà4“[nð‹H!·Ã ]ÉAVÖZn,ê[F*Bn‡Aºr ‚¤=ÃÒÖ¢dÆ"ävdwîË=V”Ie`âaˆ3µœˆß5‰Ë¦Éçr¡ØÎÌcê {9üÑÌ÷ß”®Î®¹—à óGîå0Çõsìç0ÇÖÒîì±ÄÀÚ±ÉbÃûf¾ÿŠørï–É‹Y:«_uíµ»vö äh¹WÎÀ3_ónã|™ï¿æûž8ß}×Çùâu¼ù”vìëO¦ˆ uÅ„)âvŸ5–` açžQãVû_oÖ•`:KoÖ‘‡}ÜZ‚õ’ö·fÌŽ·Ÿ”‰©Ž %{÷¼L1ÌõÍ-&è¯Í‰0ãÎ÷Èé‹Ì:SÛgÂ[ŒßÉÛÄÞ¾7¼Mx{3o ööÆð¶`†Á‹öv[x[äí&Þ–ìíšð¶ÄÛ¼-Û[c"ܽ-óV‚Q½ÞVœùva*÷Ö¶f×зÌH“§Á™o·?õ‘ùØ™“'³Ñ31ÓŽ7¦ƒ«¢ýî–B&†éÛ¯ˆJÖr’ö¸H&ÓÓüÛöMc· »]Þݨka·sz·c£¤«C޽ ¾ìy›a¶®·fëx+¼¶¼¶j›YròŸ°QwHƒvæp\BǰåoE¿Y¼„‰o#/þ—ÉS×’É–Cæ^’R{'ƒ/‰¿g % –tÛ;aŸd}ÈíM’k ’ëû/Û;mÎäÎÌ»B®½)xœÉ»6ã1¨OÑYŒ‡™cèãýÇK5®{ðž\ªs+»ócX† öe3é‰-(oØ“˜7HNÌ$'æ ’óɉyƒäļArb2©œÆÚBl|ˆM±É!65Äf†X{ˆÍ ±ù!¶(Ä–„ØÒ[b+Bìì;'ÄV…Øš[bBlSˆm ±ËClkˆm ±kBlGˆ]b;펀QªŽ;B¡3˜O·³mq³Ìí˜{€ÌÌ é6ÛÏY [a4[Æg†<µOc¹aÏÏÁÌæ«e’fˆ¸:Ž+`87ä÷µ`öŠze–ÄÔ› 1§µ` £Ù²•’Õ’×C­>ö¯¨[{mwÝÔêcÔäfc *²±R«¯#¿©­»fl©P³ì°ì®™yò1êôF³á `ðZVZ¨¹»~êô| ,lyƒ×0`½ÁkÈÃÞȵ ¥f¯1‘íÍ^ËXPj4¾}à‡}`ëœ_»Xií¡?¬o4ûÁh66µž °Ÿþ§Ñlø&Ô [1ÿn4Û˜ Å4¾ õ `4Û¥Ýãû0šÁê0õÈÏÿ5šmë{£ù,“èÃ,3{ËßàÙxþ<g–9’å—‡Ì2›~{³ÌƳ5Ë\ú°êeoõšÖeG9ÓºÆZ¨7áËÞëÍi9P]9Ù‰½9­±Õ®œìÚÞœÖ0kWNvuoNvIgNæ Ñ›ÓX‡ìÎ ÖèÍiy9]9áùôæt·‡Ý9á õæ´·ñ®œûôä´¼«®¹Ùg^Øî®:±¡Ó›Óòߺr>dàØpë9±œÓ›Óò&CNk–›SÝØ¬5|lsÐ÷zÞùÜçë9xçspÿ¯çàÏ¿ žƒw>Ïë9ÌgØV÷¼=9xçë€'QÏÁ;_Ç#rmLX=‡™<—DRÏaŠËa¸åÝ9xçsÀ«çàï÷ÑzÞù:à ÕsðÎç€çVÏÁ;_+»ºn˜w¾x~õ:xçë`×ë௞j½Þù:¸¥ÔsðÎ×^¬çàϧ¹žƒw¾V8‹õ¼ó9 –ìÎÁ;/a¬)u Ee-;³Vf%üœíѲ¬_ŠèXƺ•µboU*˜­Ô‹%ÿ8m“U_Ü`Ù·"+‡äƒ9íjª]è’PÑË@TåTËñ^—áÜ`Øgt¦(+ØÛ¬fHëlyAõ©Aà_µ5ˆ¥/ÝʆÄ™05U͜ڿm03” ²°èêm6k¢I#£»N?u_´Š~â„êÞÑO8U¢+ýdIUZýøíÞþ2Û¦¹ë/Sgš­2³'*Å@½WÞ:‚A¼vFðZd²MÜô™OS­-2_&L?ˆ€Ñ¶A¼ÅÚ ™NÓÿÁ2é'žã`™ïS®Á2-'ÃcƒO{8øLÇ*’¥¹Ü­±H™Úá5&)Ó ð6)óIbvx[¥› Þ•ÅBõ~¨8°êÁ0jÇz×0ñŠÕ‹â“)ß—S…#dN7–Q2ö¦ž’‘5q,GÉ<š¸û©wªq?ÞÓÝ?ñÔÄ¥ØOãt³ÜOÆØ„s÷“5q FÓ'z?ZúT÷hqèÔûÑ2,'ÛS£e´Mó5ZÑÔýýelL¼öÂ)ØŸ|"ÛŸ™ÅvÖþ2ަÙcFïÇ —Pÿæ9¡þ±2d¦™KxdcÁ+ØíËLc·w,wh¬ ·‰¤YoÚXþ·‰Ë¥7mfa¶-¶&Ü;‹šdÌïLóëãÀJíÆfÙ2ÅØ,sfÍŽ Æfer656+û©©±Y™œMÍÊäl‡±Y”56{P06+“³©±Yö¨·êMÎþÀØ,º`ÖØ,{ÃËÏP™76 ÛÛ›õ¶i™orc³“‚±Y6…7#ŠÉ6olVÛ,5#ŠÙ6ol‡7#êMÎÒEor–z¼ÉYrû¼±Yor›79‹4or– ²79û_ÍbqΛ•É¹ÔØìˆ`l–öÆf±ZæÍbT͛Şš76ËÛÍ2KÖØ,“äÍ2Þ (üol“³5c³œÈ¬±Y4e¼±Yl°Y›päùÛWøÓÛ€¥W~b Ž˜µ­†YRd.Æ»Úà¹x³¤Øj{À,)öVQ«ÉLdb÷ôD3KŠÍ7z‚Í7î•Ø|£ßXT³fI1„Z3KŠuTðŠ5Kjn® Þ”*¹¼)U&ƒmÞ,)‚<Þ,)Û¨…Á6¿70Øæ÷Û0´j'õ]OþÈ}aOµ†&@øY¯yUÕšñPL¬ÊÊ^þ;©5㡘3­Å jíQkfI±}Z³=ŠÓšYRìœÖ²"çV«;§µØ9e/×ìœÖ*ÃÎiÍöè¯÷ÛÅ@^Íöè¯õÛýT¿­ÑOöÛýDÿû_í·=zWˆ3­Â’\|.²•^éÄ W–Vm ¢õIèF®ü‰%´Gù_rMÔ½p‚·NVüÌZZUódÑG¶ê4õíbŸ¬ø©$¹ŠÏ'‹0ÿ(+áç)}—#…ÿc¡¬x íh¿ß>ÙRè^?~«HÔ ”Yf²¨5ÃYÑ· )ßý{©“dbÆÒךd}MG#nð~â [_•Ÿ?NÙ/ÖÞ[îOœ„Q°lwÍÀhWòÕmzLQî¿”Ž«¯ð)—M…Ò1G°™‹|ÊšW‰O-™2Ÿ3¢¼yÊÂé~ßÉö`µà¢‚·Õ×7v´-‹rÿžšŽxБYyå­néH+~‰¤r;õë|j´þ¬t,ýA']_æ½Zúç|N¿ßI×Ý”#«]êYž _Î}4xéŠ÷ܶ[*í[ÖnÅkFï~ÙŽ£®}rð•Ò±lo«éZ©Þ˜ ·Ý Ãïå}H°— •—trÔá¹ëV’IT§;£1íu—}]+ªQ¿K¼÷¦5ƒñè뎢„:+²4­«d‡îÃð­‚“5Áõ ¤©J|à ÁõŽzDk¢ëè$ ò¤šŠ®ß*)X“]oÀMlƒNÌ™ìúÈm›Þ%÷ÂëðÀKŸa·ðúøßCHWŽ—^GJ¡-Öqï”^?ä [R9¨ß îÏaspµõn¼óQ—8Uwm±QÓAØVÿç÷cub/Í]W'¾p( uâ#®ÞªNü»ÞµMø‚ävuâö¡Ô‰Í\¡2À\‰CÐø®åKk¼zŠN•¸ñ]¿U%–bØâ’Ú/þeâe½ÊÄíÿK™xgôlÕ½n¼ãÔT¥Ôl ůÜÿÁ«ð¡ª°¬¼Mô3k,Ê ëLÉ#·A•xuUbL{UbÌ ïS%fÖ¼Š-õy[Ì Ã·Ò44­»W•£ÞwÉÜ|cB—ù–"MÓç±0çç›@q@#Òôù?ªUâö ÊdzW¸•﾿Â÷¾ï-‰>yUT¾6狉ǔ‰·Eϰ£-§Ú+æfQ†wSEb {U/ ³{%F°çd›cúßn¹1Þ>Ïæ˜ù ŠÄN]z"±¬4¤ŠÄ°+;gÙ*7ØY¶jv–©Ñϲ6œQeÐê÷’GQ–Eâ C"¨_ãf`f.›'?[ÌÙÔ0^ M,^)^Ù˜ìsKÁÊ΋¶únå”›ƒr s᱕&Àà ±qûëîUvQÖîÙcb÷3%ƒkÈéóc¿)V êw.-l[ŽkY¨Íî=òQ’]ï~ç:ǃºY…>¥{¯wFéQyú{ÜÔòÄTõ mzC[KcÍÊDyg{²¹»¥׬-7Ûª·"V¬f ß¹šíÝÜs½ÍõÎI0Ό£0Ïvfm;;¥Çí oTçÜ”óQ‡ƒÄa68H\²vªIgØ¿Õäu¾sôá9+]ݳ¾¯†;r.ÛZCÇ[Õ_ËýŸëÿuÕ¯:>óëøíÁ>þþö>ÖÞê{ûngN”°ïñÚÄn8Ê›í¨0Ú·Sí{¦½o·÷[ìûr{¿ÕâÛìûûÞaßRLâ·…œÛK@êC¡ë)9¢´u->¼Úf—`Fºï…ø±QOwè¿ïï û>;ÌË9Ö·¤¿o«úëê#!ÞÑ7”7ºX!z©½¹Ä¾7[ß¶õ÷íú{Uˆ½šú çQnC•Z_ÿÝh­}¿Â¾_iß×Qÿýq gÅo gÛ÷kíûuöýzû¾Ñ¾ß`ßo´ï7éûºï欳ï›ìûf{‹Åou* ¶æÛìí{ìûã>þc!±_*Y—™/Oúãé<w5Ünßôµ¨æ;¸Éãø(oè7÷ÅÓýR¸Æ¾?cu}Ö¾ÏÞ}ξï±þ~IßíµÞYšž·.ÊMß"ìû/—pœ5÷Áeõ0*ÿ̘•J!wB~”໵´½õô‰…]§Ó“/åÜ©ýÒþý¨›ÙþlÉ爉8¢\­eÝ=—;\³'u}4*×:5kÅ%çòùñœv?ç¶Þ;ÖœïfèÃ^uZ´÷ê3¢ÝÓ8D71úT[‰ÏC¼m7ÉÜC¤êºäÞÜB³ÔÆ1êù÷DY¸Ü͆[œÖ¢žÎ;{Êš/&&þArÕ¡>µZ-¨~›<â¢þzÿÛô>gÔfmOJks>ç°Ž‹¼CìÖœ/FS¨Îìc»PkíÅuº®<€ëî_-\7O³tÍ%ëý,ÜzÚ³KÖÅØÉÄßòÅÜ’î,·gÝû2}jHÇ _úF¼ÉÇt[jïZBlDˆ µŽuŽÙ8¯qÔÉÍd“n&ïËWï%\X£‚븗X:A×½D7ŠôF¥[†” mL7¸ô^ŭ«ÐJù$½¯pƒœn“ÞÉ€”Vt§´1ØÜþ6É»kÃ;¯λ»Â»/eÞÅÃ3ï¤l›½[Þm²˜T7KUvKÓ ¦t©õF÷â’W #½t½½_½äk›½t§½ÓM¥ìÕuÅ{/ïœÉQö Ä/û»¬øóå™™[lÙ÷F¦¼(äÞb7fzY¾5ÓËŠWÎÕ}§ri¦•ËíF….@Ǫr»ÀߨtßI  *€aw)´°øÞ›l«'Ne‹Á(Ûübñ ýR?;à ·ã¹hìÌç~@튵ÿS4Ýsyɧٽª l³°5¿¬hJ$×Âûï{ &\ö¾±ûÓ=§—äKIzDÉêý{ÎY0bŸ‹»oî¹jÁ!Gþ¨ëŸÆtžœ?¦“þÄ乩åsÑ;¹96t}ÿé-«Ñ6xñSr.^Ÿøæî’õÙÝkÙíë³nZ ®¹ŠsÝŽ«¢£À[žuj” ¶ŒØ[È5™ØÉÄæãݱÄk%÷ü¸†è¶Pyÿ8äòRƒò¦µ?Cy™©’·}×Õþ6òª;–Ø[ZuAbüÚ sn_Ë´îäÎŒŸ‘—?…(ˆ·w¿'çåF-[ó•G3zw“kkôô–.xÒ!?3nóÄk}žÚވàÀé$)_UbÀ­†v¿±º«@æâ¸¹w›,ƒR+eÑ #øû%z(÷ëªxè­ ©àÁQL²ýäS®ži^ÔCÆ’Ww[òjïœDqç˜Ú≉úƆ–j¸ü›û™€àr¢¦2Žœºyz«ú’æQ;jb(xzç2)œø¼¨³àB×½¬G3jGOL44ÃAm‹·Hå†dl´»Üè‚ ‹£ü¡·ºÄôh¶p#°±6ÙJ9е\>ôp¸çê~ß›O¬ÿÕˆ#\pj ./Z;(Ùê~z¤ÄÆš» ´u4Ç´+Ý€mN˜ƒÉ)„Ü1{SÇ`‘9í!Š?¨×-»žÌ¨­ŸHº Åã¼é— UfL÷÷´&æKùº‘Õˆ2šAº’ÚɧS÷úºÄ4<éQ¬áWkL¹—[^ôvP7Ò]ÿÐ[?üðD_9¨[W˜#ðµ¢~ÃLŠ—qè­÷{ÉpøGÊ9exx'‡Þº•WÄîÖÎ6Ž„E„1F¤ã5ý§OØ7çÜŒçûÃ8°ªòºÿ:…ûæIë¢(~–÷w[ž/ äÑN÷yn-Ù÷®Y¼9¸luÞ[\H™‚å]3ù´(ïôºÏuâ|`õµ: {^·£ê 7jüóÎ#ßÚÏuõå–Ð7ù6¹|6NW…úÖü¹¾,_VŸÍçêSÏ£ä¦ÿn^xƒ¤‰­þdß[T—0ËŠ…ŸÌŸ‚ÉÇkmvVØ Œ&vNU|ŸÝõöœN˳¦Ïµ€>ôfƒËý–hÑȼèæDa4±bS‰m#†Ãîa×kåÝ5ÄwßÒU{xák΋SGµ^[õ”’b¾wT +Í÷5U®Ûªòw/á{kUÞð‰Ýºç¢ÎªhØä®îœÎ®uü¿ƒÿ÷ätžŒÞÄóôý*|”Ú6ñ} ßÏâû&¾/áûF¾7ó}}o?™½1.ºß­Óé{•Þ¿ô¼œË‰§;ˆ­X—?Eõvs^`çm4±yÔ±ƒx‘øÙÄ·:G á.¥{è¶:î©Åœ¯¹ž>?§‡ßìËakþ,ïîáûƒ|–ïßãûî[ªò4…ë«r‡Mæû·ã˜úYH.R=+.P,ô5YkµÉ™Hrºbí§Eg®a‡¨g¸G˜é\‰°ÔWãJg Ûœ+‘ÉìÍW"”ç•–ç•q?ãëVÃéÚ6,[U0¥˜ï©Uùã[ùž\•WôÑ5âU¹ÏžH¼­*§àn¾ÇWE»\Þµ˜™;ãÛ~>â567Ûz߈KÍû šwõ©Üq›+æí0Å‹cL¡:^K¾™|¿ŽïÉ|¿žïñkrrÞ^•»ï|߈Ì+2»5FŽ7ò-,RxgU~ÁÌñ®ª¼ýJ^•Ãý¥XÔÞ w`ÅM‡ü"Ý¿?ÌéÁýˆ]zŸšÕVõâ¬0ã¶¶èbj¹µ*¯ànj»ÍÍEZ˜‡êŽˆN§ïá{+ß¿¨ýüÀÎpnTÞ•[fø©½*¾§Œp¸n÷ìD#lög÷9…Èqy»v®ráý#îh¹=Ú¯_Ú#?´xFv~kñ7[n-ÞÕ *oÞÕ ¤õ-¦»Jì=H¿MÎLì;”înÉÜ!“Kìn#‰¿©J=<¹ÊÞéîQð åzWð÷aÝ7 þ&Ì;ï@B÷‹ÂÙáÝ.{§EÑß„õ®èHˆ[\¼ÍbºO”º29J§Û;Ý"JW‡wŸ±wº5”s3ïtãµïtK({¾-÷^ÏÔ½@7Þ,îN¸ ¨ÑA™,oJÌ[ nz 8P’ÝÊJ0ëKÜet{¶ÊÔ(ñy•jbÞM1ï&‚˜wAÌ»‰ æÝDón"ˆy7ļà 3ÛYÊ貕ÔO}‡ÿʦoøÃçÉ—p3Cu4]„½·BÈWgÔÅ‹t¹„¹ã¹QwÖSb=P ³‘Å¼Ó bÞi1ï´‚˜wZAÌ;­ æVóN+ˆy§Ä¼Ó bÞi1ï´‚˜wZAÌ;­ æVóN+ˆy§Ä¼Ó bÞi1ï´‚˜wZAÌ;­ æVóN+ˆy§Ä¼Ó bÞi1ï´‚ØÎ»>Än0®z¬\…òEÁ­’y{kCÍU¨¹Ì­ñÌ·éÖæ¹Æ)¿I(缤<á*N²eNêJÕ›´çw  8"î]¬{aGï¬ 6×;úåz‡Ã&4©+èžuÅæÞqÓú^ïíïÝF„–.F¤©«…ëÕ{ÈãΪO¾‡¦oî6Šjt$µYqÐ϶Ûè;>„fn©Â gßz¿¯—} H¥/pö­ “ ­u þ.¥Ó»a—”åBÿá0rI—àì[]†GŽÂº‘oÀª}¸+ÇÒ“@Xß«Áê{øy,æüᛳu϶2,Ïà OŸ‹„k ‰¹tæ]ƒâÇaqܤ6e£kës£ŸÁ½ýgûsÏœ˜p‚UmSc}.ƒï•ëg” 1¬6´TÜ ÌI8úȃë#:š;Ú’u‡ùœý¹ÑK›£Zßd¬/¨qâHè]ýy˜˜¨,ŸEá›O<Ò¦ÞÅå3$ ïr£1‹ê­T¸³Üôᛊ Clù Q1rxת5¡Æ9ˆ¥ˬéF_«-%)ømÞ0k(æ2ßr¬°;w÷0 ø•åE]w:y¥d_Í»¦&Ce-ÌK’‰ÚöÖÆÄ! &ÅyNsmôý³¬´J§R‡ÜZœ}k¯3®Ðsž˜ý4&Œ:é¦Ìc&Ô²Åͪ ¯s¶ã'|èÓ=×y.ÿÐø\®:s¸à.¿x™)·^¿ãô»[Ûš‘Ïvw^nÛKˆÅ|78G=ŽoØk.kîŒÇðÒ{Þ¶ð'PŸêœªûz;úôg}÷?wĸȽ‰~ïsé7’íÝ2b7Ç™Í7œ [SÊ…h¬â\ ÞÕ¨¾_pêSÆ–ìæ9Ã7q$κ)ÿãkÎùnöÖ×pg L¾¬Ÿ ·nx/¾‚tßó÷wéæ/Žµî€ Ž“œó¾Îíùœn6êY7}ûnq àÅÊÅ•q7dx ºvrbõ½C.•ô~Ûd¤) ÇXNã¸ä‚wuû<†7­zwž×XךvT‹µPÛ„—áã®1\3æ¤ÒË5×øØÂµçÃ5Ÿ^]Î5Þ¦œpÏêÉ¿;æ2‹ 16î\8éF­ï{Óó/†TÞ·ÏÞnÃzy7ob'qݧ£.›!ñ&¢³ÞTp7\Ž- oêqõ+vù›îð±­ oú±mÓ\¹Ø5 oú†íXxÓ—}ìZjšÏ¼ˆYw"K}G"a1q(¢½-&E4|€­9^áô~4ÃnvˆÇU‹ó§h®eIûõÍÕ¬ý’ön<½ûíÕ›ökrè×ÔÐ/¹+·£KTÔ®©s´á¾+Dzx/U¹pUWCÜŒøò˜«3kñ%Ôq/·ò»?£¹¨ô˜(õÇrÝ=¯Úp¸×`twõõ&ÑÚZ·§8öŸö»pM¦ß…¯ÁQº-ž7ø¥‹â¹*|R5nÍÉé\uSnqU.¹çi1î~ÏÛ„· ›ßxÛ¼é­jŸ,þþæ;£g.Äq”qP%·lgå\1)'Êm» nÅÈÛ®X˜oäíh0[8—vN¦.Œ^rËsqPþÕ»žÿ‚Ss.B˜aqƒ´ãîgÇ®ÏìµÂM™½V¸…›¸ zsŽÍ¿Ñp÷ázús?5.ºgFCÂóѵ®ãášëÝÎðî¼31õü÷ñdâΘ'k‡Â“Ùéù/ªE<™xQÿñdâéýo^4<Ÿ«m]Îs¥i '^±2±ykñР:W•ÔD“KV;^FÜ]VSŽ­91VñyÝä!N¿ÀRÛȵí\r 9\5!ÜßLú6õ™~o§?EúóÇÙ…Ê/þòõâdéûUUùîûÕUÃ'h8ak†>À`äWèÆ2ºâ½"æ%³Òœ"›g§åÙ ÷i*¢a;†îJœA×îˆo7l‘ó‚â›xAn·Ã ÿƒ¤ýobp„ØÿW»‘ýæpPáí¼ÛÉ;0!a7{SØ»Þô}» Üäs}ø>n´– <úçvã-ñûxÄÀ{ÕÛºæ´õˆ|kÀ.ê•ÇjâmÇ sUÌù¨í˜Ï §ìÌ•µÌcz ¿èNišèûö{vvDM½·éòTo VÇçÁ[Ct‚¿5¸]ÝN›¸ƒ,â{ wy®?ןôFSu4Ös·©jIè–T½Oy±¦E8H²÷éªf@¸©›»œ×ŽÀ¡ˆç!áÇiG˜û¬ã™{¯w-†?Ï¿áÆéôÌ}úœ GœûŽ;´w0Æ;Ç2÷æëçÉqŒÌÍÛé*˜˜ãÅÏâ[¦ŽT_‚Ø–ŒnCì9IÒšˆ‡Ä­8uQ¦|ÞE·àB¨£°ÈÞéÎ[ðÎ÷xç4(pX4- b¥5–nÑM~Ré"{§{néºL%ãlq¯­òœ<7@zå wQñý&¶Árë^Ûø[ ~Fu—m\¨Ó!Œq:Ѱ,ó®Ñëfó¹ukmôº¼ósIÌ»L#æû§kÓÞ™wM¶?¸™6y›8jMèãÁu¢Õ€ƒ‘œ”4À¿j€}×'©kh#0a04zn \ Ï9"æ9GÄ<爘çóœ#bžsd9YÌsŽˆ9>û%ð±bzÁÊÅ)Iõ¿üCì~Ç‘-Ð[}%G=P@Ÿ³'«,_4R;(³ÆÓüúnÿ½m@#µ³žFæ¢-—ݵ†>ö…0YÌó±ˆy>1ÏÇ"æùXÄ<‹˜çcó|,bžEÌó±ˆy>1ÏÇ"æùXÄ<‹˜çcó|,bžEÌó±ˆy>1ÏÇ"æùXÄ<‹˜çcó|,bžE,ì,ÏÇ"æùXÄ<‹˜çcs|¬X®/:ø@M§Ë‡ã4Ù™·ü¼g ³!Õ²·¾4Éu^p~ Å°r„†ê³”ãxPðùÄÅhÆ•Ç[߯n¤¶0: už,o‚füh´£¶Ž§òx^@'‡ê!È-ðÀP·¹´êl“»¶ÕkŽ5ö‘é½ÇFøÞpÜÐXŽ8rý¯'ˇs¹j$ Ò43âçÇr~ÓŒ«¶·­íåµÃø>_lnoå±ý‚¥0Åœ[ë@󚲦w²mz„—Ωiè‹ïyÅk†)ò¶o÷ö¨:«â¸¹ÛØèÇú6O}«ÙÔÞÓ·Icd·ï&÷!ã­Ÿœ'÷ñÜè¡ßkxŒÁa”ÏÞþõx1 ±mj岆¥Ëª—Ô4Ÿ(æb\N¼ÈÀIc&Ϲ®¡¾™ G:ߘ.^eð7#ÝÏ·]¼¬s!¦]’X–¤¶-ð¦L´ØÐÒâ¶©LC´Åõ¤µ¢¡;ˆüÂgoÿºKpIjEÛ”ƒÑE9ˆ­rähÎ\µ%}O&61Q›jLµÆ…Á1›“@ÜÞ0ÃÖ£osi”ûÔçØ\k®ÂkFíí_wÜ¡=WÙl¯:•i¿šn_-žs{iµ4“]8‘ɘØËîÑsö¹ ý¹\悪çÎwïQK4¢ÐÝ\[F<ËÝ\Ñ¡4FtÃaÙýma×âoÒ»oJ»Áä´÷įˎT;…£7›í5ßGÏ_öVé”48 GðÉÐßvY¡pÊ®\zÙ¾½$››îÄÂ5ç1»+ÿù…]Ý{ž}þº'Æ}÷DîÄÿ#¯îÂ;¹sn1,Ú»ðwdz8©TrúºKPßiG¢ßíâ”‹àæ Íæ@¢Ê›÷_<‰oN<+ÊštN4|Òþ@CTóº"ºyJ¹tßýщC_os´û¤—¡ñ5ô½Ù‘Ñ\áÖØ¤ô÷j4wã[Œ“"ArÉAÃõ1 žHñ|îûçpß?Ûîûgw3Ëù}ÿœn®'é}Ÿž+—îûçl¾ïŸ½–üú>g-yÎF1*¯Ê)-âû¸®“r:·k®„«0—9™Ë}Žs}ß$-‡9(`ÏÅ#Ï\\Íá:¥w·¸½±¿íšÑ[vÍ'˜µŸÜ5ñ âÍOXW-fÓìšÕïÕ®iÑ®YÑ]p v¥* Êo½{5ýܶsÎíUÑ­wwEÇ_{òÁÙ…'O|~áäá/ìz~ášØâQÁÝSfEY'~~á«;ðΓGÌ(^0 ýŒhZ¬Åñ+9kvŽ^Úu:šå­g®¹ Zܽst†íÉUL!Çæª(1¾ëBi¼D…ܾ?¿9x´Þ¨¥®è€Â®uo-<û³ì©kÒ;mûŒ½Ò—‚f87Õæ4xwï4;om6oùN³sÆN›ûIj»Þí3öZ¶Ó”[ûk)û.f¯˜x-;môuz#þ]¹Òi¤iÍ4ådM ¦}Ô¢]¤Þßåw‘t çÃÿ¸ë÷»èÇ{g.µÜÞ¹Üí)ƒICÓì¹øEšÃ5]oç?º{Þ¿y÷D·i÷ÌÆ»Ül®„íôˆ9ÚšŸÓ¹àèÆó”ßyÊ>yhßïb½#ç“ZXõÙÛ®8ù°Ã W³÷·¾½qÐwV}v—®ÄŠóðüƒ‹ŠÙ Zýœ¨kÁaðDÞzL§Þm}ßáä’NÔ»Øoe¼uIá[Žw|í‚›´ fŸ ×npûÀhïÞò9ô£}`{Ÿîƒ÷Äû@zŸûà½Ús_з¤çT,íÃ')žŸ$Ïs21¸R5¾`Ž[ŽIqÍ÷qŒÝ~‡ü³³Î…p¥ý°E»¼n1;D»ôG{ã§™_Þº7Ð ‡jô7¨Ü¢$Ëlœ¥§½ãäC&žœx~¼/þ’}qÈwN~ªá{/|Ë¡<ð_sjoÜ ½!½Ü–’Ïe•nÝR6hG©óG{ÃöÞï p1»CxbÏÞÐ>Á^ñ{C|ÓdØXvËŸ±l¶–¥÷;AšDs¹êÝh‡tnkg® (?ú·…pÙºþ™»‡®ÄÏå» «ÞwÛUï=í¯:4šµà°a“O>¤âÚ“{Aáɇ?¿ðäÖ8<9ïûÌìŸ1³65=³FG»O€4÷—;¼ÐÆŽF/|÷Ì×ï!{gþç™ù÷o˜ù߉º5÷3ÿ9›ù"3?Âf^­Ñª ܯڤ8Œ»Èm®n|І»Há:bEŽkw³?&8-NÕm´8µ,Mº384^›Á¡Iwɺ¬µì‘–‡öˆxp;ò¢£Ý)E3¥†F›¹çiæqkoÿ\OÏdtKڿ߃Þ`´wUî§ÐËeé=sG¢²ÍPå_hu,êZÆ>R/æ½¾ú5ðÕßzàÜÎFZ?ZzµáRN;yví‚sãú¼$× ]0W¡ô¹ã)¶KÙ¥…ìªÂa“‰Ù¹hÌÌÅÖhöÅž¹Ð}lYUŽÍÆ3ÍÆˆJòÛ¹h sñb›‹Û¸¿¼ãðÂ{gC³9o:f6®'Ï (Ü6ñ¥ðÿæWåís1Ö“ª"toÑ>ûyî6â-¯xv¾xÝf'å¼ÇkJÞ@ÿ¤ñpenΛFìž%޹Ñ6ÓìKP{ œŒµÑDñIÑØ5s8˜ckئ­ï¶tÃ`Ûúl‡s ß1Å9¿eýv6_‰ÂVŸóÙæçÓîoÝÌò­Ï¤™Û†xnŸ®ñlîÉ}i´yF»0zq3܈]Žg©»{•ÚJ´Ëéh3;ÞJPíNõÝpôÙ8–^ÃŽ¥×ð†/áy˜V.ã1zÞ ÏÞÍ·Þ¥šnнî›b¥ÊL¬|y&wÅsüÄ«¨x}7ñ-+Þ_…òU<÷O±†Û3±Æµ™X“9I†kÑÏçVý<R9úùž)ÖlœÃßwͧ‡w^ÃN±þöŽýÏ·úÄÏèï¹—º¶ö¿ÅÞ‰w1Às&U÷¯;®:xn§b=H5 ôHq1.Îðâ¿ÄðRtÅíä¥ ¼Xv /n‹ç} áž­˜Ær¹†WBV7gšx‡Í‰»9ü¶è²ó'—'ÈŸ+«JÖ¸Ëq"9Ðîø³® ZkZ–5Ô¶A‘ )Ô‡²ãˆÈu]ÎÉ`vÊŸ\¾‰Ï…§Ï ‘þëâîÜ4Ÿ¿UVÂ2̑ܒáD_“^£s²½­ýæ’Ó©(%´Ã›¹?ho'=ê³=?Ÿt#‚ªâˆm_ë}‹Ú ܾ꧅kØÅÊ»ÕnqSûràÏBýàÍŽ räf>×zMfÒƒ~%x—4=þƒëÁTzðw™[Ÿ¸ÞwDèÇ$… ןö}»šÖ|LGZÃÜÔCC‡›ÃÖÓGíÄ–ÞWk|¥jÕ{桟ފ(ÕR’»Š<ª'Ës£æBy&ß77q—ŸåhPMôÅß'·Öú9‰«èë.ÓxØ„žÃ|»AˆËí:<Åï„×þK«)Œ+ð¦˜s©½I›÷Ù›BxóþXC³`³Rø8=ùñ×£Ùy4ßïAôèµÊü›ïÓ u9—NÀ`Ž{—„wï›_½“®Dúîýºe3×xTYq~þ”ª/p{~ÓÌi4èÎÓ Í‚3ÖìW²`é³O¢þûL‡ïpç]·ØyrîàÉûNYð|þ_Èÿkï>¥êtò_3³¤+÷N§IºõüÛŠ»jìœt£»A½×ÝE­œ'8‰…|ÐøÜ)»ôÜFÎÀñ çÀƒ<–‚Ó¾ÓÞn xç¼Þì~çÈ'ï?—èÒ¿ÛõšÀQÄm¡Çò\dðƒðæ7îôøÁ‰^= ¢]š-÷™äFŸKøawî\MÒhRlwæë}ÝgYnaÛ}¹¥ÅÞ•.#ÜU)>ìÎ}Iskæ’ ì¸œO±œr©¹¯^‰‚ÝeøHþQ9µ¶Â)ÿÆŽC7®çJÃF›&Â: ÞYÌ­¡Ê‹ÓA`ù³Îu¤¾™ÁIñÙº‚}ð 2wSW®n _ÃÃP¿’Z0Dqwaíì†õGîð×É®º¨æ’ ÀÅʹ+Ž“s‚Ïy-9¿1 Vú„½‘œÜ;íípçŸZr×MâÞ.ëúþ˜7U}Ødé”´_~¸cÆ›º¢QÜQ&TV}nøD§ô"Þï"×èçðöPÞÞãÞ®øÜÍSÜúÏrÞ¤=ŒNŠÓCi7=£S±b} »Uwž{¤Ó•’ÞAÇýªâ¼yä¸ìëêýYÝ†Í¶ÅØìuJ/+.íê:ðM®ö·èn9Žû¸z¢;.ºäÖ_Šá-ª•.fG½¨8îÀŠÈz±Ëz¡›°j—¾MᣆóÚûqÞ:ÃyèWÍïÑ« 6ŸKôμÙV°sIøN3mç±|—æQ9Æ“£¹¤V³Kžò-~N ¦SN—åM™;r2=h>É}B=%§Ï=¿;­°ÂEôíÆãÐ$Úz~~1 ¤¡k]TÜõúœÎ×LËùëI<ÇeÑÛ`>¿éÀ(Ëÿ7u®ÎyKÕâ‚»ÏF7gÅâ}Ï®Z|‡¾çT-þ±¾çNBk.|3ÇæO™ˆ-§9eÑŒ‰ûGG/,-@—(ÎU}snŽJ&~:š¾p<ÎW1šVŸåu]Ñ—ÄCSžhø”¶Fëåê¾A\$õø Âp“Ášz¿ÂõX›×öØèðl#ÎÌÁ;[±†û7Á¸=*¾e :s[kÿÎaÏ­µwbìD‰î£îýŠ{Þïçt´Ýû™÷¼Õû¾µ„ËKUGz6œ€ßq¼€xÄèmmëzÍfËiÈüÒÂ$3(+(¦Oq4} Æôî½é7R¿ØOs7ïsï¨Y*;À îÝûÓ虜rÖ î>eáˆM†‹ØÃ[*À‹‘o–«¨Qp-riÅç€å;¿•kƒ›µ]½íê½R5ïÛgζ;b¾v„j^ zÙò¤rìÙ¨´°+”{¡tŠü¾x xù%(U°3^‚oÙ9çF3^ n×®p»ÃzÛÉ{ÓNY¦½Æ.e®®H¬/î¥+J-Î ^Ñmqö‰ðíë-®]£.—o—­ž5k˜™mhìH2¯Òv“f`{×i{užM½;ð®wïM¿a~åQÝíÊ÷¥ß©ö I÷îý]‹yǼªî®y½_ÚZ_Þ²£õîO™• °§Ù ª£Ýfì^W—óîaú^Êy»aœ pE4’ùÿ°soqš}7]õ®þkoÎhñ àÝή[®ú€ðäÖ|Þ½•úVvhšG³pÿåmÀå[¥|æ}žÏäOóY/.ßÔ‡ó%é|ìe¸¦Ê{Κs™m©÷î(`¶Ï×.žZ¢¾™ýñ樜wÚÅé›Å¼9Ž7ÚÃé›ãxsj77ôt;nn]2§ánnÖ鸽+á¦OºÊ#Þ‹$Õ«»u_—¯|¦Ïfž‹%ì4'¯B=K¾æWåÂZg ü lÇ“Ëv 4À*äß-ÏVø>xª ÏëÙ‰R–õ}býWø¸›?ïæòhDæHWJZbe[sMKÛ²TŸo˜e• jc·'Õ;¦¿¯¡½‹Ïë¡ù»¶¢¦†¶ÚêTG;6J¦8ÍŠ•ɦޯ˜¾`®yÛ,¯ª1zb,uæ]ëœm­l­iŠSø™åÄm;Úȯ¬%+c½›ÕåÄ}7uîTζÄèq³—”?¶8± Ißç&Z:“±“¬§hŒó§,g»r9úœxÍÆçÉËïéÍn’Ð<á¡Wü²{òšjWJ^X>R7øc¨Ë‹¥04Ÿ¯½'/ªÄ»Óú¼ÐTðöÒ¸·dVåì«ú÷8#çýKâ÷3‹‹¸Ùìß㮜÷/ŽßÏ×ÿ»d¼ßaùÛûßc‡e/Šßs”ã¥Ø·ô‰¹{aÜS†– ·K‹RuuÕ˜ªukäþˉs÷‚M9¥Ó"3rµÌ./Û™»°X§]y;˜9>'kZµ}»r¦Ñs[–ÕôÕŠkuò^½)¯ÀÏÅø¡­^Ú]^¼]ã²øªxVó;lê ~ÙÌà¦B`YŽ.Gº7q~MŽ+ãÇÆuÙWN½Éq…åhÏÔšÖ!ähæóùqS3SÀkÑÖ^£ãºíà–K,'Nä¹÷ËŽN-gu*ÛF á®µ…¨yÖ`ZôÏÈmçúüTGk߼ఞ9{nœïÜv”ÎëVšA3FÜVÆàÂ(ާyqo8yŸso^øŽøÙV.ñѶ¿|G kb#o+åÔÕVp Ze¶Üèã_úÙ;j0‚W¼ÚTÓˆçWYõ‘ξ[U V‹®nÑj‘£Ï‡k1`få=ðÉcV¹Ä/€¿u\Ru®Xª#”s±¶]Ñ»îx—j¬Ö¸[9g´æo¦ƒ#ÐÁ«ÕÆ «þŽ»sý´˜³š¥÷03ö£¢”îyîNÖq7ý3wJÅ–›Ùߟùýñ*_MßmýÄ{âý)èÎTwófþw»z>øëóåŸËóúvèùç6¿»gó;i)ï™ís6¿ƒ«WÏ þ}ñú;üàüX³®02Ú£¨®£©ÅK½´ÏKÓevW1ØØó}ƒn7¯Ý‰nÓT57ï}w‹ìwϯåÝ9öŽs…×<åÝåöŽ{‡çÚòÎë“rÓðNxç<œ˜›…ç¥ñÎùñ27 ¯£Ê»»ín±×wÓ»Ø÷§õy_cÏ9Ö!Þ9_+Üâéáç%ó¬z{ÝRÞm²w¸È÷>½xç{¬;@zû ëǡDZﱰ|ªË;ßcaõ$x KLÛ|žø"ïoLžo*‰ŸiáðÄ{…ä]>߉yk‡'þ¾É»5öN[< ótÙ;áèÄó yw½½^N‚þ¬üÀØwÚp‰ç‚óîN{'Œ›ø;)ïœß2pkòÃðîëöÇúž{­w…ífú¢AžâÙ§(Ì™âOé¢RßȯAñnðêtÝêžÛ¼_§«PÁ4~ï´¹»_…zï¶aéÛjëäe}ºäŸšð ×,)œ„žÀ•ßûUá$üzÍ]—uSžæó>óÅÜóÎûbþÇ)ŽÖLàr:û©Ñ³Kövqº!h€K—^\¯uº_ù¸pÒ)8«›;xs¥ø¾KJ^íóÅ¢É]û-Ò›™]y¥ŠO^0íæ)èœTuK¶áÞmE-÷ôóÑç–þÇ9w¢‰Ó"?€³OäßïVj¸_˜¥~íõÐëAg;sSÅ(Æik\%𡳦µfEu <Öºtõìµ|ÑLž`³-Mçlǧ«P7Ûšçt¶áÀ*¾ÌŠ?”µyüCÍœÅy§%bMkm§§×T…û¿yðä¶žv@!¼ÉùƱƒ#mnÛÛÀgâ2”º·ë“Ùƒ÷î³£½Š–/Á¾ø\][,*â–ri”5î"›÷ŒÛÆ—–íû×àp|³úâP wn :œ58гoàmÏÉø³bç®oêÚ­ÒŸ÷ ÇÿoµZ7­«C㱈Æã5èFð.¥ßqåúÛ*»NàcÞëø˜–{i´ÌÉ?U\‘¯È¹ÕñGì[㯨Îˬï¯.l—Fû¦gú!‰™éÖØÏ] ³KÚ¾6†SÞ-áÝÖðn[ˆy^6û †‹íî+l÷îÛp ¿S°ÓËý~ Ì­‹Ù)ò$ra3æÌ›k_ÌÚ‘5ËåxÔåE„¬¬·›¼f‰IJââŽÆºæCñ±ÕËÎîwº{ÄÓFç{ôDåìôÙÊÞ™Û#ÝÖôžYýEi¢Üèâ%þ¶/gVÁ+ëï‰Í}ìªw;gßð÷Öðhõ9|ã5dEwýwæ{)ñ&¾ñOŒy|â{&ßð)'ó=†ïñ^²:}|=áßõ³Ñn'üÄW“Ó]‰¥Áâ<š9õ®½×hgo ïÞkzàäžvœ|ñ…ŒÇî,Üx¸Ç³OðwËÍ×i=3§^›ÛÄœ6·‰9mnsÚÜ&æ´¹MÌis›˜Óæ61§ÍmbN›ÛļÎ.}èÜ[-òw{ËöÅî¼Å²·.‰²¦í×»·¼CÕtœ>¿¦N}îÑ-–§DøÏòyÊ*“­p„™lN‰>·uÂXg_&\dVz# —ÇO& wàò§ÿµåš4}ºxcî5òòÒÆrh32À¸è¯\oy¥|gj–Cù,ïsî©Ù<15¿ÿ‚½-7l©ù¢¹ë5/©®°¼ò c8@zóž×Ò’XÑо,=`<0§3%¯2†uá@Þz¹.§|ÑDÏ$ç3ûrÂJ2¢ß‘× Á'î(ò¬ïÍãö˜|¦é¼É×Ñ-^çó™Âé‚׬™Xé¾hv¦YBèPmE—_>r ÿäŸ_D [@T}»åO³CÎ÷9.#Dºkà—´w \þì†:FF;Ä÷¿Êèï¬M×µ¶×þiB'ଌ¾Ýϱ¼÷m )–ø:W×4Ön,2Oþ<Ï‘Ç3ËR°«íGƒëìi v)F“¯ "ø`ô”w¯'=ïG¯¯ýÂg„×äYt7^+\¹ ¯MØ÷’õºméû#ÔÑb5€á ß"ܾwG(,»ÿŽ Þ,éÎojªcˆ}s#°dóG>'¼X9˜¯êÉLñ† ù >¿pfòÃ{ò'×mÈŸ\µ!¿ù&¿ðirñ`þúóïXx#z;öbði§Æ½›!áÛä„Áz–˜§â;×å1ÿ’|ü~f7"¾SF{?i¦Ž·à4‹ò:Lº½¹½”ÅÉÝÉMÆé••ð=H³`ÞÜjÞúÅ´bà,ÌûùßNþ1Ý÷.ÏüÜ9­÷yç“ãäx+¾G¥Ù©ç¶›ãztÝg„ïã:æi„óL¢wÿì™D=øgÕþ-ê5$BÆo_˜ã¹Ä¤A7áºÜ)«>Ÿó¦…ŸÍ’žÍk¾˜_Õû‚¡Ö  Ðß½òÝcÞûž+f¸ãÙ¬›[˜Û%ÜBjóöCOqűÑ!îþñ¿\ž› oTâ¤Ùxß{qãÎqÝÃð²}­Å´yä7.{wSxwsˆy·ïƒû™ógðþ½áóm – 6o`õØûÆ<áðžˆ}'œzJåç¿GÇÿ’rC„•ÅÉÞùÛ°qú¼ƒ$þn$<œxm½œ£v_â{€.Ÿ¿) ÿ&Þ;*ù<E˜·àuüô®àó ×¼ïü »¦Dxçõ÷„K‹Þ/|wyF0÷*f=Ü«X3ôTªèIÅŠéV…?";"áYð7$cl>ù{1¯"æïUÄü½Š˜¿Wó÷*bþ^E,ÔêïU»½Œo;gþÓ\_,Ç¿x#xü<áj¿ü¢Æ§ÜÞãÍ»?ïÏÕ{ù1;¿£¹VlõÍÑ¥.õâ÷»RÙX˜væm½_›ü¾V¼hsÃXiµ®I.ÑRôJ›ƒZ4?†ýŒÞZòz¨ÕçÂó6u?}°njõ1j*ZðNÎ ýÞÜÞ±¤·ò’ãi=è¨ÑÔßÝã)\ùŸ:Øê÷1ê¤/äÄ¿8\Þ§l©¹£jÔ®x¸ø §gö¹÷1j/–§”Óøo'çY¿íÃ=¢~çÏ<–‡pí-Ǹö™‰áC\ûÏÄð!.ß#&†gpy11|…kÏ™ž|å‡ÄÄð .Ï$&f|»^pµ;M Ÿ¿šÃço}æ¦ÌN Ïg Ðgëþ‘>ã+Ø÷/Á¾'yÿ‡uͱy‡7`ß¼ûž C¥3‚Ωï¿üý¦ý—¿_Í‹í3{è¿ës¾Oúèg,¯ ±Ÿýøk—Þ!LÅÆCÈQôDøiÔœƒÛ¡œ¯GÁs3æb/]R”X™êH4u´µ'šSí‰e5Ë“¨|ž ƒž3Y¬úèȧÿÒj’¹Á rA1jN iq?ÔĨ¿Ã-ËEuÔœM^õÌ-CHz[¯Ò?ôóqðNØ´1}¨¢Ó#T†½¯3Žoc¸ž÷I/=wŒ›‚ÇuRÿßí÷¾„ÇuôØc-©\w:ýþ²'sEwìr‘ÍÃð^|«±àÖQÎCÛæ¡“_Ò=ó£}‚Öc×@x>@ë³Ðí™~¦³@ý,àÏñ§Á/›—&AÉ›§›éùšYÐÍ`¿ÉC 솶^ížîÍ Ú~< ô±> b¡=< ô×Ï‚®Æ¯ìÏìwæFa›èéwØL|‘<âáŒcìwæ31e“žNçldª:?žz[Ÿ1vÏ#?ôÚχ”ÝÍ}àTJYÐg0&› |…²/¤£<ºlˆÙ8`ÀÓÌî¹pþµ¿;ô²>êÈÃû‚þúyÀC2·yÛýæAS9~‡âYt6ÎL£ß<ÄÀLL¸ÏËN7¬øÉ.¥¯õÙÀ¿rçlXž– úì{Žweég·I¢tê½>³G˜ÿpÓ¬ìÜeôÌm øX¦íã¦Ù÷Ö0Ê{Õî,B»ÑÖ€¯eõ  lÛô”{k8(î`dwËtóæ¥Žê¶ü/SúÞÔ¾¹°¾6‰CKA<$<¾©6ÙÕƒGfêÁËÓë¬g3Pÿ¡zìNÂ;s‰t2£ýâÚ¦TÎ×{~þ˜¹y‰;Ýú*TŠ|ðÁ¬=ׯ}½õU}; }–°§tÙfOýpGu;J¥ªk3éM v†Ý;ôÎï&ö”çT²§ün¢‡^³>ì&ãõ¡½MýŒ—9¦që8®|ðÈÊè®Ö:îsð}ìïÊÝ3 ?™zXŸᮇç€þFvwúÆe‡x½õÿ²âš¶±ã/ûboß;=¡Oü¸_Ѯ϶Ǜð;tQusKÔìöÌ«Qkܳ$w÷L½H{FoÜ|PþŽÎ÷¹öø‰Òut.(Íq¦æ9_üc£xjt±vç "›Ý+o*‡@‹Þ¥}Vìûž¢.§ß+«ë¡zæÍ€›ª÷HÏÝÑsO¸zeÜg¨ ¨»g⦠ÜÌŸc{?´ó±˜â“¿²¿xd>¦Y06ÌD¾ËæÀk¸0^·…9Xbs€ÌXçÜæ€~Gåõ×áé;ÂüÂýxÃ>„;¤ï†¡yCxú.Ϭ‹,œj—Go.r÷~øØ|«£ËìáVw¼ÏÝùNTŒ‡µSÊSòäY÷ƒ†Þ^šÞYŽŠÝq—IزÀ¸Á909ÑqïÍiwyWN4Þ{sZ´;§½G?ÓÍXWNné½uÚ{kWNnñ½9í]²+'·üÞœö~ו.@oN{ÓêÊ — 7§½ût儋ЛÓÞCºr èÍÉݤžNAoNî$õœìÑÞœÜEê9Ùý9¹}ÔsƒèÍÉ}£3'{?½9­ÖEWN4_zsò¶;§áÇôæ´z2]uêv²7§Õêª~NoN´[ë9áèôæ´Ú¯]9áòôæ´ ºú©ûäÞœÖoFWp‰zsZÅ®œð’zsZk]½Ñ-¹7§÷›·;'öäzë´þ…»rŠß°·Î:† Ÿp¥zsÂ7¨ç„SÕ›“zºsFÛszžä¯Õ“ÓiìÎ w¦7§õÃÖ•ó!Üáü.wå|ßxO×»çæ¡~FÂݸÃrÂz0«½tíq~öÖ _¹žS¼©½9WpwN´[zsr“¨åܘ£àŽWìÍé8g¼ÓíÒäàþYÏÁ;Ÿƒûa=ï|nüõ¼ó9àHÔsðÎç€WRÏÁ;Ÿƒ]YÏaw¨Í—©žƒw>û«žƒw>7ÒzÞEå)—ƒ›j=ï|p›ë9xçs ×QÏÁ;Ÿ=zÞùèŒÔsðÎç@¿¤žƒw>:(õ¼ó9ÐZ©çàÏ~K=ï|´`ê9xçs 1SÏÁ;ŸýšzÞùhãÔsðÎç@{§žƒw>º>õ¼ó9ШçàÏA=ï|°D=‡Å6‡¹/vçàÏan‹Ý9xçs 3UÏÁ;ŸݱzÞùèþÖsðÎçwÕsðÎç@ϸžƒw>ºÉõ¼ó9Ðd®çàÏÁózóÄå@Gºžƒw>úÔõ¼ó9й®çàÏw®žÃrêl®öõ¼ó9Ðï®çàÏ6x=ï|øYõN_Ëäà’^ÏÁ;ŸäZÏa­ËÁõ¾žÃiÈ›prë9,W׿@~®žƒw>Zòõ¼ó9У¯çàÏ7¦žÃrfl´ië9xçs k[ÏÁ;ŸMÜzÞùè¼ÕsXï’6Z¼õ¼ó9Ðñ­çàÏõªžƒw>úÁõÎ7¹ÉOšzÞùøp¨ç°3müÝÔsðÎçÀÃC=ï|üéÔsðÎç€#QÏÁ;ŸîE=ï|s¿éÎÁ;Ÿ_–õ¼s7 Ë5éÊaÞù:ðY¯ƒw>^3ë9xçsà]³žƒw>ž8ë9xçsà‰´žƒw>>lë9xçsàƒ¶žƒw>ÞØë9xçsàýžƒw>ßë9xçsàU¸žƒw>¤zÞùøê9xçç¾ß›w>‡áuçpÚŠ¦V‚ÕkåÏ×ûzÞù†·ÔÃiÚšxÒ¯çàÏÈE=ï|üô×sðÎç@J²žƒw>^‘ë9xçsàý¸žƒw>ê9̰¹Ìc=ï\ŽH\®ú¼ZŽ—Íw«žÃrºl¸ZõŽËjrô܃Í;Ÿ£çlÞùðtê9,Çæ€ÿSÏayA6¼¢zË7²9à+ÕsX“ͪžÃò£løèõ¼ó9à`ÕsXn–ÍÑs 7ï|tê9xçsÀ«çpš&üzÞù}¤#‡Y›¼ó9àKÔsðÎçè¾—›ö^nsôÜËÍ;Ÿž_=ï|_á2ÕsðÎׯžƒw>|“zÏxçk…›T¯ƒw¾8(õ:xçs åS¯ÃjüØZ>VwÞùðXë9¬Î–­µçflÞù=ØËé‰_¼ 9 _¬}¯+Ìòãgóf.gÍ~ ¥ŽŸÕ4Žžò+>¤@Ñ(ÖŽ®[M/‡*†UÓÛÄ[ÞEð×]*y žEô×\T,aûkºÒòÁ¨s55‰å»è¯Åoû¡®ª ø —b¬ÏÔwk&Ãëû3¤õõ“â—Ðs?!u³®}Ó«Y (Ü£–¦«e] ÄÖí¯K¨Øýu §?ΧÙ$ÄV" 6œÞ  †“`§Åô 5â´z “"õïh—×ò-¶ù@ا\E¶I@—CðSš Ê06b+²•«¬ìV.Mò …Í[€Ñ5”Ú l•¡ÔÇðŽd{Q½Iм{¨D=£`–¨s4Ì ó7µ{™×Œö–{om“ýA½%Âþ°Ê\5ö§ž2¢£c@¨e˜cèe™\mä/ƒå­4*`3´ÁܨÐ×6j®0›¼0ž´^ Ûf“&Ñû‰þ gkG¾‹eksAAÉFÉ ïÆFYA0smÔà\~àÀÔi‘öw V¬Ì^(õ ÍèèjÂz;PµiÆ qJè ¹MÖLôfNÌñƒñ_Àë`f‹àÁ°Ä¸0Bž'̇°Ù`ŸL`¶Qg›K¦êãP„ˆ:É¡°ÅcæäЗƽ9ô¥®—_ x§›:O:J/áó 6xI G~†Œ'Ûõ,úÇ|Ô¢n«M<"Þ©“4êûdõ[½?l ß"̦¥>&¦šæŠò©ŸS4Ú]S…jÔÇi—Õîšö"õGß°D´?¦æ(u;›ËÒtêb^¦Só2ï¯ì°¡;ƒë.DýŠ/Ø34GÚ13ñöÛu¦H¨þ™R¹Ô|ÎdW¡à=Sî…DfIœWó5‹«#ÌÙ#¸¡&u³Å|!GDÚ=Gât0¡ßí(—$äl×ÎÔ®œ K&¡®y\ÜêšGj= ¡ l¦£¨ È£˜gvêѰôú~4;-a ƒ?¡ÿǰ ú ¬ÍÌÑc¤F©~cH4ŸÃn>{¥@¿(æl½*Ð÷c¹v`¿,„é_`o,„U`Þ±/ ìÉE°k Ô·ˆ~±³ÿŠìÜůã[³x» H­Ç±o¥?ÆR‘:g‹Ôy= u«õž†êØátæ»Ä|.§Oeê_³©Ll9ûGèËÙ‰eæé ðO™úÏ ¿efø úTfžÎ¸!Þ›gÜæ¶áßóMzorõNÒ˜ ´e£lØHãÐ#H“W6úOî­ÇÚúHâLÕ©)9K"uü¬¿‰»pÖ߸½]Ð[óm£ ”ZOÌïl,SÛÙâä©¶³µÅUÛÙß  ¶§09 Ö§ê^©)~ªP”ÐËS_#ì§âØ º§j4ÍOSÚ¾O“Þ‰¶íÓt÷ÐvzšæEÓ}ΤœCÐQ}:È?’ϰû÷3à"\ŸÁL~+¢j¶Èuå‡ã­¿ŠúØú«Ø¢lýUÔj•Гê?ïlûó¸í Ë¸^8èi¼‘h‹¬¥Ÿ §µ žÏÆHØVçÃßIx{>H™ïóA® }>_:µêï:ùºX‡5PÀ:´-¶Ôzøl÷ é[|#Š-¾Iw Õó,PÛü8¹lóÍhFèÛø÷hÆnaƒãiþ¹ ºýy®´-´µŸËÖÆçüó´mUÏóØxEùVòAæÏ§®"[ó j(2gW*¶ÿ•ÌH‰ž^É|°…¯dk•È¿íÅñ6ÞÆ|”@QÛ´¥ÕmÜöJ¨Ý\EïJÌíUô³D=Wc»D=W³=K š«ñîP½¼^Q ”ôxnx°3Æ~!ŽjAô/D-ü"ö Þì_‚ÇêÂúVfŽvpó/Ó³Ã(3§/¦ePÒKÐ(Óÿ—‚¤ÊÔ÷R0k…‹Âµô¬Z¹ÎS…ص § u¼^I…9z9û¡Âü{©Bß~ ®V…z~Š+ ‡Ÿb¾*ÔõSìƒ {ù¼Áþu îvåuÔÒ@Ÿ®£øÆ¿ž@{çzxøÇ¿¾:öÕ=}Å[ÿ«˜ üõ¿ ´ÇþWƒ ðÙÿšCc¯ý7°'Y•¯å}#ûåµäm¤Î×Á¹i¤Î×qYÁ?NÖAXoä:€7ÿ7Qc#³ÿ&Pf#ûehº‘ùØ…Æžõߌ†A#³öfnÌ\ÞÌ û? *n¤¿?Í-£‘¹ùiöO#sùæŽö[˜á&°ÁMìý&ú~hº‰yz«Þ«wo=á™ÿ­ï1Ã[ß«mŸ£.HJ@A4C š9®M.*4ëþb‘ÑQ½×–x¯^Œ³›\”¼//øÊFÙýà2‹N@ ôÃFUWUWb¡¢4¯»îx„f~oÕ][;ëmÊ«Ù|›øCêÆÛÄæxÛkâ™x^°T&<džæ÷6Ý<4]o“ ‰j~Û7-ãﻡÉWŠßN62¾]Ü_ÕþvU 9|û—ãÌoÿrf{·!3ªšÍ›¥ò $v³öšÜ›ÅXÖÆz‡Ô}´ýߩд)n“GÈâ¶=ÈêÝ“Ôé[ØV°ŠVn”ûg¥n¢7?Ëö‡Ñþn&>¡_ïfKp÷x7÷ÑÏ1A ñ@ ˆë66Hè6w÷è–¨ôn é=°’ Ôð‹° ôë¹/Èû‹B@ÊûKLjÍöKÜ‹ŠLÝø_¤·ËéúøAòƒt>H-E¶ã¹«ÉûAîDEɇˆA$pøoJÌLJQ")1Q†ù âù0H­’û0[±Doî`ŽA8w€D¸7ÜZO dðvE™:>²à&ù!ÍÆÌˆåN6+ˆåNÐj™Mÿ+Ü@*¿Â¦¯°Í~EÈDóõ1f…ú?ÆLTèéǹcT˜Ÿƒè*ÌÏÇaƒ`>¹ÜŶ«0wq©ÜE?*Ôø«0@ ¿Êü50ç¿ Dò«ÌO}û$¤¤óIî[ ôè“ÜÙè㧸¯8>EÿÉ÷)! õÿS0s@¿‚iý ÈFæÿטŸFêý4 _§…´Ë>M@¿Îfmb¶î¦M쉻Éß¹„ß*½››v?öËÝÌD?úu7}èG¿ïÁõc÷ü(§Ûô7¸¡ö#ö› Å~Ôÿ›Ìy?êúMîJýèãoÉ­fè·˜ý~ÔõzÐÌ<¤Ú :ýmÅ5O¿ bifö—;V3óø»ì€fúòY½W> “²™Yýì«øV_Üý™çßAõ'ÿﳃú3À·?3ú9vmæéugWý_`ú³+¾@=ýéÃ@Ú؇_ _xó.˜Ç/€ÀЫ{@¶¨é.˜ç/²±0D}˜ç?A3ý15d¿}‰¹HÞ?aä’ñ'oþ?ùk¡«xLµ€a`<¤×ë˜ tQ1ùâñ|ºGNŽuuÍ'CPšØyiO»·šÚX÷˜,ʵ'½ˆçQÕ™gÒÆŠ™b‡µ¨[°’ËjY”;°Í+˜#=íÌé åÅe}=ä‚”^Ñbid(å8¥÷°!l½‚Þ±ÔÔ²™ÉªàmVy³Î€r³Îûça.2ìªMšcW©È[tö'ºª+ÓŸªÂ’*nµêû²Ð«¶à—¥¯¢Ü_–.„PÈ—¥¥¤_OI(ãËâÍi«ý¹8 ÚŽ®z´ÿB]Ñfú r€æþR}ÖVùKÕ¥-õ—š{m¹¿”'(ÍÉWØ^ôç+ºwi Ew0Õý8eÜϾ¦uðWôƒ»Ù_±õ¹šÿ÷.®ægŒ+ù_ê@‡ ŠäZþ×\ýA‰-6ƒ¶ì_ÃyB³ìoÄjPþFž˜TïW¹²‚¿Î ˜±oÈ™¶ø7ØÚ6Ú7t¥V¾ñxë}ãg‘•†¥áï±´©ìì iÇRvJ~we ¬d£ôŒª¦X8ÙFÙ^hâ”Óø–}º½"qÁ³}Ť¦ÕÛßßIAJ]ü;±´“ÿNÓ©ô÷äC8ð›RæÒ~ÿ&Sÿ¦.À¬ÿ Ö²¦ì´5eÿ F¹¦ìÄÌÓTÿ£öЦëEîÐTý£:¡©úG]E5ÿ(ƒºþOræ ©ù–6¨ú÷-½¦ú6×$¦ùÛ`rØóßÖÔ«îoëªzîGñU·ûáÁm@›«çý8DHÀˆ÷ƒ%ŒdGô7)å[7ýd:ßÂÐ þøa‰%Úq\9å\÷Ç .\PËHð—‘p³×4¾Op O¡PHË´Ý4åqó¡kh,NxEqj)[Åù ]Cã|T 8Ì+ò+œ™Uu>Ê·u‡ÉÝÃ×!Ë ÃñëÉ¥«ˆ&.]EêkÒí@ÎéúQGG}ýÀƒEœ öc>tŸ †-âW<)¾R¼3uñJÝLŸÄ[ŠŸÆ†—!~š8_á[—Ðâ]|kÛ–èÓøYºÄOgþÄ]ˆwá¦$S<œ~•®â››‚ê6*„`­ë¨8ñ3Ø eæi0´Lß³ÊÌÍ.NeúÕªë¨ú<ÎJ™¾ e+–©gÛ­|'ÄqÍse8ßRÞÓLÄ»£RÁåÍH0_…~Žâ¦¢›A¼'ü°ÊE|kÞ4û±QvfUK70‡£É§kgŒGëhs>,-ã•ñ>¬Z]9ã}¸940ßûÿßêÏþº!¨?ûs%lÀ9áæ½áb¾ÅµÑÍ!Þ-Ùp ßšÓ<\åZßp߸šÖ<¶¹'óý ·Ýõé •mwÏ9(»/°l  ©ªï9þÌpWÆŒŸÅ­o%¾:½Ïk›"ãi£ìˬBj²z,œ½qfÕÓ‹s©ðU.“º/!z½‹jïÇ2 ‘¢‰1€ ùÅû wjÇI§D›óq2µAøI<üÄe‡×·>=ç§Y[tê‚tÔ³1âžëšñR¸P5ãņÔþ4ÂfŸ²áÖ [_|ûS·¾ønR¥‹¹gñ¡ÜBtSˆ7 ýƇ‚„¥ãCÁ BOñ¡b_h/"|¡ze¿‰'ÆI¨k"—Ñ„}2Õ”„º&Ò]ðÃDPmB]ÙwºƇƒ:Á…/d|e"û\p¸ÔBÕýÃÓ÷PÅPWÑî8\jQÚ‡kÎ…=¦ ñªÇÓ¤l 4MØI½ž¦;ç­ѶÌÕx´”„A¦ëvñt¹ßv˜.$­5C— íôp…¥â1ê½vë ¹àTOfÈ›fcÆ?Ľ™ñKj“å; ¶K†O…3ž ¬“=ðÚ}´ª-›_;ÀxÊÕ5ËE¹ #º(½çÄEÁµ0nüUÆ^ⱺ©§3ÅÕ|γY=¥wš©YRMÑ<ÎêŒ{<ë ÏÍ‘jŠfrX*ñDòÄ쑹/‰û3÷%ŽTëO†˜È}[= x7!suoф̓.®¶ÍQÒ%Q'ÒÜiã­+$t´t—ÔÉ£um":Fuj # Tm¡ùº.i ÁΣà ĖÒ\ =/d¶€ÍÌŽ•n—¶Ô±Òµâ<öqgîé:ó'Ëök¡t›4É‹ØèX½_,-mÖÅêŸ|–§«‰áqb«/ÇëÒ ~/"MÜñÚB˜ÇˈÛidh+.Ñ–ÔV\¢>}™nƒBp'0ÑÆZ9÷"mÉu9мœÈ{¶ä‰z/DqW&õ$&™­y’xZB@@K¹Á€$–ê½æj):zÂcñla(á “™/ñ·â9šhmŠS„å4O§°Ýµõâ9B"š§StÁÐ…áT±45G§Šÿ¥9Z¦­ª~.£ßâuÅ•ªG~$9›’±h¨9\Á%%aV°sÅÆŒ€ˆ¹Pœû2>Ž‹ -8“þ@ÌgŠé¬½p¦X–êó™\OÄߊr+^HÿžŒÂÇ)°Îâ"Âåâ,.9âqŋĘVýOe@#OcÃèÓÓ‰/O¯KsvŽX•ª÷é m.O¿=Þ O¿Ýц¾ÇÕ/‘»ë/QM‡‹‚,ö±izk£äÚD¨c”C5M£n‰/u£¤ðà®û‹e?Ý­”c¿‘qŽýÒÜÅP|"h‰?e9ظî7ZŠ4Ê1Zy•c´\(Çha6ŸCcr€—ÈqåÀIϺ&ÊðäøËgÓýš*â7MNÙȽÙdoŒ–{ãz ÷!}ó{ƒƒ5ÿæCö†yq¿Vç^Fßà/åoýÇ8G«¸ánvZ¥zK”ÇÈñËÁ-Àå¸LŒmå¸Ì˜œ—•ôžû‰¶\¦¦QG;á–Ûe8ÒvD¿4,W§®(#Ô^›Ü‘½àzÉ>È^Àî4j@ú/ý½ðwØ,³fdbÒ0Åj9Øoµ ÄZe(¿øê³^ Ï/ÂfMxРܝ¢«¸-ÊÞOžßèö¸({Ÿ½,v@”½ç;ÃÅp‹²wÛÍŨµmiШøjÁy&@ Å“ 16#Ì~bš9=F‰…JwôJ/äšI±gºêЄá*´$Ò#ã²Y—rô‘ŠpTF@yÜš©Ž`㊆{Rjeg¢bE(CÁZã6 È;*áòv›îxæ ÅžaßóK¨Ó³K¨—¥Ü¨y¤ÅØÑ8¦!3d¶Å`Q̱˜ncŠè’j;¯¯?u±¯º/]?MóÙYꦭõM7"vØÄóÝðVfôz€¦&Û¹.·íÿÝ}Îø‰Q}t Òµ]|] èÀ߸ÚÿÚÕ ªgG»º˜å1?t¸¨…wì¶ÓÈÎ@­c„Ëšgµq˜DW?8/\7F»<(¡€%$É$»Ìj‰"n§«"&;㧈Âïbô€>òžÀ)á¨Ë³[ØhíÛ-@‡Á LÝCTê8º‰’ÜãQÞ‰–/v™¹òPO–ùó–y´›Kt~}Зó=BŽ=B¿Î÷½;ß#.=~S|ˆÙYB£‚ç9äËÁ×hp¯«Ñ߀©ñë5zæ›Îó>Ø®žõÁÅÊr>,RX®®ÚÉUä¬v)_èK,†t2PdñÅ^y©Ÿ)AwÁ`/ò›*œ’@!ÏeÁ̓¯‚«‘¯‚Û”­B4v£UqM¦Ël½“B•‚="³óèx¥Úßlv–¯”Ë›¯”mï+õœ*åZì± —@‹]¬ß>bü­óͼ£çègýG?× d?×èK’¹öû‚6¥ŸKϲa.ý…ž¹¼Ôz,åEpQàñ^âºýYëödwÓÝ3ûnsË$7y¹¾ù-à ÔwµQß ÔI}7P3%ØÈwl„ªÅFto´WÓ ¶)£n÷šŸ±›U^ˆ aöDöBl£Õš½ø ‡Y„Û+Ë"ÎBl« ®çK´É]?OÒÞt¸ Ô¥™ÊµÚV³'Z® R ·+\ÕO4|L'‰q+áÊI u8KÄp¶=îqü‘ÔŒôæ@Åìm¢èbhá$Qîç´åq*JŒÝ·Ãõ¾ø9±/^ìº^ü‚bÜ~›¢Ü¿Sß`Tÿ1úÉݼ)šîb\ƉqcâÎC ”Ç­ˆ¸—›810³½ˆ/ú;¡Bîá¼±qâw .¼ã ÁÕ”W Ô€‰qåàžCì>7ƒdíÏ ŽwŒ £TÂdBݾ@q¸@ÅŒ÷ æY7m}1MÙ%œÀÕø&&œW0¾Ùó0qK€Š4» þ¶\ý)“ *··:‚[Ô—8Œd«\G¸?{¼Šö51ö5ZÙTžF[›ÛU$êcCþl@ñï(þVbxа¸YLtÓ¾ŒbYõnƒ[vÉ¡W¿j[ÛäQˆcl@¥9Ñ£/Ù ”ÓØ»Ù £{–Î}Ð55Ý¿–_nCÜõÅnÉ+€‹ÏÍ^à÷5€ìüøüÙ ®x „ì<úZoðyÅÈ^p}瓽Àß›:{ÒZ­z®„0'²ð Á%Ù îöµ~ ³_0{.-Ü.Ù .è‰e/¸sïÉ^ ÷^›!ôÈ e/Ж©õ¾NmØ7µN³¸­e/ØUþJa_°Éj•±kÕ³+kb‹rÕÊ^°_¹]e/à`Ô6»š½@½V=*èÜà²è×»³hWA®ô¾LjŒ>ƒ¿ªØ ²Ú4 |[{Þi­÷¨¤Ö^€@j}ÇÔ^-ô*æÕ^x?(Ù ðSm3®jöªÍ=Ȭ–ÜV{ª«mS0_m¦A„µýw †@“µ0µj/ð¼Q{N­ÝA±µqk‚V›*ÔÝk9@ϵ`kØ6Ù Kí¸¼ö‚ËCí7ŠZ‡¸`Ô6÷àúQë·nÄÙ ®5LÀ]®XöV^vsçÌ"îÎÙ n:µyåâSë÷ Z.Gµ©â‚Që«qï^}ÁMª–ƒ‹U-÷¬ÚFáÚUÛUܸg/¸”ÁƒÉ^pG«mw®lµéW׺¦¯!Ð~m»sQ¬uˆ{#Ø>{Á5µâ Ys)YƒïÉÀ1ëžaØzÄŸÞŸ‘ûL-£SP4÷âO ‰?%}¶ñ³ûߟeq£4¡Ð™ýñ3,n¦Ïz}‹ÄêÉú K¯¶¥¹×Öfkní†À­·†¸¹×fÅúš½àŠ\㦟-ÕÆ­KõzƒÒâ·£¤ãK½zІ¸!|h«BÈB¥0áZç‰He°äali&TŠG"XWÚ´¨o¢Ù‘Ðoý ]F§#Ã%xŸb•'lt8:ŒæF«µ Xüèl$âPþ×L Ÿ‘°Ûм[ר]$Ò²Ð='‘Â…x‰z©¾ŠÅ+r ¾áßÁî…7­»{"Æ4,_xvšˆD|2ÍJ"–™¦(;Uó…zê Ý…D cÔ„ÑZ;Øð0ñQ>ÔD›>áꂎ½XÃFó>aÏ¢O‘HS\ä/”ñH“hæ´½fÎgÂÌÁöLÄÿÓL˜9øÞ 3K@3³SÅF6,í„™‹Ùà 3‡G™„™‹Å 'ª­žˆßˆb‘fO 3‡´àð0s(+$Ìf¿RK0Þf=º„™ÃsAÂÌáÏî ^f߉v s°…­ÐÊÀ{BÂ̡Ț0sxZH˜9ã•Õ&4ç4sÆ 7:vx߆½Œ¿mx–øÙ†ÁmÍœñ«®Zš9ãG–3þ³QŠ@µA3‡¿´íð™0sè$̜焙ƒí,ÕÃsN˜9Ή&àRÂ0–O˜98Ë(@ÀVN˜9xÊ 3C9ÿ =Í*œ‰ôCtH˜9üXHMÂøAN˜9<\$Ì~/fo/R™01f=¿„™ÃçRÂÌá)aæð™‘0sè•$Ò?A™ ÝtÐìÃG"v·î@ 3‡ßŽ„™Ã›G"õ+]•f“„™3ž45sÆk&âÊŸ= 3‡œ„™Ã×M"¾­n»(›âÇ(aæðr”0sø@J˜9<$IýÃøOJ˜9t`fßK 3‡g&QñÛ”H¹¿žš9ü©$Ì^VÄÍ5þ™fO* 3‡¿Á„™Ã ŠbxeJ˜9tf/- 3‡¦DÌqqfÕ²Dü`1šf¿w 3‡‡—„™C%aæð=—0søA¡ïJ 3‡2JÂÌáK)aæðš”0søGJ˜9ômfŸG‰xÐb­¡ìŠ™„™C-6aæðg–0sx™AïR 3‡_±Dz9â\'Ì>¨f.† ™ˆç,†BÂÌÅ0(f.†¥€†N,e5Í\ S!aæ„E£lf,Šæ$X4Ñ̹™9aÑD3§â:,šhæ„EÍœ°h¢™E‰,šhæ„EÍŠ´Ìœ°( n`ÑD3‡¯QfNX4ÑÌ ‹¢` M4s¢‰fNX4ÑÌ ‹&š9r™9aÑD3',šhæP˜cæ„EÍ @fNX4ÑÌ ‹¢Œ M4s(ë2s¢‰fNX4ÑÌ ‹&š9aÑD3',šhæ„EÍœ°h¢™M4s¢‰fNX4ÑÌ ‹&š9”î˜9aÑD3',šhæPÅaæà”3s¢‰fNXºX´ ™C눙-hæÐüdæP¹aæÐeæ„E š9aQ´‘À¢Íœ°hA3™'Ý`Ñ‚fNX´ ™-hæ„EÑT‹4s¨æ0s¢Íœ°¨Ô6À¢\1„@ Ïâú©Ê L êéˆhã È„ê|Aymœ‚î`Ú8ñ ´qPj’kWî9àVXÀE­›ø®ø:b~°R,C‘<àZ˜ÀmNæãÌæç™)šŒ‚îdÄ”£ {¡c¬tQsŒ±ð혩“ÝùˆÑ¯Œi ;äX«šNãnNF— V.9±`a7ÁPiÁÛî:ô͸gü ºÕQ¥*/ˆ@'´; bKÓž(ˆ… _Fo ‡C+’ùç2 wŽY?\½PLó®Èw]RÕú:ÚÅl·,×ÝvK™L·¸ÁÒ-T½l·tO(è"?ßé—…nwÝ·Ýâ2Jçè–ï"Ýò¢[B·p"ÚÝšáúb.w…±ê‹e)"=Û}Íuw1mÅä“ÜÖ¨ØlÓÖRLúé}‘…Ò\ƒã5¢ga(6ÏUccÌYˆíª±1&Ùi ĽBßÞ¹—À"_ºqzq k–y 7õ2ÔDŒ`’‰Ñ÷Iq—èu:ÕÊ_Ð\0?ªËL 3 ªõu¤‹}-ûM³kj1¢xqÛ²ÄÌé§'ÛNlOµ$f¤ë’­›jj—¤j—µM _S–E9ß*7‰ßùãÆE97”¢ÌR¸±tÜÈ;m¬iJ4n ¶tç›åÜQ:¾éßùãGE9¿,?š)Ûµ’Ë“¡]^Ò3—rvyWÚ­mù mp2[:vC¼)An·¶4¢?~ÑA}Þn‹í}áòÏ[Z“õ Qnª}e †šß˜jNÕ×£Û­4ëSQÎ;R™l¥â¦š¥ ¼>›×.qi„ ZÃ=bs{ÝĉÕ3*f•GùûǾ‹£Ü5B‡ûxe}C#nåõD.ÞoOµ$›]0*xcC*Žn^ÒQ_AJ›÷C.á…øÆ–XÉy Í5­+«iK‰zä$QÀ;ÔeßDS‹ žQßšLVÇE9_H¦èlk²µ5EôöÚe5­þmñ†]™ZŽ%ó ©QÞôŽf¼®öi¢å-©¶ C”Ÿã˺زnn8)É9ÉE7µ·r qÁ I®\oA ¿ ¹ +Þ’ Åã_6Y’}~™_,ëË]ÙÒšbî¾êŒ—šX²Wl>Ôo«mLµY0.i`ôl¬ÏtFïkÆÏãõ”w¹û^ÙØÐÖåŽU~V]½œ~Ihsfº/jh«­Æßÿ¦Žö¨`ÿÚTcªµ:ÙÔÑX㟜;+_‰1Â(÷ó¾úÄê¶dc²–†¾=¬\†=ð•2Kå×-Kµ6œTݶ²¹–¦n@dZÓ%‡ >^¼tÚ¼ªiQÁŠšº:üPª(G‹åjÚ±Ìy^=^ÝÞŠbÏ[ëZª™ËMQÞ”å uÉTu܉5QÎ[j“í¤2©_ Þ\[Ó\íš§¤m¢ ·oLZRíÛ˜MìÉM5ÍÍ2\^Lʼn\;ã¯j ÙòËç-m­iYÖPÛÆoZVåþ£æªè9Õnsfc!çæk«}®¨`¬œ_èìmnd–ŸåÖÒЙ©Y-º¨¥¦»’}V§Òx彤[œ¾Áf˾I×¢œæx`°œÆk¦ÙQk«Õ+kiur­Ûµ<<ÁûG6Mñ• ª8Ùžò¾µ”ݹ1ÊýÅ’ÆÞ~µ©¦íÄ(ïœô˜©(—dé\tÖ&¥¾„ Ý$dOJωçÊôúúwNÜ‹‹ã-þW­5jÉJ&»r–ëÊE5-~’×Äý´€àËñsbÑ{SuuÕÀ'-ãײ¾×7W§Ä7·-k¨½Q–€΋*j“¦¼rzÜ5©æöêZõ£rö’†ö¸Á#Ys«Ñú§6YlßX«‰úsµÃZ(.÷£‚r+гŸnûw‘{¨/ƒÔ£ü—ÅÏ%%éËÔÎhˆC …KŸ«œµàèªã+Ë«ç,˜5«7¾pî¼rèiüÔÊªŠ¹sÊÈqAúÍóËçE9ïS÷ÖƒAŸ«|gMëÒÚ(÷}:UD¹—Õ‰àƒ|^å¼°·Ý…N‹žO8Ê=¦™Å"ß’iÐxä•RÆ]åaVnàôdzTð©Á¹±©—’`vTð›˜i„úƒÆ¦ôÐh—óÊ(ï€ð.?T^¿KG/*øRÐuwiËhôÓÚ—5ÐáÕ¥cF3ܰÅ÷f±ŽÓ¸7;˜a¬+ÇØ£ÝKæê¥„ ”0›I™?f®ë³K9j¬¢3G‹rgóyW|ç%6TYZ÷{ë‚ä1 hoñ‡¾SHùöEÏ®¬Ý]:Át”GyoUª#£üåqwuÚ{N;ãÿ{|•_îAwÑïªâSš“ɺ6;fˆB£óevwH¯7ÑˬZ÷s-$¨ö~—«v,½Mõ«Õ¿À·_òÍû'W—m1¯èþ•=«¨†Ms™*è]ùnn£Oúå´ƒhµ^1àºZ\鯕F;÷³EÖ¤(|¯žk?V:j sUú¼¾Õß»ô­Qþßêsé&}ë µViu GÇöÖÔ pÐ_ê¶QÈ?nzy”»’ÓËf;íÙü™ÖEe½….ò§YÈŸ‚JÏ!ö¥'€òÿÎÝ0i¾=½lšŽoSQÁá6»Rß•>íFì¶%‚Õy+Ibï:¢øê} %½›K—–£zko¹Å×Ä»<¥›Õjm«7óÝÎöúi}+þ}ψ ® †Å«s^¨.²«Výu¼ßü'Æ'YzV>ÎÝgDù \`:–cL@·¿å.05Êï›r“Š×Êüté¨qX½¿®oÍëÝúÖ¼þ†¾5¯ï*5žUžìÙë&¼ œÏO÷éÉ×7,b3Fù&>£$ÑÏã9Ó$EûÄ·E… W¤o´+áùþ)ÏÞ9“ƒj[:âÛðyQÁÊæä 7•QŠpù,]¬Ö‰ƒUÚdú;_j©Ýoi5méô ´{g¼üK£©c&£1Cß™úÖh,å[´4[ßšëSô­¹>UßB%Ëô­;MßZ‰§ë[£¶\ߪg…¾UÏúV=ø8-5é[õlÔ·ê¹Xߪg“¾Uϳô­z.Ñ·êÚ:ðÚ:b<õm1žz®åûHêy™¾UÏËõ­z~Jߪg§¾UÏ+ô­z^©ï# O©ëhâ*¬¥{it×z;âbÇn0ß&“£:Y+WÒ€+Ü •¯]f jØÊ¦®¤¯îÔg²x%àh~'7¬$ïå@Q­¡#AzÉäÚTGsûA£ŽM£¾Á£é4\ƒxäXâÄ#ÇÒ8 Ò‘ ÀµPîÖÑ£¿tœ²©š³ô}$ìR_ªú "=òfèi¥£J4[çè[³õt}ëf­]³¥Yk×l Ù¶k¶„lÛ5[B¶íš-ÕѮٲmg¶@¶íªOȶýêy¾¾Um{ õÙ¶ #Ù¶ƒÊw­ü°·&’ãµþܜŗ(h‡lÜ®…/lÜ^BG<ÛK¾Û««çUUU )Ä£ Zô}ëú†t¢Î³§cûš÷} Ó}¾/Sà† m·—°bÎö²“hñ¤ßÛð.^ò{÷ßÅÑ¿7^©~Ä/~—WvùíR,|?¶Ž÷ߎ±†n‰WmºÇÅûÜs°÷œŠã)[ žGù[ ¤WZ·Å¿î!SñòöóϦìå½ç1cûŧg†¥»)¥œ¾9í.ÁNk刭«{’†¹ž´—Å_"c–>®-)ˆ KIû„±ðrjPjo7â+c’WªÒß(¹¶øô-<ñùpC¨wüvåÑ2Wñ³óÑÇ{áüž¢?³u¼{¿¾uUö'ïü¦7³uåû ¾E"¸ðaƒùQÞJ¦†Þ¡oÑgÏ{Â}é¤Ô•P9½{+yÿ6?óQÞ35*_÷¨ùÒ‹5_ºQ}SËu›Í©¬·ü!CïÏfë˜öM¾uD+]þ íõÒ/•GèôÂ'·–.3sÚ¸çkäÎçάÕýh«íô²Úš?‘uh¿ö…@ׄ`ñ—zzñ’—ˆ†©LG÷F“×Ã*UòDßÑmSUÆL¢Ê"…N¨DcæÓŠœ^^6«ªbvyueEUTðU=YQ¾¨ªzþœ²Êù3çVUO›Y>혨àUzyæÑeÕ *§—U•WWÌ©*Ÿw´£øL½™?)üco-¾èÂݽ夯îï­(}ÕÐ[”U¼S¯Nš:½¾Õ e³ª§—Ï*;eÿlYÙ|Fž*îç_AÑõðq³æVV_=mötŸ{GæÙÞœé’Eoï}eÛ|yï“%9²÷Éòª²ªtî·Â£(çm™è±™òª¯lyWô>±å½¯÷‰//oã±QÞŠ.¨*+føOYåM°ø4‹Ÿdñé?Ùâ3âx”ëóëÚèSKõÏg•0O(ÍÕ´ÖeLãâ9¨%½=]núäéŠÓ'oN>9/]Ë s5Ý*zyº–ôɺt-é“‹Òµ¤OV÷×¢®­è¯EOÖ÷×¢'ûk/ç–L-§ ù&«ƒp6M&|N&¿Â•“2³È:=ÊgúÅòYeÇ•GïÊŒ§Kák˜æSüyfb]ŠýÓ/\Нf†Ø¥ø|ú…KÑÔß‹tòÒ‚]OÒ‡•—÷÷&KiÖkÖ£,åÈþ^e) Èz–¥|eï²”#6ô0}X1ÐK³-nÈi·¼oIÚE›Ì¯ ßB›ì¦þÙd§äͳÉf tÎ&»º¿m6Ù‰çÏà¢ñÃÇ«âø“g’½|`ìL²wlœ9“Ì€0p&ÙS6N›Iæ÷R:j¼Š?5г…ÇϪ˜3½|xñÝýËžÆ7 t/O»¸¿…yÚ/ô1O›õxwÚã:š§ÒßÖìiiì@o—”—MPf˜Æ¦´ÏJ?è©K—õºšnþ@/]:ž|]ºczèÒýnÿì³t¥½[^Y…,EGçxTظÃMª¶þ®™TÙ†©<þñ3©Îè—IuW·xTö ÈzeakÉ B»ì»²¯"ë˜KèBÚ4—ÐfÖ7—ð­s §nìžKè‘VÚ@÷.Ûu.áÉs¹D¹ö·Ð>+}o ƒ.¹ûä té²6ÕÒyøíÛçÒùU˜vÏ¥û»þæÙg‰»'…Þ[1wþôòªòiøJIú˜¿M^1ÐÅøÀþV†ÄÏègHüÁþ¦†Äçt6$öë·7[ð :ç—Í! ´|iHvÂÂüqáŽè0¤6ç®CêÝ;¾šzéd ©ß¹9†Ô-2¥Ç uEó§¾’[Cæ‰=™s âÓ3)ÌMË<±)^mñ™/I?±)ÌQñ™™צŸX0iÖDzyÇé¹póf—UFù3ôì8N˧Í+/Ÿå»Rl­$É9œ0vlñŒEÕóTVÎÇ!ÀøN)_8³l§—Ž+÷/£åz¹tîÑNï蔲Ùh™c(Ot8®sQCõ`QùÔGÍ"ffÎLüôs4-QÞín¼ŸÂ";¹zÚ¬¹ÓŽ!x ªy_q©,Šoݯ‹Ç{ú1™ÓÏœô{n.{¡š½í™ðÉeÓ\†Š»˜'‹«f²M¢‚={_è \‘~¡¥s(4jô/dÁtëØQãÓ}ˆÝ!×<9¹bz…ÕŠÝÅÓ¼9‹lÞD+Òo4Ý6Íà¾Ôf»Åô¥¶oÌaا^Z~³»k®y³h6ÛýdîvöšÎwyÔd²³m_¬ë{vê‚*׈âû³lñÝ 5}æ³Y.ÁIåÇO˲E¬D‹{YÅD¯ì{É>/ÐûDz­„•R¸y U-\ÀEÎ ÷‚ùÇTϘŸ”Ìâ­|7^j gΖÖ*OÜyeaå·rN¿éSˆ×¯-.[å¼&=–¨é«‰.$j™‰."º=“iêiityŠcY&EÍHÚ·ÊdFÈDO®,ðÑååGWOã>`NÑþî-åi½Ä:(»Ÿ°˜úÇñà—{Ïú;¬÷ÁÒéUÜhÍ™Ú?у8]øñ¼_9µl>8ÀÀýôÍÒŠÙDbwIàÑ ™DfÛ¦ol¢òät§›UFì‘-{ d¼ìxs&S‘8AõÑqH¾vÍß,âÍ_ d×»ó7+x3©ÿÍrÞ4÷¿y*oÌù'tWo²…cß,ãÍ¡ýoΈrjü›EóÐL:B!=ç ²å³hj…d¢Ò24ô=2ÊqÇh¢+”)]a+æ¡€h1¿‰Š&lX6ª*Ò»BU<ÝGª3ÏÈDÕ™•™¨:³*U½iGR¯½íYBMº·‹Yá‘ß¿áÃÂ22?ë£ ,šå.ôa ©"˜«-á…Õ ”ÈG…"C·O˜SIê>,ø"†KZ‰L++ËçLwÈåi鬧; VÕi8n O¦Ço W @°§¸Ô5//ŸÅã”GìlùX<t^?H›õØye@íâj½\1³‚Å£=³¤¼z·ÉÅZ˜Ñ©K€_+ªçN}¾;ai¯ˆçGŠCiL¤°“£|È>>®#€€øG2¶¥_þµÌƒåUó\ÛîÖ“¥T]X†ÊãêÖ'Áå¼ÅqÏO!×!ñ¬v)¨¹`饭PÃEZ´6IBxýŽò‹ê’hD®A+Ñ*ÆÐI"ÝÞèžæ4Â*¯„ín#ã½êOù×µËRPEáÛÒÐ.É¿7¦‰r›aK"¾å+aƒÂ“Ų2¯66¸í7'•p‹TÏ$»Ë«­[üôye «§_ä*¼”©KO<чæëRF\ƒºÀ_¶S‹š©s€ëcZGa=Èõ,·µ„B’yº‚,fßë6R~­Xt+ʦV/„)pêB$pETËÔñ(_d¾œ(1ÌKiáÊ(ñóhaùU-ãÇ:±º#[ÆŒvWµŒ¯@©¢¥Ä}Þ²$%)Æg.©ic\þIŒF)©ðJW»²J‘RˆAú½)jÌË‘¤˜Øn¡5N©š;-Ê}ÑôÊò•¿åk~p‡<Æ›·Ë|DÏÛªÆPèÚ$Á—o“ø‰&¬•Ò„~“óc^ÏhfìÁ‡¥H¾ŸLfH3Ucˆv½gš3&o?l`zQ¿ÆSúwŠ ¸Äf›XºýȆx“¶·ƒî+p9ù:å<ÏÈI‰–NÃsÈ&Ý—ÖxV#­¬ * ²/óÐ:Ó¡é_ÕËl™¬ ÌCQ”?#vcÕÜ+;"C"ª¸BphA!gbà,Ù¸‘ ꦖÝ¸b°yA1gáàlç^†Ïº×¾dºˆ\iúoJ;›†¿U¢êšSƒŒÕ<„:lrDÄIþV|¼ÁÔoÈ ¹_­þŽÔ†+ ç”ô6VóÛdüOsSÐÜïSÜpe`|Ô!‡ownéUFPØ¢Œ}Š[¶ |sPÆÛ1>ð'Μ|”·Q®C5—ŸäýŒ|CFôÌ£A­ñ^`h“c΃äßÀ»e›ÓhÐR¨©±|vºpõÁ_Û›°i­‚ Ú¨ô ºŠ(Ù²0 Âß¿À¬ˆ±Y=5 Yééïŵ®ì…ðw8^gÈ!”*È¥2äå1¹WþDø›9´Y2æ£Q ˆ[\öp[æFø›…³¿¹òö¢¹­Âz1Dù®Ü‘ð77…KÌhV:õŠ„\ž0ra³„¿…xÚzº¼jtv«ÉÁÌ÷”„\QÃz*ç.”)ý†ÖŽ–1 –ŽyˆC@rýÌ."†Œ ¯ÿø-Œ,–¡µòý‡ø¾òæ¼Øx“ÐŒ5ó2©Iò‹B^ao‘Éç­Ì1LjnM¶¤ZÛ£ÛË›‡ë-½Áè› 4Lj–X˜ËÉ*Ç&ó&5×#¶!zÎ9¼%Ÿ±=gíæM’á›Z.sŒf‹‘³Ábô¢h1s²põbÊ€zeðaâÅîzª7î­ÁÖºÞÄ‹+æÌÀ\ÉÄïÛ[ŒÈWF!&^\>oÞ\ ¢{‹%ÞʈÀÄ‹+ËæTL‹æi&èÆé¡ GL”!¦zÉï{H¾‡6»}óóhsÛÚ±L3ÅÏ’ÄYZ%mí©Úmñp®™˜0Õ½¶ƒ‹K:G&$ϦÐt¹þq5`/§-6¼Uüš[GË–­lk¨­i¬¬Yšœ˜¨KÖ×t4¶'juç[ŒžµÅ8EYø’½‚â׺†e_xŧ{®[›…îq=ë&1}s±ú1ó Û±B² ™¸«˜ÂmØâØÆÅe[Þ®¥«.‹²’³ÆœÎø‰½Mž 毎FtåÏ,êÚ3*-=5*‡KhÄØ®ó³ ×~vfU F4W Ë=eh‚·êÝÎÉëxÿV<'\Cß®™YÙu~E‘ïç‚ÕÙkNvŸœÛs§€©wŸ±°WGuÝl‚mgG‰®Ü¯|@±y;Eñö=qsS–½¹Æ¿I2oŽóo zÓŽÝÊyÄÏ*=oJWmváÙ§E#g¢ ¬:ꜷ.ÔIlkÞŒ–Þ:{ò_Cþ˜üÖ„ü=¹Î^µrbᤗá£IvAŽ9/Ê=ýpôúhç)wöܾpý/¤ûß¾\¶­“z q=¦–çǵPó‚S³‡M„àÜ€ãT“¼±Ý1yq´SI-N™FíÎLEÝ_ƒòÝN¾æoEwWTY‚–Ø@¹ê´hïÕgD#ähkíØÑLó¿%Ù½oÖô¸W÷·—`¦«/;¸ø|ªïœîUÙ•VÇÿn2»R9çwíyIiYwO =hÉôàþô`ÂÂé9 Ô¿bqþ¹âÑl´²ÿ–º½¹Í½Ÿ¯>o]ñÕ³s¢‘÷ôù¾¯•°ü·±—Û¹kÕztߥþmþæ&?§óð jöÓ¶¨Š˜zfvï’‰Ø_™sWTIΩÝXªé™¹Ÿd6e!‡Zæ\Ëv•z~7ï—NfþÛ/ _²zåa92Óà€™aÇpóëvŠééÚ¬ôÖ¤½ú™î¬hYÉþÑâ®a9^&9¥;öh'Ü º)N¤Ÿëè˜c‘·Ñ“²ÒRhYUèeËËÛ…;¬bŒ¶V¾Ú,†°ñÌҋa,j²Å0 4ßb_ñ1̯,)—™*cP:ù¡Ådm¤°wæ]alˆm°ÜX$¹ÍÞiZ ëíð\á{§[@ák™ÜÅDyóÎ:ÅroŽOìö· <‡›¦Å̯Åwã½Ø‘iœ‘ošÇDd–¶úÖTSbþ²šºÔ ¨<\.òà²ÍçÆ|Ó¸ØnØÈ7Mœ¨óÉCàRˆ×åÅÆ¶Dd\ç‡5›9wùiåØØÂØÈ7í¨z¾åÄ^6Jt²ë¨ùHGÝåZ,ŒÁ¥¢LÉhÌÈ79,|nÏÕ†…wNÄаð,ßlƒ‡· ïê?xìþ#oËÙµô”¿1\\›7¸¸T\Ôµ‡áâñÇgçÆ¸¸ýs1.ÞºòÃ…Ý…ìÍ‚°d|çÂû°Ô5#vsXr9ÚºÖÿ]ál§¬È[ÿt¾“ªÜî}×ÀÍPLNæu-Îéìêæÿ®œÎµ`:‰¬Ì#?q¼Ë¿üº×íÀ¬â DHÉwkœ§•<`ÁÖîva®»>p¶{—ܵê8ð„,fÝÞsû©ÌAG&¤ói{Qƒ°Ý]¯ÛÉ^ y…¥îNc»‘«e5*§Þ*åìû%Ý«Àr²7ä0ÉxIn«m{V»]_‚”1˜Iø.Zƒ ž¿]Þ}Ê}ø­Úc[ÿRê°ð 4nKëíÀmK ·Måý¼®6fI˜Ú9ðŒ¦ _­÷ݶ¡Öûnò¹òŸò3f0›öEŠÙتÏ-s˜ ƒÙtûí9cædH†ZæbQvëî§ ³ÅcUÃܳ+'öD#4ËÇÜíÌ;»{l÷víq§j‹[\kçñÖn,4=9Kz{›0壳4>ÌRƒf©£†M³ÕŽ•¥ÎÙÒ÷÷VšüÍÌÞZÌ{qBºs7³‹ïWŽf澂M/›nrØT¡ŠM¹ÂE¹ÅÑsþ ic>ƒ]65ØÇaSƒ£65Fˆ=6ŠǦàÚ©ËÎ øµÝrsO^šÁ¬qqSÆe0kìq'ï¾pí«Ó`KãwÆØÙöa—g0kÒrß¹¯ÉÔ‘â`ðî]áݽ†w1'Ú‰w7‰-fñ®1„îî«ñÂË ï¶Ã´¶&e §ˆá­1Ëm" 3kM[r§[Ôêz¬ç KkÜTÛ‰).Å)6wdÔjÔ­·@7@ZmkhN$ß”ÄÊTG¢©£­=ÑœjO,C¨²Mª–J"ªYœç‹˜:9¾­cÌÜÖŸu+Ü_«Ì{EO‰í÷º5ͬ ¯í-„/áÖ"L„Q· ·:Ìz‡ÃbGüVNmǺSzûÒ‡vÙvÙ|í²ê³31?ÚçAýS7÷X#m¶³ÑZÞæ\ÒS¿3裿…Àmo3­™ìœiú™Î´!´¹^c’Ž9Ö cLÏö9~6þK™c»#VÁ‰øœÕ{Qµ1­uÙ{çÈá°¹áäGçfj´ûVEÏ(³û4'f0ĵ{lßí ЛÚ^3»]ÑN±eÀý&ÂÌQqO1ÖevƒH>ûMþãnx´¿ó¢ÄC:·?Þ ¦Ý»C`ûvƒéoTžÚI½ÆeCo.óÖž\žË‘0&>†Í‰µÊžœnæºrbв7'û©ž›—½9íœwåÄ,foNðLgNæn\oN‹ºrb\³'§»†œ .æµØ›Óò[Ì;ár˜}ßüó9Øõ¼Ó\›ìzÞù:ÀÍõ¼ó9ÀÓõ¼ó9ÀÙõ¼ó9¸…ÖsðÎçàÖZÏÁ;ßWp|=ï|ðz=ï\­†÷Óüó9àÕsðÎÕjn õ¼ó9°VÏÁ;ŸƒeQÏÁ;ŸÃXÃíÎÁ;ŸƒF=ï|îôõ¼ó9¸Ù×sðÎçàFRÏÁ;å¨Çþ3>UÍ–?¸T”Ylfš¨ÿJ²¦Î–dfV“[–õd¬Š ~ ÍTdÙS|ŠP‚6oØ7l{Vùd£O˜³AvíÄâm€á…}»FÙ²k”?Mr£l»©«²¿¦#V?ÙPSþ~²„¨üýduO lr”U½fYo“e¼fÙ“u»þ²Î&bYTúËV›j€3¬© `s0ß5­-2&ôÒÂͱÀÕb=-€Øƒè1§;˜¾aLw0¼’Öã+À6‚*PW+õ›Õ NöÉ£gqá(R×P„ Šôo6‹ôx·Ü"&¾F`­H½#Ðý*2#˜…"–þFÀ:,ÒϑĊônä©1³qäZÇÃÃhôß:ûÜM[FôÒöË5eÎ~¹zaí*›(1¬lm›Ãûæ(iE¸›µ6“9ÜcÀ̾Åp#–#­€å R–v5A£tzДì'[™êÞ~2†ª®GP“?Z;IÛ`´¾ø´£…[Å7Ü_ïE8ß_×TËþ2&¨‰ÙŸ2òí#c{šÌ1ä˜ä&ƒce$Qøf¬  3ŽeR1Æ8NßµqAZ“sİáL1Æ`SaàïvFý¤& íÈÁXÞ2K¨;ÌxjÇ4âxúÀ†/Ãxº¬D?0KxÛ‰Ms°Lê{›„MsˆLj L`0Å7A†ð´•¹F1à¥ÿ˜Å›ß’ý< Â=h’Œ¹kCLf£èïdðv 7YHuÆÒ–a÷è¹l´=˜Âå»Àö™B°E|8½Ãñá˜o+ÐÏÙ¯ÛãpŠÔy¸6‰z:U›DVä¦Ú&™ºÖ±8³M¢ùî!e»ƒýл;¸­öîvN¶;Äϳ»cÌ㌑Q»'­º»cíÍØð¦Ç‚:}}yÚ ¼­pŸÑ÷¾;L¨Cá®™]E f%õFÕÙÄÖ¨ú¤`T}r0ª~X0ª>%U?|£QuììY£êÓƒQuyÎHªkÿ¦f¯±•÷£êX"¶FÕ!ÇxáXYÞ¨úÔ`T³zÞ¨:†õ¼QuL¢{£ê˜¯óƬ1zçªC$ñFÕ1açªc>Ï›±Æ”ž7ªŽ>oTë­7ªŽQjoTýØ`T}a°¸¼(X\^ü¿ªc'ÑU§;~ÿaÝÝU?8U?.UÇ¡7ªŽkoTÝÿ QuŒZ£êÞ!?o‹wðì¼QuìïY£êTñ¥¶´eÌÑœ½3ËÙèL¨¾ù#]OÙ%ÞÌ:Hƒ‰d:=ΠnoÒœþ{cæL'ÆÌ9a:Ouµ3ª©ýk}¦ÒÅÓ—7nmý}ÎÞZÑ!î~Þò··U÷Z.W Ì·MÃðÔ; 1òcfkåÖ’"–ÑÍu̼Ř,FÐùab ݧ8v»™ú/ôÙD·㊘uLL c½Á½ÁÆ­ß—¨LXûêäÁè8¾Í)üÀº9d‚±«KŒ·^cÚ±ºëm™ƒ¿¼-soÝœ}ë³o½uskO^f0•rjDÀOfýa%Ø# o¤¼äòÿVÚ ?¹0Eì{eboÝK—·‘nMƒÛ~YÓà¶_X5öýÂȱï6=>Wz³æHÖØ D~Óú`L4ãà~¶¬qp›Ë÷óøéMÃÜYóà~¦ïN›Ü¥nm½õdóýë霼ñ½åGo³º?6Ü ìÌãgÆÏ3ãg€™ñ}oqµüÚc5&=§lø«bsêæ÷²Ø–ºù½BSáb×™q~¯2;àü^mfÄù½&mCœ1ÉŽUåynV¼v~Î|ºé+ÇPogß™O7}e¦=†ä‚‚ÄL«« kï°<$ó©/L­³µømµª¥­`­®s2(ïw]flŽcšú±éÀÔ8J4“Ýf+Ù¾sÍö‰ mß9Ljû-†…m¿Å0¸í·êL~‹¡â·£àAXEO°U›Ã"8âqÏHfÂÕw}¡Pe-Uz#å̘"fË15~“»îcxÜ#Vì{‰Yro+åÄè.FˉÑ]ÌW:#ž‘äμOjöÝý¸õ€îbüœ™Æ67=#†©noËÝ̱·¸^a¬ðÂxúÂø¼ß» J£„bò|°%þžeæ÷'³(‘¾ƒñ×+ðŸÇ7`<¦ßÍä¹­íÃi¬çk£ _1‹&™°ŸE è]ù­âô3NeælméÛ×ÔF¾6bv#1v³QûÎNxiúöø™[[“Ê–nq¸‚Ýí{ÍN÷˜…]ï1%ÀcJUÛ]ʤ³EЯù¨«Žy·&æýñݦk~GÒ ¿#©ÆïHzãw$µùIU~G‚*üù”õ€-Âíä_¶{‡p“«‡]ÁäG]V¨Ïr¯3‡×Ä òöKr¯ÝöØÊ¼°Ör÷uØ |/_‡³œ!w_‡µ07$«ƒ¾±É¹—µ¸7nâ÷Ö~i]á÷ë¿¿²Nðûkë?nÁTÏï^«Ûö‹»Ä˜ò÷»À‡ãdQW 7åÆ ¼U<òFáý…Dïœ-øÚ o >ë8ȧö\T{jª½SÕ^€¸j/ÀcÙ ºõV³¦ê,ÂÇÚ0ôFïœ!øìJç±+ŒùÙñNVl®ó±¸…n¿Åbg°}ÉÁžò;Í_„¸ñà q;-ÖåÎí´X·;‹û¨WÛ,–ðWÆ^}½`A_/l·OcÙyµûÔ™“7WØÔö÷&¬j»ŽP×ëÒuÁYð7ÞÔÅØw—;°¯‘K©½PãkÓ5¢ðèoÁ?¨Ñ÷ÄÖ‚™e ¯ps€z7`jÁª-1rrOö}™fæì‘äž û†Lnn Í®.Ì1ëhs™Üù}àqùÁ®PÆzcÌ\3ú[ÊoìÜ[5*Â^󇨈i¶b¦2ûm2™ÜþV>v9¹Ç0)¶»XÂõ]û)í÷fß]k××v¿nŸaÜí3ê‚rZ4|f‹»‡û0üP:Á.\n—Sî´ÜVAÄ•‡«M-àI¸®Ä¸bfüÌ-fÝG¹¨=Ëb` ÔBÉšÅR<1.C[â{O¤ÿ7Ä—Œ`GÚGĸd²ó0¹LÝ7Z L©Y£ŒGš)b`TMœ‰ÑO°&10*[”˜¬IŒ~¿%¾{Âp®xÇ]œ¾ƒ# ž"ÆÕÜEŒ[5xŒ³N#…ú=ñå§ [Ãï/=]„?£Ú‚züg1rƒsý$Æl%ÅþÖ]Ù£<õ ŽŠj*©O0XˆÑ'ø-ÄÀ°_ˆq·‡CŒ»=ÌblAx5ÄØ®ÿã¾’8 Ø>â+©—0vÈÁÌÝã¾’æže$ÄWÒÎ%(¬WçÌ¡¼W’XÛEø®Ç'–b!»²°HM˜®,óåèò Á•™•XZ{Ân™úFoP3]¡îx˜Å¨þžúaÔqÝÕ£A{k1öóNŒ½Ç=C3Ö ½w™wà8C`V ÇNÐNmPo`¶Ã;Ìb˜b‡-C cìÌ#1Í\,¦uhæbñ=y§™ÃL¼‰a|}DŒ@$iОi`IJm¬½´D1.¯a kæù#‡!¾è¾¤l`ØÙCìÎKüܰkVö¥Ôa\Ÿ8›!{!­Š³ölè?‹‹xfÖž)ÆÂø:³K­s¬»ÃGź;¶Î±îŽ­sm¬´c—+íàR¬´ƒë°Ò¦ÃJ;x+íàP¬´ƒA±ÒŽ]z¬´ƒñ°ÒžÄJ;X¦"8+íØ¥ÇJ;Ø+íØ¥ÇJ;è +íØ¥ÇJ;ˆ +í %¬´ƒ”°ÒJÂJ; +í #¬´ÃæÃJ;Ì=¬´ÃËÃJ;Œ<’(ma¥7VÚa{c¥f8VÚaYb¥Æ9VÚaÛc¥67VÚáñb¥5¬´£d‚•vìÒc¥v&VÚa¾c¥u¬´Ã–çŽJVÚa½c¥Õ ¬´£8€•vD°ÒŽjVÚ±K•vìÒc¥þ0VÚ±K•vìÒc¥»ôXi‡Š•v3ãÜX˜qmm3ãØ:gƱuÎŒcëœÇÖ93ë”ÇÖ93Ž­sf[çÌ8¶Î™ql3ãØ:gƱuÎŒcëœÇÖ93Ž­sf[çÌ8¶Î™ql3ãØ:gƹy1ã f[çÌ8¶Î™ql3ãØ:gƱuÎŒcëœÇÖ93Ž­sf[çÌ8¶Î™ql3ãØ:gƱuÎŒcëœÇÖ93Ž­sf[çÌ8¶Î™ql3ãØ:gÆu»53®»­™qÝlÍŒ ›וØÌ¸nÄfÆ…‚̌Æ`Æ…¤ÍŒ i›*73úbÆÅz23®+¹™qÝÈÍŒ É›ö73®«¼™qÝäÍŒëof\ 63ãºÒš× Å̸î˜fÆÅ43{˜‡eÌŒ‹gf\Œ93ãâÕ™sÍÌ8lbf\—3ãºJšÂ53Ÿº53.dkf\¨ÖÌ8,df\hÖ̸¬™qqGÍŒƒ8™q¡W3ãb¢š×ý„7ÇAÍ8ô\f+íÌ8VÚ™q¬´3ãXigƱÒÎŒc¥‡ñÌŒc¥ÇJ;3Ž•vfî=3Ž•vf+íÌ8VÚ™q¬´3ãXigƱÒÎŒc¥‡³ÏŒc¥ÇJ;3Ž•vf+íÌ8VÚ™q”™q¬´3ãXigƱÒÎŒc¥ÇJ;3Ž•vf+íÌ8 wÌ8VÚ™q¬´3ãXigƱÒÎŒc¥ÇJ;3Ž•vf+íÌ8VÚ™q¬´3ãXigƱÒÎŒc¥ÇJ;3Ž•vf+íÌ8VÚ™q¬´3ãXigƱÒÎŒc¥GË€ÇJ;3Ž•vf+íÌ8Ltf+íÌ8VÚ™q¬´3ãXigƱÒÎŒc¥—•v3ã05™ñlÈŒ'`Cf<‘n‚f\üP3ã ØOÀ†Ìx6dư!3žHK3žHK3ž€ ™ñlÈŒ'`Cf<2ã ØG£O¤¤¥OÀ†Ìx6dư!3ž€ ™ñlÈŒ'`Cf<2ã ØOÀ†Ìx6dÆaè3ã ØOÀ†Ìx6dÆaî3ã ØOÄ^ÕŒ'`Cf<2ã ØOÀ†Ìx6dƱø5ã ØOÀ†Ìx6dƹæ1ã ØOÀ†Ìx"¶¿fÅf<2ã ØOÀ†Ì8@3ã†fÆ… ÍŒ£ÀŒ š643.lhf\ØÐÙ¥ªÓíÐØ¥OÄTcË !Â;IÄtdËsÇdËÃpdËÃndËÃ5³véÁ‚Öì<â‚ø:’Þ}-Ë<`E®~Ö.ýÚ8szcµ]o—>Qng—>QMÎ.}¢¼Ž¥•P•gi% ÐÜ.ý ­j:½=c@Å.9‰]I]HíuY½Nti²vé¥çGÏø%º9»ô ØÔÛ¥G'ÄÛ¥OtÅwvéq áh2ÿÜÓ]úD[&ËÚ¥».©j}]íb¶[°}·¸ÍÒ-w—M@®®[šÀD—)k—>tk§ë¾í÷-g—>í"Ýò¢[ׇnÁ„dÖéÖ›\_ Ç;Y§¾(fíÒïpÝRôue°KE°Kÿü`—~kÐ ÐM"ÓÐØ¥OÄkql¯ä"W½ÃUccïtÕØØ»\56v‹ã x7˜Ö.}˜‡—»ŽÙy€ãìÒ'â>:»ôf’]úD,nêlW?Õp Øy™]ú—»x™û‚3Ì%Öt¹ÓôÅKÇàð³x`é ~–/ø“pÍ¢uùóq¢(_N-”F4pSÎÊò÷º)E“;í!—æJÑ­3‹lÑ÷ÉÑE΋빭xÏ®Q®”©þó–VwÔÆ {íc)Û{,xÔæð£FŠ­ÛéhvÆ]cŸxnðKSð7ŒoòËð ©Ñ(ÿÂ…«Õ’ø_›’Kkä1Wûâú6§à,Õ*–Ø —?¡Ã xZîèÅ~ázá•Ý–2æØr/¾U[Ñ17þu+RÚs“­, JÙ6*u54c2G&eM$1a»¹%Ê=¶¡yYƒü[«òkÛh¢öûRÚ´9¹TKĵ5úFì:^S[ú¶{m£tÜùöÎí“;äÈyak &•ÿÈM€È "kÞÇ&ý’Ê2fŒŸ÷ÂSëÈU¹Ø*Ö5ÿR.mk;“µíÎXñ¨Újƨ0²µz\9åw¶r>݈ãMA¨×¹oYA‘/dÕt¾ ¿ÀÚ“Jӹ˩¬q)Ûz:Ff“67ýÆ9n”7ŠŽ(©ïkáwŽ‹£õ팉£Ü—··1ù>Oåiz5ƒr g» ãê)™4TYþæýÏ7ÖÑKë¿ÊþÚNRKX„µÙ*ÎÀœŒ0Â]dÓNŠø(ìR× Jm©k¥ªk¥®kík¥®au­˜^êWKŽèD-ÄKŠ©#éhYe_S XZÔ¼è-ëCÉ‹W´p6ÛÈ~‹…"GÊ)þþM¼Ù,8ÖÄßB[×ÖÍvxè´å%Å%ã],šØàB…kÕ‡þµêÀZõa`m+Hÿi®ö™šç{ÛâgºePXÞÔÆªX@VÊJ¢l‘—Ô´4ÔºÙÞ†bíʆ1xÚ­üýŒ–ŽÙMÞȼPä m©z&ê«S;yš½+ÜT»‚=ÐÖ¦¯b»¾†Õ³  ‹êkyý;õ) åï× Ú”´â5³5⛜ñîgÔsF§H¾YœÍ“ä­€sA³F ŸhjÂÿÐ?LíìkF<'ƒ¨’¤XÙb×7¿ñåJÀ{9—ÿ iÈÇ40_OvÒ§séÄ…2ì¯*üÀˆµsòìEÕÇ.œ‹ñ°Â5X#.\ÕÆWùýn½hj/[†aŸ?Q–Eq–¬øB}_¥ùq’è=zoŸOëkã«tMŒ¬¢óõ[IQö?u”pBÚÌÇ·˜é\Z$XvySS”ûEV×Ùò1Õm¿^­bŠ»V«äbUµëÏWª;â×X­‚‹{T«-Å®jõ°t}Sg-; ‘Ÿ$RA…êRõÓ¨à¯R–ièäóñEBÉ5#ÇÔ´­lfá_¦+¾›R§s^ºq^éŽ=êͳ:ØÔò•u¦r`ÃZ180ºÔ^&ð Ž;ò§þI>…R6ÅWçT¿øJYMÑAûÜÑÅîA”ÔsÕ*Äé•ÄóÇÊ%þ§ø”Kü_ãSãÓ|ʸü¯ó©“Éü?ÉáW’JW=¾Î×µµã•×Ã~þï¦xJþ?OÉ•=+ _üçÒ±œ¦‹?àSæÝÿ’O!ªG]#ÇÉÅ’rVTðúߊ–ÿÿ$.&ƒ+?«®^“qüPLvƒÿÖ£4|*¥c€võK¹‰*#Ó´¨ ë·‰¬³à—¿¹ƒgY|úÜÍrÇo¡×ýÕµ”õ'Ý¢¾Œü"ã$!'ìa”|–¬žìn†`ü¿4ÈJš¥nvG¢365.®e`0$HõϳâJK‚…Òƒ>< ¼Âc#Ä7 µ’@Ö¯(ó˜êøß-”z ¢u ¥¯üw ¥§cƒ« ¥ÇmµPz¡ëE…Ò‘Û,”š™èëÀB©µ2Š 4bóXýìN¨Ê©<|ÐZ3–ÖÀZ1KCjcõ‰½;GVìl/‘\§—Î,½†SóAu^vµª­Æd†r”^#[e×ÝÜs—Y+»u’›©U´s±(áAl"¶#Q𾓸[ûꨤ/¾-*LÇõç~Q‚ÿ£ù?žÿ”C¶ÌÎÆ–Ù2Ù2ÛNÍUkfÖä϶èèŒy‹É®©ÎZÒn­fÿŽþŽ·wHÇO¶Òñó,†tüÒòæ§io`kf˜·?¥œUj^_Øí„§Ó9f„Õ˜Á±…3#3_µpæfÇ[”d–3nµ¨±Áæùu¬?JÈ´Ü-õ.l<®íɰÓÛfòT~f±/ƒ£DP•ó\¤ÀÖ$jÚÚ’­BémÜv@¢¦óus®ÛÉçĶæ„#ÊÝq=“œKÛä#}rXöÙ$þ;¦ýn²°Ö›’)w75´Õjî¦ÔÖú‘Ÿ[”)wcïâZ4mÖø&Ò’ME‰šz¸úmi›ÉÖÜ£FBÄíÄ¥—¼a¹[{çÃ5=?LÛuÕÞ™ ë~.¢†X’ÜÆîpV'— 0¬%ÊÖbfgÎîöLÛ$Äõç"%¼õe7víóÏ…UµÑŸg'9¯<ý¦;U×ÖÅñû­Ý»—(¯ÞÈBä类­{}§°+'»°+ëˆWa5ÕÕÎ46ãî‰Äµ±µû·Žöîþv”öãRûŸ ÇÕ=g=ß\äFÉM§US“bO¾÷Îh\Ðh6äŒô¦·ýÉnñÖ±[æí"í?ßbâ…GË,{勱/nµsï- b}çv{Ǽ;û‚¦¾ÏØ.Äò\‡¹x„fÔíBkWÍÎ:vy–PkÓAc\÷éž;mÞ´ñ\ÐIuŽÇ€ÆD{k®Ú‘†n_7ܽ¿înl^މªŠ’Sx?ÁÍ]nñ,±ÚªsfO ¢gnÄšªÔƘÂ[·£²3hð6*R¼ -ÓùüY¼€‘ŠñÂn;€vÒ±öá,^ F°£€‘% $÷;bÄÁ‡%~ÁâÀhkhO¬¨ik>´Uëñ8?sŒbà:íwÄý37j¯®a¦ÚlǶa…²¶S5‡Ì£ÞŒpvû´ç°£vŸ0_¿ò¦‚qì˽«îÇïÍé.‡û¼Cðîc¯y;ìAo’™Yf9°=t¶ÅÔ-í>ÃøÐV›M$g;öWt%³íg“–ỹ=¢ù±e£æVpòl;¨Ã9:š¼<1ªhÌØÄèââÑÏ5êyÅc£Ž˜¨ÓË[;ZZÀmmå-‰ƒ|MšKsW‘(vó .]?ëÞb¼èˆØ†Dó Ë¥W¥bíüo¨iŧ¶Œ7žÛœpB…m’¸is’u²î¸{ŽF£òþ«›‡ÅÖ%ÒZÖ7c_\zPâ‚×¢ŠyUÇsE=ÞLuy=¹²IcéÛ%ék^Fo~aï.¹îÜžÛÓ·‰ÜÎeã`Õàû€Ñöw‹¬tžS‚(l;ò½é>ÿÃè Uë/lAmöúµûØm¥Ø]H?«¾y“£iÅ|·_Åÿ¯`Sá³Yì¨7óÿ#ëÛNŸiˆ·}rÃÙümæÝý“×E¹é]ô|gCWž‚³7óNÆ©Ûêø]ûºÒÞÞkÀãúº»Ï7 öÛvf¤ºã̺’I„‘Èý ‚h7ùªóV$Í~ó–nÙAÂ~ó7pŠßì”5±%EcÌiCÀm;-†I§›BìöóV9‰}ÙjÂTÇGª#εw˜,hÉàÅØì?še'.\#ïn¯óØn7a ·ŒtÂ0som¨ AFÕš†–:ëÚ„¤PÛ=¸íÐ"Ÿ›Û!¹%:ß™¹Ì‡scÞ}Ób˜Žð÷OŒJø~°£§Ú.FJ»s_,Óûn/!ÃŽõ7™=ºV,#Ɔ6Ú„ÃúÝ ëÞh÷òãºØùC×Þc°={­FG-ñ{a?Ýyµ§;Ù,ÕRCÛäU=· ³m=eOÝ›§ê†±uñ¯ïïÁ"ªbÍ>Ç÷owE{õCõx$4ãfQw;ÂŒˆ·2 ]Äß y·,ìcö®3~ƒÍ/VH:oß 7 æÏÏ/w%¬"Ë´Ãðµ’1¶ SŸÚRà©óc\3…û¬°±./–L°f'Óy°YŽÙ ݰ8ÜÍü‡ÎíùZÚZrŽIŒÕrn·šAn[?þ·…ÝׂJÅ£7bi3Ÿñî“wë¹}ÕºË ±Q=yÒéQ¥æx.»cît,ýî’ßèÖã¾í=㿳›Âx,iG%HüwîŽÀ&à”mp,zv϶®g_$;À—§íwv€×uË2wwM=ûˆÓ¶K 7`{ÁXô½Œ=S¸ô7·î9&jéÍ•ä9wàûØBˆÍÂ9#˜‹¸Ï¦¯æ­º§Œ],™ WÔ7¾µ=…í~Ýðí¾aæý]ýä­b³“¼_ö‰¿s?Xöœ³¹köÙ !æ1 1o›ÛÀLÛgÈõwâ‘[åÕÆí3lø=ƒ‰!ñd;Ú»­Ÿpë$.yÚ ÖÒ»ìolíúAa÷^iüÙl»~Ûì,%/]ÈWwó([ ;°ßÑi œÙÜÁ]T{CóùÅLº‘™¼Q³©¹ÔŒk.o³¹Lï==·ý[°pË\JÞ¹w*S Á,¶‡ÒÍÀÌ1wÔî ·vfÅÏ ¦°Ã#¡äýïàóÌÖÌÈ7®`-·‹›eW=oç65¾+ßYsöoÆóFxiba ²¶¾ÜÍ’çP°³«3ÐÃã¹<:ÄÍÀêÖÚ1£ûöqô}5Ü3 ëCïeWßô^ó¿»÷·ŠDåzO¿=–Áv<YÛ1j «''›¤˜ºÄN²yÑå$û”ØcÝž ·ÍëV÷Ü–Þ9²Á}s.¶CŒ]nn”£™—±6/fç$cGÀpÓ~ùLÚöØÝÝMD„®fåVð¹xÓdù§¦ñ‡ò ´u×mµvÝBÝçÆWrã| 7·œ‚é¶ÿš4†Þ* ·ß‡›ãB¯Z{{Å?«'jñ}Vž}=t3çö÷¯j'·&ÊÕº¡Gé~¿k2f¥¶åb±ÿϰؿkba7|¡Ýf±_7_c±_ Åìbc±ÿOƒÅ~gwÅzìð¿;ü7a‡_;nE>Vùû$x[µØOߌÅþÙE[nÆÛÙ=Õ]ʶ’í‹è0qþòÕö Í4à ëÀoþv܉ßîÌàÀô΋ ›†€åš3ùâBì³ÀlLiÕöuršèö5–8¼ýロiŒ}hu”aþ_;ÌÖj4A0Ã¥M¶ßäÿck:zú/ÌÖ´¶”á»ÊRÇ~“ƒ­i0 Ö•Õö`]ysÂz .Ñý°<´ƒueæÎ[Wf6¼uezêmMÓGÃâåmMc_dŸ­iúëg>$¯…s‹×b ¸YÀ¾³ »a¯ŸœúXŸLì›úë{Mí´ ÖVþ¯Uo»/o¯±'³4úH°x >ð¯±ñµÏâ5½Ñ>hL‡‡’Zr^H·Ì[k  `½Ÿm Ö®3öÀ¼•hìõædÞê9áÐ÷æ´óÚ•»a½9í¾ëʉ-±Þœà›ÎœÌ¦a{r:¬Ô•ë±½9í=¤+'vÈzsÚûQWNlÐöæ´·º®œÆFbON{¯ÞÓàÌÞœ–£Ð•Ópû{rZŽQWNc/®'§åûuå¤9½9-³+§Ñ,èÉiy±]9¹öæ´¼ò®œÆŒ^ONk‡:ä´v®Á5uÖ–Çns€ë9xçs>Ý9xç-_³¿ê9ì^3u˜›]wóÎçà^]ÏÁ;Ÿƒ{u=‡åÛÚð,ê9xçzfn%õ¼ó9¸¡ÔsðÎ× Ï«žƒw>¸±žÃâI›^P=ï|8Eõ¼ó9à&ÕsðÎç€+ZÏÁ;Ÿnj=ï|c ©;ï|øŒõ¼ó9àôÖsXkê6GróÎçè±BnÞù=VÈÍ;Ÿ£Ç ¹yçsÀǯçàßð,ê9¬­u[šõ¼ó6¾ÙëÝ6¾+âæ³÷ºl|;óÌ%³½\:Ô½èOðfšÙgÀp“î%Y— $ƒŸâÇ—d~TìÒqå#KV Xþco Úþʲ·©#KYV9uŠ®¨7î6‰§"CŒª«¢]£ý× K‚Œœ5ÊZ’®î2/ªÿfÒ·ñFw½¯Õ-“Yθ4†(!–Ø(5b¿×ZVí{Ü$ÓÆ²”Ô$|¥{L“¬ª¶¦kû{ ËŸû†­f¬ÏßOÊßOó¯ËF?í[õ´Ÿ¬NiÞ›U¯peó³âºšŸÝ?m©z@³ìE‰ïÓ,룚¶þš`u¤¿¦O›¬?ÖÃ`Ï º’âÌ@ñ5…ÂÅž(t/Ûb-²©ë@‹¬® ¶ÈÖšºß"“„ê@˯û;‹)L:kàtÖA2ë¤i$ˬêì`]r4ýƒµyÕÙÁ2ѩΖaDÝ—ËH©XŽƒeÉQ¹‡ˆl ‹ÑYºÔ&¢ S߆È©ì¯ ‘õS]z‡ÈT«”Z¥„#ÞX«.m²gÖ*‹o µÊz›jo•8õ£UváÔÏ¡ºPk· ­Šû:´Êéêd}e»°AÎwQ, bÑÎ/ddl§6Ç‘`eopk³6Yùbl”-ò|gQ×n6·†ÒOLm ¥ŸLÿP™mÖ, SÏu¦Ëfa¸² A—܃6ÛpY¸Tï†/Ü6˜¾êØ6õ5Ãe`RuŽ¢ÐÿB êî™,•aª2¦ª:GЦ:GJ…B›s¤,Ý)ÿ(Y]S/GÉœæt?Ù™S=ûÉ žvÎ~²Z§ºFËR›vÃhYTÓŒž÷ktEÿæeÖ²~1kÆ g:kXïZgVÔ]/G›¡ÕÑší—ÑÚÚ/ûK½G(`1…ö×5K³´¿öŒ€Îþ²Î+VëþB!Ú+ûËt¤z²ÿOû{Âg=ar³ž°ó²žŒñ=£ ¡žŒÑ5@Ä“12L©ÞŒ‘µZÍÇ!õh¬.·š‹±KâÚÇb¤CYc—î¢Üaضv2s—&Êý»^¿¾aÒÇIëK=§n«òq²¾ªÊEPMæÒ5N:@V»4%èî¨I?PØIÓ| î42Aw n¥ºÕŽw¼}}3áÚTãµMUßA2 ¨-zŒ ª¾ƒeòN\ÞƒeàPSw°ŒüéÿÁL¦úÑæÐT"³lzˆì…iùxÿxš¿æ÷U¤ûÌÌ&{€Î(zŠ>«†ÏÝïç.ÇfÒë&Ô{̤ÓÑ+<.î³Ã(:»£fÞ5èXgf­ ôýƒ ô1ÁúØ`]faSèãúL #è‡mXk]6¨Sè蘆õÖ­1už™@ÇÈyÍúŸè`+ìÐZèÞ­}×G*Âj8}B“ôžÙ ÞúD««œÞ «v#[#5ξõÖ1Ûîm†Ë(^jÙ›r¥N̯{èÞÌ,ïÑË”:vEgZŒ4Ëbh½¡÷B tq¤Å¬íò¿öÖÝmubÖ´8vé<Œ¤/»éÀj9¦ü¬ tp™·{̬2÷LêØE§Þ ;àãM Ï Ú°@›™@·Ôïuõr•°6[©‹©ò&Й*oáyˆm!¦±ÕLºZèºÑºø>&Ðáš H›@hUóó¶Ü™NÌ€úéôVl™NoËÝ~áu¦Ó¢’6þ 3Po©wîTo÷9{Z­Y?ÔÌ×c9¶fЛÏà“ì ³MÌ Ìž³1² NF"{þ¯aìÊb†7{QY¶WöK²53¦Üj/0ôÌ.Ì^`ö³¿Ù lβ3ôÀÍ $:ÓYpö¦ºùqšôœ½©n¶öô¸N0 Þœ9{Ä›3g{sæÔŠ->¶ “îír3mÞ˜8“î‰ÓQl’I÷¶§ºîa3šûJÖO.Q5s©˜º¥Rû‚ýðëf€—רÎfŸþÿjŸ woµÛÚÛÃvvf3ÊÞ86—½Ì6ü]}¶á±ŸìMR£/éMRÿŒY†¶Ö 1 ãÉÂÆ†·U~Xïㆠêœpoù.óÇú:æŒáºŽq§Åú­µ‚ÍMÉO3†ž3[éXÖåŠcmÃcÚw»Ð~_JÛ%µ Ï­Ç[¼ÆÖ¶·xÍ}ÅÛ†÷®Ù ÞÀ5›Á¸f3x×loàÚÚ†'‹µ_MôÝO—?EØÅöØ“iÎlèÏ6<ÛÐ÷ž]é7›Ôo2ö¬ï[Ø÷ËÛî¦_Öè½íûÝ#JkÜÎ&Ø ³ ïm„[Ûð` ?[ ßGpIfýö>ÛðøÏlÃcÓ7³ ®ë­'›ï÷÷Y÷½åGo³ºß×g¾3Ÿ?ÌŒŸfÆ÷ÝÚ†ÇZð“5{+äÖ6<Á½ò{Ò–ÉuOÎí—ÿilNØü¾l–¶ù=`fÛÛ( XÛð ß 0„ï+ØÇÛ†ù¾:¾fü¶Y-·¦•Ù^ìfkì`­’˘¥«ÚÚpÖfKmÃÿ²ËŒ¹n.M{šËµ 6¸³Sl:çì›Î9;Ŧsܦüãrå·˜³Sl¶W/¿ÅìÎ1[Ì\Ê‹½®°µ ¯.ÄqxûÃnÒ¸?S¹± olg¶á1ª\³ #€Kƒ1|nŒ»‡1:ìnÆè°³ oŒ;ÛðÆè°³ oŒ;CšÆX·3¤iìv»îÆ{Zè.7egøÜ˜ìv†Ï±ngøÜëÎ ŸcHÖâ{Õc¬`»½k¬`g¶áÁn)JŒ¥Lf˜¬Šq"fQ"†fí½I½Âž°Ç7Æ:·· –Y·µSÛð¦6ìuµY´J#àeƒ@m·5°GœÎv´±BnkÃÊeº¯Mm W_1»‘0Z˕ϚÆ¡Û ·æ´}Œ‹œUS&'¦l±ŠllÃKâ¾×\Ý1¦Ä½½nîSƇÄU»] Öö¶áÖU‡Å[pW¶E|·Ù"nGš-âv¤·Ëœn·#Íq;2µgηa¹-‚& =`‹`Tü_¶¶s™c>V­Uv[èÝîJœ5Ûððök¶áU]Ç5Xµw؆‡=P³ /¾fCÍ6<‡šmxìùrS4¶ác]é…͵Þ›g]!†^ƒ5‡.SÌ®İNˆqÅó–ùâQ·í?6€‰1!oMÛ*‡…cQGn<Ü&ÏlÃÃ2ñ½sÊk/Àb5sïpHj/`cÕ^¥¥ê xyµp]j/`®ÔlÃï ¶á±eìmÃë³:]³ ¥cXÐÖ6<—Q¿ßàãûý†Î£· n£Ç}þ"ÄNƒuávF™Óÿ4³ X˜ÚÖ6¼·DN½hßùzQðû–rf^œžÔ6üK]E/ë³ ùrk •·/ì³ Ï5ÑW믉TË5Ñc®‰Þz;×DoéÝ_­ ÷ôÙ†÷ÅÔÅÕÑw—«£¯‘¾e¶á¯é³ #þ'5úžØZÔ=LD;cíWk€Z®´9ý–^`R–þƒbv˜iXbL5[Ûðˆ†!gmÃgì8ca:íÑÖ¸c½8؆ßáªÐ~zŒd± o ë ­a>žã4cÞ°úƒUxo«ðÞ>Vá½|¬Â{;øX…GâÔ[…Çø¸· ùqo>>&ÆzX…gÅ(«ð!÷Váã91ÖÃ*|<7FyÆ*ü²ß«ð§ÅÈÎX…?=ÆtÆ*´Áî΢9f°±h® k,šëî`,šëæ`,šk ‹æÚÌÆ¢¹‡±h.”j,š •‹æB*Æ¢¹Ð‹±h.Dc,š 勿B>Æ¢¹Ð±h.„d,š A‹æâð‹æBWÆ¢¹“±h®ëœ±h®‹±h®+ž±h®Ëž±h®kŸ±hŽ #Íu4Íu)4Í…ÎEs¡EcÑ\·pcÑ\÷mcÑ\÷kcÑ\7icÑ\7gcÑ\wdcÑ\7`cÑ\×dcÑ\WXcÑ\ÈÜX4F0Í…ŒEsacÑ\ÁX4F0Í…ŒEs9»]ûÞ`ì{ƒ°ï F@­Œ€}o0ö½ÁX4#À£#`ÑŒ€Es0ÍÅwv;ßÙíX|g·cñÝŽÅwv;ßÙí˜ÿf·cþ›ÝŽùov;æ¿Ùí˜ÿf·cþ›ÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|g·cñÝç•ÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|g·cñÝŽÅwv;ßÙíX|×n7ß¹ `ñ]»ÝX|×n7ßµÛÅwívcñ]»ÝX|×n7ßµÛÅwv;€šÝŽIpv»`ÎÜX|g·£îÂnÇâ;»ÓÝìvLŸ³Û1ZÎnÇâ;»‹ïìv,¾³Û1_ÎnÇâ;»‹ïìv,¾³Û1dÎnÇâ;»‹ïìv,¾³Û1iÎn‡MÌnÇâ;»‹ïìvŒ›³Û±øÎnÇâ;»‹ïìv,¾³Û±øÎnÇâ;»‹ïìvL}³Û±øÎnÇâ;»‹ïìvŒ~³Û±øÎnÇâ;»‹ïìv̳۱øÎnÇâ;»‹ïìv̳۱øÎnÇâ;»‹ïìvL“³Û±øÎnÇâ;»‹ïìv …³Û±øÎnÇâ;»‹ïìvÌ•³Û±øÎnÇâ;»‹ïìvLˆ³Û±øÎnÇâ;»‹ïìv,¾³Û±øÎnÇâ;»ÝZ|׿I®2‹ïp:ÙòðÙòÜ'Ùò\4Ùò°Ùò0ÙòÚðÎâ;û Æ©eþ¼;¾Ž˜ßà¸FÇüaŸÁ»±ßá˜zG2ÜF½Åwî—Þâ;l8oñ6œ·øÎ[|çÆé-¾Ã"Î,¾Ë¯¸©šNo¦Ùá²a`³á0Ú«°6v"Ö µø̤ÿôßáSz‹ïð ½Åw8ÜÂÙ ¿oÕ™x•Þâû©ŠY‹ï—ºë’ªÖ—Ü,¥Ýâ†í»kžnQÝBKÀv «÷ðE­Å÷ЭϺî[n³è-¾û.Ò-ß!ºõ¡[Ÿs}±Ý‚ÍÛ‚-„ šbÖâûå®[ꀾdïÖò;“ám[£bòbkÙbŠm};zZ/>§tLñA»¼EþQ‡áË ÝNiknÁÆ×–ú¨àKE-÷$YF¹¡{6Ôîײgn|X§•Ž…Éýrìðew¡Åé¼—ãg–Žéâ ù”d÷>e{é˜1ÅQîé|Ncè¿çš'uÄÿ°ÃâÂy´~Mc ¾õeϪ0’èÆŠª‚G ê{·ÛÁ³w|MÆ[Qñå´K¡²É|N…|Æ^ˆì)+¼'ïàSÞ“ßZ:fìh®<]Nh³Ó_9Ærîž- =¶-.^H…òy| Ÿ­–ŽÇhÝɧ¦ïWø”™ðS¶yT)~ž3£‚£$¹¬¡—E-=PãJ¥cŽÀym™OUWáSMmàSoå)æH±Ýf·C&ݧoDùWÕ DyŸt†›£üÊÜòŒrÏj©iÇ6ýtì“8Ó&Qþx³Ð~ÐJ0)ðÈ£‡Ê`wkõ™Š*ûh4‹ë;ˆ¬Ç xù d”Yô~6664ŸåDèRÜ—Hà•÷¸Di*$b*ºˆÈŸ´\áGªæ¢8t#!ÍB‰Áy'ºlq ^\{"‹¸‰iЊ;ëÑ2Œø;øÌHÎ'ê=ºÎbŽÉql¯'#œÑùË0í–yžHQªíÄÒ±£˜Â“øœÉYû;! ïpƒ²”„ròl}<ä]¡˜*Ë~Öl~×à˜Bv³Õ"íï9úÖb<š¼QîkJÇjý ÀÛ‘0~¤rÿÿÃ!˜ôï‹Ã˜Ÿ†üûr·â_¹ óývnžäª|‚3 wáî£Çÿ2¸ÿ¸íüâˆÒ±2ù(ŸjÐD>EøúŽa˪ÇýIdÕ™ê0>xȱˆ4±{ïÿÿ]ñ÷d…IéØ ÅÛë[Gûßñÿˆoýï8çÜ´ø y‘ÒJ›”/ù­ÏÏA«¯y¿L|Ã6ÙœèG[•zâwß#!”LÔ"*öü^O)þþ=ÂQÅCÐ;ë£Àê¿DI‘þÖo`ñ’|¤5_ÿ%¤5˲£g>‹¦µ«Ë.¯ºgò–‘úl”@$ë“#öÝre!LYMò$†‚`µƒïu.n£(Lâ~ÈS6Kä]m¹¢¯‘ãï#ALâf´][äöC5äkDê{—Š«ñb*„²åPùL×3¿¤dÕè¡}eó#zLþ¡rÈ…û/¹nª®@9;Ú·]úoÊN£%ù®2ªËV"ƒ/_W ªÔ2½…ýc›ýÂf—œÇý¼š:Ðm¦ŽýK&6¦‘„lõ|U¸b¦˜±4åØ¥Ê€ Fò‘?„4®¨æžÊ¹ é81Ë´M&IJ•˜ä}‡³]+21ľc§xÃ’ÿó·ekdRzÉø>3íJÁ!—4î¤föãÅ­I™­4ouä­&hRsk²%ÕÚa43žF ’ØÔ,‘—“åØvÕ¤æz$6DÏùoÉg,¹XV“LÄ2ï5XÇG³ÅÈÙ`1zQ´˜/®^$D©WÀ/vg˜ì­Ù±ÖÌÕÄ‹+æÌ@¢yâÝöázòJJxâÅåóæÍeKöÖØ±¯&^\Y6§bZ4O3A?´ L%I<1¶KÒÕCòûR§ï¡ .Fßü<ÚÜv®0’€l'F NkFxSòsÁÊ•¤‘KÇ:¯ÝÆ7©1ê}Â\Œ•Ê;êŽÆ.ŠË)Ùac¢K[´t,ö¶ùw9ÿX‰å@ÜKR’`.»Ý*FÊ2jš–´ÑÏÆ0¹,ÙæÒ±ÂæqêüŠØj·LwÓ’K’µ©¥ÍœrÖxS¼H¡cØAB£¥c™àq=·xÓÊÛßÝŽ²ÆvUvFº1¬¼mUö ‰Ž/ fhç"P<ÑcLÉÊ$½1©íß¶ƒ—0Ü~n4«äÓîüb4}BVTŒÏe¹3/æ<)áÑ%Ìã¶ÕÑtÌ­/ f„ÛÍm[x?óë!‡­KbÍþÍŽ=¢×©«{–ÑËmƒFlú1S¸mÄb3‡‹ÁZü¡¾®“ë©å0GUC¡f«È>Àè"¨² 5fÈ×!w$íAL…Zs±Ì~‹Å0áâ m³7œS³w¼ñn̹xãʆof×ÙYSͨ(F]fZ £.Þ7F]6…w;,¶¹Ùbšìèêã‹!ï"ƒïÍv#…ïÕª2ºœæŽKÌÀ0¶S:M/_#ï]Î-fv¢ò—¸=…D¼žbOaàÕ™–¶ÝSQâ¨ÏDOñ&ü½±z³“$Æ}Õú_rçW!MvE”O‘ËÎÞ7*à{$ßøn¹d_Ìòª97¼#Úå’S¢¨kB ²Ç+¢ÊÃ×î›uÓÚwdÇøo\RûÞ—œ’u÷%WdýT.ønÝ7ë®3ß‘½û™WdïÍû»Kjß­=%W&•KU®ÈU^½{¥Þ‘ÿñ'ó»2£q€ß+º~nìÚÜ–Ž–øÈ¸YZB·noóˆŒy6à¾Îylu­ÙN;È™S·&kÈoúMHïìÅ s)h®Œ­_™}º0ƒŒ··h¿Vñ ±ÙìÖ£º£naÞbbÚn—°ºÉ% ÂüS늷1ÃJÖo|·kó»q¼k|÷fÞMØœ¯¸9_²9_\‚xyw¾ú;òÝ¿¹¾ê}'£ý;ª¢¼¬åÛåØDŽm}¹õ½sŸœ™Ýûä$ˆk“¡ã[÷Éng¯4–ÔæFkOÎnaÏ‘¿ƒÿfwã–=f­e{`xÿ~É ‹Ç,a×1 xd„íDª=!¶Ôbì–s2¦Ý£Åö1ïuƒxƒðļAcbÞ <±»BÌãbÞ ¼b©AbBÌû&æMÊÛš15_jû7û2q.Ëܾēߗ˜JA>_·Ô‘g˜Ï6XůîÈyë£ák¿uñ›ðÊÎOeÍ,áú±s¿¬Y%Ý|¿)«’yŽ×®ÊªâÿÙ¼¿ÛÞ†·ŸåÍçøÏÚUì…ï˜ÑÞI`?ã;•»0ÙÚœlÌLz÷œ3Û­až`cξc6¢Kƒ9mæÁß.X!Óc‹oûÿÔUï 7ÐxNÂT6jóÈ?Ú=¸íPyœpuPuÈbÃ#u HÚ]‡ïÂëГe‡=u8!/k^–á½Ìa›é‹~ôfLÅšZ00!6"·§˜mõ5taM"eÍõ}@SGÁßÿ§Ž8¸ã0gù£š79¡ºâˆdêA-‹fè4ÝF§*.éô{H3j,NhÛìÿSí¡­î¹ÆöÐ*oJ;¦ÂíGû(.9½;5¶vîµ’›ÈT™‹7¦”…£S,¡®ÕtS‰¸©œÆ'šªöÕQI¿Éø®aÎê¨êT®líÏÞ¥§êYÑ!]«.ë5·>Ù×òx2¢ ØÙê‰ò·u½)»°ë–`t!íñó÷Z‰ÙpSS;†«éŠß\Zyʵ?(Á5E&ØoVmiNßcíðvÌl£‡³1üΆ¶¥vðÍìç]ÚÏïg&«ûÙXÖ•5ôvT݈Vâ€ÛÉì#âŠéoDà~#â^äoêŽ0™}Ç.^dï0Päñ†½¹yŒl±|ì\/"ßÎïfËÁ>ýLÈñÙã^‹aÃã刽oåˆ}?°±ÊjÒÆ!ß6ÃXëê¼aÜ­s¸Ãȵ·Ý[2¦¡#YâÒ¿Àâ–òA3ÒÅèТ—vH/w=̆éâo)r)šb¯¤rsŽÿájÂb„,°]ÑG‚iæÉ‘ÆnÇ>#Ò¦7Îl4–<öš%¶yŒYb,{xCÏØöØ›“YêÌIOö`¶·¾Óš½ÕÍÞòÎÂeßÕsðÎç`ÕsðÎç`2ê9ÌÄ8ƒºlŽz³Q\t´žÃtÚÕñˆya›ã£Ä6;½žƒw¾ÆŽXwÞù ^=ï|­Ütê9xçëà>]ÏÁ;Ÿƒ»u=ï|­à“zÞùÜê9x猛]Òm¸ cÎ$Ó¿’®;š²&ûíØ›R沬DÉLEæ/µ=**Nÿ+2¨'ŽUEvC„"*²¥Íß Ë“Œ•` £‡ °9Õ ºÄ&j‰9Yæh=áÂF™ÏÑöo”yål”Y,•eÂH¤…F™Ò*f‰šÌÈiÓHÇáÁ,[fÑ»lÆá(aÎÑF L£tCq6ŠyZl‚b¥ÊÞÍ̯Eµ`˜ã˜Êßò˸î!wº¬Æ|TjqÕLVj)óR˜Émô¶ê6¦éjUO$Š=TÆ›TÕP™Y“ˆÇ0ínA£aâY ³ ×ôÈþËpõ«¸`ÝÓ†këž1\Æ·4EÙ8ê.+Hâ/ ç Ó2B»@}A×\#d G8fµ`9gäkãnŽ|­ÛÙf OÎX•ë­ M#ý%{šÎQoóï/› ÞN«Þ‘cŒ&\çÙ1ÂLêßX‘ùÔã±²a"nÙXaRað±²<¦žŒ•ÝY+†ú9VyÕã6þGÌC›fBܨ6Ù>btU#†éÆÉÆŽæd3„M§q²ù¤i'ûMªwua?iœì$i Þk¦Àv?½;à㎅½(k˜i5ÒRɘÓÎrsa¬Ëš(Ìc]ÖDá‡`]ÖFa—Ô¶¦âl† †pmƒ%æ[–ƹE6ª1"‹y—O ùaDÖËs`KŒ™É^° ÀGÙ pHf7” ŽÌ°'L5¬ª`(ÖÚ—=$Ø—•ùÄÔ¾ì¡Á¾ìÄ`_vRŸ}Y6æ­}Ù)Á¾ìáÁ¾,& ½…Llföe±®R³/û—Á¾,\±/híËÒE̲>RXÇq±6b½‘H¶°·/‹Xj•b&ÑÛtĪ·/‹Õ@oÓ‘­ã ²bÊÏÛ&•qÔ6)XÏÛ—Å\«·/‹-?ÈÛXÄ–1êÁ–1rqÁ%rÁ–1kö^3˦i¼)Vk-3šÞÞª}Eךý@ŒàÔ^`!«–4á7‡}µÍZV i*2›|p·A}ÓkìðùyôvødКy5$Ì­}Á[we<óZ0##ËN*™ ‡ƒìMvb9ÎoGp§·?‰í4oˆ›áäà?¶ÄùfŸccÜ›#Å:<1þÃÚå››©‘ÉÇõAÈĸh@Ç&S€í4¦}í4?wØNcâÀ÷O±YÃÂÜSã)…›óê—™sâYàS$ÛiªM‘l§©VŒ4{æÄØïþˆ@¿ÄÀØN#Þ€1M |‚]bà™µñ›‘E*€q%c5ûΡVÃPvxóI‘ì¨iÞ1š5„ ¾(3»¯3Ë2ì¬×²mkÖkk/0Úɶ­Y¯­™¨ÅÌOͰ-ö‡j¦1M”¿¥¿alÙÔØïo¤-ÖbÿÉûÅP 7ö‹q?ª¡6Ð=÷ v3û°iÄnfžýu n ln#ØëËŒý~ÆÕþ[®^¬¯bÐûÅäŸ7ö‹Õ=oì÷ÅÖ[†é%ik¸Tñëýê^ÔaìƒkÒÆ~±^HÕü°úçýrñð¸Å^o,nñ¶ÿ˜½W›Ý pËk\­ÞØïgÍè.õb” ³Ö¦®1aíêåãm‘²ï¼-R¬Hz›ºX”ôö±.éñ–&½åKì2y›º25•š{å2âû†1Oß7Ìwz›º$²6u1š„AÔ_ŒmÌEºˆH±%v–”±%:Ö[rl+lɱ[°%bã.ÂΖè[r Clɱ)°%"Ä–h[r Alɱ=°%‡5;õs˜‘ÂÆf¤ ÖœlLaFÊX¬ÔœÓ•šxcâO“i üiëó~ÚJƸŸ¶–1í§Ýf ûi{³~Ú(ؘÃ~-w¬×ƒ~Ø’%q!aKt„-9‘1ã§olɈ°%–H[rܤ@…Ç–&=A3îSb¶[r lÉqãŽÒáÆÊÁ–[r îS lÉj°%¢Á–h[rèÖ[[r lɱٰ%[r`QlÉD±% Å–&›°%w[r\U±%ÇM [rÜʱ%[rX™Â–×]lÉauŒå‹Õ1Œ9VÇPÁê·Cø&h‚` d‡5,:àž ±Õ1ä1à±€ÒઠLÕ1lÉau [rXÖ lÉÉêÖÓ±1‡yWlÌaº”»†K±1‡ÙRlÌa´s˜,ÅÆœ±ò'«cÜ9±1‡=WlÌÅâÌÙ`Ësܱ1‡‘RlÌa¢s±lÉ -pmÆÆ¦R±1‡¥TlÌa'sܱ1‡TlÌŲ%‡ñClÉ 7pÆÆ–U±1Ë–·ElÉaà[r˜7Å–œ‚±ˆylÉa…[rXÅ–Æ`±%'4`,bì[rBÆr f\±%'}c9­P_1ÅŠ-9Y3–¹cKŽ(¶ä°:ˆ-9¬bK«ƒØ’Ãê ¶ä°:ˆ-90¶äÀpÎÁØ’S`KL-90¶äÀÐxÀØ’S`KL-90¶äÀØ’S`KLÁ L-90¶äÀØ’SpÏS`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S@S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL³L-90œD0¶äÀØ’SÀµS`KLÁ®S°«Áìj0»LÁ®S°«Áìj0»LÁ®S°«Áìj0»LÁ®S°«Áìj0»LÁ®S°«Áìj0»LÁ®S`KLÁ]L-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀØ’S`KL-90¶äÀhé€)°%¦À–˜[r` lÉ)°%¦À–˜[r` lÉ)°%¦€W ¦À–˜[r` lÉ)°%¦À–˜[r` lÉ)°%¦À–˜[r` lÉ)°%¦À–˜[r` lÉ)°¦ÀŒ˜3r` ÌÈ)0#¦ÀŒœµ1Ç–ÿtlcŽm.ÜžØòܦØòÜ®Øò\¸ØòÜØòÜ•¬9e5†´­Íí÷¤­mëµÛ7ì%ccÎX3uv¸ÙúÞÆ›ßÛ˜cû{s ocCæâç!sÌlÌÝiUÓédŒÁ±Ë°˜32Ï.wÆà@GÜM¹èCÖ3ÒqYu6æ ÅÙ˜7xs±L¿Q ;á‹fi•ùç’ëlÌŲ6­ùv6æ>ê®_ªÚ‹&f»eíSÛnÁ9 [0è÷CÛ-0–ꌹj·¾`öVé gc.í"Ýò¢[˜«ó݂עcºõ3<ÍÂöª6•³1÷1×-uÀعÎlÌÝlÌ} ؘ{¸¤¾ÏÌšÓCð*œciÎÜ£½ÙäodŒbDzÁêŒbÇwdŒbÇwfŒbÇâY£ØÔ¥Íe̽KsÕÙøC³ 2à.î,Í™»¸³4g¦ÚYš‹ÄTQ—è{:á qî♥9k’ô“C$`ã³,úG‰¿šq(}ɵËÔ@ªò\Ti·¨@¹ÃañÅ”.0t‚¦]{Äh¯·nç¸È°­*]7/]éôå $ ÓÖ“[¤õKAUO¯M55ikv¢ÜW³IŽŒò%׉µânHXëíJÚ»…•R Œ•¸Õ4I"N2´=¥KÊv_S: ˆZÇé¾Jò÷Aj¼ù¾Ã›ÏZl*‚’ÐHô|Ü‚Du÷º¯¨–1Ñ ý%]"a–^mé´<,ÛÐQÒþ(tëiÝÄÝÎ&èW®šÜQÏl´^ÎAw$AQiêWãPôi–"ôNúI1Gÿñû±£ž3¶;êùÌ¿;êsûP Žzú=g›£ž4oÝQÛí¨Ç¼íóÀQ©ýÈæ¨Gœ(0øÊiUófUKÞ0w×3ÐÜõøËgVÌa¦9Ðwm27=>Çq’~Ìôð'=é{$!s÷<¼Ç=Oú©H÷]aÞK({H{v,凜½GZÒ½GÓ˜÷ZÌÙ{$'Ý{ô2y/5³ì=R”î=úÚ¼—êYö¾=š¼ÖÞ£¸Í{á§ìýìhéD{Zf¿X…=ŸQiÝ{4:y/…¦ü½ȽGž÷ReËßOžmïqžÀKq©6ÇùžA1œ9–Ò[ÇŸ°èƒеv³:Ä6×qZ4ƒ.½Éò Í^ŽHóèaÓ¸¨Eá°HŠsiÚµ5n¯é´hš“CêtÕjÛÀ§Z´œcÍÜ,‡Ž?_µ÷h¯ò^Oé{Ô>}¤|fÞK/ëiôÉ;p,aÞ£‰Ì{)J¥ï{ómTÞKi/}j¨/5ó^\ÙlFŸÜë.{þ7ï¥×•¾×f€wÛ$Å5ó^Ú^éû%Ñ'ö®²÷è±ò^:`é{TI}ýRh3稜¾?Q^Ü{)·™÷ÒKߣbêßKÑͼdz˜¿4Ú³—@æ=°¼—îYúþäèÇ×7Ú{à=稜킼>”ay/µô½°QÁ¿G1–÷Ò[Kß/‹>±wp‚’,ï¥Ë–¾?-úä¤éö˜Á{é·¥ïµ?ò» ˜Á{é¼e{/º£t”½fð^Úné{ÎR\Ìà½4àÒ÷ÆN˜{Ìà½.é{)D¦ýfð^Ê\é{)GÞßcï¼—NWúõWŸ%\ÞK3.}*¬B.ï¥=—¾G-Ö¿G9—÷Ò£KßOP?qïQÔå½´ÁÒ÷Ì”ÏÒ.ï¥y–¾g¦ü{xy/ݵôýŒ¨m‰Ÿ/”yy/mµô=3åó£ØË{©Á¥ïg1~>Pòå½ÔãÒ÷bÁ¤ó‰Â/ï¥×–¾g¦|}`ÞKÃ-}/‰™4?p›÷Ò:Kß3S>?Xì%M¶lÿÃxrïÁ`é´eûe™nÄY¨ ·ÆúmYju‘—Ånj‘jlÈúHkAɉ{ŒfC³2}”¾©CSr˜‘üGË¢'ûAʵ!‡&.»· >˜Ò×ÜÝ7%J{‚‚8³)UÜÇ­’ q¡&Tt«³b×É´1¾ÈÙ'RÝ yfù÷(“sƒ“:o†Ó—EI¿+P,'¿T|³•ÏJæ¼—Úou'û÷Ü™ øk˜$ÇÆ™“rHA¸¶€.Êèì© ‡'/@ìiÙ¬ãqöcó œÎ\h3Wçâ„ã* ŽfXeuú"îBšGüsÂõ9P]'‡”«9NF÷9Œ›*åJr†£þqïñ¸ÃÜKM¹z«5 þTŠ×á/Gê˵[ä±Z&s·PÌŠÔšsœa!PpŬHÙ¹šClÒ³Ä9? uùD-R‚®æY^5·²×Í9¤]Í!ÆôRŸƒ 9½“Ât­ŽÅeó y§; ~»Tü‰Z_—Æx8-¢^©WWs „“#0€”®3ürêB‰7<ÜŸöNJÙ¦/RÆîȳ°l–ñȃW æEJÚy–Ï*/¯Œ|ÿôÞäQ¾Ž<æ+­GõšºUGž³ÊŽqXïbÇSPÿâëÉ£~–œCœ¾Ë~ŽO‚Bûg-†jûg,†’ûÝCÝýSCñý.‹¡§ÅP†¿#ãà(¾<ã.I.ÏRIñG3n‘âK2®â‹3ÎŽâ‹,†JýMC¹~—ÅP³¿Ñb(ÜßqsŸe1”ðwfœ ÅgX ÅüCEÿ‹¡¬¿Íb¨íoµ ü—[ Uþ-C©“ÅPïß`1ý×Y •ÿ5Cù•ÅppŽÅpp¶Åp °Âb8 Xf1Ü,µŽ–X ‹,†3ùíÀ<‹á` Ýb¸˜i1œLµî&[ G,†K‚ñÃ9A›ÅpS0Úb8,a1\´Z '-Ãç5áØÀóšpqàyM8;ð; hù-‹qÛü¦Å¸…~ÝbœÕîµ·Ö¯XŒûì—-¬ùRpñtÅ€YŸ³7e¿ÿ¸?ûýÇ­Úï?îÚ~ÿq÷û{¹ßÜÖýþãï÷7{¿ÿ¸EûýÀï?nÜ~ÿÁ1ðû>‚ßÜÙýþƒçà÷÷{¿ÿ¸õûý×Âï?x~ÿÁáðû¾‡ßpCüþƒGâ÷œ¿ÿà§øý—Åï?x/~ÿÁ‘ñû>ßpoüþƒ§ã÷œ¿ÿàÿøýWÈï?¸E~ÿÁEòûî’ßðüþƒå÷|*¿ÿà^ùýOËï?8]~ÿÁÿòû®˜ßðÊüþûý_Íï?¸m~ÿÁƒóûΜßðëüþ3î­\ÌøRsXmxø‡Â$-{#Žhv™¹ÌDCž[Šæ£e¯~÷{wL‚¡•:!j ÞÌÂ%Öî‡LÞæ.Éz\ì-‹vC½C°ÓFÁK½0¹² }d±•K2´í½3AzæK¢5/÷zýÅ·D{˜w%"ãþÄs|a·›ê‹ê‰q=Ãܧ‰CRs]æúî]—1Š1B¦Æ›tÿáW —´üU¯»ÉtFœ3» l¹¦[‚óÌÑÞ9c˜•û2'jÀ­ïÀé¢P¯{åMãpH×Òû†Xç<á2²:S–|›)¬Ò>0Sxð®ÅÓI]á÷¿Êf? ŽÔnÑÂq³Á xW¢øX`t 4zÀíeêôR×ô¹Tî‰Þ8èâ“ù]âoçz½íSÙëº/ˆ ®÷8¬¬ö߬ áø‹Dp>)n|ÇÈ™ìÂÚjGuv{ ~¯àÀÏî–Ù<àºf÷<°àÝ<0~ðÆi[¿A·¯Ë‰2:^\…;,@ýŠœü)ƒ®åFG‰¢†¶¸kKéÊØœ:TÄwøKüçÁ—¹]¢Ùﮩ9ÚékñýEg—v¼si݆âa¢hõà_‚û°ÆàôºŸÛ»¹lòsèöX³j¾Ø£NèæEÏê­•qC5÷=ÀOE³ÍÞ)œ#:\Óìž7x ~Þè—Ç2x¡hËèŽ2ä]æÎðܶ¶d«”$Ú8¸íç«póăëvò9ñLÁ½Uk`È»jS-+[û™Í‚KÛ}¼TÀÐÈyW<ƒSjk£¿ó3ƒË¼Uèþ1ä]½3³ VH;R3ÓâœÊ}óIlÞ­ÝÂ+ºó§tåE@Äêù¸ülï{¹dm.YÜÓC ×ßx>7ìÍ&þî­m¹{;ž#öÕ)­Ÿr³«\[ów/¥¦6çfR9éÛ6PQûMÑÙiÜ¡Ggü+Ñ3öFé„<;…u3áé~Å{Fs˜÷!ÖbÞ+±E!¶%Ķ†ØµVŸî꺅Ø»à‹1ãwZŒYöN3ñ¿q·íœSuìf:Ý3šñtÏà ã@önqCÑÚg´i¡µ\71‘ìlqbömcp.¹¡£ Ï÷Æ œ}Ýí†^ßÖ‚¾FVî®Ð1Г¡×ã¿áÒV®‡NÇ/Xèhï ½¾½f‰Ï‰÷ö’FlèõKÐØÜXÓ¶,ÃÛ—\)MõÐëkp—°¥5Õ²,™æà“ ì¯[àÐë›Sèþ —¹·¸ðØÄ[M}WÏm«mhH$Ñ‘V‰QÚÚâõz^±-‰¦Ž¶öÄ’dB64Rñ?—$NÄ´ååØž¼¸×”k©ú„›‚ÉôtrÜóÉ® n¯Š·žè6¬Ùzý—»ß^'·©s¹ôÌåò6æÅ\cÞ½ªÙkqV‰öY;¥Ø‹í5Y%à—ûK¸ “í×øjåà-Îwù6Xt[Ïå“Höz9ˆÔ;Õ0©x½h?¼Ê‘îËsc×”Ô€#]î Ïj·f;ÕÔ½bMVTÂ^?D{]±9ML&\ h!6{-—'åþºj ÷S£r¨ïm–ãîí9š,Ç-ÊÜç9-ÇŽíuœc9ÖlÏqˆå˜¿-‡ÈJ6‡½9ü!ÇÁ©ëLnß›¥hXŒS’e%ûg/ÞæèWN_Ë`‡«=(=mô KÌrÚ?Ëjù[/œjñ»|À†žbó càžÅßUÀªÞ+x»÷ï^k1\¶x÷¾ä¸-Ôp˧¬8õñ®XqÙãod8÷ñî}y×nuàäÇ;dåwï–•wÛìNv…w7Ù;œÿÜÞÝeïpôåLÏâfzßžékn‰w©Éî†Çp¹ÒéÒu[pŒ÷3UðÁ2¬"^Â~¯žVÓìL3·¨¸ävQ?h9qoGNñö{u|jÉÒ€g¨á\÷ž£Áax>Ã-‹pþ~¯ÎÕ‚ö µˆóÕo\¯vÕïsâ ÷vâFì÷jy$K•¦»$ÕäÒå=F½OrâOì÷jÉ<©gG¹^M8¸î°‘ Ì7,_ÙÔû€´£®™ÀâÂæÞ·¾&<¹LMâaì÷ê4¸»´ùÄæÔŠfD!neðÍ5ÄåÆiÎ¥ÅÛèν¬I7Û¤#f3»¼xb›H^q<²Y1¦ÒåáÄ»_•¬˜ŸACkÁÚåÇ Ü2ñBìÜiT— ¿çÉ.Hz{ÃÅ8Ù8û½Ú9f}sÏ×bìø­Ê‰Ü ç€uç°ÝêN©ÛÙ1r½œNœçñIpœª›È|\þNÁŹ7‡©'¸®+dláŸòu¿1¸ zUvgɹYà£-8²¾<ƒSãÅr¤ÊûàîÚ¾‰3o”k(fìÓ¯s£Î °_ýû9 „WÞ .t«ý\êÕÕ¤ýæ¬Î :¯Ú?jŸP×M¾y{ÈJÖý=ÎÍ59Å&¶ø-ëÃI@³yÏîÏ#F±Ãy!O[wG´÷º7’C÷¬¹‰ñþíNÞm{÷s¡nY¦ç4ÙÌ!y‡F‰ª(1~ÕYE½ñ­µÙ…gâV[N³· ¼ÛyîF;Þ¼ò»ÑÎë:èn·ò»×ø™Üõ±(‘žÓïoËʹ´dÿœKœXíš*æD‘If=¢C¹GëËa)v¥w˾õ.`ÙÛƒ‚ ¼ckð¨wàŠß¼v{>òì¸ÂÞ<åÝå†ÉÀ9ר;Ü!î°|àÉç‚en‹ß2Ç햃۴LjàµÏY’8±ÄÄËJoîâ€Ùwx7ZpdÞ'qä²wÞM2ï\oŒ4ßÞ}Îú$ìÌÌô)1'Ý8EKN0®ðv:qç­7p¸.€Ã¦BEðì+p·­¬qU-öÈÜØ1ïd9¥ÞúÎ[‹úï!Í ?“;…7£'݈²¢tyGîvÞ³¹CÝ­Ç¿8Ì–¿½ E@8yÜÙ2ßi®@S h÷öYÈ Ë͉x¹)Âxct³ï©ógÆi¶™‡Óp­NoüÕB‚S;.Ý™@.rõ²d›CˆjƒzÆŽLÛ×eô$p»ɤx{65ûÆ”Kº·*naø %$ŽÚø>§á‹ÓŽâ7Á¹àŸv.¾»öÕÎ7ó6¿ûÑÞ]§.ì>=Ú¹+/¡{øxíû³þɽ·;^ü³n:Ða½™0©Lö±høÂ[r§tåF¥ºVyP7ó‡¸:7EûÕã|¿ûÝ㙺gÇ;L`fÌï3ªXfï˜wË1ïœË^œÂížßÏd¸ÏÞÀ™±>V£g¼¢¼Éi1˜}¡=,T:ðŸÊÝ­úÑöÐõ]oŒƒä„÷½nÝ,7È 9½ƒäDz½9íÎèʉvEoN‹Sºr’®7§Å¦]9Ñ´èÉé°~WNô-zsÂù«çS÷æ´œÁ®œì‚Þœ–wÙ•“™íÍiy¬!§uvLκ#cÞ9ׯ¦9ŒíÓÜ­³Á Ýu˜w>˜£žƒw>x¥žƒw>·žƒw>ø¸žƒw®¯æÖQï=ï\ææ\ÏÁ;Ÿƒ[]=ï|nxõ¼ó9¸íÕsðÎçàæWÏÁ;Ÿƒ›\=ï|îyõ¼ó9¸ÖsðÎçà¾XÏÁ;Ÿ>Y=ï|øhõ¼ó9à´ÕsðÎç€WÏÁ;Ÿ¾]=ï|øzõ¼ó9àÕsðÎç€sXÏÁ;ŸŽb=ï|8õ¼óû WÏÁ;Ÿf=ï|¸Ðõ¼óý€‡_ÏÁ;çäÚàŒn'×eñ¢©¥K/Ü9Gn‘šÎ¥a0‹×2/V€nyµË€ç¿ Íá²ÏˆƒqaôÿàD·ˆW%ÊP‹|«ŠA{Æ zN©¿éA"ˆã0H8šŒ¸[²t›e¾×õ+Ë ’øÑgY®ƒÅBV¾Áû+õ.g£g\gÌþ³¿!ot9ÔÇ!ò3«ÎygœkÈ;]õ8J´NŸ©_‰Öˬ¸ ®ÃQ×7÷wu³UÚÒ$iÕD‰wÓ*DÝ@Z…ï4‘­r+Í›¡â»Š¿?Tù„‡ ÿjÿ ýr\ÿÐtõã+7«G…¶~ù¢µõ“æ‰îsä½&-‘aèpQï0i'èÂ3LûJzÃÄñÒ=a¸44Ä.*¾8;ÃÅ™S®ÒTQ·‘àŽ?Bš5´·£êï¹øÔœŒ`o·Ø¸ÁT®‘rG©>”‹HÕ9RÚ/º‰Œ¤>\[Ž”SÕ;R®E¥)9R¼Õ;Rœ6õ{”ø £èŽ1Gñç–ûqÿÂ!å~è”àtr¿iñ\ìƒDmÁýáenè'~—í”À(@ÚÝFÑy/™V¦]wãTѾe›àWÑϳ¼µ*Ó3Ò.«¿Fô銟³æ·Ÿ°ˆfm´nÐàehÖFën¯Þï¯ÙÑúÝ_ŽêùþÒ½P_Çh’Å]£Îéþ0F÷#q4ƨ~aır„©ž•VŽº4VZ]š±6vÎDÛœö¾5Ë8ñl£8îlc^˜±qÒ5Òö']%í”q¼Á‘å89ûÔL ¦š±Àøõ=þ$ôà@4‡vÄ­ñlØêÔJ² ŠNJ¶qñ¿ ä°óƒ NøÕ§§Ýãp1ó³ûoE°Aʤ.Ê„¢”_pyQBEô4E; ÍMùü°[$ÖUüTE¹³Å»kêM£üþ;P•ifÆÓpÈxéøhÇKÃOýv{püûâÿ¬ú€ÿW×G寬ÑhÏQÅxqz´£’v öêAº ª®ƒÄ]×줽©™®~^ªÕÓe|Êâëݬîž÷ø§Š†ñŽBOÍ?¸±ÒŸ¾!15ÿ൸²¬½`‡×^€1j/@$µ –Ú psí¨¢ö¾2ì¶ì[¨öîWí¨·Ö{¶K­÷\tØdÙ î7Þ·}\rÛÜoj/Ø 8È^p›©½`ƒÖ^€kk/À½µ`­Ú .(µp¸k/¸úÔ^p㩽!×^ ƒR{ò¯½à2P{Á¤özíW‚Ú 8µ0j/¸s×^pu¨½À#ií…Ú ¸µ\…j/¸×^ JT{fQíŠFµèÕ^pE¯½@ ªöÄ\{Á£ö§§µèRÕ^ `UÛ‚Üãk» Å&{_ÓZ0mmw‚]k9@ºµÝ &­e•êvG­¸’­eå’âÎ^àH¶V+ø¯ö'©µ:¤zÝ‘C×ÓÀõÄœ½@Kª–UJÕ•á3»–¼Zë4W¼Ú lsWÈ^ào»ÖÜo× Þ¸kÕ㜻V¾ºÑlË^ົ–OÞµÊpì]›Eü|×rp¥«¡Ýs:ràÑ¿6 ø™E7.{ãÿZ¥¡ÜñB¶ŽùC¼ùáX¼–oãµ8¯õƒ›f­‹R4î˜ü×úÃ’ZÒ$îx!âŽêñ•^ë½./¸ÅÔúÁµ²Ö<¢×rà ½öwéµÊ¸¸×¦“{k-+,“ÚÜíÜê £º[}aôz«/ŒÒoõÚ©àÓìÞÀ%¾6FÛØå°wîÞ™w´.Ðwf®‹îæñ*ÌvÁÖäÞòjl$ïg±×`55 b7 âÁŒØk±¨Ìõì~W ×u6Tƒ«øFjÙßò¼kʰ}‰±ù¸ƒ½H¬äºƒä†±èl_éų\ì™®:xrì’%n6Ø3ž[põ‘Š^g}àîɦ:f€-MŒ½óÓV+Õé}rïwÞ»÷ô¾Ï;1ïºmÜÑìFsó‹qÝý‹¡õù³ã¢ùn‹Yó—¹¹PçõµÉÅžç¾tMK×Ë­­¾àjC:ÇõlOÏEÀY=sÏtì´k&¸Õå¶ãù›êÏÇõÑHø0s\ÿWûå®^8ŠìM븞ê׳q½ãú—Úb¯u0]äGW„Úâòd·ÚìŠË;{µµùý­W;Nù7º^\äj³È~ïr½ÈºÃï6—ÉN1H„Óæ2£ûž]ù¨èB÷n«û‚ÙÀ´g»îBm·³jˆ |xnÙ f¢v'D¬v·Dí®v·DR­V®jè/µ+%„Uæ9ëèJsŸÌk´~™ˆ,Š¿µðfá^f/pcP{¿£í \ÔrÀ5à:œ½€ÀnÉ^àMëpöG lÕìh4c³8hÈp³f°uçnö„Û#ø~÷{ïïÞ%?þß½K~Þ%?>à=À ¼wÉxï’VºwÉ/xPSôHðÞ%¿Q˜³.ùé𯵉CÙ¸ö}ãÚ Ø<0o³ø¥`£e/Põ‡‘½@÷îmöõc˜Pö¾ªqÎ>5vío\¾ãÚGÞ¸öÆ‘7®½ñ=jy“~9päM¼P“GÞäÀ‘79päM|B“GÞäÀ‘79päMm“GÞäÀ‘79pùN¼E“ƒ^‘—ïä€_B¨ÚäÀå;9Ôe“Cý79à·Ž94M&sF&Ì&9Ø'ä@—šhU“ýjr iMt®Éö59ÐÃ&Ùä@7›hi“ƒmKö09Ðá&ÚÜä€ûD4¼É®79ŒÖ·þ£ÿMx9ä@'œÈŒ’î9Ð'ür ENôÉÉf99àcmsr wN4ÐÉ.:9`Ëž9ÐT':ëä€#CôØÉF;9Ðm'Zîä@ßÜ-È<9Ðÿ#zñä@Cžð‘Ⱦ9pùN\¾“—ïäÀå;9pùNù“9päOù“GþäÀ‘?9à-‘GþäÀ‘?9päOù“GþäÀ‘?9਑GþäÀ‘?9päOù“GþäÀ‘?9päOù“GþäÀ‘?9päOù“GþäÀ‘?9päO¸mäÀ‘?9päOù“GþäÀ‘?9päOù“Gþä€Gù“GþäÀ‘?9päOù“GþäÀ‘?9päOù“GþäÀ‘?9päO¸|äÀá89päOù“GþäÀs:9päOù“wçäÀ‘?9ðêNù“¯îä€ëG¼º“¯îäÀ«;9ðêNù“!ràÈŸ8ò'ŽüÉ#ràÈŸ8ò'¼8ràÈŸ8ò'Z±ä€³Hô‰È#ràÈŸ8ò'ŽüÉ¿Žèú‘?r ÛGtúȇ‘èð‘GþäÀ‘?9päO4ûÈ#ràÈŸ8ò'ŽüÉ#rÀÛ#ŽüÉ#ràÈŸ8ò'LràÈŸ8ò'ŽüÉ#ràÈŸðÉ#ràÈŸ8òWsJPãÈ_9Œ#å0Žü•GþäÀ‘?9päOù“Gþ&‡Ð¾É!¤orá›Bø&‡Ð½É!dorÕ›Bô&‡Ð¼É!$orÅ›Bð&‡X&‡ &‡0³É¡ É¡{‡É!–ŸÉ!®›É!œnrˆûir›º˜˜º$˜Òî19¤`rèŽdrèº`rË›º™˜pUÉ¡‹ƒÉ¡ Éw•ÒÝ79t…09„íMa{“CØÞä¶79„íMa{“CØÞä¶79„íMa{“CØÞä¶79„íMa{“CØÞä¶79„íMa{“CØÞä¶79„íMa{“CØÞä¶79„íMa{“CØÞ¹ö'ƒ\ZróJäê@[>Ñ­C[>Ñ¥@î#Úò‰.'Úò‰n*Úò‰\âX×þÜ `>×þñóâëˆù½$®Ñ9´ç¦À׸öŸgæ—ˆñî\û'rã\û'r†ã\û'º_9×þ‰®[ε¢Û—síŸè2–¹ö_`UÓé£3>øÝÙ‡TÃ>äöh}ð35¸–1®ýãçÄ=3âšç\û'º:×þ‰n‰Îµ²ÄîÏì„sˆ1QÌ?7IçÚ?©S/³®ýç»ë’ªÖ×Q.f»5/t‹{*Ý Ýâúj»Å,s/4®ý«ÝzŠë¾íWGçÚ?í"Ýò¢[OÝz†ë‹íÖ:×sóNÔ{óVDvmôe™üÖµÿìàÔ¿=ÜS NýÙ]\ÉSÿDwWçÔ?y©«ÆÆ`93‹Ä6»Êll‹«ÌÆ.u•™"ܪ¸y§þÕy8ËuÌÎ×sçÔ?Ñ}Û9õ7“ìœú'hÉÑ%zN5»’ûæÔÿ7K†zpêhé˜blžOäSÑI|ÊæùÂÒ1x!+NçSöýó)ÍÇñ)ûþÇó)ûþKøœåVð)ïO'ò©*NâSU,åSU¬.3š*Öð©*Öò©*ÎçSU\À§ªXǧªXϧªx&ŸªâB>UÅ>UÅv첫ŠkøT/àSU¼OUñ">U…õf_|ŸªÂúk/¾†OUq-Ÿªâ-x[W7ñ©*ÞʧªxŸªâí|ªŠ›ùTïàSU¼“OUá<±ß§ªø(ÖØUÅ|ª g”ýc|ªŠó©*îâSUü*Ÿªâ|ªŠOò©*>ŧªøc¼´«Š/ñ©*þ„OUñ§|ªŠ?ãSU|™OUñç|ªŠïXqwîÌ‹ù|ªŠ ŸªÂš,>…OUÑħªèǧªhæSUX:¦„*Æó©*âSU̧ª8„OU1OU¡EÑNZíT¡EÑN“ùTZ³©B‹b6UhQ̦ -ŠÙT¡E1›*´(fS…ÅlªÐ¢˜MZ³©âd>UÅÁ¥c‹©â>UÅ>UÅ¡|ªŠ‰|ªŠI|ªŠÉ|ªŠÃøTSøT‡ó©*Ž/«Ýµ„OUqŸªâD>UÅI|ªŠ¥|ªŠ“ùT§ð©*NåSU,ãSU\P:V»kŸªb=Ÿªâ™|ªŠ ùTøœåMŒUâd¿™Ü(·‰gG eŠÇÉ'i.$×—‚¡ùä(mËô¢ñ‘ZÞ?öíåÖ8/ññßÅWJ?ÙØ‹—aÇÛ%¬l‚QÁRq¤p3fäÏÇ¿Íû!—ðB¤òD±8¯¡¹»þjK‰z¤2¬CT¨Ë¾‰.¦*<£¾5™”½yUå|!™¢³­ÉÖVLD.—¦½[¼!DW¦Ù<_–úKÓ;šÑ¨[íÓDËÑÞ—=I™¨,çø².¶¬ÖVý•UJ¹ZuAIëKŒÉÏmÄùàEr}¾­f9ž ò,É>ÿÅÌÛ›}¹Xë×Ü}Unöm,ÙkEkC;>-Mð6goßeio`ôlì»6ó Æëb…š£ll–J·r±$£‚5¦PåÀD(}Ùé@Fï7åOùÉ´ù¦ðŽ©M¢•Ôå7ßç$*øXsŸ.«Ãlwì‹-”6;ÊÏ7/¡Í½•%Ö×m–C¦ë§h!DÇø$sõrƒ´ãUÎË)GNIoü÷Œä|žy«›…³(C`åÒÆœô?õQ±à(ÿ'±«Í)ÀÍzgéX0côó‡\dTž%én–NüEì,Vn°ŠQ:ä>ó•Ѝ}õ²V-t^mIÅ9tÌÛH#n¥*M¥c…øúñ)LÒ̧çoò Qx±¦\˜b¥%ï.j©in¨½g¸â¡<ÝlZ”æ8ãQîÓ¨L`iYé8A§ÓøTôt>–ó)è´‚OuäÂÒq‚NøtºˆÏéQÞÑrP¾¡¨ž„›£‚ï¹)ØÄâÛê"Á¹œWßå]µ¤ÈåO` ¨¬×ö#·ÐÞ7²µ£Ü©Ê(·™&hHnåf¢æýŸjÞÏó©æýŸjÞm|ªyŸä ¢æ}ŠO5ï×øîû4ŸJÿë|ÎŒò^KdÌ´<µ¨^x‰ µ¾¹>uß ýX"¸xYŸó:–n®ä‹E` ÔÜ£‚çÕ;x!î+8Ë8J-Im¹”<Éõ§²öO f+¯'²¾9å¿Àš$W¨ß$°‘Ù¸0Ê?ˆÐ¥ uQþ \@ ò—(MåƒD ˆŠºˆœ+ª’¢.º‘z¤P’$t^ã‰.[Üã‚ãš"*˜¦±ÔöŒòÿ&Ò ö„!’ÌŠ'à8šå^Ã|ÍŠòŒW®8Së£ÜÛ8midqÛÒÈæóÈ(ÿ…ÊùÊÇ¿¢Qî3Éf® ³t•8…OÍò©|jÿêCj¯É×j—¹}§ëEéÄ'Ot²0¿§©ÑS]ë¢mV-Ùð$ʹý ô uáš,þROeYV.8Ètto4y=³[’çU}G·9Írv8 ÂÆØó§‘ç/ù;çð²lMÓ®(Çìò9ØŠ\2·ª:v0m'Ÿyt–ÍÉ5¶qZ{f®à“çÊzkê^ÙÇ–µi™è{*>û.q•ž:;v]]q–À ã z1¾Œ£»|ui’è zrje/¼?nãé×>ñ~¸ífûÄûß6ÕÙ'Îï¶uÈîkñE[7ô•1£ï+J_Û¾(ÿªxgÚþ®µc-Ol ŽrœË~k¯Wުݫ¢óÎÍ+ë+ÿ3ŸØr°½Èç6γí³¼9Ó%‹ÞÞûʶÙxŸöOL–Äy•öOœöÂ?„GQÎÛ2Ñc3åU_Ùòäk7{bË3¶§ý_^ÞFYü5æ“­¡sœ©•&d\š›øIëå&~rÆO9ñ(×ç¥Ú§oÛgÕùß'ç?­ÕûÁŽœbSnúĘ‹6§OÞœ.:}b|›Z¬¡mm X›ZÒ'Ʊ©%}bŒn›ZÒ'Æ5r^‹º¶¢¿=Yß_‹žlì¯EðÄ›¸W-²Õ]tÞ¨m„³i2aã<ÜæW¸rR¿¹ö(ÿ µGÞ»7Ñåûœqö¨À[«÷fÙ£|gB<3È8cƹ)ö(ÿÆ FØ£g¿<ïE:yiÁ®'éÃÊFüiJ³^³e)Gö÷*K™YäïHé½éûÞe)Glèaú°8b —f;ZÜ7Ònyß’´‹6™_¾…6™ñ úg“œ’7Ï&›1Ð9›Ì8ÜÎÛf“ÖÕù3¸ÈØgÃÇ«âø“g’çaìL2ïj?›9“Ì€0p&ÙS6N›Iæ÷R:j¼Š?5г…ÇÏÂÖ1¦£Œ±›1{;ßë¡{yZ¯¶0Oküu‡>æi³ïNkìP‡ŽæieÈ®ÚÖìiiì@o—”—aX¼˜Á46¥}VúÑ@O]º¬×Õt» î»t<ù>ºtÇôÐ¥ûÝþþÙgé:J{·£îÉGû;Ç£ÂÆnRÉïHµk&U¶¡C*|ÇLª3úeR£Ûy·xTö ÈzeakÉ B»ì»²¯"ë˜KèBÚ4—ÐfÖ7—ð­s §nìžKè‘VÚ@÷.Ûu.!Æä—BWêh¡}VúÞ@]:s÷ÉèÒemª¥óðÛ·Ï¥ó«0ížK÷wýͳÏwO ½;¶bîüéø†ÄVwÒßÀümòŠ.†Äö·2$~æ@?Câö75$> ³!±_¾½ùÛ‚Ñ<½liVT`Ó4™> óÇ…;6¢ÃÚœ»H ©wïøjjã¦=@Æú‘cHÝ2 óÇÑYz,ã‹™­ý’[Cæ‰=Y[ñœÔÒæ¦ežØ¯¶øŒLŠ—¤ŸØ怨øÌLŠkÓO,˜4ëCFKÏÔ9S¬§ËS[y†žÇ©SþJ—ωò])6ÈV™›'Œ[‘ a¥n^BU p‘3Ã-ðØ5;Ñ,ÞÊw㥶pæ|ai­ò$m°?7Ã_ˆ×¯-.[93KÔôÕD5€ÌDÝžÉ$Éjsg6Ñåp³LŠš‘´o•ÉŒ‰ž\Yà£ËË®žÆ}Àœ¢ýÝ[ÊÓzˆuPv'>ÿ@nêËúÇñà—{Ïú;¬÷ÁÒéUÜhÍ™Ú?у8]øñ¼—ËS™ÎMÜOß,­˜ I$v—Id¶múÆ&*ã›ßuú¸Ye´ÁÙ²J&)‰Ž7g2‰ãT‡˜JÇ£¨X´™':Y±Ž7§“ûµýo´x tãÔJöb6òöÕ©d7çÓüÍ"ÞüÅ@v½1°;³‚7“úß,çMsÿ›§òÆœBwõ&[8öÍ2ÞÚÿfáŒ(§Æ¿Y4v:ÈÐ é9‡P-ŸEóи •b€¡7بH•æMt…2¥+lÅ‹#Æ)3*ŽØÙò±x*è¼ ~6« 6 jWë劙,í™%åÕ˜RÂYsÀ W<~­¨ž;õùî„¥e¼"žŸ(o]:†+ô(²ë þ‘Ìmiµ|-ó`yæ–Õ¶»õdiUßç(‡…eÐÆW·68Ž­HÇ[Dï”Ì‘òŒ\áû`饭_Å´T¶¨`œEQ›E6üÛêêådÇGù/ªKB§\ Û’¡ã h-˜ootOŠ?süÂÊ+›j:ãÈxOð-ÿºvYªždéòö†vè„ñ;ÒÌ9K(T…c1UåLáv}Mcµ¢•7ÅÌxñtÏlK*áÈèÉqdwyUâÊ% Qã§Ï+[X=õø*0X᥌azó‰>4_§3âšÜî³ZÔLÝ\Ó: ë²g¹5&X’ÌÓYd1@Ç’òkE«“3iÜË q”S “P-SÇåì¢ÆÏþRZ¸2Ê_EüS›Ä¯ Ÿ¸ßzj;bs™Âmˆ‰n{{”[ÂúBS ›®áM;"‹¼ÛI|'ïœÙYOP4ƒCÑš†åÕmM("8«OFöÛÅÈ´Äì"Öiééú`+ÕÚW2ì õX<Êm.û ²…„ ë¶aclw;«»Ñ›m"òjDA2$VT×$—W”‘m 0÷u}Dhüþ´‰„§­©Ä­ùoת:a²òt`þ¢ "­u!vÉ/Lg<–ÒK…âÎN”a¥$óg8Ä4—‘§”¢–T:vCr‹Øû€¯n+P!-Æþqû÷÷«3î~ù,ó5¯š 2’z {°èl8õU°MmÚE G8˃_ì¹ÞvߦId˜‹ä6Dqµ£ŠkWG‹x{±¾W†éYëÑR–%Ày‹QZ}jÚþ H>ó'-îf¶WDwž²–﹫É- BQVîÇF`‹Þ®aÃðÖ¾S}³3ÓŠ›é;åзlù= 9>,‘i÷{}Ûèd;B˜[ONg×I9Gܾ3¶p±@È~–ø©ÙÏÖ¦a³êQ-ó»Þ¶;ý=7šE|1ú»›ƒK©3íé6Å•SÍ–©ÛÙsŠ/ëŠn«týÑÅæË~¯r]‚d¡É#VåYáòÐkýwy&cMvC­MbóVw–«5P7JàÊÙj³¶À÷E¶Ï)aÖßzXEý£¾ek™_l í鉄mé¹É£Ý»ÿiO„¤Mò+¶·'çbÑSoÍ ÙþÈöÚýݪ™Ý@= V÷´œÊ‰ÆÌªÄ‹«ó*qÞ0¯X™=óºˆï,&.:­,š.k¥[_ö“k»ö¼m7YhÛºç?^{ʯˆ+fjôõ1EfUßÌàÖgoœ¿–¾ù{/8N€gëË£¶ VÛ8jS\1j¨ÖGÔ·¯&ýï˜ÛcÃÜ®bnÏÁÎ"ým`vu˜051«Ö4s'”Äܺ¹»ÓÍvÙÖè:ÍÝm§"~Û9sÆFäƒs¶ÄælÉ$lª]È.¹·žö×v=ûºÝºNg†ïqí)w_Ó?k³ ž$¡ç"ý¹ ^¦ÇìP}³C´;­åô°s¬A©n}7ð}¸y§³Æ(LRÅË™×EO)’:»­a©·ñz[°²·th,^¹Çg‘|²yžæK<æV¾ä,‹iÊ’«3±‚·Ë¨ÜoÍT¹ 7erîÊä+–dòÍ2¢1HÒÝ‹— \wcw Ž<‰Ýë÷ØX7vOˆ<‚pt?•”lƒ®}ºÆ4Ê€°{£lH޶Q(U9Õ'í¹FÙ‚Ð¥Q¶´Ke×EâÚìŒ@5É$¸®„M’¯•èsBô˜Ejb&0Ô$rÕ×$!h‰¶6IÔYµ÷“p¿DÒûIP^bæý$.$ÜO‚ÜړͲZ ëf îKlº WD™›¶@U)ÒãúS¤WÔ*RÆ´Š¼i¹Ûìe-p¶°lo)4 v6Ê9¨:Šl(XYYÌ#±QS|º4%ÆÖ†rÊÀ@é}iCXú·QÍnT˜Žžíg1RÄ£Ù½ñ¦øyÓ T‹ag Á^xÈŸšÙéåºkÏÚÎZÔ0qäGZdŽu£¹CfמÂß5u4Ž'Ƹ—ð0ù«š4Ò̳ÂËšÚVD¹“šêVD9+ ÆK– {'¦ÈËÑ0\å| 2‡x+Ï&t „(ÿêÖd[Gc;4®Ë[ ÒPÏþ¥£I·Éž‘ú&¸#5 á;HàJË ¡®ëÑ„é'ÈÚ…^åöÖˆu‹¶-ÁØ û¼Oë‘1«ÍŸ×k~Ð NAšï›œ w“¾¾±1¹Ê¡ äˆÎ»6»­ãâIý5ÔdM¿’Ï݇~á¸Õ'&Òb›>7GŒ\k_ù—BÔ²I\.‘ì>á’¡ŸE›n³,(K‘tuC›[I>×XŒ5ëÖ1ô³™*Ò÷ìÃÆØ.ÔÐÏf:QðïÙ’ôKBöC?Ë„¯¯K&–¬Lœ”lMaßæ`{b3K¢÷ʱ¶Y$´ ÐÅÖÈ9î%°½òþ³]é›°ÖÐÏ64s]oiì*õy°«1!¶5ô³Ž°wJÙ¬´¾¶†æÄЦç2—‡%›:tŒ†·.B¨V¹™/ìm,‹J —!¦n~þÛιÅf‰¹okM2Û‘în\ø¹ñxo¢žžzãôÌ‚7KÏìxƒôÔèMÑ3“Þ=sìÍÏóá ÏÓ ™4³@Ÿ0š+¼×öfßFã7ˆ67'±À\ê.ö`dŽs9³sÿ¢ÎÑ–ÄD~™èÌ‚Tó6Ö4&œ&l›h®€¦èº³mŸÊÆ*Ôn{ó&C¢ÞL$fDW,ÎÝŸ+ÎøIß펎â ;÷ÆîHW".µ«¢S{Öò­ý{NË)Ù«ü»­ÑÏ:õnÓÚþO|k—oc2¶.Ž:¡9˜zš/îî^Ë䜵>_ÀeT³ô~™§õ5ȸî_¸lέ-“Á˜cŶ8 ö„z0bÕúb¼«NÍã¢ûVLrÞ9¢h$µërõ¥ªÅ»—p=š"¦•©Ö²,‘ÆÍêíÞÊÆD0¹Û‰14M*ã–e‘¢Jgœ’]æMTb·d„ÅØ þšƒ“¢½Ó¬§W$Þy󫉛`x¥Ûl¼,¡×¼§XJhܘ²Ð^›ðÙ~ãü·jæ!Q]VnΉò«rsO)É]k€ùñ¼è"cÍW9âªÏå…sæm| –5Üû…äj—Ř:?Æåº‡Ø=ùGñîòx£eÝÌ—Dw}Q^” 5ëÒØÐýòhgÌï63ÿ˜¦6.HTLÙÛ]@ÎŽ›'Óuc²ZM^•#_Ñéäæ{k­3}™ó޺ɱ†¾ÿït²rª{ÂzeÙíétIWŽJµTÏ©™#X{}K‡#ˆº€ù4gÂÓì oJš¹ö†¬Ùé“m`ž¥sì`qû€‹Œß2ÜP ã˜üë~fÆN2NŒëìM(3;r¢u]ÑW «¢C–¯:/»C¸m½¦ƒ1¸z¦ÞÍ…V»ÃåNß¶…·º&W!«a\Œ]þ29–”€%nÞ‡T`'ÂNÚ?ì$]ìÀ+Ö»]cævÅbÛA»ˆírïÖ¸ÚlýYm#kC#ì»'jcD¶Öôî ƒIdEï“8¹ÙÖÿ±ßâÎ0×k¾òž®SÅkP·vG%é½L¯Þ—?¥û:Þ~“=ñA¾ß€±ÜJbxWþaûžý7Ã9¸þ†jvsyy×-tv­?¼³«;g¥«MöWôn•뙿lç¿6_d…^Œ×ܸY²y˜ç`vÖÖ7b[Ñ^ð¯z¦›ÍÉdPzÐÚ¿»—š1öåÎ÷xæ٢k¢Ýà€%ê•Ùéúþ_;ýrvú¦mŒBItX¼Ó§gvúÂôR?£ fõ¦hÙñÞD3;Þ™MŽdlÖ3 `¬ 1oŠ\æ8bÏ(\ž‰%Þ,³r$Þ¤9ïî5¬ âp'V(´†F‡%&iÛ™xs0ÏÏŽŸí~æ£uÍ¾Ž¾·íl¾õ¶EqÝI®P\5$̹vÌÙóîßsWž—ÓùgÀ÷D{xΤNŠ+—¬¬ÖI‘Á·º×l #™Îä´™7oü™¼ÖfË8¶9cê—yKgÛ2ÃSäFÒ~fŸA^Ý4¸CqÒ\¼‡^Oî~÷¥Uyƒ‹.‡ÝT÷ƒ1t·Ú¯FTQ»æž™í²GïÊ«¢gµAæNϵ+ëk!?N<æ¼÷ÞT/=öìZ,}tîõ1í1}õ=Æ ˆ°z‘ý;ûÚÀ2„ìfÛô˜[îsIÂîsÂ@IÌ z¤—K¸Gt÷òRèäÇ-ßÜË™ÖKŒ•töÒ°ù]/éŸï¥L—`«}ŽÛ•Õ^Â5˜Ïôr¼fÓÜõíú¬ÞF¡·ŽöHoÏŽöÞÔÛ5\àþ.²þÂHéì¯z˜ö—žúþr›Œ.‚tæ^±mV+Ÿt¸Èö3Q?VmµïXøG·Lpç¾Þ®ˆžUäOõR\1gzÓÔžž:ãÜ‘h=UßÒžš»ë)NÄ)*Âqš÷•{ïÆî~ˆqé·ÏÖ ÷ÞÙ”‹>·\tZ”_ÙŽê}C?~¤Í„Ýa`}ƒUôý}L¸‹Ù·˜Ð“"ª—¶töÁ%µûl63{»ÜæQ‚Îù¹;àCfÆÏ&¯0® pLÍ%€mvc33$IÛ°Æ´bú/j﮼ÃGÆfî'”vGÃGR–bS™…y#¡0(ÆÜL÷¿'ƒí¸Á@=¸jŸýîæÍá½<Þ œ9&%wš›ómFËÌè 7ÎèÎ’hÕÝî}:Û¥Œ„^>U?FË7˜bmÄÖ¸»V—òž=þ‰ëÍÒXXªÉÔEßÚ9B™7®V½™ ¬ª7QxÓÚ»0ªÞ³#&¨—únñ˜ `ŸŽ½ñ}ÅñÇÛî¸}’5÷mÜà6;ÄßõÙ!£ÃmÆßrˆ­ ±M¶O°LÓ‰y?ÔŒµ·O8ÓˆwS.>ýû¸|‡îhÌÓäÜOýmÙêhìÖ¸­”‹¡:˜§Ñ%¹Gõ(_¶·ßäâš¹– 3ijËüûÞ¾+ÚÇf/%;Õ·›3ìóôîí!¶Ëæ ›E{û›ao3[~ΰb¤çeÌQ-ÙuV57®¶5uÑ:1¨oÈÖ Ül´‡ ›þq,7ÜÝR U,lȸU<—Ý®<[ž¤¿cÑoÇÂ>Rg¿MØõ›û~c1I¸½GdÉ¿lÇ®ôÛrhª=Ž~×ã%˜%Ïzf»‡‡ûhÖã ƒ÷,1í»?ÐWßcø|º W¸YœpY§P·¹>ú¼”{J½Ïëûo’žßAŸýí—»˜Ÿë€Ùá8wöÙ+·}¶\EÛgøšº4VHqâëé³å=å}þ×~¯g×û½‰S¸9ˆý¸çXŽªï2ìGuöß·ý7UÇjÇžT/«Ý汬v¬K9£â‘,ÿõæ´³Õ•#P½9íÞéʉýÀÞœvwåÄNToN‹Yºrb;ª7§Å“]91TØ›ÓÞ4ºrÊÞÞœöŽÔ•ž~oN{Oëʉ-©ÞœöÆØ•“Ö›ÓÞX»rbIª7§½=wå„Ý›Órºr¢QÕ›Óò/ºrÂÁíÍiù]]91ÞÕ›Ór»r+`O¨B¸œÆ|7X¼n¾›wÞÄ77’zÞùà‚zÞy£ßpaë9xçs#¡Ý9xçsÀˬçàžƒwÎT¸™ƒnEŒŠÌäzË¥{~MB;b4 }ˆ=ß$£]b•7™¿6™ÝáMFtuØ'›žªîÛ„”ꂊ?P¬]¦ÔÄKb¼ÞéÎgì>ët”+j’zÆA2­+ŇƒdXÌräÖ`²,[{:>Ì;IóD‡Ê–³jž 3bêͼÂ(#Ê!…´*š Vi =ewÑÔø!ÖìOþÂò‡ÊZ®4ª•Ícu{"•sƒž¨}!.ÄDÙy•VÆDû•Έ²,Öé$ñ¥ù1I7lÝÁ&Éô fp’Lói‚&KÝM]›,3ŽêÚäéq×&ÿUlTÁ¯¥»†îˆíSjü0a-õé0aõé0Ùb.š"u,õkŠÌˆkê¦ð–i›"óƒšÆÃÍxãá2™(Üq¸Ìª¯S¥f§¾Ne`LpªL1JKjªÌ!j§Êì ú9•iøÝ4òaÀnó…ºiì´F¦ËîÎÓ©{pÓÑ×Csdº´DÔ—ḛ́gÐO´GfÈœœæhÖËЙY„9š©Á„>Ì`úú0C¦ö´f²ÏÐ$™)ÃrÚ3™ƒ„y›‰þJ–˜I¯Ð*™ù•xžfíéØð0Òí<1ó2h'ûÔDa'³Ÿì†›`=Îfb“c]ÎN™°/‡‘ho>Ó2ꭞĴôÛýýŒÎ’yUÍã,Ù%Ö ÏÒžÕö;B[H³xÄ¢¸GGp¯ö!µq}¤êSuGŠé¯©=’} Z°ÿ ¨¿‹ = E³Aj}Í6o1è—mîž/–z¥fl± )«7Ç ‹jÓFµ'«Ñêùñº i¦Ž—=õüxIsH7èx³D~¼4eTÃ’X#'šù´3ç~K0ZÈ^X¢Û†öÂÙVýKd%[eÉVOn&ÿmZåÜNÃÓXå«[Ƚ¥,…´:î`i’çlcÎF¹×³ d£ëc0P‹ß!Ë‘QÞ[îãrïf¿ÉIÙs 2÷fÿ©ÔOZ«t7Ö´.us4ž]yD”wþƒ„«J2ž—§Ê©àtöme¿-l¥8æ‚ä `êÀ¡>me©üåV:¬/NÇ`²ë6"M”»Š­.ãi}€|R¼=^Ì&¬Â¶“Tî ÷ç´²kñ;¶Õ^ùþ–Ε¯Ý<Åo<0b…÷ýnr l÷®Âòû÷O8D5Læ*1˱+\ nHUÝ@b­¤Y8>BÆÕ¿ê.E£{7Ô’[-ýß³ctœÙ»x: iç48[îâUH׃a¯|CµŒÙØâ#»ñè=‹RÃöàí(fÍ+B‡6CÏNÖüa½‚ZAs¹SÎCI¿–ݯ#á8ÐQÂ<äEÑ9X‡£¸P+¦Ï×ê80ïÈx­› Œ®?ß%TתZŒLÇ´´D;ð“î#ªŽJ–@Z›J0‹¥Ñ´öÒoke_œ {¢8@ÝPƒ½—âZ+äD‹Nt²ѳîšZ,ÐŽbN„sRÌÚS¿­¦ùa’¦û傟C $ ÓSD¾!@ ï9ÄT˜ [üŸ¿ÁO§9#£MÄv/œóÒÏDïê%¨;‚¹%¬BÌ–,ïŽ|‰ë|͉ël­GNz5BeˆëÈjÁ¿ˆú‰œÐ¯¨¾¦ŽÕY#c[ñÐLÚÛ(0DJGZåüÙIZ½1Î-™Îö‚ý×ìOz¢ÿÒšüAÿ9óúþsìÞ×zîûÏé˜"ÂBñ7}t„)fBÏ·A_$îx9³ ±Œï‹Á.Q/7w,ÙÔK/”ÂÙzªõRZgÿè‘ïŸ9ƒ»þAä­ ¥ºÇú×ò?ú'Ëßí¸i_ÿ,ÑÑö¢oEô*}ihƒùCbø¡þ±|ÿ tîë=óýƒ"Á[ ^—Ç m0êß¾ù ý3bõ/ˆtB0ÄY¹¾Ëë†(ØÿPùßøÜù¯ø§[оºÿé¹ï?„Rœ©‹þTÙ÷þþ‡Þo7{iï°šé;– Ô÷W0/Î>Çû¾Å㞇úáÐ €{VXß!uöýúÐwzíûR;—ó•×>¶·Úþ7t÷²Ž lîÛ[ôÌ÷Ó!ýÓ²r×cý›úŸ¸íûýƒˆ¹¯–Lnû±‰þI µ¡ihƒù7<Ô¿€ Xíë=óýƒ‚Eÿ$TÓð­¡ æÜöýþ‘_ÿè™ïT1Ý‹ ×8{hÜ3™Ö©±FèïÇxàZÃAº–ýÙ¸ 6Pà:gã–€ ˜?Ô5±8Voü§¡ 0Ñÿ˜‰k #훉.Œ”ÍÄšmâÅÑùa&˜ƒ\¼r+ŽÐ›Zÿs_ïë÷A‡ŸüQ/þÈzë…ksÝ'ÜÄV!uÒ[]…›œ0óÝåÿ£·õ~¬··÷õ–~úÞB)¥·r~Ôï•C+Ì-¸ë¡¹µ¸¥«·ˆìë-ýô½uR ¦+š‡­0·êí¾¹íí-Dê}½¥Ÿ^L ©†^1›ÇŠÁ@ ÷2H8ôæ´sÓ•€ÞœvtåDÈøIÒzoN‹3ºr"­Ò›Óâµ®œˆõæ´ø·+' ½9-æïʉx@oN{çèÊ ©¿7§½ítå„2ß›ÓÞ³ºr"²Ô›ÓÞþºr"xñ¤`Qȉ noN“¬;'¢Q½9í]¼+'R:½9- +'‚V½9-ÿ¡+'¢³O 0¹œF¨ÈXé*2HÝ ‘¯n»éñ_QLMlÑä;Š'™Ý¦çº~Ph‡HDQÌ&2¾Í2~Ó2~sKÆ’P¦%uIª´8ÎXŠÉ€6^ÂÈÜ9>a9€ñ9œl„ÑQ޲-”£,„á~eIeƒ«9^o9^r Â5^ÒBt°²gœ£²ç–V„‡”±"‰‰T^m%xœæ€ã£Ê+ŸŽ+¯Ø\T$óà~ &–Ñ ì¥ &Òh_ Èñ›ø#ÇïZÑÓçhÔ>SŽÆ™qŽÆ0óâPϵ]DjmT~É¿c¹þhK·Mê¥IˆAóÑ$4UÐÔgnBzÈÿš´tÔ‰&mm·&Ødߦ;,’î×ϱ†ôM÷•«Ÿ©rõ;-ÎÕOr#>7äBNJ¹šÕ+åjv6e¬•ÿkvWUýcöÉ…ô ¹n°\’p/ÜÑËõêÐ|è–B(<Õ=1);ø±g %‚àƒ¬ØÜË¡J>䲚Y•ÐêYÖGT:Õ%4ŽktIùâ³b_ìåY¹‹Âœ^®Må°´½­j *øù¥0í ÿØËl)t—bQ¾pQ/ó£ðÖÒ1TõÍ>VÄo…‘€ç¯4o,•Ýø¤—pPøxéXštrï¿p¾äÕªp/|²—é…Tï±¹°¾Aæ!;¾vpú­¨¥d·ÈÂ¥H/š{ïv…ߔާ¼OöÞ» »—Až¦Þ;QaŸRœ“~Þ{_)L(E_!¹£÷‰Q H!srQ(-) µ'Å¡9É»B3““B·“‹Ã8${†yI® •¼/ a2 p–c‡‹F³,õÈó?†¦ýÌ4M›S´þŸÎÒÔɯˆ-¤ó› ˜¹ó8°“~í¦9oÎ{Ãoqý¢–úµEý2¶;ûe=qTi³ógÜGfð2wa4Ê…ylDˆÉƒ‰qVl±˜ñJåbVBŽbˆ6:Àú_¹x#•ÁiG‹NôÓUÑð‰'Ÿ=FW˜'º‚…*]Áú%Êf£%PNÆo§aÓ£ Ûî'6-#¥¨8:\îuÇÒ¥¬&>tŒóðþrô4ÛWD'\ÔU›Ó™¦M9={溓 ÕåçFTŒþœ¶´­¨®q«É÷6ô“ª§Çq»ÝM¿È½ÚØó³Ýìnv„pmƒ;ßö°#ˆùAÌïb~Gó;ÂjëfTkæOD–†O =°#ÌÕv3ðØŽ¨S­ÃްÔ;SP˜) î_é0SaïB•¦_:67¾lè™ÚTíY:SÌÀc3­cßLÑ3ß?Ñü ®£(Üø¾Aªâ­Î#̹ÎDFw’g‡\sþfOó ÔNòàßGn Û3¾YÅÓÑñ­tk.^𯰠kø_Œ='¤s"¥Q®v•à ò†¹ß·Lè ¾"RG„uÝÔȯkî6¸ÓMuîøðÔHhâÞ'„QÌu1è×Þ3÷ k-­Ù{?‚t§Å8lf%/. TJãÞ.£äÅ¢ÞŠžÐ¯­+íN¿ œþÒ2×BÅÛÀÌ\PpJÕM‰ñ'ãÐokίâTlÛÎø zñòþφMîÊR\µ¦àŠªÏ)vDqÕéW,Ø _Mx2— çQƒØè4æÒüå3÷jò³˜Râ:rÜUõ*êhtuL ùF”àì®]ú½šùNOúÞÙ}øïèxú¾ù5Qþ„ÕÑÔK¸¢l{M4lõS£'áñûáÚQX¯·’CžVãaã¼ßIž›Éw+oÁ“W‘ë¼å† žTá䜒⮺Ýï<9§¸¸ë´Ý;ußxþA%Å'OS|?âûuêÎaüVÄx+-ÞîÊP/¯E6«k—ø½Í>ð€ .z@PRn ïüþ€øÙûÛÐÖ:÷Ç-›Ú#t5ô¨åøuà©›õ»^ý_ѳ|ÕÕ3ƒçñT·}øŠžùþAq-'æß2iÓ]£Jùë€qØÏkòýÖè][èÝÝ71߃_üÎBç± ûÄ{•Øã 'ß!ô2x‘F^ý¿å¬ÿ××÷÷œ¸¿›îß©]ýÍfØSiëþp¶†^[? –Ö‡†'}/ mï©€•zsÚ9êʉ?™Þœv§tåÄDoN»G»r¢Tý$Í7äÄëJoN‹M»rr;îÍio]9!îªÉÁV ‡#Ó¶™¶Å‘iJ=hâ™i {º‰3b½sŠõµÎO‚{ò;úôGXåw¤k¼ò»ú˜*¿#ßâ•ßÙË^ùé¯üÎæÉ”ßÿÉÕûYŸËp…8žÛÓɼM¾žáÑD9{Ʊ-rÃÞ-“®)~e&mœ)¯ðš^.Já,l}ʦ¶\™_Š üÓP—û÷£#:œ+ú¥ÕRf5/`ÞZ¢îGã<¶Åá}Y ßíå3Xuúâ©vŽ· oê=Ï;ÑúŸë;ß–Ñ·¢©Až{¯w´Î½\ÛÔÒ¾Ò+‡vј£kãü)WOÔæÞ­o¥Óa;'Ïád´1‰ª(®¿ûЭ/œS:fïY½çχ5ÁŸTÿ®D}åê¶öfTÃõ‡míÅ.R~!7ŠÚø1ÂÖx¥ByhweOå!·ãêô ¥ã Ÿ­é=hÆÆÌôKìë¿/5úwzˆôæ(‡»úîqÝÄëo•ŽgVþ¡÷¬Uè)_e´÷‰e-ŸŠI®Å'ŸKvï¼? [)©k+™®¹ä³a·öM@ ÖɧS¡ŠÚôÂéÂÏJ´©„ôŠr˜"˜o¶¿ t†:ê*IëAúÌ&$Y ü§(J_¯Â-´àHZMbEÅbMxœW-¾!¶A¸˜nšY’wýhç Ä5×µ:Xf]L r ’ÖÔÀµ´AÓG LZøUÕ–B…jÄ*1 ­ QÒ‚¡m7 èRÉ@A\TíiãûèŒõL_Ž7é'¦š®ªèíIg¶éí¡šn ¼¨òDC:³±Hصt:$À×LÓ™Þ…Ã}5] ·ùù±³ãzîáµt:º@½ué´kmºì¼lµ«U3L’t³Š/ÁªÄJÞÆ°aýÇϰv-ãÍxÎw7ž ÝGËÏ±ïØ¥ß²7o†w_·³sox÷•û²Å8Y~)°ûî 9>˜~Ÿ ï>عw‡wŸ ±»k÷N‹ñqGÈq»Å¸¸¼×b°eo³Wë[C¾[,õf‹q¿¼Éb\pwÆçãb~ƒÅ`Z^o1®Â;-Æ%þÚPë‹Á"¼Æb\ø·YŒý¶Õb°ß.ï¶X &ܦPÓ†[ò­ ùV…wç„wg[ FÝ ‹q‘\jZbK,;J.qÓ|ó-Æ5TŽqMŒë`{x'÷¸&Æ5mj¨INrÓØ„O®rM 1±6‹qwóŒS.ožqÊåÍ3N¹¼yÆ©~ËbžqÊEÎ3N¹Èyw¾ÆÚ·½¹8;ÊÍÅœë;É'Ç(üÙo½Ó¢ã}¤OlžgõÜä¥ÊûŽIpSðý>—M¹óæèì×gEç¼~ÿhÝëË¢óå4„¶ Ö&Ì볂ÝWŒÞ&ð¼±"zåQe§ˆEºtÛhÖÂÒéE]Ñ8˜=ºå´;sð–®&ß“ÃÛ©-ÝÅ9#£b¹m­:-÷€øíÎñ©s”lœå—•só§,\\Z´ðøü)]9_ì\—_¹Æ¿¾ÏJœbýùé{DëK»óJ.–ƒÍâ­z·}Z”ëÅ6¯< W—7Æ.è¨k. gÝ”?ƒzûµ8vMVôs{9Uùwœ'FÚY‹{®ÀÇøÏâ\w>Žú|ú¥kÁͪr¨Ž„Ü+”ÃÖ›Lžsˆã”q…\“Êzʼ]ñ²ü)U';ñÒ·saÂ)6s{ΛrÒWçìUv{w³wÇ/\œ~ÿ¥AðÝ Ks§¨ÿ$ÊEê/ê<®\g{W¡äÚ†×&‰)J%â½=¸ 6Š~¬‚Àdsã°0ÝÞ9Fhal†!VzÑÚÛ ú¸9›@í/½mÓÛvÁŒuq²×Ãô­ùÛ»ÌྊÝFì½ÄÚKO;ÈfE»(9‡^àÄ3ŸdÍEYÑ”Œ+Ù;”Ç8Ö®8º*7_γÙÒ¬g{°ò+Í€Ÿ“³J .ïZœãÜmª/S]~»+[×ìmBõ­·&n„Ú¸æèoN¡•²ÕYwjÁ:ßZu5ˆYLdjvb¼ù< ,wåZö¶?ç»Æ¿ÏßlxcwK¼(v²W†\~þÓz™/9y¯½µM‚À¹ð¦òµnηì¾|Ñ-ª/ÚØÿlDÃûvß#uoèß+ý‡»1±a7F»‡ú2ñQê97:¶ä°é[©Gyâu Ì¿¼³U{ekÎÓ[`åï(AÒ5佡.:W.y5“›6×q¶ÕqEWgN§Ç|êQko·ÖE{¦ãºöµx¬xÕ˜›2¿¢7f/I aë«â½¤ºS|¥ù\ï̆·ÆõxK¬ß,róÀ;}ßüXî ƒ¹7<–;ÝëúN1‰¾'›KÞAáqU{V%ˆíA B3#5“7Çžý¥bs.n…YBK¯‹Ý€Ë«¬X㟻r>¦ñ"ë.{íhcÅÂæôB²°È½¯}µ4f9t½Ž=CV9b/ô,^V¼Öb:YÇ[Lœ¬Ø+èN{ûb{ÅÞµb‰gNK¸5™i1qߝРÆzâYíbª&ׄØW2 ìÂ"ë“ÖMÁ»â¶èÝ ‹Õ[ô=Öõ·èˆy§²ª»Øb1qÀŠëBÌ×-.^É×DÌ÷Lý+y÷—ª£ä{&¶té£ ¸ä{¦›pÙ;!Ôœ•§[ÿXK-&FqÙ;UeÏúk²ì냸¼>¼û’Åt‰)û9Ó»ŠwÚ¨:*~Ä ®LÎô¯RiuÃXðâæ6XgwfõCû-½´V`³—å*RÛ…X…9)sÛ.sç4 Œ¸<¦;UÓý*鮕ÆtïJcºƒ¥±ÖàD[¦Ð9n÷qº_D˜S†o£\ÈEÞ•zëêK YÌ+ 3ÚÁ¯\)¦c‰Ûú-k—û|/k×õɰvgó¬]æ®Î¤µ m梞ƒw>‡q7ßùŸ79€õV¤Ù2{a²ÔsðÎçSÔsXæ¸eÿÒã:û/ÞñûžßSäÑV×ì§JU®Úž ým…§ÊÝ–ÀÒÓ¤½ È9`1¸©çàŒëÏ7TxöTªr¥’,e¬dXcêY‰þBÌv%Q|¡­’e Õ·ŠFL}çÊ/šj?y×AÑó˜ÀŽëyø­‹á¶®’ïºÕðIð·^k Mh \¢çùø¼LØö¢À¿wëäËN[k¼ù„ÍµŽ¼Èïƒ/›Pû:úPçzúƒÏ»õxê|&›_wϤ®„Mw!“„» ¹³$UDÓrØŠP,p)߀£±}D5¯@í㜬À¦Þ¤÷ê׳ÈÅ&}Š0E&ïY˜ `«^ÂD#Ûv *wlØKS,RÇfm\õm3~ΊÌÙf¦ÈÝp óÀÞ‚_™"ó¶vÛøRmgÍÁ¥`X6ó¥ÌB‰:/ƒ__¢–ËÄ+±a.ƒ9]==›šJÔ÷lnª%˜Ï—3›_kºDs/‡©]b..‡ÿT¢ÎçУ3óØ6%æã9ô¶D_Ÿ£zÄÄy.—ý2ç¹ÔS&ö<4$Ëôd+ý.ÓÏ­ÌHæùÔQFüïùÌS™9|>}Ñ<Ÿ]Qfo\ÁN@0ø |Q–™ï+虹»‚ùªPß•Ì hèJ4S*äºEÉ 5]É^mcU˜ûmô¦Â¦» ¦F–ÐU0@PW ‘©÷W!|‹¿Ï«¸™W¨ÿê©1»ç꩎Ûq<Áoe ª±ñHjýÅ© ãÿ,sé§}Õ¥üîX¹äÕìDòÑg£lQœkZF5™ðIh¹ÀÔ„ˆ°} B}rQ¸O7Wk–=±Ö9ZóÜkøçÞ)¢–ž©É½íâ/›.ÕøË@(ž‰˜àxÛè1Xn7n:½B€&ØÄÈ…+Vbâ$:Î3úEÇ™8!Íþ¶>É#ÿߎ [ÇÇs@eÆsψ²÷ÛËòž‰fk‹ÅΊ²w‰¹Î䇆>ˤ†Ýí™Ô ϤF¹Ô3©a»{&5¶ˆ<“˜“úÜ,|3ÿmâ¦mlƒÅÜË‹®j×VEgK7*×–Ö†¥ÒîÔ­êÛyÚÒ|ÚsÕf«J¸/¬ï¨M5Y AÕ¶ð¦ø¥{º¼¾6E»õj« Óª°îW{YÉ DÔÂ5km{í üm Ç&o£¾…ç¹ oHàÌ&ê©XÈÝlØ*i¶ªû[•í­ªîV)¸Uyà*·*õ[åãÙÞ¤Q†ãÜ&(|ÃIo·•¹^¯uÝãÒ/ëjÚkªÛNJ¶Uc¾Î©JoHÕÔñhãÒFút\e} ¦—ó3ä„nÆh%Èõ§¥µ‘%X“ê cdXÓ[Â]}%L¯›C‚âÈ"go®ÃŠ\—‡»¯úas?ñH·Ïi\ñTô¿%ð°PøÃ‚àÅÓŒ®~QKMkRÇÌ`G¢}ájïcùF{KŠÊ¥z°zÔX%W/©nJáÄnÊâuÒZ+ëÚ¼Ç6 Øuk<âçí#oÝ6kÊ É™¾Dù¿ÚÐ(ñF¸„ ²Æù|ܯkÛÚÜR‹r_år™påⶤ“'ˆr¿`æôL9ºb›½¸®µ)Ê{í’•íIÌ×íïÓÕ#¯vW®Å}×ùõQÁ ÿ°<ž¸D¢¼n6¢ü§ZjUUô ²­­eÚ¢¼iT}ÉÊtúÂßÇèn=sq965%[:ÚFu‚dŠfum fb}¨0ü²UFC£èËÍM5m'&¡›¬rm+žÎ¼Ï†Á\ÃVi oÇT‡Â< > 臽iŽ!•†Æ"ÈM Ùc¦ÞŸÍAçjgjW:4ն펻_ÎÝnäBÖ,§œºj5r=âÂÆÕÉü†~ø6ùä¯Cq™(ŠË#z•ëPQÌy%àâgaÜÄrpyœrŽªüžÇÌ…´¢Æ²Në|ÛmË_ÍLÏx54øÆûGÛ;²í+w*fE׬¢s–¾¯¯†›Ö7@_G8°r~Í’ÿÚÛºjop L?}ouLt3Ó¶ôòMÆmæÂ'DÝŽ^;ç Ãi8ŸâáÁE,–vËÉxüC§\ÜÉñræoVq ³³ß¾f_7/Ó¤®YÏ©w?XKìk¹¹_‰µDoîq.ÔõÞö(Þ›X¥´;‹X´öŒ‡jÿ컵Žcœ §8 W]âê}wÄ{8åÄ~©¾ßûðìDg=Ö¿ ¿«ßr»¶¥yoúžùXß‚"íf}äwhQ=N+9U_¾÷¼ƒr¸ÿž3„SuÏC!öœ'ÅïàšØÙ¶'²pmO&ë‚­U‰³{Ršfü´+?±Åý\nâÞÑz¾/ÛþO ãŽx_Fݓ֗i–.Ÿ´¾Tß›&­ÏÕ÷º¼£vì³eöY4=ÞgÑdኹë§+ßÔî}¢a²òJ­7ïÃŽHù¹óŵk™´ž!ÄYýyѽ—CPõbojoÌŽUÇ;gÚ½Ù¼þèÈótìP¾Míò.ŸâÏcžÅÑ2ó‰C§Âë’à6Þ**Z.Ïœúx³˜`ÖLËÁëóºð¼n¼¯[@¯[@ÌëÀðºÁðz j_O­ùWŠ¡àÃíp8‚jèŽýL1ôÊX1ec½±JÚ/¸OI»G5tU´s|Órwä0k^5Ô8`v;©e‘Í :»qr®J= ˆ^>˜Ícù`hDx…IæåI…É“yëÍi±mWNæ¸7§Ýó]9ÙOªyºœ†+ÆÕ¹b¼ó|²' ÐPS7Ÿ,›åa3ƒEç_ß°B4)ExA°OŠò«« ŠoÊ’¿÷hê¡Wys¿æW’"ŒÞÓ3ª§$ýUÕSãMõ”VÇõ”V?V¸G /8M&?€º¬”µuÄ·*ër%¾XYÖ3•£ Ï Å²-ÅM©À2ßVa3Åð«*¨†Äð*p¬ñ5]Á~†+_ç[<®齋WÕ+ ñæ7¦ ðÕc”%Àj1u5à>f/ð1ÝH=X·jüxÜ߯÷÷×™téìo£T¼4íÔ›§Ij(^rÒߨI†p0!ƒ™õ¹Ÿ2KcÒèO©ßý4(`âIXü,ãÈB|³fé]ëz×|LÜæÙn²~°Iký0η³í˯¿4zÔ•þ“ã*úKÖ>YB–õÃÏúaþ=ë‡ÅïY?TâY?á=o2ÖÏýÞ…°a0e,© éø­Ü½ï½áuºšyÐÇÀ¹üJŠá4m£e[qV'±të}׊‡Y½&j»$ ”– Å(y¾n×2%–Ž*&Ãç!ö€özYU…Ÿmª øÞ{{WùÁÖžîÞQýò´Ù-úWe@,5ŠÃ{•ëdÏð}(ñi!e°ZŸ´Ow =GãQ>‰á–€,6?ºJì=ËÖ²—^; ™ìÙ3kyqÔìLù«WšXzU?žÔ4ö8z4Ǻnhâe‹ ­«b`g@?*°©s>aÓ©u¿œ?ÐD4@:IB1ýd;Hñ’˜ˆü`lö=`¬9á‚Â?;÷%r »í¸cXåÈ0ÝŠh—Éܤ¦vusƒ*ƒÍ5b;êpÊ ÷î7àŽ£ÛÙH»ÝA<•*ÜA|Ý<@‰Üº>án‚ûšhX츃šËÅU9W Ö× ߸êê5zupøóœS Ñ:Ô¿©ÄoöÄ¡‚êܶµÎñ}u:1Ôî:Acä:/^ãêÔå_ÿª?Pßèh—PŸ-¯^ŸçuŠQ\r÷©mh'ïø<ú/bN5K+>Gî¶Ek ˜Qálú¼bqÁñ;Ín)6؃ùÖ㪺kw¼O!åÒ%éT˜£âðá‚þ>¬ }XK¶Y¸c>ЇE‘‘¿‚üiw@ºÌ‚ky®\¼à:bÆ¡¨Óô‡èjõomx÷ýY°-¨÷į Ñ"(_+wÒ»¢$×ë1E;³;‹ªû/%/+ŽKˆy\¡œËnµÍ#GI9|®ŽÞœí¹ Ùæ.A„plQù…´“j½1·èE%Úïµ>´†>4”¬‡s ÌŠõÒè18 –^úØ@MqÕyùSû³Š{sf \r"çô‚v±tÕx œ¥®ÊÙïîÁZ§ÚœVu‹»ç”[6ó Úðmv¼"vùan¾/äæ[Œr€£aæBÚ;Â6¼ïîG´ßÝ,Á¸*çÞX%c®÷‰»6Îà¥$ÑxFŸûí7´¯¬qʼn±£ŽÑ³™«‘rp5r>ÿ…ÏÚéãŠÓc÷"òΉxXë¸Û8X`‰Ýª¹ñvÞªy·L§ðÎm¾)§¯Ï~6߯ìÉU»éóÛèó[­ÏLû¼–ÿÚßf/ý Ïãú›KßC}¦·ƒ í›ÀŽjz‰›aaãL¢;$ÙzÁƒ½í3Ïl¸§ï]z×Õ}d9pžä˜[¢Ë g¡7§®œû¸ Áh^ÈÉþI‡!'š˜OšÓ 9ÑÎ|’‡r¢¥Ù›ÓXMëΉæfoN°n='PíIW!§Ñ*êÉiø¨Ý9ÑÚéÍi´3ºs¢ÿõ¤‰šVoNëö¡+'ZAOrX\Îr@Ìíæ€Àð®ù÷ü wǃΘ(æxEaÿÆùR(^±Nç¸>Ã_ÇJ{›Ëþ,ƒû•¦X†[\ï`dL¾lFM¾ÏÆùÊǸ—¡æÝ»ÏèÈ^^aÙÓU[ëGÈîúW¯£{¸Ñ?£\‘š’f½ƒ›\Eþ'`üq\_å§®¾þ}l´…­bK:A »ÇùV»!ŸÏðË–Aú'ÌXãsã kÜ *úö†k”ÏœWp†Sâ²µ`ÉaìþU§ ã€dõšõbÖ2.TM“”¥¨æ«FÌüG«±ù:Î×ï°‡ª·lûèY&0´,Ë„¥èY&p°<‹ g™0sže‚ž³g™ÀÝ|€eòí¸ÒN7õ\’.‚B·Û„âÝÿÊ»N£¥7;u; ÎbB·‚èý/zSD ;d¡¥Gu¤î¸á;ªÆ¾kP!nm5o|ñ^ß> ß*7ö÷î¢Já%U¿ïá>V\Ž}³Q9q`  çnš¼¸qÛÔW^»ñìÛµJ*ŸX;å+ûWTåÛ¬rèFNŽé¨_‘}ðn øzt¶V çĘ;7œ_tGBãƒÁ<µi\·œ…ýêºîH,Ç¢4v$Öðä‰÷øQ/Â,9Ön´S&•`Ên6D5m p^z¦^7‹®Þ*ƒ¡#±Ô8Ði«%Vš–{C-su4çýÅtÊæªVü@^)V¤&è*v{Ç™v` u”€…˜†˜ Ur M`l¤¨¥m€ŸÓ =2W¹ÛŒ®eUàÑ‘Xô@c7F`p÷ÒÕQðñËv­œFÙÔµhÛLYØó:~gõwÔÓ¢mr6‘w×£ýÕöÚè,Gd~NLrw9Z(åt!÷Ëy[§s®Ý$—õâ8œ»a¶Ü‘v‹M¼ñÙÿøÕt_в£¡•XÞ_·ô•õ\e÷ôm“àRÍA¶ ëvÔ[·‹_¥e ÷½‡{Û¹µÏãqó9ðC¶{­‚è(æ­µh!èž,º÷÷ÌD‚âÌœ.t3<‰øô¿©ÃêC—.t¼ ùÝ8é›sy”¿† ©ÑdÑ7zïíx¸i?}î;v9ªMËÀ¿ësÊ¢ÒÓ¸>\ýS§a!݃ûZNùЧÐû9ôáòî.î~7ÒqŽ·}“Ø?F;Oà¸0ºáœ“¶ÕÅbÅN¹§LxÉú¬‹è±öÖg|Lä4ÀÍ{§Ï Íþ£U{÷QôÚõ@³mÞ\—éÓ™×: þ x,^ÍßÅlXqDI׺»[ºjïìêN÷gêH.ÊÒ!9çá\q =^æfcWÎQ½õ›¾Ñ£íë³&OOÅŠw=[€æTºžõ1#ãá]»ï1¼«ðÜáŒÚo”š]¢·Ì÷ÖQa×îo)\ÛŠ[1Í•ÞÃŒ}‰b}oG]ñv6Wûúœ£J@/¦î†ÜS."ß ÌV>?šZ8aXwvŸ~ÂÈXÅèÆkžŒn¼¾•£Å4å¯PÜÔ«y ¶Ðëp-Ä/Rþ¸Û´Ú/'nwú'ÊsÅ»®Ú]2f®4SIïNß;/7«?œ•xç7°k®û/³¡fê|h6~0âè¥Úðûö€fÑ÷5v}•6‰Ù…£pצüÒ<Á›y¼iæM³Þ¨÷“·ì˜ÎÙj‡fëß³Ó¯“…;ò.R Mç[`ôE]Q¾øQ`å¯h¿)o+±‚bW¬×žû…N89;àäl'çý`“*/Ç(FHáux‘"WÖ´ EW¥çjº3™û®Ñ3·zÇÓáÊê5ǹYzm]Bc¯Õ¤ûeì5»u/½f·nž©Î¸r$^ÏZ÷ÏÄkyëÞ™øú”CZáiŽ‚×W…«3±¢¯[JEÏ!ê6n^üš$ºõ¯ÄÁ‰©;F¡wDõVí8tðf3€â‰ý…ã‰] /sîpí®­ò—` &×ÚÄŽhžc²f´òï&¶mí;÷(Z»/8K½¸Ý#´žª;ì–ëåȳÁVi$™]§o³ë¬fÒŠÿH¿&º="©}êÔ°¥ºq4;Á ðŒjç߯¬vŠ7xHË2³šºãƒkt£Í!ü™N›æ qc 8Û9„7£KFÂôŒú쀙s©ÜNàM¹ÿM«iô~B‡¬­Èô2ÙŒ#¼¡ÓNÛWN^— îw h,rx/à!Ïy$–ïØï”Ï;wæ agšƒ³Û!x4Š{ÛöŠ~ &³;ê:}Ú#ð—¸Ý!<=S\jù×0óšû ‘6“vK¹Øáå^k»™]³-íå#w‡vq{ ¯ Թ̴Áðy²hƒ¾ÜýÝÄÛÏp}1x~²a©´õ¡æmgó ŽòµvÎ}·{Ãé®MïlrËn^&óä]æaN<÷¸ /3©Çéw¥¾RÌçè¶Œ¯ùÊéÚìþoÚŒã\¯sÆÛƒî”Q»tÚ_ð˜œKÎñŽwéð«ãWÕân/H÷^ñ8åd/|xÿž[Ò7KqFæÂìS=·×qG{lÅ>ùÅi£ìÒ@“O˜vrÎ#Þ@¼™ø|⋈·o%¾„øRâ#ˆ&¾ŒøŠ…+Ù #^K½€8·§n×ënvS´n üiËÿ¶î%¥sÑFþ³ý;¹Ã ~Nð*rö6ךñ-òp¢›·´Ý¸{gÉIo1øK™· ñ©t—ºEoÏZ<|¢ö6Rœ½ªà“\ô³ÖåÕ÷& ǪlÝÆðnbw“¾ g¦¬—“°3ç¹^èN”îHÛsÃ47/ÑüÛàŽ“ªâ!s'¨Övs‡.Â¼ßæêÑTÜE~»ÃÕ“ª¯ë‹¥ÈÛÔ§ˆÛÙxzYÇÛoWèö×a¤~©jýÁ¼‡üÌ™ ç5%ܹ>À>«îxãáTú¯Úñ›Úkš7ïxv³¿qž¼‹±c=ço ±Ûƒ EwÂY£ßëxzò˜N<ÌØ{¶Vˆ½ á‰øìŒŸŒØûÌÐÍ*ö74ð ÷Þ¡XâkÂ?‡÷ó!œ‘ø›‹¤w3b{ &WÎ@ͬg˜ù3È?FÞÞš'Ü|Ø%½Ô¹Èùr“Ð>ž¿m'uƒ×;¼¶€;oé~û†ÝdîVcÁWE¥3RÇ€9®È8H5oõ.åCõÃëWoÚã;²½-´GGõè­œ—íV6BqôkÍ~Ö·òàËļñš¶µÝß¼Álñ=rþÀ©ùŽ‹/è©¿vÜìºûwôAo6¤±t®ûê} ¹=\›½mY%[折Ÿï¤ž»¯²}½Ž·ej”ÇÕmîezwyh¦n»§—ÂöN7oÀM¬°Á5µ:œn<«ìö·Äö‰¿MHc™ŽòÜã{õYó{ÑÈp/ªº>}ð^$<=•²-­5µN¿FQê¾ üm¼àw87Ï÷fö¿n6&gq¸³ê”ወÃÍ!>?à‹ÏXnµ6ÅàÓÐÍRÚ°Ù»mŒ“ø:ˆy¼ƒ¼«Ç;ļ3U£ÀØ)¦†ûn4=¦ÀûƒúsŠé§¥o 9&@¿)Ìn·¶Æ4®Î¯KÖÊBП²¶N‡Ô)Úßô¿y°Î½ZZ¦ÎõÍÔ)Ïrk_L¿í›-Z$^ƒÜÝm‹»«9¾JÞý¦¿çÎ=o}ÖÂuw_BÜÝQÁЩG£v0˜Ï{ó;£üUëžÞÒ•›]¨|Žzo 7ºî¿Ñ9LÐú³®¿?göX²½‡©Ç'·ãÇ»þéàß½ëSÈ#ÜßãÞÕowßl‡a«ïYòǰçNk1}ЉÓ‚s~ß±s½[nx“ïË™XŠéÙ³þîÏžõø^÷<ñ\ìNÄËGç=ïÚ°ñºáwˆ¤ìƒöÈ‘ìëV÷Ü–Þ#šKx'Üœ4s7Oº¬†þ¶°ZÊWò|«¢«Éã±aªcífðVÇ NêÀ뙣_Õ`xFäɹ'9×ÄÞ¶ôí¸&ö¶eã~ö—XØ5óÒ»&÷¡…†´ïÓ‚S{еs”«¥·?½û`;³QÝ f3K%UZò—4×aI¢K|0¿ÏzìoÉßMà“ú½ÀùÕßhØž«ÄŽð{™o±™Ç…Hç̯RsÜÌf7óÐ1pä,[/sßüÛ™oϽ‹YRä&ëpÃMfÞÜ5·Åójç†Û̼}㻦Ó9ÓýAÜÇ|þÎZ_ðI͵úÞÁnGdªæÒÝ2[sãð7vÕ…Åì®°ûþžþøÝg€!œÆ`õ¾èòܼi/ä„ýuN¿·.×˨Ñõ[z²i^ÛÿÇo§®öɆqFôbW›ÙA¼!þ¯;èNi€‹LÒ«îÜé½'§3n¿ óÞ˜Àü‹x­w°ˆçbqSônŠŽÙv—çe‰°{w}%ì.ëÞØî®³bj`ëùýO‰}e±lª‰göÕ­N'~[4–÷Ká5w}¼]û7”\ð·c'waxÉéß|WW4bxWþþûràŠ;Ê>épÏtóVDðëÜhÓWq®Þévä÷Ÿõè ïŽñ9ÛŸÙäåËqzz!ݱlNȵ§›—ûù>\ÎNLZ»»»çR=²Ó\=ûvZ7Îþ¬îè¢åïVÍïèu>ú¦þvŽOÿfçyÌÍÎó÷orä\yØJß geï¼v;»Ð{·búZÙsÞ{î6Ûsè!uz 0bånÏi·¥{ï<•~(fww/ÿð Ý;ã {\<þ¤Îfë ®|:zBÝiOèƒï‰Ü ÅRÅVèøyÛqã.+`ÿžõ)vÆØ~þ »'åßÄ3·ó1–ÜÇ¿oY|Ÿ‡\£šwã:}7hâ½ÌÝÍ{íE³wõÿvÛ_pô;ïû6rk·¦mÂÄh lÛŽ€øØâ -¢‡ó{ï ÎûÞ¢µÀÈo"Æšó è­û÷†wÝ™¯çv܃oÕýX±¾&Nôøî‰ß{Ä—Ýon×é®´¡Wž{h ü]nygrc±w£ÂÊÒSóºŒCº4C*’fÞ®r>.Ì›9¸|¿eº9çFó.B{âŠ[ÐWP½ÛéÒ\š¹ý|¸Bhž(îq‹Ñ<Ñ÷ägË“IR9òÙ=w—®Î±jÌžì奪Oº'ç8Ýéi }f¬©‹6Äy¦ qžiCœgÚçM¬‰–8½LJöXB]éJµ­9-—«/€Kp.°üªhQ÷§Á_ŒfNàZ3-’ÙlNòÝŒzÛ­Ô¢Øxõ—˜vÅ òž >YÇÌ­™Èž›ƒ‡ƒÉ¨ºâÅqn Îú%¾b’øWG_»ê΃z­{êUÑz¾­¾€0Žê_Ò½¾îI ïúìÂaãý;´ƒ fUmª©Øõ=rܱÇðnvž4&Š]9%ûrG ïÚó+þ¾ÒÞ…öËÖõ8Ããóš*oAgâÎûôWÀbòA˜j3ë; oTjSÍ‹÷ì^xʵ`Gì‰=ROCí9¹ »=žg¾ò<ÚÁ‚³…[·×]'^S÷ýEº;÷jF™ætns*Ô²í­QîÄOGukßD?5ÛgÞ’·ô‹ÉñN|‹ýû늛.­\ãvF¹¸«Ðí¡sÜÒ^4{H~ê{Hw1³‡”Óì!»#Z¬†+;g8‡>´ãmÂïš«èÅUãôðÚ;'®w³¾õY—º=#Þ ¸ÄÍqÚû³Öe¼-îæ¦i†Ý~<Ýöãé¶O·ýxúƒ¾¥cd¼¶ΟIJ®×lf#¿…M‹7³s…ᬨgkØ_ëÖ®ÃKwàfpÈÖÅc¥ó­Ýw Úp ¶:/ŽÊ©¾ü=ýÝ€>oÖ“RÆsåæîŒ—“ΛZÚoÕí¸äV?ÃrZ¸u—KÀB9—ñS¡Íê;óæUä)Õ£þõÔ4³·&ÃG˹<æ^-GfÕ™ÈëÞ3sÝýU&ÀYçýíǵØÃÃß“)#*æ¿76󎞎oÆŽIø¥IqÓqIÞ—Lû¸ßÝ Ñ0WoRMoéã~Að“©|ÌÓµÆs}ßžŽgRuã©4ð§nÎ7‚|ÔÕÁOŠ#Þqozï}y£› /6ÓêÝd=ì®%ú(ïÐãØàgÄäµ}êäàì°Ù¡öy›k_CͼmuuÖ»Èêäm›Õcò8^c:“þþÕé‹T{ö½Ü,nuZAÂÿÕ›…ñVß°s´GQ] #e.j‡ªª&ŒçY!!”{SLµˆù›ºAžÛŒÃïàNäïN8ñó9”¯àu”¯àoÊ'ퟔ#Yð¾u§*æfxïèïóåÔIí«&Ñ‹0¸V<{ æÔ=¿£¿gz­å55ê[oÇ»:¨ÑÆý­ò A=¹Ý8îýìý*ŽCQ OäÒØ„ ÂNƵÃ,À ¯ót•»Ufº¦^c%píÀzþ¾‡¸ÇVÚròÏžñë<Ç”˜¿ûÁCõœ:áµÔ{±°UÊUëù[¨0Tì¹ÝºX%>·Lê±75ƒã’Y™Ü)TM)äç’Ûc1Þy} 0ç‘+wÁß`Á†ù­²àûÍ;ßol¹ø[%¹=Vó©p«á;<øuj®r«÷øNÛ"Åw¸ö’fË04í^ôá^®mûº½Ä>¾íx§óÕu öœ:n¤^§A ¾Î¾P{Úzáû"÷´¼ÎMuÇ37ô%Õ¦x¤/ì%õ¥Sd°»/øKÚ×záû"±xî¼ÃA”;Úûï¼;‡¸óêfÈ­Ðaà5“p‡IƒÂqøRþo§Vd;õ˜Û×›™pS•ƒŠš?ðb:7Zç)~þÉ]ÓòCüMÓâçì®ÔÌ;‹Ÿ³7ã{oµøYœÎÂG^ÐÏW±÷¼N¾Jž.tgå³ÔB&Ë÷žb ß·ÚÝ }ª›ˆ»/'®Ûi‡~á¶œ±àÞò6úŽ+$Ÿ1¹‡å`[ Å:u\„Ï¿ûà=2¹„·êÙ•¾ þK|‚fÈéwâ±…\,|1n &~ 7¾Xz‡þf»¬ÿvØqÇKü¯W&N(ÏÕÉßÕý ußêÞÐ_÷Ôþ[e‹¿Uz®VV§<•ïíI|F®-¡'ëú{¢—vú#·`i$Å%ÌדwcxUÌ"w•/?zkŽ˜sëõs1s3†¯ÞP\nöÔÛnÒQ'ñ­›ëYÓ{«þþMzBÿMz„í¤á÷úaÞɸñ¶ˆgÏwÓF¥×*Ͼ÷Îëï¶ÄŸ"©¹ xî¹ÏñTç—›€¯‰›€ç#ñÎß Àæù-5ÕiÓÝ Õ{DwÍã}p½¯•˜¿É‚ÙsMŒôž«: þÖLÌcvÅŠ¾Vå+zìÏÝ6×–Lý•“ãÚÌ-8½ór Îý§Wo¾_7Œû²7_c‚Âa\9œ.b(mÚ78?‰útÏuãÎÿÍ1ÝIóÍ4N½÷ Gn—æí0»id7åØ÷ÌïöÞ㱑'åï(Ö¡µ5›-'Æ Ñ•58¸K£š~¤·9w íâÞVof…î 7³B‹ùÎ̼@¸¸÷±W£Ã«?y¯crl€ùEpï&Gƒ8äôýzßÎU>Õž“×l£=—sVÈâuåòï¸Ñï»…»[a ßGµ)‹Äáåц3W€/ç9î‰ñ–™ÈÏ%˜ú3¼/LÕ°K¶»þ½:S»´/gfò%Ás’ÆŠÑŸ^,ø¥0û#6i’oÆãs6Ìx|FÐ¥ˆJp5RåÈZ>̶0#SÝÍùÚ†÷S317–Xøœù/ÏXœRõ/žöデ¯ªd4å÷ö ú¡Ýö{zm3z'¹®ÍôÀh¥2C·„Zv…ýsý†D§oï:Iàßɶ[à=´mÏ×nsLÏ¥ æ1æÐßbÌ÷ƒAªÓ8ú)®u:„«kb“Ì]÷g•’ÞŸÉ]×JwzãýÍ–wóñ.ph=VCû+¿KÇ›J4Ë9ÆM5„yçy¶Äüš˜Ç¾ª;Õ&æ9B`J_Á9v,xý1rä¡‚ï9|“pv{R³àù^òz[Ú¤éîb~¼Fؽ©oR]žöMJý âp“”η?äºÇÍ‹}:ƒø÷õ3øæ0ƒš‚tqïgPH5A¹âKgPnÎÒ”;y3ƒJèÊ!fÐø<t™Ÿú ÊõçÃ3H½Ï´wh&z<|Ù<Ö×T˜R¨ÌKoNË™èÊɼõæ´·ž®œf^{rZÝÔ®œÌ{oN«CÕ•“}Ñ›Ójuvådßôæ´8£+'ûª7§ÕUìÊɾëÍiõàBN;ÓïÚžÓîß®:Á!½9­ç„®œà˜Þœæ«;§ÁA=9­æ|WNpToNËêÊ ëÍiu¨»r‚ãzsZÎMWNp`oN4®ë9Á‘½9-ϧšÓøfc××}³ñNxÊä“ÕsðÎ{°åy=‡yârÀ‹«çàÏaùwç°z…¶x'¨çà¯)¨zÞùxì¨çàÏa<Æuç0ë{ÞãLã-¶;‡õ@gs˜ÿÝ9¬¸õ0Çìv{˜Ûß{… -ìϽ0>på ­¬Í¦mP‘Ó=)CoҪȮÔÌ+òƆŸ[ØuòKÛðM¾Q6îAô-11ù›äW´ GLø¿m‚Y_ @T= uöG7*Áh¿sø#´Æ“×Aq&×E< ÚNÑEÜ fý®ußüö3œû òëý~¢U¨¾ý¸^p;ÛO›E]Þïçñ¾íÜÛñm6a6yÔŤtø ­ ¥ºF³ð@2Z¸I±Ñ\Fèÿþ’ÔåuyŒ–ùþl6ÕÕ¢ 1F½–3ª1ÂðbnŒ/ÝÊ7΀¥Œ6†mSíXyÒÝXi¾ªÎ±l$¤ãÚ˜zNèm£â¾µrÊúÆ”Ôú¦ýã¦$õ–×&_ÈÚm_ß*TçÆ‰Å£ý4>S=Ž !]=@]•³¬tÐb?@·15Ò>@]ÖÿðdJwTÝšú¥²©}x ®êöŸç[.3TÝêöòMŒƒ“!q7Ç?s°›LyÖÍÙ÷ìªñšêæx]ƒ4{©ÿÚ?éü©ùX²êÊÁòæ£Oá¾3ßSäâYýŸÂ‹ÙBSpÊŒg )¿æ[uŽwʘmt8B'øpn‚1 ‡«.õàðŸÒX! ©BuÚ¥Sác% Å©ÜÂnQSÙR ÛoªæNõá9aÞ§É%´öÉ4î Äi°¯å4úž°_81ÓÁ, [oº( êÍtôHêž¾*žË髜òW6—àœl.ÙyªÔy(d.k(›DïÑ!ý>«Œ½îß|ÑÞhóøß &ƒ‰¡½¬Êfè²£I¡«©&l>¸ÆÍÔÎÕæ™ÉfbÏÏR‡ÔñYRÖU®Y¸’cßÏ^ÐDÏÒeVXw:„ø–ž¥I×f=B]ÓF=BÒ¤!•kmÓ#@a1ímPmÂ#à§ Œ{y%RÒe㉪oLî#A— ž#Í…â‘ïŠ=ú?„z jHQý²èǺ¾ÓïÈb|$}¶k+i ´³]Ùqíl#0Ðlaem›ÙÚbš…Ùbï©os¤ü«©ŸS÷~Ž”\´Õæ(¿¶Îœ¿‰g`Z)ô~Û„îÌÅ彟›Š{?÷̸§sÏìß Ôõ”¾Õö@†~ùÊ|_§#ç¢ÌJs¿Oû<áux:9tvžn¿šðyqÓ<¡2á›yÂÆÂ5G ; _¥[«ôqŽÒ~;J×uú(íyMûѺ+¨ÓG«³ Í”Ó᣹Ö0ÕGƒkbpïÑÔ–=e•˜+Ê1ÂKêÇ1ø?ˆéÇ1Œ]|£=­~þoÍWõc¾°°öü|Þ‚·æÛ6˜ÿáþmÀäd¨‘©È° ›,à7+ó…\•sæLÛ`6†6ÏúVѱʧ^+ü/,p,oÀ–Çê¾(=žc5Ú„ÇÂ`FŠ\! °Pwmƒ…px˜‘…š5mä…l0Î"ç£BßšU°æ"õ\õ/¦[ÌÈb½×6ZLÝ\²3¯1ÿ³e˜‘Å`E°èbjéÇqì|r˜äÇiÓª?Ç1ë\ÀŽûA<3Çýê!¤]›ó;Þ¹pÒ7N Ô½ãçÄÕ?çÑëÉñRwÐt/ܯM°D÷=uy‰œhh,1¿D» •¿Ž§ìM“ºz‚.ššüä(KÝ=ASª®ž û±¦ïÕ§é;AÌMÄ ügC€%Åx¢.š¼ÙáL߉˜9dŸngœDLÙI\¹˜®“´ÉÔ‡“˜r6ÐI—Æý>éÒ‡vu pïÊ®‚3c~'ÛEædí!Íÿɘ/"]suõÑ´ÕùStIQ‡O+;qÚl§f}.ÿ¦gí<žþ£‹Ò2Û·ÜÍÐD‰€Àíå Ã8¶½’ \c£éüž.ü¨..×N§Ë¼¶ÓrÍw^üºknVh:„ÎVR·ÎÐ}HØîL®†ÌÝ™RY"8SJaBøgbº;æRp³8 ¦Èþ,8›þlX ú³5§šó³µíôÿ)ò¯y~ …ËÉSج ø§Ò¿„-ùT¼‚؟ʵ-9<•9áRòT. ýy*õ&lå§¾&¾ï>õÓŒƒöÛ9\Ù ä:s_ ïÓ¹†À¿OË@>Ï V Ÿ«ØzEò­ûqç]ÅŧÈ<¬Bk»H?Ïe¿q,?$Td Ÿ'NÍÃy ‡"Zéç]›Š<»r‰©?ž–¨ã¼ð­~®Q•¨g5ȧDÎÕ`ÆýXÍå§DVã ²D?V³OKì¹5Ìk‰¾¬aO—˜‹5¸ñ(3½kØeêYK="˜FIê)S×ZT`ÊôgíøÖ¼­½”Ak¹¤”™›óAŒeöîùìæ2ów>û¢ÌüœO®2˜÷|æ±Ìüœ~/3?çSs™¾^Àæ+ƒó/€íP¡þ È[aG^ޝÐç ¸œTØ„»B_Öñ¶""«N(îëÀÚ×:ð5®bÖ£¡]¡ïëÉUa¬1VØÿëÙ/ú²ôT<Fd…yx&9+ìûgr—¨Ðg^oËg^å¼óöÞ ¸¨k3¸È~Ì7ÞSeË<¿Ê¨qSS¶-ÙÇY^jÒÔºLàv«uÀê¯l6/Upo±™èJvÁg×®ÝÏêòŒê¢T·:6`›ŽÂ¯Éný8n€O‘]ü¶¤/ïôÉü.ÔÅ]ûBy{BºPGe¾P·MõÝÔµ ¹Úü¤å#¤´AˆK“ºÈì"qã´ù.BídvÛD¶‘MÅ´mÔ-OÞ¨[žáÆ›ã‹ÏÅÌ·¿‹E{WÝs©¡],ýmˆ‹Ù  …MBlÚ›Øøx¼Þ$)mÜMôB>D¢6ÌM¨ËÇlˆMl:nƒÏ’/?m®g±9b6ų˜‘„7Ïbf6ó³¸q£}y6ó³ØÌ sp ›ŠÛá%lXnµ—À½ãF{ ‚Ûá%8àL¨}3“Év3¸ ı™ÍÊMp‹ˆêÞ>O@[Ä(QÝ[¸½˜ƒKÙ7¦ðRtðß~)ó^`s_Êü¨óR.uê„Ä)!—h9½(0o—QHå2j-0—ѯ±gÓ'˜)Ïff ÔÿlÕ«úŸ-‹fñr†$s9s\dþ.—Ž…úz9xTRæÑJi ëþñzYdÎžÃÆ/‚ žË¥}Šç‚A6Ïå¶Š/ÌçÜ‹l÷çqõéle.…[gÇ;fëlçðö{×®Ú&&ªM“Gk›±÷vJ¦lßqÓx~*϶ŸñßÇo«T²´ý¶JéD›a+‹m÷|±`´už¯Í®)¾ØaÂKÏ»MSñ|á]Mßó™îÏgØ~WÐ.cWèÊ£®]¡› :%Û•­w%õp‡¸R÷a+aßHÄ#ZÅ$±íäÿÊÜ%¶ÁTà.±Ü%¶éÂ&<´MwTÕ~•®Gšú«ØÞl»«t=ÒT^EnxOW³5ê¿Z*jÂáWs×M¸ö] Ãív5„‹øÕà„­»Ý9cÒ7,yõOŸ\ÄÑÖJè÷v¶IÂöÙÎfaÛ]ÀKø5 &¶Û5ª[3p 8|} [‚íöê.P÷ ˜3\v½€*0/ ïzûm/!²pi,ÐÿrïÁÕÝ ™Apù Aúþ"–¸üEô¥ÀŒ¾VøüEâc©þ} ží}Àé”f[‡“möH¶/x—EkoAfµ­“möL7’z‘.ƒêý‹è)hrÇ.qŽ»vÕ+´{Tï+Ùýn'¯„ýÊNz%H¯@?¯“KíÀëèì:í(ÕwŒä»ð:bì¨ëè;éz)Ñê^r½ÔÕïëQz—‚ct–nIªùzøEú|=×{Ù«¨©Hm¯ÓƒÈ^­›’æ÷Õ O¸„¯†gÀ­éÕÔR{ ·š<„v×½"}¾áC|«þTŸê¿7ErÞð¯ñ>¹áƒÄ}Ȭ†©^Ú‡©2¶Û«†°4ûùí¡V“ù½V|,Màkï@}S©Äë¤E©ì¯Ó-B÷zåÚz½x êôëÅûÒĽ^Tm”×Ã+à üzÞ²±^/Ô¥ ¿‘¾p¼QWDMô䊙¤µÉ„*ÞÀDqKx8TõF\ƒrKx#HTõF¡*MϹZs…|#Øœ[Á›¸±™ÞĦK¨ëMl6Ó›¸–qx· 6ӛؚ dÓ•Ð×]ò(§žíÒµR“»‹+hBv±¹Zî¢Æ„½Y(Lüf&,áÍ›éëÍ P6Ö›a±rCx³nÚoÖ†ÒLü4·!6×OÓ¿ýøim4õã§u[P~šYàÊøÓb¹j+ÿ4vë[œ×}“W}‹±\ßÂM£x 3êz‹òjVÞB ôö&Õ«Írý*²}o-éËMÜnŠl¿›àŠ¢g|s;ö&Ò~ûv±½nn}Ö ·w¿ÍÏ»ßÉá~Û;áæzèp{÷ÛôìÖë„›æK{J1çÝðÀÉ DcbŽë­ÿ販'Š}ÓÅžé2Áì1™ì;«S’½¨|v‹oÖrbÚÜ9ó«ª++F'å NDÈôA§ïd²Sü¸´º®L¹È/Iu4×Éô°ñ­Õ¡S7n«k˜ä{.ûÆTk¶¸Ÿ›¬nîH=ê'ûT—cs‡4GÖ‡r7s¦sí¹¨£1Êyª ž[W7PÂzRu[¯ìÙÖ^ìür÷ `æ»”UßX³´-*¸AE©Fç8¼ø‰¶šåÉ:ÙbÞÒÑå”j¬«®]e½ô¥Ü÷·àµ™TC Êùv鸒(ïe÷™Z­$ã)}êcî¾»Ž&² DõX“lkwÊ‹ïU(Ê}+-Üå|¬¹£‰­3<øù‡í¥þeÆ”øJVBêøù²(ûW¬™—ž†›lçF:ÍåÐå]ÛY›lioHQ÷˜Ò#X5×>lj4ʾ9‚Ó¨*Êˉ=O^TŠ“™Ò­÷™ä,½Å•«AÑÐN¿aRò¶*jI5®¬¶Ψͼͳ$‹©•(å®nh£y+5õ+;bãuÛFWÖ$ãí·2Õ’l­a‰’´29n©Ö͹5è¶Í5jeú<Bɦ Ÿðƒ^Ù/LgžCÿ~Üèκ´¢ÿ,³àu ™RÓÚоŒ5«f ;,%ªÕ$¤Ë”šµQuž^üté¨q㣂_nqÁÕ(<±¾.Y½deõIÉÖ”jãí¹ñ(œ0gF”•Ä ËØÒÑÅ£ØRU}ÅÕ}n÷ÊKï3V§Sê”MÕzåíÂìkÓëJGæ˜3`«ï¶ÊW7Í7­Wg§ ýô½~É*/ЇJOkÊjQKÆDySïó¥Uþzœ¸ói”û¹MX“Z¡Ú5ç—Ž=&Ê-¸×¾Uq¯gEÿ¼Å¸Sñ3¥cÆÉù”êê¶e£¹ôÍp¡KFwàXX&ÊZ¹2Êù«6᠌΀©Ö½<Êý<¹åþ¶mnKºMۗη} BÞïø«1f˜žÁ UDSÝ¥ï¨x(à^f[Û3ùr-Óôz‚k`ú¼†ÆÙý}AˆÌ„*³ô ÄUù;EÌÆ:½tܨ#¢¼I÷ùkH>ä:)€¹»#Y¯‹‡wÃè¾´µIë0¼ÿÑ{Q“}®Šž°b_:#7vŽÛj‚¤¡óÇ™åŸtŸ¸¼ƒ‡øQÖßùÐLæÈö¯;emÞh8[à:Ê]PzÄèÑQ^ö}BæÅ…<Ÿå_zŸžx”{<ï…îÝ¢u[¹Ô•y{Fí}P,¬Žó–Dy§k&Þ_Z2v : ÈFy‹Ý3“Ÿ?at1Ð×\I¶Ô,ðŒrî……÷÷âŽÒ÷5´|Àf¨SzÆ}ÃX¼ô^PWÌ»wÛï…µåø“êáEÑ?„•ë|ä_ÏJ׎[¹´±ƒŽ_AÇ…^:~^”óÖMø¡P» ä”ÞvßLUFmSåoÆ¥ßÜÚʇoÞ ÅïÞ»mÊU$é„Õe!çÏoxV8¥jî´(ïGý3Ó'·þ2§êN*,æ/pº{î5±í‹6ÉGÀ0…J°~ýû®@º-î¹ uäÅýu´sÎ ¸ßè¤ÿøI§VÍhnžm±úäà{n3:ö}ç`ÓQQ,¢ñº’ŠjfÖšúºg½uäÅ?ð$çAZyYžäÝs©åÄízz,sU±-­YÜk†´š{:Ú2Ó¥@n‹té­úìH(ºÆtÑæIha ƒ3ÏŽ„b)E@m »u6î9fÔ2 ûj®nØZ2~÷Ꜿ×Md-û\¸Òó¥¡[1ûYGì=kYçÃÿ9Ñ‹:10ðáØ¨É¶nÌç9¼sOIíªU]Ý»Ë^nÔAæÙõmûßvï~ËÍôÔz%ƒÙ?ìk¼ö¾Ùˆ»6¿[ó‡yÇ>8¯2zNê˜)SûºsÖLýÑ-¨ßy¨~c&¡«~k>žúÎÃÈÅÑkȵ":᢮Z ^>ГeOöƒ{{ÂŽùŽ1­ÊåÑ!î¿!U#’ãÅ­ºáœQ;j¬®8¢‹\RÝ”‚d¸Ì‹Å“5˜òæ… Ï®²wܼ™ÞysÃÈöÜb9¸Cx“ Äx=È {“ H…y£D¢èÆÞ ¦ê©![‡è¹±7‚]or"¹7$òmì ’èÊ–x&:'Þô1уSC ª#ñõ©ŽÔ°6ù¼A]á’Û3ï ÞX3Þ´³èÄo8O$ê‚7P¤ÃxÁ!Ÿ¯I·¦‚7OªÜEoÐH&Õ‘UàŸ9ÕTô³Å;oúH$좟Q°KÞDƒØ%oÊHùJ^ô_Tì’7€$’Ÿ?‰”¼¡òys’(û9Ö»²7× Söæ#Ä®({CH_y)äófUTwÙ‹,UÙ‹dCÙÏù¼2嫸ú”¯â{&‰”НIù*g˜1Di·e¶4Eö¹ ˆ‡ÿÍ¥!ˆE(pÁ¤ ¤"êA„‡;§.êÎ;/h&ªçàÝ÷DæmOŠÌó žÃ|8‘yú×-2_›1øºûç¤>›$Ü*$Ô$ûVé§ÙÐÔô“åÉcôCT1Ã~ˆ!×O]Ù›uŒ•,F³äP%yÑŒ,¢¸Í&~ÝŒDÒžýɃÈS á¨ÎþP®;DdiÏô±§ <$ÍHGÛ{€qTïøˆ< ´™„\@ ”è“äGÒtr"¬ƒ0N (©²ɨÎz…b u#?Ò"ÙÕ9ˆ ÌÈ äSÀ$ÙhmúÁô I²Áˆ‚03 õ ¦VäD#E Ê?¢@Cœ5.}‹¾dDðu©}àfq¦Vꉴ"Â_@‚m(“ *Šð2!C™!x¢WÈ “5ìe©Æ"t–áL0ÈesR¤# ÷€bF  „`ÍHD²@3#4*±¡F!/²×ñÄQ̶°F!hÚÙI³3¶$Œ}ÚÙ-ѧý6+vFƒ SMÝ £Ñ°JÌÁþô1Åý‘’)í¸c™YÙÿû|«Þ1Ìèi ì‹2Ëx „,PÔneêFÊD5–*3“c!Q®Ú@(#ëÒF¿ÊðÚ qµ!©R¦¿ã7}À«P×ÌM…þÀ½Â€ô^…þÁ ävà‹cVÆË2Òƒ©€á!<ýV–v+’iê¬I‹ú¨W¹„ Ò®™Ït'âðt4ÑI‚XÄ@RQ“Ó‰t¼ÐVÈ_ G½ ËÆVœ AA[¯5ôBŒ\꾉‰6Iï@€¹€!µ*øa昵a„NQ‹n:n7)þA•†è#îåúÆÆäR§%!ëüÒ’’¨à°Ð:Ë¿TÎïU˜\ä„1:(åxRˆ¥œŸ©\,ÃŽôž ²D—e¬IuˆC¥ kB†òU}%X9ŽÍ!Ar” 3™µ7oòú(ë!IÚ‰CZÿrdÍI¤°sC!¶!Çá˜ÒŠêó¸Œèî¹ù)èKPTÏûÂ]™)8¯ÖÉÕèU|ŒùK«Yëë¡äkVYJë+—³^ŠëÞju¬ìhKª.ó,Zž)DZ>k‘0Õ\Bƃú&툱zwy”÷wð╨·uÅïó^‚5=Ï£“ÂÀ¸Ö…qaK¼ÀµjSGºU¾‡ ¹C·B—DYl˜IÛ¹C k×GÙ7fºåÿjC»„ZY¨— 3eó¡ÍQîÑʱ¶­Í¡(÷U^ŒÅ„+·%ÊO”û…ºd}MGc»+'ÊÝÇ!—;Êž¢ÉRÿŒ˜DªùÓÇ€¤Páo­F*)l~Éãµ·X¾{ßôvÇ•Dó·áîES\éû˜ò¢kJ ƒ¥)AÉM1® )Ëì H)š€y:bmôô ×Uö{à9³$'Ù®Cv (Ÿè\‚ ~–²ÿ†Œi œ¨I»x™#<.è¹5Mx”Öí\&¸Æ–Ó䆮½÷¸vÕ§vß­+úAáªOÝ|íªU¸ù^õƒÂ^·ßrø<-zsrà[ìêÂé÷XœË9ø•«ˆ­îÏõæhòZH8‚Þ}³p-ß&¶„Ç«pÎ…û+=vrHÀ™2ž­]‡QÓWÓÖýö§Š+êI³½›œ¦&ró5Aj£&™¡&&òȼµrÑ<†C¡}黡P¢y¨JÌJÖj¿"ÔV„éÎf 2SöÏòò®£ˆy§Nļ«p|wº Ÿ§Š;ÂÚC¨Oœ-tÖ)çõ:”Og·ž:nBÍX¬SYgbKˆ5ðm‰†ö];ñyön¾s­õ3#²ß"ûn×;çÆpn¡3A¹)†hÓ.çbzStq}‹hjçJuš¹²ù–Z¾y–¯Áò5X>§EËWT©ƒ¼¼Žºøê,¨ ©™EA°®YôdfÊ;'&¶Áf½¼ÎYœ Žº›E£RáfQ„œ £[Inw‹«›Imìmç8çÞQ7z†h·Ö²«Š¶»pÒ~í.¿™cÔ˜Óëεý„ãíl¯ÍÓë oç‘«–ZZy7O;-8G4óý4ž?bcþmöÎfö–=æ¾^“ š 4ù z„ÞõsµËfryç ¶çóš»””€^a/)Á汤½“#ô{sÚùîʉ&ooN»Ÿ«9 ‘€X7‘ –^o꘥þ+¢s ‘ h~GJ:¡êŒb?D’ÜuˆHW’K!’”r…ËJ‚Í:Þ–îŒO©ºÖšCfÕ§È$­Q"«iœ9êr´QÞrÄÌ|š4ßãÅXHÖ´r”Fñ·¬YæX;õ§,‡:H—åÚCú¢éSEº™QWŸ*(ÈUûDõMi'7t Mã¬ú–tTÓaæÂP¢ðéÄFþ=¾…ú+RÖ1»AZœ:Âcø)l‹4ÐÐ÷@à ¤«™V­ß(,™‹ ‚÷4á9-†|TæÏöm_sVwçá=j›sþ¶UfbgFÑl£{UxYSÛŠ(wRSCÝŠ(gE#ÁäýKÈ|îINc*ùÄI±,ÚKÇŽrÞØ Ž’·­lŒ²ß¼rY”sC)xåonXÛAk­ðËÒñ(hÍßÀÞl’9½EÍémZŸjEE^9.¤©·Ôj°–²Ì Vbm ²¤à°¬¥¬p¶ipöœ¢§õEg¼ëjƒ®-ÎØEatUÁÓ‹ùõ ŸÑuµ1µA9\⼎ë¹ÒÐç&çWT ¼s p€º·_ɲP¦vœÿ¤HSïÎL`÷éÙ…Ýœ¯ž"”ö»Ä9¸8Á{Ê\6éÜc{zV戴ϚH-[wýÇkOYx— Wž²ð ×v½ù¹½²p"¨7­A5n}éO®ízöm1â} ±ÕäPm>ÇgzÝ%TÚ0±œÔö,jFmäFm¯&®Øw(×{•«eüYίŸÉÙ[‹©}˜Õnê þ mï­Gƒµu15µ %÷«â<–ûʨ CI¯8ë§…]ûfzqEÛ7 Ž›ÕéŠ#UØ eçjdà®øÚ« KÐèO¯0ÊqÅÏ…]Ñ…]Ïtõ57îÚõ’¸Ö¿kåÍÜôôLBCw2³ùÝw7Ê›âÖè½…kù6±¡†ö·Ú×µ@ï2´o¼|›w\$ˆüóÊmrlÝÍ®:µº¨½_9¸ÜÀu`§óð§ÝS½”$uÿ§·1Õ$™Q»7ó«€§÷† 1ï³–˜§Ä*{/1OÝ%æ/ ÄîÚvÕI.–Ñ–ê…Í"}®O"}®é«#}ü =ŒôËÒº‡Æ…ÈŒÈEù ½â£GHºA¥*Gƒ|"€^AµBüz'DÝ(·TÊÝ(Š¡(MìhšÔˆ!Š±ÊœQí7sÚÒÞ˜§Ëzv¼ƒŠi—LßøÍïÚmdÇ´½OöÜuŸº0{ù‚¦;*®Þ?zÎ%=_.üÅ¥Qö+žqð;èÓØ»>õ÷Ur.~Þú¼¯C“žöžÆ/:_—åR9#“ðî­‡aßív(?õC­Ï¾ã+_^ù¾«Î{ýYöžMâßã~$ë—}O¿üû¯œ}ÄmÇþÕ¥ïIÍxÿ»Û{îYî}¥äc¹?óËëN?þäW}ÄÞ³3ýûk¾1ý®¿»öí/¹}Â…¯ù{Ïå'BfE:“áT›\ŒzEê71z#²¿‰™Mì.ÚÅfv…tü“q=·¤/º£¿ëJÎŽÚÅr?;ÚD¢Ù &R*p¬?-ˆI÷h¸84]C«ü]|ò¾== Þ³ÅaàZ(¾ðŒUKßI×>9“nì¹;ÜÜhIzs?7ZÌ»5áÝÞ­"¶”Úù‚ÅÔp¨Á¸í®Á¿ó54èbcêxq0V%ÞÑs·ïó<°&¼ ÍÀxò¯ê>—˜½ÝšÜKD¬û¿é7—žë¸Û‹‡³âLˆØsk¢Egr.PMË଒³ÆöõÑNé²ï2§ÉÄ·eW DDì4.OÛØ`\¶F{®ULÿ·F»K¤¬½2»¹8.»6´ÑûeÆ»YÆ .³w Ô+ÞÏsõ¸¼®žGòòFý1yÝ{—×¼ŸÌ†Ñœ¯Ct,VVDwžâú¥úVD=Ϋâk˜¯ìrÐÕ’æPÜäHß)‡«×¼Ó÷dP§r-Ñül}‡sûêK¦9xË,µ³kú\Mª¦è å \¼0vïz«z£9^êëV¯W0çKȳH;Q}AM‹zëÕ÷Ù\nVÀÙŠ'ñ@9±3–„³„Ž6`GSÛ"ò,éªýngWô­N_£ÍÑ0Ùê_d}\d;c‚MÙ^лòÆ= %Ö†(Q*þv âo³™gßÇç°£GFÃ>ò(¥ˆ¸Ï¼‡©¸TÏÝM»YÀY¹uu®oç ݺ:ç;hr‚@éuêà‰êuÊ  ø;!ýôbÅ•À‹Çp#ðb9ļ° 1/C̋РÌÓ’J]‹ §Æž†„ƒ¶gäsÕòÂBä¸1“#¹Úr—%^0F9ïüT9RçáêGÁóŸð¤ä…s}¹Ãê@¼çSAtÇ Û ´3Ï.k¨ÛvºC½^8Ä]֬Ї½¬AÑャÙ<ö²_—5#Ø¡ììàþ‡ÖsðÎçxR@äQ!sé£7½—>/:Ðyä°«?ƒšðF®cFNîŽH~MòÂE¯sº÷“Lp?iøê¢ÖOïtÅè'¯euè§«D5š%Õªª›U—.æÇ é¬Éå¯YŽmAZ 'ŠXÚÕe¯¿üþé*o.pª³?¢\ðÈ[œðòɉw6àK±×¸ò¢ÿåDQu „€x¢ 8ªi¡€Ãú„'AŒ0¢ƒÀxþ„3.< ÂñœˆAò¢:3-¸WŒt>Ãy*RÓ`ùR¿ÿ*¾² És7„ÌA¼œ‘<ý§ô¥o\:ʸâ©××ø>Þ~m_'ê¿c÷2?ˆ\™Þÿ¢—©€‹ÅC.kÜí ööç7Žï‰¿ýù; ½ý}Ën^Ô‚;.8¾å*B$ƒ³˜žðì,~Ü:½ð„¿mRJ/<Á”¸J ÖÉ„'þÉÕûùïiŒO„åc—5(²Nô®¶e õíÊ2•Ãy”}ŸI§GÙHgDYßJ¿oR¢KŒ"£Ň»·:j¥tÝGw³–âg‘ËÅ®.·ƒšŠb# &Úi$‰èPð†3¬¾˜òå«!勪ïuå„ÏJ »°`ÚéVƒaçXŒSZÿ´½à¥¯<á­v×w®íìF†é ÿ°ö5åøt*Uþ¦æ›’¬}Ös5š2&ëf»länÅóÞ~·jÞ¿ø »|ó]û/ûÛ±W~nÉk¬ævlo' WþË?^:õ³Ÿøt» ÿ˜ùÎi¸Ò±ß®ê¹ÆnÆó'r“šƒˆèºìŒïx–¹íoå{T~1nïqºßz‘ÞÉyøÜ×ë66¢„‰i§û[Ò»ÆEùÇáz_¹F\¤ÜÎ¥ø•‰«të]ÂRng‚}>rðv2Œ9Ýj'“÷œîn ­1ï]oFðf ošyÓ¬7ÜL¹ÕWÕÃMüßÚý,r*‡îp—ߢüÛÚ]|qÑÏ$g´jBtÍ™«£þo 9lά“S÷¹-ÜìÖ•œ›¹ÓUov³÷, ÎææªoݳcÝÊ—M^ü5êwW½*kºnÜ®¿Ëèådrœ¾ñÆQ•ÅZu·õÎðsGØFWÀÞ)fYÏéÁ½ªƒþÏ¥ÿ;Aÿù½ÓôÏ÷Õõ¨Uýl{KFz9µ\¿©Üêóå⥛¸¾UËc.(Í=™õßõk‚˜’æùô?eÉ17öþ¼…š×u½¥ï¶»În¢Ï×\.æÎãÇÀCÐ…mÎÍÜvu]›snTżFô~‰ï½»³.’;æ´^å2Ú Êa´”ÃpþÑ´èʳÆßuá(~Žê9à—=ww˰ɽ÷ý3o>1§Wq´F}P®Q”{y¶‰'àø¥ŸwF;¢s郉é[½€2À nÛ:ƒº!šwäÓÿ|·Ù îíCuS£òK€¶¡«ö€ÂµŠéÿÖœDÌ{ É#í䛘Ý=ïa›{§obXyT4TËëêy$/o$gòº÷.¯yïÄÞרdž«àf"å3(nöVúN9ܬ¤979Òw†ó°M1·ó˜Åsú¸!ŠøK˜ÂÚ/í§gº+ç9–“ÄüžÓÏàMØ›Õbâ9'¥ïƒY'ß6îÔ†Wâò;^É÷òóVXÒäwy\þZfÎ )ŠŸµÎqîuýÖ|÷±Ðoô}þw¿¯ƒø‰~ëjéû={gÅ}ϫت“žaÿ´çmo {²/“ž£+„SýôÖ@O•çšµºYèvñ ˜±1÷”ÀÒM<ÅNÜ}En¯{Š/î‚ïs‡c£ëTåû¦IÓîÑÁšÈq\nOAÜ /so_b×XLU¦¬tº½úMÞÝ=ÂÚžODÌ‹o+wâYïÊxQhÄ·=¯G±‚çã(wÁ‹K[’á <^< ‚…†´#Ã?*xAiå(ú~ëÞVòbÝÊWò}U}%Ï9RŸJ^x\ý(y®±Ï…|9ï©ÞU¼è·¹ée\¤Æ‹3\¤F/²­kH£×¥¤ñ.ã!<ÚÁ?jªÔpü#Ùpü#ŽÊ½ü#›Çò8.{cÃSíæñÎó†¸MÖsðî{âÄOòžä1YŽý« Óc“¬÷×(–‰¦·Iœ8é•4é~ÛmÜ&Š„ËmØ1ýä5Zuõã- ¤||Óõã¶Ê»Y;V¢fþãà¯?¸¨– Ê€êÀ@Î8xŽuaâòÅ,½ 1¤Åyj㄃¿fßË-ò2«záÕ€Ap’ð­<ˆ¿ FÒŽĪc°Tt¡,ŸÅºL¦¼Q†ûd„‡q‰¨Ú‡s­0ãy²UNúÄY*Ézq¬†ÊgœêŠL‘¾…CU¢Þ¡ÌE‰¾庎Ðï0¶Q‰žC­¥¾ax¨-¡~0 ßw¸&~Á%éppR™÷Ãñ9‡ËÑáô·¢Ãz®Àñ!#õ_=¸^#`µsÈ“Àr@¡¹ W¬>ÙHT9òŒ„kÛHßGRC#yFÊꈴ—F1?Ìî(TØ„£LjÔN a¸“òu[Ö0‡2‡‡&±oa%HÆÞ½Õd8¦•çVçÝU¦•z¦•¦UÕN1BÂ6ªÉŠä0ÚF±Ÿ‚,¯²Î¬Ä/?´œ2™_x ^è×2¥¼Ô¯åJyA_ãÊ×±· 0ØÃ‹ g/`_ÁÇú‰–ƒ—!†§f[™SÛ!ÏØòL.òÓÏØ‚Éå[0¹2Æ–å‰ýSÎߦêêš“KcnM²ˆè&#Ú$7Õ7t&ëZvð¸â¢–g)K £øŸåëì"—ñ†ª~`J-0®d ûh6¸›âxZ]ÒS]D¯šxUÍU¥oÕÄ=ì‚­ Ô\Z5u앹ø²t¯ÊD÷zÖü—L¤J+¾5¿¤ íø`¥ÏéhJ«òÂr&Xéåšo©t9cYQYl}MÒ…ïàic[=Ó¨¨„‘¦Å²[é÷“ß—kL¾„I^aXoi‚XÇ·lÍ|ã¥ïËR§®ð5Ûhéó P³"¹<¥Ïwdö^¬"]~¥Ï–£EÝzÞšå¸LŽùeý ÿýÐø_Îýjfã’—S™ hÕ•@ ^ MWsWøß¿š*î¹}•º6ji—Í?¿ë»õ} ¤þmË+9ýgc»òà \§íœëoÍËZk¢óK@#·fES&¡Z£÷»¶ÉyîŽ?_ù GE“cë˜ý€‡’›,‘ÔªFÏÇòxÄKÑ4/Ð.h—ž„83«J>5*ïdð(÷Dé l[ÕãîÁ Ä¢3oŽªT‡4cÏ‘¦«ô>Ζùdœdµ¬ðuK7d,ñUÜ7tuß™æœõ™ü) ˜ãY•½’ûëñuOH}X#à &®oå_ew×U›ùAº™)óŽ|úŸßMWÙ=t•¯=[s;u5¸ÛédÞ¯ÙÎ? u¬quxíZÕ\Äàc¹,óÖ|ÚÍQã$¥àމ3¶ }‡ô:àˆ-%ÚÔ¸$ð.ÈkbWöp³UÜñPŒnµù-võ®A+¢yíIѰ‹Nâž«^lÝ/»ð’=‰¡ ¢|<á¶{åç¿Ù™®Sw g ¥ó®û¨Žƒì&Œ{ØÜ\®(æ5@ù^ÝéošàØßY±ÃàõŒÏì6œx-üÌzs"x¡õÆIÐdðõqß½Ýî—è}uÜ/ Ò¡©kÿС޶VŒøá€“·ëÍî”¶,Ú±sñ-6~ÿÍy±T§vÂçJ´Ÿ0ÖòfvõGbŽÛÇó¥§]Âü[íXøf5-˜Œ×e´UœÎŠxm7ï{¹U{öj³LÆÍ„jV?w©>ÞXþÙ•Ôˆ­Þܺ»ÙüÎ廚Þô’]pÖù™;?¼휴ún7®LËú CÒ¶³ùÖ mÓÞÌs5ûØÍÔî9œ“£õYe(Ü©Ö4—Ó¹œ³é1ÝÛÑóþ‹¼TS„e²$ˆñZ l6»çräoâ\Žüž‚oàñðæëÕôxçw çØÞatjì~*h좆à9Ä\Ó–Å–Zw=üµ·0ﮢÛ~Q2çæköû—/=eÒ_Xñ÷¿˜5¼üº÷üpÚÛ¢¼ýGÎ]ð9U?øÜ†Cåkûeût¯c E£Ê®î–šEò¡ú3`3© ÏñÞò—x× 8?Å3÷°_8¬÷ÜdûlÕ$¶ä\\Û¾ë3ì vÂÁzÂyÂ~kœžw]²Úí­Ú3žßèx½óœ>”ÚzÕtxÎߌ˜ï‰ÛCÞŒ“£º ´ºÖ+úy¥Ú‰C;©v²þ?Á+­ê9-ž¶M½A¿H±ÑÒ17šÞèZ¡ñ­žƒÁÅ×\*.ÑÀ²êŒž÷™îõÞfi“›¥,—ç ¯ëå’ßúŽ_–`È«{ÀŠÜ wT¹×‘{¹·’ûrõÇõªËÑ©ÂS§N•É…æuÂñÊ7Òë|íäµÜÎÆÞtð×%Þét€|¼}r÷¥™žIA‘^¤8ÙkÀ{*©šÙsÚU¹FÕ:›ÉuêmUkŠ\^£ª¦yõH^;#^£Ê¼ß«QeæG„Ðdü!£NêÜÙ7¡€ˆÊhy½S9s‹žª‰Õ½²ÆjðDÞý|œ8÷Uâw¸YV”Ô'è 7Ë-¶îJÍÔŠ–Qÿ11ë£ÿd§ÛÕ¿ÏÑôÐt”®ÀkÉL® Ÿùúѧ%¿£æò7óª¼_š·Â¬YÓqDq:Z‘MàÐØ áÝHgÄ™XÁ-<,+ÿÖ©H =MÄ@™OQªMÑ@©HiZ4š¦;&¡E>ÃÅj1‡Êƒ°üÂä ‚é³#‘ÇʃPuÂRªLèÄV\õ¡F|ô‘#e¬ÙH™ 5©!¸kÀÙò®‡X̂ʡQkúsÇzC,sõ oÇF™lúXXÙôÁ…™Ô§¾žMó–Íêw³áEÌif1Æü†£7Å.eLåOuôµF€ËÙ]#ä‹Oøp³ÐªIߨ|$•1#…vF¢Wwm¤s1}£ 1Ó³¹còަpÕF‹Ó¦ Æhøï(ÜŽf¡h»?ïð÷¾?»äûCv`‡í/ΙvÞþß'gÌr§6­o7™“r±°Ncu®xßêÓ{‹ —ÍÊ̾Y™ÕǾ:¢}•M•za¬ËX ,Ä‘©$ÛMÙ6ÊîÙ6–íˆñl'ï?™ûª÷Ÿì••=Û ÅdÏvòþ“kž“= ‹½`YXž!å7‰gaeZWd†+BŸZLªx¥ZR_Ê…ßY`Ýcý¸Xÿ{¸[e==Lrªq˜2»ÄOZjí[‚ñ”òœr³N×JzÄ•Am2oœˆV¹zåouŒ _q¬¦•qž%¬[â·æ+5ʱF•1æ?L¹>ê_w7­tšÚ95cäÕzS¶*ÊÑzv…bÎ)qu^[ÕçU+V¹Ž«-F$,y–÷. {¯[+,å†Í_ÔöÒ(§«¦ŽÓêÓKGáz¶|ןÇÀò½¢W?´$û&P„†ZÛß¹°Š ¬ÑßiE­Šk†È½§nÑ}—þí:oŽ/Ö  *{ép§¯‡B°Š•ózmM]ZJ̼†ß©1ñY©_‚rß½ ¹áÊÙdÃ@h£ÅÁÖÅl˜l—Áæ²ÏO1ÃFý_‡’˜³iY¼ÀÄ»Þ]ó´èš)ÃRï{ýñ9êþmoø§ ælZ–N8ÀýÆAÔüãËÛßûדýžrÀÚØ“CóÊ6˙۴,ëZa~¥K^È¿"užðË)7¼´ ÿê¿.±œ)SY9ÿÞzsC´gÖº=³d&0zÝòϽ:¼ß~Ý‹Mƒ®'¨†½±Ÿ·Lž`´5°?^ï2—s%ßêØf‰ºq#¶Ùý=R¢žjöX±gæ-þÎ3JjKß«‹î‚ÕÙ ½Q^¼4£Ü»I×Vj™»Ô® «.հć) ¹Þ ¦Ž«:—øURß5*NÊë.ó«ú/ó—Eç ØÌ;æ3õ¨o†¥ o{WÌ^þ¥ökØ —Ë Œ¹`“CÿSöBp`£ÿ9{ár»xÃú{°5Æåv‰¶9ksðp|l’zcf´ƒ§¸>«ëÅ ¾zìÙ ž1ÕÉf 7¾¦G²öÀÅŸo±#OA¥ÜìǶ‚µq¶c:¢¾,…nÕwNPh>‡gO^7õ«%œÞ0¹û ‰’Ó?6^žM®sºjG ïŠöîëàòŸ-¶¦©;QÚšëžÏý|h–»rsÞ´ê¦;+•—}jr:÷J[÷#ç›6ä¤g[sw¯ì›³«`°‚iö1î|À í9GÝíñ³@NáÄe(£…a6Já|šS?W£~n°„Xú6êçúVMKzY×7»·ÅSÆŠáÛé}0G`Yëí¼Å8 (Eûr÷Þµ×?‚#¢¯¨>§Î˜á©8º&Эۘ·•±Ñ³·˜IOÙ?\~½ªY=› {°Qé•„àxur|)¨¦{Õ%å¨Z¤ô¬IÕ¯ 1¯šNÌ+´“ÏÛ„„­›+9%!_Á3ŠÔƒB©õ@7„‚÷)¢¤6'ɱ.£Uðv,Éá™›ª©èsóìaõ£è›+ùštOmEójRêYÙ3¨Äl)µù . É;K§ÅÃUal­Ú›ˆx–èÉÀSù/o"b§ÜìTö‹§±Ø±eÛGÂ’Ñþ]ÆM¢¹û¹ìÚ¿¡ä‚¿;¹û ÃKNÿ滺"°iyÿá]9ì»[Æ÷2»k<½ HÔ«láÆr¹v©0éVaÒÉðAì­¥ÐM½ºµÜú´’ÚTU|k)4êa¸©b>nóÑ`Zw•÷ÚÌ zœc‚u bLFÃÄ´î›VØíålÇ­á]T>— â]ޡ̺›5ZÅ?A‰´—1úêT"ÝÓ‡>êÎgjO|?©´5LÆáBªægÞÜçAŸÈ‡ ƒc]þ?™Ÿ·ž=ZÃѵ<ŠF§ÅÁv>zØÃ}ô9gÜnáF%›Æ»·VXy;ÔjÖ~…A•çZòí(‰Žº\úBÞMОÝ&·N%ÂaîVK¨yi¸[-%Ç’Á»Õr- w+SoŒ3‰ïV&Ï\;ÍeX¨wÅâh?ÇÔµu澯[yþÆåqµ¥Œf{Ýd÷W˜Ä©ÂÅä½&Pl&°÷Øv‡íƒ¸î°[ìësŇãcÏqwØ-]ç\—¹ô}°ãÜ^K÷HÇ^“ ò{KNŸð®É‹¹õ¬þì³Ù¸>9G*'‚kΔ9È6·¡mÔ².}¡\Én<¥›¯ízù†ÏŠÓî<…Üç Ô"ó9ä^öxnܶÖå¼Éå·ìoÔo·¤Už‡zF^˜û2§”ynæR+Ô}`Ým¿eÔë Ëä·ªû»öÊö÷ìj¶•§ ×’k‡)ô†Ô ûnPoŽÎ`Ž…+:nPûÿóÀ ê´?Ü Îv‹oPnÛsçØmƶg–à ÎïF‘¿ÙP•WØÀ®¯W…•>9ÜŸ¼Ò'9en?±W|!‡WÊT}‰ÏÝ©(ãïOÄ|o+̲š¤ìQðjšêYÁ÷F÷*9òÈb¾nnK>Ÿê(y‹¾êS©8so+ù{’úTò $ä8;so+ù;9¼r'5å7­Ò]™Xz¯"æmü*_9(“T¤ôv×Ѩc0 wõ`øõX•Œ©JC´•Ußt( 䂼z Cp%W¤¯C¾+ˆ¶25X’me»Q+hE1¡D­( ÀâkEÙ D­C™ƒµ #g™[ä0Ôp•6 Þ}™¾ ç™:†ë½z6×(eú>eÒ2ýϺL#¤8ª¹3ºÂ¼ …>Ž0%ÐwÆÞïR†¹j5º ÿ˜V1€Kh¹áê£a gÊ0Ðm”moßšz5üº4Ц|sU×rõ¾¬ú?Ýæ7ÊyLÒ·æº÷S'4çûÑGôöƒmO%ûýßšõÑÚ6êûh-#ÍÍþâÔk÷W'4ëûCÐD×` sžÁö ûc 7ükA5+¼cÑÀòîX)JH=v,nñP k~´Æ2_(ÏŽÅ+EÂ|µ1 môKºmì¦ ã˜o¬éŽc×x3Žz ôasΨŒc™¬èm‘Ð+öÅì·"{h„½T¦!ȉÝ ÌX™þO@qÉ¥CɇW±CÑÀÍß$êÀJî$t$*äš„D…ý7 ‡Òm…|“¥P‹*Ÿz×À¼M†ÛÀ¼ƬžÓ;í«Ã¾ï¡Ã¾Ø¿‡Ø3Ùæaú³íÂ•Ž¢fíÔ ²]ƒ–lm× Pa£è|d›§¶÷t‰ÉMéÖôbk/¼)Ýì:Ù ïèm«˜à•ø¡ŒàPFðŠ (#xÅ´y½b*%»½¤vu¬˜PÈmáRbXÌ+±núô7³h”y+{€/̼•à§oáúÔZÿMßµª†€ ÖŸ4}ÛÉÓïc@ì 5î¯vš¢²=«ÖÂ}ùݼ‚P˜­HÝ.pP¹Àé¾^‚4kUÜ Rœ¬]VÓ¼¥¾\Ðài¥ÆDù_¿ï¾eß Gœ†G^‰žÚ üÙŠâ5T3=ʽ©tÔøqØÁ} Ký/·lžï¾ 4`%TŠÍ·öë]Gi‚’P.ûR †J@/qj€|á´ .µ Hà…^„Fô ½Òy-Ú½Œ6ÿ3ÙG2‡ÉØ‘ ñS¥ýÀ€ù_°°¦“A? ¿%#…“hóƒÀÞ÷€%¤Œ ò[e\~§ûåaw½K÷âè¥#æÞüÖl¥lç ~ý{Î=ý ήѢÑå«ÏÙ?ö ´ÒÏŸ~úšÓ?6áVz7oÕî—¾ò› Oú¯ÿÉm‰]¾þ¬†«£‰¿ž1ü„é£-W%oñe®pÄ4Ž‹Ìdý¹ÎâË{®÷Ä´9²Wª,7?;CØß¡˜#K"ã˜[J;›¤l›Èû†t0\d2ÖV‹°fH›Ê™¤ ú^c6Êæ+—¬1¤™©ý.jÙæ¤%Þ™±¡’[5ƒ¤b¤õÐT²DÐ_iÁäÏe÷ ‰›_ÎDTÙjD•-}–N²ƒ»!µ82ʦr}ú/"ÝG¤“¬.ÄYG<@Vp‘CRÂ{—ú"ëŠÄ`ÈçüY÷#tö!%¥˜¾9I_I®Œ·LÖÓ7Þe}3æÕ}[i>Ŭ^&ÑØaf1íÛr€U‰ÆGûP³ÏÖ—œ×Š=†M–]‘åÒÜ}ô,·Ë6Z;‘Ýä÷$zÙŸvËMÖe`‹wØ@YDŸ³8„jkñmþ Å·yÞ^n·L&ÒŠ‹¬Ÿfg¦ÒŠ"©Î%HBÖ–,£¬°Óÿ­‘YhÁ¢šd+ë¹ÍþUM^÷Þå5ï'ƒNŒ,£ä©ª¶àTß[pærÐÕ’æPÜäHßYFS¯·Ó6™ƒ—rMu¤7öµvª™Õl_.*á8I1kä’žH3Ì“b p‹ðKû~Gõ\> „š÷ƒ§ª„c^BÀÛ‘º;¥ÎÑ£ÉI29F¾ô3ò¶—?æ åÉ!ŠÅ;kžø¡CWJê&Çš@ööÄfr|.C°I¼ä­Þ%žp¢ÜI ê$g„žp޳ï 1O˜Án‡'·`‘Í÷R9RûÄ<±œØ V«6D!ÔTð$sÕTðÆ5USJÂÁ‡'–c™cÂ6IèÒ]>qÅÝ9 ¤^ŠÍcI(†xâxàÿy¤oK† Óm» ÃLXTš®ŽðHY6JP#M) v)¸°4餪v“ާ:7ÉD‡ŽçMªûm8Ä’¼_?©X¨#ý fà«§â ^û›fD°¿ä0À)õ,c|¢€®7Ч‚P0@òxï×ñ«©ÉÊz/òÁ@ĽñÌ?C9žø[ 8¾"O:ñØÑdÖz±ªal´é€>Xï…«“oüƒÁäðÚ_¤÷ƒ! EHQß! áb…·ýV@P‰­ßJxÜoíŒ/C­×»ý=(}ˆGbÑ>L”“|vz¨èþá¢êV~ˆçHŸâ9ÒÐw¤GÆ0;ÒW%/ÝéZk§wŽèµÓ{í§÷ì…?½sd·§wbçÇeÍŸÞ9±ûÓ;ûÀŸÞé½?½ÓOïÆ(±é {ÄGýÞ›t3µÄÏKÛYˆ²OÊx_ˆ² ’Ë“Íö²)èŸÆ«ÚW¤Ú—5´ÖµEß܂̒ÅE5­ ø½—õ²q«Þmõ>XjûÏÖ+¾g°­ÛD[_‡ø¥±»‰šuн÷Ô;iÍ\Eñü¾xИÅn§må 7žÓÍë›àH®Sm)ÖskÌ,Žôyi6ÿ!ÓY›~adïu/ËðºÞçë%}_ÇX㉞ڻqÒiŠÀºSýÙ²XNÏq Û*)U7>)ìù¼~;°¿ü>–Õp-H}ÈÀ*ê'w´üô¦gÎeh¥Í“ßÜó5ïŒÂ8FlšƒÁ¹¬ï\RgÕ¶5µ¸—\…{É/Áñ.\ÿY±;³ £´ýó‹Ó¼m`wÈ]€\¦ÍåãN2’Ó´³NËŸ‚ƒ49Ž@× >»×ÀÍÄVçž2÷igÕáLâ-äÙ¾'yä¾¼8^ír½.xØŽ×mRí z¦Ø·º¢cÉ7¯ûœ®ÄÙњݟŒãðfÞ4ËÝÅÖÅÑ!UµÏÖé[5Ö˜0û:ŒN?gœß¦0—ÓÕYË äž¢ÝçŧupaÚ¯î³Uù#wÃ$ü$ïÀ­ÇŠgá–í§V0Ì%ùwhW?ócQ÷KÎB?#­ékqMÒ‹˜»{”˜È]a§–ûå÷Ý^Ü“ä^¤š<îyN÷l}áiI㢡ë|Ã/¿Ï½üR6¼²Öð‹ƒ_Þ]sÜéÔùöü)UßEohÍž…]µSZºj³Îb¯&¸Ba·¶jÇ‚»‹}O¼XÚµ³NüûàL}4ýÚáL·«ØG_±¯;7Ïû¤xfÛ<£™0ØDß›0#`}[<“,vXÅIö=X÷ý¨{#¦²}ذ±_:÷u÷kÑ`žmƒy¼«ÞAЙâ«Gr@3Ë;pa\õmú¨oÓG}Û}Ÿ]"jüΤµØw¸—³8ÊÒNÒ½UÅXš°“ΤîNŒ¥7»1VþæIŒõu7c1{c-À…­¨_9Æ:ÇjìÄXÛ4#¼i‡_ïÜŠ5—|“˜ŽƒÎîhWø+ß̱۹m®â‡<-~xŸå¹;ÞNÆÁK{:·œG™Ÿ=s »C hö‹Óø,uõð~0FŸÿûÅ–h÷øpwéír™e³›yÌÃOáTïŒÇ®x,èîy¥)ƒ®áµ<ˆyüÆJðx üæ)`6¯o¢XÁS+„ß A˯àûA,whV¸5KÝÍó®!„劋 ËáV¢Óéì\âkŽI¬›0 ŽÛ%Pñþ¯è§+žwß3}‰¹\öæBC˜‹+­¹œýß’½—;†ßq-áf0ú¾–¬[8¢6é¦4y!ÈÆ¢µi'½: úÜW.þA'{š]¹è¡ÛËÛñú?7;ÞÆ'˜s¹Î<-½yÜæ[¢gÞJ<¥P^Áÿ1Ñ0zEoÇëÓ.qÑ)±[ò¡Û¤šZm λô«œã—Gj6=ë-ùSúègWÄVsr½t Mo¼¶YgoônOoD!1½±ój{3ŸÞ<9ôæ)›z]CÝ%êÞ@M|·.ÄѰú}´sˆ©¹usôÎõ“5Ÿ5͹¨ÙÔ{ÛÒ÷*«s‘»‰uÖõÄœq×Ôïê2¥4²Ÿ‚ƒšhfòbvL‘nAàÍ-HïŸÛèHÓá0$)ôŽpu7£ŒjæïDPƒÌoæ¯Íø€3QêÉS„.h[¶|ÀÙhêad³A·ã *Þ`nBxÌ £ñƒ–»cˆÜhhÞ†0k¸L‚ÃevÈ,ЬAaCã§U„3Ír+3E‰­Ü­ñ22”ãÜc(3ŠøÞPæm¨¡pp›7ŒÙÄÁÇ0½W]ÃäœY8|˜\¨h†‡‹Â§º†Ó–ßpîqPø†CõKÈÃá9p­ÊOØy#p⌆Ô¤$p£7ByÔ·ܵØ# ®±+F’;á>;RÔ?ÑG²Ë üdß&ôs$´yvÆHrá¼y$·6øHö$®õFþ(Ö¥wÚ}£ôN»oÚXêÞO— Õ½ŸÔâĤپ¸ùíÇþ8Z—íÂÑÒ$Rn$¸ŽæÆ\sq"Ð(^ÚD£åÈY;pô0™åýOuÛÂ(è¤NY&¦74»l;¥®NR<69egìÛ\(¬Ù}DM™ã°å»[¼ÙVîd[H¶¹ f;.ݾ&J$Ûxô!ÛqtÚlm… ™m¼Q~ãM°ñÆÈAŽ(c@üNÇ|˜oÆ0…l¼±|‹Ì9V¨SÓßVÆ·&³íD³ßÀZicƒ²ÙÚPm“›á´q°b6Ã8D pç2îïãM7ŽÍƒÚÌB :@*hÚx°±@G% ­€kH«êV§mq 3‚—•!—ŠÄÿ ›ï@rƒŠä ™°ÁÔ†SÝãA [l¼6!êU/7ßxjCMm¼6¦6÷AÌð m<Õ{6Ô±ÒÆDÅê/âDfºÍD¥jP™Á—¤[(ÃOLi†ŸR”’z’1œz’ɰ[!`+ïtÈmÉ£ÞÝŠ2.<ðNàh¦ž<êÝ­À_óNU§+…§ÞÏ…éð(ýƒKvAšQyY”ý÷äRUeÿ“uJÉݤ$ŸÐLÂ!J­Ø¤\ãÞ,2µœøÄrþXV¦Z’¸Ë£…—ýÁ'àoµ&É==ÕRnÑZ+ ÿïB/¬Ñç´ø#¦C•œ!£'›Û›[£¬ãjSÍí­©Æj,>g¥3¼RŒÈ|v¾õy®a)þ ®¡¾>ÊþM[ÍrD£Œ–ÒGõyn”û¯d87Êû˜ÂÊkm¤Ä5äþV)jMÑÜmù§„•`ƶۦJ,+2ŠøŒ?T‡YïÖŠò>ÛÚÔ«µxzé¨1î#¥£‹G£)Õ[¿å¼&﹟ÐÕ'K” eµ )äJ$Ø×„ZþA€“ýcߨ&? 3zöÖ!«%ßÝǃct×2°–ä{º€[æn«'C€Pû‰œ¡Ž·¹Ê³ú‹ËO|«Ìð¿†ké ΃‹1ØÐo`Û$Î"s5C _¼ÑØÿG¡}>CGÃ`˜9‹+©ðÝ´¨m¢e´Q†BnG7j±œã[©Cô„dߢH$g/„^&J§ü³yÃw3´© »½<¹£hòNÊÅe1-¡¸X5ètûÞ*{ãÄ«rÔÇâd«i‰zaj±䨅PÓ¡¦Vz@-mé÷—SK!®¥p›õŠsûµq£­¾Žº WÆu.·í«ër˜š  CmpT7…ÎM¹·æˆþU8Ár/³Yk¶YꘙÂXëËätŸ÷ÎLa˜Í+)ú =êK’„F¹Æ¿¥æm7B­ø(wg[‹çàªÜýî¾H;#5g7ß©­@iIõXµ-ˆqOÔ—Éü)Vç9Ý¿¢¦?î¯)Úïî®Ó1¥¨ÃC ¦µÝcµ©FS›5úmk[Å<½5§SæÌè·Sb.î„~ÃüK}GRß¹µ…0‡ÊµLoýcŸÙÝeꋨÏÌbìMóæyÝy/u0[Ìb»£Ú©vKkKU™¤¶*[ûûVGsÞ·$ºÆh?csOƒ†éfóãRñ2tæ"ôƒˆõw[÷¸)¦mвInõÜÒ6ßUB†e‹CJOÌ £m¦qÑ6Ew1æQêC`F¢5Уþw=é>sõ´ÿ¾a&—7b&P_v@}fÙ#Y.qÖáEµ©¦–šV'1˜ÁB£°ô ÚÓ”ÁjÞ"±œvWð2ÛèÃxÃÁÄîÈä(zõ$b£ÞbL:Ô‡d]deYg5È Xtèa½†V¼C†ÛW@GcO8,%yDïîh_Wîöκ©àö@÷ãM×Ò­&ƒö6•x‰Øí­öuhÿëMûºR}O¢˜¾Û¬OC×[£vNµ‹%Ñ¥=P†ÛQ+ú7›ÖAM¾\oÔ#h˜UªÙU…]îö{Bs½„¹žßk ±:Û¾K'h¼Ýì|on¯®Ã4ènµÒ0ç^Öœ9ó´H×~žƒQ:™wÛÜrÞì˜Ûx²n•nn9z|/"d—á_0éf÷Vo„j”Ä íùE!¼Ñ¼¬ñÝó%:ÏŠ‹£r)ž©%µ1tÁZjÚ G%‹'ghåÓÊÝ]!ÔnŒbº{Á\ÑÖïpûå½ÈvÐýˆ.Y¸~‚Ýt@ßnª÷˽©î¦;~¿›Îf7-0,YÝOVXí+Ñ3ÒØC»Iÿtöê¦÷¢ÊäérÄ<þ`y»*HxJ/»Ëz&‡W~S,•aÐîØî. zÇîJ†ë ïvòÌ~w‰v §ÈÕi¿ECV쮥ÿ{w­ù]/” eÓ©Oî°÷Ú,ôM°Ëb—}+*Lï2±ü6ÛCWÿ¿û,5ÚIÌSJÙgwn³žöÔ)¡±ž V ØØË´Ï¤=¢/¾G±D[*AÀûëû{ävlj°ôўͳžmz¨g™aÈñیӣ´Ö,£í”]­– móïí_!’ô1{0EM­ê¸¾¶’Ý×ßs¢§Æýµ†ëöôа¿íÐkóéµ·tAl‘õŠngß¹Õû¾Ókßw¨Äì P´}÷ÿìõñR-—ûÈNó»^¾ÝB_|0üÀnÉjÜ¡C ì׳‡fÏö¬k·@×Û·[è™ï$UÍ_™?nõý»E½›Ð¿ORŽDÝœìã»E»Óô×5¸§¿çÐß°[<æaÿøÝ™oßn¡×žÚÁ»—¦nóXš:”GOmÇ”doN;S]9÷è´{¤+'ÞñzsÚýØ•S$Þ½9-–èʉ=¹Þœ?uå„ Ú›ÓÞèª9HÝ'_7u¿ ¹ùê~IÓŠþ,”|u§„$ þ²06 ˜ ‘TÑ~ À²8SâpTTµ˜G彸¢©·¢BîZsE´nÑ™+ä[tæŠ,x(gƒ"@6 &µ¿AäV½iÀ"dÖ†/ñ-úo#eÕF™€½¹Ú}ÌÿFdR0 ÚˆÕ èÚMå±µ&´™´´r]¶d±Ï\¢§’Ö~И1Ú,ñm:cT¨¤¿4ÕÛþÔ iµ¿È¨Pù5˜†@¡c ÔýH¨cdÙ×ÌËèß@È·(¶DîòÀ@ѳ5S˜˜/ЃÌ‹BÃn¡¦óÑÂ<@»„Åh׃°¦ÁH ’% Õ9‰è׃ Í©s0±"uB›/Š6/Šz‘Y í»Èœ‘E õ|o±ˆ1Rq‘C ò¢¯ßú*Sv½×ITTúl²r227gãŒ2 É53÷Í5£þCtͨÿ­}I±öi£š†h·>Y€Ì°§'ÜfÆÞ3k!Th­…ØšÜÆ*ÕM4vìÁECe?U“1Tbª|(“Î&¦Îi"†‰%(bþ0ÉYBü‡~­M2 vÂÃE)ÖÔ×-H®á˜ýÀ®êpîl®áŸŒ{7üónÆôYôì°KŸöŽwÔåçÈõn8›‰~ÐŒqB“Å{ ŒŒ!bQ³G@Ùf{bGaŒ‘!Peˆ`\d$Œ¶ãHmIQ¼G"2\%sÐÊ1 ±,õ’€†¶õ¨Å[s”4´yöãÆ€Æ~Ï{º®|T©²»ùgޱdŸÍjÖS¢Ý=ÝíyzºŸz¨žî‡@=-œ©žŽvVOG£§£á‹z2Hk¤ €ý`”žî/ñõt 9èéÑqTטš¸·c@ÐÚÇp=Ù´cáGó&Â’1›uì qÇ¢ û?{ì~cAжÇÒöÒØ;¬6‹ð¿6Ñ¿•£M\ Íj›„)Ô×¶¹q®6 Yø\ê¡É…걪o{=ßPú1ºBND.´ÉÛ´Ó„RÚ¾m5HÜ"­34ªaœI Œ3Y‚qî^nã„«É!BOÆ •©¾q'[.]¤Ó\š%“ !õdœ„:„—ÇÙ>' ¯z:Q zr€Ã|ƒ1Qš»%ÊÓO”çÛå!Æ{¢¼ªM‰ò O”‡éº›(_™³…)õI~½‹.ý{”òÂ+:šÛ:0ÞaìÚ'Ã3|CcC3L{Ç ¾ õdb)Ó<TÎ\ç{öù§ùœêyçÅ+JGåžö{NR/·¿ð·©š:èëd²§X”ªãÚÚ(K…þSé¨#Š¥9°›\"|eGí¢–ö•Õ1Y½›¿ž­¾ÜMNúZ,/5aB”û†{üÅU¥£ÇÐä±}çïâj^ÉëÈ÷˜‹·»R7¡7`Â/ ÉPh«WÚ_p9Ö76&—ºM¡üÉþSÇWîzÝŸ°\ ]ކØÛm˜Y›©—Ãøs`uÜÏ‘'ä@BÇç°ÐC~7ÒY´A„tQå†ÑtÔv£ü·JÖ{.׎¹Ø\2|A3ïà>Ð9â±í¨‹Ö•äôôœ­“cìÞš ZõvN×ð¿HLµˆ›Ö, 8{Í ?“1°ïù|+p᣷.ßÃs{Àd¾ôö+ªo¬mt8!à,Š„+«—2åÆêù\X½å3î«×ÿƒ›e'ÿãëÁ>sågŒgÜuuwk.à½x‡ïr‹ÕKÜø®÷}co{ 5{^w¹ÎþÐßS›ë78„7¿´·?“s†9‘³YGÒÚ´ÜÆÇúexEêG{èzÆþ÷<.zæÝ|tÛ¯¬r‰è“ïL ÞJ¶ùêÞž­Xœw¢ÓõÁÿÝ3@yÞ3ðH½g\J÷õÌZb³=CîWx.æþØÿ9C ô¬I=ÛäB®_`£z¿ºùÃô$í—µ×–ò‡éeÌ=´ÿš! fLFŽ«3ƪ÷¬›#Z1˵=ƒKDÏ”¢ÿ÷‡$èÙÆþžùê=«sFCÏ,çÉö Î-0ã^|àlB~<·€%ëø [¢¹Š,k£Ã‘ðGÍäï~è¦p™;dÃm1xs#,'³Õbàú‹¤‹q‡o°ü¢Å,WÎr aÍ h*Ï(÷ÜÈ%§}|„9y‡Ë]ÏŽ¼è]UÑð‰'Ÿ=Æ\óQ-hÌ9‘àÄf‹1ž' Ço²Íü²ÎÙR¯ÒÙ¢wž¸çgóXŽÜ>¹’19™ƒÞœ×uådŽzsZ\Õ•ÓÌáVÿBNæ¸7§Å]9÷ÉøÚÝÞ•“=ò$Ÿ0äÜ'1x‹.§á2ãu>!ï¼\0;¶žƒw>8¡žƒw>ø§žƒw>¸®žÃI)›`ÕzÞù`ðzÞù8Ò±9؇õ¼ó|Kæ©îHçkʽK4‰Q+´Ü$6–u5¥4±õaÕ4‰!¦«J¿7ÆW®~oN›ê»/-fÉÿŒËÄÿÌ`?ü´Œ…g~ÍØÄcRš%¹«ÜÍÍqmÍb‡úb™°€p¶ó«–ãWÝl‹t)ëÍf”IA“^2ögì?bKÆþp5ÉØ_B§d|e|ÁÖŒB=&#Œ_²Œ_Ú’q€ñ†ˆS¤Œ¦ÅLÛš9Áìt]£Óÿ ûbMåÜøí@Ý]á<)f]’5yΓ¿óšõá9Oäñœ'Übƒ»ÿçé>ïÇøÙ¡aÏì3šWÔ»Ìè[ß‘6äqdIÙ¬QÖ7âàÒÑU˜%ö1 òmqlYEúÙ² ªü„Í„ èÒÏ»Ù;;òmé|k;Û[kz…Jƒ¹¸&ž0gF”³Ïý'ÏNØm±Zæ–šÚSÄ9¿1µBIsêVe¿LŠ•!‡S—i˜MÖßUòLžC6&W8zRáxUQÖÛ2gÌ‹!@E9 {…ɇZ©á9¥¸±/|¿÷W8¥tôFg×®(ç-¥p— {ö” ï(CM"ýg›Âß”BKŠ?’9>Q '©òB7&ç6·c…îÜ%ɨàäNStB:iRjJ¦†¢ãs3MIºCÓ’ÊÞè]™Îoî=0δŸFdåÒÆŽd”sEéX½¼7á@õMà–G@‰ Vlº"ÓÇÚóÅøæã¼ýc<Šÿ#µ| fïEî()Ÿ+ÙbLŸÃë(Å‘ô9 Ç?¥£)›uŸ®O˧ÑkÈe‘hÓälÔjcár”ÅÇÌSpžðÏE㨸SAZ¾voúG?Cùs­ã칎u ñø èßÐiÈ "ü¦Ãƒs?÷ÖFcÌqÃcöxö^Œ&‡œ}ý¬v ¿õ¼ Açù§1½ìEQx˜ëP¥`5sl}[ƒÊRR¯ÒÝÔ™JsÐ,Û˜êŽ]fj@õ²_K‡©+s¸qéDu³éüQ½š®?CØ‘X°ŸÙ¡¶¥n—v&“Ê}ÿx¨Mm0“¦¶ô˜\K'Ü=@Üb—n£O—Þq«é0aâV0’…d&ìê÷©Üâ:06™$ \ BøÝl „620Þ¯Ñ̘BDËN‹ö—3¿`h'òa¥ë©™·~}øäW3xdjR.|m“2á\xâRf)ËœŒ˜8 ݧqøZ%¦/nÖ;§ŠÉ _L&&ÖÈL¯ŒiLž8F)ËÅŒ gn|7WÒô†v·ù·˜°øž’`ôÑèàGÉîrKV¯ÉMb§]qaŽu^q¿TÝÌ\9>iD‚ôR*1W1bÝW±HJ «Õ%m¢."hÁY‡£L̨È`ƒÑÙ‘w®‰^›Á³Õ©Â^nøï/7ôÀ_n¸ÊøË \A¹ ïy³›­þ¹,Z’ÇR­×Ÿ”¬nîH ºõ’xŸ7#Mþ:Ç/T—Ž‚©ü™ß7©O_[Ià@¡“3›{[!æÔw;Ó4ài4 œ®5 ëQÀôfWS¤Ñ瀕,S›6vÙq6>”Õ³ÞÛ6òÎ$çÂ,¸µ8†sÙZgþÚiß5Ob›Áۙ˶;óWÎVѺ^kGWœ–]8ñ¬(1‰!I­ðè‚)û9ÆÚÑØmgþÔY;Ú™Ñü#§9xÅyä~Z}ÚšÖôÕèòÌÅÎSÈ“ÖH¿¾êjœ¼±Fןjê±ÃUÀ2R«³ˆ2µ«%»s@ñ ¬QÏi‹ÇaIåÌ„·†­½ˆÜ²}f÷³@—:§•ç0Og_D-zw\w!ï¶dì‡Ëúþ™f}ÿLbÇYì8sÞ8¿[Æ tp|¶¶ìµRöiÚa,K«úKÒelçî"3ûîSi›BÁ~¥z傾ÕÙ”-cSÈæ°6…œcS¨Íl eo®õ¹KÑaÍâM¡Ô¬_e6…Tw°)ô£~'·ß×ïäzÍ¢z^ÄÚýMéþ]mÚxkvØÐ¹±thìæÈŸÏqfl5ÛKÖ>Œ¾í%kFßÎöÒ9¦;ÞÚ«“©w‹ú¥7S­WÖ‚‘í•´¿cÙ?boµ•pj;ó–‚)âµc,"Ëßnºëkzµ8¥í½[Þ¼Ó©Ãpìl £vàV´=Û?G½ »Ï}×öîÅ¼Æ kÐ.l¯ÍèÁý¤îÞZ<Ðõ"2Íù­ÞRNmÆ¢›œíh½Û?XÃù×ÙfNõf›Õ½Æ´ã{ë<ûÿ·CRMÒÔI¨³ “Y^>«^XÌÍ¢t1:ÜNœìUÍtèp{g‘|xŽ$8ðœ !ê-äð.×ÛNup±×±+Xaò9°¨ó¹ûf°¹äm1aMÌ['æ¯<ª)ñö¸USâ5¿Éím.a)·¹$›b™e1oד7fú—j‡«o\9ªÚá^³Z9ŠžWNßÕZ ý(z-Uõ£è{£w%oãLïJ•Á%¥ç§wó’K×)Þ}½‚—÷äõ îð÷uöžp=i¯`ÔÔ}+è&ñð¬ŒÑnhe1«tÅ0‡±¸*bTên^Ñ5L—ß šy\Å*RÌv«HHEX£"ç‹Úû R‘¡AZ(zÛ û›n ºÍK?¤šFRÅ*V=MÔl´ôĶ2ZzX©Ñm¡Ivy”¿ 4 ¢4Á>йvô“ò»Þô“Ò–”úqâLè|?³ÉÓÌvÅJ3}ìR7ó»ÔØõÆM3y w…fjKè—ÑâSý0Éê6š|~èÏÄc¦¿Y£†_z5šþ²4òÑÙk4¤&¢y€=¦30l´øØdº&¤7X¥ˆ6AU´¨„a•f ¶ÁFŸr£FÒ±ÍhõQ‡.Å-ôŠCU v†ŠÌÊ ¶K‘D=E¦}%šÍA0Æ0ñ6e“"5Ö¶ÓŒæf€ß`\©c0})Rû¸Ez8„œ¸±r.ߪkÆZJ( á~Tbî[aø•¨µ•|%úØÊœâТÍÄ}ª+”îëCŸ_C‡NŽu;ØK©¼\Úk¨± ”¾%R3ð]‹fVkR桉ª'y&jå…Uõ#Êî²Qz‘¯A-æµU_ƒOŠ?ÌL‹ ˜6Ê­.³ZƒòV`2»8»8þ¢Û7ËK¯?v脘ñ×¾£DV—»šg¦]TZ_ .\¾ë f5”ø ~ Ö×%«—¬¬>)ÙšÒKs~âíå»*}œ½s‡.–Áç¯ä6^Ü]܉±9C.ΈK&²†äÇøÔè˼ÒQ£FEùGo^ }\ÎË,ß¡±”Ž1°ÂòˆvÛzÃØ}&Ÿ X.ÓÒò(?Ð3œÕ~hl‰ÚÈ*öp&O-¥@×0Ž+Ÿr/!G"Žsá@ÝúN99æfŋֹãΜû‚±ïhÖD8'ÜŽbÁNÔ²©ÙÒ\È3^ ÒH'a憄K€\#0†¤háŽD„8îѶsŠ@ h›;q{'ôH߉¾'#aäÞ™¸ryÒPúFßQè+ð‡ßÙv¶Ò²º¸~Àg¶ë í`6¾º^¿eö‚LÛŒmûãÚÛÕI±)}¢´D'ÌÊ›øÎUôê dÿkoxƒ,IzŽ»uUì|­Súã¡Ù½ÉÜè!5¨¹Ý’l–â z}IFވ饼€þ ô§$bþtFÌ[Q`nwؼ)ŒŽy¿;Ì»•-°s%Hƒb&§¹é™)h :#lG¶ÃÌn9wEì:7ØW`F›³Ka÷ƒM•¹^ÚˆN"gŸ<¥äüɼ/L™7ínl”àæÍ˜‚Ö©•ï6gYD4c(y sºkUOl &ºM±Ñ" ßÛ²ÄÑPµøE§°«.W|ÅâE#\N›ïŽ‘y“³8×î´§Zœ ûØË`9uæünO³×¨Î}5vž„é¶>#cöÍ·ÒÎäŒ%—ÂweÍdæcý‹ºÖýºÓõèŸå¶$—k¹âfÿ¬IuÀ†dû¬Ù°kí2°ò=ä]²oü —˜·m" ûw]Þ°MŠ+qq{È4ÝÒ3\]%IyîVK~aX;ÛAé~éÜ7+˜Ùú¾Ñ;0ÍÔ‹ö±yߟ™{~fÞ±³5úU¡Þº¹oUÝœ)%§Õ]µ¸´ydîQ«™íùÊíéº+6Î}ÃQëºmÞï?uüÿ¥æ}ÝÈÜÒSØsÞÀu×~Û–Þo3ó»!}oߎx‡ž­Ýîˆnëkz÷ƒ¼Â_ï‡ó·ìO`?xI6vBd Ö#>c;銎c¶²CþÌî9ì"X>r²v‡kz~˜ÞÂy`‘ÝÖÞÓ©²ŠQ0Þ‰Qž··@[™K`.æ”M »bJË•ï>°sÕËöê•eëwÚ¹jñèN£{w¸A.hSÜ ¹s¿Øvr/+AyÃùÝQª#í•âá]µûïªãÿêè+²_£­ ÎåW¾,kídÙz+3}´ó™Âžv§ãö‡†™þóPe«3é,ë@$¿ÃeQ‰òùmÝŒ9½]fÙS+ˆyjòB[î—U¯˜\Èfsm$1s»½µÉ÷ûÑýöGÌ®wHÚßÞ¿ë¡Såsëì(Œ—]³û4¢eÎÎb;;WØÑºÕüÝž70¾ß­ö.0vÓÌ=²Ge`LßìÍ}Y8cýx‡²7o´ùB©Óßöf°º„V©¥ÊºÿOÿ<_™yy;_iüûó5oË|­Xܽo~±36ð?fìÎþ³wáÍÿsÆvm·ãñõ0cÌUnÇ ÚFõ»ãÜ%INæª×V˜q.D3c8ÑÍoR2éß0ñ.çÀ²I8dkçW®íÚçšÝD‰ÛºÏ?^»ê“_¹VîdËÉÔ:Ë Üo=í–®Åw·¬úäî…«vÏ*Ü’{ÅiPU³•ímw§ VoüÊÞ¯ÚTwý¦2oñz½©Ömé‰÷÷l®ý'ö’F˜½¤Ír±]=ŒæD‹eþwߣÎ[bž¾HÌ[ A’ïš°¼‘zê¸%äóôEbÞ¨=±¯l“Œ+ÃM5Ø)Ñ âS™[Ö!=ýÖÓv:ëiR"14zÑô DµN.•u­ö›£)—@|Ä¢–³Úqżoß;Áõ7c©bÅgb›[“÷¾+›ÓM%ù¹£•/Hþn=y¯•Ì÷¤{çOÎé¹ÍîK£™GkÂä3²½ÜÀ°s’ÊgÖ{ÊwØÝ^»^ÖÐršmžã=™…;UŸz¼„ïù|/å͵ôeQ7;oÅçóVá\¸Ü;=šÕ/×® âBl¢—£ÍÁë"b[½sWÕ¼ O8Äp'ºf~=¬µ²áwW­Ï;|oS[dot.€çCŸ?šÞLs½Ëì#ÍÈÖ}Ýû¶¾÷zgÞ+ïm_£ÈG#xÞïA8ç›QW.ÈtóÛ=nÎd'@ªb®ÌÝNó9÷ü?Œ.ÈÁ<­(!ï ÞU=zÓZ’;ÌÇ&A3õÞ{·jZÑ}Q¡³¤ZÑý¾)¸õ]º3yïœ058!½ce3X™™Á¤ýÁMª\/Tß¼h•îúšÑøVsôÛfýRÑ™œºª+¢uǹGÚñņcŒ•²ë°f¦ÿÔt},+ïÝk‘Ž»šËgl·±ï$…p´ßu’B`ÌÇ™ðLO簾¼WóŒ?sÐúÚåÝoåN®¥¬npûMsÕ;SʳœÎ Ü<C¡¸¦…¥Ú ¼6¦~˜þG?ßÌ\tSfæ T£vç²V}ªb´<¿z¸Äá³Îû%8پɱØýwò¦ŠÏ\_ÖÄ=ŒNp6÷´ó˜oíç¥îf¬ïz KjÔ›¥›j ®h°†&bèßeă€îÖ ât¶Ö çÝkónÅ£‡,uZLÌSµñ5ê]v‹È›ºÝVî‚§¯»'+†›QÑß „å¢8‹ùZÉá!óÎ×JÌÛâÛMùì¨AŒöØ2.žbÅç™ç¬a=o2ìx\;¾Ÿý£9ÞyØQ£e°ã¯€_ ìxÿ©`¬Jò£7vLå7rì¸ìˆÜÅŽÆ2µJgßWqßÙÏcÅ÷ò§œ=‡~ÄÅ›qã7‚!o¸ñFÃ×Ûén›2!2!/êF d¼ð˜eì@cNÈõë|Þ6_kÕMyàç¸ÛåЯx‡“c"ÑRŘêÕåc¦ïy0¦Áê±Ã[‹J¢8[Z,©ùȱ$¸~‘áÒ)zkðh1ËãȽo«¸räßž2rox.Ö’ÞcØ1•²x`F㻎J¬BÖ%¾ôwx±ºWD—V®š yˆO8±'ùԳɤgŒsíG1âq#¹aÄ¥†›­/mfÅðÚAl¸”ÜâPl8¿jåßN!þ›üþ+.•. £ËÁ{Ÿ9*ѳ^;ÇIxdò,‹ÝfØïìíØÏàÒnœwÇÀ×UVÛÙVóêþšçü×°tK¥»>ãÆ¹»¾'0Þ }/#ŒwþÏçãy¼‡Xƒ—ã×y®$1o9˜—ïØ,ç%AÀo¾O`Bo5о&r\nÈNgÝŸ ÏH:Œ'!c#8!K[ËŠïÄ»îÄFê&ßú¾Ãö§±Ìؽ?KΥ݉UKú¾F·x³WáêÖŒ­FÝé‹Üé«xPï¹´s‡\*n‘bóà°GgÊv »·¬™Œ˜HŠ•ÇÅZšß·;»îÑØ)ÔBþ97š¬šÙ[n§î0)¾ðué wÍvðê¼õlåäæóç÷ípÛ˜·ñ®ŽÅ‰«xçx^í{:ïÝn¦œ„‡îÙwDû‡]˜’¯Â*¼<Ü $MŸî­”—À;¿Ù‘ùÞÒ=:Û£_·w´Éסý‡ý”ZÕ“Bkìoß¼ó¼"ÄX:ïÚ_wmD·ýÞ’° Ž{›½<ÓYPëØ[·>²·nþß{kƒí­£ÃÞšöVzgo¹4™‹Â®ZvûÉ߂;xh?µ¸Ý¤·ácÚ½töà^2õ` Óô&ÛEaï,xãöÌnT÷žÙ4°g,Ñ,ìYMøÿöÌgžñrN´ÉK/±g<&bŸ,µ}‚Pnç>¹)ìÄü>Áæ“kúÃéÚ³ÿÇ>¹éï“uÿ±O&„}2Nûdû¤c—ÌÛ±KœˆªÁ:aŸœóû$åÞÀ¿ØšS0vàÝwÊ–b‰ua§lþÿvÊÝa§x®Õ¾²Ìv îr:wÊÍa§KRn§œÆ:PªÈ謼¡Ÿ3¼Sœal²ìÀb«æ ›ˆÛÜMê'Yh¹áîš÷¦wxÄÿºk¶^DÍsïÇ®y5sŸ÷x'ÒDUÌ­ø6ní;Á¤àØmðìæu?íæ’Óÿú#]y‰RÝ/çåý”{×/~„:ïÔ=^÷»ëJNïé銥Üûnݱv¸ýÑ¡…>·Ãœ šÖÀ=rî'u“Œ ʺ{n"Çä¯ôæÐ›ûyclÍv¼iìCl—í¼vÞÞÞÀ}ÐNÖ6{»ã͊ʼnñ«Öåt"Ýy´Ý³j}|žëc#}¼M6vëý©Þ¼öp¬eº­-ìJG@ ›ÒX"ÍvŸßìJÏSãݶ°+=wßÊìÊÔª#ûÑë2°=‡•Xóó˜Ÿöúú¨Ãóݤ£û]Lì+™Üɰó:μg'Ž'àv±öoº‹ÕS,š¶ u¼þïR.$7þì.̾4ú+ú¯{M|Žx¤Ù7:н6‚[ùýâÕ뿳·ÃoHwÔ̯¸µpO…•¾ÙýmY×™¡;·ÙKXÙ†ºMàîÀ#¸¼´;kç –'Ibߤ¾¯WÕ¬·û·„V»)®j½Û«Ÿ‘•_gÇ–}òY8 ÝŸŠãÜ·&wÇ6n\˜ÑHtsºUú#Ê{ýõÜâ½ýµ\ûX-HSRË_ x´£–ùÕ2Âj©ÚËíäuVw£Q’m5»/Iu ã%9.AÉŽõ˜îƳø¿*àÂklÏ Èß¹gZ$æäöŒàw{FÎÑ ê B ëâÝî×°Þ^7‰ù‡?³cuÔðšs£±ËkvúªèÆ×—@mŸ§6xnª ¾¥ïñÖ}ÑÐØ¿à”ýŒLzš#úéFYlc—7Ï)-˜úØ‘7?¢ës¹vâ%º8}g'úÂLû}Ñ©)ç5}ˆy fbÞ.1Ïg%æw±/evSìëÓ®HuÀåõ÷[ Úì¾ßæ7#£×èöŽ|o zÛŠžÐ?Ù¢]cp¼˜()Žÿ8þŽÃñÆv°ÛO)Ž÷<¼ûv/ÐrøÛc绎^ƒ…²Ñ uÕÂí|x?Üä©g5ûå ŽOÔù®™wåÁw­¼kê}ç{ ÊõHüö/Bžªþ†{ÛjoÑá©a8½ßU fîΫw£rjj6âéaV2žè#8Y<ùû{È3ßqV•KVÊŠÚc›r>ß“žqóÉ.vy\\ß.Þ‚a›+ˆ·X\zgæý›•ݺPî]Ñf®ó³Hï;ß1‹ô¾ó] ïZß1£­ƒïFðnDï;͹µ0Šãç’Þìì… ~¤ƒT.<°Å”'0rÐAòü ôMrNXtiˆù]OÌó)“ÞWó¶Üˆå<ùØãŠp‹;{ nïÉY,Ï —TžXÞ§”÷IìvÃØ)íĶóƒv“ñÓâ0†L³ Ó3º-ÜŠm=žÝ<û†¨;u¹Se…lûil ÇÃåÈvxóý>›Ž7‘í]ðçç·aÛ>jû µÁåVm9‡è1 Ú†#ÒóÛj–‹à[_9u Êìåüă²[rÞBªeÚ¹—zµyü^’:8vlÄšËÖ4Æqœ¼>¶E{åõm+¯O•Þú.¯{sÚÓ•“Ê{sZìÛ•Û„½9í¦+§Ü{sÚ{yWN±ï÷æ´\Ž®œ8çéÍi¹X]91ŒÕ›Ór»rbë´7§å¥våÄúcoNËÁîʩͺ7§ÕæèÊIº'm ‡œX½}ÒÒqÈ)ÆÊÞœV®+'憟´`r¢ùÜ›Ój7våÄZÖ“v×BN<üôæ´z°]9_´=§Õ2îÊ)ÎÑÞœh%wä4¶ÐŒ«ÛbàÝ÷í¢ë •tYgæÃvýœu†ŠLýJæ¿"Ó²Ø\’J&&„šÄÔnx¶™<ÐáXxÌ­á@ޱf¼45*¼úo ˆ½okmÀ†'ïdÚV³[Lz£l¨öF™ú]£&Iè¡ñ¾ÕEü-ÁÈl2cºMÍN@z`ŸiÓ gªÀÕÛ„­QzÛ„edêè‡MÌñôÃJ‡›¥%¡¡i><®«¹ÜåÇŽñ·Ó=Æö@ÖãÌŽñX_e³,Q©›ý•I]ë/ãÏšœþ’Ä 3»^ت¿YJ¿q€ð—˜,Ô ™e(,.Q‹0‰¦¯…w”Öò±uáAèÀÅÐ ¡@ƒiãÎ NüàŸÇ½’ïæ £kßJOßè¾9Å`‚Õ§¿¼°QÞ1§vj²)â—ÚRïÉ!š"Q·†È"&ô ö z×*]|õ´US+ÂVYyÓ(ý’nfô,Y‡aÂ2—4 ó h…ø[L Ãe_XÓ?âx¾µyFüSÜב;;ó˜\ø§Í}íí72é{î:9’Ùg{Ò2%[oš¬QB¾êà(!FíƒQÚšÐQð#ìGì'd!ÕÍý¤Ö)¾®Ì›IÝïõq§ö»ÊMàÁÿ1mš]fë÷Ö6²™;4l·7ÝÌYË &(“ëÛhÕ¯ -´­ -—šÀѲ±¡½8-רÑ?ç[†ý ýîϦ•ì¿$®wÿ/º^ЧH› «M4ÄZ/ü|¹^Œ2S/Æè ^ŒQíêÅ”EèÅ&œ^Œ•ê²z1V>¹Ô‹±2 §^Œ]÷blOºßüÏ^´™í6] ´qÛÔÍæ8Þº‡]l|ŒÓ)¾™ MÙñpÕ­ ²Ö,®Å¡ºÉ¨K‡b œ.M¯Ð•I ÚL“À6lÏIì~pÀduKSˆ‰¦p²4Ê„{&‹©.Mf«1“aŸÇLóap’±/}_ S¨«³SàÙKó$zžp‘ê9œnÇÔs8æ@и™ÊDÆL÷T¶+w*lô„º¦¢H–°¹¦2 ŸÆ-–å46¦K¦é½ú9 §j˜.™¦<Ú`ÓÙÑ Ûd:÷ŒŽOç‹ù’2Y"œ3$‘àbÓ™ÐïÜBú=CõhgR;æKfÒÓ„þÌä^˜Ðï™°ä©4K=ú2‹¾˜ä#¸ÿØG° ä< Wús¦R ôãH¦¿ &¤î7˜/iç.‰éØOæ¢îK=·vpFÉg³=àªÎf† ÌÅlò™QW?‹l¡ÙÜ{0e2ûDZ)“ÙX³.²æ€k1g2‡íY¤6)G¹Ô?—­Vd£Ïek™‹¹ô¿È|¢Œ‰±d[Fߺh™ƒy²+#3*óÌ:ö¼Q©e[Hsر…2,Ë®˜ßgÌ0Cyle,Šg¶J¤~êP›myÿÞŒ”»]6 6»lžÌµ«×GéF©½r;‡]v”Ìi—#¾‘füÙÊÖÎ9†¹a—ÍúQOç ój÷Ì×FÖû—flþ›cd8ÓR…Y ¥³àÕ±×€c™5 «¦+ÄB¶7æÛò?&ï"æC0‹˜¯„ü‹¨=¡æEÚEz»X;DS wfw-¦vv×bL½³»Ž£·ì®ã@@ì®ã˜v–ÕØ]Ç¡£“€Ñç&—0«Ç£Ñ“pK8žÙe‡BÃHÌñìD±Œ“Ч%ê‹vÉÕ¯^-᪕Я%Ô`L;sï'27˜{?‘{$æÞOd·³ÓN”¹wõé$PaZOzOl(æ$æ°@¯O’áõé$é ô`©ìôh§,å~É®[Êü˜…¥ô¨ÀÌ,åZU`O¦fvÝÉô£1'³Øy'«.ÍãÉ\˜Øy§ÀCÄü)ô¾š>dÄ®;Vdžª¦ÛéÔ•áTæ“ð§‚yŠ\ N¥fLŸ Êåwê/â]&°öØ.Ëîµ]f íÿp—á…ÏcJ·Ë–‰ã¦ý½Lw$õò4Ý5k§ ]ª§É†¨ªr·:Ӭɜù\‡™C£ö¢Â$›¾dƒ_Ü£‚“Â\¹ù8SWFÍÇ™ÏÇY²A¤>¥¶rž¥«úu–p¬æã,Í‘æã,úÍ|œ%S@š³ÕÍÇÙrƒ¢¶.¤Ú1O±+ÐS„•ë)_‰-Ç?…™Ç>܃Qÿ§J£[;ç©2ä¯yy*¸Š9yªæB5<Õî]O½ÍÝ9›{¹éš‡lRÃ÷O“!uàib5hž†A^&àiºÐ©²st±T'ÎÑ}UpŽÜêiÎÒœ£‹¥&àðt9ж}:[8Ñ=C¡ógÈ ¾&àOÀ3xÏ<Ì<û‚LÀJî¼LÀÊǰR›D›bå¹ñ¬|ßï'ÀÞ‹¾;«´W…‰VÉB’*>Wõ©ÓçÊŸŠöÙ¹â@¨çJûA?W'tá‘se*T8ä\9pq9Wö1…Γ »:žn˜Â«åB}YM.éŠGuÒNQ‡×°ƒÙ‰k¸xÓá5`?váêa®ÕŽYKc&k-]f7®•>•pÎZêÃvþùâ° ‡Ïäqë8_z)Â|ç3•Ü:ΧèœÿK¾5aˆŸ¦º/˜OÔ'8óuÙDA:&*½r1mÞÔO}¾¸ÞghÅšwôh…Móð6^Ït1‰ëu»T§ÖË֦E„gêj®Iy¦&M·Ø uE"¼‹I î ÚÚB,tÓÎÙ ¯ ØÀ4€J.‚½SÏERŒS.ÒmO‘®Cªç"]›5ÙÉø¿êÚ¨]¤ÉÞȵ…IÛh¶Q7^ÞÏsH¹ éÄpEήéB9nÒ‹ùÅBkº,\,V†Ðî&M‡&v“˜5ª}ÓÇâ}ºI{Uµ?K÷JMù³´¥ÔÏgÉÄŸ¶Ë³Ô[ÍÌ%Ô)÷Q›c7ê[ˆ.fãlÆžTL®Í2ò/ä¶…í&×%Q»”÷4+[¸Åìå-˜ðçâu)»€íp)*a6.êW?.£o sy¨—ËÖeìg®—ñ–kÀeà…„ºžËìD=›·0Sž JÄ>ÔåÌs|q9%lD]μqÁº–\Ù¾œ‹èÿr|l`'êråU?ŸÃ–,ÐÏç ¬ êÎWùÖV|Î7âY|ÎÍ<ƒàßeiÖTWÇU6ÛIžËPNo!îÖÈ’31.ê¬MÔsu÷Qמ«ÚéÏÓíRÙªÉU•[5¹Ú[Å@ÑdlÕ¾×dl•Á,áÞ­Ú^šÜçk²µž/^’vñó5ÙÚNÏ‚Òä=Ÿ)\¡=/ }õ®À¼,¸à Ý}4 W|?îøßw7ZÇÁ¶ãlŸg¦ïÉìr me;YÃE鸙”t6ÀhÙ¤ds“^¥¯Ë@ss¥n\º‰e¡ÀmÒkÔTnÓEp±z}•xj¿WÁJ ·Wq«í]¥Û–6ñÕÂ*Ê}53÷õjñZÔ«Ù` ít“-¶þ‚¶ƒ×ÙN/ÐíKy_ÀŒpÓz°Þ¼Þp»z¡Ìp #½ð¯ã;ë uÓö|‘ÙŠ}Ñ|·k3”¡ºo~/Ò}C»àEl3Èíuí‚kw(öâ÷Æõb1Ô¯—h—¨þ—“]ðÍ…vÁKè-»à%ô‹-þ¡lÝ^ª[æã¥š+ÍÌK…HÔó—²UAÇ/ý«¸_/ý+‡ú˜y:kúìæÚ[»²^†¨ÑÛ©åÌ8zãŽdòÆyv fw[»2±o» "DZ®µ±r1›ï]L×DÅþÁÅÔ3°¼‰õsÕpw¡Rk)îÁç€ay] #‹´¸]Œì Kb6çß!Ëx /W?®ä)d?ûaOKø‹Œ[4}øªòV"¥ªÂ JGA%¯×RáoåŸ*Z¾ÕËQ‡w®øŽ"å–5Ûõõ+«ñÞ.yÎh¨\¾€T¿ìÞÊD×ÊŽ¶¤4=̳¸­-Êý¢ssU©hkoˆýÙn-=.*¸ì·~2_½ŽºÊŸ©Ã%î¹í´’:Ô¸55í5t7Œ‹o´‹ôõáÒ±%‘9{ÈNùÊø]”3§I^oï/Kkòs·÷˜Ø¨Ý¼¬q4ÃüŒê¶(ÿµË:šOÄtÖû]`j°§UØ·ôˆ#¢üü´èþ·'¸[–Ó€£JKÆEùW=h %Êyaé–À·69‰£œã‰G9´¤Á¹xâšå~î÷ö4Ê/w³¼©#=ËnÈwÛ«Ü 6³kâ:d°Ž¥JÊý§‡Mè2ó¸ªZ2±Ïe+[ZñX¶™jWÊ‚ØÊíÓËÔÊîÇkR+šÝó‡ý™~ÜÞÔåË$ßbOÅ×74×¶&µ\e•`þh<'G=¬åÖžlja÷žX:†öǽúá=šÉ•¯nêžñÿzˆ[-—°Z _lgŒãvºñŽÒ1cÇGYŸxX%·X€+a=Þù°øiqDéØb¨6Ï}Hû±¼(í³m3+XMŒÁwYòK‚Å‹°8<{Ž­c]kg[”³G²†=9 ¬ðœê% K£Üð<wýaEï^Û¬Õ¶Ê»‚=73#É™¤Qþ¯6T¡¢1| Ø¢¬q>¤n¯kÛÚ˜ãçbCäÅG˜påⶤƒUQîê’õ5í®œ(úœª~vª•õ¶¬t;¡tüƒºEÅ}„AÌ#U+ôF ÒÊ–(¯%Õ¾,É‚="U_O£¼7ó§k//7†éøÄƒ(Å—ŽÃ±q»Ê©V$_/ªohnˆ}ß¿Z:n6•ϸ?£µÄV|ÓƒÅ?ÿÁ¶áÁ®Œþíº¯ìûéëÚiQÝC2zÃCë9žõðÖ¿¸G@N¡ñwp+yÏ ‚+]ÿ ú+Í~O~µ ¸–_û[|öo1ùí[Žå¦-¶×ú$°ZWá8ÞढgÜsq7ê;g˜¬¦¢hÕM±QåÆt#}»zSkýhBœ·96ÎÓÉ´Ø…’C(MÓã ª£š3! <úÖîjØ µjö ¸Z5Oƒ@²R¢Õ°jÕìµjVBD¿€£º~ýû@©H;ƒÔZ)ëášo„¥â‡0 `WÍÃʵj.†×òq{¬ÑlÁmê9¨Ô x®€$c 0pžöáúŽ®`d_$†˜sì»tð"ˆ»/•Œ>¼¹I<¬Áå~¹OÆ<˜1 Åù-³ä’·r”·`°;ɦ6ì$·ö{ãÚÔk'y.ð/h­mþ.ölè|ráI$h½ã™qÅ^X2ë÷_ٕݹð¼ü) ÑÑuZ·×8«Š\ê¾3ôùN5?î¹)íX V‡&l.—¯¹(MÝüN\Txm=­`ìHœ‰,XU {àï½›»\ŸÛP\Ï-uNÜä®Ñ8¨•³›+KsäB¯…XÃâ=cCüÛ«‹/y[¿#[yæB52=V>ýçí—ºrÿ®PoU—ÎÎQûzn¢ÜÎ4¯zÁ°LüÕ{÷.½mîz«sãÛ ÞY×8Ÿ*ösôn¼å¡ÍÖ‹zѬ\äp= þ5ª38ÆÝzú?tvÕ~·sUâîé4vÔÞ ú¾˜ÜB¼ßI̺à‘R¿Uîo˜ÄEò¬ºÜ)UÝy xÒ­‹]ë,ÞVÚ«˜š\„cË–‘Ië,·˜×[,$·w¼s[p¼óYïƒs¾ošã­Ä¾2yÏ´[®vÍ@êÖ ÷+º–Ò/Ü®ŠsÛà›]Ús[÷ŒäJ©žsÛà› ƒoÎÆ ™z óßLP¾ž>5ßó&¹3f5\=*ãéþfg´\ò¬8/ïÍa}G<ÉUa–î³ô%fI³çg‰¹2³´Cs5ƒ»jXfµÌ¬Z—wØ}=J– ¾Y1ø¦g®’ƒoZßà,£g®â[ßܽm®âÁù×Ý7WÉ•ÌUCÕyqíì·cšã]/ óõ©0_÷2_fϹùÒ¬y—‡q.³‰›«sB=ó¬ýÍ}}‹î|óåÁ7Ÿ¹oÖä °ëÍ̓o®ß6krÕõfͶYk«ëÍÌûf-6W€WK‚7¼›ÓÜÈÜâêfÚ„‹p6nñšÜ¥J<\>êûZ9s’Óœ$ãdìê±ÁGƒ¹é6xÁÍáäLíY-æ –k£‡ÖMÎT9jR¾õ¡Ý7ƒçp@¡7!·r&¼£g¡7­¼!ê&ËöÓ8i_’ƒwúÉìH{6­EœH0¦Oa s3Ø¢7«À2&¿˜]Á ÞÀÁUÆ“¹ìV £2z-ŽýßÁ³ŽP'ôl!½KóL#´à¼ûHÞi ï¼SgÞåL£Ä×JïP‡wžùÄ;ïP‡wžÉ$ÎEâðè–S¨Ê0œ Þ1Kb¾&rxœÄ|Éákâw—¥wEßW½+‡2EïhG·•¢w~¡ÛFÑ;¿àw~¡XÉ3·”£ägóîDÈá†ðÎÏï¼ÃÞy×3êAɳµˆyÛļ+ ÅÊÃ3nhʾg¼ósIÌ;ÚйìmÏ;‡¥|å66X¥XGÇ3Çí'Ø`6O• fr¢ÿ¤#†ooN£“Їؽ9Í=¾;'j°½9c†îœhú÷æ4wóîœÀ‘³èö±ßå ’Z¦Vƒ5­ºœ –B¾îLƒ»bNÀà3\¦À p™_n>©f°ØšÇ!òI ;õm©Ý ¹0Î5䯷T3Ä4m[wÝ’¡UÚ¢‚Õ­¨ £ÌÚjõ­×oÉ8tç8ÃÐ[38E¿¡æ[jÃT£ú6LꌺS'_ý&Qô>гƒb¸îòº©×\¸áRo“b8J…pGˆ'&ÎàéäŠu1B:žâÄP½ºåcCêÓ#›€C8RûC¿‘bªé6:-gZ4R öBj#Q†K8Rºš¯‘äŒéÓ(á0Më(ÞpöEcrŽâ¾râ($Šø£àÂ9…Ò j±£é)¦£éiL-£¥Ä,~ÁþR¨WÝûË¡žêݯ¨ÄîOÝp ÷‡9‚ââêFtŒô?U÷©…k׌?”PÿvBBýc˜›„úÇÊ §æe,oá"ŽÅa\ıÊ'žËXœB #Ú&¬§ûw<‡„þ´!&B~›êÓü´)Ÿæ§MœGq Û˜7”òÇ17pÇQ'ä”qÔ‰Šø¸›c]Ñ&8Œ0ß(ä@oP?౪øp$QÊ?Þ`5z z¨è‹(5rõé@©‘«OÒ‹}:–êâã¹3£.>žyBI<¨îãx®¤pÇ#V?Hõ‹yêÓœW•ñƒØ3Žhg 6~sƒÂþAäBuü`ò¡:~0õ¡°0dTdž³ŽÒþÁ¨•£´0}.²á²¢þ!ªKšÊ‡ ’^¤@ ÛâÌeý ôºÈüL@·_s‚òkþ'HÑ_}9”ù+јC™¿}9”ýU%ŠZi‰¾Šªi‰]<Þf‰9›ˆ q‰9›ÈÞ)±&2+%z6‘ù*1‹©¯Ä®™Äœ–˜·Ir­}0 •ˆó6‰ýVbÎ&)Ÿú8Iõi&&1+%æl2¨¤ÄìM¦¦’œ!(w‰ùšŒ k‰~ÆÐ—˜™ÃЕ(Ñ¿ÃÈ]bÆ|”ÙŸ‡KÊôo û¥ Ê™‚Þc™yšBŸÊì…)ptQœ8œ½ Xr`Q>}âLUfV¦Ám-Ó§iô¿ÌþšFmeú5]êªaºòj/Lg¯”Ù_ÓÙoeöÂtzWf(YfßÏPýÚW3Pu-ÓÛphËÔ2cyŒTä$!´„áÆ&ieO˜­Mief¸±–7 £¶læ#¶l͸±Æ7EõÜXëù„ 3·d Ö·D ü¯ÂÎ÷s‚ú ‚~r?Y¨Pt?]§ð£ûI7…Ûî§Áþõ~KòýÌ)N«Àéê“©Rî&Ã>&—ø°Ôâ‰F·µCRO¢›Ïª)ÏwJG[úø±U=ÒÒì¶e ŒTs<»8Ê[¬ðy ímÒa”(Þ@&Q=«,kLÖÔ¡Må>>wî/%mÃ#2í·|¼dÖýã2wû¤%eÛ‡4éÞ>ßÉÄí«!yÙý„µ> ؃ƒ ) }S+4/]Ë}_#j5 †œ?XV\TCÞ[Õð0c®Vƒ„¶‡È|MèÃ,׳>ÔhÕ† wÜ*Ò|胩áa[µ†VŽ‘­²ú0½oêì°Z ¾C5£¼¦†‡fÕ†àgÈŽS•sK;ÄÜ/gq¢A sáß•¼[˜ª}üj,NSuº˜pÞ;Öó+J…­2âäçG×”€äð’»57§sxìçò¢üÕ°ψ}ȶ¬®#fÙ£E‘{Ð4 m#Áy–­-%ïñÑÎÀzÆÛt“_ÑAûó-?“Í]Ý¥Å]¯ª*>¹®´øäÃì}Ì$À4Sßâ®3¦®}9Výß:,QŠ'ƒ«NöÝòW¶µöù…x™oîæÿÖ§ì.æR±¼ÑżkPÌ1Gðc[]ëªr î<¥+Ú«S¹WÔ:š|¢IwÆÄ¿yŠÕÕ`o[ônüµ¦ïLS£{×pQ’3…j¿Uߺ•0§xǬ{᪲;ì¦ú²±;Œö–»æƒJ¼^Œ:{ÿßÜ:½LšÝÔ­óÂeáÉ 57¡&Ö}¡æúø¨> ·YÝÊbµã; ެZ$Ï W6èΠ7 ÞÓ ²An±tsjÀÍŠ1Åþ |£·½¨Yè¬à;Gw¢&å×fnA·²&9yÒm©Ÿ”ýu[BOýÄÇWÎ~r|¢´Jn³ÍôuöfîAÜdûËm‘úÐ_ž%tSêO~†µ¿?àêõvàèaðd0@NtÛðŽø4à\Šbß\´Ó[Pÿt”Û ÙìeˆK h/CÜ_àôX?—®Ó6Ê H–yv@É$óDd=ôxµãlɼ¥ îR6Êq—JÒ™F¸Ú¨¿Ñ#{5ò×!ß5òªñ^È_Â{Þt©¼1³çºŽ$ÕÃJ±³¦u)#Ú'€œÀs¨dz”;·¦¹ Å®ëH±‡¤çÒM}žåµÕÖ´¶®ädsñòz®#‡%uŒÑ™zmÝè(ï¦d]C}}æØRÑ*1ëÂuhGYÏÍt·/¥‚2dtÊáX[o5Ö…i+\Ï sx…/.®}`ZS˜v’Óì[Ðs•÷Í‹fßöç\8ÌÅùÎ\nÈ7#%žÞÖùÆÜ%í2)ˆìŠ.Ù‡sî°Xõìê°mªvõBä›^í|êrØÚˆò"ÚpÚr0Ïp±¯?[û4x÷²gFYá~´ƒ=ÚÙå`³v{PN«ïÄYà]`_Ï!Ǧ9¼ŸËœ=–7¼;3Ö»k¯:ýÎS.6ÜyM7.UßÇ/xñï^ÞÕíÔv×Iþμ[ßü¶Î®Î3;»ö¸txóµõYïÎ>ú ÝAüÌQÿ÷Þ™Ó|ì™9vfn»nkþ×v}b÷xî>Àܽžx>wÛÞÄüŸ¿ÿµ]{%âÙ{=±¾fïÚÿœ½#ñNÌ}¦Ï†œìgÐõaôô!Çi]nOžc;»yr·ÓT4þ{w7`ëâ»[Nùîž«`T¡'j÷}ÔÓ»×UÇN×÷?~yè¯Ñm.Ǥ·[úé|‡«÷ëýŠðÞÜû¶î‘ Ï#ûûÜFŸG¨Ñõ±Åji˜ Ýú'8#øZ~?ø®z×2PéÄú»–¬ äw-ÏæîàÙ±àFÏŽåáÙºäðl]rxÖ/9¾™É‘úZF»Ñ3ŒyçÉè8zÏ¬Š¥ŒgbžÅ«Þ¤>!yç™Ç¼ó¹Uwâý¶ª¾‚gZ+_ªÑHÌûŸ$æû§: žõ«wE¯I©wEïsRõÉ~ö.¯£43“£ä{¬~—üm°›õ[¦³X_ûØ«xÔzô6(¿2ܶ*vwªHª]7¸ ·7ø›¸xÜ+rd¢†5¨Ú9 Ò Su r®¤›A£n`ºõ5ÊÝxYrˆ.^V#ýåÆ×(Çqª³QNŒtáh”#ME£üÖèžHçÑQksÁÇlâîß²}â¶×!NeûÁ)ƒwÙOÎìÔ›~rÂÄ­QýÀM?þólææk«fø¢ð,›q¯²™>âp¥?õâÚª?‡pœ®ôgxðcƒN.­úÃ[Å…Õœ´à¾juGñ7ñ_3Pœwõo \W©ÞBàIÄçœÑz”–«Ñz”_4[¸Ãsl‘Ã0ñðZäÓFóÒÂÍÓh;ŠÏŠ{ªñ"Uç 9ýÒ…nœ‚‰é0È\T ‚?‡êò f—Tƒ©½È¼¦·8 °Èu0³Räÿ`n8ð‡à`¥.—²ÈÜà(µ³Vm5õ¡•ëS‘·­ª[}h¥ïð[QÓ‚¿Ø*æ…æ·•ºá/…Ÿ oq(€ÞâPæ»Ä pÒ„¯8Œ›,<ÅaÜ€á'ƒWY¢/ÃÀD%æy»£D†Q3üÄáºB à ov×Ô†>mKãÎD)oP: ëŽlöf ëŽÛ«½Ùºãzf5*‰p{õ<<[I¥Jõz™6JN^d®ò¸ÜgQnòY&`ÍÖ8DéŽR{#ö·^®·öÖËíÖßz¹Ýæ®`Ò[/ø[/Ïßzéb×­w^ûuÝz£ùåôÞÜ[Io¼F¡ëeÙ!äØ'ÀQuÊâ{¥)¹ç"lo¿•‹kjk;äb¥<³¥5U§ÀçiÚ% L'NÒWõtz´&ÙŒ(ÿ½”Œ~±ºµ†V_Ìç´(ç»xщ“üz\(--AŒÒX°3Ò§ÁÅX4áÁ[ƒ­·ëº£[Â7Ì0õ8Oë»àbljËTÞÏí¹:í´^SÁ6\Œç€F¶í™vÝÒ]¸ñJ ÁÙ^‰ßí<Trõí\Â.û›k»žui| ú¡kW=ëo®]u ñ(v£2η¿² m»Œ óõ\Ù†{m×Ë×qe; °ëåä]|£žR\Ï•yÄVPØ[Õþ¶°k÷«ìú¥øS¹~=ïC…AcW¾ Aì}Ô Ú†R[ÚÅûNï+œê±u¼¹Ðé‚q}y‹7®:ð܉è)N~æ:ºêÒ¶j]ôa.<èäÍèÊi7•¬ª[W²ª›+Ûêïpa³+ÍÒº‰š%±¾ÑòW&£Í&÷•9äO^.TW¾àm«^öÝÎ0S6·¦œê…©{î&€ŽTGCí„(ëÌqËz`rì”ó^.SR>xü:¥]R½Nµ‘dQú:% Öü:å¯, %¯öMì®L,öz-Ü|>bù5+uBO>¯ê­Xâuz¸$Í³Ë x¯“ÕµEvº/7`¹'/7àD¹!Vguáäò‘ËfÓ¨n£„¡ GE»¿"v–˜Rüê¡[‘; !üŠxbºdTä Um\xiòP…äÓÀÞÀ;T¹Ô”PÛn ¯Qׯ —湑 ,«Fù±U}F[(¾/Q¨l7rm qøñÃb£.*\~”_}MÎç—¾';ÔZîóq—iZO–U¤oT¤S¤+Cú†e¢\øogüîÕ¤-RözÒÙÀFAùÙ€,]WõÝòÂ<+ßct»Çè»{åLÑÁî£3]=HTwaô=Üö*0ïSǵX§ùãÚ4÷4ôäWíQö/؆ÆíNòóF"ÚhÄÈ&Â4uD9o.SÌá.ëeŸXZƒÞ$y™?So5Ö…¥a[Uä:Kó]d󸤢ÙÞw–6µ¥ô®·½¶¦c{–0 „ ¥÷9§ñÙcêí·DÃþs«¸±?ß-žU|ÌÞÙ¨uÀäUŽÏ¦YÅÏ4Vñ‹wQU¼ê–EÅ'Ÿq`çª8Vñ­Æ*^b¬âVÇL–¸Ù` ½ß©üÔö|É&7Œäk6<÷0ðíW`Û\kŒe<~j>Ôì*&ÏlÀÏlp‡ò̳ÞLXõÏUÅ>ò¶$^%VÝ’Pm-Ê©\ ô3ÍýüÃ`ÉÈk! äç7î^ÙõTÇjáY˳OĵuFßfoFèͼaËC—À.Ä:–>w{í=¹y3¦È6¶ÏíÞúyÜÏò-Í;½Ÿ †8ÌäWÀZ†‘Lß#Yß÷CúŽàS¯®·³¡Ð6vCÏMä¸i8CoÏžü”X»3¯=ÓÞ3µGë^°›—ˆïfLj.ô¬¿„>¤õËd^ÿ&-)Þ˱w3ÿ¦¬ÞÍÿÉUµÃ&‹ÑnØàbVŸq"qÍ¢™gÍÓ‡ ›Lîû}ÿ×~Ûï ±‡îê=ÀÒvG§ï›;–„{€ÇëÄ<ÃC±Ø;‡Óû{€Þ¥®³y·3+D†õAƒî²ÛѺ±>XñI¬ŠôXŸXÝa~^Áúr˜`°>Jaª¢"¦5 neGs¬Â\Ö†f‹Áãã§Í8nË;_r 2Q#fRƒ1ÔˆóX×È~A5¹Qù…ßåbUw¹&aSáö&yíÔ]¬Iê[b4é– A?z‚¿¶~ìuXýÄÀV­ýä½SȪÈŠÛB?Ä3 ¬5‹ÍC( –G³˜Þ8m@EKÿ›åS—Àbˆ£ºÕ_ùÔ¯þÜð/×_ê\°4ÔK˜ßý¹„r“è¯úÔ¿þÊ/6A˜î°DȤØP«ãV1@þ(u;#æ&2@j^êååÓíb ýÆ!Ä@æ÷~-äçfѬLèc =ƒMÒÂuªë æÕ®Ár¡þ Æn¬’ÁôÉ`Ý<Ät"Ÿªº™ ‘ß:ØbÁÀ."6Šú0„ÚQãBœ5®V¹r@™íFw1è[Áî½8Ø(Õg.p¹dd÷“Æ!xéšÙü}0ðÒd!Tyéåœ%©ÖÖÔŠ-LôÂñ¥hÀ/fÙ—›p¼_z÷ Üj¬ë’°Y‹â¦kò9¿ÕÆÅ)«ù±5ú¸˜­#ŒWZ$ÜŒËy§‹w…¢sN¯[‡¾‹k¥«.<¨U{Žò8ï ¼Ç*ª÷§ÄA_Þ½39ŠO &"oäpïLކ’Ó¦.ƒUw…œóñÖP,Á_¤Ë‰ˆœ¹Eè]dïBïZLë=*9½§§«.ºfPƒýžè©&nu6k„¹°3ÁöcÞ„*/량Bí£m."æÂÏÆ|±Qûv˜™ž^¿ÌŽŒ•iµÃÌlþ^Ìlf6Há_ý@¸œgÒ}Sç¬ñ0Î.‰é¢W’/Uá=c;A˜¯,¿‰ú_–ë"ÕSV®²|h‹ÿRÛáY²,¶¤p_Y¾ „?+º(GW¤bÊ-žéà¿!Æw•ƒ~!ÀM‹¹¾T`Ò— *’0*pnЭŸ›=ž)¹ÕKÑÀ°4Áçºf6êâ œl[ÄBlD•ÑàûSâúßQЫkv_ÞMŒGœÄxcÝ š9εè.êÝwhÏ›]¨ð²&?Š“šê€MÏn$7ƒçþ$³3¢¬ÌÄœšÙâPMŸ詤“‰õcÕÔ»§«ÁZÊ ì—F9YÕgÖ®j¬ pAŒM$†Ëy.  ÄqÒEØ×à2µ¸ÎÔámE÷?žÒõ”œ 9X¢sÔf  ã ˜âZœkznšõÜJ “£¡+ï båj»2JtEÅÅ]ër:-oÑÞJ(}hP||±@F7@Ø=¥ ƒ’'¿.{cÿá¥P’Q{7JHfšeÏâÓ1­,r† BÙldkɳøº—dz„ 6ÈÿïÊŒŸ‘™ŠÂDî­Ìä(™nÑÞŒvÏäì»à´PÂL0Êœ4,­6„ºö~LJ -¤dh@ˆÑš˜¶Ï=‰=S¹Â“+®ûtÏgžÛs»—nâÕ\ÀÚ„})‰³ù^Åw«Èy;Of÷‰¸¦åqˤ{ÖwÛövŽžü&ò”1±?yDHRnc.âÊïÞ.„÷×÷&ÞAb˜¬÷F2BµéÝÙ‰+Ø£®&_¾ÇC6]rEÏMƒoNû {Ô÷A(ÁìLŸ¨7È—q<ßN¿·ÓïêÝl&iÓ6½˜z8œ“Å –ó.—Xˆ¼•%¶^Ç;óÊ›ÏüåêƒzuÓ³\6¦™Ÿêßµ1[ÏÁžÖ‡±Ãäp½mQf0._;Rf0zsÖâhUo?ÂNø3W݆¯Sº%T° 6’*™yO˜ z{Á}bËl/p¤éÜ 7J Âí{ܱtõäê?qÖ~ºœ«ãÂ}0Çü*ÿÄ$ ìÂ¥4è8®f6`w¢eƒÐ 2y¨WêØß ú˜ŽA :þˆÐ ËzÛ ã'‰ÙFÑC9Â`3[$…FI¼sŒá #QãëøV ’B‡X‰!fˆ•_³cÍ·ÓhrMšiðdJŠôˆ2? 4;ÎÍ~ï@+ÔÕû“PÃ@:BB×ädd´hgè Ù"A+0]¬#e‹Üï!\Á@¸B9`oÑ J4†餪ó-—C $au5Hvš…¶¡û %dÀAnvI „ fÆ¡„ F8ñ¿Á²í ¥BÔ5n$ƒÍíà×ól è{6A¹"Xª&½÷ƒæV4><ƒ‡ T:F£7KÏ/=~ƒ¡Ïâ_;mÞâ¥Òér¾‰_Mñe³÷ŽðxWºÖ¾ L? 6êè ­“õ4ÕÒ À²Ààx{f€mT5Öæû±ÚZäz_‡«~ <êéF†_ŸLISüäütÏ¥·9ð(}ð¹äÛ¾/àèèhçI¬üßw,WG‹ÿ@0rñš’UÒ¨ZýÕ^|ÃQ µÙ7Á Ôâ5ZM–­n™ðZYøµÕÕûÞ+&q Úº_NçDV›Þ·.D§t.R¼æ<ó@Ê­êùÿÁà 'w¿÷}%§¿÷½]'£ç5Ö´½Ævíªžý¯]uê€w1)}½AËîL“ú× ög_f˜gÓ{1ÿM½í¬cÞÙ}ç)§t' »ž¹G¡œè·$þýýlÞl=ó¥×v¶ìÖu:}kEn ñbvá)ç]…v•´º h¨JïE5_s¦1Ó\Ìèsù^Õ«Ãgz|Å©sã…§œÿVfQÿ¥`ž³–¥–ï\tÞèôxc]wÔˆŽëÖg=¼«vÿá]uü_}E¬Gá†ÀÀO¼9ĽÒÄ4R@]-ئ_Ví¿îe=–®s™ÎãÖ¶_2Ãß´~íµ§TÿòÚS˜atü¶¶ó.Ú³°«w3y·Øp' Ù…'ßñ7מÂÛv€a;¬/Õ4V5=ÿljÂS†3gwП쭙ï9ìf1߃­¹¯.ìŠÖˆ‰Û|ò[ÈýÚÂU:‡Ÿ|çêá§ì ÈoqlU£ßv儨ðäg9剋n鎚OcvZ™ÙêìÄÑ)ãkVM¸êΓÜyç ì³/Mþ7– HâöNª5§]P×xƒ€h懚;ón}Ëi]©ó:û¨?f?è7‡½jöƒÝ%væ4sÄ¢éÎYÕnto®w`ç)9Ôhk°s$Hës]ÙƒÇQÙÐ{Åß;4E®x£Ûiv† †ÎŸfêÊ[î¾jÝ?ËKtÉ)²[pÿM]…î`Æ{õ–\#åægňBPWE³äÓOìdåáòظöŠëýä3ïFëC°xðèõ1wïÂ䫇ž¸šã5ÂJ[›{÷á³Òû°swn­%OÑòÉ3þ—מŒßGƒ?ìÎçz:ûð={Ž„)ƒ9ßf_2ƒFg±c/ònòÓ9^í<òé=ëØ~'¥~}¯•'¢—ó9ž5'0gÚ…êK\È­™ƒŸéí=0±ÜÿŒsD›ñC|ÎE†9öÿÕy¶Õ•h?t½oŸÓv6ìÙÆˆÁ¯Q˜'«3ø öÙÆ—±Ó^|m×®kâù´òÚSŽ}U<§Y>·Û¥û8-*9ùK%]ÍàÕA†WÉ9mÿ! f6îŽgö¾î0³CïYÛ3ÜÖ;wv.¶Û3W:ˆîà ºMÑ÷qG¨Dœ>ä¶)+šªÛ^Ú &Ë ^}†Ã›×äÝ—2±ô8вŒw8CÌëË™ç© Îá½›Þy·6ļ¢ ÊNAÑ×ô‰å 8IèMâuKݨ¦Ô§¢ò¼¶£úT¸&¼óîktÄ+úë]qçL¾¢÷⨓[qdˆyíEòy GòùžñÎ;¥¡¾|Š~ÈçIÔä{C,׋LõÕãR˜¡’Wùá]>©£ÍAêèFu¤.nˆùù æÕ«øÝ ú*á^ñ=æï+ïn 1¯w©º+~FUSƒw³C¬Ý길é8¨7´ÈÆ·Á>÷6á8Žc'V׋|\K¾A ¨ùpª×5Ð(è\Û(Š™èsø!ØIF¤!£k'7áRÁ(è-çâ&åÕ ¥IÖdñä(lÀ¹¸Iµû1%œ…ûQ#K¼YþúUG3v‚aø7ƒËaø7Ë—‹ŽåÍxPGÿ±¿TÄaî"þ[úão¿-hÄãíq€<;ªßÅuƯ¸&Ÿý-òÝÏûWø=¯…#>^ñ¿ ó5^5iƒ8sãíæFè`©ˆr¦Æ££z;ŸÂøéGÝÇÁóQáÄãMAŒ6«ú3„C¥Ì²EϤ¯Eê"ýF«‡pe-Rßê,ÊÿÎò\Z[é}‘­hñé[+º›Eæk¨¼i†Òß"ó0r:Caz©w(úžøT S]ÇaòU¤¹y€«ù0nm%æd8¼þýN_JÔ;\¾Q„…F0O%Nü£äHõB)¢¾Å|à6v?æ¬ÌFÙO~MDšØ¯eè£ÑÓÁÊh€*R6£Áø>Mî2õìÏÙjØþô© bæ¤L=cè}…Ù«Mª^ŒeVèûX±fÕï6üÇT˜…qèoT˜«q(.T˜ßqÐ*Ô6Nþ2UÇ8úWaŽ@Dz}rà3búÀøƒbÅÈ”Ì} Ó„0iHBØÈÔàòöªGÁš°úýž„+*Ë”iH¢rÅÿL{’*³(È¢PŽë¹òê÷‡7(Îså¾ÿ—oá…â<'nzZsÿ—ùS| )¾u5o¿EÆû{nÛ¥çןrqžÔ¿|Š|Jb߻˯?q[\î½QÅu"P½Ÿ¢ $¸Ÿç¦Äôã¹I`‹¹ÿ¿¹Aªßúrÿ§OýèGò‘¡&ýîþÑÀ¹& ú§O½÷G’Hµ ôü??·ñÍ׽ׇ™·Zó«t˜y|ïëB˜y½/®%ÈjX6Ò7£’íQ;ש?ÖÎç“GÒ?ý†Î` Ð4æï}öôk&ï]}éóü½y^í®í‹Ý"¦ºl:ÜsÿÞ_¾¬©µç>AÞóüõË„÷zþOú¹÷y×Yû\g÷ZÛ!=ÿöoîºë®Ìó,Aö<Ï^Ý_¼YÏ;^§ûm¦žw¿öûQÏx.Ðжîùàkӽݯ‹}c·ç÷îÔûIÛÿðàû°÷=Åýƒ½÷MÊ—¨mMí}X²Ýï³%ºç}÷’ ï»—lx¿gÉv¾ï\²ýÛ½d;ú³{Éîî_mÉ¶d{ßçøâ_ßçKö÷5øÒýÞ5¸ã=Ò€= Â$ù‡ïºŸ»÷÷èkßûÞo¼¨n0Þ+SŽ’ÙŠÍÏ¿Ïóëϲ¨éöÓ‹,ìòW˽ÿžú÷ýžX﨑l_e¿¸4Ê=x}4¬b}´ë™‰èÐC†Gsæ ‹ÞñŽ‚¬£º ²Oé.Èý§› žòù» žyyÏç|SÏŒnZuƿܽòŒ;ÞñÒ£üŽ%‡îþOuÏ,þþUOù~ÏÚÜï¿ó¨ì¥ïX•5朻£³'ÜÍj»3:ôû7E»¾‚ˆÎÃP° C þ·×cåó wàÑùžè(.7WöÜ©uÀ©)æ ÿ¹¸`áùþ_ú¨Ø}¼ùo¿IŽ{•‹œÊ}5|ËÕr uíévWNîØs£~ľsP~íÓsöúîø×ö¯ŸXVuésV<«y§ëóгgugÝ™sgÁ]»Pû1qÝ÷­ºë¨žýîÞ宂Ûrn’⣹³5÷Üån]ŸüÍ~únîùÊo°o}ù7ûý†ãNsÏO8nÝqšÒUìþ{¾L6­¾¥[ÒýŸº‹ÔÀÛ~}É._þrt›ÀÚ·n£ß¼!ÚåË»ìòkÝyôàý:è üò¥’ÒƒÅןñ§£¾ˆ¼Æ&Ûm“ÇöŒáº‘¿V8=³Ø0w“‚Ü¥øÊAÜ^ì]Eqpp›Z S°Ç\=°@†Í)° ,5Éxp?aóÀ#*˜lî˜Jy'?#zêŒŽÆÆÄüÚÖd²9â\™–jnK5&ü©¦a~sMKÛ²”;—æ%±‹æ›ÑÄ)`ƒpµúÓà…½²¢ÅÒt$S›ìÌÕ”†Ó¿·\+½Om¹OEyĘji¤Ÿ&@å¼kõ ;ö_ôor_†¡qÏÏFK!”—ÑÓˆ‘_ªêD¬žºâ-VÇ ûlßCì»Õ¾‡Ú÷0ûnß#ì{¤}²ïýì{´}ïoßcì{¬}·Ù÷8û>À¾´ïñö}}l߇Ø÷û>Ô¾'Ú÷$ûžl߇Ù÷û>ܾ§Ú÷4ûžnß3ì{¦}ϲï#ìûHûn·ïÙö=ǾçÚ÷<û>ʾ¶ïcìÛK á•‘‚0ü´âÌÏûQÆ??Ë=WÆ}{Ôüøá›‚2ü,!ŠäD’^LøI×üP3äçVqäeéäUÐü´ÛÌOÜ)óÓÂ5?y01?ídóC†ŸÕ¿‹"TnÍ?ðüäuÄüð’ÂO-óƒ”ËOœ:ó󪤨+òó>™P5æ‡ä ?/2'ƒŸ7•†Ó~¨óóJïâ♟8BæçA{Õy51?$¼î‰_àžóâ]XXî¥õ‚ÌüðËÅOâK懛'~âÄ›Rtü$Øe~Iyˆä‘G1Ö[ÉC%?qëÌ_]üÜᇒŸµ/EòòÂO¢CægmÏEÑkí!~Iù‰“g~âh›ª–OÙþ¿ø¡>ÉOÞMÌÏKJûÀü$¤e~âfš²_ü¬m!Öe~Ò0?ñ÷Ì•M~x]à‡Ê5?$‰ø!)ÄïmöÚ&?«BE¨–›LüP³æ§”ßÏØ·EõQ$n*?ñ Í•k~ø#ã‡Ï1~â9šŸ¼¶˜øYûvFÉü$]d~Ò‚1?„›øy‰;ùÒ7?äùF‹~æ8¢ßGìé%~¨{òCM”Ÿ¸¨æ'gæ'+{æ‡Ð?ƒ¹õ“—óÃg??ï=oœüP çç)H¸燋q~²¦g~âÊšŸ×þEM”BTü¤ga~âbšŸ¼QšÞpø!|ÅOùq´áç¹5ò4i~xå'ÿYæ'¯ùáO‚\üä.Äü`)óÃ{?©x›™¾ÔøÁâçÙ:¨²òóÌ*TÒùá‹NNù!üÅOZ4æ'n±ùý½}#ìÅÏŸP='ŸKðÿÎÏ£ü<=(CþC‘àšU•ŸÃÉã*HÆÇdÓø©YoÉÚ/ër³çÆ N&¯¥wõ›k®Ÿ:wÚÌù‰†¶„Ž"—ÀaÜ’5aÂØçò1;±deâ˜äò†æDeQbVÍŠöTsÑÓž–θ:ÕÔ”l•£ý¶¶T}ûŠšÖ$ÏKµ&šR­ÉDCs½l'B½œœÀrþšDû²d¢žÃMÛ¡³*¦•Ï™_~(IV7vÔ%ë˜ççéÎÒV×ÐÖÞÚ°¤C¹§$õ‰•©ŽD]ªùÐöÄ2ß·aÀEDǶöIÕ Ššœ póøY Élá×ytú÷³þaÍß@è<·U.M¡j“ÍmŠnJ{ÎH÷êÜŽöeêß¹+K’4xc{M-œÍ¶å 5Ÿö´ó9O­oœ˜°©°#Ñ?±á7ktIbV²“Òô¸m~{Ñ@‚³jÛ—Õ4LÌ.K5nìÓžVnuµÅ0Â熺¢¶öº"†ÌÂÚ?@í>ÉúúšZRã.i׈.ªYÞP—˜ZÓÎåIuµM®k]â‚óñ+sA[ª¶¨£½­(Y×QTÓ1%ñ´8Œ4­õ¦ù¹$Õ”¨jhJÌO6'kq i@‹Ý#f­ÊªÍ¯müšö«²j×¼¡Š‰±­X6-‘ÄŹín7óc£màGw}fWLYhff5»ëjZZ’,5csGc»2]’hL-—Ä„ö•- 4cÃÊÄn*¦p<à0%>¿¡¹.A´mŲ>ÄÃm[Ñšj^Šl~Á×m±Ìx› sðãÈahÙíæÕ¹>c-ªŸîjßä¤ü-þß7´ÂÎå¾þcY¹ü/OMü$ÿù‰Ÿ¼xNâ'Ëõ­ÿæ}«ÿc{ò¹ ™ÿ zz>'/¤Ùÿmñÿ¸4þŸ$âÿ•Ûò§æÏAîð}¹¿ŒQ.Õÿy_¿~â÷»ƒ_,ú§¾“z~Ÿº:Êù„ûÉϽù9rx×Ï2Üï^¥Y°k žD+í’µë´1‰áÃwÝu׬g޾-ŽÇÑôéY…YcçÞ{çâ±·ß¶KÎzoã÷ïÇû‰²÷_ë‹\þ÷ÆQÌãü²øÌéîçâˆPZeãùÏÄ]6ý|~ÿ+ü!þ·Æ9êÁøßº„{ã2ªqóÏÄæÅÇ“nÛe—Û2ýÈ<é¤Xí×L=Àÿ –D)­àNA}Alã}äšÿ¹¯ìÉÖÓóŠi·õ|nîM?»{nâ'¿xqâgwŸ’¸ãŠ“=ûž”ØoßÖÄ‘Ooݯçé7E·Ü”uSÁÍ==ŸÿNAwÁwv‰ ¾³/ÿçu´vv?½õ'¥OÙÍ¥û¾ìoû®:51¥ºà¶SææÿEõ•ϼû…·ír£êìØÆ’Nøþ6.9¢³—lèÙÊdʶòÐ8µ¬f+/ŽÃg,86ÞÊŠ°•õi¶ÜA Ä[YÙÊzf·²ÊÐV.-˜o[W O¿m— l ëá ˆ/·ø rÆ-¸Wv+—T_–·À¶ò ØÊ.®=»xA[ùŒÊÇÆ[YÖVžE“Ì~šEÕæSq¶ò ÜV6qm1÷\Ú¸zâîy×s»…g-Pý<·qÛ=w[˜øòržÛxiA%ý¥8»…Kê÷*ÎÆéIÏíVž¥ùИø-|ÆmeÍ—k|ÌVfðLò3â­œÎçrÛÊÊÈïôÌVöóÝGÎV>概֮áOo½}øÓ_öý›ö}Ù•Ã÷]uúð)Õ¹Ãã­üñﵕÅD [y¥aY¿•=¶õ[Y“j·°ÛÊî}º•]<ÛÊæßC[™zúØÊ}ß\®*7¹ •ùbîÿS nòérå¶ký²ô@ü?å{0n/W¶ž¾.W}lcÃæ*Pa5Ý2¼æÐW®¼©Ñ™©öDVÏþsNÏ]þQÿ+0¥û_pÿ¿…zÿÅ.A_çÏê©Ûðbû?]lÿ¿9Fê×wQÿeHBëôÁÿÅn´¥ø,ãqÿñ‡zË'­?lc·}“5îåÜà~QîÜoï6v¿äçSÑÿÌ0‡×:þû8¡$“Àæò Ìzטø_Ó.¥þ½ñqÜ”ír`!ñàãÊâ‹,n øÚ3ݲN úZ¼Š¤º·û½‘êˆÜ?Ž›‚úhˆÕ~²ë˜]÷ñ¯íúÌÑÄÓVÂÁ}ñ”>eNi#°ÿð@hêP8ê»àbíD”î±¶åüb—õ_ιi—U7ß¶oÏÏîœÜsÇå%=={¯ì¹{ß—öÜÅÿo>ý»=wíbÿ+úÿg=w§ÿ?»çî§ëÿ•ä;¦çî½ù?o¿ž»;wé¹[B÷ tp‡êŒ¤—wŒ¤žú·=óÎÉÝϾ¼¤{¿½WFûîûÒh2ÿ/úw¢Û]ý”seÁw N/¸e—ì‚ïíËÿyÙÙOï¸-ûé'ß”½ïQë³÷>ª;{ò~HÔìξ­ào nR}»ë¯^¬ÝÆ]¬ÌíXQøyB° Ÿ±ÀʰÞî¹ÝÊ.)v+óçËl Û ôÈÆõzc·²‚%ý[oå¡>ÄõãÁø Mñ©.nº£  ¿ði9=ÏØ#«g×Q8ø"Úð jÙïÿӃ΋CÇÖÑ0» ¸,^êÂÝöd|½™øáüš÷µxå¢O†²ˆ{ÎO÷oà®’CÏ~ñ.JÏ^޲BþyM)_eŠ|<9`ø.Ïàj’ÆÇ‘ÏÅq퀿©Ã•_网´‡}Å÷Þ®üJ`ãã²â(|ÕÝÅÃ'ï[<|ØÎÅÇçOä/ͺdxwtÛ®˜¬̤ ÂøCK7ïçïÎû©äYE¾;ЇçuωŠ”½ÿ‡ûúßÂæÔ;hÃݯ°«Üä ȺêYHQÖ38@û6µÃl:Œ)B‰cÇAr€³ Á¶°|©Á¸÷Ú*_y³øŒ"¥‹›b̼7B \ÜõâÀgXÜa†dT÷­òïÓç.šÞ×ã˫֧ç¡~ž‡þð<ïŸyžÅǹçYü÷<Û_ qæý¸ÙñþgodÂú¸Àˆ¯Âæåÿ6þßÁÿ{†ZØÄ÷á¡Âÿ𢸞ÿ«ø¯MY¹m8J è÷ÿŽhø®7Eßy ÿ·yø®‰øMõ½Þ Îÿáƒï»ÿç[Ø'>°…]KÖÉ„²oyF2ßÓ¯‰¿§~Ôâ?Ó—ÆßMïK»¢,È 8ßý¤m§ïþÒ‚Òwé—GMîÒ»ŸÝéÕ‡+ZyúöyÓüî]£5軈í)óýŽ£&ߥwo³ühÍuçì{¢.HêWÊ,9‘«mñy`û4°}ºÜç=vÿ»RœEMŠ6îuw:ÍÒ=ϳ˜ÍuH ò€ª€g$›¼ÔA=ÔE}ÔI½ÔÖïQQÎzæç¬z”·xïDvñDŒ§\:|Øå/éÞutÝôº+ïþyõ¯Ôsמ~ý©U=ßøVÏQýãž¿þFÏo~ý©=_[ÕóãOý¼úó®Wç½ø¥Ã§^|ÒAY'Œ-M\ºûš¨ói¥Ão+X›uuÞ—EG ·¸ }ŒÀVÖÖ1^ñØ>|é]Q_ú.›¹üÌè»ò~ÊÓ vókß=Å8#MÆäêg ¯fMó;ß=͸%<ûÙ€£á1 ‰ ~TyyOþZø Ô@÷ë»ï—íÜg€çªD%dÏ›²Ÿâ ‘)@ d§,K`²g Üó4j/îä¸mÛ¥/§„üYîýÀ§í”›Ÿ›o üóF5»hݲËιq‚Æì¬§ñkN?/©*¯d 4æg¥´S^ž ø´<~jKÙž7EOŸòr˜´zO†fxúÓil³{¬¿Jæ})ïi<×øê³¿=ÏßS ïeïCïÍcýÌ{›«@þ˜÷6¿ûÙü6›êoŠè¯ºÐLlÉzoû§þ˜¡´ Ö@™ ìõŸvêyÖÿ„qÐP°&4?zͼh íü42kLŒPÍŸ{NšˆI³ T>Û¼jvã§ò^c¬çúóó?'¿0¶I`Ò‡l7ë¸ç>}Îø”Îs¿¡H`ÊK ”kÚ°• ¶çö½yžoQ¶+ËÕäodÃÞïžç üþÕúm鉓W˜ý­Ÿ Eöؼ/8iÆ> }C >_ÿ½»¬ß¥;ç¦}9·M‰ î­ÓG}å5Êk4”×d(¯Ÿ¡¼fCyý å 0”7ÐîûÝ¿?R…©;?¶Ùrqö‡Üv_¾fÍîžL¨çQÁšÕkÖÄ ô¼øŽÝ_ù:—àoz~ ‰èòÕk:]z>áÐDÔ¹f÷׉*¨ø×O=µUïe÷Bé=¿˜A‚žÿ=ÜûãžÓë–´îõ‰Ë(úò—+¾dÆŒýßò–wöܱfÑJøÆ‚5¯ØC3rùË_>Ž 2ëŽ÷¼åË=¿¼hþüùÕ.~ÆßœÓÓó–7ÎÅ—Ïÿ›wöüú-A†¸ž½¯§ç[où‰ÿÛù }°ç×ó–‹^¿?ãå´Fˆ{ØÌ5Äÿ¦gÍ¢×át䵯?µ®îôž»ܳˆÆ¾ë—­1bÆLíž¿§sW½þ•Ù­§žžê¹íé=wÒš«öx%Ö–ÌU¿ï§sƒ^ÿJ¸Ur•fƧ¡s×=Ö´D‡>O¤/Z½ëë‰k3ÀU‚«vÝcw´#ìDRÁ ×ïÞ¢‘53›Î§33’ίÙÙ|ÛýчŸwܾ+oÚ?Q6ÜýM,)ëæÿª}'¯ì…öäŧ„ ‰—rÉŽµ Óíÿ“ÿ¡=ÿ¯~=>ÌŠ*}ÛØUÏïšóãïm|/ˆãß^àrtÖokóÛÝmõd…ûE9¶{ù¼ˆÍ‡*üsq}+!ßî‰Ô¶Ìóé‹÷–¼šÅͲ¨-äûÏœâŽãr®¶Ñýº“àÝùÜÄ«gnºÝÁÕý QÎ.ûùß ýö{&¦I³39‡òÝñ,Ÿ~¼ÿjüÄßWï?hÃ{1z{ók óüõwôó‰ßÜŸ]ƒ ú»¦O/öVŠº~£³§F»L3]òìW›µœ—›µœ×5Ô6ÊÈÁÛøngý¼ÍùDCm›¾‡oÞÿß켿ž]>gãõ³§–¡ÖŽ,¯Ô^ãñÓgÍE&>ž:½¢j ¤Sjj›£§gÕ—Íš‘/Ù3êÞèÎÂŽ¹}g}Ù˜e9™ªô»J1l=ùwMrébýbY{³æ&Öß”eB(Ì&©Œ4aÕŠIÀSÿX2~»Ô™úÇòÞ&÷€PÓ€XÆÞ¸KΛwÃbÝà»K~›w#cùxӳѱ´óvÅÚbÙô«óÁ^¨Ø!qî)6)îÍK›Ëd¿X±é±¾`¤ÜoYyí—*vd,Ý­bsbYî—)vt,¹oàáü8ß ;.–ú~¹b'Æ2èwE¨áž"£ÀÑÓç®hN¶¢Á¼ÝÕɼ²–Ü3 ØdHý-”œ#ô›ùtÉ8Bf*Åã ˆMY R„—³¨D ÕÞÀÿüŸŽVë>¾ìßWÞœ'ìÀ ã³ MÒ”Žòí­±Lk“š[“RBŽ*o¡ÑÀ8nK-{RsMÛ‰¸179±§%ç @³IÍõ5íNæXo½KÎ]êç$¯îŸõç2¥6ù›-F΋ы¢Å „qõbn•z¥æ=ñâéåSñQ{Ë ÃÈŽX/®˜3c.Úþ{ËM¼b„L¼¸|Þ¼¹ó¢çìgo¼•røÄ‹+ËæThO¸Vz+uñ‰^±¾³‡ä÷=¤NßCúá{Hßü<ÚÜÆCeŒó.ãÄC´gËC¥óOyG7~ ÚsrZô9ßÜ'Ý|ÒÍ—OºªG:[ÖÌh·"9­ZßÜÐ^]]²¤³º–èêËËÛ5R±Vf³Åä*2_k± ÂèØ×Z õ¦Óךé‘óµfzæûw4ÿy+7 •¿ý»µŸÛð `ú§ÈNbíy9-êå¶¼œYæ†O‹Å³³¢¹ôw<ï–…w±½“G?ÛöÙ¬Eݸê_qÓ·ïîÊÇS£Íñv©å¹@±7}à=ÆÙx¾bú¾ú²=×uÓ³öuyY{_’M™œÄUõGg.Zûi¬í™Z+§°”u%³ ×åDבã¸îšhVwn´sUný”ªï½ýîî›±.(]º«öJV—E“ì¦&_»fUÚ&ºY]Û™¬íhOöŽë²Qã–tV4#Ø~i­ÔÄWÖ†ùmé›ßÍîÚda1à’ó¸;Ïïn®fsmf×ϵfÙïÙX®#ð·.· _]»¢®Wj}jçÁÏ-é|ÊÁuZ|.¸†|’”øê¶‡óáb‚|r·0ðÕíçÃíùäŠaà«ëZ~›¦;ùä¦AùV·ý6î)È'Êwqê·ù€˜ä“{ò=^L2ü¡ãi>¶Ü×ðƒŠF×'F´Ö¬Pî©cùßîþº“ß³rq‘0ã1˜j૵gÿàæž;¿õéžÛ0ìûYï¹t;¶±k·ãÕ`›ŒãÁtQ´¶R#ïÚñèî&û¾¸ýmÃö·ÍÛß¶lÛºýíˆMoç²°>I_Y7­ø‹Ö×9Ѻ®è;…UÑ!ËWáƒqîË¢ÄUH\ݼW”_•“{ 22¨/§çÂ×ͼ Ìô­ÒÛFøšÞAž3¢Üýå1õ[‰a•«'EÃ^¿o®oޏ Ôù­%ÑèÕ/Œv~}Y4·óy;?ý6‰F«_íø¦hÇKÄ·r¢ÃïÊŠF_—Žùÿ¿X0,wJº7â¨v4¾Î¶õ”z¯‹Ÿd†?É ;ÀŸíÅWÇ&€?ÇiŒ°©,ØgÛ܇ê´_,`¿Œ°g—Ñ#´YŒ>Óp.@æÙ;v·3˜lÞmïØÑÎ[£y·ÅÞ±‹w„w;í;÷¦ðî{Çn½#¼»ËÞ±CGDóîK1~1˜ä^‹áN䛋3öxùíöN相Îbè_lËÔ_l؇3^öIv.æÃ>Æ%‰Ûµ8ÑY-ÆEëxá×]µYçšãnÆ-³yA²½ºŽ¹d£€Á|=8¡‘;[ÏÔ~»µ.zñ½õ´¸zdNfeM'õœÁѬ»N,r‚s¡/ë»°ÿÙ‘e™¥n½#š^’]‡‡¡ÖŒœðp«|Áæ¾,OØïßΉöpý¹,ÙÚP¿²gçªIë+—/hð}‡6‡ž9±\žøÝÃ-h‘Í%gÁÎ[ƒqNâæ’^{ …Q†þ`(½ös™Î3KQ^òÙ BN¨&Gç=ÌÏü}¿ßS£]·=_¦™p·»uG¡/~/ѵÖ[XÁ½5®]\oMF×[\ª ¥·r2|Œ_*2¿sÉÄDc²ùȃã\¶ÇPÔ1§®{Ôð1}7¼ÜÊ—Éä¼(ls½¼{*†SüĸKl#^"ÆÌ¯p3küBÁ)%øWi?7šîgc÷ Õµ„øªÁ<Çù<»¸‡¸<íƒyxçw͈{gð\ e?|'‘Ó‘Öôže$4‡få„ãüwƺ°- ïÖØ;ܾ\Þ9ÿ—±Ü¿ì 3í1 óèÿò¼Ûâ}ÐVo9y}ïÎp†Ø«»Ãj­ÜÄîÈÚÎÆŸ)ë+ÚÙÌ·œÙnï˜Ý¥aþý]×=k,s¹)äðw fΙ+7ïvØîÀ‘Oçîø”Žûnw0k~nqíUS)Æ:àx¡U–Ɔd{rbâà6?£8ûѺ(‚‡ÇöbÕ«£Öž-æ½fíÍѲ×gEܧ6q‡ÚR‚ÿžú.Ö,>†gWDO/Š[Â<-¬M†Yšl1úçq:òÀÎëj,·A3`Œ«¸ —QùK\_q$´Éç }åFwJò¾gŸU¼ûÍ£}\ÄBÞ2 ÅáÙM t¹dY¹´±#Y][k˜[‘¿CÄrFäï¸[r7sîFº“eùÚ,†ƒ¢ñ!ß„Ìm)*¶yÀ]Qç<ÇJn˜¨¼S›—u!ßž³7ÔîßXÞ$®‰¹ÕÁ±Qý¥_GoÌnã\ñ”®±7à ÞÈùNéÝðs¨‡ž¥þbï˜GÜ[úŸ½u–&Ý[îkéÛ…&gïÞr‡«¾%æÞ2/é[À²^gc9Nêñ:ëö„ñ:Ë‘’3Ë•RoN»_»râ`©7§Ås]9q»Ô›Ób÷®œ8cêÍi1|WN\4õæ´÷ª®œ8nêÍiÜSuç„–Ö›Ó8¯êΉ“§ÞœöÚ•×O½9-o¤+'¡zsZQȹ1G9ÁÅÞœ–?eÞi÷˜à´zÞù`¼z{[´9ÀŠõ¼ó9x^Ïaž¸ÜŠê9xçs€•ê9,†ºØå`2ê9Ìĸ:¸ó×sðÎçà®^ÏÁ;Ÿƒ›|=ï|îùõ¼ó9¸gÖsØ;§Í žƒw>„zÞùðê9xçgîC=ï|8Tõ¼ó9 ëÎÁ;åÀŸ±Ù[ÝþŒ‹Úã<Ûë·¾â®ÇúqÈÏoåC1#³â½n‘_UÊÑà.ç‚¿ ­FTÅmÔ{M}“º&àÜ$m+m“~괪溜‡¶]?ùÖzï'_WêL³ ¬È»ýq»‹åÿ‰¸ö çuméo¸ ØYB9Nåãþ79f&„¼ãÒQe‰&ú*M™«åøKZÜå´KüÀáxu Çøeh‘C,áèAÊ(7_ƒäøK®·knäk°îº­Æ1¢(×&L=·t¸KnEL+ƒ­£âN¶"ÊéŽ ýÓÝÂî¾ykçX^ÖlTâuq-i­+3¹üô£‰ŠöËÍšŸ§ØZeuzÇfú uvõ}™²Äò¸f½ §Lû¡ò'¦y*ß^ÂÒÃ$É/Öå0!iuw˜ü§©»ÃœšßfqÃfåUI¬ ÚôtâŒÍ¾er/!í‹}¿ío¸z¬š‡ËX£¦oøsãچ˟ëæpÍ9¸¨ÃåŸL{e„*‘Ç7©6š}2B—r±×F0ìÚ7b Œ’Óôœ×6r¾ëFÖ)xL»³NÑé²ë”¶‚…bÏ4$.êýÓE{èf ”Ó2m‘r¦ù%çu£”SõŽ’s3mÀQr>&¼¸Ÿ:£Í·Ÿ8êØ~ËéÐ~§¹ý€o·žÉú?ýÚiÀñ~rp¦Y-A½Þ_ûL“µ¿p±nc”Q{pŒîCš°1rЦ¾u’ |³ybèê÷ãßõ‰c;ƒhˆùχN´cåÌN›dìRËÿ|·‹ð w¾õÒÈd.ÜüWÌ rç <‘1Ù 8Lrö–:X‚<ç»8,«å`GØ”¾@‘¯–¿fµ89Ë*CâãoÝëg:ñ#Xo6Yqí%/t$F^0„÷ÅŒhry7мãöæ½@7¸º¾š®‹Yȼ@¯.ÜB{¿Íx…ö5âš¶F#~ojd*p ý“}Ol-ø_c¿pïQ©ñÎØŒ™—³êšé±»Ôܨ‘&¶¿i YÐßp3øu÷…G7?‰÷7oèmØi¥lc˜E×Óãìýöµ.O²÷ÙËbÓPµi19qB«‰Íˆ²wÛÍŨL;Ëu‹Š zCž#£ì½÷¶øÆÏxœ˜Ýmx’£Ût§ì*Âèg‰›0yÕN',Dï¨Bæ-MíL ¨Á;¨[CÞužÕÇÆ!OL*×/Ø…xÉæ¶Ê;¦ìÌ;P/y‡ t|$ƒTÐ1ú‚ŸDbà­Å6Áz€³‰ÑuP61ØúK,F'XL5(òe7 ê¼¾þØÅþÊ}‰õašÏíøÝtàÉNbÉL·óèˆÇ«pO˜u¦Ã¸óu8Ñå¶ÀôœÃÿѬ¸>ÓE-joãä\¯þÒÕþ®^¼Þ{G»ºLñ®™ jáÝA¶y˜Æƒ]Lù¿`ÀbnCvšyû‡öÖº°æÖe´s9„AžÏ§k ^îT^ †»–÷Õ}¦*²Õ(S”†O9r¤.çrUd"t¯|Ì;vËü¹¾Žq]Í:†?s7o,’´?X y8îmN¼î; âóØ ?ŽÄÈ‹¨ŠGL1ÞrÍðÈ„Ýä\ŽÄØy\šýnëc·qµ¶»žà2îfÙÕÈÓOq?Eܹü¦†a75ù?cs1Áå‚Uç{oö¹œ\ñ=z!æû+Ì÷‹k’ï—Áô®_0¾ü.æ¢KŒÙälw1}ø-ëƒÅ÷0 ülqò}D™ÅÎ93½i˜;¹í=oÃÞ6¸z¸Z÷Ö“Í÷Ý霼ñ½åGo³ºlÓiVg?3~˜?ÌŒï{‹«åÓÕüÛé9!<_“ëòHjç~ïEQ2:÷{Š’¡»ß{V|…ºëb¯T]ì:u œ+r+Ÿçf…›¨ï—ßWœI[Ï–¾¯ ×®PÇÌ„Pw nd‹\.îcÞ#ÚxT-1]EäÑðy¸`}ÖeæÆ ƒç±éÀ<×ÞÉn3‡ /Ãw¾…ŸHx¾sÜüÃE¥ßbÜüÃM¥ßbH.ù-†«J(¹³ZDIOð‰WJ‹8pK™!Ó¼¯¹ZSªò.wß+1½åŽß§%ì¶”y”–b”ûVö‡ ®$ÏoÔáyM”3)Ùʦ¨ÄÁõÉàm`’Ïéå_,YÉÔ%ݺ,ʾ¬µ‘ù[ÛÀµ`<«â²j…*_n¬¯®o¬A®‘ ½”4"éâQþ¨Ù>uUÿáò¶¢4òΜ]][S»,YåKµTÓBO'[Z‹fé’•QÞ›S-£ªK¢¼—¥ZFó-D„ZV*ÏÔÓiã£ü+õV¸Ôóè½V©åH¯©y«½V¬r¤kßÂ\Ö Dyor]ŸÌ6vsK”{lCó2´¯¶T7Iº”l£‰"‚-¥M›“K5í®­Ñ7Ú’SÖ *}Û½¶Q:~6¿”%,ø³&ÙeßÑÞ€‘üKZ£¼ï¸ Ð)¥¶çêV0ŠMú;$]ÏzÜÔ‚s—5äª\lK†åÒ(;;F)ç.Ñ:>¦¶š1*Œl­^ùÿÜ(÷%KjÚ¨øÓ M8n.¾Õ}¯là ³òÄKA_`?ɡʹ˩¬q)kuz ÔÍnúW§:(³4ŠŽ(©ïkáŽ0~òïhg$Hå¾¼½É÷y*OÓ«”S8ÛmWOùˤ¡Êò?0ï¾±Žî,XZ'`6NÛiCjIMcÿlIfœūȦñQØ¥®À×R× àT× Š\× Z×J]ÃêZ`lV“#:Q é’bêH:Z–FÙ×Ô‚j5ƒØ^[Óe¿x^¦7³ßâö¶({$oöoâÍfá¦&ÖíÚº¶p(`rÚò’â’ñ.Mbkop¡ÂεêCÿZõa@­ú0°¶•ÃÖÓ\í35Ï/¦—ÚÎk[sË °¼©U±€FæTQ¶ÈKjð+mf7zf²W6Œ)íþÚŒ–ŽÙM BSàÞ rËåÿdj'O³w…›/ÖÙP’Äòm#¡a‚äƒu”(p”s-R¿òß!ß(/O+^ã1[#¾©¦–1~F=ˆ\Gà©êŽ–:Mvò i¹ƒMÄ)|¢©©3ÊÿåÔξfÄs2Ð'AŠ•-ËV¶Évµ›ßør%àý´(ë“>¦uü!ÓÀ|c×QN ¸èD~`$ÓròìEÕÇ.œ;oz”sMÇx.wµñU~¿[/šÚË–5DYßS–Eq–¬øB}_¥ùq’è=zoŸOëkã«tОߤçÇ_ÅýêO;J¢ì 15ÜÕÈÀLçhåÜÕÙÔå~‘UÀu¶|Lu›GůW«˜â®Õ*¹XUíúó•êŽøõV«àâÕjK±«Z=,]ßÔYËH*)É„TPáƒM, h¶ž¬mÐ?÷à@ÉšåZþ… W WÆÿÚ„%qÛÁòYmËjꀷ•Õ-YZ]×ÐÚ¾²º¥f)O Uå‹H}™ÃÈSQöçë’K:èà%àÂQ5m+›A—i‚‹o­˜S5/Ê>ûDöÃJwˆQ³ò(gé@Qå*Иˆ=e€et©½0Ç<)¯J6µP:Ä•÷ ;ÿ§W·61•¤_L³—øÓ|Ž¿éËnûÙ¾z½5ô„Éÿt’‹[G§_µ¿¤©E¨\Èò²(ÿoj;Z[‘#_lqпò Áö•,ÊÊÙÌV¨¸ˆÁ»Kâ& P˃eLÖ± 5ì¿—Yô,ÚñŠùºFòæ8N ë*…\Ži)««k-]¬4QöÂ5¼Ü”â&;Eç#.ä0`¢ïlckjÎm£#¥ãPmæøX÷m+y§N(+]R]·í_ÆÎøJÛ²Ô ×©ø5.ˆ–ëÍ :°¬¾²¦{d£0Vö€sC ½±£å_ÚƒµäÛÌA)§Qou Zßff¹LEùÖ¶·6² {WÍšå½"Fê:\^ÍÜ 7¶ÔG9ãZøJÖÇvÛmdŸ¾,ÕÖ®Q`*¢ü4Ls(8y>§9Ri•E>¸XÕ° ‡¸)вk܉dy{ 0-nKÑ–;+ýh…Å¥së5´“Þ+óÔKõ`e'&ÓÍÀÖÚTíW¶Øc!”Ó|L«ú,Ùil}} IlŠ·iqŽ6øÔÀ³ò˜û<DùÃâ`”ýõ"ì¦ó\¯ŠÓKÇŒB âKPÃò?ËCZƒìkiÅùn"£¼inÖßó¨`…õ.Êo@½„` 6q”ÿáø®åŽÛ›N™Üèæß^ïÊ¿RSòÑnºš]Ò ð;ˇ4Çûa2ç±â«8ú]ÂmÐ…µ.Y_£C ED¹'–ŽƒŒýÛð†o+ë5B1ñq¼ÞoŠ–Ž;&Ê}7Ÿ3£Ü‹øœ徇OA¨wòy$§-}¶G¹ó9;ʽ²tÌ8¦ô½h‡W®ï‰êé8‘åü(÷s¤V­çSµ~”Ï©à´)-À¨¤§½Žûêðøv½îÊJ*Ê 5ÚsÚõê'X\-ÔuļùU*lùèF©lk~ ˆ]—ÎåÄÃÍêï·éLWÎ/r·ÁËs @­ÃÕ'ö5vÈ«ãuF™£Å—ÄÿœºøòDåü­Žqs3×[%‰ro-3žIü >DW¯K-º<šë"—É‹Zjšj««G¹c¤?5Î(÷_¨@Ó;¾tL cûË÷Ê—Þµ¡ó`ÜÐ<:µl¨à6ä1§Ýy´Ùžº!½LíN¤îŸÇXª;Ñ!€JÇLå¿ü>mß(ÿƒýcÖÛ§ò]ý‰zUùy¢½*K§¢ÜçÓ!mƉ¥c‹Ya“øÔNæS—¶3î“•r1óïoGi›õüÊå^So`‹ƒ†º$—³ÙtUòaT§-|8Ÿ³1.WÓY²ç)ýÃ_x[}W†ãKÇŽÂ^Þn“6ÕäÍŞȧ6ôI|êh2wC©…SªæN‹òÞy_—K…÷ máK÷ lO޸Тä¶Í|ÆÀ>/_ß¿ó ãîÇ#±K÷=üWr•t!ÌèŠ÷]&½Ëïï²CóÏ?è<¢ê”D ³Ò iÖŒ­Îge²$²©KU~J5‰t­Ê±r@s\å åë?lj_¬Z,’RO·óÎç‹ÛyÓ3mHi;‡þa°\I¾iéÛ†tX­öw Ú‘¾¦IÕaý4ÚT¢kµŠf%áªÚFzÖÃvlw`ËQG+”ÚVÔDËV+ªjË :c­pã†:^›Öî,µe·û‚ZÞ¡è‘ 3Ç®kP¼®½‹±£ŠaèöwZÝÑÎ\ ´Ü³nk©‡C3é¤5£{¶ôÃöìïZö‘¬–ýbÏ7&»‡n½t¡‚Žüû1ÜccuS^(ûX£#ûX¨œc%¥§-h!‹øy5ìâFDC)!ê* t)4ö³çÍÏŠäe&>×ï?äÅWe­>>+úÐä FF«_à“¢Õ/$°dôÛ£Õ'øO÷9žá+ýÓUþŹþÅy>°Ú?•, }±Ö$§gøÀ:Ÿl½ ­~‰q¡Ï±Á?ÝHàè­N¹ÀßF«[|²gù—ø¬›}`‹Ïq©q™<Û²ž¥©Xÿé¬îwhýÅ?f¯^¤³Ÿ—Õýa79ŸË^Ýé“>Çšåz½|ÿ¾SŽÎ>ÅÅ#›÷ú¾;»ûG üýîÙŒÚûyê^Y ØûŸ5)/«Jß³÷Ïêþ 2O¸#»û£.å}Ù«»\à³»¿èr·dwÿІgwÿµ 4ew_F`ô§dwʽhÎî¾ÒfwÎÞëý²ºÿÞ×ñ.0(»û.08»û]`Hv÷ ® +³»¿¿ˆ»ÿɆfwÿÀWÿèŸÝýe«ãª“}Ö/»òW»øû‚¬ÕÈ› Ù~š:ÿìqY§âöï¢ÓÆÚ0ne9¶½SCpÊs²»ÿÁ7æ·}à .К}ÚkããÓ^çRF× üAv4?:QRvKÍj¤\iºò0Dö< Ï?CmÏÃ(åaäÄò0Ü÷<Œ´XF_,ƒó0 Þ<ÌÎÎÃ0só0dú< $ÈÃåa´Æò0rcyÜ<ŒTAF­ CÜÏÃh@åa°hF¯,ƒ¹ò0(1#u‡QKÎÃHWåaÔ«ò0ò yVwF-oU8Ä‘B qäÐBRrˆƒóBbsˆC}qcœ äCqíG*-Ä‘7 qèÐ!):Ä!‘‡8(>Ä!¢‡8Tõ‡ÌâÐÝCR|ˆ#çâÈ݆8ú!Ž Xˆ#dâˆY„8‚!ލEˆ#lâˆ[„8"E!ލKˆ#âˆ]„8‚!Ž”tˆ#êâˆÿ„8"A!ޤPˆ#Ðâˆ4…8âL!޼Tˆ#â/…8ÒK!Ž@@ˆ# ∔„8RW!ŽpIˆ#¸∙„8"(!Ž Jˆ#.âÈŠ…8ò¡!Žðhˆ#¦â)C‘——áƒj«GÈ$_Ý¿O®–\xß.!‘ïØ§Ûû÷銨Qxtý<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£y<š‡Á£yØàц8x4ÄÁ£! qðhˆƒGC<âàц8x4ÄÁ£! qðhˆƒGC<âàÑg†8û3ÄÁ£! qðhˆƒGC<âàц8x4ÄÁ£! qðhˆƒB<âàц8x4ÄÁ£! qÄäB|âàÓŸ†8ø4ÄÁ§!> qðiˆƒOC|âàÓŸ†8ø4ÄÁ§!> qðiˆƒOC|âàÓŸ†8ø4ÄÁ§!> qðiˆƒOC|âàÓŸ†8ø4ÄÁ§!>Í㟆8ø4|âûÕàÓ€F— ±Èxˆðÿ.ÿgVµÈj¹Öç×¢Õå_V³œìÀj9Ù€–“}*çAv¨_é³^ç×»À7¢ÕoôWû§¯ñuÈlŸMÿZÿôuèÓ`¡ž5ët¹rÃé2sºÌÜ.ó0§Ë<Ìé2sºÌÜ.ó0§Ë<Ìé2sºÌÜ.ó0§Ë<Ìé2sºÌÜ.ó0§Ë<Ìé2sºÌÜ.ó0§Ë<Ìé2sºÌÜ.ó0§Ë<Ìé2sºÌÜ.ó0§Ë<Ìé2sºÌÜ.ó0§Ë<Ìé2sºÌÃætâœ.CœÓeˆsº qN—!Îé2Ä9]†8§Ëçtâœ.CœÓeˆsº qN—!Îé2Ä9]†8§ËçtâœVBœÓJˆsº qN—!Îé2Ä9]†8§Ëçtâœ.CœÓeˆsº qN—!Îé2Ä9-…8§Ëçtâhð‡8§ÌGÇ9Ä9m†8§Íç´âœ6CœÓfˆsÚ qN›!Îi3Ä9m†8§Íç´âœ6CœÓfˆsÚ qN›!Îi3Ä9m†8§Íç´âœ6CœÓfˆsÚ qN›!Îi3Ä9m†8§Íç´âœ6CœÓfˆsÚ qN›!Îi3Ä9m†8§Í5—•€/û½¬<-¾¬¬ÛpYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò°¹¬„8—•ç²âÆWiÇe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VB$â Áç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆƒ„CœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%›ËJˆsYÉãæ²âûÔ\V ìCô²òôø²²zÃe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃ\Vò0—•<Ìe%sYÉÃæ²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â Á †8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VB$â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+!Îe%Ŭ„8—•ç²â\VBœËJˆsY q.+yÜ\VBœËJ7—•ïØ§æ²d¢—••Cˆn²UCˆn²s‡Ýdç !ºÉV!ºÉÖ !ºÉÖ!ºÉÎBt“]à˜úñ®9p%åi¶cê§á3S? k†ÅÔOÃZt8œõam91õã]á[fLýS?„ÅÔa1õCXLýS?„ÅÔa1õCXLýS?„ÅÔa1õCXLýS?„ÅÔa1õCXLýS?„ÅÔa1õCXLýS?„qŒ›‡ÅÔOÇîLÇÔ¯ÅÔaœíæa1õCXLý†©_ãÊ5ÄÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯Æq@âbêWãbêWãbêWãbêWãbêWãbêWãbWãbWãbêWã¸Ñ qœæ†8nwC\Lýj\Lýj\LýjßÎ!.¦~5ŽwáÇUtˆ‹Y]ãr:ÄÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯ÆÅÔ¯Æñ˜âbêWãbêWãbêWãbêWãbêWãbêWãbêWãbêWãbêWãbê‡8L}E’wÄLýð¦~5Þ±OaêW¡[¢—•õCˆn²g!ºÉ.Bt“mBt“]4„è&Û8„è&»xÑM¶iÑMö¬!D7Ù%Cˆn²K‡Ýd— !ºÉž=„è&»|ÑMötزAfЇ̠;™Av2ƒ>ìd‡lÌÃÈ æadó02ƒy™Á<ŒÌ`Ff0#3˜‡‘ÌÃÈ æadó02ƒy™Á<ŒÌ`Ff0#3˜‡‘ÌÃÈ æadó02ƒy™Á<ŒÌ`Ff0#3èÇÎÉ æ¯‘ÌÃÈ æadó02ƒyØÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †8²h!Ž,Zˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!Ž,\ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`ˆ#3âÈ †82ƒ!ŽÌ`72ƒФ2ƒáýO÷ÇeO·¿)Ä#âoëË®n5þÎþø»úãaw<ì'â?ß¿­?öñ_ì‡}Fü½ýñ°ßˆ¿¿?öñÛûãaßÿp<ì?âé‡}H<ìCâwöÇüÿX<ìOâwõÇÃ>%þkýñ°O72”ù>02”!Þ·ž;„èéíyCˆn²­Cˆn²ç!ºÉ®ˆíC ÞÀëñaÇëñaÇëñaÇëñaÇë¼×“‡áõäax=y^O†×“‡áõäax=y^O†×“‡áõäax=y^O†×“‡áõäax=y^O†×“‡áõäax=y^O†×“‡áõäax=y^;ÇëÉ_ÃëÉÃðzò0¼ž< ¯'^OˆÃë qx=!¯'Äáõ„8¼ž‡×âðzB^OˆÃë qx=!¯'Äáõ„8¼ž‡×âðzB^OˆsgqîÌ!¯'Äáõ„8¼ž‡×âðzB^OˆÃë qx=!¯'Äáõ„8¼ž‡‡âðzB^OˆÃë qx=!"ÄáM„8¼ˆ‡âðBžCˆÃë qx!¯!Äá1„8<†‡—âðB^OˆÃCqx=!¯'Äáõ„8¼ž‡×âðzB^OˆÃë qx=!¯'Äáõ„8¼ž‡×âðzB^OˆÃóqx=yÜðzIy=ù{ÃÛñŽ}jxŽô!zYÙÖ=”è*»j(ÑUvõP¢«lûP¢«ìš¡DWÙ †]e/Jt•½h(ÑU¶c(ÑUöâ¡DWÙK†]e/Jt•];”è*{ÙP¢«ìåC‰®²ŸJt•íJt•½b(ÑUöÊ¡DWÙuC‰®²ë‡]e¯Jt•½z(ÑUöš¡DWÙ C‰®²×%ºÊ^7”è*{ýP¢«ìÆ¡DWÙ†]eoJt•½)öûwÏ¿>,¿XËóaYËÃþŸ;û>ììÿù°³ÿwÏûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûyûy¿y¿y¿y¿y¿yØøý qüþ…8~ÿB¿!Žß¿Çï_ˆã÷/Äñûâøý qüþ…8~ÿB¿!Žß¿Çï_ˆã÷/Äñûâøý qüÉ…8þäB¿!Žß¿Çï_ˆã÷/Äñûâøý qüþ…8~ÿB¿!Žß¿Çï_ˆãÏ.Äñûâøý qüþ…8~ÿB¿!޼Çÿ_ˆãÿ/Äñÿâøÿ qüÿ…8þÿBÿ!Žÿ¿Çÿ_ˆãÿ/Äñ³âø qü†8~C?€!ŽÀÇ`ˆã0Äñâø qü†8~Cÿ!Žÿ¿Çÿ_ˆãÿ/Äñÿâøÿ qüÿåqãïÏA¼Ôß_þÞøû ùñ+ÞwìSã÷¯ºú½­¼yÞêî­ ëÉ-×àN›f£Ò'Árûé¨I‡Ãþ‡>ìŒÂú°»ú°»ú°»ößp)ÌÃ\ ó0—Â<Ì¥0s)ÌÃ\ ó0—Â<Ì¥0s)ÌÃ\ ó0—Â<Ì¥0s)ÌÃ\ ó0—Â<Ì¥0s)ÌÃ\ ó0—Â<Ì¥0s)ÌÃ\ ó0—Â<Ì5×3 ›¿æp˜‡9æa‡y˜Ãa6‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçÐâ:BœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 q‡!Îá'Ä9†8‡Ã—aûèىὠÚWßsX ï9,†8‡ÄçâCœCbˆsH q‰!Î!1Ä9$†8‡ÄçâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 qs!Î!1Ä9$†8‡ÄçâCœCbˆsH q¯!Îá8›C£ƒ*é¡1o!Þ±oÍa±ºZÏ(]wÄ®ÃJz…yòÂÒuOÙ}þðGŽìôãÏ)pßö—â÷µ6O: mO^œú4¼‡n»8½ÓÞEÝïæÿÍ» ‰°’ŸX·Q÷{¢,X9Ò[x#Ð}¶¤ö%ÊNøÙÚ¡Ù W½Í’ìÕç¸@!{õÛ}@wŠÙ«µÜL€ýcoöYÍ’ì-.g¯>ßÞê¥ìÕouàkÑê¿r¯G«Ù„v'hÚ€6¡}ú Û}$Ð&Þó­‡n Mø°£Mø°£Mø°£Mø°£M Ý@›ÈÃÐ&ò0´‰< m"C›ÈÃÐ&ò0´‰< m"C›ÈÃÐ&ò0´‰< m"C›ÈÃÐ&ò0´‰< m"C›ÈÃÐ&ò0´‰< m"C›ÈÃÐ&ò0´‰< m£M䯡MäahyÚD†6‘‡ m"Ä¡M„8´‰‡6âÐ&BÚDˆC›qh!m"Ä¡M„8´‰‡6âÐ&BÚDˆC›qh!m"Ä9ã†8g܇6âÐ&BÚDˆC›qh!m"Ä¡M„8´‰‡6âÐ&BÚDˆsÆqh!m"Ä¡I„8´ˆ‡âÐ"BZDˆC‹qh!-"Ä¡E„8´ˆ‡âÐ"BZDˆC‹qh!-"Ä¡E„8´ˆ‡âÐ"BZDˆC‹qh!-"Ä¡E„8´ˆ‡âÐ"BZDˆC‹qh!-"Ä¡E„8´ˆ5´ˆj}Û^>ÄâIójF….ƧƣðgÙ«Ïrûp¤y•½¸ú$xž]t®flŽWn¼ñpƒ=½šV™dWÓ!sì¹z•Õqµî£&ÇU>pµèVds\ã÷F§¾Ü?}¡oÕ‹|޾Äû_⟾Կ¸Ö¿°íTÀNƒžÚ¾jl_õÂöU%Ú!Ð Û`Uo‡Iéí )‡m¹ÆË_Å®~³Of‡@é_ë_ØJ¯+ èJgsèJg·¨m•fÈÖ¡³é¿Nh}\Î~n(QêÅÏG:Øpöawöawöawöaw°áœ‡9çaŽÀy˜#p朇9çaŽÀy˜#p朇9çaŽÀy˜#p朇9çaŽÀy˜#p朇9çaŽÀy˜#p朇9çaŽÀy˜#°;wÎ_sÎÃó0Gà<Ì8›#pˆsqŽÀ!Î8Ä9‡8GàçâCœ#pˆsqŽÀ!Î8Ä9‡8GàçâCœ#pˆs´ qŽV!Î8Ä9‡8GàçâCœ#pˆsqŽÀ!Î8Ä9‡8GàçhâCœ#pˆsqŽÀ!Î8Ä9‡ø/ðýk¶ÈQ8¼ç(â…Cœ£pˆsqŽÂ!ÎQ8Ä9 ‡8Gáç(â…Cœ£pˆsqŽÂ!ÎQ8Ä9 ‡8Gáç(â…Cœ£pˆsqŽÂ!ÎQ8Ä9 ‡8Gáç(â…Cœ£pˆsqŽÂyÜ…4IÂù{sñŽýjŽÂÕý1,scé;€¡ûäMc÷i%½i¸ãBzʈï9eø‹DNë½-ÚÃ6mv@Û‡Ðöa´}Øía€vhça€vhça€vhça€vhça€vhça€vhça€vhça€vhça€vhça€vhça€vhça€vhû±s@; ÐÎÃí< ÐÎÃí‡ï¿áîÃîîÃîîÃîîÃî¾ÿ†sx枇9‡çaÎáy˜sx枇9‡çaÎáy˜sx枇9‡çaÎáy˜sx枇9‡çaÎáy˜sx枇9‡çaÎáy˜sx枇9‡çaÎá~ìÜ9<Í9<sÏÜÃó0çðìn+>ìn+>ìn+>ìn+‡l¸­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶âÇÎÝVò×ÜVò0·•<Ìm%s[ÉÃæ¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶â`Á †8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVB,âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+yÜÜVIo+ù{s[ ñŽ}jn+ÕùíKô¶òÑy÷HrõÙèó/‚åvg|8³ápèÃîpèÃîpèÃîpèÃîp8fÃá0s8ÌÃó0‡Ã<Ìá0s8ÌÃó0‡Ã<Ìá0s8ÌÃó0‡Ã<Ìá0s8ÌÃó0‡Ã<Ìá0s8ÌÃó0‡Ã<Ìá0s8ÌÃó0‡C?vîp˜¿æp˜‡9æa‡y˜Ãa6‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçÐâ:BœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 q‡!Ρ'Ä9†8‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡ÃçpâCœÃaˆs8 q‡!Îá0Ä9†8‡Ãçpâó¸9:(’ó÷æpâûÔ«õö%z8üX|[»á¶âÃî¶âÃî¶âÃî¶âÃî¶2vÃm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·?vî¶’¿æ¶’‡¹­äan+y˜ÛJ6·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·• †8X0Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶â`áç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[Éãæ¶â Hz[Éß›ÛJˆwìSs[©Îç²!C=GÝWaû÷W‡=~‚uöÉø\8rùЇݹЇݹЇݹЇݹpä†saæ\˜‡9æaÎ…y˜saæ\˜‡9æaÎ…y˜saæ\˜‡9æaÎ…y˜saæ\˜‡9æaÎ…y˜saæ\˜‡9æaÎ…y˜saæ\˜‡9æaÎ…~ìܹ0͹0s.ÌÜ ó0çÂìN->ìN->ìN-_ÜpjÉÜZò0§–<Ì©%sjÉÜZò0§–<Ì©%sjÉÜZò0§–<Ì©%sjÉÜZò0§–<Ì©%sjÉÜZò0§–<Ì©%sjÉÜZò0§–<Ìm%s[ÉÃÜVò0·•<Ìm%›ÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆƒC,âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ q°pˆs[ qn+!Îm%Ĺ­„8·•{‡8·–çÖâÜZBœ[Kˆsk qn-!έ%ŵ„8·–çÖâÜBœÛKˆs{ qn/!Îí%Ĺ½„8·—çöâÜ^BœÛKˆs{ qn/!έ%ŵ„8·–çÖâÜZBœ[KˆskÉãæ–â ^zKÉß›[JÈÏm(¼ïاæ¶R¾Do+¿ßVþhÃmŇÝmŇÝmŇÝmŇÝmŇÝmå6ÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃæ¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶â`Á †8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBlâÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[Éãæ¶â ^z[Éß›ÛJÈÏm%¼ïاæ¶R‡¾Do+¿ßVØp[ñaÇ öawLñawLñawL9`Ã1%sLÉÃSò0Ç”<Ì1%sLÉÃSò0Ç”<Ì1%sLÉÃSò0Ç”<Ì1%sLÉÃSò0Ç”<Ì1%sLÉÃSò0Ç”<Ì1%sLÉÃSò0/?vŽœ¿æ¶’‡¹­äan+y˜ÛJ6·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·• †8X0Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶â`ãç¶âÜVBœÛJˆs[ qn+!Î-%Ĺ¥„8·”ç–âÜRBœ[JˆsK qn)!Î-%Ĺ¥„8·“çvâÜNBœÛIˆs; qn'!Îí$Ĺ„8·“çvâÜNBœÛDˆsK qn)!Î-%Ĺ¥„8·”ç–âÜRBœÛSˆs;ËãæÖâ HzkÉß›[KˆwìSs[©ÎG_¢·•ß‹o+n¸­ø°»­ø°»­ø°»­ø°»­¸á¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛŠ;w[É_s[ÉÃÜVò0·•<Ìm%›ÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆƒC,âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ q°pˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­äqs[qP$½­äïÍm%Ä;ö©¹­Tç¡/ÑÛʸÛJtGÆÃ»n+!¬ÛJ붺­„°n+!¬ÛJ붺­„°n+!¬ÛJ붺­„°n+!¬ÛJ붺­„°n+!¬ÛJ붺­„°n+!¬ÛJ붺­„°n+!¬ÛJ붺­„°n+!¬ÛJ붺­„°n+!¬ÛJs[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æu[©Æ…«qaÁj\·•j\·•j\·•j\·•j\·•j\·•j\·•j\·•j\·•j\·•j\·•j\X¸×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m¥×m%Ĺ­T㺭„8·•j¼cŸr[©õ¿/ÑÛÊƼ•ñx+>ìx+>ìx+>ìx+>ìx+ã7ðVò0¼•< o%Ã[ÉÃðVò0¼•< o%Ã[ÉÃðVò0¼•< o%Ã[ÉÃðVò0¼•< o%Ã[ÉÃðVò0¼•< o%Ã[ÉÃðVò0¼•< o%Ã[ñcçx+ùkx+yÞJ†·’‡á­äaÃ[ qx+!o%Äá­„8¼•‡·âðVBÞJˆÃ[ qx+!o%Äá­„8¼•‡·âðVBÞJˆÃ[ qîì!Î=Äá­„8¼•‡·âðVBÞJˆÃ[ qx+!o%Äá­„8¼•‡·âð BÞJˆÃ[ qx+!o%Äá­„8¼•‡·âðVBÞJˆÃ[ qx+!o%Äá­„8¼•‡·âðVBÞJˆÃ[ qx+!o%Äá­„8¼•‡·âðVBÞJˆÃ[ qx+!o%Äá­„8¼•‡·âðVBÞJˆÃ[ qx+!o%ÞŠƒ")o%ox+!Þ±O o¥Úï¾Do+_ˆo+¼á¶âÃNË·–»S‹»S‹»SËo8µäaN-y˜SKæÔ’‡9µäaN-y˜SKæÔ’‡9µäaN-y˜SKæÔ’‡9µäaN-y˜SKæÔ’‡9µäaN-y˜SKæÔ’‡9µäaN-y˜SKæ¶’‡¹­äan+y˜ÛJæ¶’‡Ím%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%ÄÁ‚! qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8X8Ĺ­„8·•ç¶âÜVBœÛJˆƒ½Cœ[Kˆsk qn-!έ%ŵ„8·–çÖâÜZBœ[Kˆsk qn!Îí%Ĺ½„8·—çöâÜ^BœÛKˆs{ qn/!Îí%Ĺ½„8·—çöâÜ^BœÛKˆs{ qn/!Îí%Ĺ½„8·—5·•jÿNbñ¶ÒG‚A»/FÙŽ÷í~þYˆÿþ9ÿ˜ÿ_âÿŸ %z_üÓø¾xІû¢;î–»ƒ¢»ƒ¢»ƒâAŠy˜ƒbæ ˜‡9(æaŠy˜ƒbæ ˜‡9(æaŠy˜ƒbæ ˜‡9(æaŠy˜ƒbæ ˜‡9(æaŠy˜ƒbæ ˜‡9(æaŠy˜ƒbæ ˜‡9úú±sÜ­ü5÷Å<Ì}1s_ÌÃÜó°¹/†8÷Åç¾âÜCœûbˆs_ qî‹!Î}1Ĺ/†8÷Åç¾âÜCœûbˆs_ qî‹!Î}1Ĺ/†8÷çâÜCœûbˆs_ qî‹!Î}1Ĺ/†8÷Åç¾âÜCœûbˆs_ qîA!Î}1Ĺ/†8÷Åç¾âÜCœ{bˆsO qî‰!Î=1Ĺ'†8÷ÄçžâÜCœ{bˆsO qî‡!Îý0ņ8÷Ãç~âÜCœûaˆs? qî‡!Îý0ņ8÷Ãç~âÜCœûaˆs? qî‡!Îý0ņ8÷×ç~œÇÍ}ÑA‘ô¾˜¿7÷ÅïØ§æ¾XíßéC-ZBUÑvT>m¾ ®-_ޝ-“6\[|Ø][|Ø][|Ø][|Ø][&m¸¶äa®-y˜kKæÚ’‡¹¶äa®-y˜kKæÚ’‡¹¶äa®-y˜kKæÚ’‡¹¶äa®-y˜kKæÚ’‡¹¶äa®-y˜kKæÚ’‡¹¶äa®-y˜kKæÚâÇÎ][ò×\[ò0×–<̵%smÉÃæÚâ\[BœkKˆsm q®-!ε%Ŷ„8×–çÚâ\[BœkKˆsm q®-!ε%Ŷ„8×–çÚâ Ã†8×–çÚâ\[BœkKˆsm q®-!ε%Ŷ„8×–çÚâ\[Btâ\[BœkKˆsm q®-!ε%Ŷ„8×–çÚâ\[BœkKˆsm q®-!ε%Ŷ„8×–çÚâ\[BœkKˆsm q®-!ε%Ŷ„8×–çÚâ\[BœkKˆsm q®-!ε%Ŷ„8×–çÚâ\[BœkKˆsm q®-yÜ\[I¯-ù{sm ñŽ}j®-Õ~õ%Êdù‹ø¶rð†ÛŠ»ÛŠ»ÛŠ»ÛŠ»ÛÊÁn+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­äan+y˜ÛJæ¶’‡¹­ø±s·•ü5·•<Ìm%s[ÉÃÜVò°¹­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8X0ÄÁ‚!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·• ‡8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJ7·EÒÛJþÞÜVB¼cŸšÛJµ?}‰ÞV¾ßVFm¸­ø°»­ø°»­ø°»­ø°»­ŒÚp[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<ÌmÅ»­ä¯¹­äan+y˜ÛJæ¶’‡Ím%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%ÄÁ‚! qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8X8Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVò¸¹­8(’ÞVò÷æ¶âûÔÜVªýèKô¶ò×ñm¥uÃmŇÝmŇÝmŇÝmŇÝm¥uÃm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·•<Ìm%s[ÉÃÜVò0·?vî¶’¿æ¶’‡¹­äan+y˜ÛJ6·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·• †8X0Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶â`áç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[ qn+!Îm%Ĺ­„8·•ç¶âÜVBœÛJˆs[Éãæ¶â Hz[Éß›ÛJˆwìSs[©Ö߇èmåªE±ë›s7¸¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾Éø¾ÉÃÆõMˆãú&Äq}⸾ q\ß„8®oB×7!Žë›ÇõMˆãú&Äq}⸾ q\ß„8®oB×7!Žë›ÇõMˆãR%Äq©⸾ q\ß„8®oB×7!Žë›ÇõMˆãú&Äq}⸾ q\ß„8®oB—.!Žë›ÇõMˆãú&Äq}⸾ q\ß„8®oB×7!Žë›ÇõMˆãú&Äq}⸾ q\ß„8®oB×7!Žë›Gå6Äq}⸾ q\ß„8®oB×7!Žë›ÇõMˆãú&Äq}â¨î†8®oB×7!Žë›ÇõMˆãú&Äq}⸾ q\ßäqãú&Äq}“Çë›ïاÆõM¿êøžlO¢æaiæaiæaiæaiæaiæaiæaiæaiæaiæaiæaiæaiæaiæaiæaiæaiæai6€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4ÄY !Î qiˆHC@âÒ†8€4Ĥ! qiˆHC@∆8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! Íã†8€4@âûÔÒ<~Õ b@zÊ@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤y@š‡¤yØÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒg†8 4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆ B@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4@âÒ6€6_µ$´7Ú<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃÚ<  ÍÃІ8€6Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆhC@âÚІ8 4ÄY !  qmˆhC@âÚІ8€6Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆhó¸´!  qm7€6Ä;ö±´yüªÚ¨I€vÙ@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´y@›‡´yØÚІ8€6Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆhC@âÚg†8 4Ä´!  qmˆhC@âÚІ8€6Ä´!  qmˆ(B@âÚІ8€6Ä´!  qmˆhCâØÀ†86İ!€ qlˆ`CâØÀ†86İ!€ qlˆ`CâØÀ†86İ!€ qlˆ`CâØÀ†86İ!€ÍãÀ†86ÀâûÖÖ<~U] X§m¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡¬yÀš‡ ` qkˆXCÀâÖ°†8€5Ĭ!` qkˆXCÀâÖ°†8€5Ĭ!` qhˆ³@CÀâÖ°†8€5Ĭ!` qkˆXCÀâÖ°†8"Ĭ!` qkˆXCÀâÖ°†8€5Ĭ!` qkˆXCÀâÖ°†8€5Ĭ!` qkˆXCÀâÖ°†8€5Ĭ!` qkˆXCÀâÖ°†8€5Ĭ!` qkˆXCÀâÖj`=m`ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖ< `ÍÃÖÛÚOy qðE¿êKqΨ|CÎj\9Cüª/GÙg=¿ŸÚ—ǯº&θ!Gˆ_ÝI™Ï3þx޽9+Ížko‚ÅšçÙ›àjc«½ ºÌÏ·7Aiì {Ä^®´7+ÛmöfUxs•½97¼¹ÚÞœÞl·7«Ã›kìÍšðæöfmxóB{s~xó"{sAx³ÃÞ¬ o^loÖ‡7/±7ý›—Ú›g†7×Ú› Û—Ù› áÍËíÍEáÍOÙ›áÍN{sExó {sqxóJ{³)¼¹ÎÞ<+¼¹ÞÞ\Þ¼ÊÞlo^mo¶„7¯±7—†77؛˛×Ú›g‡7¯³7—‡7àÞ<'¼Gðæ¹á 8‚7Ï oÞX9?+ºìß—uê:žqUÖêã³¢M¾`d´š“¢Õ/$°dôÛ£Õ0…ì‹§ûÏð•þé*ÿâ\ÿâ<Xퟮñ/ÖúÀù>p¬óÉÖ»ÀaXÐ÷/.ô96ø§ }ãO°i‹µ;ŸìY>Ç%>ëfØâs\ê_\æ϶¬gi*Ö:«û]ZñÙ«áR½ÿ ÏËêþ°›œÏe¯îôIŸcM‡r½?‹^¾ß)GgŸââ¿‘Í{}ßÝý#þ~÷lFíý‡.M# š‡ÍÈæaDó0¢yÑ<Œ€hF@4# š‡ÍÈæaDó0¢yÑ<Œ€hF@4# š‡ÍÈæaDó0¢yÑ<Œ€hF@4# š‡ÍÈæaDó0¢yÑ<Œ€hF@4# š‡€hˆ# ∆8¢!Ž€hˆ# ∆8¢!Ž€hˆ# ∆8¢!Ž€hˆ# ∆8¢!Ž€hˆ#xâ†8¢!Ž€hˆ# ∆8¢!Ž€hˆ# ∆8¢!Ž€hˆ# â>†8¢!Ž€hˆcÁ Ä ñ›û㌆8£!ŽÀhˆcÉ Ä qî´!Žàhˆ#8âކ8‚£!Žàhˆ#8âÜCÁÑGp4Ĺ÷†8‚£!Žàhˆ#8âކ8‚£!Žàhˆ#8âކ8‚£!Žàhˆ#8âܹCÁÑGp4Ä qGCÁÑGp4ÁÑGp4ĺ?Þ±®>¿?þ¶þxÇ>ºú½ýñwõÇ;öÓÕìwì««?Ü¿­?Þ±¿®þëþxÇ>»úÒþxÇ~»ú²þxǾ»úòþxǾ»úSýñŽýwõ§ûãûðêþ}xõ•ýñŽy¿úsýñŽýyõUýñŽ}zõß÷Ç;ö©áS„x>3‚´!ÿ›£BíŒøÕvF5®QkgTãÚ Õ8|Á‡/âšùj~Jˆkæ«qø„!®™¯Æá†¸f¾‡Oâð_B\3[à qÍl5ß0Äúi§¾G穯:sñôg¹«ßO`¿¯ßžuÚa üîO³O;ܾš}Ús|`²=½úbŸì÷âo³3Ç­k|²X2íþ§^àþmÖÐ ¸ú#.ðÇ:qÓÞ§±WÝ×Û®So×=7=þúÃnÖQßÀ´£¾ÅYGÓF¦ÝJ{ÜÕÚtf>áÿuê¹.ðµ¬S?é—uª¢<ͺþB_kwûßí! ¿v«ÆY¢!Î q¯j"Wˆ³dCœ%â,ÙgɆ8K6ÄY²!Î’ q–lˆ³dCÒnˆ HUã,ݪÆYÂ!Îq–pˆ³„Cœ%âzCüm» e°AÒ}á7H¶&üRH×Dtê»#¦¿eh†}öp[Þ¨kBü† ׄjœ%â Ãg©…8K-ÄYj!ÎR q–Zˆ³ÔB\ׄj\ׄjœ¥â,½gé…8K/ÄYz!ÎÒ q–^ˆƒ,Cœ%â,Ág †8K0Äa¶‡8K1ÄYŠ!ÎR q–bˆ³C\ׄjf|ˆëšP³Dó¸apVç{Èk¬k»zl¹}´ ÜÀèîÅ–5mŸ>–®ÇŽ/Ý[l龪é†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ýgé†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ýgé†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ýgé†8K7ÄYº!ÎÒ q–nˆ³tCœ¥â,Ýgéæq³tÃûŸ±ñêþâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3Bœ‘ÇÍΨÎ ÏÃÁwï:ÄÃïaös™Þ¤¯jRZÁëV ^Ÿ¼Óh‘öi0¸éMwßàþB´“C7öo÷g»‡8Û=ÄÙî!Îvq¶{ˆ³ÝCœmâlÃjý}? É{v¼¼÷=Љôn·ïöæŸ1´BoºVðw›ôKCZ Ð{‡´èÍû†´èÍû‡ÍЛ‡[ò¡.€ÿ¸}Hƒ–ì¾E~ ðÁèiî€ô¶þƒPˆs q _ˆùBÈâ@¾ò…8ç€âlBœƒMˆs° ñ=}(„eôðêùð&rVßÛðáNÜñŒ¡ & ë¸ÑºÖbw“>2¤]gwoîÄ/6_ß ã£C#LÀwQÓC#¬®ïvâW†èÄdžèÄLJèÄ]C?œá~uè‡|"zªCοÐO½q¨!õ"ÄAÚ!Òq¨!Òq¨!rqrˆ2Êr=»-¼ùµ!0ϧ‡|@éÛAaŸ32Rlüäa~ò0?yŸ<ŒÀOFà'#ð“‡øÉÃüäa~ò0?yŸ<ŒÀOFà'#ð“‡øÉÃüäa~ò0?yŸ<ŒÀOFà'#ð“‡øÉÃüäa~ò0?yŸ<ŒÀOFà'#ð“‡øÉÃüäa~ò°ø q~BŸGà'Äø q~BŸGà'Äø q~BŸGà'Äø q~BŸGà'Äø q$B‰Gà'Äø q~BŸGà'Äø q~BŸGà'Äø q~B•Gà'Äø q}BŸG %ÄD qOB“GÐ$Ä0 q{B“G°$Ä( qJBÁ‘G`$Äì qFBÁžG°'Äì q{BÁžG°'Äì q{BÁžG°'Äì q{BÁžG°'Äì q\BÁž0Àg'˜êsŒþ'°ii!Þ±O·ƒŒv„ü¯ÿàâœYCœƒˆsðqΰ!ÎÁ?Ä9ï†8ÿçlâüCœƒˆsðqþ!ÎÁ?Ä9ø‡8ÿçàâüCœƒˆsðqþ!ÎÙ9Ä9ø‡8ÿçàâüCœƒˆsðqþ!ÎÁ?Ä9ø‡8ÿçàŸÇÍÁ¿ú‹žƒ®"‡•»ìJt) ÿ?áÔyD_F‡¶ŸŠ¿…Â4dÆT[ÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆCdÆ4dÆ4dÆ4dÆ4dÆ4d6¦!CÓ!ŽiÈÇ4dˆc2Ä1 ☆ qLC†8¦!CÓ!ŽiÈÇ4dˆc2Ä1 ☆ qLC†8¦!C“ƒ!ŽÉÁÇ4dˆc2Ä1 ☆ qLC†8¦!CÓ!ŽiÈÇ4dˆc2Ä1 â˜< qLC†8¸ç☈ q..!Ž©ÈçÂâ` q.,!ŽOðç¢â\PBœ‹Iˆs! qLG†8’ç"â\@Bœ Hˆsñq.!ÎE#Ä1Çâ\4B’!Ž ÉÇ„dˆcB2Ä1!☠qLH†8&$C’!Ž ÉÇ$`ˆcB2Ä1!☠qLHæqc22Ä1â\C¼cÿ˜ `ˆs ñŽ}d.€!Î0Ä;ö“¹†8¿çââûÉ\üB¼c_™‹_ˆwì/sñ ñŽ}f.~!Þ±ÏÌÅ/Ä;ö›¹ø…xǾ3¿çââûÏ\üB¼cš‹_ˆwìGsñ ñŽýh.°yÜ\C¼Ÿš!~]•ßÛUqvJˆ³SBœâì”g§„8;%ÄÙ)!ÎN qvJˆ³SBœâì”g§„8;%ÄÙ)!ÎN qvJˆ³SBœâì”g§„8;%ÄÙ)!ÎN qvJˆ³SBœâì”g§„8;%ÄÙ)yÜìðžÞ¿ÀvÆíý;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒgg„8;#ÄÙ!ÎÎqvFˆ³3BœâìŒggäq³3Â{vFxÿÂ(Çí„õÏ|75ø8ØD·¯í¯]iÃ6s€ÍÃ`ó0Ø<Ì6s€ÍÃ`ó0Ø<Ì6s€ÍÃ`ó0Ø<Ì6s€ÍÃ`ó0Ø<Ì6s€ÍÃ`ó0Ø<Ì6s€ÍÃ`ó0Ø<Ì6s€ÍÃ`ó0Ø<Ì6s€ÍÃ`ó0Ø<Ì6s€ÍÃæâ`Cœlˆs€ q°!Î6Ä9À†8Øçâ`Cœlˆs€ q°!Î6Ä9À†8Øçâüà‡8Øçâ`Cœlˆs€ q°!Î6Ä9À†8Øçâ`CœXˆs€ q°!ÎÁ5Ä9°†8À1Ä9°†8@%ÄŠ!0 q€`ˆüBœƒjˆüB â»Ø…8@.Än!P qª!P qª!ÎA5Ä9¨†8Õç âTCœƒjˆsP qª!ÎA5Ä9¨†8Õç âTCœƒj7Õç šÇ è ñŽ}jf!þS1 ý“ €4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó°¤! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ!Î qhˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ@„8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qi7€4ĤyÜÒïØ§†øÎþil•?šR>#¤>|f H}Xdg©‹ õaÑÁ¤š9ÉHó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4Hó0€4@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@â,Ðg†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qDˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒ†8€4Ĥ! qiˆHC@âÒæqHäKÞa€4oiˆwìSH«ï—Å’ Ϲ5kˆõ‘TW¢Ï ’Tîb¯‰—ÁH•-ú P(éÕèëA³äAIÿ.g¢ÕÖ‡è*Ó¯?7§†¨©­]"‹ù/ÆêBAïuÌEÞé^¶¹]‚Žùo(v„ÕQšûæß©Žð®Tiu«Žðî ‡EÑËÇ6µ×+Šk®¼ˆœ+x·yûC8D˜wºÊ…w‡åÙ;ówQ9ýˆnkj¯ãòX¸uC£¨©½¦ÿ]ú O:/æ}ŠGÏ×êã]^÷ô¥Ô}tS{Û†|QsãëȳÆ|,Ê9㤺d y«ó„p娖Öd}ô”=ö#62~w|Uí¶Þ½k¸KÑžñ»gFQþÎq¾A¿äÁ~ñ»5‰(:¼1ÎwÞ)<¿{¹j•øÝoI‰rÿøÝOqøJ†Åu$R<cý@}nDœï÷Ç£'¼ÃsSüîÏ%¦zÍ;Ì,°wÌÁ¸øÝ+tØ*Çïc¦£âw¯”šâ¼øÝ'¾Kì@«UBWÇ…ÒAoùþ:~?~wÿÏxpPüîzO…±qÿ† çÁÁVjƒv>~þmbÌŽ~¯‘Šßyñ»7üD3jßÝ0›ÖøÝûzˆi/™wˆ¯º~¿Xs0ÑÞ¡†zgü®]j®“âw¯}}rsÓ&…ÎÉñ»×ÍÇÍñ»kïÖ¢tïP œ¿ûí#³ï^Ï|&Ö¿ÍRæT]¬ãQOKïL!65ÎwœÔw4µ/éß[GJ¥rtjÉKê¸å;–µy‡ygÿNÿÒwš³/ùw…ô»d/vLs«½+fÞMÐø|ÚÁé;ÔKý»†ô»Ê›Ÿeÿ{‡¾®Ï'í€æï/i]ѶáÝ,Åkßkùàuï^Ï,Vî²|ù»·0-/¶|(ôºw¿ ƒqÅòåïnã°{òí– _û+d3»•},_þ® ƒãN·|hüºwËØ WX¾üÝÙ`‹ wY>D€Ý»«naŒVZ¾üÝ §EQÍ0ËÇ^qïþìê[kùòwá¶ÐbùvïþV{ùdË—½k:å[`Šé–ýêó‰ÑøjË—½kúûæÔ+-»ÐåûÖ<¾ÎòeïŠÌkÚ”ŠÝ»¦_…~dïú=ë+ÌÓLˇ”±Ë×}Y¹ÆòeïúÀŽÙ­c—oȳ™ï/X¾ì]¿ìø -bÈîݨ£é5–/÷çž1Õò¡–ìêký}½Øòeïšæ0<ïZˇœ²{w ÚÅÏY¾üÝ‹Á¿‹ßjù2lØüevdiË—¿û }Mç Af×ꙟ§ì]ó7Ø»CÖY>v³{÷—àŸx•åËß}…}öÓ>_†ýû¿n˱¿åËß½b>ûìzˇæ³{÷>Ò¥°|ù»£‘1¾Äòe7„þßý)ùZ¾üÝŸ£ršöÕhßoÌ“û~gïúÿ|3jŽåCVÚþäƒ ï°|ù»&׫±|èN»w#‹ÇZ¾üÝ%ÌåɧX¾ìf2àS"À¼Ëòåï>2*ʪ^bùP®¶¿–8[pÈæËß%˜åû´µï7Ô÷;{×RJ­c'Z>´¯Ý»•SÇ‹-_þn5ó4à§–ƒ{w‰öÁÍ–/·ùËì³WZ>Գݻ[ÅëzåËßýün@î»,òÚîÝg!4~nùòwŸûæõ™–ým÷î菉Ï[¾üÝ?pט?Âò!Ðmƒ&€“â¿·|ù»¹Üy‡åCÁÛ½;‚KéÙ–/wÄ‘C>`ùPøvï~Š»Si?Ë—¿»ž»H:¯(€»y9+ÌkönÐÙ„'yŒB¸{÷Qî,i?òww1¯_þåCAÜþˆûËÈ;-_þî“àƒaw[>î:îÝ=‹ý}ˆåËß}i2gWP wï¾ý ònùòw÷—…~£Pîûú¶ïwönH6÷¹!X>nîÝPæ>~¹åËß [Oú‘åCáܽ[þ(|Àòåõàñ÷÷î£ã¹‡}Úòåï>Á­bõî–…tûk}.w±bÂòåï¦1Më- êîÝÜ»øúKË—¿›î¹Øò¡°îÞ ~-ûùÈß±ìðë- ìîݵ`”~~Ÿåïn`/¦óÇȽ{½ÔÆ}}ápö¨.ˇ‚»{÷‹b"úùÈß½wzµ“åCáݽûû9Ô}ŠåËßý#Ä´‰{Z>«íoèAh)%?°|ù»C¸)N¸ÎòqStï–9Ò|ù»åÜÒ~£ ïÞ)µpßïüÝYìÅq¿j¶ü»ËÑVJfY¾üÝóžÊR¸Ìò¡@ïÞ½\É_´|ù»Üä®þŽåC¡Þþ†=“ûì _Z¾üÝAψ²ŽoùP°·¿á§Ìd<>Ëß½ûÇ·P¸wï>ÌÍ#YdùòwHwTdùØÁîÝ}¼+hù²w#r…Ãü<¡ïÞ50ßé<…wº×Nl´|Šùw3 ˜Z¾üÝÌ¿ã”yœåCaß½;V8ÙòåïÖ²ÛNóø~÷îEØó÷üÝ/A¬êñŠêîݯ‰ z†åËß}ú™ƒ{,÷l÷î·¥žÿ{–/÷;oàfè÷77iûÛo%÷‰±#-_þîµà¶ËfZ>Ý,Ýoô.Ü„·|ù»ìÎuoq‹uï®"_ìï%ù»íÜ>ÏXkùtCòï> 1¹Ùòåïþ€{ü0ÁîÝWÙ—Éå–/÷u°Âý>Æ¡€ýíÿaúQ~åËß½÷çQtÇm–ö7扃Ÿiùòw¿|g”õÖ}-ì¯íEÜ ñ÷ÎüÝ5QÖÎþ¾(]S÷÷zæ ß¾–/wãBNÞß´|8&pï~m.ý~‡åËßýúœòýý GîÝ?p'Nü½3÷Oܫ޴³åcgØßoE;­øCË—¿{w©&Æ‘{÷NðhìïIù»w½’~{¼‹cû;ðRnB•Ë—¿û08éŠS-Žìoü‘à¼RžåËßËÝ(Ý÷8>pïŽÓÍÌïûðNui>¸î݉â-ø|áÝs`ø{Žìï çƒ™Ê¿¶|ù»ÓÖFÙ¯à(Áþù${±ùlË—¿û„xH¾8Npï~MÈ÷#¼ÓJóáHÁ½û q|¾ðî§~_™°¿ 7cϱ|ù»¿`/¦õáhÁ½û+¹SðõåïþËš:ËÅþÇÍ£ð Ë—¿;¬v–ß`\÷îgàÊë-_þî瘭¹þ~€c÷î¯ ì=³¿‰KÁÙÅfË—¿»Þ¤ýÆqƒ{wqièwx'<·ÎïW9¸w¿ËL—¿kùòwŸ»\YiùàfÙߤ±§ þŸ¿;÷´(ëº×Z>=ØßawŒý‰åËßÁþ%þ¾‹ã÷îñ ^kùÂ;a…­þ~†#û›ò"0GÁß'òwç‚MÓùÀ1„{·V¼?Ḡ³ü¼f¼±)o$kùòwo?µù}WÉþ¿‚›kÅÏGþîcðÖM±|ïgj‘î£äïçqÅ?Y>¸GîÝÏÂ;*¼Ùòåï~Ž9>Ùx?IgOíá.ßçËßMËây•á›DŽ'Ü»íô©Xfùòw/ÏÀÝ×ôDý»£e½Âòåï^ò|öô/[¾ gO;kg¾¶Z¾ðN·Ã)v?HОôï¸zþAxw×Jîgÿ%p#ü»?â&Zx›åËßý)<›Z¾ —O»¼Xnù²wӳص£íŸˆKçÞA{3ú;Ë—¿ËmlÀ–Oz¨þÝxŠñ©–/w8XaÐ/,_†ã§—Q_ÁöMx·˜Ûç󌒠§êß}Þ]y¡åËß}œ[þˆ5–/ÃñÓo‚+æ÷Mx÷Eø gùàp¸w.Lãðtx÷`Y¿IÄ)tᆰãðzx÷5ðbÛI÷OïÑ}åË—½›!ìÒjx+áféß •àF»åËß KµÚþN2w‚Ï‘@†¯/wüÆ1~ŸI?Ö¿;I'Y¾üÝRvyÿoZ¾ì®0ã´8Ôòåïžö#îÍ_¶|ºUøw—J€âHË—¿{6¸dÌ,Ë—Ý!f¼>kâ÷eþî5_ç®ãî7 ·ÿîâÓ|Îòåï~¾HáK–/»CÌønxO‡w?Ï]g€ñ3n´þÝßàËÝGûÀE;Çî¯Iæn1sß©ì‰ã,_þn<û¾Éø‰8ŽîÝáâè\kùÂ;q1 »Y¾ìÎ1s üÚèµ–/¼~‰åËî3™Ç< ³|ù»“á~•³|`÷n¹fâ Ë—¿[ÿ ÿG-_v™Ys[È—¿;îTÙÏŸ0‡·ž:Ò|ávCÃ+,_vG™Ù*|ïó…wêSÑø‰0Š{÷lq‹Îòåï.‡§šØý8ÉÜ]fž¤›±ß7ù»ç+ Ë'}aÿîjqaÆò…wâMê¶|ÙÝeæYâü=×ò…wº œfø¯·Æ¿ûS8'ئ '.ö7ëyÌYá³qù»âž‡rþv{·á7”nÜ%sçï¾H}¯4œWÈðÊíÌÍ@ãQeïþÿ!! macbochs DataÍÃÉ–Êÿÿÿÿàºù5ºù8õ žR MacBochs.proj™åÉ–ÿÿÿÿMMPrCWIE¯xMžº&{­“ˆD)À7öº+û,/Ï:o1¾œ‘åÈ­ûtë¾øÓî•çBÉŽ<å4{ùÂäôóÊ#û$ ]ðÔ“­áÙ­o þ:®µ[N²œ½dyN–#“åÉ/GŽ/äyd“ÙB~“åìÈÂÉqòË‘[ÈïŽ,„/ä²™,Gn™ãdwä6Ùä¾…+¼@Ì?{²á‘cý"[€Érd°…ÜBF ù…l²# ß凂ò:' ìììü™üN>ñ6»íå Pî´s’·q3›x Ì6µ³×Ôkb÷ÙyìÌF^Žò2;‹v&°ã/HÏËINôÁ}BYÈ7áµà9Áp~ž_vʲßjµö´Z»>ÚÚõÙ¿iíúé÷·Z·n³z×î]¯­ìæg²ª*ʪ½T•çóÎx3Ö-åÓïÆŽmµŽ}¥Õ:‘üŸÞÿ÷Ï÷~û÷z_þÃçîý“/|ù7¾t?‹Ìv?ììþ؉Ø)ØÉØiØ&ì ,ßG»[Oÿ5cgcç`çbçw8öìì2ìIØuÄr qOºÿzì6ì©XôíéØ3°gbÏž={.ö<ìK°/ž ûrì+°¯Ä¾ {>öÕØ×`_‹}öõØ °b߀}#ö"ì›°oƾûVìÅØ·a/Á¾ûì;±ïÂ^Š}7ö=Ø÷b߇}?öØb?„ý0ö2ìG°Å^ŽýöãØO`?‰½{%öSØOc?ƒý,ösØÏc¿€ý"öKØ«°Wc¿Œý ö«Ø¯a¿Ž½û ì7é¡ç`—bÑ_Œ…t;¶[…­Æ2j¿Ë¹[‡E¯¶c°XÆú6ìpììîØ=°#±£°£±c°Üëô!ì^XîyÚ‡ÝËXÁø«í+è»±Œ–ÐXÆ:ˆeì ±Œ#tË8BÇ2ŽÐ#XÆú^jõ-ì·ñ•aËñ]‹ýö»Øë°×ÇFÇñqݵßÇ~{öØb„ý1ö'ØŸboÄþ ûsìMØ_`oÆþû+쯱¿Áþû;ì-Ø[±¿ÇÞ†½{öNì]Ø»±ÀÞƒe<Õþ{öOØû±ÆþûöAìC؇±ÿ…ý+öìß°Ç>Šýö1jÊGâ@à/‰Óx XŒ]‚EŸÏÇ.À¶`[±mØ…ØRâ7b×âã|¤|'r.Áú°~üèÛðÀäMØÍØ-Ø“±[±X¢S°|O»iÜS[ÆrokâÜÛ½¬Ñ¿½¬Ñ¿šz–ûW£_50A#ÔÇX£5ÐÄŽÁ‡}>öHì±Ø£Up¶Ì´Ob™;hêyÆ üÑ>•¸Vi9ö¹Xàã’¦þgŒÓÀM}RÃx§_uÖÀA ÓÀB ÓÀ? Óà)åP¸h10FTw€ 5£½É¡"@éS1VJeõ&V®ƒ +gåNG› €~F˜ ñ(âV ÜÃÈÈá )_…¯U=È:e½ÚÍÏüžZß·óI•C½ÑÓ•Æ]í¯d³Dv†Þ§ZE®~,{*›íguM NÌ„¹áïøù¥ö™OŠÇ©ŠÈ%3sQù¸Jòª—·'ÿ­ÛÌçkYZ:Ù4º÷èÉãg;Š®¤ c——f£áªŠvÊ€SÅ[²|òDžuóª¾ï¾)äŽî¼=`#0ÎÓS¥ª-äÞYHž¨+Ó¢0PQˆ$vÕá3Oˆz0¯ýùS ŸÆ¶ŽÕzœ5‡­7jÐòji«:l=¶Ûˆ†Ý › ~ñt>ÙyÁŽ z˜òî¶<î¶gﻯ½<¿xúìgf–WæÚ‘x·ý³ð•Áæ8ÉTÏ|¸å«!ˆÕ©£Ã iñƒ C!~Bð„ ‰á s8â)†( žB€äþPƒT!tb¸¢*†+p¾»X1hƒX1tq‚«)bB0 ”&!dB¸„8 ÑÃR!h²@Œ 5tÁ±ÈÀ Äã¬( aÂphPÂ.DT¨C•pg°I%CÈÅœ‚ ¡ ‚-DZˆ¸d!3¶)b,„X¬àÏaAò èBÈ…ÌáB+Äiˆ®V¸  q¢0„`Êf!›C(¶® ´A\… ‘â-iÕàž¨MÁšqD§¶:5ש¹.XOp-ß ¾Eà5 ³ Ì&0›à`nü…à/!8 ÁINBâ$Ì@p‚ øNp1ãIlgü ðƒÀÒ`ã1Ö†xCHCŒ ¬ ì!ð„4„ÂxBà 'žxBà 'žXB` %–xEpU‚Ãü“à¬#øÁß®Ið<‚Ûà£$ø'Á îGp>‚£Ü•à®w%¸+ÁY ÎJpV‚«ü”à§?%ø)ÁO þHpT‚£•à¨&x3Á› ÞLðm‚[\›àЇ&84Á¹ Npn‚O|šàÓŸ&ø4ÁW KpP‚·|–à¹Ï%x.Ás Op\‚ã—Äm·Œl)¶ [Ž­ÀÖ`•>e«(;” 7}Ê``8~ëÞ¦;÷£ !ßÕíþ¬‘DbExß:pãòË—Ÿ“uwûŒ#ƒ.@m€ å Š_H©O©Žò€12(8Pv Ä@ÉÂã(?!Åç)¥ÇQy h@韃²få(!!ä)å#ªz(åÈ‹ÄAq )MO)LŽºäž1ì 1l)Ú!%Û—Uª5â¸r Õ:4 5j6TcsTj²KÌ šKÌÖþÜ€ÁÝamG3é~öÅØì ØåØØ•ØUØÕXh7k±ë°ë±'bOÂnÀnÄnÂnÆnÁžŒÝŠíÄvaOy·\öøâã3 sSsgÅwc¨±P|sÏø˜!)íút$ nçFQ7nƒ$ãúö-YžŸ»s~8Ϋa>nÏmŒúe•¿1ŸÿËSÚ‰ù†Ä&W¶ïYrIz@$Üãæ}Üp¾ÆM¨Ää©;ÍÇSº…¬óhÙY¯w^˜ZÆ«fòµ.ž]N/HA0…Ř¯;À[R…^}kJEðTî´ÿzÑ̵¦ó]U>7AÙåÉ'è\*ÆbJ²©òÇ:Ÿu!ŒÅl§Tn&Dªåñåùöl9¬Ë~Þ^˜ôÇEëXQÕãörÞäÃqk:]sq±ÖžŒÊjܼþºdéÌŽ»5ë÷ËrØ>‘÷G­…3íÙƒz2V%:¶½”Õ¬ßxÌŸn-ÍÛI.ÀŒ#ZÜaCy¦¬úÝ©ŽžL;;Ež±Ç²>T¬é~lŠR¨¸#'Ãq1È 6B–×9[¹&íäârÄo±¼³¸<Õw¥?"‹Š ×rdóëN_ ‰U{qJíáeÛRZggm6€Š öƒJ*Õ­êY^EwÖd|»â¡fe5êiFDÊǦÊjŸYiMo½§ÉÈÁ={¯a¶†ÓVÛÉÅÂ] qÒ ;b!NT1‚•-W’r£ö!Ô“*XˆhPOª`1¢AÁT‘‡•í"8‰”áb8‰”á¢8rt41:q&®’ rmÑênË+àI;ÖÏ7ئcõ¨*;y]—UëÑ¢†„Cš¿þ°t*®7!ŠœŠëMˆ§â€T±X woœ pão’HP$¤ùÑb8ý:Öƒ‚!|ØšUE^O7l…Ûlã N¿JRIL‚`Ç O0Ïhuã(h¾ —faâ`\M²¸^ ÿÛ&õ¸´¿?¿t±¬ºuk¦£žg.Ôµ^·V2øèe׸öjØ&ˆçòѨñ¶NŠ~-§«ÊêÖÑ|mÒëåU;åÔ³âÚn!'_S¹y{“Mé"Ï[⊛ò~kþT{qD5×?Ma`VVñ[iQ7à×!ù°ñ-,jul\k’‹ S5ã,›¢”NnÍÜ6xKs¦%Ú9Á¶&X¡ãĪ®:­éN9©ÄÊqÕ_Ý8—WÛ7¶bì[[1öÍ­˜àí­ˆ‰µ*c€è%­û’VŒ}I+&xÉU‚±ÎñäܹÍÕ„Úœ:шèê®]õJÍ×äãÎz7ïRV;ƾüš~Ö[UM{"Â^øÈ#Wn·~¸Ýu‚)†+œrCöô¥UÝ&vˆÜ¨Äàj·DØM#vÕ$"Ø0[>–¤ìûÀm_nû&p¯±%ßÖn¹™zFšƒ#º€ñLP¸¶æ÷mùv1$®‡DØ%éL2Z䎡 ð;׋s;åV~û~ʺüÁŠw–çÆ«Åp«Ÿ™È„|öEº²Î…‹Âº(ü¡‹Â)UWµÓ]]Y}aÇ¿mpä{ŽlÝï´AC?6wªD 蝹Þê&Û‘œ‚ùXNX]!†Ý6Ý뇓„!0ùfm\Ñ1(êÎVЖ¬ªw®$~'þô+þÎbzCܧ‹Cn¨ؼëa­P–µ“B6ìãpñº!Üž›ëõÍ`¾GT>$©»àBÍ4v'Y؇ ÜÖäˆDX)Vv«2QÃ?¾±Lo»ƒÁ[;F‰ß g»ªh'X5È®z­d«Ç© ‚ÞPhÇpÒOˆi„¬é—£Ñ¥7¬œë²ªÛ­v*oFX)Ö—›Ô5`'0 '”Á£`€}¥“òKk%÷´SZ!V’Mù¡ Û ”Û f¬a,Y½Sk+$˜de“ 7:Í"®"‚)ÂEW|‹Ù_Ð m:Ôùx"ÑP’Ž‹U–ˆhˆ•¤sÍTÃvƒWfCñØjcì4{ºD#¶l× þŽÊ×òaw'ÍêªÈvºK‚ 6”»åÅáª0&ÁD‘@+á)ÃzÕêž·B¬$Ûz;- /‡nÌeuÉG‰°S0_éÀ§’¬Ø@Yí”\ ¤ŸåÝÇÐJ–.¯CÊ,6À°Ã5pÜÂM˜&tUeõâ•€UÅS«õ” 2Ž«Å. ÿêª*+zR¼–`$;”cfP °ÜàeA÷êA#ãXn®÷€ÐJÝ â›wU,3¢«‘#lÿÖ­ú±`Ø‘ÿJ¸2BÐ9üœ&ƽ$‚ƒpÑ·”ý¦ MߦrðF|Ç¡Áƒ¯°äÃìÕØE²Ý"·¶ßN·5ï©Jõñ'Â(ÆÀ*“² n‹‘’I døPnm†ÎPÄõâ¿fwBȽ©¬€ž k9jÇ àî^u5€¯ ˆÞ‰;Ø®2.î­Îõê5?˧Ô[ˆeC ܧŽ-R:zýIbÎFT÷°`î“S3061=5Dø6¢F›?ß ɔڌèº4JÎS¬€Aú_yìP±Ãϧ“²^C×Cñ0|õÄ Ä½¾7L Dü]]¨ ü+¤C&Ø\o\Q†ƒøfp1eœæÓÃBmÁz¶a-“"X95j`Œ ,›¬õ‹N{~ØéOh»DÙ$ñº…mqÐæ~E\¸ˆèíÜšê à4–èiG­;¶4lÑMèso~=ßÜÅÆÅácÐàÚ® ½;,±Ý»v$vv4v v,vOì^ؽ±û`Ça÷Åî‡Ý{vö@ìA؉ØIØÉ؃±S°S±3°3±MØYØfìlìì\ì<ì|ìl ¶Û†]ˆ]„mÇ‚={öpìØÅØ%Øç`—b—aŸ‹={öyØ£±Ç`Ň}>öxì °/Œ—Ï㯞÷¿vÎvöTìiØÓ±g`ÏÄž…={ö\ìyØ—`_Š}öåØW`_‰}ö|쫱¯Á¾û:ìë±`/ľûFìEØ7aߌ} ö­Ø‹±oÃ^‚};öØwbß…½ûnì{°ïžû~ì°Ä~ûaìeØ`?нû1ìDZŸÀ~{öJì§°ŸÆ~ûYìç°ŸÇ~ûEì—°Wa¯Æ~ûìW±_Ã~{ öØob¿…ý6öZìw°ßÅ^‡½û=ì÷±7`€ý!öGØc‚ý)öFìϰ?ÇÞ„ýöfì/±¿Âþûìo±·`oÅþ{övìØ;±waïÆþ{ö^ì±÷aïÇ>ˆ}ûðI¡Ô°cóÍy7Ÿ‡û<ÂçÝ}ÞÃç‘>òyôñS§ÓŠhX+G÷ZSŸ ö’¦Ôç€Ï5ÛiiS‰½Y+|.ó¹ü;.€@,kv s¶seùÌ.;Ð>ptfe†ã²ùÙ î)Ÿ«3—ü‹÷:r7ÆXXw”ùÝÿô ö›û¿ŸÅ[0Üvx0æbŽò*[ÏókÀGûÃc¼²à±ÍÔ æDŒNx~3aƒyu1ž1â^ès‡ïs‚ýË}Ÿ¾ßJßg•ï·ÚgÇÿT‹¨Ú?«Qxˆ±ùw´zR„ŸÖŠÅ;¯mÅRDàŠ%¿É‹Ç»fæ ZÉðð£ZÉòÎV2Ú|r+Þ&‘gÁÒ¬'¿âÚÞxŒÒˆ ?&‹ÇKðx.qËëÏ Úá}ÅSñÇ,üS¨ñ®šñ£ñÄX,‰ó¼Y&E¶ü¡GÐ’áŶŸJKFãõ´Th¦AÂo¬ÅâÃÏ®Åâ-†§TÜL†ÓŽ<üvñž),¢ÍêÉylƒ¨‹‹úÍÇ2óŽ@GtΑ ÌžrD§Ü Î`€™!Þ(flo“«¦èð`|¿T| ¼—nD§Û N¬´X€l¤È¶ Sî4X›Áù6MµÛ ÓV`ª2è @#: ψOƒ³œ*e˜çió0ŒFt†‘ †žaD§aØ Îô·™!Þfl¦)ú`8ŸÀ%ƒaÄe`Ñi¶‚Óë…a`)r0l'È”; Ãfp¾MS0lÆvð˜j‡ #:ÈÎÂ0âÓ0l§J™†a~p7ÃHaDç` ú`áFt†ÍàL›âMaÆfš¢†ƒñ \Rñ1F\††a+8]°^F`†‘"Ãv‚L¹Ó0lçÛ4Ãfl7 [©vÈÀ0¢30Œè, #> Ãfpª”=0<(K…©Aiª_œ*ÊSjH¢Ê‹T™j@¨ª2bUQ®Ú.. ÊKƒSAb™ò2SŸÐTšŠbSQn”~ŠâÏ üÓ/% ‚4$å… ‚4  ÈAA¨( mp%œA§ ã 9y)§OÌ)È9EA§(é Ê+EePbéYŠ2KAh’ZòbKAn\$—ŒèR”]¶‹$ƒ2É PRJ†Ä’¼\Ò'˜$“¢hR”M"kZ$Á.š$wÑ À‹&‰C^4E ô¢z`/– Ö±,ᎌÅGÏiœ8üõæˆb‹“#ÑØF3¤`0š&„‰$ùrõ€a,Á@ûub,>‰ñàloÆ`1š!ŒÁ#š$ŒÑ#š¤ŒIá#š!Œ}âG,Kª3ˆÓ8`L‹ NŽ$0&…h†A`̈!‰$ùr倱O‰eɶ_ÂHO‚>`LŠ#Qèìyˆ'Èásdô!Ü+æGsôú±Y~Ñ#ìGû WåäŒU4’\oo;?éÖáRI†øI —ÊÒÏOT’?Q×ÍóGÊËæè‡¥¨—MÑßšü$¦â¥ÓdøI·†—JRä'݃`¹$I~’Ð S™†øI\)Lç)ð“^0›¨Y~∄}9òü¤["L%ä'Î$^6G¡öE~×,SyúùI\±Låà'Ýze:IŸ¨ëæù‰£zfsôÃRTó̦èoÍ~<Ói2ü¤[îL%)ò“î1Î\’$?IȪ©LCü$.ª¦óøI¯¤šMT‚,?qôÔ¾y~²]M Ò¦ÒùIt¤6›Â¬mr«Ïn~’Êæ'©$?Iå‰ð“T–0?I% ‹lŽ0ždIOeSô÷T„XäÓXˆ™Nc‹Tx˜X¤’„ˆE.G±´&±HÅ÷‹T&‡Xòô·IˆXdsl›XdS€Xäâ Ý&©$ab‘J%©4!b‘ÍQ¨}ø¹ïÄZ°ÝÄ"•'L,RIb‘Ê!©,ab‘J"ÙÝ›²ˆE6EOEˆE>Mx·×>b‘ ì›L"¹ÅÒšÄ"ßC,R™ºWÍçéog5ÚíÄ"›¨¡k‹Ä¢/GX¤’„‰E*I”X¤Ò„ˆE6G¡öCÄB!ÅâlØ›°h`:‹³5oš1Xûòfï»°ì\¯ j·èÊ‚ 4¸”¹àn7²ÃüÇŠra8VX˜ÒXQNX!r ƒX8R:7c¶D°Ê‚³ 6gP`u­n´BÂ4ÄŠê¡Vh¯ÃA‰ÚÚˆŽGœb‡AÖŠê]€8n8[`Bs=,#è©×oÑžfXлûÙŸÓ²ƒXʯä½3]- ˆ%ù|KP>ci=¶TjYÀ»±…ù1KµP³Àa×)mvFÚK¬l!² i©Áò1ﯰ‹Vàâ}FHËÿU–uÎýIËøUý¾|Xޝzy½d©@ú |5'X/“}á«](ŸÂ§kyúãù˜|º–'¬Çŵѵ¼`ÃÓlŒÍ>,ØØ/T]Ëü s>,Ø·Ûxv…úé…oø¸ÿ‹z´ÎΈb8Km,u¸Ïîg…¥ý¼Zqu@ Ä¢ŠðaAÙûÌ«%±¸"|èE,°È‹.–h,²ˆÆyÂîg‘K´|â­›»ôO‰BÄ‚‹ÈE ±è"|XžpRƒ-:89áA‰– <8áAÉËø¦$<ði鯩 |Z†qZŸRœžðÀ§âÎHxàÓR‡3ø´paSŸ– œ•ðÀ§¾lNxàׂ³ø…[søµTãÜ„~-»8/õ·_µœŸðÀ¯Z.Hxà×R†¼€#úϯ… [ï¯Â@Z&raƒ€z\”ð  ¾lOxÐŒ‡$<h!ÅCÔ—‡%<h™ÃÃþß JµžËâ„¥ZD >òb‹¥Z‹>r­Kµ°#~d¬.ÕâŒÀeîçR-°ˆ y-£R-—,æå(Kµä!‚ä%Jÿ‘3jÅøR&ŒÁ‚¼e™—Ä¢X: wü e™|<îÌ=Z¦¾ä"½àD™úòx­ Ï>àý ´=ûnÅ÷B-dÏŽZ¾H Ù³µ|±'ûÀ':´=û°lä Z@ž}ÜwX@ýW®ÅW$ü+ׂŒ+þ•«/W‰T³ƒ}GxQÊ -w¹F¤}è˵bðìCo¬Ë—3xKx¢˜ä}h*´@$¸è{ï€ 8 ?¬øK¨?h0fÓK?¨•–*…­›[»÷±€e%w×F/~¤f¹ÆJq£“{Ómp¬Ô“[_jÖ­©Ætê1öaH,žÏ÷­Ô‚ާH—`ßø¶éÍ|nYôå©z5Š}èËÓô–û€§ë‰*ö¡vgH§`úòÌt¿*ñ˜³Òýª´äÙÒ+Øw?¾sôÄS'ÆíG¥[°<î<½TÀ>à°½·@ á†a!Kø°Ü$³„Ü ¾û8€ï€ŽaOpCø°'·„˜Î–ÀÄ"—ða)Kô#|À-,v zµ…Ü‹^ưÔ'ø|àFŒÊ,C­àò™X>,~‰…0áÃò•X >,O‰1áû;,Š Úˆå@±0&|àÈ–åD­àÃòšX$>,‰‡‹\b±Lø°d%p ¾G8 ¨(– Å™ðo·EåЄ=†E4áÃò™X„>`-¸$|¿ã^lÀ¹±¬&|ŒŠÃ‡Ý>ƵÄ&|èg`8|È‹¥6áò™Xn>ðà h2ðËn¾ˆ¥7áÃR¢X~>p_pøÐçX†>Ü ¸–Úg„øŠ%9A½ÁG±,'|àœXš>à70>ÆFµD'|èg,Ó †‹q‚ÇÁÇð«–ìÅÁ¨X¶>,o N…˜‡%<áCÿƒ À‡{‚³ÃÌ€þߣPOþ†‹w¢7á¿AÁm¼>à x|è1,ó â¡9ÀŽŽò7B8 þx3ý„Ë›báOø€CÀyø€X>Ô‹€Âþ‡å?ùÃî«j9PøÀÉ€áðÇ€ÀŽ.p „‡>Çò ðá>À7ø䬿oñcô|XpK¼Âþ…CáÿFMàÞÉ¢{¨—€iðá|KòÔšaà•ð{ ùÀž äš|Àt`|À…;íCî²Ü½Æß(éÀ øÀ³ï±x¯}XRõö¯Áwà¾ÈÒi£T3ð,þ°ÛžöUûÐg±Ø®°½¸8|Àú‡íŽ Vð¡ŽÐ"ø#- œ>h:àõðÁeàîÀ(ø€÷ÿ°œZ|Œe¦ä7†~#;Çr&ëcÑ•(­z¦µ¹¥uд6ܘҊgZFâð1î“×2 N(Ý>®i[þö¤çÈ[PíÉB´$|†µ Jk§i‚’¼…¹iÑ[ø¯I>îsÒâ·üíE^fÂǼ™´.|¬ƒÂ…y!5d‰}ÌëH\>æ!$ì‚q´0.|Ü{$m¿½OVÀR)û/Iœ>朤Årác®BZ0>Æ;Ò¢¹üíCÿ8 |¬©‘ø|¨Ð…Ú&p>æŠ$~ãIÛ„µýo}BÖÿÆ¡(}>è)¢ÿƒo“°>æodýo˜NâDð1^Ûåo_êEÖÿöU½EÿÛWõÆÂ»ð1'ið1O#éð1Ö“áåo?°€´/|¨74øXo ñwøx1\Çñ´0/|¨7ôø—I ôò7ž&pCù˜gp>æ$Þð öÂÇ<–´h/|èoðzøe‘8ícôi_øXk#qsø˜’p>æ$®ê-{Ùí¯zcQ_þPCs†û‡„Éð±Æ¢´nø˜·‘ù…õ†0óCÒb¿ð1ß i>üMƒHú|¨7¸|èoÙŸtœ›¤ÿÁÇœ˜¤ÿÁÇœ¤ÿÁǼ‚¤óðw øBÒLàãû“ô?ø ½C«õ’N s`ÒÁð{°H0ï$N ê ®ê úº%|ÌùH ÃÇœ™¤3Çzs=ñMTC„{ž¼lóDîCâMð±NH^Öm"šIƒ93I‹€¹‰ñ7Iw·…ñ‚¬ÿMâžjî>Ö¿Èúß$t²þ7 ®NÒácîGÒ"ø› !-> êí>ô¥¬ 7Y}‰mVáÉ®f“…CX>p#,JÌßÁâFX˜>Æ/’–êÄ}¤|¬¯‘44øX—!orv0œŸ¤ ÀÇܒĵù›¢;ú1|Ü3Ð[•õ5²þ7†¬ÿM?ýoŠøèSá-jF>ÆD²þ7U¼Pô¿©â…¢ÿMÕDÿ› 'ëÓà™dýošæDÿ›ž’õ¿iô*Yÿ›&Î!úß4ñÑÿ¦©N¢ÿMýo:œ‡¬ÿMOÉúßtú¬ÿMΉþ7]¼Mô¿éèdý{e’õ¿ð+²þ7C\Aô¿â ¢ÿÍàndýo†î$úß t²þ7ÎLÖÿfЉþ7SÜHô¿™ÂNÑÿfr²þ7SéÖÿÚéÝú_;\B·þמêÖÿ\>SŒE½ÌÆ„&èÙ³ð¤x"´<ž¿<\œ YIkï¢ô hOÒjÖKúO-uè'Õú…ôŸZÒ\úOÍüHÿ©™é?5£Âý>>&ý§æª_ù³fAtàrÍÚy¹”Ö\Ûú (ˆÒ¥ÿ”fZߺ|YšcCÙ$Tº›ôŸÒ³¤ÿ”~Äú«Êfxë§JiÐVFŒõDi¢¿*Î/ú«âÏ#ûYGó à¨¬¿ÎE RœpôÝ­÷ ßÁ߯$QWñœ±\Üú4 à£è¯ _ön=¿Ÿ8]÷Üçòå¯ÁYti¢¿êê¿}}î)]ZØ~IJ×U­ñ­÷<×¥ƒ@åºëÒ xîìC&L=] #é✢¿êâc¢¿êªÍDîÇ=¥‹LJHá>NNÛ?zT/Ñ_=ÒLEõHCýÕ#MôWt¥é3KKèõýŒãg;ð:´€™Kâé¿mÚý¬ÚÊ#þý•9¡GœDôW¯0wvëù€I^ÕwýÁýæ•–*ú«š[Gý¸—¼Òéæ§åQ½Ò³Dõª¢¿z¥Mˆþê÷ýÕ+ž)ú«WýµDz“è¯%Â[Ñ_KÔ¢¿–ˆsŠþêÓœ€è¯>éúT/Ñ_}ª½è¯>¥è¯>á™è¯>a°è¯>i[¢¿ú¤%‰þê“.#ú«Oz‡è¯>á±è¯>q{Ñ_}âÒ¢¿úÄKEõ 9Dõ ?Dõk>AôW¿úXôW¿0EôW¿úYôW¿úGôW¿ê%ú«_÷ýÕ/SôW¿j,ú«_}&ú«_Z›è¯~õœè¯~iU¢¿ú¥ ‰þê—^#ú«_µýÕ/CôW¿j/ú«_¼]ôW5Ë+úk@$úk@\Eô×€æ1D hÎAô×€°Dô×€0Bô×€úMô×€j'úk@1¢¿¤‡Šþ)úk@Kô×€0Oô×€´*Ñ_ÒqD Hãý5 ZŠþZ*>,úk©fED-GýµT'ú«š!ýµT=#úk©î)úk©x•该Ò.E-•®'úk©´-Ñ_K¥‰þZ*MDô×R颿–‰ŠþªæE-SÍD-Óˆè¯eÂnÑ_Ë„w¢¿–©ÏD-S_‰þZ¦ºˆþZ¦Ñ_Õ¼²è¯eÒE-SýD-ßýµL/úk™ø–è¯å⢿–‹û‰þZ®>ýµ\Cô×rá²è¯åÂ)Ñ_ËÕ‡¢¿–«¦¢¿–+^ô×rÕIô×rÕIô×rip¢¿–«N¢¿–Koý;›ó—Â6Ñ_+ÄE­ýµB|Eô× qÑ_+ÄD­‹þZ!lýµB¸ úk…úMô× ÕQô× Å‹þZ!­Sô× a†è¯ÒÔD­ÿýµRØ&úk¥æ¦D­Ô<’试â~¢¿VŠw‰þZ)œýµRÜCô×JÕOô×Já—试êmÑ_+Õ¢¿V*¯è¯•â ¢¿VJ+ýµR8'úk•ôÑ_«¤SˆþZ%ýFô×*qtÑ_«ÄWE­ÇýµJïïó>Oðù@Ÿòy¢Ï“|žìóÁ>OñyªÏ3|žés“ϳ|nöy¶Ïs|žëó<ŸçûlÖ¿ÅçVŸÛ|^èó"ŸÛ}>ÄçC}>ÌçÃ}>ÂçÅ>/ñù9>/õy™ÏÏõùHŸòùy>íó1>ëóq>?ßçã}~Ï/ôùE>¿ØçŸOØÆ„ê½]-Ásèf¹Ï+|^éó*Ÿ×ø¼Öçu>¯÷ùDŸ7nß²áæ®–±ÀX»ÇáúüÏo§«Ùs®ªIÛ1µ{ëñdM¦oGÕïI·*ñ-~ïóm>ßîó>ß¹»no¿NôÌŠÏÑwù|·ÏðùŸïõù>oòùs>Þç/øüEŸ¿äóU>_íó—}þŠÏ_õùk>Ýçk|þ†Ïßôù[>Ûçk}þŽÏßõù:Ÿï÷ùzŸ¿çó÷}¾ÁçøüCŸäó}þ‰Ï?õùFŸæóÏ}¾Éç_ø|³Ï¿ôùW>ÿÚçßøü[ŸoñùÖí®­ÚÓ›èIRÇnöy‹Ï'û¼ÕçNŸ»|>ÅçOûü™í»Uî-X$ò˜c›Ï§ú|šÏ§û|†Ïgú|–Ïgû|ŽÏçú|žÏ/ñù¥>¿Ìç—ûü Ÿ_éó«|>ßçWûüŸ_ëóë|~½Ïø|¡Ïoðù>_äó›|~³Ïoñù­>_ìóÛ|¾Äç·ûüŸßéó»|¾ÔçwûüŸßëóû|~¿Ïðùƒ>Èçû|™Ïñù£>_îóÇ|þøvWWÜ<Èe¥7”Lòñ Ÿ?éóÛéÊÞ[± ËæIÅž.`’âŸïóù³>_és½Ï >7úü)Ÿ‡ù¼›ÏÃ}áóî>ïásnð±ªYòqq±VeUєɬ¬ ‹Ÿk¶ÓÒ>„Þ¬±ÁËÞúiŸÿµÍÇB‚j„Qã%´K΃B¾kyðJ»#^PxOäÁë ïyðjÜ'#^À»"òàå¤+#^ûTäÁë]ŸŽòàE¾/¼•Çú8^ÿûbܳ‘_Š<˜û¾*û`æò+‘*ÚWãÞ˜ÎüZäÌñõ¸7^4¼&î¡ìE¼xø­¸7^CüväÁ tׯ½ñ"àwâ>˜Ñþnäý.îήû@’ü^ÜÒ÷ã>xíñ†¸$ÊÄ} pü0îƒ$÷ÁËc?ŽûàåÉŸÄ}ð*åOã>xYñƸ^³üYäÁK—?{ãÌ›â>ê¼ÁûàUË›ã>xY󗑯nþ*î9÷Ák¿‰û`þû·q¼.ù»¸^½%îƒ×AoûàåÐßG¼*z[ܯÞ÷Ák|wÄ}ð2Àq¼bzWÜ/œÞ÷Á마ûàeÔ{â>x5õÞ¸^Týcܯ­Þ÷Á» ŠûàEÓûã>xÁõÏq¼äú—¸^~} îƒWJŒûàÅØ‡â>xMöá¸^ºü¯¸^¡ýkÜ/O>÷Á;‹yð"î?¢Žx-÷±¸¶`Pá…ûð+ºjXµx~—˜kí¿¿ÎK{â>üâ-Ý÷Á†%qlöá‹û` ܇_ ¦[â>x´4îƒmÊâ>ü-ÝyðÚdEܯŸyøEcÚyø¥_º#êƒ_ª#¶ý¨‰<ü‚2Ýõá—p鮸¶š¨ûð«Ìô¸¿ØLß÷Á†Ãâ>ØXd·Èƒ-D†Ç½ù…hú`äÁæ2»Ç½ÕK²ƒy°µÌ¨Èƒ-EFG¼;&êˆMJÆÆ}ðRëž‘‡_½¦G~›î‰<ؼfŸÈƒMKÆE~e›î<Øhc¿ÈƒMxÆGlX²ô#¶[: îƒW‰'D~™›î<ØÖä ÈïˆÓTäÁ˸“"^ýy°ùÉÁ‘/O‰<ü¢9Ž<ØÖfZäÁ¶FÓ#¶vš8À/¨Ó#‘/jÏŠ{ókë4y°õÍl‡ë×îͯ´Ó'"6¾™yð²ö¡®çZ¼ =?îïÂÓ|܇_Œ§™¸¶oi<Ø(ª-òàUîÃ]C€JäÁ&:GDlÔýͯÙÓ‡—\˃í×;Ü¿ù@|O¼âþœ­<ϼñànz³QJ€:–ªâÍÓ7z{?ˆÂ‹¾`»Æ+·¸×„übXÍ ù¸*/æÕ…šU^—»YÕõüéÓ Ë'Ùõt5ïa‡ÓUíyÖÍ«ŒAˆ‰ÌKþ x{Yw3aãþïxàvÆ(m<€¶”Ç—3$èÆÑÔŠGMF£²߈M]²ñÀÓà $ð@œîrxÀs5nró(Æœ•Â~д¹yÀÔ l~½9ðx9|w[ÏÂÂÒ ö bôÑVæÎ®LýËæñíý|C0üŠ6VÓßüúÅñ|’º‡l!—úZ‹º^»îa,óß·æÑ°´à®ϵŒF7ظ÷h[üYo‰—ùdã˜\޶~ímðvÝãðóÕ¹)ìÓuÅê\KÎÌz£©]ýqäò)oIµë aVl/.G˜åý~ Æš³ßyòS÷Xûöê7üéò»·¯ÊY||»“ð0‘x 9×ÿ"êx­þ™¾w@òß„`= åÈÜË ïá À,ŽŸ_òFeÿé3ôýñÅÈ}íêW^A@¶<üÏ\ÜZWï‚ÙÎ{à›Øégo³¡ºª{œ˜}“ÊêeZÚ>sW=ŒÑ Þñ>E+ÇÞx‚Q.Y8éÓ2ñvú˜6Ai“•_vò:Rm¿‡k\úècÿŠÀXØ¿Pe'›-x\êáRÁL XΈ×véÓLw˜÷˜àÝíþçù‚üó9 âEF°ã¼—Óÿô¾Û€’°«ï¡Ø¸ (…îàz,ËêNÖ¿ÖhÆ=–¿£jýó+ßébëºrýmdüç=Ôÿ¯®Ö=Ü’ÎÜ»­>ƒg®J‹û„²Ñ¹Þ¿Î—Í»Î;1žáp|i’§ëj®l0ñ›Dé J!Y’W½·†Ên<¡¸œhÊî ÎUB{uW@ò¡¯£ÈÑ7üй´ÉÊ?© fîáZ1Rþ O¾ÌÚÞüRññOÞö«Ïy§\ÞlwW #ùÔ;ô™Gù<­›Zß÷‰Û›}Bÿ—îŽkpý÷Ø©Áõßc§7p\ñî\²®n\¦ÑžÔàŠ÷Ø©Á%¯ñß\ÿ=×à 1å,oS.ÿãÛ~óÔ¿øÂí‰7xÿ™7æ÷¸ -Í2BE1…³ªÙWòÿÆ=v!°ÅÜ Àÿ®‡ûÍôL×õQ÷þïØbxøP{ãÈÃ_'N ÿÉø"¹Ž~œôßc'#è¿ÇN$¸Ç$/ÞÃ=ÉÝ´¼d]Ý´¼L£=ÉŠ÷ØÉ’×øoFÐǵ¼ÄE¬{d&¾‡üÌqµÿVúÃ%V×%²÷pÐòð¹Ì‹m(ÞѽlŦñù›×´URú[ºvþú=‚{')\ż­’Ûæø_o«äî14­Rœ«r!˜;{æ ‹éìxƒ$×îsgÿz«#]¿Õ‘«ëz=Ô÷øv¾±‘«‡ºÇŽ·1r÷Àp|4wCà—+«ÙrìS°xk‡„tì¼dkg†tlö¯v>(äÁÖÿK#`lí[õ 횀ÿOŠ8nˆÝ)xSmyxÓ|m÷ÆþÅ›#ÏpŽ[âÞ#8ž÷Ù]07xì„Ü÷ɱ+î3Šã)qŸÑ·Å}Æp<5î~qZäá-üµK‘g/ŽgDž½9žyöáxVäÇñìȳ/Çs"Q>7òŒçx^ôãþ_÷9€ãK#´¦—Ež9¾<òÄñ‘g"ÇWFl”úªÈ3™ãù‘ç`Ž¯Žˆ[½»O¨>‘gYÜûaÜÏýFžg3 _ú÷¡­A=¾újÓÕÄø4qѧ¥ª˜k (söGzdE ¼ŠÃüªç{™C qèW;®ƒ|žÏ Æ}ÍãÚqMš#—þ¸N³ñò¾gszflÒÛE²5ÁôG³?®F+Uï Žu?³?.DãPsñˆ{d«?NЛ˜ƒGÙ!ýáyFæÞ‡¹0£?¼+êIÔ‡¿rê!uòþ8Z©š{æo3g©“÷[4C'¯×•inѨ“÷Gô†…¼7× þI¼ŸÕ›˜ÃþaÎÖ¨“÷ ´v5w‹|¨«ôñ8ÍdcÎø ŸÔébÍ’Ë{€è¤R'ºú ¾ÐÇ¥Nô3z#†õÕ÷è£NôczKŠõU¼`Ô‰¾K³Çr`žÕ¨“öwÿ€u|ûè]£N´_³“ö½‘ϨÝ«7vx'[…¯˜S–:ÕëM'ô 㘳’:i—UkÖeð„aF´Ä)X‡Q÷À»R§€z‹u…‹x߯¨Ýñ>àû«Œ:i¿, @ ùÛ½Kê¤]æ¢/PoÜϨ“~ïŸãû[Š›t×fô]šùú»û)ˆOúOèm•G]'à¾Q'ýQÍöo‘ýmÔIŸSíŒÝî´ýÌ=˜ýt-3~¦d4N8%ýto˜Â’_ó‘„wH£—×Ùüšû«hâJÞÃ$¤÷‡^‘|S¤åbqö¥þ |>¡'< GèÃú)îf^t' Hß÷§¸u¼Õ£ûA»1ð=õwàÜC·Pê×ûcÃSÜíÊWâ8ðO·§É¡ßì8pª÷M¸þã1¿ÏC7§ºÖÁuÕõÀûksRž”Óõ îw\ä׃ºÞÿãoOø&ýiŠûÜ]×{üM¥§=¥¸K຺Þ÷Ã=ð¾‡ôÇÕÌTèûR\)º¿¶–âZ©™~‡ó1/×>ânSô÷9}*õ¾ þ¡ë]@à ÏÇi¿“âfQ3ýÎ7ƒ¹krß\ îêð|35ÏyYŠ;Š™]ïâjà¦Ï| ÓõN +ÁBÝõ¯|x}>jàDà‡˜1ÓÅÝ´ÿbochs-2.6/build/macos/bochs.rsrc0000644000175000017500000004571112020641472016535 0ustar guillemguillem(This file must be converted with BinHex 4.0) :#Q*[BfKc,R*cFQ-!FR0bBe*6483!!!!!!!!!!$GVKP!!!!!!!3!!!$ES!!!ek!! !!)-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!TLEf0SFbjbFh*M45j SER4cUQ&dEh+UFAKcG#"&H'0P!J"bFh*M8P0&4!%!rrrrr`!!!!!!!!!!!!!!!!! !!!!!!,3U'bJ!!!!!!!!kIJ!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!%!!!$rrrrr3!!!!J!#!!%k6@&M6e-J8h9`F'pbG$T 0B@0)C@&NCA*c1J!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!9!#!!%3%9!M%!!3%!!3!!!!!!!)!!!!!b2$)m!!!!!!#[!&S!%3,r$!$ rrrrr!!!!!!!!!!!!@J!!!+m!!!!!!!!!(i!!J!#!!!!H!!%!#J!!!!!!V`"DJJ! !!$&b!!!!!3!!!!!!!!!!!!!!!!!!!!%!!!!!!!!!!!!!!!!!!%!!!!!!!!!!!!! !!!!!!!!!3!!!!!!!V`"D!!!$!!!!!!!!!!KHCfPQ)!!!!!!!!!!!!!!!!'&`F'` !!!!!!!!%!!"D!+m!5!!!!%J!!!!!+-m!!30(58B!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!J!!!!!!!#!!!$rJ!!#!J)#!J+!!!i1+bX#!S!!&"3m2!)#J!" lHfPT"!5!!(4dCQB3%)!!YE@QTJd0J!#eY3`-#`Z!!1EQhYjfGS!!NT)0$3S+J!$ Ki4iH$`q!!-6%V+`5%S!!JB%0$3S+J!"kHJm2$!b!!0IA(am4%B!!`F'TU4NCJ!$ cml+bUUU!!1RTjZE8e)!!GA80$3S+J!$Gh6`m+bZ!!,Hh)5%A&i!!(Ki#!TUDJ!$ 0cE@e'aZ!!,DfQjX'"S!!H(KZELJSJ!$VkqMSfYU!!&YE$3d,#i!!6Nik1V+bJ!# 3!*!!2$`+#S!!6Nif0UDQJ!#KS5)L%4'!!0hGFR*YEB!!bXUbXLSUJ!$ZlYE@DQU !!"iH'KS#!S!!mr2`m0VDJ!"fGQjZ1MU!!1(Kc-`P*B!!0MBH(U1MJ!!N*!B'!`1 !!)U+HRSq2S!!4%3l1`3%J!#'KLFR(4f!!"NC&KB$!i!![lqNT!B'J!"$3c`m%K+ !!1VUeYE@eS!!%K)5%JS+J!$LiXE'3N+!!2[lp[EDfS!!D'KGA4`FJ!"-6#!J#`Z !!0rIdY*LBS!!(4dH(JB'J!#m[*LB4ND!!)k1I(`2$i!!LiYjH33%J!$)b+bX"JD !!,qrTkFc-i!!JS+#JS'"J!$@eKSD$3f!!2Ihm[,@eS!!&48`-!B'J!$HhXV+EQk !!!i1$Ji,#i!!PjH1MX2$J!$@eV1c$3f!!,@eEQjVDi!!q[Vkq[VkJ!$3d,5d"JD !!0E@YlF5%S!!JS*eGEZlJ!$QjYVDEQk!!0VDfYVCfB!!Q*L%K!B'J!$kqZ$JhYk !!+UUUDQTUB!!TUD9P438J!#2Mi'"+bZ!!"`F2cm%")!!2cmm2$FhJ!$5dVDf-M+ !!'PT@eX'"S!!pI@q[VUkJ!$1cKJB$3f!!*qIRTkEQi!!&KB$!`)#J!#ZVQeYD@Q !!12MK)4qIS!!Rjm4%3`-J!$QjVkq%K+!!'*L@eXX,)!!5dY&45NTJ!"483N*"3@ !!#BQ)5%#!S!!-c-D'U+LJ!"mI#JS'KU!!(amE'bfYS!!eG@m[!X,J!#[Vkq[V+b !!++LPTBq2S!!hpqhYl1cJ!$dp0rIfpZ!!!S+#JS)#)!!b-JB'!`-J!"fGQ*LAPk !!0E@UUURTi!!eYDkZJB'J!!Z,LSU&"5!!0lHEQi+#S!!RTk)L!B'J!$Nj0rI[,b !!-c-bXV-c)!!m[,@eYE@J!!R*cBf#JU!!0lHcXk#JS!!aF9qIRPjJ!$2ce"34dH !!-R*a-5bXS!!EfpLBPjHJ!$fpXV+YVD!!&YE6Nj'4S!!XE'TUGcFJ!"ZEKmI'4Q !!*UDLSSM)i!!-c-b-M!`J!$DfS+#%K+!!2[ljqIQjS!!`-#'KSD'J!#9PBQ*ZlZ !!1,LfYU#JS!!HRTD@PTDJ!$kq[EfeYD!!%P*#3N'"S!!KiGlHlZlJ!"GA9PC06@ !!0lH`m1r[i!!TUCQCQ*LJ!#1MSU+8P+!!1(KZVS0$B!!9&4*538&J!$LiY$3%K+ !!&*58P*58S!!hYlHhYhGJ!"LBQ*LB'#!!,DfVUl'aS!!r[lqr[lqJ!"E@dG(VUk !!1,L-M)Q*S!!`X+TUDQTJ!$YlH$JhYk!!0A9Q*L9PB!!cmr1cY$3J!$amI$`lqq !!!B'"JB&"B!!lZl@eYE@J!"eGA4dFR+!!-$!&aF0$B!!Rjp99948J!$YlH[VeYD !!-[,`-!0$B!!)L)J)!S+J!!U+LSU+5Q!!0E@eYE@eS!!4dG&484%J!$Nj1,LeYD !!"B@-M)#!S!!iq1q[J`-J!$DfVkq"JD!!"XE'KSB')!!R*b)L"38J!!Q*Miq%K+ !!+UU&"30$B!!P*58P*16J!$mr2EfhYk!!++LLSS'"S!!4NB[,kDQJ!#cXk+L$`q !!,Li3%!k1S!!fGPIAeC@J!#`X"89$3f!!1$J,LiG(B!!cFfq[X("J!$0cCZEQCQ !!$Xl"38&"B!!hYl-c"B@J!$PjGIAeG@!!#dY,Li#!S!!2Mib-M)bJ!"58NY,4dH !!&PC6Ni9&B!!CQC58UkZJ!"A9eC@9PD!!+kZTkI'aS!!Sk13!*!!MSk!!2cmm2$ Vki!!,LiZ,LdYJ!!Q*KB@!J+!!$Bf8P)U+S!!CQC99E5dJ!#YVCqIXE'!!%Y,5dY +5S!!p26Sk1EQJ!$%a-6%b-L!!1cXMSk+LS!!jH916N0$J!"SD"SD%a1!!)+#%a- 0$B!!`F'q[Y$3J!!J)#!J(Kk!!-R*VUi0$B!!m[,DfYE@J!$Sk1MSjqH!!&pIAPj FA)!!XV*58Nj1J!$)b#3N'KU!!$Xl,Li*#B!!q[VDfYE@J!#+LK-6$!b!!+UUQCN R*i!!+#J5%JS+J!#DQMdp-M+!!)1$L)L!J)!!iZ,LiZ,LJ!#!J(amHRU!!#`X+bX )#)!!DfX2$``-J!$HhYA9dp1!!*qI&aF0$B!!%K)5%K)5J!$TkFA&#JU!!"B@&KB 5%S!!B'"58J8&J!$fp[EfprH!!,'aPjF-$)!!Ji0bFK%4J!$bmZlZeYD!!0VDeYE @eS!![,blZlbmJ!"UDQTUD@Q!!,Li&KB1$S!!p[ECfGE@J!#bXTD@"JD!!*16&"3 -$)!!`F'fYU5NJ!$ZlYVDeYD!!)k1MSk0MB!!1$Ji1$FhJ!#5NSU+!J+!!1RTRCf @PS!!+bXK)4SDJ!$TkGMB%K+!!*kH,bmK)B!!JS*QCQCQJ!#RTif0#`Z!!0VD-M) Q*S!!,5dR*`)#4dP'1$PK@J#[!1F!!!)#!JiV!K3m!RYT"(4Q%,@Q$E8-#qEHGT) 0#Z%H$m5X%S%0#RS2$0FI%F'T'I1bUZRQe(80#Ydm+lFK&ai#QXfe'lDE"RKZ+1[ SfPX0#dikXT!!2!T10UDK)K(GFQh+XLVZeQSH'J,cm0TfEMVKc#8f(U-N"J1+HMj %1`5'*adC&J1rT!C$2",UeYB5%JVLaN,lpYTSA4a-)![IdQ)G(JDmQ%D1I!q,H36 )V!DrTc1#JS(@'JhhmYB9-!EHbQi1$JZAMX2@X`feEQ[kq[V3Y!E@Ya+#GE[QfQl DfYQBK!Eki0kUUDQQP452J5XF2`3r2$I5YM*T@`Ee[VV1'!fIRTX@!`+ZE@RMK(k I%3cQ[K*L@ba,45P4#38Q)3)c'U*m+"TmE,E9[!Z[VkbLPMlIYl2dhpX+#JM)'!a fBPl@UUI@ZJBZ+K6HEJUHL!ENhlc-bXcbeYBR0JVHcS,&IRR28%I*a,*[BPlfbVC E6NDaUGaZ(aQDLL-c-M$DJK,ljqE!KSD9LE[LfS*k@PVkpYC*#3D(HlYG@6AH`lq QCQ+1LP,KZJe853ALd"*58P,HhYeLBQ#fVXEqr[jE4klL-LE#UDRYi0l9Q*A2cY$ am1m'"JAZeYCeG(,!&`fI996YkpE,`!dL)!SU+LR@eYC(486NiYB@-J,M[JcD[JB E'KLFL"3Q2K+U&!f8P*2mpYkLLJC',kDcSJqi3$VCAeD`&3hJ,Kh0[X(0QjNl"3A Hc"EPep8Y,J)q-M*55dGC6K9Q8UjA9PDZTmDMN!#1r2$V,LiY*KB#0P)UCP@dVCq a5dY+p1MQa-6)l)k+j8j$D"S6JK-0`El3)#!HbDi0mYV@k1MRAejFXP*1b#3D1bi *qYV@LK--UTNR+")+QMdbJiL!iZ,LJ(ak,#X)D`m-hYA6RaF0%K)5kF8+&KB5B&) &p[EhXCF-Jh)4mZl@fYE@[,ZmDQTTZ"B1pYR@XTB'Na3-`EDNlYV@MSk01$JhNSS #kCf@+b%DkGJ5RLmKJQCQTid,fM)Q,5F#,!!!!!"D!+m!3!Mq!#-*(%L`S-'$#"- UA-L3!1'`KT%`14*&%BR&LaBGBGaSND,(Mb"$L[4i594*NU)FB8)BkL($)48GbG5 )4'6(N5G,RM4CNq+PQMp0#[8CG1G1EbaG-U3i8k-SLp-`SCZ+EXL3!%KA%rBXk@J )9A45V4B8KJf10%dYdZCLpr(5Y+3%!3aF!XfE0fKL0ShbpJD9-TP)N!$9kiQNhLK 4!+L*SXE('bUN[qSY3G@Z(DV"@)FX!4$C'lC$!#JG'[BY'+m@QNB&UdGC&"pUPeJ 0QrBi8Q5",38#f-hlPm!KBP$a4X9+)P"4ShMc(S9%*99-5&C'FV668F(0[1#8a9C @'ZT$GS,qD8VQ*eNC12$5`p0H*MdF1#fUZ0aGF*Sh4mL8!cKFX*(qhD,i4`8QhA! fa#8!AM)-!+J-B`i!M84#"@H4f!2!-!X#8%mNQ`"JcbDD-EJ&JdKYjKY"Z3f%L6G 2hIG44c9&*a!51Y&S(3`i`S#"4GjJ-J3%+&%N`L#$f$F0"26NJKjhCF&4L8qjN!$ &R4)XIS513D&NiJd'kr$!JbH9d%4B48raj#@14+E*3jTU%VRQ)'[bd*-M4'+5c** -DXHGGZqYpek6D@QA(RIZ`@&#&fYk!PLCBilN%6R$f"2+$h9GSX`cbPcLSd#BC!, !$d0-`p-d@GQQhc"HjY*#,QLK"NHVrQN0#NpCkQN#4a@CB25L4cf"9")58b%c5LL SN!$cJaQmCC)*0)p`kLNjBN@53!)ll,"+"!XJ8-@fZcecL5hLS+HR"qr-JJ8$$2b j(UhBT'F#!$@a`dk[[*DC%dAHM2*%+1D3!!2!PGiJ`iHPj,bK6#JkX2,I0Cm3!%! 'G'#&K$Z(*%$,P394L`!$UlaM`#VR-S!)V@LTDUX*QB688c[$)-XE1BqX8)3KZi5 JJMNZZ1#T+iSS8Xl23!1G44C4r'#)2R2-XX1dddjK`"3lR'&!"!Bd$I88UcJ6MM0 #,)RHH[3NQ@3PPG#$Ud9Lm+(I$qV!SXBT(m3`E$l'rZ##h5kiR-RqAe'KX`k0Pea 5$akm2*%*-4PNXmS8Cqb3!1dCN!#Id3!RjElc$LH3!&rp$J,CB,%i*eAXPSNCHSa M$6-Qr3$!*BjimLB2pEL`QcQM32-$16LEdqrG,N$M-J"[6&-93N0iNb%jhV46ccI 8&+2+0GLq-d8#$8bq#J)4B*[ppPc)X!XLqi`McbTRd()(R&jf%B)RkhJ#`85"Xr) l!1B38)%D#Ub`!Jj%R2+f'J!NJMT8aaXcf1-5"f#%2KE)3(e8J!RT5-FplT'%IU" !1@E3`[e1i6m!rSm!RYT0YZMJ*5$j"!#)mK)2eX&#&VTM0fEB3a"`B)&ie0!#k4K !#%))J%aF``,qr8Y(&,V!3aGd3ADmqF%23QJ'2#MJE4dF!4*rd!88T+*fd)"'i(B L#RDiJ45HB"m,Na'#&,V*6D436KXkk$m1HY#0DP"%%HCBK#!8)BjZG1-DGN11*lC 4MN')"Ji%L3-l!K#1S0M0$m3KaKCf5BASid%A%1@Q1-(TM&p5"MAm*ETr$#!D(-a M'dICaM$d`e1C)!!849N%#bb#KhaSacVBG%Ed4I+5Ah)$4AEcNhXKJ452E"-N[65 N5#*K#BrJBE*S%),rp1B0N!#N*5eI0iMfkG)S60P8*&*8%,"iJeifF4d(+(",&FE *R)-B%LPm3K&*8)#BFCTPqhV&49'3!!*M#rlK*N3)!TCT81!9(QN("54aLB(U""! 8!))M"NT28I`c+1jmKNq3!1"1CHb6*D'iU%BhbY'0kP-K&@P18`#6NHC`"*aP%NQ 0KK)5R3bPRR"jb90%kT5RG18jB+&+Y!UbPC4NCLT5S3T#[(%[S331+3IjD%*LFT1 CHS0895Q93QMN%@pi4DJ%'3+6X1%GY@K#("-9#P+aT*4)b%8J5cM4,eMKL%IXjK% JH8CbpY-1Q3!J2hc)&'Xmj)dP)+-NJV%1@Ld%!$5N*aM#XF1VNV-,e34M&+UUaB, -83Gal(8BYFK&,Z5M'mlmJV"['-*Z50S4i9(&2rTKK6ImXk(0f!-k#4VqE54-0&X )+3%E`9L2fS,K"rmX)4,H!!!dd1%(5J"J&m)iKR"ria86P*8JGU%*Vf)d%&&J!K0 #3B*!6!+6S@#&+$84`CT%8"*2&*-8iQJ"2B3aN!"T)1'TM[!$NkiLN@Ni`US&#FA U6()5GNKhTLQeL&[!BK*([+j,-1""MJD4B$Cj*)bZ)e)b@U!R26'T81YaMc6#C"( T#)5iYc8"+0+%!@q3!-)Lm`S`QAlLKNIq)"4mX)Fpq-!($)8L&2Q!"LTd4iiH+p% -CP#Q-hI$(8hBkX,[XG@Xm[5UY+4&%e8!a3V[dbK`p[3M,ai'0#!e%DY+05+H#S8 M-M8m2b6J$2,3([j[KL%198QM$0)i#b+baBeDU#9XU+'(HR14T,24kmrJ2)R`a,# [PS4L&1j`Kii"`)GR@130MqJ8!-K"%&P-kaeBQ-!F$S%%GRLJ!6YJaM,Q))YCD)d ,h,$'&*aQ!!C%S"0EABq63aG5AmAS1+*3aL0q)#NPiZdE3q!N+N"J#P0FS!NqZ!& [@2!*GhcM#r*B@J0QX3X!#'&D(3+!1`BLM'RY3"l1B%!+UT''flBV6dmf9+j%X3N 9+#F6+'K#'2))`#D-)J3jbpQaP"-&RbNL#%()3Y$+)A"3-'%4ah9!')V!M@`XS'1 Vb-BihJ&UDf&"(J`)4`4Z`D"Z(#)AKdL$,IiXBBXd())Y*J'!P$e"#TV-4!c8q-% 6KS'+BZ&-"ITZd)0i+4@&k(Fh*L$%1+l9J3l-BJ*,SaE6V%@eMh(#!*EE3DXMm#j bZ!-*IZ#'2$M"$$Ke!3!88CYb@"#0YkR$"6A(QGh`"SfGm`BD9%K*Mi!+J3ALiK2 kq-30&Z%%!3LJ&$d)3!"k%!FC4#!$A6!($3LiQa#S)`b("'!4&R%02N,!R*)-J5- GbB00S!)DS9"(2hS"L[QKJ!NEI1-T`J"j043K&IB3XMh1iAEHG+%*'b5PreD!F0i JJa3*IX!NaN'(L8cA$5iBF649q-*2T@,H(36J$'XBMhLN)aj*L-)L"[l3MqTlhiD $r-GZ90#2&AcI"ZIS`V&8F)d"H0m#+iJ'%3Ml!aD6!J+EEq%+*6RL5pU5"rP43#c 3"[fMHSF85U-%4DX%3(XdDAk%J!VB3853!!kp`%1K3!@2K(RPC%jIK`3YjL@iC%P [iRpHFJQE`(LlJ3Tl3!3,q%D'`"Xhi%Bii$!&Y!QB)%eXmMVRY%)3F"a&N3NCK3l fp9)XP4)3-#3m8%b4"),$*),Sj!P8j4&(1%h5e$ipH#mRS4)ap4,V8#86G3P!3!& 'B",+3!'qm$F8S!&HJP$(-!ML8!*H!!3N%BB8F!`mi5&%8d!k@-SC2i3PIeK" +e9&CK3lIe"Eq,"8i4$%8lq9KK*K8'I@)NML*([9FP(L*Q*KIPRJ33c!4'$&5)N9 6STJ4BX)4!2CR43%82YK,21&65E@*"h&VJ&'+!1BS,S@)4%J54F91['K8V,1&#Y& GS[J4Q@%9Al&6"3%r&9%39S'-"8&849K9`*J3-"'+d[9832898q'-!f&mA)%91,@ 0J6J%PD"CZ(J*Bk@*%"%6*08LaaL)XAJ89l@0"S&NUh+2ZF"1*C'1+&*@Cc9E*l* G2h%4pq80bS!+hp!Fhi!+-C)5MNJ3p0)9AS%+[c80G4&VVk)UU+%*Z8J4`2L2D58 3[q"AMm!+*LP40E%*F#88e,!*#1)4'Q,q$dX`NfrJ9a5"$0dJ@-U`)3,a$EaJ'YT K'Sq9&MpT'#8"GK44$e3JNdY!"Fp`&B0B%#Y#@M5P%5IaAZk&P+eSA3-4N3Ha9B6 5C+JaPNEQC%p@PQDj@I-"NK55(`PT%Bp`'IF9&CL3!"pX44MHd!f03"FHSJaU!`f X!&LMB"e[F"ZEJ3IF)3LmB3HDX*!!(P)29Z&jM"B-l8)*MA!-`S%%b3!2R'9@rpK HDV-%(E%*I!#CTH*E[q%4U,NCMB!1#!*fVfNGY%9Ee@B(P*!!(-F3#DYT@qe#(l3 e%%1`$E!S%94@Lalj'e%"&'ma"$8"%kjT%YpP9,dS#ZcM*L@K#8U3!"@KrM+%hQ" Zf!#2rAJ3pZ886986AE&G)+&GN8!4%Y'+NI#F3b%#5NKP)V!1kQ8VF&!'3i"GTH@ G`Z#*%q%)q)3ES5#%3q&IZN)QM1)MJ$-RYR4,DU+-&"&'mZN*da!VjdBSA#80,$) 0hZN(SZ)6$iN9fl"I[c)6RFBS,8@GF3)$P94,1*JQ[H)*J`!@CA"Nfj'MHr)HAl- ZVr)R66)Sf(!SVq-*90C8Zd)4T!##lU"%j2"jS*G&0BF+0h-h5k3X@0T$@DSI93! )KG)Z2*TN6bB05aD@6()SF0+&dS9bMN)4AV31jK!T0,G%30CMmc0NH-SES@"ZVk* NB,NR6NB2K1)HrL+f*Y0`BQeU,leS$U%J+DM`#jIL,BiJ2#VL+BpK+CNLS&La$"1 !"9bJTqT&TR&@-TSP$AZL(Ri#$r5J#DYD"@DJ%68e%[4b&1L3!!N0-JVfJ+XheRD 08DN-)LU#j@fVX!!4J!Aki@4+BKE5F!8HJ`A1d!Q`SQITGM+jFK'b@QXe!KD2B!m k0Jam!!fld3Lr!+lK#QD64K",GchCJJ!)3+cX5U`,%!l0S!G5!!ri%$@cX$%-3!C Jk4j3PM)TT6)*kK(SJ!5-35bSm"04)5UMB!i%-5$2`Nq6m'fd`&i#S35d3![Bm"Z BF+mEJ`@@-`A[-+`-X!#RUJQXmKkK8jkik2k$2-%+YG-[2IB@b2!,$'*@BV!Ehk! `Ze%!Ra!$,+!054!1fB!2da!+6d!0c*!!!(IJ$T[`9`2KEHJbYHK5$Arb(V%#$e# QPEAQ+rA`FiV%V5T!$[S'!+cJ$YF3")T35)SJF%"c$J!!#cjE!q13!(40B`!'m(6 9X!f#F!Gh)!@6`$46i!c1N!!#,E"NJi)HUeSbmD'90&)2XDFI8H!f(%3%-I!%qH! #1(FhZp%2E3Y`!aFdLX!%FI!*Bj!!!hhJE9M!#3RJ0!M!#8[c$Z2!!-i!XZ'@2FF J,[#K@CU&"00J*%J!)0R''pUJ"T!!4frqS`@6BU9VTabK)"RYm!Bqm!)c9%JirS! $+k!#NkX,94!1A0!-qc!"(5!2i4!1$#"aib!qf4"ZYmX&fm)!l$S,eM#r%e#rG0! #J3-J!+C*qJ'%MUSlqBBhHE-E5p!McIJE!m'c!,!05Y1kll!!dFBd%X`dCj!!03r h$N[$#3M`"C@R(hKJG*1`*NF8JT@d$Ym!$8q`C3*X0bi$$6`N#U5L%1fJ(293$cT 3$jH!#%3l$V#EG0@#"3X`"3K30Gjf"YMcDPFK$(mJ2Pb(2Pp(%FU!$%K83#PFFf3 E`$RcH6bd"+6`Zk9b94*""Hlf+8l3Gi)RH$e3#M,`F*b!"4(3$&[`$I93EEDR$NP !!-d%!#D3!!,i-%Y,f!Aq+Y"bE-%+,U`F,Y!2DT!!"$['1rVf!bZJ"MP!@-Va#kb $#G0`!!f8b303aJ)3H)*A#J&J$Vq6#5kJ!+dAH3"N!mRL$ZB%*!#JHCXR!K2K$ZD !JMd8Ea9!ErrM389`F2p"!!d8"Yjh!PX`aQr("!F)4`"%!'1maa0J$Cdk"r@%)&h !3Rl32Zf6$1[J9TR3"8R`IIe`$FT%$L0`J'rd2d63")NdC$p3[20QcQkd!ZZX5+L 3!!rXS#Mma5YZi!KZ)%BK)'9,Z%,E$%1TJ-id4(diP!6&l%aQ!!lFphhLP`RrB!2 B&`AJS$-T5%5li3,YehdfY!9"pJ1mZ-m3d%L1"!ST42j0F-*$6!"(#3K)f2YphfF "1("((Y5!,J!,Te"(qL26haGrLK"+6k")e*Pr,)4jr+I5AT*'[*%%NDI-,Jf"SK5 "$8J1$U"l#4KpTd!%ED!,bN%0R)I8Ip`&*#L#Jh!*he"l2l!)b-a'8Th9F!3,""3 +#S#!@Dd'&R""cc5#CEf"+J3"Q4!#,fT*Z14rJm!1-+Y-S+!1r32A(64[Hi"+MaG +DM#"jr!l,X!+ILa01KM3kl$222'DfH8'4mL%KVf$NE319*!!)FT"$Vd`"JG)"1! !3leJ!bLJ6+1`T$(D*[mh6kc)+e%a+I"cLlr5cq+eJ@U#6Qk#"0r!"jcd(jQ!$+, q54'AapFiH%kHi!CFG*8BJ)cFj"8V%SA6L346L$jJ3!&)i0Flb)4!SSLL8!Kl5-* [`N)3S%[k@"'!k(1`#*a'LK-Q-9#!i!YJJ!6Qp!aJi!Z!!)*%XJj!)!N16K%$03M eJ1!Xj!PLi1"'J%fN-+,k[9&#f#[ZP"-KlJ9Hi)%3i%qq-!KH8!)pq"(ZC"&Z%)C !J!6Yi!9LU+3$UP&4Z8rHN!#'`!!)ib5(Pf!%!`8%Vj!!8#8"$"33K`d1"%UqNTG !iQ!SKX"3!K6`&SrB%KLbj9cHj9jZBcGQD--3jQ'H4E8XC2pK"ZB!$@0qBfhqjA! HjffZjA*HjhCqjhLHjhFHLIkCf1GpML&q(ZLB11ElC)JSPDL)RZL+AK'8LK#%hK! KHP)PC9+5,ZNVkP++Q1Qh'#3QJH8'mHJ-%5-S1P+M6ZQ9IQX+bL[Be*&2FC@+k1K m(ScX#+ZQ1&eYZZPF*0km@%qiH*bI(ZXJCBhrPDJeXZVL6GbYRZb*1*fZq1[V')V @qL,h9C!!aFP19(AXiMf`bMkG1I',"`(U#c&6T&84aTK6laL,eJkFAY'-i1Q&ZmL 2!`(Z)#AZd[9Hf@MZ3B83e1%4eM'2fTMM!Q&mc!l[!L([5dA[YfCDjRiPi$NM3h& 6rhl!`%N@IDS*E(%[""m*"Sm3iUiVphAZSIi49RA[ApEq#VH&(UfLNEdS@-lH%#& 9RNL`lJe[%$d&mF2666ZDmQJ"9Vr0mJ9"k$Blb5&CA5T+N!"[%)$)S!c0iF8*iBd T!Gj,B#(3m&Z4J'5`BQ4JeBZA!1Ya-4Fb4L'Ai&EQS&Vhi3MIm!KL-JS*#3"Za3I DaCHE-&XeYKp2Ea8!S*1HJ9J!B!I5m&LUSKVe`!IQm!JX`b$Y-&[J'[F&(q[r+!B RXTI)B!r)J!aMIa'M-"JH83r)J"K8CEE3m!ZI0C+(J4cei21ce5'8B"VFm9K$f3) rf3fMMj3P34HJE`mR!ZiJqIK8m!hfS!bk*P%8m3cQX!N8X3RQS!b)m3f,-3ScE&' 5rZ&A*A(jkKPF'e)*['!(8K!DC,!,TB%+Y9!,jP!2`B!-Uc)-LP%2`c$$aj!!#cZ E#j8!HLpK(iH)kQhKZlplpemBmed*AJBa"'AD,J!"$`iF6CTDj$T)lf#,&Z*DD#+ )N!"KVPa93N@+Y%5MaMFB-8jcY)4929'1[%hcKZ55U#AeA)kXYd58+#51N!#S&18 4TkK,5$aLK!#-%MDL4!Fb,%K3fN##5CP#T'H`iX9)!!"Sl!B03,e)MUa5BrA)UKK (2@dL!d$0CEeZ5aaK3KFh,LDINC!!c14Ceq-5!,b+BK2i80SS!-(L$SQVT)a!10L 82#B+6jT&M&BpeJ2`UbS!QcG[L[lbKQl)k&m!h&'K-P,CY%B!S#eT$8#($J#SH&V eb9FchdEB[[80CJi!T@qS!0MMfVV4-H2"i2%phQLd%K08V9j(Y535*UZG26Y#2(T )kde,8(Gl*UUdGYe$N!"BRBNlBqEj[p!GXQ2FDV!KkqFh3NF*E+`D3J`!'[N*R@f X!q#R50$aKTADC)+1UjrmLf5)DAJUM3T(*2aP#&'X@XNUC5,CK$iUk,-+MKCfZ5U 5dX5S$)"$I+020`IcSDS4"$dD`L5EPRKNP&&NZL6"EdC""TP'IQRbNRT'@@f*8HT "4a3MmGTNP%HH'@868ZCT4)G,RU''Pfm1q@@6VYaTK"9dK+(q"!eHkTN')f8DXG# M8+Kb-"*[[((%1laQmXJE6$"aC+DkH(*[3d64@FR45`BC4)4+24%"dd&QJN-*MaK G&)PTLK)')h43`L63B3$pDBK"EF,V,NFp%Q8D5A[#D#CdbTSTb5&@X[85%6SGa*1 52&PR(BS3+Q1)l@KbK*eTr#JUVN)a!DR9Rei0p0H82M[88@pj`SYA%5qCTPLIGXA V@%aj3)*34a##!al'bX$Nd&1,fR#PPEb4pPZU9V@e8(*YY662VLbGD3JH-)@KiSS p*HA3P85Bq#4-+XPPUEq8)+L5ZkB4N!!S*C*"pa*(!SdNP"mBaN[KFXZp"#j[dN@ #"ajJr["jBTrRpE4B6cJpPZ1Si2QV+-Cbm8-*TZ&4BZH"#rBS3"-!Z,NN3fYPZ&j -,JjDQ+!(%ATLY09@9K42"d(RBhUB0UTTICR#'ak$@T!!KM%PX#9UkjNFQDCC3Mf MkHC+13jkk+'*4[YYYKheCT!!)6!TBk#k0fHXXEq1JXKcE2)0(*5dHE#h8CVZqQ` R4hlQB4fe@r%%Jf551AYYb*1GUA)Bd%Q'RXC%&hed[*QDU2LQ63"PE4iJ)-AQa-' qC+9+JJk&4clXXBH2lBF"rdraSB('((0F-#166+jMRre3M0IFU)NB)MfbcJGL2ZK TSZmXFA)eCJF%H0!+FS5#Hkq#"LVqb''1(ra!IHf$B!6Cpi1LK+jiG-ZA3+3b%'N XT3TGQ0Jk["'pcl#$(@#MLF!U*3Tb$--HS5"(*NE4L%Hi`afr'!AhZRFGlM%TKcU d"cRD&`SH##0i#XQAjc4B%,i"aRljqL$D-%!+*,#$GDZV9E#db"0c'"#'9(V'-j6 a$(D0DRhQS)XbaTJcMj6'I4"J#$hN1"'*N!"1Ai!C(N%8`Mbd3H"V+,696J6@3Mk 8$aPUc"8k()51p8%$#BMd&MiQm3i%4#!#9E$+--4"MdU8SB04q8-R1L%1K$J&$Kd X#"1VS!))M*!!C[qMQFCbp32bN3-D2@K%0eK"KACi5e@0G-3Ek[ibK%RXi"d,L!! #YQB9FdJ%)4f8KLcH-BYX-#!0$%R)Xjj&MbUB3@%R,"FXY9LTZ+#L%FL`ac!55)i &aK!DhQ)N!-LK)@P*)3%*f!%@NVQ+pQN#AdR8e`6HB3!%-)!E5q'J31iQ$40N`S3 R2+%i(A8c6!aK5D%`KaPLZ$jbE#m8d-M%LH**MTrF%jpB3+BP-a!"3Yb##bm04c1 q8"4m'"-,P9b!%jd''(Jdp&"KZf,A5K)hC(b8'Sd3MPA)BBBIm-%P6e"'2(p3dRZ H!3(bQ-8ik"!,!`b8%fIJ""DF%9-`B%-@8jM#1eEKM!JmB+F$-3JQ*bV1QK3VABY baa-qL[k+4kL`(G"i`XZfd`fTrZ3"*hf(,%5cUQ8N3!+A1)NST#Q2"@#"%fMPa#` @`)!&+"%1%QN"*Q2CZYA4LLH9`J3`H$%-9)"8N6q4%#D@G!P@)'&p2jK'UfB3L6X dB"Aiq)N(%[!!"rNK!Cc)"J)'qSjhB)%"$)K&C&cd%(d*EU,AGG3V9`)-C2""J6m `Jb+lJ4PS9+8G+G,"LUbLJ"X!J!#I`!8!j%&FNBbL'JR!aa"5Jl9l6Q%"#d!!&UV jAd[`G'm(dB4FKGS6BXAb%ShJ!cPqi!)AQ1-CN8JI!-b"$J$m"J$GF-Ik!&!!4Rc L#EhB`#Si-B%rJ*FAY%K!-13*$Ij[H-5Ncm@a-kT4[m"!C(30EGh#jRSA-@a#L'C i!LSD51%IN!$M$IU*JL)88BiJP-2+","+-@#KM4`ii`chE%!$*V!0@54J%Y3!`!p 1&!PKA1'H1h"'R0-`0IXaCRj9b)6r`LQ+0fa#+pI*a$#fX!Y8R'r#CJ$!!)+3!!9 &-$S,9SDdP9h`!fh8S4Ucf)&*m@N!!qc!d`-p`cXimHB%M#21h"J)h4M$40$+pBT hBB9q!,d*)UK"$A[B3LK8S13*Vfm&@3M#P#-GD8@S!392B-3mZ$'&rVjM"ja'3#@ aB&*Q*q!-cRLZ(LL433h5Jb+f@a4Fe)HAGSa#a0Fj4kh9F!TErX1#&fXS0*0GB*9 rp+-F`!lfX+fX#&1JJ!PGH%)1JX!'@R"#ZCTqacLbm3jVF%+Yf&j!"[)"LBJF*"I IdG9YZ+D-F`0J#d`S3KMB[@k5Af!BjTXdK4(0[K$Ni!@-aX'8(feP0B5!#IGST#Z qd)%*C#-FiC!!4`0fd)!TF')9@$!e!b+`J'9@33El'%I81c#,$X5#$*8#3*lEdA% !'+)#)fIh+G+KK5G-HX)6R[4eH'(&rBRM$@m3KabJ%'`,J%)&LdK"CI2jhfa-S!2 MN!!(YTmE$JBi)a[M-)!qR5'$E"cqXLZH3!SQ-!&VH#!qA%YKV0YRKM8BiJN[6'! $PmaNUlMq)j'ML83V4)!"4iJ$'Mq`LJVdJ1Q`VQ)"q-bdTKX!jKe-i3c-hX%CN!! HL`fXr$TiQ$SG4#'#,S4!GBGLa6#Z%iTGK+,3+L#(#N32MAaN'!#V%3h-(L4%UmK M&9DYj'8pM8p0plk5#$J$3CdpK8VHBS*iX-)ihL%"Y)'L#j&6QmG4KP"iJRaJS*4 $1`S$UHYJ&p36[bGSRaM3KJe!"-26[fScU4h!+I9E[fHcT'C`Kb4""dX`[`CBKSN "K8a`"0QCPiRaK0,)Ke&!"3ScK`8k(d6,K!8NNGc#QN#C"[DK!T%BL8Z`JRfD!Nr E[Gj,*J2`2GmcJ*4L!(%B!MLS"X$MrS3'Z!1e!38!8!QA8BC(N!#eV,-(!k3`XbY $@i+pXG#9eiU99I''8,!+D&#'ELL'!,$$!)L$If!!HAJ(SU-kCrL#I8J",UL#+VL &3K5a+XJ!&GX"CS#(aaQ%,C`*0lU1(eL%G###Mc+(3T1`-R5""')I9(J'8q("aCU ')rJ%"8L#HlJ"F!J!!4#!(VM$!#L&(JL(E"LVI`!&'RJ#mV1+De#!8f!h($L(V!1 !*jJ(5)c%2"-&+NJUUmL%IcL(D&#$'fJR&b!(*J1[FcJ"imZNGM!9Z-#%!f!%I6" (IF!&A'#%!R!#@#b&1bb&Ij!!!4UJJAN$Y"KB0f%-1hDc!4(l!3MqN!#F6!L"Sk' Ldl)(pXQ%,DJe*JJ"-mL`,X!"NE-eEIL(pN%&XcL#FMc(Ff3%@,L(GT6&(NL&44J L)K!jNG0(NUY)UkJ#1r!8(QL85`#!%'L@QLa)83Lap[Q(%b!jNY[(-&#$-)#&Jfb I40M)Fr`%#iL(TBb(!HL#pZ'&&E#eUG6(8eJ"AEL1$$!r,+J'6e!GV#1'QK6,GF! !Gb!I9&J$&HJiFaJ")YM(I!3l0B#&81Li+)#&6h#!H(!&!S"$K!`"!UJ!@aXj`95 $0X$+6*U(+j!!!0mDKc[S`PS"J,!FbfEa"(Ii!A2J!aZ)"`Y)JNAB3N$6!QT-5EL 8b&0SJM#%S2jSY)'hl%PE8iIf-BHH@3G23)*+N!#&UjX*+h)%8S!!&3!KRaR,bP5 U*&L"cGa-TAa+pM%(EDJeB34+08J(&2"'#FS("f"0GLZ!&'5I")+'8"!&FC!!TCT `"!LB6@B*JIpc(Z!86J!`Je4J0b*B!D9F5J[SKh2SJR0c!A"!!A[-ZQZ)JMD)Ke4 )6Q+iJ3'i"KA!$J*BJ3T)KF2-K#jB"(ASKhlB!QKJTa9D(9)J"@C*KTS8JI1-R"C %'hH`L[BmK@+cY5,!!3Z3!-qP[)&&X-G-!)8)C8UQY)#+I0!NB%SE1)GVi%qV))C &d-cja!(#5,-'fmh*V%NHm$qed4fI-G*-B2i#X!Xl05J#&Bh2'Zf('Th2&5##)P# $0E#+(l#!)-K5TP5(+$J(!R!&TP`"('K1#%`c8H"0CQ'@b43Drh[*Y&N(pQN$`Da 5Z,65))J'(&L"q$a8(!"6`Jc6-CA+NBZ'q&4+q6c8)1M*8pL#%K@&XHc3f'NF6!' &jRR5LB%!2mh(5a9'3,8e&)h,5a96HF)"4P8$&,e53"djBK3a9##&XI68!2382A8 FY5R9kqL#'fK1@eA9UEa84K@j`h3""@K0`5bfYm5"'d$3%[d&0`$1aR&5*ie%ddN Eb&Q#0-`k-d!"#cM9G+9+4Ke-B9a*&eL"`@4A@b1#'`L"kb#(6A!%S2i*eYha9Kj 3!G24(3#-R(9SKfriXc%pKhL9ef9Yc9-)JhjBZ9j39PNP!KZi9[CN"8rJeR!083# -RB`"J1Cj(+&"Qdia@3J3!h1Va#jBf(Pp@*(EJj@,!ANGaL4)6UYSK*lT@)rYeYM abQ"*-diK'T-Pf0bj")4Y(e")"EH8eDTm6DYSJX%NJL6ic%bUJr6NeS%03"l`K)* NX"(K'L4`!fC"fD*eRSr&P$F`8[E*"h@!9VJm"5*J!@JF!#+i@(,9-#V3fSlP@Tr a"$G!Ph3"$H%)fjNS@aiifl2TeVFC"!KJKEj%5"8)K4K3J(6Jc`N,aBeY`ClY9q# %!)K"PlG3*2kkh)QI+P['-GU29FC"@)G,-%X*fMal%!-khG1J8GeJ"GUl%*KDbDe [HDH8N!#Pl1,0GAM*cRAFaPd(CG!"2[$'8+!#`JA)YH%BP-hGhGfL&%+#LR)9UKJ #6`!*a6Q8$89Hb6RHmhe*fL`AJ&6F6-%8i`A1f46F&GU*DHK""`'A0JcDF@UCC9% EAk!!52cAj"d%$'#B5j!!"!SJi*-0h0-Lh*,`*I',K2b&QF[*Q2kYRX&e"!V`KFC &Ak)4SF'p"!U3!!6dABI3a4PcZ9m*TQ!*hJj*'5H9@!)+S)"A5'![3!*-13B+m!) !jS#e33)[U'&*N!#%5jKKAr!#$K$LGR#$'IECJJ5@K-&9&"H'Q4DQiJG4ha35"51 J!#!)PJ4'!M#JJ(E!&"(Ji%%3BbVJhCRJiN)iQMUJ!'-3"@2SBJf1i#Xf'$`1&-4 )#35QJ-&pK6mQBEa3"K*H"`i'PJa1i"3#JLjHLAB)C%R`K"A@Bib`iNS'%Jl1'$m '"P&i"5r!#bm!C8mHia8Di5KHL88@"5!JR$bJJ$c!j#U'P9M'#&HQi4,`K@F3AP% !!b&q"8")&b!)C"*Z"f#3!)416Z9#8"3Ji!!++!&BTQAmRH9S&Mr%!)Rr'GbZ%4Y +TQEm$3J!1`!!"`#Z!(i!"`!"!!%!!`!$!!3!!!!0!!`!%!"D!&S!b`$,!#J!8J! !(P&eD@0V9'PYCDSJCA3JG@iJC)jMEfe`FQ9cFf9eFJ!!+!"A!!8I4dP')(0[ER3 JFQ9aG@Pc)("[GA)JGQPcG@&XDA0PFJ!S!&`!(!aMCA4dC5"TE@&RC5i!!!!!r`! !!&[8T5562q8b-!!%!!!!!!!!!!#k*S3PZLD%*3!!!!!!!!!!!!!!!!!!!!!)Bf* [G'KKEAN!!!!+BQpMD(-ZFR0bB`!!!!!8,5"cCA3JGQ9bFfP[EL"dEb!b,M!!!!! $,!!,!!!!!!$0!FB!i3)!"!*25`!!!!!!'3!'!%X"fBL"9'KTFb"cEfCdGf&bC5" TFb"bC@aPBA0PC#"eEQ4PFL"dD'8J4dj9)%a(8%`Z$8C[FL"YEh*P)'PZCQpbE@& dD@pZ,#"bC@&N)(4SC5"QD@aP)#G$6e"C58j(*b"TEQ0XG@4PC#"TEL"dD'8JBQp MD(-JC'PcG(*TBR9dD@pZ,L!J!!!!!!!!V3!'!0%"ZSK@6@&M6e-JF'pbG#"LH5" %BACTC#"#BA4dCA*SB@dX)&4TE5"6C@jPBf&X,#"$D(*TFh4[F'KP)%*[G'KKEAN JB@jN)%4KEQPPE#"(D@e`C@aPGQPMD#i!!!!!!0)!"J$e!EL)E94SC5"#Ef0SFb" dC@&Y)'Pc)'a[EfYTEQFJCQpb)'%JE@&TER4KD@jPFL"QEh)J3QpMD(-JEfiJ6@& M6e-Z)!e*CL"jEh8JG'KTEQXJH@pe)'0KEL"SC@a`,#"`E'9KFf8JBfpZG'&MG#" eFbi!!!!!!!!&!!B!&J(1L"G#Ef0SFb!b,M%Z-5!JCQpb)%eKBdp6$3!!!!!!!%m !"J#$!Fq)XP0[GA*MC5"MEf4P)'C[FL"#Ef0SFb"TFb"KGQ&TE'&LE'8JCR*[E5" dD'8J3QpMD(-JD'pYC5"`B@GP)'&d)!eSG(4`1Lm[BQpMD(-ZFfpeFQ0PCQpbCf8 ZEQ9d,L"8D'8JC'pMG@ePER4KG'P[EL"TFb"[EQaTEQ8JBA3JD(4dF$S[,f*[BfK c,R0[GA*MC@C[FQGP,QjPG#pNEf-[C'pMBQp[DbpTEQ4PH#jSG'eX)#i!!!!!!)B !"J#R!Fb)C8PQ)(P[G5"hEh9XC#"XD@YP)'0[ER4bD@*eG'8JG'mJG'KP)%*[BfK c)("bEfTPBh3X)("XC@&cC5"UEfPZ)'PZ)#"dD'8JBQpMD(-YC'9fC@a[F'9bFb" YB@PXD@jR)'aTFh3Z!!!!!!!!%!'j!,m#%d!#!)!!!!!!!"!"Z3#r!K0!!J#!!!! !!!!3!EN![`)63!)!J!!!!!!!%!'j!,m#%d!#!)!!!!!!!"!"Z3#r!K0!!J#!!!! "!!!!0ZJ!!$AS!!!!Je028P3(fJ#!!"`!EJ!$4%P86!!!!#*%6%p(!!!!,P"*3e3 !!!!kBfYTC!!!!%B!J2rr!!!bZ!3[T"3!J!!!!!!!!!3[SH3!J2rr!!!!'33[Sp` !J!!'!!!b@33[T%J&3@*[GA318(*[DQ9MG'pb)%4KG'%aNJ: bochs-2.6/build/macos/bochsico.bmp0000644000175000017500000000573012020641472017032 0ustar guillemguillemBMØ 6(   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëëë<<<>>>ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿîîîóóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@@@ X`¼Ø¼Ø£££ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼Ø¼Ø¼Ø¼Ø‡›¼Øsssÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ½½½ µÏ¼Ø¼Ø¼Ø¼Ø¼Øˆš¼Ø¼ØCCCÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ%%%¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø’¼Ø¼Ø¼Ø29mmmÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿaaa*Y`¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø˜¯+++ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿWWW:¶É¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Øéééÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ000¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø"""¼Ø¼Ø»×¸ÔºÖ¼Ø»×ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØØØ¼Ø¼Ø¼Ø¼Ø¼Ø¯Ë«ÇªÆ¬ÈµÒ¼Ø»×¯Ë—´–³˜µ³Ï¼Ø&ajÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼Ø¼Ø¼Ø¶Òœ¹•²š·™¶˜´•²§Ã(*º•²^p!€”–³®Ê%`iÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼Ø»×§Ã•²›¸"P[ ªÆ fy“­#*Wh•²#gtÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¸Õ ½—´&™­*67 ¼Ø¼ØD¡°%&akÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ™¶™¶ %¼Ø¼Ø¼Ø¼Ø¼Ø7¢³¼Ø¼Ø¼Ø¼Øÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’¨'[c¼Ø¼Ø¼Ø¼Ø»× •²»Ö¼Ø¼Ø¼ØÐÐÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼Ø¼Ø¼Ø¼Ø¼Ø36€—•²•²•²7]c¼Ø¼Ø¼ØNNNÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ@~ˆ¼Ø¼Ø¼Ø¼Ø¼Ø•²•²•²•²FM¼Ø¼Ø¼Øÿÿÿÿÿÿÿÿÿ6”¢¼Ø¼Ø¼Ø¼Ø#ºÒANQ•²•²•² ‘­•²•²H‰–¼Ø¼Øÿÿÿÿÿÿÿÿÿ&¶Ì¼Ø¼Ø¼Ø •² •±•²•²•²•²•²²²²ÿÿÿÿÿÿÿÿÿÿÿÿØØØ222)))'47•²•²•²•²•²•²•²444óóóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ•²•²•²•²•²•²•²•²•²•²•²•²•²|þþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷÷÷ ¨•²•²•²•²•²•²•²•²•²•²•²•²•²¼Ø¼Øj–ZZZÿÿÿÿÿÿÿÿÿÿÿÿ•²•²•²•²•²•²•²•²•²•²E_d.z†¼Ø¼Ø¼Ø¼Ø ¼×ÿÿÿÿÿÿÿÿÿ¼Ø¼Ø2z…555•²•²•²•²•²•²•²¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø$*ÿÿÿÿÿÿÿÿÿ¼Ø¼Ø¼Ø¼Ø¼Ø&*+•²•²•²•²U“¼Ø¼Ø¼Ø¼Ø¼Ø¼Ø ûûûÿÿÿÿÿÿÿÿÿÊÊÊ% ³¼Ø¼Ø¼Ø¼Ø¼Ø011•²8˜§¼Ø¼Ø¼Ø¼Ø¼Ø¼ØËËËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¼Ø¼Ø¼Ø¼Ø¼Ø¼ØŠœ¼Ø¼Ø¼Ø¼Ø¼Ø ‘‘‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóóó¼Ø¼Ø¼Ø¼Ø¼Ø¼×T]¼Ø¼Ø¼Ø»×èèèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ7z„¼Ø¼Ø¼Ø š¯{Žóóóÿÿÿýýýþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿííí þþþÿÿÿãããüüüÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòòòÿÿÿÿÿÿÿÿÿÿÿÿ°°°NNNÿÿÿÿÿÿþþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿbochs-2.6/build/makeall.sh0000755000175000017500000000023012020641473015373 0ustar guillemguillem#!/bin/bash for i in build-*; do echo "*** Starting make in $i ***" make -C $i echo "*** make done in $i ***" echo "" echo "" echo "" done bochs-2.6/build/redhat/0000755000175000017500000000000012020641473014702 5ustar guillemguillembochs-2.6/build/redhat/make-rpm0000755000175000017500000000546312020641473016351 0ustar guillemguillem#!/bin/bash -x ######################################################################### # $Id: make-rpm 10766 2011-11-06 12:11:46Z vruppert $ ######################################################################### # build/redhat/make-rpm # # This script creates an RPM from the bochs directory. You must run # it as root from the top of the source directory (where the configure # scripts are). Then just run: # ./build/redhat/make-rpm # ######################################################################### CAT=cat RM=rm CP=cp MV=mv MKDIR=mkdir GREP=grep ECHO=echo RPM=rpm RPMBUILD=/usr/bin/rpmbuild SED=sed TAR=tar RPMSRCPATH=_rpm_top SOURCES=${RPMSRCPATH}/SOURCES SPECS=${RPMSRCPATH}/SPECS RPMSPEC="build/redhat/bochs.rpmspec.template" TMPDIR=/tmp echo Reading version from configure.in script. VERSION='unknown' eval `${GREP} '^VERSION="' configure.in` if test $? != 0 -o "$VERSION" = unknown; then echo Could not get version number from configure.in script. echo Exiting. exit 1 fi # clean up previous rpm builds ${RM} -rf *.rpm ${RPMSRCPATH} if test -f Makefile; then make dist-clean fi # make a TAR.GZ of the entire source directory, exactly as it is. The # tar is placed in $SOURCES/bochs-$VERSION.tar.gz. Because the current # directory could be named nearly anything, I copy all the contents into # $SOURCES/bochs-$VERSION and then build a tar in $SOURCES. ${RM} -rf ${TMPDIR}/bochs-${VERSION} test $? = 0 || exit 1 ${MKDIR} ${TMPDIR}/bochs-${VERSION} test $? = 0 || exit 1 ${TAR} cf - * .??* | (cd ${TMPDIR}/bochs-${VERSION} && tar xf -) test $? = 0 || exit 1 (cd ${TMPDIR}; tar czf bochs-${VERSION}.tar.gz --exclude=.svn bochs-${VERSION}) test $? = 0 || exit 1 ${RM} -rf ${TMPDIR}/bochs-${VERSION} test $? = 0 || exit 1 # create RPM build area rm -rf ${RPMSRCPATH} mkdir ${RPMSRCPATH} ${RPMSRCPATH}/SOURCES ${RPMSRCPATH}/SPECS ${RPMSRCPATH}/BUILD ${RPMSRCPATH}/RPMS ${RPMSRCPATH}/SRPMS test $? = 0 || exit 1 # test that mkdir succeeded # copy source into sources ${MV} ${TMPDIR}/bochs-${VERSION}.tar.gz ${SOURCES} test $? = 0 || exit 1 # copy the spec into SPECS. The template is in $RPMSPEC, and we use # SED to substitute in the version number. ${RM} -f ${SPECS}/bochs.spec test $? = 0 || exit 1 ${CAT} ${RPMSPEC} | ${SED} "s/@SEDVERSION@/${VERSION}/g" > ${SPECS}/bochs.spec test $? = 0 || exit 1 # finally, start the rpm build. if [ -x ${RPMBUILD} ] then ${RPMBUILD} -ba --define "_topdir `pwd`/${RPMSRCPATH}" ${SPECS}/bochs.spec else ${RPM} -ba --define "_topdir `pwd`/${RPMSRCPATH}" ${SPECS}/bochs.spec fi # test status if test $? = 0; then echo RPM build succeeded else echo RPM build failed. exit 1 fi # copy all rpms out into main directory ALLRPMS=`find ${RPMSRCPATH} -name '*.rpm'` if test "$ALLRPMS" != ""; then echo Moving .rpm files into the main directory. mv ${ALLRPMS} . ls -l *.rpm fi bochs-2.6/build/redhat/bochs.rpmspec.template0000644000175000017500000000540212020641473021206 0ustar guillemguillemSummary: Bochs Project x86 PC Emulator Name: bochs Version: @SEDVERSION@ Release: 1 License: LGPL Group: Applications/Emulators URL:http://bochs.sourceforge.net Packager:Volker Ruppert Source:bochs-@SEDVERSION@.tar.gz BuildRoot: /var/tmp/%{name}-buildroot %description Bochs is a highly portable open source IA-32 (x86) PC emulator written in C++, that runs on most popular platforms. It includes emulation of the Intel x86 CPU, common I/O devices, and a custom BIOS. Currently, Bochs can be compiled to emulate a 386, 486, Pentium, Pentium Pro or AMD64 CPU, including optional MMX, SSEx and 3DNow! instructions. Bochs is capable of running most Operating Systems inside the emulation including Linux, DOS, Windows 9X/NT/2000/XP or Windows 7. %define pkg_name bochs %prep rm -rf $RPM_BUILD_DIR/bochs-@SEDVERSION@ tar xzvf $RPM_SOURCE_DIR/bochs-@SEDVERSION@.tar.gz if test "/" != $RPM_BUILD_ROOT; then rm -rf $RPM_BUILD_ROOT fi %build cd $RPM_BUILD_DIR/bochs-@SEDVERSION@ CONFIGURE_ARGS="--prefix=/usr --mandir=$RPM_BUILD_ROOT/%{_mandir}" export CONFIGURE_ARGS sh .conf.linux make make unpack_dlx # must use prefix=/usr since this step sets up # the paths in dlx bochsrc file. %install pwd cd $RPM_BUILD_DIR/bochs-@SEDVERSION@ for i in "" usr usr/bin usr/lib usr/share usr/share/doc %{_mandir}; do if ! test -d $RPM_BUILD_ROOT/$i; then mkdir $RPM_BUILD_ROOT/$i; fi done make install install_dlx prefix=$RPM_BUILD_ROOT/usr # Build list of plugins on the fly (if any). This allows the # spec file to support RPM building with or without plugins. cd $RPM_BUILD_ROOT find .%{_libdir} -type d | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' > \ $RPM_BUILD_DIR/file.list.%{pkg_name} find .%{_libdir} -type f | sed -e 's,^\.,\%attr(-\,root\,root) ,' \ -e '/\/etc\//s|^|%config|' >> \ $RPM_BUILD_DIR/file.list.%{pkg_name} find .%{_libdir} -type l | sed 's,^\.,\%attr(-\,root\,root) ,' >> \ $RPM_BUILD_DIR/file.list.%{pkg_name} # We could use the same technique to produce the complete file list, # with only one very minor problem: it lists directories that are # used by other programs, so when you remove the package you get # errors like # error: cannot remove /usr/share/doc - directory not empty %files -f file.list.%{pkg_name} %defattr(-, root, root) /usr/bin/bochs /usr/bin/bochs-dlx /usr/bin/bxcommit /usr/bin/bximage /usr/share/bochs/* /usr/share/doc/* %{_mandir}/* %clean rm -rf $RPM_BUILD_DIR/bochs-@SEDVERSION@ rm -rf $RPM_BUILD_DIR/file.list.%{pkg_name} if test "/" != $RPM_BUILD_ROOT; then rm -rf $RPM_BUILD_ROOT fi %preun # clean up the bochsout.txt that is always produced if you # run bochs-dlx. rm -rf /usr/share/bochs/dlxlinux/bochsout.txt %postun rmdir /usr/share/bochs > /dev/null 2>&1 bochs-2.6/build/redhat/NOTES0000644000175000017500000000257412020641473015525 0ustar guillemguillemHere's a useful usenet article that shows how to build a filelist instead of having to specify each one. ----------------------------------------------------------------- From: John Ross Hunt (bigboote@mediaone.net) Subject: RE: Newbie to build spec files Newsgroups: linux.redhat.rpm Date: 2000/07/27 > So, is there a better way, in RPM 3, to populate %files? > Because I know > 'buildroot' and it has nothing to do with %files. I found this bit of code in a .spec file to build a %files list on the fly and have been using it ever since. I've always thought RPM should be able to provide a default %files list in the event one isn't present in the .spec file. -- John Ross Hunt bigboote@mediaone.net %define pkg_name foo %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT cd $RPM_BUILD_ROOT find . -type d | sed '1,2d;s,^\.,\%attr(-\,root\,root) \%dir ,' > \ $RPM_BUILD_DIR/file.list.%{pkg_name} find . -type f | sed -e 's,^\.,\%attr(-\,root\,root) ,' \ -e '/\/etc\//s|^|%config|' >> \ $RPM_BUILD_DIR/file.list.%{pkg_name} find . -type l | sed 's,^\.,\%attr(-\,root\,root) ,' >> \ $RPM_BUILD_DIR/file.list.%{pkg_name} %clean rm -rf $RPM_BUILD_ROOT $RPM_BUILD_DIR/file.list.%{pkg_name} %files -f ../file.list.%{pkg_name} %doc README TODO example ----------------------------------------------------------------- bochs-2.6/build/macosx/0000755000175000017500000000000012020641473014725 5ustar guillemguillembochs-2.6/build/macosx/script.r0000644000175000017500000062541512020641473016431 0ustar guillemguillemdata 'scsz' (0) { $"4000 0000 0000 0000 0000 0000 0000 0000" /* @............... */ $"0000 0000 0000 0000 0000" /* .......... */ }; data 'icns' (150) { $"6963 6E73 0000 9D63 4943 4E23 0000 0108" /* icns..cICN#.... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 F000 0000 F000" /* ..........ð...ð. */ $"0003 F800 0003 F000 000F F000 001F E000" /* ..ø...ð...ð...à. */ $"002F F000 003F F800 00FF FC00 00FF FE00" /* ./ð..?ø..ÿü..ÿþ. */ $"00FF FF00 007F FF80 00BF FF80 003F FF80" /* .ÿÿ...ÿ€.¿ÿ€.?ÿ€ */ $"001F FF00 003F FF00 01FF FF80 03FF FFF0" /* ..ÿ..?ÿ..ÿÿ€.ÿÿð */ $"1FFF FFFC 3FFF FFFE 1FFF FFF8 07FF FFF4" /* .ÿÿü?ÿÿþ.ÿÿø.ÿÿô */ $"03FF FFE0 00FF FF80 007F FE40 001F FD00" /* .ÿÿà.ÿÿ€..þ@..ý. */ $"000F F000 0003 D000 0001 A000 0000 0000" /* ..ð...Ð... ..... */ $"696C 3332 0000 0739 AD00 040D 282F 1803" /* il32...9­...(/.. */ $"9700 0615 69AF C7A4 3902 9500 0715 6EC8" /* —...i¯Ç¤9.•...nÈ */ $"DEEB F58E 0D94 0008 156E C9DB EEF0 E9A0" /* ÞëõŽ.”...nÉÛîðé  */ $"1693 0009 166E C9DB EFF2 E6D1 7B0E 9200" /* .“.Æ.nÉÛïòæÑ{.’. */ $"0A15 6EC9 DBEF F1E8 CC9B 3102 9100 0A15" /* Â.nÉÛïñèÌ›1.‘.Â. */ $"6EC9 DBEF F1E9 C8B7 610A 9100 0C15 6DCC" /* nÉÛïñéÈ·a‘...mÌ */ $"DAEF F2E9 CAB3 BEA2 3D05 8F00 0E11 579C" /* Úïòéʳ¾¢=....Wœ */ $"BFF4 F1E9 CAB4 BCC1 CDA9 3F05 8D00 100A" /* ¿ôñéÊ´¼ÁÍ©?... */ $"4B76 5A69 BDEF C9B4 BCC3 C7C8 D6B2 4206" /* KvZi½ïÉ´¼ÃÇÈÖ²B. */ $"8C00 111E 787D 7479 89C8 B4BC C3C7 CBD1" /* Œ...x}ty‰È´¼ÃÇËÑ */ $"D2E0 BA45 068B 0012 2385 9489 879C B4BC" /* ÒàºE.‹..#…”‰‡œ´¼ */ $"C3C7 CCD1 D6DB DDEB C144 048A 0012 1677" /* ÃÇÌÑÖÛÝëÁD.Š...w */ $"AB9F 9AB2 BDC2 C7CC D1D6 DBE0 E6E6 F0A1" /* «Ÿš²½ÂÇÌÑÖÛàææð¡ */ $"1B8A 0012 0335 94B6 B1BD C2C7 CBD1 D6DB" /* .Š...5”¶±½ÂÇËÑÖÛ */ $"E0E5 E9EC DBAF 298B 0011 053B 9DBF C1C7" /* àåéìÛ¯)‹...;¿ÁÇ */ $"CCD1 D6DB E0E5 E9ED E1C6 921E 8C00 101E" /* ÌÑÖÛàåéíáÆ’.Œ... */ $"8AC6 C5CB D1D6 DAE0 E6E9 EDE6 C9AB 4E07" /* ŠÆÅËÑÖÚàæéíæÉ«N. */ $"8A00 130C 4188 BEC8 CFD3 D5DB E0E5 E9EE" /* Š...Aˆ¾ÈÏÓÕÛàåéî */ $"E9CE B598 3609 0187 0016 0A2E 71B3 CCC7" /* éε˜6Æ.‡..Â.q³ÌÇ */ $"C0BB D3DD DEE6 E9ED ECD5 B3B6 CEA9 6F2E" /* À»ÓÝÞæéíìÕ³¶Î©o. */ $"0A83 007F 020F 3975 B2D5 CEC3 BDB7 B2B4" /* ƒ....9u²ÕÎý·²´ */ $"DBEB E7ED EEDA B9AF CFD1 D5D6 B275 390F" /* ÛëçíîÚ¹¯ÏÑÕÖ²u9. */ $"0200 0008 3A84 BEDA D7CF CBBD B0AB ACAC" /* ....:„¾Ú×Ï˽°«¬¬ */ $"8BCB F6EE DFC0 A9B3 BBC5 CFD0 D7DA BD83" /* ‹ËöîßÀ©³»ÅÏÐ×Ú½ƒ */ $"3A08 0017 84DA D6D0 D5D4 D0C5 B8AB A591" /* :...„ÚÖÐÕÔП«¥‘ */ $"7075 D3E9 C5AB 9A98 A2B9 CDD4 D4D0 D4D6" /* puÓéÅ«š˜¢¹ÍÔÔÐÔÖ */ $"8317 0005 2770 C1DC D3D5 D4D1 CABF A896" /* ƒ...'pÁÜÓÕÔÑÊ¿¨– */ $"8575 79C2 B38D 8694 AAC2 D0D4 D3D8 BC6E" /* …uy³†”ªÂÐÔÓØ¼n */ $"2705 0000 1C01 0F44 96D7 D8D4 D5D3 D0B6" /* '......D–רÔÕÓж */ $"B49A 8470 938F 7995 B1C5 D0D3 D7D1 9242" /* ´š„p“y•±ÅÐÓ×Ñ’B */ $"0F01 8200 1804 2166 BADD D4D5 D1C6 DDC8" /* ..‚...!fºÝÔÕÑÆÝÈ */ $"9A77 7579 9AB8 CBD2 D4DA B563 2004 8500" /* šwuyš¸ËÒÔÚµc .…. */ $"1601 0C3B 8DD6 DCCE B6D9 EFB1 747E A9C5" /* ...;ÖÜζÙï±t~©Å */ $"D2D5 DBCF 883A 0C01 8800 1203 1B5D B6DF" /* ÒÕÛψ:..ˆ....]¶ß */ $"BD9B 9F8E 92B9 D0D7 DADF AF5A 1A03 8C00" /* ½›ŸŽ’¹Ð×Ú߯Z..Œ. */ $"0E09 3385 D1D1 B6BF D0D9 DCE4 D281 3209" /* .Æ3…ÑѶ¿ÐÙÜäÒ2Æ */ $"8F00 0C02 1656 B2EE E3E0 E5E9 AE54 1602" /* ....V²îãàåé®T.. */ $"9200 0807 2F84 E0F6 D77F 2E07 9500 0602" /* ’.../„àö×...•... */ $"1453 9351 1402 9800 0206 1106 8B00 AD00" /* .S“Q..˜.....‹.­. */ $"040D 272E 1803 9700 0615 66AA C19F 3702" /* ..'...—...fªÁŸ7. */ $"9500 0715 6BC3 D7E4 F28A 0D94 0008 156B" /* •...kÃ×äòŠ.”...k */ $"C3D4 E7E9 E29B 1593 0009 156B C3D4 E8EB" /* ÃÔçéâ›.“.Æ.kÃÔèë */ $"E0CB 770D 9200 0A15 6BC3 D5E8 EAE2 C696" /* àËw.’.Â.kÃÕèêâÆ– */ $"2F02 9100 0A15 6BC3 D4E8 EAE2 C2B2 5E09" /* /.‘.Â.kÃÔèêâ²^Æ */ $"9100 0C14 6AC5 D3E8 EBE3 C4AE B89C 3B05" /* ‘...jÅÓèëãÄ®¸œ;. */ $"8F00 0E11 5497 BAED EAE3 C4AF B7BB C7A4" /* ...T—ºíêãį·»Ç¤ */ $"3D05 8D00 100A 4A73 5865 B7E8 C3AF B6BD" /* =...ÂJsXe·èï¶½ */ $"C2C3 CFAD 4005 8C00 111D 7479 7175 85C2" /* ÂÃÏ­@.Œ...tyqu… */ $"AFB6 BDC2 C6CB CCDA B543 068B 0012 2282" /* ¯¶½ÂÆËÌÚµC.‹.."‚ */ $"9085 8398 AFB6 BDC2 C6CB D0D5 D6E4 BC42" /* …ƒ˜¯¶½ÂÆËÐÕÖä¼B */ $"048A 0012 1674 A69A 96AD B8BC C2C6 CBD0" /* .Š...t¦š–­¸¼ÂÆËÐ */ $"D5D9 DFDF EA9C 1B8A 0012 0333 90B1 ACB8" /* ÕÙßßêœ.Š...3±¬¸ */ $"BCC1 C6CB CFD5 D9DE E3E6 D4AA 288B 0011" /* ¼ÁÆËÏÕÙÞãæÔª(‹.. */ $"0539 98B9 BBC2 C6CB D0D5 D9DF E3E6 DAC1" /* .9˜¹»ÂÆËÐÕÙßãæÚÁ */ $"8D1D 8C00 101E 88C2 C0C5 CBCF D4DA DFE2" /* .Œ...ˆÂÀÅËÏÔÚßâ */ $"E6DF C3A6 4C07 8A00 130C 4188 BEC8 CBCC" /* æßæL.Š...Aˆ¾ÈËÌ */ $"CFD5 DADE E2E7 E2C8 B096 3609 0187 0016" /* ÏÕÚÞâçâȰ–6Æ.‡.. */ $"0A2E 71B3 CCC7 C1BC CFD7 D8DF E3E6 E5CF" /* Â.q³ÌÇÁ¼ÏרßãæåÏ */ $"ADB3 CFA9 6F2E 0A83 007F 020F 3975 B2D5" /* ­³Ï©o.ƒ....9u²Õ */ $"CEC3 BDB7 B2B4 D7E4 E1E6 E8D4 B4AB CFD1" /* Îý·²´×äáæèÔ´«ÏÑ */ $"D5D6 B275 390F 0200 0008 3A84 BEDA D7CF" /* ÕÖ²u9.....:„¾Ú×Ï */ $"CBBD B0AB ACAC 8AC6 EFE7 D9BB A5B3 BBC5" /* ˽°«¬¬ŠÆïçÙ»¥³»Å */ $"CFD0 D7DA BD83 3A08 0017 84DA D6D0 D5D4" /* ÏÐ×Ú½ƒ:...„ÚÖÐÕÔ */ $"D0C5 B8AB A590 6C71 CDE2 BFA6 9999 A2B9" /* П«¥lqÍ⿦™™¢¹ */ $"CDD4 D4D0 D4D6 8317 0005 2770 C1DC D3D5" /* ÍÔÔÐÔÖƒ...'pÁÜÓÕ */ $"D4D1 CABF A791 8171 76BD AE8B 8794 AAC2" /* ÔÑÊ¿§‘qv½®‹‡”ªÂ */ $"D0D4 D3D8 BC6E 2705 0000 1C01 0F44 96D7" /* ÐÔÓØ¼n'......D–× */ $"D8D4 D5D3 D0B3 AF95 806D 8F8C 7995 B1C5" /* ØÔÕÓг¯•€mŒy•±Å */ $"D0D3 D7D1 9242 0F01 8200 1804 2166 BADD" /* ÐÓ×Ñ’B..‚...!fºÝ */ $"D4D5 D1C3 D7C2 9574 7279 9AB8 CBD2 D4DA" /* ÔÕÑÃוtryš¸ËÒÔÚ */ $"B563 2004 8500 1601 0C3B 8DD6 DCCE B6D4" /* µc .…....;ÖÜÎ¶Ô */ $"E8AB 717E A8C5 D2D5 DBCF 883A 0C01 8800" /* è«q~¨ÅÒÕÛψ:..ˆ. */ $"1203 1B5D B6DF BD9A 9D8C 92B9 D0D7 DADF" /* ...]¶ß½šŒ’¹Ð×Úß */ $"AF5A 1A03 8C00 0E09 3385 D1D1 B7C0 D0D9" /* ¯Z..Œ..Æ3…ÑÑ·ÀÐÙ */ $"DCE4 D281 3209 8F00 0C02 1656 B2EE E3E0" /* ÜäÒ2Æ....V²îãà */ $"E5E9 AE54 1602 9200 0807 2F84 E0F6 D77F" /* åé®T..’.../„àö×. */ $"2E07 9500 0602 1453 9351 1402 9800 0206" /* ..•....S“Q..˜... */ $"1106 8B00 AD00 040D 272E 1803 9700 0615" /* ..‹.­...'...—... */ $"67AC C4A1 3802 9500 0715 6CC5 DAE7 F38C" /* g¬Ä¡8.•...lÅÚçóŒ */ $"0D94 0008 156C C6D7 EAEC E59D 1593 0009" /* .”...lÆ×êìå.“.Æ */ $"156C C5D7 EBEE E2CD 790E 9200 0A15 6CC6" /* .lÅ×ëîâÍy.’.Â.lÆ */ $"D7EB EDE4 C998 3002 9100 0A15 6CC5 D7EB" /* ×ëíäɘ0.‘.Â.lÅ×ë */ $"EDE5 C5B4 600A 9100 0C15 6BC8 D6EB EEE5" /* íåÅ´`‘...kÈÖëîå */ $"C7B0 BB9F 3C05 8F00 0E11 5699 BCF0 EDE5" /* ǰ»Ÿ<....V™¼ðíå */ $"C7B1 B9BE CAA7 3E05 8D00 100A 4B74 5967" /* DZ¹¾Ê§>...ÂKtYg */ $"BAEB C6B1 B9C0 C4C6 D2AF 4105 8C00 111D" /* ºëƱ¹ÀÄÆÒ¯A.Œ... */ $"767A 7277 86C4 B1B9 BFC4 C9CD CFDD B744" /* vzrw†Ä±¹¿ÄÉÍÏÝ·D */ $"068B 0012 2383 9187 859A B1B9 BFC4 C9CD" /* .‹..#ƒ‘‡…š±¹¿ÄÉÍ */ $"D2D8 D9E7 BE43 048A 0012 1676 A89C 98AF" /* ÒØÙç¾C.Š...v¨œ˜¯ */ $"BABF C3C9 CDD2 D8DC E2E2 ED9E 1B8A 0012" /* º¿ÃÉÍÒØÜââíž.Š.. */ $"0334 91B3 AEBA BFC4 C9CD D2D8 DCE1 E6E9" /* .4‘³®º¿ÄÉÍÒØÜáæé */ $"D7AC 288B 0011 053A 9BBC BEC4 C9CD D2D7" /* ׬(‹...:›¼¾ÄÉÍÒ× */ $"DCE2 E6E9 DDC3 8F1E 8C00 101E 89C4 C2C8" /* ÜâæéÝÃ.Œ...‰ÄÂÈ */ $"CDD2 D7DC E2E5 E9E2 C5A8 4D07 8A00 130C" /* ÍÒ×ÜâåéâŨM.Š... */ $"4188 BEC7 CDCE D1D7 DCE1 E5EA E5CB B297" /* Aˆ¾ÇÍÎÑ×Üáåêå˲— */ $"3609 0187 0016 0A2E 71B3 CCC7 C1BC D1DA" /* 6Æ.‡..Â.q³ÌÇÁ¼ÑÚ */ $"DBE2 E5E9 E8D2 AFB4 CFA9 6F2E 0A83 007C" /* ÛâåéèÒ¯´Ï©o.ƒ.| */ $"020F 3975 B2D5 CEC3 BDB7 B2B4 D8E7 E3E9" /* ..9u²ÕÎý·²´Øçãé */ $"EAD7 B6AD CED1 D5D6 B275 390F 0200 0008" /* ê×¶­ÎÑÕÖ²u9..... */ $"3A84 BEDA D7CF CBBD B0AB ACAC 8AC8 F2EA" /* :„¾Ú×Ï˽°«¬¬ŠÈòê */ $"DBBD A6B3 BBC5 CFD0 D7DA BD83 3A00 0017" /* Û½¦³»ÅÏÐ×Ú½ƒ:... */ $"84DA D6D0 D5D4 D0C5 B8AB A591 6E73 D0E5" /* „ÚÖÐÕÔП«¥‘nsÐå */ $"C2A8 9A99 A2B9 CDD4 D4D0 D4D6 8300 0005" /* Â¨š™¢¹ÍÔÔÐÔÖƒ... */ $"2770 C1DC D3D5 D4D1 CABF A893 8373 78BF" /* 'pÁÜÓÕÔÑÊ¿¨“ƒsx¿ */ $"B08C 8794 AAC2 D0D4 D3D8 BC6E 2780 001C" /* °Œ‡”ªÂÐÔÓØ¼n'€.. */ $"010F 4496 D7D8 D4D5 D3D0 B5B1 9781 6F90" /* ..D–רÔÕÓе±—o */ $"8D79 95B1 C5D0 D3D7 D192 420F 0182 0018" /* y•±ÅÐÓ×Ñ’B..‚.. */ $"0421 66BA DDD4 D5D1 C4D9 C497 7574 799A" /* .!fºÝÔÕÑÄÙÄ—utyš */ $"B8CB D2D4 DAB5 6320 0485 0016 010C 3B8D" /* ¸ËÒÔÚµc .…....; */ $"D6DC CEB6 D6EB AE72 7EA9 C5D2 D5DB CF88" /* ÖÜζÖë®r~©ÅÒÕÛψ */ $"3A0C 0188 0012 031B 5DB6 DFBD 9A9E 8D92" /* :..ˆ....]¶ß½šž’ */ $"B9D0 D7DA DFAF 5A1A 038C 000E 0933 85D1" /* ¹Ð×Ú߯Z..Œ..Æ3…Ñ */ $"D1B6 BFD0 D9DC E4D2 8132 098F 000C 0216" /* Ѷ¿ÐÙÜäÒ2Æ.... */ $"56B2 EEE3 E0E5 E9AE 5416 0292 0008 072F" /* V²îãàåé®T..’.../ */ $"84E0 F6D7 7F2E 0795 0006 0214 5393 5114" /* „àö×...•....S“Q. */ $"0298 0002 0611 068B 006C 386D 6B00 0004" /* .˜.....‹.l8mk... */ $"0800 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"000A 272E 1101 0000 0000 0000 0000 0000" /* .Â'............. */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"1473 CCD8 9324 0100 0000 0000 0000 0000" /* .sÌØ“$.......... */ $"0000 0000 0000 0000 0000 0000 0000 0014" /* ................ */ $"7CF3 FFFF F97B 0800 0000 0000 0000 0000" /* |óÿÿù{.......... */ $"0000 0000 0000 0000 0000 0000 0000 147E" /* ...............~ */ $"F4FF FFFF FEA5 1000 0000 0000 0000 0000" /* ôÿÿÿþ¥.......... */ $"0000 0000 0000 0000 0000 0000 0014 7DF4" /* ..............}ô */ $"FFFF FFFF FA7F 0800 0000 0000 0000 0000" /* ÿÿÿÿú........... */ $"0000 0000 0000 0000 0000 0000 157D F3FF" /* .............}óÿ */ $"FFFF FFFD B029 0100 0000 0000 0000 0000" /* ÿÿÿý°).......... */ $"0000 0000 0000 0000 0000 0014 7DF4 FFFF" /* ............}ôÿÿ */ $"FFFF FFED 5D06 0000 0000 0000 0000 0000" /* ÿÿÿí]........... */ $"0000 0000 0000 0000 0000 147D F4FF FFFF" /* ...........}ôÿÿÿ */ $"FFFF FFFE C23A 0400 0000 0000 0000 0000" /* ÿÿÿþÂ:.......... */ $"0000 0000 0000 0000 0014 7EF4 FFFF FFFF" /* ..........~ôÿÿÿÿ */ $"FFFF FFFF FEC2 3A04 0000 0000 0000 0000" /* ÿÿÿÿþÂ:......... */ $"0000 0000 0000 0000 0A73 F3FF FFFF FFFF" /* ........Âsóÿÿÿÿÿ */ $"FFFF FFFF FFFE C33A 0400 0000 0000 0000" /* ÿÿÿÿÿþÃ:........ */ $"0000 0000 0000 0000 27CD FFFF FFFF FFFF" /* ........'Íÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FEC1 3904 0000 0000 0000" /* ÿÿÿÿÿÿþÁ9....... */ $"0000 0000 0000 0000 2ED9 FFFF FFFF FFFF" /* .........Ùÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFE C037 0200 0000 0000" /* ÿÿÿÿÿÿÿþÀ7...... */ $"0000 0000 0000 0000 1297 FCFF FFFF FFFF" /* .........—üÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FDA3 1700 0000 0000" /* ÿÿÿÿÿÿÿÿý£...... */ $"0000 0000 0000 0000 012B ADFD FFFF FFFF" /* .........+­ýÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFD9 2F00 0000 0000" /* ÿÿÿÿÿÿÿÿÿÙ/..... */ $"0000 0000 0000 0000 0002 2BAD FDFF FFFF" /* ..........+­ýÿÿÿ */ $"FFFF FFFF FFFF FFFF FFBA 1F00 0000 0000" /* ÿÿÿÿÿÿÿÿÿº...... */ $"0000 0000 0000 0000 0000 0646 D5FF FFFF" /* ...........FÕÿÿÿ */ $"FFFF FFFF FFFF FFFF E554 0500 0000 0000" /* ÿÿÿÿÿÿÿÿåT...... */ $"0000 0000 0000 0000 0622 61B8 FBFF FFFF" /* ........."a¸ûÿÿÿ */ $"FFFF FFFF FFFF FFFE B02D 0601 0000 0000" /* ÿÿÿÿÿÿÿþ°-...... */ $"0000 0000 0000 0829 6DBC F3FF FFFF FFFF" /* .......)m¼óÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF F9BB 6E29 0800 0000" /* ÿÿÿÿÿÿÿÿù»n).... */ $"0000 0001 0B31 7AC8 F6FF FFFF FFFF FFFF" /* .....1zÈöÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF F6C8 7A31 0B01" /* ÿÿÿÿÿÿÿÿÿÿöÈz1.. */ $"0000 0737 86D2 F9FF FFFF FFFF FFFF FFFF" /* ...7†Òùÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF F9D2 8637" /* ÿÿÿÿÿÿÿÿÿÿÿÿùÒ†7 */ $"0700 1CA8 F9FF FFFF FFFF FFFF FFFF FFFF" /* ...¨ùÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF F9A9" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿù© */ $"1C00 0C51 B8F7 FFFF FFFF FFFF FFFF FFFF" /* ...Q¸÷ÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFF7 B851" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿ÷¸Q */ $"0C00 0109 2E80 DEFE FFFF FFFF FFFF FFFF" /* ...Æ.€Þþÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFE DE80 2E09" /* ÿÿÿÿÿÿÿÿÿÿÿþÞ€.Æ */ $"0100 0000 0314 4EAE F4FF FFFF FFFF FFFF" /* ......N®ôÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF F4AE 4E14 0300" /* ÿÿÿÿÿÿÿÿÿÿô®N... */ $"0000 0000 0001 0727 76D6 FDFF FFFF FFFF" /* .......'vÖýÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FDD6 7627 0701 0000" /* ÿÿÿÿÿÿÿÿýÖv'.... */ $"0000 0000 0000 0002 1145 A2F0 FFFF FFFF" /* .........E¢ðÿÿÿÿ */ $"FFFF FFFF FFFF FFF0 A245 1102 0000 0000" /* ÿÿÿÿÿÿÿð¢E...... */ $"0000 0000 0000 0000 0006 226C CEFC FFFF" /* .........."lÎüÿÿ */ $"FFFF FFFF FFFC CE6C 2206 0000 0000 0000" /* ÿÿÿÿÿüÎl"....... */ $"0000 0000 0000 0000 0000 020E 3E98 EBFF" /* ............>˜ëÿ */ $"FFFF FFFF EB97 3D0E 0200 0000 0000 0000" /* ÿÿÿÿë—=......... */ $"0000 0000 0000 0000 0000 0000 051D 62C4" /* ..............bÄ */ $"FAFF FAC4 621D 0500 0000 0000 0000 0000" /* úÿúÄb........... */ $"0000 0000 0000 0000 0000 0000 0001 0C36" /* ...............6 */ $"8FCF 8F36 0C01 0000 0000 0000 0000 0000" /* Ï6............ */ $"0000 0000 0000 0000 0000 0000 0000 0004" /* ................ */ $"1838 1804 0000 0000 0000 0000 0000 0000" /* .8.............. */ $"0069 6373 2300 0000 4800 0000 0000 0000" /* .ics#...H....... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 4001 E001" /* ............@.à. */ $"C007 C007 F00F F007 F807 F00F F83F FE3F" /* À.À.ð.ð.ø.ð.ø?þ? */ $"FE1F F803 E805 D000 8069 7333 3200 0002" /* þ.ø.è.Ð.€is32... */ $"6584 0003 010F 1E09 8900 0412 6295 4703" /* e„.....Ɖ...b•G. */ $"8700 0512 6CDA F37E 0986 0006 126C DCEF" /* ‡...lÚó~Ɔ...lÜï */ $"C349 0385 0007 0F60 DCF0 CBB4 550A 8400" /* ÃI.…...`ÜðË´U„. */ $"0906 417C BAD2 B5CA C057 0B83 000A 0B64" /* Æ.A|ºÒµÊÀW.ƒ.Â.d */ $"8E96 BDC7 CFDC D154 0582 000A 0440 9FBB" /* Ž–½ÇÏÜÑT.‚.Â.@Ÿ» */ $"C7D1 DBE3 EF88 0D82 000A 0325 8FCC CDDA" /* ÇÑÛãïˆ.‚.Â.%ÌÍÚ */ $"E5EC C960 0880 003E 0418 4A92 C1C0 DFE7" /* åìÉ`.€.>..J’ÁÀßç */ $"EFD2 BE95 4A18 0408 3E95 C9D1 B3A7 A1E7" /* ïÒ¾•J...>•Éѳ§¡ç */ $"E1AB B6D5 C994 3D07 3899 D9D2 C5AD 7894" /* á«¶ÕÉ”=.8™ÙÒÅ­x” */ $"AD88 AACF D797 3700 031E 68BE DEC8 C476" /* ­ˆªÏ×—7...h¾ÞÈÄv */ $"81B2 DBBA 661E 0380 000A 0A3A 8FC9 B69A" /* ²Ûºf..€.ÂÂ:ɶš */ $"CDDA 8E39 0A83 0008 0219 5EB7 EDBE 6019" /* ÍÚŽ9ƒ....^·í¾`. */ $"0286 0004 0837 7535 0882 0084 0003 010F" /* .†...7u5.‚.„.... */ $"1D09 8900 0412 5F90 4503 8700 0512 69D4" /* .Ɖ..._E.‡...iÔ */ $"F07B 0886 0006 1269 D6E8 BD47 0385 0007" /* ð{.†...iÖè½G.….. */ $"0E5D D6E9 C5AF 5209 8400 0905 3F79 B4CC" /* .]ÖéůRÆ„.Æ.?y´Ì */ $"B0C4 BB55 0A83 000A 0B61 8A92 B8C1 C9D5" /* °Ä»Uƒ.Â.aŠ’¸ÁÉÕ */ $"CB51 0582 000A 043E 9BB6 C1CB D4DC E884" /* ËQ.‚.Â.>›¶ÁËÔÜè„ */ $"0D82 000A 0325 8DC7 C7D4 DEE5 C35D 0880" /* .‚.Â.%ÇÇÔÞåÃ].€ */ $"003E 0418 4A92 C1BF D9E0 E8CB BB95 4A18" /* .>..J’Á¿ÙàèË»•J. */ $"0408 3E95 C9D1 B3A7 9EE0 DBA7 B7D5 C994" /* ..>•Éѳ§žàÛ§·ÕÉ” */ $"3D07 3899 D9D2 C6AC 7490 A888 AACF D797" /* =.8™ÙÒÆ¬t¨ˆªÏ×— */ $"3700 031E 68BE DFC5 BE72 80B2 DBBA 661E" /* 7...h¾ßžr€²Ûºf. */ $"0380 000A 0A3A 8FC8 B399 CDDA 8E39 0A83" /* .€.ÂÂ:ȳ™ÍÚŽ9ƒ */ $"0008 0219 5EB7 EDBE 6019 0286 0004 0837" /* ....^·í¾`..†...7 */ $"7535 0882 0084 0003 010F 1E09 8900 0412" /* u5.‚.„.....Ɖ... */ $"6092 4603 8700 0512 6BD7 F27C 0986 0006" /* `’F.‡...k×ò|Ɔ.. */ $"126B D8EB C048 0385 0007 0F5F D9EC C8B1" /* .kØëÀH.…..._Ùìȱ */ $"530A 8400 0906 407A B6CE B2C7 BD56 0A83" /* S„.Æ.@z¶Î²Ç½Vƒ */ $"000A 0B62 8C94 BAC4 CCD8 CE52 0582 000A" /* .Â.bŒ”ºÄÌØÎR.‚. */ $"043F 9DB8 C4CD D7DF EB86 0D82 000A 0325" /* .?¸ÄÍ×ßë†.‚.Â.% */ $"8ECA CAD6 E1E8 C55E 0880 003D 0418 4A92" /* ŽÊÊÖáèÅ^.€.=..J’ */ $"C1C0 DCE3 EBCE BC96 4A18 0008 3E95 C9D1" /* ÁÀÜãëμ–J...>•ÉÑ */ $"B3A7 9FE3 DDA9 B6D5 C994 0807 3899 D9D2" /* ³§ŸãÝ©¶ÕÉ”..8™ÙÒ */ $"C5AC 7692 AA88 AACF D797 0700 031E 68BE" /* Ŭv’ªˆªÏ×—....h¾ */ $"DEC6 C174 81B2 DBBA 661E 8100 0A0A 3A8F" /* ÞÆÁt²Ûºf..ÂÂ: */ $"C8B4 99CD DA8E 390A 8300 0802 195E B7ED" /* È´™ÍÚŽ9ƒ....^·í */ $"BE60 1902 8600 0408 3775 3508 8200 7338" /* ¾`..†...7u5.‚.s8 */ $"6D6B 0000 0108 0000 0000 0000 0001 0F1D" /* mk.............. */ $"0700 0000 0000 0000 0000 0000 0014 6F9E" /* ..............ož */ $"4002 0000 0000 0000 0000 0000 147E F3FC" /* @............~óü */ $"8307 0000 0000 0000 0000 0014 7EF4 FFE6" /* ƒ...........~ôÿæ */ $"4E02 0000 0000 0000 0000 147E F4FF FFEA" /* N..........~ôÿÿê */ $"5F09 0000 0000 0000 0008 70F3 FFFF FFFF" /* _Æ........póÿÿÿÿ */ $"E15A 0900 0000 0000 000F 9FFE FFFF FFFF" /* áZÆ.......Ÿþÿÿÿÿ */ $"FFE1 5304 0000 0000 0004 4BDB FFFF FFFF" /* ÿáS.......KÛÿÿÿÿ */ $"FFFE 9E0F 0000 0000 0002 1A8A F9FF FFFF" /* ÿþž........Šùÿÿÿ */ $"FFF6 7208 0000 0003 174F 9FED FFFF FFFF" /* ÿör......OŸíÿÿÿÿ */ $"FFFC BC4F 1703 0A46 A9EB FEFF FFFF FFFF" /* ÿü¼O..ÂF©ëþÿÿÿÿÿ */ $"FFFF FEEB A947 0B53 CCFD FFFF FFFF FFFF" /* ÿÿþë©G.SÌýÿÿÿÿÿÿ */ $"FFFF FFFD CC53 0008 3898 EEFF FFFF FFFF" /* ÿÿÿýÌS..8˜îÿÿÿÿÿ */ $"FFFF EE98 3808 0000 0216 5FC5 FBFF FFFF" /* ÿÿî˜8....._Åûÿÿÿ */ $"FBC5 5F16 0200 0000 0000 0630 8DE9 FDE9" /* ûÅ_........0éýé */ $"8D30 0600 0000 0000 0000 0001 1255 B155" /* 0...........U±U */ $"1201 0000 0000 6974 3332 0000 4D55 0000" /* ......it32..MU.. */ $"0000 FF00 FF00 FF00 FF00 FF00 FF00 B400" /* ..ÿ.ÿ.ÿ.ÿ.ÿ.ÿ.´. */ $"07C1 C1C3 C6CC D3DA E2F3 000B C1BC BABE" /* .ÁÁÃÆÌÓÚâó..Á¼º¾ */ $"C5CB D1D7 DDE4 EAF1 F000 0ECA B7B9 C0C5" /* ÅËÑ×Ýäêñð..Ê·¹ÀÅ */ $"CCD3 D7DD E5EA EEF0 F1F2 ED00 0BCA B6B9" /* ÌÓ×Ýåêîðñòí..ʶ¹ */ $"BFC7 CBD2 D8DD E4EA EE80 F001 F1F2 EB00" /* ¿ÇËÒØÝäêî€ð.ñòë. */ $"0BCF B7B9 BEC5 CBD1 D7DD E4E9 EE82 F000" /* .Ï·¹¾ÅËÑ×Ýäéî‚ð. */ $"F1EA 000B CAB7 B9C0 C5CC D2D7 DDE4 EAEE" /* ñê..Ê·¹ÀÅÌÒ×Ýäêî */ $"83F0 01F1 F1E8 000B CAB5 B9C0 C6CC D2D8" /* ƒð.ññè..ʵ¹ÀÆÌÒØ */ $"DDE4 EAEE 84F0 01EF EBE7 000B CFB7 B9BE" /* Ýäêî„ð.ïëç..Ï·¹¾ */ $"C5CB D0D7 DDE3 E9EE 85F0 02EA E3E3 E500" /* ÅËÐ×Ýãéî…ð.êããå. */ $"0BCA B7B9 C0C5 CCD2 D7DE E5EA EE84 F004" /* .Ê·¹ÀÅÌÒ×Þåêî„ð. */ $"EFEA E2DA D8E4 000B C9B5 B9C0 C6CC D2D8" /* ïêâÚØä..ɵ¹ÀÆÌÒØ */ $"DDE5 EAEE 84F0 05EF EAE3 DAD3 D0E3 000B" /* Ýåêî„ð.ïêãÚÓÐã.. */ $"CEB6 B9BE C5CB D0D7 DDE3 EAEE 84F0 06EF" /* ζ¹¾ÅËÐ×Ýãêî„ð.ï */ $"EAE3 DBD3 CBC6 E200 0BCA B7B9 C0C5 CCD2" /* êãÛÓËÆâ..Ê·¹ÀÅÌÒ */ $"D7DE E5E9 EE84 F007 EFEA E1DA D3CB C3C1" /* ×Þåéî„ð.ïêáÚÓËÃÁ */ $"E100 0BC9 B5B9 C0C6 CCD2 D8DD E5EA EE84" /* á..ɵ¹ÀÆÌÒØÝåêî„ */ $"F008 EFEA E3DA D3CC C4BC C0E0 000B CEB6" /* ð.ïêãÚÓÌļÀà..ζ */ $"B9BF C5CB D1D7 DDE3 EAEE 84F0 09EF EAE3" /* ¹¿ÅËÑ×Ýãêî„ðÆïêã */ $"DBD3 CCC6 BCB6 BFDF 000B CDB8 B9BF C6CC" /* ÛÓÌÆ¼¶¿ß..͸¹¿ÆÌ */ $"D1D7 DDE4 E9EE 84F0 0AEF EAE3 DBD3 CBC4" /* Ñ×Ýäéî„ðÂïêãÛÓËÄ */ $"BEB4 B6BE DE00 0BC9 B6B9 BFC5 CCD3 D8DD" /* ¾´¶¾Þ..ɶ¹¿ÅÌÓØÝ */ $"E4EA EE84 F00A EFEA E3DA D3CB C3BC B5AF" /* äêî„ðÂïêãÚÓËüµ¯ */ $"B8DE 000B CEB6 B9BF C5CB D2D8 DDE3 EAEE" /* ¸Þ..ζ¹¿ÅËÒØÝãêî */ $"84F0 0AEF EAE3 DBD3 CCC5 BCB5 ACB6 DE00" /* „ðÂïêãÛÓÌżµ¬¶Þ. */ $"0BCD B8B9 BFC6 CCD1 D7DE E4E9 EE84 F00B" /* .͸¹¿ÆÌÑ×Þäéî„ð. */ $"EFEA E3DB D3CB C4BD B4AC B6C8 DD00 0BC9" /* ïêãÛÓËĽ´¬¶ÈÝ..É */ $"B6B9 BFC5 CCD3 D7DD E5EA EE84 F00B EFEA" /* ¶¹¿ÅÌÓ×Ýåêî„ð.ïê */ $"E3DA D3CB C3BC B4AB B8D1 DD00 0BCA B5B9" /* ãÚÓËü´«¸ÑÝ..ʵ¹ */ $"BFC5 CBD2 D8DD E4EA EE84 F00B EFEA E3DB" /* ¿ÅËÒØÝäêî„ð.ïêãÛ */ $"D3CC C5BC B5AC B9D1 DD00 0BCD B7B9 BFC6" /* ÓÌżµ¬¹ÑÝ..Í·¹¿Æ */ $"CCD1 D7DE E4E9 EE84 F00B EFE9 E2DB D3CB" /* ÌÑ×Þäéî„ð.ïéâÛÓË */ $"C4BD B4AC B7D3 DD00 0BC9 B6BA C0C5 CCD3" /* Ľ´¬·ÓÝ..ɶºÀÅÌÓ */ $"D7DD E5EA EE84 F00B EFEA E2DA D3CB C3BC" /* ×Ýåêî„ð.ïêâÚÓËü */ $"B4AC B8D1 DD00 0BCA B5B9 C0C7 CBD2 D8DD" /* ´¬¸ÑÝ..ʵ¹ÀÇËÒØÝ */ $"E4EA EE84 F00B EFEA E3DA D3CC C5BC B5AE" /* äêî„ð.ïêãÚÓÌżµ® */ $"B2C5 DD00 0BCF B7B9 BEC5 CBD1 D7DD E4E9" /* ²ÅÝ..Ï·¹¾ÅËÑ×Ýäé */ $"EE85 F00C EAE3 DBD3 CBC5 BDB5 ADB0 BCBC" /* î…ð.êãÛÓËŽµ­°¼¼ */ $"C3DB 000B CAB7 B9C0 C5CC D2D7 DDE4 EAEE" /* ÃÛ..Ê·¹ÀÅÌÒ×Ýäêî */ $"84F0 0FEF EAE2 DAD3 CBC4 BDB5 ADB1 BABC" /* „ð.ïêâÚÓËĽµ­±º¼ */ $"BCBE C6D9 000B C9B5 B9C0 C6CC D2D8 DDE4" /* ¼¾ÆÙ..ɵ¹ÀÆÌÒØÝä */ $"EAEE 84F0 11EF EAE3 DAD3 CCC4 BCB5 AEB2" /* êî„ð.ïêãÚÓÌļµ®² */ $"BCBC BDBE BFC1 C8D7 000B CEB6 B9BE C5CB" /* ¼¼½¾¿ÁÈ×..ζ¹¾ÅË */ $"D0D7 DDE3 E9EE 85F0 12EA E3DB D3CC C5BD" /* Ð×Ýãéî…ð.êãÛÓÌŽ */ $"B5AD B0BC BBBC BEBF C0C2 C4CA D500 0BCA" /* µ­°¼»¼¾¿ÀÂÄÊÕ..Ê */ $"B7B9 C0C5 CCD2 D7DE E5EA EE84 F015 EFEA" /* ·¹ÀÅÌÒ×Þåêî„ð.ïê */ $"E2DA D3CB C4BD B4AD B2BB BCBC BEBF C1C2" /* âÚÓËĽ´­²»¼¼¾¿Á */ $"C4C4 C6CC D300 0BC9 B5B9 C0C6 CCD2 D8DD" /* ÄÄÆÌÓ..ɵ¹ÀÆÌÒØÝ */ $"E5EA EE84 F017 EFEA E3DA D3CC C4BC B5AC" /* åêî„ð.ïêãÚÓÌﵬ */ $"B3BC BCBD BEC0 C1C2 C4C5 C6C7 C8CE D100" /* ³¼¼½¾ÀÁÂÄÅÆÇÈÎÑ. */ $"0BCE B7BC C3C9 CED2 D7DD E3EA EE84 F00A" /* .η¼ÃÉÎÒ×Ýãêî„ð */ $"EFEA E3DB D3CC C5BD B5AD B280 BC06 BEBF" /* ïêãÛÓÌŽµ­²€¼.¾¿ */ $"C0C2 C4C5 C680 C801 CBD0 CF00 0BCE BAB4" /* ÀÂÄÅÆ€È.ËÐÏ..κ´ */ $"ADAA B6C8 D8E4 E6E9 EE84 F014 EFEA E1DA" /* ­ª¶ÈØäæéî„ð.ïêáÚ */ $"D3CB C4BD B4AD B2BB BCBD BEBF C1C2 C4C5" /* ÓËĽ´­²»¼½¾¿ÁÂÄÅ */ $"C680 C803 CACB CDD2 CD00 0BCC A183 6B63" /* Æ€È.ÊËÍÒÍ..Ì¡ƒkc */ $"6164 6A83 B6E8 F484 F01D EFEA E3DA D3CC" /* adjƒ¶èô„ð.ïêãÚÓÌ */ $"C4BC B5AD B2BC BCBD BEC0 C1C2 C4C5 C6C8" /* ļµ­²¼¼½¾ÀÁÂÄÅÆÈ */ $"C8C9 CACC CDCD D0D5 CB00 0EC9 8A6B 6261" /* ÈÉÊÌÍÍÐÕË..ÉŠkba */ $"6061 6263 6263 84CE F6F1 81F0 1FEF EAE3" /* `abcbc„Îöñð.ïêã */ $"DBD3 CCC6 BDB5 ADB2 BCBC BDBE BFC1 C2C4" /* ÛÓÌÆ½µ­²¼¼½¾¿ÁÂÄ */ $"C5C7 C8C8 C9CB CCCD CECF D0D2 D6C9 0034" /* ÅÇÈÈÉËÌÍÎÏÐÒÖÉ.4 */ $"B288 6E6B 6662 6263 6567 6969 6771 C0F5" /* ²ˆnkfbbcegiigqÀõ */ $"F1F0 F0EF EAE3 DBD3 CBC4 BEB5 ADB0 BBBB" /* ñððïêãÛÓËľµ­°»» */ $"BCBE BFC1 C2C3 C5C6 C8C8 C9CA CCCC CECF" /* ¼¾¿ÁÂÃÅÆÈÈÉÊÌÌÎÏ */ $"D1D2 D3D5 D8C7 001D A67D 7774 6E67 6464" /* ÑÒÓÕØÇ..¦}wtngdd */ $"6568 6A6B 6D71 7072 BFF6 F0EF EAE3 DAD3" /* ehjkmqpr¿öðïêãÚÓ */ $"CBC3 BCB5 ADB2 80BC 15BE BFC1 C2C4 C5C6" /* Ëüµ­²€¼.¾¿ÁÂÄÅÆ */ $"C7C8 C9CA CBCD CECF D1D2 D3D5 D6D7 DAC5" /* ÇÈÉÊËÍÎÏÑÒÓÕÖ×ÚÅ */ $"0038 B282 7D7C 7771 6B67 6768 6B6C 6E71" /* .8²‚}|wqkgghklnq */ $"7476 757E DAF4 EAE3 DBD3 CCC5 BCB5 ADB2" /* tvu~ÚôêãÛÓÌżµ­² */ $"BCBC BDBE BFC1 C2C4 C5C7 C8C8 C9CA CCCD" /* ¼¼½¾¿ÁÂÄÅÇÈÈÉÊÌÍ */ $"CECF D1D2 D3D5 D6D7 D8D9 DDC4 0039 947C" /* ÎÏÑÒÓÕÖרÙÝÄ.9”| */ $"8180 7B75 6E6A 696B 6D6F 7175 7779 7B77" /* €{unjikmoquwy{w */ $"9DEA E3DB D3CB C4BD B4AD B0BB BBBC BEBF" /* êãÛÓËĽ´­°»»¼¾¿ */ $"C0C2 C4C5 C6C8 C8C9 CACC CDCE CFD1 D2D3" /* ÀÂÄÅÆÈÈÉÊÌÍÎÏÑÒÓ */ $"D4D6 D7D8 D9DA DCE0 C200 1CB5 8582 8585" /* ÔÖרÙÚÜàÂ..µ…‚…… */ $"817A 736F 6E6E 7174 7679 7B7D 7E7F 80C6" /* zsonnqtvy{}~.€Æ */ $"DFD3 CBC3 BCB4 ACB2 80BC 1BBE BFC1 C2C4" /* ßÓËü´¬²€¼.¾¿ÁÂÄ */ $"C5C6 C7C8 C9CA CBCD CECF D1D2 D3D5 D6D7" /* ÅÆÇÈÉÊËÍÎÏÑÒÓÕÖ× */ $"D8D9 DBDC DDDF E3C1 003C A481 8688 8985" /* ØÙÛÜÝßãÁ.<¤†ˆ‰… */ $"7F79 7471 7275 787A 7C7E 7F81 8483 AED8" /* .ytqruxz|~.„ƒ®Ø */ $"CDC5 BCB5 AEB2 BCBC BDBE BFC1 C2C4 C5C7" /* Íżµ®²¼¼½¾¿ÁÂÄÅÇ */ $"C8C8 C9CA CCCD CED0 D1D2 D3D5 D6D7 D8D9" /* ÈÈÉÊÌÍÎÐÑÒÓÕÖ×ØÙ */ $"DBDC DDDF E0E2 E5C0 003D 9A82 898B 8B89" /* ÛÜÝßàâåÀ.=š‚‰‹‹‰ */ $"857E 7876 7678 7A7D 7F81 8184 888A A8CD" /* …~xvvxz}.„ˆŠ¨Í */ $"C6BD B5AD B0BC BBBC BEBF C0C2 C4C5 C6C8" /* ƽµ­°¼»¼¾¿ÀÂÄÅÆÈ */ $"C8C9 CACC CCCE CFD0 D2D3 D5D6 D7D8 D9DA" /* ÈÉÊÌÌÎÏÐÒÓÕÖרÙÚ */ $"DCDD DEE0 E2E2 E4E7 BF00 088B 888C 8D8F" /* ÜÝÞàââäç¿..‹ˆŒ */ $"8F8C 857F 807C 177F 8183 8485 888D 93A7" /* Œ….€|..ƒ„…ˆ“§ */ $"C4BD B5AD B1BA BCBC BEBF C1C2 C4C5 C680" /* Ľµ­±º¼¼¾¿ÁÂÄÅÆ€ */ $"C817 CACC CDCE CFD1 D2D3 D5D6 D7D8 D9DB" /* È.ÊÌÍÎÏÑÒÓÕÖרÙÛ */ $"DCDD DFE0 E2E3 E4E5 E6E9 BE00 3F8B 8C8E" /* ÜÝßàâãäåæé¾.?‹ŒŽ */ $"9193 9492 8D87 8482 8283 8486 8789 8D94" /* ‘“”’‡„‚‚ƒ„†‡‰” */ $"9BAB BCB5 AEB2 BCBC BDBE BFC1 C2C4 C5C7" /* ›«¼µ®²¼¼½¾¿ÁÂÄÅÇ */ $"C8C8 C9CA CCCD CED0 D1D2 D4D5 D6D8 D8D9" /* ÈÈÉÊÌÍÎÐÑÒÔÕÖØØÙ */ $"DBDC DEDF E0E2 E3E4 E6E7 E7E8 EABD 000A" /* ÛÜÞßàâãäæççèê½. */ $"9B8B 9093 9696 9794 908B 8780 8632 8789" /* ›‹“––—”‹‡€†2‡‰ */ $"8C92 9AA2 B1B6 ADB0 BCBB BCBE BFC0 C2C4" /* Œ’𢱶­°¼»¼¾¿ÀÂÄ */ $"C5C6 C8C8 C9CB CCCC CECF D0D2 D3D4 D6D7" /* ÅÆÈÈÉËÌÌÎÏÐÒÓÔÖ× */ $"D8D9 DADC DDDE E0E2 E2E4 E6E7 E8E8 E9EA" /* ØÙÚÜÝÞàââäæçèèéê */ $"ECBC 0020 AE8E 9396 989A 9D9C 9994 8F8B" /* ì¼. ®Ž“–˜šœ™”‹ */ $"898A 8B8D 9299 A2A9 B3AE B1BA BCBC BEBF" /* ‰Š‹’™¢©³®±º¼¼¾¿ */ $"C1C2 C4C5 C680 C816 CACC CDCE CFD1 D2D3" /* ÁÂÄÅÆ€È.ÊÌÍÎÏÑÒÓ */ $"D5D6 D7D8 D9DB DCDD DFE0 E2E3 E4E5 E780" /* ÕÖרÙÛÜÝßàâãäåç€ */ $"E803 EAEB ECE9 BB00 42C2 9696 999B 9FA1" /* è.êëìé».B––™›Ÿ¡ */ $"A2A0 9C96 908E 8D8F 9398 A0A9 B1B3 B1BC" /* ¢ œ–Ž“˜ ©±³±¼ */ $"BCBD BEC0 C1C2 C4C5 C7C8 C8C9 CACC CDCE" /* ¼½¾ÀÁÂÄÅÇÈÈÉÊÌÍÎ */ $"D0D1 D2D4 D5D6 D8D8 D9DB DCDE DFE0 E2E3" /* ÐÑÒÔÕÖØØÙÛÜÞßàâã */ $"E4E6 E7E8 E8E9 EAEC ECEB E7E5 BA00 43CC" /* äæçèèéêììëçåº.CÌ */ $"A295 9B9E A2A5 A6A6 A29B 9592 9194 979D" /* ¢•›ž¢¥¦¦¢›•’‘”— */ $"A7AE B5B4 BABB BCBE BFC0 C2C4 C5C6 C8C8" /* §®µ´º»¼¾¿ÀÂÄÅÆÈÈ */ $"C9CB CCCC CECF D0D2 D3D4 D6D7 D8D9 DADC" /* ÉËÌÌÎÏÐÒÓÔÖרÙÚÜ */ $"DDDE E0E2 E3E4 E6E7 E8E8 E9EA EBEC EBE9" /* ÝÞàâãäæçèèéêëìëé */ $"E2DD DCBA 001C C29A 9EA2 A5A8 AAAA A7A3" /* âÝܺ..šž¢¥¨ªª§£ */ $"9D99 9799 9EA5 ADB4 BBB9 BBBC BEBF C1C2" /* ™—™ž¥­´»¹»¼¾¿Á */ $"C4C5 C680 C816 CACC CDCE D0D1 D2D3 D5D6" /* ÄÅÆ€È.ÊÌÍÎÐÑÒÓÕÖ */ $"D7D8 D9DB DCDD DFE0 E2E3 E4E5 E780 E800" /* רÙÛÜÝßàâãäåç€è. */ $"EA80 EC04 E9E4 DDD6 D3BB 0003 BAA0 A5A9" /* ê€ì.éäÝÖÓ»..º ¥© */ $"81AC 30A8 A4A0 9E9F A5AB B2BC BCBB BDBE" /* ¬0¨¤ žŸ¥«²¼¼»½¾ */ $"C0C1 C2C4 C5C6 C8C8 C9CA CCCD CED0 D1D2" /* ÀÁÂÄÅÆÈÈÉÊÌÍÎÐÑÒ */ $"D4D5 D6D8 D8D9 DBDC DEDF E0E2 E3E4 E6E7" /* ÔÕÖØØÙÛÜÞßàâãäæç */ $"E8E8 E9EA 80EC 06E9 E5DF D8D0 CAAC BA00" /* èèéê€ì.éåߨÐʬº. */ $"42D5 B3A5 ABAC ADAE AEAC AAA6 A4A6 ABB0" /* BÕ³¥«¬­®®¬ª¦¤¦«° */ $"B8BB BABD BEBF C1C2 C4C5 C7C8 C8C9 CBCC" /* ¸»º½¾¿ÁÂÄÅÇÈÈÉËÌ */ $"CDCE CFD1 D2D3 D5D6 D7D8 D9DB DCDD DFE0" /* ÍÎÏÑÒÓÕÖרÙÛÜÝßà */ $"E2E3 E4E6 E7E8 E8E9 EAEB ECED EBE6 E0DB" /* âãäæçèèéêëìíëæàÛ */ $"D3CB C5AC BB00 41C6 B7AB ADAE AFAF B0AE" /* ÓËŬ».AÆ·«­®¯¯°® */ $"ACAC ADB1 B5B8 BABC BEBF C1C2 C3C5 C6C8" /* ¬¬­±µ¸º¼¾¿ÁÂÃÅÆÈ */ $"C8C9 CACC CCCE CFD1 D2D3 D5D6 D7D8 D9DB" /* ÈÉÊÌÌÎÏÑÒÓÕÖרÙÛ */ $"DCDD DFE0 E1E3 E4E5 E7E8 E8E9 EAEB ECED" /* ÜÝßàáãäåçèèéêëìí */ $"EBE7 E1DB D4CC C6BF ACBC 0004 CFBD ACAF" /* ëçáÛÔÌÆ¿¬¼..Ͻ¬¯ */ $"B082 B236 B4B6 B8BA BDBE BFC0 C2C4 C5C6" /* °‚²6´¶¸º½¾¿ÀÂÄÅÆ */ $"C7C8 C9CA CBCD CECF D1D2 D3D5 D6D7 D8D9" /* ÇÈÉÊËÍÎÏÑÒÓÕÖ×ØÙ */ $"DBDC DDDF E0E2 E3E4 E5E6 E8E8 E9EA EBEC" /* ÛÜÝßàâãäåæèèéêëì */ $"EDEC E8E2 DBD4 CDC7 BFB9 ACBD 003F D7BF" /* íìèâÛÔÍÇ¿¹¬½.?׿ */ $"AEB1 B3B4 B5B6 B6B7 B9BB BDBE BFC1 C2C4" /* ®±³´µ¶¶·¹»½¾¿ÁÂÄ */ $"C5C7 C8C8 C9CB CCCD CECF D1D2 D3D5 D6D7" /* ÅÇÈÈÉËÌÍÎÏÑÒÓÕÖ× */ $"D8D9 DBDC DDDF E0E2 E3E4 E6E7 E8E8 E9EA" /* ØÙÛÜÝßàâãäæçèèéê */ $"EBEC EDED E9E4 DED6 CFC9 C2BA B4AC BE00" /* ëìííéäÞÖÏɺ´¬¾. */ $"3ED6 C0B1 B4B5 B7B7 B8B9 BABC BEBF C1C2" /* >ÖÀ±´µ··¸¹º¼¾¿Á */ $"C3C5 C6C8 C8C9 CACC CCCE CFD1 D2D3 D4D6" /* ÃÅÆÈÈÉÊÌÌÎÏÑÒÓÔÖ */ $"D7D8 D9DB DCDD DFE0 E2E3 E4E5 E7E8 E8E9" /* רÙÛÜÝßàâãäåçèèé */ $"EAEB ECED EDEA E5DF D7CF CAC3 BBB4 ADAC" /* êëìííêåß×ÏÊû´­¬ */ $"BF00 3DD7 C2B3 B7B8 B9BA BBBD BEBF C1C2" /* ¿.=׳·¸¹º»½¾¿Á */ $"C4C5 C6C7 C8C9 CACB CDCE CFD1 D2D3 D5D6" /* ÄÅÆÇÈÉÊËÍÎÏÑÒÓÕÖ */ $"D7D8 D9DB DCDD DFE0 E2E3 E4E5 E6E8 E8E9" /* רÙÛÜÝßàâãäåæèèé */ $"EAEB ECED EEEA E6DF D9D1 C9C3 BDB5 ADA7" /* êëìíîêæßÙÑÉýµ­§ */ $"ACC0 003C D8C4 B6B8 BABB BDBE BFC1 C2C4" /* ¬À.<ØÄ¶¸º»½¾¿ÁÂÄ */ $"C5C7 C8C8 C9CA CCCD CECF D1D2 D3D5 D6D7" /* ÅÇÈÈÉÊÌÍÎÏÑÒÓÕÖ× */ $"D8D9 DBDC DDDF E0E2 E3E4 E6E7 E8E8 E9EA" /* ØÙÛÜÝßàâãäæçèèéê */ $"ECEC EDEE EBE7 E2DA D3CC C5BE B8AF A8A3" /* ììíîëçâÚÓÌž¸¯¨£ */ $"ACC1 003A D8C6 B8BB BCBE BFC0 C2C4 C5C6" /* ¬Á.:ØÆ¸»¼¾¿ÀÂÄÅÆ */ $"C8C8 C9CA CCCD CECF D1D2 D3D4 D6D7 D8D9" /* ÈÈÉÊÌÍÎÏÑÒÓÔÖ×ØÙ */ $"DBDC DDDF E0E2 E3E4 E5E7 E8E8 E9EA EBEC" /* ÛÜÝßàâãäåçèèéêëì */ $"EDEE ECE7 E3DB D3CD C6BE B8B1 A9A1 A5C3" /* íîìçãÛÓÍÆ¾¸±©¡¥Ã */ $"0039 DAC8 BDBF BFC1 C2C4 C5C6 C7C8 C9CA" /* .9ÚȽ¿¿ÁÂÄÅÆÇÈÉÊ */ $"CBCD CECF D1D2 D3D5 D6D7 D8D9 DBDC DDDF" /* ËÍÎÏÑÒÓÕÖרÙÛÜÝß */ $"E0E2 E3E4 E5E6 E8E8 E9EA EBEC EDEE EDE9" /* àâãäåæèèéêëìíîíé */ $"E3DD D5CD C7C0 B8B1 ABA2 A3C5 C400 37DB" /* ãÝÕÍÇÀ¸±«¢£ÅÄ.7Û */ $"CCC2 C1C2 C4C5 C7C8 C8C9 CACC CDCE D0D1" /* ÌÂÁÂÄÅÇÈÈÉÊÌÍÎÐÑ */ $"D2D3 D5D6 D7D8 D9DB DCDE DFE0 E2E3 E4E6" /* ÒÓÕÖרÙÛÜÞßàâãäæ */ $"E7E8 E8E9 EAEC ECED EEEE EAE5 DED7 D0C8" /* çèèéêììíîîêåÞ×ÐÈ */ $"C3BB B3AC A59D CBC5 0036 FDE1 CEC8 C4C5" /* û³¬¥ËÅ.6ýáÎÈÄÅ */ $"C6C8 C8C9 CACC CCCE CFD0 D2D3 D5D6 D7D8" /* ÆÈÈÉÊÌÌÎÏÐÒÓÕÖר */ $"D9DA DCDD DEE0 E2E2 E4E6 E7E8 E8E9 EAEB" /* ÙÚÜÝÞàââäæçèèéêë */ $"ECED EEEE EBE7 E0D8 D1CA C2BC B5AD A79C" /* ìíîîëçàØÑʼµ­§œ */ $"BEC4 0007 FDFD FFBF BED0 CDC6 80C8 16CA" /* ¾Ä..ýýÿ¿¾ÐÍÆ€È.Ê */ $"CCCD CECF D1D2 D3D5 D6D7 D8D9 DBDC DDDF" /* ÌÍÎÏÑÒÓÕÖרÙÛÜÝß */ $"E0E2 E3E4 E5E7 80E8 12EA ECEC EDEE EEEB" /* àâãäåç€è.êììíîîë */ $"E7E1 D9D1 CAC4 BCB5 AEA7 9DB2 C400 38FD" /* çáÙÑÊļµ®§²Ä.8ý */ $"AAAA BCC5 C9C8 D2D2 C9C9 CACC CDCE D0D1" /* ªª¼ÅÉÈÒÒÉÉÊÌÍÎÐÑ */ $"D2D4 D5D6 D8D8 D9DB DCDE DFE0 E2E3 E4E6" /* ÒÔÕÖØØÙÛÜÞßàâãäæ */ $"E7E8 E8E9 EBEC ECED EEEE EDE8 E2DA D4CB" /* çèèéëììíîîíèâÚÔË */ $"C6BE B6B0 A99F A9E6 C200 39FD 7F7F BEC6" /* ƾ¶°©Ÿ©æÂ.9ý..¾Æ */ $"CAC9 C9C8 C7D3 D5CB CCCC CECF D0D2 D3D4" /* ÊÉÉÈÇÓÕËÌÌÎÏÐÒÓÔ */ $"D6D7 D8D9 DADC DDDE E0E2 E3E4 E6E7 E8E8" /* ÖרÙÚÜÝÞàâãäæçèè */ $"E9EA EBEC EDEE EEED EAE2 DBD5 CDC6 C1B9" /* éêëìíîîíêâÛÕÍÆÁ¹ */ $"B1AB A2A1 DDC1 0023 FD7F 7FC4 C8CB CACA" /* ±«¢¡ÝÁ.#ý..ÄÈËÊÊ */ $"C9C9 C8C7 C5D4 D8CE CECF D1D2 D3D5 D6D7" /* ÉÉÈÇÅÔØÎÎÏÑÒÓÕÖ× */ $"D8D9 DBDC DDDF E0E2 E3E4 E5E7 80E8 13EA" /* ØÙÛÜÝßàâãäåç€è.ê */ $"ECEC EDEE EFED EAE4 DCD5 CFC8 C0BA B2AA" /* ììíîïíêäÜÕÏÈÀº²ª */ $"A3A0 C8C0 003D FD7F 7FC8 CACC CCCB CBCA" /* £ ÈÀ.=ý..ÈÊÌÌËËÊ */ $"C9C8 C7C5 C4C2 D5DC D0D1 D2D4 D5D6 D8D8" /* ÉÈÇÅÄÂÕÜÐÑÒÔÕÖØØ */ $"D9DB DCDE DFE0 E2E3 E4E6 E7E8 E8E9 EBEC" /* ÙÛÜÞßàâãäæçèèéëì */ $"ECED EEEF EFEB E6DE D7CE CAC2 BBB4 ACA5" /* ìíîïïëæÞ×ÎÊ»´¬¥ */ $"9BCB CBC6 BE00 3B7F 8EC8 CBCD CDCC CBCA" /* ›ËËÆ¾.;.ŽÈËÍÍÌËÊ */ $"CAC8 C7C7 C5C4 C1C0 BED6 E0D3 D3D4 D6D7" /* ÊÈÇÇÅÄÁÀ¾ÖàÓÓÔÖ× */ $"D8D9 DADC DDDE E0E2 E3E4 E6E7 E8E8 E9EA" /* ØÙÚÜÝÞàâãäæçèèéê */ $"EBEC EDEE EFEF ECE6 DFD9 D0CA C4BC B4AE" /* ëìíîïïìæßÙÐÊļ´® */ $"A89C C280 CE02 CCC8 80BA 0001 AACC 80CE" /* ¨œÂ€Î.ÌÈ€º..ªÌ€Î */ $"1FCD CDCC CCCB CAC8 C7C6 C4C2 C0BE BCBA" /* .ÍÍÌÌËÊÈÇÆÄÂÀ¾¼º */ $"D6E2 D5D6 D7D8 D9DB DCDD DFE0 E2E3 E4E5" /* ÖâÕÖרÙÛÜÝßàâãäå */ $"E780 E813 EAEC ECED EEEF EFED E8E0 D9D2" /* ç€è.êììíîïïíèàÙÒ */ $"CBC4 BEB6 AEA8 9FBE 83D0 02CE CBAB B600" /* Ëľ¶®¨Ÿ¾ƒÐ.ÎË«¶. */ $"02B8 CBCF 80CE 36CD CCCC CBCA C9C7 C6C4" /* .¸ËÏ€Î6ÍÌÌËÊÉÇÆÄ */ $"C2C1 BFBC BBB9 B7B5 DCE6 D8D8 D9DB DCDE" /* ÂÁ¿¼»¹·µÜæØØÙÛÜÞ */ $"DFE0 E2E3 E4E6 E7E8 E8E9 EAEC ECED EEEF" /* ßàâãäæçèèéêììíîï */ $"EFED E9E3 DBD3 CCC5 BEB8 B0A9 A0AD 80CF" /* ïíéãÛÓÌž¸°© ­€Ï */ $"80D0 81CF 01CB B8B2 0003 C1CD D0D0 80CF" /* €ÐÏ.˸²..ÁÍÐÐ€Ï */ $"27CE CCCB CAC9 C8C6 C4C3 C1BF BDBB BBB8" /* 'ÎÌËÊÉÈÆÄÃÁ¿½»»¸ */ $"B7B5 B4B3 D9EC D9DB DCDD DFE0 E2E3 E4E6" /* ·µ´³ÙìÙÛÜÝßàâãäæ */ $"E7E8 E8E9 EAEB ECED EE80 EF0D E9E4 DDD5" /* çèèéêëìíî€ï.éäÝÕ */ $"CEC8 C0B9 B3AB A39D CFCF 86D0 03D1 D1CD" /* ÎÈÀ¹³«£ÏφÐ.ÑÑÍ */ $"C1AE 0004 C7D0 D3D2 D280 D137 CFCE CDCC" /* Á®..ÇÐÓÒÒ€Ñ7ÏÎÍÌ */ $"CBC9 C7C6 C4C2 C0BE BCBA B9B7 B6B4 B3B4" /* ËÉÇÆÄÂÀ¾¼º¹·¶´³´ */ $"B4CC EFDC DDDF E0E1 E3E4 E5E7 E8E8 E9EA" /* ´ÌïÜÝßàáãäåçèèéê */ $"EBEC EDEE EEEF EFEB E4DD D7CE C8C2 BAB2" /* ëìíîîïïëäÝ×ÎȺ² */ $"ACA5 9DCD 81D0 85D2 80D3 01D0 C7AA 0001" /* ¬¥ÍÐ…Ò€Ó.ÐǪ.. */ $"C8D2 80D4 3ED3 D3D2 D1D0 CFCE CDCB CAC8" /* ÈÒ€Ô>ÓÓÒÑÐÏÎÍËÊÈ */ $"C5C3 C2C0 BEBC BBB9 B8B6 B5B4 B4B3 B2B2" /* ÅÃÂÀ¾¼»¹¸¶µ´´³²² */ $"CAF3 DFE0 E2E3 E4E5 E6E8 E8E9 EAEB ECED" /* Êóßàâãäåæèèéêëìí */ $"EEEE F0EF EBE6 DDD7 D0C9 C2BB B3AC A69D" /* îîðïëæÝ×ÐÉ»³¬¦ */ $"CBCF D0D0 81D1 00D2 83D3 81D4 01D2 C8A6" /* ËÏÐÐÑ.ÒƒÓÔ.ÒȦ */ $"0001 CED3 82D5 16D4 D3D3 D2D1 CECD CBC9" /* ..ÎÓ‚Õ.ÔÓÓÒÑÎÍËÉ */ $"C6C4 C2C0 BDBC BBB9 B8B6 B5B4 B4B5 82B4" /* ÆÄÂÀ½¼»¹¸¶µ´´µ‚´ */ $"28CC F4E1 E3E4 E6E7 E8E8 E9EA ECEC EDEE" /* (Ìôáãäæçèèéêììíî */ $"EFF0 F0EC E7E1 D8D2 CBC4 BDB6 AEA7 9DB9" /* ïððìçáØÒËĽ¶®§¹ */ $"CDCE CFCF D0D0 D1D1 D2D3 82D4 83D5 01D3" /* ÍÎÏÏÐÐÑÑÒÓ‚ÔƒÕ.Ó */ $"CEA1 0002 9FCE D384 D411 D3D2 D1D0 CFCE" /* Ρ..ŸÎÓ„Ô.ÓÒÑÐÏÎ */ $"CBC8 C5C3 C0BC BAB7 B7B5 B4B3 82B1 01B2" /* ËÈÅÃÀ¼º··µ´³‚±.² */ $"B280 B12A B2CB F4E4 E5E7 E8E8 E9EA EBEC" /* ²€±*²Ëôäåçèèéêëì */ $"EDEE EEEF F0EE E8E1 DAD2 CBC5 BEB6 AFA9" /* íîîïðîèáÚÒËž¶¯© */ $"A0AA C8C8 C9CA CACC CDCE D0D0 D1D2 D281" /*  ªÈÈÉÊÊÌÍÎÐÐÑÒÒ */ $"D384 D402 D3CE 9F9C 0002 B8D0 D485 D548" /* Ó„Ô.ÓΟœ..¸ÐÔ…ÕH */ $"D4D4 D3D2 D1CF CDCA C7C4 C1BC BAB7 B5B3" /* ÔÔÓÒÑÏÍÊÇÄÁ¼º·µ³ */ $"B2B2 B1B0 B1B1 B0B0 B1B0 B1B1 B0B1 B0D2" /* ²²±°±±°°±°±±°±°Ò */ $"F4E7 E8E8 E9EA EBEC EDEE EEEF F0EE E9E2" /* ôçèèéêëìíîîïðîéâ */ $"DBD3 CBC6 BFB7 AFA9 A1A4 C1C1 C3C6 C6C7" /* ÛÓËÆ¿·¯©¡¤ÁÁÃÆÆÇ */ $"C9CA CCCE D0D1 D1D3 D380 D486 D502 D4D0" /* ÉÊÌÎÐÑÑÓÓ€Ô†Õ.ÔÐ */ $"B898 0001 C3D1 88D5 47D4 D3D2 D2D1 CECB" /* ¸˜..ÃшÕGÔÓÒÒÑÎË */ $"C9C5 C2BD BAB7 B4B2 B0AF ADAD ACAD ADAF" /* ÉŽº·´²°¯­­¬­­¯ */ $"AEB0 AFAE AEAC B097 7ED1 EFE8 E9EA ECEC" /* ®°¯®®¬°—~Ñïèéêìì */ $"EDEE EEF0 F0EF EAE4 DCD6 CEC7 C1BA B2AA" /* íîîððïêäÜÖÎÇÁº²ª */ $"A49F BEBA BDBD BFC1 C3C4 C7C8 CACD D0D0" /* ¤Ÿ¾º½½¿ÁÃÄÇÈÊÍÐÐ */ $"D180 D300 D489 D501 D1C3 9400 01C7 D18A" /* Ñ€Ó.Ô‰Õ.ÑÔ..ÇÑŠ */ $"D515 D4D3 D2D2 D1CE CBC9 C5C0 BDB9 B5B2" /* Õ.ÔÓÒÒÑÎËÉÅÀ½¹µ² */ $"B0AE ADAC ABAA ACAB 80AA 0FAB AAAB ADA5" /* °®­¬«ª¬«€ª.«ª«­¥ */ $"7372 75C6 EFEB EBEC EDEE EE80 F01F EBE6" /* sruÆïëëìíîî€ð.ëæ */ $"DED6 CFC9 C2BB B4AC A69C B7B2 B3B5 B7B8" /* ÞÖÏÉ»´¬¦œ·²³µ·¸ */ $"BABC BEC3 C4C7 CBCD D0D1 D2D3 D3D4 8BD5" /* º¼¾ÃÄÇËÍÐÑÒÓÓÔ‹Õ */ $"01D1 C790 0002 CCD3 D78C D614 D5D4 D3D2" /* .ÑÇ..ÌÓ׌Ö.ÕÔÓÒ */ $"CFCD CBC7 C1BF BAB7 B3B1 AFAD ACAB ABAA" /* ÏÍËÇÁ¿º·³±¯­¬««ª */ $"AB80 AA32 ABA9 ABA1 7578 706E 75C5 F3EC" /* «€ª2«©«¡uxpnuÅóì */ $"EDEE EEEF F0F0 ECE6 DFD8 CFCA C3BB B4AD" /* íîîïððìæßØÏÊû´­ */ $"A69D B0AB ADAE AEAF B2B5 B8BB BEC3 C6C9" /* ¦°«­®®¯²µ¸»¾ÃÆÉ */ $"CCD0 D2D3 D4D4 D58D D601 D3CC 8C00 03CD" /* ÌÐÒÓÔÔÕÖ.ÓÌŒ..Í */ $"D1D3 D38C D516 D4D4 D3D2 D1CF CDCA C7C3" /* ÑÓÓŒÕ.ÔÔÓÒÑÏÍÊÇà */ $"BFBA B8B3 B0AE ACAA A9A8 A7A6 A680 A531" /* ¿º¸³°®¬ª©¨§¦¦€¥1 */ $"A6A4 797C 7171 7270 78CA F4EE EEEF F0F0" /* ¦¤y|qqrpxÊôîîïðð */ $"EDE7 E0D9 D2CA C4BD B5AE A89E A9A6 A3A5" /* íçàÙÒÊĽµ®¨ž©¦£¥ */ $"A5A6 A8A9 AAAF B5B8 BDC1 C6C9 CED0 D2D3" /* ¥¦¨©ª¯µ¸½ÁÆÉÎÐÒÓ */ $"D3D4 8AD5 06D4 D4D3 D3D4 D2CD 8900 05B3" /* ÓÔŠÕ.ÔÔÓÓÔÒ͉..³ */ $"D3D6 D4D3 D38B D525 D4D4 D3D2 D1D0 CECB" /* ÓÖÔÓÓ‹Õ%ÔÔÓÒÑÐÎË */ $"C9C5 C1BE BAB6 B4B1 AEAB A9A7 A6A3 A3A4" /* ÉÅÁ¾º¶´±®«©§¦££¤ */ $"A4A1 A47D 8074 7272 7373 7078 CAF5 80F0" /* ¤¡¤}€trrsspxÊõ€ð */ $"22EE E9E2 DBD3 CCC5 BEB7 AFA9 A2A5 A29E" /* "îéâÛÓÌž·¯©¢¥¢ž */ $"9D9C 9EA0 A0A1 A6AB AEB4 BBBF C5C9 CCD0" /* œž  ¡¦«®´»¿ÅÉÌÐ */ $"D2D3 D3D4 89D5 08D4 D3D1 D0D1 D3D4 D1B3" /* ÒÓÓÔ‰Õ.ÔÓÑÐÑÓÔѳ */ $"8800 0A78 93C1 D8D7 D5D4 D4D5 D7D7 87D6" /* ˆ.Âx“ÁØ×ÕÔÔÕ××‡Ö */ $"15D5 D4D4 D3D2 D1CF CCC9 C6C2 BFBD B9B6" /* .ÕÔÔÓÒÑÏÌÉÆÂ¿½¹¶ */ $"B3AE ADAB A8A6 A480 A331 8187 7B76 7474" /* ³®­«¨¦¤€£1‡{vtt */ $"7373 7470 75C8 F8F1 EEE9 E3DC D4CD C6BF" /* sstpuÈøñîéãÜÔÍÆ¿ */ $"B8B0 A9A2 A2A0 9B9B 9898 999A 9DA0 A3AA" /* ¸°©¢¢ ››˜˜™š £ª */ $"AFB4 BBC0 C5CA CDD1 D3D3 D4D5 88D6 09D5" /* ¯´»ÀÅÊÍÑÓÓÔÕˆÖÆÕ */ $"D3D1 CFCE D0D3 BF93 7888 000C 6B89 8BA5" /* ÓÑÏÎÐÓ¿“xˆ..k‰‹¥ */ $"D1D7 D6D3 D3D4 D6D6 D785 D61F D5D5 D4D4" /* Ñ×ÖÓÓÔÖÖ×…Ö.ÕÕÔÔ */ $"D2D2 D1CE CCCA C7C3 C1BE BAB7 B3B0 ACAB" /* ÒÒÑÎÌÊÇÃÁ¾º·³°¬« */ $"A7A5 A5A3 8793 867C 7A78 7676 8074 2770" /* §¥¥£‡“†|zxvv€t'p */ $"78CC F6EA E3DD D5CE C8C1 B9B3 ABA4 AC90" /* xÌöêãÝÕÎÈÁ¹³«¤¬ */ $"9795 9493 9495 9799 9CA1 A6AD B4BA C0C5" /* —•”“”•—™œ¡¦­´ºÀÅ */ $"CBCD D2D2 D3D4 D586 D60B D5D4 D2CF CDCC" /* ËÍÒÒÓÔÕ†Ö.ÕÔÒÏÍÌ */ $"CECB A38B 896B 8900 0B28 7889 8DBB D7D6" /* ÎË£‹‰k‰..(x‰»×Ö */ $"D4D2 D2D4 D686 D549 D4D4 D3D3 D1D1 CFCE" /* ÔÒÒÔÖ†ÕIÔÔÓÓÑÑÏÎ */ $"CCCA C7C3 C1BE BBB7 B3AE ACA9 A6A4 918E" /* ÌÊÇÃÁ¾»·³®¬©¦¤‘Ž */ $"9488 817D 7B79 7776 7574 7471 7BCA EADE" /* ”ˆ}{ywvuttq{ÊêÞ */ $"D8D0 C8C3 BCB3 ACA6 AA8E 8F90 908D 8E8F" /* ØÐÈü³¬¦ªŽŽ */ $"9194 979C 9FA6 AEB5 BBC0 C6CA CFD1 D1D3" /* ‘”—œŸ¦®µ»ÀÆÊÏÑÑÓ */ $"D3D4 84D5 0CD4 D3D2 CFCD CBCC CEB6 8D89" /* ÓÔ„Õ.ÔÓÒÏÍËÌζ‰ */ $"7828 8C00 0651 8387 9CCF D8D5 80D2 01D4" /* x(Œ..Qƒ‡œÏØÕ€Ò.Ô */ $"D685 D547 D4D3 D2D2 D1D1 D0CE CDCB C8C6" /* Ö…ÕGÔÓÒÒÑÑÐÎÍËÈÆ */ $"C3C0 BCB9 B4B0 AEA9 9C8D 9E94 8E87 827F" /* ÃÀ¼¹´°®©œž”އ‚. */ $"7C7A 7876 7575 7470 78C8 DCD1 CAC2 BCB5" /* |zxvuutpxÈÜÑʼµ */ $"ADA7 A88B 8A89 8A88 898A 8D90 959B 9EA3" /* ­§¨‹Š‰Šˆ‰Š•›ž£ */ $"ABB0 B7BD C3C8 CCCF D1D2 D3D4 84D5 0BD4" /* «°·½ÃÈÌÏÑÒÓÔ„Õ.Ô */ $"D3D0 CECC CBCD C79B 8783 518F 000D 166F" /* ÓÐÎÌËÍÇ›‡ƒQ...o */ $"8689 B4D6 D6D3 D1D1 D4D5 D6D6 84D5 45D3" /* †‰´ÖÖÓÑÑÔÕÖÖ„ÕEÓ */ $"D3D2 D2D1 D0D0 CECC CAC7 C4C1 BEBA B5B2" /* ÓÒÒÑÐÐÎÌÊÇÄÁ¾ºµ² */ $"AE8B A89E 9A94 8C87 837F 7D7B 7977 7673" /* ®‹¨žš”Œ‡ƒ.}{ywvs */ $"7470 8FD2 CCC4 BDB6 AFA7 A59A 8685 8687" /* tpÒÌĽ¶¯§¥š†…†‡ */ $"8889 8B8E 9298 9FA3 ABB0 B7BC C2C6 CACE" /* ˆ‰‹Ž’˜Ÿ£«°·¼ÂÆÊÎ */ $"D0D1 D2D3 D482 D50C D4D3 D1CF CCCB CCCD" /* ÐÑÒÓÔ‚Õ.ÔÓÑÏÌËÌÍ */ $"AF89 866F 1692 000C 447E 8495 CADA D7D5" /* ¯‰†o.’..D~„•ÊÚ×Õ */ $"D2D3 D5D8 D784 D643 D5D4 D4D3 D2D2 D1D1" /* ÒÓըׄÖCÕÔÔÓÒÒÑÑ */ $"CFCC CAC6 C3C2 BDB7 A8A5 A2A3 A19B 928C" /* ÏÌÊÆÃ½·¨¥¢£¡›’Œ */ $"8783 807D 7B79 7674 7576 73AE CBBF B8B1" /* ‡ƒ€}{yvtuvs®Ë¿¸± */ $"A9A3 AC7D 8283 8489 888C 8F94 999E A5AD" /* ©£¬}‚ƒ„‰ˆŒ”™ž¥­ */ $"B2B8 BDC3 C6CA CFD1 D2D3 D3D5 82D6 0BD5" /* ²¸½ÃÆÊÏÑÒÓÓÕ‚Ö.Õ */ $"D3D1 CFCD CDCE C394 847E 4495 000D 0E66" /* ÓÑÏÍÍÎÔ„~D•...f */ $"8285 AFD8 D9D6 D2D2 D3D6 D7D7 84D6 40D4" /* ‚…¯ØÙÖÒÒÓÖ×ׄÖ@Ô */ $"D4D3 D3D2 D2D0 CFCD CAC9 C5C3 BF9A ACA6" /* ÔÓÓÒÒÐÏÍÊÉÅÃ¿š¬¦ */ $"AAA9 A298 918C 8784 817D 7976 7576 7670" /* ª©¢˜‘Œ‡„}yvuvvp */ $"87C1 BAB1 ABA4 A978 7E7F 8182 8889 8D93" /* ‡Áº±«¤©x~.‚ˆ‰“ */ $"99A1 A7AD B2B9 BEC3 C7CB CFD0 D2D2 D3D5" /* ™¡§­²¹¾ÃÇËÏÐÒÒÓÕ */ $"81D6 0CD5 D4D2 D0CD CCCD CDAA 8582 660E" /* Ö.ÕÔÒÐÍÌÍͪ…‚f. */ $"9800 0C39 7881 8EC7 DBD8 D4D1 D2D4 D6D7" /* ˜..9xŽÇÛØÔÑÒÔÖ× */ $"85D6 19D4 D4D3 D3D2 D1D0 CFCD C9C6 C2A6" /* …Ö.ÔÔÓÓÒÑÐÏÍÉÆÂ¦ */ $"A8AD B2B1 ABA1 9991 8C88 847F 7B80 7820" /* ¨­²±«¡™‘Œˆ„.{€x */ $"7671 70AD B5AB A6A8 7179 7A7C 7F84 898E" /* vqp­µ«¦¨qyz|.„‰Ž */ $"959B A2A7 B0B4 B9BE C4C8 CBCF D0D1 D2D3" /* •›¢§°´¹¾ÄÈËÏÐÑÒÓ */ $"D581 D60B D5D3 D1CE CDCD CFBE 8D81 7839" /* ÕÖ.ÕÓÑÎÍÍϾx9 */ $"9B00 0C08 607F 81A8 D8DB D6D2 D1D2 D4D7" /* ›...`.¨ØÛÖÒÑÒÔ× */ $"85D6 3BD5 D4D4 D3D3 D2D0 D0CE C9C0 AFAE" /* …Ö;ÕÔÔÓÓÒÐÐÎÉÀ¯® */ $"B4BA B9B3 AAA0 9891 8C87 817D 7C7B 7874" /* ´º¹³ª ˜‘Œ‡}|{xt */ $"6F6B 9BB1 A6A8 8276 767A 7D83 888E 969A" /* ok›±¦¨‚vvz}ƒˆŽ–š */ $"A2A9 B1B7 BCC2 C4C9 CDCF D1D1 D3D3 D580" /* ¢©±·¼ÂÄÉÍÏÑÑÓÓÕ€ */ $"D60C D5D4 D2CF CDCC CECC A481 7F60 089E" /* Ö.ÕÔÒÏÍÌÎ̤.`.ž */ $"000D 2D74 808B C1DC D9D4 D1D1 D3D6 D7D7" /* ..-t€‹ÁÜÙÔÑÑÓÖ×× */ $"84D6 00D4 80D3 43D2 D1CF CBBF ACB5 B9C0" /* „Ö.Ô€ÓCÒÑÏË¿¬µ¹À */ $"C1BD B6AB A197 918A 8582 807C 7772 6D66" /* Á½¶«¡—‘Š…‚€|wrmf */ $"8DAC A593 6D72 777C 8087 8C94 9BA4 ACB3" /* ¬¥“mrw|€‡Œ”›¤¬³ */ $"B9BE C2C7 CACD CFD1 D2D3 D3D5 D6D6 D5D4" /* ¹¾ÂÇÊÍÏÑÒÓÓÕÖÖÕÔ */ $"D3D1 CECC CDCF B989 8074 2DA2 000C 587E" /* ÓÑÎÌÍϹ‰€t-¢..X~ */ $"80A1 D6DD D9D4 D1D2 D5D8 D884 D700 D680" /* €¡ÖÝÙÔÑÒÕØØ„×.Ö€ */ $"D42E D3D1 CDC2 AFBC C1C7 CBC9 C3B9 ADA1" /* Ô.ÓÑͯ¼ÁÇËÉù­¡ */ $"9790 8B89 857D 7770 6B65 8AA9 9E66 7074" /* —‹‰…}wpkeŠ©žfpt */ $"7B80 868E 989F A6AF B4BC C1C5 C9CD D0D2" /* {€†Ž˜Ÿ¦¯´¼ÁÅÉÍÐÒ */ $"D280 D40E D6D7 D7D6 D5D3 D0CE CECF CB9D" /* Ò€Ô.Ö××ÖÕÓÐÎÎÏË */ $"807E 58A5 000C 246E 7F86 BEDE DAD6 D1D0" /* €~X¥..$n.†¾ÞÚÖÑÐ */ $"D2D5 D784 D642 D5D4 D2D2 D1CD C8BD C0C7" /* ÒÕׄÖBÕÔÒÒÑÍȽÀÇ */ $"CED2 D4D0 C6B9 AA9F 9892 8D86 7D76 716B" /* ÎÒÔÐÆ¹ªŸ˜’†}vqk */ $"6791 AA61 6B70 7980 868E 98A1 A8AF B5BD" /* g‘ªakpy€†Ž˜¡¨¯µ½ */ $"C0C5 CACC CFD1 D1D3 D3D4 D6D6 D5D4 D3D0" /* ÀÅÊÌÏÑÑÓÓÔÖÖÕÔÓÐ */ $"CECC CDCF B486 7F6E 24A8 000A 4D7A 7D9A" /* ÎÌÍÏ´†.n$¨.ÂMz}š */ $"D4DD D8D3 CFD0 D380 D781 D640 D5D4 D2D1" /* ÔÝØÓÏÐÓ€×Ö@ÕÔÒÑ */ $"D0CB C6C3 C6CD D5D9 DDDB D4C7 B6AA A29A" /* ÐËÆÃÆÍÕÙÝÛÔǶª¢š */ $"9187 7D76 716A 6AA3 6769 6E79 8388 929B" /* ‘‡}vqjj£ginyƒˆ’› */ $"A2AA B0B9 BFC2 C8CA CECF D1D2 D3D3 D4D6" /* ¢ª°¹¿ÂÈÊÎÏÑÒÓÓÔÖ */ $"D6D5 D4D1 CFCD CDCE C697 7D7A 4DAB 0050" /* ÖÕÔÑÏÍÍÎÆ—}zM«.P */ $"1A69 7D81 B7E0 DBD7 D1D0 D2D6 D8D7 D8D7" /* .i}·àÛ×ÑÐÒÖØ×Ø× */ $"D6D5 D5D4 D1CF CBC5 C2CD D4DC E2E5 E6E0" /* ÖÕÕÔÑÏËÅÂÍÔÜâåæà */ $"D5C6 BAB0 A194 897E 7670 6782 7468 7079" /* ÕÆº°¡”‰~vpg‚thpy */ $"848C 949E A5AF B5BD C1C5 CACD CFD2 D2D4" /* „Œ”ž¥¯µ½ÁÅÊÍÏÒÒÔ */ $"D4D6 D6D7 D6D5 D4D1 CFCE CFD1 AE80 7D69" /* ÔÖÖ×ÖÕÔÑÏÎÏÑ®€}i */ $"1AAE 004C 4676 7C93 D2E0 DAD5 D2D0 D3D7" /* .®.LFv|“ÒàÚÕÒÐÓ× */ $"D9D9 D7D5 D4D4 D0CE C8C1 B9D3 DBE2 E8EB" /* ÙÙ×ÕÔÔÐÎÈÁ¹ÓÛâèë */ $"EBE6 DFD5 CABB A897 8A7F 766F 6E7C 6670" /* ëæßÕÊ»¨—Š.von|fp */ $"7985 8E97 A0AA B2B8 BDC2 C7CA CED0 D2D3" /* y…Ž— ª²¸½ÂÇÊÎÐÒÓ */ $"D4D4 D6D7 D7D6 D4D2 D0CE CED0 C690 7C76" /* ÔÔÖ××ÖÔÒÐÎÎÐÆ|v */ $"46B1 004A 0E62 7B7D B0E1 DFDA D3D1 D3D6" /* F±.J.b{}°áßÚÓÑÓÖ */ $"D9D8 D7D5 D4D0 CEC8 C0B6 A7E3 E9EC EFED" /* ÙØ×ÕÔÐÎÈÀ¶§ãéìïí */ $"EBE7 E0D4 C3AE 9C8E 8076 6F80 6470 7D87" /* ëçàÔ€vo€dp}‡ */ $"919A A5AE B6BA C1C6 CACD D0D3 D3D5 D5D7" /* ‘𥮶ºÁÆÊÍÐÓÓÕÕ× */ $"D7D8 D7D6 D4D2 D0CF D0D0 A87D 7B62 0EB4" /* ר×ÖÔÒÐÏÐШ}{b.´ */ $"0046 3972 7A8C CFE3 DED9 D3D2 D4D6 D7D7" /* .F9rzŒÏãÞÙÓÒÔÖ×× */ $"D6D1 CDC8 BFB6 AA9B FCF0 EFEF EEEB E4D8" /* ÖÑÍÈ¿¶ª›üðïïîëäØ */ $"C7B2 A192 8379 7763 727F 8A95 A1AA B1B9" /* Dz¡’ƒywcr.Š•¡ª±¹ */ $"C0C4 C9CE D0D3 D3D5 D6D6 D8D9 D8D8 D6D4" /* ÀÄÉÎÐÓÓÕÖÖØÙØØÖÔ */ $"D2D0 D1D3 C18A 7A72 39B7 0044 085A 7979" /* ÒÐÑÓÁŠzr9·.D.Zyy */ $"A9E0 E3DE D7D4 D3D4 D6D4 D3CE C8C0 B7A9" /* ©àãÞ×ÔÓÔÖÔÓÎÈÀ·© */ $"9E92 FDF4 F0F0 EDE1 D4C5 B2A2 9588 7D60" /* ž’ýôððíáÔŲ¢•ˆ}` */ $"7784 8E9A A3AD B7BC C2C7 CCCF D3D4 D6D6" /* w„Žš£­·¼ÂÇÌÏÓÔÖÖ */ $"D7D8 D9DA D9D8 D6D4 D2D1 D3D0 A279 795A" /* רÙÚÙØÖÔÒÑÓТyyZ */ $"08BA 0040 2F6F 7987 C9E8 E1DC D5D4 D3D3" /* .º.@/oy‡ÉèáÜÕÔÓÓ */ $"D2CF CBC3 B7AD 9F94 96CF FDF6 EADC CDC0" /* ÒÏË÷­Ÿ”–ÏýöêÜÍÀ */ $"B1A7 976F 687D 8993 9DA7 B2B8 BFC7 CACE" /* ±§—oh}‰“§²¸¿ÇÊÎ */ $"D2D5 D5D7 D8D8 DADB DADA D8D6 D4D3 D3D5" /* ÒÕÕרØÚÛÚÚØÖÔÓÓÕ */ $"BD85 796F 2FBE 003C 5476 78A2 E2E4 DFD7" /* ½…yo/¾.†„ˆ‰ */ $"8B8B 8882 7B78 787A 7B7D 7E80 8184 898F" /* ‹‹ˆ‚{xxz{}~€„‰ */ $"A2BF B8B0 A8AC B5B7 B7B9 B9BB BCBE BFC0" /* ¢¿¸°¨¬µ··¹¹»¼¾¿À */ $"C2C3 C4C4 C5C7 C8C9 CBCC CDCF CFD1 D2D3" /* ÂÃÄÄÅÇÈÉËÌÍÏÏÑÒÓ */ $"D5D6 D7D9 DADA DCDD DEDF E3BE 0018 8687" /* ÕÖ×ÙÚÚÜÝÞßã¾..†‡ */ $"8B8C 8F8F 8E89 8380 7E7E 7F80 8183 8489" /* ‹ŒŽ‰ƒ€~~.€ƒ„‰ */ $"8F97 A6B7 B0A9 AD80 B723 B9BA BBBC BEBF" /* —¦·°©­€·#¹º»¼¾¿ */ $"C0C2 C3C4 C4C6 C7C8 CACB CCCE CFD0 D0D2" /* ÀÂÃÄÄÆÇÈÊËÌÎÏÐÐÒ */ $"D3D5 D6D8 D9DA DBDC DDDF E0E0 E2E4 BD00" /* ÓÕÖØÙÚÛÜÝßààâä½. */ $"0A96 878C 8F91 9392 908B 8783 8082 3284" /* –‡Œ‘“’‹‡ƒ€‚2„ */ $"8588 8E96 9EAB B1A8 ABB7 B6B7 B9B9 BABC" /* …ˆŽ–ž«±¨«·¶·¹¹º¼ */ $"BEBF C0C2 C3C4 C4C5 C6C8 C9CA CCCD CFCF" /* ¾¿ÀÂÃÄÄÅÆÈÉÊÌÍÏÏ */ $"D0D1 D3D4 D6D7 D9D9 DADB DDDF DFE0 E2E3" /* ÐÑÓÔÖ×ÙÙÚÛÝßßàâã */ $"E4E5 BC00 41A8 8A8F 9194 9698 9795 8F8B" /* äå¼.A¨Š‘”–˜—•‹ */ $"8785 8687 898E 959E A4AD A9AC B5B7 B7B9" /* ‡…†‡‰Ž•ž¤­©¬µ··¹ */ $"B9BB BCBE BFC0 C2C3 C4C4 C5C7 C8C9 CBCC" /* ¹»¼¾¿ÀÂÃÄÄÅÇÈÉËÌ */ $"CDCF CFD1 D2D3 D5D6 D7D9 D9DA DCDD DEE0" /* ÍÏÏÑÒÓÕÖ×ÙÙÚÜÝÞà */ $"E1E2 E3E3 E5E5 E2BB 0015 BC91 9194 979A" /* áâããååâ»..¼‘‘”—š */ $"9D9D 9C97 918C 8A8A 8B8F 949C A3AB ADAC" /* œ—‘ŒŠŠ‹”œ£«­¬ */ $"80B7 29B9 BABB BCBE BFC0 C2C3 C4C4 C6C7" /* €·)¹º»¼¾¿ÀÂÃÄÄÆÇ */ $"C8CA CBCC CECF CFD1 D2D3 D5D6 D8D9 DADB" /* ÈÊËÌÎÏÏÑÒÓÕÖØÙÚÛ */ $"DCDD DFE0 E1E2 E3E4 E5E5 E4E0 DEBA 0043" /* ÜÝßàáâãäååäàÞº.C */ $"C69D 9197 999E A0A1 A19D 9791 8E8D 8F93" /* Æ‘—™ž ¡¡—‘Ž“ */ $"99A1 A8AF AFB6 B6B7 B9B9 BABC BEBF C0C2" /* ™¡¨¯¯¶¶·¹¹º¼¾¿À */ $"C3C4 C4C5 C6C8 C9CA CCCD CFCF D0D2 D3D4" /* ÃÄÄÅÆÈÉÊÌÍÏÏÐÒÓÔ */ $"D6D7 D9D9 DADC DDDF DFE0 E2E3 E4E4 E5E5" /* Ö×ÙÙÚÜÝßßàâãääåå */ $"E1DC D7D5 BA00 3ABC 9699 9EA1 A3A5 A5A2" /* áÜ×Õº.:¼–™ž¡£¥¥¢ */ $"9D98 9493 9599 9FA7 AFB6 B4B6 B7B9 B9BB" /* ˜”“•™Ÿ§¯¶´¶·¹¹» */ $"BCBE BFC0 C2C3 C4C4 C5C7 C8CA CBCC CDCF" /* ¼¾¿ÀÂÃÄÄÅÇÈÊËÌÍÏ */ $"CFD1 D2D4 D5D6 D7D9 D9DA DCDD DEE0 E1E2" /* ÏÑÒÔÕÖ×ÙÙÚÜÝÞàáâ */ $"E3E4 80E5 04E2 DDD6 D0CC BB00 03B4 9BA1" /* ãä€å.âÝÖÐÌ»..´›¡ */ $"A481 A73A A39F 9B99 9A9F A6AD B7B7 B6B8" /* ¤§:£Ÿ›™šŸ¦­··¶¸ */ $"B9B9 BBBC BEBF C0C2 C3C4 C4C5 C7C8 CACB" /* ¹¹»¼¾¿ÀÂÃÄÄÅÇÈÊË */ $"CCCE CFCF D1D2 D3D5 D6D8 D9DA DBDC DDDF" /* ÌÎÏÏÑÒÓÕÖØÙÚÛÜÝß */ $"E0E1 E2E3 E4E4 E5E5 E3DE D9D2 CAC4 A7BA" /* àáâãääååãÞÙÒÊħº */ $"0042 CEAE A1A6 A7A8 A9A9 A7A5 A2A0 A0A5" /* .Bή¡¦§¨©©§¥¢  ¥ */ $"ABB2 B6B5 B8B9 B9BB BCBE BFC0 C2C3 C4C4" /* «²¶µ¸¹¹»¼¾¿ÀÂÃÄÄ */ $"C5C7 C8C9 CBCC CDCF D0D0 D2D3 D5D6 D7D9" /* ÅÇÈÉËÌÍÏÐÐÒÓÕÖ×Ù */ $"D9DA DCDD DFDF E1E2 E3E4 E4E5 E6E4 DFDA" /* ÙÚÜÝßßáâãääåæäßÚ */ $"D4CD C5BF A7BB 0041 C0B1 A6A8 A9AA ABAB" /* ÔÍÅ¿§».AÀ±¦¨©ª«« */ $"A9A8 A6A7 ABAF B3B5 B7B9 B9BA BCBD BFC0" /* ©¨¦§«¯³µ·¹¹º¼½¿À */ $"C1C3 C4C4 C5C6 C8C9 CBCC CDCF CFD0 D2D3" /* ÁÃÄÄÅÆÈÉËÌÍÏÏÐÒÓ */ $"D5D6 D7D8 D9DA DCDD DEE0 E1E2 E3E4 E4E5" /* ÕÖרÙÚÜÝÞàáâãääå */ $"E6E4 E0DA D5CE C6C0 BAA7 BC00 04C8 B8A7" /* æäàÚÕÎÆÀº§¼..ȸ§ */ $"AAAB 82AD 36AE B1B3 B5B8 B9B9 BBBC BEBF" /* ª«‚­6®±³µ¸¹¹»¼¾¿ */ $"C0C2 C3C4 C4C5 C7C8 C9CB CCCD CFCF D0D2" /* ÀÂÃÄÄÅÇÈÉËÌÍÏÏÐÒ */ $"D3D5 D6D7 D8D9 DADC DDDE DFE1 E2E3 E4E4" /* ÓÕÖרÙÚÜÝÞßáâãää */ $"E5E6 E5E1 DCD5 CFC7 C0BA B3A7 BD00 3FCF" /* åæåáÜÕÏÇÀº³§½.?Ï */ $"B8A9 ACAE AEAF AFB1 B2B4 B6B8 B9BA BBBC" /* ¸©¬®®¯¯±²´¶¸¹º»¼ */ $"BEBF C0C2 C3C4 C4C5 C7C8 C9CB CCCD CFD0" /* ¾¿ÀÂÃÄÄÅÇÈÉËÌÍÏÐ */ $"D0D2 D3D5 D6D7 D9DA DBDC DDDF E0E1 E2E3" /* ÐÒÓÕÖ×ÙÚÛÜÝßàáâã */ $"E4E4 E5E6 E6E2 DED7 D0C9 C3BC B5AE A7BE" /* ääåææâÞ×ÐÉüµ®§¾ */ $"003E CFBA ACAF AFB1 B2B3 B4B5 B7B9 B9BA" /* .>Ϻ¬¯¯±²³´µ·¹¹º */ $"BCBD BFC0 C1C3 C4C4 C5C6 C8C9 CBCC CDCF" /* ¼½¿ÀÁÃÄÄÅÆÈÉËÌÍÏ */ $"CFD0 D2D3 D5D6 D7D8 D9DA DCDD DEE0 E1E2" /* ÏÐÒÓÕÖרÙÚÜÝÞàáâ */ $"E3E4 E4E5 E6E6 E3DE D8D1 C9C3 BDB6 AFA8" /* ãääåææãÞØÑÉý¶¯¨ */ $"A7BF 003D D0BC AEB0 B2B4 B5B6 B8B9 BABB" /* §¿.=м®°²´µ¶¸¹º» */ $"BCBE BFC0 C2C3 C4C4 C5C7 C8C9 CBCC CDCF" /* ¼¾¿ÀÂÃÄÄÅÇÈÉËÌÍÏ */ $"CFD0 D2D3 D5D6 D7D8 D9DA DCDD DEDF E1E2" /* ÏÐÒÓÕÖרÙÚÜÝÞßáâ */ $"E3E4 E4E5 E6E7 E3DF D9D2 CBC3 BDB7 AFA8" /* ãääåæçãßÙÒËý·¯¨ */ $"A2A7 C000 3CD1 BDB0 B3B5 B6B8 B9BA BBBC" /* ¢§À.<ѽ°³µ¶¸¹º»¼ */ $"BEBF C0C2 C3C4 C4C5 C7C8 C9CB CCCD CFD0" /* ¾¿ÀÂÃÄÄÅÇÈÉËÌÍÏÐ */ $"D0D2 D3D5 D6D7 D9DA DBDC DDDF E0E1 E2E3" /* ÐÒÓÕÖ×ÙÚÛÜÝßàáâã */ $"E4E4 E5E6 E7E5 E1DB D4CD C6BF B9B2 AAA4" /* ääåæçåáÛÔÍÆ¿¹²ª¤ */ $"9EA7 C100 3AD1 C0B3 B6B7 B9B9 BABC BEBF" /* ž§Á.:ÑÀ³¶·¹¹º¼¾¿ */ $"C0C1 C3C4 C4C5 C7C8 C9CB CCCD CFCF D0D2" /* ÀÁÃÄÄÅÇÈÉËÌÍÏÏÐÒ */ $"D3D5 D6D7 D8D9 DADC DDDE E0E1 E2E3 E4E4" /* ÓÕÖרÙÚÜÝÞàáâãää */ $"E5E6 E7E5 E1DC D5CD C7C0 B9B3 ACA4 9D9F" /* åæçåáÜÕÍÇÀ¹³¬¤Ÿ */ $"C300 39D3 C2B8 BABA BBBC BEBF C0C2 C3C4" /* Ã.9Ó¸ºº»¼¾¿ÀÂÃÄ */ $"C4C5 C7C8 C9CB CCCD CFCF D0D2 D3D5 D6D7" /* ÄÅÇÈÉËÌÍÏÏÐÒÓÕÖ× */ $"D8D9 DADC DDDE DFE1 E2E3 E4E4 E5E6 E7E6" /* ØÙÚÜÝÞßáâãääåæçæ */ $"E2DC D6CE C7C1 BBB3 ACA6 9D9E BFC4 0037" /* âÜÖÎÇÁ»³¬¦ž¿Ä.7 */ $"D4C5 BEBB BCBE BFC0 C2C3 C4C4 C6C7 C8CA" /* Ôž»¼¾¿ÀÂÃÄÄÆÇÈÊ */ $"CBCC CDCF CFD0 D2D3 D5D6 D8D9 DADB DCDD" /* ËÌÍÏÏÐÒÓÕÖØÙÚÛÜÝ */ $"DFE0 E1E2 E3E4 E4E5 E6E7 E7E3 DED7 D0CA" /* ßàáâãääåæççãÞ×ÐÊ */ $"C2BD B5AE A7A0 98C5 C500 36FD DBC9 C4BE" /* ½µ®§ ˜ÅÅ.6ýÛÉľ */ $"BFC0 C2C3 C4C4 C5C6 C8C9 CACC CDCF CFD0" /* ¿ÀÂÃÄÄÅÆÈÉÊÌÍÏÏÐ */ $"D1D3 D4D6 D7D9 D9DA DBDD DFDF E0E2 E3E4" /* ÑÓÔÖ×ÙÙÚÛÝßßàâãä */ $"E4E5 E6E7 E6E4 E0D9 D1CB C4BD B7B0 A8A2" /* äåæçæäàÙÑËĽ·°¨¢ */ $"97B8 C400 37FD FDFF BFBD CAC8 C1C2 C3C4" /* —¸Ä.7ýýÿ¿½ÊÈÁÂÃÄ */ $"C4C5 C7C8 C9CB CCCD CFCF D1D2 D3D5 D6D7" /* ÄÅÇÈÉËÌÍÏÏÑÒÓÕÖ× */ $"D9D9 DADC DDDE E0E1 E2E3 E4E4 E5E6 E7E7" /* ÙÙÚÜÝÞàáâãääåæçç */ $"E4E0 DAD3 CBC5 BEB7 B1A9 A298 AEC4 0008" /* äàÚÓËž·±©¢˜®Ä.. */ $"FDAA AABC C5C9 C8CE CD80 C42C C6C7 C8CA" /* ýªª¼ÅÉÈÎÍ€Ä,ÆÇÈÊ */ $"CBCC CECF D0D0 D2D3 D5D6 D8D9 DADB DCDD" /* ËÌÎÏÐÐÒÓÕÖØÙÚÛÜÝ */ $"DFE0 E1E2 E3E4 E4E5 E6E7 E7E6 E1DB D5CD" /* ßàáâãääåæççæáÛÕÍ */ $"C5C0 B9B2 ABA4 9AA3 E0C2 0029 FD7F 7FBE" /* ÅÀ¹²«¤š£àÂ.)ý..¾ */ $"C6CA C9C9 C8C7 D0D1 C6C5 C6C8 C9CA CCCD" /* ÆÊÉÉÈÇÐÑÆÅÆÈÉÊÌÍ */ $"CFCF D0D1 D3D4 D6D7 D9D9 DADC DDDF DFE0" /* ÏÏÐÑÓÔÖ×ÙÙÚÜÝßßà */ $"E2E3 E4E4 E5E6 80E7 0CE3 DCD5 CFC7 C0BB" /* âãää忀ç.ãÜÕÏÇÀ» */ $"B3AB A69D 9DD6 C100 3AFD 7F7F C4C8 CBCA" /* ³«¦ÖÁ.:ý..ÄÈËÊ */ $"CAC9 C9C8 C7C5 D1D3 C8C8 C9CB CCCD CFCF" /* ÊÉÉÈÇÅÑÓÈÈÉËÌÍÏÏ */ $"D1D2 D3D5 D6D7 D9D9 DADC DDDE E0E1 E2E3" /* ÑÒÓÕÖ×ÙÙÚÜÝÞàáâã */ $"E4E4 E5E6 E7E8 E6E3 DED6 CFC9 C2BB B4AD" /* ääåæçèæãÞÖÏÉ»´­ */ $"A59E 9CC3 C000 3DFD 7F7F C8CA CCCC CBCB" /* ¥žœÃÀ.=ý..ÈÊÌÌËË */ $"CAC9 C8C7 C5C4 C2D2 D8CA CBCC CECF CFD1" /* ÊÉÈÇÅÄÂÒØÊËÌÎÏÏÑ */ $"D2D3 D5D6 D8D9 DADB DCDD DFE0 E1E2 E3E4" /* ÒÓÕÖØÙÚÛÜÝßàáâãä */ $"E4E5 E6E7 E8E8 E4DF D8D0 C9C4 BDB5 AFA7" /* äåæçèèäߨÐÉĽµ¯§ */ $"A096 C9CB C6BE 003B 7F8E C8CB CDCD CCCB" /*  –ÉËÆ¾.;.ŽÈËÍÍÌË */ $"CACA C8C7 C7C5 C4C1 C0BE D2DC CECD CFCF" /* ÊÊÈÇÇÅÄÁÀ¾ÒÜÎÍÏÏ */ $"D0D2 D3D4 D6D7 D9D9 DADC DDDF DFE0 E2E3" /* ÐÒÓÔÖ×ÙÙÚÜÝßßàâã */ $"E4E4 E5E6 E7E8 E8E5 E0D9 D2CB C4BE B7AF" /* ääåæçèèåàÙÒËľ·¯ */ $"A9A3 98BF 80CE 02CC C880 BA00 01AA CC80" /* ©£˜¿€Î.ÌÈ€º..ªÌ€ */ $"CE36 CDCD CCCC CBCA C8C7 C6C4 C2C0 BEBC" /* Î6ÍÍÌÌËÊÈÇÆÄÂÀ¾¼ */ $"BAD4 DED0 D0D1 D2D4 D5D6 D7D9 D9DA DCDD" /* ºÔÞÐÐÑÒÔÕÖ×ÙÙÚÜÝ */ $"DEE0 E1E2 E3E4 E4E5 E6E7 E8E8 E6E1 D9D3" /* ÞàáâãääåæçèèæáÙÓ */ $"CCC5 BEB8 B1A9 A39A BA83 D002 CECB ABB6" /* Ìž¸±©£šºƒÐ.ÎË«¶ */ $"0002 B8CB CF80 CE36 CDCC CCCB CAC9 C7C6" /* ..¸ËÏ€Î6ÍÌÌËÊÉÇÆ */ $"C4C2 C1BF BCBB B9B7 B5D9 E2D1 D2D3 D5D6" /* ÄÂÁ¿¼»¹·µÙâÑÒÓÕÖ */ $"D8D9 DADB DCDD DFE0 E1E2 E3E4 E4E5 E6E7" /* ØÙÚÛÜÝßàáâãääåæç */ $"E8E8 E7E2 DCD4 CDC7 C0B9 B2AB A49C AA80" /* èèçâÜÔÍÇÀ¹²«¤œª€ */ $"CF80 D081 CF01 CBB8 B200 03C1 CDD0 D080" /* Ï€ÐÏ.˸²..ÁÍÐЀ */ $"CF27 CECC CBCA C9C8 C6C4 C3C1 BFBD BBBB" /* Ï'ÎÌËÊÉÈÆÄÃÁ¿½»» */ $"B8B7 B5B4 B3D6 E8D3 D5D6 D7D9 D9DA DCDD" /* ¸·µ´³ÖèÓÕÖ×ÙÙÚÜÝ */ $"DFDF E1E2 E3E4 E4E5 E6E7 80E8 0DE3 DDD7" /* ßßáâãääåæç€è.ãÝ× */ $"CFC8 C2BA B4AD A69E 98CF CF86 D003 D1D1" /* ÏȺ´­¦ž˜ÏφÐ.ÑÑ */ $"CDC1 AE00 04C7 D0D3 D2D2 80D1 37CF CECD" /* ÍÁ®..ÇÐÓÒÒ€Ñ7ÏÎÍ */ $"CCCB C9C7 C6C4 C2C0 BEBC BAB9 B7B6 B4B3" /* ÌËÉÇÆÄÂÀ¾¼º¹·¶´³ */ $"B4B4 CBEB D6D7 D8D9 DADC DDDE E0E1 E2E3" /* ´´ËëÖרÙÚÜÝÞàáâã */ $"E4E4 E5E6 E7E7 E8E8 E4DD D7D1 C9C2 BCB5" /* ääåæççèèäÝ×Ñɼµ */ $"ADA7 A098 CB81 D085 D280 D301 D0C7 AA00" /* ­§ ˜ËÐ…Ò€Ó.ÐǪ. */ $"01C8 D280 D43E D3D3 D2D1 D0CF CECD CBCA" /* .ÈÒ€Ô>ÓÓÒÑÐÏÎÍËÊ */ $"C8C5 C3C2 C0BE BCBB B9B8 B6B5 B4B4 B3B2" /* ÈÅÃÂÀ¾¼»¹¸¶µ´´³² */ $"B2C9 EED8 D9DA DCDD DEDF E1E2 E3E4 E4E5" /* ²ÉîØÙÚÜÝÞßáâãääå */ $"E6E7 E7E9 E8E5 DFD7 D1CA C3BC B6AE A7A1" /* æççéèåß×ÑÊü¶®§¡ */ $"99C9 CFD0 D081 D100 D283 D381 D401 D2C8" /* ™ÉÏÐÐÑ.ÒƒÓÔ.ÒÈ */ $"A600 01CE D382 D516 D4D3 D3D2 D1CE CDCB" /* ¦..ÎÓ‚Õ.ÔÓÓÒÑÎÍË */ $"C9C6 C4C2 C0BD BCBB B9B8 B6B5 B4B4 B582" /* ÉÆÄÂÀ½¼»¹¸¶µ´´µ‚ */ $"B428 CBF0 DBDC DDDF E0E1 E2E3 E4E4 E5E6" /* ´(ËðÛÜÝßàáâãääåæ */ $"E7E8 E9E9 E6E1 DAD2 CBC5 BEB7 B1A9 A298" /* çèééæáÚÒËž·±©¢˜ */ $"B6CD CECF CFD0 D0D1 D1D2 D382 D483 D501" /* ¶ÍÎÏÏÐÐÑÑÒÓ‚ÔƒÕ. */ $"D3CE A100 029F CED3 84D4 11D3 D2D1 D0CF" /* ÓΡ..ŸÎÓ„Ô.ÓÒÑÐÏ */ $"CECB C8C5 C3C0 BCBA B7B7 B5B4 B382 B101" /* ÎËÈÅÃÀ¼º··µ´³‚±. */ $"B2B2 80B1 2AB2 CBEE DDDE E0E1 E2E3 E4E4" /* ²²€±*²ËîÝÞàáâãää */ $"E5E6 E7E7 E8E9 E7E1 DBD4 CCC5 C0B8 B1AA" /* åæççèéçáÛÔÌÅÀ¸±ª */ $"A49B A7C7 C8C9 CACA CCCD CED0 D0D1 D2D2" /* ¤›§ÇÈÉÊÊÌÍÎÐÐÑÒÒ */ $"81D3 84D4 02D3 CE9F 9C00 02B8 D0D4 85D5" /* Ó„Ô.ÓΟœ..¸ÐÔ…Õ */ $"48D4 D4D3 D2D1 CFCD CAC7 C4C1 BCBA B7B5" /* HÔÔÓÒÑÏÍÊÇÄÁ¼º·µ */ $"B3B2 B2B1 B0B1 B1B0 B0B1 B0B1 B1B0 B1B0" /* ³²²±°±±°°±°±±°±° */ $"CFF0 E0E1 E2E3 E4E4 E5E6 E7E7 E8E9 E7E2" /* Ïðàáâãääåæççèéçâ */ $"DBD5 CEC5 C0BA B2AB A59C 9FC1 C1C3 C6C6" /* ÛÕÎÅÀº²«¥œŸÁÁÃÆÆ */ $"C7C9 CACC CED0 D1D1 D3D3 80D4 86D5 02D4" /* ÇÉÊÌÎÐÑÑÓÓ€Ô†Õ.Ô */ $"D0B8 9800 01C3 D188 D547 D4D3 D2D2 D1CE" /* и˜..ÃшÕGÔÓÒÒÑÎ */ $"CBC9 C5C2 BDBA B7B4 B2B0 AFAD ADAC ADAD" /* ËÉŽº·´²°¯­­¬­­ */ $"AFAE B0AF AEAE ACB0 977B CCE8 E2E3 E4E4" /* ¯®°¯®®¬°—{Ìèâãää */ $"E5E6 E7E7 E9E9 E8E3 DDD6 CFC8 C1BB B5AD" /* åæççééèãÝÖÏÈÁ»µ­ */ $"A69F 9ABD BABD BDBF C1C3 C4C7 C8CA CDD0" /* ¦Ÿš½º½½¿ÁÃÄÇÈÊÍÐ */ $"D0D1 80D3 00D4 89D5 01D1 C394 0001 C7D1" /* ÐÑ€Ó.Ô‰Õ.ÑÔ..ÇÑ */ $"8AD5 15D4 D3D2 D2D1 CECB C9C5 C0BD B9B5" /* ŠÕ.ÔÓÒÒÑÎËÉÅÀ½¹µ */ $"B2B0 AEAD ACAB AAAC AB80 AA0F ABAA ABAD" /* ²°®­¬«ª¬«€ª.«ª«­ */ $"A572 6F72 C1E9 E4E4 E5E6 E7E7 80E9 1FE4" /* ¥rorÁéääåæçç€é.ä */ $"DFD8 D0CA C3BC B5AF A7A1 97B5 B2B3 B5B7" /* ߨÐÊüµ¯§¡—µ²³µ· */ $"B8BA BCBE C3C4 C7CB CDD0 D1D2 D3D3 D48B" /* ¸º¼¾ÃÄÇËÍÐÑÒÓÓÔ‹ */ $"D501 D1C7 9000 02CC D3D7 8CD6 14D5 D4D3" /* Õ.ÑÇ..ÌÓ׌Ö.ÕÔÓ */ $"D2CF CDCB C7C1 BFBA B7B3 B1AF ADAC ABAB" /* ÒÏÍËÇÁ¿º·³±¯­¬«« */ $"AAAB 80AA 32AB A9AB A173 756D 6B71 C0EB" /* ª«€ª2«©«¡sumkqÀë */ $"E5E6 E7E7 E8E9 E9E5 DFD9 D2CA C4BD B6AF" /* åæççèééåßÙÒÊĽ¶¯ */ $"A9A1 98AD ABAD AEAE AFB2 B5B8 BBBE C3C6" /* ©¡˜­«­®®¯²µ¸»¾ÃÆ */ $"C9CC D0D2 D3D4 D4D5 8DD6 01D3 CC8C 0003" /* ÉÌÐÒÓÔÔÕÖ.ÓÌŒ.. */ $"CDD1 D3D3 8CD5 16D4 D4D3 D2D1 CFCD CAC7" /* ÍÑÓÓŒÕ.ÔÔÓÒÑÏÍÊÇ */ $"C3BF BAB8 B3B0 AEAC AAA9 A8A7 A6A6 80A5" /* ÿº¸³°®¬ª©¨§¦¦€¥ */ $"31A6 A477 796D 6E6F 6D75 C4ED E7E7 E8E9" /* 1¦¤wymnomuÄíççèé */ $"E9E6 E1DA D3CC C4BF B8B0 AAA3 99A5 A5A3" /* éæáÚÓÌÄ¿¸°ª£™¥¥£ */ $"A5A5 A6A8 A9AA AFB5 B8BD C1C6 C9CE D0D2" /* ¥¥¦¨©ª¯µ¸½ÁÆÉÎÐÒ */ $"D3D3 D48A D506 D4D4 D3D3 D4D2 CD89 0005" /* ÓÓÔŠÕ.ÔÔÓÓÔÒ͉.. */ $"B3D3 D6D4 D3D3 8BD5 25D4 D4D3 D2D1 D0CE" /* ³ÓÖÔÓÓ‹Õ%ÔÔÓÒÑÐÎ */ $"CBC9 C5C1 BEBA B6B4 B1AE ABA9 A7A6 A3A3" /* ËÉÅÁ¾º¶´±®«©§¦££ */ $"A4A4 A1A4 7C7C 706E 6F70 706D 74C5 EE80" /* ¤¤¡¤||pnoppmtÅî€ */ $"E922 E7E2 DBD4 CDC6 BFB9 B2AA A49D A1A1" /* é"çâÛÔÍÆ¿¹²ª¤¡¡ */ $"9E9D 9C9E A0A0 A1A6 ABAE B4BB BFC5 C9CC" /* žœž  ¡¦«®´»¿ÅÉÌ */ $"D0D2 D3D3 D489 D508 D4D3 D1D0 D1D3 D4D1" /* ÐÒÓÓÔ‰Õ.ÔÓÑÐÑÓÔÑ */ $"B388 000A 7893 C1D8 D7D5 D4D4 D5D7 D787" /* ³ˆ.Âx“ÁØ×ÕÔÔÕ×ׇ */ $"D615 D5D4 D4D3 D2D1 CFCC C9C6 C2BF BDB9" /* Ö.ÕÔÔÓÒÑÏÌÉÆÂ¿½¹ */ $"B6B3 AEAD ABA8 A6A4 80A3 0380 8477 7380" /* ¶³®­«¨¦¤€£.€„ws€ */ $"712A 7070 6C72 C2F1 E9E7 E2DC D5CE C7C0" /* q*pplrÂñéçâÜÕÎÇÀ */ $"BAB3 ABA4 9D9D A09B 9B98 9899 9A9D A0A3" /* º³«¤ ››˜˜™š £ */ $"AAAF B4BB C0C5 CACD D1D3 D3D4 D588 D609" /* ª¯´»ÀÅÊÍÑÓÓÔÕˆÖÆ */ $"D5D3 D1CF CED0 D3BF 9378 8800 0C6B 898B" /* ÕÓÑÏÎÐÓ¿“xˆ..k‰‹ */ $"A5D1 D7D6 D3D3 D4D6 D6D7 85D6 4AD5 D5D4" /* ¥Ñ×ÖÓÓÔÖÖ×…ÖJÕÕÔ */ $"D4D2 D2D1 CECC CAC7 C3C1 BEBA B7B3 B0AC" /* ÔÒÒÑÎÌÊÇÃÁ¾º·³°¬ */ $"ABA7 A5A5 A386 8F82 7976 7473 7271 7071" /* «§¥¥£†‚yvtsrqpq */ $"6D75 C6EF E4DD D8D0 C8C2 BBB3 ADA6 9FA7" /* muÆïäÝØÐÈ»³­¦Ÿ§ */ $"8F97 9594 9394 9597 999C A1A6 ADB4 BAC0" /* —•”“”•—™œ¡¦­´ºÀ */ $"C5CB CDD2 D2D3 D4D5 86D6 0BD5 D4D2 CFCD" /* ÅËÍÒÒÓÔÕ†Ö.ÕÔÒÏÍ */ $"CCCE CBA3 8B89 6B89 000B 2878 898D BBD7" /* ÌÎË£‹‰k‰..(x‰»× */ $"D6D4 D2D2 D4D6 86D5 1FD4 D4D3 D3D1 D1CF" /* ÖÔÒÒÔÖ†Õ.ÔÔÓÓÑÑÏ */ $"CECC CAC7 C3C1 BEBB B7B3 AEAC A9A6 A491" /* ÎÌÊÇÃÁ¾»·³®¬©¦¤‘ */ $"8B8F 847C 7977 7574 7280 7126 6D77 C5E3" /* ‹„|ywutr€q&mwÅã */ $"D8D1 CAC2 BDB6 AEA7 A1A4 8C8F 9090 8D8E" /* ØÑʽ¶®§¡¤ŒŽ */ $"8F91 9497 9C9F A6AE B5BB C0C6 CACF D1D1" /* ‘”—œŸ¦®µ»ÀÆÊÏÑÑ */ $"D3D3 D484 D50C D4D3 D2CF CDCB CCCE B68D" /* ÓÓÔ„Õ.ÔÓÒÏÍËÌζ */ $"8978 288C 0006 5183 879C CFD8 D580 D201" /* ‰x(Œ..Qƒ‡œÏØÕ€Ò. */ $"D4D6 85D5 47D4 D3D2 D2D1 D1D0 CECD CBC8" /* ÔÖ…ÕGÔÓÒÒÑÑÐÎÍËÈ */ $"C6C3 C0BC B9B4 B0AE A99C 8A9A 9089 827F" /* ÆÃÀ¼¹´°®©œŠš‰‚. */ $"7B78 7675 7372 7271 6D75 C2D6 CAC4 BDB7" /* {xvusrrqmuÂÖÊĽ· */ $"B0A8 A2A3 898A 898A 8889 8A8D 9095 9B9E" /* °¨¢£‰Š‰Šˆ‰Š•›ž */ $"A3AB B0B7 BDC3 C8CC CFD1 D2D3 D484 D50B" /* £«°·½ÃÈÌÏÑÒÓÔ„Õ. */ $"D4D3 D0CE CCCB CDC7 9B87 8351 8F00 0D16" /* ÔÓÐÎÌËÍÇ›‡ƒQ... */ $"6F86 89B4 D6D6 D3D1 D1D4 D5D6 D684 D545" /* o†‰´ÖÖÓÑÑÔÕÖÖ„ÕE */ $"D3D3 D2D2 D1D0 D0CE CCCA C7C4 C1BE BAB5" /* ÓÓÒÒÑÐÐÎÌÊÇÄÁ¾ºµ */ $"B2AE 8AA3 9896 9088 837F 7C7A 7875 7473" /* ²®Š£˜–ˆƒ.|zxuts */ $"7071 6D8B CCC6 BFB8 B1AA A2A0 9786 8586" /* pqm‹ÌÆ¿¸±ª¢ —†…† */ $"8788 898B 8E92 989F A3AB B0B7 BCC2 C6CA" /* ‡ˆ‰‹Ž’˜Ÿ£«°·¼ÂÆÊ */ $"CED0 D1D2 D3D4 82D5 0CD4 D3D1 CFCC CBCC" /* ÎÐÑÒÓÔ‚Õ.ÔÓÑÏÌËÌ */ $"CDAF 8986 6F16 9200 0C44 7E84 95CA DAD7" /* ͯ‰†o.’..D~„•ÊÚ× */ $"D5D2 D3D5 D8D7 84D6 43D5 D4D4 D3D2 D2D1" /* ÕÒÓըׄÖCÕÔÔÓÒÒÑ */ $"D1CF CCCA C6C3 C2BD B7A8 A09D 9E9C 958E" /* ÑÏÌÊÆÃ½·¨ žœ•Ž */ $"8883 7F7D 7A78 7573 7172 7370 AAC5 BAB2" /* ˆƒ.}zxusqrspªÅº² */ $"ACA5 9EA8 7C82 8384 8988 8C8F 9499 9EA5" /* ¬¥ž¨|‚ƒ„‰ˆŒ”™ž¥ */ $"ADB2 B8BD C3C6 CACF D1D2 D3D3 D582 D60B" /* ­²¸½ÃÆÊÏÑÒÓÓÕ‚Ö. */ $"D5D3 D1CF CDCD CEC3 9484 7E44 9500 0D0E" /* ÕÓÑÏÍÍÎÔ„~D•... */ $"6682 85AF D8D9 D6D2 D2D3 D6D7 D784 D640" /* f‚…¯ØÙÖÒÒÓÖ×ׄÖ@ */ $"D4D4 D3D3 D2D2 D0CF CDCA C9C5 C3BF 99A6" /* ÔÔÓÓÒÒÐÏÍÊÉÅÿ™¦ */ $"A1A5 A49D 948C 8783 807D 7975 7372 7373" /* ¡¥¤”Œ‡ƒ€}yusrss */ $"6D83 BBB4 ACA6 A0A4 777E 7F81 8288 898D" /* mƒ»´¬¦ ¤w~.‚ˆ‰ */ $"9399 A1A7 ADB2 B9BE C3C7 CBCF D0D2 D2D3" /* “™¡§­²¹¾ÃÇËÏÐÒÒÓ */ $"D581 D60C D5D4 D2D0 CDCC CDCD AA85 8266" /* ÕÖ.ÕÔÒÐÍÌÍͪ…‚f */ $"0E98 000C 3978 818E C7DB D8D4 D1D2 D4D6" /* .˜..9xŽÇÛØÔÑÒÔÖ */ $"D785 D63D D4D4 D3D3 D2D1 D0CF CDC9 C6C2" /* ×…Ö=ÔÔÓÓÒÑÐÏÍÉÆÂ */ $"A2A3 A8AD ACA6 9C94 8D88 8480 7B77 7574" /* ¢£¨­¬¦œ”ˆ„€{wut */ $"7472 6D6C A7B0 A6A1 A470 797A 7C7F 8489" /* trml§°¦¡¤pyz|.„‰ */ $"8E95 9BA2 A7B0 B4B9 BEC4 C8CB CFD0 D1D2" /* Ž•›¢§°´¹¾ÄÈËÏÐÑÒ */ $"D3D5 81D6 0BD5 D3D1 CECD CDCF BE8D 8178" /* ÓÕÖ.ÕÓÑÎÍÍϾx */ $"399B 000C 0860 7F81 A8D8 DBD6 D2D1 D2D4" /* 9›...`.¨ØÛÖÒÑÒÔ */ $"D785 D63B D5D4 D4D3 D3D2 D0D0 CEC9 C0AB" /* ×…Ö;ÕÔÔÓÓÒÐÐÎÉÀ« */ $"A9AE B5B4 AEA4 9C93 8D88 837D 7A78 7774" /* ©®µ´®¤œ“ˆƒ}zxwt */ $"716C 6897 ACA1 A380 7676 7A7D 8388 8E96" /* qlh—¬¡£€vvz}ƒˆŽ– */ $"9AA2 A9B1 B7BC C2C4 C9CD CFD1 D1D3 D3D5" /* 𢩱·¼ÂÄÉÍÏÑÑÓÓÕ */ $"80D6 0CD5 D4D2 CFCD CCCE CCA4 817F 6008" /* €Ö.ÕÔÒÏÍÌÎ̤.`. */ $"9E00 0D2D 7480 8BC1 DCD9 D4D1 D1D3 D6D7" /* ž..-t€‹ÁÜÙÔÑÑÓÖ× */ $"D784 D600 D480 D343 D2D1 CFCB BFA7 B0B5" /* ׄÖ.Ô€ÓCÒÑÏË¿§°µ */ $"BBBC B9B0 A69C 938D 8781 7E7C 7873 6F6A" /* »¼¹°¦œ“‡~|xsoj */ $"6389 A7A0 8F6D 7277 7C80 878C 949B A4AC" /* c‰§ mrw|€‡Œ”›¤¬ */ $"B3B9 BEC2 C7CA CDCF D1D2 D3D3 D5D6 D6D5" /* ³¹¾ÂÇÊÍÏÑÒÓÓÕÖÖÕ */ $"D4D3 D1CE CCCD CFB9 8980 742D A200 0C58" /* ÔÓÑÎÌÍϹ‰€t-¢..X */ $"7E80 A1D6 DDD9 D4D1 D2D5 D8D8 84D7 00D6" /* ~€¡ÖÝÙÔÑÒÕØØ„×.Ö */ $"80D4 2ED3 D1CD C2AA B7BC C1C5 C3BD B4A8" /* €Ô.ÓÑͪ·¼ÁÅý´¨ */ $"9C93 8C87 8481 7A73 6D68 6286 A499 6670" /* œ“Œ‡„zsmhb†¤™fp */ $"747B 8086 8E98 9FA6 AFB4 BCC1 C5C9 CDD0" /* t{€†Ž˜Ÿ¦¯´¼ÁÅÉÍÐ */ $"D2D2 80D4 0ED6 D7D7 D6D5 D3D0 CECE CFCB" /* ÒÒ€Ô.Ö××ÖÕÓÐÎÎÏË */ $"9D80 7E58 A500 0C24 6E7F 86BE DEDA D6D1" /* €~X¥..$n.†¾ÞÚÖÑ */ $"D0D2 D5D7 84D6 42D5 D4D2 D2D1 CDC8 B9BA" /* ÐÒÕׄÖBÕÔÒÒÑÍȹº */ $"C1C8 CCCD C9C1 B4A5 9A93 8E89 827A 736D" /* ÁÈÌÍÉÁ´¥š“މ‚zsm */ $"6864 8DA6 616B 7079 8086 8E98 A1A8 AFB5" /* hd¦akpy€†Ž˜¡¨¯µ */ $"BDC0 C5CA CCCF D1D1 D3D3 D4D6 D6D5 D4D3" /* ½ÀÅÊÌÏÑÑÓÓÔÖÖÕÔÓ */ $"D0CE CCCD CFB4 867F 6E24 A800 0A4D 7A7D" /* ÐÎÌÍÏ´†.n$¨.ÂMz} */ $"9AD4 DDD8 D3CF D0D3 80D7 81D6 40D5 D4D2" /* šÔÝØÓÏÐÓ€×Ö@ÕÔÒ */ $"D1D0 CBC6 BFC0 C7CF D3D7 D5CD C1B1 A69D" /* ÑÐËÆ¿ÀÇÏÓ×ÕÍÁ±¦ */ $"958D 837A 726E 6766 9E66 696E 7983 8892" /* •ƒzrngfžfinyƒˆ’ */ $"9BA2 AAB0 B9BF C2C8 CACE CFD1 D2D3 D3D4" /* ›¢ª°¹¿ÂÈÊÎÏÑÒÓÓÔ */ $"D6D6 D5D4 D1CF CDCD CEC6 977D 7A4D AB00" /* ÖÖÕÔÑÏÍÍÎÆ—}zM«. */ $"501A 697D 81B7 E0DB D7D1 D0D2 D6D8 D7D8" /* P.i}·àÛ×ÑÐÒ֨ר */ $"D7D6 D5D5 D4D1 CFCB C5C0 C7CE D5DC DFDF" /* ×ÖÕÕÔÑÏËÅÀÇÎÕÜßß */ $"DACE C0B5 AA9D 9085 7A72 6D64 7E73 6870" /* ÚÎÀµª…zrmd~shp */ $"7984 8C94 9EA5 AFB5 BDC1 C5CA CDCF D2D2" /* y„Œ”ž¥¯µ½ÁÅÊÍÏÒÒ */ $"D4D4 D6D6 D7D6 D5D4 D1CF CECF D1AE 807D" /* ÔÔÖÖ×ÖÕÔÑÏÎÏÑ®€} */ $"691A AE00 4C46 767C 93D2 E0DA D5D2 D0D3" /* i.®.LFv|“ÒàÚÕÒÐÓ */ $"D7D9 D9D7 D5D4 D4D0 CEC8 C1B9 CED5 DBE1" /* ×ÙÙ×ÕÔÔÐÎÈÁ¹ÎÕÛá */ $"E4E4 E0D9 CEC4 B6A3 9386 7B73 6B6A 7866" /* ääàÙÎĶ£“†{skjxf */ $"7079 858E 97A0 AAB2 B8BD C2C7 CACE D0D2" /* py…Ž— ª²¸½ÂÇÊÎÐÒ */ $"D3D4 D4D6 D7D7 D6D4 D2D0 CECE D0C6 907C" /* ÓÔÔÖ××ÖÔÒÐÎÎÐÆ| */ $"7646 B100 4A0E 627B 7DB0 E1DF DAD3 D1D3" /* vF±.J.b{}°áßÚÓÑÓ */ $"D6D9 D8D7 D5D4 D0CE C8C0 B6A5 DDE2 E6E8" /* ÖÙØ×ÕÔÐÎÈÀ¶¥Ýâæè */ $"E6E4 E0D9 CEBD A897 8A7D 736C 7C64 707D" /* æäàÙν¨—Š}sl|dp} */ $"8791 9AA5 AEB6 BAC1 C6CA CDD0 D3D3 D5D5" /* ‡‘𥮶ºÁÆÊÍÐÓÓÕÕ */ $"D7D7 D8D7 D6D4 D2D0 CFD0 D0A8 7D7B 620E" /* ×ר×ÖÔÒÐÏÐШ}{b. */ $"B400 4639 727A 8CCF E3DE D9D3 D2D4 D6D7" /* ´.F9rzŒÏãÞÙÓÒÔÖ× */ $"D7D6 D1CD C8BF B6AA 99F5 E9E8 E8E7 E4DE" /* ×ÖÑÍÈ¿¶ª™õéèèçäÞ */ $"D2C1 AD9C 8E7F 7674 6272 7F8A 95A1 AAB1" /* ÒÁ­œŽ.vtbr.Š•¡ª± */ $"B9C0 C4C9 CED0 D3D3 D5D6 D6D8 D9D8 D8D6" /* ¹ÀÄÉÎÐÓÓÕÖÖØÙØØÖ */ $"D4D2 D0D1 D3C1 8A7A 7239 B700 4408 5A79" /* ÔÒÐÑÓÁŠzr9·.D.Zy */ $"79A9 E0E3 DED7 D4D3 D4D6 D4D3 CEC8 C0B7" /* y©àãÞ×ÔÓÔÖÔÓÎÈÀ· */ $"A99E 90F6 EDE9 E9E6 DBCE BFAD 9D90 8479" /* ©žöíééæÛο­„y */ $"5F77 848E 9AA3 ADB7 BCC2 C7CC CFD3 D4D6" /* _w„Žš£­·¼ÂÇÌÏÓÔÖ */ $"D6D7 D8D9 DAD9 D8D6 D4D2 D1D3 D0A2 7979" /* ÖרÙÚÙØÖÔÒÑÓТyy */ $"5A08 BA00 402F 6F79 87C9 E8E1 DCD5 D4D3" /* Z.º.@/oy‡ÉèáÜÕÔÓ */ $"D3D2 CFCB C3B7 AD9F 9494 CAF6 EFE3 D5C7" /* ÓÒÏË÷­Ÿ””ÊöïãÕÇ */ $"BBAC A293 6D68 7D89 939D A7B2 B8BF C7CA" /* »¬¢“mh}‰“§²¸¿ÇÊ */ $"CED2 D5D5 D7D8 D8DA DBDA DAD8 D6D4 D3D3" /* ÎÒÕÕרØÚÛÚÚØÖÔÓÓ */ $"D5BD 8579 6F2F BE00 3C54 7678 A2E2 E4DF" /* Õ½…yo/¾. */ $"8986 8A8B 8C8D 8983 7D7A 7A7B 7D7F 8081" /* ‰†Š‹Œ‰ƒ}zz{}.€ */ $"8385 8A90 A4C1 BAB2 AAAF B8B9 B9BB BCBE" /* ƒ…ФÁº²ª¯¸¹¹»¼¾ */ $"BFC1 C1C2 C4C5 C6C7 C9CA CBCC CDCD CFD1" /* ¿ÁÁÂÄÅÆÇÉÊËÌÍÍÏÑ */ $"D2D4 D5D6 D8D9 D9DA DCDE DFE0 E1E2 E5BE" /* ÒÔÕÖØÙÙÚÜÞßàáâå¾ */ $"003F 8889 8D8E 9091 908B 8581 807F 8182" /* .?ˆ‰Ž‘‹…€.‚ */ $"8384 878B 9298 A8B9 B2AB AFB9 B9BA BBBC" /* ƒ„‡‹’˜¨¹²«¯¹¹º»¼ */ $"BEC0 C1C1 C2C4 C5C6 C8C9 CACB CDCD CECF" /* ¾ÀÁÁÂÄÅÆÈÉÊËÍÍÎÏ */ $"D1D2 D3D5 D6D8 D9D9 DBDC DEDF E0E2 E3E3" /* ÑÒÓÕÖØÙÙÛÜÞßàâãã */ $"E5E7 BD00 0A98 898E 9093 9494 918D 8985" /* åç½.˜‰Ž“””‘‰… */ $"8084 3285 878A 9097 9FAE B3AA AEB9 B8B9" /* €„2…‡Š—Ÿ®³ª®¹¸¹ */ $"BBBC BDBF C1C1 C2C4 C5C6 C8C8 C9CB CCCD" /* »¼½¿ÁÁÂÄÅÆÈÈÉËÌÍ */ $"CECF D0D2 D3D4 D6D8 D9D9 DADC DEDE E0E2" /* ÎÏÐÒÓÔÖØÙÙÚÜÞÞàâ */ $"E2E3 E5E6 E6E8 BC00 41AA 8C91 9395 979A" /* âãåææè¼.AªŒ‘“•—š */ $"9995 918C 8887 8788 8B8F 96A0 A7B0 ACAF" /* ™•‘Œˆ‡‡ˆ‹– §°¬¯ */ $"B8B9 B9BB BCBE BFC1 C1C2 C4C5 C6C7 C9CA" /* ¸¹¹»¼¾¿ÁÁÂÄÅÆÇÉÊ */ $"CBCC CDCD CFD1 D2D4 D5D6 D8D9 D9DA DCDE" /* ËÌÍÍÏÑÒÔÕÖØÙÙÚÜÞ */ $"DFE0 E1E3 E4E5 E6E6 E7E8 E6BB 0042 C093" /* ßàáãäåææçèæ».BÀ“ */ $"9396 989C 9F9F 9D99 938E 8B8B 8D91 959D" /* “–˜œŸŸ™“Ž‹‹‘• */ $"A6AE B0AF B9B9 BABB BDBE C0C1 C1C2 C4C5" /* ¦®°¯¹¹º»½¾ÀÁÁÂÄÅ */ $"C6C8 C9CA CBCD CDCE CFD1 D2D4 D5D6 D8D9" /* ÆÈÉÊËÍÍÎÏÑÒÔÕÖØÙ */ $"D9DA DCDE DFE0 E2E3 E4E5 E6E6 E8E8 E7E3" /* ÙÚÜÞßàâãäåææèèçã */ $"E1BA 0043 C9A0 9398 9CA0 A2A3 A39F 9893" /* áº.CÉ “˜œ ¢££Ÿ˜“ */ $"908F 9195 9AA4 ABB1 B1B7 B8B9 BBBC BDBF" /* ‘•𤫱±·¸¹»¼½¿ */ $"C1C1 C2C4 C5C6 C8C8 C9CB CCCD CECF D0D2" /* ÁÁÂÄÅÆÈÈÉËÌÍÎÏÐÒ */ $"D3D5 D6D8 D9D9 DADC DEDF E0E2 E2E3 E5E6" /* ÓÕÖØÙÙÚÜÞßàââãåæ */ $"E6E7 E8E7 E5DF DAD9 BA00 42BF 989C A0A3" /* æçèçåßÚÙº.B¿˜œ £ */ $"A5A7 A7A4 A099 9695 969B A2AA B1B8 B6B8" /* ¥§§¤ ™–•–›¢ª±¸¶¸ */ $"B9BB BCBE BFC1 C1C2 C4C5 C6C7 C9CA CBCC" /* ¹»¼¾¿ÁÁÂÄÅÆÇÉÊËÌ */ $"CDCD CFD1 D2D4 D5D7 D8D9 D9DA DCDE DFE0" /* ÍÍÏÑÒÔÕרÙÙÚÜÞßà */ $"E1E3 E4E5 E6E6 E7E8 E8E5 E0D9 D2D0 BB00" /* áãäåææçèèåàÙÒл. */ $"03B7 9DA2 A681 A930 A5A1 9D9B 9DA3 A8AF" /* .·¢¦©0¥¡›£¨¯ */ $"B9B9 B8BA BBBD BEBF C1C1 C2C4 C5C6 C8C9" /* ¹¹¸º»½¾¿ÁÁÂÄÅÆÈÉ */ $"CACB CDCD CECF D1D2 D4D5 D6D8 D9D9 DADC" /* ÊËÍÍÎÏÑÒÔÕÖØÙÙÚÜ */ $"DEDF E0E2 E3E4 E5E6 E680 E806 E6E1 DBD4" /* Þßàâãäåææ€è.æáÛÔ */ $"CDC7 AABA 0042 D2B0 A3A8 A9AA ABAB A9A6" /* ÍǪº.BÒ°£¨©ª««©¦ */ $"A3A1 A3A8 ADB4 B8B7 BABB BCBE C0C1 C1C2" /* £¡£¨­´¸·º»¼¾ÀÁÁ */ $"C4C5 C6C8 C9CA CBCC CDCE CFD1 D2D3 D5D6" /* ÄÅÆÈÉÊËÌÍÎÏÑÒÓÕÖ */ $"D8D9 D9DB DCDE DFE0 E2E2 E4E5 E6E7 E7E8" /* ØÙÙÛÜÞßàââäåæççè */ $"E9E7 E2DC D7CF C8C1 AABB 0041 C3B3 A8AA" /* éçâÜ×ÏÈÁª».Aó¨ª */ $"ABAC ADAD ABAA A9AA ADB1 B5B7 B9BB BCBE" /* «¬­­«ª©ª­±µ·¹»¼¾ */ $"BFC1 C1C2 C3C5 C6C7 C9C9 CBCC CDCD CFD1" /* ¿ÁÁÂÃÅÆÇÉÉËÌÍÍÏÑ */ $"D2D3 D5D6 D8D9 D9DA DCDD DFE0 E1E3 E4E5" /* ÒÓÕÖØÙÙÚÜÝßàáãäå */ $"E6E6 E7E8 E9E7 E3DD D7D1 C9C2 BCAA BC00" /* ææçèéçãÝ×Ñɼª¼. */ $"04CB BAA9 ACAD 82AF 12B0 B3B5 B7BA BBBC" /* .˺©¬­‚¯.°³µ·º»¼ */ $"BDBF C0C1 C2C4 C5C6 C7C8 CACB 80CD 20CF" /* ½¿ÀÁÂÄÅÆÇÈÊË€Í Ï */ $"D1D2 D4D5 D6D8 D9D9 DADC DEDF E0E1 E2E4" /* ÑÒÔÕÖØÙÙÚÜÞßàáâä */ $"E5E6 E6E7 E8E9 E8E4 DED8 D1CA C3BC B6AA" /* åææçèéèäÞØÑÊü¶ª */ $"BD00 3FD2 BBAB AEB0 B1B2 B2B3 B4B6 B8BA" /* ½.?Ò»«®°±²²³´¶¸º */ $"BBBC BEC0 C1C1 C2C4 C5C6 C8C9 CACB CCCD" /* »¼¾ÀÁÁÂÄÅÆÈÉÊËÌÍ */ $"CECF D1D2 D3D5 D6D8 D9D9 DBDC DEDF E0E2" /* ÎÏÑÒÓÕÖØÙÙÛÜÞßàâ */ $"E3E4 E5E6 E7E7 E8E9 E9E5 E1DA D3CC C5BF" /* ãäåæççèééåáÚÓÌÅ¿ */ $"B7B0 AABE 003E D2BD AEB1 B2B3 B4B5 B6B7" /* ·°ª¾.>Ò½®±²³´µ¶· */ $"B9BB BCBE BFC1 C1C2 C3C5 C6C7 C9C9 CBCC" /* ¹»¼¾¿ÁÁÂÃÅÆÇÉÉËÌ */ $"CDCD CFD0 D2D4 D5D6 D8D9 D9DA DCDE DFE0" /* ÍÍÏÐÒÔÕÖØÙÙÚÜÞßà */ $"E1E3 E4E5 E6E6 E7E8 E9E9 E6E1 DBD4 CCC6" /* áãäåææçèééæáÛÔÌÆ */ $"C0B8 B1AA AABF 0016 D3BF B0B3 B4B6 B7B8" /* À¸±ªª¿..Ó¿°³´¶·¸ */ $"BABB BCBE BFC0 C1C2 C4C5 C6C7 C8CA CB80" /* º»¼¾¿ÀÁÂÄÅÆÇÈÊË€ */ $"CD23 CFD1 D2D4 D5D6 D8D9 D9DA DCDE DFE0" /* Í#ÏÑÒÔÕÖØÙÙÚÜÞßà */ $"E1E2 E4E5 E6E6 E7E8 E9EA E6E2 DBD5 CDC6" /* áâäåææçèéêæâÛÕÍÆ */ $"C0BA B1AA A5AA C000 3CD5 C1B2 B5B7 B8BA" /* Àº±ª¥ªÀ.<ÕÁ²µ·¸º */ $"BBBC BEC0 C1C1 C2C4 C5C6 C8C9 CACB CCCD" /* »¼¾ÀÁÁÂÄÅÆÈÉÊËÌÍ */ $"CECF D1D2 D3D5 D6D8 D9D9 DBDC DEDF E0E2" /* ÎÏÑÒÓÕÖØÙÙÛÜÞßàâ */ $"E3E4 E5E6 E6E8 E8E9 EAE7 E4DE D6D0 C9C2" /* ãäåææèèéêçäÞÖÐÉ */ $"BBB5 ACA6 A0AA C100 3AD5 C2B5 B8B9 BBBC" /* »µ¬¦ ªÁ.:Õµ¸¹»¼ */ $"BDBF C1C1 C2C3 C5C6 C7C9 CACB CCCD CDCF" /* ½¿ÁÁÂÃÅÆÇÉÊËÌÍÍÏ */ $"D0D2 D4D5 D6D8 D9D9 DADC DEDF E0E1 E3E4" /* ÐÒÔÕÖØÙÙÚÜÞßàáãä */ $"E5E6 E6E7 E8E9 EAE8 E3DF D7D0 C9C3 BBB5" /* åææçèéêèãß×ÐÉûµ */ $"AEA7 9FA2 C300 10D7 C5BA BCBC BEBF C1C1" /* ®§Ÿ¢Ã..ן¼¼¾¿ÁÁ */ $"C2C4 C5C6 C7C8 CACB 80CD 25CF D1D2 D4D5" /* ÂÄÅÆÇÈÊË€Í%ÏÑÒÔÕ */ $"D6D8 D9D9 DADC DEDF E0E1 E2E4 E5E6 E6E7" /* ÖØÙÙÚÜÞßàáâäåææç */ $"E8E9 EAE9 E5DF D9D1 C9C4 BDB5 AEA8 9FA0" /* èéêéåßÙÑÉĽµ®¨Ÿ  */ $"C2C4 0037 D8C9 C0BE C0C1 C1C2 C4C5 C6C8" /* ÂÄ.7ØÉÀ¾ÀÁÁÂÄÅÆÈ */ $"C9CA CBCD CDCE CFD1 D2D3 D5D6 D8D9 D9DB" /* ÉÊËÍÍÎÏÑÒÓÕÖØÙÙÛ */ $"DCDE DFE0 E2E3 E4E5 E6E6 E8E8 E9EA EAE6" /* ÜÞßàâãäåææèèéêêæ */ $"E1DA D4CC C5BF B8B0 A9A2 9AC7 C500 36FD" /* áÚÔÌÅ¿¸°©¢šÇÅ.6ý */ $"DECC C7C2 C1C2 C4C5 C6C7 C8C9 CBCC CDCE" /* ÞÌÇÂÁÂÄÅÆÇÈÉËÌÍÎ */ $"CFD1 D2D3 D4D6 D8D9 D9DA DCDE DEE0 E2E2" /* ÏÑÒÓÔÖØÙÙÚÜÞÞàââ */ $"E3E5 E6E6 E7E8 E9EA EAE7 E3DC D4CD C7BF" /* ãåææçèéêêçãÜÔÍÇ¿ */ $"BAB2 AAA5 99BB C400 37FD FDFF BFBD CCC9" /* º²ª¥™»Ä.7ýýÿ¿½ÌÉ */ $"C2C4 C5C6 C7C9 CACB CCCD CDCF D1D2 D4D5" /* ÂÄÅÆÇÉÊËÌÍÍÏÑÒÔÕ */ $"D6D8 D9D9 DADC DEDF E0E1 E3E4 E5E6 E6E7" /* ÖØÙÙÚÜÞßàáãäåææç */ $"E8E9 EAEA E7E3 DDD6 CDC8 C1B9 B2AB A49A" /* èéêêçãÝÖÍÈÁ¹²«¤š */ $"B0C4 0038 FDAA AABC C5C9 C8D0 CEC6 C6C8" /* °Ä.8ýªª¼ÅÉÈÐÎÆÆÈ */ $"C9CA CBCD CDCE CFD1 D2D3 D5D6 D8D9 D9DA" /* ÉÊËÍÍÎÏÑÒÓÕÖØÙÙÚ */ $"DCDE DFE0 E2E3 E4E5 E6E6 E8E8 E9EA EAE9" /* ÜÞßàâãäåææèèéêêé */ $"E4DE D8D0 C8C3 BBB4 ADA6 9CA6 E4C2 000B" /* äÞØÐÈû´­¦œ¦äÂ.. */ $"FD7F 7FBE C6CA C9C9 C8C7 D1D2 80C9 1ACB" /* ý..¾ÆÊÉÉÈÇÑÒ€É.Ë */ $"CCCD CECF D0D2 D3D4 D6D8 D9D9 DADC DEDF" /* ÌÍÎÏÐÒÓÔÖØÙÙÚÜÞß */ $"E0E2 E2E3 E5E6 E6E7 E8E9 80EA 0CE6 DFD8" /* àââãåææçèé€ê.æßØ */ $"D1CA C3BD B5AE A89F 9EDA C100 3AFD 7F7F" /* ÑÊýµ®¨ŸžÚÁ.:ý.. */ $"C4C8 CBCA CAC9 C9C8 C7C5 D2D5 CBCB CCCD" /* ÄÈËÊÊÉÉÈÇÅÒÕËËÌÍ */ $"CDCF D1D2 D4D5 D6D8 D9D9 DADC DEDF E0E1" /* ÍÏÑÒÔÕÖØÙÙÚÜÞßàá */ $"E3E4 E5E6 E6E7 E8E9 EAEB E9E6 E0D8 D2CB" /* ãäåææçèéêëéæàØÒË */ $"C4BD B7AF A8A0 9EC5 C000 3DFD 7F7F C8CA" /* Ľ·¯¨ žÅÀ.=ý..ÈÊ */ $"CCCC CBCB CAC9 C8C7 C5C4 C2D5 DACD CDCE" /* ÌÌËËÊÉÈÇÅÄÂÕÚÍÍÎ */ $"CFD1 D2D4 D5D6 D8D9 D9DA DCDE DFE0 E2E3" /* ÏÑÒÔÕÖØÙÙÚÜÞßàâã */ $"E4E5 E6E6 E8E8 E9EA EBEB E7E1 DAD3 CCC6" /* äåææèèéêëëçáÚÓÌÆ */ $"BFB7 B1A9 A298 CACB C6BE 003B 7F8E C8CB" /* ¿·±©¢˜ÊËÆ¾.;.ŽÈË */ $"CDCD CCCB CACA C8C7 C7C5 C4C1 C0BE D5DD" /* ÍÍÌËÊÊÈÇÇÅÄÁÀ¾ÕÝ */ $"D0CF D0D2 D3D5 D6D8 D9D9 DADC DEDF E0E2" /* ÐÏÐÒÓÕÖØÙÙÚÜÞßàâ */ $"E2E3 E5E6 E6E7 E8E9 EAEB EBE8 E2DC D5CD" /* âãåææçèéêëëèâÜÕÍ */ $"C6C1 B9B1 ABA5 99C0 80CE 02CC C880 BA00" /* ÆÁ¹±«¥™À€Î.ÌÈ€º. */ $"01AA CC80 CE36 CDCD CCCC CBCA C8C7 C6C4" /* .ªÌ€Î6ÍÍÌÌËÊÈÇÆÄ */ $"C2C0 BEBC BAD5 DFD1 D2D4 D5D7 D8D9 D9DA" /* ÂÀ¾¼ºÕßÑÒÔÕרÙÙÚ */ $"DCDE DFE0 E1E3 E4E5 E6E6 E7E8 E9EA EBEB" /* ÜÞßàáãäåææçèéêëë */ $"E9E3 DCD6 CFC7 C0BB B3AB A59C BC83 D002" /* éãÜÖÏÇÀ»³«¥œ¼ƒÐ. */ $"CECB ABB6 0002 B8CB CF80 CE36 CDCC CCCB" /* ÎË«¶..¸ËÏ€Î6ÍÌÌË */ $"CAC9 C7C6 C4C2 C1BF BCBB B9B7 B5DA E3D4" /* ÊÉÇÆÄÂÁ¿¼»¹·µÚãÔ */ $"D5D6 D8D9 D9DA DCDE DFE0 E2E3 E4E5 E6E6" /* ÕÖØÙÙÚÜÞßàâãäåææ */ $"E8E8 E9EA EBEB E9E5 DFD7 D0C9 C2BB B5AD" /* èèéêëëéåß×ÐÉ»µ­ */ $"A69D AB80 CF80 D081 CF01 CBB8 B200 03C1" /* ¦«€Ï€ÐÏ.˸²..Á */ $"CDD0 D080 CF38 CECC CBCA C9C8 C6C4 C3C1" /* ÍÐЀÏ8ÎÌËÊÉÈÆÄÃÁ */ $"BFBD BBBB B8B7 B5B4 B3D8 EBD6 D8D9 D9DB" /* ¿½»»¸·µ´³ØëÖØÙÙÛ */ $"DCDE DFE0 E2E2 E4E5 E6E7 E7E8 E9EA EBEB" /* ÜÞßàââäåæççèéêëë */ $"EAE6 E0DA D1CA C4BD B6AF A8A0 9ACF CF86" /* êæàÚÑÊĽ¶¯¨ šÏφ */ $"D003 D1D1 CDC1 AE00 04C7 D0D3 D2D2 80D1" /* Ð.ÑÑÍÁ®..ÇÐÓÒÒ€Ñ */ $"37CF CECD CCCB C9C7 C6C4 C2C0 BEBC BAB9" /* 7ÏÎÍÌËÉÇÆÄÂÀ¾¼º¹ */ $"B7B6 B4B3 B4B4 CBED D9D9 DADC DDDF E0E1" /* ·¶´³´´ËíÙÙÚÜÝßàá */ $"E3E4 E5E6 E6E7 E8E9 EAEA EBEB E7E0 DAD3" /* ãäåææçèéêêëëçàÚÓ */ $"CBC5 BFB7 AFA9 A29A CC81 D085 D280 D301" /* ËÅ¿·¯©¢šÌÐ…Ò€Ó. */ $"D0C7 AA00 01C8 D280 D43E D3D3 D2D1 D0CF" /* ÐǪ..ÈÒ€Ô>ÓÓÒÑÐÏ */ $"CECD CBCA C8C5 C3C2 C0BE BCBB B9B8 B6B5" /* ÎÍËÊÈÅÃÂÀ¾¼»¹¸¶µ */ $"B4B4 B3B2 B2C9 F0DA DCDE DFE0 E1E2 E4E5" /* ´´³²²ÉðÚÜÞßàáâäå */ $"E6E6 E7E8 E9EA EAEC EBE8 E2DA D3CC C5BF" /* ææçèéêêìëèâÚÓÌÅ¿ */ $"B8B0 A9A3 9ACA CFD0 D081 D100 D283 D381" /* ¸°©£šÊÏÐÐÑ.ÒƒÓ */ $"D401 D2C8 A600 01CE D382 D516 D4D3 D3D2" /* Ô.ÒȦ..ÎÓ‚Õ.ÔÓÓÒ */ $"D1CE CDCB C9C6 C4C2 C0BD BCBB B9B8 B6B5" /* ÑÎÍËÉÆÄÂÀ½¼»¹¸¶µ */ $"B4B4 B582 B428 CBF2 DDDF E0E2 E3E4 E5E6" /* ´´µ‚´(ËòÝßàâãäåæ */ $"E6E8 E8E9 EAEB ECEC E8E4 DDD5 CFC8 C1B9" /* æèèéêëììèäÝÕÏÈÁ¹ */ $"B3AB A59A B7CD CECF CFD0 D0D1 D1D2 D382" /* ³«¥š·ÍÎÏÏÐÐÑÑÒÓ‚ */ $"D483 D501 D3CE A100 029F CED3 84D4 11D3" /* ÔƒÕ.ÓΡ..ŸÎÓ„Ô.Ó */ $"D2D1 D0CF CECB C8C5 C3C0 BCBA B7B7 B5B4" /* ÒÑÐÏÎËÈÅÃÀ¼º··µ´ */ $"B382 B101 B2B2 80B1 2AB2 CBF0 E0E1 E3E4" /* ³‚±.²²€±*²Ëðàáãä */ $"E5E6 E6E7 E8E9 EAEA EBEC EAE3 DED6 CEC8" /* åææçèéêêëìêãÞÖÎÈ */ $"C2BB B3AD A69D A7C8 C8C9 CACA CCCD CED0" /* »³­¦§ÈÈÉÊÊÌÍÎÐ */ $"D0D1 D2D2 81D3 84D4 02D3 CE9F 9C00 02B8" /* ÐÑÒÒÓ„Ô.ÓΟœ..¸ */ $"D0D4 85D5 48D4 D4D3 D2D1 CFCD CAC7 C4C1" /* ÐÔ…ÕHÔÔÓÒÑÏÍÊÇÄÁ */ $"BCBA B7B5 B3B2 B2B1 B0B1 B1B0 B0B1 B0B1" /* ¼º·µ³²²±°±±°°±°± */ $"B1B0 B1B0 D1F2 E3E4 E5E6 E6E7 E8E9 EAEA" /* ±°±°Ñòãäåææçèéêê */ $"EBEC EAE5 DED7 D0C8 C2BC B4AD A79E A1C1" /* ëìêåÞ×Ðȼ´­§ž¡Á */ $"C1C3 C6C6 C7C9 CACC CED0 D1D1 D3D3 80D4" /* ÁÃÆÆÇÉÊÌÎÐÑÑÓÓ€Ô */ $"86D5 02D4 D0B8 9800 01C3 D188 D547 D4D3" /* †Õ.Ôи˜..ÃшÕGÔÓ */ $"D2D2 D1CE CBC9 C5C2 BDBA B7B4 B2B0 AFAD" /* ÒÒÑÎËÉŽº·´²°¯­ */ $"ADAC ADAD AFAE B0AF AEAE ACB0 977C CFEB" /* ­¬­­¯®°¯®®¬°—|Ïë */ $"E5E6 E6E8 E8E9 EAEA ECEC EBE6 E0D9 D2CB" /* åææèèéêêììëæàÙÒË */ $"C3BD B7AF A8A1 9CBD BABD BDBF C1C3 C4C7" /* ý·¯¨¡œ½º½½¿ÁÃÄÇ */ $"C8CA CDD0 D0D1 80D3 00D4 89D5 01D1 C394" /* ÈÊÍÐÐÑ€Ó.Ô‰Õ.ÑÔ */ $"0001 C7D1 8AD5 15D4 D3D2 D2D1 CECB C9C5" /* ..ÇÑŠÕ.ÔÓÒÒÑÎËÉÅ */ $"C0BD B9B5 B2B0 AEAD ACAB AAAC AB80 AA0F" /* À½¹µ²°®­¬«ª¬«€ª. */ $"ABAA ABAD A573 7073 C4EC E7E7 E8E9 EAEA" /* «ª«­¥spsÄìççèéêê */ $"80EC 1FE7 E2DA D3CC C6BE B8B1 A9A3 99B6" /* €ì.çâÚÓÌÆ¾¸±©£™¶ */ $"B2B3 B5B7 B8BA BCBE C3C4 C7CB CDD0 D1D2" /* ²³µ·¸º¼¾ÃÄÇËÍÐÑÒ */ $"D3D3 D48B D501 D1C7 9000 02CC D3D7 8CD6" /* ÓÓÔ‹Õ.ÑÇ..ÌÓ×ŒÖ */ $"14D5 D4D3 D2CF CDCB C7C1 BFBA B7B3 B1AF" /* .ÕÔÓÒÏÍËÇÁ¿º·³±¯ */ $"ADAC ABAB AAAB 80AA 32AB A9AB A174 766F" /* ­¬««ª«€ª2«©«¡tvo */ $"6D73 C2EF E8E9 EAEA EBEC ECE8 E2DC D4CD" /* msÂïèéêêëììèâÜÔÍ */ $"C6C0 B8B1 ABA4 9AAE ABAD AEAE AFB2 B5B8" /* ÆÀ¸±«¤š®«­®®¯²µ¸ */ $"BBBE C3C6 C9CC D0D2 D3D4 D4D5 8DD6 01D3" /* »¾ÃÆÉÌÐÒÓÔÔÕÖ.Ó */ $"CC8C 0003 CDD1 D3D3 8CD5 16D4 D4D3 D2D1" /* ÌŒ..ÍÑÓÓŒÕ.ÔÔÓÒÑ */ $"CFCD CAC7 C3BF BAB8 B3B0 AEAC AAA9 A8A7" /* ÏÍÊÇÿº¸³°®¬ª©¨§ */ $"A6A6 80A5 31A6 A478 7A6F 6F71 6E76 C7F0" /* ¦¦€¥1¦¤xzooqnvÇð */ $"EAEA EBEC ECE9 E3DC D6CF C7C1 BAB2 ABA5" /* êêëììéãÜÖÏÇÁº²«¥ */ $"9BA7 A6A3 A5A5 A6A8 A9AA AFB5 B8BD C1C6" /* ›§¦£¥¥¦¨©ª¯µ¸½ÁÆ */ $"C9CE D0D2 D3D3 D48A D506 D4D4 D3D3 D4D2" /* ÉÎÐÒÓÓÔŠÕ.ÔÔÓÓÔÒ */ $"CD89 0005 B3D3 D6D4 D3D3 8BD5 25D4 D4D3" /* ͉..³ÓÖÔÓÓ‹Õ%ÔÔÓ */ $"D2D1 D0CE CBC9 C5C1 BEBA B6B4 B1AE ABA9" /* ÒÑÐÎËÉÅÁ¾º¶´±®«© */ $"A7A6 A3A3 A4A4 A1A4 7C7E 7270 7071 726E" /* §¦££¤¤¡¤|~rppqrn */ $"76C7 F180 EC22 EAE5 DED6 D0C9 C2BB B4AD" /* vÇñ€ì"êåÞÖÐÉ»´­ */ $"A69F A2A2 9E9D 9C9E A0A0 A1A6 ABAE B4BB" /* ¦Ÿ¢¢žœž  ¡¦«®´» */ $"BFC5 C9CC D0D2 D3D3 D489 D508 D4D3 D1D0" /* ¿ÅÉÌÐÒÓÓÔ‰Õ.ÔÓÑÐ */ $"D1D3 D4D1 B388 000A 7893 C1D8 D7D5 D4D4" /* ÑÓÔѳˆ.Âx“ÁØ×ÕÔÔ */ $"D5D7 D787 D615 D5D4 D4D3 D2D1 CFCC C9C6" /* Õ×ׇÖ.ÕÔÔÓÒÑÏÌÉÆ */ $"C2BF BDB9 B6B3 AEAD ABA8 A6A4 80A3 0381" /* ¿½¹¶³®­«¨¦¤€£. */ $"8578 7480 722A 7172 6E73 C5F4 EDEA E5DF" /* …xt€r*qrnsÅôíêåß */ $"D8D0 CAC3 BCB5 ADA7 9F9F A09B 9B98 9899" /* ØÐÊüµ­§ŸŸ ››˜˜™ */ $"9A9D A0A3 AAAF B4BB C0C5 CACD D1D3 D3D4" /* š £ª¯´»ÀÅÊÍÑÓÓÔ */ $"D588 D609 D5D3 D1CF CED0 D3BF 9378 8800" /* ÕˆÖÆÕÓÑÏÎÐÓ¿“xˆ. */ $"0C6B 898B A5D1 D7D6 D3D3 D4D6 D6D7 85D6" /* .k‰‹¥Ñ×ÖÓÓÔÖÖ×…Ö */ $"4AD5 D5D4 D4D2 D2D1 CECC CAC7 C3C1 BEBA" /* JÕÕÔÔÒÒÑÎÌÊÇÃÁ¾º */ $"B7B3 B0AC ABA7 A5A5 A387 9084 7B77 7675" /* ·³°¬«§¥¥£‡„{wvu */ $"7473 7272 6E76 C8F2 E6E0 DAD2 CBC4 BEB6" /* tsrrnvÈòæàÚÒËľ¶ */ $"B0A8 A1A9 9097 9594 9394 9597 999C A1A6" /* °¨¡©—•”“”•—™œ¡¦ */ $"ADB4 BAC0 C5CB CDD2 D2D3 D4D5 86D6 0BD5" /* ­´ºÀÅËÍÒÒÓÔÕ†Ö.Õ */ $"D4D2 CFCD CCCE CBA3 8B89 6B89 000B 2878" /* ÔÒÏÍÌÎË£‹‰k‰..(x */ $"898D BBD7 D6D4 D2D2 D4D6 86D5 1FD4 D4D3" /* ‰»×ÖÔÒÒÔÖ†Õ.ÔÔÓ */ $"D3D1 D1CF CECC CAC7 C3C1 BEBB B7B3 AEAC" /* ÓÑÑÏÎÌÊÇÃÁ¾»·³®¬ */ $"A9A6 A491 8D91 867E 7B79 7775 7480 7326" /* ©¦¤‘‘†~{ywut€s& */ $"6F78 C8E6 DBD5 CDC5 C0B9 B0AA A3A6 8D8F" /* oxÈæÛÕÍÅÀ¹°ª£¦ */ $"9090 8D8E 8F91 9497 9C9F A6AE B5BB C0C6" /* Ž‘”—œŸ¦®µ»ÀÆ */ $"CACF D1D1 D3D3 D484 D50C D4D3 D2CF CDCB" /* ÊÏÑÑÓÓÔ„Õ.ÔÓÒÏÍË */ $"CCCE B68D 8978 288C 0006 5183 879C CFD8" /* Ìζ‰x(Œ..Qƒ‡œÏØ */ $"D580 D201 D4D6 85D5 47D4 D3D2 D2D1 D1D0" /* Õ€Ò.ÔÖ…ÕGÔÓÒÒÑÑÐ */ $"CECD CBC8 C6C3 C0BC B9B4 B0AE A99C 8C9B" /* ÎÍËÈÆÃÀ¼¹´°®©œŒ› */ $"928B 8480 7D7A 7876 7574 7373 6F77 C4D9" /* ’‹„€}zxvutssowÄÙ */ $"CEC7 BFB9 B2AA A4A5 8A8A 898A 8889 8A8D" /* ÎÇ¿¹²ª¤¥ŠŠ‰Šˆ‰Š */ $"9095 9B9E A3AB B0B7 BDC3 C8CC CFD1 D2D3" /* •›ž£«°·½ÃÈÌÏÑÒÓ */ $"D484 D50B D4D3 D0CE CCCB CDC7 9B87 8351" /* Ô„Õ.ÔÓÐÎÌËÍÇ›‡ƒQ */ $"8F00 0D16 6F86 89B4 D6D6 D3D1 D1D4 D5D6" /* ...o†‰´ÖÖÓÑÑÔÕÖ */ $"D684 D545 D3D3 D2D2 D1D0 D0CE CCCA C7C4" /* Ö„ÕEÓÓÒÒÑÐÐÎÌÊÇÄ */ $"C1BE BAB5 B2AE 8AA5 9B98 918A 8580 7D7B" /* Á¾ºµ²®Š¥›˜‘Š…€}{ */ $"7977 7574 7372 6F8D CFC9 C1BA B3AC A5A2" /* ywutsroÏÉÁº³¬¥¢ */ $"9886 8586 8788 898B 8E92 989F A3AB B0B7" /* ˜†…†‡ˆ‰‹Ž’˜Ÿ£«°· */ $"BCC2 C6CA CED0 D1D2 D3D4 82D5 0CD4 D3D1" /* ¼ÂÆÊÎÐÑÒÓÔ‚Õ.ÔÓÑ */ $"CFCC CBCC CDAF 8986 6F16 9200 0C44 7E84" /* ÏÌËÌͯ‰†o.’..D~„ */ $"95CA DAD7 D5D2 D3D5 D8D7 84D6 43D5 D4D4" /* •ÊÚ×ÕÒÓըׄÖCÕÔÔ */ $"D3D2 D2D1 D1CF CCCA C6C3 C2BD B7A8 A29F" /* ÓÒÒÑÑÏÌÊÆÃ½·¨¢Ÿ */ $"A09E 988F 8984 817E 7B79 7774 7373 7472" /*  ž˜‰„~{ywtsstr */ $"ABC7 BCB5 AEA7 A0AA 7D82 8384 8988 8C8F" /* «Ç¼µ®§ ª}‚ƒ„‰ˆŒ */ $"9499 9EA5 ADB2 B8BD C3C6 CACF D1D2 D3D3" /* ”™ž¥­²¸½ÃÆÊÏÑÒÓÓ */ $"D582 D60B D5D3 D1CF CDCD CEC3 9484 7E44" /* Õ‚Ö.ÕÓÑÏÍÍÎÔ„~D */ $"9500 0D0E 6682 85AF D8D9 D6D2 D2D3 D6D7" /* •...f‚…¯ØÙÖÒÒÓÖ× */ $"D784 D640 D4D4 D3D3 D2D2 D0CF CDCA C9C5" /* ׄÖ@ÔÔÓÓÒÒÐÏÍÊÉÅ */ $"C3BF 99A8 A3A7 A69F 958E 8985 827E 7A77" /* ÿ™¨£§¦Ÿ•މ…‚~zw */ $"7473 7475 6E84 BEB7 AEA8 A2A6 777E 7F81" /* tstun„¾·®¨¢¦w~. */ $"8288 898D 9399 A1A7 ADB2 B9BE C3C7 CBCF" /* ‚ˆ‰“™¡§­²¹¾ÃÇËÏ */ $"D0D2 D2D3 D581 D60C D5D4 D2D0 CDCC CDCD" /* ÐÒÒÓÕÖ.ÕÔÒÐÍÌÍÍ */ $"AA85 8266 0E98 000C 3978 818E C7DB D8D4" /* ª…‚f.˜..9xŽÇÛØÔ */ $"D1D2 D4D6 D785 D619 D4D4 D3D3 D2D1 D0CF" /* ÑÒÔÖ×…Ö.ÔÔÓÓÒÑÐÏ */ $"CDC9 C6C2 A3A5 AAB0 AEA8 9E96 8F8A 8682" /* ÍÉÆÂ£¥ª°®¨ž–І‚ */ $"7D79 8076 2074 6F6E AAB2 A8A3 A571 797A" /* }y€v tonª²¨£¥qyz */ $"7C7F 8489 8E95 9BA2 A7B0 B4B9 BEC4 C8CB" /* |.„‰Ž•›¢§°´¹¾ÄÈË */ $"CFD0 D1D2 D3D5 81D6 0BD5 D3D1 CECD CDCF" /* ÏÐÑÒÓÕÖ.ÕÓÑÎÍÍÏ */ $"BE8D 8178 399B 000C 0860 7F81 A8D8 DBD6" /* ¾x9›...`.¨ØÛÖ */ $"D2D1 D2D4 D785 D63B D5D4 D4D3 D3D2 D0D0" /* ÒÑÒÔ×…Ö;ÕÔÔÓÓÒÐÐ */ $"CEC9 C0AD ABB1 B6B6 B1A7 9E95 8F89 857F" /* ÎÉÀ­«±¶¶±§ž•‰…. */ $"7B7A 7876 736D 6999 AFA3 A581 7676 7A7D" /* {zxvsmi™¯£¥vvz} */ $"8388 8E96 9AA2 A9B1 B7BC C2C4 C9CD CFD1" /* ƒˆŽ–𢩱·¼ÂÄÉÍÏÑ */ $"D1D3 D3D5 80D6 0CD5 D4D2 CFCD CCCE CCA4" /* ÑÓÓÕ€Ö.ÕÔÒÏÍÌÎ̤ */ $"817F 6008 9E00 0D2D 7480 8BC1 DCD9 D4D1" /* .`.ž..-t€‹ÁÜÙÔÑ */ $"D1D3 D6D7 D784 D600 D480 D343 D2D1 CFCB" /* ÑÓÖ×ׄÖ.Ô€ÓCÒÑÏË */ $"BFA9 B2B7 BDBE BBB2 A89E 958F 8883 807E" /* ¿©²·½¾»²¨ž•ˆƒ€~ */ $"7A76 706B 648B A9A2 906D 7277 7C80 878C" /* zvpkd‹©¢mrw|€‡Œ */ $"949B A4AC B3B9 BEC2 C7CA CDCF D1D2 D3D3" /* ”›¤¬³¹¾ÂÇÊÍÏÑÒÓÓ */ $"D5D6 D6D5 D4D3 D1CE CCCD CFB9 8980 742D" /* ÕÖÖÕÔÓÑÎÌÍϹ‰€t- */ $"A200 0C58 7E80 A1D6 DDD9 D4D1 D2D5 D8D8" /* ¢..X~€¡ÖÝÙÔÑÒÕØØ */ $"84D7 00D6 80D4 2ED3 D1CD C2AC B9BE C3C8" /* „×.Ö€Ô.ÓÑͬ¹¾ÃÈ */ $"C6C0 B6AA 9E95 8E89 8682 7C74 6F6A 6387" /* ÆÀ¶ªž•މ†‚|tojc‡ */ $"A69B 6670 747B 8086 8E98 9FA6 AFB4 BCC1" /* ¦›fpt{€†Ž˜Ÿ¦¯´¼Á */ $"C5C9 CDD0 D2D2 80D4 0ED6 D7D7 D6D5 D3D0" /* ÅÉÍÐÒÒ€Ô.Ö××ÖÕÓÐ */ $"CECE CFCB 9D80 7E58 A500 0C24 6E7F 86BE" /* ÎÎÏË€~X¥..$n.†¾ */ $"DEDA D6D1 D0D2 D5D7 84D6 42D5 D4D2 D2D1" /* ÞÚÖÑÐÒÕׄÖBÕÔÒÒÑ */ $"CDC8 BBBD C4CA CFD1 CCC3 B6A7 9C95 908B" /* ÍÈ»½ÄÊÏÑÌö§œ•‹ */ $"847C 746F 6A65 8FA7 616B 7079 8086 8E98" /* „|toje§akpy€†Ž˜ */ $"A1A8 AFB5 BDC0 C5CA CCCF D1D1 D3D3 D4D6" /* ¡¨¯µ½ÀÅÊÌÏÑÑÓÓÔÖ */ $"D6D5 D4D3 D0CE CCCD CFB4 867F 6E24 A800" /* ÖÕÔÓÐÎÌÍÏ´†.n$¨. */ $"0A4D 7A7D 9AD4 DDD8 D3CF D0D3 80D7 81D6" /* ÂMz}šÔÝØÓÏÐÓ€×Ö */ $"40D5 D4D2 D1D0 CBC6 C1C2 CAD1 D6D9 D8D0" /* @ÕÔÒÑÐËÆÁÂÊÑÖÙØÐ */ $"C3B3 A89F 978F 857B 746F 6868 A067 696E" /* 󨟗…{tohh gin */ $"7983 8892 9BA2 AAB0 B9BF C2C8 CACE CFD1" /* yƒˆ’›¢ª°¹¿ÂÈÊÎÏÑ */ $"D2D3 D3D4 D6D6 D5D4 D1CF CDCD CEC6 977D" /* ÒÓÓÔÖÖÕÔÑÏÍÍÎÆ—} */ $"7A4D AB00 501A 697D 81B7 E0DB D7D1 D0D2" /* zM«.P.i}·àÛ×ÑÐÒ */ $"D6D8 D7D8 D7D6 D5D5 D4D1 CFCB C5C1 C9D0" /* ֨ר×ÖÕÕÔÑÏËÅÁÉÐ */ $"D8DE E1E2 DDD1 C3B7 AD9F 9186 7B74 6E65" /* ØÞáâÝÑ÷­Ÿ‘†{tne */ $"8074 6870 7984 8C94 9EA5 AFB5 BDC1 C5CA" /* €thpy„Œ”ž¥¯µ½ÁÅÊ */ $"CDCF D2D2 D4D4 D6D6 D7D6 D5D4 D1CF CECF" /* ÍÏÒÒÔÔÖÖ×ÖÕÔÑÏÎÏ */ $"D1AE 807D 691A AE00 4C46 767C 93D2 E0DA" /* Ñ®€}i.®.LFv|“ÒàÚ */ $"D5D2 D0D3 D7D9 D9D7 D5D4 D4D0 CEC8 C1B9" /* ÕÒÐÓ×ÙÙ×ÕÔÔÐÎÈÁ¹ */ $"D0D7 DEE4 E7E7 E3DB D1C6 B8A5 9588 7C74" /* Ð×ÞäççãÛÑÆ¸¥•ˆ|t */ $"6D6B 7A66 7079 858E 97A0 AAB2 B8BD C2C7" /* mkzfpy…Ž— ª²¸½ÂÇ */ $"CACE D0D2 D3D4 D4D6 D7D7 D6D4 D2D0 CECE" /* ÊÎÐÒÓÔÔÖ××ÖÔÒÐÎÎ */ $"D0C6 907C 7646 B100 4A0E 627B 7DB0 E1DF" /* ÐÆ|vF±.J.b{}°áß */ $"DAD3 D1D3 D6D9 D8D7 D5D4 D0CE C8C0 B6A6" /* ÚÓÑÓÖÙØ×ÕÔÐÎÈÀ¶¦ */ $"DFE5 E8EB E9E7 E3DC D1C0 AB99 8C7F 756D" /* ßåèëéçãÜÑÀ«™Œ.um */ $"7D64 707D 8791 9AA5 AEB6 BAC1 C6CA CDD0" /* }dp}‡‘𥮶ºÁÆÊÍÐ */ $"D3D3 D5D5 D7D7 D8D7 D6D4 D2D0 CFD0 D0A8" /* ÓÓÕÕ×ר×ÖÔÒÐÏÐШ */ $"7D7B 620E B400 4639 727A 8CCF E3DE D9D3" /* }{b.´.F9rzŒÏãÞÙÓ */ $"D2D4 D6D7 D7D6 D1CD C8BF B6AA 9AF8 ECEB" /* ÒÔÖ××ÖÑÍÈ¿¶ªšøìë */ $"EBEA E7E1 D4C3 AF9E 9080 7776 6372 7F8A" /* ëêçáÔwvcr.Š */ $"95A1 AAB1 B9C0 C4C9 CED0 D3D3 D5D6 D6D8" /* •¡ª±¹ÀÄÉÎÐÓÓÕÖÖØ */ $"D9D8 D8D6 D4D2 D0D1 D3C1 8A7A 7239 B700" /* ÙØØÖÔÒÐÑÓÁŠzr9·. */ $"4408 5A79 79A9 E0E3 DED7 D4D3 D4D6 D4D3" /* D.Zyy©àãÞ×ÔÓÔÖÔÓ */ $"CEC8 C0B7 A99E 91FA F0EC ECE9 DDD1 C1AF" /* ÎÈÀ·©ž‘úðììéÝÑÁ¯ */ $"A092 857B 6077 848E 9AA3 ADB7 BCC2 C7CC" /*  ’…{`w„Žš£­·¼ÂÇÌ */ $"CFD3 D4D6 D6D7 D8D9 DAD9 D8D6 D4D2 D1D3" /* ÏÓÔÖÖרÙÚÙØÖÔÒÑÓ */ $"D0A2 7979 5A08 BA00 402F 6F79 87C9 E8E1" /* ТyyZ.º.@/oy‡Éèá */ $"DCD5 D4D3 D3D2 CFCB C3B7 AD9F 9495 CCF9" /* ÜÕÔÓÓÒÏË÷­Ÿ”•Ìù */ $"F2E6 D8C9 BDAE A495 6E68 7D89 939D A7B2" /* òæØÉ½®¤•nh}‰“§² */ $"B8BF C7CA CED2 D5D5 D7D8 D8DA DBDA DAD8" /* ¸¿ÇÊÎÒÕÕרØÚÛÚÚØ */ $"D6D4 D3D3 D5BD 8579 6F2F BE00 3C54 7678" /* ÖÔÓÓÕ½…yo/¾.Kž÷ÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"F79E 4B3E 2E1E 1108 0401 0000 0000 0000" /* ÷žK>............ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0102" /* ................ */ $"050C 1625 3544 65CE FFFF FFFF FFFF FFFF" /* ...%5DeÎÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFCE" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÎ */ $"6544 3525 160C 0502 0100 0000 0000 0000" /* eD5%............ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0103 0810 1D2C 3C4A 92F3 FFFF FFFF FFFF" /* .....,L£úÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FAA2 4B3E 2F1F 1209 0401 0000 0000" /* ÿÿú¢K>/..Æ...... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0102 050C" /* ................ */ $"1725 3546 66D1 FFFF FFFF FFFF FFFF FFFF" /* .%5FfÑÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFD1 6545 3525 170C 0502 0100 0000 0000" /* ÿÑeE5%.......... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0103" /* ................ */ $"0810 1D2D 3D4A 92F6 FFFF FFFF FFFF FFFF" /* ...-=J’öÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFF6" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿö */ $"924A 3D2D 1D10 0803 0100 0000 0000 0000" /* ’J=-............ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0205 0B16 2434 435F C5FF FFFF FFFF FFFF" /* ....$4C_Åÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF C55F" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅ_ */ $"4334 2416 0B05 0200 0000 0000 0000 0000" /* C4$............. */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0001 0307 0F1B 2B3B 4988 EEFF FFFF FFFF" /* ......+;Iˆîÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF EE88 493B" /* ÿÿÿÿÿÿÿÿÿÿÿÿîˆI; */ $"2B1B 0F07 0301 0000 0000 0000 0000 0000" /* +............... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0001 040A 1422 3241 58BB FFFF FFFF" /* .....Â."2AX»ÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFBB 5841 3222" /* ÿÿÿÿÿÿÿÿÿÿÿ»XA2" */ $"140A 0401 0000 0000 0000 0000 0000 0000" /* .Â.............. */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0103 060E 1A29 3947 7EE7 FFFF" /* .........)9G~çÿÿ */ $"FFFF FFFF FFFF FFFF FFE7 7E47 3929 1A0E" /* ÿÿÿÿÿÿÿÿÿç~G9).. */ $"0603 0100 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0104 0913 2031 4052 AEFC" /* ........Æ. 1@R®ü */ $"FFFF FFFF FFFF FFFC AE52 4031 2013 0904" /* ÿÿÿÿÿÿÿü®R@1 .Æ. */ $"0100 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0001 0306 0D19 2838 4670" /* ............(8Fp */ $"E1FF FFFF FFFF E170 4638 2819 0D06 0301" /* áÿÿÿÿÿápF8(..... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0001 0409 121F 2F3E" /* ...........Æ../> */ $"4FA2 FAFF FAA2 4F3E 2F1F 1209 0401 0000" /* O¢úÿú¢O>/..Æ.... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0102 060C 1726" /* ...............& */ $"3645 69D3 6945 3626 170C 0602 0100 0000" /* 6EiÓiE6&........ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0103 0811" /* ................ */ $"1E2D 3A40 3A2D 1E11 0803 0100 0000 0000" /* .-:@:-.......... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0205" /* ................ */ $"0C15 2026 2015 0C05 0200 0000 0000 0000" /* .. & ........... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0001" /* ................ */ $"0307 0C0F 0C07 0301 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0001 0304 0301 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 00" /* ... */ }; data 'plst' (0) { $"3C3F 786D 6C20 7665 7273 696F 6E3D 2231" /* ...CFBund */ $"6C65 4465 7665 6C6F 706D 656E 7452 6567" /* leDevelopmentReg */ $"696F 6E3C 2F6B 6579 3E0D 093C 7374 7269" /* ionEnglishCFBund */ $"6C65 4963 6F6E 4669 6C65 3C2F 6B65 793E" /* leIconFile */ $"0D09 3C73 7472 696E 673E 3135 303C 2F73" /* .Æ150.ÆCFB */ $"756E 646C 6549 6E66 6F44 6963 7469 6F6E" /* undleInfoDiction */ $"6172 7956 6572 7369 6F6E 3C2F 6B65 793E" /* aryVersion */ $"0D09 3C73 7472 696E 673E 362E 303C 2F73" /* .Æ6.0.ÆCFB */ $"756E 646C 6550 6163 6B61 6765 5479 7065" /* undlePackageType */ $"3C2F 6B65 793E 0D09 3C73 7472 696E 673E" /* */ $"4150 504C 3C2F 7374 7269 6E67 3E0D 093C" /* APPL.Æ< */ $"6B65 793E 4346 4275 6E64 6C65 5369 676E" /* key>CFBundleSign */ $"6174 7572 653C 2F6B 6579 3E0D 093C 7374" /* ature.Æaplt.ÆLSPrefe */ $"7273 4361 7262 6F6E 3C2F 6B65 793E 0D09" /* rsCarbon.Æ */ $"3C74 7275 652F 3E0D 3C2F 6469 6374 3E0D" /* .. */ $"3C2F 706C 6973 743E 0D" /* . */ }; data 'scpt' (128) { $"4661 7364 5541 5320 312E 3130 312E 3130" /* FasdUAS 1.101.10 */ $"0E00 0000 040F FFFF 0001 0002 0003 01FF" /* ......ÿÿ.......ÿ */ $"FF00 000D 0001 0002 6C00 0100 0000 00FF" /* ÿ.......l......ÿ */ $"FE00 0401 FFFE 0000 0C00 0400 2000 1A20" /* þ...ÿþ...... .. */ $"4E75 6C6C 2053 6372 6970 742C 206E 6565" /* Null Script, nee */ $"6420 7468 6520 6170 7000 0200 000E 0002" /* d the app....... */ $"0000 0F10 0003 0002 FFFD 0005 01FF FD00" /* ........ÿý...ÿý. */ $"0010 0005 0000 6173 6372 0001 000C FADE" /* ......ascr....úÞ */ $"DEAD" /* Þ­ */ }; data 'spsh' (0) { $"0000" /* .. */ }; data 'CODE' (0, purgeable) { $"0000 0028 0000 0000 0000 0008 0000 0020" /* ...(........... */ $"0064 3F3C 0001 A9F0" /* .d?<..©ð */ }; data 'CODE' (1, locked, preload) { $"0000 0001 4E56 FFF8 2F03 7600 2F03 303C" /* ....NVÿø/.v./.0< */ $"A1AD A746 261F 2D48 FFF8 2F03 303C A89F" /* ¡­§F&.-Hÿø/.0<¨Ÿ */ $"A746 261F 202E FFF8 B1C0 6720 2F03 203C" /* §F&. .ÿø±Àg /. < */ $"6370 6E74 41EE FFFC 2248 A1AD 2288 261F" /* cpntAîÿü"H¡­"ˆ&. */ $"4A40 6608 4AAE FFFC 6702 7601 1003 262E" /* J@f.J®ÿüg.v...&. */ $"FFF4 4E5E 4E75 8F47 6F74 436F 6D70 6F6E" /* ÿôN^NuGotCompon */ $"656E 744D 6772 0000 4E56 0000 2F0C 4EBA" /* entMgr..NV../.Nº */ $"FF94 4A00 672A 598F 2F3C 6170 6C74 2F3C" /* ÿ”J.g*Y/ÚàÍ%¼ÀàŒÓþëÛ{¿„¿'½@ šåééèrÕÍß¿ÁÞ׉ˆƒ^< Ðר  CåÞééæ–™Ü£Ý´­²}BÖÐÐÿ<RÙØÙ~ ™ÒàÒÒ_7b³w’›‚†5v±Ä¹ìÿ\Y6 mñüè•pÏšÙÝÝÙÈÔ´¶Žâ€ Ÿs4#Ðû€þ™™ÅÝÝ®¶³Êuž–ä€ Ì;7 Ñû€þN˜º…ÐÞ¼»Ë­tçÅÿ&!•ïþüè“£s^>K˪„¤&wäñæãÊ.F½ØØ¶€ÿªžˆ€×Ø‘µçèéµss‘Ù××9—ƒ3 ¦€ØÙcß¼}AØØ×²r˸ƒ !J±b½×ר×€ tØØ×ÇE×ÿƒ8δ´;*ªY ¡Õ1 k0@†8×ØÈ³©D4’±¶&:²ŠE¯¾8‡6Ø×ØÖË·²¸ÓÖ)3ÕÆ²²¶ÎÙ8…ÿ4ר××ÙØ×Ø××,9Ø×ØÖØØ®F†#AÕ‚ØרØ*8Ø×NbU‡¯$JÓÙÙØÙØØ gÙ×Ù©¶‹»Dר××Ù zØÓ;dU ÿ™WÌ××| á‘ ÿ™ 6`U”ÿÅEG¿Š‡ªˆÐª ÿ 12,'  “Ð/ €€ Ð/ÁÂõþÙÃú· Ð,ÑúþþÉù~ ‡ŠÐB5¾þãÔ ª ÿ‰ˆ 5þþq yI'‰K%¦‘/ñ«þš}è%Ï^  ˆ¶5þ¹5c|‡Ä!÷´Åþô ‡ÿƒ `M=…oC":E þ S…Ìq '4µ½®"¯þt¿„¿'§7 ÀÅÅÃ_Ë +ƒR7 ´»• 8Á¹ÅÅÁ‰†UÖйÿ<K½¼½q ™Ç¿¬®V %  #ÈÿWQ3 mñûè•41q€ Ÿv4"Ðú€þ ›o€ Ì;5 Ñú€þN˜¶ ×&ÿ#!•íþûè%>(3>H5@Vªr#wäñÔÒ¸L7) ¦¼¼ˆ¶€ÿªŽzq»¼µÖ×לul½»»1<ƒ3 “½»¼½ZÏ¢m:¼¼»š9#Zƒ !C—U¦ºº¼º€ g¼¼º­E°ÿƒ2²——3%”M º- \/@†2¼»ª—‘<-|–š#0–u;“¢8‡0¼»¼º«š–š³º&-¹¤––™²¼8…ÿ.»¼»»¾»»¼»»)3¼»¼¹¾¼—C†#8¹…¼'3¼»D\U‡¯$?·¾½¼¾¼¾ \½»¾’¶‹¯<»¼»»½k¼¹3dU ÿ™M³»»mˆ á‘ ÿ™ /`U”ÿÅEG¿Š‡ªˆÐª ÿ-0)&  “Ð/ € Ð-ÌÍõþÛÍú¶ Ð+ÖúþþÏùv ‡ŠÐA3¾þãÑ ª ÿ‰ˆ 3þþg  y? $‰K#§‘-òªþ” xéÑW ˆ¶2þ¸4c|‡}ø¯Áþô  ‡ÿƒ  `M  @-C¢þ S…Ìq %  þi¿„¿'( T€  'ƒ7€     Öйÿ<€)+ ™¶*    Èÿ\/ oñûé•€  $j€ Ÿq2 Ðú€þ €  ›f€ Ì84 Ðú€þI•µ  ×ÿ& –îþûè  4CLª wäñ €¶€ÿª$´ €4ƒ3  7Rƒ  €€ C°ÿƒ  (>†   8‡ … €8…ÿ‡ƒC†#†‚\U‡¯$ƒ€¶‹¯ ƒ dU ÿ  á‘ ÿ•  `U”ÿÅED¿Šl8mk ×ôôôôôôôôôôô¬ ôÿÿÿÿÿÿÿÿÿÿÿÍ ôÿÿÿÿÿÿÿÿÿÿÿÍ ôÿÿÿÿÿÿÿÿÿÿÿÍc ôÿÿÿÿÿÿÿÿÿÿÿΦ«:ýÿÿÿÿÿÿÿÿÿÿÿüÖÅ(€þoƒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿææÿ¦ßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÊFþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÝ.?÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿá [Òýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¦fáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈ .ûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿöôôÑ:Ñýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿ|XÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÆJó9pÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõ i›rÒÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ÷š ¤øÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞ!Óÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿƒ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿã†ßA€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ €ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýW^ñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþâ` øÿÿÿÿÿÿÿÿÿÿÿÿÿÿüž-¿øÿÿÿÿÿÿÿÿÿÿÿß=-®üÿÿÿÿÿÿÿüª:§øÿÿÿþÝ=vùú]ich#HÿÿÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿÁ€ÿÿÁÀÿÿýàÿÿÿàÿÿÿàÿÿÿàÿÿÿàÿÿÿÀ?ÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿüÿÿÿÿüÿÿÿÿøÿÿÿÿøÿÿÿÿøÿÿÿÿøÿÿÿÿðÿÿÿÿ0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿøÿÿðÿÿÀÿÿ€ÿþüðÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿÁ€ÿÿÁÀÿÿýàÿÿÿàÿÿÿàÿÿÿàÿÿÿàÿÿÿÀ?ÿÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿü?ÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿüÿÿÿÿüÿÿÿÿøÿÿÿÿøÿÿÿÿøÿÿÿÿøÿÿÿÿðÿÿÿÿ0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿøÿÿðÿÿÀÿÿ€ÿþüðÀih32Æ» HNPTRNTLJHH‚FDFE‹˜ â!25520*&# ƒS˜å+6 ‰Q˜å+1 ŠU‰„‹f˜å*/&¾¾Âòþþ”;Õþþf˜å*)*Àäû€þ ’Äìþå¯v*fq¼’å+i‡¡€þ ”ÉþòÙ€’G³››‘åQ?(Nþþ“åþáÏ|¥1¿¶»¬}Ôÿ}+4?°þ”þöáÔwy_YQbgÐ븖vÿŽÆJ _~Mü”þö߯ž¯Ã¬»Ç–gnáË´xÿŽÚ<(4ÓÓpSþîÚ”þýá—ãóíßÛâ׫v»Ì¶x†Žu/€þþônÑ«…ôôîªþýóå€þጳ½ªxÌÿF‚©%žd€kÝ õ£=áú©üþàĉ ‚yÚá1ŠAŒ€ÆvµŽ¹/á-0îþáÜzxt¸ÿŠ è¼Y¦ãÍé}˜¨–àߤ¸áMþûÞØx›Æ‰™ÌR3¬åÙå€é–¿ÉÞÞØµÅ©½¼ßß°{ɈÿäËÚPàØéçÔ É¹áßа°yáßáÏzt߇ÌÙÖÚ‰+»éÔéåi¬Úá˜ááÞ«œ¯¦zj·ª…,c°ØÙר^@äàÞééèt¡‚­Žu„ºØÄ›‰p/F®œ¢ªÖ€ WÙÖÚ×ÖA€J×ÓÓàÐÐÓ3ŠC\·œvx‰z‰„gN†´ÖË·Ëâ¶p-À:+žëûøáÓX pÚ̇Ô×ßÚÔÙÚÚ߸¦Ë€€·îå2&Øøý€þñÈ¿½¶ÚßààßÌ…‘¤Þ @™­ð‚ ªñ0(áû‚þ€~v¶ÚÚÜÞ…Õª³ÍÈtWó˜Àäƒ ×'áü‚þ ”’×€¶ÚáÔÕÒáÖ‰tíå®ÞÿÅ# 0 àô€þ üôc¼™@)/ÀÙ¿”€wl<‘œ·à€*ÐY"ÜæûþûôÝ3! šbpm9Öaí‚È€ºÖ8€ŒÜîðæçÚÛ¶r€ÓÖÚÖÕ ×+ÿÇ'Àe¾Ã* ÆéäèèéçÑ  ‚×ÙÙØÙ™„ å AØÙÙÖÚ×Úµ€Dèêèêê·²§²@7ÙÚØÙÖ–—Û†d€ÑÖÙ×Ú×ÚØçè´¯H€ ÙØ××ÖמϪä†fazFÌ€ÙØÙד %:A¾×ØÙÙÕ7–Ýá“á†Yu²µ†xØ×ÖÙ×ן/ÏÙÙ×ÖØ—!Ðć"_jη²²ƒ€ÙŠ: ÀÚÚ6±"Њ"YbÙÕɶ²¯Rz®³Qa£T*'…°¶Њ _iØØ×Ѳ±¯cH¤€²ÀHb²²£HH²²ÀÖЊ n×ÙÙ×Ù×ʺ€²°ÏÖ×P_ÕË»²¯¯²¼ÏÙ×Ћ!cÙØÙÙØÙÙÖÒÏÐÖרÙPiØØÔÊÃÄËÓØØÎЋ iØ×ÙØ×ÙÙÖ×ÖØÙ€×Qk×€Ù ØÖÙ××¶'ŠBÎ×Ö×ÙØ×ÙØÙ××Ù×Pj×ÖÙ€×ÖÒPx¶‹¶j \ÍØÙ×Ù×0tØÙـל6¯¶ŽäŠ€ÖÙØÙØØÙØÙ×¾ÙרÙÒP†¶’ÈŽEר×Ù ØÀ××Ö“ã•Â: kÓ€Ù ×ÙÇ×ÎO>¶™Ø!bҀص–¥Ûj€ _…¶Ÿ ¿W8Ÿ¤îÅIѪ‘» HNPRRNRLJHH‚FDFE‹˜ â1441/)&! ƒS˜å+5 ‰Q˜å+0 ŠU‰„‹f˜å*.&ÀÀÃñþþ”ÎÁÖþüf˜å*))Ãäú€þ ‘ÆìþN fŠ’å*g‡¡€þ ’Êþ¥ G K‘åO=&Lþþ”åþ 1¿¶ Ôÿ}*3>¯þ”þÅ  Ь ÿŽÆI]}Lü”þÉ4Y#U[ ÿŽÈ;&3ÓÓqVþíÙ”þ÷Uòë/|áµ  .Žu.€þþôkÑ«…ôðŒþý´S€þ kÿE‚¨%žc€aÐÄ£='ú©üþ ­á.‰AŒ€¹s¥1/,/ïþ fÿŠ è¼X‹º­ÅjŒ™mMþòQƉ™ÌR 1™¿µ¾€Å‘ª %°ˆÿ䯾:¸¯ÅÀ° Ä Ô‡Ì½º¾~*ŭŽhv™y²ª…cž¼#Y 7º·ÅÅÄd•uk9J$"8É€ S½º¾»º@€C×ÓÃ⩬-x '    %"+â¶p-¬9)Ÿêú÷áÓV €€1ÖØ1%Øöü€þñ€  Pá‚ ªñ0(áú‚þ€   Uóäƒ Ò'áû‚þ ”’È  íå$^ÿÅ# ) àô€þ üôb¼˜R>, b€*ÐT"ÜæúþúóÝ,@))1'om2ºTâ‚È€¡º1€ŒÜîðäÔÊΠ@@0)7#€ºº¾º¹×+ÿÇ$¦X¥¬% ÆéÙÖÖÙÖÃB<'03p»¼¾»½™„ å =¼½½º¾»¾¦€CÞÚÖÚÚ –˜–67½¾¼½º‚|†d€ µº½»¾»¾¼€Õ×™”G€ ½¼»»º»3%цfYj?²€½¼½»ƒ #4:§¼¼½½¹0–ÝRá†Yg–˜uo¼ºº¾»ºŽ-¶¾¼»º¼„ Ðć"__²š––rp½y2 ©¾¾„.–"Њ"YX½¹¦š––G i“—GUŠH&s•œЊ"_^½¼»³¤––”V=‹—––£CV––‹?>––£¸Њ cº¾¾º¾º«œ€–•©¸ºHT¸®–••–ž³¾ºЋ!V½¼½½¼½½¹±°³º»¼½J^¼¼·ª§¥«·¼¼²Ћ [¼»½¼»½½º»º¼½€»K`»€½ ¼º½»»ž'Š:²€º½½º½»¼»º¼ºJ_»º¾»€º´Ev¶‹¶jP²¼½»½»-i¼½½€»‡6¯¶ŽäŠoº½¼½¼¼½¼½»¦½»¼½µFˆ¶’ÈŒ?»¼»½ ¼©»»º€ã•Â: _¸¾¼¾¼½­»³C>¶™Ø!Y¸€¼¡¥Ûj€ Rˆ¶Ÿ ¿Z8§¤îÅGѪ‘» HNNRPNPJJHƒFDFE‹˜ â/33/,($  ƒM˜å*4 ‰Q˜å*/ ‰•”T‡†Šf˜å),%ËÊÎñþþ“ÒÍÙþüf˜å)&'Íäú€þ ‘ÎíþD f…’å)g„¡€þ “ÐþŸ G K‘åM=% Kþþæþ 1¿¶ Ôÿy(1;¯þ”þÁ Ð¥ ÿŽÆG]}Mü”þÅ -W  UU  ÿŽÈ8%2ÔÔpQþíÚ”þ÷ Jòë uã±  (Žr+€þþôkÑ«…ó•ƒþý®G€þ  [ÿC‚©$c€ Á¢;ú§üþ £á. ‰A‹€ B --*-òþ fÿŠ è¼ W  &hLþò LƉ™ÌO* 1 € ›  €  «ˆÿä 6  ” € ԇ̀€1(  #*  €  ²ª…c B  € #  -B+É€1‚=€ A×Ô¾     â¶p+.7( ¤êú÷âÔV ‚  € ÖØ/%€ Úöü€þò   F Ù‚ ªñ. 'âú‚þ€   Uó äƒ Ò% âû‚þ ’‘È   íå Nÿ½# "  áô€þ üôb»—6 €  [€Ð7€  ÝçúþúóÞ fmà‚È€  €ÝîðÁ€  €×ÿÇ$   Èég€  ™„å *‚€@} 4 u†d€…€ F€‚- ʆf' ‚   –ÝEᆠVGƒ" ‚Ðć\  € 6 ЊY ‚ €  Њ\€  € ЊŒ ƒЋ„€€ ЋŒ† 'Š‹ …v¶‹¶fˆ&ƒ6»¶Žä‡†‚޶’ÈŒ†€ã•Â:  >¶™à"€¥Ûj€  ˆ¶Ÿ ¿U8§¤îÅDѪ‘h8mk F|F ÞüýýýýýýýýýýýýýýýýÞ.ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë2ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë2ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë2ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë26.ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë2£Ê3ëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿì9nó¥ EøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýÒºV PôüŒ þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþýèfr÷ÿ² ´ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþññþÿØ&Nìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿë2¼þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ·3Úÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòº(Erëþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøq PÉíøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿé4iÊðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÂ-ÚüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚ2.ÓúþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúdždIöþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýýóD©óÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñKjËõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþîÔûìD%Ñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿý¼W,ì¸3ÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíaÐ>PÓûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿõ½ÄC Íðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýõd¸ñþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþË Z¸øÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿù‹¦ûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôPQôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÎ´ìØ'Pôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¾'M“Pôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯  Pôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ Pôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ Pôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ Wôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯ üÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ« ®þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷hYÞýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøÜ_<±òýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿê-S»øÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüß_[Øôþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþën&[Á÷þÿÿÿÿÿÿÿÿÿÿÿÿÿûÎM!rÞüÿÿÿÿÿÿÿÿÿÿÿ÷¤3iÁñþÿÿÿÿÿÿ÷»EZ´èùÿÿøÓm >§þþ¥'it32oÿÿ¡ª¶Úä¨åäÚ¶ªÉ ¶âÜÙÝØÏÌÂÂ€Ì ÏÏÕØÛØÏÏÌÏÕ”ØÛÝÙÜâ¶Çª¦N  ! €Œ A°ªÆÚ\%$€-33.--(''$ $  \ÚÆâ0!,22€54541310,+*)&%$# 0âÆå "2778830.++('&#€ ŒåÆå $47;60**" €–€åÆ å +575+€  œ€3åÆ å *47/  €"ŒŠ€FåÆå+57*+7KZaa\O?,"!€!!)192.%ƒ!‚€FåÆ å+57*$æÜËÂÌÝòüþ*€ *þòèßÔÖäíø‚þw‚€LåÆ å*43*JÓă¾Óìüþ*€ /ûëÑÆ¾¾ÄÍâùþw‚€FåÆå *43*&eƾ¾½¾ÀÂÑÝòûþ*€ 8ðÙÍľ¾ÁÎÝóþ €FåÆ å *43*6u¿€¾ËÙÞçîû‚þ*;äÏþ¾ÆÖàèûþþû鼜šq €FåÆ å *4/"0m€¾ÍÜæð÷÷ƒþ* JâËÆ¾¾Öë÷þþýîßæ€„&€L刪ÚðÚ¶¶å*32!*]ÉÀÇÝëôû…þ* CáÇÄÂÔìýþþúåÚ˯ƒvw~*€F凪pqv¨àÔµå*.*àÙÞî÷ü†þ *JÜËÅÒùþ ôÝÕ¶•y~x€Få‡Úx‘|~™Ô´å "("XŸØéðü†þ * JâËÆÜû€þ ýáÜ˨…vz›>€Få‡â¹·±™}wÒ¶³å#'4?<;2#$*DƒÓƒþ*>æÔÌæ€þ ìÞÞ×¾•{z“¢å‡ â´²³±—|x媲 å.HJJA=7*(€"½‚þ*7ðáÖð€þ ááßϳ}~¢¨€å‡ Úî¶±±®‰xwײå*QJ?>0(%Nñþ*€.øïå€þ çááÞÏ©Š|~¢©€ë¶¿××¶ª ¿ë»±±§–}tvÔ°ªê)MG2$ ‡þ*€'ýûûþþùâááÛгŠ{˜ €ÀæÞÑÖê俪ªêظ±±¤‚xt¥Ô¯ ¿·NH:!„é€þ*€*‚þ*÷ÜááßÕ³~zvŠaqq_K >abx´Öä¶åè뱫Œxxwж­ªä}I<+$DN?-$gùþþ*€*‚þ öàááàÔ¶™{v€yfv_LX]XQPcbfjbØÐåëÝÁ±±–|xvÝÚ­¶ãf@/ 061#ag;€”þþ*€*‚þ ÷àááßÏ´™ƒ‚‡˜†€~–«{z|uhlc|áÐçìÔÒº³¡†xwä­ ÚÑP5%1myK € *"3&ùþ*€*‚þ*õÜáÚßÍ¨ŠŽ›¨›¿¶°››­±±®±¦™{ofcbÇðëãÓÒǺ³Žxwuå­ä¾E3%%Cd0%l±ÉÈ®d‚û*€*‚þ+÷ÞááÞ¿“®º¿¹×ÑÔ˼ÃÃÌÙßÓɱ†ohg:²ÖÝÓÆÍ¸µ«wxuꪬå‰;(%($*^¤¢¸i=* SÆÓëáÓÓiê*€*‚þ+úäáÚ֬гÖÌÓÜçÝÍòÝÙÔßÛÍÓÍÓ®Žxwx°ÃÇÇÒº³±xwvu¿«ªêf<''("SÄÓÓÍÓΪ6 S×ëþüëñÚ*€*‚þ+ýçááÒ—£ÎãðëûúíÔëßàà××âàÖ×棃vx±»ÃÇÓÆ¶±xxwuÚ«¿ªZ9&% 6¿ÒÛãâÞÕΦ$û‚þœÅ*€*ƒþ÷ááÆÉà÷þýñãßçù÷úþûîãàÛÓ‡x}±¶»ÀÉóªxxwwäª ªånJ.%âîü€þüðÓƒþŸ¿*€*ƒþüçá×ßë‚þúâáâ÷ƒþûäáÚ“zг€½Éó›~xx™åª Ô»\I/…þ ëNþËnG¤þŸ«%€ &äèôýÈôüù⺪éû€þýþóááåü„þùááÀŒˆ¤³³½¼¹ª›}xxÌå© ¶ØKR=%€þÔ‰a†äþ~ò.µ%þŸ € +j©Ø[??€×úþúæ°†Ùæááù†þááØ‘z‚¤³¶³°ž’xxw¾ä©ÚªFG1þþäX– Xþ§ÜŠþŸ†’±Ü½“òþþÃi3wâáãþþðéü‚þááÚ°zz’±³³¤Žxx}ÔÚ©äJD+ þþo²¬*%þ¿Ù>þŸ–áÇ%¢©ÞÇ Áùþýƒ~‰4ªàáôö´sV°úþÜááØzz€‘Š‚yx{x“ض¨ÌënH6'ëþA’t þ¿Ó€þŸ€€´Ù½I£µurz™éþ¹#7*yÛááø£;´eYïþÛáßÚz‚xu‡ÌÔ¨¶åáW>%€AÓþA þ¿¸"€þŠ€±Úàv3"µ‰z¢³¹õ¢XæáÚÍ- AIîþ€áÜ€z€xvtw¸Ô§ÔÒ¥WH/ «þM þÈv©b "eê\E­ÐÔYTWr‰ËÑÕ¾¶• '¼ßáÝv«û€þüááßÚŽz€xw€ºáÔ¤ª¿Úäày 9(móY "òããééèçèéʱδ„–ŸÅÚáßÞ½¢‹ bêááã€7üþû€á ׳x|Žˆ²ää¶£¶îèäÑ«U9& ¸Y€*eæããèãÍâééè} ˆ¨·¨¦z–ÔàáßßÞ·¤+Šçàáéb €þýûëÛááØ¡xxz‡ÄìÆª¢ÔØ»y,4( ‘œ>°ÝãÈÝææèé è³!{’¨¿ÔĺÚßáݽ¦¶½ÎÀǘ%–ûþüûíåááÜáÔ’xx‚·ßÆ¡ª¶îé¶\„"5€)›Óèèäã¾Öãææ„餤èÐй®ÄÚáÚáÜááÛ¶ƒ°•€°É³¹ËâßßááÚ½Šx}„¾àªŸª¿äÕ¨n*‚HbD3( -¼€ãäçÛåçéç„é,ç8×Ä¢¢ÎÛÜßáàáßÔ´¶¼ÓÛÚɼ­°ÍѾÇÖßßÚß×¢z}xˆÉ䞪¿äµN‚HнÒL6€  BÝããèè‰é'ää®AäêžÌÙáÚßÞáà̰ÉÖØÌµ³ƒ•ÕàÝÚÒÉÎÎËË¢}€x™ÙÚœª¿ä®]„?ËËÑÚÉiP+ jàãÉØ‰éçããÔ8/åÉĤ¹ÖááßßÚáЃ°€y®ááß߀á ÜὊzxtt°ñ¿š¶îݰ?†*“ÑÚØØÒU<(†àéßÏà‰é-çåä­ÒÛ¿¶¼ÞÞáÞÆ«§ÔËű“Š€€¨×ÞÝÚ»±ÆËÐÑ¢|zsqw±ä̘ªÔЈ4 „L¼É×Ú±_J1hÑééÝÔÕçˆé,èãä^Á͇¸ÏÚÝáàØ¢ŒÁààÕ¬¤­ÃÙá࣎nq€¦¶§zoos—߯—¶åÌ\„»ÙÚÖÖÙÚÚÖ‰N?+.»€éÛÒÖçˆéå绹 J¬áÒãááژ˃áÞ̽™sœ½³¯¦³™†zttj@žìƪ”й3ƒ(tÕ…ØÏsF.!`¶éèæÜÐÙæ†é-æèè£{)°ÖÝÖÙÝŽ‘—ÃÕÝ×Áµ¨€—®ÅÞ×Ͼ³¦zwlrIe¿ê†åâÚ¶‡¶Ÿ„/ŽÂÖÚÖÙÚÚÖÖÚÚÅb?'„uãééçØÒÒˆé/©˜V-Ú××zv{‚zzŒzžÖÚÚÖË¿³ ’™„zsa~/ ‰ØõØÅ¨€¥¤£ªÐÔª…ÚD‚3{¾Ò×ÚÖÙØ×ÖÙÚ××Ä[6€ „ xÚãäèÙÍÒà€è?éèéçâÙ «‡#p¼ƒ|¦¡‡{il|ÂÞÖÖÞÑÆ¼±¡—œzxly0&^›™™žž§¦ª­Ìä¶„Æ")ÂÞÖØØ×ÙØ××ÙÙØ×ÚÀU% ƒM6{š®Ô×áèåÕÖÚ××ÑØÏл6¢®I"IP¡»·§“xpxŠŽš§¬©§ ”™•‚zz{vzA F€‹•™±¸º»»·»¹µÁÎ붃Æ‚WËÖÙÙÖÖÚÚÖÖ×ÚÖÖ¡A…‚/m×ÝÓÓÉÓÓÑàèÖËËÐËÒÓÖF Ф¤Cs€›\\„¤··¨~vqqx™‰€z™„v€g$x††Ž ´ÆÒÛË˵µ·ÀÀÛê⪂ÚX‚*p¹ÓÙÚ×Ö€ÙÂŒ]L/„€€-ŸÙÜâëëÞÐÒÓÒÕÛÛ¹ÀÁ¿´L%€y‹³Á¶ƒ…yŽª­­Ÿ—‹‚~|€z }„†•©©¶¤†}w^‚ŠŒ›­ÃÌÁž’”„q¤¼À¿Õñ¶‚ª×˜S‚pš½×ØÙÍ•P=-'ƒ-‚ÍÛãîððõìÚÓÐÒÓÓŒKKQEMs£¼ÐÈÍÁ€v´ÆÇÇÉÍÍÆÆ¶­­€µ ¶ÄÄÇÑÉÖй¯˜¡Ÿ¨ÀÑÌd  #v¥½ÃáòÚƒ¶âÐpƒAvÀ§\::/'‚€! žÓÜëöûûýøðéáÖÓÓºX7*Ip¨½ÚÚ½ÚÖ‡ÔÚÔÚßá€Ú€ÔÙÔÔÚÕ€Ú ßÔɸ’™³Â˨M„€±½Úî䄪¿Ö»`"„ (176+!€:ÑâéðöûýüýýûõôòôîT,a¨ÏÝÖ±š…†×áÝÝááàÞááààÝáÞÜ×Òð§¬ÁÔÞáÔ²ŽŸ«B€ ~  µÞõ冪¿åâbƒ ';;(  bÖðð÷úûûü€þýý€þä -©ÈÚÚßÄÉÔqªÉáÜÜáÚßßáÚßßÚáßÕ½¨Šwzz­­ÉáßͨŠv1ƒ {• ½Üñ䈪ÔáS<:/$™Úð÷øý‰þM‚ mÉÕÛŸ–­«€ÂÑØÙàƒáààáàÞÖ€’Í„ª›³ÆÜ×´›vOƒ N·—¡¿ÛòÚŠ¶äΠd".9*""*€½àð÷ùýýˆþׂcyŒÚ’€}œ®¶ÂÅÕáÜÝÝ€ÜàáÚО|“¬‰½Ñ°›³³²Ðƪvv`€ K®Ý䜎¯Ïßñ¶‹ª¶ßñÆ$;0'€("Ááð÷ûû‰þû…7v~zqzˆ¨¶ÆÚÚßÚÚáÜÜáÚÃ…v›ÕÍ€Ô˳ÉÉÍÕÔ½vttK 3–ßóö¾˜•±×áäª ªçÍ,%=+€‚Ááð÷ûýŠþ„6L“˜‘’™xŒ£·ÑÙÛàáßáÝÚÙ¾‚yyÉÙÍÏÒÜÜßÛÔªpttuGˆÐäÔíÔ›Ž¤ÉÝ俎 Ìë¨,J*€  ‚Æáë÷úüŠþŒƒ7•Ÿ†‹š·Þˆzu‹¢¹Ì×àáßààÚÔ€·ª‰¹ÚÚÜÜáÛÒÛptfvëæÆªÚÙ’»Øà䪶å×H(C'€€‚ÁáððüüŠþé‚& Æ¢”–²×vz€—°½ÍÚÚááÜÔÔ΀ÉÕÚÉÚááÚÚÖ¹›v€t ªíÔßéÙ®ØÝð¶ŒÔá¥;'J&  ‚¿áððøüˆþýöãY»³¤—Žˆ”Ì´}y„œ¯ÅÓ€ÜÞÜÙÕ»v}‰³€·´··¢‚}vpx”ÖóæÍ¸˜–¯ÅÛåÔŠª¿î߀N/ ‚ªáððøý‡þûøðÛZ€ ¼ÞŦ{^PC)$Bk|®ÆÛÛÝÐÕÀ³¡–vx~€xwxxwvcT?4Kœ¸—–•žªÄÔÛìÔ‰¶îèÞ¨=ƒ?0€    ~Þéðñú„þüûûúñ÷ðl€¼Ó¯ŒkZzŸº€Ôο¨š‡q‚vf€vaE'€ ~•  ´ÅÝÝëÔ‰ÔÐS„&%€ !dÝâåîöüý‚þüùõóèßß-€4TŽV2Xq„­ÊÐÆ°‘ƒ€•œ•žc1  6F”¼ÔáêðÔ‰а3„ Ji €"‚ 9ÜÜâæðûûþþû ÷ðçÝ®y3€ƒ+~ ³½š|qRHpmcm ƒ9¸ÖÖÅa"ŸíñЉªÑE… "|ÄÅ& €   ‚©ÜÜáæîïøûúûù÷ïéÝÒÏ´…sge3„+pŽ£‡vm0("7[j‚¯ØÚ××Ò˜>—ã׉¿¿‚~ÅÕÙÙw!„uÑÜÝâäíöúøùòééäááÏÇÜáΑ< €‚ DxuuG ƒ <¦Í×Ù×רÚÚÔ}+%€"’¶ˆªÈ„ VºÓÖÖÅ8€…'ŒÐÜÜßî÷÷ððâêççåÚÚçåм¶’X‚ /ra+„qÓÚÚÖÙÚÚÖÖÚÚÕŸ<׉̇"ƒ +XªÒÙ»8€ [Ï[ƒ s½ÜÝæìööðâèäé€ä èäÝÔâÞÉt$U ƒMÉר×ÖÙØ×ÖÙÚÖÚÁ@€J׊¶ÖÉZ ƒ 3 ÖЊ¨×Ù¯E ƒ!²Ùâäððãåäçééè€éççêèÈ`€ ) ƒ'»Óר××ÙØ××ÙÙØÖÆ€Iȶ‹ª¿äši5‚ªÌÚ®/ cÔÖÚ×Åq+„³ÜÜââãååèçêèèçêçÚ¦<€‚€+; X§ÜÙÚÖÚÚÖÖÚÚÖÖ×Úƒ €:¼ÔŽª¿ään€H”ÅÕ¹M(3Z¡Õ×ÚÖÙÙØ¿Š,„ pÂÜßÜçåçèêéçèèêèê鸲²wT Rš«bƒ(–ÖÚ×ÚÖÚØ×ØÚØ×ØØ«4DaÂ꪿åÌv €€ A ÚÖÑÙÖÚÙÙÖÖ×ÚÖÚ××ÚÚ×µy…DÕéçè€êè€êèêêß·€²¯§²±²²}„X«ÙÚÖÚ×ÚÖÖÙÚÖÖÙÖV‚I Ž™Û哪ÚãTqºÔØ×‚Ù ØØ×ÙØØ×רÙÑ›.…£æäç€éè€éè俱©€²©¯œs ƒ T©Í××ÙרØÙÙØ×ÙÙÕ­J’›™“Ýä”êe„ uÎÚ‚Ø××ÚÖÙרØ×ÚØÚ´p2ƒ jtË€çèçèçÙ¾«€²«¬jO„*ËÚÖØÚÖØÙÙØØ×ÚØÑy€ AŠ£±²•ÝÚ•åd…R®Ñ€ÖÙÙÖÚ×Ú×ÚÖÚD„€ç éêç×´²²¯¤m"†ÚÙÖÖÚÚ×ÚÚ××ÖÖÚ×o‚ žºÁÏıŸ¢ä¿• åf!„B°ÕÕØØ×Ù×ØØ€×Ø×ÚÕpƒ ÊÐàáÞ¸°¬›!„ ;³ÙÙØÙ×רØ×ÙØÙÙÖÁV‚ vÙÜÝÝÃ¥˜¯êª• åf "\¤‚L ]¡ÅÖÚÖ×Ù€×Ø€×ÚÕ½Tƒ *1`m2„ M•´ÍØÙÖÚ€× Ù×ÚÖÚ× 6€ X¸êêëèܵ™ŽÜä–åf-f±²¨q@ ‚lÃÖ‚Ú×€Ú ÙÙÚÚÖÙÖÚÓŠ/††wÍÖÚÙÖÖÚÖÙÚÚ×ÚÖÚÐRtçÆ¿åîÂŒŸìÚ–å_ (n®±²­‘j@‚T¬Ê€×Ù× Ø××ÙØØ×ÙØØ³y%Š8ˆ«ÙÙ××ÙÙ×ÙØ××Ù×ØÑ­M€ªæª€ªÔçÀåꪖåYu°€²º°ª†. ‚ +xÏÚÖ€×ÚÖ×ÚÙ××ÚÖ×ÒÅy.‰ QµÏ€Ù××ÚÙ×ÚÙÖ×ÚÖÖ—/!¥åƒ¶×Ôª—å_p»»‚²´µf„ tÖÚ ÖÚÚÖÖÙÙÐÐÁc7´×€Ö ÙÚÖÖÙÖÖÚÚÖÎ{ƒ $¥å¡å_kÐÄÄ·²¶²²·¸©N ‚"[“ÊØÖÖ×ÕÖË™n=#„ÁÓ…ØÕ´^€  (X+!¥å¡ å_jÖÐÎÁ»ƒ²¹¢d$ƒ €ÃÖÙÑ›y6‚:+‚   mÀÙÚÚ×ÚÖÖ€ +6]±±9" ¥å¡ å_iÖÙ×ÑÒ¾¹‚²µµ@ ŠÃàÔ¨¶ØÌŽ-ƒF}ÂÖÚÖ€Ú‚ÖÙÖÖÚÖÙÚÚ‚ÖÙÖÚ© € ÖÚÙÖÚÖÚÖ××лrŒÍéªÔÒ˜a3 N­ÒÙ××ÖÙÚ×ÙÚÖÙØ×Ö‚Ù×ÙØ€¥Ú××Ú€×ÖÚÖÙÖÇ–[7£ÒÔ®¶äãÁŠ< %aŸËÖ‚Ù×ÙÙ×ÙØ×ׂÙØØ€Ù×Ü”€%¾Ú×ÙØ€×Ø×€ÙÖεP‚†Ñå¶±ª¶îé¦\$ +g¹ÖÚÖÖÙÖÖÚÚƒÖÙ€Ö××Ú’€'½ÚÖ×€ÚÙÙ€ÖÑâA‚æ×ªµÔÜL Ew©ÒÚÖÙÙ×ÙÚ×Ö‚ÙÚׂÙ×’€'ÀÖÙÙ‚×ÙÙв€)‚5§áÔ¹¶åÝŽY* E¤ÖÙØØÙ×ר‚Ù×ÙØØ×’€,ÀÙÙרÖμ“3‚“Ýä¶»ªÔáÂV‚ #iÃÖÖÚÚÙ‚ÖÚÖÚ×ÚÖŽ€7ÄÖÚÖÙħƒ"‚ªå¿ª¾¶äܹfƒ$‹ÃÔÖ×ÙÚÖ€ÙÚÖÙ×Öz€;ÉÚ€×ÖØÅ‘5‚S´ÔªÁª¶îÝÊ@‚R­ÏÙØÙ×ÙØÚ¼N3Å×̾o ‚=»å¶Æª¿åÌNƒmÁÖÖ××€ÖÙÖÚÖÙ»/;ÄÚÚØÇ¤K‚;ÀתɪÔت_!‚&Jz²Ò€Ø×ÚÖØØ®$€<µÓÖB‚<ŒÒÔͶîé«K„ ^ÌÖÙÖÚÙÖ¢)€ŽVƒQÝå¶ÐÔÒ‰5 ƒ 8Qy¸Ê×Òq 3&‚"jÒÔªÓ¶äݨj*ƒ  +d_‚‚…Ðä¶Öª¿äãÁ¤<„€ƒ„*™Ø¿ªÙª¶îÝʇ7„ƒ‚+}ÒÔªÞª¿äÖÆ™*ƒ'\¥Ýä¶âª¿äã´oT(C¨Ðä¿ªå ª¶îèÞÅ”b6€3‹Ñ俪꪿ßêãаxAvÏïÆªµÿÿ¡ª¶Úä¨åäÚ¶ªÉ ¶âÜÙÝØÏÌÂÂ€Ì ÏÏÕØÛÕÏÏÌÏÒÕ“ØÛÝÙÜâ¶Çª¦N € €Œ A°ªÆÚf##€,00-,,(''# "  fÚÆâ0+11€4343020/+*))&%!! 0âÆå "166772/.++&&%#€ ŒåÆå $36:5/**" €–€åÆ å +464*€  œ€3åÆ å *36.  €"ŒŠ€BåÆå+46*+7JX__YN=,"!€!!)182.%ƒ!‚€BåÆ å+46*$æÜÌÄÍÝòüþ*€ *þòèßÕ×äì÷‚þu‚€IåÆ å*32*HÓÆƒÁÓëüþ*€ .úëÒÈÁÁÆÎâøþu‚€BåÆå *32*&cÈÀÀ¿ÁÃÃÒÝñúþ*€ 7ðÙÎÆÁÁÃÏÝó€þüo€BåÆå *32*5qÂÁÁÀÍÚÞæîú‚þ*:äÏÅÁÁÉ×àçúþþë…" €BåÆ å *3."/l€ÁÎÜæðööƒþ* HâÍÈÁÁÖëöþþõ. €L刪ÚðÚ¶¶å*21!)`ÊÃÈÝêôú…þ* BáÈÆÄÕìýþþãN €B凪 _ÐÔµå)-*:àÚÞîöû†þ *HÜÌÇÒøþ ª €Bå‡Ú  RÔ´å "("XžØèðû†þ * HâÍÈÜú€þ ò €Bå‡â ö³å"&3=;:1,$!*DƒÓƒþ*=åÔÍå€þ Š å‡ â 媲 å,FHH@<6*(€"½‚þ*6ðáÖð€þ  €å‡ Ú³ ײå'OI>=/&#Lñþ*€1÷ïå€þ V €ë¶¿××¶ª ¿Ê Ô°ªê)LF2# †þ*€-ýúûþþÔ+ €Àæ×¶ÈÜ俪ªàu  YÔ¯ ¿·LE9 „è€þ*€*‚þÆ  3‡Öä¶åš$ ¹¶­ªä}G<*$CM>,#fùþþ*€*‚þÅ€    ÈÐå¬" »Ú­¶ãf@. /60!_k:€”þþ*€*‚þÆ€      € ,ÒÐç£ "ä­ ÚÑO3#0lxK € *"2&øþ*€*‚þ*à     µðë å­ä¾D0##Cd/%k°ÈÊ®cû*€*‚þ&Î%.?n¡¡„1*6:ª©D€ ꪬå…:(#&$*\¤ ¸f<* QÈÓêáÍÓhë*€*‚þ+â:¡ÓÜæÝΨ).»ÎÓÎs ! ¿«ªàc;''&!QÆÓÓÎÓÏ«6 V×êþûêñ€Ù*€*‚þ+÷UUàêúóëÏŸ/6ÂÒáàѵ6  Ú«¿ªZ9##5ÀÒÛâáÞÕϦ$û‚þÅ*€*ƒþÈ*ÞþõÍF`æñùýúîái  äª ªåkI."âêø€þûðÓƒþŸ¿*€*ƒþû].¢‚þæA.̓þû’ €  åª Ô»ZG.…þ êLþËkF¤þŸ«%€ &äèôý³ðûØ@jú€þýþ´Sï„þÙ  Lå© ¶ØHO<%€þÕ‡a…äþ~ò.¶%þŸ € +sžÍY?0Jíþúæ°„ÍP×…þ ü € wä©ÚªDF0þþäX– Xþ§ÜŠþŸ†ƒ£Î­°þþÃl2S.Jþþðèû‚þ €ˆÚ©äGB* þþm²¬*#þ¿Ù=þŸˆÓ¯#ŽžÒ¸*Ùþýƒ}‰3c µö´sY°úþ  D±¶¨ÌëkG4'êþA‘s þ¿Ó€þŸ€x¦Î²P§7²þ¹#6*xaÊ¢:³dXïþ  #™Ô¨¶åáU="€@ÓþA þ¿¸"€þŠ€w£ÏÓs2"¥91Ô XMª, @Jïþ€     fÔ§ÔÒ¥Y<- ªþM þ½d›^ !eçX?¡ÅÈWSV$q ‚(+j«û€þû€$S¥Ô¤ª¿Úäày 8(lóY "ÚººÅÅÆÊÊŬ£»¬ƒ–5)R `mJŽ€6ûþÞ€  .eµä¶£¶îèäÑ®U7" ¸X€*W¾ººÄº­ÀÅÅÃj yž©™ž$~]k` Ž€þýòx*¡âƪ¢ÔØ»y,4# ‘œ4•·º¨·¾¾ÁÅ Ä—rƒ²Ê $'_$–ûþüÞA" vÌÆ¡ª¶îé¶\„"4€)’ÆÊûº¢­¼¾¾„ÅŒœÜÅÅ«M ƒ  3fA'›àªŸª¿äÕ¨k*‚?]A2€ & €º¼À¸¾ÀÅÀ„Å,À/‡Ï¨8   '«äžª¿äµN‚F¥¶vG0 8¶ººÄĉÅ-»» @Ö½[   DÙÚœª¿ä®Z„=®°¼¾©]:) [¸º©¯‰ÅÀºº°2.×Ä )„  €  jÞ¿š¶îݰ?†)Џ¾¼¼·vP:%s¸Å¼©¸‰Å-Á¼¼•ÇͲ}R#  ~ä̘ªÔÐ4 „B£±¼»ºº¾˜YH0€ Z¯ÅŶ¬«¿ˆÅ,Ä»ÁR²»|¨°o$ e߯—¶åÌY„Ÿ½¾ºº½¾¾»~J:*'€Å¸¨³ÀˆÅ½Â2«v H™»¨Jƒ ›ìƪ”й3ƒ&k¹…¼´iD.€Q›ÅÃÀ³«´¿†Å-¿Ã•m'·º§rN e¿ê‚åØÔÚ¶‡¶Ÿ„.€¯º¾º½¾¾ºº¾¾¬\:%„fÁÅÅÀ¯¨¨ˆÅžŠK,¾¼¶   € †Øå¸yI€<==]ªÔª…ÚD‚0t¡¼»¾º¾»ºº¾¾ºº§V5€ „ i·ÇÁŵ¬©»€Ä+ÅÄÅý½ t w!g™!($  €4.'=ªä¶„Æ'«ºº¼¼»½¼»»½½¼»¾§P% ƒ(5y˜«ÅËÉÉÁ­¬¶­¯±¯¯«3–¡E#20'   € !!"!",…ᶃÆ‚S°º½½ºº¾¾ºº»¾ººŽ@…‚&l×ÝÓÓÉÃÍÌÎó°®©°¨¬µ>xŒŒ )''€   #%"!$6®âª‚ÚS‚)g¤¸½¾»º€½©}XE)„€€žÙÜâêêÞÑ€ÍÒÒ̦££¡œC<   ) &*-!.sã¶‚ª×˜P‚dŠ©º½¾·†L<-&ƒ &‚ÎÛâíððôìÚÒÑÍÍÓŒIIOC €€€ €  !$PÙÚƒ¶âÐpƒ@i¬˜V99.%‚€! ŸÓÜêõúúý÷ðèáÖÓÓ»V6*€€€ „1"GÖ䄪¿Öµ` „ '065& €:ÑâèðõúüûýüúõôñóîT €+q<€Q<Û冪¿åÝ_ƒ &::( b×ððöùúúû€þýý€þä -   ƒ I5Ý䈪ÔáS<9,"—Ùðö÷ý‰þL‚ ˆ   ƒ NX6ÝÚŠ¶äΠd$.9(!*€½àðöøýýˆþÖ‚ ( &ƒ   € € H®Ýº4Fã¶‹ª¶ßñÆ#:0%€("Ááðöúú‰þú… € 2"    .–ßóä€Uäª ªçÍ+$<)€‚ÁáðöúýŠþ„$F‡`>:W  DˆÐäÔä’*$Œ¿Ž Ìë¨+9(€  ‚ÅáêöùüŠþŠƒ–†‹–¯Ç0   €  ëæÆªÚqLÖª¶åÒH(A'€€‚ÁáððûûŠþè‚7 È ”ޖްÈ    IíÔß߇$5Ò¶ŒÔá¥>'G$  ‚ÀáððøüˆþýõâY¼´£—ˆ“Ë´  " ƒ CÌíÍœV8¬ÔŠª¿î߀K$ ‚«áððøý‡þúøðÛY€ »ßǦz^YSF4$$ …  #)F\A$;ÍÔ‰¶îèÞ¨=ƒ>.‚    |Þèðñù„þûúúùñöðk€¼Ó°‹n@0))075  ‚ €  %€  *¿Ô‰ÔЙS„$%€!cÝâåíõüü‚þûøõóèßß/€ekN9,)'').71 !LZpv1€0F”áÔ‰а0„ Ha"‚ 9ÜÜâæðúúþþú öðæÝ¢j,€@4ƒ)132 olgm ƒ2œºº¬TOâñЉªÑB… m·©& ‚©ÜÜáæîï÷úùúøöïèÙü¦ve^Y19@<€0.€),72*+#8[i‚™½¾ºº¶„.“ã׉¿¿‚rª¹½»j „ sÒÜÝâäìöù÷øòèèÕÖÓ¶ÑÓ»„B!@@=<<0/€) 176  ƒ 5²»½»»¼¾¾¹l&€"’¶ˆªÈ„ K¡¸ºº¬1…%ŒÑÜÜßîööððâæÔÔ×ÏÊÔ׍ ƒO@<00€) 77* )„gº¾¾º½¾¾ºº¾¾¹Š7׉̇"ƒ &K’¸½¡1 O¸Sƒ s½ÜÝåìõõðáÚÒØÓÓÔØÓÐÉÒÒ»r?@@=10€)06/€ ƒH­»¼»º½¼»º½¾º¾¦7€J׊¶ÖÉZ ƒ -¹´y’º½B ƒ!²ÚâäððÝÕÓÖÙÙÖ€ÙÕØÚÜ»X@@>=7/&&)700ƒ$¦ºº½ºº¾½ºº¾¾»ºª€Iȶ‹ª¿ä“i3‚ “´¾–,€ V¹º¾»°g$„³ÜÜââÝÕÔÖÕÚÖÖÕÚÕÊH@@:00€)€7$ O˜½»¾º¾¾ºº¾¾ºº»¾r €7ÂÔŽª¿äÝn€C‚®¹¡oC$-SŒ¹»¾º½½¼©{)„ qÂÜßÜÕÔ××ÚÙ€×Ù×ÚØ¥––oaC<80V„‘Tƒ&ƒ»¾»¾º¾¼»¼¾¼»¼¼”-‚œêª¿åÌs €€ =”¾ºÂ½»¾½½ºº»¾º¾»»¾¾¼¦j…CÔèÕÖ€ÚÖ€ÚÖÚÚË €–—˜–i„X˜½¾º¾»¾ºº½¾ºº½ºK‚|哪ÚãTh§º½»‚¾ ½½º¾»»ºº½½µŠ-…£ØÓÕ€Ù×€ÙÖФ–€–”„cƒ K”µ»º¾º»»¾¾½º¾¾º“ ä”êe„ k´¾‚¼»»¾º½»¼¼»¾¼¾¡f1ƒ dl»€Õ×Õ×Öâ‘€–‘‘YC„)q³¾º¼¾º¼½½¼¼»¾¼´h €  §Ú•åd…P¢µ€º½½º¾»¾»¾º¾D…€Õ ÙÚÕÁ™––”Œl"†€¾½ºº¾¾»¾¾»»ºº¾»a‚ 3<$%$%Ñ¿• åf!„?žºº½½º¾º»»€º½º¾¹hƒ °ÀÏÒ¸š•’…o!„ 6œ¾¾»¾ºº»»º¾»¾¾¹§J‚ kˆ>3( @ક åf  U‹uC O‘­º¾º»½€»¼€»¾º¦„Kƒ &.Y}b.„ F†žµ½½º¾€» ½»¾º¾»‹/€ X¸ààÑ—3ä–åf)\––c& ‚dªº‚¾»€¾ ½½¾¾º½º¾º{.††jµº¾½ºº¾º½¾¾»¾º¾´GtçÆ¿Øª"³Ú–å_ 'b”–—˜\8‚M–²€»½» ¼»»½¼¼»½¼¼ s"Š5v˜½½»»½½»½¼»»½»¼¶—E€ªæª€ªÔ¯LzખåYg•€–œ•‘u( ‚ *oµ¾º¾ºº¾¾»»¾ºº¶ªr+‰ L¶½¾¾»º¾¾»¾¾ºº¾º¹„, ¥åƒ¶×Ôª—å\d‚–š›_„ kº¾ º¾¾ºº½½´´¦[6¡»€º ½¾ºº½ºº¾¾º»pƒ $¥å¡å_`®¨¢š–™––šœ‘G ‚!S‚°¼ºº»¹º°…_8!w®¹…¼º T€  &Q+ ¥å¡ å__º´²¥ƒ–›ŽVƒ p¨º½µ‡j.‚2$‚   l©½¾¾»¾ºº„€ .Q––8" ¥å¡ å_^º¾¹µ©Ÿœ‚–ššr2 3B†\‚ &Hk}|e$€ :^S1 D’³¸¼³˜m1PbŽŒ@¢å¡å\Vº½½º¹±ª¡›–™€–—‘tMƒ Dt‹’–——˜KUŽ”~Z61bi8€3^y…“–”š> Ÿå¡åV[ºº½½¾º´«¨›–š›–o-…@iŽ‚–Œ–BT…––‰wV2 ‡ :`ˆ–›¨:¢å¡å_\½¾»¼»º¼¹µ«¥Ÿœ—‚– ~U2 *MxŽƒ– — C WŽ–‰mI2‚(JgŒ€– ˜ž¨°5¢å¡å_^ºº½ºº¾¾»¾½³²§¡š– —–’V30=h„“–—ƒ– —£­®C Vœœ‚–‹~\? %>x—•€– œ£­¸¹,Ÿå¡åV^¾º¾¾ºº»»º¾ºº³®§ž‚–”Œ||‡”†–©±´´GS©¨¡˜ƒ–kA,$"6K{– ›¨°´º¾,¢å¡å8€]º¾»º€½¼€½º¾µ³¬¥ ž™–”––5”––˜ž¥¬µ¶µºJT°µ®¢ ™˜—––“ygZZdt‰š––˜¢°²¶½»»-Ÿå ªà€c¾ºº½¾¾»€¾º½¾¾»º¸²«¢œœ––•ƒ–•œ ©¶¸¹ºº¾ºHT¹¾¸´³¨¥–•””•–œ¡ª³¹º¾»ºº0¢å ¿ÞZ¾¾½ºº¾€º¾½ºº¾º´«¨¢ƒ–˜¥©´³¸¾‚ºITº¾¾»º´­¤‚–›––››¨²º¾º»¾¾º0¢å ÚÑV¼¼»¼¾º¼¼¾¼»¼¾º€¼¾½¸´·­­««¦¤«¨®µ¸¹¼¼º€¼,¾ºI^¹º¾»¼ºº²®«¢¢ŸŸœŸ¢©±´º½º¼¾¼º¼6Ÿå äÌ€Vºº¾¾º€¾ºº¾¾º¾º½º¾º½µº³€º¾»¾ºº»‚¾º¾K^º¾º½º¾º½º´²²€® ­©®´´º¾¾»¾¾€º› £ä åÌ€V¾ºº½€º½¾ºº½º¾º€¾ º»»¾º½ºº¾º½¾¾‚º'½ººP_º¾½½º¾½º¾¾½º´º¹¹´´¾¾ºº»»º¾½³‘9€ «Ú åÌ€[º»¼€»¼½º»¼»½º¾½½º»¾º»¾º¼½½º»¼»»¾K`¾½»»¾½º½»¾€º»»½€»½€»žO'Ƕ äÏ€I°º½½¾¾½º¾¾½½€¾»¾€º‚¾º¾¾º¾½ºº‚¾½½¾¾K_ºº½½ºº¾»€º½º‚¾ º½¾¾»»®›Dq⪠ÚÌ‚ D{¦¹»»½¼»»¼€»¼¼€½¼»½»»¼»»½½ƒ»¼€» J_½»¼¼½»¼€½¼¼‚» ½¼»»¼µ¦x:#iͶ¡¶à‚ :uªº½ºº¾º½½¾¾½º½ºº»»º¾¾»‚º¾€º ¾J_º¾»¾ºº¾»»º¾¾º½º¯‹E ‚vÌÖ¶£Ô¿ƒ (K‡±½¾º¾»»ºº»¾»¾¾½½¾ºº½‚¾º€¾ ºK_¾º½º¾¾º½½¾ºº¾¶¢‡>2ˆÓת¥ÔÃb) G‰°º¼9_޼º«w8€>ŠÃàÔ¨¶ØÌŒ-ƒ>i¨º¾º€¾‚º½ºº¾º½¾¾‚º½º¾ž € sº¾½º¾º¾º»»´¢c‰ÍéªÔÒ˜a/ D•µ½€º‚¾»¾¾º¾»ºº‚¾»¾»Œ€•¾º»¾º¾º¾»­„O7£ÒÔ®¶äÜÁŠ<  TНº‚½»½½»½¼»»‚½¼¼€½»½„€"¦¾»½¼€»¼»€½º±›F‚ˆÑå¶±ª¶îé¦\# $ZŸº¾ºº½ºº¾¾ƒº½€º»»¾ƒ€%¦¾º»€¾½½€ºµ¨Ž9‚ßתµÔÜJ ?j–·¾º¾¾»¾¾ººƒ¾»€¾½½ºƒ€%©º¾½€º»»¾½µšo$‚3£áÔ¹¶åÝŒY* ?“º½¼¼½»»¼‚½»½¼¼»ƒ€)©½½»¼º²¢€-‚“Ýä¶»ªÔá›V‚ ]¨ºº¾¾½‚º¾º¾»¾º|€0«º¾º½²˜r‚ªå¿ª¾¶äܹfƒ#}¬¹º»½¾º€½¾º½»ºo€6¯¾€»º¼«{/‚S´ÔªÁª¶îÝÊ>‚Nœ´¾»¾º¾»¾©K.«º±¤a ‚=»å¶Æª¿åÌKƒd¦ºº»»€º½º¾º½.4«¾¾¼«Œ@‚;ÀתɪÔت_!‚"BpŸ¸€¼»¾º¼¼™#€3¡·¨9 ‚<ŒÒÔͶîé«K„ S´º½º¾½ºŽ#o|KƒQÝå¶ÐÔÒ…7 ƒ 0Jr¢°¼¶c  * ‚"jÒÔªÓ¶ää¨j*ƒ  (WR‚‚ˆÐä¶Öª¿äãÁ¤9„€ƒ„*™Ø¿ªÙª¶îÝʇ:„ƒ‚+ÒÔªÞª¿äÖÆ”*ƒ'\¥Ýä¶âª¿äã´lT(C¨Ðä¿ªå ª¶îÝÞÅ”a6€4‹Ñ俪꪿ßêãаw@vÏïÆªµÿÿ¡ª¶Úä¨åäÚ¶ªÉ ¶âÜÙÝØÏÌÅÅ€Ì ÏÏÕØÛÕÏÏÌÏÒÕ“ØÛÝÙÜâ¶Çª¦J  €Œ =°ªÆÚX""€)..+))'%%"! XÚÆâ0)//€3232.0-,)(('%$!  ,âÆå 050,+**%%$! € ŒåÆå"2584-))  €–€åÆå *353( œ€,åÆ å )25+  €  ŒŠ€BåÆå*35)(6IY__ZL<+"!€!!&.71-$ƒ!‚€BåÆ å*35) #çÝÑÎÒÞòüþ)€ )þòéàÙÛæì÷‚þu‚€FåÆ å)20)GÔ΃ÍÔëüþ)€ +úëÖÎÍÍÎÓãøþu‚€BåÆå)20)%_ÎËËÇÍÍÎÖÞñúþ)€ 6ðÚÒÎÍÍÎÔÞó€þük€€BåÆå)20)3sÍÌÌÊÒÛßæîú‚þ)8åÓÎÍÍÏÙáçúþþê~ €BåÆ å)2+ .k€ÍÓÝçðööƒþ) GãÒÎÍÍÖëöþþõˆ! €I刪ÚðÚ¶¶å)1.'ZÐÍÏÞêôú…þ)@âÏÎÎÙíýþþâD €B凪ZÐÔµå(*)áÛßîöû†þ )GÝÒÎÔøþ£  € €Bå‡ÚRÔ´å '  TŸÚèðû†þ ) GãÒÎÝú€þ ò €Bå‡â ´¶³å $1<98/#(DƒÓƒþ);å×Óå€þ ‚   €å‡â €  媲 å*EGG>95)'€  ½‚þ)5ðâÖð€þ€  €å‡ Ú¯  ײå%MG=<-%" Kñþ)€*÷ïæ€þJ€ €ë¶¿××¶ª ¿Ê Ô°ªê)IE1"…þ)€!ýúûþþÑ  €Àæ×¶ÈÜ俪ªàr € YÔ¯ ¿·JE7 „è€þ)€)‚þ €   $Öä¶å ¹¶­ªäyE;( "AK;*!fùþþ)€)‚þÁ    ÈÐå¥  »Ú­¶ãf=+-40 [e8€”þþ)€)‚þ  €    &ÒÐç   € "ä­ ÚÑM2"/kxH € ) 0$øþ)€)‚þ¿   €    ²ðëw  å­ä¾B.""?c- $i±ÊѰbû)€)‚þÊ€& "8g  ~% (+  œ©8  ꪬå‚8'"%")[¡¶f9) NÎÔêâËÔfê)€)‚þ+á- £ÔÝæÞÓ¢ !»ÓÔÓn    ¿«ªàc8&&% QÐÔÔÓÔÔ¬5 QØêþûêñ€Ú)€)‚þ÷J JßêúóëÍœ (ÂÒãáϱ* €   € Ú«¿ªU8""3ÃÔÝãâà×Ò£"û‚þŸÅ)€)ƒþà ÜþõË;Väñùýúîâ^ €  äª ªånG,"ãêø€þûðÔƒþŸ¿)€)ƒþûR !ž‚þå6ʃþûŒ ‚  åª Ô»XE+…þ êJþËkD£þŸ«$€ %äèóý)•ûÔ3 `ú€þýþ®Gî„þØ    <å© ¶ØHM9"€þÚ„_„åþ}ò+¸%þŸ € +NJ?/@íþúç®ÊCÔ…þü € wä©ÚªDE/þþåT“Tþ¨Ý‰þŸ† «þþÄg0O:þþðèû‚þ € ˆÚ©ä|GB( þþl°¨)"þ¿Û=þŸ  !×þý€z†0P±ö¸rS¯úþ  ƒ  8±¶¨ÌëkE3 &êþAq þ¿Ô€þŸ€  ®þ¶4'wXÈ 8°cYòþ   ™Ô¨¶åáU<"  >ÔþA þ¿¶ €þ‰€  B0 -ÑTA ©* >Kòþ€    fÔ§ÔÒ¥Y9,€  §þK þ{DF bÐ? =RU !f q[«û€þû€ € "L–Ô¤ª¿Úäày 5'  kóW b 18 ‚ ‚“(  O \c:Ž€5ûþÛ€   (aµä¶£¶îèä̱U6  ¶W   € &’   ~Ra\ Ž€þýòo   %žâƪ¢ÔØ»y,1€   ’œ    @ ‚ $ \"’ûþüÛˆ4   sÌÆ¡ª¶îé¶V„ 2€  &[[8  „  ”G   € ƒ  .a6   #˜àªŸª¿äÕ¨h&‚ G51     „  S£, ‚   € !§äžª¿äµN‚E@ 50   ‰  >ŽX   €   ‚  BÙÚœª¿ä®Z„<  6(  ‰ +”ž   „  „   hÞ¿š¶îݰ?†(J€--+  ‰  .‡B) ‚  €       xä̘ªÔÐ4 „ ,D"   ˆ    ;M     €    b߯—¶åÌY„… 1/(      ˆ   #G*: „€     —ìÆª”й3ƒ† (B-      †  -       a¿ê‚åØÔÚ¶‡¶Ÿ„+!-‡ A$€  „ ˆ *6  € ƒ €  €ƒØâµyB‚6YªÔª…ÚD‚8 ˆ B4  „  = €   0  ‚    €.! €  5ªä¶„Æ ‰B" €   ƒ+4x–—¶™R,    ##     €  !…ᶃÆ‚1 Š=…  ‚ k×ÞÔÔɾ˹€     €  €   €  '®âª‚ÚS‚(* „ 2B& †  €ŸÛÝãêêßÔÍËÄȯ…8!!$         ‚  ) #nã¶‚ª×”N ‚&€')/9+% ƒ  ÓÜãíððôìÜÓÓÍËÔŒHHMB     ‚     €   DÙÚƒ¶âÐpƒ> .1,77+$‚ €! ¤ÔÝêõúúý÷ðèâÖÔÔ¿V5)  „ ‹   „  <Ö䄪¿Ö»\ „ -44 €  9ÑãèðõúüûýüúõôñóïR   ƒ „  €  €A 1Û冪¿åÝ_ƒ #88' € bÙððöùúúû€þýý€þå     €   €   ƒ 6 (Ý䈪ÔáS:7'"   –Úðö÷ý‰þJ‚    ‰   ƒ NU *ÙÚŠ¶äΠa +7'   )€¼áðöøýýˆþÕ‚    ƒ    € H®Ýº) :ã¶‹ª¶ßñÃ!7.$ € ' Àâðöúú‰þú…   €    €   +Žßóä~ I䪪çÐ*#:( ‚   ‚ÀâðöúýŠþ„&&:78F € € € €  €    DˆÖäÔä’ †¿Ž Ìë¨)5(    ‚ÃâêöùüŠþ‡ƒ›š†Š”¯Ã*  ‚  ææÆªÚq @Öª¶åÒD'A%€ ƒ €‚ÀâððûûŠþè‚ Î’Ž“Ž®È   €  € DíÔßß‚ $öŒÔá¥9&F#  €   ‚¾âððøüˆþýõã W¼´ ”ˆ“˲  €   „   @Ìí͘R +¬ÔŠª¿îßy€J  ‚¨âððøý‡þúøðÜY€ºàΤŒz[J&   …  &CM5 0ÇÔ‰¶îèÞ¤:ƒ;,   zàèðñù„þûúúùñöðk€¼Ô¬‹i €   ‚ € $€ €  ¿Ô‰ÔÐS„#" cÞãæíõüü‚þûøõóéàà,€ GŒK'  €  HNfn'ƒ€ :áÔ‰Ъ0„  G&    ‚ 9ÝÝãçðúúþþú öðæÞZ€„  fkam ƒKàñЉªÑB…Z   ‚©ÝÝâæîï÷úùúøöïè§  „ 1Uiƒ‚ ‘ã׉¿¿ƒ€   „rÖÝÞãåìöù÷øòèè2 € ‚‚  „‡"’¶ˆªÈ„    …$ÒÝÝàîööððãž   ‚‚    „ ˆ 7׉̇ƒ  €  "%ƒ r½ÝÞåìõõðÖQ€  €‚ ƒŠ€J׊¶ÖÉZ ƒ €,8ƒ  ±Üãåð丽„ Š€Fȶ‹ª¿ä“i3‚   /2„´ÝÝã㯈‚€ 1 ‰€7ÇÔŽª¿äÝn#  ‚„sÂÞà݈   ƒ ‰–꪿åÌs €€*J  Š …@Ô芀  „T+Š‚ u哪ÚãR1)  Š"…¡[† €„ Š € zä”êe „  ‹€./ƒ. „ ‚„( ‹   £Ú•åd…NZ‘A…ƒ €k †€‰‚ -7 Ê¿•åf  †4,!ƒ  ! „Œ‚ k‚3' 7ક åf/)  N ƒ; „ !‰€ X¸ààÑ" uä–åf  ‚.+††ŒqçÆ¿Øž ®Ú–å_  ‚ )  T Š*Œ€ªæª€ªÔ§>pÖª–åV ƒ ‚GŽ>‰ ' Œ‚¥åƒ¶×Ôª—å\†.„ .‹ ) 5&‹ 'ƒ!¥å¡å\ † ‚ ƒ‘( … € *¥å¡å\‰ƒ„ ‚  k„6€  7 ¥å¡ å\‡ ƒƒ €€*&  + ¢å¡å\‹ „€ €  '€   )¢å¡åV,Ž … ‚  ‡ ƒ&¢å¡å\ ‚‚  € †  ‚ € 0¢å¡å\†  ‚  Šƒ  ƒ  (¢å¡åV‰  … ˆ  …€‡*¢å¡å5€)Š …‡  $‚ „ &¢å ªà€Ž • ƒ ‚ „-¢å ¿Þ ƒ$“ „/¢å ÚÑ‘     †ƒ ƒ‡¢å äÏ€”  ˆ    ‡ £ä åÌ€§&‰  ˆ€ ¯Ú åÌ€§— €'Ƕ äÏ€ ¦—m⪠ÚÌ‚¦ “#iͶ¡¶à‚£ “‚vÌÖ¶£Ô¿ƒ¡‘ ‚2ˆÓת¥ÔÃ_'œ €>ÃàÔ¨¶ØÌ‰+ƒ ›€ 2Ž ‰ÍéªÔÒ”\- ˜ 0€9Œ 5ŸÒÔ®¶äÜÁ‡<– €Œ‚ŽÑå¶±ª¶îé¦V!—€Š‚ßתµÔÒœJ “€‡‚3£áÔ¹¶åÝŒY'’€… ‚Ýä¶»ªÔáÉ™V‚‘ €…€‚ªå¿ª¾¶äܹcƒ! ‹ (€ƒ‚S´ÔªÁª¶îÝÊ<‚9+ Š&? ‚ ‚;»å¶Æª¿åÌHƒ & Š+‚‚8ÀתɪÔàª\ƒ 1… "€€‚9ŒÒÔͶîé¶H„6ƒ‚ƒNÝå¶ÐÔÒ…5 ƒ G  ‚"fÒÔªÓ¶äÝ¥j&ƒ  ‚‚ˆÐä¶Öª¿äãÉ¡9„€ ƒ„'™Ø¿ªÙª¶îÝÊ5„ƒ‚)}ÒÔªÞª¿äÖÊ‘(ƒ#Y¥Ýä¶âª¿äã°oO$>¥Ð俪媶îÝÞÅ”]53ŽÑ俪꪿ßêãÑ®v> vÏïÆªµt8mk@%=KOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPOK=%>g‘¨¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¨‘g>7}´×æëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëæ×´}7J£ÞöüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüöÞ£JO®êüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüê®OP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯P6E;! P¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯P7xš‹Y( P¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PI ÓΞZ"P¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯PK¦ãîÑ‘DP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë¯Q=‘Øôë»n- Q¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýì´X 'nÂðöÝ¥`) W´ìýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþñÃt5'88%W´ìûóס^( 'nÂñþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøÞªu_nЉhD&Q¯ëýüóÖŸZ!E–ÚøþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýôßĹÂÔÓº–iC! P¯ëýÿüòÐŒ<%iºìüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýøñîñööìÙºV" Q°ëýÿÿûæ§K=‘Ø÷þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþýþþþü÷ëΑI"(^µíýÿÿýë¯PK¨æüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþûëÀ‚]_‡Èñþÿÿýì´WP¯ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøåȶ¶ÈæùþÿÿþñÂn'W´ìýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýùñííñùýÿÿÿþ÷Ø‘='nÂñþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþýýþþÿÿÿÿÿüæ¨KE–Úøþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë®P -n¼ìüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýë®P![¤Ýøþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûæ§K<ÑóýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüòÐŒ<L¨æûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüòÖŸZ!X³ìýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþü÷ëÒŸ^( 3tÃñþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýøíÙº‘Z(  "DoªÞøþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøåÀ—iC" .[‘¼ÞôýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüíÀ}I&'=LWr¤ÒëøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøÚ—J  !Sr¤Ñçð÷üýþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüæ¨L&Di‘­ÃÞóûýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ÷Ø‘=&Di–»ØèðøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþñÂn''Di–»Ùì÷üýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýî¸_ !h•»Ùìøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþöב=&Di–¼Ýóüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüæ¨K&En¤Òë÷üýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþýþþÿÿýê®O-[‘ºØèñùýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüøñîñùýÿüæ¨K "Ci‘®Èæùþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþü÷ìÚÃºÉæùý÷Ø‘=%>Y†ÈñþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýøìÙ»–pe‡Èñûìºi%%^µíýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýôÞ¼–iD),_¶ìõÙ–ER°ëýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþøÞªoE& Y´êéºi&X´ìýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþñÃt3 /sÁåÑ‘C3tÃñþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýí´Z /a¤ÔОZ" "DoªÞøþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýí¶_,)>Sr¤ÌÌ ^( .[‘¼Þôýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþñȇeo’¬¾ÍÈ^) '>Sr¤ÒëøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþùæÉºÃ×ãØ»’Z(  !Sr¤Òëøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþü÷ëÒ _-.[‘»ÝóüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýøìÙº‘Z)  "Cn¤Òë÷üýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüóݼ–iC" -[‘ºØèðøüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýøëÒ¤nE& "Ci‘¬ÁÚìøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüóݼ‘[-%>Rn–¼ÝóûýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüòÖ¥nC" 'En¤ÑçðøýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýøëÒ _--[¬ÃÞóüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþüóÝ»‘Z)  !Rn–»Ùì÷üýþÿÿÿÿÿÿÿÿÿÿÿþü÷ìÙº‘[-'Di–»Øèð÷üýþÿÿÿÿÿÿþü÷ìÙ»–iC" &Di‘¬ÁØèñùýÿÿÿÿýøíÙ»–iD&%>Rm’®ÈæùþÿÿþùåÁ—jD&'>Y†ÈñþÿÿþñÈ‚K'%^µíýÿÿýíµ\! bochs-2.6/build/macosx/Info.plist.in0000644000175000017500000000165112020641473017305 0ustar guillemguillem CFBundleDevelopmentRegion English CFBundleExecutable bochs CFBundleGetInfoString @VERSION@ Carbon CFBundleIconFile bochs-icn CFBundleIdentifier net.sourceforge.bochs.bochs CFBundleInfoDictionaryVersion 6.0 CFBundleName Bochs Carbon @VERSION@ CFBundlePackageType APPL CFBundleShortVersionString Bochs Carbon (@VERSION@) CFBundleSignature BOCHS CFBundleVersion @VERSION@ CSResourcesFileMapped bochs-2.6/build/macosx/README.macosx-binary0000644000175000017500000000000012020641473020346 0ustar guillemguillembochs-2.6/build/macosx/script.data0000644000175000017500000003272412020641473017074 0ustar guillemguillemþíúÎ •8__PAGEZERO__TEXT __text__TEXT(xx€__cstring__TEXT-œ__picsymbol_stub__TEXT.,Ô,€$Œ__DATA0 __data__DATA0 __la_symbol_ptr__DATA0 4  __nl_symbol_ptr__DATA0T T__dyld__DATA0d d__common__DATA0€<8__LINKEDIT@Ô0Ô /usr/lib/dyld d<ö*¬/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices 4<õ¨L;/usr/lib/libSystem.B.dylibh`/System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServicesÀŸ0/usr/lib/libSystem.B.dylib #"$€ @d¨Aù ¡\€$€‚A„º<úÏ€²´Yþÿÿÿÿÿ„8ðÿýþÿÿÿÿð†Àøºð2fìÀæ2ÑM< HD| P®,@‚ÿà,A‚ 8H€=? L¦ëx€,A‚„,@‚ÿøƒãxÄóx¥ëx8ÆHHõ|¦“áÿü”!ÿ BŸè¦<8c\8@H}€@| x|¦N€!€h8!`|¦ƒáÿüN€ =`k0d,‹A†N€ 8 N8€`„-Ü8`8D8`;8Dà=€€ 0d| ¦=€aŒN€ =`k0h}i¦N€ |¦¿¡ÿô”!ÿ |> x~xž|8`8€(H…|`x@>@€x >@€| >@8( ƒ¾@8`-H)}8`-€ž@Hõ€!€|¦»¡ÿôN€ |¦¿Áÿø”!ÿ |> x~xž|8H8`-HÙ~@8@D>D€ ,@‚Hx>D))€x| @‚L>D))€|| @‚4>D€ H~D>H€  >H€ ,(A‚H>D)8 DKÿÿ|8`-€ž@H€H,A‚4>H€ ,A‚>H€ €~H| x|¦N€!€~HH‘€!€|¦»ÁÿøN€ |¦¿Áÿø”!ÿ |> xBŸè¦H9=?)¼€ @€@,A‚>@  T>(@H=?€ixHÕ=?€itH¥€!€|¦»ÁÿøN€ |¦9 8”!ÿ aD8a@°B™!A™!@H©€h8!`|¦N€ <`ap<€sc|¦`„pt`clt”!ÿ°HU,8A‚ Kÿÿ™8|x€X8!P|¦N€ __dyld_mod_term_funcs__dyld_make_delayed_module_initializer_callsThe kernel support for the dynamic linker is not present to run this program. |¦BŸ}h¦=k|¦‹ì}‰¦9kìN€ |¦BŸ}h¦=k|¦‹Ì}‰¦9kÌN€ |¦BŸ}h¦=k|¦‹¬}‰¦9k¬N€ |¦BŸ}h¦=k|¦‹Œ}‰¦9kŒN€ |¦BŸ}h¦=k|¦‹l}‰¦9klN€ |¦BŸ}h¦=k|¦‹L}‰¦9kLN€ |¦BŸ}h¦=k|¦‹,}‰¦9k,N€ |¦BŸ}h¦=k|¦‹ }‰¦9k N€ |¦BŸ}h¦=k|¦‹ì}‰¦9kìN€ |¦BŸ}h¦=k|¦‹Ì}‰¦9kÌN€ |¦BŸ}h¦=k|¦‹¬}‰¦9k¬N€ |¦BŸ}h¦=k|¦‹Œ}‰¦9kŒN€ |¦BŸ}h¦=k|¦‹l}‰¦9klN€ -0„,Œ+p*ìI —àà—`‚@‹ +€(• ‹`…`&lŒ$zÄ ÐÀ \ ˜ |*Ä©0(*Ä©0$*Ä©0 *Ä©0H*Ä©0D*Ä©0@*Ä©0<*Ä©08*Ä©04*Ä©00*Ä©0,*Ä©0P*Ä©0L*Ä0 00 40ˆK0Œh0Ž0”¡0˜»0œÖ0 ó0¤ 0¨.0¬P0°t0´•0ž0¸¯ $zÄÆ &lŒÜ àÿ  |  \' ‚@J —`p ‹ ~ ‹`¤ • Ì (Ó —àÛ …`ã  ÐÀê I ð +€ö  ˜`³lŒŽ˜™Qm‘J¶ ! !"_NXArgc_NXArgv___progname__mh_execute_header_catch_exception_raise_catch_exception_raise_state_catch_exception_raise_state_identity_clock_alarm_reply_do_mach_notify_dead_name_do_mach_notify_no_senders_do_mach_notify_port_deleted_do_mach_notify_send_once_do_seqnos_mach_notify_dead_name_do_seqnos_mach_notify_no_senders_do_seqnos_mach_notify_port_deleted_do_seqnos_mach_notify_send_once_environ_receive_samples_CallComponentDispatch_OpenDefaultComponent___keymgr_dwarf2_register_sections___keymgr_global__cthread_init_routine__dyld_register_func_for_add_image__dyld_register_func_for_remove_image__init_keymgr__keymgr_get_and_lock_processwide_ptr__keymgr_set_and_unlock_processwide_ptr_abort_atexit_calloc_errno_exit_free_mach_init_routinebochs-2.6/build/macosx/pbdevelopment.plist0000644000175000017500000000037612020641473020654 0ustar guillemguillem PBXProjectSourcePath /Users/bryce/bochs/bochs/bochs.pbproj bochs-2.6/build/macosx/diskimage.pl0000755000175000017500000000624112020641473017225 0ustar guillemguillem#!/usr/bin/perl # # # Copyright (C) 1991-2002 and beyond by Bungie Studios, Inc. # and the "Aleph One" developers. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # This license is contained in the file "COPYING", # which is included with this source code; it is available online at # http://www.gnu.org/licenses/gpl.html # # my $fullfolderPath = shift(@ARGV); die "err: No folder specified" unless defined($fullfolderPath) && length($fullfolderPath); $fullfolderPath =~ s{/$}{}; $fullfolderPath =~ m{([^/]+)$}; local $folderName = $1; local $folderSize = undef; local $imageName = "'$fullfolderPath.dmg'"; local $imageSectors = undef; local $imageTemp = "'$fullfolderPath-tmp.dmg'"; local $mount_point = "bochs-image-mount"; die "err: $folderName is not a directory\n" if(!-d $fullfolderPath); # Know a better way to get the first value from du? ($folderSize) = split(m/ /, `du -s "$fullfolderPath"`); die "err: du failed with $?\n" if($?); # Inflate $folderSize for disk image overhead. Minimum 5 MB disk local $fiveMBImage=20*(2048); # BBD: I had to raise this to 20meg or the ditto command would run # out of disk space. Apparently the technique of measuring the # amount of space required is not working right. $imageSectors = $folderSize + int($folderSize * 0.15); if($imageSectors < $fiveMBImage) { $imageSectors = $fiveMBImage; } print "Minimum sectors = $fiveMBImage\n"; print "Folder sectors = $folderSize\n"; print "Image sectors = $imageSectors\n"; # Create image, overwriting prior version `hdiutil create -ov -sectors $imageSectors $imageTemp`; die "err: hdiutil create failed with $?\n" if($?); # Initialize the image local $hdid_info=`hdid -nomount $imageTemp`; die "err: hdid -nomount failed with $?\n" if($?); $hdid_info =~ s/( |\t|\n)+/~!/g; local (@hdid_info) = split(m/~!/, $hdid_info); local ($disk_dev, $hfs_dev); $disk_dev = $hdid_info[0]; $hfs_dev = $hdid_info[4]; $mount_dev = $hdid_info[4]; $disk_dev =~ s{/dev/}{}; $hfs_dev =~ s/disk/rdisk/; `newfs_hfs -v "$folderName" $hfs_dev`; if($?) { local $err = $?; `hdiutil eject $disk_dev`; die "err: newfs_hfs failed with $err\n"; } # Fill the image `mkdir $mount_point`; `/sbin/mount -t hfs $mount_dev $mount_point`; if($?) { local $err = $?; `hdiutil eject $disk_dev`; die "err: mount failed with $err\n"; } `ditto -rsrcFork "$fullfolderPath" $mount_point`; if($?) { local $err = $?; `umount $mount_dev`; `hdiutil eject $disk_dev`; `rmdir $mount_point`; die "err: ditto failed with $err\n"; } `umount $mount_dev`; `hdiutil eject $disk_dev`; `rmdir $mount_point`; # Create the compressed image `hdiutil convert $imageTemp -format UDCO -o $imageName`; die "err: hdiutil convert failed with $?\n" if($?); `rm $imageTemp`; print "$imageName is your new diskimage\n"; bochs-2.6/build/macosx/bochs.applescript0000644000175000017500000000455412020641473020303 0ustar guillemguillemproperty bochs_path : "Contents/MacOS/bochs" property bochs_app : "" on run tell application "Finder" to get container of (path to me) as string set script_path to POSIX path of result -- Locate bochs set bochs_alias to findBochs() -- Tell Terminal to run bochs from the command line --Use the script's directory as the current directory tell application "Terminal" activate do script "cd '" & script_path & "';exec '" & (POSIX path of bochs_app) & bochs_path&"'" -- Wait for Terminal to change the name first, then change it to ours delay 1 set AppleScript's text item delimiters to "/" set the text_item_list to every text item of the script_path set AppleScript's text item delimiters to "" set next_to_last to ((count of text_item_list) - 1) set the folder_name to item next_to_last of text_item_list set name of front window to "Running bochs in ../" & folder_name & "/" end tell end run -- Taken from examples at http://www.applescriptsourcebook.com/tips/findlibrary.html to Hunt for itemName at folderList --Returns path to itemName as string, or empty string if not found repeat with aFolder in folderList try if class of aFolder is constant then return alias ((path to aFolder as string) & itemName) as string else if folder of (info for alias aFolder) then return alias (aFolder & itemName) as string end if on error number -43 --item not there, go to next folder end try end repeat return "" --return empty string if item not found end Hunt on findBochs() try if bochs_app is "" then error number -43 return alias bochs_app on error number -43 -- bochs_app no good, go hunting try tell application "Finder" to get container of (path to me) as string set this_dir_alias to alias result tell application "Finder" to get container of (this_dir_alias) as string set one_up_dir_alias to alias result set TheUsualPlaces to {this_dir_alias as string, one_up_dir_alias as string} Hunt for "bochs.app" at TheUsualPlaces set result_alias to result if result_alias is "" then error number -43 set bochs_app to result_alias as string return result_alias on error number -43 --Give up seeking, Ask the user choose application with prompt "Please locate Bochs:" as alias set result_alias to result set bochs_app to result_alias as string return result_alias end try end try end findBochsbochs-2.6/build/macosx/make-dmg.sh0000755000175000017500000000514012020641473016746 0ustar guillemguillem#!/bin/sh # # $Id: make-dmg.sh 10213 2011-02-25 15:32:08Z sshwarts $ # # Make a DMG of Bochs. This script must be run from the main source # directory, e.g. "./build/macosx/make-dmg.sh". If you haven't run # configure yet, it runs .conf.macosx for you. Then it creates a # temporary directory _dmg_top and does a make install into that # directory, and builds a disk image. At the end it cleans up the # temporary directory. # VERSION=@VERSION@ # substituted in with configure script VERSION=2.0.pre4 BUILDROOT=./_dmg_top INSTALL_PREFIX=$BUILDROOT/Bochs-${VERSION} DMG=./Bochs-${VERSION}.dmg # test if we're in the right directory. if not, bomb. echo '-- Is the script run from the right directory?' if test -f main.cc -a -f bochs.h; then echo yes else echo no echo ERROR: Run it from the top of the Bochs source tree, where bochs.h is found. exit 10 fi # test if configure has been run already. if not, run .conf.macosx. configured=0 echo '-- Has configure been run already?' if test -f config.h -a -f Makefile; then echo yes else echo no. I will run .conf.macosx now. /bin/sh -x .conf.macosx conf_retcode=$? configured=1 if test "$conf_retcode" != 0; then echo ERROR: configure failed. Correct errors in .conf.macosx and try again. exit 20 fi fi # remove any leftovers from previous image creation. echo "-- Removing leftovers from previous runs" rm -rf ${BUILDROOT} ${BUILDROOT}.dmg ${DMG} # make new buildroot directory echo "-- Making ${BUILDROOT} directory" mkdir ${BUILDROOT} && mkdir ${INSTALL_PREFIX} if test $? != 0; then echo ERROR: mkdir ${BUILDROOT} or mkdir ${INSTALL_PREFIX} failed exit 30 fi # run make and then make install into it echo "-- Running make" make if test $? != 0; then echo ERROR: make failed exit 40 fi echo "-- Running make install with prefix=${INSTALL_PREFIX}" make install prefix=${INSTALL_PREFIX} if test $? != 0; then echo ERROR: make install with prefix=${INSTALL_PREFIX} failed exit 50 fi # create new disk image echo "-- Making a disk image with root at ${BUILDROOT}, using diskimage.pl" ./build/macosx/diskimage.pl ${BUILDROOT} if test $? != 0; then echo ERROR: diskimage.pl script failed exit 60 fi if test ! -f ${BUILDROOT}.dmg; then echo ERROR: diskimage.pl succeeded but I cannot find the image ${BUILDROOT}.dmg. exit 70 fi # rename to the right thing echo "-- Renaming the output disk image to ${DMG}" mv ${BUILDROOT}.dmg ${DMG} if test $? != 0; then echo ERROR: rename failed exit 80 fi echo "-- Done! The final disk image is " ls -l ${DMG} echo "-- Cleaning up the temporary files in ${BUILDROOT}" rm -rf ${BUILDROOT} exit 0 bochs-2.6/build/macosx/bochs.r0000644000175000017500000030114312020641473016210 0ustar guillemguillemdata 'BNDL' (128) { $"426F 6368 0000 0001 4652 4546 0000 0000" /* Boch....FREF.... */ $"0080 4943 4E23 0000 0000 0080" /* .€ICN#.....€ */ }; data 'Boch' (0, "Owner resource") { $"00" /* . */ }; data 'FREF' (128) { $"4150 504C 0000 00" /* APPL... */ }; data 'icl4' (128) { $"0000 0000 0000 000F F000 00FF FF00 0000" /* ........ð..ÿÿ... */ $"0000 0000 0000 00FC CF0F FFFC CF00 0000" /* .......üÏ.ÿüÏ... */ $"0000 0000 0000 0FCC BBFC DF1F 3F00 0000" /* .......Ì»üß.?... */ $"0000 0000 0000 FCCB BFCD F1DF FF00 0000" /* ......üË¿Íñßÿ... */ $"0000 0000 000F CCCF FCDF 1DFF DDF0 0000" /* ......ÌÏüß.ÿÝð.. */ $"0000 0000 00FC CFFF CDF1 DFFD DDCF 0000" /* .....üÏÿÍñßýÝÏ.. */ $"0000 0000 0FCC FFFC DF1D FFFD DCCC F000" /* .....Ìÿüß.ÿýÜÌð. */ $"0000 0000 FCCF FFFD F1DF FFFD CCCC CFFF" /* ....üÏÿýñßÿýÌÌÏÿ */ $"0000 000F CCFF FFFF 1FFF FFCC CCCC DFFF" /* ....Ìÿÿÿ.ÿÿÌÌÌßÿ */ $"0000 00FC CFFF FFF1 FCCC CCCC CCCC DFFF" /* ...üÏÿÿñüÌÌÌÌÌßÿ */ $"0000 0FCC FFFC CFFD FFFD DDDC CCCC DFFF" /* ...ÌÿüÏýÿýÝÜÌÌßÿ */ $"0000 FCCF FFCC CFFF FFFF FFDD DDCC DFFF" /* ..üÏÿÌÏÿÿÿÿÝÝÌßÿ */ $"000F CCFF FCFF FFCC FFF9 99FF FFDD DFFF" /* ..ÌÿüÿÿÌÿù™ÿÿÝßÿ */ $"00FC CFFF CCFF FFCC FFF0 0000 FFFF FFFF" /* .üÏÿÌÿÿÌÿð..ÿÿÿÿ */ $"0FCC CFFC FFCF FFCF FFF0 0000 0F99 FFFF" /* .ÌÏüÿÏÿÏÿð...™ÿÿ */ $"FCCC FFCC FFFC FCFF FFFF FFF0 0FFF FBBF" /* üÌÿÌÿüüÿÿÿÿð.ÿû¿ */ $"FCCC FFCC FFFF CFFF F00F FFF0 0FFF BBBF" /* üÌÿÌÿÿÏÿð.ÿð.ÿ»¿ */ $"0FCC CFFF FFFC FFFF F00F FFF0 0FFB BBF0" /* .ÌÏÿÿüÿÿð.ÿð.û»ð */ $"00FC CFFF CCCF F000 FFF0 0FF0 0FFB BF00" /* .üÏÿÌÏð.ÿð.ð.û¿. */ $"000F CCFF CCFF 0000 FFF0 0FFF FFBB F000" /* ..ÌÿÌÿ..ÿð.ÿÿ»ð. */ $"0000 FCCF FFF0 0FFF FFFF FFFF FBBF 0000" /* ..üÏÿð.ÿÿÿÿÿû¿.. */ $"0000 0FCC FFF0 0FFF F00F FFFF BBFD DDDD" /* ...Ìÿð.ÿð.ÿÿ»ýÝÝ */ $"0000 00FC CFF0 0FFF F00F FFFB BFEE EEED" /* ...üÏð.ÿð.ÿû¿îîí */ $"0000 000F CCFF 00FF F00F FFBB FEEE EEE0" /* ....Ìÿ.ÿð.ÿ»þîîà */ $"0000 0000 FCCF F000 00FF FBBF AAEE EE00" /* ....üÏð..ÿû¿ªîî. */ $"0000 0000 0FCC FF00 0FFF BBFA AEEE E000" /* .....Ìÿ..ÿ»ú®îà. */ $"0000 0000 00FC CFFF FFF8 8FAA EEE0 0000" /* .....üÏÿÿøªîà.. */ $"0000 0000 000F CCCF FB88 FAEE E000 0000" /* ......ÌÏûˆúîà... */ $"0000 0000 0000 FCCB B88F EEE0 0000 0000" /* ......ü˸îà.... */ $"0000 0000 0000 0FCC BBFE EE00 0000 0000" /* .......Ì»þî..... */ $"0000 0000 0000 00FC CFEE 0000 0000 0000" /* .......üÏî...... */ $"0000 0000 0000 000F FE00 0000 0000 0000" /* ........þ....... */ }; data 'icl8' (128) { $"0000 0000 0000 0000 0000 0000 0000 00FF" /* ...............ÿ */ $"FF00 0000 0000 FFFF FFFF 0000 0000 0000" /* ÿ.....ÿÿÿÿ...... */ $"0000 0000 0000 0000 0000 0000 0000 FF2C" /* ..............ÿ, */ $"2CFF 00FF FFFF FF13 13FF 0000 0000 0000" /* ,ÿ.ÿÿÿÿ..ÿ...... */ $"0000 0000 0000 0000 0000 0000 00FF 2C2C" /* .............ÿ,, */ $"3434 FF08 33FF 05FF D8FF 0000 0000 0000" /* 44ÿ.3ÿ.ÿØÿ...... */ $"0000 0000 0000 0000 0000 0000 FF2C 2C34" /* ............ÿ,,4 */ $"34FF 0833 FF05 33FF FFFF 0000 0000 0000" /* 4ÿ.3ÿ.3ÿÿÿ...... */ $"0000 0000 0000 0000 0000 00FF 2C2C 2CFF" /* ...........ÿ,,,ÿ */ $"FF08 33FF 0533 FFFF 3333 FF00 0000 0000" /* ÿ.3ÿ.3ÿÿ33ÿ..... */ $"0000 0000 0000 0000 0000 FF2C 2CFF FFFF" /* ..........ÿ,,ÿÿÿ */ $"0833 FF05 33FF FF33 3333 08FF 0000 0000" /* .3ÿ.3ÿÿ333.ÿ.... */ $"0000 0000 0000 0000 00FF 2C2C FFFF FF08" /* .........ÿ,,ÿÿÿ. */ $"33FF 0533 FFFF FF33 3308 0808 FF00 0000" /* 3ÿ.3ÿÿÿ33...ÿ... */ $"0000 0000 0000 0000 FF2C 2CFF FFFF FF33" /* ........ÿ,,ÿÿÿÿ3 */ $"FF05 33FF FFFF FF33 0808 0808 08FF FFFF" /* ÿ.3ÿÿÿÿ3.....ÿÿÿ */ $"0000 0000 0000 00FF 2C2C FFFF FFFF FFFF" /* .......ÿ,,ÿÿÿÿÿÿ */ $"05FF FFFF FFFF 0808 0808 0808 33FF FFFF" /* .ÿÿÿÿÿ......3ÿÿÿ */ $"0000 0000 0000 FF2C 2CFF FFFF FFFF FF05" /* ......ÿ,,ÿÿÿÿÿÿ. */ $"FF08 0808 0808 0808 0808 0808 33FF FFFF" /* ÿ...........3ÿÿÿ */ $"0000 0000 00FF 2C2C FFFF FF2A 2AFF FF33" /* .....ÿ,,ÿÿÿ**ÿÿ3 */ $"FFFF FF33 3333 3308 0808 0808 33FF FFFF" /* ÿÿÿ3333.....3ÿÿÿ */ $"0000 0000 FF2C 2CFF FFFF 2A2A 2AFF FFFF" /* ....ÿ,,ÿÿÿ***ÿÿÿ */ $"FFFF FFFF FFFF 3333 3333 0808 33FF FFFF" /* ÿÿÿÿÿÿ3333..3ÿÿÿ */ $"0000 00FF 2C2C FFFF FF2A FFFF FFFF 2A2A" /* ...ÿ,,ÿÿÿ*ÿÿÿÿ** */ $"FFFF FFE8 E8E8 FFFF FFFF 3333 33FF FFFF" /* ÿÿÿèèèÿÿÿÿ333ÿÿÿ */ $"0000 FF2C 2CFF FFFF 2A2A FFFF FFFF 2A2A" /* ..ÿ,,ÿÿÿ**ÿÿÿÿ** */ $"FFFF FF00 0000 0000 FFFF FFFF FFFF FFFF" /* ÿÿÿ.....ÿÿÿÿÿÿÿÿ */ $"00FF 2C2C 2CFF FF2A FFFF 2AFF FFFF 2AFF" /* .ÿ,,,ÿÿ*ÿÿ*ÿÿÿ*ÿ */ $"FFFF FF00 0000 0000 00FF E8E8 FFFF FFFF" /* ÿÿÿ......ÿèèÿÿÿÿ */ $"FF2C 2C2C FFFF 2A2A FFFF FF2A FF2A FFFF" /* ÿ,,,ÿÿ**ÿÿÿ*ÿ*ÿÿ */ $"FFFF FFFF FFFF FF00 00FF FFFF FF34 34FF" /* ÿÿÿÿÿÿÿ..ÿÿÿÿ44ÿ */ $"FF2C 2C2C FFFF 2A2A FFFF FFFF 2AFF FFFF" /* ÿ,,,ÿÿ**ÿÿÿÿ*ÿÿÿ */ $"FF00 00FF FFFF FF00 00FF FFFF 3434 34FF" /* ÿ..ÿÿÿÿ..ÿÿÿ444ÿ */ $"00FF 2C2C 2CFF FFFF FFFF FF2A FFFF FFFF" /* .ÿ,,,ÿÿÿÿÿÿ*ÿÿÿÿ */ $"FF00 00FF FFFF FF00 00FF FF34 3434 FF00" /* ÿ..ÿÿÿÿ..ÿÿ444ÿ. */ $"0000 FF2C 2CFF FFFF 2A2A 2AFF FF00 0000" /* ..ÿ,,ÿÿÿ***ÿÿ... */ $"FFFF FF00 00FF FF00 00FF FF34 34FF 0000" /* ÿÿÿ..ÿÿ..ÿÿ44ÿ.. */ $"0000 00FF 2C2C FFFF 2A2A FFFF 0000 0000" /* ...ÿ,,ÿÿ**ÿÿ.... */ $"FFFF FF00 00FF FFFF FFFF 3434 FF00 0000" /* ÿÿÿ..ÿÿÿÿÿ44ÿ... */ $"0000 0000 FF2C 2CFF FFFF FF00 00FF FFFF" /* ....ÿ,,ÿÿÿÿ..ÿÿÿ */ $"FFFF FFFF FFFF FFFF FF34 34FF 0000 0000" /* ÿÿÿÿÿÿÿÿÿ44ÿ.... */ $"0000 0000 00FF 2C2C FFFF FF00 00FF FFFF" /* .....ÿ,,ÿÿÿ..ÿÿÿ */ $"FF00 00FF FFFF FFFF 3434 FFFA FAFA FAFA" /* ÿ..ÿÿÿÿÿ44ÿúúúúú */ $"0000 0000 0000 FF2C 2CFF FF00 00FF FFFF" /* ......ÿ,,ÿÿ..ÿÿÿ */ $"FF00 00FF FFFF FF34 34FF FBFB FBFB FBFA" /* ÿ..ÿÿÿÿ44ÿûûûûûú */ $"0000 0000 0000 00FF 2C2C FFFF 0000 FFFF" /* .......ÿ,,ÿÿ..ÿÿ */ $"FF00 00FF FFFF 3434 FFFB FBFB FBFB FB00" /* ÿ..ÿÿÿ44ÿûûûûûû. */ $"0000 0000 0000 0000 FF2C 2CFF FF00 0000" /* ........ÿ,,ÿÿ... */ $"0000 FFFF FF34 34FF FDFD FCFC FCFB 0000" /* ..ÿÿÿ44ÿýýüüüû.. */ $"0000 0000 0000 0000 00FF 2C2C FFFF 0000" /* .........ÿ,,ÿÿ.. */ $"00FF FFFF 3434 FFFD FDFC FCFB FB00 0000" /* .ÿÿÿ44ÿýýüüûû... */ $"0000 0000 0000 0000 0000 FF2C 2CFF FFFF" /* ..........ÿ,,ÿÿÿ */ $"FFFF FFE1 E1FF FDFD FCFB FB00 0000 0000" /* ÿÿÿááÿýýüûû..... */ $"0000 0000 0000 0000 0000 00FF 2C2C 2CFF" /* ...........ÿ,,,ÿ */ $"FF34 E1E1 FFFD FCFB FB00 0000 0000 0000" /* ÿ4ááÿýüûû....... */ $"0000 0000 0000 0000 0000 0000 FF2C 2C34" /* ............ÿ,,4 */ $"34E1 E1FF FCFB FB00 0000 0000 0000 0000" /* 4ááÿüûû......... */ $"0000 0000 0000 0000 0000 0000 00FF 2C2C" /* .............ÿ,, */ $"3434 FFFB FBFB 0000 0000 0000 0000 0000" /* 44ÿûûû.......... */ $"0000 0000 0000 0000 0000 0000 0000 FF2C" /* ..............ÿ, */ $"2CFF FBFB 0000 0000 0000 0000 0000 0000" /* ,ÿûû............ */ $"0000 0000 0000 0000 0000 0000 0000 00FF" /* ...............ÿ */ $"FFFB 0000 0000 0000 0000 0000 0000 0000" /* ÿû.............. */ }; data 'icl8' (129) { $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FF00 0000 0000 0000 0000 0000 0000 0000" /* ÿ............... */ $"0000 0000 0000 0000 0000 0000 0000 00FF" /* ...............ÿ */ $"FF00 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B" /* ÿ.++++++++++++++ */ $"2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B F9FF" /* ++++++++++++++ùÿ */ $"FF00 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B" /* ÿ.++++++++++++++ */ $"2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2BF9 F9FF" /* +++++++++++++ùùÿ */ $"FF00 2B2B 2B00 0000 0000 0000 0000 0000" /* ÿ.+++........... */ $"0000 0000 0000 0000 0000 0000 F9F9 F9FF" /* ............ùùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF 2A2A FFFF" /* ÿ.++.ÿÿÿÿÿÿÿ**ÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF 00F9 F9FF" /* ÿÿÿÿÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FF2A 2A2A FFFF" /* ÿ.++.ÿÿÿÿÿÿ***ÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF 00F9 F9FF" /* ÿÿÿÿÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF 2AFF FFFF FF2A" /* ÿ.++.ÿÿÿÿÿ*ÿÿÿÿ* */ $"2AFF FFFF FFFF FFFF FFFF FFFF 00F9 F9FF" /* *ÿÿÿÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FF2A 2AFF FFFF FF2A" /* ÿ.++.ÿÿÿÿ**ÿÿÿÿ* */ $"2AFF FFFF 0000 0000 00FF FFFF 00F9 F9FF" /* *ÿÿÿ.....ÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF 2AFF FF2A FFFF FF2A" /* ÿ.++.ÿÿÿ*ÿÿ*ÿÿÿ* */ $"FFFF FFFF 0000 0000 0000 FFFF 00F9 F9FF" /* ÿÿÿÿ......ÿÿ.ùùÿ */ $"FF00 2B2B 00FF FF2A 2AFF FFFF 2AFF 2AFF" /* ÿ.++.ÿÿ**ÿÿÿ*ÿ*ÿ */ $"FFFF FFFF FFFF FFFF 0000 FFFF 00F9 F9FF" /* ÿÿÿÿÿÿÿÿ..ÿÿ.ùùÿ */ $"FF00 2B2B 00FF FF2A 2AFF FFFF FF2A FFFF" /* ÿ.++.ÿÿ**ÿÿÿÿ*ÿÿ */ $"FFFF 0000 FFFF FFFF 0000 FFFF 00F9 F9FF" /* ÿÿ..ÿÿÿÿ..ÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF 2AFF FFFF" /* ÿ.++.ÿÿÿÿÿÿÿ*ÿÿÿ */ $"FFFF 0000 FFFF FFFF 0000 FFFF 00F9 F9FF" /* ÿÿ..ÿÿÿÿ..ÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FF2A 2A2A FFFF 0000" /* ÿ.++.ÿÿÿÿ***ÿÿ.. */ $"00FF FFFF 0000 FFFF 0000 FFFF 00F9 F9FF" /* .ÿÿÿ..ÿÿ..ÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FF2A 2AFF FF00 0000" /* ÿ.++.ÿÿÿÿ**ÿÿ... */ $"00FF FFFF 0000 FFFF FFFF FFFF 00F9 F9FF" /* .ÿÿÿ..ÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF 0000 FFFF" /* ÿ.++.ÿÿÿÿÿÿÿ..ÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF 00F9 F9FF" /* ÿÿÿÿÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF 0000 FFFF" /* ÿ.++.ÿÿÿÿÿÿÿ..ÿÿ */ $"FFFF 0000 FFFF FFFF FFFF FFFF 00F9 F9FF" /* ÿÿ..ÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF 0000 FFFF" /* ÿ.++.ÿÿÿÿÿÿÿ..ÿÿ */ $"FFFF 0000 FFFF FFFF FFFF FFFF 00F9 F9FF" /* ÿÿ..ÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF FF00 00FF" /* ÿ.++.ÿÿÿÿÿÿÿÿ..ÿ */ $"FFFF 0000 FFFF FFFF FFFF FFFF 00F9 F9FF" /* ÿÿ..ÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF FFFF 0000" /* ÿ.++.ÿÿÿÿÿÿÿÿÿ.. */ $"0000 00FF FFFF FFFF FFFF FFFF 00F9 F9FF" /* ...ÿÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B 00FF FFFF FFFF FFFF FFFF FF00" /* ÿ.++.ÿÿÿÿÿÿÿÿÿÿ. */ $"0000 FFFF FFFF FFFF FFFF FFFF 00F9 F9FF" /* ..ÿÿÿÿÿÿÿÿÿÿ.ùùÿ */ $"FF00 2B2B F900 0000 0000 0000 0000 0000" /* ÿ.++ù........... */ $"0000 0000 0000 0000 0000 0000 00F9 F9FF" /* .............ùùÿ */ $"FF00 F9F9 F9E3 E3E3 E3E3 E3F9 F9F9 F9F9" /* ÿ.ùùùããããããùùùùù */ $"F9F9 F9F9 F9F9 F9F9 F9F9 F9F9 F9F9 F9FF" /* ùùùùùùùùùùùùùùùÿ */ $"FFF9 F9F9 F9E3 E3E3 E3E3 E3F9 F9F9 F9F9" /* ÿùùùùããããããùùùùù */ $"F9F9 F9F9 F9F9 F9F9 F9F9 F9F9 F9F9 F9FF" /* ùùùùùùùùùùùùùùùÿ */ $"FF00 0000 0000 0000 0000 0000 0000 0000" /* ÿ............... */ $"0000 0000 0000 0000 0000 0000 0000 00FF" /* ...............ÿ */ $"FF00 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 0000" /* ÿ.++++++++++++.. */ $"00FF 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2BFF" /* .ÿ+++++++++++++ÿ */ $"FF00 2BFC F9F9 F9F9 F9F9 F9F9 F9F9 002B" /* ÿ.+üùùùùùùùùùù.+ */ $"2BFF FFF9 F9F9 F9F9 F9F9 F9F9 2B2B 2BFF" /* +ÿÿùùùùùùùùù+++ÿ */ $"FF00 2BFC 2B2B 2B2B 2B2B 2B2B 2B2B 002B" /* ÿ.+ü++++++++++.+ */ $"2BFF F92B 2B2B 2B2B 2B2B 2B2B 002B 2BFF" /* +ÿù+++++++++.++ÿ */ $"FF00 2B2B 0000 0000 0000 0000 0000 002B" /* ÿ.++...........+ */ $"2BFF 2B00 0000 0000 0000 0000 2B2B 2BFF" /* +ÿ+.........+++ÿ */ $"FF00 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B FFFF" /* ÿ.++++++++++++ÿÿ */ $"FFFF 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2BFF" /* ÿÿ+++++++++++++ÿ */ $"FF00 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B" /* ÿ.++++++++++++++ */ $"2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2B2B 2BFF" /* +++++++++++++++ÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ }; data 'ICN#' (128) { $"0001 83C0 0002 5E40 0004 25C0 0008 49C0" /* ..ƒÀ..^@..%À..IÀ */ $"0011 9320 0027 2610 004E 4E08 009E 9E07" /* ..“ .'&..NN..žž. */ $"013F 7C07 027E 8007 04E6 E007 09C7 FC07" /* .?|..~€..æà.ÆÇü. */ $"13BC FFC7 273C E0FF 46DD E07F 8CEB FE79" /* .¼ÿÇ'<àÿFÝà.Œëþy */ $"8CF7 9E71 47EF 9E62 2718 E664 1330 E7C8" /* Œ÷žqGïžb'.æd.0çÈ */ $"09E7 FF90 04E7 9F3F 0267 9E7F 0133 9CFE" /* Æçÿ.çŸ?.gž..3œþ */ $"0098 39FC 004C 73F8 0027 E7E0 0011 8F80" /* .˜9ü.Lsø.'çà..€ */ $"0008 1E00 0004 3C00 0002 7000 0001 C000" /* ......<...p...À. */ $"0001 83C0 0003 DFC0 0007 FFC0 000F FFC0" /* ..ƒÀ..ßÀ..ÿÀ..ÿÀ */ $"001F FFE0 003F FFF0 007F FFF8 00FF FFFF" /* ..ÿà.?ÿð..ÿø.ÿÿÿ */ $"01FF FFFF 03FF FFFF 07FF FFFF 0FFF FFFF" /* .ÿÿÿ.ÿÿÿ.ÿÿÿ.ÿÿÿ */ $"1FFF FFFF 3FFF FFFF 7FFF FFFF FFFF FFFF" /* .ÿÿÿ?ÿÿÿ.ÿÿÿÿÿÿÿ */ $"FFFF FFFF 7FFF FFFE 3FFF FFFC 1FFF FFF8" /* ÿÿÿÿ.ÿÿþ?ÿÿü.ÿÿø */ $"0FFF FFF0 07FF FFFF 03FF FFFF 01FF FFFE" /* .ÿÿð.ÿÿÿ.ÿÿÿ.ÿÿþ */ $"00FF FFFC 007F FFF8 003F FFE0 001F FF80" /* .ÿÿü..ÿø.?ÿà..ÿ€ */ $"000F FE00 0007 FC00 0003 F000 0001 C000" /* ..þ...ü...ð...À. */ }; data 'ics#' (128) { $"00E8 0098 0324 0663 0E03 1BE3 368F 29ED" /* .è.˜.$.c...ã6)í */ $"BB68 54B8 2B77 156E 0ADC 0530 0260 0180" /* »hT¸+w.nÂÜ.0.`.€ */ $"01F8 03F8 07FC 0FFF 1FFF 3FFF 7FFF FFFF" /* .ø.ø.ü.ÿ.ÿ?ÿ.ÿÿÿ */ $"FFFE 7FFC 3FFF 1FFE 0FFC 07F0 03E0 0180" /* ÿþ.ü?ÿ.þ.ü.ð.à.€ */ }; data 'ics4' (128) { $"0000 000C FFFC F000 0000 00CB FD1F F000" /* ....ÿüð....Ëý.ð. */ $"0000 0CFF D1FD DF00 0000 CFFD 1FFD CCFF" /* ...ÿÑýß...Ïý.ýÌÿ */ $"000C FFF1 CCCC CCFF 00CF FCFF FFFD DCFF" /* ..ÿñÌÌÌÿ.ÏüÿÿýÜÿ */ $"0CFF CFFC F000 FFFF CCFC FCCF FFF0 FFBF" /* .ÿÏüð.ÿÿÌüüÏÿðÿ¿ */ $"FCFF FCFF 0FF0 FBB0 0FCF CF00 F0FF FB00" /* üÿüÿ.ðû°.ÏÏ.ðÿû. */ $"00FC F0FF 0FFF BDDD 000F CF0F 0FFB EEE0" /* .üðÿ.ÿ½Ý..Ï..ûîà */ $"0000 FCF0 FFBA EE00 0000 0FCF B8AE 0000" /* ..üðÿºî....ϸ®.. */ $"0000 00FC BEE0 0000 0000 000F E000 0000" /* ...ü¾à......à... */ }; data 'ics8' (128) { $"0000 0000 0000 002C FFFF FF13 FF00 0000" /* .......,ÿÿÿ.ÿ... */ $"0000 0000 0000 2C34 FF33 05FF FF00 0000" /* ......,4ÿ3.ÿÿ... */ $"0000 0000 002C FFFF 3305 FF33 33FF 0000" /* .....,ÿÿ3.ÿ33ÿ.. */ $"0000 0000 2CFF FF33 05FF FF33 0808 FFFF" /* ....,ÿÿ3.ÿÿ3..ÿÿ */ $"0000 002C FFFF FF05 0808 0808 0808 FFFF" /* ...,ÿÿÿ.......ÿÿ */ $"0000 2CFF FF2A FFFF FFFF FF33 3308 FFFF" /* ..,ÿÿ*ÿÿÿÿÿ33.ÿÿ */ $"002C FFFF 2AFF FF2A FF00 0000 FFFF FFFF" /* .,ÿÿ*ÿÿ*ÿ...ÿÿÿÿ */ $"2C2C FF2A FF2A 2AFF FFFF FF00 FFFF 34FF" /* ,,ÿ*ÿ**ÿÿÿÿ.ÿÿ4ÿ */ $"FF2C FFFF FF2A FFFF 00FF FF00 FF34 3400" /* ÿ,ÿÿÿ*ÿÿ.ÿÿ.ÿ44. */ $"00FF 2CFF 2AFF 0000 FF00 FFFF FF34 0000" /* .ÿ,ÿ*ÿ..ÿ.ÿÿÿ4.. */ $"0000 FF2C FF00 FFFF 00FF FFFF 34FA FAFA" /* ..ÿ,ÿ.ÿÿ.ÿÿÿ4úúú */ $"0000 00FF 2CFF 00FF 00FF FF34 FBFB FB00" /* ...ÿ,ÿ.ÿ.ÿÿ4ûûû. */ $"0000 0000 FF2C FF00 FFFF 34FD FCFB 0000" /* ....ÿ,ÿ.ÿÿ4ýüû.. */ $"0000 0000 00FF 2CFF 34E1 FDFB 0000 0000" /* .....ÿ,ÿ4áýû.... */ $"0000 0000 0000 FF2C 34FB FB00 0000 0000" /* ......ÿ,4ûû..... */ $"0000 0000 0000 00FF FB00 0000 0000 0000" /* .......ÿû....... */ }; data 'MENU' (128, "Apple") { $"0080 0000 0000 0000 0000 FFFF FFFB 0114" /* .€........ÿÿÿû.. */ $"0F41 626F 7574 204D 6163 426F 6368 73C9" /* .About MacBochsÉ */ $"0000 0000 012D 0000 0000 00" /* .....-..... */ }; data 'MENU' (129, "File") { $"0081 0000 0000 0000 0000 FFFF FFFF 0446" /* .........ÿÿÿÿ.F */ $"696C 6504 5175 6974 0051 0000 00" /* ile.Quit.Q... */ }; data 'MENU' (130, "Edit") { $"0082 0000 0000 0000 0000 FFFF FFFB 0445" /* .‚........ÿÿÿû.E */ $"6469 7404 556E 646F 005A 0000 012D 0000" /* dit.Undo.Z...-.. */ $"0000 0343 7574 0058 0000 0443 6F70 7900" /* ...Cut.X...Copy. */ $"4300 0005 5061 7374 6500 5600 0005 436C" /* C...Paste.V...Cl */ $"6561 7200 0000 0000" /* ear..... */ }; data 'MENU' (131, "MacBochs") { $"0083 0000 0000 0000 0000 FFFF FE7B 084D" /* .ƒ........ÿÿþ{.M */ $"6163 426F 6368 730C 456A 6563 7420 466C" /* acBochs.Eject Fl */ $"6F70 7079 0045 0000 012D 0000 0000 114D" /* oppy.E...-.....M */ $"6163 204D 6F75 7365 2050 6F69 6E74 6572" /* ac Mouse Pointer */ $"004B 1200 0554 6F6F 6C73 0042 1200 074D" /* .K...Tools.B...M */ $"656E 7542 6172 004D 1200 0B46 756C 6C20" /* enuBar.M...Full */ $"5363 7265 656E 0046 0000 0743 6F6E 736F" /* Screen.F...Conso */ $"6C65 0054 0000 012D 0000 0000 0853 6E61" /* le.T...-.....Sna */ $"7073 686F 7400 0000 0005 5265 7365 7400" /* pshot.....Reset. */ $"0000 0000" /* .... */ }; data 'MBAR' (128) { $"0004 0080 0081 0082 0083" /* ...€..‚.ƒ */ }; data 'clut' (128) { $"0000 0000 0000 00FF 0000 0000 0000 0000" /* .......ÿ........ */ $"0001 0000 0A3D FFFF 0002 0CCC FFFF 0000" /* ....Â=ÿÿ...Ìÿÿ.. */ $"0003 0000 FFFF A3D6 0004 FFFF 0000 0CCC" /* ....ÿÿ£Ö..ÿÿ...Ì */ $"0005 A3D6 0000 FFFF 0006 FFFF 51EB 0000" /* ..£Ö..ÿÿ..ÿÿQë.. */ $"0007 A3D6 A3D6 A3D6 0008 51EB 51EB 51EB" /* ..£Ö£Ö£Ö..QëQëQë */ $"0009 0000 5C28 FFFF 000A 5C28 FFFF 0000" /* .Æ..\(ÿÿ.Â\(ÿÿ.. */ $"000B 0000 FFFF F332 000C FFFF 0000 5C28" /* ....ÿÿó2..ÿÿ..\( */ $"000D F332 0000 FFFF 000E FFFF F332 0000" /* ..ó2..ÿÿ..ÿÿó2.. */ $"000F FFFF FFFF FFFF 0010 A3D6 A3D6 A3D6" /* ..ÿÿÿÿÿÿ..£Ö£Ö£Ö */ $"0011 A3D6 A3D6 A3D6 0012 A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö..£Ö£Ö£Ö */ $"0013 A3D6 A3D6 A3D6 0014 A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö..£Ö£Ö£Ö */ $"0015 A3D6 A3D6 A3D6 0016 A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö..£Ö£Ö£Ö */ $"0017 A3D6 A3D6 A3D6 0018 A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö..£Ö£Ö£Ö */ $"0019 A3D6 A3D6 A3D6 001A A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö..£Ö£Ö£Ö */ $"001B A3D6 A3D6 A3D6 001C A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö..£Ö£Ö£Ö */ $"001D A3D6 A3D6 A3D6 001E A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö..£Ö£Ö£Ö */ $"001F A3D6 A3D6 A3D6 0020 A3D6 A3D6 A3D6" /* ..£Ö£Ö£Ö. £Ö£Ö£Ö */ $"0021 A3D6 A3D6 A3D6 0022 A3D6 A3D6 A3D6" /* .!£Ö£Ö£Ö."£Ö£Ö£Ö */ $"0023 A3D6 A3D6 A3D6 0024 A3D6 A3D6 A3D6" /* .#£Ö£Ö£Ö.$£Ö£Ö£Ö */ $"0025 A3D6 A3D6 A3D6 0026 A3D6 A3D6 A3D6" /* .%£Ö£Ö£Ö.&£Ö£Ö£Ö */ $"0027 A3D6 A3D6 A3D6 0028 A3D6 A3D6 A3D6" /* .'£Ö£Ö£Ö.(£Ö£Ö£Ö */ $"0029 A3D6 A3D6 A3D6 002A A3D6 A3D6 A3D6" /* .)£Ö£Ö£Ö.*£Ö£Ö£Ö */ $"002B A3D6 A3D6 A3D6 002C A3D6 A3D6 A3D6" /* .+£Ö£Ö£Ö.,£Ö£Ö£Ö */ $"002D A3D6 A3D6 A3D6 002E A3D6 A3D6 A3D6" /* .-£Ö£Ö£Ö..£Ö£Ö£Ö */ $"002F A3D6 A3D6 A3D6 0030 A3D6 A3D6 A3D6" /* ./£Ö£Ö£Ö.0£Ö£Ö£Ö */ $"0031 A3D6 A3D6 A3D6 0032 A3D6 A3D6 A3D6" /* .1£Ö£Ö£Ö.2£Ö£Ö£Ö */ $"0033 A3D6 A3D6 A3D6 0034 A3D6 A3D6 A3D6" /* .3£Ö£Ö£Ö.4£Ö£Ö£Ö */ $"0035 A3D6 A3D6 A3D6 0036 A3D6 A3D6 A3D6" /* .5£Ö£Ö£Ö.6£Ö£Ö£Ö */ $"0037 A3D6 A3D6 A3D6 0038 A3D6 A3D6 A3D6" /* .7£Ö£Ö£Ö.8£Ö£Ö£Ö */ $"0039 A3D6 A3D6 A3D6 003A A3D6 A3D6 A3D6" /* .9£Ö£Ö£Ö.:£Ö£Ö£Ö */ $"003B A3D6 A3D6 A3D6 003C A3D6 A3D6 A3D6" /* .;£Ö£Ö£Ö.<£Ö£Ö£Ö */ $"003D A3D6 A3D6 A3D6 003E A3D6 A3D6 A3D6" /* .=£Ö£Ö£Ö.>£Ö£Ö£Ö */ $"003F A3D6 A3D6 A3D6 0040 0000 0000 0000" /* .?£Ö£Ö£Ö.@...... */ $"0041 0000 0000 0000 0042 0000 0000 0000" /* .A.......B...... */ $"0043 0000 0000 0000 0044 0000 0000 0000" /* .C.......D...... */ $"0045 0000 0000 0000 0046 0000 0000 0000" /* .E.......F...... */ $"0047 0000 0000 0000 0048 0000 0000 0000" /* .G.......H...... */ $"0049 0000 0000 0000 004A 0000 0000 0000" /* .I.......J...... */ $"004B 0000 0000 0000 004C 0000 0000 0000" /* .K.......L...... */ $"004D 0000 0000 0000 004E 0000 0000 0000" /* .M.......N...... */ $"004F 0000 0000 0000 0050 0000 0000 0000" /* .O.......P...... */ $"0051 0000 0000 0000 0052 0000 0000 0000" /* .Q.......R...... */ $"0053 0000 0000 0000 0054 0000 0000 0000" /* .S.......T...... */ $"0055 0000 0000 0000 0056 0000 0000 0000" /* .U.......V...... */ $"0057 0000 0000 0000 0058 0000 0000 0000" /* .W.......X...... */ $"0059 0000 0000 0000 005A 0000 0000 0000" /* .Y.......Z...... */ $"005B 0000 0000 0000 005C 0000 0000 0000" /* .[.......\...... */ $"005D 0000 0000 0000 005E 0000 0000 0000" /* .].......^...... */ $"005F 0000 0000 0000 0060 0000 0000 0000" /* ._.......`...... */ $"0061 0000 0000 0000 0062 0000 0000 0000" /* .a.......b...... */ $"0063 0000 0000 0000 0064 0000 0000 0000" /* .c.......d...... */ $"0065 0000 0000 0000 0066 0000 0000 0000" /* .e.......f...... */ $"0067 0000 0000 0000 0068 0000 0000 0000" /* .g.......h...... */ $"0069 0000 0000 0000 006A 0000 0000 0000" /* .i.......j...... */ $"006B 0000 0000 0000 006C 0000 0000 0000" /* .k.......l...... */ $"006D 0000 0000 0000 006E 0000 0000 0000" /* .m.......n...... */ $"006F 0000 0000 0000 0070 0000 0000 0000" /* .o.......p...... */ $"0071 0000 0000 0000 0072 0000 0000 0000" /* .q.......r...... */ $"0073 0000 0000 0000 0074 0000 0000 0000" /* .s.......t...... */ $"0075 0000 0000 0000 0076 0000 0000 0000" /* .u.......v...... */ $"0077 0000 0000 0000 0078 0000 0000 0000" /* .w.......x...... */ $"0079 0000 0000 0000 007A 0000 0000 0000" /* .y.......z...... */ $"007B 0000 0000 0000 007C 0000 0000 0000" /* .{.......|...... */ $"007D 0000 0000 0000 007E 0000 0000 0000" /* .}.......~...... */ $"007F 0000 0000 0000 0080 0000 0000 0000" /* .........€...... */ $"0081 0000 0000 0000 0082 0000 0000 0000" /* ........‚...... */ $"0083 0000 0000 0000 0084 0000 0000 0000" /* .ƒ.......„...... */ $"0085 0000 0000 0000 0086 0000 0000 0000" /* .….......†...... */ $"0087 0000 0000 0000 0088 0000 0000 0000" /* .‡.......ˆ...... */ $"0089 0000 0000 0000 008A 0000 0000 0000" /* .‰.......Š...... */ $"008B 0000 0000 0000 008C 0000 0000 0000" /* .‹.......Œ...... */ $"008D 0000 0000 0000 008E 0000 0000 0000" /* ........Ž...... */ $"008F 0000 0000 0000 0090 0000 0000 0000" /* .............. */ $"0091 0000 0000 0000 0092 0000 0000 0000" /* .‘.......’...... */ $"0093 0000 0000 0000 0094 0000 0000 0000" /* .“.......”...... */ $"0095 0000 0000 0000 0096 0000 0000 0000" /* .•.......–...... */ $"0097 0000 0000 0000 0098 0000 0000 0000" /* .—.......˜...... */ $"0099 0000 0000 0000 009A 0000 0000 0000" /* .™.......š...... */ $"009B 0000 0000 0000 009C 0000 0000 0000" /* .›.......œ...... */ $"009D 0000 0000 0000 009E 0000 0000 0000" /* ........ž...... */ $"009F 0000 0000 0000 00A0 0000 0000 0000" /* .Ÿ....... ...... */ $"00A1 0000 0000 0000 00A2 0000 0000 0000" /* .¡.......¢...... */ $"00A3 0000 0000 0000 00A4 0000 0000 0000" /* .£.......¤...... */ $"00A5 0000 0000 0000 00A6 0000 0000 0000" /* .¥.......¦...... */ $"00A7 0000 0000 0000 00A8 0000 0000 0000" /* .§.......¨...... */ $"00A9 0000 0000 0000 00AA 0000 0000 0000" /* .©.......ª...... */ $"00AB 0000 0000 0000 00AC 0000 0000 0000" /* .«.......¬...... */ $"00AD 0000 0000 0000 00AE 0000 0000 0000" /* .­.......®...... */ $"00AF 0000 0000 0000 00B0 0000 0000 0000" /* .¯.......°...... */ $"00B1 0000 0000 0000 00B2 0000 0000 0000" /* .±.......²...... */ $"00B3 0000 0000 0000 00B4 0000 0000 0000" /* .³.......´...... */ $"00B5 0000 0000 0000 00B6 0000 0000 0000" /* .µ.......¶...... */ $"00B7 0000 0000 0000 00B8 0000 0000 0000" /* .·.......¸...... */ $"00B9 0000 0000 0000 00BA 0000 0000 0000" /* .¹.......º...... */ $"00BB 0000 0000 0000 00BC 0000 0000 0000" /* .».......¼...... */ $"00BD 0000 0000 0000 00BE 0000 0000 0000" /* .½.......¾...... */ $"00BF 0000 0000 0000 00C0 0000 0000 0000" /* .¿.......À...... */ $"00C1 0000 0000 0000 00C2 0000 0000 0000" /* .Á.......Â...... */ $"00C3 0000 0000 0000 00C4 0000 0000 0000" /* .Ã.......Ä...... */ $"00C5 0000 0000 0000 00C6 0000 0000 0000" /* .Å.......Æ...... */ $"00C7 0000 0000 0000 00C8 0000 0000 0000" /* .Ç.......È...... */ $"00C9 0000 0000 0000 00CA 0000 0000 0000" /* .É.......Ê...... */ $"00CB 0000 0000 0000 00CC 0000 0000 0000" /* .Ë.......Ì...... */ $"00CD 0000 0000 0000 00CE 0000 0000 0000" /* .Í.......Î...... */ $"00CF 0000 0000 0000 00D0 0000 0000 0000" /* .Ï.......Ð...... */ $"00D1 0000 0000 0000 00D2 0000 0000 0000" /* .Ñ.......Ò...... */ $"00D3 0000 0000 0000 00D4 0000 0000 0000" /* .Ó.......Ô...... */ $"00D5 0000 0000 0000 00D6 0000 0000 0000" /* .Õ.......Ö...... */ $"00D7 0000 0000 0000 00D8 0000 0000 0000" /* .×.......Ø...... */ $"00D9 0000 0000 0000 00DA 0000 0000 0000" /* .Ù.......Ú...... */ $"00DB 0000 0000 0000 00DC 0000 0000 0000" /* .Û.......Ü...... */ $"00DD 0000 0000 0000 00DE 0000 0000 0000" /* .Ý.......Þ...... */ $"00DF 0000 0000 0000 00E0 0000 0000 0000" /* .ß.......à...... */ $"00E1 0000 0000 0000 00E2 0000 0000 0000" /* .á.......â...... */ $"00E3 0000 0000 0000 00E4 0000 0000 0000" /* .ã.......ä...... */ $"00E5 0000 0000 0000 00E6 0000 0000 0000" /* .å.......æ...... */ $"00E7 0000 0000 0000 00E8 0000 0000 0000" /* .ç.......è...... */ $"00E9 0000 0000 0000 00EA 0000 0000 0000" /* .é.......ê...... */ $"00EB 0000 0000 0000 00EC 0000 0000 0000" /* .ë.......ì...... */ $"00ED 0000 0000 0000 00EE 0000 0000 0000" /* .í.......î...... */ $"00EF 0000 0000 0000 00F0 0000 0000 0000" /* .ï.......ð...... */ $"00F1 0000 0000 0000 00F2 0000 0000 0000" /* .ñ.......ò...... */ $"00F3 0000 0000 0000 00F4 0000 0000 0000" /* .ó.......ô...... */ $"00F5 0000 0000 0000 00F6 0000 0000 0000" /* .õ.......ö...... */ $"00F7 0000 0000 0000 00F8 0000 0000 0000" /* .÷.......ø...... */ $"00F9 0000 0000 0000 00FA 0000 0000 0000" /* .ù.......ú...... */ $"00FB 0000 0000 0000 00FC 0000 0000 0000" /* .û.......ü...... */ $"00FD 0000 0000 0000 00FE 0000 0000 0000" /* .ý.......þ...... */ $"00FF 0000 0000 0000" /* .ÿ...... */ }; data 'DLOG' (128, "About") { $"0028 0028 0154 0209 0001 0100 0100 0000" /* .(.(.T.Æ........ */ $"0000 0080 00" /* ...€. */ }; data 'DITL' (128) { $"0003 0000 0000 010B 0199 011F 01D3 0402" /* .........™...Ó.. */ $"4F4B 0000 0000 0003 000C 0064 01D2 88DC" /* OK.........d.ÒˆÜ */ $"424F 4348 5320 6973 2043 6F70 7972 6967" /* BOCHS is Copyrig */ $"6874 2031 3939 342D 3139 3939 2062 7920" /* ht 1994-1999 by */ $"4B65 7669 6E20 502E 204C 6177 746F 6E2E" /* Kevin P. Lawton. */ $"0D0D 424F 4348 5320 6973 2063 6F6D 6D65" /* ..BOCHS is comme */ $"7263 6961 6C20 736F 6674 7761 7265 2E0D" /* rcial software.. */ $"0D46 6F72 206D 6F72 6520 696E 666F 726D" /* .For more inform */ $"6174 696F 6E2C 2072 6561 6420 7468 6520" /* ation, read the */ $"6669 6C65 2027 4C49 4345 4E53 4527 2069" /* file 'LICENSE' i */ $"6E63 6C75 6465 6420 696E 2074 6865 2062" /* ncluded in the b */ $"6F63 6873 2064 6973 7472 6962 7574 696F" /* ochs distributio */ $"6E2E 2020 4966 2079 6F75 2064 6F6E 2774" /* n. If you don't */ $"2068 6176 6520 6163 6365 7373 2074 6F20" /* have access to */ $"7468 6973 2066 696C 652C 206F 7220 6861" /* this file, or ha */ $"7665 2071 7565 7374 696F 6E73 0000 0000" /* ve questions.... */ $"0062 000C 00DA 01D3 88B9 7265 6761 7264" /* .b...Ú.Óˆ¹regard */ $"696E 6720 7468 6520 6C69 6365 6E73 696E" /* ing the licensin */ $"6720 706F 6C69 6379 2C20 7468 6520 6175" /* g policy, the au */ $"7468 6F72 206D 6179 2062 6520 636F 6E74" /* thor may be cont */ $"6163 7465 6420 7669 613A 0D0D 5553 204D" /* acted via:..US M */ $"6169 6C3A 2020 4B65 7669 6E20 4C61 7774" /* ail: Kevin Lawt */ $"6F6E 0D20 2020 2020 2020 2020 2020 2020" /* on. */ $"2020 3532 3820 4C65 7869 6E67 746F 6E20" /* 528 Lexington */ $"5374 2E0D 2020 2020 2020 2020 2020 2020" /* St.. */ $"2020 2057 616C 7468 616D 2C20 4D41 2030" /* Waltham, MA 0 */ $"3231 3534 0D0D 454D 6169 6C3A 2020 2020" /* 2154..EMail: */ $"626F 6368 7340 776F 726C 642E 7374 642E" /* bochs@world.std. */ $"636F 6D61 0000 0000 00DB 000C 0102 01D5" /* coma.....Û.....Õ */ $"8863 4D61 6342 6F63 6873 2070 6F72 7420" /* ˆcMacBochs port */ $"6279 2044 6176 6964 2042 6174 7465 7268" /* by David Batterh */ $"616D 203C 6472 6261 7474 6572 4070 726F" /* am */ $"200D 7769 7468 2063 6F6E 7472 6962 7574" /* .with contribut */ $"696F 6E73 2066 726F 6D20 5469 6D20 5365" /* ions from Tim Se */ $"6E65 6361 6C00" /* necal. */ }; data 'DITL' (200) { $"0001 0000 0000 006B 0129 007F 0163 0404" /* .......k.)...c.. */ $"5175 6974 0000 0000 000C 0053 0060 0163" /* Quit.......S.`.c */ $"8892 5468 6520 426F 6368 7320 5043 2065" /* ˆ’The Bochs PC e */ $"6D75 6C61 746F 7220 6861 7320 6861 6C74" /* mulator has halt */ $"6564 2E0D 0D49 6620 796F 7520 6469 646E" /* ed...If you didn */ $"2774 2065 7870 6563 7420 7468 6973 2074" /* 't expect this t */ $"6F20 6861 7070 656E 2C20 636F 6E73 756C" /* o happen, consul */ $"7420 796F 7572 206C 6F67 2066 696C 6520" /* t your log file */ $"2874 7970 6963 616C 6C79 2022 626F 6368" /* (typically "boch */ $"732E 6F75 7422 2920 746F 2066 696E 6420" /* s.out") to find */ $"6F75 7420 7768 6174 2077 656E 7420 7772" /* out what went wr */ $"6F6E 672E" /* ong. */ }; data 'cicn' (128) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 3DFF FFF8 7FFF FFFC 7FFF" /* ......=ÿÿø.ÿÿü.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 3FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ?ÿ */ $"FFFC 0000 0000 3DFF FFF8 4220 0104 4220" /* ÿü....=ÿÿøB ..B */ $"0106 4220 F106 4A20 F15E 4E20 F176 4A20" /* ..B ñ.J ñ^N ñvJ */ $"F15E 4A20 F106 4220 F106 4220 0106 4220" /* ñ^J ñ.B ñ.B ..B */ $"0106 421F FF06 4000 0006 4000 0006 41FF" /* ..B.ÿ.@...@...Aÿ */ $"FFC6 4200 0006 4200 0006 4200 0006 4200" /* ÿÆB...B...B...B. */ $"8006 4200 8006 4201 4006 4201 4006 4202" /* €.B.€.B.@.B.@.B. */ $"2006 4202 2006 4207 F006 4204 1006 5A04" /* .B. .B.ð.B...Z. */ $"101E 5A00 001E 4200 0006 7FFF FFDE 3FFF" /* ..Z...B....ÿÿÞ?ÿ */ $"FFFC 0000 0000 0000 0005 0000 FFFF FFFF" /* ÿü..........ÿÿÿÿ */ $"FFFF 0001 CCCC CCCC FFFF 0002 6666 6666" /* ÿÿ..ÌÌÌÌÿÿ..ffff */ $"CCCC 0003 BBBB BBBB BBBB 0004 5555 5555" /* ÌÌ..»»»»»»..UUUU */ $"5555 000F 0000 0000 0000 0000 0000 0000" /* UU.............. */ $"0000 0000 0000 0000 0000 00FF FF0F FFFF" /* ...........ÿÿ.ÿÿ */ $"FFFF FFFF FFFF FFFF F000 0F00 0041 11F0" /* ÿÿÿÿÿÿÿÿð....A.ð */ $"0000 0000 001F 0000 1F00 0F01 1143 3320" /* .............C3 */ $"1010 1111 1114 0113 32F0 0F01 1143 3320" /* ........2ð...C3 */ $"0100 4444 0114 0133 32F0 0F01 2143 3320" /* ..DD...32ð..!C3 */ $"1010 4222 0114 0F1F F4F0 0F03 2243 3320" /* ..B"....ôð.."C3 */ $"0110 4222 0114 0FFF 1FF0 0F01 2343 3320" /* ..B"...ÿ.ð..#C3 */ $"1110 4222 0114 0F1F F2F0 0F01 2343 3320" /* ..B"....òð..#C3 */ $"1110 4222 0114 0333 32F0 0F01 3343 3320" /* ..B"...32ð..3C3 */ $"1110 4222 0114 0333 32F0 0F01 3343 3320" /* ..B"...32ð..3C3 */ $"1110 0000 0114 0333 32F0 0F01 3343 3320" /* .......32ð..3C3 */ $"1111 1111 1114 0333 32F0 0F01 3343 3334" /* .......32ð..3C34 */ $"4444 4444 4444 0333 32F0 0F01 3330 0000" /* DDDDDD.32ð..30.. */ $"0000 0000 0000 0333 32F0 0F01 3333 3333" /* .......32ð..3333 */ $"3333 3333 3333 3333 32F0 0F01 3334 4444" /* 333333332ð..34DD */ $"4444 4444 4444 4433 32F0 0F01 3343 3333" /* DDDDDDD32ð..3C33 */ $"3333 3333 3333 3303 32F0 0F01 3343 3333" /* 3333333.2ð..3C33 */ $"3333 3333 3333 3303 32F0 0F01 3343 3333" /* 3333333.2ð..3C33 */ $"3333 3333 3333 3303 32F0 0F01 3343 3333" /* 3333333.2ð..3C33 */ $"3333 F333 3333 3303 32F0 0F01 3343 3333" /* 33ó3333.2ð..3C33 */ $"3333 F333 3333 3303 32F0 0F01 3343 3333" /* 33ó3333.2ð..3C33 */ $"333F 3F33 3333 3303 32F0 0F01 3343 3333" /* 3??3333.2ð..3C33 */ $"333F 3F33 3333 3303 32F0 0F01 3343 3333" /* 3??3333.2ð..3C33 */ $"33F3 33F3 3333 3303 32F0 0F01 3343 3333" /* 3ó3ó333.2ð..3C33 */ $"33F3 33F3 3333 3303 32F0 0F01 3343 3333" /* 3ó3ó333.2ð..3C33 */ $"3FFF FFFF 3333 3303 32F0 0F01 3343 3333" /* ?ÿÿÿ333.2ð..3C33 */ $"3F33 333F 3333 3303 32F0 0F02 2343 3333" /* ?33?333.2ð..#C33 */ $"3F33 333F 3333 3302 22F0 0F0F F043 3333" /* ?33?333."ð..ðC33 */ $"3333 3333 3333 330F F2F0 0F00 0043 3333" /* 3333333.òð...C33 */ $"3333 3333 3333 3303 32F0 0F22 2242 2222" /* 3333333.2ð.""B"" */ $"2222 2222 2222 2212 22F0 00FF FFFF FFFF" /* """""""."ð.ÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FF00" /* ÿÿÿÿÿÿÿÿÿ. */ }; data 'cicn' (129) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 3DFF FFF8 7FFF FFFC 7FFF" /* ......=ÿÿø.ÿÿü.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE FFFF FFFF FFFF FFFF FFFF" /* ÿþ.ÿÿþÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿÿ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 3FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ?ÿ */ $"FFFC 0000 0000 3DFF FFF8 427F FF04 43FF" /* ÿü....=ÿÿøB.ÿ.Cÿ */ $"FF86 43F0 FFC6 4FE0 F3FE 4F20 F1F6 5E20" /* ÿ†CðÿÆOàóþO ñö^ */ $"F3FE 7E20 F7BE 7A20 FF1E 7A20 1F1E 7220" /* óþ~ ÷¾z ÿ.z ..r */ $"3D0E 721F FF0E E000 F007 E001 E007 E1FF" /* =.r.ÿ.à.ð.à.à.áÿ */ $"FFC7 E207 8007 E20F 0007 E21E 0007 E23C" /* ÿÇâ.€.â...â...â< */ $"8007 7278 800E 72F1 400E 7BE1 401E 7BC2" /* €.rx€.rñ@.{á@.{ */ $"201E 7F82 203E 5F07 F07E 4F04 10F6 5FC4" /* ..‚ >_.ð~O..ö_Ä */ $"13FE 5BF0 0FDE 43FF FF86 7FFF FFDE 3FFF" /* .þ[ð.ÞCÿÿ†.ÿÿÞ?ÿ */ $"FFFC 0000 0000 0000 0006 0000 FFFF FFFF" /* ÿü..........ÿÿÿÿ */ $"FFFF 0001 CCCC CCCC FFFF 0002 6666 6666" /* ÿÿ..ÌÌÌÌÿÿ..ffff */ $"CCCC 0003 BBBB BBBB BBBB 0004 5555 5555" /* ÌÌ..»»»»»»..UUUU */ $"5555 0005 DDDD 0000 0000 000F 0000 0000" /* UU..ÝÝ.......... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 00FF FF0F FFFF 5555 5555 FFFF FFFF" /* ...ÿÿ.ÿÿUUUUÿÿÿÿ */ $"F000 0F00 0041 1555 5555 5555 555F 0000" /* ð....A.UUUUUU_.. */ $"1F00 0F01 1145 5555 5555 5555 5555 5113" /* .....EUUUUUUUUQ. */ $"32F0 0F01 1155 5555 0100 4444 5555 5533" /* 2ð...UUU..DDUUU3 */ $"32F0 0F01 2555 5520 1010 4222 0155 555F" /* 2ð..%UU ..B".UU_ */ $"F4F0 0F03 5555 3320 0110 4222 0115 5555" /* ôð..UU3 ..B"..UU */ $"1FF0 0F05 5553 3320 1110 4222 0155 5555" /* .ð..US3 ..B".UUU */ $"52F0 0F55 5543 3320 1110 4222 0555 5355" /* Rð.UUC3 ..B".USU */ $"55F0 0F55 5343 3320 1110 4222 5555 0335" /* Uð.USC3 ..B"UU.5 */ $"55F0 0555 5343 3320 1110 0005 5554 0335" /* Uð.USC3 ....UT.5 */ $"5550 0555 3343 3320 1111 1155 5514 0333" /* UP.U3C3 ...UU..3 */ $"5550 0555 3343 3334 4444 4555 5444 0333" /* UP.U3C34DDEUTD.3 */ $"5550 5551 3330 0000 0000 5555 0000 0333" /* UPUQ30....UU...3 */ $"3555 5551 3333 3333 3335 5553 3333 3333" /* 5UUQ333335US3333 */ $"3555 5551 3334 4444 4455 5544 4444 4433" /* 5UUQ34DDDUUDDDD3 */ $"3555 5551 3343 3333 3555 5333 3333 3303" /* 5UUQ3C335US3333. */ $"3555 5551 3343 3333 5555 3333 3333 3303" /* 5UUQ3C33UU33333. */ $"3555 5551 3343 3335 5553 3333 3333 3303" /* 5UUQ3C35US33333. */ $"3555 5551 3343 3355 5533 F333 3333 3303" /* 5UUQ3C3UU3ó3333. */ $"3555 0555 3343 3555 5333 F333 3333 3303" /* 5U.U3C5US3ó3333. */ $"5550 0555 3343 5555 333F 3F33 3333 3303" /* UP.U3CUU3??3333. */ $"5550 0555 5345 5553 333F 3F33 3333 3305" /* UP.USEUS3??3333. */ $"5550 0F55 5355 5533 33F3 33F3 3333 3305" /* UP.USUU33ó3ó333. */ $"55F0 0F55 5555 5333 33F3 33F3 3333 3355" /* Uð.UUUS33ó3ó333U */ $"55F0 0F05 5555 3333 3FFF FFFF 3333 3555" /* Uð..UU33?ÿÿÿ335U */ $"52F0 0F01 5555 3333 3F33 333F 3333 5555" /* Rð..UU33?33?33UU */ $"32F0 0F02 2555 5533 3F33 333F 3355 5552" /* 2ð..%UU3?33?3UUR */ $"22F0 0F0F F055 5555 3333 3333 5555 550F" /* "ð..ðUUU3333UUU. */ $"F2F0 0F00 0045 5555 5555 5555 5555 5303" /* òð...EUUUUUUUUS. */ $"32F0 0F22 2242 2555 5555 5555 5552 2212" /* 2ð.""B%UUUUUUR". */ $"22F0 00FF FFFF FFFF 5555 5555 FFFF FFFF" /* "ð.ÿÿÿÿÿUUUUÿÿÿÿ */ $"FF00" /* ÿ. */ }; data 'cicn' (131) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 3DFF FFF8 7FFF FFFC 7FFF" /* ......=ÿÿø.ÿÿü.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE FFFF FFFF FFFF FFFF FFFF" /* ÿþ.ÿÿþÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿÿ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 3FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ?ÿ */ $"FFFC 0000 0000 3DFF FFF8 427F FF04 43FF" /* ÿü....=ÿÿøB.ÿ.Cÿ */ $"FF86 43F0 FFC6 4FE0 F3FE 4F20 F1F6 5E20" /* ÿ†CðÿÆOàóþO ñö^ */ $"F3FE 7E20 F7BE 7A20 FF1E 7A20 1F1E 7220" /* óþ~ ÷¾z ÿ.z ..r */ $"3D0E 721F FF0E E000 F007 E001 E007 E1FF" /* =.r.ÿ.à.ð.à.à.áÿ */ $"FFC7 E207 8007 E20F 0007 E21E 0007 E23F" /* ÿÇâ.€.â...â...â? */ $"E007 727C 100E 72F4 100E 7BE7 E01E 7BC4" /* à.r|..rô..{çà.{Ä */ $"101E 7F84 103E 5F04 107E 4F04 10F6 5FC7" /* ...„.>_..~O..ö_Ç */ $"E3FE 5BF0 0FDE 43FF FF86 7FFF FFDE 3FFF" /* ãþ[ð.ÞCÿÿ†.ÿÿÞ?ÿ */ $"FFFC 0000 0000 0000 0006 0000 FFFF FFFF" /* ÿü..........ÿÿÿÿ */ $"FFFF 0001 CCCC CCCC FFFF 0002 6666 6666" /* ÿÿ..ÌÌÌÌÿÿ..ffff */ $"CCCC 0003 BBBB BBBB BBBB 0004 5555 5555" /* ÌÌ..»»»»»»..UUUU */ $"5555 0005 DDDD 0000 0000 000F 0000 0000" /* UU..ÝÝ.......... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 00FF FF0F FFFF 5555 5555 FFFF FFFF" /* ...ÿÿ.ÿÿUUUUÿÿÿÿ */ $"F000 0F00 0041 1555 5555 5555 555F 0000" /* ð....A.UUUUUU_.. */ $"1F00 0F01 1145 5555 5555 5555 5555 5113" /* .....EUUUUUUUUQ. */ $"32F0 0F01 1155 5555 0100 4444 5555 5533" /* 2ð...UUU..DDUUU3 */ $"32F0 0F01 2555 5520 1010 4222 0155 555F" /* 2ð..%UU ..B".UU_ */ $"F4F0 0F03 5555 3320 0110 4222 0115 5555" /* ôð..UU3 ..B"..UU */ $"1FF0 0F05 5553 3320 1110 4222 0155 5555" /* .ð..US3 ..B".UUU */ $"52F0 0F55 5543 3320 1110 4222 0555 5355" /* Rð.UUC3 ..B".USU */ $"55F0 0F55 5343 3320 1110 4222 5555 0335" /* Uð.USC3 ..B"UU.5 */ $"55F0 0555 5343 3320 1110 0005 5554 0335" /* Uð.USC3 ....UT.5 */ $"5550 0555 3343 3320 1111 1155 5514 0333" /* UP.U3C3 ...UU..3 */ $"5550 0555 3343 3334 4444 4555 5444 0333" /* UP.U3C34DDEUTD.3 */ $"5550 5551 3330 0000 0000 5555 0000 0333" /* UPUQ30....UU...3 */ $"3555 5551 3333 3333 3335 5553 3333 3333" /* 5UUQ333335US3333 */ $"3555 5551 3334 4444 4455 5544 4444 4433" /* 5UUQ34DDDUUDDDD3 */ $"3555 5551 3343 3333 3555 5333 3333 3303" /* 5UUQ3C335US3333. */ $"3555 5551 3343 3333 5555 3333 3333 3303" /* 5UUQ3C33UU33333. */ $"3555 5551 3343 3335 5553 3333 3333 3303" /* 5UUQ3C35US33333. */ $"3555 5551 3343 3355 55FF FFF3 3333 3303" /* 5UUQ3C3UUÿÿó333. */ $"3555 0555 3343 3555 5F33 333F 3333 3303" /* 5U.U3C5U_33?333. */ $"5550 0555 3343 5555 3F33 333F 3333 3303" /* UP.U3CUU?33?333. */ $"5550 0555 5345 5553 3FFF FFF3 3333 3305" /* UP.USEUS?ÿÿó333. */ $"5550 0F55 5355 5533 3F33 333F 3333 3305" /* UP.USUU3?33?333. */ $"55F0 0F55 5555 5333 3F33 333F 3333 3355" /* Uð.UUUS3?33?333U */ $"55F0 0F05 5555 3333 3F33 333F 3333 3555" /* Uð..UU33?33?335U */ $"52F0 0F01 5555 3333 3F33 333F 3333 5555" /* Rð..UU33?33?33UU */ $"32F0 0F02 2555 5533 3FFF FFF3 3355 5552" /* 2ð..%UU3?ÿÿó3UUR */ $"22F0 0F0F F055 5555 3333 3333 5555 550F" /* "ð..ðUUU3333UUU. */ $"F2F0 0F00 0045 5555 5555 5555 5555 5303" /* òð...EUUUUUUUUS. */ $"32F0 0F22 2242 2555 5555 5555 5552 2212" /* 2ð.""B%UUUUUUR". */ $"22F0 00FF FFFF FFFF 5555 5555 FFFF FFFF" /* "ð.ÿÿÿÿÿUUUUÿÿÿÿ */ $"FF00" /* ÿ. */ }; data 'cicn' (130) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 3DFF FFF8 7FFF FFFC 7FFF" /* ......=ÿÿø.ÿÿü.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 7FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ.ÿ */ $"FFFE 7FFF FFFE 7FFF FFFE 7FFF FFFE 3FFF" /* ÿþ.ÿÿþ.ÿÿþ.ÿÿþ?ÿ */ $"FFFC 0000 0000 3DFF FFF8 4220 0104 4220" /* ÿü....=ÿÿøB ..B */ $"0106 4220 F106 4A20 F15E 4E20 F176 4A20" /* ..B ñ.J ñ^N ñvJ */ $"F15E 4A20 F106 4220 F106 4220 0106 4220" /* ñ^J ñ.B ñ.B ..B */ $"0106 421F FF06 4000 0006 4000 0006 41FF" /* ..B.ÿ.@...@...Aÿ */ $"FFC6 4200 0006 4200 0006 4200 0006 4207" /* ÿÆB...B...B...B. */ $"E006 4204 1006 4204 1006 4207 E006 4204" /* à.B...B...B.à.B. */ $"1006 4204 1006 4204 1006 4204 1006 5A07" /* ..B...B...B...Z. */ $"E01E 5A00 001E 4200 0006 7FFF FFDE 3FFF" /* à.Z...B....ÿÿÞ?ÿ */ $"FFFC 0000 0000 0000 0005 0000 FFFF FFFF" /* ÿü..........ÿÿÿÿ */ $"FFFF 0001 CCCC CCCC FFFF 0002 6666 6666" /* ÿÿ..ÌÌÌÌÿÿ..ffff */ $"CCCC 0003 BBBB BBBB BBBB 0004 5555 5555" /* ÌÌ..»»»»»»..UUUU */ $"5555 000F 0000 0000 0000 0000 0000 0000" /* UU.............. */ $"0000 0000 0000 0000 0000 00FF FF0F FFFF" /* ...........ÿÿ.ÿÿ */ $"FFFF FFFF FFFF FFFF F000 0F00 0041 11F0" /* ÿÿÿÿÿÿÿÿð....A.ð */ $"0000 0000 001F 0000 1F00 0F01 1143 3320" /* .............C3 */ $"1010 1111 1114 0113 32F0 0F01 1143 3320" /* ........2ð...C3 */ $"0100 4444 0114 0133 32F0 0F01 2143 3320" /* ..DD...32ð..!C3 */ $"1010 4222 0114 0F1F F4F0 0F03 2243 3320" /* ..B"....ôð.."C3 */ $"0110 4222 0114 0FFF 1FF0 0F01 2343 3320" /* ..B"...ÿ.ð..#C3 */ $"1110 4222 0114 0F1F F2F0 0F01 2343 3320" /* ..B"....òð..#C3 */ $"1110 4222 0114 0333 32F0 0F01 3343 3320" /* ..B"...32ð..3C3 */ $"1110 4222 0114 0333 32F0 0F01 3343 3320" /* ..B"...32ð..3C3 */ $"1110 0000 0114 0333 32F0 0F01 3343 3320" /* .......32ð..3C3 */ $"1111 1111 1114 0333 32F0 0F01 3343 3334" /* .......32ð..3C34 */ $"4444 4444 4444 0333 32F0 0F01 3330 0000" /* DDDDDD.32ð..30.. */ $"0000 0000 0000 0333 32F0 0F01 3333 3333" /* .......32ð..3333 */ $"3333 3333 3333 3333 32F0 0F01 3334 4444" /* 333333332ð..34DD */ $"4444 4444 4444 4433 32F0 0F01 3343 3333" /* DDDDDDD32ð..3C33 */ $"3333 3333 3333 3303 32F0 0F01 3343 3333" /* 3333333.2ð..3C33 */ $"3333 3333 3333 3303 32F0 0F01 3343 3333" /* 3333333.2ð..3C33 */ $"3333 3333 3333 3303 32F0 0F01 3343 3333" /* 3333333.2ð..3C33 */ $"3FFF FFF3 3333 3303 32F0 0F01 3343 3333" /* ?ÿÿó333.2ð..3C33 */ $"3F33 333F 3333 3303 32F0 0F01 3343 3333" /* ?33?333.2ð..3C33 */ $"3F33 333F 3333 3303 32F0 0F01 3343 3333" /* ?33?333.2ð..3C33 */ $"3FFF FFF3 3333 3303 32F0 0F01 3343 3333" /* ?ÿÿó333.2ð..3C33 */ $"3F33 333F 3333 3303 32F0 0F01 3343 3333" /* ?33?333.2ð..3C33 */ $"3F33 333F 3333 3303 32F0 0F01 3343 3333" /* ?33?333.2ð..3C33 */ $"3F33 333F 3333 3303 32F0 0F01 3343 3333" /* ?33?333.2ð..3C33 */ $"3F33 333F 3333 3303 32F0 0F02 2343 3333" /* ?33?333.2ð..#C33 */ $"3FFF FFF3 3333 3302 22F0 0F0F F043 3333" /* ?ÿÿó333."ð..ðC33 */ $"3333 3333 3333 330F F2F0 0F00 0043 3333" /* 3333333.òð...C33 */ $"3333 3333 3333 3303 32F0 0F22 2242 2222" /* 3333333.2ð.""B"" */ $"2222 2222 2222 2212 22F0 00FF FFFF FFFF" /* """""""."ð.ÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FF00" /* ÿÿÿÿÿÿÿÿÿ. */ }; data 'cicn' (134) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 0000 7C00 0003 FF00 0007" /* ........|...ÿ... */ $"8380 0006 01C0 000F 00E0 007F E070 00FF" /* ƒ€...À...à..àp.ÿ */ $"F030 00FF F030 00FF F018 01FF F818 01FF" /* ð0.ÿð0.ÿð..ÿø..ÿ */ $"F818 01FF F80C 03FF FC0C 03FF FC0C 03FF" /* ø..ÿø..ÿü..ÿü..ÿ */ $"FC04 03FF FC04 07FF FE00 07FF FE00 07FF" /* ü..ÿü..ÿþ..ÿþ..ÿ */ $"FE00 07FF FE00 07FF FE00 07FF FE00 07FF" /* þ..ÿþ..ÿþ..ÿþ..ÿ */ $"FE00 07FF FE00 07FF FE00 03FF FE00 03FF" /* þ..ÿþ..ÿþ..ÿþ..ÿ */ $"FC00 01FF FC00 01FF F800 00FF F000 003F" /* ü..ÿü..ÿø..ÿð..? */ $"C000 0000 0000 0000 7C00 0003 FF00 0007" /* À.......|...ÿ... */ $"8380 0006 01C0 000F 00E0 007F E070 0080" /* ƒ€...À...à..àp.€ */ $"1030 0080 1030 0080 1018 0100 0818 0100" /* .0.€.0.€........ */ $"0818 0100 080C 0200 040C 03FF FC0C 0200" /* ...........ÿü... */ $"0404 0200 0404 0400 0200 0500 0200 0500" /* ................ */ $"0200 0500 0200 0500 0200 0500 0200 0500" /* ................ */ $"0200 0500 0200 0480 0200 0280 0200 0242" /* .......€...€...B */ $"0400 0146 0400 0106 0800 00C0 3000 003F" /* ...F.......À0..? */ $"C000 0000 0000 0000 0005 0000 FFFF FFFF" /* À...........ÿÿÿÿ */ $"FFFF 0001 BBBB BBBB BBBB 0002 8888 8888" /* ÿÿ..»»»»»»..ˆˆˆˆ */ $"8888 0003 DDDD DDDD DDDD 0004 EEEE EEEE" /* ˆˆ..ÝÝÝÝÝÝ..îîîî */ $"EEEE 000F 0000 0000 0000 0000 0000 0000" /* îî.............. */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0222 2200 0000 0000 0000 0000 0000" /* ...""........... */ $"0022 2222 2222 0000 0000 0000 0000 0000" /* .""""".......... */ $"0222 2000 0022 2000 0000 0000 0000 0000" /* ." .." ......... */ $"0220 0000 0002 2200 0000 0000 0000 0000" /* . ...."......... */ $"2222 0000 0000 2220 0000 0000 0000 0FFF" /* ""...." .......ÿ */ $"FFFF FFF0 0000 0222 0000 0000 0000 F211" /* ÿÿÿð..."......ò. */ $"1111 110F 0000 0022 0000 0000 0000 F211" /* ......."......ò. */ $"1111 110F 0000 0022 0000 0000 0000 F211" /* ......."......ò. */ $"4111 110F 0000 0002 2000 0000 000F 2314" /* A....... .....#. */ $"4111 1110 F000 0002 2000 0000 000F 2314" /* A...ð... .....#. */ $"1111 1110 F000 0002 2000 0000 000F 2344" /* ....ð... .....#D */ $"1111 1110 F000 0000 2200 0000 00F2 1311" /* ....ð..."....ò.. */ $"1111 1111 0F00 0000 2200 0000 00F2 2222" /* ........"....ò"" */ $"2222 2222 2F00 0000 2200 0000 00F2 1311" /* """"/..."....ò.. */ $"1111 1111 0F00 0000 0200 0000 00F2 1311" /* .............ò.. */ $"1111 1111 0F00 0000 0200 0000 0F21 1311" /* .............!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1311" /* .....ð.......!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1311" /* .....ð.......!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1311" /* .....ð.......!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1311" /* .....ð.......!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1311" /* .....ð.......!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1311" /* .....ð.......!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1311" /* .....ð.......!.. */ $"1111 1111 10F0 0000 0000 0000 0F21 1131" /* .....ð.......!.1 */ $"1111 1111 10F0 0000 0000 0000 00F1 1133" /* .....ð.......ñ.3 */ $"1121 1111 10F0 0000 0000 0000 00F2 1113" /* .!...ð.......ò.. */ $"3221 1111 0F00 0000 0000 0000 000F 2111" /* 2!............!. */ $"1221 1111 0F00 0000 0000 0000 000F 2211" /* .!............". */ $"1111 1100 F000 0000 0000 0000 0000 FF22" /* ....ð.........ÿ" */ $"2110 00FF 0000 0000 0000 0000 0000 00FF" /* !..ÿ...........ÿ */ $"FFFF FF00 0000 0000 0000" /* ÿÿÿ....... */ }; data 'cicn' (135) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 000F FC00 007F FF00 01FF" /* ........ü...ÿ..ÿ */ $"FF80 03F6 0FC0 07CF 03E0 0F7F E1F0 1EFF" /* ÿ€.ö.À.Ï.à..áð.ÿ */ $"F3F8 3CFF F7BC 38FF FF1C 79FF FE1E 71FF" /* óø<ÿ÷¼8ÿÿ.yÿþ.qÿ */ $"FC1E 71FF F80E E3FF FC0F E3FF FC0F E3FF" /* ü.qÿø.ãÿü.ãÿü.ãÿ */ $"FC07 E3FF FC07 E7FF FE07 E7FF FE07 E7FF" /* ü.ãÿü.çÿþ.çÿþ.çÿ */ $"FE07 77FF FE0E 77FF FE0E 7FFF FE1E 3FFF" /* þ.wÿþ.wÿþ..ÿþ.?ÿ */ $"FE1C 3FFF FE3C 1FFF FE78 0FFF FEF0 07FF" /* þ.?ÿþ<.ÿþx.ÿþð.ÿ */ $"FFE0 03FF FFC0 01FF FF80 00FF FE00 003F" /* ÿà.ÿÿÀ.ÿÿ€.ÿþ..? */ $"F000 0000 0000 000F FC00 007F FF00 01FF" /* ð.......ü...ÿ..ÿ */ $"FF80 03F6 0FC0 07CF 03E0 0F7F E1F0 1E80" /* ÿ€.ö.À.Ï.à..áð.€ */ $"13F8 3C80 17BC 3880 1F1C 7900 1E1E 7100" /* .ø<€.¼8€..y...q. */ $"3C1E 7100 780E E200 F40F E3FF FC0F E203" /* <.q.x.â.ô.ãÿü.â. */ $"C407 E207 8407 E40F 0207 E51E 0207 E53C" /* Ä.â.„.ä...å...å< */ $"0207 7578 020E 75F0 020E 7DE0 021E 3FC0" /* ..ux..uð..}à..?À */ $"021C 3F80 023C 1F80 0278 0F80 02F0 07C2" /* ..?€.<.€.x.€.ð. */ $"07E0 03F6 0FC0 01FF FF80 00FF FE00 003F" /* .à.ö.À.ÿÿ€.ÿþ..? */ $"F000 0000 0000 0000 0006 0000 FFFF FFFF" /* ð...........ÿÿÿÿ */ $"FFFF 0001 BBBB BBBB BBBB 0002 8888 8888" /* ÿÿ..»»»»»»..ˆˆˆˆ */ $"8888 0003 DDDD DDDD DDDD 0004 EEEE EEEE" /* ˆˆ..ÝÝÝÝÝÝ..îîîî */ $"EEEE 0005 DDDD 0000 0000 000F 0000 0000" /* îî..ÝÝ.......... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 5555 5555 2200 0000" /* ........UUUU"... */ $"0000 0000 0000 0555 5555 5555 5552 0000" /* .......UUUUUUR.. */ $"0000 0000 0005 5555 5555 5555 5555 5000" /* ......UUUUUUUUP. */ $"0000 0000 0055 5555 0220 0000 5555 5500" /* .....UUU. ..UUU. */ $"0000 0000 0555 5500 2222 0000 0055 5550" /* .....UU.""...UUP */ $"0000 0000 5555 0FFF FFFF FFF0 0005 5555" /* ....UU.ÿÿÿÿð..UU */ $"0000 0005 5550 F211 1111 110F 0055 5555" /* ....UPò......UUU */ $"5000 0055 5500 F211 1111 110F 0555 5055" /* P..UU.ò......UPU */ $"5500 0055 5000 F211 4111 110F 5555 0005" /* U..UP.ò.A...UU.. */ $"5500 0555 500F 2314 4111 1115 5550 0005" /* U..UP.#.A...UP.. */ $"5550 0555 000F 2314 1111 1155 5500 0002" /* UP.U..#....UU... */ $"5550 0555 000F 2344 1111 1555 5000 0000" /* UP.U..#D...UP... */ $"5550 5550 00F2 1311 1111 5555 0F00 0000" /* UPUP.ò....UU.... */ $"2555 5550 00F2 2222 2225 5552 2F00 0000" /* %UUP.ò"""%UR/... */ $"2555 5550 00F2 1311 1155 5511 0F00 0000" /* %UUP.ò...UU..... */ $"0555 5550 00F2 1311 1555 5111 0F00 0000" /* .UUP.ò...UQ..... */ $"0555 5550 0F21 1311 5555 1111 10F0 0000" /* .UUP.!..UU...ð.. */ $"0555 5550 0F21 1315 5551 1111 10F0 0000" /* .UUP.!..UQ...ð.. */ $"0555 5550 0F21 1355 5511 1111 10F0 0000" /* .UUP.!.UU....ð.. */ $"0555 0555 0F21 1555 5111 1111 10F0 0000" /* .U.U.!.UQ....ð.. */ $"5550 0555 0F21 5555 1111 1111 10F0 0000" /* UP.U.!UU.....ð.. */ $"5550 0555 5F25 5551 1111 1111 10F0 0005" /* UP.U_%UQ.....ð.. */ $"5550 0055 5F55 5511 1111 1111 10F0 0005" /* UP.U_UU......ð.. */ $"5500 0055 5555 5311 1111 1111 10F0 0055" /* U..UUUS......ð.U */ $"5500 0005 5555 1131 1111 1111 10F0 0555" /* U...UU.1.....ð.U */ $"5000 0000 5555 1133 1121 1111 10F0 5555" /* P...UU.3.!...ðUU */ $"0000 0000 0555 5513 3221 1111 0F55 5550" /* .....UU.2!...UUP */ $"0000 0000 0055 5555 1221 1111 5555 5500" /* .....UUU.!..UUU. */ $"0000 0000 0005 5555 5555 5555 5555 5000" /* ......UUUUUUUUP. */ $"0000 0000 0000 F555 5555 5555 5550 0000" /* ......õUUUUUUP.. */ $"0000 0000 0000 00FF 5555 5555 0000 0000" /* .......ÿUUUU.... */ $"0000" /* .. */ }; data 'cicn' (138) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 000F F000 001F F800 3EFF F800 7FFF" /* ....ð...ø.>ÿø..ÿ */ $"FFF4 7FFF FFFE FFFF FFFF FFFF FFFF FFFF" /* ÿô.ÿÿþÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" /* ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFF 7FFF FFFE 00FF" /* ÿÿÿÿÿÿÿÿÿÿ.ÿÿþ.ÿ */ $"FF00 00FF FF00 007F FE00 003F FC00 001F" /* ÿ..ÿÿ...þ..?ü... */ $"F800 0007 E000 0000 0000 0000 0000 0000" /* ø...à........... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 000F F000 0010 0800 3EF0 0800 5FE0" /* ....ð.....>ð.._à */ $"07F4 42E0 050A C5C0 0307 FF77 EEFD 809F" /* .ôBà.ÂÅÀ..ÿwîý€Ÿ */ $"F901 80B8 1D01 FFA7 E5FF FF58 1AFF FFA0" /* ù.€¸..ÿ§åÿÿX.ÿÿ  */ $"05FF FFA0 05FF FF40 02FF FF40 02FF FF40" /* .ÿÿ .ÿÿ@.ÿÿ@.ÿÿ@ */ $"02FF FF40 02FF FF40 02FF 7F40 02FE 00A0" /* .ÿÿ@.ÿÿ@.ÿ.@.þ.  */ $"0500 00A0 0500 0058 1A00 0027 E400 0018" /* ... ...X...'ä... */ $"1800 0007 E000 0000 0000 0000 0000 0000" /* ....à........... */ $"0000 0000 0000 0000 0004 0000 FFFF FFFF" /* ............ÿÿÿÿ */ $"FFFF 0001 8888 8888 8888 0002 EEEE EEEE" /* ÿÿ..ˆˆˆˆˆˆ..îîîî */ $"EEEE 0003 CCCC CCCC CCCC 000F 0000 0000" /* îî..ÌÌÌÌÌÌ...... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 FFFF FFFF 0000 0000" /* ........ÿÿÿÿ.... */ $"0000 0000 0000 000F 0000 0000 F000 0000" /* ............ð... */ $"0000 00FF FFF0 FFFF 3300 0000 F000 0000" /* ...ÿÿðÿÿ3...ð... */ $"0000 0F0F FFFF FFF3 3333 3330 0FFF FFFF" /* ....ÿÿÿó3330.ÿÿÿ */ $"0F00 0F00 00F2 FFF3 3333 3333 0F2F 0000" /* .....òÿó3333./.. */ $"F0F0 FF00 0F2F FF33 3333 3333 00FF 0000" /* ððÿ../ÿ33333.ÿ.. */ $"2FFF FFFF FFFF 2FFF 3FFF FFF2 FFF0 FFFF" /* /ÿÿÿÿÿ/ÿ?ÿÿòÿðÿÿ */ $"FF3F F333 3333 F00F FFFF FFFF F00F 3333" /* ÿ?ó333ð.ÿÿÿÿð.33 */ $"333F F333 3333 F2FF F000 002F FF0F 3333" /* 3?ó333òÿð../ÿ.33 */ $"333F FFFF FFFF F0F0 0FFF FFF0 0F0F FFFF" /* 3?ÿÿÿÿðð.ÿÿð..ÿÿ */ $"FFFF FFFF FFFF 2F0F F000 000F F0F2 FFFF" /* ÿÿÿÿÿÿ/.ð...ðòÿÿ */ $"FFFF FFFF FFFF F0F0 0000 0000 0F0F FFFF" /* ÿÿÿÿÿÿðð......ÿÿ */ $"FFFF FFFF FFFF F0F0 0033 3000 0F0F FFFF" /* ÿÿÿÿÿÿðð.30...ÿÿ */ $"FFFF FFFF FFFF 0F10 0333 3330 00F0 FFFF" /* ÿÿÿÿÿÿ...330.ðÿÿ */ $"FFFF FFFF FFFF 0F13 3333 3333 00F0 FFFF" /* ÿÿÿÿÿÿ..3333.ðÿÿ */ $"FFFF FFFF FFFF 0F13 3333 3333 00F0 FFFF" /* ÿÿÿÿÿÿ..3333.ðÿÿ */ $"FFFF FFFF FFFF 0F11 3333 3333 00F0 FFFF" /* ÿÿÿÿÿÿ..3333.ðÿÿ */ $"FFFF FFFF FFFF 0F11 3333 3333 30F0 FFFF" /* ÿÿÿÿÿÿ..33330ðÿÿ */ $"FFFF 0FFF FFFF 0F11 1333 3333 31F0 FFFF" /* ÿÿ.ÿÿÿ...3331ðÿÿ */ $"FFF0 0000 0000 F0F1 1133 3333 1F0F 0000" /* ÿð....ðñ.333.... */ $"0000 0000 0000 F0F1 1111 3311 1F0F 0000" /* ......ðñ..3..... */ $"0000 0000 0000 0F0F F111 111F F0F0 0000" /* ........ñ...ðð.. */ $"0000 0000 0000 00F0 0FFF FFF0 0F00 0000" /* .......ð.ÿÿð.... */ $"0000 0000 0000 000F F000 000F F000 0000" /* ........ð...ð... */ $"0000 0000 0000 0000 0FFF FFF0 0000 0000" /* .........ÿÿð.... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000" /* .. */ }; data 'cicn' (137) { $"0000 0000 8008 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0002 0001 0002 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 0000 0000 000F F000 003F" /* ............ð..? */ $"FC00 00FF FF00 01FF FF80 03FF FFC0 07FF" /* ü..ÿÿ..ÿÿ€.ÿÿÀ.ÿ */ $"FFE0 0FFF FFF0 0FFF FFF0 1FFF FFF8 1FFF" /* ÿà.ÿÿð.ÿÿð.ÿÿø.ÿ */ $"FFF8 3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF" /* ÿø?ÿÿü?ÿÿü?ÿÿü?ÿ */ $"FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF" /* ÿü?ÿÿü?ÿÿü?ÿÿü?ÿ */ $"FFFC 1FFF FFF8 1FFF FFF8 0FFF FFF0 0FFF" /* ÿü.ÿÿø.ÿÿø.ÿÿð.ÿ */ $"FFF0 07FF FFE0 03FF FFC0 01FF FF80 00FF" /* ÿð.ÿÿà.ÿÿÀ.ÿÿ€.ÿ */ $"FF00 003F FC00 000F F000 0000 0000 0000" /* ÿ..?ü...ð....... */ $"0000 0000 0000 0000 0000 000F F000 003F" /* ............ð..? */ $"FC00 00F8 1F00 01C0 0380 0380 01C0 0700" /* ü..ø...À.€.€.À.. */ $"70E0 0E00 F070 0C01 F030 1803 F018 1807" /* pà..ðp..ð0..ð... */ $"7018 380E 701C 301C 700C 3038 700C 3070" /* p.8.p.0.p.08p.0p */ $"700C 3070 700C 3038 700C 301C 700C 380E" /* p.0pp.08p.0.p.8. */ $"701C 1807 7018 1803 F018 0C01 F030 0E00" /* p...p...ð...ð0.. */ $"F070 0700 70E0 0380 01C0 01C0 0380 00F8" /* ðp..pà.€.À.À.€.ø */ $"1F00 003F FC00 000F F000 0000 0000 0000" /* ...?ü...ð....... */ $"0000 0000 0000 0000 0002 0000 FFFF FFFF" /* ............ÿÿÿÿ */ $"FFFF 0001 5555 5555 5555 0002 CCCC CCCC" /* ÿÿ..UUUUUU..ÌÌÌÌ */ $"CCCC 0000 0000 0000 0000 0000 0000 0000" /* ÌÌ.............. */ $"0000 0000 0055 5500 0000 0000 0555 5550" /* .....UU......UUP */ $"0000 0000 556A A955 0000 0001 5AAA AAA5" /* ....Uj©U....Zªª¥ */ $"4000 0005 6AAA AAA9 5000 0015 AAAA AAAA" /* @...jªª©P...ªªªª */ $"5400 0056 AAAA 55AA 9500 005A AAA9 552A" /* T..VªªUª•..Zª©U* */ $"A500 016A AAA5 552A A940 016A AA95 952A" /* ¥..jª¥U*©@.jª••* */ $"A940 056A AA56 952A A950 05AA A95A 952A" /* ©@.jªV•*©P.ª©Z•* */ $"AA50 05AA A56A 952A AA50 05AA 952A 952A" /* ªP.ª¥j•*ªP.ª•*•* */ $"AA50 05AA 952A 952A AA50 05AA A54A 952A" /* ªP.ª•*•*ªP.ª¥J•* */ $"AA50 05AA A952 952A AA50 056A AA54 952A" /* ªP.ª©R•*ªP.jªT•* */ $"A950 016A AA95 152A A940 016A AAA5 552A" /* ©P.jª•.*©@.jª¥U* */ $"A940 005A AAA9 552A A500 0056 AAAA 552A" /* ©@.Zª©U*¥..VªªU* */ $"9500 0015 AAAA 802A 5400 0005 6AAA AAA9" /* •...ªª€*T...jªª© */ $"5000 0001 5AAA AAA5 4000 0000 556A A955" /* P...Zªª¥@...Uj©U */ $"0000 0000 0555 5550 0000 0000 0055 5500" /* .....UUP.....UU. */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000" /* .. */ }; data 'cicn' (136) { $"0000 0000 8008 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0002 0001 0002 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 0000 0000 000F F000 003F" /* ............ð..? */ $"FC00 00FF FF00 01FF FF80 03FF FFC0 07FF" /* ü..ÿÿ..ÿÿ€.ÿÿÀ.ÿ */ $"FFE0 0FFF FFF0 0FFF FFF0 1FFF FFF8 1FFF" /* ÿà.ÿÿð.ÿÿð.ÿÿø.ÿ */ $"FFF8 3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF" /* ÿø?ÿÿü?ÿÿü?ÿÿü?ÿ */ $"FFFC 3FFF FFFC 3FFF FFFC 3FFF FFFC 3FFF" /* ÿü?ÿÿü?ÿÿü?ÿÿü?ÿ */ $"FFFC 1FFF FFF8 1FFF FFF8 0FFF FFF0 0FFF" /* ÿü.ÿÿø.ÿÿø.ÿÿð.ÿ */ $"FFF0 07FF FFE0 03FF FFC0 01FF FF80 00FF" /* ÿð.ÿÿà.ÿÿÀ.ÿÿ€.ÿ */ $"FF00 003F FC00 000F F000 0000 0000 0000" /* ÿ..?ü...ð....... */ $"0000 0000 0000 0000 0000 000F F000 003F" /* ............ð..? */ $"FC00 00F8 1F00 01C0 0380 0380 01C0 0700" /* ü..ø...À.€.€.À.. */ $"00E0 0E03 C070 0C03 C030 1803 C018 1803" /* .à..Àp..À0..À... */ $"C018 3803 C01C 3003 C00C 3003 C00C 3003" /* À.8.À.0.À.0.À.0. */ $"C00C 3003 C00C 3003 C00C 3003 C00C 3803" /* À.0.À.0.À.0.À.8. */ $"C01C 1803 C018 1803 C018 0C03 C030 0E03" /* À...À...À...À0.. */ $"C070 0700 00E0 0380 01C0 01C0 0380 00F8" /* Àp...à.€.À.À.€.ø */ $"1F00 003F FC00 000F F000 0000 0000 0000" /* ...?ü...ð....... */ $"0000 0000 0000 0000 0002 0000 FFFF FFFF" /* ............ÿÿÿÿ */ $"FFFF 0001 5555 5555 5555 0002 CCCC CCCC" /* ÿÿ..UUUUUU..ÌÌÌÌ */ $"CCCC 0000 0000 0000 0000 0000 0000 0000" /* ÌÌ.............. */ $"0000 0000 0055 5500 0000 0000 0555 5550" /* .....UU......UUP */ $"0000 0000 556A A955 0000 0001 5AAA AAA5" /* ....Uj©U....Zªª¥ */ $"4000 0005 6AAA AAA9 5000 0015 AAAA AAAA" /* @...jªª©P...ªªªª */ $"5400 0056 AAA5 5AAA 9500 005A AAA5 52AA" /* T..Vª¥Zª•..Zª¥Rª */ $"A500 016A AAA5 52AA A940 016A AAA5 52AA" /* ¥..jª¥Rª©@.jª¥Rª */ $"A940 056A AAA5 52AA A950 05AA AAA5 52AA" /* ©@.jª¥Rª©P.ªª¥Rª */ $"AA50 05AA AAA5 52AA AA50 05AA AAA5 52AA" /* ªP.ªª¥RªªP.ªª¥Rª */ $"AA50 05AA AAA5 52AA AA50 05AA AAA5 52AA" /* ªP.ªª¥RªªP.ªª¥Rª */ $"AA50 05AA AAA5 52AA AA50 056A AAA5 52AA" /* ªP.ªª¥RªªP.jª¥Rª */ $"A950 016A AAA5 52AA A940 016A AAA5 52AA" /* ©P.jª¥Rª©@.jª¥Rª */ $"A940 005A AAA5 52AA A500 0056 AAA5 52AA" /* ©@.Zª¥Rª¥..Vª¥Rª */ $"9500 0015 AAA8 02AA 5400 0005 6AAA AAA9" /* •...ª¨.ªT...jªª© */ $"5000 0001 5AAA AAA5 4000 0000 556A A955" /* P...Zªª¥@...Uj©U */ $"0000 0000 0555 5550 0000 0000 0055 5500" /* .....UUP.....UU. */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000" /* .. */ }; data 'cicn' (139) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 FFF0 0000 FFF8 0000 FFF8 0000 FFF8" /* ..ÿð..ÿø..ÿø..ÿø */ $"0000 FFF8 0000 FFF8 0000 FFF8 0000 FFF8" /* ..ÿø..ÿø..ÿø..ÿø */ $"0000 FFF8 0000 FFF8 0000 FFF8 0000 FFF8" /* ..ÿø..ÿø..ÿø..ÿø */ $"0000 FFF8 0000 FFF8 0000 FFF8 0000 FFF8" /* ..ÿø..ÿø..ÿø..ÿø */ $"0000 0000 01F0 0000 01F0 0000 1FFF 0600" /* .....ð...ð...ÿ.. */ $"1FFF 0600 1FFF 0600 1FFF 0604 1FFF 0706" /* .ÿ...ÿ...ÿ...ÿ.. */ $"1FFF 03FF 1FFF 01FF 1FFF 0006 1FFF 0004" /* .ÿ.ÿ.ÿ.ÿ.ÿ...ÿ.. */ $"1FFF 0000 1FFF 0000 1FFF 0000 1FFF 0000" /* .ÿ...ÿ...ÿ...ÿ.. */ $"1FFF FFF0 0000 8078 0000 8058 0000 8078" /* .ÿÿð..€x..€X..€x */ $"0000 8008 0000 8008 0000 8008 0000 8008" /* ..€...€...€...€. */ $"0000 8008 0000 8008 0000 8008 0000 8008" /* ..€...€...€...€. */ $"0000 8008 0000 8008 0000 8008 0000 FFF8" /* ..€...€...€...ÿø */ $"0000 0000 01F0 0000 0150 0000 1E0F 0600" /* .....ð...P...... */ $"13FD 0600 1099 0600 110D 0604 1207 0706" /* .ý...™.......... */ $"140D 03FF 1219 01FF 1131 0006 10E1 0004" /* ...ÿ...ÿ.1...á.. */ $"1041 0000 1001 0000 1001 0000 1001 0000" /* .A.............. */ $"1FFF 0000 0000 0000 0004 0000 FFFF FFFF" /* .ÿ..........ÿÿÿÿ */ $"FFFF 0001 5555 5555 5555 0002 CCCC CCCC" /* ÿÿ..UUUUUU..ÌÌÌÌ */ $"CCCC 0003 DDDD 0000 0000 000F 0000 0000" /* ÌÌ..ÝÝ.......... */ $"0000 FFFF FFFF FFF1 0000 0000 0000 0000" /* ..ÿÿÿÿÿñ........ */ $"0000 F000 0000 0FFF 1000 0000 0000 0000" /* ..ð....ÿ........ */ $"0000 F000 0000 0F2F F000 0000 0000 0000" /* ..ð..../ð....... */ $"0000 F000 0000 0FFF F000 0000 0000 0000" /* ..ð....ÿð....... */ $"0000 F000 0000 0022 F000 0000 0000 0000" /* ..ð...."ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 F000 0000 0002 F000 0000 0000 0000" /* ..ð.....ð....... */ $"0000 FFFF FFFF FFFF F000 0000 0000 0000" /* ..ÿÿÿÿÿÿð....... */ $"0000 0000 0000 0000 0000 0000 000F 111F" /* ................ */ $"0000 0000 0000 0000 0000 0000 0001 0F21" /* ...............! */ $"0000 0000 0000 0000 0000 000F 1112 0002" /* ................ */ $"F11F 0000 0330 0000 0000 0001 00FF FFFF" /* ñ....0.......ÿÿÿ */ $"F10F 0000 0330 0000 0000 0001 0222 100F" /* ñ....0.......".. */ $"122F 0000 0330 0000 0000 0001 0221 0002" /* ./...0.......!.. */ $"F12F 0000 0330 0000 0300 0001 0210 0000" /* ñ/...0.......... */ $"2F1F 0000 0333 0000 0330 0001 0100 0002" /* /....3...0...... */ $"F12F 0000 0033 3333 3333 0001 0210 002F" /* ñ/...33333...../ */ $"122F 0000 0003 3333 3333 0001 0221 02F1" /* ./....3333...!.ñ */ $"222F 0000 0000 0000 0330 0001 0222 1F12" /* "/.......0...".. */ $"222F 0000 0000 0000 0300 0001 0222 2122" /* "/..........."!" */ $"222F 0000 0000 0000 0000 0001 0222 2222" /* "/...........""" */ $"222F 0000 0000 0000 0000 0001 0222 2222" /* "/...........""" */ $"222F 0000 0000 0000 0000 0001 0222 2222" /* "/...........""" */ $"222F 0000 0000 0000 0000 000F FFFF FFFF" /* "/..........ÿÿÿÿ */ $"FFFF" /* ÿÿ */ }; data 'cicn' (140) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0007 C000 0007 C000 0007 C000 001F" /* ....À...À...À... */ $"F000 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ð..ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 0007 C000 0004 4000 0005 4000 0018" /* ÿð..À...@...@... */ $"3000 1FE0 0FF0 1040 0C10 107F FE30 103C" /* 0..à.ð.@....þ0.< */ $"1E30 1008 0C30 1010 0630 1020 0330 1040" /* .0...0...0. .0.@ */ $"01B0 1080 00F0 1100 01B0 1200 0330 1100" /* .°.€.ð...°...0.. */ $"0630 1080 0C30 1040 1830 1020 3030 1010" /* .0.€.0.@.0. 00.. */ $"6030 1008 C030 1005 8030 1003 0030 1000" /* `0..À0..€0...0.. */ $"0030 1000 0030 1000 0030 1000 0030 1000" /* .0...0...0...0.. */ $"0030 1000 0030 1000 0030 17FF FFF0 1FFF" /* .0...0...0.ÿÿð.ÿ */ $"FFF0 0000 0000 0000 0004 0000 FFFF FFFF" /* ÿð..........ÿÿÿÿ */ $"FFFF 0001 5555 5555 5555 0002 CCCC CCCC" /* ÿÿ..UUUUUU..ÌÌÌÌ */ $"CCCC 0003 1111 1111 1111 000F 0000 0000" /* ÌÌ.............. */ $"0000 0000 0000 0000 0311 1300 0000 0000" /* ................ */ $"0000 0000 0000 0000 0102 0100 0000 0000" /* ................ */ $"0000 0000 0000 0000 010F 2100 0000 0000" /* ..........!..... */ $"0000 0000 0000 0001 1222 2211 0000 0000" /* .........""..... */ $"0000 0003 1111 1110 0000 0002 3111 1113" /* ............1... */ $"0000 0001 0000 0122 2222 2222 1322 0023" /* .......""""".".# */ $"0000 0001 0222 2133 3333 3333 3312 2213" /* ....."!333333.". */ $"0000 0001 0222 2211 1100 0003 1112 2213" /* ....."".......". */ $"0000 0001 0222 2222 1000 0002 3122 2213" /* ....."""....1"". */ $"0000 0001 0222 2221 0000 0000 2312 2213" /* .....""!....#.". */ $"0000 0001 0222 2210 0000 0000 0231 2213" /* .....""......1". */ $"0000 0001 0222 2100 0000 0000 0023 1213" /* ....."!......#.. */ $"0000 0001 0222 1000 0000 0000 0002 3113" /* ....."........1. */ $"0000 0001 0221 0000 0000 0000 0023 1213" /* .....!.......#.. */ $"0000 0001 0210 0000 0000 0000 0231 2213" /* .............1". */ $"0000 0001 0221 0000 0000 0000 2312 2213" /* .....!......#.". */ $"0000 0001 0222 1000 0000 0002 3122 2213" /* ....."......1"". */ $"0000 0001 0222 2100 0000 0023 1222 2213" /* ....."!....#."". */ $"0000 0001 0222 2210 0000 0231 2222 2213" /* .....""....1""". */ $"0000 0001 0222 2221 0000 2312 2222 2213" /* .....""!..#.""". */ $"0000 0001 0222 2222 1002 3122 2222 2213" /* ....."""..1"""". */ $"0000 0001 0222 2222 2123 1222 2222 2213" /* ....."""!#."""". */ $"0000 0001 0222 2222 2231 2222 2222 2213" /* .....""""1""""". */ $"0000 0001 0222 2222 2222 2222 2222 2213" /* ....."""""""""". */ $"0000 0001 0222 2222 2222 2222 2222 2213" /* ....."""""""""". */ $"0000 0001 0222 2222 2222 2222 2222 2213" /* ....."""""""""". */ $"0000 0001 0222 2222 2222 2222 2222 2213" /* ....."""""""""". */ $"0000 0001 0222 2222 2222 2222 2222 2213" /* ....."""""""""". */ $"0000 0001 0222 2222 2222 2222 2222 2213" /* ....."""""""""". */ $"0000 0001 0222 2222 2222 2222 2222 2213" /* ....."""""""""". */ $"0000 0001 2111 1111 1111 1111 1111 1113" /* ....!........... */ $"0000 0003 3333 3333 3333 3333 3333 3333" /* ....333333333333 */ $"0000" /* .. */ }; data 'cicn' (141) { $"0000 0000 8008 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0002 0001 0002 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 1FFF FE00 1FFF FF00 1FFF FF80 1FFF" /* ...ÿþ..ÿÿ..ÿÿ€.ÿ */ $"FFC0 1FFF FFE0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿÀ.ÿÿà.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF" /* ÿð.ÿÿð.ÿÿð.ÿÿð.ÿ */ $"FFF0 1FFF FE00 1000 0700 1000 0580 1000" /* ÿð.ÿþ........€.. */ $"04C0 1000 0460 1000 0430 1000 07F0 1000" /* .À...`...0...ð.. */ $"03F0 1000 0010 1000 0010 10C0 0010 11E0" /* .ð.........À...à */ $"0010 13D0 0010 13D7 6E10 1120 0010 10C0" /* ...Ð...×n.. ...À */ $"0010 1000 0010 1000 0010 10C0 0010 1120" /* ...........À... */ $"0010 1210 0010 1217 6E10 1120 0010 10C0" /* ........n.. ...À */ $"0010 1000 0010 1000 0010 1000 0010 1000" /* ................ */ $"0010 1000 0010 1000 0010 1000 0010 1FFF" /* ...............ÿ */ $"FFF0 0000 0000 0000 0003 0000 FFFF FFFF" /* ÿð..........ÿÿÿÿ */ $"FFFF 0001 5555 5555 5555 0002 CCCC CCCC" /* ÿÿ..UUUUUU..ÌÌÌÌ */ $"CCCC 0003 0000 0000 0000 03FF FFFF FFF4" /* ÌÌ.........ÿÿÿÿô */ $"0000 0300 0000 003D 0000 0300 0000 003B" /* .......=.......; */ $"4000 0300 0000 0032 D000 0300 0000 0030" /* @......2Ð......0 */ $"B400 0300 0000 0032 AD00 0300 0000 003F" /* ´......2­......? */ $"FF00 0300 0000 0005 5700 0300 0000 000A" /* ÿ.......W...... */ $"AB00 0300 0000 0000 0B00 0302 F800 0000" /* «...........ø... */ $"0B00 030B 5E00 0000 0B00 030D F900 0000" /* ....^.......ù... */ $"0B00 0305 F93F 3C7C 0B00 030B AE0A 8A2A" /* ....ù?<|....®ÂŠ* */ $"0B00 0302 5800 0000 0B00 0300 0000 0000" /* ....X........... */ $"0B00 0300 0000 0000 0B00 0302 5800 0000" /* ............X... */ $"0B00 0309 0600 0000 0B00 0304 2900 0000" /* ...Æ........)... */ $"0B00 0304 A93F 3CFC 0B00 0309 A60A 8A2A" /* ....©?<ü...ƦŠ* */ $"0B00 0302 7800 0000 0B00 0300 0000 0000" /* ....x........... */ $"0B00 0300 0000 0000 0B00 0300 0000 0000" /* ................ */ $"0B00 0300 0000 0000 0B00 0300 0000 0000" /* ................ */ $"0B00 0300 0000 0000 0B00 032A AAAA AAAA" /* ...........*ªªªª */ $"AB00 03FF FFFF FFFF FF00" /* «..ÿÿÿÿÿÿ. */ }; data 'cicn' (132) { $"0000 0000 8020 0000 0000 0020 0020 0000" /* ....€ ..... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0008 0001 0008 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 007F FC00 01FF FF00 03FF" /* ........ü..ÿÿ..ÿ */ $"FF80 07FF FFC0 0FFF FFE0 1FFF FFF0 3FFF" /* ÿ€.ÿÿÀ.ÿÿà.ÿÿð?ÿ */ $"FFF8 7FFF FFFC 7FFF FFFC 7FFF FFFC FFFF" /* ÿø.ÿÿü.ÿÿü.ÿÿüÿÿ */ $"FFFE FFFF FFFE FFFF FFFF FFFF FFFF FFFF" /* ÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFE 7FFF FFFE FFFF FFFF FFFF FFFF" /* ÿÿÿþ.ÿÿþÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFE 7FFF FFFE 7FFF" /* ÿÿÿÿÿÿÿÿÿþ.ÿÿþ.ÿ */ $"FFFC 7FFF FFFC 3FFF FFF8 1FFF FFF0 0FFF" /* ÿü.ÿÿü?ÿÿø.ÿÿð.ÿ */ $"FFE0 07FF FFC0 03FF FF80 01FF FF00 007F" /* ÿà.ÿÿÀ.ÿÿ€.ÿÿ... */ $"FC00 0000 0000 007F FC00 01F0 3F00 03C0" /* ü.......ü..ð?..À */ $"0780 0740 03C0 0E00 0560 1C20 0230 3A00" /* .€.@.À...`. .0:. */ $"0458 7510 08BC 6A80 111C 7548 227C E08F" /* .Xu..¼j€..uH"|à */ $"C4FE F55F FBEE FFFC 57FF DDFB BF7F FFD7" /* Äþõ_ûîÿüWÿÝû¿.ÿ× */ $"DBFF EFF6 5FEF FFB6 D7FF FDFB BF77 FFD4" /* Ûÿïö_ïÿ¶×ÿýû¿wÿÔ */ $"7FFF EFBF F55F FE47 E2AE 7C8A 055E 7110" /* .ÿï¿õ_þGâ®|Š.^q. */ $"42AC 7A24 015C 3440 20B8 1888 0078 0D40" /* B¬z$.\4@ ¸.ˆ.x.@ */ $"10F0 0790 01FC 03C0 07FE 01F8 1FFF 007F" /* .ð..ü.À.þ.ø.ÿ.. */ $"FFFF 0000 0000 0000 0012 0000 FFFF FFFF" /* ÿÿ..........ÿÿÿÿ */ $"FFFF 0001 CCCC CCCC CCCC 0002 FFFF FFFF" /* ÿÿ..ÌÌÌÌÌÌ..ÿÿÿÿ */ $"CCCC 0003 FFFF CCCC FFFF 0004 CCCC FFFF" /* ÌÌ..ÿÿÌÌÿÿ..ÌÌÿÿ */ $"FFFF 0005 CCCC CCCC FFFF 0006 9999 FFFF" /* ÿÿ..ÌÌÌÌÿÿ..™™ÿÿ */ $"FFFF 0007 9999 9999 CCCC 0008 6666 6666" /* ÿÿ..™™™™ÌÌ..ffff */ $"9999 0009 EEEE EEEE EEEE 000A DDDD DDDD" /* ™™.Æîîîîîî.ÂÝÝÝÝ */ $"DDDD 000B BBBB BBBB BBBB 000C AAAA AAAA" /* ÝÝ..»»»»»»..ªªªª */ $"AAAA 000D 8888 8888 8888 000E 5555 5555" /* ªª..ˆˆˆˆˆˆ..UUUU */ $"5555 000F 4444 4444 4444 0010 2222 2222" /* UU..DDDDDD.."""" */ $"2222 0011 1111 1111 1111 00FF 0000 0000" /* "".........ÿ.... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0010 1010 100F" /* ................ */ $"0F0F 0F0F 1010 1010 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0010 100F 0F0D 0C0B" /* ................ */ $"0101 010B 0C0D 1110 1010 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 100F 0F0C 010A 090A" /* .............ÂÆÂ */ $"0A0A 0A0A 0A01 0B0B 1110 1000 0000 0000" /* ÂÂÂÂÂ........... */ $"0000 0000 0000 0010 0F0D 0B09 0000 090A" /* ...........Æ..ÆÂ */ $"0A0A 0A0A 010A 0A0A 010C 1110 0000 0000" /* ÂÂÂÂ.ÂÂÂ........ */ $"0000 0000 0000 100F 0B02 0A00 0000 0009" /* ..........Â....Æ */ $"0A0A 0A01 0A0A 0A0A 090A 0B11 1000 0000" /* ÂÂÂ.ÂÂÂÂÆÂ...... */ $"0000 0000 0010 0F0A 0209 0200 0000 0009" /* .......Â.Æ.....Æ */ $"0A0A 0A0A 010A 0A09 0A00 0A0B 1110 0000" /* ÂÂÂÂ.ÂÂÆÂ.Â..... */ $"0000 0000 100F 0B02 0A02 0902 0000 0000" /* ........Â.Æ..... */ $"090A 0A01 0A0A 090A 000A 000A 0B11 1000" /* ÆÂÂ.ÂÂÆÂ.Â.Â.... */ $"0000 0010 0F0D 040A 020A 0209 0200 0000" /* .......Â.Â.Æ.... */ $"090A 0A0A 010A 0A09 0A00 0A00 0A0C 1110" /* ÆÂÂÂ.ÂÂÆÂ.Â.Â... */ $"0000 0010 0F0B 0604 0A02 0A02 0902 0000" /* ........Â.Â.Æ... */ $"090A 0A01 0A0A 090A 000A 000A 0901 1110" /* ÆÂÂ.ÂÂÆÂ.Â.ÂÆ... */ $"0000 000F 0D0A 0406 0406 020A 0209 0200" /* .....Â.....Â.Æ.. */ $"000A 010A 0A09 0A00 0A09 0A09 0A0A 0C11" /* .Â.ÂÂÆÂ.ÂÆÂÆÂÂ.. */ $"0000 100F 0C04 0A04 0604 0602 0902 010D" /* ......Â.....Æ... */ $"0D0D 0D0C 090A 000A 090A 090A 0A05 0B11" /* ....ÆÂ.ÂÆÂÆÂÂ... */ $"1000 100F 0B05 040A 0406 0406 0201 0B0B" /* .......Â........ */ $"0B0B 0B0B 0B01 0A09 0A0A 050A 0505 0111" /* ......ÂÆÂÂ.Â.... */ $"1000 0F0D 0505 0505 0A0A 0A06 010B 0B0B" /* ........ÂÂÂ..... */ $"0B0B 0B0A 000B 090A 0A05 0A05 0305 030D" /* ...Â..ÆÂÂ.Â..... */ $"1110 0F07 0505 0505 0505 0A0A 0C0B 0B0B" /* ..........ÂÂ.... */ $"0E0E 0E00 0A0B 0C0A 0503 0503 0503 0507" /* ....Â..Â........ */ $"1110 0F07 0505 0505 0505 0505 0D0B 0B0E" /* ................ */ $"0F0F 0F0D 0B0B 0D05 0305 0305 0305 0507" /* ................ */ $"1110 0F07 0505 0505 0503 0503 0D0B 0B0E" /* ................ */ $"0F00 000D 0B0B 0D03 0503 0505 0505 0507" /* ................ */ $"1110 0F07 0305 0305 0305 0305 0D0B 010E" /* ................ */ $"0F00 0F0D 0B0B 0D05 0505 0505 0505 0507" /* ................ */ $"1110 0F07 0503 0503 0505 050A 0C0B 0A00" /* ...........Â..Â. */ $"0D0D 0D0B 0B0B 0C0A 0A05 0505 0505 050D" /* .......ÂÂ....... */ $"1110 0F0D 0505 0505 0A05 0A0A 090A 000A" /* ........Â.ÂÂÆÂ. */ $"0B0B 0B0B 0B0B 0106 040A 0A0A 0505 0508" /* .........ÂÂÂ.... */ $"1110 100F 0B05 0A0A 050A 0A09 0A01 0B0B" /* ......ÂÂ.ÂÂÆÂ... */ $"0B0B 0B0B 0B01 0A02 0604 0604 0A04 0B11" /* ......Â.....Â... */ $"1010 100F 0C0A 050A 090A 090A 000A 0C0D" /* .....Â.ÂÆÂÆÂ.Â.. */ $"0D0D 0D0C 0909 020A 020A 0406 040A 0C11" /* ....ÆÆ.Â.Â...Â.. */ $"1000 000F 0D0A 0A09 0A09 0A00 0A09 0A01" /* .....ÂÂÆÂÆÂ.ÂÆÂ. */ $"0B01 0A09 0002 0902 0A02 0A04 0604 0D11" /* ..ÂÆ..Æ.Â.Â..... */ $"1000 0010 0F01 090A 000A 000A 090A 0A01" /* ......ÆÂ.Â.ÂÆÂÂ. */ $"010B 0A09 0000 0009 020A 040A 040A 1110" /* ..ÂÆ...Æ.Â.Â.Â.. */ $"0000 0010 0F0B 0A00 0A00 0A09 0A0A 0101" /* ......Â.Â.ÂÆÂÂ.. */ $"0B01 0A09 0000 0002 0902 0A04 0A0D 1110" /* ..ÂÆ....Æ.Â.Â... */ $"0000 0000 100F 0B0A 000A 000A 090A 0101" /* .......Â.Â.ÂÆÂ.. */ $"010B 0A0A 0900 0000 0209 020A 0D11 1000" /* ..ÂÂÆ....Æ.Â.... */ $"0000 0000 0010 0F0B 0A00 0A09 0A01 0101" /* ........Â.ÂÆÂ... */ $"0B01 0A0A 0900 0000 0002 0A0D 1110 1000" /* ..ÂÂÆ.....Â..... */ $"0000 0000 0000 100F 0B0A 090A 0A01 0101" /* .........ÂÆÂÂ... */ $"010B 010A 0900 0000 000A 0D11 1010 0000" /* ...ÂÆ....Â...... */ $"0000 0000 0000 0010 0F0B 010A 0101 0101" /* ...........Â.... */ $"0B01 010A 0900 0000 0A0D 1110 1010 1010" /* ...ÂÆ...Â....... */ $"0000 0000 0000 0000 100F 0F0D 0B01 0101" /* ................ */ $"010B 010A 0909 0C0D 11FF 1010 1010 1010" /* ...ÂÆÆ...ÿ...... */ $"1000 0000 0000 0000 0010 100F 0F0D 0C0B" /* ................ */ $"0101 0B0C 0D10 FF11 1010 1010 1010 1010" /* ......ÿ......... */ $"1010 0000 0000 0000 0000 0010 1010 1010" /* ................ */ $"1010 FFFF FF10 1010 1010 1010 1010 1010" /* ..ÿÿÿ........... */ $"1010" /* .. */ }; data 'cicn' (133) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 007F FC00 01FF FF00 03FF" /* ........ü..ÿÿ..ÿ */ $"FF80 07FF FFC0 0FFF FFE0 1FFF FFF0 3FFF" /* ÿ€.ÿÿÀ.ÿÿà.ÿÿð?ÿ */ $"FFF8 7FFF FFFC 7FFF FFFC 7FFF FFFC FFFF" /* ÿø.ÿÿü.ÿÿü.ÿÿüÿÿ */ $"FFFE FFFF FFFE FFFF FFFF FFFF FFFF FFFF" /* ÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿ */ $"FFFF FFFE 7FFF FFFE FFFF FFFF FFFF FFFF" /* ÿÿÿþ.ÿÿþÿÿÿÿÿÿÿÿ */ $"FFFF FFFF FFFF FFFF FFFE 7FFF FFFE 7FFF" /* ÿÿÿÿÿÿÿÿÿþ.ÿÿþ.ÿ */ $"FFFC 7FFF FFFC 3FFF FFF8 1FFF FFF0 0FFF" /* ÿü.ÿÿü?ÿÿø.ÿÿð.ÿ */ $"FFE0 07FF FFC0 03FF FF80 01FF FF00 007F" /* ÿà.ÿÿÀ.ÿÿ€.ÿÿ... */ $"FC00 0000 0000 007F FC00 01FF FF00 03FF" /* ü.......ü..ÿÿ..ÿ */ $"FF80 07F0 0FC0 0F80 03E0 1E20 03F0 3E00" /* ÿ€.ð.À.€.à. .ð>. */ $"07F8 7D10 0FBC 7A80 1F1C 7548 3E7C E08F" /* .ø}..¼z€..uH>|à */ $"FCFE F55F FBEE FFFC F7FF FDFB FF7F FFD7" /* üþõ_ûîÿü÷ÿýûÿ.ÿ× */ $"DBFF EFF7 DFEF FFBF D7FF FDFF BF77 FFFC" /* Ûÿï÷ßïÿ¿×ÿýÿ¿wÿü */ $"7FFF EFFF F55F FEF7 E2AE 7DEA 055E 73D0" /* .ÿïÿõ_þ÷â®}ê.^sÐ */ $"42BC 7FA4 017C 3F40 20F8 1E88 00F8 0FC0" /* B¼.¤.|?@ ø.ˆ.ø.À */ $"13F0 07F0 1FFC 03FF FFFE 01FF FFFF 007F" /* .ð.ð.ü.ÿÿþ.ÿÿÿ.. */ $"FFFF 0000 0000 0000 000F 0000 FFFF FFFF" /* ÿÿ..........ÿÿÿÿ */ $"FFFF 0001 CCCC CCCC CCCC 0002 FFFF FFFF" /* ÿÿ..ÌÌÌÌÌÌ..ÿÿÿÿ */ $"CCCC 0003 FFFF CCCC FFFF 0004 CCCC FFFF" /* ÌÌ..ÿÿÌÌÿÿ..ÌÌÿÿ */ $"FFFF 0005 CCCC CCCC FFFF 0006 9999 FFFF" /* ÿÿ..ÌÌÌÌÿÿ..™™ÿÿ */ $"FFFF 0007 EEEE EEEE EEEE 0008 DDDD DDDD" /* ÿÿ..îîîîîî..ÝÝÝÝ */ $"DDDD 0009 BBBB BBBB BBBB 000A AAAA AAAA" /* ÝÝ.Æ»»»»»».ªªªª */ $"AAAA 000B 8888 8888 8888 000C 5555 5555" /* ªª..ˆˆˆˆˆˆ..UUUU */ $"5555 000D 4444 4444 4444 000E 2222 2222" /* UU..DDDDDD.."""" */ $"2222 000F DDDD 0000 0000 0000 0000 0000" /* ""..ÝÝ.......... */ $"0000 0000 0000 0000 0000 0000 0000 0EEE" /* ...............î */ $"FFFF FFFF EE00 0000 0000 0000 000E EFFF" /* ÿÿÿÿî.........ïÿ */ $"FFFF FFFF FFFE 0000 0000 0000 00EF FFFF" /* ÿÿÿÿÿþ.......ïÿÿ */ $"FFFF FFFF FFFF F000 0000 0000 0EFF FFFF" /* ÿÿÿÿÿÿð......ÿÿÿ */ $"7888 8818 FFFF FF00 0000 0000 EFFF FF00" /* xˆˆ.ÿÿÿ.....ïÿÿ. */ $"0788 8188 88FF FFF0 0000 000E FFFF 2000" /* .ˆˆˆÿÿð....ÿÿ . */ $"0788 8818 878F FFFF 0000 00EF FFF2 7200" /* .ˆˆ.‡ÿÿ...ïÿòr. */ $"0078 8188 78FF FFFF F000 0EFF FF28 2720" /* .xˆxÿÿÿð..ÿÿ(' */ $"0078 8818 8FFF F0FF FF00 0EFF F482 8272" /* .xˆ.ÿðÿÿ..ÿô‚‚r */ $"0078 8188 FFFF 087F FF00 0FFF F646 2827" /* .xˆÿÿ..ÿ..ÿöF(' */ $"2008 188F FFF7 878F FFF0 EFFF 8464 6272" /* ..ÿ÷‡ÿðïÿ„dbr */ $"1BBB BAFF FF78 7885 FFF0 EFFF 4846 4621" /* .»ºÿÿxx…ÿðïÿHFF! */ $"9999 9FFF F788 5855 FFF0 FFF5 5588 8619" /* ™™Ÿÿ÷ˆXUÿðÿõUˆ†. */ $"9999 FFFF 7885 8535 3FFF FFF5 5555 88A9" /* ™™ÿÿx……5?ÿÿõUUˆ© */ $"99CF FFF9 A853 5353 5FFF FFF5 5555 55B9" /* ™Ïÿù¨SSS_ÿÿõUUU¹ */ $"9CFF FF99 B535 3535 5FFF FFF5 5553 53B9" /* œÿÿ™µ555_ÿÿõUSS¹ */ $"9FFF FB99 B353 5555 5FFF FFF5 3535 35B9" /* Ÿÿû™³SUU_ÿÿõ555¹ */ $"FFFF DB99 B555 5555 5FFF FFF3 5355 58AF" /* ÿÿÛ™µUUU_ÿÿóSUX¯ */ $"FFFB B999 A885 5555 5FFF FFF5 5585 88FF" /* ÿû¹™¨…UU_ÿÿõU…ˆÿ */ $"FF99 9999 1648 8855 5FFF EFFF 8858 8FFF" /* ÿ™™™.HˆU_ÿïÿˆXÿ */ $"F999 9991 8264 6484 FFFE EFFF 5878 FFFF" /* ù™™‘‚dd„ÿþïÿXxÿÿ */ $"ABBB BA77 2828 4648 FFF0 0FFF F78F FFF7" /* «»ºw((FHÿð.ÿ÷ÿ÷ */ $"8191 8702 7282 846F FFF0 0EFF F8FF FF78" /* ‘‡.r‚„oÿð.ÿøÿÿx */ $"8119 8700 0728 484F FF00 0EFF FFFF F788" /* .‡..(HOÿ..ÿÿÿ÷ˆ */ $"1191 8700 0272 84FF FF00 00EF FFFF 0878" /* .‘‡..r„ÿÿ..ïÿÿ.x */ $"1119 8870 0027 2FFF F000 000E FFFF 8781" /* ..ˆp.'/ÿð...ÿÿ‡ */ $"1191 8870 0002 FFFF E000 0000 EFFF FF81" /* .‘ˆp..ÿÿà...ïÿÿ */ $"1119 1870 00FF FFFE 0000 0000 0EFF FFFF" /* ...p.ÿÿþ.....ÿÿÿ */ $"1191 1870 FFFF FFEE EE00 0000 00EF FFFF" /* .‘.pÿÿÿîî....ïÿÿ */ $"FFFF FFFF FFFF FEEE EEE0 0000 000E EFFF" /* ÿÿÿÿÿÿþîîà....ïÿ */ $"FFFF FFFF FFFE EEEE EEEE 0000 0000 0EEE" /* ÿÿÿÿÿþîîîî.....î */ $"FFFF FFFF EEEE EEEE EEEE" /* ÿÿÿÿîîîîîî */ }; data 'cicn' (142) { $"0000 0000 8010 0000 0000 0020 0020 0000" /* ....€...... . .. */ $"0000 0000 0000 0048 0000 0048 0000 0000" /* .......H...H.... */ $"0004 0001 0004 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0004 0000 0000 0020 0020" /* ............. . */ $"0000 0000 0004 0000 0000 0020 0020 0000" /* ........... . .. */ $"0000 0000 0000 211E 79E0 2120 4110 2120" /* ......!.yà! A.! */ $"4110 211C 79E0 2102 4180 2102 4160 1E3C" /* A.!.yà!.A€!.A`.< */ $"7910 0000 0000 0000 0000 0000 0004 0000" /* y............... */ $"0038 0000 0040 0000 0080 0000 0100 0000" /* .8...@...€...... */ $"0100 7FFF FFFC 7FFF FFFC 7FFF FFFC 7FFF" /* ...ÿÿü.ÿÿü.ÿÿü.ÿ */ $"FFFC 7FFF FFFC 7FFF FFFC 7FFF FFFC 7FFF" /* ÿü.ÿÿü.ÿÿü.ÿÿü.ÿ */ $"FFFC 7FFF FFFC 7FFF FFFC 7FFF FFFC 7FFF" /* ÿü.ÿÿü.ÿÿü.ÿÿü.ÿ */ $"FFFC 7FFF FFFC 7FFF FFFC 0000 0000 0000" /* ÿü.ÿÿü.ÿÿü...... */ $"0000 0000 0000 211E 79E0 2120 4110 2120" /* ......!.yà! A.! */ $"4110 211C 79E0 2102 4180 2102 4160 1E3C" /* A.!.yà!.A€!.A`.< */ $"7910 0000 0000 0000 0000 0000 0004 0000" /* y............... */ $"0038 0000 0040 0000 0080 0000 0100 0000" /* .8...@...€...... */ $"0100 7FFF FFFC 4000 0004 5555 5454 4000" /* ...ÿÿü@...UUTT@. */ $"0004 4000 0004 5555 5554 4AAA 88A4 5555" /* ..@...UUUTJªˆ¤UU */ $"5554 4AAA 80A4 5555 4154 4AAA 88A4 55FD" /* UTJª€¤UUATJªˆ¤Uý */ $"5554 4000 0004 7FFF FFFC 0000 0000 0000" /* UT@....ÿÿü...... */ $"0000 0000 0000 0000 0004 0000 FFFF FFFF" /* ............ÿÿÿÿ */ $"FFFF 0001 FFFF FFFF CCCC 0002 7777 7777" /* ÿÿ..ÿÿÿÿÌÌ..wwww */ $"7777 0003 8888 8888 8888 000F 0000 0000" /* ww..ˆˆˆˆˆˆ...... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 00F0 000F 000F FFF0 0FFF F00F FFF0" /* ...ð....ÿð.ÿð.ÿð */ $"0000 00F0 000F 00F0 0000 0F00 000F 000F" /* ...ð...ð........ */ $"0000 00F0 000F 00F0 0000 0F00 000F 000F" /* ...ð...ð........ */ $"0000 00F0 000F 000F FF00 0FFF F00F FFF0" /* ...ð....ÿ..ÿð.ÿð */ $"0000 00F0 000F 0000 00F0 0F00 000F F000" /* ...ð.....ð....ð. */ $"0000 00F0 000F 0000 00F0 0F00 000F 0FF0" /* ...ð.....ð.....ð */ $"0000 000F FFF0 00FF FF00 0FFF F00F 000F" /* ....ÿð.ÿÿ..ÿð... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0200 0000 0000 0000 0000 0000 0000 0022" /* ..............." */ $"2000 0000 0000 0000 0000 0000 0000 0200" /* ............... */ $"0000 0000 0000 0000 0000 0000 0000 2000" /* .............. . */ $"0000 0000 0000 0000 0000 0000 0002 0000" /* ................ */ $"0000 0000 0000 0000 0000 0000 0002 0000" /* ................ */ $"0000 0333 3333 3333 3333 3333 3333 3333" /* ...3333333333333 */ $"3300 0300 0000 0000 0000 0000 0000 0000" /* 3............... */ $"0300 030F 1F1F 1F1F 1F1F 1F1F 1F11 1F1F" /* ................ */ $"1300 0301 1111 1111 1111 1111 1111 1111" /* ................ */ $"1300 0301 1111 1111 1111 1111 1111 1111" /* ................ */ $"1300 030F 1F1F 1F1F 1F1F 1F1F 1F1F 1F1F" /* ................ */ $"1300 0301 F1F1 F1F1 F1F1 F111 F111 F1F1" /* ....ñññññññ.ñ.ññ */ $"1300 030F 1F1F 1F1F 1F1F 1F1F 1F1F 1F1F" /* ................ */ $"1300 0301 F1F1 F1F1 F1F1 F111 1111 F1F1" /* ....ñññññññ...ññ */ $"1300 030F 1F1F 1F1F 1F1F 1F11 111F 1F1F" /* ................ */ $"1300 0301 F1F1 F1F1 F1F1 F111 F111 F1F1" /* ....ñññññññ.ñ.ññ */ $"1300 030F 1F1F FFFF FF1F 1F1F 1F1F 1F1F" /* ......ÿÿÿ....... */ $"1300 0301 1111 1111 1111 1111 1111 1111" /* ................ */ $"1300 0333 3333 3333 3333 3333 3333 3333" /* ...3333333333333 */ $"3300 0000 0000 0000 0000 0000 0000 0000" /* 3............... */ $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ $"0000" /* .. */ }; data 'ALRT' (200, "Quit") { $"0042 006A 00D0 01DC 00C8 4444 300A" /* .B.j.Ð.Ü.ÈDD0 */ }; bochs-2.6/build/win32/0000755000175000017500000000000012020641473014375 5ustar guillemguillembochs-2.6/build/win32/vs2008ex-workspace.zip0000644000175000017500000006447712020641473020436 0ustar guillemguillemPK¤¡Au9ðf‡%vs2008/bochs.sln­šÍŽÛ6ÇÏY`ßÁØ^R$\I‘‡(’jmtöøC»Qk[ ËNS¤y²úH}…Ž${×Jju(è,)3úsø1Dþùëïë«Ê宪«ûýìç²>Ì׳»ýaUV³»j}Ø—Õv–—ëâõ,¯v›9Ø»ºyÈè-¥×W_~ä^½š…»¢®gœR}}õfWýZ,÷/o>êÌ2Mt&,aÌS¢=c„RKaðVðO7_Ͼ™Ý,ªå»úæõ±qû~ù”¦ÿÑR°J½",£”Á17„Ó ¤ ž+ª>Ý\_½8ú½ƒèËc×ÅvUl—eQ7ž«z|¿yñQ&\KM=Ia#F:F —ZRš© Õ'øΰEfYžkÃ=á¹L‰Š‘ŒÃ·/\bM–RÉZ$ʰEº,̓OrN‚óà ÑLJ’RO•©Sœ¶H”a‹d”šD‰@¬£t¥)ɘΠO3ø¯y®E¢ ;-•b΃ef¥ç*%VjE²Œ2ÌÅD§%ưCæ:w‰äð=©‰¤&†Á—9k’\B $ù‰1l‘&ä§ I"ƒ&‚C,OɅѩ˸UR¶H”a‹T*1<€¥L2GD*¢SƉ”^{ÉËB7<(Ã.‰MK‘pÈ ꤆(Ó†9å·]a »Ïe©j'aç6%&M ݸñÆ2¥,ïFcØ"AŠ r9«d0£Áš"•óVÎ4Õ-eØ"¹3!ã_Ž ªƒ¥IŒ%Á&–&I’%¶›(Ã)mâò ´6 ¸ðÆ-²@¼MBâ´Œu#Ž2l‘ZçŒÄC‚êšk˜%YšäH¥ ݇£ »áIƒñ¼å.ÕC Ää>*·T0™ÃZ×!Q†]^ɸ÷9Q>m¾–+ë„ ²™hŽ)I]èòcȰ]õ—Ùë«çGc—þoWÅâðЮþÇöù€Rðf’@–ÕfSî»@ºöy ¨„›&r3(º8Úæy¨õxŠ0–‡Æ!üé¹ÇdßîWe=¯7Ï®uj"ˆûNƒû¾¨ýk ÷‡²qzC€YŸ§p_V«â}ã²môæf¥œ"„M±©v4>»Öy¨óÓAlË庬ۅáØ<uæš"ŒzX´‡ä¶ÑSs˜hMX-Ž«ÂjÑ›˜óñdIùv[ì¯v¿=%çéÁyH¨Üt!ÕÕa»z¨íöÂQ§ çP/žƒÎy(¨ãØt¡¼[=mh½½%sù,¤o×Õb¾†sI×8•~§ ÖUÛûòá°›77ëùþjÙ® Ü'£æ ä›3ÇŸ¿”Û„Ã˳^óò§b]Ìëâéu¯ß‰zî¿çî@4P“ž‡ƒ«yoÏâ¼µàê}á-;”ëÕ-ÍêIÔ‹ísñÆŸãû’‡:.¢µ‹§]ÖÇŠÑn qH;Ô ­]<í²v8VŒvcˆCÚ¡Žåhíâi—µÃ±b´CÔSSോ¦ h‡bEi7‚8¤ªBkO»¬Ž£Ýâv¨:­]<í²v8VŒvcˆƒsS„âçl4m`΢XQsvqpŸÅTÏø}6š6°Ï¢XQûìâv¨¢­]<í²v8VŒvcˆCÚ¡n*ÐÚÅÓ.k‡cÅh7†8˜w˜+|ÞEÓòÅŠÊ»ÄÁ}s7„ßg£iû,ŠµÏŽ i‡ºÄBkO»¬Ž£Ýâ`ÞanÜðyMÈ;+*ïF‡´C]¢µ‹§]ÖÇŠÑn q°&ÃÜeâk²hÚ@M†bEÕd#ˆ—µûßËÔÓ=é›]õXìö§ÿÕÓ¿Ïý®\=õ¬VXäöû»ðŸžž\_ý PKže@2´˜à¦&vs2008/bochs.vcprojíZ[oâ:~f¥ýÚ‡]ír)ìö¨J9«rëA¢PA/ç 9În“8²–žË?c'BKÉVÚ£.â*qfì™ù¾­ž|Ÿ{îÁ=ɸ_ËËùð)w˜?­åo˜ïðY8¬|«ä¿ÿþþÝÉ5“!q‡*t¿ü¨zÿ.?]>PËG"ÏŸóøé:™úøK¹¬zÄC!›Ó™Ì/UÏ®:ÍZþïÓòñ×ÊoÍ£Âa½\.|ýzxT8®WŽ •rëèÛq«Y9*ý«Õ.‰˜‚j œì‹»Å*f 44wrá5á“úmùª_bлjEËçJF£”R9¹äÜm3¢·RúµÁý ›†‚(\6^"5¶²NìpúÏrµ\?TA¨šL ã\<ÖòÅQ±8âömÁÑ¢‘PÇW ŽI=d®ÓåSbmº¯ %ã…#ÌuL?gÊ‹ôLè#°ÌSsíÝÖ=øJŽäK¡TÜ3:YÄÿ<ï6‰"gàž‹,:7`AÜ3 îùãéžwšÝ¥\NÃG8’Hcd¬¨\;–ÿM¡£‰oF·Á½ÅWŒËõ¥16<[`Ÿ;u¦GˆÛñ©: º2‘]_Ð4†l¡‡`Œ¤ í˜I˜ÿ€Ä¢ %H>$‘É(ÌÎN¯Z±ÆÍVýêÌ7ú½a¿Û²Æ8Üìß ­žùO‚ŒSKÆ-د'§‘ÎÒÿ ¡ è,ñGJðlô¼Ë¤Â:Øå4öxM1‰Š­3çÙ©vpÌ&Oó¥N$,Qx^ü†_¯ ÷àÖòÕxtÀ8 * êÄGöÔòÔ8¯r¦Ðt|]ÂŒÁmó°Ç Ü">&©3ÉCAá)ò›U7ël†v¼Š]ËM(tÉ*W«ÛVÃ)»Ì¿ËœÓZ8eÓ’«MÀwp¯3,}`¾ç]f a¨r«óò 9½‹ž°Mí~G0OàЋcFФ'î¢Ôe@2® €À° H•ªŸ‹¯ëx§¦†öðQ*ð–é0 ¸ëíhb(´ËÏšž­9ÐPÏ…‘ÖAN%zT€Ï 12ÐêTG Sm‹ÝÌTw›(~YDë’¦E3D~+¾¶¤ÛÖmÏ<Èbài`çÂ&,[®]p©6ïi'¥TðrO2Ùº gëKRÂûÎdß™<¡ÆÿÑ›$›fÇw±VµCŸêñÖ< ~|ÒÉÖ¼G¯ï]zë½Kcp9¶WƒÖ¸×ßœzÞÙ0)MJàž™£×JIZïn’rÜò v)‰o¦[Ðw]}[”Få‡Ú Dõ¥FhMf{+´¦ðÊfèÍ4;½]kvÒ|y¡Ý9ÌŠU¶†f…9vÌœÍ,vìÅâ¿r´aòÑÜA˜Êdë aô wðØm/–y‹=T _©‹ZŠ.€0 •\­½/nŠÌ#v+½×ÐÔ#-‰Ôò4,jÑùÜÔr`b ‹;®Åð7 n-›¨Tk¡gˆ) .ÚvDÍ 7¨±¸Hã(Ç‘ÊÓžpãMÕBq5[6âm{êBlcÉL$J‰Õ¥'fgóç™.÷{}È€¯ {pw\—§Z±™êg„ÞíÞ] §ŒïáÝUx=Âü=º»Š.—{xwÞ€Ž¥98î!ÞYˆÝpº¯Ð¿4¾æÏÎŽÚÑ…çsG힨k†Gí™g1ßÍz°Ž®/f)Ædå›=ÿÑæ•úñ¡þuÊÑvõ:Ýe-ܨ¿ˆäæô9(å …e{å¸SKÐ þ”e3ßSiMÙĺ ¦øó'+TæfL€,ŠŸ›à/Ü ¿ÍüýÉo`E4]¹Ü&n|u¶|9)=óÿe8þPK{hÒ>fòovs2008/bxcommit.vcprojíXmoÓ0þ<$þŠø‚v] ˆ)+¨MÛQ©ë¦v/|˜49ε1$vd;£ãå¿sŽ“†m¬ /B ñ!Sb?ç;?÷œ}ëÞëU=¸©˜à]g§Ùr§"`|ÙuÎÄÕØi?o;¯_Ý¿·wÊTJ¢¹N&ޤxTß¿·•¿_%Ðu,ä÷䉃S§ÅÒ»O[-30%1‚üqÌ´SZ]çSÛÛöÛ/G ¯ýl·ñ¬ÝÚiìvv{a¯Óku:~§÷â‹1;&r z$q½B¾_;ʼ¼Âgï("z!d¬ÌWùi>lfƒ¶c¶3‹ík&{ÇBD#²“×?=Ál™J¢Ñm6tcì?3ˆ€(ø\úÛ:Lu’ê“@µW]§yÞlž ÿ]CZ°…¹CÀˆ†Jð5÷6;Å2!H¦!@²újhÕu>:õÆ\iE¸üãS/ÏÆ$´:?I–’0’">õ^´š—*Á%”]öDÁáâ`ä!ëv w<9`œÅì#(o–òcÄù’È«E–ЂDëpC" Õ ç »NÎK?eQ0KC´  0ã‡læ ³›¡Ž­]–›2|[3o6™íð¸6Ó¿}§—*-â̦üíÁd@4ÙH¼ulÎÀŸƒ¼dîÕÕÙŒ“·…i.6ˆÛÒ8/j­©#?7z˜Ri(¶6•”L<'/#D'Ú$šè¬ì:ùè˜GŒÃ(åÔŒW áùÙ’zAÀ̉ƜFi°–5…Ñ7s¦ …FA)!QŒŒgFˆ8O;mw:öOöÝ ïp:?œ ñev|1z'³áÅôðâ¬7›Ž§ûó|±¹–Œ/0öì\Ó2…|5ªK®u¼5äÄÖÛ˜À%DÆß¯ÍË(©e&(9Ý”ƒ„†JAŒ>ä„)ëNµTÞ¶.÷MeÞáaÀz"û8œ§xƒÁ‘½g;,³8O“D"÷sM¤N“>á¤Ýy¥> ÇBf D*)”©–ö÷lªä`…£¼4Ò©4Ç^UÞpI“ÒÚç‚—1­ðªŒÃª‹Y5/!F$Â(«Ù¾VW¯TYௗöçWJC\z›sBF!XŽÆu9m| W@SC0r„ô˜·²4ìñ{@hȸ¡ºŠ·žÙ·®¡¶¥kº„¿‡:о¢´ßõSë+Zå|´òDR'Ê^’œ‚d V¯TŽ„Òw_k{Û×ZÍÍÉütY¯5 ´²1)¡ÿÛ’ÿmIÑ–”ªØþ3Ië·6׎ܨO£yá…@ß#¾sGk±SÝ3”ý\Ç`m7õ Q»[°ð_ì¶²fÌÍ?VYÀ£ìùËz‰‹¿¬—°ä×é$Úµs‘5Ü̉ýï~{×%ñßìn ©ll À)( ¹ñ½þ${Õ ¿é4æYE>È Öµ…tš$.uéjåJê°p¥+‚Èeø„É;×'ú›ëÔ:Ée Æv GD‡])™¢%Û–kkWÞêƒ6üLSš–„V\CÕWŽ…m8ˆJD¾zO%^&©¿µ›zÛÌJÿ_ߤȕket‡êì%û=Õ…nˆº Quaì2ÕÕÍÂi÷ò4ug!0*\šJ×7ˆ–Xm|´ë3îÊ¥r—lá¾K–ø@öÇZßôjßóŠÜ„O¢¼Z˽íïü˜‹ã_PKhÒ>QUƒ%‹vs2008/bximage.vcprojíX[oÓ0~‰ÿ€"@Юë¸*+¨MÛQ©ë¦v*MNrš˜%vd;¥ãòß9Ž“fëVB ñ-q¾sûÎññiöß­âèᄤœu¬ÝfËzÌã>eAÇ:§ÌçŸdc·ý¢m½{ûàþþ•)‰f*õ)?ü#xêÁý{ùÝÉUË@:OŸZøê¬PýæY«¥&$F»¢1 À*…NGýŽõe·Õz³÷òù ÑuZÝÆóç­WÞîëa£ýª×{9è¿nž;ß´Ø ¨¡@uŸ¸¸\ÛÉŒ¼Åkÿ8"jÁE,õSù¨Œ:¾½¶¥v2‰"û'œGC4/o>:œ-h ¢Ðl¶´±vÍNÜ4øZZ»w”ª$U}*0p.®:VsÞlιû±ák¨˜ƒO‰‚ è Ã& »…’Uà#Í u5 ”ìXŸ9#&‰"TþäÌÉóЇI#%ç§I ˆCÁã3çe«¹” ªFí©„£ÅáÐA¾ÍB÷d|HégÎ4e'4†1uW§’èЂDrwC"ˆ‡ÑÍ@u¬œ“^J#ÌM±vÃ׎͋õÆ£Ç&çšÓ'ÍPÅF.£Þ$ ïÖœë€ “,)ýÚàw¶ 8©T<ÎdêÀ?ŽûD‘`€ÄsQGæÜˆ%õé^]ý”ìá¨?.q÷0ÍñYó|‹5Uäæïó)4¿F ’±ÃãáâšÙ£Dé,Uî6~ß§z…D#æE©¿.X =kæ0L ‘Rr…FY&„ˆóÑd¯m_ô½ÓûÂ9šÌŽÆƒ\¨G$õ°¤Ð.8!x—ˆßËߙ催úÒg|÷×Qo§(ñÂ")!v1â1• {à˜{&ÒMÑ‚ Wï™;•¯=á¸b])äìo…ŸÁ´]XBT†9K“D k3E„J“a DÇR"…‘µ˜ÓÍ+sx˜Ý !•UERàOAòTxp=ãU¢wÉT%Ú¤8G9ØhR¡›Uko¯ÊªSvY{7kpéÓºéþ°`Uð©¥±”ÄhŽ`*ÚµS‘ojØL‰­Õ¸³+© .kvJ˜Ïuõu¡àŽÒfÊ׺‚+ðR­ É@nîAÓ‰R52ßÕ1Öj<„ÑHU«)ö~ u =éÐjnëçЕ^•åáÊáI»Ir‚.h½ qÌ¥Ú~äìïÜ8¦<2L!"¡ÞÐ ¸ÆØP‚ÿÿ38Ü*?3:gÛˆE”Á0ež^¬Âò#¿u¶˜Üœ-ðfzr18§ÓÁÅäèâ¼;Œ&³¢)AYpŒ¾ã?Ó¶LE÷0âFë0²ó[÷×µxÍÁ¤LAýÑdSxûpRbjŽ'¥À/(Ù2ùËœÞ:#Èn5Ù·³ê¢òªóÝÿSÉoŸJr–ÿɹdcIfkSX€æ4çõ§‘ìV¸6Í̲mú0ƒÓÒ±¼$±=Û[­láÙ>,las?²)^aòÑv‰ºvX#y]B„¾-ᘨPŸó˜JoM¶¡Úˆr·F­­ßgJÁ’ÍŠÓ­ú 2°´¦‘kïÊbÆ)³‹¼ßŠ¥FåDù¯‡i^ä…kªhKÑ™óõ®¢ íË.Ä¢ c›²¨n‰y™;ÍâDÞp¨B˜r–óÐ7úk:¸ô!Ù­OÈäÖ}H=n{©°Ý8±ý(ÀÝØÆKÙ.e¶¤Ð…ý1 ð‚ì‘Þ´jîó†pq—DÒ,—û;w|DÆõïPKmhÒ>hžã%ævs2008/bx_debug.vcprojíYëoÓ0ÿ ÿŠø‚vëÆc(+¨MÛQ©”©Ýƒ•*'¹¶ÇŽlg´<þwÎqÒt쑎ç€}Øæ\îÎw¿;ßÏÑv_Î#v÷¤¢‚×ZuÓ¹ <!åÓºsLy(>¨JmëÉ–óòÅÛ»GT%„ uR±/Å;ôÛ·²ÕÁ"†ºcUîz:øê(wýüÑæ¦ôI„Jþ|‚ŸLÂzï°Ûª;Ÿvv:µš×lVZµÇÊãç;µJãy­QivÚÏwžyÏžsy¸ð3º0,0-ýåSܪ]r­FQNúLØ¥ù¬^‡þ¢Œì‹+”šÁdõ¯.ó­Ì{e[ÿníO¥ù ‚òd~sð¯Yñ~c"ÕÍÉÿ+Šÿ›N¾ZD¾`êæì_³ò¯_él©A^p‹´ˆçÝ"gxYŒÝÞ"g‘K9[ûÎ(‚™ªæ”Wë¼ M¥Ä¸´mÍïvb§ázQ ÆTÅ’hîíÒ*Y±J—{Lø„)+.v7Îù·Ê¿PK†²y@:…æ Ša½vs2008/cpu.vcprojíÝoÓ0ÀŸAâ@   ƧJA¬P© ´²‡I‘ë\ƒcG¶S2>þwì¤% - âù‡n‰{w¶ïwö9‰Û>|\¤üâ”fRô;7»[‹ ¨ ™ˆûC&BùN_¿yëέÎãGÎ?<`:'|fòÉ—J¾j.œ?·g‚¥ì=èÁ^.^±¦l®ˆ:Þ×$¶ Š×°lnB¡Ô L¿³ôÉNÎx8•±s±kží¾kØÑªüú¥ËsçÓ+ÝĤ•^éú –;ZùÜuJÝÑ„qoWò7NUäÚÈ´ÔÙDüõóéò(bÙl¢só¨£`Ý]ÿ’îóÉpºQ7¦™fŒCmÕF\fbêA⨅!s%„Oåyø%ÎØ±qv;˜ÐFå)s¤M>×GKeëßLI ZKe£†‰Ò”Õ;œìnßêÃÑÎþÓ^0ìôv—Çöá‹ÃÙÒ€ S‡‰yjôêAø HÊ…Ä·D³¼›ÑdÕ­!sPS¦ ñTÒ²¯ß©­ü1wÁþ#Ãu÷d¬Hêï NÔzøTñC¢„«Àûíeé,Ï2ZÏ Q&Ïvˆ°ÀûëOXJ”sÃD¸Y§lð¸<°ÎXDÂ=Ð2WN0_£ú#uP+œK©AÎM®À¶rk{{]mÖ䔉·Ã*µðrÂ<58›¯wøºzŸ¸Vn4ð‡ÖùoaÑMkÑu \Û×®¯sM×Õ:.2Û¤y/¥6§Ï‘oœÈ+?Ïq{ÀhØ,Ë©Jxƒ*2"–ËÝ Sá2áf‰p÷«D ö^³Ñ`o쾟ìíNvŸ®âÌ(&â—Rrû¯ž¾K•u 2ç_ºU&7‹ÕêdÔzˆýbN­OϪµÌ†yµV8%³6ŸèÿpæÜý÷2çÒÃ-É«ÞþõìùM‘.Ëö ‚®.3¿9ÿrÅYP_åÜY‹K‘ªêJÄ][g=Ú£EÑS´BÔS=ò³¯${Ó›s"¥8 ˉ81l/‰IÜ´çœv´ ù®K+ÏUJ+­ï–§^ôÖŠµ/×LæëçåJìôÑWKTP–ïš½AêÎÔ£êÍêjBÆþ3Þ¾…”ý§|÷6Röš2àdí7àŒQ$ì5aÅLró.Bö2.¹ZW\-€|ûÌxNCì5`f°ç€qIí=b\P{—Ó~#¦„ó " ){M9˰׀=‘ŒÏ`@A¬Y0ŠE ~žÇÚ 4.ÿZ-ØJµÏ¨Cbfé6Æ,ÝИ¥[Ÿ~úÍÙÑÒ&"äì3gX€ÀÇ ~#.(dN1ûŒ9C“¨ A·4®¶=GÍIP£8bnf¼õé=ê, Åá^CŽA€b4°Ç 7{šQB\pûÍXàNqÏ ãªËo¾ p{MøMšábß!sIp9í9á˜QÂq_P+0ã® V`Ƨ­ÀŒ;‚¼¦œ¦ö°ÆË'¿ç¿¡ŒqYí?c\SûÏÔ^#ÎHÌDŒŒ½fl«Â |mÀl€$í=iZòà•²ç” >Mö²†8“v»Hã{ïi',Âûœm€Œ7:[ït¶2Þêô›qš"`¯ËÈ ¿IÄsÊ?éæ;à • ¤ì=å,ʲïEÈÞCÖF17ùÒ|²(p>ð=Tä(%ÙgÈ…ÄQì5`²ÀaøjxM8¶'¸ÈoÆó”á³Iïã“I¿›yŠ£Ø{Ä8ŠýF¬ ¡o±÷ˆqÇ_ c>ndÌȾCVøÁWß/pǟ׀ Ñoq{y‘ÞߺëjÏS]>‹>Ì4³å‚6²€ßMçwšà®Ôÿqyh@U'Õ±=\µõÔE'®+ó•H¿“ô’,ë%EÑKÒË^lø4=c´›œiZ™Kšè3êÒÒgUÎòp~v]÷j¦ÍÂ&úJA¬ASÅ2#U#_ýDâï±hý»,‘Eñ›,÷ï5°TÿHU3âl»Q3 dæºÓ$hª_ajb@hÓ$à8yDœ4 }¦M´Ý­³&ú‹&µ/Ò&Q]4ë9KÀ ÓÔDeµ‰Ÿå¯ªX—‡O¹œ®«âúäá¦sÂg&™|©ä Æ–PKEiÒ>Öìì׫…vs2008/disasm.vcprojíYÝoÚ0î¤ýU´‡M”–µÛ”²©è(­ø({@BNr€·ÄŽl‡Á>þ÷cHÚµ%tÕ¦jíŸïûÎ÷sÄá‡ylÏ@HÊYÅÚ-–¬m`÷)›T¬e>ÿ* »{û{Ö‡÷OŸžS“ «bŸò3Á?ƒ§ž>ÙZ>õT,òí¼|iáÖùJõ»W¥’&´IˆL>•D†V&{ÜoÖ*Ö÷ƒƒò»½úþ~a¿\u ¯ß¼.Þ¾ÙÝ+ìï×ÞÖœ7µƒÝzé§ë1Õ¨í+_R3‰÷ø9< ˆsJ½Ê–zaœÐá•÷,MØI$v.‰ö84i6//ÎÆt ¢ÐlBúvÁN ~dö¶NcŪF†ÎÅ¢b‡Å⻟ Â0¶&S Bð)QË|ɼ©Å땚)ªÀÇdG Ô¢;P²b={~î4™T$Pý‹sgYŒI(9ìGA|hž;¥âLF¨Bµ} §ã“†ƒY7„£^ë„2Òo NÌz4„u‹¾$thL‚ÔÝ)ÄÃøº *Ö2/Õ˜~‹Ot¢µ{˜íØpE/<{n*¯3û¢8U¡‘K `J†Oiæu@ÈÖgÀ”Þ6ü;7 8±TK{q«Îˆ¤aµ`A‹²/©xæ¡g2åâƒÐ­wõˆ ÍÄ*FÞt•)!D ¢E¥B­-î™Ä^•]¥ßÕgëý©;O\¨{ªŠdÍŒ%]#0 ‚¡õ$¾¬¦Ý8ŠHÙUD¨8ªÆ@˜¸s;Œ02¿’ǃ‹m”'zL^#˜Xr98tbØz¥r9ϪÔÝød›¡„­˜Ó9¼¾äuïžÕ#íêF¥†ø›°V¥—²æ;¸yÀ®ôòL7æ6ññŒKuó>ܹZëa´n<Ù D}Íš ¡ë#€>èí´ô×ñq”ácŠ•¸S;to@¿Ý|XËÚþ¶ –I®´Œ#Ð2ö;ÂÙV2šLßÞ‡ÉæãžÁÝèþÁ]’ÿ‡vI¸÷ê~#É„Ö1`HÃòÛ:}Mˆ ÙMºq;a1¦ KÅò¢Èölo>·…gû0¶…ÍýÀ¦ø™FŸm—¨ (`Œ,Ç èÛ ÎˆšêQ¶Ì›þùàqŠžÉ ^I_Áð5/Ùh–ÕœI|u ÎŸÆ†mÍ 5Y¡±WÊ4»¯Ü=ÎÙ¸U L#ùØ´HÌGÀC­¿\0EæåÿËŸ<*7\5Ì;ÅuW)Þ("{ŠWihSlz±pç#s3K¾‹«’?†&E\ôíÎzð'Õ±6I†,“Ç〻$†œ-w®ùûé¿PKd@IA"³—;vs2008/fpu.vcprojí[ÝoÚH¦Rÿ‡õ᪖¯„p­®)!CrHh±¼½kí®)ôîþ÷@€†BÊÃõ?Dñ®gfgæ7;¿]Źú´p³9I9«fKùbö ˜É-ÊfÕì=eÿ*s¥óËóì§?^¿ºº£Ò'Ž¡|‹òžà_ÀT¯_eâ§ÁÒƒj69Óß½Ëâ«»•éï‹Å`¢K\šz~öQñzØnT³]V*%½QnæêµËr®Ü¬üž«]~¨äêõb©\Ó?–+¥ò?Ú€ˆ¨–@S_¹xX¯.€nf®zQS.\Œ‡Á öc»8ä3…P£°¥r5àÜiQ¢Qa{¨s6¥3_…ËÆKlÍm¬Ó€‰?ûûqµÌ­¯<_5¨ÀÀ¹XV³ùQ>?â“/9+„ÚLpÁ¢DÁÑ­…#Ê+#6ªÀÂ4{ ÔÒ°”¬fßüv§·™TÄqÐøÛ;=Æ¡Sâ;JކÞL Z‚»wz¥˜ŸKMÈÈìPÂíô¦¥ÇùÎdjƒÎ eÔ¥ß@ê}Ÿ ¨ :D,‡’̸‰#!v×&‚˜ªšsR÷©cuø,Hqà†86ZÍçÞüaäômÞVn¤¦>+|Šs¡nsL¯#ùÂ^Ý—Š»¡Î1âÞtD‘k`€‰çâ{˜ æÔL÷bù,Ý›v£sT»fqÃjæÖS8a¬AËÔ,‹3Äi3Óñ­uQÀÉçßc©Q,ỘÑTþD¾ÏG¿c˜e¬ ¤äkk ܸ¹ÚÝ‹smÜhÖ‡×Ú¸Ó®kÝøß4nï ­Wë׺·í†Î_·»×Z÷v\3ŒæM½ÓìkC£‰²ƒÏc½7í›xE¬.õX]ذ=1£À­Ï€•+¢JÚÞ/#ì:yÏ´W Ü ¦ªC¥Â~×áfœ¢µU'ÁyÒðÚ ŽûÆ *£N$¢0Ûâ…Xüž¬ spªÙ‹xÖð=O`J E„ò½:aX'Õ,âï LØRÚ,hV¡Ã­ðaŒTa¸­>Hî ¾/•ýªûuöWA„,¥ccñÚ*/.­†&;”=½{£z „mV}Øg÷ÖC'Ç&|ÿºµÀË£úE“ÿLj֥¹-zDEˆu"ÍC«¶:÷Žq¯Ç¥ÚßZ¯ [tôcj샸MŽ#G G[Â)A¦ù‚\5â6s(ƒ–ÏÌ`¾¹ð‹Oɧ0è3ø³»ÁŸÏåKm¬÷c£©ûÍ1JÞ×ú]T2V-E dž¦ <èo´’]†]šŒ W®²rVÐüvÕq¼3ŸOÅ+Å‘ñŽÌa:ÞQøIBþe·ûëî&ÞɧÜÍhÿSÒÝ™Š®­}˜‚ÀÛýêR»3^ßoÃG$  ª6ÂZ< E¢¥#‘jÖô<ÍÔÌÅB¦fÁT·âí}Ñ&Dm1Q`!n4€n:‡QvÐ-ƒ¤¦ç ·”7ãÌÅJ‘Ö÷§ˆ½Wìµâf.pÀ¡v¾Û»ûV…•×…ïÜ>.ž'ÎE¿xDÑ‹#!!R„°‡ŒËRŒ“±7…8Ùû)À xŒ‡xe§0'fÓåóåÄ£ŒÞ)ÐÉšI•œt˜N¬±DGÒ-x¬]*Í夣¬a2…9Ñ0KÊLž‚œl—Îù"…8É{ÜY¦'aɧjŠgl•ÜgVÎ#æCŠøË@\z`RâÐoéÕêe žÂü"`.UR _Ð9×wˆe¥h¿´Š)Òÿc¤ÃG"´v?/Œ>~êóB[³=O³ Ív5Êâ(WÏ„›¶ÌÛ[slå™a(?©”-P‚;ã¯'Ø€… ^Ël„à—î‰ÀõO´€u¤ø‰6äR*8%”ð>ÿóêfÑŸÝSûÍlÖy4}[{íð qâïnW…'þ¡çÿPKpiÒ>8jõ5·%vs2008/gui.vcprojíZmoÓ0þ<$þÃñ}Ù ”´¦í¨Ô½¨Ý *UNrmÌ;²®åå¿c;i²2J³ (ýÐ)¹Üïî9ß“X;x? Éö¸ÀŒÖ¬rÕÚê1ÓQͺÂÔg7¢´³ûj×zÿîñ£ƒK,bDz2ö1;ãìxòñ£­ôê|AÍJT¶çÏ-õèræúí‹jU NP¨”F1¶rã‹v£f}Ùi½j¾Ü]-½iì4K/÷÷Ko÷÷ª¥æîÛ†S¯¿Þ¯î´¾i³sÄG [\¹ºaü:[Ã,ðNýÎ’CÆC¡ïò[}c"0¹ííZZP1•9“ƒsÆH ÉÃù[‡Ñ!ÅIµ¬ý »µN _óõ¶NcŲ¹JñiÍ*÷Ëå>s?•x¢œ¨µ©‚‘„¥ÊsË'@¼œ¹ €c ¾*v\N{€5ëÉÓK§M…D„(÷Ï. QL¤è_D#Ž|hq^:¯«å±ˆ” ‘¸½p:+2Lì dê*«¼NŒms Têlj~e¡ ÉBcSDýãq§$: )tŠØ\Û>ƨrO¦÷²=n7:…Òè8,Œ0Ì«îºHjp4[e/•¶)ÁZ1õ´¼9‰MGAªpèûX?B¤M=ûY+bªË/T7b*$C ²/dì #c>ŒS ‡ˆ3„`\u¦Æ£2¿jŸìíÚ'fýâÈtÚu{àtϽ¦sÑmNNW‡Ý“öÉQ/uÔ“ÓÑ™JÊÌ'µ(¤OTÃɼᲦÜjRä’,¿Œt0½ÎÌó½¤dþ@>p݃w÷Z_Í­rä³Ú¡rÏ;XHå²Ã¼¤¼w g ¸z‡åÎ+·t*Y,lÄQ¨;«®ÄZY»ØéâT­n’Ë‘íÅQÄAˆžD\ÆQQ ±±úÑ'ÛErŽ´‡tªQ±á É@2]´>Ð`໣²gj—›U´]!ú7o>³¹Kþ‹¿¢sÓŽ%#|ù¸6j‹7o¦‘âjò¾x±ŒÌ´ú‡ò¹À×0 Q´Áx1¦l³×b>t7¯3À‡˜JàCäÁéuF:B…’Ã浆YÂDzÆÅçuÆùFgµxí!¤_Û&|ˆrÀèÎLj°ÍhXÿ¾1tï“ŧ4饾à8)9.þÙqR`Qd“‰„6¦ä!‡GÁ*gG´6‡ðÉß%–m¬à€Ý¬…O2ëÕÞ÷37«¼e¬àäh 'Q~ËX˼¬´gVöc*°ëR±0—G„¹ˆˆDœßT~òWJþPK\¡Aé£Ô«Qvs2008/iodev.vcprojí\[oâ8~f¤ùš‡Í-´«V);*ºHô"èeI xšÄ^Û¡°—ÿ¾vœh‡63Öjg½~@Šs>Ûç;>'NlN?/Ã`o)C8j–ªûå=yØGѬY¾G‘Yå ~T/þùí›Ó;Äb yì#|Mñèñ·oJéÕÍŠÀfY‰ì¹?–Å­» úäÓþ¾¬¸¡B؇‹òZõü¶×n–ÿ¨5Ün«Q9>9lTÛ'nåø°Õ©´Ï†{|vxppô—T»ty— °GLòV’&DGK§×àSLC&Kë¢,¤}£kÔ¥|©–hÔ¶TNo0º(€ªTÛ.º8š¢YLͦMlÕm´3€ þ¹n¯tsó6¢b蘮šåê¨ZáÉ— UÂJ¬qHCè#Àá«Â[Í+*3˜9¤ˆC_›@ÊWÃ9„œ5ËïÞß¹½ˆqþ۲цSœnÉŒv)ïÜŸö« FS°· ^M/ºnjõRéì¦"¢ß!sqtƒBØG èê–™èÐywç€OŒoy³œÚ¥£Àïã™4´ìž0€ìØ(«¯¼{¯˜—–ýPóPé%(Ê’«Ôòr@0Ñí,`Äåm%_Û©àÆŒã0Ñ)"þëE¿ 88‡†Ç´ˆÎ=œ !]  s/Wߤ{Ñk÷ £ïâ+n –®—ä$Ò,7ÒÚ^ vãÈ“õ%Q R3ßGòz‘Ä~îŠ ªV? oD‹h #'©‡ˆÙ …Ãx1L…S çH拘{½ËFݹlwZ·çθßk9cwp3vÜÛAg|y5¾?\ö.χ)ÐS‘®ÅX’À$ÚJݨ$üŒ¯ý,÷ÅR'“ V.`ÐGÑÃSuÑCOYÊÿ W§ÊõžN±Q°ªÄ›gFa †¢ÚGŒ Ð>öR»>Sͬ?‘Sk|Þ,&\(]ª%ª¥°bt—Â= ‘l]oMé0&„ £9 <&- Ûö "1Sýd8¦|îE»Uwëìöå©”+bNLÖÁ~£ñZkRòYxb+A ÚœI~‘ñMôz&{Z(œ´°ˆh‹yÛ¢¯w°Èx'Ì{­åîÒŤH¯1㻣ïim+c½œCÛpÏŠeP_ŠËŸ¢6{Úìù-Ù3K3ÿ\ro$Ç,QŠ;í«û,)>M}kàsZâöߓєâŽ|VË%j…³Ùàwæ²Rz‘|rO:ÜM.rsü0¹nüãåºMO0?ÓmŽö_ÍsOªÔ’r§Šµw¶à|RÎמɥˆüÙq˜øâ^"¢šV"ͲGˆã9ÞréPÏñáÔ¡ö‰ßœ|q&€o¥‰Æ(Ãh¯ŸË8¦Ì6AU/5]ª¥ÔžgîÖ¿¹ê¦9_‰¿¯ÅÚ\lçÌ$jY¿kÏ:^lDÏžF~ðñ¨E9ž Ìä±4›MsÌB3hy6›g/ÄÌrl6Çâ'D–fÓi¥ØlŠá’OIŒèo–h³‰ž˜•eÙl–g¢×Sny6›ç9 ¾OíšÙpšy–eÓYNÞ[šÍ¦ù®&XÄm˳Ù<@AÀÀòl8Ïžý4e>ÅuÄìK0ói#ß~™2f»”2Ÿb~\÷Ž-ÏÆól)6›bæy0Ì~e6žhH°«åÿËc -Ó†3àG?FcyX€Z¶ g›@ð`i6žæÅ Œ=DilŸÇ §:ŽB@´ß© çYÌhK±ñ{˜ÚÛ¦ÓŒ(·OÛÿy¦“K©*tŸžºTg«¿vêrîÌ qæË¥3¥£(ê=ÉËù–Û|ß>-Œìt˜HrôH@xÐÑ_ï¦×AI·jë@äû€u@²M¦:éF=µ=NCo ùî-|kˆ§7]³M šÉsM ]Rt]+ÿ\¨ ¢¥¿þС…¢Þ¢ëC$¯hµ`¶ßÿiAm¼uÐÁÉ—´: r½¤©Ÿ<Œka¬ŸôvÂl>F¨jõ瞀 ý·‡uá´ö•?YõPK†iÒ>ܧÒq‚<vs2008/memory.vcprojíXÛnÚ@}N¥þCdõ¡U !Ðô"C«` E"$âú€„{€mí]kwMI/ÿÞñ®±“¦ÁŽªJ©š¤õì\ÏŒçõ÷›Àß_ƒ”³†uX®XûÀ\îQ¶lXÊ<þE–«GUëý»ÇêTFĪȣü\ðOàªÇö’Óè2„†eTöçÏ-¼ºØº~û¢R‰} R—Vf{2î¶Ö·f³Óyó¶Ú*U;G¯K/^–šÕV¥Ôn½tjÇo›¯+G‡?b³KPÞ¾pñ9 £c¼ÃOýÜ'jÁE ã§ì1~ÐIèòjU+h‹ƒk&õç~‡ú ÍåõG‡³]F‚( «E¿È®Ä€DÂ÷,ÞÞY¤ÂHµ¨ÀÒˆ†Už–ËS>ÿTFÙ¨u™€G‰‚\åkáM/^nݬ@P‚‚P—À’ ëÉÓ §Ë¤"¾îŸ]8I7Z° ‘¯ät.ñ #xpἪ”×2DÒ¸K8[œvDÝŽG½SÊh@¿‚tÑzt.ˆ¸K²Ä„ÄOÓ]A\¬oªa%¸4#ê{=¾ŒŽÓCâĦ[yéÉSÓùÙgå• Œn€ižRäã‚@Û¶×ÀT|môn5p"©x mЍ<íµˆ"'À碈ÍæCkê½¹¼“íi·Õ+TFÏáAˆ(f^qêB7‡(ýªÔi—ù”A'bn,ooBÂ’m({¯ˆße®yé(R8Œå8”I%¢AžJÍebŠðãÀ¸ %8T”iGh5éökU»ßj7Ç'ö¬×mÚ3g0š ÛÎxОõÏf“ãA¿Û?&ކJàJ:ÇZôfÂXÜàœ©lÎÒYÜk32÷Ó²z°¿GÙçÔ<ËÐ5Hy€x ôèÝxŦfc•CwµEEJ0‚èQ©Ðk»Ø›¶[øçñ»u‹ÿ4Žo\ÏTű2¶t‡Á„†Ñu}YO‡Q D}¨ˆPQØ$Œ0uçNad Þ$„ WÇ(Ïôw6yƒ`F ÑrpéDpô*µZ^4t7´ð›m&„–)'{xwË}:ÿsTãT -”và3QmJ7UÍO°xÁséæ…îlÉñœKuû®\#­Ý4Ú‚y´,F¢^¬šK¡™ê>èÝ ´ò×ùq–ñcÊ•xÓ:› oa¿Ã|ZËÆþ®¤–Yî¢4£Q˜ÐŒúÒÙž^]{× wôñ¸gt7»t§ñÿÈN—{/¨î‘Ô²,@sA•_žÓ_ ú¨@\!È¡žÆ}­bB•†å†¡íÚîfc ×ö`a ›{¾Mñ³ ?Ùs¢®°€ ’¬ð1·5œµŠWY‚Û>W£—Ëü½ã‡pfš!š³…ó7®VÛõ¬™óÄ‹U¤×Î?T¹(Þf*Ýžý7Zˆ[¶†ùzð»­±ÂåÚ+Ü«À¦Ì/º#æÜ]Éòö+ÅÝÏÕ¥äç/§ÔÇN@ŒXêã‰ÏçÄ—Fœ=Ô~ó¯'ÊPK’iÒ>pÚbƒvs2008/niclist.vcprojíXmoÓ0þ ÿE|A»®e¼(+¨KÛQ©ë¦v|˜49Î51$vd;£ãå¿sŽÓ„Òu H ø-9ßùÎÏ=vžfÿõ"‰ï_TLð®³Ûl9÷S0v·Œâ£jì¶÷ÚÎëW÷îîŸ3•‘x¦³€‰)ÞÕ÷îÞ)îN¯Sè:Öå¾÷ø±ƒCçË©_>iµŒaBtâŒÆLi§ ><õ»ÎgïàùpÐï ­Ö^§ñtÐÙx±»·×xÞê·ž=Ý{î=k·¾š°S"CÐC‰Ó}òC™'Oò ¯ý“˜è¹‰2OÕ£y°U˜õuÚŽ1ìä;+!û§BÄCƒ²ƒ«žàsf’hLkS¬Ú¾ËÓ? ¿TÙîg:ÍtŸI ZÈë®Ó¼h6/„ÿ¾Wë4âd#¶¸®$¶mØ]Nd„9©¯g€V]çÁÃsoÄ•&qŒ“?:÷Š>ôaN²X«‹³4”$€¡ɹ÷¬Õ¼R)N¡ì´g ŽçGCñ¶†Þéøˆq–°O ¼iÆOYcæK"¯Ï ± 9‰åFDªAÎ@w“ƒŒÅÁX„bS.ßv±´7<´=7˜>jF:±q9ô¶YxWbnyìà ¸6ÃÖgc€—)-’<¦Žû»£qŸhrx!ëļòŠQ@¸×?{4ê+¿;Øæ%ÂÖc•ÅkêØ/"ÞöS|mÀV<ÆžHRt¯ÊCê¦Út™h»Û +bì  ”È dB¾-p‹&¶{Ùœº—Þñdv<A9aH<ß@Þu´Ì : ŠQ¤æ/ú§êcÆ\± ™^Õ@m½A¹ÒͰ¤4*âzJAâã*Çhg< š¯n-t‰€oöÉ“—•ˆP’İâÝßÉM^¸‚¸Zæ,KS‰€Î4‘:Kç W@Ê•7V^ð0¿é:O·2‰pB0%2Ia¥Ë[B7Çlæ€í~áåe±Î¤9 Zζl8å˜ñµw°q®j*Ú[‰‹%ž&zÄ©„ÓlE»v+Š ?¶Ä:­ÓÂ' n§gà—ÉýÙµÒTLŸsÔ†^½ 0ÅUÃ&Á`43 „ˆÞênµçè¡ã¦Û`ídŒ¹±Ø”®u|öÑýÔq=P´tÝÚ‘ú÷Ý–y¸ðDZ§Ä^š¢asVo¥7¿œöwV^è·‹‹)Ä@Ô“Ò:וó‰ñ_bX‰±F?#2:…uÄcÆa˜qjìƒEJxñ³¥ž ™¬ª¼™ž^ÎÞÙtp99¾|Û›NF“ÃÙòˆÑ’ñð‹ÂåѲ.@ªcuÀ‰—õå¯ssp–áµtJ…m}¥²¼Y«T>5ÕJðËzå/Ó#“¿LðÖQ$»[À®%6ª”ÿåÆo•Êÿ¤àøÁ¤rÛæ SPÖå‡çòëH~«A~'Sfù6½Ÿ»ØÔÖ¥ëÐ4u©K WR7€¹+]Ä.Ã+Jß»>Ñ+oa3CÁKˆ±¶+8!:ê:ˆyÂ-Á¶PÛ°eÜš†Úø‰¦ ¬ÐÜòÚºõÌ)=аž*UIÙ6t­ÈÕWð¯­ßT³}ß@ûF¼‰&‘!Q"¤I”¸Œ5×™s j#ù.ͤë'©Ä!R°—v}Æ]*7ds÷}âùŸ›³ÚûbÆÂ'±²æêa熧hÿPK¦iÒ>$‰^dÜvs2008/stubs.vcprojíXKoÚ@>§RÿCdõЪ…ðH[!C«` E"$âz@B‹=À¶ö®µ»¦¤ÿÞñ®ÁÍ ;j©Ú’=;ïùv> þ~ø‡k’rÖ°ÊÅ’uÌåeˆ5¡Ìã_d¡\y]±Þ¿{ú¤~IeDü¡Š<Ê/ÿ®zúä y]…аŒÊ¡óò¥…G—[×µW¥R,è“•¤ŠæÒJMOÇÝVÃúÖ,—Þ:µ×¯ ÇÕÊqá¸V+šÍ·µÂ§éÔÊΛV¹rò#6±Õèì ŸwQtˆwø©_øD-¸dü–¾Æ/:]]µbÅ‚#mqtͤ>âÜïP¤9¼þêp¶ ËH…aµè†ì—8ðHøžÆ;8T©X:W «8-§|þ© Œ²Që2"™Ê×›Qoݬ@P6;¡®†+%Ö³ç—N—IE|Ý¿¸t’i´`A"_Éé8\ âAGðàÒyS*®eˆ.¤q;–p¾8ë8Øu#8õÎ(£ý ÒDlDèѹ âj,ÉZ—îŠâb}CP +éK3¢¾×ã˸ÑqzØ€8±éV^xöÜL>îì‹âJÆNÀŒ Ÿv mÛ^Sñ±Ñ?º×À‰¤â¶É£þñ¬×"ŠœAp:yl&0‚XS°Ý›«Ùžu[½\eô„ØÅÔ+¢.TñpˆÒW¥šH»Ì§ :scy{–,ƒDáÄóh|Dü.sýÈÛA‘‚D05l5‚Ã)¹@Q¦PcÒíW+v¿ÕnŽOíY¯Û´gÎ`4¶ñ =ëŸÏ&'ƒ~·:L •Àísyë%¤DÉ bJ¥˜Úáî ÍÈÜߕЃ5ø=Ê>ïÌÓ ]Óï ¬…†Ù­ë4ÕË©º«m¤„ˆ• ö¸kzxÛtÛéy|îq¿Ë†ãå bø4Q+ãôöLˆ`]——Žo…¡)‡Š…MÂSv&˜#Kð y$\H“¯»l²p`h9¸_"ˆ²Rµš ]ÆóÌ}‰ @(a©r²r÷NܧóßoêIœi®ÕÑÂ|†<ªM馪Y æ¯w.ݬÈÃÃ<)^p©îß´õ£kì´Ÿ/[0–ùØÒ‹U3¹2UýÏ”ÿ™òáLYÊI„¯jA"¢˜2—lšg);î˜OZç“á=ÜWÎ&µ÷¤´Ôp¡ÜtfÔ“Ìôrè²økºN¸£°ŒìfìtÿÿªÓÕ>¢»!’Z6€`£rã}÷CS?*¿ÐãPcñP«˜ÐF¥a¹ah»¶»ÙØÂµ=XØÂæžoSü¬ÂOöœ¨_8ÀIv ø˜Û.ˆZ5¬»¶X*(º¦—ÆÍÖÏ-.ßóë75Mû›±‘³·¯VÛw#F:Zlú­ÄóU¤WÐ_T9Hài°r´ Ü­"(´W­U`Sæÿ m¹ho–FlnÅ©ÏçÄ—Fœ¾ÔîøW å?PKå ?vs2008/PK¢Œd@œRšò6vs2008/cpudb.vcprojí[moâ8þÌJû*´nµËK¡ÐV)·jôÐQZA_î’e’x›Ø‘ã´p/ÿý&o(¶Tº½’ÕÆÎÌØ3ÏxžØfO¾{ï¤Ç¯e÷óÅìpC˜ŒjÙ;ÆMñèåöK•RöÛ¯?œÜ2ϧvOù&WR|C}ü‰Ÿ®'.Ô²‘ÈžþåK_Ý&¦¿‹AG‡:(d¸¾9È>©žß´êµì_•ré¨rT¬çËGåÜÁ©®çŽ+ú~î¸T9ª‹gÕF¥úO vMåTS¢±G!ï§£„CàD3'W6UC!/h=5ƒF<ô®\ ä3…P£0§rr-„Ýd6D­Â|S|ÈF¾¤ ‡‡˜ë›§ô÷Óh™K_¹¾ª3‰Ž 9©eóý|¾/ßsf  µ¸é€É¨‚5¢sG $F,L‰avAªIÏP^-ûé—[½Å=Em¾Õcê0¤¾­¼þ;’Ô„¦έ^-æ<Mx‘Ù.‡M=Žw&szݾ`œ9ìOðô®Ï¯™m6TNn<: ©íA<]‹Jj w=Pµl“3ŸÙf[Œ‚ÓC÷ƒ‰õ“þܧ_"̃˜~Î[ʉôÂÐG`…Oq̇ Ôm<WÁëH¾°RA÷=%œPgñ?.Úuªè9pÀÀ ¹‰Î z ˜îñä‡t/ZõöFn´uá¸Å«™KWà„ 2-sjš,è¡v‹¶oNóŒ¦æÙWüÕþË0[¤ï`0ûžò^?6‚qÆÌ0Àó„ÄìÁ,—.¯V§\ÒH½qvs®‘vëLëÄÏø¦~y׋ `º¨§tÁôd؈<1LE¥Æü臅$ïVâ“ç3@ïÛÌSXÄÚˆ½^PL"3Ò~©éé<.'ûŒzˆF±^.~G%Æ…°kÙrÜÛó]WbŒzŠJå»g”#ôµ,F4^™°J´xP 7Çi8^H Êq…™]ð„/ xŽþjÕÕ:«a¥t¬¾D[ûÅryÝhh²ÍøýÆ 2ÊFùl"‡¥ó…L°Ù`Ó¯ù4˜çFE Žá¿‡MDÏ!ÉÌ®ùßSðß?øn‰ÜÛÔÁ)Ú;€v™ÜSåP–‚½`à4ÔJý•‚“r¹šB¿Ð?2ë:(•žÇíàÀóâ8ãî÷7uLr_%%bX8óô–e0w-à—ÉQµR$JØÌ¡<þý¯|ÉÂë55±Ó¥þ¿F<|T £Æ³Ûúè÷7Ënë-Ír]Í5ËѽxÕ%íÌݼ5—IÛ_üno/¹U|¥0,ïµ³ÛÚ…åweoduþ"æ-Œ.œò¿…ÉgGÈoâüÒóÉ­,o§ÍÌ­ýš9zÛÚÔô\gkK+ ÞÀîÌŽtkk3Û­‹Îâ·ôÖ“[ú¡¶­Õ…¯€•æf)&êŽ~%vn‹µã_=5N Kþ+öÿ PK¦/@ :Øê> vs2008/iodev_network.vcprojíY[oâ8~f¤ùU43šáR(3S¥ìt‘(­ —}@B&9€§‰Ù¥{ùï{‡kK¡ív·¶ðÕåÔôá—\No´H€B”{0î1P7\\[sÇjÉúã°V¯äsÅbºP¬}Oäk‡érþÛAº~pøý›SÉ—¿‹iµs"† êjK3o±+ 8utæ5à"z5_êE fYÈkùT6ÖÈ.©sîשf•]^:œ è0D¡ÛÄÅÒÞ‚Ÿ6ø@$ü9÷—:T©*˜:·%+ÓÍdº¼ÿ3-Œ°k0"…—Ü›–LÍŒ@P;¡n;#%KÖ‡—NƒIE|ͺt’nTa@"_ÉîE8ăºàÁ¥ó5—ËMHcöBÂéà¤î$UO¥ÊçÍÊh@é´#vNhÒ¾ âöB’!4 þ,ÜÄÅü: JVR—JD}¯É‡ºÐ:<,€¬;ÝOøh:¯+û)3RÑ‹`Z?%•× A¬[Súµ‘Ï®Up"©xël#þÛI³J9Xx.¶Ñ¹‚~Ęº€åžÜ>J÷¤Qmn•FÓáAˆU\°š: •nN ’UHv̧ êsõ~m– …D ìyT¿"~ƒ¹~äÍ H1”É|A4RD‘ˆ,rWª¨/ã=}ÖØDŽ RrèB”Äa£UÈÛ­j­rql÷šŠÝsÚç½N͹h×z­ÓÞU¹Ýj´Ž;‰¡Ž8¢Î0©xR¡ÓO)œšnÊT‘¾?˯ cð›”]¯ªc„®)™÷+ æ…ÁàêYë.M°L莦U’t$šT*4ÞänRè;&¦íèë³¶ÆÍ,*Ž'0Ыà¶6-^§pEÓÞušów¢0XüŽ"BEa…0ÄÜbú Ž0<º^$„ waµ^u½Îz<$$R¡H ­ý\¡°ÉšÔ}Ýú¤ PÂOH<—·ê¼OûÏ/nYG¼Õœ©b#®aÑŠt—E7ø˜¼ûÒÝA}âðp›PϸTëÇóQv‰Ò&Ù*ô£ávëiÑívAtG¯;z} ½Néç`ÏÞ{N™ßTO¯¦¬¹ÊûsÃ’^ŒÿçPž1°†ð²3‰ìÖt·dð‰d—ЇEƒéoý8àzü0+Ë«!ÃÞë#Ãûñÿ§Âû²þW‰peË\JÛ0·øé•ue=»½ÆH ôÙ‰±¹‹×F¤d¹ah»¶;™ØÂµ=ØÂæžoSü…?í>QK¡-$3ð:MÇpFÔH:S¾nR¾.ìçr¹Œ›Ô0Q7úw9þ«ôLu±®&õ¦©<[{2§ÙiÜÙ;o—Ñï–Wžyñèf«QoЗÞj¿ŸnE¾¿CÏÛAÏ»~¿~ßèw  g¿Þõú­ôZü·À®Û¯=Ÿ§u;tiȨ»k÷¸Ýñ#Þ×\ÍG÷]GxC í^GM™ÿœ‹âh ?Ï ™—1ϰ—05= /b õHH×¥Ù6? û¼Oüägƒùâ({ÏÿýqÿoPK¦/@$¶‚VÓ/vs2008/iodev_sound.vcprojíY[oâ8~f¤ùU43šáVJgªÀŽJ€.¥—v“p'±#Û¡t/ÿ}ã„KJzÑnwËC«Ä9÷óù|¶¨|ŸûÞÁ sA­Å\Á8ÀÔa.¡“ªqM¨ËnE¶xX>4¾ÿòþ]劈y=º„]rvƒùþ]&~ê߸jh‘ëóg>]%¦O¾ j¡ƒ|"Ìų‘`!u¥³A«^5þ(7¿5­Rù0[(|=ΕËß²'År)kž”šåBã¸Ô<úK©õŸ`Ùä`ò–ñ _‘#7S¹ô3î õ¶|U/q$céPÉgò‘F~M¥ÒgÌkë·üú«Åè˜LBŽ$¸]¬­­øéb#ÿ\úË\„2epHñ»ª‘ærCfßd¹Öb-*1÷±KÄ;…×Üë†%f¦˜‰](v€¹¼ëM1–¢j|øxeµ¨ÈóÀü§++îFQèI1Ž\ÜäÌ¿²Ž ¹™À„Ðf_ŒÏ›V\õLæ´ß>'”øäw,¬nHûÄÇmbsÄïM  1òáNGä×òjÄu©…ÄsÛl¢ ­Âƒ¨À†ÉzöÃGÝyUÙO¹©ôµ^Ôݲè)®¼JGº¦R}Öòù­ V($ó#4â¿·ëH¢3L1žñ4:רîa>#†rÏï¥{Þª·S¥Ñ¶˜@W¬f.©š¤j”âÕõÅÍ:j½1GB,pêºD}B^‹:^è. H0`(—ûh$€"úPä¡¡-¢5µÓcÐ@Žƒ…`Ð(‰6lÂV§thvêÚà̵[5sduû£^Ãt£ÎÅèú´ÛiuÎz±¡žä0 .!©hNÓOœ\nÊLƒ"Û[äׯ3ìµ ýq_"ttÉÜ_1`žk ÞßkÕù• œiR#!°nx› ¦Û̉˼a i†­vÚ'‹˜ì?_!¬ËJX7x›Â5âTyWI.;Ü ƒ€Cé{q5Dq«É?€7Daãº] so‚j»êvíhÐ8ˆ¥,A![ÅB©´Ë˜T]M½Ï5L¢«û#šÊ)úîûù¥=Uñ¦š1uhÜF´&œuÑݦÏÚÎ.ÿ͹ł4^2!·æJ~̦×:¶ÃI:ru•h:j]ÝëžXC¬ ñü¼9ZáÍ„CáKýâ:áËû¬X\~î"ü?ì´úªË/$ò©‰nÍài.ŠUgü(àfô°(Ê«¡ÁÑë£ÁM<üÿIp3ç•ï-é‹h1‡{{rM½÷¾¸±F@ +ÄÙ‹py‰h×Z¤j8A`:¦3Ÿ›Ü1]<6¹É\Ï$ð7 nLÉ5vPâiƒá MføÉ©qºxèxC,Š¥¯…œ—0ÖÖê›äþÀíy¡ºZÖ#z×8^ˆmÝ”‰D>‰;¿xºŒ6,¯<ýáq½vñxßé7Ñiõߣó}·ßL·}æî»ýfºÍÄ~o¿nߺïö¸ÛÑ#â·œùõ]ÿggþ)ís gþ©oê=ã„?]ƒÏ“/`&9›¼)E|/dJMÕg™Bë{v«­U@èe}3<ó˜¼øÖ¸|©äòC/¬ÿ PK¦/@+Fýqø#vs2008/iodev_usb.vcprojíZ[oâ8~f¤ùU43šáÖÛ¶ ì¨è QZqi÷ 9‰!n;²†îå¿ïq®JÚA»Ý…¤Ø97Ÿóù|±Eéë$ðƘ ÂhÙ(æ Æ¦s •;B]ö]d‹‡'‡Æ×_ß¿+Ý!¿##—°Îî±#ß¿Ë$OÝÇ— -r`}þlÀ«Û©éó/…‚šh¡„sñx Û˜«_öÕ²ñGýø¼vZ?;Í^œY¿d‹…b¶rV8ÏžœZÕ‹“óÃâYáì/¥ÖE|„eƒÁïŒ?Ì<Ån ØLéÆGrÈx Ôh>Tƒ$XáÑ¡’Ïäcü’J©Ë˜_'>Ö£üòÐbtHFGÜ&.–æü´±‘ÀÎýe®#F²J8,ñDz‘ëçr}fßg¹Öb *1°KÄ…—ÜërOÍx˜‰]Hvˆ¹|ìxKQ6>|¼µTHäû`þÓ­•T£Š‡(ò¥è÷ÂG.®sÜZ§…ÜX„`Bh³=¯‡Wu+Éz&sÑm^Jò;V;¢]à&±9â=FÐù³p=Ä‘ëë`Y6’¼T"â»M6R‰VáAT`ýé|öÃG]y•ÙO9OZ/.€.Yü”d^-Ǻµ1¦R½Öòùµ V$$ b4â¿]5«H¢KL1$žñ4:wØî`>&†tO_¤{Õ¨6S-£i± „,.XÍ\‡R'HÙ8JfÔ'×#ê¨ùÚ$D4i‰À…ëõ ù êø‘;ƒ"Á€¡\î  ‘Šx@’ûBF¶ˆçÔ>Ol@9‚q@ $Þ8° ­£C³U­Uz—æ Ù¨˜«ÝtjV¯]´®wíV£uÙI u$‡öt‹Š»8Mð”ÀÉ9àf ÌÔ(²ýÙúšxŒý&¡«ê¡£Sæ~Ày®1¸º×ú³î• oš!!pNx“ †›ÌI’üD}Z [í³5.f1Ø}ÂW¦•°.ï:…;Ä©ò®–8¯o' C‰ïHÄeV¼-.ý´! ÛÖmcÁ"îà§Z¯º^g=4 ) PÄÁV±pt´É˜T5M½Ë5H¢‹»#îÉ«îûç{¡¢MÕ_ªP„œF´"œeÑͦ]³-œMÞë‹…i¼aB®oÉ¥ü=O¬UlG£t´ê*Ñt¤º º§Ô=¥¾„R§”ó0æ`1§ì oª×wS¦\åÃâÜð³Dãÿµ4§•×\~&‘OMqK_Ip™¸Q4¨ú¶®Ç³”¼¼=\EÃÿŸþVWü¯’ßÊ”>|¶ñs8©O¦+ãÙ)5~:X ÌNŒÉƒXD»Ö"eà CÓ1ÉÄäŽéâ¡ÉMæú&ŸÞ›6’K¼ ,$}ñ™Œñ ’žjn:u}H]_8‚ `}9ç$YL h O™ý™CóLu1³úó¦^<[»'§ùiÜù'§[Ñ“¯•7¾ýâ%å†ß¨%`t_íݨ¶GÜ}©w¤Ô‘½/õn”:û]½#¥fžCöµÞZ‡œ¨«¯Õr¿ÎX´ÎÎg²¯õ»Öñ#lý5—úðG—œýCÓ›LL/0 õî ÀÛBßIΗÛ0¥/[±_ÆÛ°£>»¶a'æômšÆ6lEÛ jò¬¡E¤ëi}'vé3ùÉ}Ù|PÊÿàO-0ÿ7PK¤¡A0/w^óÛ vs2008/iodev_hdimage.vcprojíZmoâ8þÌJûªh?ìj—·B{:nUè!QZmï2Éî&qd;”ÞË¿qœðÒ–B[t×»ò¡RìÌŒgæÏ“A­|ŸùÞÁ¸ ,¨Å\Á8€Àa. ÆUãš.»ÙâáÑ¡ñý—*WTDÄëÊȥ삳päÇ™ä©wBÕÐ"Öׯ¾ºJMÿü­PPmâ£e.L—úd ÆÂÄéeÓ®׊‡¶ÝÈÛ?•²eÛ*fO¬r9{T«ŠVñø¨`ÕÿRj=ÂÇ Þ2þc~Z|:œ©\xDŽ÷…Z-–j‘ø‚Q–•|&käWT*=Ƽõ@¯ò«K‹#:Ž8‘xlrÄÊÞÒ9ð€øsq^æ<’a$mÊ1tÆïªF®ŸËõÙð&˵°k¸.%6 ¯¯!)§f&À©“—wÝ €UãÓç+«I<͹²4l‘È“¢Ž9q¡Á™erS¢ ¡Í^ 85¬$ë™ÌI¯uFêÓßAX(èQZtÈ ¿»ˆwÕoîî„pâ`|]U#ÉK-¢žÛbc•hå&@9ÖO÷³Ÿ>käUf¿ä&Ò×z1²ø)ɼ bÝú©^kùüZ+’ù±Î6⿵l"É)€‰g|kvO©˜îÙݳtÏšvk«0ZóCÌâ’ÕÌy(8qTR²Û <@# µ_Ÿ…$HšB"pâºT½"^3p¼È—"¬¡\îV#Å*â‘Iî  E¼§îzbqÀÊq@Ʊº°J⋃—°Ù.šm»^»<5­fÍXÞ [·.;õAû|p}Òi7Û§ÝÄPWrlQTÜ©ðФž2XprQpó¢ÌÔ2ôæñµ` ^‹?î«£‡ŽN™û+`Ís]ƒ÷ïZ¥ƒåBg’fIðñ Þ¢B¢ñs’D?0‘Â1TwmÍ1s¯Þ@_ÕX ·•°†xÂ5á:]…¹À¸…!Çäw%á2 k$Àš[ÿ‰Š#êv@°ˆ;ð°¬Ö«®×Y_º) ›PÄÑV±P*m: M*\·¾éºP( –oHÜ—·BÞ£Ã×'÷Dy¼UŸ±ˆ°hM8«¢›|NÜCálò 1³X¸«LÈõí¹’_¡´§IÖ†a4ÞŽb]%ºÁ.‰îéuO¯Ï¡×”~þö,±gʤøÆ>¿NYó>7†Ÿ$½¸þ_CyÚÀÂËÏ%ò[ÓÝŠÁ’]&nÍ@}ëÇ7â‡yZÞ Þ>Vÿ*|,ê•ïmé¡´#à8ŧ#ë½õ|z‘–è³׿A,¢Ö"Uà CÓ1ÙÌäŽéÂÈä&s=“âß$¼1‡D®p„²ôÀqšNá‚ȉjt:}ý$}}ÇEÖË9Iu­ÿ㟥çªËyÝЩ7uå¹ØÚ›™JäS¿óß.¢ß-o<ýâE`nU”{Èßäi›ÜÃý.àžú·„Ci÷{‚»¼‡ûÀ:Yê÷p¿¸§#"÷`ÿ‡ÁŽq~[3îé{÷&8Õ…æǽ‰oÒÀ{ÙpGDH“ÏýÉJ½b|؉¥ô«t¶„#(Äb'ÆÒï§ÝÙ*ïÆVÒùwb+n+k--׬ÞÖ¿[œzlH¼ä7Å¢’äŸpÿoPK¤¡Au9ðf‡% vs2008/bochs.slnPKže@2´˜à¦& µvs2008/bochs.vcprojPK?{hÒ>fòo$ Æ vs2008/bxcommit.vcproj aÀŸ-ÌЃ,¨WÌЃ,¨WÌPK?hÒ>QUƒ%‹$ vs2008/bximage.vcproj ¸fŸ-ÌЃ,¨WÌЃ,¨WÌPK?mhÒ>hžã%æ$ evs2008/bx_debug.vcproj ë÷ž-ÌЃ,¨WÌЃ,¨WÌPK?†²y@:…æ Ša½$ vs2008/cpu.vcproj p†–­Ä ÍÅSÒý¬ûÌÅSÒý¬ûÌPK?EiÒ>Öìì׫…$ 8#vs2008/disasm.vcproj mÝçŸ-ÌЃ,¨WÌЃ,¨WÌPKd@IA"³—; (vs2008/fpu.vcprojPK?piÒ>8jõ5·%$ ÷-vs2008/gui.vcproj ¢½ -ÌЃ,¨WÌЃ,¨WÌPK\¡Aé£Ô«Q C3vs2008/iodev.vcprojPK?†iÒ>ܧÒq‚<$ 9vs2008/memory.vcproj &•0 -ÌЃ,¨WÌЃ,¨WÌPK?’iÒ>pÚbƒ$ C>vs2008/niclist.vcproj Bã> -ÌЃ,¨WÌЃ,¨WÌPK?¦iÒ>$‰^dÜ$ zCvs2008/stubs.vcproj lXT -ÌЃ,¨WÌЃ,¨WÌPK?å ?$Hvs2008/ Ѓ,¨WÌЃ,¨WÌЃ,¨WÌPK¢Œd@œRšò6 4Hvs2008/cpudb.vcprojPK¦/@ :Øê>  WNvs2008/iodev_network.vcprojPK¦/@$¶‚VÓ/ zSvs2008/iodev_sound.vcprojPK¦/@+Fýqø# „Xvs2008/iodev_usb.vcprojPK¤¡A0/w^óÛ  ±]vs2008/iodev_hdimage.vcprojPKLÝbbochs-2.6/build/win32/bochs.manifest0000644000175000017500000000116212020641473017223 0ustar guillemguillem Quartus bochs-2.6/build/win32/cc2cpp0000755000175000017500000000014712020641473015477 0ustar guillemguillem#!/bin/sh list=`find . -name '*.cc' | sed 's/\.cc$//'` for i in $list; do mv ${i}.cc ${i}.cpp done bochs-2.6/build/win32/vs2008ex-plugins-workspace.zip0000644000175000017500000022253212020641473022101 0ustar guillemguillemPKÊÕ>vs2008/PKÅd@y.‰*a Øqvs2008/bochs-plugins.slnå›Ír¹ÇÏq•ßAå\6µ ¾?9à39$©­¸*9º(qd3+‰ ):ÞÚì“åGÊ+¤‡äÈoˆmL”C<Ë5ú æO Ñ݃þ×?þùòÅïW7Ûõn}ûxõ§Õn¿¸»zó¸_®ÖWoÖwûÇÕú᪬îºo®Êz{¿€kºí®ÿÑ×”¾|ñËáâ×__å›m·Û]qJíËßn×én¿zõƒ ÑÅ,±AzÂX¢Ä&Æ¥žFÇà·’ÿøêWW¿¾zu½¾y¿{õÍ©ñúÃÍ(}ÿOá*“4aR"%ÓÄî§Y+—×Tÿøêå‹_œîûþÁ@¿:uS·é–ÝÃͪÛõwÚ¬w§_Áßüâ%¸U–&b„Dú‰S‘Ç•U”•þþwáB)ÖñDxQ†H¥ ž='…wÁPÅHÔ…d ¦ä$ H§àæ99b™RÄÐDµT&jNHÔ…ÇךÅ$3 ^I¸Râ•Õ$ÊàéœÔLs᩵p<ÃÝ”‘H#±†q¢T²)ÂwÈòq”¨ Z2j¢ƒ+¥àpsç(Ü×8¢#ÌubܵÄ\x@²¢²4ú03ÜÜâŒÕ¹K1m(+$êÂ’+/b ðE&‰•!“äEÑzɘ: QÖÆà.$Èð<–ï˜'¡dgM4Jg{@¢.<>¸É.%¸[‰ž'gJ\á0ƒ‹§’©‹éˆD]Èü°/º—/>}4Õ||»ì®÷ï¶àÔ>7¨Ç}õ,¹Yß߯9¶Ï£ËÛB"—ŽHNAá<É^x*„Âÿ7v eöú/ uáÿìËZÝ/ÞuG‰Ís…¥Nh0>Røª$5$0ŒX<0…x–ñKWèf³ïµ€ÿFÊ`ØsLâåj·ØÝ÷÷<¶Î2ÂÏ1ˆÛ£·c PÛÊsÜþÝ~Õßþ}ãþ·_­—݇þ–‡ÆÈ‚`6ƒçÂ}w¿Þ~ßßóØ:ÊyŽA<¬nîV»ƒ9=5χò[žc»ÇýõÁÑ<4FJ`<ˆçÙYÞþmõ øi‹;´Ï’™I4êL8Ì"ƒáÄ @EÓER‘3›ÁÎòöa}Z¹C{´v‚O.HI2ã4‚¹ëxãŠ+'•ÔÁQ?¶·×'… 52oœñä%, aYçXH"‰´– =š·/\Ÿ›ûõî$PßÍ !­7Ù‘X ý !žc PP &Vá9Îa-}¿8×ÇÉ”u)DÕoÜ â²å0—œ ÖƒQ<º_¸>›ÕÍIhëS´,Ô$AX* ølÄéÀ‰Í&Å©VÎBŸÇ'}F;z °†"/$‹úøÔçKt¹¨ ½“C˜>Þ ë Z#ûŽUæÔýq‰ÈX8qQÁü‘TÑhŒŽ_~tª¼_ž…Cï\'A3WàzjMéãlð E†ÞùT¤6NG;nïÖ›Í÷'™Ž‘5’ à5SF¿›ⵓÄDþ#8´’ÏÁZ×}½^l—'†îhÝ1´£‚Ĥ<Øm ¦–¨¨­qNËDÅ ”z²,·†uwìë$]Và)ÂjStb^' 8ÜŽõ€ã•g ÓæfˆA u®O˜ºœ Q\G î6q ¢gŠG­#åjúìÖû‡åýzXqCw”éá!» þ#/È’Ï[‘"Š·2QÉÒ ”‚ùÃW»Å§ÙÔ÷F9®¨Ö)‘$lŸ4Â5ˆÙÀµ”ÓÍÓvºëÕzwJ™}êëdO*+GbÖ¹E±ö™p¼9x T 7ö÷‹Í¦VÞÐùà^‡¤بÂ\ŸWÄG FK] Ô†Tø”Ú]¿í_ଭž>yÞèy@õ‹R$ ‹÷ÚGiròs°èÝÇÇÛÍ~µýëI¬§þè5\vž% n¸/ŒH ž§£àèXrr¬0; /êÝâ¾Û¬·Ci\ŽÎœ NÈ?ÓªÂŧ]¶o„šiZ‚&EˆJ†¸8ÉEEeu¶vAÒîûÅÛ›Õv»ÎÀœ}2úâ¼£:ƒQ¤ÑÃ8 üðœÚþ¨˜„9°g W¿s|o$?ÛH¬rHŒhËa„™+’ê}Þè,ÏTÉÿ«—b¿¹[_/îàºccíP×·«wûí¢ï|{·x¼]oïßvÃEýÀSJÿïî2Â/Ïzý/ÿØÝu‹]÷ôëQÿ8ÆÑí2œÓp+£χƒ“çõÙ8_{¸Õ‡.Þ¾ûéø'ÐÂ~u·|M'³FÆö¹xÓˆŸÆ÷SªÀ­];í²v8V‹vSˆ5íP5!híÚi—µÃ±Z´›B¬i‡ªAk×N»¬ŽÕ¢ÝbU;L= ^»fZE;«I» Äšv¨2´ví´ËÚáX-ÚM!Ö´CÕð µk§]ÖÇjÑn ±ºf1Hø5ÛL«¬Y«iÍN V÷YLå~Ÿm¦UöY«iŸ@¬i‡*øBk×N»¬ŽÕ¢ÝbM;T•Z»vÚeíp¬í¦«óS^‡ŸwʹʼC±šæÝbM;TE Z»vÚeíp¬í¦«{¦R¿W4Ó*{ŠÕ´WL V}L!ÞGi¦U|«ÉG™@¬Î;L}!~Þ5Ó*óÅjšwˆ5íPµ‡híÚi—µÃ±Z´›B¬i‡ªKDk×N»¬ŽÕ¢ÝbÕGÁÔ,â}”fZÅGA±š|” νÃÔ3âí]3­bïP¬&{7XÓUãˆÖ®vY;«E»)νÃT>âí]3­bïP¬&{7X]³˜ZHüšm¦UÖ,ŠÕ´f'kÚ¡ê#ÑÚµÓ.k‡cµh7…XÓU;‰Ö®vY;«E»)ÄjÎSM‰Ï¹7Ó*9w«)ç>XÍßa*,ñù»fZ%‡b5åï&kÚ¡ª.ÑÚµÓ.k‡cµh7…X+0u˜ø¸¢™V‰+P¬¦¸b±ê£`ª2ñ>J3­â£ XM>Êbõ,¦J–§™V9˃b5å™@¬æ>1u›øÜg3­’ûD±šrŸˆ?s–ççk9[Îò4Òªgy¬Æ³<ÍÄj\©ðÄÇÍ´J\b5ň5íPµŸhíÚi—µÃ±Z´›B¬î˜zPü^ÑL«ì(VÓ^1XÏß!ªDòw­´ZþÃjËßµ«ï¶1u£øwÛÍ´Ê»m«éÝöb5‚©&ÅçQši•< ŠÕ”G™@¬i‡ª3m©h¤Uk¬í¦«gf1•§ø3³Í´Ê™Y«E»)νÃÔ¢âí]3­bïP¬&{7Xw˜*Uü¼k¦UæŠÕ4ï&«{¦v¿W4Ó*{ŠÕ´WL VµãÂJ##E÷{ÐÄ™À€œŒ—¶îÒ²Ï6Ó*Ú¡XMÚM VßW`ª‚ñï+ši•÷(VÓûŠ ÄjÎSȌϹ7Ó*9w«)ç>Xw˜¢fü¼k¦UæŠÕ4ï&ë¹D™sC. •VË`Xm¹€vâeí~¶˜y¨Sþv»ÞtÛÇ¡|\OýÛÕò©ÿ‡õ²ƒ+ŠÿÝ›üoðôÉËÿPK]­A‹iiD(vs2008/bochs.vcprojíZ[oâ8~f¤ùš‡K)¥3]U);jv‘(TÐË> !Ç9·‰ÙNK÷òß÷ØI€0¥dªU§â7qÎñå|Ÿ?[=ü: ƒ­;Š ^/ïVªå-àTxŒOêåkÆ=q¯¶wk_j寿½}sxÅTL‚Ž=&Î¥¸ªß¾)¥OÔˉÉVããÇ2~ºÊš>øT­šŠ. ÑÈÔWå¹ëée»Y/ÿuT=ø\ûµ¹¿½{\­nþ¼»¿}p\;Ø®U[û_ZÍÚ~uÿãÖB›–TDèbsDN@ŸHüt/äí¬wÛ5N tx=2Tæmþj^Ò±á¬÷jƾ´c=vr.‡B',€äm'ÿÚ|Ì&±$»M»ÈÕ-ôÓ7žü=ï­Ô‹uë&“!êåʰR ÷fÛ3¦‰Q›k!xŒhXcšë8g7kÄÉ4xþ¤~øZÕËï~¹j´¹Ò$°ñ÷WŸ&ŒIh5¼Œ&’xp"ExÕØ¯VîT„M¨¤ÙK½ñÙI#w©ttÑ9cœ…ìOP~Ì/XæJ".™à€Æ$P×'’PœÝt½œÆ¤ hhM5pƒ¤êñFýPÁÙ:*,¸ÅR®-™-}S†–R™2šP[zX†  þ©ù0×y÷KBšs¢ý÷I§Ç1 ¼Ž˜\ML0æ&ì~;ó1@¾¯ø:Lü,Þ CìS ´‰"XßÖpm>'ö;+±Ò"´>EÌÿ8ë4‰&§ÀѲˆÏ5¸wŒb<}ø.ß³v³3·+n¥°&y6íò4¥ö¿RHšè&æk£Ñiˆ0Bó…Á•z‘6IJäž®täyÌÔ Íi{³5Â@%ãú„CcHq‡ÆPéØMé‹ÉÍ”̵ËSB»»WsFÍÖñå©3jôºƒ^§åŒ°ºÙ»8]û!mi®ç4¯—÷æÓdÞ|þ+BQ?›Rº8óS“rGÐtÆKŽYT\³\mz6K84|9& æ(ŒAâºËîÛ–ÞgWoöåЂpØT³eM’®“z™F‘C::’:Œé/pþüèÆq‰Î)ÓBJiplw`äåµ#®Ð4Ê©Gâò­ ]yõ7s\ äšýzÝÖ;3[™Y3‹lÔ;ß »Ø|‘è/|FɇøJº÷µ‚âíÕ\¦{ŸÐÛ Ð¯è x_+¼!a|ƒîkEW(¢ ¼¯ÞˆŽ”=8n ~µñd“¡j|í#žWµ“{ÑÇŽÚ>ž¨#ÇÇ£¶:ŒEÖÉõ…ŸcLQ¾¹Óô?šžéŸêŸçœlWÏóç•þk€È.Xƒ‚QáÐX:n9^0q$­áO;.㎜(gÂÆÎM4ÁØ¢(TöfL‚ªÈ»ÀŸ¸<~™ë÷x+’êäzì4. Ò«³ùËáÎ#ÿȇõÿPK{hÒ>fòovs2008/bxcommit.vcprojíXmoÓ0þ<$þŠø‚v] ˆ)+¨MÛQ©ë¦v/|˜49ε1$vd;£ãå¿sŽ“†m¬ /B ñ!Sb?ç;?÷œ}ëÞëU=¸©˜à]g§Ùr§"`|ÙuÎÄÕØi?o;¯_Ý¿·wÊTJ¢¹N&ޤxTß¿·•¿_%Ðu,ä÷䉃S§ÅÒ»O[-30%1‚üqÌ´SZ]çSÛÛöÛ/G ¯ýl·ñ¬ÝÚiìvv{a¯Óku:~§÷â‹1;&r z$q½B¾_;ʼ¼Âgï("z!d¬ÌWùi>lfƒ¶c¶3‹ík&{ÇBD#²“×?=Ál™J¢Ñm6tcì?3ˆ€(ø\úÛ:Lu’ê“@µW]§yÞlž ÿ]CZ°…¹CÀˆ†Jð5÷6;Å2!H¦!@²újhÕu>:õÆ\iE¸üãS/ÏÆ$´:?I–’0’">õ^´š—*Á%”]öDÁáâ`ä!ëv w<9`œÅì#(o–òcÄù’È«E–ЂDëpC" Õ ç »NÎK?eQ0KC´  0ã‡læ ³›¡Ž­]–›2|[3o6™íð¸6Ó¿}§—*-â̦üíÁd@4ÙH¼ulÎÀŸƒ¼dîÕÕÙŒ“·…i.6ˆÛÒ8/j­©#?7z˜Ri(¶6•”L<'/#D'Ú$šè¬ì:ùè˜GŒÃ(åÔŒW áùÙ’zAÀ̉ƜFi°–5…Ñ7s¦ …FA)!QŒŒgFˆ8O;mw:öOöÝ ïp:?œ ñev|1z'³áÅôðâ¬7›Ž§ûó|±¹–Œ/0öì\Ó2…|5ªK®u¼5äÄÖÛ˜À%DÆß¯ÍË(©e&(9Ý”ƒ„†JAŒ>ä„)ëNµTÞ¶.÷MeÞáaÀz"û8œ§xƒÁ‘½g;,³8O“D"÷sM¤N“>á¤Ýy¥> ÇBf D*)”©–ö÷lªä`…£¼4Ò©4Ç^UÞpI“ÒÚç‚—1­ðªŒÃª‹Y5/!F$Â(«Ù¾VW¯TYௗöçWJC\z›sBF!XŽÆu9m| W@SC0r„ô˜·²4ìñ{@hȸ¡ºŠ·žÙ·®¡¶¥kº„¿‡:о¢´ßõSë+Zå|´òDR'Ê^’œ‚d V¯TŽ„Òw_k{Û×ZÍÍÉütY¯5 ´²1)¡ÿÛ’ÿmIÑ–”ªØþ3Ië·6׎ܨO£yá…@ß#¾sGk±SÝ3”ý\Ç`m7õ Q»[°ð_ì¶²fÌÍ?VYÀ£ìùËz‰‹¿¬—°ä×é$Úµs‘5Ü̉ýï~{×%ñßìn ©ll À)( ¹ñ½þ${Õ ¿é4æYE>È Öµ…tš$.uéjåJê°p¥+‚Èeø„É;×'ú›ëÔ:Ée Æv GD‡])™¢%Û–kkWÞêƒ6üLSš–„V\CÕWŽ…m8ˆJD¾zO%^&©¿µ›zÛÌJÿ_ߤȕket‡êì%û=Õ…nˆº Quaì2ÕÕÍÂi÷ò4ug!0*\šJ×7ˆ–Xm|´ë3îÊ¥r—lá¾K–ø@öÇZßôjßóŠÜ„O¢¼Z˽íïü˜‹ã_PKhÒ>QUƒ%‹vs2008/bximage.vcprojíX[oÓ0~‰ÿ€"@Юë¸*+¨MÛQ©ë¦v*MNrš˜%vd;¥ãòß9Ž“fëVB ñ-q¾sûÎññiöß­âèᄤœu¬ÝfËzÌã>eAÇ:§ÌçŸdc·ý¢m½{ûàþþ•)‰f*õ)?ü#xêÁý{ùÝÉUË@:OŸZøê¬PýæY«¥&$F»¢1 À*…NGýŽõe·Õz³÷òù ÑuZÝÆóç­WÞîëa£ýª×{9è¿nž;ß´Ø ¨¡@uŸ¸¸\ÛÉŒ¼Åkÿ8"jÁE,õSù¨Œ:¾½¶¥v2‰"û'œGC4/o>:œ-h ¢Ðl¶´±vÍNÜ4øZZ»w”ª$U}*0p.®:VsÞlιû±ák¨˜ƒO‰‚ è Ã& »…’Uà#Í u5 ”ìXŸ9#&‰"TþäÌÉóЇI#%ç§I ˆCÁã3çe«¹” ªFí©„£ÅáÐA¾ÍB÷d|HégÎ4e'4†1uW§’èЂDrwC"ˆ‡ÑÍ@u¬œ“^J#ÌM±vÃ׎͋õÆ£Ç&çšÓ'ÍPÅF.£Þ$ ïÖœë€ “,)ýÚàw¶ 8©T<ÎdêÀ?ŽûD‘`€ÄsQGæÜˆ%õé^]ý”ìá¨?.q÷0ÍñYó|‹5Uäæïó)4¿F ’±ÃãáâšÙ£Dé,Uî6~ß§z…D#æE©¿.X =kæ0L ‘Rr…FY&„ˆóÑd¯m_ô½ÓûÂ9šÌŽÆƒ\¨G$õ°¤Ð.8!x—ˆßËߙ催úÒg|÷×Qo§(ñÂ")!v1â1• {à˜{&ÒMÑ‚ Wï™;•¯=á¸b])äìo…ŸÁ´]XBT†9K“D k3E„J“a DÇR"…‘µ˜ÓÍ+sx˜Ý !•UERàOAòTxp=ãU¢wÉT%Ú¤8G9ØhR¡›Uko¯ÊªSvY{7kpéÓºéþ°`Uð©¥±”ÄhŽ`*ÚµS‘ojØL‰­Õ¸³+© .kvJ˜Ïuõu¡àŽÒfÊ׺‚+ðR­ É@nîAÓ‰R52ßÕ1Öj<„ÑHU«)ö~ u =éÐjnëçЕ^•åáÊáI»Ir‚.h½ qÌ¥Ú~äìïÜ8¦<2L!"¡ÞÐ ¸ÆØP‚ÿÿ38Ü*?3:gÛˆE”Á0ež^¬Âò#¿u¶˜Üœ-ðfzr18§ÓÁÅäèâ¼;Œ&³¢)AYpŒ¾ã?Ó¶LE÷0âFë0²ó[÷×µxÍÁ¤LAýÑdSxûpRbjŽ'¥À/(Ù2ùËœÞ:#Èn5Ù·³ê¢òªóÝÿSÉoŸJr–ÿɹdcIfkSX€æ4çõ§‘ìV¸6Í̲mú0ƒÓÒ±¼$±=Û[­láÙ>,las?²)^aòÑv‰ºvX#y]B„¾-ᘨPŸó˜JoM¶¡Úˆr·F­­ßgJÁ’ÍŠÓ­ú 2°´¦‘kïÊbÆ)³‹¼ßŠ¥FåDù¯‡i^ä…kªhKÑ™óõ®¢ íË.Ä¢ c›²¨n‰y™;ÍâDÞp¨B˜r–óÐ7úk:¸ô!Ù­OÈäÖ}H=n{©°Ý8±ý(ÀÝØÆKÙ.e¶¤Ð…ý1 ð‚ì‘Þ´jîó†pq—DÒ,—û;w|DÆõïPKê¡Ô>˜åŽà2‹vs2008/bx_acpi.vcprojíXYoÓ@~‰ÿ€"@à«I*7 ø*‘Ò´JZÂC¤hmO’{mv×!åøïÌÚÎ ¡† ©›zggfwf¾/ÎÙËU<\4bRµ\)=æE>eóNiL™}ZµvR+½|ñàþÙk*ŒdâÓèŠGoÁ“îßËŸ®ocè”2•‡æÓ§%\z½v}ú¬RQ‚ QÉ]M‰ÓÒÖøü¦guJŸ¬F«b;¶©µLÛцÙÖŒF««U˶OOê­Ša}QfׄÏA:Ý}ˆø»Í>é&/pœ]DÎ" 5ÛNÕ$?ÆW¯•”àyjñ|Ïäì:Ї ²Åý©±'œHÜ6Èvö±ÀM柷»Ý»LdœH‹r <â·RyR.O"÷­æ+ÕL©Ç$ð|J$Ü¡º·qV†|§—³ ÇÄÄd‚îuÿ‚2Ò Ìa®i}êrÂoo™£åŒr¿ ‰'@n\ ü~4Ç\ ö£Ç=¦"y2Y˵G³â¨àŸ”2ÌìÒeYŧMr^›WR[{ LªåLÿùQ32 S›"êo.ú‘äp‚I,b3w|I=@|®nÊö¢gõ …Ñ7£0Æ,n½"4b©ŠCäͪj¾O•„=承‘ABGTP&$OB`r"dâŠTù°Ì½`¢cy DÄ-˜Q–úDãÞ ^Ó§–mÜœëSór0ºìÛúÅÖåx¤Ò…ÜIŠ ÁUùß… Bƒê!¨00à½Û”x‹µN©žËÇ„3ì6}XB°•Ž’8æxБ$\&±AÞ)axë½ÒKÕc꺦ÉrÒìaw–‡0Ĺ?%܃ÝÜezÜæxn§»É3“@&ð”•zý®ÝÐeŸ²w…¯…RÎÏtˆ b`>0/ÅËn™¸‘·债¹‘ò‚ ã pD°$µÂ%Éo `†é „ÌÀq¸zX¸=£ÄÝ !¦h ‚,¤ú•ðŒIb»¬®¶½/Q¾0e˜­½»“3Åñ”A|tUŠä{f¡d¡ú;(¢j¯¨ª³2£¸ˆb7Ž‘!éŒÃùU$äÑ–ŒT¸Ç7?æ¾!€e+Æ~ßé5[²üUNûÏI¿“D"• a‹»~©;˜oÞïÒG |‡ÉF)ž¦*ÙÖ™J§äűîéþ­Vº3=òâXÄou—HˆPUÎHŒ¾O çciôøÚÛpÌV½åT5³Õ=ÑõVSëVšM­Ö­×¬ÖI­[sœ/{¡Ž‘7 0À%\¹è”Ö_ù'êýºìyÊ(·Z›}CÕÇ_TsÃÝŠÜÑžïî´™Úñ>klÁ€eúæØÅâÉ¿|üCe 9¤3|ã+ >ðïÁq¸‹õbqê”8<}%ü£è;­ŸâO+íŠÖ>5,­áVZ»mZ³vâöIÍ6ãWзÈÃþÙÐ;ŽÞ5îéÔ‹t/áºƺÌuîÕpHÝ¥Lçs¡ÏéLÏq@ú¡s+£©=fsýYÍF³eu›]£©9íJEkx•¶Ö6Z]­]7Œj­ÚíZ•jžÃ`²ç¼—œ‘K‚¼Ïl'gÏ¿ó#Ê¿PK¢Ô>t&±X4”vs2008/bx_biosdev.vcprojíXmoÓ0þ ÿU|AJ×®oÊ JÒdT꺩Ý(*UNrm ‰l§t¼üwÎIº¬…²À^$¦¥‹ÏwgßÝã{ê¼Ü„ÁÃ5pA#Ö«Uk•‡À¼È§lÙ«L)ó£B;ª7ë•—/Ü?yMEB‚‰L|]ðè-xòÁý{ùÛåu ½J¦òÐzú´‚S¯·®»Ïj5%‘•ÜÍÜ¥‘ða])ìO¯ý^åS»Qï7ífW³ì–©[ݶf؆­9mÛ©×:íZ³Ñý¢Ì. _‚t8züñw7K¥ë¼Àçä" rñP¨Q1Tƒ|#b£^Q‚ç©Åó““Ë( €È&w‡VÄt™p"qÙT´'»µNÜdù¹XíÞy"ãDö)ÇÀ#~Ý«TgÕê,rßj¾RÍ”LÁ§Dª; g•ÈWºp¾8s,LL&0.‡g”Ñ~avICR—~}%È-$û]N< |òÆ¥™ÐÀFKÌj?z<`*’'³­\{ô8+Ž þIu%ÃÌ.ÍQ–U|»IÎkë‚Cjk¯I5é??h`%BFajSFýÍÙ°O$9œ`ËØLÁ_SŸ›ëŸ²=ô‡¥ÂZQc ¯XªâY YUÍ÷©’`À¼ ñoAAdД É“˜œ ™¸"•Eù9ÃLtÌ#„ˆx”¥>ÑÁt0jÔõyß6¯Nõ¹u>šœm}Žâþùt¢Ò‰ÜIŠŒÁUùßË=“ê!¨0°Và½EJ\`­Wiäò)á ÎÖÒIÇ„˜HÂe›„1འ†·]+=T¦Žkš,'}Á6vgyCœûcQÂ=Ø©Á¦‡mçv~;yVÈ„î²ÖhܵºRö®ô±PÊùžöQÓ‡˜ÌKñr»ÌÜÈ[‰j@ÝÜHyAqP8"X’zé’ä§0ÃtBfàØŸÝ/ÜŽ‹IâN®…„S´A"RýÊGxƤ6QL«£moÀK”/LfkçìäLqF¼eP†Ê@™|oÃ,Õƒú¨þʨšÂ+«êl¬(.£hÄ12$]Ðr8¿ˆ„<Ø’‘ wøæÇÜ7†ˆ€rìÇ3åüW(ÿœ®¢@ñÂ’“p·_ý§ÈßM‘[ư€2pæ)¹½‰ YMÊqhuöì;ZŽ9GûÌi/çÛºÛóÑù|jŒGƒÑédÛã$G»À€ðOÑý¾áÈ¢õÚŒ¸ÁMl)Uª&U˜ÿ"•þeT9úk©2ï5Yþ*§ýç¤ßÆI{"‘ÊÆ°ŽÅÝ^êöÆ7÷»ôU¿Åd“ÏS•léL¥WñâX÷t7݇…ùNñYÅou—HˆP=›œ‘}ŸÀÀÇ0ÒèñÚ{ìXíFÛ9Ò¬¶ÑÔŽí–fÔZ-­nà}¸Ý¬uÇù²ÃjyÓ€\Ñ«^eû•–_±«ž§ìríå7l}ð®ZE¹£CßÝl3µÃ­ ×(ð€•úfÛ%â)¾üCe9ª3ˆ@ä+ >ðï!r…ЋõÂqê”øxúFøØmt»ÍF§¦uºf_;vkÇZ§c›Z«ÞtL»Y·MÇüE®òÈ6:dƒ'Ž{:õ"ÝK¸î†±îK{u|¤îR¦ó¥Ð—t¡¿—ø@ú¡s^¨=fKýYLH«Ý7Z†ÙÒœN­¦{µŽÖ1Û†Öi˜æQýÈ0úµ£“¢€W0‹vs2008/bx_cmos.vcprojíXmÒ@þ¬‰ÿÁ?h´åõÒCÓ8I8îwâ²mXm·uw‹œ/ÿÝÙ¶ÀâU?ø’˜ÜrÝÙ™Ù™g硜¾\‡ÁÃpA#Ö)UË•ÒC`^äS¶è”&”ùÑ¡Uõ†^zùâÁýÓ×T$$ËħÑ%Þ‚'Ü¿—?]ÝÄÐ)e*í§OK¸ôzãúäY¥¢C¢’»žya$J;ã³ë¾Ó)}Òkõ¶ÙêšZÍ©ZZ]o9ÚI£Z×L«áXõzOïÚæevEød£»·Ý'ÝäŽÓË€ÈyÄC¡f»©šä§ÀøjzI ž§Ï÷LN¯¢(èÑD¶¸?µ#6§‹„‰Û¦¢Ù­}p“ÅçÝn÷.'Ò¡øM§Tž–ËÓÈ}«ùJ5Sê3 <Ÿ w¨îmœ•!ßéZÀÅü¼gcb2y58§Œ†ô#{”°+€ºœð›kAh9'€Üï’pâIàc[—VB-0¨ýèqŸ©HžL7ríÑã¬8*ø'å¥ 3»4GYVñi›œ×ö%‡Ô¶»&Õr¦ÿü¨…©Mõ7ç‡Hr 8Á$±™€;¾¢ >×7?e{Þw…ÂØQcw^±TÅ!r‡fU5ß§JB‚>ó‚Äß‚‚È a *(’'!092qE*‹|Xå^0Ñ1<"âÌ)K}¢ƒIXÓ™Óµ®ÏŒ™}1_ ºÆ ÅÎÅdl Ó…ÜIŠŒÀUù߃Ë=‹ê!¨0°—ཻ”x‡µN©–Ë'„3ì6XA°“Ž“8æ ÄX.“Ø"Œï”0¼Í^é¥ê3u]ÓdõÒìaw–‡0Ĺ?%܃½ÜazÜæxng·“g'L8à)+µÚ]»¡Ëeï _ ¥œŸé5ÄÀ|`^Š—Û dêFÞR”êæFÊ ‚ŒƒÂÁ’è…K’ßÀ Ó9™ãpõ°p{.Ɖ;¾BLÑ8YHõ+á“:ÄnY]íî¼Dù”a¶öîNÎçÄ[Rðaª É÷&ÌB=ÈAõwPDÕ^QÕÞÚŽâ"Šf#CÒ9-†óËHÈ£-©po~Ì}#€(Æ~Œ˜-Œdu4Í–c6M«©õÚ•ŠV÷*m­mµL­]³¬ª^5M§RͳqLöœ÷’³ rI 2ñnrúü;?¢¡ü+PKšp?>»8†àvs2008/bx_debug.vcprojíY[oÚ0~Þ¤ý‡*Úæ (í.­R6A€‰ÒŠK»$ä$ðæØ‘í0Øå¿ÏŽ[YèºK»õ¡­srî·ÏQ^ϲ3.0£«\ܵv€zÌÇtR±.0õÙQ(ï=ß³^¿zpÿè‹‘žŒ|ÌÎ8{ž|pÿ^rê/B¨X†eÇyòÄR¯ÎSÕ‡Oww5¡ƒÅäÎG>¸ÑÄʤ­zÅútpÐ,—Z­P/?«ž” ÕÃrµPk6^:/Ÿ¿h|Ñb}Ä' ›\éûÀøû¥¡ØÊ+õstF3ý”=êã†pÏÒ„R,QZ9ê3Fš˜€0/×FÇxq$•Ù˜ô mÅN]Çú9³vï4’a$똫À_T¬â°X2÷]!M‹bjQ <# 9¬k†Mž¥J¦À±_¥9.½)€ëá£s§E…D„(åϤu£ˆH1„Ž|hrœ;/v‹3*¨8Ÿ4•oC¨öÛ'˜âát#ÚÇ´±Ë_ š(‡ÆˆHÜ"Ž<]dÅJrR‹0ñÛl¢S¬ÝSákdž)½ðð‘©¹ÎéãâTF.N½)–:-s®‚X¶1*õkÃ_Ú(àDB² –Ù†ýíI»Ž$: ©Úl#snø { Ò=_\Iö¤UooFÛaAˆ dZUÇ…RÉlHtÕ|k "-ê‘È_ö¡:­øTµ¦Bò(*‡BF®Ð4WçhøA7ôÉD£Jºj„`\µ¦±~¡f­ÕÙß³GõFmplÚ­šÝIÎêMýô¢—(P½#³Þ©Xû™bÏ„å¿ä7}²> Ãt±CošÆ(.ÞÆBª½Öf^œ…ïdÓL¹z .Õ¾t…©ÑtñkH€fU¹ßÈ~8Õva$‹§…!!zq…5D)ðŠ¥R¦2Þ-ª÷Qìp3>¨-Û(ˆª‰ó» XÄ=Xí†<ÑËdò*kjšp9‘ååîþ~ž5¥²éû­Ô4F4cNVé›`7?ëyÆ«ÚÕ­öB]Uà=lÃZ^Æšëàö»ÂË3Ýœ;,ÜÆÇ3&äæ=zTZÞã` Û!!7̹X¸Ê|‡†whxU4ÌVr‹L¡QOÓóÑä^ü·à²³—#§ÛõΠÛuNGÕn§Õ9Na³'¹Â˜3¢úcöÅ@ÝKè Š\²Œ6F'½á2ñ\Ü]¼ŸAÞLz3öf<[¢o&°¯_;7_“ ÿO›„|C0ö’ˆi]ꥬ߻­Ì-0ˆvs2008/bx_dma.vcprojíXmoÚ0þ¼IûÚ‡M[JA)›È[‡DiíºHÈIð–8™í0º—ÿ¾s °±fû°iRMãóÝÙw÷øÂÉËU>\4fÝJ½Z«<æÇeónåš² þ ´º~¤W^¾xpÿä5) Ç2 h|Áã·àË÷ïO—7 t+¹ÊCëéÓ .½^»î<«Õ”`H"TòVÓ "•­íéUßîV>uš¶Ór]S³ŽêŽÖÔ; ­ã´u­étÚf»g™–Sû¢Ì. Ÿƒt9zûów›m²=^à8¹‰œÅ<j¶ªIq ¯¡W”àyfñ|Çää2ŽC—† òÅÝ©³§œHÜ6íÉnícƒ—Î?ow»wžÊ$•6åxÌoº•ê¤ZÄÞ[-Pª¹RŸIà”H¸Cugã¼ ÅNWÎgg®…‰É½ËÁe4¢AX£”]ÒÔã„ß\ 2GË ~„_ƒÜ¸4Sƒx޹@íGûLEòd²–kçÅQÁ?©.d”Ûe9ʳŠO›ä¼¶.8d¶Î˜T˹þóƒV*de6eÔßœ l"É)0à“XÆæ¼1ð%õñ¹ºù)Û³¾=(ÆÀŠ£³¸õŠÐH¤*‘[4«ªUö™¦ÁD QA™<€É‰©'2YÀ²ð‚‰Nxìƒ1·aFYæ\÷‡ ݘڎyujL­óáø|àSÛç×cc˜-N2ôpžÊÿ\î™DPA…!€µÿ؆ Ä[¬u+B~M8Ãf3€%„[é8MŽKÂeš˜„1àÝ †·Þ+»T}¦®k–,7{ÀvgyCœ#qÊ}Ø©Á¦‡mçvz;yVÊ”ž²ÖhܵºPö®ôµPÊÅ™öQcC,ægx¹Ý@&^ì/D5¤^a¤¼ È8(,‰^º$Å-Ì098öW÷ ·ãbœzã!!­C„T¿ ^€1©Cl—ÕÕvVà§Ê¦ ³µsw ¦8#þ‚2(žÊ@™|¯Ã,ÕƒlTeTMá—UuWVœ”Qì% 2$Ñr8¿ˆ…<Ø’‘ wøæÇÜ7‚°låØçÊåø¯Pþ x½ˆCÅ sN¢Ý~]ÿO‘¿›"׌Ñg!eà¦ÌWrg•V|§-Ç¡ÕɳïPh9æî3§5ºœŽëjäL‡çÓëÞhØžŽ×=Nr$¼ ÿåÝïGê…ÜaÄ 7±eT©šÔÆüW©ô/£Êá_K•E¯Ù’å¯rÚNúmœ´'™l3àXÜõKÝÞ|ó~—=Jà·˜lœáùa¦’o«t+~’¾áãßje03â 4(ŽEòÖðˆ4ˆˆÔXŒÄèûú†‘E¯½M×:n»uÍ:îiÍÆqKëÕZ-Mï5tûøHïé®ûe‡#Ô1Ц!¸„ "ÝÊú+ÿ$ˆHÕ÷•Ma´¶ú†©¾§n ·¹£;ßÝhsµÃm ÐØb«ôͱËÅS|÷ø‡"Ê Dçð:€ÆW@àßCãa— „â"2( qøÆJÁ×it:GvMkwL[kzµ¦Ön;¦ÖÒ\Ó9ÒÓ5|‹"êŸ ™ãàMã¾AýØðSnxQbáÜྎCeŸ cNgÆÛd޲ƒƒXìL} ›Èò`2ZÇv¯Õ3[šÛ®Õ´¦_kkm󸧵¦Y×뽞]«ÉØ&.:Éi{$,ºÌvròü;¿ ¡ü+PKq“1@#[€'E¦vs2008/bx_es1370.vcprojíXÛnÛ8}vþC`ô¡E+_ä;o¡‹•5àØ4û`À $Úf"Q*)¹Îîößw(É%ñFÛb‹>ˆ q83äÌÎsþqë{g X¿\¯ÔÊg„9KÙª_¾¥Ì ¾¥®¶ÔòÇß^¿:ÿDEŒ½Y»4¸âÁq¢×¯JÙÛõCHúåTåÌxÿ¾ SŸv®{j5)c”ì킈z£“ˆ2ó‹›¡Ù/ÿUXj·^3”–:h+Ín¯«è­¦¥ÔͶªõ «Ý©™_¥Ù5æ+Y~ øý~¥Ä'l¶t~åáhp_ÈÑa(Ù> †*õKÕÄ¢š39¿Ï¢IGÕüÐØ’®bŽ#X6["';ZÇ$v¼úû°ZiGa™”Càè—+óJeØwŠ+US¥!‹÷‰KqD^PÍ-œ"[éFÉòÒ2²Ä”JÚõè’2êÓ?‰0¦1»¦>Q›cþp#ð ,—Ø$ó»Æ;°‰ö.õ˜zî(XÉ\ôËoÞÂ>a{ïæ;¹òæmZü»Ê:òS»$GiV“·,9ŸŒ+NÛÁ†°HN§úÕ“F,¢ÀOlЍÿq92q„/#¡€±¹%öŒð uàsûðŸl/‡æ¨P##ðCÈâ‘×Ò$Œdq’Jî‹VÒ\—J ö†ÌñbwJD ¨ LD<ö!‹sŶHdK6™Htȇp“, xá Ç -Ì~sÆd<›Œhbsr;Cãd"s’ {S@ä?—’ŽuT1ÖŇ2q†µ~¹‘Éo1gÐoFdC¼ƒt‡!‡Î"Ì£8Ô1ƒôËÞn­äP ™<®I²¬äºØ‹åÁ pîN‰bî§58mzÚætnÇÉ3b/Š9øª×—V—#Êî  ©œÛÓ5& s¡·§x9j s;pÖ¢âQ;3’^dœHaoì ”$;%2L—DDypìf.çbÛ³_ÈÒÉ~å¼Ä$7q˜–G{°%N,}AÊd¶rg'mF—ØYSF àC“(tγ0 õ ÔïIU]8EU­­„Eµ0†¤KZ çWˆN·äójŽoþû¦Ä#P¶bìÇSåbü—Sþ¡ x»<É +øúÈ÷ëú/ŠüѹcŒ!óà|[1s¤|° 1Ç5y‰C+óßO¡ãÇjL¯³q3,Ɠŭ6dz]³‹80ßD–|pµÁÇd¹ëÁ†mod™²[=6ÿFNýi8süÓrfÖtž°æ·’Û/rúÿÉé‘(½¿MÉ’p(îîv÷h¼¿è%¯Ðÿ(m–àù,QI—NUúe' ‘ƒøÛn‘K–(p=DáY‡wÈÆ—Ï6£&F?ÇdèÊ/=Ü›–Ñit¬ºbt´–ÒltÚŠVk·Uk¨f§¥jªe}Í‘…ÜFÖ4\_é†\áh6i\s8~̧îŠãdÀK­Só§Ü}òæº7<®Ì ýú¥Ö»W;ÙvÕÝ®«O¶],žg¾F~òˆÒ‰ Ú)ÎNÀòw‚]Ÿƒåð¢5`rí#Ê’ÌA[ážDa¯ÑëµÝšÒíé¦Ò´kM¥ÛèJ[mYú ¥tKÿ®s ,âŽKž ’;ˆ:rbŽl?D®·BÜQá‰Mâ+Vt‰îÂ<$ùAÀ†[Q/å Ù }Á›“YiwL­­émÅêÖjJÓ©u•®ÞÑ”nC×ëj]ÓÌZý8+ÇÁ¤1¦½å løÂLŇÁyõ™ÿ¯üPK-¢Ô>lÔV}7švs2008/bx_extfpuirq.vcprojíXmÒ@þ¬‰ÿÁ?h´ÈÛñ’šÒÒ“„ã.p'~ !Ûv€Õv[w·Èùòßm =P¼ê_“+יݙyv–Ó—›À¸.hȺ¥j¹RzÌ =Ê–ÝÒ”2/ü ´jí¤VzùâÁýÓ×TÄÄŸÈØ£á%ß‚+Ü¿—½]ÝDÐ-¥*ͧOK8õzëºó¬RQ‚ PÉÙÌa#QLùûRîáìz`uKŸÚýŽQµUíİ«Z£bu´N¥ÕК¦Ý·:U»Ú®Ô¿(³+— mŽ>?„üÝn±d¥øœ^úD.B5ʇjmƒ¬×JJð<±x¾grz†¾M}éäþÐ Ù‚.cN$.›ˆd·Ö±À‰—ŸóÕî]Ä2Š¥E9ò›n©<+—g¡óVó”jª4`x%îPÝ[8­E¶Òµ€‹Å¹mbbRq5<§Œô#s³+À:œð›kA–h¹ ¾€ÌïŠpâJà;—½˜úÞ0\b.PûÑãS‘<™måÚ£ÇiqTðOÊ+¤vIŽÒ¬âÛ.9¯ÍK‰m LªéTÿùQ32 ›"êo·‘ä p‚I,b3g|M]@|nn~Êö|` …14à Â,æ^‘TÅ!2G³ªšçQ%!þ€¹~ìíAA¤Ð” É㘜 ;"‘…¬3/˜èˆ‡.r ”%>ÑÁt0ª×ô¹Õï]Ÿésób4¹öõ9Š­‹éD%™“=ă£ò¿—{="¨‹ ÂÀ\ûNä!(q޵n©žÉ§„3l9CXƒŸK'qqÜèD.ã¨GÞ-axÛµ’C5`ê¸&ɲ“ldw–‡0Ĺ7ÆÜ…½ÜazÜæxnç·“gƾŒ9à.+õú]«¡Ë!eï  ¥œíé5DÀ<`n‚—Û dæ„îJ”}êdFÊ ‚ŒƒÂÁ’Ô —$;%€¦ 2Çáìaáö\Lbgr#$˜¢-pR‘êW 0&µ‰|ZíþÜXù”a¶öÎNÆçÄ]Qða¨ É÷6ÌB=ÈBõwPDµ'Ü¢ªöÆ £"ŠF!CÒ-†óËPÈ£-©po~Ì}cðËVŒýxª\Œÿ2å?À€ÓUè+^Xrì÷ëêŠüݹeŒó);f®’÷7aÙ7ÛbZž=û…cÎÑ!sšã«ù¤o^ûóÑÅ|jŒGƒÑÙdÛã$G»Āð_ÚýŽpä¶õöqü]l Uª&µ3ÿU*ý˨rô×ReÖkr²üUNûÏI¿“D"‘a‹»½ÔŒw÷»äU¿Åd“Ï•téT¥[r£Hwuÿ6݃…z¾NñYEou‡Hˆ@=›Œ‘}ÃÀÃ0’èñÚÛ°ÍV½…7^³eœhz«©•fS«õšÕ:©5Ûþ²ÇjYÓ\Ã%‘«niû•¶»d—]WYf¦[Ûoøúèm57ÌËrG¾»Ý¦jÇ›A¦‘#kõͶ‹Å“}ù‡"J'2\§ ;‚ÉW@<àßÃä Áé+ä*Ð)óñqõðŽB°SïtNêíŠÖîô,­áTZ»ÝïiÍÚ‰ÝëŸÔú=»÷Ë\e±ÿl|È"GOwuꆺsÝ "Ýó—:wkøHÝ¡LçK¡/éB-ñäCç 6:†¼PzÄ–ú²>š’fË2šF¯©ÙíJEk¸•¶Öîµ ­]ïõªµªaX•j–’Ã`Ò÷¬«œù¡Cü¬ãäƒÓçßùM å_PK8¢Ô>ƒ“‰4‘vs2008/bx_floppy.vcprojíXmoÚ0þ¼IûÚ‡M[ ¨R6å…tH”VЮû€„œäo‰“Ù£{ùï;'¡)l¬Ù>ìEšTÓø|wöÝ=¾‡pür…WÀY¯vPoÔó〲E¯vEYÚ~¨×^¾xpÿø5) '2 h|Îã·àË÷ïO× ôj¹ÊCûéÓ.½Þ¸>zÖh(ÁˆD¨ä­gó0N’ëZi~r9pzµOnËj™–s¤5Ú¶ÖÒ;®f¶ZZÇîX½©·Zzã‹2» |ÒåèðCÌßÝì”móÇñyHä<æ‘P³rª&Å90¦^S‚ç™Åó-“ã‹8]‚È·§vÌæt‘r"qÛL´#»µ^ºø\îvï,•I*Ê1ð˜_÷jõi½>½·Z Ts¥“À#(‘p‡êÖÆy!Š.œÍO]“ Ì‹á)e4¢AØã”]ІÔã„__ ²@Ë9 ~—„_Ÿ€¼qi¥4 †ñsÚ˜ŠäÉt#×=΋£‚R_Ê(·Ër”gŸn’óÚ>çÙöWÀ¤ZÎõŸï5°S!ã(³©¢þætèIN€'˜Ä*6WàM€¯¨ˆÏõõOÙžœa¥0†v%˜ÅÒ+B#‘ª8D–hVU ª$$0?Lƒ@P9$ DeBò4&§B¦žÈdq«Â &:á±BÄÜ9e™Otp55ucæô­ËcfŸ&gþ1C±sv51FÙBá$C Çà©üoÁåžEõTØKð߉2%.±Ö«5 ùá ûÍV–ÒIš$:‘„Ë4±cÀ{5 o³Wv©L]×,Ynö€]ìÎò†8Æ â”û°Uƒ;L÷ÛìÏíìvòì4”)øO‘¿›"7Œ1`!eà¦ÌWòþ:!¬øZ[CëÓgß¡ÐjÌ9ÚeN{|1›ôíËq6:›]™ãÑ`t2Ùô8É‘ðÎ1 ü—w¿=©ò>#^x[F•ªI•æ¿H¥UŽþZª,zMI–¿Êiÿ9é·qÒŽHd²1Ìcq7/u;ó›÷»ìQ¿Åd“ Ï3•|ë\¥Wó“Äð ÿÖk#€¹¡Aq,“·†G¤AD¤Æº`$Fß§00Œ,z|ím¹v§Ùq4»cj­f§­™v[ÓͦîtuSwÝ/[¡ŽQ4 1Àœ¹ìÕ6_ù§ùvÝ÷•Ya·1ü†¬÷¾ª–†eMîhÐw÷Ú\m'(4J8`¡¾9v…xʯÿPDùBêa{ù Hü{€\"òc‰h\Fe!ßX‹`/þŽšGG‡ÍnCëYŽÖò-­Ûí[Z[?t­þ¡Þ·\ë×ð·,ÿÙà?öÞ7îÔ ?å†%F. îë8¤áQfð…0tn¼M8 û08ˆµñÎÕ‡‘°…ñ¬öæ£Ýq̶iµ5·Ûhh-¿ÑÕºVÇÔºMË:ÐLÓiùØ &.úÉI{$,zM99~þŸÒPþPKH¢Ô>i’ …;«vs2008/bx_gameport.vcprojíXmoÚ0þ¼IûÚ‡M[$¨R6å…tH”VЮûP 9ÉÞ'³Žîå¿ïœl¬Ù>ìEšÔPç|wöÝ=¾sübG7ÀMX¯Ö¬7jÀ‚$¤lÞ«]Q&ï…ÖÔõÚ‹çî¿¢"#ÑDf!MÎyòùàþ½rtq›B¯V¨8OžÔpêÕÊõÑÓFC F$F%9ã M¸¬mœ\Ü^ícÓ5šŽçµ´n·ki­–ah–kw4»k´õNë¨cXögevAø¤ÇÑÓû„¿]¯•/ôŸãóˆÈYÂc¡Þ6¯ê¥Ü Æhè5%x–[<Û29¾H’È£ˆbrûÕIØŒÎ3N$.›‹vd_­ã‚ŸÍ?mV»w–É4“.åxÂo{µúu½~øo´P©J&ÇR"áÕ­…‹R”+] 8›z&¦XÃSÊhL?€pÆ» 1 ©Ï ¿½dŽ–3 (ý.'>¹vig4 ‡ÉsÚ ˜ŠäñõJ®=|TGÿ¸¾qa—ç¨È*ŽÖÉyåœsÈmû7À¤š.ôŸí5p2!“8·©¢þútèIN€'˜Ä*6WàO€ßПËÛŸ²=¸ÃJa $N1‹¯Tªâ¹A³ªZR%!Ñ€Q®AA0” ɳ˜¼2óE.KB¸)½`¢Sž DÂ]˜Q–ûDWƒ‘¡›S·o_ž˜Sçl49öÍ)ŠÝ³«‰9Ê'J'9zH4_å .÷l"h€ ÂÀY@ðVlBPâ Öz5£”_ΰã á¢t’¥)ÇN$á2KmÂð^ Ã[­•ªSÇ5O–—°ÝYÂçáD’ñ¶jp‡é~›ý¹~<'‹dÆwÙ0Œ»VC—CÊÞV>J¹ÜÓ.j\H…À‚/_7k? ¢Qÿà=eq¬F¥¹ò‡pã E°8zåâ”ç0×tB0ÙÝ-á–‹IæOn…„“µ‚ANR+D F§6±™V‡¼¿„ S¾0y˜·­STrÆ) ”A¤X*U2¿ ³R7rQý-TQµEPUÕ[:IZEÑJSäJ:£Õž¹·9#)n1ÏYp `Ùªñ /”«1a©ü¸ðj‘DŠ!æœÄÛ»ùŸ,7Y®¸cÀ"ÊÀËX äýeJXù·›Ö¯Ÿ~‡L«qèh—CñÅtÒw.ÇýéèlzeGƒÑÉdÕã$Gê;Ç€ð_Ñýö°¥^ÊûŒøÑ:¶œ4U“Z›ÿ*©þe¤9úkI³ì5{hó—Øí?;ý6vÚ‰\6†p,óꢷó¾¾óåC ü+N›äÈ>ÈUŠ¥ •^-HS30ü[.ÍffF&Åg‘¾1}"M"bõ,Knbô]ƒÃȣǫpËs:FÇkjNÇ:ÔZF§­Yv[Ó-Cw;‡º¥{Þç-¶PÛ(ÛDà œ¹èÕV×€ëÕ½»ʰ´\™~CÜ{/°ÃMUîhÖw÷ÝBmW(56€ÀR}³íjñ”_Eþ¡ˆŠ‰ÖÆö@ò%ø÷ ¹@ì¥æñ¸ˆMÊ"|s)½<2ŽŽnCëÙ®Öòêg™¾­µõCÏîê}Û³‹2ôŸ Ùdï™ãIƒÄ 2núqj†ÑÜäŽ4}ÊL>æœÎÌ7éÈ?LbibÄ3õa¦ln¾'7{3Òî¸VÛ²Ûš×m4´VÐèj]»ci]ö›zÓ²ÜF³ÌÈn0Ÿì)'Qⓨì7›—ãgßù‘ å_PK_?Øš‡3”vs2008/bx_harddrv.vcprojíXmÒ@þ¬‰ÿÁ?h´å==4m)' Ç]àÎó Ù¶¬¶Ûº»EΗÿîl[à@ñª|ILn¹îìÌìÎ̳óPN^®Ãàá ¸ ë–ªåJé!0/ò)[tK×”ùÑ¡Uõ†^zùâÁý“×T$$˜ÈħÑÞ‚'Ü¿—?]ÞÄÐ-e*í§OK¸ôzãºó¬RQ‚ QÉ]Ï–„û>_•vö§Wƒ^·ô©ÞqͺÙÑÚ¶©Õ«f]ëÔZuÍéT;m«Ý¬:ºóE™]¾ÙçèñCÄßm·J÷yãä" rñP¨Ùnª&ùA0Äš^R‚ç©Åó=““Ë( ú4‘-îOíˆÍé"áDâ¶©è@vkŸ¸Éâón·{牌Ù£øM·Tž–ËÓÈ}«ùJ5S0 <Ÿ w¨îmœU"ßéJÀùü¬ocb2y9<£Œ†ô#{œ°Kºœð›+Ah9'€Ü/Ö‰xøäÖ¥•ÐÀF Ìj?z<`*’'Ó\{ô8+Ž þIy)ÃÌ.ÍQ–U|Ú&çµ}Á!µuVÀ¤ZÎôŸ5°!£0µ)¢þælØ#’œN0‰El®Á_QŸë›Ÿ²=ô†…ÂÚQcw^±TÅ!r‡fU5ß§JB‚ó‚Äß‚‚È a *(’'!092qE*‹|Xå^0Ñ1<"â=˜S–úD׃QM7f=Ǻ:5föùhr>tŒŠ{ç×c”.äNRô` ®Êÿ\îYDPA…!€½ïØ… Ä;¬uKµ\~M8Æ3„;é$‰cŽHÂe[„1à݆·Ù+½T¦®kš¬~ú€mìÎò†8÷Ç ¢„{°Wƒ;LÛÏíìvòì$ L•"ùÞ„Y¨õPýQµ„WTµ¿¶£¸ˆ¢ÇÈtN‹áü"òhKF*Üã›sßÀ²c?ž)ã¿\ù0àõ2 /,8 ÷ûuõ?EþnŠÜ0Æ€”A?až’;똰ü{m1-OŸ}‡B‹1çè9íñålâØWcg6:Ÿ]›ãÑ`t:Ùô8É‘ð.0 ü—u¿#©çr‡7ØÆ–R¥jR[ó_¥Ò¿Œ*G-Uæ½fG–¿Êiÿ9é·qÒH¤²1Ìcq7/uóíû]ú(ßb²IŠç‡©J¶u¦Ò-yqlx†‡ëµáÃ܈üÀ 8–ñ[Ã%Ò "Tc3£ïøF½zííÛ­Z«_Õì–ÙÐêµVS3+ͦ¦›5½×jè¦ÞïÙãuŒ¼i@€®à‚Èe·´ùÊ?Í_±Ëž§ìrÃå7l}ô]ug¸+Êúîf›©o¹ÆX©oŽ],žüûÇ?Q¶£:ƒØD¾âÿ"—½ØX"—¡AY€Ã3ÖÂ? ÀN­ÓiÔڭݱzZÝ­ÔµvÛ±´¦Þè[NCw¬¾õ‹\æ‘ÿltÈ Go÷ êE†—pà cÃ÷tÒp)3øB :7ÞÆ ~ÄÚÀ€çêÈÙÂø@VGÒlõ̦i5µ~»RÑê^¥­µ­–©µk–UÕ«¦Ù«Tó„“=çå4ˆ\äÝf79yþ_ÓPþPK­A É|n™À vs2008/bx_hdimage.vcprojíZmoÚHþL¥þ‡Èê‡V=có*‡«ü‚sH"Hšû ­í6ñۭׄÜ]ÿûÍÚæÅI¸¸m®ê)H1x×3³;3ÏÎãA9ù´ò½£%¦1 ƒ®P;–„#8¡K‚yW¸"ÞÅbMnȧ_ß¾9ùLây–¸$<§á vØÛ7•üîâ>Â]!92>~àÑçµéÎ/’Ä'†È!{5]¸ÄGs,lõO/ûfWøK‘zr£&k¢ÔnYb]–:b[éÕÄFG3­z³Õií/\íÑ9f‹w!½Ý,•®»­œœ{ˆÍBêÇ|´òA¾pQ‘¹|¥šjT *'aèYÄÃÙ¨Za0#ó„"ËæKævÖ1±ÌÿÞ®V%,J˜I(8Òû®p|}||Ú7¢ËE3¡~À0õ±KÃψÎ2‘¯tãÑìÌ2òÀT*ÚÅàŒÄ'âØ'Áññ€ØÑûËRÒfÈ‹qnw(r`Ì6&õ„xî œóXt…wïaŸ°½×ëyñÝû,9ÜùÇ ægziŒ²¨¦wyp>秺½%œÉW÷*IÌB?Õ)#þûÙÀD âC„BZFç ÛL—ÄÁ€ÏÕýWéžõÍA)7FèGÅ«•QÄxrÒLn’VÑ\—ðäõÇKÜ Ž3H¨€ ÄŒ&>Dñ:f‰§s¡‹—¹tDCÇqHM<¤à…ƒÐ*²:5{úå©:5FÃÉhÐS§0mŽ®&ê0}Iу¼1 â_€KEG1qTà6ع·.äÓ9Öº‚’Ï_!@Áà%ö¶³“$Š(ltÂeI¤£ÐÀ½õZé¡êü¸¦Á²Ò(cϦ€swŒã0¡~œƒýªûuöÇvº<#ñXBÁVMR”çV“Ü–>\¸°§-jLáÀ…âžáe§€\Û¡³ˆ=bçJÜ €ŒbŽ#ämŽ}‰”ä§C„É Ç¬ŽõÓ‡‰+˜˜$öä>fØß$²2F@D¼^¹/ >ñMló£Ý[a'á¶ dÚv9žx#ùÉ=Ê|mº—þ¢X9¤û5¥»~H÷+IwäˆÄŸÒýJÒ½œ!vHöëH¶ãÒÐ?$û%{zǽ<¤üœòôšÀ==ão¹˜>Õ3. 9ŒÔ4Œ _%ô‹£®bwo‹ØQ:†Ò–ÄvG7ź-ÕÅv»§‹M¹a齆ÜÓ-ý;[ÄE‡ß×¼œ­úËØÊßœ^ÄVJË/a)«ù{-=ƒ®õolOá‹:*qBÕI¨jû‘êzs•:2\LµI Òy¬ÎÉL½‰æpáôC¥8^©¸ÿP£`®Þ¡å^@6[¦ÖÔô¦hµ%I¬;R[lë-Ml+º^“kšfJµ]@î:“ù˜ýærê…6òòßc¶ƒ“êÿyóÿPK£Ô>üŸ1‘vs2008/bx_ioapic.vcprojíXmÒ@þ¬‰ÿÁ?h´…»ƒôÐô…ž$w;ñ Ù¶¬¶Ûº»EΗÿîl[à@ñª|IL®½îìÌìÎ̳󴜾\EáÃ%pAcÖ©Ô«µÊC`~P6ïTÆ”ñ¡Õõ#½òòŃû§¯©HI8’i@ãK¿_>¸¯xººI SÉUÚOŸVpêõÚuûY­¦¡’·šÒ˜$Ô¯lÍÏ®{N§ò©iZv·é64½ÝîjMÝ6µ–º5MÝiÖên]¯[_”Ùás.G‡bþn³R¶Ì ¼N/C"g1„m‡jPì#lè%xžY<ß19½ŠãÐ¥!ˆ|rwhÇlFç)'—ÍD{²[ë8à¥óÏÛÕî]¤2I¥C9ó›N¥:©V'±÷V ”j®Ôcx%îPÝY8/D±Òµ€‹Ù¹kcbryÕ?§ŒFô#{˜²+AŸzœð›kAæh9#¡€Âï‚pâKà#—VJàÏ1¨ýèq©HžLÖríÑã¼8*ø'Õ…Œr»,GyVñi“œ×ö%‡Ì¶»&Õt®ÿü  G™Mõ7ç}‡Hr 8Á$–±ƒ7¾¤> >W7?e{Þsú¥ÂèÛq”`·^‰TÅ!r‹fUµ  JBÂóÃ4Ø‚‚È!a *(’§092õD&‹X^0Ñ }"æÌ(Ë|¢ƒqoÐЩӵ®ÏŒ©}1]ô»ÆÅÎÅxd ²‰ÂI†ÁSùßË=‹ê#¨0°à¿Û”x‹µN¥QÈÇ„3ì7}XB¸•ŽÒ$á¸Ñ‘$\¦‰EÞ©`xëµ²CÕcê¸fÉr³ìbw–‡0Äy0§Ü‡ÜazØæpn§·“g§¡L9à.kÆ]«¡Ë>eïJ ¥\ìi5$À`~†—Û dâÅþBTCêFÊ ‚ŒƒÂÁ’è¥KRœÀ Ó™ƒcv¿p;.F©7º"LÑ8yHõ«á“ÚÄvZíî üTù”a¶vÎNÁçÄ_P%ðaª ”É÷:ÌR=ÈAõwPFÕ~YUweÇIE3I!錖Ãùe,äÁ–ŒT¸Ã7?æ¾!„€e+Ç~ø©º5ÜÖäŽ}w¯ÍÕw‚Bc ,Ô7Û.OñúñE”O Îv¯€À¿È"/1ˆÆEdPâå+Ä_»Ñn5Z5­Õ¶­éÕšZ«Õµ´cýȵºGz×r­_ÃߢügƒCþ8xÞ¸oP?6ü”^”A87¸¯ã% 2ƒÏ…1§3ãm2Ç ²›ÁA¬ Œw¦nFÂæÆ²<˜ãÇ<6­cÍmÕjZÓ¯µ´–ubj­†eÕõºi:µz‘ý`ò碟œ…±G¢×l§Ï¿óSÊ¿PKŽ£Ô>i,—LÆvs2008/bx_keyboard.vcprojíX[Ò@~ÖÄÿ`ˆ-÷kºhh J‚ìvÅ2m0n;­3Sd½üeƒgÚBÅ­>xIL¶ìÌ™sÎ̹Ì÷QΞm}ïþ¸ ë*Årá>0'p)[u 3ÊÜàÐ*ÕFµðìé½»g¯¨ˆˆ7•‘Kƒ ¼GÞ»{']Þ„Ð-$*÷ÍÇ ¸ôjçºó¤\V‚1ñQÉÞ.®áÆw ™ƒçWC«[øP­´Œf§\ÓL«ÑÓêƒvE3šå¶Ö0›íV§Ó¬[åÚ'evIø 䀣Ëw¿ÞïoôŸ³ ÈeÀ}¡fÙTMÒ“`ŒµjA J±EéÀäì2¼õ@$‹‡S3`KºŠ8‘¸m,:’}µv´ú˜ívç<’a$-Ê1ð€ßt Åy±8ì7š«T¥!“À}p)‘p‹êÁÆI)Ò®œ/_LLL"è]Ž^RF}ú„9‰Ø%õaDmNøÍ• +´\O@êwM8qðS{—FD=w¬0¨ýàá©HÍwríÁä8*øGŵô»8GIVq´OÎ+ó‚ClÛß“j9Ñ/40#!?¶É£þúåÈ"’<œ`óØÌÀžßP°?·7?eûrhr…12?Ä,f^±5B©ŠCdÖͪj®K•„xCæx‘»o "i »‚2!yäcçBF¶ˆe ›Ô &:äBÜ‚%e±Ot0ŽkU}aõ«çúÂ<OÏG}}bë|6ÕÇñBê$îâMÀVù?h—;ÔÁ¦ÂÀ\ƒs-²”8ëµn¡–Êg„3DœlÀˤÓ( 91•„Ë(4cÀ» o·W|©†L]×8Yƒx€8vkyÃ>w' ‚ˆ;pPƒ[LOÛœÎíâë䙑'#xÊr­vÛnèrDÙuîk¡”Ó3w!0˜÷Ë×2·g-еS#囌ƒê#‚%©æ.IzK3L— dÒǫDž;p1ìéàcŠvC‰^¹Ø^€1©CdËêj÷·àDʦ ³upwR¦xIœ5e£?z*yò½ 3Y¨~ yT áäUlÍ Ì£Ø CdHº¤ùúü"ò4$Ÿ•øæÇÜ7ˆ€|ìÇå|ü—*ÿœ­OñŠÿ¯+ÿ)òwSäŽ1†Ì£ s”¼¿ IMòqhqþä;š9ÇÇÌiN.Ó¾y5é/Æç‹Yo2ŽŸOw'9Þ„ÿô;Á‘;èí3b{ûØbªT µ7ÿU*ý˨rü×ReŠ5Yþ*§ýç¤ßÆIG"Ë&°ŽÅݽÔÍ÷ïwñPÿŠÉ¦q?ßU’­•nÁ CÝÑüÛnu–zàz:Åg¾Ñm"u"|õlSFbômCÈ£Ç×ÞúÀlÕZƒŠf¶z ­^k5µ^¹ÙÔª½ZÕj5ª½ê`ðé€#Ô1RÐÜÀ‘ëna÷•¾{Ç.:Ž2L-w¦ßÐõÉ—ÕÌ0«Ê-};Ú&j§± Ó(íN]úæØùâI¿€üC% yë,‰ÿ…þ‡ %ðØóˆ ü{سF õ5ÏÚ×)óðqô­pOBM§Öé4jí²Öî–V·Ëu­ÝîZ³ÚýFµo Œ_…šuúÏõñçÃ>>ò’?I'!š;:u݉¸nû¡îz+;U|¤nS¦ó•ÐWt©¿ Wø@ü¡s[ó¶TzÈVú;²9™×fËê5{FS´Ëe­î”ÛZÛhõ´vÍ0*ÕJ¯g•+i^ƒIÆ)=÷›x)=e“³Òw~EùPKˆ“1@ œ'6D¤vs2008/bx_ne2k.vcprojíXÛnÛ8}vþC`ô¡E+_ä;o¡‹•5àØ4û`À $Úf"Q*E¹Îîößw(É%ñFÛb‹>ˆ q83äÌÎsþqë{gÂ#°~¹^©•Ïs—²U¿|K™|‰”ºÚRË{ýêübìÍDìÒàŠwį_•²·ë‡ô˩ʙñþ}¦>í\÷>ÔjR0Æ>(ÙÛ#ê}ù`|q34ûå¿ÚÍŽnµ,S±ô®¥4ë]éjžRïõF]íZ=Mý*Í®1_aqp÷%à÷ûu’E`«¥ó+‹eÀýHŽC9Èvñ5T©_ª&ÕœÉùuxõH:ªæ‡FÀ–ts,`Ùl‰œìh“ØñêïÃj¥I,ÂX˜”Càè—+óJeØwŠ+US¥!„ûÄ¥XTs §eÈVº‰ÈdyiYbJ%íztIõéŸ$2¦1»¦>Q›cþpáX.±‘ÌïsìÀ6fDì]ê1õÜQ°’¹è—ß¼…}ÂöÞÍwråÍÛ´82øw•µðS»$GiV“·,9ŸŒ+NÛÁ†0!§SýêI#ŽDà'6EÔÿ¸™Xà Âd(àEln‰=#|CøÜ>ü'ÛË¡9*ÆÈü²xäµ4 …,NRÉ}ÑJšëR)ÁÞ9^ìîAI”B*(‹}Èâ<±%²À%›Ì $:äC¢(à&Y ðÂAŽ*Z˜ýæ-ŒÉx6 ÐÄæäv†ÆÉDæ$Aö¦€>È.%GÔPAÄXç>:„‰3¬õËL~‹9ƒn3"⤳8 9lt&0q¨cè—!¼ÝZÉ¡2y\“dYÉ ô°˃àÜ’(ˆ¹CžÖà´éi›Ó¹]'ψ=sðU¯5/­.G”Ý>R9·§jLæBgOñrÔ@ævଣŠGíÌHzq"q„½ý±/P’ì”È0]’HäÁ±›}\¸œ‹YlÏ"Aü}!KS ,$û• ð"“ÜÄaZíÁ–8±ô)“ÙÊ´]bgM)€Mf Ð9ÏÂ,ÔƒLP¿'ETõÈ)ªjm ,¢¨…!0$]Òb8¿ "qº%ŸWs|óïÜ7%²c?ž*㿜òeÀÛuàI^XÁ×G¾_×Qä¦Èc ™çÛŠ™#åƒmˆYt\“—8´2ÿðý:~L¡Æôz17ÓÁb&Ë]0l{û ΔÝê±ù7rêOÙ㟖3³¦ó„5¿•Ü~‘ÓÿONDéýmJ–„Cqw·»GãýE/y…þDi³Ïg‰JºtªÒ/;aˆäÀßv‹\²Dë! Ï:¼C6G¾|¶51ú9&CW~±ÈèáþÛ´ŒN£cÕ££µ”f£ÓV´Z»­¨ZC5;-US-ëkŽ,ä6²¦AàúJ7ä ‹uؤqÍò†<—îŠãdÀK­Só§Ü}òæº7<®Ì ýú¥Ö»W;ÙvÕÝ®«O¶],žg¾F~òˆÒ‰ Ú)ÎNÀòw‚]Ÿƒåð¢5`rí#Ê’ÌAÛÈ=‰Â^£×k5º5¥ÛÓM¥iךJ·;Е¶Ú²ôAKè–þ=(\ç@X<Ä—<$wuäÄÙ~ˆ\o…¸£Â#Mâ«­èÝ…+xHòƒ€ ·¢^ʲú‚7'³Òî˜Z[ÓÛŠÕ­Õ”¦Së*]½£)݆®×Õº¦™µúqVŽƒIcL{Ë…Øð…™Šƒóê3ÿ]ù?PKZ£Ô>ÃË]+Jvs2008/bx_nogui.vcprojíXmÒ@þ¬‰ÿÁ?h´å=M_à$ḠÜy~ !Ûv€Õv[w·ÈùòßmËUP¼ê_“[®;;3»3óì<”g/¶ap\Јõ+õj­r˜ù”­ú•+Êüè½ÐêzK¯¼x~ïî³WT$$˜ÉħÑ9Þ€'ïݽ“?]\ÇЯd*÷íÇ+¸ôjçº÷¤VS‚ QÉÝ.X´Jh¥°>¹9ýÊGÝ2žÕljƒºÞÖšV«£™=»®µôV¯Ùj¶­^Íü¬Ì._rô÷>âoo6JwyŽãÙy@ä2â¡P³bª&ù10À†^Q‚§©ÅÓ=“gQ i"[ÜŸÚ[ÒU‰ÄmSÑì«}p“Õ§b·;g‰ŒéPŽGüº_©Î«Õyä¾Ñ|¥š)˜‚O‰„[T÷6Îêït)àly:´11™À¼ŸRFCú„=MØ aL]Nøõ¥ +´\’@@îwM8ñ$ðÈ—VB­0¨ýàሩHÍwríÁì8*øGÕµ 3»4GYVñé&9¯ìs©í`LªåLÿéQ;2 S›2ê¯OÇ‘äp‚I,csî ø†z€øÜ^ÿ”íéÈ— clGaŒY,¼"4b©ŠCdfU5ß§JB‚ó‚Ä¿‘AÂ@TP&$OB`r.dâŠTù°É½`¢cy DÄXR–úDW£IC7ÎÀº<1öÙdv6 ;gW3c’.äNRô` ®Êÿ\îXDPA…!€½ï­(BPâkýJ#—_ΰ݌aA!%qÌAˆ™$\&±EÞ¯`x»½ÒK5b꺦ɦØÄn-aˆs "J¸y JUö¸ÍñÜ.¾Nž2ဧ¬5·í†.Ç”½-}-”r~¦CÔ8óy)^¾n s7òÖ¢P77R^dŽ–D/]’ü–f˜.AÈ ‡«‡…Ûs1KÜÙµbŠvÀ!HCª_ù/À˜Ô!Šeuµ[ðå S†ÙÚ»;9SœoM”À‡©2P&ß»0Kõ ÕßBUKxeU‡[;ŠË(šqŒ I—´ÎÏ#!¶d¤Â=¾ù1÷M!" ûñL¹ÿÊ€¯ÖQ xaÅI¸ß¯ëÿ)òwSäŽ1F,  † ó”|° YMÊqhuþä;ZŽ9'‡ÌiO/³}9,&g‹+s:MNf»'9Þ9„ÿ²îw„#õ\>`Ä nbK©R5©Âü©ô/£ÊÉ_K•y¯)ÈòW9í?'ý6N:‰T6…%p,îî¥î`~ó~—>Jà_1Ù,ÅóýT%Û:SéW¼86<ÃÿíÖðaiD~`Pëøáiª±Í‰Ñw Œ| #_{›C»Óè ëšÝ1[Z³Ñikf­ÝÖt³¡;–nêÃáç=ŽPÇÈ›àΉ\§€]%tž¾^W=OÙäF;«o˜úè{jaXä–î|{£ÍÔŽ·\£ÀVé›c—ˆ§øîñE”-äˆÎàu/øÀ¿‡Æ5Â.6ÖÅuhPàðŒ­ð‚¯×èõZnMëö,Gkºµ¦Öí,­­·†Ö ¥¬¡•ƒ¯Ìɦ ŽÞîÔ‹ /á†Ɔ¬ îé8¤áRfð•0Vti¼‰W8 ý08ˆ­‡]ª#f+ã=Ù ¦Ýq̶iµµa·VÓš^­«u­Ž©u–U×ë¦éÔêG‚ÉžóNpD. D&.&Ïž~ç70”PK£Ô>ÃÁÿ4—vs2008/bx_parallel.vcprojíXmÒ@þ¬‰ÿÁ?h´XÞ!=4´…“„ã.pçù„lÛVÛmÝÝ"çËw¶-ô@ñª|ILn¹îìÌìÎ̳óPN^nÿḠ!ë–*e½ô˜z”-»¥kʼðƒÐ*ÕFµôòŃû'¯©ˆ‰?•±Gà ¾W>¸/{º¼‰ [JUZOŸ–péõÖuç™®+Á˜¨älæáÄ÷Á/åN¯†v·ô©_«èõF¥®5jfK«w,]3õNCkÛm«×hv*m½ùE™]¾9àèòCÈßíöJ6zãäÂ'rò@¨Y>U“ì$c­ZR‚ç‰Åó=““Ë0ôÔ‘.îO­-è2æDⶉè@vkœxù9ßíÞy,£XÚ”cà!¿é–ʳry:o5O©¦JC&àQ"áÕ½ÓRd;] 8_œ ,LL*è]ŽÎ(£ýšÄì’0¢'üæJ%Z.ˆ/ ó»ÂB¹øäÎ¥Sß…KÌj?zz*Eò½ ³P²QýQ5…[Tu°±Â¨ˆb/Š!é‚ÃùE(äÑ–ŒT¸Ç7?æ¾ ø@c?ž*ã¿Lù0àõ*ô/,9 öûuå?EþnŠÜ2Æù”Á f®’÷7a"­I1-Ïž}‡B‹1çø9­Éå|Ú·®&ýùø|~Ý›Œ‡ãÓé¶ÇIŽ„wá¿´ûáÈmëí3âø»ØªTMjgþ«Tú—Qåø¯¥Ê¬×ädù«œöŸ“~'ˆD"›À8wûRw0ß½ß%ø-&›&x~˜¨¤[§*Ý’E†k¸ø·Ù,ŒÐó Šc½5" "56#1ú>†¡‡a$Ñãko}`µj­AE³Z½†V¯µšZOo6µj¯Vµ[j¯:|ÙãuŒ¬i€®á‚ÈU·´ýÊ?Û¾c—]Wf–[ÓoèúèËjn˜WåŽ}w·MÕŽ÷‚L#–ê›c‹'ûòE”.d°N1v’¯€xÀ¿Éb/2VˆÇU`PæãpðŽ"°Sëtµ¶®µ;¦­Õ½®µÛ}SkV³ß¨öÍù«\e¡ÿlxÈ!Gïw ꆆsà "Ãó—w«8¤áPfð¥0–ta¼–8 ù08ˆ/Ô‡±¥ñ¬f¤Ù²{ÍžÙÔm]×ê®ÞÖÚf«§µk¦Y©Vz=[¯d9 &}ÎzÊ©:Ä©8Ÿœ<ÿÎj(ÿ PK£Ô>‹u“*0ˆvs2008/bx_pci.vcprojíXmoÓ0þ ÿU|AJš®oÊ j“tT꺩Ý*UNrm ‰l§t¼üwÎIº¬…²À^$¤¹‹ÏwgßÝã{š¿Ü„ÁÃ5pA#Ö­Ôªzå!0/ò)[v+W”ùѡՌ†QyùâÁýã×T$$˜ÊħÑ9Þ‚'Ü¿—?]\ÇЭd*­§O+¸ôzëºóLו`LBTr7󨣕Âöärhw+Ÿt[ov§¥5œ–­Õ [ëØÍž@ïV³iéFã‹2» | rÀÑÛ‡ˆ¿»Ù&ÝãŽãó€ÈEÄC¡fÅTMòC`xu£¢ÏS‹ç;&ÇQ h"[ÜZ[Ðe‰ÄmSÑžìÖ>6¸Éòs±Û½³DƉ´)ÇÀ#~Ý­TgÕê,rßj¾RÍ”†LÁ§Dª;gUÈwºp¶8X˜˜LлRFCú„5IØ aD]Nøõ¥ K´\@@îwE8ñ$ð)È—ý„þ(Zb.PûÑã!S‘<™måÚ£ÇYqTðOª+fvi޲¬âÓMr^[çR[g LªåLÿùA+2 S›2êoNG6‘äp‚I,csîøšz€øÜ\ÿ”íéЕ cdEaŒY,¼"4b©ŠCdfU5ß§JB‚!ó‚Ä¿‘AÂDTP&$OB`r&dâŠTù°Î½`¢cy DÄmXP–úDWÃqÝ0ç¶Ó¿<1çÖÙxz6rÌ9Ší³«©9Nr')zH0Wå.÷úDPA…!€µï(BPâkÝJ=—_ΰٌ` A!&qÌñ SI¸Lâ>a x·‚ám÷J/Õ©ëš&k>` »³<„!Îý ˆ(áìÔàÓÃ6‡s;¿<+ dÂO©×ëwí†.G”½+}-”r~¦}ÔØóy)^n7™y+Q ¨›)/2 GKb”.I~K3L dŽýÕýÂí¸˜&îôZH1E[à$!Õ¯|„`LêŲºÚμDù”a¶vîNΧÄ[Q%ðÑS(“ïm˜¥zêï Œj_xeU+ŠË(öâ’.h9œŸGBlÉH…;|ócî›@X¶rìÇ3åüW(ÿ¼ZEâ…%'án¿®ý§ÈßM‘[Ʋ€2$ÌSrg–§-Ç¡ÕÙ³ïPh9æï3§5¹˜OërâÌÇgó«Þd<ŸL·=Nr$¼s ÿeÝïG¹ÜaÄ nbK©R5©Âü©ô/£Êñ_K•y¯)ÈòW9í?'ý6NÚ‰T6p,îö¥no~ó~—>Jà·˜lšâùaª’m©t+^›žéáßfcú°0#?0)ŽUüÖt‰4‰ÕØäŒÄèû†>†‘F¯½G«Uo jšÕê5´£z«©õôfS3zuÃn5Œž1|ÙáuŒ¼i@€®áœÈU·²ýÊ?‹=Zõ̘-Íd}0Í–ÝköúMmÐÖuíÈÓÛZ»ßêiíz¿_3j½ž­×òdì“=çä$ˆ\ä]¦˜?ÿÎ/h(ÿ PK£Ô>Û‡r43”vs2008/bx_pci2isa.vcprojíXmoÓ0þ ÿU|AJ—¾NYAÍKG¥®›Úò¡Rå$×Ö8ÁvJÇË眤ËZ( |àEBZºø|wöÝ=¾§îÉËM<\4bÝÊQµVyÌ‹|Ê–ÝÊ”2?ú ´#½©W^¾xpÿä5 &2ñitÁ£·àÉ÷ïåo—×1t+™ÊCëéÓ N½Þº>~V«)Áˆ„¨änæ±Gu*H¥°?½ØÝÊ'KoÖZ-ÛÖìzÇÑNÛÒzN­¡õF£Ù0[ºÝù¢Ì. _‚ìsôø!âïn–J×yÏÉE@ä"â¡P£b¨ùF0ĺ^Q‚ç©Åó““Ë( ú4‘Mî­ˆ-è2áDⲩhOvkÜdù¹XíÞy"ãDÚ”cà¿îVª³ju¹o5_©fJ&‡àS"áÕ…³Jä+] 8_œõ-LL&è]Ï(£!ýÂ'ì’†0¤.'üúJ%Z.H ÷»"œxøäK3¡?Œ–˜ Ô~ôxÀT$Of[¹öèqVü“êJ†™]š£,«øv“œ×Ö‡ÔÖY“j:Ó~ÐÀJ„ŒÂÔ¦Œú›³¡M$9œ`ËØLÁ_SŸ›ëŸ²=ØÃRa ­(Œ1‹…W„F,Uqˆ,ЬªæûTIH0`^ø7€  2Hˆ Ê„äIL΄L\‘Ê"Ö¹LtÌ#„ˆ¸ ÊRŸè`:Õucn;æÕ©1·ÎG“ó¡cÌQlŸO'Æ(Ȥè!Á\•ÿ¸Ü3‰ ‚ CkÞ;Q„ ÄÖº•z.Ÿΰá a A!$qÌAˆ‰$\&±IÞ­`xÛµÒC5`긦Éê§/ØÆî,aˆs "J¸;5¸Ãô°ÍáÜÎo'ÏJ™pÀ]Öêõ»VC—CÊÞ•>J9ßÓ>jlˆùÀ¼/·È̼•¨ÔÍ”…#‚%ÑK—$?%€¦ 2Çþì~áv\Lwr-$„˜¢-p‘êW> 0&µ‰bZmg^¢|aÊ0[;g'gŠ3â­(ƒøè© ”É÷6ÌR=ÈFõwPFÕ^YÕþÆŠâ2н8F†¤ Zç‘[2Ráßü˜ûÆPŽýx¦\‚ÿ å?À€ÓU(^Xrîöë£ÿù»)rËPý„yJîlbÂDV“rZ=û…–cÎÑ>sZãËùı®ÆÎ|t>ŸöÆ£Áèt²íq’#á]`@ø/ë~8RÏå#np[J•ªIæ¿H¥UŽþZªÌ{MA–¿Êiÿ9é·qÒžH¤²1,€cq·—º½ñÍý.}•Ào1Ù$ÅóÃT%[:SéV¼86<ÃÃ¿ÍÆðaaD~`P|Vñ[Ã%Ò "TÏ&g$Fß'0ð1Œ4z¼ö6úV»ÞîiV»×ÔõvKëá=XÓ{uÝn7õžÞïÙáµ¼i@€®á‚ÈU·²ýÊ?˯ØUÏSv¹áÖò¶>xW- ‹¢ÜÑ¡ïn¶™ÚáVkxÀJ}³íñß?þ¡ˆ²‰ÕÄ òø÷¹BèÅÆ ḠÊ|Òp)3øRKº0ÞÆK| ý08ˆ/Ô‡³¥ñ¬&¤Õ¶{­žÙÒúZMkxµŽÖ1Û=­S7Í#ý¨×³kGyBöƒÉÞóŽrD. D&.'Ï¿ókÊ¿PK£Ô>µÒiê3”vs2008/bx_pci_ide.vcprojíXmoÓ0þ ÿU|AJ—¾++¨y•ºnj7ƇI•“\[CâÛ)/ÿs’¶k¡,ð iîâóÝÙw÷øž¦Ç/WQøp \Иõ*GÕZå!0?(›÷*W”ñ¡éM½òòŃûǯ©HI8‘i@ãs¿_>¸¯xº¸I WÉUZOŸVpéõÚu÷Y­¦#¡’·š&>Ò*[û“ËÝ«|ê4kfÛév4½Ù0µFDZµ®cÖ4Ûi¹n£Õêê­ÖevAø¤ËÑ㇘¿Ûl•íóÇñyHä,æ‘P³íTMŠƒ`ˆu½¢Ï3‹ç;&Çqº4‘/îN­˜Íè<åDâ¶™hOvk¼tþy»Û½³T&©´)ÇÀc~Ó«T¯«ÕëØ{«J5W0 <‚€ w¨îlœW¢ØéRÀÙìÔµ01¹ 1<¥ŒFô#kœ² Ázœð›KAæh9#¡€Âï‚pâKà—fJÃ`Ï1¨ýèñ€©Hž\¯åÚ£ÇyqTðOª åvYŽò¬âÓ&9¯­s™­³&Õr®ÿü • G™Mõ7§C›Hr 8Á$–±¹o|I}@|®n~Êöt`K…1´â(Á,n½"4©ŠCäͪjA@•„„æ‡i°‘CÂ@TP&$O#`òZÈÔ™,`YxÁD'<öAˆ˜Û0£,󉮣ºnLmǼ<1¦ÖÙhr6tŒ)Ší³«‰1Ê 'zH8Oå.÷L"¨ ÂÀZ€ÿNlCPâ-Öz•z!¿"œaít’& ǃN$á2MLÂð^Ã[ï•]ªS×5K–›=`»³<„!΃1ˆ8å>ìÔàÓÃ6‡s;½<+ eÊOY«×ïÚ ]){WúZ(åâLû¨±!ó3¼Ün ×^ì/D5¤^a¤¼ È8(,‰^º$Å-Ì098öW÷ ·ãb’z“!!­CˆT¿ ^€1©Cl—ÕÕvVà§Ê¦ ³µsw ¦8%þ‚2(¾Ê@™|¯Ã,ÕƒlTeTMá—UuWVœ”Qì' 2$Ñr8?…<Ø’‘ wøæÇÜ7†°låØçÊåø¯Pþ xµˆCÅ sN¢Ý~}ôŸ"7E®cÀBÊÀM™¯äÎ*!¬ø^[ŽC«×ϾC¡å˜s´ÏœÖøb:q¬Ë±3M¯úãÑ`t2Y÷8É‘ðÎ1 ü—w¿©r‡/ÜÄ–Q¥jRó_¥Ò¿Œ*G-U½fK–¿Êiÿ9é·qÒžHd²1Ì€cq×/u{óÍû]ö(ßb²I†ç‡™J¾u®Ò«øIbø†«•À̈ƒÐ 8É[Ã#Ò "RcU0£ïSF=¾ö6\«]o»GšÕî7µF½ÝÒúµVKÓûuÝn7õ¾îº_v8B£hb€K8'rÑ«¬¿ò_¯ØUßWv…áÚò¶>ø®º5ÜåŽ}w³ÍÕ·‚Bc‹¬Ô7Ç.OñýãŠ(_(PCì"_ €‘ „^b,Ž‹È ,Äá+`·Þí6ëšÖéš¶Öðj ­ÓqL­¥7]ÓiêŽéš¿ÀEùÏF‡ rðÆqß ~lø)7¼(1‚pnp_Ç! 2ƒÏ…1§3ãm2ÇÙ‡ÁA¬ x¦>Œ„Ídy0!­¶ÝoõÍ–ævj5­á×:ZÇl÷µNÝ4ô£~ß® Ù&.:ÊI{$,ºÍvrüü;¿¦¡ü+PKŽ£Ô>«6U0ˆvs2008/bx_pic.vcprojíXmoÚ0þ¼IûÚ‡M[ T)›È[‡DiíºHÈIð–8™í0º—ÿ¾s °±fû°iRMãóÝÙw÷øÂÉËU>\4fÝJ½Z«<æÇeónåš² þ ´º~¤W^¾xpÿä5) Ç2 h|Áã·àË÷ïO—7 t+¹ÊCëéÓ .½^»>~V«)ÁD¨ä­¦ õ+[ÛÓ«¾Ý­|r[M·Ö¶ZÝv­é;ÚqËÔµŽÓvÜ#½Ö³:Í/Êì’ð9H—£·1·Ù&Û㎓‹ÈYÌ#¡fÛ©š‡ÀðzE žgÏwLN.ã8ti"_ÜZ1›ÑyʉÄm3ÑžìÖ>6xéüóv·{ç©LRiSŽÇü¦[©NªÕIì½Õ¥š+õ™A@‰„;Tw6ΫPìt%à|væZ˜˜\лœQF#ú„5JÙ%`@=NøÍ• s´œ‘P@áwA8ñ%ð1ÈK3¥a0ˆç˜ Ô~ô¸ÏT$O&k¹öèq^ü“êBF¹]–£<«ø´IÎkë‚Cfë,Iµœë??h`¥BÆQfSFýÍÙÀ&’œN0‰el®Á_RŸ«›Ÿ²=ëÛƒRa ¬8J0‹[¯Dªâ¹E³ªZP%!aŸùalAAä0” ÉÓ˜œ™z"“Å, /˜è„Ç>sf”e>ÑÁuØÐ©í˜W§ÆÔ:ŽÏŽ1E±}~=6†ÙBá$C Gà©üïÀåžIõTX ð߉mJ¼ÅZ·Ò(äׄ3l6XB¸•ŽÓ$áxб$\¦‰IÞ­`xë½²KÕgêºfÉr³law–‡0Äy0§Ü‡ÜazØæpn§·“g¥¡L9à)kÆ]»¡ËeïJ_ ¥\œi56$À`~†—Û dâÅþBTCêFÊ ‚ŒƒÂÁ’è¥KRÜÀ Ó™ƒcu¿p;.Æ©7¾"LÑ8IHõ«á“:ÄvY]mg~ª|aÊ0[;w§`Š3â/(ƒøè© ”É÷:ÌR=ÈFõwPFÕ~YUweÅIÅ^’ CÒ-‡ó‹Xȃ-©p‡o~Ì}#ËVŽýx®\Žÿ å?À€×‹8T¼0ç$Úí×õÿù»)rÍ}RnÊ|%wV aÅwÚrZ<û…–cÎá>sZ£Ë騱®FÎtx>½î†ýáéxÝã$G»À€ð_Þýp¤^ÈF¼p[F•ªImÌ•Jÿ2ªþµTYôš-Yþ*§ýç¤ßÆI{"‘ÉF0ŽÅ]¿ÔíÍ7ïwÙ£~‹ÉÆžf*ùÖ¹J·â'‰á>þ­VF3#BƒâX$o HƒˆHUÁHŒ¾O¡`YôøÚÛt­v£íÖ5«Ý;ÒšvKëÕZ-Mï5t»}¤÷t×ý²ÃêEÓ€\‘‹neý•’P¿êûʦ0Z[}ÃÔßS·†Û‚ÜÑïn´¹Úá6Phl±€UúæØåâ)¾{üCå ¢sx@ã+ ðï¡q°KŒBq”…8|c%‚ƒà;n5:5­slÚZÓ«5µNÇ1µ–~äšÎ‘ù à[QÿldÈo÷ êdžŸrË#ç÷uÒð(3ø\s:3Þ&s}ÄÊÀ`gêÃHØÜø@–“ÑjÛ½VÏlin§VÓš~­£uÌvOë4L³®×{=»V/’±Lþ\t’Ó0öHXt™íääùw~ACùWPK o/@w¥£,Yµvs2008/bx_pit.vcprojíXÛnÛ8}vþC`ô¡E+_äkÀx ]³;°“f ”DÛL$JKQ®³»ýåý†Jò-‰×j-º@È©’3sx™‹ëÀ?[ÓõÊõJ­|F˜z”-zå;ʼðs¬ÔÕ–ZþøËëWŸhœ`"†×<¼'®xýª”¿ÝîsìÂ2&Dl‡Ôê{ƒp!sÑ+¿y ë„å½›nú•7o³âÈàßU–"ÈüÒeYMßòä|2®9I}­aB~Îì«GŒ$aú1ÿíj`b/ #¡ñ¹#΄ðu àsýøU¾W}sP(ŒdqoÔÒ(²8i%·E+ižGeöûÌõo Jâ PAY,x@§±Hœ8í =²ÊGDGùºþS"¿·Dn£Ï|ØßvÂ\Ùo­#ÌâýšœÒÐÊôà ZL9‡O•ÓßÌ&–q;¶fÃÑìNûÃËɆãÁ»†€ÒCöû=ÕÈ õZ ;þ6¶T*%I=uÿF)ýa¤røÃJeÎ5ÏÄò[5í§&ý÷šô¤+»¶Éœp(îæR÷¤½½ß¥¯@û{J6Iñ|–šdSg&½²EÈE.ü­×È#sz>¢ð,£{ä`pÈg+£¿'¤ïÉƒŠŒ®½MÛè4:v]1:ZKi6:mE«µÛŠª5T³ÓR5Õ¶¿h„\FNn­tE®±X¦€MüS¸^wU·Õ¬¸nºÌ3s}.×G/«[Çýªœ èSl»5;Ê‹êfÕÕgË.Ï <¢ìÃWÔùg‰ÿÇ%N_FŽ°Î¯{„¿Ä:K —-r–¢ ‡¹h{GIæ¼q~ÞjtkJ÷\7•¦Sk*Ý®¥+mµeëVKµt[ÿV’Y°(‚ÿÞ"ø¨ÿ‰ôlŽ/%ˆ»ˆº!rŽœ Bž¿@ÜUáÈ¡ ñEŒtŽî£<$ýApPZ#ÈØ\þ ˆ-Ðg¼:šÑvÇÔÚšÞVìn­¦4ÝZWéêMé6t½®Ö5ͬÕ÷3ºLc&;—~èÀ#ëÞ5.ª/ü»úÿPK[£Ô> %ò–0gvs2008/bx_rfb.vcprojíXmÒ@þ¬‰ÿÁ?h´'Ž—T4}¡' Ç]àNüp Ù¶¬×nëî9_þ»³mAñª1¾$&WnwvfvgæÙy(Ï^¬¢ðþ¸ 1ëVjGÕÊ}`~P6ïV&”ñ;¡Õôc½òâù½»Ï^Q‘’p,Ó€Æç<~¾¼w÷N1º¸I [ÉUîÛWpéÕÚuçIµªC¡’·šò™WÙÚž\önåCM¯éŽÙ8ÖZ»¥5z¶«YjC3{V»Ù0N»æ~Rf„ÏAº½½‹ùõf›lçø<;‰œÅ<j¶ªIq ¯®W”àifñtÇäÙE‡. Aä‹»S;f3:O9‘¸m&Ú“}±^:ÿ¸ÝíÎY*“T:”cà1¿éVŽ®ŽŽ®bï(Õ\©Ï$ðJ$Ü¢º³q^…b§Kg³SׯÄäóbpJè{ö(e4‚õ8á7—‚ÌÑrFB…ßáÄ—ÀÇ 7.­”†Á žc.PûÁÃ>S‘<ºZ˵óâ¨à-d”Ûe9Ê³Š£Mr^Ùç2ÛÞ˜T˹þÓƒv*de6eÔ_Ÿ"É 0à“XÆfÞø’ú€ø\Ýüíiß” c`ÇQ‚YÜzEh$R‡È-šUÕ‚€* ûÌÓ` "‡„¨ LHžFÀä•©'2YÀ²ð‚‰Nxìƒ1w`FYæLúúnLžuybLí³áølÐ3¦(vÎ&cc˜-N2ôpžÊÿ\îXDPA…!€½ÿZlCPâ-Öº•z!Ÿΰ٠` áV:N“„ƒcI¸L‹0¼[ÁðÖ{e—ªÏÔuÍ’åfla·–‡0Äy0§Ü‡¢¥*{Øæpn§_&ÏNC™rÀSVëõÛvC—Ê®K_ ¥\œi5$À`~†—/È•û qRïþ;û×u] Ê#ŽƒÂÁòè¥ËSÜÀlÓ™eu¿ˆ;.Æ©7¾"L×D Iõ®¡Ÿ:ÄvY]óÞ üTùÂôaævîQÁ§Ä_P%°bª ”Éý:ÌRýÈAõk(£j ¿¬ª»²ã¤Œ¢™$È–tFËaþ<ò`{FZÜážïóàB Ê1!Ï•Ëqa¡üØp²ˆCÅsN¢ÝÞ]ûO—¿›.×ìÑg!eà¦ÌWòÞ*!Lä5)ŧª_@§Ã}:µGÓqϾõ¦Ã³éÄ ûÓñºÙIŽ,xŽ‘á¿¼  N½÷ñÂMªnµ1ÿY~ýËøsø×ògÑt0èOÝ¢úmDµ'™l3àXèõ[ßÞ|ó˜ %ð/èmœaû~¦’o«t+~’¾áãßje03â 4(>‹äái©gUУoSèF=¾7\»Uo¹5Ín™ÇZ£ÞjjfµÙÔt³®;­cÝÔ]÷Óq¨c B p çD.2ðÎSzÅgÞ‘ï+‹Âdmóy|ÝnËqKþ½÷æj‡B¡±EÖè«c—‹§ø:òE”/xÎÁu‹/À¿…Å‚.1ÄEdPâã+„^§Þé×ÛU­Ý±­áUZ»Ý³´¦~ìZ½c½g¹V½2'C8xO¸oP?6ü”^”A87¸¯ã# 2ƒÏ…1§3ãM2DzƒƒXxØ™ú067Þ‘åÁ`š-ÇlšVSsÛÕªÖð«m­mµL­]·¬š^3M§Z;L>.úÀI{$¹x;yöô?¡ü3PKH“1@K=™D vs2008/bx_sb16.vcprojíXmoÛ6þìýÑ-ZÙ²”øŒWèÅÊ 8v`'Í>0(‰¶™H”FJ޳­ÿ}GI~KâEë°¢ D†x¼;òîÞ#æüó: NV„ ±nµQS«'„y‘OÙ¢[½¥Ì„ÒÐδêç_Þ¾9ÿBEŠƒI’ú4ºâÑñ’·o*ÅÛõcLºÕ\åÄúø± S_6®;ŸTU †8%w=n£YÝ_ÜôínõOCíôtíTS=ëL9í¨ ÅÔMqtUÕ ]³ÍFã«4»Æ|A‡ƒ»‡ˆßo×É­VίœÌ# 9Ú å ØħkR¿RÏ,ê&ç×Q84 ù¨~8´"6§‹”ã–-–8í­c7]üµ[­2J“8MlÊ!ðˆ?v«µi­6Ü;Å—ª¹RŸ%„‡Ä§8!¯¨,œ—¡XéFÑüÒ±ŠÄT*Æõà’2Ò?ˆ°Æ)»¦!P—cþx#ð,ç8¤ð»Ä{° I¶.Í”þ ZÈ\t«ïÞÃ>a{¦¹òî}^ü‡Ú2 s»,GyV³·"9_¬+N2ÛÞŠ°DNçúõ£V*’(Ìlʨÿv9°q‚/#¡ˆ—±¹%î„ðõàsýø¯l/ûö T+ cÈâž×Ê(Ndq²Jn‹V1|ŸJ úÌ R JD ¨ L$< !‹S‘¤®Èd‘OV…HtÌ#q›Ìxá ô‡º†fvϼ¹@3k4œŒ=4±=º a6Q8ÉЃƒ1 ò—ЉõT±–Ä»» qµnU/ä·˜3è6²"ÁN:Iã˜ÃF' æI›˜AºUo³Vv¨úL×,YNö=ìÕò`8÷ÇDD)÷Èó7=ns<·³ýäYi¤|5T]m5p9 ì¾ô±Ê{Ú¡Æ&1a>tö/{ dêFÞRÔêFÒ €Œ‰#l}‰’§„@†éœˆä›Ù§…;p1IÝÉ£HH¸-deŒ…d¿ò^b’›ØMË£Ý[/•¾ e2[g'oF—Ø[RFJàÃ(u΋0Kõ ÔïIUSxeUµÅe8†¤sZçW‘HŽ·äóúßü3÷I@ låØçÊåøï@ù»2àí2 $/,àëã°_7~Rä÷¦È côYçÛI™'å½uŒ™Ø¯ÉkZ›~úï:|J¡Öøz6éY7ãÞl8šÝãax1Ù4»„ó]AdÙçö^|J–›ÜcØ ¶Afœ)»ÕSóoäÔ†3‡?,gMçk~+¹ý$§ÿŸœžˆòûÛ˜Ì ‡ânnwOÆÛ‹^ö ýÒ&žO2•|é\¥[õâyȃ¿õùdŽ"?@že|‡\œ ,Bù¬ jbô÷”ô}ùÅ"£‡ûï©cµô–ÓP¬–÷_½ÕT µÙT4y÷mi†æ8_ÈBn£h®¯tE®p²Ì›5®)?æOåu»æyìrÛÜø9s½·n ÷ëòJ·~­ñnÕŽvƒF}³ëú³m—‹ç…o‘<¢|¢v޲# ü•`Ÿð—@¹ôÅh ˆ\†ˆ2$óÐZøG1ØÑ;3½­*íŽi+§®zª´Û=SijgŽÙ;Óz¦c~;—,à†G^ ‘{ˆzòRŽÜ0F~°@ÜÓàIKâ tŽîâ<$ûAÀ„k1ÏåŠÙ=àÕÑœ4[¶Ñ4̦â´UU9õÔ¶Ò6[†ÒÖM³¡5 ÃVû9Ù&1ï+AäÂ×e.Þ Îë/üg äPKÕ¤Ô>Oh¯–RÚvs2008/bx_serial.vcprojíX[oÚ0~Þ¤ý‡ íaÓ¡ª”M¹‰Ò ÚuHÈIà5q2Û¡t—¿¼ß°ã$À`cÍö°‹4©¡Îñ9Ç>æøå2 .€ ³N¥^­Uó〲Y§rEYß­®ê•—/Ü?~MEJ‘LŸóø-øòÁý{Åèâ6N%Wyh?}ZÁ©×+×GÏj5%•¼åD§$¬lÌO.{N§ò¡Q³ê­šÝÒœvÝÒÌn]3­¦«5×µj‡Í#[¯Rf„Ï@ºÞÄüz½R¶Ì |ŽÏC"§1„zÛ¼ª—baC¯(ÁóÌâù–ÉñE‡. Aä“Û¯v̦t–r"qÙL´#ûj¼töq³Ú½³T&©t(ÇÀc~Û©TÇÕê8öÞjRÍ•zL  Dª[ ç…(Vºp6=umLL.0/ú§”ш¾aSvA#èS~{)È -§$PøN|ÜÆäÚ¥•Ò0èÇ3Ìj?zÜc*’'ã•\{ô8/Ž þIu.£Ü.ËQžU­“óÚ>çÙvÀ¤šÎõŸï5°S!ã(³)£þæ´ïIN€'˜Ä26Wà€/¨ØŸËÛŸ²=í9ýRaôí8J0‹¯Ø‰TÅ!rÓͪjA@•„„=æ‡i°n "o »‚2!yaÇB¦žÈdq‹Â &:á±BÄÜ)e™OtpÕ4tcât­ËcbŸ Fgý®1A±sv52ÙDá$ëÁSùßj—{ÔǦÂÀžƒ-6!(ñ¦×:•F!¿"œ!ÞôaáF:J“„ƒ#I¸L‹0¼SÁðVke‡ªÇÔqÍ’åfD±;ËCöy0§Ü‡­Üaºßfn'_'ÏNC™rÀ]Ö»VC—}Ê®K ¥\ìi·kH€Àü¬_¾±ûsQ ©÷ðFÄþuCWãÂòˆ ÇAõÁòè¥ËSœÀlÓ)™7Êîìn·\ŒRot+$D˜®Uä$…]¶`|j›iuÌ»KðSå Ó‡™Û:GkœN”èSe LîWa–Â#Õ¯¡Œª%ü²ªîÒŽ“2Šf’ [Ò)-×óç±{áiq‹{~̃C(Ç„píV£åÖ5»ejVS3kͦ¦› Ýiê¦îºŸ¶øBm£1Àœ9ïTVWq~ó®ú¾2+ìV†ß÷Þ+ìÆpS“;ÀúnÜÍÕö£B¡±.®*ï7Û.OñUäŠ(Ÿø¹*O8¹ù_é¸ÒÙPß=¯€À¿=sĘĘ#îÌ#ƒ²ßXŠ`/Ò5ŽŽíšÖ>²íÀ«hív×Òšú¡kuõ®åZ¿†4ó"ðŸkãÏ;m¼ã¦|ކ ö4÷ êdžŸrË#g÷u|¤áQfð™0ftj¼Mfø@öapKÓ6UFÂfÆ YìMk³å˜MÓjjn»VÓüZ[k[-Sk7,«®×MÓ©Õ‹´î“ : c„9m^ŽŸç7Y”PKU“1@0¦4>^ùvs2008/bx_soundmod.vcprojíX[oÛ6~vþ‡ÀèÊV¾H¾‚ñ ]3ŽØI³%Ñ6‰Ò(Éq¶õ¿ïP’/JãZk±¢ DytÎ!Ï…ß'æüÃÆ÷ÎÖ„G4`ƒj³Ö¨žæ.eËAõŽ27xŒ¤¦Ü–«~}ýêü#ìMãÄ¥Á5~UÉG7O!T3•3ýÝ»*¼ú¸uÝßhÁû doæQ0×ÜêÞÁÅíÐTÿjËšÙ7ûŠ$[­¶Ô²LEê©Ý¶d)VOî+F£Õ4> ³Ì—$¶8¸| øÃn­t!ØnåüÚÃñ"à~$fû©˜ä;YèWê©E½`r~žE=’ÍêÅ©°]&ǰl¾DAv°ŽAìdù÷~µÊU‡IlPüiP­ÍjµY`ßK®PÍ”†,&Ü'.Å19¡ZX8+E¾ÒmD®—–ž'¦RQoF—”QŸþI"}’°ê“µ9æO·^‚å{Éý®0ÇlcJâK-¡ž; –"ƒê›_`Ÿ°½·³­\zóKVüÛÚ*ö3»4GYVÓQžœú5'©­¹&,¯3ýúQ=‰âÀOmʨÿ~92pŒ/#¡€—±¹#ö”ð5uôçæé_Ù^Q©0Fzà‡Å¯•«0ÅI+¹+ZEu]*$Ø2ÇKÜ]CPe- +(‹bžøÅY'v”Ê—¬s/艢€dm6/„áX‘ÑÜ0µÛ 4ׯÆÓ«‘‰æ 6®î¦hœ¾È¤Ýƒ½ tä¿Ð. GÔ¦‚ˆ¾"ÎC´!ç½6¨*¹üsˆ3"kâí¥Ó$ 9ltc'¡†`P…ð¶k¥‡jÈÄqM“e¥À±“åÁ úÜ@!îÏkpÜô¸ÍñÜΓ§'^œpðÕl(Ê©ÕÀ刲‡ÒÇB(ö´ïƒ„„¹€îY¿ÈÌœUTó¨}öH™ï‹Qn.üA»q": {;(Qœü¼È5](.¶Éöíó\L{úÅÄß•´2ÁÀI¹\h4щMì_‹Cnnˆ“_<‘·Â)Ê`é;+ÊH‰NQEJø<ÌRhd€ú)£ªENYUk£aE5 +é‚–ëøë Šƒóy½À<_fÁ ñ”­òL¹”¿+Þ­O0ľCŠÈÝüI–ß›,·Ü1dœo+aŽ››³è°&§Ø´6{ÿíd:~N¦úäf>5õÛ‰9_ÍïÔÉx8¾˜nÁ.æÀ×Yúñ}ƒÏis‹Á&ö· 2eOVÏÍ¿’]öÿ°ì™ƒÎøókiî'Mý÷4õL”Ýé&dA8”y{ã{6ß]þÒ!0Á¹MÓÎ>KU²¥3•AÕ Cä þ6ä’ \QxVá=²qŒpä‹g““£$dèŠo=܉[–ÞUºVSÒ»*܉•nGRŽ$«ŠltÛ²*[Ö§mˆmäðAàJK×äÇ«´uS›¥ðÙö^sœ¼õ2ûÌÁç<~ô>»3<¬Í ì>Ã;µ£Ø°Õ¨ow]ÿlÛåâyáËä({ñÕŒúYíÿqµÓ!àÊú`—ð—`hx¢`ÐÊG”1m"÷(êô•~¿­ôR¯¯RËn´¤^ÏÔ¤ŽÜ¶4³-›š¥}ê¬ møM-}ÔÕ‰|m?I^Êwuä$Ù~ˆ\o‰¸#Ã#›2Ä—ZÒº—ðôÁGÕA â…l‰ñúhŠ;]Cí¨ZG²z†Ôr=©§uU©§hZSnªªÑh¦ø0˜,ÆŒ˜.¼À†‹J&ÞOÎë/üËäÿPK5£Ô>P•ð/3”vs2008/bx_speaker.vcprojíXmoÚ0þ¼IûÚ‡M[ºZ JÙ”Ò!QZA;ö¡r’¼&Nf;Œîå¿ïœl¬Ù>ìEšTÓø|wöÝ=¾‡pòrGÀMX§V?ÐkIHÙ¬SS&ï…V7ŽŒÚË¦"#ÑHf!M.xòùàþ½òéò6…N­Pyè<}ZÃ¥×+×ÇÏt] $F%9)àµýéUÏíÔ>Öu½iXFSk[Ç í°íYšmèºÖrœ¦g9zóØ=ü¬Ì. Ÿô8z|Ÿð›õVù>/pœ\DDN 5ÛLÕ¤<†Ø0jJð<·x¾err™$‘G#ÅâöÔIØ”Î2N$n›‹vd_íゟÍ>mv»wžÉ4“.åxÂo;µƒëƒƒëÄ«…JµPê1 <† w¨nm\T¢ÜéJÀùôÌs01…ÀºìŸQFcú„3ÌØ%¡O}Nøí• 3´œ’H@éwN8 $ðȵK;£QØOf˜ Ô~ô¸ÇT$O®WríÑã¢8*ø'svyŽŠ¬âÓ:9¯ ¹mwLªåBÿù^'2‰s›*êoÎú.‘äp‚I¬b3|A@|.oÊö¬çö+…Ñw’8Å,n¼"4R©ŠCäͪjaH•„D=DY¸Q@ÂDTP&$Ïb`òZÈ̹, aQzÁD§< @ˆ„»0¥,÷‰ƽAÃ0'n×¾:5'Îù`tÞïš»çã‘9ÈJ'9zH4_å .÷l"h€ ÂÀ™Cp#6!(ñkZ£” gØpú°€h#eiÊAˆ‘$\f©MÞ©ax«½òKÕcêºæÉòòlcw–‡0Äy8‘d<€­Üaºßfn'_'ÏÉ"™qÀSêÆ]»¡Ë>e7•¯…R.Ï´‹R`!° ÇË× äÚO‚¹8ˆ¨_)/2 GKbT.IyK3L§ dŽÝÕÝÂm¹eþèVHˆ1E+à$"Õ¯B„`Lê›euµ»K2å S†ÙÚº;%Sœ‘`NTÀ‡¥2P%ß«0+õ Õo Šª-‚ªªÞÒIÒ*ŠVš"CÒ)­†ó‹DȽ-©p‹o~Ì}Cˆ€¨Æ~¼P®Æ¥ò`Àñ<‰/Ì8‰·ûuý?EþnŠ\1FE”—±@ɻ˔0QÔ¤‡"¨ž}‡B«1ç`—9áådÔu®†ÝÉà|2¶†ƒÞàt´êq’#á]`@ø¯è~{8Ò(å]Füh[N•ªI­Í•Jÿ2ªüµTYöš Yþ*§ýç¤ßÆI;"‘ˆ0ŽÅ]½ÔíÌ×ïwù£þ“r‘&±Ë’‘}—A/Ä0òèñµ÷ÐsZ–Wל–u¤6ZMÍÒ›MͰ†Û:2,Ãó>oq„:FÙ4 ÂpAä¼S[}å¿._±‚@Ù•†+ËoØzï»êÆpS”;:ôÝͶPÛß J °Rß»Z<å÷(¢b¡Du±=ˆ|$þ=DÎz©9G8Îc“²G`.E¸€Çãã£F[×ÚǶ«úú¡Önwm­iyv÷ÈèÚžý‹œ—‘ÿltÈ {oL$fqÓS3Œf& Òô)3ùL˜3:5ߦ3˜ÄÒÄ€§êÃLÙÌ|O{Òl¹VÓ²›š×Öuí0ÐÛZÛnYZ»aÛu£nY®^/²Lñ\v”Ó(ñI$ ñfròü;¿¦¡ü PK5£Ô>z¬(u5—vs2008/bx_unmapped.vcprojíXmoÓ0þ ÿU|AJš®/SVP^šQ©ë¦vc|˜T9ɵ5$N°Ññòß9'i»Êx‘æ.>ß}wïizôrG¯ š°^­Q×kIHÙ¼W»¤,L>­a´ŒÚË"#ÑDf!MÎxòùàþ½òéü&…^­Pyè<}ZÃ¥×+ׇÏt] F$F%9ÍXLÒÂÚÆÁñÅÀíÕ>ÙVÛv[vGkyCíà@oi–ãêšÓÕ[ïÚ®g|Qfç„ÏAz]~Hø»õ^ùF/pEDÎ 5ÛLÕ¤< ÆØ4jJð<·x¾ertž$‘G#ÅâöÔIØŒÎ3N$n›‹vd·öqÁÏæŸ7»Ý;ÍdšI—r <á7½Zýª^¿Jü·Z¨T ¥“Àc)‘p‡êÖÆE)Ê.œÎN<S¬óá e4¦A8ãŒÓ†Ôç„ß\2Gˉ”~„“@Ÿ€\»´3…Ãd޹@íGLEòäj%×=.Š£‚R_ȸ°ËsTdŸÖÉyíœqÈmû×À¤Z.ôŸï5p2!“8·©¢þædèIŽ'˜Ä*6—àO€_ÓŸË›Ÿ²=¸ÃJa $N1‹¯Tªâ¹A³ªZR%!Ñ€Q®AA0” ɳ˜¼2óE.KB¸.½`¢Sž DÂ]˜Q–ûD—ƒQÓ0§nß¾86§Îéhr:ì›S»§—s”/”Nrôh ¾Êÿ\îÙDÐA…!€³€àØ„ Ä¬õjÍR~I8ÃŽ3„kˆ6ÒI–¦:‘„Ë,µ cÀ{5 oµW~©L]×,•*ù^…Y©¹¨þª¨Ú"¨ªê-$­¢h¥)2$Ñj8?K„ÜÛ’‘ ·øæÇÜ7†°lÕØÊÕø¯Tþ x¹H"Å sNâí~ÝøO‘¿›"WŒ1`eàe,Pòþ2%¬üb[CëWϾC¡Õ˜s´ËœÎø|:é;ãþtt:½´Æ£Áèx²êq’#áa@ø¯è~{8Ò(å}Füh[N•ªI­Í•Jÿ2ªýµTYöš Yþ*§ýç¤ßÆI;"‘ËÆ0ŽÅ]½ÔíÌ×ïwù£~‹É&9žæ*ÅÖ…J¯¤©˜þ-—f33 #“âX¤oMŸH“ˆXeÉHŒ¾Ï`byôøÚ{à9fÇkhNÇjiÍN[³ôv[3¬¦ávZ†exÞ—-ŽPÇ(›Dà5œ¹èÕV_ù¯VïØõ P†¥åÊôºÞû²º1ÜTåŽ}w·-Ôö÷‚Rc,Õ7Ç®OùäЍX(a]`l$_ ’ Ä^j.‹Ø¤,˜KîEàaóð°ÕìêZ÷Ðvµ_?кݾ­µ–g÷[Fßöì_EࢠýgÃCÙ{çx`Ò 1ƒŒ›~œša47y`à¦O™Éçœәù6ã€üÃä –&Fî›#~-Ð 4§È8µ;G9°×&õˆxnÍd,Úù7oaŸ°½wãÕ¼òæm’éü»Â<ô½8FITã§48ŸŒKŽcÝÎÓP¾Nä‹{ŒH„Ìu²ˆÿqÑ3QˆÎ1Å!ƳèÜ`{„ù‚8ð¹¼ÿ&Ý‹®ÙËäFÏ`~Qܲš¡LNœÉuÒršë9ƒ¼.u¼È]‚`‘@BT*Bùű#[ÄsÌÅ‹Ô :àÌÁB0nâ)À /„n¿ZQ'fG¿>W'Æ ?ô:ê¦ÍÁÍHíÇ/R#1z7ôAüwà’Ó‘ € \ÀÆ;wbãB:b­¯¦ó7ˆS¨9=¼ÀÞfv‡ŽBÄÃ(Ð…´óàÞj­øPu©<®q°¬ø*ÙÁô 8w‡X°ˆ;øqö«î×ÙÛÉvðŒÈ #¶Ê¥jõÐj`²Gè]æc!…wö´A‰L]¨ï ^¶ ÈØfÎ\¬VšÄQG&åxÀzåʼR™öâJÕTiÈ"Â}âR‘Ts §¥ÈVºd²¼´Œ,1¥RÿztIõéŸDÓ˜]SŸŒ¨Í1¸x–Kì ’ù]cŽØÆŒD{—zL=w¬d.zå7oaŸ°½wó\yó6-Ž þ]eù©]’£4«É[–œOÆ'‰í`CX$§SýêI#Qà'6EÔÿ¸™8„ÈPÀ‹ØÜ{Fø†:ð¹}øO¶—CsT(Œ‘ø!dñÈkiF²8I%÷E+õ]—J ö†ÌñbwJD ¨ LD<ö!‹sŶHdK6™Htȇp“, xá ÇšŠæ@¿¹@ c2žMF´±9¹¡q2‘9IЃ½) òŸƒKIÇ‚:*kâÜ‹C™8ÃZ¯¬eò[ÌtœÙï ÅaÈa£³ó(uÌ ½2„·[+9TC&k’,+y>öby0œ»S"‚˜;äi N›ž¶9ÛÅqòŒØ‹b¾ê5M{i5p9¢ì¾ð±Ê¹=Pc’0º{Š—£2·g-*µ3#é@ƉÄööǾ@I²SB ÃtID”Çnöqár.f±={ñ÷…,M10‘ìW.À‹@Lr‡iy´[âÄÒ¤Lf+wvÒft‰5e¤>ú2…Îyf¡d‚ú=)¢ª §¨ªµ5‚°ˆb? !é’ÃùU ¢Ó-ù¼šã›ç¾)ñ”­ûñT¹ÿå”(Þ®Oò ¾>òýºþ‹"4EîcÈ<8ßVÌ)lCÌÄqM^âÐÊüÃ÷Sèø1…ÓëÅl`ÜL‹ñdqÛŸŽ‡ã‹Ù®ÙE˜ï "K>¹Úàc²Üõàö·2áLÙ­›#§þ4œ9þi93k:OXó[Éí9ýÿäôH”ÞߦdI8ww»{4Þ_ô’WèÿG”6Kð|–¨¤K§*½²†ÈAüm·È%K¸¢ð¬Ã;dãaáËg›Q£Ÿc2tå‹Œî¿ Ëhkm«®í~Sihpî×Z-EíkªÙnª}Õ²¾æÈBn#k®¯tC®p´N›4®9\¶ç» wÅq2à¥Ö©ùSî>ysÝWæ…~ýRëÝ«ì;ên×Õ'Û.Ï3_#?yDéDíg'`ù;Á.áÏÁr ø Ñ0¹öeIæ ­pO¢°«u»M­SS:]ÝTv­¡t:]i©MK4Õné߃Âu„ÅCÜqÉsArQ'@NÌ‘í‡ÈõVˆ;*<²)C|%Њ.Ñ]¸‚‡$?Øp‹ ê¥üA![¡/xs2+­¶Ùoõõ–buj5¥áÔ:JGo÷•ަëuµÞúqVŽƒIcL{Ë…Øð…™Šƒóê3ÿaù?PKÉ“1@x{ûûF¨vs2008/bx_usb_uhci.vcprojíXÛnÛ8}vþC`ô¡E+_¤øÆ[èbe 8N`'Í>0(‰¶™H”JJ®³»ý÷JòEI¼Ñ¶Ø¢"CÎ 93‡sÄœ}ÜþÉšpACÖ¯6kê anèQ¶ìWo)óÂ/Biª-µúñ·×¯Î>Q‘`' ¯xxGÜøõ«Jþvý‘~5S91ß¿¯ÂÔ§­ëÞ‡FC Æ8%g3O„3OV.­îœß ­~õ¯©†®YŠnu{ʩֳ•^³ÛU4ÕèšmÍhuNµ¯Òìó%‰m.¿„ü~·Vºl·rvåãxò@ÈÑ~(ùN FM•ú•zjQ/˜œ]‡¡oSŸd£zqh†lA— Ç1,›/Q¬c'Yþ½_­r™ÄQ[”Cà!èWk³Zm:wŠ'U3¥!‹ ˆGqL^P-,œ•"_éFËÅ…m扩TôëÑe4 aNvM2¢ÇüáFà%X.°/Hîw…9vaSï\ õ½Q¸”¹èWß¼…}ÂöÞͶråÍÛ¬82øwµUdvi޲¬¦oyr>™Wœ¤¶ƒ5a±œÎôëG ÌDÄaÚ”QÿãbdáŸF C!/csKœ)ákêÀçæá?Ù^ ­Q©0FfDů•Ë(–ÅI+¹+ZE÷<*%Ø2×O¼ ($ ‚2ó$€,ÎDœ8"•…Yç^ Ñ]"DÈ-²¤à…ƒ0k*š[ãæÍÍËñôr4@s[—·S4N'r')z°?ôAþ p©XP@!sEÜ{±!çXëWµ\~‹9ƒŽ3"kâï¥Ó$Š8ltc'‘ _…ð¶k¥‡jÈäqM“e§/ÐÇ^,f€soBD˜p—<­ÁqÓã6Çs;?Lž™øqÂÁW³¡i/­.G”Ý—>R¹°§=j,æAwÏðrÐ@fNè®DͧNn$½È8‘8ÂþîØ—(I~Jd˜.ˆˆ‹àØÎ>.\ÁÅ4q¦"&Á®• &’ýÊxˆInb?-ö`CÜDú‚”ÉlÎNÖŒ.°»¢Œ”À‡.3Pêœça–êA¨ß“2ª†p˪Ú3ŒÊ(êQ I´ίBoÉgõßü;÷MˆO låØgÊåø¯ üCðvú’–ðõQì×Í_ù£)rËCæÃù¶æJù`a&kò‡Öf¾ŸBÇ)Ôœ\ϧóf2˜/ç·úd<ŸO·Í.æÀ|WYúÉ}Гå¶vü])gÊnõØü9õ§áÌñOË™yÓyšßJn¿Èéÿ'§G¢ìþ6! ¡¸ÛÛÝ£ñ¾Bÿ? ´iŠç“T%[:SéWÝ(B.ráo³AY Ðó…gÝ!Ç‹@>›œšýœ¡'¿Xdôpÿ=µÍŽÖ±›ŠÙÑ[pÿí´½Ñn+ª®©V§¥êªm-…ÜFÞ4\_éš\áx•6m\3¸l϶îšëæÀˬ3ó§Ü}ôæº3<¬Ì ýú¥Ö»S;Ú¶õí®ëO¶].žg¾F~òˆ²‰ÚÎŽÀòw‚=Ÿƒå ð¡`r Ê’ÌEáEaOëõZZ·¡t{†¥œ:S¥ÛJ[mÙÆ ¥ Ûø® ,â–Kž ’»ˆº!rŽœ Bž¿DÜUቑCâK–tî¢%<$ýAÀ†Q/äŠØ}Áë£Yiw,½­mÅî6Ê©Ûè*]££+]Í0šjS×­Fó0+‡Ád1f½åÜøÂÌÄûÁYý™ÿ°üPK÷Žd@Lò·ŠY³vs2008/bx_vga.vcprojíX[oÛ6~vþ‡ÀèC‹V¶,ßÁx…,Y™Çì¤ÙCƒ’h›‰Dj”ä:Ûú—÷v(É%ñ¬XÑ"C<:ççÂï#sþqã{gk"BÊY¯\«¨å3ÂîR¶ì•o)sùçP©iM­üñ—ׯÎ?Ñ0ÆÞ,Š]ʯ¿'NôúU){»~ H¯œªœïß—áÓ§­ëîU•‚1öAÉÞÌ×K\ÞÛ^Ü Í^ùOMmÖšÚUêf×T†¥)]£©)†ÚTv»e4Œ/Òì‹%‰,Þ>sñ°›&™VZ:¿òp´àÂåh?”ƒl^]“ú¥jbQÍ™œ_sîYÔ#騚œ-è28‚i³)r²ƒyLbÇË¿ö³•&qÄ‘IÎÅc¯\¹«Tî¸}¯¸R5U²ˆŸ¸Gä„jnâ´ ÙL7!™,.-#KL©¤_.)£>ýƒ„Æ4f×Ô'#j ,oB¼ËöB’ù]aXÆŒD;—ý˜zîˆ/e.zå7oa°¼ww[¹òæmZü»Ê*òS»$GiV“·,9ŸŒ+AÛÁš°H~Nõ«G Œ8Œ¸ŸØQÿírdâ_F C\±¹%öŒˆ5uôçæñ«l/‡æ¨P#ƒûdñÀkiD²8I%wE+é®K¥{Cæx±»kJ´%tea$b²xF±&2î’uæî0äÂ$ hƒ¤ya# Çu ÍÍAÿæÍÉx6 ÐÄæäv†ÆÉ‡ÌIÒ=Ø›B÷AþsíRêã:ÐT1VÄy÷!dâ¬×zåz&¿Å‚،Țx{é, EXDqÐÇ Ð+CxÛ¹’M5dr»&ɲ’€°“åÁ úÜ’ÇÂ!ÏkpÜô¸ÍñÜΓgÄ^ ðUSëõS³Ëe…·…Tέiß5& sØÓ~9;›;«°âQ;3’^ É‘}„½Ý¶/P’l—È0]0Ê7ÇöëÓÂå\Ìb{öFÄß²4Å@B¯\h/1ÉEì?Ë­=Ø'–¾ e2[¹½“‚Ñ%vV”‘ý¡Ë ÚçY˜…0ÈõRDµ:EU­Áƒ"ŠzCÒ-ÖçW<ŒŽCòy5Ç7ÿÎ}Sâ([1ö©r1þË)W¼]qOòÂNy¼®ý¤ÈïM‘[Æ2ö·3GÊ›³ð°&§8´r÷á -Æœã§ÌiL¯ç³q3ÌÇ“ù­>dz-ÆEï JÙè÷”#·Ð;`Øöv±%T)Aê©ù7RéC•ã–*3¬yF–ßÊi?9é¿ç¤'¢ôÚ6% " ¸ÛKÝ“ñî~—¼ì0Ù,éç³D%:Ué• @rào³A.Y îzˆÂ³ î‘#„C_>›Œ‘ý=&CWTdôpímXF»Þ¶jŠÑÖ›J£Þn)ºÚj)š^×ÌvSÓ5Ëú’㹌 4ÜZéš\áh•4lr促ëuÅq²~KR«çL}ôžº3<,È t>´;µ£0°Õ¨nW]}¶ìbñ¼pöøÁ#J?|E‰.ÈÏ2ÿËœ¼Š_ v‰x tV€.Zâ¬|DsÐ&tbL·Þí6ëUétû¦Ò°Õ†Òé úJKkZýASô­~aŒù{‡1«\ï}[õq";ÛCÆKù¢GN,íÈõ–H8<²)Cb¢%] û` I~“6¶?(`Kô¯&´Õ6õ–Þo)VGU•†£v”N¿­+z¿_ÓjºnªµÃ„“Ƙ’Î…Çm¸q¤âýà¼úÂ?[AþPKÍ¢Ô>Zѽ3dvs2008/bx_win32.vcprojíXmoÚ0þ¼IûÚ‡M[$-P¥l"/tH”VÐŽ}@BNr€·ÄÉl‡Ñ½ü÷“ƒ5Û‡½H“Ÿïξ»Ç÷`Î^¬¢ðh \Иµ+õj­rÌÊæíʘ² ~/´º~¢W^<pÿì) G2 h|Åã7àË÷ïo×· ´+¹Ê‘ýäI§^­]Ÿ>­Õ”`@"TòVÓ÷”zek}~ÓsÚ•n½éÔ솫éÃÖŽ­¦®uŒz]³uÃî× ×­7>+³kÂç »ý½ùÛÍBÙ*Ïñ9» ‰œÅ<j´ªA±ñz÷žeÏvLήã8ìÒD>¹;´c6£ó”‰Ëf¢=ÙWë8à¥óOÛÕî]¦2I¥C9óÛv¥:©V'±÷F ”j®Ôcx%îPÝY8¯C±Ò€ËÙEׯÄä‚Îuÿ‚2Ñ ìaÊ®i}êqÂoo™£åŒ„ ¿ ‰/@n\Z) ƒ~<Ç\ öÃG=¦"yæœÎÌ7ÉÈ>LbeâfgêÃLØÜ|O–ƒi4N£c5´n«VÓŽýZKkYÍŽÖ2,«®×;§V?Lþ^t‚ó0öHXt‰íàìÙw~CùPKv²y@€j‡„½vs2008/cpu.vcprojí[oÓ0€ŸAâ? ŠPÆÆU¥ Ö T*­lãaRä:'‰Á±#Û)—ÿŽ´dJË‚¸8ç¡à¸ç_¾cÇñÒGOæ)¿<¥™ÝÖíöVë2*C&ân눉P¾×7ooßÝn=y|éâ£C¦sÂ'&™|¥ä[ æÒÅ ‹Ôë“ º­Rärïúõ–ýêpiúá­-—±GR+D³¼U)>;õ»­·ïöû»ƒ›ÃÞýÁÍ;ƒÁÖ͇ÃíÛöŸ§[wnß>ô|vj¯‰ŠÁ •5õ^ªw_Ë( xl?^qb"©Rí®ªKwQÖÀµmg»å2n·Î¨LóøSUÚ…—¹ÉrÓg ¨‘ê¤Ûj·ÛÇrúöfèDK¡‘0 R1°FôLÁ%‚;K# (f ´Ýœ2'“ÀènëÊÕÃÞHhC8·Æ¯öú‘œ}|ÅŠ„0T2=ìÝÛjÏtfMèÒ솗ыaÏöw™ñôõø,e@÷ösñš¥0fSEÔÉ&±­PD¸†Eu¢5 &`º­EŸì指c».vÕ³Íw;^æß¼rµdîúôZ;1i©Wt} Ë¥–}î…î`¸¯Kù[+z¹62-t6óbÜ'†<ŠX6›èÁtjÆ(ØîžŸü’î‹Q¼Q3Æ=™fŒCeÕz\fbªA⨅!s9„åyøÕÏX±~vÃ~˜ÐFå)s¬M>ÕÇ eÛ¿™’´–Êz …)«w4ÚÛÙîýÁîÁ³N0ívöiûMÿåÑdaÀº‰©Ü¤ÛÚ© Ó²ás !(çß:þ1ÍòvF“eK´†tjÛn«Ô7ˆ¨ÕûŘZ)®Žª•̆qµRXYëOô8rîý{‘sÑà ‰ËÖþõèùM–.òö!‚.o3¿¹þzÇY$ ¨S1wRøâåB¤,ºq÷ÖY‡vè|ÞQ´BÔQò³Ÿ${Û™s&¤8 ‹‰81l¯ˆIÜ´ç:íx'ò}›–=W*-µ¾[¬¼é­«¾\3™¯Ÿ—K±Õ£¯’(¡8,ßU{ƒöT œÿ¨Eå›!&Ô•„Œýg¼³”ý§|ïRöš2àdí7àŒQ$ì5aÅLrûBö2.¹W\ €ü{Íx6GÀžÆXì5áØ^€BÆ>3ž¦ —ÔÞ#Ƶ߈Í4ÅQì=bÅ~#&³yEBör”„ì3ä¹ÄQì5à) °×€™AÀžÆÆÞ#Æ»bïã]±ßˆ)á<ˆ>‡ð›r–#`¯+z:ŸÇ€‚Xײ`æ(\øyîkKиükh\6t` EÔ>£‰!¥›£tC@c”nh<Ûï7gGK›<Š³ÏœaƒúxN!sªˆÙgÌš„@eº! qµí9jNâ€Ås#0ãÖ§÷¨³<€„{ 9ŠÑÀ¦"ö5£„&¸àö›±À“âžÆU—ß|àöšðÛ4ÃľCæ’àrÚsÂ1£„ã¹ F`ÆSAÀŒO)OyM9MñmŸ~Öxûä7àœã À—Õþ3Æ5µÿŒqAí5âŒÄLÄÈØkƶ(<À×̨AÒÞ“V %ŸáO&øNÙàÓdß!kˆS8i7‹4±÷žvÂ"ÜçldÜèldÜéldÜêô›qš"`¯ËÈ ß$â9eéæ;à •3¤ì=eüº@V!{YuæÁ9¬Bß¡£xí(1î‰62î‰62î‰úYáÑ@ßÏpOÔkÀ†èw8Š=‡‚ºìÄui¾é¶’N’ed>ï$i‡‰E+6s’1ÚNÎ5­L%Mô9uiÑçUÎr÷9¿v8­W2 ÛIÍ9­a MËŒT5Œœz‰üï±hý»,Íܯa©zùn=Nl§V5 dæšSuùvÙ:„6uÜ„“'AÄI-‡u§’zO'êèÏléuÖM5´çõZÎÒ0`ÂÔ5‘EYeâgQ§ÌÖEò—SÂu™]]<ºuÈtNøÄä!“¯”| ÔØü/PKšp?Å”_Á«…vs2008/disasm.vcprojíYÝoÚ0î¤ýU´‡M”–µÛ”²©è(­ø({@BNr€·ÄŽl‡Á>þ÷cHÚµ%tÕ¦jíŸïûÎ÷sÄá‡ylÏ@HÊYÅÚ-–¬m`÷)›T¬e>ÿ* »{û{Ö‡÷OŸžS“ «bŸò3Á?ƒ§ž>ÙZ>õT,òí¼|iáÖùJõ»W¥’&´IˆL>•D†V&{ÜoÖ*Ö÷ƒƒò»½úþ~a¿\u ¯ß¼.Þ¾ÙÝ+ìï×ÞÖœ7µƒÝzé§ë1Õ¨í+_R3‰÷ø9< ˆsJ½Ê–zaœÐá•÷,MØI$v.‰ö84i6//ÎÆt ¢ÐlBúvÁN ~dö¶NcŪF†ÎÅ¢b‡Å⻟ Â0¶&S Bð)QË|ɼ©Å땚)ªÀÇdG Ô¢;P²b={~î4™T$Pý‹sgYŒI(9ìGA|hž;¥âLF¨Bµ} §ã“†ƒY7„£^ë„2Òo NÌz4„u‹¾$thL‚ÔÝ)ÄÃøº *Ö2/Õ˜~‹Ot¢µ{˜íØpE/<{n*¯3û¢8U¡‘K `J†Oiæu@ÈÖgÀ”Þ6ü;7 8±TK;i«Îˆ¤aµ`A‹²/©xæ¡g2åâƒÐ­wõˆ ÍÄ*FÞt•)!D ¢E¥B­-î™Ä^•]¥ßÕgëý©;O\¨{ªŠdÍŒ%]#0 ‚¡õ$¾¬¦Ý8ŠHÙUD¨8ªÆ@˜¸s;Œ02¿’ǃ‹m”'zL^#˜Xr98tbØz¥r9ϪÔÝød›¡„­˜Ó9¼¾äuïžÕ#íêF¥†ø›°V¥—²æ;¸yÀ®ôòL7æ6ññŒKuó>ܹZëa´n<Ù D}Íš ¡ë#€>èí´ô×ñq”ácŠ•¸S;to@¿r>¬em[PË$×@ZÆ‘hûál+M¦oï‰ÃääžÁÝèþÁ]’ÿ‡vI¸÷ê~#É„Ö1`HÃòÛ:}Mˆ ÙMºq;a1¦ KÅò¢Èölo>·…gû0¶…ÍýÀ¦ø™FŸm—¨ (`Œ,Ç èÛ ÎˆšêQ¶Ì›þùàqŠžÉ ^I_Áð5/Ùh–ÕœI|u ÎŸÆ†mÍ 5Y¡±WÊ4»¯Ü=ÎÙ¸U L#ùØ´HÌGÀC­¿\0EæåÿËŸ<*7\5Ì;ÅuW)Þ("{ŠWihSlz±pç#s3K¾‹«’?†&E\ôíÎzð'Õ±6I†,“Ç〻$†œ-w®ùûé¿PKd@0Ú:s±—;vs2008/fpu.vcprojí[ßoÚH~¦Rÿ‡ÈêÃU-µr¸ ¤H„ É= ¡Å`{×Ú]SèÝýï7þÁφBÊÃõ?Dñ®gfwæûv>[q®?Í]çlBRÎÊZ!w®³¸MÙ¤¬=Pfó¯2[¸¸ºÐ>ýñúÕõ=•>qLåÛ”wÿ–zý*_õ”µÈäÌx÷NÃ[÷ËÐߟŸmâ¢ÑØóµµãM¿Y+k]•J£V¬g«•«b¶X/ýž­\}(e«ÕóB±b|,– Å·P ¡¾rñ¸Z#\·™¹î8D¹pe0ZƒA¼Ìíò"°ÏäCü–Ëus§AˆFùí¡ÁÙ˜N|A./±5·±N Fþäïõj™;_y¾ªQ‰s±(k¹A.7à£/Y;0ŒšLpÁ¦DÁÓ­…#ŠË STeö@¨…9P²¬½ùíÞh2©ˆã`ð·÷FŒC ÆÄw”ô½‰ 64wïÒyn&= !£°} wãÛ†×;“©ôZ·”Q—~it}Ö£.´èH±èK2 à&Ž„x»S"ˆ…Ù™ ÊZ\“ªO»Å'A‰ƒíaúÁÆËùì›ß"̃š¾ÍM•ù…¥À ¯âš Aè[ŸSÁíÈ>¿×Áð¥ânèsŒùŸ·­Qä`á¹8ÆçF&ˆµË=_<Ë÷¶Yk•FËஇU܈š¹óTNHh™ŠmÓ`†8Mf9¾½â¤H.÷©F‘$Âw±†©ü‘|Ÿ‹~Ç!°ÊÈ ¤ä¹ƒ®fûòBÖêÕþ>l5«z;¾Æ;µ»SïTº•ö]³¦‡ó7ÍöÞ¾VL³~[mÕ»z߬£mïóÐèô‡fó6^Ù¥Öì*k—ëXQâög@抈IÛçe€]'çYÓe¤w„¥jQ©°ßµ¸—hÇmYÆQpFž ¼ÚÇsą̃ i̶y>6 ‚ë œu*¦ïyKj*"”ïU Cž”5Ä!>A™°¥4YЬ 7 ìÞYDG» ’û‚全ßu¿Ï~DøÇV6_`¬Âùåå¡Õ0d‹²Ç£OoÄJØ&ëÃ>»—[ðýëV‚]Õ/jXüG8Æ´*­mÓ#q ב´­Ú˜Ü;f{.ÕþÖzß’£KcÀcrœ8ŠÈø8yÜ2N2Èçä²7™C4|fóõ¹GXü”|Š‚>C?Ûúù\½Ô‡F·74ëF¿[¢åC¥ÛF'sÙR”@åé` ÂýV²«°13uFP+—Õ5+h~»î‡„8>™Ï—â¥ãÄxÇæ°ï8ü¤ ÿ2‚ÛþõwïäKîf¶ÿ©èîLE¯­]ƒÀ·ûåKíÎxõ~^¢mHµrñ,4‰–ŽLÊšåyº¥[ó¹.,݆±.tn;:ÅŸ©÷Eµ¥DA„¸Ñ¾pÓtˆšÝ2(Ú`|1w 9+®\ìy}ÿ±÷{å¸YËp¨¯Ìöž¾¥E~¹ëüwÛ>.Ÿ'ž‹~ñŒ¢GB B¤'a—¥'cn q²!öS€ðâÕ4…9é0[.Ÿ¥('eÜ-| ™T)ÌI‡ÙáÄJÜHz¤µK¥•¢œt”• L¦0'fI™ÅS“ ò¹˜§'b;‹á$#,ùXñ[e÷™õˆõ˜"þ2—X”8ô[újõ2Oa~0J)Ð/è¬ë;ĶS´_Úóç)Òÿc¤ÃK"4v?/Œ>~êó©>õ<}:ŸëSW§,Îâ0{FÜšÊÜt‹1Ç2Ï SùI瀶@ î ¿žæxA-Oˆþ_º'F×?1òHñcÈ…TpJ*áûüÏ» ˜Dv#Lí³Éóh:ú¶öÆá#âÄßÝ®×ù'þ¡çÿPKšp?—fg±”vs2008/gui.vcprojíYmoÓ0þ ÿE|A_¶¥­i;*uÝÔ—••*7¹6f‰ÙN×òòß±4YÙJ2ŠŒ~È”\îÎw÷œï‰»êû¥ï=^㘒šqP,ØÔÁd^3F˜8ôŠ_ïß=zX½À<1'vÝœX½Á¤ß´†½æ¤{6÷ºíîI?vÔL¦s™”žOrQˆßȆiÃ%-õ IÐÔKòëÀ¼&—‰y¡•ÌùȦzðæ^˹U lw]ÎÁ—îYs!]v¨­Ë{‹á„©Úa©óÒ5R •ûÎWU—b¥¬€Ýît„‘«ëäRdûa0à¼/aPG„‹’Îì3DМp2®7S–ém6Y]ákYrô„ d–+•¬Õ¤K…fîýµF$UާñOðöðt÷’«8sÍ”†,ÿ%äQ­s;QÍ 0o¶Sng­ÛZZ4Èà9åbû®–6Hëç4Ú€i8ÏG¢ŽRͤÐTuO {½;–sòcÂ…·e>~œ¤ü˜p¥|Ó8õ·°_%›ÖÒþ¿;©i³­”–hä#´T}7:{ GD›¨oxpKßH"ùËènò÷Ñ®ÿBv:×?Ou?ˆ¸–õ` ˆ½>vþðœœ@õ­v ûºk•héH¥fØA`Ú¦½\šÌ6˜™Ì¤Žgby¹Á'sŠÄ (ñTOƶ€s$\5ÊTÑÆ@܉3m]»Ô¬¤ìò¹×¦ùÚæ&ùo?E§¦)#<{\kµí›7шqÕyß<_FzZýCùÜàKXù(Øc|Ÿ1¤tÁö0ßg˜9ö1ÀfÈÞ#}¯‘°¶v±Çù>ã|¥²šÄŸqʸÁÔwvç`äÑ}ßÜÿ¾Ñ¬ïxÛ?ÿã[lË9%úâ¶sŠkºA`ºòœâú&&Þ¯œJÜ]%¿h­݉þfxÈþfNìÆÔ‰›]h`'W5]ð¢û[FKâe§¾ÝÙN(GçÇb®oO<:EÄéCµtËÓ¥ü;PKšp?d·Ý„©vs2008/iodev.vcprojíX[oÚ0~î¤ý‡*Úæ hK7m l‚¥—²$d’xKìÈv(Ýå¿ïÄI/RM“º­‘âãïø\}¾@åÃ*ð÷— $å¬j¬}`.÷(›W­e¿”…ã×GÖ‡÷OŸT.¨ŒˆßW‘Gù¹àŸÁUOŸì%oƒ«ª–ì;/_Z¸u±>úÝ«ƒƒXÐ%‚(÷`ieª'Ãv£j};z]+;­z¹ðöÝq¹pÜxçÞ×›…F­Ü,;okLJ‡¯Äj"æ Z»äâKjE›xOåÜ'jÆE ãU¶ŒÚ]ùÈŠ%­Qº¡Rpî·¨ÒlÞ\:œÍè<D¡Y-º%»f§> ß3{{g‘ #Õ CçâªjÇÅâ˜O?„X›)x”(Ø ¾aÞ”âx}ÌUàa²C꪿P²j={~á´™TÄ÷ñøNRÌHä+9†sAeЊ˜Ë›«°d$€šçÑx‹ømæú‘—¶"‰ÍX|…ÝH™T" €©±TÑT&ª˜~l¤ä›Š2}jÚÝò‘Ým4ëÃ{Òi×í‰ÓLúMgØkNºg“Q­×mwOúÉA}%p"c,z0¡-Hv°ÏTÖgi'í5™úiXX‚ß¡ìKªžyèšLyx tëݹbc=°Š¡»X'EJЀèP©ðÐwM^类³?¯Ö†ãSo8^¸ n©:Šc0Vt‹Âˆ†ÖuxYIûQ ²¯ˆPQX'Œ0aïl0ÂȼH ®wÑ.Õ :[ûÀt@‚rpæD°óÊå]Öðȸž¹/¶iJXNÆðÖŠûtúûI­Åžæ' ,ÀÈ­K7…ît0¼Séî²ÜZ9<Ìãâ9—jóô­”n0ÖvmÀ4šçcP/†æâO}dÏGö¼?{üqrœdä˜%î4ÎFý ÔWÎÇi¦íïÉh™â&>+¥ˆR^63ðßä²==Ú,þr×·ô ²ÈãºÉÃã:ÿÿ†ét´çn‰¤–õ`˜ Ò@n­ÓßžúU¸ÆŽ}Ý‹ûbLHÕrÃÐvmwµ²…k{0³…Í=ߦø,ÂÏö”¨k`Œ$³|ôm çD-â9fÒ6Ƈ¢GEWg/U4šwÈ{ËOàL5Ë莼{Üjض;hY11ÍwÏ‘:QÿTFÙ¨u™€G‰‚\åkáM/^nݬ@P‚‚P—À’ ëÉÓ §Ë¤"¾îŸ]8I7Z° ‘¯ät.ñ #xpἪ”×2DÒ¸K8[œvDÝŽG½SÊh@¿‚tÑzt.ˆ¸K²Ä„ÄOÓ]A\¬oªa%¸4#ê{=¾ŒŽÓCâĦ[yéÉSÓùÙgå• Œn€ižRäã‚@Û¶×ÀT|môn5p"©x mЍ<íµˆ"'À碈ÍæCkê½¹¼“íi·Õ+TFÏáAˆ(f^qêB7‡(ýªÔi—ù”A'bn,ooBÂ’m({¯ˆße®yé(R8Œå8”I%¢AžJÍebŠðãÀ¸ %8T”iGh5éökU»ßj7Ç'ö¬×mÚ3g0š ÛÎxОõÏf“ãA¿Û?&ކJàJ:ÇZôfÂXÜàœ©lÎÒIÚk32÷Ó²z°¿GÙçÔ<ËÐ5Hy€x ôèÝxŦfc•CwµEEJ0‚èQ©Ðk»Ø›¶[øçñ»u‹ÿ4Žo\ÏTű2¶t‡Á„†Ñu}YO‡Q D}¨ˆPQØ$Œ0uçNad Þ$„ WÇ(Ïôw6yƒ`F ÑrpéDpô*µZ^4t7´ð›m&„–)'{xwË}:ÿsTãT -”và3QmJ7UÍO°xÁséæ…îlÉñœKuû®\#­Ý4Ú‚y´,F¢^¬šK¡™ê>èÝ ´ò×ùq–ñcÊ•xÓ:› oa¿Z>­ecWRË,wQšÑ(LhFýélO/‡.‹¿½ë„;ú€DrÏènvÿèNãÿÿ.÷^PÝ/"©eX€æ‚4*¿<§¿@õQ¸BC=ûZÅ„6* Ë CÛµÝÍÆ®íÁÂ6÷|›âg~²çD]a$Y/àcnk8'j¯²·-|®F/54–7ø{ÇáÌ4C4g ço\­¶ë-4Y3扫H¯¨sQ¼ÍTº3*·l óõàw[c…Ë!´W¸5VM™_tG̹»’åíWŠ» ž«KÉ7Î_N©€±Ôǟω/8{¨üæ_O”ÿPK’iÒ>pÚbƒvs2008/niclist.vcprojíXmoÓ0þ ÿE|A»®e¼(+¨KÛQ©ë¦v|˜49Î51$vd;£ãå¿sŽÓ„Òu H ø-9ßùÎÏ=vžfÿõ"‰ï_TLð®³Ûl9÷S0v·Œâ£jì¶÷ÚÎëW÷îîŸ3•‘x¦³€‰)ÞÕ÷îÞ)îN¯Sè:Öå¾÷ø±ƒCçË©_>iµŒaBtâŒÆLi§ ><õ»ÎgïàùpÐï ­Ö^§ñtÐÙx±»·×xÞê·ž=Ý{î=k·¾š°S"CÐC‰Ó}òC™'Oò ¯ý“˜è¹‰2OÕ£y°U˜õuÚŽ1ìä;+!û§BÄCƒ²ƒ«žàsf’hLkS¬Ú¾ËÓ? ¿TÙîg:ÍtŸI ZÈë®Ó¼h6/„ÿ¾Wë4âd#¶¸®$¶mØ]Nd„9©¯g€V]çÁÃsoÄ•&qŒ“?:÷Š>ôaN²X«‹³4”$€¡ɹ÷¬Õ¼R)N¡ì´g ŽçGCñ¶†Þéøˆq–°O ¼iÆOYcæK"¯Ï ± 9‰åFDªAÎ@w“ƒŒÅÁX„bS.ßv±´7<´=7˜>jF:±q9ô¶YxWbnyìà ¸6ÃÖgc€—)-’<¦Žû»£qŸhrx!ëļòŠQ@¸×?{4ê+¿;Øæ%ÂÖc•ÅkêØ/"ÞöS|mÀV<ÆžHRt¯ÊCê¦Út™h»Û +bì  ”È dB¾-p‹&¶{Ùœº—Þñdv<A9aH<ß@Þu´Ì : ŠQ¤æ/ú§êcÆ\± ™^Õ@m½A¹ÒͰ¤4*âzJAâã*Çhg< š¯n-t‰€oöÉ“—•ˆP’İâÝßÉM^¸‚¸Zæ,KS‰€Î4‘:Kç W@Ê•7V^ð0¿é:O·2‰pB0%2Ia¥Ë[B7Çlæ€í~áåe±Î¤9 Zζl8å˜ñµw°q®j*Ú[‰‹%ž&zÄ©„ÓlE»v+Š ?¶Ä:­ÓÂ' n§gà—ÉýÙµÒTLŸsÔ†^½ 0ÅUÃ&Á`43 „ˆÞênµçè¡ã¦Û`ídŒ¹±Ø”®u|öÑýÔq=P´tÝÚ‘ú÷Ý–y¸ðDZ§Ä^š¢asVo¥7¿œöwV^è·‹‹)Ä@Ô“Ò:וó‰ñ_bX‰±F?#2:…uÄcÆa˜qjìƒEJxñ³¥ž ™¬ª¼™ž^ÎÞÙtp99¾|Û›NF“ÃÙòˆÑ’ñð‹ÂåѲ.@ªcuÀ‰—õå¯ssp–áµtJ…m}¥²¼Y«T>5ÕJðËzå/Ó#“¿LðÖQ$»[À®%6ª”ÿåÆo•Êÿ¤àøÁ¤rÛæ SPÖå‡çòëH~«A~'Sfù6½Ÿ»ØÔÖ¥ëÐ4u©K WR7€¹+]Ä.Ã+Jß»>Ñ+oa3CÁKˆ±¶+8!:ê:ˆyÂ-Á¶PÛ°eÜš†Úø‰¦ ¬ÐÜòÚºõÌ)=аž*UIÙ6t­ÈÕWð¯­ßT³}ß@ûF¼‰&‘!Q"¤I”¸Œ5×™s j#ù.ͤë'©Ä!R°—v}Æ]*7ds÷}âùŸ›³ÚûbÆÂ'±²æêa熧hÿPKšp?†ð5¦dÜvs2008/stubs.vcprojíXKoÚ@>§RÿCdõЪ…H[!C«` E"$âz@B‹=À¶ö®µ»¦¤ÿÞñ®ÁÍì¨=¤jHöì¼çÛù€Úûuà®@HÊYÝ:.–¬C`.÷([Ô­1eÿ" Çå×eëý»§OjWTFĨȣüRðOધO’§áuu˨:/_Zxtµq]}U*Å‚ PIªh&­ÔôlÔiÖ­oãÒ[§úúuá¤R>)œT«¥B£ñ¶Zxã4œê±ó¦y\>ý› ‰X€j tö…‹ÏÛ(:Ä;üÔ.}¢æ\2~K_ヮ®R¶bÁ‘¶8ºaRrî·©ÒÞ|u8›ÓE$ˆÂ°ZtKöKœ>ø@$|Oã\D*ŒT“ ,‹ëºUœ‹>ûTFÙ¨u˜€G‰‚LåáÍ(N6n– ¨›‚P׃%€’uëÙó+§Ã¤"¾î_\9É4š0'‘¯äd.ñ -xpå¼)W2DÒ¸I¸˜Ÿ·ìºœ»ç”Ñ€~éô#6¤téLq=’d ͉¿MwIq±¾¨º•ô¥QßëòEÜè8=l@œØd#/<{n&wöEq©c§`F†OÛÎǶm­€©øØèí4p"©x mò¨<ï6‰"gÀ@œN›1Ì VÔl÷úúA¶çf7W]‡!v1õЍ U<¢ôU©$Òó)ƒvÄÜXÞZ‡„%Ë Q8õ<¿Ã\?ò¶P¤ ŒÅD [àpAJ.@”i#Ôwz•²Ýk¶£3{Úí4ì©ÓN-gÔoM{Óñi¿×é G%pû\bÞz )Ar‚˜R)¦¶¨9h12ó·%ta~—²Ï[ó4C×tÅûk¡avç:Môr*†îrÓ)!À¢K¥B§]îšÞ5Ýtz_£î·Ùp¼\A ŸŠceœÞƒ1 £ëòÒñ ¢0 å@¡¢°AaÊÎad^$„ )b²ñuŸM -÷K$QVªT²¢¡Ëxž¹/±%,UNVîÞ‰ûtöûM=3͵:š8€ÏGµ!ÝT5+ÁüõΤ›¹½vx˜'ÅK.ÕîM[;ºÁNûù² ³h‘-½X5“+SÕÿLùŸ)Δ¥œDø ¡F$" €)sÉ&ùØqš²ã–)ñ¤y1ìà¾J6©¥¸ ¥¥†ûÍhä¦3£þ›dv —C‡Å_ÓuÂmý€4òÈÈnúøÈN÷ÿŸ¡:]íc º["©e}˜ƒ†À1*·Þ·?4õ£ñ =4µŠ mTê–†¶k»ëµ-\Ûƒ¹-lîù6ÅÏ2üdψú…Ld·€¹­à’¨eݺo‹¥‚¢kziÜlüÜáò=¿~SÓ´¿9{ûjµ}7Òh¤£Å¦ßI<_EzýEõ˜ƒž+; eä>h-A¡½Dh-›2ÿOiÃE{³4bs+Î|>#¾4âô¥vtÏ¿R(ÿ PKš“1@N — w—vs2008/bx_netmod.vcprojíYmoÛ6þìýÑ-ZÙ²¿Añ ½X™Çì¤Ù%Ñ6‰T)Êq¶õ¿ï(ɯ‰-Ê "uwäÝ=¼ç˜œ}^þÉóˆ0Ú)VJjñS—y„Î;ÅB=v)•j½ZüüËÛ7g_H#,b°KÎn±+Þ¾)doW!îS‘óãÇ"|ú²6Ýþ¤ªrb€rVSŠEÀ¼âVýüºguŠ¨Í¶¡ÖlCQͺ¡œÝšÒnÛu¥¡7L£Ûj׊þMªÒZ"÷Ðäâs,lŸï¿Ûì"Ù8R8»ô‘˜1Dr´ÊA¶Gð¾V•ò…r¢QÞS9»bÌ·‰ÓQyh2:#ó˜#ËfKìÍí¬ca'žÿ¹]­0ŒE ‹p ãbiR*M˜s«xR4êQy€=‚~Ftoá4IÙJ×Î.l3 L¡ _õ/%ùGæ(¦W$À}âpÄ®#4Íò#œÙ] Ž\ØÆ‹I#&¾×gs‹NñÝ{Ø'lïÃd=¯¼{Ÿ&G:ÿ¡´Aª—Ä(jò–ç‹yÉq¢Û]b*äçT¾|TÁŒ#Á‚D'øo} tŽ)†1žGç;cÌ—ÄÅ€ÝÕÃ?Ò½èYý\nôM„Å«…a(dr’Ln’VÐ=Èä÷¨ëÇÞG)$4@¡‘àqQœD"v¢dŽyx™Y@‡œ¹8Š·ð `€BoP«jS«k\ŸkSs8û]m ÓÖðf¬ ’™‘=Èú þ{p)(".€ \Àæ»wÑÖ…l:ÃZ§XËæo§P‹úx‰ýíì8C ÄEˆB:Epo½Vr¨zT×$XvòîÙô 8÷F8b1wñãW=®s<¶ÓÝà™±/b¶*j­öÜj`²Oè]îc!…÷ö´E…CL=¨û)^v ÈÄaî"*ùÄÉ”¤ÇGÈßû)ÉN †“ŽÄ>8Ö_·gb;ã‡Hà`“ÈÂGÉzå¼0ø$7±ý,vw…ÝXÚ‚Éhí´] wA(Î]F ×9ÏÜÌUƒ,¿ÃyDÈÍ+j¯LæÔÃ’ÌH>œ_²H/Égå=¾ù{îaCÚò±O…óñßžðweÀ›ó%/Ì¡ûدוWŠüÞ¹fŒõá|Û1uå|w"íæä9-M>ý{ R¨9ºšŽ»æõ¨; §7úhМ×ÅNp`¾Kð,iÆwÊà!Y®kp—"Çß8™p¦¬V‡ê/äÔ†3?,gfEçk¾”Ü^Éé¿'§ƒ©ôþ6Â3Ì!¹ëÛÝÁxsÑK^¡þïPÚ8ÁóI"’.ŠtŠnj®æÂÏj¥yx¦1Ï×<‹ðVsÐPÈg•Q%_cÜódÇ"½‡»ñ©m6kM»¢˜M½®œÖš EW ¥ª×ªV³^Õ«¶ým,ä6²¢áúJ–ø‰EؤpMàÎ,oÈ,Sû~Éu3ð¥Rùûèíu£¸›gjösåw#v´&¬%Êë]—m;Ÿ?Ot$?¸G釗ä{ ƒ×|ÿ<ù¾—>¾&üçHxúÇÐ×lÿ³¼Bëp¤Óø#ó§:´¡¶€6ch„B—A]myG‹v­Ý®×ZªÒj–rꨧJ«Õ5”FµnÝzµkØÆ ‹ ‡‹=æwr}AxÊMîjÄešsÍ BÍóçw«ðÍ!TãóH›“™vÎáÁÉ/ ®8+ üžÉ_ZHçÚ=ZK£ié Ýh(vKU•SWm)-£©+­šaTª]·ÔÊn\vI}LÆsŸ9ÈÏšÉíà¬üÄ?T`þ/PKPd@ƒMTZð6vs2008/cpudb.vcprojí[ëoâ8ÿÌJû?Th?Üj—G¡ÐV)·*zè(­ û€d™d Þ&vä8-Üã¿Éƒg¡°¥Òí•|¨6vfÆžùçÛìÙ·‘c<‚ô˜à•ôa6Ÿ>n“ña%}ϸ)ž¼Ìa¡THûõㇳ;æùÔî*ßdâZŠï`¨RñÓÍØ…J:9п|Iã«»‰éÓ¯ù|ÐѦ ®oöÓ3Õ‹Ûf­’þ«T,œ”NòµÌqñ¤˜9:×õÌiI?ÌœJ'¥|¾Z®—Êÿj7TA5${òa:J8N4uvmS5Òñ‚Ö¬4â9 wÅB ŸÊ…¹•³!ì³!j固à6ô%U8l<ÄBßÜ85èûÿg£¥®|åúªÆ$:.丒Îö²ÙžèϘh$Ôä ¤&£ 6ˆ. p41bd L ³ R»€ò*éO¿ÜéMî)jÛhüóãPƒõmåõnÝ¡¤&4¤pîôr>ûè¹h‹ÌÞzp5¸lèq¼S©ó›Ö%ãÌa‚§w|~Ãh±¾¤r|ëÑ!Nh@mâéZTR½ë‚ª¤ã˜T}f›-1 BLÝ&Ö›ôg>ýaÄôsÖRN¤†>+|Šc8¡ný¸ ^Gò¹µ ºï)á„:ÛˆÿqÙªQE/€^Èmtî¡ßùÈ ÀpÆ?¤{Ù¬µ¶r£¥ ÇÅ(ÎYM]¹*'L)h©sÓdAµ›Ü°}sšg 0E0Ͼâ®Ôð_†Ù"}ƒÙó”ß÷z±Œ3f†ž'$ffA¸$py5ÛÅ‚Fjõêí…FZͪ֎ŸñMíê¾ÀtQ³t©¤‹3ÃFä‰ù`*Ê(5@/,$Y×°&>y8}ô¾Å<…E¬%ŒØë%ÅIdúAÚ¯4=‡À¥à`W©hëÕâ÷Tò`\x{æL×w]‰1ê**•ïV)Gè+iŒh¼(Ra•hò þ„n„X’7&å¸ÂÌx—‘ÃÒùB&ج¿mÈ×|Ìs«"PÃð?À6¢UÏXÝ"'Ö{›‹¼í{Ʀq#]¸ÛLðZxj}Å<Ë-°ÌËŒ×p©lÇy2ÞŽõ„ÞKxïGxoRŒ›Üf>7‚þúÈ¥<þüÝ’_âÅíh±=G‹DïÜn]¿íÔIûŠÜŸwÚÍöÅ„»J"\£Oá'ù\uX&Î8£RuN‘'î…DÔ³eõMü/µ×0ìDõ%Ž]’Ù̲K ¯äÙŸ†GÛ?."þþ™tÑßÿ”K—º¢Mf q7>Ù‚.µ§»ÑðyeŽ»a>„"ÑБH°óv5C3F#Mš Mj´5†–û]ëSµ@0…¸ÜnÙ#\Se…»ƒ †¡ëa-xùˆ6}²¨ã€Ìq4cC‘¥ç k7ÉSÅùøn(÷›*÷TlíªœHä&³Î=›övþ¬øúÉ=Š^¼ vLräöò}€\8„Žó ØïlCH`%B¥¤Ü¤6§TH€ßàí1Gc`›ä¸”à¾'¸ˆ \Ž9Q§å|‚úž NL_U8ÊçÉ'i%¸ïîì˜xHîcÒ—Ì)àšÿ=ÿýƒïȃM|‘ ½hÉUe Ø{ö NC ¡1Ð_)8)Ë ô{ý³±®ƒRÉyÜ>\1ß!Ž3Jà~ÿpSÇ$eR †…3OnYös×.œQ‘œ”Ky¢„ÍÊàß?ðÊ—,¼^Sc;YêÿkÄÃG2j<»­~³ê¶ÞÒ,×Õ¬ÑH³ñØ‹W]ÒÎÝÍ[ ™´ûÅïîö&·Š¯³Ô†å½v!p;»°ú®ì¬.^ļ…Ñ¥Sþ·0ùìùMœ_y>¹“åÝ´™¹³_sGo;›šžëìliÍ¡ÁØÛ‘îlmn»³sÑYþ–Þyr+?Ôvµºô°ÖÜ<ÅDÝѯÄ.lѧvü ²Yã,·â¿raÿ¿PKq/@8mRÂvs2008/bx_e1000.vcprojíXÛnÛ8}vþC`ô¡E+_ãKÀx ]¬¬Çì¤Ù%Ñ6‰T)Êuv·ÿ¾CIv,'Þ¨]lчQ g†œ™Ã9¢Ï?nÿdMDD9ë•ë•Zù„0—{”-{å[Ê<þ%ÒêV£üñ·×¯Î?Ñ(ÆþTÆåW‚ßW¾~UÊÞ®BÒ+§*'æû÷e˜ú´u}ö¡VS‚@ÉÙÌI½–J2ë‹›Õ+ÿÕi×Û5ÛhkvÛhj§-«£ÙFCëÛ-³Õm÷»ÝºñU™M8—ÊYb÷Àã5K"m³_¸¸ßí!™„0JçW>– .‚H‡jíbo6”~©šXTs&çלû6õI:ªæ‡&g ºŒ–°l¶DN¶·ŽEœxù÷ãj¥q,ÃXZT@N¸xè•+³JeÆ;ÍSª©Ò€I"âQ,É ª¹…Óe+ÝDd¼¸´Í,1¥’~=¼¤ŒôO™“˜]Ó€ ©#°x¸‰ð,ØHæw…vaS"w.˜úÞ/U.zå7oaŸ°½w³­\{ó6-Ž þ]e%ƒÔ.ÉQšÕä-KÎ'óJĶ¿&LªéT¿zÔÀŒ#ɃĦˆú—C K|A qQÄæ–8S"ÖÔ%ÝÍÃ7Ù^¬a¡0†&BÈâž×Ò8”ª8I%wE+éžG•ûæú±·%Q ¨ ,’" ‹³HÆN”ȸGÖ™Ht(¸K¢ˆ ‹, xá FÍš[}ãæÍÍñh:öÑÄÖøvŠFÉDæ$Aö'€>È.%GÔPAÄ\÷>z !gXë•›™ü hHÖÄ”Nã0°Ñ©ÄBÆ¡ W†ð¶k%‡jÀÔqM’e'/Ðß^,f€soB" —<­ÁqÓã6Çs;ßOžû2à«^k6_Z \)»/|,”rnO¨±HH˜]?ÅË^™9Ü]EŸ:™‘ò Dáû»c_ $Ù)!aº ‘̃c;{X¸œ‹iìL"I‚]!K ¥ú•ð"“ÚÄã´:Úý qcå R¦²•;;i3ºÄîŠ2RºÊ@¡sž…Y¨Y ~OЍ‘[TÕÞ˜<,¢¨‡!0$]Ðb8¿â‘<Þ’Ï«9¾ùw@ÙŠ±ŸH•‹ñ_Nù‡2àíŠûŠ–ðõ‘ï×õ_ù£)rËæÃù¶cæ*ybí×ä%­Ì> FÓm³“˜ï "K>Å÷Úà!Yn{pŸaÇß™p¦êV‡æßÉ©? gŽ~ZÎÌšÎÖü^rûENÿ?9ˆÒûÛ„,ˆ€ânowãÝE/y…þ¿GiÓÏ'‰JºtªÒ+»aˆ\äÂßfƒ<²@Üó…gÞ!K„£@=›Œšý“§¾XTôp5>µÍN³c×5³£·´Óf§­éµv[kè͆Õi5ô†mÍ‘…ÚFÖ4\_éš\a¹J›4®#RÝgÉÕ¹âºòRóÔþ)y½ºî ÷KóBÃ~©÷îÔŽ6„­Fu»ëê“m‹ç™Ï‘Ÿ<¢t"Ãv ´#¸ü`ˆçp¹†h \ˆ2À$sÑ&òŽÂð¬yvÖjvkZ÷̰´S§vªu»}Ck7Z¶Ño5ú†mü'®r(,ã–Mž‹R¸ˆº¹±@N"Ï_"á6à‘È¡ ‰e„–tîÂ%<$ù‡€7Â^¨(dKô¯¦¥Ý±ô¶®~¸êÖjÚ©[ëj]££kݦaÔu]·jõý´ì“Ƙv— Ÿ;ð™ŠçÕg~{ù?PKvd@º!*-_Ëvs2008/bx_svga_cirrus.vcprojíX[oÛ6~vþ‡ÀèC‹V¶,ß¡x…®™Çì¤ÙCƒ’h›‰$ª¤ä:Ûú—÷v(É%ñ¬XÑ"C<:ççÂï#sþqøgkÌ8¡á Ú¨ÉÕ3ºÔ#árP½%¡G¿p©¡´•êÇ_^¿:ÿDx‚üYœx„^1zÝøõ«JþvýáA5S93Þ¿¯Â§O[×ý²,c€’³™óõÍ]ÂX«{7CsPý£­õåŽÕ·%ÙÐd©eæÈ=©eõÛ¶©[ŠÑo|f׈-ql3ðú…²‡Ýté\°âÊù•âe£ýP òÅ@˜MEèWê©E½`r~M©og£zqhÐpA– C1L›OQÌcb'Yþ¹Ÿ­2Iâ(‰M pÊÕÚ]­vG{ɪ™Ò0Œ1 °GPŒO¨&Ϊ‘ÏtÃñdqiyb*íztIBß17¦IxM<"Cìñ†£%X.Ïqîw…ra3ï\ê ñ½]Š\ ªoÞÂ:ayïî¶réÍÛ¬8"øwµUdvi޲¬¦oyr>W §¶Ö‡±øœé× iÚ”Qÿírd¢]àC†(+cs‹fkâbèÏÍ㿲½š£RaŒ Dů•I‹â¤•Ü­¢yäC×O¼]C̳–P¡+HÈc–Å;'OeÔÃëÜ $:bÔÅœSfâ´AÚ¼°†ã¦¢ÎMK¿¹PçÆd<›Œ,ubsr;SÇé‡ÜIÚ=ÈŸB÷Aþ íRÑ'.4„€vø>„\œ÷Ú ÚÌå·ˆ…:#¼Æþ^:K¢ˆÁBg1bqé(„ ªÞv®tS C±]ÓdÙé @ÙÉò úÜ›bNæâç58nzÜæxnç‡É3?NøjÈÍæ©ÙÀ刄¥·…P.¬iß5&ŽpèÀgýr wuW¼æ'7^ É}„üݶ/Q’|—`È0Y`›cûõiá .f‰3{ä1v…¬L‘À+Ú CLbûÏbk[ì&¤Ld«°w20ºD¸Dh"¥öyf) 2Aý—QÕ¹[VÕÞ4*£¨E0$Yr}~Ey|’Ïë¾ùgî›bCÙʱË”Ëñ_Aù»2àíŠú‚–pú(âuã'E~oŠÜ2Æ0ôaÛIè ¹µ‰PÈkrŠCkw^ ÐrÌ9~ÊœÆôz>³Œ›©5Oæ·Út<_̶3 ¼+(=l ßSŽÜB¯"ÇßÅ–R¥©§æßH¥? UŽXªÌ±æY~+§ýä¤ÿž“žˆ²kÛ/0ƒân/uOÆ»û]ú °Àd³´ŸÏR•lêLePu£HuUþ6Õà •z¾JàYE÷ªƒbñ@<›œ‘Bò9ÁCOTDôpímÙF·Ùµ’ÑÕÚR«ÙíHšÜéHŠÖTÌn[ÑÛþZౌ40ÜZÉ_¡x•6lzä¿;¸f×\7ï»Ì8³~ÎØGï«;ÃÜ@éS€»S; [úvÕõgË.Ï g<¢ìCÙRC¥]ÊðÏ2ÿËœ¾šŸ_1ò0{ |V€2‘ºäY* xBWÝpï(Öô›ý~»Ù“¥^_7¥–#·¤^ÏÒ¥ŽÒ¶u«­Xº­—Æš¿žaͪЃßÖÈG}œÈÒöÐñRž˜«—ªnÂT'ˆTÏ_ªÌUà‰U‡„*[ruIê}´„§?*›6*$n!~Ô(\ª_Ðúhb;]SëhzG²{²,µ\¹'õô®&õšºÞPšfÊÃÄ“Ř‘Ð…O¸dâýà¼þÂ?aAþ7PKvd@zraF¨vs2008/bx_usb_xhci.vcprojíXÛnÛ8}vþC`ô¡E+_ä;o¡›³;°“f ”DÛL$J%%×ÙÝþû%ù¢$Þh[lч‘!g†œ™Ã9bÎ?n}ïlC¸ ë—ë•ZùŒ0'p)[õË·”¹Á¡ÔÕ–ZþøÛëW矨ˆ±7‹b—W<¸#NôúU){»~I¿œªœïß—aêÓÎuïC­&c샒½]ÄÂ^l×-\Ü Í~ù¯n«×5ëf]iwÕšÒ´Ô–¢›­¦Òj½®jÕZMÕú*Í®1_‘hÀÁå—€ßï×J‚í–ί<-î 9: å Û ÄØP¥~©šXTs&ç×Aà ¨GÒQ5?4¶¤«˜ã–Í–ÈÉŽÖ1‰¯þ>¬VšÄQG&åxÀúåʼR™öâJÕTiÈ"Â}âR‘Ts §¥ÈVºd²¼YbJ%íztIõéŸDÓ˜]SŸŒ¨Í1¸x–Kì ’ù]cŽØÆŒD{—zL=w¬d.úå7oaŸ°½wó\yó6-Ž þ]eù©]’£4«É[–œOÆ'‰­µ!,’Ó©~õ¤‹(ð›"ê\ŽLá Âd(àEln‰=#|CøÜ>ü'ÛË¡9*ÆÈü²xäµ4 #Yœ¤’û¢•4×¥R‚½!s¼ØÝ‚‘B*(}Èâ\D±-Yà’MæòÀ!BÜ$K€A^8ÃqCE ÓÒo.ИŒg“‘… 6'·34N&2' z°7ôAþsp)éXP@!cMœ{q!gXë—™üsgD6Ä;HgqrØè,Â<ŠC3(@¿ áíÖJÕÉãš$k¼@{±<˜ÎÝ)AÌò´§MOÛœÎíâ8yFìE1_õZ£ñÒjàrDÙ}ác!•s{: Æ$!a.t÷/G dnÎZT4™Bç< ³P2AýžQÕ…STu°5‚°ˆ¢†ÀtI‹áü*Ñé–|^ÍñÍ¿sß”xÊVŒýxª\ŒÿrÊ?”o×'ya_ù~]ÿE‘?š"wŒ1dœïAÌ)·¶!fâ¸&/qheþáû)tü˜Béõbf7Sk1ž,nµéx8¾˜íš]Äù® ²ä“û¨ >&Ë]¶¶½} gÊnõØü9õ§áÌñOË™YÓyšßJn¿Èéÿ'§G¢ôþ6%K¡¸»ÛÝ£ñþ¢—¼Bÿ?¢´Y‚ç³D%]:Ué—0Drào»E.Y¢Àõ…gÞ!G _>ÛŒšý“¡+¿XdôpÿmŒN£3¨+FGk)ÍF§­hµv[Qµ†jvZª¦_sd!·‘5 ×Wº!W8Z'€M×.ÛóÝ…»â8ðRëÔü)wŸ¼¹î +óB¿~©õîÕNöƒFu·ëê“m‹ç™¯‘Ÿ<¢t"ƒvг°ü`—ðç`¹ü…h ˜\ûˆ2€$sÐV¸'QØkôz­F·¦t{º©4íZSév-]i«­nµTKè߃Âu„ÅCÜqÉsArQ'@NÌ‘í‡ÈõVˆ;*<²)C|%Њ.Ñ]¸‚‡$?Øp‹ ê¥üA![¡/xs2+펩µ5½­ ºµšÒtj]¥«w4¥ÛÐõºZ×4³V?ÎÊq0iŒio¹ð¾0Sñap^}æ?l ÿPK?ÊÕ>$0vs2008/ Ö ¿20Ì n,¨WÌ n,¨WÌPKÅd@y.‰*a Øq %vs2008/bochs-plugins.slnPK]­A‹iiD( ¼ vs2008/bochs.vcprojPK?{hÒ>fòo$ 1vs2008/bxcommit.vcproj aÀŸ-Ì n,¨WÌ n,¨WÌPK?hÒ>QUƒ%‹$ xvs2008/bximage.vcproj ¸fŸ-Ì n,¨WÌ n,¨WÌPK?ê¡Ô>˜åŽà2‹$ Ðvs2008/bx_acpi.vcproj Ö¡m/Ì n,¨WÌ n,¨WÌPK?¢Ô>t&±X4”$ 5#vs2008/bx_biosdev.vcproj â¼m/Ì n,¨WÌ n,¨WÌPK? ¢Ô>“¢€W0‹$ Ÿ(vs2008/bx_cmos.vcproj wÊÆm/Ì n,¨WÌ n,¨WÌPK?šp?>»8†à$ .vs2008/bx_debug.vcproj ¢ðP»`Ìð,±ÛÃaÌð,±ÛÃaÌPK?¢Ô>»­Ì-0ˆ$ 3vs2008/bx_dma.vcproj ¬Øm/Ì n,¨WÌ n,¨WÌPKq“1@#[€'E¦ x8vs2008/bx_es1370.vcprojPK?-¢Ô>lÔV}7š$ ò=vs2008/bx_extfpuirq.vcproj ðìm/Ì n,¨WÌ n,¨WÌPK?8¢Ô>ƒ“‰4‘$ aCvs2008/bx_floppy.vcproj  úm/Ì n,¨WÌ n,¨WÌPK?H¢Ô>i’ …;«$ ÊHvs2008/bx_gameport.vcproj |½ n/Ì n,¨WÌ n,¨WÌPK?_?Øš‡3”$ üŸ1‘$ tYvs2008/bx_ioapic.vcproj  çyo/Ì n,¨WÌ n,¨WÌPK?Ž£Ô>i,—LÆ$ Ú^vs2008/bx_keyboard.vcproj F…wo/Ì n,¨WÌ n,¨WÌPKˆ“1@ œ'6D¤ ]dvs2008/bx_ne2k.vcprojPK?Z£Ô>ÃË]+J$ Ôivs2008/bx_nogui.vcproj ÖL>o/Ì n,¨WÌ n,¨WÌPK?£Ô>ÃÁÿ4—$ 3ovs2008/bx_parallel.vcproj  çyo/Ì n,¨WÌ n,¨WÌPK?£Ô>‹u“*0ˆ$ žtvs2008/bx_pci.vcproj s¶xo/Ì n,¨WÌ n,¨WÌPK?£Ô>Û‡r43”$ zvs2008/bx_pci2isa.vcproj s¶xo/Ì n,¨WÌ n,¨WÌPK?£Ô>µÒiê3”$ ivs2008/bx_pci_ide.vcproj  çyo/Ì n,¨WÌ n,¨WÌPK?Ž£Ô>«6U0ˆ$ Ò„vs2008/bx_pic.vcproj F…wo/Ì n,¨WÌ n,¨WÌPK o/@w¥£,Yµ 4Švs2008/bx_pit.vcprojPK?[£Ô> %ò–0g$ ¿vs2008/bx_rfb.vcproj ~?o/Ì n,¨WÌ n,¨WÌPKH“1@K=™D  !•vs2008/bx_sb16.vcprojPK?Õ¤Ô>Oh¯–RÚ$ ˜švs2008/bx_serial.vcproj =~åp/Ì n,¨WÌ n,¨WÌPKU“1@0¦4>^ù  vs2008/bx_soundmod.vcprojPK?5£Ô>P•ð/3”$ ´¥vs2008/bx_speaker.vcproj ¯“o/Ì n,¨WÌ n,¨WÌPK?5£Ô>z¬(u5—$ «vs2008/bx_unmapped.vcproj ¯“o/Ì n,¨WÌ n,¨WÌPK¯“1@/tO—½ ‰°vs2008/bx_usb_common.vcprojPK»“1@‹ F¨ Y¶vs2008/bx_usb_ohci.vcprojPKÉ“1@x{ûûF¨ Ö»vs2008/bx_usb_uhci.vcprojPK÷Žd@Lò·ŠY³ SÁvs2008/bx_vga.vcprojPK?Í¢Ô>Zѽ3d$ ÞÆvs2008/bx_win32.vcproj uÀŸn/Ì n,¨WÌ n,¨WÌPK?v²y@€j‡„½$ EÌvs2008/cpu.vcproj ŽôsÄ ÍÌ Ðý¬ûÌÌ Ðý¬ûÌPK?šp?Å”_Á«…$ øÓvs2008/disasm.vcproj ¢ðP»`Ìð,±ÛÃaÌð,±ÛÃaÌPKd@0Ú:s±—; ÕØvs2008/fpu.vcprojPK?šp?—fg±”$ µÞvs2008/gui.vcproj ¢ðP»`Ìð,±ÛÃaÌð,±ÛÃaÌPK?šp?d·Ý„©$ äãvs2008/iodev.vcproj ¢ðP»`Ìð,±ÛÃaÌð,±ÛÃaÌPK?šp?¾“é‚<$ ™èvs2008/memory.vcproj ¢ðP»`Ìð,±ÛÃaÌð,±ÛÃaÌPK?’iÒ>pÚbƒ$ Mívs2008/niclist.vcproj Bã> -Ì n,¨WÌ n,¨WÌPK?šp?†ð5¦dÜ$ „òvs2008/stubs.vcproj ¢ðP»`Ìð,±ÛÃaÌð,±ÛÃaÌPKš“1@N — w— ÷vs2008/bx_netmod.vcprojPKPd@ƒMTZð6 Åüvs2008/cpudb.vcprojPKq/@8mR ævs2008/bx_e1000.vcprojPKvd@º!*-_Ë lvs2008/bx_svga_cirrus.vcprojPKvd@zraF¨ vs2008/bx_usb_xhci.vcprojPK22‚bochs-2.6/build/win32/nsis/0000755000175000017500000000000012020641473015351 5ustar guillemguillembochs-2.6/build/win32/nsis/bochs.ico0000644000175000017500000000137612020641473017152 0ustar guillemguillem è( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿp€€»»»0»»»»0»³;»»»0»»° »»»»°;»»0 »»»»»°;»»» »»»»»°;³3»° »³333°33;° »3°33° ³0 ¸°0»»»»±‹»»1»»»33»»€€ »»°330»°»»°330 °333333333333ƒ333333€¸33333»»±»°3330»»»0p »»€33»»»°;»»€3 »»»€ »»±»»³»»° »‹pÿÿÿÿÿÿÿÿÿÿÿÿüÿÿðÿÿÀÿÿ€ÿþÿø?àààððððððÀ€€ððÀ€€ðüÿ€ÿÿÀáÿÿÿÿÿbochs-2.6/build/win32/nsis/Makefile.in0000644000175000017500000000156712020641473017427 0ustar guillemguillem# To build an NSIS installer, get NSIS version 2.0a7 from # http://sourceforge.net/projects/nsis # Fix the MAKENSIS variable so that you have the correct path. # Unzip the windows binary release into a subdirectory of this # directory, for example "2.0.pre2". Make sure the VERSION # variable has the same name as the directory, and in bochs.nsi # the VER_MAJOR, VER_MINOR, and VER_REV values should also match. # # Type make, and it should build an installer called Bochs-${VERSION}.exe MAKENSIS='c:/Program Files/NSIS/makensis' VERSION=@VERSION@ TARGET=Bochs-${VERSION}.exe DLXDIR=bochs-${VERSION}/dlxlinux all: ${TARGET} fixups:: if test -f ${DLXDIR}/bochsrc.txt; then mv ${DLXDIR}/bochsrc.txt ${DLXDIR}/bochsrc.bxrc; fi rm -f ${DLXDIR}/*.bat ${TARGET}: fixups bochs.nsi rm -rf ${TARGET} ${MAKENSIS} bochs.nsi test -f ${TARGET} ls -l ${TARGET} clean:: rm -rf ${TARGET} bochs-2.6/build/win32/nsis/lgban.ico0000644000175000017500000052424612020641473017145 0ustar guillemguillem00h ènèV (> 00¨f ¨È¶$h~+€€ (æ0`` ¨”9HH ˆT¶Í@@ (B>"00 ¨%fd  ¨Š ˆ ¶š h>¤(0`€€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿpˆ€€ðp0€;{»;3;1p³³³»{;;;;;;@;;3p;³³³³³;;³1ðp3³·»›;{3³»³0€·³¹³»{› ;“»;p·»;;;;›³0s³»;;3pp;;;›³³³³³03»7¹³³pp ;;;;;;;;3¹3³»1 ;›;97“³³p3¹33s›0 {;3·33y;370³° ;3¹030035¹³R{;p031³»70C³³³#s»;{;@3³³·{;{³0S33³³0;;;³331;;7ps³³³3³³P;³°3»;;73³3P31;;p€;;;733q#;34±p»;—33±³³0xp³333P3³3;33€p73³³3039·“9ps3³9;;3³·;3p3³9³·3s3;3³033³73³0¹33³»;p7s;;93371S;;;;0€3³³@9³³p33C»;³³±€p;;;³s33;;;;{€³³³·{ {³³³¹1€t3³¹³³ ³³³¹spS»;;·0;³³³°„;³³³1{;›3p÷s³»r@3³P;0x€p@øwÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÀÿÿÿÿÿÿÿüÿÿÿøÿÿà?ÿÿÀÿÿÿüÿðÿðððøøøøøø?ø?øðÀ€€€ð?øøàÀ€À?ðÿüÿÿÿÿà€ÿÿøàÿÿþðÿÿÿÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( @€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿp‡€€3;;3;;;;p;;;;;33³³³³³»37;;;;{³³³0@;;¹·¹³;;›³3³·;3»;“s; ;3133;¹1 s10;³p;³0;;s3;7;;333s³0p3³³q333;³0p€³»q50331;P353·³0€3³;03;93P3;3³03733p3;07¹ »³0€3p3³°3»;3pp3»30s41»{;@;»300;;;“3»;0·¹°p³·3³€p3pppHÿÿÿÿÿÿÿÿÿþÿÿðÿÿÀÿÿ€ÿþÿüÿà?ààààààààÀ€ààÀ€àøþÿÿÁãÿÿÿÿÿÿÿÿÿ(0 €€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿp3p;³°p€3³³ 35€»;;C»3 »;;{;;1€s³¹³³³3³p³sA1ps330#³p€0;·05;4pp3³130;ð»q30q°13@s30€33°3;3p7;313±;pp€3;1s;³1p;³0S00;·³A;;0·³€p3³p;€pSp‡€ÿÿÿÿÿÿÿÃÿÿÿüð?ÀÀÀÀÀÀÀ€€ÀÀ€ðüÿÿÿÿÿ( €€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿp3€3³7³» 3p;;3;731713´;43·330p33;p3331!€p3±7³q;1R;5;0±p„8pÿÿþøàÀ€ÀÀ€À€ÀðŸÿÿ(0`                 $  " #"& $'"('. %) $( (-!$&*(+(,+.)+)*+.*0*0-5.5 ,1,1/207 2905274:5:8?$$$)))...444:::;<<<==:E;D ?J=E:@ BLAFBKCKFQIUIV HT NZFPGPKULUNZQ[R[Q]U^RZ GM MU PW"U]Tb Ra Xf^n]kWaXeYbXa]k%\d%_kboamdobq csi|brdpjvgxl~kxjzo}l|p}$ju!ix#q}GGGKKKKLLNNNTTTYYY`aakllrrr{{{ n‚n€ wŒzŒz~stƒu…w…s‚x‡v‰}}Œ~—˜|‘ }‹— ‚™ƒ–ƒ“†˜‡™†‡˜Š"ƒ”)‚•!‰š ‹¥ Ž©Œ£“ª ‘­ ™¯”§–®œ¯”±”°™µœ³¹Ÿµ¡¹¡½¦¿ ¤»£º¦¾¦½¥º¥Á §À«Ç ¬Ä«È­É ®È©Á­ÅªÀ¯È±Ì °Ê °Ê ²Ì³Ì ´Î µÏ°É´ÎµÑ ¶Ð ·ÑºÖ¼×¹Ô»Ø¼Ø ½Ø¾Ø€€€ŒŒŒ“””———˜˜˜œ¡¡¡¥¥¥«««¬¬¬´´´»»»½¾¾ÁÁÁÆÆÆÈÉÉÎÎÎ×××ÜÜÜåååëýòN&ïòLPûï';rU’ùL*{Êãä» [&÷#‡ÚèèääÔšåÅ0ëõ uÚääèäèèÚ5®èèÒ=NMH¼äèäèäèäèá5œèåäÍ['ü– tÜèèèäèäèääá7 èèèèè¹='û”#WÈäèèääèäèèèäåXräåäèèèØ| –ò % ãäååååååäèäèääeaäåèèèèäè¹=(ò’5 ÔåååååååååèäèèèäfaèåäèèääèèØm’våååååååååååääääèäecäåäááØØáääã€õDååååèååãÒÒÑÍØÒáääfaèåÒÅÁÁÁÁÒäèè##ÔåååèãÒÅÁÁÁÁÁÁÁÍáecØÅÁ¿™p—ÀÁÍáä& ÓååäÒÅÁ¿«qov›¼ÁÁÍfoÁÁ§\Q¦ÁÁÒ#ÓåÚÍÁÁ¶]0^®b~¶na%0~ÀÅ* ÈÒÁÁ¿vGbT%  uÚèÚt=®&*¿ÁÁ™@;²åääãʆT µåååèåµ5 ¿®Q‹ÚååèèäåÊi *zÓåäåäÑWü TiÂåååååèÓrF‡«e#%ÔèååÜl L WÈãèèèèèщ%†ºÁÁÁ³%%°åååå´* ””Fµåäèèèåå¸7%€º¿¿¿º†*FUÈååèÈXJöùN cÜåååäèèÊl k¶ÁÀ¿¿·ssÀ®X,¥ãèè㉠ò& åååååäãŸ*S£—˜F;®¿¿¿¿˜*@­Ôv# –*¥ãåååã­5sbºÁ¿¿¿¿Á¶W&’öþë H¾Ü¥D a¸Á¹º‡H& G£¿¿¿¿¿¿¿¿ÁÁŠ(÷–  T´¿¿¿¿¿¿ÀºRXÁ¿¿¿¿¿¿¿¿¿œUí&Xœ¿À¿¿¿¿¿¿¿ÀT_¿¿¿¿¿¿¿¿­FHkLûíBœ¿¿¿¿¿¿¿¿¿¿¿¿T_¿¿¿¿¿½œiF­ãå !Nùò' b®¿¿¿¿¿¿¿¿¿¿T`¿¿¿¿¸YH®ãáèååÄbN*Wbb²¿¿¿¿¿¿¿¿T_¿¿¿x!5 ãèèèåååå¹) þò lÈäåÓ :`¬¿¿¿¿¿½T`¿²H%‹×èáèèèååÑp N÷uãäèåååÚ %U‡¼¿¿¿T_²5sÓäèèèèèååÍ@KúL7­ååååêåÑ©F5v¼¿TG% ³áèèäèèèäåÁ0 óí&&¥Êååååååã¸T `5­äèèääèèäÁm õí kÌååååèååʽèèèäèèèÁC(õL HŸÔååååååÓ F£ÚèäääØšMñû’5ˆÔåèäåÖ&&7ˆÓä»CL’&#s¯Ôå_'ï'%V ’ÿí(5õð'N÷J”ÿö“íùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÀÿÿÿÿÿÿÿüÿÿÿøÿÿà?ÿÿÀÿÿÿüÿðÿðððøøøøøø?ø?øðÀ€€€ð?øøàÀ€À?ðÿüÿÿÿÿà€ÿÿøàÿÿþðÿÿÿÿïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ( @               ! ""' # " !% !$#( %* '+ ',(/ (-!$$'(++/,2.6 *0+1 -2/4+0.3/3/5 063;2;4< 39 4: 6= 6=057=8=!!!%%%---222999>>>8A:A ;D >F;ABLDN @JCN DN ENBKBKDKEMEPEPHT KYNZJRKUNWNWNZ PZQ\T_R[T]Vf T` Ve Zf \mVaWdYf\g[i_p`manbn `q aqhx kzaqaqerdpj{k|m pBBBGGGHHHOPPPPPXXX]]]```iiiqqq}~~n€o€u…s‰v‰t‰{Ž {Žr€v†y‡uˆ{Šyˆz}Ž}z|’€‘ƒ•™ †™ „‚“ˆ›ˆš‰œ ‡ Ž£ ˆ ‰¢ Œ¦ § « ީޡ¤’® « ‘­‘¥“§–ª”±•±›³™¶ š°š¸œ¹Ÿº”° · ¸¢¾¡¸¤» §¿£º¨¿¦Â¨Â©Æ¨À ¬Å¯Ë ®È ¯È±Í´Ï ±Ë ±Ê ³Í ²Ì ´Ï°È¶Î¶Ñ¶ÑºÖ¼× ¸Ó¹Ô¹Ô»Ø¼Ø¼Ø„„„‰‰‰‹ŒŒ™™™œœœ«««¬¬¬±±±µµµ½½½ÂÂÂÄÄÄÐÐÐíŠñ‚ ìñEAp|F‚V¶ÝÝÑ PÀ<êê-¨ÝÝÝäÜkäÛJ‡FfØÝäÝäÝÝdÝäÝ‘ GïI5½äÝÝäÝÝÝä4@äääÝËPí2šäÝÝäÝÝäÝäÝ@=äÝÝäÝÝ“ G–ÝÝÝÝÝÝÝÝÝÝä@=ÝÝÒËÌÛݶ íF_äÝÝÝË¿¾¿¿ÀÝ==ÒÀ³‘¤¿ÌÝ í†MäÝË¿­jMSw¤¿@P¹) h¹Êí†MÒ¿½w 3,!%<a–0”í…S¾ž0_ÈäÝÑŸ_ØääÂMí†3M,§ÝäÝݨAAt5!–ØäÜgI‚šÜäÝä½C!–´¹¬52¬äÝ¥ì‹dØäÝäØu |´µµ›d–pÑäÑ@†ì}ääÝä”!&[\Sš¹µ´ds[ I‹ ŽÚ£A2’´wA Z­¹¹¹¹¹Ÿê„ !|Á¹¹¹µ©r¹¹¹¹µµ|Eñ€´µ¹¹¾µ¾¤ r¹¹¹µŽ&3¨· Œ‡p­µ¾µ¾´¬|¹¹›!&·ÜäÝØd íìyѨWp¬¹µ¾© l­W-Üäääݪ ‚†fÚÛÝä¸VW µ¬t5 tØääääÝxGæ ¸äääÝÈdAt–ÝäÝäݾP‰å-šØÝÝÝØŽšäääÝË<èìFZšØÝÝÚ wÇÛïð„m£dòŒ%‰‹Eææ„ñÿÿÿÿÿÿÿÿÿþÿÿðÿÿÀÿÿ€ÿþÿüÿà?ààààààààÀ€ààÀ€àøþÿÿÁãÿÿÿÿÿÿÿÿÿ(0@               ! # $ # # $ #& %*%) ). (-"%&).5 +0 *0 .3 /6 /40618184< 2929 7?###&'')))&022227B 7@ 9A ;D?H >H AI CNEN GPKT NW NYGQOYT^ Sa U` WfVeXeXg [i ^k ]i ]mTaYd_q andq ftgt hv hv izm{k~ lcphvJJJLMMVVVfggooopppuuu}}} m€pr r†t‰ w z‹ yŽz|Œw‡x‡yŠx— {‘ |’ ~• ““ ƒ– „— ƒ› „š‡š „œˆˆš ˆœ€’Œ¢‹¥ Œ¦ ލ‘§‘®”© ’®—¬‘¥•±”°™±µ š° ³ žµŸµœ¹›°¡º¢¿ ¡¸ ¤» ¥¼§¾¥Á§Ä¨Ä ¨Á ªÂ­Å ¯È³Î ±Ë´ÏµÑ¸ÓºÖ¼× ¸Ó¼Øƒƒƒ„„„‰‰‰ŽŽ’’’š››œœœ¦§§±±±¹¹¹¾¾¾ÀÀÀÅÅÅÌÌÌi¸:Ywgu¯³­ —ж½I¬¯³³¯ ˜¯—0e½7$’³³³³³¯#ƒ³¯¯m9:_¯¯³³¯³³³%€³¯®¯—»in¯³®¦¤Ÿ¤«%€¦zœ®\¶ºR¯¦”R%t”””lu(t±³³Ÿ0¿h ƒ¯³£U -`•"H b³³³³†¶À:E¯³ª^p³³³; ¿f,]¡³­UN¡«O »k 3]Àk fÀµ¼ÿÿÿÿÿÿÿÃÿÿÿüð?ÀÀÀÀÀÀÀ€€ÀÀ€ðüÿÿÿÿÿ(    # % !$ #) &, '- )/ *0 ,2 ,2 .4 05 17 29 4; 5= 5= 8?7<489> 8< ;DBK@H ER GQ GT HR HT KTP^ P[ P^ S]-AD>EF TcZh _lZe?[a cq cu gu iwh{ lFFFLUVPVWikkjklqqqz{{y|} m q€x { x z ~ €’ ‚š ŠŠ ‡  ˆ¢ ¡ Œ§–¬’¯˜¯•± Ÿ¶Ÿ»  · §¿¦ÁªÇ­Æ ªÃ «Ä­È²Î ²Ì ´Î¶Ò¶ÑºÖ¼Ø‹‹‹ŽŽŽ’’‘‘‘———°°°···¸¸¸½½½a95+Fha"X_^^*;I_^^^^_M-hI^\TTYYNPX7?S2# #">7%.\VC[%4aV^= 2JQC(dRF ¶¶¶ŠtttÚ222ìúýýýþýýýý%(üIPý*{‰ü¢¸ü ´Îþ¸Ôþ¸Ôþ»×ÿºÖÿºÖÿ¼ØÿºÖÿ»×ÿ¯ÉþkyûûýþþþþþMYþw‹þyŒþYhþ,3þþþýýýý ú111æ|}}°ÄÄÄkîîîûûûýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýûûûììì%¾¾¾¢rrrÐ9::èõýýýþþýý ü03ø^hý‰šþ£»þ³Ìþ¹ÕþºÖþ»×ÿ¼Øÿ»×ÿ¼Øÿ¼Øÿ»×ÿ»×ÿºÕÿ°ËþrúúýþþþþQ]þ—¯þ°Ëþ±Ìþ¤¾þ€”þEOþþýýýýý û!!!ô```Ö¹¹¹yîîîûûûýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýûûû÷÷÷ééé®®®•MOOáùüýýþþþý ý!#û W_ý$‹›ý ­Åþ ¶Ñþ¹Õþ¹ÕÿºÖÿºÖÿ»×ÿ»×ÿºÖÿ¼ØÿºÖÿºÖÿ¼ØÿºÖÿ ´Îþ(ú+,úýþþþ þy‹þ´Ïÿ»×ÿ»×ÿºÕÿ±Ìþ’©þN[þþýýþýýüøWWWÞ¯¯¯‰æææ&øøøüüüýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýùùùíííÁÁÁjpppÔ,--ò ûýýýþýý ý !ý/RXë(‰˜û©Áþ¶Ñþ¸ÔþºÖÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ¼ØÿºÖÿºÖÿ¼Øÿ¼Øÿ»×ÿ»×ÿ·Òþ–«ý?Eýýýþþ)/þ‹ þ¶ÑÿºÖÿºÖÿºÖÿ¹Õÿ´ÏÿŸ¹þaqþ %þþþþýýýú111ï|||ÄÌÌÌZòòòüüüýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýûûûõõõßßß0“““¦000îúýýýþýýý ùAFûŒ þ«Åþ ¶ÑþºÖþºÖþ»×þ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿºÖÿ»×ÿ»×ÿ¼Øÿ¼ØÿºÖÿ»×ÿ¼Øÿ¹ÔþŸ¶þMVý ýýþý+0þ£þ¸Ôÿ¼Øÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ¸Ôÿ¨Âþhyþ &þþþþþýýýùbccÚÃÄÄ^ïïïúúúýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýûûûööö-êéésÊÉɨ¯(((ëüýþþþþý û ,1ú%dn뢶ò¶Ñþ»×ÿºÖÿ»×þ¼Øþ»×þºÖÿºÖÿ»×ÿ¼Øÿ¼Øÿ¼ØÿºÖÿ¼ØÿºÖÿ»×ÿ¼Øÿ¼Øÿ¼ØÿºÕþ ¢¹þT]ý ýýþý&)ú‰œþ¶ÑÿºÖÿºÖÿºÖÿºÖÿºÖÿºÖÿ¹Õþ¦Àþ`pþþþþþþþýýùZZZ൵µrèèè'ùøø3ýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýüüüùùùëëëMËÊÊ¸š™™¡\\\Ý!!!øûýþýýý ý%(ý%QYö!‹œô ®Èþ¸ÓþºÖþ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»Öÿ¸Ôþ ¢ºþU^ý ýýþý #ü„—þ·Òÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ·Òþ Ÿ·þUdþþþþþþþýýûDEEáš››œÜÛÛÇöööüüüýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýúúúòòòØØØ@¥¥¥…aaaÙ***÷ûýýýþýý ü@Gý tþ ´þ ³Íþ¸Ôþ»×ÿ¼Øÿ»×ÿ»×ÿºÖþ»×þ¼Øþ»×ÿºÖÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿºÖÿ¼ØÿºÖÿ»×ÿ¼Øÿ»×ÿ¹Õþ ¤»þT^ý ýýþýý’þµÐÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ¼×þ·Òþ ˜²þ]mþ/6þþþþþþþý û///ñƒ„„¾×××Z÷ööIýüüýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýúúúëë뻼¼quuu»9::åùýýýýýýý-0úeqü–«þ ®Çþ¸Ôÿ»Öÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÕþ ¢ºþS^ý ýýþýý~ŽþµÐÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ¼ØþºÖþ¶Òÿ¤¿þ„™þTcþ)0þþþþþþýü())ò‚‚‚ÌÙØØ·÷÷÷Rýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþýýýýýýûûûöõõiâââ=¦§§QRRÞ÷üýýþýýý ý$/1ú/|ˆûªÂþ·ÒþºÕÿºÖÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×þºÖþ»×þ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿºÖÿ¼ØÿºÖÿ»×ÿ¼Øÿ¹Õþ ¢¹ýT^ý ýýþýý~Žþ·ÑÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ¼ØþºÖÿ¸Ôÿ³ÎÿŸ¸þ|þKWþþþþþþýü---ò‡‡‡ÎÛÚÚ®÷ööSüüüýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûöõõbçççM½½½·yyyº788âúýýýýýý ý#ý$FLý7ƒŽü®Æþ¸ÔþºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÕþ £ºýV`ü üýýý ýt„þ ´Îþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ¹Ôþ²Íþš³þiyþ29þþýýýý ü000ñ…„„ÐÏÎ΋ðïïûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûøøøòòòÞÞÞ>¹¹¹©‡‡‡ÅEEEâ÷ûüýýýý ý"'ýJSþ{Œþœ°þ±Éþ¹ÔþºÖþ»×þ»×þºÖþ»×þ¼Øþ»×þ»×þ»×þ¼Øþ»×þºÖþºÖþ»×þ»×þºÖþ»×þ»×þ¼Øþ»×þ»×þ»×þºÖþ¼ØþºÖþ¼ØþºÖþ ¦½ý]húûýýý ü,\dò­ÅýºÖþºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ¼ØþºÖþºÖþ¼ØþºÖþ¶ÒþªÃþ†œþN[þ$þ ýýýü ü(((óeeeȲ²²zæææ|ø÷÷Aûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûôôôããã2ÅÆÆj   •stt¼BBBå!!!÷ ûýýýýýý ý=Býxˆý ´þ ±Ìþ¸ÓþºÖþ¼Øþ»×þºÖþ»×þ¼Øþ»×þºÖþ»×þ»×þºÖþºÖþ¼Øþ»×þ»×þºÖþ»×þ¼Øþ»×þºÖþºÖþ»×þ¼Øþ¼Øþ¼Øþ»×þ»×þºÖþºÖþ¯Èý$t€ý"%ýýýýü'@Dõž³þ¹Ôþ»×þºÖþºÖþºÖþºÖþºÖþºÖþºÖþ»×þ¼Øþ»×þ»×þ¼Øþ¼Øþ¹Õþ±Ìþ™±þj{þ5=þýýýüüöHIIâ“““ÇÑÐÐhïïïùùùýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýüüü÷÷÷ééé±¾¿¿lwxx·CDDâ)**ïö ûýýýþþýý #ý!\fý’¥þ ®Çþ¸Ôþ»×þºÖÿ¼ØÿºÖÿºÖÿºÖÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ»×ÿ¼Øÿ¼ØþºÖþºÖþºÖÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿºÖÿ¼Øÿ»×ÿ¼Øþ ¶Ñþ‡šþ /5þýþýý26û—«þºÕÿ»×ÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ¼Øþ¼Øþ¼Øþ¼Øÿ¼ØÿºÖÿ»×ÿ»×ÿºÖÿºÖÿºÖÿµÑÿ©ÃþŒ¤þVcþþýýýý û(((òWWWÝœœœ¤ÚÚÚBõõõ üüüýýýýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþüüüôôô ÉÉÉhwxxÉ122íö ûýýýýþýýþ ý')ô/u€ì ªÂþµÐþ¹ÔþºÖþºÖþ¼ØÿºÖÿ¼Øÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿºÖÿ»×ÿ»×ÿºÖÿºÖþ¼Øþ¼Øþ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿºÖÿºÖÿ¼Øÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ»×ÿºÖþ¶Òþ¥þ:@þ þþþý-2ü”¬þ·Óÿ»×ÿ»×ÿºÖÿºÖÿºÖÿºÖþºÖþºÖþºÖÿºÖÿ¼Øÿ»×ÿ»×ÿ¼Øÿ¼Øÿ»×ÿ»×ÿºÖÿ¶Ñþ§Àþ |‘þ09þ ýýýýý û!!!ôeffÉÊÊÊOïïïøøø üüüýýýýýýþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþùùùËËËeXXXÛúüüýýþþýýý ý ý$W_þ9 ¯þ ³ÍþºÕþºÖÿ»×þ¼Øþ¼Øþ¼ØÿºÖÿ¼ØÿºÖÿºÖÿ»×ÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ¼Øÿ¼Øþ¼ØþºÖþºÖÿ»×ÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ¼ØÿºÖÿºÖÿºÖÿ»×ÿ»×ÿ»×þ¹Ôþ”¨þ>Eþ þþþý03û–¬þ¹Õÿ¼Øÿ»×ÿ»×ÿ¼Øÿ¼Øÿ¼Øþ¼Øþ¼Øþ¼Øÿ¼Øÿ¼ØÿºÖÿ»×ÿ»×ÿºÖÿºÖÿ»×ÿ»×ÿºÖÿ¸Ôÿ±Íþ–¯þQ^þ"þ þþýýý ú.//ñˆˆˆÂÌÌÌnëêê¾÷÷÷üüüýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþóóó ½ùýýýýþýýý ü#&ý%DIù/y„þ©Áþ ·Òÿ»ÖÿºÖÿ»×ÿ»×þºÖþºÖþºÖÿ¼ØÿºÖÿ¼Øÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿºÖÿ¼ØÿºÖÿºÖþºÖþ¼Øþ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿºÖÿºÖÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»×þ·Òþ‘¦þ=Dþ þþþý-1ü”¨þ·ÓÿºÖÿ¼Øÿ¼ØÿºÖÿºÖÿºÖþºÖþºÖþºÖÿºÖÿ»×ÿ¼Øÿ»×ÿ»×ÿ¼Øÿ¼Øÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ´Ðþ¡ºþoþ5>þþþþþýýùNNNï’’’µÊÊÊ^îîîúúúýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþïïï \^^Ò üþýýýþý û'*ü*NSöz‹ý"ž²þ´Íþ¹ÔÿºÖÿ»×ÿ»×ÿ¼Øÿ»×þ»×þ¼Øþ¼Øÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»Øþ»×þ»×þ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ·Óþ“§þ>Dþ þþþý-1ü–«þ¹Õÿ¼Øÿ¼Øÿ»×ÿ»×ÿ¼Øÿ¼Øþ»×þ¼Øþ¼Øÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖþ¸Ôþ¬ÇþˆžþP]þ %þ þþþýý ü"##ø[[[߬¬¬‰çççAúúú"üüüýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþììì JKKÝüþýýý þ8>ýXaø$}Œü#Ÿ²þ ²Íþ¸Óþ»×ÿºÖÿ»×ÿ»×ÿ»×ÿºÖÿ¼Øþ»×þ»×þ»×ÿ»×ÿ¼ØÿºÖÿ¼Øÿ»×ÿ»×ÿºÖÿ»×ÿ¼ØÿºÖÿ»×ÿ¼ØÿºÖþ»×þ»×þ¼Øÿ»×ÿ»×ÿºÖÿ»×ÿ¼ØÿºÖÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×þ¸Ôþ”¨þ>Eþ þþþý03û”¨þ¸Óÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ¼Øÿ»×ÿºÖÿ¼Øÿ»×ÿ»×ÿ»×þºÖþºÕþ³Îÿœ´þfwþ)1þ þþþþýýúIJJá±±±¼ðïïbüüüýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþëëë FGGßüþýý ýU^þ•«þ ªÂþ²Ìþ ¸Óþ»Öÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ¸Óþ”¨þ?Eþ þþþý14û•ªþ¹Ôÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿºÖÿºÖÿºÖÿºÖÿºÖÿºÖÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þºÖÿ¶Ñÿ¢»þ evþ"&þþþþþýýøoooÁÚÚÚEúúúýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþììì IJJÝüþýý þt„þ³ÍÿºÖÿºÕÿ¼ØÿºÖÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ¼ØþºÖþ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿºÖÿ»×ÿ¼ØþºÖþ»×þ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿºÖÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×þ·Óþ•©þ>Eþ þþþý15ú—¬þ¸Ôÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×þ»×þºÖþºÖÿ¹Õÿ¹Õÿ¹Õÿ¸Ôÿ·Óÿ·Óÿ·Óÿ·Óÿ¸Ôÿ¹ÕÿºÖÿ»×ÿ»×þ»×þ»×þ»×ÿºÖÿ·Òÿ³þ`kþ)-þþþþþý üKKKáÃÃÃeøøøýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþîîî YZZÔ üþýýýjwþ±Êþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿºÖÿºÖþºÖþºÖþºÖÿºÖÿºÖÿºÖÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×þ·Óþ“§þ>Dþ þþþý04û•ªþ¸Óÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖþºÖþ¹Õþ¶Òÿ¶Òÿ´Ðÿ±Íÿ°Ìÿ¯Ëÿ®Êÿ®Êÿ¯Ëÿ±Íÿ´Ðÿ¶Òÿ¹Õÿ¹Õþ»×þ»×þ»×ÿ»×ÿ»×ÿ ·Òÿ¤ºþ$~Œþ$LQþþýþþý=>>æ´µµk÷÷÷ýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþóóó „„„¾úþýýý#U]þ¤ºþ¹Õÿ»×ÿºÖÿ¼ØÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ¼ØþºÖÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ¼ØÿºÖÿ¸Ôÿ¸ÔÿºÖÿ·Óÿ¸Ôÿ¹Õþ¸Ôþ¹Õþ¸Ôÿ·Óÿ·Óÿ·Óÿ¹Õÿ¹ÕÿºÖÿºÖÿºÖÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×þ·Òþ‘¦þ=Dþ þþþý-2ü”«þ¸Ôÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ¸Ôþ¶Òþ´Ðþ¯Ëÿ¬Èÿ§Äÿ¥Âÿ¤Áÿ¤Àÿ£Àÿ£¿ÿ£¿ÿ¥Âÿ©Åÿ­Éÿ³ÏÿµÑþºÖþºÖþ»×ÿ»×ÿ»×ÿ»×ÿ¸Ôÿ²Êÿ“¦þ'*üýþþý9::䯰°iöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ÷÷÷»»»t÷ýýý ý÷ýþþý899䯯¯jöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýüýèåæÇabbÒ üýýýû+nyü®Åþ»×ÿ¼Øÿ¼ØÿºÖÿ¼ØÿºÖÿºÖÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þºÖÿ¹Õÿ¹Õÿ·Óÿ³Ïÿ®Êÿ¦Ãÿ¡½ÿ¹ÿ›·ÿ›·ÿ›·ÿ›·ÿ›·þ›·þš·þ™·ÿ›·ÿ›¸ÿ›¸ÿ›¸ÿœ¸ÿžºÿ ¼ÿ£ÀÿªÆÿ®Êÿ²Îÿ¶ÒÿºÖþ¹Ôþ”©þ>Eþ ýýþý04û—«þ·Òÿ¸ÔÿµÑÿ²Îÿ¬Èÿ§Ãÿ¡½þ›·þ—³þ–´ÿ•´ÿ”±ÿ“±ÿ’°ÿ’¯ÿ’¯ÿ“¯ÿ”¯ÿ•±ÿ •±ÿ–²ÿ–³ÿœ¸þ¤Áþ¬Èþ³Ïÿ·Óÿ»×ÿºÖÿ»×ÿ¼Øÿ ­Æþ9=øýþþý899ã°°°höööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýððð”””³úýýýý)[cý¥»þ¹ÕþºÖþºÖþºÖþ¼ØþºÖþ¼Øþ¼Øþ»×þ»×þ»×þ»×þ¹Õþ¸ÔþµÑþ³Ïþ¬Èþ¥Áþ¡½þ›¸þ—¶þ–³þ–´þ–¶þ–¶þ–¶þ–¶þ–µþ–µþ–³þ–¶þ—¶þ˜µþ–´þ—´þ—µþ™µþš¶þžºþ£Àþ©Åþ¯ÊþµÐþµÐþ“¨þ@Gý ýýýý15û–¬þ´Ðþ²Îþ«Çþ¦ÂþŸ¼þ›·þš¶þ–´þ•²þ”³þ‘¯þ ‰£þ ~•þ pƒþ gxþ gxþ p‚þ ‚™þŽªþ’±þ•³þ–²þ–µþ›·þ ¼þ¨Äþ®Êþ³Ïþ·Óþ»×þºÖþªÃþ9<øýýýý677䯯¯jöööýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýôôô ¬¬¬‹÷üýý ýPYýžµþ¹Õþ¼Øþ¼Øþ¼ØþºÖþ¼ØþºÖþºÖþ»×þºÖþ¹Õþ¸Ôþ´Ðþ³Ïþ¬Èþ¤Àþ ½þœ¸þ˜µþ•³þ•²þ–³þ–´þ˜µþ˜µþ˜´þ˜´þ˜´þ•´þ—µþ™µþ˜¶þ—¶þ–³þ ”¯þ•³þ “¯þ•³þ–³þ™µþžºþ¥Áþ¬Èþ¯Ëþ¤þ>Dý ýýýý6=ý’¦þ«Çþ§Ãþ¡½þ›·þ—´þ•³þ ’®þ“±þ’°þ Фþ {’þ_nþFRþ3=þ+3þ+3þ3<þFRþ `rþ €—þެþ”²þ•²þ•³þ—µþœ¹þ¥Áþ­Éþ²Îþ·Óþ¸Ôþ¬Åý9<øüýýü888䮯¯jöööýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýõöö ±²²ƒ'''ôýýý ýOYþ Ÿ¶þºÖþ»×þºÖþºÖþ»×þ»×þºÖþ¼ØþºÖþ¸ÔþµÑþ³Ïþ­Éþ¨Äþ¡½þœ¸þ˜µþ–´þ–²þ–²þ•³þ–³þ “­þ ¨þ ¥þ Œ£þ Œ£þ ¤þ ¥þ‘©þ˜²þœ¶þ¸þœ·þ˜¶þ™¶þ˜µþ–³þ–²þ–²þ—³þœ¸þ¥Âþ­Èþ¤þ?Fý ýýý þ@Gþ ¦þ¡½þž»þ™·þ–´þ–²þ•²þ ¬þŒ¨þ—þl~þO[þ08þ!þþ þ þþ!þ09þN[þp‡þФþ®þ”³þ–³þ—³þš·þ ¼þ¨Äþ°Ìþ³Ïþ ªÄþ9=øýýýý899䯯¯jöööýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ³³³€'''ôýýý þOYþ žµþ¸Ôÿ¼Øÿ¼Øÿ»×ÿ»×ÿºÖÿºÖÿ·Óÿ¶Òÿ²Îÿ®Êþ¨Äþ¢¿þž»ÿ™µÿ–²ÿ–²ÿ–³ÿ–´ÿ ”°ÿ ©ÿ ƒšÿm}þYfþPZþKUþKTþOXþPZþXbþkwþ |Žþ…™þŒ¡þ•¬þ š´þ›¶ÿ–´ÿ•´ÿ•´ÿ—³ÿš·ÿ¢¾þ«Æþ£þ:Bþ ýýþ þO[þŒ¤ÿš¸ÿ–³ÿ–²ÿ•³ÿ”±ÿŽ«ÿ‚šþmþWfþ;Eþ#)þþþþþþþþþ!(þ:Eþ\lþxþ©þ“¯þ•²ÿ–³ÿ˜´ÿºÿ¥Áÿ¬Èÿ ¥¾þ$<@øýþþý899䯯¯jöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ±±±…%%%õýýý þNYþ µþ¹Õÿ»×ÿ»×ÿ»×ÿºÖÿ¹Õÿ·Óÿ²Îÿ­Éÿ¨Äÿ£¿þºþ˜µþ–³ÿ–³ÿ–³ÿ•²ÿ•²ÿªÿ–ÿftþ ALþ&-þþþþþþþþþ þ-2þ!@FþZdþ pþ zŽþ €•ÿ ‰¡ÿ«ÿ”¯ÿ›·ÿ¥Áþ¬Çþ¤þDþ þþ þ+3þduÿ §ÿ”³ÿ“°ÿ ˆ¢ÿ v‹ÿ ]mþ>Hþ&-þþ þþþýý ý "&ý "ü üýýýþþ*2þHTþi{þ€™ÿ©ÿ“¯ÿ–²ÿ—µÿŸ½ÿ¸þAHþþþþý899ã°°°iöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ±±±…$%%õýýý þMWþ ´þ¹Õÿ»×ÿ»×ÿ¶Òÿ²Îÿ­Éÿ¦Âÿ ¼ÿœ¸ÿ—µÿ–´þ•²þ–³þ˜³ÿ—²ÿ‹¢ÿqƒþ Q]þ .4þþ þþþþþþýýýþþþþþþþ þþþ'-þ 4;þDNþcpý„•þ#}‹þ8=þ ýþ þ#*þ Wdÿ Š£ÿ‘­ÿ –ÿdtÿFSþ-5þþ þýýýýý5;þ]iþw‡þp~üPYü*-û ýýþþþ$+þ>IþZiþ p…ÿ ƒœÿ ªÿ–²ÿŸ¼ÿ ž¸ÿAHþþþþý788䯯¯jöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ³³³&&&õýýý þNYþ žµþ¸Ôÿ¸Ôÿ¶Òÿ°Ìÿ«Çÿ£Àÿœ¸ÿ˜µÿ—µÿ•²ÿ–³þ˜´þ˜´þ–®ÿ|ÿVbþ 3:þþ þþþþþýýýýüýýþþþþþþþþþ þ þýý27ý!<@ýýýþþþ9Aþfvþ ewÿ LXþ2;þ#þþþýýý ü.0÷ ^ký‡šþ¤¼þ±Ëþ¯Çþž´þ{‹üIQý ýýýý þþ.5þBNþ[kÿ q„ÿ ¤ÿ¢½ÿ ¢»þ?Fþýþþý899䯯¯jöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ´´´'''ôýýý þOYþ ´þµÑÿµÑÿ°Ìÿ©Åÿ¡½ÿ›·ÿ–³ÿ–´ÿ–´ÿ–´ÿ™´þ™´þ’ªþixþ 8Aþ þ þþþþþþþ ý ý%'ù+-ü+-û%&ù ý ýýýýþþþþþþýýýý ýýýþþþþ&+þ$*þþþ þþþýýü8MO㈘ú§¿þ ´Îþ¹Õÿ»ÖÿºÕÿ ·Òþ °Êþš°þ1ktþ"$ü ýýýýþ!þ-3þ=GþZgþ“¨þ ¡¹þ9>úýþþý899䯯¯jöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ²²²ƒ'''ôýýý ýOYþ ™°þ®Êÿ¬Èÿ¥Áÿ ¼ÿ˜´ÿ–±ÿ ”¯ÿ—³ÿ™µÿ›·ÿ—²þz‹þJTþ$)þ þþþþþþþ þ.1þ'_hþ„”ý¡ý’¦ý¤ü¡ý‚“ý2kró0MRç6;÷ "'ýþþýýýþþþýýýýýþþþþþþþþþýý ý)79ù(q}ü ´ó µÎþºÖþ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ·ÒþªÁþ$‹›þ:=þ ýýýþþ þþ"þDKù“ý/1ùýþþý899䯯¯jöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ³³³€%&&õýýý üR]ý ”«þ¤Àÿžºÿ›·ÿ—´ÿ–´ÿ•³ÿ–²ÿ˜³ÿ–±ÿ Š¡þ dtþ 07þþþþþþýý ý$'ý+Y`þ"ŽŸþ¨Àþ ´Îþ¸Ôþ·Òþ¹Ôþ¸Ôþ µÏþ­Åû¦¼ø ž´ü–«þ$‚‘þ"]gþ=Cý%'û ýýýýýýýþþþþþþþþþþýýûW`ü•¨ý¯Èý·Òþ¹ÕþºÖÿ»×ÿ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿ»×ÿ»Öþ µÏþ–ªþ+RYý !ú ýþþþþýý ýýýþþý999ã°°°höööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ³´´$%%õýýý"ý Wfþ¨þ›·ÿ—´ÿ–²ÿ–´ÿ–µÿ•³ÿ–²ÿ ަÿj{þ >Gþþ ýýþýýýýü*EIû"þ §¿þ ³ÎþºÕÿ¼Øÿ½ÙÿºÖþ¼ØþºÖþºÖþºÖþºÖþ¸Ôþ·Òþ ´Îþ ®Çþ¤ºþ1„‘þesýDLý ûýýýýþþþþþþþþþþýü,\cýœ¯ý ²Ëþ¸ÔþºÖþ¼Øÿ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿ»×ÿ¼Øÿ¼Øÿ»×ÿ¹Õÿ µÏþ!¤¸þ0vý=Cý ýýýýýýýýýþþý899䯯¯iöööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ±±±…"""öýýý!'þ ^nþ ¦þ–µÿ–µÿ–µÿ˜´ÿ”¯ÿ ¥ÿs…þGSþ")þ þýýýýýü û5:ý-t€þœ±þ ±Ëþ¹Õÿ¼Øÿ»×ÿºÖÿºÖÿ¼ØþºÖþ¼Øþ¼Øÿ»×ÿ»×ÿ¼Øÿ¼ØÿºÖÿ¹Õÿ¸Óþ ´Ïþ ®Èþ´ý%p}ü'*ýýýýþþþþþþþþþþý ý:?ý-vþ¡·þ²Ëþ¹Ôþ¹ÕþºÖÿºÖÿ»×ÿ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿ¼Øÿ¼Øÿ»×þ¹Ôþ°Êþ›°þdqü#%ú üýýþþþþþþý:;;ä±±±höööýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ±±±„%%%õýýý$*þ_oþ ¦ÿ–´ÿ—´ÿ•±ÿ ¦ÿ q…þJVþ -4þþ þþýýýý ü"#õ,dmð  ¹þ ±Êþ¹Ôÿ»Öÿ»×ÿ»×ÿºÖÿ»×ÿ¼Øÿ¼ØþºÖþ»×þºÖÿºÖÿ»×ÿ»×ÿºÖÿºÖÿ»×ÿ»×þ¸Óþ ®Æý1‹˜ù.DGë ýýýýþþýýýýýýþþýýþ þ.3þl{ý œ²ý ±Ëþ¹Õþ»×þ¼Øÿ»×ÿºÖÿºÖÿ»×ÿ¼Øÿ¼ØÿºÖÿºÖÿºÖþºÖþ¸Óþ¬Æþv‡û,.ù üýýþþþþþý<==ä³´´zõõõýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ´´´€'''ôýýý"þYhþ ާþ—²ÿ§ÿ ~“þU`þ-4þþ þþþþýý ý ý?DúE…Ù ®Èý¶Òþ¹ÕÿºÖÿ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿºÖÿ»×þ¼ØþºÖþ¼Øÿ¼Øÿ»×ÿ»×ÿ¼×ÿ ºÕþ ´Ïþ ­Æþ›°ün}ý')ø ýýýýýýýý ý ýý ýýýýþþþýý ý15÷ }‘ýŸ¶ù ¯Èþ¶ÐþºÖþ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿ¼Øÿ¼Øÿ¼Øþ»×þºÖþ¹Õþ °Èþ }‹ø37öûýýþþþþý566îžžžáãããs÷÷÷.üüüýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýööö ²²²ƒ&''õýýýýMWþ„—þ €•þ$blþ 9@þ#þþþþþýýý û05ügtý# ²þ ´Ïþ¹Ôþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿºÖÿ ¶Ðþ§¾þ¡ús‚ü3ILö üýýþýýýý ü ý;@û]iý O\þ17ýý ýýýýþýýýý ú%LSï{Šú˜¬ù «ÃþµÐÿ¸ÔÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ¹Õþ ¯Èþ'„“ò!Cþn{þš®þ ²Ìþ¹Õþ»×þ¼Øþ»×þ»×þ»×þ»×þ»×þºÖþ¹Õý¯Èý*“£î]hù&(÷üüýýýü û,--ìpqq¸···oâââ5öööhüûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýööö ²²²‚#$$öýýýýýýýýýýýü5:ú gvü€õš®÷­Åþ µÐýºÕþ»×þ¼Øþ»×þ»×þ»×þºÖþ»×þ»×þ»×þ¼Øþ»×þ¼Øþ»×þ¹Õþ¹Ôý µÏþ¤ºø|ŒñOYý'+ýþýýýýýýý ý$59ü-^fú!{Œû¥þ ‘­þ”²þ•´þ “®þ“¯þ”³þ “¯þ’­þ Œ¦þ—ö kzõO[ü!%üüýýýýýýþ þ!ý JPýˆšý ­Çþ¸Óþ»×þ¼Øþ»×þ»×þ»×þ»×þ»×þºÖþ»ÖþµÏþ¥½þ*z†÷0=?ç ýýýýýüüøCDDå‚‚‚¯ÏÎλóòòuúúú ýüüýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýõõõ µµµ€())ôýýýþþþþýýýú#OUû®Éþ´Ïþ·ÒþºÕþ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»Öÿ·Ñþ£¹ú/z…ìJRø%(ô üýþþþþýý ü+0úWeýz‹ýŽ¥ý ‘¬þ“°þ•²ÿ•²ÿ “¯ÿ”±ÿ•±ÿ•±ÿ”°ÿ•±ÿ”±þ ªþ&†™þ(_jú!$ûýýþþþþþþþýý 06ý$juúŸµý¶ÑþºÖþ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¹Ôþ²Êý)’¢î&\dý"%þ þýýýýý ü!!!õ[\\Ö¥¥¥ÉÚÙÙdôóólûûûýýýýýýþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýûûûîî¢¢ž$$$öýýýþþþýýü9>ý#s€üž²÷´ÏþºÖþ»×ÿ»×ÿ»×þ¼ØþºÖþ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ¸ÓÿµÐÿ—¬þ$T\ú"$ô üýýýþþýýý$&úFMýrƒü ‹¤þ“®þ”°þ”±þ”²ÿ•±ÿ•±ÿ”°ÿ”²ÿ•²ÿ•³ÿ •±ÿ“°ÿ ‹¦þw‰õ&LSö!#û üýýþýýýýþþýýýüFMü‰þ¡¸þ³ÌþºÖþºÖÿºÖÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×þ¹Õþ µÏþ¦¼þz‰þ:@ý ýýýýþýýû233éoooÒ···¬æååiø÷÷]üüüýýýþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýûûûîîî³³³·QRRáûýýýþýý ý#:>ò'dnü,”£þ­Åþ ¹Ôþ»ÖþºÖÿºÖÿºÖÿºÖþºÖþ»×þ»×ÿºÖÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿ¹Õÿ¸Óÿ§¾þ~þBJþ üýýýþþýýý ú DNý.r~ý„šþ ‘¬þ”±þ•³þ”²þ“¯þ”°ÿ•²ÿ “®ÿ”²ÿ•´ÿ”±ÿ ’®ÿ “°ÿŒ¤þl{þ5<û ûýýýýýý üüýýþþþýý ý'+ý$QYù,‡•ý«Ãþ¹Õÿ¼Øÿ»×ÿ»×ÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ¸Ôÿ °ÉþŒŸþLSüûýýþþýýü÷BCCã‘‘¸ÕÕÕjóóóûûûýýýþþþýýýýýýþþþþþþþþþþþþþýýýýýýýýýýýùùùëëë§§§›>??èúýýýýýý!ú_kü-“£ü¬ÃýµÎþ»Öÿ¼ØÿºÖÿ»×ÿ¼Øÿ¼Øÿ¼Øþ¼Øþ¼ØþºÖÿ¼Øÿ¼Øÿ¼ØÿºÖÿºÖÿºÖþºÖþºÖþµÐþœ±þZdþ$(þ ýýýþýýýý ü,DHë)juù „›þ¬þ”²þ”²ÿ “¯ÿ”²þ“°þ”³þ”³ÿ•³ÿ”²ÿ”´ÿ ’®ÿ”°þ‘¬þ†Ÿþ*^gþ'+þ ýýýýýýý ü37ú"Ybü)35ú ýýýþþýýý ý16ýuƒþ «Äþ·ÓþºÖþ»×þ»×ÿ»×ÿ¼ØÿºÖÿºÖÿºÖÿ»Öþ²Ìþ™®ýgsý+/ý ýýýþýýý ú*++ïhiiѵµµêêê#úúúýýýýýýýýýþýýýýýýýýýýýýýýûûû ÷÷÷ ïîîŽÕÕÕ~†††ª/00í ûýýýýý ý/1ö,v‚ù¥»ý ¶Ðþ¹Ôþ¼ØþºÖÿ»×ÿ¼Øÿ»×ÿºÖÿºÖÿºÖþºÖþºÖþ¼ØÿºÖÿºÖÿºÖÿ¼Øÿ¼ØþºÖþµÏý «Åý%y†î4:÷ýþýýýýýüü8?ýj|ýƒ›ü Ž©ý“±þ”°ÿ ’­ÿ”±ÿ”²ÿ”³þ“°þ ‘¬þ”¯ÿ ’®ÿ”²ÿ”³ÿ”²þ§þ˜ý @Fý þþþþþýýý ü49ú |’ý ‰£ý~‘ý6`hû+.ú ýýýþþýý ý!%þhuþ ªÂý¶Ñý ºÔþ¼×þ»×ÿºÖÿ¼Øÿ¼Øÿ¼Øÿ»ÖÿºÖþµÐþ «Äþ*‹œþ"@Fý ýýýýþýýüù@@@ì   ™ççç'ûûûýýýýüü ýýýýüü úùùõõõîîîfâááÆÆÆ`ˆˆˆ®:;;éùüýýýýý ýDLý’¦þ ´ÎþºÕþ¼×þºÖÿ¼ØÿºÖÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ¼Øþ¼Øþ¼Øþ¼ØÿºÖÿ¼Øÿ¼ÙÿºÖþ ´Îþ©Àý,‰˜è#>Cêýýýþýýýýü')ögwöЦþ®þ“²þ”³þ ’­þ”±ÿ•±ÿ”±ÿ”´ÿ”±þ“®þ•³þ•³ÿ”³ÿ”²þ ©þ‰¢þ3z†ü'24ô ýþþþýýýý "ý3[cè ˆ þ‘¬þ ‘¬þ “®þ «þ ˆ¢þ[hý!%ý þþþþýýýý&AEë'‡–즽ý ³Íþ·Óþ»×þ¼ØÿºÖÿºÖÿ»×ÿ»×ÿºÖÿºÖþ ´Ïþ©Âþ&]gü !ùüýþþýýý ü;<<ç°°°uòòòýýýüúú¿ýýý öõõLßÜÝÀ»»»u›››ŸmnnÏ9::ëøüýýþýýüý$RYý™¬þ´Ïþ¹ÕÿºÖÿºÖÿ¼ØÿºÖÿ¼ØÿºÖÿ»×ÿ¼Øÿ»×ÿºÖÿºÖþºÖþºÖþºÖÿ¼Øÿ¹ÕÿºÕÿ ¯Èþ”§ý*_gø%'÷ ýýþþþýýýýø'MSõw‰ü†žþ ªþ ‘­ÿ”°ÿ•±ÿ•±ÿ”´ÿ”¯ÿ “®ÿ•±þ•²þ•²þ•±ÿ ’­þ¨þ{ŒýQZýûýýþþýý ýý @Lþu‰þ ‹¥þ“±þ”³ÿ”°ÿ•±ÿ”¯ÿ ’®þ ¨þ$r‚þ>Fþþþýýýýý ýù"NUû|Œý  ¸ý´Îþ¸Ôÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»Öÿ¶Ñþ ®Èýž³û!ˆ™ü@W[äùýþþþþþýù~~~½äää-üüü üüü1úúúÞÝÝÁŠŠŠ¼=??ë÷ ûýýýþþþý ü#%ú'[cüœ°þ¶ÑþºÖÿ¼Øÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øþ»×þ¼Øþ¼ØÿºÖÿ´Îþ£ºþ‘þENýüýýþþþþýýýýýú8>ú Weý r‡þ €˜þŠ¢þ ¬þ‘¯þ‘®ÿ «ÿ‘®ÿ‘¯þ’¯þ’¯þ«þ ˆŸþ!l{ü$8;ö üýýþþýý ü/2û]jý† þ Žªþ”°ÿ•²ÿ•±ÿ “¯ÿ•±ÿ”±ÿ”²ÿ”²ÿ ªÿ •þ\hþ-2þýýýýþýý ý!#ùR^ýŽ£þ§¾þµÎþ¹ÔÿºÕþºÕþ ´Ïþžµþy‰ý&RZñ'46÷üýýþþþþþýússsÊààà2üüüüûûžôôô¶¶¶}566î üýýþþþþþþý59ü)r}ö¢¶ý¶Ñþ»Öÿ»×ÿºÖÿ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿ¼ØÿºÖÿ»×ÿ¼Øÿ»×ÿºÖþ»×þ¹Õþ¶Ñþ¥¼þ †™þU^þ).þ ýýýþþýýýýýýþýýýý+2þ@Hþ/Ybþgyþ s‰þu‡þvŠþ oƒþj~þ o„þt‰þmþTaý*.û üýýþþþý ù#=Cùo}ý ‹¦þ’¯þ“±þ”³ÿ•±ÿ•±ÿ•²ÿ•±ÿ”°ÿ”±ÿ•²ÿ•±ÿ ‘®ÿŒ£þt‡þ?Füüýýýþþýý ý18þ[eþ(…“þ ¶þ ¯Éþ ¨Àû‡›ù Wcý&*ü üýýýþþþþþýü%%%ò‘‘‘¦èèè%üüüýüüòòò ¡¡˜øýþþþþþþþþ9>ý’þ«Ãþ·ÒýºÖþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿºÖþ·Òý ­ÇþŠ›ùWbý &,þ þþþþþþþýûû ýýýþþþþþþ ýýþ*0þ/3þ15þ &+þ!þ%+þ/3þ $)þýýýýþþþþýMWö"{Œ÷ާþ”°þ”±þ“¯þ”±ÿ•±ÿ•±ÿ”²ÿ•²ÿ”±ÿ”±ÿ•²ÿ•²ÿ “¯ÿ”¯ÿ‘¬þ•ý#^iú )/ý ýýýþþþþþ þ(+þ LSþ esýYeù-1õýýýýþþþýýýý ü$$$ñooo¼ËËËTõõõýýýýýýóóó©©©Œ$$$öýýþþþþþþý:?ýuƒû ¶þ ³Îý»Öþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿ»×ÿºÖÿºÕÿ¶Ñþ ¬Åþ$•§ïgsø/3ø üýþþþýýýþ6<ýVbûXfû7;ýýýýýýþþþýýýþþþþýýýþþþþýýýþ-1þZfþ€–þ ªþ”°þ•³þ”±þ•²þ”²ÿ“¯ÿ”±ÿ”±ÿ•³ÿ”±ÿ”±ÿ•±ÿ”±ÿ”±ÿ•±ÿ•±þ ‘­þ ‹¦þmý:Aýü ýýýýþþþþ þ ý ýýýýýþýýý ýúö788êXXXÕÏÎÎÎsòòòüüüýýýýýýøøø ÌÌÌV^^^ßúýýýþþþþý ý%'û!V_ù%†•ó¤»þµÎþºÕþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ·Òþ«Ãþ£þivü#@Dðøýýýþþýý ü&*ýP]þzŽþ §þ ލþzŽþ Udþ18þþýýýýþþþþþþþþýýýþþþþýýýGPþqƒþŠ þ ‘«ÿ•°ÿ”°ÿ”±þ”±þ“°þ”²ÿ”¯ÿ•±ÿ•±ÿ”°ÿ”±ÿ”±ÿ•±ÿ”°ÿ•±ÿ•²ÿ•²ÿ “°ÿ“¯þ Œ¦þzý]jý#@Fý!#ý ýýþþþþþþþþýýýý üù)))ùEEEîeffÓ‰‰‰¡®®®pÍÍÍRéèèU÷÷÷.üüüýýýýýýýýýûûûííí´µµ€deeÛ122öúüýýþþýýýú14ö$[dö!žö ®Æþ¹ÔþºÖÿ»×ÿ»×ÿ»×ÿ»ÖÿºÕÿ ´Îþœ²þlyý=Cüü üýýþþþþ ýú=Aùdsý …þ‘®þ ’®ÿ”°ÿ’°þ ‹¦þs‡þ]mþENý,2ûûýýýþþþþþþýýýþþþþþ03þ!\fþ—þ ªÿ“¯ÿ”°ÿ•±ÿ”°ÿ•±þ”±þ”±þ”±ÿ•³ÿ•±ÿ”²ÿ”°ÿ”°ÿ•±ÿ•±ÿ•²ÿ•±ÿ•´ÿ “®ÿ”¯ÿ”°þ“¯þ“¯þ©þ~“þaoý7>ý ýýþþþþþþþýü ü###úTTTçzzzÆššš¢¿¾¾ÕÔÔÔIæææ)ôôôúùùüüüýýýýýýþþþýýýýýýýýýúúúíííDÎÎμ£££”qrrÄ===åøüýýýýýýüù;@ùw†ý ¥½þ ¶Ðþ ºÕþ¹Ôþ µÐþ¯Çþ*—§þm{þ FPý!$ý ýýýýýýýýý8?ý^lü{ü ‹§þ“¯þ•³þ”²þ”±þ”±þ ‘­þ‘®þ ‹¦þ ‚™þq‡ý+Xaî+68îû ýýýýýýýýýýýý ý+/ýO]þs„þ‡žþ’°þ”²þ•²þ•±þ•²þ•²þ•±þ”±þ ’®þ”±þ ’®þ”²þ “¯þ•±þ•²þ•²þ•²þ“°þ”²þ “¯þ”±þ•±þ•±þ•±þ”°þ ’®þ «þ‡žþ.eoî%(õýýýýýýýýýùCDDߌŒŒ«ÆÆÆ×ÞÞÞIììì'÷÷÷=úúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûû÷÷÷*îîîÜÜÜ2½½½bŒŒŒ¯HHHä÷ûüýýýýü ü !%ýFOý?„Ž×¨¾ó§¾ý9„‘ýKTþ03þ þ ýýýýýýýüûü'Xbý yþ Фþ ªþ”°þ “¯þ”²þ”´þ ’®þ”°þ”±þ ’®þ”±þ“°þ ©ýˆŸùzŽùoý1]eç,>㢣£„ååå%øøøýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþýýýýýýýýýüüüùùùðððÎÎÎRvvv½*++òûýýýþþýýüüýþþþþþýý ý þ7=ýAnuÙ†ü ‘¬û “±þ ’®ÿ”²ÿ”³ÿ”²ÿ•³ÿ ’®ÿ”°ÿ”³ÿ”±þ”±þ”²þ ’®ÿ•²ÿ”±ÿ“¯ÿ•³ÿ ’®þ“¯þ”°þ“¯þ ¦þ]mþýýýý ýNXý …Ÿþ”°þ ’­þ”°ÿ”´ÿ”´ÿ•±ÿ”²ÿ”³ÿ•±ÿ”²ÿ”²ÿ•±þ”°þ”°þ•±ÿ•²ÿ•´ÿ”³ÿ”±ÿ”²ÿ“°ÿ”°ÿ ’®ÿ“°ÿ ”°ÿ “®þ Ž©þ…œþsƒýFNý üüýþþþþþþþþþýøbbb×¾¾¾oëëëøøøüüüýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüøøøèèè$¦¦¦¸UUUæöüýþþþýýýýþýýýý ý!ýBIþetþ ‡¡þ ާþ “±þ”³þ•²þ”³ÿ”±ÿ“¯ÿ”°ÿ•±ÿ ’®ÿ”³ÿ•±ÿ ’­þ”³þ ’®þ•±ÿ•±ÿ•±ÿ•±ÿ”°ÿ”±ÿ•±ÿ•²ÿ•±ÿŽ©þaoþýýýý ýPZý † þ“²ÿ”±ÿ•±ÿ•±ÿ ’®ÿ•³ÿ”°ÿ “¯ÿ•±ÿ“¯ÿ”±ÿ•²þ ’®þ”±þ•²ÿ”³ÿ ’®ÿ“±ÿ ’¯ÿ”²ÿ”±ÿ•±ÿ•±ÿ“±ÿ §þ‡›þ`pþENý$&ø ýýýýþýýýýýýýþýýøMNNÜ›››žÕÕÕFñññúúúýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýûúú ðî¿¿n^^^Ñûýþþþþþþýýýü ü%)ýDMþhwþ‰œþ’¬þ”¯ÿ•±ÿ”²ÿ ’®ÿ•±ÿ”±ÿ “¯ÿ•²ÿ”²ÿ”´ÿ•²ÿ”²ÿ”±ÿ•±þ”±þ”³þ”³ÿ•³ÿ•±ÿ”±ÿ“¯ÿ”²ÿ•´ÿ•³ÿ”³ÿ ªþ_nþýýýý ýPZý † þ ‘­ÿ•±ÿ•±ÿ”²ÿ•±ÿ•±ÿ•±ÿ•±ÿ•±ÿ•²ÿ•²ÿ•±þ”²þ”±þ”²ÿ”³ÿ ’¯ÿ“±ÿ “¯ÿ”°ÿ”¯þ”¯þ Ž©þ €™þdqþEú5owõ$Œœü9qyç7;û ýýýýýýýûHHHߘ™™ÈÈÈCááá0òòòúúúýýýýýýþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýûûûííí¨©©‰788ëýþþþþý ü"$÷8@ý"Waô/~Žè §þ‘®þ“°ÿ”²þ”³þ”±þ “¯ÿ”²ÿ•±ÿ•±ÿ•²ÿ•±ÿ”±ÿ”±ÿ•³ÿ“°ÿ”°ÿ•±ÿ”²ÿ”´þ “®þ•±þ•±ÿ•±ÿ•±ÿ•±ÿ•±ÿ•±ÿ”±ÿ “®ÿ”±ÿ Œ¥þ^nþýýýý ýPZý †þ”°ÿ•³ÿ•±ÿ”±ÿ•²ÿ•±ÿ“¯ÿ•²ÿ•²ÿ “°ÿ”°ÿ•²þ “®þ”±þ•²ÿ”³ÿ “®ÿ “¯þ ªþ†øq„÷%OXîõýþþþýýýý ýþ:?ý)jtñ±ú ±Êþ µÏþ¯Èþ(‹šý:?ü ýýýýýþýûõIIIÞ{{{¸²³³oÞÞÞ6óóóûûûýýýýýýþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýûûûôôôæææ-ÐÐÐP‘‘¦000íýþþþþý)+õ&Zcô”þ‹¤þ ’®þ•±þ”±ÿ “¯ÿ”±þ”²þ“¯þ”±ÿ•³ÿ”¯ÿ•²ÿ•³ÿ”¯ÿ”°ÿ”±ÿ•²ÿ•²ÿ”°ÿ”±ÿ“°ÿ”³þ”±þ”±þ”¯ÿ•±ÿ•²ÿ”°ÿ•²ÿ”°ÿ “®ÿ”±ÿ•±ÿ ލþ_nþýýýý ýPZý †þ”±ÿ”¯ÿ”±ÿ “¯ÿ•²ÿ•²ÿ•²ÿ•²ÿ”±ÿ”±ÿ•±ÿ•²þ”¯þ”³þ “°ÿ ’®þ ªþƒ›þn~üQ[ó)-ó üýýþþþýý ýý7<ýeoþ”§þ¯Èþ·ÒþºÖþ¼Øÿ¸Ôþ°Éþ%ˆ˜þ JQý"&ý ýýýþþýýüø???å~~~³ºººkááá4óóóúúúüüüýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýûûûôôôààà9¸¸¸xŒ¢kkkÆ===éúýþþþþý"#õFNûetþ{Žþ Ž©þ’®ÿ “°ÿ•²ÿ•²þ”±þ”±þ•²ÿ•²ÿ“¯ÿ•³ÿ”²ÿ”±ÿ•±ÿ•²ÿ•²ÿ•²ÿ”°ÿ•±ÿ•²ÿ“¯þ”²þ•±þ”°ÿ•³ÿ”²ÿ”²ÿ•³ÿ”°ÿ”±ÿ•²ÿ•²ÿ ލþ_nþýýýý ýPZý †Ÿþ”²ÿ“¯ÿ”±ÿ•²ÿ•±ÿ•±ÿ•³ÿ”±ÿ”±ÿ•±ÿ•²ÿ•²þ “°þ“°þ ©þ…™þl}ýLVû+0ûúýýýþþýý ý+.ýFMý grýŒœþ©Àþ ·ÒþºÕÿºÖÿ»×ÿ»×ÿ»×ÿ¹Ôþ²Ìþ›¯þo|þ:?ý ýýýþþþýý üôNNNÛ‡‡‡¨´µµtÖÖÖJîîîùùùüüüþþþþþþþþþþþþþþþþþþýýýúúúèèè(¼¼¼u~~~¸HHHæ&&&òù üüýþþþþýý ü "'ý;Bþ Ziþu†þ‹¢þ «þ“®þ”¯þ”²þ•³ÿ•²ÿ•²ÿ”³ÿ“¯ÿ•²ÿ•²ÿ”²ÿ”°ÿ•±ÿ•²ÿ•±ÿ•±ÿ”¯þ”²þ•±þ•²ÿ”±ÿ”±ÿ•²ÿ”±ÿ•±ÿ•²ÿ•³ÿ•³ÿ Œ¦þ_nþýýýý ýP\ý ‡ þ”°ÿ•³ÿ•±ÿ”´ÿ“¯ÿ”²ÿ”°ÿ”±ÿ”±ÿ”°ÿ”±ÿ•²þ’°þˆŸþjyý!LSû ).ü ûýýýþþþýý "û*T[ýŽþ˜­þ©Àþ µÏþºÕÿºÖÿºÖÿ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿºÖÿ ¸ÓþªÁþ‡—þ'PVûü ýýýþþþýýû$%%ðCCCännn᝝‡æææ.úúúþþþþþþþþþþþþýýýüüüøøøããã.¢££‹QQQÛ ÷ üýýýýýþþþþþýýý þþ-1þJSþp€þ Š£þ‘¯ý ”±þ “¯ÿ”³ÿ•³ÿ”±ÿ”°ÿ•±ÿ•±ÿ”±ÿ”²ÿ•²ÿ•±ÿ•±ÿ “®ÿ”³þ•±þ•±þ•±ÿ•²ÿ•°ÿ•±ÿ•°ÿ•±ÿ•²ÿ•´ÿ ’¯ÿ ©þ`oþýýýý ýP[ý †žþ”°ÿ “¯ÿ”³ÿ ’¯ÿ”±ÿ”±ÿ“®ÿ”¯ÿ•²ÿ”²ÿ ’®þ «þ”ý%QYù%(ý üýýýþþþþþý/?Bë}Œü µþ °Êþ¸ÔþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ¹Ôÿ±Ëþš®ý!y†ü AEø ûýýýþþýýý ü÷UVVÞ»»»ôôôþþþþþþýýýýýýúúúðððÎÎÎW³666æøýýþþýýýýýýþþþþþþþþ þ !%ý%LUðxŒ÷ Š£þ ‘­þ“±þ ’®ÿ ’®ÿ•³ÿ•²ÿ”±ÿ”¯ÿ•²ÿ“¯ÿ”°ÿ•³ÿ”²ÿ”²þ•²þ•²þ “¯ÿ•±ÿ•²ÿ•²ÿ•²ÿ•´ÿ•´ÿ ’¯ÿ ‘¬ÿ Ž©þ^nþýýýý ýNYý †Ÿþ”²ÿ”±ÿ”±ÿ”°ÿ•±ÿ•±ÿ•±ÿ”°ÿ”±þ ¬þ ˆ þ.o|ö39û üýýýþþþþþ þ-/þn{ýš¯÷ ³Ìþ·Óþ»×þ¼Øþ»×ÿ»×ÿºÖÿ»×ÿ»×ÿºÖÿ»×ÿ¼Øÿ¼Øÿ¼ØÿºÖÿ¼Øÿ»×ÿºÖþ·Òþ±Êþ™®ü{Œý!69õüýþþþþþýý.//óŸŸŸ¬ïîî²ýýýýýýûûûóóóÞÞÞ<¬­­‚\]]Ì ó ûýýþþýýüý ý+.ý*.ýýýýýþþþþþý ú'+ú+S\ît‡û Š¢þ ’¯þ “¯ÿ ’¯ÿ•³ÿ”±ÿ•±ÿ•±ÿ•±ÿ•±ÿ•±ÿ ’®ÿ”³þ”±þ”±þ”±ÿ•±ÿ”¯ÿ”¯ÿ“®ÿ”°ÿ ’®ÿ”±ÿ”°ÿ ލþ]mþ ýýýý ýNYý †žþ ‘®ÿ”³ÿ•²ÿ•³ÿ•±ÿ•±ÿ•³ÿ “¯þ‰¡þ)qð"FKó!û üýýþþþþþ þ%)þ ]gþ’¦þ ­Åþ·Òþ¹Õþ»ØþºÖþ»×þ¼Øÿ¼Øÿ¼Øÿ»×ÿ»×ÿ¼Øÿ»×ÿºÖÿºÖÿ»×ÿ»×ÿºÖÿ»×ÿ»×þ»×þ¸Ôþ±Ëþ Š þ FQüýýþþþþþþý222öªªª™òññ9üüüøøø(èè蹸¸¸„qqqÔ222îøýýýþýýýý$'úAHùfrý*þ$‰šþ,[cñ#35öý ýýýýýþýýüû"%üT_ý%‚”þ©þ ’°þ “°þ “¯ÿ•²ÿ•²ÿ•³ÿ•²ÿ•²ÿ•±ÿ•±þ”³þ ’­þ•²ÿ•´ÿ”²ÿ”°ÿ”±ÿ”±ÿ”±ÿ”±ÿ•±ÿ ލþ^nþýýýý ýP\ý ‡¡þ“°ÿ”´ÿ ‘­ÿ”³ÿ ’­ÿ”±ÿ ­þ$•þ5Y`ú$&ù ûýýýþýýý ý%(ý%U]þ-‰˜þ«ÁþµÐþ»Öÿ¼Øÿ¼Øÿ¼ØþºÖþ¼Øþ»×ÿºÖÿºÖÿºÖÿ»×ÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ¼ØÿºÖþ·Óþ­Çþ…šþ?JþþýþþþþþýýûTUUßÇÈÈdöööóóóÒÒÒSŒŒŒÀAAAôúýýýþýýý ý38ü euþ‡›ý¢·þ ²Íþ ¶Ðþ ¶Ðþ&¬Áý$’¤þ }þ_ký.1úýýýýýýýýýý%36÷ U`ý0{Šþ Фþ «þ ’®þ•´þ ’¯ÿ”±ÿ”´ÿ•´ÿ”±þ ‘­þ•³þ•±ÿ”¯ÿ “°ÿ•²ÿ•³ÿ”²ÿ”³ÿ”±ÿ•±ÿŽ©þaoþýýýý ýP]ý…œþ“±ÿ”´ÿ”³ÿ ‘¬ÿ ”±þ¨þvˆþ)ELýüýýýýýýý ü!#ù%PWù&ƒ’þ§½þ ¶Ñþ¹Õÿ¼ØÿºÖÿºÖÿºÖÿºÖþ»×þºÖþ»×ÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ¼Øÿ»ÖÿºÖÿºÖÿºÖÿ»×ÿ»×ÿ·Òÿ¯Êþ”ªþ`oþ)0þ þþþþþýýýýúCCC覦¦¨ëééÍûûûÏÏÏShhhÝøüýýýýýý ü!ù#\fþ˜¬þ®Èþ·ÓþºÖþ¼×þ»×þ»×þ¹Õþ¸Óþ¶Ñþ ¬Åþ—ªþ.kuý48ùù üýýýýýýý ü$'ý&IPý$r€ý‡žý ¬þ ‘­þ“±þ ’®þ“²þ ’®þ”±þ•±þ”±þ”²þ•±þ”±þ”²þ “°þ”²þ ’®þ”±þ ªþ^nýýýýý üP\ý †žþ“°þ ’®þ”°þ ‘¬þ†›þAgoþ(,ý ýýýýýýý üù#DJö.è§¾þ µÏþºÖþ¼Øþ»×þ»×þ»×þ¼Øþ¼Øþ¼Øþ»×þ»×þ¼Øþ»×þºÖþºÖþºÖþ¼Øþ»×þºÖþ¼Øþ¼Øþ»ÖþµÏþ£¼þ’þEOþýýýýýýýý û÷+++îaaaé²²²”êèè²ùùù(üüü•••µøüýýýýýü ú;AûJ„è ¯Éý·ÓþºÖþºÕþºÖþºÖþ»×þ»×þ»×þºÖþºÖþ¹Õþ¶Ñþ²Ìý!¡¶õ?owë16ûýýýýýýýýý ýûEMúj{ý}“ý‹¥þ ‘¬þ ‘«þ”³þ”±þ•±þ”°þ“¯þ”²þ “¯þ”±þ”³þ”³þ”±þ”²þ Фþ`nýýýýý üPYý„šþ“±þ”²þ ’­þ•þ,IPþ ýýýýýýý ü ù=Cû6u~ë#ª¿ý ´Îý¸ÓýºÕþºÖþºÖþ»×þºÖþ¼ØþºÖþºÖþºÖþ»×þ»×þºÖþ»×þ¼Øþ»×þ»×þ»×þ¼×þ»×þ¹Õþ·Òþ­ÇþŽ¥þR_þ þ ýýýýýýü û óAAAÞpppΪªª¡ÞÝÝœôôôBúúúüüüýýývvvØûýýýýýýú)V]óŸ´ü ´Íþ¹Ôþ»×þ»×þ»Öþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ ¹Ôþ¯ÈþŒžþYbþ27ý ü üýýýýýýý ýü!8<ý]hýw‰ý…þލþ’¯ý“°þ•²þ•²þ”°þ”°þ•³þ“¯þ”°þ “¯þ”°þ Œ¥þ]nýýýýý ýOYý †žþ”±þ ‘®þ…™þ OWý ýýýýýýý ý 8>ý kvó¡¸ý ´Îþ¹ÔþºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþºÖþ·Òþ§Àþ {Žþ :Eþþýýýýýýý÷BCCÞ………ÀÆÆÆªêéé‹õôôUúúúýýýýýýýýýýýý„„„Çúýþþþþý!''õ$lwû›°þ´Îþ¹Ôþ»×ÿ»×þ»×þºÖþ»×ÿ»×ÿ¼Øÿ»×ÿ¼ØÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ·ÒþªÂþ‹þ$`jü27ý ýýýýþþþýýýû7<ýNZý(gsú xýŠ£þ ’°þ “¯ÿ”°ÿ•³ÿ”±ÿ”±ÿ•±ÿ•²ÿ•²ÿŽªþ]nþýýýý ýOZý … þ ªþ“þ*U\ýûýþþýý ý"&ýS[þ‰ý °Êþ·Òþ¼×þºÖÿ»×ÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿ¼ØÿºÖÿ»×þ»×þ»×þ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ»×ÿ¹Õÿ¸Ôÿ¦Àÿs…þ.5þ þþýýýýý ü&''ó\]]Ö­®®yæææSöõõ“ûúúTýýýýýýþþþþþþýýýýýý°°°‡011óüýþþþý ü+/ýT\ý zŒþ¦»þ ´Ïþ¸ÔþºÖþ»×þ»×ÿ»×ÿ»Øÿ»Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ¼×ÿ¹Õÿ ¶Ñþ§¼þ…–þ[gý7=ýûýýýþþþýýý ü#$ø 7>ü%`lû|þ‹£þ ‘­ÿ”²ÿ”±ÿ”±ÿ•±ÿ”±ÿ”³ÿ ¨þ_nýýýýý ýP]ýƒ›þzþ JQþüýýþýý ü9?û p€ý³þ ´Îþ¹ÕþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿºÖÿ¸Óÿ¥¿þk~þ,4þ þþþýýý ü$$$õPPPà‡‡‡­ÁÁÁoîïïûûûýýýýýýýýýþþþþþþþþþýýýýýýÞÞÞ4‡‡‡±*++ï ûýýþýýý ü$)ý#W`þ€þ&¦ºþ¶ÐþºÖþ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿ¼ØÿºÖÿ»×ÿ»×ÿ»×ÿ½Øÿ%ÁÙÿ¿ÙÿºÖþ¸Óþ ´Îþ ¤½þŒŸþhuú6EGíû ýþþþþþýýý ü û8>ýT`þuŠþ ‹¥þ «þ ”±þ ”¯ÿ“°ÿ”³ÿ ‹¤þaoýüýýýüMYý n}þ@Gþ ýýýþýýû$GMù†—ü ªÄþ·Óþ»×þ»×þ»×ÿºÖÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿ¼ØÿºÖþ»×þ»×þ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿ¶Ñÿ¨Âþhyþ&,þ þþþþýûøMMMÞ‹‹‹§ÁÁÁÐâââ9ôôôûûûýýýþþþþþþþþþþþþþþþþþþýýýýýýööö ÚÚÚ:–——‘IIIãøüýþþýýý ý),ý%W`ý Ÿ³ý¸Óþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼×ÿ¾Øÿ½Øÿ¼Øþ»×þºÖþ¹ÕÿµÑþ ®Çü)›­òx‡üT^ý$'þ ýýýýþþýýý ýþ ,2ýFQû%jvü!ˆšþ¨þ ‘­þ”²ÿ §þaoýýýýý ü.2ü/3ý ýþþþýý ü$AFú&Œœü°Êþ¹ÔþºÖþ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ¸Óÿ­Èÿ¦þ[jþ &þþþþþýü"""ómmm»½½½cäää/öõõUûûû ýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýøøøèèè!½½½bopp¿+++ñûýýþþýýýü%jtú©Áþ ·ÒþºÕÿ»×ÿ»×ÿ¼ØÿºÖÿ¼ØÿºÖÿ»×ÿ»×ÿ»×ÿ¼×ÿ¼Øÿ¼Øþ»×þºÖþ¼Øÿ»ÖþºÕþ¸Óþ ³Íþ¤»þ„”þ Xbþ+/ýýýýýýýýþþý ü "ü ?Dûgvý}’þޤþ Š£þ\kýýýýýý ýýýþþþý ý;@ú!‚ý°Éþ¹Õþ»×ÿ»×þ»×þ¼Øþ»×ÿ»×ÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼ØÿºÖÿ¼ØþºÖþ»×þ»×ÿ¹Õÿ±Ìÿ ž¶þy‹þ@Kþþþþþþýý%&&ôsssÂËËËUòòòûûûýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýûûûóóóÖÖÖ?›››šQQQâ÷ üýýþþý ü13ö,p|õ$°þ­Äþ ²Íÿ ¶Ñÿ ¹Ôÿ¼×ÿ»×ÿ»×ÿºÖÿºÖÿºÖÿºÖÿºÖÿ¼Øþ¼Øþ¼Øþ»×ÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ¸Óþ ³Íþ¤¼þƒ”þR\ý.2úý ýýýýþþýýý ý "ü9?ú5W]ø ^lýFOý ýýýýýýýýþþþ þPXý'‹›ý ¯Èþ¹Õþ»×ÿ»×ÿ»×þ»×þºÖþ¼Øÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿºÖÿºÖÿºÖÿºÖÿ¼ØÿºÖþºÖþ¸Óþ¯Êÿ›´þvŠþMYþ'-þþþþþþýü&''øuvvÌÉÉÉÀòòòOüüüýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþýýýüüüøøøééé"ÄÄÄi”””³XXXßöüýýýý û!#û>CüR]þ aoþ5ˆ–þ=µÈþºÓþ¹Õþ¼ØÿºÖÿ¼Øÿ¼Øÿ¼Øÿ¼Øÿ¼Øþ»×þºÖþºÖÿ¼ØÿºÖÿºÖÿºÖÿ»Öÿ»×ÿºÕþ ´Îþ§¾þýpý MTþ ü üýýþþþýýý ü üý ýýýýýýþþþþþ þbnþ¡·þ ²Ëþ¸ÔþºÖÿ»×ÿ»×ÿ»×þºÖþ¼Øþ¼ØÿºÖÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ»×ÿºÕÿ´Ïþ¥¿þ†›þeuþCNþ!&þþþþþþýýü&''ð}~~¸ÑÐбóòòuûûûýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþýýýýýýûûû÷÷÷ îíí•×××|“““²000ì÷ûýýýý ý þþ!#ü6V[ëD™¦û ²Ìþ·Òþ»×þºÖþºÖÿºÖÿºÖÿºÖþ»×þ¼Øþ¼ØÿºÖÿ¼Øÿ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿºÕÿ¸Ôþ·Ñþ²Íþ¦¼þ‹ý@X\ó'*ûýýýþþþýýýýþþþýýýþþþþ þk{þ§Àþ¶Ñþ»×ÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»×þ»×þºÖþºÖÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿºÖÿ¹Õÿ´Ïþž·þm~þ>Hþ"&þþ þþþþþþýý û)**„®ÚÚÚBöööûûû ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýýýýýýýüüüùùùòòò ÒÒÒNˆ‰‰§>??ãô ûüýýýýý ý!"û%juý ¡·ü­Æú µÏþ¹Ôþ¼×ÿ¼Øÿ¼Øþ¼Øþ»×þºÖÿºÖÿ¼ØÿºÖÿºÖÿºÖÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ¼ØÿºÖÿ¸Ôþ ·Òþ°Êý ¥½þn}ý-1üþ þþýýýþþþþþýýýþþþþ.y…þ°Êþ¸Óÿ¼Øÿ»×ÿºÖÿºÖÿºÖÿ»×ÿ»×þ»×þºÖþ¼Øÿ¼ØÿºÖÿºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»Öÿ´Ðþ˜±þHTþþýýþþþþþýýýû===é   ççç"øùùýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýùùùñññ ÐÐÐT“““¬SSSÖ)))ñù ûýýýýýü$24ó8_eå“ý›±þ ®Èþ ´Îþ·Òþ¹Õþ¼Øþ¼Øÿ¼ØÿºÖÿ¼Øÿ¼Øÿ¼Øÿ»×ÿºÖÿºÖÿºÖÿºÖÿ¼Øÿ¼ØÿºÖþºÖþ·Óþ²Íþ¢·þ'nzþ 4<þ ý ý ýýýýþþþýýýþþþ-NUþ¡·þ·Óÿ»ÖÿºÖÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ»×þºÖþ¼ØþºÖÿ»×ÿ¼Øÿ¼Øÿ»×ÿ»×ÿ»Öÿ»Öÿ¸Ôÿ«Åþ£þDOþ þýýýþþýýýýú%%%ò^^^á¶µµ§ìììúúúýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýüüüùùùðððÒÒÒa™™™ÆcccÌ=>>ç !!ô ûýýýýý ý ýDLýo}ýˆšý›±þ«Ãþ ¶Ðþ¹ÕþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ¼Øÿ¼Øÿ¼Øÿ»×ÿ»×þ»×þ¼Øþ¼×ÿ¹Õÿ´Ïÿ–«þjwþ"OVû9>ý#(ýýýþþþýýýþþþ4:þu„þ¡¸þ°Éþ¸Óÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ¼Øÿ»×ÿ»×ÿºÖÿºÕÿ¸Óÿ±Ìÿ¶þpþ2:þ þþýýýýýý û÷000ïWWW׉‰‰©ÌÌÌsóóóûûûýýýþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýüüüøøø/îííxÖÖÖL³³³‚‚‚´HHHÜó ûýýþþþ ýû15ûDMý#fqýžý¨¾þ ´ÍþµÐþµÐþºÕþ»×þ»×ÿ»×ÿºÖÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×þºÖþ»×þ»×ÿ»×ÿºÖÿ¸Óÿ±Êþ¢¸þ£þx‰þ),ûýþþþýýýþþþþ%(þPYþ#|ŠþŸ´þ ²Ìþ¹Õÿ¼Øÿ»×ÿ»×ÿºÖþ¼ØþºÖþ¼ØÿºÖÿºÖÿ¼Øÿ¹Õÿ¯Éþš²þ”þSaþ&,þ þþþýýý û÷)))íCCCámmmŸŸŸ›ÊÊÊcççç,øøøüüüýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüúúúôôôààà7¶¶¶o‚‚¦MMMÛ###ó ûüýýýýý ýû7;ý%[cþ n}þq‚þ‘ú¡µð ´Ïþ¸ÓþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ ¹Ôþ ±Ëþ†˜þ#&üýþþþýýýþþþþþþ$(þ MTþ}Œþ£¹þ´Ïþ·Òþ¹ÕþºÖþ»×þ»×þ»×ÿ»×ÿ»×ÿ¸Ôÿ§Áþ’þNZþ*1þþþþþýýüôEFFÙtuu°˜™™Œ¹¹¹q×××Híííøøøüüüýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûôôô ååå+ÅÅÅ_‘’’^^^Ê777å÷ üýýýýýý ýýý$'ù#NUì|ŒûŸ´þ ±Ëþ ¶Òþ¹Õþ»×þ»×þ»×þ¼Øþ»×þºÖþ»×þ»×þ»×þ»×þ¼×þ¹Òþ(š«ð@Gù ýýýýýýüýýýýýýýý ý $'ýNVýqù'“¤ú«ÃþµÐþ¸Ôþ¼Øþ¹ÕþºÕþ³Ïþ¤½þt†þ4=þýýýýýýý û&''òkll·¸¸iááá1ïïïööö úúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûû÷÷÷íííÓÓÓG¯°°e|}}¦BCCß÷ ûüýýýýýýü ü$'ûHOýsý—«ýªÂý ¶Ñý¹ÕþºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ¸Ôþ&¥¹ý0[bð ùüýýüûõ?@@èLLLß111ëùüüýýýýý üù!8<ú$bl÷’¦û©Âý µÏþ³Îþ¡»þ –þZiþ+2þ þýýýýýü û011‡¬ÒÒÒHòòòúúúüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúôôô ààà.´µµl|}}²DDDà÷ üüýýýýýýý ý #ý?Fü'fpó‡˜ù¡·þ²Ìþ·ÒþºÕþºÖþºÖþ»×þ»×þºÖþ ²Ìþ}Œþ(,üüýýýü%%%ðnoo¼²²²rÄÄÄO¥¥¥~`aaÉ)**ñ ûýýýýýýýýú=Cûgsý‹Ÿþ ‰ŸþWfþ+2þþþýýýýýý û9::íÈÞÞÞ¤øøøüüüýýýýýýýýýýýýýýýüûû€ýýý ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýúúúñññÛÛÛ8³³³z‚‚¿KKKçö ûýýýþþýýý üù/3ûOYýkzþ ƒ”þ&œ¯þ ±Ëþ µÏÿ ·Òÿ¹Õÿ·Òÿ ›´þJTþýýýýýõmmm½ÍÍÍNððð÷÷÷íííËÌÌP•••¥WXXÖ"""õüýþþþþýý ü ý28ý2:þþþþþþþýýû-..ôhiiÙªªª›áààÃøøø8ýýýþþþþþþþþþþþþþþþýýýýýý7ýýýþýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüùùùñññãââ‰ÇÆÆ™™™ ihhÍ888íûüýþþþýýýýýþ'+þ7<ý P[þ*nyþ2‘¡þ¨¿þ ¥½þgvþ !þþþýýúPPP໼¼wóóóûûûýýýüüüööö ééé!ËËËQ’’’³GGGòüüýþþþýýýýýþþþþþýü ö```ܧ§§‘ÙØØÛïïï#ùùù+üüüýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýûúú÷÷÷îîîäää!ÖÔÔΘ˜˜¸...ò úýýýýýþþþþýý ý þ þ*.ý-1üþþþþýû444¥Çîíížûûûýýýýýýýýýýýýüüü÷÷÷ ëëë ×ÕÕážžžšCCCí÷ ûýýýýýýýþþýýý û344ë”””›ÙÙÙ5ðððùùùüüüýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýüüüüüüùùù ïïïÆÆÆgwwwÜ677ï÷úüýýýþþýýýþýýýýþþýý÷}~~¼âââCúúúýýýýýýýýýþþþþþþýýýýýýüüüùùù òòòààà'®­­„bccÕ'((ô ûýýüýýýýý û%%%óaaaÚµµµxêêêøøøýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýüüü÷÷÷êèèºÁÁÁw±bccÌ999é÷ ûýýýýýýþþþþþþþý ûUVVáÌÌÌšöõõŸýýýýýýýýýýýýþþþþþþþþþþþþýýýýýýýýýûûûôôôKØ×׿”””ºMNNß"""óøù úýýüøEEEè”””¬×××HóóóûûûýýýýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþýýýýýýüüüøøøñññÛÛÛ@µµµœ€€€ÏGGGâ%%%òøúüüýýýþþþýý ü455𯰰žóòò£üüüýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýø÷÷RéèèƒÄÄÄŒŽŽŽ»ijjÈfggÊNOOà***ï###ò777ìghhÏ­­­Žååå/ùùùýýýýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþýýýýýýûûûöõõUååår¿¾¾ž“““°ttt¶`aa¼IJJÎ333ê÷ úüýýýüø===蘘˜©èèè)ûûûýýýþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüûû÷ööcêêê^ÜÜÜF×××L½½½²•––œ‘’’¥®­­ÀÔÔÔVïïïúúúýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýûûû÷ööcñðð<ééé!ååå$ÕÕÕG°°°‚‡ˆˆœabb¶CCCÛ///ë)))õ///ìCCCÜkll³°±±~æææ*ùùùýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûùùùöõõƒññññññ(öõõxúúúüüüýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýüüüúúúöööðññ ááá-ÁÁÁa¥¦¦yœœœ‡¤¥¥zÀÀÀdããã,ôôô ûûûýýýýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýý2ýýý4ýýýþþþþþþþþþþýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýïïïïïïïïïïïïïïïïïïïïïîîîîîîíííêêêèèèçççèèèêêêíííïïïïïïïïïïïïïïïïïïîîî&îíí|îííxîîî8ïïïïïïïîî îííeîîîïïïïïïïïïïïïïïïiiihhhhgg]hhh7hhhihh hhhLhhh      ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿïÞî?ÿàpÞïûßÿÿÿÿÿÿÿÿÿÿàøÿÿÿÿÿÿÿÿÿÿÿÿÿÿñøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(`À €”ëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëëþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýúúúøøø÷÷÷ùùùüüüýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýûûû÷÷÷îîî×××3±±±|¤¤¤”ÊÊÊ[ñññûûûýýýýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþýýýýýýýýýýüüûúúõõõ äää*½½½’„„„ÀAAAàõöIIIå³³³qëêêIøøøýýýýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýûúúööö ðððêééfÖÕÕW²²²vvvº444ìùûýý û===âÅÖÖÖNôôô ûûûýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýüüüûûûôôô ÞÝÝa®­­­|}}ÃbccÒ@@@íö úüýýýþýüøUUUÔ´´´oèèè÷÷÷üüüýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüùùùóóóâáá|¬¬¬vZ[[Ê+++ñú üýýýýýýýýýýýú233éttt¯ÄÄÄ_ìììøøøüüüüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüøøø&ëëë@ÌÌÌ™¡¡¡ˆVVVâô ùüüýýýýýýýýýýýýüûù,--ë}}}³ÌÌÌuíììUùùùüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúñññ×××w’’’´EEEåö ûýýýýýý ý ü(+û%'üýýýýýýýýýüùMMMÙ˜ÞÞÞ4öööûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþýýýüûûôôô ÜÜÜ.   ŠSSSÕö üüýýý ý ü (-ý>Cú'U]ñt…ú‘¤ýŠšý,0ûýýþþþþþþýý ú"""ófffƺººmíííúúúýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýüüüøøøïîîV¸¸¸m___Äó ûýýýý ý úJPúx‡û˜­þ¦¾þ¬Äþ ´Îþ·Òþ°Éþiwýýýþþþ þ þ þ þýýýù888뜃éééøøøüüüýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýüüüùùùëêê‚ÅÅÅ`ˆˆˆ¾111ëùýýýý ý #'ýBKý)€Žý§¾ýµÏþ·ÒþºÖÿ¹Õÿ»×ÿ»×ÿµÐþx‰üüýþþþMZþƒ—þyþ@Iþþþýü û%%%ìxyy¶ÌÌÌSôôô üüüýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýüüüöööÝÝÝ8”””£777ñùüýýý ü#&ü U]ûŽ¡þ­ÆþµÐþ¹ÕþºÖþ¼Øÿ»×ÿ¼ØÿºÖÿ»×ÿ¶Ñþ„•û "ûýþ þ=Gþ™±þ³Îþ³Îþ¡¹þgwþþýýýüøYYYÚÅÅÅ[ïïïúúúýýýýýýþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýøøøîîîÀÀÀbiiiÇ&&&ðüýýý ý ý#KQñ„”ý§¾þ¶Ñþ¹Õÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ»×ÿ»×ÿ»×ÿ¸Óþ—¬ý05ýýýþWdþ©Âþ¹ÕÿºÖÿ·Òÿ©Ãþl~þ$*þ ýýýýøHHHÝœ–èèèøøøýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþýýýüüüööö7ÞÞÞ8‹‹‹ %%%ð úýýýýý>Có‰œþ­Æþ¶Ñþ¹ÔþºÖþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÕþ £ºýBJýýýý\hþ ¬Åþ»×ÿ»×ÿ»×ÿ¹Ôÿ°Ëþ€”þ&-þýþýý ûõ†††°ÜÜÜ5÷÷÷ ýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýüüüøøøëëë}ÇÇÇ‹tttÆ ðûýýý ý&(øbn÷Ÿ´ôµÐþ¹Õÿ»×þ¼ØþºÖþ»×ÿ¼Øÿ»×ÿ»×ÿºÖÿ»×ÿ»×ÿ¼Øÿ»×ÿ¹Õþ ¤¼ýIQüýý ýU`ý ªÄþ»Öÿ»×ÿ»×ÿ»×ÿºÖÿ®Éþ nþ#þþþþýü !!ôpqq»ÔÔÔhôóóJûûûýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýùùùîîîÍÍÍJwwwË111óúüüýý ýKTý!’¤ý ®Èý·Òþ»×þ»Øÿ»×þ»×þ¼ØþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ¹Ôþ ¦¾ýGOýýý ýOYý §ÀþºÕÿ»×ÿ»×ÿ»×ÿ»×ÿ¹Ôþ«Åþs‡þ08þþþþýüùNOOßµµµ~ððð>ûûûýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýüüüøøøæææ!ŸŸŸ“LLLØøýýýý ý/1ûzŠý¥½þ¶ÐþºÖþ»×þ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖþ ¤½ýGOýýý ýMVþ ¨¿þºÕÿ»×ÿ»×ÿ»×ÿ»×ÿºÖþ¹Õþ¯Êþ’©þYhþ"'þ þþýýúGGG㿾¾»óòòPüûûýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýüüüøøøììì4ÈÈÈ¥}}}«###ò úýýþ ýý">Cü$Œ›ý ²Ìþ¸ÔþºÖÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»Øÿ¹Õþ ¤½ýJRü ýý ýHQý §¾þ¹Õþ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ¹Õþ¶Òÿ¬Æþ‘¨þEPþþþýý ûKKKç¼¼¼¾íìì:úúúýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüùùùöööéééÉÈÈŽ‘‘‘³>>>èúüýýýý8?þo~ýž²þ ´Îþ¹Ôþ¼Øþ»×þ»×þ»×þ»×þ»×þ¼Øþ»×þºÖþ¼Øþ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ»×þ ¨ÀýPYú üýý6;øœ²ü¹Ôþ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ»×þµÐþ¤½þo‚þ*0þ þýýûAAAç›››’äããXööö(üüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüùùùïïïÒÒÒD¨©©‡www´???ä÷ûüýü ü&(ühtþ ´þ²Ìþ¸Óþ»Öþ»×þºÖþ¼Øþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ¼Øþ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ±Êý!lxýýýü!#ùˆ™ü¸Óþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ¸Óþ®Éþ‡þN[þþ ýü ú%%%ðwvvп¿¿nééé÷øøüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýöööÖÖÖf˜˜˜´HIIÚôúüýýýý ýDJôŒŸþ ®Çþ¸Óþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þµÐþ‚”þýýý ü€’ý·Òþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþºÖþµÑþ§Áþuˆþ4=þ ýüýú222ñ€­ÑÑÑ?óóó úúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþúúúÚÚÚ>eeeÈô ûýýýýý ý "%ý-dký µù¶Ñþ¹Õÿ»×þ»×þ»×þ»×ÿ»×ÿºÖÿ¼Øÿ»×ÿºÖÿ¼Øÿ»×ÿ»×þ¼Øþ»×þºÖÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×þ·Òþ‰œþ þþýü€“ý¶Òþ¼Øÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ¼ØÿºÖÿ»×ÿ»×ÿºÖÿ¼Øÿ¸Ôÿ°Ëþ”«þMZþþýýüõJJJÒª««…ÞÞÞ„òòò úúúýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþööö“÷ýýýýý ü),û QYû"žþ ¯Èþ¸Óþ¹Õþ»×ÿºÖþ»×þ»×þ»×ÿ¼Øÿ»×ÿºÖÿ¼Øÿ»×ÿºÖÿ¼ØÿºÖþ»×þ¼Øþ»×ÿºÖÿ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×þ¶Ñþˆ›þ þþý ýý¶Ñþ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ¼ØÿºÖÿ¼Øÿ»×ÿ»×ÿ¼ØÿºÖÿ¶Ñþ§Àþs…þ19þ þýý û÷Z[[Ý©©©ˆååå*øøøýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþòòòxyy¤ ùýýý ý%(ù"U]ü Š™ü¦¾þ ¶ÐþºÖÿºÖÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ·Óþ‰œþ þþýü‘ý¶Ñþ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¸Ôþ¯Êþ£þEPþþþýý ú/00ïŽŽŽ§ççç‡ûûûýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþððð nooª úýý ý tþ  ¸þ®ÈþµÐþºÕþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ¸ÓþŠþ þþýü€‘ý¶Òþ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿºÖÿºÖÿ¹ÕÿºÖÿºÖÿ»×ÿ»×ÿºÖþ¹ÕþµÐþŸ¹þVcþþþýýü)))ò¯¯¯€÷÷÷ ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþñññ rrr© úýý'*þ œ²þ·Òÿ¹Õÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿºÖÿ¼ØþºÖþ»×þ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ»×ÿ»×ÿºÖÿ¼Øþ»×þ»×þ¼ØÿºÖÿºÖÿ»×ÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿ»×þ·Òþ‹žþ þþýü‚”ý¶Òþ»×ÿ»×ÿ¼ØÿºÖÿ»×þ¹Õþ¹Õþ¹Õÿ¸Ôÿ¶Óÿ¶Òÿ¶Òÿ·Óÿ¹ÕÿºÖÿºÖÿºÖþ»×þºÖþ·Òÿœ²þJRþþþýýù………¶óóóýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþôôô‹ŒŒšøýýý#¡þ·Óþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖþ»×þºÖþ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ¸ÔÿºÖÿ¸Ôÿ¹Õþ¹Õþ¹Õþ¸ÔÿºÖÿ¸Ôÿ¹ÕÿºÖÿ»×ÿºÖÿ»×ÿ¼Øÿ»×þ·Òþˆ›þ þþýü‘ý¶Ñþ»×ÿ»×ÿºÖÿºÖÿ¸Ôþ¶Òþ³Ïþ®ÊÿªÇÿªÆÿ¨Äÿ¨ÄÿªÆÿ­Éÿ³Ïÿ·ÓÿºÖþºÖþ»×þºÖÿ·Òþ©Àþ(}‹þ ýýþ úrss·ñññ ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþøøø¿¿¿föýýým{þµÏþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þºÖÿºÖÿ»×ÿ¸ÔÿµÑÿ³Ïÿ³Ïÿ³Ïÿ²Ïþ²Îþ²Îþ²Îÿ²Îÿ³Ïÿ´ÐÿµÑÿ·Óÿ¹ÕÿºÖÿ»×ÿ»×þ·Óþ‰œþ þþý ü‘ý¶ÑþºÖÿºÖÿºÖÿ·Óÿ²Îþ©Æþ£¿þŸ¼ÿœºÿ›¸ÿ›¸ÿ›¸ÿ›¹ÿŸ»ÿ¦Âÿ¬Éÿ´Ðþ¸Ôþ»×þ»×ÿ»×ÿ¹Õÿ ¨Áþ+/úýþ úopp¸ððð ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþûûûßßß>777ëýý ý OZþ ¯ÈþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þºÖþºÖÿ¸Ôÿ¶Òÿ¯Ëÿ©Åÿ¦Âÿ¤Àÿ¥Áÿ¢¿þ¤Àþ£Àþ£Àÿ¤Àÿ¥Áÿ¤Áÿ¨Äÿ¬Èÿ°Ìÿ´Ðÿ¹ÔÿºÖþ·Òþ‰œþ þýýüý¶ÑþºÖÿ·Óÿ³Ïÿ¬Èÿ¥Áþ›¸þ—´þ–´ÿ ”°ÿ”°ÿ”²ÿ•³ÿ•²ÿ–³ÿ™¶ÿŸ¼ÿ«Çþ´Ðþ¸Ôþ»×ÿ»×ÿºÖÿªÄþ04ùýþ úooo¸ððð ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýëééacccÎ ûýý9>û ³þºÕþ»×þºÖþ»×þ»×þ»×þ»×þ»×þ»×þ¹Õþ¸ÔþµÑþ±ÍþªÇþ¢¾þœ¹þ™µþ™¶þ™¶þ™¶þ™¶þ˜¶þ˜¶þ™¶þ™¶þ™¶þš·þ¹þ¡½þ¨Äþ®ÊþµÐþ¶Òþ‹þ ýýýü“ý³Îþ²Îþ¬Èþ¥ÁþŸ»þ™¶þ–³þ”³þ«þ‡¢þ ~–þ|“þ ‚™þªþ“°þ•²þ—µþž»þ§Äþ°Ìþ¶Òþ¹Õþ¼Øþ«Äþ/2ùýý úopp·ððð ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüðð𠆆†¬ùýý-1ý“¨þ¹Ôþ»×þ»×þ»×þ»×þ»×þ»×þ¹Õþ¹ÕþµÑþ±Íþ©Åþ¢¾þœ¹þ˜µþ•³þ–´þ–´þ—³þ—³þ—³þ•³þ—´þ˜¶þ—¶þ–³þ–²þ•±þ˜´þ›·þ¢¾þªÆþ¯Ëþ†™ý ýýý  ý~þªÅþ§Ãþžºþ™µþ•³þ“°þ­þ †Ÿþ lþO]þ=Gþ9CþCNþ `qþ ~–þ­þ”²þ–³þš¸þ£¿þ­Éþ´Ðþ¸Ôþ«Äý/2ùüý úooo¸ïïï ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýòòò ‘’’žøýý+/þ’¦þ¸Ôþ»×þ»×þºÖþºÖþ»×þºÖþµÑþ±ÍþªÆþ£¿þœ¸þ˜´þ–³þ•²þ”±þ ‘«þ…œþ€•þ ~’þ”þ–þ‹ þ ˜±þ›¶þšµþ™¶þ˜µþ–³þ–³þ˜´þŸ¼þªÆþ†™þ ýýý )-þ }‘þžºþ›·þ–´þ•±þ‘®þ ˆ¢þsˆþUdþ09þþ þ þþ#*þ@Kþkþ… þ‘°þ•²þ˜µþžºþ§Ãþ±Íþ§Áþ03ùýý úooo¸ððð ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýóóó ‘‘‘÷ýý*/þ‘¥þ¸Ôÿ»×ÿºÖÿºÖÿ¹Õÿ¶Òÿ²Îÿ«Çÿ¤Àþœ¹þ˜µþ–²ÿ•²ÿ”±ÿ ªÿ“þ Tbþ ;Eþ 07þ-4þ 06þ 18þ8?þ GPþ\gþ"x‡þ¦þ“®þ’­ÿ’¯ÿ–²ÿ¹þ©Äþ„˜þ þýþ Iþ^oþ |“ÿ §ÿ™¶ÿ ›´þ5;þýþ úooo¸ððð ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýóóó “““›÷ýý*/þ¥þµÐÿ´Ðÿ®Êÿ¥Áÿ›¸ÿ—´ÿ–µÿ•±ÿ—³þ ‘©þm}þ FýzŠý&(úýþ úopp¸ððð ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýóóó ‘’’›÷ýý17ü‰Ÿþ ¼ÿ›¸ÿ˜µÿ–´ÿ•±ÿ•¯ÿ‰¢þiyþ17þþýþþý ý=Dý)‚þ ¦½þ²ÌþµÐþ¶ÐýµÏþ °Éþ¨¿ú  ·ý“§þr€þNVþ/3üý ýýýýþþþþþþþý ýHNü¢ý ¯Èý·ÒþºÖþ»×ÿ»Øÿ»×ÿ»×ÿ»×ÿ¹Ôþ ¯Çþþ<@û ýýýý ýý ýýþ úpqq·ððð ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýóóó ‘‘øý ý;Fþ †žþ˜´ÿ–´ÿ–³ÿ”±ÿ ަþnþ AKþþýýýý ý/2ý"lxüŸµþ´Ïþ¹Õþ»×ÿ»×þ»×þ»×þ»×þ»ÖþºÕþ¸ÓþµÏþ¬Äþ”¨þu…ý>Dü ýýýþþþþþþþýü%t€þ¤»þ³Îþ¹Õþ»×þ¼Øÿ»Øÿ»×ÿ»×ÿ»×ÿ»×ÿºÕÿ µÎþš­þeqý%(üýýýýýýþ úppp·ððð ýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýóóó žøý þ ?Jþ †žÿ•³ÿ•±ÿ ލþq…þ LYþ%+þþþýý üø^iõ”©þ ¯Éþ¸Òþ»×ÿºÖÿ»×ÿ¼Øþ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿºÖþ·Óþ ¯Èþ#¡û$?Dò ýýýþýýýýýþý ý "ýBJþ‚•ý ¨Àý¶ÑþºÕþ¼Øÿ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿºÖÿ¶Ñþ ¬Æþ†šü,0ù üýþþþþ ûsttºíîîüüüýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþýýýóóó ’’’÷ý ý 5>þ†œþ ’«ÿ{þR^þ%+þþþýýý ý>Dü0Žé ®Èþ·ÒþºÕÿ¼Øÿ»×ÿ¼ØÿºÖÿ»×þ¼Øþ»×þ»×ÿ»×ÿ»×ÿ ¸Ôþ±ÊþŸ¶ürû-1ú ýýýýýýý!$ýýýýýýý ýüFOû‡™ö ¨ÀþµÏþºÖþ»×ÿºÖÿ»×ÿ¼Øÿ»×ÿºÖþ¹Õþ²Íþ¢û=Bó ýýýþþ üXXXæÍÍÍ“óòòPüüüýýýþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýóóó ‘‘‘œ÷üý%)ýiwþ[hþ .2þþ ýýýý ü "ú_kü ¶þ ´ÎþºÕþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÕþµÐþŸ´þ#p|ö=Cûüýýýüü ü5;ücpý uŠþ[hý05ü ü üýýýý ý#'ø V^ô“ú §¿þ´Ïþ¹ÕþºÖþ»×þ»×þ»×þ»×þºÖþ ³Íþ “¤ù"9<òüýýýýù]^^ÑÁÁÁŠòòò úúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýòòò ‘‘÷ýý ý ý þýýýýü&*õMTø)‰—õ ¯Èý·ÒþºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖý¶Ñý¨Àý‚“þ9?ýüüýýýý û 9=új{ýˆžý «þ‘­þŽ«þ…œþl|ý>F÷!÷ üýýüü üýCIýþ«Âþ¸Óþ»×þ»×þ»×þ»×þ»×þºÕþµÐýš®õ!]fôùüüýüú@@@ã§§§~ßßß3öõõ>üüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýóóó ‘‘žøýýýýýýý ý!$ú rƒü ö§¿ü µÎþºÕý¼Øþ»×þ»×þºÖþ»×þ»×þ¼Øþ»×þ¼Øþ¸Ôþ¶Ðý®Çþ&‹›íGOü "ý ýýýýý ý%(ü1epü–ü ªþ“±þ”³þ“¯þ”²þ’®þ ©þ„›úk{øAJü üýýýýý þ  ýalý ¢ºþ´ÏþºÖþºÖþ»×þºÖþ»×þºÖþ ·Óþ ªÂþ,wƒó /1ñ ýýýý ú'''ðfggÆÍÌÌ­ðððHøøø üüüýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþýýýüüüïïï8Ž¢øýýþýý ü ý PXö”¨÷°Ëþ·Òþ¹Õþ»×þºÖþ»×þ¼Øÿ»×ÿ»×ÿºÖÿ»×ÿ»×ÿ»×ÿ¸Óÿ¯Éþ‡™û'?Cî û ýýþýýý$(ýZgû „œþ ©ý ‘­þ”±þ•±ÿ“¯ÿ”²ÿ•±ÿ”±ÿ­þ…û.hsû!"ùýýýýýýþý ý14û~ý §¿þ ´ÏþºÖþ»×þ»×ÿ»×ÿ»×ÿºÕþ ³ÍýŸ³ýWaý ýýýüýú344샃ƒµÐÏЭððð4úúúýýýþþþýýýýýýþþþþþþþþþþþþýýýýýýûûûòòòÈÇÇ—QRRÛ ûýýýý üDI÷'wƒý§¿þ·ÒþºÕþ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿºÖþ¹Õþ¶Ðþ¢¹þo~þ*-ü ýýýþý ý!$ûNWýs„ý§þ“°þ”²þ”°þ”±ÿ”¯ÿ”²ÿ•²ÿ “¯þ ‘­þƒ™þHSúúýýýý ý ýýýýýý !ýMVû$‡—ý ®Çþ¹Ôþ»×ÿ»×ÿ»×ÿ»×þ»×þ·Óþ«Ãþr€þ),û ýýýýüùRRRÛ¬¬¬±ççç1øøøüüüýýýýýýþþþþþþýýýýýýüüü÷÷÷ééé%¯¯¯tIIIßúýýý ü-0út„ü¤¹ý ³Ìþ¹ÔþºÖÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿºÖþ·Óþ ®Èü‹üCJýýýýýý ý "ý IQòu…û Фþ ‘®þ“°þ”²þ “°þ”±þ”³ÿ”²ÿ”³ÿ ’­þ §þp‚ý8>ý ýýýýü ü:Aû!\hü37ý ýýýýý ý&)ým{þ ¨Áþ·Òþ»Öþ»×ÿ¼Øÿ»×ÿ»Öÿ¹Ôþ¯ÉþŒžþHPý ýýýýý û,--îxxxÀÑÑÑIôôô üüüýýýýýýüüüùùù ôóóFééé.ÄÄć~~~¸...ê ûýýý ýCIý¡ú °Êþ¹Ôþ»×þºÖÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ¹Ôþ ³Íþ±îYeù"%ø ýýýýý û@Jûr‡þ ‰¤þ ‘®þ“¯þ”¯ÿ•²ÿ”³þ “¯þ“¯þ”²ÿ”±þ ¬þŒ¢þcpù!ýþþýý ý úGQö ~•ý ‹¥þ‚—ý_mü.3ý ýþýýý ýWbûœ°ñ ±Ëþ¸ÓþºÖþ¼Øÿ»×ÿ»×ÿºÖþµÐþ¤ºþn{ýüýýýýüø`aaÍÔÔÔ@ùùùýüüRûúúîììÉÉÉe¦¦¦ŸmnnÃ444æøüýýý ý!PWý³þµÐþ¹Õþ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×þ»×þ»×þ¹Õÿ·Òþ §Àþ$s€ú59ó üýýýýýü$=Aõs†ü ‡ þ «ÿ“¯ÿ”°ÿ”³ÿ”°ÿ”±þ”±þ•±þ“¯þ ¨þvˆýFNü üýþýýý 19ýi{üˆ¡ü‘®þ”¯þ’®þ ©þ~”þHQþþ þýýý ü/3öepü—­ý¯Êþ¸Óþ¼×ÿ»×ÿ»×ÿ·Òþ ­Æþ—«û(ajó ôýþþýýõ˜˜˜œõõõ ýüü7ñññ<­­­²?AAèø ûüýýþýù%bkü¤»þ¶Ñþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»Öþ¸Óþ°ÊþŽ¢þXcý üýýýýýýýý û/5û Yhþ r‡þ„šþ Œ¨þ ©ÿ §ÿŽªþ¨þŒ¨þ †žþetý'*ù ýýýýýüU`ü šþ ªþ”°þ”°þ”¯ÿ”±ÿ“±þ’¯þ ˆ¡þk{þ39ýýýýýý ü17û p€þž³þ²Ëþ¶ÑþµÐþ ¤¼þn|ý ?Dôüýýþþýýùˆˆˆ³ôôô ýüüZããã/dddÂúýýþþþý(+ýsü©Àý¶Òþ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ¼Øÿ»×ÿ¹Õþ¸Ôþ±Ëýš¯ý`mý+/þýýýþý ýüýýýýýý !%þ6<ý HTþT_þUaþ EQþ HTþT_þ =Fþ ýýýþþ ý'+÷(bnø Š¢þ“®þ“¯þ•±þ•±ÿ”²ÿ”±ÿ•²ÿ•±ÿ“¯ÿ ލþ |’þ OYû ýýýýýýý:?þ%hrþ•ªþƒ”ö ENûý üýýþýýý ú899å¶¶¶t÷÷÷ýýýâââ/bbbÆ úýþþþþýOWýŽ¡ü ®ÈýºÕþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÕÿ¹Õþ ±Ìþž³õjwú#%ù ýþþýý þ'+ýJTú=Düýýýýþþýþþ þ þ þ ý ýþýýýþþ8>ýv‰þ Œ¦þ”°þ•±þ•²þ”±þ•±ÿ”±ÿ”±ÿ”±ÿ•±ÿ”±ÿ•±þ’®þ Œ§þl~ý,1ü ýýýýþþ þýý ýýýýýý üö233ì___Ó¸¸¸ïïïûûûýýýðð𢢢–'((ò üýýýþý ý26ü*wƒð¡¶þ ´Îþ¹ÕþºÖÿ»×ÿ»×ÿºÖÿºÕÿ³Îþ¡¸þq€ýý[gþ„˜þ ªþ‘¯þ ’¯þ“°ÿ”±þ“¯þ•²þ•²ÿ”°ÿ•±ÿ”²ÿ”²ÿ”¯ÿ’­þhyþ ýýýür‡ý’­þ”±ÿ’®þލþ(w‡þ?Fý ýýýýü ý!ù#W`ñŠœý­Åþ¸ÓÿºÕÿ»×ÿ»×ÿ»×ÿ¼Øþ»Öþ¼Øþ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ»×ÿºÖÿ¶Ñþ©Âþwˆþ7?þýþþýýüû---ô„……¼ááá ùùù&€€€·öüýýý ü$'ú6dkï ¢¹þ³Íþ·ÒþºÖþ»Öþ»×þºÖþ¸ÓþµÐþ ¬Åþ ›²ý:gnì&)ü ýýýýýýý%)üWdüxý ‰£þ ªþ ’®þ”±þ•±þ“¯þ”³þ “¯þ”³þ”³þ”°þ «þhxý ýýüüqƒý ‘®þ“¯þ ‹¤þ$^jþý ýýýý ý  û#KQó%Žžú ªÂû µÏþ¹Õþ»Öþ»×þ»×þºÖþ»×þ»×þ»×þ»×þ¼Øþ»×þ¼Øþ¼Øþ»×þ·Óþ¯ÉþޤþEPþý ýýýý üö=>>áyyyËÀÀÀ£éèèDøøøüüü[[[à úýýýü&(ö!ƒ’ø ­Çý·ÒýºÖþºÖþ»Öþ»×þ»×þ»×þ»×þ»Öþ»Öþ¸Òý °Éý¢ýU_ý(,ü ýýýýýý ý #üIQüo€ýƒšý Ž©ý ‘­þ”±þ”±þ”±þ”±þ”°þ”¯þ«þfxý ýýýüqƒý¬þФþ!coýýýýýýý?Gý‚“÷ «ÄýµÐý¹Õý»Öþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ¸Ôþ¬Çþ u‡þ)0þ þýýüüú677æŽŽŽ±ÓÓÓ®îíír÷öö ûûûüüüýýýwww¿øýýýý#%ùgsý™¯ý °Êþ·Óþ¹Õþ»Öþ»×þ¼Øþ»×þ»×þ»×þ»×þ»×þ»×þ·ÒþªÂþžþS\ý #&ýüýýýýý ý "ý9?ùUbü~“ý ‹¥þ ¬þ”²þ“¯þ•±þ”³þ‘®þfyý ýýý ýp„þ† þ ^jý!#üýýý ü #ücpý›°þ³ÍýºÕþºÖþ»×þ»×þ»×þ»×þ¼Øþ»×þ»×þ»×þ»×þ¼Øþ»×þ¼Øþ»×þºÖþ·Òþ¨Ãþq„þ#(þþýýü û!!!ô\]]Õ°°°zêêê&øøø7üüüýýýýýýýýýýýýÀÀÀ`PPPÙùýýýýý *0ý"nzþ™­þ´Îþ¹Õþ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×ÿ»×ÿ ¼×ÿÀÙÿ »Öþ¶Ñþ«Äþ¢þamû"14ôüýþýýýý ü,0ûQ[þwþ ‹¦þ ‘®þ “°þ “°þ «þiyþ ýýýügwýT^ý ýýýý ü5:ù’ý°Êþ¹Ôþ»Öþ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿ»×ÿ»×þ»×þ¼ØþºÖÿ»×ÿ·Óÿ«Æþctþ#þþþýüõ___ͧ§§ÄÝÝÝ<óóóûûûýýýýýýþýýþþþýýýýýýðððÇÇÇPcccÐô úýýýý ý04ý#¢ý µÐþ¹Õþ»Öÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ »×ÿ½Øÿ ¼Øÿ»×þ¹Õþ·Òþ ¯Éýš­÷z‰ý37þþ ýýýýýý ý "&ý@Hú'tƒýŠ ý ¨þ Ž©þhxý ýýý ý-1û ýþþý ý'*û'Š™ü ±ËþºÕþ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þºÖþ¸Ôÿ±Ìþ–®þ[jþþþþýü%%%ñ†††¤ÛÛÛ5òòò9úúúýýýýýýþþþþþþþþþþþþýýýýýýüüü÷÷÷æææ   ˆGGGàøüýýý ý?Dø‘¤û­Åþ µÐþ¹Ôÿ»Öÿ¼Øÿ»×ÿ»×ÿ»×ÿ¼×ÿ¼×ÿ»×þ»×þ»×þºÕþ¸Óþ´Îþ©Áþ‘þAHý  ý ýýýýþýý ý9@ü`nüu†ýWeý ýýýýýýþþý7<ü‘ý ²Íþ¹Õþ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¼Øÿ»×ÿºÖþ¸Ôþ°Êþ—¯þ qƒþ3:þ þþþýü///ò˜˜˜ºçææ5ùùùýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýþþþýýýúúúïïïÄÄÄ_€€€ºAAAçùüýý û7;ù^jý q‚þ+—¨þ·Îþ ·Òþ»Öþ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿºÖÿºÕÿµÐþ ¶þ|‹ýVaþ,/ýüýýýýýýü#'ü!$ýýýýýþþþþFOþ”©þ ±Ëþ¸Ôþ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¹ÕÿµÐþ©Ãþ‹ þhxþ8Bþþþþþý û,,,í–––°æåå˜ùùùýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþýýýüüü÷÷÷îííYÓÓÓa}}}¯666àøüüý ýý$'û1bjô™¬ý ²Íþ¸ÓþºÕþ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿºÖÿºÖÿ¸ÔþµÐþ ¯Èþ³þ*u€÷@Hü ý ýþþýýýýþýýýþþ þU`þ ž·þ¶Ñþ»×ÿ»×ÿ»×ÿ»×ÿ»×þºÖþ»×þ»Øÿ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ·Óþ¦¿þs…þ:Bþ þþþþþýý û===⨨¨}êêêúùù üüüýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþýýýýýýýüüøøøëëëÅÅÅL}}}­>>>èø üýýýü49ü!p|ó–©ö ¬Åþ·Ñþ¸ÓþºÕþ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ¹Ôþ³Îý §Àþ~ýDIþþ ýýýýýþýýýþþ JQþ ·þ¶ÑþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿºÖÿ·Òþ¨Âþ`pþ þýýýýýýüùPPPá¹¹¹nðððûûûýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýüüüøøøìììÑÑÑ@ŽŽŽÄQQQØ(((ðùýýý û #ûMWý|ý˜­ý ªÁþ µÐþ¹ÔþºÖÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ¹ÕþµÐþ ¨Àþ€‘þOVý48üýýýþýýýþþGOþ£þ­Åþ·Òþ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ¹Õÿ·Óÿ¯ÊþŒ¢þLXþþþýýýý ú!!!óEEEᇇ‡ªÐÐПòòòûûûýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýüüüùùùðïï]×××C«««dddÉ(((ï úüýý ýû27ýPYý‚’þ¦¼þ®Èþ²Ìþ·ÒþºÖþºÖÿ»×ÿ»×ÿ»×ÿ¼ØþºÖþ»×þ»×ÿ¹Õÿ¶Ñþ«Âþ–ªþn}ý üýþýýýþþ þ05þbmþ—«þ ±Ëþ¹Ôþ»ÖþºÖþ»×þ»×þ»×þºÖÿºÖÿ±Ëþ’©þk}þ/6þþþýýúö788ç^^^Ñ›œœ’ËËËXëëëøøøüüüýýýþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýüüüúúúóóóÝÝÝ.³³³okkkÅ000åõ úýýý ý ý27þ9AýWaó‘¤ô ­Åþ¶Ðþ¹ÔþºÖÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿºÖÿ ¸ÓþªÂüR]ý ýýýýüýýýþþþ+0þepý œ²ý«Ãý¶Ñþ¹Õþ»×þºÖþ·Óÿ«ÆþxŒþ07þþþþýýøDEEÛ›œœ‹ÈÉÉIÞÞÞ-ðððøøøüüüýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûöööìììÌÌÌO‘‘‘ŒQRRÎõ ûýýýýý ýúT]ý„–ý¥¼þ ´Îþ¹Ôþ»Öþ»Öþ»×þ»×þ»×þºÖþ±Êþ3t~ñ úýýý ù011í<<<åõüýýýý ý "ù)LRú‡™ù ¨Áþ ³Íþ«Æþ ¦þ_oþ!&þýýýýýùghhÆËËËPñññùùùûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûøøøðððÔÔÔ9’’’œLMMÛö ûûüýýý ý #ýHPøv„öš¯ý ­Æþ ³ÌþµÐþ¸ÔþºÖþ·Òþ•©ý49üüýüùOOOÔ´µµjÊÊÊ?›@AAâöûüýýü ü%(úT]ý‘þfwþ-4þþýýýü û#$$ónooÑÕÔÔ¨öööûûûýýýýýýýýýýüüdýýý ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüùùùððð×××F¤¤¤ÂaaaÇ444çøýýýýý ýý +1ýGOý"fpþ †™þ™­þ«Äþ §¿þ Tbýýýý ûGGGßÃÃÃYóóó ÷÷÷ïïïÏÏÏQ‰ŠŠ£@@@çúüýýýý ý ýýþýýý û%%%òaaaͳ³³³äääy÷÷÷üüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýúúúòòò@ßßß2ÂÂÂ_”””Ù;;;èùýýýýþþ ýý !þ04þFOýFPýþþýü(((ò¤¤¤Ëîîî>ûûûýýýüüüøøøêêêÈÇÇ—‰‰‰¹111ñø üýýýýýýýüú233ꥥ¥ÛÛÛ7ôôô>ûûûýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýûûûø÷÷ñññÕÕÕE………ÕJJJà%%%ñúýýþýýýýýýýýýùyyy¿çççMúúú üüüýýýþþþýýýüüüøøø ðððÜÜÜ-   ¯HHHâ÷ üýüýý û())òttt¾ÉÉÉTñññ úúúýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýùøø ìììQÐÐÐL£¤¤ƒnooÊ222ïú ûüüýýþþýý úLLLáÊÉÉ·÷÷÷=ýýýýýýýýýþþþþþþþþþýýýýýýúúúñññSÄÄij¹AAAå344í###ôúøBCCꘘ˜ âââ,÷÷÷üüüýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýüüüùùùóóóæææxÁÀÀ|ˆˆˆ¿aaaÅGHHÏ000çö úüýüøGGGß¶¶¶wñðð!üüüýýýýýýýýýþþþþþþþþþþþþþþþýýýüüü÷ööëêê€ÐÐÐQÄÄÄ_¢¢¢³€­–––ÂÈÉÉ]ìììúúúýýýýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþýýýýýýüûû÷÷÷!ñññ@éééààà+ÃÃÃZ™™™~nnnµDDDà:::îNNN×}~~¤ÇÇÇVñññûûûýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýüüüûûûøøøôóóSðððóóóSùùù üüüýýýýýýþþþþþþýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþþþþþþþþþþýýýýýýóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóòòòóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóòòòóóóóóóóóóóóóóóóóóóóóóòòòòòòñññíííééé ÝÝÝÍÍÍ+ÉÉÉ0ÑÑÑ(áááìììñññóóóóóóóóóòòòóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóòòòòòòòòòòòòòòò/òññaóóóóóóóóóóóóòòòóóóòòòóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóòòòóóóóóóóóóóóóóóóóóóóóóóóóóóóóóóòòò‡‡‡‡‡‡†††………………†††‡‡‡‡‡‡‡‡‡‡‡‡;‡††s‡‡‡‡‡‡‡‡‡‡‡‡D‡‡‡‡‡‡       ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ ÀŒ  ÀŒÃÿÿÿÿàÿüÿÿÿÿÿÿÿÿÿü8ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(H `TÖÖÖüüüüüüûûûüüüûûûüüüûûûüüüûûûüüüüüüûûûüüüûûûüüüûûûüüüüüüûûûüüüûûûüüüûûûüüüûûûüüüüüüûûûüüüûûûüüüûûûüüüûûûüüüûûûùùùúúúúúúüüüûûûüüüûûûüüüüüüûûûüüüûûûüüüûûûüüüûûûüüüüüüûûûüüüûûûüüüûûûüüüûûûüüüüüüûûûüüüûûûüüüûûûüüüûûûüüüûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúõõõìììØØØ:ÛÛÛ7òòòúúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûû÷÷÷òòò ßßß*²±±™kll³777âHHHÜ®®®tìëì6øøøüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûöööíìì3ØØØ9ÂÁÁŠ•–––UUUÐò úû ú+++ëÃÕÕÕ9óóóúúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûööö éèè/¿¿¿QrrrÓAAAä+++îø úýýýýü÷LMMÔ¬¬¬mâââ#öööûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúôôô!àààd¸¸¸dlllÖ%%%î ùüüüüýýýýýü úôWWWË»»»_éééU÷÷÷ûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüöööæææ³³³“YYYÔ ô ùýüýü û)-ü=Cý ýýýýýýý ù&''ïzzzµÏÏÏEñññ úúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüøøøïïïÄÄÄOhii¹$%%ð ûýý ý üELülzý‘ø›²ü£ºþ^jý ýýýýý ýüüù?@@⨨¨yëëëùùùüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúñññ1ÔÔÔVŽŽŽ¾...ë øûü ý !%ýMTý•§ú¯Éý³Íý¶Ñý¸ÔýµÐýƒ•ý üýýýTbþbqý.5þ ýüúñ‚ƒƒ ÚÚÚ5öööüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷éé騩©>??èùûý ü #üü™®ý±Ëþ¶ÑýºÕþ»×þ»×þ»×þ¸Óþ£ü ûý ýQ^þ¨Âþ°Ëþž¶þHTýýýü÷bbbÌÎÎÎDòòò úúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúóóó ÑÑÑ?cccÄõúüüüU`û–ªù°Êý·Òþ»×þ»×þ»×þ»×þ»×þ»×þºÕþ ¡¹ý 06ýýý kzý²Íþ»×þ¶Òþ©ÃþZiþýýü ù777è«««zïïïùùùüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûöööèççU°¯¯±:;;à øýýü7=÷‡˜ó°Êý·Òþ»×þºÖþ»×þ¼Øþ»×þ»×þ»×þ¼ØþºÖþ ¥¾þ;Aüýýfsý³Íþ»×þºÖþ¸Ôþ«ÅþTbþýýýú&&&ñ•••’èèèTøøøüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüùùùïïïÁÁÁZZZZÛ÷ ûü ü #'üjvý¤»ýµÏýºÖý»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ §¿ý;Aýý ý_lý²Íþ»×þ»×þ»×þ¸Óþ¦Áþ_nþ$þ ýýûöpppÃáàà`÷÷÷üüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûôôôâââLŒŒŒŸ&''î ùýý ýþýýýýý(,ýDLý duþ wŠþˆ þ•°þ¢»þkzýýýO\þ‹§þ‘®þ‰£þk€þ>Iþ#ý ý ý ý ý ý ý*2þ]mþ ‡Ÿþ’®þ—´þ›·þoýýü788ã×××)úúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûâââ(MMMÒû ý[fý±Ìþ¹Õþ´Ðþ«Çþ ½þ™¶þ–³þ”°þ ©þqƒþ >>àüýý ü&*üalý¢¸ú´Ïý¹Õþ»×þ»×þ»×þ»×þ»×þ»ÖþºÖþµÐþ £ºþdoü ø ýüý ü%*üS^ý ‚šýªþ’®þ”±þ”±þ”±þ ’®þ Фþet÷$'ûýýýýýý ý#&ü huýš¯ý´Îþ¹Õþ»×þ»Öþ¶Òý­ÅþzŠý )-ý ýüüöVWWÚµµµëëë@øøøýýýýýýýýýüüüûûûøøøïïïÅÄÄORRRÔùüý üT_ü–©û±Êý¸ÓýºÖý»×þ»×þ»×þ»×þ»×þºÖý·Òý¯Èý‰œüÓÓÓL•••ŒGGGÜöúýüüJSý¡ï ¦¾þ„–ýPYý %ý ýýü ý ýUbý—ý«þ“°þ”±þ’¯þ¬þŠ¥þwˆõO[ú16óú ýýý ý%*÷ Tcý€–þ Žªþ’°þ”±þ”±þ•²þ”±þ”±þ”±þ•²þ”²þ”±þ”±þ•²þ“°þ ¨ý ™þ#JRô ýýýýü000뜄âáá[ððð÷÷÷ úúúýýýýýýýýýýýýýýýüüüùùùòòò ââ⣣£y?@@Üùüü ý ú(,úý ýýýýý>Eó#z‹ê Œ§ý‘®þ”²þ”±þ”±þ”²þ”±þ”±ý ‘­ý ¨ý ‡Ÿü •ý GSý ýý #(ý xýŒ¨ý‘®þ”²þ”±þ”±þ”±þ”±þ”±þ”±þ”²þ”±þ“°þ “¯þ ‘­þ ©þƒ™ý!`lý"%ú üüýýýû```ÄÔÔÔ4òòò ûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúóóó ÓÓÓPvvvÊôýýüýüý ü ýENýq…ý ‰£û ­ý”±þ”±þ”±þ”°þ”²þ”±þ”±þ•²þ”±þ“°þ”±þªþUbý ýý,2ý ‚›þ“¯þ”±þ”±þ”°þ”±þ”±þ”±þ”±þ”±þ“±þ“±þ’®ýŽªþ€–ýWeý.4üýýüý ü ýüüö^^^ž¾¾`íîîùùùûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüöööÖ××=LMMØûýüü ü#&ôQ\ü vŠþ ‰£þ‘®þ“¯ý”°þ”±þ”±þ”±þ”±þ”±þ”±þ”°þ”±þ”±þ”°þ”°þ ©þUbþ ýý,2ý ‚šý”°þ”±þ”±þ”°þ”³þ”±þ”°þ”±þ“±þ“¯ýªý‡ŸúXgû %+ýýýýýü;@ø"s€ú%[cô üüü ù122狌ŒÎÎÎAîîî÷÷÷ûûûýýýýýýýýýýýýýýýýýýûûûøøøîîîÎÎÎEYYYÌüýüùU`ùyŽù Œ¦ý «þ”±þ”°þ”±þ”±þ”±þ”°þ”²þ”±þ”±þ”±þ”±þ•²þ”°þ”±þ”¯þ©þUbý ýý,2ý ‚™þ”¯þ”°þ”²þ”±þ”±þ”±þ“°þ“°þ Žªþƒœýdt÷/5÷ûüý ýý38ýv…ý¦½ü ²Ìý ¬Äþmyü$(ý ýüûö111æ{||ªÌÌÌGîîîøøøûûûýýýýýýüüüúúúðððÇÇÇQ®EEEÛöüýü û4:ü_oý–ý Ž©ý‘­ý”±þ”±þ”±þ”±þ”²þ”±þ”±þ”±þ”±þ•±þ•²þ•²þ”±þ”±þªþUcþ ýý,2ý ‚šý“¯þ”²þ”±þ”²þ”±þ“¯þ¬þ„›ýbpý28ûüüüü üGOýw‡þ ¶þ´Îþ¸ÔýºÖþ¹Ôþ ±Êþ¢ýELýýüüû÷:;;â~«ÅÆÆYòòòýýýüüüöööççç ¡¡;;;åøüüýýüýýý'+ýR_ý—û ¨ý’¯þ“°þ”±þ”±þ”±þ”±þ”±þ•²þ”±þ”±þ”±þ”±þ”²þ ©þUcý ýý,2ý ‚šþ“°þ”±þ”±þ “®þ‘®ý Š¥þqƒü39üüýýýý5;ú}ø¨¿þµÐþ¹Ôþ»×þ»×þ»×þ»×þ¹ÕþµÐþ¤»ýr€ü .4ü ýýüüøLLLàÙØØ^øøøïîî)ÆÆÆSopp²óúüý ý !ý:@ý%)ûüýýý ü',ùWdö}“ý ¨þ’¯þ“°þ”±þ”±þ”±þ”²þ”°þ”±þ”°þ”±þ”°þ©þTbý ýý,1ý ‚šý“°þ”±þ“¯þ «ý|üJSöûüüüý,1þkxý £ºýµÏý¹Ôý»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ´Ïþ¥¾ý gwýýýýü û9::ë×ÖÖgÞÞÞ+‘Á555íùûý ý 05ücqý þ¤ºþ“¥ûjwýAIý ü üýý ü,0üý~“þ Œ¦þ’®þ“±þ”²þ”°þ”±þ”±þ”²þ”±þ”±þªþUcý ýý-3ý ‚šþ“±þ ­þŒ¥þj{ý(+û ýýü ü'+ùamýš®þ ²Ìþ¸Óþ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ¹Õþ³Îþ›²þ\jþýýýü ü!!!ôˆˆˆÀíííM{{{¶÷üýü û#\eöž´þ±Ëþ·Òþ¹Ôþ¸Óý³Îþ ¨Áýˆ›ý%INóý ýýý ý"%ýNYüyý ‰¤þ ªþ“°þ”±þ”±þ”¯þ”²þ”±þŽ©þUcý ýý,2ý ˜þ‘¬þ†žþ"MVý ýýý ý "ü!Yaõ—«÷ °Êþ·Òþ»Öþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ·Óþ¬ÆþyŒþ19þ ýýü ú$$$ðXYYתªª°êééDøøøJJJã úýü úo{ø ¨ÀýµÐýºÕþ»×þ»×þ»×þºÖþ¹ÕþµÐý ¬Åý~ý@Hýý ýýý ý ýDLümý„›ý Žªý“°þ“°þ”±þ”°þ©þSbý ýý+1ý –ý…þLUý ýýýýHQý’¦ú±Êý·ÒýºÕý»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ·Ñþ¦ÀþZhþþýüûõ[\\Ⱦ½½§êêêkôôô úúúüüü«öûý ü04ün}ý¤»þ ´Ïþ¹Õþ»×þ»×þ»×þ»×þ»×þºÔþ ¶Ðþ©Áþ{ý@Hü ü ýýý ý ü*/û^lü˜þŽ©þ‘®þ“°þ Ž«þUcý ýý*.ýr†þDKý ýýý!ûqýªÁþ¶ÑýºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»Öþ¶Òþ¤½þP^þýýü÷AAAä“““žÝÝÝ2õõõ üüüüüüýýýýýýããã#§!!!ñ úüýý04ý!…•ý³Îý¹Õþ»×þ»×þ»×þ»×þ¼×þ¾ØþºÕþ´Ïþ¬Æý!¢õVaü  ý ýýüü ý !ýMYü}ý Š£ý Š¥ýUaý ýýü,0ý ýýýü#†–ü²Ìý¸Ôþ»Öþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ¸Ôþ±Ìþ•­þCOþ ýýü󃄄¡ÛÛÛKòòò$ùùùüüüýýýýýýýýýýýýùùùððð ¹¹¹bOOOÜ÷ üü ý-2ùŠœû«Ãþ²Ìý·ÒþºÖý»×þ»×þ¼×þ¼×þ»×þºÖþ·Òý±Ëþœ°ý\hý %)üýýýý ý üBKüeqüBKý ýýýýý ý )-ýý²ÍýºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ¹Õþ¶Ñþ°Ëþ›´þgwý%*ý ýýû ö‘‘‘Àêêê.ùùùüüüýýýýýýýýýýýýýýýýýýýýýûûûõõõááá*­­­«JJJÚö ú ü ü 06ý T\ý,œ­ù±Ëý·ÒýºÖý»×þ»×þ»×þ»×þ»×þºÖþ·Òþ²Ëý ¶þ|ŒýBHúý ýýýü ý ýýýýý ý 6=ý —­þ³Îþ¹Õþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þ¶Òþ¨Ãþ}‘þJVþ#)ý ýýü ú$$$ŸˆìëëPùùùüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûôôôááá#¡¡¡xNNN×õ û ý ü !ücoû˜«ö ­Æý¶Ðþ¹ÔþºÖþ»×þ»×þ»×þ»×þ»×þ¹Õþ´Ïþ «Åý •«ýQZýý ýýýýýýýý27ý™¯þ³ÎþºÖþ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÕþµÐþŸ¸þIUýý ýýüüù<<<é´´´mïïïúúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúóóóááá"­­­ deeÇ,--îø û üüGOýx‡ü˜®ý ¯Éþ´Ïý¸Òý¹ÕýºÖý»×þ»×þ»×þºÖþ¶Ñþ ¯Éþ ¥þ^iý 7>ýýýýýýý-3þ‚”þ«Äþ¶Ñþ¹Õþ»×þ»×þ»×þ»×þ¹Õþ¶Ñþ¬Æþ…™þ5>þ ýüû ùö:::è|}}¯ÏÏÏvòòòûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûõõõçççÁÂÂWuvv¬000ì÷ û üý $'ýS\ý u…þ†™ù «Ãú´Ïý¸Ôþ»×þ»×þ»×þ»×þºÖþ·Òþ ­Åþ ý  üýýýüý ý ýGNþŠ›þ¯ÈýµÐþ¹ÕþºÖþ¸Ôþ²Íþ£þKWþ"ý ýý ú)))êkll´   ƒÒÒÒ@ííí÷÷÷üüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüüüüöööìììÎÎÎ<”••‰JKKÑõ ûý ýýû=Dúy‰ý¢ºþ ²Íý·ÒþºÖþºÖþ»×þ¹Õþ¬ÃþKQó ýü ú###ñ---ìøûý ýý=Cøy‡û ¦¾ý¯Éþ¡ºþv‰þ*0þ ýýüúHIIÚ¹¹¹^êêêôôôúúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûøøøòòòÜÝÝ)žžž…OOOØô ùûüüü4:úeqù Ž¢ý£ºþ°ÊþµÏþ±Ëþy‰ýüü ú>>>ܯ¯¯iÇÈÈA‚‚¢344çùüüü ü>Eýetý:Cýþýü ú óbccÓÍÌ̘ôôôûûûüüüýýýýüü<ýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúòòò ÝÝÝ]­­­|rrr»666ëùüüý ý!ý38ýQ[ýuƒý ‘ý *0ýýü(((ð«««’ððð öööìììÆÆÆPzyyÈ111èùûýý ýýüüöRRRͬ¬¬ŠãããSöööûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúõõõîîîÌÌÌMxxxÆ888çõ úüüý ý ýýýüù€¸êééAúúúüüüûûû÷÷÷îîî,ÌÌÌA‡‡‡­566éùûüü ú...ì‚‚‚¤ÛÛÛ-ôôôúúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüøøøííí4ÏÏÏCžžžZZZÚ'''ð÷ ùûýüüøRSS×××׈øøøýýýýýýýýýýýýüüüøøøïïï4ÅÅÅ‹wwwÊRSSÓ888è***ïVVVÕµµµoìììùùùüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüûûûùùùóóóãããO¾¾¾¢££r}~~¦HIIÒ(((êó'''ë]]]ÆÊÊÊQõõõ üüüýýýýýýýýýýýýýýýýýýûûû÷÷÷îîî:âââ+ËËË„ÃÃÀàßß?ôôô ûûûüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïîîîíííêêêçççããã ÚÚÚº»»I¦¦¦_¹¹¹KÜÜÜéééíííïïïïïïïïïïïïïïïîîîïïïîîîìììììììììîîî8ïïïïïïïïïïïïïïï ïïïïïïïïïïïïïïïïïïïïïïïïïïïïïïjjjhhhggghhhjjjkkk!kjjAlllkkkkkk   ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ*•( €©Uÿÿÿàÿþ3ÿÿÿÿÿÿÿþ?ÿÿÿÿÿÿÿÿÿÿÿ(@€ Bééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééééþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþýýýüüü÷÷÷ôôôöööúúúýýýþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýúúúôôôèèè;ºººY~~~¨›››’çççøøøýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýüüüøøøòòò êêê5ÖÖÖB   ˆIIIßò÷ômnn¹ÒÑÑnòòò ûûûýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüööö ìììÉÉÉZ~~~ÄPPPÛ---ñøûüýü ú666墢¢|âââôôô úúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûõõõåååN¿¿¿ZqppÓ%%%ðùûüüüýýýüúöJKKÕ®®®jæååJöööûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüøøøëëë¼¼¼saaaÐ!!!ó úýý ý ü+/úFMü!ýýýýýý ûòiii¿ÇÈÈMñññ úúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýúúúñññÑÑÑQqqq­(((ì úü ýüAHûq€ý‹žýŸµü ¦¿þn}ý ýýþ þ þ ý ü ù233èìììøøøýýýþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýûûûöööÞÞÞ]888éøü ý üIRýƒ”ý ªÃý´Ïþ·Óþ¹Õþ¶ÑþŠžý üý þP]þŒ¢þgxþ $þ üûòqqq·ÜÜÜ/öööüüüýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýùùùïïï ¿¿¿[QRRÕø ü ýýDK÷Œžý­Çþ¶ÑþºÕþ»×þ»×ÿ»×ÿ¸Ôþš¯ý #'ýýþ“¨þ³Íþ°Ëþˆžþ+2þ ýüøUUUÑÃÄÄTñññ ûûûýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþýýýýýýûûûôôôßßßU†††›ó úýü/5÷„–ú®Èþ¶Ñý¹Õþ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖþ ¥½ý39ýý  ý ›±þ¹ÕÿºÖÿ´Ðþ•­þ-4þ þý ú...í¬¬¬síííùùùýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýýýýýýý÷÷÷ççç«««—PPPØøü ý #ýbmü£ºüµÐþ¹Õþ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×ÿºÖþ ¦¾þ6=ýý ý •¬þ¹Õÿ»×ÿ»×þµÐþޤþ09þþý û !!ñŠŠŠÁççç0ùùùýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúòòò!ÓÓÓþý ýýýý ý"þM[þ}•þ«þ˜´ÿ˜±þ)-þý())êÊËË;úúúþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýïïï mmm¹ úýsƒþ³ÎþµÑÿ«ÇÿŸ¼ÿ™¶þ•±þ ‘¬þ yþ DOþþ þý ý ý ýýýý þþ)/þKTý@Gý ýþ Zhþ j}þ?Kþþ ý ü -3üm{ý‹žýcpü "&ý ýý9Cþ btþ …þ ”¬þ ',ýý(((ëÊÊÊ;úúúþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýïïï ooo¸ úýrƒþ«Æþ§Ãÿ›·ÿ•²ÿ”°þ Š£þYgþ#þ ý ý ý+0þS^ü^hýS]ü7<ö "üý ýýýýýýþþþ þ ýü ]gõ  ·ý²Íþ´Ïþ °Êþ”§þ?Fýý ý þ5=þt„ý üý())ëÊÊÊ;úúúþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýïïï nnn· úý p‚þš¶þ—´ÿ“°þŽ©þ oþ18þ ý ý ý!$ühuþ¡¸þ°Êþ±Ëý°Êþ ªÂü ¡¸ý‹þbmý28ýüüýýþþþý$'üƒ”ý «Åý·Òþ»×þ»×ÿºÕþ¶Ñþ §Àþ"cný  ý ý ý ý ýý)))êÊËË;úúúþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýïïï lmm¹ úý q„þ‘®þ©þtˆþAKþþ ý ýûS^ú™­þ±Ëþ¸ÓþºÖþ»×þ»×þºÖþ¹Õþ´Ïþ «Äþ’¦ü7<øüýýýýýý ýR\ý –«ý°Êþ¸Óþ»Öþ»×ÿ»×ÿ¸Ôþ ±Ëþ“¨ý6=û üýýý(((ìÉÉÉDøøøýýýþþþþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýïïï noo¸ úýfvþzþ JVþþ ýý ü38ý!‚‘ô¯Éþ·Òþ»Öþ»×þ»×þ»×þ»×þ¹ÕþµÏþ¤ºý}û -3ü ýüýý05ý )/ýýýý ý ü_lø˜­ü¯Éþ¶ÒþºÖþ»×þºÖþµÐþŸ¶üCJõ üýýö‘‘‘¶çççJùùùýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýïïï mnn¹ ú ý &*ýþ ý ýü&*ù\f÷ ¡¸ýµÐý¹Õý»×þ»×þ»×þ»×þ¹Õý¶Ñý ¬Åý“ý7=ûüüüü5;ühwý …þ ƒœþeuý8?ú ûüü ü $'ùU_ý—«þ²Ìþ¹Õþ»ÖþºÖþ¶Ñý¡·ûT]ô ûüûô}~~¤ØØØ3óóó!úúúüüüýýýýýýýýýýýýýýýýýýýýýýýýííí mmm¹ úýýý ý%(ù sƒü›±ú °Éý·Òþ»×þ»×þ»×þ»×þ»×þ·Óþ ­Æý„”÷BJøý ýý ý )0ýdqý…ý¬þ’¯þ“¯þŽ©þ ‚›ü`mû üýýý ý$(ýrý «Ãý¶ÑþºÖþºÖþ·Óþ ­Æþ"|Šó).ý ýû÷BBBݬ¬¬±èçç:÷÷÷üüüýýýýýýþþþþþþýýýüüüöööÖÖÖaJKKÙûýý úS\ý˜­ü²Íþ¸ÓþºÖþ»×þ»×ÿ»×ÿ»×þ¹Õþ´Ïþ žµþQ[ü û ýý ý "%ýVbýƒšý«þ’¯þ”°þ”²þ’®þ Œ§þfvû#&ûüýý ýýýý CKýˆ™ý°Êþ¸Ôþ»ÖþºÕþ³Îþœ²þJSýýý üôcddÓÉÉÉyòòò úúúüüüýýýûûûööö ííí,ÇÇÇVKKKÙùü ý6;ùŽ¡ý ¯Èý·ÒþºÖþ»×þ»×þ»×þ»×ÿºÖþ¶Ñþ®Èý|ø */ý ýýýýQ\ø~•ý ©þ’®þ“±þ”±þ“°þ­þ ‡ þMXýýýü üDó…—ü ªÄþ¶Ñþ¹Ôþ¶Ðþ ¨Áý€ü$&õýýû$$$ï¾¾¾^øøø=ÙÙÙ[MNNÜ÷ ûüý ýcmû ªÃþ·Òþ»×ÿ»×ÿ»×ÿ»×ÿºÖþ¸Ôý´Îþ  ·þgtþ $ü ýýýýý ü +1ý Veýr…þ |“þ |“þz’þ z‘þZgý ûýý ý;Bü {’ýŽªþ“®þ”±ÿ’¯þŽªþyŽþý s‡ý‡¡þ vŒý HTý %)üüýýýýýýý ý/4ýoþ Œ¤þ’®þ”±þ”±þ”±þ”±þ”±þ”²þ”²þ’®þ¨ýzýLWý üýýýýúøBBBässsÔ¦¦¦yÒÒÒ8îîî$ùùùüüüöööåääO³³³jiii¹###ð øû ü !û`mýž²òž³ýn{þ :Aþýüü ü%)ýcuý †žþ¬þ’°þ­þŒ¦þ €—ýboõ>E÷!$ø üýý ý*/ø [ký‚™þ¬þ“¯þ”±þ”±þ”±þ”±þ”±þ”²þ”±þ”±þ”²þ’®þ Š¥ýwŒý04öüýýü)))í“““‹ÚÚÚZîîîõõõùùùüüüýýýýýýýýýûûûõõõìììÍÍÍ>eee»ö ûý ý!ù ü ýýý ý ýNWñ…œð Ž©þ“°þ”±þ”±þ”±þ“°þ“°þ«þ ‹£ý ƒ›ý dtý ýý *0ý ~–ýŽ©þ’°þ“°þ”±þ”±þ”±þ”±þ”²þ”±þ”±þ’¯þ ‘­þ ލþ€–ýU_ý ü ýýýýýRSSÎÑÑÑ6ñññ ûûûýýýýýýýýýýýýýýýþþþýýýýýýüüü÷÷÷ëë룣£®(((íüýýýý ü #(ýS^þ –þ ¨þ’­þ”°þ”±ÿ”±ÿ”²þ”±þ”±þ”±ÿ”±þ”²þ‘®þ r†ýýý4:ý † þ”°þ”±ÿ”±ÿ”±ÿ”±þ”±þ”±þ“±ÿ“°þ‘®þލþ|“þOZþ!%ü ýýýü ü üýøJJJ׳³³mììì÷÷÷üüüýýýýýýýýýþþþþþþþþþýýýýýýøøøãããabbÆüþýü,1ú_mö ‚šþ©þ‘®þ”°ÿ•±ÿ”°ÿ”±ÿ”±ÿ”±þ”±þ”°þ”±ÿ”±ÿ”±ÿ ‘­þq…þýý4:ý‡ þ”±ÿ”±ÿ”±ÿ”²ÿ”±þ”°þ“°þ‘¯þ Ž©þ ‚™ûVcö ý ýý ýý6;ùz‰ú¢øDJü ýü û"""ïrrr¨ººº\ééé÷÷÷ûûûüüüþþþþþþýýýûûûóóó ÚÚÚ4£££|DDDÜüþý6;öo‚þ ‡¡þ ªþ“°þ”±þ”±ÿ”²ÿ”±ÿ”±ÿ”±ÿ”±þ”±þ”±þ”±ÿ”±ÿ”°ÿ’®þr†þýý4:ý‡¡þ“¯ÿ”±ÿ•±ÿ”±ÿ”±þ’®þ Žªþ€•ýYfü(-÷ üý ý ý9?ýr€ý§¾þ³Îþ´Ïþ£ºý^iý  ý ýü ù!!!ðjjj¸½½½Yçççöööýýýýýýøøøëë룣£DDDßõ úýýý ý #ýFPþq„ý ‹¥ý‘­þ”±þ”±ÿ•±ÿ”±ÿ•±ÿ”°þ”±þ•±þ”±ÿ”±ÿ”±ÿ’¯þq†þýý4;ý‡ þ”±ÿ”±ÿ”±ÿ”¯þ «þ ‡¢ýYeý'+ü üýý ý??äø üý ýý !%ý;Cþ^jþ R\þþýõ£££­ððð öööíííÉÉÉMvvvÕ"""ô úýü ýýüøAAAÚ®¯¯oæææKöööüüüþþþýýýýýýýýýþýýýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýüüüøøøòòò ààà)”””¼MMMÙ!!!òúüüý ýýýúpppÇêêê?úúúýýýüüüøøøïïï ÖÖÖC}}}Í*++î÷ùù$%%ñ}}}®ÛÛÛ-ôôôûûûüüüýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýþþþþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýúúúôôôæææ½½½ŒrrrÄEFFÕ+++æõ ù ùöMNNÚÚÚÚ\øøøýýýýýýþþþýýýýýýùùùííí:ÇÇLjtttÄkkk̲²²sìììùùùýýýýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþþþþýýýýýýöööööööööööööööööööööööööööööööööööööööööööööööööööööööööôôôðððèèè-àààÌÌÌ8£££dqqq¦cccµ‡ÔÔÔ0îîîöööööööööööööööööööööõõõòòòíííééé.ééé.ïïï óóóöööööööööõõõöööööööööööööööööööööööööööööööööööööööööööööõõõ§§§§§§¦¦¦¤¤¤   œœœ›››žžž£££¦¦¦§§§§§§§§§¦¦¦D¦¦¦7§§§§§§§§§¦¦¦+§§§ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(0` €%———————————————————————————————————————————————————————————————————————————ôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôñññìììéééíííòòòôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôôþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþþþþýýýüüüúúúöööïïï ÛÛÛ7   {hhh»«««qíììùøøýýýýýýýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüøøøððð ÖÖÖJªªª‚yyy­777âö÷ðtttµÙÙÙ+óóóùùùýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷îîîÏÏÏQ€€€°.//çö ù ûüüûø566ß”••„âââ8ôõõûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúñññ ÒÒÒ6wwwº%&&ðøüü.3ùOYü8=ýýýý û÷JLLÓ¸¹¹]ïïï ùùùýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýûûûôôôààà>–––š---èùû #'üamü˜­ý ©Âþ­Æþ ˆœýýý#þDOþ#ý ùò‰‰‰Žäää÷÷÷ýýýýýýýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþýýýùùùïïï ¹¹¹\EEEÜ÷ ü "&úguý £»ý²Íþ¸ÓþºÖþ¹Ôþ›²þ !ý ýoþ¨Áþ“©þ/8ýüöaaaÀÔÔÔ6ôõõûûûýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýýýýýýýýýýûûûôôôàààS¢ô ú ûT_ö¢ºþ³Îþ¸Óþ»×þ»×ÿ»×ÿºÖþ ¦¾þ ,1ýý~þµÐþµÑþ ¹þ2;þ ý ù9::áÀÀÀZñññûûûýýýþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷ëë릦¦t888èøü7=üŠœý¯Êý¸ÓþºÖþ»×þ»×þ»×þ»×þ»×þ§Àþ -3ýý xˆýµÐþºÖþµÐþ¶þMZþý ú$''ï§§¨•ðððûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüüúúúôôôëëëÇÇÇfgggÊõ ú ýYdý¤»þµÐþºÖþ»×þ»×þ»×þ»×þ»×þ»×þºÖþ©Âþ 16üýn}ü´Îþ»×þ»×þ·Óþ¯Éþ‡œþ3:ýü"&&ñ›êêê'öööûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýùùùééé"¦§§zXXXÇ"""ð úýCJû •ªý±Ëþ¸Óþ»×þ»×þ»×þ»×þ»×þ»×þ»×þ»×þºÖþ®ÈþFOýýR]ü±Ìþ»×þ»×þ»×þºÖþµÐþ£¼þapý#üõabcÇÆÆÆGïïï ùùùüüüýýýýýýýýýýýýýýýýýýþþþþþþþþþóóó‚‚‚ ó ûü)-üo}ý «Äý¶Ñþ»Öþ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ°ÊþS]þýNXý±Ëþ»×þ»×þ»×þ»×ÿ»×ÿ·Óþ±Ëþ‹ þ7@ý ú$''뀀€µØØØ7õõõýýýþþþþþþþþþýýýýýýþþþþþþþþþííí HHHÌ ú (-ým{ü¢¸ý´Îþ¸Ôþ»×þ»×þ»×ÿ»×ÿ»×ÿ»×ÿ»×þ»×þ»×þ»×ÿ»×ÿ»×ÿ±Ëþ T_þýNXý±Ëþ»×þ»×þ»×þ»×ÿºÖÿºÖÿºÕþ´Ðþ£¼þTaýüùFFFÚÜÜÜFûûûþþþþþþþþþýýýýýýþþþþþþþþþííí LMMÉ úWbý¬Æþ¸Óþ»×þ»×þ»×þ»×þ»×ÿ»×ÿºÖÿ¹Õÿ¹Õþ¹Õþ¸Ôþ¹ÕÿºÖÿ»×ÿ±ËþS_þýNYý°Êþ»×þ¹ÕþµÑþ±Íÿ®Ëÿ¯Ìÿ´Ðþ¸Ôþ¶Òþ«Äþ_kþýõ²³³aøøøþþþþþþþþþýýýýýýþþþþþþþþþñññ |||Ÿ ø 9Aý®ÈþºÖÿ»×ÿ»×þºÖþ»×þ¹ÕÿµÑÿ­Éÿ«ÇÿªÇþªÆþ«Çþ­Éÿ²Îÿ·Óÿ°Êþ S^þýMXý°Êþ·Óþ­ÉþŸ¼þ˜´ÿ–²ÿ—´ÿœ¹þªÆþ¶Òþ·Óþ§¿þ  ûöª««b÷÷÷þþþþþþþþþýýýýýýýýýýýýýýýööö«««zö $'ý¢ºþºÖþº×þºÖþ¹ÕþµÑþ¬Èþ ½þ—´þ•²þ”°þ”°þ—³þ˜µþœ¸þ¦Âþ©ÃþS^þý NYý¦Àþ¢¾þ–³þŒ¨þr‡þ\mþk~þ‰¤þ–²þ¤Áþ³Ïþ©Âþ $üöª««b÷÷÷ýýýýýýýýýýýýýýýýýýýýýýýý÷÷÷º»»Võ #ý žµþ¹Õþ¹Õþ¶Òþ­Éþ ½þ–²þªþ {þ \jþ Vcþ\jþ qƒþˆŸþŽªþ’­þš³þOZþþ Weþ‘¬þ«þwþIWþ#þþþ>Jþwþ‘­þ¹þŸ¸þ!%üõª««böööýýýýýýýýýýýýýýýýýýýýýýýýøøøºººWõ"ý œ³þ·Óþ°Ìþ£¿þ—´þ‘­þ —þ IUþþýýüýý,3þ N[þt…þFOýþYhþ|”þQ`þ!'ýý #&ýKUý (-üý*2þcvþ‰¢þ¨þ "&ýöª««b÷÷÷ýýýýýýýýýýýýýýýþþþþþþþþþøùù»»»Uõ "þ ™°þªÆÿœ·ÿ“°þ ‹¥þ [jþ#þþþ 6<ýJSü@Gü$(øýþþý ý ýþ$þþ ýXa÷ ž¶ý¬Æþ ¡¹þZdþþþ5>þoý ýöª««b÷÷÷þþþþþþþþþýýýýýýþþþþþþþþþùùù»»»Võ$*þ Š£þ•±þŽ©þoƒþ18þýý38ý€’þªÃþ¯Éþ®Çý ¦¿ý•ªþhvý 3:ýýýýýý ýr€ý§¿þ´ÏþºÖþ·Óþ°Éþ€þ /5ýý ýý÷ªªªcöööýýýþþþþþþýýýýýýþþþþþþþþþøùùº»»Wõ$*ý €—þ wŒþ>Iþýý #üiuö ¦¾þµÐþ¹Õþ»×þ»×þ¶Ñþ ­Çþ’¦ý=Cùýý ýý ý ý "ý _mý  ¸ü³Íþ·Óþ¹Õþ´Ïþ ¡¸ýCJù ýýù›››”îîîûûûýýýþþþýýýýýýýýýýýýýýýøøøº»»Võý 6>ýýýûDKù”©ý²Ìþ¸Óþ»×þ»×þ¸Óþ³Íý Ÿ¶þWbü "üýü29ügxý u‹ýMYý  ú ü ý ',ú`lý  ·þ´Îþ¹Õþ·Òþ §¾üR[öü ü(()ì¡¡¡èèè#÷÷÷üüüýýýýýýýýýýýýüüüôôô¶¶¶d÷ý ýüFOù ”©ü ­Çý¶ÑýºÖþ»×þ¹ÕþµÐþ £ºýcoö#'ýýü (-ýetý ‡ ý«þ«þ ‡¡ýmú üüü ü */ý~ý­Æþ¶Ñþ¶Ñý ¯Èý{Š÷ '+ý úõ```ÓÈÇÈmðððùùùüüüüüüùùùòññÖÖÖ0[[[Ð ù ý38ü€‘ü ­Æþ¶ÑþºÖþ»×þ»×þ·Òþ¯Éý…˜ý 28ý ü ý !%ûZgý ƒ›þ«þ“¯þ’®þŒ¦þl}ý $ü ü ü,2ü ý ýýDMý ™°þ³Íþ·Òþ³Îþ ›±ýCLýý ú'''îŽŽŽ¡æææøøøïïï*ÒÒÒU‘‘‘–888âùüPZý ¤¼ýµÐþ¹Õþ»ÖþºÖþ¹Õþ³Îþ›²ýPYöüýüIý`qþmþfzþ evý.4ü ý ý-2ú xý¨þ’­þ‘­þ‹¥þgyþ #'ý ýý 4<ýx‡ý ˜®ü Zfüûý ûõkkk¼óóó±±±j"""ñ ûý üpú ©ÀþµÐþ·ÓþµÐþ ªÃþ|Œú .3ûý ý#ýYhý N[ý!ý ý ý ý ý ý ý ýýITý „œþ¬ý“°þ”±þ”±þ“°þ«þ ™ýDNý ý ý ýýûù###óLLLÖ’ààà7÷÷÷îîî¶µµ___½ò ùü;AúŒž÷¢¹ýw†þ 8@ýü üýIUü~•ýŒ§þŒ§þ ‚šýaqù5=ùú ýý ü 4<üoýŒ¨þ’®þ”°þ”±þ”±þ”²þ”²þ“°þŽ©ý ƒýVcúýýüòƒƒƒ¤ÒÒÒPëëëóóóùùùüüüûûûöööìììÅÅÅCWWWÃ÷ üü üý ýý9Aús†óŒ§þ’®þ“°þ“°þ’®ý«þ ‹¤ý —ý 6>ý ý =Gý† ý¬þ“¯þ”±þ”±þ”±þ”±þ“°þ¬þ ‹¥þr†ý:Büý ýýý455á¿¿¿Jííí ùùùýýýýýýýýýþþþýýýüüüõõõßßß7abb¼ûýý ùBMýs‡ý ‹¥þ«þ“°þ”±ÿ”±ÿ”±þ”±þ”±þ”±þ‹¦þ ?Iþ ýFPý¨þ”±þ”±ÿ”±þ”±þ”±þ ¬þŒ¦þq…û8@ýý ýý6<úGPùü ù++,ê“““…ÜÝÝ'òòòúúúüüüþþþýýýùùùîîîÅÅÅHabb½ûý$'øj|ü…žýŽªþ“¯þ”±ÿ”±ÿ”±ÿ•±ÿ•±þ•±þ”±þ”±ÿŒ§þ ?Iþ ýFQý¨þ”±ÿ”±ÿ“°þ‘­þ Œ§þt‰ýAKøü ýý6<þzŠý ¨Áý ªÃþp~ý #&ü û÷555â’’’ŠÛÛÛ-òòò ûûûõôôÝÝÝ&xxx©&&'îø üý ü"ýJUý z‘ýŒ§þ’®þ”±þ”±ÿ•±ÿ•±þ•±þ”±þ”±ÿ‹§þ ?Iþ ýFQý¨þ”±ÿ’®þ©þ ~•ýAJüý ýý6=ú„•ý ªÂþ´Ïþ¹Ôþ¹Õþ³Îþ”¨þEMüü û÷<<<â¿¿¿ièèè,®®®pDDDÕøü !üCKýLUü !%ýüý ûJVû|’ý Œ§þ‘­þ”±þ”±þ”±þ”±þ”±þŒ§þ >Iþ ýFQýŒ¨þ¬þ ˆ¢þYfù !ü ýü-2ýrý ©ÁþµÐýºÕþºÖþ»×þ»×þ·Óþ¬Åþ•þ#ýý ü!""ó´´´„yyy«ô úüR\ú ˜®ý­Æý ­Æý žµýqý-1øü ü  ýFOý wþ Фþ«þ“¯þ”°þ”²þ‹§þ ?Iþ ýEPý ˆ¢ý~”þ9Aýýü $'újwø£ºý´Ïþ¸Ôþ»Öþ»×þ»×þ»×þµÐþ¥¾þ_nþý û÷:::㘘˜¢êëë>@AAáùýHPú ´þ°Êý¹Ôþ»×þ¹Ôþ´Îþ ¥½þlzý (-ýý ýý:Býevý †Ÿý©þ’®þŒ§þ >Iþ ýAKýuŠý-2ý ýýT_ý  ·ý²Íþ¹Ôþ»×þ»×þ»×þ»×þºÖþ´Ïþ›²þ7?ýû ø,--ë•••Žããã[óóó ùùùª««i.//éùü17ý’ý±Ëþ¸ÓþºÖÿ»ÖÿºÔþ³Îþ £»þtƒù 5;ýý ýý ',ýXfýƒ™þ ƒþ=Fþ ý,1ý $ý ýýy‰ü¯Êý¸Óþ»×þ»×ÿ»×ÿ»×þºÖþ¶Òþ°Ëþ¦þ,3þüöuvv¦ÔÔÔSòòò úúúýýýýýýñññ ÕÕÕ3jkk¹!""ñù #ûq€ü˜­þ ²Ëþ·Òþ»Öþ»×þ¸Ôþ´Îþ ¬Åþ‚”þBKýý ýý ý@Iü $)ýýý ý#þ}Žþ±Ìþ¹Ôþ»×þ»×ÿ»×ÿ»Öÿ¶Ñþ®Èþ‘§þVdþýûôºëëëøøøýýýýýýýýýýýýýýýøøøîîîÆÆÆNfff²#&&ñù ûRZû–ªù­Çþ´Ïþ¹Ôþ»×þ¹ÕþµÐþ¯Èþ™®ý `mý $ýý ýýýý ý ˆœþ±Ëþ¹Õþ»×þ»×þ»×ÿ¹Õÿ³Îþ”«þ9Bþýü ù(((ï¡¡¡xîîîúúúýýýþþþþþþýýýýýýýýýýýýüüü÷÷÷ííí ÊÊÊ\¡133ç÷ úAHüo}ýž´ý®Çþ³Îþ¸ÓþºÖþ·Òþ²Íþ Ÿ¶þjwý ).ýýýü ýmzþ ¦¾þ³Îþ¸Óþ¹Õþ¶Ðþ§¿þs…þ"(ýúö233æuvv­ÈÈÈ\ñññúúúýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûøøøððð ×××-“““ƒGIIÏö ú "ý /4ûkxû Ÿµý°Êý¶Ñþ¸Óþ³Îý—«ú #ü úõò øü .3ýlyü Ÿ·ýªÄþޤþ8Aþý ú-..è¡¡¡sÜÝÝ%ïïï ÷÷÷ûûûýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúóóóää䦦¦sQQQÙ ñúû $(üT_üý œ³þ¥½þJTýü!!!𥥥kÄÅÅAmnn±"##ðúü ',ü CMýýûõUVVׂòòò úúúüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþþþþþþþýýýýýýýýýþþþýýýûûûõõõèèè#ÈÈÈWlll»)))íø üý  ý).ýýøŠŠŠ¯íííõõõíííÇÇÇ[ppp°%&&ïù ûù344ä¡¡¡sèçç#õõõüüüýýýýýýýýýýýýýýýýýýþþþþþþþþþýýýýýýþþþþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýûûû÷÷÷îîîÏÏÏ;‘¨HHHÙ***çô÷ô]]]ÇãããHùùùýýýüüüøøøîîîÃÃÀ‚ƒƒž[\\Îrrr½ÐÐÐ>òòò ûûûýüüýýýþþþþþþþþþýýýýýýýýýþþþþþþþþþýýýýýýìììììììììììììììëëëìììììììììììììììëëëìììëëëèèèâááÙÙÙÊÊÊ(¢¢¢Wyzz‰’““nÒÒÒæææìììëëëììììììëëëçççááá ÝÝÝ ààà æææ(ëëëìììëëëìììììììììììììììëëëìììììììììììììììMMMIIIGGGIIILLLOOOOOOOOOOOOOOOÿÿÿÿÿÿ8qÎ8ãÿÿƒü/ÿÿÿÿÿÿÿ( @ €ÝÝÝÝÝÝÝÝÝÜÜÜÝÝÝÝÝÝÝÝÝÜÜÜÝÝÝÝÝÝÝÝÝÜÜÜÜÜÜÛÛÛÕÕÕÌÌÌ ÌÌÌ ÑÑÑÚÚÚÜÜÜÝÝÝÝÝÝÝÝÝÜÜÜÝÝÝÝÝÝÝÝÝÜÜÜÝÝÝÝÝÝÝÝÝýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷îîî âââÅÅÅ=‚‚‚•```À»»»Uèèè õõõüüüýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýüüü÷÷÷ìììÔÔÔ4‘’ŒIOOÚ&/0ïôõ%&&ìyyy˜ÐÐÐ6ííí øøøýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýúúúððð ÛÛÛ#އ7@@ä+.ôCJú[gû T_ýüû "ö7@BàŸŸqåååõõõüüüýýýýýýýýýýýýýýýýýýýýýýýýþþþþþþýýýýýýýýýüüüõõõæææ¯°°fGMOÖ*-ôJRù ƒ–ý¥¼þªÃþ ¤ý#(ý?Iý€“ý DMú)+ðpss¨ØØØ"ñññûûûþþþýýýýýýýýýþþþýýýýýýýýýýýýýýýüüüùùùîîî ÏÐÐ9uxx¬ ,.ñ:@ø~ú§Àý³Íþ¸ÔþºÕþŸ·ý 4;ý Zfý¤¼þ ¸ýJTû&)õLRTÌÈÉÉHïïï ûûûýýýýýýýýýýýýýýýýýýýýýýýý÷÷÷ííí ÚÚÚ#ŸŸz8@Bá,0õZeû ž¶ý°Ëý¹Ôþ»×þ»×þºÖþ¢ºþ 7>ý WcýªÄþ´Ïþ¥¿þqƒü4:øì€‡ˆ’ØØØ,ïïï ûûûýýýýýýýýýþþþúúúÅÅÅ=*12ê4;úpü ¤¼þ²Ìþ¹Õþ»×ÿºÖþºÖþ»×þºÖÿ»×þ¨Àþ HRý ENý¨ÁþºÖþ¹Õþ¸Ôÿ²Íþ¨Áý x‰û05õDKKÛÂÂÂRõõõþþþýýýýýýýýýúùùÄÄÄ:$-/í fuý¨Àþ¸ÓþºÖþ¹Õþ¸ÔþµÒþ´Ðþ´ÐþµÑþ¸Ôþ§Àþ HQý ENý¦¿þµÒþ¬Èþ¦Âþ§Äþ®Éþ«Åþ}Žý+.󃃃ïïï ýýýýýýýýýýýýûûûÛÚÚ!:DEàUaü­Æþ¹Õþ¸Ôþ²Îþ¥Áþ—³þ“­þ“®þ˜³þ¡¼þž·þ GQý ENý›´þ›µþ‡ þo„þ{’þ“®þ§Âþ›³ý25ô|}}‘êêê ýýýýýýýýýýýýýýýßßßKRSÑNWü¨ÂþµÑþ§Âþ•¯þ˜þYhþEQý KWý _nýtŠþ–þ =FýEPþ{’þj|ý=Gý*1ý-6þ[kþ‡ þˆ þ16õ|}}‘êëë ýýýýýýýýýþþþýýýàààKSTÐMVûž·þšµþŠ¢þ `pþ07þ*0ý AJý ;Bû*1ý&+ý )/ý!ý%*þ3=ý&,ý S^û ‰ý p€þ19þ@Kþ apý(+õ{||‘ëëë þþþýýýýýýýýýýýýàààJQSÐHSû€—þp„þGý&,ý 8?û~û©Âý³Íþ²Ìý§¿ýz‹ý 8>üý 2:ý Q`ý 19ýý-3ü l{ý  ·ýªÃþ¡¹ýU_ø  ú;AAá¹¹¹Qéêê÷÷÷üüüúúúòòò ÐÐÐ+;@@Üü .4ý v†ü ¢¹ý°Ëþ³Îþ­Æþ ‹Ÿý ENú"(ý 29ýduý šý€˜þ k~ý (.üý ý ;Cý „–ý¦¾þ¥¼þx‰ú27ø)34ë…††¨ÜÜÜ*ñññßßß'µµµdSVWÃ$&õQ\ü ³þ°ÊþµÏý°Êþ žµý _kù"ýü KWü uŠý™ý‚œþ i|ý *1ý$ý JWü`pý 2:ý$)ý \iû –­ýžµþ ƒ–ý4:ùôWWWËÜÜÜ0ŒŒŒ›,,,ë÷T^ûœ³þ¯Éþ±Ìþ¤¼ý wˆý 7?ý!%ý"&ýü+2ý FRýKXý BMý#ý-4ý mý‡ þ‰£þ €˜þ P^ý"(ü,3ý [gýNYú#&ö!##ðSSSÔÙÙÙ4½½½Uaaa»!$%ð,/÷hwü —¬û z‹ý @Hü!&ü 6>ý hzýyþ [lý 8Aù "üý ü HTý ~•ý¨þ“¯þ”±þŽ©þ€™ý`qý û üõgkk²¯¯¯bÞÞÞ ðððððð äää±²²M@EFß ú $ü!%ý 19ý \lû ƒœû©þ¬þŒ¨þ„ý i|ýý P_ý…þ«þ”°þ’®þ‹§þ €™þ\lý +1ýüü&(î”––mÚÚÚïïï úúúûûûïïï ÒÒÒ wxx” úûP]û xýˆ¢þ’­þ”±þ•±þ”±þ’®þ v‹ý#)ý ZjþŒ§þ’¯þŒ¨þ ‚›ý aqû 18û#)ý ?Hýy‰ü}ü8>ø*,ð^bb¶·¸¸Pâããäää½½½FOTTÌ%'ó "ûü)/ý Saü }”ý‹¥þ‘¬þ”°þ”±þ’®þ vŒý#)ý Yiý‰£þ‡¡þj{ü 3;ü!&ü ëGMôz‰ù œ³ý©Áþ«Åþ¨Áþ ›±þ l{ý 17ýýü ýboýŸ·þ²Ìþ¶Òþ®Èþ•¬þ ISû)-ö(24ëruv²ÛÛÛóóóüüüýýýýýýýýýúúúóó󿿿ůÆ<{‚–8FHß:>ôT^úu„û ´ý§Àý£ºý‰›ý'+úô"#ò-1ø`mû ’§ý›²þl}ü17ù'34냃ÃÃÃAèèèõõõüüüýýýýýýýýýýýýýýýýýýûûûõõõêêê ÒÒÓ(Ž‘’IPRØ.0ó8=÷Zfü t„ýQ]ü)*ó†´µµJeij¼#/1ð04÷9?ù),ôOUWȵ¶¶qèèèõõõûûûýýýýýýýýýýýýýýýøøøøøøøøø÷÷÷øøø÷÷÷òòòèèè ØØØ¡¢¢o\``Ç.8:ã)*î ))íorr¶ÞÞÞéêê àà຺ºWjllµKMNÖŠŒŒˆØØØëëëõõõøøøøøø÷÷÷øøøøøøøøø÷÷÷¾¾¾¾¾¾¾¾¾½½½ººº²²²§§§˜˜˜wwwJtttT¥¥¥¶¶¶½½½¼¼¼µµµ««« §§§¯®®*¸¸¸½½½ ½½½¾¾¾¾¾¾ÿÿÿÿ:;ÿáñÿ(0 ` mmmiiiiiikkkÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÖÖÖËËË ººº¡¡¡9”””Q½½½ÐÐÐÛÛÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜýýýýýýýýýýýýýýýýýý÷÷÷ééé ÑÒÒ*—žŸ{anp½7CDä4<=ælnn¨ÁÂÃ<æææöööýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýýûûûïïï ØÙÚ™¡¢rG\_Ù'U[ïmy÷_kû ',ú5:ô7MQ♚{ÛÛÛòòòüüüýýýýýýýýýýýýýýýýýýýýýüüüõõõää亾¿JZjm¿'OUí{‹ø ´þ¦¿þ¡ýý v‡ýŽ£þ n~ý>Gý=D÷fnp¨ÚÚÚüüüýýýýýýßßßoxz¡JSöHSý EOü v‡ü›³ýœ³ý Ž¢ý \iü *0ü 3<ý 7@ý'-ý MWü „—ý—­ý ‘ý;BøAQSÖ¸»»AçççöööæææÅÆÆ'P^aÅ5;ø fuü™°ý£»þŸ¶ý zŒý AJû ü,2ý9Aý hvý¤ýˆ›üT\õ:HJãš›œ€ÝÝݧ¦¦vTWWÍ =Bò}ŽüŸ¶þ¢¹ý ¦ý Xeü,3ü +1ü R`ý cuý _qý :Cý EPý l€ý k~ý EQý HSü oýpû&<@ðIJJÞ¸¸¸d¡¡¡wKNOÖ"CHðtƒù ˆœý ftý=Fý N[ý dwý N[ý 1:û+2ý/7ý Yiý€˜ý‹¥ý† ýrˆý HSý#ü*-õYce¹¤¥¦gÜÜÜààà¿ÀÁ,\fh°'+ø,2ü FQý lû‚›þˆ¢þ…žþnƒý3<ý Yiþƒ›þŒ§þˆ¢þ {‘ý Wfý 4<ý 29û/2ñx€‚ÆÇÇ%áááÞÞÞ±´µGQ\^»"%ù 29ü _pý{’þ‹¦þ“¯þ”±þ~–þ COþ duþ„œþ ~–ý ]mý ?Iü P\ý }ý’¨ýo}ù$=AïW[\È«««c‡ˆˆ:FHâS[ôq€û \jý >Gü P]ý oƒý™þ‹¥þ{“þ ALþ Yhý j|ý CMü HRû zŒý ¸þ¬Æþ¤½þ ƒ–ûDJôBFFàœœœabb¿/@Cëm{ù “¨ý›²ý Ž¢ý bpü@Jý JUý ewý j}þ 1:ý ?Hý 5<ý jxý´ý«Äþ­Æþ¢ºþ ‘ú"GMïgtv±ÁÃÄFßßßÌÍÍ"—˜„D]`Ø(mwï¢ö š±ü˜®þ Ž£ý m|ý FOý 07ý ýý esýžµý®Çþ§Àþ ˆœú^hõ1JNè‹”•‹ÛÛÛòòò ûûûöööèèèÏÓÓ)–£¥rSmqÅ,bjít‚ö‹ü‘¦ý‚”þLUø"#ó!/1ð\fõ‰œû ’§ýiv÷,KPér›·»¼Määäöööýýýýýýýýýüüüöööêêê ×ÙÙ¦®¯bewz¶3RWè$`iñjvô+HL쀆‡Œ§«¬Qgux´3OTè.QVëRdfǬ±²eÞßßñññúúúýýýýýýýýýÔÔÔÔÔÔÔÔÔÐÐÐÅÅÅ ³´´“–—Fbkl€BLM©cijв³³!ÀÀÀ´µµ’’Q}~p«­­(ÄÄÄ ÐÐÐÔÔÔÔÔÔÔÔÔIIIBBB777 111888 BBBHHHCCCCCC EEE JJJÿÃÿ$% ü?(  @žžžžžžžžžžžžžžž™™™ „„„‡‡‡‘‘‘œœœžžžžžžžžžžžžžžžèèèççççççãããÖ×× ÀÆÇ‹™›fXgi¦S_`³¢¦§@ÎÑÑßßßççççççççççççýýýüüüòòòÞâ㥴·^PtzË*~‹î|ŠôHOó0^eç…™œ„Ùßàòòòýýýýýýýýý÷÷÷çéé ÄÎÐ4l†Šª+u€ìŸµ÷ ©Âý–¬þ ZgýŽ¢ú!zˆðb€…µÌ×Ù*ëíí ùùùýýýïïï £­¯l@lsߎŸô ©Âü°Ëþ·Óþ ¸þ esý™°þ ¨Áü”¨ôHu}ѱ¾ÀXííí ýýýééé „•˜‡#‹›ñ¢ºý¥¿þ›´þ™²þ¢þ XdþŒ¢þަþ¤ý ôcw{¶âââýýýééé £¦s!Žñ¦þw‹þ_nþ [iýWeý@JýS`ý_ný_nýo€ùXos¼ØØØýýýåå匜žu eqòWeý pý¢ý ’ý AKý5>ý4<ýcrý ‡šý[gù>Z_ÕÀÇÉ-èéé ÃÃÄ4_sv®Zeö ‰ý“©ý l|ý DNü Xgý btý DOý LXý Taý {ü"myòVceн¾¾Lˆ‰‰› 00¨f ¨È¶$h~+€€ (æ0`` ¨”9HH ˆT¶Í@@ (B>"00 ¨%fd  ¨Š ˆ ¶š h>¤(0`€€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ€ppp3pp;33p;³·³0€;³·»»³p;;{;;s³³;;³³³³³·³13³·³»;;@;;;·0p³³»;;›{;¹³»3;·¹³·»;·³·;;0³¹³·“;;;39³³0·³³333—03—{³³7;703p³—034³p0s0;·³0;;³01;;;3{;³€3·³·»s0;{337»;‹‹³3³»0p44ÿ‹»7@·»p3pÿ‹;0 !³°pR@ÿø01w3€ÿÿÿP÷c“quÿÿÿw™—q€!Bÿÿø™—y‘‡Bÿ÷5™9™1‘“3qÿø÷‘9—“™y0p³³pxø³31S19y€p;;@ ;;·9S™51w·1;»·³7“™q™€p´!·¹»y™Q9q`C{;{y999y‘€t·± y•9Wø‘p0qp SSpÿ“€Pwwpsxyˆÿ‘‚øw‡ˆ˜øø—•ˆ‡ø“ÿ˜ø“— wù‘W™yPˆ÷“‘W“P%÷ø‘y€w÷ø——Pÿøÿ‰€!€÷ÿpBxˆwˆw4RR‡ˆxˆˆxxˆ€ÿÿü?ÿÿÿÿðÿÿÿÿÀÿÿÿÿÿÿÿüÿÿÿðÿÿà?ÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿ?ÿ?üøø þÿÿþøððüÿþÿÿÀÿÿðÿÿüÿüÿü?ÿþ?ÿþÿþ ÿþ|ÿþ|ÿÿþ}ÿÿþ0ÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿ( @€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿpp€3·0³»³»;;³±p»;{;S·³03³³³³;;³;;y³{³“;3¹³3q!s77313X3{;p»33³³3p³173³P‹»3³00÷·;3p@ÿø1qA0 ÿÿ‡‘X$ÿø1—“Y4ƒ0ÿøY™‘“ 7»Ax³3SS830³»syW4;{“““—³3™qˆ—E77W‘‡wx‰ÿ8W‡÷?™ø‡——pOyrRˆ?“pø_õtðø/ÿ0st$%ÿþÿÿðÿÿÀÿÿ€ÿþÿøÿøø?ø?ø?ø?øøààøøðàð?ø?ÿ?ÿ€ÿ€ÿÀÿÀŸÿÀŸÿÀ¿ÿÄÿÿÀÿÿÀÿÿÿÿÿ(0 €€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿp€3p;; 63³·³³»; ;³p ;y³³3 313c30131;1@S·03³7p31‹·0³p0hø3P30pÿq‘Qw@ø99€q3pøQ•‚;»3y9p;;y‘—€t7q—xwˆpwwx˜—ypx‘p ø1pxˆx€ppÿçÿÿÿþÿøðððððàÀððÀÀðüþþÿoÿoÿÿÿÿÿ( €€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ33€;;7³·3;p131p10s0q'x³3pÿSwø“‘p3{7•8!;ywHyw‰x‡wwˆˆ€þøààààÀÀÀÀàøøøøü(0`      "/5 -" " 3 %#%%+%, *-"% &)+/*- 5#+1.25< 4;9=&((,-3,46344459;:: C@& FMIP [P;DD8:@b havw {#(l48qA=LAJ CKHN@GCJJUKTKS R[RY%GM6PA&NW%RY2QXUa Ud ^lYe2\c fncnro ds fx l|ivu}$dn.gq q~DCCGHHLKKSTTYWVUVX]]\BFfQYk_``bbcjkkhwntttxvuvxz|||‚†—(›;”,0‹'7•68’¨·!«"¸"+£#+¶49¶S†?C‰ p uˆ z‰y‡ ”'|‹Í!0ß3=Ö&à&4áMÞŠ}×E†_)bþþþþûj|“t“••””””•“z}:?–c°ËÑdz)ÞúúïÕñ"<=u|sststts0=}}~|¢Ö\ÄÉÉÉU¸ÎÌÒÒÒ]J¬usu}””us:qÜ’æ( ¥ÇɈ 5ËÌÏÒÒÒÏ…^Á}”””}||t<Ûã( °½7 [ÌÒÒÒÒÒ©†À••”“zt•••z=c) N½ÏÏÒÒÒE¼•›•{•t€ ••tÝn(ÚTÔÌÔJ ¹Ž”›‚™(pþí›zy'÷a¾)¿ÆPv–+™hAþü›u=sÝaûnkrjÙ D\†ølžìáþü›tttsá' þýþaå÷aØñòôþî¤þþù”t}{sÝ*øûðdþûn÷þДžüü£êþëut““sÝf,) ÚØÚ÷þŸ•t€¢}—t?š}sà )ÞÞ÷þŸ™ts:9;?‹¡zsßb( fþÞ÷þЕtttèÚ(gÖÙûþßûþüŸzs{ŒÚ*÷þþþþßûþþô—s2èÚ+÷þþßøþü@Ú+¿÷÷áÚkqáàÚÚ(Ú+* á****)( ßÞßßÚÞßÞÚÞÚÚÚÞÚÚãÿÿü?ÿÿÿÿðÿÿÿÿÀÿÿÿÿÿÿÿüÿÿÿðÿÿà?ÿÿ€ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿ÿ?ÿ?üøø þÿÿþøððüÿþÿÿÀÿÿðÿÿüÿüÿü?ÿþ?ÿþÿþ ÿþ|ÿþ|ÿÿþ}ÿÿþ0ÿÿþÿÿþÿÿþÿÿÿÿÿÿÿÿÿÿ( @     03" !  : 8 !% %* (,!"+. 0$>!,2 ,24< 4;<<!"!!%%$%%%(')**(+-*,--.-$37)473449:: J*@@? C NY^>F Ey `gcr bqhv gx k{esivm{ppq{ nvFEENMMQRRZ\\a__MNwdeeihhrstxwu|||€Ž‰“šœ(Ž$‘ ž?˜%%†%'ˆ7:‡$0–¤¬³¼!¯(¨ »*º:·(.¬#-³&-º(1¹4;³ q |Žr€ |’#r€yµPZŒCE˜DG¡QY¨rv«yz± Å!Ì(Ì#Ó%Û&Û-4Ã/<ã7@ÎikËNZæjtêpxë ‚• …™Œ›‚–†˜ ަ“¦ ’¬ ˜¯‘¥¤‘ª —³ š¶ ¹›±Ÿº9€ª  · ¡¾¥´¤¹z†‰xž¡a‚³ £À ªÄ¬Ã ³Î¶Ï µÐ ºÕ ¼Ø²Ô¾ß#´Ò»àJ“ŃÏÐßÄçÅèÔäÙè+Öä]ÆÝƒƒƒ‡ˆˆ‹ŒŒ‘’“˜——œœœ‹¦ŠŒ¬‘ª‚„¿‹Œ¹£¢¢¬¬­²²²¾¿¿Œ‘Ø™œÜ­°Úˆã”哙å¾ÀÀ°ØáÅÅÅÍÎÎÈÉÐÛÛÛÊËêÌèëëììëìúîñòõõõõõúûûû/(ß ;pæ;¶ÍȱY/#³ÍÍÍÍ ³Í® Ýp±ÍÍÍÍÍÍ °ÍÍÇ:nàdÉÌÌÍÍÍÍÍiÍÍÍÍ”2aÍÍÍÍÍÍÍÍÍiÍÍÍÍ͵ mdÍÍÍÍÀÀÀÉÍeËÀµµÇÍNàvhÍÍÀµY%aµ»b²T—ÀQàvhǹe ”<P# K¼j NWæÛf—&hÊÍͼ ±ÍÍÈ<æÜNÂÍÍÊh ;Á¶Q#¶Íͱ ã/#–a°Í¶(ñØØ×¯S'UÉÍÇIqef KwùûÙÔ·4! •ÍÍ:vè( )  süþþøVX">ˆEG OI6Ý-Üüþþþ(vßš‡¥ |ˆ‡Hì“à/  Ûþþþö9…Ф¤¡|Œ¡B@á’/]1 müþüæ |Œˆ¤££Œ ˆ~=ÊÍÈ1 ÝòÚа\9{|€{y7FŠ‹Ó&¿Í] »ÑÕÖ½k™ŽŒŒŒŠzræ(U˜) IÑÖÖÖ[Ò¥£‰‡££†å5) pKÎ϶T¾£¢Hãt Þ(Ã.p`lž_Ýý£x‚ó)çñÝÝÛ(ÄÅëõ¬ýúŒ‡†Ÿ2ÛèoûÞ2þª‘÷íîꃦˆŸu-//ç2þ§ˆzCD„ð†Û2)(æñ3þ«‡A©œv(ôùþñoüú¨Cäw/öþñ3üþý?w/-3((à22/(((ÿþÿÿðÿÿÀÿÿ€ÿþÿøÿøø?ø?ø?ø?øøààøøðàð?ø?ÿ?ÿ€ÿ€ÿÀÿÀŸÿÀŸÿÀ¿ÿÄÿÿÀÿÿÀÿÿÿÿÿ(0@    1"  ,; # !% !$%) %) )-#&#%*-0*+1/6 .3 5<4;:?$%&#'- ,-()*+,-'(6 261234:;;::>>>L2 \R 'M:B9@?HAemv!q@IDM ZM@P GSMX LY P[P\!BG"GN7@A!PYUa ZfZf_lZe[pam cp fuip fxn|,iuDEEIKTQRRHHhKZrabbceefgghiiqrrzz{}{{}}}~}„€ˆ˜œ%—)™¢¥¦«­µ¼½#ª"¶#µ ½-7¢).·/8µ(F“ q yŠxƒˆ|Œ!|‹F´Z^ˆYZ£ih§kl®sv¯st°"À&Æ(Á$Ò$Ú%Þ#/Õ5LÈHOÏX^ÆKSÑ_eÅ€Œ ‚“…š„—2‰œ ¤Œ Œ¥ ”© ”­ š± ˜´ ž¹œ´ £º¦½­½b¡­x°½ ¥Á «Ã ªÅ ­Æ «È ­È ³Ì´Í±É¶Ð ¸Ò ºÖ ¼× ¼Ø·Ù¿á~‚ÎÂæÄèØèP×ツ„„……‰ˆ‡ˆ‰‰Ž•–™™ž›ž¥¡¡¡§§§«ª©­¬¬±°¯¯°°³µ´¶µµ„É’—ȘšÊ¦©Ü¬®Ø°´à«°ò¬±óšâèÆÆÇÉÉÌÏÏÏÙÙÚÛÜÜÜÜÜ×èíáâøïðûóó÷öö÷÷÷øøøøýýý55Ð-Qˆ:i3W·½º ºˆ3bH³½½½º ¹º«* §½½½½½½·½½ºSe½½ºµ°µ½ ³³¨°º(½µ¨I&Z§ŸGC¨;©W W³ƒ%[º &!" G¬¼¸R KR··PÊœÐRK¥‡ ÌÄíE$ Ÿº¢ÇV +äêÞ‡698-C§F5 dêìëÌaw”no@š] dêìãq{••tzt0‹ÚÇ'£‰ âå¯=rn|wwwmABÔ#žºM £¿ÂªUŠx|xlÍÌLO)¾ÂÂ…˜•z}—tÔ b1¡\Y‚^æ‘_ÇÒif>®Ö×ÛçxtÕbÆÆÎbݓٙÀŒ’Ž//ÔeÝ|?`€/ÔãáÇé›7jØ/ßãÏbãàÆ2+iÿçÿÿÿþÿøðððððàÀððÀÀðüþþÿoÿoÿÿÿÿÿ(   ; %*.218 25"69<>> CU C u"%v @G DM ZM JS JU JT LV NZHP PY R_ R^PZ9X^Ri8]b9Kz aq er hz ky0cgEFF@NL@WVKXZRRRSTUVVWXXX\^^\psfffdwzhwyg|puv~~~<— 'Ž8>‹§ª®!¤"¥#® ¼x*p‹|€BH±]a±_c·`b¶`uµrw·ww·À%Ó$Ù.8ÍS[Ð|ÄipØ …˜ Ž¢ ‘§’§ ˜­ —±œ¹§¾p„‡ ¦Á ©Á ®É²Ë ³Ï µÐ ºÖ ¼Ø¶Ö[®ÀÅÔ)Àà†ˆˆ‹Ž‘‘‘‘’™ššŸ  ›¤¥«««®®®°±±´´´¸¸¸¯°Ñ‚ÔÛÈÈÈÖ×ÝÙÙÙíõö÷÷÷øøø,-"Wb'r6TddddX\Wdb_da]_5UY' $4[[UX 2$7vg^!j)|z*+?:#k  |y AOBM;`fhC9=?uo ZeDO@QF1E3(JKx=L--mmPHHRI1iwpS-nE3ktrrprþøààààÀÀÀÀàøøøøü(€ ÑÑÑËË˱²²\y{|òJKLù ûýý667ò   `ËËËÒÒÑÑÑÑÍÍÍÉÉÉ¿¿¿)„…†yNOO½ø ýýþý úJJJÆŸ”ŽPÈÈÈÏÏÏÑÑÑÏÏÏÆÆÆ ···!¬¬¬XUUU¼777Òñ úüýþþþý ú($"àwww—···-ÉÉÉ ÐÐÏÒÒÒÎÎÎÈÈÈ£¤¤@uuu!!!ïö ùýýýþþþþþþýü÷+,,ꇆ…q°®­<ÊÊÉ ÐÐÐÒÒÒÎÎÎÈÈȵµµH]^^Ÿ000Ú øüþþþþýýýþþþþþþþûò><:Ôvro„ÁÀÀ+ËËËÑÐÐÐÐÐËÊʼ¹·¦¥¥Ebcc®%%%å øýþþþþþþ üûûýþþþþþþþþüó:62Ï‹‰ZÅÅÄÐÏÏÑÐÐËËË··¶-~~}lQF@³ô ùüýþþýýýüüENù jwù Uaùûýþþþýüýýýýûôtqp—°«¨0ÌÌÌÒÒÒÒÒÒÌÌËÄÃà ‡‚\BA@Ãöûüýýýþ ý û(-û?Fú&W^ùzŠø´ø ¯Ç÷ š°ø ?Hù üýþý û 'ú %úüýþþüõ=:8È ŸŸeÇÇÇÐÏÏÏÏÏÇÇÆ›™—GD82Èðúýþþýýü$'û OXùv†ø𝸠©Âø ¯Èø ´Ï÷¹Ô÷¹Õ÷­Æ÷ anùüýýý&,úbpùxŠøKVù"û ýþýý úðm_X”º·¶ÍÍÍÒÒÒÐÐÏÊÊɰ®¬*ron•!! ëúýýþþý ü +0ûR\ùø §¼÷³Î÷¸Ó÷ºÖ÷»×÷»×÷ºÖ÷¼Ø÷±Ë÷kyø üýþü5=úˆšø«Ä÷˜°øo~ø4<ûüýýýüñSOM¨°°¯HËËÊÑÐÐÒÒÒÎÎÍÈzrp331Êôýþþþþ þ&*û_iù ‹Ÿø ¥¾ø ³Í÷¹Õ÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»Ö÷³Î÷qƒøüþþþ6>ú’¨ø·Ò÷·Ò÷«ÅøŒ£øXhú %û ýþþý ù;98Ö–ˆ€^ÇÆÆ ÐÐÐÎÎÎÆÆÆœ˜–TWSQ¹ñúþþþý ü'*ü!V^ùš­÷¯È÷·Ò÷ºÕ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ ·Ñ÷„“÷%(ûýþý4;ú•¬ø·Ó÷ºÖ÷¹Õ÷µÐ÷¥¿øƒ—ø2:ú ýýþþú"èvokz¾¾½'ÎÎÍÏÏÏÈÈÉ¥¥¥Befe % ã ùüýþý ýûZcùŸø«ÃøµÐ÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷»×÷·Ó÷”©ø 16úýþý 8@ú™°ø¹Õ÷»×÷»×÷ºÖ÷·Ó÷ªÄ÷…šøDQúûýþýûïZWU¶¥™@ËÊÉÑÑÑÐÐÐÈÈÈ···%pqr´///Ýøüýýýýû AIú |Žø©Â÷µÐ÷ºÕ÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¹Õ÷š°ø ;Cúýþý4;ú”ªø¸Ó÷¼Ø÷»×÷»×÷»×÷¸Ô÷¯È÷•¦øixø'.ú üýýü ø6.*Ï–’JÇÇÆ ÐÏÏÏÏÏÂÂÂ{||‘;;<ï÷üþýý üû38úm|ù¢¸÷´Ï÷¹Õ÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¹Ô÷ ´ø AIú ýþý.2ú¢ø¸Ó÷»×÷»×÷»×÷»×÷»×÷¹Õ÷³Î÷¢»÷~‘øDMùûýýýûæ‚}{¸²®&ÍÍÌÐÐÐËË˾¾¿3egg›öüýýþ üû 6=ú^kù ¡ø®Èø¸Ô÷ºÖ÷»×÷»×÷»×÷¼Ø÷»×÷ºÖ÷»×÷»×÷»×÷»×÷¼Ø÷ºÖ÷»×÷»×÷»×÷»×÷ºÖ÷ ž´øAHúýþý*.úŸø¶Ñ÷»×÷»×÷»×÷»×÷ºÖ÷»×÷ºÖ÷·Ó÷©Ã÷ޤøZhùûýþþûðUKD­±®­'ÍÍÌÑÑÑËËË´´´+‚‚–--.â÷ýþþýû;Fúk|ù•«ø­ÆøµÑ÷¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷ºÖ÷»×÷»×÷»×÷¹Ô÷ ŸµøAHú ýþþ*.ú‹žø·Ó÷ºÖ÷»×÷¼Ø÷¼Ø÷¼Ø÷»×÷»×÷¹Ö÷¸Ô÷±Í÷Ÿ¸ø sƒø2:û ýþþý ö@93Ĭ¬«/ÊÊÊ ÑÑÐÑÑÑÌÌ̼¼¼ˆˆˆqABCÑ÷üþýý ü%,úVeù’¨ø®È÷·Ò÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¸Õ÷ Ÿ¹ø CLú ýþý'*ú‰›ø¸Ó÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»Ö÷¶Ñ÷©Ä÷Ž¢øKVúüýýý ù110Ü‹ƒt¿¾ÏÏÏÑÑÑÎÎÎÆÆÆ ’’vOPQ»ô ûýýþ üû9Búr„ù ºøµÐ÷¹Õ÷ºÖ÷ºÖ÷»×÷»×÷»×÷¼Ø÷ºÖ÷»×÷¼Ø÷ºÖ÷¼Ø÷»×÷ºÖ÷»×÷»×÷»×÷»×÷¼Ø÷»×÷»×÷»×÷»×÷ºÖ÷¢º÷GNú ýþýû*{ˆ÷´Í÷ºÕ÷»×÷¼Ø÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷ºÕ÷°Ê÷—®ø`nù(.û ýýýûëpd_‹ÃàÍÍÍÑÑÑÏÏÎÇÆÆŸŸŸKdde±ô úüýý üûAJúk|ùœ´ø²Í÷¹Õ÷ºÖ÷¼Ø÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷ºÖ÷»×÷»×÷ºÖ÷¼Ø÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷ ¬Â÷Zaù ýýý ü"Xbø©À÷»×÷»×÷»×÷¼Ø÷»×÷»×÷»×÷»×÷ºÖ÷»×÷»×÷ºÖ÷ºÖ÷µÐ÷§Àøƒ–øAKúüýþüöOOO¯žžžDÆÆÆ ÐÐÐÒÒÒÌḬ̀®¬*okj™###ì ùýýýüû29úfvù–­ø¯É÷·Ó÷ºÖ÷¼Ø÷¼Ø÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷»×÷»×÷ºÖ÷ ´Î÷ p~ùûýþ üKTú ¥½ø¹Õ÷»×÷»×÷»×÷¼Ø÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¸Ô÷­È÷Œ¡øTaù#)û üýü ù !!òvvv€ÂÂÂ(ÌÌÌÑÑÑÑÑÐÇÆÆ ­««N420À ôýþþýû*1úT`ù‡œø©Ãø·Ó÷ºÕ÷»×÷¼Ø÷¼Ø÷¼Ø÷»×÷»×÷»×÷ºÖ÷»×÷¼Ø÷¼Ø÷¼Ø÷»×÷»×÷¼Ø÷»×÷»×÷»×÷»×÷ºÖ÷¼Ø÷¼Ø÷¼Ø÷¼Ø÷¼Ø÷»×÷¼Ø÷¼Ø÷¶Ð÷zŠùûþþ ýKSú ¥½ø¹Õ÷»×÷ºÖ÷¼Ø÷»×÷»×÷»×÷ºÖ÷»×÷»×÷¼Ø÷¼Ø÷¼Ø÷¼Ø÷ºÖ÷ºÕ÷³Í÷´øvˆù8AúüþþüòFFFÌœ››KÄÂÁÏÎÎÍÌÌ‹‚}c%Øùýýþ ý$)úQ^ù ‘ø¨Ã÷¶Ñ÷¸Ô÷ºÖ÷»×÷ºÖ÷»×÷»×÷»×÷»×÷¼×÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷»×÷¼Ø÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷ºÖ÷»×÷¶Ñ÷|‹ø ûýþ üJSú £»øºÖ÷»×÷»×÷ºÖ÷¼Ø÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¼Ø÷ºÖ÷ºÖ÷¸Ô÷ªÆ÷ ŠŸøZiù!%ûýýý ûôgUL ±¯­*ÌÌÌÒÒÒÉÉÉjih| õýþý ý08úm€ø›³÷±Í÷¹Ô÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷µÐ÷|Šø ûýý üJSú ¤¼ø¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷¸Ô÷¯Ê÷›¯øjzù%+û ýýþü óCA?¼««ªYÌÌÌÒÒÒÈÈÈfffƒ ùþþý(.û”ø¬Ç÷·Ó÷ºÖ÷»×÷¼Ø÷»×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷¼Ø÷»×÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷¼Ø÷»×÷»×÷¼Ø÷»×÷¼Ø÷»×÷ºÖ÷»×÷»×÷¼Ø÷»×÷¼Ø÷»×÷»×÷·Ò÷|Œø ûýý üJSú ¤»ø¹Õ÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷»×÷»×÷¼Ø÷¹Õ÷¶Ð÷£¾øx‹ø4;úýýýü ú000Þ²²²SÎÎÎÈÈÈfffƒ ùþþý6=û™°ø·Ó÷»×÷»×÷»×÷»×÷¼Ø÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷¼Ø÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷»×÷»×÷»×÷¼Ø÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×÷ºÖ÷¶Ñ÷}Œø ûýþ üLUú¥¾ø¹Õ÷»×÷»×÷¼Ø÷ºÖ÷»×÷¼Ø÷»×÷»×÷º×÷»×÷¹Õ÷ºÖ÷ºÖ÷º×÷»×÷»×÷ºÖ÷»×÷»×÷¹Õ÷¸Ó÷­Ç÷£øLYúüýþý ùTSS³ÇÆÆÒÑÑÉÉÉfffƒ ùþþþ4<û›±ø¸Ô÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷»×÷»×÷º×÷ºÖ÷»×÷¼Ø÷ºÖ÷»×÷ºÖ÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷µÐ÷~ø ûþþ ýLTú¤¼øºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷º×÷¹Õ÷¶Õ÷¸Ô÷¶Ô÷·Ô÷ µÕ÷¸Ö÷º×÷»×÷º×÷»×÷»×÷ºÖ÷ºÖ÷³Ï÷™²øYhùüþþý3/,ܨ£ŸGÐÐÐÈÈÈgffƒ ùþþý4<û™±ø¸Ô÷»×÷¼Ø÷»×÷»×÷¼Ø÷»×÷ºÖ÷»×÷¼×÷»×÷»×÷»×÷»×÷¼Ø÷»×÷º×÷¹Ö÷¹Ö÷¹Ö÷µÓ÷¶Ô÷ ³Õ÷µÓ÷µÓ÷·Ô÷¸Õ÷ºÖ÷»×÷º×÷»×÷¼Ø÷»×÷»×÷»×÷»×÷µÐ÷|‹ø ûýþ üIQú £»øºÖ÷ºÖ÷»×÷»×÷ºÖ÷¹Õ÷¹Õ÷´Ñ÷°Ï÷®Î÷¬Ê÷«È÷©Ê÷©È÷©È÷¯Í÷±Ï÷´Ó÷ºÖ÷¼Ø÷»×÷»×÷»×÷ºÖ÷µÑ÷Ÿ¸øDNúýþýôЉ‰cÍÍÍÉÈÈihg{ õýþý4<ûš±ø¸Ô÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷»×÷¼Ø÷ºÖ÷»×÷»×÷»×÷¼Ø÷¸Õ÷´Ò÷³Ò÷®Ï÷«Ê÷ªÊ÷©É÷¥Ç÷¥Ä÷©Ç÷«Ê÷¯Í÷µÓ÷¸Õ÷ºÖ÷»×÷ºÖ÷»×÷»×÷»×÷¶Ñ÷z‰ø ûýý üIQú ¢ºø¹Õ÷»×÷ºÖ÷ºÖ÷¹Ö÷´Ó÷®Ï÷ªË÷¢Ä÷¢À÷ ½÷ž»÷º÷œº÷ž»÷¡Â÷¥Ã÷­É÷²Ï÷¹Õ÷»×÷ºÖ÷»×÷»×÷ºÖ÷°Ëøcoù ýþýõ†††eÌÌÌÉÉÉkihr ñýþý6>û œ³ø¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷ºÖ÷¹Õ÷·Ó÷²Ï÷ªÏ÷§Æ÷ ¿÷ž½÷›¹÷™µ÷˜µ÷˜µ÷š¶÷›·÷ À÷ªÌ÷¯Í÷´Ñ÷·Ö÷»×÷¹Õ÷ºÖ÷ºÖ÷´Ï÷z‰øûýý üEMú  ·øºÖ÷¼Ø÷¹Õ÷¶Ó÷±Î÷©Ì÷¢Á÷ž¼÷˜µ÷—´÷—´÷—³÷–²÷š¶÷–³÷š·÷š·÷ ½÷¨Ê÷³Ï÷¸Õ÷»×÷»×÷»×÷»×÷³Í÷cnø ýþýõ†††eÌÌÌËËËurokíýþý Dù²øºÖ÷»×÷ºÖ÷»×÷¼Ø÷»×÷»×÷»×÷¼Ø÷ºÖ÷º×÷µÕ÷²Ñ÷­Ë÷¥Ã÷ ¾÷›·÷—³÷•±÷”°÷“¯÷«÷’¬÷’¬÷”°÷”°÷•±÷•±÷“¯÷•²÷š·÷Ÿ¾÷¦Ä÷¯Í÷µÒ÷·Ó÷ ±Î÷z‰ø ûýþ üAJú ™²ø±Í÷­Í÷£Å÷Ÿ½÷š·÷˜µ÷•±÷“¯÷©÷€˜øoøcuøctønø—ø«÷”¯÷•±÷˜µ÷»÷¢Â÷®Ë÷´Ï÷·Ó÷¼Ø÷ ²Ì÷^hù ýþýõ‡ˆˆeÌÌÌÒÒÒÁÁÁ:::Æüþ ý>Eú³ø¹Ô÷¼Ø÷¼Ø÷ºÖ÷»×÷»×÷ºÖ÷¼Ø÷¹Õ÷¸Ô÷³Ó÷¬Ê÷¥Ã÷Ÿ½÷›¸÷—³÷–²÷•±÷”¯÷©÷…øzøwŠø•ø‹¥ø’­÷•°÷•±÷•±÷•±÷–²÷–³÷™µ÷¡¿÷ ¨Ç÷¯Ì÷­È÷w‡øûþþ ý AJú “­ø¥Æ÷ ¾÷™¶÷–³÷–²÷”¯÷‘¬÷ ‹¤øl}øMZù5>ú)0ú&/ú09úFSùhyø ‰¢ø’­÷•±÷—³÷š·÷ ¾÷©Ë÷±Í÷µÑ÷ ±Ë÷"]gø þþþõ†‡‡eÍÍÍÃÃà =??Àûþ ý?Fú œ²ø¹Ô÷»×÷»×÷»×÷¼Ø÷»×÷¹Ö÷¹Ö÷²Ñ÷­Í÷§Ä÷ž»÷™µ÷–²÷•±÷–±÷•°÷’­÷ ‡Ÿøl}ùKVù19ú+2ú8AúVdùv‹ø‹¤ø’¬÷”¯÷”°÷”°÷”¯÷•±÷–²÷˜´÷¢¾÷¤À÷q€ùûýýûDOù‰¢ø˜´÷–²÷•±÷•±÷’­÷ ˆŸø u‰øZhù7@ú û üüü üû.4ú S`ùzøŒ¦ø”¯÷•±÷—³÷œ¹÷¤Â÷¬Ê÷ ¬Ç÷]fø ýþýõ†††eÌÌÌÃÃà =??Àûþ ý?Gú œ²øºÕ÷»×÷»×÷»×÷»×÷¶Õ÷¶Ó÷¯Ï÷§Æ÷ ¾÷œ¸÷—³÷•±÷•±÷”¯÷ ’­÷ Œ¥ø mø JXù%)úüüü üü,2úHTù gwù –ø¨ø’¬ø“®÷”°÷”°÷”°÷˜´÷™´÷l|ùûýüùFSù‚˜ø“¯÷”°÷’®÷Œ¦÷z‘ø\iø@Kù)/úûýýýýýýû#(úAMùewø ˆ¡ø’­÷”°÷–³÷™¶÷¡½÷ £¾÷"`jø üýýõ‡‡ˆeÌÌÌÃÃà <==Áûþ ý=Cùš°ø¸Ô÷»×÷»×÷ºÖ÷µÑ÷°Ï÷¨É÷ ¾÷œ¹÷—³÷–²÷•±÷”°÷•¯÷ ¦øwŠøLXù%+úûýýþýýýý ýû1=úUfù|’øŒ¦ø’­÷”¯÷”°÷•±÷¨÷i{ùûýýúGSø{‘ø‘¬÷ލ÷ }’ø crøALù%,úû üýþ ýýý ýþý üú5@ù^mø}’ø§÷’®÷•°÷˜³÷ ™³÷`kø úûüõ‡‡ˆeÌÌÌÃÃà =>>Àûþ ý??Àüþ ý>Eú ›±ø¸Ô÷·Ô÷³Ñ÷§Ë÷Ÿ¾÷™¶÷–²÷–²÷•±÷•°÷“®øŒ£ø k|ø >Lù ú üýþþþü*1ûHRú guùHRúü þþþþ üû1>úYhùpƒøzŽørƒøGRù üþþ û2:úYiùP]ù6?ú"ú üýþþ þ??Àûþ ý@Gú ™±ø¯Ì÷­Ë÷£Á÷›¹÷—´÷–²÷•±÷–²÷”¯÷ §ø wŠøCMù!ú ûýþþý ý "%ú_mù•­ø¬Æø¯É÷¦¿ø•ø^mù5>úü ýýþýû$û+2û#û üýþýý üûû ûýþýü,.û6fmøŸµ÷³Î÷¸Ô÷ºÕ÷ºÖ÷¸Ó÷±Ë÷™­÷)T[÷ ûýþüû (ú/6úS_ù~‘ø,T[ø$%ù ùù%'(òŠ‹‹eÌÌÌÃÃà =??Àûý ýBIù“­ø¥Â÷Ÿ¾÷š¶÷–³÷–²÷–²÷–±÷•°÷Š¢øU`ù (-úûüýýþý üELúz‰ø¢»øµÑ÷¸Ô÷¹Ô÷¸Ô÷´Ï÷­Èø —®øm}ù GPù %û þýýýýýþþþþþþýýýýþ üS]ù ÷®Å÷·Ò÷»×÷»×÷»×÷»×÷»Ö÷»Ö÷µÐ÷§¾÷r€ø*.û þýýü ûû7;ú$69ùùù ù+,-ò‹ŒeÌÌÌÃÃà <>>ÀûýûHQù Œ£øš·÷—´÷•±÷•±÷”°÷’­÷ާør„ø 6>úüýýýýýü-1úw…ù£ºø³Î÷¹Ô÷»×÷ºÖ÷»×÷¼Ø÷ºÖ÷¹Õ÷¶Ò÷¯Ê÷ Ÿ·ø…™øXcú (+ûýýýþþþþþþþþþþýü$[dù¢¹÷´Î÷¹Õ÷ºÖ÷»×÷¼Ø÷»×÷ºÖ÷»×÷ºÖ÷»×÷¹Ô÷®È÷“¤øXbú"'û ýýýýý ûúùù-./òŽeÌÌÌÃÃà >@@Áúû úP[ù …›ø”°÷•±÷•°÷”°÷Š¢ø xø ISùûýýþþý ü),û&]fù.™ª÷³Î÷¸Ô÷ºÖ÷»×÷»×÷»×÷ºÖ÷»×÷¼Ø÷»×÷»×÷ºÖ÷¸Ô÷µÑ÷¯Éø žµ÷*clø#&ûýþþþþþþþþþþý ûbnø”¦ø®Æ÷·Ó÷ºÖ÷»×÷»×÷¼Ø÷»×÷ºÖ÷¼Ø÷ºÖ÷ºÖ÷ºÖ÷¶Ñ÷°Êø ¤ø KUúüýþþýû úú)*+òŒŽeÌÍÍÐÐÒÎÎÒÎÎÒÑÑÓÃÄÄ BDDÀøú$&ùPZø ƒ˜ø “®÷”®÷ ¦ø vŠøVcù 3;úûýþþþýûFMú‡™ø¬Äø·Ò÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¹Õ÷µÐ÷ž²ø/clø "$ûýþþþþþþþþþþþýû8=ú gtù‘¥ø²Íø¸Ó÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÕ÷¶Ñø¤½øgvú$(û ýþþýü ü õŒeÍÍÍÎÎÓ¿»Í+ˆ‡Á†“ÎyËÌÒÄÄÄ KLL¿÷ù')ùKTø€”ø Œ¥÷ ~’ø^mù0?úû ûýýýý ý04ú"iuø›°ø´Î÷ºÖ÷»×÷»×÷¼Ø÷»×÷»×÷¼Ø÷¼Ø÷»×÷»×÷¼Ø÷»×÷¹Õ÷¹Ô÷ ³Í÷¦½÷€‘øGMú ýýýþþþýý#&ú ü ýýþþþýýý-1ûjxù›¯ø ¯É÷¸Ó÷¹Õ÷ºÖ÷»×÷»×÷»×÷»×÷¼Ø÷»×÷¼Ø÷¸Ó÷¯Éø¦øBùkyø\hø 7?úú ûüþýýýûNZù’£ø ¬Ä÷¶Ò÷»Ö÷º×÷»×÷»×÷»×÷¼Ø÷ºÖ÷»×÷»×÷»×÷ºÖ÷»×÷¼×÷¶Ñ÷¤ºø-{‡øGOú "û ýýþýýþ9?ûBJú#Ybøw‰øhxøCKú!$û ýýþþþýýý8>újwù’¥ø ®Å÷¸Ó÷ºÖ÷»×÷»×÷ºÖ÷»×÷»×÷ºÖ÷¼Ø÷ºÕ÷¶Ñ÷§Áøm}ú07û üýþüé}{fÅÅÄÌËÍÇÄÏ£¡Ï^LVÛÈ%Ìï¨ô"šî„‚º•ÌÌÑÅÅÅ RST¿!##öùúú%'úü üüýýþý ý03ú-r}ø¡¸ø´Î÷¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»Ö÷»Ö÷¸Ó÷³Íøž³÷OWú ü üþþþý ý7>ü ‚ù­½÷¶Æ÷­Æ÷ ˜³÷‘«÷ …›øl|ø#LTùû þýýþþý ýü04ûcnù ¡¹øµÏ÷¹Ô÷»×÷»Ö÷»×÷»×÷»×÷»×÷»×÷»×÷¹Ô÷²Íø”«ø^lùüýþûæi_[𭦍1ˆº¢FJÑê&2Ùð"Ðó °ôò]b³œÆÆÎ ÑÑÒÄÅÅ OPQ¿÷ú ûýýýýýý ý!$üHOù2|‰ø ·÷ °Ê÷·Ò÷ºÖ÷»Ö÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¸Ò÷°È÷š¯ø!juù%(û ýýþþýýý=Hù¸È÷ËÝ÷ÑãöÕæöÑäö ¿Õö £½÷–±÷«÷ ‡ŸøxŒø,SZø +2ûýýýþþýýý26ú1Œö «Ä÷ ¶Ð÷¹Õ÷»×÷¼Ø÷»×÷»×÷»×÷»×÷»×÷ºÖ÷·Ó÷®È÷„˜ø7?ûýýü ö <æ46“î&.±ò$Ãô#Çô¸ô¤ó89㦢½SÏÏÑÅÅÅ HIJ¿øüýþþþýý ü?Eú‰šø ¯È÷µÐ÷¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷»×÷»×÷ºÖ÷»×÷¹Õ÷ ²Ë÷’¤÷(eoø-/û ýýþþþþ üY`û hqù¶Æ÷ÎàöÔæöÕçöÖçöÕçöÓåö ÄÙ÷§Á÷•¯÷”¯÷’¬÷§ø‰¢øm€ùCNúû ýþþþýýüWaùš­ø´Î÷¸Ó÷ºÖ÷¼Ø÷ºÖ÷»×÷»×÷¼Ø÷»×÷ºÖ÷ºÖ÷¶Ñ÷¥¾ø^múüýýý&ú gø —õ¯ô ±õ¡ô"œî‰½]ÍÍÑÎÎν½½#:;:Ëüþþþþþü%'ú#gqøœ°ø ²Ëø·Ò÷¸Ó÷¹Ô÷ºÕ÷»×÷¼Ø÷»×÷»×÷»×÷»×÷»×÷»×÷»Ö÷ºÖ÷·Òø­Èøz‰ù58ú üþþþþþ üû]np÷@ÃÑöÌÝ÷ÑâöÖèö×èö×èö×èö×èö×èöÔæö ÆÛ÷ º÷—±÷‘«÷•±÷”¯ø©ø†œønøLXúý þþþþþýúýýýþþþúMOOÝ®¯¯©äää_ìîî^×îïd$ÖæñÔæöÖçö×èöÙéöÕçö×èö×èöØèö×èö×çöÆØö¡·÷“¬÷‚“÷ gaøO<øC ø=ø7#øNHøq~ør„ø-1ûýþýýý ý-1úqø ªÂø·Ò÷ºÕ÷¼Ø÷»×÷»×÷»×÷»×÷¼Ø÷»×÷¹Õ÷¶Ò÷©Ãøv‡ù%+û ýýýü=ù &iñ”±`ÌÌÏÏÏÏÊÊʾ½½¨£ O`QI Ýúýþý ý "ûcpù”¨ø ¢ºø‚•øKTø ,0ù ù ú úú úúü)0ûvŠø¯É÷¸Ô÷·Ò÷®Æ÷&Š›÷NXù"û ýþþýýüùSTTÚÌÌÌrêêê_ñññiðòòlºäé½'ÕäòÔåöÖçö×èö×èö×çöÖçö×èöÖçöÖçöÕæöÏàöª¾÷ ‚‘ø SCøC ø?ø6ø0ø*ø-ø:(øF4ø6"ù&úúûýýýý  ûXdù“¦ø «È÷ ¶Ñ÷ºÖ÷»×÷»×÷»×÷»×÷¼Ø÷»×÷ºÖ÷¸Ô÷²Í÷Ž£ø@Iúüýýý ùsty£ÄÄÅÐÐÐÑÐÐÊÉɦ¡ž;†…„oGDAÉó ùüýýþü9Aú‚•ø«Ä÷£¼ø Zfù "%ùùú ú ú ú ú ú ú û û#)û†›ø°Ë÷œ±ø/`gø"$û ýýþþþýú;<<厾ÚÛÛkííí_òòò„ðððïëíîõ²áæõ,ÕäõÓåöÕæö×çöÖçö×çö×çöÖçöÔãö׿ö׿÷ ÐÜ÷—øSKøCø?ø9ø6ø.ø'ø&ø*ø 2ø 2!ù)ùùù úüýþý ýý IPú’¤ø²Êø¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷µÐ÷§Á÷[hùüýþýõƒƒƒÉÉÉÊÉÉ‹ŠP5/+Ððûþþþýü19ûYhù –¬ø°Êø¦¿øaoù!#úúú ú ú ú ú ú ú ú ú úúTaùŒž÷CIú üþþþþþ ýùijjë¿ÀÁƒèèè\ïïïlïïï¸òòòäòòóøíïðùÍéì»EØæôÓäö×çöÓäöÓãöÔæöÕæö Ïßö ÈÖ÷ÌÜ÷ ÉÖ÷ ª³÷dZøCø@ø>ø5ø0ø*ø)ø)ø-ø1ø++ø@øùùú ûýþþþþ þ14û{Šø«Åø·Òø¹Õ÷ºÖ÷¼Ø÷»×÷»×÷»×÷»×÷¼Ø÷¸Ó÷¦ÀøSaúüþþü+(%ܪŸ™AÑÐÏÐÐФ¡Ÿ90+'Ôúýýþþý!ûeuù”¬ø«Åø³Î÷ ¥½ø[gù !$úúúúú ú ú ú ú ú ú úúú "ú û ýýþþþýúRRSݤ¤¤²ÚÚÚoììì[ðððiíííÔòòòöôôõ÷òòòüïðñúäîð¢yßçõÓä÷Ôä÷ Ñß÷ ÉØ÷Ïß÷Óâ÷ ÆÔ÷ ¦¹÷ –¥÷ˆø WLøF!ø?ø?ø<ø0ø. ø* ø( ø*ø2ù1øJøeöI÷&øùùú üýýþþýý EOû£ø­Æø·Ó÷¹Õ÷»×÷»×÷»×÷ºÖ÷»×÷ºÖ÷¬Ç÷~‘ø3:úýþû'"àŸ‰VÐÏÏÏÏÏ’’’Nóüþþþþý&*ûv‡ø¡¸ø ³Ð÷ ±Í÷ tƒø%'ùúúúú ú ú ú ú ú ú ú úúùúýþþþþýøuvwÅÝÝÝ_êêê[ððð\òòòuîîîÑòòò÷öö÷÷öö÷øöö÷ùòòòúåêë÷¯âèô0ÒßõÓÞö ÇÖ÷ µÄ÷ ¸É÷ÈÕ÷ ¶Æ÷ }ˆø HDø,ø@ø>ø:ø8ø3ø/ ø+ ø( ø( ø.ø4ù+'ø[÷ vö rö]÷4øùúúúûýýþþ ýýZhú˜°ø´Ï÷»Ö÷»×÷»×÷¼Ø÷ºÖ÷°Ë÷€”ø"ú %ú ýüínki|ÈÇÆÑÑÐÑÑÑ´´´5EFEÐ ùüýþþý ý&+üS\ù øž³÷CKø"#ùúúúúú ú ú ú ú ú ú úúùúüþþþýúrrsÄÚÚÛgîîîYóóó_ïïï®ðððØòòò÷÷÷øøøøùøøøùø÷÷øùôôõùíïïúÔçêÙvÜâÉ,ÆÓòµÅôž÷v…ø u€ùjvù@Cù ù*ø=ø9ø1ø0ø. ø+ ø( ø( ø+ø2ø1ø!>ø oö Œõ õ {ö h÷Fø!)ù "ù--ø=BG÷335ø üýþþýý9Bú–®ø³Í÷¸Ó÷·Ò÷³Î÷£½øj}ø'.û ý ü ü#ævnlyÀ¿ÀÏÏÏÌËËš‹VC?=½í úýýþþý ý(+ú%HNù*,ùùúúú ú ú ú ú ú ú ú ú úúúú ûýþþü@AAÜØØÙaîîîXóóógñññ»ñññõøøøøûûûûüüüýûûûûúúûúùùúùøøùùôõöøêîî÷ßìí¸Ëåèzg©²Ñ&\eé "úýýú ù@#ø Aø>ø1ø+ø) ø) ø( ø)ø1ø2ø+%ø Q÷ õ ¤õ µõ ªõ Šõ vö]÷#S÷JVjùgky÷losøNPTú üþþþý ý6>û r„ù“©ø Œ øv‰ù9Aúüýýü IöLOž¶¦£ÂBÇÆÏ ÐÐÒÒÑÑÍÌ̾¼»„{wlND?µè úýþþþþ û!"ù$&'ùúú ú ú ú ú ú ú ú ú ú úúúúûüþþ ý^_`Ôâãã[óóó_îîî»ïïïøõõõùûûûûüüüýýýýþýýýþýýýþüüüýúúûú÷÷øùôôôúòòò÷ëíî°áææew}}Áüþþ û4NAøq€võEePöI+÷9ø-ø)ø%ø)ø,ø4ø/ øM÷ sö Žõ ±ô Èô Æô ·ô œõ …ö$ö?DôNW“öaj‘÷^d÷ Où#ú ý þüûþü ,4ûü þ ýþ þ1ú rö­ô$ÌðBCÍè‘ÕnÉÊÔÑÑÔÐÐÏËÊʹ´±!™—–K_]\®è ùüþý û,./ù135øùú ú ú ú ú ú ú ú ú ú ú úúúúýþþ ülnnÓæææ\îîî®îîî÷òòòú÷÷øùüüüüýýýþýýýþýýýþýýýþüüýýûûüüúúúùøøùùöö÷÷ñññòêêëР¡ äúþýùy~|÷ÉÌË¢˜ž›ðmyqóD\Lö<ø 0ø,ø.ø3ø1!ø!E÷ nö …õ ¢õ ¼ô Ðô Óó Íô ¾ô §õ–õ‹õ}õ özötö c÷MøSøWøV÷Gù:ù$ù ü ý þ üLùö ›õ ¨õºôÉñ*6Øã†×kÆÆÓ ÐÐÓÑÐÐÎÍÍÇÇǺº¹BFB@«íûýû=?@ø*/3ùù ú úúúú úúúúú ú úúú ûþþþü–˜˜ÔééébñññÍññòú÷÷øøûûûûüüüýýýýþýýýþýýýþýýýþýýýþýýýþüüüýüüüüúúúúööö÷çççÔ••¾ûýýú€€ÞÞß߈ÍÎΫ›Ÿžõƒ‡†úlqoø^eb÷<^Jö>^R÷;?÷ M÷ hö ~ö šõ ¶ô Éô ÙóÚó!×óÏó Åô µô ¤õ Žõ yõ zõ õ zö yö yö yö xö vö pö aö O÷Dù02Mø]cƒ÷bk¹õDLªö'0¡õœõ Ÿõ ¨ôÁñ(ÔìqxÕ}½·Í6ÏÏÒÍÍͼ¹·„||62/Ó ùú>?Aø+-.øù ú ú úúúúúú ú úûûúú üþþþü¤§¦ÕìììbñññÎòòòú÷÷øøûûûûüüýýýýýþýýýþýýýþýýýþýýýþýýýþýýýþüüüýüüüýúúúúååæßkkkÞüýý üTTTÔ·¸¸Âº¼¼Íž¡¡õ““÷‰‰‰úŠ‹‹õ ¡äª¯¶Ì7=†õ vö ö •õ °ô Äô Òó Ûó Úó ÜóÙó Õó Ìô ¸ô †õ ‚õ “õ ¥õ ¨õ §õ §õ ¦õ §õ —õ „õ zõ pö oö(,‚ö‰Œ¹öÔÖèúÈÉåù•™ÒöQWµõ%õ˜õ ¤ô½ò&ÐîroͰÇÇÓ ÐÐÓÐÐÏÊÉÉ ©¦¥3>50Ë !!÷:;?÷+,.øù ú ú ú ú ú ú ú ú úüýý ûú üþþþü¨©©ÕìììbððñÍòòóùúúúúûûûûüüýýýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþüüüýúúúýâââúXXYû ýþþýù¢££º›žŸó‘““õŽõ’””ö›œ¢ôÀÁΧnr§çõ €õ ’õ ©õ Àô Ðó Ùó Üó Þó Þó Øó Ôó Êó ¡ô ‹õ ´ô ¾ô Äô Éô Ôô Öô Ôô Òô Èô ²ô —õ {õ uöyö=@–õÇÉâûóôøüííöüÍÏìùyÎö/7¦õ—õ  ô¼ò'3×ä„‹ÕpÈÉÓ ÊÉɈˆˆZ'))ô35Aø,-.ùù ú ú ú ú ú ú ú ú ú úüü ûú üþþþü©«¬ÕììíbîîïÊõõööøøùøûûüüýýýýýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþøøøýÃÄÅü9::üýþþþ üill̈Ž÷„‡ù‡Œ’ù˜›¨ö³¸Êöfj¨ôô {õ õ ¡õ ¸ô Îô Ùó Þó ßó ßó Ýó Üó Óó ¼ô ’õ ‰õ ¨õ —ô ¡ô Éô ×ó Ûó Ûó Ýó Ùô Ñô »ô Šõ tö töwöŸ½øêêìÖõõöûõõùüááîùŽ’Ñö,4¦õ•õ  ôÆñ6AÖ骭Ô;ÎÏÓÍÍÍ“””V023ñ578ù-/0ùùúú ú ú ú ú ú ú ú ú û ûúú ûþþþý¨©©ÕíííbñññÍõõö÷ùùúúûûüüýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþöööþ¦¦¦ýýþþþþþ ü6Zfù;‡šùI]”÷NS™öZd£ö'„öõ Šõ ¡õ ³ô Êô Öó Úó ßó ßó ßó ßó Ûó Õó ¸ô ‹õ õ ƒõ  ô Äô Ïô Ìô Ôó Õó Ùó Ûó Øô Éô “õ vö tös÷ABaö†‡ŠÒÆÇÇÆïïïëóóöûàáðø}‚Ëö *œõ –õ µô'ÑïqxÕ¢ÊËÔÐÐÏÍÍÍÂÁÁ}|{o"#$ô/12ù245ù$&(ùúú úú ú ú úú ú ú ú úù"##ùúüþþü¨©©ÕìììbñññÎõõööùùúùûûûúüüýýýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþüüüþóóóý——˜ûþþþþýü'ü yö$‘õƒö|ö!‡õ’õ˜õ ¥õ µô Äô Õó Úó Üó Úó Üó Üó Þó Üó Øó Áô “õ õ £õ Âô ¶ô ³ô Ëô µô ¼ô Åô Êô Òô Éô õ wö r÷ [÷ ûû789ðƒƒëÒÒÒ¹åæéüÆÇå÷T[´ô—ô ¢ôÅò6AÙÜÄÅÓ ÑÐÐËËÊ·µ´ƒdjii!å ú"$$ú467ø,./ù#ùùùúúú úú ú ú ú ú!"ù#%%ùúûýýü¢££ÕëëëbñññÎõõõöøøùùûûûûüüüýýýýþýýýþýýýþýýýþýýýþýýýþýýýþýýýþüüüþëëëý|}~ú þþþýü ]÷ zö¦õ¿ô Œõ €õ‰õ ­õ ³ô ¿ô Æô Óô Ýó Ýó Þó Ýó Ýó Ûó Þó Þó Úó Ïô «ô ‡õ ”õ ô •ô Âô ¸ô  ô ¨ô µô Áô Ïô ¾ô “õ vö h÷4ù ýýýúGGHø„„†ù²²½ð‚‡ÂÖ",›ô ›ô ½ó+6ÕßÁÁÒ ÁÀÁÏÏÏÇÆÆŒ„~c>;:½î ùüýü023ù357ù#(+ù !ùùùúú úú ú ú ú úùù ú ûüý üˆˆŠæÜÝÞ—ðððÍôôõõ÷÷øøûûûûüüüüýýýþüüýýüüýýüüüýüüüýýýýþüüüýüüüýúúúüÜÝÝüCEEùþþý ý Xø ¨õ ¾ô Äô ¦ô ›ô Ÿõ ˆõ ­õ Åô Ðô Öó Ýó ßó ßó ßó ßó àó Þó ßó Þó Þó Úó Ãô ™ô „ô ƒõ šõ ­õ ¥ô Ÿô ©ô Àô ×ô Ôó ´ô Œõ sö Bøýýþýýýü:;>óceá+4ôõ ³ô$.Ï髞ÄsÀ¾ÀÑÑÑËÊʰ©¥.hc`ƒëúýþþþýú-/1ù245ù&((ù!ùùú ú ú ú ú ú ú ú ú ú ú úûý ýZ[\Þàààsïïï²ïïð÷ôôõùøøøùúúûùûûûúüüüüüüüýüüüýûûûüúúúûûûûüüüüüôôôú­®®«ûþþý û ˆö ¸õ Òô ×ó Òô ¹ô ²õ Žõ …õ ¾ô Øô Ûó Ýó Þó Ýó Ýó ßó Þó ßó Ýó Þó Þó Ýó Ôó Àô §ô õ …õ ‰õ ¦õ ¬ô Ãô Øô Ùô Éô £õ „õ {÷*@ùûýþþþþý ý$-Aø)7ô™õ ±ô!)Ì¾ž¾¼ÀÏÏÎÇÆÆ™“IA3,É ðüþþþþþ ü$&ú)47ù289ø/34ø&*ù ùúú ú ú ú ú ú ú ú ú úûûþþ99:èÌÌ̃îîïbëëìññññûõõöùùùúùûûûûúúûúûûüüùùúùõõõ÷ôôôöññòòòòóßèèéªPQQèûþþþ û \÷ šõ Äô ×ô Ñô ®ô šõ •õ õ °ô Øô Üó Üó Þó ßó Ýó Ýó àó àó Ýó Þó Þó Ýó Ûó Ôô Ëô »ô ­ô ªô ¹ô Ëô ×ó Ûô Ïô µô •õ ”õ<¥ö XŠ÷ !-úýþþþþþý%;ø4>õŸõ ¯ô'-Ì¾ž¿¼¿ÐÐÐÊÊʵ²±#dWP %#!Ý ùýýþý ý ü26úT]ù&€Žø)…“ø,W]ø3BEø18:ø'+,ù!!ùú ú ú ú ú ú ú ú ú úûüýýùŠŠ‹Àåååfííî˜íííòóóôøøøøùùùúúøøù÷ôôôóîîïêððñ‰îîîƒêêëƒæææw³³´¤PQRï*+,øú üý ûIø qö ¢õ Äô Ñô Æô ½ô Âô ¤õ Ÿõ Ìô Òô Ôô ×ô Öó ×ó Üó Úô Öô Ôô Òô Ñô Ðô Òô Ðô Ñô Ñô Íô Îô Ñô Öó Õó Êô ¶ô ›õ ˜õ®õ#½ô %°õp÷#ü ýýþþý ý?ø$1õ£õ·ô18Îꨰ€¿¾¿ÏÏϼ»ºŒ‹t//.ã øüþþýý üGNù‘ø𮸠¯È÷´Ï÷ µÏ÷©¿÷„”÷#Zcø4>@ø+/0ø"%&ùù ù ú ú ú ú ú ú ú ûüýýüMNNöÊËˈííí[ïïð“ííîìïïïúòòó÷ñññÍîîïœççé|çéêtØÚÞ½ÌÑÖèÊÐцpx|ðJTXõDNR÷?JM÷,46ø ûûGø mö ‡õ ¢õ ¹ô Èô ·ô ³ô ’õ }õ ›õ ½ô Âô Äô Åô Áô Ãô »ô ´ô ¨ô ¤ô¦ô§ô §ô ¬ô ¸ô »ô Áô Çô Íô Èô »ô §ô õ„õ —õ œõ §ô ºô ¿ô •õ Aú&ûü ý üùQ÷õ°ô"Áó=FÓßÂÂÐÁÀÀÆÅÅ d^Z–íûýþþý ü37úq}øŸµø²Í÷ºÕ÷ºÖ÷ºÖ÷ºÖ÷¹Õ÷´Ï÷ ›±÷(kv÷6OSø/8Døù ù ú ú ú ú ú ú ú úûýþýùˆˆ‰Åâââ[îîî\îîî•ëëëñííí¿íîîhâäæ„ÎÓÙÝÈÖÜÓ¾×ÞȰÒÛÜ€ÁÎÈ=–©ó+¤ö(‹¢÷$Š ÷!gtø "'ûû!1ù1o÷!õ ‚ö •õ ±ô ©õ õ {õ €õ €õ›õ­ô ±ô ¬ô Ÿõ ›õ ’õŒõ †õ‚õ€õ€õõ ƒõ Œõ ’ô  ô ¬ô ´ô «ô ˜õ „õ wökö |ö ˆõ õ ¢õ ·ô Áô ¶ô ’õ wöqø k÷%iö‹öªõ½ô",Âñ][¼ÙÈÈÒ ¼¼¼íüýþþþ û"PWù˜¯÷ °É÷¸Ó÷»×÷ºÖ÷¼Ø÷»×÷»×÷»×÷»Ö÷¸Ó÷ «Å÷˜®÷6[dø(.0øù ú ú ú ú ú ú ú úûýþþýø†††¿ÎÎÏpÛÛÛtÜÞ߃ßâäÅÓÙÓ¼ËØæ§ÌÖô|ÌÝö7Åãê-»Ùï²Îõ­Ìö ªÏö ¬Í÷ ¨Í÷ ¤¿÷o„ø,2ù"(ù awø q•øLuøNø sö „ö rö `özõ!™õ"¬õ!¯õ ¤õ Œõ õ |õ zõ ~õ ‚õ ‘õ õ “õ‹õ ƒõ €õ €õ õ ‹õ –õ õ ~õ yö _÷ 1ø7ø nö ö õ œõ ®ô ¼ô ÄôÇô#¿ô%¼ô%®ô#±õ¹õ%¿ó3:ÅêžžÉTÍÍÑ»»»óþþþþý):=ø!”¦÷°Ì÷¸Ó÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷ºÖ÷ ²Î÷+vƒ÷5=?øù ú ú ú ú ú ú ú ûüþþþþýú?BCóowyðŽ¢¦ðš¾ÊóÉÖõbÇÜ÷7Æãö¾àö³Ö÷ °Øö µÛö ±Úö³Úö ³Øö ³×ö¬Ì÷œ»÷GSù @Cù ƒ’ø šø06ûþ'ú 7ùFøjö)’õ+¬ô$±õ ¥õ õ wö qö „õ ˜õ žõ ¨ô ®ô ®ô ©ô £õ ™õ –õ Žõ ‚õ |õ ~õ }õ wõ qö?÷ù ýú Q÷ ô‘ô ™ô ¦ô µô¸ô ¹ô ¸ô!·ô·ô¶ô"1¸ðni³²Á½È!ÒÑÓÂÁÀ.)%ÜùýþþýûIPù„”ø §¾÷¶Ï÷¸Ó÷ºÖ÷»×÷»×÷»×÷ºÖ÷»×÷¼Ø÷»×÷ ±Ï÷*‘÷8CF÷#%ù ú ú ú ú ú ú ú ûýýþþþþ ý "ühv÷=­ÆöCÀÛö4Äà÷¿áöµ×÷ ¯Ö÷²Ø÷ ½ãö Àåö Àåö Âæö Àåö Àåö ¼ßö­Ì÷MYøirù” øvƒøýý û5=ùt‰÷ Fö!Šõ$žõ"¡õ õ õ oõtõõ Àô Èô Éô Ïô Ìô Áô ¹ô ­ô õ •õ ”õ ‚õzõ sõ sö qö4ø ûý ûô/8dÔX]¡«'1™é!í ð ¢ò¤ó¤ò!«ò%¨ñ'2°íab©Ä´¶Ë-ÎÎÑËËËš˜A92-Ì õûýþý ý üKSúv„ø¢·÷¶Ð÷¹Õ÷»×÷¼Ø÷»×÷ºÖ÷»×÷¼Ø÷¶Ñ÷‰š÷4KPø!-/ø ù ú ú ú ú ú ú ûüýþýý ý19û—ø ³Ó÷¾áö¼áö ºßö ¯Öö°×ö ¿äö Âæö Ãçö Ãçö Ãçö Ãçö Ãçö Äèö Âçö ¶ØöO\úŠ–ø‡”ø MVù ýý)LRù”ª÷ ­Ê÷ £Ìö `®õ †õ ‡õ Šõ‰õ ’õ ô ™ô “õ ˜ô »ôÇô Òô Òô Ëô Áô ¯ô ¡ô —õ õ }õvõ kö mö2ø û ø*('܈‰ŠŠ¸¹½¿ÀɹºÉ§¢ºE}pœ¯jg »hf¡¼gf¢¼gf¡»tkš«Žy™ŸÁÀÊÎÎÑÌËˬ£ž9fc`ŒêûþþýýýüIPú “§ø³Î÷ºÖ÷»×÷»×÷»×÷»×÷»×÷·Ó÷™®÷/TYø067ø#ù úú ú ú ú ú ú ûýýýûFRúšµ÷»Þö ¿ãö ºáö ±Öö­Õö ¸ßö Áåö Ãçö Äèö Äèö Äèö Äèö Äèö Ãçö Áçö½åö ¶ØöYgø ˆ–ø w„ø +/ú ýDJú%š¯÷®Ñö ©ÖöÚõYÒõ%¢õ ’õ ’õ ¹ô Ðô Öó Íô ¹ô ¯ô •ô“ô¬ô Äô Õó Ðô Ãô ¹ô «õ ™õ‚õxõ qõ köF÷ ö5.,Ïž™•DÉÉÉÑÑÑÑÑÒÏÎÐÌËÎÉÈÍÉÉÎ ÈÈÍ ÉÈÍÊÉÍÍÌÎÑÐÑÎÎÍÃÁÁˆ}vl0'"Û öûüýþþ ý)/ü†ø¬Æ÷´Ïø¸Ó÷¹Õ÷»×÷¼Ø÷ºÕ÷©Â÷1`hø&?Dø),ùúúú ú ú ú ú ûýý$ûfxù¦Å÷ ½àö Áåö ¸Üö ¯×ö µÜö ¼âö Áæö Ãçö Äèö Äèö Äèö Äèö Äèö Äèö Ãçö¿åöºáö ªÊ÷]_ø ˜¤ø~‰ø15ú-NUøŽ¥ø§ÓöŠ×õRÜõ1Ýô#Öó ©ô ™ô ¸ô Òô Ûó Úó Øó Øô Õó ¿ô °ô œô Žõ¨ô ¼ô ·ô ®ô ¬ô £õ Šõzõvõ rö bô#Gí–”—MÊÊÊÐÐÐËÊÊÀ¿¿ld_‡520Àîûýþþýý,2ûnúœ°ø¶Î÷¹Õ÷»Ö÷»×÷³Î÷~ø3PUø%47ù!$ú ú ú ú ú ú ú ûýýO\ù ¡À÷ »ß÷ ¾ãö ³Ùö ¯×ö ¶Ý÷ Áæö Ãçö Ãçö Äèö Äèö Äèö Äèö Äèö Äèö Ãçö Ãçö½äö ¶Û÷ …œø=Dù ¥±ø´Â÷5Ÿ÷7œ´÷ÊöYØõ+Ýô"Þó Úô »ô œô ¿ô Ùô ×ó ¿ô ¨ô ¢ô ®ô Æô ×ó Ùó Çô ¬ô šõ †õ Šõ ›ô ±ô ­õ Œõ{õ uõ qöuò{~¥iÆÆÊÑÑÑÐÐÐÊÉÉ«¨¦0wtrŠæ ùýþþþþ þ#;>û@ˆ“ø®Åø¸Ó÷ºÕ÷·Ò÷›°÷*ajø*>Bø),ùúú ú ú ú ú ûþ þbsù ­Ñ÷ ¿äö ¶Ú÷ ­Óö ¹àö Ãçö Äèö Äèö Äèö Äèö Äèö Äèö Äèö Äèö Äèö Ãçö¿åö¸àö ªË÷T`ø-/ù³¾ø(ÈÔ÷g­Âö:o¶õ!CÆõ%Ûô Þó Þó Öó ¹ô ¯ô Ïô Íô Áô «ô —ô Žõ †õ ˜ô Äô Ùó Úó Ôô Àô µô Ãô Êô Íô ¹ô‹õ{õ võ tö~°gÌÌÏÏÏÏÇÆÆ¢¡¡Clhe¡)'&Úôûýþþ ý û+RYù ™°ø¨½÷ ²Ëø ªÄ÷v‡÷/CR÷'.1ù úú ú ú ú ú ûü ýR`ù ¬Ïö¹áö ®Óö ¶Ýö Áåö Ãçö Äèö Äèö Äèö Äèö Äèö Äèö Äèö Äèö ÃèöÀæöºãö³Ú÷ xŽø$(ù46ù¾Ê÷[ÄÐ÷‚—¾ö#3®õÁô Øô ßó ßó Ùó Öó Óô Íô ·ô ´ô ´ô °ô ªô ˜õ ƒõ ™ô Ëô Üó Ýó Øô ×ô Úô Ûó ×ô Èô ›ô}õyõ võ}ñƒƒ¬nÉÈÍÑÑÑÎÎÎÈÈȼººphc‰=84Åò úýýý ý#%û-LQúpù”ªø$ƒ“÷+NTø'47ù "ùùúú ú ú úüý3<ú ¦È÷¶Ýöºáö ¿äö Àæö Ãçö Äèö Ãçö Ãçö Ãçö Äèö Äèö Äèö Äèö Ãçö Ãçöºáö ¥Æ÷.7ú ú+?Aø-ÁÍ÷m¹Ë÷]f°ô¯ô Îô Ùó Ýó Þó Ýó Þó Üó Êô ´ô Âô Òó Ñô Éô ¹ô žô Œõ ¶ô Öó ÚóÖóÏó Íó Ôó Ñó Îó ºôŒô~õyõ{óND‚Ô»¹Ã!ÐÐÏÊÉȰª¦/ˆ†…ia]Yµ ê úüýýý ü?ù8:;ù>@õ$&&ùúúúúú¡¢¢üííîý¦¦§úŠ‹Œöx{|÷ûýpqqùÜÜÜý;;;ù]]]º\]]Æ011øþûÔÔÔÌmmm´ úþþ%'ü ¢°÷¦¶÷@Eûþjwù¦²÷ ¾Ì÷ ‚”ø7úƒ÷|‚Þ÷ëìøýííîû|~öacdömpsöGNf÷5C¿ô'ÞóZeèõÑÓïùÅÅÈ댎ŽÙhkjô¬­®âòòòÝüüüüýýýþùùüýÂÆõû.àô Þó ×ó¥ô ~õ €õ ‰õ Œõ ‡õõ {õ {õ{ò;;‰Ñª¨¶CÎÍÏËÊÊzww§GGIó-./øùúú ûüŸŸŸýñññýææçʘššÒwyyö())û&''ú”––î××׺<<<ê^^^ÄddeÌwxxìüûÕÕÕÌmmm´ úþþ ý'*ü&*ü ýþenú®º÷¶Ä÷‡”ù þ`øKTÑõØÙõúòóöüÈÉÊ«„††ë\^`ô@CMøT]´ö /ßô2@ãô·½óúððõøäääôÔÔÔøììíúùùúýüüüýýýýþøùüýÃÆöû.áô Úó Çó ’ô õ ‘õ ¦ô ªô ¦ô ™õ ˆõ ~õ zô~ïpa“²ÆÀÆÎÎͧ˜‘gVVWì9:<ö$%&ùúú ûýžžžýôôôýøøøûìììÍ˜š›ø‚ƒƒú¡¢¢òççç¾µ¶¶÷566ùaaaúttuõ¤¥¦µKKL÷)**úØØØÌrrr´ùýþþ ýü&()üBFFüYú ²½÷MÀÉùcx}ýQWjû$)x÷&-¬õ•éöëìøûóóôúéééȾ¿À説°ùº¾àø:Gâô,âô‰íöíîúýùúûýûûûýüüüþüüüýýýýþýýýþ÷øüý¿Ãöú-âô ×ó ¹ô ô †õ ¥ô °ô ´ô ±ô ©ô šõ ‡õ zõ{òfbžÂÀÉÒÒÓÑÑÐÉÉÈ ‹ŒŒ«EFGô+-.øùúûüžžžûôôôûûûüûùùùýõõõüòòòüõõõúìììùš›œõ$$$ühhhüÀÀÁ¸‡‡‰ìZ[[÷}÷ßßßÌxxx´uvvùüþýü{|}ü°°±üËÍÍüÕåæûPÆÑ÷¯êîûÜäïú•œâ÷(1ÃôšõJQÒõÌÏóù÷÷ûüûûûýøøøüôõõýëì÷ü{ƒìö,âô5BãôÆÊöúö÷üýüüýýýýýþýýýþüüüþüüüýôôûý©­ó÷*ßô Éô ¬ô „ô ˜õ °ô ³ô ºô ¸ô ³ô £ô Œõ {õ{ó?@•ç³³Ç/ÑÑÓÐÐЫ«¬QOQRð123ø"#$ùùú !!øŸ  ¢ççèÍõõø×øøùîùùùðúúúÜöö÷Öààà¾fhhËüpppüêêêôèèèûâããýëëëûçççͶ¥¥¥ú%&&ûþýü°±±üòòòýúúúþôùúýè÷øýìöúýÐÕöùCOåô ÓóŸô'¹õv}ãõîîúýüüýþýýýþüüüþö÷üýÀÃô÷?Käó.áòpyêõàâùúøøüüüüýþüüüýüüüýùùùûçèóéjsäð$Úó ®ô „õ …õ ¥õ ¸ô »ô ¾ô Äô ¸ô «ô õ |õ zõ!%‹ë§¨Â2ÑÑÒÒÒÒ¼½½-nopÇ;<>õ&'(ø "#ùù%'(÷ŠŒŒÀáââaðððXîîï“îîî—òòò[ììì\ÅÅÆ•GHHø(**ùƒ„„ùïððýüüüþüüüþúúûýåååツ„Õ«««ú'((ûþþ!!!üµµµýøøøþýýýþýýýþüýýþñòûü‘˜ð÷*áôÔô §ô¨ô&2Ôô½Àðùõõûþüüýþüüýþùùûüäåøí—œìÐ,9àó-:áô–íöÛÝò÷òòöùùùûø÷÷øõêëîÜÑÓæ¨GRÞêÍó ¡õ }õ õ ¥õ ¸ô ½ô Âô Çô ºô ¯ô ”õ |õ zõ "~즦¾2ÐÐÒÊÊÊ ˆ‰Š‹?ABó)**ø$%&ù#$%ù !ùJLMòÌÌÌuâââUåååWâãã_àààUÖÖÖh‡‡‡Û%&&ú233ø”––ÈææçÒúúûøúúúùîîïõÏÏÏ÷‡†ˆñµµ¶û())ûþý!!!ü´µµý÷÷÷þýýýþýýýþúúüýßàùúGSæô#àô ×ó ³ô ô Ãô^fàôÍÏðùëëðöööùõòòõöääíë²¶äÛJUáò'ßó0=àô¢ÞôÔÖãÒíîó‹êëñ”ÔÕâ·Œ”à¼+5Çñ¯ô ”õ võ |ô¤ô »ô Âô Èô Êô ½ô °ô –õ {õ yô "~ê§§½1ÑÑÒÏÏÏœžnJKLê)+,ø$%'ù'()ù&()ù-//÷IKLñwxy탅†î€‚íNNPí788òù þ()*÷…‡ˆÔÜÜÜvééêÃîîî™ØÙÛ±¯°°§’““öÃÄÄü)**ûþý!!!ü´µµý÷÷÷þýýýþýýýþööüý¨­ñù)7ãôßó Ùó Ãô žô¥ô'ÊósyÙ̾ÁâŽÙÚè¯ããì›ããíj¯´è¸COÛò ÑóÒô*6Ùò—âÓ¶ºé‰­±ç‚’ܰ:BÂñ ô †õ xõoô#!mé/*œè'ÆñËô Êó Èô ¹ô °ô –õ {õyò;=ŠÉ±²Ã%ÒÒÒÑÑÑÂÂÃ?abcÔ/02÷"#%ø*+,øLMOø?ABùúû ûû ýýýüúEGHõ—˜™ÁÊËÌšÚÚÚh¸¸¹nooô±²²÷ÏÏÏü*++ûþý!!!ü´µµý÷÷÷þýýýþýýýþòóûý„Œìø+ßóàó Þó Ìô ¨ô ”ô­ô$.¹ñ?F½ðuzÄð£¥ÚÄ—šØ³V_Ìð#0¿ó¿ô ÂôÈó-8Õñ5AÙï!-Ðï ¿ñ¢ó ‚õoöjô+'^æsck˜‹©o@FÍë"Òñ Ëó Äô ·ô ¯ô “õ {õ{ðyz¦pÇÈÍÒÒÒÊÊÊ'pqrÂ689ô"#$ù#%&ùFHIø[[\ö;=>ùûýýý ü!""úúùù.00÷NPPîRSSÚ:;;ðijj÷ãããûÔÔÔý+++ûþý!!!ü´µµý÷÷÷þýýýþýýýþðñûüu~ëö%Þó ßó Þó Òô ¶ô –õ “õ žõ¤õ!¨ô+2ºó%(³ó§óžõ £õ °ô ³ô ³ô³ô ªô ˜õ õ qöhögòVRx·¾¸ºÄÄÍ ƒÒw%Õî Îó Áô ´ô ¨õ ˆõ zô|í~¨mÌÌÏÎÎη··kDFGó)*+ù !ùù%&'ù+--ù!""úûþþúQTT÷OQQö-00øú ýþ ýý¶¶¶üôôôþ×××ý+++ûþþ!!!üµµµýøøøþýýýþýýýþïðûýs|ì÷%àô àó àó ×ô ¿ô  õ ‡õ „õ …õ Žõ Žõ „õ õ }õ ~õ õ œõ ‹õ |õ xõ yõ söiöjõ,/lí “Ÿ^ÎÍÎÍÍÓ”ÖU*×ì Îó ¸ô ±ô —õ õzô11‚×––´KÏÏÑÒÒÒ¾¾¾_QRTí577÷ ""ùùúú úüýý ü255ùHJKö?BCø*+,ùû ü þPPPøæççüùùùý×××ý+++ûþý!!!ü´µµý÷÷÷þýýýþýýýþïðûýs|ì÷%ßó àó ßó Øó Âô  ô ƒõ {õ xö yö xö uö nö iöV÷Zö eõ aõ \õ [õ hôkñ"%kï26nêww–‡ÈÈËÑÑÑÍÎÓ•š×T%1Ûë Æô ³ô «ô ‘õ |õzòPQ’«ÄÄË ÑÑÒÒÒÒÅÄÄ…ƒ‚³ACCö-/0øùú úûûýýý ý ýü û ûû"##û©ªªøôôôýúúúý×××ý+++ûþý!!!ü´µµüö÷÷ýüüüýüüüýñòûývìø'ßóàó ßó Öó Áô šô €õ {õ zö söX÷]÷ V÷M÷ù õ$"3Ë1/FÎ69[Ì;@uÌBEyË^^€Ç¤¥´;²´¾&ÆÆÊ ÏÏÐÍÍÒ•™ÔV%0Ïí ¼ó ±ô ¡ô ˆõ{ó!{íffœ‘ËËÏÂÁÀVKDÌHIJõ?@Aø,..ù ""ùúú ú úûüüüûú ù !ùsttöááâûúúúýûûûþ×××ý+++ûþý"ü¯´±ûòóóøùùùùüüüüõöüý¥ªòú(6áôàó Üó ×ó ½ô •ô |õ ~õ ‹õ g÷úû ü üýçŽ?ÀÀ ÃÃÆ ÃÄÈ ÅÅÉ ÉÉÌÍÍÏÑÑÒÈÇÐ |wÀ‘¹ï ´ô ®ô —õ õ{ñRR”§ÃÃË ÏÏѽ¼»/-*Ú==?öHJKø=?@ø578ø*,-ø#%&ù ùùúú úû ú úùHIIäÑÒÒÇ÷÷÷üüüüþûûûþ×××ý+++ûþý" û®±°öììíõòòòÂûûûäúúüýëìúýAMåõ%áô Þó Öó »ô ”õ |õ õ ”õ iø ýýþþýåš™˜9ÏÏÏÑÑÒ¼¼Ï77¸ç´ò ±ô ¥ô ô~ó"#~ꜜ¸BÍÍлº¹Üù568ø<=>÷=?@÷;<=ø8:;ø356ø*++ù$&&ù""ù ùùúù566ø´´´÷ôôôùüüüýýýýþûûûþ×××ý+++ûþý&'(ù®¯¯öííínñññañññÔüüüüõöüþÃÇöü-âôßó Öó ¿ô ™õ ~õ |õ ’ö hø ýþþþþåš™˜9ÏÏÏÍÍÒ›Ë=¹í ³ô °ô žõ †ô%'~å}}¨mÇÇÍ ÒÒÓº¹¹× ùù ""ù$&&ø.00ø8:;ø89:ø79:÷588ö*6/ö,10÷-21ù@BBøhiiÚ´µµãðððýûûûþýýýþýýýþûûûþ×××ý+++ûþý*+,÷¯°±Àêëë_îîîgððð ûûûùûûüýâãùü]gçõ&ÞóÜó Çô  õ }õ zö Šö k÷ûýþþü᜚™7ÐÏÏÇÈÑEI¿¹µð ´ô ¬ô ô~ñHJºÄÄË ÐÐÑ»¹¹!Óø"##ù !"ùùù ù,..÷]`a™µ­´°­¯¯õ¶¸¸ùÈÉÉûàààëõõõñúúúýýýýþýýýþýýýþûûûþ×××ý+++ûþý.00ô¶¶·Œéééfííí€òòòoúúúõüüüýööüýÔÖ÷úQ\çõ%Þó Îó ¬ô …õ yõ ~ö vö)ùýþþü7(!Ò­¤¡0ÐÐÏÄÄÏ @E»»²ò ­ó óƒð'*‚ç ¡º>ÍÍлº¹%# Úø)+,ù)+,ùùùù)=0ôÖ××gçççgëëëhìíìÙññò÷÷÷÷ûúúúüüüüýýýýýýýýþýýýþýýýþûûûþ×××ý+++ûþý/01óµ¶¶ˆéééfììì}ïïïjöö÷ñüüüûüüüýö÷üþÓÖùû*8âô×ó ¾ô —õ }õ {õ |õ Y÷ùþþüC0&䩤.ÑÐÐÄÄÍ CE“¼‡óò#ˆæQS”ª  º=ËËÏ»»º&$"Ú ø-//ù.01ù"$%ùù ""ùTWVðÛÜÜvëëëvîîîoðððñññóøøùöúúûúüüüýüüüýýýýþýýýþýýýþûûûþ×××ý+++ûþý.//óµµ¶ŠèèèuìììyìììnïïïŸ÷÷øÔüüüúüüýþïðûýr{ëö&2Ýó Ìô «õ ‰õ zõ {ö löùþþûE2)ζ«§-ÒÑÑÈÈÎNQ“¶"#ê$'‚èz|¨pÄÄÌ ÍÍл»»)'$Þ!!ù-/0ù/12ù$&&ùù'))ùbddðÜÜÜuééékêêênîîîfñññzòòòÙóóôîöö÷÷üüüüýýýþýýýþýýýþûûûþ×××ý+++ûþý./0ôµ¶·Œééélìììëëëpííídñññlóóó×øøøîö÷ûûàâùû¤©ð÷NXàõ!)Ãõ¦õ ˆõ ö göúþþûYSOÀ¿º¹&ÒÑÑÍÍг³Ä%§§¾1ªª¾/ÆÆÌ ÐÐÑ»»»*($ß ""ù-/0ù123ø)*+ùú)++ùhgjîÜÜÜyâââ„åååxááá†ííígðððjððð‡ððñÁ÷÷÷ôüüüýýýýþýýýþûûûþ×××ý+++ûþý'))ø²²³²êëë_íííhëëëmëëëpííímððð^ððñ…óóôäùùûüôôüþâãøû•šçø;D¹öŽö uö8ù ýþþüE2)ζ«§-ÒÑÑÑÒÒÐÐÒÑÑÒ»»»+(%ß!#"ù./0ù133ø)++ùù!##ù[]^ñÛÛÜ…âââƒäääyßàà‰êêêqëëërîîîañññañññïøøùúüüüýýýýþûûûþ×××ý+++ûþý%&&ú¯°°õììì`îîîaìììvêêêjêêêiìììcððð]òòòÅüüüüüüýýùùüýêëôý…‰£ùAú"û ýýþþüD1'媥.ÒÑл»º(&#Û #!ù.00ù234ø*++ùùùFGHòÜÜÜiëëësêêênéééjêêêkêêêiëëëjïïï`îîîéùùùúüüüýýýýþûûûþ×××ý+++ûþý""#ü²³³÷ëëëËïïïjíííwëëëkìììjííízððð{öööÍüüüüýýýþüüýþóóôý•–™úüýýþþþûJ92˸¯«,ÒÑÑ»»»&(#Ü#!ù/01ù244ø+,,ùù ú'((öÒÒÒ¤ááâ}áááoàááháááháááhááámäääjãããïêêêùìììýìììþêêêþÌÌÌý%&&ûþýü©ªªüàààùáááËàààŸÝÝÞŸÞÞÞžááá­ããäòéêêùìììýìììþìììþåååýŽúüýþþþþûUKGĽ·´(ÒÑÑ»»»%'#Ü$ ø012ù345ø,--ùù úûOQQ÷cddÜopqÅz{|Å}€Æ}~ÅwxxÅjklÉZ[[öUVVûUUUýUUUþTTTþGGGþþþþ þ<<<ýRRRýUVVùXZZö]^^ôYZZöYYYøUUUùUUUýUUUþUUUþUUUþQQQý333ý ýþþþþþûE2)嫦-ÒÑÑ»»»-*&Ú!""ø.00ù456ø./0ø ùú ü üùø÷"#$÷!##÷÷ù û þþþþþþþþþþþ þ þ ý ü ý þþþþþþþþþþþþþýB0'ϳ©¤.ÑÐм»»,(%Ú!""ø022ù345ø234ø(**ùúú ú ú ú ú ú ú úûýþýýýþþþþþþþþþýýþþþþþþþþþþþþþþü5)#׬¥¢2ÑÐл»»*(%Ýø,./ù345ø567ø123ø+-.ù%''ù$"ùùùùúùúú ûûûûûýýýýýýýýýýýþþþþþþþþþþþþþþü⟜8ÐÏϽ¼»)%"Ôø())ù234ø345ø456ø456ø133ø,./ù+-.ù)++ù')*ù%'(ù#%&ù"$%ùùúúúúúúúû ú ú ú úûúûüýþþþþþþþþþþþþþüäž›š8ÐÏÏÂÀÀJ<4Ê÷#%&ù,/0ø023ø245ø345ø345ø234ø134ø023ø.01ù.01ù,./ù*,-ù')*ù%')ù$&'ù#%%ù!"#ù "ù!ùúúúúúú ú úúúýþþþþþþþþþþþþþü3)#Ù¬¦£2ÑÑÐËÊÉ ‡ƒ€Œ ñø!!"ø#$%ø(*+ù),,ø*,-ù-//ø./0ø+-.ø),,ø(**ù&((ù%&&ù%''ù$%&ù#$%ù!#$ø ù øùùùúú ú úúúûüýþþþþþþþþþþþþýöhda¨ÅÃÂÒÒÒÐÏ϶±¯)lgd¡/-*Þ ä"!å%$"æ)(&è-,)ç/-*æ0.,å0.,å,,)ç''&ç%%#è"" æ%$#æ&%#è&$#ç!! æããâääâââääääääåäääääååççåæ#â^[Y¯§¢ž?ÎÍÍÎÎÎÆÅÅž›˜F‹ŠMŒŠ‰M‹ŠOŽŒP’O“ŽO’ŽN“ŽO‘OŽ‹OŽŒŠPŒ‹ŠNŒ‹ŠNŽ‹PŽŒŠPŒ‹‰N‹ŠˆK‹Š‰LЉˆJЉ‡L‰ˆ‡LŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡JŠˆ‡J‰‡†M‰‡†MŠˆ‡K‹‰ˆL™”’IÄÂÂ"ÍÍÍÒÒÒÏÏÏÍÍÍÌÌÌÍÌÌÍÍÌÎÍÍÍÍÍÍÍÍÍÍÍÍÍÌÍÍÍÍÌÌÌÌÌÌÌÌÍÌÌÍÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÍÍÍÌÌÌÌÌÌÌÌÌÌÌÌÎÍÍÏÏÎÑÑÐÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ?ÿÿÿÿÿÿÿøÿÿÿÿÿÿÿàÿÿÿÿÿÿÿ€ÿÿÿÿÿÿþÿÿÿÿÿÿüÿÿÿÿÿðÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿàÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿðøÿÿÿððÿÿÿð@?ÿÿÿð?ÿÿÿðÿÿÿðÿÿÿðÿÿÿàÿÿÿ€ÿÿþÿÿøÿÿàÿÿàÿÿÀÿÿÀÿÿÀÿÿàÿÿàÿÿøÿÿþÿÿÿÀÿÿÿàÿÿÿøÿÿøÿÿàÿÿ€?ÿÿ?ÿü?ÿø?ÿà?ÿÀ?ÿÀÿÀÿÀÿÀÿÿÀÿÿàÿÿðÿÿÿøÿÿÿþÿÿÿÿÿ€ÿÿÿÿÿÀÿÿÿÿÿøÿÿÿÿþÿÿÿÿÿ€ÿÿÿÿÿàÿÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿàÿÿÿÿÿÿàÿÿÿÿÿÿðÿÿÿÿÿÿðÿÿÿÿÿðÿÿÿÿÿøÿÿÿÿÿøÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿüÿÿÿÿÿÿüÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿþÿÿÿÿÿÿÿpÿÿÿÿÿÿÿàÿÿÿÿÿÿÿàÿÿÿÿÿÿÿàÿÿÿÿÿÿÿàÿÿÿÿÿÿÿàÿÿÿÿÿÿÿà?ÿÿÿÿÿÿÿàÿÿÿÿÿÿÿñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(`À €”ÑÑÑÍÍÍÄÄĘ™™ˆLNNõûýø‚‚‚ÅÄÄ ÐÐÏÒÒÒÍÍÍÇÇÇ ¶¶¶2‰ŠŠeRSSÀí ûþýüîjb]’»ºº)ËÊÊÑÑÑÒÒÒÍÍÍÅÅÅ™™™QLLL·-..Ý÷ûýþþþþý ø677Ö……„p¸·¶)ËËËÑÑÑÐÐÐËËËÀÀÀYIJJ·ò úýþþýýýþþþþüô;98ц„‚v½¼»ÎÎÎÑÑÐÊÉɹ¸¸„}ykKKK¿õûýþþý ý%)û4;úüýþþýýýüõFDA»±°°9ÉÉÈÑÑÑÒÒÒÌÌÌÂÂÁ ytq~"#"è ÷ûþþþü&*û=Cúbmù•©ø Ÿ´ø JUù üþþû!úüþý ú!ê~}|yÄÄÄÎÍÍÎÎÎÅÅÅŽ_1+(Ù öûþþ ý ûMTù}ŽøŸ¶ø¬Åø³Ìø·Óø²Íø røüþý4<úz‰øbqù%+û þþüöJB=¹²¯­%ÌÌËÒÒÒÐÐÐÉÉɤŸœ:Ħ¡ž9ÊÊÊÑÑÑÏÏÏÇÇÇ£££GRSSµõ úþ ý!ûFQú}‘ø§Áø·ÒøºÖø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×øºÖ÷ ªÁøGMúþþ û‹ø¸Ó÷»×ø»×ø»×ø»×ø»×ø»×÷º×÷ºÖ÷·Óø«Åø„˜ø@Jûýþ ú.+)ØŽŽŽT¿¿¿ÎÎÎÒÒÒÌÌË»¹¹b^[¡ð úü ýû;Cùzø¥¾ø´Ïø¸Ôø»×ø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×øºÖø²Ìø ^kù ýþ ü}ø¶Ñø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷ºÖø¹Õø²Íø˜¯øZhù#û ýûõSTT¯²±±8ÊÉÉÑÑÐÎÎÍ¢›—F<:8Å øýþü29úhwùŸ·ø³Îø¸ÔøºÖø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø³Íøgtø üþ ü|ø¶Ñø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×ø»×øºÖø¶Òø¨Âø~‘ø7@ú ýý ù!""îxtuÂÁÀÎÎÎÊÉÉYXW“ ÷þþüTaù•­ø±Ìø·Ó÷ºÖ÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø´Îøgsø üþ ü|ø¶Ñø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø¸Ôø°Êø—¬øR_ùüþûöKHE´¶¶¶6ÍÍÍÇÇÇRRRŸúþ þZhú¦¿ø¶ÒøºÖ÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø¼Øø»×ø»×ø´Îøhtø üþ ü}øµÐø»×ø»×ø»×ø»×ø»×øº×÷º×÷»×÷»×÷»×÷»×÷»×÷»×øºÕøµÐø¡ºøetù $û ýý ùABBÏ···+ÑÑÐÇÇÇRRRŸúÿ þkzù³Îø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×ø»×ø»×÷»×÷»×÷»×÷»×÷ºÖ÷»×÷»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø´Îøhvøüþ ü ~øµÐø»×ø»×ø»×ø»×÷º×÷ºÖ÷¹Õ÷¹Ö÷¸Ö÷¹Ö÷¹Ö÷ºÖ÷ºÖ÷»×÷ºÖø¸ÓøªÄø”ø19úþþ÷†ƒ‚~ÌÌÌÇÇÇRRRŸúÿ þkzù³Îø»×ø»×÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø¼Øø»×ø»×÷º×÷¹Ö÷·Ô÷¶Ô÷¶Ô÷µÒ÷¸Ô÷¸Õ÷º×÷ºÖ÷»×÷»×÷»×ø»×ø³Îøhuø üþü|ø¶Ñø»×ø»×ø»×÷¹Õ÷·Õ÷³Ñ÷°Î÷­Ë÷¬Ì÷¬Ê÷®Ì÷³Ñ÷¶Ô÷ºÖ÷»×ø»×ø¹Õø±Ëø†šøüþ ûOLJ¸ÈÈÈÇÇÇUTS”úÿ þkzù´Îø»×ø¼Ø÷»×÷»×÷»×ø»×ø»×ø»×ø»×ø»×÷»Ø÷¸Ô÷³Ñ÷¯Ï÷©É÷§Ç÷¥Ä÷£Â÷§Ä÷ ªÊ÷²Ð÷¶Ô÷ºÖ÷ºÖ÷»×ø»×ø´Îøerø üþüz‹ø´Ïø»×ø¹Õø¸Ô÷²Ð÷ªÌ÷¢Ã÷ ¾÷ž»÷œ¹÷œº÷Ÿ½÷¢Â÷¬É÷µÑ÷ºÖøºÖø»×ø¹Õ÷¦¿÷ -1ûþüEEEÁÆÆÆ ÉÉÉYWVŠ ùþ þ où´ÏøºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷¸Õ÷´Ò÷­Ì÷£Æ÷º÷š·÷—³÷—³÷—³÷—³÷™µ÷Ÿ¿÷¨Æ÷°Ð÷¸Õ÷¹Õ÷¹Õ÷³Í÷erø üþü u†øµÐ÷·Ô÷´Ñ÷«Ë÷£Ã÷›¸÷–³÷”°÷“¯÷“­ø”±÷•²÷˜µ÷»÷¨Ç÷´Ð÷¸Õ÷»×÷»×÷ §À÷,/ûþüEFGÁÅÅÅ ÌÌˇ‚€q öþüqøµÏ÷»×÷ºÖ÷»×÷»×÷»×÷»×÷ºÖ÷¸Ö÷³Ò÷­Ê÷¥Ã÷»÷˜´÷–²÷“¯÷ª÷«ø“®÷”°÷•±÷”¯÷˜´÷ž»÷§Æ÷±Î÷·Ó÷¯Ë÷eqø üýü rƒø­É÷­Ì÷£Ã÷œ¹÷˜µ÷”¯÷ª÷˜ø nøj}øv‹ø‰£÷’®÷–²÷›¹÷£Â÷¯Í÷¶Ò÷ºÖ÷¨À÷*-ûýûFGGÁÅÅÅ ÐÐЭ­­,óþüo~ù´Ïø»×÷»×÷»×÷»×÷»×÷¹Õ÷µÒ÷­Ì÷¤Â÷º÷™µ÷–²÷“¯÷ލø~“øj{ùk~ø€–øާø“®÷•°÷•±÷–²÷˜´÷ ¾÷©Æ÷¨Ä÷aoø üþü nøŸ¾÷»÷—´÷•±÷«÷‡Ÿøhyø@Jù(.ú (ú,4úMYù xøªø”°÷˜µ÷Ÿ¿÷ªÈ÷±Î÷¦¿÷)+úþüDEEÂÅÅÅ ÒÒÒ°°°#òþüpùµÏø»×ø»×÷»×÷¹Ö÷¶Ó÷¯Í÷¦Ä÷žº÷˜´÷–²÷”¯øªø €—øZgù.6úûû07úXeùyø‰¡ø«ø’¬ø•±ø–³ø˜´÷œ¶ø \iù üüúh{ø’­ø•±ø’­ø‰¢ø oøMYù+1úüýý ýû4=úbrù…žø’­ø–²øœ¹ø¥Â÷ ž·÷+.úýüDEFÂÅÅÅ ÒÒÒ°°°$òþün|ø´Îø»×ø»×÷·Ó÷°Ï÷¨Æ÷Ÿ¼÷™µ÷–²÷•°ø“¬ø …øaqù/6úûýþþý ü!û >Kúh{ù†Ÿø«ø”°ø–²ø©ø Xfù üý#údvøŒ¦øŒ¦ø xŒøP^ù,3úû ü ýýý ýý ü%-úQ_ù}’ø©ø”¯ø˜³÷ ”¬÷15ùûûFGHÁÅÅÆ ÒÒÒ°°°$òþüm|ù³Îø¹Ö÷¶Ò÷ªÊ÷ À÷™¶÷—³ø•±ø“®øާø pƒø =Gúûýþý ýüü ýþ ýû>Iúj}ù…žøާø‹¤ø Vcù üþúaqù|’ø^mù4?ùû üþý.2ûhwù{‹øGOú ý ý ü#úCNùizø„›ø«ø ‡žø 8<ùúøEGGÁÆÆÆ ÒÒÒ°°°#òþüo~ù±Ìø±Ï÷§Æ÷š¸÷—³÷–²ø”¯ø«ø~“ø GQú!û üþþ ý-3ûgwù¢øƒ–øFPú%û ý þ ýû3;úNZù HRù#üþþ ü)/ú.5úû üþ þ!#ûepùŸµø±Ìø³Îø «Ãøƒ•ø49ú ýþû'/úDPùl~ù~’ø&7:ùù÷KLLÀÆÆÆ ÒÒÒ°°°#òþ üm~ø¤Â÷ À÷™¶÷˜´÷•°÷“®øŒ¤øYeù"(û üýþþ üR[ù ¥ø¯ÉøµÐø³ÎøªÄø–­øcsù 5<ûý þ ý ý ýýþþþýýýþýOXù”¦ø ¯Éø¸Ó÷ºÖ÷ºÖø¹Õø³ÎøŸµ÷Xdùý ý üüûELù")*ùù ""÷QRSÀÆÆÇ ÒÒÒ°°°#òýûl}ø—³ø—³÷–²÷“®÷Œ¥ø pƒø 5=úýýþþ ü=Bú‰›ø ­Æø¶Ñ÷ºÖ÷ºÖø»×øºÕø·Òø°Ëøž¶ø ‘øISúüýþþþÿþþþþ ýT\ù¡·ø³Íø¹Ô÷ºÖ÷»×÷»×ø»×øºÖ÷·Óø«Äø…–øAKúüþþý ûú!!÷STUÀÇÇÇ ÒÒÓÒÒÒÒÒÒ±±±$ð û(,ú l}øªø“®ø¦øv‰ø O[ù!ûýþþ ý.3ûo|ù¤º÷µÐø¹Õ÷»×÷»×÷»×ø»×ø»×ø»×øºÖ÷¸Ó÷²Ìø Ÿ¶ø"akø ýþþþþþþþþý27úo{ù œ²ø±Ìø¸Ó÷»×÷»×ø»×ø»×øºÖøºÕøµÐø¦¿øm}ù#(ü ýýýûøOPQÁÆÆÆ ÎÎÓ¿½Î#µ·Ï+ÍÍÒÒÒÒ²³³#%''ïú,0ùesøŠ¢ø ~“ø Scù)/úûýþýüPYù“¨ø²Íø¹Ôø»×÷»×÷»×÷»×÷»×ø»×ø»×øºÖø¸Ó÷ °Ê÷œ±÷alùüýþþýý üýýþþþý 28ûn}ù¡¸÷²Íø¹ÔøºÖø»×ø»×ø»×øºÖø¹Ôø²Íø¦ø?Iûýþþý??@È»»»ÏÏÏÒÒÓËËÓ«­Ò:RT¼Ï?F±×ÁÂÍÑÑÓÒÒÒ´´´#./0î ù"#ù'OVøU`ù,2úûüþþ ý-0ú ~ø ©Áø¶ÑøºÕø»×ø»×ø»×÷»×÷»×÷»×ø»×øºÕøµÐøŸµø%blø,0û ýþþ þ!ý R\úcnø zø_mù27ûýþþþþý6<úm{ù¤¹ø³Îø¹Ô÷»×÷»×ø¼Øø»×øºÖø¶ÑøªÄøs„ú#(û ýþõYVS˜¿¾ÀÄÄË ›—Ët;FØ×#»ð$ŸíŽÀsÎÎÑÒÒÒ´µµ#./0ïú û û ýýþýý/3ûdpù µ÷³Í÷¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷¸Ô÷µÐø®Çø{Šø-1û ýþþþý htú½ÎöÈØ÷ÄÛ÷ ¦¾÷ “­ø‡Ÿøk{ø;Aúü þþþý ý *.ûv…ø¬Ä÷·ÒøºÕ÷»×÷»×÷»×÷»×÷¹Õ÷²Í÷§ÀøXfúý ý ø3(&Ùif™©6>Âì +Ïñ¿ó¥ñaa«§ÆÆÏ ÐÐв²²#"$$ð üýýýý ý/4ûù ¤¼÷ ²Ì÷¸Ó÷»×÷»×÷»×÷»×÷»×÷»×÷»Ö÷ºÖ÷¶Ñ÷¦½÷"zˆø9>ûýýýý ýJOû xƒùÄÕöÑâöÕçöÔåöÎáö °É÷—²÷‘«÷ ‰¢÷zøTdú(/û ýýýýýKSú”§ø²Ì÷¸Ó÷»×÷»×÷»×÷»×÷ºÖ÷·Ó÷¯É÷‡œø3:û ý ü "úkö õ°ô¦ó)/žè¿ÀÍÑÐÐÈÈÈ—–•Qöþþþ ý"%û Yaù˜«÷¬Åø°Êø³ÍøµÏ÷¸Ó÷ºÖ÷»×÷»×÷»×÷ºÖ÷¹Ó÷²Ë÷ “§øHPú üþþþû/00ôgwyç0ÄÒôÎÞ÷Ôåö×çö×çö×èöÖçöÎâ÷ ®Æ÷ ˜²÷’­÷‘«øŠžø{ø\kù-3ûýþþ ý )-ûjxùž³ø ´ÎøºÖ÷»×÷»×÷»×÷»×÷ºÖ÷µÐø›³øQ^úý þýBù ~ö •õ% é¼½ÌÒÑÑÎÍÍ¿¿½~uou'%$ØûþþüGNù†—øŸµ÷ŒŸøgvùVbùUaùguù•©ø²Ìø¹Ôø»Ö÷¹Õ÷·Òø §½øq~ø ,1û ýþþý!!"òvwwÍÄÅŇÍãä~"ÒãóÕæ÷×èö×èö×èö×è÷×è÷Õæ÷Å×÷›³÷‘ªø ‚‘øe_øXHøQHøhrøbqù%)üýþþý9>ûŽ ø±Ìø¹Ôø»×÷»×÷»×÷»×ø»×ø·Óø¬Æøx‹ù"'û ý þ%û c÷)2–ê¼½ÈÓÓÓÑÐÐËËÊÀÀ¿¦žšJSMJŸòüþ ý $(ûkzø˜®ø‚•ø NXù "&ù ú ú úû#(üx‹ù°Êø·Ñø ¯È÷ŒžøDLúüþþþ û(()ò¢¢£™äääeìíîkÈèë™%ÕåóÖç÷Öçö×èö×èö×è÷×ç÷Öç÷ÎÞ÷ ¢µ÷ t{øH*ø@ø6ø/ø3øKBù;/ùû ûýþ þ %*ûsƒù £¼ø ³Ï÷¹Ô÷»×÷»×ø»×ø»×ø¹Ôø³Îø—®ø?Hû ýþ ý'ô°°´@ÌÍÍÎÎξ½¼}yvlDB@Íô úýþüAJú ¥ø¢ºø _lù"$úú ú ú û û û û!û‡œù ·ø(\dùû þýþýø\]]ÎÆÇljèèèbïïïªíïïô½ãèô,ÕåôÕæ÷ÖçöÕæöÖçöÔå÷Óâ÷Óã÷ ÌØ÷ {€øI-øAø9ù1ù)ø(ø0ø 0%ù$ùúúüþþ þ"%ýw„ù­Å÷·Òø»Öø»×ø»×ø»×ø»Öø¶ÒøªÄøWdúýý û:::׺º¹ÑÐÐÒÒÒ¼ººJGE¯õûþþýCNùvˆù¦¿ø¥½ø \iø"ùú ú ú ú û û û û úAJú5:û ýþþýú==>î ¡¢¶àààaëëëwîîîáóóôôðñòùÞîð²OÚçõÔä÷ Òâ÷ Ïà÷Óä÷ ÌÚ÷ µÅ÷ ¯¾÷ „‡øN2øAù>ù2ù-ù)ø*ø2ø'2øPø%ùùú üýþþý LVú–«ø±Ìø·Óø»×ø»×ø»×ø»×ø¶Ñø¢»øO[ùýýó†wnyÐÏÏÑÑÑ¡¡ :ðüþþþ!ü zŒø ¦¿÷­È÷myø#%ùúúú ú ú û û û úú ûýþþýùxxy»ÐÐÐqéééaïïïyïïïãõõõööö÷øóóôùåìíìàèõ ÑÞõËØö ·ÇöÂÐ÷ ¸Çø |†ø HBøB%ø@ø:ù5ù/ù*ù)ø.ø1øO÷ pö`÷7øùúû üþþ ý"ý bqú¢»øµÑøºÖøºÖø¹Ôø°Êør‚ù-4úü ù30/ɱ®¬(ÐÏÏÒÒÒ¼½¼"JGEÄ øüþþ ý$)ü[gù&‹œ÷9>ù ùúúú ú ú û û û úúûýþþ ûttt»ÝÝÝdîîïcððð¯ññòåöö÷øùùúùøøùùöööøîñòùÑéëÑeÕÞÒ,´ÂíŒõbmù W`ú42ù&ù<ø8ø0ø.ù*ù)ù,ù2ø)(ø nö ’õ Œõ röK÷2ø!03øGKP÷((*û ýþþýAKû–¬ø¯Éø®Èøœ´ø`où"ü ý û<5@ɦ¥ª.ÊÊËÍÍÌ­©¦2ha\’$"!á öüþþ ý&)ú%'ùùúú ú ú ú û û û úúú üþþ##$÷ÈÈÈoííícïïï±òòóöúúúùüüüýüüüýûûüüúúúúöö÷øêïïùäî﮲ÎÒ?Y\Ü ü þ ù*I6÷%Q3÷@÷1ø*ø(ù)ù0ø/ øM÷ ‚ö ®õ »ô £õ ƒö jöEM~öbgˆölpø$)<úýþ ý ý,7û ZjùLWú/6ûüý)ú tõ9B½È›–ÆjÇÈÒ ÑÑÔÏÏÎÉÈDZ«§,xvt~*((Ø ÷üþ ü,-/ø%&'ùú û ú ú ú û û û úúú ûþþ001õÏÐÐnííî°ððð÷öö÷ùüüüüýýýþýýýþýýýþüüüýúúúùøøùøññòõäåæÂ~€ã ýþ!ø¥«¨Ú—Ÿ›àWl^ó"H.ø 2ø ,ø0ø2 ø F÷ uö šõ ½ô Ïô Ëô µô˜õŠõ%~ö%ötö T÷>ùFùEø 9ù &ú ü ý ýIùˆö¥ô½ñ#/Óë†ÕmÇÇÓ ÐÐÓÏÏÏÊÊÊÀÀÀuqp| é úú9;<ø"%ùú ûúúúûû û ûûúüþþNOOôÚÚÚsðððØôôõøúúûûýýýþýýýþþþþÿýýýþýýýþýýýþüüüüùùúøååæÑttuÎ ýþù½¾¾¦ÍÎΠ—›šõ|~ùhnl÷Qk`õ;VZö "T÷ oö õ µô Íô Ùô ØôÏô ¿ô ©õ ˆõ ~õ õ ~õ |ö zö zö tö h÷ T÷ "Røfi‰÷tz½öIP­õ'Ÿõ õ²ò%ÍìqtÑŒÁ½Ï&ÐÐÓÑÐÐÈÇÇ ­«ª?GA=º÷89:ø ""ù ú û ú ú úû ûûý ûúüþþVWWõÝÞÞtððñØõõöùûûûüýýýþþþþÿþþþÿþþþÿþþþÿýýýþýýýþûûûýåååöNNNöþþ ûkllਪ«å–˜™ô‘‘ö‘ö°²»¼Z_•ê|õ Œõ ¬ô Èô Öô ÛôÝôØô Ñô µô õ  õ ºô ¾ô Åô Äô ¿ô §õ Šõ vövöMQ›öÏÐäûØÙíúŸ¢×ö?H°õ›õ©ó'Éíx}Ô€ÉÊÓÊÊÌÍÌ̲±°!'()ñ24<ø!#$ùú ú ú ú ú ú ú ûü ûúüþþXYZõÞÞÞtïïðÕöö÷÷úúûûýýýþýýýþýýýþýýýþýýýþýýýþýýýþúúúþÑÑÑû566üþþþ;<=ã‰é…Šø‹˜÷§ª»öfk¦çôˆõ ¢ô Àô Õó Ýó Þó Ýó Úó Îô ™ô “õ ©õ ¤ô Ëô Øô Ùô Ùô Ðô ¸ô ƒõ wö{õ²³ÌðêêîñììôûÃÄá÷IO´õ›õ®ó)4Ð囟ÔUÆÆÌÐÏϾ¾¾456î356ø%&'ùùú ú ú ú ú ú ú úúúüýýXXXõÝÞÞtññòÖ÷÷ø÷ûûûûüüýýýýýþýýýþýýýþýýýþýýýþýýýþ÷÷÷ý´´´ýýþþý ü&>Xù4m–ø@GöIQ™õ#†õ‹ô  õ ¹ô Òô Úó Þó Þó Þó Úó Ëô “õ ‚õ —õ ¿ô Èô Îô Ïô Õô Öó Êô Žõ vöqõAB[‹ßÒÒÓÛçèîðº»à÷9B¨õô¿ðU^Ö¾¿ÀËÏÏÏÆÆÆ ¶µ´…~pô+-.ù,.0ù!ùúú ú ú ú ú ú úú !!úûýþVWWõÝÝÝtñññ×öö÷÷ûûûûüüüýýýýþýýýþýýýþýýýþýýýþýýýþôôôþ£££ûýþþü Gù ö£ôõ‰õžõ ¬ô »ô Íô Úó Ýó Ûó Ûó Þó Ýó Ðô ¥ô ‰õ ®õ §ô »ô µô ±ô »ô Çô Æô ’õ s÷ T÷üû?AAõ˜™šàÊËÕúy~Áð"™ô®ô+6Ôàº»Ë |{|ÑÑÐÌË˳°®%d`]é øüû145ù#(,ù ùúú ú û û û úúú ûüþIIIôÏÏКððð×õõö÷úúúúüüüüýýýþýýýþýýýþýýýþýýýþüüüþîîîþjklú ýþ þ Zø ¤õ »ô ¥ô —õ ˆõ ³õ Çô Òô Üó ßó àô àô ßô Þô Þô Úô Äô ”ô †õ –õ ¯ô ¥ô ¨ô Äô Öô ºô ˆõ e÷ûþþýý459újl×%-›ô§ô$.Ë笥ÃF{z{ÏÏÏÇÆÅ”ІR/,)Ï øýþþ ý $&ù156ø&()ùùúú ú û û ú ú ú ûûþ$%%÷ÈÉÉ€ììíµññòööö÷øúúúúûûüüüüüýüüüüùùúøúúúøøøøúËËËÜ.//ìýþû ˆö Âô Õô Îô ¯ô •õ ‘õ Êô Ûó Üó Ýó ßô ßô Þô Þô Ýô ßô Öô Àô £ô Žõ ‘ô °ô Äô ×ô Ïô §ô ƒõ5q÷ #ûþþþþ ý$6ù&1ô¤ô!)Çí¢”¼xzxzÑÑÑËÊʲ­ª*fb_‹ìúþþ þü4:ú&Zcø-INø0:<ø&+-ù ùú ú ú û û û ûûüþú““”ºæææzíííäóóóøùùùøúúúøøøùøóóôêñññÆíííÀæææŸ‘‘½$&&ù üý ûWøœõ Èô Êô ¬ô ®õ Žõ Ãô Õô Øó Ûó Úô Ýô Ûô Øô ×ô Öô Öô Òô Ëô Âô ¿ô Ìô Öô Ïô µô ˜ô¦õ:®õ Wøýþþþþ3ù%0õ©ô*2È뤓¶qzyzÐÐÐÂÁÀŽk1-,Ö øüþ ý  üQ\úøžµø«Ã÷›¯÷ p}ø.GKø(/2ø""ùú ú û û û û ûüþýHIIíÓÓÓzííí€îîîæòòò÷óóôèïððºèéêãæè†ÐÖÛÍÁÉË•[fiïALQö3=AøúûNø }ö £õ ¿ô ¿ô ¸ô “õ •õ ¼ô Åô Èô Æô Æô ¾ô ³õ ®õ°õ °õ µô ¾ô Âô Èô Ìô Âô ªô õ “õ  õ ²õ °ô lø-ûüý üFø”ö·ô6?Îä¶²Â{z{ÊÊÊpli„ïüýþü==¾ûþþý#SZùž·÷³Îø¹ÕøºÖø»×ø»×ø»×ø»ÖøµÑ÷ ªÃ÷1_gø')ù ú û û û û ûûþþüùjkmȨ­¯¶¶Áĵ¼ÏØÚ É×ójÉÝõ2Âàõ³×õ±Òõ «Ñö «Îö©Ë÷œº÷JWù9Aù |ø Rhù 2ú ]÷Z÷hö$•õ%®ô©õ Žõ zõ {õ ƒõ ‘õ žõ õ —õ õ Šõ õ ƒõ ‰õ |õ nö9øù O÷ €õ ’õ ¥ô ¸ô¿ô"»ô$¸ô"µô"¹ò08¼èŸšÂ[ÆÆÊÉÉÉMJH¯ øþþý!>Cù‚‘ø ©ÁøµÏø¹Õø»×ø»×øºÖø»×ø¼Ø÷ ±Î÷.s~÷(46ù ú ú û û û ûüþþþ ý û$U`öO¯ÃóPÃÜö Ááö¸Ú÷ ¯Ô÷ »á÷ ¿å÷ Àå÷ ¿äö ¾âö¯Ð÷euøpxø ˆ•ø.1û ý !û[oø7‹ö$—õ#¥õ õ zõuõ›õ Âô Âô Éô Âô ¶ô §õ ˜õ ’õ €õ xõ sö eö!ù ý ùBðHNš¹#+šê#¡í#¦ï"©ð$ªð'«ï.7®ê~»ÊÊÑÊÊËÎÎί­¬(G?:½÷ûþ ý ýBJûx…ø¯Èø·Òø¼Øø»×ø»×ø»×÷ µÐ÷%~Œ÷)?Cø!ù ú ú û û û üþþýühzù ¯Î÷¼ß÷¸Ü÷ ²Ù÷ ·Ý÷ Áå÷ Ãç÷ Äè÷ Äè÷ Äèö Ãçö ¹Ü÷l~ùŠ—øfqùü#&û&zŒ÷ ¥È÷ ™Êö ;Ÿõ Œõ Žõ ™õ «ô ¢ô —ô ­ô Àô Óô Ìô ¿ô «ô ›õ õzõ mö aö"÷õHFE¶²³¶;¾¿ÈººÊž•±d«Ž~}­~}­†©†¥˜°aÈÈÏ ÑÑÓÎÍÍ»¸·|xuo"ç ùýþýý R]û¡ºø²Íø¸ÓøºÖø»×÷·Ò÷¥÷0KQø(-ù ú ú û û û ûþ ý7@ú‡ ø¶×÷ »ß÷ ´Û÷ ²Ù÷ ¼â÷ Âç÷ Äè÷ Äè÷ Åé÷ Äè÷ Äèö¾åö µØ÷rø øPYù.3úvŠø¢Ë÷„×õKÙô )Âô –ô ©ô Îô Õô Ñô Êô ±ôžô žô ¿ô Æô »ô °õ šõ~õtö köFòSPU§¼»ºÎÎÎÓÓÓÒÑÒÏÏÑÌÌÏÌÌÏÌÌÏÍÍÏÐÏÑÒÒÒÐÐÐÉÇǤŸ:OJG¦ã ùýþ þ.5ûesúš°ø´Íø¹Ô÷¹Õ÷¥½÷&akø'8;ø!ù ú ú ú ú ûþ &û‡¡÷ ¸Ú÷ ºÞ÷ ³Ùö ¶Ýö Áæö Ãèö Äèö Äèö Äèö Äèö Äèö Ãçö»áö ªÊ÷QYù ¡­ø ‘Ÿ÷6…š÷ˆÇöU×õ,Þô ×ô °ô ±ô Òó Ñô µô °ô Áô Ñô Îô °ô ô •õ ›õ ¬ô §õõ vö rõ26{Ͳ´»!ÎÎÎÍÍÍÆÅÅš–”OCB@»î ùüý ý),û9|‡ø ªÃ÷³Î÷ ²Ì÷ €÷)ELø(+ù ú ú ú ú ûý/6û ž¾÷ ºßö ±Öö ¸ßö Âæö Ãçö Äèö Äèö Äèö Äèö Äèö Ãçö¾åö³Ùö~”ø15ùµ¿÷Q¶ÉöDpµõ8Èô #Ýó Þó Òô ¹ô Èô Åô ¸ô  ô “ô Žõ µô Õó ×ó Èô ¿ô Ëô Íô ²ôõxõ vôEI“¿ÃÃÊ ÒÒÒÍÍÍÅÄÄš—–QTPL¨ñ øüþüDKú(~Œ÷Ÿµ÷•ªø,P[ø!03ùù ú ú ú ûü"ü ˜¸÷µÜ÷ ¸Þö Áæö Ãèö Äèö Äèö Äèö Äèö Äèö Äèö Âçö¸ßö¿÷ 2:ù!8:ù!¾Í÷z¡¿ö-;±õÊô Üó Þó Ûô Ûô Îô µô ¿ô Àô ¶ô šô Žõ Æô Úó Ùó Ôô Ôô Òô Åô‘ô}õyô<:ˆÒµ°¼+ÑÑÒÒÒÒÎÎÍÇÆÆ«¥¢4mkk“3/,Ù÷ü þ ý'+úU`ø,MRø,02ùú ú û ûûüþ …žø°Ó÷·Þ÷¹á÷ ¾â÷ ¿å÷ Áç÷ Âç÷ Äè÷ Äè÷ Äè÷ Ãç÷ ¹Ü÷i|ùüPSùU¼È÷j‚»õ(¯õ Ñô Ûô Þô Þô Ýô Ñô ¸ô Âô Òô Ñô ¾ô £õ±ôÒô!Éô"ÌôÙô Ûó ×ó ÃôŽõ}õ#%„ì•—·XÏÏÑÏÏÏÉÈÈ ¸··(vvvŠ964Ïö ùü ýú-12ùú ú û û û û%&ú\|‚÷9…’÷† ø®Ò÷ ¯Ó÷ ¯Ô÷»á÷¿å÷ Ãç÷ Äè÷ Äè÷ ¿â÷œ¹÷.5ücjú «ø'´Á÷Q“¾ö/¥õÌô Ûô Þô Þô Ýô Ðô ¶ô ³ô ¿ô ¸ôŸõl÷45“öcfÏ÷qtÓ÷krÝõ&3àô#ßôÞó Öó ¨ôõ‚µ\ÌÌÐÐÐÐÊÊʸ¶´"žTRPN¦ç úú/12øù ú û û ûúHJK÷‘––¾'(ûý?Kû  À÷±×÷¹á÷¼â÷ ½à÷ Ãæ÷ Àã÷ ©É÷GTúý FLû‹—ø¥²÷/–±ö$7–õ¾ô Øô ßô ÝôÕô°õ!‡õCH¿ô!Õô"-Ðô8Kåô#ßó Üó ºôƒõòSUŸ½ÂÂË ÏÎÐÒÑÒÒÒÒÍÍÍÆÆÅ ›šGNMK²$$#ê57:õ !ù ú ú û úú‰ŠŠø™ššäûþ ý9~Œø!µØö¶Úö«É÷œµ÷2³Ë÷±Í÷ Ucú ýý!ü›¨ø%¦÷`ƒö7B‰ö›õ Ïô Ûô!×ô¹ô&,ö5ûPX¦ö%Ùô"0ÖôAEmø þýœëóóóüúúýþðñûý¥«òø)áó Üó Àô‡õ|õ!#‡éof’ž¡•°dÿÇÏÏÑÑÑÑÎÍÍÅÄÄ”ŽVOII×%),öú ú û ú!$$ù¹»»óŸ  ûýýýzƒ…ûk¡¬Ð&kyø1U]ø"üDªõ(,=ùü=Gr÷+Õô)×ô7AuøýüY[[ÝçççóýýýýùùýþÈÌöù-âó Úó ·ôõzõ{ô~ò()†íf^™¿¸µÃ,ÎÎÐÒÒÒÌÊÊ—„|h==>òùú ú ú033ùÕÕÖÓ¤¤¤üCDDùúý€‚ûŒüIMNá=AAæ ýüÀÁÁÔ$%%óý ý biú ­¹ø ©µø ILùdoø ¡÷ }ö™õJOÂõ¬°ÍøDGKù*,.ø@DS÷6BÓô*Úôv|½ö@AGúTVWøKLLõàààµüüüüúúýþËÎ÷ü /áó Ûó ²ô õ zözözõ zõ~ñTOż¸À!ÐÏÑÑÑн¼»LLMNî'((øúúû!##úßßßüµµµû†ˆ‰÷EFGøý„……úûRRRÌMNNÔûûÊÊʲ'''îþýclú¥³øDIû ??ûýýüéêêþïôôþÎíñüÝíöü–Ÿë÷(Óô¢õU]ÖõÚÜöû÷÷ûýüüüþòóûýš ðö.<ãóluêõåæùûøùüýüüýþûûüüððø÷–éï'Öò ô ‡õ ¨õ ·ô ¼ô Áô ¯ô ”õ }õƒíй_ÎÎÑÊÊË‚ƒ¥9:;ô#%&ùù*--ö»¼¼“èèè\êêê‹ëëëqäääa­®®´)**ørstõëëëúøøøûõõöúÜÝÝ݆‡‡ôCDDûýý•••üóóóýûüüþøùüýÚÝøúHUæô Öó§ô%¿ôŽ“çöïïúûúúûû÷÷úùÛÜõÙemæå+9àó–ìößàðöõõùñññôîØÙê·bkÛÞÃó ‰õ €õ ©õ »ô Âô Åô ²ô šõ |õ~톆­`ÌÌÐÏÏÏš››f?@Añ')*ø&'(ù#%%÷defÖ¯°°¤¼¾¾£­­®¢Œ«BCCö ù~€Îààà®ñññìáâäÓ´µ¶Î©ªªöGHHûýý•••üôôôþýýýþööüþª°óù,áô×ô µô¨ô/9Ñ󝳿Ôääï¯ççïÕØÙ诂ˆäæ,Ûó%2Ùô’—ÛóÙÛíkÖØéz”™Ûº$-ºñ—ô|ô|ó©òÂò Éô Çô ´ô œõ }õ~숉¯^ÏÏÑÒÒÒÁÁÁ5VXXÛ)+,÷()*ùGIJù)++ø'))÷.00ö ÷û üûEGGô««¬®ÔÔÕÆÆÆxyzðÎÎÎûKLLüýý•••üôôôþýýýþñòüþs|ë÷&àô Ýô Åô œô«ô4<¼íjnÃꨪÛÈœ Ù·@JÊð#ÀóÄô'2ÑñEOÙç.8Ïæ%µðôrõmñWKa±vl¬¢(1ÏîÍó Âô ³ô šõ}ô9:ˆÉ½½ÈÑÑÒÓÓÓÉÉÉrrs½012ö"$%ù?AAùDFF÷ !ú üþü+--ùùù-./÷CDEè;;<î““”øáááýMNNüýý•••üôôôþýýýþîïûýakéö$ßô Ýô Îô §ô ’ô™ôŸô&,°ó!§ó›ó ›ô ªõ ­ô§ô žô ‡õ rõjó75kã³®¶&ººÌENÔ¼Ïò ½ô ¬õ Œõ}ò@B‹ÃÆÆÌÍÍΠ ¡ˆ@ABó#$%ùù úú üýüGJJ÷FHI÷$&'úü ý...û×רûèèèþNOOüýý•••üôôôþýýýþíîûý_jéö#ßô ßô Óô °ô ‹õ õ õ ƒõ |ö vö mö xõ €õ pô môqónñ,0pé‚€œxÉÉÌÆÇÓ R[×°Îñ ´ô £õ ‚õ}ð~©jÊÊÎÐÐд³³KZZZÞ/01øùú ûûýýüûúûûùñññþëëëþNOOüýý”••üóóóýüüüýðñüþalê÷%àô Þô Óô ­õ †õ {õ zö `÷ ^÷U÷3ø -ð&$EÒ.0ZÔ26qÔDExÑyyš˜™«SÉÉÍÐÐÑÅÆÒ W`Ô²Áñ °ô •õó&)€äž¸AÏÏÑÐÐÏ£Ÿ>NKJã@BCö-/0ø!!ùúú ûûû û ûúGIIøØØØúùùùþìììþNOOüýýŒ”ùïïðöùùúøôõüýœ¢ñú+áôÜô Òô ªõ õ ƒõ õûü üý  Óµµ¸ÃÃÇ ÃÃÈ ÆÇËÊÊÍÎÎÐÒÒÒÑÑÓº·Ì-?@ºÑ¶ó «õ ‰õï{{¨mÉÉÎÏÎΕ”“B)((é?@A÷>@A÷8:;ø/02ù'(*ù úúúùú,..ø»»¼ÐõõõþýýýþìììþNOOüýü’“”öèèè´óóóž÷øúúÛÝùýFRçö#àô Ñô ¨õ „õ ‚õ õþþþý&$#ÏÂÂÁ ÌÌÒ’ÊN¶í°ô õƒò??‹Å¶¶ÆÐÐÒÎÎΔ“’Aèù&'(ù-./ø79:÷8;;÷79:ö/63ö-21÷466ùSTT误¯íðððüüüüþþþþÿìììþNOOüýú“””Öèèèfïïï‚øøùìóôüý›¡ðù,ßô×ô ²ô …õ ~õ ‹öûþþü(%$ÍÃàÇÈÑCH¾ºµð ¬õó"%€ìª«¿*ÍÍÐÎÎΔ”“?ç"#$ù!##ùùùJãô"Ñô¨ô ƒõ yö höûþ ûXD;·ÈÆÅÇÇÏCE’à ˆë;?’Å––¶IÉÉÎÐÐÒÎÎΗ–”C&'%ê+--ø-/0ùù'))ø}ÓßààsêêêrîîîzòòòºõõõîøøøøüüüüýýýþýýýþëëëýNOOüýø™šš¦åååxììì|ííígóóó‘öööìóóûúÅÈõùbjãõ%.Äôœõ }ö möûý úi_Z¬ÇÆÅÌÌÏ—˜·MŠŠ¯^±²Â%ËËÏÑÑÒÏÎΘ—•D()'ë+-.ø/01ù!#$ù()*øƒÓÝÝÝ}àáá‰ááá‰îîîrðððyññòºøøùùýýýþýýýþìììþNOOüýú•––ÏçççaìììpëëëníííjñññbññóÐõöûûëëúý²¶êù=E«ö {ö8ùýþ ûXE;·ÈÆÅÒÒÓÏÏÑÎÏÑÐÐÒÏÎΗ–”C()(ê+-.ø012ù!##ù!!ørstÓßßßxééémééémêêêkëëëiïïïôôôõüüüýýýýþìììþNOOüýý’“”õèèèƒîîîlëëërëëënîîîlóóó¬üüüûûûýþííòýy{…ú ýýþþ ûXE;·ÈÆÅÏÎΗ–”C$)%é-./ø123ù!##ùùSTUÝÕÕÕŽßßßnÞÞÞjßßßjßßßoááá‡äååöêêêýëëëþÞÞÞþFGGüýýŠŠŠúÚÚÚîÞßßÛÜÜ’ÝÝÝ“ßßàÃçççíêêêüëëëþâââþuuvú þþþÿ ûi_Z¬ÈÆÅÏÎΘ–”B%)&é-./ø234ù#$%ùùúFHGð[\\ÑgiiÑjklÑdfgÑUVWÛHHIøFFFýFFFþ???þþþþ())ýAAAüGHIøKLLõIJJöGHHùEEEüFFFþGGGþBBBþ##$ýþÿÿÿ ûXE;·ÈÆÅÏÎΘ–•B)('é-./ø345ù)+,ùúú úùøøø ùýþþþþþþþþþýýþþþÿþþþÿÿÿüQ@8»ÆÄà ÏÏΙ—•C((&ê*,-ø345ù234ù*,,ù $#ùúùùùú ûûüüüýýýýýýýþþþÿÿþþþÿÿÿü4/+ÊÄÃà ÐÏÏš˜–?&%$æ'''ø134ù356ø356ø/12ù,./ù*+,ù')*ù%'(ù$%&ù úúúúúúú û û ûûûýþþÿÿþþþÿÿÿü.+(ÏÅÄÄ ÑÑѶ°®.?;8Ö!##ö()*ø,-.ø/01ø/12ø022ø/11ø-./ø*,,ø)*+ø&()ø%&'ø$%&ø!"#ø !øøùùú ú úúûýþþþþýþþþý ùcYU¬ÉÈÈÊÊÊ ƒ~zy654Ü$#"æ''&è-,+é00.è310ç221ç//-é**)é''&è))(è))(é&&%è#""æ!! åååäåççççççççççééèèEB@Æ¥¢ŸCÏÎÎÑÑÐÊÊÉ ®­«3š™˜;š™˜>œ›™>ž›>Ÿ›>Ÿžœ>œš>›š™>š™™>šš™>›š™>š™˜>™˜—<™—–;˜—–;——–;˜–•:˜–•:˜–•:˜–•:˜–•:˜–•:˜–•:˜–•:˜–•:˜–•:˜–•:—–•:—–•<—–•<˜–•;žœš;½¼»"ÍÍÍÒÒÒÑÑÑÏÏÏÏÏÏÎÎÎÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÏÎÏÏÎÎÎÎÏÏÎÏÏÎÏÏÎÏÏÎÏÏÎÏÏÎÏÏÎÏÏÎÏÏÎÏÏÎÏÏÎÎÎÎÏÏÎÏÏÎÏÏÏÐÐÐÒÒÑÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿøÿÿÿÿÿÿÿÿà?ÿÿÿÿÿÿÿÿ€ÿÿÿÿÿÿÿþÿÿÿÿÿÿÿüÿÿÿÿÿÿÿðÿÿÿÿÿÿÿÀÿÿÿÿÿÿ?ÿÿÿÿÿþÿÿÿÿÿøÿÿÿÿÿàÿÿÿÿÿ€ÿÿÿÿÿÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÏÿÿü‡ÿÿüÿÿüÿÿüÿÿüÿÿøÿÿàÿÿ€ÿÿÿþÿþÿþÿÿÿÿ€ÿà?ÿøÿþÿþÿøÿàÿÀÿþþþþþ?ÿÿ€ÿÿÿàÿÿÿðÿÿÿüÿÿÿÿ€ÿÿÿÿàÿÿÿø?ÿÿÿþÿÿÿÿ€ÿÿÿÿÀÿÿÿÿÀÿÿÿÿàÿÿÿÿàÿÿÿÿðÿÿÿÿðÿÿÿÿðÿÿÿÿðÿÿÿÿøÿÿÿÿøÿÿÿÿøÿÿÿÿøÀÿÿÿÿøÀ?ÿÿÿÿøÀÿÿÿÿøÀÿÿÿÿøÀÿÿÿÿÿøÃÿÿÿÿÿøÿÿÿÿÿÿøÿÿÿÿÿÿøÿÿÿÿÿÿøÿÿÿÿÿÿøÿÿÿÿÿÿøÿÿÿÿÿÿøÿÿÿÿÿÿüÿÿÿÿÿÿüÿÿÿÿÿÿÿ?ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(H `TÑÑÑÌÌÌÄÄÄ ¨¨¨9WYYÛûý677Ý­«ª/ËÊÊÑÑÑÐÐÐÊÊʺºº………nKKK¹ ì úþþ ù*'&܆†‡qÃÃÃÌÌÌÑÑÑÏÎÎÇÇÇ´´³*tuu…##$æöûüýýþþûö754ÓŠˆ‡kÀ¿¿ÎÎÎÏÎÎÇÆÆ¡¡ >`\Z–&&&æ ù ü þý!ü HQú',ûýþýý ûöKJH¶«¨§5ÊÊÊÑÑÑÐÏÏÉÉÈ®«©,ZVTí ø üý&*ûR]ùwˆù˜­ø§Àø n~ø ýýûEPù %û ü ù ç…qÄÄÄ ÏÏÏÒÒÒÍÍ̼º¸xvtv###ç ù ý ý 39ûhuù Ÿµø°ÊøµÐø¸Óø¶Ñ÷ †™øüý5=ûš°ø¢øGQúý üô^]\¢¸µ³"ÍÍÍÒÒÒÎÎÎÅÅÅ œ™˜P?<:Ä÷ û ý'+ûn|ù £ºø³Í÷¸Ó÷ºÖ÷»×÷»×÷¸Ó÷”©ø üþ;Cû¨ÁøµÐ÷¨Áøpù#ü ý ø=63ƪ©¨8ÉÉÉÐÐÐÐÐÐÇÇÇ £££KNNO»ö û ý!%û bpù¦¿ø³Íø¸Ó÷»×÷»×÷»×÷»×÷»×÷ºÕ÷  ·ø ).û þ:Aû©ÂøºÖ÷¸Ô÷°ÊøŒŸø;Dûý úí}zgÆÅÅ ÏÏÏÑÑÑÌÌÌÁÁÁlmmò ú ü#û LVú ’§ø±Ëø¸Ôø»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷£»ø -3ûþ27û ¨Àø»×÷»Ö÷¹Õ÷´Ïø´ø]jùü ûñ^XU»º¹ÍÍÍÒÒÒÍÍÍÀÁÁŽŽŽb566Ø÷ üüQ]ù§ø®Èø¶ÑøºÖø»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷ ¤¼ø .3û þ/4û ¦¿øºÕ÷»×÷»×÷ºÖ÷·Òø«Æø~’ù,2û ý ÷A?=¼²°¯/ËËËÒÒÒÏÎÎÆÆÆ ›››QFGGÆö ûü4<úx‹ù«Åø·ÒøºÕ÷»Ö÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷ §Àø49û þ"&ûœ²÷¹Ô÷»×÷»×÷»×÷ºÖ÷¹Ôø²Íø—®øLWúü ú)&#Ý”’‘MÇÇÇÏÏÏÒÒÒËÊʯ­¬)UTT±ð úü,2ûpø£¼ø´Ï÷¹Õ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷¯Éø IRú ýüŠø¸Ó÷»×÷»×÷»×÷»×÷»×÷ºÖ÷¶Ñ÷§Àøjzù#(ûúí\]]¢¹¹¹$ËÊÊÑÐÐÏÏÏžš˜C,+*Ø ù ü!&úaoù›³ø²Íø¹Ô÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷±ËøT]ù þü ˆ›ø·Ó÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¸Ó÷°ËøŽ£øBLùü ø++,܉‚dÇÇÆÐÐÐÌËËpppw ÷ý.5üˆø¯Éø¸ÓøºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷²ÌøT^ù ýü ˆ›ø·Ò÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¹Õ÷´Ïø ·øYgùý ûñooo–ÇÇÇÑÑÑÊÊÊnnnz øþS`û®ÉøºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷ºÖ÷»×÷»×÷»×÷»×÷»×÷±ËøU_ù þü ‰œø·Ò÷»×÷»×÷»×÷»×÷¹Ö÷¸Õ÷¸Õ÷¹Ö÷ºÖ÷ºÖ÷·Òø¬ÇøvŠù!&û ýôš™˜UÎÎÎÊÊÊnnnz ø ýUaû±Ë÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷º×÷¸Õ÷µÓ÷´Ò÷³Ñ÷´Ñ÷·Ô÷ºÖ÷ºÖ÷ºÖ÷»×÷±ËøS^ù ýü ‡šø·Ò÷ºÖ÷ºÖ÷·Ô÷±Ð÷­Ë÷ªÇ÷©Ç÷¬Ë÷²Ð÷¸Ô÷ºÖ÷¹Õø°Êøs„ùý øjhgŽÊÊÊËËËrppl ÷ þVbú±Ìø»×÷»×÷»×÷»×÷»×÷»×÷ºÖ÷¸Õ÷±Ï÷©É÷¡Á÷ž»÷œ¹÷º÷£À÷¬Ë÷´Ò÷¹Õ÷ºÖ÷°ËøQ\ù þü ƒ–ø¶Ñ÷·Ó÷°Ï÷¦Å÷º÷™¶÷˜´÷—´÷š·÷ ½÷­Ë÷¸Ô÷ºÖ÷·Òø Ž¢øý ùcdd“ÉÉÉÎÎÎЉ[ö ý[gù²Íø»×÷»×÷»×÷»×÷ºÖ÷¸Ö÷²Ð÷©Ç÷ ½÷˜´÷”°ø‘«ø‘¬ø”°ø–²÷˜´÷¡¿÷¬Ê÷µÒ÷®É÷R\ù þü ’ø®Ê÷¨È÷ž¼÷—³÷«ø˜øsˆøyøŒ¦ø”¯øº÷¨Ç÷µÐ÷¶Ñø øý úeee“ÉÉÉÑÐв±±"ó ý[gù²Ì÷»×÷ºÖ÷ºÖ÷¹Õ÷³Ñ÷©Ç÷ž»÷˜´÷“®÷Œ¦øvŠø[jùgyùƒšø©ø“­÷•±÷˜µ÷¢¾÷¤¾÷MWù ýü wŒø›¸÷—³÷‘¬÷…žøbsù4<ú%û%,úIUù ~”ø«ø˜´÷¢Á÷¬ÈøŠøý ùcdd“ÈÈÈÒÒÒ´´´ò ý[gù²Ìø»×÷¹Õ÷³Ò÷ªÊ÷ ¾÷™µ÷”°÷ލøv‹ø DQùü üü(.ûP]út‰øФø’®ø•°÷’¬ø HSù ýúmø©ø‰¢øi{ø>Húû ý þ þü.6úevùФø”°øš¶øƒ—ø û ødee“ÉÉɳ´´ò ýYeù²Ì÷¸Ô÷¯Ì÷¢Á÷š¶÷•±÷«ø …œø S`ù#û ý ýýüýý!ûGSúv‹ø‰¢ø‡Ÿø ENùýûfwøs†øHTù"ûýý /4ûcqùCJúýý#)úTbù{øŒ¦øwŠø#&úödee“ÈÈÈ´´´ò ý[gù«Ç÷¨Ç÷œº÷–²÷’®øŠ£øbsù(/û ü þý7?ûyŒø•ªødtú3<ûýýû5>ûDú“¨ø°Êø¹Ô÷ºÖ÷¹Õ÷´Îø ž³÷S]úü ýý!ûú#$%ômoo’ÉÉɵµµñ ú _mùާøªø~”ø Taùû ý þ üR[úš®÷²Ìø¸Ó÷»×÷»×÷»×÷¹Ô÷´Ïø©Âø‰›ø04ûþþþþþþ ýIQù ‹žø®Çø¶ÑøºÖ÷»×÷ºÖ÷·Óø¯Êø¤ø9Bûýýüökll“ÉÉÉÐÐÓÇÇм½Ï!ÍÍÒ¶¶¶()*ï!#ùVaù”øZhù(0úüþ ý 4:ûø®Èø·Ò÷»Ö÷»×÷»×÷»×÷ºÖ÷¶Ñø®Ç÷‹øBHúýþ ýý,2û ü ýþ ýüQ[ú“¨ø°Êø¶Ñ÷ºÖ÷»×÷ºÕ÷µÐ÷¨Áøcrúý þ ûLKK±¿¾¿ ÊÊÎÀÁÒkoÊŸ;A¯Û½¼Ë!ÑÑÓ·¸¸./0ïú(+ú #(ûü ý ý "ü ]gù ¢¹ø´ÏøºÕ÷»×÷»×÷»×÷ºÖ÷¸Ó÷²Ìøš¯øHQúü ý þ(-ü y„ù›ªø §÷ zŽøOZú  ü ý þ þ!üLVú •ªø²Ìø¸Óø»×÷ºÖ÷¸Ôø±Ìø“©øHSûüöSQQ¦˜©OVYÇÎ+Ëî$§ì‹¿bÍÍÑÑÑѵµµ"#$ñ üþþ ý #&ülzùŸ´÷±Ìø·Ò÷ºÖ÷»×÷»×÷»×÷¹Õø³Îø˜¬ø_jù ü þ þ ý EKû­½÷ÊÛ÷Ðá÷ÉÛ÷ ¤½÷¨ø‚˜ø^nù2<ûý þ þükxù ¨Àø¶ÐøºÖ÷»×÷ºÖ÷¶Ñø®Èøvˆù&+û ú1ö„ó®ó©ðSVª´ÈÉÐÐÏÏÇÆÅ‘ŽQöýý üJRúŽ ø £º÷§Àø¬Æ÷³Îø¸Ô÷ºÖ÷ºÕ÷·Òø ¬Äøx‰ø"%ü ý ýú;?@îl›ŸßÈ×õÑâ÷Öçö×èöÕæöËÞ÷ ¢»÷‘ª÷‹¡÷€‘øesù9Bûý ýý =Eû†–ø ±Ê÷¸Óø»×÷»×÷¹Ô÷´Î÷™±ø=Gúýü RùŒòDI¨·ÅÆÍ ÏÏÏÈÈÈ·³²!gb_Šò û ý17û{Œø ŠøZgù07ù%*ù/5úhvù©ÃøµÐø ±Ë÷‘¥øGOúýþ ü ô²ØÝÞj¡ßå—ÓäôÖçö×èö×çö×çöÓä÷³Å÷Š÷_TøD'ø7ùOJøV\ù ü ý þýdpù ¦½ø´Ðø¹Õ÷»×÷»×÷¶Ñø«Åøk{ù üþ ,úHLvÀÁÁÆÑÑÑÊÊʨ¥¤3ihg‘,)'Ú ö ûü T`ú •¬ø `mù(+ù ú ú ú úú[iù  ·ø cmù "û ýüú?@@௰°—ææçvèìíÑœáèé"ÖåôÖç÷Öæ÷Õæ÷Òâ÷ÏÝ÷ ­¸÷VGøAø6ø,ø+ø 1"ù)ùù üþý+0üyˆù®Æ÷·ÒøºÖ÷»×÷¸Ô÷²ÍøŠžø#)ü üðŽfÌËËÐÐЦ¤¢7 æ øü ýEOú…šø£»ø \iù !ùú ú ú ú ú ú #'ú17û ýþ ü(((†¾ØÙÙpèèèŸððñðïòóöÇêîÊ2ÖåõÒáö ÌÜ÷ÌÛ÷ °¾÷ ˜ ø ^NøDø:ø/ø*ù,ø."øT÷,øú ûý þýITû ”©ø²Ìø¹Ô÷»×÷¹Ô÷­Çøv‰øüøH>8ÄÊÊÊÐÐД••Xòûþý GPú‹Ÿø}ø&(ùúú ú ú ú úúúýýý233ê¼¼¼€çççkííí©óóôô÷÷øöôõõùâìí÷nÚãá!ÄÑõž­ö ™¥÷ fkø2%ù@ø6ø1ø*ø*ù0ø">÷ yõ qöCø#ù!#ú!û ý ýýiyùªÃø²Ì÷®Èø„™ø%-ûû)%(Ù›š?ÌËÌÑÑÑÇÆÆ tnk)%#Þ ö û ý ü25ú!"ùú ú ú ú ú úúú üþúš››˜çççjïïïÒ÷÷øöûûüüûûûûúúúúðôõùÝìî×£ÌÑ-QUéü ú$G3÷G%÷5ø+ø)ø.ø,%ø cö  õ ®õ Šö föDMt÷_dxø*.=úýþüFVúm€ùJWúü ü U÷TW­®³²É(ÌÌÒÐÏÏÊÊɹµ³~m432Í ö üú%)+ùú ú ú ú ú ú úú ûýø²³´‘êêëÊôôõ÷ûûûüýýýþýýýýüüüýùùúùõö÷ößáâÓcffå ýù¨­«Í‹ƒì?[H÷=(÷ 4ø 3'øX÷ Šõ ºô Ïô Äô¤õŒõ övö Y÷Oø T÷ Gø .ú ü2úw÷Ÿô!¹ðÌÕ­­Ð8ÈÈÎÐÐÐÆÅŃ€e137ó$&'ùú ú ú ú ú ûýû üþ!!!øÍÍΕðððßùùúùüüüýýýýþýýýþýýýþýýýþûûûþÚÚÚü222üþ ýWX[Ú„‡ŒöˆŒ”ö›ž´êGJ•ê…õ ¥õ Èô Úô Þó Ûó Îô ˜õ §õ ªô Ëô Õô Ôô Æô —õ yö58Šö××âðàáíû”˜Ñö'/£ô °ñDNÒÊ»¼Í‹‹ÐÐÐÆÆÆ˜˜˜G234ó(*+ùù ú ú ú ú ú ûú üý!!!øÍÍÍ•ñññàùùúùüüüýýýýþýýýþýýýþýýýþùùùþ¾¿¿ýýþ ý ü(K~÷4AŽõ5=“õŒõ£ô Áô ×ô Üó Ýó Üó Îô “õ õ »ô Äô Èô Òô Òô °ô vögöPPX­ßÚÚã炆Åö žô(Âë‹Î`ˆˆÒÑÑËË˵´³qnm|300Õø/12ù!$ùú ú ú ú ú ú úûýùÅÆÆïïðàøøùøûûüüýýýþýýýþýýýþýýýþôôôþ  ¡ûþþ,û ~ö°ô õ’õ³õ Åô ×ô Üó Ýó Ýó Þó Öô ®ô ’õ ™ô ¹ô ¦ô »ô Ëô §õ q÷0ù ýûPQTùޤä)2œó ±ðnrÊ‚……ÏÏÏÆÆÆ’Œ‰O,)&Ø ÷ü ý %'ú-23ù "ùú ú ú ú ú ú ûüú¦§¨©éééÌõõö÷úúúúûûüüüüüüûûûùùùúùêêêøWWWã ý ý h÷ Áô Çô °ô “õ ´ô ×ô Ýó Þó Þó Þó Þó Üô Íô «ô ”õ ô ³ô Îô Êô –õ"p÷üþþ þû-8ô ªñ\V¾ÊƒƒŒÑÑÑÊÊʳ±°&`[Y•ï û ýý7=ú#grø+RYø+8<ø%'ùú ú ú ú úûü üjjkÒààá‡ïïïð÷÷øõøøø÷óóôëïðñ´æèê²ÁÄÆ¡389÷û ýGø ›õ Èô µô °õ ¢ô Ïô Ôô ×ô Øô Õô Ñô Ïô Ïô Ëô Ãô Ãô Ðô Éô ©ô Ÿõ+¬õZøý þþ ü#/†õ!­ñf^¼¼„ƒŒËËËŒŠW,-,á øýýDLûŠžø ©Á÷ °Êø«Â÷}Žø.INø )-ù ú ú ú ú ûüþ&''ø¼½½ˆæææ‹êêëíìíï±ÝãæŸÎÝâ´ºÓÛÈf”Ÿâ:o}õ,]h÷ "û!Bù{ö šõ ¯ô ™õ …õ ¡õ ¸ô ¶ô ¬õ ¤õ —õ–ô–ô ¡ô ­ô ºô ¶ô ”õ}õ Žõ ›õ ±ô „÷ Mù ?úP÷˜õ",½íƒ…Æt‡‡ŒÇÇÆ998Æ úþüjwø ¥½÷´Ï÷ºÖ÷ºÖ÷¹Ô÷´Î÷Ÿ¶÷.OWøù ú ú ú ûüþ û678죨©£½Èʱ½ÒÛÍ•ÌÛîSÇàñ,¸×í®ÏõªÌö ¢Á÷lø3>ù kˆø'Qùh÷ höõ#¦õ¦õ ‰õ õ †õ –õ šõ ”õ Œõ †õ Œõ ˆõ rö =÷ Dø ~ô˜ò¯ó¸ó#´ô$­ó$µò=A»á´³Æ#‹‹ÉÉÉQOM¨ ÷ü üMTúŽ¡ø ¯Ç÷·Ò÷»×÷»×÷»×÷ ±Ì÷,hr÷&)ù ú ú ú ûüþþ üGQ÷<¨¾ò=ÂÞõºÜö´Ùö ½ãö Àåö Àåö ºÞöšµøclø p|øý%0úe‰÷6•ö!žõ Œõ |õ“õ ·ô Åô Åô ·ô £õ •õ õ uõ fö ù ø/2M×\a£=C¥Ç,2£é)1¦ë)3©ëCF©ØœŸÄTÆÆËÏÎκ¹¸_YV›ò û ýüNVú¢ºø³Îø¹ÔøºÖ÷µÐ÷"yˆø$48ù ú ú ú û üþüVfú «Ë÷·Û÷ ±×ö ºà÷ Âæ÷ Äè÷ Äè÷ Äèö ¼á÷ ¤Á÷ v‚ø JSù-4û†¢ø–Ìö]Éõ ”õ ô ¿ô ¾ô ­ô¢ô ¸ô Íô ¾ô ªõ õxõ fö/óXSTŸ¸¸º ÄÄÊ Á¿Ê°®Â4¬¬Â6­­Ã6½¸Ä&ÍÌÑÌÌÍÏÏÏÆÆÆ—‘M:74Àò û þ(.ün~ù£ºøµÏø·Ñ÷•ªø'HMø"%ù ú ú û ü ýj}ù ²Ô÷ µÙ÷ ´Úö Àåö Ãçö Äèö Äèö Äèö Ãè÷¶Û÷ Š ÷ ‡ø"w†ø'†©÷kÐö1Üô !Ëô ©ô Íô Åô ¹ô Çô Ìô ±ô  ô  ô ©ô õ}õ rô?Dz¼¾¾ÃÏÏÏÒÒÒÑÑÒÑÑÒÒÒÓÒÒÑÌËËÀ¿¿ƒ‚€h864Ñö ú ý.3û#ø ªÃø §¿÷%`kø!/2ù ú ú û ûý ‰£÷ ´Ø÷ ´Úö Áæö Äèö Äèö Äèö Äèö Ãèö¼â÷©Ì÷KTù• ø\£Àö%Gºõ%Øô Ýó Êô Èô ¿ô ¯ô Ÿô ”õ Ãô Öô Éô Êô Îô «ô€õxócfŸ“ÅÅÌÑÑÑÌË˾¾½ŠTC><Áí ù ü8=úiwù!kwø%58ùù ú ú ûý r‰ù±Ö÷ »á÷ Àåö Âçö Ãçö Äèö Äèö Äèö ¸Ý÷ rˆø04ú5¡®÷^{·ö$Áô Ùô Ýó Ýó Ñô ºô Ëô Äô ©ô ¤õÑô!ÒôÐô Ôô Èô •ô~ô>;†ÙÃÄÌ ÑÑÐÍÌÌÅÅÄ §¤£DXXX«ì ø û û*/1ùù ú ú úû?hp÷*Œ ÷¡Â÷ °Ô÷ ³Ø÷¾äö Âçö Ãçö Àã÷¦Å÷19ü ~…ø-«¹÷I{·õ!¹ô Øô Þó ÝôÒô ¶ô ¹ô½ôŸõ…öJOÄ÷\aÏö=GÞô&ÞôÚó ¿ô…ô&)‡ê¾¾ÉÑÑÒÒÒÒÎÎÎÇÇÆ ®­¬,zyxw)(&Ûö-/0÷ù ú ú ú#&&ú‰ŽË#&û'.üƒœ÷°Õö¸Þö·Ø÷¼Ý÷ ±Ò÷LZúýitùª÷9‡©ö Ÿõ Òô ÝóØô¯õ)-„ö)3Íô+Ïô-1\ù)ü¥¦±ûããñýÍÐõúakéö%Þô ÑôŒôƒï‹‹³eÅÄËÎÎÐÒÒÓÐÐÐÊÊʽ¼¼sqp†?>Aá"#÷ ú úùVXYø¤¥¥ûý þJejú7¦¾ë$—®ödrùL’Ÿø&htùþý luù ¤®÷Pjw÷!.ö ´ôÓô"¿ô,2l÷ 6û6BÁõ,Òó/5[øýfggãííîûõöüýÇËöú+áó Ðôõ}ó'%€ëYR“Á¤œµWËÊÏÑÑÒÐÐÐÊÉÉ•‡e246óú úú}ß«««ý89:úü_dfüjstñQ\^àüCJKüeijâ ûþ šø ®¹ø"NSùm‰÷ *Šö"©õpuÊöSVbø%(2ùENžõ+Ôôbhœö67<úQST÷åååÒúúüýÒÕ÷ü /áô Ïô ƒõ {õ{õ|ò,-‡æš•¯ZÌÌÏÒÑÑ¿¿¾4IIJî ""ùúù~üÀÁÁõŠŒŒô**+ûklmûrrsñfgg¼-..ùHHHúuuu¼û ýŒùOUûS\ú¥³÷Zwø(1Ž÷¾Áåû©«±ïlosöKS~ö&4×ó¡¦åø¥§­èŠŒŒöîîîáúûýýÓÕ÷ü!/ßó Ëô „õ ‰õ õƒô~ò<=‹Î»·Â$ÒÑÒÉÈÈ hdcÏ/12õúú~~~ýêêê󽾿。úºº»âcddèqrré~ßUUUù}}}»ù þ ý%01üMuwû6µÀøSv‡û/7†ø…ŠÛöáâëí¿ÀÂá–™¬ùS]áõnwéõæçôýòòóüøøùýùúýþÐÓöü-Ûô °ô Œô ¨õ ®õ  õ †õ힘´VÏÏÑÏÎΩªªU@BCñ ""øù€ÙèèêåóóóòñññçØØØÕ>>>ö§§§è³³´óÂÂÃøŒŒŒ½aaaù þ999ýÑÓÓýÞéëý¶ßéû¨´èø!-Äô07½õÌÎðúòò÷ýîïöý£¨îø9Eäô¼Àôùóôûüúúûüôôúû«¯íñ&Ìó •ô  õ µô ½ô °õ Žõ€ïvy¯ÌÌÐÑÑÑÁÁÁ\]^Ñ)*+÷$%&øcdeØÙÙÙcààá„ßààb§¨§¯677ø¶··æñññøêêëø”••äjjjúýDDDüéééýùûüþéìúüZfçõ"Ïô«õdlÞõããôûòòùùÚÛñæ_häëKVäôÃÆêöéêöÐÚÛëÈksØÙ±ô ‚õŸô ¼ô Åô ¶ô “õ€ïno£‚ËËÐÊÊÊz{|¦/01õ+,-ø577ô_`aàuwxÞLLMß)**ô'((ù ¢¢¶ÚÛÛ«ÑÒÓ¥“”•ìlllüþDEEýëëëþúúýþÊÎöû,:ãôÖô«ô%¹ô}‚ÓÐÃÄáÌÉÊæYbØê'ÏóKT×ó‘—ã¨tyÕ¿")ªñóní<7™Ù$Êï Èó µô •õ°XÍÍÐÏÏÏŸ  o89:ñ)*+øIJK÷%&'úü ü ""ùø,..÷abcßYZZç¼½½ùoooûýDDDüêêêþøùýþ´¹óú-àô Ùó »ô˜ô¢ó,1«ñ15±ò¢ó©ô°ó¯ñœòzô nðjd„™®¯É%5?ÐÒÅò ¯ô ‹ô €ë®®Á&ÑÑÒÒÒÒÂÂÂ3LMNé$%%ùùú üý133ø;=>ø úüaabúÞÞÞýrrrýþDEEýëëëþøøýþ²·óú,áô Ýó Äô ‘õ ~õ ö xö oö iôwñoðrï"ríEG|ε´½&ÁÁÐ FOÖ¿½ò ¥ôƒòGI¶ÂÂÊ ÅÅÅ gcbÆ466öùú ûüý üú)**ú¿¿¿úéééþtttüýBECûèèéúøùüü¾Âõú&4âôÜó Âô Šõ }ö `÷9ù-ù ò^]i‚{}’j…‡£i«ª·:ÅÅÊ ÍÍÐÀÀÐ@FÅdzò –ó‚逪iËËÏÅÄÄ 876Ø?AAõ689ø*,-ù!"#øùùùú‹ŒŒâðððýïïïþtttýþBFDøááâÑôôöÆíîûû[fé÷$Ýô Àô ‰õ ƒö Rù þþ›4ÉÉÊÎÎÏÐÐÑÎÎÓ££Ë”Å–—·KËËР11/Û,-.ø%'(ù&((÷‘’’¼áááuííîóóóÐ÷÷øôüüüûüüüýðððþtttüüLNOÝÞÞÞtììíxñññ„ôô÷åäåøùˆéö'0Äõõ tö(úý.(%ß¹³±%ÑÑÐÎÎÑ•–·Ptu¦~»»ÈÌÌÐÑÑÒÃà331Ü-..ø)++ù(**÷”•–¿ÛÛÜ„äääííîpððð‹÷÷÷îüüüýðððþtttýþGHHîÞßßzìììpìììoðððfððôÔðñúýÅÇëû=D•÷ Lù ýý*!ãµ­©(ÒÒÑÑÑÒÎÎÑÎÎÑÐÐÒÃà020Ú.//ø*+,ù ø~€¸ÙÙÙsàààqáááoââãoççççîîîýåååþmmmý þ???ùÖÖÖÍââãràààjâââˆêêêÖîîïýáâåþ\]cû þþþ.(%๳±%ÒÑÑ 240Ú./0ø+--ùø677÷pqqÍ‚ƒƒµ…††µ}~~¸oooòmmmýhhhþ333þþýdddúlllômmnñlmmömmmúnnnþgggþ,,-ýþþþ) ãµ­¨(ÑÑÐÃà531Ù/00÷/11ù !"ùúù÷öøü þ þþþþþ þ ý ý þ þ þþþþþ#毩¦+ÑÑÐÃà10.Ø+-,÷234ù/12ù)++ù"$%ù !ùùúûû û ü üüüüýýþþþþþþþ줣¢1ÐÐÐÈÇÇPJGÄ())ô,./÷012÷012÷011÷-./÷*,,÷'()÷$%&÷"#$÷ !÷øøùù ùùüýýýýýýû+(%൳±&ÒÒÑÍÌÌ¡œLFDBÉ321Ó875×=<9Õ?=;Ô<;9Ö654Ö532Õ654×210Ô0/.Ó++*Ò))(Ò('&Ñ&$$Ò%#"Ò$#"Ó$"!Ó$"!Ó$"!Ó$"!Ó$"!Ó#!!Õ#"!Ô1.,Ј…ƒpÊÊÉÒÒÒÍÍÍÇÇÇÄÃà ÃÃà ÄÄà ÄÄà ÄÄà ÃÃà ÃÃà ÃÃà ÃÃà    ÂÂÁ ÂÁÁ ÁÁÁ ÁÁÁ ÁÁÁ ÁÁÁ ÁÁÁ ÁÁÁ ÁÁÁ ÁÁÁ ÂÂÁ ÅÅÅËËËÑÑÑÿÿÿüÿÿÿÿÿÿðÿÿÿÿÿÿÀÿÿÿÿÿÿÿÿÿÿÿüÿÿÿÿÿðÿÿÿÿÿÀ?ÿÿÿÿ€ÿÿÿþÿÿÿøÿÿÿðÿÿÿÀÿÿÀ?ÿÿÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿÀÿÿàÿÿàÿÿàÿÿàÿÿàÿàÿÀÿ€þ?ü?ø?ø?ø?üÿÿÀÿÀÿþøøøøøü ?þÿÿ€ÿÿàÿÿøÿÿÿÿÿÿÀÿÿÿàÿÿÿðÿÿÿðÿÿÿðÿÿÿøÿÿÿøÿÿÿøÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿüÿÿÿÿÿÿÿÿÿÿÿ(@€ BÑÑÑÌÌÌÄÄÅ ¬¬­3^__Áú üHIIÄ´±° ËËËÑÑÑÑÑÑÊÊÊ»»»‚‚‚kKKK¾ë ùýþ ù210׉‰‰e¿¿¾ÌÌÌÑÑÑÏÏÏÈÈȸ¸·y.//×ö û ýü ýþþûõ977Î’ŽWÆÆÆ ÏÏÏÐÐÐÊÊʵ³±ccc“$" â ÷ üý#'üBIú xˆøOZù ýýüü úõ][YŸ»ºº ÌÌÌÑÑÑÒÒÒÌÌ̾¾½{zyw!ç ø ûüDLú ƒ•ø ¥¾ø°Éø°Ê÷ „–øý ýMXùx‹ø5>ûü ø-*'ØžœFÉÈÈÑÐÐÎÎÎÆÆÆ ›š™J:64Ç÷ üýJSú Ž£ø¬ÆøµÐø¹Õ÷»×÷¹Ô÷‘§ø ü þbpù¬Åø¢¼øgwùüûí|uqsÄÃÃÏÎÎÏÐÐÉÉɪª«>>ºú!ü–¬ø´Ï÷ºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷±Ë÷MVú ý 07û§ÀøºÖ÷»×÷»×÷ºÖ÷ºÖ÷ºÖ÷»×÷ºÖ÷ºÖ÷´Îøš³øHTúü ÷UUU³ÇÇÇ ÅÅÄ>>>ºû#(ü¡¹øºÖ÷»×÷»×÷»×÷»×÷»×÷»×÷»×÷¹Ö÷¸Õ÷·Õ÷·Ô÷¸Õ÷ºÖ÷ºÖ÷»×÷»×÷±ËøMVú þ 06û§ÀøºÖ÷»×÷¹Õ÷µÒ÷±Ï÷¯Î÷°Í÷´Ò÷¸Ô÷ºÖ÷·Òø¦ÀøS_ú ý쮬¬/ÑÑÑÅÅÅA@?² ú$)ü¢»øºÕ÷»×÷»×÷»×÷»×÷ºÖ÷¹Ö÷¶Ó÷®Í÷¦Å÷¢À÷Ÿ¾÷£Á÷«Ê÷´Ñ÷¸Õ÷ºÖ÷°Ê÷KTú ý .3û¥¾ø¸Ô÷¶Ò÷«Ë÷¡Á÷œ¹÷š¶÷›¸÷Ÿ½÷ªÈ÷·Ó÷¹Ö÷µÐ÷„—øýô¤££8ÐÐÐÇÇÇWTT  ù (-û £»øºÕ÷»×÷»×÷»×÷ºÖ÷¶Ó÷®Ë÷£Â÷™¶÷”°÷‘«÷’­÷•±÷—²÷¼÷ªÈ÷´Ñ÷¬È÷JTú ý +0û ¹ø¬Ê÷£Á÷˜µ÷«÷‚™øvŠø˜ø«÷˜µ÷¦Ã÷³Ð÷µÐ÷„–øýô£¤¤8ÏÏÏÊÊÊ|||k ø ).û £ºøºÖ÷ºÖ÷ºÖ÷·Ô÷¯Í÷£À÷š¶÷“¯÷‹¥øpƒùSbùdvù„œø©ø“®ø—³÷Ÿ¼÷¡¼ø FPú ý,2úªø˜µø’­ø„œø`pù/6ú#û+2ú\kù‡ ø”°øŸ½÷©Å÷“øþô£££8ÐÐÐËËË~gö ).û ¢ºøºÕ÷¸Ô÷°Ï÷¥Ä÷›¸÷”°÷ލ÷u‰øûýý$ûHVús‰øzø 5<úþ&+úctùCMù ûý  ü[fúˆ›øYcúüü/7ú^nù€—øm|ø "úñ¤¤¤8ÐÐÐËËË~gö */û ™³ø¡¿÷˜´÷’®øŒ¥÷ _nù!&û ý þ !$ü fuù£»ø¨Á÷‹ øUbú&+ûýüü ýýý ü ýýHOú•¨ø±Ëø´Ï÷°Êø ÷ 5<úýû*0úKTù!"ú*+,𦦦8ÏÐÐËËË€€gõ 4;ú Š¢ø“®÷§øtˆø5<úý ýýMVú ›±ø²Í÷¸Ô÷ºÖ÷¶Ñ÷°Ê÷œ´ø l{ù&*üýþþþþý8?ú ˜­ø¯É÷¸Ó÷ºÖ÷ºÖ÷µÐ÷¦¾ø l|ù"'ü ý ýû)*+𦧧8ÏÏÏÒÒÓÍÎÒÍÍÒÏÏÒÌÌ̃„„g"#ó9?ù”ø{ŽøFSùû ýý28ûƒ•ø¯Éø·Ò÷ºÖ÷»×÷»×÷ºÖ÷µÐø ©Âø|Œø'*üý þýü ýþ ý 07ût„ù ¨Àø´Ïø¸Ô÷ºÖ÷¹Ô÷³Íø–­øAKúþ ýõ?ÉÉÊÊÊÒ¤¥ÏIdh¼ªÆÆÐ ÒÒÓÌÌ̈‰‰f&()ó%'ú>Fú!û ýþ ü`kù ¤»ø´Ï÷¹Õ÷»×÷»×÷ºÕ÷¶Ñ÷°Êø ø?Fûý ýý ]fú|Šø ~’øUbú"&û þ ýý 4:ûsù«Åø¶Ñ÷ºÕ÷ºÖ÷·Ò÷­Ç÷v‰ù(.û ú222Ë Ÿ?ˆ†Ã‚.9Îâ"*©éš›ÄQÍÍÑÊÊÊ„……gôýý ý "üfsúœ±÷°Êø·Ò÷ºÖ÷»×÷»×÷¹Ô÷±Ìø“¦øPZúý ü üûý þý9?û£ø±Ë÷¸Ó÷»×÷¹Õ÷³Îø¢ºøUbú ù!ó$tò«ò ªïbe®žÉÉÐÍÍ̺¸·WVUŸ úþüFMú‹œø˜­øš±ø¦¾ø³Îø¹Õ÷ºÖ÷µÐø §½øgtù ü ý ú011îxˆŠÐ$ÆÕôÐà÷ÖçöÖèöÓåö¼Ñ÷ •®÷‹£ø{ˆøalù;Dûý þü]hú¡¸øµÐøºÖ÷»×÷·Òø®Èø|ù$,ü ý Aù„òSX¬¥ÇÇÍÑÑÑËËË  œ™B>:8À ÷ ü (-ûsƒø |Žø HQù(,ù!%ù-3ûx‰ù®È÷ ®Èø‰›ø :Aûý üùabbÉÐÑÑzÊãå#ÓãóÖçöÖçöÖçöÕæöËÛ÷ —ª÷bXøE(ø6øE<ùB>ùû ü ý5;û Ž¢ø¯Ê÷·ÒøºÖ÷¹Õ÷³Î÷œ´øALú ý !úNPk¹ÁÂÅÑÑÑÉÉÉŒŠ‡X?>=Åõ ùûNYú•ªø \iù!"ù ú ú ú úú ‘øS\úü ý û.//ô™š›£ááá€ëììÓÏèëæ0ÖåôÕæöÕåöÑâ÷ËÙ÷ ¾É÷ dYøCø6ø,ø+ø/$ù#ùú ü þþHPú´ø²Íø¹Ô÷ºÖ÷·ÒøªÄøUcú üôˆ…„lÎÎγ²±$"! ç ùþý y‹øŸ¸÷coø!"ùú ú ú ú úú û ýüùmmnÀÎÎÎ|ççç‡ðððìôôõöâîïãcÚåõÎÜõ¾Ìö ½Ê÷ ‰ø TFøCø9ø.ø* ø.ø$9øa÷9øúû ý ý %ü l{ú©Ãø¶Ñ÷¶Ñ÷­Çøk|ù"úò{ymÎÎÎÃÃÃSOM²ó û ü %)ücnø.2ùùú ú ú ú úúûý ûfffÀÝÝÝhììì±ôôõîùùúøøøùøïôõùÂçêÕ_ÀÊÐhrô FMû -*ù ?!ø:÷.ø* ø+ø.ø`÷ –õ ƒöT÷.EøGKVø!üþýFTú”¬ø“ªøUeúý(ú^]z—¼¼ÅÎÎÐÏÏÎÅÄÄ ’ŒŠSJHG´ò û ü&*+ùù ú ú ú ú úúúýúŸŸ œèèé²óóôõûûüûýýýþüüüýøùúùðôô÷ÚáâºPXYç ý2@;ù{‰€á:YCõ6ø .ø2ø K÷ ˆö ¼ô Âô  õ'‹õ19‚ö$)p÷<ù7ú 9ú 4ú ý ýHù”ó$,¿ì}‚ÑsÇÇÓÐÐÓÑÑÐÌÌÌÅÅÅ ›šF;85Ë÷135÷ù úúúú û ûûþù¼½½ŸíííãùùúøýýýþýýýþýýýýýýýþûûûûããäæMMNæ ü:<;ë´·¶µ“’õsxw÷gzxé+cö ~ö ¯õ Ñô×óÍôµô ‡õ Œõ Žö Œö ‡ö rö^÷MP€÷†‹Â÷LR±ö%¤ó'¿ìprÎ’ÇÈÒ¾¾ÀÒÒÒÌÌ̸¸·EDCÃ126öù ú ú ú ûü üûþùÂÃáïïïâúúúùýýýþýýýþýýýþýýýþûûûýÜÜÜü011üýûƒ†ŠÝ…ˆŽö“—¥öbg¡ß…õ ¤õ Ëô Ûó Ýó Ôó ®ô žô «ô Éô Òô Îô °õ ~ö!~õ½¿ÕòÖ×èû€…Êõ!(¢ó )Àê‰Òg¹¹ÀÒÑÑÍÍ̽½½XXX«123÷ùú ú ú û ûúúýúÁ¡ñññâúúúúýýýþýýýþýýýþýýýþùùùþÂÂÂýýþý$Kú.Iö6=’õ Žõ¥ô Åô Øô Ýó Þó ×ó ©ô Žõ ¶ô Äô Çô Ïô Éô ˆöoö=>N𔕙åÎÏÚëflºõ ¤òIØõœŸ¶õy{}ïÁÂÂÕ÷øùýÕ×÷ý!/Ýô ½ô ƒõ „õõò@>‹ÌÀ¾ÇÑÑÒÐÏÏ«¦¥JFGHí øú\\\üááá𦧨åghh÷¸¸¹ØTUUèwxxÚ556ø™™™Ãúþ"$ü!24ü1’šù8–¨ù-7fútyÑöרã裥ªå~ƒªø8EÞô»¿îùãäêùôôôü÷øúýÓÕ÷ü -Úô §ô ’õ ªõ ¤õ Šõ핎°aÎÎÑÒÑÑÈÈÈrstµ+,-õ ù_``äääåæòòòñëëëè®®®ÝRSSúº»»å§¨¨÷¤¤¤ÄYYYùþVWWüÈÎÎü¸ÝãûÃØìúGTÕõ-3³ôÀÃìúîïõýçèôünvçõkuéõèêùûøùûýõõúû´¹îó'Êó ”ô ©õ ·ô ¸ô šõïop©ËËÏÎÎΜœd89:ò%''øIKKéÑÒÒiÝÝÞ~×××fppqÚdeeëâââðëìì÷¨©©èkllúþlllýìîîþòôûþ¥¬ñø*Úô®õW`ØõÞßòûéêöø»¿ìâ;HáòŒ“çõÞßðÖÙÚëËqyØÑ¬óô­óÁô Àô ¢ôðfgŸËËÏÑÑÒ¹ºº1GHIæ*+,÷:<<÷ABCóSUUñ--.ôùHIJï¼¼½ªÐÐÑ™“••ãvwwûþmmmýïïïþïðûýakéö$Üô¸ô ¯ôekËѬ®ÙÖšÛµ*6Éò)ÌókrÚÑ\cÐÇ!'¢ò{ò41qÔFFµÍÊð ½ô ¡ô퉊¯[ÍÍÐÈÈÈkklÂ)+,ö678ø'))ú ýü355ø ø*+,ö<<<ð´´´ù|||üþmmmýïïïþëíúýLXæõ!Ýô Æô˜ô•ó" ò˜óô¡ôšóŽòxñ%*që—“¨R›Í?&Ïí ¶ô “ô"#ƒæ¥¦½3ÐÐÒËËË“““†789ôùúûý !"û !"ùûQQQúàààý~ýþlmmüîîîýìíúýMYæõ"Þô Éô “õ {ö pö e÷ NöKè#$_Þ-0tÛQS‡µˆ‰¤hÅÅÌ §ªÑ1 *Éë «ôˆò?AÃÅÅÌËËË€|zsFHIò./0ù !ùú ú ûú,--ôÂÃÂîêêêý€ýþhljøèèéêñòúõˆíø(ßô Çô õ ƒö@ùüúQPU“ºº¿ÃÃÉ ÆÇËÍÍÏÉÉÐЉÆiµíŸó„윜¹?ÌÌÐÊÊÊonmv''(ó./0ø578÷587ö.31ö.11÷?AAñ£¤¤õòòòüðððþýülmnèääåmñòöÚÝßùû1?âôÌô ’õ ö=ùþ ùZXWÉÈÈÇÇÑIM½±®ð‘îln£„ÇÈÍÉÉÉqont())ó ""ù!!øahdл¾¼‰ÉËÊíÞßàöóóóúûûûþñññý€ýûrst¾ááâxôôô¯òóúù·¼óù!.×ô¤õ }öZ÷ü øvjd€ÊÉÉÅÆÏ6;§Î#œéPR™¬¼½ÉÏÏÑÉÉÉsrpw-//ò')*ù&((÷–——´ááávîîî™ôôõëúúúùýýýýñññý€ýûrss¿ááá|îîîzóóöÃîïùöŠêõ+4Äõ‹ö möû ÷‚yuxÌÊÊÊÊÐyzªy„…¯dÅÆÍÏÏÑÊÊÊtsqy/00ò,-.ù)*+ö›œœ·ÝÝÝççç|îîîvóóóÂûûûúòòòþýýlmnåâââgìììsîîîlîïò¥ðñúûÊÌëû?>ÈŠ‰ˆ`½¼¼ËÊÊÑÑÑÊÉÉ»»»ƒ‚dDECÀ!#ñ"÷ +1ú KTúEOúý ü ÷!#ñOQP°ª©©-ÆÆÆÑÑÐÍÍÍÁÁÁ —••DBBB !ñ#'øHQù €’ø ·ø¦¿ø ƒ•øý%+üs…øGRù #ö)-,à‹‰ˆ[ÁÁÀ ÎÎÎÎÎÎÅÅÅ ªªª,```˜$$ë #÷ GQù †™ø¨Áø³Íø¹Õ÷¸Ô÷ –¬÷&+ü2:ûš²ø¤½øoø )-ø"$ïjigЏ·¶ËËÊÐÐÐÈÈȺººtuu(02å#%õ :Aø z‹ø§À÷³Î÷¸Ô÷»×÷»×÷¹Õ÷µø-3ü 17û¡¹÷·Ò÷­Ç÷ŠŸø@Iø "óGJI·§¦¤,ÇÆÆÐÐÐÑÑÑËË˼¼¼T=CCÍ"$ô 3:øu‡ù¢»ø±Ìø¸Ô÷»×÷»×÷»×÷»×÷ºÕ÷Ÿ·÷.4ü -2û žµø¹Õ÷¹Ô÷²Í÷ ¸ø_lø&*ö.45Ö“’‘LÂÁÁ ÎÎÎÑÑÑÆÆÆ¢¢¡8NRS´%'ñ -2öapø˜°ø°Êø¸ÔøºÖø»×÷»×÷»×÷»×ø»×øºÖ÷¥½÷ 8@û#'ü ‘¦ø¸Óø»×÷ºÖ÷µÑ÷ªÃø~‘ø 6=ö++êlooƒ···ÉÉÈÑÑÑÎÎΠž;,..ß!öMXø¦ø¬Æø¶ÒøºÖø»×ø»×ø»×÷»×÷»×÷»×ø»×ø»×÷§À÷ AIú!%ý ¡ø·Òø»×÷»×÷»×÷¹Ô÷¯Êø˜®øS_÷%'ô9=>ÍœœCÇÇÇËˡ‡‡Vñ9Aûž¶ø´Ï÷¹Õ÷»×ø»×ø»×÷ºÖ÷ºÖ÷¹Ö÷¹Ö÷ºÖ÷º×÷»×÷©Á÷ CKú!&ýŽ¢ø·Ò÷ºÖ÷¹Õ÷¸Ô÷¸Ô÷¸Ô÷³Ï÷¥¾øhxø %(÷-01⬬¬0ÎÎÎËˈ††TòBLû¨Áø»×÷»×÷»×÷ºÖ÷¹Õ÷¶Ó÷°Ï÷¬Ë÷¬É÷²Ï÷·Ô÷¹Õ÷¨Á÷ BJú %ý Œ øµÐ÷µÒ÷¬Ë÷¦Â÷¤Á÷¨Æ÷²Ï÷µÐ÷¦¿÷Xdú!#ò„„ƒdËËËÍÍÍ“‘‘G "ï ENû©Â÷»×÷ºÖ÷¸Õ÷¶Ó÷­Ë÷ ½÷•°÷ª÷’­÷˜´÷¤Â÷°Í÷£½÷ @Hú #ý†›ø©Å÷ž¼÷ª÷€—ø|“øŒ¦÷š·÷®Ê÷¬Å÷ esú"$ò€€€gÈÈÈÐÐЬ¬¬%&î GOú©Âø¹Õ÷¶Ó÷¯Ì÷¡¾÷”®÷†žøbsùGSú`qù€—øŒ§ø—³÷“¬øDú !$ü03ûnxøµÅ÷±Ã÷ ¤øk{ø=Gû#ý ý Fú¤øhuù )-ûø144í——˜¥ÌØÙ¥q×àß ÖåôÔåöÎÞ÷ ÀÌ÷ wwøG+ø7ø2$ù'!úûý4:û v‡ù¨Áø²Íø±Ìø ¸øPbú #øJMU»»»¾ÌÌË{yxv##"ê ø 6=ù |ø Ydù$&ù ú ú ú ú '+ûüøeffÇÆÇdžâããÎæîïò¦åëà+ÎÛô¾Ëõ £®÷ qløI*ø6ø,ø-øKø9ø ùü ý JUû‘¦ø«Äø§Àø‡ø -6÷+,0ப«-ÌÌÌžœ›G;87Íò øBJù+.úú ú ú úú üû[[[ÉÒÒÓƒìììßøøø÷ô÷øøÝîñî†ËÒÅ#dkñ@BøH4÷B$ö 1ø,ø'5ø õ õ _÷4<]÷&+?ú ü%6ül„ùm„ù1CûC÷de”µ¶ÅÈÈËÑÑÑÈÈȸ¶¶ƒ‚‚a665Ïô&+-÷úú ú ú úûù………·âââÝùùù÷üüüýûûüýôøùøÒØÙãGOPë!úŽ–’Æ^pfõ4MD÷7B÷ qö ®õ Çô°õ‹öyö f÷g÷[ø!Iú9Coø.5˜ò.6³êw|Ì|ººÊ“”—ÏÏÏÆÆÆ®®­ PON°+,/ôù ú ú ú ü üø“””ºççèçúúûûýýýýýýýþúúúüÖÖÖú566úûdhnæ{‹ôv}œæ#+†ó ¥ô Íô Øó Ëô  õ ¥õ ¼ô ½ô ¡õyöegŸõ«¬ÏöW^¶ò/7¶é}‚Én‹Œ—ÐÐÏÇÇÆ¯®®^]]›,./õù ú ú ú úûø“““ºèèèçûûûûýýýþýýýþöööþ¾¿¿ü #ý ü Tù,<”ô&/–õ¨ô Éô Ùô Üó Ñô œõ ¬ô ¾ô Âô Àô„ö"$Yöacn쟸ð:B¥ð8@¼Ö‚•ÌÌÌ¿¾¾ ‰†…V232Ôõ*+ø"-/ùù ú ú ú úù}~~ÅààáÞøøøöúúûûúúúøìììùðý @ú ¤ô ¦õ žô Çô ×ô Üô Ûô Õô »ô ô ¬ô Àô »ô {ö (ûü*ü4:€ï)1®äur7ËËʰ°°%ZYV ï "øDMúqø!bmø"7;ùú ú úû úEFFèÎÎΠêêìïíðóäáêí·ÄÓØ¸Vhmè+3ùBù “õ °ô ¢õ ·ô Éô Ëô Äô ¿ô »ô »ô ½ô ¸ô ™õ šõaø$ü %ü#põ/7²âzvŽ,ÄÄà GFE¾ó "úqø ¡¸ø ¬Åø «Äø‡™ø:?ù ú ú û üùrz{¾¸È̸·Öß¿‚ÍßèNºÑä!Ÿºô€—÷9Mù Axø x÷ |ö›õ ¥õ ”õ •õ œõ —õ •ô ™õ €ö Zözñšïœï&’ñ#,¤ìX[¶·‡‡• ÅÅÄ`]\›ð øYcù –¬ø°ÉøµÑ÷ ªÄ÷"[dø!ù ú û ýü=Fø.Ÿ¶ò/½Ûó»Ýô¿âö½áõ ®Î÷ qƒø N_ù7Rú`Ÿö&õ ’õ ›õ ®õ ¾ô ²õ šõ ƒõ lô5ñIKc³sw¯u\^­®TY¯¸fh±¨ª«Ä,–ÌÌ̽½¼€}{g.00Ö !ô /5ùu…ø £ºø ©Á÷tƒø-3ù ú úü;Gû ™·÷ ®Ò÷ »àö Âæö Âçö ¿ãö °Ñ÷}ø`wøp´ö?Êô ±ô ¿ô ¼ô ¿ô ±ô ²ô «ô õtðQRw¢³³¹ÁÁÈ ÁÂÍ ÀÁÍ ÅÅÎ ÆÆÊÏÏÏÅÅݯ¯nnm‚-33Ú%'ò@F÷|Œ÷‚•ø :@ùú úû ]oú §È÷ ¼á÷ Âæö Ãçö Ãèö ·Úö‹£÷w‡ø@u²ö/Ìô "Öô Ëô ½ô ®ô £ôÊôÊôÊô £ôƒîxx¥tÃÃÊ ÎÎÎÅÅÅ´³²ƒ‚j?EDË(*ð38õ%46÷ù úú LVú’«÷¬Î÷ ·Ú÷ Àå÷ ½à÷ ¨Ç÷Wcú'‰™ø4Y²õ&Ñô ÙôÑô ¹ô¸ôŸõ28µöDLÎõ#0Úô Ìô•ï[]Ÿ¡¿¿Ê ÑÑÑÐÏÏÈÇǹ¹¹–••HONN±013ìö ú !ùforç26ücsú¥Æö«Èö§Ä÷ Ziù6<ü…•ø1cö#»ô!Ðô$¯õ.4•ö'¾ô(+]ùlm‚÷ÇÊåüŽ•íø,×ô¤ò.0ŽÝ—“±LÂÀÉÍÍÐÑÑÑÊÉɾ¾¾…~l+-.ðú(+,ø”•–ð6:;úBORúLs{ê0MSóUmqñ"%ú59û›÷#Vkø:”ö%3µõPU‰÷6;e÷,7¿ôFKuø`afóßßåêËÎöû(5ØôŸôƒñ%%†éjgŸ ¿¾ÈÐÐÑÐÐϺºº"JJJå÷*,,ù¸¸¹õ‚„…ïfhiólnnÞZ\\ãnooÙ""õ -/üPVû"rù nøLY§÷©¬Äðmo‡ñMWÂõ›ŸÖö«¬¶óêëíñÎÐõü+7Õô ›ô •õó#$ˆèНbËÊÏÆÆÆ |||+,-ò.//øËËÌãÚÚÚíÆÇÇáabbõ£¤¥æ¦¦¦×FHHôývü—¾Çû’­Ôú9Fºõ ¤ÞøÓÔçö§¬èöu~æôÝàôúêëôù¼¾íõ%.Äó ›ô ®ô ¬ôŽíbc£šÄÄË ÎÎΣ£¤K=>?ì345öš›œ¤¼¼½šŽŽµ]^^ìÉÉÉåÂÃÃßijjö***ý¯±±ýÝàïýyƒæ÷%0ÇôDKÉôÃÅéßÃÅéÙ\eßí„‹áôÈÉç¹uzÏÓ!&žð›ð»ð ¶ó”íYZœ¡ÃÃÌ ÑÑѽ¾¾RSUØ;<=ô345õ())õ$%%ö022õz{{É„„…Ü………ú222ý¶¶¶ýÜÞòýPZäõ#Ñô©ô9>¯ð\_½Ü,1®ò#*µñ/5´í&*”í13~åxt¦o(1Çß³ò‘ë||«jÈÈÎÃÃà z{{¥*+,õú üû'))ø,--ú”••ù‹ŒŒû444ýµ¶µûÜÞòüLWæõ"Óô ¡ô€õqõbòhæ+.xÜGJ‰Ã„„£n©ªÇ:AÇ̨ñ(*䣣½2ÎÎÑÄÄÄ oml’<=?ñ%'(øøù%&&ùabbðÓÔÔý’’’ý454ú°²±æââñã|„ìõ+Ôô õ öüöddnv°°º¾¾Ç ÃÃË §§Ê+,0µß œëef£ÂÂË Â baa’*,,ò-//öNQQåsvuÚŽð×××÷æææý———ý667÷±²²æçí²ÍÐõöCMÜó§õ |ö"ûó{wuhÈÇÇËÌÑ…‡Âb/2­ßBD™Æ··ÇÍÍÐÁÁÁ dcc“122ñ,..õ˜™™¨Ö××èééáôôôøîîîü—˜˜ý677õ±±±’ççé‰éêõÖ±µîô;AÃôö>øò‹„€`ÉÇÇÌÌО½Esu«„´´ÇÊÊÏ ffe”344ò022ôœªÕÕÕƒãããzèèèÌâããûý...ù§§¨®ÛÛÛzßàâvÜÝçÞ½¿Øû47mùüóˆ{bËÉÈÑÑÒËËÐËËÏÍÎÑ ege“566ò&((÷```Õ“””¢š››¤““”ÕŒŒŒûXXXýûhhhôŠŠ‹ÈŽŽÐ’öƒ„‡ü-.1ý þó‹„€`ÊÈÈÃàgff“566ñ*,,÷"%%ö%''ô&((ô øûýýüûûýþ þþózxhÉÈÈÈÈÈvsr…:<;ê667ñ456ñ022ñ,..ñ'()ñ#$$ò òòóó õ ÷ ö ÷ö 숅ƒaËËËÍÍÍ´²²&srq‡ihg‘llkkkj‘ggf‘fff‘cdca``Ž^^^Ž\\[ŽZZYZXXZXWZXWYXWZYYusr}º¹¹ÏÏÎÌÌÌÇÇÇààà ÂÂÁ ÁÁÁ ÁÁÁ ÁÁÁ ÁÁÁ ÁÁÀ ÁÀÀ ÁÀÀ ÁÀÀ ÁÀÀ ÁÁÁ ÇÇÇÍÍÍÿÿÀÿÿÿÿÿÿÿüÿÿÿøÿÿà?ÿÿ€ÿþÿüÿüÿüÿüÿüÿüÿþÿþÿþþüðààààøøðààààðÿüÿ?ÿÀÿðÿøÿøÿøÿüÿü?ÿü?ÿüÿüÿÿüÿÿüÿÿüÿÿüÿÿþ?ÿ( @ €ÑÑÑÉÉɺºº›œœ3bff†&**è"&'çtssg±±±ÇÆÆÑÑÑÌË˽¼¼›9`kl—-DHâCIð?Fö$'÷+.íIUW»šžŸ=À¿¿ ÎÎÎÎÎΠ©««$enoŽ)BEæXbñ“õ˜®ø}ø.5ý^kø]iò)CGãz‚‚m¸¹¹ÊÊÊÐÐÐÆÆÆ´µµz„…r4KOÖQY𠃕õ¢º÷°Ë÷·Ò÷–¬øCMüvˆø›²÷ ~ôHNìZhiŸ¬®¯ ÆÅÅÑÑÑÌËË»¼¼–—NFZ]¿MTí |ô ¸÷¯É÷¸Ô÷»×÷ºÖ÷š±÷GQü x‰ù¬Æø¬Å÷ •ªõ\fð@UXÄ™Ÿ 9¿¿¿ ÍÍÍÀÀÀ nst‹$AFékyò›²ö­Çø·Ó÷»×÷»×÷»×÷»×÷žµ÷NYû n~ú®Èø¹Õ÷±Ë÷¢ºöv†ñ)JOâu€yº»»ÎÎεµµ>JLË ^kõ ·÷µÑ÷ºÖ÷¹Õ÷¶Ó÷µÑ÷¶Ò÷¸Ô÷ž¶÷ NYû m}ù©ÃøµÑ÷±Î÷­É÷¥¿÷ ‚•ô%HMé„…rÆÆÆ³³³@QSÅ jxõªÄ÷¹Õ÷µÒ÷ªÆ÷™´÷’¬÷˜³÷¨Ä÷˜°÷JUûgwùš´÷”¯÷„œø‹¤ø¸÷˜°÷[fðdmn‘¾¾¾ ¶¶¶Pbd©lzô§À÷¬É÷˜³÷‚™ø_oùN[úhzù‚šøyøÂÂÐ ¾¾ÀÐÏϳ³³U]_©15ö,2ü OZú …—ø¢º÷¨Á÷ ›±÷p~÷BHùW^ù‡“ø y‰ø PZú5;ýHPû ’øœ³÷›²÷ z‹õ KUæM]‚¬HRªÑŸ ¾Aºº½¾¾½¸¸¸‚‡‡T+9;Û39ø OYù R\ùr‚ù•ªø€‘öKR÷;NQìr”˜º)ºÇôÀÐ÷°½÷v}øJDø66ú).ü Vcú“¨øžµø ”¬õ Oiø"6`ꀅ£b±±´ ´´´`_^ª&/0éNWóIRø%(ú "&ú *.úCJù69øaklн¿¿°¾ÙÜäKÌØó½Èõ÷ UAø8%ø).ø=ù 3û 3Aü sˆù“«ø„ŸøG[ïZ]i¦®®´ ¶¶¶ |zyx3:;Ø6:ñ*-÷ú ú úùOSSØÆÆÆºíííòæóõö¥ÏÓÛ7koô/YPóI7ö40ø ![ö õq÷+cø!NûGqùNmú4fóotª‡¡¢´hhnÁÁÁ¿¾¾ ž Ÿ*PQQ«$()óú ú ûøoooÑÚÚÚìûûûúöøùüÈÌÍöBHLöGOXâZdxö/>~î¡ô Ãôµô ’õ ›õ õ +x÷nu§óJP¨åruµw\]l ÄÄÄÁÁÁ Ÿ Ÿ+TYZŸ'.0óù ú úømmmÖÙÙÙíúúúùóóóû·¸¸ú12?ú[÷%/’ô$¬ôÊó Õô Åô ©ô µô µô{ö57Xô^a’í5<ÖPPhƒƒƒ´³³ ‹ŒŒX6DEÓDJñ]gö=Bù!ù úùGHHæÀÄÅËÞéëíÎâæÖ{“™Ý!8Jú ~õ  ô ªõ Äô Èô Àô ´ô ¯ô ¡õ ~õCûOø28™ÜKJe*ƒƒƒ™˜˜:9;;Ý@Eñ €’÷ –¬øˆœ÷:@ù ú ú(*ùa|ƒÏŠÉ×Õ]ÄÚì-§Àòv’ö Lxø &{÷!›õ ¢õ ©ô ©ô ô Žônï%*{ã.5—á7>œßX\£¤YZjƒƒƒ°°°wxwx.=?ßRZð‹žô “¨÷U_ø!ù û /7úŠ¡õ¶×ôÂãõ´Õõ“¯÷fˆøY¨ö*¯õ ²ô ²ô ³ô ©ô‰ò68vÉ‘¬8¤¥Á.¤¥Ä9©©¹eflÂÁÁ¿¾¾ ¡££/fqrŒ4OSÛ&ají \gó#'ùú ALú—µ÷ µØ÷ ¾áö ®Îör‡ø+u°ö6Èô!Éô·ô«õ'Ãô'Åô#¤ðUWž¥²²ÁÎÎÏÐÐÒ¿¿ÀËËʾ¾¾ ©¬­%y‚r>HIÐ'/2ð$&ù7KOò!]jú˜³ö¥Áö‚˜÷drù#dœö4Áô&¾ô$+¨õ,1ömq²÷ksØ÷)3Åñ6:›Ò›¸4ÃÃË ÐÐÒÍÍÍÁÁÁ §§§$NNOÈ033ôhlmöFTWù\z€ï7V]ó>í“””¨ÀÀÀˆÅÆÆÛ”••ûVWWñ­­®šº»Å¨¡¢¸ù&(Iû##+ë’ŽŒIËÉÉËËÐÈÉÏÈÈÏÐÐÒ»»»`a`«9::î8::îJKKè@@Aó---û&&&ù///ö;;;ö,,/úý$#$싊LËÊÉÄÃà {zyŒLLLÛFGGàBCCá=>>á667á111á,,,â***ã)((ä(((ä@>>Ô£¡ 8ÍÍÍËË˽½½««ª#§¦¦'¦¥¥'¤¤¤'¢¢¢&¡  & ŸŸ&Ÿžž&Ÿžž& ŸŸ'®­­ ÐÐÐÿÀÿÿ€ÿþÿøð?ððððððàÀÀÀÀÀ€€€Àðüÿÿÿÿ€ÿ€ÿ€ÿ€ÿÿ€ÿÿ€ÿ(0 ` ÌÌ̾¾¾ ¡¦§)boqƒ)58Ý+57Ùz}}_µ¸¸ÉÉÉÎÎÎÂÃà ª¯°!iz|‡2Y^Ûnzîhvó7<õ NUëVkn§§¯¯&ÄÅÅ ÐÐÐÐÐÐÆÆÆ´¹º}i7[`Òtí ›±ô¦¿÷£øHRû †™ö~Žî8[`Ï‘žF¾ÀÀ ÍÍÍÑÑÑÂÂà —¡£CIdhºlx뙯òªÃöµÐ÷ºÖ÷›³øT_û”ªøªÃ÷–ªñ'ajãt‡‰s¶»¼ÉÉÉÏÏϧ©©,5RVÝ„–ð¨Áö²Í÷·Ó÷·Ô÷¸Õ÷œ³øVbû“©ø³Î÷«Æ÷  ¸óm{ëWkn®·º»ÐÐÐÏÏÏœŸ 3(V^ç™°÷µÑ÷­É÷¸÷—°÷ »÷”ª÷P\û‡œø˜²÷Œ¥ø’«÷ ޤõ+]eå› ¡<ÎÎÎÐÐШ­®+Zb啬÷ž¹÷‡ŸøcsùXfûr…øu‰ø;Dûevø]mùQ^û_núu‰ø)X`ç–œž@ÌÌÌ«¯¯.TZäw‹øl~ùLXû o€ù‹ øjyúDü ]húŒ ø‹ŸøfsñIdt¦\j¬³©«½*™™›¤¤£¯¯¯!ahi‹7;ñCKù ISú sƒøw†ö-U[õjŠŽËC´¾é¬¸ö …Œ÷NHø69ú :Fû r†ù ”©ô sõ)Ig册¡W””—¤¤£wwv4ACáLSð"$ù !$ú*-ù0AD¬¶ËÚÜì„ÊÐä/–õ[P÷?;÷ &Q÷ \ø1WúJkû s—øOpïx}“p‹‹– ¥¤¤µ¶µy~b/67áø úùZ[[ÜÑÑÑíïôõøÄÐÒö>OV÷Pcqè.Brò˜õ ­ô õ Žö%v÷L\–ñOW¤Èwy“,#¤¤¤¶¸¸zƒƒ`1ADÜ'*ø úøXYYßÎÐÑíêïñø²º½÷1;Sú'~õ%¢ôÃô Çô ©ô ¨ô•õ$']õOS‹åJM‹|"žž npp‘,MRçròdp÷*.ùù,68ö™®³È©ÖàÕ_£³âTqø ,‹öŸõ µô ±ô «ô¡ò!‡í&,|êZgûQ|£ùitÁôrw½õ—›Ðõ£¦Ùö39¸ð#'¥è\^¦©»»Æ ÁÁÁƒƒ„‰YZZÛ^__Ôqqræ}írx‚û~ˆÈùALÀôquÁã\b¿íjn¼ÒFI¦Ì)/´âSU§¯··ÅÇÇÇ “””YFGGæ9::õXYZô›œœù…†ô‡‹Ïñ:A¼ò"}ó?@rÌvw v½@DH²Î€µjÀÀÉ ÈÈÈTHIIäz||ij´´ï«««ø†‡ŒÍ±³ÌÊW\¸ñ"$fòOM\ª­­³§¨Å1€‚·¹ºËÊÊÌÈÈÈŽŽTJKK䂃ƒ¶¡¢£º‰‰‰øccdæ–®……•ñ**@ôXUZ¥·¶·ÉÉÏÉÉÐËËÐÌÌËšššKYYZÙJKLäMNNäBBCè===ç;;;è668ê545æeccÀ¿¿ ÏÎλ»»“’’P…„„Z€Z}}}YzzzYyxxYxwwY€€U¥¤¤.ÆÆÆþÿø?àÀÀÀÀàÀ€€€€€€€Àøüüüüü?ü?(  @ÏÏÏÃÅÆ §²´ hƒy.OSÓ3JN˃ŽQºÀÁÍÍ͸¸¸ÈÉʶÀÁ€˜œa;w€Î“¤ë’¥ñbnò%r~åk‰‚³¾ÀÈÊÊÑÑѲ²²¨²³-S|‚°Œé©Áò®É÷ ¹øm}ú —¬ô–©ëO|ƒ®§´¶+ÈÉÊ­­­|‘k#ŽŸç ¡¹õ¡»÷ž¸÷•¬÷dsú¤÷ ‘©ö£ìXuy®¾ÁÁ «««“–`…–ꊡøl~úl}ùhyùITúXfùgxùixôEnx¾¯´¸°°´bbb¤¥¦ z‹ŽdU`î Xeú „–÷‰›ö[dùZcùJSûn|ù xŠö)^kØtˆ©x› ©QQRaaaŽŽ6L`c¸DKð CLùgr÷U{€Ýb¯·ä&™¡ö UZ÷ 8Mù Kjùzó-bãyJKKQ```+V_`¤*,ó"$ùBLNèºÆÈæ³ÊÏïCdpï$Ffõ#õ(Žö +}÷2L„ïYb‘~ABL]]\’’&Qcf¤9>ô#%ø?HJì³ÄÈ飻Ãé,Epø&–õ·ô «ô¢ð(/tì?M^^^uyya?lsÙ }Œì49ö 7;ùH–¦æ6©Åómœ÷2™ö¯õ©ó'+‹ã^b¥lo›oEEN ___¦ªª ›«­8ay}—4NSã,HMñ"„™ö ›´õ%l•÷6´ô,5­õAH»ô?DªÕ™š¾)¡¡®OOS···ÊË˺½½‰ŒdVbeèYpuïQmsí:f…ùLa¬ö\c¹õˆ‹Åò8=°æab¬¥££¯ ÐÐг´´`abÑVXX惇‡ë‚‡œú@K±ô[`°æW[¨Ù[^°°]_¯¬  ®···_``ÄmooÜŸŸŸô‡ˆ˜ÒZ^¨ò56lê¥@ŒŽ½\ ¡ÁC©©²»»»fgg½wxx»zzzäggn×jkvÜDESß¡Ÿ¦0ÈÇÍËËѳ³µÀÀÀ ŽhtttŠoooŒiii___Žsss€²²²ÑÑÐà€€€€€àðððbochs-2.6/build/win32/nsis/penguin.ico0000644000175000017500000000635612020641473017524 0ustar guillemguillem è6 ¨(Æ ( @€€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ01333333;»»³;»³;»»»³ÿÿð;»»»;»»»¿ÿÿÿ;»»»°;»»»°ÿÿÿ÷;»»»»»»»ÿÿÿ÷;»»° »»°ÿÿÿ÷³3;°»°ÿÿÿÿÿ» »ÿÿÿÿÿ3ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿðÿÿÿÿÿpÿÿÿ÷ÿÿÿÿÿÿÿ÷ÿðw7ðs37»»;»»» »ÿÿ€ÿðÿøàÀ?ÀÀÀÀàø?ü?ü?ü?ü?þ?þ?ÿÿÿÿÿ€ÿÿÀÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿðÿÿø?ÿ( @€€€€€€€€€€ÀÀÀÀÜÀðʦ """)))UUUMMMBBB999€|ÿPPÿ“ÖÿìÌÆÖïÖçç©­3f™Ì3333f3™3Ì3ÿff3fff™fÌfÿ™™3™f™™™Ì™ÿÌÌ3ÌfÌ™ÌÌÌÿÿfÿ™ÿÌ3333f3™3Ì3ÿ3333333f33™33Ì33ÿ3f3f33ff3f™3fÌ3fÿ3™3™33™f3™™3™Ì3™ÿ3Ì3Ì33Ìf3Ì™3ÌÌ3Ìÿ3ÿ33ÿf3ÿ™3ÿÌ3ÿÿff3fff™fÌfÿf3f33f3ff3™f3Ìf3ÿffff3fffff™ffÌf™f™3f™ff™™f™Ìf™ÿfÌfÌ3fÌ™fÌÌfÌÿfÿfÿ3fÿ™fÿÌÌÿÿÌ™™™3™™™™Ì™™33™f™3Ì™ÿ™f™f3™3f™f™™fÌ™3ÿ™™3™™f™™™™™Ì™™ÿ™Ì™Ì3fÌf™Ì™™ÌÌ™Ìÿ™ÿ™ÿ3™Ìf™ÿ™™ÿÌ™ÿÿÌ™3ÌfÌ™ÌÌ™3Ì33Ì3fÌ3™Ì3ÌÌ3ÿÌfÌf3™ffÌf™ÌfÌ™fÿ̙̙3Ì™fÌ™™Ì™ÌÌ™ÿÌÌÌÌ3ÌÌfÌÌ™ÌÌÌÌÌÿÌÿÌÿ3™ÿfÌÿ™ÌÿÌÌÿÿÌ3ÿfÿ™Ì3ÿ33ÿ3fÿ3™ÿ3Ìÿ3ÿÿfÿf3Ìffÿf™ÿfÌÌfÿÿ™ÿ™3ÿ™fÿ™™ÿ™Ìÿ™ÿÿÌÿÌ3ÿÌfÿÌ™ÿÌÌÿÌÿÿÿ3Ìÿfÿÿ™ÿÿÌffÿfÿffÿÿÿffÿfÿÿÿf!¥___www†††–––ËË˲²²×××ÝÝÝãããêêêñññøøøðûÿ¤  €€€ÿÿÿÿÿÿÿÿÿÿÿÿ "## "**" **+111# *111" 1111888Y8+ 18888R 188Y888881ÿÿÿÿÿ 1881YY88 188118888ÿÿÿÿÿÿÿ 18Y881881 188Y8YY88 ÿÿÿÿÿÿÿ¼18888888 188188Y8 ÿÿÿÿÿÿÿ¼1111888 818888 ÿÿÿÿÿÿÿÿ81**188 1888 ÿÿÿÿÿÿÿÿÿÿ81 Y Y8 ÿÿÿÿÿÿÿÿÿÿÿ11 ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ  ¼ÿÿÿÿÿÿÿÿÿÿÿÿÿ  ôÿÿÿÿÿÿÿÿÿÿÿÿÿ C ÿÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿÿÿÿ  ÿÿÿÿÿÿÿô ÷ÿÿóôÿÿôñô ÿÿÿÿÿÿÿÿÿ ôÿ¼ÿÿÿÿ ñQ¼ðÿÿ 111Qð C 88Y711 188Y77 787 ÿ ÿÿ ì ÿÿ ñÿò  ë  ê ÿðÿøàÀ?ÀÀÀÀàø?ü?ü?ü?ü?þ?þ?ÿÿÿÿÿ€ÿÿÀÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿàÿÿðÿÿø?ÿ( À€€€€€€€€€ÀÀÀ€€€ÿÿÿÿÿÿÿÿÿÿÿÿ33 »»;» »»ÿÿ;»° »°ÿÿ3; ÿÿ° ÿÿÿðÿÿÿðÿÿøÿ÷ÿÿsw»°ppãÏ€€€àààððøüüüüü?ü?bochs-2.6/build/win32/nsis/unbochs.ico0000644000175000017500000000137612020641473017515 0ustar guillemguillem è( @€€€€€€€€€€€€€ÀÀÀÿÿÿÿÿÿÿÿÿÿÿÿ™€™ pp ™™ » ™»»0»™ »»»0»³ ™»»»0»»™ ¹›»»°;¹›0 »»™»»°;™»» »»¹›»°9“3»° »³3™3°™3;° »3 “¹“3° ³0™™ ·°0»»¹»±{»»™™1»»»“9“»»pp »»°™33™0»°»»° “30 °™33™33“3339“s™33333™· “3333 ›»±»™3330»™»0€ ¹›p33»»¹™»»p3 »»»™p »»±»»³ ™»»° »™{ €ÿÿÿÿÿÿÿÿÏÿóçüçóðÏùÀŸü€?þø?àààððððððÀ€€ððÀ€€àÌs߀ûÿÀáÿÿÿÿÿbochs-2.6/build/win32/nsis/bochs.nsi.in0000644000175000017500000002222612020641473017573 0ustar guillemguillem;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; $Id: bochs.nsi.in 10815 2011-12-04 08:25:01Z vruppert $ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Setup Script for NSIS Installer ; ; Created: Michael Rich (istan) ; ; Based on Example Script by Joost Verburg ; also original BOCHS script by Robert (segra) ; updated for NSIS 2.44 by Volker Ruppert ; ;--------------------- ;Include Modern UI 2 !include "MUI2.nsh" ;-------------------------------- ;Include MultiUser !define MULTIUSER_EXECUTIONLEVEL Highest !define MULTIUSER_MUI !include MultiUser.nsh Function .onInit !insertmacro MULTIUSER_INIT FunctionEnd Function un.onInit !insertmacro MULTIUSER_UNINIT FunctionEnd ;-------------------------------- !define VERSION @VERSION@ !define NAME "Bochs ${VERSION}" !define CURRENTPAGE $9 !define TEMP1 $R0 !define TEMP2 $R1 !define SRCDIR bochs-${VERSION} !define PGDIR "$SMPROGRAMS\Bochs ${VERSION}" !define DESKTOP_DLXLINK "$DESKTOP\Linux Demo in ${NAME}.lnk" !define DESKTOP_DLX_PIF "$DESKTOP\Linux Demo in ${NAME}.pif" ;-------------------------------- ;General Name "${NAME}" OutFile Bochs-${VERSION}.exe SetOverwrite on ; Installation Types InstType "Normal" InstType "Full (with DLX Linux demo)" ;Folder-select dialog InstallDir $PROGRAMFILES\Bochs-${VERSION} InstallDirRegKey HKLM "Software\${NAME}" "" ;-------------------------------- ;Interface Settings !define MUI_ABORTWARNING !define MUI_COMPONENTSPAGE_NODESC !define MUI_ICON "bochs.ico" !define MUI_UNICON "unbochs.ico" ;-------------------------------- ;Pages !insertmacro MUI_PAGE_LICENSE ${SRCDIR}\COPYING.txt !insertmacro MULTIUSER_PAGE_INSTALLMODE !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;-------------------------------- ;Languages !insertmacro MUI_LANGUAGE "English" ;-------------------------------- ;Installer Sections Section "Bochs Program (required)" SecCore SectionIn 1 2 RO SetOutPath "$INSTDIR" File "${SRCDIR}\*.exe" File "${SRCDIR}\*.txt" File "*.ico" ; Install keymaps SetOutPath "$INSTDIR\keymaps" File "${SRCDIR}\keymaps\*" SectionEnd Section "ROM Images (required)" SecROMs SectionIn 1 2 RO SetOutPath "$INSTDIR" File "${SRCDIR}\BIOS-bochs-*" File "${SRCDIR}\VGABIOS-*" SectionEnd Section "Documentation in HTML" SecDocs SectionIn 1 2 SetOutPath "$INSTDIR\docs" File "${SRCDIR}\share\doc\bochs\index.html" SetOutPath "$INSTDIR\docs\user" File "${SRCDIR}\share\doc\bochs\user\*" SetOutPath "$INSTDIR\docs\development" File "${SRCDIR}\share\doc\bochs\development\*" SetOutPath "$INSTDIR\docs\documentation" File "${SRCDIR}\share\doc\bochs\documentation\*" SetOutPath "$INSTDIR\docs\images" File "${SRCDIR}\share\doc\bochs\images\*" SectionEnd Section "DLX Linux Demo" SecDLX SectionIn 2 SetOutPath "$INSTDIR\dlxlinux" File "${SRCDIR}\dlxlinux\*" ; Fix up the path to the Bochs executable FileOpen $1 "$INSTDIR\dlxlinux\run.bat" w FileWrite $1 'cd "$INSTDIR\dlxlinux"$\r$\n' FileWrite $1 "..\bochs -q -f bochsrc.bxrc$\r$\n" FileClose $1 SectionEnd Section "Add Bochs to the Start Menu and Desktop" SecIcons SectionIn 1 2 ; Set the Program Group as output to ensure it exists SetOutPath "${PGDIR}" ; Change the output back to the install folder so the "Start In" paths get set properly SetOutPath "$INSTDIR" CreateShortCut "${PGDIR}\${NAME}.lnk" "$INSTDIR\Bochs.exe" "" "$INSTDIR\bochs.ico" "0" CreateShortCut "${PGDIR}\Readme.lnk" \ "$INSTDIR\Readme.txt" CreateShortCut "${PGDIR}\Bochs Sample Setup.lnk" \ "$INSTDIR\bochsrc-sample.txt" CreateShortCut "${PGDIR}\Disk Image Creation Tool.lnk" \ "$INSTDIR\bximage.exe" CreateShortCut "${PGDIR}\NIC Lister.lnk" \ "$INSTDIR\niclist.exe" WriteINIStr "${PGDIR}\Help.url" \ "InternetShortcut" "URL" "file://$INSTDIR/docs/index.html" WriteINIStr "${PGDIR}\Home Page.url" \ "InternetShortcut" "URL" "http://bochs.sourceforge.net/" CreateShortCut "${PGDIR}\${NAME} Folder.lnk" \ "$INSTDIR" CreateShortCut "${PGDIR}\Uninstall Bochs.lnk" \ "$INSTDIR\Uninstall.exe" "" "$INSTDIR\unbochs.ico" "0" ; Create shortcut to DLX Linux if it was installed IfFileExists "$INSTDIR\dlxlinux\*" 0 no CreateShortCut "${PGDIR}\DLX Linux.lnk" "$INSTDIR\dlxlinux\run.bat" "" "$INSTDIR\penguin.ico" "0" ; Add a link to the DLX demo to the desktop CreateShortCut "${DESKTOP_DLXLINK}" "$INSTDIR\dlxlinux\run.bat" "" "$INSTDIR\bochs.ico" "0" no: SectionEnd Section "Register .bxrc Extension" SecExtension SectionIn 1 2 RO ; back up old value of .bxrc ReadRegStr $1 HKCR ".bxrc" "" StrCmp $1 "" Label1 StrCmp $1 "BochsConfigFile" Label1 WriteRegStr HKCR ".bxrc" "backup_val" $1 Label1: WriteRegStr HKCR ".bxrc" "" "BochsConfigFile" WriteRegStr HKCR "BochsConfigFile" "" "${NAME} Config File" WriteRegStr HKCR "BochsConfigFile\DefaultIcon" "" "$INSTDIR\bochs.ico,0" WriteRegStr HKCR "BochsConfigFile\shell" "" "Configure" WriteRegStr HKCR "BochsConfigFile\shell\Configure\command" "" '"$INSTDIR\Bochs.exe" -f "%1"' WriteRegStr HKCR "BochsConfigFile\shell" "" "Edit" WriteRegStr HKCR "BochsConfigFile\shell\Edit\command" "" '$WINDIR\NOTEPAD.EXE "%1"' WriteRegStr HKCR "BochsConfigFile\shell" "" "Debugger" WriteRegStr HKCR "BochsConfigFile\shell\Debugger\command" "" '"$INSTDIR\Bochsdbg.exe" -f "%1"' WriteRegStr HKCR "BochsConfigFile\shell" "" "Run" WriteRegStr HKCR "BochsConfigFile\shell\Run\command" "" '"$INSTDIR\Bochs.exe" -q -f "%1"' SectionEnd Section -post ; Register Uninstaller WriteRegStr HKLM "SOFTWARE\${NAME}" "" $INSTDIR WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "DisplayName" "${NAME} (remove only)" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "DisplayIcon" "$INSTDIR\bochs.ico,0" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "DisplayVersion" "${VERSION}" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "Publisher" "The Bochs Project" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "URLInfoAbout" "http://bochs.sourceforge.net" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "Readme" '$INSTDIR\Readme.txt' WriteRegDWord HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "NoModify" "1" WriteRegDWord HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "NoRepair" "1" WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "InstallLocation" '$INSTDIR\' WriteRegExpandStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" "UninstallString" '"$INSTDIR\Uninstall.exe"' ; Write the uninstaller WriteUninstaller "$INSTDIR\Uninstall.exe" SectionEnd ;-------------------------------- ;Installer Functions Function .onInstSuccess MessageBox MB_YESNO|MB_ICONQUESTION \ "Would you like to see a list of changes?" \ IDNO NoChanges ExecWait 'notepad.exe $INSTDIR\CHANGES.TXT' NoChanges: MessageBox MB_YESNO|MB_ICONQUESTION \ "Setup has completed. Show README now?" \ IDNO NoReadme ExecWait 'notepad.exe $INSTDIR\README.txt' NoReadme: MessageBox MB_OK "Thank you for installing Bochs, think inside the bochs." FunctionEnd ;-------------------------------- ;Uninstaller Section Section "Uninstall" ReadRegStr $1 HKCR ".bxrc" "" StrCmp $1 "BochsConfigFile" 0 NoOwn ; only do this if we own it ReadRegStr $1 HKCR ".bxrc" "backup_val" StrCmp $1 "" 0 RestoreBackup ; if backup == "" then delete the whole key DeleteRegKey HKCR ".bxrc" Goto NoOwn RestoreBackup: WriteRegStr HKCR ".bxrc" "" $1 DeleteRegValue HKCR ".bxrc" "backup_val" NoOwn: DeleteRegKey HKCR "BochsConfigFile" DeleteRegKey HKLM "SOFTWARE\${NAME}" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${NAME}" Delete "${PGDIR}\*.lnk" Delete "${PGDIR}\*.pif" Delete "${PGDIR}\*.url" RMDir "${PGDIR}" Delete "${DESKTOP_DLXLINK}" Delete "${DESKTOP_DLX_PIF}" Delete "$INSTDIR\*.exe" Delete "$INSTDIR\*.txt" Delete "$INSTDIR\*.ico" Delete "$INSTDIR\keymaps\*" Delete "$INSTDIR\BIOS-bochs-*" Delete "$INSTDIR\VGABIOS-*" Delete "$INSTDIR\dlxlinux\*" Delete "$INSTDIR\docs\index.html" Delete "$INSTDIR\docs\user\*" Delete "$INSTDIR\docs\development\*" Delete "$INSTDIR\docs\documentation\*" Delete "$INSTDIR\docs\images\*" RMDIR "$INSTDIR\keymaps" RMDIR "$INSTDIR\dlxlinux" RMDIR "$INSTDIR\docs\user" RMDIR "$INSTDIR\docs\development" RMDIR "$INSTDIR\docs\documentation" RMDIR "$INSTDIR\docs\images" RMDIR "$INSTDIR\docs" RMDIR "$INSTDIR" SectionEnd ;eof bochs-2.6/build/win32/diffcc2cpp0000755000175000017500000000015612020641473016330 0ustar guillemguillem#!/bin/sh list=`find . -name '*.cpp' | sed 's/\.cpp$//'` for i in $list; do diff -u ${i}.cc ${i}.cpp done bochs-2.6/build/win32/README.win32-binary0000644000175000017500000000000012020641473017466 0ustar guillemguillembochs-2.6/build/win32/cpp2cc0000755000175000017500000000015112020641473015472 0ustar guillemguillem#!/bin/sh list=`find . -name '*.cpp' | sed 's/\.cpp$//'` for i in $list; do mv ${i}.cpp ${i}.cc done bochs-2.6/build/linux/0000755000175000017500000000000012020641466014574 5ustar guillemguillembochs-2.6/build/linux/README.linux-binary0000644000175000017500000000000012020641466020062 0ustar guillemguillembochs-2.6/build/linux/bochs-dlx.in0000755000175000017500000000603112020641466017012 0ustar guillemguillem#!/bin/sh BOCHS=@prefix@/bin/bochs DLXINST=@prefix@/share/bochs/dlxlinux GZIP=@GZIP@ if [ ! -z $1 ]; then DLXPATH=$1 else DLXPATH=$HOME/.bochsdlx fi CONFFILE=$HOME/.bochsdlx/bochsconf makedlxdir() { echo echo --------------------------------------------------------------- echo To run the DLX Linux demo, I need to create a directory called echo $DLXPATH, and copy some configuration files echo and a 10 megabyte disk image into the directory. echo --------------------------------------------------------------- ok='unknown' while test $ok = 'unknown'; do echo Is that okay? [y/n] read j case $j in y*) ok=1 ;; n*) ok=0 ;; esac done if test $ok != 1; then echo Aborting exit 1 fi #echo DEBUG: Creating $HOME/.bochsdlx/bochsrc echo DLXPATH=$DLXPATH > $CONFFILE . $CONFFILE for file in bochsrc.txt readme.txt testform.txt; do if [ ! -f $DLXPATH/$file ]; then echo Copying $DLXINST/$file '->' $DLXPATH/. cp $DLXINST/$file $DLXPATH/. else echo "ERROR: $file already exists in $DLXPATH. Remove it to replace." fi; done if [ ! -f $DLXPATH/hd10meg.img ]; then echo Uncompressing $DLXINST/hd10meg.img.gz '->' $DLXPATH/hd10meg.img $GZIP -dc $DLXINST/hd10meg.img.gz > $DLXPATH/hd10meg.img else echo "ERROR: hd10meg.img already exists in $DLXPATH. Remove it to replace." fi } echo --------------------------------------------------------------- echo " DLX Linux Demo, for Bochs x86 Emulator" echo --------------------------------------------------------------- echo -n "Checking for bochs binary..." if test ! -x $BOCHS; then echo FAILED echo ERROR: I could not find bochs in $BOCHS exit 1 fi echo ok echo -n "Checking for DLX linux directory..." if test ! -d $DLXINST; then echo FAILED echo ERROR: I could not find the DLX linux directory. exit 1 fi echo ok echo -n "Checking for $GZIP..." $GZIP < /dev/null > /dev/null if test $? = 0; then echo ok else echo not found echo ERROR: without $GZIP in your PATH, I cannot continue. exit 1 fi echo -n "Checking for $HOME/.bochsdlx directory..." if test -d "$HOME/.bochsdlx"; then echo "ok" if test -f "$CONFFILE"; then . $CONFFILE else makedlxdir fi else #echo DEBUG: Creating $HOME/.bochsdlx mkdir -p $HOME/.bochsdlx mkdir -p $DLXPATH makedlxdir fi echo Entering $DLXPATH cd $DLXPATH # Now that we're in the DLXPATH, make sure that bochsrc.txt & hd10meg.img exist if test ! -f bochsrc.txt; then echo ERROR: bochsrc.txt not found exit 1 fi if test ! -f hd10meg.img; then echo ERROR: hd10meg.img not found exit 1 fi echo Running bochs # ok now try it $BOCHS -q echo echo --------------------------------------------------------------- echo The DLX Linux demo is over. If you want to free up the disk echo space in your account, remove the .bochsdlx directory from echo your home directory. Example: echo " rm -rf ~/.bochsdlx" echo Please be careful with rm -rf because it can make a mess. echo --------------------------------------------------------------- exit 0 bochs-2.6/build/batch-build.perl0000755000175000017500000002104412020641473016501 0ustar guillemguillem#!/usr/bin/perl ##################################################################### # $Id: batch-build.perl 10213 2011-02-25 15:32:08Z sshwarts $ ##################################################################### # # Batch build tool for multiple configurations # # switches: # - show output vs. send it all to nohup. --nohup # - serial or parallel. --parallel # # no args: serial, display output # --nohup: serial, output to nohup.out. (Need summary.) # --nohup --parallel: parallel, output to nohup.out # --parallel: parallel, spawn xterm for each # sub usage { print <$name/build.sh"); print BUILD <$name/xterm-init.sh"); print XTI < #ifdef HAVE_LOCALE_H #include #endif #if defined(macintosh) // Work around a bug in SDL 1.2.4 on MacOS X, which redefines getenv to // SDL_getenv, but then neglects to provide SDL_getenv. It happens // because we are defining -Dmacintosh. #undef getenv #endif int bochsrc_include_count = 0; #if BX_PLUGINS Bit8u bx_user_plugin_count = 0; #endif #define LOG_THIS genlog-> extern bx_debug_t bx_dbg; static const char *get_builtin_variable(const char *varname); static int parse_line_unformatted(const char *context, char *line); static int parse_line_formatted(const char *context, int num_params, char *params[]); static int parse_bochsrc(const char *rcfile); static int get_floppy_type_from_image(const char *filename); static Bit64s bx_param_handler(bx_param_c *param, int set, Bit64s val) { char pname[BX_PATHNAME_LEN]; Bit8u device; //Bit8u channel; bx_list_c *base = (bx_list_c*) param->get_parent(); base->get_param_path(pname, BX_PATHNAME_LEN); if (!strncmp(pname, "ata.", 4)) { // channel = pname[4] - '0'; if (!strcmp(base->get_name(), "master")) { device = 0; } else { device = 1; } if (!strcmp(param->get_name(), "type")) { if (set) { switch (val) { case BX_ATA_DEVICE_DISK: ((bx_param_filename_c*)SIM->get_param("path", base))->set_extension("img"); break; case BX_ATA_DEVICE_CDROM: ((bx_param_filename_c*)SIM->get_param("path", base))->set_extension("iso"); break; } } } else { BX_PANIC(("bx_param_handler called with unknown parameter '%s.%s'", pname, param->get_name())); return -1; } } else { param->get_param_path(pname, BX_PATHNAME_LEN); if ((!strcmp(pname, BXPN_FLOPPYA_TYPE)) || (!strcmp(pname, BXPN_FLOPPYB_TYPE))) { if (set) { if (val == BX_FLOPPY_AUTO) { val = get_floppy_type_from_image(SIM->get_param_string("path", base)->getptr()); SIM->get_param_enum("type", base)->set(val); } else if (!SIM->get_init_done() && (val != BX_FLOPPY_NONE)) { switch (val) { case BX_FLOPPY_2_88: device = BX_FDD_350ED; break; case BX_FLOPPY_720K: case BX_FLOPPY_1_44: device = BX_FDD_350HD; break; default: device = BX_FDD_525HD; } SIM->get_param_enum("devtype", base)->set(device); } } } else { BX_PANIC(("bx_param_handler called with unknown parameter '%s'", pname)); return -1; } } return val; } const char *bx_param_string_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { char pname[BX_PATHNAME_LEN]; param->get_param_path(pname, BX_PATHNAME_LEN); if (!strcmp(pname, BXPN_SCREENMODE)) { if (set==1) { BX_INFO(("Screen mode changed to %s", val)); } #if BX_PLUGINS } else if (!strncmp(pname, "misc.user_plugin", 16)) { if ((strlen(oldval) > 0) && (strcmp(oldval, "none"))) { PLUG_unload_user_plugin(oldval); } if ((strlen(val) > 0) && (strcmp(val, "none"))) { PLUG_load_user_plugin(val); } #endif } else { BX_PANIC(("bx_param_string_handler called with unknown parameter '%s'", pname)); } return val; } void bx_init_std_nic_options(const char *name, bx_list_c *menu) { // networking module choices static const char *eth_module_list[] = { "null", #if BX_NETMOD_LINUX "linux", #endif #if BX_NETMOD_TAP "tap", #endif #if BX_NETMOD_TUNTAP "tuntap", #endif #if BX_NETMOD_WIN32 "win32", #endif #if BX_NETMOD_FBSD "fbsd", #endif #if BX_NETMOD_VDE "vde", #endif #if BX_NETMOD_SLIRP "slirp", #endif "vnet", NULL }; bx_param_enum_c *ethmod; bx_param_string_c *macaddr; bx_param_filename_c *path, *bootrom; char descr[120]; sprintf(descr, "MAC address of the %s device. Don't use an address of a machine on your net.", name); macaddr = new bx_param_string_c(menu, "macaddr", "MAC Address", descr, "", 6); macaddr->set_options(macaddr->RAW_BYTES); macaddr->set_initial_val("\xfe\xfd\xde\xad\xbe\xef"); macaddr->set_separator(':'); ethmod = new bx_param_enum_c(menu, "ethmod", "Ethernet module", "Module used for the connection to the real net.", eth_module_list, 0, 0); ethmod->set_by_name("null"); ethmod->set_ask_format("Choose ethernet module for the device [%s] "); new bx_param_string_c(menu, "ethdev", "Ethernet device", "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.", "xl0", BX_PATHNAME_LEN); path = new bx_param_filename_c(menu, "script", "Device configuration script", "Name of the script that is executed after Bochs initializes the network interface (optional).", "none", BX_PATHNAME_LEN); path->set_ask_format("Enter new script name, or 'none': [%s] "); bootrom = new bx_param_filename_c(menu, "bootrom", "Boot ROM image", "Pathname of network boot ROM image to load", "", BX_PATHNAME_LEN); bootrom->set_format("Name of boot ROM image: %s"); } void bx_init_usb_options(const char *usb_name, const char *pname, int maxports) { char group[16], name[8], descr[512], label[512]; bx_param_c *usb = SIM->get_param("ports.usb"); sprintf(group, "USB %s", usb_name); sprintf(label, "%s Configuration", usb_name); bx_list_c *menu = new bx_list_c(usb, pname, label); menu->set_options(menu->SHOW_PARENT); sprintf(label, "Enable %s emulation", usb_name); sprintf(descr, "Enables the %s emulation", usb_name); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", label, descr, 0); bx_list_c *deplist = new bx_list_c(NULL); for (int i = 0; i < maxports; i++) { sprintf(name, "port%d", i+1); sprintf(label, "Port #%d Configuration", i+1); sprintf(descr, "Device connected to %s port #%d and it's options", usb_name, i+1); bx_list_c *port = new bx_list_c(menu, name, label); port->set_options(port->SERIES_ASK | port->USE_BOX_TITLE); sprintf(descr, "Device connected to %s port #%d", usb_name, i+1); bx_param_string_c *device = new bx_param_string_c(port, "device", "Device", descr, "", BX_PATHNAME_LEN); sprintf(descr, "Options for device connected to %s port #%d", usb_name, i+1); bx_param_string_c *options = new bx_param_string_c(port, "options", "Options", descr, "", BX_PATHNAME_LEN); port->set_group(group); deplist->add(port); deplist->add(device); deplist->add(options); } enabled->set_dependent_list(deplist); } void bx_plugin_ctrl_reset(bx_bool init_done) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL); if (init_done) { for (int i = 0; i < base->get_size(); i++) { ((bx_param_bool_c*)base->get(i))->set(0); } SIM->opt_plugin_ctrl("*", 0); } // add the default set of plugins to the list new bx_param_bool_c(base, "unmapped", "", "", 1); new bx_param_bool_c(base, "biosdev", "", "", 1); new bx_param_bool_c(base, "speaker", "", "", 1); new bx_param_bool_c(base, "extfpuirq", "", "", 1); new bx_param_bool_c(base, "parallel", "", "", 1); new bx_param_bool_c(base, "serial", "", "", 1); #if BX_SUPPORT_GAMEPORT new bx_param_bool_c(base, "gameport", "", "", 1); #endif #if BX_SUPPORT_IODEBUG && BX_DEBUGGER new bx_param_bool_c(base, "iodebug", "", "", 1); #endif if (init_done) { SIM->opt_plugin_ctrl("*", 1); } } void bx_init_options() { int i; bx_list_c *menu; bx_list_c *deplist; bx_param_num_c *ioaddr, *ioaddr2, *irq; bx_param_bool_c *enabled, *readonly, *status; bx_param_enum_c *mode, *type, *toggle; bx_param_filename_c *path; char name[BX_PATHNAME_LEN], descr[512], label[512]; bx_param_c *root_param = SIM->get_param("."); // general options subtree menu = new bx_list_c(root_param, "general", ""); // config interface option, set in bochsrc or command line static const char *config_interface_list[] = { #ifdef WIN32 "win32config", #endif #if BX_USE_TEXTCONFIG "textconfig", #endif #if BX_WITH_WX "wx", #endif NULL }; bx_param_enum_c *sel_config = new bx_param_enum_c(menu, "config_interface", "Configuration interface", "Select configuration interface", config_interface_list, 0, 0); sel_config->set_by_name(BX_DEFAULT_CONFIG_INTERFACE); static const char *bochs_start_names[] = { "quick", "load", "edit", "run" }; // quick start option, set by command line arg new bx_param_enum_c(menu, "start_mode", "Bochs start types", "Bochs start types", bochs_start_names, BX_RUN_START, BX_QUICK_START); new bx_param_bool_c(menu, "restore", "Restore Bochs session", "Restore Bochs session", 0); new bx_param_string_c(menu, "restore_path", "Path to data for restore", "Path to data for restore", "", BX_PATHNAME_LEN); // benchmarking mode, set by command line arg new bx_param_num_c(menu, "benchmark", "benchmark mode", "set benchmark mode", 0, BX_MAX_BIT32U, 0); // subtree for setting up log actions by device in bochsrc bx_list_c *logfn = new bx_list_c(menu, "logfn", "Logfunctions"); new bx_list_c(logfn, "debug", ""); new bx_list_c(logfn, "info", ""); new bx_list_c(logfn, "error", ""); new bx_list_c(logfn, "panic", ""); // optional plugin control new bx_list_c(menu, "plugin_ctrl", "Optional Plugin Control"); bx_plugin_ctrl_reset(0); // subtree for special menus bx_list_c *special_menus = new bx_list_c(root_param, "menu", ""); #if BX_SUPPORT_SMP #define BX_CPU_PROCESSORS_LIMIT 255 #define BX_CPU_CORES_LIMIT 8 #define BX_CPU_HT_THREADS_LIMIT 4 #else #define BX_CPU_PROCESSORS_LIMIT 1 #define BX_CPU_CORES_LIMIT 1 #define BX_CPU_HT_THREADS_LIMIT 1 #endif // cpu subtree bx_list_c *cpu_param = new bx_list_c(root_param, "cpu", "CPU Options"); static const char *cpu_names[] = { #define bx_define_cpudb(model) #model, #include "cpudb.h" NULL }; #undef bx_define_cpudb new bx_param_enum_c(cpu_param, "model", "CPU configuration", "Choose pre-defined CPU configuration", cpu_names, 0, 0); // cpu options bx_param_num_c *nprocessors = new bx_param_num_c(cpu_param, "n_processors", "Number of processors in SMP mode", "Sets the number of processors for multiprocessor emulation", 1, BX_CPU_PROCESSORS_LIMIT, 1); nprocessors->set_enabled(BX_CPU_PROCESSORS_LIMIT > 1); bx_param_num_c *ncores = new bx_param_num_c(cpu_param, "n_cores", "Number of cores in each processor in SMP mode", "Sets the number of cores per processor for multiprocessor emulation", 1, BX_CPU_CORES_LIMIT, 1); ncores->set_enabled(BX_CPU_CORES_LIMIT > 1); bx_param_num_c *nthreads = new bx_param_num_c(cpu_param, "n_threads", "Number of HT threads per each core in SMP mode", "Sets the number of HT (Intel(R) HyperThreading Technology) threads per core for multiprocessor emulation", 1, BX_CPU_HT_THREADS_LIMIT, 1); nthreads->set_enabled(BX_CPU_HT_THREADS_LIMIT > 1); new bx_param_num_c(cpu_param, "ips", "Emulated instructions per second (IPS)", "Emulated instructions per second, used to calibrate bochs emulated time with wall clock time.", BX_MIN_IPS, BX_MAX_BIT32U, 4000000); #if BX_SUPPORT_SMP new bx_param_num_c(cpu_param, "quantum", "Quantum ticks in SMP simulation", "Maximum amount of instructions allowed to execute before returning control to another CPU.", BX_SMP_QUANTUM_MIN, BX_SMP_QUANTUM_MAX, 16); #endif new bx_param_bool_c(cpu_param, "reset_on_triple_fault", "Enable CPU reset on triple fault", "Enable CPU reset if triple fault occured (highly recommended)", 1); #if BX_CPU_LEVEL >= 5 new bx_param_bool_c(cpu_param, "ignore_bad_msrs", "Ignore RDMSR / WRMSR to unknown MSR register", "Ignore RDMSR/WRMSR to unknown MSR register", 1); #endif new bx_param_bool_c(cpu_param, "cpuid_limit_winnt", "Limit max CPUID function to 3", "Limit max CPUID function reported to 3 to workaround WinNT issue", 0); #if BX_SUPPORT_MONITOR_MWAIT new bx_param_bool_c(cpu_param, "mwait_is_nop", "Don't put CPU to sleep state by MWAIT", "Don't put CPU to sleep state by MWAIT", 0); #endif #if BX_CONFIGURE_MSRS new bx_param_filename_c(cpu_param, "msrs", "Configurable MSR definition file", "Set path to the configurable MSR definition file", "", BX_PATHNAME_LEN); #endif cpu_param->set_options(menu->SHOW_PARENT); // cpuid subtree #if BX_CPU_LEVEL >= 4 bx_list_c *cpuid_param = new bx_list_c(root_param, "cpuid", "CPUID Options"); new bx_param_string_c(cpuid_param, "vendor_string", "CPUID vendor string", "Set the CPUID vendor string", #if BX_CPU_VENDOR_INTEL "GenuineIntel", #else "AuthenticAMD", #endif BX_CPUID_VENDOR_LEN+1); new bx_param_string_c(cpuid_param, "brand_string", "CPUID brand string", "Set the CPUID brand string", #if BX_CPU_VENDOR_INTEL " Intel(R) Pentium(R) 4 CPU ", #else "AMD Athlon(tm) processor", #endif BX_CPUID_BRAND_LEN+1); new bx_param_num_c(cpuid_param, "stepping", "Stepping ID", "Processor 4-bits stepping ID", 0, 15, 3); new bx_param_num_c(cpuid_param, "model", "Model ID", "Processor model ID, extended model ID", 0, 255, 3); new bx_param_num_c(cpuid_param, "family", "Family ID", "Processor family ID, extended family ID", BX_CPU_LEVEL, (BX_CPU_LEVEL >= 6) ? 4095 : BX_CPU_LEVEL, BX_CPU_LEVEL); #if BX_CPU_LEVEL >= 5 new bx_param_bool_c(cpuid_param, "mmx", "Support for MMX instruction set", "Support for MMX instruction set", 1); // configure defaults to XAPIC enabled static const char *apic_names[] = { "legacy", "xapic", #if BX_CPU_LEVEL >= 6 "xapic_ext", "x2apic", #endif NULL }; new bx_param_enum_c(cpuid_param, "apic", "APIC configuration", "Select APIC configuration (Legacy APIC/XAPIC/XAPIC_EXT/X2APIC)", apic_names, BX_CPUID_SUPPORT_XAPIC, BX_CPUID_SUPPORT_LEGACY_APIC); #endif #if BX_CPU_LEVEL >= 6 // configure defaults to CPU_LEVEL = 6 with SSE2 enabled static const char *sse_names[] = { "none", "sse", "sse2", "sse3", "ssse3", "sse4_1", "sse4_2", NULL }; new bx_param_enum_c(cpuid_param, "sse", "Support for SSE instruction set", "Support for SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 instruction set", sse_names, BX_CPUID_SUPPORT_SSE2, BX_CPUID_SUPPORT_NOSSE); new bx_param_bool_c(cpuid_param, "sse4a", "Support for AMD SSE4A instructions", "Support for AMD SSE4A instructions", 0); new bx_param_bool_c(cpuid_param, "sep", "Support for SYSENTER/SYSEXIT instructions", "Support for SYSENTER/SYSEXIT instructions", 1); new bx_param_bool_c(cpuid_param, "movbe", "Support for MOVBE instruction", "Support for MOVBE instruction", 0); new bx_param_bool_c(cpuid_param, "adx", "Support for ADX instructions", "Support for ADCX/ADOX instructions", 0); new bx_param_bool_c(cpuid_param, "aes", "Support for AES instruction set", "Support for AES instruction set", 0); new bx_param_bool_c(cpuid_param, "xsave", "Support for XSAVE extensions", "Support for XSAVE extensions", 0); new bx_param_bool_c(cpuid_param, "xsaveopt", "Support for XSAVEOPT instruction", "Support for XSAVEOPT instruction", 0); #if BX_SUPPORT_AVX new bx_param_num_c(cpuid_param, "avx", "Support for AVX instruction set", "Support for AVX instruction set", 0, 2, 0); new bx_param_bool_c(cpuid_param, "avx_f16c", "Support for AVX F16 convert instructions", "Support for AVX F16 convert instructions", 0); new bx_param_bool_c(cpuid_param, "avx_fma", "Support for AVX FMA instructions", "Support for AVX FMA instructions", 0); new bx_param_num_c(cpuid_param, "bmi", "Support for BMI instructions", "Support for Bit Manipulation Instructions (BMI)", 0, 2, 0); new bx_param_bool_c(cpuid_param, "xop", "Support for AMD XOP instructions", "Support for AMD XOP instructions", 0); new bx_param_bool_c(cpuid_param, "fma4", "Support for AMD four operand FMA instructions", "Support for AMD FMA4 instructions", 0); new bx_param_bool_c(cpuid_param, "tbm", "Support for AMD TBM instructions", "Support for AMD Trailing Bit Manipulation (TBM) instructions", 0); #endif #if BX_SUPPORT_X86_64 new bx_param_bool_c(cpuid_param, "x86_64", "x86-64 and long mode", "Support for x86-64 and long mode", 1); new bx_param_bool_c(cpuid_param, "1g_pages", "1G pages support in long mode", "Support for 1G pages in long mode", 0); new bx_param_bool_c(cpuid_param, "pcid", "PCID support in long mode", "Support for process context ID (PCID) in long mode", 0); new bx_param_bool_c(cpuid_param, "fsgsbase", "FS/GS BASE access instructions support", "FS/GS BASE access instructions support in long mode", 0); #endif new bx_param_bool_c(cpuid_param, "smep", "Supervisor Mode Execution Protection support", "Supervisor Mode Execution Protection support", 0); #if BX_SUPPORT_MONITOR_MWAIT new bx_param_bool_c(cpuid_param, "mwait", "MONITOR/MWAIT instructions support", "MONITOR/MWAIT instructions support", BX_SUPPORT_MONITOR_MWAIT); #endif #if BX_SUPPORT_VMX new bx_param_num_c(cpuid_param, "vmx", "Support for Intel VMX extensions emulation", "Support for Intel VMX extensions emulation", 0, BX_SUPPORT_VMX, 1); #endif #if BX_SUPPORT_SVM new bx_param_bool_c(cpuid_param, "svm", "Secure Virtual Machine (SVM) emulation support", "Secure Virtual Machine (SVM) emulation support", 0); #endif #endif // CPU_LEVEL >= 6 cpuid_param->set_options(menu->SHOW_PARENT); // CPUID subtree depends on CPU model SIM->get_param_enum(BXPN_CPU_MODEL)->set_dependent_list(cpuid_param->clone(), 0); // enable CPUID subtree only for CPU model choice #0 SIM->get_param_enum(BXPN_CPU_MODEL)->set_dependent_bitmap(0, BX_MAX_BIT64U); #endif // CPU_LEVEL >= 4 // memory subtree bx_list_c *memory = new bx_list_c(root_param, "memory", "Memory Options"); bx_list_c *stdmem = new bx_list_c(memory, "standard", "Standard Options"); bx_list_c *optrom = new bx_list_c(memory, "optrom", "Optional ROM Images"); bx_list_c *optram = new bx_list_c(memory, "optram", "Optional RAM Images"); bx_list_c *ram = new bx_list_c(stdmem, "ram", "RAM size options"); bx_list_c *rom = new bx_list_c(stdmem, "rom", "BIOS ROM options"); bx_list_c *vgarom = new bx_list_c(stdmem, "vgarom", "VGABIOS ROM options"); // memory options (ram & rom) bx_param_num_c *ramsize = new bx_param_num_c(ram, "size", "Memory size (megabytes)", "Amount of RAM in megabytes", 1, ((Bit64u)(1) << BX_PHY_ADDRESS_WIDTH) / (1024*1024), BX_DEFAULT_MEM_MEGS); ramsize->set_ask_format("Enter memory size (MB): [%d] "); ramsize->set_options(ramsize->USE_SPIN_CONTROL); bx_param_num_c *host_ramsize = new bx_param_num_c(ram, "host_size", "Host allocated memory size (megabytes)", "Amount of host allocated memory in megabytes", 1, 2048, BX_DEFAULT_MEM_MEGS); host_ramsize->set_ask_format("Enter host memory size (MB): [%d] "); host_ramsize->set_options(ramsize->USE_SPIN_CONTROL); ram->set_options(ram->SERIES_ASK); path = new bx_param_filename_c(rom, "path", "ROM BIOS image", "Pathname of ROM image to load", "", BX_PATHNAME_LEN); path->set_format("Name of ROM BIOS image: %s"); sprintf(name, "%s/BIOS-bochs-latest", (char *)get_builtin_variable("BXSHARE")); path->set_initial_val(name); bx_param_num_c *romaddr = new bx_param_num_c(rom, "addr", "ROM BIOS address", "The address at which the ROM image should be loaded", 0, BX_MAX_BIT32U, 0); romaddr->set_base(16); romaddr->set_format("0x%05x"); romaddr->set_long_format("ROM BIOS address: 0x%05x"); rom->set_options(rom->SERIES_ASK); path = new bx_param_filename_c(vgarom, "path", "VGA BIOS image", "Pathname of VGA ROM image to load", "", BX_PATHNAME_LEN); path->set_format("Name of VGA BIOS image: %s"); sprintf(name, "%s/VGABIOS-lgpl-latest", get_builtin_variable("BXSHARE")); path->set_initial_val(name); vgarom->set_options(vgarom->SERIES_ASK); bx_param_num_c *optaddr; for (i=0; iset_format(strdup(label)); sprintf(descr, "The address at which the optional ROM image #%d should be loaded", i+1); optaddr = new bx_param_num_c(optnum1, "addr", "Address", descr, 0, BX_MAX_BIT32U, 0); optaddr->set_base(16); optaddr->set_format("0x%05x"); sprintf(label, "Optional ROM #%d address:", i+1); strcat(label, " 0x%05x"); optaddr->set_long_format(strdup(label)); optnum1->set_options(optnum1->SERIES_ASK | optnum1->USE_BOX_TITLE); } optrom->set_options(optrom->SHOW_PARENT); for (i=0; iset_format(strdup(label)); sprintf(descr, "The address at which the optional RAM image #%d should be loaded", i+1); optaddr = new bx_param_num_c(optnum2, "addr", "Address", descr, 0, BX_MAX_BIT32U, 0); optaddr->set_base(16); optaddr->set_format("0x%05x"); sprintf(label, "Optional RAM #%d address:", i+1); strcat(label, " 0x%05x"); optaddr->set_long_format(strdup(label)); optnum2->set_options(optnum2->SERIES_ASK | optnum2->USE_BOX_TITLE); } optram->set_options(optram->SHOW_PARENT); memory->set_options(memory->SHOW_PARENT | memory->USE_TAB_WINDOW); // clock & cmos subtree bx_list_c *clock_cmos = new bx_list_c(root_param, "clock_cmos", "Clock & CMOS Options"); // clock & cmos options static const char *clock_sync_names[] = { "none", "realtime", "slowdown", "both", NULL }; bx_param_enum_c *clock_sync = new bx_param_enum_c(clock_cmos, "clock_sync", "Synchronisation method", "Host to guest time synchronization method", clock_sync_names, BX_CLOCK_SYNC_NONE, BX_CLOCK_SYNC_NONE); bx_param_num_c *time0 = new bx_param_num_c(clock_cmos, "time0", "Initial CMOS time for Bochs\n(1:localtime, 2:utc, other:time in seconds)", "Initial time for Bochs CMOS clock, used if you really want two runs to be identical", 0, BX_MAX_BIT32U, BX_CLOCK_TIME0_LOCAL); bx_param_bool_c *rtc_sync = new bx_param_bool_c(clock_cmos, "rtc_sync", "Sync RTC speed with realtime", "If enabled, the RTC runs at realtime speed", 0); deplist = new bx_list_c(NULL); deplist->add(rtc_sync); clock_sync->set_dependent_list(deplist, 0); clock_sync->set_dependent_bitmap(BX_CLOCK_SYNC_REALTIME, 1); clock_sync->set_dependent_bitmap(BX_CLOCK_SYNC_BOTH, 1); bx_list_c *cmosimage = new bx_list_c(clock_cmos, "cmosimage", "CMOS Image Options"); bx_param_bool_c *use_cmosimage = new bx_param_bool_c(cmosimage, "enabled", "Use a CMOS image", "Controls the usage of a CMOS image", 0); path = new bx_param_filename_c(cmosimage, "path", "Pathname of CMOS image", "Pathname of CMOS image", "", BX_PATHNAME_LEN); bx_param_bool_c *rtc_init = new bx_param_bool_c(cmosimage, "rtc_init", "Initialize RTC from image", "Controls whether to initialize the RTC with values stored in the image", 0); deplist = new bx_list_c(NULL); deplist->add(path); deplist->add(rtc_init); use_cmosimage->set_dependent_list(deplist); time0->set_ask_format("Enter Initial CMOS time (1:localtime, 2:utc, other:time in seconds): [%d] "); clock_sync->set_ask_format("Enter Synchronisation method: [%s] "); clock_cmos->set_options(clock_cmos->SHOW_PARENT); cmosimage->set_options(cmosimage->SHOW_PARENT); // pci subtree bx_list_c *pci = new bx_list_c(root_param, "pci", "PCI Options"); // pci options deplist = new bx_list_c(NULL); bx_param_bool_c *i440fx_support = new bx_param_bool_c(pci, "i440fx_support", "Enable i440FX PCI Support", "Controls whether to emulate the i440FX PCI chipset", BX_SUPPORT_PCI); // pci slots bx_list_c *slot = new bx_list_c(pci, "slot", "PCI Slots"); deplist->add(slot); for (i=0; iadd(devname); } i440fx_support->set_dependent_list(deplist); pci->set_options(pci->SHOW_PARENT); slot->set_options(slot->SHOW_PARENT); // display subtree bx_list_c *display = new bx_list_c(root_param, "display", "Bochs Display & Interface Options"); // this is a list of gui libraries that are known to be available at // compile time. The one that is listed first will be the default, // which is used unless the user overrides it on the command line or // in a configuration file. static const char *display_library_list[] = { #if BX_WITH_X11 "x", #endif #if BX_WITH_WIN32 "win32", #endif #if BX_WITH_CARBON "carbon", #endif #if BX_WITH_MACOS "macos", #endif #if BX_WITH_AMIGAOS "amigaos", #endif #if BX_WITH_SDL "sdl", #endif #if BX_WITH_SVGA "svga", #endif #if BX_WITH_TERM "term", #endif #if BX_WITH_RFB "rfb", #endif #if BX_WITH_WX "wx", #endif #if BX_WITH_NOGUI "nogui", #endif NULL }; bx_param_enum_c *sel_displaylib = new bx_param_enum_c(display, "display_library", "VGA Display Library", "Select VGA Display Library", display_library_list, 0, 0); sel_displaylib->set_by_name(BX_DEFAULT_DISPLAY_LIBRARY); sel_displaylib->set_ask_format("Choose which library to use for the Bochs display: [%s] "); new bx_param_string_c(display, "displaylib_options", "Display Library options", "Options passed to Display Library", "", BX_PATHNAME_LEN); new bx_param_bool_c(display, "private_colormap", "Use a private colormap", "Request that the GUI create and use it's own non-shared colormap. This colormap will be used when in the bochs window. If not enabled, a shared colormap scheme may be used. Not implemented on all GUI's.", 0); bx_param_bool_c *fullscreen = new bx_param_bool_c(display, "fullscreen", "Use full screen mode", "When enabled, bochs occupies the whole screen instead of just a window.", 0); bx_param_string_c *screenmode = new bx_param_string_c(display, "screenmode", "Screen mode name", "Screen mode name", "", BX_PATHNAME_LEN); screenmode->set_handler(bx_param_string_handler); #if !BX_WITH_AMIGAOS fullscreen->set_enabled(0); screenmode->set_enabled(0); #endif bx_param_num_c *vga_update_freq = new bx_param_num_c(display, "vga_update_frequency", "VGA Update Frequency", "Number of VGA updates per emulated second", 1, 60, 5); vga_update_freq->set_ask_format ("Type a new value for VGA update frequency: [%d] "); bx_param_string_c *vga_extension = new bx_param_string_c(display, "vga_extension", "VGA Extension", "Name of the VGA extension", "none", BX_PATHNAME_LEN); vga_extension->set_initial_val("vbe"); display->set_options(display->SHOW_PARENT); // keyboard & mouse subtree bx_list_c *kbd_mouse = new bx_list_c(root_param, "keyboard_mouse", "Keyboard & Mouse Options"); bx_list_c *keyboard = new bx_list_c(kbd_mouse, "keyboard", "Keyboard Options"); bx_list_c *mouse = new bx_list_c(kbd_mouse, "mouse", "Mouse Options"); static const char *keyboard_type_names[] = { "xt", "at", "mf", NULL }; // keyboard & mouse options type = new bx_param_enum_c(keyboard, "type", "Keyboard type", "Keyboard type reported by the 'identify keyboard' command", keyboard_type_names, BX_KBD_MF_TYPE, BX_KBD_XT_TYPE); type->set_ask_format ("Enter keyboard type: [%s] "); new bx_param_num_c(keyboard, "serial_delay", "Keyboard serial delay", "Approximate time in microseconds that it takes one character to be transferred from the keyboard to controller over the serial path.", 1, BX_MAX_BIT32U, 250); new bx_param_num_c(keyboard, "paste_delay", "Keyboard paste delay", "Approximate time in microseconds between attemps to paste characters to the keyboard controller.", 1000, BX_MAX_BIT32U, 100000); bx_param_bool_c *use_kbd_mapping = new bx_param_bool_c(keyboard, "use_mapping", "Use keyboard mapping", "Controls whether to use the keyboard mapping feature", 0); bx_param_filename_c *keymap = new bx_param_filename_c(keyboard, "keymap", "Keymap filename", "Pathname of the keymap file used", "", BX_PATHNAME_LEN); keymap->set_extension("map"); deplist = new bx_list_c(NULL); deplist->add(keymap); use_kbd_mapping->set_dependent_list(deplist); bx_param_string_c *user_shortcut = new bx_param_string_c(keyboard, "user_shortcut", "Userbutton shortcut", "Defines the keyboard shortcut to be sent when you press the 'user' button in the headerbar.", "none", 20); user_shortcut->set_runtime_param(1); static const char *mouse_type_list[] = { "none", "ps2", "imps2", #if BX_SUPPORT_BUSMOUSE "bus", #endif "serial", "serial_wheel", "serial_msys", NULL }; type = new bx_param_enum_c(mouse, "type", "Mouse type", "The mouse type can be one of these: 'none', 'ps2', 'imps2', 'serial', 'serial_wheel'" #if BX_SUPPORT_BUSMOUSE ", 'bus'" #endif , mouse_type_list, BX_MOUSE_TYPE_PS2, BX_MOUSE_TYPE_NONE); type->set_ask_format("Choose the type of mouse [%s] "); new bx_param_bool_c(mouse, "enabled", "Enable mouse capture", "Controls whether the mouse sends events to the guest. The hardware emulation is always enabled.", 0); static const char *mouse_toggle_list[] = { "ctrl+mbutton", "ctrl+f10", "ctrl+alt", "f12", NULL }; toggle = new bx_param_enum_c(mouse, "toggle", "Mouse toggle method", "The mouse toggle method can be one of these: 'ctrl+mbutton', 'ctrl+f10', 'ctrl+alt'", mouse_toggle_list, BX_MOUSE_TOGGLE_CTRL_MB, BX_MOUSE_TOGGLE_CTRL_MB); toggle->set_ask_format("Choose the mouse toggle method [%s] "); kbd_mouse->set_options(kbd_mouse->SHOW_PARENT); keyboard->set_options(keyboard->SHOW_PARENT); mouse->set_options(mouse->SHOW_PARENT); // boot parameter subtree bx_list_c *boot_params = new bx_list_c(root_param, "boot_params", "Boot Options"); // boot sequence for (i=0; i<3; i++) { sprintf(name, "boot_drive%d", i+1); sprintf(label, "Boot drive #%d", i+1); sprintf(descr, "Name of drive #%d in boot sequence (A, C or CD)", i+1); bx_param_enum_c *bootdrive = new bx_param_enum_c(boot_params, name, label, descr, &bochs_bootdisk_names[(i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE], (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE, (i==0)?BX_BOOT_FLOPPYA:BX_BOOT_NONE); bootdrive->set_ask_format("Boot from floppy drive, hard drive or cdrom ? [%s] "); } new bx_param_bool_c(boot_params, "floppy_sig_check", "Skip Floppy Boot Signature Check", "Skips check for the 0xaa55 signature on floppy boot device.", 0); // loader hack bx_list_c *load32bitos = new bx_list_c(boot_params, "load32bitos", "32-bit OS Loader Hack"); static const char *loader_os_names[] = { "none", "linux", "nullkernel", NULL }; bx_param_enum_c *whichOS = new bx_param_enum_c(load32bitos, "which", "Which operating system?", "Which OS to boot", loader_os_names, Load32bitOSNone, Load32bitOSNone); path = new bx_param_filename_c(load32bitos, "path", "Pathname of OS to load", "Pathname of the 32-bit OS to load", "", BX_PATHNAME_LEN); bx_param_filename_c *iolog = new bx_param_filename_c(load32bitos, "iolog", "Pathname of I/O log file", "I/O logfile used for initializing the hardware", "", BX_PATHNAME_LEN); bx_param_filename_c *initrd = new bx_param_filename_c(load32bitos, "initrd", "Pathname of initrd", "Pathname of the initial ramdisk", "", BX_PATHNAME_LEN); whichOS->set_ask_format("Enter OS to load: [%s] "); path->set_ask_format("Enter pathname of OS: [%s]"); iolog->set_ask_format("Enter pathname of I/O log: [%s] "); initrd->set_ask_format("Enter pathname of initrd: [%s] "); load32bitos->set_options(menu->SERIES_ASK); whichOS->set_dependent_list(load32bitos->clone(), 1); whichOS->set_dependent_bitmap(Load32bitOSNone, 0); whichOS->set(Load32bitOSNone); boot_params->set_options(menu->SHOW_PARENT); // floppy subtree bx_list_c *floppy = new bx_list_c(root_param, "floppy", "Floppy Options"); new bx_list_c(floppy, "0", "First Floppy Drive"); new bx_list_c(floppy, "1", "Second Floppy Drive"); bx_param_enum_c *devtype; // floppy options for (i = 0; i < 2; i++) { bx_list_c *floppyX = (bx_list_c*)floppy->get(i); devtype = new bx_param_enum_c(floppyX, "devtype", "Type of floppy drive", "Type of floppy drive", floppy_devtype_names, BX_FDD_NONE, BX_FDD_NONE); devtype->set_ask_format("What type of floppy drive? [%s] "); if (i == 0) { strcpy(label, "First floppy image/device"); strcpy(descr, "Pathname of first floppy image file or device. If you're booting from floppy, this should be a bootable floppy."); } else { strcpy(label, "Second floppy image/device"); strcpy(descr, "Pathname of second floppy image file or device."); } path = new bx_param_filename_c(floppyX, "path", label, descr, "", BX_PATHNAME_LEN); path->set_ask_format("Enter new filename, or 'none' for no disk: [%s] "); path->set_extension("img"); path->set_initial_val("none"); type = new bx_param_enum_c(floppyX, "type", "Type of floppy media", "Type of floppy media", floppy_type_names, BX_FLOPPY_NONE, BX_FLOPPY_NONE); type->set_ask_format("What type of floppy media? (auto=detect) [%s] "); type->set_handler(bx_param_handler); type->set_runtime_param(1); readonly = new bx_param_bool_c(floppyX, "readonly", "Write Protection", "Floppy media write protection", 0); readonly->set_ask_format("Is media write protected? [%s] "); status = new bx_param_bool_c(floppyX, "status", "Inserted", "Floppy media status (inserted / ejected)", 0); status->set_ask_format("Is media inserted in drive? [%s] "); deplist = new bx_list_c(NULL); deplist->add(path); devtype->set_dependent_list(deplist, 1); devtype->set_dependent_bitmap(BX_FDD_NONE, 0); deplist = new bx_list_c(NULL); deplist->add(type); deplist->add(readonly); deplist->add(status); path->set_dependent_list(deplist); floppyX->set_options(floppyX->SERIES_ASK | floppyX->USE_BOX_TITLE); } floppy->set_options(floppy->SHOW_PARENT); // ATA/ATAPI subtree bx_list_c *ata = new bx_list_c(root_param, "ata", "ATA/ATAPI Options"); ata->set_options(ata->USE_TAB_WINDOW); // disk options const char *s_atachannel[] = { "ATA channel 0", "ATA channel 1", "ATA channel 2", "ATA channel 3", }; const char *s_atadevname[2] = { "master", "slave", }; const char *s_atadevice[4][2] = { { "First HD/CD on channel 0", "Second HD/CD on channel 0" }, { "First HD/CD on channel 1", "Second HD/CD on channel 1" }, { "First HD/CD on channel 2", "Second HD/CD on channel 2" }, { "First HD/CD on channel 3", "Second HD/CD on channel 3" } }; Bit16u ata_default_ioaddr1[4] = { 0x1f0, 0x170, 0x1e8, 0x168 }; Bit16u ata_default_ioaddr2[4] = { 0x3f0, 0x370, 0x3e0, 0x360 }; Bit8u ata_default_irq[4] = { 14, 15, 11, 9 }; #define BXP_PARAMS_PER_ATA_DEVICE 12 bx_list_c *ata_menu[BX_MAX_ATA_CHANNEL]; bx_list_c *ata_res[BX_MAX_ATA_CHANNEL]; for (Bit8u channel=0; channelset_options(bx_list_c::USE_TAB_WINDOW); ata_res[channel] = new bx_list_c(ata_menu[channel], "resources", s_atachannel[channel]); ata_res[channel]->set_options(bx_list_c::SERIES_ASK); enabled = new bx_param_bool_c(ata_res[channel], "enabled", "Enable ATA channel", "Controls whether ata channel is installed or not", 0); enabled->set_ask_format("Channel is enabled: [%s] "); ioaddr = new bx_param_num_c(ata_res[channel], "ioaddr1", "I/O Address 1", "IO adress of ata command block", 0, 0xffff, ata_default_ioaddr1[channel]); ioaddr->set_base(16); ioaddr->set_ask_format("Enter new ioaddr1: [0x%x] "); ioaddr2 = new bx_param_num_c(ata_res[channel], "ioaddr2", "I/O Address 2", "IO adress of ata control block", 0, 0xffff, ata_default_ioaddr2[channel]); ioaddr2->set_base(16); ioaddr2->set_ask_format("Enter new ioaddr2: [0x%x] "); irq = new bx_param_num_c(ata_res[channel], "irq", "IRQ", "IRQ used by this ata channel", 0, 15, ata_default_irq[channel]); irq->set_ask_format("Enter new IRQ: [%d] "); irq->set_options(irq->USE_SPIN_CONTROL); // all items in the ata[channel] menu depend on the enabled flag. // The menu list is complete, but a few dependent_list items will // be added later. Use clone() to make a copy of the dependent_list // so that it can be changed without affecting the menu. enabled->set_dependent_list(ata_res[channel]->clone()); for (Bit8u slave=0; slave<2; slave++) { menu = new bx_list_c(ata_menu[channel], s_atadevname[slave], s_atadevice[channel][slave]); menu->set_options(menu->SERIES_ASK); bx_param_bool_c *present = new bx_param_bool_c(menu, "present", "Enable this device", "Controls whether ata device is installed or not", 0); present->set_ask_format("Device is enabled: [%s] "); static const char *atadevice_type_names[] = { "disk", "cdrom", NULL }; type = new bx_param_enum_c(menu, "type", "Type of ATA device", "Type of ATA device (disk or cdrom)", atadevice_type_names, BX_ATA_DEVICE_DISK, BX_ATA_DEVICE_DISK); type->set_ask_format("Enter type of ATA device, disk or cdrom: [%s] "); path = new bx_param_filename_c(menu, "path", "Path or physical device name", "Pathname of the image or physical device (cdrom only)", "", BX_PATHNAME_LEN); path->set_ask_format("Enter new filename: [%s] "); path->set_extension("img"); mode = new bx_param_enum_c(menu, "mode", "Type of disk image", "Mode of the ATA harddisk", hdimage_mode_names, BX_HDIMAGE_MODE_FLAT, BX_HDIMAGE_MODE_FLAT); mode->set_ask_format("Enter mode of ATA device, (flat, concat, etc.): [%s] "); status = new bx_param_bool_c(menu, "status", "Inserted", "CD-ROM media status (inserted / ejected)", 0); status->set_ask_format("Is media inserted in drive? [%s] "); bx_param_filename_c *journal = new bx_param_filename_c(menu, "journal", "Path of journal file", "Pathname of the journal file", "", BX_PATHNAME_LEN); journal->set_ask_format("Enter path of journal file: [%s]"); deplist = new bx_list_c(NULL); deplist->add(journal); mode->set_dependent_list(deplist, 0); mode->set_dependent_bitmap(BX_HDIMAGE_MODE_UNDOABLE, 1); mode->set_dependent_bitmap(BX_HDIMAGE_MODE_VOLATILE, 1); mode->set_dependent_bitmap(BX_HDIMAGE_MODE_VVFAT, 1); bx_param_num_c *cylinders = new bx_param_num_c(menu, "cylinders", "Cylinders", "Number of cylinders", 0, 262143, 0); cylinders->set_ask_format("Enter number of cylinders: [%d] "); bx_param_num_c *heads = new bx_param_num_c(menu, "heads", "Heads", "Number of heads", 0, 16, 0); heads->set_ask_format("Enter number of heads: [%d] "); bx_param_num_c *spt = new bx_param_num_c(menu, "spt", "Sectors per track", "Number of sectors per track", 0, 63, 0); spt->set_ask_format("Enter number of sectors per track: [%d] "); bx_param_string_c *model = new bx_param_string_c(menu, "model", "Model name", "String returned by the 'identify device' command", "Generic 1234", 41); model->set_ask_format("Enter new model name: [%s]"); static const char *atadevice_biosdetect_names[] = { "none", "auto", "cmos", NULL }; bx_param_enum_c *biosdetect = new bx_param_enum_c(menu, "biosdetect", "BIOS Detection", "Type of bios detection", atadevice_biosdetect_names, BX_ATA_BIOSDETECT_AUTO, BX_ATA_BIOSDETECT_NONE); biosdetect->set_ask_format("Enter bios detection type: [%s]"); static const char *atadevice_translation_names[] = { "none", "lba", "large", "rechs", "auto", NULL }; bx_param_enum_c *translation = new bx_param_enum_c(menu, "translation", "Translation type", "How the ata-disk translation is done by the bios", atadevice_translation_names, BX_ATA_TRANSLATION_AUTO, BX_ATA_TRANSLATION_NONE); translation->set_ask_format("Enter translation type: [%s]"); // the menu and all items on it depend on the present flag deplist = new bx_list_c(NULL); deplist->add(type); deplist->add(path); deplist->add(model); deplist->add(biosdetect); present->set_dependent_list(deplist); // the master/slave menu depends on the ATA channel's enabled flag enabled->get_dependent_list()->add(menu); // the present flag depends on the ATA channel's enabled flag enabled->get_dependent_list()->add(present); // some items depend on the drive type bx_param_c *type_deplist[] = { mode, status, cylinders, heads, spt, translation, NULL }; deplist = new bx_list_c(NULL, "deplist", "", type_deplist); type->set_dependent_list(deplist, 0); type->set_dependent_bitmap(BX_ATA_DEVICE_DISK, 0x3d); type->set_dependent_bitmap(BX_ATA_DEVICE_CDROM, 0x02); type->set_handler(bx_param_handler); } // Enable two ATA interfaces by default, disable the others. // Now that the dependence relationships are established, call set() on // the ata device present params to set all enables correctly. enabled->set_initial_val(channel<2); enabled->set(channel<2); } // disk menu bx_param_c *disk_menu_init_list[] = { SIM->get_param(BXPN_FLOPPYA), SIM->get_param(BXPN_FLOPPYB), SIM->get_param(BXPN_ATA0_RES), SIM->get_param(BXPN_ATA0_MASTER), SIM->get_param(BXPN_ATA0_SLAVE), #if BX_MAX_ATA_CHANNEL>1 SIM->get_param(BXPN_ATA1_RES), SIM->get_param(BXPN_ATA1_MASTER), SIM->get_param(BXPN_ATA1_SLAVE), #endif #if BX_MAX_ATA_CHANNEL>2 SIM->get_param(BXPN_ATA2_RES), SIM->get_param(BXPN_ATA2_MASTER), SIM->get_param(BXPN_ATA2_SLAVE), #endif #if BX_MAX_ATA_CHANNEL>3 SIM->get_param(BXPN_ATA3_RES), SIM->get_param(BXPN_ATA3_MASTER), SIM->get_param(BXPN_ATA3_SLAVE), #endif SIM->get_param("boot_params"), NULL }; menu = new bx_list_c(special_menus, "disk", "Bochs Disk Options", disk_menu_init_list); menu->set_options(menu->SHOW_PARENT); // disk menu for win32paramdlg bx_param_c *disk_menu2_init_list[] = { SIM->get_param("floppy"), SIM->get_param("ata.0"), #if BX_MAX_ATA_CHANNEL>1 SIM->get_param("ata.1"), #endif #if BX_MAX_ATA_CHANNEL>2 SIM->get_param("ata.2"), #endif #if BX_MAX_ATA_CHANNEL>3 SIM->get_param("ata.3"), #endif SIM->get_param("boot_params"), NULL }; menu = new bx_list_c(special_menus, "disk_win32", "Bochs Disk Options", disk_menu2_init_list); menu->set_options(menu->USE_TAB_WINDOW); // ports subtree bx_list_c *ports = new bx_list_c(root_param, "ports", "Serial and Parallel Port Options"); ports->set_options(ports->USE_TAB_WINDOW | ports->SHOW_PARENT); // parallel ports bx_list_c *parallel = new bx_list_c(ports, "parallel", "Parallel Port Options"); parallel->set_options(parallel->SHOW_PARENT); // parport options initialized in the devive plugin code // serial ports bx_list_c *serial = new bx_list_c(ports, "serial", "Serial Port Options"); serial->set_options(serial->SHOW_PARENT); // serial port options initialized in the devive plugin code // usb subtree bx_list_c *usb = new bx_list_c(ports, "usb", "USB Configuration"); usb->set_options(usb->USE_TAB_WINDOW | usb->SHOW_PARENT); // USB host controller options initialized in the devive plugin code // network subtree bx_list_c *network = new bx_list_c(root_param, "network", "Network Configuration"); network->set_options(network->USE_TAB_WINDOW | network->SHOW_PARENT); // network device options initialized in the devive plugin code // sound subtree bx_list_c *sound = new bx_list_c(root_param, "sound", "Sound Configuration"); sound->set_options(sound->USE_TAB_WINDOW | sound->SHOW_PARENT); // sound device options initialized in the devive plugin code // misc options subtree bx_list_c *misc = new bx_list_c(root_param, "misc", "Configure Everything Else"); misc->set_options(misc->SHOW_PARENT); // port e9 hack new bx_param_bool_c(misc, "port_e9_hack", "Enable port 0xE9 hack", "Debug messages written to i/o port 0xE9 will be displayed on console", 0); // GDB stub menu = new bx_list_c(misc, "gdbstub", "GDB Stub Options"); menu->set_options(menu->SHOW_PARENT | menu->USE_BOX_TITLE); menu->set_enabled(BX_GDBSTUB); enabled = new bx_param_bool_c(menu, "enabled", "Enable GDB stub", "", 0); enabled->set_enabled(BX_GDBSTUB); new bx_param_num_c(menu, "port", "Port", "TCP/IP port for GDB stub", 0, 65535, 1234); new bx_param_num_c(menu, "text_base", "Text base", "", 0, BX_MAX_BIT32U, 0); new bx_param_num_c(menu, "data_base", "Data base", "", 0, BX_MAX_BIT32U, 0); new bx_param_num_c(menu, "bss_base", "BSS base", "", 0, BX_MAX_BIT32U, 0); enabled->set_dependent_list(menu->clone()); #if BX_PLUGINS // user plugin options menu = new bx_list_c(misc, "user_plugin", "User Plugin Options"); menu->set_options(menu->SHOW_PARENT | menu->USE_BOX_TITLE); for (i=0; iset_handler(bx_param_string_handler); } // user-defined options subtree bx_list_c *user = new bx_list_c(root_param, "user", "User-defined options"); user->set_options(user->SHOW_PARENT); #endif // log options subtree menu = new bx_list_c(root_param, "log", "Logfile Options"); menu->set_options(menu->SHOW_PARENT); // log options path = new bx_param_filename_c(menu, "filename", "Log filename", "Pathname of bochs log file", "-", BX_PATHNAME_LEN); path->set_ask_format("Enter log filename: [%s] "); path->set_extension("txt"); bx_param_string_c *prefix = new bx_param_string_c(menu, "prefix", "Log output prefix", "Prefix prepended to log output", "%t%e%d", BX_PATHNAME_LEN); prefix->set_ask_format("Enter log prefix: [%s] "); path = new bx_param_filename_c(menu, "debugger_filename", "Debugger Log filename", "Pathname of debugger log file", "-", BX_PATHNAME_LEN); path->set_ask_format("Enter debugger log filename: [%s] "); path->set_extension("log"); path->set_enabled(BX_DEBUGGER); // runtime options menu = new bx_list_c(special_menus, "runtime", "Runtime options"); bx_list_c *cdrom = new bx_list_c(menu, "cdrom", "CD-ROM options"); cdrom->set_options(cdrom->SHOW_PARENT); usb = new bx_list_c(menu, "usb", "USB options"); usb->set_options(usb->SHOW_PARENT | usb->USE_TAB_WINDOW); // misc runtime options misc = new bx_list_c(menu, "misc", "Misc options"); misc->add(SIM->get_param(BXPN_VGA_UPDATE_FREQUENCY)); misc->add(SIM->get_param(BXPN_MOUSE_ENABLED)); misc->add(SIM->get_param(BXPN_KBD_PASTE_DELAY)); misc->add(SIM->get_param(BXPN_USER_SHORTCUT)); misc->set_options(misc->SHOW_PARENT | misc->SHOW_GROUP_NAME); } void bx_reset_options() { // optional plugin control bx_plugin_ctrl_reset(1); // cpu SIM->get_param("cpu")->reset(); #if BX_CPU_LEVEL >= 4 // cpuid SIM->get_param("cpuid")->reset(); #endif // memory (ram & rom) SIM->get_param("memory")->reset(); // clock & cmos SIM->get_param("clock_cmos")->reset(); // pci SIM->get_param("pci")->reset(); // display & interface SIM->get_param("display")->reset(); // keyboard & mouse SIM->get_param("keyboard_mouse")->reset(); // boot SIM->get_param("boot_params")->reset(); // floppy drives SIM->get_param("floppy")->reset(); // ata/atapi drives SIM->get_param("ata")->reset(); // serial/parallel/usb SIM->get_param("ports")->reset(); // network devices SIM->get_param("network")->reset(); // sound devices SIM->get_param("sound")->reset(); // misc SIM->get_param("misc")->reset(); // logfile SIM->get_param("log")->reset(); #if BX_PLUGINS // user-defined options SIM->get_param("user")->reset(); bx_user_plugin_count = 0; #endif } int bx_read_configuration(const char *rcfile) { // parse rcfile first, then parse arguments in order. BX_INFO (("reading configuration from %s", rcfile)); if (parse_bochsrc(rcfile) < 0) { BX_PANIC (("reading from %s failed", rcfile)); return -1; } // update log actions for (int level=0; levelget_default_log_action(level); io->set_log_action(level, action); } return 0; } int bx_parse_cmdline(int arg, int argc, char *argv[]) { //if (arg < argc) BX_INFO (("parsing command line arguments")); while (arg < argc) { BX_INFO (("parsing arg %d, %s", arg, argv[arg])); parse_line_unformatted("cmdline args", argv[arg]); arg++; } // update log actions for (int level=0; levelget_default_log_action(level); io->set_log_action(level, action); } return 0; } char *bx_find_bochsrc() { FILE *fd = NULL; char rcfile[512]; Bit32u retry = 0, found = 0; // try several possibilities for the bochsrc before giving up while (!found) { rcfile[0] = 0; switch (retry++) { case 0: strcpy (rcfile, ".bochsrc"); break; case 1: strcpy (rcfile, "bochsrc"); break; case 2: strcpy (rcfile, "bochsrc.txt"); break; #ifdef WIN32 case 3: strcpy (rcfile, "bochsrc.bxrc"); break; #elif !BX_WITH_MACOS // only try this on unix case 3: { char *ptr = getenv("HOME"); if (ptr) snprintf (rcfile, sizeof(rcfile), "%s/.bochsrc", ptr); } break; case 4: strcpy (rcfile, "/etc/bochsrc"); break; #endif default: return NULL; } if (rcfile[0]) { BX_DEBUG (("looking for configuration in %s", rcfile)); fd = fopen(rcfile, "r"); if (fd) found = 1; } } assert (fd != NULL && rcfile[0] != 0); fclose (fd); return strdup(rcfile); } static int parse_bochsrc(const char *rcfile) { FILE *fd = NULL; char *ret; char line[512]; char context[BX_PATHNAME_LEN]; Bit32u linenum = 1; // try several possibilities for the bochsrc before giving up bochsrc_include_count++; fd = fopen (rcfile, "r"); if (fd == NULL) return -1; int retval = 0; do { ret = fgets(line, sizeof(line)-1, fd); line[sizeof(line) - 1] = '\0'; size_t len = strlen(line); if ((len>0) && (line[len-1] < ' ')) line[len-1] = '\0'; if ((ret != NULL) && strlen(line)) { sprintf(context, "%s:%u", rcfile, linenum); if (parse_line_unformatted(context, line) < 0) { retval = -1; break; // quit parsing after first error } } linenum++; } while (!feof(fd)); fclose(fd); bochsrc_include_count--; return retval; } static const char *get_builtin_variable(const char *varname) { #ifdef WIN32 int code; DWORD size; DWORD type = 0; HKEY hkey; char keyname[80]; static char data[MAX_PATH]; #endif if (strlen(varname)<1) return NULL; else { if (!strcmp(varname, "BXSHARE")) { #ifdef WIN32 wsprintf(keyname, "Software\\Bochs %s", VER_STRING); code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &hkey); if (code == ERROR_SUCCESS) { data[0] = 0; size = MAX_PATH; if (RegQueryValueEx(hkey, "", NULL, (LPDWORD)&type, (LPBYTE)data, (LPDWORD)&size) == ERROR_SUCCESS) { RegCloseKey(hkey); return data; } else { RegCloseKey(hkey); return NULL; } } else { return NULL; } #else return BX_SHARE_PATH; #endif } return NULL; } } static int parse_line_unformatted(const char *context, char *line) { #define MAX_PARAMS_LEN 40 char *ptr; unsigned i, string_i = 0; char string[512]; char *params[MAX_PARAMS_LEN]; int num_params; bx_bool inquotes = 0; bx_bool comment = 0; memset(params, 0, sizeof(params)); if (line == NULL) return 0; // if passed nothing but whitespace, just return for (i=0; i=strlen(line)) return 0; num_params = 0; if (!strncmp(line, "#include", 8)) ptr = strtok(line, " "); else ptr = strtok(line, ":"); while ((ptr) && (!comment)) { if (!inquotes) { string_i = 0; } else { string[string_i++] = ','; } for (i=0; iset_default_log_action(level, action); } else { sprintf(pname, "general.logfn.%s", params[0]); base = (bx_list_c*) SIM->get_param(pname); mparam = (bx_param_num_c*) base->get_by_name(module); if (mparam != NULL) { mparam->set(action); } else { mparam = new bx_param_num_c(base, module, "", "", -1, BX_MAX_BIT32U, action); if (mparam == NULL) { PARSE_ERR(("%s: %s: failed to add log module.", context, params[0])); } } } } else { PARSE_ERR(("%s: %s directive malformed.", context, params[0])); free(param); return -1; } free(param); } return 0; } static int parse_debug_symbols(const char *context, const char **params, int num_params) { #if BX_DEBUGGER Bit32u offset = 0; const char *filename = 0; while (num_params > 0) { if (!strncmp(*params, "file=", 5)) { filename = *params + 5; } else if (!strncmp(*params, "offset=", 7)) { char* end; offset = strtoul(*params + 7, &end, 0); if (*end) PARSE_ERR(("%s: debug_symbols: invalid parameter %s", context, *params)); } else { PARSE_ERR(("%s: debug_symbols: invalid parameter %s", context, *params)); } params++; num_params--; } if (!filename) PARSE_ERR(("%s: debug_symbols: missing file name", context)); if (bx_dbg_symbol_command(filename, 1, offset) < 0) PARSE_ERR(("%s: debug_symbols: failed to load symbols from '%s'", context, filename)); #endif return 0; } static int parse_param_bool(const char *input, int len, const char *param) { if (input[len] == '0' || input[len] == '1') { SIM->get_param_bool(param)->set(input[len] - '0'); return 0; } return -1; } int bx_parse_usb_port_params(const char *context, bx_bool devopt, const char *param, int maxports, bx_list_c *base) { int idx, plen; char tmpname[20]; if (!devopt) { plen = 4; } else { plen = 7; } idx = param[plen]; if ((idx < '1') || (idx > '9') || (param[plen + 1] != '=')) { PARSE_ERR(("%s: usb_%s: portX / optionsX parameter malformed.", context, base->get_name())); return -1; } idx -= '0'; if (idx > maxports) { PARSE_ERR(("%s: usb_%s: port number out of range.", context, base->get_name())); return -1; } sprintf(tmpname, "port%d.%s", idx, devopt ? "options" : "device"); SIM->get_param_string(tmpname, base)->set(¶m[plen + 2]); return 0; } int bx_parse_nic_params(const char *context, const char *param, bx_list_c *base) { int tmp[6]; char tmpchar[6]; int valid = 0; int n; if (!strncmp(param, "enabled=", 8)) { if (atol(¶m[8]) == 0) valid |= 0x80; } else if (!strncmp(param, "mac=", 4)) { n = sscanf(¶m[4], "%x:%x:%x:%x:%x:%x", &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]); if (n != 6) { PARSE_ERR(("%s: '%s' mac address malformed.", context, base->get_name())); } for (n=0;n<6;n++) tmpchar[n] = (unsigned char)tmp[n]; SIM->get_param_string("macaddr", base)->set(tmpchar); valid |= 0x04; } else if (!strncmp(param, "ethmod=", 7)) { if (!SIM->get_param_enum("ethmod", base)->set_by_name(¶m[7])) PARSE_ERR(("%s: ethernet module '%s' not available", context, ¶m[7])); } else if (!strncmp(param, "ethdev=", 7)) { SIM->get_param_string("ethdev", base)->set(¶m[7]); } else if (!strncmp(param, "script=", 7)) { SIM->get_param_string("script", base)->set(¶m[7]); } else if (!strncmp(param, "bootrom=", 8)) { SIM->get_param_string("bootrom", base)->set(¶m[8]); } else { PARSE_WARN(("%s: unknown parameter '%s' for '%s' ignored.", context, param, base->get_name())); return -1; } return valid; } static int parse_line_formatted(const char *context, int num_params, char *params[]) { int i, slot, t; bx_list_c *base; if (num_params < 1) return 0; if (num_params < 2) { PARSE_ERR(("%s: a bochsrc option needs at least one parameter", context)); } #if BX_SUPPORT_PCIPNIC // Temporary HACK for the PCI Pseudo NIC's bochsrc option name change if (!strcmp(params[0], "pnic")) { strcpy(params[0], "pcipnic"); } #endif if (!strcmp(params[0], "#include")) { if (num_params != 2) { PARSE_ERR(("%s: ignoring malformed #include directive.", context)); } if (!strcmp(params[1], context)) { PARSE_ERR(("%s: cannot include this file again.", context)); } if (bochsrc_include_count == 2) { PARSE_ERR(("%s: include directive in an included file not supported yet.", context)); } bx_read_configuration(params[1]); } else if ((!strcmp(params[0], "floppya")) || (!strcmp(params[0], "floppyb"))) { if (!strcmp(params[0], "floppya")) { base = (bx_list_c*) SIM->get_param(BXPN_FLOPPYA); } else { base = (bx_list_c*) SIM->get_param(BXPN_FLOPPYB); } for (i=1; iget_param_enum("devtype", base)->set(BX_FDD_350ED); } else if (!strcmp(params[i]+5, "1_44")) { SIM->get_param_enum("devtype", base)->set(BX_FDD_350HD); } else if (!strcmp(params[i]+5, "1_2")) { SIM->get_param_enum("devtype", base)->set(BX_FDD_525HD); } else if (!strcmp(params[i]+5, "720k")) { SIM->get_param_enum("devtype", base)->set(BX_FDD_350DD); } else if (!strcmp(params[i]+5, "360k")) { SIM->get_param_enum("devtype", base)->set(BX_FDD_525DD); } else { PARSE_ERR(("%s: %s: unknown type '%s'.", context, params[0], params[i]+5)); } } else if (!strncmp(params[i], "2_88=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_2_88); } else if (!strncmp(params[i], "1_44=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_1_44); } else if (!strncmp(params[i], "1_2=", 4)) { SIM->get_param_string("path", base)->set(¶ms[i][4]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_1_2); } else if (!strncmp(params[i], "720k=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_720K); } else if (!strncmp(params[i], "360k=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_360K); } // use CMOS reserved types? else if (!strncmp(params[i], "160k=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_160K); } else if (!strncmp(params[i], "180k=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_180K); } else if (!strncmp(params[i], "320k=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); SIM->get_param_enum("type", base)->set(BX_FLOPPY_320K); } else if (!strncmp(params[i], "image=", 6)) { /* "image=" means we should get floppy type from image */ SIM->get_param_string("path", base)->set(¶ms[i][6]); t = get_floppy_type_from_image(¶ms[i][6]); if (t != BX_FLOPPY_UNKNOWN) SIM->get_param_enum("type", base)->set(t); else PARSE_ERR(("%s: %s image size doesn't match one of the supported types.", context, params[0])); } else if (!strcmp(params[i], "status=inserted")) { SIM->get_param_bool("status", base)->set(1); } else if (!strcmp(params[i], "status=ejected")) { SIM->get_param_bool("status", base)->set(0); } else if (!strncmp(params[i], "write_protected=", 16)) { SIM->get_param_bool("readonly", base)->set(atol(¶ms[i][16])); } else { PARSE_ERR(("%s: %s attribute '%s' not understood.", context, params[0], params[i])); } } } else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) == 4)) { char tmpname[80]; Bit8u channel = params[0][3]; if ((channel < '0') || (channel > '9')) { PARSE_ERR(("%s: ataX directive malformed.", context)); } channel-='0'; if (channel >= BX_MAX_ATA_CHANNEL) { PARSE_ERR(("%s: ataX directive malformed.", context)); } if ((num_params < 2) || (num_params > 5)) { PARSE_ERR(("%s: ataX directive malformed.", context)); } sprintf(tmpname, "ata.%d.resources", channel); base = (bx_list_c*) SIM->get_param(tmpname); if (strncmp(params[1], "enabled=", 8)) { PARSE_ERR(("%s: ataX directive malformed.", context)); } else { SIM->get_param_bool("enabled", base)->set(atol(¶ms[1][8])); } if (num_params > 2) { if (strncmp(params[2], "ioaddr1=", 8)) { PARSE_ERR(("%s: ataX directive malformed.", context)); } else { if ((params[2][8] == '0') && (params[2][9] == 'x')) SIM->get_param_num("ioaddr1", base)->set(strtoul(¶ms[2][8], NULL, 16)); else SIM->get_param_num("ioaddr1", base)->set(strtoul(¶ms[2][8], NULL, 10)); } } if (num_params > 3) { if (strncmp(params[3], "ioaddr2=", 8)) { PARSE_ERR(("%s: ataX directive malformed.", context)); } else { if ((params[3][8] == '0') && (params[3][9] == 'x')) SIM->get_param_num("ioaddr2", base)->set(strtoul(¶ms[3][8], NULL, 16)); else SIM->get_param_num("ioaddr2", base)->set(strtoul(¶ms[3][8], NULL, 10)); } } if (num_params > 4) { if (strncmp(params[4], "irq=", 4)) { PARSE_ERR(("%s: ataX directive malformed.", context)); } else { SIM->get_param_num("irq", base)->set(atol(¶ms[4][4])); } } } // ataX-master, ataX-slave else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) > 4)) { Bit8u channel = params[0][3]; int type = -1, mode = BX_HDIMAGE_MODE_FLAT, biosdetect = BX_ATA_BIOSDETECT_AUTO; Bit32u cylinders = 0, heads = 0, sectors = 0; char tmpname[80]; if ((channel < '0') || (channel > '9')) { PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); } channel-='0'; if (channel >= BX_MAX_ATA_CHANNEL) { PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); } if ((strcmp(¶ms[0][4], "-slave")) && (strcmp(¶ms[0][4], "-master"))) { PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); } sprintf(tmpname, "ata.%d.%s", channel, ¶ms[0][5]); base = (bx_list_c*) SIM->get_param(tmpname); for (i=1; ifind_by_name(¶ms[i][5]); if (type < 0) { PARSE_ERR(("%s: ataX-master/slave: unknown type '%s'", context, ¶ms[i][5])); } } else if (!strncmp(params[i], "mode=", 5)) { mode = SIM->get_param_enum("mode", base)->find_by_name(¶ms[i][5]); if (mode < 0) { PARSE_ERR(("%s: ataX-master/slave: unknown mode '%s'", context, ¶ms[i][5])); } } else if (!strncmp(params[i], "path=", 5)) { SIM->get_param_string("path", base)->set(¶ms[i][5]); } else if (!strncmp(params[i], "cylinders=", 10)) { cylinders = atol(¶ms[i][10]); } else if (!strncmp(params[i], "heads=", 6)) { heads = atol(¶ms[i][6]); } else if (!strncmp(params[i], "spt=", 4)) { sectors = atol(¶ms[i][4]); } else if (!strncmp(params[i], "model=", 6)) { SIM->get_param_string("model", base)->set(¶ms[i][6]); } else if (!strncmp(params[i], "biosdetect=", 11)) { biosdetect = SIM->get_param_enum("biosdetect", base)->find_by_name(¶ms[i][11]); if (biosdetect < 0) { PARSE_ERR(("%s: ataX-master/slave: unknown biosdetect '%s'", context, ¶ms[i][11])); } } else if (!strcmp(params[i], "translation=none")) { SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_NONE); } else if (!strcmp(params[i], "translation=lba")) { SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LBA); } else if (!strcmp(params[i], "translation=large")) { SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE); } else if (!strcmp(params[i], "translation=echs")) { // synonym of large SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_LARGE); } else if (!strcmp(params[i], "translation=rechs")) { SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_RECHS); } else if (!strcmp(params[i], "translation=auto")) { SIM->get_param_enum("translation", base)->set(BX_ATA_TRANSLATION_AUTO); } else if (!strcmp(params[i], "status=ejected")) { SIM->get_param_bool("status", base)->set(0); } else if (!strcmp(params[i], "status=inserted")) { SIM->get_param_bool("status", base)->set(1); } else if (!strncmp(params[i], "journal=", 8)) { SIM->get_param_string("journal", base)->set(¶ms[i][8]); } else { PARSE_ERR(("%s: ataX-master/slave directive malformed.", context)); } } // Enables the ata device if (type >= 0) { SIM->get_param_enum("type", base)->set(type); SIM->get_param_num("biosdetect", base)->set(biosdetect); if (type == BX_ATA_DEVICE_DISK) { if (strlen(SIM->get_param_string("path", base)->getptr()) > 0) { SIM->get_param_bool("present", base)->set(1); SIM->get_param_enum("mode", base)->set(mode); SIM->get_param_num("cylinders", base)->set(cylinders); if ((cylinders == 0) && (heads == 0) && (sectors == 0)) { PARSE_WARN(("%s: ataX-master/slave CHS set to 0/0/0 - autodetection enabled", context)); // using heads = 16 and spt = 63 for autodetection (bximage defaults) SIM->get_param_num("heads", base)->set(16); SIM->get_param_num("spt", base)->set(63); } else { SIM->get_param_num("heads", base)->set(heads); SIM->get_param_num("spt", base)->set(sectors); } } else { SIM->get_param_bool("present", base)->set(0); } } else if (type == BX_ATA_DEVICE_CDROM) { SIM->get_param_bool("present", base)->set(1); } } else { SIM->get_param_bool("present", base)->set(0); } } else if (!strcmp(params[0], "boot")) { char tmppath[80]; if (num_params < 2) { PARSE_ERR(("%s: boot directive malformed.", context)); } for (i=1; iget_param_enum(tmppath)->set(BX_BOOT_NONE); } else if (!strcmp(params[i], "a")) { SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA); } else if (!strcmp(params[i], "floppy")) { SIM->get_param_enum(tmppath)->set(BX_BOOT_FLOPPYA); } else if (!strcmp(params[i], "c")) { SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC); } else if (!strcmp(params[i], "disk")) { SIM->get_param_enum(tmppath)->set(BX_BOOT_DISKC); } else if (!strcmp(params[i], "cdrom")) { SIM->get_param_enum(tmppath)->set(BX_BOOT_CDROM); } else if (!strcmp(params[i], "network")) { SIM->get_param_enum(tmppath)->set(BX_BOOT_NETWORK); } else { PARSE_ERR(("%s: boot directive with unknown boot drive '%s'. use 'floppy', 'disk', 'cdrom' or 'network'.", context, params[i])); } } if (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == BX_BOOT_NONE) { PARSE_ERR(("%s: first boot drive must be one of 'floppy', 'disk' or 'cdrom'.", context)); } if ((SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE2)->get()) || (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()) || ((SIM->get_param_enum(BXPN_BOOTDRIVE3)->get() != BX_BOOT_NONE) && (SIM->get_param_enum(BXPN_BOOTDRIVE2)->get() == SIM->get_param_enum(BXPN_BOOTDRIVE3)->get()))) { PARSE_ERR(("%s: a boot drive appears twice in boot sequence.", context)); } } else if (!strcmp(params[0], "floppy_bootsig_check")) { if (num_params != 2) { PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context)); } if (strncmp(params[1], "disabled=", 9)) { PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context)); } if (parse_param_bool(params[1], 9, BXPN_FLOPPYSIGCHECK) < 0) { PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context)); } } else if (!strcmp(params[0], "log")) { if (num_params != 2) { PARSE_ERR(("%s: log directive has wrong # args.", context)); } SIM->get_param_string(BXPN_LOG_FILENAME)->set(params[1]); } else if (!strcmp(params[0], "logprefix")) { if (num_params != 2) { PARSE_ERR(("%s: logprefix directive has wrong # args.", context)); } SIM->get_param_string(BXPN_LOG_PREFIX)->set(params[1]); } else if (!strcmp(params[0], "debugger_log")) { if (num_params != 2) { PARSE_ERR(("%s: debugger_log directive has wrong # args.", context)); } SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME)->set(params[1]); } else if (!strcmp(params[0], "panic")) { if (num_params < 2) { PARSE_ERR(("%s: panic directive malformed.", context)); } if (parse_log_options(context, num_params, params) < 0) { return -1; } } else if (!strcmp(params[0], "error")) { if (num_params < 2) { PARSE_ERR(("%s: error directive malformed.", context)); } if (parse_log_options(context, num_params, params) < 0) { return -1; } } else if (!strcmp(params[0], "info")) { if (num_params < 2) { PARSE_ERR(("%s: info directive malformed.", context)); } if (parse_log_options(context, num_params, params) < 0) { return -1; } } else if (!strcmp(params[0], "debug")) { if (num_params < 2) { PARSE_ERR(("%s: debug directive malformed.", context)); } if (parse_log_options(context, num_params, params) < 0) { return -1; } } else if (!strcmp(params[0], "cpu")) { if (num_params < 2) { PARSE_ERR(("%s: cpu directive malformed.", context)); } for (i=1; iget_param_num(BXPN_CPU_NPROCESSORS)->set(processors); SIM->get_param_num(BXPN_CPU_NCORES)->set(cores); SIM->get_param_num(BXPN_CPU_NTHREADS)->set(threads); } else if (!strncmp(params[i], "model=", 6)) { if (! SIM->get_param_enum(BXPN_CPU_MODEL)->set_by_name(¶ms[i][6])) PARSE_ERR(("%s: unsupported CPU model option.", context)); } else if (!strncmp(params[i], "ips=", 4)) { SIM->get_param_num(BXPN_IPS)->set(atol(¶ms[i][4])); #if BX_SUPPORT_SMP } else if (!strncmp(params[i], "quantum=", 8)) { SIM->get_param_num(BXPN_SMP_QUANTUM)->set(atol(¶ms[i][8])); #endif } else if (!strncmp(params[i], "reset_on_triple_fault=", 22)) { if (parse_param_bool(params[i], 22, BXPN_RESET_ON_TRIPLE_FAULT) < 0) { PARSE_ERR(("%s: cpu directive malformed.", context)); } #if BX_CPU_LEVEL >= 5 } else if (!strncmp(params[i], "ignore_bad_msrs=", 16)) { if (parse_param_bool(params[i], 16, BXPN_IGNORE_BAD_MSRS) < 0) { PARSE_ERR(("%s: cpu directive malformed.", context)); } #endif #if BX_SUPPORT_MONITOR_MWAIT } else if (!strncmp(params[i], "mwait_is_nop=", 13)) { if (parse_param_bool(params[i], 13, BXPN_MWAIT_IS_NOP) < 0) { PARSE_ERR(("%s: cpu directive malformed.", context)); } #endif } else if (!strncmp(params[i], "msrs=", 5)) { SIM->get_param_string(BXPN_CONFIGURABLE_MSRS_PATH)->set(¶ms[i][5]); } else if (!strncmp(params[i], "cpuid_limit_winnt=", 18)) { if (parse_param_bool(params[i], 18, BXPN_CPUID_LIMIT_WINNT) < 0) { PARSE_ERR(("%s: cpu directive malformed.", context)); } } else { PARSE_ERR(("%s: cpu directive malformed.", context)); } } #if BX_CPU_LEVEL >= 4 } else if (!strcmp(params[0], "cpuid")) { if (num_params < 2) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } for (i=1; iget_param_string(BXPN_VENDOR_STRING)->set(¶ms[i][14]); } else if (!strncmp(params[i], "brand_string=", 13)) { if (strlen(¶ms[i][13]) > BX_CPUID_BRAND_LEN) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } SIM->get_param_string(BXPN_BRAND_STRING)->set(¶ms[i][13]); } else if (!strncmp(params[i], "stepping=", 9)) { SIM->get_param_num(BXPN_CPUID_STEPPING)->set(atol(¶ms[i][9])); } else if (!strncmp(params[i], "model=", 6)) { SIM->get_param_num(BXPN_CPUID_MODEL)->set(strtoul(¶ms[i][6], NULL, 0)); } else if (!strncmp(params[i], "family=", 7)) { SIM->get_param_num(BXPN_CPUID_FAMILY)->set(strtoul(¶ms[i][7], NULL, 0)); #if BX_CPU_LEVEL >= 5 } else if (!strncmp(params[i], "mmx=", 4)) { if (parse_param_bool(params[i], 4, BXPN_CPUID_MMX) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "apic=", 5)) { if (! SIM->get_param_enum(BXPN_CPUID_APIC)->set_by_name(¶ms[i][5])) PARSE_ERR(("%s: unsupported apic option.", context)); } else if (!strncmp(params[i], "xapic=", 6)) { PARSE_ERR(("%s: unsupported xapic option (deprecated).", context)); #endif #if BX_CPU_LEVEL >= 6 } else if (!strncmp(params[i], "sse=", 4)) { if (! SIM->get_param_enum(BXPN_CPUID_SSE)->set_by_name(¶ms[i][4])) PARSE_ERR(("%s: unsupported sse option.", context)); } else if (!strncmp(params[i], "sse4a=", 6)) { if (parse_param_bool(params[i], 6, BXPN_CPUID_SSE4A) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "aes=", 4)) { if (parse_param_bool(params[i], 4, BXPN_CPUID_AES) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "movbe=", 6)) { if (parse_param_bool(params[i], 6, BXPN_CPUID_MOVBE) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "adx=", 4)) { if (parse_param_bool(params[i], 4, BXPN_CPUID_ADX) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "sep=", 4)) { if (parse_param_bool(params[i], 4, BXPN_CPUID_SEP) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "xsave=", 6)) { if (parse_param_bool(params[i], 6, BXPN_CPUID_XSAVE) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "xsaveopt=", 9)) { if (parse_param_bool(params[i], 9, BXPN_CPUID_XSAVEOPT) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } #if BX_SUPPORT_AVX } else if (!strncmp(params[i], "avx=", 4)) { SIM->get_param_num(BXPN_CPUID_AVX)->set(atol(¶ms[i][4])); } else if (!strncmp(params[i], "avx_f16c=", 9)) { if (parse_param_bool(params[i], 9, BXPN_CPUID_AVX_F16CVT) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "avx_fma=", 8)) { if (parse_param_bool(params[i], 8, BXPN_CPUID_AVX_FMA) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "bmi=", 4)) { SIM->get_param_num(BXPN_CPUID_BMI)->set(atol(¶ms[i][4])); } else if (!strncmp(params[i], "xop=", 4)) { if (parse_param_bool(params[i], 4, BXPN_CPUID_XOP) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "tbm=", 4)) { if (parse_param_bool(params[i], 4, BXPN_CPUID_TBM) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "fma4=", 5)) { if (parse_param_bool(params[i], 5, BXPN_CPUID_FMA4) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } #endif #if BX_SUPPORT_VMX } else if (!strncmp(params[i], "vmx=", 4)) { SIM->get_param_num(BXPN_CPUID_VMX)->set(atol(¶ms[i][4])); #endif #if BX_SUPPORT_SVM } else if (!strncmp(params[i], "svm=", 4)) { if (parse_param_bool(params[i], 4, BXPN_CPUID_SVM) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } #endif #if BX_SUPPORT_X86_64 } else if (!strncmp(params[i], "x86_64=", 7)) { if (parse_param_bool(params[i], 7, BXPN_CPUID_X86_64) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "1g_pages=", 9)) { if (parse_param_bool(params[i], 9, BXPN_CPUID_1G_PAGES) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "pcid=", 5)) { if (parse_param_bool(params[i], 5, BXPN_CPUID_PCID) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } else if (!strncmp(params[i], "fsgsbase=", 9)) { if (parse_param_bool(params[i], 9, BXPN_CPUID_FSGSBASE) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } #endif } else if (!strncmp(params[i], "smep=", 5)) { if (parse_param_bool(params[i], 5, BXPN_CPUID_SMEP) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } #if BX_SUPPORT_MONITOR_MWAIT } else if (!strncmp(params[i], "mwait=", 6)) { if (parse_param_bool(params[i], 6, BXPN_CPUID_MWAIT) < 0) { PARSE_ERR(("%s: cpuid directive malformed.", context)); } #endif #endif } else if (!strncmp(params[i], "cpuid_limit_winnt=", 18)) { PARSE_ERR(("%s: cpuid_limit_winnt moved to CPU .bochsrc option.", context)); } else { PARSE_ERR(("%s: cpuid directive malformed.", context)); } } #endif } else if (!strcmp(params[0], "megs")) { if (num_params != 2) { PARSE_ERR(("%s: megs directive: wrong # args.", context)); } SIM->get_param_num(BXPN_MEM_SIZE)->set(atol(params[1])); SIM->get_param_num(BXPN_HOST_MEM_SIZE)->set(atol(params[1])); } else if (!strcmp(params[0], "memory")) { if (num_params < 3) { PARSE_ERR(("%s: memory directive malformed.", context)); } for (i=1; i 3)) { PARSE_ERR(("%s: romimage directive: wrong # args.", context)); } if (!strncmp(params[1], "file=", 5)) { SIM->get_param_string(BXPN_ROM_PATH)->set(¶ms[1][5]); } else { PARSE_ERR(("%s: romimage directive malformed.", context)); } if (num_params == 3) { if (!strncmp(params[2], "address=", 8)) { if ((params[2][8] == '0') && (params[2][9] == 'x')) SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(¶ms[2][8], NULL, 16)); else SIM->get_param_num(BXPN_ROM_ADDRESS)->set(strtoul(¶ms[2][8], NULL, 10)); } else { PARSE_ERR(("%s: romimage directive malformed.", context)); } } else { SIM->get_param_num(BXPN_ROM_ADDRESS)->set(0); } } else if (!strcmp(params[0], "vgaromimage")) { if (num_params != 2) { PARSE_ERR(("%s: vgaromimage directive: wrong # args.", context)); } if (!strncmp(params[1], "file=", 5)) { SIM->get_param_string(BXPN_VGA_ROM_PATH)->set(¶ms[1][5]); } else { PARSE_ERR(("%s: vgaromimage directive malformed.", context)); } } else if (!strncmp(params[0], "optromimage", 11)) { int num = atoi(¶ms[0][11]); char tmppath[80], tmpaddr[80]; if ((num < 1) || (num > BX_N_OPTROM_IMAGES)) { PARSE_ERR(("%s: optromimage%d: not supported", context, num)); } if (num_params != 3) { PARSE_ERR(("%s: optromimage%d directive: wrong # args.", context, num)); } sprintf(tmppath, "memory.optrom.%d.path", num); sprintf(tmpaddr, "memory.optrom.%d.addr", num); for (i=1; i BX_N_OPTRAM_IMAGES)) { PARSE_ERR(("%s: optramimage%d: not supported", context, num)); } if (num_params != 3) { PARSE_ERR(("%s: optramimage%d directive: wrong # args.", context, num)); } sprintf(tmppath, "memory.optram.%d.path", num); sprintf(tmpaddr, "memory.optram.%d.addr", num); for (i=1; i 0) { SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY)->set(1000000 / value); PARSE_WARN(("%s: 'vga_update_interval' will be replaced by new 'vga: update_freq' option.", context)); } else { PARSE_ERR(("%s: invalid value for vga_update_interval", context)); } } else if (!strcmp(params[0], "vga")) { if (num_params < 2) { PARSE_ERR(("%s: vga directive malformed.", context)); } for (i=1; iget_param_num(BXPN_KBD_SERIAL_DELAY)->set(atol(params[1])); if (SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get() < 5) { PARSE_ERR (("%s: keyboard_serial_delay not big enough!", context)); } PARSE_WARN(("%s: 'keyboard_serial_delay' will be replaced by new 'keyboard' option.", context)); } else if (!strcmp(params[0], "keyboard_paste_delay")) { if (num_params != 2) { PARSE_ERR(("%s: keyboard_paste_delay directive: wrong # args.", context)); } SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set(atol(params[1])); if (SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get() < 1000) { PARSE_ERR (("%s: keyboard_paste_delay not big enough!", context)); } PARSE_WARN(("%s: 'keyboard_paste_delay' will be replaced by new 'keyboard' option.", context)); } else if (!strcmp(params[0], "text_snapshot_check")) { PARSE_ERR(("%s: the 'text_snapshot_check' feature has been removed.", context)); } else if (!strcmp(params[0], "mouse")) { if (num_params < 2) { PARSE_ERR(("%s: mouse directive malformed.", context)); } for (i=1; iget_param_string(BXPN_SCREENMODE)->set(¶ms[1][5]); #endif } else if ((!strcmp(params[0], "pci")) || (!strcmp(params[0], "i440fxsupport"))) { // new option 'pci' for future extensions char tmpdev[80]; int enabled = -1; int chipset = -1; if (!strcmp(params[0], "i440fxsupport")) { chipset = 1; PARSE_WARN(("%s: 'i440fxsupport' will be replaced by new 'pci' option.", context)); } for (i=1; iget_param_bool(BXPN_I440FX_SUPPORT)->set(0); } else if (enabled == 1) { if (chipset == 1) { SIM->get_param_bool(BXPN_I440FX_SUPPORT)->set(1); } else { PARSE_ERR(("%s: pci: chipset not specified", context)); } } } else if (!strcmp(params[0], "cmosimage")) { for (i=1; iget_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(0); } else if (!strcmp(params[i], "rtc_init=image")) { SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->set(1); } else { // for backward compatiblity SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->set(params[i]); } } if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) { SIM->get_param_bool(BXPN_CMOSIMAGE_ENABLED)->set(1); } } else if (!strcmp(params[0], "clock")) { for (i=1; iget_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_LOCAL); } else if (!strcmp(params[i], "time0=utc")) { SIM->get_param_num(BXPN_CLOCK_TIME0)->set(BX_CLOCK_TIME0_UTC); } else if (!strncmp(params[i], "time0=", 6)) { SIM->get_param_num(BXPN_CLOCK_TIME0)->set(atoi(¶ms[i][6])); } else { BX_ERROR(("%s: unknown parameter for clock ignored.", context)); } } } else if (!strcmp(params[0], "gdbstub")) { #if BX_GDBSTUB if (num_params < 2) { PARSE_ERR(("%s: gdbstub directive: wrong # args.", context)); } base = (bx_list_c*) SIM->get_param(BXPN_GDBSTUB); for (i=1; iset(0); BX_INFO(("Disabled gdbstub")); bx_dbg.gdbstub_enabled = 0; } else if (params[i][8] == '1') { SIM->get_param_bool("enabled", base)->set(1); BX_INFO(("Enabled gdbstub")); bx_dbg.gdbstub_enabled = 1; } else { PARSE_ERR(("%s: gdbstub directive malformed.", context)); } } else if (!strncmp(params[i], "port=", 5)) { SIM->get_param_num("port", base)->set(atoi(¶ms[i][5])); } else if (!strncmp(params[i], "text_base=", 10)) { SIM->get_param_num("text_base", base)->set(atoi(¶ms[i][10])); } else if (!strncmp(params[i], "data_base=", 10)) { SIM->get_param_num("data_base", base)->set(atoi(¶ms[i][10])); } else if (!strncmp(params[i], "bss_base=", 9)) { SIM->get_param_num("bss_base", base)->set(atoi(¶ms[i][9])); } else { PARSE_ERR(("%s: gdbstub directive malformed.", context)); } } #else PARSE_ERR(("%s: Bochs is not compiled with gdbstub support", context)); #endif } else if (!strcmp(params[0], "magic_break")) { #if BX_DEBUGGER if (num_params != 2) { PARSE_ERR(("%s: magic_break directive: wrong # args.", context)); } if (strncmp(params[1], "enabled=", 8)) { PARSE_ERR(("%s: magic_break directive malformed.", context)); } if (params[1][8] == '0') { BX_INFO(("Ignoring magic break points")); bx_dbg.magic_break_enabled = 0; } else if (params[1][8] == '1') { BX_INFO(("Stopping on magic break points")); bx_dbg.magic_break_enabled = 1; } else { PARSE_ERR(("%s: magic_break directive malformed.", context)); } #else PARSE_WARN(("%s: Bochs is not compiled with internal debugger support", context)); #endif } else if (!strcmp(params[0], "debug_symbols")) { if (parse_debug_symbols(context, (const char **)(params + 1), num_params - 1) < 0) { return -1; } } else if (!strcmp(params[0], "print_timestamps")) { if (num_params != 2) { PARSE_ERR(("%s: print_timestamps directive: wrong # args.", context)); } if (strncmp(params[1], "enabled=", 8)) { PARSE_ERR(("%s: print_timestamps directive malformed.", context)); } if (params[1][8] == '0' || params[1][8] == '1') { bx_dbg.print_timestamps = params[1][8] - '0'; } else { PARSE_ERR(("%s: print_timestamps directive malformed.", context)); } } else if (!strcmp(params[0], "port_e9_hack")) { if (num_params != 2) { PARSE_ERR(("%s: port_e9_hack directive: wrong # args.", context)); } if (strncmp(params[1], "enabled=", 8)) { PARSE_ERR(("%s: port_e9_hack directive malformed.", context)); } if (parse_param_bool(params[1], 8, BXPN_PORT_E9_HACK) < 0) { PARSE_ERR(("%s: port_e9_hack directive malformed.", context)); } } else if (!strcmp(params[0], "load32bitOSImage")) { if ((num_params!=4) && (num_params!=5)) { PARSE_ERR(("%s: load32bitOSImage directive: wrong # args.", context)); } if (strncmp(params[1], "os=", 3)) { PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); } if (!strcmp(¶ms[1][3], "nullkernel")) { SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSNullKernel); } else if (!strcmp(¶ms[1][3], "linux")) { SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->set(Load32bitOSLinux); } else { PARSE_ERR(("%s: load32bitOSImage: unsupported OS.", context)); } if (strncmp(params[2], "path=", 5)) { PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); } if (strncmp(params[3], "iolog=", 6)) { PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); } SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->set(¶ms[2][5]); SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->set(¶ms[3][6]); if (num_params == 5) { if (strncmp(params[4], "initrd=", 7)) { PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context)); } SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->set(¶ms[4][7]); } } else if (!strcmp(params[0], "keyboard_type")) { if (num_params != 2) { PARSE_ERR(("%s: keyboard_type directive: wrong # args.", context)); } if (!SIM->get_param_enum(BXPN_KBD_TYPE)->set_by_name(params[1])) { PARSE_ERR(("%s: keyboard_type directive: wrong arg '%s'.", context,params[1])); } PARSE_WARN(("%s: 'keyboard_type' will be replaced by new 'keyboard' option.", context)); } else if (!strcmp(params[0], "keyboard_mapping") ||!strcmp(params[0], "keyboardmapping")) { for (i=1; iget_param_enum(BXPN_SEL_CONFIG_INTERFACE)->set_by_name(params[1])) PARSE_ERR(("%s: config_interface '%s' not available", context, params[1])); } else if (!strcmp(params[0], "display_library")) { if ((num_params < 2) || (num_params > 3)) { PARSE_ERR(("%s: display_library directive: wrong # args.", context)); } if (!SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->set_by_name(params[1])) PARSE_ERR(("%s: display library '%s' not available", context, params[1])); if (num_params == 3) { if (!strncmp(params[2], "options=", 8)) { SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->set(¶ms[2][8]); } } } #if BX_PLUGINS else if (!strcmp(params[0], "user_plugin")) { char tmpname[80]; for (i=1; iget_param_string(tmpname)->set(¶ms[i][5]); } else { PARSE_ERR(("%s: too many user plugins", context)); } } else { PARSE_ERR(("%s: unknown user plugin parameter '%s'", context, params[i])); } } } #endif else if (!strcmp(params[0], "plugin_ctrl")) { char *param, *pname, *val; for (i=1; iopt_plugin_ctrl(pname, atoi(val)); } else { PARSE_ERR(("%s: plugin_ctrl directive malformed", context)); } } else { PARSE_ERR(("%s: plugin_ctrl directive malformed", context)); } free(param); } } // add-on options handled by registered functions else if (SIM->is_addon_option(params[0])) { return SIM->parse_addon_option(context, num_params, ¶ms[0]); } // treat unknown option as plugin name and try to load it else if (SIM->opt_plugin_ctrl(params[0], 1)) { // after loading the plugin a bochsrc option with it's name must exist if (SIM->is_addon_option(params[0])) { return SIM->parse_addon_option(context, num_params, ¶ms[0]); } else { PARSE_ERR(("%s: directive '%s' not understood", context, params[0])); } } else { PARSE_ERR(("%s: directive '%s' not understood", context, params[0])); } return 0; } static const char *fdtypes[] = { "none", "1_2", "1_44", "2_88", "720k", "360k", "160k", "180k", "320k" }; int bx_write_floppy_options(FILE *fp, int drive) { char devtype[80], path[80], type[80], status[80], readonly[80]; int ftype; BX_ASSERT(drive==0 || drive==1); sprintf(devtype, "floppy.%d.devtype", drive); sprintf(path, "floppy.%d.path", drive); sprintf(type, "floppy.%d.type", drive); sprintf(status, "floppy.%d.status", drive); sprintf(readonly, "floppy.%d.readonly", drive); ftype = SIM->get_param_enum(devtype)->get(); if (ftype == BX_FDD_NONE) { fprintf(fp, "# no floppy%c\n", (char)'a'+drive); return 0; } else { fprintf(fp, "floppy%c: type=", (char)'a'+drive); if (ftype == BX_FDD_350ED) { fprintf(fp, "2_88"); } else if (ftype == BX_FDD_350HD) { fprintf(fp, "1_44"); } else if (ftype == BX_FDD_525HD) { fprintf(fp, "1_2"); } else if (ftype == BX_FDD_350DD) { fprintf(fp, "720k"); } else if (ftype == BX_FDD_525DD) { fprintf(fp, "360k"); } } if ((SIM->get_param_enum(type)->get() > BX_FLOPPY_NONE) && (SIM->get_param_enum(type)->get() <= BX_FLOPPY_LAST)) { fprintf(fp, ", %s=\"%s\", status=%s, write_protected=%d", fdtypes[SIM->get_param_enum(type)->get() - BX_FLOPPY_NONE], SIM->get_param_string(path)->getptr(), SIM->get_param_bool(status)->get() ? "inserted":"ejected", SIM->get_param_bool(readonly)->get()); } fprintf(fp, "\n"); return 0; } int bx_write_ata_options(FILE *fp, Bit8u channel, bx_list_c *base) { fprintf(fp, "ata%d: enabled=%d", channel, SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { fprintf(fp, ", ioaddr1=0x%x, ioaddr2=0x%x, irq=%d", SIM->get_param_num("ioaddr1", base)->get(), SIM->get_param_num("ioaddr2", base)->get(), SIM->get_param_num("irq", base)->get()); } fprintf(fp, "\n"); return 0; } int bx_write_atadevice_options(FILE *fp, Bit8u channel, Bit8u drive, bx_list_c *base) { if (SIM->get_param_bool("present", base)->get()) { fprintf(fp, "ata%d-%s: ", channel, drive==0?"master":"slave"); if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) { fprintf(fp, "type=disk"); fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected()); fprintf(fp, ", translation=%s", SIM->get_param_enum("translation", base)->get_selected()); fprintf(fp, ", path=\"%s\", cylinders=%d, heads=%d, spt=%d", SIM->get_param_string("path", base)->getptr(), SIM->get_param_num("cylinders", base)->get(), SIM->get_param_num("heads", base)->get(), SIM->get_param_num("spt", base)->get()); if (SIM->get_param_string("journal", base)->getptr() != NULL) if (strcmp(SIM->get_param_string("journal", base)->getptr(), "") != 0) fprintf(fp, ", journal=\"%s\"", SIM->get_param_string("journal", base)->getptr()); } else if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_CDROM) { fprintf(fp, "type=cdrom, path=\"%s\", status=%s", SIM->get_param_string("path", base)->getptr(), SIM->get_param_bool("status", base)->get() ? "inserted":"ejected"); } fprintf(fp, ", biosdetect=%s", SIM->get_param_enum("biosdetect", base)->get_selected()); if (SIM->get_param_string("model", base)->getptr()>0) { fprintf(fp, ", model=\"%s\"", SIM->get_param_string("model", base)->getptr()); } fprintf(fp, "\n"); } return 0; } int bx_write_usb_options(FILE *fp, int maxports, bx_list_c *base) { int i; char tmpname[20]; fprintf(fp, "usb_%s: enabled=%d", base->get_name(), SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { for (i = 1; i <= maxports; i++) { sprintf(tmpname, "port%d.device", i); fprintf(fp, ", port%d=%s", i, SIM->get_param_string(tmpname, base)->getptr()); sprintf(tmpname, "port%d.options", i); fprintf(fp, ", options%d=%s", i, SIM->get_param_string(tmpname, base)->getptr()); } } fprintf(fp, "\n"); return 0; } int bx_write_pci_nic_options(FILE *fp, bx_list_c *base) { fprintf (fp, "%s: enabled=%d", base->get_name(), SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { char *ptr = SIM->get_param_string("macaddr", base)->getptr(); fprintf (fp, ", mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s, bootrom=%s", (unsigned int)(0xff & ptr[0]), (unsigned int)(0xff & ptr[1]), (unsigned int)(0xff & ptr[2]), (unsigned int)(0xff & ptr[3]), (unsigned int)(0xff & ptr[4]), (unsigned int)(0xff & ptr[5]), SIM->get_param_enum("ethmod", base)->get_selected(), SIM->get_param_string("ethdev", base)->getptr(), SIM->get_param_string("script", base)->getptr(), SIM->get_param_string("bootrom", base)->getptr()); } fprintf (fp, "\n"); return 0; } int bx_write_loader_options(FILE *fp) { if (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNone) { fprintf(fp, "# no loader\n"); return 0; } BX_ASSERT((SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) || (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSNullKernel)); fprintf (fp, "load32bitOSImage: os=%s, path=%s, iolog=%s, initrd=%s\n", (SIM->get_param_enum(BXPN_LOAD32BITOS_WHICH)->get() == Load32bitOSLinux) ? "linux" : "nullkernel", SIM->get_param_string(BXPN_LOAD32BITOS_PATH)->getptr(), SIM->get_param_string(BXPN_LOAD32BITOS_IOLOG)->getptr(), SIM->get_param_string(BXPN_LOAD32BITOS_INITRD)->getptr()); return 0; } int bx_write_clock_cmos_options(FILE *fp) { fprintf(fp, "clock: "); switch (SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()) { case BX_CLOCK_SYNC_NONE: fprintf(fp, "sync=none"); break; case BX_CLOCK_SYNC_REALTIME: fprintf(fp, "sync=realtime"); break; case BX_CLOCK_SYNC_SLOWDOWN: fprintf(fp, "sync=slowdown"); break; case BX_CLOCK_SYNC_BOTH: fprintf(fp, "sync=both"); break; default: BX_PANIC(("Unknown value for sync method")); } switch (SIM->get_param_num(BXPN_CLOCK_TIME0)->get()) { case 0: break; case BX_CLOCK_TIME0_LOCAL: fprintf(fp, ", time0=local"); break; case BX_CLOCK_TIME0_UTC: fprintf(fp, ", time0=utc"); break; default: fprintf(fp, ", time0=%u", SIM->get_param_num(BXPN_CLOCK_TIME0)->get()); } fprintf(fp, ", rtc_sync=%d\n", SIM->get_param_bool(BXPN_CLOCK_RTC_SYNC)->get()); if (strlen(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()) > 0) { fprintf(fp, "cmosimage: file=%s, ", SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr()); fprintf(fp, "rtc_init=%s\n", SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->get()?"image":"time0"); } else { fprintf(fp, "# no cmosimage\n"); } return 0; } int bx_write_log_options(FILE *fp, bx_list_c *base) { fprintf(fp, "log: %s\n", SIM->get_param_string("filename", base)->getptr()); fprintf(fp, "logprefix: %s\n", SIM->get_param_string("prefix", base)->getptr()); fprintf(fp, "panic: action=%s\n", io->getaction(logfunctions::get_default_action(LOGLEV_PANIC))); fprintf(fp, "error: action=%s\n", io->getaction(logfunctions::get_default_action(LOGLEV_ERROR))); fprintf(fp, "info: action=%s\n", io->getaction(logfunctions::get_default_action(LOGLEV_INFO))); fprintf(fp, "debug: action=%s\n", io->getaction(logfunctions::get_default_action(LOGLEV_DEBUG))); return 0; } int bx_write_keyboard_options(FILE *fp) { fprintf(fp, "keyboard: type=%s, serial_delay=%u, paste_delay=%u, ", SIM->get_param_enum(BXPN_KBD_TYPE)->get_selected(), SIM->get_param_num(BXPN_KBD_SERIAL_DELAY)->get(), SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->get()); if (SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) { fprintf(fp, "keymap=%s\n", SIM->get_param_string(BXPN_KBD_KEYMAP)->getptr()); } else { fprintf(fp, "keymap=\n"); } fprintf(fp, "user_shortcut: keys=%s\n", SIM->get_param_string(BXPN_USER_SHORTCUT)->getptr()); return 0; } int bx_write_debugger_options(FILE *fp) { #if BX_DEBUGGER fprintf(fp, "debugger_log: %s\n", SIM->get_param_string(BXPN_DEBUGGER_LOG_FILENAME)->getptr()); fprintf(fp, "magic_break: enabled=%d\n", bx_dbg.magic_break_enabled); // TODO: debug symbols #endif #if BX_GDBSTUB bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_GDBSTUB); bx_bool enabled = SIM->get_param_bool("enabled", base)->get(); if (enabled) { fprintf(fp, "gdbstub: enabled=%d, port=%d, text_base=%d, data_base=%d, bss_base=%d\n", enabled, SIM->get_param_num("port", base)->get(), SIM->get_param_num("text_base", base)->get(), SIM->get_param_num("data_base", base)->get(), SIM->get_param_num("bss_base", base)->get()); } else { fprintf(fp, "# no gdb stub\n"); } #endif return 0; } // return values: // 0: written ok // -1: failed // -2: already exists, and overwrite was off int bx_write_configuration(const char *rc, int overwrite) { int i; char *strptr, tmppath[80], tmpaddr[80], tmpdev[80]; bx_list_c *base; BX_INFO(("write current configuration to %s", rc)); // check if it exists. If so, only proceed if overwrite is set. FILE *fp = fopen(rc, "r"); if (fp != NULL) { fclose(fp); if (!overwrite) return -2; } fp = fopen(rc, "w"); if (fp == NULL) return -1; // finally it's open and we can start writing. fprintf(fp, "# configuration file generated by Bochs\n"); base = (bx_list_c*) SIM->get_param(BXPN_PLUGIN_CTRL); if (base->get_size() > 0) { fprintf(fp, "plugin_ctrl: "); for (i = 0; i < base->get_size(); i++) { if (i > 0) fprintf(fp, ", "); bx_param_bool_c *plugin = (bx_param_bool_c*)(base->get(i)); fprintf(fp, "%s=1", plugin->get_name()); } fprintf(fp, "\n"); } #if BX_PLUGINS // user plugins for (i=0; iget_param_string(tmpdev)->getptr()) > 0) { fprintf(fp, "user_plugin: name=%s\n", SIM->get_param_string(tmpdev)->getptr()); } } #endif fprintf(fp, "config_interface: %s\n", SIM->get_param_enum(BXPN_SEL_CONFIG_INTERFACE)->get_selected()); fprintf(fp, "display_library: %s", SIM->get_param_enum(BXPN_SEL_DISPLAY_LIBRARY)->get_selected()); strptr = SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr(); if (strlen(strptr) > 0) fprintf(fp, ", options=\"%s\"\n", strptr); else fprintf(fp, "\n"); fprintf(fp, "memory: host=%d, guest=%d\n", SIM->get_param_num(BXPN_HOST_MEM_SIZE)->get(), SIM->get_param_num(BXPN_MEM_SIZE)->get()); strptr = SIM->get_param_string(BXPN_ROM_PATH)->getptr(); if (strlen(strptr) > 0) { fprintf(fp, "romimage: file=\"%s\"", strptr); if (SIM->get_param_num(BXPN_ROM_ADDRESS)->get() != 0) fprintf(fp, ", address=0x%08x\n", (unsigned int) SIM->get_param_num(BXPN_ROM_ADDRESS)->get()); else fprintf(fp, "\n"); } else { fprintf(fp, "# no romimage\n"); } strptr = SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr(); if (strlen(strptr) > 0) fprintf(fp, "vgaromimage: file=\"%s\"\n", strptr); else fprintf(fp, "# no vgaromimage\n"); fprintf(fp, "boot: %s", SIM->get_param_enum(BXPN_BOOTDRIVE1)->get_selected()); for (i=1; i<3; i++) { sprintf(tmppath, "boot_params.boot_drive%d", i+1); if (SIM->get_param_enum(tmppath)->get() != BX_BOOT_NONE) { fprintf(fp, ", %s", SIM->get_param_enum(tmppath)->get_selected()); } } fprintf(fp, "\n"); fprintf(fp, "floppy_bootsig_check: disabled=%d\n", SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->get()); // it would be nice to put this type of function as methods on // the structs like bx_floppy_options::print or something. bx_write_floppy_options(fp, 0); bx_write_floppy_options(fp, 1); for (Bit8u channel=0; channelget_param(tmppath); bx_write_ata_options(fp, channel, (bx_list_c*) SIM->get_param("resources", base)); bx_write_atadevice_options(fp, channel, 0, (bx_list_c*) SIM->get_param("master", base)); bx_write_atadevice_options(fp, channel, 1, (bx_list_c*) SIM->get_param("slave", base)); } for (i=0; iget_param_string(tmppath)->getptr(); if (strlen(strptr) > 0) fprintf(fp, "optromimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr, (unsigned int)SIM->get_param_num(tmpaddr)->get()); } for (i=0; iget_param_string(tmppath)->getptr(); if (strlen(strptr) > 0) fprintf(fp, "optramimage%d: file=\"%s\", address=0x%05x\n", i+1, strptr, (unsigned int)SIM->get_param_num(tmpaddr)->get()); } // pci fprintf(fp, "pci: enabled=%d", SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()); if (SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) { fprintf(fp, ", chipset=i440fx"); for (i=0; iget_param_string(tmpdev)->getptr(); if (strlen(strptr) > 0) { fprintf(fp, ", slot%d=%s", i+1, strptr); } } } fprintf(fp, "\n"); fprintf(fp, "vga: extension=%s, update_freq=%u\n", SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY)->get()); #if BX_SUPPORT_SMP fprintf(fp, "cpu: count=%u:%u:%u, ips=%u, quantum=%d, ", SIM->get_param_num(BXPN_CPU_NPROCESSORS)->get(), SIM->get_param_num(BXPN_CPU_NCORES)->get(), SIM->get_param_num(BXPN_CPU_NTHREADS)->get(), SIM->get_param_num(BXPN_IPS)->get(), SIM->get_param_num(BXPN_SMP_QUANTUM)->get()); #else fprintf(fp, "cpu: count=1, ips=%u, ", SIM->get_param_num(BXPN_IPS)->get()); #endif fprintf(fp, "model=%s, reset_on_triple_fault=%d, cpuid_limit_winnt=%d", SIM->get_param_enum(BXPN_CPU_MODEL)->get_selected(), SIM->get_param_bool(BXPN_RESET_ON_TRIPLE_FAULT)->get(), SIM->get_param_bool(BXPN_CPUID_LIMIT_WINNT)->get()); #if BX_CPU_LEVEL >= 5 fprintf(fp, ", ignore_bad_msrs=%d", SIM->get_param_bool(BXPN_IGNORE_BAD_MSRS)->get()); #endif #if BX_SUPPORT_MONITOR_MWAIT fprintf(fp, ", mwait_is_nop=%d", SIM->get_param_bool(BXPN_MWAIT_IS_NOP)->get()); #endif #if BX_CONFIGURE_MSRS strptr = SIM->get_param_string(BXPN_CONFIGURABLE_MSRS_PATH)->getptr(); if (strlen(strptr) > 0) fprintf(fp, ", msrs=\"%s\"", strptr); #endif fprintf(fp, "\n"); #if BX_CPU_LEVEL >= 4 if (! SIM->get_param_enum(BXPN_CPU_MODEL)->get()) { // dump only when using BX_GENERIC CPUDB profile fprintf(fp, "cpuid: family=%d, model=0x%02x, stepping=%d", SIM->get_param_num(BXPN_CPUID_FAMILY)->get(), SIM->get_param_num(BXPN_CPUID_MODEL)->get(), SIM->get_param_num(BXPN_CPUID_STEPPING)->get()); #if BX_CPU_LEVEL >= 5 fprintf(fp, ", mmx=%d, apic=%s", SIM->get_param_bool(BXPN_CPUID_MMX)->get(), SIM->get_param_enum(BXPN_CPUID_APIC)->get_selected()); #endif #if BX_CPU_LEVEL >= 6 fprintf(fp, ", sse=%s, sse4a=%d, sep=%d, aes=%d, xsave=%d, xsaveopt=%d, movbe=%d, adx=%d, smep=%d", SIM->get_param_enum(BXPN_CPUID_SSE)->get_selected(), SIM->get_param_bool(BXPN_CPUID_SSE4A)->get(), SIM->get_param_bool(BXPN_CPUID_SEP)->get(), SIM->get_param_bool(BXPN_CPUID_AES)->get(), SIM->get_param_bool(BXPN_CPUID_XSAVE)->get(), SIM->get_param_bool(BXPN_CPUID_XSAVEOPT)->get(), SIM->get_param_bool(BXPN_CPUID_MOVBE)->get(), SIM->get_param_bool(BXPN_CPUID_ADX)->get(), SIM->get_param_bool(BXPN_CPUID_SMEP)->get()); #if BX_SUPPORT_AVX fprintf(fp, ", avx=%d, avx_f16c=%d, avx_fma=%d, bmi=%d, xop=%d, tbm=%d, fma4=%d", SIM->get_param_num(BXPN_CPUID_AVX)->get(), SIM->get_param_bool(BXPN_CPUID_AVX_F16CVT)->get(), SIM->get_param_bool(BXPN_CPUID_AVX_FMA)->get(), SIM->get_param_num(BXPN_CPUID_BMI)->get(), SIM->get_param_bool(BXPN_CPUID_XOP)->get(), SIM->get_param_bool(BXPN_CPUID_TBM)->get(), SIM->get_param_bool(BXPN_CPUID_FMA4)->get()); #endif #if BX_SUPPORT_VMX fprintf(fp, ", vmx=%d", SIM->get_param_num(BXPN_CPUID_VMX)->get()); #endif #if BX_SUPPORT_SVM fprintf(fp, ", svm=%d", SIM->get_param_num(BXPN_CPUID_SVM)->get()); #endif #if BX_SUPPORT_X86_64 fprintf(fp, ", x86_64=%d, 1g_pages=%d, pcid=%d, fsgsbase=%d", SIM->get_param_bool(BXPN_CPUID_X86_64)->get(), SIM->get_param_bool(BXPN_CPUID_1G_PAGES)->get(), SIM->get_param_bool(BXPN_CPUID_PCID)->get(), SIM->get_param_bool(BXPN_CPUID_FSGSBASE)->get()); #endif #if BX_SUPPORT_MONITOR_MWAIT fprintf(fp, ", mwait=%d", SIM->get_param_bool(BXPN_CPUID_MWAIT)->get()); #endif #endif fprintf(fp, "\n"); const char *vendor_string = SIM->get_param_string(BXPN_VENDOR_STRING)->getptr(); if (vendor_string) fprintf(fp, "cpuid: vendor_string=\"%s\"\n", vendor_string); const char *brand_string = SIM->get_param_string(BXPN_BRAND_STRING)->getptr(); if (brand_string) fprintf(fp, "cpuid: brand_string=\"%s\"\n", brand_string); fprintf(fp, "\n"); } #endif fprintf(fp, "print_timestamps: enabled=%d\n", bx_dbg.print_timestamps); bx_write_debugger_options(fp); fprintf(fp, "port_e9_hack: enabled=%d\n", SIM->get_param_bool(BXPN_PORT_E9_HACK)->get()); fprintf(fp, "private_colormap: enabled=%d\n", SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get()); #if BX_WITH_AMIGAOS fprintf(fp, "fullscreen: enabled=%d\n", SIM->get_param_bool(BXPN_FULLSCREEN)->get()); fprintf(fp, "screenmode: name=\"%s\"\n", SIM->get_param_string(BXPN_SCREENMODE)->getptr()); #endif bx_write_clock_cmos_options(fp); bx_write_loader_options(fp); bx_write_log_options(fp, (bx_list_c*) SIM->get_param("log")); bx_write_keyboard_options(fp); fprintf(fp, "mouse: enabled=%d, type=%s, toggle=%s\n", SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get(), SIM->get_param_enum(BXPN_MOUSE_TYPE)->get_selected(), SIM->get_param_enum(BXPN_MOUSE_TOGGLE)->get_selected()); SIM->save_addon_options(fp); fclose(fp); return 0; } bochs-2.6/LICENSE0000644000175000017500000000045512020641507013343 0ustar guillemguillemThe following points clarify the Bochs license: 1) Bochs as a whole is released under the GNU Lesser General Public License 2) Parts of Bochs have specific licenses which are compatible with the GNU Lesser General Public License. Hence each source file contains its own licensing information. bochs-2.6/iodev/0000755000175000017500000000000012020641505013436 5ustar guillemguillembochs-2.6/iodev/serial.h0000644000175000017500000001707012020641505015073 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: serial.h 11224 2012-06-21 17:33:37Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef BX_IODEV_SERIAL_H #define BX_IODEV_SERIAL_H // Peter Grehan (grehan@iprg.nokia.com) coded most of this // serial emulation. #if BX_USE_SER_SMF # define BX_SER_SMF static # define BX_SER_THIS theSerialDevice-> #else # define BX_SER_SMF # define BX_SER_THIS this-> #endif #if defined(WIN32) #define SERIAL_ENABLE #endif #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) || defined(__APPLE__) || defined(__sun__) #define SERIAL_ENABLE extern "C" { #include }; #endif #define BX_SERIAL_MAXDEV 4 #define BX_PC_CLOCK_XTL 1843200.0 #define BX_SER_RXIDLE 0 #define BX_SER_RXPOLL 1 #define BX_SER_RXWAIT 2 #define BX_SER_THR 0 #define BX_SER_RBR 0 #define BX_SER_IER 1 #define BX_SER_IIR 2 #define BX_SER_FCR 2 #define BX_SER_LCR 3 #define BX_SER_MCR 4 #define BX_SER_LSR 5 #define BX_SER_MSR 6 #define BX_SER_SCR 7 #define BX_SER_MODE_NULL 0 #define BX_SER_MODE_FILE 1 #define BX_SER_MODE_TERM 2 #define BX_SER_MODE_RAW 3 #define BX_SER_MODE_MOUSE 4 #define BX_SER_MODE_SOCKET 5 #define BX_SER_MODE_PIPE 6 enum { BX_SER_INT_IER, BX_SER_INT_RXDATA, BX_SER_INT_TXHOLD, BX_SER_INT_RXLSTAT, BX_SER_INT_MODSTAT, BX_SER_INT_FIFO }; #if USE_RAW_SERIAL class serial_raw; #endif typedef struct { /* * UART internal state */ bx_bool ls_interrupt; bx_bool ms_interrupt; bx_bool rx_interrupt; bx_bool tx_interrupt; bx_bool fifo_interrupt; bx_bool ls_ipending; bx_bool ms_ipending; bx_bool rx_ipending; bx_bool fifo_ipending; Bit8u IRQ; Bit8u rx_fifo_end; Bit8u tx_fifo_end; int baudrate; int tx_timer_index; int rx_pollstate; int rx_timer_index; int fifo_timer_index; int io_mode; int tty_id; SOCKET socket_id; FILE *output; #ifdef WIN32 HANDLE pipe; #endif #if USE_RAW_SERIAL serial_raw* raw; #endif #if defined(SERIAL_ENABLE) && !defined(WIN32) struct termios term_orig, term_new; #endif /* * Register definitions */ Bit8u rxbuffer; /* receiver buffer register (r/o) */ Bit8u thrbuffer; /* transmit holding register (w/o) */ /* Interrupt Enable Register */ struct { bx_bool rxdata_enable; /* 1=enable receive data interrupts */ bx_bool txhold_enable; /* 1=enable tx. holding reg. empty ints */ bx_bool rxlstat_enable; /* 1=enable rx line status interrupts */ bx_bool modstat_enable; /* 1=enable modem status interrupts */ } int_enable; /* Interrupt Identification Register (r/o) */ struct { bx_bool ipending; /* 0=interrupt pending */ Bit8u int_ID; /* 3-bit interrupt ID */ } int_ident; /* FIFO Control Register (w/o) */ struct { bx_bool enable; /* 1=enable tx and rx FIFOs */ Bit8u rxtrigger; /* 2-bit code for rx fifo trigger level */ } fifo_cntl; /* Line Control Register (r/w) */ struct { Bit8u wordlen_sel; /* 2-bit code for char length */ bx_bool stopbits; /* select stop bit len */ bx_bool parity_enable; /* ... */ bx_bool evenparity_sel; /* ... */ bx_bool stick_parity; /* ... */ bx_bool break_cntl; /* 1=send break signal */ bx_bool dlab; /* divisor latch access bit */ } line_cntl; /* MODEM Control Register (r/w) */ struct { bx_bool dtr; /* DTR output value */ bx_bool rts; /* RTS output value */ bx_bool out1; /* OUTPUT1 value */ bx_bool out2; /* OUTPUT2 value */ bx_bool local_loopback; /* 1=loopback mode */ } modem_cntl; /* Line Status Register (r/w) */ struct { bx_bool rxdata_ready; /* 1=receiver data ready */ bx_bool overrun_error; /* 1=receive overrun detected */ bx_bool parity_error; /* 1=rx char has a bad parity bit */ bx_bool framing_error; /* 1=no stop bit detected for rx char */ bx_bool break_int; /* 1=break signal detected */ bx_bool thr_empty; /* 1=tx hold register (or fifo) is empty */ bx_bool tsr_empty; /* 1=shift reg and hold reg empty */ bx_bool fifo_error; /* 1=at least 1 err condition in fifo */ } line_status; /* Modem Status Register (r/w) */ struct { bx_bool delta_cts; /* 1=CTS changed since last read */ bx_bool delta_dsr; /* 1=DSR changed since last read */ bx_bool ri_trailedge; /* 1=RI moved from low->high */ bx_bool delta_dcd; /* 1=CD changed since last read */ bx_bool cts; /* CTS input value */ bx_bool dsr; /* DSR input value */ bx_bool ri; /* RI input value */ bx_bool dcd; /* DCD input value */ } modem_status; Bit8u scratch; /* Scratch Register (r/w) */ Bit8u tsrbuffer; /* transmit shift register (internal) */ Bit8u rx_fifo[16]; /* receive FIFO (internal) */ Bit8u tx_fifo[16]; /* transmit FIFO (internal) */ Bit8u divisor_lsb; /* Divisor latch, least-sig. byte */ Bit8u divisor_msb; /* Divisor latch, most-sig. byte */ } bx_serial_t; class bx_serial_c : public bx_devmodel_c { public: bx_serial_c(); virtual ~bx_serial_c(); virtual void init(void); virtual void reset(unsigned type) {} virtual void register_state(void); private: bx_serial_t s[BX_SERIAL_MAXDEV]; int detect_mouse; int mouse_port; int mouse_type; int mouse_delayed_dx; int mouse_delayed_dy; int mouse_delayed_dz; struct { int num_elements; Bit8u buffer[BX_MOUSE_BUFF_SIZE]; int head; } mouse_internal_buffer; static void lower_interrupt(Bit8u port); static void raise_interrupt(Bit8u port, int type); static void rx_fifo_enq(Bit8u port, Bit8u data); static void tx_timer_handler(void *); BX_SER_SMF void tx_timer(void); static void rx_timer_handler(void *); BX_SER_SMF void rx_timer(void); static void fifo_timer_handler(void *); BX_SER_SMF void fifo_timer(void); static void mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy); void mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_SER_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/pci2isa.h0000644000175000017500000000445612020641505015152 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pci2isa.h 11148 2012-04-23 17:06:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_PIC2ISA_H #define BX_IODEV_PIC2ISA_H #if BX_USE_P2I_SMF # define BX_P2I_SMF static # define BX_P2I_THIS thePci2IsaBridge-> #else # define BX_P2I_SMF # define BX_P2I_THIS this-> #endif class bx_piix3_c : public bx_pci2isa_stub_c { public: bx_piix3_c(); virtual ~bx_piix3_c(); virtual void init(void); virtual void reset(unsigned type); virtual void pci_set_irq(Bit8u devfunc, unsigned line, bx_bool level); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif private: struct { Bit8u elcr1; Bit8u elcr2; Bit8u apmc; Bit8u apms; Bit8u irq_registry[16]; Bit32u irq_level[16]; Bit8u pci_reset; } s; static void pci_register_irq(unsigned pirq, unsigned irq); static void pci_unregister_irq(unsigned pirq); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_P2I_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/pit.cc0000644000175000017500000003377612020641505014561 0ustar guillemguillem/////////////////////////////////////////////////////////////////////// // $Id: pit.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "pit.h" #include "virt_timer.h" #include "speaker.h" #define LOG_THIS thePit-> bx_pit_c *thePit = NULL; int libpit_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { thePit = new bx_pit_c(); bx_devices.pluginPitDevice = thePit; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePit, BX_PLUGIN_PIT); return 0; // Success } else { return -1; } } void libpit_LTX_plugin_fini(void) { delete thePit; } //Important constant #defines: #define USEC_PER_SECOND (1000000) //1.193181MHz Clock #define TICKS_PER_SECOND (1193181) // define a macro to convert floating point numbers into 64-bit integers. // In MSVC++ you can convert a 64-bit float into a 64-bit signed integer, // but it will not convert a 64-bit float into a 64-bit unsigned integer. // This macro works around that. #define F2I(x) ((Bit64u)(Bit64s) (x)) #define I2F(x) ((double)(Bit64s) (x)) //USEC_ALPHA is multiplier for the past. //USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present. #define USEC_ALPHA ((double)(.8)) #define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA)) #define USEC_ALPHA2 ((double)(.5)) #define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2)) #define ALPHA_LOWER(old,new) ((Bit64u)((oldget_bochs_root()->remove("pit"); BX_DEBUG(("Exit")); } void bx_pit_c::init(void) { DEV_register_irq(0, "8254 PIT"); DEV_register_ioread_handler(this, read_handler, 0x0040, "8254 PIT", 1); DEV_register_ioread_handler(this, read_handler, 0x0041, "8254 PIT", 1); DEV_register_ioread_handler(this, read_handler, 0x0042, "8254 PIT", 1); DEV_register_ioread_handler(this, read_handler, 0x0043, "8254 PIT", 1); DEV_register_ioread_handler(this, read_handler, 0x0061, "8254 PIT", 1); DEV_register_iowrite_handler(this, write_handler, 0x0040, "8254 PIT", 1); DEV_register_iowrite_handler(this, write_handler, 0x0041, "8254 PIT", 1); DEV_register_iowrite_handler(this, write_handler, 0x0042, "8254 PIT", 1); DEV_register_iowrite_handler(this, write_handler, 0x0043, "8254 PIT", 1); DEV_register_iowrite_handler(this, write_handler, 0x0061, "8254 PIT", 1); BX_DEBUG(("starting init")); BX_PIT_THIS s.speaker_data_on = 0; BX_PIT_THIS s.speaker_active = 0; BX_PIT_THIS s.timer.init(); BX_PIT_THIS s.timer.set_OUT_handler(0, irq_handler); Bit64u my_time_usec = bx_virt_timer.time_usec(); if (BX_PIT_THIS s.timer_handle[0] == BX_NULL_TIMER_HANDLE) { BX_PIT_THIS s.timer_handle[0] = bx_virt_timer.register_timer(this, timer_handler, (unsigned) 100 , 1, 1, "pit"); } BX_DEBUG(("RESETting timer.")); bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); BX_DEBUG(("deactivated timer.")); if (BX_PIT_THIS s.timer.get_next_event_time()) { bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), 0); BX_DEBUG(("activated timer.")); } BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); BX_PIT_THIS s.last_usec = my_time_usec; BX_PIT_THIS s.total_ticks = 0; BX_PIT_THIS s.total_usec = 0; BX_DEBUG(("finished init")); BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec)); BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0])); BX_DEBUG(("s.timer.get_next_event_time=%d", BX_PIT_THIS s.timer.get_next_event_time())); BX_DEBUG(("s.last_next_event_time=%d", BX_PIT_THIS s.last_next_event_time)); #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("pit", this); #endif } void bx_pit_c::reset(unsigned type) { BX_PIT_THIS s.timer.reset(type); } void bx_pit_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "pit", "8254 PIT State"); new bx_shadow_bool_c(list, "speaker_data_on", &BX_PIT_THIS s.speaker_data_on); new bx_shadow_bool_c(list, "speaker_active", &BX_PIT_THIS s.speaker_active); new bx_shadow_num_c(list, "last_usec", &BX_PIT_THIS s.last_usec); new bx_shadow_num_c(list, "last_next_event_time", &BX_PIT_THIS s.last_next_event_time); new bx_shadow_num_c(list, "total_ticks", &BX_PIT_THIS s.total_ticks); new bx_shadow_num_c(list, "total_usec", &BX_PIT_THIS s.total_usec); bx_list_c *counter = new bx_list_c(list, "counter"); BX_PIT_THIS s.timer.register_state(counter); } void bx_pit_c::timer_handler(void *this_ptr) { bx_pit_c * class_ptr = (bx_pit_c *) this_ptr; class_ptr->handle_timer(); } void bx_pit_c::handle_timer() { Bit64u my_time_usec = bx_virt_timer.time_usec(); Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec; Bit32u time_passed32 = (Bit32u)time_passed; BX_DEBUG(("entering timer handler")); if(time_passed32) { periodic(time_passed32); } BX_PIT_THIS s.last_usec = BX_PIT_THIS s.last_usec + time_passed; if (time_passed || (BX_PIT_THIS s.last_next_event_time != BX_PIT_THIS s.timer.get_next_event_time())) { BX_DEBUG(("RESETting timer")); bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); BX_DEBUG(("deactivated timer")); if(BX_PIT_THIS s.timer.get_next_event_time()) { bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), 0); BX_DEBUG(("activated timer")); } BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); } BX_DEBUG(("s.last_usec="FMT_LL"d", BX_PIT_THIS s.last_usec)); BX_DEBUG(("s.timer_id=%d", BX_PIT_THIS s.timer_handle[0])); BX_DEBUG(("s.timer.get_next_event_time=%x", BX_PIT_THIS s.timer.get_next_event_time())); BX_DEBUG(("s.last_next_event_time=%d", BX_PIT_THIS s.last_next_event_time)); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_pit_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_PIT_SMF bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_pit_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PIT_SMF bx_bool refresh_clock_div2; Bit8u value = 0; handle_timer(); switch (address) { case 0x40: /* timer 0 - system ticks */ value = BX_PIT_THIS s.timer.read(0); break; case 0x41: /* timer 1 read */ value = BX_PIT_THIS s.timer.read(1); break; case 0x42: /* timer 2 read */ value = BX_PIT_THIS s.timer.read(2); break; case 0x43: /* timer 1 read */ value = BX_PIT_THIS s.timer.read(3); break; case 0x61: /* AT, port 61h */ refresh_clock_div2 = (bx_bool)((bx_virt_timer.time_usec() / 15) & 1); value = (BX_PIT_THIS s.timer.read_OUT(2) << 5) | (refresh_clock_div2 << 4) | (BX_PIT_THIS s.speaker_data_on << 1) | (BX_PIT_THIS s.timer.read_GATE(2) ? 1 : 0); break; default: BX_PANIC(("unsupported io read from port 0x%04x", address)); } BX_DEBUG(("read from port 0x%04x, value = 0x%02x", address, value)); return value; } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_pit_c::write_handler(void *this_ptr, Bit32u address, Bit32u dvalue, unsigned io_len) { #if !BX_USE_PIT_SMF bx_pit_c *class_ptr = (bx_pit_c *) this_ptr; class_ptr->write(address, dvalue, io_len); } void bx_pit_c::write(Bit32u address, Bit32u dvalue, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PIT_SMF Bit8u value; Bit64u my_time_usec = bx_virt_timer.time_usec(); Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec; Bit32u value32, time_passed32 = (Bit32u)time_passed; bx_bool new_speaker_active; if(time_passed32) { periodic(time_passed32); } BX_PIT_THIS s.last_usec = BX_PIT_THIS s.last_usec + time_passed; value = (Bit8u) dvalue; BX_DEBUG(("write to port 0x%04x, value = 0x%02x", address, value)); switch (address) { case 0x40: /* timer 0: write count register */ BX_PIT_THIS s.timer.write(0, value); break; case 0x41: /* timer 1: write count register */ BX_PIT_THIS s.timer.write(1, value); break; case 0x42: /* timer 2: write count register */ BX_PIT_THIS s.timer.write(2, value); break; case 0x43: /* timer 0-2 mode control */ BX_PIT_THIS s.timer.write(3, value); break; case 0x61: BX_PIT_THIS s.timer.set_GATE(2, value & 0x01); BX_PIT_THIS s.speaker_data_on = (value >> 1) & 0x01; new_speaker_active = ((value & 3) == 3); if (BX_PIT_THIS s.speaker_active != new_speaker_active) { if (new_speaker_active) { value32 = BX_PIT_THIS get_timer(2); if (value32 == 0) value32 = 0x10000; DEV_speaker_beep_on((float)(1193180.0 / value32)); } else { DEV_speaker_beep_off(); } BX_PIT_THIS s.speaker_active = new_speaker_active; } break; default: BX_PANIC(("unsupported io write to port 0x%04x = 0x%02x", address, value)); } if (time_passed || (BX_PIT_THIS s.last_next_event_time != BX_PIT_THIS s.timer.get_next_event_time())) { BX_DEBUG(("RESETting timer")); bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]); BX_DEBUG(("deactivated timer")); if(BX_PIT_THIS s.timer.get_next_event_time()) { bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0], (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())), 0); BX_DEBUG(("activated timer")); } BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time(); } BX_DEBUG(("s.last_usec="FMT_LL"d", BX_PIT_THIS s.last_usec)); BX_DEBUG(("s.timer_id=%d", BX_PIT_THIS s.timer_handle[0])); BX_DEBUG(("s.timer.get_next_event_time=%x", BX_PIT_THIS s.timer.get_next_event_time())); BX_DEBUG(("s.last_next_event_time=%d", BX_PIT_THIS s.last_next_event_time)); } bx_bool bx_pit_c::periodic(Bit32u usec_delta) { Bit32u ticks_delta = 0; BX_PIT_THIS s.total_usec += usec_delta; ticks_delta = (Bit32u)((USEC_TO_TICKS((Bit64u)(BX_PIT_THIS s.total_usec)))-BX_PIT_THIS s.total_ticks); BX_PIT_THIS s.total_ticks += ticks_delta; while ((BX_PIT_THIS s.total_ticks >= TICKS_PER_SECOND) && (BX_PIT_THIS s.total_usec >= USEC_PER_SECOND)) { BX_PIT_THIS s.total_ticks -= TICKS_PER_SECOND; BX_PIT_THIS s.total_usec -= USEC_PER_SECOND; } while(ticks_delta>0) { Bit32u maxchange = BX_PIT_THIS s.timer.get_next_event_time(); Bit32u timedelta = maxchange; if((maxchange == 0) || (maxchange>ticks_delta)) { timedelta = ticks_delta; } BX_PIT_THIS s.timer.clock_all(timedelta); ticks_delta -= timedelta; } return 0; } void bx_pit_c::irq_handler(bx_bool value) { if (value == 1) { DEV_pic_raise_irq(0); } else { DEV_pic_lower_irq(0); } } Bit16u bx_pit_c::get_timer(int Timer) { return BX_PIT_THIS s.timer.get_inlatch(Timer); } #if BX_DEBUGGER void bx_pit_c::debug_dump(int argc, char **argv) { Bit32u value; int counter = -1; dbg_printf("82C54 PIT\n\n"); dbg_printf("GATE #2 = %d\n", BX_PIT_THIS s.timer.read_GATE(2)); dbg_printf("Speaker = %d\n\n", BX_PIT_THIS s.speaker_data_on); if (argc == 0) { for (int i = 0; i < 3; i++) { value = BX_PIT_THIS get_timer(i); if (value == 0) value = 0x10000; dbg_printf("counter #%d: freq=%.3f, OUT=%d\n", i, (float)(1193180.0 / value), BX_PIT_THIS s.timer.read_OUT(i)); } dbg_printf("\nSupported options:\n"); dbg_printf("info device 'pit' 'counter=N' - show status of counter N\n"); } else { for (int arg = 0; arg < argc; arg++) { if (!strncmp(argv[arg], "counter=", 8) && isdigit(argv[arg][8])) { counter = atoi(&argv[arg][8]); } else { dbg_printf("\nUnknown option: '%s'\n", argv[arg]); return; } } if ((counter >= 0) && (counter < 3)) { value = BX_PIT_THIS get_timer(counter); if (value == 0) value = 0x10000; dbg_printf("counter #%d: freq=%.3f\n", counter, (float)(1193180.0 / value)); BX_PIT_THIS s.timer.print_cnum(counter); } else { dbg_printf("\nInvalid PIT counter number: %d\n", counter); } } } #endif bochs-2.6/iodev/harddrv.h0000644000175000017500000001705212020641505015246 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: harddrv.h 11162 2012-05-06 19:19:00Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_HDDRIVE_H #define BX_IODEV_HDDRIVE_H #define MAX_MULTIPLE_SECTORS 16 typedef enum _sense { SENSE_NONE = 0, SENSE_NOT_READY = 2, SENSE_ILLEGAL_REQUEST = 5, SENSE_UNIT_ATTENTION = 6 } sense_t; typedef enum _asc { ASC_ILLEGAL_OPCODE = 0x20, ASC_LOGICAL_BLOCK_OOR = 0x21, ASC_INV_FIELD_IN_CMD_PACKET = 0x24, ASC_MEDIUM_MAY_HAVE_CHANGED = 0x28, ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39, ASC_MEDIUM_NOT_PRESENT = 0x3a } asc_t; class device_image_t; class LOWLEVEL_CDROM; typedef struct { struct { bx_bool busy; bx_bool drive_ready; bx_bool write_fault; bx_bool seek_complete; bx_bool drq; bx_bool corrected_data; bx_bool index_pulse; unsigned index_pulse_count; bx_bool err; } status; Bit8u error_register; Bit8u head_no; union { Bit8u sector_count; struct { #ifdef BX_LITTLE_ENDIAN unsigned c_d : 1; unsigned i_o : 1; unsigned rel : 1; unsigned tag : 5; #else /* BX_BIG_ENDIAN */ unsigned tag : 5; unsigned rel : 1; unsigned i_o : 1; unsigned c_d : 1; #endif } interrupt_reason; }; Bit8u sector_no; union { Bit16u cylinder_no; Bit16u byte_count; }; Bit8u buffer[MAX_MULTIPLE_SECTORS*512 + 4]; Bit32u buffer_size; Bit32u buffer_index; Bit32u drq_index; Bit8u current_command; Bit8u multiple_sectors; bx_bool lba_mode; bx_bool packet_dma; Bit8u mdma_mode; Bit8u udma_mode; struct { bx_bool reset; // 0=normal, 1=reset controller bx_bool disable_irq; // 0=allow irq, 1=disable irq } control; Bit8u reset_in_progress; Bit8u features; struct { Bit8u feature; Bit8u nsector; Bit8u sector; Bit8u lcyl; Bit8u hcyl; } hob; Bit32u num_sectors; bx_bool lba48; } controller_t; struct sense_info_t { sense_t sense_key; struct { Bit8u arr[4]; } information; struct { Bit8u arr[4]; } specific_inf; struct { Bit8u arr[3]; } key_spec; Bit8u fruc; Bit8u asc; Bit8u ascq; }; struct error_recovery_t { unsigned char data[8]; error_recovery_t (); }; Bit16u read_16bit(const Bit8u* buf) BX_CPP_AttrRegparmN(1); Bit32u read_32bit(const Bit8u* buf) BX_CPP_AttrRegparmN(1); struct cdrom_t { bx_bool ready; bx_bool locked; #ifdef LOWLEVEL_CDROM LOWLEVEL_CDROM* cd; #endif Bit32u capacity; int next_lba; int remaining_blocks; struct currentStruct { error_recovery_t error_recovery; } current; }; struct atapi_t { Bit8u command; int drq_bytes; int total_bytes_remaining; }; #if BX_USE_HD_SMF # define BX_HD_SMF static # define BX_HD_THIS theHardDrive-> # define BX_HD_THIS_PTR theHardDrive #else # define BX_HD_SMF # define BX_HD_THIS this-> # define BX_HD_THIS_PTR this #endif typedef enum { IDE_NONE, IDE_DISK, IDE_CDROM } device_type_t; class bx_hard_drive_c : public bx_hard_drive_stub_c { public: bx_hard_drive_c(); virtual ~bx_hard_drive_c(); virtual void init(); virtual void reset(unsigned type); virtual Bit32u get_first_cd_handle(void); virtual bx_bool get_cd_media_status(Bit32u handle); virtual bx_bool set_cd_media_status(Bit32u handle, bx_bool status); #if BX_SUPPORT_PCI virtual bx_bool bmdma_read_sector(Bit8u channel, Bit8u *buffer, Bit32u *sector_size); virtual bx_bool bmdma_write_sector(Bit8u channel, Bit8u *buffer); virtual void bmdma_complete(Bit8u channel); #endif virtual void register_state(void); virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len) { return read_handler(this, address, io_len); } virtual void virt_write_handler(Bit32u address, Bit32u value, unsigned io_len) { write_handler(this, address, value, io_len); } #if !BX_USE_HD_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); static void seek_timer_handler(void *); BX_HD_SMF void seek_timer(void); static void runtime_config_handler(void *); void runtime_config(void); private: BX_HD_SMF bx_bool calculate_logical_address(Bit8u channel, Bit64s *sector) BX_CPP_AttrRegparmN(2); BX_HD_SMF void increment_address(Bit8u channel, Bit64s *sector) BX_CPP_AttrRegparmN(2); BX_HD_SMF void identify_drive(Bit8u channel); BX_HD_SMF void identify_ATAPI_drive(Bit8u channel); BX_HD_SMF void command_aborted(Bit8u channel, unsigned command); BX_HD_SMF void init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bx_bool lazy = 0); BX_HD_SMF void ready_to_send_atapi(Bit8u channel) BX_CPP_AttrRegparmN(1); BX_HD_SMF void raise_interrupt(Bit8u channel) BX_CPP_AttrRegparmN(1); BX_HD_SMF void atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc, bx_bool show); BX_HD_SMF void init_mode_sense_single(Bit8u channel, const void* src, int size); BX_HD_SMF void atapi_cmd_nop(controller_t *controller) BX_CPP_AttrRegparmN(1); BX_HD_SMF bx_bool bmdma_present(void); BX_HD_SMF void set_signature(Bit8u channel, Bit8u id); BX_HD_SMF bx_bool ide_read_sector(Bit8u channel, Bit8u *buffer, Bit32u buffer_size); BX_HD_SMF bx_bool ide_write_sector(Bit8u channel, Bit8u *buffer, Bit32u buffer_size); BX_HD_SMF void lba48_transform(controller_t *controller, bx_bool lba48); static Bit64s cdrom_status_handler(bx_param_c *param, int set, Bit64s val); static const char* cdrom_path_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen); // FIXME: // For each ATA channel we should have one controller struct // and an array of two drive structs struct channel_t { struct drive_t { device_image_t* hdimage; device_type_t device_type; // 512 byte buffer for ID drive command // These words are stored in native word endian format, as // they are fetched and returned via a return(), so // there's no need to keep them in x86 endian format. Bit16u id_drive[256]; bx_bool identify_set; controller_t controller; cdrom_t cdrom; sense_info_t sense; atapi_t atapi; Bit8u model_no[41]; int statusbar_id; Bit8u device_num; // for ATAPI identify & inquiry bx_bool status_changed; } drives[2]; unsigned drive_select; Bit16u ioaddr1; Bit16u ioaddr2; Bit8u irq; } channels[BX_MAX_ATA_CHANNEL]; int seek_timer_index; Bit8u cdrom_count; bx_bool pci_enabled; }; #endif bochs-2.6/iodev/extfpuirq.h0000644000175000017500000000313012020641505015633 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: extfpuirq.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef BX_IODEV_EXTFPUIRQ_H #define BX_IODEV_EXTFPUIRQ_H #if BX_USE_EFI_SMF # define BX_EXTFPUIRQ_SMF static # define BX_EXTFPUIRQ_THIS theExternalFpuIrq-> #else # define BX_EXTFPUIRQ_SMF # define BX_EXTFPUIRQ_THIS this-> #endif class bx_extfpuirq_c : public bx_devmodel_c { public: bx_extfpuirq_c(); virtual ~bx_extfpuirq_c(); virtual void init(void); virtual void reset(unsigned type); private: static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_EFI_SMF void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/pci2isa.cc0000644000175000017500000003075212020641505015306 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pci2isa.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // i440FX Support - PCI-to-ISA bridge (PIIX3) // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI #include "pci.h" #include "pci2isa.h" #define LOG_THIS thePci2IsaBridge-> bx_piix3_c *thePci2IsaBridge = NULL; int libpci2isa_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { thePci2IsaBridge = new bx_piix3_c(); bx_devices.pluginPci2IsaBridge = thePci2IsaBridge; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePci2IsaBridge, BX_PLUGIN_PCI2ISA); return 0; // Success } else { return -1; } } void libpci2isa_LTX_plugin_fini(void) { delete thePci2IsaBridge; } bx_piix3_c::bx_piix3_c() { put("pci2isa", "P2I"); } bx_piix3_c::~bx_piix3_c() { SIM->get_bochs_root()->remove("pci2isa"); BX_DEBUG(("Exit")); } void bx_piix3_c::init(void) { unsigned i; // called once when bochs initializes Bit8u devfunc = BX_PCI_DEVICE(1,0); DEV_register_pci_handlers(this, &devfunc, BX_PLUGIN_PCI2ISA, "PIIX3 PCI-to-ISA bridge"); DEV_register_iowrite_handler(this, write_handler, 0x00B2, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_iowrite_handler(this, write_handler, 0x00B3, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_iowrite_handler(this, write_handler, 0x04D0, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_iowrite_handler(this, write_handler, 0x04D1, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_iowrite_handler(this, write_handler, 0x0CF9, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_ioread_handler(this, read_handler, 0x00B2, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_ioread_handler(this, read_handler, 0x00B3, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_ioread_handler(this, read_handler, 0x04D0, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_ioread_handler(this, read_handler, 0x04D1, "PIIX3 PCI-to-ISA bridge", 1); DEV_register_ioread_handler(this, read_handler, 0x0CF9, "PIIX3 PCI-to-ISA bridge", 1); for (i=0; i<256; i++) BX_P2I_THIS pci_conf[i] = 0x0; for (i=0; i<16; i++) BX_P2I_THIS s.irq_registry[i] = 0x0; for (i=0; i<16; i++) BX_P2I_THIS s.irq_level[i] = 0x0; // readonly registers BX_P2I_THIS pci_conf[0x00] = 0x86; BX_P2I_THIS pci_conf[0x01] = 0x80; BX_P2I_THIS pci_conf[0x02] = 0x00; BX_P2I_THIS pci_conf[0x03] = 0x70; BX_P2I_THIS pci_conf[0x04] = 0x07; BX_P2I_THIS pci_conf[0x0a] = 0x01; BX_P2I_THIS pci_conf[0x0b] = 0x06; BX_P2I_THIS pci_conf[0x0e] = 0x80; // irq routing registers BX_P2I_THIS pci_conf[0x60] = 0x80; BX_P2I_THIS pci_conf[0x61] = 0x80; BX_P2I_THIS pci_conf[0x62] = 0x80; BX_P2I_THIS pci_conf[0x63] = 0x80; #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("pci2isa", this); #endif } void bx_piix3_c::reset(unsigned type) { BX_P2I_THIS pci_conf[0x05] = 0x00; BX_P2I_THIS pci_conf[0x06] = 0x00; BX_P2I_THIS pci_conf[0x07] = 0x02; BX_P2I_THIS pci_conf[0x4c] = 0x4d; BX_P2I_THIS pci_conf[0x4e] = 0x03; BX_P2I_THIS pci_conf[0x4f] = 0x00; BX_P2I_THIS pci_conf[0x69] = 0x02; BX_P2I_THIS pci_conf[0x70] = 0x80; BX_P2I_THIS pci_conf[0x76] = 0x0c; BX_P2I_THIS pci_conf[0x77] = 0x0c; BX_P2I_THIS pci_conf[0x78] = 0x02; BX_P2I_THIS pci_conf[0x79] = 0x00; BX_P2I_THIS pci_conf[0x80] = 0x00; BX_P2I_THIS pci_conf[0x82] = 0x00; BX_P2I_THIS pci_conf[0xa0] = 0x08; BX_P2I_THIS pci_conf[0xa2] = 0x00; BX_P2I_THIS pci_conf[0xa3] = 0x00; BX_P2I_THIS pci_conf[0xa4] = 0x00; BX_P2I_THIS pci_conf[0xa5] = 0x00; BX_P2I_THIS pci_conf[0xa6] = 0x00; BX_P2I_THIS pci_conf[0xa7] = 0x00; BX_P2I_THIS pci_conf[0xa8] = 0x0f; BX_P2I_THIS pci_conf[0xaa] = 0x00; BX_P2I_THIS pci_conf[0xab] = 0x00; BX_P2I_THIS pci_conf[0xac] = 0x00; BX_P2I_THIS pci_conf[0xae] = 0x00; for (unsigned i = 0; i < 4; i++) { pci_set_irq(0x08, i+1, 0); pci_unregister_irq(i); } BX_P2I_THIS s.elcr1 = 0x00; BX_P2I_THIS s.elcr2 = 0x00; BX_P2I_THIS s.pci_reset = 0x00; BX_P2I_THIS s.apms = 0x00; BX_P2I_THIS s.apmc = 0x00; } void bx_piix3_c::register_state(void) { unsigned i; char name[6]; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "pci2isa", "PCI-to-ISA Bridge State"); register_pci_state(list); BXRS_HEX_PARAM_FIELD(list, elcr1, BX_P2I_THIS s.elcr1); BXRS_HEX_PARAM_FIELD(list, elcr2, BX_P2I_THIS s.elcr2); BXRS_HEX_PARAM_FIELD(list, apmc, BX_P2I_THIS s.apmc); BXRS_HEX_PARAM_FIELD(list, apms, BX_P2I_THIS s.apms); BXRS_HEX_PARAM_FIELD(list, pci_reset, BX_P2I_THIS s.pci_reset); bx_list_c *irqr = new bx_list_c(list, "irq_registry"); for (i=0; i<16; i++) { sprintf(name, "%d", i); new bx_shadow_num_c(irqr, name, &BX_P2I_THIS s.irq_registry[i]); } bx_list_c *irql = new bx_list_c(list, "irq_level"); for (i=0; i<16; i++) { sprintf(name, "%d", i); new bx_shadow_num_c(irql, name, &BX_P2I_THIS s.irq_level[i]); } } void bx_piix3_c::after_restore_state(void) { for (unsigned i=0; i<16; i++) { if (BX_P2I_THIS s.irq_registry[i]) { DEV_register_irq(i, "PIIX3 IRQ routing"); } } } void bx_piix3_c::pci_register_irq(unsigned pirq, unsigned irq) { if ((irq < 16) && (((1 << irq) & 0xdef8) > 0)) { if (BX_P2I_THIS pci_conf[0x60 + pirq] < 16) { pci_unregister_irq(pirq); } BX_P2I_THIS pci_conf[0x60 + pirq] = irq; if (!BX_P2I_THIS s.irq_registry[irq]) { DEV_register_irq(irq, "PIIX3 IRQ routing"); } BX_P2I_THIS s.irq_registry[irq] |= (1 << pirq); } } void bx_piix3_c::pci_unregister_irq(unsigned pirq) { Bit8u irq = BX_P2I_THIS pci_conf[0x60 + pirq]; if (irq < 16) { BX_P2I_THIS s.irq_registry[irq] &= ~(1 << pirq); if (!BX_P2I_THIS s.irq_registry[irq]) { BX_P2I_THIS pci_set_irq(0x08, pirq+1, 0); DEV_unregister_irq(irq, "PIIX3 IRQ routing"); } BX_P2I_THIS pci_conf[0x60 + pirq] = 0x80; } } void bx_piix3_c::pci_set_irq(Bit8u devfunc, unsigned line, bx_bool level) { Bit8u pirq = ((devfunc >> 3) + line - 2) & 0x03; #if BX_SUPPORT_APIC // forward this function call to the ioapic too if (DEV_ioapic_present()) { DEV_ioapic_set_irq_level(pirq + 16, level); } #endif Bit8u irq = BX_P2I_THIS pci_conf[0x60 + pirq]; if ((irq < 16) && (((1 << irq) & 0xdef8) > 0)) { if (level == 1) { if (!BX_P2I_THIS s.irq_level[irq]) { DEV_pic_raise_irq(irq); BX_DEBUG(("PIRQ%c -> IRQ %d = 1", pirq+65, irq)); } BX_P2I_THIS s.irq_level[irq] |= (1 << (devfunc >> 3)); } else { BX_P2I_THIS s.irq_level[irq] &= ~(1 << (devfunc >> 3)); if (!BX_P2I_THIS s.irq_level[irq]) { DEV_pic_lower_irq(irq); BX_DEBUG(("PIRQ%c -> IRQ %d = 0", pirq+65, irq)); } } } } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_piix3_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_P2I_SMF bx_piix3_c *class_ptr = (bx_piix3_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_piix3_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_P2I_SMF switch (address) { case 0x00b2: return(BX_P2I_THIS s.apmc); case 0x00b3: return(BX_P2I_THIS s.apms); case 0x04d0: return(BX_P2I_THIS s.elcr1); case 0x04d1: return(BX_P2I_THIS s.elcr2); case 0x0cf9: return(BX_P2I_THIS s.pci_reset); } return(0xffffffff); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_piix3_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_P2I_SMF bx_piix3_c *class_ptr = (bx_piix3_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_piix3_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_P2I_SMF switch (address) { case 0x00b2: #if BX_SUPPORT_PCI DEV_acpi_generate_smi((Bit8u)value); #else BX_ERROR(("write %08x: APM command register not supported without ACPI", value)); #endif BX_P2I_THIS s.apmc = value & 0xff; break; case 0x00b3: BX_P2I_THIS s.apms = value & 0xff; break; case 0x04d0: value &= 0xf8; if (value != BX_P2I_THIS s.elcr1) { BX_P2I_THIS s.elcr1 = value; BX_INFO(("write: ELCR1 = 0x%02x", BX_P2I_THIS s.elcr1)); DEV_pic_set_mode(1, BX_P2I_THIS s.elcr1); // master PIC } break; case 0x04d1: value &= 0xde; if (value != BX_P2I_THIS s.elcr2) { BX_P2I_THIS s.elcr2 = value; BX_INFO(("write: ELCR2 = 0x%02x", BX_P2I_THIS s.elcr2)); DEV_pic_set_mode(0, BX_P2I_THIS s.elcr2); // slave PIC } break; case 0x0cf9: BX_INFO(("write: CPU reset register = 0x%02x", value)); BX_P2I_THIS s.pci_reset = value & 0x02; if (value & 0x04) { if (BX_P2I_THIS s.pci_reset) { bx_pc_system.Reset(BX_RESET_HARDWARE); } else { bx_pc_system.Reset(BX_RESET_SOFTWARE); } } break; } } // pci configuration space read callback handler Bit32u bx_piix3_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x10) && (address < 0x34)) return; for (unsigned i=0; i> (i*8)) & 0xFF; switch (address+i) { case 0x04: case 0x06: break; case 0x60: case 0x61: case 0x62: case 0x63: if (value8 != BX_P2I_THIS pci_conf[address+i]) { if (value8 >= 0x80) { pci_unregister_irq((address+i) & 0x03); } else { pci_register_irq((address+i) & 0x03, value8); } BX_INFO(("PCI IRQ routing: PIRQ%c# set to 0x%02x", address+i-31, value8)); } break; default: BX_P2I_THIS pci_conf[address+i] = value8; BX_DEBUG(("PIIX3 PCI-to-ISA write register 0x%02x value 0x%02x", address+i, value8)); } } } #if BX_DEBUGGER void bx_piix3_c::debug_dump(int argc, char **argv) { int arg, i, j, r; dbg_printf("PIIX3 ISA bridge\n\n"); dbg_printf("ELCR1 = 0x%02x\n", BX_P2I_THIS s.elcr1); dbg_printf("ELCR2 = 0x%02x\n", BX_P2I_THIS s.elcr2); if (argc == 0) { for (i = 0; i < 4; i++) { dbg_printf("PIRQ%c# = 0x%02x", i + 65, BX_P2I_THIS pci_conf[0x60 + i]); Bit8u irq = BX_P2I_THIS pci_conf[0x60 + i]; if (irq < 16) { dbg_printf(" (level=%d)\n", BX_P2I_THIS s.irq_level[irq] > 0); } else { dbg_printf("\n"); } } dbg_printf("\nSupported options:\n"); dbg_printf("info device 'pci2isa' 'dump=full' - show PCI config space\n"); } else { for (arg = 0; arg < argc; arg++) { if (!strcmp(argv[arg], "dump=full")) { dbg_printf("\nPCI config space\n\n"); r = 0; for (i=0; i<16; i++) { dbg_printf("%04x ", r); for (j=0; j<16; j++) { dbg_printf(" %02x", BX_P2I_THIS pci_conf[r++]); } dbg_printf("\n"); } } else { dbg_printf("\nUnknown option: '%s'\n", argv[arg]); } } } } #endif #endif /* BX_SUPPORT_PCI */ bochs-2.6/iodev/sound/0000755000175000017500000000000012020641502014563 5ustar guillemguillembochs-2.6/iodev/sound/soundwin.cc0000644000175000017500000004264412020641502016752 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundwin.cc 11150 2012-04-23 18:52:11Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // This file (SOUNDWIN.CC) written and donated by Josef Drexler // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "soundmod.h" #include "soundwin.h" #if defined(WIN32) && BX_SUPPORT_SOUNDLOW #define LOG_THIS device-> bx_sound_windows_c::bx_sound_windows_c(logfunctions *dev) :bx_sound_lowlevel_c(dev) { MidiOpen = 0; WaveOutOpen = 0; WaveInOpen = 0; ismidiready = 1; iswaveready = 1; // size is the total size of the midi header and buffer and the // BX_SOUND_WINDOWS_NBUF wave header and buffers, all aligned // on a 16-byte boundary #define ALIGN(size) ((size + 15) & ~15) #define size ALIGN(sizeof(MIDIHDR)) \ + ALIGN(sizeof(WAVEHDR)) * (BX_SOUND_WINDOWS_NBUF + 1) \ + ALIGN(BX_SOUND_WINDOWS_MAXSYSEXLEN) \ + ALIGN(BX_SOUNDLOW_WAVEPACKETSIZE + 64) * (BX_SOUND_WINDOWS_NBUF + 1) DataHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size); DataPointer = (Bit8u*) GlobalLock(DataHandle); if (DataPointer == NULL) BX_PANIC(("GlobalLock returned NULL-pointer")); #define NEWBUFFER(size) &(DataPointer[offset]); offset += ALIGN(size) unsigned offset = 0; MidiHeader = (LPMIDIHDR) NEWBUFFER(sizeof(MIDIHDR)); MidiData = (LPSTR) NEWBUFFER(BX_SOUND_WINDOWS_MAXSYSEXLEN); for (int bufnum=0; bufnum size) BX_PANIC(("Allocated memory was too small!")); #undef size #undef ALIGN #undef NEWBUFFER BX_INFO(("Sound output module 'win' initialized")); } bx_sound_windows_c::~bx_sound_windows_c() { GlobalUnlock(DataHandle); GlobalFree(DataHandle); } int bx_sound_windows_c::waveready() { if (iswaveready == 0) checkwaveready(); if (iswaveready == 1) return BX_SOUNDLOW_OK; else return BX_SOUNDLOW_ERR; } int bx_sound_windows_c::midiready() { if (ismidiready == 0) checkmidiready(); if (ismidiready == 1) return BX_SOUNDLOW_OK; else return BX_SOUNDLOW_ERR; } int bx_sound_windows_c::openmidioutput(const char *mididev) { // could make the output device selectable, // but currently only the midi mapper is supported UNUSED(mididev); UINT deviceid = (UINT) MIDIMAPPER; MidiOpen = 0; UINT ret = midiOutOpen(&MidiOut, deviceid, 0, 0, CALLBACK_NULL); if (ret == 0) MidiOpen = 1; BX_DEBUG(("midiOutOpen() = %d, MidiOpen: %d", ret, MidiOpen)); return (MidiOpen == 1) ? BX_SOUNDLOW_OK : BX_SOUNDLOW_ERR; } int bx_sound_windows_c::sendmidicommand(int delta, int command, int length, Bit8u data[]) { UINT ret; if (MidiOpen != 1) return BX_SOUNDLOW_ERR; if ((command == 0xf0) || (command == 0xf7) || (length > 3)) { BX_DEBUG(("SYSEX started, length %d", length)); ismidiready = 0; // until the buffer is done memcpy(MidiData, data, length); MidiHeader->lpData = MidiData; MidiHeader->dwBufferLength = BX_SOUND_WINDOWS_MAXSYSEXLEN; MidiHeader->dwBytesRecorded = 0; MidiHeader->dwUser = 0; MidiHeader->dwFlags = 0; ret = midiOutPrepareHeader(MidiOut, MidiHeader, sizeof(*MidiHeader)); if (ret != 0) BX_ERROR(("midiOutPrepareHeader(): error = %d", ret)); ret = midiOutLongMsg(MidiOut, MidiHeader, sizeof(*MidiHeader)); if (ret != 0) BX_ERROR(("midiOutLongMsg(): error = %d", ret)); } else { DWORD msg = command; for (int i = 0; idwFlags = WHDR_DONE; head = 0; tailfull = 0; tailplay = 0; needreopen = 0; #endif return BX_SOUNDLOW_OK; } int bx_sound_windows_c::playnextbuffer() { UINT ret; PCMWAVEFORMAT waveformat; int bufnum; // if the format is different, we have to reopen the device, // so reset it first if (needreopen != 0) if (WaveOutOpen != 0) ret = waveOutReset(hWaveOut); // clean up the buffers and mark if output is ready checkwaveready(); // do we have to play anything? if (tailplay == head) return BX_SOUNDLOW_OK; // if the format is different, we have to close and reopen the device // or, just open the device if it's not open yet if ((needreopen != 0) || (WaveOutOpen == 0)) { if (WaveOutOpen != 0) { ret = waveOutClose(hWaveOut); WaveOutOpen = 0; } // try three times to find a suitable format for (int tries = 0; tries < 3; tries++) { int frequency = WaveInfo[0].frequency; bx_bool stereo = WaveInfo[0].stereo; int bits = WaveInfo[0].bits; // int format = WaveInfo[0].format; int bps = (bits / 8) * (stereo + 1); waveformat.wf.wFormatTag = WAVE_FORMAT_PCM; waveformat.wf.nChannels = stereo + 1; waveformat.wf.nSamplesPerSec = frequency; waveformat.wf.nAvgBytesPerSec = frequency * bps; waveformat.wf.nBlockAlign = bps; waveformat.wBitsPerSample = bits; ret = waveOutOpen(&(hWaveOut), WaveDevice, (LPWAVEFORMATEX)&(waveformat.wf), 0, 0, CALLBACK_NULL); if (ret != 0) { char errormsg[4*MAXERRORLENGTH+1]; waveOutGetErrorTextA(ret, errormsg, 4*MAXERRORLENGTH+1); BX_DEBUG(("waveOutOpen: %s", errormsg)); switch (tries) { case 0: // maybe try a different frequency if (frequency < 15600) frequency = 11025; else if (frequency < 31200) frequency = 22050; else frequency = 44100; BX_DEBUG(("Couldn't open wave device (error %d), trying frequency %d", ret, frequency)); break; case 1: // or something else frequency = 11025; stereo = 0; bits = 8; bps = 1; BX_DEBUG(("Couldn't open wave device again (error %d), trying 11KHz, mono, 8bit", ret)); break; case 2: // nope, doesn't work BX_ERROR(("Couldn't open wave output device (error = %d)!", ret)); return BX_SOUNDLOW_ERR; } BX_DEBUG(("The format was: wFormatTag=%d, nChannels=%d, nSamplesPerSec=%d,", waveformat.wf.wFormatTag, waveformat.wf.nChannels, waveformat.wf.nSamplesPerSec)); BX_DEBUG((" nAvgBytesPerSec=%d, nBlockAlign=%d, wBitsPerSample=%d", waveformat.wf.nAvgBytesPerSec, waveformat.wf.nBlockAlign, waveformat.wBitsPerSample)); } else { WaveOutOpen = 1; needreopen = 0; break; } } } for (bufnum=tailplay; bufnum != head; bufnum++, bufnum &= BX_SOUND_WINDOWS_NMASK, tailplay=bufnum) { BX_DEBUG(("Playing buffer %d", bufnum)); // prepare the wave header WaveHeader[bufnum]->lpData = WaveData[bufnum]; WaveHeader[bufnum]->dwBufferLength = length[bufnum]; WaveHeader[bufnum]->dwBytesRecorded = length[bufnum]; WaveHeader[bufnum]->dwUser = 0; WaveHeader[bufnum]->dwFlags = 0; WaveHeader[bufnum]->dwLoops = 1; ret = waveOutPrepareHeader(hWaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum])); if (ret != 0) { BX_ERROR(("waveOutPrepareHeader(): error = %d", ret)); return BX_SOUNDLOW_ERR; } ret = waveOutWrite(hWaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum])); if (ret != 0) { char errormsg[4*MAXERRORLENGTH+1]; waveOutGetErrorTextA(ret, errormsg, 4*MAXERRORLENGTH+1); BX_ERROR(("waveOutWrite(): %s", errormsg)); } } return BX_SOUNDLOW_OK; } int bx_sound_windows_c::startwaveplayback(int frequency, int bits, bx_bool stereo, int format) { BX_DEBUG(("startwaveplayback(%d, %d, %d, %x)", frequency, bits, stereo, format)); #ifdef usewaveOut // check if any of the properties have changed if ((WaveInfo[0].frequency != frequency) || (WaveInfo[0].bits != bits) || (WaveInfo[0].stereo != stereo) || (WaveInfo[0].format != format)) { needreopen = 1; // store the current settings to be used by sendwavepacket() WaveInfo[0].frequency = frequency; WaveInfo[0].bits = bits; WaveInfo[0].stereo = stereo; WaveInfo[0].format = format; } #endif #ifdef usesndPlaySnd int bps = (bits / 8) * (stereo + 1); LPWAVEFILEHEADER header = (LPWAVEFILEHEADER) WaveData[0]; memcpy(header->RIFF, "RIFF", 4); memcpy(header->TYPE, "WAVE", 4); memcpy(header->chnk, "fmt ", 4); header->chnklen = 16; header->waveformat.wf.wFormatTag = WAVE_FORMAT_PCM; header->waveformat.wf.nChannels = stereo + 1; header->waveformat.wf.nSamplesPerSec = frequency; header->waveformat.wf.nAvgBytesPerSec = frequency * bps; header->waveformat.wf.nBlockAlign = bps; header->waveformat.wBitsPerSample = bits; memcpy(header->chnk2, "data", 4); #endif return BX_SOUNDLOW_OK; } int bx_sound_windows_c::sendwavepacket(int length, Bit8u data[]) { #ifdef usewaveOut int bufnum; #endif #ifdef usesndPlaySnd UINT ret; #endif BX_DEBUG(("sendwavepacket(%d, %p)", length, data)); #ifdef usewaveOut bufnum = head; memcpy(WaveData[bufnum], data, length); this->length[bufnum] = length; // select next buffer to write to bufnum++; bufnum &= BX_SOUND_WINDOWS_NMASK; if (((bufnum + 1) & BX_SOUND_WINDOWS_NMASK) == tailfull) { // this should not actually happen! BX_ERROR(("Output buffer overflow! Not played. Iswaveready was %d", iswaveready)); iswaveready = 0; // stop the output for a while return BX_SOUNDLOW_ERR; } head = bufnum; // check if more buffers are available, otherwise stall the emulator if (((bufnum + 2) & BX_SOUND_WINDOWS_NMASK) == tailfull) { BX_DEBUG(("Buffer status: Head %d, TailFull %d, TailPlay %d. Stall.", head, tailfull, tailplay)); iswaveready = 0; } playnextbuffer(); #endif #ifdef usesndPlaySnd LPWAVEFILEHEADER header = (LPWAVEFILEHEADER) WaveData[0]; header->length = length + 36; header->chnk2len = length; memcpy(&(header->data), data, length); ret = sndPlaySoundA((LPCSTR) header, SND_SYNC | SND_MEMORY); if (ret != 0) { BX_DEBUG(("sndPlaySoundA: %d", ret)); } #endif return BX_SOUNDLOW_OK; } int bx_sound_windows_c::stopwaveplayback() { BX_DEBUG(("stopwaveplayback()")); #ifdef usewaveOut // this is handled by checkwaveready() when closing #endif #ifdef usesndPlaySnd sndPlaySoundA(NULL, SND_ASYNC | SND_MEMORY); WaveOpen = 0; #endif return BX_SOUNDLOW_OK; } int bx_sound_windows_c::closewaveoutput() { BX_DEBUG(("closewaveoutput")); #ifdef usewaveOut if (WaveOutOpen == 1) { waveOutReset(hWaveOut); // let checkwaveready() clean up the buffers checkwaveready(); waveOutClose(hWaveOut); head = 0; tailfull = 0; tailplay = 0; needreopen = 0; } #endif return BX_SOUNDLOW_OK; } void bx_sound_windows_c::checkmidiready() { if ((MidiHeader->dwFlags & MHDR_DONE) != 0) { BX_DEBUG(("SYSEX message done, midi ready again")); midiOutUnprepareHeader(MidiOut, MidiHeader, sizeof(*MidiHeader)); ismidiready = 1; } } void bx_sound_windows_c::checkwaveready() { int bufnum; // clean up all finished buffers and mark them as available for (bufnum=tailfull; (bufnum != tailplay) && ((WaveHeader[bufnum]->dwFlags & WHDR_DONE) != 0); bufnum++, bufnum &= BX_SOUND_WINDOWS_NMASK) { BX_DEBUG(("Buffer %d done.", bufnum)); waveOutUnprepareHeader(hWaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum])); } tailfull = bufnum; // enable gathering data if a buffer is available if (((head + 2) & BX_SOUND_WINDOWS_NMASK) != tailfull) { BX_DEBUG(("Buffer status: Head %d, TailFull %d, TailPlay %d. Ready.", head, tailfull, tailplay)); iswaveready = 1; } } int bx_sound_windows_c::openwaveinput(const char *wavedev, sound_record_handler_t rh) { UNUSED(wavedev); record_handler = rh; if (rh != NULL) { record_timer_index = bx_pc_system.register_timer(this, record_timer_handler, 1, 1, 0, "soundwin"); // record timer: inactive, continuous, frequency variable } recording = 0; return BX_SOUNDLOW_OK; } int bx_sound_windows_c::recordnextpacket() { MMRESULT result; WaveInHdr->lpData = (LPSTR)WaveInData; WaveInHdr->dwBufferLength = record_packet_size; WaveInHdr->dwBytesRecorded = 0; WaveInHdr->dwUser = 0L; WaveInHdr->dwFlags = 0L; WaveInHdr->dwLoops = 0L; waveInPrepareHeader(hWaveIn, WaveInHdr, sizeof(WAVEHDR)); result = waveInAddBuffer(hWaveIn, WaveInHdr, sizeof(WAVEHDR)); if (result) { BX_ERROR(("Couldn't add buffer for recording (error = %d)", result)); return BX_SOUNDLOW_ERR; } else { result = waveInStart(hWaveIn); if (result) { BX_ERROR(("Couldn't start recording (error = %d)", result)); return BX_SOUNDLOW_ERR; } else { recording = 1; return BX_SOUNDLOW_OK; } } } int bx_sound_windows_c::startwaverecord(int frequency, int bits, bx_bool stereo, int format) { Bit64u timer_val; Bit8u shift = 0; MMRESULT result; if (record_timer_index != BX_NULL_TIMER_HANDLE) { if (bits == 16) shift++; if (stereo) shift++; record_packet_size = (frequency / 10) << shift; // 0.1 sec if (record_packet_size > BX_SOUNDLOW_WAVEPACKETSIZE) { record_packet_size = BX_SOUNDLOW_WAVEPACKETSIZE; } timer_val = (Bit64u)record_packet_size * 1000000 / (frequency << shift); bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1); } // check if any of the properties have changed if ((WaveInfo[1].frequency != frequency) || (WaveInfo[1].bits != bits) || (WaveInfo[1].stereo != stereo) || (WaveInfo[1].format != format)) { WaveInfo[1].frequency = frequency; WaveInfo[1].bits = bits; WaveInfo[1].stereo = stereo; WaveInfo[1].format = format; if (WaveInOpen) { waveInClose(hWaveIn); } // Specify recording parameters WAVEFORMATEX pFormat; pFormat.wFormatTag = WAVE_FORMAT_PCM; pFormat.nChannels = 1 << stereo; pFormat.nSamplesPerSec = frequency; pFormat.nAvgBytesPerSec = frequency << shift; pFormat.nBlockAlign = 1 << shift; pFormat.wBitsPerSample = bits; pFormat.cbSize = 0; result = waveInOpen(&hWaveIn, WAVEMAPPER, &pFormat, 0L, 0L, WAVE_FORMAT_DIRECT); if (result) { BX_ERROR(("Couldn't open wave device for recording (error = %d)", result)); return BX_SOUNDLOW_ERR; } else { WaveInOpen = 1; } } return recordnextpacket(); } int bx_sound_windows_c::getwavepacket(int length, Bit8u data[]) { if (WaveInOpen && recording) { do {} while (waveInUnprepareHeader(hWaveIn, WaveInHdr, sizeof(WAVEHDR)) == WAVERR_STILLPLAYING); memcpy(data, WaveInData, length); return recordnextpacket(); } else { memset(data, 0, length); return BX_SOUNDLOW_OK; } } int bx_sound_windows_c::stopwaverecord() { if (record_timer_index != BX_NULL_TIMER_HANDLE) { bx_pc_system.deactivate_timer(record_timer_index); } if (WaveInOpen && recording) { do {} while (waveInUnprepareHeader(hWaveIn, WaveInHdr, sizeof(WAVEHDR)) == WAVERR_STILLPLAYING); recording = 0; } return BX_SOUNDLOW_OK; } int bx_sound_windows_c::closewaveinput() { stopwaverecord(); if (WaveInOpen) { waveInClose(hWaveIn); } return BX_SOUNDLOW_OK; } void bx_sound_windows_c::record_timer_handler(void *this_ptr) { bx_sound_windows_c *class_ptr = (bx_sound_windows_c *) this_ptr; class_ptr->record_timer(); } void bx_sound_windows_c::record_timer(void) { record_handler(this->device, record_packet_size); } #endif // defined(WIN32) bochs-2.6/iodev/sound/sb16.cc0000644000175000017500000033114012020641502015647 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: sb16.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // The original version of the SB16 support written and donated by Josef Drexler // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_SB16 #include "sb16.h" #include "soundmod.h" #include "soundlnx.h" #include "soundwin.h" #include "soundosx.h" #include "soundsdl.h" #define LOG_THIS theSB16Device-> bx_sb16_c *theSB16Device = NULL; // builtin configuration handling functions void sb16_init_options(void) { bx_param_c *sound = SIM->get_param("sound"); bx_list_c *menu = new bx_list_c(sound, "sb16", "SB16 Configuration"); menu->set_options(menu->SHOW_PARENT); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", "Enable SB16 emulation", "Enables the SB16 emulation", 0); bx_param_num_c *midimode = new bx_param_num_c(menu, "midimode", "Midi mode", "Controls the MIDI output format.", 0, 3, 0); bx_param_filename_c *midifile = new bx_param_filename_c(menu, "midifile", "MIDI file", "The filename is where the MIDI data is sent. This can be device or just a file.", "", BX_PATHNAME_LEN); bx_param_num_c *wavemode = new bx_param_num_c(menu, "wavemode", "Wave mode", "Controls the wave output format.", 0, 3, 0); bx_param_filename_c *wavefile = new bx_param_filename_c(menu, "wavefile", "Wave file", "This is the device/file where the wave output is stored", "", BX_PATHNAME_LEN); bx_param_num_c *loglevel = new bx_param_num_c(menu, "loglevel", "Log level", "Controls how verbose the SB16 emulation is (0 = no log, 5 = all errors and infos).", 0, 5, 0); bx_param_filename_c *logfile = new bx_param_filename_c(menu, "logfile", "Log file", "The file to write the SB16 emulator messages to.", "", BX_PATHNAME_LEN); logfile->set_extension("log"); bx_param_num_c *dmatimer = new bx_param_num_c(menu, "dmatimer", "DMA timer", "Microseconds per second for a DMA cycle.", 0, BX_MAX_BIT32U, 0); midimode->set_options(midimode->USE_SPIN_CONTROL); wavemode->set_options(wavemode->USE_SPIN_CONTROL); loglevel->set_options(loglevel->USE_SPIN_CONTROL); loglevel->set_group("SB16"); dmatimer->set_group("SB16"); bx_list_c *deplist = new bx_list_c(NULL); deplist->add(midimode); deplist->add(wavemode); deplist->add(loglevel); deplist->add(dmatimer); enabled->set_dependent_list(deplist); deplist = new bx_list_c(NULL); deplist->add(midifile); midimode->set_dependent_list(deplist); deplist = new bx_list_c(NULL); deplist->add(wavefile); wavemode->set_dependent_list(deplist); deplist = new bx_list_c(NULL); deplist->add(logfile); loglevel->set_dependent_list(deplist); } Bit32s sb16_options_parser(const char *context, int num_params, char *params[]) { if (!strcmp(params[0], "sb16")) { int enable = 1; bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16); for (int i = 1; i < num_params; i++) { if (!strncmp(params[i], "enabled=", 8)) { enable = atol(¶ms[i][8]); } else if (!strncmp(params[i], "midi=", 5)) { SIM->get_param_string("midifile", base)->set(¶ms[i][5]); } else if (!strncmp(params[i], "midimode=", 9)) { SIM->get_param_num("midimode", base)->set(atol(¶ms[i][9])); } else if (!strncmp(params[i], "wave=", 5)) { SIM->get_param_string("wavefile", base)->set(¶ms[i][5]); } else if (!strncmp(params[i], "wavemode=", 9)) { SIM->get_param_num("wavemode", base)->set(atol(¶ms[i][9])); } else if (!strncmp(params[i], "log=", 4)) { SIM->get_param_string("logfile", base)->set(¶ms[i][4]); } else if (!strncmp(params[i], "loglevel=", 9)) { SIM->get_param_num("loglevel", base)->set(atol(¶ms[i][9])); } else if (!strncmp(params[i], "dmatimer=", 9)) { SIM->get_param_num("dmatimer", base)->set(atol(¶ms[i][9])); } else { BX_ERROR(("%s: unknown parameter for sb16 ignored.", context)); } } if ((enable != 0) && (SIM->get_param_num("dmatimer", base)->get() > 0)) SIM->get_param_bool("enabled", base)->set(1); else SIM->get_param_bool("enabled", base)->set(0); } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s sb16_options_save(FILE *fp) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16); fprintf(fp, "sb16: enabled=%d", SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { fprintf(fp, ", midimode=%d, midi=%s, wavemode=%d, wave=%s, loglevel=%d, log=%s, dmatimer=%d", SIM->get_param_num("midimode", base)->get(), SIM->get_param_string("midifile", base)->getptr(), SIM->get_param_num("wavemode", base)->get(), SIM->get_param_string("wavefile", base)->getptr(), SIM->get_param_num("loglevel", base)->get(), SIM->get_param_string("logfile", base)->getptr(), SIM->get_param_num("dmatimer", base)->get()); } fprintf(fp, "\n"); return 0; } // device plugin entry points int libsb16_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theSB16Device = new bx_sb16_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSB16Device, BX_PLUGIN_SB16); // add new configuration parameter for the config interface sb16_init_options(); // register add-on option for bochsrc and command line SIM->register_addon_option("sb16", sb16_options_parser, sb16_options_save); return(0); // Success } void libsb16_LTX_plugin_fini(void) { delete theSB16Device; SIM->unregister_addon_option("sb16"); ((bx_list_c*)SIM->get_param("sound"))->remove("sb16"); } // some shortcuts to save typing #define LOGFILE BX_SB16_THIS logfile #define MIDIDATA BX_SB16_THIS midifile #define WAVEDATA BX_SB16_THIS wavefile #define MPU BX_SB16_THIS mpu401 #define DSP BX_SB16_THIS dsp #define MIXER BX_SB16_THIS mixer #define EMUL BX_SB16_THIS emuldata #define OPL BX_SB16_THIS opl #define BX_SB16_OUTPUT BX_SB16_THIS soundmod // here's a safe way to print out null pointeres #define MIGHT_BE_NULL(x) ((x==NULL)? "(null)" : x) // the device object bx_sb16_c::bx_sb16_c(void) { put("SB16"); memset(&mpu401, 0, sizeof(mpu401)); memset(&dsp, 0, sizeof(dsp)); memset(&opl, 0, sizeof(opl)); currentdma8 = 0; currentdma16 = 0; mpu401.timer_handle = BX_NULL_TIMER_HANDLE; dsp.timer_handle = BX_NULL_TIMER_HANDLE; opl.timer_handle = BX_NULL_TIMER_HANDLE; soundmod = NULL; midimode = 0; midifile = NULL; wavemode = 0; wavefile = NULL; loglevel = 0; logfile = NULL; } bx_sb16_c::~bx_sb16_c(void) { switch (midimode) { case 2: if (MIDIDATA != NULL) finishmidifile(); break; case 1: if (MPU.outputinit != 0) BX_SB16_OUTPUT->closemidioutput(); break; case 3: if (MIDIDATA != NULL) fclose(MIDIDATA); break; } switch (wavemode) { case 2: if (WAVEDATA != NULL) finishvocfile(); break; case 1: if (DSP.outputinit != 0) BX_SB16_OUTPUT->closewaveoutput(); if (DSP.inputinit != 0) BX_SB16_OUTPUT->closewaveinput(); break; case 3: if (WAVEDATA != NULL) fclose(WAVEDATA); break; } delete(BX_SB16_OUTPUT); delete [] DSP.dma.chunk; if ((SIM->get_param_num(BXPN_SB16_LOGLEVEL)->get() > 0) && LOGFILE) fclose(LOGFILE); SIM->get_bochs_root()->remove("sb16"); BX_DEBUG(("Exit")); } void bx_sb16_c::init(void) { unsigned addr, i; // Read in values from config interface bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", base)->get()) { BX_INFO(("SB16 disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("sb16"))->set(0); return; } if ((strlen(SIM->get_param_string("logfile", base)->getptr()) < 1)) SIM->get_param_num("loglevel", base)->set(0); if (SIM->get_param_num("loglevel", base)->get() > 0) { LOGFILE = fopen(SIM->get_param_string("logfile", base)->getptr(),"w"); // logfile for errors etc. if (LOGFILE == NULL) { BX_ERROR(("Error opening file %s. Logging disabled.", SIM->get_param_string("logfile", base)->getptr())); SIM->get_param_num("loglevel", base)->set(0); } } BX_SB16_THIS midimode = SIM->get_param_num("midimode", base)->get(); BX_SB16_THIS wavemode = SIM->get_param_num("wavemode", base)->get(); BX_SB16_THIS dmatimer = SIM->get_param_num("dmatimer", base)->get(); BX_SB16_THIS loglevel = SIM->get_param_num("loglevel", base)->get(); char *wavefile = SIM->get_param_string(BXPN_SB16_WAVEFILE)->getptr(); if ((BX_SB16_THIS wavemode == 1) || (BX_SB16_THIS midimode == 1)) { // let the output functions initialize if (!strcmp(wavefile, "sdl")) { BX_SB16_OUTPUT = DEV_sound_init_module("sdl", BX_SB16_THISP); } else { BX_SB16_OUTPUT = DEV_sound_init_module("default", BX_SB16_THISP); } if (BX_SB16_OUTPUT == NULL) { writelog(MIDILOG(2), "Couldn't initialize output devices. Output disabled."); BX_SB16_THIS midimode = 0; BX_SB16_THIS wavemode = 0; } } DSP.dma.chunk = new Bit8u[BX_SOUNDLOW_WAVEPACKETSIZE]; DSP.dma.chunkindex = 0; if (BX_SB16_THIS wavemode == 1) { int ret = BX_SB16_OUTPUT->openwaveoutput(wavefile); if (ret != BX_SOUNDLOW_OK) { writelog(WAVELOG(2), "Error: Could not open wave output device."); BX_SB16_THIS wavemode = 0; DSP.outputinit = 0; } else { DSP.outputinit = 1; } } DSP.inputinit = 0; MPU.outputinit = 0; if (DSP.dma.chunk == NULL) { writelog(WAVELOG(2), "Couldn't allocate wave buffer - wave output disabled."); BX_SB16_THIS wavemode = 0; } BX_INFO(("midi=%d,%s wave=%d,%s log=%d,%s dmatimer=%d", BX_SB16_THIS midimode, MIGHT_BE_NULL(SIM->get_param_string("midifile", base)->getptr()), BX_SB16_THIS wavemode, MIGHT_BE_NULL(SIM->get_param_string("wavefile", base)->getptr()), BX_SB16_THIS loglevel, MIGHT_BE_NULL(SIM->get_param_string("logfile", base)->getptr()), BX_SB16_THIS dmatimer)); // allocate the FIFO buffers - except for the MPUMIDICMD buffer // these sizes are generous, 16 or 8 would probably be sufficient MPU.datain.init((int) 64); // the input MPU.dataout.init((int) 64); // and output MPU.cmd.init((int) 64); // and command buffers MPU.midicmd.init((int) 256); // and the midi command buffer (note- large SYSEX'es have to fit!) DSP.datain.init((int) 64); // the DSP input DSP.dataout.init((int) 64); // and output buffers EMUL.datain.init((int) 64); // the emulator ports EMUL.dataout.init((int) 64); // for changing emulator settings // reset all parts of the hardware by // triggering their reset functions // reset the Emulator port emul_write(0x00); // reset the MPU401 mpu_command(0xff); MPU.last_delta_time = 0xffffffff; // reset the DSP DSP.dma.highspeed = 0; DSP.dma.mode = 0; DSP.irqpending = 0; DSP.midiuartmode = 0; DSP.resetport = 1; // so that one call to dsp_reset is sufficient dsp_reset(0); // (reset is 1 to 0 transition) DSP.testreg = 0; BX_SB16_IRQ = -1; // will be initialized later by the mixer reset for (i=0; iget_param(BXPN_MENU_RUNTIME_MISC); misc_rt->add(SIM->get_param(BXPN_SB16_DMATIMER)); misc_rt->add(SIM->get_param(BXPN_SB16_LOGLEVEL)); SIM->get_param_num(BXPN_SB16_DMATIMER)->set_handler(sb16_param_handler); SIM->get_param_num(BXPN_SB16_DMATIMER)->set_runtime_param(1); SIM->get_param_num(BXPN_SB16_LOGLEVEL)->set_handler(sb16_param_handler); SIM->get_param_num(BXPN_SB16_LOGLEVEL)->set_runtime_param(1); } void bx_sb16_c::reset(unsigned type) { } void bx_sb16_c::register_state(void) { unsigned i, j; char name[8]; bx_list_c *chip, *ins_map, *item, *patch; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "sb16", "SB16 State"); bx_list_c *mpu = new bx_list_c(list, "mpu"); new bx_shadow_bool_c(mpu, "uartmode", &MPU.uartmode); new bx_shadow_bool_c(mpu, "irqpending", &MPU.irqpending); new bx_shadow_bool_c(mpu, "forceuartmode", &MPU.forceuartmode); new bx_shadow_bool_c(mpu, "singlecommand", &MPU.singlecommand); new bx_shadow_bool_c(mpu, "outputinit", &MPU.outputinit); new bx_shadow_num_c(mpu, "current_timer", &MPU.current_timer); new bx_shadow_num_c(mpu, "last_delta_time", &MPU.last_delta_time); bx_list_c *patchtbl = new bx_list_c(mpu, "patchtable"); for (i=0; impu401.current_timer++; } void bx_sb16_c::dsp_dmatimer(void *this_ptr) { bx_sb16_c *This = (bx_sb16_c *) this_ptr; // raise the DRQ line. It is then lowered by the dma read / write functions // when the next byte has been sent / received. // However, don't do this if the next byte/word will fill up the // output buffer and the output functions are not ready yet // or if buffer is empty in input mode. if ((BX_SB16_THIS wavemode != 1) || ((This->dsp.dma.chunkindex + 1 < BX_SOUNDLOW_WAVEPACKETSIZE) && (This->dsp.dma.count > 0)) || (BX_SB16_OUTPUT->waveready() == BX_SOUNDLOW_OK)) { if (((This->dsp.dma.output == 0) && (This->dsp.dma.chunkcount > 0)) || (This->dsp.dma.output == 1)) { if ((DSP.dma.bits == 8) || (BX_SB16_DMAH == 0)) { DEV_dma_set_drq(BX_SB16_DMAL, 1); } else { DEV_dma_set_drq(BX_SB16_DMAH, 1); } } } } void bx_sb16_c::opl_timer (void *this_ptr) { ((bx_sb16_c *) this_ptr)->opl_timerevent(); } // the various IO handlers // The DSP/FM music part // dsp_reset() resets the DSP after the sequence 1/0. Returns // 0xaa on the data port void bx_sb16_c::dsp_reset(Bit32u value) { writelog(WAVELOG(4), "DSP Reset port write value %x", value); // just abort high speed mode if it is set if (DSP.dma.highspeed != 0) { DSP.dma.highspeed = 0; writelog(WAVELOG(4), "High speed mode aborted"); return; } if ((DSP.resetport == 1) && (value == 0)) { // 1-0 sequences to reset port, do one of the following: // if in UART MIDI mode, abort it, don't reset // if in Highspeed mode (not SB16!), abort it, don't reset // otherwise reset if (DSP.midiuartmode != 0) { // abort UART MIDI mode DSP.midiuartmode = 0; writelog(MIDILOG(4), "DSP UART MIDI mode aborted"); return; } // do the reset writelog(WAVELOG(4), "DSP resetting..."); if (DSP.irqpending != 0) { DEV_pic_lower_irq(BX_SB16_IRQ); writelog(WAVELOG(4), "DSP reset: IRQ untriggered"); } if (DSP.dma.mode != 0) { writelog(WAVELOG(4), "DSP reset: DMA aborted"); DSP.dma.mode = 1; // no auto init anymore dsp_dmadone(); } DSP.resetport = 0; DSP.speaker = 0; DSP.irqpending = 0; DSP.midiuartmode = 0; DSP.prostereo = 0; DSP.dma.mode = 0; DSP.dma.fifo = 0; DSP.dma.output = 0; DSP.dma.stereo = 0; DSP.dma.issigned = 0; DSP.dma.count = 0; DSP.dma.highspeed = 0; DSP.dma.chunkindex = 0; DSP.dataout.reset(); // clear the buffers DSP.datain.reset(); DSP.dataout.put(0xaa); // acknowledge the reset } else DSP.resetport = value; } // dsp_dataread() reads the data port of the DSP Bit32u bx_sb16_c::dsp_dataread() { Bit8u value = 0xff; // if we are in MIDI UART mode, call the mpu401 part instead if (DSP.midiuartmode != 0) value = mpu_dataread(); else { // default behaviour: if none available, return last byte again // if (DSP.dataout.empty() == 0) DSP.dataout.get(&value); } writelog(WAVELOG(4), "DSP Data port read, result = %x", value); return(value); } // dsp_datawrite() writes a command or data byte to the data port void bx_sb16_c::dsp_datawrite(Bit32u value) { int bytesneeded; Bit8u index = 0, mode = 0, value8 = 0; Bit16u length = 0; writelog(WAVELOG(4), "DSP Data port write, value %x", value); // in high speed mode, any data passed to DSP is a sample if (DSP.dma.highspeed != 0) { dsp_getsamplebyte(value); return; } // route information to mpu401 part if in MIDI UART mode if (DSP.midiuartmode != 0) { mpu_datawrite(value); return; } if (DSP.datain.hascommand() == 1) // already a command pending, add to argument list { if (DSP.datain.put(value) == 0) { writelog(WAVELOG(3), "DSP command buffer overflow for command %02x", DSP.datain.currentcommand()); } } else // no command pending, set one up { bytesneeded = 0; // find out how many arguments the command takes switch (value) { // all fallbacks intended! case 0x04: case 0x0f: case 0x10: case 0x40: case 0x38: case 0xe0: case 0xe4: case 0xf9: bytesneeded = 1; break; case 0x05: case 0x0e: case 0x14: case 0x16: case 0x17: case 0x41: case 0x42: case 0x48: case 0x74: case 0x75: case 0x76: case 0x77: case 0x80: bytesneeded = 2; break; // 0xb0 ... 0xbf: case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: // 0xc0 ... 0xcf: case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: bytesneeded = 3; break; } DSP.datain.newcommand(value, bytesneeded); } if (DSP.datain.commanddone() == 1) // command is complete, process it { writelog(WAVELOG(4), "DSP command %x with %d arg bytes", DSP.datain.currentcommand(), DSP.datain.bytes()); switch (DSP.datain.currentcommand()) { // DSP commands - comments are the parameters for // this command, and/or the output // ASP commands (Advanced Signal Processor) // undocumented (?), just from looking what an SB16 does case 0x04: DSP.datain.get(&value8); break; case 0x05: DSP.datain.get(&value8); DSP.datain.get(&value8); break; case 0x0e: DSP.datain.get(&index); DSP.datain.get(&value8); BX_SB16_THIS csp_reg[index] = value; break; case 0x0f: DSP.datain.get(&index); DSP.dataout.put(BX_SB16_THIS csp_reg[index]); break; // direct mode DAC case 0x10: // 1: 8bit sample DSP.datain.get(&value8); // sample is ignored break; // uncomp'd, normal DAC DMA case 0x14: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc0, 0x00, length, 0); break; // 2-bit comp'd, normal DAC DMA, no ref byte case 0x16: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc0, 0x00, length, 2); break; // 2-bit comp'd, normal DAC DMA, 1 ref byte case 0x17: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc0, 0x00, length, 2|8); break; // uncomp'd, auto DAC DMA case 0x1c: // none dsp_dma(0xc4, 0x00, DSP.dma.blocklength, 0); break; // 2-bit comp'd, auto DAC DMA, 1 ref byte case 0x1f: // none dsp_dma(0xc4, 0x00, DSP.dma.blocklength, 2|8); break; // direct mode ADC case 0x20: // o1: 8bit sample DSP.dataout.put(0x80); // put a silence, for now. break; // uncomp'd, normal ADC DMA case 0x24: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc8, 0x00, length, 0); break; // uncomp'd, auto ADC DMA case 0x2c: // none dsp_dma(0xcc, 0x00, DSP.dma.blocklength, 0); break; // ? polling mode MIDI input case 0x30: break; // ? interrupt mode MIDI input case 0x31: break; // 0x34..0x37: UART mode MIDI output case 0x34: // UART mode MIDI input/output case 0x35: // UART polling mode MIDI IO with time stamp case 0x36: // UART interrupt mode MIDI IO with time stamp case 0x37: // Fallbacks intended - all set the midi uart mode DSP.midiuartmode = 1; break; // MIDI output case 0x38: DSP.datain.get(&value8); // route to mpu401 part mpu_datawrite(value8); break; // set time constant case 0x40: // 1: timeconstant DSP.datain.get(&value8); DSP.dma.timeconstant = value8 << 8; DSP.dma.samplerate = (Bit32u) 256000000L / ((Bit32u) 65536L - (Bit32u) DSP.dma.timeconstant); break; // set samplerate for input case 0x41: // (fallback intended) // set samplerate for output case 0x42: // 1,2: hi(frq) lo(frq) DSP.datain.getw1(&(DSP.dma.samplerate)); DSP.dma.timeconstant = 65536 - (Bit32u) 256000000 / (Bit32u) DSP.dma.samplerate; break; // set block length case 0x48: // 1,2: lo(blk len) hi(blk len) DSP.datain.getw(&(DSP.dma.blocklength)); break; // 4-bit comp'd, normal DAC DMA, no ref byte case 0x74: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc0, 0x00, length, 4); break; // 4-bit comp'd, normal DAC DMA, 1 ref byte case 0x75: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc0, 0x00, length, 4|8); break; // 3-bit comp'd, normal DAC DMA, no ref byte case 0x76: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc0, 0x00, length, 3); break; // 3-bit comp'd, normal DAC DMA, 1 ref byte case 0x77: // 1,2: lo(length) hi(length) DSP.datain.getw(&length); dsp_dma(0xc0, 0x00, length, 3|8); break; // 4-bit comp'd, auto DAC DMA, 1 ref byte case 0x7d: // none dsp_dma(0xc4, 0x00, DSP.dma.blocklength, 4|8); break; // 3-bit comp'd, auto DAC DMA, 1 ref byte case 0x7f: // none dsp_dma(0xc4, 0x00, DSP.dma.blocklength, 3|8); break; // silence period case 0x80: // 1,2: lo(silence) hi(silence) (len in samples) DSP.datain.getw(&length); // only handled for VOC output so far if (BX_SB16_THIS wavemode == 2) { Bit8u temparray[3] = { length & 0xff, length >> 8, DSP.dma.timeconstant >> 8 }; writevocblock(3, 3, temparray, 0, NULL); } break; // 8-bit auto DAC DMA, highspeed case 0x90: //none dsp_dma(0xc4, 0x00, DSP.dma.blocklength, 16); break; // 8-bit normal DAC DMA, highspeed case 0x91: //none dsp_dma(0xc0, 0x00, DSP.dma.blocklength, 16); break; // 8-bit auto ADC DMA, highspeed case 0x98: //none dsp_dma(0xcc, 0x00, DSP.dma.blocklength, 16); break; case 0x99: // 8-bit normal DMA //none dsp_dma(0xc8, 0x00, DSP.dma.blocklength, 16); break; // switch to mono for SBPro DAC/ADC case 0xa0: // none DSP.prostereo = 1; break; // switch to stereo for SBPro DAC/ADC case 0xa8: //// none DSP.prostereo = 2; break; // 0xb0 ... 0xbf: // 16 bit DAC/ADC DMA, general commands // fallback intended case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: // 0xc0 ... 0xcf: // 8 bit DAC/ADC DMA, general commands case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: DSP.datain.get(&mode); DSP.datain.getw(&length); dsp_dma(DSP.datain.currentcommand(), mode, length, 0); break; // pause 8 bit DMA transfer case 0xd0: // none if (DSP.dma.mode != 0) dsp_disabledma(); break; // speaker on case 0xd1: // none DSP.speaker = 1; break; // speaker off case 0xd3: // none DSP.speaker = 0; break; // continue 8 bit DMA, see 0xd0 case 0xd4: // none if (DSP.dma.mode != 0) dsp_enabledma(); break; // pause 16 bit DMA case 0xd5: // none if (DSP.dma.mode != 0) dsp_disabledma(); break; // continue 16 bit DMA, see 0xd5 case 0xd6: // none if (DSP.dma.mode != 0) dsp_enabledma(); break; // read speaker on/off (out ff=on, 00=off) case 0xd8: // none, o1: speaker; ff/00 DSP.dataout.put((DSP.speaker == 1)?0xff:0x00); break; // stop 16 bit auto DMA case 0xd9: // none if (DSP.dma.mode != 0) { DSP.dma.mode = 1; // no auto init anymore dsp_dmadone(); } break; // stop 8 bit auto DMA case 0xda: // none if (DSP.dma.mode != 0) { DSP.dma.mode = 1; // no auto init anymore dsp_dmadone(); } break; // DSP identification case 0xe0: DSP.datain.get(&value8); DSP.dataout.put(~value8); break; // get version, out 2 bytes (major, minor) case 0xe1: // none, o1/2: version major.minor DSP.dataout.put(4); if (DSP.dataout.put(5) == 0) { writelog(WAVELOG(3), "DSP version couldn't be written - buffer overflow"); } break; case 0xe3: // none, output: Copyright string // the Windows driver needs the exact text, otherwise it // won't load. Same for diagnose.exe DSP.dataout.puts("COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992."); DSP.dataout.put(0); // need extra string end break; // write test register case 0xe4: DSP.datain.get(&DSP.testreg); break; // read test register case 0xe8: DSP.dataout.put(DSP.testreg); break; // Trigger 8-bit IRQ case 0xf2: DSP.dataout.put(0xaa); DSP.irqpending = 1; MIXER.reg[0x82] |= 1; // reg 82 shows the kind of IRQ DEV_pic_raise_irq(BX_SB16_IRQ); break; // ??? - Win98 needs this case 0xf9: DSP.datain.get(&value8); switch (value8) { case 0x0e: DSP.dataout.put(0xff); break; case 0x0f: DSP.dataout.put(0x07); break; case 0x37: DSP.dataout.put(0x38); break; default: DSP.dataout.put(0x00); } break; // unknown command default: writelog(WAVELOG(3), "unknown DSP command %x, ignored", DSP.datain.currentcommand()); break; } DSP.datain.clearcommand(); DSP.datain.flush(); } } // dsp_dma() initiates all kinds of dma transfers void bx_sb16_c::dsp_dma(Bit8u command, Bit8u mode, Bit16u length, Bit8u comp) { int ret; bx_list_c *base; // command: 8bit, 16bit, in/out, single/auto, fifo // mode: mono/stereo, signed/unsigned // (for info on command and mode see sound blaster programmer's manual, // cmds bx and cx) // length: number of samples - not number of bytes // comp: bit-coded are: type of compression; ref-byte; highspeed // D0..D2: 0=none, 2,3,4 bits ADPCM // D3: ref-byte // D6: highspeed writelog(WAVELOG(4), "DMA initialized. Cmd %02x, mode %02x, length %d, comp %d", command, mode, length, comp); if ((command >> 4) == 0xb) // 0xb? = 16 bit DMA { DSP.dma.bits = 16; DSP.dma.bps = 2; } else // 0xc? = 8 bit DMA { DSP.dma.bits = 8; DSP.dma.bps = 1; } // Prevent division by zero in some instances if (DSP.dma.samplerate == 0) DSP.dma.samplerate= 10752; command &= 0x0f; DSP.dma.output = 1 - (command >> 3); // 1=output, 0=input DSP.dma.mode = 1 + ((command >> 2) & 1); // 0=none, 1=normal, 2=auto DSP.dma.fifo = (command >> 1) & 1; // ? not sure what this is DSP.dma.stereo = (mode >> 5) & 1; if (DSP.dma.stereo != 0) DSP.dma.bps *= 2; DSP.dma.blocklength = length; DSP.dma.issigned = (mode >> 4) & 1; DSP.dma.highspeed = (comp >> 4) & 1; DSP.dma.chunkindex = 0; DSP.dma.chunkcount = 0; Bit32u sampledatarate = (Bit32u) DSP.dma.samplerate * (Bit32u) DSP.dma.bps; if ((DSP.dma.bits == 16) && (BX_SB16_DMAH != 0)) { DSP.dma.count = (DSP.dma.blocklength + 1) * (DSP.dma.bps / 2) - 1; DSP.dma.timer = BX_SB16_THIS dmatimer / (sampledatarate / 2) * BX_DMA_BUFFER_SIZE; } else { DSP.dma.count = (DSP.dma.blocklength + 1) * DSP.dma.bps - 1; DSP.dma.timer = BX_SB16_THIS dmatimer / sampledatarate * BX_DMA_BUFFER_SIZE; } writelog(WAVELOG(5), "DMA is %db, %dHz, %s, %s, mode %d, %s, %s, %d bps, %d usec/DMA", DSP.dma.bits, DSP.dma.samplerate, (DSP.dma.stereo != 0)?"stereo":"mono", (DSP.dma.output == 1)?"output":"input", DSP.dma.mode, (DSP.dma.issigned == 1)?"signed":"unsigned", (DSP.dma.highspeed == 1)?"highspeed":"normal speed", sampledatarate, DSP.dma.timer); DSP.dma.format = DSP.dma.issigned | ((comp & 7) << 1) | ((comp & 8) << 4); // write the output to the device/file if (DSP.dma.output == 1) { if (BX_SB16_THIS wavemode == 1) { if (DSP.outputinit == 1) { ret = BX_SB16_OUTPUT->startwaveplayback(DSP.dma.samplerate, DSP.dma.bits, DSP.dma.stereo, DSP.dma.format); if (ret != BX_SOUNDLOW_OK) { BX_SB16_THIS wavemode = 0; writelog(WAVELOG(2), "Error: Could not start wave playback."); } } } else if ((BX_SB16_THIS wavemode == 2) || (BX_SB16_THIS wavemode == 3)) { base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16); WAVEDATA = fopen(SIM->get_param_string("wavefile", base)->getptr(),"wb"); if (WAVEDATA == NULL) { writelog (WAVELOG(2), "Error opening file %s. Wavemode disabled.", SIM->get_param_string("wavefile", base)->getptr()); BX_SB16_THIS wavemode = 0; } else if (BX_SB16_THIS wavemode == 2) { initvocfile(); } } DSP.dma.chunkcount = sampledatarate / 10; // 0.1 sec if (DSP.dma.chunkcount > BX_SOUNDLOW_WAVEPACKETSIZE) { DSP.dma.chunkcount = BX_SOUNDLOW_WAVEPACKETSIZE; } } else { if (BX_SB16_THIS wavemode == 1) { if (DSP.inputinit == 0) { ret = BX_SB16_OUTPUT->openwaveinput(SIM->get_param_string(BXPN_SB16_WAVEFILE)->getptr(), sb16_adc_handler); if (ret != BX_SOUNDLOW_OK) { BX_SB16_THIS wavemode = 0; writelog(WAVELOG(2), "Error: Could not open wave input device."); } else { DSP.inputinit = 1; } } if (DSP.inputinit == 1) { ret = BX_SB16_OUTPUT->startwaverecord(DSP.dma.samplerate, DSP.dma.bits, DSP.dma.stereo, DSP.dma.format); if (ret != BX_SOUNDLOW_OK) { BX_SB16_THIS wavemode = 0; writelog(WAVELOG(2), "Error: Could not start wave record."); } } } DSP.dma.chunkcount = 0; } dsp_enabledma(); } Bit32u bx_sb16_c::sb16_adc_handler(void *this_ptr, Bit32u buflen) { bx_sb16_c *class_ptr = (bx_sb16_c*)this_ptr; class_ptr->dsp_adc_handler(buflen); return 0; } Bit32u bx_sb16_c::dsp_adc_handler(Bit32u buflen) { Bit32u len; len = DSP.dma.chunkcount - DSP.dma.chunkindex; if (len > 0) { memcpy(DSP.dma.chunk, DSP.dma.chunk+DSP.dma.chunkindex, len); DSP.dma.chunkcount = len; } DSP.dma.chunkindex = 0; if ((DSP.dma.chunkcount + buflen) > BX_SOUNDLOW_WAVEPACKETSIZE) { DSP.dma.chunkcount = BX_SOUNDLOW_WAVEPACKETSIZE; len = DSP.dma.chunkcount + buflen - BX_SOUNDLOW_WAVEPACKETSIZE; BX_DEBUG(("dsp_adc_handler(): unhandled len=%d", len)); } else { DSP.dma.chunkcount += buflen; len = 0; } BX_SB16_OUTPUT->getwavepacket(DSP.dma.chunkcount, DSP.dma.chunk); return len; } // dsp_enabledma(): Start the DMA timer and thus the transfer void bx_sb16_c::dsp_enabledma() { bx_pc_system.activate_timer(DSP.timer_handle, DSP.dma.timer, 1); } // dsp_disabledma(): Stop the DMA timer and thus the transfer, but don't abort it void bx_sb16_c::dsp_disabledma() { bx_pc_system.deactivate_timer(DSP.timer_handle); } // dsp_bufferstatus() checks if the DSP is ready for data/commands Bit32u bx_sb16_c::dsp_bufferstatus() { Bit32u result = 0x7f; // MSB set -> not ready for commands if (DSP.datain.full() == 1) result |= 0x80; writelog(WAVELOG(4), "DSP Buffer status read, result %x", result); return(result); } // dsp_status() checks if the DSP is ready to send data Bit32u bx_sb16_c::dsp_status() { Bit32u result = 0x7f; // read might be to acknowledge IRQ if (DSP.irqpending != 0) { MIXER.reg[0x82] &= (~0x01); writelog(WAVELOG(4), "8-bit DMA or SBMIDI IRQ acknowledged"); if ((MIXER.reg[0x82] & 0x07) == 0) { DSP.irqpending = 0; DEV_pic_lower_irq(BX_SB16_IRQ); } } // if buffer is not empty, there is data to be read if (DSP.dataout.empty() == 0) result |= 0x80; writelog(WAVELOG(4), "DSP output status read, result %x", result); return(result); } // dsp_irq16ack() notifies that the 16bit DMA IRQ has been acknowledged Bit32u bx_sb16_c::dsp_irq16ack() { Bit32u result = 0xff; if (DSP.irqpending != 0) { MIXER.reg[0x82] &= (~0x02); if ((MIXER.reg[0x82] & 0x07) == 0) { DSP.irqpending = 0; DEV_pic_lower_irq(BX_SB16_IRQ); } writelog(WAVELOG(4), "16-bit DMA IRQ acknowledged"); } else writelog(WAVELOG(3), "16-bit DMA IRQ acknowledged but not active!"); return result; } // the DMA handlers // highlevel input and output handlers - rerouting to/from file,device // write a wave packet to the output device void bx_sb16_c::dsp_sendwavepacket() { switch (BX_SB16_THIS wavemode) { case 1: BX_SB16_OUTPUT->sendwavepacket(DSP.dma.chunkindex, DSP.dma.chunk); break; case 3: fwrite(DSP.dma.chunk, 1, DSP.dma.chunkindex, WAVEDATA); break; case 2: Bit8u temparray[12] = { DSP.dma.samplerate & 0xff, DSP.dma.samplerate >> 8, 0, 0, DSP.dma.bits, DSP.dma.stereo + 1, 0, 0, 0, 0, 0, 0 }; switch ((DSP.dma.format >> 1) & 7) { case 2: temparray[7] = 3; break; case 3: temparray[7] = 2; break; case 4: temparray[7] = 1; break; } if (DSP.dma.bits == 16) temparray[7] = 4; writevocblock(9, 12, temparray, DSP.dma.chunkindex, DSP.dma.chunk); break; } DSP.dma.chunkindex = 0; } // put a sample byte into the output buffer void bx_sb16_c::dsp_getsamplebyte(Bit8u value) { if (DSP.dma.chunkindex < DSP.dma.chunkcount) DSP.dma.chunk[DSP.dma.chunkindex++] = value; if (DSP.dma.chunkindex >= DSP.dma.chunkcount) dsp_sendwavepacket(); } // read a sample byte from the input buffer Bit8u bx_sb16_c::dsp_putsamplebyte() { Bit8u value = DSP.dma.chunk[DSP.dma.chunkindex++]; if (DSP.dma.chunkindex >= DSP.dma.chunkcount) { DSP.dma.chunkcount = 0; DSP.dma.chunkindex = 0; } return value; } // called when the last byte of a DMA transfer has been received/sent void bx_sb16_c::dsp_dmadone() { writelog(WAVELOG(4), "DMA transfer done, triggering IRQ"); if ((DSP.dma.output == 1) && (DSP.dma.mode != 2)) { dsp_sendwavepacket(); // flush the output if (BX_SB16_THIS wavemode == 1) { BX_SB16_OUTPUT->stopwaveplayback(); } else if (BX_SB16_THIS wavemode != 0) { fflush(WAVEDATA); } } else if ((DSP.dma.output == 0) && (DSP.dma.mode != 2)) { if (BX_SB16_THIS wavemode == 1) { BX_SB16_OUTPUT->stopwaverecord(); } } // generate the appropriate IRQ if (DSP.dma.bits == 8) MIXER.reg[0x82] |= 1; else MIXER.reg[0x82] |= 2; DEV_pic_raise_irq(BX_SB16_IRQ); DSP.irqpending = 1; // if auto-DMA, reinitialize if (DSP.dma.mode == 2) { if ((DSP.dma.bits == 16) && (BX_SB16_DMAH != 0)) { DSP.dma.count = (DSP.dma.blocklength + 1) * (DSP.dma.bps / 2) - 1; } else { DSP.dma.count = (DSP.dma.blocklength + 1) * DSP.dma.bps - 1; } writelog(WAVELOG(4), "auto-DMA reinitializing to length %d", DSP.dma.count); } else { DSP.dma.mode = 0; dsp_disabledma(); } } // now the actual transfer routines, called by the DMA controller // note that read = from application to soundcard (output), // and write = from soundcard to application (input) Bit16u bx_sb16_c::dma_read8(Bit8u *buffer, Bit16u maxlen) { Bit16u len = 0; DEV_dma_set_drq(BX_SB16_DMAL, 0); // the timer will raise it again writelog(WAVELOG(5), "Received 8-bit DMA: 0x%02x, %d remaining ", buffer[0], DSP.dma.count); do { dsp_getsamplebyte(buffer[len++]); DSP.dma.count--; } while ((len < maxlen) && (DSP.dma.count != 0xffff)); if (DSP.dma.count == 0xffff) // last byte received dsp_dmadone(); return len; } Bit16u bx_sb16_c::dma_write8(Bit8u *buffer, Bit16u maxlen) { Bit16u len = 0; DEV_dma_set_drq(BX_SB16_DMAL, 0); // the timer will raise it again do { buffer[len++] = dsp_putsamplebyte(); DSP.dma.count--; } while ((len < maxlen) && (DSP.dma.count != 0xffff)); writelog(WAVELOG(5), "Sent 8-bit DMA: 0x%02x, %d remaining ", buffer[0], DSP.dma.count); if (DSP.dma.count == 0xffff) // last byte sent dsp_dmadone(); return len; } Bit16u bx_sb16_c::dma_read16(Bit16u *buffer, Bit16u maxlen) { Bit16u len = 0; Bit8u *buf8; DEV_dma_set_drq(BX_SB16_DMAH, 0); // the timer will raise it again writelog(WAVELOG(5), "Received 16-bit DMA: 0x%04x, %d remaining ", buffer[0], DSP.dma.count); do { buf8 = (Bit8u*)(buffer+len); dsp_getsamplebyte(buf8[0]); dsp_getsamplebyte(buf8[1]); len++; DSP.dma.count--; } while ((len < maxlen) && (DSP.dma.count != 0xffff)); if (DSP.dma.count == 0xffff) // last word received dsp_dmadone(); return len; } Bit16u bx_sb16_c::dma_write16(Bit16u *buffer, Bit16u maxlen) { Bit16u len = 0; Bit8u *buf8; DEV_dma_set_drq(BX_SB16_DMAH, 0); // the timer will raise it again do { buf8 = (Bit8u*)(buffer+len); buf8[0] = dsp_putsamplebyte(); buf8[1] = dsp_putsamplebyte(); len++; DSP.dma.count--; } while ((len < maxlen) && (DSP.dma.count != 0xffff)); writelog(WAVELOG(5), "Sent 16-bit DMA: 0x%4x, %d remaining ", buffer[0], DSP.dma.count); if (DSP.dma.count == 0xffff) // last word sent dsp_dmadone(); return len; } // the mixer, supported type is CT1745 (as in an SB16) void bx_sb16_c::mixer_writedata(Bit32u value) { int i; // do some action depending on what register was written switch (MIXER.regindex) { case 0: // initialize mixer writelog(BOTHLOG(4), "Initializing mixer..."); MIXER.reg[0x04] = 0xcc; MIXER.reg[0x0a] = 0x00; MIXER.reg[0x22] = 0xcc; MIXER.reg[0x26] = 0xcc; MIXER.reg[0x28] = 0x00; MIXER.reg[0x2e] = 0x00; MIXER.reg[0x3c] = 0x1f; MIXER.reg[0x3d] = 0x15; MIXER.reg[0x3e] = 0x0b; for (i=0x30; i<=0x35; i++) MIXER.reg[i] = 0xc0; for (i=0x36; i<=0x3b; i++) MIXER.reg[i] = 0x00; for (i=0x3f; i<=0x43; i++) MIXER.reg[i] = 0x00; for (i=0x44; i<=0x47; i++) MIXER.reg[i] = 0x80; MIXER.regindex = 0; // next mixer register read is register 0 return; case 0x04: // DAC level MIXER.reg[0x32] = (value & 0xf0) | 0x08; MIXER.reg[0x33] = ((value & 0x0f) << 4) | 0x08; break; case 0x0a: // microphone level MIXER.reg[0x3a] = (value << 5) | 0x18; break; case 0x22: // master volume MIXER.reg[0x30] = (value & 0xf0) | 0x08; MIXER.reg[0x31] = ((value & 0x0f) << 4) | 0x08; break; case 0x26: // FM level MIXER.reg[0x34] = (value & 0xf0) | 0x08; MIXER.reg[0x35] = ((value & 0x0f) << 4) | 0x08; break; case 0x28: // CD audio level MIXER.reg[0x36] = (value & 0xf0) | 0x08; MIXER.reg[0x37] = ((value & 0x0f) << 4) | 0x08; break; case 0x2e: // line in level MIXER.reg[0x38] = (value & 0xf0) | 0x08; MIXER.reg[0x39] = ((value & 0x0f) << 4) | 0x08; break; case 0x30: // master volume left MIXER.reg[0x22] &= 0x0f; MIXER.reg[0x22] |= (value & 0xf0); break; case 0x31: // master volume right MIXER.reg[0x22] &= 0xf0; MIXER.reg[0x22] |= (value >> 4); break; case 0x32: // DAC level left MIXER.reg[0x04] &= 0x0f; MIXER.reg[0x04] |= (value & 0xf0); break; case 0x33: // DAC level right MIXER.reg[0x04] &= 0xf0; MIXER.reg[0x04] |= (value >> 4); break; case 0x34: // FM level left MIXER.reg[0x26] &= 0x0f; MIXER.reg[0x26] |= (value & 0xf0); break; case 0x35: // FM level right MIXER.reg[0x26] &= 0xf0; MIXER.reg[0x26] |= (value >> 4); break; case 0x36: // CD audio level left MIXER.reg[0x28] &= 0x0f; MIXER.reg[0x28] |= (value & 0xf0); break; case 0x37: // CD audio level right MIXER.reg[0x28] &= 0xf0; MIXER.reg[0x28] |= (value >> 4); break; case 0x38: // line in level left MIXER.reg[0x2e] &= 0x0f; MIXER.reg[0x2e] |= (value & 0xf0); break; case 0x39: // line in level right MIXER.reg[0x2e] &= 0xf0; MIXER.reg[0x2e] |= (value >> 4); break; case 0x3a: // microphone level MIXER.reg[0x0a] = (value >> 5); break; case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: break; case 0x80: // IRQ mask case 0x81: // DMA mask MIXER.reg[MIXER.regindex] = value; set_irq_dma(); // both 0x80 and 0x81 handled return; default: // ignore read-only registers return; } // store the value MIXER.reg[MIXER.regindex] = value; writelog(BOTHLOG(4), "mixer register %02x set to %02x", MIXER.regindex, MIXER.reg[MIXER.regindex]); } Bit32u bx_sb16_c::mixer_readdata() { writelog(BOTHLOG(4), "read from mixer register %02x returns %02x", MIXER.regindex, MIXER.reg[MIXER.regindex]); return(MIXER.reg[MIXER.regindex]); } void bx_sb16_c::mixer_writeregister(Bit32u value) { MIXER.regindex = value; } void bx_sb16_c::set_irq_dma() { static bx_bool isInitialized=0; int newirq; int oldDMA8, oldDMA16; // set the IRQ according to the value in mixer register 0x80 switch (MIXER.reg[0x80]) { case 1: newirq = 2; break; case 2: newirq = 5; break; case 4: newirq = 7; break; case 8: newirq = 10; break; default: newirq = 5; writelog(BOTHLOG(3), "Bad value %02x in mixer register 0x80. IRQ set to %d", MIXER.reg[0x80], newirq); MIXER.reg[0x80] = 2; } if (newirq != BX_SB16_IRQ) // a different IRQ was set { if (BX_SB16_IRQ > 0) DEV_unregister_irq(BX_SB16_IRQ, "SB16"); BX_SB16_IRQ = newirq; DEV_register_irq(BX_SB16_IRQ, "SB16"); } // set the 8 bit DMA oldDMA8=BX_SB16_DMAL; switch (MIXER.reg[0x81] & 0x0f) { case 1: BX_SB16_DMAL = 0; break; case 2: BX_SB16_DMAL = 1; break; case 8: BX_SB16_DMAL = 3; break; default: BX_SB16_DMAL = 1; writelog(BOTHLOG(3), "Bad value %02x in mixer register 0x81. DMA8 set to %d", MIXER.reg[0x81], BX_SB16_DMAL); MIXER.reg[0x81] &= (~0x0f); MIXER.reg[0x81] |= (1 << BX_SB16_DMAL); } // Unregister the previous DMA if initialized if ((isInitialized) && (oldDMA8 != BX_SB16_DMAL)) DEV_dma_unregister_channel(oldDMA8); // And register the new 8bits DMA Channel if ((!isInitialized) || (oldDMA8 != BX_SB16_DMAL)) DEV_dma_register_8bit_channel(BX_SB16_DMAL, dma_read8, dma_write8, "SB16"); // and the 16 bit DMA oldDMA16=BX_SB16_DMAH; switch (MIXER.reg[0x81] >> 4) { case 0: BX_SB16_DMAH = 0; // no 16-bit DMA break; case 2: BX_SB16_DMAH = 5; break; case 4: BX_SB16_DMAH = 6; break; case 8: BX_SB16_DMAH = 7; break; default: BX_SB16_DMAH = 0; writelog(BOTHLOG(3), "Bad value %02x in mixer register 0x81. DMA16 set to %d", MIXER.reg[0x81], BX_SB16_DMAH); MIXER.reg[0x81] &= (~0xf0); // MIXER.reg[0x81] |= (1 << BX_SB16_DMAH); // no default 16 bit channel! } // Unregister the previous DMA if initialized if ((isInitialized) && (oldDMA16 != 0) && (oldDMA16 != BX_SB16_DMAH)) DEV_dma_unregister_channel(oldDMA16); // And register the new 16bits DMA Channel if ((BX_SB16_DMAH != 0) && (oldDMA16 != BX_SB16_DMAH)) DEV_dma_register_16bit_channel(BX_SB16_DMAH, dma_read16, dma_write16, "SB16"); // If not already initialized if(!isInitialized) { isInitialized=1; } else { writelog(BOTHLOG(1), "Resources set to I%d D%d H%d", BX_SB16_IRQ, BX_SB16_DMAL, BX_SB16_DMAH); } } // now the MPU 401 part // the MPU 401 status port shows if input or output are ready // Note that the bits are inverse to their meaning Bit32u bx_sb16_c::mpu_status() { Bit32u result = 0; if ((MPU.datain.full() == 1) || ((BX_SB16_THIS midimode == 1) && (BX_SB16_OUTPUT->midiready() == BX_SOUNDLOW_ERR))) result |= 0x40; // output not ready if (MPU.dataout.empty() == 1) result |= 0x80; // no input available writelog(MIDILOG(4), "MPU status port, result %02x", result); return(result); } // the MPU 401 command port void bx_sb16_c::mpu_command(Bit32u value) { int i; int bytesneeded; if (MPU.cmd.hascommand() == 1) // already a command pending, abort that one { if ((MPU.cmd.currentcommand() != value) || (MPU.cmd.commanddone() == 0)) // it's a different command, or the old one isn't done yet, abort it { MPU.cmd.clearcommand(); MPU.cmd.flush(); } // if it's the same one, and we just completed the argument list, // we leave it as it is and process it here } if (MPU.cmd.hascommand() == 0) // no command pending, set one up { bytesneeded = 0; if ((value >> 4) == 14) bytesneeded = 1; MPU.cmd.newcommand(value, bytesneeded); } if (MPU.cmd.commanddone() == 1) // command is complete, process it { switch (MPU.cmd.currentcommand()) { case 0x3f: writelog(MIDILOG(5), "MPU cmd: UART mode on"); MPU.uartmode=1; MPU.irqpending=1; MPU.singlecommand=0; if (BX_SB16_IRQMPU != -1) { MIXER.reg[0x82] |= 4; DEV_pic_raise_irq(BX_SB16_IRQMPU); } break; case 0xff: writelog(MIDILOG(4), "MPU cmd: Master reset of device"); MPU.uartmode=MPU.forceuartmode; MPU.singlecommand=0; for (i=0; i<16; i++) { MPU.banklsb[i] = 0; MPU.bankmsb[i] = 0; MPU.program[i] = 0; } MPU.cmd.reset(); MPU.dataout.reset(); MPU.datain.reset(); MPU.midicmd.reset(); /* if (BX_SB16_IRQ != -1) { MIXER.reg[0x82] |= 4; BX_SB16_THIS devices->pic->trigger_irq(BX_SB16_IRQ); } */ break; case 0xd0: // d0 and df: prefix for midi command case 0xdf: // like uart mode, but only a single command MPU.singlecommand = 1; writelog(MIDILOG(4), "MPU: prefix %02x received", MPU.cmd.currentcommand()); break; default: writelog(MIDILOG(3), "MPU cmd: unknown command %02x ignored", MPU.cmd.currentcommand()); break; } // Need to put an MPU_ACK into the data port if command successful // we'll fake it even if we didn't process the command, so as to // allow detection of the MPU 401. if (MPU.dataout.put(0xfe) == 0) writelog(MIDILOG(3), "MPU_ACK error - output buffer full"); MPU.cmd.clearcommand(); // clear the command from the buffer } } // MPU 401 data port/read: contains an MPU_ACK after receiving a command // Will contain other data as well when other than UART mode is supported Bit32u bx_sb16_c::mpu_dataread() { Bit8u res8bit; Bit32u result; // also acknowledge IRQ? if (MPU.irqpending != 0) { MPU.irqpending = 0; MIXER.reg[0x82] &= (~4); if ((MIXER.reg[0x82] & 0x07) == 0) DEV_pic_lower_irq(BX_SB16_IRQMPU); writelog(MIDILOG(4), "MPU IRQ acknowledged"); } if (MPU.dataout.get(&res8bit) == 0) { writelog(MIDILOG(3), "MPU data port not ready - no data in buffer"); result = 0xff; } else result = (Bit32u) res8bit; writelog(MIDILOG(4), "MPU data port, result %02x", result); return(result); } // MPU 401 data port/write: This is where the midi stream comes from, // as well as arguments to any pending command void bx_sb16_c::mpu_datawrite(Bit32u value) { writelog(MIDILOG(4), "write to MPU data port, value %02x", value); if (MPU.cmd.hascommand() == 1) { // there is a command pending, add arguments to it if (MPU.cmd.put(value) == 0) writelog(MIDILOG(3), "MPU Command arguments too long - buffer full"); if (MPU.cmd.commanddone() == 1) BX_SB16_THIS mpu_command(MPU.cmd.currentcommand()); } else if ((MPU.uartmode == 0) && (MPU.singlecommand == 0)) { // Hm? No UART mode, but still data? Maybe should send it // to the command port... Only SBMPU401.EXE does this... writelog(MIDILOG(4), "MPU Data %02x received but no UART mode. Assuming it's a command.", value); mpu_command(value); return; } else // no MPU command pending, in UART mode, this has to be midi data mpu_mididata(value); } // A byte of midi data has been received void bx_sb16_c::mpu_mididata(Bit32u value) { // first, find out if it is a midi command or midi data bx_bool ismidicommand = 0; if (value >= 0x80) { // bit 8 usually denotes a midi command... ismidicommand = 1; if ((value == 0xf7) && (MPU.midicmd.currentcommand() == 0xf0)) // ...except if it is a continuing SYSEX message, then it just // denotes the end of a SYSEX chunk, not the start of a message { ismidicommand = 0; // first, it's not a command MPU.midicmd.newcommand(MPU.midicmd.currentcommand(), MPU.midicmd.bytes()); // Then, set needed bytes to current buffer // because we didn't know the length before } } if (ismidicommand == 1) { // this is a command, check if an old one is pending if (MPU.midicmd.hascommand() == 1) { writelog(MIDILOG(3), "Midi command %02x incomplete, has %d of %d bytes.", MPU.midicmd.currentcommand(), MPU.midicmd.bytes(), MPU.midicmd.commandbytes()); // write as much as we can. Should we do this? processmidicommand(0); // clear the pending command MPU.midicmd.clearcommand(); MPU.midicmd.flush(); } // find the number of arguments to the command static const signed eventlength[] = { 2, 2, 2, 2, 1, 1, 2, 255}; // note - length 255 commands have unknown length MPU.midicmd.newcommand(value, eventlength[(value & 0x70) >> 4]); } else // no command, just arguments to the old command { if (MPU.midicmd.hascommand() == 0) { // no command pending, ignore the data writelog(MIDILOG(3), "Midi data %02x received, but no command pending?", value); return; } // just some data to the command if (MPU.midicmd.put(value) == 0) writelog(MIDILOG(3), "Midi buffer overflow!"); if (MPU.midicmd.commanddone() == 1) { // the command is complete, process it writelog(MIDILOG(5), "Midi command %02x complete, has %d bytes.", MPU.midicmd.currentcommand(), MPU.midicmd.bytes()); processmidicommand(0); // and remove the command from the buffer MPU.midicmd.clearcommand(); MPU.midicmd.flush(); } } } // The emulator port/read: See if commands were successful Bit32u bx_sb16_c::emul_read() { Bit8u res8bit; Bit32u result; if (EMUL.datain.get(&res8bit) == 0) { writelog(3, "emulator port not ready - no data in buffer"); result = 0x00; } else result = (Bit32u) res8bit; writelog(4, "emulator port, result %02x", result); return(result); } // Emulator port/write: Changing instrument mapping etc. void bx_sb16_c::emul_write(Bit32u value) { Bit8u value8 = 0; writelog(4, "write to emulator port, value %02x", value); if (EMUL.dataout.hascommand() == 0) // no command pending, set it up { static signed char cmdlength[] = { 0, 0, 4, 2, 6, 1, 0, 0, 1, 1, 0, 1}; if (value > 11) { writelog(3, "emulator command %02x unknown, ignored.", value); return; } writelog(5, "emulator command %02x, needs %d arguments", value, cmdlength[value]); EMUL.dataout.newcommand(value, cmdlength[value]); EMUL.datain.reset(); EMUL.datain.put(0xfe); } else EMUL.dataout.put(value); // otherwise just add data if (EMUL.dataout.commanddone() == 1) { // process the command writelog(4, "executing emulator command %02x with %d arguments", EMUL.dataout.currentcommand(), EMUL.dataout.bytes()); switch (EMUL.dataout.currentcommand()) { case 0: // reinit of emulator writelog(4, "Emulator reinitialized"); EMUL.remaps = 0; EMUL.dataout.reset(); EMUL.datain.reset(); EMUL.datain.put(0xfe); break; case 1: // dummy command to reset state of emulator port // just give a few times to end any commands break; case 2: // map bank if (EMUL.remaps >= BX_SB16_PATCHTABLESIZE) break; EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].oldbankmsb)); EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].oldbanklsb)); EMUL.remaplist[EMUL.remaps].oldprogch = 0xff; EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].newbankmsb)); EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].newbanklsb)); EMUL.remaplist[EMUL.remaps].newprogch = 0xff; EMUL.datain.put(4); writelog(4, "Map bank command received, from %d %d to %d %d", EMUL.remaplist[EMUL.remaps].oldbankmsb, EMUL.remaplist[EMUL.remaps].oldbanklsb, EMUL.remaplist[EMUL.remaps].newbankmsb, EMUL.remaplist[EMUL.remaps].newbanklsb); EMUL.remaps++; break; case 3: // map program change if (EMUL.remaps >= BX_SB16_PATCHTABLESIZE) break; EMUL.remaplist[EMUL.remaps].oldbankmsb = 0xff; EMUL.remaplist[EMUL.remaps].oldbanklsb = 0xff; EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].oldprogch)); EMUL.remaplist[EMUL.remaps].newbankmsb = 0xff; EMUL.remaplist[EMUL.remaps].newbanklsb = 0xff; EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].newprogch)); EMUL.datain.put(2); writelog(4, "Map program change received, from %d to %d", EMUL.remaplist[EMUL.remaps].oldprogch, EMUL.remaplist[EMUL.remaps].newprogch); EMUL.remaps++; break; case 4: // map bank and program change if (EMUL.remaps >= BX_SB16_PATCHTABLESIZE) break; EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].oldbankmsb)); EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].oldbanklsb)); EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].oldprogch)); EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].newbankmsb)); EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].newbanklsb)); EMUL.dataout.get (& (EMUL.remaplist[EMUL.remaps].newprogch)); EMUL.datain.put(6); writelog(4, "Complete remap received, from %d %d %d to %d %d %d", EMUL.remaplist[EMUL.remaps].oldbankmsb, EMUL.remaplist[EMUL.remaps].oldbanklsb, EMUL.remaplist[EMUL.remaps].oldprogch, EMUL.remaplist[EMUL.remaps].newbankmsb, EMUL.remaplist[EMUL.remaps].newbanklsb, EMUL.remaplist[EMUL.remaps].newprogch); EMUL.remaps++; break; case 5: EMUL.dataout.get(&value8); // dump emulator state switch (value8) { case 0: EMUL.datain.puts("SB16 Emulator for Bochs\n"); break; case 1: EMUL.datain.puts("UART mode=%d (force=%d)\n", MPU.uartmode, MPU.forceuartmode); break; case 2: EMUL.datain.puts("timer=%d\n", MPU.current_timer); break; case 3: EMUL.datain.puts("%d remappings active\n", EMUL.remaps); break; case 4: EMUL.datain.puts("Resources are A%3x I%d D%d H%d T%d P%3x; Adlib at %3x\n", BX_SB16_IO, BX_SB16_IRQ, BX_SB16_DMAL, BX_SB16_DMAH, 6, BX_SB16_IOMPU, BX_SB16_IOADLIB); break; case 5: EMUL.datain.puts("Current OPL2/3 mode: %s", // ok, I admit that this is a bit ugly... (OPL.mode == single)?"single OPL2 (OPL3 disabled)\n": (OPL.mode == adlib)?"single OPL2 (no OPL3)\n": (OPL.mode == dual)?"double OPL2\n": (OPL.mode == opl3)?"OPL3\n": "unknown"); break; default: EMUL.datain.puts("no info. Only slots 0..5 have values.\n"); break; } break; case 6: // close midi and wave files and/or output if ((BX_SB16_THIS midimode == 2) || (BX_SB16_THIS midimode == 3)) { if (BX_SB16_THIS midimode == 2) finishmidifile(); fclose(MIDIDATA); } else if (BX_SB16_THIS midimode == 1) BX_SB16_OUTPUT->closemidioutput(); BX_SB16_THIS midimode = 0; if ((BX_SB16_THIS wavemode == 2) || (BX_SB16_THIS wavemode == 3)) { if (BX_SB16_THIS wavemode == 2) finishvocfile(); fclose(WAVEDATA); } else BX_SB16_OUTPUT->closewaveoutput(); BX_SB16_THIS wavemode = 0; break; case 7: // clear bank/program mappings EMUL.remaps = 0; writelog(4, "Bank/program mappings cleared."); break; case 8: // set force uart mode on/off EMUL.dataout.get(&value8); MPU.forceuartmode = value8; if (value8 != 0) MPU.uartmode = MPU.forceuartmode; writelog(4, "Force UART mode = %d", MPU.forceuartmode); break; case 9: // enter specific OPL2/3 mode EMUL.dataout.get(&value8); writelog(4, "Entering OPL2/3 mode %d", value8); opl_entermode((bx_sb16_fm_mode) value8); break; case 10: // check emulator present EMUL.datain.put(0x55); break; case 11: // send data to midi device EMUL.dataout.get(&value8); mpu_mididata(value8); } EMUL.dataout.clearcommand(); EMUL.dataout.flush(); } } // and finally the OPL (FM emulation) part // select a new operational mode for the FM part // this also serves as reset for the OPL chip void bx_sb16_c::opl_entermode(bx_sb16_fm_mode newmode) { int i, j; // do nothing if the mode is unchanged if (OPL.mode == newmode) return; // if the old mode was 0, and the new mode is 3, then // no reset is necessary, just set the flag if ((OPL.mode == single) && (newmode == opl3)) { writelog(MIDILOG(4), "OPL3 mode enabled"); OPL.mode = newmode; return; } writelog(MIDILOG(4), "Switching to OPL mode %d from %d", newmode, OPL.mode); for (i=0; i> (6 - (i % 2))) == 0) { // set flags only if unmasked writelog(MIDILOG(5), "OPL Timer Interrupt: Chip %d, Timer %d", i/2, 1 << (i % 2)); OPL.tflag[i/2] |= 1 << (6 - (i % 2)); // set the overflow flag OPL.tflag[i/2] |= 1 << 7; // set the IRQ flag } } } } } // return the status of one of the OPL2's, or the // base status of the OPL3 Bit32u bx_sb16_c::opl_status(int chipid) { Bit32u status = OPL.tflag[chipid]; writelog(MIDILOG(5), "OPL status of chip %d is %02x", chipid, status); return status; } // set the register index for one of the OPL2's or the // base or advanced register index for the OPL3 void bx_sb16_c::opl_index(Bit32u value, int chipid) { OPL.index[chipid] = value; } // write to the data port void bx_sb16_c::opl_data(Bit32u value, int chipid) { int index = OPL.index[chipid]; int opernum = -1; // OPL3 operator number; 0..35 int channum = -1; // OPL3 channel number; 0..17 int subopnum = -1; // channel operator; 0..nop-1 writelog(MIDILOG(4), "Write to OPL(%d) register %02x: %02x", chipid, index, value); // first find out operator and/or channel numbers // case 0x20 ... 0x95: includes too many ports, but that is harmless // case 0xe0 ... 0xf5: if (((index>=0x20) && (index<=0x95)) || ((index>=0xe0) && (index<=0xf5))) { // operator access // find the operator number. 0..17 on chip 1, 18..35 on chip 2 // note, the numbers are not continuous (again...), so we need // this rather weird calculation opernum = index & 0x07; if (opernum > 5) // invalid register, has no operator associated { opernum = -1; goto break_here; } opernum += ((index & 0x18) >> 3) * 6; if (opernum > 17) // Operators 18+ have to be accessed on other address set { opernum = -1; goto break_here; } if (chipid == 1) opernum += BX_SB16_FM_NOP / 2; // find out the channel number, and which of the channel's operators this is channum = opernum % 3 + ((int) (opernum / 6)) * 3; subopnum = 0; if ((opernum % 6) > 2) // second operator subopnum = 1; // if (channel - 3) is in a four-operator mode, that is really // what this operator belongs to if (channum >= 3) { if (OPL.chan[channum - 3].nop == 4) { channum -= 3; subopnum += 2; } } writelog(MIDILOG(5), "Is Channel %d, Oper %d, Subop %d", channum, opernum, subopnum); } else if ((index>=0xa0) && (index<=0xc8)) { // channel access channum = index & 0x0f; if (OPL.chan[channum].nop == 0) channum = -1; // the channel is disabled writelog(MIDILOG(5), "Is channel %d", channum); } break_here: switch (index & 0xff) { // WSEnable and Test Register case 0x01: OPL.wsenable[chipid] = (value >> 5) & 1; if ((value & 0x1f) != 0) writelog(MIDILOG(3), "Warning: Test Register set to %02x", value & 0x1f); break; // the two timer counts case 0x02: OPL.timerinit[chipid * 2] = OPL.timer[chipid * 2] = value; break; case 0x03: OPL.timerinit[chipid * 2 + 1] = OPL.timer[chipid * 2 + 1] = (value << 2); break; // if OPL2: timer masks // if OPL3: 4-operator modes case 0x04: if ((chipid == 0) || (OPL.mode == dual)) opl_settimermask(value, chipid); else opl_set4opmode(value & 0x3f); break; // only OPL3: OPL3 enable case 0x05: if (chipid == 1) { if ((value & 1) != 0) opl_entermode(opl3); else opl_entermode(single); } break; // Composite Sine Wave and Note-sel (ignored) case 0x08: if (value != 0) writelog(MIDILOG(3), "Warning: write of %02x to CSW/Note-sel ignored", value); break; // most importantly the percussion part case 0xbd: opl_setpercussion(value, chipid); break; // the operator registers // case 0x20 ... 0x35: case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: // case 0x60 ... 0x75: case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: // case 0x80 ... 0x95: case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8a: case 0x8b: case 0x8c: case 0x8d: case 0x8e: case 0x8f: case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: if (opernum != -1) { opl_changeop(channum, opernum, (index / 0x20) - 1, value); break; } // else let default: catch it // case 0x40 ... 0x55: case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: if (opernum != -1) { opl_changeop(channum, opernum, 1, value & 0xc0); if (subopnum != -1) opl_setvolume(channum, subopnum, value & 0x3f); break; } // else let default: catch it // case 0xe0 ... 0xf5: case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: if (opernum != -1) { opl_changeop(channum, opernum, 5, value & 0x07); break; } // else let default: catch it // and the channel registers // case 0xa0 ... 0xa8: case 0xa0: case 0xa1: case 0xa2: case 0xa3: case 0xa4: case 0xa5: case 0xa6: case 0xa7: case 0xa8: if (channum != -1) { if (value != (Bit32u)(OPL.chan[channum].freq & 0xff)) { OPL.chan[channum].freq &= 0xff00; OPL.chan[channum].freq |= value; opl_setfreq(channum); } break; } // else let default: catch it // case 0xb0 ... 0xb8: case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb8: if (channum != -1) { if ((value & 0x1f) != ((Bit32u)(OPL.chan[channum].freq >> 8) & 0x1f)) { OPL.chan[channum].freq &= 0x00ff; OPL.chan[channum].freq |= (value & 0x1f) << 8; opl_setfreq(channum); } opl_keyonoff(channum, (value >> 5) & 1); break; } // else let default: catch it // this is a channel access, but it belongs to the instrument // definition, so put it into value [4] of the channel's first operator // case 0xc0 ... 0xc8: case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: if (channum != -1) { int needchange = 0; if ((OPL.oper[OPL.chan[channum].opnum[0]][4] & 1) != (int)(value & 1)) needchange = 1; opl_changeop(channum, OPL.chan[channum].opnum[0], 4, value & 0x3f); if (needchange == 1) opl_setmodulation(channum); break; } // else let default: catch it default: writelog(MIDILOG(3), "Attempt to write %02x to unknown OPL(%d) register %02x", value, chipid, index); break; } } // change a value of an operator void bx_sb16_c::opl_changeop(int channum, int opernum, int byte, int value) { if (OPL.oper[opernum][byte] != value) { OPL.oper[opernum][byte] = value; OPL.chan[channum].needprogch = 1; } } // called for a write to the 4-operator mode register void bx_sb16_c::opl_set4opmode(int new4opmode) { int i, channel1, channel2; writelog(MIDILOG(4), "Switching to 4-op mode %02x", new4opmode); // every bit switches a 4-op channel-pairing on or off // 4-op mode is two channels combined into the first one for (i = 0; i<6; i++) { channel1 = i + (i / 3) * 6; channel2 = channel1 + 3; if (((new4opmode >> i) & 1) != 0) { // enable 4-op mode opl_keyonoff(channel1, 0); opl_keyonoff(channel2, 0); OPL.chan[channel1].nop = 4; OPL.chan[channel2].nop = 0; OPL.chan[channel1].needprogch = 1; } else { // disable 4-op mode opl_keyonoff(channel1, 0); OPL.chan[channel1].nop = 2; OPL.chan[channel2].nop = 2; OPL.chan[channel1].needprogch = 1; OPL.chan[channel2].needprogch = 1; } } } // called for a write to port 4 of either chip void bx_sb16_c::opl_settimermask(int value, int chipid) { if ((value & 0x80) != 0) // reset IRQ and timer flags { // all other bits ignored! writelog(MIDILOG(5), "IRQ Reset called"); OPL.tflag[chipid] = 0; return; } OPL.tmask[chipid] = value & 0x63; writelog(MIDILOG(5), "New timer mask for chip %d is %02x", chipid, OPL.tmask[chipid]); // do we have to activate or deactivate the timer? if (((value & 0x03) != 0) ^ (OPL.timer_running != 0)) { if ((value & 0x03) != 0) // yes, it's different. Start or stop? { writelog(MIDILOG(5), "Starting timers"); bx_pc_system.activate_timer(OPL.timer_handle, 80, 1); OPL.timer_running = 1; } else { writelog(MIDILOG(5), "Stopping timers"); bx_pc_system.deactivate_timer(OPL.timer_handle); OPL.timer_running = 0; } } } // called when the modulation mode of a channel changes void bx_sb16_c::opl_setmodulation(int channel) { int opernum = OPL.chan[channel].opnum[0]; if ((OPL.chan[channel].nop == 0) && (channel >= 3) && (OPL.chan[channel].nop == 4)) channel -= 3; if (OPL.chan[channel].nop == 2) { OPL.chan[channel].ncarr = (OPL.oper[opernum][4] & 1) + 1; OPL.chan[channel].needprogch = 1; } else if (OPL.chan[channel].nop == 4) { int opernum2 = OPL.chan[channel].opnum[2]; int modmode = (OPL.oper[opernum][4] & 1) | ((OPL.oper[opernum2][4] & 1) >> 1); OPL.chan[channel].ncarr = modmode + 1 - (modmode / 2); OPL.chan[channel].needprogch = 1; } } // called for a write to register 0xbd, the percussion register void bx_sb16_c::opl_setpercussion(Bit8u value, int chipid) { UNUSED(value); UNUSED(chipid); } // called when a channel volume changes // opnum is which of the channel's operators had the change, not // the actual operator number. Thus, it's from 0..3. void bx_sb16_c::opl_setvolume(int channel, int opnum, int outlevel) { UNUSED(opnum); UNUSED(outlevel); OPL.chan[channel].midivol = 127; } // called when a frequency change is complete, to find out the // corresponding midi key and pitch bender values void bx_sb16_c::opl_setfreq(int channel) { int block,fnum; // definition: // low-byte of freq: 8 bit F-Number, LSB's // high-byte of freq: [2 reserved][KEY-ON][3 block][2 F-Number MSB's] // [KEY-ON] is ignored by this function // // the definition of the F-number is // F-Number = Frequency * 2**(20-block) / (49716 Hz) // // Thus, the frequency can be calculated as // Frequency = F-Number / 2**(20-block) * 49716 Hz // // (But remember that afreq is in 10^-3 Hz!) // fnum = OPL.chan[channel].freq & 0x3ff; block = (OPL.chan[channel].freq >> 10) & 0x07; writelog(MIDILOG(5), "F-Num is %d, block is %d", fnum, block); Bit32u realfreq; const Bit32u freqbase = 49716000; // const is better than #define if type is important // this is a bit messy to preserve accuracy as much as possible, // otherwise we might either lose precision, or the higher bits. realfreq = ((freqbase >> 4) * fnum) >> (16 - block); OPL.chan[channel].afreq = realfreq; // now find out what MIDI key this corresponds to, and with what // pitch bender value... (the latter not implemented yet) int octave=0; // 0: Octave from 523.2511 Hz; pos=higher, neg=lower int keynum=0; // 0=C; 1=C#; 2=D; ...; 11=B if (realfreq > 8175) { // 8.175 is smallest possible frequency const Bit32u freqC = 523251; // Midi note 72; "C": 523.251 Hz Bit32u keyfreq; // Frequency scaled to the octave from freqC to 2*freqC if (realfreq > freqC) { while ((realfreq >> (++octave)) > freqC); keyfreq = realfreq >> (--octave); } else { while ((realfreq << (++octave)) < freqC); keyfreq = realfreq << octave; octave = -octave; } // this is a reasonable approximation for keyfreq /= 1.059463 // (that value is 2**(1/12), which is the difference between two keys) while ((keyfreq -= ((keyfreq * 1000) / 17817)) > freqC) keynum++; } else { octave = -6; keynum = 0; } OPL.chan[channel].midinote = (octave + 6) * 12 + keynum; writelog(MIDILOG(5), "New frequency %.3f is key %d in octave %d; midi note %d", (float) realfreq/1000.0, keynum, octave, OPL.chan[channel].midinote); } // called when a note is possibly turned on or off void bx_sb16_c::opl_keyonoff(int channel, bx_bool onoff) { int i; Bit8u commandbytes[3]; if (OPL.mode == fminit) return; // first check if there really is a change in the state if (onoff == OPL.chan[channel].midion) return; OPL.chan[channel].midion = onoff; // check if we have a midi channel, otherwise allocate one if possible if (OPL.chan[channel].midichan == 0xff) { for (i=0; i<16; i++) if (((OPL.midichannels >> i) & 1) != 0) { OPL.chan[channel].midichan = i; OPL.midichannels &= ~(1 << i); // mark channel as used OPL.chan[channel].needprogch = 1; } if (OPL.chan[channel].midichan == 0xff) return; } if (OPL.chan[channel].needprogch != 0) opl_midichannelinit(channel); commandbytes[0] = OPL.chan[channel].midichan; commandbytes[1] = OPL.chan[channel].midinote; commandbytes[2] = 0; if (onoff == 0) { commandbytes[0] |= 0x80; // turn it off } else { commandbytes[0] |= 0x90; // turn it on commandbytes[2] = OPL.chan[channel].midivol; } writemidicommand(commandbytes[0], 2, & (commandbytes[1])); } // setup a midi channel void bx_sb16_c::opl_midichannelinit(int channel) { UNUSED(channel); } /* Handlers for the midi commands/midi file output */ // Write the header of the midi file. Track length is 0x7fffffff // until we know how long it's really going to be void bx_sb16_c::initmidifile() { struct { Bit8u chunk[4]; Bit32u chunklen; // all values in BIG Endian! Bit16u smftype; Bit16u tracknum; Bit16u timecode; // 0x80 + deltatimesperquarter << 8 } midiheader = #ifdef BX_LITTLE_ENDIAN { "MTh", 0x06000000, 0, 0x0100, 0x8001 }; #else { "MTh", 6, 0, 1, 0x180 }; #endif midiheader.chunk[3] = 'd'; struct { Bit8u chunk[4]; Bit32u chunklen; Bit8u data[15]; } trackheader = #ifdef BX_LITTLE_ENDIAN { "MTr", 0xffffff7f, #else { "MTr", 0x7fffffff, #endif { 0x00,0xff,0x51,3,0x07,0xa1,0x20, // set tempo 120 (0x7a120 us per quarter) 0x00,0xff,0x58,4,4,2,0x18,0x08 }}; // time sig 4/4 trackheader.chunk[3] = 'k'; fwrite(&midiheader, 1, 14, MIDIDATA); fwrite(&trackheader, 1, 23, MIDIDATA); } // write the midi command to the midi file void bx_sb16_c::writemidicommand(int command, int length, Bit8u data[]) { bx_list_c *base; /* We need to determine the time elapsed since the last MIDI command */ int deltatime = currentdeltatime(); /* Initialize output device if necessary and not done yet */ if (BX_SB16_THIS midimode == 1) { if (MPU.outputinit != 1) { writelog(MIDILOG(4), "Initializing Midi output."); if (BX_SB16_OUTPUT->openmidioutput(SIM->get_param_string(BXPN_SB16_MIDIFILE)->getptr()) == BX_SOUNDLOW_OK) MPU.outputinit = 1; else MPU.outputinit = 0; if (MPU.outputinit != 1) { writelog(MIDILOG(2), "Error: Couldn't open midi output. Midi disabled."); BX_SB16_THIS midimode = 0; return; } } BX_SB16_OUTPUT->sendmidicommand(deltatime, command, length, data); return; } else if ((BX_SB16_THIS midimode == 2) || (BX_SB16_THIS midimode == 3)) { base = (bx_list_c*) SIM->get_param(BXPN_SOUND_SB16); MIDIDATA = fopen(SIM->get_param_string("midifile", base)->getptr(),"wb"); if (MIDIDATA == NULL) { writelog (MIDILOG(2), "Error opening file %s. Midimode disabled.", SIM->get_param_string("midifile", base)->getptr()); BX_SB16_THIS midimode = 0; } else if (BX_SB16_THIS midimode == 2) { initmidifile(); } } if (BX_SB16_THIS midimode < 2) return; if (BX_SB16_THIS midimode == 2) writedeltatime(deltatime); fputc(command, MIDIDATA); if ((command == 0xf0) || (command == 0xf7)) // write event length for sysex/meta events writedeltatime(length); fwrite(data, 1, length, MIDIDATA); } // determine how many delta times have passed since // this function was called last int bx_sb16_c::currentdeltatime() { int deltatime; // counting starts at first access if (MPU.last_delta_time == 0xffffffff) MPU.last_delta_time = MPU.current_timer; deltatime = MPU.current_timer - MPU.last_delta_time; MPU.last_delta_time = MPU.current_timer; return deltatime; } // process the midi command stored in MPU.midicmd.to the midi driver void bx_sb16_c::processmidicommand(bx_bool force) { int i, channel; Bit8u value; bx_bool needremap = 0; channel = MPU.midicmd.currentcommand() & 0xf; // we need to log bank changes and program changes if ((MPU.midicmd.currentcommand() >> 4) == 0xc) { // a program change value = MPU.midicmd.peek(0); writelog(MIDILOG(1), "* ProgramChange channel %d to %d", channel, value); MPU.program[channel] = value; needremap = 1; } else if ((MPU.midicmd.currentcommand() >> 4) == 0xb) { // a control change, could be a bank change if (MPU.midicmd.peek(0) == 0) { // bank select MSB value = MPU.midicmd.peek(1); writelog(MIDILOG(1), "* BankSelectMSB (%x %x %x) channel %d to %d", MPU.midicmd.peek(0), MPU.midicmd.peek(1), MPU.midicmd.peek(2), channel, value); MPU.bankmsb[channel] = value; needremap = 1; } else if (MPU.midicmd.peek(0) == 32) { // bank select LSB value = MPU.midicmd.peek(1); writelog(MIDILOG(1), "* BankSelectLSB channel %d to %d", channel, value); MPU.banklsb[channel] = value; needremap = 1; } } Bit8u temparray[256]; i = 0; while (MPU.midicmd.empty() == 0) MPU.midicmd.get(&(temparray[i++])); writemidicommand(MPU.midicmd.currentcommand(), i, temparray); // if single command, revert to command mode if (MPU.singlecommand != 0) { MPU.singlecommand = 0; // and trigger IRQ? // MPU.irqpending = 1; // BX_SB16_THIS devices->pic->trigger_irq(BX_SB16_IRQMPU); } if ((force == 0) && (needremap == 1)) // have to check the remap lists, and remap program change if necessary midiremapprogram(channel); } // check if a program change has to be remapped, and do it if necessary void bx_sb16_c::midiremapprogram(int channel) { int bankmsb,banklsb,program; Bit8u commandbytes[2]; bankmsb = MPU.bankmsb[channel]; banklsb = MPU.banklsb[channel]; program = MPU.program[channel]; for(int i = 0; i < EMUL.remaps; i++) { if (((EMUL.remaplist[i].oldbankmsb == bankmsb) || (EMUL.remaplist[i].oldbankmsb == 0xff)) && ((EMUL.remaplist[i].oldbanklsb == banklsb) || (EMUL.remaplist[i].oldbanklsb == 0xff)) && ((EMUL.remaplist[i].oldprogch == program) || (EMUL.remaplist[i].oldprogch == 0xff))) { writelog(5, "Remapping instrument for channel %d", channel); if ((EMUL.remaplist[i].newbankmsb != bankmsb) && (EMUL.remaplist[i].newbankmsb != 0xff)) { // write control change bank msb MPU.bankmsb[channel] = EMUL.remaplist[i].newbankmsb; commandbytes[0] = 0; commandbytes[1] = EMUL.remaplist[i].newbankmsb; writemidicommand(0xb0 | channel, 2, commandbytes); } if ((EMUL.remaplist[i].newbanklsb != banklsb) && (EMUL.remaplist[i].newbanklsb != 0xff)) { // write control change bank lsb MPU.banklsb[channel] = EMUL.remaplist[i].newbanklsb; commandbytes[0] = 32; commandbytes[1] = EMUL.remaplist[i].newbanklsb; writemidicommand(0xb0 | channel, 2, commandbytes); } if ((EMUL.remaplist[i].newprogch != program) && (EMUL.remaplist[i].newprogch != 0xff)) { // write program change MPU.program[channel] = EMUL.remaplist[i].newprogch; commandbytes[0] = EMUL.remaplist[i].newprogch; writemidicommand(0xc0 | channel, 1, commandbytes); } } } } // convert a number into a delta time coded value int bx_sb16_c::converttodeltatime(Bit32u deltatime, Bit8u value[4]) { int i, count; Bit8u outbytes[4]; count = 0; if (deltatime <= 0) { count = 1; value[0] = 0; } else { while ((deltatime > 0) && (count < 4)) // split into parts { // of seven bits outbytes[count++] = deltatime & 0x7f; deltatime >>= 7; } for (i=0; i> 24) | ((tracklen & 0x00ff0000) >> 8) | ((tracklen & 0x0000ff00) << 8); #endif fwrite(&tracklen, 4, 1, MIDIDATA); } /* Handlers for the voc file output */ // Write the header of the voc file. void bx_sb16_c::initvocfile() { struct { char id[20]; Bit16u headerlen; // All in LITTLE Endian! Bit16u version; Bit16u chksum; } vocheader = { "Creative Voice File", #ifdef BX_LITTLE_ENDIAN 0x1a, 0x0114, 0x111f }; #else 0x1a00, 0x1401, 0x1f11 }; #endif vocheader.id[19] = 26; // Replace string end with 26 fwrite(&vocheader, 1, sizeof vocheader, WAVEDATA); } // write one block to the voc file void bx_sb16_c::writevocblock(int block, Bit32u headerlen, Bit8u header[], Bit32u datalen, Bit8u data[]) { Bit32u i; if (block > 9) { writelog(WAVELOG(3), "VOC Block %d not recognized, ignored.", block); return; } fputc(block, WAVEDATA); i = headerlen + datalen; #ifdef BX_LITTLE_ENDIAN fwrite(&i, 1, 3, WAVEDATA); // write the length in 24-bit little endian #else Bit8u lengthbytes[3]; lengthbytes[0] = i & 0xff; i >>= 8; lengthbytes[1] = i & 0xff; i >>= 8; lengthbytes[2] = i & 0xff; fwrite(lengthbytes, 1, 3, WAVEDATA); #endif writelog(WAVELOG(5), "Voc block %d; Headerlen %d; Datalen %d", block, headerlen, datalen); if (headerlen > 0) fwrite(header, 1, headerlen, WAVEDATA); if (datalen > 0) fwrite(data, 1, datalen, WAVEDATA); } // close the voc file void bx_sb16_c::finishvocfile() { fputc(0, WAVEDATA); // blocktype 0: end block } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_sb16_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_SB16_SMF bx_sb16_c *class_ptr = (bx_sb16_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_sb16_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_SB16_SMF switch (address) { // 2x0: FM Music Status Port // 2x8 and 388 are aliases case BX_SB16_IO + 0x00: case BX_SB16_IO + 0x08: case BX_SB16_IOADLIB + 0x00: return opl_status(0); // 2x1: reserved (w: FM Music Data Port) // 2x9 and 389 are aliases case BX_SB16_IO + 0x01: case BX_SB16_IO + 0x09: case BX_SB16_IOADLIB + 0x01: break; // 2x2: Advanced Music Status Port // or (for SBPro1) FM Music Status Port 2 // 38a is an alias case BX_SB16_IO + 0x02: case BX_SB16_IOADLIB + 0x02: return opl_status(1); // 2x3: reserved (w: Adv. FM Music Data Port) // or (for SBPro1) FM Music Data Port 2 // 38b is an alias case BX_SB16_IO + 0x03: case BX_SB16_IOADLIB + 0x03: break; // 2x4: reserved (w: Mixer Register Port) case BX_SB16_IO + 0x04: break; // 2x5: Mixer Data Port case BX_SB16_IO + 0x05: return mixer_readdata(); // 2x6: reserved (w: DSP Reset) case BX_SB16_IO + 0x06: break; // 2x7: reserved case BX_SB16_IO + 0x07: break; // 2x8: FM Music Status Port (OPL-2) // handled above // 2x9: reserved (w: FM Music Data Port) // handled above // 2xa: DSP Read Data Port case BX_SB16_IO + 0x0a: return dsp_dataread(); // 2xb: reserved case BX_SB16_IO + 0x0b: break; // 2xc: DSP Buffer Status Port case BX_SB16_IO + 0x0c: return dsp_bufferstatus(); // 2xd: reserved case BX_SB16_IO + 0x0d: break; // 2xe: DSP Data Status Port case BX_SB16_IO + 0x0e: return dsp_status(); // 2xf: DSP Acknowledge 16bit DMA IRQ case BX_SB16_IO + 0x0f: return dsp_irq16ack(); // 3x0: MPU Data Port Read case BX_SB16_IOMPU + 0x00: return mpu_dataread(); // 3x1: MPU Status Port case BX_SB16_IOMPU + 0x01: return mpu_status(); // 3x2: reserved case BX_SB16_IOMPU + 0x02: break; // 3x3: *Emulator* Port case BX_SB16_IOMPU + 0x03: return emul_read(); } // If we get here, the port wasn't valid writelog(3, "Read access to 0x%04x: unsupported port!", address); return(0xff); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_sb16_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_SB16_SMF bx_sb16_c *class_ptr = (bx_sb16_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_sb16_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_SB16_SMF switch (address) { // 2x0: FM Music Register Port // 2x8 and 388 are aliases case BX_SB16_IO + 0x00: case BX_SB16_IO + 0x08: case BX_SB16_IOADLIB + 0x00: opl_index(value, 0); return; // 2x1: FM Music Data Port // 2x9 and 389 are aliases case BX_SB16_IO + 0x01: case BX_SB16_IO + 0x09: case BX_SB16_IOADLIB + 0x01: opl_data(value, 0); return; // 2x2: Advanced FM Music Register Port // or (for SBPro1) FM Music Register Port 2 // 38a is an alias case BX_SB16_IO + 0x02: case BX_SB16_IOADLIB + 0x02: opl_index(value, 1); return; // 2x3: Advanced FM Music Data Port // or (for SBPro1) FM Music Data Port 2 // 38b is an alias case BX_SB16_IO + 0x03: case BX_SB16_IOADLIB + 0x03: opl_data(value, 1); return; // 2x4: Mixer Register Port case BX_SB16_IO + 0x04: mixer_writeregister(value); return; // 2x5: Mixer Data Portr, case BX_SB16_IO + 0x05: mixer_writedata(value); return; // 2x6: DSP Reset case BX_SB16_IO + 0x06: dsp_reset(value); return; // 2x7: reserved case BX_SB16_IO + 0x07: break; // 2x8: FM Music Register Port (OPL-2) // handled above // 2x9: FM Music Data Port // handled above // 2xa: reserved (r: DSP Data Port) case BX_SB16_IO + 0x0a: break; // 2xb: reserved case BX_SB16_IO + 0x0b: break; // 2xc: DSP Write Command/Data case BX_SB16_IO + 0x0c: dsp_datawrite(value); return; // 2xd: reserved case BX_SB16_IO + 0x0d: break; // 2xe: reserved (r: DSP Buffer Status) case BX_SB16_IO + 0x0e: break; // 2xf: reserved case BX_SB16_IO + 0x0f: break; // 3x0: MPU Command Port case BX_SB16_IOMPU + 0x00: mpu_datawrite(value); return; // 3x1: MPU Data Port case BX_SB16_IOMPU + 0x01: mpu_command(value); return; // 3x2: reserved case BX_SB16_IOMPU + 0x02: break; // 3x3: *Emulator* Port case BX_SB16_IOMPU + 0x03: emul_write(value); return; } // if we arrive here, the port is unsupported writelog(3, "Write access to 0x%04x (value = 0x%02x): unsupported port!", address, value); } void bx_sb16_c::writelog(int loglev, const char *str, ...) { // append a line to the log file, if desired if (BX_SB16_THIS loglevel >= loglev) { fprintf(LOGFILE, FMT_TICK, bx_pc_system.time_ticks()); fprintf(LOGFILE, " (%d) ", loglev); va_list ap; va_start(ap, str); vfprintf(LOGFILE, str, ap); va_end(ap); fprintf(LOGFILE, "\n"); fflush(LOGFILE); } } // the round-robin FIFO buffers of the SB16 bx_sb16_buffer::bx_sb16_buffer() { length = 0; // total bytes in buffer head = 0; // pointer to next slot available for new data tail = 0; // pointer to next slot to be read from buffer = NULL; // pointer to the actual data } void bx_sb16_buffer::init(int bufferlen) { if (buffer != NULL) // Was it initialized before? delete buffer; length = bufferlen; buffer = new Bit8u[length]; if (buffer == NULL) length = 0; // This will be checked later reset(); } void bx_sb16_buffer::reset() { head = 0; // Reset the pointers tail = 0; clearcommand(); // no current command set } bx_sb16_buffer::~bx_sb16_buffer() { if (buffer != NULL) delete [] buffer; buffer = NULL; length = 0; } // Report how many bytes are available int bx_sb16_buffer::bytes(void) { if (empty() != 0) return 0; // empty / not initialized int bytes = head - tail; if (bytes < 0) bytes += length; return (bytes); } // This puts one byte into the buffer bx_bool bx_sb16_buffer::put(Bit8u data) { if (full() != 0) return 0; // buffer full buffer[head++] = data; // Write data, and increase write pointer head %= length; // wrap it around so it stays inside the data return 1; // put was successful } // This writes a formatted string to the buffer bx_bool bx_sb16_buffer::puts(const char *data, ...) { if (data == NULL) return 0; // invalid string //char string[length]; char *string; int index = 0; string = (char *) malloc(length); va_list ap; va_start(ap, data); vsprintf(string, data, ap); va_end(ap); if ((int) strlen(string) >= length) BX_PANIC(("bx_sb16_buffer: puts() too long!")); while (string[index] != 0) { if (put((Bit8u) string[index]) == 0) return 0; // buffer full index++; } return 1; } // This returns if the buffer is full, i.e. if a put will fail bx_bool bx_sb16_buffer::full(void) { if (length == 0) return 1; // not initialized if (((head + 1) % length) == tail) return 1; // buffer full return 0; // buffer has some space left } // This reads the next available byte from the buffer bx_bool bx_sb16_buffer::get(Bit8u *data) { if (empty() != 0) { // Buffer is empty. Still, if it was initialized, return // the last byte again. if (length > 0) (*data) = buffer[ (tail - 1) % length ]; return 0; // buffer empty } (*data) = buffer[tail++]; // read data and increase read pointer tail %= length; // and wrap it around to stay inside the data return 1; // get was successful } // Read a word in lo/hi order bx_bool bx_sb16_buffer::getw(Bit16u *data) { Bit8u dummy; if (bytes() < 2) { if (bytes() == 1) { get(&dummy); *data = (Bit16u) dummy; } else dummy = 0; return 0; } get(&dummy); *data = (Bit16u) dummy; get(&dummy); *data |= ((Bit16u) dummy) << 8; return 1; } // Read a word in hi/lo order bx_bool bx_sb16_buffer::getw1(Bit16u *data) { Bit8u dummy; if (bytes() < 2) { if (bytes() == 1) { get(&dummy); *data = ((Bit16u) dummy) << 8; } else dummy = 0; return 0; } get(&dummy); *data = ((Bit16u) dummy) << 8; get(&dummy); *data |= (Bit16u) dummy; return 1; } // This returns if the buffer is empty, i.e. if a get will fail bx_bool bx_sb16_buffer::empty(void) { if (length == 0) return 1; // not inialized if (head == tail) return 1; // buffer empty return 0; // buffer contains data } // Flushes the buffer void bx_sb16_buffer::flush(void) { tail = head; return; } // Peeks ahead in the buffer // Warning: No checking if result is valid. Must call bytes() to check that! Bit8u bx_sb16_buffer::peek(int offset) { return buffer[(tail + offset) % length]; } // Set a new active command void bx_sb16_buffer::newcommand(Bit8u newcmd, int bytes) { command = newcmd; havecommand = 1; bytesneeded = bytes; } // Return the currently active command Bit8u bx_sb16_buffer::currentcommand(void) { return command; } // Clear the active command void bx_sb16_buffer::clearcommand(void) { command = 0; havecommand = 0; bytesneeded = 0; } // return if the command has received all necessary bytes bx_bool bx_sb16_buffer::commanddone(void) { if (hascommand() == 0) return 0; // no command pending - not done then if (bytes() >= bytesneeded) return 1; // yes, it's done return 0; // no, it's not } // return if there is a command pending bx_bool bx_sb16_buffer::hascommand(void) { return havecommand; } int bx_sb16_buffer::commandbytes(void) { return bytesneeded; } // runtime parameter handler Bit64s bx_sb16_c::sb16_param_handler(bx_param_c *param, int set, Bit64s val) { if (set) { char pname[BX_PATHNAME_LEN]; param->get_param_path(pname, BX_PATHNAME_LEN); if (!strcmp(pname, BXPN_SB16_DMATIMER)) { BX_SB16_THIS dmatimer = (Bit32u)val; } else if (!strcmp(pname, BXPN_SB16_LOGLEVEL)) { BX_SB16_THIS loglevel = (int)val; } else { BX_PANIC(("sb16_param_handler called with unexpected parameter '%s'", pname)); } } return val; } #endif /* if BX_SUPPORT_SB16 */ bochs-2.6/iodev/sound/soundosx.cc0000644000175000017500000004655112020641502016767 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundosx.cc 10977 2012-01-15 07:52:04Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // This file (SOUNDOSX.CC) written and donated by Brian Huffman #ifdef PARANOID #include #endif #include "iodev.h" #include "soundmod.h" #include "soundosx.h" #if defined(macintosh) && BX_SUPPORT_SOUNDLOW #define LOG_THIS device-> #if BX_WITH_MACOS #include #else #include #include #include #include #include #include #include #endif #include #if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1030) #define BX_SOUND_OSX_CONVERTER_NEW_API 1 #endif #ifdef BX_SOUND_OSX_use_converter #ifndef BX_SOUND_OSX_CONVERTER_NEW_API OSStatus MyRenderer (void *inRefCon, AudioUnitRenderActionFlags inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, AudioBuffer *ioData); OSStatus MyACInputProc (AudioConverterRef inAudioConverter, UInt32* outDataSize, void** outData, void* inUserData); #else OSStatus MyRenderer (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); OSStatus MyACInputProc (AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData); #endif #endif // Global variables #ifdef BX_SOUND_OSX_use_converter AUGraph MidiGraph; AudioUnit synthUnit; #endif #ifdef BX_SOUND_OSX_use_quicktime SndChannelPtr WaveChannel; ExtSoundHeader WaveInfo; ExtSoundHeader WaveHeader[BX_SOUND_OSX_NBUF]; #endif #ifdef BX_SOUND_OSX_use_converter AudioUnit WaveOutputUnit = NULL; AudioConverterRef WaveConverter = NULL; #endif bx_sound_osx_c::bx_sound_osx_c(logfunctions *dev) :bx_sound_lowlevel_c(dev) { MidiOpen = 0; WaveOpen = 0; head = 0; tail = 0; for (int i=0; i=1) ? data[0] : 0; Bit8u arg2 = (length >=2) ? data[1] : 0; MusicDeviceMIDIEvent (synthUnit, command, arg1, arg2, delta); } else { MusicDeviceSysEx (synthUnit, data, length); } #endif return BX_SOUNDLOW_OK; } int bx_sound_osx_c::closemidioutput() { BX_DEBUG(("closemidioutput()")); MidiOpen = 0; #ifdef BX_SOUND_OSX_use_converter AUGraphStop (MidiGraph); AUGraphClose (MidiGraph); #endif return BX_SOUNDLOW_OK; } #ifdef BX_SOUND_OSX_use_quicktime #if BX_WITH_MACOS pascal #endif void WaveCallbackProc (SndChannelPtr chan, SndCommand *cmd) { // a new buffer is available, so increment tail pointer int *tail = (int *) (cmd->param2); (*tail)++; } #endif int bx_sound_osx_c::openwaveoutput(const char *wavedev) { OSStatus err; BX_DEBUG(("openwaveoutput(%s)", wavedev)); // open the default output unit #ifdef BX_SOUND_OSX_use_quicktime err = SndNewChannel (&WaveChannel, sampledSynth, 0, NewSndCallBackUPP(WaveCallbackProc)); if (err != noErr) return BX_SOUNDLOW_ERR; #endif #ifdef BX_SOUND_OSX_use_converter #ifndef BX_SOUND_OSX_CONVERTER_NEW_API err = OpenDefaultAudioOutput (&WaveOutputUnit); if (err != noErr) return BX_SOUNDLOW_ERR; AudioUnitInputCallback input; input.inputProc = MyRenderer; input.inputProcRefCon = (void *) this; AudioUnitSetProperty (WaveOutputUnit, kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(input)); #else ComponentDescription desc; desc.componentType = kAudioUnitType_Output; desc.componentSubType = kAudioUnitSubType_DefaultOutput; desc.componentManufacturer = kAudioUnitManufacturer_Apple; desc.componentFlags = 0; desc.componentFlagsMask = 0; Component c = FindNextComponent(NULL, &desc); if (c == NULL) { BX_ERROR(("Core Audio: Unable to find default audio output component\n")); return BX_SOUNDLOW_ERR; } err = OpenAComponent(c, &WaveOutputUnit); if (err) { BX_ERROR(("Core Audio: Unable to open audio output (err=%X)\n", (unsigned int)err)); return BX_SOUNDLOW_ERR; } AURenderCallbackStruct input; input.inputProc = MyRenderer; input.inputProcRefCon = (void *) this; err = AudioUnitSetProperty (WaveOutputUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(input)); if (err) { BX_ERROR(("Core Audio: AudioUnitSetProperty error (err=%X)\n", (unsigned int)err)); return BX_SOUNDLOW_ERR; } #endif err = AudioUnitInitialize (WaveOutputUnit); if (err) { BX_ERROR(("Core Audio: AudioUnitInitialize error (err=%X)\n", (unsigned int)err)); return BX_SOUNDLOW_ERR; } #endif WaveOpen = 1; return BX_SOUNDLOW_OK; } #ifdef BX_SOUND_OSX_use_converter OSStatus bx_sound_osx_c::core_audio_pause() { OSStatus err = noErr; if (WaveOutputUnit) { err = AudioOutputUnitStop (WaveOutputUnit); if (err) { BX_ERROR(("Core Audio: nextbuffer(): AudioOutputUnitStop (err=%X)\n", (unsigned int)err)); } WavePlaying = 0; } return err; } OSStatus bx_sound_osx_c::core_audio_resume() { OSStatus err = noErr; if (WaveConverter) { err = AudioConverterReset (WaveConverter); if (err) { BX_ERROR(("Core Audio: core_audio_resume(): AudioConverterReset (err=%X)\n", (unsigned int)err)); return err; } } if (WaveOutputUnit) { err = AudioOutputUnitStart (WaveOutputUnit); if (err) { BX_ERROR(("Core Audio: core_audio_resume(): AudioOutputUnitStart (err=%X)\n", (unsigned int)err)); return err; } WavePlaying = 1; } return err; } #endif int bx_sound_osx_c::startwaveplayback(int frequency, int bits, bx_bool stereo, int format) { #ifdef BX_SOUND_OSX_use_converter static int oldfreq, oldbits, oldformat; static bx_bool oldstereo; AudioStreamBasicDescription srcFormat, dstFormat; UInt32 formatSize = sizeof(AudioStreamBasicDescription); OSStatus err; #endif BX_DEBUG(("startwaveplayback(%d, %d, %d, %x)", frequency, bits, stereo, format)); #ifdef BX_SOUND_OSX_use_quicktime WaveInfo.samplePtr = NULL; WaveInfo.numChannels = stereo ? 2 : 1; WaveInfo.sampleRate = frequency << 16; // sampleRate is a 16.16 fixed-point value WaveInfo.loopStart = 0; WaveInfo.loopEnd = 0; WaveInfo.encode = extSH; // WaveInfo has type ExtSoundHeader WaveInfo.baseFrequency = 1; // not sure what means. It's only a Uint8. WaveInfo.numFrames = 0; //WaveInfo.AIFFSampleRate = frequency; // frequency as float80 WaveInfo.markerChunk = NULL; WaveInfo.instrumentChunks = NULL; WaveInfo.AESRecording = NULL; WaveInfo.sampleSize = bits * WaveInfo.numChannels; #endif #ifdef BX_SOUND_OSX_use_converter if ((frequency == oldfreq) && (bits == oldbits) && (stereo == oldstereo) && (format == oldformat)) return BX_SOUNDLOW_OK; // nothing to do oldfreq = frequency; oldbits = bits; oldstereo = stereo; oldformat = format; // update the source audio format UInt32 bytes = bits / 8; UInt32 channels = stereo ? 2 : 1; srcFormat.mSampleRate = (Float64) frequency; srcFormat.mFormatID = kAudioFormatLinearPCM; srcFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked; if (format & 1) srcFormat.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; srcFormat.mBytesPerPacket = channels * bytes; srcFormat.mFramesPerPacket = 1; srcFormat.mBytesPerFrame = channels * bytes; srcFormat.mChannelsPerFrame = channels; srcFormat.mBitsPerChannel = bytes * 8; if (WavePlaying) { err = AudioOutputUnitStop (WaveOutputUnit); if (err) BX_ERROR(("Core Audio: startwaveplayback(): AudioOutputUnitStop (err=%X)\n", (unsigned int)err)); } if (WaveConverter) { err = AudioConverterDispose (WaveConverter); if (err) BX_ERROR(("Core Audio: startwaveplayback(): AudioConverterDispose (err=%X)\n", (unsigned int)err)); } err = AudioUnitGetProperty (WaveOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &dstFormat, &formatSize); if (err) { BX_ERROR(("Core Audio: startwaveplayback(): AudioUnitGetProperty (err=%X)\n", (unsigned int)err)); return BX_SOUNDLOW_ERR; } #ifdef BX_SOUND_OSX_CONVERTER_NEW_API // force interleaved mode dstFormat.mFormatFlags |= kAudioFormatFlagIsNonInterleaved; dstFormat.mBytesPerPacket = dstFormat.mBytesPerFrame = (dstFormat.mBitsPerChannel + 7) / 8; err = AudioUnitSetProperty (WaveOutputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &dstFormat, sizeof(dstFormat)); if (err) { BX_ERROR(("Core Audio: startwaveplayback(): AudioUnitSetProperty (err=%X)\n", (unsigned int)err)); return BX_SOUNDLOW_ERR; } #endif err = AudioConverterNew (&srcFormat, &dstFormat, &WaveConverter); if (err) { BX_ERROR(("Core Audio: startwaveplayback(): AudioConverterNew (err=%X)\n", (unsigned int)err)); return BX_SOUNDLOW_ERR; } if (srcFormat.mChannelsPerFrame == 1 && dstFormat.mChannelsPerFrame == 2) { // map single-channel input to both output channels SInt32 map[2] = {0,0}; err = AudioConverterSetProperty (WaveConverter, kAudioConverterChannelMap, sizeof(map), (void*) map); if (err) { BX_ERROR(("Core Audio: startwaveplayback(): AudioConverterSetProperty (err=%X)\n", (unsigned int)err)); return BX_SOUNDLOW_ERR; } } if (WavePlaying) { if (core_audio_resume() != noErr) return BX_SOUNDLOW_ERR; } #endif return BX_SOUNDLOW_OK; } int bx_sound_osx_c::waveready() { // HACK: the -4 is to keep from overwriting buffers that // have been sent, but possibly not yet played. There // should be a better way of doing this. if (WaveOpen && (head - tail < BX_SOUND_OSX_NBUF-4)) { return BX_SOUNDLOW_OK; } else { #ifdef BX_SOUND_OSX_use_converter // If buffer is full, make sure sound is playing if (!WavePlaying) { if (core_audio_resume() != noErr) return BX_SOUNDLOW_ERR; } #endif return BX_SOUNDLOW_ERR; } } int bx_sound_osx_c::sendwavepacket(int length, Bit8u data[]) { #ifdef BX_SOUND_OSX_use_quicktime SndCommand mySndCommand; #endif BX_DEBUG(("sendwavepacket(%d, %p), head=%u", length, data, head)); // sanity check if ((!WaveOpen) || (head - tail >= BX_SOUND_OSX_NBUF)) return BX_SOUNDLOW_ERR; // find next available buffer int n = head++ % BX_SOUND_OSX_NBUF; // put data in buffer memcpy(WaveData[n], data, length); WaveLength[n] = length; #ifdef BX_SOUND_OSX_use_quicktime memcpy(&WaveHeader[n], &WaveInfo, sizeof(WaveInfo)); WaveHeader[n].samplePtr = (char *) (WaveData[n]); WaveHeader[n].numFrames = length * 8 / WaveInfo.sampleSize; #endif #ifdef BX_SOUND_OSX_use_converter // make sure that the sound is playing if (!WavePlaying) { if (core_audio_resume() != noErr) return BX_SOUNDLOW_ERR; } #endif #ifdef BX_SOUND_OSX_use_quicktime // queue buffer to play mySndCommand.cmd = bufferCmd; mySndCommand.param1 = 0; mySndCommand.param2 = (long)(&WaveHeader[n]); SndDoCommand(WaveChannel, &mySndCommand, TRUE); // queue callback for when buffer finishes mySndCommand.cmd = callBackCmd; mySndCommand.param1 = 0; mySndCommand.param2 = (long)(&tail); SndDoCommand(WaveChannel, &mySndCommand, TRUE); #endif return BX_SOUNDLOW_OK; } int bx_sound_osx_c::stopwaveplayback() { return BX_SOUNDLOW_OK; } int bx_sound_osx_c::closewaveoutput() { #ifdef BX_SOUND_OSX_use_converter if (WavePlaying) AudioOutputUnitStop (WaveOutputUnit); if (WaveConverter) AudioConverterDispose (WaveConverter); if (WaveOutputUnit) CloseComponent (WaveOutputUnit); WavePlaying = 0; WaveOpen = 0; WaveConverter = NULL; WaveOutputUnit = NULL; #endif return BX_SOUNDLOW_OK; } #ifdef BX_SOUND_OSX_use_converter #ifndef BX_SOUND_OSX_CONVERTER_NEW_API OSStatus MyRenderer (void *inRefCon, AudioUnitRenderActionFlags inActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, AudioBuffer *ioData) { OSStatus err; UInt32 size = ioData->mDataByteSize; err = AudioConverterFillBuffer (WaveConverter, MyACInputProc, inRefCon, &size, ioData->mData); return err; } OSStatus MyACInputProc (AudioConverterRef inAudioConverter, UInt32* outDataSize, void** outData, void* inUserData) { bx_sound_osx_c *self = (bx_sound_osx_c*) inUserData; self->nextbuffer ((int*) outDataSize, outData); return noErr; } #else OSStatus MyRenderer (void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { UInt32 packets; AudioStreamBasicDescription dstFormat; UInt32 formatSize = sizeof(AudioStreamBasicDescription); OSStatus err = noErr; err = AudioConverterGetProperty (WaveConverter, kAudioConverterCurrentOutputStreamDescription, &formatSize, &dstFormat); if (err) { return err; } packets = inNumberFrames / dstFormat.mFramesPerPacket; err = AudioConverterFillComplexBuffer(WaveConverter, MyACInputProc, inRefCon, &packets, ioData, NULL); return err; } OSStatus MyACInputProc (AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) { OSStatus err; bx_sound_osx_c *self = (bx_sound_osx_c*) inUserData; AudioStreamBasicDescription srcFormat; UInt32 formatSize = sizeof(AudioStreamBasicDescription); err = AudioConverterGetProperty (inAudioConverter, kAudioConverterCurrentInputStreamDescription, &formatSize, &srcFormat); if (err) { *ioNumberDataPackets = 0; return err; } int outDataSize = *ioNumberDataPackets * srcFormat.mBytesPerPacket; void *outData = ioData->mBuffers[0].mData; self->nextbuffer ((int*) &outDataSize, &outData); *ioNumberDataPackets = outDataSize / srcFormat.mBytesPerPacket; ioData->mBuffers[0].mDataByteSize = outDataSize; ioData->mBuffers[0].mData = outData; return noErr; } #endif void bx_sound_osx_c::nextbuffer (int *outDataSize, void **outData) { BX_DEBUG(("nextbuffer(), tail=%u", tail)); if (head - tail <= 0) { *outData = NULL; *outDataSize = 0; // We are getting behind, so stop the output for now core_audio_pause(); } else { int n = tail % BX_SOUND_OSX_NBUF; *outData = (void *) (WaveData[n]); *outDataSize = WaveLength[n]; tail++; } } #endif int bx_sound_osx_c::openwaveinput(const char *wavedev, sound_record_handler_t rh) { UNUSED(wavedev); record_handler = rh; if (rh != NULL) { record_timer_index = bx_pc_system.register_timer(this, record_timer_handler, 1, 1, 0, "soundosx"); // record timer: inactive, continuous, frequency variable } // TODO return BX_SOUNDLOW_OK; } int bx_sound_osx_c::startwaverecord(int frequency, int bits, bx_bool stereo, int format) { Bit64u timer_val; Bit8u shift = 0; UNUSED(format); if (record_timer_index != BX_NULL_TIMER_HANDLE) { if (bits == 16) shift++; if (stereo) shift++; record_packet_size = (frequency / 10) << shift; // 0.1 sec if (record_packet_size > BX_SOUNDLOW_WAVEPACKETSIZE) { record_packet_size = BX_SOUNDLOW_WAVEPACKETSIZE; } timer_val = (Bit64u)record_packet_size * 1000000 / (frequency << shift); bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1); } // TODO return BX_SOUNDLOW_OK; } int bx_sound_osx_c::getwavepacket(int length, Bit8u data[]) { // TODO memset(data, 0, length); return BX_SOUNDLOW_OK; } int bx_sound_osx_c::stopwaverecord() { if (record_timer_index != BX_NULL_TIMER_HANDLE) { bx_pc_system.deactivate_timer(record_timer_index); } // TODO return BX_SOUNDLOW_OK; } int bx_sound_osx_c::closewaveinput() { stopwaverecord(); // TODO return BX_SOUNDLOW_OK; } void bx_sound_osx_c::record_timer_handler(void *this_ptr) { bx_sound_osx_c *class_ptr = (bx_sound_osx_c *) this_ptr; class_ptr->record_timer(); } void bx_sound_osx_c::record_timer(void) { record_handler(this->device, record_packet_size); } #endif // defined(macintosh) bochs-2.6/iodev/sound/soundlnx.h0000644000175000017500000000626012020641502016612 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundlnx.h 11213 2012-06-08 20:49:39Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // Josef Drexler coded the original version of the lowlevel sound support // for Linux using OSS. The current version also supports OSS on FreeBSD and // ALSA PCM input/output on Linux. #if (defined(linux) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) #define BX_SOUND_LINUX_BUFSIZE BX_SOUNDLOW_WAVEPACKETSIZE * 2 #if BX_HAVE_ALSASOUND #define ALSA_PCM_NEW_HW_PARAMS_API #include #endif class bx_sound_linux_c : public bx_sound_lowlevel_c { public: bx_sound_linux_c(logfunctions *dev); virtual ~bx_sound_linux_c(); virtual int get_type() {return BX_SOUNDLOW_LINUX;} virtual int waveready(); virtual int midiready(); virtual int openmidioutput(const char *mididev); virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]); virtual int closemidioutput(); virtual int openwaveoutput(const char *wavedev); virtual int startwaveplayback(int frequency, int bits, bx_bool stereo, int format); virtual int sendwavepacket(int length, Bit8u data[]); virtual int stopwaveplayback(); virtual int closewaveoutput(); virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh); virtual int startwaverecord(int frequency, int bits, bx_bool stereo, int format); virtual int getwavepacket(int length, Bit8u data[]); virtual int stopwaverecord(); virtual int closewaveinput(); static void record_timer_handler(void *); void record_timer(void); private: #if BX_HAVE_ALSASOUND int alsa_seq_open(const char *alsadev); int alsa_seq_output(int delta, int command, int length, Bit8u data[]); int alsa_pcm_open(bx_bool input, int frequency, int bits, bx_bool stereo, int format); int alsa_pcm_write(); bx_bool use_alsa_seq; bx_bool use_alsa_pcm; struct { snd_seq_t *handle; int source_port; } alsa_seq; struct { snd_pcm_t *handle; snd_pcm_uframes_t frames; int alsa_bufsize, audio_bufsize; char *buffer; } alsa_pcm[2]; #endif FILE *midi; char *wave_device[2]; int wave_fd[2]; struct { int oldfreq, oldbits, oldformat; bx_bool oldstereo; } wave_ch[2]; Bit8u audio_buffer[2][BX_SOUND_LINUX_BUFSIZE]; }; #endif bochs-2.6/iodev/sound/soundmod.h0000644000175000017500000000660012020641502016566 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundmod.h 11214 2012-06-09 10:12:05Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2011-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Common code for sound lowlevel modules // this is the size of a sound packet used for sending and receiving // it should not be too large to avoid lag, and not too // small to avoid unnecessary overhead. #define BX_SOUNDLOW_WAVEPACKETSIZE 8192 // Definitions for the output functions #define BX_SOUNDLOW_OK 0 #define BX_SOUNDLOW_ERR 1 // Lowlvel sound modules #define BX_SOUNDLOW_DUMMY 0 #define BX_SOUNDLOW_LINUX 1 #define BX_SOUNDLOW_OSX 2 #define BX_SOUNDLOW_WIN 3 #define BX_SOUNDLOW_SDL 4 typedef Bit32u (*sound_record_handler_t)(void *arg, Bit32u len); class bx_sound_lowlevel_c; // Pseudo device that loads the lowlevel sound module class bx_soundmod_ctl_c : public bx_soundmod_ctl_stub_c { public: bx_soundmod_ctl_c(); virtual ~bx_soundmod_ctl_c() {} virtual void* init_module(const char *type, logfunctions *device); virtual bx_bool beep_on(float frequency); virtual bx_bool beep_off(); private: bx_sound_lowlevel_c *soundmod; }; // The class with the input/output functions class bx_sound_lowlevel_c : public logfunctions { public: /* These functions are the sound lowlevel functions, sending the music or sending/receiving sound to/from the OS specific driver. They are in a different file (soundxxx.cc) because they are non-portable, while everything in the soundcard code is portable */ bx_sound_lowlevel_c(logfunctions *dev); virtual ~bx_sound_lowlevel_c(); virtual int get_type() {return BX_SOUNDLOW_DUMMY;} virtual int waveready(); virtual int midiready(); virtual int openmidioutput(const char *mididev); virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]); virtual int closemidioutput(); virtual int openwaveoutput(const char *wavedev); virtual int startwaveplayback(int frequency, int bits, bx_bool stereo, int format); virtual int sendwavepacket(int length, Bit8u data[]); virtual int stopwaveplayback(); virtual int closewaveoutput(); virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh); virtual int startwaverecord(int frequency, int bits, bx_bool stereo, int format); virtual int getwavepacket(int length, Bit8u data[]); virtual int stopwaverecord(); virtual int closewaveinput(); static void record_timer_handler(void *); void record_timer(void); protected: logfunctions *device; int record_timer_index; int record_packet_size; sound_record_handler_t record_handler; }; bochs-2.6/iodev/sound/es1370.h0000644000175000017500000000667012020641502015667 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: es1370.h 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // ES1370 soundcard support (ported from QEMU) // // Copyright (c) 2005 Vassili Karpov (malc) // Copyright (C) 2011 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_ES1370_H #define BX_IODEV_ES1370_H #if BX_USE_ES1370_SMF # define BX_ES1370_SMF static # define BX_ES1370_THIS theES1370Device-> # define BX_ES1370_THIS_PTR theES1370Device #else # define BX_ES1370_SMF # define BX_ES1370_THIS this-> # define BX_ES1370_THIS_PTR this #endif typedef struct { Bit32u shift; Bit32u leftover; Bit32u scount; Bit32u frame_addr; Bit32u frame_cnt; } chan_t; typedef struct { chan_t chan[3]; Bit32u ctl; Bit32u status; Bit32u mempage; Bit32u codec; Bit32u sctl; int dac1_timer_index; int dac2_timer_index; bx_bool dac_outputinit; bx_bool adc_inputinit; int dac_nr_active; Bit16u dac_packet_size[2]; Bit8u devfunc; } bx_es1370_t; // forward definition class bx_sound_lowlevel_c; class bx_es1370_c : public bx_devmodel_c, bx_pci_device_stub_c { public: bx_es1370_c(); virtual ~bx_es1370_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); private: bx_es1370_t s; BX_ES1370_SMF void set_irq_level(bx_bool level); BX_ES1370_SMF void update_status(Bit32u new_status); BX_ES1370_SMF void check_lower_irq(Bit32u sctl); BX_ES1370_SMF void update_voices(Bit32u ctl, Bit32u sctl, bx_bool force); BX_ES1370_SMF void run_channel(unsigned channel, int timer_id, Bit32u buflen); static void es1370_timer_handler(void *); void es1370_timer(void); static Bit32u es1370_adc_handler(void *, Bit32u len); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_ES1370_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif bx_sound_lowlevel_c *soundmod; }; #endif bochs-2.6/iodev/sound/soundmod.cc0000644000175000017500000001610712020641502016727 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundmod.cc 11214 2012-06-09 10:12:05Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2011-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Common sound module code and dummy sound lowlevel functions // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_SOUNDLOW #include "soundmod.h" #include "soundlnx.h" #include "soundosx.h" #include "soundwin.h" #include "soundsdl.h" #ifndef WIN32 #include #endif #if BX_WITH_SDL #include #endif #define LOG_THIS theSoundModCtl-> bx_soundmod_ctl_c* theSoundModCtl = NULL; int libsoundmod_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theSoundModCtl = new bx_soundmod_ctl_c; bx_devices.pluginSoundModCtl = theSoundModCtl; return 0; // Success } else { return -1; } } void libsoundmod_LTX_plugin_fini(void) { delete theSoundModCtl; } bx_soundmod_ctl_c::bx_soundmod_ctl_c() { put("sound", "SOUND"); soundmod = NULL; } void* bx_soundmod_ctl_c::init_module(const char *type, logfunctions *device) { if (!strcmp(type, "default")) { soundmod = new BX_SOUND_LOWLEVEL_C(device); #if BX_WITH_SDL } else if (!strcmp(type, "sdl")) { soundmod = new bx_sound_sdl_c(device); #endif } else if (!strcmp(type, "dummy")) { soundmod = new bx_sound_lowlevel_c(device); } else { BX_PANIC(("unknown sound module type '%s'", type)); } return soundmod; } #ifndef WIN32 pthread_t thread; #endif Bit8u *beep_buffer; int beep_bytes, beep_bufsize; bx_bool beep_active = 0; #ifdef WIN32 DWORD WINAPI beep_thread(LPVOID indata) #else void beep_thread(void *indata) #endif { Bit8u level; int i, j; beep_active = 1; bx_sound_lowlevel_c *soundmod = (bx_sound_lowlevel_c*)indata; level = 0x40; i = 0; while (beep_bytes > 0) { j = 0; do { beep_buffer[j++] = level; if ((++i % beep_bytes) == 0) level ^= 0x40; } while (j < beep_bufsize); soundmod->sendwavepacket(beep_bufsize, beep_buffer); if (soundmod->get_type() == BX_SOUNDLOW_WIN) { #ifdef WIN32 Sleep(100); #endif } else if (soundmod->get_type() == BX_SOUNDLOW_SDL) { #if BX_WITH_SDL SDL_Delay(100); #endif } } soundmod->stopwaveplayback(); free(beep_buffer); beep_active = 0; #ifdef WIN32 return 0; #else pthread_exit(NULL); #endif } bx_bool bx_soundmod_ctl_c::beep_on(float frequency) { if (soundmod != NULL) { BX_DEBUG(("Beep ON (frequency=%.2f)",frequency)); if (!beep_active) { soundmod->startwaveplayback(44100, 8, 0, 0); beep_bytes = (int)(44100.0 / frequency / 2); beep_bufsize = 4410; beep_buffer = (Bit8u*)malloc(beep_bufsize); #ifdef WIN32 DWORD threadID; CreateThread(NULL, 0, beep_thread, soundmod, 0, &threadID); #else pthread_create(&thread, NULL, (void *(*)(void *))&beep_thread, soundmod); #endif } return 1; } return 0; } bx_bool bx_soundmod_ctl_c::beep_off() { if (soundmod != NULL) { BX_DEBUG(("Beep OFF")); if (beep_active) { beep_bytes = 0; #ifdef WIN32 while (beep_active) Sleep(1); #else pthread_join(thread, NULL); #endif } return 1; } return 0; } // The dummy sound lowlevel functions. They don't do anything. bx_sound_lowlevel_c::bx_sound_lowlevel_c(logfunctions *dev) { device = dev; record_timer_index = BX_NULL_TIMER_HANDLE; } bx_sound_lowlevel_c::~bx_sound_lowlevel_c() { } int bx_sound_lowlevel_c::waveready() { return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::midiready() { return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::openmidioutput(const char *mididev) { UNUSED(mididev); return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::sendmidicommand(int delta, int command, int length, Bit8u data[]) { UNUSED(delta); UNUSED(command); UNUSED(length); UNUSED(data); return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::closemidioutput() { return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::openwaveoutput(const char *wavedev) { UNUSED(wavedev); return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::startwaveplayback(int frequency, int bits, bx_bool stereo, int format) { UNUSED(frequency); UNUSED(bits); UNUSED(stereo); UNUSED(format); return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::sendwavepacket(int length, Bit8u data[]) { UNUSED(length); UNUSED(data); return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::stopwaveplayback() { return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::closewaveoutput() { return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::openwaveinput(const char *wavedev, sound_record_handler_t rh) { UNUSED(wavedev); record_handler = rh; if (rh != NULL) { record_timer_index = bx_pc_system.register_timer(this, record_timer_handler, 1, 1, 0, "soundmod"); // record timer: inactive, continuous, frequency variable } return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::startwaverecord(int frequency, int bits, bx_bool stereo, int format) { Bit64u timer_val; Bit8u shift = 0; UNUSED(format); if (record_timer_index != BX_NULL_TIMER_HANDLE) { if (bits == 16) shift++; if (stereo) shift++; record_packet_size = (frequency / 10) << shift; // 0.1 sec if (record_packet_size > BX_SOUNDLOW_WAVEPACKETSIZE) { record_packet_size = BX_SOUNDLOW_WAVEPACKETSIZE; } timer_val = (Bit64u)record_packet_size * 1000000 / (frequency << shift); bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1); } return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::getwavepacket(int length, Bit8u data[]) { memset(data, 0, length); return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::stopwaverecord() { if (record_timer_index != BX_NULL_TIMER_HANDLE) { bx_pc_system.deactivate_timer(record_timer_index); } return BX_SOUNDLOW_OK; } int bx_sound_lowlevel_c::closewaveinput() { stopwaverecord(); return BX_SOUNDLOW_OK; } void bx_sound_lowlevel_c::record_timer_handler(void *this_ptr) { bx_sound_lowlevel_c *class_ptr = (bx_sound_lowlevel_c *) this_ptr; class_ptr->record_timer(); } void bx_sound_lowlevel_c::record_timer(void) { record_handler(this->device, record_packet_size); } #endif bochs-2.6/iodev/sound/es1370.cc0000644000175000017500000006430212020641502016021 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: es1370.cc 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // ES1370 soundcard support (ported from QEMU) // // Copyright (c) 2005 Vassili Karpov (malc) // Copyright (C) 2011 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_ES1370 #include "pci.h" #include "es1370.h" #include "soundmod.h" #include "soundlnx.h" #include "soundwin.h" #include "soundosx.h" #include "soundsdl.h" #define LOG_THIS theES1370Device-> bx_es1370_c* theES1370Device = NULL; const Bit8u es1370_iomask[64] = {7, 1, 3, 1, 7, 1, 3, 1, 1, 3, 1, 0, 7, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 7, 1, 3, 1, 6, 0, 2, 0, 6, 0, 2, 0, 6, 0, 2, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0}; #define ES1370_CTL 0x00 #define ES1370_STATUS 0x04 #define ES1370_UART_DATA 0x08 #define ES1370_UART_STATUS 0x09 #define ES1370_UART_CTL 0x09 #define ES1370_UART_TEST 0x0a #define ES1370_MEMPAGE 0x0c #define ES1370_CODEC 0x10 #define ES1370_SCTL 0x20 #define ES1370_DAC1_SCOUNT 0x24 #define ES1370_DAC2_SCOUNT 0x28 #define ES1370_ADC_SCOUNT 0x2c #define ES1370_DAC1_FRAMEADR 0xc30 #define ES1370_DAC1_FRAMECNT 0xc34 #define ES1370_DAC2_FRAMEADR 0xc38 #define ES1370_DAC2_FRAMECNT 0xc3c #define ES1370_ADC_FRAMEADR 0xd30 #define ES1370_ADC_FRAMECNT 0xd34 #define ES1370_PHA_FRAMEADR 0xd38 #define ES1370_PHA_FRAMECNT 0xd3c #define STAT_INTR 0x80000000 #define STAT_DAC1 0x00000004 #define STAT_DAC2 0x00000002 #define STAT_ADC 0x00000001 #define SCTRL_R1INTEN 0x00000400 #define SCTRL_P2INTEN 0x00000200 #define SCTRL_P1INTEN 0x00000100 #define DAC1_CHANNEL 0 #define DAC2_CHANNEL 1 #define ADC_CHANNEL 2 const char chan_name[3][5] = {"DAC1", "DAC2", "ADC"}; const Bit16u dac1_freq[4] = {5512, 11025, 22050, 44100}; const Bit16u ctl_ch_en[3] = {0x0040, 0x0020, 0x0010}; const Bit16u sctl_ch_pause[3] = {0x0800, 0x1000, 0x0000}; const Bit16u sctl_loop_sel[3] = {0x2000, 0x4000, 0x8000}; // builtin configuration handling functions void es1370_init_options(void) { bx_param_c *sound = SIM->get_param("sound"); bx_list_c *menu = new bx_list_c(sound, "es1370", "ES1370 Configuration"); menu->set_options(menu->SHOW_PARENT); menu->set_enabled(BX_SUPPORT_ES1370); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", "Enable ES1370 emulation", "Enables the ES1370 emulation", 0); enabled->set_enabled(BX_SUPPORT_ES1370); bx_param_filename_c *wavedev = new bx_param_filename_c(menu, "wavedev", "Wave device", "This is the device where the wave output is sent to", "", BX_PATHNAME_LEN); bx_list_c *deplist = new bx_list_c(NULL); deplist->add(wavedev); enabled->set_dependent_list(deplist); } Bit32s es1370_options_parser(const char *context, int num_params, char *params[]) { if (!strcmp(params[0], "es1370")) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_ES1370); for (int i = 1; i < num_params; i++) { if (!strncmp(params[i], "enabled=", 8)) { SIM->get_param_bool("enabled", base)->set(atol(¶ms[i][8])); } else if (!strncmp(params[i], "wavedev=", 8)) { SIM->get_param_string("wavedev", base)->set(¶ms[i][8]); } else { BX_ERROR(("%s: unknown parameter for es1370 ignored.", context)); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s es1370_options_save(FILE *fp) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_ES1370); fprintf(fp, "es1370: enabled=%d", SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { fprintf(fp, ", wavedev=%s", SIM->get_param_string("wavedev", base)->getptr()); } fprintf(fp, "\n"); return 0; } // device plugin entry points int libes1370_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theES1370Device = new bx_es1370_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theES1370Device, BX_PLUGIN_ES1370); // add new configuration parameter for the config interface es1370_init_options(); // register add-on option for bochsrc and command line SIM->register_addon_option("es1370", es1370_options_parser, es1370_options_save); return 0; // Success } void libes1370_LTX_plugin_fini(void) { SIM->unregister_addon_option("es1370"); bx_list_c *menu = (bx_list_c*)SIM->get_param("sound"); menu->remove("es1370"); delete theES1370Device; } // the device object bx_es1370_c::bx_es1370_c() { put("es1370", "E1370"); memset(&s, 0, sizeof(bx_es1370_t)); s.dac1_timer_index = BX_NULL_TIMER_HANDLE; s.dac2_timer_index = BX_NULL_TIMER_HANDLE; soundmod = NULL; } bx_es1370_c::~bx_es1370_c() { if (s.dac_outputinit) { soundmod->closewaveoutput(); } if (s.adc_inputinit) { soundmod->closewaveinput(); } delete soundmod; SIM->get_bochs_root()->remove("es1370"); BX_DEBUG(("Exit")); } void bx_es1370_c::init(void) { // Read in values from config interface bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_SOUND_ES1370); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", base)->get()) { BX_INFO(("ES1370 disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("es1370"))->set(0); return; } BX_ES1370_THIS s.devfunc = 0x00; DEV_register_pci_handlers(this, &BX_ES1370_THIS s.devfunc, BX_PLUGIN_ES1370, "Experimental ES1370 soundcard"); for (unsigned i=0; i<256; i++) { BX_ES1370_THIS pci_conf[i] = 0x0; } BX_ES1370_THIS pci_base_address[0] = 0; char *wavedev = SIM->get_param_string(BXPN_ES1370_WAVEDEV)->getptr(); if (!strcmp(wavedev, "sdl")) { BX_ES1370_THIS soundmod = DEV_sound_init_module("sdl", BX_ES1370_THIS_PTR); } else { BX_ES1370_THIS soundmod = DEV_sound_init_module("default", BX_ES1370_THIS_PTR); } int ret = BX_ES1370_THIS soundmod->openwaveoutput(wavedev); if (ret != BX_SOUNDLOW_OK) { BX_ERROR(("could not open wave output device")); BX_ES1370_THIS s.dac_outputinit = 0; } else { BX_ES1370_THIS s.dac_outputinit = 1; } BX_ES1370_THIS s.adc_inputinit = 0; BX_ES1370_THIS s.dac_nr_active = -1; if (BX_ES1370_THIS s.dac1_timer_index == BX_NULL_TIMER_HANDLE) { BX_ES1370_THIS s.dac1_timer_index = bx_pc_system.register_timer (BX_ES1370_THIS_PTR, es1370_timer_handler, 1, 1, 0, "es1370.dac1"); // DAC1 timer: inactive, continuous, frequency variable } if (BX_ES1370_THIS s.dac2_timer_index == BX_NULL_TIMER_HANDLE) { BX_ES1370_THIS s.dac2_timer_index = bx_pc_system.register_timer (BX_ES1370_THIS_PTR, es1370_timer_handler, 1, 1, 0, "es1370.dac2"); // DAC2 timer: inactive, continuous, frequency variable } BX_INFO(("ES1370 initialized")); } void bx_es1370_c::reset(unsigned type) { unsigned i; static const struct reset_vals_t { unsigned addr; unsigned char val; } reset_vals[] = { { 0x00, 0x74 }, { 0x01, 0x12 }, { 0x02, 0x00 }, { 0x03, 0x50 }, { 0x04, 0x05 }, { 0x05, 0x00 }, // command_io { 0x06, 0x00 }, { 0x07, 0x04 }, // status { 0x08, 0x00 }, // revision number { 0x09, 0x00 }, // interface { 0x0a, 0x01 }, // class_sub { 0x0b, 0x04 }, // class_base Multimedia Audio Device { 0x0e, 0x00 }, // header type generic // address space 0x10 - 0x13 { 0x10, 0x01 }, { 0x11, 0x00 }, { 0x12, 0x00 }, { 0x13, 0x00 }, { 0x2c, 0x42 }, { 0x2d, 0x49 }, // subsystem vendor { 0x2e, 0x4c }, { 0x2f, 0x4c }, // subsystem id { 0x3c, 0x00 }, // IRQ { 0x3d, BX_PCI_INTA }, // INT { 0x3e, 0x0c }, // min_gnt { 0x3f, 0x80 }, // max_lat }; for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { BX_ES1370_THIS pci_conf[reset_vals[i].addr] = reset_vals[i].val; } BX_ES1370_THIS s.ctl = 1; BX_ES1370_THIS s.status = 0x60; BX_ES1370_THIS s.mempage = 0; BX_ES1370_THIS s.codec = 0; BX_ES1370_THIS s.sctl = 0; for (i = 0; i < 3; i++) { BX_ES1370_THIS s.chan[i].scount = 0; BX_ES1370_THIS s.chan[i].leftover = 0; } DEV_gameport_set_enabled(0); // Deassert IRQ set_irq_level(0); } void bx_es1370_c::register_state(void) { unsigned i; char chname[6]; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "es1370", "ES1370 State"); for (i = 0; i < 3; i++) { sprintf(chname, "chan%d", i); bx_list_c *chan = new bx_list_c(list, chname, ""); BXRS_HEX_PARAM_FIELD(chan, shift, BX_ES1370_THIS s.chan[i].shift); BXRS_HEX_PARAM_FIELD(chan, leftover, BX_ES1370_THIS s.chan[i].leftover); BXRS_HEX_PARAM_FIELD(chan, scount, BX_ES1370_THIS s.chan[i].scount); BXRS_HEX_PARAM_FIELD(chan, frame_addr, BX_ES1370_THIS s.chan[i].frame_addr); BXRS_HEX_PARAM_FIELD(chan, frame_cnt, BX_ES1370_THIS s.chan[i].frame_cnt); } BXRS_HEX_PARAM_FIELD(list, ctl, BX_ES1370_THIS s.ctl); BXRS_HEX_PARAM_FIELD(list, status, BX_ES1370_THIS s.status); BXRS_HEX_PARAM_FIELD(list, mempage, BX_ES1370_THIS s.mempage); BXRS_HEX_PARAM_FIELD(list, codec, BX_ES1370_THIS s.codec); BXRS_HEX_PARAM_FIELD(list, sctl, BX_ES1370_THIS s.sctl); register_pci_state(list); } void bx_es1370_c::after_restore_state(void) { if (DEV_pci_set_base_io(BX_ES1370_THIS_PTR, read_handler, write_handler, &BX_ES1370_THIS pci_base_address[0], &BX_ES1370_THIS pci_conf[0x10], 64, &es1370_iomask[0], "ES1370")) { BX_INFO(("new base address: 0x%04x", BX_ES1370_THIS pci_base_address[0])); } BX_ES1370_THIS check_lower_irq(BX_ES1370_THIS s.sctl); BX_ES1370_THIS s.adc_inputinit = 0; BX_ES1370_THIS s.dac_nr_active = -1; BX_ES1370_THIS update_voices(BX_ES1370_THIS s.ctl, BX_ES1370_THIS s.sctl, 1); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_es1370_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_ES1370_SMF bx_es1370_c *class_ptr = (bx_es1370_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_es1370_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_ES1370_SMF Bit32u val = 0x0, shift; Bit16u offset; unsigned i; BX_DEBUG(("register read from address 0x%04x - ", address)); offset = address - BX_ES1370_THIS pci_base_address[0]; if (offset >= 0x30) { offset |= (BX_ES1370_THIS s.mempage << 8); } shift = (offset & 3) << 3; switch (offset & ~3) { case ES1370_CTL: val = BX_ES1370_THIS s.ctl >> shift; break; case ES1370_STATUS: val = BX_ES1370_THIS s.status >> shift; break; case ES1370_UART_DATA: case ES1370_UART_STATUS: case ES1370_UART_TEST: BX_ERROR(("reading from UART not supported yet")); break; case ES1370_MEMPAGE: val = BX_ES1370_THIS s.mempage; break; case ES1370_CODEC: val = BX_ES1370_THIS s.codec; break; case ES1370_SCTL: val = BX_ES1370_THIS s.sctl >> shift; break; case ES1370_DAC1_SCOUNT: case ES1370_DAC2_SCOUNT: case ES1370_ADC_SCOUNT: i = (offset - ES1370_DAC1_SCOUNT) / 4; val = BX_ES1370_THIS s.chan[i].scount >> shift; break; case ES1370_DAC1_FRAMEADR: val = BX_ES1370_THIS s.chan[0].frame_addr; break; case ES1370_DAC2_FRAMEADR: val = BX_ES1370_THIS s.chan[1].frame_addr; break; case ES1370_ADC_FRAMEADR: val = BX_ES1370_THIS s.chan[2].frame_addr; break; case ES1370_DAC1_FRAMECNT: val = BX_ES1370_THIS s.chan[0].frame_cnt; break; case ES1370_DAC2_FRAMECNT: val = BX_ES1370_THIS s.chan[1].frame_cnt; break; case ES1370_ADC_FRAMECNT: val = BX_ES1370_THIS s.chan[2].frame_cnt; break; case ES1370_PHA_FRAMEADR: BX_ERROR(("reading from phantom frame address")); val = ~0U; break; case ES1370_PHA_FRAMECNT: BX_ERROR(("reading from phantom frame count")); val = ~0U; break; default: val = ~0U; // keep compiler happy BX_ERROR(("unsupported io read from offset=0x%04x!", offset)); break; } BX_DEBUG(("val = 0x%08x", val)); return(val); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_es1370_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_ES1370_SMF bx_es1370_c *class_ptr = (bx_es1370_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_es1370_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_ES1370_SMF Bit16u offset; Bit32u shift, mask; unsigned i; BX_DEBUG(("register write to address 0x%04x - value = 0x%08x", address, value)); offset = address - BX_ES1370_THIS pci_base_address[0]; if (offset >= 0x30) { offset |= (BX_ES1370_THIS s.mempage << 8); } shift = (offset & 3) << 3; switch (offset & ~3) { case ES1370_CTL: mask = (0xffffffff >> ((4 - io_len) << 3)) << shift; value = (BX_ES1370_THIS s.ctl & ~mask) | ((value << shift) & mask); if ((value ^ BX_ES1370_THIS s.ctl) & 0x04) { DEV_gameport_set_enabled((value & 0x04) != 0); } BX_ES1370_THIS update_voices(value, BX_ES1370_THIS s.sctl, 0); break; case ES1370_UART_DATA: case ES1370_UART_CTL: case ES1370_UART_TEST: BX_ERROR(("writing to UART not supported yet")); break; case ES1370_MEMPAGE: BX_ES1370_THIS s.mempage = value & 0x0f; break; case ES1370_CODEC: BX_ES1370_THIS s.codec = value & 0xffff; BX_DEBUG(("writing to CODEC register 0x%02x, value = 0x%02x", (value >> 8) & 0xff, value & 0xff)); break; case ES1370_SCTL: mask = (0xffffffff >> ((4 - io_len) << 3)) << shift; value = (BX_ES1370_THIS s.sctl & ~mask) | ((value << shift) & mask); BX_ES1370_THIS check_lower_irq(value); BX_ES1370_THIS update_voices(BX_ES1370_THIS s.ctl, value, 0); break; case ES1370_DAC1_SCOUNT: case ES1370_DAC2_SCOUNT: case ES1370_ADC_SCOUNT: i = (offset - ES1370_DAC1_SCOUNT) / 4; value &= 0xffff; BX_ES1370_THIS s.chan[i].scount = value | (value << 16); break; case ES1370_DAC1_FRAMEADR: BX_ES1370_THIS s.chan[0].frame_addr = value; break; case ES1370_DAC2_FRAMEADR: BX_ES1370_THIS s.chan[1].frame_addr = value; break; case ES1370_ADC_FRAMEADR: BX_ES1370_THIS s.chan[2].frame_addr = value; break; case ES1370_DAC1_FRAMECNT: BX_ES1370_THIS s.chan[0].frame_cnt = value; break; case ES1370_DAC2_FRAMECNT: BX_ES1370_THIS s.chan[1].frame_cnt = value; break; case ES1370_ADC_FRAMECNT: BX_ES1370_THIS s.chan[2].frame_cnt = value; break; case ES1370_PHA_FRAMEADR: BX_ERROR(("writing to phantom frame address")); break; case ES1370_PHA_FRAMECNT: BX_ERROR(("writing to phantom frame count")); break; default: BX_ERROR(("unsupported io write to offset=0x%04x!", offset)); break; } } void bx_es1370_c::es1370_timer_handler(void *this_ptr) { bx_es1370_c *class_ptr = (bx_es1370_c *) this_ptr; class_ptr->es1370_timer(); } void bx_es1370_c::es1370_timer(void) { int timer_id; unsigned i; timer_id = bx_pc_system.triggeredTimerID(); i = (timer_id == BX_ES1370_THIS s.dac1_timer_index) ? 0 : 1; run_channel(i, timer_id, BX_ES1370_THIS s.dac_packet_size[i]); } void bx_es1370_c::run_channel(unsigned chan, int timer_id, Bit32u buflen) { Bit32u new_status = BX_ES1370_THIS s.status; Bit32u addr, sc, csc_bytes, cnt, size, left, transfered, temp; Bit8u tmpbuf[BX_SOUNDLOW_WAVEPACKETSIZE]; bx_bool irq = 0; chan_t *d = &BX_ES1370_THIS s.chan[chan]; if (!(BX_ES1370_THIS s.ctl & ctl_ch_en[chan]) || (BX_ES1370_THIS s.sctl & sctl_ch_pause[chan])) { if (chan == ADC_CHANNEL) { BX_ES1370_THIS soundmod->stopwaverecord(); } else { bx_pc_system.deactivate_timer(timer_id); } return; } addr = d->frame_addr; sc = d->scount & 0xffff; csc_bytes = ((d->scount >> 16) + 1) << d->shift; cnt = d->frame_cnt >> 16; size = d->frame_cnt & 0xffff; left = ((size - cnt + 1) << 2) + d->leftover; transfered = 0; temp = BX_MIN(buflen, BX_MIN(left, csc_bytes)); addr += (cnt << 2) + d->leftover; if (chan == ADC_CHANNEL) { BX_ES1370_THIS soundmod->getwavepacket(temp, tmpbuf); DEV_MEM_WRITE_PHYSICAL_DMA(addr, temp, tmpbuf); transfered = temp; } else { DEV_MEM_READ_PHYSICAL_DMA(addr, temp, tmpbuf); if (((int)chan == BX_ES1370_THIS s.dac_nr_active) && BX_ES1370_THIS s.dac_outputinit) { BX_ES1370_THIS soundmod->sendwavepacket(temp, tmpbuf); } transfered = temp; } if (csc_bytes == transfered) { irq = 1; d->scount = sc | (sc << 16); BX_DEBUG(("%s: all samples played/recorded - signalling IRQ (if enabled)", chan_name[chan])); } else { irq = 0; d->scount = sc | (((csc_bytes - transfered - 1) >> d->shift) << 16); } cnt += (transfered + d->leftover) >> 2; if (BX_ES1370_THIS s.sctl & sctl_loop_sel[chan]) { BX_ERROR(("%s: non looping mode not supported", chan_name[chan])); } else { d->frame_cnt = size; if (cnt <= d->frame_cnt) { d->frame_cnt |= cnt << 16; } } d->leftover = (transfered + d->leftover) & 3; if (irq) { if (BX_ES1370_THIS s.sctl & (1 << (8 + chan))) { new_status |= (4 >> chan); } } if (new_status != BX_ES1370_THIS s.status) { update_status(new_status); } } Bit32u bx_es1370_c::es1370_adc_handler(void *this_ptr, Bit32u buflen) { bx_es1370_c *class_ptr = (bx_es1370_c *) this_ptr; class_ptr->run_channel(ADC_CHANNEL, 0, buflen); return 0; } void bx_es1370_c::set_irq_level(bx_bool level) { DEV_pci_set_irq(BX_ES1370_THIS s.devfunc, BX_ES1370_THIS pci_conf[0x3d], level); } void bx_es1370_c::update_status(Bit32u new_status) { Bit32u level = new_status & (STAT_DAC1 | STAT_DAC2 | STAT_ADC); if (level) { BX_ES1370_THIS s.status = new_status | STAT_INTR; } else { BX_ES1370_THIS s.status = new_status & ~STAT_INTR; } set_irq_level(level != 0); } void bx_es1370_c::check_lower_irq(Bit32u sctl) { Bit32u new_status = BX_ES1370_THIS s.status; if (!(sctl & SCTRL_P1INTEN) && (BX_ES1370_THIS s.sctl & SCTRL_P1INTEN)) { new_status &= ~STAT_DAC1; } if (!(sctl & SCTRL_P2INTEN) && (BX_ES1370_THIS s.sctl & SCTRL_P2INTEN)) { new_status &= ~STAT_DAC2; } if (!(sctl & SCTRL_R1INTEN) && (BX_ES1370_THIS s.sctl & SCTRL_R1INTEN)) { new_status &= ~STAT_ADC; } if (new_status != BX_ES1370_THIS s.status) { update_status(new_status); } } void bx_es1370_c::update_voices(Bit32u ctl, Bit32u sctl, bx_bool force) { unsigned i; Bit32u old_freq, new_freq, old_fmt, new_fmt; int ret, timer_id; Bit64u timer_val; for (i = 0; i < 3; ++i) { chan_t *d = &BX_ES1370_THIS s.chan[i]; old_fmt = (BX_ES1370_THIS s.sctl >> (i << 1)) & 3; new_fmt = (sctl >> (i << 1)) & 3; if (i == DAC1_CHANNEL) { old_freq = dac1_freq[(BX_ES1370_THIS s.ctl >> 12) & 3]; new_freq = dac1_freq[(ctl >> 12) & 3]; } else { old_freq = 1411200 / (((BX_ES1370_THIS s.ctl >> 16) & 0x1fff) + 2); new_freq = 1411200 / (((ctl >> 16) & 0x1fff) + 2); } if ((old_fmt != new_fmt) || (old_freq != new_freq) || force) { d->shift = (new_fmt & 1) + (new_fmt >> 1); if (new_freq) { if (i == ADC_CHANNEL) { if (!BX_ES1370_THIS s.adc_inputinit) { ret = BX_ES1370_THIS soundmod->openwaveinput(SIM->get_param_string(BXPN_ES1370_WAVEDEV)->getptr(), es1370_adc_handler); if (ret != BX_SOUNDLOW_OK) { BX_ERROR(("could not open wave input device")); } else { BX_ES1370_THIS s.adc_inputinit = 1; } } } } } if (((ctl ^ BX_ES1370_THIS s.ctl) & ctl_ch_en[i]) || ((sctl ^ BX_ES1370_THIS s.sctl) & sctl_ch_pause[i]) || force) { bx_bool on = ((ctl & ctl_ch_en[i]) && !(sctl & sctl_ch_pause[i])); if (i == DAC1_CHANNEL) { timer_id = BX_ES1370_THIS s.dac1_timer_index; } else { timer_id = BX_ES1370_THIS s.dac2_timer_index; } if (on) { BX_INFO(("%s: freq = %d, nchannels %d, fmt %d, shift %d", chan_name[i], new_freq, 1 << (new_fmt & 1), (new_fmt & 2) ? 16 : 8, d->shift)); if (i == ADC_CHANNEL) { if (BX_ES1370_THIS s.adc_inputinit) { ret = BX_ES1370_THIS soundmod->startwaverecord(new_freq, (new_fmt >> 1) ? 16 : 8, (new_fmt & 1), (new_fmt >> 1)); if (ret != BX_SOUNDLOW_OK) { BX_ES1370_THIS soundmod->closewaveinput(); BX_ES1370_THIS s.adc_inputinit = 0; BX_ERROR(("could not start wave record")); } } } else { if ((BX_ES1370_THIS s.dac_nr_active == -1) && BX_ES1370_THIS s.dac_outputinit) { ret = BX_ES1370_THIS soundmod->startwaveplayback(new_freq, (new_fmt >> 1) ? 16 : 8, (new_fmt & 1), (new_fmt >> 1)); if (ret != BX_SOUNDLOW_OK) { BX_ES1370_THIS soundmod->closewaveoutput(); BX_ES1370_THIS s.dac_outputinit = 0; BX_ERROR(("could not start wave playback")); } else { BX_ES1370_THIS s.dac_nr_active = i; } } BX_ES1370_THIS s.dac_packet_size[i] = (new_freq / 10) << d->shift; // 0.1 sec if (BX_ES1370_THIS s.dac_packet_size[i] > BX_SOUNDLOW_WAVEPACKETSIZE) { BX_ES1370_THIS s.dac_packet_size[i] = BX_SOUNDLOW_WAVEPACKETSIZE; } timer_val = (Bit64u)BX_ES1370_THIS s.dac_packet_size[i] * 1000000 / (new_freq << d->shift); bx_pc_system.activate_timer(timer_id, (Bit32u)timer_val, 1); } } else { if (i == ADC_CHANNEL) { if (BX_ES1370_THIS s.adc_inputinit) { BX_ES1370_THIS soundmod->stopwaverecord(); } } else { if (((int)i == BX_ES1370_THIS s.dac_nr_active) && BX_ES1370_THIS s.dac_outputinit) { BX_ES1370_THIS soundmod->stopwaveplayback(); BX_ES1370_THIS s.dac_nr_active = -1; } bx_pc_system.deactivate_timer(timer_id); } } } } BX_ES1370_THIS s.ctl = ctl; BX_ES1370_THIS s.sctl = sctl; } // pci configuration space read callback handler Bit32u bx_es1370_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x14) && (address < 0x34)) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_ES1370_THIS pci_conf[address+i]; switch (address+i) { case 0x04: value8 &= 0x05; BX_ES1370_THIS pci_conf[address+i] = value8; break; case 0x05: value8 &= 0x01; BX_ES1370_THIS pci_conf[address+i] = value8; break; case 0x3d: // case 0x06: // disallowing write to status lo-byte (is that expected?) break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); BX_ES1370_THIS pci_conf[address+i] = value8; } break; case 0x10: value8 = (value8 & 0xfc) | 0x01; case 0x11: case 0x12: case 0x13: baseaddr_change |= (value8 != oldval); default: BX_ES1370_THIS pci_conf[address+i] = value8; } } if (baseaddr_change) { if (DEV_pci_set_base_io(BX_ES1370_THIS_PTR, read_handler, write_handler, &BX_ES1370_THIS pci_base_address[0], &BX_ES1370_THIS pci_conf[0x10], 64, &es1370_iomask[0], "ES1370")) { BX_INFO(("new base address: 0x%04x", BX_ES1370_THIS pci_base_address[0])); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } #endif // BX_SUPPORT_PCI && BX_SUPPORT_ES1370 bochs-2.6/iodev/sound/soundsdl.cc0000644000175000017500000001077212020641502016734 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundsdl.cc 11214 2012-06-09 10:12:05Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Lowlevel sound output support for SDL written by Volker Ruppert #include "iodev.h" #include "soundmod.h" #include "soundsdl.h" #if BX_WITH_SDL && BX_SUPPORT_SOUNDLOW #define LOG_THIS device-> #if BX_WITH_SDL #include #endif #define BX_SOUND_SDL_BUFSIZE BX_SOUNDLOW_WAVEPACKETSIZE * 8 static struct { int iptr; int optr; Bit8u data[BX_SOUND_SDL_BUFSIZE]; } audio_buffer; bx_sound_sdl_c::bx_sound_sdl_c(logfunctions *dev) :bx_sound_lowlevel_c(dev) { WaveOpen = 0; if (SDL_InitSubSystem(SDL_INIT_AUDIO)) { BX_PANIC(("Initialization of sound output module 'sdl' failed")); } else { BX_INFO(("Sound output module 'sdl' initialized")); } } bx_sound_sdl_c::~bx_sound_sdl_c() { SDL_QuitSubSystem(SDL_INIT_AUDIO); } int bx_sound_sdl_c::openwaveoutput(const char *wavedev) { WaveOpen = 1; return BX_SOUNDLOW_OK; } void sdl_callback(void *unused, Bit8u *stream, int len) { int amount = audio_buffer.iptr - audio_buffer.optr; if (amount < 0) { amount += BX_SOUND_SDL_BUFSIZE; } if (amount > len) { amount = len; } int tmplen = BX_SOUND_SDL_BUFSIZE - audio_buffer.optr; if (amount <= tmplen) { SDL_MixAudio(stream, &audio_buffer.data[audio_buffer.optr], amount, SDL_MIX_MAXVOLUME); audio_buffer.optr += amount; } else { SDL_MixAudio(stream, &audio_buffer.data[audio_buffer.optr], tmplen, SDL_MIX_MAXVOLUME); amount -= tmplen; SDL_MixAudio(stream, &audio_buffer.data[0], amount, SDL_MIX_MAXVOLUME); audio_buffer.optr = amount; } } int bx_sound_sdl_c::startwaveplayback(int frequency, int bits, bx_bool stereo, int format) { SDL_AudioSpec fmt; int signeddata = format & 1; BX_DEBUG(("startwaveplayback(%d, %d, %d, %x)", frequency, bits, stereo, format)); fmt.freq = frequency; if (bits == 16) { if (signeddata == 1) fmt.format = AUDIO_S16; else fmt.format = AUDIO_U16; } else if (bits == 8) { if (signeddata == 1) fmt.format = AUDIO_S8; else fmt.format = AUDIO_U8; } else return BX_SOUNDLOW_ERR; fmt.channels = stereo + 1; fmt.samples = frequency / 10; fmt.callback = sdl_callback; fmt.userdata = NULL; if (SDL_OpenAudio(&fmt, NULL) < 0) { BX_PANIC(("SDL_OpenAudio() failed")); return BX_SOUNDLOW_ERR; } audio_buffer.iptr = 0; audio_buffer.optr = 0; return BX_SOUNDLOW_OK; } int bx_sound_sdl_c::waveready() { int size; if (WaveOpen) { size = audio_buffer.optr - audio_buffer.iptr; if (size <= 0) { size += BX_SOUND_SDL_BUFSIZE; } if (size < BX_SOUNDLOW_WAVEPACKETSIZE) { return BX_SOUNDLOW_ERR; } else { return BX_SOUNDLOW_OK; } } else { return BX_SOUNDLOW_ERR; } } int bx_sound_sdl_c::sendwavepacket(int length, Bit8u data[]) { int ret = BX_SOUNDLOW_OK; int tmpsize; SDL_PauseAudio(1); if (waveready() == BX_SOUNDLOW_OK) { if ((audio_buffer.iptr + length) > BX_SOUND_SDL_BUFSIZE) { tmpsize = BX_SOUND_SDL_BUFSIZE - audio_buffer.iptr; memcpy(audio_buffer.data+audio_buffer.iptr, data, tmpsize); memcpy(audio_buffer.data, data+tmpsize, length-tmpsize); audio_buffer.iptr = length-tmpsize; } else { memcpy(audio_buffer.data+audio_buffer.iptr, data, length); audio_buffer.iptr += length; } } else { BX_ERROR(("SDL: audio buffer overflow")); ret = BX_SOUNDLOW_ERR; } SDL_PauseAudio(0); return ret; } int bx_sound_sdl_c::stopwaveplayback() { SDL_CloseAudio(); return BX_SOUNDLOW_OK; } int bx_sound_sdl_c::closewaveoutput() { WaveOpen = 0; return BX_SOUNDLOW_OK; } #endif // BX_WITH_SDL bochs-2.6/iodev/sound/soundsdl.h0000644000175000017500000000315612020641502016574 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundsdl.h 11214 2012-06-09 10:12:05Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Lowlevel sound output support for SDL written by Volker Ruppert #if BX_WITH_SDL #include "bochs.h" class bx_sound_sdl_c : public bx_sound_lowlevel_c { public: bx_sound_sdl_c(logfunctions *dev); virtual ~bx_sound_sdl_c(); virtual int get_type() {return BX_SOUNDLOW_SDL;} virtual int waveready(); virtual int openwaveoutput(const char *wavedev); virtual int startwaveplayback(int frequency, int bits, bx_bool stereo, int format); virtual int sendwavepacket(int length, Bit8u data[]); virtual int stopwaveplayback(); virtual int closewaveoutput(); private: bx_bool WaveOpen; }; #endif // BX_WITH_SDL bochs-2.6/iodev/sound/Makefile.in0000644000175000017500000002043612020641502016635 0ustar guillemguillem# Copyright (C) 2012 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Makefile for the iodev/sound component of bochs @SUFFIX_LINE@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ VPATH = @srcdir@ bindir = @bindir@ libdir = @libdir@ datarootdir = @datarootdir@ mandir = @mandir@ man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 docdir = $(datarootdir)/doc/bochs sharedir = $(datarootdir)/bochs top_builddir = .. top_srcdir = @top_srcdir@ SHELL = @SHELL@ @SET_MAKE@ CXX = @CXX@ CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ PLUGIN_PATH=@libdir@ top_builddir = ../.. LIBTOOL=@LIBTOOL@ WIN32_DLL_IMPORT_LIBRARY=../../dllexports.a SOUNDLOW_OBJS = @SOUNDLOW_OBJS@ BX_INCDIRS = -I.. -I../.. -I$(srcdir)/.. -I$(srcdir)/../.. -I../../@INSTRUMENT_DIR@ -I$(srcdir)/../../@INSTRUMENT_DIR@ LOCAL_CXXFLAGS = $(MCH_CFLAGS) OBJS_THAT_CAN_BE_PLUGINS = \ @SOUNDCARD_OBJS@ \ soundmod.o OBJS_THAT_SUPPORT_OTHER_PLUGINS = \ $(SOUNDLOW_OBJS) NONPLUGIN_OBJS = @IODEV_EXT_NON_PLUGIN_OBJS@ PLUGIN_OBJS = @IODEV_EXT_PLUGIN_OBJS@ SOUND_LINK_OPTS = @SOUND_LINK_OPTS@ all: libsound.a plugins: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@) libsound.a: $(NONPLUGIN_OBJS) @RMCOMMAND@ libsound.a @MAKELIB@ $(NONPLUGIN_OBJS) @RANLIB@ libsound.a # standard compile rule for C++ files .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@ ##### building plugins with libtool %.lo: %.@CPP_SUFFIX@ $(LIBTOOL) --mode=compile --tag CXX $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@ libbx_%.la: %.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) # special link rules for plugins that require more than one object file libbx_soundmod.la: soundmod.lo $(SOUNDLOW_OBJS:.o=.lo) $(LIBTOOL) --mode=link --tag CXX $(CXX) -module soundmod.lo $(SOUNDLOW_OBJS:.o=.lo) -o libbx_soundmod.la -rpath $(PLUGIN_PATH) $(SOUND_LINK_OPTS) #### building DLLs for win32 (tested on cygwin only) bx_%.dll: %.o $(CXX) $(CXXFLAGS) -shared -o $@ $< $(WIN32_DLL_IMPORT_LIBRARY) # special link rules for plugins that require more than one object file bx_soundmod.dll: soundmod.o $(SOUNDLOW_OBJS) $(CXX) $(CXXFLAGS) -shared -o bx_soundmod.dll soundmod.o $(SOUNDLOW_OBJS) $(WIN32_DLL_IMPORT_LIBRARY) -lwinmm ##### end DLL section clean: @RMCOMMAND@ -rf .libs *.lo *.o *.la *.a *.dll dist-clean: clean @RMCOMMAND@ Makefile ########################################### # dependencies generated by # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | sed -e 's/\.cc/.@CPP_SUFFIX@/g' # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | \ # sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g' # # This means that every source file is listed twice, once with a .o rule # and then again with an identical .lo rule. The .lo rules are used when # building plugins. ########################################### es1370.o: es1370.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h ../pci.h es1370.h soundmod.h soundlnx.h soundwin.h \ soundosx.h sb16.o: sb16.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h sb16.h soundmod.h soundlnx.h soundwin.h soundosx.h soundlnx.o: soundlnx.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundlnx.h soundmod.o: soundmod.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundlnx.h soundosx.h soundwin.h soundosx.o: soundosx.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundosx.h soundwin.o: soundwin.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundwin.h es1370.lo: es1370.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h ../pci.h es1370.h soundmod.h soundlnx.h soundwin.h \ soundosx.h sb16.lo: sb16.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h sb16.h soundmod.h soundlnx.h soundwin.h soundosx.h soundlnx.lo: soundlnx.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundlnx.h soundmod.lo: soundmod.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundlnx.h soundosx.h soundwin.h soundosx.lo: soundosx.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundosx.h soundwin.lo: soundwin.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h soundmod.h soundwin.h bochs-2.6/iodev/sound/soundwin.h0000644000175000017500000001566612020641502016620 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundwin.h 11213 2012-06-08 20:49:39Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // This file (SOUNDWIN.H) written and donated by Josef Drexler #if defined(WIN32) #include // uncomment one of the following two #defines //#define usesndPlaySnd #define usewaveOut #define BX_SOUND_WINDOWS_MAXSYSEXLEN 256 // maximum supported length of a sysex message #define BX_SOUND_WINDOWS_NBUF 64 // number of buffers for the output, must be power of 2 and >= 4 #define BX_SOUND_WINDOWS_NMASK (BX_SOUND_WINDOWS_NBUF - 1) #ifndef WAVEMAPPER #define WAVEMAPPER -1 #endif // Definitions for WINMM.DLL, if not defined already #ifndef MMSYSERR_NOERROR #pragma pack(1) typedef UINT HMIDIOUT; typedef HMIDIOUT *LPHMIDIOUT; typedef struct midihdr_tag { LPSTR lpData; DWORD dwBufferLength; DWORD dwBytesRecorded; DWORD dwUser; DWORD dwFlags; struct midihdr_tag *lpNext; DWORD reserved; } MIDIHDR, *LPMIDIHDR; typedef UINT HWAVEOUT; typedef HWAVEOUT *LPHWAVEOUT; typedef struct wavehdr_tag { LPSTR lpData; DWORD dwBufferLength; DWORD dwBytesRecorded; DWORD dwUser; DWORD dwFlags; DWORD dwLoops; struct wavehdr_tag *lpNext; DWORD reserved; } WAVEHDR, *LPWAVEHDR; #define WHDR_DONE 0x00000001 #define WHDR_PREPARED 0x00000002 #define WHDR_BEGINLOOP 0x00000004 #define WHDR_ENDLOOP 0x00000008 #define WHDR_INQUEUE 0x00000010 typedef struct waveformat_tag { WORD wFormatTag; WORD nChannels; DWORD nSamplesPerSec; DWORD nAvgBytesPerSec; WORD nBlockAlign; } WAVEFORMAT, *LPWAVEFORMAT; #define WAVE_FORMAT_PCM 1 typedef struct pcmwaveformat_tag { WAVEFORMAT wf; WORD wBitsPerSample; } PCMWAVEFORMAT, *LPPCMWAVEFORMAT; #define MIDIMAPPER -1 #define CALLBACK_NULL 0x00000000 #define CALLBACK_WINDOW 0x00010000 #define CALLBACK_TASK 0x00020000 #define CALLBACK_FUNCTION 0x00030000 #define MMSYSERR_NOERROR 0 #define MMSYSERR_ERROR 1 #define MMSYSERR_BADDEVICEID 2 #define MMSYSERR_NOTENABLED 3 #define MMSYSERR_ALLOCATED 4 #define MMSYSERR_INVALHANDLE 5 #define MMSYSERR_NODRIVER 6 #define MMSYSERR_NOMEM 7 #define MMSYSERR_NOTSUPPORTED 8 #define MMSYSERR_NOMAP 7 #define MIDIERR_UNPREPARED 64 #define MIDIERR_STILLPLAYING 65 #define MIDIERR_NOTREADY 66 #define MIDIERR_NODEVICE 67 #define WAVERR_BADFORMAT 32 #define WAVERR_STILLPLAYING 33 #define WAVERR_UNPREPARED 34 #define WAVERR_SYNC 35 #define MAXERRORLENGTH 128 extern "C" { UINT STDCALL midiOutOpen(LPHMIDIOUT, UINT, DWORD, DWORD, DWORD); UINT STDCALL midiOutShortMsg(HMIDIOUT, DWORD); UINT STDCALL midiOutLongMsg(HMIDIOUT, LPMIDIHDR, UINT); UINT STDCALL midiOutPrepareHeader(HMIDIOUT, LPMIDIHDR, UINT); UINT STDCALL midiOutUnprepareHeader(HMIDIOUT, LPMIDIHDR, UINT); UINT STDCALL midiOutReset(HMIDIOUT); UINT STDCALL midiOutClose(HMIDIOUT); UINT STDCALL waveOutOpen(LPHWAVEOUT, UINT, LPWAVEFORMAT, DWORD, DWORD, DWORD); UINT STDCALL waveOutWrite(HWAVEOUT, LPWAVEHDR, UINT); UINT STDCALL waveOutPrepareHeader(HWAVEOUT, LPWAVEHDR, UINT); UINT STDCALL waveOutUnprepareHeader(HWAVEOUT, LPWAVEHDR, UINT); UINT STDCALL waveOutReset(HWAVEOUT); UINT STDCALL waveOutClose(HWAVEOUT); UINT STDCALL waveOutGetErrorTextA(UINT, LPSTR, UINT); BOOL STDCALL sndPlaySoundA(LPCSTR, UINT); } #pragma pack(0) #endif // MMSYSERR_NOERROR defined #ifndef WAVEFILEHEADER #pragma pack(push, 1) typedef struct { char RIFF[4]; Bit32u length; char TYPE[4]; char chnk[4]; Bit32u chnklen; PCMWAVEFORMAT waveformat; char chnk2[4]; Bit32u chnk2len; char data[1]; } WAVEFILEHEADER, *LPWAVEFILEHEADER; #pragma pack(pop) #endif class bx_sound_windows_c : public bx_sound_lowlevel_c { public: bx_sound_windows_c(logfunctions *dev); virtual ~bx_sound_windows_c(); virtual int get_type() {return BX_SOUNDLOW_WIN;} virtual int waveready(); virtual int midiready(); virtual int openmidioutput(const char *mididev); virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]); virtual int closemidioutput(); virtual int openwaveoutput(const char *wavedev); virtual int startwaveplayback(int frequency, int bits, bx_bool stereo, int format); virtual int sendwavepacket(int length, Bit8u data[]); virtual int stopwaveplayback(); virtual int closewaveoutput(); virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh); virtual int startwaverecord(int frequency, int bits, bx_bool stereo, int format); virtual int getwavepacket(int length, Bit8u data[]); virtual int stopwaverecord(); virtual int closewaveinput(); static void record_timer_handler(void *); void record_timer(void); private: struct bx_sound_waveinfo_struct { int frequency; int bits; bx_bool stereo; int format; }; HMIDIOUT MidiOut; // Midi output device int MidiOpen; // is it open? HWAVEOUT hWaveOut; // Wave output device int WaveOutOpen; // is it open? HWAVEIN hWaveIn; // Wave input device int WaveInOpen; // is it open? UINT WaveDevice; // Wave device ID, for waveOutOpen // some data for the wave buffers HANDLE DataHandle; // returned by GlobalAlloc() Bit8u *DataPointer; // returned by GlobalLock() LPWAVEHDR WaveHeader[BX_SOUND_WINDOWS_NBUF]; LPSTR WaveData[BX_SOUND_WINDOWS_NBUF]; LPWAVEHDR WaveInHdr; LPSTR WaveInData; bx_bool recording; int length[BX_SOUND_WINDOWS_NBUF]; // length of the data in the buffer int needreopen; // if the format has changed int head,tailfull,tailplay; // These are for three states of the buffers: empty, full, played bx_sound_waveinfo_struct WaveInfo[2]; // format for the next buffer to be played int iswaveready; // and the midi buffer for the SYSEX messages LPMIDIHDR MidiHeader; LPSTR MidiData; int ismidiready; int playnextbuffer(); int recordnextpacket(); void checkmidiready(); void checkwaveready(); }; #endif // defined(WIN32) bochs-2.6/iodev/sound/soundosx.h0000644000175000017500000000553012020641502016621 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundosx.h 11213 2012-06-08 20:49:39Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // This file (SOUNDOSX.H) written and donated by Brian Huffman #ifdef macintosh #include "bochs.h" // uncomment one of these two: #if BX_WITH_MACOS #define BX_SOUND_OSX_use_quicktime #else #define BX_SOUND_OSX_use_converter //#define BX_SOUND_OSX_use_quicktime #include #endif #define BX_SOUND_OSX_NBUF 8 // number of buffers for digital output class bx_sound_osx_c : public bx_sound_lowlevel_c { public: bx_sound_osx_c(logfunctions *dev); virtual ~bx_sound_osx_c(); virtual int get_type() {return BX_SOUNDLOW_OSX;} virtual int waveready(); virtual int midiready(); virtual int openmidioutput(const char *mididev); virtual int sendmidicommand(int delta, int command, int length, Bit8u data[]); virtual int closemidioutput(); virtual int openwaveoutput(const char *wavedev); virtual int startwaveplayback(int frequency, int bits, bx_bool stereo, int format); virtual int sendwavepacket(int length, Bit8u data[]); virtual int stopwaveplayback(); virtual int closewaveoutput(); #ifdef BX_SOUND_OSX_use_converter void nextbuffer(int *outDataSize, void **outData); #endif virtual int openwaveinput(const char *wavedev, sound_record_handler_t rh); virtual int startwaverecord(int frequency, int bits, bx_bool stereo, int format); virtual int getwavepacket(int length, Bit8u data[]); virtual int stopwaverecord(); virtual int closewaveinput(); static void record_timer_handler(void *); void record_timer(void); private: int MidiOpen; int WaveOpen; Bit8u WaveData[BX_SOUND_OSX_NBUF][BX_SOUNDLOW_WAVEPACKETSIZE]; int WaveLength[BX_SOUND_OSX_NBUF]; int head, tail; // buffer pointers #ifdef BX_SOUND_OSX_use_converter int WavePlaying; OSStatus core_audio_pause(); OSStatus core_audio_resume(); #endif }; #endif // macintosh bochs-2.6/iodev/sound/sb16.h0000644000175000017500000003754712020641502015527 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: sb16.h 11282 2012-07-14 14:20:36Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // The original version of the SB16 support written and donated by Josef Drexler #ifndef BX_IODEV_SB16_H #define BX_IODEV_SB16_H #if BX_USE_SB16_SMF # define BX_SB16_SMF static # define BX_SB16_THIS theSB16Device-> # define BX_SB16_THISP (theSB16Device) #else # define BX_SB16_SMF # define BX_SB16_THIS this-> # define BX_SB16_THISP (this) #endif // If the buffer commands are to be inlined: #define BX_SB16_BUFINL BX_CPP_INLINE // BX_CPP_INLINE is defined to the inline keyword for the C++ compiler. // maximum number of patch translations #define BX_SB16_PATCHTABLESIZE 1024 // the resources. Of these, IRQ and DMA's can be changed via a DSP command #define BX_SB16_IO 0x220 // IO base address of DSP, mixer & FM part #define BX_SB16_IOLEN 16 // number of addresses covered #define BX_SB16_IOMPU 0x330 // IO base address of MPU402 part #define BX_SB16_IOMPULEN 4 // number of addresses covered #define BX_SB16_IOADLIB 0x388 // equivalent to 0x220..0x223 and 0x228..0x229 #define BX_SB16_IOADLIBLEN 4 // number of addresses covered #define BX_SB16_IRQ theSB16Device->currentirq #define BX_SB16_IRQMPU BX_SB16_IRQ // IRQ for the MPU401 part - same value #define BX_SB16_DMAL theSB16Device->currentdma8 #define BX_SB16_DMAH theSB16Device->currentdma16 /* A few notes: IRQ, DMA8bit and DMA16bit are for the DSP part. These are changeable at runtime in mixer registers 0x80 and 0x81. The defaults after a mixer initialization are IRQ 5, DMA8 1, no DMA16 Any of the address lengths can be zero to disable that particular subdevice. Turning off the DSP still leaves FM music enabled on the BX_SB16_IOADLIB ports, unless those are disabled as well. BX_SB16_IOMPULEN should be 4 or 2. In the latter case, the emulator is completely invisible, and runtime changes are not possible BX_SB16_IOADLIBLEN should be 2 or 4. If 0, Ports 0x388.. don't get used, but the OPL2 can still be accessed at 0x228..0x229. If 2, the usual Adlib emulation is enabled. If 4, an OPL3 is emulated at adresses 0x388..0x38b, or two separate OPL2's. */ #define BX_SB16_MIX_REG 0x100 // total number of mixer registers // The array containing an instrument/bank remapping struct bx_sb16_ins_map { Bit8u oldbankmsb, oldbanklsb, oldprogch; Bit8u newbankmsb, newbanklsb, newprogch; }; // One operator of the FM emulation #define BX_SB16_FM_NOP 36 // OPL3 has 36 operators #define BX_SB16_FM_OPB 6 // one operator has 6 bytes typedef Bit8u bx_sb16_fm_operator[BX_SB16_FM_OPB]; /* Explanation of the values: (note [xx] is one bit for xx; [5 xx] is five bits for xx, all bits listed MSB to LSB) [0] = [Tremolo][Vibrato][Sustain][KSR][4 Frequency Multiply] [1] = [2 Key Scale Level][6 Output Level for modulators, reserved for others] [2] = [4 Attack Rate][4 Decay Rate] [3] = [4 Sustain Level][4 Release Rate] [4] = [2 reserved][Right][Left][3 Feedback Factor][SynthType] [5] = [5 reserved][3 Waveform Select] Frequency and Output Level are really properties of the channel, so they get stored there. However, Output Level of the modulator in FM synthesis varies the instrument. [4] is only set for the first operator, and zeroed for the others. All reserved bits are zeroed. */ // One channel (1 to 4 operators) #define BX_SB16_FM_NCH 18 // OPL3 has at most 18 channels typedef struct { int nop; // number of operators used: 0=disabled, 1=percussion, 2 or 4=melodic int ncarr; // how many carriers this channel has (1..3) int opnum[4]; // operator numbers Bit16u freq; // frequency (in a special code) Bit32u afreq; // actual frequency in milli-Hertz (10^-3 Hz) Bit8u midichan; // assigned midi channel bx_bool needprogch; // has the instrument changed Bit8u midinote; // currently playing midi note bx_bool midion; // is the note on Bit16u midibend; // current value of the pitch bender Bit8u outputlevel[4];// 6-bit output level attenuations Bit8u midivol; // current midi volume (velocity) } bx_sb16_fm_channel; // This is the class for the input and // output FIFO buffers of the SB16 class bx_sb16_buffer { public: BX_SB16_BUFINL bx_sb16_buffer(void); BX_SB16_BUFINL ~bx_sb16_buffer(); BX_SB16_BUFINL void init(int bufferlen); BX_SB16_BUFINL void reset(); /* These functions return 1 on success and 0 on error */ BX_SB16_BUFINL bx_bool put(Bit8u data); // write one byte in the buffer BX_SB16_BUFINL bx_bool puts(const char *data, ...); // write a formatted string to the buffer BX_SB16_BUFINL bx_bool get(Bit8u *data); // read the next available byte BX_SB16_BUFINL bx_bool getw(Bit16u *data); // get word, in order lo/hi BX_SB16_BUFINL bx_bool getw1(Bit16u *data);// get word, in order hi/lo BX_SB16_BUFINL bx_bool full(void); // is the buffer full? BX_SB16_BUFINL bx_bool empty(void); // is it empty? BX_SB16_BUFINL void flush(void); // empty the buffer BX_SB16_BUFINL int bytes(void); // return number of bytes in the buffer BX_SB16_BUFINL Bit8u peek(int ahead); // peek ahead number of bytes /* These are for caching the command number */ BX_SB16_BUFINL void newcommand(Bit8u newcmd, int bytes); // start a new command with length bytes BX_SB16_BUFINL Bit8u currentcommand(void); // return the current command BX_SB16_BUFINL void clearcommand(void); // clear the command BX_SB16_BUFINL bx_bool commanddone(void); // return if all bytes have arrived BX_SB16_BUFINL bx_bool hascommand(void); // return if there is a pending command BX_SB16_BUFINL int commandbytes(void); // return the length of the command private: Bit8u *buffer; int head,tail,length; Bit8u command; bx_bool havecommand; int bytesneeded; }; // forward definition class bx_sound_lowlevel_c; // The actual emulator class, emulating the sound blaster ports class bx_sb16_c : public bx_devmodel_c { public: bx_sb16_c(); virtual ~bx_sb16_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); virtual void after_restore_state(void); /* Make writelog available to output functions */ BX_SB16_SMF void writelog(int loglev, const char *str, ...); // return midimode and wavemode setting (for lowlevel output class) int get_midimode() const {return midimode;} int get_wavemode() const {return wavemode;} // runtimer parameter handler static Bit64s sb16_param_handler(bx_param_c *param, int set, Bit64s val); private: int midimode, wavemode, loglevel; Bit32u dmatimer; FILE *logfile, *midifile, *wavefile; // the output files or devices bx_sound_lowlevel_c *soundmod; // the lowlevel class int currentirq; int currentdma8; int currentdma16; // the MPU 401 relevant variables struct bx_sb16_mpu_struct { bx_sb16_buffer datain, dataout, cmd, midicmd; bx_bool uartmode, irqpending, forceuartmode, singlecommand; int banklsb[BX_SB16_PATCHTABLESIZE]; int bankmsb[BX_SB16_PATCHTABLESIZE]; // current patch lists int program[BX_SB16_PATCHTABLESIZE]; int timer_handle, current_timer; // no. of delta times passed Bit32u last_delta_time; // timer value at last command bx_bool outputinit; } mpu401; // the DSP variables struct bx_sb16_dsp_struct { bx_sb16_buffer datain, dataout; Bit8u resetport; // last value written to the reset port Bit8u speaker,prostereo; // properties of the sound input/output bx_bool irqpending; // Is an IRQ pending (not ack'd) bx_bool midiuartmode; // Is the DSP in MIDI UART mode Bit8u testreg; struct bx_sb16_dsp_dma_struct { // Properties of the current DMA transfer: // mode= 0: no transfer, 1: single-cycle transfer, 2: auto-init DMA // bits= 8 or 16 // fifo= ?? Bit used in DMA command, no idea what it means... // output= 0: input, 1: output // bps= bytes per sample; =(dmabits/8)*(dmastereo+1) // stereo= 0: mono, 1: stereo // issigned= 0: unsigned data, 1: signed data // highspeed= 0: normal mode, 1: highspeed mode (only SBPro) // timer= so many us between data bytes int mode, bits, bps, format, timer; bx_bool fifo, output, stereo, issigned, highspeed; Bit16u count; // bytes remaining in this transfer Bit8u *chunk; // buffers up to BX_SOUNDLOW_WAVEPACKETSIZE bytes int chunkindex; // index into the buffer int chunkcount; // for input: size of the recorded input Bit16u timeconstant; Bit16u blocklength, samplerate; } dma; int timer_handle; // handle for the DMA timer bx_bool outputinit; // have the lowlevel output been initialized bx_bool inputinit; // have the lowlevel input been initialized } dsp; // the ASP/CSP registers Bit8u csp_reg[256]; enum bx_sb16_fm_mode {single, adlib, dual, opl3, fminit}; // the variables common to all FM emulations struct bx_sb16_opl_struct; friend struct bx_sb16_opl_struct; struct bx_sb16_opl_struct { bx_sb16_fm_mode mode; // modes: single: one OPL2 (OPL3 disabled), // adlib: one OPL2 (no OPL3), // dual: two seperate OPL2 // opl3: one OPL3 (enabled) int timer_handle; int timer_running; Bit16u midichannels; // bitmask: unused midichannels int drumchannel; // midi channel for percussion (10) int index[2]; // index register for the two chips int wsenable[2]; // wave form select enable Bit16u timer[4]; // two timers on each chip Bit16u timerinit[4]; // initial timer counts int tmask[2]; // the timer masking byte for both chips int tflag[2]; // shows if the timer overflow has occured int percmode[2]; // percussion mode enabled int cyhhnote[2]; // cymbal and high hat midi notes int cyhhon[2]; // cymbal and high hat notes on bx_sb16_fm_operator oper[BX_SB16_FM_NOP]; bx_sb16_fm_channel chan[BX_SB16_FM_NCH]; } opl; struct bx_sb16_mixer_struct { Bit8u regindex; Bit8u reg[BX_SB16_MIX_REG]; } mixer; struct bx_sb16_emul_struct { bx_sb16_buffer datain, dataout; bx_sb16_ins_map remaplist[256]; Bit16u remaps; } emuldata; /* DMA input and output, 8 and 16 bit */ BX_SB16_SMF Bit16u dma_write8(Bit8u *buffer, Bit16u maxlen); BX_SB16_SMF Bit16u dma_read8(Bit8u *buffer, Bit16u maxlen); BX_SB16_SMF Bit16u dma_write16(Bit16u *buffer, Bit16u maxlen); BX_SB16_SMF Bit16u dma_read16(Bit16u *buffer, Bit16u maxlen); /* the MPU 401 part of the emulator */ BX_SB16_SMF Bit32u mpu_status(); // read status port 3x1 BX_SB16_SMF void mpu_command(Bit32u value); // write command port 3x1 BX_SB16_SMF Bit32u mpu_dataread(); // read data port 3x0 BX_SB16_SMF void mpu_datawrite(Bit32u value); // write data port 3x0 BX_SB16_SMF void mpu_mididata(Bit32u value); // get a midi byte static void mpu_timer (void *); /* The DSP part */ BX_SB16_SMF void dsp_reset(Bit32u value); // write to reset port 2x6 BX_SB16_SMF Bit32u dsp_dataread(); // read from data port 2xa BX_SB16_SMF void dsp_datawrite(Bit32u value); // write to data port 2xa BX_SB16_SMF Bit32u dsp_bufferstatus(); // read buffer status 2xc BX_SB16_SMF Bit32u dsp_status(); // read dsp status 2xe BX_SB16_SMF void dsp_getsamplebyte(Bit8u value); BX_SB16_SMF Bit8u dsp_putsamplebyte(); BX_SB16_SMF void dsp_sendwavepacket(); BX_SB16_SMF Bit32u dsp_irq16ack(); // ack 16 bit IRQ 2xf BX_SB16_SMF void dsp_dma(Bit8u command, Bit8u mode, Bit16u length, Bit8u comp); // initiate a DMA transfer BX_SB16_SMF void dsp_dmadone(); // stop a DMA transfer BX_SB16_SMF void dsp_enabledma(); // enable the transfer BX_SB16_SMF void dsp_disabledma(); // temporarily disable DMA static void dsp_dmatimer(void *); static Bit32u sb16_adc_handler(void *, Bit32u len); Bit32u dsp_adc_handler(Bit32u len); /* The mixer part */ BX_SB16_SMF Bit32u mixer_readdata(void); BX_SB16_SMF void mixer_writedata(Bit32u value); BX_SB16_SMF void mixer_writeregister(Bit32u value); BX_SB16_SMF void set_irq_dma(); /* The emulator ports to change emulator properties */ BX_SB16_SMF Bit32u emul_read (void); // read emulator port BX_SB16_SMF void emul_write(Bit32u value); // write emulator port /* The FM emulation part */ BX_SB16_SMF void opl_entermode(bx_sb16_fm_mode newmode); BX_SB16_SMF Bit32u opl_status(int chipid); BX_SB16_SMF void opl_index(Bit32u value, int chipid); BX_SB16_SMF void opl_data(Bit32u value, int chipid); static void opl_timer(void *); BX_SB16_SMF void opl_timerevent(void); BX_SB16_SMF void opl_changeop(int channum, int opernum, int byte, int value); BX_SB16_SMF void opl_settimermask(int value, int chipid); BX_SB16_SMF void opl_set4opmode(int new4opmode); BX_SB16_SMF void opl_setmodulation(int channel); BX_SB16_SMF void opl_setpercussion(Bit8u value, int chipid); BX_SB16_SMF void opl_setvolume(int channel, int opnum, int outlevel); BX_SB16_SMF void opl_setfreq(int channel); BX_SB16_SMF void opl_keyonoff(int channel, bx_bool onoff); BX_SB16_SMF void opl_midichannelinit(int channel); /* several high level sound handlers */ BX_SB16_SMF int currentdeltatime(); BX_SB16_SMF void processmidicommand(bx_bool force); BX_SB16_SMF void midiremapprogram(int channel); // remap program change BX_SB16_SMF int converttodeltatime(Bit32u deltatime, Bit8u value[4]); BX_SB16_SMF void writemidicommand(int command, int length, Bit8u data[]); BX_SB16_SMF void writedeltatime(Bit32u deltatime); // write in delta time coding BX_SB16_SMF void initmidifile(); // Write midi file header BX_SB16_SMF void finishmidifile(); // write track length etc. BX_SB16_SMF void initvocfile(); // Write voc file header BX_SB16_SMF void writevocblock(int block, Bit32u headerlen, Bit8u header[], Bit32u datalen, Bit8u data[]); BX_SB16_SMF void finishvocfile(); // close voc file /* The port IO multiplexer functions */ static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_SB16_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #define BOTHLOG(x) (x) #define WRITELOG (BX_SB16_THIS writelog) #define MIDILOG(x) ((BX_SB16_THIS midimode>0?x:0x7f)) #define WAVELOG(x) ((BX_SB16_THIS wavemode>0?x:0x7f)) #endif bochs-2.6/iodev/sound/soundlnx.cc0000644000175000017500000004751612020641502016761 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: soundlnx.cc 10977 2012-01-15 07:52:04Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Josef Drexler coded the original version of the lowlevel sound support // for Linux using OSS. The current version also supports OSS on FreeBSD and // ALSA PCM input/output on Linux. #include "iodev.h" #include "soundmod.h" #include "soundlnx.h" #if (defined(linux) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && BX_SUPPORT_SOUNDLOW #define LOG_THIS device-> #include #include #include bx_sound_linux_c::bx_sound_linux_c(logfunctions *dev) :bx_sound_lowlevel_c(dev) { #if BX_HAVE_ALSASOUND alsa_seq.handle = NULL; alsa_pcm[0].handle = NULL; alsa_pcm[1].handle = NULL; alsa_pcm[0].buffer = NULL; alsa_pcm[1].buffer = NULL; #endif midi = NULL; wave_device[0] = NULL; wave_device[1] = NULL; wave_fd[0] = -1; wave_fd[1] = -1; BX_INFO(("Sound lowlevel module 'linux' initialized")); } bx_sound_linux_c::~bx_sound_linux_c() { // nothing for now } int bx_sound_linux_c::waveready() { return BX_SOUNDLOW_OK; } int bx_sound_linux_c::midiready() { return BX_SOUNDLOW_OK; } #if BX_HAVE_ALSASOUND int bx_sound_linux_c::alsa_seq_open(const char *alsadev) { char *mididev, *ptr; int client, port, ret = 0; int length = strlen(alsadev) + 1; mididev = new char[length]; if (mididev == NULL) return BX_SOUNDLOW_ERR; strcpy(mididev, alsadev); ptr = strtok(mididev, ":"); if (ptr == NULL) { BX_ERROR(("ALSA sequencer setup: missing client parameters")); return BX_SOUNDLOW_ERR; } client = atoi(ptr); ptr = strtok(NULL, ":"); if (ptr == NULL) { BX_ERROR(("ALSA sequencer setup: missing port parameter")); return BX_SOUNDLOW_ERR; } port = atoi(ptr); delete(mididev); if (snd_seq_open(&alsa_seq.handle, "default", SND_SEQ_OPEN_OUTPUT, 0) < 0) { BX_ERROR(("Couldn't open ALSA sequencer for midi output")); return BX_SOUNDLOW_ERR; } ret = snd_seq_create_simple_port(alsa_seq.handle, NULL, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC); if (ret < 0) { BX_ERROR(("ALSA sequencer: error creating port %s", snd_strerror(errno))); } else { alsa_seq.source_port = ret; ret = snd_seq_connect_to(alsa_seq.handle, alsa_seq.source_port, client, port); if (ret < 0) { BX_ERROR(("ALSA sequencer: could not connect to port %d:%d", client, port)); } } if (ret < 0) { snd_seq_close(alsa_seq.handle); return BX_SOUNDLOW_ERR; } else { return BX_SOUNDLOW_OK; } } #endif int bx_sound_linux_c::openmidioutput(const char *mididev) { if ((mididev == NULL) || (strlen(mididev) < 1)) return BX_SOUNDLOW_ERR; #if BX_HAVE_ALSASOUND use_alsa_seq = !strncmp(mididev, "alsa:", 5); if (use_alsa_seq) { return alsa_seq_open(mididev+5); } #endif midi = fopen(mididev,"w"); if (midi == NULL) { BX_ERROR(("Couldn't open midi output device %s: %s", mididev, strerror(errno))); return BX_SOUNDLOW_ERR; } return BX_SOUNDLOW_OK; } #if BX_HAVE_ALSASOUND int bx_sound_linux_c::alsa_seq_output(int delta, int command, int length, Bit8u data[]) { int cmd, chan, value; snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, alsa_seq.source_port); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); cmd = command & 0xf0; chan = command & 0x0f; switch (cmd) { case 0x80: ev.type = SND_SEQ_EVENT_NOTEOFF; ev.data.note.channel = chan; ev.data.note.note = data[0]; ev.data.note.velocity = data[1]; ev.data.note.duration = delta; break; case 0x90: ev.type = SND_SEQ_EVENT_NOTEON; ev.data.note.channel = chan; ev.data.note.note = data[0]; ev.data.note.velocity = data[1]; ev.data.note.duration = 0; break; case 0xa0: ev.type = SND_SEQ_EVENT_KEYPRESS; ev.data.control.channel = chan; ev.data.control.param = data[0]; ev.data.control.value = data[1]; break; case 0xb0: ev.type = SND_SEQ_EVENT_CONTROLLER; ev.data.control.channel = chan; ev.data.control.param = data[0]; ev.data.control.value = data[1]; break; case 0xc0: ev.type = SND_SEQ_EVENT_PGMCHANGE; ev.data.control.channel = chan; ev.data.control.value = data[0]; break; case 0xd0: ev.type = SND_SEQ_EVENT_CHANPRESS; ev.data.control.channel = chan; ev.data.control.value = data[0]; break; case 0xe0: ev.type = SND_SEQ_EVENT_PITCHBEND; ev.data.control.channel = chan; value = data[0] | (data[1] << 7); value -= 0x2000; ev.data.control.value = value; break; case 0xf0: BX_ERROR(("alsa_seq_output(): SYSEX not implemented, length=%d", length)); return BX_SOUNDLOW_ERR; default: BX_ERROR(("alsa_seq_output(): unknown command 0x%02x, length=%d", command, length)); return BX_SOUNDLOW_ERR; } snd_seq_event_output(alsa_seq.handle, &ev); snd_seq_drain_output(alsa_seq.handle); return BX_SOUNDLOW_OK; } #endif int bx_sound_linux_c::sendmidicommand(int delta, int command, int length, Bit8u data[]) { #if BX_HAVE_ALSASOUND if ((use_alsa_seq) && (alsa_seq.handle != NULL)) { return alsa_seq_output(delta, command, length, data); } #endif UNUSED(delta); fputc(command, midi); fwrite(data, 1, length, midi); fflush(midi); // to start playing immediately return BX_SOUNDLOW_OK; } int bx_sound_linux_c::closemidioutput() { #if BX_HAVE_ALSASOUND if ((use_alsa_seq) && (alsa_seq.handle != NULL)) { snd_seq_close(alsa_seq.handle); return BX_SOUNDLOW_OK; } #endif fclose(midi); return BX_SOUNDLOW_OK; } int bx_sound_linux_c::openwaveoutput(const char *wavedev) { #if BX_HAVE_ALSASOUND use_alsa_pcm = !strcmp(wavedev, "alsa"); if (use_alsa_pcm) { return BX_SOUNDLOW_OK; } #endif int length = strlen(wavedev) + 1; if (wave_device[0] != NULL) delete [] wave_device[0]; wave_device[0] = new char[length]; if (wave_device[0] == NULL) return BX_SOUNDLOW_ERR; strncpy(wave_device[0], wavedev, length); return BX_SOUNDLOW_OK; } #if BX_HAVE_ALSASOUND int bx_sound_linux_c::alsa_pcm_open(bx_bool mode, int frequency, int bits, bx_bool stereo, int format) { int ret; snd_pcm_format_t fmt; snd_pcm_hw_params_t *params; unsigned int size, freq; int dir, signeddata = format & 1; alsa_pcm[mode].audio_bufsize = 0; if (alsa_pcm[mode].handle == NULL) { ret = snd_pcm_open(&alsa_pcm[mode].handle, "default", mode ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (ret < 0) { return BX_SOUNDLOW_ERR; } BX_INFO(("ALSA: opened default PCM %s device", mode ? "input":"output")); } snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(alsa_pcm[mode].handle, params); snd_pcm_hw_params_set_access(alsa_pcm[mode].handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if ((frequency == wave_ch[mode].oldfreq) && (bits == wave_ch[mode].oldbits) && (stereo == wave_ch[mode].oldstereo) && (format == wave_ch[mode].oldformat)) return BX_SOUNDLOW_OK; // nothing to do wave_ch[mode].oldfreq = frequency; wave_ch[mode].oldbits = bits; wave_ch[mode].oldstereo = stereo; wave_ch[mode].oldformat = format; freq = (unsigned int)frequency; if (bits == 16) { if (signeddata == 1) fmt = SND_PCM_FORMAT_S16_LE; else fmt = SND_PCM_FORMAT_U16_LE; size = 2; } else if (bits == 8) { if (signeddata == 1) fmt = SND_PCM_FORMAT_S8; else fmt = SND_PCM_FORMAT_U8; size = 1; } else return BX_SOUNDLOW_ERR; if (stereo) size *= 2; snd_pcm_hw_params_set_format(alsa_pcm[mode].handle, params, fmt); snd_pcm_hw_params_set_channels(alsa_pcm[mode].handle, params, (stereo != 0) ? 2 : 1); snd_pcm_hw_params_set_rate_near(alsa_pcm[mode].handle, params, &freq, &dir); alsa_pcm[mode].frames = 32; snd_pcm_hw_params_set_period_size_near(alsa_pcm[mode].handle, params, &alsa_pcm[mode].frames, &dir); ret = snd_pcm_hw_params(alsa_pcm[mode].handle, params); if (ret < 0) { return BX_SOUNDLOW_ERR; } snd_pcm_hw_params_get_period_size(params, &alsa_pcm[mode].frames, &dir); alsa_pcm[mode].alsa_bufsize = alsa_pcm[mode].frames * size; BX_DEBUG(("ALSA: buffer size set to %d", alsa_pcm[mode].alsa_bufsize)); if (alsa_pcm[mode].buffer != NULL) { free(alsa_pcm[mode].buffer); alsa_pcm[mode].buffer = NULL; } return BX_SOUNDLOW_OK; } #endif int bx_sound_linux_c::startwaveplayback(int frequency, int bits, bx_bool stereo, int format) { int fmt, ret; int signeddata = format & 1; #if BX_HAVE_ALSASOUND if (use_alsa_pcm) { return alsa_pcm_open(0, frequency, bits, stereo, format); } #endif if ((wave_device[0] == NULL) || (strlen(wave_device[0]) < 1)) return BX_SOUNDLOW_ERR; if (wave_fd[0] == -1) { wave_fd[0] = open(wave_device[0], O_WRONLY); if (wave_fd[0] == -1) { return BX_SOUNDLOW_ERR; } else { BX_INFO(("OSS: opened output device %s", wave_device[0])); } } else { if ((frequency == wave_ch[0].oldfreq) && (bits == wave_ch[0].oldbits) && (stereo == wave_ch[0].oldstereo) && (format == wave_ch[0].oldformat)) return BX_SOUNDLOW_OK; // nothing to do } wave_ch[0].oldfreq = frequency; wave_ch[0].oldbits = bits; wave_ch[0].oldstereo = stereo; wave_ch[0].oldformat = format; if (bits == 16) if (signeddata == 1) fmt = AFMT_S16_LE; else fmt = AFMT_U16_LE; else if (bits == 8) if (signeddata == 1) fmt = AFMT_S8; else fmt = AFMT_U8; else return BX_SOUNDLOW_ERR; // set frequency etc. ret = ioctl(wave_fd[0], SNDCTL_DSP_RESET); if (ret != 0) BX_DEBUG(("ioctl(SNDCTL_DSP_RESET): %s", strerror(errno))); /* ret = ioctl(wave_fd[0], SNDCTL_DSP_SETFRAGMENT, &fragment); if (ret != 0) BX_DEBUG(("ioctl(SNDCTL_DSP_SETFRAGMENT, %d): %s", fragment, strerror(errno))); */ ret = ioctl(wave_fd[0], SNDCTL_DSP_SETFMT, &fmt); if (ret != 0) // abort if the format is unknown, to avoid playing noise { BX_DEBUG(("ioctl(SNDCTL_DSP_SETFMT, %d): %s", fmt, strerror(errno))); return BX_SOUNDLOW_ERR; } ret = ioctl(wave_fd[0], SNDCTL_DSP_STEREO, &stereo); if (ret != 0) BX_DEBUG(("ioctl(SNDCTL_DSP_STEREO, %d): %s", stereo, strerror(errno))); ret = ioctl(wave_fd[0], SNDCTL_DSP_SPEED, &frequency); if (ret != 0) BX_DEBUG(("ioctl(SNDCTL_DSP_SPEED, %d): %s", frequency, strerror(errno))); // ioctl(wave_fd[0], SNDCTL_DSP_GETBLKSIZE, &fragment); // BX_DEBUG(("current output block size is %d", fragment)); return BX_SOUNDLOW_OK; } #if BX_HAVE_ALSASOUND int bx_sound_linux_c::alsa_pcm_write() { int ret; if (alsa_pcm[0].buffer == NULL) { alsa_pcm[0].buffer = (char *)malloc(alsa_pcm[0].alsa_bufsize); } while (alsa_pcm[0].audio_bufsize >= alsa_pcm[0].alsa_bufsize) { memcpy(alsa_pcm[0].buffer, audio_buffer[0], alsa_pcm[0].alsa_bufsize); ret = snd_pcm_writei(alsa_pcm[0].handle, alsa_pcm[0].buffer, alsa_pcm[0].frames); if (ret == -EAGAIN) continue; if (ret == -EPIPE) { /* EPIPE means underrun */ BX_ERROR(("ALSA: underrun occurred")); snd_pcm_prepare(alsa_pcm[0].handle); } else if (ret < 0) { BX_ERROR(("ALSA: error from writei: %s", snd_strerror(ret))); } else if (ret != (int)alsa_pcm[0].frames) { BX_ERROR(("ALSA: short write, write %d frames", ret)); } alsa_pcm[0].audio_bufsize -= alsa_pcm[0].alsa_bufsize; memcpy(audio_buffer[0], audio_buffer[0]+alsa_pcm[0].alsa_bufsize, alsa_pcm[0].audio_bufsize); } if ((alsa_pcm[0].audio_bufsize == 0) && (alsa_pcm[0].buffer != NULL)) { free(alsa_pcm[0].buffer); alsa_pcm[0].buffer = NULL; } return BX_SOUNDLOW_OK; } #endif int bx_sound_linux_c::sendwavepacket(int length, Bit8u data[]) { #if BX_HAVE_ALSASOUND if (use_alsa_pcm) { if ((alsa_pcm[0].audio_bufsize+length) <= BX_SOUND_LINUX_BUFSIZE) { memcpy(audio_buffer[0]+alsa_pcm[0].audio_bufsize, data, length); alsa_pcm[0].audio_bufsize += length; } else { BX_ERROR(("ALSA: audio buffer overflow")); return BX_SOUNDLOW_ERR; } if (alsa_pcm[0].audio_bufsize < alsa_pcm[0].alsa_bufsize) { return BX_SOUNDLOW_OK; } else { return alsa_pcm_write(); } } #endif int ret = write(wave_fd[0], data, length); if (ret == length) { return BX_SOUNDLOW_OK; } else { BX_ERROR(("OSS: write error")); return BX_SOUNDLOW_ERR; } } int bx_sound_linux_c::stopwaveplayback() { #if BX_HAVE_ALSASOUND if (use_alsa_pcm && (alsa_pcm[0].audio_bufsize > 0)) { if (alsa_pcm[0].audio_bufsize < alsa_pcm[0].alsa_bufsize) { memset(audio_buffer[0]+alsa_pcm[0].audio_bufsize, 0, alsa_pcm[0].alsa_bufsize-alsa_pcm[0].audio_bufsize); alsa_pcm[0].audio_bufsize = alsa_pcm[0].alsa_bufsize; } alsa_pcm_write(); return BX_SOUNDLOW_OK; } #endif // ioctl(wave_fd[0], SNDCTL_DSP_SYNC); // close(wave_fd[0]); // wave_fd[0] = -1; return BX_SOUNDLOW_OK; } int bx_sound_linux_c::closewaveoutput() { #if BX_HAVE_ALSASOUND if (use_alsa_pcm && (alsa_pcm[0].handle != NULL)) { snd_pcm_drain(alsa_pcm[0].handle); snd_pcm_close(alsa_pcm[0].handle); alsa_pcm[0].handle = NULL; return BX_SOUNDLOW_OK; } #endif if (wave_device[0] != NULL) delete(wave_device[0]); if (wave_fd[0] != -1) { close(wave_fd[0]); wave_fd[0] = -1; } wave_device[0] = NULL; return BX_SOUNDLOW_OK; } int bx_sound_linux_c::openwaveinput(const char *wavedev, sound_record_handler_t rh) { record_handler = rh; if (rh != NULL) { record_timer_index = bx_pc_system.register_timer(this, record_timer_handler, 1, 1, 0, "soundlnx"); // record timer: inactive, continuous, frequency variable } #if BX_HAVE_ALSASOUND use_alsa_pcm = !strcmp(wavedev, "alsa"); if (use_alsa_pcm) { return BX_SOUNDLOW_OK; } #endif int length = strlen(wavedev) + 1; if (wave_device[1] != NULL) delete [] wave_device[1]; wave_device[1] = new char[length]; if (wave_device[1] == NULL) return BX_SOUNDLOW_ERR; strncpy(wave_device[1], wavedev, length); return BX_SOUNDLOW_OK; } int bx_sound_linux_c::startwaverecord(int frequency, int bits, bx_bool stereo, int format) { Bit64u timer_val; Bit8u shift = 0; int fmt, ret; int signeddata = format & 1; if (record_timer_index != BX_NULL_TIMER_HANDLE) { if (bits == 16) shift++; if (stereo) shift++; record_packet_size = (frequency / 10) << shift; // 0.1 sec if (record_packet_size > BX_SOUNDLOW_WAVEPACKETSIZE) { record_packet_size = BX_SOUNDLOW_WAVEPACKETSIZE; } timer_val = (Bit64u)record_packet_size * 1000000 / (frequency << shift); bx_pc_system.activate_timer(record_timer_index, (Bit32u)timer_val, 1); } #if BX_HAVE_ALSASOUND if (use_alsa_pcm) { return alsa_pcm_open(1, frequency, bits, stereo, format); } #endif if ((wave_device[1] == NULL) || (strlen(wave_device[1]) < 1)) return BX_SOUNDLOW_ERR; if (wave_fd[1] == -1) { wave_fd[1] = open(wave_device[1], O_RDONLY); if (wave_fd[1] == -1) { return BX_SOUNDLOW_ERR; } else { BX_INFO(("OSS: opened input device %s", wave_device[1])); } } else { if ((frequency == wave_ch[0].oldfreq) && (bits == wave_ch[0].oldbits) && (stereo == wave_ch[0].oldstereo) && (format == wave_ch[0].oldformat)) return BX_SOUNDLOW_OK; // nothing to do } wave_ch[0].oldfreq = frequency; wave_ch[0].oldbits = bits; wave_ch[0].oldstereo = stereo; wave_ch[0].oldformat = format; if (bits == 16) if (signeddata == 1) fmt = AFMT_S16_LE; else fmt = AFMT_U16_LE; else if (bits == 8) if (signeddata == 1) fmt = AFMT_S8; else fmt = AFMT_U8; else return BX_SOUNDLOW_ERR; // set frequency etc. ret = ioctl(wave_fd[1], SNDCTL_DSP_RESET); if (ret != 0) BX_DEBUG(("ioctl(SNDCTL_DSP_RESET): %s", strerror(errno))); ret = ioctl(wave_fd[1], SNDCTL_DSP_SETFMT, &fmt); if (ret != 0) { // abort if the format is unknown, to avoid playing noise BX_DEBUG(("ioctl(SNDCTL_DSP_SETFMT, %d): %s", fmt, strerror(errno))); return BX_SOUNDLOW_ERR; } ret = ioctl(wave_fd[1], SNDCTL_DSP_STEREO, &stereo); if (ret != 0) { BX_DEBUG(("ioctl(SNDCTL_DSP_STEREO, %d): %s", stereo, strerror(errno))); return BX_SOUNDLOW_ERR; } ret = ioctl(wave_fd[1], SNDCTL_DSP_SPEED, &frequency); if (ret != 0) { BX_DEBUG(("ioctl(SNDCTL_DSP_SPEED, %d): %s", frequency, strerror(errno))); return BX_SOUNDLOW_ERR; } return BX_SOUNDLOW_OK; } int bx_sound_linux_c::getwavepacket(int length, Bit8u data[]) { int ret; #if BX_HAVE_ALSASOUND if (use_alsa_pcm) { if (alsa_pcm[1].buffer == NULL) { alsa_pcm[1].buffer = (char *)malloc(alsa_pcm[1].alsa_bufsize); } while (alsa_pcm[1].audio_bufsize < length) { ret = snd_pcm_readi(alsa_pcm[1].handle, alsa_pcm[1].buffer, alsa_pcm[1].frames); if (ret == -EAGAIN) continue; if (ret == -EPIPE) { /* EPIPE means overrun */ BX_ERROR(("overrun occurred")); snd_pcm_prepare(alsa_pcm[1].handle); } else if (ret < 0) { BX_ERROR(("error from read: %s", snd_strerror(ret))); } else if (ret != (int)alsa_pcm[1].frames) { BX_ERROR(("short read, read %d frames", ret)); } memcpy(audio_buffer[1]+alsa_pcm[1].audio_bufsize, alsa_pcm[1].buffer, alsa_pcm[1].alsa_bufsize); alsa_pcm[1].audio_bufsize += alsa_pcm[1].alsa_bufsize; } memcpy(data, audio_buffer[1], length); alsa_pcm[1].audio_bufsize -= length; if ((alsa_pcm[1].audio_bufsize <= 0) && (alsa_pcm[1].buffer != NULL)) { free(alsa_pcm[1].buffer); alsa_pcm[1].buffer = NULL; } return BX_SOUNDLOW_OK; } #endif ret = read(wave_fd[1], data, length); if (ret == length) { return BX_SOUNDLOW_OK; } else { BX_ERROR(("OSS: write error")); return BX_SOUNDLOW_ERR; } } int bx_sound_linux_c::stopwaverecord() { if (record_timer_index != BX_NULL_TIMER_HANDLE) { bx_pc_system.deactivate_timer(record_timer_index); } #if BX_HAVE_ALSASOUND if (use_alsa_pcm && (alsa_pcm[1].handle != NULL)) { snd_pcm_drain(alsa_pcm[1].handle); return BX_SOUNDLOW_OK; } #endif return BX_SOUNDLOW_OK; } int bx_sound_linux_c::closewaveinput() { stopwaverecord(); #if BX_HAVE_ALSASOUND if (use_alsa_pcm && (alsa_pcm[1].handle != NULL)) { snd_pcm_drain(alsa_pcm[1].handle); snd_pcm_close(alsa_pcm[1].handle); alsa_pcm[1].handle = NULL; return BX_SOUNDLOW_OK; } #endif if (wave_device[1] != NULL) delete(wave_device[1]); if (wave_fd[1] != -1) { close(wave_fd[1]); wave_fd[1] = -1; } wave_device[1] = NULL; return BX_SOUNDLOW_OK; } void bx_sound_linux_c::record_timer_handler(void *this_ptr) { bx_sound_linux_c *class_ptr = (bx_sound_linux_c *) this_ptr; class_ptr->record_timer(); } void bx_sound_linux_c::record_timer(void) { record_handler(this->device, record_packet_size); } #endif bochs-2.6/iodev/pic.h0000644000175000017500000000704212020641505014365 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pic.h 11148 2012-04-23 17:06:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_PIC_H #define BX_IODEV_PIC_H #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 typedef struct { Bit8u single_PIC; /* 0=cascaded PIC, 1=master only */ Bit8u interrupt_offset; /* programmable interrupt vector offset */ union { Bit8u slave_connect_mask; /* for master, a bit for each interrupt line 0=not connect to a slave, 1=connected */ Bit8u slave_id; /* for slave, id number of slave PIC */ } u; Bit8u sfnm; /* specially fully nested mode: 0=no, 1=yes*/ Bit8u buffered_mode; /* 0=no buffered mode, 1=buffered mode */ Bit8u master_slave; /* master/slave: 0=slave PIC, 1=master PIC */ Bit8u auto_eoi; /* 0=manual EOI, 1=automatic EOI */ Bit8u imr; /* interrupt mask register, 1=masked */ Bit8u isr; /* in service register */ Bit8u irr; /* interrupt request register */ Bit8u read_reg_select; /* 0=IRR, 1=ISR */ Bit8u irq; /* current IRQ number */ Bit8u lowest_priority; /* current lowest priority irq */ bx_bool INT; /* INT request pin of PIC */ Bit8u IRQ_in; /* IRQ pins of PIC */ struct { bx_bool in_init; bx_bool requires_4; Bit8u byte_expected; } init; bx_bool special_mask; bx_bool polled; /* Set when poll command is issued. */ bx_bool rotate_on_autoeoi; /* Set when should rotate in auto-eoi mode. */ Bit8u edge_level; /* bitmap for irq mode (0=edge, 1=level) */ } bx_pic_t; class bx_pic_c : public bx_pic_stub_c { public: bx_pic_c(); virtual ~bx_pic_c(); virtual void init(void); virtual void reset(unsigned type); virtual void lower_irq(unsigned irq_no); virtual void raise_irq(unsigned irq_no); virtual void set_mode(bx_bool ma_sl, Bit8u mode); virtual Bit8u IAC(void); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif virtual void register_state(void); private: struct { bx_pic_t master_pic; bx_pic_t slave_pic; } s; static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_PIC_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif 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); }; #endif bochs-2.6/iodev/parallel.cc0000644000175000017500000003640412020641505015550 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: parallel.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // //////////////////////////////////////////////////////// // This code was just a few stubs until Volker.Ruppert@t-online.de // fixed it up in November 2001. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "parallel.h" #define LOG_THIS theParallelDevice-> bx_parallel_c *theParallelDevice = NULL; // builtin configuration handling functions void parport_init_options(void) { char name[4], label[80], descr[80]; bx_list_c *parallel = (bx_list_c*)SIM->get_param("ports.parallel"); for (int i=0; iset_options(menu->SERIES_ASK); sprintf(label, "Enable parallel port #%d", i+1); sprintf(descr, "Controls whether parallel port #%d is installed or not", i+1); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", label, descr, (i==0)? 1 : 0); // only enable #1 by default sprintf(label, "Parallel port #%d output file", i+1); sprintf(descr, "Data written to parport#%d by the guest OS is written to this file", i+1); bx_param_filename_c *path = new bx_param_filename_c(menu, "outfile", label, descr, "", BX_PATHNAME_LEN); path->set_extension("out"); bx_list_c *deplist = new bx_list_c(NULL); deplist->add(path); enabled->set_dependent_list(deplist); } } Bit32s parport_options_parser(const char *context, int num_params, char *params[]) { if ((!strncmp(params[0], "parport", 7)) && (strlen(params[0]) == 8)) { char tmpname[80]; int idx = params[0][7]; if ((idx < '1') || (idx > '9')) { BX_PANIC(("%s: parportX directive malformed.", context)); } idx -= '0'; if (idx > BX_N_PARALLEL_PORTS) { BX_PANIC(("%s: parportX port number out of range.", context)); } sprintf(tmpname, "ports.parallel.%d", idx); bx_list_c *base = (bx_list_c*) SIM->get_param(tmpname); for (int i=1; iset(atol(¶ms[i][8])); } else if (!strncmp(params[i], "file=", 5)) { SIM->get_param_string("outfile", base)->set(¶ms[i][5]); SIM->get_param_bool("enabled", base)->set(1); } else { BX_ERROR(("%s: unknown parameter for parport%d ignored.", context, idx)); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s parport_options_save(FILE *fp) { char pname[20]; for (int i=0; iget_param(pname); fprintf(fp, "parport%d: enabled=%d", i+1, SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { fprintf(fp, ", file=\"%s\"", SIM->get_param_string("outfile", base)->getptr()); } fprintf(fp, "\n"); } return 0; } // device plugin entry points int libparallel_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theParallelDevice = new bx_parallel_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theParallelDevice, BX_PLUGIN_PARALLEL); // add new configuration parameters for the config interface parport_init_options(); // register add-on options for bochsrc and command line SIM->register_addon_option("parport1", parport_options_parser, parport_options_save); SIM->register_addon_option("parport2", parport_options_parser, NULL); return(0); // Success } void libparallel_LTX_plugin_fini(void) { char pnum[4]; SIM->unregister_addon_option("parport1"); SIM->unregister_addon_option("parport2"); bx_list_c *menu = (bx_list_c*)SIM->get_param("ports.parallel"); for (int i=0; iremove(pnum); } delete theParallelDevice; } // the device object bx_parallel_c::bx_parallel_c() { put("parallel", "PAR"); for (int i=0; iget_bochs_root()->remove("parallel"); BX_DEBUG(("Exit")); } void bx_parallel_c::init(void) { Bit16u ports[BX_PARPORT_MAXDEV] = {0x0378, 0x0278}; Bit8u irqs[BX_PARPORT_MAXDEV] = {7, 5}; char name[16], pname[20]; bx_list_c *base; int count = 0; BX_DEBUG(("Init $Id: parallel.cc 11346 2012-08-19 08:16:20Z vruppert $")); for (unsigned i=0; iget_param(pname); if (SIM->get_param_bool("enabled", base)->get()) { sprintf(name, "Parallel Port %d", i + 1); /* parallel interrupt and i/o ports */ BX_PAR_THIS s[i].IRQ = irqs[i]; for (unsigned addr=ports[i]; addr<=(unsigned)(ports[i]+2); addr++) { DEV_register_ioread_handler(this, read_handler, addr, name, 1); } DEV_register_iowrite_handler(this, write_handler, ports[i], name, 1); DEV_register_iowrite_handler(this, write_handler, ports[i]+2, name, 1); BX_INFO (("parallel port %d at 0x%04x irq %d", i+1, ports[i], irqs[i])); /* internal state */ BX_PAR_THIS s[i].STATUS.error = 1; BX_PAR_THIS s[i].STATUS.slct = 1; BX_PAR_THIS s[i].STATUS.pe = 0; BX_PAR_THIS s[i].STATUS.ack = 1; BX_PAR_THIS s[i].STATUS.busy = 1; BX_PAR_THIS s[i].CONTROL.strobe = 0; BX_PAR_THIS s[i].CONTROL.autofeed = 0; BX_PAR_THIS s[i].CONTROL.init = 1; BX_PAR_THIS s[i].CONTROL.slct_in = 1; BX_PAR_THIS s[i].CONTROL.irq = 0; BX_PAR_THIS s[i].CONTROL.input = 0; BX_PAR_THIS s[i].initmode = 0; /* output file */ char *outfile = SIM->get_param_string("outfile", base)->getptr(); if (strlen(outfile) > 0) { s[i].output = fopen(outfile, "wb"); if (!s[i].output) BX_PANIC(("Could not open '%s' to write parport%d output", outfile, i+1)); } count++; } } // Check if the device is disabled or not configured if (count == 0) { BX_INFO(("parallel ports disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("parallel"))->set(0); return; } } void bx_parallel_c::reset(unsigned type) { } void bx_parallel_c::register_state(void) { unsigned i; char name[4], pname[20]; bx_list_c *base, *port; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "parallel", "Parallel Port State"); for (i=0; iget_param(pname); if (SIM->get_param_bool("enabled", base)->get()) { sprintf(name, "%d", i); port = new bx_list_c(list, name); new bx_shadow_num_c(port, "data", &BX_PAR_THIS s[i].data, BASE_HEX); new bx_shadow_bool_c(port, "slct", &BX_PAR_THIS s[i].STATUS.slct); new bx_shadow_bool_c(port, "ack", &BX_PAR_THIS s[i].STATUS.ack); new bx_shadow_bool_c(port, "busy", &BX_PAR_THIS s[i].STATUS.busy); new bx_shadow_bool_c(port, "strobe", &BX_PAR_THIS s[i].CONTROL.strobe); new bx_shadow_bool_c(port, "autofeed", &BX_PAR_THIS s[i].CONTROL.autofeed); new bx_shadow_bool_c(port, "init", &BX_PAR_THIS s[i].CONTROL.init); new bx_shadow_bool_c(port, "slct_in", &BX_PAR_THIS s[i].CONTROL.slct_in); new bx_shadow_bool_c(port, "irq", &BX_PAR_THIS s[i].CONTROL.irq); new bx_shadow_bool_c(port, "input", &BX_PAR_THIS s[i].CONTROL.input); new bx_shadow_bool_c(port, "initmode", &BX_PAR_THIS s[i].initmode); } } } void bx_parallel_c::virtual_printer(Bit8u port) { if (BX_PAR_THIS s[port].STATUS.slct) { if (BX_PAR_THIS s[port].output != NULL) { fputc(BX_PAR_THIS s[port].data, BX_PAR_THIS s[port].output); fflush (BX_PAR_THIS s[port].output); } if (BX_PAR_THIS s[port].CONTROL.irq == 1) { DEV_pic_raise_irq(BX_PAR_THIS s[port].IRQ); } BX_PAR_THIS s[port].STATUS.ack = 0; BX_PAR_THIS s[port].STATUS.busy = 1; } else { BX_ERROR(("data is valid, but printer is offline")); } } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_parallel_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_PAR_SMF bx_parallel_c *class_ptr = (bx_parallel_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_parallel_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PAR_SMF Bit8u offset; Bit8u port = 0; Bit32u retval; offset = address & 0x07; switch (address & 0x03f8) { case 0x0378: port = 0; break; case 0x0278: port = 1; break; } switch (offset) { case BX_PAR_DATA: if (!BX_PAR_THIS s[port].CONTROL.input) { return (Bit32u)BX_PAR_THIS s[port].data; } else { BX_ERROR(("read: input mode not supported")); return (0xFF); } break; case BX_PAR_STAT: { retval = ((BX_PAR_THIS s[port].STATUS.busy << 7) | (BX_PAR_THIS s[port].STATUS.ack << 6) | (BX_PAR_THIS s[port].STATUS.pe << 5) | (BX_PAR_THIS s[port].STATUS.slct << 4) | (BX_PAR_THIS s[port].STATUS.error << 3)); if (BX_PAR_THIS s[port].STATUS.ack == 0) { BX_PAR_THIS s[port].STATUS.ack = 1; if (BX_PAR_THIS s[port].CONTROL.irq == 1) { DEV_pic_lower_irq(BX_PAR_THIS s[port].IRQ); } } if (BX_PAR_THIS s[port].initmode == 1) { BX_PAR_THIS s[port].STATUS.busy = 1; BX_PAR_THIS s[port].STATUS.slct = 1; BX_PAR_THIS s[port].STATUS.ack = 0; if (BX_PAR_THIS s[port].CONTROL.irq == 1) { DEV_pic_raise_irq(BX_PAR_THIS s[port].IRQ); } BX_PAR_THIS s[port].initmode = 0; } BX_DEBUG(("read: parport%d status register returns 0x%02x", port+1, retval)); return retval; } break; case BX_PAR_CTRL: { retval = ((BX_PAR_THIS s[port].CONTROL.input << 5) | (BX_PAR_THIS s[port].CONTROL.irq << 4) | (BX_PAR_THIS s[port].CONTROL.slct_in << 3) | (BX_PAR_THIS s[port].CONTROL.init << 2) | (BX_PAR_THIS s[port].CONTROL.autofeed << 1) | (BX_PAR_THIS s[port].CONTROL.strobe)); BX_DEBUG(("read: parport%d control register returns 0x%02x", port+1, retval)); return retval; } break; } return(0); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_parallel_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_PAR_SMF bx_parallel_c *class_ptr = (bx_parallel_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_parallel_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PAR_SMF Bit8u offset; Bit8u port = 0; char name[16]; offset = address & 0x07; switch (address & 0x03f8) { case 0x0378: port = 0; break; case 0x0278: port = 1; break; } switch (offset) { case BX_PAR_DATA: BX_PAR_THIS s[port].data = (Bit8u)value; BX_DEBUG(("write: parport%d data output register = 0x%02x", port+1, (Bit8u)value)); break; case BX_PAR_CTRL: { if ((value & 0x01) == 0x01) { if (BX_PAR_THIS s[port].CONTROL.strobe == 0) { BX_PAR_THIS s[port].CONTROL.strobe = 1; virtual_printer(port); // data is valid now } } else { if (BX_PAR_THIS s[port].CONTROL.strobe == 1) { BX_PAR_THIS s[port].CONTROL.strobe = 0; } } BX_PAR_THIS s[port].CONTROL.autofeed = ((value & 0x02) == 0x02); if ((value & 0x04) == 0x04) { if (BX_PAR_THIS s[port].CONTROL.init == 0) { BX_PAR_THIS s[port].CONTROL.init = 1; BX_PAR_THIS s[port].STATUS.busy = 0; BX_PAR_THIS s[port].STATUS.slct = 0; BX_PAR_THIS s[port].initmode = 1; BX_DEBUG(("parport%d: printer init requested", port+1)); } } else { if (BX_PAR_THIS s[port].CONTROL.init == 1) { BX_PAR_THIS s[port].CONTROL.init = 0; } } if ((value & 0x08) == 0x08) { if (BX_PAR_THIS s[port].CONTROL.slct_in == 0) { BX_PAR_THIS s[port].CONTROL.slct_in = 1; BX_DEBUG(("parport%d: printer now online", port+1)); } } else { if (BX_PAR_THIS s[port].CONTROL.slct_in == 1) { BX_PAR_THIS s[port].CONTROL.slct_in = 0; BX_DEBUG(("parport%d: printer now offline", port+1)); } } BX_PAR_THIS s[port].STATUS.slct = BX_PAR_THIS s[port].CONTROL.slct_in; if ((value & 0x10) == 0x10) { if (BX_PAR_THIS s[port].CONTROL.irq == 0) { BX_PAR_THIS s[port].CONTROL.irq = 1; sprintf(name, "Parallel Port %d", port+1); DEV_register_irq(BX_PAR_THIS s[port].IRQ, name); BX_DEBUG(("parport%d: irq mode selected", port+1)); } } else { if (BX_PAR_THIS s[port].CONTROL.irq == 1) { BX_PAR_THIS s[port].CONTROL.irq = 0; sprintf(name, "Parallel Port %d", port+1); DEV_unregister_irq(BX_PAR_THIS s[port].IRQ, name); BX_DEBUG(("parport%d: polling mode selected", port+1)); } } if ((value & 0x20) == 0x20) { if (BX_PAR_THIS s[port].CONTROL.input == 0) { BX_PAR_THIS s[port].CONTROL.input = 1; BX_DEBUG(("parport%d: data input mode selected", port+1)); } } else { if (BX_PAR_THIS s[port].CONTROL.input == 1) { BX_PAR_THIS s[port].CONTROL.input = 0; BX_DEBUG(("parport%d: data output mode selected", port+1)); } } if ((value & 0xC0) > 0) { BX_ERROR(("write: parport%d: unsupported control bit ignored", port+1)); } } break; } } bochs-2.6/iodev/extfpuirq.cc0000644000175000017500000000525512020641505016003 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: extfpuirq.cc 10898 2011-12-30 11:13:37Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // External circuit for MSDOS compatible FPU exceptions // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "extfpuirq.h" #define LOG_THIS theExternalFpuIrq-> bx_extfpuirq_c *theExternalFpuIrq = NULL; int libextfpuirq_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theExternalFpuIrq = new bx_extfpuirq_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theExternalFpuIrq, BX_PLUGIN_EXTFPUIRQ); return(0); // Success } void libextfpuirq_LTX_plugin_fini(void) { delete theExternalFpuIrq; } bx_extfpuirq_c::bx_extfpuirq_c(void) { put("extfpuirq", "EFIRQ"); } bx_extfpuirq_c::~bx_extfpuirq_c(void) { BX_DEBUG(("Exit")); } void bx_extfpuirq_c::init(void) { // called once when bochs initializes DEV_register_iowrite_handler(this, write_handler, 0x00F0, "External FPU IRQ", 1); DEV_register_irq(13, "External FPU IRQ"); } void bx_extfpuirq_c::reset(unsigned type) { // We should handle IGNNE here DEV_pic_lower_irq(13); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_extfpuirq_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_EFI_SMF bx_extfpuirq_c *class_ptr = (bx_extfpuirq_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_extfpuirq_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_EFI_SMF // We should handle IGNNE here DEV_pic_lower_irq(13); } bochs-2.6/iodev/dma.h0000644000175000017500000000700312020641505014350 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: dma.h 11277 2012-07-12 21:20:46Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef _PCDMA_H #define _PCDMA_H #if BX_USE_DMA_SMF # define BX_DMA_SMF static # define BX_DMA_THIS theDmaDevice-> #else # define BX_DMA_SMF # define BX_DMA_THIS this-> #endif class bx_dma_c : public bx_dma_stub_c { public: bx_dma_c(); virtual ~bx_dma_c(); virtual void init(void); virtual void reset(unsigned type); virtual void raise_HLDA(void); virtual void set_DRQ(unsigned channel, bx_bool val); virtual unsigned get_TC(void); virtual void register_state(void); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif virtual unsigned registerDMA8Channel(unsigned channel, Bit16u (* dmaRead)(Bit8u *data_byte, Bit16u maxlen), Bit16u (* dmaWrite)(Bit8u *data_byte, Bit16u maxlen), const char *name); virtual unsigned registerDMA16Channel(unsigned channel, Bit16u (* dmaRead)(Bit16u *data_word, Bit16u maxlen), Bit16u (* dmaWrite)(Bit16u *data_word, Bit16u maxlen), const char *name); virtual unsigned unregisterDMAChannel(unsigned channel); private: static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_DMA_SMF Bit32u read (Bit32u address, unsigned io_len) BX_CPP_AttrRegparmN(2); void write(Bit32u address, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); #endif BX_DMA_SMF void control_HRQ(bx_bool ma_sl); BX_DMA_SMF void reset_controller(unsigned num); struct { bx_bool DRQ[4]; // DMA Request bx_bool DACK[4]; // DMA Acknowlege bx_bool mask[4]; bx_bool flip_flop; Bit8u status_reg; Bit8u command_reg; bx_bool ctrl_disabled; struct { struct { Bit8u mode_type; bx_bool address_decrement; bx_bool autoinit_enable; Bit8u transfer_type; } mode; Bit16u base_address; Bit16u current_address; Bit16u base_count; Bit16u current_count; Bit8u page_reg; bx_bool used; } chan[4]; /* DMA channels 0..3 */ } s[2]; // state information DMA-1 / DMA-2 bx_bool HLDA; // Hold Acknowlege bx_bool TC; // Terminal Count Bit8u ext_page_reg[16]; // Extra page registers (unused) struct { Bit16u (* dmaRead8)(Bit8u *data_byte, Bit16u maxlen); Bit16u (* dmaWrite8)(Bit8u *data_byte, Bit16u maxlen); Bit16u (* dmaRead16)(Bit16u *data_word, Bit16u maxlen); Bit16u (* dmaWrite16)(Bit16u *data_word, Bit16u maxlen); } h[4]; // DMA read and write handlers }; #endif // #ifndef _PCDMA_H bochs-2.6/iodev/virt_timer.h0000644000175000017500000001222012020641505015770 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: virt_timer.h 11183 2012-05-17 09:11:48Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef _BX_VIRT_TIMER_H #define _BX_VIRT_TIMER_H // should be adjusted if want to support more SMP processors #define BX_MAX_VIRTUAL_TIMERS (32) #define BX_NULL_VIRTUAL_TIMER_HANDLE 10000 #define BX_MAX_VIRTUAL_TIME (0x7fffffff) class BOCHSAPI bx_virt_timer_c : public logfunctions { private: struct { bx_bool inUse; // Timer slot is in-use (currently registered). Bit64u period; // Timer periodocity in virtual useconds. Bit64u timeToFire; // Time to fire next (in virtual useconds). bx_bool active; // 0=inactive, 1=active. bx_bool continuous; // 0=one-shot timer, 1=continuous periodicity. bx_timer_handler_t funct; // A callback function for when the // timer fires. // This function MUST return. void *this_ptr; // The this-> pointer for C++ callbacks // has to be stored as well. char id[BxMaxTimerIDLen]; // String ID of timer. } timer[BX_MAX_VIRTUAL_TIMERS]; unsigned numTimers; // Number of currently allocated timers. //Variables for the timer subsystem: Bit64u current_timers_time; Bit64u timers_next_event_time; Bit64u last_sequential_time; bx_bool in_timer_handler; //Variables for the time sync subsystem: Bit64u virtual_next_event_time; Bit64u current_virtual_time; //Real time variables: Bit64u last_real_time; Bit64u total_real_usec; Bit64u last_realtime_delta; Bit64u real_time_delay; //System time variables: Bit64u last_usec; Bit64u usec_per_second; Bit64u stored_delta; Bit64u last_system_usec; Bit64u em_last_realtime; //Virtual timer variables: Bit64u total_ticks; Bit64u last_realtime_ticks; Bit64u ticks_per_second; // Local copy of IPS value Bit64u ips; bx_bool init_done; int system_timer_id; //Whether or not to use realtime virtual timers. bx_bool virtual_timers_realtime; // A special null timer is always inserted in the timer[0] slot. This // make sure that at least one timer is always active, and that the // duration is always less than a maximum 32-bit integer, so a 32-bit // counter can be used for the current countdown. static const Bit64u NullTimerInterval; static void nullTimer(void* this_ptr); //Step the given number of cycles, optionally calling any timer handlers. void periodic(Bit64u time_passed); //Called when next_event_time changes. void next_event_time_update(void); //Called to advance the virtual time. // calls periodic as needed. void advance_virtual_time(Bit64u time_passed); public: bx_virt_timer_c(); virtual ~bx_virt_timer_c() {} //Get the current virtual time. // This may return the same value on subsequent calls. Bit64u time_usec(void); //Get the current virtual time. // This will return a monotonically increasing value. // MUST NOT be called from within a timer handler. Bit64u time_usec_sequential(void); //Register a timer handler to go off after a given interval. //Register a timer handler to go off with a periodic interval. int register_timer(void *this_ptr, bx_timer_handler_t handler, Bit32u useconds, bx_bool continuous, bx_bool active, const char *id); //unregister a previously registered timer. bx_bool unregisterTimer(unsigned timerID); void start_timers(void); //activate a deactivated but registered timer. void activate_timer(unsigned timer_index, Bit32u useconds, bx_bool continuous); //deactivate (but don't unregister) a currently registered timer. void deactivate_timer(unsigned timer_index); //Timer handler passed to pc_system static void pc_system_timer_handler(void* this_ptr); //The real timer handler. void timer_handler(); //Initialization step #1 in constructor and for cleanup void setup(void); //Initialization step #2 void init(void); void register_state(void); //Determine the real time elapsed during runtime config or between save and //restore. void set_realtime_delay(void); }; BOCHSAPI extern bx_virt_timer_c bx_virt_timer; #endif // _BX_VIRT_TIMER_H bochs-2.6/iodev/pic.cc0000644000175000017500000010130512020641505014520 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pic.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "pic.h" #define LOG_THIS thePic-> bx_pic_c *thePic = NULL; int libpic_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { thePic = new bx_pic_c(); bx_devices.pluginPicDevice = thePic; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePic, BX_PLUGIN_PIC); return 0; // Success } else { return -1; } } void libpic_LTX_plugin_fini(void) { delete thePic; } bx_pic_c::bx_pic_c(void) { put("PIC"); } bx_pic_c::~bx_pic_c(void) { SIM->get_bochs_root()->remove("pic"); BX_DEBUG(("Exit")); } void bx_pic_c::init(void) { /* 8259 PIC (Programmable Interrupt Controller) */ DEV_register_ioread_handler(this, read_handler, 0x0020, "8259 PIC", 1); DEV_register_ioread_handler(this, read_handler, 0x0021, "8259 PIC", 1); DEV_register_ioread_handler(this, read_handler, 0x00A0, "8259 PIC", 1); DEV_register_ioread_handler(this, read_handler, 0x00A1, "8259 PIC", 1); DEV_register_iowrite_handler(this, write_handler, 0x0020, "8259 PIC", 1); DEV_register_iowrite_handler(this, write_handler, 0x0021, "8259 PIC", 1); DEV_register_iowrite_handler(this, write_handler, 0x00A0, "8259 PIC", 1); DEV_register_iowrite_handler(this, write_handler, 0x00A1, "8259 PIC", 1); BX_PIC_THIS s.master_pic.single_PIC = 0; BX_PIC_THIS s.master_pic.interrupt_offset = 0x08; /* IRQ0 = INT 0x08 */ /* slave PIC connected to IRQ2 of master */ BX_PIC_THIS s.master_pic.u.slave_connect_mask = 0x04; BX_PIC_THIS s.master_pic.sfnm = 0; /* normal nested mode */ BX_PIC_THIS s.master_pic.buffered_mode = 0; /* unbuffered mode */ BX_PIC_THIS s.master_pic.master_slave = 1; /* master PIC */ BX_PIC_THIS s.master_pic.auto_eoi = 0; /* manual EOI from CPU */ BX_PIC_THIS s.master_pic.imr = 0xFF; /* all IRQ's initially masked */ BX_PIC_THIS s.master_pic.isr = 0x00; /* no IRQ's in service */ BX_PIC_THIS s.master_pic.irr = 0x00; /* no IRQ's requested */ BX_PIC_THIS s.master_pic.read_reg_select = 0; /* IRR */ BX_PIC_THIS s.master_pic.irq = 0; BX_PIC_THIS s.master_pic.INT = 0; BX_PIC_THIS s.master_pic.init.in_init = 0; BX_PIC_THIS s.master_pic.init.requires_4 = 0; BX_PIC_THIS s.master_pic.init.byte_expected = 0; BX_PIC_THIS s.master_pic.special_mask = 0; BX_PIC_THIS s.master_pic.lowest_priority = 7; BX_PIC_THIS s.master_pic.polled = 0; BX_PIC_THIS s.master_pic.rotate_on_autoeoi = 0; BX_PIC_THIS s.master_pic.edge_level = 0; BX_PIC_THIS s.master_pic.IRQ_in = 0; BX_PIC_THIS s.slave_pic.single_PIC = 0; BX_PIC_THIS s.slave_pic.interrupt_offset = 0x70; /* IRQ8 = INT 0x70 */ BX_PIC_THIS s.slave_pic.u.slave_id = 0x02; /* slave PIC connected to IRQ2 of master */ BX_PIC_THIS s.slave_pic.sfnm = 0; /* normal nested mode */ BX_PIC_THIS s.slave_pic.buffered_mode = 0; /* unbuffered mode */ BX_PIC_THIS s.slave_pic.master_slave = 0; /* slave PIC */ BX_PIC_THIS s.slave_pic.auto_eoi = 0; /* manual EOI from CPU */ BX_PIC_THIS s.slave_pic.imr = 0xFF; /* all IRQ's initially masked */ BX_PIC_THIS s.slave_pic.isr = 0x00; /* no IRQ's in service */ BX_PIC_THIS s.slave_pic.irr = 0x00; /* no IRQ's requested */ BX_PIC_THIS s.slave_pic.read_reg_select = 0; /* IRR */ BX_PIC_THIS s.slave_pic.irq = 0; BX_PIC_THIS s.slave_pic.INT = 0; BX_PIC_THIS s.slave_pic.init.in_init = 0; BX_PIC_THIS s.slave_pic.init.requires_4 = 0; BX_PIC_THIS s.slave_pic.init.byte_expected = 0; BX_PIC_THIS s.slave_pic.special_mask = 0; BX_PIC_THIS s.slave_pic.lowest_priority = 7; BX_PIC_THIS s.slave_pic.polled = 0; BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = 0; BX_PIC_THIS s.slave_pic.edge_level = 0; BX_PIC_THIS s.slave_pic.IRQ_in = 0; #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("pic", this); #endif } void bx_pic_c::reset(unsigned type) {} void bx_pic_c::register_state(void) { bx_list_c *ctrl; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "pic", "PIC State"); ctrl = new bx_list_c(list, "master"); new bx_shadow_num_c(ctrl, "interrupt_offset", &BX_PIC_THIS s.master_pic.interrupt_offset, BASE_HEX); new bx_shadow_num_c(ctrl, "auto_eoi", &BX_PIC_THIS s.master_pic.auto_eoi, BASE_HEX); new bx_shadow_num_c(ctrl, "imr", &BX_PIC_THIS s.master_pic.imr, BASE_HEX); new bx_shadow_num_c(ctrl, "isr", &BX_PIC_THIS s.master_pic.isr, BASE_HEX); new bx_shadow_num_c(ctrl, "irr", &BX_PIC_THIS s.master_pic.irr, BASE_HEX); new bx_shadow_num_c(ctrl, "read_reg_select", &BX_PIC_THIS s.master_pic.read_reg_select); new bx_shadow_num_c(ctrl, "irq", &BX_PIC_THIS s.master_pic.irq, BASE_HEX); new bx_shadow_num_c(ctrl, "lowest_priority", &BX_PIC_THIS s.master_pic.lowest_priority, BASE_HEX); new bx_shadow_bool_c(ctrl, "INT", &BX_PIC_THIS s.master_pic.INT); new bx_shadow_num_c(ctrl, "IRQ_in", &BX_PIC_THIS s.master_pic.IRQ_in, BASE_HEX); new bx_shadow_bool_c(ctrl, "in_init", &BX_PIC_THIS s.master_pic.init.in_init); new bx_shadow_bool_c(ctrl, "requires_4", &BX_PIC_THIS s.master_pic.init.requires_4); new bx_shadow_num_c(ctrl, "byte_expected", &BX_PIC_THIS s.master_pic.init.byte_expected); new bx_shadow_bool_c(ctrl, "special_mask", &BX_PIC_THIS s.master_pic.special_mask); new bx_shadow_bool_c(ctrl, "polled", &BX_PIC_THIS s.master_pic.polled); new bx_shadow_bool_c(ctrl, "rotate_on_autoeoi", &BX_PIC_THIS s.master_pic.rotate_on_autoeoi); new bx_shadow_num_c(ctrl, "edge_level", &BX_PIC_THIS s.master_pic.edge_level, BASE_HEX); ctrl = new bx_list_c(list, "slave"); new bx_shadow_num_c(ctrl, "interrupt_offset", &BX_PIC_THIS s.slave_pic.interrupt_offset, BASE_HEX); new bx_shadow_num_c(ctrl, "auto_eoi", &BX_PIC_THIS s.slave_pic.auto_eoi, BASE_HEX); new bx_shadow_num_c(ctrl, "imr", &BX_PIC_THIS s.slave_pic.imr, BASE_HEX); new bx_shadow_num_c(ctrl, "isr", &BX_PIC_THIS s.slave_pic.isr, BASE_HEX); new bx_shadow_num_c(ctrl, "irr", &BX_PIC_THIS s.slave_pic.irr, BASE_HEX); new bx_shadow_num_c(ctrl, "read_reg_select", &BX_PIC_THIS s.slave_pic.read_reg_select); new bx_shadow_num_c(ctrl, "irq", &BX_PIC_THIS s.slave_pic.irq, BASE_HEX); new bx_shadow_num_c(ctrl, "lowest_priority", &BX_PIC_THIS s.slave_pic.lowest_priority, BASE_HEX); new bx_shadow_bool_c(ctrl, "INT", &BX_PIC_THIS s.slave_pic.INT); new bx_shadow_num_c(ctrl, "IRQ_in", &BX_PIC_THIS s.slave_pic.IRQ_in, BASE_HEX); new bx_shadow_bool_c(ctrl, "in_init", &BX_PIC_THIS s.slave_pic.init.in_init); new bx_shadow_bool_c(ctrl, "requires_4", &BX_PIC_THIS s.slave_pic.init.requires_4); new bx_shadow_num_c(ctrl, "byte_expected", &BX_PIC_THIS s.slave_pic.init.byte_expected); new bx_shadow_bool_c(ctrl, "special_mask", &BX_PIC_THIS s.slave_pic.special_mask); new bx_shadow_bool_c(ctrl, "polled", &BX_PIC_THIS s.slave_pic.polled); new bx_shadow_bool_c(ctrl, "rotate_on_autoeoi", &BX_PIC_THIS s.slave_pic.rotate_on_autoeoi); new bx_shadow_num_c(ctrl, "edge_level", &BX_PIC_THIS s.slave_pic.edge_level, BASE_HEX); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_pic_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_PIC_SMF bx_pic_c *class_ptr = (bx_pic_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_pic_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PIC_SMF BX_DEBUG(("IO read from %04x", (unsigned) address)); /* 8259A PIC */ if((address == 0x20 || address == 0x21) && BX_PIC_THIS s.master_pic.polled) { // In polled mode. Treat this as an interrupt acknowledge clear_highest_interrupt(& BX_PIC_THIS s.master_pic); BX_PIC_THIS s.master_pic.polled = 0; service_master_pic(); return io_len==1?BX_PIC_THIS s.master_pic.irq:(BX_PIC_THIS s.master_pic.irq)<<8|(BX_PIC_THIS s.master_pic.irq); // Return the current irq requested } if((address == 0xa0 || address == 0xa1) && BX_PIC_THIS s.slave_pic.polled) { // In polled mode. Treat this as an interrupt acknowledge clear_highest_interrupt(& BX_PIC_THIS s.slave_pic); BX_PIC_THIS s.slave_pic.polled = 0; service_slave_pic(); return io_len==1?BX_PIC_THIS s.slave_pic.irq:(BX_PIC_THIS s.slave_pic.irq)<<8|(BX_PIC_THIS s.slave_pic.irq); // Return the current irq requested } switch (address) { case 0x20: if (BX_PIC_THIS s.master_pic.read_reg_select) { /* ISR */ BX_DEBUG(("read master ISR = %02x", (unsigned) BX_PIC_THIS s.master_pic.isr)); return(BX_PIC_THIS s.master_pic.isr); } else { /* IRR */ BX_DEBUG(("read master IRR = %02x", (unsigned) BX_PIC_THIS s.master_pic.irr)); return(BX_PIC_THIS s.master_pic.irr); } break; case 0x21: BX_DEBUG(("read master IMR = %02x", (unsigned) BX_PIC_THIS s.master_pic.imr)); return(BX_PIC_THIS s.master_pic.imr); case 0xA0: if (BX_PIC_THIS s.slave_pic.read_reg_select) { /* ISR */ BX_DEBUG(("read slave ISR = %02x", (unsigned) BX_PIC_THIS s.slave_pic.isr)); return(BX_PIC_THIS s.slave_pic.isr); } else { /* IRR */ BX_DEBUG(("read slave IRR = %02x", (unsigned) BX_PIC_THIS s.slave_pic.irr)); return(BX_PIC_THIS s.slave_pic.irr); } break; case 0xA1: BX_DEBUG(("read slave IMR = %02x", (unsigned) BX_PIC_THIS s.slave_pic.imr)); return(BX_PIC_THIS s.slave_pic.imr); } BX_PANIC(("io read to address %04x", (unsigned) address)); return(0); /* default if not found above */ } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_pic_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_PIC_SMF bx_pic_c *class_ptr = (bx_pic_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_pic_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PIC_SMF BX_DEBUG(("IO write to %04x = %02x", (unsigned) address, (unsigned) value)); /* 8259A PIC */ switch (address) { case 0x20: if (value & 0x10) { /* initialization command 1 */ BX_DEBUG(("master: init command 1 found")); BX_DEBUG((" requires 4 = %u", (unsigned) (value & 0x01))); BX_DEBUG((" cascade mode: [0=cascade,1=single] %u", (unsigned) ((value & 0x02) >> 1))); BX_PIC_THIS s.master_pic.init.in_init = 1; BX_PIC_THIS s.master_pic.init.requires_4 = (value & 0x01); BX_PIC_THIS s.master_pic.init.byte_expected = 2; /* operation command 2 */ BX_PIC_THIS s.master_pic.imr = 0x00; /* clear the irq mask register */ BX_PIC_THIS s.master_pic.isr = 0x00; /* no IRQ's in service */ BX_PIC_THIS s.master_pic.irr = 0x00; /* no IRQ's requested */ BX_PIC_THIS s.master_pic.lowest_priority = 7; BX_PIC_THIS s.master_pic.INT = 0; /* reprogramming clears previous INTR request */ BX_PIC_THIS s.master_pic.auto_eoi = 0; BX_PIC_THIS s.master_pic.rotate_on_autoeoi = 0; if (value & 0x02) BX_PANIC(("master: ICW1: single mode not supported")); if (value & 0x08) { BX_PANIC(("master: ICW1: level sensitive mode not supported")); } else { BX_DEBUG(("master: ICW1: edge triggered mode selected")); } BX_SET_INTR(0); return; } if ((value & 0x18) == 0x08) { /* OCW3 */ Bit8u special_mask, poll, read_op; special_mask = (value & 0x60) >> 5; poll = (value & 0x04) >> 2; read_op = (value & 0x03); if (poll) { BX_PIC_THIS s.master_pic.polled = 1; return; } if (read_op == 0x02) /* read IRR */ BX_PIC_THIS s.master_pic.read_reg_select = 0; else if (read_op == 0x03) /* read ISR */ BX_PIC_THIS s.master_pic.read_reg_select = 1; if (special_mask == 0x02) { /* cancel special mask */ BX_PIC_THIS s.master_pic.special_mask = 0; } else if (special_mask == 0x03) { /* set specific mask */ BX_PIC_THIS s.master_pic.special_mask = 1; service_master_pic(); } return; } /* OCW2 */ switch (value) { case 0x00: // Rotate in auto eoi mode clear case 0x80: // Rotate in auto eoi mode set BX_PIC_THIS s.master_pic.rotate_on_autoeoi = (value != 0); break; case 0xA0: // Rotate on non-specific end of interrupt case 0x20: /* end of interrupt command */ clear_highest_interrupt(& BX_PIC_THIS s.master_pic); if(value == 0xA0) {// Rotate in Auto-EOI mode BX_PIC_THIS s.master_pic.lowest_priority ++; if(BX_PIC_THIS s.master_pic.lowest_priority > 7) BX_PIC_THIS s.master_pic.lowest_priority = 0; } service_master_pic(); break; case 0x40: // Intel PIC spec-sheet seems to indicate this should be ignored BX_INFO(("IRQ no-op")); break; case 0x60: /* specific EOI 0 */ case 0x61: /* specific EOI 1 */ case 0x62: /* specific EOI 2 */ case 0x63: /* specific EOI 3 */ case 0x64: /* specific EOI 4 */ case 0x65: /* specific EOI 5 */ case 0x66: /* specific EOI 6 */ case 0x67: /* specific EOI 7 */ BX_PIC_THIS s.master_pic.isr &= ~(1 << (value-0x60)); service_master_pic(); break; // IRQ lowest priority commands case 0xC0: // 0 7 6 5 4 3 2 1 case 0xC1: // 1 0 7 6 5 4 3 2 case 0xC2: // 2 1 0 7 6 5 4 3 case 0xC3: // 3 2 1 0 7 6 5 4 case 0xC4: // 4 3 2 1 0 7 6 5 case 0xC5: // 5 4 3 2 1 0 7 6 case 0xC6: // 6 5 4 3 2 1 0 7 case 0xC7: // 7 6 5 4 3 2 1 0 BX_INFO(("IRQ lowest command 0x%x", value)); BX_PIC_THIS s.master_pic.lowest_priority = value - 0xC0; break; case 0xE0: // specific EOI and rotate 0 case 0xE1: // specific EOI and rotate 1 case 0xE2: // specific EOI and rotate 2 case 0xE3: // specific EOI and rotate 3 case 0xE4: // specific EOI and rotate 4 case 0xE5: // specific EOI and rotate 5 case 0xE6: // specific EOI and rotate 6 case 0xE7: // specific EOI and rotate 7 BX_PIC_THIS s.master_pic.isr &= ~(1 << (value-0xE0)); BX_PIC_THIS s.master_pic.lowest_priority = (value - 0xE0); service_master_pic(); break; case 0x02: // single mode bit: 1 = single, 0 = cascade // ignore. 386BSD writes this value but works with it ignored. break; default: BX_PANIC(("write to port 20h = %02x", value)); } /* switch (value) */ break; case 0x21: /* initialization mode operation */ if (BX_PIC_THIS s.master_pic.init.in_init) { switch (BX_PIC_THIS s.master_pic.init.byte_expected) { case 2: BX_PIC_THIS s.master_pic.interrupt_offset = value & 0xf8; BX_PIC_THIS s.master_pic.init.byte_expected = 3; BX_DEBUG(("master: init command 2 = %02x", (unsigned) value)); BX_DEBUG((" offset = INT %02x", BX_PIC_THIS s.master_pic.interrupt_offset)); return; break; case 3: BX_DEBUG(("master: init command 3 = %02x", (unsigned) value)); if (BX_PIC_THIS s.master_pic.init.requires_4) { BX_PIC_THIS s.master_pic.init.byte_expected = 4; } else { BX_PIC_THIS s.master_pic.init.in_init = 0; } return; break; case 4: BX_DEBUG(("master: init command 4 = %02x", (unsigned) value)); if (value & 0x02) { BX_DEBUG((" auto EOI")); BX_PIC_THIS s.master_pic.auto_eoi = 1; } else { BX_DEBUG(("normal EOI interrupt")); BX_PIC_THIS s.master_pic.auto_eoi = 0; } if (value & 0x01) { BX_DEBUG((" 80x86 mode")); } else BX_PANIC((" not 80x86 mode")); BX_PIC_THIS s.master_pic.init.in_init = 0; return; default: BX_PANIC(("master expecting bad init command")); } } /* normal operation */ BX_DEBUG(("setting master pic IMR to %02x", value)); BX_PIC_THIS s.master_pic.imr = value; service_master_pic(); return; case 0xA0: if (value & 0x10) { /* initialization command 1 */ BX_DEBUG(("slave: init command 1 found")); BX_DEBUG((" requires 4 = %u", (unsigned) (value & 0x01))); BX_DEBUG((" cascade mode: [0=cascade,1=single] %u", (unsigned) ((value & 0x02) >> 1))); BX_PIC_THIS s.slave_pic.init.in_init = 1; BX_PIC_THIS s.slave_pic.init.requires_4 = (value & 0x01); BX_PIC_THIS s.slave_pic.init.byte_expected = 2; /* operation command 2 */ BX_PIC_THIS s.slave_pic.imr = 0x00; /* clear irq mask */ BX_PIC_THIS s.slave_pic.isr = 0x00; /* no IRQ's in service */ BX_PIC_THIS s.slave_pic.irr = 0x00; /* no IRQ's requested */ BX_PIC_THIS s.slave_pic.lowest_priority = 7; BX_PIC_THIS s.slave_pic.INT = 0; /* reprogramming clears previous INTR request */ BX_PIC_THIS s.master_pic.IRQ_in &= ~(1 << 2); BX_PIC_THIS s.slave_pic.auto_eoi = 0; BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = 0; if (value & 0x02) BX_PANIC(("slave: ICW1: single mode not supported")); if (value & 0x08) { BX_PANIC(("slave: ICW1: level sensitive mode not supported")); } else { BX_DEBUG(("slave: ICW1: edge triggered mode selected")); } return; } if ((value & 0x18) == 0x08) { /* OCW3 */ Bit8u special_mask, poll, read_op; special_mask = (value & 0x60) >> 5; poll = (value & 0x04) >> 2; read_op = (value & 0x03); if (poll) { BX_PIC_THIS s.slave_pic.polled = 1; return; } if (read_op == 0x02) /* read IRR */ BX_PIC_THIS s.slave_pic.read_reg_select = 0; else if (read_op == 0x03) /* read ISR */ BX_PIC_THIS s.slave_pic.read_reg_select = 1; if (special_mask == 0x02) { /* cancel special mask */ BX_PIC_THIS s.slave_pic.special_mask = 0; } else if (special_mask == 0x03) { /* set specific mask */ BX_PIC_THIS s.slave_pic.special_mask = 1; service_slave_pic(); } return; } switch (value) { case 0x00: // Rotate in auto eoi mode clear case 0x80: // Rotate in auto eoi mode set BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = (value != 0); break; case 0xA0: // Rotate on non-specific end of interrupt case 0x20: /* end of interrupt command */ clear_highest_interrupt(& BX_PIC_THIS s.slave_pic); if(value == 0xA0) {// Rotate in Auto-EOI mode BX_PIC_THIS s.slave_pic.lowest_priority ++; if(BX_PIC_THIS s.slave_pic.lowest_priority > 7) BX_PIC_THIS s.slave_pic.lowest_priority = 0; } service_slave_pic(); break; case 0x40: // Intel PIC spec-sheet seems to indicate this should be ignored BX_INFO(("IRQ no-op")); break; case 0x60: /* specific EOI 0 */ case 0x61: /* specific EOI 1 */ case 0x62: /* specific EOI 2 */ case 0x63: /* specific EOI 3 */ case 0x64: /* specific EOI 4 */ case 0x65: /* specific EOI 5 */ case 0x66: /* specific EOI 6 */ case 0x67: /* specific EOI 7 */ BX_PIC_THIS s.slave_pic.isr &= ~(1 << (value-0x60)); service_slave_pic(); break; // IRQ lowest priority commands case 0xC0: // 0 7 6 5 4 3 2 1 case 0xC1: // 1 0 7 6 5 4 3 2 case 0xC2: // 2 1 0 7 6 5 4 3 case 0xC3: // 3 2 1 0 7 6 5 4 case 0xC4: // 4 3 2 1 0 7 6 5 case 0xC5: // 5 4 3 2 1 0 7 6 case 0xC6: // 6 5 4 3 2 1 0 7 case 0xC7: // 7 6 5 4 3 2 1 0 BX_INFO(("IRQ lowest command 0x%x", value)); BX_PIC_THIS s.slave_pic.lowest_priority = value - 0xC0; break; case 0xE0: // specific EOI and rotate 0 case 0xE1: // specific EOI and rotate 1 case 0xE2: // specific EOI and rotate 2 case 0xE3: // specific EOI and rotate 3 case 0xE4: // specific EOI and rotate 4 case 0xE5: // specific EOI and rotate 5 case 0xE6: // specific EOI and rotate 6 case 0xE7: // specific EOI and rotate 7 BX_PIC_THIS s.slave_pic.isr &= ~(1 << (value-0xE0)); BX_PIC_THIS s.slave_pic.lowest_priority = (value - 0xE0); service_slave_pic(); break; case 0x02: // single mode bit: 1 = single, 0 = cascade // ignore. 386BSD writes this value but works with it ignored. break; default: BX_PANIC(("write to port A0h = %02x", value)); } /* switch (value) */ break; case 0xA1: /* initialization mode operation */ if (BX_PIC_THIS s.slave_pic.init.in_init) { switch (BX_PIC_THIS s.slave_pic.init.byte_expected) { case 2: BX_PIC_THIS s.slave_pic.interrupt_offset = value & 0xf8; BX_PIC_THIS s.slave_pic.init.byte_expected = 3; BX_DEBUG(("slave: init command 2 = %02x", (unsigned) value)); BX_DEBUG((" offset = INT %02x", BX_PIC_THIS s.slave_pic.interrupt_offset)); return; case 3: BX_DEBUG(("slave: init command 3 = %02x", (unsigned) value)); if (BX_PIC_THIS s.slave_pic.init.requires_4) { BX_PIC_THIS s.slave_pic.init.byte_expected = 4; } else { BX_PIC_THIS s.slave_pic.init.in_init = 0; } return; case 4: BX_DEBUG(("slave: init command 4 = %02x", (unsigned) value)); if (value & 0x02) { BX_DEBUG((" auto EOI")); BX_PIC_THIS s.slave_pic.auto_eoi = 1; } else { BX_DEBUG(("normal EOI interrupt")); BX_PIC_THIS s.slave_pic.auto_eoi = 0; } if (value & 0x01) { BX_DEBUG((" 80x86 mode")); } else BX_PANIC((" not 80x86 mode")); BX_PIC_THIS s.slave_pic.init.in_init = 0; return; default: BX_PANIC(("slave: expecting bad init command")); } } /* normal operation */ BX_DEBUG(("setting slave pic IMR to %02x", value)); BX_PIC_THIS s.slave_pic.imr = value; service_slave_pic(); return; } /* switch (address) */ } // new IRQ signal handling routines void bx_pic_c::lower_irq(unsigned irq_no) { #if BX_SUPPORT_APIC // forward this function call to the ioapic too if (DEV_ioapic_present() && (irq_no != 2)) { DEV_ioapic_set_irq_level(irq_no, 0); } #endif Bit8u mask = (1 << (irq_no & 7)); if ((irq_no <= 7) && (BX_PIC_THIS s.master_pic.IRQ_in & mask)) { BX_DEBUG(("IRQ line %d now low", (unsigned) irq_no)); BX_PIC_THIS s.master_pic.IRQ_in &= ~(mask); BX_PIC_THIS s.master_pic.irr &= ~(mask); } else if ((irq_no > 7) && (irq_no <= 15) && (BX_PIC_THIS s.slave_pic.IRQ_in & mask)) { BX_DEBUG(("IRQ line %d now low", (unsigned) irq_no)); BX_PIC_THIS s.slave_pic.IRQ_in &= ~(mask); BX_PIC_THIS s.slave_pic.irr &= ~(mask); } } void bx_pic_c::raise_irq(unsigned irq_no) { #if BX_SUPPORT_APIC // forward this function call to the ioapic too if (DEV_ioapic_present() && (irq_no != 2)) { DEV_ioapic_set_irq_level(irq_no, 1); } #endif Bit8u mask = (1 << (irq_no & 7)); if ((irq_no <= 7) && !(BX_PIC_THIS s.master_pic.IRQ_in & mask)) { BX_DEBUG(("IRQ line %d now high", (unsigned) irq_no)); BX_PIC_THIS s.master_pic.IRQ_in |= mask; BX_PIC_THIS s.master_pic.irr |= mask; service_master_pic(); } else if ((irq_no > 7) && (irq_no <= 15) && !(BX_PIC_THIS s.slave_pic.IRQ_in & mask)) { BX_DEBUG(("IRQ line %d now high", (unsigned) irq_no)); BX_PIC_THIS s.slave_pic.IRQ_in |= mask; BX_PIC_THIS s.slave_pic.irr |= mask; service_slave_pic(); } } void bx_pic_c::set_mode(bx_bool ma_sl, Bit8u mode) { if (ma_sl) { BX_PIC_THIS s.master_pic.edge_level = mode; } else { BX_PIC_THIS s.slave_pic.edge_level = mode; } } void bx_pic_c::clear_highest_interrupt(bx_pic_t *pic) { int irq; int lowest_priority; int highest_priority; /* clear highest current in service bit */ lowest_priority = pic->lowest_priority; highest_priority = lowest_priority + 1; if(highest_priority > 7) highest_priority = 0; irq = highest_priority; do { if (pic->isr & (1 << irq)) { pic->isr &= ~(1 << irq); break; /* Return mask of bit cleared. */ } irq ++; if(irq > 7) irq = 0; } while(irq != highest_priority); } 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; } isr = BX_PIC_THIS s.master_pic.isr; 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 */ max_irq = highest_priority; if (isr) { while ((isr & (1 << max_irq)) == 0) { max_irq++; if(max_irq > 7) max_irq = 0; } if (max_irq == highest_priority) return; /* Highest priority interrupt in-service, * no other priorities allowed */ if (max_irq > 7) BX_PANIC(("error in service_master_pic()")); } } /* now, see if there are any higher priority requests */ if ((unmasked_requests = (BX_PIC_THIS s.master_pic.irr & ~BX_PIC_THIS s.master_pic.imr))) { irq = highest_priority; do { /* for special mode, since we're looking at all IRQ's, skip if * current IRQ is already in-service */ if (! (BX_PIC_THIS s.master_pic.special_mask && ((isr >> irq) & 0x01))) { if (unmasked_requests & (1 << irq)) { BX_DEBUG(("signalling IRQ(%u)", (unsigned) irq)); BX_PIC_THIS s.master_pic.INT = 1; BX_PIC_THIS s.master_pic.irq = irq; BX_SET_INTR(1); return; } /* if (unmasked_requests & ... */ } irq ++; if(irq > 7) irq = 0; } while(irq != max_irq); /* do ... */ } /* if (unmasked_requests = ... */ } void bx_pic_c::service_slave_pic(void) { Bit8u unmasked_requests; int irq; Bit8u isr, max_irq; Bit8u highest_priority = BX_PIC_THIS s.slave_pic.lowest_priority + 1; if(highest_priority > 7) highest_priority = 0; if (BX_PIC_THIS s.slave_pic.INT) { /* last interrupt still not acknowleged */ return; } isr = BX_PIC_THIS s.slave_pic.isr; if (BX_PIC_THIS s.slave_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 */ max_irq = highest_priority; if (isr) { while ((isr & (1 << max_irq)) == 0) { max_irq++; if(max_irq > 7) max_irq = 0; } if (max_irq == highest_priority) return; /* Highest priority interrupt in-service, * no other priorities allowed */ if (max_irq > 7) BX_PANIC(("error in service_slave_pic()")); } } /* now, see if there are any higher priority requests */ if ((unmasked_requests = (BX_PIC_THIS s.slave_pic.irr & ~BX_PIC_THIS s.slave_pic.imr))) { irq = highest_priority; do { /* for special mode, since we're looking at all IRQ's, skip if * current IRQ is already in-service */ if (! (BX_PIC_THIS s.slave_pic.special_mask && ((isr >> irq) & 0x01))) { if (unmasked_requests & (1 << irq)) { BX_DEBUG(("slave: signalling IRQ(%u)", (unsigned) 8 + irq)); BX_PIC_THIS s.slave_pic.INT = 1; BX_PIC_THIS s.slave_pic.irq = irq; BX_PIC_THIS raise_irq(2); /* request IRQ 2 on master pic */ return; } /* if (unmasked_requests & ... */ } irq ++; if(irq > 7) irq = 0; } while(irq != max_irq); /* do ... */ } /* if (unmasked_requests = ... */ } /* CPU handshakes with PIC after acknowledging interrupt */ Bit8u bx_pic_c::IAC(void) { Bit8u vector; Bit8u irq; BX_SET_INTR(0); BX_PIC_THIS s.master_pic.INT = 0; // Check for spurious interrupt if (BX_PIC_THIS s.master_pic.irr == 0) { return (BX_PIC_THIS s.master_pic.interrupt_offset + 7); } // In level sensitive mode don't clear the irr bit. if (!(BX_PIC_THIS s.master_pic.edge_level & (1 << BX_PIC_THIS s.master_pic.irq))) BX_PIC_THIS s.master_pic.irr &= ~(1 << BX_PIC_THIS s.master_pic.irq); // In autoeoi mode don't set the isr bit. if (!BX_PIC_THIS s.master_pic.auto_eoi) BX_PIC_THIS s.master_pic.isr |= (1 << BX_PIC_THIS s.master_pic.irq); else if (BX_PIC_THIS s.master_pic.rotate_on_autoeoi) BX_PIC_THIS s.master_pic.lowest_priority = BX_PIC_THIS s.master_pic.irq; if (BX_PIC_THIS s.master_pic.irq != 2) { irq = BX_PIC_THIS s.master_pic.irq; vector = irq + BX_PIC_THIS s.master_pic.interrupt_offset; } else { /* IRQ2 = slave pic IRQ8..15 */ BX_PIC_THIS s.slave_pic.INT = 0; BX_PIC_THIS s.master_pic.IRQ_in &= ~(1 << 2); // Check for spurious interrupt if (BX_PIC_THIS s.slave_pic.irr == 0) { return (BX_PIC_THIS s.slave_pic.interrupt_offset + 7); } irq = BX_PIC_THIS s.slave_pic.irq; vector = irq + BX_PIC_THIS s.slave_pic.interrupt_offset; // In level sensitive mode don't clear the irr bit. if (!(BX_PIC_THIS s.slave_pic.edge_level & (1 << BX_PIC_THIS s.slave_pic.irq))) BX_PIC_THIS s.slave_pic.irr &= ~(1 << BX_PIC_THIS s.slave_pic.irq); // In autoeoi mode don't set the isr bit. if (!BX_PIC_THIS s.slave_pic.auto_eoi) BX_PIC_THIS s.slave_pic.isr |= (1 << BX_PIC_THIS s.slave_pic.irq); else if (BX_PIC_THIS s.slave_pic.rotate_on_autoeoi) BX_PIC_THIS s.slave_pic.lowest_priority = BX_PIC_THIS s.slave_pic.irq; service_slave_pic(); irq += 8; // for debug printing purposes } service_master_pic(); BX_DBG_IAC_REPORT(vector, irq); return(vector); } #if BX_DEBUGGER void bx_pic_c::debug_dump(int argc, char **argv) { dbg_printf("i8259A PIC\n\n"); dbg_printf("master IMR = %02x\n", BX_PIC_THIS s.master_pic.imr); dbg_printf("master ISR = %02x\n", BX_PIC_THIS s.master_pic.isr); dbg_printf("master IRR = %02x\n", BX_PIC_THIS s.master_pic.irr); dbg_printf("master IRQ = %02x\n", BX_PIC_THIS s.master_pic.irq); dbg_printf("slave IMR = %02x\n", BX_PIC_THIS s.slave_pic.imr); dbg_printf("slave ISR = %02x\n", BX_PIC_THIS s.slave_pic.isr); dbg_printf("slave IRR = %02x\n", BX_PIC_THIS s.slave_pic.irr); dbg_printf("slave IRQ = %02x\n", BX_PIC_THIS s.slave_pic.irq); if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif bochs-2.6/iodev/pci_ide.h0000644000175000017500000000522312020641505015205 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pci_ide.h 10424 2011-06-25 12:43:27Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_PCIIDE_H #define BX_IODEV_PCIIDE_H #if BX_USE_PIDE_SMF # define BX_PIDE_SMF static # define BX_PIDE_THIS thePciIdeController-> # define BX_PIDE_THIS_PTR thePciIdeController #else # define BX_PIDE_SMF # define BX_PIDE_THIS this-> # define BX_PIDE_THIS_PTR this #endif class bx_pci_ide_c : public bx_pci_ide_stub_c { public: bx_pci_ide_c(); virtual ~bx_pci_ide_c(); virtual void init(void); virtual void reset(unsigned type); virtual bx_bool bmdma_present(void); virtual void bmdma_set_irq(Bit8u channel); virtual void register_state(void); virtual void after_restore_state(void); static Bit64s param_save_handler(void *devptr, bx_param_c *param); static void param_restore_handler(void *devptr, bx_param_c *param, Bit64s val); #if !BX_USE_PIDE_SMF Bit64s param_save(bx_param_c *param); void param_restore(bx_param_c *param, Bit64s val); #endif virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); static void timer_handler(void *); BX_PIDE_SMF void timer(void); private: struct { struct { bx_bool cmd_ssbm; bx_bool cmd_rwcon; Bit8u status; Bit32u dtpr; Bit32u prd_current; int timer_index; Bit8u *buffer; Bit8u *buffer_top; Bit8u *buffer_idx; } bmdma[2]; } s; static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_PIDE_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/biosdev.cc0000644000175000017500000001721212020641505015403 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: biosdev.cc 11058 2012-02-23 17:16:35Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Here are the virtual ports use to display messages from the bioses : // // 0x0400 : rombios Panic port with line number // 0x0401 : rombios Panic port with message, panic flag or line number // 0x0402 : rombios Info port with message // 0x0403 : rombios Debug port with message // // 0x0500 : vgabios Info port with message // 0x0501 : vgabios Panic port with line number // 0x0502 : vgabios Panic port with message, panic flag or line number // 0x0503 : vgabios Debug port with message // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "biosdev.h" bx_biosdev_c *theBiosDevice = NULL; logfunctions *bioslog; logfunctions *vgabioslog; int libbiosdev_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theBiosDevice = new bx_biosdev_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theBiosDevice, BX_PLUGIN_BIOSDEV); return(0); // Success } void libbiosdev_LTX_plugin_fini(void) { delete theBiosDevice; } bx_biosdev_c::bx_biosdev_c(void) { memset(&s, 0, sizeof(s)); bioslog = new logfunctions(); bioslog->put("BIOS"); vgabioslog = new logfunctions(); vgabioslog->put("vgabios", "VBIOS"); } bx_biosdev_c::~bx_biosdev_c(void) { bioslog->ldebug("Exit"); if (bioslog != NULL) { delete bioslog; bioslog = NULL; } if (vgabioslog != NULL) { delete vgabioslog; vgabioslog = NULL; } } void bx_biosdev_c::init(void) { DEV_register_iowrite_handler(this, write_handler, 0x0400, "Bios Panic Port 1", 3); DEV_register_iowrite_handler(this, write_handler, 0x0401, "Bios Panic Port 2", 3); DEV_register_iowrite_handler(this, write_handler, 0x0402, "Bios Info Port", 1); DEV_register_iowrite_handler(this, write_handler, 0x0403, "Bios Debug Port", 1); DEV_register_iowrite_handler(this, write_handler, 0x0500, "VGABios Info Port", 1); DEV_register_iowrite_handler(this, write_handler, 0x0501, "VGABios Panic Port 1", 3); DEV_register_iowrite_handler(this, write_handler, 0x0502, "VGABios Panic Port 2", 3); DEV_register_iowrite_handler(this, write_handler, 0x0503, "VGABios Debug Port", 1); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_biosdev_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_BIOS_SMF bx_biosdev_c *class_ptr = (bx_biosdev_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_biosdev_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_BIOS_SMF UNUSED(io_len); switch (address) { // 0x400-0x401 are used as panic ports for the rombios case 0x0401: if (value==0) { // The next message sent to the info port will cause a panic BX_BIOS_THIS s.bios_panic_flag = 1; break; } else if (BX_BIOS_THIS s.bios_message_i > 0) { // if there are bits of message in the buffer, print them as the // panic message. Otherwise fall into the next case. if (BX_BIOS_THIS s.bios_message_i >= BX_BIOS_MESSAGE_SIZE) BX_BIOS_THIS s.bios_message_i = BX_BIOS_MESSAGE_SIZE-1; BX_BIOS_THIS s.bios_message[ BX_BIOS_THIS s.bios_message_i] = 0; BX_BIOS_THIS s.bios_message_i = 0; bioslog->panic("%s", BX_BIOS_THIS s.bios_message); break; } case 0x0400: if (value > 0) { bioslog->panic("BIOS panic at rombios.c, line %d", value); } break; // 0x0402 is used as the info port for the rombios // 0x0403 is used as the debug port for the rombios case 0x0402: case 0x0403: BX_BIOS_THIS s.bios_message[BX_BIOS_THIS s.bios_message_i] = (Bit8u) value; BX_BIOS_THIS s.bios_message_i ++; if (BX_BIOS_THIS s.bios_message_i >= BX_BIOS_MESSAGE_SIZE) { BX_BIOS_THIS s.bios_message[ BX_BIOS_MESSAGE_SIZE - 1] = 0; BX_BIOS_THIS s.bios_message_i = 0; if (address==0x403) bioslog->ldebug("%s", BX_BIOS_THIS s.bios_message); else bioslog->info("%s", BX_BIOS_THIS s.bios_message); } else if ((value & 0xff) == '\n') { BX_BIOS_THIS s.bios_message[ BX_BIOS_THIS s.bios_message_i - 1 ] = 0; BX_BIOS_THIS s.bios_message_i = 0; if (BX_BIOS_THIS s.bios_panic_flag==1) bioslog->panic("%s", BX_BIOS_THIS s.bios_message); else if (address==0x403) bioslog->ldebug("%s", BX_BIOS_THIS s.bios_message); else bioslog->info("%s", BX_BIOS_THIS s.bios_message); BX_BIOS_THIS s.bios_panic_flag = 0; } break; // 0x501-0x502 are used as panic ports for the vgabios case 0x0502: if (value==0) { BX_BIOS_THIS s.vgabios_panic_flag = 1; break; } else if (BX_BIOS_THIS s.vgabios_message_i > 0) { // if there are bits of message in the buffer, print them as the // panic message. Otherwise fall into the next case. if (BX_BIOS_THIS s.vgabios_message_i >= BX_BIOS_MESSAGE_SIZE) BX_BIOS_THIS s.vgabios_message_i = BX_BIOS_MESSAGE_SIZE-1; BX_BIOS_THIS s.vgabios_message[ BX_BIOS_THIS s.vgabios_message_i] = 0; BX_BIOS_THIS s.vgabios_message_i = 0; vgabioslog->panic("%s", BX_BIOS_THIS s.vgabios_message); break; } case 0x0501: if (value > 0) { vgabioslog->panic("VGABIOS panic at vgabios.c, line %d", value); } break; // 0x0500 is used as the message port for the vgabios case 0x0500: case 0x0503: BX_BIOS_THIS s.vgabios_message[BX_BIOS_THIS s.vgabios_message_i] = (Bit8u) value; BX_BIOS_THIS s.vgabios_message_i ++; if (BX_BIOS_THIS s.vgabios_message_i >= BX_BIOS_MESSAGE_SIZE) { BX_BIOS_THIS s.vgabios_message[ BX_BIOS_MESSAGE_SIZE - 1] = 0; BX_BIOS_THIS s.vgabios_message_i = 0; if (address==0x503) vgabioslog->ldebug("%s", BX_BIOS_THIS s.vgabios_message); else vgabioslog->info("%s", BX_BIOS_THIS s.vgabios_message); } else if ((value & 0xff) == '\n') { BX_BIOS_THIS s.vgabios_message[ BX_BIOS_THIS s.vgabios_message_i - 1 ] = 0; BX_BIOS_THIS s.vgabios_message_i = 0; if (BX_BIOS_THIS s.vgabios_panic_flag==1) vgabioslog->panic("%s", BX_BIOS_THIS s.vgabios_message); else if (address==0x503) vgabioslog->ldebug("%s", BX_BIOS_THIS s.vgabios_message); else vgabioslog->info("%s", BX_BIOS_THIS s.vgabios_message); BX_BIOS_THIS s.vgabios_panic_flag = 0; } break; default: break; } } bochs-2.6/iodev/pci_ide.cc0000644000175000017500000003663312020641505015354 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pci_ide.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // i440FX Support - PCI IDE controller (PIIX3) // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI #include "pci.h" #include "pci_ide.h" #define LOG_THIS thePciIdeController-> bx_pci_ide_c *thePciIdeController = NULL; const Bit8u bmdma_iomask[16] = {1, 0, 1, 0, 4, 0, 0, 0, 1, 0, 1, 0, 4, 0, 0, 0}; int libpci_ide_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { thePciIdeController = new bx_pci_ide_c(); bx_devices.pluginPciIdeController = thePciIdeController; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePciIdeController, BX_PLUGIN_PCI_IDE); return(0); // Success } void libpci_ide_LTX_plugin_fini(void) { delete thePciIdeController; } bx_pci_ide_c::bx_pci_ide_c() { put("pci_ide", "PIDE"); s.bmdma[0].timer_index = BX_NULL_TIMER_HANDLE; s.bmdma[1].timer_index = BX_NULL_TIMER_HANDLE; s.bmdma[0].buffer = NULL; s.bmdma[1].buffer = NULL; } bx_pci_ide_c::~bx_pci_ide_c() { if (s.bmdma[0].buffer != NULL) { delete [] s.bmdma[0].buffer; } if (s.bmdma[1].buffer != NULL) { delete [] s.bmdma[1].buffer; } SIM->get_bochs_root()->remove("pci_ide"); BX_DEBUG(("Exit")); } void bx_pci_ide_c::init(void) { unsigned i; Bit8u devfunc = BX_PCI_DEVICE(1,1); DEV_register_pci_handlers(this, &devfunc, BX_PLUGIN_PCI_IDE, "PIIX3 PCI IDE controller"); // register BM-DMA timer for (i=0; i<2; i++) { if (BX_PIDE_THIS s.bmdma[i].timer_index == BX_NULL_TIMER_HANDLE) { BX_PIDE_THIS s.bmdma[i].timer_index = DEV_register_timer(this, timer_handler, 1000, 0,0, "PIIX3 BM-DMA timer"); } } BX_PIDE_THIS s.bmdma[0].buffer = new Bit8u[0x20000]; BX_PIDE_THIS s.bmdma[1].buffer = new Bit8u[0x20000]; for (i=0; i<256; i++) BX_PIDE_THIS pci_conf[i] = 0x0; // readonly registers BX_PIDE_THIS pci_conf[0x00] = 0x86; BX_PIDE_THIS pci_conf[0x01] = 0x80; BX_PIDE_THIS pci_conf[0x02] = 0x10; BX_PIDE_THIS pci_conf[0x03] = 0x70; BX_PIDE_THIS pci_conf[0x09] = 0x80; BX_PIDE_THIS pci_conf[0x0a] = 0x01; BX_PIDE_THIS pci_conf[0x0b] = 0x01; BX_PIDE_THIS pci_conf[0x0e] = 0x00; BX_PIDE_THIS pci_conf[0x20] = 0x01; BX_PIDE_THIS pci_base_address[4] = 0; } void bx_pci_ide_c::reset(unsigned type) { BX_PIDE_THIS pci_conf[0x04] = 0x01; BX_PIDE_THIS pci_conf[0x06] = 0x80; BX_PIDE_THIS pci_conf[0x07] = 0x02; if (SIM->get_param_bool(BXPN_ATA0_ENABLED)->get()) { BX_PIDE_THIS pci_conf[0x40] = 0x00; BX_PIDE_THIS pci_conf[0x41] = 0x80; } if (SIM->get_param_bool(BXPN_ATA1_ENABLED)->get()) { BX_PIDE_THIS pci_conf[0x42] = 0x00; BX_PIDE_THIS pci_conf[0x43] = 0x80; } BX_PIDE_THIS pci_conf[0x44] = 0x00; for (unsigned i=0; i<2; i++) { BX_PIDE_THIS s.bmdma[i].cmd_ssbm = 0; BX_PIDE_THIS s.bmdma[i].cmd_rwcon = 0; BX_PIDE_THIS s.bmdma[i].status = 0; BX_PIDE_THIS s.bmdma[i].dtpr = 0; BX_PIDE_THIS s.bmdma[i].prd_current = 0; BX_PIDE_THIS s.bmdma[i].buffer_top = BX_PIDE_THIS s.bmdma[i].buffer; BX_PIDE_THIS s.bmdma[i].buffer_idx = BX_PIDE_THIS s.bmdma[i].buffer; } } // save/restore code begin void bx_pci_ide_c::register_state(void) { char name[6]; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "pci_ide", "PCI IDE Controller State"); register_pci_state(list); new bx_shadow_data_c(list, "buffer0", BX_PIDE_THIS s.bmdma[0].buffer, 0x20000); new bx_shadow_data_c(list, "buffer1", BX_PIDE_THIS s.bmdma[1].buffer, 0x20000); for (unsigned i=0; i<2; i++) { sprintf(name, "%d", i); bx_list_c *ctrl = new bx_list_c(list, name); BXRS_PARAM_BOOL(ctrl, cmd_ssbm, BX_PIDE_THIS s.bmdma[i].cmd_ssbm); BXRS_PARAM_BOOL(ctrl, cmd_rwcon, BX_PIDE_THIS s.bmdma[i].cmd_rwcon); BXRS_HEX_PARAM_FIELD(ctrl, status, BX_PIDE_THIS s.bmdma[i].status); BXRS_HEX_PARAM_FIELD(ctrl, dtpr, BX_PIDE_THIS s.bmdma[i].dtpr); BXRS_HEX_PARAM_FIELD(ctrl, prd_current, BX_PIDE_THIS s.bmdma[i].prd_current); BXRS_PARAM_SPECIAL32(ctrl, buffer_top, BX_PIDE_THIS param_save_handler, BX_PIDE_THIS param_restore_handler); BXRS_PARAM_SPECIAL32(ctrl, buffer_idx, BX_PIDE_THIS param_save_handler, BX_PIDE_THIS param_restore_handler); } } void bx_pci_ide_c::after_restore_state(void) { if (DEV_pci_set_base_io(BX_PIDE_THIS_PTR, read_handler, write_handler, &BX_PIDE_THIS pci_base_address[4], &BX_PIDE_THIS pci_conf[0x20], 16, &bmdma_iomask[0], "PIIX3 PCI IDE controller")) { BX_INFO(("new BM-DMA address: 0x%04x", BX_PIDE_THIS pci_base_address[4])); } } Bit64s bx_pci_ide_c::param_save_handler(void *devptr, bx_param_c *param) { #if !BX_USE_PIDE_SMF bx_pci_ide_c *class_ptr = (bx_pci_ide_c *) devptr; return class_ptr->param_save(param, val); } Bit64s bx_pci_ide_c::param_save(bx_param_c *param) { #else UNUSED(devptr); #endif // !BX_USE_PIDE_SMF int chan = atoi(param->get_parent()->get_name()); Bit64s val = 0; if (!strcmp(param->get_name(), "buffer_top")) { val = (Bit32u)(BX_PIDE_THIS s.bmdma[chan].buffer_top - BX_PIDE_THIS s.bmdma[chan].buffer); } else if (!strcmp(param->get_name(), "buffer_idx")) { val = (Bit32u)(BX_PIDE_THIS s.bmdma[chan].buffer_idx - BX_PIDE_THIS s.bmdma[chan].buffer); } return val; } void bx_pci_ide_c::param_restore_handler(void *devptr, bx_param_c *param, Bit64s val) { #if !BX_USE_PIDE_SMF bx_pci_ide_c *class_ptr = (bx_pci_ide_c *) devptr; class_ptr->param_restore(param, val); } void bx_pci_ide_c::param_restore(bx_param_c *param, Bit64s val) { #else UNUSED(devptr); #endif // !BX_USE_PIDE_SMF int chan = atoi(param->get_parent()->get_name()); if (!strcmp(param->get_name(), "buffer_top")) { BX_PIDE_THIS s.bmdma[chan].buffer_top = BX_PIDE_THIS s.bmdma[chan].buffer + val; } else if (!strcmp(param->get_name(), "buffer_idx")) { BX_PIDE_THIS s.bmdma[chan].buffer_idx = BX_PIDE_THIS s.bmdma[chan].buffer + val; } } // save/restore code end bx_bool bx_pci_ide_c::bmdma_present(void) { return (BX_PIDE_THIS pci_base_address[4] > 0); } void bx_pci_ide_c::bmdma_set_irq(Bit8u channel) { if (channel < 2) { BX_PIDE_THIS s.bmdma[channel].status |= 0x04; } } void bx_pci_ide_c::timer_handler(void *this_ptr) { bx_pci_ide_c *class_ptr = (bx_pci_ide_c *) this_ptr; class_ptr->timer(); } void bx_pci_ide_c::timer() { int timer_id, count; Bit8u channel; Bit32u size, sector_size; struct { Bit32u addr; Bit32u size; } prd; timer_id = bx_pc_system.triggeredTimerID(); if (timer_id == BX_PIDE_THIS s.bmdma[0].timer_index) { channel = 0; } else { channel = 1; } if (((BX_PIDE_THIS s.bmdma[channel].status & 0x01) == 0) || (BX_PIDE_THIS s.bmdma[channel].prd_current == 0)) { return; } DEV_MEM_READ_PHYSICAL(BX_PIDE_THIS s.bmdma[channel].prd_current, 4, (Bit8u *)&prd.addr); DEV_MEM_READ_PHYSICAL(BX_PIDE_THIS s.bmdma[channel].prd_current+4, 4, (Bit8u *)&prd.size); size = prd.size & 0xfffe; if (size == 0) { size = 0x10000; } if (BX_PIDE_THIS s.bmdma[channel].cmd_rwcon) { BX_DEBUG(("READ DMA to addr=0x%08x, size=0x%08x", prd.addr, size)); count = size - (BX_PIDE_THIS s.bmdma[channel].buffer_top - BX_PIDE_THIS s.bmdma[channel].buffer_idx); while (count > 0) { sector_size = count; if (DEV_hd_bmdma_read_sector(channel, BX_PIDE_THIS s.bmdma[channel].buffer_top, §or_size)) { BX_PIDE_THIS s.bmdma[channel].buffer_top += sector_size; count -= sector_size; } else { break; } }; if (count > 0) { BX_PIDE_THIS s.bmdma[channel].status &= ~0x01; BX_PIDE_THIS s.bmdma[channel].status |= 0x06; return; } else { DEV_MEM_WRITE_PHYSICAL_DMA(prd.addr, size, BX_PIDE_THIS s.bmdma[channel].buffer_idx); BX_PIDE_THIS s.bmdma[channel].buffer_idx += size; } } else { BX_DEBUG(("WRITE DMA from addr=0x%08x, size=0x%08x", prd.addr, size)); DEV_MEM_READ_PHYSICAL_DMA(prd.addr, size, BX_PIDE_THIS s.bmdma[channel].buffer_top); BX_PIDE_THIS s.bmdma[channel].buffer_top += size; count = BX_PIDE_THIS s.bmdma[channel].buffer_top - BX_PIDE_THIS s.bmdma[channel].buffer_idx; while (count > 511) { if (DEV_hd_bmdma_write_sector(channel, BX_PIDE_THIS s.bmdma[channel].buffer_idx)) { BX_PIDE_THIS s.bmdma[channel].buffer_idx += 512; count -= 512; } else { break; } }; if (count > 511) { BX_PIDE_THIS s.bmdma[channel].status &= ~0x01; BX_PIDE_THIS s.bmdma[channel].status |= 0x06; return; } } if (prd.size & 0x80000000) { BX_PIDE_THIS s.bmdma[channel].status &= ~0x01; BX_PIDE_THIS s.bmdma[channel].status |= 0x04; BX_PIDE_THIS s.bmdma[channel].prd_current = 0; DEV_hd_bmdma_complete(channel); } else { // To avoid buffer overflow reset buffer pointers and copy data if necessary count = BX_PIDE_THIS s.bmdma[channel].buffer_top - BX_PIDE_THIS s.bmdma[channel].buffer_idx; if (count > 0) { memcpy(BX_PIDE_THIS s.bmdma[channel].buffer, BX_PIDE_THIS s.bmdma[channel].buffer_idx, count); } BX_PIDE_THIS s.bmdma[channel].buffer_top = BX_PIDE_THIS s.bmdma[channel].buffer + count; BX_PIDE_THIS s.bmdma[channel].buffer_idx = BX_PIDE_THIS s.bmdma[channel].buffer; // Prepare for next PRD BX_PIDE_THIS s.bmdma[channel].prd_current += 8; DEV_MEM_READ_PHYSICAL(BX_PIDE_THIS s.bmdma[channel].prd_current, 4, (Bit8u *)&prd.addr); DEV_MEM_READ_PHYSICAL(BX_PIDE_THIS s.bmdma[channel].prd_current+4, 4, (Bit8u *)&prd.size); size = prd.size & 0xfffe; if (size == 0) { size = 0x10000; } bx_pc_system.activate_timer(BX_PIDE_THIS s.bmdma[channel].timer_index, (size >> 4) | 0x10, 0); } } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_pci_ide_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_PIDE_SMF bx_pci_ide_c *class_ptr = (bx_pci_ide_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_pci_ide_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PIDE_SMF Bit8u offset, channel; Bit32u value = 0xffffffff; offset = address - BX_PIDE_THIS pci_base_address[4]; channel = (offset >> 3); offset &= 0x07; switch (offset) { case 0x00: value = BX_PIDE_THIS s.bmdma[channel].cmd_ssbm | (BX_PIDE_THIS s.bmdma[channel].cmd_rwcon << 3); BX_DEBUG(("BM-DMA read command register, channel %d, value = 0x%02x", channel, value)); break; case 0x02: value = BX_PIDE_THIS s.bmdma[channel].status; BX_DEBUG(("BM-DMA read status register, channel %d, value = 0x%02x", channel, value)); break; case 0x04: value = BX_PIDE_THIS s.bmdma[channel].dtpr; BX_DEBUG(("BM-DMA read DTP register, channel %d, value = 0x%04x", channel, value)); break; } return value; } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_pci_ide_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_PIDE_SMF bx_pci_ide_c *class_ptr = (bx_pci_ide_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_pci_ide_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PIDE_SMF Bit8u offset, channel; offset = address - BX_PIDE_THIS pci_base_address[4]; channel = (offset >> 3); offset &= 0x07; switch (offset) { case 0x00: BX_DEBUG(("BM-DMA write command register, channel %d, value = 0x%02x", channel, value)); BX_PIDE_THIS s.bmdma[channel].cmd_rwcon = (value >> 3) & 1; if ((value & 0x01) && !BX_PIDE_THIS s.bmdma[channel].cmd_ssbm) { BX_PIDE_THIS s.bmdma[channel].cmd_ssbm = 1; BX_PIDE_THIS s.bmdma[channel].status |= 0x01; BX_PIDE_THIS s.bmdma[channel].prd_current = BX_PIDE_THIS s.bmdma[channel].dtpr; BX_PIDE_THIS s.bmdma[channel].buffer_top = BX_PIDE_THIS s.bmdma[channel].buffer; BX_PIDE_THIS s.bmdma[channel].buffer_idx = BX_PIDE_THIS s.bmdma[channel].buffer; bx_pc_system.activate_timer(BX_PIDE_THIS s.bmdma[channel].timer_index, 1000, 0); } else if (!(value & 0x01) && BX_PIDE_THIS s.bmdma[channel].cmd_ssbm) { BX_PIDE_THIS s.bmdma[channel].cmd_ssbm = 0; BX_PIDE_THIS s.bmdma[channel].status &= ~0x01; } break; case 0x02: BX_PIDE_THIS s.bmdma[channel].status = (value & 0x60) | (BX_PIDE_THIS s.bmdma[channel].status & 0x01) | (BX_PIDE_THIS s.bmdma[channel].status & (~value & 0x06)); BX_DEBUG(("BM-DMA write status register, channel %d, value = 0x%02x", channel, value)); break; case 0x04: BX_PIDE_THIS s.bmdma[channel].dtpr = value & 0xfffffffc; BX_DEBUG(("BM-DMA write DTP register, channel %d, value = 0x%04x", channel, value)); break; } } // pci configuration space read callback handler Bit32u bx_pci_ide_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x10) && (address < 0x20)) || ((address > 0x23) && (address < 0x40))) return; for (unsigned i=0; i> (i*8)) & 0xFF; switch (address+i) { case 0x05: case 0x06: break; case 0x04: BX_PIDE_THIS pci_conf[address+i] = value8 & 0x05; break; case 0x20: value8 = (value8 & 0xfc) | 0x01; case 0x21: case 0x22: case 0x23: bmdma_change |= (value8 != oldval); default: BX_PIDE_THIS pci_conf[address+i] = value8; BX_DEBUG(("PIIX3 PCI IDE write register 0x%02x value 0x%02x", address+i, value8)); } } if (bmdma_change) { if (DEV_pci_set_base_io(BX_PIDE_THIS_PTR, read_handler, write_handler, &BX_PIDE_THIS pci_base_address[4], &BX_PIDE_THIS pci_conf[0x20], 16, &bmdma_iomask[0], "PIIX3 PCI IDE controller")) { BX_INFO(("new BM-DMA address: 0x%04x", BX_PIDE_THIS pci_base_address[4])); } } } #endif /* BX_SUPPORT_PCI */ bochs-2.6/iodev/scancodes.h0000644000175000017500000000236712020641505015561 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: scancodes.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_SCANCODES_H #define BX_SCANCODES_H // Translation table of the 8042 extern unsigned char translation8042[256]; typedef struct { const char *make; const char *brek; } scancode; // Scancodes table extern scancode scancodes[BX_KEY_NBKEYS][3]; #endif bochs-2.6/iodev/unmapped.h0000644000175000017500000000344712020641505015430 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: unmapped.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_UNMAPPED_H #define BX_IODEV_UNMAPPED_H #if BX_USE_UM_SMF # define BX_UM_SMF static # define BX_UM_THIS theUnmappedDevice-> #else # define BX_UM_SMF # define BX_UM_THIS this-> #endif class bx_unmapped_c : public bx_devmodel_c { public: bx_unmapped_c(); virtual ~bx_unmapped_c(); virtual void init(void); virtual void reset(unsigned type) {} private: static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_UM_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif struct { Bit8u port80; Bit8u port8e; Bit8u shutdown; bx_bool port_e9_hack; } s; // state information }; #endif bochs-2.6/iodev/iodebug.cc0000644000175000017500000002400112020641505015360 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: iodebug.cc 11146 2012-04-19 18:03:13Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_IODEBUG #include "cpu/cpu.h" #include "iodebug.h" #define BX_IODEBUG_THIS this-> bx_iodebug_c *theIODebugDevice = NULL; int libiodebug_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theIODebugDevice = new bx_iodebug_c(); bx_devices.pluginIODebug = theIODebugDevice; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theIODebugDevice, BX_PLUGIN_IODEBUG); return(0); // Success } void libiodebug_LTX_plugin_fini(void) { bx_devices.pluginIODebug = &bx_devices.stubIODebug; delete theIODebugDevice; } struct bx_iodebug_s_type { bx_bool enabled; unsigned register_select; Bit32u registers[2]; bx_phy_address monitored_mem_areas_start[BX_IODEBUG_MAX_AREAS]; bx_phy_address monitored_mem_areas_end[BX_IODEBUG_MAX_AREAS]; } bx_iodebug_s; bx_iodebug_c::bx_iodebug_c() { put("iodebug", "IODBG"); } void bx_iodebug_c::init(void) { DEV_register_ioread_handler(this, read_handler, 0x8A00,"BOCHS IODEBUG", 2); DEV_register_iowrite_handler(this, write_handler, 0x8A00,"BOCHS IODEBUG", 2); DEV_register_iowrite_handler(this, write_handler, 0x8A01,"BOCHS IODEBUG", 2); bx_iodebug_s.enabled = 0; bx_iodebug_s.register_select = 0; for(int i=0;iread(addr, io_len); } Bit32u bx_iodebug_c::read(Bit32u addr, unsigned io_len) { if (bx_iodebug_s.enabled) return 0x8A00; return(0); } void bx_iodebug_c::write_handler(void *this_ptr, Bit32u addr, Bit32u dvalue, unsigned io_len) { bx_iodebug_c *bx_iodebug_ptr = (bx_iodebug_c *) this_ptr; bx_iodebug_ptr->write(addr, dvalue, io_len); } void bx_iodebug_c::write(Bit32u addr, Bit32u dvalue, unsigned io_len) { //fprintf(stderr, "IODEBUG addr: %4x\tdvalue: %8x\tio_len: %8x\n", (unsigned) addr, (unsigned) dvalue, io_len); if (addr == 0x8A01) { bx_iodebug_s.registers[bx_iodebug_s.register_select] = (bx_iodebug_s.registers[bx_iodebug_s.register_select] << 16) + (dvalue & 0xFFFF); } if (addr != 0x8A00) return; if (!bx_iodebug_s.enabled) { if(dvalue == 0x8A00) { bx_iodebug_s.enabled = 1; // fprintf(stderr, "IODEBUG enabled\n"); bx_iodebug_s.registers[0] = 0; bx_iodebug_s.registers[1] = 0; } return; } switch(dvalue) { case 0x8A01: bx_iodebug_s.register_select = 0; // fprintf(stderr, "IODEBUG register 0 selected\n"); break; case 0x8A02: bx_iodebug_s.register_select = 1; // fprintf(stderr, "IODEBUG register 1 selected\n"); break; case 0x8A80: bx_iodebug_s.register_select = 0; bx_iodebug_c::add_range(bx_iodebug_s.registers[0], bx_iodebug_s.registers[1]); bx_iodebug_s.registers[0] = 0; bx_iodebug_s.registers[1] = 0; break; #if BX_DEBUGGER case 0x8AE0: fprintf(stderr, "request return to dbg prompt received, 0x8AE0 command (iodebug)\n"); bx_guard.interrupt_requested=1; break; case 0x8AE2: fprintf(stderr, "request made by the guest os to disable tracing, iodebug port 0x8A00->0x8AE2\n"); BX_CPU(dbg_cpu)->trace = 0; break; case 0x8AE3: fprintf(stderr, "request made by the guest os to enable tracing, iodebug port 0x8A00->0x8AE3\n"); BX_CPU(dbg_cpu)->trace = 1; break; case 0x8AE4: fprintf(stderr, "request made by the guest os to disable register tracing, iodebug port 0x8A00->0x8AE4\n"); BX_CPU(dbg_cpu)->trace_reg = 0; break; case 0x8AE5: fprintf(stderr, "request made by the guest os to enable register tracing, iodebug port 0x8A00->0x8AE5\n"); BX_CPU(dbg_cpu)->trace_reg = 1; break; #endif case 0x8AFF: bx_iodebug_s.enabled = 0; // fprintf(stderr, "IODEBUG device deactivated\n"); // break; // default: // fprintf(stderr,"IODEBUG unsupported register code\n"); } } // Static function void bx_iodebug_c::mem_write(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) { if(! bx_iodebug_s.enabled) return; unsigned area = bx_iodebug_c::range_test(addr, len); // Device is enabled, testing address ranges if(area) { area--; #if BX_DEBUGGER if (cpu != NULL) { fprintf(stdout, "IODEBUG CPU %d @ eip: " FMT_ADDRX " write at monitored memory location " FMT_PHY_ADDRX "\n", cpu->bx_cpuid, cpu->get_instruction_pointer(), addr); } else { fprintf(stdout, "IODEBUG write at monitored memory location " FMT_PHY_ADDRX "\n", addr); } bx_guard.interrupt_requested=1; #else fprintf(stderr, "IODEBUG write to monitored memory area: %2i\t", area); if (cpu != NULL) fprintf(stderr, "by EIP:\t\t" FMT_ADDRX "\n\t", cpu->get_instruction_pointer()); else fprintf(stderr, "(device origin)\t"); fprintf(stderr, "range start: \t\t" FMT_PHY_ADDRX "\trange end:\t" FMT_PHY_ADDRX "\n\taddress accessed:\t%08X\tdata written:\t", bx_iodebug_s.monitored_mem_areas_start[area], bx_iodebug_s.monitored_mem_areas_end[area], (unsigned) addr); switch(len) { case 1: { Bit8u data8 = * ((Bit8u *) data); fprintf(stderr,"%02X\n", (unsigned) data8); break; } case 2: { Bit16u data16 = * ((Bit16u *) data); fprintf(stderr,"%04X\n", (unsigned) data16); break; } case 4: { Bit32u data32 = * ((Bit32u *) data); fprintf(stderr,"%08X\n", (unsigned) data32); break; } case 8: { Bit64u data64 = * ((Bit64u *) data); fprintf(stderr,"%08X%08x\n", (unsigned) (data64 >> 32), (unsigned) (data64 & 0xffffffff)); break; } default: fprintf(stderr, "unsupported write size\n"); } #endif } } void bx_iodebug_c::mem_read(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) { if(! bx_iodebug_s.enabled) return; unsigned area = bx_iodebug_c::range_test(addr, len); // Device is enabled, testing address ranges if(area) { area--; #if BX_DEBUGGER if (cpu != NULL) { fprintf(stdout, "IODEBUG CPU %d @ eip: " FMT_ADDRX " read at monitored memory location " FMT_PHY_ADDRX "\n", cpu->bx_cpuid, cpu->get_instruction_pointer(), addr); } else { fprintf(stdout, "IODEBUG read at monitored memory location " FMT_PHY_ADDRX "\n", addr); } bx_guard.interrupt_requested=1; #else fprintf(stderr, "IODEBUG read at monitored memory area: %2i\t", area); if (cpu != NULL) fprintf(stderr, "by EIP:\t\t" FMT_ADDRX "\n\t", cpu->get_instruction_pointer()); else fprintf(stderr, "(device origin)\t"); fprintf(stderr, "range start: \t\t" FMT_PHY_ADDRX "\trange end:\t" FMT_PHY_ADDRX "\n\taddress accessed:\t" FMT_PHY_ADDRX "\tdata written:\t", bx_iodebug_s.monitored_mem_areas_start[area], bx_iodebug_s.monitored_mem_areas_end[area], (unsigned) addr); switch(len) { case 1: { Bit8u data8 = * ((Bit8u *) data); fprintf(stderr,"%02X\n", data8); break; } case 2: { Bit16u data16 = * ((Bit16u *) data); fprintf(stderr,"%04X\n", data16); break; } case 4: { Bit32u data32 = * ((Bit32u *) data); fprintf(stderr,"%08X\n", data32); break; } case 8: { Bit64u data64 = * ((Bit64u *) data); fprintf(stderr,"%08X%08x\n", (Bit32u)(data64 >> 32), (Bit32u)(data64 & 0xffffffff)); break; } default: fprintf(stderr, "unsupported read size\n"); } #endif } } unsigned bx_iodebug_c::range_test(bx_phy_address addr, unsigned len) { for(unsigned i=0;i } #ifdef __linux__ extern "C" { #include #include } #endif #include "iodev.h" #include "hdimage/hdimage.h" #include "floppy.h" // windows.h included by bochs.h #ifdef WIN32 extern "C" { #include } #endif #define LOG_THIS theFloppyController-> bx_floppy_ctrl_c *theFloppyController; /* for main status register */ #define FD_MS_MRQ 0x80 #define FD_MS_DIO 0x40 #define FD_MS_NDMA 0x20 #define FD_MS_BUSY 0x10 #define FD_MS_ACTD 0x08 #define FD_MS_ACTC 0x04 #define FD_MS_ACTB 0x02 #define FD_MS_ACTA 0x01 #define FROM_FLOPPY 10 #define TO_FLOPPY 11 #define FLOPPY_DMA_CHAN 2 #define FDRIVE_NONE 0x00 #define FDRIVE_525DD 0x01 #define FDRIVE_525HD 0x02 #define FDRIVE_350DD 0x04 #define FDRIVE_350HD 0x08 #define FDRIVE_350ED 0x10 typedef struct { unsigned id; Bit8u trk; Bit8u hd; Bit8u spt; unsigned sectors; Bit8u drive_mask; } floppy_type_t; static floppy_type_t floppy_type[8] = { {BX_FLOPPY_160K, 40, 1, 8, 320, 0x03}, {BX_FLOPPY_180K, 40, 1, 9, 360, 0x03}, {BX_FLOPPY_320K, 40, 2, 8, 640, 0x03}, {BX_FLOPPY_360K, 40, 2, 9, 720, 0x03}, {BX_FLOPPY_720K, 80, 2, 9, 1440, 0x1f}, {BX_FLOPPY_1_2, 80, 2, 15, 2400, 0x02}, {BX_FLOPPY_1_44, 80, 2, 18, 2880, 0x18}, {BX_FLOPPY_2_88, 80, 2, 36, 5760, 0x10} }; static Bit16u drate_in_k[4] = { 500, 300, 250, 1000 }; int libfloppy_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theFloppyController = new bx_floppy_ctrl_c(); bx_devices.pluginFloppyDevice = theFloppyController; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theFloppyController, BX_PLUGIN_FLOPPY); return 0; // Success } else { return -1; } } void libfloppy_LTX_plugin_fini(void) { delete theFloppyController; } bx_floppy_ctrl_c::bx_floppy_ctrl_c() { put("floppy", "FDD"); memset(&s, 0, sizeof(s)); s.floppy_timer_index = BX_NULL_TIMER_HANDLE; } bx_floppy_ctrl_c::~bx_floppy_ctrl_c() { char pname[10]; for (int i = 0; i < 2; i++) { close_media(&BX_FD_THIS s.media[i]); sprintf(pname, "floppy.%d", i); bx_list_c *floppy = (bx_list_c*)SIM->get_param(pname); SIM->get_param_string("path", floppy)->set_handler(NULL); SIM->get_param_bool("readonly", floppy)->set_handler(NULL); SIM->get_param_bool("status", floppy)->set_handler(NULL); } SIM->get_bochs_root()->remove("floppy"); BX_DEBUG(("Exit")); } void bx_floppy_ctrl_c::init(void) { Bit8u i, devtype, cmos_value; char pname[10]; BX_DEBUG(("Init $Id: floppy.cc 11346 2012-08-19 08:16:20Z vruppert $")); DEV_dma_register_8bit_channel(2, dma_read, dma_write, "Floppy Drive"); DEV_register_irq(6, "Floppy Drive"); for (unsigned addr=0x03F2; addr<=0x03F7; addr++) { DEV_register_ioread_handler(this, read_handler, addr, "Floppy Drive", 1); DEV_register_iowrite_handler(this, write_handler, addr, "Floppy Drive", 1); } cmos_value = 0x00; /* start out with: no drive 0, no drive 1 */ BX_FD_THIS s.num_supported_floppies = 0; for (i=0; i<4; i++) { BX_FD_THIS s.media[i].type = BX_FLOPPY_NONE; BX_FD_THIS s.media[i].sectors_per_track = 0; BX_FD_THIS s.media[i].tracks = 0; BX_FD_THIS s.media[i].heads = 0; BX_FD_THIS s.media[i].sectors = 0; BX_FD_THIS s.media[i].fd = -1; BX_FD_THIS s.media[i].vvfat_floppy = 0; BX_FD_THIS s.media[i].status_changed = 0; BX_FD_THIS s.media_present[i] = 0; BX_FD_THIS s.device_type[i] = FDRIVE_NONE; } // // Floppy A setup // devtype = SIM->get_param_enum(BXPN_FLOPPYA_DEVTYPE)->get(); cmos_value = (devtype << 4); if (devtype != BX_FDD_NONE) { BX_FD_THIS s.device_type[0] = 1 << (devtype - 1); BX_FD_THIS s.num_supported_floppies++; BX_FD_THIS s.statusbar_id[0] = bx_gui->register_statusitem(" A: "); } else { BX_FD_THIS s.statusbar_id[0] = -1; } if (SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->get() != BX_FLOPPY_NONE) { if (SIM->get_param_bool(BXPN_FLOPPYA_STATUS)->get()) { BX_FD_THIS s.media[0].write_protected = SIM->get_param_bool(BXPN_FLOPPYA_READONLY)->get(); if (evaluate_media(BX_FD_THIS s.device_type[0], SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->get(), SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), & BX_FD_THIS s.media[0])) { BX_FD_THIS s.media_present[0] = 1; #define MED (BX_FD_THIS s.media[0]) BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); if (MED.write_protected) SIM->get_param_bool(BXPN_FLOPPYA_READONLY)->set(1); #undef MED } else { SIM->get_param_bool(BXPN_FLOPPYA_STATUS)->set(0); } } } // // Floppy B setup // devtype = SIM->get_param_enum(BXPN_FLOPPYB_DEVTYPE)->get(); cmos_value |= devtype; if (devtype != BX_FDD_NONE) { BX_FD_THIS s.device_type[1] = 1 << (devtype - 1); BX_FD_THIS s.num_supported_floppies++; BX_FD_THIS s.statusbar_id[1] = bx_gui->register_statusitem(" B: "); } else { BX_FD_THIS s.statusbar_id[1] = -1; } if (SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->get() != BX_FLOPPY_NONE) { if (SIM->get_param_bool(BXPN_FLOPPYB_STATUS)->get()) { BX_FD_THIS s.media[1].write_protected = SIM->get_param_bool(BXPN_FLOPPYB_READONLY)->get(); if (evaluate_media(BX_FD_THIS s.device_type[1], SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->get(), SIM->get_param_string(BXPN_FLOPPYB_PATH)->getptr(), & BX_FD_THIS s.media[1])) { BX_FD_THIS s.media_present[1] = 1; #define MED (BX_FD_THIS s.media[1]) BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", SIM->get_param_string(BXPN_FLOPPYB_PATH)->getptr(), MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); if (MED.write_protected) SIM->get_param_bool(BXPN_FLOPPYB_READONLY)->set(1); #undef MED } else { SIM->get_param_bool(BXPN_FLOPPYB_STATUS)->set(0); } } } /* CMOS Floppy Type and Equipment Byte register */ DEV_cmos_set_reg(0x10, cmos_value); if (BX_FD_THIS s.num_supported_floppies > 0) { DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0x3e) | ((BX_FD_THIS s.num_supported_floppies-1) << 6) | 1); } else { DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0x3e)); } if (BX_FD_THIS s.floppy_timer_index == BX_NULL_TIMER_HANDLE) { BX_FD_THIS s.floppy_timer_index = bx_pc_system.register_timer(this, timer_handler, 250, 0, 0, "floppy"); } /* phase out s.non_dma in favor of using FD_MS_NDMA, more like hardware */ BX_FD_THIS s.main_status_reg &= ~FD_MS_NDMA; // enable DMA from start /* these registers are not cleared by reset */ BX_FD_THIS s.SRT = 0; BX_FD_THIS s.HUT = 0; BX_FD_THIS s.HLT = 0; // runtime parameters for (i = 0; i < 2; i++) { sprintf(pname, "floppy.%d", i); bx_list_c *floppy = (bx_list_c*)SIM->get_param(pname); SIM->get_param_string("path", floppy)->set_handler(floppy_param_string_handler); SIM->get_param_string("path", floppy)->set_runtime_param(1); SIM->get_param_bool("readonly", floppy)->set_handler(floppy_param_handler); SIM->get_param_bool("readonly", floppy)->set_runtime_param(1); SIM->get_param_bool("status", floppy)->set_handler(floppy_param_handler); SIM->get_param_bool("status", floppy)->set_runtime_param(1); } // register handler for correct floppy parameter handling after runtime config SIM->register_runtime_config_handler(this, runtime_config_handler); #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("floppy", this); #endif } void bx_floppy_ctrl_c::reset(unsigned type) { Bit32u i; BX_FD_THIS s.pending_irq = 0; BX_FD_THIS s.reset_sensei = 0; /* no reset result present */ BX_FD_THIS s.main_status_reg = 0; BX_FD_THIS s.status_reg0 = 0; BX_FD_THIS s.status_reg1 = 0; BX_FD_THIS s.status_reg2 = 0; BX_FD_THIS s.status_reg3 = 0; // software reset (via DOR port 0x3f2 bit 2) does not change DOR if (type == BX_RESET_HARDWARE) { BX_FD_THIS s.DOR = 0x0c; // motor off, drive 3..0 // DMA/INT enabled // normal operation // drive select 0 // DIR and CCR affected only by hard reset for (i=0; i<4; i++) { BX_FD_THIS s.DIR[i] |= 0x80; // disk changed } BX_FD_THIS s.data_rate = 2; /* 250 Kbps */ BX_FD_THIS s.lock = 0; } else { BX_INFO(("controller reset in software")); } if (BX_FD_THIS s.lock == 0) { BX_FD_THIS s.config = 0; BX_FD_THIS s.pretrk = 0; } BX_FD_THIS s.perp_mode = 0; for (i=0; i<4; i++) { BX_FD_THIS s.cylinder[i] = 0; BX_FD_THIS s.head[i] = 0; BX_FD_THIS s.sector[i] = 0; BX_FD_THIS s.eot[i] = 0; } DEV_pic_lower_irq(6); if (!(BX_FD_THIS s.main_status_reg & FD_MS_NDMA)) { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); } enter_idle_phase(); } void bx_floppy_ctrl_c::register_state(void) { unsigned i; char name[8]; bx_list_c *drive; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "floppy", "Floppy State"); new bx_shadow_num_c(list, "data_rate", &BX_FD_THIS s.data_rate); bx_list_c *command = new bx_list_c(list, "command"); for (i=0; i<10; i++) { sprintf(name, "%d", i); new bx_shadow_num_c(command, name, &BX_FD_THIS s.command[i], BASE_HEX); } new bx_shadow_num_c(list, "command_index", &BX_FD_THIS s.command_index); new bx_shadow_num_c(list, "command_size", &BX_FD_THIS s.command_size); new bx_shadow_bool_c(list, "command_complete", &BX_FD_THIS s.command_complete); new bx_shadow_num_c(list, "pending_command", &BX_FD_THIS s.pending_command, BASE_HEX); new bx_shadow_bool_c(list, "multi_track", &BX_FD_THIS s.multi_track); new bx_shadow_bool_c(list, "pending_irq", &BX_FD_THIS s.pending_irq); new bx_shadow_num_c(list, "reset_sensei", &BX_FD_THIS s.reset_sensei); new bx_shadow_num_c(list, "format_count", &BX_FD_THIS s.format_count); new bx_shadow_num_c(list, "format_fillbyte", &BX_FD_THIS s.format_fillbyte, BASE_HEX); bx_list_c *result = new bx_list_c(list, "result"); for (i=0; i<10; i++) { sprintf(name, "%d", i); new bx_shadow_num_c(result, name, &BX_FD_THIS s.result[i], BASE_HEX); } new bx_shadow_num_c(list, "result_index", &BX_FD_THIS s.result_index); new bx_shadow_num_c(list, "result_size", &BX_FD_THIS s.result_size); new bx_shadow_num_c(list, "DOR", &BX_FD_THIS s.DOR, BASE_HEX); new bx_shadow_num_c(list, "TDR", &BX_FD_THIS s.TDR, BASE_HEX); new bx_shadow_bool_c(list, "TC", &BX_FD_THIS s.TC); new bx_shadow_num_c(list, "main_status_reg", &BX_FD_THIS s.main_status_reg, BASE_HEX); new bx_shadow_num_c(list, "status_reg0", &BX_FD_THIS s.status_reg0, BASE_HEX); new bx_shadow_num_c(list, "status_reg1", &BX_FD_THIS s.status_reg1, BASE_HEX); new bx_shadow_num_c(list, "status_reg2", &BX_FD_THIS s.status_reg2, BASE_HEX); new bx_shadow_num_c(list, "status_reg3", &BX_FD_THIS s.status_reg3, BASE_HEX); new bx_shadow_num_c(list, "floppy_buffer_index", &BX_FD_THIS s.floppy_buffer_index); new bx_shadow_bool_c(list, "lock", &BX_FD_THIS s.lock); new bx_shadow_num_c(list, "SRT", &BX_FD_THIS s.SRT, BASE_HEX); new bx_shadow_num_c(list, "HUT", &BX_FD_THIS s.HUT, BASE_HEX); new bx_shadow_num_c(list, "HLT", &BX_FD_THIS s.HLT, BASE_HEX); new bx_shadow_num_c(list, "config", &BX_FD_THIS s.config, BASE_HEX); new bx_shadow_num_c(list, "pretrk", &BX_FD_THIS s.pretrk); new bx_shadow_num_c(list, "perp_mode", &BX_FD_THIS s.perp_mode); new bx_shadow_data_c(list, "buffer", BX_FD_THIS s.floppy_buffer, 512); for (i=0; i<4; i++) { sprintf(name, "drive%d", i); drive = new bx_list_c(list, name); new bx_shadow_num_c(drive, "cylinder", &BX_FD_THIS s.cylinder[i]); new bx_shadow_num_c(drive, "head", &BX_FD_THIS s.head[i]); new bx_shadow_num_c(drive, "sector", &BX_FD_THIS s.sector[i]); new bx_shadow_num_c(drive, "eot", &BX_FD_THIS s.eot[i]); new bx_shadow_bool_c(drive, "media_present", &BX_FD_THIS s.media_present[i]); new bx_shadow_num_c(drive, "DIR", &BX_FD_THIS s.DIR[i], BASE_HEX); } } void bx_floppy_ctrl_c::runtime_config_handler(void *this_ptr) { bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr; class_ptr->runtime_config(); } void bx_floppy_ctrl_c::runtime_config(void) { unsigned drive; bx_bool status; char pname[16]; for (drive=0; drive<2; drive++) { if (BX_FD_THIS s.media[drive].status_changed) { sprintf(pname, "floppy.%d.status", drive); status = SIM->get_param_bool(pname)->get(); if (BX_FD_THIS s.media_present[drive]) { BX_FD_THIS set_media_status(drive, 0); } if (status) { BX_FD_THIS set_media_status(drive, 1); } BX_FD_THIS s.media[drive].status_changed = 0; } } } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_floppy_ctrl_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_FD_SMF bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr; return class_ptr->read(address, io_len); } /* reads from the floppy io ports */ Bit32u bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_FD_SMF Bit8u value = 0, drive; Bit8u pending_command = BX_FD_THIS s.pending_command; switch (address) { #if BX_DMA_FLOPPY_IO case 0x3F2: // diskette controller digital output register value = BX_FD_THIS s.DOR; break; case 0x3F4: /* diskette controller main status register */ value = BX_FD_THIS s.main_status_reg; break; case 0x3F5: /* diskette controller data */ if ((BX_FD_THIS s.main_status_reg & FD_MS_NDMA) && ((BX_FD_THIS s.pending_command & 0x4f) == 0x46)) { dma_write(&value, 1); lower_interrupt(); // don't enter idle phase until we've given CPU last data byte if (BX_FD_THIS s.TC) enter_idle_phase(); } else if (BX_FD_THIS s.result_size == 0) { BX_ERROR(("port 0x3f5: no results to read")); BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; value = BX_FD_THIS s.result[0]; } else { value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++]; BX_FD_THIS s.main_status_reg &= 0xF0; BX_FD_THIS lower_interrupt(); if (BX_FD_THIS s.result_index >= BX_FD_THIS s.result_size) { enter_idle_phase(); } } break; #endif // #if BX_DMA_FLOPPY_IO case 0x3F3: // Tape Drive Register drive = BX_FD_THIS s.DOR & 0x03; if (BX_FD_THIS s.media_present[drive]) { switch (BX_FD_THIS s.media[drive].type) { case BX_FLOPPY_160K: case BX_FLOPPY_180K: case BX_FLOPPY_320K: case BX_FLOPPY_360K: case BX_FLOPPY_1_2: value = 0x00; break; case BX_FLOPPY_720K: value = 0xc0; break; case BX_FLOPPY_1_44: value = 0x80; break; case BX_FLOPPY_2_88: value = 0x40; break; default: // BX_FLOPPY_NONE value = 0x20; break; } } else { value = 0x20; } break; case 0x3F6: // Reserved for future floppy controllers // This address shared with the hard drive controller value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len); break; case 0x3F7: // diskette controller digital input register // This address shared with the hard drive controller: // Bit 7 : floppy // Bits 6..0: hard drive value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len); value &= 0x7f; // add in diskette change line if motor is on drive = BX_FD_THIS s.DOR & 0x03; if (BX_FD_THIS s.DOR & (1<<(drive+4))) { value |= (BX_FD_THIS s.DIR[drive] & 0x80); } break; default: BX_ERROR(("io_read: unsupported address 0x%04x", (unsigned) address)); return(0); break; } BX_DEBUG(("read(): during command 0x%02x, port 0x%04x returns 0x%02x", pending_command, address, value)); return (value); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_floppy_ctrl_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_FD_SMF bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr; class_ptr->write(address, value, io_len); } /* writes to the floppy io ports */ void bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_FD_SMF Bit8u dma_and_interrupt_enable; Bit8u normal_operation, prev_normal_operation; Bit8u drive_select; Bit8u motor_on_drive0, motor_on_drive1; BX_DEBUG(("write access to port 0x%04x, value=0x%02x", address, value)); switch (address) { #if BX_DMA_FLOPPY_IO case 0x3F2: /* diskette controller digital output register */ motor_on_drive0 = value & 0x10; motor_on_drive1 = value & 0x20; /* set status bar conditions for Floppy 0 and Floppy 1 */ if (BX_FD_THIS s.statusbar_id[0] >= 0) { if (motor_on_drive0 != (BX_FD_THIS s.DOR & 0x10)) bx_gui->statusbar_setitem(BX_FD_THIS s.statusbar_id[0], motor_on_drive0); } if (BX_FD_THIS s.statusbar_id[1] >= 0) { if (motor_on_drive1 != (BX_FD_THIS s.DOR & 0x20)) bx_gui->statusbar_setitem(BX_FD_THIS s.statusbar_id[1], motor_on_drive1); } dma_and_interrupt_enable = value & 0x08; if (!dma_and_interrupt_enable) BX_DEBUG(("DMA and interrupt capabilities disabled")); normal_operation = value & 0x04; drive_select = value & 0x03; prev_normal_operation = BX_FD_THIS s.DOR & 0x04; BX_FD_THIS s.DOR = value; if (prev_normal_operation==0 && normal_operation) { // transition from RESET to NORMAL bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, 250, 0); } else if (prev_normal_operation && normal_operation==0) { // transition from NORMAL to RESET BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.pending_command = 0xfe; // RESET pending } BX_DEBUG(("io_write: digital output register")); BX_DEBUG((" motor on, drive1 = %d", motor_on_drive1 > 0)); BX_DEBUG((" motor on, drive0 = %d", motor_on_drive0 > 0)); BX_DEBUG((" dma_and_interrupt_enable=%02x", (unsigned) dma_and_interrupt_enable)); BX_DEBUG((" normal_operation=%02x", (unsigned) normal_operation)); BX_DEBUG((" drive_select=%02x", (unsigned) drive_select)); if (BX_FD_THIS s.device_type[drive_select] == FDRIVE_NONE) { BX_DEBUG(("WARNING: non existing drive selected")); } break; case 0x3f4: /* diskette controller data rate select register */ BX_FD_THIS s.data_rate = value & 0x03; if (value & 0x80) { BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.pending_command = 0xfe; // RESET pending bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, 250, 0); } if ((value & 0x7c) > 0) { BX_ERROR(("write to data rate select register: unsupported bits set")); } break; case 0x3F5: /* diskette controller data */ BX_DEBUG(("command = 0x%02x", (unsigned) value)); if ((BX_FD_THIS s.main_status_reg & FD_MS_NDMA) && ((BX_FD_THIS s.pending_command & 0x4f) == 0x45)) { BX_FD_THIS dma_read((Bit8u *) &value, 1); BX_FD_THIS lower_interrupt(); break; } else if (BX_FD_THIS s.command_complete) { if (BX_FD_THIS s.pending_command != 0) BX_PANIC(("write 0x03f5: receiving new command 0x%02x, old one (0x%02x) pending", value, BX_FD_THIS s.pending_command)); BX_FD_THIS s.command[0] = value; BX_FD_THIS s.command_complete = 0; BX_FD_THIS s.command_index = 1; /* read/write command in progress */ BX_FD_THIS s.main_status_reg &= ~FD_MS_DIO; // leave drive status untouched BX_FD_THIS s.main_status_reg |= FD_MS_MRQ | FD_MS_BUSY; switch (value) { case 0x03: /* specify */ BX_FD_THIS s.command_size = 3; break; case 0x04: // get status BX_FD_THIS s.command_size = 2; break; case 0x07: /* recalibrate */ BX_FD_THIS s.command_size = 2; break; case 0x08: /* sense interrupt status */ BX_FD_THIS s.command_size = 1; break; case 0x0f: /* seek */ BX_FD_THIS s.command_size = 3; break; case 0x4a: /* read ID */ BX_FD_THIS s.command_size = 2; break; case 0x4d: /* format track */ BX_FD_THIS s.command_size = 6; break; case 0x45: case 0xc5: /* write normal data */ BX_FD_THIS s.command_size = 9; break; case 0x46: case 0x66: case 0xc6: case 0xe6: /* read normal data */ BX_FD_THIS s.command_size = 9; break; case 0x0e: // dump registers (Enhanced drives) case 0x10: // Version command, enhanced controller returns 0x90 case 0x14: // Unlock command (Enhanced) case 0x94: // Lock command (Enhanced) BX_FD_THIS s.command_size = 0; BX_FD_THIS s.pending_command = value; enter_result_phase(); break; case 0x12: // Perpendicular mode (Enhanced) BX_FD_THIS s.command_size = 2; break; case 0x13: // Configure command (Enhanced) BX_FD_THIS s.command_size = 4; break; case 0x18: // National Semiconductor version command; return 80h // These commands are not implemented on the standard // controller and return an error. They are available on // the enhanced controller. BX_DEBUG(("io_write: 0x3f5: unsupported floppy command 0x%02x", (unsigned) value)); BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command enter_result_phase(); break; default: BX_ERROR(("io_write: 0x3f5: invalid floppy command 0x%02x", (unsigned) value)); BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command enter_result_phase(); break; } } else { BX_FD_THIS s.command[BX_FD_THIS s.command_index++] = value; } if (BX_FD_THIS s.command_index == BX_FD_THIS s.command_size) { /* read/write command not in progress any more */ floppy_command(); BX_FD_THIS s.command_complete = 1; } BX_DEBUG(("io_write: diskette controller data")); return; break; #endif // #if BX_DMA_FLOPPY_IO case 0x3F6: /* diskette controller (reserved) */ BX_DEBUG(("io_write: reserved register 0x3f6 unsupported")); // this address shared with the hard drive controller DEV_hd_write_handler(bx_devices.pluginHardDrive, address, value, io_len); break; #if BX_DMA_FLOPPY_IO case 0x3F7: /* diskette controller configuration control register */ if ((value & 0x03) != BX_FD_THIS s.data_rate) BX_INFO(("io_write: config control register: 0x%02x", value)); BX_FD_THIS s.data_rate = value & 0x03; switch (BX_FD_THIS s.data_rate) { case 0: BX_DEBUG((" 500 Kbps")); break; case 1: BX_DEBUG((" 300 Kbps")); break; case 2: BX_DEBUG((" 250 Kbps")); break; case 3: BX_DEBUG((" 1 Mbps")); break; } break; default: BX_ERROR(("io_write ignored: 0x%04x = 0x%02x", (unsigned) address, (unsigned) value)); break; #endif // #if BX_DMA_FLOPPY_IO } } void bx_floppy_ctrl_c::floppy_command(void) { unsigned i; Bit8u motor_on; Bit8u head, drive, cylinder, sector, eot; Bit8u sector_size; //Bit8u data_length; Bit32u logical_sector, sector_time, step_delay; // Print command char buf[9+(9*5)+1], *p = buf; p += sprintf(p, "COMMAND: "); for (i=0; i> 4; BX_FD_THIS s.HUT = BX_FD_THIS s.command[1] & 0x0f; BX_FD_THIS s.HLT = BX_FD_THIS s.command[2] >> 1; BX_FD_THIS s.main_status_reg |= (BX_FD_THIS s.command[2] & 0x01) ? FD_MS_NDMA : 0; if (BX_FD_THIS s.main_status_reg & FD_MS_NDMA) BX_ERROR(("non DMA mode not fully implemented yet")); enter_idle_phase(); return; case 0x04: // get status drive = (BX_FD_THIS s.command[1] & 0x03); BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; BX_FD_THIS s.status_reg3 = 0x28 | (BX_FD_THIS s.head[drive]<<2) | drive | (BX_FD_THIS s.media[drive].write_protected ? 0x40 : 0x00); if ((BX_FD_THIS s.device_type[drive] != FDRIVE_NONE) && (BX_FD_THIS s.cylinder[drive] == 0)) BX_FD_THIS s.status_reg3 |= 0x10; enter_result_phase(); return; case 0x07: // recalibrate drive = (BX_FD_THIS s.command[1] & 0x03); BX_FD_THIS s.DOR &= 0xfc; BX_FD_THIS s.DOR |= drive; BX_DEBUG(("floppy_command(): recalibrate drive %u", (unsigned) drive)); step_delay = calculate_step_delay(drive, 0); bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, step_delay, 0); /* command head to track 0 * controller set to non-busy * error condition noted in Status reg 0's equipment check bit * seek end bit set to 1 in Status reg 0 regardless of outcome * The last two are taken care of in timer(). */ BX_FD_THIS s.cylinder[drive] = 0; BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= (1 << drive); return; case 0x08: /* sense interrupt status */ /* execution: * get status * result: * no interupt * byte0 = status reg0 * byte1 = current cylinder number (0 to 79) */ if (BX_FD_THIS s.reset_sensei > 0) { drive = 4 - BX_FD_THIS s.reset_sensei; BX_FD_THIS s.status_reg0 &= 0xf8; BX_FD_THIS s.status_reg0 |= (BX_FD_THIS s.head[drive] << 2) | drive; BX_FD_THIS s.reset_sensei--; } else if (!BX_FD_THIS s.pending_irq) { BX_FD_THIS s.status_reg0 = 0x80; } BX_DEBUG(("sense interrupt status")); enter_result_phase(); return; case 0x0f: /* seek */ /* command: * byte0 = 0F * byte1 = drive & head select * byte2 = cylinder number * execution: * postion head over specified cylinder * result: * no result bytes, issues an interrupt */ drive = BX_FD_THIS s.command[1] & 0x03; BX_FD_THIS s.DOR &= 0xfc; BX_FD_THIS s.DOR |= drive; BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; step_delay = calculate_step_delay(drive, BX_FD_THIS s.command[2]); bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, step_delay, 0); /* ??? should also check cylinder validity */ BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.command[2]; /* data reg not ready, drive not busy */ BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= (1 << drive); return; case 0x13: // Configure BX_DEBUG(("configure (eis = 0x%02x)", BX_FD_THIS s.command[2] & 0x40)); BX_DEBUG(("configure (efifo = 0x%02x)", BX_FD_THIS s.command[2] & 0x20)); BX_DEBUG(("configure (no poll = 0x%02x)", BX_FD_THIS s.command[2] & 0x10)); BX_DEBUG(("configure (fifothr = 0x%02x)", BX_FD_THIS s.command[2] & 0x0f)); BX_DEBUG(("configure (pretrk = 0x%02x)", BX_FD_THIS s.command[3])); BX_FD_THIS s.config = BX_FD_THIS s.command[2]; BX_FD_THIS s.pretrk = BX_FD_THIS s.command[3]; enter_idle_phase(); return; case 0x4a: // read ID drive = BX_FD_THIS s.command[1] & 0x03; BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; BX_FD_THIS s.DOR &= 0xfc; BX_FD_THIS s.DOR |= drive; motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01; if (motor_on == 0) { BX_ERROR(("floppy_command(): read ID: motor not on")); BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= FD_MS_BUSY; return; // Hang controller } if (BX_FD_THIS s.device_type[drive] == FDRIVE_NONE) { BX_ERROR(("floppy_command(): read ID: bad drive #%d", drive)); BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= FD_MS_BUSY; return; // Hang controller } if (BX_FD_THIS s.media_present[drive] == 0) { BX_INFO(("attempt to read sector ID with media not present")); BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= FD_MS_BUSY; return; // Hang controller } BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive]<<2) | drive; // time to read one sector at 300 rpm sector_time = 200000 / BX_FD_THIS s.media[drive].sectors_per_track; bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, sector_time, 0); /* data reg not ready, controller busy */ BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= FD_MS_BUSY; return; case 0x4d: // format track drive = BX_FD_THIS s.command[1] & 0x03; BX_FD_THIS s.DOR &= 0xfc; BX_FD_THIS s.DOR |= drive; motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01; if (motor_on == 0) BX_PANIC(("floppy_command(): format track: motor not on")); BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01; sector_size = BX_FD_THIS s.command[2]; BX_FD_THIS s.format_count = BX_FD_THIS s.command[3]; BX_FD_THIS s.format_fillbyte = BX_FD_THIS s.command[5]; if (BX_FD_THIS s.device_type[drive] == FDRIVE_NONE) BX_PANIC(("floppy_command(): format track: bad drive #%d", drive)); if (sector_size != 0x02) { // 512 bytes BX_PANIC(("format track: sector size %d not supported", 128<> 7); if ((BX_FD_THIS s.DOR & 0x08) == 0) BX_PANIC(("read/write command with DMA and int disabled")); drive = BX_FD_THIS s.command[1] & 0x03; BX_FD_THIS s.DOR &= 0xfc; BX_FD_THIS s.DOR |= drive; motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01; if (motor_on == 0) BX_PANIC(("floppy_command(): read/write: motor not on")); head = BX_FD_THIS s.command[3] & 0x01; cylinder = BX_FD_THIS s.command[2]; /* 0..79 depending */ sector = BX_FD_THIS s.command[4]; /* 1..36 depending */ eot = BX_FD_THIS s.command[6]; /* 1..36 depending */ sector_size = BX_FD_THIS s.command[5]; // data_length = BX_FD_THIS s.command[8]; BX_DEBUG(("read/write normal data")); BX_DEBUG(("BEFORE")); BX_DEBUG((" drive = %u", (unsigned) drive)); BX_DEBUG((" head = %u", (unsigned) head)); BX_DEBUG((" cylinder = %u", (unsigned) cylinder)); BX_DEBUG((" sector = %u", (unsigned) sector)); BX_DEBUG((" eot = %u", (unsigned) eot)); if (BX_FD_THIS s.device_type[drive] == FDRIVE_NONE) BX_PANIC(("floppy_command(): read/write: bad drive #%d", drive)); // check that head number in command[1] bit two matches the head // reported in the head number field. Real floppy drives are // picky about this, as reported in SF bug #439945, (Floppy drive // read input error checking). if (head != ((BX_FD_THIS s.command[1]>>2)&1)) { BX_ERROR(("head number in command[1] doesn't match head field")); BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination BX_FD_THIS s.status_reg1 = 0x04; // 0000 0100 BX_FD_THIS s.status_reg2 = 0x00; // 0000 0000 enter_result_phase(); return; } if (BX_FD_THIS s.media_present[drive] == 0) { BX_INFO(("attempt to read/write sector %u with media not present", (unsigned) sector)); return; // Hang controller } if (sector_size != 0x02) { // 512 bytes BX_PANIC(("read/write command: sector size %d not supported", 128<= BX_FD_THIS s.media[drive].tracks) { BX_PANIC(("io: norm r/w parms out of range: sec#%02xh cyl#%02xh eot#%02xh head#%02xh", (unsigned) sector, (unsigned) cylinder, (unsigned) eot, (unsigned) head)); return; } if (sector > BX_FD_THIS s.media[drive].sectors_per_track) { BX_INFO(("attempt to read/write sector %u past last sector %u", (unsigned) sector, (unsigned) BX_FD_THIS s.media[drive].sectors_per_track)); BX_FD_THIS s.cylinder[drive] = cylinder; BX_FD_THIS s.head[drive] = head; BX_FD_THIS s.sector[drive] = sector; BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; BX_FD_THIS s.status_reg1 = 0x04; BX_FD_THIS s.status_reg2 = 0x00; enter_result_phase(); return; } if (cylinder != BX_FD_THIS s.cylinder[drive]) { BX_DEBUG(("io: cylinder request != current cylinder")); reset_changeline(); } logical_sector = (cylinder * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) + (head * BX_FD_THIS s.media[drive].sectors_per_track) + (sector - 1); if (logical_sector >= BX_FD_THIS s.media[drive].sectors) { BX_PANIC(("io: logical sector out of bounds")); } // This hack makes older versions of the Bochs BIOS work if (eot == 0) { eot = BX_FD_THIS s.media[drive].sectors_per_track; } BX_FD_THIS s.cylinder[drive] = cylinder; BX_FD_THIS s.head[drive] = head; BX_FD_THIS s.sector[drive] = sector; BX_FD_THIS s.eot[drive] = eot; if ((BX_FD_THIS s.command[0] & 0x4f) == 0x46) { // read floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, 512, FROM_FLOPPY); /* controller busy; if DMA mode, data reg not ready */ BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= FD_MS_BUSY; if (BX_FD_THIS s.main_status_reg & FD_MS_NDMA) { BX_FD_THIS s.main_status_reg |= (FD_MS_MRQ | FD_MS_DIO); } // time to read one sector at 300 rpm sector_time = 200000 / BX_FD_THIS s.media[drive].sectors_per_track; bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, sector_time , 0); } else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write /* controller busy; if DMA mode, data reg not ready */ BX_FD_THIS s.main_status_reg &= FD_MS_NDMA; BX_FD_THIS s.main_status_reg |= FD_MS_BUSY; if (BX_FD_THIS s.main_status_reg & FD_MS_NDMA) { BX_FD_THIS s.main_status_reg |= FD_MS_MRQ; } else { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); } } else { BX_PANIC(("floppy_command(): unknown read/write command")); return; } break; case 0x12: // Perpendicular mode BX_FD_THIS s.perp_mode = BX_FD_THIS s.command[1]; BX_INFO(("perpendicular mode: config=0x%02x", BX_FD_THIS s.perp_mode)); enter_idle_phase(); break; default: // invalid or unsupported command; these are captured in write() above BX_PANIC(("You should never get here! cmd = 0x%02x", BX_FD_THIS s.command[0])); } } void bx_floppy_ctrl_c::floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, Bit32u bytes, Bit8u direction) { int ret = 0; if (BX_FD_THIS s.device_type[drive] == FDRIVE_NONE) BX_PANIC(("floppy_xfer: bad drive #%d", drive)); BX_DEBUG(("floppy_xfer: drive=%u, offset=%u, bytes=%u, direction=%s floppy", drive, offset, bytes, (direction==FROM_FLOPPY)? "from" : "to")); #if BX_WITH_MACOS if (strcmp(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), SuperDrive)) #endif { if (BX_FD_THIS s.media[drive].vvfat_floppy) { ret = (int)BX_FD_THIS s.media[drive].vvfat->lseek(offset, SEEK_SET); } else { ret = (int)lseek(BX_FD_THIS s.media[drive].fd, offset, SEEK_SET); } if (ret < 0) { BX_PANIC(("could not perform lseek() to %d on floppy image file", offset)); return; } } if (direction == FROM_FLOPPY) { if (BX_FD_THIS s.media[drive].vvfat_floppy) { ret = BX_FD_THIS s.media[drive].vvfat->read(buffer, bytes); #if BX_WITH_MACOS } else if (!strcmp(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), SuperDrive)) ret = fd_read((char *) buffer, offset, bytes); #endif } else { ret = ::read(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes); } if (ret < int(bytes)) { if (ret > 0) { BX_INFO(("partial read() on floppy image returns %u/%u", (unsigned) ret, (unsigned) bytes)); memset(buffer + ret, 0, bytes - ret); } else { BX_INFO(("read() on floppy image returns 0")); memset(buffer, 0, bytes); } } } else { // TO_FLOPPY BX_ASSERT (!BX_FD_THIS s.media[drive].write_protected); if (BX_FD_THIS s.media[drive].vvfat_floppy) { ret = BX_FD_THIS s.media[drive].vvfat->write(buffer, bytes); #if BX_WITH_MACOS } else if (!strcmp(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), SuperDrive)) ret = fd_write((char *) buffer, offset, bytes); #endif } else { ret = ::write(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes); } if (ret < int(bytes)) { BX_PANIC(("could not perform write() on floppy image file")); } } } void bx_floppy_ctrl_c::timer_handler(void *this_ptr) { bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr; class_ptr->timer(); } void bx_floppy_ctrl_c::timer() { Bit8u drive, motor_on; drive = BX_FD_THIS s.DOR & 0x03; switch (BX_FD_THIS s.pending_command) { case 0x07: // recal BX_FD_THIS s.status_reg0 = 0x20 | drive; motor_on = ((BX_FD_THIS s.DOR>>(drive+4)) & 0x01); if ((BX_FD_THIS s.device_type[drive] == FDRIVE_NONE) || (motor_on == 0)) { BX_FD_THIS s.status_reg0 |= 0x50; } enter_idle_phase(); BX_FD_THIS raise_interrupt(); break; case 0x0f: // seek BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive]<<2) | drive; enter_idle_phase(); BX_FD_THIS raise_interrupt(); break; case 0x4a: /* read ID */ enter_result_phase(); break; case 0x45: /* write normal data */ case 0xc5: if (BX_FD_THIS s.TC) { // Terminal Count line, done BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive; BX_FD_THIS s.status_reg1 = 0; BX_FD_THIS s.status_reg2 = 0; BX_DEBUG(("<>")); BX_DEBUG(("AFTER")); BX_DEBUG((" drive = %u", drive)); BX_DEBUG((" head = %u", BX_FD_THIS s.head[drive])); BX_DEBUG((" cylinder = %u", BX_FD_THIS s.cylinder[drive])); BX_DEBUG((" sector = %u", BX_FD_THIS s.sector[drive])); enter_result_phase(); } else { // transfer next sector if (!(BX_FD_THIS s.main_status_reg & FD_MS_NDMA)) { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); } } break; case 0x46: /* read normal data */ case 0x66: case 0xc6: case 0xe6: // transfer next sector if (BX_FD_THIS s.main_status_reg & FD_MS_NDMA) { BX_FD_THIS s.main_status_reg &= ~FD_MS_BUSY; // clear busy bit BX_FD_THIS s.main_status_reg |= FD_MS_MRQ | FD_MS_DIO; // data byte waiting } else { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); } break; case 0x4d: /* format track */ if ((BX_FD_THIS s.format_count == 0) || BX_FD_THIS s.TC) { BX_FD_THIS s.format_count = 0; BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive; enter_result_phase(); } else { // transfer next sector if (!(BX_FD_THIS s.main_status_reg & FD_MS_NDMA)) { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1); } } break; case 0xfe: // (contrived) RESET theFloppyController->reset(BX_RESET_SOFTWARE); BX_FD_THIS s.pending_command = 0; BX_FD_THIS s.status_reg0 = 0xc0; BX_FD_THIS raise_interrupt(); BX_FD_THIS s.reset_sensei = 4; break; case 0x00: // nothing pending? break; default: BX_PANIC(("floppy:timer(): unknown case %02x", (unsigned) BX_FD_THIS s.pending_command)); } } Bit16u bx_floppy_ctrl_c::dma_write(Bit8u *buffer, Bit16u maxlen) { // A DMA write is from I/O to Memory // We need to return the next data byte(s) from the floppy buffer // to be transfered via the DMA to memory. (read block from floppy) // // maxlen is the maximum length of the DMA transfer Bit8u drive = BX_FD_THIS s.DOR & 0x03; Bit16u len = 512 - BX_FD_THIS s.floppy_buffer_index; if (len > maxlen) len = maxlen; memcpy(buffer, &BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index], len); BX_FD_THIS s.floppy_buffer_index += len; BX_FD_THIS s.TC = get_tc() && (len == maxlen); if ((BX_FD_THIS s.floppy_buffer_index >= 512) || (BX_FD_THIS s.TC)) { if (BX_FD_THIS s.floppy_buffer_index >= 512) { increment_sector(); // increment to next sector before retrieving next one BX_FD_THIS s.floppy_buffer_index = 0; } if (BX_FD_THIS s.TC) { // Terminal Count line, done BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive; BX_FD_THIS s.status_reg1 = 0; BX_FD_THIS s.status_reg2 = 0; BX_DEBUG(("<>")); BX_DEBUG(("AFTER")); BX_DEBUG((" drive = %u", drive)); BX_DEBUG((" head = %u", BX_FD_THIS s.head[drive])); BX_DEBUG((" cylinder = %u", BX_FD_THIS s.cylinder[drive])); BX_DEBUG((" sector = %u", BX_FD_THIS s.sector[drive])); if (!(BX_FD_THIS s.main_status_reg & FD_MS_NDMA)) { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); } enter_result_phase(); } else { // more data to transfer Bit32u logical_sector, sector_time; // remember that not all floppies have two sides, multiply by s.head[drive] logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) + (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) + (BX_FD_THIS s.sector[drive] - 1); floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, 512, FROM_FLOPPY); if (!(BX_FD_THIS s.main_status_reg & FD_MS_NDMA)) { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); } // time to read one sector at 300 rpm sector_time = 200000 / BX_FD_THIS s.media[drive].sectors_per_track; bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, sector_time , 0); } } return len; } Bit16u bx_floppy_ctrl_c::dma_read(Bit8u *buffer, Bit16u maxlen) { // A DMA read is from Memory to I/O // We need to write the data_byte which was already transfered from memory // via DMA to I/O (write block to floppy) // // maxlen is the length of the DMA transfer (not implemented yet) Bit8u drive = BX_FD_THIS s.DOR & 0x03; Bit32u logical_sector, sector_time; if (BX_FD_THIS s.pending_command == 0x4d) { // format track in progress BX_FD_THIS s.format_count--; switch (3 - (BX_FD_THIS s.format_count & 0x03)) { case 0: BX_FD_THIS s.cylinder[drive] = *buffer; break; case 1: if (*buffer != BX_FD_THIS s.head[drive]) BX_ERROR(("head number does not match head field")); break; case 2: BX_FD_THIS s.sector[drive] = *buffer; break; case 3: if (*buffer != 2) BX_ERROR(("dma_read: sector size %d not supported", 128<<(*buffer))); BX_DEBUG(("formatting cylinder %u head %u sector %u", BX_FD_THIS s.cylinder[drive], BX_FD_THIS s.head[drive], BX_FD_THIS s.sector[drive])); for (unsigned i = 0; i < 512; i++) { BX_FD_THIS s.floppy_buffer[i] = BX_FD_THIS s.format_fillbyte; } logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) + (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) + (BX_FD_THIS s.sector[drive] - 1); floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, 512, TO_FLOPPY); if (!(BX_FD_THIS s.main_status_reg & FD_MS_NDMA)) { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); } // time to write one sector at 300 rpm sector_time = 200000 / BX_FD_THIS s.media[drive].sectors_per_track; bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, sector_time , 0); break; } return 1; } else { // write normal data Bit16u len = 512 - BX_FD_THIS s.floppy_buffer_index; if (len > maxlen) len = maxlen; memcpy(&BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index], buffer, len); BX_FD_THIS s.floppy_buffer_index += len; BX_FD_THIS s.TC = get_tc() && (len == maxlen); if ((BX_FD_THIS s.floppy_buffer_index >= 512) || (BX_FD_THIS s.TC)) { logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) + (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) + (BX_FD_THIS s.sector[drive] - 1); if (BX_FD_THIS s.media[drive].write_protected) { // write protected error BX_INFO(("tried to write disk %u, which is write-protected", drive)); // ST0: IC1,0=01 (abnormal termination: started execution but failed) BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // ST1: DataError=1, NDAT=1, NotWritable=1, NID=1 BX_FD_THIS s.status_reg1 = 0x27; // 0010 0111 // ST2: CRCE=1, SERR=1, BCYL=1, NDAM=1. BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001 enter_result_phase(); return 1; } floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer, 512, TO_FLOPPY); increment_sector(); // increment to next sector after writing current one BX_FD_THIS s.floppy_buffer_index = 0; if (!(BX_FD_THIS s.main_status_reg & FD_MS_NDMA)) { DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0); } // time to write one sector at 300 rpm sector_time = 200000 / BX_FD_THIS s.media[drive].sectors_per_track; bx_pc_system.activate_timer(BX_FD_THIS s.floppy_timer_index, sector_time , 0); // the following is a kludge; i (jc) don't know how to work with the timer if ((BX_FD_THIS s.main_status_reg & FD_MS_NDMA) && BX_FD_THIS s.TC) { enter_result_phase(); } } return len; } } void bx_floppy_ctrl_c::raise_interrupt(void) { DEV_pic_raise_irq(6); BX_FD_THIS s.pending_irq = 1; BX_FD_THIS s.reset_sensei = 0; } void bx_floppy_ctrl_c::lower_interrupt(void) { if (BX_FD_THIS s.pending_irq) { DEV_pic_lower_irq(6); BX_FD_THIS s.pending_irq = 0; } } void bx_floppy_ctrl_c::increment_sector(void) { Bit8u drive; drive = BX_FD_THIS s.DOR & 0x03; // values after completion of data xfer // ??? calculation depends on base_count being multiple of 512 BX_FD_THIS s.sector[drive] ++; if ((BX_FD_THIS s.sector[drive] > BX_FD_THIS s.eot[drive]) || (BX_FD_THIS s.sector[drive] > BX_FD_THIS s.media[drive].sectors_per_track)) { BX_FD_THIS s.sector[drive] = 1; if (BX_FD_THIS s.multi_track) { BX_FD_THIS s.head[drive] ++; if (BX_FD_THIS s.head[drive] > 1) { BX_FD_THIS s.head[drive] = 0; BX_FD_THIS s.cylinder[drive] ++; reset_changeline(); } } else { BX_FD_THIS s.cylinder[drive] ++; reset_changeline(); } if (BX_FD_THIS s.cylinder[drive] >= BX_FD_THIS s.media[drive].tracks) { // Set to 1 past last possible cylinder value. // I notice if I set it to tracks-1, prama linux won't boot. BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.media[drive].tracks; BX_INFO(("increment_sector: clamping cylinder to max")); } } } unsigned bx_floppy_ctrl_c::set_media_status(unsigned drive, bx_bool status) { char *path; unsigned type; if (drive == 0) type = SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->get(); else type = SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->get(); // if setting to the current value, nothing to do if ((status == BX_FD_THIS s.media_present[drive]) && ((status == 0) || (type == BX_FD_THIS s.media[drive].type))) return(status); if (status == 0) { // eject floppy close_media(&BX_FD_THIS s.media[drive]); BX_FD_THIS s.media_present[drive] = 0; if (drive == 0) { SIM->get_param_bool(BXPN_FLOPPYA_STATUS)->set(0); } else { SIM->get_param_bool(BXPN_FLOPPYB_STATUS)->set(0); } BX_FD_THIS s.DIR[drive] |= 0x80; // disk changed line return(0); } else { // insert floppy if (drive == 0) { path = SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(); } else { path = SIM->get_param_string(BXPN_FLOPPYB_PATH)->getptr(); } if (!strcmp(path, "none")) return(0); if (evaluate_media(BX_FD_THIS s.device_type[drive], type, path, & BX_FD_THIS s.media[drive])) { BX_FD_THIS s.media_present[drive] = 1; if (drive == 0) { #define MED (BX_FD_THIS s.media[0]) BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); if (MED.write_protected) SIM->get_param_bool(BXPN_FLOPPYA_READONLY)->set(1); #undef MED SIM->get_param_bool(BXPN_FLOPPYA_STATUS)->set(1); } else { #define MED (BX_FD_THIS s.media[1]) BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", SIM->get_param_string(BXPN_FLOPPYB_PATH)->getptr(), MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track)); if (MED.write_protected) SIM->get_param_bool(BXPN_FLOPPYB_READONLY)->set(1); #undef MED SIM->get_param_bool(BXPN_FLOPPYB_STATUS)->set(1); } return(1); } else { BX_FD_THIS s.media_present[drive] = 0; if (drive == 0) { SIM->get_param_bool(BXPN_FLOPPYA_STATUS)->set(0); SIM->get_param_enum(BXPN_FLOPPYA_TYPE)->set(BX_FLOPPY_NONE); } else { SIM->get_param_bool(BXPN_FLOPPYB_STATUS)->set(0); SIM->get_param_enum(BXPN_FLOPPYB_TYPE)->set(BX_FLOPPY_NONE); } return(0); } } } #ifdef O_BINARY #define BX_RDONLY O_RDONLY | O_BINARY #define BX_RDWR O_RDWR | O_BINARY #else #define BX_RDONLY O_RDONLY #define BX_RDWR O_RDWR #endif bx_bool bx_floppy_ctrl_c::evaluate_media(Bit8u devtype, Bit8u type, char *path, floppy_t *media) { struct stat stat_buf; int i, ret; int type_idx = -1; #ifdef __linux__ struct floppy_struct floppy_geom; #endif #ifdef WIN32 char sTemp[1024]; bx_bool raw_floppy = 0; HANDLE hFile; DWORD bytes; DISK_GEOMETRY dg; unsigned tracks = 0, heads = 0, spt = 0; #endif //If media file is already open, close it before reopening. close_media(media); // check media type if (type == BX_FLOPPY_NONE) { return 0; } for (i = 0; i < 8; i++) { if (type == floppy_type[i].id) type_idx = i; } if (type_idx == -1) { BX_ERROR(("evaluate_media: unknown media type %d", type)); return 0; } if ((floppy_type[type_idx].drive_mask & devtype) == 0) { BX_ERROR(("evaluate_media: media type %d not valid for this floppy drive", type)); return 0; } // use virtual VFAT support if requested if (!strncmp(path, "vvfat:", 6) && (devtype == FDRIVE_350HD)) { media->vvfat = DEV_hdimage_init_image(BX_HDIMAGE_MODE_VVFAT, 1474560, ""); if (media->vvfat != NULL) { if (media->vvfat->open(path + 6) == 0) { media->type = BX_FLOPPY_1_44; media->tracks = media->vvfat->cylinders; media->heads = media->vvfat->heads; media->sectors_per_track = media->vvfat->spt; media->sectors = 2880; media->vvfat_floppy = 1; media->fd = 0; } } if (media->vvfat_floppy) return 1; } // open media file (image file or device) #ifdef macintosh media->fd = 0; if (strcmp(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), SuperDrive)) #endif #ifdef WIN32 if ((isalpha(path[0])) && (path[1] == ':') && (strlen(path) == 2)) { raw_floppy = 1; wsprintf(sTemp, "\\\\.\\%s", path); hFile = CreateFile(sTemp, GENERIC_READ, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { BX_ERROR(("Cannot open floppy drive")); return(0); } if (!DeviceIoControl(hFile, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg), &bytes, NULL)) { BX_ERROR(("No media in floppy drive")); CloseHandle(hFile); return(0); } else { tracks = (unsigned)dg.Cylinders.QuadPart; heads = (unsigned)dg.TracksPerCylinder; spt = (unsigned)dg.SectorsPerTrack; } CloseHandle(hFile); if (!media->write_protected) media->fd = open(sTemp, BX_RDWR); else media->fd = open(sTemp, BX_RDONLY); } else #endif { if (!media->write_protected) media->fd = open(path, BX_RDWR); else media->fd = open(path, BX_RDONLY); } if (!media->write_protected && (media->fd < 0)) { BX_INFO(("tried to open '%s' read/write: %s",path,strerror(errno))); // try opening the file read-only media->write_protected = 1; #ifdef macintosh media->fd = 0; if (strcmp(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), SuperDrive)) #endif #ifdef WIN32 if (raw_floppy == 1) media->fd = open(sTemp, BX_RDONLY); else #endif media->fd = open(path, BX_RDONLY); if (media->fd < 0) { // failed to open read-only too BX_INFO(("tried to open '%s' read only: %s",path,strerror(errno))); media->type = type; return(0); } } #if BX_WITH_MACOS if (!strcmp(SIM->get_param_string(BXPN_FLOPPYA_PATH)->getptr(), SuperDrive)) ret = fd_stat(&stat_buf); else ret = fstat(media->fd, &stat_buf); #elif defined(WIN32) if (raw_floppy) { memset (&stat_buf, 0, sizeof(stat_buf)); stat_buf.st_mode = S_IFCHR; ret = 0; } else #endif { // unix ret = fstat(media->fd, &stat_buf); } if (ret) { BX_PANIC(("fstat floppy 0 drive image file returns error: %s", strerror(errno))); return(0); } if (S_ISREG(stat_buf.st_mode)) { // regular file switch (type) { // use CMOS reserved types case BX_FLOPPY_160K: // 160K 5.25" case BX_FLOPPY_180K: // 180K 5.25" case BX_FLOPPY_320K: // 320K 5.25" // standard floppy types case BX_FLOPPY_360K: // 360K 5.25" case BX_FLOPPY_720K: // 720K 3.5" case BX_FLOPPY_1_2: // 1.2M 5.25" case BX_FLOPPY_2_88: // 2.88M 3.5" media->type = type; media->tracks = floppy_type[type_idx].trk; media->heads = floppy_type[type_idx].hd; media->sectors_per_track = floppy_type[type_idx].spt; media->sectors = floppy_type[type_idx].sectors; if (stat_buf.st_size > (int)(media->sectors * 512)) { BX_ERROR(("evaluate_media: size of file '%s' (%lu) too large for selected type", path, (unsigned long) stat_buf.st_size)); return 0; } break; default: // 1.44M 3.5" media->type = type; if (stat_buf.st_size <= 1474560) { media->tracks = floppy_type[type_idx].trk; media->heads = floppy_type[type_idx].hd; media->sectors_per_track = floppy_type[type_idx].spt; } else if (stat_buf.st_size == 1720320) { media->sectors_per_track = 21; media->tracks = 80; media->heads = 2; } else if (stat_buf.st_size == 1763328) { media->sectors_per_track = 21; media->tracks = 82; media->heads = 2; } else if (stat_buf.st_size == 1884160) { media->sectors_per_track = 23; media->tracks = 80; media->heads = 2; } else { BX_ERROR(("evaluate_media: file '%s' of unknown size %lu", path, (unsigned long) stat_buf.st_size)); return 0; } media->sectors = media->heads * media->tracks * media->sectors_per_track; } return (media->sectors > 0); // success } else if (S_ISCHR(stat_buf.st_mode) #if BX_WITH_MACOS == 0 #ifdef S_ISBLK || S_ISBLK(stat_buf.st_mode) #endif #endif ) { // character or block device // assume media is formatted to typical geometry for drive media->type = type; #ifdef __linux__ if (ioctl(media->fd, FDGETPRM, &floppy_geom) < 0) { BX_ERROR(("cannot determine media geometry, trying to use defaults")); media->tracks = floppy_type[type_idx].trk; media->heads = floppy_type[type_idx].hd; media->sectors_per_track = floppy_type[type_idx].spt; media->sectors = floppy_type[type_idx].sectors; return (media->sectors > 0); } media->tracks = floppy_geom.track; media->heads = floppy_geom.head; media->sectors_per_track = floppy_geom.sect; media->sectors = floppy_geom.size; #elif defined(WIN32) media->tracks = tracks; media->heads = heads; media->sectors_per_track = spt; media->sectors = media->heads * media->tracks * media->sectors_per_track; #else media->tracks = floppy_type[type_idx].trk; media->heads = floppy_type[type_idx].hd; media->sectors_per_track = floppy_type[type_idx].spt; media->sectors = floppy_type[type_idx].sectors; #endif return (media->sectors > 0); // success } else { // unknown file type BX_ERROR(("unknown mode type")); return 0; } } void bx_floppy_ctrl_c::close_media(floppy_t *media) { if (media->fd >= 0) { if (media->vvfat_floppy) { media->vvfat->close(); delete media->vvfat; media->vvfat_floppy = 0; } else { close(media->fd); } media->fd = -1; } } void bx_floppy_ctrl_c::enter_result_phase(void) { Bit8u drive; unsigned i; drive = BX_FD_THIS s.DOR & 0x03; /* these are always the same */ BX_FD_THIS s.result_index = 0; // not necessary to clear any status bits, we're about to set them all BX_FD_THIS s.main_status_reg |= FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY; /* invalid command */ if ((BX_FD_THIS s.status_reg0 & 0xc0) == 0x80) { BX_FD_THIS s.result_size = 1; BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0; return; } switch (BX_FD_THIS s.pending_command) { case 0x04: // get status BX_FD_THIS s.result_size = 1; BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg3; break; case 0x08: // sense interrupt BX_FD_THIS s.result_size = 2; BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0; BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive]; break; case 0x0e: // dump registers BX_FD_THIS s.result_size = 10; for (i = 0; i < 4; i++) { BX_FD_THIS s.result[i] = BX_FD_THIS s.cylinder[i]; } BX_FD_THIS s.result[4] = (BX_FD_THIS s.SRT << 4) | BX_FD_THIS s.HUT; BX_FD_THIS s.result[5] = (BX_FD_THIS s.HLT << 1) | ((BX_FD_THIS s.main_status_reg & FD_MS_NDMA) ? 1 : 0); BX_FD_THIS s.result[6] = BX_FD_THIS s.eot[drive]; BX_FD_THIS s.result[7] = (BX_FD_THIS s.lock << 7) | (BX_FD_THIS s.perp_mode & 0x7f); BX_FD_THIS s.result[8] = BX_FD_THIS s.config; BX_FD_THIS s.result[9] = BX_FD_THIS s.pretrk; break; case 0x10: // version BX_FD_THIS s.result_size = 1; BX_FD_THIS s.result[0] = 0x90; break; case 0x14: // unlock case 0x94: // lock BX_FD_THIS s.lock = (BX_FD_THIS s.pending_command >> 7); BX_FD_THIS s.result_size = 1; BX_FD_THIS s.result[0] = (BX_FD_THIS s.lock << 4); break; case 0x4a: // read ID case 0x4d: // format track case 0x46: // read normal data case 0x66: case 0xc6: case 0xe6: case 0x45: // write normal data case 0xc5: BX_FD_THIS s.result_size = 7; BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0; BX_FD_THIS s.result[1] = BX_FD_THIS s.status_reg1; BX_FD_THIS s.result[2] = BX_FD_THIS s.status_reg2; BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive]; BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive]; BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive]; BX_FD_THIS s.result[6] = 2; /* sector size code */ BX_FD_THIS raise_interrupt(); break; } // Print command result (max. 10 bytes) char buf[8+(10*5)+1], *p = buf; p += sprintf(p, "RESULT: "); for (i=0; i= 512 makes it more robust, but allows for sloppy code... * pick your poison? * note: byte and head are 0-based; eot, sector, and heads are 1-based. */ terminal_count = ((BX_FD_THIS s.floppy_buffer_index == 512) && (BX_FD_THIS s.sector[drive] == BX_FD_THIS s.eot[drive]) && (BX_FD_THIS s.head[drive] == (BX_FD_THIS s.media[drive].heads - 1))); } else { terminal_count = DEV_dma_get_tc(); } return terminal_count; } // floppy runtime parameter handling Bit64s bx_floppy_ctrl_c::floppy_param_handler(bx_param_c *param, int set, Bit64s val) { bx_list_c *base = (bx_list_c*) param->get_parent(); Bit8u drive; if (set) { drive = atoi(base->get_name()); if (!strcmp(param->get_name(), "status")) { BX_FD_THIS s.media[drive].status_changed = 1; } else if (!strcmp(param->get_name(), "readonly")) { BX_FD_THIS s.media[drive].write_protected = (bx_bool)val; BX_FD_THIS s.media[drive].status_changed = 1; } } return val; } const char* bx_floppy_ctrl_c::floppy_param_string_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { char pname[BX_PATHNAME_LEN]; Bit8u drive; bx_list_c *base = (bx_list_c*) param->get_parent(); if ((strlen(val) < 1) || !strcmp ("none", val)) { val = "none"; } param->get_param_path(pname, BX_PATHNAME_LEN); if ((!strcmp(pname, BXPN_FLOPPYA_PATH)) || (!strcmp(pname, BXPN_FLOPPYB_PATH))) { if (set==1) { drive = atoi(base->get_name()); if (SIM->get_param_enum("devtype", base)->get() == BX_FDD_NONE) { BX_ERROR(("Cannot add a floppy drive at runtime")); SIM->get_param_string("path", base)->set("none"); } if (SIM->get_param_bool("status", base)->get() == 1) { // tell the device model that we removed, then inserted the disk BX_FD_THIS s.media[drive].status_changed = 1; } } } else { BX_PANIC(("floppy_param_string_handler called with unknown parameter '%s'", pname)); } return val; } #if BX_DEBUGGER void bx_floppy_ctrl_c::debug_dump(int argc, char **argv) { int i; dbg_printf("i82077AA FDC\n\n"); for (i = 0; i < 2; i++) { dbg_printf("fd%d: ", i); if (BX_FD_THIS s.device_type[i] == FDRIVE_NONE) { dbg_printf("not installed\n"); } else if (BX_FD_THIS s.media[i].type == BX_FLOPPY_NONE) { dbg_printf("media not present\n"); } else { #define MED (BX_FD_THIS s.media[i]) dbg_printf("tracks=%d, heads=%d, spt=%d, readonly=%d\n", MED.tracks, MED.heads, MED.sectors_per_track, MED.write_protected); #undef MED } } dbg_printf("\ncontroller status: "); if (BX_FD_THIS s.pending_command == 0) { if (BX_FD_THIS s.command_complete) { dbg_printf("idle phase\n"); } else { dbg_printf("command phase (command=0x%02x)\n", BX_FD_THIS s.command[0]); } } else { if (BX_FD_THIS s.result_size == 0) { dbg_printf("execution phase (command=0x%02x)\n", BX_FD_THIS s.pending_command); } else { dbg_printf("result phase (command=0x%02x)\n", BX_FD_THIS s.pending_command); } } dbg_printf("DOR = 0x%02x\n", BX_FD_THIS s.DOR); dbg_printf("MSR = 0x%02x\n", BX_FD_THIS s.main_status_reg); dbg_printf("DSR = 0x%02x\n", BX_FD_THIS s.data_rate); if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif bochs-2.6/iodev/slowdown_timer.h0000644000175000017500000000302512020641505016663 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: slowdown_timer.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef BX_IODEV_SLOWDOWN_TIMER_H #define BX_IODEV_SLOWDOWN_TIMER_H class bx_slowdown_timer_c : public logfunctions { private: struct { Bit64u start_time; Bit64u start_emulated_time; Bit64u lasttime; int timer_handle; float MAXmultiplier; Bit64u Q; // sleep rate in usec } s; public: bx_slowdown_timer_c(); void init(void); void exit(void); void after_restore_state(void); static void timer_handler(void * this_ptr); void handle_timer(); }; extern bx_slowdown_timer_c bx_slowdown_timer; #endif bochs-2.6/iodev/virt_timer.cc0000644000175000017500000004323012020641505016133 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: virt_timer.cc 11183 2012-05-17 09:11:48Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA //////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////// // //Realtime Algorithm (with gettimeofday) // HAVE: // Real number of usec. // Emulated number of usec. // WANT: // Number of ticks to use. // Number of emulated usec to wait until next try. // // ticks=number of ticks needed to match total real usec. // if(desired ticks > max ticks for elapsed real time) // ticks = max ticks for elapsed real time. // if(desired ticks > max ticks for elapsed emulated usec) // ticks = max ticks for emulated usec. // next wait ticks = number of ticks until next event. // next wait real usec = (current ticks + next wait ticks) * usec per ticks // next wait emulated usec = next wait real usec * emulated usec / real usec // if(next wait emulated usec < minimum emulated usec for next wait ticks) // next wait emulated usec = minimum emulated usec for next wait ticks. // if(next wait emulated usec > max emulated usec wait) // next wait emulated usec = max emulated usec wait. // // How to calculate elapsed real time: // store an unused time value whenever no ticks are used in a given time. // add this to the current elapsed time. // How to calculate elapsed emulated time: // same as above. // Above can be done by not updating last_usec and last_sec. // // How to calculate emulated usec/real usec: // Each time there are actual ticks: // Alpha_product(old emulated usec, emulated usec); // Alpha_product(old real usec, real usec); // Divide resulting values. // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "param_names.h" #include "virt_timer.h" //Important constant #defines: #define USEC_PER_SECOND (1000000) // define a macro to convert floating point numbers into 64-bit integers. // In MSVC++ you can convert a 64-bit float into a 64-bit signed integer, // but it will not convert a 64-bit float into a 64-bit unsigned integer. // This macro works around that. #define F2I(x) ((Bit64u)(Bit64s) (x)) #define I2F(x) ((double)(Bit64s) (x)) //CONFIGURATION #defines: //MAINLINE Configuration (For realtime PIT): //How much faster than real time we can go: #define MAX_MULT (1.25) //Minimum number of emulated useconds per second. // Now calculated using BX_MIN_IPS, the minimum number of // instructions per second. #define MIN_USEC_PER_SECOND (((((Bit64u)USEC_PER_SECOND)*((Bit64u)BX_MIN_IPS))/((Bit64u)ips))+(Bit64u)1) //DEBUG configuration: //Debug with printf options. #define DEBUG_REALTIME_WITH_PRINTF 0 #define GET_VIRT_REALTIME64_USEC() (bx_get_realtime64_usec()) //Set up Logging. #define LOG_THIS bx_virt_timer. //A single instance. bx_virt_timer_c bx_virt_timer; //USEC_ALPHA is multiplier for the past. //USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present. #define USEC_ALPHA ((double)(.8)) #define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA)) #define USEC_ALPHA2 ((double)(.5)) #define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2)) #define ALPHA_LOWER(old,new) ((Bit64u)((old0); BX_ASSERT(!in_timer_handler); if (last_sequential_time >= current_timers_time) { periodic(1); last_sequential_time = current_timers_time; } return current_timers_time; } //Register a timer handler to go off after a given interval. //Register a timer handler to go off with a periodic interval. int bx_virt_timer_c::register_timer(void *this_ptr, bx_timer_handler_t handler, Bit32u useconds, bx_bool continuous, bx_bool active, const char *id) { //We don't like starting with a zero period timer. BX_ASSERT((!active) || (useconds>0)); //Search for an unused timer. unsigned int i; for (i=0; i < numTimers; i++) { if ((timer[i].inUse == 0) || (i == numTimers)) break; } // If we didn't find a free slot, increment the bound, numTimers. if (i == numTimers) numTimers++; // One new timer installed. BX_ASSERT(numTimers0); timer[timer_index].period = useconds; timer[timer_index].timeToFire = current_timers_time + (Bit64u)useconds; timer[timer_index].active = 1; timer[timer_index].continuous = continuous; if (useconds < timers_next_event_time) { timers_next_event_time = useconds; next_event_time_update(); //FIXME } } //deactivate (but don't unregister) a currently registered timer. void bx_virt_timer_c::deactivate_timer(unsigned timer_index) { BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS); //No need to prevent doing this to unused/inactive timers. timer[timer_index].active = 0; } void bx_virt_timer_c::advance_virtual_time(Bit64u time_passed) { BX_ASSERT(time_passed <= virtual_next_event_time); current_virtual_time += time_passed; virtual_next_event_time -= time_passed; if (current_virtual_time > current_timers_time) { periodic(current_virtual_time - current_timers_time); } } //Called when next_event_time changes. void bx_virt_timer_c::next_event_time_update(void) { virtual_next_event_time = timers_next_event_time + current_timers_time - current_virtual_time; if (init_done) { bx_pc_system.deactivate_timer(system_timer_id); BX_ASSERT(virtual_next_event_time); bx_pc_system.activate_timer(system_timer_id, (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))), 0); } } void bx_virt_timer_c::setup(void) { numTimers = 0; current_timers_time = 0; timers_next_event_time = BX_MAX_VIRTUAL_TIME; last_sequential_time = 0; in_timer_handler = 0; virtual_next_event_time = BX_MAX_VIRTUAL_TIME; current_virtual_time = 0; init_done = 0; } void bx_virt_timer_c::init(void) { if ((SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()!=BX_CLOCK_SYNC_REALTIME) && (SIM->get_param_enum(BXPN_CLOCK_SYNC)->get()!=BX_CLOCK_SYNC_BOTH)) virtual_timers_realtime = 0; else virtual_timers_realtime = 1; if (virtual_timers_realtime) { BX_INFO(("using 'realtime pit' synchronization method")); } // Local copy of IPS value to avoid reading it frequently in timer handler ips = SIM->get_param_num(BXPN_IPS)->get(); register_timer(this, nullTimer, (Bit32u)NullTimerInterval, 1, 1, "Null Timer"); system_timer_id = bx_pc_system.register_timer(this, pc_system_timer_handler, (Bit32u)virtual_next_event_time, 0, 1, "Virtual Timer"); //Real time variables: #if BX_HAVE_REALTIME_USEC last_real_time = GET_VIRT_REALTIME64_USEC(); #endif total_real_usec = 0; last_realtime_delta = 0; real_time_delay = 0; //System time variables: last_usec = 0; usec_per_second = USEC_PER_SECOND; stored_delta = 0; last_system_usec = 0; em_last_realtime = 0; //Virtual timer variables: total_ticks = 0; last_realtime_ticks = 0; ticks_per_second = USEC_PER_SECOND; init_done = 1; } void bx_virt_timer_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "virt_timer", "Virtual Timer State"); bx_list_c *vtimers = new bx_list_c(list, "timer"); for (unsigned i = 0; i < numTimers; i++) { char name[4]; sprintf(name, "%d", i); bx_list_c *bxtimer = new bx_list_c(vtimers, name); BXRS_PARAM_BOOL(bxtimer, inUse, timer[i].inUse); BXRS_DEC_PARAM_FIELD(bxtimer, period, timer[i].period); BXRS_DEC_PARAM_FIELD(bxtimer, timeToFire, timer[i].timeToFire); BXRS_PARAM_BOOL(bxtimer, active, timer[i].active); BXRS_PARAM_BOOL(bxtimer, continuous, timer[i].continuous); } BXRS_DEC_PARAM_SIMPLE(list, current_timers_time); BXRS_DEC_PARAM_SIMPLE(list, timers_next_event_time); BXRS_DEC_PARAM_SIMPLE(list, last_sequential_time); BXRS_DEC_PARAM_SIMPLE(list, virtual_next_event_time); BXRS_DEC_PARAM_SIMPLE(list, current_virtual_time); BXRS_DEC_PARAM_SIMPLE(list, last_real_time); BXRS_DEC_PARAM_SIMPLE(list, total_real_usec); BXRS_DEC_PARAM_SIMPLE(list, last_realtime_delta); BXRS_DEC_PARAM_SIMPLE(list, last_usec); BXRS_DEC_PARAM_SIMPLE(list, usec_per_second); BXRS_DEC_PARAM_SIMPLE(list, stored_delta); BXRS_DEC_PARAM_SIMPLE(list, last_system_usec); BXRS_DEC_PARAM_SIMPLE(list, em_last_realtime); BXRS_DEC_PARAM_SIMPLE(list, total_ticks); BXRS_DEC_PARAM_SIMPLE(list, last_realtime_ticks); BXRS_DEC_PARAM_SIMPLE(list, ticks_per_second); } void bx_virt_timer_c::timer_handler(void) { if (!virtual_timers_realtime) { Bit64u temp_final_time = bx_pc_system.time_usec(); temp_final_time -= current_virtual_time; while (temp_final_time) { if ((temp_final_time)>(virtual_next_event_time)) { temp_final_time -= virtual_next_event_time; advance_virtual_time(virtual_next_event_time); } else { advance_virtual_time(temp_final_time); temp_final_time -= temp_final_time; } } bx_pc_system.activate_timer(system_timer_id, (Bit32u)BX_MIN(0x7FFFFFFF,(virtual_next_event_time>2)?(virtual_next_event_time-2):1), 0); return; } Bit64u usec_delta = bx_pc_system.time_usec()-last_usec; if (usec_delta) { #if BX_HAVE_REALTIME_USEC Bit64u ticks_delta = 0; Bit64u real_time_delta = GET_VIRT_REALTIME64_USEC() - last_real_time - real_time_delay; Bit64u real_time_total = real_time_delta + total_real_usec; Bit64u system_time_delta = (Bit64u)usec_delta + (Bit64u)stored_delta; if (real_time_delta) { last_realtime_delta = real_time_delta; last_realtime_ticks = total_ticks; } ticks_per_second = USEC_PER_SECOND; //Start out with the number of ticks we would like // to have to line up with real time. ticks_delta = real_time_total - total_ticks; if (real_time_total < total_ticks) { //This slows us down if we're already ahead. // probably only an issue on startup, but it solves some problems. ticks_delta = 0; } if (ticks_delta + total_ticks - last_realtime_ticks > (F2I(MAX_MULT * I2F(last_realtime_delta)))) { //This keeps us from going too fast in relation to real time. #if 0 ticks_delta = (F2I(MAX_MULT * I2F(last_realtime_delta))) + last_realtime_ticks - total_ticks; #endif ticks_per_second = F2I(MAX_MULT * I2F(USEC_PER_SECOND)); } if (ticks_delta > system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND) { //This keeps us from having too few instructions between ticks. ticks_delta = system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND; } if (ticks_delta > virtual_next_event_time) { //This keeps us from missing ticks. ticks_delta = virtual_next_event_time; } if (ticks_delta) { # if DEBUG_REALTIME_WITH_PRINTF //Every second print some info. if (((last_real_time + real_time_delta) / USEC_PER_SECOND) > (last_real_time / USEC_PER_SECOND)) { Bit64u temp1, temp2, temp3, temp4; temp1 = (Bit64u) total_real_usec; temp2 = (total_real_usec); temp3 = (Bit64u)total_ticks; temp4 = (Bit64u)((total_real_usec) - total_ticks); printf("useconds: " FMT_LL "u, ", temp1); printf("expect ticks: " FMT_LL "u, ", temp2); printf("ticks: " FMT_LL "u, ", temp3); printf("diff: "FMT_LL "u\n", temp4); } # endif last_real_time += real_time_delta; total_real_usec += real_time_delta; last_system_usec += system_time_delta; stored_delta = 0; total_ticks += ticks_delta; } else { stored_delta = system_time_delta; } Bit64u a = usec_per_second, b; if (real_time_delta) { //FIXME Bit64u em_realtime_delta = last_system_usec + stored_delta - em_last_realtime; b=((Bit64u)USEC_PER_SECOND * em_realtime_delta / real_time_delta); em_last_realtime = last_system_usec + stored_delta; } else { b=a; } usec_per_second = ALPHA_LOWER(a,b); #else BX_ASSERT(0); #endif #if BX_HAVE_REALTIME_USEC advance_virtual_time(ticks_delta); #endif } last_usec=last_usec + usec_delta; bx_pc_system.deactivate_timer(system_timer_id); BX_ASSERT(virtual_next_event_time); bx_pc_system.activate_timer(system_timer_id, (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))), 0); } void bx_virt_timer_c::pc_system_timer_handler(void* this_ptr) { ((bx_virt_timer_c *)this_ptr)->timer_handler(); } void bx_virt_timer_c::set_realtime_delay() { if (virtual_timers_realtime) { real_time_delay = GET_VIRT_REALTIME64_USEC() - last_real_time; } } bochs-2.6/iodev/speaker.h0000644000175000017500000000343212020641505015243 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: speaker.h 11195 2012-05-24 18:06:40Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright 2003 by David N. Welton . // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* * This file defines a class to deal with the speaker. * This class also tries to play beeps on the console * (linux only) and also forwards beeps to the gui * so we have the possiblity to signal the beep */ #ifndef BX_PC_SPEAKER_H #define BX_PC_SPEAKER_H class bx_speaker_c : public bx_speaker_stub_c { public: bx_speaker_c(); virtual ~bx_speaker_c(); virtual void init(void); virtual void reset(unsigned int); void beep_on(float frequency); void beep_off(); private: float beep_frequency; // 0 : beep is off bx_bool outputinit; #ifdef __linux__ /* Do we have access? If not, just skip everything else. */ signed int consolefd; const static unsigned int clock_tick_rate = 1193180; #elif defined(WIN32) Bit64u usec_start; #endif }; #endif bochs-2.6/iodev/pci.cc0000644000175000017500000004307412020641505014530 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pci.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // i440FX Support - PMC/DBX // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI #include "pci.h" #define LOG_THIS thePciBridge-> bx_pci_bridge_c *thePciBridge = NULL; int libpci_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { thePciBridge = new bx_pci_bridge_c(); bx_devices.pluginPciBridge = thePciBridge; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePciBridge, BX_PLUGIN_PCI); return 0; // Success } else { return -1; } } void libpci_LTX_plugin_fini(void) { delete thePciBridge; } bx_pci_bridge_c::bx_pci_bridge_c() { put("PCI"); } bx_pci_bridge_c::~bx_pci_bridge_c() { SIM->get_bochs_root()->remove("pci_bridge"); BX_DEBUG(("Exit")); } void bx_pci_bridge_c::init(void) { // called once when bochs initializes unsigned i; BX_PCI_THIS num_pci_handlers = 0; /* set unused elements to appropriate values */ for (i=0; i < BX_MAX_PCI_DEVICES; i++) { BX_PCI_THIS pci_handler[i].handler = NULL; } for (i=0; i < 0x100; i++) { BX_PCI_THIS pci_handler_id[i] = BX_MAX_PCI_DEVICES; // not assigned } for (i=0; i < BX_N_PCI_SLOTS; i++) { BX_PCI_THIS slot_used[i] = 0; // no device connected } BX_PCI_THIS slots_checked = 0; // confAddr accepts dword i/o only DEV_register_ioread_handler(this, read_handler, 0x0CF8, "i440FX", 4); DEV_register_iowrite_handler(this, write_handler, 0x0CF8, "i440FX", 4); for (i=0x0CFC; i<=0x0CFF; i++) { DEV_register_ioread_handler(this, read_handler, i, "i440FX", 7); DEV_register_iowrite_handler(this, write_handler, i, "i440FX", 7); } Bit8u devfunc = BX_PCI_DEVICE(0,0); DEV_register_pci_handlers(this, &devfunc, BX_PLUGIN_PCI, "440FX Host bridge"); for (i=0; i<256; i++) BX_PCI_THIS pci_conf[i] = 0x0; // readonly registers BX_PCI_THIS pci_conf[0x00] = 0x86; BX_PCI_THIS pci_conf[0x01] = 0x80; BX_PCI_THIS pci_conf[0x02] = 0x37; BX_PCI_THIS pci_conf[0x03] = 0x12; BX_PCI_THIS pci_conf[0x0b] = 0x06; #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("pci", this); #endif } void bx_pci_bridge_c::reset(unsigned type) { unsigned i; char devname[80]; char *device; if (!BX_PCI_THIS slots_checked) { for (i=0; iget_param_string(devname)->getptr(); if ((strlen(device) > 0) && !BX_PCI_THIS slot_used[i]) { BX_PANIC(("Unknown plugin '%s' at PCI slot #%d", device, i+1)); } } BX_PCI_THIS slots_checked = 1; } BX_PCI_THIS confAddr = 0; BX_PCI_THIS confData = 0; BX_PCI_THIS pci_conf[0x04] = 0x06; BX_PCI_THIS pci_conf[0x05] = 0x00; BX_PCI_THIS pci_conf[0x06] = 0x80; BX_PCI_THIS pci_conf[0x07] = 0x02; BX_PCI_THIS pci_conf[0x0d] = 0x00; BX_PCI_THIS pci_conf[0x0f] = 0x00; BX_PCI_THIS pci_conf[0x50] = 0x00; BX_PCI_THIS pci_conf[0x51] = 0x01; BX_PCI_THIS pci_conf[0x52] = 0x00; BX_PCI_THIS pci_conf[0x53] = 0x80; BX_PCI_THIS pci_conf[0x54] = 0x00; BX_PCI_THIS pci_conf[0x55] = 0x00; BX_PCI_THIS pci_conf[0x56] = 0x00; BX_PCI_THIS pci_conf[0x57] = 0x01; BX_PCI_THIS pci_conf[0x58] = 0x10; for (i=0x59; i<0x60; i++) BX_PCI_THIS pci_conf[i] = 0x00; BX_PCI_THIS pci_conf[0x72] = 0x02; } void bx_pci_bridge_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "pci_bridge", "PCI Bridge State"); BXRS_HEX_PARAM_FIELD(list, confAddr, BX_PCI_THIS confAddr); BXRS_HEX_PARAM_FIELD(list, confData, BX_PCI_THIS confData); register_pci_state(list); } void bx_pci_bridge_c::after_restore_state(void) { BX_PCI_THIS smram_control(BX_PCI_THIS pci_conf[0x72]); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_pci_bridge_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_PCI_SMF bx_pci_bridge_c *class_ptr = (bx_pci_bridge_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_pci_bridge_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PCI_SMF switch (address) { case 0x0CF8: return BX_PCI_THIS confAddr; case 0x0CFC: case 0x0CFD: case 0x0CFE: case 0x0CFF: { Bit32u handle, retval; Bit8u devfunc, regnum; if ((BX_PCI_THIS confAddr & 0x80FF0000) == 0x80000000) { devfunc = (BX_PCI_THIS confAddr >> 8) & 0xff; regnum = (BX_PCI_THIS confAddr & 0xfc) + (address & 0x03); handle = BX_PCI_THIS pci_handler_id[devfunc]; if ((io_len <= 4) && (handle < BX_MAX_PCI_DEVICES)) retval = BX_PCI_THIS pci_handler[handle].handler->pci_read_handler(regnum, io_len); else retval = 0xFFFFFFFF; } else retval = 0xFFFFFFFF; BX_PCI_THIS confData = retval; return retval; } } BX_PANIC(("unsupported IO read to port 0x%x", (unsigned) address)); return(0xffffffff); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_pci_bridge_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_PCI_SMF bx_pci_bridge_c *class_ptr = (bx_pci_bridge_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_pci_bridge_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PCI_SMF switch (address) { case 0xCF8: BX_PCI_THIS confAddr = value; if ((value & 0x80FFFF00) == 0x80000000) { BX_DEBUG(("440FX PMC register 0x%02x selected", value & 0xfc)); } else if ((value & 0x80000000) == 0x80000000) { BX_DEBUG(("440FX request for bus 0x%02x device 0x%02x function 0x%02x", (value >> 16) & 0xFF, (value >> 11) & 0x1F, (value >> 8) & 0x07)); } break; case 0xCFC: case 0xCFD: case 0xCFE: case 0xCFF: if ((BX_PCI_THIS confAddr & 0x80FF0000) == 0x80000000) { Bit8u devfunc = (BX_PCI_THIS confAddr >> 8) & 0xff; Bit8u regnum = (BX_PCI_THIS confAddr & 0xfc) + (address & 0x03); Bit32u handle = BX_PCI_THIS pci_handler_id[devfunc]; if ((io_len <= 4) && (handle < BX_MAX_PCI_DEVICES)) { if (((regnum>=4) && (regnum<=7)) || (regnum==12) || (regnum==13) || (regnum>14)) { BX_PCI_THIS pci_handler[handle].handler->pci_write_handler(regnum, value, io_len); BX_PCI_THIS confData = value << (8 * (address & 0x03)); } else BX_DEBUG(("read only register, write ignored")); } } break; default: BX_PANIC(("IO write to port 0x%x", (unsigned) address)); } } // pci configuration space read callback handler Bit32u bx_pci_bridge_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x10) && (address < 0x34)) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_PCI_THIS pci_conf[address+i]; switch (address+i) { case 0x04: BX_PCI_THIS pci_conf[address+i] = (value8 & 0x40) | 0x06; break; case 0x06: case 0x0c: break; case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: if (value != oldval) { BX_PCI_THIS pci_conf[address+i] = value8; if ((address+i) == 0x59) { area = BX_MEM_AREA_F0000; DEV_mem_set_memory_type(area, 0, (value >> 4) & 0x1); DEV_mem_set_memory_type(area, 1, (value >> 5) & 0x1); } else { area = ((address+i) - 0x5a) << 1; DEV_mem_set_memory_type(area, 0, (value >> 0) & 0x1); DEV_mem_set_memory_type(area, 1, (value >> 1) & 0x1); area++; DEV_mem_set_memory_type(area, 0, (value >> 4) & 0x1); DEV_mem_set_memory_type(area, 1, (value >> 5) & 0x1); } BX_INFO(("440FX PMC write to PAM register %x (TLB Flush)", address+i)); bx_pc_system.MemoryMappingChanged(); } break; case 0x72: smram_control(value); // SMRAM conrol register break; default: BX_PCI_THIS pci_conf[address+i] = value8; BX_DEBUG(("440FX PMC write register 0x%02x value 0x%02x", address+i, value8)); } } } void bx_pci_bridge_c::smram_control(Bit8u value8) { // // From i440FX chipset manual: // // [7:7] Reserved. // [6:6] SMM Space Open (DOPEN), when DOPEN=1 and DLCK=0, SMM space DRAM // became visible even CPU not indicte SMM mode access. This is // indended to help BIOS to initialize SMM space. // [5:5] SMM Space Closed (DCLS), when DCLS=1, SMM space is not accessible // for data references, even if CPU indicates SMM mode access. Code // references may still access SMM space DRAM. // [4:4] SMM Space Locked (DLCK), when DLCK=1, DOPEN is set to 0 and // both DLCK and DOPEN became R/O. DLCK can only be cleared by // a power-on reset. // [3:3] SMRAM Enable (SMRAME) // [2:0] SMM space base segment, program the location of SMM space // reserved. // // SMRAM space access cycles: // | SMRAME | DLCK | DCLS | DOPEN | CPU_SMM | | Code | Data | // ------------------------------------------ --------------- // | 0 | X | X | X | X | -> | PCI | PCI | // | 1 | 0 | X | 0 | 0 | -> | PCI | PCI | // | 1 | 0 | 0 | 0 | 1 | -> | DRAM | DRAM | // | 1 | 0 | 0 | 1 | X | -> | DRAM | DRAM | // | 1 | 1 | 0 | X | 1 | -> | DRAM | DRAM | // | 1 | 0 | 1 | 0 | 1 | -> | DRAM | PCI | // | 1 | 0 | 1 | 1 | X | -> | ---- | ---- | // | 1 | 1 | X | X | 0 | -> | PCI | PCI | // | 1 | 1 | 1 | X | 1 | -> | DRAM | PCI | // ------------------------------------------ --------------- value8 = (value8 & 0x78) | 0x2; // ignore reserved bits if (BX_PCI_THIS pci_conf[0x72] & 0x10) { value8 &= 0xbf; // set DOPEN=0, DLCK=1 value8 |= 0x10; } if ((value8 & 0x08) == 0) { bx_devices.mem->disable_smram(); } else { bx_bool DOPEN = (value8 & 0x40) > 0, DCLS = (value8 & 0x20) > 0; if(DOPEN && DCLS) BX_PANIC(("SMRAM control: DOPEN not mutually exclusive with DCLS !")); bx_devices.mem->enable_smram(DOPEN, DCLS); } BX_INFO(("setting SMRAM control register to 0x%02x", value8)); BX_PCI_THIS pci_conf[0x72] = value8; } #if BX_DEBUGGER void bx_pci_bridge_c::debug_dump(int argc, char **argv) { int arg, i, j, r; dbg_printf("i440FX PMC/DBX\n\n"); dbg_printf("confAddr = 0x%08x\n", BX_PCI_THIS confAddr); dbg_printf("confData = 0x%08x\n", BX_PCI_THIS confData); if (argc == 0) { for (i = 0x59; i < 0x60; i++) { dbg_printf("PAM reg 0x%02x = 0x%02x\n", i, BX_PCI_THIS pci_conf[i]); } dbg_printf("SMRAM control = 0x%02x\n", BX_PCI_THIS pci_conf[0x72]); dbg_printf("\nSupported options:\n"); dbg_printf("info device 'pci' 'dump=full' - show PCI config space\n"); } else { for (arg = 0; arg < argc; arg++) { if (!strcmp(argv[arg], "dump=full")) { dbg_printf("\nPCI config space\n\n"); r = 0; for (i=0; i<16; i++) { dbg_printf("%04x ", r); for (j=0; j<16; j++) { dbg_printf(" %02x", BX_PCI_THIS pci_conf[r++]); } dbg_printf("\n"); } } else { dbg_printf("\nUnknown option: '%s'\n", argv[arg]); } } } } #endif bx_bool bx_pci_bridge_c::register_pci_handlers(bx_pci_device_stub_c *dev, Bit8u *devfunc, const char *name, const char *descr) { unsigned i, handle; int first_free_slot = -1; char devname[80]; char *device; if (strcmp(name, "pci") && strcmp(name, "pci2isa") && strcmp(name, "pci_ide") && (*devfunc == 0x00)) { for (i = 0; i < BX_N_PCI_SLOTS; i++) { sprintf(devname, "pci.slot.%d", i+1); device = SIM->get_param_string(devname)->getptr(); if (strlen(device) > 0) { if (!strcmp(name, device)) { *devfunc = (i + 2) << 3; BX_PCI_THIS slot_used[i] = 1; BX_INFO(("PCI slot #%d used by plugin '%s'", i+1, name)); break; } } else if (first_free_slot == -1) { first_free_slot = i; } } if (*devfunc == 0x00) { // auto-assign device to PCI slot if possible if (first_free_slot != -1) { i = (unsigned)first_free_slot; sprintf(devname, "pci.slot.%d", i+1); SIM->get_param_string(devname)->set(name); *devfunc = (i + 2) << 3; BX_PCI_THIS slot_used[i] = 1; BX_INFO(("PCI slot #%d used by plugin '%s'", i+1, name)); } else { BX_ERROR(("Plugin '%s' not connected to a PCI slot", name)); return 0; } } } /* check if device/function is available */ if (BX_PCI_THIS pci_handler_id[*devfunc] == BX_MAX_PCI_DEVICES) { if (BX_PCI_THIS num_pci_handlers >= BX_MAX_PCI_DEVICES) { BX_INFO(("too many PCI devices installed.")); BX_PANIC((" try increasing BX_MAX_PCI_DEVICES")); return 0; } handle = BX_PCI_THIS num_pci_handlers++; BX_PCI_THIS pci_handler[handle].handler = dev; BX_PCI_THIS pci_handler_id[*devfunc] = handle; BX_INFO(("%s present at device %d, function %d", descr, *devfunc >> 3, *devfunc & 0x07)); return 1; // device/function mapped successfully } else { return 0; // device/function not available, return false. } } bx_bool bx_pci_bridge_c::is_pci_device(const char *name) { unsigned i; char devname[80]; char *device; for (i = 0; i < BX_N_PCI_SLOTS; i++) { sprintf(devname, "pci.slot.%d", i+1); device = SIM->get_param_string(devname)->getptr(); if ((strlen(device) > 0) && (!strcmp(name, device))) { return 1; } } return 0; } bx_bool bx_pci_bridge_c::pci_set_base_mem(void *this_ptr, memory_handler_t f1, memory_handler_t f2, Bit32u *addr, Bit8u *pci_conf, unsigned size) { Bit32u newbase; Bit32u oldbase = *addr; Bit32u mask = ~(size - 1); Bit8u pci_flags = pci_conf[0x00] & 0x0f; if ((pci_flags & 0x06) > 0) { BX_PANIC(("PCI base memory flag 0x%02x not supported", pci_flags)); return 0; } pci_conf[0x00] &= (mask & 0xf0); pci_conf[0x01] &= (mask >> 8) & 0xff; pci_conf[0x02] &= (mask >> 16) & 0xff; pci_conf[0x03] &= (mask >> 24) & 0xff; ReadHostDWordFromLittleEndian(pci_conf, newbase); pci_conf[0x00] |= pci_flags; if (newbase != mask && newbase != oldbase) { // skip PCI probe if (oldbase > 0) { DEV_unregister_memory_handlers(this_ptr, oldbase, oldbase + size - 1); } if (newbase > 0) { DEV_register_memory_handlers(this_ptr, f1, f2, newbase, newbase + size - 1); } *addr = newbase; return 1; } return 0; } bx_bool bx_pci_bridge_c::pci_set_base_io(void *this_ptr, bx_read_handler_t f1, bx_write_handler_t f2, Bit32u *addr, Bit8u *pci_conf, unsigned size, const Bit8u *iomask, const char *name) { unsigned i; Bit32u newbase; Bit32u oldbase = *addr; Bit16u mask = ~(size - 1); Bit8u pci_flags = pci_conf[0x00] & 0x03; pci_conf[0x00] &= (mask & 0xfc); pci_conf[0x01] &= (mask >> 8); ReadHostDWordFromLittleEndian(pci_conf, newbase); pci_conf[0x00] |= pci_flags; if (((newbase & 0xfffc) != mask) && (newbase != oldbase)) { // skip PCI probe if (oldbase > 0) { for (i=0; i 0) { DEV_unregister_ioread_handler(this_ptr, f1, oldbase + i, iomask[i]); DEV_unregister_iowrite_handler(this_ptr, f2, oldbase + i, iomask[i]); } } } if (newbase > 0) { for (i=0; i 0) { DEV_register_ioread_handler(this_ptr, f1, newbase + i, name, iomask[i]); DEV_register_iowrite_handler(this_ptr, f2, newbase + i, name, iomask[i]); } } } *addr = newbase; return 1; } return 0; } #endif /* BX_SUPPORT_PCI */ bochs-2.6/iodev/gameport.h0000644000175000017500000000375412020641505015436 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: gameport.h 10289 2011-03-31 16:54:06Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2003-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef BX_IODEV_GAMEPORT_H #define BX_IODEV_GAMEPORT_H #if BX_USE_GAMEPORT_SMF # define BX_GAMEPORT_SMF static # define BX_GAMEPORT_THIS theGameport-> #else # define BX_GAMEPORT_SMF # define BX_GAMEPORT_THIS this-> #endif class bx_gameport_c : public bx_game_stub_c { public: bx_gameport_c(); virtual ~bx_gameport_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); virtual void set_enabled(bx_bool val) {enabled = val;} private: bx_bool enabled; int joyfd; Bit8u port; Bit16u delay_x; Bit16u delay_y; bx_bool timer_x; bx_bool timer_y; Bit64u write_usec; BX_GAMEPORT_SMF void poll_joydev(void); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_GAMEPORT_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/scancodes.cc0000644000175000017500000004136112020641505015714 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: scancodes.cc 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "bochs.h" #include "scancodes.h" unsigned char translation8042[256] = { 0xff,0x43,0x41,0x3f,0x3d,0x3b,0x3c,0x58,0x64,0x44,0x42,0x40,0x3e,0x0f,0x29,0x59, 0x65,0x38,0x2a,0x70,0x1d,0x10,0x02,0x5a,0x66,0x71,0x2c,0x1f,0x1e,0x11,0x03,0x5b, 0x67,0x2e,0x2d,0x20,0x12,0x05,0x04,0x5c,0x68,0x39,0x2f,0x21,0x14,0x13,0x06,0x5d, 0x69,0x31,0x30,0x23,0x22,0x15,0x07,0x5e,0x6a,0x72,0x32,0x24,0x16,0x08,0x09,0x5f, 0x6b,0x33,0x25,0x17,0x18,0x0b,0x0a,0x60,0x6c,0x34,0x35,0x26,0x27,0x19,0x0c,0x61, 0x6d,0x73,0x28,0x74,0x1a,0x0d,0x62,0x6e,0x3a,0x36,0x1c,0x1b,0x75,0x2b,0x63,0x76, 0x55,0x56,0x77,0x78,0x79,0x7a,0x0e,0x7b,0x7c,0x4f,0x7d,0x4b,0x47,0x7e,0x7f,0x6f, 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x54, 0x80,0x81,0x82,0x41,0x54,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff }; // Definition of scancodes make and break, // for each set (mf1/xt , mf2/at , mf3/ps2) // The table must be in BX_KEY order // scancode scancodes[BX_KEY_NBKEYS][3] = { { // BX_KEY_CTRL_L ( ibm 58) { "\x1D" , "\x9D" }, { "\x14" , "\xF0\x14" }, { "\x11" , "\xF0\x11" }, }, { // BX_KEY_SHIFT_L ( ibm 44) { "\x2A" , "\xAA" }, { "\x12" , "\xF0\x12" }, { "\x12" , "\xF0\x12" }, }, { // BX_KEY_F1 ( ibm 112 ) { "\x3B" , "\xBB" }, { "\x05" , "\xF0\x05" }, { "\x07" , "\xF0\x07" }, }, { // BX_KEY_F2 ( ibm 113 ) { "\x3C" , "\xBC" }, { "\x06" , "\xF0\x06" }, { "\x0F" , "\xF0\x0F" }, }, { // BX_KEY_F3 ( ibm 114 ) { "\x3D" , "\xBD" }, { "\x04" , "\xF0\x04" }, { "\x17" , "\xF0\x17" }, }, { // BX_KEY_F4 ( ibm 115 ) { "\x3E" , "\xBE" }, { "\x0C" , "\xF0\x0C" }, { "\x1F" , "\xF0\x1F" }, }, { // BX_KEY_F5 ( ibm 116 ) { "\x3F" , "\xBF" }, { "\x03" , "\xF0\x03" }, { "\x27" , "\xF0\x27" }, }, { // BX_KEY_F6 ( ibm 117 ) { "\x40" , "\xC0" }, { "\x0B" , "\xF0\x0B" }, { "\x2F" , "\xF0\x2F" }, }, { // BX_KEY_F7 ( ibm 118 ) { "\x41" , "\xC1" }, { "\x83" , "\xF0\x83" }, { "\x37" , "\xF0\x37" }, }, { // BX_KEY_F8 ( ibm 119 ) { "\x42" , "\xC2" }, { "\x0A" , "\xF0\x0A" }, { "\x3F" , "\xF0\x3F" }, }, { // BX_KEY_F9 ( ibm 120 ) { "\x43" , "\xC3" }, { "\x01" , "\xF0\x01" }, { "\x47" , "\xF0\x47" }, }, { // BX_KEY_F10 ( ibm 121 ) { "\x44" , "\xC4" }, { "\x09" , "\xF0\x09" }, { "\x4F" , "\xF0\x4F" }, }, { // BX_KEY_F11 ( ibm 122 ) { "\x57" , "\xD7" }, { "\x78" , "\xF0\x78" }, { "\x56" , "\xF0\x56" }, }, { // BX_KEY_F12 ( ibm 123 ) { "\x58" , "\xD8" }, { "\x07" , "\xF0\x07" }, { "\x5E" , "\xF0\x5E" }, }, { // BX_KEY_CTRL_R ( ibm 64 ) { "\xE0\x1D" , "\xE0\x9D" }, { "\xE0\x14" , "\xE0\xF0\x14" }, { "\x58" , "\xF0\x58" }, }, { // BX_KEY_SHIFT_R ( ibm 57 ) { "\x36" , "\xB6" }, { "\x59" , "\xF0\x59" }, { "\x59" , "\xF0\x59" }, }, { // BX_KEY_CAPS_LOCK ( ibm 30 ) { "\x3A" , "\xBA" }, { "\x58" , "\xF0\x58" }, { "\x14" , "\xF0\x14" }, }, { // BX_KEY_NUM_LOCK ( ibm 90 ) { "\x45" , "\xC5" }, { "\x77" , "\xF0\x77" }, { "\x76" , "\xF0\x76" }, }, { // BX_KEY_ALT_L ( ibm 60 ) { "\x38" , "\xB8" }, { "\x11" , "\xF0\x11" }, { "\x19" , "\xF0\x19" }, }, { // BX_KEY_ALT_R ( ibm 62 ) { "\xE0\x38" , "\xE0\xB8" }, { "\xE0\x11" , "\xE0\xF0\x11" }, { "\x39" , "\xF0\x39" }, }, { // BX_KEY_A ( ibm 31 ) { "\x1E" , "\x9E" }, { "\x1C" , "\xF0\x1C" }, { "\x1C" , "\xF0\x1C" }, }, { // BX_KEY_B ( ibm 50 ) { "\x30" , "\xB0" }, { "\x32" , "\xF0\x32" }, { "\x32" , "\xF0\x32" }, }, { // BX_KEY_C ( ibm 48 ) { "\x2E" , "\xAE" }, { "\x21" , "\xF0\x21" }, { "\x21" , "\xF0\x21" }, }, { // BX_KEY_D ( ibm 33 ) { "\x20" , "\xA0" }, { "\x23" , "\xF0\x23" }, { "\x23" , "\xF0\x23" }, }, { // BX_KEY_E ( ibm 19 ) { "\x12" , "\x92" }, { "\x24" , "\xF0\x24" }, { "\x24" , "\xF0\x24" }, }, { // BX_KEY_F ( ibm 34 ) { "\x21" , "\xA1" }, { "\x2B" , "\xF0\x2B" }, { "\x2B" , "\xF0\x2B" }, }, { // BX_KEY_G ( ibm 35 ) { "\x22" , "\xA2" }, { "\x34" , "\xF0\x34" }, { "\x34" , "\xF0\x34" }, }, { // BX_KEY_H ( ibm 36 ) { "\x23" , "\xA3" }, { "\x33" , "\xF0\x33" }, { "\x33" , "\xF0\x33" }, }, { // BX_KEY_I ( ibm 24 ) { "\x17" , "\x97" }, { "\x43" , "\xF0\x43" }, { "\x43" , "\xF0\x43" }, }, { // BX_KEY_J ( ibm 37 ) { "\x24" , "\xA4" }, { "\x3B" , "\xF0\x3B" }, { "\x3B" , "\xF0\x3B" }, }, { // BX_KEY_K ( ibm 38 ) { "\x25" , "\xA5" }, { "\x42" , "\xF0\x42" }, { "\x42" , "\xF0\x42" }, }, { // BX_KEY_L ( ibm 39 ) { "\x26" , "\xA6" }, { "\x4B" , "\xF0\x4B" }, { "\x4B" , "\xF0\x4B" }, }, { // BX_KEY_M ( ibm 52 ) { "\x32" , "\xB2" }, { "\x3A" , "\xF0\x3A" }, { "\x3A" , "\xF0\x3A" }, }, { // BX_KEY_N ( ibm 51 ) { "\x31" , "\xB1" }, { "\x31" , "\xF0\x31" }, { "\x31" , "\xF0\x31" }, }, { // BX_KEY_O ( ibm 25 ) { "\x18" , "\x98" }, { "\x44" , "\xF0\x44" }, { "\x44" , "\xF0\x44" }, }, { // BX_KEY_P ( ibm 26 ) { "\x19" , "\x99" }, { "\x4D" , "\xF0\x4D" }, { "\x4D" , "\xF0\x4D" }, }, { // BX_KEY_Q ( ibm 17 ) { "\x10" , "\x90" }, { "\x15" , "\xF0\x15" }, { "\x15" , "\xF0\x15" }, }, { // BX_KEY_R ( ibm 20 ) { "\x13" , "\x93" }, { "\x2D" , "\xF0\x2D" }, { "\x2D" , "\xF0\x2D" }, }, { // BX_KEY_S ( ibm 32 ) { "\x1F" , "\x9F" }, { "\x1B" , "\xF0\x1B" }, { "\x1B" , "\xF0\x1B" }, }, { // BX_KEY_T ( ibm 21 ) { "\x14" , "\x94" }, { "\x2C" , "\xF0\x2C" }, { "\x2C" , "\xF0\x2C" }, }, { // BX_KEY_U ( ibm 23 ) { "\x16" , "\x96" }, { "\x3C" , "\xF0\x3C" }, { "\x3C" , "\xF0\x3C" }, }, { // BX_KEY_V ( ibm 49 ) { "\x2F" , "\xAF" }, { "\x2A" , "\xF0\x2A" }, { "\x2A" , "\xF0\x2A" }, }, { // BX_KEY_W ( ibm 18 ) { "\x11" , "\x91" }, { "\x1D" , "\xF0\x1D" }, { "\x1D" , "\xF0\x1D" }, }, { // BX_KEY_X ( ibm 47 ) { "\x2D" , "\xAD" }, { "\x22" , "\xF0\x22" }, { "\x22" , "\xF0\x22" }, }, { // BX_KEY_Y ( ibm 22 ) { "\x15" , "\x95" }, { "\x35" , "\xF0\x35" }, { "\x35" , "\xF0\x35" }, }, { // BX_KEY_Z ( ibm 46 ) { "\x2C" , "\xAC" }, { "\x1A" , "\xF0\x1A" }, { "\x1A" , "\xF0\x1A" }, }, { // BX_KEY_0 ( ibm 11 ) { "\x0B" , "\x8B" }, { "\x45" , "\xF0\x45" }, { "\x45" , "\xF0\x45" }, }, { // BX_KEY_1 ( ibm 2 ) { "\x02" , "\x82" }, { "\x16" , "\xF0\x16" }, { "\x16" , "\xF0\x16" }, }, { // BX_KEY_2 ( ibm 3 ) { "\x03" , "\x83" }, { "\x1E" , "\xF0\x1E" }, { "\x1E" , "\xF0\x1E" }, }, { // BX_KEY_3 ( ibm 4 ) { "\x04" , "\x84" }, { "\x26" , "\xF0\x26" }, { "\x26" , "\xF0\x26" }, }, { // BX_KEY_4 ( ibm 5 ) { "\x05" , "\x85" }, { "\x25" , "\xF0\x25" }, { "\x25" , "\xF0\x25" }, }, { // BX_KEY_5 ( ibm 6 ) { "\x06" , "\x86" }, { "\x2E" , "\xF0\x2E" }, { "\x2E" , "\xF0\x2E" }, }, { // BX_KEY_6 ( ibm 7 ) { "\x07" , "\x87" }, { "\x36" , "\xF0\x36" }, { "\x36" , "\xF0\x36" }, }, { // BX_KEY_7 ( ibm 8 ) { "\x08" , "\x88" }, { "\x3D" , "\xF0\x3D" }, { "\x3D" , "\xF0\x3D" }, }, { // BX_KEY_8 ( ibm 9 ) { "\x09" , "\x89" }, { "\x3E" , "\xF0\x3E" }, { "\x3E" , "\xF0\x3E" }, }, { // BX_KEY_9 ( ibm 10 ) { "\x0A" , "\x8A" }, { "\x46" , "\xF0\x46" }, { "\x46" , "\xF0\x46" }, }, { // BX_KEY_ESC ( ibm 110 ) { "\x01" , "\x81" }, { "\x76" , "\xF0\x76" }, { "\x08" , "\xF0\x08" }, }, { // BX_KEY_SPACE ( ibm 61 ) { "\x39" , "\xB9" }, { "\x29" , "\xF0\x29" }, { "\x29" , "\xF0\x29" }, }, { // BX_KEY_SINGLE_QUOTE ( ibm 41 ) { "\x28" , "\xA8" }, { "\x52" , "\xF0\x52" }, { "\x52" , "\xF0\x52" }, }, { // BX_KEY_COMMA ( ibm 53 ) { "\x33" , "\xB3" }, { "\x41" , "\xF0\x41" }, { "\x41" , "\xF0\x41" }, }, { // BX_KEY_PERIOD ( ibm 54 ) { "\x34" , "\xB4" }, { "\x49" , "\xF0\x49" }, { "\x49" , "\xF0\x49" }, }, { // BX_KEY_SLASH ( ibm 55 ) { "\x35" , "\xB5" }, { "\x4A" , "\xF0\x4A" }, { "\x4A" , "\xF0\x4A" }, }, { // BX_KEY_SEMICOLON ( ibm 40 ) { "\x27" , "\xA7" }, { "\x4C" , "\xF0\x4C" }, { "\x4C" , "\xF0\x4C" }, }, { // BX_KEY_EQUALS ( ibm 13 ) { "\x0D" , "\x8D" }, { "\x55" , "\xF0\x55" }, { "\x55" , "\xF0\x55" }, }, { // BX_KEY_LEFT_BRACKET ( ibm 27 ) { "\x1A" , "\x9A" }, { "\x54" , "\xF0\x54" }, { "\x54" , "\xF0\x54" }, }, { // BX_KEY_BACKSLASH ( ibm 42, 29) { "\x2B" , "\xAB" }, { "\x5D" , "\xF0\x5D" }, { "\x53" , "\xF0\x53" }, }, { // BX_KEY_RIGHT_BRACKET ( ibm 28 ) { "\x1B" , "\x9B" }, { "\x5B" , "\xF0\x5B" }, { "\x5B" , "\xF0\x5B" }, }, { // BX_KEY_MINUS ( ibm 12 ) { "\x0C" , "\x8C" }, { "\x4E" , "\xF0\x4E" }, { "\x4E" , "\xF0\x4E" }, }, { // BX_KEY_GRAVE ( ibm 1 ) { "\x29" , "\xA9" }, { "\x0E" , "\xF0\x0E" }, { "\x0E" , "\xF0\x0E" }, }, { // BX_KEY_BACKSPACE ( ibm 15 ) { "\x0E" , "\x8E" }, { "\x66" , "\xF0\x66" }, { "\x66" , "\xF0\x66" }, }, { // BX_KEY_ENTER ( ibm 43 ) { "\x1C" , "\x9C" }, { "\x5A" , "\xF0\x5A" }, { "\x5A" , "\xF0\x5A" }, }, { // BX_KEY_TAB ( ibm 16 ) { "\x0F" , "\x8F" }, { "\x0D" , "\xF0\x0D" }, { "\x0D" , "\xF0\x0D" }, }, { // BX_KEY_LEFT_BACKSLASH ( ibm 45 ) { "\x56" , "\xD6" }, { "\x61" , "\xF0\x61" }, { "\x13" , "\xF0\x13" }, }, { // BX_KEY_PRINT ( ibm 124 ) { "\xE0\x2A\xE0\x37" , "\xE0\xB7\xE0\xAA" }, { "\xE0\x12\xE0\x7C" , "\xE0\xF0\x7C\xE0\xF0\x12" }, { "\x57" , "\xF0\x57" }, }, { // BX_KEY_SCRL_LOCK ( ibm 125 ) { "\x46" , "\xC6" }, { "\x7E" , "\xF0\x7E" }, { "\x5F" , "\xF0\x5F" }, }, { // BX_KEY_PAUSE ( ibm 126 ) { "\xE1\x1D\x45\xE1\x9D\xC5" , "" }, { "\xE1\x14\x77\xE1\xF0\x14\xF0\x77" , "" }, { "\x62" , "\xF0\x62" }, }, { // BX_KEY_INSERT ( ibm 75 ) { "\xE0\x52" , "\xE0\xD2" }, { "\xE0\x70" , "\xE0\xF0\x70" }, { "\x67" , "\xF0\x67" }, }, { // BX_KEY_DELETE ( ibm 76 ) { "\xE0\x53" , "\xE0\xD3" }, { "\xE0\x71" , "\xE0\xF0\x71" }, { "\x64" , "\xF0\x64" }, }, { // BX_KEY_HOME ( ibm 80 ) { "\xE0\x47" , "\xE0\xC7" }, { "\xE0\x6C" , "\xE0\xF0\x6C" }, { "\x6E" , "\xF0\x6E" }, }, { // BX_KEY_END ( ibm 81 ) { "\xE0\x4F" , "\xE0\xCF" }, { "\xE0\x69" , "\xE0\xF0\x69" }, { "\x65" , "\xF0\x65" }, }, { // BX_KEY_PAGE_UP ( ibm 85 ) { "\xE0\x49" , "\xE0\xC9" }, { "\xE0\x7D" , "\xE0\xF0\x7D" }, { "\x6F" , "\xF0\x6F" }, }, { // BX_KEY_PAGE_DOWN ( ibm 86 ) { "\xE0\x51" , "\xE0\xD1" }, { "\xE0\x7A" , "\xE0\xF0\x7A" }, { "\x6D" , "\xF0\x6D" }, }, { // BX_KEY_KP_ADD ( ibm 106 ) { "\x4E" , "\xCE" }, { "\x79" , "\xF0\x79" }, { "\x7C" , "\xF0\x7C" }, }, { // BX_KEY_KP_SUBTRACT ( ibm 105 ) { "\x4A" , "\xCA" }, { "\x7B" , "\xF0\x7B" }, { "\x84" , "\xF0\x84" }, }, { // BX_KEY_KP_END ( ibm 93 ) { "\x4F" , "\xCF" }, { "\x69" , "\xF0\x69" }, { "\x69" , "\xF0\x69" }, }, { // BX_KEY_KP_DOWN ( ibm 98 ) { "\x50" , "\xD0" }, { "\x72" , "\xF0\x72" }, { "\x72" , "\xF0\x72" }, }, { // BX_KEY_KP_PAGE_DOWN ( ibm 103 ) { "\x51" , "\xD1" }, { "\x7A" , "\xF0\x7A" }, { "\x7A" , "\xF0\x7A" }, }, { // BX_KEY_KP_LEFT ( ibm 92 ) { "\x4B" , "\xCB" }, { "\x6B" , "\xF0\x6B" }, { "\x6B" , "\xF0\x6B" }, }, { // BX_KEY_KP_RIGHT ( ibm 102 ) { "\x4D" , "\xCD" }, { "\x74" , "\xF0\x74" }, { "\x74" , "\xF0\x74" }, }, { // BX_KEY_KP_HOME ( ibm 91 ) { "\x47" , "\xC7" }, { "\x6C" , "\xF0\x6C" }, { "\x6C" , "\xF0\x6C" }, }, { // BX_KEY_KP_UP ( ibm 96 ) { "\x48" , "\xC8" }, { "\x75" , "\xF0\x75" }, { "\x75" , "\xF0\x75" }, }, { // BX_KEY_KP_PAGE_UP ( ibm 101 ) { "\x49" , "\xC9" }, { "\x7D" , "\xF0\x7D" }, { "\x7D" , "\xF0\x7D" }, }, { // BX_KEY_KP_INSERT ( ibm 99 ) { "\x52" , "\xD2" }, { "\x70" , "\xF0\x70" }, { "\x70" , "\xF0\x70" }, }, { // BX_KEY_KP_DELETE ( ibm 104 ) { "\x53" , "\xD3" }, { "\x71" , "\xF0\x71" }, { "\x71" , "\xF0\x71" }, }, { // BX_KEY_KP_5 ( ibm 97 ) { "\x4C" , "\xCC" }, { "\x73" , "\xF0\x73" }, { "\x73" , "\xF0\x73" }, }, { // BX_KEY_UP ( ibm 83 ) { "\xE0\x48" , "\xE0\xC8" }, { "\xE0\x75" , "\xE0\xF0\x75" }, { "\x63" , "\xF0\x63" }, }, { // BX_KEY_DOWN ( ibm 84 ) { "\xE0\x50" , "\xE0\xD0" }, { "\xE0\x72" , "\xE0\xF0\x72" }, { "\x60" , "\xF0\x60" }, }, { // BX_KEY_LEFT ( ibm 79 ) { "\xE0\x4B" , "\xE0\xCB" }, { "\xE0\x6B" , "\xE0\xF0\x6B" }, { "\x61" , "\xF0\x61" }, }, { // BX_KEY_RIGHT ( ibm 89 ) { "\xE0\x4D" , "\xE0\xCD" }, { "\xE0\x74" , "\xE0\xF0\x74" }, { "\x6A" , "\xF0\x6A" }, }, { // BX_KEY_KP_ENTER ( ibm 108 ) { "\xE0\x1C" , "\xE0\x9C" }, { "\xE0\x5A" , "\xE0\xF0\x5A" }, { "\x79" , "\xF0\x79" }, }, { // BX_KEY_KP_MULTIPLY ( ibm 100 ) { "\x37" , "\xB7" }, { "\x7C" , "\xF0\x7C" }, { "\x7E" , "\xF0\x7E" }, }, { // BX_KEY_KP_DIVIDE ( ibm 95 ) { "\xE0\x35" , "\xE0\xB5" }, { "\xE0\x4A" , "\xE0\xF0\x4A" }, { "\x77" , "\xF0\x77" }, }, { // BX_KEY_WIN_L { "\xE0\x5B" , "\xE0\xDB" }, { "\xE0\x1F" , "\xE0\xF0\x1F" }, { "\x8B" , "\xF0\x8B" }, }, { // BX_KEY_WIN_R { "\xE0\x5C" , "\xE0\xDC" }, { "\xE0\x27" , "\xE0\xF0\x27" }, { "\x8C" , "\xF0\x8C" }, }, { // BX_KEY_MENU { "\xE0\x5D" , "\xE0\xDD" }, { "\xE0\x2F" , "\xE0\xF0\x2F" }, { "\x8D" , "\xF0\x8D" }, }, { // BX_KEY_ALT_SYSREQ { "\x54" , "\xD4" }, { "\x84" , "\xF0\x84" }, { "\x57" , "\xF0\x57" }, }, { // BX_KEY_CTRL_BREAK { "\xE0\x46" , "\xE0\xC6" }, { "\xE0\x7E" , "\xE0\xF0\x7E" }, { "\x62" , "\xF0\x62" }, }, { // BX_KEY_INT_BACK { "\xE0\x6A" , "\xE0\xEA" }, { "\xE0\x38" , "\xE0\xF0\x38" }, { "\x38" , "\xF0\x38" }, }, { // BX_KEY_INT_FORWARD { "\xE0\x69" , "\xE0\xE9" }, { "\xE0\x30" , "\xE0\xF0\x30" }, { "\x30" , "\xF0\x30" }, }, { // BX_KEY_INT_STOP { "\xE0\x68" , "\xE0\xE8" }, { "\xE0\x28" , "\xE0\xF0\x28" }, { "\x28" , "\xF0\x28" }, }, { // BX_KEY_INT_MAIL { "\xE0\x6C" , "\xE0\xEC" }, { "\xE0\x48" , "\xE0\xF0\x48" }, { "\x48" , "\xF0\x48" }, }, { // BX_KEY_INT_SEARCH { "\xE0\x65" , "\xE0\xE5" }, { "\xE0\x10" , "\xE0\xF0\x10" }, { "\x10" , "\xF0\x10" }, }, { // BX_KEY_INT_FAV { "\xE0\x66" , "\xE0\xE6" }, { "\xE0\x18" , "\xE0\xF0\x18" }, { "\x18" , "\xF0\x18" }, }, { // BX_KEY_INT_HOME { "\xE0\x32" , "\xE0\xB2" }, { "\xE0\x3A" , "\xE0\xF0\x3A" }, { "\x97" , "\xF0\x97" }, }, { // BX_KEY_POWER_MYCOMP { "\xE0\x6B" , "\xE0\xEB" }, { "\xE0\x40" , "\xE0\xF0\x40" }, { "\x40" , "\xF0\x40" }, }, { // BX_KEY_POWER_CALC { "\xE0\x21" , "\xE0\xA1" }, { "\xE0\x2B" , "\xE0\xF0\x2B" }, { "\x99" , "\xF0\x99" }, }, { // BX_KEY_POWER_SLEEP { "\xE0\x5F" , "\xE0\xDF" }, { "\xE0\x3F" , "\xE0\xF0\x3F" }, { "\x7F" , "\xF0\x7F" }, }, { // BX_KEY_POWER_POWER { "\xE0\x5E" , "\xE0\xDE" }, { "\xE0\x37" , "\xE0\xF0\x37" }, { "" , "" }, }, { // BX_KEY_POWER_WAKE { "\xE0\x63" , "\xE0\xE3" }, { "\xE0\x5E" , "\xE0\xF0\x5E" }, { "" , "" }, }, }; bochs-2.6/iodev/acpi.cc0000644000175000017500000004317412020641505014672 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: acpi.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2006 Volker Ruppert // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // PIIX4 ACPI support // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI #include "pci.h" #include "acpi.h" #define LOG_THIS theACPIController-> bx_acpi_ctrl_c* theACPIController = NULL; // FIXME const Bit8u acpi_pm_iomask[64] = {2, 0, 2, 0, 2, 0, 0, 0, 4, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 0, 0, 7, 7, 0, 0, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 7, 7, 7, 7, 7, 7, 7, 7, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0}; const Bit8u acpi_sm_iomask[16] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 2, 0, 0, 0}; #define PM_FREQ 3579545 #define ACPI_DBG_IO_ADDR 0xb044 #define RSM_STS (1 << 15) #define PWRBTN_STS (1 << 8) #define RTC_EN (1 << 10) #define PWRBTN_EN (1 << 8) #define GBL_EN (1 << 5) #define TMROF_EN (1 << 0) #define SCI_EN (1 << 0) #define SUS_EN (1 << 13) #define ACPI_ENABLE 0xf1 #define ACPI_DISABLE 0xf0 extern void apic_bus_deliver_smi(void); int libacpi_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theACPIController = new bx_acpi_ctrl_c(); bx_devices.pluginACPIController = theACPIController; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theACPIController, BX_PLUGIN_ACPI); return 0; // Success } void libacpi_LTX_plugin_fini(void) { bx_devices.pluginACPIController = &bx_devices.stubACPIController; delete theACPIController; } /* ported from QEMU: compute with 96 bit intermediate result: (a*b)/c */ Bit64u muldiv64(Bit64u a, Bit32u b, Bit32u c) { union { Bit64u ll; struct { #if WORDS_BIGENDIAN Bit32u high, low; #else Bit32u low, high; #endif } l; } u, res; Bit64u rl, rh; u.ll = a; rl = (Bit64u)u.l.low * (Bit64u)b; rh = (Bit64u)u.l.high * (Bit64u)b; rh += (rl >> 32); rl &= 0xffffffff; res.l.high = (Bit32u)(rh / c); res.l.low = (Bit32u)((((rh % c) << 32) + rl) / c); return res.ll; } bx_acpi_ctrl_c::bx_acpi_ctrl_c() { put("ACPI"); memset(&s, 0, sizeof(s)); s.timer_index = BX_NULL_TIMER_HANDLE; } bx_acpi_ctrl_c::~bx_acpi_ctrl_c() { SIM->get_bochs_root()->remove("acpi"); BX_DEBUG(("Exit")); } void bx_acpi_ctrl_c::init(void) { // called once when bochs initializes unsigned i; BX_ACPI_THIS s.devfunc = BX_PCI_DEVICE(1, 3); DEV_register_pci_handlers(this, &BX_ACPI_THIS s.devfunc, BX_PLUGIN_ACPI, "ACPI Controller"); if (BX_ACPI_THIS s.timer_index == BX_NULL_TIMER_HANDLE) { BX_ACPI_THIS s.timer_index = bx_pc_system.register_timer(this, timer_handler, 1000, 0, 0, "ACPI"); } DEV_register_iowrite_handler(this, write_handler, ACPI_DBG_IO_ADDR, "ACPI", 4); for (i=0; i<256; i++) { BX_ACPI_THIS pci_conf[i] = 0x0; } BX_ACPI_THIS s.pm_base = 0x0; BX_ACPI_THIS s.sm_base = 0x0; // readonly registers static const struct init_vals_t { unsigned addr; unsigned char val; } init_vals[] = { { 0x00, 0x86 }, { 0x01, 0x80 }, { 0x02, 0x13 }, { 0x03, 0x71 }, { 0x08, 0x03 }, // revision number { 0x0a, 0x80 }, // other bridge device { 0x0b, 0x06 }, // bridge device { 0x0e, 0x00 }, // header type { 0x3d, BX_PCI_INTA } // interrupt pin #1 }; for (i = 0; i < sizeof(init_vals) / sizeof(*init_vals); ++i) { BX_ACPI_THIS pci_conf[init_vals[i].addr] = init_vals[i].val; } } void bx_acpi_ctrl_c::reset(unsigned type) { BX_ACPI_THIS pci_conf[0x04] = 0x00; // command_io + command_mem BX_ACPI_THIS pci_conf[0x05] = 0x00; BX_ACPI_THIS pci_conf[0x06] = 0x80; // status_devsel_medium BX_ACPI_THIS pci_conf[0x07] = 0x02; BX_ACPI_THIS pci_conf[0x3c] = 0x00; // IRQ // PM base 0x40 - 0x43 BX_ACPI_THIS pci_conf[0x40] = 0x01; BX_ACPI_THIS pci_conf[0x41] = 0x00; BX_ACPI_THIS pci_conf[0x42] = 0x00; BX_ACPI_THIS pci_conf[0x43] = 0x00; // clear DEVACTB register on PIIX4 ACPI reset BX_ACPI_THIS pci_conf[0x58] = 0x00; BX_ACPI_THIS pci_conf[0x59] = 0x00; // device resources BX_ACPI_THIS pci_conf[0x5a] = 0x00; BX_ACPI_THIS pci_conf[0x5b] = 0x00; BX_ACPI_THIS pci_conf[0x5f] = 0x90; BX_ACPI_THIS pci_conf[0x63] = 0x60; BX_ACPI_THIS pci_conf[0x67] = 0x98; // SM base 0x90 - 0x93 BX_ACPI_THIS pci_conf[0x90] = 0x01; BX_ACPI_THIS pci_conf[0x91] = 0x00; BX_ACPI_THIS pci_conf[0x92] = 0x00; BX_ACPI_THIS pci_conf[0x93] = 0x00; BX_ACPI_THIS s.pmsts = 0; BX_ACPI_THIS s.pmen = 0; BX_ACPI_THIS s.pmcntrl = 0; BX_ACPI_THIS s.tmr_overflow_time = 0xffffff; BX_ACPI_THIS s.smbus.stat = 0; BX_ACPI_THIS s.smbus.ctl = 0; BX_ACPI_THIS s.smbus.cmd = 0; BX_ACPI_THIS s.smbus.addr = 0; BX_ACPI_THIS s.smbus.data0 = 0; BX_ACPI_THIS s.smbus.data1 = 0; BX_ACPI_THIS s.smbus.index = 0; for (unsigned i = 0; i < 32; i++) { BX_ACPI_THIS s.smbus.data[i] = 0; } } void bx_acpi_ctrl_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "acpi", "ACPI Controller State"); BXRS_HEX_PARAM_FIELD(list, pmsts, BX_ACPI_THIS s.pmsts); BXRS_HEX_PARAM_FIELD(list, pmen, BX_ACPI_THIS s.pmen); BXRS_HEX_PARAM_FIELD(list, pmcntrl, BX_ACPI_THIS s.pmcntrl); BXRS_HEX_PARAM_FIELD(list, tmr_overflow_time, BX_ACPI_THIS s.tmr_overflow_time); bx_list_c *smbus = new bx_list_c(list, "smbus", "ACPI SMBus"); BXRS_HEX_PARAM_FIELD(smbus, stat, BX_ACPI_THIS s.smbus.stat); BXRS_HEX_PARAM_FIELD(smbus, ctl, BX_ACPI_THIS s.smbus.ctl); BXRS_HEX_PARAM_FIELD(smbus, cmd, BX_ACPI_THIS s.smbus.cmd); BXRS_HEX_PARAM_FIELD(smbus, addr, BX_ACPI_THIS s.smbus.addr); BXRS_HEX_PARAM_FIELD(smbus, data0, BX_ACPI_THIS s.smbus.data0); BXRS_HEX_PARAM_FIELD(smbus, data1, BX_ACPI_THIS s.smbus.data1); BXRS_HEX_PARAM_FIELD(smbus, index, BX_ACPI_THIS s.smbus.index); bx_list_c *data = new bx_list_c(smbus, "data", "ACPI SMBus data"); for (unsigned i = 0; i < 32; i++) { char name[6]; sprintf(name, "0x%02x", i); new bx_shadow_num_c(data, name, &BX_ACPI_THIS s.smbus.data[i], BASE_HEX); } register_pci_state(list); } void bx_acpi_ctrl_c::after_restore_state(void) { if (DEV_pci_set_base_io(BX_ACPI_THIS_PTR, read_handler, write_handler, &BX_ACPI_THIS s.pm_base, &BX_ACPI_THIS pci_conf[0x40], 64, &acpi_pm_iomask[0], "ACPI PM base")) { BX_INFO(("new PM base address: 0x%04x", BX_ACPI_THIS s.pm_base)); } if (DEV_pci_set_base_io(BX_ACPI_THIS_PTR, read_handler, write_handler, &BX_ACPI_THIS s.sm_base, &BX_ACPI_THIS pci_conf[0x90], 16, &acpi_sm_iomask[0], "ACPI SM base")) { BX_INFO(("new SM base address: 0x%04x", BX_ACPI_THIS s.sm_base)); } } void bx_acpi_ctrl_c::set_irq_level(bx_bool level) { DEV_pci_set_irq(BX_ACPI_THIS s.devfunc, BX_ACPI_THIS pci_conf[0x3d], level); } Bit32u bx_acpi_ctrl_c::get_pmtmr(void) { Bit64u value = muldiv64(bx_pc_system.time_usec(), PM_FREQ, 1000000); return (Bit32u)(value & 0xffffff); } Bit16u bx_acpi_ctrl_c::get_pmsts(void) { Bit16u pmsts = BX_ACPI_THIS s.pmsts; Bit64u value = muldiv64(bx_pc_system.time_usec(), PM_FREQ, 1000000); if (value >= BX_ACPI_THIS s.tmr_overflow_time) BX_ACPI_THIS s.pmsts |= TMROF_EN; return pmsts; } void bx_acpi_ctrl_c::pm_update_sci(void) { Bit16u pmsts = get_pmsts(); bx_bool sci_level = (((pmsts & BX_ACPI_THIS s.pmen) & (RTC_EN | PWRBTN_EN | GBL_EN | TMROF_EN)) != 0); BX_ACPI_THIS set_irq_level(sci_level); // schedule a timer interruption if needed if ((BX_ACPI_THIS s.pmen & TMROF_EN) && !(pmsts & TMROF_EN)) { Bit64u expire_time = muldiv64(BX_ACPI_THIS s.tmr_overflow_time, 1000000, PM_FREQ); bx_pc_system.activate_timer(BX_ACPI_THIS s.timer_index, (Bit32u)expire_time, 0); } else { bx_pc_system.deactivate_timer(BX_ACPI_THIS s.timer_index); } } void bx_acpi_ctrl_c::generate_smi(Bit8u value) { /* ACPI specs 3.0, 4.7.2.5 */ if (value == ACPI_ENABLE) { BX_ACPI_THIS s.pmcntrl |= SCI_EN; } else if (value == ACPI_DISABLE) { BX_ACPI_THIS s.pmcntrl &= ~SCI_EN; } if (BX_ACPI_THIS pci_conf[0x5b] & 0x02) { apic_bus_deliver_smi(); } } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_acpi_ctrl_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_ACPI_SMF bx_acpi_ctrl_c *class_ptr = (bx_acpi_ctrl_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_acpi_ctrl_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_ACPI_SMF Bit8u reg = address & 0x3f; Bit32u value = 0xffffffff; if ((address & 0xffc0) == BX_ACPI_THIS s.pm_base) { if ((BX_ACPI_THIS pci_conf[0x80] & 0x01) == 0) { return value; } switch (reg) { case 0x00: value = BX_ACPI_THIS get_pmsts(); break; case 0x02: value = BX_ACPI_THIS s.pmen; break; case 0x04: value = BX_ACPI_THIS s.pmcntrl; break; case 0x08: value = BX_ACPI_THIS get_pmtmr(); break; default: BX_INFO(("ACPI read from PM register 0x%02x not implemented yet", reg)); } BX_DEBUG(("ACPI read from PM register 0x%02x returns 0x%08x", reg, value)); } else { if (((BX_ACPI_THIS pci_conf[0x04] & 0x01) == 0) && ((BX_ACPI_THIS pci_conf[0xd2] & 0x01) == 0)) { return value; } switch (reg) { case 0x00: value = BX_ACPI_THIS s.smbus.stat; break; case 0x02: BX_ACPI_THIS s.smbus.index = 0; value = BX_ACPI_THIS s.smbus.ctl & 0x1f; break; case 0x03: value = BX_ACPI_THIS s.smbus.cmd; break; case 0x04: value = BX_ACPI_THIS s.smbus.addr; break; case 0x05: value = BX_ACPI_THIS s.smbus.data0; break; case 0x06: value = BX_ACPI_THIS s.smbus.data1; break; case 0x07: value = BX_ACPI_THIS s.smbus.data[BX_ACPI_THIS s.smbus.index++]; if (BX_ACPI_THIS s.smbus.index > 31) { BX_ACPI_THIS s.smbus.index = 0; } break; default: value = 0; BX_INFO(("ACPI read from SMBus register 0x%02x not implemented yet", reg)); } BX_DEBUG(("ACPI read from SMBus register 0x%02x returns 0x%08x", reg, value)); } return value; } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_acpi_ctrl_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_ACPI_SMF bx_acpi_ctrl_c *class_ptr = (bx_acpi_ctrl_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_acpi_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_ACPI_SMF Bit8u reg = address & 0x3f; if ((address & 0xffc0) == BX_ACPI_THIS s.pm_base) { if ((BX_ACPI_THIS pci_conf[0x80] & 0x01) == 0) { return; } BX_DEBUG(("ACPI write to PM register 0x%02x, value = 0x%04x", reg, value)); switch (reg) { case 0x00: { Bit16u pmsts = BX_ACPI_THIS get_pmsts(); if (pmsts & value & TMROF_EN) { // if TMRSTS is reset, then compute the new overflow time Bit64u d = muldiv64(bx_pc_system.time_usec(), PM_FREQ, 1000000); BX_ACPI_THIS s.tmr_overflow_time = (d + BX_CONST64(0x800000)) & ~BX_CONST64(0x7fffff); } BX_ACPI_THIS s.pmsts &= ~value; BX_ACPI_THIS pm_update_sci(); } break; case 0x02: BX_ACPI_THIS s.pmen = value; BX_ACPI_THIS pm_update_sci(); break; case 0x04: { BX_ACPI_THIS s.pmcntrl = value & ~(SUS_EN); if (value & SUS_EN) { // change suspend type Bit16u sus_typ = (value >> 10) & 7; switch (sus_typ) { case 0: // soft power off bx_user_quit = 1; LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); BX_PANIC(("ACPI control: soft power off")); break; case 1: BX_INFO(("ACPI control: suspend to ram")); BX_ACPI_THIS s.pmsts |= (RSM_STS | PWRBTN_STS); DEV_cmos_set_reg(0xF, 0xFE); bx_pc_system.Reset(BX_RESET_HARDWARE); break; default: break; } } } break; default: BX_INFO(("ACPI write to PM register 0x%02x not implemented yet", reg)); } } else if ((address & 0xfff0) == BX_ACPI_THIS s.sm_base) { if (((BX_ACPI_THIS pci_conf[0x04] & 0x01) == 0) && ((BX_ACPI_THIS pci_conf[0xd2] & 0x01) == 0)) { return; } BX_DEBUG(("ACPI write to SMBus register 0x%02x, value = 0x%04x", reg, value)); switch (reg) { case 0x00: BX_ACPI_THIS s.smbus.stat = 0; BX_ACPI_THIS s.smbus.index = 0; break; case 0x02: BX_ACPI_THIS s.smbus.ctl = 0; // TODO: execute SMBus command break; case 0x03: BX_ACPI_THIS s.smbus.cmd = 0; break; case 0x04: BX_ACPI_THIS s.smbus.addr = 0; break; case 0x05: BX_ACPI_THIS s.smbus.data0 = 0; break; case 0x06: BX_ACPI_THIS s.smbus.data1 = 0; break; case 0x07: BX_ACPI_THIS s.smbus.data[BX_ACPI_THIS s.smbus.index++] = value; if (BX_ACPI_THIS s.smbus.index > 31) { BX_ACPI_THIS s.smbus.index = 0; } break; default: BX_INFO(("ACPI write to SMBus register 0x%02x not implemented yet", reg)); } } else { BX_DEBUG(("DBG: 0x%08x", value)); } } void bx_acpi_ctrl_c::timer_handler(void *this_ptr) { bx_acpi_ctrl_c *class_ptr = (bx_acpi_ctrl_c *) this_ptr; class_ptr->timer(); } void bx_acpi_ctrl_c::timer() { BX_ACPI_THIS pm_update_sci(); } // pci configuration space read callback handler Bit32u bx_acpi_ctrl_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x10) && (address < 0x34)) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_ACPI_THIS pci_conf[address+i]; switch (address+i) { case 0x04: value8 = (value8 & 0xfe) | (value & 0x01); goto set_value; break; case 0x06: // disallowing write to status lo-byte (is that expected?) break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); } goto set_value; break; case 0x40: value8 = (value8 & 0xc0) | 0x01; case 0x41: case 0x42: case 0x43: pm_base_change |= (value8 != oldval); goto set_value; break; case 0x90: value8 = (value8 & 0xf0) | 0x01; case 0x91: case 0x92: case 0x93: sm_base_change |= (value8 != oldval); default: set_value: BX_ACPI_THIS pci_conf[address+i] = value8; } } if (pm_base_change) { if (DEV_pci_set_base_io(BX_ACPI_THIS_PTR, read_handler, write_handler, &BX_ACPI_THIS s.pm_base, &BX_ACPI_THIS pci_conf[0x40], 64, &acpi_pm_iomask[0], "ACPI PM base")) { BX_INFO(("new PM base address: 0x%04x", BX_ACPI_THIS s.pm_base)); } } if (sm_base_change) { if (DEV_pci_set_base_io(BX_ACPI_THIS_PTR, read_handler, write_handler, &BX_ACPI_THIS s.sm_base, &BX_ACPI_THIS pci_conf[0x90], 16, &acpi_sm_iomask[0], "ACPI SM base")) { BX_INFO(("new SM base address: 0x%04x", BX_ACPI_THIS s.sm_base)); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } #endif // BX_SUPPORT_PCI bochs-2.6/iodev/pcidev.cc0000644000175000017500000004152012020641505015221 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pcidev.cc 10961 2012-01-09 17:15:03Z vruppert $ ///////////////////////////////////////////////////////////////////////// /* * PCIDEV: PCI host device mapping * Copyright (C) 2003 - Frank Cornelis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Based on pcivga code: * Copyright (C) 2002,2003 Mike Nordell */ // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_PCIDEV #include "pcidev.h" #include "kernel_pcidev.h" #include #include #include #define LOG_THIS thePciDevAdapter-> bx_pcidev_c* thePciDevAdapter = NULL; // builtin configuration handling functions void pcidev_init_options(void) { bx_param_c *pci = SIM->get_param("pci"); bx_list_c *pcidev = new bx_list_c(pci, "pcidev", "Host PCI Device Mapping"); bx_param_num_c *pcivid = new bx_param_num_c(pcidev, "vendor", "PCI Vendor ID", "The vendor ID of the host PCI device to map", 0, 0xffff, 0xffff); // vendor id 0xffff = no pci device present pcivid->set_base(16); pcivid->set_format("0x%04x"); pcivid->set_long_format("PCI Vendor ID: 0x%04x"); bx_param_num_c *pcidid = new bx_param_num_c(pcidev, "device", "PCI Device ID", "The device ID of the host PCI device to map", 0, 0xffff, 0x0); pcidid->set_base(16); pcidid->set_format("0x%04x"); pcidid->set_long_format("PCI Device ID: 0x%04x"); pcidev->set_options(pcidev->SHOW_PARENT | pcidev->USE_BOX_TITLE); bx_list_c *deplist = ((bx_param_bool_c*)SIM->get_param(BXPN_I440FX_SUPPORT))->get_dependent_list(); deplist->add(pcidev); deplist->add(pcivid); deplist->add(pcidid); } Bit32s pcidev_options_parser(const char *context, int num_params, char *params[]) { if (!strcmp(params[0], "pcidev")) { if (num_params != 3) { BX_PANIC(("%s: pcidev directive malformed.", context)); } for (int i = 1; i < num_params; i++) { if (!strncmp(params[i], "vendor=", 7)) { if ((params[i][7] == '0') && (toupper(params[i][8]) == 'X')) SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(¶ms[i][7], NULL, 16)); else SIM->get_param_num(BXPN_PCIDEV_VENDOR)->set(strtoul(¶ms[i][7], NULL, 10)); } else if (!strncmp(params[i], "device=", 7)) { if ((params[i][7] == '0') && (toupper(params[i][8]) == 'X')) SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(¶ms[i][7], NULL, 16)); else SIM->get_param_num(BXPN_PCIDEV_DEVICE)->set(strtoul(¶ms[i][7], NULL, 10)); } else { BX_ERROR(("%s: unknown parameter for pcidev ignored.", context)); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s pcidev_options_save(FILE *fp) { if (SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get() != 0xffff) { fprintf(fp, "pcidev: vendor=0x%04x, device=0x%04x\n", SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get(), SIM->get_param_num(BXPN_PCIDEV_DEVICE)->get()); } return 0; } // device plugin entry points int libpcidev_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { thePciDevAdapter = new bx_pcidev_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePciDevAdapter, BX_PLUGIN_PCIDEV); // add new configuration parameter for the config interface pcidev_init_options(); // register add-on option for bochsrc and command line SIM->register_addon_option("pcidev", pcidev_options_parser, pcidev_options_save); return 0; // Success } void libpcidev_LTX_plugin_fini(void) { SIM->unregister_addon_option("pcidev"); bx_list_c *menu = (bx_list_c*)SIM->get_param("network"); menu->remove("pcidev"); delete thePciDevAdapter; } // the device object bx_pcidev_c::bx_pcidev_c() { put("pcidev", "PCI2H"); } bx_pcidev_c::~bx_pcidev_c() { BX_DEBUG(("Exit")); } static void pcidev_sighandler(int param) { bx_pcidev_c *pcidev = thePciDevAdapter; BX_INFO(("Interrupt received.")); DEV_pci_set_irq(pcidev->devfunc, pcidev->intpin, 0); /* * We need to first lower the IRQ line or else we don't * get any IRQs through */ DEV_pci_set_irq(pcidev->devfunc, pcidev->intpin, 1); } static bx_bool pcidev_mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { struct region_struct *region = (struct region_struct *)param; bx_pcidev_c *pcidev = region->pcidev; int fd = pcidev->pcidev_fd; int ret = -1; if (fd == -1) return false; /* we failed to handle the request, so let a default handler do it for us */ BX_INFO(("Reading I/O memory at 0x%08x", (unsigned)addr)); struct pcidev_io_struct io; io.address = addr + region->host_start - region->start; switch(len) { case 1: ret = ioctl(fd, PCIDEV_IOCTL_READ_MEM_BYTE, &io); *(Bit8u *)data = io.value; break; case 2: ret = ioctl(fd, PCIDEV_IOCTL_READ_MEM_WORD, &io); *(Bit16u *)data = io.value; break; case 4: ret = ioctl(fd, PCIDEV_IOCTL_READ_MEM_DWORD, &io); *(Bit32u *)data = io.value; break; default: BX_ERROR(("Unsupported pcidev read mem operation")); break; } if (ret == -1) { BX_ERROR(("pcidev read mem error")); } return true; // ok, we handled the request } static bx_bool pcidev_mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { struct region_struct *region = (struct region_struct *)param; bx_pcidev_c *pcidev = region->pcidev; int fd = pcidev->pcidev_fd; int ret = -1; if (fd == -1) return false; /* we failed to handle the request, so let a default handler do it for us */ BX_INFO(("Writing I/O memory at 0x%08x", (unsigned)addr)); struct pcidev_io_struct io; io.address = addr + region->host_start - region->start; switch(len) { case 1: io.value = *(Bit8u *)data; ret = ioctl(fd, PCIDEV_IOCTL_WRITE_MEM_BYTE, &io); break; case 2: io.value = *(Bit16u *)data; ret = ioctl(fd, PCIDEV_IOCTL_WRITE_MEM_WORD, &io); break; case 4: io.value = *(Bit32u *)data; ret = ioctl(fd, PCIDEV_IOCTL_WRITE_MEM_DWORD, &io); break; default: BX_ERROR(("Unsupported pcidev write mem operation")); break; } if (ret == -1) { BX_ERROR(("pcidev write mem error")); } return true; } static const char * const pcidev_name = "Experimental PCI 2 host PCI"; void bx_pcidev_c::init(void) { // Check if the device is disabled or not configured if (SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get() == 0xffff) { BX_INFO(("Host PCI device mapping disabled")); BX_UNREGISTER_DEVICE_DEVMODEL("pcidev"); return; } BX_PCIDEV_THIS pcidev_fd = -1; int fd; fd = open("/dev/pcidev", O_RDWR); if (fd == -1) { switch(errno) { case ENODEV: BX_PANIC(("The pcidev kernel module is not loaded!")); break; default: BX_PANIC(("open /dev/pcidev: %s", strerror(errno))); break; } return; } BX_PCIDEV_THIS pcidev_fd = fd; struct pcidev_find_struct find; unsigned short vendor = SIM->get_param_num(BXPN_PCIDEV_VENDOR)->get(); unsigned short device = SIM->get_param_num(BXPN_PCIDEV_DEVICE)->get(); find.deviceID = device; find.vendorID = vendor; if (ioctl(fd, PCIDEV_IOCTL_FIND, &find) == -1) { switch (errno) { case ENOENT: BX_PANIC(("PCI device not found on host system.")); break; case EBUSY: BX_PANIC(("PCI device already used by another kernel module.")); break; default: perror("ioctl"); break; } close(fd); BX_PCIDEV_THIS pcidev_fd = -1; return; } BX_INFO(("vendor: %04x; device: %04x @ host %04x:%04x.%d", vendor, device, (unsigned)find.bus, (unsigned)find.device, (unsigned)find.func)); BX_PCIDEV_THIS devfunc = 0x00; DEV_register_pci_handlers(this, &BX_PCIDEV_THIS devfunc, BX_PLUGIN_PCIDEV, pcidev_name); BX_PCIDEV_THIS irq = 0; struct pcidev_io_struct io; io.address = 0x3d; int ret = ioctl(fd, PCIDEV_IOCTL_READ_CONFIG_BYTE, &io); if (ret != -1) { BX_PCIDEV_THIS intpin = io.value; } else { BX_PCIDEV_THIS intpin = 0; } for (int idx = 0; idx < PCIDEV_COUNT_RESOURCES; idx++) { BX_PCIDEV_THIS regions[idx].start = 0; // emulated device not yet initialized if (!find.resources[idx].start) continue; BX_INFO(("PCI resource @ %x-%x (%s)", (unsigned)find.resources[idx].start, (unsigned)find.resources[idx].end, (find.resources[idx].flags & PCIDEV_RESOURCE_IO ? "I/O" : "Mem"))); BX_PCIDEV_THIS regions[idx].size = find.resources[idx].end - find.resources[idx].start + 1; BX_PCIDEV_THIS regions[idx].host_start = find.resources[idx].start; struct pcidev_io_struct io; io.address = PCI_BASE_ADDRESS_0 + idx * 4; if (ioctl(fd, PCIDEV_IOCTL_READ_CONFIG_DWORD, &io) == -1) BX_ERROR(("Error reading a base address config reg")); BX_PCIDEV_THIS regions[idx].config_value = io.value; /* * We will use ®ion[idx] as parameter for our I/O or memory * handler. So we provide a pcidev pointer to the pcidev object * in order for the handle to be able to use its pcidev object */ BX_PCIDEV_THIS regions[idx].pcidev = this; } struct sigaction sa; sa.sa_handler = pcidev_sighandler; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sigaction(SIGUSR1, &sa, NULL); /* * The kernel pcidev will fire SIGUSR1 signals when it receives * interrupts from the host PCI device. */ ioctl(fd, PCIDEV_IOCTL_INTERRUPT, 1); } void bx_pcidev_c::reset(unsigned type) { } // pci configuration space read callback handler Bit32u bx_pcidev_c::pci_read_handler(Bit8u address, unsigned io_len) { int ret = -1; int fd = BX_PCIDEV_THIS pcidev_fd; if (fd == -1) return 0xffffffff; struct pcidev_io_struct io; io.address = address; switch(io_len) { case 1: ret = ioctl(fd, PCIDEV_IOCTL_READ_CONFIG_BYTE, &io); break; case 2: ret = ioctl(fd, PCIDEV_IOCTL_READ_CONFIG_WORD, &io); break; case 4: ret = ioctl(fd, PCIDEV_IOCTL_READ_CONFIG_DWORD, &io); break; } if (ret == -1) BX_ERROR(("pcidev config read error")); // we don't use the host irq line but our own bochs irq line if (address == PCI_INTERRUPT_LINE) { io.value = (io.value & 0xffffff00) | (BX_PCIDEV_THIS irq & 0xff); } if (PCI_BASE_ADDRESS_0 <= address && address <= PCI_BASE_ADDRESS_5) { BX_INFO(("Reading pcidev base address #%d", (address - PCI_BASE_ADDRESS_0) / 4)); io.value = BX_PCIDEV_THIS regions[(address - PCI_BASE_ADDRESS_0) >> 2].config_value; if (address & 3) { io.value >>= (8 * (address & 3)); } } return io.value; } // pci configuration space write callback handler void bx_pcidev_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len) { int ret = -1; Bit8u *iomask; Bit32u bitmask; int fd = BX_PCIDEV_THIS pcidev_fd; if (fd == -1) return; // we do a host 2 guest irq line mapping if (address == PCI_INTERRUPT_LINE) { value &= 0xff; BX_INFO(("Changing the pcidev irq line from %d to %d", BX_PCIDEV_THIS irq, value)); BX_PCIDEV_THIS irq = value; return; } if ((PCI_BASE_ADDRESS_0 <= address) && (address <= PCI_BASE_ADDRESS_5)) { /* * Two things to do here: * - update the cached config space value via a probe * - remap the I/O or memory handler if required */ int io_reg_idx = (address - PCI_BASE_ADDRESS_0) >> 2; switch (io_len) { case 1: bitmask = 0xff; break; case 2: bitmask = 0xffff; break; default: bitmask = 0xffffffff; } bitmask <<= (8 * (address & 3)); value <<= (8 * (address & 3)); value |= BX_PCIDEV_THIS regions[io_reg_idx].config_value & ~bitmask; BX_INFO(("Changing pcidev base address #%d - New value: %#x", (address - PCI_BASE_ADDRESS_0) / 4, value)); struct pcidev_io_struct io; io.address = address; io.value = value; ret = ioctl(fd, PCIDEV_IOCTL_PROBE_CONFIG_DWORD, &io); if (ret == -1) { BX_ERROR(("Error probing a base address reg!")); return; } unsigned long base = io.value; BX_PCIDEV_THIS regions[io_reg_idx].config_value = base; /* remap the I/O or memory handler if required using io.value * We assume that an I/O memory region will stay and I/O memory * region. And that an I/O port region also will stay an I/O port * region. */ if ((base & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) { if (DEV_pci_set_base_mem(&(BX_PCIDEV_THIS regions[io_reg_idx]), pcidev_mem_read_handler, pcidev_mem_write_handler, &BX_PCIDEV_THIS regions[io_reg_idx].start, (Bit8u*)&BX_PCIDEV_THIS regions[io_reg_idx].config_value, BX_PCIDEV_THIS regions[io_reg_idx].size)) { BX_INFO(("new base #%d memory address: 0x%08x", io_reg_idx, BX_PCIDEV_THIS regions[io_reg_idx].start)); } } else { /* * Remap our I/O port handlers here. */ iomask = (Bit8u*)malloc(BX_PCIDEV_THIS regions[io_reg_idx].size); memset(iomask, 7, BX_PCIDEV_THIS regions[io_reg_idx].size); if (DEV_pci_set_base_io(&(BX_PCIDEV_THIS regions[io_reg_idx]), read_handler, write_handler, &BX_PCIDEV_THIS regions[io_reg_idx].start, (Bit8u*)&BX_PCIDEV_THIS regions[io_reg_idx].config_value, BX_PCIDEV_THIS regions[io_reg_idx].size, iomask, "pcidev")) { BX_INFO(("new base #%d i/o address: 0x%04x", io_reg_idx, (Bit16u)BX_PCIDEV_THIS regions[io_reg_idx].start)); } free(iomask); } return; } struct pcidev_io_struct io; io.address = address; io.value = value; switch(io_len) { case 1: ret = ioctl(fd, PCIDEV_IOCTL_WRITE_CONFIG_BYTE, &io); break; case 2: ret = ioctl(fd, PCIDEV_IOCTL_WRITE_CONFIG_WORD, &io); break; case 4: ret = ioctl(fd, PCIDEV_IOCTL_WRITE_CONFIG_DWORD, &io); break; } if (ret == -1) BX_ERROR(("pcidev config write error")); } Bit32u bx_pcidev_c::read_handler(void *param, Bit32u address, unsigned io_len) { #if !BX_USE_PCIDEV_SMF bx_pcidev_c *class_ptr = ((struct region_struct *)param)->pcidev; return class_ptr->read(param, address, io_len); } Bit32u bx_pcidev_c::read(void *param, Bit32u address, unsigned io_len) { #endif struct region_struct *region = (struct region_struct *)param; int ret = -1; int fd = BX_PCIDEV_THIS pcidev_fd; if (fd == -1) return 0xffffffff; struct pcidev_io_struct io; // here we map the io address io.address = address + region->host_start - region->start; switch(io_len) { case 1: ret = ioctl(fd, PCIDEV_IOCTL_READ_IO_BYTE, &io); break; case 2: ret = ioctl(fd, PCIDEV_IOCTL_READ_IO_WORD, &io); break; case 4: ret = ioctl(fd, PCIDEV_IOCTL_READ_IO_DWORD, &io); break; } if (ret == -1) { BX_ERROR(("pcidev read I/O error")); io.value = 0xffffffff; } return io.value; } void bx_pcidev_c::write_handler(void *param, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_PCIDEV_SMF bx_pcidev_c *class_ptr = ((struct region_struct *)param)->pcidev; class_ptr->write(param, address, value, io_len); } void bx_pcidev_c::write(void *param, Bit32u address, Bit32u value, unsigned io_len) { #endif struct region_struct *region = (struct region_struct *)param; int ret = -1; int fd = BX_PCIDEV_THIS pcidev_fd; if (fd == -1) return; struct pcidev_io_struct io; // here we map the I/O address io.address = address + region->host_start - region->start; io.value = value; switch(io_len) { case 1: ret = ioctl(fd, PCIDEV_IOCTL_WRITE_IO_BYTE, &io); break; case 2: ret = ioctl(fd, PCIDEV_IOCTL_WRITE_IO_WORD, &io); break; case 4: ret = ioctl(fd, PCIDEV_IOCTL_WRITE_IO_DWORD, &io); break; } if (ret == -1) BX_ERROR(("pcidev I/O write error")); } #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIDEV bochs-2.6/iodev/Makefile.in0000644000175000017500000006224212020641505015511 0ustar guillemguillem# Copyright (C) 2001-2012 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Makefile for the iodev component of bochs @SUFFIX_LINE@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ VPATH = @srcdir@ bindir = @bindir@ libdir = @libdir@ datarootdir = @datarootdir@ mandir = @mandir@ man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 docdir = $(datarootdir)/doc/bochs sharedir = $(datarootdir)/bochs top_builddir = .. top_srcdir = @top_srcdir@ SHELL = @SHELL@ @SET_MAKE@ CXX = @CXX@ CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ PLUGIN_PATH=@libdir@ top_builddir = .. LIBTOOL=@LIBTOOL@ WIN32_DLL_IMPORT_LIBRARY=../dllexports.a BX_INCDIRS = -I.. -I$(srcdir)/.. -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@ LOCAL_CXXFLAGS = $(MCH_CFLAGS) PCIDEV_CXXFLAGS = -I$(srcdir)/../host/linux/pcidev OBJS_THAT_CANNOT_BE_PLUGINS = \ devices.o \ virt_timer.o \ slowdown_timer.o \ $(MCH_OBJS) OBJS_THAT_CAN_BE_PLUGINS = \ pic.o \ pit.o \ serial.o \ parallel.o \ floppy.o \ keyboard.o \ vga.o \ svga_cirrus.o \ biosdev.o \ cmos.o \ harddrv.o \ dma.o \ unmapped.o \ extfpuirq.o \ speaker.o \ busmouse.o \ ioapic.o \ @PCI_OBJ@ \ @GAME_OBJS@ \ @IODEBUG_OBJS@ OBJS_THAT_SUPPORT_OTHER_PLUGINS = \ pit82c54.o \ scancodes.o \ serial_raw.o \ vgacore.o NONPLUGIN_OBJS = @IODEV_NON_PLUGIN_OBJS@ PLUGIN_OBJS = @IODEV_PLUGIN_OBJS@ all: libiodev.a plugins: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@) libiodev.a: $(NONPLUGIN_OBJS) @RMCOMMAND@ libiodev.a @MAKELIB@ $(NONPLUGIN_OBJS) @RANLIB@ libiodev.a # standard compile rule for C++ files .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@ pcidev.o : pcidev.@CPP_SUFFIX@ $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $(PCIDEV_CXXFLAGS) @CXXFP@$< @OFP@$@ ##### building plugins with libtool %.lo: %.@CPP_SUFFIX@ $(LIBTOOL) --mode=compile --tag CXX $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@ pcidev.lo : pcidev.@CPP_SUFFIX@ $(LIBTOOL) --mode=compile --tag CXX $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $(PCIDEV_CXXFLAGS) $< -o $@ libbx_%.la: %.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) # special link rules for plugins that require more than one object file libbx_keyboard.la: keyboard.lo scancodes.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module keyboard.lo scancodes.lo -o libbx_keyboard.la -rpath $(PLUGIN_PATH) libbx_pit.la: pit82c54.lo pit.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module pit82c54.lo pit.lo -o libbx_pit.la -rpath $(PLUGIN_PATH) libbx_serial.la: serial.lo serial_raw.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module serial.lo serial_raw.lo -o libbx_serial.la -rpath $(PLUGIN_PATH) libbx_vga.la: vga.lo vgacore.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module vga.lo vgacore.lo -o libbx_vga.la -rpath $(PLUGIN_PATH) libbx_svga_cirrus.la: svga_cirrus.lo vgacore.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module svga_cirrus.lo vgacore.lo -o libbx_svga_cirrus.la -rpath $(PLUGIN_PATH) #### building DLLs for win32 (tested on cygwin only) bx_%.dll: %.o $(CXX) $(CXXFLAGS) -shared -o $@ $< $(WIN32_DLL_IMPORT_LIBRARY) # special link rules for plugins that require more than one object file bx_keyboard.dll: keyboard.o scancodes.o $(CXX) $(CXXFLAGS) -shared -o bx_keyboard.dll keyboard.o scancodes.o $(WIN32_DLL_IMPORT_LIBRARY) bx_pit.dll: pit82c54.o pit.o $(CXX) $(CXXFLAGS) -shared -o bx_pit.dll pit82c54.o pit.o $(WIN32_DLL_IMPORT_LIBRARY) bx_gameport.dll: gameport.o $(CXX) $(CXXFLAGS) -shared -o bx_gameport.dll gameport.o $(WIN32_DLL_IMPORT_LIBRARY) -lwinmm bx_serial.dll: serial.o serial_raw.o $(CXX) $(CXXFLAGS) -shared -o bx_serial.dll serial.o serial_raw.o $(WIN32_DLL_IMPORT_LIBRARY) -lwsock32 bx_vga.dll: vga.o vgacore.o $(CXX) $(CXXFLAGS) -shared -o bx_vga.dll vga.o vgacore.o $(WIN32_DLL_IMPORT_LIBRARY) bx_svga_cirrus.dll: svga_cirrus.o vgacore.o $(CXX) $(CXXFLAGS) -shared -o bx_svga_cirrus.dll svga_cirrus.o vgacore.o $(WIN32_DLL_IMPORT_LIBRARY) ##### end DLL section clean: @RMCOMMAND@ -rf .libs *.lo *.o *.la *.a *.dll dist-clean: clean @RMCOMMAND@ Makefile ########################################### # dependencies generated by # gcc -MM -I.. -I../instrument/stubs *.cc | sed -e 's/\.cc/.@CPP_SUFFIX@/g' # gcc -MM -I.. -I../instrument/stubs *.cc | \ # sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g' # # This means that every source file is listed twice, once with a .o rule # and then again with an identical .lo rule. The .lo rules are used when # building plugins. ########################################### acpi.o: acpi.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h acpi.h biosdev.o: biosdev.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h biosdev.h busmouse.o: busmouse.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h busmouse.h cmos.o: cmos.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h cmos.h virt_timer.h devices.o: devices.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h ../iodev/virt_timer.h \ ../iodev/slowdown_timer.h dma.o: dma.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h dma.h extfpuirq.o: extfpuirq.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h extfpuirq.h floppy.o: floppy.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h hdimage/hdimage.h floppy.h gameport.o: gameport.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h gameport.h harddrv.o: harddrv.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h harddrv.h hdimage/hdimage.h hdimage/cdrom.h ioapic.o: ioapic.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h ioapic.h iodebug.o: iodebug.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h keyboard.o: keyboard.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h ../gui/keymap.h keyboard.h scancodes.h parallel.o: parallel.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h parallel.h pci2isa.o: pci2isa.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h pci2isa.h pci.o: pci.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h pcidev.o: pcidev.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci_ide.o: pci_ide.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h pci_ide.h pic.o: pic.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pic.h pit82c54.o: pit82c54.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pit82c54.h pit.o: pit.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pit.h pit82c54.h virt_timer.h speaker.h scancodes.o: scancodes.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h scancodes.h serial.o: serial.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h serial.h serial_raw.o: serial_raw.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h slowdown_timer.o: slowdown_timer.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../param_names.h \ slowdown_timer.h speaker.o: speaker.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h speaker.h sound/soundmod.h svga_cirrus.o: svga_cirrus.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h vgacore.h svga_cirrus.h virt_timer.h unmapped.o: unmapped.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h unmapped.h vga.o: vga.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h vgacore.h vga.h virt_timer.h vgacore.o: vgacore.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h vgacore.h virt_timer.h virt_timer.o: virt_timer.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../param_names.h \ virt_timer.h acpi.lo: acpi.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h acpi.h biosdev.lo: biosdev.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h biosdev.h busmouse.lo: busmouse.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h busmouse.h cmos.lo: cmos.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h cmos.h virt_timer.h devices.lo: devices.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h ../iodev/virt_timer.h \ ../iodev/slowdown_timer.h dma.lo: dma.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h dma.h extfpuirq.lo: extfpuirq.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h extfpuirq.h floppy.lo: floppy.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h hdimage/hdimage.h floppy.h gameport.lo: gameport.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h gameport.h harddrv.lo: harddrv.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h harddrv.h hdimage/hdimage.h hdimage/cdrom.h ioapic.lo: ioapic.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h ioapic.h iodebug.lo: iodebug.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h keyboard.lo: keyboard.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h ../gui/keymap.h keyboard.h scancodes.h parallel.lo: parallel.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h parallel.h pci2isa.lo: pci2isa.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h pci2isa.h pci.lo: pci.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h pcidev.lo: pcidev.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci_ide.lo: pci_ide.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pci.h pci_ide.h pic.lo: pic.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pic.h pit82c54.lo: pit82c54.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pit82c54.h pit.lo: pit.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h pit.h pit82c54.h virt_timer.h speaker.h scancodes.lo: scancodes.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h scancodes.h serial.lo: serial.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h serial.h serial_raw.lo: serial_raw.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h slowdown_timer.lo: slowdown_timer.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../param_names.h \ slowdown_timer.h speaker.lo: speaker.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h speaker.h sound/soundmod.h svga_cirrus.lo: svga_cirrus.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h vgacore.h svga_cirrus.h virt_timer.h unmapped.lo: unmapped.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h unmapped.h vga.lo: vga.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h vgacore.h vga.h virt_timer.h vgacore.lo: vgacore.@CPP_SUFFIX@ iodev.h ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../plugin.h ../extplugin.h \ ../ltdl.h ../param_names.h vgacore.h virt_timer.h virt_timer.lo: virt_timer.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h ../gui/siminterface.h \ ../cpudb.h ../gui/paramtree.h ../memory/memory.h ../pc_system.h \ ../gui/gui.h ../instrument/stubs/instrument.h ../param_names.h \ virt_timer.h bochs-2.6/iodev/devices.txt0000644000175000017500000001432612020641505015627 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: devices.txt 11391 2012-09-02 10:51:47Z vruppert $ ///////////////////////////////////////////////////////////////////////// MOTHER BOARD (i440FX Support) devices.cc | +---- 82441FX (PMC) and 82442 (DBX) emulation pci.cc | +---- 82371SB (PIIX3) PCI ISA IDE XCELERATOR | | | +---- PCI-to-ISA bridge pci2isa.cc | +---- PCI IDE controller pci_ide.cc | | | +---- PIIX4 ACPI support acpi.cc | +---- PCI host device mapping (Linux only) pcidev.cc | +---- Integrated peripherals | | | +---- 8259A PIC pic.cc | +---- 82093AA I/O APIC ioapic.cc | +---- 8254/82C54 Programmable Interval Timer pit.cc, pit82c54.cc | | | | | +---- PC Speaker (lowlevel) speaker.cc | | | +---- 8237 DMA controller dma.cc | +---- 82077A Floppy Drive Controller (*) floppy.cc | +---- CMOS device cmos.cc | +---- External circuit for #FERR pin extfpuirq.cc | +---- Parallel ports emulation parallel.cc | +---- UART 16550A Serial Port serial.cc | | | | | +---- Host specific Modules serial_raw.cc | | | +---- Standard PC gameport gameport.cc | +------------- Debugging/Instrumentation biosdev.cc, iodebug.cc, unmapped.cc Attached devices | +---- PS/2 Keyboard and Mouse keyboard.cc, scancodes.cc | +---- Bus Mouse (not complete) busmouse.cc | +---- Hard Drive + ATA controller harddrv.cc | | | +---- Hard Drive image support (*) hdimage/ | | | | | +---- Core and basic modules hdimage.cc | | | | | +---- Additional modules | | | | | +---- VMware version 3 vmware3.cc | | +---- VMware 4 (VMDK) vmware4.cc | | +---- VirtualPC vpc-img.cc | | +---- Virtual VFAT vvfat.cc | | | +---- CD/DVD-ROM image / device access (*) hdimage/cdrom.cc | | | +---- Host specific Modules | | | +---- Amiga/MorphOS hdimage/cdrom_amigaos.cc | +---- Windows hdimage/cdrom_win32.cc | +---- Mac OSX hdimage/cdrom_osx.cc | +---- Linux and others hdimage/cdrom_misc.cc | +---- Graphics (VGA core) vgacore.cc | | | +---- VGA adapter with VBE and PCI VGA support vga.cc | +---- Cirrus Logic PCI/ISA CLGD5446 SVGA adapter svga_cirrus.cc | +---- Network support network/ | | | +---- Network Devices | | | | | +---- NE2000 (ISA/PCI) ne2k.cc | | +---- PCI Pseudo NIC pcipnic.cc | | +---- Intel 82540EM Gigabit Ethernet e1000.cc | | | +---- Networking Modules netmod.cc | | | | | +-- Host specific Modules eth_fbsd.cc, eth_linux.cc, eth_win32.cc | | | +---- Dummy module eth_null.cc | +---- TAP Interface eth_tap.cc | +---- TUN/TAP Interface eth_tuntap.cc | +---- VDE Interface eth_vde.cc | +---- virtual Ethernet locator eth_vnet.cc | +---- backend for Slirp eth_slirp.cc | +---- Sound support sound/ | | | +---- Sound devices | | | | | +---- Sound Blaster SB16 (ISA) sb16.cc | | +---- ES1370 (PCI) es1370.cc | | | +---- Sound modules | | | +---- Dummy / Control Module soundmod.cc | +---- Host specific Modules soundlnx.cc, soundosx.cc, soundwin.cc | +---- USB support usb/ | +---- Host Controllers | | | +---- USB OHCI adapter usb_ohci.cc | +---- USB UHCI adapter (PIIX3) usb_uhci.cc | +---- USB xHCI adapter usb_xhci.cc | +---- Attached USB devices | | | +-- Control Module usb_common.cc | +---- USB HID emulation usb_hid.cc +---- USB external HUB usb_hub.cc +---- USB mass storage device (*) usb_msd.cc, scsi_device.cc +---- USB HP DeskJet 920C printer usb_printer.cc (*) USB MSD uses hdimage / cdrom code for image / device access Floppy uses hdimage code for VVFAT support BOCHS timer sycronisation modules | +---- Slowdown timer slowdown_timer.cc +---- Virtual timer virt_timer.cc TODO: bochs-2.6/iodev/hdimage/0000755000175000017500000000000012020641504015033 5ustar guillemguillembochs-2.6/iodev/hdimage/vpc-img.cc0000644000175000017500000002702612020641504016713 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vpc-img.cc 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Block driver for Connectix / Microsoft Virtual PC images (ported from QEMU) // // Copyright (c) 2005 Alex Beregszaszi // Copyright (c) 2009 Kevin Wolf // Copyright (C) 2012 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "hdimage.h" #include "vpc-img.h" #define LOG_THIS bx_devices.pluginHDImageCtl-> // be*_to_cpu : convert disk (big) to host endianness #if defined (BX_LITTLE_ENDIAN) #define be16_to_cpu(val) bx_bswap16(val) #define be32_to_cpu(val) bx_bswap32(val) #define be64_to_cpu(val) bx_bswap64(val) #define cpu_to_be32(val) bx_bswap32(val) #else #define be16_to_cpu(val) (val) #define be32_to_cpu(val) (val) #define be64_to_cpu(val) (val) #define cpu_to_be32(val) (val) #endif int vpc_image_t::open(const char* pathname) { int i; vhd_footer_t *footer; vhd_dyndisk_header_t *dyndisk_header; Bit8u buf[HEADER_SIZE]; Bit32u checksum; Bit64u imgsize; int disk_type = VHD_DYNAMIC; #ifdef WIN32 HANDLE hFile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); if (hFile != INVALID_HANDLE_VALUE) { ULARGE_INTEGER FileSize; FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); CloseHandle(hFile); if ((FileSize.LowPart != INVALID_FILE_SIZE) || (GetLastError() == NO_ERROR)) { imgsize = FileSize.QuadPart; } else { return -1; } } else { return -1; } #endif fd = ::open(pathname, O_RDWR #ifdef O_BINARY | O_BINARY #endif ); if (fd < 0) { return fd; } #ifndef WIN32 struct stat stat_buf; if (fstat(fd, &stat_buf)) { BX_PANIC(("fstat() returns error!")); } imgsize = (Bit64u)stat_buf.st_size; #endif if (bx_read_image(fd, 0, (char*)footer_buf, HEADER_SIZE) != HEADER_SIZE) { ::close(fd); return -1; } footer = (vhd_footer_t*)footer_buf; if (strncmp((char*)footer->creator, "conectix", 8)) { if (imgsize < HEADER_SIZE) { ::close(fd); return -1; } // If a fixed disk, the footer is found only at the end of the file if (bx_read_image(fd, imgsize-HEADER_SIZE, (char*)footer_buf, HEADER_SIZE) != HEADER_SIZE) { ::close(fd); return -1; } if (strncmp((char*)footer->creator, "conectix", 8)) { ::close(fd); return -1; } disk_type = VHD_FIXED; } checksum = be32_to_cpu(footer->checksum); footer->checksum = 0; if (vpc_checksum(footer_buf, HEADER_SIZE) != checksum) BX_ERROR(("The header checksum of '%s' is incorrect", pathname)); // Write 'checksum' back to footer, or else will leave it with zero. footer->checksum = be32_to_cpu(checksum); // The visible size of a image in Virtual PC depends on the geometry // rather than on the size stored in the footer (the size in the footer // is too large usually) cylinders = be16_to_cpu(footer->cyls); heads = footer->heads; spt = footer->secs_per_cyl; sector_count = (Bit64u)(cylinders * heads * spt); hd_size = sector_count * 512; if (sector_count >= 65535 * 16 * 255) { ::close(fd); return -EFBIG; } if (disk_type == VHD_DYNAMIC) { if (bx_read_image(fd, be64_to_cpu(footer->data_offset), buf, HEADER_SIZE) != HEADER_SIZE) { ::close(fd); return -1; } dyndisk_header = (vhd_dyndisk_header_t*)buf; if (strncmp((char*)dyndisk_header->magic, "cxsparse", 8)) { ::close(fd); return -1; } block_size = be32_to_cpu(dyndisk_header->block_size); bitmap_size = ((block_size / (8 * 512)) + 511) & ~511; max_table_entries = be32_to_cpu(dyndisk_header->max_table_entries); pagetable = new Bit32u[max_table_entries]; bat_offset = be64_to_cpu(dyndisk_header->table_offset); if (bx_read_image(fd, bat_offset, (void*)pagetable, max_table_entries * 4) != (max_table_entries * 4)) { ::close(fd); return -1; } free_data_block_offset = (bat_offset + (max_table_entries * 4) + 511) & ~511; for (i = 0; i < max_table_entries; i++) { pagetable[i] = be32_to_cpu(pagetable[i]); if (pagetable[i] != 0xFFFFFFFF) { Bit64s next = (512 * (Bit64s)pagetable[i]) + bitmap_size + block_size; if (next > (Bit64s)free_data_block_offset) { free_data_block_offset = next; } } } last_bitmap_offset = (Bit64s) -1; } cur_sector = 0; BX_INFO(("'vpc' disk image opened: path is '%s'", pathname)); return 0; } void vpc_image_t::close(void) { if (fd > -1) { delete [] pagetable; ::close(fd); } } Bit64s vpc_image_t::lseek(Bit64s offset, int whence) { if (whence == SEEK_SET) { cur_sector = (Bit32u)(offset / 512); } else if (whence == SEEK_CUR) { cur_sector += (Bit32u)(offset / 512); } else { BX_ERROR(("lseek: mode not supported yet")); return -1; } if (cur_sector >= sector_count) return -1; return 0; } ssize_t vpc_image_t::read(void* buf, size_t count) { char *cbuf = (char*)buf; Bit32u scount = (Bit32u)(count / 0x200); vhd_footer_t *footer = (vhd_footer_t*)footer_buf; Bit64s offset, sectors, sectors_per_block; int ret; if (cpu_to_be32(footer->type) == VHD_FIXED) { return bx_read_image(fd, cur_sector * 512, buf, count); } while (scount > 0) { offset = get_sector_offset(cur_sector, 0); sectors_per_block = block_size >> 9; sectors = sectors_per_block - (cur_sector % sectors_per_block); if (sectors > scount) { sectors = scount; } if (offset == -1) { memset(buf, 0, 512); } else { ret = bx_read_image(fd, offset, cbuf, sectors * 512); if (ret != 512) { return -1; } } scount -= sectors; cur_sector += sectors; cbuf += sectors * 512; } return count; } ssize_t vpc_image_t::write(const void* buf, size_t count) { char *cbuf = (char*)buf; Bit32u scount = (Bit32u)(count / 512); vhd_footer_t *footer = (vhd_footer_t*)footer_buf; Bit64s offset, sectors, sectors_per_block; int ret; if (cpu_to_be32(footer->type) == VHD_FIXED) { return bx_write_image(fd, cur_sector * 512, (void*)buf, count); } while (scount > 0) { offset = get_sector_offset(cur_sector, 1); sectors_per_block = block_size >> 9; sectors = sectors_per_block - (cur_sector % sectors_per_block); if (sectors > scount) { sectors = scount; } if (offset == -1) { offset = alloc_block(cur_sector); if (offset < 0) return -1; } ret = bx_write_image(fd, offset, cbuf, sectors * 512); if (ret != sectors * 512) { return -1; } scount -= sectors; cur_sector += sectors; cbuf += sectors * 512; } return count; } Bit32u vpc_image_t::get_capabilities(void) { return HDIMAGE_HAS_GEOMETRY; } Bit32u vpc_image_t::vpc_checksum(Bit8u *buf, size_t size) { Bit32u res = 0; unsigned i; for (i = 0; i < size; i++) res += buf[i]; return ~res; } /* * Returns the absolute byte offset of the given sector in the image file. * If the sector is not allocated, -1 is returned instead. * * The parameter write must be 1 if the offset will be used for a write * operation (the block bitmaps is updated then), 0 otherwise. */ Bit64s vpc_image_t::get_sector_offset(Bit64s sector_num, int write) { Bit64u offset = sector_num * 512; Bit64u bitmap_offset, block_offset; Bit32u pagetable_index, pageentry_index; pagetable_index = offset / block_size; pageentry_index = (offset % block_size) / 512; if ((pagetable_index >= (Bit32u)max_table_entries) || (pagetable[pagetable_index] == 0xffffffff)) return -1; // not allocated bitmap_offset = 512 * (Bit64u) pagetable[pagetable_index]; block_offset = bitmap_offset + bitmap_size + (512 * pageentry_index); // We must ensure that we don't write to any sectors which are marked as // unused in the bitmap. We get away with setting all bits in the block // bitmap each time we write to a new block. This might cause Virtual PC to // miss sparse read optimization, but it's not a problem in terms of // correctness. if (write && (last_bitmap_offset != bitmap_offset)) { Bit8u *bitmap = new Bit8u[bitmap_size]; last_bitmap_offset = bitmap_offset; memset(bitmap, 0xff, bitmap_size); bx_write_image(fd, bitmap_offset, bitmap, bitmap_size); delete [] bitmap; } return (Bit64s)block_offset; } /* * Writes the footer to the end of the image file. This is needed when the * file grows as it overwrites the old footer * * Returns 0 on success and < 0 on error */ int vpc_image_t::rewrite_footer() { int ret; Bit64s offset = free_data_block_offset; ret = bx_write_image(fd, offset, footer_buf, HEADER_SIZE); if (ret < 0) return ret; return 0; } /* * Allocates a new block. This involves writing a new footer and updating * the Block Allocation Table to use the space at the old end of the image * file (overwriting the old footer) * * Returns the sectors' offset in the image file on success and < 0 on error */ Bit64s vpc_image_t::alloc_block(Bit64s sector_num) { Bit64s new_bat_offset; Bit64u old_fdbo; Bit32u index, bat_value; int ret; // Check if sector_num is valid if ((sector_num < 0) || (sector_num > sector_count)) return -1; // Write entry into in-memory BAT index = (sector_num * 512) / block_size; if (pagetable[index] != 0xFFFFFFFF) return -1; pagetable[index] = free_data_block_offset / 512; // Initialize the block's bitmap Bit8u *bitmap = new Bit8u[bitmap_size]; memset(bitmap, 0xff, bitmap_size); ret = bx_write_image(fd, free_data_block_offset, bitmap, bitmap_size); delete [] bitmap; if (ret < 0) { return ret; } // Write new footer (the old one will be overwritten) old_fdbo = free_data_block_offset; free_data_block_offset += (block_size + bitmap_size); ret = rewrite_footer(); if (ret < 0) { free_data_block_offset = old_fdbo; return -1; } // Write BAT entry to disk new_bat_offset = bat_offset + (4 * index); bat_value = be32_to_cpu(pagetable[index]); ret = bx_write_image(fd, new_bat_offset, &bat_value, 4); if (ret < 0) { free_data_block_offset = old_fdbo; return -1; } return get_sector_offset(sector_num, 0); } bochs-2.6/iodev/hdimage/cdrom_win32.cc0000644000175000017500000003335712020641504017503 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cdrom_win32.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // These are the low-level CDROM functions which are called // from 'harddrv.cc'. They effect the OS specific functionality // needed by the CDROM emulation in 'harddrv.cc'. Mostly, just // ioctl() calls and such. Should be fairly easy to add support // for your OS if it is not supported yet. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "bochs.h" #if BX_SUPPORT_CDROM #include "cdrom.h" #define LOG_THIS /* no SMF tricks here, not needed */ extern "C" { #include } #if defined(WIN32) // windows.h included by bochs.h #include #include "aspi-win32.h" #include "scsidefs.h" DWORD (*GetASPI32SupportInfo)(void); DWORD (*SendASPI32Command)(LPSRB); BOOL (*GetASPI32Buffer)(PASPI32BUFF); BOOL (*FreeASPI32Buffer)(PASPI32BUFF); BOOL (*TranslateASPI32Address)(PDWORD,PDWORD); DWORD (*GetASPI32DLLVersion)(void); static OSVERSIONINFO osinfo; static BOOL isWindowsXP; static BOOL bHaveDev; static UINT cdromCount = 0; static HINSTANCE hASPI = NULL; #define BX_CD_FRAMESIZE 2048 #define CD_FRAMESIZE 2048 // READ_TOC_EX structure(s) and #defines #define CDROM_READ_TOC_EX_FORMAT_TOC 0x00 #define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01 #define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02 #define CDROM_READ_TOC_EX_FORMAT_PMA 0x03 #define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04 #define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05 #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM #define IOCTL_CDROM_READ_TOC_EX CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS) #ifndef IOCTL_DISK_GET_LENGTH_INFO #define IOCTL_DISK_GET_LENGTH_INFO CTL_CODE(IOCTL_DISK_BASE, 0x0017, METHOD_BUFFERED, FILE_READ_ACCESS) #endif typedef struct _CDROM_READ_TOC_EX { UCHAR Format : 4; UCHAR Reserved1 : 3; // future expansion UCHAR Msf : 1; UCHAR SessionTrack; UCHAR Reserved2; // future expansion UCHAR Reserved3; // future expansion } CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX; typedef struct _TRACK_DATA { UCHAR Reserved; UCHAR Control : 4; UCHAR Adr : 4; UCHAR TrackNumber; UCHAR Reserved1; UCHAR Address[4]; } TRACK_DATA, *PTRACK_DATA; typedef struct _CDROM_TOC_SESSION_DATA { // Header UCHAR Length[2]; // add two bytes for this field UCHAR FirstCompleteSession; UCHAR LastCompleteSession; // One track, representing the first track // of the last finished session TRACK_DATA TrackData[1]; } CDROM_TOC_SESSION_DATA, *PCDROM_TOC_SESSION_DATA; // End READ_TOC_EX structure(s) and #defines #include bool ReadCDSector(unsigned int hid, unsigned int tid, unsigned int lun, unsigned long frame, unsigned char *buf, int bufsize) { HANDLE hEventSRB; SRB_ExecSCSICmd srb; DWORD dwStatus; hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL); memset(&srb,0,sizeof(SRB_ExecSCSICmd)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = hid; srb.SRB_Target = tid; srb.SRB_Lun = lun; srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_PostProc = hEventSRB; srb.SRB_BufPointer = buf; srb.SRB_BufLen = bufsize; srb.SRB_CDBLen = 10; srb.CDBByte[0] = SCSI_READ10; srb.CDBByte[2] = (unsigned char) (frame>>24); srb.CDBByte[3] = (unsigned char) (frame>>16); srb.CDBByte[4] = (unsigned char) (frame>>8); srb.CDBByte[5] = (unsigned char) (frame); srb.CDBByte[7] = 0; srb.CDBByte[8] = 1; /* read 1 frames */ ResetEvent(hEventSRB); dwStatus = SendASPI32Command((SRB *)&srb); if(dwStatus == SS_PENDING) { WaitForSingleObject(hEventSRB, 100000); } CloseHandle(hEventSRB); return (srb.SRB_TargStat == STATUS_GOOD); } int GetCDCapacity(unsigned int hid, unsigned int tid, unsigned int lun) { HANDLE hEventSRB; SRB_ExecSCSICmd srb; DWORD dwStatus; unsigned char buf[8]; hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL); memset(&buf, 0, sizeof(buf)); memset(&srb,0,sizeof(SRB_ExecSCSICmd)); srb.SRB_Cmd = SC_EXEC_SCSI_CMD; srb.SRB_HaId = hid; srb.SRB_Target = tid; srb.SRB_Lun = lun; srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; srb.SRB_SenseLen = SENSE_LEN; srb.SRB_PostProc = hEventSRB; srb.SRB_BufPointer = (unsigned char *)buf; srb.SRB_BufLen = 8; srb.SRB_CDBLen = 10; srb.CDBByte[0] = SCSI_READCDCAP; srb.CDBByte[2] = 0; srb.CDBByte[3] = 0; srb.CDBByte[4] = 0; srb.CDBByte[5] = 0; srb.CDBByte[8] = 0; ResetEvent(hEventSRB); dwStatus = SendASPI32Command((SRB *)&srb); if(dwStatus == SS_PENDING) { WaitForSingleObject(hEventSRB, 100000); } CloseHandle(hEventSRB); return ((buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]) * ((buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7]); } static unsigned int cdrom_count = 0; cdrom_interface::cdrom_interface(const char *dev) { char prefix[6]; sprintf(prefix, "CD%d", ++cdrom_count); put(prefix); fd = -1; // File descriptor not yet allocated if (dev == NULL) { path = NULL; } else { path = strdup(dev); } using_file=0; bUseASPI = FALSE; osinfo.dwOSVersionInfoSize = sizeof(osinfo); GetVersionEx(&osinfo); isWindowsXP = (osinfo.dwMajorVersion > 5) || ((osinfo.dwMajorVersion == 5) && (osinfo.dwMinorVersion >= 1)); } cdrom_interface::~cdrom_interface(void) { if (path) free(path); BX_DEBUG(("Exit")); } bx_bool cdrom_interface::insert_cdrom(const char *dev) { unsigned char buffer[BX_CD_FRAMESIZE]; // Load CD-ROM. Returns 0 if CD is not ready. if (dev != NULL) path = strdup(dev); BX_INFO (("load cdrom with path=%s", path)); char drive[256]; if ((path[1] == ':') && (strlen(path) == 2)) { if(osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) { // Use direct device access under windows NT/2k/XP // With all the backslashes it's hard to see, but to open D: drive // the name would be: \\.\d: sprintf(drive, "\\\\.\\%s", path); BX_INFO (("Using direct access for cdrom.")); // This trick only works for Win2k and WinNT, so warn the user of that. } else { BX_INFO(("Using ASPI for cdrom. Drive letters are unused yet.")); bUseASPI = TRUE; } using_file = 0; } else { strcpy(drive,path); using_file = 1; BX_INFO (("Opening image file as a cd")); } if(bUseASPI) { DWORD d; UINT cdr, cnt, max; UINT i, j, k; SRB_HAInquiry sh; SRB_GDEVBlock sd; if (!hASPI) { hASPI = LoadLibrary("WNASPI32.DLL"); if (hASPI) { SendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress(hASPI, "SendASPI32Command"); GetASPI32DLLVersion = (DWORD(*)(void))GetProcAddress(hASPI, "GetASPI32DLLVersion"); GetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress(hASPI, "GetASPI32SupportInfo"); d = GetASPI32DLLVersion(); BX_INFO(("WNASPI32.DLL version %d.%02d initialized", d & 0xff, (d >> 8) & 0xff)); } else { BX_PANIC(("Could not load ASPI drivers, so cdrom access will fail")); return 0; } } cdr = 0; bHaveDev = FALSE; d = GetASPI32SupportInfo(); cnt = LOBYTE(LOWORD(d)); for(i = 0; i < cnt; i++) { memset(&sh, 0, sizeof(sh)); sh.SRB_Cmd = SC_HA_INQUIRY; sh.SRB_HaId = i; SendASPI32Command((LPSRB)&sh); if(sh.SRB_Status != SS_COMP) continue; max = (int)sh.HA_Unique[3]; for(j = 0; j < max; j++) { for(k = 0; k < 8; k++) { memset(&sd, 0, sizeof(sd)); sd.SRB_Cmd = SC_GET_DEV_TYPE; sd.SRB_HaId = i; sd.SRB_Target = j; sd.SRB_Lun = k; SendASPI32Command((LPSRB)&sd); if(sd.SRB_Status == SS_COMP) { if(sd.SRB_DeviceType == DTYPE_CDROM) { cdr++; if(cdr > cdromCount) { hid = i; tid = j; lun = k; cdromCount++; bHaveDev = TRUE; } } } if(bHaveDev) break; } if(bHaveDev) break; } } fd=1; } else { hFile=CreateFile((char *)&drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); if (hFile !=(void *)0xFFFFFFFF) fd=1; if (!using_file) { DWORD lpBytesReturned; DeviceIoControl(hFile, IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, NULL, 0, &lpBytesReturned, NULL); } } if (fd < 0) { BX_ERROR(("open cd failed for %s: %s", path, strerror(errno))); return 0; } // I just see if I can read a sector to verify that a // CD is in the drive and readable. return read_block(buffer, 0, 2048); } bx_bool cdrom_interface::start_cdrom() { // Spin up the cdrom drive. if (fd >= 0) { BX_INFO(("start_cdrom: your OS is not supported yet")); return 0; // OS not supported yet, return 0 always } return 0; } void cdrom_interface::eject_cdrom() { // Logically eject the CD. I suppose we could stick in // some ioctl() calls to really eject the CD as well. if (fd >= 0) { if (using_file == 0) { if (!bUseASPI) { DWORD lpBytesReturned; DeviceIoControl(hFile, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &lpBytesReturned, NULL); } } fd = -1; } } bx_bool cdrom_interface::read_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format) { // Read CD TOC. Returns 0 if start track is out of bounds. if (fd < 0) { BX_PANIC(("cdrom: read_toc: file not open.")); return 0; } // This is a hack and works okay if there's one rom track only if (!isWindowsXP || using_file) { return create_toc(buf, length, msf, start_track, format); } // the implementation below is the platform-dependent code required // to read the TOC from a physical cdrom. if (isWindowsXP) { // This only works with WinXP CDROM_READ_TOC_EX input; memset(&input, 0, sizeof(input)); input.Format = format; input.Msf = msf; input.SessionTrack = start_track; // We have to allocate a chunk of memory to make sure it is aligned on a sector base. UCHAR *data = (UCHAR *) VirtualAlloc(NULL, 2048*2, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); unsigned long iBytesReturned; DeviceIoControl(hFile, IOCTL_CDROM_READ_TOC_EX, &input, sizeof(input), data, 804, &iBytesReturned, NULL); // now copy it to the users buffer and free our buffer *length = data[1] + (data[0] << 8) + 2; memcpy(buf, data, *length); VirtualFree(data, 0, MEM_RELEASE); return 1; } else { return 0; } } Bit32u cdrom_interface::capacity() { // Return CD-ROM capacity. I believe you want to return // the number of blocks of capacity the actual media has. if (bUseASPI) { return ((GetCDCapacity(hid, tid, lun) / 2352) + 1); } else if (using_file) { ULARGE_INTEGER FileSize; FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); return (Bit32u)(FileSize.QuadPart / 2048); } else { /* direct device access */ if (isWindowsXP) { LARGE_INTEGER length; DWORD iBytesReturned; DeviceIoControl(hFile, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &length, sizeof(length), &iBytesReturned, NULL); return (Bit32u)(length.QuadPart / 2048); } else { ULARGE_INTEGER FreeBytesForCaller; ULARGE_INTEGER TotalNumOfBytes; ULARGE_INTEGER TotalFreeBytes; GetDiskFreeSpaceEx(path, &FreeBytesForCaller, &TotalNumOfBytes, &TotalFreeBytes); return (Bit32u)(TotalNumOfBytes.QuadPart / 2048); } } } bx_bool BX_CPP_AttrRegparmN(3) cdrom_interface::read_block(Bit8u* buf, Bit32u lba, int blocksize) { // Read a single block from the CD LARGE_INTEGER pos; ssize_t n = 0; Bit8u try_count = 3; Bit8u* buf1; if (blocksize == 2352) { memset(buf, 0, 2352); memset(buf+1, 0xff, 10); Bit32u raw_block = lba + 150; buf[12] = (raw_block / 75) / 60; buf[13] = (raw_block / 75) % 60; buf[14] = (raw_block % 75); buf[15] = 0x01; buf1 = buf + 16; } else { buf1 = buf; } do { if(bUseASPI) { ReadCDSector(hid, tid, lun, lba, buf1, BX_CD_FRAMESIZE); n = BX_CD_FRAMESIZE; } else { pos.QuadPart = (LONGLONG)lba*BX_CD_FRAMESIZE; pos.LowPart = SetFilePointer(hFile, pos.LowPart, &pos.HighPart, SEEK_SET); if ((pos.LowPart == 0xffffffff) && (GetLastError() != NO_ERROR)) { BX_PANIC(("cdrom: read_block: SetFilePointer returned error.")); } else { ReadFile(hFile, (void *) buf1, BX_CD_FRAMESIZE, (unsigned long *) &n, NULL); } } } while ((n != BX_CD_FRAMESIZE) && (--try_count > 0)); return (n == BX_CD_FRAMESIZE); } #endif /* WIN32 */ #endif /* if BX_SUPPORT_CDROM */ bochs-2.6/iodev/hdimage/hdimage.cc0000644000175000017500000012615012020641504016745 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: hdimage.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "cdrom.h" #include "hdimage.h" #include "vmware3.h" #include "vmware4.h" #include "vvfat.h" #include "vpc-img.h" #if BX_HAVE_SYS_MMAN_H #include #endif #ifdef linux #include #include #endif #define LOG_THIS theHDImageCtl-> bx_hdimage_ctl_c* theHDImageCtl = NULL; int libhdimage_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theHDImageCtl = new bx_hdimage_ctl_c; bx_devices.pluginHDImageCtl = theHDImageCtl; return 0; // Success } else { return -1; } } void libhdimage_LTX_plugin_fini(void) { delete theHDImageCtl; } bx_hdimage_ctl_c::bx_hdimage_ctl_c() { put("hdimage", "IMG"); } device_image_t* bx_hdimage_ctl_c::init_image(Bit8u image_mode, Bit64u disk_size, const char *journal) { device_image_t *hdimage = NULL; // instantiate the right class switch (image_mode) { case BX_HDIMAGE_MODE_FLAT: hdimage = new default_image_t(); break; case BX_HDIMAGE_MODE_CONCAT: hdimage = new concat_image_t(); break; #if EXTERNAL_DISK_SIMULATOR case BX_HDIMAGE_MODE_EXTDISKSIM: hdimage = new EXTERNAL_DISK_SIMULATOR_CLASS(); break; #endif //EXTERNAL_DISK_SIMULATOR #if DLL_HD_SUPPORT case BX_HDIMAGE_MODE_DLL_HD: hdimage = new dll_image_t(); break; #endif //DLL_HD_SUPPORT case BX_HDIMAGE_MODE_SPARSE: hdimage = new sparse_image_t(); break; case BX_HDIMAGE_MODE_VMWARE3: hdimage = new vmware3_image_t(); break; case BX_HDIMAGE_MODE_VMWARE4: hdimage = new vmware4_image_t(); break; case BX_HDIMAGE_MODE_UNDOABLE: hdimage = new undoable_image_t(journal); break; case BX_HDIMAGE_MODE_GROWING: hdimage = new growing_image_t(); break; case BX_HDIMAGE_MODE_VOLATILE: hdimage = new volatile_image_t(journal); break; case BX_HDIMAGE_MODE_VVFAT: hdimage = new vvfat_image_t(disk_size, journal); break; case BX_HDIMAGE_MODE_VPC: hdimage = new vpc_image_t(); break; default: BX_PANIC(("unsupported HD mode : '%s'", hdimage_mode_names[image_mode])); break; } return hdimage; } #ifdef LOWLEVEL_CDROM LOWLEVEL_CDROM* bx_hdimage_ctl_c::init_cdrom(const char *dev) { return new LOWLEVEL_CDROM(dev); } #endif // helper functions int bx_read_image(int fd, Bit64s offset, void *buf, int count) { if (lseek(fd, offset, SEEK_SET) == -1) { return -1; } return read(fd, buf, count); } int bx_write_image(int fd, Bit64s offset, void *buf, int count) { if (lseek(fd, offset, SEEK_SET) == -1) { return -1; } return write(fd, buf, count); } /*** base class device_image_t ***/ device_image_t::device_image_t() { hd_size = 0; } Bit32u device_image_t::get_capabilities() { return (cylinders == 0) ? HDIMAGE_AUTO_GEOMETRY : 0; } /*** default_image_t function definitions ***/ int default_image_t::open(const char* pathname) { return open(pathname, O_RDWR); } int default_image_t::open(const char* pathname, int flags) { #ifdef WIN32 HANDLE hFile = CreateFile(pathname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL); if (hFile != INVALID_HANDLE_VALUE) { ULARGE_INTEGER FileSize; FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart); GetFileTime(hFile, NULL, NULL, &mtime); CloseHandle(hFile); if ((FileSize.LowPart != INVALID_FILE_SIZE) || (GetLastError() == NO_ERROR)) { hd_size = FileSize.QuadPart; } else { return -1; } } else { return -1; } #endif fd = ::open(pathname, flags #ifdef O_BINARY | O_BINARY #endif ); if (fd < 0) { return fd; } #ifndef WIN32 /* look at size of image file to calculate disk geometry */ struct stat stat_buf; if (fstat(fd, &stat_buf)) { BX_PANIC(("fstat() returns error!")); } #ifdef linux if (stat_buf.st_rdev) { // Is this a special device file (e.g. /dev/sde) ? ioctl(fd, BLKGETSIZE64, &hd_size); // yes it's! } else #endif { hd_size = (Bit64u)stat_buf.st_size; // standard unix procedure to get size of regular files } mtime = stat_buf.st_mtime; #endif BX_INFO(("hd_size: "FMT_LL"u", hd_size)); if (hd_size <= 0) BX_PANIC(("size of disk image not detected / invalid")); if ((hd_size % 512) != 0) BX_PANIC(("size of disk image must be multiple of 512 bytes")); return fd; } void default_image_t::close() { if (fd > -1) { ::close(fd); } } Bit64s default_image_t::lseek(Bit64s offset, int whence) { return (Bit64s)::lseek(fd, (off_t)offset, whence); } ssize_t default_image_t::read(void* buf, size_t count) { return ::read(fd, (char*) buf, count); } ssize_t default_image_t::write(const void* buf, size_t count) { return ::write(fd, (char*) buf, count); } Bit32u default_image_t::get_timestamp() { return (fat_datetime(mtime, 1) | (fat_datetime(mtime, 0) << 16)); } char increment_string(char *str, int diff) { // find the last character of the string, and increment it. char *p = str; while (*p != 0) p++; BX_ASSERT(p>str); // choke on zero length strings p--; // point to last character of the string (*p) += diff; // increment to next/previous ascii code. BX_DEBUG(("increment string returning '%s'", str)); return (*p); } /*** concat_image_t function definitions ***/ concat_image_t::concat_image_t() { fd = -1; } void concat_image_t::increment_string(char *str) { ::increment_string(str, +1); } int concat_image_t::open(const char* pathname0) { char *pathname = strdup(pathname0); BX_DEBUG(("concat_image_t.open")); Bit64s start_offset = 0; for (int i=0; i -1) { ::close(fd); } } Bit64s concat_image_t::lseek(Bit64s offset, int whence) { if ((offset % 512) != 0) BX_PANIC(("lseek HD with offset not multiple of 512")); BX_DEBUG(("concat_image_t.lseek(%d)", whence)); // is this offset in this disk image? if (offset < thismin) { // no, look at previous images for (int i=index-1; i>=0; i--) { if (offset >= start_offset_table[i]) { index = i; fd = fd_table[i]; thismin = start_offset_table[i]; thismax = thismin + length_table[i] - 1; BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index)); break; } } } else if (offset > thismax) { // no, look at later images for (int i=index+1; i= length_table[index]) { BX_PANIC(("concat_image_t.lseek to byte %ld failed", (long)offset)); return -1; } seek_was_last_op = 1; return (Bit64s)::lseek(fd, (off_t)offset, whence); } ssize_t concat_image_t::read(void* buf, size_t count) { BX_DEBUG(("concat_image_t.read %ld bytes", (long)count)); // notice if anyone does sequential read or write without seek in between. // This can be supported pretty easily, but needs additional checks for // end of a partial image. if (!seek_was_last_op) BX_PANIC(("no seek before read")); return ::read(fd, (char*) buf, count); } ssize_t concat_image_t::write(const void* buf, size_t count) { BX_DEBUG(("concat_image_t.write %ld bytes", (long)count)); // notice if anyone does sequential read or write without seek in between. // This can be supported pretty easily, but needs additional checks for // end of a partial image. if (!seek_was_last_op) BX_PANIC(("no seek before write")); return ::write(fd, (char*) buf, count); } /*** sparse_image_t function definitions ***/ sparse_image_t::sparse_image_t() { fd = -1; pathname = NULL; #ifdef _POSIX_MAPPED_FILES mmap_header = NULL; #endif pagetable = NULL; parent_image = NULL; } /* void showpagetable(Bit32u * pagetable, size_t numpages) { printf("Non null pages: "); for (int i = 0; i < numpages; i++) { if (pagetable[i] != 0xffffffff) { printf("%d ", i); } } printf("\n"); } */ void sparse_image_t::read_header() { BX_ASSERT(sizeof(header) == SPARSE_HEADER_SIZE); int ret = ::read(fd, &header, sizeof(header)); if (-1 == ret) { panic(strerror(errno)); } if (sizeof(header) != ret) { panic("could not read entire header"); } if (dtoh32(header.magic) != SPARSE_HEADER_MAGIC) { panic("failed header magic check"); } if ((dtoh32(header.version) != SPARSE_HEADER_VERSION) && (dtoh32(header.version) != SPARSE_HEADER_V1)) { panic("unknown version in header"); } pagesize = dtoh32(header.pagesize); Bit32u numpages = dtoh32(header.numpages); total_size = pagesize; total_size *= numpages; pagesize_shift = 0; while ((pagesize >> pagesize_shift) > 1) pagesize_shift++; if ((Bit32u)(1 << pagesize_shift) != pagesize) { panic("failed block size header check"); } pagesize_mask = pagesize - 1; size_t preamble_size = (sizeof(Bit32u) * numpages) + sizeof(header); data_start = 0; while ((size_t)data_start < preamble_size) data_start += pagesize; bx_bool did_mmap = 0; #ifdef _POSIX_MAPPED_FILES // Try to memory map from the beginning of the file (0 is trivially a page multiple) void *mmap_header = mmap(NULL, preamble_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (mmap_header == MAP_FAILED) { BX_INFO(("failed to mmap sparse disk file - using conventional file access")); mmap_header = NULL; } else { mmap_length = preamble_size; did_mmap = 1; pagetable = ((Bit32u *) (((Bit8u *) mmap_header) + sizeof(header))); system_pagesize_mask = getpagesize() - 1; } #endif if (!did_mmap) { pagetable = new Bit32u[numpages]; if (pagetable == NULL) { panic("could not allocate memory for sparse disk block table"); } ret = ::read(fd, pagetable, sizeof(Bit32u) * numpages); if (-1 == ret) { panic(strerror(errno)); } if ((int)(sizeof(Bit32u) * numpages) != ret) { panic("could not read entire block table"); } } } int sparse_image_t::open(const char* pathname0) { pathname = strdup(pathname0); BX_DEBUG(("sparse_image_t.open")); fd = ::open(pathname, O_RDWR #ifdef O_BINARY | O_BINARY #endif ); if (fd < 0) { return -1; // open failed } BX_DEBUG(("sparse_image: open image %s", pathname)); read_header(); struct stat stat_buf; if (fstat(fd, &stat_buf) != 0) panic(("fstat() returns error!")); underlying_filesize = stat_buf.st_size; if ((underlying_filesize % pagesize) != 0) panic("size of sparse disk image is not multiple of page size"); underlying_current_filepos = 0; if (-1 == ::lseek(fd, 0, SEEK_SET)) panic("error while seeking to start of file"); lseek(0, SEEK_SET); //showpagetable(pagetable, header.numpages); char * parentpathname = strdup(pathname); char lastchar = ::increment_string(parentpathname, -1); if ((lastchar >= '0') && (lastchar <= '9')) { struct stat stat_buf; if (0 == stat(parentpathname, &stat_buf)) { parent_image = new sparse_image_t(); int ret = parent_image->open(parentpathname); if (ret != 0) return ret; if ( (parent_image->pagesize != pagesize) || (parent_image->total_size != total_size)) { panic("child drive image does not have same page count/page size configuration"); } } } if (parentpathname != NULL) free(parentpathname); if (dtoh32(header.version) == SPARSE_HEADER_VERSION) { hd_size = dtoh64(header.disk); BX_INFO(("sparse: pagesize = 0x%x, data_start = 0x" FMT_LL "x", pagesize, data_start)); } return 0; // success } void sparse_image_t::close() { BX_DEBUG(("concat_image_t.close")); if (pathname != NULL) { free(pathname); } #ifdef _POSIX_MAPPED_FILES if (mmap_header != NULL) { int ret = munmap(mmap_header, mmap_length); if (ret != 0) BX_INFO(("failed to un-memory map sparse disk file")); } pagetable = NULL; // We didn't malloc it #endif if (fd > -1) { ::close(fd); } if (pagetable != NULL) { delete [] pagetable; } if (parent_image != NULL) { delete parent_image; } } Bit64s sparse_image_t::lseek(Bit64s offset, int whence) { //showpagetable(pagetable, header.numpages); if ((offset % 512) != 0) BX_PANIC(("lseek HD with offset not multiple of 512")); if (whence != SEEK_SET) BX_PANIC(("lseek HD with whence not SEEK_SET")); BX_DEBUG(("sparse_image_t.lseek(%d)", whence)); if (offset > total_size) { BX_PANIC(("sparse_image_t.lseek to byte %ld failed", (long)offset)); return -1; } //printf("Seeking to position %ld\n", (long) offset); set_virtual_page((Bit32u)(offset >> pagesize_shift)); position_page_offset = (Bit32u)(offset & pagesize_mask); return 0; } inline Bit64s sparse_image_t::get_physical_offset() { Bit64s physical_offset = data_start; physical_offset += ((Bit64s)position_physical_page << pagesize_shift); physical_offset += position_page_offset; return physical_offset; } void sparse_image_t::set_virtual_page(Bit32u new_virtual_page) { position_virtual_page = new_virtual_page; position_physical_page = dtoh32(pagetable[position_virtual_page]); } ssize_t sparse_image_t::read_page_fragment(Bit32u read_virtual_page, Bit32u read_page_offset, size_t read_size, void * buf) { if (read_virtual_page != position_virtual_page) { set_virtual_page(read_virtual_page); } position_page_offset = read_page_offset; if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED) { if (parent_image != NULL) { return parent_image->read_page_fragment(read_virtual_page, read_page_offset, read_size, buf); } else { memset(buf, 0, read_size); } } else { Bit64s physical_offset = get_physical_offset(); if (physical_offset != underlying_current_filepos) { off_t ret = ::lseek(fd, (off_t)physical_offset, SEEK_SET); // underlying_current_filepos update deferred if (ret == -1) panic(strerror(errno)); } //printf("Reading %s at position %ld size %d\n", pathname, (long) physical_offset, (long) read_size); ssize_t readret = ::read(fd, buf, read_size); if (readret == -1) { panic(strerror(errno)); } if ((size_t)readret != read_size) { panic("could not read block contents from file"); } underlying_current_filepos = physical_offset + read_size; } return read_size; } ssize_t sparse_image_t::read(void* buf, size_t count) { //showpagetable(pagetable, header.numpages); ssize_t total_read = 0; BX_DEBUG(("sparse_image_t.read %ld bytes", (long)count)); while (count != 0) { size_t can_read = pagesize - position_page_offset; if (count < can_read) can_read = count; BX_ASSERT (can_read != 0); size_t was_read = read_page_fragment(position_virtual_page, position_page_offset, can_read, buf); if (was_read != can_read) { BX_PANIC(("could not read from sparse disk")); } total_read += can_read; position_page_offset += can_read; if (position_page_offset == pagesize) { position_page_offset = 0; set_virtual_page(position_virtual_page + 1); } BX_ASSERT(position_page_offset < pagesize); buf = (((Bit8u *) buf) + can_read); count -= can_read; } return total_read; } void sparse_image_t::panic(const char * message) { char buffer[1024]; if (message == NULL) { snprintf(buffer, sizeof(buffer), "error with sparse disk image %s", pathname); } else { snprintf(buffer, sizeof(buffer), "error with sparse disk image %s - %s", pathname, message); } BX_PANIC(("%s", buffer)); } ssize_t sparse_image_t::write(const void* buf, size_t count) { //showpagetable(pagetable, header.numpages); ssize_t total_written = 0; Bit32u update_pagetable_start = position_virtual_page; Bit32u update_pagetable_count = 0; BX_DEBUG(("sparse_image_t.write %ld bytes", (long)count)); while (count != 0) { size_t can_write = pagesize - position_page_offset; if (count < can_write) can_write = count; BX_ASSERT (can_write != 0); if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED) { // We just add on another page at the end of the file // Reclamation, compaction etc should currently be done off-line Bit64s data_size = underlying_filesize - data_start; BX_ASSERT((data_size % pagesize) == 0); Bit32u data_size_pages = (Bit32u)(data_size / pagesize); Bit32u next_data_page = data_size_pages; pagetable[position_virtual_page] = htod32(next_data_page); position_physical_page = next_data_page; Bit64s page_file_start = data_start + ((Bit64s)position_physical_page << pagesize_shift); if (parent_image != NULL) { // If we have a parent, we must merge our portion with the parent void *writebuffer = NULL; if (can_write == pagesize) { writebuffer = (void *) buf; } else { writebuffer = malloc(pagesize); if (writebuffer == NULL) panic("Cannot allocate sufficient memory for page-merge in write"); // Read entire page - could optimize, but simple for now parent_image->read_page_fragment(position_virtual_page, 0, pagesize, writebuffer); void *dest_start = ((Bit8u *) writebuffer) + position_page_offset; memcpy(dest_start, buf, can_write); } int ret = (int)::lseek(fd, page_file_start, SEEK_SET); // underlying_current_filepos update deferred if (ret == -1) panic(strerror(errno)); ret = ::write(fd, writebuffer, pagesize); if (ret == -1) panic(strerror(errno)); if (pagesize != (Bit32u)ret) panic("failed to write entire merged page to disk"); if (can_write != pagesize) { free(writebuffer); } } else { // We need to write a zero page because read has been returning zeroes // We seek as close to the page end as possible, and then write a little // This produces a sparse file which has blanks // Also very quick, even when pagesize is massive int ret = (int)::lseek(fd, page_file_start + pagesize - 4, SEEK_SET); // underlying_current_filepos update deferred if (ret == -1) panic(strerror(errno)); Bit32u zero = 0; ret = ::write(fd, &zero, 4); if (ret == -1) panic(strerror(errno)); if (ret != 4) panic("failed to write entire blank page to disk"); } update_pagetable_count = (position_virtual_page - update_pagetable_start) + 1; underlying_filesize = underlying_current_filepos = page_file_start + pagesize; } BX_ASSERT(position_physical_page != SPARSE_PAGE_NOT_ALLOCATED); Bit64s physical_offset = get_physical_offset(); if (physical_offset != underlying_current_filepos) { off_t ret = ::lseek(fd, (off_t)physical_offset, SEEK_SET); // underlying_current_filepos update deferred if (ret == -1) panic(strerror(errno)); } //printf("Writing at position %ld size %d\n", (long) physical_offset, can_write); ssize_t writeret = ::write(fd, buf, can_write); if (writeret == -1) { panic(strerror(errno)); } if ((size_t)writeret != can_write) { panic("could not write block contents to file"); } underlying_current_filepos = physical_offset + can_write; total_written += can_write; position_page_offset += can_write; if (position_page_offset == pagesize) { position_page_offset = 0; set_virtual_page(position_virtual_page + 1); } BX_ASSERT(position_page_offset < pagesize); buf = (((Bit8u *) buf) + can_write); count -= can_write; } if (update_pagetable_count != 0) { bx_bool done = 0; off_t pagetable_write_from = sizeof(header) + (sizeof(Bit32u) * update_pagetable_start); size_t write_bytecount = update_pagetable_count * sizeof(Bit32u); #ifdef _POSIX_MAPPED_FILES if (mmap_header != NULL) { // Sync from the beginning of the page size_t system_page_offset = pagetable_write_from & system_pagesize_mask; void *start = ((Bit8u *) mmap_header + pagetable_write_from - system_page_offset); int ret = msync(start, system_page_offset + write_bytecount, MS_ASYNC); if (ret != 0) panic(strerror(errno)); done = 1; } #endif if (!done) { int ret = (int)::lseek(fd, pagetable_write_from, SEEK_SET); // underlying_current_filepos update deferred if (ret == -1) panic(strerror(errno)); //printf("Writing header at position %ld size %ld\n", (long) pagetable_write_from, (long) write_bytecount); ret = ::write(fd, &pagetable[update_pagetable_start], write_bytecount); if (ret == -1) panic(strerror(errno)); if ((size_t)ret != write_bytecount) panic("could not write entire updated block header"); underlying_current_filepos = pagetable_write_from + write_bytecount; } } return total_written; } #if DLL_HD_SUPPORT /*** dll_image_t function definitions ***/ /* function vdisk_open(path:PChar;numclusters,clustersize:integer):integer; procedure vdisk_read(vunit:integer;blk:integer;var buf:TBlock); procedure vdisk_write(vunit:integer;blk:integer;var buf:TBlock); procedure vdisk_close(vunit:integer); */ HINSTANCE hlib_vdisk = 0; int (*vdisk_open) (const char *path,int numclusters,int clustersize); void (*vdisk_read) (int vunit,int blk,void *buf); void (*vdisk_write) (int vunit,int blk,const void *buf); void (*vdisk_close) (int vunit); int dll_image_t::open (const char* pathname) { if (hlib_vdisk == 0) { hlib_vdisk = LoadLibrary("vdisk.dll"); if (hlib_vdisk != 0) { vdisk_read = (void (*)(int,int,void*)) GetProcAddress(hlib_vdisk,"vdisk_read"); vdisk_write = (void (*)(int,int,const void*)) GetProcAddress(hlib_vdisk,"vdisk_write"); vdisk_open = (int (*)(const char *,int,int)) GetProcAddress(hlib_vdisk,"vdisk_open"); vdisk_close = (void (*)(int)) GetProcAddress(hlib_vdisk,"vdisk_close"); } } if (hlib_vdisk != 0) { vunit = vdisk_open(pathname,0x10000,64); vblk = 0; } else { vunit = -2; } return vunit; } void dll_image_t::close () { if (vunit >= 0 && hlib_vdisk != 0) { vdisk_close(vunit); } } Bit64s dll_image_t::lseek(Bit64s offset, int whence) { vblk = (int)(offset >> 9); return 0; } ssize_t dll_image_t::read (void* buf, size_t count) { if (vunit >= 0 && hlib_vdisk != 0) { vdisk_read(vunit,vblk,buf); return count; } else { return -1; } } ssize_t dll_image_t::write (const void* buf, size_t count) { if (vunit >= 0 && hlib_vdisk != 0) { vdisk_write(vunit,vblk,buf); return count; } else { return -1; } } #endif // DLL_HD_SUPPORT // redolog implementation redolog_t::redolog_t() { fd = -1; catalog = NULL; bitmap = NULL; extent_index = (Bit32u)0; extent_offset = (Bit32u)0; extent_next = (Bit32u)0; } void redolog_t::print_header() { BX_INFO(("redolog : Standard Header : magic='%s', type='%s', subtype='%s', version = %d.%d", header.standard.magic, header.standard.type, header.standard.subtype, dtoh32(header.standard.version)/0x10000, dtoh32(header.standard.version)%0x10000)); if (dtoh32(header.standard.version) == STANDARD_HEADER_VERSION) { BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL "d", dtoh32(header.specific.catalog), dtoh32(header.specific.bitmap), dtoh32(header.specific.extent), dtoh64(header.specific.disk))); } else if (dtoh32(header.standard.version) == STANDARD_HEADER_V1) { redolog_header_v1_t header_v1; memcpy(&header_v1, &header, STANDARD_HEADER_SIZE); BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = " FMT_LL "d", dtoh32(header_v1.specific.catalog), dtoh32(header_v1.specific.bitmap), dtoh32(header_v1.specific.extent), dtoh64(header_v1.specific.disk))); } } int redolog_t::make_header(const char* type, Bit64u size) { Bit32u entries, extent_size, bitmap_size; Bit64u maxsize; Bit32u flip=0; // Set standard header values memset(&header, 0, sizeof(redolog_header_t)); strcpy((char*)header.standard.magic, STANDARD_HEADER_MAGIC); strcpy((char*)header.standard.type, REDOLOG_TYPE); strcpy((char*)header.standard.subtype, type); header.standard.version = htod32(STANDARD_HEADER_VERSION); header.standard.header = htod32(STANDARD_HEADER_SIZE); entries = 512; bitmap_size = 1; // Compute #entries and extent size values do { extent_size = 8 * bitmap_size * 512; header.specific.catalog = htod32(entries); header.specific.bitmap = htod32(bitmap_size); header.specific.extent = htod32(extent_size); maxsize = (Bit64u)entries * (Bit64u)extent_size; flip++; if(flip&0x01) bitmap_size *= 2; else entries *= 2; } while (maxsize < size); header.specific.timestamp = 0; header.specific.disk = htod64(size); print_header(); catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u)); bitmap = (Bit8u*)malloc(dtoh32(header.specific.bitmap)); if ((catalog == NULL) || (bitmap==NULL)) BX_PANIC(("redolog : could not malloc catalog or bitmap")); for (Bit32u i=0; i= extent_next) extent_next = dtoh32(catalog[i]) + 1; } } BX_INFO(("redolog : next extent will be at index %d",extent_next)); // memory used for storing bitmaps bitmap = (Bit8u *)malloc(dtoh32(header.specific.bitmap)); bitmap_blocks = 1 + (dtoh32(header.specific.bitmap) - 1) / 512; extent_blocks = 1 + (dtoh32(header.specific.extent) - 1) / 512; BX_DEBUG(("redolog : each bitmap is %d blocks", bitmap_blocks)); BX_DEBUG(("redolog : each extent is %d blocks", extent_blocks)); imagepos = 0; bitmap_update = 1; return 0; } void redolog_t::close() { if (fd >= 0) ::close(fd); if (catalog != NULL) free(catalog); if (bitmap != NULL) free(bitmap); } Bit64u redolog_t::get_size() { return dtoh64(header.specific.disk); } Bit32u redolog_t::get_timestamp() { return dtoh32(header.specific.timestamp); } bx_bool redolog_t::set_timestamp(Bit32u timestamp) { header.specific.timestamp = htod32(timestamp); // Update header bx_write_image(fd, 0, &header, dtoh32(header.standard.header)); return 1; } Bit64s redolog_t::lseek(Bit64s offset, int whence) { if ((offset % 512) != 0) { BX_PANIC(("redolog : lseek() offset not multiple of 512")); return -1; } if (whence == SEEK_SET) { imagepos = offset; } else if (whence == SEEK_CUR) { imagepos += offset; } else { BX_PANIC(("redolog: lseek() mode not supported yet")); return -1; } if (imagepos > (Bit64s)dtoh64(header.specific.disk)) { BX_PANIC(("redolog : lseek() to byte %ld failed", (long)offset)); return -1; } Bit32u old_extent_index = extent_index; extent_index = (Bit32u)(imagepos / dtoh32(header.specific.extent)); if (extent_index != old_extent_index) { bitmap_update = 1; } extent_offset = (Bit32u)((imagepos % dtoh32(header.specific.extent)) / 512); BX_DEBUG(("redolog : lseeking extent index %d, offset %d",extent_index, extent_offset)); return imagepos; } ssize_t redolog_t::read(void* buf, size_t count) { Bit64s block_offset, bitmap_offset; ssize_t ret; if (count != 512) { BX_PANIC(("redolog : read() with count not 512")); return -1; } BX_DEBUG(("redolog : reading index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index]))); if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) { // page not allocated return 0; } bitmap_offset = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u)); bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks); block_offset = bitmap_offset + ((Bit64s)512 * (bitmap_blocks + extent_offset)); BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset)); BX_DEBUG(("redolog : block offset is %x", (Bit32u)block_offset)); if (bitmap_update) { if (bx_read_image(fd, (off_t)bitmap_offset, bitmap, dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap)) { BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index)); return -1; } bitmap_update = 0; } if (((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00) { BX_DEBUG(("read not in redolog")); // bitmap says block not in redolog return 0; } ret = bx_read_image(fd, (off_t)block_offset, buf, count); if (ret >= 0) lseek(512, SEEK_CUR); return ret; } ssize_t redolog_t::write(const void* buf, size_t count) { Bit32u i; Bit64s block_offset, bitmap_offset, catalog_offset; ssize_t written; bx_bool update_catalog = 0; if (count != 512) { BX_PANIC(("redolog : write() with count not 512")); return -1; } BX_DEBUG(("redolog : writing index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index]))); if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED) { if (extent_next >= dtoh32(header.specific.catalog)) { BX_PANIC(("redolog : can't allocate new extent... catalog is full")); return -1; } BX_DEBUG(("redolog : allocating new extent at %d", extent_next)); // Extent not allocated, allocate new catalog[extent_index] = htod32(extent_next); extent_next += 1; char *zerobuffer = (char*)malloc(512); memset(zerobuffer, 0, 512); // Write bitmap bitmap_offset = (Bit64s)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u)); bitmap_offset += (Bit64s)512 * dtoh32(catalog[extent_index]) * (extent_blocks + bitmap_blocks); ::lseek(fd, (off_t)bitmap_offset, SEEK_SET); for (i=0; i> (extent_offset%8)) & 0x01) == 0x00) { bitmap[extent_offset/8] |= 1 << (extent_offset%8); bx_write_image(fd, (off_t)bitmap_offset, bitmap, dtoh32(header.specific.bitmap)); } // Write catalog if (update_catalog) { // FIXME if mmap catalog_offset = (Bit64s)STANDARD_HEADER_SIZE + (extent_index * sizeof(Bit32u)); BX_DEBUG(("redolog : writing catalog at offset %x", (Bit32u)catalog_offset)); bx_write_image(fd, (off_t)catalog_offset, &catalog[extent_index], sizeof(Bit32u)); } if (written >= 0) lseek(512, SEEK_CUR); return written; } /*** growing_image_t function definitions ***/ growing_image_t::growing_image_t() { redolog = new redolog_t(); } growing_image_t::~growing_image_t() { delete redolog; } int growing_image_t::open(const char* pathname) { int filedes = redolog->open(pathname, REDOLOG_SUBTYPE_GROWING); hd_size = redolog->get_size(); BX_INFO(("'growing' disk opened, growing file is '%s'", pathname)); return filedes; } void growing_image_t::close() { redolog->close(); } Bit64s growing_image_t::lseek(Bit64s offset, int whence) { return redolog->lseek(offset, whence); } ssize_t growing_image_t::read(void* buf, size_t count) { size_t n = 0; ssize_t ret = 0; memset(buf, 0, count); while (n < count) { ret = redolog->read((char*) buf, 512); if (ret < 0) break; n += 512; } return (ret < 0) ? ret : count; } ssize_t growing_image_t::write(const void* buf, size_t count) { size_t n = 0; ssize_t ret = 0; while (n < count) { ret = redolog->write((char*) buf, 512); if (ret < 0) break; n += 512; } return (ret < 0) ? ret : count; } /*** undoable_image_t function definitions ***/ undoable_image_t::undoable_image_t(const char* _redolog_name) { redolog = new redolog_t(); ro_disk = new default_image_t(); redolog_name = NULL; if (_redolog_name != NULL) { if (strcmp(_redolog_name,"") != 0) { redolog_name = strdup(_redolog_name); } } } undoable_image_t::~undoable_image_t() { delete redolog; delete ro_disk; } int undoable_image_t::open(const char* pathname) { char *logname=NULL; Bit32u timestamp1, timestamp2; if (ro_disk->open(pathname, O_RDONLY)<0) return -1; hd_size = ro_disk->hd_size; // if redolog name was set if (redolog_name != NULL) { if (strcmp(redolog_name, "") != 0) { logname = (char*)malloc(strlen(redolog_name) + 1); strcpy(logname, redolog_name); } } // Otherwise we make up the redolog filename from the pathname if (logname == NULL) { logname = (char*)malloc(strlen(pathname) + UNDOABLE_REDOLOG_EXTENSION_LENGTH + 1); sprintf(logname, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION); } if (redolog->open(logname,REDOLOG_SUBTYPE_UNDOABLE) < 0) { if (redolog->create(logname, REDOLOG_SUBTYPE_UNDOABLE, hd_size) < 0) { BX_PANIC(("Can't open or create redolog '%s'",logname)); return -1; } } if (hd_size != redolog->get_size()) { BX_PANIC(("size reported by redolog doesn't match r/o disk size")); free(logname); return -1; } timestamp1 = ro_disk->get_timestamp(); timestamp2 = redolog->get_timestamp(); if (timestamp2 != 0) { if (timestamp1 != timestamp2) { BX_PANIC(("unexpected modification time of the r/o disk")); free(logname); return -1; } } else if (timestamp1 != 0) { redolog->set_timestamp(timestamp1); } BX_INFO(("'undoable' disk opened: ro-file is '%s', redolog is '%s'", pathname, logname)); free(logname); return 0; } void undoable_image_t::close() { redolog->close(); ro_disk->close(); if (redolog_name!=NULL) free(redolog_name); } Bit64s undoable_image_t::lseek(Bit64s offset, int whence) { redolog->lseek(offset, whence); return ro_disk->lseek(offset, whence); } ssize_t undoable_image_t::read(void* buf, size_t count) { size_t n = 0; ssize_t ret = 0; while (n < count) { if ((size_t)redolog->read((char*) buf, 512) != 512) { ret = ro_disk->read((char*) buf, 512); if (ret < 0) break; } n += 512; } return (ret < 0) ? ret : count; } ssize_t undoable_image_t::write(const void* buf, size_t count) { size_t n = 0; ssize_t ret = 0; while (n < count) { ret = redolog->write((char*) buf, 512); if (ret < 0) break; n += 512; } return (ret < 0) ? ret : count; } /*** volatile_image_t function definitions ***/ volatile_image_t::volatile_image_t(const char* _redolog_name) { redolog = new redolog_t(); ro_disk = new default_image_t(); redolog_temp = NULL; redolog_name = NULL; if (_redolog_name != NULL) { if (strcmp(_redolog_name,"") != 0) { redolog_name = strdup(_redolog_name); } } } volatile_image_t::~volatile_image_t() { delete redolog; delete ro_disk; } int volatile_image_t::open(const char* pathname) { int filedes; const char *logname=NULL; if (ro_disk->open(pathname, O_RDONLY)<0) return -1; hd_size = ro_disk->hd_size; // if redolog name was set if (redolog_name != NULL) { if (strcmp(redolog_name, "") != 0) { logname = redolog_name; } } // otherwise use pathname as template if (logname == NULL) { logname = pathname; } redolog_temp = (char*)malloc(strlen(logname) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1); sprintf (redolog_temp, "%s%s", logname, VOLATILE_REDOLOG_EXTENSION); filedes = mkstemp (redolog_temp); if (filedes < 0) { BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); return -1; } if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, hd_size) < 0) { BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); return -1; } #if (!defined(WIN32)) && !BX_WITH_MACOS // on unix it is legal to delete an open file unlink(redolog_temp); #endif BX_INFO(("'volatile' disk opened: ro-file is '%s', redolog is '%s'", pathname, redolog_temp)); return 0; } void volatile_image_t::close() { redolog->close(); ro_disk->close(); #if defined(WIN32) || BX_WITH_MACOS // on non-unix we have to wait till the file is closed to delete it unlink(redolog_temp); #endif if (redolog_temp!=NULL) free(redolog_temp); if (redolog_name!=NULL) free(redolog_name); } Bit64s volatile_image_t::lseek(Bit64s offset, int whence) { redolog->lseek(offset, whence); return ro_disk->lseek(offset, whence); } ssize_t volatile_image_t::read(void* buf, size_t count) { size_t n = 0; ssize_t ret = 0; while (n < count) { if ((size_t)redolog->read((char*) buf, 512) != 512) { ret = ro_disk->read((char*) buf, 512); if (ret < 0) break; } n += 512; } return (ret < 0) ? ret : count; } ssize_t volatile_image_t::write(const void* buf, size_t count) { size_t n = 0; ssize_t ret = 0; while (n < count) { ret = redolog->write((char*) buf, 512); if (ret < 0) break; n += 512; } return (ret < 0) ? ret : count; } bochs-2.6/iodev/hdimage/Makefile.in0000644000175000017500000002522612020641504017107 0ustar guillemguillem# Copyright (C) 2012 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Makefile for the iodev/hdimage component of bochs @SUFFIX_LINE@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ VPATH = @srcdir@ bindir = @bindir@ libdir = @libdir@ datarootdir = @datarootdir@ mandir = @mandir@ man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 docdir = $(datarootdir)/doc/bochs sharedir = $(datarootdir)/bochs top_builddir = .. top_srcdir = @top_srcdir@ SHELL = @SHELL@ @SET_MAKE@ CXX = @CXX@ CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ PLUGIN_PATH=@libdir@ top_builddir = ../.. LIBTOOL=@LIBTOOL@ WIN32_DLL_IMPORT_LIBRARY=../../dllexports.a CDROM_OBJS = @CDROM_OBJS@ BX_INCDIRS = -I.. -I../.. -I$(srcdir)/.. -I$(srcdir)/../.. -I../../@INSTRUMENT_DIR@ -I$(srcdir)/../../@INSTRUMENT_DIR@ LOCAL_CXXFLAGS = $(MCH_CFLAGS) OBJS_THAT_CAN_BE_PLUGINS = \ hdimage.o OBJS_THAT_SUPPORT_OTHER_PLUGINS = \ vmware3.o \ vmware4.o \ vvfat.o \ vpc-img.o \ $(CDROM_OBJS) NONPLUGIN_OBJS = @IODEV_EXT_NON_PLUGIN_OBJS@ PLUGIN_OBJS = @IODEV_EXT_PLUGIN_OBJS@ all: libhdimage.a plugins: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@) libhdimage.a: $(NONPLUGIN_OBJS) @RMCOMMAND@ libhdimage.a @MAKELIB@ $(NONPLUGIN_OBJS) @RANLIB@ libhdimage.a # standard compile rule for C++ files .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@ ##### building plugins with libtool %.lo: %.@CPP_SUFFIX@ $(LIBTOOL) --mode=compile --tag CXX $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@ libbx_%.la: %.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) # special link rules for plugins that require more than one object file libbx_hdimage.la: hdimage.lo vmware3.lo vmware4.lo vvfat.lo vpc-img.lo $(CDROM_OBJS:.o=.lo) $(LIBTOOL) --mode=link --tag CXX $(CXX) -module hdimage.lo vmware3.lo vmware4.lo vvfat.lo vpc-img.lo $(CDROM_OBJS:.o=.lo) -o libbx_hdimage.la -rpath $(PLUGIN_PATH) #### building DLLs for win32 (tested on cygwin only) bx_%.dll: %.o $(CXX) $(CXXFLAGS) -shared -o $@ $< $(WIN32_DLL_IMPORT_LIBRARY) # special link rules for plugins that require more than one object file bx_hdimage.dll: hdimage.o vmware3.o vmware4.o vvfat.o vpc-img.o $(CDROM_OBJS) $(CXX) $(CXXFLAGS) -shared -o bx_hdimage.dll hdimage.o vmware3.o vmware4.o vvfat.o vpc-img.o $(CDROM_OBJS) $(WIN32_DLL_IMPORT_LIBRARY) ##### end DLL section clean: @RMCOMMAND@ -rf .libs *.lo *.o *.la *.a *.dll dist-clean: clean @RMCOMMAND@ Makefile ########################################### # dependencies generated by # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | sed -e 's/\.cc/.@CPP_SUFFIX@/g' # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | \ # sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g' # # This means that every source file is listed twice, once with a .o rule # and then again with an identical .lo rule. The .lo rules are used when # building plugins. ########################################### cdrom_amigaos.o: cdrom_amigaos.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h scsi_commands.h cdrom.h cdrom.o: cdrom.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h cdrom_misc.o: cdrom_misc.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h cdrom_osx.o: cdrom_osx.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h cdrom_win32.o: cdrom_win32.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h hdimage.o: hdimage.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h cdrom.h hdimage.h vmware3.h vmware4.h \ vvfat.h vpc-img.h vmware3.o: vmware3.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vmware3.h vmware4.o: vmware4.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vmware4.h vpc-img.o: vpc-img.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vpc-img.h vvfat.o: vvfat.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vvfat.h cdrom_amigaos.lo: cdrom_amigaos.@CPP_SUFFIX@ ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h scsi_commands.h cdrom.h cdrom.lo: cdrom.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h cdrom_misc.lo: cdrom_misc.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h cdrom_osx.lo: cdrom_osx.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h cdrom_win32.lo: cdrom_win32.@CPP_SUFFIX@ ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h cdrom.h hdimage.lo: hdimage.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h cdrom.h hdimage.h vmware3.h vmware4.h \ vvfat.h vpc-img.h vmware3.lo: vmware3.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vmware3.h vmware4.lo: vmware4.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vmware4.h vpc-img.lo: vpc-img.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vpc-img.h vvfat.lo: vvfat.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../ltdl.h ../../param_names.h hdimage.h vvfat.h bochs-2.6/iodev/hdimage/cdrom_osx.cc0000644000175000017500000004161312020641504017344 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cdrom_osx.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // These are the low-level CDROM functions which are called // from 'harddrv.cc'. They effect the OS specific functionality // needed by the CDROM emulation in 'harddrv.cc'. Mostly, just // ioctl() calls and such. Should be fairly easy to add support // for your OS if it is not supported yet. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "bochs.h" #if BX_SUPPORT_CDROM #include "cdrom.h" #define LOG_THIS /* no SMF tricks here, not needed */ extern "C" { #include } #if defined(__APPLE__) #include #include #include #include #if defined (__GNUC__) && (__GNUC__ >= 4) #include #else #include #endif #include #include #include #include #include #include #include #include #include // These definitions were taken from mount_cd9660.c // There are some similar definitions in IOCDTypes.h // however there seems to be some dissagreement in // the definition of CDTOC.length struct _CDMSF { u_char minute; u_char second; u_char frame; }; #define MSF_TO_LBA(msf) \ (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150) struct _CDTOC_Desc { u_char session; u_char ctrl_adr; /* typed to be machine and compiler independent */ u_char tno; u_char point; struct _CDMSF address; u_char zero; struct _CDMSF p; }; struct _CDTOC { u_short length; /* in native cpu endian */ u_char first_session; u_char last_session; struct _CDTOC_Desc trackdesc[1]; }; static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator, mach_port_t *masterPort); static kern_return_t GetDeviceFilePath(io_iterator_t mediaIterator, char *deviceFilePath, CFIndex maxPathSize); //int OpenDrive(const char *deviceFilePath); static struct _CDTOC *ReadTOC(const char *devpath); static char CDDevicePath[MAXPATHLEN]; #define BX_CD_FRAMESIZE 2048 #define CD_FRAMESIZE 2048 #include static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator, mach_port_t *masterPort) { kern_return_t kernResult; CFMutableDictionaryRef classesToMatch; kernResult = IOMasterPort(bootstrap_port, masterPort); if (kernResult != KERN_SUCCESS) { fprintf (stderr, "IOMasterPort returned %d\n", kernResult); return kernResult; } // CD media are instances of class kIOCDMediaClass. classesToMatch = IOServiceMatching(kIOCDMediaClass); if (classesToMatch == NULL) fprintf (stderr, "IOServiceMatching returned a NULL dictionary.\n"); else { // Each IOMedia object has a property with key kIOMediaEjectableKey // which is true if the media is indeed ejectable. So add property // to CFDictionary for matching. CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue); } kernResult = IOServiceGetMatchingServices(*masterPort, classesToMatch, mediaIterator); if ((kernResult != KERN_SUCCESS) || (*mediaIterator == NULL)) fprintf(stderr, "No ejectable CD media found.\n kernResult = %d\n", kernResult); return kernResult; } static kern_return_t GetDeviceFilePath(io_iterator_t mediaIterator, char *deviceFilePath, CFIndex maxPathSize) { io_object_t nextMedia; kern_return_t kernResult = KERN_FAILURE; nextMedia = IOIteratorNext(mediaIterator); if (nextMedia == NULL) { *deviceFilePath = '\0'; } else { CFTypeRef deviceFilePathAsCFString; deviceFilePathAsCFString = IORegistryEntryCreateCFProperty(nextMedia, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0); *deviceFilePath = '\0'; if (deviceFilePathAsCFString) { size_t devPathLength = strlen(_PATH_DEV); strcpy(deviceFilePath, _PATH_DEV); if (CFStringGetCString((const __CFString *) deviceFilePathAsCFString, deviceFilePath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII)) { // fprintf(stderr, "BSD path: %s\n", deviceFilePath); kernResult = KERN_SUCCESS; } CFRelease(deviceFilePathAsCFString); } } IOObjectRelease(nextMedia); return kernResult; } static int OpenDrive(const char *deviceFilePath) { int fileDescriptor = open(deviceFilePath, O_RDONLY); if (fileDescriptor == -1) fprintf(stderr, "Error %d opening device %s.\n", errno, deviceFilePath); return fileDescriptor; } static struct _CDTOC * ReadTOC(const char *devpath) { struct _CDTOC * toc_p = NULL; io_iterator_t iterator = 0; io_registry_entry_t service = 0; CFDictionaryRef properties = 0; CFDataRef data = 0; mach_port_t port = 0; char *devname; if ((devname = strrchr(devpath, '/')) != NULL) { ++devname; } else { devname = (char *) devpath; } if (IOMasterPort(bootstrap_port, &port) != KERN_SUCCESS) { fprintf(stderr, "IOMasterPort failed\n"); goto Exit; } if (IOServiceGetMatchingServices(port, IOBSDNameMatching(port, 0, devname), &iterator) != KERN_SUCCESS) { fprintf(stderr, "IOServiceGetMatchingServices failed\n"); goto Exit; } service = IOIteratorNext(iterator); IOObjectRelease(iterator); iterator = 0; while (service && !IOObjectConformsTo(service, "IOCDMedia")) { if (IORegistryEntryGetParentIterator(service, kIOServicePlane, &iterator) != KERN_SUCCESS) { fprintf(stderr, "IORegistryEntryGetParentIterator failed\n"); goto Exit; } IOObjectRelease(service); service = IOIteratorNext(iterator); IOObjectRelease(iterator); } if (service == NULL) { fprintf(stderr, "CD media not found\n"); goto Exit; } if (IORegistryEntryCreateCFProperties(service, (__CFDictionary **) &properties, kCFAllocatorDefault, kNilOptions) != KERN_SUCCESS) { fprintf(stderr, "IORegistryEntryGetParentIterator failed\n"); goto Exit; } data = (CFDataRef) CFDictionaryGetValue(properties, CFSTR(kIOCDMediaTOCKey)); if (data == NULL) { fprintf(stderr, "CFDictionaryGetValue failed\n"); goto Exit; } else { CFRange range; CFIndex buflen; buflen = CFDataGetLength(data) + 1; range = CFRangeMake(0, buflen); toc_p = (struct _CDTOC *) malloc(buflen); if (toc_p == NULL) { fprintf(stderr, "Out of memory\n"); goto Exit; } else { CFDataGetBytes(data, range, (unsigned char *) toc_p); } /* fprintf(stderr, "Table of contents\n length %d first %d last %d\n", toc_p->length, toc_p->first_session, toc_p->last_session); */ CFRelease(properties); } Exit: if (service) { IOObjectRelease(service); } return toc_p; } static unsigned int cdrom_count = 0; cdrom_interface::cdrom_interface(const char *dev) { char prefix[6]; sprintf(prefix, "CD%d", ++cdrom_count); put(prefix); fd = -1; // File descriptor not yet allocated if (dev == NULL) { path = NULL; } else { path = strdup(dev); } using_file=0; } cdrom_interface::~cdrom_interface(void) { if (fd >= 0) close(fd); if (path) free(path); BX_DEBUG(("Exit")); } bx_bool cdrom_interface::insert_cdrom(const char *dev) { unsigned char buffer[BX_CD_FRAMESIZE]; ssize_t ret; // Load CD-ROM. Returns 0 if CD is not ready. if (dev != NULL) path = strdup(dev); BX_INFO (("load cdrom with path=%s", path)); if(strcmp(path, "drive") == 0) { mach_port_t masterPort = NULL; io_iterator_t mediaIterator; kern_return_t kernResult; BX_INFO(("Insert CDROM")); kernResult = FindEjectableCDMedia(&mediaIterator, &masterPort); if (kernResult != KERN_SUCCESS) { BX_INFO(("Unable to find CDROM")); return 0; } kernResult = GetDeviceFilePath(mediaIterator, CDDevicePath, sizeof(CDDevicePath)); if (kernResult != KERN_SUCCESS) { BX_INFO(("Unable to get CDROM device file path")); return 0; } // Here a cdrom was found so see if we can read from it. // At this point a failure will result in panic. if (strlen(CDDevicePath)) { fd = open(CDDevicePath, O_RDONLY); } } else { fd = open(path, O_RDONLY); } if (fd < 0) { BX_ERROR(("open cd failed for %s: %s", path, strerror(errno))); return 0; } // do fstat to determine if it's a file or a device, then set using_file. struct stat stat_buf; ret = fstat (fd, &stat_buf); if (ret) { BX_PANIC (("fstat cdrom file returned error: %s", strerror (errno))); } if (S_ISREG (stat_buf.st_mode)) { using_file = 1; BX_INFO (("Opening image file as a cd.")); } else { using_file = 0; BX_INFO (("Using direct access for cdrom.")); } // I just see if I can read a sector to verify that a // CD is in the drive and readable. return read_block(buffer, 0, 2048); } bx_bool cdrom_interface::start_cdrom() { // Spin up the cdrom drive. if (fd >= 0) { BX_INFO(("start_cdrom: your OS is not supported yet")); return 0; // OS not supported yet, return 0 always } return 0; } void cdrom_interface::eject_cdrom() { // Logically eject the CD. I suppose we could stick in // some ioctl() calls to really eject the CD as well. if (fd >= 0) { close(fd); fd = -1; } } bx_bool cdrom_interface::read_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format) { // Read CD TOC. Returns 0 if start track is out of bounds. if (fd < 0) { BX_PANIC(("cdrom: read_toc: file not open.")); return 0; } // This is a hack and works okay if there's one rom track only if (using_file || (format != 0)) { return create_toc(buf, length, msf, start_track, format); } // all these implementations below are the platform-dependent code required // to read the TOC from a physical cdrom. { struct _CDTOC *toc = ReadTOC(CDDevicePath); if ((start_track > toc->last_session) && (start_track != 0xaa)) return 0; buf[2] = toc->first_session; buf[3] = toc->last_session; if (start_track < toc->first_session) start_track = toc->first_session; int len = 4; for (int i = start_track; i <= toc->last_session; i++) { buf[len++] = 0; // Reserved buf[len++] = toc->trackdesc[i].ctrl_adr ; // ADR, control buf[len++] = i; // Track number buf[len++] = 0; // Reserved // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = toc->trackdesc[i].address.minute; buf[len++] = toc->trackdesc[i].address.second; buf[len++] = toc->trackdesc[i].address.frame; } else { unsigned lba = (unsigned)(MSF_TO_LBA(toc->trackdesc[i].address)); buf[len++] = (lba >> 24) & 0xff; buf[len++] = (lba >> 16) & 0xff; buf[len++] = (lba >> 8) & 0xff; buf[len++] = (lba >> 0) & 0xff; } } // Lead out track buf[len++] = 0; // Reserved buf[len++] = 0x16; // ADR, control buf[len++] = 0xaa; // Track number buf[len++] = 0; // Reserved Bit32u blocks = capacity(); // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = (Bit8u)(((blocks + 150) / 75) / 60); // minute buf[len++] = (Bit8u)(((blocks + 150) / 75) % 60); // second buf[len++] = (Bit8u)((blocks + 150) % 75); // frame; } else { buf[len++] = (blocks >> 24) & 0xff; buf[len++] = (blocks >> 16) & 0xff; buf[len++] = (blocks >> 8) & 0xff; buf[len++] = (blocks >> 0) & 0xff; } buf[0] = ((len-2) >> 8) & 0xff; buf[1] = (len-2) & 0xff; *length = len; return 1; } } Bit32u cdrom_interface::capacity() { // Return CD-ROM capacity. I believe you want to return // the number of blocks of capacity the actual media has. if (using_file) { // return length of the image file struct stat stat_buf; int ret = fstat (fd, &stat_buf); if (ret) { BX_PANIC (("fstat on cdrom image returned err: %s", strerror(errno))); } if ((stat_buf.st_size % 2048) != 0) { BX_ERROR (("expected cdrom image to be a multiple of 2048 bytes")); } return (stat_buf.st_size / 2048); } // Find the size of the first data track on the cd. This has produced // the same results as the linux version on every cd I have tried, about // 5. The differences here seem to be that the entries in the TOC when // retrieved from the IOKit interface appear in a reversed order when // compared with the linux READTOCENTRY ioctl. { // Return CD-ROM capacity. I believe you want to return // the number of bytes of capacity the actual media has. BX_INFO(("Capacity")); struct _CDTOC *toc = ReadTOC(CDDevicePath); if (toc == NULL) { BX_PANIC(("capacity: Failed to read toc")); } size_t toc_entries = (toc->length - 2) / sizeof(struct _CDTOC_Desc); BX_DEBUG(("reading %d toc entries\n", toc_entries)); int start_sector = -1; int data_track = -1; // Iterate through the list backward. Pick the first data track and // get the address of the immediately previous (or following depending // on how you look at it). The difference in the sector numbers // is returned as the sized of the data track. for (int i=toc_entries - 1; i>=0; i--) { BX_DEBUG(("session %d ctl_adr %d tno %d point %d lba %d z %d p lba %d\n", (int)toc->trackdesc[i].session, (int)toc->trackdesc[i].ctrl_adr, (int)toc->trackdesc[i].tno, (int)toc->trackdesc[i].point, MSF_TO_LBA(toc->trackdesc[i].address), (int)toc->trackdesc[i].zero, MSF_TO_LBA(toc->trackdesc[i].p))); if (start_sector != -1) { start_sector = MSF_TO_LBA(toc->trackdesc[i].p) - start_sector; break; } if ((toc->trackdesc[i].ctrl_adr >> 4) != 1) continue; if (toc->trackdesc[i].ctrl_adr & 0x04) { data_track = toc->trackdesc[i].point; start_sector = MSF_TO_LBA(toc->trackdesc[i].p); } } free(toc); if (start_sector == -1) { start_sector = 0; } BX_INFO(("first data track %d data size is %d", data_track, start_sector)); return start_sector; } } bx_bool BX_CPP_AttrRegparmN(3) cdrom_interface::read_block(Bit8u* buf, Bit32u lba, int blocksize) { // Read a single block from the CD off_t pos; ssize_t n = 0; Bit8u try_count = 3; Bit8u* buf1; if (blocksize == 2352) { memset(buf, 0, 2352); memset(buf+1, 0xff, 10); Bit32u raw_block = lba + 150; buf[12] = (raw_block / 75) / 60; buf[13] = (raw_block / 75) % 60; buf[14] = (raw_block % 75); buf[15] = 0x01; buf1 = buf + 16; } else { buf1 = buf; } do { #define CD_SEEK_DISTANCE kCDSectorSizeWhole if(using_file) { pos = lseek(fd, (off_t) lba * BX_CD_FRAMESIZE, SEEK_SET); if (pos < 0) { BX_PANIC(("cdrom: read_block: lseek returned error.")); } else { n = read(fd, buf1, BX_CD_FRAMESIZE); } } else { // This seek will leave us 16 bytes from the start of the data // hence the magic number. pos = lseek(fd, (off_t) lba * CD_SEEK_DISTANCE + 16, SEEK_SET); if (pos < 0) { BX_PANIC(("cdrom: read_block: lseek returned error.")); } else { n = read(fd, buf1, CD_FRAMESIZE); } } } while ((n != BX_CD_FRAMESIZE) && (--try_count > 0)); return (n == BX_CD_FRAMESIZE); } #endif /* if defined(__APPLE__) */ #endif /* if BX_SUPPORT_CDROM */ bochs-2.6/iodev/hdimage/scsidefs.h0000644000175000017500000003524312020641504017016 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: scsidefs.h 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // iodev/scsidefs.h // // This file was copied from ... ? // //*************************************************************************** // Name: SCSIDEFS.H // // Description: SCSI definitions ('C' Language) //*************************************************************************** //*************************************************************************** // %%% TARGET STATUS VALUES %%% //*************************************************************************** #define STATUS_GOOD 0x00 // Status Good #define STATUS_CHKCOND 0x02 // Check Condition #define STATUS_CONDMET 0x04 // Condition Met #define STATUS_BUSY 0x08 // Busy #define STATUS_INTERM 0x10 // Intermediate #define STATUS_INTCDMET 0x14 // Intermediate-condition met #define STATUS_RESCONF 0x18 // Reservation conflict #define STATUS_COMTERM 0x22 // Command Terminated #define STATUS_QFULL 0x28 // Queue full //*************************************************************************** // %%% SCSI MISCELLANEOUS EQUATES %%% //*************************************************************************** #define MAXLUN 7 // Maximum Logical Unit Id #define MAXTARG 7 // Maximum Target Id #define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs #define MAX_NUM_HA 8 // Maximum Number of SCSI HA's //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ // // %%% SCSI COMMAND OPCODES %%% // ///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ //*************************************************************************** // %%% Commands for all Device Types %%% //*************************************************************************** #define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional) #define SCSI_COMPARE 0x39 // Compare (O) #define SCSI_COPY 0x18 // Copy (O) #define SCSI_COP_VERIFY 0x3A // Copy and Verify (O) #define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY) #define SCSI_LOG_SELECT 0x4C // Log Select (O) #define SCSI_LOG_SENSE 0x4D // Log Sense (O) #define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific) #define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific) #define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific) #define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific) #define SCSI_READ_BUFF 0x3C // Read Buffer (O) #define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY) #define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O) #define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY) #define SCSI_WRITE_BUFF 0x3B // Write Buffer (O) //*************************************************************************** // %%% Commands Unique to Direct Access Devices %%% //*************************************************************************** #define SCSI_COMPARE 0x39 // Compare (O) #define SCSI_FORMAT 0x04 // Format Unit (MANDATORY) #define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O) #define SCSI_PREFETCH 0x34 // Prefetch (O) #define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O) #define SCSI_READ6 0x08 // Read 6-byte (MANDATORY) #define SCSI_READ10 0x28 // Read 10-byte (MANDATORY) #define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY) #define SCSI_RD_DEFECT 0x37 // Read Defect Data (O) #define SCSI_READ_LONG 0x3E // Read Long (O) #define SCSI_REASS_BLK 0x07 // Reassign Blocks (O) #define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O) #define SCSI_RELEASE 0x17 // Release Unit (MANDATORY) #define SCSI_REZERO 0x01 // Rezero Unit (O) #define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O) #define SCSI_SRCH_DAT_H 0x30 // Search Data High (O) #define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O) #define SCSI_SEEK6 0x0B // Seek 6-Byte (O) #define SCSI_SEEK10 0x2B // Seek 10-Byte (O) #define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY) #define SCSI_SET_LIMIT 0x33 // Set Limits (O) #define SCSI_START_STP 0x1B // Start/Stop Unit (O) #define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O) #define SCSI_VERIFY 0x2F // Verify (O) #define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY) #define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY) #define SCSI_WRT_VERIFY 0x2E // Write and Verify (O) #define SCSI_WRITE_LONG 0x3F // Write Long (O) #define SCSI_WRITE_SAME 0x41 // Write Same (O) //*************************************************************************** // %%% Commands Unique to Sequential Access Devices %%% //*************************************************************************** #define SCSI_ERASE 0x19 // Erase (MANDATORY) #define SCSI_LOAD_UN 0x1B // Load/Unload (O) #define SCSI_LOCATE 0x2B // Locate (O) #define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY) #define SCSI_READ_POS 0x34 // Read Position (O) #define SCSI_READ_REV 0x0F // Read Reverse (O) #define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O) #define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY) #define SCSI_REWIND 0x01 // Rewind (MANDATORY) #define SCSI_SPACE 0x11 // Space (MANDATORY) #define SCSI_VERIFY_T 0x13 // Verify (Tape) (O) #define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY) //*************************************************************************** // %%% Commands Unique to Printer Devices %%% //*************************************************************************** #define SCSI_PRINT 0x0A // Print (MANDATORY) #define SCSI_SLEW_PNT 0x0B // Slew and Print (O) #define SCSI_STOP_PNT 0x1B // Stop Print (O) #define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O) //*************************************************************************** // %%% Commands Unique to Processor Devices %%% //*************************************************************************** #define SCSI_RECEIVE 0x08 // Receive (O) #define SCSI_SEND 0x0A // Send (O) //*************************************************************************** // %%% Commands Unique to Write-Once Devices %%% //*************************************************************************** #define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O) #define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O) #define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O) #define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O) #define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O) #define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O) #define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O) #define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O) #define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O) #define SCSI_VERIFY10 0x2F // Verify 10-Byte (O) #define SCSI_VERIFY12 0xAF // Verify 12-Byte (O) #define SCSI_WRITE12 0xAA // Write 12-Byte (O) #define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O) #define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O) //*************************************************************************** // %%% Commands Unique to CD-ROM Devices %%% //*************************************************************************** #define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O) #define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O) #define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O) #define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O) #define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O) #define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O) #define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY) #define SCSI_READHEADER 0x44 // Read Header (O) #define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O) #define SCSI_READ_TOC 0x43 // Read TOC (O) //*************************************************************************** // %%% Commands Unique to Scanner Devices %%% //*************************************************************************** #define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O) #define SCSI_GETWINDOW 0x25 // Get Window (O) #define SCSI_OBJECTPOS 0x31 // Object Postion (O) #define SCSI_SCAN 0x1B // Scan (O) #define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY) //*************************************************************************** // %%% Commands Unique to Optical Memory Devices %%% //*************************************************************************** #define SCSI_UpdateBlk 0x3D // Update Block (O) //*************************************************************************** // %%% Commands Unique to Medium Changer Devices %%% //*************************************************************************** #define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O) #define SCSI_INITELSTAT 0x07 // Initialize Element Status (O) #define SCSI_POSTOELEM 0x2B // Position to Element (O) #define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O) #define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O) //*************************************************************************** // %%% Commands Unique to Communication Devices %%% //*************************************************************************** #define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY) #define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O) #define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O) #define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY) #define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O) #define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O) //\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ // // %%% END OF SCSI COMMAND OPCODES %%% // ///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/ //*************************************************************************** // %%% Request Sense Data Format %%% //*************************************************************************** typedef struct { BYTE ErrorCode; // Error Code (70H or 71H) BYTE SegmentNum; // Number of current segment descriptor BYTE SenseKey; // Sense Key(See bit definitions too) BYTE InfoByte0; // Information MSB BYTE InfoByte1; // Information MID BYTE InfoByte2; // Information MID BYTE InfoByte3; // Information LSB BYTE AddSenLen; // Additional Sense Length BYTE ComSpecInf0; // Command Specific Information MSB BYTE ComSpecInf1; // Command Specific Information MID BYTE ComSpecInf2; // Command Specific Information MID BYTE ComSpecInf3; // Command Specific Information LSB BYTE AddSenseCode; // Additional Sense Code BYTE AddSenQual; // Additional Sense Code Qualifier BYTE FieldRepUCode; // Field Replaceable Unit Code BYTE SenKeySpec15; // Sense Key Specific 15th byte BYTE SenKeySpec16; // Sense Key Specific 16th byte BYTE SenKeySpec17; // Sense Key Specific 17th byte BYTE AddSenseBytes; // Additional Sense Bytes } SENSE_DATA_FMT; //*************************************************************************** // %%% REQUEST SENSE ERROR CODE %%% //*************************************************************************** #define SERROR_CURRENT 0x70 // Current Errors #define SERROR_DEFERED 0x71 // Deferred Errors //*************************************************************************** // %%% REQUEST SENSE BIT DEFINITIONS %%% //*************************************************************************** #define SENSE_VALID 0x80 // Byte 0 Bit 7 #define SENSE_FILEMRK 0x80 // Byte 2 Bit 7 #define SENSE_EOM 0x40 // Byte 2 Bit 6 #define SENSE_ILI 0x20 // Byte 2 Bit 5 //*************************************************************************** // %%% REQUEST SENSE SENSE KEY DEFINITIONS %%% //*************************************************************************** #define KEY_NOSENSE 0x00 // No Sense #define KEY_RECERROR 0x01 // Recovered Error #define KEY_NOTREADY 0x02 // Not Ready #define KEY_MEDIUMERR 0x03 // Medium Error #define KEY_HARDERROR 0x04 // Hardware Error #define KEY_ILLGLREQ 0x05 // Illegal Request #define KEY_UNITATT 0x06 // Unit Attention #define KEY_DATAPROT 0x07 // Data Protect #define KEY_BLANKCHK 0x08 // Blank Check #define KEY_VENDSPEC 0x09 // Vendor Specific #define KEY_COPYABORT 0x0A // Copy Abort #define KEY_EQUAL 0x0C // Equal (Search) #define KEY_VOLOVRFLW 0x0D // Volume Overflow #define KEY_MISCOMP 0x0E // Miscompare (Search) #define KEY_RESERVED 0x0F // Reserved //*************************************************************************** // %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%% //*************************************************************************** #define DTYPE_DASD 0x00 // Disk Device #define DTYPE_SEQD 0x01 // Tape Device #define DTYPE_PRNT 0x02 // Printer #define DTYPE_PROC 0x03 // Processor #define DTYPE_WORM 0x04 // Write-once read-multiple #define DTYPE_CROM 0x05 // CD-ROM device #define DTYPE_CDROM 0x05 // CD-ROM device #define DTYPE_SCAN 0x06 // Scanner device #define DTYPE_OPTI 0x07 // Optical memory device #define DTYPE_JUKE 0x08 // Medium Changer device #define DTYPE_COMM 0x09 // Communications device #define DTYPE_RESL 0x0A // Reserved (low) #define DTYPE_RESH 0x1E // Reserved (high) #define DTYPE_UNKNOWN 0x1F // Unknown or no device type //*************************************************************************** // %%% ANSI APPROVED VERSION DEFINITIONS %%% //*************************************************************************** #define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand #define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1) #define ANSI_SCSI2 0x2 // Device complies to SCSI-2 #define ANSI_RESLO 0x3 // Reserved (low) #define ANSI_RESHI 0x7 // Reserved (high) bochs-2.6/iodev/hdimage/vmware4.h0000644000175000017500000000552612020641504016601 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmware4.h 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// /* * This file provides support for VMWare's virtual disk image * format version 4 and above. * * Author: Sharvil Nanavati * Contact: snrrrub@gmail.com * * Copyright (C) 2006 Sharvil Nanavati. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _VMWARE4_H #define _VMWARE4_H 1 class vmware4_image_t : public device_image_t { public: vmware4_image_t(); virtual ~vmware4_image_t(); int open(const char* pathname); void close(); Bit64s lseek(Bit64s offset, int whence); ssize_t read(void* buf, size_t count); ssize_t write(const void* buf, size_t count); Bit32u get_capabilities(); private: static const off_t INVALID_OFFSET; static const int SECTOR_SIZE; #if defined(_MSC_VER) #pragma pack(push, 1) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=packed #endif typedef struct _VM4_Header { Bit8u id[4]; Bit32u version; Bit32u flags; Bit64u total_sectors; Bit64u tlb_size_sectors; Bit64u description_offset_sectors; Bit64u description_size_sectors; Bit32u slb_count; Bit64u flb_offset_sectors; Bit64u flb_copy_offset_sectors; Bit64u tlb_offset_sectors; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif VM4_Header; #if defined(_MSC_VER) #pragma pack(pop) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=reset #endif bool is_open() const; bool is_valid_header() const; bool read_header(); off_t perform_seek(); void flush(); Bit32u read_block_index(Bit64u sector, Bit32u index); void write_block_index(Bit64u sector, Bit32u index, Bit32u block_sector); int file_descriptor; VM4_Header header; Bit8u* tlb; off_t tlb_offset; off_t current_offset; bool is_dirty; }; #endif bochs-2.6/iodev/hdimage/vmware4.cc0000644000175000017500000002450112020641504016731 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmware4.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// /* * This file provides support for VMWare's virtual disk image * format version 4 and above. * * Author: Sharvil Nanavati * Contact: snrrrub@gmail.com * * Copyright (C) 2006 Sharvil Nanavati. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "hdimage.h" #include "vmware4.h" #define LOG_THIS bx_devices.pluginHDImageCtl-> const off_t vmware4_image_t::INVALID_OFFSET = (off_t)-1; const int vmware4_image_t::SECTOR_SIZE = 512; vmware4_image_t::vmware4_image_t() : file_descriptor(-1), tlb(0), tlb_offset(INVALID_OFFSET), current_offset(INVALID_OFFSET), is_dirty(false) { } vmware4_image_t::~vmware4_image_t() { close(); } int vmware4_image_t::open(const char * pathname) { close(); int flags = O_RDWR; #ifdef O_BINARY flags |= O_BINARY; #endif file_descriptor = ::open(pathname, flags); if(!is_open()) return -1; if(!read_header()) BX_PANIC(("unable to read vmware4 virtual disk header from file '%s'", pathname)); tlb = new Bit8u[(unsigned)header.tlb_size_sectors * SECTOR_SIZE]; if(tlb == 0) BX_PANIC(("unable to allocate " FMT_LL "d bytes for vmware4 image's tlb", header.tlb_size_sectors * SECTOR_SIZE)); tlb_offset = INVALID_OFFSET; current_offset = 0; is_dirty = false; hd_size = header.total_sectors * SECTOR_SIZE; cylinders = (unsigned)hd_size / (16 * 63); heads = 16; spt = 63; BX_DEBUG(("VMware 4 disk geometry:")); BX_DEBUG((" .size = " FMT_LL "d", hd_size)); BX_DEBUG((" .cylinders = %d", cylinders)); BX_DEBUG((" .heads = %d", heads)); BX_DEBUG((" .sectors = %d", spt)); return 1; } void vmware4_image_t::close() { if(file_descriptor == -1) return; flush(); delete [] tlb; tlb = 0; ::close(file_descriptor); file_descriptor = -1; } Bit64s vmware4_image_t::lseek(Bit64s offset, int whence) { switch(whence) { case SEEK_SET: current_offset = (off_t)offset; return current_offset; case SEEK_CUR: current_offset += (off_t)offset; return current_offset; case SEEK_END: current_offset = header.total_sectors * SECTOR_SIZE + (off_t)offset; return current_offset; default: BX_DEBUG(("unknown 'whence' value (%d) when trying to seek vmware4 image", whence)); return INVALID_OFFSET; } } ssize_t vmware4_image_t::read(void * buf, size_t count) { ssize_t total = 0; while(count > 0) { off_t readable = perform_seek(); if(readable == INVALID_OFFSET) { BX_DEBUG(("vmware4 disk image read failed on %u bytes at " FMT_LL "d", (unsigned)count, current_offset)); return -1; } off_t copysize = ((off_t)count > readable) ? readable : count; memcpy(buf, tlb + current_offset - tlb_offset, (size_t)copysize); current_offset += copysize; total += (long)copysize; count -= (size_t)copysize; } return total; } ssize_t vmware4_image_t::write(const void * buf, size_t count) { ssize_t total = 0; while(count > 0) { off_t writable = perform_seek(); if(writable == INVALID_OFFSET) { BX_DEBUG(("vmware4 disk image write failed on %u bytes at " FMT_LL "d", (unsigned)count, current_offset)); return -1; } off_t writesize = ((off_t)count > writable) ? writable : count; memcpy(tlb + current_offset - tlb_offset, buf, (size_t)writesize); current_offset += writesize; total += (long)writesize; count -= (size_t)writesize; is_dirty = true; } return total; } bool vmware4_image_t::is_open() const { return (file_descriptor != -1); } bool vmware4_image_t::is_valid_header() const { if(header.id[0] != 'K' || header.id[1] != 'D' || header.id[2] != 'M' || header.id[3] != 'V') { BX_DEBUG(("not a vmware4 image")); return false; } if(header.version != 1) { BX_DEBUG(("unsupported vmware4 image version")); return false; } return true; } bool vmware4_image_t::read_header() { if(!is_open()) BX_PANIC(("attempt to read vmware4 header from a closed file")); if(::read(file_descriptor, &header, sizeof(VM4_Header)) != sizeof(VM4_Header)) return false; header.version = dtoh32(header.version); header.flags = dtoh32(header.flags); header.total_sectors = dtoh64(header.total_sectors); header.tlb_size_sectors = dtoh64(header.tlb_size_sectors); header.description_offset_sectors = dtoh64(header.description_offset_sectors); header.description_size_sectors = dtoh64(header.description_size_sectors); header.slb_count = dtoh32(header.slb_count); header.flb_offset_sectors = dtoh64(header.flb_offset_sectors); header.flb_copy_offset_sectors = dtoh64(header.flb_copy_offset_sectors); header.tlb_offset_sectors = dtoh64(header.tlb_offset_sectors); if(!is_valid_header()) BX_PANIC(("invalid vmware4 virtual disk image")); BX_DEBUG(("VM4_Header (size=%u)", (unsigned)sizeof(VM4_Header))); BX_DEBUG((" .version = %d", header.version)); BX_DEBUG((" .flags = %d", header.flags)); BX_DEBUG((" .total_sectors = " FMT_LL "d", header.total_sectors)); BX_DEBUG((" .tlb_size_sectors = " FMT_LL "d", header.tlb_size_sectors)); BX_DEBUG((" .description_offset_sectors = " FMT_LL "d", header.description_offset_sectors)); BX_DEBUG((" .description_size_sectors = " FMT_LL "d", header.description_size_sectors)); BX_DEBUG((" .slb_count = %d", header.slb_count)); BX_DEBUG((" .flb_offset_sectors = " FMT_LL "d", header.flb_offset_sectors)); BX_DEBUG((" .flb_copy_offset_sectors = " FMT_LL "d", header.flb_copy_offset_sectors)); BX_DEBUG((" .tlb_offset_sectors = " FMT_LL "d", header.tlb_offset_sectors)); return true; } // // Returns the number of bytes that can be read from the current offset before needing // to perform another seek. // off_t vmware4_image_t::perform_seek() { if(current_offset == INVALID_OFFSET) { BX_DEBUG(("invalid offset specified in vmware4 seek")); return INVALID_OFFSET; } // // The currently loaded tlb can service the request. // if(tlb_offset / (header.tlb_size_sectors * SECTOR_SIZE) == current_offset / (header.tlb_size_sectors * SECTOR_SIZE)) return (header.tlb_size_sectors * SECTOR_SIZE) - (current_offset - tlb_offset); flush(); Bit64u index = current_offset / (header.tlb_size_sectors * SECTOR_SIZE); Bit32u slb_index = (Bit32u)(index % header.slb_count); Bit32u flb_index = (Bit32u)(index / header.slb_count); Bit32u slb_sector = read_block_index(header.flb_offset_sectors, flb_index); Bit32u slb_copy_sector = read_block_index(header.flb_copy_offset_sectors, flb_index); if(slb_sector == 0 && slb_copy_sector == 0) { BX_DEBUG(("loaded vmware4 disk image requires un-implemented feature")); return INVALID_OFFSET; } if(slb_sector == 0) slb_sector = slb_copy_sector; Bit32u tlb_sector = read_block_index(slb_sector, slb_index); tlb_offset = index * header.tlb_size_sectors * SECTOR_SIZE; if(tlb_sector == 0) { // // Allocate a new tlb // memset(tlb, 0, (size_t)header.tlb_size_sectors * SECTOR_SIZE); // // Instead of doing a write to increase the file size, we could use // ftruncate but it is not portable. // off_t eof = ((::lseek(file_descriptor, 0, SEEK_END) + SECTOR_SIZE - 1) / SECTOR_SIZE) * SECTOR_SIZE; ::write(file_descriptor, tlb, (unsigned)header.tlb_size_sectors * SECTOR_SIZE); tlb_sector = (Bit32u)eof / SECTOR_SIZE; write_block_index(slb_sector, slb_index, tlb_sector); write_block_index(slb_copy_sector, slb_index, tlb_sector); ::lseek(file_descriptor, eof, SEEK_SET); } else { ::lseek(file_descriptor, tlb_sector * SECTOR_SIZE, SEEK_SET); ::read(file_descriptor, tlb, (unsigned)header.tlb_size_sectors * SECTOR_SIZE); ::lseek(file_descriptor, tlb_sector * SECTOR_SIZE, SEEK_SET); } return (header.tlb_size_sectors * SECTOR_SIZE) - (current_offset - tlb_offset); } void vmware4_image_t::flush() { if(!is_dirty) return; // // Write dirty sectors to disk first. Assume that the file is already at the // position for the current tlb. // ::write(file_descriptor, tlb, (unsigned)header.tlb_size_sectors * SECTOR_SIZE); is_dirty = false; } Bit32u vmware4_image_t::read_block_index(Bit64u sector, Bit32u index) { Bit32u ret; bx_read_image(file_descriptor, sector * SECTOR_SIZE + index * sizeof(Bit32u), &ret, sizeof(Bit32u)); return dtoh32(ret); } void vmware4_image_t::write_block_index(Bit64u sector, Bit32u index, Bit32u block_sector) { block_sector = htod32(block_sector); bx_write_image(file_descriptor, sector * SECTOR_SIZE + index * sizeof(Bit32u), &block_sector, sizeof(Bit32u)); } Bit32u vmware4_image_t::get_capabilities(void) { return HDIMAGE_HAS_GEOMETRY; } bochs-2.6/iodev/hdimage/vpc-img.h0000644000175000017500000001101412020641504016543 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vpc-img.h 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Block driver for Connectix / Microsoft Virtual PC images (ported from QEMU) // // Copyright (c) 2005 Alex Beregszaszi // Copyright (c) 2009 Kevin Wolf // Copyright (C) 2012 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // ///////////////////////////////////////////////////////////////////////// #ifndef BX_VPCIMG_H #define BX_VPCIMG_H #define HEADER_SIZE 512 enum vhd_type { VHD_FIXED = 2, VHD_DYNAMIC = 3, VHD_DIFFERENCING = 4, }; #if defined(_MSC_VER) && (_MSC_VER<1300) #pragma pack(push, 1) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=packed #endif // always big-endian typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct vhd_footer_t { Bit8u creator[8]; // "conectix" Bit32u features; Bit32u version; // Offset of next header structure, 0xFFFFFFFF if none Bit64u data_offset; // Seconds since Jan 1, 2000 0:00:00 (UTC) Bit32u timestamp; Bit8u creator_app[4]; // "vpc " Bit16u major; Bit16u minor; Bit8u creator_os[4]; // "Wi2k" Bit64u orig_size; Bit64u size; Bit16u cyls; Bit8u heads; Bit8u secs_per_cyl; Bit32u type; // Checksum of the Hard Disk Footer ("one's complement of the sum of all // the bytes in the footer without the checksum field") Bit32u checksum; // UUID used to identify a parent hard disk (backing file) Bit8u uuid[16]; Bit8u in_saved_state; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif vhd_footer_t; typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct vhd_dyndisk_header_t { Bit8u magic[8]; // "cxsparse" // Offset of next header structure, 0xFFFFFFFF if none Bit64u data_offset; // Offset of the Block Allocation Table (BAT) Bit64u table_offset; Bit32u version; Bit32u max_table_entries; // 32bit/entry // 2 MB by default, must be a power of two Bit32u block_size; Bit32u checksum; Bit8u parent_uuid[16]; Bit32u parent_timestamp; Bit32u reserved; // Backing file name (in UTF-16) Bit8u parent_name[512]; struct { Bit32u platform; Bit32u data_space; Bit32u data_length; Bit32u reserved; Bit64u data_offset; } parent_locator[8]; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif vhd_dyndisk_header_t; #if defined(_MSC_VER) && (_MSC_VER<1300) #pragma pack(pop) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=reset #endif class vpc_image_t : public device_image_t { public: int open(const char* pathname); void close(); Bit64s lseek(Bit64s offset, int whence); ssize_t read(void* buf, size_t count); ssize_t write(const void* buf, size_t count); Bit32u get_capabilities(); private: Bit32u vpc_checksum(Bit8u *buf, size_t size); Bit64s get_sector_offset(Bit64s sector_num, int write); int rewrite_footer(void); Bit64s alloc_block(Bit64s sector_num); int fd; Bit64s sector_count; Bit64s cur_sector; Bit8u footer_buf[HEADER_SIZE]; Bit64u free_data_block_offset; int max_table_entries; Bit64u bat_offset; Bit64u last_bitmap_offset; Bit32u *pagetable; Bit32u block_size; Bit32u bitmap_size; }; #endif bochs-2.6/iodev/hdimage/hdimage.h0000644000175000017500000003402312020641504016604 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: hdimage.h 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2005-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_HDIMAGE_H #define BX_HDIMAGE_H // hdimage capabilities #define HDIMAGE_READONLY 1 #define HDIMAGE_HAS_GEOMETRY 2 #define HDIMAGE_AUTO_GEOMETRY 4 // SPARSE IMAGES HEADER #define SPARSE_HEADER_MAGIC (0x02468ace) #define SPARSE_HEADER_VERSION 2 #define SPARSE_HEADER_V1 1 #define SPARSE_HEADER_SIZE (256) // Plenty of room for later #define SPARSE_PAGE_NOT_ALLOCATED (0xffffffff) typedef struct { Bit32u magic; Bit32u version; Bit32u pagesize; Bit32u numpages; Bit64u disk; Bit32u padding[58]; } sparse_header_t; #define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image" #define STANDARD_HEADER_V1 (0x00010000) #define STANDARD_HEADER_VERSION (0x00020000) #define STANDARD_HEADER_SIZE (512) // WARNING : headers are kept in x86 (little) endianness typedef struct { Bit8u magic[32]; Bit8u type[16]; Bit8u subtype[16]; Bit32u version; Bit32u header; } standard_header_t; #define REDOLOG_TYPE "Redolog" #define REDOLOG_SUBTYPE_UNDOABLE "Undoable" #define REDOLOG_SUBTYPE_VOLATILE "Volatile" #define REDOLOG_SUBTYPE_GROWING "Growing" #define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff) #define UNDOABLE_REDOLOG_EXTENSION ".redolog" #define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION)) #define VOLATILE_REDOLOG_EXTENSION ".XXXXXX" #define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION)) typedef struct { // the fields in the header are kept in little endian Bit32u catalog; // #entries in the catalog Bit32u bitmap; // bitmap size in bytes Bit32u extent; // extent size in bytes Bit32u timestamp; // modification time in FAT format (subtype 'undoable' only) Bit64u disk; // disk size in bytes } redolog_specific_header_t; typedef struct { // the fields in the header are kept in little endian Bit32u catalog; // #entries in the catalog Bit32u bitmap; // bitmap size in bytes Bit32u extent; // extent size in bytes Bit64u disk; // disk size in bytes } redolog_specific_header_v1_t; typedef struct { standard_header_t standard; redolog_specific_header_t specific; Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_t))]; } redolog_header_t; typedef struct { standard_header_t standard; redolog_specific_header_v1_t specific; Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_v1_t))]; } redolog_header_v1_t; // htod : convert host to disk (little) endianness // dtoh : convert disk (little) to host endianness #if defined (BX_LITTLE_ENDIAN) #define htod32(val) (val) #define dtoh32(val) (val) #define htod64(val) (val) #define dtoh64(val) (val) #else #define htod32(val) bx_bswap32(val) #define dtoh32(val) htod32(val) #define htod64(val) bx_bswap64(val) #define dtoh64(val) htod64(val) #endif #ifndef HDIMAGE_HEADERS_ONLY int bx_read_image(int fd, Bit64s offset, void *buf, int count); int bx_write_image(int fd, Bit64s offset, void *buf, int count); class device_image_t { public: // Default constructor device_image_t(); virtual ~device_image_t() {} // Open a image. Returns non-negative if successful. virtual int open(const char* pathname) = 0; // Close the image. virtual void close() = 0; // Position ourselves. Return the resulting offset from the // beginning of the file. virtual Bit64s lseek(Bit64s offset, int whence) = 0; // Read count bytes to the buffer buf. Return the number of // bytes read (count). virtual ssize_t read(void* buf, size_t count) = 0; // Write count bytes from buf. Return the number of bytes // written (count). virtual ssize_t write(const void* buf, size_t count) = 0; // Get image capabilities virtual Bit32u get_capabilities(); unsigned cylinders; unsigned heads; unsigned spt; Bit64u hd_size; }; // FLAT MODE class default_image_t : public device_image_t { public: // Open a image. Returns non-negative if successful. int open(const char* pathname); // Open an image with specific flags. Returns non-negative if successful. int open(const char* pathname, int flags); // Close the image. void close(); // Position ourselves. Return the resulting offset from the // beginning of the file. Bit64s lseek(Bit64s offset, int whence); // Read count bytes to the buffer buf. Return the number of // bytes read (count). ssize_t read(void* buf, size_t count); // Write count bytes from buf. Return the number of bytes // written (count). ssize_t write(const void* buf, size_t count); // Get modification time in FAT format Bit32u get_timestamp(); private: int fd; #ifndef WIN32 time_t mtime; #else FILETIME mtime; #endif }; // CONCAT MODE class concat_image_t : public device_image_t { public: // Default constructor concat_image_t(); // Open a image. Returns non-negative if successful. int open(const char* pathname); // Close the image. void close(); // Position ourselves. Return the resulting offset from the // beginning of the file. Bit64s lseek(Bit64s offset, int whence); // Read count bytes to the buffer buf. Return the number of // bytes read (count). ssize_t read(void* buf, size_t count); // Write count bytes from buf. Return the number of bytes // written (count). ssize_t write(const void* buf, size_t count); private: #define BX_CONCAT_MAX_IMAGES 8 int fd_table[BX_CONCAT_MAX_IMAGES]; Bit64s start_offset_table[BX_CONCAT_MAX_IMAGES]; Bit64s length_table[BX_CONCAT_MAX_IMAGES]; void increment_string(char *str); int maxfd; // number of entries in tables that are valid // notice if anyone does sequential read or write without seek in between. // This can be supported pretty easily, but needs additional checks. // 0=something other than seek was last operation // 1=seek was last operation int seek_was_last_op; // the following variables tell which partial image file to use for // the next read and write. int index; // index into table int fd; // fd to use for reads and writes Bit64s thismin, thismax; // byte offset boundary of this image }; // SPARSE MODE class sparse_image_t : public device_image_t { // Format of a sparse file: // 256 byte header, containing details such as page size and number of pages // Page indirection table, mapping virtual pages to physical pages within file // Physical pages till end of file public: // Default constructor sparse_image_t(); // Open a image. Returns non-negative if successful. int open(const char* pathname); // Close the image. void close(); // Position ourselves. Return the resulting offset from the // beginning of the file. Bit64s lseek(Bit64s offset, int whence); // Read count bytes to the buffer buf. Return the number of // bytes read (count). ssize_t read(void* buf, size_t count); // Write count bytes from buf. Return the number of bytes // written (count). ssize_t write(const void* buf, size_t count); private: int fd; #ifdef _POSIX_MAPPED_FILES void * mmap_header; size_t mmap_length; size_t system_pagesize_mask; #endif Bit32u *pagetable; // Header is written to disk in little-endian (x86) format // Thus needs to be converted on big-endian systems before read // The pagetable is also kept little endian sparse_header_t header; Bit32u pagesize; int pagesize_shift; Bit32u pagesize_mask; Bit64s data_start; Bit64s underlying_filesize; char *pathname; Bit64s position; Bit32u position_virtual_page; Bit32u position_physical_page; Bit32u position_page_offset; Bit64s underlying_current_filepos; Bit64s total_size; void panic(const char * message); Bit64s get_physical_offset(); void set_virtual_page(Bit32u new_virtual_page); void read_header(); ssize_t read_page_fragment(Bit32u read_virtual_page, Bit32u read_page_offset, size_t read_size, void * buf); sparse_image_t *parent_image; }; #if EXTERNAL_DISK_SIMULATOR #include "external-disk-simulator.h" #endif #if DLL_HD_SUPPORT class dll_image_t : public device_image_t { public: // Open a image. Returns non-negative if successful. int open(const char* pathname); // Close the image. void close(); // Position ourselves. Return the resulting offset from the // beginning of the file. Bit64s lseek(Bit64s offset, int whence); // Read count bytes to the buffer buf. Return the number of // bytes read (count). ssize_t read(void* buf, size_t count); // Write count bytes from buf. Return the number of bytes // written (count). ssize_t write(const void* buf, size_t count); private: int vunit,vblk; }; #endif // REDOLOG class class redolog_t { public: redolog_t(); int make_header(const char* type, Bit64u size); int create(const char* filename, const char* type, Bit64u size); int create(int filedes, const char* type, Bit64u size); int open(const char* filename, const char* type); void close(); Bit64u get_size(); Bit32u get_timestamp(); bx_bool set_timestamp(Bit32u timestamp); Bit64s lseek(Bit64s offset, int whence); ssize_t read(void* buf, size_t count); ssize_t write(const void* buf, size_t count); private: void print_header(); int fd; redolog_header_t header; // Header is kept in x86 (little) endianness Bit32u *catalog; Bit8u *bitmap; bx_bool bitmap_update; Bit32u extent_index; Bit32u extent_offset; Bit32u extent_next; Bit32u bitmap_blocks; Bit32u extent_blocks; Bit64s imagepos; }; // GROWING MODE class growing_image_t : public device_image_t { public: // Contructor growing_image_t(); virtual ~growing_image_t(); // Open a image. Returns non-negative if successful. int open(const char* pathname); // Close the image. void close(); // Position ourselves. Return the resulting offset from the // beginning of the file. Bit64s lseek(Bit64s offset, int whence); // Read count bytes to the buffer buf. Return the number of // bytes read (count). ssize_t read(void* buf, size_t count); // Write count bytes from buf. Return the number of bytes // written (count). ssize_t write(const void* buf, size_t count); private: redolog_t *redolog; }; // UNDOABLE MODE class undoable_image_t : public device_image_t { public: // Contructor undoable_image_t(const char* redolog_name); virtual ~undoable_image_t(); // Open a image. Returns non-negative if successful. int open(const char* pathname); // Close the image. void close(); // Position ourselves. Return the resulting offset from the // beginning of the file. Bit64s lseek(Bit64s offset, int whence); // Read count bytes to the buffer buf. Return the number of // bytes read (count). ssize_t read(void* buf, size_t count); // Write count bytes from buf. Return the number of bytes // written (count). ssize_t write(const void* buf, size_t count); private: redolog_t *redolog; // Redolog instance default_image_t *ro_disk; // Read-only flat disk instance char *redolog_name; // Redolog name }; // VOLATILE MODE class volatile_image_t : public device_image_t { public: // Contructor volatile_image_t(const char* redolog_name); virtual ~volatile_image_t(); // Open a image. Returns non-negative if successful. int open(const char* pathname); // Close the image. void close(); // Position ourselves. Return the resulting offset from the // beginning of the file. Bit64s lseek(Bit64s offset, int whence); // Read count bytes to the buffer buf. Return the number of // bytes read (count). ssize_t read(void* buf, size_t count); // Write count bytes from buf. Return the number of bytes // written (count). ssize_t write(const void* buf, size_t count); private: redolog_t *redolog; // Redolog instance default_image_t *ro_disk; // Read-only flat disk instance char *redolog_name; // Redolog name char *redolog_temp; // Redolog temporary file name }; class bx_hdimage_ctl_c : public bx_hdimage_ctl_stub_c { public: bx_hdimage_ctl_c(); virtual ~bx_hdimage_ctl_c() {} virtual device_image_t *init_image(Bit8u image_mode, Bit64u disk_size, const char *journal); #ifdef LOWLEVEL_CDROM virtual LOWLEVEL_CDROM* init_cdrom(const char *dev); #endif }; #endif // HDIMAGE_HEADERS_ONLY #endif bochs-2.6/iodev/hdimage/vvfat.h0000644000175000017500000001415512020641504016340 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vvfat.h 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Virtual VFAT image support (shadows a local directory) // ported from QEMU block driver with some additions (see vvfat.cc) // // Copyright (c) 2004,2005 Johannes E. Schindelin // Copyright (C) 2010-2012 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // ///////////////////////////////////////////////////////////////////////// #ifndef BX_VVFAT_H #define BX_VVFAT_H typedef struct array_t { char *pointer; unsigned int size, next, item_size; } array_t; typedef struct { Bit8u head; Bit8u sector; Bit8u cylinder; } mbr_chs_t; #if defined(_MSC_VER) && (_MSC_VER<1300) #pragma pack(push, 1) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=packed #endif typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct direntry_t { Bit8u name[8]; Bit8u extension[3]; Bit8u attributes; Bit8u reserved[2]; Bit16u ctime; Bit16u cdate; Bit16u adate; Bit16u begin_hi; Bit16u mtime; Bit16u mdate; Bit16u begin; Bit32u size; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif direntry_t; #if defined(_MSC_VER) && (_MSC_VER<1300) #pragma pack(pop) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=reset #endif // this structure are used to transparently access the files enum { MODE_UNDEFINED = 0, MODE_NORMAL = 1, MODE_MODIFIED = 2, MODE_DIRECTORY = 4, MODE_FAKED = 8, MODE_DELETED = 16, MODE_RENAMED = 32 }; typedef struct mapping_t { // begin is the first cluster, end is the last+1 Bit32u begin, end; // as this->directory is growable, no pointer may be used here unsigned int dir_index; // the clusters of a file may be in any order; this points to the first int first_mapping_index; union { /* offset is * - the offset in the file (in clusters) for a file, or * - the next cluster of the directory for a directory, and * - the address of the buffer for a faked entry */ struct { Bit32u offset; } file; struct { int parent_mapping_index; int first_dir_index; } dir; } info; // path contains the full path, i.e. it always starts with vvfat_path char *path; Bit8u mode; int read_only; } mapping_t; #ifndef WIN32 Bit16u fat_datetime(time_t time, int return_time); #else Bit16u fat_datetime(FILETIME time, int return_time); #endif class vvfat_image_t : public device_image_t { public: vvfat_image_t(Bit64u size, const char* redolog_name); virtual ~vvfat_image_t(); int open(const char* dirname); void close(); Bit64s lseek(Bit64s offset, int whence); ssize_t read(void* buf, size_t count); ssize_t write(const void* buf, size_t count); Bit32u get_capabilities(); private: bx_bool sector2CHS(Bit32u spos, mbr_chs_t *chs); void init_mbr(); direntry_t* create_long_filename(const char* filename); void fat_set(unsigned int cluster, Bit32u value); void init_fat(); direntry_t* create_short_and_long_name(unsigned int directory_start, const char* filename, int is_dot); int read_directory(int mapping_index); Bit32u sector2cluster(off_t sector_num); off_t cluster2sector(Bit32u cluster_num); int init_directories(const char* dirname); bx_bool read_sector_from_file(const char *path, Bit8u *buffer, Bit32u sector); void set_file_attributes(void); Bit32u fat_get_next(Bit32u current); bx_bool write_file(const char *path, direntry_t *entry, bx_bool create); direntry_t* read_direntry(Bit8u *buffer, char *filename); void parse_directory(const char *path, Bit32u start_cluster); void commit_changes(void); void close_current_file(void); int open_file(mapping_t* mapping); int find_mapping_for_cluster_aux(int cluster_num, int index1, int index2); mapping_t* find_mapping_for_cluster(int cluster_num); mapping_t* find_mapping_for_path(const char* path); int read_cluster(int cluster_num); Bit8u *first_sectors; Bit32u offset_to_bootsector; Bit32u offset_to_fat; Bit32u offset_to_root_dir; Bit32u offset_to_data; Bit16u cluster_size; Bit8u sectors_per_cluster; Bit32u sectors_per_fat; Bit32u sector_count; Bit32u cluster_count; // total number of clusters of this partition Bit32u max_fat_value; Bit32u first_cluster_of_root_dir; Bit16u root_entries; Bit16u reserved_sectors; Bit8u fat_type; array_t fat, directory, mapping; int current_fd; mapping_t* current_mapping; Bit8u *cluster; // points to current cluster Bit8u *cluster_buffer; // points to a buffer to hold temp data Bit16u current_cluster; const char *vvfat_path; Bit32u sector_num; bx_bool use_mbr_file; bx_bool use_boot_file; FILE *vvfat_attr_fd; bx_bool vvfat_modified; void *fat2; redolog_t *redolog; // Redolog instance char *redolog_name; // Redolog name char *redolog_temp; // Redolog temporary file name }; #endif bochs-2.6/iodev/hdimage/cdrom.cc0000644000175000017500000001156712020641504016460 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cdrom.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // shared code for the low-level cdrom support // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "bochs.h" #if BX_SUPPORT_CDROM #include "cdrom.h" #define LOG_THIS /* no SMF tricks here, not needed */ #define BX_CD_FRAMESIZE 2048 bx_bool cdrom_interface::create_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format) { unsigned i; Bit32u blocks; int len = 4; switch (format) { case 0: // From atapi specs : start track can be 0-63, AA if ((start_track > 1) && (start_track != 0xaa)) return 0; buf[2] = 1; buf[3] = 1; if (start_track <= 1) { buf[len++] = 0; // Reserved buf[len++] = 0x14; // ADR, control buf[len++] = 1; // Track number buf[len++] = 0; // Reserved // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = 0; // minute buf[len++] = 2; // second buf[len++] = 0; // frame } else { buf[len++] = 0; buf[len++] = 0; buf[len++] = 0; buf[len++] = 0; // logical sector 0 } } // Lead out track buf[len++] = 0; // Reserved buf[len++] = 0x16; // ADR, control buf[len++] = 0xaa; // Track number buf[len++] = 0; // Reserved blocks = capacity(); // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = (Bit8u)(((blocks + 150) / 75) / 60); // minute buf[len++] = (Bit8u)(((blocks + 150) / 75) % 60); // second buf[len++] = (Bit8u)((blocks + 150) % 75); // frame; } else { buf[len++] = (blocks >> 24) & 0xff; buf[len++] = (blocks >> 16) & 0xff; buf[len++] = (blocks >> 8) & 0xff; buf[len++] = (blocks >> 0) & 0xff; } buf[0] = ((len-2) >> 8) & 0xff; buf[1] = (len-2) & 0xff; break; case 1: // multi session stuff - emulate a single session only buf[0] = 0; buf[1] = 0x0a; buf[2] = 1; buf[3] = 1; for (i = 0; i < 8; i++) buf[4+i] = 0; len = 12; break; case 2: // raw toc - emulate a single session only (ported from qemu) buf[2] = 1; buf[3] = 1; for (i = 0; i < 4; i++) { buf[len++] = 1; buf[len++] = 0x14; buf[len++] = 0; if (i < 3) { buf[len++] = 0xa0 + i; } else { buf[len++] = 1; } buf[len++] = 0; buf[len++] = 0; buf[len++] = 0; if (i < 2) { buf[len++] = 0; buf[len++] = 1; buf[len++] = 0; buf[len++] = 0; } else if (i == 2) { blocks = capacity(); if (msf) { buf[len++] = 0; // reserved buf[len++] = (Bit8u)(((blocks + 150) / 75) / 60); // minute buf[len++] = (Bit8u)(((blocks + 150) / 75) % 60); // second buf[len++] = (Bit8u)((blocks + 150) % 75); // frame; } else { buf[len++] = (blocks >> 24) & 0xff; buf[len++] = (blocks >> 16) & 0xff; buf[len++] = (blocks >> 8) & 0xff; buf[len++] = (blocks >> 0) & 0xff; } } else { buf[len++] = 0; buf[len++] = 0; buf[len++] = 0; buf[len++] = 0; } } buf[0] = ((len-2) >> 8) & 0xff; buf[1] = (len-2) & 0xff; break; default: BX_PANIC(("cdrom: create_toc(): unknown format")); return 0; } *length = len; return 1; } bx_bool cdrom_interface::seek(Bit32u lba) { unsigned char buffer[BX_CD_FRAMESIZE]; return read_block(buffer, lba, BX_CD_FRAMESIZE); } #endif /* if BX_SUPPORT_CDROM */ bochs-2.6/iodev/hdimage/scsi_commands.h0000644000175000017500000003320412020641504020030 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: scsi_commands.h 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// /* scsi/commands.h Used only in cdrom_amigaos.cc. Operation codes for SCSI-2 commands 30 Nov 94 Peter Urbanec Created file 10 Jan 95 Peter Urbanec Added SCSI_ prefix to all commands 31 Jan 95 Peter Urbanec Released to public */ /* All device types */ #define SCSI_CHANGE_DEFINITION 0x40 #define SCSI_COMPARE 0x39 #define SCSI_COPY 0x18 #define SCSI_COPY_AND_VERIFY 0x3a #define SCSI_INQUIRY 0x12 #define SCSI_LOG_SELECT 0x4c #define SCSI_LOG_SENSE 0x4d #define SCSI_MODE_SELECT_6 0x15 #define SCSI_MODE_SELECT_10 0x55 #define SCSI_MODE_SENSE_6 0x1a #define SCSI_MODE_SENSE_10 0x5a #define SCSI_READ_BUFFER 0x3c #define SCSI_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_REQUEST_SENSE 0x03 #define SCSI_SEND_DIAGNOSTIC 0x1d #define SCSI_TEST_UNIT_READY 0x00 #define SCSI_WRITE_BUFFER 0x3b /* Direct Access devices */ #define SCSI_DA_CHANGE_DEFINITION 0x40 #define SCSI_DA_COMPARE 0x39 #define SCSI_DA_COPY 0x18 #define SCSI_DA_COPY_AND_VERIFY 0x3a #define SCSI_DA_FORMAT_UNIT 0x04 #define SCSI_DA_INQUIRY 0x12 #define SCSI_DA_LOCK_UNLOCK_CACHE 0x36 #define SCSI_DA_LOG_SELECT 0x4c #define SCSI_DA_LOG_SENSE 0x4d #define SCSI_DA_MODE_SELECT_6 0x15 #define SCSI_DA_MODE_SELECT_10 0x55 #define SCSI_DA_MODE_SENSE_6 0x1a #define SCSI_DA_MODE_SENSE_10 0x5a #define SCSI_DA_PRE_FETCH 0x34 #define SCSI_DA_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define SCSI_DA_READ_6 0x08 #define SCSI_DA_READ_10 0x28 #define SCSI_DA_READ_BUFFER 0x3c #define SCSI_DA_READ_CAPACITY 0x25 #define SCSI_DA_READ_DEFECT_DATA 0x37 #define SCSI_DA_READ_LONG 0x3e #define SCSI_DA_REASSIGN_BLOCKS 0x07 #define SCSI_DA_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_DA_RELEASE 0x17 #define SCSI_DA_REQUEST_SENSE 0x03 #define SCSI_DA_RESERVE 0x16 #define SCSI_DA_REZERO_UNIT 0x01 #define SCSI_DA_SEARCH_DATA_EQUAL 0x31 #define SCSI_DA_SEARCH_DATA_HIGH 0x30 #define SCSI_DA_SEARCH_DATA_LOW 0x32 #define SCSI_DA_SEEK_6 0x0b #define SCSI_DA_SEEK_10 0x2b #define SCSI_DA_SEND_DIAGNOSTIC 0x1d #define SCSI_DA_SET_LIMITS 0x33 #define SCSI_DA_START_STOP_UNIT 0x1b #define SCSI_DA_SYNCHRONIZE_CACHE 0x35 #define SCSI_DA_TEST_UNIT_READY 0x00 #define SCSI_DA_VERIFY 0x2f /* Sequential access devices */ #define SCSI_SA_CHANGE_DEFINITION 0x40 #define SCSI_SA_COMPARE 0x39 #define SCSI_SA_COPY 0x18 #define SCSI_SA_COPY_AND_VERIFY 0x3a #define SCSI_SA_ERASE 0x19 #define SCSI_SA_INQUIRY 0x12 #define SCSI_SA_LOAD_UNLOAD 0x1b #define SCSI_SA_LOCATE 0x2b #define SCSI_SA_LOG_SELECT 0x4c #define SCSI_SA_LOG_SENSE 0x4d #define SCSI_SA_MODE_SELECT_6 0x15 #define SCSI_SA_MODE_SELECT_10 0x55 #define SCSI_SA_MODE_SENSE_6 0x1a #define SCSI_SA_MODE_SENSE_10 0x5a #define SCSI_SA_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define SCSI_SA_READ 0x08 #define SCSI_SA_READ_BLOCK_LIMITS 0x05 #define SCSI_SA_READ_BUFFER 0x3c #define SCSI_SA_READ_POSITION 0x34 #define SCSI_SA_READ_REVERSE 0x0f #define SCSI_SA_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_SA_RECOVER_BUFFERED_DATA 0x14 #define SCSI_SA_RELEASE_UNIT 0x17 #define SCSI_SA_REQUEST_SENSE 0x03 #define SCSI_SA_RESERVE_UNIT 0x16 #define SCSI_SA_REWIND 0x01 #define SCSI_SA_SEND_DIAGNOSTIC 0x1d #define SCSI_SA_SPACE 0x11 #define SCSI_SA_TEST_UNIT_READY 0x00 #define SCSI_SA_VERIFY 0x13 #define SCSI_SA_WRITE 0x0a #define SCSI_SA_WRITE_BUFFER 0x3b #define SCSI_SA_WRITE_FILEMARKS 0x10 /* Printer devices */ #define SCSI_PRT_CHANGE_DEFINITION 0x40 #define SCSI_PRT_COMPARE 0x39 #define SCSI_PRT_COPY 0x18 #define SCSI_PRT_COPY_AND_VERIFY 0x3a #define SCSI_PRT_FORMAT 0x04 #define SCSI_PRT_INQUIRY 0x12 #define SCSI_PRT_LOG_SELECT 0x4c #define SCSI_PRT_LOG_SENSE 0x4d #define SCSI_PRT_MODE_SELECT_6 0x15 #define SCSI_PRT_MODE_SELECT_10 0x55 #define SCSI_PRT_MODE_SENSE_6 0x1a #define SCSI_PRT_MODE_SENSE_10 0x5a #define SCSI_PRT_PRINT 0x0a #define SCSI_PRT_READ_BUFFER 0x3c #define SCSI_PRT_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_PRT_RECOVER_BUFFERED_DATA 0x14 #define SCSI_PRT_RELEASE_UNIT 0x17 #define SCSI_PRT_REQUEST_SENSE 0x03 #define SCSI_PRT_RESERVE_UNIT 0x16 #define SCSI_PRT_SEND_DIAGNOSTIC 0x1d #define SCSI_PRT_SLEW_AND_PRINT 0x0b #define SCSI_PRT_STOP_PRINT 0x1b #define SCSI_PRT_SYNCHRONIZE_BUFFER 0x10 #define SCSI_PRT_TEST_UNIT_READY 0x00 #define SCSI_PRT_WRITE_BUFFER 0x3b /* Processor devices */ #define SCSI_CPU_CHANGE_DEFINITION 0x40 #define SCSI_CPU_COMPARE 0x39 #define SCSI_CPU_COPY 0x18 #define SCSI_CPU_COPY_AND_VERIFY 0x3a #define SCSI_CPU_INQUIRY 0x12 #define SCSI_CPU_LOG_SELECT 0x4c #define SCSI_CPU_LOG_SENSE 0x4d #define SCSI_CPU_READ_BUFFER 0x3c #define SCSI_CPU_RECEIVE 0x08 #define SCSI_CPU_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_CPU_REQUEST_SENSE 0x03 #define SCSI_CPU_SEND 0x0a #define SCSI_CPU_SEND_DIAGNOSTIC 0x1d #define SCSI_CPU_TEST_UNIT_READY 0x00 #define SCSI_CPU_WRITE_BUFFER 0x3b /* Write Once devices */ #define SCSI_WO_CHANGE_DEFINITION 0x40 #define SCSI_WO_COMPARE 0x39 #define SCSI_WO_COPY 0x18 #define SCSI_WO_COPY_AND_VERIFY 0x3a #define SCSI_WO_INQUIRY 0x12 #define SCSI_WO_LOCK_UNLOCK_CACHE 0x36 #define SCSI_WO_LOG_SELECT 0x4c #define SCSI_WO_LOG_SENSE 0x4d #define SCSI_WO_MEDIUM_SCAN 0x38 #define SCSI_WO_MODE_SELECT_6 0x15 #define SCSI_WO_MODE_SELECT_10 0x55 #define SCSI_WO_MODE_SENSE_6 0x1a #define SCSI_WO_MODE_SENSE_10 0x5a #define SCSI_WO_PRE_FETCH 0x34 #define SCSI_WO_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define SCSI_WO_READ_6 0x08 #define SCSI_WO_READ_10 0x28 #define SCSI_WO_READ_12 0xa8 #define SCSI_WO_READ_BUFFER 0x3c #define SCSI_WO_READ_CAPACITY 0x25 #define SCSI_WO_READ_LONG 0x3e #define SCSI_WO_REASSIGN_BLOCKS 0x07 #define SCSI_WO_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_WO_RELEASE 0x17 #define SCSI_WO_REQUEST_SENSE 0x03 #define SCSI_WO_RESERVE 0x16 #define SCSI_WO_REZERO_UNIT 0x01 #define SCSI_WO_SEARCH_DATA_EQUAL_10 0x31 #define SCSI_WO_SEARCH_DATA_EQUAL_12 0xb1 #define SCSI_WO_SEARCH_DATA_HIGH_10 0x30 #define SCSI_WO_SEARCH_DATA_HIGH_12 0xb0 #define SCSI_WO_SEARCH_DATA_LOW_10 0x32 #define SCSI_WO_SEARCH_DATA_LOW_12 0xb2 #define SCSI_WO_SEEK_6 0x0b #define SCSI_WO_SEEK_10 0x2b #define SCSI_WO_SEND_DIAGNOSTIC 0x1d #define SCSI_WO_SET_LIMITS_10 0x33 #define SCSI_WO_SET_LIMITS_12 0xb3 #define SCSI_WO_START_STOP_UNIT 0x1b #define SCSI_WO_SYNCHRONIZE_CACHE 0x35 #define SCSI_WO_TEST_UNIT_READY 0x00 #define SCSI_WO_VERIFY_10 0x2f #define SCSI_WO_VERIFY_12 0xaf #define SCSI_WO_WRITE_6 0x0a #define SCSI_WO_WRITE_10 0x2a #define SCSI_WO_WRITE_12 0xaa #define SCSI_WO_WRITE_AND_VERIFY_10 0x2e #define SCSI_WO_WRITE_AND_VERIFY_12 0xae #define SCSI_WO_WRITE_BUFFER 0x3b #define SCSI_WO_WRITE_LONG 0x3f /* CD-ROM devices */ #define SCSI_CD_CHANGE_DEFINITION 0x40 #define SCSI_CD_COMPARE 0x39 #define SCSI_CD_COPY 0x18 #define SCSI_CD_COPY_AND_VERIFY 0x3a #define SCSI_CD_INQUIRY 0x12 #define SCSI_CD_LOCK_UNLOCK_CACHE 0x36 #define SCSI_CD_LOG_SELECT 0x4c #define SCSI_CD_LOG_SENSE 0x4d #define SCSI_CD_MODE_SELECT_6 0x15 #define SCSI_CD_MODE_SELECT_10 0x55 #define SCSI_CD_MODE_SENSE_6 0x1a #define SCSI_CD_MODE_SENSE_10 0x5a #define SCSI_CD_PAUSE_RESUME 0x4b #define SCSI_CD_PLAY_AUDIO_10 0x45 #define SCSI_CD_PLAY_AUDIO_12 0xa5 #define SCSI_CD_PLAY_AUDIO_MSF 0x47 #define SCSI_CD_PLAY_AUDIO_TRACK_INDEX 0x48 #define SCSI_CD_PLAY_TRACK_RELATIVE_10 0x49 #define SCSI_CD_PLAY_TRACK_RELATIVE_12 0xa9 #define SCSI_CD_PRE_FETCH 0x34 #define SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define SCSI_CD_READ_6 0x08 #define SCSI_CD_READ_10 0x28 #define SCSI_CD_READ_12 0xa8 #define SCSI_CD_READ_BUFFER 0x3c #define SCSI_CD_READ_CD_ROM_CAPACITY 0x25 #define SCSI_CD_READ_HEADER 0x44 #define SCSI_CD_READ_LONG 0x3e #define SCSI_CD_READ_SUB_CHANNEL 0x42 #define SCSI_CD_READ_TOC 0x43 #define SCSI_CD_RECEIVE_DIAGNOSTIC_RESULT 0x1c #define SCSI_CD_RELEASE 0x17 #define SCSI_CD_REQUEST_SENSE 0x03 #define SCSI_CD_RESERVE 0x16 #define SCSI_CD_REZERO_UNIT 0x01 #define SCSI_CD_SEARCH_DATA_EQUAL_10 0x31 #define SCSI_CD_SEARCH_DATA_EQUAL_12 0xb1 #define SCSI_CD_SEARCH_DATA_HIGH_10 0x30 #define SCSI_CD_SEARCH_DATA_HIGH_12 0xb0 #define SCSI_CD_SEARCH_DATA_LOW_10 0x32 #define SCSI_CD_SEARCH_DATA_LOW_12 0xb2 #define SCSI_CD_SEEK_6 0x0b #define SCSI_CD_SEEK_10 0x2b #define SCSI_CD_SEND_DIAGNOSTIC 0x1d #define SCSI_CD_SET_LIMITS_10 0x33 #define SCSI_CD_SET_LIMITS_12 0xb3 #define SCSI_CD_START_STOP_UNIT 0x1b #define SCSI_CD_SYNCHRONIZE_CACHE 0x35 #define SCSI_CD_TEST_UNIT_READY 0x00 #define SCSI_CD_VERIFY_10 0x2f #define SCSI_CD_VERIFY_12 0xaf #define SCSI_CD_WRITE_BUFFER 0x3b /* Scanner devices */ #define SCSI_SC_CHANGE_DEFINITION 0x40 #define SCSI_SC_COMPARE 0x39 #define SCSI_SC_COPY 0x18 #define SCSI_SC_COPY_AND_VERIFY 0x3a #define SCSI_SC_GET_DATA_BUFFER_STATUS 0x34 #define SCSI_SC_GET_WINDOW 0x25 #define SCSI_SC_INQUIRY 0x12 #define SCSI_SC_LOG_SELECT 0x4c #define SCSI_SC_LOG_SENSE 0x4d #define SCSI_SC_MODE_SELECT_6 0x15 #define SCSI_SC_MODE_SELECT_10 0x55 #define SCSI_SC_MODE_SENSE_6 0x1a #define SCSI_SC_MODE_SENSE_10 0x5a #define SCSI_SC_OBJECT_POSITION 0x31 #define SCSI_SC_READ 0x28 #define SCSI_SC_READ_BUFFER 0x3c #define SCSI_SC_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_SC_RELEASE_UNIT 0x17 #define SCSI_SC_REQUEST_SENSE 0x03 #define SCSI_SC_RESERVE_UNIT 0x16 #define SCSI_SC_SCAN 0x1b #define SCSI_SC_SET_WINDOW 0x24 #define SCSI_SC_SEND 0x2a #define SCSI_SC_SEND_DIAGNOSTIC 0x1d #define SCSI_SC_TEST_UNIT_READY 0x00 #define SCSI_SC_WRITE_BUFFER 0x3b /* Optical memory devices */ #define SCSI_OM_CHANGE_DEFINITION 0x40 #define SCSI_OM_COMPARE 0x39 #define SCSI_OM_COPY 0x18 #define SCSI_OM_COPY_AND_VERIFY 0x3a #define SCSI_OM_ERASE_10 0x2c #define SCSI_OM_ERASE_12 0xac #define SCSI_OM_FORMAT_UNIT 0x04 #define SCSI_OM_INQUIRY 0x12 #define SCSI_OM_LOCK_UNLOCK_CACHE 0x36 #define SCSI_OM_LOG_SELECT 0x4c #define SCSI_OM_LOG_SENSE 0x4d #define SCSI_OM_MEDIUM_SCAN 0x38 #define SCSI_OM_MODE_SELECT_6 0x15 #define SCSI_OM_MODE_SELECT_10 0x55 #define SCSI_OM_MODE_SENSE_6 0x1a #define SCSI_OM_MODE_SENSE_10 0x5a #define SCSI_OM_PRE_FETCH 0x34 #define SCSI_OM_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define SCSI_OM_READ_6 0x08 #define SCSI_OM_READ_10 0x28 #define SCSI_OM_READ_12 0xa8 #define SCSI_OM_READ_BUFFER 0x3c #define SCSI_OM_READ_CAPACITY 0x25 #define SCSI_OM_READ_DEFECT_DATA_10 0x37 #define SCSI_OM_READ_DEFECT_DATA_12 0xb7 #define SCSI_OM_READ_GENERATION 0x29 #define SCSI_OM_READ_LONG 0x3e #define SCSI_OM_READ_UPDATED_BLOCK 0x2d #define SCSI_OM_REASSIGN_BLOCKS 0x07 #define SCSI_OM_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_OM_RELEASE 0x17 #define SCSI_OM_REQUEST_SENSE 0x03 #define SCSI_OM_RESERVE 0x16 #define SCSI_OM_REZERO_UNIT 0x01 #define SCSI_OM_SEARCH_DATA_EQUAL_10 0x31 #define SCSI_OM_SEARCH_DATA_EQUAL_12 0xb1 #define SCSI_OM_SEARCH_DATA_HIGH_10 0x30 #define SCSI_OM_SEARCH_DATA_HIGH_12 0xb0 #define SCSI_OM_SEARCH_DATA_LOW_10 0x32 #define SCSI_OM_SEARCH_DATA_LOW_12 0xb2 #define SCSI_OM_SEEK_6 0x0b #define SCSI_OM_SEEK_10 0x2b #define SCSI_OM_SEND_DIAGNOSTIC 0x1d #define SCSI_OM_SET_LIMITS_10 0x33 #define SCSI_OM_SET_LIMITS_12 0xb3 #define SCSI_OM_START_STOP_UNIT 0x1b #define SCSI_OM_SYNCHRONIZE_CACHE 0x35 #define SCSI_OM_TEST_UNIT_READY 0x00 #define SCSI_OM_UPDATE_BLOCK 0x3d #define SCSI_OM_VERIFY_10 0x2f #define SCSI_OM_VERIFY_12 0xaf #define SCSI_OM_WRITE_6 0x0a #define SCSI_OM_WRITE_10 0x2a #define SCSI_OM_WRITE_12 0xaa #define SCSI_OM_WRITE_AND_VERIFY_10 0x2e #define SCSI_OM_WRITE_AND_VERIFY_12 0xae #define SCSI_OM_WRITE_BUFFER 0x3b #define SCSI_OM_WRITE_LONG 0x3f /* Medium changer devices */ #define SCSI_MC_CHANGE_DEFINITION 0x40 #define SCSI_MC_EXCHANGE_MEDIUM 0xa6 #define SCSI_MC_INITIALIZE_ELEMENT_STATUS 0x07 #define SCSI_MC_INQUIRY 0x12 #define SCSI_MC_LOG_SELECT 0x4c #define SCSI_MC_LOG_SENSE 0x4d #define SCSI_MC_MODE_SELECT_6 0x15 #define SCSI_MC_MODE_SELECT_10 0x55 #define SCSI_MC_MODE_SENSE_6 0x1a #define SCSI_MC_MODE_SENSE_10 0x5a #define SCSI_MC_MOVE_MEDIUM 0xa5 #define SCSI_MC_POSITION_TO_ELEMENT 0x2b #define SCSI_MC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e #define SCSI_MC_READ_BUFFER 0x3c #define SCSI_MC_READ_ELEMENT_STATUS 0xb8 #define SCSI_MC_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_MC_RELEASE 0x17 #define SCSI_MC_REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5 #define SCSI_MC_REQUEST_SENSE 0x03 #define SCSI_MC_RESERVE 0x16 #define SCSI_MC_REZERO_UNIT 0x01 #define SCSI_MC_SEND_DIAGNOSTIC 0x1d #define SCSI_MC_SEND_VOLUME_TAG 0xb6 #define SCSI_MC_TEST_UNIT_READY 0x00 #define SCSI_MC_WRITE_BUFFER 0x3b /* Communications devices */ #define SCSI_COM_CHANGE_DEFINITION 0x40 #define SCSI_COM_GET_MESSAGE_6 0x08 #define SCSI_COM_GET_MESSAGE_10 0x28 #define SCSI_COM_GET_MESSAGE_12 0xa8 #define SCSI_COM_INQUIRY 0x12 #define SCSI_COM_LOG_SELECT 0x4c #define SCSI_COM_LOG_SENSE 0x4d #define SCSI_COM_MODE_SELECT_6 0x15 #define SCSI_COM_MODE_SELECT_10 0x55 #define SCSI_COM_MODE_SENSE_6 0x1a #define SCSI_COM_MODE_SENSE_10 0x5a #define SCSI_COM_READ_BUFFER 0x3c #define SCSI_COM_RECEIVE_DIAGNOSTIC_RESULTS 0x1c #define SCSI_COM_REQUEST_SENSE 0x03 #define SCSI_COM_SEND_DIAGNOSTIC 0x1d #define SCSI_COM_SEND_MESSAGE_6 0x0a #define SCSI_COM_SEND_MESSAGE_10 0x2a #define SCSI_COM_SEND_MESSAGE_12 0xaa #define SCSI_COM_TEST_UNIT_READY 0x00 #define SCSI_COM_WRITE_BUFFER 0x3b bochs-2.6/iodev/hdimage/cdrom_misc.cc0000644000175000017500000003735612020641504017477 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cdrom_misc.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // These are the low-level CDROM functions which are called // from 'harddrv.cc'. They effect the OS specific functionality // needed by the CDROM emulation in 'harddrv.cc'. Mostly, just // ioctl() calls and such. Should be fairly easy to add support // for your OS if it is not supported yet. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "bochs.h" #if BX_SUPPORT_CDROM #include "cdrom.h" #define LOG_THIS /* no SMF tricks here, not needed */ extern "C" { #include } #ifdef __linux__ extern "C" { #include #include // I use the framesize in non OS specific code too #define BX_CD_FRAMESIZE CD_FRAMESIZE } #elif defined(__GNU__) || (defined(__CYGWIN32__) && !defined(WIN32)) extern "C" { #include #define BX_CD_FRAMESIZE 2048 #define CD_FRAMESIZE 2048 } #elif defined(__sun) extern "C" { #include #include #include #include #define BX_CD_FRAMESIZE CDROM_BLK_2048 } #elif defined(__DJGPP__) extern "C" { #include #define BX_CD_FRAMESIZE 2048 #define CD_FRAMESIZE 2048 } #elif (defined(__NetBSD__) || defined(__NetBSD_kernel__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) // OpenBSD pre version 2.7 may require extern "C" { } structure around // all the includes, because the i386 sys/disklabel.h contains code which // c++ considers invalid. #include #include #include #include #if defined(__OpenBSD__) #include #endif #include #include // ntohl(x) et al have been moved out of sys/param.h in FreeBSD 5 #include // XXX #define BX_CD_FRAMESIZE 2048 #define CD_FRAMESIZE 2048 #elif !defined(WIN32) // all others (Irix, Tru64) #include #include #include #define BX_CD_FRAMESIZE 2048 #define CD_FRAMESIZE 2048 #endif #include static unsigned int cdrom_count = 0; cdrom_interface::cdrom_interface(const char *dev) { char prefix[6]; sprintf(prefix, "CD%d", ++cdrom_count); put(prefix); fd = -1; // File descriptor not yet allocated if (dev == NULL) { path = NULL; } else { path = strdup(dev); } using_file=0; } cdrom_interface::~cdrom_interface(void) { if (fd >= 0) close(fd); if (path) free(path); BX_DEBUG(("Exit")); } bx_bool cdrom_interface::insert_cdrom(const char *dev) { unsigned char buffer[BX_CD_FRAMESIZE]; ssize_t ret; // Load CD-ROM. Returns 0 if CD is not ready. if (dev != NULL) path = strdup(dev); BX_INFO (("load cdrom with path=%s", path)); // all platforms except win32 fd = open(path, O_RDONLY); if (fd < 0) { BX_ERROR(("open cd failed for %s: %s", path, strerror(errno))); return 0; } // do fstat to determine if it's a file or a device, then set using_file. struct stat stat_buf; ret = fstat (fd, &stat_buf); if (ret) { BX_PANIC (("fstat cdrom file returned error: %s", strerror (errno))); } if (S_ISREG (stat_buf.st_mode)) { using_file = 1; BX_INFO (("Opening image file as a cd.")); } else { using_file = 0; BX_INFO (("Using direct access for cdrom.")); } // I just see if I can read a sector to verify that a // CD is in the drive and readable. return read_block(buffer, 0, 2048); } bx_bool cdrom_interface::start_cdrom() { // Spin up the cdrom drive. if (fd >= 0) { #if defined(__NetBSD__) || defined(__NetBSD_kernel__) if (ioctl (fd, CDIOCSTART) < 0) BX_DEBUG(("start_cdrom: start returns error: %s", strerror (errno))); return 1; #else BX_INFO(("start_cdrom: your OS is not supported yet")); return 0; // OS not supported yet, return 0 always #endif } return 0; } void cdrom_interface::eject_cdrom() { // Logically eject the CD. I suppose we could stick in // some ioctl() calls to really eject the CD as well. if (fd >= 0) { #if (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) (void) ioctl (fd, CDIOCALLOW); if (ioctl (fd, CDIOCEJECT) < 0) BX_DEBUG(("eject_cdrom: eject returns error")); #endif #if __linux__ if (!using_file) ioctl (fd, CDROMEJECT, NULL); #endif close(fd); fd = -1; } } bx_bool cdrom_interface::read_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format) { // Read CD TOC. Returns 0 if start track is out of bounds. if (fd < 0) { BX_PANIC(("cdrom: read_toc: file not open.")); return 0; } // This is a hack and works okay if there's one rom track only if (using_file || (format != 0)) { return create_toc(buf, length, msf, start_track, format); } // all these implementations below are the platform-dependent code required // to read the TOC from a physical cdrom. #if __linux__ || defined(__sun) { struct cdrom_tochdr tochdr; if (ioctl(fd, CDROMREADTOCHDR, &tochdr)) BX_PANIC(("cdrom: read_toc: READTOCHDR failed.")); if ((start_track > tochdr.cdth_trk1) && (start_track != 0xaa)) return 0; buf[2] = tochdr.cdth_trk0; buf[3] = tochdr.cdth_trk1; if (start_track < tochdr.cdth_trk0) start_track = tochdr.cdth_trk0; int len = 4; for (int i = start_track; i <= tochdr.cdth_trk1; i++) { struct cdrom_tocentry tocentry; tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA; tocentry.cdte_track = i; if (ioctl(fd, CDROMREADTOCENTRY, &tocentry)) BX_PANIC(("cdrom: read_toc: READTOCENTRY failed.")); buf[len++] = 0; // Reserved buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control buf[len++] = i; // Track number buf[len++] = 0; // Reserved // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = tocentry.cdte_addr.msf.minute; buf[len++] = tocentry.cdte_addr.msf.second; buf[len++] = tocentry.cdte_addr.msf.frame; } else { buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff; buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff; buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff; buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff; } } // Lead out track struct cdrom_tocentry tocentry; tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA; #ifdef CDROM_LEADOUT tocentry.cdte_track = CDROM_LEADOUT; #else tocentry.cdte_track = 0xaa; #endif if (ioctl(fd, CDROMREADTOCENTRY, &tocentry)) BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed.")); buf[len++] = 0; // Reserved buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control buf[len++] = 0xaa; // Track number buf[len++] = 0; // Reserved // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = tocentry.cdte_addr.msf.minute; buf[len++] = tocentry.cdte_addr.msf.second; buf[len++] = tocentry.cdte_addr.msf.frame; } else { buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff; buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff; buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff; buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff; } buf[0] = ((len-2) >> 8) & 0xff; buf[1] = (len-2) & 0xff; *length = len; return 1; } #elif (defined(__NetBSD__) || defined(__NetBSD_kernel__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) { struct ioc_toc_header h; struct ioc_read_toc_entry t; if (ioctl (fd, CDIOREADTOCHEADER, &h) < 0) BX_PANIC(("cdrom: read_toc: READTOCHDR failed.")); if ((start_track > h.ending_track) && (start_track != 0xaa)) return 0; buf[2] = h.starting_track; buf[3] = h.ending_track; if (start_track < h.starting_track) start_track = h.starting_track; int len = 4; for (int i = start_track; i <= h.ending_track; i++) { struct cd_toc_entry tocentry; t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT; t.starting_track = i; t.data_len = sizeof(tocentry); t.data = &tocentry; if (ioctl (fd, CDIOREADTOCENTRYS, &t) < 0) BX_PANIC(("cdrom: read_toc: READTOCENTRY failed.")); buf[len++] = 0; // Reserved buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control buf[len++] = i; // Track number buf[len++] = 0; // Reserved // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = tocentry.addr.msf.minute; buf[len++] = tocentry.addr.msf.second; buf[len++] = tocentry.addr.msf.frame; } else { buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff; buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff; buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff; buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff; } } // Lead out track struct cd_toc_entry tocentry; t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT; t.starting_track = 0xaa; t.data_len = sizeof(tocentry); t.data = &tocentry; if (ioctl (fd, CDIOREADTOCENTRYS, &t) < 0) BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed.")); buf[len++] = 0; // Reserved buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control buf[len++] = 0xaa; // Track number buf[len++] = 0; // Reserved // Start address if (msf) { buf[len++] = 0; // reserved buf[len++] = tocentry.addr.msf.minute; buf[len++] = tocentry.addr.msf.second; buf[len++] = tocentry.addr.msf.frame; } else { buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff; buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff; buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff; buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff; } buf[0] = ((len-2) >> 8) & 0xff; buf[1] = (len-2) & 0xff; *length = len; return 1; } #else BX_INFO(("read_toc: your OS is not supported yet")); return 0; // OS not supported yet, return 0 always. #endif } Bit32u cdrom_interface::capacity() { // Return CD-ROM capacity. I believe you want to return // the number of blocks of capacity the actual media has. if (using_file) { // return length of the image file struct stat stat_buf; int ret = fstat (fd, &stat_buf); if (ret) { BX_PANIC (("fstat on cdrom image returned err: %s", strerror(errno))); } if ((stat_buf.st_size % 2048) != 0) { BX_ERROR (("expected cdrom image to be a multiple of 2048 bytes")); } return (stat_buf.st_size / 2048); } #if defined(__sun) { struct stat buf = {0}; if (fd < 0) { BX_PANIC(("cdrom: capacity: file not open.")); } if(fstat(fd, &buf) != 0) BX_PANIC(("cdrom: capacity: stat() failed.")); return(buf.st_size); } #elif (defined(__NetBSD__) || defined(__NetBSD_kernel__) || defined(__OpenBSD__)) { // We just read the disklabel, imagine that... struct disklabel lp; if (fd < 0) BX_PANIC(("cdrom: capacity: file not open.")); if (ioctl(fd, DIOCGDINFO, &lp) < 0) BX_PANIC(("cdrom: ioctl(DIOCGDINFO) failed")); BX_DEBUG(("capacity: %u", lp.d_secperunit)); return(lp.d_secperunit); } #elif defined(__linux__) { // Read the TOC to get the data size, since BLKGETSIZE doesn't work on // non-ATAPI drives. This is based on Keith Jones code below. // 21 June 2001 int i, dtrk_lba, num_sectors; int dtrk = 0; struct cdrom_tochdr td; struct cdrom_tocentry te; if (fd < 0) BX_PANIC(("cdrom: capacity: file not open.")); if (ioctl(fd, CDROMREADTOCHDR, &td) < 0) BX_PANIC(("cdrom: ioctl(CDROMREADTOCHDR) failed")); num_sectors = -1; dtrk_lba = -1; for (i = td.cdth_trk0; i <= td.cdth_trk1; i++) { te.cdte_track = i; te.cdte_format = CDROM_LBA; if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0) BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed")); if (dtrk_lba != -1) { num_sectors = te.cdte_addr.lba - dtrk_lba; break; } if (te.cdte_ctrl & CDROM_DATA_TRACK) { dtrk = i; dtrk_lba = te.cdte_addr.lba; } } if (num_sectors < 0) { if (dtrk_lba != -1) { te.cdte_track = CDROM_LEADOUT; te.cdte_format = CDROM_LBA; if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0) BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed")); num_sectors = te.cdte_addr.lba - dtrk_lba; } else BX_PANIC(("cdrom: no data track found")); } BX_INFO(("cdrom: Data track %d, length %d", dtrk, num_sectors)); return(num_sectors); } #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) { // Read the TOC to get the size of the data track. // Keith Jones , 16 January 2000 #define MAX_TRACKS 100 int i, num_tracks, num_sectors; struct ioc_toc_header td; struct ioc_read_toc_entry rte; struct cd_toc_entry toc_buffer[MAX_TRACKS + 1]; if (fd < 0) BX_PANIC(("cdrom: capacity: file not open.")); if (ioctl(fd, CDIOREADTOCHEADER, &td) < 0) BX_PANIC(("cdrom: ioctl(CDIOREADTOCHEADER) failed")); num_tracks = (td.ending_track - td.starting_track) + 1; if (num_tracks > MAX_TRACKS) BX_PANIC(("cdrom: TOC is too large")); rte.address_format = CD_LBA_FORMAT; rte.starting_track = td.starting_track; rte.data_len = (num_tracks + 1) * sizeof(struct cd_toc_entry); rte.data = toc_buffer; if (ioctl(fd, CDIOREADTOCENTRYS, &rte) < 0) BX_PANIC(("cdrom: ioctl(CDIOREADTOCENTRYS) failed")); num_sectors = -1; for (i = 0; i < num_tracks; i++) { if (rte.data[i].control & 4) { /* data track */ num_sectors = ntohl(rte.data[i + 1].addr.lba) - ntohl(rte.data[i].addr.lba); BX_INFO(("cdrom: Data track %d, length %d", rte.data[i].track, num_sectors)); break; } } if (num_sectors < 0) BX_PANIC(("cdrom: no data track found")); return(num_sectors); } #else BX_ERROR(("capacity: your OS is not supported yet")); return(0); #endif } bx_bool BX_CPP_AttrRegparmN(3) cdrom_interface::read_block(Bit8u* buf, Bit32u lba, int blocksize) { // Read a single block from the CD off_t pos; ssize_t n = 0; Bit8u try_count = 3; Bit8u* buf1; if (blocksize == 2352) { memset(buf, 0, 2352); memset(buf+1, 0xff, 10); Bit32u raw_block = lba + 150; buf[12] = (raw_block / 75) / 60; buf[13] = (raw_block / 75) % 60; buf[14] = (raw_block % 75); buf[15] = 0x01; buf1 = buf + 16; } else { buf1 = buf; } do { pos = lseek(fd, (off_t) lba * BX_CD_FRAMESIZE, SEEK_SET); if (pos < 0) { BX_PANIC(("cdrom: read_block: lseek returned error.")); } else { n = read(fd, (char*) buf1, BX_CD_FRAMESIZE); } } while ((n != BX_CD_FRAMESIZE) && (--try_count > 0)); return (n == BX_CD_FRAMESIZE); } #endif /* if BX_SUPPORT_CDROM */ bochs-2.6/iodev/hdimage/vmware3.h0000644000175000017500000000750112020641504016573 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmware3.h 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// /* * This file provides the interface for using VMWare's virtual * disk image format under Bochs. * * Author: Sharvil Nanavati, for Net Integration Technologies, Inc. * Contact: snrrrub@yahoo.com * * Copyright (C) 2003 Net Integration Technologies, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _COWDISK_H #define _COWDISK_H 1 class vmware3_image_t : public device_image_t { public: vmware3_image_t() : FL_SHIFT(25), FL_MASK(0xFE000000) { }; int open(const char* pathname); void close(); Bit64s lseek(Bit64s offset, int whence); ssize_t read(void* buf, size_t count); ssize_t write(const void* buf, size_t count); Bit32u get_capabilities(); private: static const off_t INVALID_OFFSET; #if defined(_MSC_VER) && (_MSC_VER<1300) #pragma pack(push, 1) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=packed #endif typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct _COW_Header { Bit8u id[4]; Bit32u header_version; Bit32u flags; Bit32u total_sectors; Bit32u tlb_size_sectors; Bit32u flb_offset_sectors; Bit32u flb_count; Bit32u next_sector_to_allocate; Bit32u cylinders; Bit32u heads; Bit32u sectors; Bit8u PAD0[1016]; Bit32u last_modified_time; Bit8u PAD1[572]; Bit32u last_modified_time_save; Bit8u label[8]; Bit32u chain_id; Bit32u number_of_chains; Bit32u cylinders_in_disk; Bit32u heads_in_disk; Bit32u sectors_in_disk; Bit32u total_sectors_in_disk; Bit8u PAD2[8]; Bit32u vmware_version; Bit8u PAD3[364]; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif COW_Header ; #if defined(_MSC_VER) && (_MSC_VER<1300) #pragma pack(pop) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=reset #endif struct COW_Image; friend struct COW_Image; struct COW_Image { int fd; COW_Header header; Bit32u * flb; Bit32u ** slb; Bit8u * tlb; off_t offset; off_t min_offset; off_t max_offset; bool synced; } * images, * current; int read_header(int fd, COW_Header & header); int write_header(int fd, COW_Header & header); int read_ints(int fd, Bit32u *buffer, size_t count); int write_ints(int fd, Bit32u *buffer, size_t count); char * generate_cow_name(const char * filename, Bit32u chain); bool is_valid_header(COW_Header & header); off_t perform_seek(); bool sync(); const Bit32u FL_SHIFT; const Bit32u FL_MASK; off_t requested_offset; Bit32u slb_count; Bit32u tlb_size; }; #endif bochs-2.6/iodev/hdimage/cdrom_amigaos.cc0000644000175000017500000001416512020641504020155 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cdrom_amigaos.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2000-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // These are the low-level CDROM functions which are called // from 'harddrv.cc'. They effect the OS specific functionality // needed by the CDROM emulation in 'harddrv.cc'. Mostly, just // ioctl() calls and such. Should be fairly easy to add support // for your OS if it is not supported yet. #include "bochs.h" #include "scsi_commands.h" #include "cdrom.h" #include #include #include #include #include #include #include #include #include #define LOG_THIS /* no SMF tricks here, not needed */ #define BX_CD_FRAMESIZE 2048 #define CD_FRAMESIZE 2048 #define SENSELEN 32 #define MAX_DATA_LEN 252 int amiga_cd_unit; char amiga_cd_device[256]; struct MsgPort *CDMP; /* Pointer for message port */ struct IOExtTD *CDIO; /* Pointer for IORequest */ int cd_error; typedef struct { UBYTE pad0; UBYTE trackType; UBYTE trackNum; UBYTE pad1; ULONG startFrame; } TOCENTRY; typedef struct { UWORD length; UBYTE firstTrack; UBYTE lastTrack; TOCENTRY tocs[100]; } TOC; typedef struct { ULONG sectors; ULONG blocksize; } CAPACITY; unsigned char sensebuf[SENSELEN]; int DoSCSI (UBYTE * data, int datasize, UBYTE * cmd, int cmdsize, UBYTE flags); cdrom_interface::cdrom_interface(char *dev) { char buf[256]; sscanf(dev, "%s%s", amiga_cd_device, buf); amiga_cd_unit = atoi(buf); CDMP = CreateMsgPort(); if (CDMP != NULL) { CDIO = (struct IOExtTD *)CreateIORequest(CDMP, sizeof(struct IOExtTD)); if (CDIO != NULL) { cd_error = OpenDevice(amiga_cd_device, amiga_cd_unit, (struct IORequest *)CDIO, 0); if (cd_error != 0) BX_PANIC(("CD_Open: could not open device %s unit %d\n", amiga_cd_device, amiga_cd_unit)); } } } cdrom_interface::~cdrom_interface(void) { if (cd_error == 0) { CloseDevice((struct IORequest *)CDIO); } if (CDIO != NULL) { DeleteIORequest((struct IORequest *)CDIO); } if (CDMP != NULL) { DeleteMsgPort(CDMP); } } bx_bool cdrom_interface::insert_cdrom(char *dev) { Bit8u cdb[6]; Bit8u buf[2*BX_CD_FRAMESIZE]; Bit8u i = 0; memset(cdb,0,sizeof(cdb)); cdb[0] = SCSI_DA_START_STOP_UNIT; cdb[4] = 1 | 2; DoSCSI(0, 0,cdb,sizeof(cdb),SCSIF_READ); /*Check if there's a valid media present in the drive*/ CDIO->iotd_Req.io_Data = buf; CDIO->iotd_Req.io_Command = CMD_READ; CDIO->iotd_Req.io_Length = BX_CD_FRAMESIZE; CDIO->iotd_Req.io_Offset = BX_CD_FRAMESIZE; for(i = 0; i < 200; i++) /*it takes a while for the cdrom to validate*/ { DoIO((struct IORequest *)CDIO); if (CDIO->iotd_Req.io_Error == 0) break; Delay (10); } if (CDIO->iotd_Req.io_Error != 0) return false; else return true; } void cdrom_interface::eject_cdrom() { Bit8u cdb[6]; memset(cdb,0,sizeof(cdb)); cdb[0] = SCSI_DA_START_STOP_UNIT; cdb[4] = 0 | 2; DoSCSI(0, 0,cdb,sizeof(cdb),SCSIF_READ); } bx_bool cdrom_interface::read_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format) { Bit8u cdb[10]; TOC *toc; toc = (TOC*) buf; if (format != 0) return false; memset(cdb,0,sizeof(cdb)); cdb[0] = SCSI_CD_READ_TOC; if (msf) cdb[1] = 2; else cdb[1] = 0; cdb[6] = start_track; cdb[7] = sizeof(TOC)>>8; cdb[8] = sizeof(TOC)&0xFF; DoSCSI((UBYTE *)buf, sizeof(TOC), cdb, sizeof(cdb), SCSIF_READ); *length = toc->length + 4; return true; } Bit32u cdrom_interface::capacity() { CAPACITY cap; Bit8u cdb[10]; memset(cdb,0,sizeof(cdb)); cdb[0] = SCSI_DA_READ_CAPACITY; int err; if ((err = DoSCSI((UBYTE *)&cap, sizeof(cap), cdb, sizeof (cdb), (SCSIF_READ | SCSIF_AUTOSENSE))) == 0) return(cap.sectors); else BX_PANIC (("Couldn't get media capacity")); } bx_bool cdrom_interface::read_block(Bit8u* buf, int lba, int blocksize) { CDIO->iotd_Req.io_Data = buf; CDIO->iotd_Req.io_Command = CMD_READ; CDIO->iotd_Req.io_Length = BX_CD_FRAMESIZE; CDIO->iotd_Req.io_Offset = lba * BX_CD_FRAMESIZE; DoIO((struct IORequest *)CDIO); if (CDIO->iotd_Req.io_Error != 0) { BX_PANIC(("Error %d reading CD data sector: %ld", CDIO->iotd_Req.io_Error, lba)); return 0; } return 1; } bx_bool cdrom_interface::start_cdrom() { // Spin up the cdrom drive. if (fd >= 0) { BX_INFO(("start_cdrom: your OS is not supported yet.")); return 0; // OS not supported yet, return 0 always. } return 0; } int DoSCSI(UBYTE *data, int datasize, Bit8u *cmd,int cmdsize, UBYTE direction) { struct SCSICmd scmd; CDIO->iotd_Req.io_Command = HD_SCSICMD; CDIO->iotd_Req.io_Data = &scmd; CDIO->iotd_Req.io_Length = sizeof(scmd); scmd.scsi_Data = (UWORD *)data; scmd.scsi_Length = datasize; scmd.scsi_SenseActual = 0; scmd.scsi_SenseData = sensebuf; scmd.scsi_SenseLength = SENSELEN; scmd.scsi_Command = cmd; scmd.scsi_CmdLength = cmdsize; scmd.scsi_Flags = SCSIF_AUTOSENSE | direction; DoIO((struct IORequest *)CDIO); if (CDIO->iotd_Req.io_Error != 0) { BX_PANIC(("DoSCSI: error %d", CDIO->iotd_Req.io_Error)); } return CDIO->iotd_Req.io_Error; } bochs-2.6/iodev/hdimage/aspi-win32.h0000644000175000017500000002762412020641504017113 0ustar guillemguillem// // iodev/aspi-win32.h // $Id: aspi-win32.h 11315 2012-08-05 18:13:38Z vruppert $ // // This file was copied from cdrecord 1.9 under libscg/scg/aspi-win32.h. // The only modification is related to use of the PACKED keyword. // #ifndef __ASPI_WIN32_H_ #define __ASPI_WIN32_H_ #include #ifndef PACKED // It seems that VC++ has no PACKED keyword but Cygwin does. We can just // define PACKED to be empty if it's not already defined by the system // headers. #define PACKED /* empty */ #endif /*************************************************************************** ** SCSI MISCELLANEOUS EQUATES ***************************************************************************/ #define SENSE_LEN 14 /* Default sense buffer length */ #define SRB_DIR_SCSI 0x00 /* Direction determined by SCSI */ #define SRB_POSTING 0x01 /* Enable ASPI posting */ #define SRB_ENABLE_RESIDUAL_COUNT 0x04 /* Enable residual byte count */ /* reporting */ #define SRB_DIR_IN 0x08 /* Transfer from SCSI target to */ /* host */ #define SRB_DIR_OUT 0x10 /* Transfer from host to SCSI */ /* target */ #define SRB_EVENT_NOTIFY 0x40 /* Enable ASPI event notification */ #define RESIDUAL_COUNT_SUPPORTED 0x02 /* Extended buffer flag */ #define MAX_SRB_TIMEOUT 1080001u /* 30 hour maximum timeout in sec */ #define DEFAULT_SRB_TIMEOUT 1080001u /* use max.timeout by default */ /*************************************************************************** ** ASPI command definitions ***************************************************************************/ #define SC_HA_INQUIRY 0x00 /* Host adapter inquiry */ #define SC_GET_DEV_TYPE 0x01 /* Get device type */ #define SC_EXEC_SCSI_CMD 0x02 /* Execute SCSI command */ #define SC_ABORT_SRB 0x03 /* Abort an SRB */ #define SC_RESET_DEV 0x04 /* SCSI bus device reset */ #define SC_SET_HA_PARMS 0x05 /* Set HA parameters */ #define SC_GET_DISK_INFO 0x06 /* Get Disk */ #define SC_RESCAN_SCSI_BUS 0x07 /* Rebuild SCSI device map */ #define SC_GETSET_TIMEOUTS 0x08 /* Get/Set target timeouts */ /*************************************************************************** ** SRB Status ***************************************************************************/ #define SS_PENDING 0x00 /* SRB being processed */ #define SS_COMP 0x01 /* SRB completed without error */ #define SS_ABORTED 0x02 /* SRB aborted */ #define SS_ABORT_FAIL 0x03 /* Unable to abort SRB */ #define SS_ERR 0x04 /* SRB completed with error */ #define SS_INVALID_CMD 0x80 /* Invalid ASPI command */ #define SS_INVALID_HA 0x81 /* Invalid host adapter number */ #define SS_NO_DEVICE 0x82 /* SCSI device not installed */ #define SS_INVALID_SRB 0xE0 /* Invalid parameter set in SRB */ #define SS_OLD_MANAGER 0xE1 /* ASPI manager doesn't support */ /* windows */ #define SS_BUFFER_ALIGN 0xE1 /* Buffer not aligned (replaces */ /* SS_OLD_MANAGER in Win32) */ #define SS_ILLEGAL_MODE 0xE2 /* Unsupported Windows mode */ #define SS_NO_ASPI 0xE3 /* No ASPI managers */ #define SS_FAILED_INIT 0xE4 /* ASPI for windows failed init */ #define SS_ASPI_IS_BUSY 0xE5 /* No resources available to */ /* execute command */ #define SS_BUFFER_TO_BIG 0xE6 /* Buffer size too big to handle */ #define SS_BUFFER_TOO_BIG 0xE6 /* Correct spelling of 'too' */ #define SS_MISMATCHED_COMPONENTS 0xE7 /* The DLLs/EXEs of ASPI don't */ /* version check */ #define SS_NO_ADAPTERS 0xE8 /* No host adapters to manager */ #define SS_INSUFFICIENT_RESOURCES 0xE9 /* Couldn't allocate resources */ /* needed to init */ #define SS_ASPI_IS_SHUTDOWN 0xEA /* Call came to ASPI after */ /* PROCESS_DETACH */ #define SS_BAD_INSTALL 0xEB /* The DLL or other components */ /* are installed wrong */ /*************************************************************************** ** Host Adapter Status ***************************************************************************/ #define HASTAT_OK 0x00 /* No error detected by HA */ #define HASTAT_SEL_TO 0x11 /* Selection Timeout */ #define HASTAT_DO_DU 0x12 /* Data overrun/data underrun */ #define HASTAT_BUS_FREE 0x13 /* Unexpected bus free */ #define HASTAT_PHASE_ERR 0x14 /* Target bus phase sequence */ #define HASTAT_TIMEOUT 0x09 /* Timed out while SRB was */ /* waiting to be processed */ #define HASTAT_COMMAND_TIMEOUT 0x0B /* Adapter timed out while */ /* processing SRB */ #define HASTAT_MESSAGE_REJECT 0x0D /* While processing the SRB, the */ /* adapter received a MESSAGE */ #define HASTAT_BUS_RESET 0x0E /* A bus reset was detected */ #define HASTAT_PARITY_ERROR 0x0F /* A parity error was detected */ #define HASTAT_REQUEST_SENSE_FAILED 0x10 /* The adapter failed in issuing */ /*************************************************************************** ** SRB - HOST ADAPTER INQUIRIY - SC_HA_INQUIRY (0) ***************************************************************************/ typedef struct { BYTE SRB_Cmd; /* 00/000 ASPI command code == SC_HA_INQUIRY */ BYTE SRB_Status; /* 01/001 ASPI command status byte */ BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ BYTE SRB_Flags; /* 03/003 ASPI request flags */ DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ BYTE HA_Count; /* 08/008 Number of host adapters present */ BYTE HA_SCSI_ID; /* 09/009 SCSI ID of host adapter */ BYTE HA_ManagerId[16]; /* 0a/010 String describing the manager */ BYTE HA_Identifier[16]; /* 1a/026 String describing the host adapter */ BYTE HA_Unique[16]; /* 2a/042 Host Adapter Unique parameters */ WORD HA_Rsvd1; /* 3a/058 Reserved, must = 0 */ } PACKED SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry; /*************************************************************************** ** SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1) ***************************************************************************/ typedef struct { BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_GET_DEV_TYPE */ BYTE SRB_Status; /* 01/001 ASPI command status byte */ BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ BYTE SRB_Target; /* 08/008 Target's SCSI ID */ BYTE SRB_Lun; /* 09/009 Target's LUN number */ BYTE SRB_DeviceType; /* 0a/010 Target's peripheral device type */ BYTE SRB_Rsvd1; /* 0b/011 Reserved, must = 0 */ } PACKED SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock; /*************************************************************************** ** SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2) ***************************************************************************/ typedef struct { BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_EXEC_SCSI_CMD */ BYTE SRB_Status; /* 01/001 ASPI command status byte */ BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ BYTE SRB_Target; /* 08/008 Target's SCSI ID */ BYTE SRB_Lun; /* 09/009 Target's LUN */ WORD SRB_Rsvd1; /* 0a/010 Reserved for alignment */ DWORD SRB_BufLen; /* 0c/012 Data Allocation Length */ BYTE FAR *SRB_BufPointer; /* 10/016 Data Buffer Pointer */ BYTE SRB_SenseLen; /* 14/020 Sense Allocation Length */ BYTE SRB_CDBLen; /* 15/021 CDB Length */ BYTE SRB_HaStat; /* 16/022 Host Adapter Status */ BYTE SRB_TargStat; /* 17/023 Target Status */ VOID FAR *SRB_PostProc; /* 18/024 Post routine */ BYTE SRB_Rsvd2[20]; /* 1c/028 Reserved, must = 0 */ BYTE CDBByte[16]; /* 30/048 SCSI CDB */ BYTE SenseArea[SENSE_LEN+2]; /* 40/064 Request Sense buffer */ } PACKED SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd; typedef struct { BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_ABORT_SRB */ BYTE SRB_Status; /* 01/001 ASPI command status byte */ BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */ DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */ void *SRB_ToAbort; /* 08/008 Pointer to SRB to abort */ } PACKED SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort; /*************************************************************************** ** SRB - BUS DEVICE RESET - SC_RESET_DEV (4) ***************************************************************************/ typedef struct { BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_RESET_DEV */ BYTE SRB_Status; /* 01/001 ASPI command status byte */ BYTE SRB_HaId; /* 02/002 ASPI host adapter number */ DWORD SRB_Flags; /* 04/004 Reserved */ BYTE SRB_Target; /* 08/008 Target's SCSI ID */ BYTE SRB_Lun; /* 09/009 Target's LUN number */ BYTE SRB_Rsvd1[12]; /* 0A/010 Reserved for alignment */ BYTE SRB_HaStat; /* 16/022 Host Adapter Status */ BYTE SRB_TargStat; /* 17/023 Target Status */ VOID FAR *SRB_PostProc; /* 18/024 Post routine */ BYTE SRB_Rsvd2[36]; /* 1C/028 Reserved, must = 0 */ } SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset; typedef struct tag_ASPI32BUFF { PBYTE AB_BufPointer; DWORD AB_BufLen; DWORD AB_ZeroFill; DWORD AB_Reserved; } PACKED ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF; typedef struct { BYTE SRB_Cmd; BYTE SRB_Status; BYTE SRB_HaId; BYTE SRB_Flags; DWORD SRB_Hdr_Rsvd; } SRB, *PSRB, FAR *LPSRB; #endif bochs-2.6/iodev/hdimage/vmware3.cc0000644000175000017500000004011712020641504016731 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vmware3.cc 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// /* * This file provides support for VMWare's virtual disk image * format version 3. * * Author: Sharvil Nanavati, for Net Integration Technologies, Inc. * Contact: snrrrub@yahoo.com * * Copyright (C) 2003 Net Integration Technologies, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "hdimage.h" #include "vmware3.h" const off_t vmware3_image_t::INVALID_OFFSET=(off_t)-1; #define LOG_THIS bx_devices.pluginHDImageCtl-> #define DTOH32_HEADER(field) (header.field = (dtoh32(header.field))) #define HTOD32_HEADER(field) (header.field = (htod32(header.field))) int vmware3_image_t::read_header(int fd, COW_Header & header) { int res; if((res = ::read(fd, &header, sizeof(COW_Header))) < 0) return res; DTOH32_HEADER(header_version); DTOH32_HEADER(flags); DTOH32_HEADER(total_sectors); DTOH32_HEADER(tlb_size_sectors); DTOH32_HEADER(flb_offset_sectors); DTOH32_HEADER(flb_count); DTOH32_HEADER(next_sector_to_allocate); DTOH32_HEADER(cylinders); DTOH32_HEADER(heads); DTOH32_HEADER(sectors); DTOH32_HEADER(last_modified_time); DTOH32_HEADER(last_modified_time_save); DTOH32_HEADER(chain_id); DTOH32_HEADER(number_of_chains); DTOH32_HEADER(cylinders_in_disk); DTOH32_HEADER(heads_in_disk); DTOH32_HEADER(sectors_in_disk); DTOH32_HEADER(total_sectors_in_disk); DTOH32_HEADER(vmware_version); return res; } int vmware3_image_t::write_header(int fd, COW_Header & hostHeader) { COW_Header header; memcpy(&header, &hostHeader, sizeof(COW_Header)); HTOD32_HEADER(header_version); HTOD32_HEADER(flags); HTOD32_HEADER(total_sectors); HTOD32_HEADER(tlb_size_sectors); HTOD32_HEADER(flb_offset_sectors); HTOD32_HEADER(flb_count); HTOD32_HEADER(next_sector_to_allocate); HTOD32_HEADER(cylinders); HTOD32_HEADER(heads); HTOD32_HEADER(sectors); HTOD32_HEADER(last_modified_time); HTOD32_HEADER(last_modified_time_save); HTOD32_HEADER(chain_id); HTOD32_HEADER(number_of_chains); HTOD32_HEADER(cylinders_in_disk); HTOD32_HEADER(heads_in_disk); HTOD32_HEADER(sectors_in_disk); HTOD32_HEADER(total_sectors_in_disk); HTOD32_HEADER(vmware_version); return ::write(fd, &header, sizeof(COW_Header)); } #undef DTOH32_HEADER #undef HTOD32_HEADER int vmware3_image_t::read_ints(int fd, Bit32u *buffer, size_t count) { size_t i; Bit32u *p; int res=::read(fd, (void*)buffer, count * 4); for (p = buffer, i=0; ifd = ::open(filename, flags); if(current->fd < 0) BX_PANIC(("unable to open vmware3 COW Disk file '%s'", filename)); if(read_header(current->fd, current->header) < 0) BX_PANIC(("unable to read header or invalid header in vmware3 COW Disk file '%s'", filename)); if(!is_valid_header(current->header)) BX_PANIC(("invalid vmware3 COW Disk file '%s'", filename)); current->flb = new unsigned [current->header.flb_count]; if(current->flb == 0) BX_PANIC(("cannot allocate %d bytes for flb in vmware3 COW Disk '%s'", current->header.flb_count * 4, filename)); current->slb = new unsigned * [current->header.flb_count]; if(current->slb == 0) BX_PANIC(("cannot allocate %d bytes for slb in vmware3 COW Disk '%s'", current->header.flb_count * 4, filename)); unsigned j; for(j = 0; j < current->header.flb_count; ++j) { current->slb[j] = new unsigned [slb_count]; if(current->slb[j] == 0) BX_PANIC(("cannot allocate %d bytes for slb[] in vmware3 COW Disk '%s'", slb_count * 4, filename)); } current->tlb = new Bit8u [tlb_size]; if(current->tlb == 0) BX_PANIC(("cannot allocate %d bytes for tlb in vmware3 COW Disk '%s'", tlb_size, filename)); if(::lseek(current->fd, current->header.flb_offset_sectors * 512, SEEK_SET) < 0) BX_PANIC(("unable to seek vmware3 COW Disk file '%s'", filename)); if(read_ints(current->fd, current->flb, current->header.flb_count) < 0) BX_PANIC(("unable to read flb from vmware3 COW Disk file '%s'", filename)); for(j = 0; j < current->header.flb_count; ++j) if(current->flb[j] != 0) { if(::lseek(current->fd, current->flb[j] * 512, SEEK_SET) < 0) BX_PANIC(("unable to seek vmware3 COW Disk file '%s'", filename)); if(read_ints(current->fd, current->slb[j], slb_count) < 0) BX_PANIC(("unable to read slb from vmware3 COW Disk file '%s'", filename)); } current->min_offset = offset; offset += current->header.total_sectors * 512; current->max_offset = offset; current->offset = INVALID_OFFSET; current->synced = true; delete[] filename; } current = &images[0]; requested_offset = 0; if (header.total_sectors_in_disk!=0) { cylinders = header.cylinders_in_disk; heads = header.heads_in_disk; spt = header.sectors_in_disk; hd_size = header.total_sectors_in_disk * 512; } else { cylinders = header.cylinders; heads = header.heads; spt = header.sectors; hd_size = header.total_sectors * 512; } return 1; } off_t vmware3_image_t::perform_seek() { if(requested_offset < current->min_offset || requested_offset >= current->max_offset) { if(!sync()) { BX_DEBUG(("could not sync before switching vmware3 COW files")); return INVALID_OFFSET; } while(requested_offset < current->min_offset) current = &images[current->header.chain_id - 1]; while(requested_offset >= current->max_offset) current = &images[current->header.chain_id + 1]; } if(current->offset != INVALID_OFFSET && requested_offset >= current->offset && requested_offset < current->offset + tlb_size) return (requested_offset - current->offset); if(!sync()) { BX_DEBUG(("could not sync before seeking vmware3 COW file")); return INVALID_OFFSET; } unsigned relative_offset = (unsigned)(requested_offset - current->min_offset); unsigned i = relative_offset >> FL_SHIFT; unsigned j = (relative_offset & ~FL_MASK) / tlb_size; if(current->slb[i][j]) { if(::lseek(current->fd, current->slb[i][j] * 512, SEEK_SET) < 0) { BX_DEBUG(("could not seek vmware3 COW to sector slb[%d][%d]", i, j)); return INVALID_OFFSET; } if(::read(current->fd, current->tlb, tlb_size) < 0) { BX_DEBUG(("could not read %d bytes from vmware3 COW image", tlb_size)); return INVALID_OFFSET; } } else memset(current->tlb, 0, tlb_size); current->offset = (requested_offset / tlb_size) * tlb_size; return (requested_offset - current->offset); } ssize_t vmware3_image_t::read(void * buf, size_t count) { ssize_t total = 0; while(count > 0) { off_t offset = perform_seek(); if(offset == INVALID_OFFSET) { BX_DEBUG(("vmware3 COW read failed on %u bytes", (unsigned)count)); return -1; } unsigned bytes_remaining = (unsigned)(tlb_size - offset); unsigned amount = (bytes_remaining > count) ? count : bytes_remaining; memcpy(buf, current->tlb + offset, amount); requested_offset += amount; total += amount; count -= amount; } return total; } /* This could be done much better, I'm sure. In fact, the whole header doesn't * need to be re-written each time a new tlb is allocated nor does the whole * slb need to be re-written (most of the time) but that can be changed whenever * it becomes an issue... image I/O is not a bottleneck. */ bool vmware3_image_t::sync() { if(current->synced) return true; unsigned relative_offset = (unsigned)(current->offset - current->min_offset); unsigned i = relative_offset >> FL_SHIFT; unsigned j = (relative_offset & ~FL_MASK) / tlb_size; if (current->slb[i][j] == 0) { if (current->flb[i] == 0) { unsigned slb_size = slb_count * 4; /* Re-write the FLB */ current->flb[i] = current->header.next_sector_to_allocate; if(::lseek(current->fd, current->header.flb_offset_sectors * 512, SEEK_SET) < 0) { BX_DEBUG(("could not seek vmware3 COW image to flb on sync")); return false; } if(write_ints(current->fd, current->flb, current->header.flb_count) < 0) { BX_DEBUG(("could not re-write flb to vmware3 COW image on sync")); return false; } current->header.next_sector_to_allocate += (slb_size / 512) + ((slb_size % 512) ? 1 : 0); } /* Re-write the SLB */ current->slb[i][j] = current->header.next_sector_to_allocate; if(::lseek(current->fd, current->flb[i] * 512, SEEK_SET) < 0) { BX_DEBUG(("could not seek vmware3 COW image to slb on sync")); return false; } if(write_ints(current->fd, current->slb[i], slb_count) < 0) { BX_DEBUG(("could not re-write slb to vmware3 COW image on sync")); return false; } current->header.next_sector_to_allocate += current->header.tlb_size_sectors; /* Update the header */ if(::lseek(current->fd, 0, SEEK_SET) < 0) { BX_DEBUG(("could not seek to vmware3 COW image to offset 0 on sync")); return false; } if(write_header(current->fd, current->header) < 0) { BX_DEBUG(("could not re-write header to vmware3 COW image on sync")); return false; } } if(::lseek(current->fd, current->slb[i][j] * 512, SEEK_SET) < 0) { BX_DEBUG(("could not seek vmware3 COW image to offset %d on sync", current->slb[i][j] * 512)); return false; } if(::write(current->fd, current->tlb, tlb_size) < 0) { BX_DEBUG(("could not write tlb to vmware3 COW image on sync")); return false; } current->synced = true; return true; } ssize_t vmware3_image_t::write(const void * buf, size_t count) { ssize_t total = 0; while(count > 0) { off_t offset = perform_seek(); if(offset == INVALID_OFFSET) return -1; unsigned bytes_remaining = (unsigned)(tlb_size - offset); unsigned amount = 0; current->synced = false; if(bytes_remaining > count) { memcpy(current->tlb + offset, buf, count); amount = count; } else { memcpy(current->tlb + offset, buf, bytes_remaining); if(!sync()) { BX_DEBUG(("failed to sync when writing %u bytes", (unsigned)count)); return -1; } amount = bytes_remaining; } requested_offset += amount; total += amount; count -= amount; } return total; } Bit64s vmware3_image_t::lseek(Bit64s offset, int whence) { if(whence == SEEK_SET) requested_offset = (off_t)offset; else if (whence == SEEK_CUR) requested_offset += (off_t)offset; else if (whence == SEEK_END) requested_offset = (off_t)(current->header.total_sectors_in_disk * 512) + (off_t)offset; else { BX_DEBUG(("unknown 'whence' value (%d) when trying to seek vmware3 COW image", whence)); return -1; } return requested_offset; } void vmware3_image_t::close() { if(current == 0) return; unsigned count = current->header.number_of_chains; if (count < 1) count = 1; for(unsigned i = 0; i < count; ++i) { if (images != NULL) { current = &images[i]; for(unsigned j = 0; j < current->header.flb_count; ++j) delete[] current->slb[j]; delete[] current->flb; delete[] current->slb; delete[] current->tlb; ::close(current->fd); delete[] images; images = NULL; } } current = 0; } Bit32u vmware3_image_t::get_capabilities(void) { return HDIMAGE_HAS_GEOMETRY; } bochs-2.6/iodev/hdimage/cdrom.h0000644000175000017500000000520612020641504016313 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cdrom.h 11315 2012-08-05 18:13:38Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Header file for low-level OS specific CDROM emulation class cdrom_base_c : public logfunctions { public: virtual ~cdrom_base_c(void) {} // Load CD-ROM. Returns 0 if CD is not ready. virtual bx_bool insert_cdrom(const char *dev = NULL) = 0; // Logically eject the CD. virtual void eject_cdrom() = 0; // Read CD TOC. Returns 0 if start track is out of bounds. virtual bx_bool read_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format) = 0; // Return CD-ROM capacity (in 2048 byte frames) virtual Bit32u capacity() = 0; // Read a single block from the CD. Returns 0 on failure. virtual bx_bool read_block(Bit8u* buf, Bit32u lba, int blocksize) BX_CPP_AttrRegparmN(3) = 0; // Start (spin up) the CD. virtual bx_bool start_cdrom() = 0; // Seek for new block address. virtual bx_bool seek(Bit32u lba) = 0; // Create CD TOC from image. Called from read_toc(). virtual bx_bool create_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format) = 0; }; class cdrom_interface : public cdrom_base_c { public: cdrom_interface(const char *dev); virtual ~cdrom_interface(void); bx_bool insert_cdrom(const char *dev = NULL); void eject_cdrom(); bx_bool read_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format); Bit32u capacity(); bx_bool read_block(Bit8u* buf, Bit32u lba, int blocksize) BX_CPP_AttrRegparmN(3); bx_bool start_cdrom(); bx_bool seek(Bit32u lba); bx_bool create_toc(Bit8u* buf, int* length, bx_bool msf, int start_track, int format); private: int fd; char *path; int using_file; #ifdef WIN32 BOOL bUseASPI; HANDLE hFile; int hid; int tid; int lun; #endif }; bochs-2.6/iodev/hdimage/vvfat.cc0000644000175000017500000016605312020641504016503 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vvfat.cc 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Virtual VFAT image support (shadows a local directory) // ported from QEMU block driver with some additions (see below) // // Copyright (c) 2004,2005 Johannes E. Schindelin // Copyright (C) 2010-2012 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. // ///////////////////////////////////////////////////////////////////////// // ADDITIONS: // - win32 specific directory functions (required for MSVC) // - configurable disk geometry // - read MBR and boot sector from file // - FAT32 support // - volatile runtime write support using the hdimage redolog_t class // - ask user on Bochs exit if directory and file changes should be committed // - save and restore FAT file attributes using a separate file // - set file modification date and time after committing file changes // - vvfat floppy support (1.44 MB media only) // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #ifndef WIN32 #include #include #endif #include "iodev.h" #include "hdimage.h" #include "vvfat.h" #define LOG_THIS bx_devices.pluginHDImageCtl-> #define VVFAT_MBR "vvfat_mbr.bin" #define VVFAT_BOOT "vvfat_boot.bin" #define VVFAT_ATTR "vvfat_attr.cfg" #if defined (BX_LITTLE_ENDIAN) #define htod16(val) (val) #else #define htod16(val) ( (((val)&0xff00)>>8) | (((val)&0xff)<<8) ) #endif #define dtoh16 htod16 #ifndef F_OK #define F_OK 0 #endif // portable mkdir / rmdir static int bx_mkdir(const char *path) { #ifndef WIN32 return mkdir(path, 0755); #else return (CreateDirectory(path, NULL) != 0) ? 0 : -1; #endif } static int bx_rmdir(const char *path) { #ifndef WIN32 return rmdir(path); #else return (RemoveDirectory(path) != 0) ? 0 : -1; #endif } // dynamic array functions static inline void array_init(array_t* array,unsigned int item_size) { array->pointer = NULL; array->size = 0; array->next = 0; array->item_size = item_size; } static inline void array_free(array_t* array) { if (array->pointer) free(array->pointer); array->size=array->next = 0; } // does not automatically grow static inline void* array_get(array_t* array,unsigned int index) { assert(index < array->next); return array->pointer + index * array->item_size; } static inline int array_ensure_allocated(array_t* array, int index) { if ((index + 1) * array->item_size > array->size) { int new_size = (index + 32) * array->item_size; array->pointer = (char*)realloc(array->pointer, new_size); if (!array->pointer) return -1; memset(array->pointer + array->size, 0, new_size - array->size); array->size = new_size; array->next = index + 1; } return 0; } static inline void* array_get_next(array_t* array) { unsigned int next = array->next; void* result; if (array_ensure_allocated(array, next) < 0) return NULL; array->next = next + 1; result = array_get(array, next); return result; } static inline void* array_insert(array_t* array,unsigned int index,unsigned int count) { if ((array->next+count)*array->item_size > array->size) { int increment = count*array->item_size; array->pointer = (char*)realloc(array->pointer, array->size+increment); if (!array->pointer) return NULL; array->size += increment; } memmove(array->pointer+(index+count)*array->item_size, array->pointer+index*array->item_size, (array->next-index)*array->item_size); array->next += count; return array->pointer+index*array->item_size; } /* this performs a "roll", so that the element which was at index_from becomes * index_to, but the order of all other elements is preserved. */ static inline int array_roll(array_t* array, int index_to, int index_from, int count) { char* buf; char* from; char* to; int is; if (!array || (index_to < 0) || (index_to >= (int)array->next) || (index_from < 0 || (index_from >= (int)array->next))) return -1; if (index_to == index_from) return 0; is = array->item_size; from = array->pointer+index_from*is; to = array->pointer+index_to*is; buf = (char*)malloc(is*count); memcpy(buf, from, is*count); if (index_to < index_from) memmove(to+is*count, to, from-to); else memmove(from, from+is*count, to-from); memcpy(to, buf, is*count); free(buf); return 0; } #if 0 static inline int array_remove_slice(array_t* array,int index, int count) { assert(index >=0); assert(count > 0); assert(index + count <= (int)array->next); if (array_roll(array,array->next-1,index,count)) return -1; array->next -= count; return 0; } static int array_remove(array_t* array,int index) { return array_remove_slice(array, index, 1); } // return the index for a given member static int array_index(array_t* array, void* pointer) { size_t offset = (char*)pointer - array->pointer; assert((offset % array->item_size) == 0); assert(offset/array->item_size < array->next); return offset/array->item_size; } #endif #if defined(_MSC_VER) #pragma pack(push, 1) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=packed #endif typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct bootsector_t { Bit8u jump[3]; Bit8u name[8]; Bit16u sector_size; Bit8u sectors_per_cluster; Bit16u reserved_sectors; Bit8u number_of_fats; Bit16u root_entries; Bit16u total_sectors16; Bit8u media_type; Bit16u sectors_per_fat; Bit16u sectors_per_track; Bit16u number_of_heads; Bit32u hidden_sectors; Bit32u total_sectors; union { #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct { Bit8u drive_number; Bit8u reserved; Bit8u signature; Bit32u id; Bit8u volume_label[11]; Bit8u fat_type[8]; Bit8u ignored[0x1c0]; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif fat16; #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct { Bit32u sectors_per_fat; Bit16u flags; Bit8u major, minor; Bit32u first_cluster_of_root_dir; Bit16u info_sector; Bit16u backup_boot_sector; Bit8u reserved1[12]; Bit8u drive_number; Bit8u reserved2; Bit8u signature; Bit32u id; Bit8u volume_label[11]; Bit8u fat_type[8]; Bit8u ignored[0x1a4]; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif fat32; } u; Bit8u magic[2]; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif bootsector_t; typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct partition_t { Bit8u attributes; /* 0x80 = bootable */ mbr_chs_t start_CHS; Bit8u fs_type; /* 0x1 = FAT12, 0x6 = FAT16, 0xe = FAT16_LBA, 0xb = FAT32, 0xc = FAT32_LBA */ mbr_chs_t end_CHS; Bit32u start_sector_long; Bit32u length_sector_long; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif partition_t; typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct mbr_t { Bit8u ignored[0x1b8]; Bit32u nt_id; Bit8u ignored2[2]; partition_t partition[4]; Bit8u magic[2]; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif mbr_t; typedef #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif struct infosector_t { Bit32u signature1; Bit8u ignored[0x1e0]; Bit32u signature2; Bit32u free_clusters; Bit32u mra_cluster; // most recently allocated cluster Bit8u reserved[14]; Bit8u magic[2]; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif infosector_t; #if defined(_MSC_VER) #pragma pack(pop) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=reset #endif vvfat_image_t::vvfat_image_t(Bit64u size, const char* _redolog_name) { first_sectors = new Bit8u[0xc000]; memset(&first_sectors[0], 0, 0xc000); hd_size = size; redolog = new redolog_t(); redolog_temp = NULL; redolog_name = NULL; if (_redolog_name != NULL) { if (strcmp(_redolog_name,"") != 0) { redolog_name = strdup(_redolog_name); } } } vvfat_image_t::~vvfat_image_t() { delete [] first_sectors; delete redolog; } bx_bool vvfat_image_t::sector2CHS(Bit32u spos, mbr_chs_t *chs) { Bit32u head, sector; sector = spos % spt; spos /= spt; head = spos % heads; spos /= heads; if (spos > 1023) { /* Overflow, it happens if 32bit sector positions are used, while CHS is only 24bit. Windows/Dos is said to take 1023/255/63 as nonrepresentable CHS */ chs->head = 0xff; chs->sector = 0xff; chs->cylinder = 0xff; return 1; } chs->head = (Bit8u)head; chs->sector = (Bit8u)((sector+1) | ((spos >> 8) << 6)); chs->cylinder = (Bit8u)spos; return 0; } void vvfat_image_t::init_mbr(void) { mbr_t* real_mbr = (mbr_t*)first_sectors; partition_t* partition = &(real_mbr->partition[0]); bx_bool lba; // Win NT Disk Signature real_mbr->nt_id = htod32(0xbe1afdfa); partition->attributes = 0x80; // bootable // LBA is used when partition is outside the CHS geometry lba = sector2CHS(offset_to_bootsector, &partition->start_CHS); lba |= sector2CHS(sector_count - 1, &partition->end_CHS); // LBA partitions are identified only by start/length_sector_long not by CHS partition->start_sector_long = htod32(offset_to_bootsector); partition->length_sector_long = htod32(sector_count - offset_to_bootsector); /* FAT12/FAT16/FAT32 */ /* DOS uses different types when partition is LBA, probably to prevent older versions from using CHS on them */ partition->fs_type = fat_type==12 ? 0x1: fat_type==16 ? (lba?0xe:0x06): /*fat_tyoe==32*/ (lba?0xc:0x0b); real_mbr->magic[0] = 0x55; real_mbr->magic[1] = 0xaa; } // dest is assumed to hold 258 bytes, and pads with 0xffff up to next multiple of 26 static inline int short2long_name(char* dest,const char* src) { int i; int len; for (i = 0; (i < 129) && src[i]; i++) { dest[2*i] = src[i]; dest[2*i+1] = 0; } len = 2 * i; dest[2*i] = dest[2*i+1] = 0; for (i = 2 * i + 2; (i % 26); i++) dest[i] = (char)0xff; return len; } direntry_t* vvfat_image_t::create_long_filename(const char* filename) { char buffer[258]; int length = short2long_name(buffer, filename), number_of_entries = (length+25) / 26, i; direntry_t* entry; for (i = 0; i < number_of_entries; i++) { entry = (direntry_t*)array_get_next(&directory); entry->attributes = 0xf; entry->reserved[0] = 0; entry->begin = 0; entry->name[0] = (number_of_entries - i) | (i==0 ? 0x40:0); } for (i = 0; i < 26 * number_of_entries; i++) { int offset = (i % 26); if (offset < 10) offset = 1 + offset; else if (offset < 22) offset = 14 + offset - 10; else offset = 28 + offset - 22; entry = (direntry_t*)array_get(&directory, directory.next - 1 - (i / 26)); entry->name[offset] = buffer[i]; } return (direntry_t*)array_get(&directory, directory.next-number_of_entries); } static char is_long_name(const direntry_t* direntry) { return direntry->attributes == 0xf; } static void set_begin_of_direntry(direntry_t* direntry, Bit32u begin) { direntry->begin = htod16(begin & 0xffff); direntry->begin_hi = htod16((begin >> 16) & 0xffff); } static inline Bit8u fat_chksum(const direntry_t* entry) { Bit8u chksum = 0; int i; for (i = 0; i < 11; i++) { unsigned char c; c = (i < 8) ? entry->name[i] : entry->extension[i-8]; chksum = (((chksum & 0xfe) >> 1) | ((chksum & 0x01) ? 0x80:0)) + c; } return chksum; } // if return_time==0, this returns the fat_date, else the fat_time #ifndef WIN32 Bit16u fat_datetime(time_t time, int return_time) { struct tm* t; struct tm t1; t = &t1; localtime_r(&time, t); if (return_time) return htod16((t->tm_sec/2) | (t->tm_min<<5) | (t->tm_hour<<11)); return htod16((t->tm_mday) | ((t->tm_mon+1)<<5) | ((t->tm_year-80)<<9)); } #else Bit16u fat_datetime(FILETIME time, int return_time) { FILETIME localtime; SYSTEMTIME systime; FileTimeToLocalFileTime(&time, &localtime); FileTimeToSystemTime(&localtime, &systime); if (return_time) return htod16((systime.wSecond/2) | (systime.wMinute<<5) | (systime.wHour<<11)); return htod16((systime.wDay) | (systime.wMonth<<5) | ((systime.wYear-1980)<<9)); } #endif void vvfat_image_t::fat_set(unsigned int cluster, Bit32u value) { if (fat_type == 32) { Bit32u* entry = (Bit32u*)array_get(&fat, cluster); *entry = htod32(value); } else if (fat_type == 16) { Bit16u* entry = (Bit16u*)array_get(&fat, cluster); *entry = htod16(value & 0xffff); } else { int offset = (cluster * 3 / 2); Bit8u* p = (Bit8u*)array_get(&fat, offset); switch (cluster & 1) { case 0: p[0] = value & 0xff; p[1] = (p[1] & 0xf0) | ((value>>8) & 0xf); break; case 1: p[0] = (p[0]&0xf) | ((value&0xf)<<4); p[1] = (value>>4); break; } } } void vvfat_image_t::init_fat(void) { if (fat_type == 12) { array_init(&fat, 1); array_ensure_allocated(&fat, sectors_per_fat * 0x200 * 3 / 2 - 1); } else { array_init(&fat, (fat_type==32) ? 4:2); array_ensure_allocated(&fat, sectors_per_fat * 0x200 / fat.item_size - 1); } memset(fat.pointer, 0, fat.size); switch (fat_type) { case 12: max_fat_value = 0xfff; break; case 16: max_fat_value = 0xffff; break; case 32: max_fat_value = 0x0fffffff; break; default: max_fat_value = 0; /* error... */ } } direntry_t* vvfat_image_t::create_short_and_long_name( unsigned int directory_start, const char* filename, int is_dot) { int i, j, long_index = directory.next; direntry_t* entry = NULL; direntry_t* entry_long = NULL; if (is_dot) { entry = (direntry_t*)array_get_next(&directory); memset(entry->name,0x20,11); memcpy(entry->name,filename,strlen(filename)); return entry; } entry_long = create_long_filename(filename); i = strlen(filename); for (j = i - 1; j>0 && filename[j]!='.';j--); if (j > 0) i = (j > 8 ? 8 : j); else if (i > 8) i = 8; entry = (direntry_t*)array_get_next(&directory); memset(entry->name, 0x20, 11); memcpy(entry->name, filename, i); if (j > 0) for (i = 0; i < 3 && filename[j+1+i]; i++) entry->extension[i] = filename[j+1+i]; // upcase & remove unwanted characters for (i=10;i>=0;i--) { if (i==10 || i==7) for (;i>0 && entry->name[i]==' ';i--); if (entry->name[i]<=' ' || entry->name[i]>0x7f || strchr(".*?<>|\":/\\[];,+='",entry->name[i])) entry->name[i]='_'; else if (entry->name[i]>='a' && entry->name[i]<='z') entry->name[i]+='A'-'a'; } if (entry->name[0] == 0xe5) entry->name[0] = 0x05; // mangle duplicates while (1) { direntry_t* entry1 = (direntry_t*)array_get(&directory, directory_start); int j; for (;entry1name,entry->name,11)) break; // found dupe if (entry1==entry) // no dupe found break; // use all 8 characters of name if (entry->name[7]==' ') { int j; for(j=6;j>0 && entry->name[j]==' ';j--) entry->name[j]='~'; } // increment number for (j=7;j>0 && entry->name[j]=='9';j--) entry->name[j]='0'; if (j > 0) { if (entry->name[j]<'0' || entry->name[j]>'9') entry->name[j]='0'; else entry->name[j]++; } } // calculate checksum; propagate to long name if (entry_long) { Bit8u chksum = fat_chksum(entry); // calculate anew, because realloc could have taken place entry_long = (direntry_t*)array_get(&directory, long_index); while (entry_longreserved[1]=chksum; entry_long++; } } return entry; } /* * Read a directory. (the index of the corresponding mapping must be passed). */ int vvfat_image_t::read_directory(int mapping_index) { mapping_t* mapping = (mapping_t*)array_get(&this->mapping, mapping_index); direntry_t* direntry; const char* dirname = mapping->path; Bit32u first_cluster = mapping->begin; int parent_index = mapping->info.dir.parent_mapping_index; mapping_t* parent_mapping = (mapping_t*) (parent_index >= 0 ? array_get(&this->mapping, parent_index) : NULL); int first_cluster_of_parent = parent_mapping ? (int)parent_mapping->begin : -1; int count = 0; #ifndef WIN32 DIR* dir = opendir(dirname); struct dirent* entry; int i; assert(mapping->mode & MODE_DIRECTORY); if (!dir) { mapping->end = mapping->begin; return -1; } i = mapping->info.dir.first_dir_index = first_cluster == first_cluster_of_root_dir ? 0 : directory.next; if (first_cluster != first_cluster_of_root_dir) { // create the top entries of a subdirectory direntry = create_short_and_long_name(i, ".", 1); direntry = create_short_and_long_name(i, "..", 1); } // actually read the directory, and allocate the mappings while ((entry=readdir(dir))) { if ((first_cluster == 0) && (directory.next >= (Bit16u)(root_entries - 1))) { BX_ERROR(("Too many entries in root directory, using only %d", count)); closedir(dir); return -2; } unsigned int length = strlen(dirname) + 2 + strlen(entry->d_name); char* buffer; direntry_t* direntry; struct stat st; bx_bool is_dot = !strcmp(entry->d_name, "."); bx_bool is_dotdot = !strcmp(entry->d_name, ".."); if ((first_cluster == first_cluster_of_root_dir) && (is_dotdot || is_dot)) continue; buffer = (char*)malloc(length); snprintf(buffer,length,"%s/%s",dirname,entry->d_name); if (stat(buffer, &st) < 0) { free(buffer); continue; } bx_bool is_mbr_file = !strcmp(entry->d_name, VVFAT_MBR); bx_bool is_boot_file = !strcmp(entry->d_name, VVFAT_BOOT); bx_bool is_attr_file = !strcmp(entry->d_name, VVFAT_ATTR); if (first_cluster == first_cluster_of_root_dir) { if (is_attr_file || ((is_mbr_file || is_boot_file) && (st.st_size == 512))) { free(buffer); continue; } } count++; // create directory entry for this file if (!is_dot && !is_dotdot) { direntry = create_short_and_long_name(i, entry->d_name, 0); } else { direntry = (direntry_t*)array_get(&directory, is_dot ? i : i + 1); } direntry->attributes = (S_ISDIR(st.st_mode) ? 0x10 : 0x20); direntry->reserved[0] = direntry->reserved[1]=0; direntry->ctime = fat_datetime(st.st_ctime, 1); direntry->cdate = fat_datetime(st.st_ctime, 0); direntry->adate = fat_datetime(st.st_atime, 0); direntry->begin_hi = 0; direntry->mtime = fat_datetime(st.st_mtime, 1); direntry->mdate = fat_datetime(st.st_mtime, 0); if (is_dotdot) set_begin_of_direntry(direntry, first_cluster_of_parent); else if (is_dot) set_begin_of_direntry(direntry, first_cluster); else direntry->begin = 0; // do that later if (st.st_size > 0x7fffffff) { BX_ERROR(("File '%s' is larger than 2GB", buffer)); free(buffer); closedir(dir); return -3; } direntry->size = htod32(S_ISDIR(st.st_mode) ? 0:st.st_size); // create mapping for this file if (!is_dot && !is_dotdot && (S_ISDIR(st.st_mode) || st.st_size)) { current_mapping = (mapping_t*)array_get_next(&this->mapping); current_mapping->begin = 0; current_mapping->end = st.st_size; /* * we get the direntry of the most recent direntry, which * contains the short name and all the relevant information. */ current_mapping->dir_index = directory.next-1; current_mapping->first_mapping_index = -1; if (S_ISDIR(st.st_mode)) { current_mapping->mode = MODE_DIRECTORY; current_mapping->info.dir.parent_mapping_index = mapping_index; } else { current_mapping->mode = MODE_UNDEFINED; current_mapping->info.file.offset = 0; } current_mapping->path = buffer; current_mapping->read_only = (st.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) == 0; } else { free(buffer); } } closedir(dir); #else WIN32_FIND_DATA finddata; char filter[MAX_PATH]; wsprintf(filter, "%s\\*.*", dirname); HANDLE hFind = FindFirstFile(filter, &finddata); int i; assert(mapping->mode & MODE_DIRECTORY); if (hFind == INVALID_HANDLE_VALUE) { mapping->end = mapping->begin; return -1; } i = mapping->info.dir.first_dir_index = first_cluster == first_cluster_of_root_dir ? 0 : directory.next; if (first_cluster != first_cluster_of_root_dir) { // create the top entries of a subdirectory direntry = create_short_and_long_name(i, ".", 1); direntry = create_short_and_long_name(i, "..", 1); } // actually read the directory, and allocate the mappings do { if ((first_cluster == 0) && (directory.next >= (Bit16u)(root_entries - 1))) { BX_ERROR(("Too many entries in root directory, using only %d", count)); FindClose(hFind); return -2; } unsigned int length = lstrlen(dirname) + 2 + lstrlen(finddata.cFileName); char* buffer; direntry_t* direntry; bx_bool is_dot = !lstrcmp(finddata.cFileName, "."); bx_bool is_dotdot = !lstrcmp(finddata.cFileName, ".."); if ((first_cluster == first_cluster_of_root_dir) && (is_dotdot || is_dot)) continue; bx_bool is_mbr_file = !lstrcmp(finddata.cFileName, VVFAT_MBR); bx_bool is_boot_file = !lstrcmp(finddata.cFileName, VVFAT_BOOT); bx_bool is_attr_file = !lstrcmp(finddata.cFileName, VVFAT_ATTR); if (first_cluster == first_cluster_of_root_dir) { if (is_attr_file || ((is_mbr_file || is_boot_file) && (finddata.nFileSizeLow == 512))) continue; } buffer = (char*)malloc(length); snprintf(buffer, length, "%s/%s", dirname, finddata.cFileName); count++; // create directory entry for this file if (!is_dot && !is_dotdot) { direntry = create_short_and_long_name(i, finddata.cFileName, 0); } else { direntry = (direntry_t*)array_get(&directory, is_dot ? i : i + 1); } direntry->attributes = ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0x10 : 0x20); direntry->reserved[0] = direntry->reserved[1]=0; direntry->ctime = fat_datetime(finddata.ftCreationTime, 1); direntry->cdate = fat_datetime(finddata.ftCreationTime, 0); direntry->adate = fat_datetime(finddata.ftLastAccessTime, 0); direntry->begin_hi = 0; direntry->mtime = fat_datetime(finddata.ftLastWriteTime, 1); direntry->mdate = fat_datetime(finddata.ftLastWriteTime, 0); if (is_dotdot) set_begin_of_direntry(direntry, first_cluster_of_parent); else if (is_dot) set_begin_of_direntry(direntry, first_cluster); else direntry->begin = 0; // do that later if (finddata.nFileSizeLow > 0x7fffffff) { BX_ERROR(("File '%s' is larger than 2GB", buffer)); free(buffer); FindClose(hFind); return -3; } direntry->size = htod32((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 0:finddata.nFileSizeLow); // create mapping for this file if (!is_dot && !is_dotdot && ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) || finddata.nFileSizeLow)) { current_mapping = (mapping_t*)array_get_next(&this->mapping); current_mapping->begin = 0; current_mapping->end = finddata.nFileSizeLow; /* * we get the direntry of the most recent direntry, which * contains the short name and all the relevant information. */ current_mapping->dir_index = directory.next-1; current_mapping->first_mapping_index = -1; if (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { current_mapping->mode = MODE_DIRECTORY; current_mapping->info.dir.parent_mapping_index = mapping_index; } else { current_mapping->mode = MODE_UNDEFINED; current_mapping->info.file.offset = 0; } current_mapping->path = buffer; current_mapping->read_only = (finddata.dwFileAttributes & FILE_ATTRIBUTE_READONLY); } else { free(buffer); } } while (FindNextFile(hFind, &finddata)); FindClose(hFind); #endif // fill with zeroes up to the end of the cluster while (directory.next % (0x10 * sectors_per_cluster)) { direntry_t* direntry = (direntry_t*)array_get_next(&directory); memset(direntry, 0, sizeof(direntry_t)); } if (fat_type != 32) { if ((mapping_index == 0) && (directory.next < root_entries)) { // root directory int cur = directory.next; array_ensure_allocated(&directory, root_entries - 1); memset(array_get(&directory, cur), 0, (root_entries - cur) * sizeof(direntry_t)); } } // reget the mapping, since this->mapping was possibly realloc()ed mapping = (mapping_t*)array_get(&this->mapping, mapping_index); if (first_cluster == 0) { first_cluster = 2; } else { first_cluster += (directory.next - mapping->info.dir.first_dir_index) * 0x20 / cluster_size; } mapping->end = first_cluster; direntry = (direntry_t*)array_get(&directory, mapping->dir_index); set_begin_of_direntry(direntry, mapping->begin); return 0; } Bit32u vvfat_image_t::sector2cluster(off_t sector_num) { return (Bit32u)((sector_num - offset_to_data) / sectors_per_cluster) + 2; } off_t vvfat_image_t::cluster2sector(Bit32u cluster_num) { return (off_t)(offset_to_data + (cluster_num - 2) * sectors_per_cluster); } int vvfat_image_t::init_directories(const char* dirname) { bootsector_t* bootsector; infosector_t* infosector; mapping_t* mapping; unsigned int i; unsigned int cluster; char size_txt[8]; Bit64u volume_sector_count = 0, tmpsc; cluster_size = sectors_per_cluster * 0x200; cluster_buffer = new Bit8u[cluster_size]; bootsector = (bootsector_t*)(first_sectors + offset_to_bootsector * 0x200); if (!use_boot_file) { volume_sector_count = sector_count - offset_to_bootsector; tmpsc = volume_sector_count - reserved_sectors - root_entries / 16; cluster_count = (tmpsc * 0x200) / ((sectors_per_cluster * 0x200) + fat_type / 4); sectors_per_fat = ((cluster_count + 2) * fat_type / 8) / 0x200; sectors_per_fat += (((cluster_count + 2) * fat_type / 8) % 0x200) > 0; } else { if (fat_type != 32) { sectors_per_fat = bootsector->sectors_per_fat; } else { sectors_per_fat = bootsector->u.fat32.sectors_per_fat; } } offset_to_fat = offset_to_bootsector + reserved_sectors; offset_to_root_dir = offset_to_fat + sectors_per_fat * 2; offset_to_data = offset_to_root_dir + root_entries / 16; if (use_boot_file) { cluster_count = (sector_count - offset_to_data) / sectors_per_cluster; } array_init(&this->mapping, sizeof(mapping_t)); array_init(&directory, sizeof(direntry_t)); /* add volume label */ { direntry_t *entry = (direntry_t*)array_get_next(&directory); entry->attributes = 0x28; // archive | volume label entry->mdate = 0x3d81; // 01.12.2010 entry->mtime = 0x6000; // 12:00:00 memcpy(entry->name, "BOCHS VV", 8); memcpy(entry->extension, "FAT", 3); } // Now build FAT, and write back information into directory init_fat(); mapping = (mapping_t*)array_get_next(&this->mapping); mapping->begin = 0; mapping->dir_index = 0; mapping->info.dir.parent_mapping_index = -1; mapping->first_mapping_index = -1; mapping->path = strdup(dirname); i = strlen(mapping->path); if (i > 0 && mapping->path[i - 1] == '/') mapping->path[i - 1] = '\0'; mapping->mode = MODE_DIRECTORY; mapping->read_only = 0; vvfat_path = mapping->path; for (i = 0, cluster = first_cluster_of_root_dir; i < this->mapping.next; i++) { // fix fat entry if not root directory of FAT12/FAT16 int fix_fat = (cluster != 0); mapping = (mapping_t*)array_get(&this->mapping, i); if (mapping->mode & MODE_DIRECTORY) { mapping->begin = cluster; if (read_directory(i)) { BX_PANIC(("Could not read directory '%s'", mapping->path)); return -1; } mapping = (mapping_t*)array_get(&this->mapping, i); } else { assert(mapping->mode == MODE_UNDEFINED); mapping->mode = MODE_NORMAL; mapping->begin = cluster; if (mapping->end > 0) { direntry_t* direntry = (direntry_t*)array_get(&directory, mapping->dir_index); mapping->end = cluster + 1 + (mapping->end-1) / cluster_size; set_begin_of_direntry(direntry, mapping->begin); } else { mapping->end = cluster + 1; fix_fat = 0; } } assert(mapping->begin < mapping->end); /* next free cluster */ cluster = mapping->end; if (cluster >= (cluster_count + 2)) { sprintf(size_txt, "%d", (sector_count >> 11)); BX_PANIC(("Directory does not fit in FAT%d (capacity %s MB)", fat_type, (fat_type == 12) ? (sector_count == 2880) ? "1.44":"2.88" : size_txt)); return -EINVAL; } // fix fat for entry if (fix_fat) { int j; for (j = mapping->begin; j < (int)(mapping->end - 1); j++) fat_set(j, j + 1); fat_set(mapping->end - 1, max_fat_value); } } mapping = (mapping_t*)array_get(&this->mapping, 0); assert((fat_type == 32) || (mapping->end == 2)); // the FAT signature fat_set(0, max_fat_value); fat_set(1, max_fat_value); current_mapping = NULL; if (!use_boot_file) { bootsector->jump[0] = 0xeb; if (fat_type != 32) { bootsector->jump[1] = 0x3e; } else { bootsector->jump[1] = 0x58; } bootsector->jump[2] = 0x90; memcpy(bootsector->name,"MSWIN4.1", 8); // Win95/98 need this to detect FAT32 bootsector->sector_size = htod16(0x200); bootsector->sectors_per_cluster = sectors_per_cluster; bootsector->reserved_sectors = htod16(reserved_sectors); bootsector->number_of_fats = 0x2; if (fat_type != 32) { bootsector->root_entries = htod16(root_entries); } bootsector->total_sectors16 = (volume_sector_count > 0xffff) ? 0:htod16(volume_sector_count); bootsector->media_type = ((fat_type != 12) ? 0xf8:0xf0); if (fat_type != 32) { bootsector->sectors_per_fat = htod16(sectors_per_fat); } bootsector->sectors_per_track = htod16(spt); bootsector->number_of_heads = htod16(heads); bootsector->hidden_sectors = htod32(offset_to_bootsector); bootsector->total_sectors = htod32((volume_sector_count > 0xffff) ? volume_sector_count:0); if (fat_type != 32) { bootsector->u.fat16.drive_number = (fat_type == 12) ? 0:0x80; // assume this is hda (TODO) bootsector->u.fat16.signature = 0x29; bootsector->u.fat16.id = htod32(0xfabe1afd); memcpy(bootsector->u.fat16.volume_label, "BOCHS VVFAT", 11); memcpy(bootsector->u.fat16.fat_type, (fat_type==12) ? "FAT12 ":"FAT16 ", 8); } else { bootsector->u.fat32.sectors_per_fat = htod32(sectors_per_fat); bootsector->u.fat32.first_cluster_of_root_dir = first_cluster_of_root_dir; bootsector->u.fat32.info_sector = htod16(1); bootsector->u.fat32.backup_boot_sector = htod16(6); bootsector->u.fat32.drive_number = 0x80; // assume this is hda (TODO) bootsector->u.fat32.signature = 0x29; bootsector->u.fat32.id = htod32(0xfabe1afd); memcpy(bootsector->u.fat32.volume_label, "BOCHS VVFAT", 11); memcpy(bootsector->u.fat32.fat_type, "FAT32 ", 8); } bootsector->magic[0] = 0x55; bootsector->magic[1] = 0xaa; } fat.pointer[0] = bootsector->media_type; if (fat_type == 32) { // backup boot sector memcpy(&first_sectors[(offset_to_bootsector + 6) * 0x200], &first_sectors[offset_to_bootsector * 0x200], 0x200); // FS info sector infosector = (infosector_t*)(first_sectors + (offset_to_bootsector + 1) * 0x200); infosector->signature1 = htod32(0x41615252); infosector->signature2 = htod32(0x61417272); infosector->free_clusters = htod32(cluster_count - cluster + 2); infosector->mra_cluster = htod32(2); infosector->magic[0] = 0x55; infosector->magic[1] = 0xaa; } return 0; } bx_bool vvfat_image_t::read_sector_from_file(const char *path, Bit8u *buffer, Bit32u sector) { int fd = ::open(path, O_RDONLY #ifdef O_BINARY | O_BINARY #endif #ifdef O_LARGEFILE | O_LARGEFILE #endif ); if (fd < 0) return 0; int offset = sector * 0x200; if (::lseek(fd, offset, SEEK_SET) != offset) { return 0; ::close(fd); } int result = ::read(fd, buffer, 0x200); ::close(fd); bx_bool bootsig = ((buffer[0x1fe] == 0x55) && (buffer[0x1ff] == 0xaa)); return (result == 0x200) && bootsig; } void vvfat_image_t::set_file_attributes(void) { char path[BX_PATHNAME_LEN]; char fpath[BX_PATHNAME_LEN]; char line[512]; char *ret, *ptr; FILE *fd; Bit8u attributes; int i; sprintf(path, "%s/%s", vvfat_path, VVFAT_ATTR); fd = fopen(path, "r"); if (fd != NULL) { do { ret = fgets(line, sizeof(line) - 1, fd); if (ret != NULL) { line[sizeof(line) - 1] = '\0'; size_t len = strlen(line); if ((len > 0) && (line[len - 1] < ' ')) line[len - 1] = '\0'; ptr = strtok(line, ":"); if (ptr[0] == 34) { strcpy(fpath, ptr + 1); } else { strcpy(fpath, ptr); } if (fpath[strlen(fpath) - 1] == 34) { fpath[strlen(fpath) - 1] = '\0'; } mapping_t* mapping = find_mapping_for_path(fpath); if (mapping != NULL) { direntry_t* entry = (direntry_t*)array_get(&directory, mapping->dir_index); attributes = entry->attributes; ptr = strtok(NULL, ""); for (i = 0; i < (int)strlen(ptr); i++) { switch (ptr[i]) { case 'a': attributes &= ~0x20; break; case 'S': attributes |= 0x04; break; case 'H': attributes |= 0x02; break; case 'R': attributes |= 0x01; break; } } entry->attributes = attributes; } } } while (!feof(fd)); fclose(fd); } } int vvfat_image_t::open(const char* dirname) { Bit32u size_in_mb; char path[BX_PATHNAME_LEN]; Bit8u sector_buffer[0x200]; int filedes; const char *logname = NULL; char ftype[10]; bx_bool ftype_ok; use_mbr_file = 0; use_boot_file = 0; fat_type = 0; sectors_per_cluster = 0; snprintf(path, BX_PATHNAME_LEN, "%s/%s", dirname, VVFAT_MBR); if (read_sector_from_file(path, sector_buffer, 0)) { mbr_t* real_mbr = (mbr_t*)sector_buffer; partition_t* partition = &(real_mbr->partition[0]); if ((partition->fs_type != 0) && (partition->length_sector_long > 0)) { if ((partition->fs_type == 0x06) || (partition->fs_type == 0x0e)) { fat_type = 16; } else if ((partition->fs_type == 0x0b) || (partition->fs_type == 0x0c)) { fat_type = 32; } else { BX_ERROR(("MBR file: unsupported FS type = 0x%02x", partition->fs_type)); } if (fat_type != 0) { sector_count = partition->start_sector_long + partition->length_sector_long; spt = partition->start_sector_long; if (partition->end_CHS.head > 15) { heads = 16; } else { heads = partition->end_CHS.head + 1; } cylinders = sector_count / (heads * spt); offset_to_bootsector = spt; memcpy(&first_sectors[0], sector_buffer, 0x200); use_mbr_file = 1; BX_INFO(("VVFAT: using MBR from file")); } } } snprintf(path, BX_PATHNAME_LEN, "%s/%s", dirname, VVFAT_BOOT); if (read_sector_from_file(path, sector_buffer, 0)) { bootsector_t* bs = (bootsector_t*)sector_buffer; if (use_mbr_file) { sprintf(ftype, "FAT%d ", fat_type); if (fat_type == 32) { ftype_ok = memcmp(bs->u.fat32.fat_type, ftype, 8) == 0; } else { ftype_ok = memcmp(bs->u.fat16.fat_type, ftype, 8) == 0; } Bit32u sc = bs->total_sectors16 + bs->total_sectors + bs->hidden_sectors; if (ftype_ok && (sc == sector_count) && (bs->number_of_fats == 2)) { use_boot_file = 1; } } else { if (memcmp(bs->u.fat16.fat_type, "FAT12 ", 8) == 0) { fat_type = 12; } else if (memcmp(bs->u.fat16.fat_type, "FAT16 ", 8) == 0) { fat_type = 16; } else if (memcmp(bs->u.fat32.fat_type, "FAT32 ", 8) == 0) { fat_type = 32; } else { memcpy(ftype, bs->u.fat16.fat_type, 8); ftype[8] = 0; BX_PANIC(("boot sector file: unsupported FS type = '%s'", ftype)); return -1; } if ((fat_type != 0) && (bs->number_of_fats == 2)) { sector_count = bs->total_sectors16 + bs->total_sectors + bs->hidden_sectors; spt = bs->sectors_per_track; if (bs->number_of_heads > 15) { heads = 16; } else { heads = bs->number_of_heads; } cylinders = sector_count / (heads * spt); offset_to_bootsector = bs->hidden_sectors; use_boot_file = 1; } } if (use_boot_file) { sectors_per_cluster = bs->sectors_per_cluster; reserved_sectors = bs->reserved_sectors; root_entries = bs->root_entries; first_cluster_of_root_dir = (fat_type != 32) ? 0 : bs->u.fat32.first_cluster_of_root_dir; memcpy(&first_sectors[offset_to_bootsector * 0x200], sector_buffer, 0x200); BX_INFO(("VVFAT: using boot sector from file")); } } if (!use_mbr_file && !use_boot_file) { if (hd_size == 1474560) { // floppy support cylinders = 80; heads = 2; spt = 18; offset_to_bootsector = 0; fat_type = 12; sectors_per_cluster = 1; first_cluster_of_root_dir = 0; root_entries = 224; reserved_sectors = 1; } else { if (cylinders == 0) { cylinders = 1024; heads = 16; spt = 63; } offset_to_bootsector = spt; } sector_count = cylinders * heads * spt; } hd_size = 512L * ((Bit64u)sector_count); if (sectors_per_cluster == 0) { size_in_mb = (Bit32u)(hd_size >> 20); if ((size_in_mb >= 2047) || (fat_type == 32)) { fat_type = 32; if (size_in_mb >= 32767) { sectors_per_cluster = 64; } else if (size_in_mb >= 16383) { sectors_per_cluster = 32; } else if (size_in_mb >= 8191) { sectors_per_cluster = 16; } else { sectors_per_cluster = 8; } first_cluster_of_root_dir = 2; root_entries = 0; reserved_sectors = 32; } else { fat_type = 16; if (size_in_mb >= 1023) { sectors_per_cluster = 64; } else if (size_in_mb >= 511) { sectors_per_cluster = 32; } else if (size_in_mb >= 255) { sectors_per_cluster = 16; } else if (size_in_mb >= 127) { sectors_per_cluster = 8; } else { sectors_per_cluster = 4; } first_cluster_of_root_dir = 0; root_entries = 512; reserved_sectors = 1; } } current_cluster = 0xffff; current_fd = 0; if ((!use_mbr_file) && (offset_to_bootsector > 0)) init_mbr(); init_directories(dirname); set_file_attributes(); // VOLATILE WRITE SUPPORT snprintf(path, BX_PATHNAME_LEN, "%s/vvfat.dir", dirname); // if redolog name was set if (redolog_name != NULL) { if (strcmp(redolog_name, "") != 0) { logname = redolog_name; } } // otherwise use path as template if (logname == NULL) { logname = path; } redolog_temp = (char*)malloc(strlen(logname) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1); sprintf(redolog_temp, "%s%s", logname, VOLATILE_REDOLOG_EXTENSION); filedes = mkstemp(redolog_temp); if (filedes < 0) { BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); return -1; } if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, hd_size) < 0) { BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp)); return -1; } #if (!defined(WIN32)) && !BX_WITH_MACOS // on unix it is legal to delete an open file unlink(redolog_temp); #endif vvfat_modified = 0; BX_INFO(("'vvfat' disk opened: directory is '%s', redolog is '%s'", dirname, redolog_temp)); return 0; } direntry_t* vvfat_image_t::read_direntry(Bit8u *buffer, char *filename) { const Bit8u lfn_map[13] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; direntry_t *entry; bx_bool entry_ok = 0, has_lfn = 0; char lfn_tmp[BX_PATHNAME_LEN]; int i; memset(filename, 0, BX_PATHNAME_LEN); lfn_tmp[0] = 0; do { entry = (direntry_t*)buffer; if (entry->name[0] == 0) { entry = NULL; break; } else if ((entry->name[0] != '.') && (entry->name[0] != 0xe5) && ((entry->attributes & 0x0f) != 0x08)) { if (is_long_name(entry)) { for (i = 0; i < 13; i++) { lfn_tmp[i] = buffer[lfn_map[i]]; } lfn_tmp[i] = 0; strcat(lfn_tmp, filename); strcpy(filename, lfn_tmp); has_lfn = 1; buffer += 32; } else { if (!has_lfn) { if (entry->name[0] == 0x05) entry->name[0] = 0xe5; memcpy(filename, entry->name, 8); i = 7; while ((i > 0) && (filename[i] == ' ')) filename[i--] = 0; if (entry->extension[0] != ' ') strcat(filename, "."); memcpy(filename+i+2, entry->extension, 3); i = strlen(filename) - 1; while (filename[i] == ' ') filename[i--] = 0; for (i = 0; i < (int)strlen(filename); i++) { if ((filename[i] > 0x40) && (filename[i] < 0x5b)) { filename[i] |= 0x20; } } } entry_ok = 1; } } else { buffer += 32; } } while (!entry_ok); return entry; } Bit32u vvfat_image_t::fat_get_next(Bit32u current) { if (fat_type == 32) { return dtoh32(((Bit32u*)fat2)[current]); } else if (fat_type == 16) { return dtoh16(((Bit16u*)fat2)[current]); } else { int offset = (current * 3 / 2); Bit8u* p = (((Bit8u*)fat2) + offset); Bit32u value = 0; switch (current & 1) { case 0: value = p[0] | ((p[1] & 0x0f) << 8); break; case 1: value = (p[0] >> 4) | (p[1] << 4); break; } return value; } } bx_bool vvfat_image_t::write_file(const char *path, direntry_t *entry, bx_bool create) { int fd; Bit32u csize, fsize, fstart, cur, next, rsvd_clusters, bad_cluster; Bit64u offset; Bit8u *buffer; #ifndef WIN32 struct tm tv; struct utimbuf ut; #else HANDLE hFile; FILETIME at, mt, tmp; SYSTEMTIME st; #endif csize = sectors_per_cluster * 0x200; rsvd_clusters = max_fat_value - 15; bad_cluster = max_fat_value - 8; fsize = dtoh32(entry->size); fstart = dtoh16(entry->begin) | (dtoh16(entry->begin_hi) << 16); if (create) { fd = ::open(path, O_CREAT | O_RDWR | O_TRUNC #ifdef O_BINARY | O_BINARY #endif #ifdef O_LARGEFILE | O_LARGEFILE #endif , 0644); } else { fd = ::open(path, O_RDWR | O_TRUNC #ifdef O_BINARY | O_BINARY #endif #ifdef O_LARGEFILE | O_LARGEFILE #endif ); } if (fd < 0) return 0; buffer = (Bit8u*)malloc(csize); next = fstart; do { cur = next; offset = cluster2sector(cur); lseek(offset * 0x200, SEEK_SET); read(buffer, csize); if (fsize > csize) { ::write(fd, buffer, csize); fsize -= csize; } else { ::write(fd, buffer, fsize); } next = fat_get_next(cur); if ((next >= rsvd_clusters) && (next < bad_cluster)) { BX_ERROR(("reserved clusters not supported")); } } while (next < rsvd_clusters); ::close(fd); #ifndef WIN32 tv.tm_year = (entry->mdate >> 9) + 80; tv.tm_mon = ((entry->mdate >> 5) & 0x0f) - 1; tv.tm_mday = entry->mdate & 0x1f; tv.tm_hour = (entry->mtime >> 11); tv.tm_min = (entry->mtime >> 5) & 0x3f; tv.tm_sec = (entry->mtime & 0x1f) << 1; tv.tm_isdst = -1; ut.modtime = mktime(&tv); if (entry->adate != 0) { tv.tm_year = (entry->adate >> 9) + 80; tv.tm_mon = ((entry->adate >> 5) & 0x0f) - 1; tv.tm_mday = entry->adate & 0x1f; tv.tm_hour = 0; tv.tm_min = 0; tv.tm_sec = 0; ut.actime = mktime(&tv); } else { ut.actime = ut.modtime; } utime(path, &ut); #else hFile = CreateFile(path, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { memset(&st, 0, sizeof(st)); st.wYear = (entry->mdate >> 9) + 1980; st.wMonth = ((entry->mdate >> 5) & 0x0f); st.wDay = entry->mdate & 0x1f; st.wHour = (entry->mtime >> 11); st.wMinute = (entry->mtime >> 5) & 0x3f; st.wSecond = (entry->mtime & 0x1f) << 1; SystemTimeToFileTime(&st, &tmp); LocalFileTimeToFileTime(&tmp, &mt); if (entry->adate != 0) { st.wYear = (entry->adate >> 9) + 1980; st.wMonth = ((entry->adate >> 5) & 0x0f); st.wDay = entry->adate & 0x1f; st.wHour = 0; st.wMinute = 0; st.wSecond = 0; SystemTimeToFileTime(&st, &tmp); LocalFileTimeToFileTime(&tmp, &at); } else { at = mt; } SetFileTime(hFile, NULL, &at, &mt); CloseHandle(hFile); } #endif return 1; } void vvfat_image_t::parse_directory(const char *path, Bit32u start_cluster) { Bit32u csize, fstart, cur, next, size, rsvd_clusters; Bit64u offset; Bit8u *buffer, *ptr; direntry_t *entry, *newentry; char filename[BX_PATHNAME_LEN]; char full_path[BX_PATHNAME_LEN]; char attr_txt[4]; mapping_t *mapping; csize = sectors_per_cluster * 0x200; rsvd_clusters = max_fat_value - 15; if (start_cluster == 0) { size = root_entries * 32; offset = offset_to_root_dir; buffer = (Bit8u*)malloc(size); lseek(offset * 0x200, SEEK_SET); read(buffer, size); } else { size = csize; buffer = (Bit8u*)malloc(size); next = start_cluster; do { cur = next; offset = cluster2sector(cur); lseek(offset * 0x200, SEEK_SET); read(buffer+(size-csize), csize); next = fat_get_next(cur); if (next < rsvd_clusters) { size += csize; buffer = (Bit8u*)realloc(buffer, size); } } while (next < rsvd_clusters); } ptr = buffer; do { newentry = read_direntry(ptr, filename); if (newentry != NULL) { sprintf(full_path, "%s/%s", path, filename); if ((newentry->attributes != 0x10) && (newentry->attributes != 0x20)) { if (vvfat_attr_fd != NULL) { attr_txt[0] = 0; if ((newentry->attributes & 0x30) == 0) strcpy(attr_txt, "a"); if (newentry->attributes & 0x04) strcpy(attr_txt, "S"); if (newentry->attributes & 0x02) strcat(attr_txt, "H"); if (newentry->attributes & 0x01) strcat(attr_txt, "R"); fprintf(vvfat_attr_fd, "\"%s\":%s\n", full_path, attr_txt); } } fstart = dtoh16(newentry->begin) | (dtoh16(newentry->begin_hi) << 16); mapping = find_mapping_for_cluster(fstart); if (mapping == NULL) { if ((newentry->attributes & 0x10) > 0) { bx_mkdir(full_path); parse_directory(full_path, fstart); } else { if (access(full_path, F_OK) == 0) { mapping = find_mapping_for_path(full_path); if (mapping != NULL) { mapping->mode &= ~MODE_DELETED; } write_file(full_path, newentry, 0); } else { write_file(full_path, newentry, 1); } } } else { entry = (direntry_t*)array_get(&directory, mapping->dir_index); if (!strcmp(full_path, mapping->path)) { if ((newentry->attributes & 0x10) > 0) { parse_directory(full_path, fstart); mapping->mode &= ~MODE_DELETED; } else { if ((newentry->mdate != entry->mdate) || (newentry->mtime != entry->mtime) || (newentry->size != entry->size)) { write_file(full_path, newentry, 0); } mapping->mode &= ~MODE_DELETED; } } else { if ((newentry->cdate == entry->cdate) && (newentry->ctime == entry->ctime)) { rename(mapping->path, full_path); if (newentry->attributes == 0x10) { parse_directory(full_path, fstart); mapping->mode &= ~MODE_DELETED; } else { if ((newentry->mdate != entry->mdate) || (newentry->mtime != entry->mtime) || (newentry->size != entry->size)) { write_file(full_path, newentry, 0); } mapping->mode &= ~MODE_DELETED; } } else { if ((newentry->attributes & 0x10) > 0) { bx_mkdir(full_path); parse_directory(full_path, fstart); } else { if (access(full_path, F_OK) == 0) { mapping = find_mapping_for_path(full_path); if (mapping != NULL) { mapping->mode &= ~MODE_DELETED; } write_file(full_path, newentry, 0); } else { write_file(full_path, newentry, 1); } } } } } ptr = (Bit8u*)newentry+32; } } while ((newentry != NULL) && ((Bit32u)(ptr - buffer) < size)); free(buffer); } void vvfat_image_t::commit_changes(void) { char path[BX_PATHNAME_LEN]; mapping_t *mapping; int i; // read modified FAT fat2 = malloc(sectors_per_fat * 0x200); lseek(offset_to_fat * 0x200, SEEK_SET); read(fat2, sectors_per_fat * 0x200); // mark all mapped directories / files for delete for (i = 1; i < (int)this->mapping.next; i++) { mapping = (mapping_t*)array_get(&this->mapping, i); if (mapping->first_mapping_index < 0) { mapping->mode |= MODE_DELETED; } } sprintf(path, "%s/%s", vvfat_path, VVFAT_ATTR); vvfat_attr_fd = fopen(path, "w"); // parse new directory tree and create / modify directories and files parse_directory(vvfat_path, (fat_type == 32) ? first_cluster_of_root_dir : 0); if (vvfat_attr_fd != NULL) fclose(vvfat_attr_fd); // remove all directories and files still marked for delete for (i = this->mapping.next - 1; i > 0; i--) { mapping = (mapping_t*)array_get(&this->mapping, i); if (mapping->mode & MODE_DELETED) { direntry_t* entry = (direntry_t*)array_get(&directory, mapping->dir_index); if (entry->attributes == 0x10) { bx_rmdir(mapping->path); } else { unlink(mapping->path); } } } free(fat2); } void vvfat_image_t::close(void) { char msg[BX_PATHNAME_LEN + 80]; mapping_t *mapping; if (vvfat_modified) { sprintf(msg, "Write back changes to directory '%s'?\n\nWARNING: This feature is still experimental!", vvfat_path); if (SIM->ask_yes_no("Bochs VVFAT modified", msg, 0)) { commit_changes(); } } array_free(&fat); array_free(&directory); for (unsigned i = 0; i < this->mapping.next; i++) { mapping = (mapping_t*)array_get(&this->mapping, i); free(mapping->path); } array_free(&this->mapping); if (cluster_buffer != NULL) delete [] cluster_buffer; redolog->close(); #if defined(WIN32) || BX_WITH_MACOS // on non-unix we have to wait till the file is closed to delete it unlink(redolog_temp); #endif if (redolog_temp!=NULL) free(redolog_temp); if (redolog_name!=NULL) free(redolog_name); } Bit64s vvfat_image_t::lseek(Bit64s offset, int whence) { redolog->lseek(offset, whence); if (whence == SEEK_SET) { sector_num = (Bit32u)(offset / 512); } else if (whence == SEEK_CUR) { sector_num += (Bit32u)(offset / 512); } else { BX_ERROR(("lseek: mode not supported yet")); return -1; } if (sector_num >= sector_count) return -1; return 0; } void vvfat_image_t::close_current_file(void) { if(current_mapping) { current_mapping = NULL; if (current_fd) { ::close(current_fd); current_fd = 0; } } current_cluster = 0xffff; } // mappings between index1 and index2-1 are supposed to be ordered // return value is the index of the last mapping for which end>cluster_num int vvfat_image_t::find_mapping_for_cluster_aux(int cluster_num, int index1, int index2) { while(1) { int index3; mapping_t* mapping; index3 = (index1+index2) / 2; mapping = (mapping_t*)array_get(&this->mapping, index3); assert(mapping->begin < mapping->end); if (mapping->begin >= (unsigned int)cluster_num) { assert(index2 != index3 || index2 == 0); if (index2 == index3) return index1; index2 = index3; } else { if (index1 == index3) return (mapping->end <= (unsigned int)cluster_num) ? index2 : index1; index1 = index3; } assert(index1 <= index2); } } mapping_t* vvfat_image_t::find_mapping_for_cluster(int cluster_num) { int index = find_mapping_for_cluster_aux(cluster_num, 0, mapping.next); mapping_t* mapping; if (index >= (int)this->mapping.next) return NULL; mapping = (mapping_t*)array_get(&this->mapping, index); if ((int)mapping->begin > cluster_num) return NULL; assert(((int)mapping->begin <= cluster_num) && ((int)mapping->end > cluster_num)); return mapping; } // This function simply compares path == mapping->path. Since the mappings // are sorted by cluster, this is expensive: O(n). mapping_t* vvfat_image_t::find_mapping_for_path(const char* path) { int i; for (i = 0; i < (int)this->mapping.next; i++) { mapping_t* mapping = (mapping_t*)array_get(&this->mapping, i); if ((mapping->first_mapping_index < 0) && !strcmp(path, mapping->path)) return mapping; } return NULL; } int vvfat_image_t::open_file(mapping_t* mapping) { if (!mapping) return -1; if (!current_mapping || strcmp(current_mapping->path, mapping->path)) { /* open file */ int fd = ::open(mapping->path, O_RDONLY #ifdef O_BINARY | O_BINARY #endif #ifdef O_LARGEFILE | O_LARGEFILE #endif ); if (fd < 0) return -1; close_current_file(); current_fd = fd; current_mapping = mapping; } return 0; } int vvfat_image_t::read_cluster(int cluster_num) { mapping_t* mapping; if (current_cluster != cluster_num) { int result=0; off_t offset; assert(!current_mapping || current_fd || (current_mapping->mode & MODE_DIRECTORY)); if (!current_mapping || ((int)current_mapping->begin > cluster_num) || ((int)current_mapping->end <= cluster_num)) { // binary search of mappings for file mapping = find_mapping_for_cluster(cluster_num); assert(!mapping || ((cluster_num >= (int)mapping->begin) && (cluster_num < (int)mapping->end))); if (mapping && mapping->mode & MODE_DIRECTORY) { close_current_file(); current_mapping = mapping; read_cluster_directory: offset = cluster_size * (cluster_num - current_mapping->begin); cluster = (unsigned char*)directory.pointer+offset + 0x20 * current_mapping->info.dir.first_dir_index; assert(((cluster -(unsigned char*)directory.pointer) % cluster_size) == 0); assert((char*)cluster + cluster_size <= directory.pointer + directory.next * directory.item_size); current_cluster = cluster_num; return 0; } if (open_file(mapping)) return -2; } else if (current_mapping->mode & MODE_DIRECTORY) goto read_cluster_directory; assert(current_fd); offset = cluster_size * (cluster_num - current_mapping->begin) + current_mapping->info.file.offset; if (::lseek(current_fd, offset, SEEK_SET) != offset) return -3; cluster = cluster_buffer; result = ::read(current_fd, cluster, cluster_size); if (result < 0) { current_cluster = 0xffff; return -1; } current_cluster = cluster_num; } return 0; } ssize_t vvfat_image_t::read(void* buf, size_t count) { char *cbuf = (char*)buf; Bit32u scount = (Bit32u)(count / 0x200); while (scount-- > 0) { if ((ssize_t)redolog->read(cbuf, 0x200) != 0x200) { if (sector_num < offset_to_data) { if (sector_num < (offset_to_bootsector + reserved_sectors)) memcpy(cbuf, &first_sectors[sector_num * 0x200], 0x200); else if ((sector_num - offset_to_fat) < sectors_per_fat) memcpy(cbuf, &fat.pointer[(sector_num - offset_to_fat) * 0x200], 0x200); else if ((sector_num - offset_to_fat - sectors_per_fat) < sectors_per_fat) memcpy(cbuf, &fat.pointer[(sector_num - offset_to_fat - sectors_per_fat) * 0x200], 0x200); else memcpy(cbuf, &directory.pointer[(sector_num - offset_to_root_dir) * 0x200], 0x200); } else { Bit32u sector = sector_num - offset_to_data, sector_offset_in_cluster = (sector % sectors_per_cluster), cluster_num = sector / sectors_per_cluster + 2; if (read_cluster(cluster_num) != 0) { memset(cbuf, 0, 0x200); } else { memcpy(cbuf, cluster + sector_offset_in_cluster * 0x200, 0x200); } } redolog->lseek((sector_num + 1) * 0x200, SEEK_SET); } sector_num++; cbuf += 0x200; } return count; } ssize_t vvfat_image_t::write(const void* buf, size_t count) { ssize_t ret = 0; char *cbuf = (char*)buf; Bit32u scount = (Bit32u)(count / 512); bx_bool update_imagepos; while (scount-- > 0) { update_imagepos = 1; if (sector_num == 0) { // allow writing to MBR (except partition table) memcpy(&first_sectors[0], cbuf, 0x1b8); } else if (sector_num == offset_to_bootsector) { // allow writing to boot sector memcpy(&first_sectors[sector_num * 0x200], cbuf, 0x200); } else if ((fat_type == 32) && (sector_num == (offset_to_bootsector + 1))) { // allow writing to FS info sector memcpy(&first_sectors[sector_num * 0x200], cbuf, 0x200); } else if (sector_num < (offset_to_bootsector + reserved_sectors)) { BX_ERROR(("VVFAT write ignored: sector=%d, count=%d", sector_num, scount)); ret = -1; } else { vvfat_modified = 1; update_imagepos = 0; ret = redolog->write(cbuf, 0x200); } if (ret < 0) break; sector_num++; cbuf += 0x200; if (update_imagepos) { redolog->lseek(sector_num * 0x200, SEEK_SET); } } return (ret < 0) ? ret : count; } Bit32u vvfat_image_t::get_capabilities(void) { return HDIMAGE_HAS_GEOMETRY; } bochs-2.6/iodev/pit82c54.cc0000644000175000017500000007372212020641505015242 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pit82c54.cc 11156 2012-05-01 15:53:28Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* * Emulator of an Intel 8254/82C54 Programmable Interval Timer. * Greg Alexander * * * Things I am unclear on (greg): * 1.)What happens if both the status and count registers are latched, * but the first of the two count registers has already been read? * I.E.: * latch count 0 (16-bit) * Read count 0 (read LSByte) * READ_BACK status of count 0 * Read count 0 - do you get MSByte or status? * This will be flagged as an error. * 2.)What happens when we latch the output in the middle of a 2-part * unlatched read? * 3.)I assumed that programming a counter removes a latched status. * 4.)I implemented the 8254 description of mode 0, not the 82C54 one. * 5.)clock() calls represent a rising clock edge followed by a falling * clock edge. * 6.)What happens when we trigger mode 1 in the middle of a 2-part * write? */ // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "pit82c54.h" #define LOG_THIS this-> void pit_82C54::print_counter(counter_type &thisctr) { #if BX_DEBUGGER dbg_printf("count: %d\n", thisctr.count); dbg_printf("count_binary: 0x%04x\n", thisctr.count_binary); dbg_printf("counter GATE: %x\n", thisctr.GATE); dbg_printf("counter OUT: %x\n", thisctr.OUTpin); dbg_printf("next_change_time: %d\n", thisctr.next_change_time); #endif } void pit_82C54::print_cnum(Bit8u cnum) { if (cnum>MAX_COUNTER) { BX_ERROR(("Bad counter index to print_cnum")); } else { print_counter(counter[cnum]); } } void pit_82C54::latch_counter(counter_type &thisctr) { if (thisctr.count_LSB_latched || thisctr.count_MSB_latched) { //Do nothing because previous latch has not been read.; } else { switch(thisctr.read_state) { case MSByte: thisctr.outlatch=thisctr.count & 0xFFFF; thisctr.count_MSB_latched=1; break; case LSByte: thisctr.outlatch=thisctr.count & 0xFFFF; thisctr.count_LSB_latched=1; break; case LSByte_multiple: thisctr.outlatch=thisctr.count & 0xFFFF; thisctr.count_LSB_latched=1; thisctr.count_MSB_latched=1; break; case MSByte_multiple: if (!(seen_problems & UNL_2P_READ)) { // seen_problems|=UNL_2P_READ; BX_ERROR(("Unknown behavior when latching during 2-part read.")); BX_ERROR((" This message will not be repeated.")); } //I guess latching and resetting to LSB first makes sense; BX_DEBUG(("Setting read_state to LSB_mult")); thisctr.read_state=LSByte_multiple; thisctr.outlatch=thisctr.count & 0xFFFF; thisctr.count_LSB_latched=1; thisctr.count_MSB_latched=1; break; default: BX_ERROR(("Unknown read mode found during latch command.")); break; } } } void pit_82C54::set_OUT(counter_type &thisctr, bx_bool data) { if (thisctr.OUTpin != data) { thisctr.OUTpin = data; if (thisctr.out_handler != NULL) { thisctr.out_handler(data); } } } void BX_CPP_AttrRegparmN(2) pit_82C54::set_count(counter_type &thisctr, Bit32u data) { thisctr.count=data & 0xFFFF; set_binary_to_count(thisctr); } void BX_CPP_AttrRegparmN(1) pit_82C54::set_count_to_binary(counter_type &thisctr) { if (thisctr.bcd_mode) { thisctr.count= (((thisctr.count_binary/1)%10)<<0) | (((thisctr.count_binary/10)%10)<<4) | (((thisctr.count_binary/100)%10)<<8) | (((thisctr.count_binary/1000)%10)<<12); } else { thisctr.count=thisctr.count_binary; } } void BX_CPP_AttrRegparmN(1) pit_82C54::set_binary_to_count(counter_type &thisctr) { if (thisctr.bcd_mode) { thisctr.count_binary= (1*((thisctr.count>>0)&0xF)) + (10*((thisctr.count>>4)&0xF)) + (100*((thisctr.count>>8)&0xF)) + (1000*((thisctr.count>>12)&0xF)); } else { thisctr.count_binary=thisctr.count; } } void BX_CPP_AttrRegparmN(1) pit_82C54::decrement (counter_type &thisctr) { if (!thisctr.count) { if (thisctr.bcd_mode) { thisctr.count=0x9999; thisctr.count_binary=9999; } else { thisctr.count=0xFFFF; thisctr.count_binary=0xFFFF; } } else { thisctr.count_binary--; set_count_to_binary(thisctr); } } void pit_82C54::init(void) { put("pit82c54", "PIT81"); for(int i=0;i<3;i++) { BX_DEBUG(("Setting read_state to LSB")); counter[i].read_state=LSByte; counter[i].write_state=LSByte; counter[i].GATE=1; counter[i].OUTpin=1; counter[i].triggerGATE=0; counter[i].mode=4; counter[i].first_pass=0; counter[i].bcd_mode=0; counter[i].count=0; counter[i].count_binary=0; counter[i].state_bit_1=0; counter[i].state_bit_2=0; counter[i].null_count=0; counter[i].rw_mode=1; counter[i].count_written=1; counter[i].count_LSB_latched=0; counter[i].count_MSB_latched=0; counter[i].status_latched=0; counter[i].next_change_time=0; counter[i].out_handler=NULL; } seen_problems=0; } pit_82C54::pit_82C54(void) { init(); } void pit_82C54::reset(unsigned type) {} void pit_82C54::register_state(bx_param_c *parent) { char name[4]; for (unsigned i=0; i<3; i++) { sprintf(name, "%d", i); bx_list_c *tim = new bx_list_c(parent, name); new bx_shadow_bool_c(tim, "GATE", &counter[i].GATE); new bx_shadow_bool_c(tim, "OUTpin", &counter[i].OUTpin); new bx_shadow_num_c(tim, "count", &counter[i].count); new bx_shadow_num_c(tim, "outlatch", &counter[i].outlatch); new bx_shadow_num_c(tim, "inlatch", &counter[i].inlatch); new bx_shadow_num_c(tim, "status_latch", &counter[i].status_latch); new bx_shadow_num_c(tim, "rw_mode", &counter[i].rw_mode); new bx_shadow_num_c(tim, "mode", &counter[i].mode); new bx_shadow_bool_c(tim, "bcd_mode", &counter[i].bcd_mode); new bx_shadow_bool_c(tim, "null_count", &counter[i].null_count); new bx_shadow_bool_c(tim, "count_LSB_latched", &counter[i].count_LSB_latched); new bx_shadow_bool_c(tim, "count_MSB_latched", &counter[i].count_MSB_latched); new bx_shadow_bool_c(tim, "status_latched", &counter[i].status_latched); new bx_shadow_num_c(tim, "count_binary", &counter[i].count_binary); new bx_shadow_bool_c(tim, "triggerGATE", &counter[i].triggerGATE); new bx_shadow_num_c(tim, "write_state", (Bit8u*)&counter[i].write_state); new bx_shadow_num_c(tim, "read_state", (Bit8u*)&counter[i].read_state); new bx_shadow_bool_c(tim, "count_written", &counter[i].count_written); new bx_shadow_bool_c(tim, "first_pass", &counter[i].first_pass); new bx_shadow_bool_c(tim, "state_bit_1", &counter[i].state_bit_1); new bx_shadow_bool_c(tim, "state_bit_2", &counter[i].state_bit_2); new bx_shadow_num_c(tim, "next_change_time", &counter[i].next_change_time); } } void BX_CPP_AttrRegparmN(2) pit_82C54::decrement_multiple(counter_type &thisctr, Bit32u cycles) { while(cycles>0) { if (cycles<=thisctr.count_binary) { thisctr.count_binary-=cycles; cycles-=cycles; set_count_to_binary(thisctr); } else { cycles-=(thisctr.count_binary+1); thisctr.count_binary-=thisctr.count_binary; set_count_to_binary(thisctr); decrement(thisctr); } } } void pit_82C54::clock_multiple(Bit8u cnum, Bit32u cycles) { if (cnum>MAX_COUNTER) { BX_ERROR(("Counter number too high in clock")); } else { counter_type &thisctr = counter[cnum]; while(cycles>0) { if (thisctr.next_change_time==0) { if (thisctr.count_written) { switch(thisctr.mode) { case 0: if (thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) { decrement_multiple(thisctr, cycles); } break; case 1: decrement_multiple(thisctr, cycles); break; case 2: if (!thisctr.first_pass && thisctr.GATE) { decrement_multiple(thisctr, cycles); } break; case 3: if (!thisctr.first_pass && thisctr.GATE) { decrement_multiple(thisctr, 2*cycles); } break; case 4: if (thisctr.GATE) { decrement_multiple(thisctr, cycles); } break; case 5: decrement_multiple(thisctr, cycles); break; default: break; } } cycles-=cycles; } else { switch(thisctr.mode) { case 0: case 1: case 2: case 4: case 5: if (thisctr.next_change_time > cycles) { decrement_multiple(thisctr,cycles); thisctr.next_change_time-=cycles; cycles-=cycles; } else { decrement_multiple(thisctr,(thisctr.next_change_time-1)); cycles-=thisctr.next_change_time; clock(cnum); } break; case 3: if (thisctr.next_change_time > cycles) { decrement_multiple(thisctr,cycles*2); thisctr.next_change_time-=cycles; cycles-=cycles; } else { decrement_multiple(thisctr,(thisctr.next_change_time-1)*2); cycles-=thisctr.next_change_time; clock(cnum); } break; default: cycles-=cycles; break; } } } } } void BX_CPP_AttrRegparmN(1) pit_82C54::clock(Bit8u cnum) { if (cnum>MAX_COUNTER) { BX_ERROR(("Counter number too high in clock")); } else { counter_type &thisctr = counter[cnum]; switch(thisctr.mode) { case 0: if (thisctr.count_written) { if (thisctr.null_count) { set_count(thisctr, thisctr.inlatch); if (thisctr.GATE) { if (thisctr.count_binary==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; } } else { thisctr.next_change_time=0; } thisctr.null_count=0; } else { if (thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) { decrement(thisctr); if (!thisctr.OUTpin) { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; if (!thisctr.count) { set_OUT(thisctr,1); } } else { thisctr.next_change_time=0; } } else { thisctr.next_change_time=0; //if the clock isn't moving. } } } else { thisctr.next_change_time=0; //default to 0. } thisctr.triggerGATE=0; break; case 1: if (thisctr.count_written) { if (thisctr.triggerGATE) { set_count(thisctr, thisctr.inlatch); if (thisctr.count_binary==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; } thisctr.null_count=0; set_OUT(thisctr,0); if (thisctr.write_state==MSByte_multiple) { BX_ERROR(("Undefined behavior when loading a half loaded count.")); } } else { decrement(thisctr); if (!thisctr.OUTpin) { if (thisctr.count_binary==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; } if (thisctr.count==0) { set_OUT(thisctr,1); } } else { thisctr.next_change_time=0; } } } else { thisctr.next_change_time=0; //default to 0. } thisctr.triggerGATE=0; break; case 2: if (thisctr.count_written) { if (thisctr.triggerGATE || thisctr.first_pass) { set_count(thisctr, thisctr.inlatch); thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; thisctr.null_count=0; if (thisctr.inlatch==1) { BX_ERROR(("ERROR: count of 1 is invalid in pit mode 2.")); } if (!thisctr.OUTpin) { set_OUT(thisctr,1); } if (thisctr.write_state==MSByte_multiple) { BX_ERROR(("Undefined behavior when loading a half loaded count.")); } thisctr.first_pass=0; } else { if (thisctr.GATE) { decrement(thisctr); thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF; if (thisctr.count==1) { thisctr.next_change_time=1; set_OUT(thisctr,0); thisctr.first_pass=1; } } else { thisctr.next_change_time=0; } } } else { thisctr.next_change_time=0; } thisctr.triggerGATE=0; break; case 3: if (thisctr.count_written) { if ((thisctr.triggerGATE || thisctr.first_pass || thisctr.state_bit_2) && thisctr.GATE) { set_count(thisctr, thisctr.inlatch & 0xFFFE); thisctr.state_bit_1=thisctr.inlatch & 0x1; if (!thisctr.OUTpin || !thisctr.state_bit_1) { if (((thisctr.count_binary/2)-1)==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF; } } else { if ((thisctr.count_binary/2)==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF; } } thisctr.null_count=0; if (thisctr.inlatch==1) { BX_ERROR(("Count of 1 is invalid in pit mode 3.")); } if (!thisctr.OUTpin) { set_OUT(thisctr,1); } else if (thisctr.OUTpin && !thisctr.first_pass) { set_OUT(thisctr,0); } if (thisctr.write_state==MSByte_multiple) { BX_ERROR(("Undefined behavior when loading a half loaded count.")); } thisctr.state_bit_2=0; thisctr.first_pass=0; } else { if (thisctr.GATE) { decrement(thisctr); decrement(thisctr); if (!thisctr.OUTpin || !thisctr.state_bit_1) { thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF; } else { thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF; } if (thisctr.count==0) { thisctr.state_bit_2=1; thisctr.next_change_time=1; } if ((thisctr.count==2) && (!thisctr.OUTpin || !thisctr.state_bit_1)) { thisctr.state_bit_2=1; thisctr.next_change_time=1; } } else { thisctr.next_change_time=0; } } } else { thisctr.next_change_time=0; } thisctr.triggerGATE=0; break; case 4: if (thisctr.count_written) { if (!thisctr.OUTpin) { set_OUT(thisctr,1); } if (thisctr.null_count) { set_count(thisctr, thisctr.inlatch); if (thisctr.GATE) { if (thisctr.count_binary==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; } } else { thisctr.next_change_time=0; } thisctr.null_count=0; if (thisctr.write_state==MSByte_multiple) { BX_ERROR(("Undefined behavior when loading a half loaded count.")); } thisctr.first_pass=1; } else { if (thisctr.GATE) { decrement(thisctr); if (thisctr.first_pass) { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; if (!thisctr.count) { set_OUT(thisctr,0); thisctr.next_change_time=1; thisctr.first_pass=0; } } else { thisctr.next_change_time=0; } } else { thisctr.next_change_time=0; } } } else { thisctr.next_change_time=0; } thisctr.triggerGATE=0; break; case 5: if (thisctr.count_written) { if (!thisctr.OUTpin) { set_OUT(thisctr,1); } if (thisctr.triggerGATE) { set_count(thisctr, thisctr.inlatch); if (thisctr.count_binary==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; } thisctr.null_count=0; if (thisctr.write_state==MSByte_multiple) { BX_ERROR(("Undefined behavior when loading a half loaded count.")); } thisctr.first_pass=1; } else { decrement(thisctr); if (thisctr.first_pass) { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; if (!thisctr.count) { set_OUT(thisctr,0); thisctr.next_change_time=1; thisctr.first_pass=0; } } else { thisctr.next_change_time=0; } } } else { thisctr.next_change_time=0; } thisctr.triggerGATE=0; break; default: BX_ERROR(("Mode not implemented.")); thisctr.next_change_time=0; thisctr.triggerGATE=0; break; } } } void pit_82C54::clock_all(Bit32u cycles) { BX_DEBUG(("clock_all: cycles=%d",cycles)); clock_multiple(0,cycles); clock_multiple(1,cycles); clock_multiple(2,cycles); } Bit8u pit_82C54::read(Bit8u address) { if (address>MAX_ADDRESS) { BX_ERROR(("Counter address incorrect in data read.")); } else if (address==CONTROL_ADDRESS) { BX_DEBUG(("PIT Read: Control Word Register.")); //Read from control word register; /* This might be okay. If so, 0 seems the most logical * return value from looking at the docs. */ BX_ERROR(("Read from control word register not defined.")); return 0; } else { //Read from a counter; BX_DEBUG(("PIT Read: Counter %d.",address)); counter_type &thisctr=counter[address]; if (thisctr.status_latched) { //Latched Status Read; if (thisctr.count_MSB_latched && (thisctr.read_state==MSByte_multiple)) { BX_ERROR(("Undefined output when status latched and count half read.")); } else { thisctr.status_latched=0; return thisctr.status_latch; } } else { //Latched Count Read; if (thisctr.count_LSB_latched) { //Read Least Significant Byte; if (thisctr.read_state==LSByte_multiple) { BX_DEBUG(("Setting read_state to MSB_mult")); thisctr.read_state=MSByte_multiple; } thisctr.count_LSB_latched=0; return (thisctr.outlatch & 0xFF); } else if (thisctr.count_MSB_latched) { //Read Most Significant Byte; if (thisctr.read_state==MSByte_multiple) { BX_DEBUG(("Setting read_state to LSB_mult")); thisctr.read_state=LSByte_multiple; } thisctr.count_MSB_latched=0; return ((thisctr.outlatch>>8) & 0xFF); } else { //Unlatched Count Read; if (!(thisctr.read_state & 0x1)) { //Read Least Significant Byte; if (thisctr.read_state==LSByte_multiple) { thisctr.read_state=MSByte_multiple; BX_DEBUG(("Setting read_state to MSB_mult")); } return (thisctr.count & 0xFF); } else { //Read Most Significant Byte; if (thisctr.read_state==MSByte_multiple) { BX_DEBUG(("Setting read_state to LSB_mult")); thisctr.read_state=LSByte_multiple; } return ((thisctr.count>>8) & 0xFF); } } } } //Should only get here on errors; return 0; } void pit_82C54::write(Bit8u address, Bit8u data) { if (address>MAX_ADDRESS) { BX_ERROR(("Counter address incorrect in data write.")); } else if (address==CONTROL_ADDRESS) { Bit8u SC, RW, M, BCD; controlword=data; BX_DEBUG(("Control Word Write.")); SC = (controlword>>6) & 0x3; RW = (controlword>>4) & 0x3; M = (controlword>>1) & 0x7; BCD = controlword & 0x1; if (SC == 3) { //READ_BACK command; int i; BX_DEBUG(("READ_BACK command.")); for(i=0;i<=MAX_COUNTER;i++) { if ((M>>i) & 0x1) { //If we are using this counter; counter_type &thisctr=counter[i]; if (!((controlword>>5) & 1)) { //Latch Count; latch_counter(thisctr); } if (!((controlword>>4) & 1)) { //Latch Status; if (thisctr.status_latched) { //Do nothing because latched status has not been read.; } else { thisctr.status_latch= ((thisctr.OUTpin & 0x1) << 7) | ((thisctr.null_count & 0x1) << 6) | ((thisctr.rw_mode & 0x3) << 4) | ((thisctr.mode & 0x7) << 1) | (thisctr.bcd_mode&0x1); thisctr.status_latched=1; } } } } } else { counter_type &thisctr = counter[SC]; if (!RW) { //Counter Latch command; BX_DEBUG(("Counter Latch command. SC=%d",SC)); latch_counter(thisctr); } else { //Counter Program Command; BX_DEBUG(("Counter Program command. SC=%d, RW=%d, M=%d, BCD=%d",SC,RW,M,BCD)); thisctr.null_count=1; thisctr.count_LSB_latched=0; thisctr.count_MSB_latched=0; thisctr.status_latched=0; thisctr.inlatch=0; thisctr.count_written=0; thisctr.first_pass=1; thisctr.rw_mode=RW; thisctr.bcd_mode=(BCD > 0); thisctr.mode=M; switch(RW) { case 0x1: BX_DEBUG(("Setting read_state to LSB")); thisctr.read_state=LSByte; thisctr.write_state=LSByte; break; case 0x2: BX_DEBUG(("Setting read_state to MSB")); thisctr.read_state=MSByte; thisctr.write_state=MSByte; break; case 0x3: BX_DEBUG(("Setting read_state to LSB_mult")); thisctr.read_state=LSByte_multiple; thisctr.write_state=LSByte_multiple; break; default: BX_ERROR(("RW field invalid in control word write.")); break; } //All modes except mode 0 have initial output of 1.; if (M) { set_OUT(thisctr, 1); } else { set_OUT(thisctr, 0); } thisctr.next_change_time=0; } } } else { //Write to counter initial value. counter_type &thisctr = counter[address]; BX_DEBUG(("Write Initial Count: counter=%d, count=%d",address,data)); switch(thisctr.write_state) { case LSByte_multiple: thisctr.inlatch = data; thisctr.write_state = MSByte_multiple; break; case LSByte: thisctr.inlatch = data; thisctr.count_written = 1; break; case MSByte_multiple: thisctr.write_state = LSByte_multiple; thisctr.inlatch |= (data << 8); thisctr.count_written = 1; break; case MSByte: thisctr.inlatch = (data << 8); thisctr.count_written = 1; break; default: BX_ERROR(("write counter in invalid write state.")); break; } if (thisctr.count_written && thisctr.write_state != MSByte_multiple) { thisctr.null_count = 1; set_count(thisctr, thisctr.inlatch); } switch(thisctr.mode) { case 0: if (thisctr.write_state==MSByte_multiple) { set_OUT(thisctr,0); } thisctr.next_change_time=1; break; case 1: if (thisctr.triggerGATE) { //for initial writes, if already saw trigger. thisctr.next_change_time=1; } //Otherwise, no change. break; case 6: case 2: thisctr.next_change_time=1; //FIXME: this could be loosened. break; case 7: case 3: thisctr.next_change_time=1; //FIXME: this could be loosened. break; case 4: thisctr.next_change_time=1; break; case 5: if (thisctr.triggerGATE) { //for initial writes, if already saw trigger. thisctr.next_change_time=1; } //Otherwise, no change. break; } } } void pit_82C54::set_GATE(Bit8u cnum, bx_bool data) { if (cnum>MAX_COUNTER) { BX_ERROR(("Counter number incorrect in 82C54 set_GATE")); } else { counter_type &thisctr = counter[cnum]; if (!((thisctr.GATE&&data) || (!(thisctr.GATE||data)))) { BX_DEBUG(("Changing GATE %d to: %d",cnum,data)); thisctr.GATE=data; if (thisctr.GATE) { thisctr.triggerGATE=1; } switch(thisctr.mode) { case 0: if (data && thisctr.count_written) { if (thisctr.null_count) { thisctr.next_change_time=1; } else { if ((!thisctr.OUTpin) && (thisctr.write_state!=MSByte_multiple)) { if (thisctr.count_binary==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; } } else { thisctr.next_change_time=0; } } } else { if (thisctr.null_count) { thisctr.next_change_time=1; } else { thisctr.next_change_time=0; } } break; case 1: if (data && thisctr.count_written) { //only triggers cause a change. thisctr.next_change_time=1; } break; case 2: if (!data) { set_OUT(thisctr,1); thisctr.next_change_time=0; } else { if (thisctr.count_written) { thisctr.next_change_time=1; } else { thisctr.next_change_time=0; } } break; case 3: if (!data) { set_OUT(thisctr,1); thisctr.first_pass=1; thisctr.next_change_time=0; } else { if (thisctr.count_written) { thisctr.next_change_time=1; } else { thisctr.next_change_time=0; } } break; case 4: if (!thisctr.OUTpin || thisctr.null_count) { thisctr.next_change_time=1; } else { if (data && thisctr.count_written) { if (thisctr.first_pass) { if (thisctr.count_binary==0) { thisctr.next_change_time=1; } else { thisctr.next_change_time=thisctr.count_binary & 0xFFFF; } } else { thisctr.next_change_time=0; } } else { thisctr.next_change_time=0; } } break; case 5: if (data && thisctr.count_written) { //only triggers cause a change. thisctr.next_change_time=1; } break; default: break; } } } } bx_bool pit_82C54::read_OUT(Bit8u cnum) { if (cnum>MAX_COUNTER) { BX_ERROR(("Counter number incorrect in 82C54 read_OUT")); return 0; } return counter[cnum].OUTpin; } bx_bool pit_82C54::read_GATE(Bit8u cnum) { if (cnum>MAX_COUNTER) { BX_ERROR(("Counter number incorrect in 82C54 read_GATE")); return 0; } return counter[cnum].GATE; } Bit32u pit_82C54::get_clock_event_time(Bit8u cnum) { if (cnum>MAX_COUNTER) { BX_ERROR(("Counter number incorrect in 82C54 read_GATE")); return 0; } return counter[cnum].next_change_time; } Bit32u pit_82C54::get_next_event_time(void) { Bit32u time0=get_clock_event_time(0); Bit32u time1=get_clock_event_time(1); Bit32u time2=get_clock_event_time(2); Bit32u out=time0; if (time1 && (time1 bx_cmos_c *theCmosDevice = NULL; // CMOS register definitions from Ralf Brown's interrupt list v6.1, in a file // called cmos.lst. In cases where there are multiple uses for a given // register in the interrupt list, I only listed the purpose that Bochs // actually uses it for, but I wrote "alternatives" next to it. #define REG_SEC 0x00 #define REG_SEC_ALARM 0x01 #define REG_MIN 0x02 #define REG_MIN_ALARM 0x03 #define REG_HOUR 0x04 #define REG_HOUR_ALARM 0x05 #define REG_WEEK_DAY 0x06 #define REG_MONTH_DAY 0x07 #define REG_MONTH 0x08 #define REG_YEAR 0x09 #define REG_STAT_A 0x0a #define REG_STAT_B 0x0b #define REG_STAT_C 0x0c #define REG_STAT_D 0x0d #define REG_DIAGNOSTIC_STATUS 0x0e /* alternatives */ #define REG_SHUTDOWN_STATUS 0x0f #define REG_EQUIPMENT_BYTE 0x14 #define REG_CSUM_HIGH 0x2e #define REG_CSUM_LOW 0x2f #define REG_IBM_CENTURY_BYTE 0x32 /* alternatives */ #define REG_IBM_PS2_CENTURY_BYTE 0x37 /* alternatives */ // Bochs CMOS map // // Idx Len Description // 0x10 1 floppy drive types // 0x11 1 configuration bits // 0x12 1 harddisk types // 0x13 1 advanced configuration bits // 0x15 2 base memory in 1k // 0x17 2 memory size above 1M in 1k // 0x19 2 extended harddisk types // 0x1b 9 harddisk configuration (hd0) // 0x24 9 harddisk configuration (hd1) // 0x2d 1 boot sequence (fd/hd) // 0x30 2 memory size above 1M in 1k // 0x34 2 memory size above 16M in 64k // 0x38 1 eltorito boot sequence (#3) + bootsig check // 0x39 2 ata translation policy (ata0...ata3) // 0x3d 1 eltorito boot sequence (#1 + #2) // // Qemu CMOS map // // Idx Len Description // 0x5b 3 extra memory above 4GB // 0x5f 1 number of processors Bit8u bcd_to_bin(Bit8u value, bx_bool is_binary) { if (is_binary) return value; else return ((value >> 4) * 10) + (value & 0x0f); } Bit8u bin_to_bcd(Bit8u value, bx_bool is_binary) { if (is_binary) return value; else return ((value / 10) << 4) | (value % 10); } int libcmos_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theCmosDevice = new bx_cmos_c(); bx_devices.pluginCmosDevice = theCmosDevice; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theCmosDevice, BX_PLUGIN_CMOS); return 0; // Success } else { return -1; } } void libcmos_LTX_plugin_fini(void) { if (theCmosDevice != NULL) { delete theCmosDevice; theCmosDevice = NULL; } } bx_cmos_c::bx_cmos_c(void) { put("CMOS"); memset(&s, 0, sizeof(s)); s.periodic_timer_index = BX_NULL_TIMER_HANDLE; s.one_second_timer_index = BX_NULL_TIMER_HANDLE; s.uip_timer_index = BX_NULL_TIMER_HANDLE; } bx_cmos_c::~bx_cmos_c(void) { save_image(); char *tmptime; if ((tmptime = strdup(ctime(&(BX_CMOS_THIS s.timeval)))) != NULL) { tmptime[strlen(tmptime)-1]='\0'; BX_INFO(("Last time is %u (%s)", (unsigned) get_timeval(), tmptime)); free(tmptime); } SIM->get_bochs_root()->remove("cmos"); BX_DEBUG(("Exit")); } void bx_cmos_c::init(void) { BX_DEBUG(("Init $Id: cmos.cc 11346 2012-08-19 08:16:20Z vruppert $")); // CMOS RAM & RTC DEV_register_ioread_handler(this, read_handler, 0x0070, "CMOS RAM", 1); DEV_register_ioread_handler(this, read_handler, 0x0071, "CMOS RAM", 1); DEV_register_iowrite_handler(this, write_handler, 0x0070, "CMOS RAM", 1); DEV_register_iowrite_handler(this, write_handler, 0x0071, "CMOS RAM", 1); DEV_register_irq(8, "CMOS RTC"); int clock_sync = SIM->get_param_enum(BXPN_CLOCK_SYNC)->get(); BX_CMOS_THIS s.rtc_sync = ((clock_sync == BX_CLOCK_SYNC_REALTIME) || (clock_sync == BX_CLOCK_SYNC_BOTH)) && SIM->get_param_bool(BXPN_CLOCK_RTC_SYNC)->get(); if (BX_CMOS_THIS s.periodic_timer_index == BX_NULL_TIMER_HANDLE) { BX_CMOS_THIS s.periodic_timer_index = DEV_register_timer(this, periodic_timer_handler, 1000000, 1,0, "cmos"); // continuous, not-active } if (BX_CMOS_THIS s.one_second_timer_index == BX_NULL_TIMER_HANDLE) { if (BX_CMOS_THIS s.rtc_sync) { BX_CMOS_THIS s.one_second_timer_index = bx_virt_timer.register_timer(this, one_second_timer_handler, 1000000, 1, 0, "cmos"); // continuous, not-active } else { BX_CMOS_THIS s.one_second_timer_index = DEV_register_timer(this, one_second_timer_handler, 1000000, 1,0, "cmos"); // continuous, not-active } } if (BX_CMOS_THIS s.uip_timer_index == BX_NULL_TIMER_HANDLE) { BX_CMOS_THIS s.uip_timer_index = DEV_register_timer(this, uip_timer_handler, 244, 0, 0, "cmos"); // one-shot, not-active } if (SIM->get_param_num(BXPN_CLOCK_TIME0)->get() == BX_CLOCK_TIME0_LOCAL) { BX_INFO(("Using local time for initial clock")); BX_CMOS_THIS s.timeval = time(NULL); } else if (SIM->get_param_num(BXPN_CLOCK_TIME0)->get() == BX_CLOCK_TIME0_UTC) { bx_bool utc_ok = 0; BX_INFO(("Using utc time for initial clock")); BX_CMOS_THIS s.timeval = time(NULL); #if BX_HAVE_GMTIME #if BX_HAVE_MKTIME struct tm *utc_holder = gmtime(&BX_CMOS_THIS s.timeval); utc_holder->tm_isdst = -1; utc_ok = 1; BX_CMOS_THIS s.timeval = mktime(utc_holder); #elif BX_HAVE_TIMELOCAL struct tm *utc_holder = gmtime(&BX_CMOS_THIS s.timeval); utc_holder->tm_isdst = 0; // XXX Is this correct??? utc_ok = 1; BX_CMOS_THIS s.timeval = timelocal(utc_holder); #endif //BX_HAVE_MKTIME #endif //BX_HAVE_GMTIME if (!utc_ok) { BX_ERROR(("UTC time is not supported on your platform. Using current time(NULL)")); } } else { BX_INFO(("Using specified time for initial clock")); BX_CMOS_THIS s.timeval = SIM->get_param_num(BXPN_CLOCK_TIME0)->get(); } // load CMOS from image file if requested. if (SIM->get_param_bool(BXPN_CMOSIMAGE_ENABLED)->get()) { int fd, ret; struct stat stat_buf; fd = open(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr(), O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (fd < 0) { BX_PANIC(("trying to open cmos image file '%s'", SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr())); } ret = fstat(fd, &stat_buf); if (ret) { BX_PANIC(("CMOS: could not fstat() image file.")); } if ((stat_buf.st_size != 64) && (stat_buf.st_size != 128)) { BX_PANIC(("CMOS: image file size must be 64 or 128")); } ret = ::read(fd, (bx_ptr_t) BX_CMOS_THIS s.reg, (unsigned)stat_buf.st_size); if (ret != stat_buf.st_size) { BX_PANIC(("CMOS: error reading cmos file.")); } close(fd); BX_INFO(("successfuly read from image file '%s'.", SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr())); BX_CMOS_THIS s.rtc_mode_12hour = ((BX_CMOS_THIS s.reg[REG_STAT_B] & 0x02) == 0); BX_CMOS_THIS s.rtc_mode_binary = ((BX_CMOS_THIS s.reg[REG_STAT_B] & 0x04) != 0); if (SIM->get_param_bool(BXPN_CMOSIMAGE_RTC_INIT)->get()) { update_timeval(); } else { update_clock(); } } else { // CMOS values generated BX_CMOS_THIS s.reg[REG_STAT_A] = 0x26; BX_CMOS_THIS s.reg[REG_STAT_B] = 0x02; BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00; BX_CMOS_THIS s.reg[REG_STAT_D] = 0x80; #if BX_SUPPORT_FPU == 1 BX_CMOS_THIS s.reg[REG_EQUIPMENT_BYTE] |= 0x02; #endif BX_CMOS_THIS s.rtc_mode_12hour = 0; BX_CMOS_THIS s.rtc_mode_binary = 0; update_clock(); } char *tmptime; while((tmptime = strdup(ctime(&(BX_CMOS_THIS s.timeval)))) == NULL) { BX_PANIC(("Out of memory.")); } tmptime[strlen(tmptime)-1]='\0'; BX_INFO(("Setting initial clock to: %s (time0=%u)", tmptime, (Bit32u)BX_CMOS_THIS s.timeval)); free(tmptime); BX_CMOS_THIS s.timeval_change = 0; #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("cmos", this); #endif } void bx_cmos_c::reset(unsigned type) { BX_CMOS_THIS s.cmos_mem_address = 0; // RESET affects the following registers: // CRA: no effects // CRB: bits 4,5,6 forced to 0 // CRC: bits 4,5,6,7 forced to 0 // CRD: no effects BX_CMOS_THIS s.reg[REG_STAT_B] &= 0x8f; BX_CMOS_THIS s.reg[REG_STAT_C] = 0; // One second timer for updating clock & alarm functions if (BX_CMOS_THIS s.rtc_sync) { bx_virt_timer.activate_timer(BX_CMOS_THIS s.one_second_timer_index, 1000000, 1); } else { bx_pc_system.activate_timer(BX_CMOS_THIS s.one_second_timer_index, 1000000, 1); } // handle periodic interrupt rate select BX_CMOS_THIS CRA_change(); } void bx_cmos_c::save_image(void) { int fd, ret; // save CMOS to image file if requested. if (SIM->get_param_bool(BXPN_CMOSIMAGE_ENABLED)->get()) { fd = open(SIM->get_param_string(BXPN_CMOSIMAGE_PATH)->getptr(), O_WRONLY #ifdef O_BINARY | O_BINARY #endif ); ret = ::write(fd, (bx_ptr_t) BX_CMOS_THIS s.reg, 128); if (ret != 128) { BX_PANIC(("CMOS: error writing cmos file.")); } close(fd); } } void bx_cmos_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "cmos", "CMOS State"); BXRS_HEX_PARAM_FIELD(list, mem_address, BX_CMOS_THIS s.cmos_mem_address); bx_list_c *ram = new bx_list_c(list, "ram"); for (unsigned i=0; i<128; i++) { char name[6]; sprintf(name, "0x%02x", i); new bx_shadow_num_c(ram, name, &BX_CMOS_THIS s.reg[i], BASE_HEX); } } void bx_cmos_c::after_restore_state(void) { BX_CMOS_THIS s.rtc_mode_12hour = ((BX_CMOS_THIS s.reg[REG_STAT_B] & 0x02) == 0); BX_CMOS_THIS s.rtc_mode_binary = ((BX_CMOS_THIS s.reg[REG_STAT_B] & 0x04) != 0); BX_CMOS_THIS update_timeval(); BX_CMOS_THIS CRA_change(); } void bx_cmos_c::CRA_change(void) { Bit8u nibble, dcc; // Periodic Interrupt timer nibble = BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f; dcc = (BX_CMOS_THIS s.reg[REG_STAT_A] >> 4) & 0x07; if ((nibble == 0) || ((dcc & 0x06) == 0)) { // No Periodic Interrupt Rate when 0, deactivate timer bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index); BX_CMOS_THIS s.periodic_interval_usec = (Bit32u) -1; // max value } else { // values 0001b and 0010b are the same as 1000b and 1001b if (nibble <= 2) nibble += 7; BX_CMOS_THIS s.periodic_interval_usec = (unsigned) (1000000.0L / (32768.0L / (1 << (nibble - 1)))); // if Periodic Interrupt Enable bit set, activate timer if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40) bx_pc_system.activate_timer(BX_CMOS_THIS s.periodic_timer_index, BX_CMOS_THIS s.periodic_interval_usec, 1); else bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index); } } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_cmos_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_CMOS_SMF bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_cmos_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif Bit8u ret8; BX_DEBUG(("CMOS read of CMOS register 0x%02x", (unsigned) BX_CMOS_THIS s.cmos_mem_address)); switch (address) { case 0x0070: // this register is write-only on most machines BX_DEBUG(("read of index port 0x70. returning 0xff")); return(0xff); case 0x0071: ret8 = BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address]; // all bits of Register C are cleared after a read occurs. if (BX_CMOS_THIS s.cmos_mem_address == REG_STAT_C) { BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00; DEV_pic_lower_irq(8); } return(ret8); default: BX_PANIC(("unsupported cmos read, address=0x%04x!", (unsigned) address)); return(0); } } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_cmos_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_CMOS_SMF bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_CMOS_SMF BX_DEBUG(("CMOS write to address: 0x%04x = 0x%02x", address, value)); switch (address) { case 0x0070: BX_CMOS_THIS s.cmos_mem_address = value & 0x7F; break; case 0x0071: switch (BX_CMOS_THIS s.cmos_mem_address) { case REG_SEC_ALARM: // seconds alarm case REG_MIN_ALARM: // minutes alarm case REG_HOUR_ALARM: // hours alarm BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value; BX_DEBUG(("alarm time changed to %02x:%02x:%02x", BX_CMOS_THIS s.reg[REG_HOUR_ALARM], BX_CMOS_THIS s.reg[REG_MIN_ALARM], BX_CMOS_THIS s.reg[REG_SEC_ALARM])); break; case REG_SEC: // seconds case REG_MIN: // minutes case REG_HOUR: // hours case REG_WEEK_DAY: // day of the week case REG_MONTH_DAY: // day of the month case REG_MONTH: // month case REG_YEAR: // year case REG_IBM_CENTURY_BYTE: // century case REG_IBM_PS2_CENTURY_BYTE: // century (PS/2) BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value; if (BX_CMOS_THIS s.cmos_mem_address == REG_IBM_PS2_CENTURY_BYTE) { BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] = value; } if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x80) { BX_CMOS_THIS s.timeval_change = 1; } else { update_timeval(); } break; case REG_STAT_A: // Control Register A // bit 7: Update in Progress (read-only) // 1 = signifies time registers will be updated within 244us // 0 = time registers will not occur before 244us // note: this bit reads 0 when CRB bit 7 is 1 // bit 6..4: Divider Chain Control // 000 oscillator disabled // 001 oscillator disabled // 010 Normal operation // 011 TEST // 100 TEST // 101 TEST // 110 Divider Chain RESET // 111 Divider Chain RESET // bit 3..0: Periodic Interrupt Rate Select // 0000 None // 0001 3.90625 ms // 0010 7.8125 ms // 0011 122.070 us // 0100 244.141 us // 0101 488.281 us // 0110 976.562 us // 0111 1.953125 ms // 1000 3.90625 ms // 1001 7.8125 ms // 1010 15.625 ms // 1011 31.25 ms // 1100 62.5 ms // 1101 125 ms // 1110 250 ms // 1111 500 ms unsigned dcc; dcc = (value >> 4) & 0x07; if ((dcc & 0x06) == 0x06) { BX_INFO(("CRA: divider chain RESET")); } else if (dcc > 0x02) { BX_PANIC(("CRA: divider chain control 0x%02x", dcc)); } BX_CMOS_THIS s.reg[REG_STAT_A] &= 0x80; BX_CMOS_THIS s.reg[REG_STAT_A] |= (value & 0x7f); BX_CMOS_THIS CRA_change(); break; case REG_STAT_B: // Control Register B // bit 0: Daylight Savings Enable // 1 = enable daylight savings // 0 = disable daylight savings // bit 1: 24/12 hour mode // 1 = 24 hour format // 0 = 12 hour format // bit 2: Data Mode // 1 = binary format // 0 = BCD format // bit 3: "square wave enable" // Not supported and always read as 0 // bit 4: Update Ended Interrupt Enable // 1 = enable generation of update ended interrupt // 0 = disable // bit 5: Alarm Interrupt Enable // 1 = enable generation of alarm interrupt // 0 = disable // bit 6: Periodic Interrupt Enable // 1 = enable generation of periodic interrupt // 0 = disable // bit 7: Set mode // 1 = user copy of time is "frozen" allowing time registers // to be accessed without regard for an occurance of an update // 0 = time updates occur normally if (value & 0x01) BX_ERROR(("write status reg B, daylight savings unsupported")); value &= 0xf7; // bit3 always 0 // Note: setting bit 7 clears bit 4 if (value & 0x80) value &= 0xef; unsigned prev_CRB; prev_CRB = BX_CMOS_THIS s.reg[REG_STAT_B]; BX_CMOS_THIS s.reg[REG_STAT_B] = value; if ((prev_CRB & 0x02) != (value & 0x02)) { BX_CMOS_THIS s.rtc_mode_12hour = ((value & 0x02) == 0); update_clock(); } if ((prev_CRB & 0x04) != (value & 0x04)) { BX_CMOS_THIS s.rtc_mode_binary = ((value & 0x04) != 0); update_clock(); } if ((prev_CRB & 0x40) != (value & 0x40)) { // Periodic Interrupt Enabled changed if (prev_CRB & 0x40) { // transition from 1 to 0, deactivate timer bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index); } else { // transition from 0 to 1 // if rate select is not 0, activate timer if ((BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f) != 0) { bx_pc_system.activate_timer( BX_CMOS_THIS s.periodic_timer_index, BX_CMOS_THIS s.periodic_interval_usec, 1); } } } if ((prev_CRB >= 0x80) && (value < 0x80) && BX_CMOS_THIS s.timeval_change) { update_timeval(); BX_CMOS_THIS s.timeval_change = 0; } break; case REG_STAT_C: // Control Register C case REG_STAT_D: // Control Register D BX_ERROR(("write to control register 0x%02x ignored (read-only)", BX_CMOS_THIS s.cmos_mem_address)); break; case REG_DIAGNOSTIC_STATUS: BX_DEBUG(("write register 0x0e: 0x%02x", value)); BX_CMOS_THIS s.reg[REG_DIAGNOSTIC_STATUS] = value; break; case REG_SHUTDOWN_STATUS: switch (value) { case 0x00: /* proceed with normal POST (soft reset) */ BX_DEBUG(("Reg 0Fh(00): shutdown action = normal POST")); break; case 0x01: /* shutdown after memory size check */ BX_DEBUG(("Reg 0Fh(01): request to change shutdown action" " to shutdown after memory size check")); break; case 0x02: /* shutdown after successful memory test */ BX_DEBUG(("Reg 0Fh(02): request to change shutdown action" " to shutdown after successful memory test")); break; case 0x03: /* shutdown after failed memory test */ BX_DEBUG(("Reg 0Fh(03): request to change shutdown action" " to shutdown after successful memory test")); break; case 0x04: /* jump to disk bootstrap routine */ BX_DEBUG(("Reg 0Fh(04): request to change shutdown action " "to jump to disk bootstrap routine.")); break; case 0x05: /* flush keyboard (issue EOI) and jump via 40h:0067h */ BX_DEBUG(("Reg 0Fh(05): request to change shutdown action " "to flush keyboard (issue EOI) and jump via 40h:0067h.")); break; case 0x06: BX_DEBUG(("Reg 0Fh(06): Shutdown after memory test !")); break; case 0x07: /* reset (after failed test in virtual mode) */ BX_DEBUG(("Reg 0Fh(07): request to change shutdown action " "to reset (after failed test in virtual mode).")); break; case 0x08: /* used by POST during protected-mode RAM test (return to POST) */ BX_DEBUG(("Reg 0Fh(08): request to change shutdown action " "to return to POST (used by POST during protected-mode RAM test).")); break; case 0x09: /* return to BIOS extended memory block move (interrupt 15h, func 87h was in progress) */ BX_DEBUG(("Reg 0Fh(09): request to change shutdown action " "to return to BIOS extended memory block move.")); break; case 0x0a: /* jump to DWORD pointer at 40:67 */ BX_DEBUG(("Reg 0Fh(0a): request to change shutdown action" " to jump to DWORD at 40:67")); break; case 0x0b: /* iret to DWORD pointer at 40:67 */ BX_DEBUG(("Reg 0Fh(0b): request to change shutdown action" " to iret to DWORD at 40:67")); break; case 0x0c: /* retf to DWORD pointer at 40:67 */ BX_DEBUG(("Reg 0Fh(0c): request to change shutdown action" " to retf to DWORD at 40:67")); break; default: BX_ERROR(("unsupported shutdown status: 0x%02x!", value)); } BX_CMOS_THIS s.reg[REG_SHUTDOWN_STATUS] = value; break; default: BX_DEBUG(("write reg 0x%02x: value = 0x%02x", BX_CMOS_THIS s.cmos_mem_address, value)); BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value; } break; } } void bx_cmos_c::checksum_cmos(void) { Bit16u sum = 0; for (unsigned i=0x10; i<=0x2d; i++) sum += BX_CMOS_THIS s.reg[i]; BX_CMOS_THIS s.reg[REG_CSUM_HIGH] = (sum >> 8) & 0xff; /* checksum high */ BX_CMOS_THIS s.reg[REG_CSUM_LOW] = (sum & 0xff); /* checksum low */ } void bx_cmos_c::periodic_timer_handler(void *this_ptr) { bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; class_ptr->periodic_timer(); } void bx_cmos_c::periodic_timer() { // if periodic interrupts are enabled, trip IRQ 8, and // update status register C if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40) { BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xc0; // Interrupt Request, Periodic Int DEV_pic_raise_irq(8); } } void bx_cmos_c::one_second_timer_handler(void *this_ptr) { bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; class_ptr->one_second_timer(); } void bx_cmos_c::one_second_timer() { // divider chain reset - RTC stopped if ((BX_CMOS_THIS s.reg[REG_STAT_A] & 0x60) == 0x60) return; // update internal time/date buffer BX_CMOS_THIS s.timeval++; // Dont update CMOS user copy of time/date if CRB bit7 is 1 // Nothing else do to if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x80) return; BX_CMOS_THIS s.reg[REG_STAT_A] |= 0x80; // set UIP bit // UIP timer for updating clock & alarm functions bx_pc_system.activate_timer(BX_CMOS_THIS s.uip_timer_index, 244, 0); } void bx_cmos_c::uip_timer_handler(void *this_ptr) { bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr; class_ptr->uip_timer(); } void bx_cmos_c::uip_timer() { update_clock(); // if update interrupts are enabled, trip IRQ 8, and // update status register C if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x10) { BX_CMOS_THIS s.reg[REG_STAT_C] |= 0x90; // Interrupt Request, Update Ended DEV_pic_raise_irq(8); } // compare CMOS user copy of time/date to alarm time/date here if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x20) { // Alarm interrupts enabled bx_bool alarm_match = 1; if ((BX_CMOS_THIS s.reg[REG_SEC_ALARM] & 0xc0) != 0xc0) { // seconds alarm not in dont care mode if (BX_CMOS_THIS s.reg[REG_SEC] != BX_CMOS_THIS s.reg[REG_SEC_ALARM]) alarm_match = 0; } if ((BX_CMOS_THIS s.reg[REG_MIN_ALARM] & 0xc0) != 0xc0) { // minutes alarm not in dont care mode if (BX_CMOS_THIS s.reg[REG_MIN] != BX_CMOS_THIS s.reg[REG_MIN_ALARM]) alarm_match = 0; } if ((BX_CMOS_THIS s.reg[REG_HOUR_ALARM] & 0xc0) != 0xc0) { // hours alarm not in dont care mode if (BX_CMOS_THIS s.reg[REG_HOUR] != BX_CMOS_THIS s.reg[REG_HOUR_ALARM]) alarm_match = 0; } if (alarm_match) { BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xa0; // Interrupt Request, Alarm Int DEV_pic_raise_irq(8); } } BX_CMOS_THIS s.reg[REG_STAT_A] &= 0x7f; // clear UIP bit } void bx_cmos_c::update_clock() { struct tm *time_calendar; unsigned year, month, day, century; Bit8u val_bcd, hour; time_calendar = localtime(& BX_CMOS_THIS s.timeval); // update seconds BX_CMOS_THIS s.reg[REG_SEC] = bin_to_bcd(time_calendar->tm_sec, BX_CMOS_THIS s.rtc_mode_binary); // update minutes BX_CMOS_THIS s.reg[REG_MIN] = bin_to_bcd(time_calendar->tm_min, BX_CMOS_THIS s.rtc_mode_binary); // update hours if (BX_CMOS_THIS s.rtc_mode_12hour) { hour = time_calendar->tm_hour; val_bcd = (hour > 11) ? 0x80 : 0x00; if (hour > 11) hour -= 12; if (hour == 0) hour = 12; val_bcd |= bin_to_bcd(hour, BX_CMOS_THIS s.rtc_mode_binary); BX_CMOS_THIS s.reg[REG_HOUR] = val_bcd; } else { BX_CMOS_THIS s.reg[REG_HOUR] = bin_to_bcd(time_calendar->tm_hour, BX_CMOS_THIS s.rtc_mode_binary); } // update day of the week day = time_calendar->tm_wday + 1; // 0..6 to 1..7 BX_CMOS_THIS s.reg[REG_WEEK_DAY] = bin_to_bcd(day, BX_CMOS_THIS s.rtc_mode_binary); // update day of the month day = time_calendar->tm_mday; BX_CMOS_THIS s.reg[REG_MONTH_DAY] = bin_to_bcd(day, BX_CMOS_THIS s.rtc_mode_binary); // update month month = time_calendar->tm_mon + 1; BX_CMOS_THIS s.reg[REG_MONTH] = bin_to_bcd(month, BX_CMOS_THIS s.rtc_mode_binary); // update year year = time_calendar->tm_year % 100; BX_CMOS_THIS s.reg[REG_YEAR] = bin_to_bcd(year, BX_CMOS_THIS s.rtc_mode_binary); // update century century = (time_calendar->tm_year / 100) + 19; BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] = bin_to_bcd(century, BX_CMOS_THIS s.rtc_mode_binary); // Raul Hudea pointed out that some bioses also use reg 0x37 for the // century byte. Tony Heller says this is critical in getting WinXP to run. BX_CMOS_THIS s.reg[REG_IBM_PS2_CENTURY_BYTE] = BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE]; } void bx_cmos_c::update_timeval() { struct tm time_calendar; Bit8u val_bin, pm_flag; // update seconds time_calendar.tm_sec = bcd_to_bin(BX_CMOS_THIS s.reg[REG_SEC], BX_CMOS_THIS s.rtc_mode_binary); // update minutes time_calendar.tm_min = bcd_to_bin(BX_CMOS_THIS s.reg[REG_MIN], BX_CMOS_THIS s.rtc_mode_binary); // update hours if (BX_CMOS_THIS s.rtc_mode_12hour) { pm_flag = BX_CMOS_THIS s.reg[REG_HOUR] & 0x80; val_bin = bcd_to_bin(BX_CMOS_THIS s.reg[REG_HOUR] & 0x70, BX_CMOS_THIS s.rtc_mode_binary); if ((val_bin < 12) & (pm_flag > 0)) { val_bin += 12; } else if ((val_bin == 12) & (pm_flag == 0)) { val_bin = 0; } time_calendar.tm_hour = val_bin; } else { time_calendar.tm_hour = bcd_to_bin(BX_CMOS_THIS s.reg[REG_HOUR], BX_CMOS_THIS s.rtc_mode_binary); } // update day of the month time_calendar.tm_mday = bcd_to_bin(BX_CMOS_THIS s.reg[REG_MONTH_DAY], BX_CMOS_THIS s.rtc_mode_binary); // update month time_calendar.tm_mon = bcd_to_bin(BX_CMOS_THIS s.reg[REG_MONTH], BX_CMOS_THIS s.rtc_mode_binary) - 1; // update year val_bin = bcd_to_bin(BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE], BX_CMOS_THIS s.rtc_mode_binary); val_bin = (val_bin - 19) * 100; val_bin += bcd_to_bin(BX_CMOS_THIS s.reg[REG_YEAR], BX_CMOS_THIS s.rtc_mode_binary); time_calendar.tm_year = val_bin; BX_CMOS_THIS s.timeval = mktime(& time_calendar); } #if BX_DEBUGGER void bx_cmos_c::debug_dump(int argc, char **argv) { int i, j, r; dbg_printf("CMOS RTC\n\n"); dbg_printf("Index register: 0x%02x\n\n", BX_CMOS_THIS s.cmos_mem_address); r = 0; for (i=0; i<8; i++) { dbg_printf("%04x ", r); for (j=0; j<16; j++) { dbg_printf(" %02x", BX_CMOS_THIS s.reg[r++]); } dbg_printf("\n"); } if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif bochs-2.6/iodev/pit.h0000644000175000017500000000435212020641505014407 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pit.h 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef _BX_PIT_H #define _BX_PIT_H #include "bochs.h" #include "pit82c54.h" #if BX_USE_PIT_SMF # define BX_PIT_SMF static # define BX_PIT_THIS thePit-> #else # define BX_PIT_SMF # define BX_PIT_THIS this-> #endif class bx_pit_c : public bx_devmodel_c { public: bx_pit_c(); virtual ~bx_pit_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif private: static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_PIT_SMF Bit32u read(Bit32u addr, unsigned len); void write(Bit32u addr, Bit32u Value, unsigned len); #endif struct s_type { pit_82C54 timer; bx_bool speaker_data_on; bx_bool speaker_active; Bit64u last_usec; Bit32u last_next_event_time; Bit64u total_ticks; Bit64u total_usec; int timer_handle[3]; } s; static void timer_handler(void *this_ptr); BX_PIT_SMF void handle_timer(); BX_PIT_SMF bx_bool periodic(Bit32u usec_delta); BX_PIT_SMF void irq_handler(bx_bool value); BX_PIT_SMF Bit16u get_timer(int Timer); }; #endif // #ifndef _BX_PIT_H bochs-2.6/iodev/serial.cc0000644000175000017500000020473712020641505015241 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: serial.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Peter Grehan (grehan@iprg.nokia.com) coded the original version of this // serial emulation. He implemented a single 8250, and allow terminal // input/output to stdout on FreeBSD. // The current version emulates up to 4 UART 16550A with FIFO. Terminal // input/output now works on some more platforms. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #ifndef WIN32 #include #include #include #include #define closesocket(s) close(s) typedef int SOCKET; #endif #include "iodev.h" #include "serial.h" #if defined(WIN32) && !defined(FILE_FLAG_FIRST_PIPE_INSTANCE) #define FILE_FLAG_FIRST_PIPE_INSTANCE 0 #endif #if USE_RAW_SERIAL #include "serial_raw.h" #endif #define LOG_THIS theSerialDevice-> bx_serial_c *theSerialDevice = NULL; // builtin configuration handling functions void serial_init_options(void) { static const char *serial_mode_list[] = { "null", "file", "pipe", "pipe-client", "pipe-server", "term", "raw", "mouse", "socket", "socket-client", "socket-server", NULL }; char name[4], label[80], descr[120]; bx_list_c *serial = (bx_list_c*)SIM->get_param("ports.serial"); for (int i=0; iset_options(menu->SERIES_ASK); sprintf(label, "Enable serial port #%d (COM%d)", i+1, i+1); sprintf(descr, "Controls whether COM%d is installed or not", i+1); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", label, descr, (i==0)?1 : 0); // only enable the first by default sprintf(label, "I/O mode of the serial device for COM%d", i+1); bx_param_enum_c *mode = new bx_param_enum_c(menu, "mode", label, "The mode can be one these: 'null', 'file', 'pipe', 'term', 'raw', 'mouse', 'socket'", serial_mode_list, 0, 0); mode->set_ask_format("Choose I/O mode of the serial device [%s] "); sprintf(label, "Pathname of the serial device for COM%d", i+1); bx_param_filename_c *path = new bx_param_filename_c(menu, "dev", label, "The path can be a real serial device or a pty (X/Unix only)", "", BX_PATHNAME_LEN); bx_list_c *deplist = new bx_list_c(NULL); deplist->add(mode); deplist->add(path); enabled->set_dependent_list(deplist); } } Bit32s serial_options_parser(const char *context, int num_params, char *params[]) { if ((!strncmp(params[0], "com", 3)) && (strlen(params[0]) == 4)) { char tmpname[80]; int idx = params[0][3]; if ((idx < '1') || (idx > '9')) { BX_PANIC(("%s: comX directive malformed.", context)); } idx -= '0'; if (idx > BX_N_SERIAL_PORTS) { BX_PANIC(("%s: comX port number out of range.", context)); } sprintf(tmpname, "ports.serial.%d", idx); bx_list_c *base = (bx_list_c*) SIM->get_param(tmpname); for (int i=1; iset(atol(¶ms[i][8])); } else if (!strncmp(params[i], "mode=", 5)) { if (!SIM->get_param_enum("mode", base)->set_by_name(¶ms[i][5])) BX_PANIC(("%s: com%d serial port mode '%s' not available", context, idx, ¶ms[i][5])); SIM->get_param_bool("enabled", base)->set(1); } else if (!strncmp(params[i], "dev=", 4)) { SIM->get_param_string("dev", base)->set(¶ms[i][4]); SIM->get_param_bool("enabled", base)->set(1); } else { BX_ERROR(("%s: unknown parameter for com%d ignored.", context, idx)); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s serial_options_save(FILE *fp) { char pname[20]; for (int i=0; iget_param(pname); fprintf(fp, "com%d: enabled=%d", i+1, SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { fprintf(fp, ", mode=%s", SIM->get_param_enum("mode", base)->get_selected()); fprintf(fp, ", dev=\"%s\"", SIM->get_param_string("dev", base)->getptr()); } fprintf(fp, "\n"); } return 0; } // device plugin entry points int libserial_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theSerialDevice = new bx_serial_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSerialDevice, BX_PLUGIN_SERIAL); // add new configuration parameters for the config interface serial_init_options(); // register add-on options for bochsrc and command line SIM->register_addon_option("com1", serial_options_parser, serial_options_save); SIM->register_addon_option("com2", serial_options_parser, NULL); SIM->register_addon_option("com3", serial_options_parser, NULL); SIM->register_addon_option("com4", serial_options_parser, NULL); return(0); // Success } void libserial_LTX_plugin_fini(void) { char pnum[4]; SIM->unregister_addon_option("com1"); SIM->unregister_addon_option("com2"); SIM->unregister_addon_option("com3"); SIM->unregister_addon_option("com4"); delete theSerialDevice; bx_list_c *menu = (bx_list_c*)SIM->get_param("ports.serial"); for (int i=0; iremove(pnum); } } // the device object bx_serial_c::bx_serial_c(void) { put("serial", "SER"); for (int i=0; iget_param(pname); if (SIM->get_param_bool("enabled", base)->get()) { switch (BX_SER_THIS s[i].io_mode) { case BX_SER_MODE_FILE: if (BX_SER_THIS s[i].output != NULL) fclose(BX_SER_THIS s[i].output); break; case BX_SER_MODE_TERM: #if defined(SERIAL_ENABLE) && !defined(WIN32) if (s[i].tty_id >= 0) { tcsetattr(s[i].tty_id, TCSAFLUSH, &s[i].term_orig); } #endif break; case BX_SER_MODE_RAW: #if USE_RAW_SERIAL delete [] BX_SER_THIS s[i].raw; #endif break; case BX_SER_MODE_SOCKET: if (BX_SER_THIS s[i].socket_id >= 0) closesocket(BX_SER_THIS s[i].socket_id); break; case BX_SER_MODE_PIPE: #ifdef WIN32 if (BX_SER_THIS s[i].pipe) CloseHandle(BX_SER_THIS s[i].pipe); #endif break; } } } SIM->get_bochs_root()->remove("serial"); BX_DEBUG(("Exit")); } void bx_serial_c::init(void) { Bit16u ports[BX_SERIAL_MAXDEV] = {0x03f8, 0x02f8, 0x03e8, 0x02e8}; char name[16], pname[20]; bx_list_c *base; unsigned i, count = 0; BX_SER_THIS detect_mouse = 0; BX_SER_THIS mouse_port = -1; BX_SER_THIS mouse_type = BX_MOUSE_TYPE_NONE; BX_SER_THIS mouse_internal_buffer.num_elements = 0; for (i=0; iget_param(pname); if (SIM->get_param_bool("enabled", base)->get()) { sprintf(name, "Serial Port %d", i + 1); /* serial interrupt */ BX_SER_THIS s[i].IRQ = 4 - (i & 1); if (i < 2) { DEV_register_irq(BX_SER_THIS s[i].IRQ, name); } /* internal state */ BX_SER_THIS s[i].ls_ipending = 0; BX_SER_THIS s[i].ms_ipending = 0; BX_SER_THIS s[i].rx_ipending = 0; BX_SER_THIS s[i].fifo_ipending = 0; BX_SER_THIS s[i].ls_interrupt = 0; BX_SER_THIS s[i].ms_interrupt = 0; BX_SER_THIS s[i].rx_interrupt = 0; BX_SER_THIS s[i].tx_interrupt = 0; BX_SER_THIS s[i].fifo_interrupt = 0; if (BX_SER_THIS s[i].tx_timer_index == BX_NULL_TIMER_HANDLE) { BX_SER_THIS s[i].tx_timer_index = bx_pc_system.register_timer(this, tx_timer_handler, 0, 0,0, "serial.tx"); // one-shot, inactive } if (BX_SER_THIS s[i].rx_timer_index == BX_NULL_TIMER_HANDLE) { BX_SER_THIS s[i].rx_timer_index = bx_pc_system.register_timer(this, rx_timer_handler, 0, 0,0, "serial.rx"); // one-shot, inactive } if (BX_SER_THIS s[i].fifo_timer_index == BX_NULL_TIMER_HANDLE) { BX_SER_THIS s[i].fifo_timer_index = bx_pc_system.register_timer(this, fifo_timer_handler, 0, 0,0, "serial.fifo"); // one-shot, inactive } BX_SER_THIS s[i].rx_pollstate = BX_SER_RXIDLE; /* int enable: b0000 0000 */ BX_SER_THIS s[i].int_enable.rxdata_enable = 0; BX_SER_THIS s[i].int_enable.txhold_enable = 0; BX_SER_THIS s[i].int_enable.rxlstat_enable = 0; BX_SER_THIS s[i].int_enable.modstat_enable = 0; /* int ID: b0000 0001 */ BX_SER_THIS s[i].int_ident.ipending = 1; BX_SER_THIS s[i].int_ident.int_ID = 0; /* FIFO control: b0000 0000 */ BX_SER_THIS s[i].fifo_cntl.enable = 0; BX_SER_THIS s[i].fifo_cntl.rxtrigger = 0; BX_SER_THIS s[i].rx_fifo_end = 0; BX_SER_THIS s[i].tx_fifo_end = 0; /* Line Control reg: b0000 0000 */ BX_SER_THIS s[i].line_cntl.wordlen_sel = 0; BX_SER_THIS s[i].line_cntl.stopbits = 0; BX_SER_THIS s[i].line_cntl.parity_enable = 0; BX_SER_THIS s[i].line_cntl.evenparity_sel = 0; BX_SER_THIS s[i].line_cntl.stick_parity = 0; BX_SER_THIS s[i].line_cntl.break_cntl = 0; BX_SER_THIS s[i].line_cntl.dlab = 0; /* Modem Control reg: b0000 0000 */ BX_SER_THIS s[i].modem_cntl.dtr = 0; BX_SER_THIS s[i].modem_cntl.rts = 0; BX_SER_THIS s[i].modem_cntl.out1 = 0; BX_SER_THIS s[i].modem_cntl.out2 = 0; BX_SER_THIS s[i].modem_cntl.local_loopback = 0; /* Line Status register: b0110 0000 */ BX_SER_THIS s[i].line_status.rxdata_ready = 0; BX_SER_THIS s[i].line_status.overrun_error = 0; BX_SER_THIS s[i].line_status.parity_error = 0; BX_SER_THIS s[i].line_status.framing_error = 0; BX_SER_THIS s[i].line_status.break_int = 0; BX_SER_THIS s[i].line_status.thr_empty = 1; BX_SER_THIS s[i].line_status.tsr_empty = 1; BX_SER_THIS s[i].line_status.fifo_error = 0; /* Modem Status register: bXXXX 0000 */ BX_SER_THIS s[i].modem_status.delta_cts = 0; BX_SER_THIS s[i].modem_status.delta_dsr = 0; BX_SER_THIS s[i].modem_status.ri_trailedge = 0; BX_SER_THIS s[i].modem_status.delta_dcd = 0; BX_SER_THIS s[i].modem_status.cts = 0; BX_SER_THIS s[i].modem_status.dsr = 0; BX_SER_THIS s[i].modem_status.ri = 0; BX_SER_THIS s[i].modem_status.dcd = 0; BX_SER_THIS s[i].scratch = 0; /* scratch register */ BX_SER_THIS s[i].divisor_lsb = 1; /* divisor-lsb register */ BX_SER_THIS s[i].divisor_msb = 0; /* divisor-msb register */ BX_SER_THIS s[i].baudrate = 115200; for (unsigned addr=ports[i]; addr<(unsigned)(ports[i]+8); addr++) { BX_DEBUG(("com%d initialize register for read/write: 0x%04x",i+1, addr)); DEV_register_ioread_handler(this, read_handler, addr, name, 1); DEV_register_iowrite_handler(this, write_handler, addr, name, 1); } BX_SER_THIS s[i].io_mode = BX_SER_MODE_NULL; const char *mode = SIM->get_param_enum("mode", base)->get_selected(); const char *dev = SIM->get_param_string("dev", base)->getptr(); if (!strcmp(mode, "file")) { if (strlen(dev) > 0) { BX_SER_THIS s[i].output = fopen(dev, "wb"); if (BX_SER_THIS s[i].output) BX_SER_THIS s[i].io_mode = BX_SER_MODE_FILE; } } else if (!strcmp(mode, "term")) { #if defined(SERIAL_ENABLE) && !defined(WIN32) if (strlen(dev) > 0) { BX_SER_THIS s[i].tty_id = open(dev, O_RDWR|O_NONBLOCK,600); if (BX_SER_THIS s[i].tty_id < 0) { BX_PANIC(("open of com%d (%s) failed", i+1, dev)); } else { BX_SER_THIS s[i].io_mode = BX_SER_MODE_TERM; BX_DEBUG(("com%d tty_id: %d", i+1, BX_SER_THIS s[i].tty_id)); tcgetattr(BX_SER_THIS s[i].tty_id, &BX_SER_THIS s[i].term_orig); memcpy(&BX_SER_THIS s[i].term_orig, &BX_SER_THIS s[i].term_new, sizeof(struct termios)); BX_SER_THIS s[i].term_new.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON); BX_SER_THIS s[i].term_new.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); BX_SER_THIS s[i].term_new.c_cflag &= ~(CSIZE|PARENB); BX_SER_THIS s[i].term_new.c_cflag |= CS8; BX_SER_THIS s[i].term_new.c_oflag |= OPOST | ONLCR; // Enable NL to CR-NL translation #ifndef TRUE_CTLC // ctl-C will exit Bochs, or trap to the debugger BX_SER_THIS s[i].term_new.c_iflag &= ~IGNBRK; BX_SER_THIS s[i].term_new.c_iflag |= BRKINT; BX_SER_THIS s[i].term_new.c_lflag |= ISIG; #else // ctl-C will be delivered to the serial port BX_SER_THIS s[i].term_new.c_iflag |= IGNBRK; BX_SER_THIS s[i].term_new.c_iflag &= ~BRKINT; #endif /* !def TRUE_CTLC */ BX_SER_THIS s[i].term_new.c_iflag = 0; BX_SER_THIS s[i].term_new.c_oflag = 0; BX_SER_THIS s[i].term_new.c_cflag = CS8|CREAD|CLOCAL; BX_SER_THIS s[i].term_new.c_lflag = 0; BX_SER_THIS s[i].term_new.c_cc[VMIN] = 1; BX_SER_THIS s[i].term_new.c_cc[VTIME] = 0; //BX_SER_THIS s[i].term_new.c_iflag |= IXOFF; tcsetattr(BX_SER_THIS s[i].tty_id, TCSAFLUSH, &BX_SER_THIS s[i].term_new); } } #else BX_PANIC(("serial terminal support not available")); #endif /* def SERIAL_ENABLE */ } else if (!strcmp(mode, "raw")) { #if USE_RAW_SERIAL BX_SER_THIS s[i].raw = new serial_raw(dev); BX_SER_THIS s[i].io_mode = BX_SER_MODE_RAW; #else BX_PANIC(("raw serial support not present")); #endif } else if (!strcmp(mode, "mouse")) { BX_SER_THIS s[i].io_mode = BX_SER_MODE_MOUSE; BX_SER_THIS mouse_port = i; BX_SER_THIS mouse_type = SIM->get_param_enum(BXPN_MOUSE_TYPE)->get(); } else if (!strncmp(mode, "socket", 6)) { BX_SER_THIS s[i].io_mode = BX_SER_MODE_SOCKET; struct sockaddr_in sin; struct hostent *hp; char host[BX_PATHNAME_LEN]; int port; SOCKET socket; bx_bool server = !strcmp(mode, "socket-server"); #if defined(WIN32) static bx_bool winsock_init = false; if (!winsock_init) { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 0); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) BX_PANIC(("WSAStartup failed")); winsock_init = true; } #endif strcpy(host, dev); char *substr = strtok(host, ":"); substr = strtok(NULL, ":"); if (!substr) { BX_PANIC(("com%d: inet address is wrong (%s)", i+1, dev)); } port = atoi(substr); hp = gethostbyname(host); if (!hp) { BX_PANIC(("com%d: gethostbyname failed (%s)", i+1, host)); } memset ((char*) &sin, 0, sizeof (sin)); #if BX_HAVE_SOCKADDR_IN_SIN_LEN sin.sin_len = sizeof sin; #endif memcpy ((char*) &(sin.sin_addr), hp->h_addr, hp->h_length); sin.sin_family = hp->h_addrtype; sin.sin_port = htons (port); socket = ::socket (AF_INET, SOCK_STREAM, 0); if (socket < 0) BX_PANIC(("com%d: socket() failed",i+1)); // server mode if (server) { if (::bind (socket, (sockaddr *) &sin, sizeof (sin)) < 0 || ::listen (socket, SOMAXCONN) < 0) { closesocket(socket); socket = (SOCKET) -1; BX_PANIC(("com%d: bind() or listen() failed (host:%s, port:%d)",i+1, host, port)); } else { BX_INFO(("com%d: waiting for client to connect (host:%s, port:%d)",i+1, host, port)); SOCKET client; if ((client = ::accept (socket, NULL, 0)) < 0) BX_PANIC(("com%d: accept() failed (host:%s, port:%d)",i+1, host, port)); closesocket(socket); socket = client; } } // client mode else if (::connect (socket, (sockaddr *) &sin, sizeof (sin)) < 0) { closesocket(socket); socket = (SOCKET) -1; BX_INFO(("com%d: connect() failed (host:%s, port:%d)",i+1, host, port)); } BX_SER_THIS s[i].socket_id = socket; if (socket > 0) BX_INFO(("com%d - inet %s - socket_id: %d, ip:%s, port:%d", i+1, server ? "server" : "client", socket, host, port)); } else if (!strncmp(mode, "pipe", 4)) { if (strlen(dev) > 0) { #ifdef WIN32 bx_bool server = !strcmp(mode, "pipe-server"); HANDLE pipe; BX_SER_THIS s[i].io_mode = BX_SER_MODE_PIPE; // server mode if (server) { pipe = CreateNamedPipe( dev, PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 4096, 4096, 0, NULL); if (pipe == INVALID_HANDLE_VALUE) BX_PANIC(("com%d: CreateNamedPipe(%s) failed", i+1, dev)); BX_INFO(("com%d: waiting for client to connect to %s", i+1, dev)); if (!ConnectNamedPipe(pipe, NULL) && GetLastError() != ERROR_PIPE_CONNECTED) { CloseHandle(pipe); pipe = INVALID_HANDLE_VALUE; BX_PANIC(("com%d: ConnectNamedPipe(%s) failed", i+1, dev)); } } // client mode else { pipe = CreateFile( dev, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (pipe == INVALID_HANDLE_VALUE) BX_INFO(("com%d: failed to open pipe %s", i+1, dev)); } if (pipe != INVALID_HANDLE_VALUE) BX_SER_THIS s[i].pipe = pipe; #else BX_PANIC(("support for serial mode '%s' not available", mode)); #endif } } else if (strcmp(mode, "null")) { BX_PANIC(("unknown serial i/o mode '%s'", mode)); } // simulate device connected if (BX_SER_THIS s[i].io_mode != BX_SER_MODE_RAW) { BX_SER_THIS s[i].modem_status.cts = 1; BX_SER_THIS s[i].modem_status.dsr = 1; } count++; BX_INFO(("com%d at 0x%04x irq %d", i+1, ports[i], BX_SER_THIS s[i].IRQ)); } } // Check if the device is disabled or not configured if (count == 0) { BX_INFO(("serial ports disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("serial"))->set(0); return; } if ((BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL) || (BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_WHEEL) || (BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_MSYS)) { DEV_register_default_mouse(this, mouse_enq_static, NULL); } } void bx_serial_c::register_state(void) { unsigned i, j; char name[6]; bx_list_c *port; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "serial", "Serial Port State"); for (i=0; iread(address, io_len); } Bit32u bx_serial_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_SER_SMF Bit8u offset, val; Bit8u port = 0; offset = address & 0x07; switch (address & 0x03f8) { case 0x03f8: port = 0; break; case 0x02f8: port = 1; break; case 0x03e8: port = 2; break; case 0x02e8: port = 3; break; } switch (offset) { case BX_SER_RBR: /* receive buffer, or divisor latch LSB if DLAB set */ if (BX_SER_THIS s[port].line_cntl.dlab) { val = BX_SER_THIS s[port].divisor_lsb; } else { if (BX_SER_THIS s[port].fifo_cntl.enable) { val = BX_SER_THIS s[port].rx_fifo[0]; if (BX_SER_THIS s[port].rx_fifo_end > 0) { memcpy(&BX_SER_THIS s[port].rx_fifo[0], &BX_SER_THIS s[port].rx_fifo[1], 15); BX_SER_THIS s[port].rx_fifo_end--; } if (BX_SER_THIS s[port].rx_fifo_end == 0) { BX_SER_THIS s[port].line_status.rxdata_ready = 0; BX_SER_THIS s[port].rx_interrupt = 0; BX_SER_THIS s[port].rx_ipending = 0; BX_SER_THIS s[port].fifo_interrupt = 0; BX_SER_THIS s[port].fifo_ipending = 0; lower_interrupt(port); } } else { val = BX_SER_THIS s[port].rxbuffer; BX_SER_THIS s[port].line_status.rxdata_ready = 0; BX_SER_THIS s[port].rx_interrupt = 0; BX_SER_THIS s[port].rx_ipending = 0; lower_interrupt(port); } } break; case BX_SER_IER: /* interrupt enable register, or div. latch MSB */ if (BX_SER_THIS s[port].line_cntl.dlab) { val = BX_SER_THIS s[port].divisor_msb; } else { val = BX_SER_THIS s[port].int_enable.rxdata_enable | (BX_SER_THIS s[port].int_enable.txhold_enable << 1) | (BX_SER_THIS s[port].int_enable.rxlstat_enable << 2) | (BX_SER_THIS s[port].int_enable.modstat_enable << 3); } break; case BX_SER_IIR: /* interrupt ID register */ /* * Set the interrupt ID based on interrupt source */ if (BX_SER_THIS s[port].ls_interrupt) { BX_SER_THIS s[port].int_ident.int_ID = 0x3; BX_SER_THIS s[port].int_ident.ipending = 0; } else if (BX_SER_THIS s[port].fifo_interrupt) { BX_SER_THIS s[port].int_ident.int_ID = 0x6; BX_SER_THIS s[port].int_ident.ipending = 0; } else if (BX_SER_THIS s[port].rx_interrupt) { BX_SER_THIS s[port].int_ident.int_ID = 0x2; BX_SER_THIS s[port].int_ident.ipending = 0; } else if (BX_SER_THIS s[port].tx_interrupt) { BX_SER_THIS s[port].int_ident.int_ID = 0x1; BX_SER_THIS s[port].int_ident.ipending = 0; } else if (BX_SER_THIS s[port].ms_interrupt) { BX_SER_THIS s[port].int_ident.int_ID = 0x0; BX_SER_THIS s[port].int_ident.ipending = 0; } else { BX_SER_THIS s[port].int_ident.int_ID = 0x0; BX_SER_THIS s[port].int_ident.ipending = 1; } BX_SER_THIS s[port].tx_interrupt = 0; lower_interrupt(port); val = BX_SER_THIS s[port].int_ident.ipending | (BX_SER_THIS s[port].int_ident.int_ID << 1) | (BX_SER_THIS s[port].fifo_cntl.enable ? 0xc0 : 0x00); break; case BX_SER_LCR: /* Line control register */ val = BX_SER_THIS s[port].line_cntl.wordlen_sel | (BX_SER_THIS s[port].line_cntl.stopbits << 2) | (BX_SER_THIS s[port].line_cntl.parity_enable << 3) | (BX_SER_THIS s[port].line_cntl.evenparity_sel << 4) | (BX_SER_THIS s[port].line_cntl.stick_parity << 5) | (BX_SER_THIS s[port].line_cntl.break_cntl << 6) | (BX_SER_THIS s[port].line_cntl.dlab << 7); break; case BX_SER_MCR: /* MODEM control register */ val = BX_SER_THIS s[port].modem_cntl.dtr | (BX_SER_THIS s[port].modem_cntl.rts << 1) | (BX_SER_THIS s[port].modem_cntl.out1 << 2) | (BX_SER_THIS s[port].modem_cntl.out2 << 3) | (BX_SER_THIS s[port].modem_cntl.local_loopback << 4); break; case BX_SER_LSR: /* Line status register */ val = BX_SER_THIS s[port].line_status.rxdata_ready | (BX_SER_THIS s[port].line_status.overrun_error << 1) | (BX_SER_THIS s[port].line_status.parity_error << 2) | (BX_SER_THIS s[port].line_status.framing_error << 3) | (BX_SER_THIS s[port].line_status.break_int << 4) | (BX_SER_THIS s[port].line_status.thr_empty << 5) | (BX_SER_THIS s[port].line_status.tsr_empty << 6) | (BX_SER_THIS s[port].line_status.fifo_error << 7); BX_SER_THIS s[port].line_status.overrun_error = 0; BX_SER_THIS s[port].line_status.framing_error = 0; BX_SER_THIS s[port].line_status.break_int = 0; BX_SER_THIS s[port].ls_interrupt = 0; BX_SER_THIS s[port].ls_ipending = 0; lower_interrupt(port); break; case BX_SER_MSR: /* MODEM status register */ #if USE_RAW_SERIAL if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { bx_bool prev_cts = BX_SER_THIS s[port].modem_status.cts; bx_bool prev_dsr = BX_SER_THIS s[port].modem_status.dsr; bx_bool prev_ri = BX_SER_THIS s[port].modem_status.ri; bx_bool prev_dcd = BX_SER_THIS s[port].modem_status.dcd; val = BX_SER_THIS s[port].raw->get_modem_status(); BX_SER_THIS s[port].modem_status.cts = (val & 0x10) >> 4; BX_SER_THIS s[port].modem_status.dsr = (val & 0x20) >> 5; BX_SER_THIS s[port].modem_status.ri = (val & 0x40) >> 6; BX_SER_THIS s[port].modem_status.dcd = (val & 0x80) >> 7; if (BX_SER_THIS s[port].modem_status.cts != prev_cts) { BX_SER_THIS s[port].modem_status.delta_cts = 1; } if (BX_SER_THIS s[port].modem_status.dsr != prev_dsr) { BX_SER_THIS s[port].modem_status.delta_dsr = 1; } if ((BX_SER_THIS s[port].modem_status.ri == 0) && (prev_ri == 1)) BX_SER_THIS s[port].modem_status.ri_trailedge = 1; if (BX_SER_THIS s[port].modem_status.dcd != prev_dcd) { BX_SER_THIS s[port].modem_status.delta_dcd = 1; } } #endif val = BX_SER_THIS s[port].modem_status.delta_cts | (BX_SER_THIS s[port].modem_status.delta_dsr << 1) | (BX_SER_THIS s[port].modem_status.ri_trailedge << 2) | (BX_SER_THIS s[port].modem_status.delta_dcd << 3) | (BX_SER_THIS s[port].modem_status.cts << 4) | (BX_SER_THIS s[port].modem_status.dsr << 5) | (BX_SER_THIS s[port].modem_status.ri << 6) | (BX_SER_THIS s[port].modem_status.dcd << 7); BX_SER_THIS s[port].modem_status.delta_cts = 0; BX_SER_THIS s[port].modem_status.delta_dsr = 0; BX_SER_THIS s[port].modem_status.ri_trailedge = 0; BX_SER_THIS s[port].modem_status.delta_dcd = 0; BX_SER_THIS s[port].ms_interrupt = 0; BX_SER_THIS s[port].ms_ipending = 0; lower_interrupt(port); break; case BX_SER_SCR: /* scratch register */ val = BX_SER_THIS s[port].scratch; break; default: val = 0; // keep compiler happy BX_PANIC(("unsupported io read from address=0x%04x!", address)); break; } BX_DEBUG(("com%d register read from address: 0x%04x = 0x%02x", port+1, address, val)); return(val); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_serial_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_SER_SMF bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_SER_SMF bx_bool gen_int = 0; Bit8u offset, new_wordlen; #if USE_RAW_SERIAL bx_bool mcr_changed = 0; Bit8u p_mode; #endif Bit8u port = 0; offset = address & 0x07; switch (address & 0x03f8) { case 0x03f8: port = 0; break; case 0x02f8: port = 1; break; case 0x03e8: port = 2; break; case 0x02e8: port = 3; break; } BX_DEBUG(("com%d register write to address: 0x%04x = 0x%02x", port+1, address, value)); bx_bool new_b0 = value & 0x01; bx_bool new_b1 = (value & 0x02) >> 1; bx_bool new_b2 = (value & 0x04) >> 2; bx_bool new_b3 = (value & 0x08) >> 3; bx_bool new_b4 = (value & 0x10) >> 4; bx_bool new_b5 = (value & 0x20) >> 5; bx_bool new_b6 = (value & 0x40) >> 6; bx_bool new_b7 = (value & 0x80) >> 7; switch (offset) { case BX_SER_THR: /* transmit buffer, or divisor latch LSB if DLAB set */ if (BX_SER_THIS s[port].line_cntl.dlab) { BX_SER_THIS s[port].divisor_lsb = value; if ((value != 0) || (BX_SER_THIS s[port].divisor_msb != 0)) { BX_SER_THIS s[port].baudrate = (int) (BX_PC_CLOCK_XTL / (16 * ((BX_SER_THIS s[port].divisor_msb << 8) | BX_SER_THIS s[port].divisor_lsb))); } } else { Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[port].line_cntl.wordlen_sel); if (BX_SER_THIS s[port].line_status.thr_empty) { if (BX_SER_THIS s[port].fifo_cntl.enable) { BX_SER_THIS s[port].tx_fifo[BX_SER_THIS s[port].tx_fifo_end++] = value & bitmask; } else { BX_SER_THIS s[port].thrbuffer = value & bitmask; } BX_SER_THIS s[port].line_status.thr_empty = 0; if (BX_SER_THIS s[port].line_status.tsr_empty) { if (BX_SER_THIS s[port].fifo_cntl.enable) { BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].tx_fifo[0]; memcpy(&BX_SER_THIS s[port].tx_fifo[0], &BX_SER_THIS s[port].tx_fifo[1], 15); BX_SER_THIS s[port].line_status.thr_empty = (--BX_SER_THIS s[port].tx_fifo_end == 0); } else { BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].thrbuffer; BX_SER_THIS s[port].line_status.thr_empty = 1; } BX_SER_THIS s[port].line_status.tsr_empty = 0; raise_interrupt(port, BX_SER_INT_TXHOLD); bx_pc_system.activate_timer(BX_SER_THIS s[port].tx_timer_index, (int) (1000000.0 / BX_SER_THIS s[port].baudrate * (BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)), 0); /* not continuous */ } else { BX_SER_THIS s[port].tx_interrupt = 0; lower_interrupt(port); } } else { if (BX_SER_THIS s[port].fifo_cntl.enable) { if (BX_SER_THIS s[port].tx_fifo_end < 16) { BX_SER_THIS s[port].tx_fifo[BX_SER_THIS s[port].tx_fifo_end++] = value & bitmask; } else { BX_ERROR(("com%d: transmit FIFO overflow", port+1)); } } else { BX_ERROR(("com%d: write to tx hold register when not empty", port+1)); } } } break; case BX_SER_IER: /* interrupt enable register, or div. latch MSB */ if (BX_SER_THIS s[port].line_cntl.dlab) { BX_SER_THIS s[port].divisor_msb = value; if ((value != 0) || (BX_SER_THIS s[port].divisor_lsb != 0)) { BX_SER_THIS s[port].baudrate = (int) (BX_PC_CLOCK_XTL / (16 * ((BX_SER_THIS s[port].divisor_msb << 8) | BX_SER_THIS s[port].divisor_lsb))); } } else { if (new_b3 != BX_SER_THIS s[port].int_enable.modstat_enable) { BX_SER_THIS s[port].int_enable.modstat_enable = new_b3; if (BX_SER_THIS s[port].int_enable.modstat_enable == 1) { if (BX_SER_THIS s[port].ms_ipending == 1) { BX_SER_THIS s[port].ms_interrupt = 1; BX_SER_THIS s[port].ms_ipending = 0; gen_int = 1; } } else { if (BX_SER_THIS s[port].ms_interrupt == 1) { BX_SER_THIS s[port].ms_interrupt = 0; BX_SER_THIS s[port].ms_ipending = 1; lower_interrupt(port); } } } if (new_b1 != BX_SER_THIS s[port].int_enable.txhold_enable) { BX_SER_THIS s[port].int_enable.txhold_enable = new_b1; if (BX_SER_THIS s[port].int_enable.txhold_enable == 1) { BX_SER_THIS s[port].tx_interrupt = BX_SER_THIS s[port].line_status.thr_empty; if (BX_SER_THIS s[port].tx_interrupt) gen_int = 1; } else { BX_SER_THIS s[port].tx_interrupt = 0; lower_interrupt(port); } } if (new_b0 != BX_SER_THIS s[port].int_enable.rxdata_enable) { BX_SER_THIS s[port].int_enable.rxdata_enable = new_b0; if (BX_SER_THIS s[port].int_enable.rxdata_enable == 1) { if (BX_SER_THIS s[port].fifo_ipending == 1) { BX_SER_THIS s[port].fifo_interrupt = 1; BX_SER_THIS s[port].fifo_ipending = 0; gen_int = 1; } if (BX_SER_THIS s[port].rx_ipending == 1) { BX_SER_THIS s[port].rx_interrupt = 1; BX_SER_THIS s[port].rx_ipending = 0; gen_int = 1; } } else { if (BX_SER_THIS s[port].rx_interrupt == 1) { BX_SER_THIS s[port].rx_interrupt = 0; BX_SER_THIS s[port].rx_ipending = 1; lower_interrupt(port); } if (BX_SER_THIS s[port].fifo_interrupt == 1) { BX_SER_THIS s[port].fifo_interrupt = 0; BX_SER_THIS s[port].fifo_ipending = 1; lower_interrupt(port); } } } if (new_b2 != BX_SER_THIS s[port].int_enable.rxlstat_enable) { BX_SER_THIS s[port].int_enable.rxlstat_enable = new_b2; if (BX_SER_THIS s[port].int_enable.rxlstat_enable == 1) { if (BX_SER_THIS s[port].ls_ipending == 1) { BX_SER_THIS s[port].ls_interrupt = 1; BX_SER_THIS s[port].ls_ipending = 0; gen_int = 1; } } else { if (BX_SER_THIS s[port].ls_interrupt == 1) { BX_SER_THIS s[port].ls_interrupt = 0; BX_SER_THIS s[port].ls_ipending = 1; lower_interrupt(port); } } } if (gen_int) raise_interrupt(port, BX_SER_INT_IER); } break; case BX_SER_FCR: /* FIFO control register */ if (new_b0 && !BX_SER_THIS s[port].fifo_cntl.enable) { BX_INFO(("com%d: FIFO enabled", port+1)); BX_SER_THIS s[port].rx_fifo_end = 0; BX_SER_THIS s[port].tx_fifo_end = 0; } BX_SER_THIS s[port].fifo_cntl.enable = new_b0; if (new_b1) { BX_SER_THIS s[port].rx_fifo_end = 0; } if (new_b2) { BX_SER_THIS s[port].tx_fifo_end = 0; } BX_SER_THIS s[port].fifo_cntl.rxtrigger = (value & 0xc0) >> 6; break; case BX_SER_LCR: /* Line control register */ new_wordlen = value & 0x03; #if USE_RAW_SERIAL if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { if (BX_SER_THIS s[port].line_cntl.wordlen_sel != new_wordlen) { BX_SER_THIS s[port].raw->set_data_bits(new_wordlen + 5); } if (new_b2 != BX_SER_THIS s[port].line_cntl.stopbits) { BX_SER_THIS s[port].raw->set_stop_bits(new_b2 ? 2 : 1); } if ((new_b3 != BX_SER_THIS s[port].line_cntl.parity_enable) || (new_b4 != BX_SER_THIS s[port].line_cntl.evenparity_sel) || (new_b5 != BX_SER_THIS s[port].line_cntl.stick_parity)) { if (new_b3 == 0) { p_mode = P_NONE; } else { p_mode = ((value & 0x30) >> 4) + 1; } BX_SER_THIS s[port].raw->set_parity_mode(p_mode); } if ((new_b6 != BX_SER_THIS s[port].line_cntl.break_cntl) && (!BX_SER_THIS s[port].modem_cntl.local_loopback)) { BX_SER_THIS s[port].raw->set_break(new_b6); } } #endif // USE_RAW_SERIAL BX_SER_THIS s[port].line_cntl.wordlen_sel = new_wordlen; /* These are ignored, but set them up so they can be read back */ BX_SER_THIS s[port].line_cntl.stopbits = new_b2; BX_SER_THIS s[port].line_cntl.parity_enable = new_b3; BX_SER_THIS s[port].line_cntl.evenparity_sel = new_b4; BX_SER_THIS s[port].line_cntl.stick_parity = new_b5; BX_SER_THIS s[port].line_cntl.break_cntl = new_b6; if (BX_SER_THIS s[port].modem_cntl.local_loopback && BX_SER_THIS s[port].line_cntl.break_cntl) { BX_SER_THIS s[port].line_status.break_int = 1; BX_SER_THIS s[port].line_status.framing_error = 1; rx_fifo_enq(port, 0x00); } /* used when doing future writes */ if (!new_b7 && BX_SER_THIS s[port].line_cntl.dlab) { // Start the receive polling process if not already started // and there is a valid baudrate. if (BX_SER_THIS s[port].rx_pollstate == BX_SER_RXIDLE && BX_SER_THIS s[port].baudrate != 0) { BX_SER_THIS s[port].rx_pollstate = BX_SER_RXPOLL; bx_pc_system.activate_timer(BX_SER_THIS s[port].rx_timer_index, (int) (1000000.0 / BX_SER_THIS s[port].baudrate * (BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)), 0); /* not continuous */ } #if USE_RAW_SERIAL if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { BX_SER_THIS s[port].raw->set_baudrate(BX_SER_THIS s[port].baudrate); } #endif // USE_RAW_SERIAL BX_DEBUG(("com%d: baud rate set - %d", port+1, BX_SER_THIS s[port].baudrate)); } BX_SER_THIS s[port].line_cntl.dlab = new_b7; break; case BX_SER_MCR: /* MODEM control register */ if ((BX_SER_THIS s[port].io_mode == BX_SER_MODE_MOUSE) && ((BX_SER_THIS s[port].line_cntl.wordlen_sel == 2) || (BX_SER_THIS s[port].line_cntl.wordlen_sel == 3))) { if (new_b0 && !new_b1) BX_SER_THIS detect_mouse = 1; if (new_b0 && new_b1 && (BX_SER_THIS detect_mouse == 1)) BX_SER_THIS detect_mouse = 2; } #if USE_RAW_SERIAL if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { mcr_changed = (BX_SER_THIS s[port].modem_cntl.dtr != new_b0) | (BX_SER_THIS s[port].modem_cntl.rts != new_b1); } #endif BX_SER_THIS s[port].modem_cntl.dtr = new_b0; BX_SER_THIS s[port].modem_cntl.rts = new_b1; BX_SER_THIS s[port].modem_cntl.out1 = new_b2; BX_SER_THIS s[port].modem_cntl.out2 = new_b3; if (new_b4 != BX_SER_THIS s[port].modem_cntl.local_loopback) { BX_SER_THIS s[port].modem_cntl.local_loopback = new_b4; if (BX_SER_THIS s[port].modem_cntl.local_loopback) { /* transition to loopback mode */ #if USE_RAW_SERIAL if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { if (BX_SER_THIS s[port].modem_cntl.dtr || BX_SER_THIS s[port].modem_cntl.rts) { BX_SER_THIS s[port].raw->set_modem_control(0); } } #endif if (BX_SER_THIS s[port].line_cntl.break_cntl) { #if USE_RAW_SERIAL if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { BX_SER_THIS s[port].raw->set_break(0); } #endif BX_SER_THIS s[port].line_status.break_int = 1; BX_SER_THIS s[port].line_status.framing_error = 1; rx_fifo_enq(port, 0x00); } } else { /* transition to normal mode */ #if USE_RAW_SERIAL if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { mcr_changed = 1; if (BX_SER_THIS s[port].line_cntl.break_cntl) { BX_SER_THIS s[port].raw->set_break(0); } } #endif } } if (BX_SER_THIS s[port].modem_cntl.local_loopback) { bx_bool prev_cts = BX_SER_THIS s[port].modem_status.cts; bx_bool prev_dsr = BX_SER_THIS s[port].modem_status.dsr; bx_bool prev_ri = BX_SER_THIS s[port].modem_status.ri; bx_bool prev_dcd = BX_SER_THIS s[port].modem_status.dcd; BX_SER_THIS s[port].modem_status.cts = BX_SER_THIS s[port].modem_cntl.rts; BX_SER_THIS s[port].modem_status.dsr = BX_SER_THIS s[port].modem_cntl.dtr; BX_SER_THIS s[port].modem_status.ri = BX_SER_THIS s[port].modem_cntl.out1; BX_SER_THIS s[port].modem_status.dcd = BX_SER_THIS s[port].modem_cntl.out2; if (BX_SER_THIS s[port].modem_status.cts != prev_cts) { BX_SER_THIS s[port].modem_status.delta_cts = 1; BX_SER_THIS s[port].ms_ipending = 1; } if (BX_SER_THIS s[port].modem_status.dsr != prev_dsr) { BX_SER_THIS s[port].modem_status.delta_dsr = 1; BX_SER_THIS s[port].ms_ipending = 1; } if (BX_SER_THIS s[port].modem_status.ri != prev_ri) BX_SER_THIS s[port].ms_ipending = 1; if ((BX_SER_THIS s[port].modem_status.ri == 0) && (prev_ri == 1)) BX_SER_THIS s[port].modem_status.ri_trailedge = 1; if (BX_SER_THIS s[port].modem_status.dcd != prev_dcd) { BX_SER_THIS s[port].modem_status.delta_dcd = 1; BX_SER_THIS s[port].ms_ipending = 1; } raise_interrupt(port, BX_SER_INT_MODSTAT); } else { if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_MOUSE) { if (BX_SER_THIS detect_mouse == 2) { if ((BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL) || (BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_MSYS)) { BX_SER_THIS mouse_internal_buffer.head = 0; BX_SER_THIS mouse_internal_buffer.num_elements = 1; BX_SER_THIS mouse_internal_buffer.buffer[0] = 'M'; } else if (BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_WHEEL) { BX_SER_THIS mouse_internal_buffer.head = 0; BX_SER_THIS mouse_internal_buffer.num_elements = 6; BX_SER_THIS mouse_internal_buffer.buffer[0] = 'M'; BX_SER_THIS mouse_internal_buffer.buffer[1] = 'Z'; BX_SER_THIS mouse_internal_buffer.buffer[2] = '@'; BX_SER_THIS mouse_internal_buffer.buffer[3] = '\0'; BX_SER_THIS mouse_internal_buffer.buffer[4] = '\0'; BX_SER_THIS mouse_internal_buffer.buffer[5] = '\0'; } BX_SER_THIS detect_mouse = 0; } } if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_RAW) { #if USE_RAW_SERIAL if (mcr_changed) { BX_SER_THIS s[port].raw->set_modem_control(value & 0x03); } #endif } else { /* simulate device connected */ BX_SER_THIS s[port].modem_status.cts = 1; BX_SER_THIS s[port].modem_status.dsr = 1; BX_SER_THIS s[port].modem_status.ri = 0; BX_SER_THIS s[port].modem_status.dcd = 0; } } break; case BX_SER_LSR: /* Line status register */ BX_ERROR(("com%d: write to line status register ignored", port+1)); break; case BX_SER_MSR: /* MODEM status register */ BX_ERROR(("com%d: write to MODEM status register ignored", port+1)); break; case BX_SER_SCR: /* scratch register */ BX_SER_THIS s[port].scratch = value; break; default: BX_PANIC(("unsupported io write to address=0x%04x, value = 0x%02x!", (unsigned) address, (unsigned) value)); break; } } void bx_serial_c::rx_fifo_enq(Bit8u port, Bit8u data) { bx_bool gen_int = 0; if (BX_SER_THIS s[port].fifo_cntl.enable) { if (BX_SER_THIS s[port].rx_fifo_end == 16) { BX_ERROR(("com%d: receive FIFO overflow", port+1)); BX_SER_THIS s[port].line_status.overrun_error = 1; raise_interrupt(port, BX_SER_INT_RXLSTAT); } else { BX_SER_THIS s[port].rx_fifo[BX_SER_THIS s[port].rx_fifo_end++] = data; switch (BX_SER_THIS s[port].fifo_cntl.rxtrigger) { case 1: if (BX_SER_THIS s[port].rx_fifo_end == 4) gen_int = 1; break; case 2: if (BX_SER_THIS s[port].rx_fifo_end == 8) gen_int = 1; break; case 3: if (BX_SER_THIS s[port].rx_fifo_end == 14) gen_int = 1; break; default: gen_int = 1; } if (gen_int) { bx_pc_system.deactivate_timer(BX_SER_THIS s[port].fifo_timer_index); BX_SER_THIS s[port].line_status.rxdata_ready = 1; raise_interrupt(port, BX_SER_INT_RXDATA); } else { bx_pc_system.activate_timer(BX_SER_THIS s[port].fifo_timer_index, (int) (1000000.0 / BX_SER_THIS s[port].baudrate * (BX_SER_THIS s[port].line_cntl.wordlen_sel + 5) * 16), 0); /* not continuous */ } } } else { if (BX_SER_THIS s[port].line_status.rxdata_ready == 1) { BX_ERROR(("com%d: overrun error", port+1)); BX_SER_THIS s[port].line_status.overrun_error = 1; raise_interrupt(port, BX_SER_INT_RXLSTAT); } BX_SER_THIS s[port].rxbuffer = data; BX_SER_THIS s[port].line_status.rxdata_ready = 1; raise_interrupt(port, BX_SER_INT_RXDATA); } } void bx_serial_c::tx_timer_handler(void *this_ptr) { bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; class_ptr->tx_timer(); } void bx_serial_c::tx_timer(void) { bx_bool gen_int = 0; Bit8u port = 0; int timer_id; timer_id = bx_pc_system.triggeredTimerID(); if (timer_id == BX_SER_THIS s[0].tx_timer_index) { port = 0; } else if (timer_id == BX_SER_THIS s[1].tx_timer_index) { port = 1; } else if (timer_id == BX_SER_THIS s[2].tx_timer_index) { port = 2; } else if (timer_id == BX_SER_THIS s[3].tx_timer_index) { port = 3; } if (BX_SER_THIS s[port].modem_cntl.local_loopback) { rx_fifo_enq(port, BX_SER_THIS s[port].tsrbuffer); } else { switch (BX_SER_THIS s[port].io_mode) { case BX_SER_MODE_FILE: fputc(BX_SER_THIS s[port].tsrbuffer, BX_SER_THIS s[port].output); fflush(BX_SER_THIS s[port].output); break; case BX_SER_MODE_TERM: #if defined(SERIAL_ENABLE) BX_DEBUG(("com%d: write: '%c'", port+1, BX_SER_THIS s[port].tsrbuffer)); if (BX_SER_THIS s[port].tty_id >= 0) { write(BX_SER_THIS s[port].tty_id, (bx_ptr_t) & BX_SER_THIS s[port].tsrbuffer, 1); } #endif break; case BX_SER_MODE_RAW: #if USE_RAW_SERIAL if (!BX_SER_THIS s[port].raw->ready_transmit()) BX_PANIC(("com%d: not ready to transmit", port+1)); BX_SER_THIS s[port].raw->transmit(BX_SER_THIS s[port].tsrbuffer); #endif break; case BX_SER_MODE_MOUSE: BX_INFO(("com%d: write to mouse ignored: 0x%02x", port+1, BX_SER_THIS s[port].tsrbuffer)); break; case BX_SER_MODE_SOCKET: if (BX_SER_THIS s[port].socket_id >= 0) { #ifdef WIN32 BX_INFO(("attempting to write win32 : %c", BX_SER_THIS s[port].tsrbuffer)); ::send(BX_SER_THIS s[port].socket_id, (const char*) & BX_SER_THIS s[port].tsrbuffer, 1, 0); #else ::write(BX_SER_THIS s[port].socket_id, (bx_ptr_t) & BX_SER_THIS s[port].tsrbuffer, 1); #endif } case BX_SER_MODE_PIPE: #ifdef WIN32 if (BX_SER_THIS s[port].pipe) { DWORD written; WriteFile(BX_SER_THIS s[port].pipe, (bx_ptr_t)& BX_SER_THIS s[port].tsrbuffer, 1, &written, NULL); } #endif break; } } BX_SER_THIS s[port].line_status.tsr_empty = 1; if (BX_SER_THIS s[port].fifo_cntl.enable && (BX_SER_THIS s[port].tx_fifo_end > 0)) { BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].tx_fifo[0]; BX_SER_THIS s[port].line_status.tsr_empty = 0; memcpy(&BX_SER_THIS s[port].tx_fifo[0], &BX_SER_THIS s[port].tx_fifo[1], 15); gen_int = (--BX_SER_THIS s[port].tx_fifo_end == 0); } else if (!BX_SER_THIS s[port].line_status.thr_empty) { BX_SER_THIS s[port].tsrbuffer = BX_SER_THIS s[port].thrbuffer; BX_SER_THIS s[port].line_status.tsr_empty = 0; gen_int = 1; } if (!BX_SER_THIS s[port].line_status.tsr_empty) { if (gen_int) { BX_SER_THIS s[port].line_status.thr_empty = 1; raise_interrupt(port, BX_SER_INT_TXHOLD); } bx_pc_system.activate_timer(BX_SER_THIS s[port].tx_timer_index, (int) (1000000.0 / BX_SER_THIS s[port].baudrate * (BX_SER_THIS s[port].line_cntl.wordlen_sel + 5)), 0); /* not continuous */ } } void bx_serial_c::rx_timer_handler(void *this_ptr) { bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; class_ptr->rx_timer(); } void bx_serial_c::rx_timer(void) { #if BX_HAVE_SELECT && defined(SERIAL_ENABLE) struct timeval tval; fd_set fds; #endif Bit8u port = 0; int timer_id; bx_bool data_ready = 0; timer_id = bx_pc_system.triggeredTimerID(); if (timer_id == BX_SER_THIS s[0].rx_timer_index) { port = 0; } else if (timer_id == BX_SER_THIS s[1].rx_timer_index) { port = 1; } else if (timer_id == BX_SER_THIS s[2].rx_timer_index) { port = 2; } else if (timer_id == BX_SER_THIS s[3].rx_timer_index) { port = 3; } int bdrate = BX_SER_THIS s[port].baudrate / (BX_SER_THIS s[port].line_cntl.wordlen_sel + 5); unsigned char chbuf = 0; if (BX_SER_THIS s[port].io_mode == BX_SER_MODE_TERM) { #if BX_HAVE_SELECT && defined(SERIAL_ENABLE) tval.tv_sec = 0; tval.tv_usec = 0; // MacOS: I'm not sure what to do with this, since I don't know // what an fd_set is or what FD_SET() or select() do. They aren't // declared in the CodeWarrior standard library headers. I'm just // leaving it commented out for the moment. FD_ZERO(&fds); if (BX_SER_THIS s[port].tty_id >= 0) FD_SET(BX_SER_THIS s[port].tty_id, &fds); #endif } if ((BX_SER_THIS s[port].line_status.rxdata_ready == 0) || (BX_SER_THIS s[port].fifo_cntl.enable)) { switch (BX_SER_THIS s[port].io_mode) { case BX_SER_MODE_SOCKET: #if BX_HAVE_SELECT && defined(SERIAL_ENABLE) if (BX_SER_THIS s[port].line_status.rxdata_ready == 0) { tval.tv_sec = 0; tval.tv_usec = 0; FD_ZERO(&fds); SOCKET socketid = BX_SER_THIS s[port].socket_id; if (socketid >= 0) FD_SET(socketid, &fds); if ((socketid >= 0) && (select(socketid+1, &fds, NULL, NULL, &tval) == 1)) { ssize_t bytes = (ssize_t) #ifdef WIN32 ::recv(socketid, (char*) &chbuf, 1, 0); #else read(socketid, &chbuf, 1); #endif if (bytes > 0) { BX_INFO((" -- COM %d : read byte [%d]", port+1, chbuf)); data_ready = 1; } } } #endif break; case BX_SER_MODE_RAW: #if USE_RAW_SERIAL int data; if ((data_ready = BX_SER_THIS s[port].raw->ready_receive())) { data = BX_SER_THIS s[port].raw->receive(); if (data < 0) { data_ready = 0; switch (data) { case RAW_EVENT_BREAK: BX_SER_THIS s[port].line_status.break_int = 1; raise_interrupt(port, BX_SER_INT_RXLSTAT); break; case RAW_EVENT_FRAME: BX_SER_THIS s[port].line_status.framing_error = 1; raise_interrupt(port, BX_SER_INT_RXLSTAT); break; case RAW_EVENT_OVERRUN: BX_SER_THIS s[port].line_status.overrun_error = 1; raise_interrupt(port, BX_SER_INT_RXLSTAT); break; case RAW_EVENT_PARITY: BX_SER_THIS s[port].line_status.parity_error = 1; raise_interrupt(port, BX_SER_INT_RXLSTAT); break; case RAW_EVENT_CTS_ON: case RAW_EVENT_CTS_OFF: case RAW_EVENT_DSR_ON: case RAW_EVENT_DSR_OFF: case RAW_EVENT_RING_ON: case RAW_EVENT_RING_OFF: case RAW_EVENT_RLSD_ON: case RAW_EVENT_RLSD_OFF: raise_interrupt(port, BX_SER_INT_MODSTAT); break; } } } if (data_ready) { chbuf = data; } #endif break; case BX_SER_MODE_TERM: #if BX_HAVE_SELECT && defined(SERIAL_ENABLE) if ((BX_SER_THIS s[port].tty_id >= 0) && (select(BX_SER_THIS s[port].tty_id + 1, &fds, NULL, NULL, &tval) == 1)) { (void) read(BX_SER_THIS s[port].tty_id, &chbuf, 1); BX_DEBUG(("com%d: read: '%c'", port+1, chbuf)); data_ready = 1; } #endif break; case BX_SER_MODE_MOUSE: if (BX_SER_THIS mouse_internal_buffer.num_elements > 0) { chbuf = BX_SER_THIS mouse_internal_buffer.buffer[BX_SER_THIS mouse_internal_buffer.head]; BX_SER_THIS mouse_internal_buffer.head = (BX_SER_THIS mouse_internal_buffer.head + 1) % BX_MOUSE_BUFF_SIZE; BX_SER_THIS mouse_internal_buffer.num_elements--; data_ready = 1; } break; case BX_SER_MODE_PIPE: #ifdef WIN32 DWORD avail = 0; if (BX_SER_THIS s[port].pipe && PeekNamedPipe(BX_SER_THIS s[port].pipe, NULL, 0, NULL, &avail, NULL) && avail > 0) { ReadFile(BX_SER_THIS s[port].pipe, &chbuf, 1, &avail, NULL); data_ready = 1; } #endif break; } if (data_ready) { if (!BX_SER_THIS s[port].modem_cntl.local_loopback) { rx_fifo_enq(port, chbuf); } } else { if (!BX_SER_THIS s[port].fifo_cntl.enable) { bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms } } } else { // Poll at 4x baud rate to see if the next-char can // be read bdrate *= 4; } bx_pc_system.activate_timer(BX_SER_THIS s[port].rx_timer_index, (int) (1000000.0 / bdrate), 0); /* not continuous */ } void bx_serial_c::fifo_timer_handler(void *this_ptr) { bx_serial_c *class_ptr = (bx_serial_c *) this_ptr; class_ptr->fifo_timer(); } void bx_serial_c::fifo_timer(void) { Bit8u port = 0; int timer_id; timer_id = bx_pc_system.triggeredTimerID(); if (timer_id == BX_SER_THIS s[0].fifo_timer_index) { port = 0; } else if (timer_id == BX_SER_THIS s[1].fifo_timer_index) { port = 1; } else if (timer_id == BX_SER_THIS s[2].fifo_timer_index) { port = 2; } else if (timer_id == BX_SER_THIS s[3].fifo_timer_index) { port = 3; } BX_SER_THIS s[port].line_status.rxdata_ready = 1; raise_interrupt(port, BX_SER_INT_FIFO); } void bx_serial_c::mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy) { ((bx_serial_c*)dev)->mouse_enq(delta_x, delta_y, delta_z, button_state, absxy); } void bx_serial_c::mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy) { Bit8u b1, b2, b3, mouse_data[5]; int bytes, tail; if (BX_SER_THIS mouse_port == -1) { BX_ERROR(("mouse not connected to a serial port")); return; } // if the DTR and RTS lines aren't up, the mouse doesn't have any power to send packets. if (!BX_SER_THIS s[BX_SER_THIS mouse_port].modem_cntl.dtr || !BX_SER_THIS s[BX_SER_THIS mouse_port].modem_cntl.rts) return; // scale down the motion if ((delta_x < -1) || (delta_x > 1)) delta_x /= 2; if ((delta_y < -1) || (delta_y > 1)) delta_y /= 2; if(delta_x>127) delta_x=127; if(delta_y>127) delta_y=127; if(delta_x<-128) delta_x=-128; if(delta_y<-128) delta_y=-128; BX_SER_THIS mouse_delayed_dx+=delta_x; BX_SER_THIS mouse_delayed_dy-=delta_y; BX_SER_THIS mouse_delayed_dz =delta_z; if ((BX_SER_THIS mouse_internal_buffer.num_elements + 4) >= BX_MOUSE_BUFF_SIZE) { return; /* buffer doesn't have the space */ } if (BX_SER_THIS mouse_delayed_dx > 127) { delta_x = 127; BX_SER_THIS mouse_delayed_dx -= 127; } else if (BX_SER_THIS mouse_delayed_dx < -128) { delta_x = -128; BX_SER_THIS mouse_delayed_dx += 128; } else { delta_x = BX_SER_THIS mouse_delayed_dx; BX_SER_THIS mouse_delayed_dx = 0; } if (BX_SER_THIS mouse_delayed_dy > 127) { delta_y = 127; BX_SER_THIS mouse_delayed_dy -= 127; } else if (BX_SER_THIS mouse_delayed_dy < -128) { delta_y = -128; BX_SER_THIS mouse_delayed_dy += 128; } else { delta_y = BX_SER_THIS mouse_delayed_dy; BX_SER_THIS mouse_delayed_dy = 0; } if (BX_SER_THIS mouse_type != BX_MOUSE_TYPE_SERIAL_MSYS) { b1 = (Bit8u) delta_x; b2 = (Bit8u) delta_y; b3 = (Bit8u) -((Bit8s) delta_z); mouse_data[0] = 0x40 | ((b1 & 0xc0) >> 6) | ((b2 & 0xc0) >> 4); mouse_data[0] |= ((button_state & 0x01) << 5) | ((button_state & 0x02) << 3); mouse_data[1] = b1 & 0x3f; mouse_data[2] = b2 & 0x3f; mouse_data[3] = b3 & 0x0f; mouse_data[3] |= ((button_state & 0x04) << 2); bytes = 3; if (BX_SER_THIS mouse_type == BX_MOUSE_TYPE_SERIAL_WHEEL) bytes = 4; } else { b1 = (Bit8u) (delta_x / 2); b2 = (Bit8u) -((Bit8s) (delta_y / 2)); mouse_data[0] = 0x80 | ((~button_state & 0x01) << 2); mouse_data[0] |= ((~button_state & 0x06) >> 1); mouse_data[1] = b1; mouse_data[2] = b2; mouse_data[3] = 0; mouse_data[4] = 0; bytes = 5; } /* enqueue mouse data in multibyte internal mouse buffer */ for (int i = 0; i < bytes; i++) { tail = (BX_SER_THIS mouse_internal_buffer.head + BX_SER_THIS mouse_internal_buffer.num_elements) % BX_MOUSE_BUFF_SIZE; BX_SER_THIS mouse_internal_buffer.buffer[tail] = mouse_data[i]; BX_SER_THIS mouse_internal_buffer.num_elements++; } } bochs-2.6/iodev/dma.cc0000644000175000017500000007163212020641505014517 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: dma.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "dma.h" #define LOG_THIS theDmaDevice-> #define DMA_MODE_DEMAND 0 #define DMA_MODE_SINGLE 1 #define DMA_MODE_BLOCK 2 #define DMA_MODE_CASCADE 3 bx_dma_c *theDmaDevice = NULL; int libdma_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theDmaDevice = new bx_dma_c (); bx_devices.pluginDmaDevice = theDmaDevice; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theDmaDevice, BX_PLUGIN_DMA); return 0; // Success } else { return -1; } } void libdma_LTX_plugin_fini(void) { delete theDmaDevice; } bx_dma_c::bx_dma_c() { put("DMA"); memset(&s, 0, sizeof(s)); } bx_dma_c::~bx_dma_c() { SIM->get_bochs_root()->remove("dma"); BX_DEBUG(("Exit")); } unsigned bx_dma_c::registerDMA8Channel(unsigned channel, Bit16u (* dmaRead)(Bit8u *data_byte, Bit16u maxlen), Bit16u (* dmaWrite)(Bit8u *data_byte, Bit16u maxlen), const char *name) { if (channel > 3) { BX_PANIC(("registerDMA8Channel: invalid channel number(%u).", channel)); return 0; // Fail } if (BX_DMA_THIS s[0].chan[channel].used) { BX_PANIC(("registerDMA8Channel: channel(%u) already in use.", channel)); return 0; // Fail } BX_INFO(("channel %u used by %s", channel, name)); BX_DMA_THIS h[channel].dmaRead8 = dmaRead; BX_DMA_THIS h[channel].dmaWrite8 = dmaWrite; BX_DMA_THIS s[0].chan[channel].used = 1; return 1; // OK } unsigned bx_dma_c::registerDMA16Channel(unsigned channel, Bit16u (* dmaRead)(Bit16u *data_word, Bit16u maxlen), Bit16u (* dmaWrite)(Bit16u *data_word, Bit16u maxlen), const char *name) { if ((channel < 4) || (channel > 7)) { BX_PANIC(("registerDMA16Channel: invalid channel number(%u).", channel)); return 0; // Fail } if (BX_DMA_THIS s[1].chan[channel & 0x03].used) { BX_PANIC(("registerDMA16Channel: channel(%u) already in use.", channel)); return 0; // Fail } BX_INFO(("channel %u used by %s", channel, name)); channel &= 0x03; BX_DMA_THIS h[channel].dmaRead16 = dmaRead; BX_DMA_THIS h[channel].dmaWrite16 = dmaWrite; BX_DMA_THIS s[1].chan[channel].used = 1; return 1; // OK } unsigned bx_dma_c::unregisterDMAChannel(unsigned channel) { bx_bool ma_sl = (channel > 3); BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used = 0; BX_INFO(("channel %u no longer used", channel)); return 1; } unsigned bx_dma_c::get_TC(void) { return BX_DMA_THIS TC; } void bx_dma_c::init(void) { unsigned c, i, j; BX_DEBUG(("Init $Id: dma.cc 11346 2012-08-19 08:16:20Z vruppert $")); /* 8237 DMA controller */ for (i=0; i < 2; i++) { for (j=0; j < 4; j++) { BX_DMA_THIS s[i].DRQ[j] = 0; BX_DMA_THIS s[i].DACK[j] = 0; } } BX_DMA_THIS HLDA = 0; BX_DMA_THIS TC = 0; // 0000..000F for (i=0x0000; i<=0x000F; i++) { DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1); DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3); } // 00080..008F for (i=0x0080; i<=0x008F; i++) { DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1); DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3); } // 000C0..00DE for (i=0x00C0; i<=0x00DE; i+=2) { DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1); DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3); } for (i=0; i<2; i++) { for (c=0; c<4; c++) { BX_DMA_THIS s[i].chan[c].mode.mode_type = 0; // demand mode BX_DMA_THIS s[i].chan[c].mode.address_decrement = 0; // address increment BX_DMA_THIS s[i].chan[c].mode.autoinit_enable = 0; // autoinit disable BX_DMA_THIS s[i].chan[c].mode.transfer_type = 0; // verify BX_DMA_THIS s[i].chan[c].base_address = 0; BX_DMA_THIS s[i].chan[c].current_address = 0; BX_DMA_THIS s[i].chan[c].base_count = 0; BX_DMA_THIS s[i].chan[c].current_count = 0; BX_DMA_THIS s[i].chan[c].page_reg = 0; BX_DMA_THIS s[i].chan[c].used = 0; } } memset(&BX_DMA_THIS ext_page_reg[0], 0, 16); BX_DMA_THIS s[1].chan[0].used = 1; // cascade channel in use BX_INFO(("channel 4 used by cascade")); #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("dma", this); #endif } void bx_dma_c::reset(unsigned type) { reset_controller(0); reset_controller(1); } void bx_dma_c::reset_controller(unsigned num) { BX_DMA_THIS s[num].mask[0] = 1; BX_DMA_THIS s[num].mask[1] = 1; BX_DMA_THIS s[num].mask[2] = 1; BX_DMA_THIS s[num].mask[3] = 1; BX_DMA_THIS s[num].ctrl_disabled = 0; BX_DMA_THIS s[num].command_reg = 0; BX_DMA_THIS s[num].status_reg = 0; BX_DMA_THIS s[num].flip_flop = 0; } void bx_dma_c::register_state(void) { unsigned i, c; char name[6]; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "dma", "DMA State"); for (i=0; i<2; i++) { sprintf(name, "%d", i); bx_list_c *ctrl = new bx_list_c(list, name); BXRS_PARAM_BOOL(ctrl, flip_flop, BX_DMA_THIS s[i].flip_flop); BXRS_HEX_PARAM_FIELD(ctrl, status_reg, BX_DMA_THIS s[i].status_reg); BXRS_HEX_PARAM_FIELD(ctrl, command_reg, BX_DMA_THIS s[i].command_reg); BXRS_PARAM_BOOL(ctrl, ctrl_disabled, BX_DMA_THIS s[i].ctrl_disabled); for (c=0; c<4; c++) { sprintf(name, "%d", c); bx_list_c *chan = new bx_list_c(ctrl, name); BXRS_PARAM_BOOL(chan, DRQ, BX_DMA_THIS s[i].DRQ[c]); BXRS_PARAM_BOOL(chan, DACK, BX_DMA_THIS s[i].DACK[c]); BXRS_PARAM_BOOL(chan, mask, BX_DMA_THIS s[i].mask[c]); BXRS_DEC_PARAM_FIELD(chan, mode_type, BX_DMA_THIS s[i].chan[c].mode.mode_type); BXRS_PARAM_BOOL(chan, address_decrement, BX_DMA_THIS s[i].chan[c].mode.address_decrement); BXRS_PARAM_BOOL(chan, autoinit_enable, BX_DMA_THIS s[i].chan[c].mode.autoinit_enable); BXRS_DEC_PARAM_FIELD(chan, transfer_type, BX_DMA_THIS s[i].chan[c].mode.transfer_type); BXRS_HEX_PARAM_FIELD(chan, base_address, BX_DMA_THIS s[i].chan[c].base_address); BXRS_HEX_PARAM_FIELD(chan, current_address, BX_DMA_THIS s[i].chan[c].current_address); BXRS_HEX_PARAM_FIELD(chan, base_count, BX_DMA_THIS s[i].chan[c].base_count); BXRS_HEX_PARAM_FIELD(chan, current_count, BX_DMA_THIS s[i].chan[c].current_count); BXRS_HEX_PARAM_FIELD(chan, page_reg, BX_DMA_THIS s[i].chan[c].page_reg); } } bx_list_c *extpg = new bx_list_c(list, "ext_page"); for (i=0; i<16; i++) { sprintf(name, "0x%02x", 0x80+i); new bx_shadow_num_c(extpg, name, &BX_DMA_THIS ext_page_reg[i], BASE_HEX); } } // index to find channel from register number (only [0],[1],[2],[6] used) Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0}; // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_dma_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_DMA_SMF bx_dma_c *class_ptr = (bx_dma_c *) this_ptr; return class_ptr->read(address, io_len); } /* 8237 DMA controller */ Bit32u BX_CPP_AttrRegparmN(2) bx_dma_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_DMA_SMF Bit8u retval; Bit8u channel; BX_DEBUG(("read addr=%04x", (unsigned) address)); #if BX_DMA_FLOPPY_IO < 1 /* if we're not supporting DMA/floppy IO just return a bogus value */ return(0xff); #endif bx_bool ma_sl = (address >= 0xc0); switch (address) { case 0x00: /* DMA-1 current address, channel 0 */ case 0x02: /* DMA-1 current address, channel 1 */ case 0x04: /* DMA-1 current address, channel 2 */ case 0x06: /* DMA-1 current address, channel 3 */ case 0xc0: /* DMA-2 current address, channel 0 */ case 0xc4: /* DMA-2 current address, channel 1 */ case 0xc8: /* DMA-2 current address, channel 2 */ case 0xcc: /* DMA-2 current address, channel 3 */ channel = (address >> (1 + ma_sl)) & 0x03; if (BX_DMA_THIS s[ma_sl].flip_flop==0) { BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; return (BX_DMA_THIS s[ma_sl].chan[channel].current_address & 0xff); } else { BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; return (BX_DMA_THIS s[ma_sl].chan[channel].current_address >> 8); } case 0x01: /* DMA-1 current count, channel 0 */ case 0x03: /* DMA-1 current count, channel 1 */ case 0x05: /* DMA-1 current count, channel 2 */ case 0x07: /* DMA-1 current count, channel 3 */ case 0xc2: /* DMA-2 current count, channel 0 */ case 0xc6: /* DMA-2 current count, channel 1 */ case 0xca: /* DMA-2 current count, channel 2 */ case 0xce: /* DMA-2 current count, channel 3 */ channel = (address >> (1 + ma_sl)) & 0x03; if (BX_DMA_THIS s[ma_sl].flip_flop==0) { BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; return (BX_DMA_THIS s[ma_sl].chan[channel].current_count & 0xff); } else { BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; return (BX_DMA_THIS s[ma_sl].chan[channel].current_count >> 8); } case 0x08: // DMA-1 Status Register case 0xd0: // DMA-2 Status Register // bit 7: 1 = channel 3 request // bit 6: 1 = channel 2 request // bit 5: 1 = channel 1 request // bit 4: 1 = channel 0 request // bit 3: 1 = channel 3 has reached terminal count // bit 2: 1 = channel 2 has reached terminal count // bit 1: 1 = channel 1 has reached terminal count // bit 0: 1 = channel 0 has reached terminal count // reading this register clears lower 4 bits (hold flags) retval = BX_DMA_THIS s[ma_sl].status_reg; BX_DMA_THIS s[ma_sl].status_reg &= 0xf0; return retval; case 0x0d: // DMA-1: temporary register case 0xda: // DMA-2: temporary register // only used for memory-to-memory transfers // write to 0x0d / 0xda clears temporary register BX_ERROR(("DMA-%d: read of temporary register always returns 0", ma_sl+1)); return 0; case 0x0081: // DMA-1 page register, channel 2 case 0x0082: // DMA-1 page register, channel 3 case 0x0083: // DMA-1 page register, channel 1 case 0x0087: // DMA-1 page register, channel 0 channel = channelindex[address - 0x81]; return BX_DMA_THIS s[0].chan[channel].page_reg; case 0x0089: // DMA-2 page register, channel 2 case 0x008a: // DMA-2 page register, channel 3 case 0x008b: // DMA-2 page register, channel 1 case 0x008f: // DMA-2 page register, channel 0 channel = channelindex[address - 0x89]; return BX_DMA_THIS s[1].chan[channel].page_reg; case 0x0080: case 0x0084: case 0x0085: case 0x0086: case 0x0088: case 0x008c: case 0x008d: case 0x008e: BX_DEBUG(("read: extra page register 0x%04x (unused)", (unsigned) address)); return BX_DMA_THIS ext_page_reg[address & 0x0f]; case 0x0f: // DMA-1: undocumented: read all mask bits case 0xde: // DMA-2: undocumented: read all mask bits retval = BX_DMA_THIS s[ma_sl].mask[0] | (BX_DMA_THIS s[ma_sl].mask[1] << 1) | (BX_DMA_THIS s[ma_sl].mask[2] << 2) | (BX_DMA_THIS s[ma_sl].mask[3] << 3); return (0xf0 | retval); default: BX_ERROR(("read: unsupported address=%04x", (unsigned) address)); return 0; } } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_dma_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_DMA_SMF bx_dma_c *class_ptr = (bx_dma_c *) this_ptr; class_ptr->write(address, value, io_len); } /* 8237 DMA controller */ void BX_CPP_AttrRegparmN(3) bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_DMA_SMF Bit8u set_mask_bit; Bit8u channel; if (io_len > 1) { if ((io_len == 2) && (address == 0x0b)) { #if BX_USE_DMA_SMF BX_DMA_THIS write_handler(NULL, address, value & 0xff, 1); BX_DMA_THIS write_handler(NULL, address+1, value >> 8, 1); #else BX_DMA_THIS write(address, value & 0xff, 1); BX_DMA_THIS write(address+1, value >> 8, 1); #endif return; } BX_ERROR(("io write to address %08x, len=%u", (unsigned) address, (unsigned) io_len)); return; } BX_DEBUG(("write: address=%04x value=%02x", (unsigned) address, (unsigned) value)); #if BX_DMA_FLOPPY_IO < 1 /* if we're not supporting DMA/floppy IO just return */ return; #endif bx_bool ma_sl = (address >= 0xc0); switch (address) { case 0x00: case 0x02: case 0x04: case 0x06: case 0xc0: case 0xc4: case 0xc8: case 0xcc: channel = (address >> (1 + ma_sl)) & 0x03; BX_DEBUG((" DMA-%d base and current address, channel %d", ma_sl+1, channel)); if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */ BX_DMA_THIS s[ma_sl].chan[channel].base_address = value; BX_DMA_THIS s[ma_sl].chan[channel].current_address = value; } else { /* 2nd byte */ BX_DMA_THIS s[ma_sl].chan[channel].base_address |= (value << 8); BX_DMA_THIS s[ma_sl].chan[channel].current_address |= (value << 8); BX_DEBUG((" base = %04x", BX_DMA_THIS s[ma_sl].chan[channel].base_address)); BX_DEBUG((" curr = %04x", BX_DMA_THIS s[ma_sl].chan[channel].current_address)); } BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; break; case 0x01: case 0x03: case 0x05: case 0x07: case 0xc2: case 0xc6: case 0xca: case 0xce: channel = (address >> (1 + ma_sl)) & 0x03; BX_DEBUG((" DMA-%d base and current count, channel %d", ma_sl+1, channel)); if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */ BX_DMA_THIS s[ma_sl].chan[channel].base_count = value; BX_DMA_THIS s[ma_sl].chan[channel].current_count = value; } else { /* 2nd byte */ BX_DMA_THIS s[ma_sl].chan[channel].base_count |= (value << 8); BX_DMA_THIS s[ma_sl].chan[channel].current_count |= (value << 8); BX_DEBUG((" base = %04x", BX_DMA_THIS s[ma_sl].chan[channel].base_count)); BX_DEBUG((" curr = %04x", BX_DMA_THIS s[ma_sl].chan[channel].current_count)); } BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop; break; case 0x08: /* DMA-1: command register */ case 0xd0: /* DMA-2: command register */ if ((value & 0xfb) != 0x00) BX_ERROR(("write to command register: value 0x%02x not supported", (unsigned) value)); BX_DMA_THIS s[ma_sl].command_reg = value; BX_DMA_THIS s[ma_sl].ctrl_disabled = (value >> 2) & 0x01; control_HRQ(ma_sl); break; case 0x09: // DMA-1: request register case 0xd2: // DMA-2: request register channel = value & 0x03; // note: write to 0x0d / 0xda clears this register if (value & 0x04) { // set request bit BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4)); BX_DEBUG(("DMA-%d: set request bit for channel %u", ma_sl+1, channel)); } else { // clear request bit BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4)); BX_DEBUG(("DMA-%d: cleared request bit for channel %u", ma_sl+1, channel)); } control_HRQ(ma_sl); break; case 0x0a: case 0xd4: set_mask_bit = value & 0x04; channel = value & 0x03; BX_DMA_THIS s[ma_sl].mask[channel] = (set_mask_bit > 0); BX_DEBUG(("DMA-%d: set_mask_bit=%u, channel=%u, mask now=%02xh", ma_sl+1, set_mask_bit, channel, BX_DMA_THIS s[ma_sl].mask[channel])); control_HRQ(ma_sl); break; case 0x0b: /* DMA-1 mode register */ case 0xd6: /* DMA-2 mode register */ channel = value & 0x03; BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type = (value >> 6) & 0x03; BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement = (value >> 5) & 0x01; BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable = (value >> 4) & 0x01; BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type = (value >> 2) & 0x03; BX_DEBUG(("DMA-%d: mode register[%u] = %02x", ma_sl+1, channel, (unsigned) value)); break; case 0x0c: /* DMA-1 clear byte flip/flop */ case 0xd8: /* DMA-2 clear byte flip/flop */ BX_DEBUG(("DMA-%d: clear flip/flop", ma_sl+1)); BX_DMA_THIS s[ma_sl].flip_flop = 0; break; case 0x0d: // DMA-1: master clear case 0xda: // DMA-2: master clear BX_DEBUG(("DMA-%d: master clear", ma_sl+1)); // writing any value to this port resets DMA controller 1 / 2 // same action as a hardware reset // mask register is set (chan 0..3 disabled) // command, status, request, temporary, and byte flip-flop are all cleared reset_controller(ma_sl); break; case 0x0e: // DMA-1: clear mask register case 0xdc: // DMA-2: clear mask register BX_DEBUG(("DMA-%d: clear mask register", ma_sl+1)); BX_DMA_THIS s[ma_sl].mask[0] = 0; BX_DMA_THIS s[ma_sl].mask[1] = 0; BX_DMA_THIS s[ma_sl].mask[2] = 0; BX_DMA_THIS s[ma_sl].mask[3] = 0; control_HRQ(ma_sl); break; case 0x0f: // DMA-1: write all mask bits case 0xde: // DMA-2: write all mask bits BX_DEBUG(("DMA-%d: write all mask bits", ma_sl+1)); BX_DMA_THIS s[ma_sl].mask[0] = value & 0x01; value >>= 1; BX_DMA_THIS s[ma_sl].mask[1] = value & 0x01; value >>= 1; BX_DMA_THIS s[ma_sl].mask[2] = value & 0x01; value >>= 1; BX_DMA_THIS s[ma_sl].mask[3] = value & 0x01; control_HRQ(ma_sl); break; case 0x81: /* DMA-1 page register, channel 2 */ case 0x82: /* DMA-1 page register, channel 3 */ case 0x83: /* DMA-1 page register, channel 1 */ case 0x87: /* DMA-1 page register, channel 0 */ /* address bits A16-A23 for DMA channel */ channel = channelindex[address - 0x81]; BX_DMA_THIS s[0].chan[channel].page_reg = value; BX_DEBUG(("DMA-1: page register %d = %02x", channel, (unsigned) value)); break; case 0x89: /* DMA-2 page register, channel 2 */ case 0x8a: /* DMA-2 page register, channel 3 */ case 0x8b: /* DMA-2 page register, channel 1 */ case 0x8f: /* DMA-2 page register, channel 0 */ /* address bits A16-A23 for DMA channel */ channel = channelindex[address - 0x89]; BX_DMA_THIS s[1].chan[channel].page_reg = value; BX_DEBUG(("DMA-2: page register %d = %02x", channel + 4, (unsigned) value)); break; case 0x0080: case 0x0084: case 0x0085: case 0x0086: case 0x0088: case 0x008c: case 0x008d: case 0x008e: BX_DEBUG(("write: extra page register 0x%04x (unused)", (unsigned) address)); BX_DMA_THIS ext_page_reg[address & 0x0f] = value; break; default: BX_ERROR(("write ignored: %04xh = %02xh", (unsigned) address, (unsigned) value)); } } void bx_dma_c::set_DRQ(unsigned channel, bx_bool val) { Bit32u dma_base, dma_roof; bx_bool ma_sl; if (channel > 7) { BX_PANIC(("set_DRQ() channel > 7")); return; } ma_sl = (channel > 3); BX_DMA_THIS s[ma_sl].DRQ[channel & 0x03] = val; if (!BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used) { BX_PANIC(("set_DRQ(): channel %d not connected to device", channel)); return; } channel &= 0x03; if (!val) { // clear bit in status reg BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4)); control_HRQ(ma_sl); return; } BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4)); if ((BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_SINGLE) && (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_DEMAND) && (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_CASCADE)) { BX_PANIC(("set_DRQ: mode_type(%02x) not handled", BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type)); } dma_base = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) | (BX_DMA_THIS s[ma_sl].chan[channel].base_address << ma_sl); if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0) { dma_roof = dma_base + (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl); } else { dma_roof = dma_base - (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl); } if ((dma_base & (0x7fff0000 << ma_sl)) != (dma_roof & (0x7fff0000 << ma_sl))) { BX_INFO(("dma_base = 0x%08x", dma_base)); BX_INFO(("dma_base_count = 0x%08x", BX_DMA_THIS s[ma_sl].chan[channel].base_count)); BX_INFO(("dma_roof = 0x%08x", dma_roof)); BX_PANIC(("request outside %dk boundary", 64 << ma_sl)); } control_HRQ(ma_sl); } void bx_dma_c::control_HRQ(bx_bool ma_sl) { unsigned channel; // do nothing if controller is disabled if (BX_DMA_THIS s[ma_sl].ctrl_disabled) return; // deassert HRQ if no DRQ is pending if ((BX_DMA_THIS s[ma_sl].status_reg & 0xf0) == 0) { if (ma_sl) { bx_pc_system.set_HRQ(0); } else { BX_DMA_THIS set_DRQ(4, 0); } return; } // find highest priority channel for (channel=0; channel<4; channel++) { if ((BX_DMA_THIS s[ma_sl].status_reg & (1 << (channel+4))) && (BX_DMA_THIS s[ma_sl].mask[channel]==0)) { if (ma_sl) { // assert Hold ReQuest line to CPU bx_pc_system.set_HRQ(1); } else { // send DRQ to cascade channel of the master BX_DMA_THIS set_DRQ(4, 1); } break; } } } void bx_dma_c::raise_HLDA(void) { unsigned channel; bx_phy_address phy_addr; bx_bool ma_sl = 0; Bit16u maxlen, len = 1; Bit8u buffer[BX_DMA_BUFFER_SIZE]; BX_DMA_THIS HLDA = 1; // find highest priority channel for (channel=0; channel<4; channel++) { if ((BX_DMA_THIS s[1].status_reg & (1 << (channel+4))) && (BX_DMA_THIS s[1].mask[channel]==0)) { ma_sl = 1; break; } } if (channel == 0) { // master cascade channel BX_DMA_THIS s[1].DACK[0] = 1; for (channel=0; channel<4; channel++) { if ((BX_DMA_THIS s[0].status_reg & (1 << (channel+4))) && (BX_DMA_THIS s[0].mask[channel]==0)) { ma_sl = 0; break; } } } if (channel >= 4) { // wait till they're unmasked return; } phy_addr = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) | (BX_DMA_THIS s[ma_sl].chan[channel].current_address << ma_sl); if (!BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement) { maxlen = (BX_DMA_THIS s[ma_sl].chan[channel].current_count + 1) << ma_sl; BX_DMA_THIS TC = (maxlen <= BX_DMA_BUFFER_SIZE); if (maxlen > BX_DMA_BUFFER_SIZE) { maxlen = BX_DMA_BUFFER_SIZE; } } else { BX_DMA_THIS TC = (BX_DMA_THIS s[ma_sl].chan[channel].current_count == 0); maxlen = 1 << ma_sl; } if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 1) { // write // DMA controlled xfer of bytes from I/O to Memory if (!ma_sl) { if (BX_DMA_THIS h[channel].dmaWrite8) len = BX_DMA_THIS h[channel].dmaWrite8(buffer, maxlen); else BX_PANIC(("no dmaWrite handler for channel %u.", channel)); DEV_MEM_WRITE_PHYSICAL_DMA(phy_addr, len, buffer); BX_DBG_DMA_REPORT(phy_addr, len, BX_WRITE, buffer[0]); // FIXME } else { if (BX_DMA_THIS h[channel].dmaWrite16) len = BX_DMA_THIS h[channel].dmaWrite16((Bit16u*)buffer, maxlen / 2); else BX_PANIC(("no dmaWrite handler for channel %u.", channel)); DEV_MEM_WRITE_PHYSICAL_DMA(phy_addr, len, buffer); BX_DBG_DMA_REPORT(phy_addr, len * 2, BX_WRITE, buffer[0] | (buffer[1] << 16)); // FIXME } } else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 2) { // read // DMA controlled xfer of bytes from Memory to I/O if (!ma_sl) { DEV_MEM_READ_PHYSICAL_DMA(phy_addr, maxlen, buffer); if (BX_DMA_THIS h[channel].dmaRead8) len = BX_DMA_THIS h[channel].dmaRead8(buffer, maxlen); BX_DBG_DMA_REPORT(phy_addr, len, BX_READ, buffer[0]); // FIXME } else { DEV_MEM_READ_PHYSICAL_DMA(phy_addr, maxlen, buffer); if (BX_DMA_THIS h[channel].dmaRead16) len = BX_DMA_THIS h[channel].dmaRead16((Bit16u*)buffer, maxlen / 2); BX_DBG_DMA_REPORT(phy_addr, len * 2, BX_READ, buffer[0] | (buffer[1] << 16)); // FIXME } } else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 0) { // verify if (!ma_sl) { if (BX_DMA_THIS h[channel].dmaWrite8) len = BX_DMA_THIS h[channel].dmaWrite8(buffer, 1); else BX_PANIC(("no dmaWrite handler for channel %u.", channel)); } else { if (BX_DMA_THIS h[channel].dmaWrite16) len = BX_DMA_THIS h[channel].dmaWrite16((Bit16u*)buffer, 1); else BX_PANIC(("no dmaWrite handler for channel %u.", channel)); } } else { BX_PANIC(("hlda: transfer_type 3 is undefined")); } BX_DMA_THIS s[ma_sl].DACK[channel] = 1; // check for expiration of count, so we can signal TC and DACK(n) // at the same time. if (!BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement) BX_DMA_THIS s[ma_sl].chan[channel].current_address += len; else BX_DMA_THIS s[ma_sl].chan[channel].current_address--; BX_DMA_THIS s[ma_sl].chan[channel].current_count -= len; if (BX_DMA_THIS s[ma_sl].chan[channel].current_count == 0xffff) { // count expired, done with transfer // assert TC, deassert HRQ & DACK(n) lines BX_DMA_THIS s[ma_sl].status_reg |= (1 << channel); // hold TC in status reg if (BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable == 0) { // set mask bit if not in autoinit mode BX_DMA_THIS s[ma_sl].mask[channel] = 1; } else { // count expired, but in autoinit mode // reload count and base address BX_DMA_THIS s[ma_sl].chan[channel].current_address = BX_DMA_THIS s[ma_sl].chan[channel].base_address; BX_DMA_THIS s[ma_sl].chan[channel].current_count = BX_DMA_THIS s[ma_sl].chan[channel].base_count; } BX_DMA_THIS TC = 0; // clear TC, adapter card already notified BX_DMA_THIS HLDA = 0; bx_pc_system.set_HRQ(0); // clear HRQ to CPU BX_DMA_THIS s[ma_sl].DACK[channel] = 0; // clear DACK to adapter card if (!ma_sl) { BX_DMA_THIS set_DRQ(4, 0); // clear DRQ to cascade BX_DMA_THIS s[1].DACK[0] = 0; // clear DACK to cascade } } } #if BX_DEBUGGER void bx_dma_c::debug_dump(int argc, char **argv) { int ch, i, j; dbg_printf("i8237A DMA controller\n\n"); for (i = 0; i < 2; i++) { for (j = 0; j < 4; j++) { if (BX_DMA_THIS s[i].chan[j].used) { ch = i * 4 + j; dbg_printf("DMA channel %d", ch); if (ch == 4) { dbg_printf(" (cascade)\n"); } else if (BX_DMA_THIS s[i].DRQ[j] && !BX_DMA_THIS s[i].mask[j]) { dbg_printf(" (active)\n"); dbg_printf(" address: base=0x%04x, current=0x%04x\n", BX_DMA_THIS s[i].chan[j].base_address, BX_DMA_THIS s[i].chan[j].current_address); dbg_printf(" count: base=0x%04x, current=0x%04x\n", BX_DMA_THIS s[i].chan[j].base_count, BX_DMA_THIS s[i].chan[j].current_count); dbg_printf(" page: 0x%02x\n", BX_DMA_THIS s[i].chan[j].page_reg); dbg_printf(" mask: %u\n", BX_DMA_THIS s[i].mask[j]); dbg_printf(" flip_flop: %u\n", BX_DMA_THIS s[i].flip_flop); dbg_printf(" status_reg: 0x%02x\n", BX_DMA_THIS s[i].status_reg); dbg_printf(" mode_type: %u\n", BX_DMA_THIS s[i].chan[j].mode.mode_type); dbg_printf(" address_decrement: %u\n", BX_DMA_THIS s[i].chan[j].mode.address_decrement); dbg_printf(" autoinit_enable: %u\n", BX_DMA_THIS s[i].chan[j].mode.autoinit_enable); dbg_printf(" transfer_type: %u\n", BX_DMA_THIS s[i].chan[j].mode.transfer_type); } else { dbg_printf(" (not active: DRQ=%u, mask=%u)\n", BX_DMA_THIS s[i].DRQ[j], BX_DMA_THIS s[i].mask[j]); } } } } if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif bochs-2.6/iodev/serial_raw.h0000644000175000017500000000523412020641505015743 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: serial_raw.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if USE_RAW_SERIAL #ifdef __linux__ #include #endif #ifdef WIN32 // experimental raw serial receive support on win32 //#define WIN32_RECEIVE_RAW #endif #define P_NONE 0 #define P_ODD 1 #define P_EVEN 2 #define P_HIGH 3 #define P_LOW 4 #define RAW_EVENT_BREAK -1 #define RAW_EVENT_CTS_ON -2 #define RAW_EVENT_CTS_OFF -3 #define RAW_EVENT_DSR_ON -4 #define RAW_EVENT_DSR_OFF -5 #define RAW_EVENT_RING_ON -6 #define RAW_EVENT_RING_OFF -7 #define RAW_EVENT_RLSD_ON -8 #define RAW_EVENT_RLSD_OFF -9 #define RAW_EVENT_FRAME -10 #define RAW_EVENT_OVERRUN -11 #define RAW_EVENT_PARITY -12 #define THREAD_RX_BUFSIZE 8192 #define RX_BUFSIZE 256 class serial_raw : public logfunctions { public: serial_raw(const char *devname); virtual ~serial_raw(); void set_baudrate(int rate); void set_data_bits(int); void set_stop_bits(int); void set_parity_mode(int mode); void set_break(int mode); void set_modem_control(int ctrl); int get_modem_status(); void transmit(Bit8u byte); bx_bool ready_transmit(); bx_bool ready_receive(); int receive (); #ifdef WIN32_RECEIVE_RAW void serial_thread(); #endif private: void setup_port(); #ifdef WIN32_RECEIVE_RAW void enq_event(Bit16s event); #endif bx_bool present; unsigned rxdata_count; #ifdef WIN32 HANDLE hCOM; DCB dcb; BOOL DCBchanged; DWORD MSR_value; Bit16s rxdata_buffer[RX_BUFSIZE]; #ifdef WIN32_RECEIVE_RAW HANDLE hRawSerialThread; BOOL thread_active; BOOL thread_quit; OVERLAPPED rx_ovl; OVERLAPPED thread_ovl; unsigned thread_rxdata_count; Bit16s thread_rxdata_buffer[THREAD_RX_BUFSIZE]; #endif #endif }; #endif bochs-2.6/iodev/pit82c54.h0000644000175000017500000001040112020641505015065 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pit82c54.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* * Emulator of an Intel 8254/82C54 Programmable Interval Timer. * Greg Alexander */ #ifndef _PIT_82C54_H_ #define _PIT_82C54_H_ 1 typedef void (*out_handler_t)(bx_bool value); class pit_82C54 : public logfunctions { public: //Please do not use these. They are public because they have to be // to compile on some platforms. They are not to be used by other // classes. enum rw_status { LSByte=0, MSByte=1, LSByte_multiple=2, MSByte_multiple=3 }; private: enum { MAX_COUNTER=2, MAX_ADDRESS=3, CONTROL_ADDRESS=3, MAX_MODE=5 }; enum real_RW_status { LSB_real=1, MSB_real=2, BOTH_real=3 }; enum problem_type { UNL_2P_READ=1 }; struct counter_type { //Chip IOs; bx_bool GATE; //GATE Input value at end of cycle bx_bool OUTpin; //OUT output this cycle //Architected state; Bit32u count; //Counter value this cycle Bit16u outlatch; //Output latch this cycle Bit16u inlatch; //Input latch this cycle Bit8u status_latch; //Status Register data; Bit8u rw_mode; //2-bit R/W mode from command word register. Bit8u mode; //3-bit mode from command word register. bx_bool bcd_mode; //1-bit BCD vs. Binary setting. bx_bool null_count; //Null count bit of status register. //Latch status data; bx_bool count_LSB_latched; bx_bool count_MSB_latched; bx_bool status_latched; //Miscelaneous State; Bit32u count_binary; //Value of the count in binary. bx_bool triggerGATE; //Whether we saw GATE rise this cycle. rw_status write_state; //Read state this cycle rw_status read_state; //Read state this cycle bx_bool count_written; //Whether a count written since programmed bx_bool first_pass; //Whether or not this is the first loaded count. bx_bool state_bit_1; //Miscelaneous state bits. bx_bool state_bit_2; Bit32u next_change_time; //Next time something besides count changes. //0 means never. out_handler_t out_handler; // OUT pin callback (for IRQ0) }; counter_type counter[3]; Bit8u controlword; int seen_problems; void latch_counter(counter_type & thisctr); void set_OUT (counter_type & thisctr, bx_bool data); void set_count (counter_type & thisctr, Bit32u data) BX_CPP_AttrRegparmN(2); void set_count_to_binary (counter_type & thisctr) BX_CPP_AttrRegparmN(1); void set_binary_to_count (counter_type & thisctr) BX_CPP_AttrRegparmN(1); void decrement (counter_type & thisctr) BX_CPP_AttrRegparmN(1); void decrement_multiple(counter_type & thisctr, Bit32u cycles) BX_CPP_AttrRegparmN(2); void clock(Bit8u cnum) BX_CPP_AttrRegparmN(1); void print_counter(counter_type & thisctr); public: pit_82C54 (void); void init (void); void reset (unsigned type); void register_state(bx_param_c *parent); void clock_all(Bit32u cycles); void clock_multiple(Bit8u cnum, Bit32u cycles); Bit8u read(Bit8u address); void write(Bit8u address, Bit8u data); void set_GATE(Bit8u cnum, bx_bool data); bx_bool read_GATE(Bit8u cnum); bx_bool read_OUT(Bit8u cnum); void set_OUT_handler(Bit8u cnum, out_handler_t outh); Bit32u get_clock_event_time(Bit8u cnum); Bit32u get_next_event_time(void); Bit16u get_inlatch(int countnum); void print_cnum(Bit8u cnum); }; #endif bochs-2.6/iodev/ioapic.cc0000644000175000017500000002363412020641505015221 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ioapic.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_APIC #include "ioapic.h" #define LOG_THIS theIOAPIC-> bx_ioapic_c *theIOAPIC = NULL; int libioapic_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theIOAPIC = new bx_ioapic_c(); bx_devices.pluginIOAPIC = theIOAPIC; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theIOAPIC, BX_PLUGIN_IOAPIC); return(0); // Success } void libioapic_LTX_plugin_fini(void) { bx_devices.pluginIOAPIC = &bx_devices.stubIOAPIC; delete theIOAPIC; } static bx_bool ioapic_read(bx_phy_address a20addr, unsigned len, void *data, void *param) { if((a20addr & ~0x3) != ((a20addr+len-1) & ~0x3)) { BX_PANIC(("I/O APIC read at address 0x" FMT_PHY_ADDRX " spans 32-bit boundary !", a20addr)); return 1; } Bit32u value = theIOAPIC->read_aligned(a20addr & ~0x3); if(len == 4) { // must be 32-bit aligned *((Bit32u *)data) = value; return 1; } // handle partial read, independent of endian-ness value >>= (a20addr&3)*8; if (len == 1) *((Bit8u *) data) = value & 0xff; else if (len == 2) *((Bit16u *)data) = value & 0xffff; else BX_PANIC(("Unsupported I/O APIC read at address 0x" FMT_PHY_ADDRX ", len=%d", a20addr, len)); return 1; } static bx_bool ioapic_write(bx_phy_address a20addr, unsigned len, void *data, void *param) { if(a20addr & 0xf) { BX_PANIC(("I/O apic write at unaligned address 0x" FMT_PHY_ADDRX, a20addr)); return 1; } if (len == 4) { theIOAPIC->write_aligned(a20addr, *((Bit32u*) data)); } else { if ((a20addr & 0xff) != 0) BX_PANIC(("I/O apic write with len=%d (should be 4) at address 0x" FMT_PHY_ADDRX, len, a20addr)); if (len == 2) theIOAPIC->write_aligned(a20addr, (Bit32u) *((Bit16u*) data)); else if (len == 1) theIOAPIC->write_aligned(a20addr, (Bit32u) *((Bit8u*) data)); else BX_PANIC(("Unsupported I/O APIC write at address 0x" FMT_PHY_ADDRX ", len=%d", a20addr, len)); } return 1; } void bx_io_redirect_entry_t::sprintf_self(char *buf) { sprintf(buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x", (unsigned) destination(), (unsigned) is_masked(), (unsigned) trigger_mode(), (unsigned) remote_irr(), (unsigned) pin_polarity(), (unsigned) delivery_status(), (unsigned) destination_mode(), (unsigned) delivery_mode(), (unsigned) vector()); } void bx_io_redirect_entry_t::register_state(bx_param_c *parent) { BXRS_HEX_PARAM_SIMPLE(parent, lo); BXRS_HEX_PARAM_SIMPLE(parent, hi); } #define BX_IOAPIC_BASE_ADDR (0xfec00000) #define BX_IOAPIC_DEFAULT_ID (BX_SMP_PROCESSORS) bx_ioapic_c::bx_ioapic_c(): base_addr(BX_IOAPIC_BASE_ADDR) { set_id(BX_IOAPIC_DEFAULT_ID); put("ioapic", "IOAP"); } bx_ioapic_c::~bx_ioapic_c() { SIM->get_bochs_root()->remove("ioapic"); BX_DEBUG(("Exit")); } void bx_ioapic_c::init(void) { BX_INFO(("initializing I/O APIC")); DEV_register_memory_handlers(theIOAPIC, ioapic_read, ioapic_write, base_addr, base_addr + 0xfff); reset(BX_RESET_HARDWARE); #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("ioapic", this); #endif } void bx_ioapic_c::reset(unsigned type) { // all interrupts masked for (int i=0; i> 1; if (index >= 0 && index < BX_IOAPIC_NUM_PINS) { bx_io_redirect_entry_t *entry = ioredtbl + index; data = (ioregsel&1) ? entry->get_hi_part() : entry->get_lo_part(); break; } BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel)); } return data; } void bx_ioapic_c::write_aligned(bx_phy_address address, Bit32u value) { BX_DEBUG(("IOAPIC: write aligned addr=%08x, data=%08x", (unsigned) address, value)); address &= 0xff; if (address == 0x00) { ioregsel = value; return; } else { if (address != 0x10) BX_PANIC(("IOAPIC: write to unsupported address")); } // only reached when writing data register switch (ioregsel) { case 0x00: // set APIC ID { Bit8u newid = (value >> 24) & apic_id_mask; BX_INFO(("IOAPIC: setting id to 0x%x", newid)); set_id (newid); return; } case 0x01: // version case 0x02: // arbitration id BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x", ioregsel)); return; default: int index = (ioregsel - 0x10) >> 1; if (index >= 0 && index < BX_IOAPIC_NUM_PINS) { bx_io_redirect_entry_t *entry = ioredtbl + index; if (ioregsel&1) entry->set_hi_part(value); else entry->set_lo_part(value); char buf[1024]; entry->sprintf_self(buf); BX_DEBUG(("IOAPIC: now entry[%d] is %s", index, buf)); service_ioapic(); return; } BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel)); } } void bx_ioapic_c::set_irq_level(Bit8u int_in, bx_bool level) { if (int_in == 0) { // timer connected to pin #2 int_in = 2; } BX_DEBUG(("set_irq_level(): INTIN%d: level=%d", int_in, level)); if (int_in < BX_IOAPIC_NUM_PINS) { Bit32u bit = 1<trigger_mode()) { // level triggered if (level) { intin |= bit; irr |= bit; service_ioapic(); } else { intin &= ~bit; irr &= ~bit; } } else { // edge triggered if (level) { intin |= bit; irr |= bit; service_ioapic(); } else { intin &= ~bit; } } } } } void bx_ioapic_c::receive_eoi(Bit8u vector) { BX_DEBUG(("IOAPIC: received EOI for vector %d", vector)); } void bx_ioapic_c::service_ioapic() { static unsigned int stuck = 0; Bit8u vector = 0; // look in IRR and deliver any interrupts that are not masked. BX_DEBUG(("IOAPIC: servicing")); for (unsigned bit=0; bit < BX_IOAPIC_NUM_PINS; bit++) { Bit32u mask = 1<is_masked()) { // clear irr bit and deliver if (entry->delivery_mode() == 7) { vector = DEV_pic_iac(); } else { vector = entry->vector(); } bx_bool done = apic_bus_deliver_interrupt(vector, entry->destination(), entry->delivery_mode(), entry->destination_mode(), entry->pin_polarity(), entry->trigger_mode()); if (done) { if (! entry->trigger_mode()) irr &= ~mask; entry->clear_delivery_status(); stuck = 0; } else { entry->set_delivery_status(); stuck++; if (stuck > 5) BX_INFO(("vector %#x stuck?", vector)); } } else { BX_DEBUG(("service_ioapic(): INTIN%d is masked", bit)); } } } } void bx_ioapic_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "ioapic", "IOAPIC State"); BXRS_HEX_PARAM_SIMPLE(list, ioregsel); BXRS_HEX_PARAM_SIMPLE(list, intin); BXRS_HEX_PARAM_SIMPLE(list, irr); bx_list_c *table = new bx_list_c(list, "ioredtbl"); for (unsigned i=0; isprintf_self(buf); dbg_printf("entry[%d]: %s\n", i, buf); } if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif #endif /* if BX_SUPPORT_APIC */ bochs-2.6/iodev/devices.cc0000644000175000017500000007711012020641505015375 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: devices.cc 11349 2012-08-20 07:35:30Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // I/O port handlers API Copyright (C) 2003 by Frank Cornelis // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "iodev.h" #include "iodev/virt_timer.h" #include "iodev/slowdown_timer.h" #define LOG_THIS bx_devices. /* main memory size (in Kbytes) * subtract 1k for extended BIOS area * report only base memory, not extended mem */ #define BASE_MEMORY_IN_K 640 bx_devices_c bx_devices; // constructor for bx_devices_c bx_devices_c::bx_devices_c() { put("devices", "DEV"); read_port_to_handler = NULL; write_port_to_handler = NULL; io_read_handlers.next = NULL; io_read_handlers.handler_name = NULL; io_write_handlers.next = NULL; io_write_handlers.handler_name = NULL; init_stubs(); for (unsigned i=0; i < BX_MAX_IRQS; i++) { irq_handler_name[i] = NULL; } } bx_devices_c::~bx_devices_c() { // nothing needed for now timer_handle = BX_NULL_TIMER_HANDLE; } void bx_devices_c::init_stubs() { pluginPciBridge = &stubPci; pluginPci2IsaBridge = &stubPci2Isa; pluginPciIdeController = &stubPciIde; #if BX_SUPPORT_PCI pluginACPIController = &stubACPIController; #endif pluginKeyboard = &stubKeyboard; pluginDmaDevice = &stubDma; pluginFloppyDevice = &stubFloppy; pluginCmosDevice = &stubCmos; pluginVgaDevice = &stubVga; pluginPicDevice = &stubPic; pluginHardDrive = &stubHardDrive; pluginSpeaker = &stubSpeaker; #if BX_SUPPORT_IODEBUG pluginIODebug = &stubIODebug; #endif #if BX_SUPPORT_APIC pluginIOAPIC = &stubIOAPIC; #endif #if BX_SUPPORT_GAMEPORT pluginGameport = &stubGameport; #endif #if BX_SUPPORT_PCIUSB pluginUsbDevCtl = &stubUsbDevCtl; #endif #if BX_SUPPORT_SOUNDLOW pluginSoundModCtl = &stubSoundModCtl; #endif #if BX_NETWORKING pluginNetModCtl = &stubNetModCtl; #endif } void bx_devices_c::init(BX_MEM_C *newmem) { unsigned i; const char def_name[] = "Default"; const char *vga_ext; BX_DEBUG(("Init $Id: devices.cc 11349 2012-08-20 07:35:30Z vruppert $")); mem = newmem; /* set builtin default handlers, will be overwritten by the real default handler */ register_default_io_read_handler(NULL, &default_read_handler, def_name, 7); io_read_handlers.next = &io_read_handlers; io_read_handlers.prev = &io_read_handlers; io_read_handlers.usage_count = 0; // not used with the default handler register_default_io_write_handler(NULL, &default_write_handler, def_name, 7); io_write_handlers.next = &io_write_handlers; io_write_handlers.prev = &io_write_handlers; io_write_handlers.usage_count = 0; // not used with the default handler if (read_port_to_handler) delete [] read_port_to_handler; if (write_port_to_handler) delete [] write_port_to_handler; read_port_to_handler = new struct io_handler_struct *[PORTS]; write_port_to_handler = new struct io_handler_struct *[PORTS]; /* set handlers to the default one */ for (i=0; i < PORTS; i++) { read_port_to_handler[i] = &io_read_handlers; write_port_to_handler[i] = &io_write_handlers; } for (i=0; i < BX_MAX_IRQS; i++) { delete [] irq_handler_name[i]; irq_handler_name[i] = NULL; } // removable devices init bx_keyboard.dev = NULL; bx_keyboard.enq_event = NULL; for (i=0; i < 2; i++) { bx_mouse[i].dev = NULL; bx_mouse[i].enq_event = NULL; bx_mouse[i].enabled_changed = NULL; } // common mouse settings mouse_captured = SIM->get_param_bool(BXPN_MOUSE_ENABLED)->get(); mouse_type = SIM->get_param_enum(BXPN_MOUSE_TYPE)->get(); // register as soon as possible - the devices want to have their timers ! bx_virt_timer.init(); bx_slowdown_timer.init(); // BBD: At present, the only difference between "core" and "optional" // plugins is that initialization and reset of optional plugins is handled // by the plugin device list (). Init and reset of core plugins is done // "by hand" in this file. Basically, we're using core plugins when we // want to control the init order. // PLUG_load_plugin(hdimage, PLUGTYPE_CORE); #if BX_NETWORKING network_enabled = is_network_enabled(); if (network_enabled) PLUG_load_plugin(netmod, PLUGTYPE_CORE); #endif #if BX_SUPPORT_SOUNDLOW sound_enabled = is_sound_enabled(); if (sound_enabled) PLUG_load_plugin(soundmod, PLUGTYPE_CORE); #endif // PCI logic (i440FX) if (SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) { #if BX_SUPPORT_PCI PLUG_load_plugin(pci, PLUGTYPE_CORE); PLUG_load_plugin(pci2isa, PLUGTYPE_CORE); #if BX_SUPPORT_PCIUSB usb_enabled = is_usb_enabled(); if (usb_enabled) PLUG_load_plugin(usb_common, PLUGTYPE_CORE); #endif PLUG_load_plugin(acpi, PLUGTYPE_STANDARD); #else BX_ERROR(("Bochs is not compiled with PCI support")); #endif } PLUG_load_plugin(cmos, PLUGTYPE_CORE); PLUG_load_plugin(dma, PLUGTYPE_CORE); PLUG_load_plugin(pic, PLUGTYPE_CORE); PLUG_load_plugin(pit, PLUGTYPE_CORE); PLUG_load_plugin(floppy, PLUGTYPE_CORE); vga_ext = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(); if (!strcmp(vga_ext, "cirrus")) { #if BX_SUPPORT_CLGD54XX PLUG_load_plugin(svga_cirrus, PLUGTYPE_CORE); #else BX_ERROR(("Bochs is not compiled with Cirrus support")); #endif } else { PLUG_load_plugin(vga, PLUGTYPE_CORE); } #if BX_SUPPORT_APIC PLUG_load_plugin(ioapic, PLUGTYPE_STANDARD); #endif PLUG_load_plugin(keyboard, PLUGTYPE_STANDARD); #if BX_SUPPORT_BUSMOUSE if (mouse_type == BX_MOUSE_TYPE_BUS) { PLUG_load_plugin(busmouse, PLUGTYPE_OPTIONAL); } #endif if (is_harddrv_enabled()) { PLUG_load_plugin(harddrv, PLUGTYPE_STANDARD); #if BX_SUPPORT_PCI if (SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) { PLUG_load_plugin(pci_ide, PLUGTYPE_STANDARD); } #endif } // system hardware register_io_read_handler(this, &read_handler, 0x0092, "Port 92h System Control", 1); register_io_write_handler(this, &write_handler, 0x0092, "Port 92h System Control", 1); // misc. CMOS Bit64u memory_in_k = mem->get_memory_len() / 1024; Bit64u extended_memory_in_k = memory_in_k > 1024 ? (memory_in_k - 1024) : 0; if (extended_memory_in_k > 0xfc00) extended_memory_in_k = 0xfc00; DEV_cmos_set_reg(0x15, (Bit8u) BASE_MEMORY_IN_K); DEV_cmos_set_reg(0x16, (Bit8u) (BASE_MEMORY_IN_K >> 8)); DEV_cmos_set_reg(0x17, (Bit8u) (extended_memory_in_k & 0xff)); DEV_cmos_set_reg(0x18, (Bit8u) ((extended_memory_in_k >> 8) & 0xff)); DEV_cmos_set_reg(0x30, (Bit8u) (extended_memory_in_k & 0xff)); DEV_cmos_set_reg(0x31, (Bit8u) ((extended_memory_in_k >> 8) & 0xff)); Bit64u extended_memory_in_64k = memory_in_k > 16384 ? (memory_in_k - 16384) / 64 : 0; // Limit to 3 GB - 16 MB. PCI Memory Address Space starts at 3 GB. if (extended_memory_in_64k > 0xbf00) extended_memory_in_64k = 0xbf00; DEV_cmos_set_reg(0x34, (Bit8u) (extended_memory_in_64k & 0xff)); DEV_cmos_set_reg(0x35, (Bit8u) ((extended_memory_in_64k >> 8) & 0xff)); Bit64u memory_above_4gb = (mem->get_memory_len() > BX_CONST64(0x100000000)) ? (mem->get_memory_len() - BX_CONST64(0x100000000)) : 0; if (memory_above_4gb) { DEV_cmos_set_reg(0x5b, (Bit8u)(memory_above_4gb >> 16)); DEV_cmos_set_reg(0x5c, (Bit8u)(memory_above_4gb >> 24)); DEV_cmos_set_reg(0x5d, memory_above_4gb >> 32); } if (timer_handle != BX_NULL_TIMER_HANDLE) { timer_handle = bx_pc_system.register_timer(this, timer_handler, (unsigned) BX_IODEV_HANDLER_PERIOD, 1, 1, "devices.cc"); } // Clear fields for bulk IO acceleration transfers. bulkIOHostAddr = 0; bulkIOQuantumsRequested = 0; bulkIOQuantumsTransferred = 0; bx_init_plugins(); /* now perform checksum of CMOS memory */ DEV_cmos_checksum(); } void bx_devices_c::reset(unsigned type) { mem->disable_smram(); bx_reset_plugins(type); } void bx_devices_c::register_state() { bx_virt_timer.register_state(); bx_plugins_register_state(); } void bx_devices_c::after_restore_state() { bx_slowdown_timer.after_restore_state(); bx_virt_timer.set_realtime_delay(); bx_plugins_after_restore_state(); } void bx_devices_c::exit() { // delete i/o handlers before unloading plugins struct io_handler_struct *io_read_handler = io_read_handlers.next; struct io_handler_struct *curr = NULL; while (io_read_handler != &io_read_handlers) { io_read_handler->prev->next = io_read_handler->next; io_read_handler->next->prev = io_read_handler->prev; curr = io_read_handler; io_read_handler = io_read_handler->next; delete [] curr->handler_name; delete curr; } struct io_handler_struct *io_write_handler = io_write_handlers.next; while (io_write_handler != &io_write_handlers) { io_write_handler->prev->next = io_write_handler->next; io_write_handler->next->prev = io_write_handler->prev; curr = io_write_handler; io_write_handler = io_write_handler->next; delete [] curr->handler_name; delete curr; } bx_virt_timer.setup(); bx_slowdown_timer.exit(); // unload optional and user plugins first bx_unload_plugins(); bx_unload_core_plugins(); PLUG_unload_plugin(hdimage); #if BX_NETWORKING if (network_enabled) PLUG_unload_plugin(netmod); #endif #if BX_SUPPORT_SOUNDLOW if (sound_enabled) PLUG_unload_plugin(soundmod); #endif #if BX_SUPPORT_PCIUSB if (usb_enabled) PLUG_unload_plugin(usb_common); #endif init_stubs(); } Bit32u bx_devices_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_DEV_SMF bx_devices_c *class_ptr = (bx_devices_c *) this_ptr; return class_ptr->port92_read(address, io_len); } Bit32u bx_devices_c::port92_read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_DEV_SMF BX_DEBUG(("port92h read partially supported!!!")); BX_DEBUG((" returning %02x", (unsigned) (BX_GET_ENABLE_A20() << 1))); return(BX_GET_ENABLE_A20() << 1); } void bx_devices_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_DEV_SMF bx_devices_c *class_ptr = (bx_devices_c *) this_ptr; class_ptr->port92_write(address, value, io_len); } void bx_devices_c::port92_write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_DEV_SMF BX_DEBUG(("port92h write of %02x partially supported!!!", (unsigned) value)); BX_DEBUG(("A20: set_enable_a20() called")); BX_SET_ENABLE_A20((value & 0x02) >> 1); BX_DEBUG(("A20: now %u", (unsigned) BX_GET_ENABLE_A20())); if (value & 0x01) { /* high speed reset */ BX_INFO(("iowrite to port0x92 : reset resquested")); bx_pc_system.Reset(BX_RESET_SOFTWARE); } } // This defines the builtin default read handler, // so Bochs does not segfault if unmapped is not loaded Bit32u bx_devices_c::default_read_handler(void *this_ptr, Bit32u address, unsigned io_len) { UNUSED(this_ptr); return 0xffffffff; } // This defines the builtin default write handler, // so Bochs does not segfault if unmapped is not loaded void bx_devices_c::default_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { UNUSED(this_ptr); } void bx_devices_c::timer_handler(void *this_ptr) { bx_devices_c *class_ptr = (bx_devices_c *) this_ptr; class_ptr->timer(); } void bx_devices_c::timer() { // separate calls to bx_gui->handle_events from the keyboard code. { static int multiple=0; if (++multiple==10) { multiple=0; SIM->periodic(); if (! bx_pc_system.kill_bochs_request) bx_gui->handle_events(); } } } bx_bool bx_devices_c::register_irq(unsigned irq, const char *name) { if (irq >= BX_MAX_IRQS) { BX_PANIC(("IO device %s registered with IRQ=%d above %u", name, irq, (unsigned) BX_MAX_IRQS-1)); return 0; } if (irq_handler_name[irq]) { BX_PANIC(("IRQ %u conflict, %s with %s", irq, irq_handler_name[irq], name)); return 0; } irq_handler_name[irq] = new char[strlen(name)+1]; strcpy(irq_handler_name[irq], name); return 1; } bx_bool bx_devices_c::unregister_irq(unsigned irq, const char *name) { if (irq >= BX_MAX_IRQS) { BX_PANIC(("IO device %s tried to unregister IRQ %d above %u", name, irq, (unsigned) BX_MAX_IRQS-1)); return 0; } if (!irq_handler_name[irq]) { BX_INFO(("IO device %s tried to unregister IRQ %d, not registered", name, irq)); return 0; } if (strcmp(irq_handler_name[irq], name)) { BX_INFO(("IRQ %u not registered to %s but to %s", irq, name, irq_handler_name[irq])); return 0; } delete [] irq_handler_name[irq]; irq_handler_name[irq] = NULL; return 1; } bx_bool bx_devices_c::register_io_read_handler(void *this_ptr, bx_read_handler_t f, Bit32u addr, const char *name, Bit8u mask) { addr &= 0xffff; if (!f) return 0; /* first check if the port already has a handlers != the default handler */ if (read_port_to_handler[addr] && read_port_to_handler[addr] != &io_read_handlers) { // the default BX_ERROR(("IO device address conflict(read) at IO address %Xh", (unsigned) addr)); BX_ERROR((" conflicting devices: %s & %s", read_port_to_handler[addr]->handler_name, name)); return 0; } /* first find existing handle for function or create new one */ struct io_handler_struct *curr = &io_read_handlers; struct io_handler_struct *io_read_handler = NULL; do { if (curr->funct == f && curr->mask == mask && curr->this_ptr == this_ptr && !strcmp(curr->handler_name, name)) { // really want the same name too io_read_handler = curr; break; } curr = curr->next; } while (curr->next != &io_read_handlers); if (!io_read_handler) { io_read_handler = new struct io_handler_struct; io_read_handler->funct = (void *)f; io_read_handler->this_ptr = this_ptr; io_read_handler->handler_name = new char[strlen(name)+1]; strcpy(io_read_handler->handler_name, name); io_read_handler->mask = mask; io_read_handler->usage_count = 0; // add the handler to the double linked list of handlers io_read_handlers.prev->next = io_read_handler; io_read_handler->next = &io_read_handlers; io_read_handler->prev = io_read_handlers.prev; io_read_handlers.prev = io_read_handler; } io_read_handler->usage_count++; read_port_to_handler[addr] = io_read_handler; return 1; // address mapped successfully } bx_bool bx_devices_c::register_io_write_handler(void *this_ptr, bx_write_handler_t f, Bit32u addr, const char *name, Bit8u mask) { addr &= 0xffff; if (!f) return 0; /* first check if the port already has a handlers != the default handler */ if (write_port_to_handler[addr] && write_port_to_handler[addr] != &io_write_handlers) { // the default BX_ERROR(("IO device address conflict(write) at IO address %Xh", (unsigned) addr)); BX_ERROR((" conflicting devices: %s & %s", write_port_to_handler[addr]->handler_name, name)); return 0; } /* first find existing handle for function or create new one */ struct io_handler_struct *curr = &io_write_handlers; struct io_handler_struct *io_write_handler = NULL; do { if (curr->funct == f && curr->mask == mask && curr->this_ptr == this_ptr && !strcmp(curr->handler_name, name)) { // really want the same name too io_write_handler = curr; break; } curr = curr->next; } while (curr->next != &io_write_handlers); if (!io_write_handler) { io_write_handler = new struct io_handler_struct; io_write_handler->funct = (void *)f; io_write_handler->this_ptr = this_ptr; io_write_handler->handler_name = new char[strlen(name)+1]; strcpy(io_write_handler->handler_name, name); io_write_handler->mask = mask; io_write_handler->usage_count = 0; // add the handler to the double linked list of handlers io_write_handlers.prev->next = io_write_handler; io_write_handler->next = &io_write_handlers; io_write_handler->prev = io_write_handlers.prev; io_write_handlers.prev = io_write_handler; } io_write_handler->usage_count++; write_port_to_handler[addr] = io_write_handler; return 1; // address mapped successfully } bx_bool bx_devices_c::register_io_read_handler_range(void *this_ptr, bx_read_handler_t f, Bit32u begin_addr, Bit32u end_addr, const char *name, Bit8u mask) { Bit32u addr; begin_addr &= 0xffff; end_addr &= 0xffff; if (end_addr < begin_addr) { BX_ERROR(("!!! end_addr < begin_addr !!!")); return 0; } if (!f) { BX_ERROR(("!!! f == NULL !!!")); return 0; } /* first check if the port already has a handlers != the default handler */ for (addr = begin_addr; addr <= end_addr; addr++) if (read_port_to_handler[addr] && read_port_to_handler[addr] != &io_read_handlers) { // the default BX_ERROR(("IO device address conflict(read) at IO address %Xh", (unsigned) addr)); BX_ERROR((" conflicting devices: %s & %s", read_port_to_handler[addr]->handler_name, name)); return 0; } /* first find existing handle for function or create new one */ struct io_handler_struct *curr = &io_read_handlers; struct io_handler_struct *io_read_handler = NULL; do { if (curr->funct == f && curr->mask == mask && curr->this_ptr == this_ptr && !strcmp(curr->handler_name, name)) { io_read_handler = curr; break; } curr = curr->next; } while (curr->next != &io_read_handlers); if (!io_read_handler) { io_read_handler = new struct io_handler_struct; io_read_handler->funct = (void *)f; io_read_handler->this_ptr = this_ptr; io_read_handler->handler_name = new char[strlen(name)+1]; strcpy(io_read_handler->handler_name, name); io_read_handler->mask = mask; io_read_handler->usage_count = 0; // add the handler to the double linked list of handlers io_read_handlers.prev->next = io_read_handler; io_read_handler->next = &io_read_handlers; io_read_handler->prev = io_read_handlers.prev; io_read_handlers.prev = io_read_handler; } io_read_handler->usage_count += end_addr - begin_addr + 1; for (addr = begin_addr; addr <= end_addr; addr++) read_port_to_handler[addr] = io_read_handler; return 1; // address mapped successfully } bx_bool bx_devices_c::register_io_write_handler_range(void *this_ptr, bx_write_handler_t f, Bit32u begin_addr, Bit32u end_addr, const char *name, Bit8u mask) { Bit32u addr; begin_addr &= 0xffff; end_addr &= 0xffff; if (end_addr < begin_addr) { BX_ERROR(("!!! end_addr < begin_addr !!!")); return 0; } if (!f) { BX_ERROR(("!!! f == NULL !!!")); return 0; } /* first check if the port already has a handlers != the default handler */ for (addr = begin_addr; addr <= end_addr; addr++) if (write_port_to_handler[addr] && write_port_to_handler[addr] != &io_write_handlers) { // the default BX_ERROR(("IO device address conflict(read) at IO address %Xh", (unsigned) addr)); BX_ERROR((" conflicting devices: %s & %s", write_port_to_handler[addr]->handler_name, name)); return 0; } /* first find existing handle for function or create new one */ struct io_handler_struct *curr = &io_write_handlers; struct io_handler_struct *io_write_handler = NULL; do { if (curr->funct == f && curr->mask == mask && curr->this_ptr == this_ptr && !strcmp(curr->handler_name, name)) { io_write_handler = curr; break; } curr = curr->next; } while (curr->next != &io_write_handlers); if (!io_write_handler) { io_write_handler = new struct io_handler_struct; io_write_handler->funct = (void *)f; io_write_handler->this_ptr = this_ptr; io_write_handler->handler_name = new char[strlen(name)+1]; strcpy(io_write_handler->handler_name, name); io_write_handler->mask = mask; io_write_handler->usage_count = 0; // add the handler to the double linked list of handlers io_write_handlers.prev->next = io_write_handler; io_write_handler->next = &io_write_handlers; io_write_handler->prev = io_write_handlers.prev; io_write_handlers.prev = io_write_handler; } io_write_handler->usage_count += end_addr - begin_addr + 1; for (addr = begin_addr; addr <= end_addr; addr++) write_port_to_handler[addr] = io_write_handler; return 1; // address mapped successfully } // Registration of default handlers (mainly be the unmapped device) bx_bool bx_devices_c::register_default_io_read_handler(void *this_ptr, bx_read_handler_t f, const char *name, Bit8u mask) { io_read_handlers.funct = (void *)f; io_read_handlers.this_ptr = this_ptr; if (io_read_handlers.handler_name) { delete [] io_read_handlers.handler_name; } io_read_handlers.handler_name = new char[strlen(name)+1]; strcpy(io_read_handlers.handler_name, name); io_read_handlers.mask = mask; return 1; } bx_bool bx_devices_c::register_default_io_write_handler(void *this_ptr, bx_write_handler_t f, const char *name, Bit8u mask) { io_write_handlers.funct = (void *)f; io_write_handlers.this_ptr = this_ptr; if (io_write_handlers.handler_name) { delete [] io_write_handlers.handler_name; } io_write_handlers.handler_name = new char[strlen(name)+1]; strcpy(io_write_handlers.handler_name, name); io_write_handlers.mask = mask; return 1; } bx_bool bx_devices_c::unregister_io_read_handler(void *this_ptr, bx_read_handler_t f, Bit32u addr, Bit8u mask) { addr &= 0xffff; struct io_handler_struct *io_read_handler = read_port_to_handler[addr]; //BX_INFO(("Unregistering I/O read handler at %#x", addr)); if (!io_read_handler) { BX_ERROR((">>> NO IO_READ_HANDLER <<<")); return 0; } if (io_read_handler == &io_read_handlers) { BX_ERROR((">>> CANNOT UNREGISTER THE DEFAULT IO_READ_HANDLER <<<")); return 0; // cannot unregister the default handler } if (io_read_handler->funct != f) { BX_ERROR((">>> NOT THE SAME IO_READ_HANDLER FUNC <<<")); return 0; } if (io_read_handler->this_ptr != this_ptr) { BX_ERROR((">>> NOT THE SAME IO_READ_HANDLER THIS_PTR <<<")); return 0; } if (io_read_handler->mask != mask) { BX_ERROR((">>> NOT THE SAME IO_READ_HANDLER MASK <<<")); return 0; } read_port_to_handler[addr] = &io_read_handlers; // reset to default io_read_handler->usage_count--; if (!io_read_handler->usage_count) { // kill this handler entry io_read_handler->prev->next = io_read_handler->next; io_read_handler->next->prev = io_read_handler->prev; delete [] io_read_handler->handler_name; delete io_read_handler; } return 1; } bx_bool bx_devices_c::unregister_io_write_handler(void *this_ptr, bx_write_handler_t f, Bit32u addr, Bit8u mask) { addr &= 0xffff; struct io_handler_struct *io_write_handler = write_port_to_handler[addr]; if (!io_write_handler) return 0; if (io_write_handler == &io_write_handlers) return 0; // cannot unregister the default handler if (io_write_handler->funct != f) return 0; if (io_write_handler->this_ptr != this_ptr) return 0; if (io_write_handler->mask != mask) return 0; write_port_to_handler[addr] = &io_write_handlers; // reset to default io_write_handler->usage_count--; if (!io_write_handler->usage_count) { // kill this handler entry io_write_handler->prev->next = io_write_handler->next; io_write_handler->next->prev = io_write_handler->prev; delete [] io_write_handler->handler_name; delete io_write_handler; } return 1; } bx_bool bx_devices_c::unregister_io_read_handler_range(void *this_ptr, bx_read_handler_t f, Bit32u begin, Bit32u end, Bit8u mask) { begin &= 0xffff; end &= 0xffff; Bit32u addr; bx_bool ret = 1; /* * the easy way this time */ for (addr = begin; addr <= end; addr++) if (!unregister_io_read_handler(this_ptr, f, addr, mask)) ret = 0; return ret; } bx_bool bx_devices_c::unregister_io_write_handler_range(void *this_ptr, bx_write_handler_t f, Bit32u begin, Bit32u end, Bit8u mask) { begin &= 0xffff; end &= 0xffff; Bit32u addr; bx_bool ret = 1; /* * the easy way this time */ for (addr = begin; addr <= end; addr++) if (!unregister_io_write_handler(this_ptr, f, addr, mask)) ret = 0; return ret; } /* * Read a byte of data from the IO memory address space */ Bit32u BX_CPP_AttrRegparmN(2) bx_devices_c::inp(Bit16u addr, unsigned io_len) { struct io_handler_struct *io_read_handler; Bit32u ret; BX_INSTR_INP(addr, io_len); io_read_handler = read_port_to_handler[addr]; if (io_read_handler->mask & io_len) { ret = ((bx_read_handler_t)io_read_handler->funct)(io_read_handler->this_ptr, (Bit32u)addr, io_len); } else { switch (io_len) { case 1: ret = 0xff; break; case 2: ret = 0xffff; break; default: ret = 0xffffffff; break; } if (addr != 0x0cf8) { // don't flood the logfile when probing PCI BX_ERROR(("read from port 0x%04x with len %d returns 0x%x", addr, io_len, ret)); } } BX_INSTR_INP2(addr, io_len, ret); BX_DBG_IO_REPORT(addr, io_len, BX_READ, ret); return(ret); } /* * Write a byte of data to the IO memory address space. */ void BX_CPP_AttrRegparmN(3) bx_devices_c::outp(Bit16u addr, Bit32u value, unsigned io_len) { struct io_handler_struct *io_write_handler; BX_INSTR_OUTP(addr, io_len, value); BX_DBG_IO_REPORT(addr, io_len, BX_WRITE, value); io_write_handler = write_port_to_handler[addr]; if (io_write_handler->mask & io_len) { ((bx_write_handler_t)io_write_handler->funct)(io_write_handler->this_ptr, (Bit32u)addr, value, io_len); } else if (addr != 0x0cf8) { // don't flood the logfile when probing PCI BX_ERROR(("write to port 0x%04x with len %d ignored", addr, io_len)); } } bx_bool bx_devices_c::is_harddrv_enabled(void) { char pname[24]; for (int i=0; iget_param_bool(pname)->get()) return 1; } return 0; } bx_bool bx_devices_c::is_network_enabled(void) { if (PLUG_device_present("e1000") || PLUG_device_present("ne2k") || PLUG_device_present("pcipnic")) { return 1; } return 0; } bx_bool bx_devices_c::is_sound_enabled(void) { if (PLUG_device_present("es1370") || PLUG_device_present("sb16")) { return 1; } return 0; } bx_bool bx_devices_c::is_usb_enabled(void) { if (PLUG_device_present("usb_ohci") || PLUG_device_present("usb_uhci") || PLUG_device_present("usb_xhci")) { return 1; } return 0; } // removable keyboard/mouse registration void bx_devices_c::register_removable_keyboard(void *dev, bx_keyb_enq_t keyb_enq) { if (bx_keyboard.dev == NULL) { bx_keyboard.dev = dev; bx_keyboard.enq_event = keyb_enq; } } void bx_devices_c::unregister_removable_keyboard(void *dev) { if (dev == bx_keyboard.dev) { bx_keyboard.dev = NULL; bx_keyboard.enq_event = NULL; } } void bx_devices_c::register_default_mouse(void *dev, bx_mouse_enq_t mouse_enq, bx_mouse_enabled_changed_t mouse_enabled_changed) { if (bx_mouse[0].dev == NULL) { bx_mouse[0].dev = dev; bx_mouse[0].enq_event = mouse_enq; bx_mouse[0].enabled_changed = mouse_enabled_changed; } } void bx_devices_c::register_removable_mouse(void *dev, bx_mouse_enq_t mouse_enq, bx_mouse_enabled_changed_t mouse_enabled_changed) { if (bx_mouse[1].dev == NULL) { bx_mouse[1].dev = dev; bx_mouse[1].enq_event = mouse_enq; bx_mouse[1].enabled_changed = mouse_enabled_changed; } } void bx_devices_c::unregister_removable_mouse(void *dev) { if (dev == bx_mouse[1].dev) { bx_mouse[1].dev = NULL; bx_mouse[1].enq_event = NULL; bx_mouse[1].enabled_changed = NULL; } } bx_bool bx_devices_c::optional_key_enq(Bit8u *scan_code) { if (bx_keyboard.dev != NULL) { return bx_keyboard.enq_event(bx_keyboard.dev, scan_code); } return 0; } // common mouse device handlers void bx_devices_c::mouse_enabled_changed(bx_bool enabled) { mouse_captured = enabled; if ((bx_mouse[1].dev != NULL) && (bx_mouse[1].enabled_changed != NULL)) { bx_mouse[1].enabled_changed(bx_mouse[1].dev, enabled); return; } if ((bx_mouse[0].dev != NULL) && (bx_mouse[0].enabled_changed != NULL)) { bx_mouse[0].enabled_changed(bx_mouse[0].dev, enabled); } } void bx_devices_c::mouse_motion(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy) { // If mouse events are disabled on the GUI headerbar, don't // generate any mouse data if (!mouse_captured) return; // if a removable mouse is connected, redirect mouse data to the device if (bx_mouse[1].dev != NULL) { bx_mouse[1].enq_event(bx_mouse[1].dev, delta_x, delta_y, delta_z, button_state, absxy); return; } // if a mouse is connected, direct mouse data to the device if (bx_mouse[0].dev != NULL) { bx_mouse[0].enq_event(bx_mouse[0].dev, delta_x, delta_y, delta_z, button_state, absxy); } } void bx_pci_device_stub_c::register_pci_state(bx_list_c *list) { char name[6]; bx_list_c *pci = new bx_list_c(list, "pci_conf"); for (unsigned i=0; i<256; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(pci, name, &pci_conf[i], BASE_HEX); } } void bx_pci_device_stub_c::load_pci_rom(const char *path) { struct stat stat_buf; int fd, ret; unsigned long size, max_size; if (*path == '\0') { BX_PANIC(("PCI ROM image undefined")); return; } // read in PCI ROM image file fd = open(path, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if (fd < 0) { BX_PANIC(("couldn't open PCI ROM image file '%s'.", path)); return; } ret = fstat(fd, &stat_buf); if (ret) { BX_PANIC(("couldn't stat PCI ROM image file '%s'.", path)); return; } max_size = 0x20000; size = (unsigned long)stat_buf.st_size; if (size > max_size) { close(fd); BX_PANIC(("PCI ROM image too large")); return; } if ((size % 512) != 0) { close(fd); BX_PANIC(("PCI ROM image size must be multiple of 512 (size = %ld)", size)); return; } while ((size - 1) < max_size) { max_size >>= 1; } pci_rom_size = (max_size << 1); pci_rom = new Bit8u[pci_rom_size]; while (size > 0) { ret = read(fd, (bx_ptr_t) pci_rom, size); if (ret <= 0) { BX_PANIC(("read failed on PCI ROM image: '%s'", path)); } size -= ret; } close(fd); BX_INFO(("loaded PCI ROM '%s' (size=%u / PCI=%uk)", path, (unsigned) stat_buf.st_size, pci_rom_size >> 10)); } bochs-2.6/iodev/vgacore.h0000644000175000017500000001775412020641505015253 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vgacore.h 11129 2012-04-08 14:21:18Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_VGACORE_H #define BX_IODEV_VGACORE_H // Make colour #define MAKE_COLOUR(red, red_shiftfrom, red_shiftto, red_mask, \ green, green_shiftfrom, green_shiftto, green_mask, \ blue, blue_shiftfrom, blue_shiftto, blue_mask) \ ( \ ((((red_shiftto) > (red_shiftfrom)) ? \ (red) << ((red_shiftto) - (red_shiftfrom)) : \ (red) >> ((red_shiftfrom) - (red_shiftto))) & \ (red_mask)) | \ ((((green_shiftto) > (green_shiftfrom)) ? \ (green) << ((green_shiftto) - (green_shiftfrom)) : \ (green) >> ((green_shiftfrom) - (green_shiftto))) & \ (green_mask)) | \ ((((blue_shiftto) > (blue_shiftfrom)) ? \ (blue) << ((blue_shiftto) - (blue_shiftfrom)) : \ (blue) >> ((blue_shiftfrom) - (blue_shiftto))) & \ (blue_mask)) \ ) #define X_TILESIZE 16 #define Y_TILESIZE 24 class bx_vgacore_c : public bx_vga_stub_c #if BX_SUPPORT_PCI , public bx_pci_device_stub_c #endif { public: bx_vgacore_c(); virtual ~bx_vgacore_c(); virtual void init(void); virtual void reset(unsigned type) {} static bx_bool mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param); static bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param); virtual Bit8u mem_read(bx_phy_address addr); virtual void mem_write(bx_phy_address addr, Bit8u value); virtual void trigger_timer(void *this_ptr); virtual void set_override(bx_bool enabled); virtual void register_state(bx_list_c *parent); virtual void after_restore_state(void); #if BX_DEBUGGER virtual void debug_dump(void); #endif virtual void redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height); virtual int get_snapshot_mode(void); virtual void get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, unsigned *txWidth); virtual Bit32u get_gfx_snapshot(Bit8u **snapshot_ptr, Bit8u **palette_ptr, unsigned *iHeight, unsigned *iWidth, unsigned *iDepth); virtual void init_vga_extension(void) {} static void timer_handler(void *); void timer(void); protected: void init_standard_vga(void); void init_gui(void); void init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t f_write); void init_systemtimer(bx_timer_handler_t f_timer, param_event_handler f_param); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); Bit8u get_vga_pixel(Bit16u x, Bit16u y, Bit16u saddr, Bit16u lc, bx_bool bs, Bit8u **plane); bx_bool get_dac_palette(Bit8u **palette_ptr, Bit8u shift); void update(void); void determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth); void calculate_retrace_timing(void); bx_bool skip_update(void); struct { struct { bx_bool color_emulation; // 1=color emulation, base address = 3Dx // 0=mono emulation, base address = 3Bx bx_bool enable_ram; // enable CPU access to video memory if set Bit8u clock_select; // 0=25Mhz 1=28Mhz bx_bool select_high_bank; // when in odd/even modes, select // high 64k bank if set bx_bool horiz_sync_pol; // bit6: negative if set bx_bool vert_sync_pol; // bit7: negative if set // bit7,bit6 represent number of lines on display: // 0 = reserved // 1 = 400 lines // 2 = 350 lines // 3 - 480 lines } misc_output; struct { Bit8u address; Bit8u reg[0x19]; bx_bool write_protect; } CRTC; struct { bx_bool flip_flop; /* 0 = address, 1 = data-write */ unsigned address; /* register number */ bx_bool video_enabled; Bit8u palette_reg[16]; Bit8u overscan_color; Bit8u color_plane_enable; Bit8u horiz_pel_panning; Bit8u color_select; struct { bx_bool graphics_alpha; bx_bool display_type; bx_bool enable_line_graphics; bx_bool blink_intensity; bx_bool pixel_panning_compat; bx_bool pixel_clock_select; bx_bool internal_palette_size; } mode_ctrl; } attribute_ctrl; struct { Bit8u write_data_register; Bit8u write_data_cycle; /* 0, 1, 2 */ Bit8u read_data_register; Bit8u read_data_cycle; /* 0, 1, 2 */ Bit8u dac_state; struct { Bit8u red; Bit8u green; Bit8u blue; } data[256]; Bit8u mask; } pel; struct { Bit8u index; Bit8u set_reset; Bit8u enable_set_reset; Bit8u color_compare; Bit8u data_rotate; Bit8u raster_op; Bit8u read_map_select; Bit8u write_mode; bx_bool read_mode; bx_bool odd_even; bx_bool chain_odd_even; Bit8u shift_reg; bx_bool graphics_alpha; Bit8u memory_mapping; /* 0 = use A0000-BFFFF * 1 = use A0000-AFFFF EGA/VGA graphics modes * 2 = use B0000-B7FFF Monochrome modes * 3 = use B8000-BFFFF CGA modes */ Bit8u color_dont_care; Bit8u bitmask; Bit8u latch[4]; } graphics_ctrl; struct { Bit8u index; Bit8u map_mask; bx_bool reset1; bx_bool reset2; Bit8u reg1; Bit8u char_map_select; bx_bool extended_mem; bx_bool odd_even; bx_bool chain_four; bx_bool clear_screen; } sequencer; bx_bool vga_enabled; bx_bool vga_mem_updated; unsigned line_offset; unsigned line_compare; unsigned vertical_display_end; unsigned blink_counter; bx_bool *vga_tile_updated; Bit8u *memory; Bit32u memsize; Bit8u text_snapshot[128 * 1024]; // current text snapshot Bit8u tile[X_TILESIZE * Y_TILESIZE * 4]; /**< Currently allocates the tile as large as needed. */ Bit16u charmap_address; bx_bool x_dotclockdiv2; bx_bool y_doublescan; // h/v retrace timing Bit32u htotal_usec; Bit32u hbstart_usec; Bit32u hbend_usec; Bit32u vtotal_usec; Bit32u vblank_usec; Bit32u vrstart_usec; Bit32u vrend_usec; // shift values for extensions Bit8u plane_shift; Bit32u plane_offset; Bit8u dac_shift; // last active resolution and bpp Bit16u last_xres; Bit16u last_yres; Bit8u last_bpp; Bit8u last_msl; // maximum resolution and number of tiles Bit16u max_xres; Bit16u max_yres; Bit16u num_x_tiles; Bit16u num_y_tiles; } s; // state information int timer_id; bx_bool extension_init; bx_bool pci_enabled; }; #endif bochs-2.6/iodev/vgacore.cc0000644000175000017500000027642012020641505015406 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vgacore.cc 11129 2012-04-08 14:21:18Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "param_names.h" #include "vgacore.h" #include "virt_timer.h" #define BX_VGA_THIS this-> #define BX_VGA_THIS_PTR this #define LOG_THIS #define VGA_TRACE_FEATURE // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, do nothing. #define SET_TILE_UPDATED(xtile, ytile, value) \ do { \ if (((xtile) < s.num_x_tiles) && ((ytile) < s.num_y_tiles)) \ s.vga_tile_updated[(xtile)+(ytile)* s.num_x_tiles] = value; \ } while (0) // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, return 0. #define GET_TILE_UPDATED(xtile,ytile) \ ((((xtile) < s.num_x_tiles) && ((ytile) < s.num_y_tiles))? \ s.vga_tile_updated[(xtile)+(ytile)* s.num_x_tiles] \ : 0) static const Bit16u charmap_offset[8] = { 0x0000, 0x4000, 0x8000, 0xc000, 0x2000, 0x6000, 0xa000, 0xe000 }; static const Bit8u ccdat[16][4] = { { 0x00, 0x00, 0x00, 0x00 }, { 0xff, 0x00, 0x00, 0x00 }, { 0x00, 0xff, 0x00, 0x00 }, { 0xff, 0xff, 0x00, 0x00 }, { 0x00, 0x00, 0xff, 0x00 }, { 0xff, 0x00, 0xff, 0x00 }, { 0x00, 0xff, 0xff, 0x00 }, { 0xff, 0xff, 0xff, 0x00 }, { 0x00, 0x00, 0x00, 0xff }, { 0xff, 0x00, 0x00, 0xff }, { 0x00, 0xff, 0x00, 0xff }, { 0xff, 0xff, 0x00, 0xff }, { 0x00, 0x00, 0xff, 0xff }, { 0xff, 0x00, 0xff, 0xff }, { 0x00, 0xff, 0xff, 0xff }, { 0xff, 0xff, 0xff, 0xff }, }; bx_vgacore_c::bx_vgacore_c() { memset(&s, 0, sizeof(s)); timer_id = BX_NULL_TIMER_HANDLE; } bx_vgacore_c::~bx_vgacore_c() { if (s.memory != NULL) { delete [] s.memory; s.memory = NULL; } if (s.vga_tile_updated != NULL) { delete [] s.vga_tile_updated; s.vga_tile_updated = NULL; } SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY)->set_handler(NULL); } void bx_vgacore_c::init(void) { unsigned x,y; BX_VGA_THIS extension_init = 0; BX_VGA_THIS pci_enabled = 0; BX_VGA_THIS init_standard_vga(); BX_VGA_THIS init_vga_extension(); BX_VGA_THIS init_gui(); BX_VGA_THIS s.num_x_tiles = BX_VGA_THIS s.max_xres / X_TILESIZE + ((BX_VGA_THIS s.max_xres % X_TILESIZE) > 0); BX_VGA_THIS s.num_y_tiles = BX_VGA_THIS s.max_yres / Y_TILESIZE + ((BX_VGA_THIS s.max_yres % Y_TILESIZE) > 0); BX_VGA_THIS s.vga_tile_updated = new bx_bool[BX_VGA_THIS s.num_x_tiles * BX_VGA_THIS s.num_y_tiles]; for (y = 0; y < BX_VGA_THIS s.num_y_tiles; y++) for (x = 0; x < BX_VGA_THIS s.num_x_tiles; x++) SET_TILE_UPDATED(x, y, 0); char *strptr = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(); if (!BX_VGA_THIS extension_init && (strlen(strptr) > 0) && strcmp(strptr, "none")) { BX_PANIC(("unknown display extension: %s", strptr)); } if (!BX_VGA_THIS pci_enabled) { BX_MEM(0)->load_ROM(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr(), 0xc0000, 1); } } void bx_vgacore_c::init_standard_vga(void) { char *extname; // initialize VGA controllers and other internal stuff BX_VGA_THIS s.vga_enabled = 1; BX_VGA_THIS s.misc_output.color_emulation = 1; BX_VGA_THIS s.misc_output.enable_ram = 1; BX_VGA_THIS s.misc_output.horiz_sync_pol = 1; BX_VGA_THIS s.misc_output.vert_sync_pol = 1; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = 1; BX_VGA_THIS s.line_offset=80; BX_VGA_THIS s.line_compare=1023; BX_VGA_THIS s.vertical_display_end=399; BX_VGA_THIS s.attribute_ctrl.video_enabled = 1; BX_VGA_THIS s.attribute_ctrl.color_plane_enable = 0x0f; BX_VGA_THIS s.pel.dac_state = 0x01; BX_VGA_THIS s.pel.mask = 0xff; BX_VGA_THIS s.graphics_ctrl.memory_mapping = 2; // monochrome text mode BX_VGA_THIS s.sequencer.reset1 = 1; BX_VGA_THIS s.sequencer.reset2 = 1; BX_VGA_THIS s.sequencer.extended_mem = 1; // display mem greater than 64K BX_VGA_THIS s.sequencer.odd_even = 1; // use sequential addressing mode BX_VGA_THIS s.plane_shift = 16; BX_VGA_THIS s.dac_shift = 2; BX_VGA_THIS s.last_bpp = 8; BX_VGA_THIS s.htotal_usec = 31; BX_VGA_THIS s.vtotal_usec = 14285; BX_VGA_THIS s.max_xres = 800; BX_VGA_THIS s.max_yres = 600; // initialize memory, handlers and timer (depending on extension) extname = SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(); if ((strlen(extname) == 0) || (!strcmp(extname, "none"))) { BX_VGA_THIS s.memsize = 0x40000; if (BX_VGA_THIS s.memory == NULL) BX_VGA_THIS s.memory = new Bit8u[BX_VGA_THIS s.memsize]; memset(BX_VGA_THIS s.memory, 0, BX_VGA_THIS s.memsize); } DEV_register_memory_handlers(BX_VGA_THIS_PTR, mem_read_handler, mem_write_handler, 0xa0000, 0xbffff); // video card with BIOS ROM DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0xcf) | 0x00); } void bx_vgacore_c::init_gui(void) { unsigned i,string_i; int argc; char *argv[16]; char *ptr; char string[512]; size_t len; // set up display library options and start gui memset(argv, 0, sizeof(argv)); argc = 1; argv[0] = (char *)"bochs"; len = strlen(SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr()); if (len > 0) { char *options = new char[len + 1]; strcpy(options, SIM->get_param_string(BXPN_DISPLAYLIB_OPTIONS)->getptr()); ptr = strtok(options, ","); while (ptr) { string_i = 0; for (i=0; iinit(argc, argv, BX_VGA_THIS s.max_xres, BX_VGA_THIS s.max_yres, X_TILESIZE, Y_TILESIZE); for (i = 1; i < (unsigned)argc; i++) { if (argv[i] != NULL) { free(argv[i]); argv[i] = NULL; } } } void bx_vgacore_c::init_iohandlers(bx_read_handler_t f_read, bx_write_handler_t f_write) { unsigned addr, i; Bit8u io_mask[16] = {3, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1}; for (addr=0x03B4; addr<=0x03B5; addr++) { DEV_register_ioread_handler(this, f_read, addr, "vga video", 1); DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3); } for (addr=0x03BA; addr<=0x03BA; addr++) { DEV_register_ioread_handler(this, f_read, addr, "vga video", 1); DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3); } i = 0; for (addr=0x03C0; addr<=0x03CF; addr++) { DEV_register_ioread_handler(this, f_read, addr, "vga video", io_mask[i++]); DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3); } for (addr=0x03D4; addr<=0x03D5; addr++) { DEV_register_ioread_handler(this, f_read, addr, "vga video", 3); DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3); } for (addr=0x03DA; addr<=0x03DA; addr++) { DEV_register_ioread_handler(this, f_read, addr, "vga video", 1); DEV_register_iowrite_handler(this, f_write, addr, "vga video", 3); } } void bx_vgacore_c::init_systemtimer(bx_timer_handler_t f_timer, param_event_handler f_param) { bx_param_num_c *vga_update_freq = SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY); Bit64u interval = 1000000 / vga_update_freq->get(); BX_INFO(("interval=" FMT_LL "u", interval)); if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) { BX_VGA_THIS timer_id = bx_virt_timer.register_timer(this, f_timer, (Bit32u)interval, 1, 1, "vga"); vga_update_freq->set_handler(f_param); vga_update_freq->set_runtime_param(1); } if (interval < 300000) { BX_VGA_THIS s.blink_counter = 300000 / (unsigned)interval; } else { BX_VGA_THIS s.blink_counter = 1; } } void bx_vgacore_c::register_state(bx_list_c *parent) { unsigned i; char name[6]; bx_list_c *reg; bx_list_c *list = new bx_list_c(parent, "vgacore", "VGA Core State"); bx_list_c *misc = new bx_list_c(list, "misc_output"); new bx_shadow_bool_c(misc, "color_emulation", &BX_VGA_THIS s.misc_output.color_emulation); new bx_shadow_bool_c(misc, "enable_ram", &BX_VGA_THIS s.misc_output.enable_ram); new bx_shadow_num_c(misc, "clock_select", &BX_VGA_THIS s.misc_output.clock_select); new bx_shadow_bool_c(misc, "select_high_bank", &BX_VGA_THIS s.misc_output.select_high_bank); new bx_shadow_bool_c(misc, "horiz_sync_pol", &BX_VGA_THIS s.misc_output.horiz_sync_pol); new bx_shadow_bool_c(misc, "vert_sync_pol", &BX_VGA_THIS s.misc_output.vert_sync_pol); bx_list_c *crtc = new bx_list_c(list, "CRTC"); new bx_shadow_num_c(crtc, "address", &BX_VGA_THIS s.CRTC.address, BASE_HEX); reg = new bx_list_c(crtc, "reg"); for (i=0; i<=0x18; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_VGA_THIS s.CRTC.reg[i], BASE_HEX); } new bx_shadow_bool_c(crtc, "write_protect", &BX_VGA_THIS s.CRTC.write_protect); bx_list_c *actl = new bx_list_c(list, "attribute_ctrl"); new bx_shadow_bool_c(actl, "flip_flop", &BX_VGA_THIS s.attribute_ctrl.flip_flop); new bx_shadow_num_c(actl, "address", &BX_VGA_THIS s.attribute_ctrl.address, BASE_HEX); new bx_shadow_bool_c(actl, "video_enabled", &BX_VGA_THIS s.attribute_ctrl.video_enabled); reg = new bx_list_c(actl, "palette_reg"); for (i=0; i<16; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_VGA_THIS s.attribute_ctrl.palette_reg[i], BASE_HEX); } new bx_shadow_num_c(actl, "overscan_color", &BX_VGA_THIS s.attribute_ctrl.overscan_color, BASE_HEX); new bx_shadow_num_c(actl, "color_plane_enable", &BX_VGA_THIS s.attribute_ctrl.color_plane_enable, BASE_HEX); new bx_shadow_num_c(actl, "horiz_pel_panning", &BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning, BASE_HEX); new bx_shadow_num_c(actl, "color_select", &BX_VGA_THIS s.attribute_ctrl.color_select, BASE_HEX); bx_list_c *mode = new bx_list_c(actl, "mode_ctrl"); new bx_shadow_bool_c(mode, "graphics_alpha", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha); new bx_shadow_bool_c(mode, "display_type", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type); new bx_shadow_bool_c(mode, "enable_line_graphics", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics); new bx_shadow_bool_c(mode, "blink_intensity", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity); new bx_shadow_bool_c(mode, "pixel_panning_compat", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat); new bx_shadow_bool_c(mode, "pixel_clock_select", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select); new bx_shadow_bool_c(mode, "internal_palette_size", &BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size); bx_list_c *pel = new bx_list_c(list, "pel"); new bx_shadow_num_c(pel, "write_data_register", &BX_VGA_THIS s.pel.write_data_register, BASE_HEX); new bx_shadow_num_c(pel, "write_data_cycle", &BX_VGA_THIS s.pel.write_data_cycle); new bx_shadow_num_c(pel, "read_data_register", &BX_VGA_THIS s.pel.read_data_register, BASE_HEX); new bx_shadow_num_c(pel, "read_data_cycle", &BX_VGA_THIS s.pel.read_data_cycle); new bx_shadow_num_c(pel, "dac_state", &BX_VGA_THIS s.pel.dac_state); new bx_shadow_num_c(pel, "mask", &BX_VGA_THIS s.pel.mask, BASE_HEX); new bx_shadow_data_c(list, "pel_data", &BX_VGA_THIS s.pel.data[0].red, sizeof(BX_VGA_THIS s.pel.data)); bx_list_c *gfxc = new bx_list_c(list, "graphics_ctrl"); new bx_shadow_num_c(gfxc, "index", &BX_VGA_THIS s.graphics_ctrl.index); new bx_shadow_num_c(gfxc, "set_reset", &BX_VGA_THIS s.graphics_ctrl.set_reset); new bx_shadow_num_c(gfxc, "enable_set_reset", &BX_VGA_THIS s.graphics_ctrl.enable_set_reset); new bx_shadow_num_c(gfxc, "color_compare", &BX_VGA_THIS s.graphics_ctrl.color_compare); new bx_shadow_num_c(gfxc, "data_rotate", &BX_VGA_THIS s.graphics_ctrl.data_rotate); new bx_shadow_num_c(gfxc, "raster_op", &BX_VGA_THIS s.graphics_ctrl.raster_op); new bx_shadow_num_c(gfxc, "read_map_select", &BX_VGA_THIS s.graphics_ctrl.read_map_select); new bx_shadow_num_c(gfxc, "write_mode", &BX_VGA_THIS s.graphics_ctrl.write_mode); new bx_shadow_num_c(gfxc, "read_mode", &BX_VGA_THIS s.graphics_ctrl.read_mode); new bx_shadow_bool_c(gfxc, "odd_even", &BX_VGA_THIS s.graphics_ctrl.odd_even); new bx_shadow_bool_c(gfxc, "chain_odd_even", &BX_VGA_THIS s.graphics_ctrl.chain_odd_even); new bx_shadow_num_c(gfxc, "shift_reg", &BX_VGA_THIS s.graphics_ctrl.shift_reg); new bx_shadow_bool_c(gfxc, "graphics_alpha", &BX_VGA_THIS s.graphics_ctrl.graphics_alpha); new bx_shadow_num_c(gfxc, "memory_mapping", &BX_VGA_THIS s.graphics_ctrl.memory_mapping); new bx_shadow_num_c(gfxc, "color_dont_care", &BX_VGA_THIS s.graphics_ctrl.color_dont_care, BASE_HEX); new bx_shadow_num_c(gfxc, "bitmask", &BX_VGA_THIS s.graphics_ctrl.bitmask, BASE_HEX); new bx_shadow_num_c(gfxc, "latch0", &BX_VGA_THIS s.graphics_ctrl.latch[0], BASE_HEX); new bx_shadow_num_c(gfxc, "latch1", &BX_VGA_THIS s.graphics_ctrl.latch[1], BASE_HEX); new bx_shadow_num_c(gfxc, "latch2", &BX_VGA_THIS s.graphics_ctrl.latch[2], BASE_HEX); new bx_shadow_num_c(gfxc, "latch3", &BX_VGA_THIS s.graphics_ctrl.latch[3], BASE_HEX); bx_list_c *sequ = new bx_list_c(list, "sequencer"); new bx_shadow_num_c(sequ, "index", &BX_VGA_THIS s.sequencer.index); new bx_shadow_num_c(sequ, "map_mask", &BX_VGA_THIS s.sequencer.map_mask); new bx_shadow_bool_c(sequ, "reset1", &BX_VGA_THIS s.sequencer.reset1); new bx_shadow_bool_c(sequ, "reset2", &BX_VGA_THIS s.sequencer.reset2); new bx_shadow_num_c(sequ, "reg1", &BX_VGA_THIS s.sequencer.reg1, BASE_HEX); new bx_shadow_num_c(sequ, "char_map_select", &BX_VGA_THIS s.sequencer.char_map_select); new bx_shadow_bool_c(sequ, "extended_mem", &BX_VGA_THIS s.sequencer.extended_mem); new bx_shadow_bool_c(sequ, "odd_even", &BX_VGA_THIS s.sequencer.odd_even); new bx_shadow_bool_c(sequ, "chain_four", &BX_VGA_THIS s.sequencer.chain_four); new bx_shadow_bool_c(list, "enabled", &BX_VGA_THIS s.vga_enabled); new bx_shadow_num_c(list, "line_offset", &BX_VGA_THIS s.line_offset); new bx_shadow_num_c(list, "line_compare", &BX_VGA_THIS s.line_compare); new bx_shadow_num_c(list, "vertical_display_end", &BX_VGA_THIS s.vertical_display_end); new bx_shadow_num_c(list, "charmap_address", &BX_VGA_THIS s.charmap_address); new bx_shadow_bool_c(list, "x_dotclockdiv2", &BX_VGA_THIS s.x_dotclockdiv2); new bx_shadow_bool_c(list, "y_doublescan", &BX_VGA_THIS s.y_doublescan); new bx_shadow_num_c(list, "plane_shift", &BX_VGA_THIS s.plane_shift); new bx_shadow_num_c(list, "plane_offset", &BX_VGA_THIS s.plane_offset); new bx_shadow_num_c(list, "dac_shift", &BX_VGA_THIS s.dac_shift); new bx_shadow_num_c(list, "last_bpp", &BX_VGA_THIS s.last_bpp); new bx_shadow_data_c(list, "memory", BX_VGA_THIS s.memory, BX_VGA_THIS s.memsize); } void bx_vgacore_c::after_restore_state(void) { for (unsigned i=0; i<256; i++) { bx_gui->palette_change(i, BX_VGA_THIS s.pel.data[i].red << BX_VGA_THIS s.dac_shift, BX_VGA_THIS s.pel.data[i].green << BX_VGA_THIS s.dac_shift, BX_VGA_THIS s.pel.data[i].blue << BX_VGA_THIS s.dac_shift); } bx_gui->set_text_charmap(&BX_VGA_THIS s.memory[0x20000 + BX_VGA_THIS s.charmap_address]); BX_VGA_THIS s.last_xres = BX_VGA_THIS s.max_xres; BX_VGA_THIS s.last_yres = BX_VGA_THIS s.max_yres; BX_VGA_THIS redraw_area(0, 0, BX_VGA_THIS s.max_xres, BX_VGA_THIS s.max_yres); BX_VGA_THIS calculate_retrace_timing(); BX_VGA_THIS update(); bx_gui->flush(); } void bx_vgacore_c::determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth) { int ai[0x20]; int i,h,v; for (i = 0 ; i < 0x20 ; i++) ai[i] = BX_VGA_THIS s.CRTC.reg[i]; h = (ai[1] + 1) * 8; v = (ai[18] | ((ai[7] & 0x02) << 7) | ((ai[7] & 0x40) << 3)) + 1; if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 0) { *piWidth = 640; *piHeight = 480; if (BX_VGA_THIS s.CRTC.reg[6] == 0xBF) { if (BX_VGA_THIS s.CRTC.reg[23] == 0xA3 && BX_VGA_THIS s.CRTC.reg[20] == 0x40 && BX_VGA_THIS s.CRTC.reg[9] == 0x41) { *piWidth = 320; *piHeight = 240; } else { if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1; *piWidth = h; *piHeight = v; } } else if ((h >= 640) && (v >= 400)) { *piWidth = h; *piHeight = v; } } else if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) { *piWidth = h; *piHeight = v; } else { if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1; *piWidth = h; *piHeight = v; } } void bx_vgacore_c::calculate_retrace_timing() { Bit32u dot_clock[4] = {25175000, 28322000, 25175000, 25175000}; Bit32u htotal, hbstart, hbend, clock, cwidth, vtotal, vrstart, vrend, hfreq, vfreq; htotal = BX_VGA_THIS s.CRTC.reg[0] + 5; htotal <<= BX_VGA_THIS s.x_dotclockdiv2; cwidth = ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 1) ? 8 : 9; clock = dot_clock[BX_VGA_THIS s.misc_output.clock_select]; hfreq = clock / (htotal * cwidth); BX_VGA_THIS s.htotal_usec = 1000000 / hfreq; hbstart = BX_VGA_THIS s.CRTC.reg[2]; BX_VGA_THIS s.hbstart_usec = (1000000 * hbstart * cwidth) / clock; hbend = (BX_VGA_THIS s.CRTC.reg[3] & 0x1f) + ((BX_VGA_THIS s.CRTC.reg[5] & 0x80) >> 2); hbend = hbstart + ((hbend - hbstart) & 0x3f); BX_VGA_THIS s.hbend_usec = (1000000 * hbend * cwidth) / clock; vtotal = BX_VGA_THIS s.CRTC.reg[6] + ((BX_VGA_THIS s.CRTC.reg[7] & 0x01) << 8) + ((BX_VGA_THIS s.CRTC.reg[7] & 0x20) << 4) + 2; vrstart = BX_VGA_THIS s.CRTC.reg[16] + ((BX_VGA_THIS s.CRTC.reg[7] & 0x04) << 6) + ((BX_VGA_THIS s.CRTC.reg[7] & 0x80) << 2); vrend = ((BX_VGA_THIS s.CRTC.reg[17] & 0x0f) - vrstart) & 0x0f; vrend = vrstart + vrend + 1; vfreq = hfreq / vtotal; BX_VGA_THIS s.vtotal_usec = 1000000 / vfreq; BX_VGA_THIS s.vblank_usec = BX_VGA_THIS s.htotal_usec * BX_VGA_THIS s.vertical_display_end; BX_VGA_THIS s.vrstart_usec = BX_VGA_THIS s.htotal_usec * vrstart; BX_VGA_THIS s.vrend_usec = BX_VGA_THIS s.htotal_usec * vrend; BX_DEBUG(("hfreq = %.1f kHz / vfreq = %d Hz", ((double)hfreq / 1000), vfreq)); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_vgacore_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { bx_vgacore_c *class_ptr = (bx_vgacore_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_vgacore_c::read(Bit32u address, unsigned io_len) { Bit64u display_usec, line_usec; Bit16u ret16; Bit8u retval; #if defined(VGA_TRACE_FEATURE) Bit32u ret = 0; #define RETURN(x) do { ret = (x); goto read_return; } while (0) #else #define RETURN return #endif if (io_len == 2) { ret16 = bx_vgacore_c::read(address, 1); ret16 |= (bx_vgacore_c::read(address+1, 1)) << 8; RETURN(ret16); } #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io read from 0x%04x", (unsigned) address)); #endif if ((address >= 0x03b0) && (address <= 0x03bf) && (BX_VGA_THIS s.misc_output.color_emulation)) { RETURN(0xff); } if ((address >= 0x03d0) && (address <= 0x03df) && (BX_VGA_THIS s.misc_output.color_emulation==0)) { RETURN(0xff); } switch (address) { case 0x03ba: /* Input Status 1 (monochrome emulation modes) */ case 0x03ca: /* Feature Control ??? */ case 0x03da: /* Input Status 1 (color emulation modes) */ // bit3: Vertical Retrace // 0 = display is in the display mode // 1 = display is in the vertical retrace mode // bit0: Display Enable // 0 = display is in the display mode // 1 = display is not in the display mode; either the // horizontal or vertical retrace period is active retval = 0; display_usec = bx_pc_system.time_usec() % BX_VGA_THIS s.vtotal_usec; if ((display_usec >= BX_VGA_THIS s.vrstart_usec) && (display_usec <= BX_VGA_THIS s.vrend_usec)) { retval |= 0x08; } if (display_usec >= BX_VGA_THIS s.vblank_usec) { retval |= 0x01; } else { line_usec = display_usec % BX_VGA_THIS s.htotal_usec; if ((line_usec >= BX_VGA_THIS s.hbstart_usec) && (line_usec <= BX_VGA_THIS s.hbend_usec)) { retval |= 0x01; } } /* reading this port resets the flip-flop to address mode */ BX_VGA_THIS s.attribute_ctrl.flip_flop = 0; RETURN(retval); break; case 0x03c0: /* */ if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) { //BX_INFO(("io read: 0x3c0: flip_flop = 0")); retval = (BX_VGA_THIS s.attribute_ctrl.video_enabled << 5) | BX_VGA_THIS s.attribute_ctrl.address; RETURN(retval); } else { BX_ERROR(("io read: 0x3c0: flip_flop != 0")); return(0); } break; case 0x03c1: /* */ switch (BX_VGA_THIS s.attribute_ctrl.address) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: retval = BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address]; RETURN(retval); break; case 0x10: /* mode control register */ retval = (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha << 0) | (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type << 1) | (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics << 2) | (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity << 3) | (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat << 5) | (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select << 6) | (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size << 7); RETURN(retval); break; case 0x11: /* overscan color register */ RETURN(BX_VGA_THIS s.attribute_ctrl.overscan_color); break; case 0x12: /* color plane enable */ RETURN(BX_VGA_THIS s.attribute_ctrl.color_plane_enable); break; case 0x13: /* horizontal PEL panning register */ RETURN(BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning); break; case 0x14: /* color select register */ RETURN(BX_VGA_THIS s.attribute_ctrl.color_select); break; default: BX_INFO(("io read: 0x3c1: unknown register 0x%02x", (unsigned) BX_VGA_THIS s.attribute_ctrl.address)); RETURN(0); } break; case 0x03c2: /* Input Status 0 */ BX_DEBUG(("io read 0x3c2: input status #0: ignoring")); RETURN(0); break; case 0x03c3: /* VGA Enable Register */ RETURN(BX_VGA_THIS s.vga_enabled); break; case 0x03c4: /* Sequencer Index Register */ RETURN(BX_VGA_THIS s.sequencer.index); break; case 0x03c5: /* Sequencer Registers 00..04 */ switch (BX_VGA_THIS s.sequencer.index) { case 0: /* sequencer: reset */ BX_DEBUG(("io read 0x3c5: sequencer reset")); RETURN(BX_VGA_THIS s.sequencer.reset1 | (BX_VGA_THIS s.sequencer.reset2<<1)); break; case 1: /* sequencer: clocking mode */ BX_DEBUG(("io read 0x3c5: sequencer clocking mode")); RETURN(BX_VGA_THIS s.sequencer.reg1); break; case 2: /* sequencer: map mask register */ RETURN(BX_VGA_THIS s.sequencer.map_mask); break; case 3: /* sequencer: character map select register */ RETURN(BX_VGA_THIS s.sequencer.char_map_select); break; case 4: /* sequencer: memory mode register */ retval = (BX_VGA_THIS s.sequencer.extended_mem << 1) | (BX_VGA_THIS s.sequencer.odd_even << 2) | (BX_VGA_THIS s.sequencer.chain_four << 3); RETURN(retval); break; default: BX_DEBUG(("io read 0x3c5: index %u unhandled", (unsigned) BX_VGA_THIS s.sequencer.index)); RETURN(0); } break; case 0x03c6: /* PEL mask ??? */ RETURN(BX_VGA_THIS s.pel.mask); break; case 0x03c7: /* DAC state, read = 11b, write = 00b */ RETURN(BX_VGA_THIS s.pel.dac_state); break; case 0x03c8: /* PEL address write mode */ RETURN(BX_VGA_THIS s.pel.write_data_register); break; case 0x03c9: /* PEL Data Register, colors 00..FF */ if (BX_VGA_THIS s.pel.dac_state == 0x03) { switch (BX_VGA_THIS s.pel.read_data_cycle) { case 0: retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].red; break; case 1: retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].green; break; case 2: retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].blue; break; default: retval = 0; // keep compiler happy } BX_VGA_THIS s.pel.read_data_cycle++; if (BX_VGA_THIS s.pel.read_data_cycle >= 3) { BX_VGA_THIS s.pel.read_data_cycle = 0; BX_VGA_THIS s.pel.read_data_register++; } } else { retval = 0x3f; } RETURN(retval); break; case 0x03cc: /* Miscellaneous Output / Graphics 1 Position ??? */ retval = ((BX_VGA_THIS s.misc_output.color_emulation & 0x01) << 0) | ((BX_VGA_THIS s.misc_output.enable_ram & 0x01) << 1) | ((BX_VGA_THIS s.misc_output.clock_select & 0x03) << 2) | ((BX_VGA_THIS s.misc_output.select_high_bank & 0x01) << 5) | ((BX_VGA_THIS s.misc_output.horiz_sync_pol & 0x01) << 6) | ((BX_VGA_THIS s.misc_output.vert_sync_pol & 0x01) << 7); RETURN(retval); break; case 0x03ce: /* Graphics Controller Index Register */ RETURN(BX_VGA_THIS s.graphics_ctrl.index); break; case 0x03cd: /* ??? */ BX_DEBUG(("io read from 03cd")); RETURN(0x00); break; case 0x03cf: /* Graphics Controller Registers 00..08 */ switch (BX_VGA_THIS s.graphics_ctrl.index) { case 0: /* Set/Reset */ RETURN(BX_VGA_THIS s.graphics_ctrl.set_reset); break; case 1: /* Enable Set/Reset */ RETURN(BX_VGA_THIS s.graphics_ctrl.enable_set_reset); break; case 2: /* Color Compare */ RETURN(BX_VGA_THIS s.graphics_ctrl.color_compare); break; case 3: /* Data Rotate */ retval = ((BX_VGA_THIS s.graphics_ctrl.raster_op & 0x03) << 3) | ((BX_VGA_THIS s.graphics_ctrl.data_rotate & 0x07) << 0); RETURN(retval); break; case 4: /* Read Map Select */ RETURN(BX_VGA_THIS s.graphics_ctrl.read_map_select); break; case 5: /* Mode */ retval = ((BX_VGA_THIS s.graphics_ctrl.shift_reg & 0x03) << 5) | ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01) << 4) | ((BX_VGA_THIS s.graphics_ctrl.read_mode & 0x01) << 3) | ((BX_VGA_THIS s.graphics_ctrl.write_mode & 0x03) << 0); if (BX_VGA_THIS s.graphics_ctrl.odd_even || BX_VGA_THIS s.graphics_ctrl.shift_reg) BX_DEBUG(("io read 0x3cf: reg 05 = 0x%02x", (unsigned) retval)); RETURN(retval); break; case 6: /* Miscellaneous */ retval = ((BX_VGA_THIS s.graphics_ctrl.memory_mapping & 0x03) << 2) | ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01) << 1) | ((BX_VGA_THIS s.graphics_ctrl.graphics_alpha & 0x01) << 0); RETURN(retval); break; case 7: /* Color Don't Care */ RETURN(BX_VGA_THIS s.graphics_ctrl.color_dont_care); break; case 8: /* Bit Mask */ RETURN(BX_VGA_THIS s.graphics_ctrl.bitmask); break; default: /* ??? */ BX_DEBUG(("io read: 0x3cf: index %u unhandled", (unsigned) BX_VGA_THIS s.graphics_ctrl.index)); RETURN(0); } break; case 0x03d4: /* CRTC Index Register (color emulation modes) */ RETURN(BX_VGA_THIS s.CRTC.address); break; case 0x03b5: /* CRTC Registers (monochrome emulation modes) */ case 0x03d5: /* CRTC Registers (color emulation modes) */ if (BX_VGA_THIS s.CRTC.address > 0x18) { BX_DEBUG(("io read: invalid CRTC register 0x%02x", (unsigned) BX_VGA_THIS s.CRTC.address)); RETURN(0); } RETURN(BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]); break; case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */ case 0x03cb: /* not sure but OpenBSD reads it a lot */ default: BX_INFO(("io read from vga port 0x%04x", (unsigned) address)); RETURN(0); /* keep compiler happy */ } #if defined(VGA_TRACE_FEATURE) read_return: if (io_len == 1) { BX_DEBUG(("8-bit read from 0x%04x = 0x%02x", (unsigned) address, ret)); } else { BX_DEBUG(("16-bit read from 0x%04x = 0x%04x", (unsigned) address, ret)); } return ret; #endif } #if defined(VGA_TRACE_FEATURE) #undef RETURN #endif // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_vgacore_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { bx_vgacore_c *class_ptr = (bx_vgacore_c *) this_ptr; class_ptr->write(address, value, io_len, 0); } void bx_vgacore_c::write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log) { Bit8u charmap1, charmap2, prev_memory_mapping; bx_bool prev_video_enabled, prev_line_graphics, prev_int_pal_size, prev_graphics_alpha; bx_bool needs_update = 0, charmap_update = 0; #if defined(VGA_TRACE_FEATURE) if (!no_log) switch (io_len) { case 1: BX_DEBUG(("8-bit write to %04x = %02x", (unsigned)address, (unsigned)value)); break; case 2: BX_DEBUG(("16-bit write to %04x = %04x", (unsigned)address, (unsigned)value)); break; default: BX_PANIC(("Weird VGA write size")); } #else if (io_len == 1) { BX_DEBUG(("io write to 0x%04x = 0x%02x", (unsigned) address, (unsigned) value)); } #endif if (io_len == 2) { bx_vgacore_c::write(address, value & 0xff, 1, 1); bx_vgacore_c::write(address+1, (value >> 8) & 0xff, 1, 1); return; } if ((address >= 0x03b0) && (address <= 0x03bf) && (BX_VGA_THIS s.misc_output.color_emulation)) return; if ((address >= 0x03d0) && (address <= 0x03df) && (BX_VGA_THIS s.misc_output.color_emulation==0)) return; switch (address) { case 0x03ba: /* Feature Control (monochrome emulation modes) */ #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 3ba: feature control: ignoring")); #endif break; case 0x03c0: /* Attribute Controller */ if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) { /* address mode */ prev_video_enabled = BX_VGA_THIS s.attribute_ctrl.video_enabled; BX_VGA_THIS s.attribute_ctrl.video_enabled = (value >> 5) & 0x01; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 3c0: video_enabled = %u", (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled)); #endif if (BX_VGA_THIS s.attribute_ctrl.video_enabled == 0) bx_gui->clear_screen(); else if (!prev_video_enabled) { #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("found enable transition")); #endif needs_update = 1; } value &= 0x1f; /* address = bits 0..4 */ BX_VGA_THIS s.attribute_ctrl.address = value; switch (value) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: break; default: BX_DEBUG(("io write 0x3c0: address mode reg=0x%02x", (unsigned) value)); } } else { /* data-write mode */ switch (BX_VGA_THIS s.attribute_ctrl.address) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: if (value != BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address]) { BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address] = value; needs_update = 1; } break; case 0x10: // mode control register prev_line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics; prev_int_pal_size = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = (value >> 0) & 0x01; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = (value >> 1) & 0x01; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = (value >> 2) & 0x01; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = (value >> 3) & 0x01; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = (value >> 5) & 0x01; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = (value >> 6) & 0x01; BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = (value >> 7) & 0x01; if (((value >> 2) & 0x01) != prev_line_graphics) { charmap_update = 1; } if (((value >> 7) & 0x01) != prev_int_pal_size) { needs_update = 1; } #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 0x3c0: mode control: 0x%02x", (unsigned) value)); #endif break; case 0x11: // Overscan Color Register BX_VGA_THIS s.attribute_ctrl.overscan_color = (value & 0x3f); #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 0x3c0: overscan color = 0x%02x", (unsigned) value)); #endif break; case 0x12: // Color Plane Enable Register BX_VGA_THIS s.attribute_ctrl.color_plane_enable = (value & 0x0f); needs_update = 1; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 0x3c0: color plane enable = 0x%02x", (unsigned) value)); #endif break; case 0x13: // Horizontal Pixel Panning Register BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = (value & 0x0f); needs_update = 1; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 0x3c0: horiz pel panning = 0x%02x", (unsigned) value)); #endif break; case 0x14: // Color Select Register BX_VGA_THIS s.attribute_ctrl.color_select = (value & 0x0f); needs_update = 1; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 0x3c0: color select = 0x%02x", (unsigned) BX_VGA_THIS s.attribute_ctrl.color_select)); #endif break; default: BX_DEBUG(("io write 0x3c0: data-write mode 0x%02x", (unsigned) BX_VGA_THIS s.attribute_ctrl.address)); } } BX_VGA_THIS s.attribute_ctrl.flip_flop = !BX_VGA_THIS s.attribute_ctrl.flip_flop; break; case 0x03c2: // Miscellaneous Output Register BX_VGA_THIS s.misc_output.color_emulation = (value >> 0) & 0x01; BX_VGA_THIS s.misc_output.enable_ram = (value >> 1) & 0x01; BX_VGA_THIS s.misc_output.clock_select = (value >> 2) & 0x03; BX_VGA_THIS s.misc_output.select_high_bank = (value >> 5) & 0x01; BX_VGA_THIS s.misc_output.horiz_sync_pol = (value >> 6) & 0x01; BX_VGA_THIS s.misc_output.vert_sync_pol = (value >> 7) & 0x01; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 3c2:")); BX_DEBUG((" color_emulation (attempted) = %u", (value >> 0) & 0x01)); BX_DEBUG((" enable_ram = %u", (unsigned) BX_VGA_THIS s.misc_output.enable_ram)); BX_DEBUG((" clock_select = %u", (unsigned) BX_VGA_THIS s.misc_output.clock_select)); BX_DEBUG((" select_high_bank = %u", (unsigned) BX_VGA_THIS s.misc_output.select_high_bank)); BX_DEBUG((" horiz_sync_pol = %u", (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol)); BX_DEBUG((" vert_sync_pol = %u", (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol)); #endif calculate_retrace_timing(); break; case 0x03c3: // VGA enable // bit0: enables VGA display if set BX_VGA_THIS s.vga_enabled = value & 0x01; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 0x03c3: VGA enable = %u", BX_VGA_THIS s.vga_enabled)); #endif break; case 0x03c4: /* Sequencer Index Register */ if (value > 4) { BX_DEBUG(("io write 3c4: value > 4")); } BX_VGA_THIS s.sequencer.index = value; break; case 0x03c5: /* Sequencer Registers 00..04 */ switch (BX_VGA_THIS s.sequencer.index) { case 0: /* sequencer: reset */ #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("write 0x3c5: sequencer reset: value=0x%02x", (unsigned) value)); #endif if (BX_VGA_THIS s.sequencer.reset1 && ((value & 0x01) == 0)) { BX_VGA_THIS s.sequencer.char_map_select = 0; BX_VGA_THIS s.charmap_address = 0; charmap_update = 1; } BX_VGA_THIS s.sequencer.reset1 = (value >> 0) & 0x01; BX_VGA_THIS s.sequencer.reset2 = (value >> 1) & 0x01; break; case 1: /* sequencer: clocking mode */ if ((value ^ BX_VGA_THIS s.sequencer.reg1) & 0x29) { BX_VGA_THIS s.x_dotclockdiv2 = ((value & 0x08) > 0); BX_VGA_THIS s.sequencer.clear_screen = ((value & 0x20) > 0); calculate_retrace_timing(); needs_update = 1; } BX_VGA_THIS s.sequencer.reg1 = value & 0x3d; break; case 2: /* sequencer: map mask register */ BX_VGA_THIS s.sequencer.map_mask = (value & 0x0f); break; case 3: /* sequencer: character map select register */ BX_VGA_THIS s.sequencer.char_map_select = value & 0x3f; charmap1 = value & 0x13; if (charmap1 > 3) charmap1 = (charmap1 & 3) + 4; charmap2 = (value & 0x2C) >> 2; if (charmap2 > 3) charmap2 = (charmap2 & 3) + 4; if (BX_VGA_THIS s.CRTC.reg[0x09] > 0) { BX_VGA_THIS s.charmap_address = charmap_offset[charmap1]; charmap_update = 1; } if (charmap2 != charmap1) BX_INFO(("char map select: map #2 in block #%d unused", charmap2)); break; case 4: /* sequencer: memory mode register */ BX_VGA_THIS s.sequencer.extended_mem = (value >> 1) & 0x01; BX_VGA_THIS s.sequencer.odd_even = (value >> 2) & 0x01; BX_VGA_THIS s.sequencer.chain_four = (value >> 3) & 0x01; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write 0x3c5: memory mode:")); BX_DEBUG((" extended_mem = %u", (unsigned) BX_VGA_THIS s.sequencer.extended_mem)); BX_DEBUG((" odd_even = %u", (unsigned) BX_VGA_THIS s.sequencer.odd_even)); BX_DEBUG((" chain_four = %u", (unsigned) BX_VGA_THIS s.sequencer.chain_four)); #endif break; default: BX_DEBUG(("io write 0x3c5: index 0x%02x unhandled", (unsigned) BX_VGA_THIS s.sequencer.index)); } break; case 0x03c6: /* PEL mask */ BX_VGA_THIS s.pel.mask = value; if (BX_VGA_THIS s.pel.mask != 0xff) BX_DEBUG(("io write 0x3c6: PEL mask=0x%02x != 0xFF", value)); // BX_VGA_THIS s.pel.mask should be and'd with final value before // indexing into color register BX_VGA_THIS s.pel.data[] break; case 0x03c7: // PEL address, read mode BX_VGA_THIS s.pel.read_data_register = value; BX_VGA_THIS s.pel.read_data_cycle = 0; BX_VGA_THIS s.pel.dac_state = 0x03; break; case 0x03c8: /* PEL address write mode */ BX_VGA_THIS s.pel.write_data_register = value; BX_VGA_THIS s.pel.write_data_cycle = 0; BX_VGA_THIS s.pel.dac_state = 0x00; break; case 0x03c9: /* PEL Data Register, colors 00..FF */ switch (BX_VGA_THIS s.pel.write_data_cycle) { case 0: BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red = value; break; case 1: BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green = value; break; case 2: BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue = value; needs_update |= bx_gui->palette_change(BX_VGA_THIS s.pel.write_data_register, BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red << BX_VGA_THIS s.dac_shift, BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green << BX_VGA_THIS s.dac_shift, BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue << BX_VGA_THIS s.dac_shift); break; } BX_VGA_THIS s.pel.write_data_cycle++; if (BX_VGA_THIS s.pel.write_data_cycle >= 3) { //BX_INFO(("BX_VGA_THIS s.pel.data[%u] {r=%u, g=%u, b=%u}", // (unsigned) BX_VGA_THIS s.pel.write_data_register, // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red, // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green, // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue); BX_VGA_THIS s.pel.write_data_cycle = 0; BX_VGA_THIS s.pel.write_data_register++; } break; case 0x03ca: /* Graphics 2 Position (EGA) */ // ignore, EGA only??? break; case 0x03cc: /* Graphics 1 Position (EGA) */ // ignore, EGA only??? break; case 0x03cd: /* ??? */ BX_DEBUG(("io write to 0x3cd = 0x%02x", (unsigned) value)); break; case 0x03ce: /* Graphics Controller Index Register */ if (value > 0x08) /* ??? */ BX_DEBUG(("io write: 0x3ce: value > 8")); BX_VGA_THIS s.graphics_ctrl.index = value; break; case 0x03cf: /* Graphics Controller Registers 00..08 */ switch (BX_VGA_THIS s.graphics_ctrl.index) { case 0: /* Set/Reset */ BX_VGA_THIS s.graphics_ctrl.set_reset = value & 0x0f; break; case 1: /* Enable Set/Reset */ BX_VGA_THIS s.graphics_ctrl.enable_set_reset = value & 0x0f; break; case 2: /* Color Compare */ BX_VGA_THIS s.graphics_ctrl.color_compare = value & 0x0f; break; case 3: /* Data Rotate */ BX_VGA_THIS s.graphics_ctrl.data_rotate = value & 0x07; BX_VGA_THIS s.graphics_ctrl.raster_op = (value >> 3) & 0x03; break; case 4: /* Read Map Select */ BX_VGA_THIS s.graphics_ctrl.read_map_select = value & 0x03; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("io write to 0x3cf = 0x%02x (RMS)", (unsigned) value)); #endif break; case 5: /* Mode */ BX_VGA_THIS s.graphics_ctrl.write_mode = value & 0x03; BX_VGA_THIS s.graphics_ctrl.read_mode = (value >> 3) & 0x01; BX_VGA_THIS s.graphics_ctrl.odd_even = (value >> 4) & 0x01; BX_VGA_THIS s.graphics_ctrl.shift_reg = (value >> 5) & 0x03; if (BX_VGA_THIS s.graphics_ctrl.odd_even) BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x", (unsigned) value)); if (BX_VGA_THIS s.graphics_ctrl.shift_reg) BX_DEBUG(("io write: 0x3cf: mode reg: value = 0x%02x", (unsigned) value)); break; case 6: /* Miscellaneous */ prev_graphics_alpha = BX_VGA_THIS s.graphics_ctrl.graphics_alpha; // prev_chain_odd_even = BX_VGA_THIS s.graphics_ctrl.chain_odd_even; prev_memory_mapping = BX_VGA_THIS s.graphics_ctrl.memory_mapping; BX_VGA_THIS s.graphics_ctrl.graphics_alpha = value & 0x01; BX_VGA_THIS s.graphics_ctrl.chain_odd_even = (value >> 1) & 0x01; BX_VGA_THIS s.graphics_ctrl.memory_mapping = (value >> 2) & 0x03; #if !defined(VGA_TRACE_FEATURE) BX_DEBUG(("memory_mapping set to %u", (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping)); BX_DEBUG(("graphics mode set to %u", (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha)); BX_DEBUG(("odd_even mode set to %u", (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even)); BX_DEBUG(("io write: 0x3cf: misc reg: value = 0x%02x", (unsigned) value)); #endif if (prev_memory_mapping != BX_VGA_THIS s.graphics_ctrl.memory_mapping) needs_update = 1; if (prev_graphics_alpha != BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { needs_update = 1; BX_VGA_THIS s.last_yres = 0; } break; case 7: /* Color Don't Care */ BX_VGA_THIS s.graphics_ctrl.color_dont_care = value & 0x0f; break; case 8: /* Bit Mask */ BX_VGA_THIS s.graphics_ctrl.bitmask = value; break; default: /* ??? */ BX_DEBUG(("io write: 0x3cf: index %u unhandled", (unsigned) BX_VGA_THIS s.graphics_ctrl.index)); } break; case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */ case 0x03d4: /* CRTC Index Register (color emulation modes) */ BX_VGA_THIS s.CRTC.address = value & 0x7f; if (BX_VGA_THIS s.CRTC.address > 0x18) BX_DEBUG(("write: invalid CRTC register 0x%02x selected", (unsigned) BX_VGA_THIS s.CRTC.address)); break; case 0x03b5: /* CRTC Registers (monochrome emulation modes) */ case 0x03d5: /* CRTC Registers (color emulation modes) */ if (BX_VGA_THIS s.CRTC.address > 0x18) { BX_DEBUG(("write: invalid CRTC register 0x%02x ignored", (unsigned) BX_VGA_THIS s.CRTC.address)); return; } if (BX_VGA_THIS s.CRTC.write_protect && (BX_VGA_THIS s.CRTC.address < 0x08)) { if (BX_VGA_THIS s.CRTC.address == 0x07) { BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] &= ~0x10; BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] |= (value & 0x10); BX_VGA_THIS s.line_compare &= 0x2ff; if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100; needs_update = 1; break; } else { return; } } if (value != BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]) { BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] = value; switch (BX_VGA_THIS s.CRTC.address) { case 0x00: case 0x02: case 0x03: case 0x05: case 0x06: case 0x10: calculate_retrace_timing(); break; case 0x07: BX_VGA_THIS s.vertical_display_end &= 0xff; if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x02) BX_VGA_THIS s.vertical_display_end |= 0x100; if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x40) BX_VGA_THIS s.vertical_display_end |= 0x200; BX_VGA_THIS s.line_compare &= 0x2ff; if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100; calculate_retrace_timing(); needs_update = 1; break; case 0x08: // Vertical pel panning change needs_update = 1; break; case 0x09: BX_VGA_THIS s.y_doublescan = ((value & 0x9f) > 0); BX_VGA_THIS s.line_compare &= 0x1ff; if (BX_VGA_THIS s.CRTC.reg[0x09] & 0x40) BX_VGA_THIS s.line_compare |= 0x200; charmap_update = 1; needs_update = 1; break; case 0x0A: case 0x0B: case 0x0E: case 0x0F: // Cursor size / location change BX_VGA_THIS s.vga_mem_updated = 1; break; case 0x0C: case 0x0D: // Start address change if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { needs_update = 1; } else { BX_VGA_THIS s.vga_mem_updated = 1; } break; case 0x11: BX_VGA_THIS s.CRTC.write_protect = ((BX_VGA_THIS s.CRTC.reg[0x11] & 0x80) > 0); calculate_retrace_timing(); break; case 0x12: BX_VGA_THIS s.vertical_display_end &= 0x300; BX_VGA_THIS s.vertical_display_end |= BX_VGA_THIS s.CRTC.reg[0x12]; calculate_retrace_timing(); break; case 0x13: case 0x14: case 0x17: // Line offset change BX_VGA_THIS s.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 1; if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) BX_VGA_THIS s.line_offset <<= 2; else if ((BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) == 0) BX_VGA_THIS s.line_offset <<= 1; needs_update = 1; break; case 0x18: BX_VGA_THIS s.line_compare &= 0x300; BX_VGA_THIS s.line_compare |= BX_VGA_THIS s.CRTC.reg[0x18]; needs_update = 1; break; } } break; case 0x03da: /* Feature Control (color emulation modes) */ BX_DEBUG(("io write: 3da: ignoring: feature ctrl & vert sync")); break; case 0x03c1: /* */ default: BX_ERROR(("unsupported io write to port 0x%04x, val=0x%02x", (unsigned) address, (unsigned) value)); } if (charmap_update) { bx_gui->set_text_charmap( & BX_VGA_THIS s.memory[0x20000 + BX_VGA_THIS s.charmap_address]); BX_VGA_THIS s.vga_mem_updated = 1; } if (needs_update) { // Mark all video as updated so the changes will go through BX_VGA_THIS redraw_area(0, 0, BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres); } } void bx_vgacore_c::set_override(bx_bool enabled) { if (enabled) { bx_virt_timer.deactivate_timer(BX_VGA_THIS timer_id); } else { Bit64u interval = 1000000 / SIM->get_param_num(BXPN_VGA_UPDATE_FREQUENCY)->get(); bx_virt_timer.activate_timer(BX_VGA_THIS timer_id, (Bit32u)interval, 1); BX_VGA_THIS redraw_area(0, 0, BX_VGA_THIS s.last_xres, BX_VGA_THIS s.last_yres); } } void bx_vgacore_c::trigger_timer(void *this_ptr) { timer_handler(this_ptr); } void bx_vgacore_c::timer_handler(void *this_ptr) { bx_vgacore_c *class_ptr = (bx_vgacore_c *) this_ptr; class_ptr->timer(); } void bx_vgacore_c::timer(void) { update(); bx_gui->flush(); } Bit8u bx_vgacore_c::get_vga_pixel(Bit16u x, Bit16u y, Bit16u saddr, Bit16u lc, bx_bool bs, Bit8u **plane) { Bit8u attribute, bit_no, palette_reg_val, DAC_regno; Bit32u byte_offset; if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1; bit_no = 7 - (x % 8); if (y > lc) { byte_offset = x / 8 + ((y - lc - 1) * BX_VGA_THIS s.line_offset); } else { byte_offset = saddr + x / 8 + (y * BX_VGA_THIS s.line_offset); } attribute = (((plane[0][byte_offset] >> bit_no) & 0x01) << 0) | (((plane[1][byte_offset] >> bit_no) & 0x01) << 1) | (((plane[2][byte_offset] >> bit_no) & 0x01) << 2) | (((plane[3][byte_offset] >> bit_no) & 0x01) << 3); attribute &= BX_VGA_THIS s.attribute_ctrl.color_plane_enable; // undocumented feature ???: colors 0..7 high intensity, colors 8..15 blinking if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity) { if (bs) { attribute |= 0x08; } else { attribute ^= 0x08; } } palette_reg_val = BX_VGA_THIS s.attribute_ctrl.palette_reg[attribute]; if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size) { // use 4 lower bits from palette register // use 4 higher bits from color select register // 16 banks of 16-color registers DAC_regno = (palette_reg_val & 0x0f) | (BX_VGA_THIS s.attribute_ctrl.color_select << 4); } else { // use 6 lower bits from palette register // use 2 higher bits from color select register // 4 banks of 64-color registers DAC_regno = (palette_reg_val & 0x3f) | ((BX_VGA_THIS s.attribute_ctrl.color_select & 0x0c) << 4); } // DAC_regno &= video DAC mask register ??? return DAC_regno; } bx_bool bx_vgacore_c::skip_update(void) { Bit64u display_usec; /* handle clear screen request from the sequencer */ if (BX_VGA_THIS s.sequencer.clear_screen) { bx_gui->clear_screen(); BX_VGA_THIS s.sequencer.clear_screen = 0; } /* skip screen update when vga/video is disabled or the sequencer is in reset mode */ if (!BX_VGA_THIS s.vga_enabled || !BX_VGA_THIS s.attribute_ctrl.video_enabled || !BX_VGA_THIS s.sequencer.reset2 || !BX_VGA_THIS s.sequencer.reset1 || (BX_VGA_THIS s.sequencer.reg1 & 0x20)) return 1; /* skip screen update if the vertical retrace is in progress */ display_usec = bx_pc_system.time_usec() % BX_VGA_THIS s.vtotal_usec; if ((display_usec > BX_VGA_THIS s.vrstart_usec) && (display_usec < BX_VGA_THIS s.vrend_usec)) { return 1; } return 0; } void bx_vgacore_c::update(void) { unsigned iHeight, iWidth; static unsigned cs_counter = 1; static bx_bool cs_visible = 0; bx_bool cs_toggle = 0; cs_counter--; /* no screen update necessary */ if ((BX_VGA_THIS s.vga_mem_updated == 0) && (cs_counter > 0)) return; if (cs_counter == 0) { cs_counter = BX_VGA_THIS s.blink_counter; if ((!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) || (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity)) { cs_toggle = 1; cs_visible = !cs_visible; } else { if (BX_VGA_THIS s.vga_mem_updated == 0) return; cs_toggle = 0; cs_visible = 0; } } // fields that effect the way video memory is serialized into screen output: // GRAPHICS CONTROLLER: // BX_VGA_THIS s.graphics_ctrl.shift_reg: // 0: output data in standard VGA format or CGA-compatible 640x200 2 color // graphics mode (mode 6) // 1: output data in CGA-compatible 320x200 4 color graphics mode // (modes 4 & 5) // 2: output data 8 bits at a time from the 4 bit planes // (mode 13 and variants like modeX) // if (BX_VGA_THIS s.vga_mem_updated==0 || BX_VGA_THIS s.attribute_ctrl.video_enabled == 0) if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { // Graphics mode Bit8u color; unsigned bit_no, r, c, x, y; unsigned long byte_offset, start_addr; unsigned xc, yc, xti, yti; start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d]; determine_screen_dimensions(&iHeight, &iWidth); if((iWidth != BX_VGA_THIS s.last_xres) || (iHeight != BX_VGA_THIS s.last_yres) || (BX_VGA_THIS s.last_bpp > 8)) { bx_gui->dimension_update(iWidth, iHeight); BX_VGA_THIS s.last_xres = iWidth; BX_VGA_THIS s.last_yres = iHeight; BX_VGA_THIS s.last_bpp = 8; } if (skip_update()) return; switch (BX_VGA_THIS s.graphics_ctrl.shift_reg) { case 0: // interleaved shift Bit8u attribute, palette_reg_val, DAC_regno; unsigned long line_compare; Bit8u *plane[4]; if ((BX_VGA_THIS s.CRTC.reg[0x17] & 1) == 0) { // CGA 640x200x2 for (yc=0, yti=0; yc>= 1; for (c=0; c> bit_no) & 1); DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val]; BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno; } } SET_TILE_UPDATED (xti, yti, 0); bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); } } } } else { // output data in serial fashion with each display plane // output on its associated serial output. Standard EGA/VGA format plane[0] = &BX_VGA_THIS s.memory[0 << BX_VGA_THIS s.plane_shift]; plane[1] = &BX_VGA_THIS s.memory[1 << BX_VGA_THIS s.plane_shift]; plane[2] = &BX_VGA_THIS s.memory[2 << BX_VGA_THIS s.plane_shift]; plane[3] = &BX_VGA_THIS s.memory[3 << BX_VGA_THIS s.plane_shift]; line_compare = BX_VGA_THIS s.line_compare; if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1; for (yc=0, yti=0; yc>= 1; for (c=0; cgraphics_tile_update(BX_VGA_THIS s.tile, xc, yc); } } } } break; // case 0 case 1: // output the data in a CGA-compatible 320x200 4 color graphics // mode. (planar shift, modes 4 & 5) /* CGA 320x200x4 start */ for (yc=0, yti=0; yc>= 1; for (c=0; c>= 1; /* 0 or 0x2000 */ byte_offset = start_addr + ((y & 1) << 13); /* to the start of the line */ byte_offset += (320 / 4) * (y / 2); /* to the byte start */ byte_offset += (x / 4); attribute = 6 - 2*(x % 4); palette_reg_val = (BX_VGA_THIS s.memory[byte_offset]) >> attribute; palette_reg_val &= 3; DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val]; BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno; } } SET_TILE_UPDATED (xti, yti, 0); bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); } } } /* CGA 320x200x4 end */ break; // case 1 case 2: // output the data eight bits at a time from the 4 bit plane // (format for VGA mode 13 hex) case 3: // FIXME: is this really the same ??? if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) { // DW set: doubleword mode unsigned long pixely, pixelx, plane; if (BX_VGA_THIS s.misc_output.select_high_bank != 1) BX_PANIC(("update: select_high_bank != 1")); for (yc=0, yti=0; yc>= 1; for (c=0; c> 1; plane = (pixelx % 4); byte_offset = start_addr + (plane * 65536) + (pixely * BX_VGA_THIS s.line_offset) + (pixelx & ~0x03); color = BX_VGA_THIS s.memory[byte_offset]; BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color; } } SET_TILE_UPDATED (xti, yti, 0); bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); } } } } else if (BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) { // B/W set: byte mode, modeX unsigned long pixely, pixelx, plane; for (yc=0, yti=0; yc>= 1; for (c=0; c> 1; plane = (pixelx % 4); byte_offset = (plane * 65536) + (pixely * BX_VGA_THIS s.line_offset) + (pixelx >> 2); color = BX_VGA_THIS s.memory[start_addr + byte_offset]; BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color; } } SET_TILE_UPDATED (xti, yti, 0); bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); } } } } else { // word mode unsigned long pixely, pixelx, plane; for (yc=0, yti=0; yc>= 1; for (c=0; c> 1; plane = (pixelx % 4); byte_offset = (plane * 65536) + (pixely * BX_VGA_THIS s.line_offset) + ((pixelx >> 1) & ~0x01); color = BX_VGA_THIS s.memory[start_addr + byte_offset]; BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color; } } SET_TILE_UPDATED (xti, yti, 0); bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc); } } } } break; // case 2 default: BX_PANIC(("update: shift_reg == %u", (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg)); } BX_VGA_THIS s.vga_mem_updated = 0; return; } else { // text mode unsigned long start_address; unsigned long cursor_address, cursor_x, cursor_y; bx_vga_tminfo_t tm_info; unsigned VDE, cols, rows, cWidth; Bit8u MSL; tm_info.start_address = 2*((BX_VGA_THIS s.CRTC.reg[12] << 8) + BX_VGA_THIS s.CRTC.reg[13]); tm_info.cs_start = BX_VGA_THIS s.CRTC.reg[0x0a] & 0x3f; if (!cs_visible) { tm_info.cs_start |= 0x20; } tm_info.cs_end = BX_VGA_THIS s.CRTC.reg[0x0b] & 0x1f; tm_info.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 2; tm_info.line_compare = BX_VGA_THIS s.line_compare; tm_info.h_panning = BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning & 0x0f; tm_info.v_panning = BX_VGA_THIS s.CRTC.reg[0x08] & 0x1f; tm_info.line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics; tm_info.split_hpanning = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat; tm_info.blink_flags = 0; if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity) { tm_info.blink_flags |= BX_TEXT_BLINK_MODE; if (cs_toggle) tm_info.blink_flags |= BX_TEXT_BLINK_TOGGLE; if (cs_visible) tm_info.blink_flags |= BX_TEXT_BLINK_STATE; } if ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 0) { if (tm_info.h_panning >= 8) tm_info.h_panning = 0; else tm_info.h_panning++; } else { tm_info.h_panning &= 0x07; } for (int index = 0; index < 16; index++) { tm_info.actl_palette[index] = BX_VGA_THIS s.attribute_ctrl.palette_reg[index]; } // Verticle Display End: find out how many lines are displayed VDE = BX_VGA_THIS s.vertical_display_end; // Maximum Scan Line: height of character cell MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f; cols = BX_VGA_THIS s.CRTC.reg[1] + 1; // workaround for update() calls before VGABIOS init if (cols == 1) { cols = 80; MSL = 15; } if ((MSL == 1) && (VDE == 399)) { // emulated CGA graphics mode 160x100x16 colors MSL = 3; } rows = (VDE+1)/(MSL+1); if ((rows * tm_info.line_offset) > (1 << 17)) { BX_ERROR(("update(): text mode: out of memory")); return; } cWidth = ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 1) ? 8 : 9; iWidth = cWidth * cols; iHeight = VDE+1; if ((iWidth != BX_VGA_THIS s.last_xres) || (iHeight != BX_VGA_THIS s.last_yres) || (MSL != BX_VGA_THIS s.last_msl) || (BX_VGA_THIS s.last_bpp > 8)) { bx_gui->dimension_update(iWidth, iHeight, MSL+1, cWidth); BX_VGA_THIS s.last_xres = iWidth; BX_VGA_THIS s.last_yres = iHeight; BX_VGA_THIS s.last_msl = MSL; BX_VGA_THIS s.last_bpp = 8; } if (skip_update()) return; // pass old text snapshot & new VGA memory contents start_address = tm_info.start_address; cursor_address = 2*((BX_VGA_THIS s.CRTC.reg[0x0e] << 8) + BX_VGA_THIS s.CRTC.reg[0x0f]); if (cursor_address < start_address) { cursor_x = 0xffff; cursor_y = 0xffff; } else { cursor_x = ((cursor_address - start_address)/2) % (iWidth/cWidth); cursor_y = ((cursor_address - start_address)/2) / (iWidth/cWidth); } bx_gui->text_update(BX_VGA_THIS s.text_snapshot, &BX_VGA_THIS s.memory[start_address], cursor_x, cursor_y, &tm_info); if (BX_VGA_THIS s.vga_mem_updated) { // screen updated, copy new VGA memory contents into text snapshot memcpy(BX_VGA_THIS s.text_snapshot, &BX_VGA_THIS s.memory[start_address], tm_info.line_offset*rows); BX_VGA_THIS s.vga_mem_updated = 0; } } } bx_bool bx_vgacore_c::mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { bx_vgacore_c *class_ptr = (bx_vgacore_c *) param; Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { *data_ptr = class_ptr->mem_read(addr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } Bit8u bx_vgacore_c::mem_read(bx_phy_address addr) { Bit32u offset; Bit8u *plane0, *plane1, *plane2, *plane3; switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) { case 1: // 0xA0000 .. 0xAFFFF if (addr > 0xAFFFF) return 0xff; offset = addr & 0xFFFF; break; case 2: // 0xB0000 .. 0xB7FFF if ((addr < 0xB0000) || (addr > 0xB7FFF)) return 0xff; offset = addr & 0x7FFF; break; case 3: // 0xB8000 .. 0xBFFFF if (addr < 0xB8000) return 0xff; offset = addr & 0x7FFF; break; default: // 0xA0000 .. 0xBFFFF offset = addr & 0x1FFFF; } if (BX_VGA_THIS s.sequencer.chain_four) { // Mode 13h: 320 x 200 256 color mode: chained pixel representation return BX_VGA_THIS s.memory[(offset & ~0x03) + (offset % 4)*65536]; } plane0 = &BX_VGA_THIS s.memory[(0 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; plane1 = &BX_VGA_THIS s.memory[(1 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; plane2 = &BX_VGA_THIS s.memory[(2 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; plane3 = &BX_VGA_THIS s.memory[(3 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; /* addr between 0xA0000 and 0xAFFFF */ switch (BX_VGA_THIS s.graphics_ctrl.read_mode) { case 0: /* read mode 0 */ BX_VGA_THIS s.graphics_ctrl.latch[0] = plane0[offset]; BX_VGA_THIS s.graphics_ctrl.latch[1] = plane1[offset]; BX_VGA_THIS s.graphics_ctrl.latch[2] = plane2[offset]; BX_VGA_THIS s.graphics_ctrl.latch[3] = plane3[offset]; return(BX_VGA_THIS s.graphics_ctrl.latch[BX_VGA_THIS s.graphics_ctrl.read_map_select]); break; case 1: /* read mode 1 */ { Bit8u color_compare, color_dont_care; Bit8u latch0, latch1, latch2, latch3, retval; color_compare = BX_VGA_THIS s.graphics_ctrl.color_compare & 0x0f; color_dont_care = BX_VGA_THIS s.graphics_ctrl.color_dont_care & 0x0f; latch0 = BX_VGA_THIS s.graphics_ctrl.latch[0] = plane0[offset]; latch1 = BX_VGA_THIS s.graphics_ctrl.latch[1] = plane1[offset]; latch2 = BX_VGA_THIS s.graphics_ctrl.latch[2] = plane2[offset]; latch3 = BX_VGA_THIS s.graphics_ctrl.latch[3] = plane3[offset]; latch0 ^= ccdat[color_compare][0]; latch1 ^= ccdat[color_compare][1]; latch2 ^= ccdat[color_compare][2]; latch3 ^= ccdat[color_compare][3]; latch0 &= ccdat[color_dont_care][0]; latch1 &= ccdat[color_dont_care][1]; latch2 &= ccdat[color_dont_care][2]; latch3 &= ccdat[color_dont_care][3]; retval = ~(latch0 | latch1 | latch2 | latch3); return retval; } break; default: return 0; } } bx_bool bx_vgacore_c::mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { bx_vgacore_c *class_ptr = (bx_vgacore_c *) param; Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { class_ptr->mem_write(addr, *data_ptr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } void bx_vgacore_c::mem_write(bx_phy_address addr, Bit8u value) { Bit32u offset; Bit8u new_val[4] = {0,0,0,0}; unsigned start_addr; Bit8u *plane0, *plane1, *plane2, *plane3; switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) { case 1: // 0xA0000 .. 0xAFFFF if ((addr < 0xA0000) || (addr > 0xAFFFF)) return; offset = (Bit32u)addr - 0xA0000; break; case 2: // 0xB0000 .. 0xB7FFF if ((addr < 0xB0000) || (addr > 0xB7FFF)) return; offset = (Bit32u)addr - 0xB0000; break; case 3: // 0xB8000 .. 0xBFFFF if ((addr < 0xB8000) || (addr > 0xBFFFF)) return; offset = (Bit32u)addr - 0xB8000; break; default: // 0xA0000 .. 0xBFFFF if ((addr < 0xA0000) || (addr > 0xBFFFF)) return; offset = (Bit32u)addr - 0xA0000; } start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d]; if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // 0xB8000 .. 0xBFFFF unsigned x_tileno, x_tileno2, y_tileno; /* CGA 320x200x4 / 640x200x2 start */ BX_VGA_THIS s.memory[offset] = value; offset -= start_addr; if (offset>=0x2000) { y_tileno = offset - 0x2000; y_tileno /= (320/4); y_tileno <<= 1; //2 * y_tileno; y_tileno++; x_tileno = (offset - 0x2000) % (320/4); x_tileno <<= 2; //*= 4; } else { y_tileno = offset / (320/4); y_tileno <<= 1; //2 * y_tileno; x_tileno = offset % (320/4); x_tileno <<= 2; //*=4; } x_tileno2=x_tileno; if (BX_VGA_THIS s.graphics_ctrl.shift_reg==0) { x_tileno*=2; x_tileno2+=7; } else { x_tileno2+=3; } if (BX_VGA_THIS s.x_dotclockdiv2) { x_tileno/=(X_TILESIZE/2); x_tileno2/=(X_TILESIZE/2); } else { x_tileno/=X_TILESIZE; x_tileno2/=X_TILESIZE; } if (BX_VGA_THIS s.y_doublescan) { y_tileno/=(Y_TILESIZE/2); } else { y_tileno/=Y_TILESIZE; } BX_VGA_THIS s.vga_mem_updated = 1; SET_TILE_UPDATED (x_tileno, y_tileno, 1); if (x_tileno2!=x_tileno) { SET_TILE_UPDATED (x_tileno2, y_tileno, 1); } return; /* CGA 320x200x4 / 640x200x2 end */ } /* else if (BX_VGA_THIS s.graphics_ctrl.memory_mapping != 1) { BX_PANIC(("mem_write: graphics: mapping = %u", (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping)); return; } */ if (BX_VGA_THIS s.sequencer.chain_four) { unsigned x_tileno, y_tileno; // 320 x 200 256 color mode: chained pixel representation BX_VGA_THIS s.memory[(offset & ~0x03) + (offset % 4)*65536] = value; if (BX_VGA_THIS s.line_offset > 0) { offset -= start_addr; x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE/2); if (BX_VGA_THIS s.y_doublescan) { y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE/2); } else { y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE; } BX_VGA_THIS s.vga_mem_updated = 1; SET_TILE_UPDATED (x_tileno, y_tileno, 1); } return; } } /* addr between 0xA0000 and 0xAFFFF */ plane0 = &BX_VGA_THIS s.memory[(0 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; plane1 = &BX_VGA_THIS s.memory[(1 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; plane2 = &BX_VGA_THIS s.memory[(2 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; plane3 = &BX_VGA_THIS s.memory[(3 << BX_VGA_THIS s.plane_shift) + BX_VGA_THIS s.plane_offset]; switch (BX_VGA_THIS s.graphics_ctrl.write_mode) { unsigned i; case 0: /* write mode 0 */ { const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask; const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset; const Bit8u enable_set_reset = BX_VGA_THIS s.graphics_ctrl.enable_set_reset; /* perform rotate on CPU data in case its needed */ if (BX_VGA_THIS s.graphics_ctrl.data_rotate) { value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) | (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate)); } new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask; new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask; new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask; new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask; switch (BX_VGA_THIS s.graphics_ctrl.raster_op) { case 0: // replace new_val[0] |= ((enable_set_reset & 1) ? ((set_reset & 1) ? bitmask : 0) : (value & bitmask)); new_val[1] |= ((enable_set_reset & 2) ? ((set_reset & 2) ? bitmask : 0) : (value & bitmask)); new_val[2] |= ((enable_set_reset & 4) ? ((set_reset & 4) ? bitmask : 0) : (value & bitmask)); new_val[3] |= ((enable_set_reset & 8) ? ((set_reset & 8) ? bitmask : 0) : (value & bitmask)); break; case 1: // AND new_val[0] |= ((enable_set_reset & 1) ? ((set_reset & 1) ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) : 0) : (value & BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask); new_val[1] |= ((enable_set_reset & 2) ? ((set_reset & 2) ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) : 0) : (value & BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask); new_val[2] |= ((enable_set_reset & 4) ? ((set_reset & 4) ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) : 0) : (value & BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask); new_val[3] |= ((enable_set_reset & 8) ? ((set_reset & 8) ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) : 0) : (value & BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask); break; case 2: // OR new_val[0] |= ((enable_set_reset & 1) ? ((set_reset & 1) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)) : ((value | BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask)); new_val[1] |= ((enable_set_reset & 2) ? ((set_reset & 2) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)) : ((value | BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask)); new_val[2] |= ((enable_set_reset & 4) ? ((set_reset & 4) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)) : ((value | BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask)); new_val[3] |= ((enable_set_reset & 8) ? ((set_reset & 8) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)) : ((value | BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask)); break; case 3: // XOR new_val[0] |= ((enable_set_reset & 1) ? ((set_reset & 1) ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)) : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask); new_val[1] |= ((enable_set_reset & 2) ? ((set_reset & 2) ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)) : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask); new_val[2] |= ((enable_set_reset & 4) ? ((set_reset & 4) ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)) : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask); new_val[3] |= ((enable_set_reset & 8) ? ((set_reset & 8) ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)) : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask); break; default: BX_PANIC(("vga_mem_write: write mode 0: op = %u", (unsigned) BX_VGA_THIS s.graphics_ctrl.raster_op)); } } break; case 1: /* write mode 1 */ for (i=0; i<4; i++) { new_val[i] = BX_VGA_THIS s.graphics_ctrl.latch[i]; } break; case 2: /* write mode 2 */ { const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask; new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask; new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask; new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask; new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask; switch (BX_VGA_THIS s.graphics_ctrl.raster_op) { case 0: // write new_val[0] |= (value & 1) ? bitmask : 0; new_val[1] |= (value & 2) ? bitmask : 0; new_val[2] |= (value & 4) ? bitmask : 0; new_val[3] |= (value & 8) ? bitmask : 0; break; case 1: // AND new_val[0] |= (value & 1) ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) : 0; new_val[1] |= (value & 2) ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) : 0; new_val[2] |= (value & 4) ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) : 0; new_val[3] |= (value & 8) ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) : 0; break; case 2: // OR new_val[0] |= (value & 1) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask); new_val[1] |= (value & 2) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask); new_val[2] |= (value & 4) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask); new_val[3] |= (value & 8) ? bitmask : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask); break; case 3: // XOR new_val[0] |= (value & 1) ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask); new_val[1] |= (value & 2) ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask); new_val[2] |= (value & 4) ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask); new_val[3] |= (value & 8) ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask) : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask); break; } } break; case 3: /* write mode 3 */ { const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask & value; const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset; /* perform rotate on CPU data */ if (BX_VGA_THIS s.graphics_ctrl.data_rotate) { value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) | (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate)); } new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask; new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask; new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask; new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask; value &= bitmask; switch (BX_VGA_THIS s.graphics_ctrl.raster_op) { case 0: // write new_val[0] |= (set_reset & 1) ? value : 0; new_val[1] |= (set_reset & 2) ? value : 0; new_val[2] |= (set_reset & 4) ? value : 0; new_val[3] |= (set_reset & 8) ? value : 0; break; case 1: // AND new_val[0] |= ((set_reset & 1) ? value : 0) & BX_VGA_THIS s.graphics_ctrl.latch[0]; new_val[1] |= ((set_reset & 2) ? value : 0) & BX_VGA_THIS s.graphics_ctrl.latch[1]; new_val[2] |= ((set_reset & 4) ? value : 0) & BX_VGA_THIS s.graphics_ctrl.latch[2]; new_val[3] |= ((set_reset & 8) ? value : 0) & BX_VGA_THIS s.graphics_ctrl.latch[3]; break; case 2: // OR new_val[0] |= ((set_reset & 1) ? value : 0) | BX_VGA_THIS s.graphics_ctrl.latch[0]; new_val[1] |= ((set_reset & 2) ? value : 0) | BX_VGA_THIS s.graphics_ctrl.latch[1]; new_val[2] |= ((set_reset & 4) ? value : 0) | BX_VGA_THIS s.graphics_ctrl.latch[2]; new_val[3] |= ((set_reset & 8) ? value : 0) | BX_VGA_THIS s.graphics_ctrl.latch[3]; break; case 3: // XOR new_val[0] |= ((set_reset & 1) ? value : 0) ^ BX_VGA_THIS s.graphics_ctrl.latch[0]; new_val[1] |= ((set_reset & 2) ? value : 0) ^ BX_VGA_THIS s.graphics_ctrl.latch[1]; new_val[2] |= ((set_reset & 4) ? value : 0) ^ BX_VGA_THIS s.graphics_ctrl.latch[2]; new_val[3] |= ((set_reset & 8) ? value : 0) ^ BX_VGA_THIS s.graphics_ctrl.latch[3]; break; } } break; default: BX_PANIC(("vga_mem_write: write mode %u ?", (unsigned) BX_VGA_THIS s.graphics_ctrl.write_mode)); } if (BX_VGA_THIS s.sequencer.map_mask & 0x0f) { BX_VGA_THIS s.vga_mem_updated = 1; if (BX_VGA_THIS s.sequencer.map_mask & 0x01) plane0[offset] = new_val[0]; if (BX_VGA_THIS s.sequencer.map_mask & 0x02) plane1[offset] = new_val[1]; if (BX_VGA_THIS s.sequencer.map_mask & 0x04) { if ((offset & 0xe000) == BX_VGA_THIS s.charmap_address) { bx_gui->set_text_charbyte((offset & 0x1fff), new_val[2]); } plane2[offset] = new_val[2]; } if (BX_VGA_THIS s.sequencer.map_mask & 0x08) plane3[offset] = new_val[3]; unsigned x_tileno, y_tileno; if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) { offset -= start_addr; x_tileno = (offset % BX_VGA_THIS s.line_offset) * 4 / (X_TILESIZE / 2); if (BX_VGA_THIS s.y_doublescan) { y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2); } else { y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE; } SET_TILE_UPDATED (x_tileno, y_tileno, 1); } else { if (BX_VGA_THIS s.line_compare < BX_VGA_THIS s.vertical_display_end) { if (BX_VGA_THIS s.line_offset > 0) { if (BX_VGA_THIS s.x_dotclockdiv2) { x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16); } else { x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8); } if (BX_VGA_THIS s.y_doublescan) { y_tileno = ((offset / BX_VGA_THIS s.line_offset) * 2 + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE; } else { y_tileno = ((offset / BX_VGA_THIS s.line_offset) + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE; } SET_TILE_UPDATED (x_tileno, y_tileno, 1); } } if (offset >= start_addr) { offset -= start_addr; if (BX_VGA_THIS s.line_offset > 0) { if (BX_VGA_THIS s.x_dotclockdiv2) { x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16); } else { x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8); } if (BX_VGA_THIS s.y_doublescan) { y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2); } else { y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE; } SET_TILE_UPDATED (x_tileno, y_tileno, 1); } } } } } int bx_vgacore_c::get_snapshot_mode() { if (!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { return BX_GUI_SNAPSHOT_TXT; } else if ((BX_VGA_THIS s.graphics_ctrl.shift_reg == 0) && ((BX_VGA_THIS s.CRTC.reg[0x17] & 1) != 0)) { return BX_GUI_SNAPSHOT_GFX; } else if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) { return BX_GUI_SNAPSHOT_GFX; } else { return BX_GUI_SNAPSHOT_UNSUP; } } void bx_vgacore_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, unsigned *txWidth) { unsigned VDE, MSL; if (!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { *text_snapshot = &BX_VGA_THIS s.text_snapshot[0]; VDE = BX_VGA_THIS s.vertical_display_end; MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f; *txHeight = (VDE+1)/(MSL+1); *txWidth = BX_VGA_THIS s.CRTC.reg[1] + 1; } else { *txHeight = 0; *txWidth = 0; } } bx_bool bx_vgacore_c::get_dac_palette(Bit8u **palette_ptr, Bit8u shift) { unsigned i; Bit8u *dst_ptr; *palette_ptr = (Bit8u*)malloc(256 * 4); if (palette_ptr == NULL) return 0; dst_ptr = *palette_ptr; for (i = 0; i < 256; i++) { *(dst_ptr++) = (BX_VGA_THIS s.pel.data[i].blue << shift); *(dst_ptr++) = (BX_VGA_THIS s.pel.data[i].green << shift); *(dst_ptr++) = (BX_VGA_THIS s.pel.data[i].red << shift); *(dst_ptr++) = 0; } return 1; } Bit32u bx_vgacore_c::get_gfx_snapshot(Bit8u **snapshot_ptr, Bit8u **palette_ptr, unsigned *iHeight, unsigned *iWidth, unsigned *iDepth) { Bit32u len; unsigned line_compare, start_addr, x, y; unsigned byte_offset, px, py; Bit8u *dst_ptr, *plane[4]; *iHeight = BX_VGA_THIS s.last_yres; *iWidth = BX_VGA_THIS s.last_xres; *iDepth = 8; len = (BX_VGA_THIS s.last_xres * BX_VGA_THIS s.last_yres); *snapshot_ptr = (Bit8u*)malloc(len); if (snapshot_ptr == NULL) return 0; dst_ptr = *snapshot_ptr; plane[0] = &BX_VGA_THIS s.memory[0 << BX_VGA_THIS s.plane_shift]; plane[1] = &BX_VGA_THIS s.memory[1 << BX_VGA_THIS s.plane_shift]; plane[2] = &BX_VGA_THIS s.memory[2 << BX_VGA_THIS s.plane_shift]; plane[3] = &BX_VGA_THIS s.memory[3 << BX_VGA_THIS s.plane_shift]; start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d]; line_compare = BX_VGA_THIS s.line_compare; if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1; if ((BX_VGA_THIS s.graphics_ctrl.shift_reg == 0) && (BX_VGA_THIS s.graphics_ctrl.memory_mapping != 3)) { for (y = 0; y < BX_VGA_THIS s.last_yres; y++) { for (x = 0; x < BX_VGA_THIS s.last_xres; x++) { *(dst_ptr++) = BX_VGA_THIS get_vga_pixel(x, y, start_addr, line_compare, 0, plane); } } BX_VGA_THIS get_dac_palette(palette_ptr, BX_VGA_THIS s.dac_shift); return len; } else if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) { for (y = 0; y < BX_VGA_THIS s.last_yres; y++) { for (x = 0; x < BX_VGA_THIS s.last_xres; x++) { px = x >> 1; py = y >> BX_VGA_THIS s.y_doublescan; byte_offset = start_addr + py * BX_VGA_THIS s.line_offset; if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) { // DW set: doubleword mode byte_offset += (px & ~0x03); } else if (BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) { // B/W set: byte mode, modeX byte_offset += (px >> 2); } else { byte_offset += (px >> 1) & ~0x01; } *(dst_ptr++) = plane[px % 4][byte_offset]; } } BX_VGA_THIS get_dac_palette(palette_ptr, 2); return len; } else { *iHeight = 0; *iWidth = 0; *iDepth = 0; return 0; } } #if BX_DEBUGGER void bx_vgacore_c::debug_dump(void) { dbg_printf("Standard VGA adapter\n\n"); dbg_printf("s.misc_output.color_emulation = %u\n", (unsigned) BX_VGA_THIS s.misc_output.color_emulation); dbg_printf("s.misc_output.enable_ram = %u\n", (unsigned) BX_VGA_THIS s.misc_output.enable_ram); dbg_printf("s.misc_output.clock_select = %u ", (unsigned) BX_VGA_THIS s.misc_output.clock_select); if (BX_VGA_THIS s.misc_output.clock_select == 0) dbg_printf("(25Mhz 640 horiz pixel clock)\n"); else dbg_printf("(28Mhz 720 horiz pixel clock)\n"); dbg_printf("s.misc_output.select_high_bank = %u\n", (unsigned) BX_VGA_THIS s.misc_output.select_high_bank); dbg_printf("s.misc_output.horiz_sync_pol = %u\n", (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol); dbg_printf("s.misc_output.vert_sync_pol = %u ", (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol); switch ((BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | BX_VGA_THIS s.misc_output.horiz_sync_pol) { case 1: dbg_printf("(400 lines)\n"); break; case 2: dbg_printf("(350 lines)\n"); break; case 3: dbg_printf("(480 lines)\n"); break; default: dbg_printf("(reserved)\n"); } dbg_printf("s.graphics_ctrl.odd_even = %u\n", (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even); dbg_printf("s.graphics_ctrl.chain_odd_even = %u\n", (unsigned) BX_VGA_THIS s.graphics_ctrl.chain_odd_even); dbg_printf("s.graphics_ctrl.shift_reg = %u\n", (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg); dbg_printf("s.graphics_ctrl.graphics_alpha = %u\n", (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha); dbg_printf("s.graphics_ctrl.memory_mapping = %u ", (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping); switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) { case 1: dbg_printf("(A0000-AFFFF)\n"); break; case 2: dbg_printf("(B0000-B7FFF)\n"); break; case 3: dbg_printf("(B8000-BFFFF)\n"); break; default: dbg_printf("(A0000-BFFFF)\n"); break; } dbg_printf("s.sequencer.extended_mem = %u\n", (unsigned) BX_VGA_THIS s.sequencer.extended_mem); dbg_printf("s.sequencer.odd_even = %u (inverted)\n", (unsigned) BX_VGA_THIS s.sequencer.odd_even); dbg_printf("s.sequencer.chain_four = %u\n", (unsigned) BX_VGA_THIS s.sequencer.chain_four); dbg_printf("s.attribute_ctrl.video_enabled = %u\n", (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled); dbg_printf("s.attribute_ctrl.mode_ctrl.graphics_alpha = %u\n", (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha); dbg_printf("s.attribute_ctrl.mode_ctrl.display_type = %u\n", (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type); dbg_printf("s.attribute_ctrl.mode_ctrl.internal_palette_size = %u\n", (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size); dbg_printf("s.attribute_ctrl.mode_ctrl.pixel_clock_select = %u\n", (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select); } #endif void bx_vgacore_c::redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height) { unsigned xti, yti, xt0, xt1, yt0, yt1, xmax, ymax; if (width == 0 || height == 0) { return; } BX_VGA_THIS s.vga_mem_updated = 1; if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) { // graphics mode xmax = BX_VGA_THIS s.last_xres; ymax = BX_VGA_THIS s.last_yres; xt0 = x0 / X_TILESIZE; yt0 = y0 / Y_TILESIZE; if (x0 < xmax) { xt1 = (x0 + width - 1) / X_TILESIZE; } else { xt1 = (xmax - 1) / X_TILESIZE; } if (y0 < ymax) { yt1 = (y0 + height - 1) / Y_TILESIZE; } else { yt1 = (ymax - 1) / Y_TILESIZE; } for (yti=yt0; yti<=yt1; yti++) { for (xti=xt0; xti<=xt1; xti++) { SET_TILE_UPDATED(xti, yti, 1); } } } else { // text mode memset(BX_VGA_THIS s.text_snapshot, 0, sizeof(BX_VGA_THIS s.text_snapshot)); } } bochs-2.6/iodev/keyboard.h0000644000175000017500000002026412020641505015413 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: keyboard.h 11224 2012-06-21 17:33:37Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef _PCKEY_H #define _PCKEY_H #define BX_KBD_ELEMENTS 16 // these keywords should only be used in keyboard.cc #if BX_USE_KEY_SMF # define BX_KEY_SMF static # define BX_KEY_THIS theKeyboard-> #else # define BX_KEY_SMF # define BX_KEY_THIS this-> #endif #define MOUSE_MODE_RESET 10 #define MOUSE_MODE_STREAM 11 #define MOUSE_MODE_REMOTE 12 #define MOUSE_MODE_WRAP 13 class bx_keyb_c : public bx_keyb_stub_c { public: bx_keyb_c(); virtual ~bx_keyb_c(); // implement bx_devmodel_c interface virtual void init(void); virtual void reset(unsigned type); // override stubs from bx_keyb_stub_c virtual void gen_scancode(Bit32u key); virtual void paste_bytes(Bit8u *data, Bit32s length); virtual void register_state(void); virtual void after_restore_state(void); // runtime options static Bit64s kbd_param_handler(bx_param_c *param, int set, Bit64s val); BX_KEY_SMF void paste_delay_changed(Bit32u value); private: BX_KEY_SMF Bit8u get_kbd_enable(void); BX_KEY_SMF void service_paste_buf (); BX_KEY_SMF void create_mouse_packet(bx_bool force_enq); BX_KEY_SMF unsigned periodic(Bit32u usec_delta); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_KEY_SMF void write(Bit32u address, Bit32u value, unsigned io_len); Bit32u read(Bit32u address, unsigned io_len); #endif struct { struct { /* status bits matching the status port*/ bx_bool pare; // Bit7, 1= parity error from keyboard/mouse - ignored. bx_bool tim; // Bit6, 1= timeout from keyboard - ignored. bx_bool auxb; // Bit5, 1= mouse data waiting for CPU to read. bx_bool keyl; // Bit4, 1= keyswitch in lock position - ignored. bx_bool c_d; /* Bit3, 1=command to port 64h, 0=data to port 60h */ bx_bool sysf; // Bit2, bx_bool inpb; // Bit1, bx_bool outb; // Bit0, 1= keyboard data or mouse data ready for CPU // check aux to see which. Or just keyboard // data before AT style machines /* internal to our version of the keyboard controller */ bx_bool kbd_clock_enabled; bx_bool aux_clock_enabled; bx_bool allow_irq1; bx_bool allow_irq12; Bit8u kbd_output_buffer; Bit8u aux_output_buffer; Bit8u last_comm; Bit8u expecting_port60h; Bit8u expecting_mouse_parameter; Bit8u last_mouse_command; Bit32u timer_pending; bx_bool irq1_requested; bx_bool irq12_requested; bx_bool scancodes_translate; bx_bool expecting_scancodes_set; Bit8u current_scancodes_set; bx_bool bat_in_progress; } kbd_controller; struct mouseStruct { Bit8u type; Bit8u sample_rate; Bit8u resolution_cpmm; // resolution in counts per mm Bit8u scaling; Bit8u mode; Bit8u saved_mode; // the mode prior to entering wrap mode bx_bool enable; Bit8u get_status_byte () { // top bit is 0 , bit 6 is 1 if remote mode. Bit8u ret = (Bit8u) ((mode == MOUSE_MODE_REMOTE) ? 0x40 : 0); ret |= (enable << 5); ret |= (scaling == 1) ? 0 : (1 << 4); ret |= ((button_status & 0x1) << 2); ret |= ((button_status & 0x2) << 0); return ret; } Bit8u get_resolution_byte () { Bit8u ret = 0; switch (resolution_cpmm) { case 1: ret = 0; break; case 2: ret = 1; break; case 4: ret = 2; break; case 8: ret = 3; break; default: genlog->panic("mouse: invalid resolution_cpmm"); }; return ret; } Bit8u button_status; Bit16s delayed_dx; Bit16s delayed_dy; Bit16s delayed_dz; Bit8u im_request; bx_bool im_mode; } mouse; struct { int num_elements; Bit8u buffer[BX_KBD_ELEMENTS]; int head; bx_bool expecting_typematic; bx_bool expecting_led_write; Bit8u delay; Bit8u repeat_rate; Bit8u led_status; bx_bool scanning_enabled; } kbd_internal_buffer; struct { int num_elements; Bit8u buffer[BX_MOUSE_BUFF_SIZE]; int head; } mouse_internal_buffer; #define BX_KBD_CONTROLLER_QSIZE 5 Bit8u controller_Q[BX_KBD_CONTROLLER_QSIZE]; unsigned controller_Qsize; unsigned controller_Qsource; // 0=keyboard, 1=mouse } s; // State information for saving/loading // The paste buffer does NOT exist in the hardware. It is a bochs // construction that allows the user to "paste" arbitrary length sequences of // keystrokes into the emulated machine. Since the hardware buffer is only // 16 bytes, a very small amount of data can be added to the hardware buffer // at a time. The paste buffer keeps track of the bytes that have not yet // been pasted. // // Lifetime of a paste buffer: The paste data comes from the system // clipboard, which must be accessed using platform independent code in the // gui. Because every gui has its own way of managing the clipboard memory // (in X windows, you're supposed to call Xfree for example), in the platform // specific code we make a copy of the clipboard buffer with // "new Bit8u[length]". Then the pointer is passed into // bx_keyb_c::paste_bytes, along with the length. The gui code never touches // the pastebuf again, and does not free it. The keyboard code is // responsible for deallocating the paste buffer using delete [] buf. The // paste buffer is binary data, and it is probably NOT null terminated. // // Summary: A paste buffer is allocated (new) in the platform-specific gui // code, passed to the keyboard model, and is freed (delete[]) when it is no // longer needed. Bit8u *pastebuf; // ptr to bytes to be pasted, or NULL if none in progress Bit32u pastebuf_len; // length of pastebuf Bit32u pastebuf_ptr; // ptr to next byte to be added to hw buffer Bit32u pastedelay; // count before paste bx_bool paste_service; // set to 1 when gen_scancode() is called from paste service bx_bool stop_paste; // stop the current paste operation on keypress or hardware reset BX_KEY_SMF void resetinternals(bx_bool powerup); BX_KEY_SMF void set_kbd_clock_enable(Bit8u value) BX_CPP_AttrRegparmN(1); BX_KEY_SMF void set_aux_clock_enable(Bit8u value); BX_KEY_SMF void kbd_ctrl_to_kbd(Bit8u value); BX_KEY_SMF void kbd_ctrl_to_mouse(Bit8u value); BX_KEY_SMF void kbd_enQ(Bit8u scancode); BX_KEY_SMF void kbd_enQ_imm(Bit8u val); BX_KEY_SMF void activate_timer(void); BX_KEY_SMF void controller_enQ(Bit8u data, unsigned source); BX_KEY_SMF bx_bool mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3, Bit8u b4); BX_KEY_SMF void mouse_enQ(Bit8u mouse_data); static void mouse_enabled_changed_static(void *dev, bx_bool enabled); void mouse_enabled_changed(bx_bool enabled); static void mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy); void mouse_motion(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy); static void timer_handler(void *); void timer(void); int timer_handle; int statusbar_id[3]; }; #endif // #ifndef _PCKEY_H bochs-2.6/iodev/acpi.h0000644000175000017500000000513212020641505014524 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: acpi.h 10419 2011-06-23 15:56:02Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2006 Volker Ruppert // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef BX_IODEV_ACPI_H #define BX_IODEV_ACPI_H #if BX_USE_ACPI_SMF # define BX_ACPI_SMF static # define BX_ACPI_THIS theACPIController-> # define BX_ACPI_THIS_PTR theACPIController #else # define BX_ACPI_SMF # define BX_ACPI_THIS this-> # define BX_ACPI_THIS_PTR this #endif class bx_acpi_ctrl_c : public bx_acpi_ctrl_stub_c { public: bx_acpi_ctrl_c(); virtual ~bx_acpi_ctrl_c(); virtual void init(void); virtual void reset(unsigned type); virtual void generate_smi(Bit8u value); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_ACPI_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif BX_ACPI_SMF void timer(void); private: BX_ACPI_SMF void set_irq_level(bx_bool level); BX_ACPI_SMF Bit32u get_pmtmr(void); BX_ACPI_SMF Bit16u get_pmsts(void); BX_ACPI_SMF void pm_update_sci(void); static void timer_handler(void *); struct { Bit8u devfunc; Bit32u pm_base; Bit32u sm_base; Bit16u pmsts; Bit16u pmen; Bit16u pmcntrl; Bit64u tmr_overflow_time; int timer_index; struct { Bit8u stat; Bit8u ctl; Bit8u cmd; Bit8u addr; Bit8u data0; Bit8u data1; Bit8u index; Bit8u data[32]; } smbus; } s; }; #endif bochs-2.6/iodev/keyboard.cc0000644000175000017500000016743312020641505015563 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: keyboard.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Now features proper implementation of keyboard opcodes 0xF4 to 0xF6 // Silently ignores PS/2 keyboard extensions (0xF7 to 0xFD) // Explicit panic on resend (0xFE) // // Emmanuel Marty // NB: now the PS/2 mouse support is in, outb changes meaning // in conjunction with auxb // auxb == 0 && outb == 0 => both buffers empty (nothing to read) // auxb == 0 && outb == 1 => keyboard controller output buffer full // auxb == 1 && outb == 0 => not used // auxb == 1 && outb == 1 => mouse output buffer full. // (das) // Notes from Christophe Bothamy // // This file includes code from Ludovic Lange (http://ludovic.lange.free.fr) // Implementation of 3 scancodes sets mf1,mf2,mf3 with or without translation. // Default is mf2 with translation // Ability to switch between scancodes sets // Ability to turn translation on or off // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "gui/keymap.h" #include #include "keyboard.h" #include "scancodes.h" #define LOG_THIS theKeyboard-> #define VERBOSE_KBD_DEBUG 0 bx_keyb_c *theKeyboard = NULL; int libkeyboard_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { // Create one instance of the keyboard device object. theKeyboard = new bx_keyb_c(); // Before this plugin was loaded, pluginKeyboard pointed to a stub. // Now make it point to the real thing. bx_devices.pluginKeyboard = theKeyboard; // Register this device. BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theKeyboard, BX_PLUGIN_KEYBOARD); return(0); // Success } void libkeyboard_LTX_plugin_fini(void) { delete theKeyboard; } bx_keyb_c::bx_keyb_c() { put("keyboard", "KBD"); memset(&s, 0, sizeof(s)); pastebuf = NULL; } bx_keyb_c::~bx_keyb_c() { // remove runtime parameter handlers SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set_handler(NULL); SIM->get_param_num(BXPN_MOUSE_ENABLED)->set_handler(NULL); if (pastebuf != NULL) { delete [] pastebuf; } SIM->get_bochs_root()->remove("keyboard"); BX_DEBUG(("Exit")); } // flush internal buffer and reset keyboard settings to power-up condition void bx_keyb_c::resetinternals(bx_bool powerup) { BX_KEY_THIS s.kbd_internal_buffer.num_elements = 0; for (int i=0; iget_param_num(BXPN_KBD_SERIAL_DELAY)->get(), 1, 1, "8042 Keyboard controller"); resetinternals(1); BX_KEY_THIS s.kbd_internal_buffer.led_status = 0; BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1; BX_KEY_THIS s.mouse_internal_buffer.num_elements = 0; for (i=0; iget_param_enum(BXPN_MOUSE_TYPE)->get(); BX_KEY_THIS s.mouse.sample_rate = 100; // reports per second BX_KEY_THIS s.mouse.resolution_cpmm = 4; // 4 counts per millimeter BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */ BX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET; BX_KEY_THIS s.mouse.enable = 0; BX_KEY_THIS s.mouse.delayed_dx = 0; BX_KEY_THIS s.mouse.delayed_dy = 0; BX_KEY_THIS s.mouse.delayed_dz = 0; BX_KEY_THIS s.mouse.im_request = 0; // wheel mouse mode request BX_KEY_THIS s.mouse.im_mode = 0; // wheel mouse mode for (i=0; iget_param_num(BXPN_KBD_PASTE_DELAY)->get()); BX_KEY_THIS paste_service = 0; BX_KEY_THIS stop_paste = 0; // mouse port installed on system board DEV_cmos_set_reg(0x14, DEV_cmos_get_reg(0x14) | 0x04); // add keyboard LEDs to the statusbar BX_KEY_THIS statusbar_id[0] = bx_gui->register_statusitem("NUM"); BX_KEY_THIS statusbar_id[1] = bx_gui->register_statusitem("CAPS"); BX_KEY_THIS statusbar_id[2] = bx_gui->register_statusitem("SCRL"); if ((BX_KEY_THIS s.mouse.type == BX_MOUSE_TYPE_PS2) || (BX_KEY_THIS s.mouse.type == BX_MOUSE_TYPE_IMPS2)) { DEV_register_default_mouse(this, mouse_enq_static, mouse_enabled_changed_static); } // init runtime parameter SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set_handler(kbd_param_handler); SIM->get_param_num(BXPN_KBD_PASTE_DELAY)->set_runtime_param(1); SIM->get_param_num(BXPN_MOUSE_ENABLED)->set_handler(kbd_param_handler); SIM->get_param_num(BXPN_MOUSE_ENABLED)->set_runtime_param(1); } void bx_keyb_c::reset(unsigned type) { if (BX_KEY_THIS pastebuf != NULL) { BX_KEY_THIS stop_paste = 1; } } void bx_keyb_c::register_state(void) { int i; char name[4]; bx_list_c *buffer; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "keyboard", "Keyboard State"); bx_list_c *ctrl = new bx_list_c(list, "controller"); BXRS_PARAM_BOOL(ctrl, tim, BX_KEY_THIS s.kbd_controller.tim); BXRS_PARAM_BOOL(ctrl, auxb, BX_KEY_THIS s.kbd_controller.auxb); BXRS_PARAM_BOOL(ctrl, c_d, BX_KEY_THIS s.kbd_controller.c_d); BXRS_PARAM_BOOL(ctrl, sysf, BX_KEY_THIS s.kbd_controller.sysf); BXRS_PARAM_BOOL(ctrl, inpb, BX_KEY_THIS s.kbd_controller.inpb); BXRS_PARAM_BOOL(ctrl, outb, BX_KEY_THIS s.kbd_controller.outb); BXRS_PARAM_BOOL(ctrl, kbd_clock_enabled, BX_KEY_THIS s.kbd_controller.kbd_clock_enabled); BXRS_PARAM_BOOL(ctrl, aux_clock_enabled, BX_KEY_THIS s.kbd_controller.aux_clock_enabled); BXRS_PARAM_BOOL(ctrl, allow_irq1, BX_KEY_THIS s.kbd_controller.allow_irq1); BXRS_PARAM_BOOL(ctrl, allow_irq12, BX_KEY_THIS s.kbd_controller.allow_irq12); BXRS_HEX_PARAM_FIELD(ctrl, kbd_output_buffer, BX_KEY_THIS s.kbd_controller.kbd_output_buffer); BXRS_HEX_PARAM_FIELD(ctrl, aux_output_buffer, BX_KEY_THIS s.kbd_controller.aux_output_buffer); BXRS_HEX_PARAM_FIELD(ctrl, last_comm, BX_KEY_THIS s.kbd_controller.last_comm); BXRS_DEC_PARAM_FIELD(ctrl, expecting_port60h, BX_KEY_THIS s.kbd_controller.expecting_port60h); BXRS_DEC_PARAM_FIELD(ctrl, expecting_mouse_parameter, BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter); BXRS_HEX_PARAM_FIELD(ctrl, last_mouse_command, BX_KEY_THIS s.kbd_controller.last_mouse_command); BXRS_DEC_PARAM_FIELD(ctrl, timer_pending, BX_KEY_THIS s.kbd_controller.timer_pending); BXRS_PARAM_BOOL(ctrl, irq1_requested, BX_KEY_THIS s.kbd_controller.irq1_requested); BXRS_PARAM_BOOL(ctrl, irq12_requested, BX_KEY_THIS s.kbd_controller.irq12_requested); BXRS_PARAM_BOOL(ctrl, scancodes_translate, BX_KEY_THIS s.kbd_controller.scancodes_translate); BXRS_PARAM_BOOL(ctrl, expecting_scancodes_set, BX_KEY_THIS s.kbd_controller.expecting_scancodes_set); BXRS_DEC_PARAM_FIELD(ctrl, current_scancodes_set, BX_KEY_THIS s.kbd_controller.current_scancodes_set); BXRS_PARAM_BOOL(ctrl, bat_in_progress, BX_KEY_THIS s.kbd_controller.bat_in_progress); bx_list_c *mouse = new bx_list_c(list, "mouse"); BXRS_DEC_PARAM_FIELD(mouse, sample_rate, BX_KEY_THIS s.mouse.sample_rate); BXRS_DEC_PARAM_FIELD(mouse, resolution_cpmm, BX_KEY_THIS s.mouse.resolution_cpmm); BXRS_DEC_PARAM_FIELD(mouse, scaling, BX_KEY_THIS s.mouse.scaling); BXRS_DEC_PARAM_FIELD(mouse, mode, BX_KEY_THIS s.mouse.mode); BXRS_DEC_PARAM_FIELD(mouse, saved_mode, BX_KEY_THIS s.mouse.saved_mode); BXRS_PARAM_BOOL(mouse, enable, BX_KEY_THIS s.mouse.enable); BXRS_DEC_PARAM_FIELD(mouse, button_status, BX_KEY_THIS s.mouse.button_status); BXRS_DEC_PARAM_FIELD(mouse, delayed_dx, BX_KEY_THIS s.mouse.delayed_dx); BXRS_DEC_PARAM_FIELD(mouse, delayed_dy, BX_KEY_THIS s.mouse.delayed_dy); BXRS_DEC_PARAM_FIELD(mouse, delayed_dz, BX_KEY_THIS s.mouse.delayed_dz); BXRS_DEC_PARAM_FIELD(mouse, im_request, BX_KEY_THIS s.mouse.im_request); BXRS_PARAM_BOOL(mouse, im_mode, BX_KEY_THIS s.mouse.im_mode); bx_list_c *kbdbuf = new bx_list_c(list, "kbd_internal_buffer"); BXRS_DEC_PARAM_FIELD(kbdbuf, num_elements, BX_KEY_THIS s.kbd_internal_buffer.num_elements); buffer = new bx_list_c(kbdbuf, "buffer"); for (i=0; istatusbar_setitem(BX_KEY_THIS statusbar_id[0], value & 0x02); bx_gui->statusbar_setitem(BX_KEY_THIS statusbar_id[1], value & 0x04); bx_gui->statusbar_setitem(BX_KEY_THIS statusbar_id[2], value & 0x01); } } Bit64s bx_keyb_c::kbd_param_handler(bx_param_c *param, int set, Bit64s val) { if (set) { char pname[BX_PATHNAME_LEN]; param->get_param_path(pname, BX_PATHNAME_LEN); if (!strcmp(pname, BXPN_KBD_PASTE_DELAY)) { BX_KEY_THIS paste_delay_changed((Bit32u)val); } else if (!strcmp(pname, BXPN_MOUSE_ENABLED)) { if (set) { bx_gui->mouse_enabled_changed(val!=0); DEV_mouse_enabled_changed(val!=0); } } else { BX_PANIC(("kbd_param_handler called with unexpected parameter '%s'", pname)); } } return val; } void bx_keyb_c::paste_delay_changed(Bit32u value) { BX_KEY_THIS pastedelay = value / BX_IODEV_HANDLER_PERIOD; BX_INFO(("will paste characters every %d keyboard ticks",BX_KEY_THIS pastedelay)); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions // read function - the big picture: // if address == data port then // if byte for mouse then return it // else if byte for keyboard then return it // else address== status port // assemble the status bits and return them. // Bit32u bx_keyb_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_KEY_SMF bx_keyb_c *class_ptr = (bx_keyb_c *)this_ptr; return (class_ptr->read(address, io_len)); } Bit32u bx_keyb_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_KEY_SMF Bit8u val; if (address == 0x60) { /* output buffer */ if (BX_KEY_THIS s.kbd_controller.auxb) { /* mouse byte available */ val = BX_KEY_THIS s.kbd_controller.aux_output_buffer; BX_KEY_THIS s.kbd_controller.aux_output_buffer = 0; BX_KEY_THIS s.kbd_controller.outb = 0; BX_KEY_THIS s.kbd_controller.auxb = 0; BX_KEY_THIS s.kbd_controller.irq12_requested = 0; if (BX_KEY_THIS s.controller_Qsize) { unsigned i; BX_KEY_THIS s.kbd_controller.aux_output_buffer = BX_KEY_THIS s.controller_Q[0]; BX_KEY_THIS s.kbd_controller.outb = 1; BX_KEY_THIS s.kbd_controller.auxb = 1; if (BX_KEY_THIS s.kbd_controller.allow_irq12) BX_KEY_THIS s.kbd_controller.irq12_requested = 1; for (i=0; i= 2 else if (address == 0x64) { /* status register */ val = (BX_KEY_THIS s.kbd_controller.pare << 7) | (BX_KEY_THIS s.kbd_controller.tim << 6) | (BX_KEY_THIS s.kbd_controller.auxb << 5) | (BX_KEY_THIS s.kbd_controller.keyl << 4) | (BX_KEY_THIS s.kbd_controller.c_d << 3) | (BX_KEY_THIS s.kbd_controller.sysf << 2) | (BX_KEY_THIS s.kbd_controller.inpb << 1) | BX_KEY_THIS s.kbd_controller.outb; BX_KEY_THIS s.kbd_controller.tim = 0; return val; } #else /* BX_CPU_LEVEL > 0 */ /* XT MODE, System 8255 Mode Register */ else if (address == 0x64) { /* status register */ BX_DEBUG(("IO read from port 64h, system 8255 mode register")); return BX_KEY_THIS s.kbd_controller.outb; } #endif /* BX_CPU_LEVEL > 0 */ BX_PANIC(("unknown address in io read to keyboard port %x", (unsigned) address)); return 0; /* keep compiler happy */ } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_keyb_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_KEY_SMF bx_keyb_c *class_ptr = (bx_keyb_c *)this_ptr; class_ptr->write(address, value, io_len); } void bx_keyb_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_KEY_SMF Bit8u command_byte; static int kbd_initialized=0; BX_DEBUG(("keyboard: 8-bit write to %04x = %02x", (unsigned)address, (unsigned)value)); switch (address) { case 0x60: // input buffer // if expecting data byte from command last sent to port 64h if (BX_KEY_THIS s.kbd_controller.expecting_port60h) { BX_KEY_THIS s.kbd_controller.expecting_port60h = 0; // data byte written last to 0x60 BX_KEY_THIS s.kbd_controller.c_d = 0; if (BX_KEY_THIS s.kbd_controller.inpb) { BX_PANIC(("write to port 60h, not ready for write")); } switch (BX_KEY_THIS s.kbd_controller.last_comm) { case 0x60: // write command byte { bx_bool scan_convert, disable_keyboard, disable_aux; scan_convert = (value >> 6) & 0x01; disable_aux = (value >> 5) & 0x01; disable_keyboard = (value >> 4) & 0x01; BX_KEY_THIS s.kbd_controller.sysf = (value >> 2) & 0x01; BX_KEY_THIS s.kbd_controller.allow_irq1 = (value >> 0) & 0x01; BX_KEY_THIS s.kbd_controller.allow_irq12 = (value >> 1) & 0x01; set_kbd_clock_enable(!disable_keyboard); set_aux_clock_enable(!disable_aux); if (BX_KEY_THIS s.kbd_controller.allow_irq12 && BX_KEY_THIS s.kbd_controller.auxb) BX_KEY_THIS s.kbd_controller.irq12_requested = 1; else if (BX_KEY_THIS s.kbd_controller.allow_irq1 && BX_KEY_THIS s.kbd_controller.outb) BX_KEY_THIS s.kbd_controller.irq1_requested = 1; BX_DEBUG((" allow_irq12 set to %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12)); if (!scan_convert) BX_INFO(("keyboard: scan convert turned off")); // (mch) NT needs this BX_KEY_THIS s.kbd_controller.scancodes_translate = scan_convert; } break; case 0xcb: // write keyboard controller mode BX_DEBUG(("write keyboard controller mode with value %02xh", (unsigned) value)); break; case 0xd1: // write output port BX_DEBUG(("write output port with value %02xh", (unsigned) value)); BX_DEBUG(("write output port : %sable A20",(value & 0x02)?"en":"dis")); BX_SET_ENABLE_A20((value & 0x02) != 0); if (!(value & 0x01)) { BX_INFO(("write output port : processor reset requested!")); bx_pc_system.Reset(BX_RESET_SOFTWARE); } break; case 0xd4: // Write to mouse // I don't think this enables the AUX clock //set_aux_clock_enable(1); // enable aux clock line kbd_ctrl_to_mouse(value); // ??? should I reset to previous value of aux enable? break; case 0xd3: // write mouse output buffer // Queue in mouse output buffer controller_enQ(value, 1); break; case 0xd2: // Queue in keyboard output buffer controller_enQ(value, 0); break; default: BX_PANIC(("=== unsupported write to port 60h(lastcomm=%02x): %02x", (unsigned) BX_KEY_THIS s.kbd_controller.last_comm, (unsigned) value)); } } else { // data byte written last to 0x60 BX_KEY_THIS s.kbd_controller.c_d = 0; BX_KEY_THIS s.kbd_controller.expecting_port60h = 0; /* pass byte to keyboard */ /* ??? should conditionally pass to mouse device here ??? */ if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0) { set_kbd_clock_enable(1); } kbd_ctrl_to_kbd(value); } break; case 0x64: // control register // command byte written last to 0x64 BX_KEY_THIS s.kbd_controller.c_d = 1; BX_KEY_THIS s.kbd_controller.last_comm = value; // most commands NOT expecting port60 write next BX_KEY_THIS s.kbd_controller.expecting_port60h = 0; switch (value) { case 0x20: // get keyboard command byte BX_DEBUG(("get keyboard command byte")); // controller output buffer must be empty if (BX_KEY_THIS s.kbd_controller.outb) { BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value)); break; } command_byte = (BX_KEY_THIS s.kbd_controller.scancodes_translate << 6) | ((!BX_KEY_THIS s.kbd_controller.aux_clock_enabled) << 5) | ((!BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) << 4) | (0 << 3) | (BX_KEY_THIS s.kbd_controller.sysf << 2) | (BX_KEY_THIS s.kbd_controller.allow_irq12 << 1) | (BX_KEY_THIS s.kbd_controller.allow_irq1 << 0); controller_enQ(command_byte, 0); break; case 0x60: // write command byte BX_DEBUG(("write command byte")); // following byte written to port 60h is command byte BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; break; case 0xa0: BX_DEBUG(("keyboard BIOS name not supported")); break; case 0xa1: BX_DEBUG(("keyboard BIOS version not supported")); break; case 0xa7: // disable the aux device set_aux_clock_enable(0); BX_DEBUG(("aux device disabled")); break; case 0xa8: // enable the aux device set_aux_clock_enable(1); BX_DEBUG(("aux device enabled")); break; case 0xa9: // Test Mouse Port // controller output buffer must be empty if (BX_KEY_THIS s.kbd_controller.outb) { BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); break; } controller_enQ(0x00, 0); // no errors detected break; case 0xaa: // motherboard controller self test BX_DEBUG(("Self Test")); if (kbd_initialized == 0) { BX_KEY_THIS s.controller_Qsize = 0; BX_KEY_THIS s.kbd_controller.outb = 0; kbd_initialized++; } // controller output buffer must be empty if (BX_KEY_THIS s.kbd_controller.outb) { BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value)); break; } // (mch) Why is this commented out??? Enabling BX_KEY_THIS s.kbd_controller.sysf = 1; // self test complete controller_enQ(0x55, 0); // controller OK break; case 0xab: // Interface Test // controller output buffer must be empty if (BX_KEY_THIS s.kbd_controller.outb) { BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); break; } controller_enQ(0x00, 0); break; case 0xad: // disable keyboard set_kbd_clock_enable(0); BX_DEBUG(("keyboard disabled")); break; case 0xae: // enable keyboard set_kbd_clock_enable(1); BX_DEBUG(("keyboard enabled")); break; case 0xaf: // get controller version BX_INFO(("'get controller version' not supported yet")); break; case 0xc0: // read input port // controller output buffer must be empty if (BX_KEY_THIS s.kbd_controller.outb) { BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); break; } // keyboard not inhibited controller_enQ(0x80, 0); break; case 0xca: // read keyboard controller mode controller_enQ(0x01, 0); // PS/2 (MCA)interface break; case 0xcb: // write keyboard controller mode BX_DEBUG(("write keyboard controller mode")); // write keyboard controller mode to bit 0 of port 0x60 BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; break; case 0xd0: // read output port: next byte read from port 60h BX_DEBUG(("io write to port 64h, command d0h (partial)")); // controller output buffer must be empty if (BX_KEY_THIS s.kbd_controller.outb) { BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value)); break; } controller_enQ( (BX_KEY_THIS s.kbd_controller.irq12_requested << 5) | (BX_KEY_THIS s.kbd_controller.irq1_requested << 4) | (BX_GET_ENABLE_A20() << 1) | 0x01, 0); break; case 0xd1: // write output port: next byte written to port 60h BX_DEBUG(("write output port")); // following byte to port 60h written to output port BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; break; case 0xd3: // write mouse output buffer //FIXME: Why was this a panic? BX_DEBUG(("io write 0x64: command = 0xD3(write mouse outb)")); // following byte to port 60h written to output port as mouse write. BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; break; case 0xd4: // write to mouse BX_DEBUG(("io write 0x64: command = 0xD4 (write to mouse)")); // following byte written to port 60h BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; break; case 0xd2: // write keyboard output buffer BX_DEBUG(("io write 0x64: write keyboard output buffer")); BX_KEY_THIS s.kbd_controller.expecting_port60h = 1; break; case 0xdd: // Disable A20 Address Line BX_SET_ENABLE_A20(0); break; case 0xdf: // Enable A20 Address Line BX_SET_ENABLE_A20(1); break; case 0xc1: // Continuous Input Port Poll, Low case 0xc2: // Continuous Input Port Poll, High case 0xe0: // Read Test Inputs BX_PANIC(("io write 0x64: command = %02xh", (unsigned) value)); break; case 0xfe: // System (cpu?) Reset, transition to real mode BX_INFO(("io write 0x64: command 0xfe: reset cpu")); bx_pc_system.Reset(BX_RESET_SOFTWARE); break; default: if (value==0xff || (value>=0xf0 && value<=0xfd)) { /* useless pulse output bit commands ??? */ BX_DEBUG(("io write to port 64h, useless command %02x", (unsigned) value)); return; } BX_ERROR(("unsupported io write to keyboard port %x, value = %x", (unsigned) address, (unsigned) value)); break; } break; default: BX_PANIC(("unknown address in bx_keyb_c::write()")); } } // service_paste_buf() transfers data from the paste buffer to the hardware // keyboard buffer. It tries to transfer as many chars as possible at a // time, but because different chars require different numbers of scancodes // we have to be conservative. Note that this process depends on the // keymap tables to know what chars correspond to what keys, and which // chars require a shift or other modifier. void bx_keyb_c::service_paste_buf() { if (!BX_KEY_THIS pastebuf) return; BX_DEBUG(("service_paste_buf: ptr at %d out of %d", BX_KEY_THIS pastebuf_ptr, BX_KEY_THIS pastebuf_len)); int fill_threshold = BX_KBD_ELEMENTS - 8; BX_KEY_THIS paste_service = 1; while ((BX_KEY_THIS pastebuf_ptr < BX_KEY_THIS pastebuf_len) && !BX_KEY_THIS stop_paste) { if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= fill_threshold) { BX_KEY_THIS paste_service = 0; return; } // there room in the buffer for a keypress and a key release. // send one keypress and a key release. Bit8u byte = BX_KEY_THIS pastebuf[BX_KEY_THIS pastebuf_ptr]; BXKeyEntry *entry = bx_keymap.findAsciiChar(byte); if (!entry) { BX_ERROR(("paste character 0x%02x ignored", byte)); } else { BX_DEBUG(("pasting character 0x%02x. baseKey is %04x", byte, entry->baseKey)); if (entry->modKey != BX_KEYMAP_UNKNOWN) BX_KEY_THIS gen_scancode(entry->modKey); BX_KEY_THIS gen_scancode(entry->baseKey); BX_KEY_THIS gen_scancode(entry->baseKey | BX_KEY_RELEASED); if (entry->modKey != BX_KEYMAP_UNKNOWN) BX_KEY_THIS gen_scancode(entry->modKey | BX_KEY_RELEASED); } BX_KEY_THIS pastebuf_ptr++; } // reached end of pastebuf. free the memory it was using. delete [] BX_KEY_THIS pastebuf; BX_KEY_THIS pastebuf = NULL; BX_KEY_THIS stop_paste = 0; BX_KEY_THIS paste_service = 0; } // paste_bytes schedules an arbitrary number of ASCII characters to be // inserted into the hardware queue as it become available. Any previous // paste which is still in progress will be thrown out. BYTES is a pointer // to a region of memory containing the chars to be pasted. When the paste // is complete, the keyboard code will call delete [] bytes; void bx_keyb_c::paste_bytes(Bit8u *bytes, Bit32s length) { BX_DEBUG(("paste_bytes: %d bytes", length)); if (BX_KEY_THIS pastebuf) { BX_ERROR(("previous paste was not completed! %d chars lost", BX_KEY_THIS pastebuf_len - BX_KEY_THIS pastebuf_ptr)); delete [] BX_KEY_THIS pastebuf; // free the old paste buffer } BX_KEY_THIS pastebuf = bytes; BX_KEY_THIS pastebuf_ptr = 0; BX_KEY_THIS pastebuf_len = length; BX_KEY_THIS service_paste_buf(); } void bx_keyb_c::gen_scancode(Bit32u key) { unsigned char *scancode; Bit8u i; if ((BX_KEY_THIS pastebuf != NULL) && (!BX_KEY_THIS paste_service)) { BX_KEY_THIS stop_paste = 1; return; } BX_DEBUG(("gen_scancode(): %s %s", bx_keymap.getBXKeyName(key), (key >> 31)?"released":"pressed")); if (!BX_KEY_THIS s.kbd_controller.scancodes_translate) BX_DEBUG(("keyboard: gen_scancode with scancode_translate cleared")); // Ignore scancode if keyboard clock is driven low if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0) return; // Ignore scancode if scanning is disabled if (BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled==0) return; // Switch between make and break code if (key & BX_KEY_RELEASED) scancode=(unsigned char *)scancodes[(key&0xFF)][BX_KEY_THIS s.kbd_controller.current_scancodes_set].brek; else scancode=(unsigned char *)scancodes[(key&0xFF)][BX_KEY_THIS s.kbd_controller.current_scancodes_set].make; // if we have a removable keyboard installed, we need to call its handler first if (DEV_optional_key_enq(scancode)) { return; } if (BX_KEY_THIS s.kbd_controller.scancodes_translate) { // Translate before send Bit8u escaped=0x00; for (i=0; i= BX_KBD_CONTROLLER_QSIZE) BX_PANIC(("controller_enq(): controller_Q full!")); BX_KEY_THIS s.controller_Q[BX_KEY_THIS s.controller_Qsize++] = data; BX_KEY_THIS s.controller_Qsource = source; return; } // the Q is empty if (source == 0) { // keyboard BX_KEY_THIS s.kbd_controller.kbd_output_buffer = data; BX_KEY_THIS s.kbd_controller.outb = 1; BX_KEY_THIS s.kbd_controller.auxb = 0; BX_KEY_THIS s.kbd_controller.inpb = 0; if (BX_KEY_THIS s.kbd_controller.allow_irq1) BX_KEY_THIS s.kbd_controller.irq1_requested = 1; } else { // mouse BX_KEY_THIS s.kbd_controller.aux_output_buffer = data; BX_KEY_THIS s.kbd_controller.outb = 1; BX_KEY_THIS s.kbd_controller.auxb = 1; BX_KEY_THIS s.kbd_controller.inpb = 0; if (BX_KEY_THIS s.kbd_controller.allow_irq12) BX_KEY_THIS s.kbd_controller.irq12_requested = 1; } } void bx_keyb_c::kbd_enQ_imm(Bit8u val) { if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) { BX_PANIC(("internal keyboard buffer full (imm)")); return; } /* enqueue scancode in multibyte internal keyboard buffer */ /* int tail = (BX_KEY_THIS s.kbd_internal_buffer.head + BX_KEY_THIS s.kbd_internal_buffer.num_elements) % BX_KBD_ELEMENTS; */ BX_KEY_THIS s.kbd_controller.kbd_output_buffer = val; BX_KEY_THIS s.kbd_controller.outb = 1; if (BX_KEY_THIS s.kbd_controller.allow_irq1) BX_KEY_THIS s.kbd_controller.irq1_requested = 1; } void bx_keyb_c::kbd_enQ(Bit8u scancode) { int tail; BX_DEBUG(("kbd_enQ(0x%02x)", (unsigned) scancode)); if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) { BX_INFO(("internal keyboard buffer full, ignoring scancode.(%02x)", (unsigned) scancode)); return; } /* enqueue scancode in multibyte internal keyboard buffer */ BX_DEBUG(("kbd_enQ: putting scancode 0x%02x in internal buffer", (unsigned) scancode)); tail = (BX_KEY_THIS s.kbd_internal_buffer.head + BX_KEY_THIS s.kbd_internal_buffer.num_elements) % BX_KBD_ELEMENTS; BX_KEY_THIS s.kbd_internal_buffer.buffer[tail] = scancode; BX_KEY_THIS s.kbd_internal_buffer.num_elements++; if (!BX_KEY_THIS s.kbd_controller.outb && BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) { activate_timer(); BX_DEBUG(("activating timer...")); return; } } bx_bool bx_keyb_c::mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3, Bit8u b4) { int bytes = 3; if (BX_KEY_THIS s.mouse.im_mode) bytes = 4; if ((BX_KEY_THIS s.mouse_internal_buffer.num_elements + bytes) >= BX_MOUSE_BUFF_SIZE) { return(0); /* buffer doesn't have the space */ } mouse_enQ(b1); mouse_enQ(b2); mouse_enQ(b3); if (BX_KEY_THIS s.mouse.im_mode) mouse_enQ(b4); return(1); } void bx_keyb_c::mouse_enQ(Bit8u mouse_data) { int tail; BX_DEBUG(("mouse_enQ(%02x)", (unsigned) mouse_data)); if (BX_KEY_THIS s.mouse_internal_buffer.num_elements >= BX_MOUSE_BUFF_SIZE) { BX_ERROR(("[mouse] internal mouse buffer full, ignoring mouse data.(%02x)", (unsigned) mouse_data)); return; } /* enqueue mouse data in multibyte internal mouse buffer */ tail = (BX_KEY_THIS s.mouse_internal_buffer.head + BX_KEY_THIS s.mouse_internal_buffer.num_elements) % BX_MOUSE_BUFF_SIZE; BX_KEY_THIS s.mouse_internal_buffer.buffer[tail] = mouse_data; BX_KEY_THIS s.mouse_internal_buffer.num_elements++; if (!BX_KEY_THIS s.kbd_controller.outb && BX_KEY_THIS s.kbd_controller.aux_clock_enabled) { activate_timer(); return; } } void bx_keyb_c::kbd_ctrl_to_kbd(Bit8u value) { BX_DEBUG(("controller passed byte %02xh to keyboard", value)); if (BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic) { BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 0; BX_KEY_THIS s.kbd_internal_buffer.delay = (value >> 5) & 0x03; switch (BX_KEY_THIS s.kbd_internal_buffer.delay) { case 0: BX_INFO(("setting delay to 250 mS (unused)")); break; case 1: BX_INFO(("setting delay to 500 mS (unused)")); break; case 2: BX_INFO(("setting delay to 750 mS (unused)")); break; case 3: BX_INFO(("setting delay to 1000 mS (unused)")); break; } BX_KEY_THIS s.kbd_internal_buffer.repeat_rate = value & 0x1f; double cps = 1 /((double)(8 + (value & 0x07)) * (double)exp(log((double)2) * (double)((value >> 3) & 0x03)) * 0.00417); BX_INFO(("setting repeat rate to %.1f cps (unused)", cps)); kbd_enQ(0xFA); // send ACK return; } if (BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write) { BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 0; BX_KEY_THIS s.kbd_internal_buffer.led_status = value; BX_DEBUG(("LED status set to %02x", (unsigned) BX_KEY_THIS s.kbd_internal_buffer.led_status)); bx_gui->statusbar_setitem(BX_KEY_THIS statusbar_id[0], value & 0x02); bx_gui->statusbar_setitem(BX_KEY_THIS statusbar_id[1], value & 0x04); bx_gui->statusbar_setitem(BX_KEY_THIS statusbar_id[2], value & 0x01); kbd_enQ(0xFA); // send ACK %%% return; } if (BX_KEY_THIS s.kbd_controller.expecting_scancodes_set) { BX_KEY_THIS s.kbd_controller.expecting_scancodes_set = 0; if(value != 0) { if(value < 4) { BX_KEY_THIS s.kbd_controller.current_scancodes_set = (value-1); BX_INFO(("Switched to scancode set %d", (unsigned) BX_KEY_THIS s.kbd_controller.current_scancodes_set + 1)); kbd_enQ(0xFA); } else { BX_ERROR(("Received scancodes set out of range: %d", value)); kbd_enQ(0xFF); // send ERROR } } else { // Send ACK (SF patch #1159626) kbd_enQ(0xFA); // Send current scancodes set to port 0x60 kbd_enQ(1 + (BX_KEY_THIS s.kbd_controller.current_scancodes_set)); } return; } switch (value) { case 0x00: // ??? ignore and let OS timeout with no response kbd_enQ(0xFA); // send ACK %%% break; case 0x05: // ??? // (mch) trying to get this to work... BX_KEY_THIS s.kbd_controller.sysf = 1; kbd_enQ_imm(0xfe); break; case 0xed: // LED Write BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 1; kbd_enQ_imm(0xFA); // send ACK %%% break; case 0xee: // echo kbd_enQ(0xEE); // return same byte (EEh) as echo diagnostic break; case 0xf0: // Select alternate scan code set BX_KEY_THIS s.kbd_controller.expecting_scancodes_set = 1; BX_DEBUG(("Expecting scancode set info...")); kbd_enQ(0xFA); // send ACK break; case 0xf2: // identify keyboard BX_INFO(("identify keyboard command received")); // XT sends nothing, AT sends ACK // MFII with translation sends ACK+ABh+41h // MFII without translation sends ACK+ABh+83h if (SIM->get_param_enum(BXPN_KBD_TYPE)->get() != BX_KBD_XT_TYPE) { kbd_enQ(0xFA); if (SIM->get_param_enum(BXPN_KBD_TYPE)->get() == BX_KBD_MF_TYPE) { kbd_enQ(0xAB); if(BX_KEY_THIS s.kbd_controller.scancodes_translate) kbd_enQ(0x41); else kbd_enQ(0x83); } } break; case 0xf3: // typematic info BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 1; BX_INFO(("setting typematic info")); kbd_enQ(0xFA); // send ACK break; case 0xf4: // enable keyboard BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1; kbd_enQ(0xFA); // send ACK break; case 0xf5: // reset keyboard to power-up settings and disable scanning resetinternals(1); kbd_enQ(0xFA); // send ACK BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 0; BX_INFO(("reset-disable command received")); break; case 0xf6: // reset keyboard to power-up settings and enable scanning resetinternals(1); kbd_enQ(0xFA); // send ACK BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1; BX_INFO(("reset-enable command received")); break; case 0xfe: // resend. aiiee. BX_PANIC(("got 0xFE (resend)")); break; case 0xff: // reset: internal keyboard reset and afterwards the BAT BX_DEBUG(("reset command received")); resetinternals(1); kbd_enQ(0xFA); // send ACK BX_KEY_THIS s.kbd_controller.bat_in_progress = 1; kbd_enQ(0xAA); // BAT test passed break; case 0xd3: kbd_enQ(0xfa); break; case 0xf7: // PS/2 Set All Keys To Typematic case 0xf8: // PS/2 Set All Keys to Make/Break case 0xf9: // PS/2 PS/2 Set All Keys to Make case 0xfa: // PS/2 Set All Keys to Typematic Make/Break case 0xfb: // PS/2 Set Key Type to Typematic case 0xfc: // PS/2 Set Key Type to Make/Break case 0xfd: // PS/2 Set Key Type to Make default: BX_ERROR(("kbd_ctrl_to_kbd(): got value of 0x%02x", value)); kbd_enQ(0xFE); /* send NACK */ break; } } void bx_keyb_c::timer_handler(void *this_ptr) { bx_keyb_c *class_ptr = (bx_keyb_c *)this_ptr; unsigned retval; retval=class_ptr->periodic(1); if(retval&0x01) DEV_pic_raise_irq(1); if(retval&0x02) DEV_pic_raise_irq(12); } unsigned bx_keyb_c::periodic(Bit32u usec_delta) { /* static int multiple=0; */ static unsigned count_before_paste=0; Bit8u retval; UNUSED(usec_delta); if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) { if(++count_before_paste>=BX_KEY_THIS pastedelay) { // after the paste delay, consider adding moving more chars // from the paste buffer to the keyboard buffer. BX_KEY_THIS service_paste_buf(); count_before_paste=0; } } retval = BX_KEY_THIS s.kbd_controller.irq1_requested | (BX_KEY_THIS s.kbd_controller.irq12_requested << 1); BX_KEY_THIS s.kbd_controller.irq1_requested = 0; BX_KEY_THIS s.kbd_controller.irq12_requested = 0; if (BX_KEY_THIS s.kbd_controller.timer_pending == 0) { return(retval); } if (usec_delta >= BX_KEY_THIS s.kbd_controller.timer_pending) { BX_KEY_THIS s.kbd_controller.timer_pending = 0; } else { BX_KEY_THIS s.kbd_controller.timer_pending -= usec_delta; return(retval); } if (BX_KEY_THIS s.kbd_controller.outb) { return(retval); } /* nothing in outb, look for possible data xfer from keyboard or mouse */ if (BX_KEY_THIS s.kbd_internal_buffer.num_elements && (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled || BX_KEY_THIS s.kbd_controller.bat_in_progress)) { BX_DEBUG(("service_keyboard: key in internal buffer waiting")); BX_KEY_THIS s.kbd_controller.kbd_output_buffer = BX_KEY_THIS s.kbd_internal_buffer.buffer[BX_KEY_THIS s.kbd_internal_buffer.head]; BX_KEY_THIS s.kbd_controller.outb = 1; // commented out since this would override the current state of the // mouse buffer flag - no bug seen - just seems wrong (das) // BX_KEY_THIS s.kbd_controller.auxb = 0; BX_KEY_THIS s.kbd_internal_buffer.head = (BX_KEY_THIS s.kbd_internal_buffer.head + 1) % BX_KBD_ELEMENTS; BX_KEY_THIS s.kbd_internal_buffer.num_elements--; if (BX_KEY_THIS s.kbd_controller.allow_irq1) BX_KEY_THIS s.kbd_controller.irq1_requested = 1; } else { create_mouse_packet(0); if (BX_KEY_THIS s.kbd_controller.aux_clock_enabled && BX_KEY_THIS s.mouse_internal_buffer.num_elements) { BX_DEBUG(("service_keyboard: key(from mouse) in internal buffer waiting")); BX_KEY_THIS s.kbd_controller.aux_output_buffer = BX_KEY_THIS s.mouse_internal_buffer.buffer[BX_KEY_THIS s.mouse_internal_buffer.head]; BX_KEY_THIS s.kbd_controller.outb = 1; BX_KEY_THIS s.kbd_controller.auxb = 1; BX_KEY_THIS s.mouse_internal_buffer.head = (BX_KEY_THIS s.mouse_internal_buffer.head + 1) % BX_MOUSE_BUFF_SIZE; BX_KEY_THIS s.mouse_internal_buffer.num_elements--; if (BX_KEY_THIS s.kbd_controller.allow_irq12) BX_KEY_THIS s.kbd_controller.irq12_requested = 1; } else { BX_DEBUG(("service_keyboard(): no keys waiting")); } } return(retval); } void bx_keyb_c::activate_timer(void) { if (BX_KEY_THIS s.kbd_controller.timer_pending == 0) { BX_KEY_THIS s.kbd_controller.timer_pending = 1; } } void bx_keyb_c::kbd_ctrl_to_mouse(Bit8u value) { // if we are not using a ps2 mouse, some of the following commands need to return different values bx_bool is_ps2 = 0; if ((BX_KEY_THIS s.mouse.type == BX_MOUSE_TYPE_PS2) || (BX_KEY_THIS s.mouse.type == BX_MOUSE_TYPE_IMPS2)) is_ps2 = 1; BX_DEBUG(("MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value)); BX_DEBUG((" enable = %u", (unsigned) BX_KEY_THIS s.mouse.enable)); BX_DEBUG((" allow_irq12 = %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12)); BX_DEBUG((" aux_clock_enabled = %u", (unsigned) BX_KEY_THIS s.kbd_controller.aux_clock_enabled)); // an ACK (0xFA) is always the first response to any valid input // received from the system other than Set-Wrap-Mode & Resend-Command if (BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter) { BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0; switch (BX_KEY_THIS s.kbd_controller.last_mouse_command) { case 0xf3: // Set Mouse Sample Rate BX_KEY_THIS s.mouse.sample_rate = value; BX_DEBUG(("mouse: sampling rate set: %d Hz", value)); if ((value == 200) && (!BX_KEY_THIS s.mouse.im_request)) { BX_KEY_THIS s.mouse.im_request = 1; } else if ((value == 100) && (BX_KEY_THIS s.mouse.im_request == 1)) { BX_KEY_THIS s.mouse.im_request = 2; } else if ((value == 80) && (BX_KEY_THIS s.mouse.im_request == 2)) { if (BX_KEY_THIS s.mouse.type == BX_MOUSE_TYPE_IMPS2) { BX_INFO(("wheel mouse mode enabled")); BX_KEY_THIS s.mouse.im_mode = 1; } else { BX_INFO(("wheel mouse mode request rejected")); } BX_KEY_THIS s.mouse.im_request = 0; } else { BX_KEY_THIS s.mouse.im_request = 0; } controller_enQ(0xFA, 1); // ack break; case 0xe8: // Set Mouse Resolution switch (value) { case 0: BX_KEY_THIS s.mouse.resolution_cpmm = 1; break; case 1: BX_KEY_THIS s.mouse.resolution_cpmm = 2; break; case 2: BX_KEY_THIS s.mouse.resolution_cpmm = 4; break; case 3: BX_KEY_THIS s.mouse.resolution_cpmm = 8; break; default: BX_PANIC(("mouse: unknown resolution %d", value)); break; } BX_DEBUG(("mouse: resolution set to %d counts per mm", BX_KEY_THIS s.mouse.resolution_cpmm)); controller_enQ(0xFA, 1); // ack break; default: BX_PANIC(("MOUSE: unknown last command (%02xh)", (unsigned) BX_KEY_THIS s.kbd_controller.last_mouse_command)); } } else { BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0; BX_KEY_THIS s.kbd_controller.last_mouse_command = value; // test for wrap mode first if (BX_KEY_THIS s.mouse.mode == MOUSE_MODE_WRAP) { // if not a reset command or reset wrap mode // then just echo the byte. if ((value != 0xff) && (value != 0xec)) { BX_DEBUG(("mouse: wrap mode: ignoring command 0x%02x",value)); controller_enQ(value, 1); // bail out return; } } switch (value) { case 0xe6: // Set Mouse Scaling to 1:1 controller_enQ(0xFA, 1); // ACK BX_KEY_THIS s.mouse.scaling = 2; BX_DEBUG(("mouse: scaling set to 1:1")); break; case 0xe7: // Set Mouse Scaling to 2:1 controller_enQ(0xFA, 1); // ACK BX_KEY_THIS s.mouse.scaling = 2; BX_DEBUG(("mouse: scaling set to 2:1")); break; case 0xe8: // Set Mouse Resolution controller_enQ(0xFA, 1); // ACK BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1; break; case 0xea: // Set Stream Mode BX_DEBUG(("mouse: stream mode on")); BX_KEY_THIS s.mouse.mode = MOUSE_MODE_STREAM; controller_enQ(0xFA, 1); // ACK break; case 0xec: // Reset Wrap Mode // unless we are in wrap mode ignore the command if (BX_KEY_THIS s.mouse.mode == MOUSE_MODE_WRAP) { BX_DEBUG(("mouse: wrap mode off")); // restore previous mode except disable stream mode reporting. // ### TODO disabling reporting in stream mode BX_KEY_THIS s.mouse.mode = BX_KEY_THIS s.mouse.saved_mode; controller_enQ(0xFA, 1); // ACK } break; case 0xee: // Set Wrap Mode // ### TODO flush output queue. // ### TODO disable interrupts if in stream mode. BX_DEBUG(("mouse: wrap mode on")); BX_KEY_THIS s.mouse.saved_mode = BX_KEY_THIS s.mouse.mode; BX_KEY_THIS s.mouse.mode = MOUSE_MODE_WRAP; controller_enQ(0xFA, 1); // ACK break; case 0xf0: // Set Remote Mode (polling mode, i.e. not stream mode.) BX_DEBUG(("mouse: remote mode on")); // ### TODO should we flush/discard/ignore any already queued packets? BX_KEY_THIS s.mouse.mode = MOUSE_MODE_REMOTE; controller_enQ(0xFA, 1); // ACK break; case 0xf2: // Read Device Type controller_enQ(0xFA, 1); // ACK if (BX_KEY_THIS s.mouse.im_mode) controller_enQ(0x03, 1); // Device ID (wheel z-mouse) else controller_enQ(0x00, 1); // Device ID (standard) BX_DEBUG(("mouse: read mouse ID")); break; case 0xf3: // Set Mouse Sample Rate (sample rate written to port 60h) controller_enQ(0xFA, 1); // ACK BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1; break; case 0xf4: // Enable (in stream mode) // is a mouse present? if (is_ps2) { BX_KEY_THIS s.mouse.enable = 1; controller_enQ(0xFA, 1); // ACK BX_DEBUG(("mouse enabled (stream mode)")); } else { // a mouse isn't present. We need to return a 0xFE (resend) instead of a 0xFA (ACK) controller_enQ(0xFE, 1); // RESEND BX_KEY_THIS s.kbd_controller.tim = 1; } break; case 0xf5: // Disable (in stream mode) BX_KEY_THIS s.mouse.enable = 0; controller_enQ(0xFA, 1); // ACK BX_DEBUG(("mouse disabled (stream mode)")); break; case 0xf6: // Set Defaults BX_KEY_THIS s.mouse.sample_rate = 100; /* reports per second (default) */ BX_KEY_THIS s.mouse.resolution_cpmm = 4; /* 4 counts per millimeter (default) */ BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */ BX_KEY_THIS s.mouse.enable = 0; BX_KEY_THIS s.mouse.mode = MOUSE_MODE_STREAM; controller_enQ(0xFA, 1); // ACK BX_DEBUG(("mouse: set defaults")); break; case 0xff: // Reset // is a mouse present? if (is_ps2) { BX_KEY_THIS s.mouse.sample_rate = 100; /* reports per second (default) */ BX_KEY_THIS s.mouse.resolution_cpmm = 4; /* 4 counts per millimeter (default) */ BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */ BX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET; BX_KEY_THIS s.mouse.enable = 0; if (BX_KEY_THIS s.mouse.im_mode) BX_INFO(("wheel mouse mode disabled")); BX_KEY_THIS s.mouse.im_mode = 0; /* (mch) NT expects an ack here */ controller_enQ(0xFA, 1); // ACK controller_enQ(0xAA, 1); // completion code controller_enQ(0x00, 1); // ID code (standard after reset) BX_DEBUG(("mouse reset")); } else { // a mouse isn't present. We need to return a 0xFE (resend) instead of a 0xFA (ACK) controller_enQ(0xFE, 1); // RESEND BX_KEY_THIS s.kbd_controller.tim = 1; } break; case 0xe9: // Get mouse information // should we ack here? (mch): Yes controller_enQ(0xFA, 1); // ACK controller_enQ(BX_KEY_THIS s.mouse.get_status_byte(), 1); // status controller_enQ(BX_KEY_THIS s.mouse.get_resolution_byte(), 1); // resolution controller_enQ(BX_KEY_THIS s.mouse.sample_rate, 1); // sample rate BX_DEBUG(("mouse: get mouse information")); break; case 0xeb: // Read Data (send a packet when in Remote Mode) controller_enQ(0xFA, 1); // ACK // perhaps we should be adding some movement here. mouse_enQ_packet(((BX_KEY_THIS s.mouse.button_status & 0x0f) | 0x08), 0x00, 0x00, 0x00); // bit3 of first byte always set //assumed we really aren't in polling mode, a rather odd assumption. BX_ERROR(("mouse: Warning: Read Data command partially supported.")); break; case 0xbb: // OS/2 Warp 3 uses this command BX_ERROR(("mouse: ignoring 0xbb command")); break; default: // If PS/2 mouse present, send NACK for unknown commands, otherwise ignore if (is_ps2) { BX_ERROR(("kbd_ctrl_to_mouse(): got value of 0x%02x", value)); controller_enQ(0xFE, 1); /* send NACK */ } } } } void bx_keyb_c::create_mouse_packet(bx_bool force_enq) { Bit8u b1, b2, b3, b4; if(BX_KEY_THIS s.mouse_internal_buffer.num_elements && !force_enq) return; Bit16s delta_x = BX_KEY_THIS s.mouse.delayed_dx; Bit16s delta_y = BX_KEY_THIS s.mouse.delayed_dy; Bit8u button_state=BX_KEY_THIS s.mouse.button_status | 0x08; if(!force_enq && !delta_x && !delta_y) { return; } if(delta_x>254) delta_x=254; if(delta_x<-254) delta_x=-254; if(delta_y>254) delta_y=254; if(delta_y<-254) delta_y=-254; b1 = (button_state & 0x0f) | 0x08; // bit3 always set if ((delta_x>=0) && (delta_x<=255)) { b2 = (Bit8u) delta_x; BX_KEY_THIS s.mouse.delayed_dx-=delta_x; } else if (delta_x > 255) { b2 = (Bit8u) 0xff; BX_KEY_THIS s.mouse.delayed_dx-=255; } else if (delta_x >= -256) { b2 = (Bit8u) delta_x; b1 |= 0x10; BX_KEY_THIS s.mouse.delayed_dx-=delta_x; } else { b2 = (Bit8u) 0x00; b1 |= 0x10; BX_KEY_THIS s.mouse.delayed_dx+=256; } if ((delta_y>=0) && (delta_y<=255)) { b3 = (Bit8u) delta_y; BX_KEY_THIS s.mouse.delayed_dy-=delta_y; } else if (delta_y > 255) { b3 = (Bit8u) 0xff; BX_KEY_THIS s.mouse.delayed_dy-=255; } else if (delta_y >= -256) { b3 = (Bit8u) delta_y; b1 |= 0x20; BX_KEY_THIS s.mouse.delayed_dy-=delta_y; } else { b3 = (Bit8u) 0x00; b1 |= 0x20; BX_KEY_THIS s.mouse.delayed_dy+=256; } b4 = (Bit8u) -BX_KEY_THIS s.mouse.delayed_dz; mouse_enQ_packet(b1, b2, b3, b4); } void bx_keyb_c::mouse_enabled_changed_static(void *dev, bx_bool enabled) { ((bx_keyb_c*)dev)->mouse_enabled_changed(enabled); } void bx_keyb_c::mouse_enabled_changed(bx_bool enabled) { if (BX_KEY_THIS s.mouse.delayed_dx || BX_KEY_THIS s.mouse.delayed_dy || BX_KEY_THIS s.mouse.delayed_dz) { create_mouse_packet(1); } BX_KEY_THIS s.mouse.delayed_dx=0; BX_KEY_THIS s.mouse.delayed_dy=0; BX_KEY_THIS s.mouse.delayed_dz=0; BX_DEBUG(("PS/2 mouse %s", enabled?"enabled":"disabled")); } void bx_keyb_c::mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy) { ((bx_keyb_c*)dev)->mouse_motion(delta_x, delta_y, delta_z, button_state, absxy); } void bx_keyb_c::mouse_motion(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy) { bx_bool force_enq=0; // don't generate interrupts if we are in remote mode. if (BX_KEY_THIS s.mouse.mode == MOUSE_MODE_REMOTE) // is there any point in doing any work if we don't act on the result // so go home. return; // Note: enable only applies in STREAM MODE. if (BX_KEY_THIS s.mouse.enable==0) return; // scale down the motion if ((delta_x < -1) || (delta_x > 1)) delta_x /= 2; if ((delta_y < -1) || (delta_y > 1)) delta_y /= 2; if (!BX_KEY_THIS s.mouse.im_mode) delta_z = 0; #ifdef VERBOSE_KBD_DEBUG if (delta_x != 0 || delta_y != 0 || delta_z != 0) BX_DEBUG(("[mouse] Dx=%d Dy=%d Dz=%d", delta_x, delta_y, delta_z)); #endif /* ifdef VERBOSE_KBD_DEBUG */ if ((delta_x==0) && (delta_y==0) && (delta_z==0) && (BX_KEY_THIS s.mouse.button_status == (button_state & 0x7))) { BX_DEBUG(("Ignoring useless mouse_motion call:")); BX_DEBUG(("This should be fixed in the gui code.")); return; } if ((BX_KEY_THIS s.mouse.button_status != (button_state & 0x7)) || delta_z) { force_enq=1; } BX_KEY_THIS s.mouse.button_status = button_state & 0x7; if(delta_x>255) delta_x=255; if(delta_y>255) delta_y=255; if(delta_x<-256) delta_x=-256; if(delta_y<-256) delta_y=-256; BX_KEY_THIS s.mouse.delayed_dx+=delta_x; BX_KEY_THIS s.mouse.delayed_dy+=delta_y; BX_KEY_THIS s.mouse.delayed_dz = delta_z; if((BX_KEY_THIS s.mouse.delayed_dx>255)|| (BX_KEY_THIS s.mouse.delayed_dx<-256)|| (BX_KEY_THIS s.mouse.delayed_dy>255)|| (BX_KEY_THIS s.mouse.delayed_dy<-256)) { force_enq=1; } create_mouse_packet(force_enq); } bochs-2.6/iodev/svga_cirrus.h0000644000175000017500000002274312020641505016146 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: svga_cirrus.h 11148 2012-04-23 17:06:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Makoto Suzuki (suzu) // Volker Ruppert (vruppert) // Robin Kay (komadori) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #if BX_SUPPORT_CLGD54XX #if BX_USE_CIRRUS_SMF # define BX_CIRRUS_SMF static # define BX_CIRRUS_THIS theSvga-> # define BX_CIRRUS_THIS_PTR theSvga #else # define BX_CIRRUS_SMF # define BX_CIRRUS_THIS this-> # define BX_CIRRUS_THIS_PTR this #endif // BX_USE_CIRRUS_SMF // 0x3b4,0x3d4 #define VGA_CRTC_MAX 0x18 #define CIRRUS_CRTC_MAX 0x27 // 0x3c4 #define VGA_SEQENCER_MAX 0x04 #define CIRRUS_SEQENCER_MAX 0x1f // 0x3ce #define VGA_CONTROL_MAX 0x08 #define CIRRUS_CONTROL_MAX 0x39 // Size of internal cache memory for bitblt. (must be >= 256 and 4-byte aligned) #define CIRRUS_BLT_CACHESIZE (2048 * 4) #if BX_SUPPORT_PCI #define CIRRUS_VIDEO_MEMORY_MB 4 #else #define CIRRUS_VIDEO_MEMORY_MB 2 #endif #define CIRRUS_VIDEO_MEMORY_KB (CIRRUS_VIDEO_MEMORY_MB * 1024) #define CIRRUS_VIDEO_MEMORY_BYTES (CIRRUS_VIDEO_MEMORY_KB * 1024) typedef void (*bx_cirrus_bitblt_rop_t)( Bit8u *dst,const Bit8u *src, int dstpitch,int srcpitch, int bltwidth,int bltheight); class bx_svga_cirrus_c : public bx_vgacore_c { public: bx_svga_cirrus_c(); virtual ~bx_svga_cirrus_c(); virtual void init_vga_extension(void); virtual void reset(unsigned type); virtual void redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height); virtual Bit8u mem_read(bx_phy_address addr); virtual void mem_write(bx_phy_address addr, Bit8u value); virtual int get_snapshot_mode(void); virtual void get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, unsigned *txWidth); virtual Bit32u get_gfx_snapshot(Bit8u **snapshot_ptr, Bit8u **palette_ptr, unsigned *iHeight, unsigned *iWidth, unsigned *iDepth); virtual void register_state(void); virtual void after_restore_state(void); #if BX_SUPPORT_PCI virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); #endif #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif private: static Bit32u svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void svga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_CIRRUS_SMF Bit32u svga_read(Bit32u address, unsigned io_len); void svga_write(Bit32u address, Bit32u value, unsigned io_len); #endif BX_CIRRUS_SMF void mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value); BX_CIRRUS_SMF void mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value); static void svga_timer_handler(void *); static Bit64s svga_param_handler(bx_param_c *param, int set, Bit64s val); BX_CIRRUS_SMF void svga_timer(void); BX_CIRRUS_SMF void svga_modeupdate(void); BX_CIRRUS_SMF void svga_update(void); BX_CIRRUS_SMF void svga_init_members(); BX_CIRRUS_SMF void draw_hardware_cursor(unsigned, unsigned, bx_svga_tileinfo_t *); // bank memory BX_CIRRUS_SMF void update_bank_ptr(Bit8u bank_index); // 0x3b4-0x3b5,0x3d4-0x3d5 BX_CIRRUS_SMF Bit8u svga_read_crtc(Bit32u address, unsigned index); BX_CIRRUS_SMF void svga_write_crtc(Bit32u address, unsigned index, Bit8u value); // 0x3c4-0x3c5 BX_CIRRUS_SMF Bit8u svga_read_sequencer(Bit32u address, unsigned index); BX_CIRRUS_SMF void svga_write_sequencer(Bit32u address, unsigned index, Bit8u value); // 0x3ce-0x3cf BX_CIRRUS_SMF Bit8u svga_read_control(Bit32u address, unsigned index); BX_CIRRUS_SMF void svga_write_control(Bit32u address, unsigned index, Bit8u value); // memory-mapped I/O BX_CIRRUS_SMF Bit8u svga_mmio_vga_read(Bit32u address); BX_CIRRUS_SMF void svga_mmio_vga_write(Bit32u address,Bit8u value); BX_CIRRUS_SMF Bit8u svga_mmio_blt_read(Bit32u address); BX_CIRRUS_SMF void svga_mmio_blt_write(Bit32u address,Bit8u value); BX_CIRRUS_SMF void svga_reset_bitblt(void); BX_CIRRUS_SMF void svga_bitblt(); BX_CIRRUS_SMF void svga_colorexpand(Bit8u *dst,const Bit8u *src,int count,int pixelwidth); #if BX_USE_CIRRUS_SMF #define svga_colorexpand_8_static svga_colorexpand_8 #define svga_colorexpand_16_static svga_colorexpand_16 #define svga_colorexpand_24_static svga_colorexpand_24 #define svga_colorexpand_32_static svga_colorexpand_32 #else static void svga_colorexpand_8_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count); static void svga_colorexpand_16_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count); static void svga_colorexpand_24_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count); static void svga_colorexpand_32_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count); #endif BX_CIRRUS_SMF void svga_colorexpand_8(Bit8u *dst,const Bit8u *src,int count); BX_CIRRUS_SMF void svga_colorexpand_16(Bit8u *dst,const Bit8u *src,int count); BX_CIRRUS_SMF void svga_colorexpand_24(Bit8u *dst,const Bit8u *src,int count); BX_CIRRUS_SMF void svga_colorexpand_32(Bit8u *dst,const Bit8u *src,int count); BX_CIRRUS_SMF void svga_setup_bitblt_cputovideo(Bit32u dstaddr,Bit32u srcaddr); BX_CIRRUS_SMF void svga_setup_bitblt_videotocpu(Bit32u dstaddr,Bit32u srcaddr); BX_CIRRUS_SMF void svga_setup_bitblt_videotovideo(Bit32u dstaddr,Bit32u srcaddr); #if BX_USE_CIRRUS_SMF == 0 static void svga_patterncopy_static(void *this_ptr); static void svga_simplebitblt_static(void *this_ptr); static void svga_solidfill_static(void *this_ptr); static void svga_patterncopy_memsrc_static(void *this_ptr); static void svga_simplebitblt_memsrc_static(void *this_ptr); static void svga_colorexpand_transp_memsrc_static(void *this_ptr); #else #define svga_patterncopy_static svga_patterncopy #define svga_simplebitblt_static svga_simplebitblt #define svga_solidfill_static svga_solidfill #define svga_patterncopy_memsrc_static svga_patterncopy_memsrc #define svga_simplebitblt_memsrc_static svga_simplebitblt_memsrc #define svga_colorexpand_transp_memsrc_static svga_colorexpand_transp_memsrc #endif BX_CIRRUS_SMF void svga_patterncopy(); BX_CIRRUS_SMF void svga_simplebitblt(); BX_CIRRUS_SMF void svga_solidfill(); BX_CIRRUS_SMF void svga_patterncopy_memsrc(); BX_CIRRUS_SMF void svga_simplebitblt_memsrc(); BX_CIRRUS_SMF void svga_colorexpand_transp_memsrc(); BX_CIRRUS_SMF bx_bool svga_asyncbitblt_next(); BX_CIRRUS_SMF bx_cirrus_bitblt_rop_t svga_get_fwd_rop_handler(Bit8u rop); BX_CIRRUS_SMF bx_cirrus_bitblt_rop_t svga_get_bkwd_rop_handler(Bit8u rop); struct { Bit8u index; Bit8u reg[CIRRUS_CRTC_MAX+1]; } crtc; // 0x3b4-5/0x3d4-5 struct { Bit8u index; Bit8u reg[CIRRUS_SEQENCER_MAX+1]; } sequencer; // 0x3c4-5 struct { Bit8u index; Bit8u reg[CIRRUS_CONTROL_MAX+1]; Bit8u shadow_reg0; Bit8u shadow_reg1; } control; // 0x3ce-f struct { unsigned lockindex; Bit8u data; Bit8u palette[48]; } hidden_dac; // 0x3c6 bx_bool svga_unlock_special; bx_bool svga_needs_update_tile; bx_bool svga_needs_update_dispentire; bx_bool svga_needs_update_mode; unsigned svga_xres; unsigned svga_yres; unsigned svga_pitch; unsigned svga_bpp; unsigned svga_dispbpp; Bit32u bank_base[2]; Bit32u bank_limit[2]; Bit8u *disp_ptr; struct { bx_cirrus_bitblt_rop_t rop_handler; int pixelwidth; int bltwidth; int bltheight; int dstpitch; int srcpitch; Bit8u bltmode; Bit8u bltmodeext; Bit8u bltrop; Bit8u *dst; const Bit8u *src; Bit32u srcaddr; #if BX_USE_CIRRUS_SMF void (*bitblt_ptr)(); #else void (*bitblt_ptr)(void *this_ptr); #endif Bit8u *memsrc_ptr; // CPU -> video Bit8u *memsrc_endptr; int memsrc_needed; Bit8u *memdst_ptr; // video -> CPU Bit8u *memdst_endptr; int memdst_bytesperline; int memdst_needed; Bit8u memsrc[CIRRUS_BLT_CACHESIZE]; Bit8u memdst[CIRRUS_BLT_CACHESIZE]; } bitblt; struct { Bit16u x, y, size; } hw_cursor; struct { Bit16u x, y, w, h; } redraw; bx_bool is_unlocked() { return svga_unlock_special; } bx_bool banking_granularity_is_16k() { return !!(control.reg[0x0B] & 0x20); } bx_bool banking_is_dual() { return !!(control.reg[0x0B] & 0x01); } #if BX_SUPPORT_PCI BX_CIRRUS_SMF void svga_init_pcihandlers(void); BX_CIRRUS_SMF bx_bool cirrus_mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param); BX_CIRRUS_SMF bx_bool cirrus_mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param); #endif }; #endif // BX_SUPPORT_CLGD54XX bochs-2.6/iodev/speaker.cc0000644000175000017500000001007612020641505015403 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: speaker.cc 11195 2012-05-24 18:06:40Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright 2003 by David N. Welton . // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define BX_PLUGGABLE #include "iodev.h" #include "speaker.h" #if BX_SUPPORT_SOUNDLOW #include "sound/soundmod.h" #endif #ifdef __linux__ #include #include #include #include #include #include #include #include #endif #define LOG_THIS theSpeaker-> bx_speaker_c *theSpeaker= NULL; int libspeaker_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theSpeaker = new bx_speaker_c(); bx_devices.pluginSpeaker = theSpeaker; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSpeaker, BX_PLUGIN_SPEAKER); return(0); // Success } void libspeaker_LTX_plugin_fini(void) { bx_devices.pluginSpeaker = &bx_devices.stubSpeaker; delete theSpeaker; } bx_speaker_c::bx_speaker_c() { put("speaker", "SPEAK"); beep_frequency = 0.0; // Off #ifdef __linux__ consolefd = -1; #endif } bx_speaker_c::~bx_speaker_c() { #ifdef __linux__ if (consolefd >= 0) { ioctl(consolefd, KIOCSOUND, 0); close(consolefd); } #endif BX_DEBUG(("Exit")); } void bx_speaker_c::init(void) { outputinit = 0; } void bx_speaker_c::reset(unsigned type) { if (!outputinit) { outputinit = 1; #if BX_SUPPORT_SOUNDLOW if (DEV_soundmod_beep_off()) { BX_INFO(("Using lowlevel sound support for output")); return; } #endif #ifdef __linux__ consolefd = open("/dev/console", O_WRONLY); if (consolefd != -1) { BX_INFO(("Using /dev/console for output")); } else { BX_ERROR(("Failed to open /dev/console: %s", strerror(errno))); BX_ERROR(("Deactivating beep on console")); } #elif defined(WIN32) BX_INFO(("Using system beep for output")); #endif } beep_off(); } void bx_speaker_c::beep_on(float frequency) { beep_frequency = frequency; #if BX_SUPPORT_SOUNDLOW if (DEV_soundmod_beep_on(frequency)) return; #endif #ifdef __linux__ if (consolefd != -1) { this->info("pc speaker on with frequency %f", frequency); ioctl(consolefd, KIOCSOUND, (int)(clock_tick_rate/frequency)); } #elif defined(WIN32) usec_start = bx_pc_system.time_usec(); #endif // give the gui a chance to signal beep on bx_gui->beep_on(frequency); } #if defined(WIN32) static struct { DWORD frequency; DWORD msec; } beep_info; DWORD WINAPI BeepThread(LPVOID) { static BOOL threadActive = FALSE; while (threadActive) Sleep(10); threadActive = TRUE; Beep(beep_info.frequency, beep_info.msec); threadActive = FALSE; return 0; } #endif void bx_speaker_c::beep_off() { #if BX_SUPPORT_SOUNDLOW if (DEV_soundmod_beep_off()) return; #endif if (beep_frequency != 0.0) { #ifdef __linux__ if (consolefd != -1) { ioctl(consolefd, KIOCSOUND, 0); } #elif defined(WIN32) // FIXME: sound should start at beep_on() and end here DWORD threadID; beep_info.msec = (DWORD)((bx_pc_system.time_usec() - usec_start) / 1000); beep_info.frequency = (DWORD)beep_frequency; CreateThread(NULL, 0, BeepThread, NULL, 0, &threadID); #endif // give the gui a chance to signal beep off bx_gui->beep_off(); beep_frequency = 0.0; } } bochs-2.6/iodev/cmos.h0000644000175000017500000000546212020641505014557 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: cmos.h 11182 2012-05-15 17:03:45Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef BX_IODEV_CMOS_H #define BX_IODEV_CMOS_H #if BX_USE_CMOS_SMF # define BX_CMOS_SMF static # define BX_CMOS_THIS theCmosDevice-> #else # define BX_CMOS_SMF # define BX_CMOS_THIS this-> #endif class bx_cmos_c : public bx_cmos_stub_c { public: bx_cmos_c(); virtual ~bx_cmos_c(); virtual void init(void); virtual void checksum_cmos(void); virtual void reset(unsigned type); virtual void save_image(void); virtual void register_state(void); virtual void after_restore_state(void); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif virtual Bit32u get_reg(unsigned reg) { return s.reg[reg]; } virtual void set_reg(unsigned reg, Bit32u val) { s.reg[reg] = val; } virtual time_t get_timeval() { return s.timeval; } struct { int periodic_timer_index; Bit32u periodic_interval_usec; int one_second_timer_index; int uip_timer_index; time_t timeval; Bit8u cmos_mem_address; bx_bool timeval_change; bx_bool rtc_mode_12hour; bx_bool rtc_mode_binary; bx_bool rtc_sync; Bit8u reg[128]; } s; // state information private: static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_CMOS_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned len); #endif public: static void periodic_timer_handler(void *); static void one_second_timer_handler(void *); static void uip_timer_handler(void *); BX_CMOS_SMF void periodic_timer(void); BX_CMOS_SMF void one_second_timer(void); BX_CMOS_SMF void uip_timer(void); private: BX_CMOS_SMF void update_clock(void); BX_CMOS_SMF void update_timeval(void); BX_CMOS_SMF void CRA_change(void); }; #endif bochs-2.6/iodev/parallel.h0000644000175000017500000000434012020641505015404 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: parallel.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_PARPORT_H #define BX_IODEV_PARPORT_H #if BX_USE_PAR_SMF # define BX_PAR_SMF static # define BX_PAR_THIS theParallelDevice-> #else # define BX_PAR_SMF # define BX_PAR_THIS this-> #endif #define BX_PARPORT_MAXDEV 2 #define BX_PAR_DATA 0 #define BX_PAR_STAT 1 #define BX_PAR_CTRL 2 typedef struct { Bit8u data; struct { bx_bool error; bx_bool slct; bx_bool pe; bx_bool ack; bx_bool busy; } STATUS; struct { bx_bool strobe; bx_bool autofeed; bx_bool init; bx_bool slct_in; bx_bool irq; bx_bool input; } CONTROL; Bit8u IRQ; FILE *output; bx_bool initmode; } bx_par_t; class bx_parallel_c : public bx_devmodel_c { public: bx_parallel_c(); virtual ~bx_parallel_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); private: bx_par_t s[BX_PARPORT_MAXDEV]; static void virtual_printer(Bit8u port); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_PAR_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/biosdev.h0000644000175000017500000000353412020641505015247 0ustar guillemguillem//////////////////////////////////////////////////////////////////////// // $Id: biosdev.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_BIOSDEV_H #define BX_IODEV_BIOSDEV_H #define BX_BIOS_MESSAGE_SIZE 80 #if BX_USE_BIOS_SMF # define BX_BIOS_SMF static # define BX_BIOS_THIS theBiosDevice-> #else # define BX_BIOS_SMF # define BX_BIOS_THIS this-> #endif class bx_biosdev_c : public bx_devmodel_c { public: bx_biosdev_c(); virtual ~bx_biosdev_c(); virtual void init(void); virtual void reset(unsigned type) {} private: static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_BIOS_SMF void write(Bit32u address, Bit32u value, unsigned io_len); #endif struct { Bit8u bios_message[BX_BIOS_MESSAGE_SIZE]; unsigned int bios_message_i; bx_bool bios_panic_flag; Bit8u vgabios_message[BX_BIOS_MESSAGE_SIZE]; unsigned int vgabios_message_i; bx_bool vgabios_panic_flag; } s; // state information }; #endif bochs-2.6/iodev/iodebug.h0000644000175000017500000000366212020641505015234 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: iodebug.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef _BX_IODEBUG_H #define _BX_IODEBUG_H #if BX_SUPPORT_IODEBUG #define BX_IODEBUG_MAX_AREAS 30 class bx_iodebug_c : public bx_iodebug_stub_c { public: bx_iodebug_c(); virtual ~bx_iodebug_c() {} virtual void init(void); virtual void reset (unsigned type) {} virtual void mem_write(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data); virtual void mem_read(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data); private: static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); Bit32u read(Bit32u addr, unsigned io_len); void write(Bit32u addr, Bit32u dvalue, unsigned io_len); static unsigned range_test(bx_phy_address addr, unsigned len); static void add_range(bx_phy_address addr_start, bx_phy_address addr_end); }; #endif #endif bochs-2.6/iodev/pci.h0000644000175000017500000000633512020641505014371 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pci.h 11148 2012-04-23 17:06:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_PCI_BRIDGE_H #define BX_IODEV_PCI_BRIDGE_H #define BX_MAX_PCI_DEVICES 20 #define BX_PCI_DEVICE(device, function) ((device)<<3 | (function)) #if BX_USE_PCI_SMF # define BX_PCI_SMF static # define BX_PCI_THIS thePciBridge-> #else # define BX_PCI_SMF # define BX_PCI_THIS this-> #endif #define BX_PCI_INTA 1 #define BX_PCI_INTB 2 #define BX_PCI_INTC 3 #define BX_PCI_INTD 4 class bx_pci_device_stub_c; class bx_pci_bridge_c : public bx_pci_bridge_stub_c { public: bx_pci_bridge_c(); virtual ~bx_pci_bridge_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); virtual void after_restore_state(void); virtual bx_bool register_pci_handlers(bx_pci_device_stub_c *device, Bit8u *devfunc, const char *name, const char *descr); virtual bx_bool is_pci_device(const char *name); virtual bx_bool pci_set_base_mem(void *this_ptr, memory_handler_t f1, memory_handler_t f2, Bit32u *addr, Bit8u *pci_conf, unsigned size); virtual bx_bool pci_set_base_io(void *this_ptr, bx_read_handler_t f1, bx_write_handler_t f2, Bit32u *addr, Bit8u *pci_conf, unsigned size, const Bit8u *iomask, const char *name); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif private: Bit8u pci_handler_id[0x100]; // 256 devices/functions struct { bx_pci_device_stub_c *handler; } pci_handler[BX_MAX_PCI_DEVICES]; unsigned num_pci_handlers; bx_bool slot_used[BX_N_PCI_SLOTS]; bx_bool slots_checked; Bit32u confAddr; Bit32u confData; void smram_control(Bit8u value); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_PCI_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/serial_raw.cc0000644000175000017500000003044312020641505016101 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: serial_raw.cc 10898 2011-12-30 11:13:37Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if USE_RAW_SERIAL #include "serial_raw.h" #define LOG_THIS #ifdef WIN32_RECEIVE_RAW DWORD WINAPI RawSerialThread(VOID *this_ptr); #endif serial_raw::serial_raw(const char *devname) { #ifdef WIN32 char portstr[MAX_PATH]; #ifdef WIN32_RECEIVE_RAW DWORD threadID; #endif #endif put("serial_raw", "SERR"); #ifdef WIN32 memset(&dcb, 0, sizeof(DCB)); dcb.DCBlength = sizeof(DCB); dcb.fBinary = 1; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.Parity = NOPARITY; dcb.ByteSize = 8; dcb.StopBits = ONESTOPBIT; dcb.BaudRate = CBR_115200; DCBchanged = FALSE; if (lstrlen(devname) > 0) { wsprintf(portstr, "\\\\.\\%s", devname); hCOM = CreateFile(portstr, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (hCOM != INVALID_HANDLE_VALUE) { present = 1; GetCommModemStatus(hCOM, &MSR_value); SetupComm(hCOM, 8192, 2048); PurgeComm(hCOM, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); #ifdef WIN32_RECEIVE_RAW SetCommMask(hCOM, EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING | EV_RLSD | EV_RXCHAR); memset(&rx_ovl, 0, sizeof(OVERLAPPED)); rx_ovl.hEvent = CreateEvent(NULL,TRUE,FALSE,"receive"); hRawSerialThread = CreateThread(NULL, 0, RawSerialThread, this, 0, &threadID); #endif } else { present = 0; BX_ERROR(("Raw device '%s' not present", devname)); } } else { present = 0; } #else present = 0; #endif set_modem_control(0x00); set_break(0); rxdata_count = 0; } serial_raw::~serial_raw(void) { if (present) { #ifdef WIN32 #ifdef WIN32_RECEIVE_RAW thread_quit = TRUE; SetCommMask(hCOM, 0); while (thread_active) Sleep(10); CloseHandle(thread_ovl.hEvent); CloseHandle(rx_ovl.hEvent); CloseHandle(hRawSerialThread); #endif CloseHandle(hCOM); #endif } } void serial_raw::set_baudrate(int rate) { BX_DEBUG (("set_baudrate %d", rate)); #ifdef WIN32 switch (rate) { case 110: dcb.BaudRate = CBR_110; break; case 300: dcb.BaudRate = CBR_300; break; case 600: dcb.BaudRate = CBR_600; break; case 1200: dcb.BaudRate = CBR_1200; break; case 2400: dcb.BaudRate = CBR_2400; break; case 4800: dcb.BaudRate = CBR_4800; break; case 9600: dcb.BaudRate = CBR_9600; break; case 19200: dcb.BaudRate = CBR_19200; break; case 38400: dcb.BaudRate = CBR_38400; break; case 57600: dcb.BaudRate = CBR_57600; break; case 115200: dcb.BaudRate = CBR_115200; break; default: BX_ERROR(("set_baudrate(): unsupported value %d", rate)); } DCBchanged = TRUE; #endif } void serial_raw::set_data_bits(int val) { BX_DEBUG (("set data bits (%d)", val)); #ifdef WIN32 dcb.ByteSize = val; DCBchanged = TRUE; #endif } void serial_raw::set_stop_bits(int val) { BX_DEBUG (("set stop bits (%d)", val)); #ifdef WIN32 if (val == 1) { dcb.StopBits = ONESTOPBIT; } if (dcb.ByteSize == 5) { dcb.StopBits = ONE5STOPBITS; } else { dcb.StopBits = TWOSTOPBITS; } DCBchanged = TRUE; #endif } void serial_raw::set_parity_mode(int mode) { BX_DEBUG (("set parity mode %d", mode)); #ifdef WIN32 switch (mode) { case 0: dcb.fParity = FALSE; dcb.Parity = NOPARITY; break; case 1: dcb.fParity = TRUE; dcb.Parity = ODDPARITY; break; case 2: dcb.fParity = TRUE; dcb.Parity = EVENPARITY; break; case 3: dcb.fParity = TRUE; dcb.Parity = MARKPARITY; break; case 4: dcb.fParity = TRUE; dcb.Parity = SPACEPARITY; break; } DCBchanged = TRUE; #endif } void serial_raw::set_break(int mode) { BX_DEBUG (("set break %s", mode?"on":"off")); #ifdef WIN32 if (mode) { SetCommBreak(hCOM); } else { ClearCommBreak(hCOM); } #endif } void serial_raw::set_modem_control(int ctrl) { BX_DEBUG (("set modem control 0x%02x", ctrl)); #ifdef WIN32 EscapeCommFunction(hCOM, (ctrl & 0x01)?SETDTR:CLRDTR); EscapeCommFunction(hCOM, (ctrl & 0x02)?SETRTS:CLRRTS); #endif } int serial_raw::get_modem_status() { int status = 0; #ifdef WIN32 status = MSR_value; #endif BX_DEBUG (("get modem status returns 0x%02x", status)); return status; } void serial_raw::setup_port() { #ifdef WIN32 DWORD DErr; COMMTIMEOUTS ctmo; ClearCommError(hCOM, &DErr, NULL); PurgeComm(hCOM, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); memset(&ctmo, 0, sizeof(ctmo)); SetCommTimeouts(hCOM, &ctmo); SetCommState(hCOM, &dcb); rxdata_count = 0; #ifdef WIN32_RECEIVE_RAW thread_rxdata_count = 0; #endif #endif } void serial_raw::transmit(Bit8u byte) { #ifdef WIN32 DWORD DErr, Len2; OVERLAPPED tx_ovl; #endif BX_DEBUG (("transmit %d", byte)); if (present) { #ifdef WIN32 if (DCBchanged) { setup_port(); } else { ClearCommError(hCOM, &DErr, NULL); } memset(&tx_ovl, 0, sizeof(OVERLAPPED)); tx_ovl.hEvent = CreateEvent(NULL,TRUE,TRUE,"transmit"); if (!WriteFile(hCOM, &byte, 1, &Len2, &tx_ovl)) { if (GetLastError() == ERROR_IO_PENDING) { if (WaitForSingleObject(tx_ovl.hEvent, 100) == WAIT_OBJECT_0) { GetOverlappedResult(hCOM, &tx_ovl, &Len2, FALSE); } } } if (Len2 != 1) BX_ERROR(("transmit failed: len = %d", Len2)); ClearCommError(hCOM, &DErr, NULL); CloseHandle(tx_ovl.hEvent); #endif } } bx_bool serial_raw::ready_transmit() { BX_DEBUG (("ready_transmit returning %d", present)); return present; } bx_bool serial_raw::ready_receive() { #ifdef WIN32_RECEIVE_RAW if ((rxdata_count == 0) && (thread_rxdata_count > 0)) { SetEvent(thread_ovl.hEvent); SetEvent(rx_ovl.hEvent); } #endif BX_DEBUG (("ready_receive returning %d", (rxdata_count > 0))); return (rxdata_count > 0); } int serial_raw::receive() { #ifdef WIN32 int data; #endif if (present) { #ifdef WIN32 if (DCBchanged) { setup_port(); } data = rxdata_buffer[0]; if (rxdata_count > 0) { memcpy(&rxdata_buffer[0], &rxdata_buffer[1], sizeof(Bit16s)*(RX_BUFSIZE-1)); rxdata_count--; } if (data < 0) { switch (data) { case RAW_EVENT_CTS_ON: MSR_value |= 0x10; break; case RAW_EVENT_CTS_OFF: MSR_value &= ~0x10; break; case RAW_EVENT_DSR_ON: MSR_value |= 0x20; break; case RAW_EVENT_DSR_OFF: MSR_value &= ~0x20; break; case RAW_EVENT_RING_ON: MSR_value |= 0x40; break; case RAW_EVENT_RING_OFF: MSR_value &= ~0x40; break; case RAW_EVENT_RLSD_ON: MSR_value |= 0x80; break; case RAW_EVENT_RLSD_OFF: MSR_value &= ~0x80; break; } } return data; #else BX_DEBUG (("receive returning 'A'")); return (int)'A'; #endif } else { BX_DEBUG (("receive returning 'A'")); return (int)'A'; } } #ifdef WIN32_RECEIVE_RAW DWORD WINAPI RawSerialThread(VOID *this_ptr) { serial_raw *class_ptr = (serial_raw *) this_ptr; class_ptr->serial_thread(); return 0; } void serial_raw::serial_thread() { DWORD DErr, Len2; DWORD EvtMask, MSR, Temp; char s1[2]; SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); thread_active = TRUE; thread_quit = FALSE; memset(&thread_ovl, 0, sizeof(OVERLAPPED)); thread_ovl.hEvent = CreateEvent(NULL,TRUE,TRUE,"thread"); thread_rxdata_count = 0; while (!thread_quit) { if ((rxdata_count == 0) && (thread_rxdata_count > 0)) { if (thread_rxdata_count > RX_BUFSIZE) { memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*RX_BUFSIZE); memcpy(&thread_rxdata_buffer[0], &thread_rxdata_buffer[RX_BUFSIZE], sizeof(Bit16s)*(thread_rxdata_count-RX_BUFSIZE)); rxdata_count = RX_BUFSIZE; thread_rxdata_count -= RX_BUFSIZE; } else { memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*thread_rxdata_count); rxdata_count = thread_rxdata_count; thread_rxdata_count = 0; } } ClearCommError(hCOM, &DErr, NULL); EvtMask = 0; if (!WaitCommEvent(hCOM, &EvtMask, &thread_ovl)) { if (GetLastError() == ERROR_IO_PENDING) { if (WaitForSingleObject(thread_ovl.hEvent, INFINITE) == WAIT_OBJECT_0) { GetOverlappedResult(hCOM, &thread_ovl, &Temp, FALSE); } } } if (EvtMask & EV_RXCHAR) { if (thread_rxdata_count < THREAD_RX_BUFSIZE) { do { ClearCommError(hCOM, &DErr, NULL); if (!ReadFile(hCOM, s1, 1, &Len2, &rx_ovl)) { if (GetLastError() == ERROR_IO_PENDING) { if (WaitForSingleObject(rx_ovl.hEvent, INFINITE) != WAIT_OBJECT_0) { Len2 = 0; } else { GetOverlappedResult(hCOM, &rx_ovl, &Len2, FALSE); } } else { Len2 = 0; } } if (Len2 > 0) { enq_event(s1[0]); } if ((rxdata_count == 0) && (thread_rxdata_count > 0)) { if (thread_rxdata_count > RX_BUFSIZE) { memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*RX_BUFSIZE); memcpy(&thread_rxdata_buffer[0], &thread_rxdata_buffer[RX_BUFSIZE], sizeof(Bit16s)*(thread_rxdata_count-RX_BUFSIZE)); rxdata_count = RX_BUFSIZE; thread_rxdata_count -= RX_BUFSIZE; } else { memcpy(&rxdata_buffer[0], &thread_rxdata_buffer[0], sizeof(Bit16s)*thread_rxdata_count); rxdata_count = thread_rxdata_count; thread_rxdata_count = 0; } } } while ((Len2 != 0) && (thread_rxdata_count < THREAD_RX_BUFSIZE)); ClearCommError(hCOM, &DErr, NULL); } } if (EvtMask & EV_BREAK) { enq_event(RAW_EVENT_BREAK); } if (EvtMask & EV_ERR) { ClearCommError(hCOM, &DErr, NULL); if (DErr & CE_FRAME) { enq_event(RAW_EVENT_FRAME); } if (DErr & CE_OVERRUN) { enq_event(RAW_EVENT_OVERRUN); } if (DErr & CE_RXPARITY) { enq_event(RAW_EVENT_PARITY); } } if (EvtMask & (EV_CTS | EV_DSR | EV_RING | EV_RLSD)) { GetCommModemStatus(hCOM, &MSR); } if (EvtMask & EV_CTS) { if (MSR & MS_CTS_ON) { enq_event(RAW_EVENT_CTS_ON); } else { enq_event(RAW_EVENT_CTS_OFF); } } if (EvtMask & EV_DSR) { if (MSR & MS_DSR_ON) { enq_event(RAW_EVENT_DSR_ON); } else { enq_event(RAW_EVENT_DSR_OFF); } } if (EvtMask & EV_RING) { if (MSR & MS_RING_ON) { enq_event(RAW_EVENT_RING_ON); } else { enq_event(RAW_EVENT_RING_OFF); } } if (EvtMask & EV_RLSD) { if (MSR & MS_RLSD_ON) { enq_event(RAW_EVENT_RLSD_ON); } else { enq_event(RAW_EVENT_RLSD_OFF); } } } CloseHandle(thread_ovl.hEvent); thread_active = FALSE; } void serial_raw::enq_event(Bit16s event) { if (thread_rxdata_count < THREAD_RX_BUFSIZE) { thread_rxdata_buffer[thread_rxdata_count++] = event; } else { fprintf(stderr, "receive buffer overflow\n"); } } #endif #endif bochs-2.6/iodev/floppy.h0000644000175000017500000001344112020641505015123 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: floppy.h 11277 2012-07-12 21:20:46Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // #ifndef BX_IODEV_FLOPPY_H #define BX_IODEV_FLOPPY_H #define FROM_FLOPPY 10 #define TO_FLOPPY 11 #if BX_USE_FD_SMF # define BX_FD_SMF static # define BX_FD_THIS theFloppyController-> #else # define BX_FD_SMF # define BX_FD_THIS this-> #endif typedef struct { int fd; /* file descriptor of floppy image file */ unsigned sectors_per_track; /* number of sectors/track */ unsigned sectors; /* number of formatted sectors on diskette */ unsigned tracks; /* number of tracks */ unsigned heads; /* number of heads */ unsigned type; unsigned write_protected; unsigned status_changed; bx_bool vvfat_floppy; device_image_t *vvfat; } floppy_t; class bx_floppy_ctrl_c : public bx_floppy_stub_c { public: bx_floppy_ctrl_c(); virtual ~bx_floppy_ctrl_c(); virtual void init(void); virtual void reset(unsigned type); virtual unsigned set_media_status(unsigned drive, bx_bool status); virtual void register_state(void); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif private: struct { Bit8u data_rate; Bit8u command[10]; /* largest command size ??? */ Bit8u command_index; Bit8u command_size; bx_bool command_complete; Bit8u pending_command; bx_bool multi_track; bx_bool pending_irq; Bit8u reset_sensei; Bit8u format_count; Bit8u format_fillbyte; Bit8u result[10]; Bit8u result_index; Bit8u result_size; Bit8u DOR; // Digital Ouput Register Bit8u TDR; // Tape Drive Register Bit8u cylinder[4]; // really only using 2 drives Bit8u head[4]; // really only using 2 drives Bit8u sector[4]; // really only using 2 drives Bit8u eot[4]; // really only using 2 drives bx_bool TC; // Terminal Count status from DMA controller /* MAIN STATUS REGISTER * b7: MRQ: main request 1=data register ready 0=data register not ready * b6: DIO: data input/output: * 1=controller->CPU (ready for data read) * 0=CPU->controller (ready for data write) * b5: NDMA: non-DMA mode: 1=controller not in DMA modes * 0=controller in DMA mode * b4: BUSY: instruction(device busy) 1=active 0=not active * b3-0: ACTD, ACTC, ACTB, ACTA: * drive D,C,B,A in positioning mode 1=active 0=not active */ Bit8u main_status_reg; Bit8u status_reg0; Bit8u status_reg1; Bit8u status_reg2; Bit8u status_reg3; // drive field allows up to 4 drives, even though probably only 2 will // ever be used. floppy_t media[4]; unsigned num_supported_floppies; Bit8u floppy_buffer[512+2]; // 2 extra for good measure unsigned floppy_buffer_index; int floppy_timer_index; bx_bool media_present[4]; Bit8u device_type[4]; Bit8u DIR[4]; // Digital Input Register: // b7: 0=diskette is present and has not been changed // 1=diskette missing or changed bx_bool lock; // FDC lock status Bit8u SRT; // step rate time Bit8u HUT; // head unload time Bit8u HLT; // head load time Bit8u config; // configure byte #1 Bit8u pretrk; // precompensation track Bit8u perp_mode; // perpendicular mode int statusbar_id[2]; // IDs of the status LEDs } s; // state information static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_FD_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif BX_FD_SMF Bit16u dma_write(Bit8u *buffer, Bit16u maxlen); BX_FD_SMF Bit16u dma_read(Bit8u *buffer, Bit16u maxlen); BX_FD_SMF void floppy_command(void); BX_FD_SMF void floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, Bit32u bytes, Bit8u direction); BX_FD_SMF void raise_interrupt(void); BX_FD_SMF void lower_interrupt(void); BX_FD_SMF void enter_idle_phase(void); BX_FD_SMF void enter_result_phase(void); BX_FD_SMF Bit32u calculate_step_delay(Bit8u drive, Bit8u new_cylinder); BX_FD_SMF void reset_changeline(void); BX_FD_SMF bx_bool get_tc(void); static void timer_handler(void *); BX_FD_SMF void timer(void); BX_FD_SMF void increment_sector(void); BX_FD_SMF bx_bool evaluate_media(Bit8u devtype, Bit8u type, char *path, floppy_t *media); BX_FD_SMF void close_media(floppy_t *media); // runtime options static Bit64s floppy_param_handler(bx_param_c *param, int set, Bit64s val); static const char* floppy_param_string_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen); static void runtime_config_handler(void *); void runtime_config(void); }; #endif bochs-2.6/iodev/vga.h0000644000175000017500000001464012020641505014371 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vga.h 11148 2012-04-23 17:06:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // PCI VGA dummy adapter Copyright (C) 2002,2003 Mike Nordell // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_VGA_H #define BX_IODEV_VGA_H // Bochs VBE definitions #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 16 #define VBE_DISPI_4BPP_PLANE_SHIFT 22 #define VBE_DISPI_BANK_ADDRESS 0xA0000 #define VBE_DISPI_BANK_SIZE_KB 64 #define VBE_DISPI_MAX_XRES 2560 #define VBE_DISPI_MAX_YRES 1600 #define VBE_DISPI_MAX_BPP 32 #define VBE_DISPI_IOPORT_INDEX 0x01CE #define VBE_DISPI_IOPORT_DATA 0x01CF #define VBE_DISPI_INDEX_ID 0x0 #define VBE_DISPI_INDEX_XRES 0x1 #define VBE_DISPI_INDEX_YRES 0x2 #define VBE_DISPI_INDEX_BPP 0x3 #define VBE_DISPI_INDEX_ENABLE 0x4 #define VBE_DISPI_INDEX_BANK 0x5 #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 #define VBE_DISPI_INDEX_X_OFFSET 0x8 #define VBE_DISPI_INDEX_Y_OFFSET 0x9 #define VBE_DISPI_INDEX_VIDEO_MEMORY_64K 0xa #define VBE_DISPI_ID0 0xB0C0 #define VBE_DISPI_ID1 0xB0C1 #define VBE_DISPI_ID2 0xB0C2 #define VBE_DISPI_ID3 0xB0C3 #define VBE_DISPI_ID4 0xB0C4 #define VBE_DISPI_ID5 0xB0C5 #define VBE_DISPI_BPP_4 0x04 #define VBE_DISPI_BPP_8 0x08 #define VBE_DISPI_BPP_15 0x0F #define VBE_DISPI_BPP_16 0x10 #define VBE_DISPI_BPP_24 0x18 #define VBE_DISPI_BPP_32 0x20 #define VBE_DISPI_DISABLED 0x00 #define VBE_DISPI_ENABLED 0x01 #define VBE_DISPI_GETCAPS 0x02 #define VBE_DISPI_8BIT_DAC 0x20 #define VBE_DISPI_LFB_ENABLED 0x40 #define VBE_DISPI_NOCLEARMEM 0x80 #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000 #define VBE_DISPI_TOTAL_VIDEO_MEMORY_KB (VBE_DISPI_TOTAL_VIDEO_MEMORY_MB * 1024) #define VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB * 1024) // End Bochs VBE definitions #if BX_USE_VGA_SMF # define BX_VGA_SMF static # define BX_VGA_THIS theVga-> # define BX_VGA_THIS_PTR theVga #else # define BX_VGA_SMF # define BX_VGA_THIS this-> # define BX_VGA_THIS_PTR this #endif class bx_vga_c : public bx_vgacore_c { public: bx_vga_c(); virtual ~bx_vga_c(); virtual void reset(unsigned type); BX_VGA_SMF bx_bool mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param); BX_VGA_SMF bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param); virtual Bit8u mem_read(bx_phy_address addr); virtual void mem_write(bx_phy_address addr, Bit8u value); virtual void register_state(void); virtual void after_restore_state(void); virtual void redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height); virtual int get_snapshot_mode(void); virtual Bit32u get_gfx_snapshot(Bit8u **snapshot_ptr, Bit8u **palette_ptr, unsigned *iHeight, unsigned *iWidth, unsigned *iDepth); virtual void init_vga_extension(void); static void timer_handler(void *); #if BX_USE_VGA_SMF == 0 BX_VGA_SMF void timer(void); #endif #if BX_SUPPORT_PCI virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); #endif #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif static Bit64s vga_param_handler(bx_param_c *param, int set, Bit64s val); protected: static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if BX_USE_VGA_SMF static void write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #endif void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); BX_VGA_SMF void update(void); // Bochs VBE section virtual bx_bool vbe_set_base_addr(Bit32u *addr, Bit8u *pci_conf); BX_VGA_SMF Bit8u vbe_mem_read(bx_phy_address addr) BX_CPP_AttrRegparmN(1); BX_VGA_SMF void vbe_mem_write(bx_phy_address addr, Bit8u value) BX_CPP_AttrRegparmN(2); static Bit32u vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if BX_USE_VGA_SMF == 0 Bit32u vbe_read(Bit32u address, unsigned io_len); void vbe_write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log); #endif private: bx_bool vbe_present; struct { Bit16u cur_dispi; Bit32u base_address; Bit16u xres; Bit16u yres; Bit16u bpp; Bit16u max_xres; Bit16u max_yres; Bit16u max_bpp; Bit16u bank; bx_bool enabled; Bit16u curindex; Bit32u visible_screen_size; /**< in bytes */ Bit16u offset_x; /**< Virtual screen x start (in pixels) */ Bit16u offset_y; /**< Virtual screen y start (in pixels) */ Bit16u virtual_xres; Bit16u virtual_yres; Bit32u virtual_start; /**< For dealing with bpp>8, this is where the virtual screen starts. */ Bit8u bpp_multiplier; /**< We have to save this b/c sometimes we need to recalculate stuff with it. */ bx_bool lfb_enabled; bx_bool get_capabilities; bx_bool dac_8bit; } vbe; // VBE state information }; #endif bochs-2.6/iodev/pcidev.h0000644000175000017500000000424012020641505015061 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pcidev.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// /* * PCIDEV: PCI host device mapping * Copyright (C) 2003 - Frank Cornelis * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef BX_IODEV_PCIDEV_H #define BX_IODEV_PCIDEV_H #if BX_USE_PCIDEV_SMF # define BX_PCIDEV_THIS thePciDevAdapter-> # define BX_PCIDEV_THIS_ thePciDevAdapter #else # define BX_PCIDEV_THIS this-> # define BX_PCIDEV_THIS_ this #endif struct region_struct { Bit32u config_value; Bit32u start; // can change Bit32u size; Bit32u host_start; // never changes!!! class bx_pcidev_c *pcidev; }; class bx_pcidev_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: bx_pcidev_c(); virtual ~bx_pcidev_c(); virtual void init(void); virtual void reset(unsigned type); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); int pcidev_fd; // to access the pcidev // resource mapping struct region_struct regions[6]; Bit8u devfunc; Bit8u intpin; Bit8u irq; private: static Bit32u read_handler(void *param, Bit32u address, unsigned io_len); static void write_handler(void *param, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_PCIDEV_SMF Bit32u read(void *param, Bit32u address, unsigned io_len); void write(void *param, Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/vga.cc0000644000175000017500000014501212020641505014525 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: vga.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // PCI VGA dummy adapter Copyright (C) 2002,2003 Mike Nordell // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // Standard VGA emulation + Bochs VBE support + PCI VGA interface // NOTE from the original pcivga code: // This "driver" was created for the SOLE PURPOSE of getting BeOS // to boot. It currently does NOTHING more than presenting a generic VGA // device on the PCI bus. ALL gfx in/out-put is still handled by the VGA code. // Furthermore, almost all of the PCI registers are currently acting like RAM. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "vgacore.h" #include "vga.h" #include "virt_timer.h" #define LOG_THIS theVga-> // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, do nothing. #define SET_TILE_UPDATED(xtile, ytile, value) \ do { \ if (((xtile) < BX_VGA_THIS s.num_x_tiles) && ((ytile) < BX_VGA_THIS s.num_y_tiles)) \ BX_VGA_THIS s.vga_tile_updated[(xtile)+(ytile)*BX_VGA_THIS s.num_x_tiles] = value; \ } while (0) // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, return 0. #define GET_TILE_UPDATED(xtile,ytile) \ ((((xtile) < BX_VGA_THIS s.num_x_tiles) && ((ytile) < BX_VGA_THIS s.num_y_tiles))? \ BX_VGA_THIS s.vga_tile_updated[(xtile)+(ytile)*BX_VGA_THIS s.num_x_tiles] \ : 0) bx_vga_c *theVga = NULL; int libvga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theVga = new bx_vga_c(); bx_devices.pluginVgaDevice = theVga; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theVga, BX_PLUGIN_VGA); return 0; // Success } else { return -1; } } void libvga_LTX_plugin_fini(void) { delete theVga; } bx_vga_c::bx_vga_c() : bx_vgacore_c() { put("VGA"); } bx_vga_c::~bx_vga_c() { SIM->get_bochs_root()->remove("vga"); BX_DEBUG(("Exit")); } void bx_vga_c::init_vga_extension(void) { unsigned addr; Bit16u max_xres, max_yres, max_bpp; Bit8u devfunc = 0x00; unsigned i; BX_VGA_THIS init_iohandlers(read_handler, write_handler); BX_VGA_THIS init_systemtimer(timer_handler, vga_param_handler); BX_VGA_THIS pci_enabled = DEV_is_pci_device("pcivga"); // The following is for the VBE display extension BX_VGA_THIS vbe_present = 0; BX_VGA_THIS vbe.enabled = 0; BX_VGA_THIS vbe.dac_8bit = 0; BX_VGA_THIS vbe.base_address = 0x0000; if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "vbe")) { BX_VGA_THIS put("BXVGA"); for (addr=VBE_DISPI_IOPORT_INDEX; addr<=VBE_DISPI_IOPORT_DATA; addr++) { DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7); DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7); } if (!BX_VGA_THIS pci_enabled) { BX_VGA_THIS vbe.base_address = VBE_DISPI_LFB_PHYSICAL_ADDRESS; DEV_register_memory_handlers(theVga, mem_read_handler, mem_write_handler, BX_VGA_THIS vbe.base_address, BX_VGA_THIS vbe.base_address + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES - 1); } if (BX_VGA_THIS s.memory == NULL) BX_VGA_THIS s.memory = new Bit8u[VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES]; memset(BX_VGA_THIS s.memory, 0, VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES); BX_VGA_THIS s.memsize = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES; BX_VGA_THIS vbe.cur_dispi=VBE_DISPI_ID0; BX_VGA_THIS vbe.xres=640; BX_VGA_THIS vbe.yres=480; BX_VGA_THIS vbe.bpp=8; BX_VGA_THIS vbe.bank=0; BX_VGA_THIS vbe.curindex=0; BX_VGA_THIS vbe.offset_x=0; BX_VGA_THIS vbe.offset_y=0; BX_VGA_THIS vbe.virtual_xres=640; BX_VGA_THIS vbe.virtual_yres=480; BX_VGA_THIS vbe.bpp_multiplier=1; BX_VGA_THIS vbe.virtual_start=0; BX_VGA_THIS vbe.lfb_enabled=0; BX_VGA_THIS vbe.get_capabilities=0; bx_gui->get_capabilities(&max_xres, &max_yres, &max_bpp); if (max_xres > VBE_DISPI_MAX_XRES) { BX_VGA_THIS vbe.max_xres=VBE_DISPI_MAX_XRES; } else { BX_VGA_THIS vbe.max_xres=max_xres; } if (max_yres > VBE_DISPI_MAX_YRES) { BX_VGA_THIS vbe.max_yres=VBE_DISPI_MAX_YRES; } else { BX_VGA_THIS vbe.max_yres=max_yres; } if (max_bpp > VBE_DISPI_MAX_BPP) { BX_VGA_THIS vbe.max_bpp=VBE_DISPI_MAX_BPP; } else { BX_VGA_THIS vbe.max_bpp=max_bpp; } BX_VGA_THIS s.max_xres = BX_VGA_THIS vbe.max_xres; BX_VGA_THIS s.max_yres = BX_VGA_THIS vbe.max_yres; BX_VGA_THIS vbe_present = 1; BX_VGA_THIS extension_init = 1; BX_INFO(("VBE Bochs Display Extension Enabled")); } #if BX_SUPPORT_PCI if (BX_VGA_THIS pci_enabled) { DEV_register_pci_handlers(this, &devfunc, "pcivga", "Experimental PCI VGA"); for (i = 0; i < 256; i++) { BX_VGA_THIS pci_conf[i] = 0x0; } // readonly registers static const struct init_vals_t { unsigned addr; unsigned char val; } init_vals[] = { // Note that the values for vendor and device id are selected at random! // There might actually be "real" values for "experimental" vendor and // device that should be used! { 0x00, 0x34 }, { 0x01, 0x12 }, // 0x1234 - experimental vendor { 0x02, 0x11 }, { 0x03, 0x11 }, // 0x1111 - experimental device { 0x0a, 0x00 }, // class_sub VGA controller { 0x0b, 0x03 }, // class_base display { 0x0e, 0x00 } // header_type_generic }; for (i = 0; i < sizeof(init_vals) / sizeof(*init_vals); ++i) { BX_VGA_THIS pci_conf[init_vals[i].addr] = init_vals[i].val; } if (BX_VGA_THIS vbe_present) { BX_VGA_THIS pci_conf[0x10] = 0x08; BX_VGA_THIS pci_base_address[0] = 0; } BX_VGA_THIS pci_rom_address = 0; BX_VGA_THIS load_pci_rom(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr()); } #endif #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("vga", this); #endif } void bx_vga_c::reset(unsigned type) { #if BX_SUPPORT_PCI if (BX_VGA_THIS pci_enabled) { static const struct reset_vals_t { unsigned addr; unsigned char val; } reset_vals[] = { { 0x04, 0x03 }, { 0x05, 0x00 }, // command_io + command_mem { 0x06, 0x00 }, { 0x07, 0x02 } // status_devsel_medium }; for (unsigned i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { BX_VGA_THIS pci_conf[reset_vals[i].addr] = reset_vals[i].val; } } #endif } void bx_vga_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "vga", "VGA Adapter State"); bx_vgacore_c::register_state(list); #if BX_SUPPORT_PCI if (BX_VGA_THIS pci_enabled) { register_pci_state(list); } #endif // register state for Bochs VBE if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "vbe")) { bx_list_c *vbe = new bx_list_c(list, "vbe"); new bx_shadow_num_c(vbe, "cur_dispi", &BX_VGA_THIS vbe.cur_dispi, BASE_HEX); new bx_shadow_num_c(vbe, "xres", &BX_VGA_THIS vbe.xres); new bx_shadow_num_c(vbe, "yres", &BX_VGA_THIS vbe.yres); new bx_shadow_num_c(vbe, "bpp", &BX_VGA_THIS vbe.bpp); new bx_shadow_num_c(vbe, "bank", &BX_VGA_THIS vbe.bank); new bx_shadow_bool_c(vbe, "enabled", &BX_VGA_THIS vbe.enabled); new bx_shadow_num_c(vbe, "curindex", &BX_VGA_THIS vbe.curindex); new bx_shadow_num_c(vbe, "visible_screen_size", &BX_VGA_THIS vbe.visible_screen_size); new bx_shadow_num_c(vbe, "offset_x", &BX_VGA_THIS vbe.offset_x); new bx_shadow_num_c(vbe, "offset_y", &BX_VGA_THIS vbe.offset_y); new bx_shadow_num_c(vbe, "virtual_xres", &BX_VGA_THIS vbe.virtual_xres); new bx_shadow_num_c(vbe, "virtual_yres", &BX_VGA_THIS vbe.virtual_yres); new bx_shadow_num_c(vbe, "virtual_start", &BX_VGA_THIS vbe.virtual_start); new bx_shadow_num_c(vbe, "bpp_multiplier", &BX_VGA_THIS vbe.bpp_multiplier); new bx_shadow_bool_c(vbe, "lfb_enabled", &BX_VGA_THIS vbe.lfb_enabled); new bx_shadow_bool_c(vbe, "get_capabilities", &BX_VGA_THIS vbe.get_capabilities); new bx_shadow_bool_c(vbe, "dac_8bit", &BX_VGA_THIS vbe.dac_8bit); } } void bx_vga_c::after_restore_state(void) { #if BX_SUPPORT_PCI if (BX_VGA_THIS pci_enabled) { if (BX_VGA_THIS vbe_present) { if (BX_VGA_THIS vbe_set_base_addr(&BX_VGA_THIS pci_base_address[0], &BX_VGA_THIS pci_conf[0x10])) { BX_INFO(("new base address: 0x%08x", BX_VGA_THIS pci_base_address[0])); } } if (DEV_pci_set_base_mem(this, mem_read_handler, mem_write_handler, &BX_VGA_THIS pci_rom_address, &BX_VGA_THIS pci_conf[0x30], BX_VGA_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_VGA_THIS pci_rom_address)); } } #endif if (BX_VGA_THIS vbe.enabled) { bx_gui->dimension_update(BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, 0, 0, BX_VGA_THIS vbe.bpp); } bx_vgacore_c::after_restore_state(); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_vga_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if BX_USE_VGA_SMF == 0 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; class_ptr->write(address, value, io_len, 0); #else UNUSED(this_ptr); theVga->write(address, value, io_len, 0); #endif } #if BX_USE_VGA_SMF void bx_vga_c::write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { UNUSED(this_ptr); theVga->write(address, value, io_len, 1); } #endif void bx_vga_c::write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log) { if (io_len == 2) { #if BX_USE_VGA_SMF bx_vga_c::write_handler_no_log(0, address, value & 0xff, 1); bx_vga_c::write_handler_no_log(0, address+1, (value >> 8) & 0xff, 1); #else bx_vga_c::write(address, value & 0xff, 1, 1); bx_vga_c::write(address+1, (value >> 8) & 0xff, 1, 1); #endif return; } if ((address >= 0x03b0) && (address <= 0x03bf) && (BX_VGA_THIS s.misc_output.color_emulation)) return; if ((address >= 0x03d0) && (address <= 0x03df) && (BX_VGA_THIS s.misc_output.color_emulation==0)) return; switch (address) { case 0x03b5: /* CRTC Registers (monochrome emulation modes) */ case 0x03d5: /* CRTC Registers (color emulation modes) */ if (BX_VGA_THIS s.CRTC.address > 0x18) { BX_DEBUG(("write: invalid CRTC register 0x%02x ignored", (unsigned) BX_VGA_THIS s.CRTC.address)); return; } if (value != BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]) { switch (BX_VGA_THIS s.CRTC.address) { case 0x13: case 0x14: case 0x17: if (!BX_VGA_THIS vbe.enabled || (BX_VGA_THIS vbe.bpp == VBE_DISPI_BPP_4)) { // Line offset change bx_vgacore_c::write(address, value, io_len, no_log); } else { BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] = value; } break; default: bx_vgacore_c::write(address, value, io_len, no_log); } } break; default: bx_vgacore_c::write(address, value, io_len, no_log); } } Bit64s bx_vga_c::vga_param_handler(bx_param_c *param, int set, Bit64s val) { Bit32u interval; // handler for runtime parameter 'vga: update_freq' if (set) { interval = (Bit32u)(1000000 / val); BX_INFO(("Changing timer interval to %d", interval)); BX_VGA_THIS timer_handler(theVga); bx_virt_timer.activate_timer(BX_VGA_THIS timer_id, interval, 1); if (interval < 300000) { BX_VGA_THIS s.blink_counter = 300000 / (unsigned)interval; } else { BX_VGA_THIS s.blink_counter = 1; } } return val; } void bx_vga_c::timer_handler(void *this_ptr) { #if BX_USE_VGA_SMF == 0 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; class_ptr->timer(); } void bx_vga_c::timer(void) { #else UNUSED(this_ptr); #endif update(); bx_gui->flush(); } void bx_vga_c::update(void) { unsigned iHeight, iWidth; if (BX_VGA_THIS vbe.enabled) { /* no screen update necessary */ if ((BX_VGA_THIS s.vga_mem_updated==0) && BX_VGA_THIS s.graphics_ctrl.graphics_alpha) return; /* skip screen update when vga/video is disabled or the sequencer is in reset mode */ if (!BX_VGA_THIS s.vga_enabled || !BX_VGA_THIS s.attribute_ctrl.video_enabled || !BX_VGA_THIS s.sequencer.reset2 || !BX_VGA_THIS s.sequencer.reset1 || (BX_VGA_THIS s.sequencer.reg1 & 0x20)) return; /* skip screen update if the vertical retrace is in progress (using 72 Hz vertical frequency) */ if ((bx_pc_system.time_usec() % 13888) < 70) return; if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) { // specific VBE code display update code unsigned pitch; unsigned xc, yc, xti, yti; unsigned r, c, w, h; int i; unsigned long red, green, blue, colour; Bit8u * vid_ptr, * vid_ptr2; Bit8u * tile_ptr, * tile_ptr2; bx_svga_tileinfo_t info; Bit8u dac_size = BX_VGA_THIS vbe.dac_8bit ? 8 : 6; iWidth=BX_VGA_THIS vbe.xres; iHeight=BX_VGA_THIS vbe.yres; pitch = BX_VGA_THIS s.line_offset; Bit8u *disp_ptr = &BX_VGA_THIS s.memory[BX_VGA_THIS vbe.virtual_start]; if (bx_gui->graphics_tile_info(&info)) { if (info.is_indexed) { switch (BX_VGA_THIS vbe.bpp) { case 4: case 15: case 16: case 24: case 32: BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays")); break; case 8: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i); } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = (Bit8u)(colour >> i); } } } vid_ptr += pitch; tile_ptr += info.pitch; } bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; } } else { switch (BX_VGA_THIS vbe.bpp) { case 4: BX_ERROR(("cannot draw 4bpp SVGA")); break; case 8: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i); } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = (Bit8u)(colour >> i); } } } vid_ptr += pitch; tile_ptr += info.pitch; } bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 15: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i); } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = (Bit8u)(colour >> i); } } } vid_ptr += pitch; tile_ptr += info.pitch; } bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 16: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i); } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = (Bit8u)(colour >> i); } } } vid_ptr += pitch; tile_ptr += info.pitch; } bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 24: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i); } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = (Bit8u)(colour >> i); } } } vid_ptr += pitch; tile_ptr += info.pitch; } bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 32: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i); } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = (Bit8u)(colour >> i); } } } vid_ptr += pitch; tile_ptr += info.pitch; } bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; } } BX_VGA_THIS s.last_xres = iWidth; BX_VGA_THIS s.last_yres = iHeight; BX_VGA_THIS s.vga_mem_updated = 0; } else { BX_PANIC(("cannot get svga tile info")); } } else { unsigned r, c, x, y; unsigned xc, yc, xti, yti; Bit8u *plane[4]; BX_VGA_THIS determine_screen_dimensions(&iHeight, &iWidth); if ((iWidth != BX_VGA_THIS s.last_xres) || (iHeight != BX_VGA_THIS s.last_yres) || (BX_VGA_THIS s.last_bpp > 8)) { bx_gui->dimension_update(iWidth, iHeight); BX_VGA_THIS s.last_xres = iWidth; BX_VGA_THIS s.last_yres = iHeight; BX_VGA_THIS s.last_bpp = 8; } plane[0] = &BX_VGA_THIS s.memory[0<>= 1; for (c=0; cgraphics_tile_update(BX_VGA_THIS s.tile, xc, yc); } } } } } else { BX_VGA_THIS bx_vgacore_c::update(); } } bx_bool bx_vga_c::mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { *data_ptr = theVga->mem_read(addr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } Bit8u bx_vga_c::mem_read(bx_phy_address addr) { #if BX_SUPPORT_PCI if ((BX_VGA_THIS pci_enabled) && (BX_VGA_THIS pci_rom_size > 0)) { Bit32u mask = (BX_VGA_THIS pci_rom_size - 1); if ((addr & ~mask) == BX_VGA_THIS pci_rom_address) { if (BX_VGA_THIS pci_conf[0x30] & 0x01) { return BX_VGA_THIS pci_rom[addr & mask]; } else { return 0xff; } } } #endif // if in a vbe enabled mode, read from the vbe_memory if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4)) { return vbe_mem_read(addr); } else if ((BX_VGA_THIS vbe.base_address != 0) && (addr >= BX_VGA_THIS vbe.base_address)) { return 0xff; } return bx_vgacore_c::mem_read(addr); } bx_bool bx_vga_c::mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { theVga->mem_write(addr, *data_ptr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } void bx_vga_c::mem_write(bx_phy_address addr, Bit8u value) { // if in a vbe enabled mode, write to the vbe_memory if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4)) { vbe_mem_write(addr, value); return; } else if ((BX_VGA_THIS vbe.base_address != 0) && (addr >= BX_VGA_THIS vbe.base_address)) { return; } bx_vgacore_c::mem_write(addr, value); } int bx_vga_c::get_snapshot_mode() { if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp >= 8)) { return BX_GUI_SNAPSHOT_GFX; } else { return bx_vgacore_c::get_snapshot_mode(); } } Bit32u bx_vga_c::get_gfx_snapshot(Bit8u **snapshot_ptr, Bit8u **palette_ptr, unsigned *iHeight, unsigned *iWidth, unsigned *iDepth) { Bit32u len, len1; unsigned i, shift; Bit8u *dst_ptr, *src_ptr; if ((BX_VGA_THIS vbe.enabled) && (BX_VGA_THIS vbe.bpp >= 8)) { *iHeight = BX_VGA_THIS vbe.yres; *iWidth = BX_VGA_THIS vbe.xres; *iDepth = BX_VGA_THIS vbe.bpp; len1 = BX_VGA_THIS vbe.xres * BX_VGA_THIS vbe.bpp_multiplier; len = len1 * BX_VGA_THIS vbe.yres; *snapshot_ptr = (Bit8u*)malloc(len); if (snapshot_ptr == NULL) return 0; src_ptr = BX_VGA_THIS s.memory + BX_VGA_THIS vbe.virtual_start; dst_ptr = *snapshot_ptr; for (i = 0; i < BX_VGA_THIS vbe.yres; i++) { memcpy(dst_ptr, src_ptr, len1); src_ptr += BX_VGA_THIS s.line_offset; dst_ptr += len1; } if (*iDepth == 8) { if (BX_VGA_THIS vbe.dac_8bit) { shift = 0; } else { shift = 2; } BX_VGA_THIS get_dac_palette(palette_ptr, shift); } return len; } else { return bx_vgacore_c::get_gfx_snapshot(snapshot_ptr, palette_ptr, iHeight, iWidth, iDepth); } } void bx_vga_c::redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height) { unsigned xti, yti, xt0, xt1, yt0, yt1, xmax, ymax; if (width == 0 || height == 0) { return; } if (BX_VGA_THIS vbe.enabled) { BX_VGA_THIS s.vga_mem_updated = 1; xmax = BX_VGA_THIS vbe.xres; ymax = BX_VGA_THIS vbe.yres; xt0 = x0 / X_TILESIZE; yt0 = y0 / Y_TILESIZE; if (x0 < xmax) { xt1 = (x0 + width - 1) / X_TILESIZE; } else { xt1 = (xmax - 1) / X_TILESIZE; } if (y0 < ymax) { yt1 = (y0 + height - 1) / Y_TILESIZE; } else { yt1 = (ymax - 1) / Y_TILESIZE; } for (yti=yt0; yti<=yt1; yti++) { for (xti=xt0; xti<=xt1; xti++) { SET_TILE_UPDATED(xti, yti, 1); } } } else { bx_vgacore_c::redraw_area(x0, y0, width, height); } } bx_bool bx_vga_c::vbe_set_base_addr(Bit32u *addr, Bit8u *pci_conf) { if (DEV_pci_set_base_mem(BX_VGA_THIS_PTR, mem_read_handler, mem_write_handler, addr, pci_conf, VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)) { BX_VGA_THIS vbe.base_address = *addr; return 1; } return 0; } Bit8u BX_CPP_AttrRegparmN(1) bx_vga_c::vbe_mem_read(bx_phy_address addr) { Bit32u offset; if (addr >= BX_VGA_THIS vbe.base_address) { // LFB read offset = (Bit32u)(addr - BX_VGA_THIS vbe.base_address); } else { // banked mode read offset = (Bit32u)(BX_VGA_THIS vbe.bank*65536 + addr - 0xA0000); } // check for out of memory read if (offset > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES) return 0; return (BX_VGA_THIS s.memory[offset]); } void BX_CPP_AttrRegparmN(2) bx_vga_c::vbe_mem_write(bx_phy_address addr, Bit8u value) { Bit32u offset; unsigned x_tileno, y_tileno; if (BX_VGA_THIS vbe.lfb_enabled) { if (addr >= BX_VGA_THIS vbe.base_address) { // LFB write offset = (Bit32u)(addr - BX_VGA_THIS vbe.base_address); } else { // banked mode write while in LFB mode -> ignore return; } } else { if (addr < BX_VGA_THIS vbe.base_address) { // banked mode write offset = (Bit32u)(BX_VGA_THIS vbe.bank*65536 + (addr - 0xA0000)); } else { // LFB write while in banked mode -> ignore return; } } // check for out of memory write if (offset < VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES) { BX_VGA_THIS s.memory[offset]=value; } else { // make sure we don't flood the logfile static int count=0; if (count<100) { count ++; BX_INFO(("VBE_mem_write out of video memory write at %x",offset)); } } offset-=BX_VGA_THIS vbe.virtual_start; // only update the UI when writing 'onscreen' if (offset < BX_VGA_THIS vbe.visible_screen_size) { y_tileno = ((offset / BX_VGA_THIS vbe.bpp_multiplier) / BX_VGA_THIS vbe.virtual_xres) / Y_TILESIZE; x_tileno = ((offset / BX_VGA_THIS vbe.bpp_multiplier) % BX_VGA_THIS vbe.virtual_xres) / X_TILESIZE; if ((y_tileno < BX_VGA_THIS s.num_y_tiles) && (x_tileno < BX_VGA_THIS s.num_x_tiles)) { BX_VGA_THIS s.vga_mem_updated = 1; SET_TILE_UPDATED (x_tileno, y_tileno, 1); } } } Bit32u bx_vga_c::vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if BX_USE_VGA_SMF == 0 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; return class_ptr->vbe_read(address, io_len); } Bit32u bx_vga_c::vbe_read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // BX_USE_VGA_SMF == 0 Bit16u retval; // BX_INFO(("VBE_read %x (len %x)", address, io_len)); if (address==VBE_DISPI_IOPORT_INDEX) { // index register return (Bit32u) BX_VGA_THIS vbe.curindex; } else { // data register read switch (BX_VGA_THIS vbe.curindex) { case VBE_DISPI_INDEX_ID: // Display Interface ID check return BX_VGA_THIS vbe.cur_dispi; case VBE_DISPI_INDEX_XRES: // x resolution if (BX_VGA_THIS vbe.get_capabilities) { return BX_VGA_THIS vbe.max_xres; } else { return BX_VGA_THIS vbe.xres; } case VBE_DISPI_INDEX_YRES: // y resolution if (BX_VGA_THIS vbe.get_capabilities) { return BX_VGA_THIS vbe.max_yres; } else { return BX_VGA_THIS vbe.yres; } case VBE_DISPI_INDEX_BPP: // bpp if (BX_VGA_THIS vbe.get_capabilities) { return BX_VGA_THIS vbe.max_bpp; } else { return BX_VGA_THIS vbe.bpp; } case VBE_DISPI_INDEX_ENABLE: // vbe enabled retval = BX_VGA_THIS vbe.enabled; if (BX_VGA_THIS vbe.get_capabilities) retval |= VBE_DISPI_GETCAPS; if (BX_VGA_THIS vbe.dac_8bit) retval |= VBE_DISPI_8BIT_DAC; return retval; case VBE_DISPI_INDEX_BANK: // current bank return BX_VGA_THIS vbe.bank; case VBE_DISPI_INDEX_X_OFFSET: return BX_VGA_THIS vbe.offset_x; case VBE_DISPI_INDEX_Y_OFFSET: return BX_VGA_THIS vbe.offset_y; case VBE_DISPI_INDEX_VIRT_WIDTH: return BX_VGA_THIS vbe.virtual_xres; case VBE_DISPI_INDEX_VIRT_HEIGHT: return BX_VGA_THIS vbe.virtual_yres; case VBE_DISPI_INDEX_VIDEO_MEMORY_64K: return (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB >> 6); default: BX_PANIC(("VBE unknown data read index 0x%x",BX_VGA_THIS vbe.curindex)); break; } } BX_PANIC(("VBE_read shouldn't reach this")); return 0; /* keep compiler happy */ } void bx_vga_c::vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if BX_USE_VGA_SMF == 0 bx_vga_c *class_ptr = (bx_vga_c *) this_ptr; class_ptr->vbe_write(address, value, io_len); } Bit32u bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif bx_bool new_vbe_8bit_dac; bx_bool needs_update = 0; unsigned i; // BX_INFO(("VBE_write %x = %x (len %x)", address, value, io_len)); switch(address) { // index register case VBE_DISPI_IOPORT_INDEX: BX_VGA_THIS vbe.curindex = (Bit16u) value; break; // data register // FIXME: maybe do some 'sanity' checks on received data? case VBE_DISPI_IOPORT_DATA: switch (BX_VGA_THIS vbe.curindex) { case VBE_DISPI_INDEX_ID: // Display Interface ID check { if ((value == VBE_DISPI_ID0) || (value == VBE_DISPI_ID1) || (value == VBE_DISPI_ID2) || (value == VBE_DISPI_ID3) || (value == VBE_DISPI_ID4) || (value == VBE_DISPI_ID5)) { // allow backwards compatible with previous dispi bioses BX_VGA_THIS vbe.cur_dispi=value; } else { BX_PANIC(("VBE unknown Display Interface %x", value)); } // make sure we don't flood the logfile static int count=0; if (count < 100) { count++; BX_INFO(("VBE known Display Interface %x", value)); } } break; case VBE_DISPI_INDEX_XRES: // set xres { // check that we don't set xres during vbe enabled if (!BX_VGA_THIS vbe.enabled) { // check for within max xres range if (value <= VBE_DISPI_MAX_XRES) { BX_VGA_THIS vbe.xres=(Bit16u) value; BX_INFO(("VBE set xres (%d)", value)); } else { BX_INFO(("VBE set xres more then max xres (%d)", value)); } } else { BX_ERROR(("VBE set xres during vbe enabled!")); } } break; case VBE_DISPI_INDEX_YRES: // set yres { // check that we don't set yres during vbe enabled if (!BX_VGA_THIS vbe.enabled) { // check for within max yres range if (value <= VBE_DISPI_MAX_YRES) { BX_VGA_THIS vbe.yres=(Bit16u) value; BX_INFO(("VBE set yres (%d)", value)); } else { BX_INFO(("VBE set yres more then max yres (%d)", value)); } } else { BX_ERROR(("VBE set yres during vbe enabled!")); } } break; case VBE_DISPI_INDEX_BPP: // set bpp { // check that we don't set bpp during vbe enabled if (!BX_VGA_THIS vbe.enabled) { // for backward compatiblity if (value == 0) value = VBE_DISPI_BPP_8; // check for correct bpp range if ((value == VBE_DISPI_BPP_4) || (value == VBE_DISPI_BPP_8) || (value == VBE_DISPI_BPP_15) || (value == VBE_DISPI_BPP_16) || (value == VBE_DISPI_BPP_24) || (value == VBE_DISPI_BPP_32)) { BX_VGA_THIS vbe.bpp=(Bit16u) value; BX_INFO(("VBE set bpp (%d)", value)); } else { BX_ERROR(("VBE set bpp with unknown bpp (%d)", value)); } } else { BX_ERROR(("VBE set bpp during vbe enabled!")); } } break; case VBE_DISPI_INDEX_BANK: // set bank { value=value & 0xff; // FIXME lobyte = vbe bank A? unsigned divider = (BX_VGA_THIS vbe.bpp!=VBE_DISPI_BPP_4)?64:256; // check for max bank nr if (value < (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB / divider)) { if (!BX_VGA_THIS vbe.lfb_enabled) { BX_DEBUG(("VBE set bank to %d", value)); BX_VGA_THIS vbe.bank = value; BX_VGA_THIS s.plane_offset = (BX_VGA_THIS vbe.bank << 16); } else { BX_ERROR(("VBE set bank in LFB mode ignored")); } } else { BX_ERROR(("VBE set invalid bank (%d)", value)); } } break; case VBE_DISPI_INDEX_ENABLE: // enable video { if ((value & VBE_DISPI_ENABLED) && !BX_VGA_THIS vbe.enabled) { unsigned depth=0; // setup virtual resolution to be the same as current reso BX_VGA_THIS vbe.virtual_yres=BX_VGA_THIS vbe.yres; BX_VGA_THIS vbe.virtual_xres=BX_VGA_THIS vbe.xres; // reset offset BX_VGA_THIS vbe.offset_x=0; BX_VGA_THIS vbe.offset_y=0; BX_VGA_THIS vbe.virtual_start=0; switch((BX_VGA_THIS vbe.bpp)) { // Default pixel sizes case VBE_DISPI_BPP_8: BX_VGA_THIS vbe.bpp_multiplier = 1; BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres; depth=8; break; case VBE_DISPI_BPP_4: BX_VGA_THIS vbe.bpp_multiplier = 1; BX_VGA_THIS s.line_offset = (BX_VGA_THIS vbe.virtual_xres >> 3); depth=4; break; case VBE_DISPI_BPP_15: BX_VGA_THIS vbe.bpp_multiplier = 2; BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * 2; depth=15; break; case VBE_DISPI_BPP_16: BX_VGA_THIS vbe.bpp_multiplier = 2; BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * 2; depth=16; break; case VBE_DISPI_BPP_24: BX_VGA_THIS vbe.bpp_multiplier = 3; BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * 3; depth=24; break; case VBE_DISPI_BPP_32: BX_VGA_THIS vbe.bpp_multiplier = 4; BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres << 2; depth=32; break; } BX_VGA_THIS vbe.visible_screen_size = BX_VGA_THIS s.line_offset * BX_VGA_THIS vbe.yres; BX_INFO(("VBE enabling x %d, y %d, bpp %d, %u bytes visible", BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, BX_VGA_THIS vbe.bpp, BX_VGA_THIS vbe.visible_screen_size)); if (depth > 4) { BX_VGA_THIS vbe.lfb_enabled = (bx_bool)(value & VBE_DISPI_LFB_ENABLED); if ((value & VBE_DISPI_NOCLEARMEM) == 0) { memset(BX_VGA_THIS s.memory, 0, BX_VGA_THIS vbe.visible_screen_size); } bx_gui->dimension_update(BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, 0, 0, depth); BX_VGA_THIS s.last_bpp = depth; } else { BX_VGA_THIS s.plane_shift = VBE_DISPI_4BPP_PLANE_SHIFT; BX_VGA_THIS s.plane_offset = (BX_VGA_THIS vbe.bank << 16); } } else if (((value & VBE_DISPI_ENABLED) == 0) && BX_VGA_THIS vbe.enabled) { BX_INFO(("VBE disabling")); BX_VGA_THIS vbe.lfb_enabled = 0; BX_VGA_THIS s.plane_shift = 16; BX_VGA_THIS s.plane_offset = 0; } BX_VGA_THIS vbe.enabled = (bx_bool)(value & VBE_DISPI_ENABLED); BX_VGA_THIS vbe.get_capabilities = (bx_bool)((value & VBE_DISPI_GETCAPS) != 0); new_vbe_8bit_dac = (bx_bool)((value & VBE_DISPI_8BIT_DAC) != 0); if (new_vbe_8bit_dac != BX_VGA_THIS vbe.dac_8bit) { if (new_vbe_8bit_dac) { for (i=0; i<256; i++) { BX_VGA_THIS s.pel.data[i].red <<= 2; BX_VGA_THIS s.pel.data[i].green <<= 2; BX_VGA_THIS s.pel.data[i].blue <<= 2; } BX_INFO(("DAC in 8 bit mode")); } else { for (i=0; i<256; i++) { BX_VGA_THIS s.pel.data[i].red >>= 2; BX_VGA_THIS s.pel.data[i].green >>= 2; BX_VGA_THIS s.pel.data[i].blue >>= 2; } BX_INFO(("DAC in standard mode")); } BX_VGA_THIS vbe.dac_8bit = new_vbe_8bit_dac; BX_VGA_THIS s.dac_shift = new_vbe_8bit_dac ? 0 : 2; needs_update = 1; } } break; case VBE_DISPI_INDEX_X_OFFSET: { BX_DEBUG(("VBE offset x %d", value)); BX_VGA_THIS vbe.offset_x=(Bit16u)value; BX_VGA_THIS vbe.virtual_start = BX_VGA_THIS vbe.offset_y * BX_VGA_THIS s.line_offset; if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) { BX_VGA_THIS vbe.virtual_start += (BX_VGA_THIS vbe.offset_x * BX_VGA_THIS vbe.bpp_multiplier); } else { BX_VGA_THIS vbe.virtual_start += (BX_VGA_THIS vbe.offset_x >> 3); } needs_update = 1; } break; case VBE_DISPI_INDEX_Y_OFFSET: { BX_DEBUG(("VBE offset y %d", value)); Bit32u new_screen_start = value * BX_VGA_THIS s.line_offset; if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) { if ((new_screen_start + BX_VGA_THIS vbe.visible_screen_size) > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES) { BX_PANIC(("VBE offset y %d out of bounds", value)); break; } new_screen_start += (BX_VGA_THIS vbe.offset_x * BX_VGA_THIS vbe.bpp_multiplier); } else { if ((new_screen_start + BX_VGA_THIS vbe.visible_screen_size) > (VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES / 4)) { BX_PANIC(("VBE offset y %d out of bounds", value)); break; } new_screen_start += (BX_VGA_THIS vbe.offset_x >> 3); } BX_VGA_THIS vbe.virtual_start = new_screen_start; BX_VGA_THIS vbe.offset_y = (Bit16u)value; needs_update = 1; } break; case VBE_DISPI_INDEX_VIRT_WIDTH: { BX_INFO(("VBE requested virtual width %d", value)); // calculate virtual width & height dimensions // req: // virt_width > xres // virt_height >=yres // virt_width*virt_height < MAX_VIDEO_MEMORY // basicly 2 situations // situation 1: // MAX_VIDEO_MEMORY / virt_width >= yres // adjust result height // else // adjust result width based upon virt_height=yres Bit16u new_width=value; Bit16u new_height; if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) { new_height=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES / BX_VGA_THIS vbe.bpp_multiplier) / new_width; } else { new_height=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES * 2) / new_width; } if (new_height >=BX_VGA_THIS vbe.yres) { // we have a decent virtual width & new_height BX_INFO(("VBE decent virtual height %d",new_height)); } else { // no decent virtual height: adjust width & height new_height=BX_VGA_THIS vbe.yres; if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) { new_width=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES / BX_VGA_THIS vbe.bpp_multiplier) / new_height; } else { new_width=(VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES * 2) / new_height; } BX_INFO(("VBE recalc virtual width %d height %d",new_width, new_height)); } BX_VGA_THIS vbe.virtual_xres=new_width; BX_VGA_THIS vbe.virtual_yres=new_height; if (BX_VGA_THIS vbe.bpp != VBE_DISPI_BPP_4) { BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres * BX_VGA_THIS vbe.bpp_multiplier; } else { BX_VGA_THIS s.line_offset = BX_VGA_THIS vbe.virtual_xres >> 3; } BX_VGA_THIS vbe.visible_screen_size = BX_VGA_THIS s.line_offset * BX_VGA_THIS vbe.yres; } break; case VBE_DISPI_INDEX_VIRT_HEIGHT: BX_ERROR(("VBE: write to virtual height register ignored")); break; default: BX_ERROR(("VBE: write unsupported register at index 0x%x",BX_VGA_THIS vbe.curindex)); break; } if (needs_update) { BX_VGA_THIS s.vga_mem_updated = 1; for (unsigned xti = 0; xti < BX_VGA_THIS s.num_x_tiles; xti++) { for (unsigned yti = 0; yti < BX_VGA_THIS s.num_y_tiles; yti++) { SET_TILE_UPDATED (xti, yti, 1); } } } break; } // end switch address } #if BX_SUPPORT_PCI // pci configuration space read callback handler Bit32u bx_vga_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x14) && (address < 0x30)) return; if (address == 0x30) { value = value & 0xfffffc01; romaddr_change = 1; } for (unsigned i = 0; i < io_len; i++) { unsigned write_addr = address + i; Bit8u old_value = BX_VGA_THIS pci_conf[write_addr]; Bit8u new_value = (Bit8u)(value & 0xff); switch (write_addr) { case 0x04: // disallowing write to command case 0x06: // disallowing write to status lo-byte (is that expected?) break; case 0x10: // base address #0 new_value = (new_value & 0xf0) | (old_value & 0x0f); case 0x11: case 0x12: case 0x13: if (BX_VGA_THIS vbe_present) { baseaddr_change |= (old_value != new_value); } else { break; } default: BX_VGA_THIS pci_conf[write_addr] = new_value; } value >>= 8; } if (baseaddr_change) { if (BX_VGA_THIS vbe_set_base_addr(&BX_VGA_THIS pci_base_address[0], &BX_VGA_THIS pci_conf[0x10])) { BX_INFO(("new base address: 0x%08x", BX_VGA_THIS pci_base_address[0])); } } if (romaddr_change) { if (DEV_pci_set_base_mem(this, mem_read_handler, mem_write_handler, &BX_VGA_THIS pci_rom_address, &BX_VGA_THIS pci_conf[0x30], BX_VGA_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_VGA_THIS pci_rom_address)); } } } #endif #if BX_DEBUGGER void bx_vga_c::debug_dump(int argc, char **argv) { if (BX_VGA_THIS vbe.enabled) { dbg_printf("Bochs VGA/VBE adapter\n\n"); dbg_printf("current mode : %u x %u x %u\n", BX_VGA_THIS vbe.xres, BX_VGA_THIS vbe.yres, BX_VGA_THIS vbe.bpp); } else { bx_vgacore_c::debug_dump(); } if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif bochs-2.6/iodev/network/0000755000175000017500000000000012020641503015125 5ustar guillemguillembochs-2.6/iodev/network/eth_tuntap.cc0000644000175000017500000002702212020641503017612 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_tuntap.cc 10975 2012-01-14 17:03:00Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // eth_tuntap.cc - TUN/TAP interface by Renzo Davoli // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING && BX_NETMOD_TUNTAP #define LOG_THIS netdev-> #include #include #include #ifndef __APPLE__ #include #endif #include #include #ifdef __linux__ #include #else #include #endif #include #include #include #ifdef __linux__ #include #include #include #else #include #if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__NetBSD__) #include #endif #endif #include #include #include #define BX_ETH_TUNTAP_LOGGING 0 int tun_alloc(char *dev); // // Define the class. This is private to this module // class bx_tuntap_pktmover_c : public eth_pktmover_c { public: bx_tuntap_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: int fd; int rx_timer_index; static void rx_timer_handler(void *); void rx_timer (); Bit8u guest_macaddr[6]; #if BX_ETH_TUNTAP_LOGGING FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt; #endif }; // // Define the static class that registers the derived pktmover class, // and allocates one on request. // class bx_tuntap_locator_c : public eth_locator_c { public: bx_tuntap_locator_c(void) : eth_locator_c("tuntap") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_tuntap_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_tuntap_match; // // Define the methods for the bx_tuntap_pktmover derived class // // the constructor bx_tuntap_pktmover_c::bx_tuntap_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { int flags; this->netdev = dev; #ifdef NEVERDEF if (strncmp (netif, "tun", 3) != 0) { BX_PANIC(("eth_tuntap: interface name (%s) must be tun", netif)); } char filename[BX_PATHNAME_LEN]; sprintf(filename, "/dev/net/%s", netif); // check if the TUN/TAP devices is running, and turn on ARP. This is based // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/ int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { BX_PANIC(("socket creation: %s", strerror(errno))); return; } struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name)); if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { BX_PANIC(("SIOCGIFFLAGS on %s: %s", netif, strerror (errno))); close(sock); return; } if (!(ifr.ifr_flags & IFF_RUNNING)) { BX_PANIC(("%s device is not running", netif)); close(sock); return; } if ((ifr.ifr_flags & IFF_NOARP)) { BX_INFO(("turn on ARP for %s device", netif)); ifr.ifr_flags &= ~IFF_NOARP; if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { BX_PANIC(("SIOCSIFFLAGS: %s", strerror(errno))); close(sock); return; } } close(sock); fd = open (filename, O_RDWR); #endif char intname[IFNAMSIZ]; strcpy(intname,netif); fd=tun_alloc(intname); if (fd < 0) { BX_PANIC(("open failed on %s: %s", netif, strerror (errno))); return; } /* set O_ASYNC flag so that we can poll with read() */ if ((flags = fcntl(fd, F_GETFL)) < 0) { BX_PANIC(("getflags on tun device: %s", strerror (errno))); } flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { BX_PANIC(("set tun device flags: %s", strerror (errno))); } BX_INFO(("tuntap network driver: opened %s device", netif)); /* Execute the configuration script */ if((script != NULL) && (strcmp(script, "") != 0) && (strcmp(script, "none") != 0)) { if (execute_script(this->netdev, script, intname) < 0) BX_ERROR(("execute script '%s' on %s failed", script, intname)); } // Start the rx poll this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, 1, 1, "eth_tuntap"); // continuous, active this->rxh = rxh; this->rxstat = rxstat; memcpy(&guest_macaddr[0], macaddr, 6); #if BX_ETH_TUNTAP_LOGGING // eventually Bryce wants txlog to dump in pcap format so that // tcpdump -r FILE can read it and interpret packets. txlog = fopen("ne2k-tx.log", "wb"); if (!txlog) BX_PANIC(("open ne2k-tx.log failed")); txlog_txt = fopen("ne2k-txdump.txt", "wb"); if (!txlog_txt) BX_PANIC(("open ne2k-txdump.txt failed")); fprintf(txlog_txt, "tuntap packetmover readable log file\n"); fprintf(txlog_txt, "net IF = %s\n", netif); fprintf(txlog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(txlog_txt, "\n--\n"); fflush(txlog_txt); rxlog = fopen("ne2k-rx.log", "wb"); if (!rxlog) BX_PANIC(("open ne2k-rx.log failed")); rxlog_txt = fopen("ne2k-rxdump.txt", "wb"); if (!rxlog_txt) BX_PANIC(("open ne2k-rxdump.txt failed")); fprintf(rxlog_txt, "tuntap packetmover readable log file\n"); fprintf(rxlog_txt, "net IF = %s\n", netif); fprintf(rxlog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(rxlog_txt, "\n--\n"); fflush(rxlog_txt); #endif } void bx_tuntap_pktmover_c::sendpkt(void *buf, unsigned io_len) { #ifdef __APPLE__ //FIXME unsigned int size = write (fd, (char*)buf+14, io_len-14); if (size != io_len-14) { BX_PANIC(("write on tuntap device: %s", strerror (errno))); } else { BX_DEBUG(("wrote %d bytes on tuntap - 14 bytes Ethernet header", io_len)); } #elif NEVERDEF Bit8u txbuf[BX_PACKET_BUFSIZE]; txbuf[0] = 0; txbuf[1] = 0; memcpy (txbuf+2, buf, io_len); unsigned int size = write (fd, txbuf, io_len+2); if (size != io_len+2) { BX_PANIC(("write on tuntap device: %s", strerror (errno))); } else { BX_DEBUG(("wrote %d bytes + 2 byte pad on tuntap", io_len)); } #else unsigned int size = write (fd, buf, io_len); if (size != io_len) { BX_PANIC(("write on tuntap device: %s", strerror (errno))); } else { BX_DEBUG(("wrote %d bytes on tuntap", io_len)); } #endif #if BX_ETH_TUNTAP_LOGGING BX_DEBUG(("sendpkt length %u", io_len)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. int n = fwrite(buf, io_len, 1, txlog); if (n != 1) BX_ERROR(("fwrite to txlog failed")); // dump packet in hex into an ascii log file write_pktlog_txt(txlog_txt, (const Bit8u *)buf, io_len, 0); // flush log so that we see the packets as they arrive w/o buffering fflush(txlog); #endif } void bx_tuntap_pktmover_c::rx_timer_handler (void *this_ptr) { bx_tuntap_pktmover_c *class_ptr = (bx_tuntap_pktmover_c *) this_ptr; class_ptr->rx_timer(); } void bx_tuntap_pktmover_c::rx_timer() { int nbytes; Bit8u buf[BX_PACKET_BUFSIZE]; Bit8u *rxbuf; if (fd<0) return; #ifdef __APPLE__ //FIXME:hack nbytes = 14; bzero(buf, nbytes); buf[0] = buf[6] = 0xFE; buf[1] = buf[7] = 0xFD; buf[12] = 8; nbytes += read (fd, buf+nbytes, sizeof(buf)-nbytes); rxbuf=buf; #elif NEVERDEF nbytes = read (fd, buf, sizeof(buf)); // hack: discard first two bytes rxbuf = buf+2; nbytes-=2; #else nbytes = read (fd, buf, sizeof(buf)); rxbuf=buf; #endif // hack: TUN/TAP device likes to create an ethernet header which has // the same source and destination address FE:FD:00:00:00:00. // Change the dest address to FE:FD:00:00:00:01. if (!memcmp(&rxbuf[0], &rxbuf[6], 6)) { rxbuf[5] = guest_macaddr[5]; } #ifdef __APPLE__ //FIXME:hack if (nbytes>14) #else if (nbytes>0) #endif BX_DEBUG(("tuntap read returned %d bytes", nbytes)); #ifdef __APPLE__ //FIXME:hack if (nbytes<14) { #else if (nbytes<0) { #endif if (errno != EAGAIN) BX_ERROR(("tuntap read error: %s", strerror(errno))); return; } #if BX_ETH_TUNTAP_LOGGING if (nbytes > 0) { BX_DEBUG(("receive packet length %u", nbytes)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. int n = fwrite(rxbuf, nbytes, 1, rxlog); if (n != 1) BX_ERROR (("fwrite to rxlog failed")); // dump packet in hex into an ascii log file write_pktlog_txt(rxlog_txt, rxbuf, nbytes, 1); // flush log so that we see the packets as they arrive w/o buffering fflush(rxlog); } #endif BX_DEBUG(("eth_tuntap: got packet: %d bytes, dst=%02x:%02x:%02x:%02x:%02x:%02x, src=%02x:%02x:%02x:%02x:%02x:%02x", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); if (nbytes < 60) { BX_INFO(("packet too short (%d), padding to 60", nbytes)); nbytes = 60; } if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, rxbuf, nbytes); } else { BX_ERROR(("device not ready to receive data")); } } int tun_alloc(char *dev) { struct ifreq ifr; char *ifname; int fd, err; // split name into device:ifname if applicable, to allow for opening // persistent tuntap devices for (ifname = dev; *ifname; ifname++) { if (*ifname == ':') { *(ifname++) = '\0'; break; } } if ((fd = open(dev, O_RDWR)) < 0) return -1; #ifdef __linux__ memset(&ifr, 0, sizeof(ifr)); /* Flags: IFF_TUN - TUN device (no Ethernet headers) * IFF_TAP - TAP device * * IFF_NO_PI - Do not provide packet information */ ifr.ifr_flags = IFF_TAP | IFF_NO_PI; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if ((err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0) { close(fd); return err; } strncpy(dev, ifr.ifr_name, IFNAMSIZ); dev[IFNAMSIZ-1]=0; ioctl(fd, TUNSETNOCSUM, 1); #endif return fd; } #endif /* if BX_NETWORKING && BX_NETMOD_TUNTAP */ bochs-2.6/iodev/network/eth_tap.cc0000644000175000017500000003357612020641503017076 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_tap.cc 10975 2012-01-14 17:03:00Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // eth_tap.cc - TAP interface by Bryce Denney // // Here's how to get this working. On the host machine: // $ su root // # /sbin/insmod ethertap // Using /lib/modules/2.2.14-5.0/net/ethertap.o // # mknod /dev/tap0 c 36 16 # if not already there // # /sbin/ifconfig tap0 10.0.0.1 // # /sbin/route add -host 10.0.0.2 gw 10.0.0.1 // // Now you have a tap0 device which you can on the ifconfig output. The // tap0 interface has the IP address of 10.0.0.1. The bochs machine will have // the IP address 10.0.0.2. // // Compile a bochs version from March 8, 2002 or later with --enable-ne2000. // Add this ne2k line to your .bochsrc to activate the tap device. // ne2k: ioaddr=0x280, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 // Don't change the mac or ethmod! // // Boot up DLX Linux in Bochs. Log in as root and then type the following // commands to set up networking: // # ifconfig eth0 10.0.0.2 // # route add -net 10.0.0.0 // # route add default gw 10.0.0.1 // Now you should be able to ping from guest OS to your host machine, if // you give its IP number. I'm still having trouble with pings from the // host machine to the guest, so something is still not right. Symptoms: I // ping from the host to the guest's IP address 10.0.0.2. With tcpdump I can // see the ping going to Bochs, and then the ping reply coming from Bochs. // But the ping program itself does not see the responses....well every // once in a while it does, like 1 in 60 pings. // // host$ ping 10.0.0.2 // PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 : 56(84) bytes of data. // // Netstat output: // 20:29:59.018776 fe:fd:0:0:0:0 fe:fd:0:0:0:1 0800 98: 10.0.0.1 > 10.0.0.2: icmp: echo request // 4500 0054 2800 0000 4001 3ea7 0a00 0001 // 0a00 0002 0800 09d3 a53e 0400 9765 893c // 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213 // 1415 1617 1819 // 20:29:59.023017 fe:fd:0:0:0:1 fe:fd:0:0:0:0 0800 98: 10.0.0.2 > 10.0.0.1: icmp: echo reply // 4500 0054 004a 0000 4001 665d 0a00 0002 // 0a00 0001 0000 11d3 a53e 0400 9765 893c // 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213 // 1415 1617 1819 // // I suspect it may be related to the fact that ping 10.0.0.1 from the // host also doesn't work. Why wouldn't the host respond to its own IP // address on the tap0 device? // // Theoretically, if you set up packet forwarding (with masquerading) on the // host, you should be able to get Bochs talking to anyone on the internet. // // Pavel Dufek (PD), CZ, 2008 - quick & dirty hack for Solaris 10 sparc tap // ala Qemu. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING && BX_NETMOD_TAP #define LOG_THIS netdev-> #include #include #include #ifndef __APPLE__ #include #endif #include #include #include #include #include #if defined(__linux__) #include #include #include #elif BX_HAVE_NET_IF_H #include #endif #include #include #include #if defined(__sun__) // Sun/Solaris specific defines/includes #define TUNNEWPPA (('T'<<16) | 0x0001) #include #endif #define BX_ETH_TAP_LOGGING 0 // // Define the class. This is private to this module // class bx_tap_pktmover_c : public eth_pktmover_c { public: bx_tap_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: int fd; int rx_timer_index; static void rx_timer_handler(void *); void rx_timer (); Bit8u guest_macaddr[6]; #if BX_ETH_TAP_LOGGING FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt; #endif }; // // Define the static class that registers the derived pktmover class, // and allocates one on request. // class bx_tap_locator_c : public eth_locator_c { public: bx_tap_locator_c(void) : eth_locator_c("tap") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_tap_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_tap_match; // // Define the methods for the bx_tap_pktmover derived class // // the constructor bx_tap_pktmover_c::bx_tap_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { int flags; char filename[BX_PATHNAME_LEN]; this->netdev = dev; if (strncmp (netif, "tap", 3) != 0) { BX_PANIC(("eth_tap: interface name (%s) must be tap0..tap15", netif)); } #if defined(__sun__) strcpy(filename,"/dev/tap"); /* PD - device on Solaris is always the same */ #else sprintf(filename, "/dev/%s", netif); #endif #if defined(__linux__) // check if the TAP devices is running, and turn on ARP. This is based // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/ int sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock < 0) { BX_PANIC(("socket creation: %s", strerror(errno))); return; } struct ifreq ifr; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name)); if(ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) { BX_PANIC(("SIOCGIFFLAGS on %s: %s", netif, strerror(errno))); close(sock); return; } if (!(ifr.ifr_flags & IFF_RUNNING)) { BX_PANIC(("%s device is not running", netif)); close(sock); return; } if ((ifr.ifr_flags & IFF_NOARP)){ BX_INFO(("turn on ARP for %s device", netif)); ifr.ifr_flags &= ~IFF_NOARP; if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) { BX_PANIC(("SIOCSIFFLAGS: %s", strerror(errno))); close(sock); return; } } close(sock); #endif fd = open (filename, O_RDWR); if (fd < 0) { BX_PANIC(("open failed on TAP %s: %s", netif, strerror(errno))); return; } #if defined(__sun__) char *ptr; /* PD - ppa allocation ala qemu */ char my_dev[10]; /* enough ... */ int ppa=-1; struct strioctl strioc_ppa; my_dev[10-1]=0; strncpy(my_dev,netif,10); /* following ptr= does not work with const char* */ if( *my_dev ) { /* find the ppa number X from string tapX */ ptr = my_dev; while( *ptr && !isdigit((int)*ptr) ) ptr++; ppa = atoi(ptr); } /* Assign a new PPA and get its unit number. */ strioc_ppa.ic_cmd = TUNNEWPPA; strioc_ppa.ic_timout = 0; strioc_ppa.ic_len = sizeof(ppa); strioc_ppa.ic_dp = (char *)&ppa; if ((ppa = ioctl (fd, I_STR, &strioc_ppa)) < 0) BX_PANIC(("Can't assign new interface tap%d !",ppa)); #endif /* set O_ASYNC flag so that we can poll with read() */ if ((flags = fcntl(fd, F_GETFL)) < 0) { BX_PANIC(("getflags on tap device: %s", strerror(errno))); } flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { BX_PANIC(("set tap device flags: %s", strerror(errno))); } BX_INFO(("tap network drive: opened %s device", netif)); /* Execute the configuration script */ char intname[IFNAMSIZ]; strcpy(intname,netif); if((script != NULL) && (strcmp(script, "") != 0) && (strcmp(script, "none") != 0)) { if (execute_script(this->netdev, script, intname) < 0) BX_ERROR(("execute script '%s' on %s failed", script, intname)); } // Start the rx poll this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, 1, 1, "eth_tap"); // continuous, active this->rxh = rxh; this->rxstat = rxstat; memcpy(&guest_macaddr[0], macaddr, 6); #if BX_ETH_TAP_LOGGING // eventually Bryce wants txlog to dump in pcap format so that // tcpdump -r FILE can read it and interpret packets. txlog = fopen("ne2k-tx.log", "wb"); if (!txlog) BX_PANIC(("open ne2k-tx.log failed")); txlog_txt = fopen("ne2k-txdump.txt", "wb"); if (!txlog_txt) BX_PANIC(("open ne2k-txdump.txt failed")); fprintf(txlog_txt, "tap packetmover readable log file\n"); fprintf(txlog_txt, "net IF = %s\n", netif); fprintf(txlog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(txlog_txt, "\n--\n"); fflush(txlog_txt); rxlog = fopen("ne2k-rx.log", "wb"); if (!rxlog) BX_PANIC(("open ne2k-rx.log failed")); rxlog_txt = fopen("ne2k-rxdump.txt", "wb"); if (!rxlog_txt) BX_PANIC(("open ne2k-rxdump.txt failed")); fprintf(rxlog_txt, "tap packetmover readable log file\n"); fprintf(rxlog_txt, "net IF = %s\n", netif); fprintf(rxlog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(rxlog_txt, "\n--\n"); fflush(rxlog_txt); #endif } void bx_tap_pktmover_c::sendpkt(void *buf, unsigned io_len) { Bit8u txbuf[BX_PACKET_BUFSIZE]; txbuf[0] = 0; txbuf[1] = 0; unsigned int size; #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \ defined(__APPLE__) || defined(__OpenBSD__) || defined(__sun__) // Should be fixed for other *BSD memcpy(txbuf, buf, io_len); /* PD - for Sun variant the retry cycle from qemu - mainly to be sure packet is really out */ #if defined(__sun__) int ret; for(;;) { ret=write(fd, txbuf, io_len); if (ret < 0 && (errno == EINTR || errno == EAGAIN)) { } else { size=ret; break; } } #else /* not defined __sun__ */ size = write(fd, txbuf, io_len); #endif /* whole condition about defined __sun__ */ if (size != io_len) { #else /* not bsd/apple/sun style */ memcpy(txbuf+2, buf, io_len); size = write(fd, txbuf, io_len+2); if (size != io_len+2) { #endif BX_PANIC(("write on tap device: %s", strerror(errno))); } else { BX_DEBUG(("wrote %d bytes + ev. 2 byte pad on tap", io_len)); } #if BX_ETH_TAP_LOGGING BX_DEBUG(("sendpkt length %u", io_len)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. int n = fwrite(buf, io_len, 1, txlog); if (n != 1) BX_ERROR(("fwrite to txlog failed, io_len = %u", io_len)); // dump packet in hex into an ascii log file write_pktlog_txt(txlog_txt, (const Bit8u *)buf, io_len, 0); // flush log so that we see the packets as they arrive w/o buffering fflush(txlog); #endif } void bx_tap_pktmover_c::rx_timer_handler(void *this_ptr) { bx_tap_pktmover_c *class_ptr = (bx_tap_pktmover_c *) this_ptr; class_ptr->rx_timer(); } void bx_tap_pktmover_c::rx_timer() { int nbytes; Bit8u buf[BX_PACKET_BUFSIZE]; Bit8u *rxbuf; if (fd<0) return; #if defined(__sun__) struct strbuf sbuf; int f = 0; sbuf.maxlen = sizeof(buf); sbuf.buf = (char *)buf; nbytes = getmsg(fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1; #else nbytes = read (fd, buf, sizeof(buf)); #endif // hack: discard first two bytes #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__sun__) // Should be fixed for other *BSD rxbuf = buf; #else rxbuf = buf+2; nbytes-=2; #endif #if defined(__linux__) // hack: TAP device likes to create an ethernet header which has // the same source and destination address FE:FD:00:00:00:00. // Change the dest address to FE:FD:00:00:00:01. if (!memcmp(&rxbuf[0], &rxbuf[6], 6)) { rxbuf[5] = guest_macaddr[5]; } #endif if (nbytes>0) BX_DEBUG(("tap read returned %d bytes", nbytes)); if (nbytes<0) { if (errno != EAGAIN) BX_ERROR(("tap read error: %s", strerror(errno))); return; } #if BX_ETH_TAP_LOGGING if (nbytes > 0) { BX_DEBUG(("receive packet length %u", nbytes)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. int n = fwrite(rxbuf, nbytes, 1, rxlog); if (n != 1) BX_ERROR(("fwrite to rxlog failed, nbytes = %d", nbytes)); // dump packet in hex into an ascii log file write_pktlog_txt(rxlog_txt, rxbuf, nbytes, 1); // flush log so that we see the packets as they arrive w/o buffering fflush(rxlog); } #endif BX_DEBUG(("eth_tap: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); if (nbytes < 60) { BX_INFO(("packet too short (%d), padding to 60", nbytes)); nbytes = 60; } if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, rxbuf, nbytes); } else { BX_ERROR(("device not ready to receive data")); } } #endif /* if BX_NETWORKING && BX_NETMOD_TAP */ bochs-2.6/iodev/network/pnic_api.h0000644000175000017500000000343512020641503017065 0ustar guillemguillem/* * Constants etc. for the Bochs/Etherboot pseudo-NIC * * This header file must be valid C and C++. * * Operation of the pseudo-NIC (PNIC) is pretty simple. To write a * command plus data, first write the length of the data to * PNIC_REG_LEN, then write the data a byte at a type to * PNIC_REG_DATA, then write the command code to PNIC_REG_CMD. The * status will be available from PNIC_REG_STAT. The length of any * data returned will be in PNIC_REG_LEN and can be read a byte at a * time from PNIC_REG_DATA. */ /* * PCI parameters */ #define PNIC_PCI_VENDOR 0xfefe /* Hopefully these won't clash with */ #define PNIC_PCI_DEVICE 0xefef /* any real PCI device IDs. */ /* * 'Hardware' register addresses, offset from io_base */ #define PNIC_REG_CMD 0x00 /* Command register, 2 bytes, write only */ #define PNIC_REG_STAT 0x00 /* Status register, 2 bytes, read only */ #define PNIC_REG_LEN 0x02 /* Length register, 2 bytes, read-write */ #define PNIC_REG_DATA 0x04 /* Data port, 1 byte, read-write */ /* * PNIC_MAX_REG used in Bochs to claim i/o space */ #define PNIC_MAX_REG 0x04 /* * Command code definitions: write these into PNIC_REG_CMD */ #define PNIC_CMD_NOOP 0x0000 #define PNIC_CMD_API_VER 0x0001 #define PNIC_CMD_READ_MAC 0x0002 #define PNIC_CMD_RESET 0x0003 #define PNIC_CMD_XMIT 0x0004 #define PNIC_CMD_RECV 0x0005 #define PNIC_CMD_RECV_QLEN 0x0006 #define PNIC_CMD_MASK_IRQ 0x0007 #define PNIC_CMD_FORCE_IRQ 0x0008 /* * Status code definitions: read these from PNIC_REG_STAT * * We avoid using status codes that might be confused with * randomly-read data (e.g. 0x0000, 0xffff etc.) */ #define PNIC_STATUS_OK 0x4f4b /* 'OK' */ #define PNIC_STATUS_UNKNOWN_CMD 0x3f3f /* '??' */ /* * Other miscellaneous information */ #define PNIC_API_VERSION 0x0101 /* 1.1 */ bochs-2.6/iodev/network/ne2k.h0000644000175000017500000002426712020641503016150 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ne2k.h 11148 2012-04-23 17:06:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Peter Grehan (grehan@iprg.nokia.com) coded all of this // NE2000/ether stuff. // // An implementation of an ne2000 ISA ethernet adapter. This part uses // a National Semiconductor DS-8390 ethernet MAC chip, with some h/w // to provide a windowed memory region for the chip and a MAC address. // #ifndef BX_IODEV_NE2K #define BX_IODEV_NE2K #if BX_USE_NE2K_SMF # define BX_NE2K_SMF static # define BX_NE2K_THIS theNE2kDevice-> # define BX_NE2K_THIS_PTR theNE2kDevice #else # define BX_NE2K_SMF # define BX_NE2K_THIS this-> # define BX_NE2K_THIS_PTR this #endif #define BX_NE2K_MEMSIZ (32*1024) #define BX_NE2K_MEMSTART (16*1024) #define BX_NE2K_MEMEND (BX_NE2K_MEMSTART + BX_NE2K_MEMSIZ) class eth_pktmover_c; typedef struct { // // ne2k register state // // Page 0 // // Command Register - 00h read/write struct { bx_bool stop; // STP - Software Reset command bx_bool start; // START - start the NIC bx_bool tx_packet; // TXP - initiate packet transmission Bit8u rdma_cmd; // RD0,RD1,RD2 - Remote DMA command Bit8u pgsel; // PS0,PS1 - Page select } CR; // Interrupt Status Register - 07h read/write struct { bx_bool pkt_rx; // PRX - packet received with no errors bx_bool pkt_tx; // PTX - packet transmitted with no errors bx_bool rx_err; // RXE - packet received with 1 or more errors bx_bool tx_err; // TXE - packet tx'd " " " " " bx_bool overwrite; // OVW - rx buffer resources exhausted bx_bool cnt_oflow; // CNT - network tally counter MSB's set bx_bool rdma_done; // RDC - remote DMA complete bx_bool reset; // RST - reset status } ISR; // Interrupt Mask Register - 0fh write struct { bx_bool rx_inte; // PRXE - packet rx interrupt enable bx_bool tx_inte; // PTXE - packet tx interrput enable bx_bool rxerr_inte; // RXEE - rx error interrupt enable bx_bool txerr_inte; // TXEE - tx error interrupt enable bx_bool overw_inte; // OVWE - overwrite warn int enable bx_bool cofl_inte; // CNTE - counter o'flow int enable bx_bool rdma_inte; // RDCE - remote DMA complete int enable bx_bool reserved; // D7 - reserved } IMR; // Data Configuration Register - 0eh write struct { bx_bool wdsize; // WTS - 8/16-bit select bx_bool endian; // BOS - byte-order select bx_bool longaddr; // LAS - long-address select bx_bool loop; // LS - loopback select bx_bool auto_rx; // AR - auto-remove rx packets with remote DMA Bit8u fifo_size; // FT0,FT1 - fifo threshold } DCR; // Transmit Configuration Register - 0dh write struct { bx_bool crc_disable; // CRC - inhibit tx CRC Bit8u loop_cntl; // LB0,LB1 - loopback control bx_bool ext_stoptx; // ATD - allow tx disable by external mcast bx_bool coll_prio; // OFST - backoff algorithm select Bit8u reserved; // D5,D6,D7 - reserved } TCR; // Transmit Status Register - 04h read struct { bx_bool tx_ok; // PTX - tx complete without error bx_bool reserved; // D1 - reserved bx_bool collided; // COL - tx collided >= 1 times bx_bool aborted; // ABT - aborted due to excessive collisions bx_bool no_carrier; // CRS - carrier-sense lost bx_bool fifo_ur; // FU - FIFO underrun bx_bool cd_hbeat; // CDH - no tx cd-heartbeat from transceiver bx_bool ow_coll; // OWC - out-of-window collision } TSR; // Receive Configuration Register - 0ch write struct { bx_bool errors_ok; // SEP - accept pkts with rx errors bx_bool runts_ok; // AR - accept < 64-byte runts bx_bool broadcast; // AB - accept eth broadcast address bx_bool multicast; // AM - check mcast hash array bx_bool promisc; // PRO - accept all packets bx_bool monitor; // MON - check pkts, but don't rx Bit8u reserved; // D6,D7 - reserved } RCR; // Receive Status Register - 0ch read struct { bx_bool rx_ok; // PRX - rx complete without error bx_bool bad_crc; // CRC - Bad CRC detected bx_bool bad_falign; // FAE - frame alignment error bx_bool fifo_or; // FO - FIFO overrun bx_bool rx_missed; // MPA - missed packet error bx_bool rx_mbit; // PHY - unicast or mcast/bcast address match bx_bool rx_disabled; // DIS - set when in monitor mode bx_bool deferred; // DFR - collision active } RSR; Bit16u local_dma; // 01,02h read ; current local DMA addr Bit8u page_start; // 01h write ; page start register Bit8u page_stop; // 02h write ; page stop register Bit8u bound_ptr; // 03h read/write ; boundary pointer Bit8u tx_page_start; // 04h write ; transmit page start register Bit8u num_coll; // 05h read ; number-of-collisions register Bit16u tx_bytes; // 05,06h write ; transmit byte-count register Bit8u fifo; // 06h read ; FIFO Bit16u remote_dma; // 08,09h read ; current remote DMA addr Bit16u remote_start; // 08,09h write ; remote start address register Bit16u remote_bytes; // 0a,0bh write ; remote byte-count register Bit8u tallycnt_0; // 0dh read ; tally counter 0 (frame align errors) Bit8u tallycnt_1; // 0eh read ; tally counter 1 (CRC errors) Bit8u tallycnt_2; // 0fh read ; tally counter 2 (missed pkt errors) // // Page 1 // // Command Register 00h (repeated) // Bit8u physaddr[6]; // 01-06h read/write ; MAC address Bit8u curr_page; // 07h read/write ; current page register Bit8u mchash[8]; // 08-0fh read/write ; multicast hash array // // Page 2 - diagnostic use only // // Command Register 00h (repeated) // // Page Start Register 01h read (repeated) // Page Stop Register 02h read (repeated) // Current Local DMA Address 01,02h write (repeated) // Transmit Page start address 04h read (repeated) // Receive Configuration Register 0ch read (repeated) // Transmit Configuration Register 0dh read (repeated) // Data Configuration Register 0eh read (repeated) // Interrupt Mask Register 0fh read (repeated) // Bit8u rempkt_ptr; // 03h read/write ; remote next-packet pointer Bit8u localpkt_ptr; // 05h read/write ; local next-packet pointer Bit16u address_cnt; // 06,07h read/write ; address counter // // Page 3 - should never be modified. // // Novell ASIC state Bit8u macaddr[32]; // ASIC ROM'd MAC address, even bytes Bit8u mem[BX_NE2K_MEMSIZ]; // on-chip packet memory // ne2k internal state Bit32u base_address; int base_irq; int tx_timer_index; bx_bool tx_timer_active; int statusbar_id; // pci stuff bx_bool pci_enabled; #if BX_SUPPORT_PCI Bit8u devfunc; #endif } bx_ne2k_t; class bx_ne2k_c : public bx_devmodel_c #if BX_SUPPORT_PCI , public bx_pci_device_stub_c #endif { public: bx_ne2k_c(); virtual ~bx_ne2k_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); #if BX_SUPPORT_PCI virtual void after_restore_state(void); #endif #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif #if BX_SUPPORT_PCI virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); #endif private: bx_ne2k_t s; eth_pktmover_c *ethdev; BX_NE2K_SMF Bit32u read_cr(void); BX_NE2K_SMF void write_cr(Bit32u value); BX_NE2K_SMF void set_irq_level(bx_bool level); BX_NE2K_SMF Bit32u chipmem_read(Bit32u address, unsigned io_len) BX_CPP_AttrRegparmN(2); BX_NE2K_SMF Bit32u asic_read(Bit32u offset, unsigned io_len) BX_CPP_AttrRegparmN(2); BX_NE2K_SMF Bit32u page0_read(Bit32u offset, unsigned io_len); BX_NE2K_SMF Bit32u page1_read(Bit32u offset, unsigned io_len); BX_NE2K_SMF Bit32u page2_read(Bit32u offset, unsigned io_len); BX_NE2K_SMF Bit32u page3_read(Bit32u offset, unsigned io_len); BX_NE2K_SMF void chipmem_write(Bit32u address, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); BX_NE2K_SMF void asic_write(Bit32u address, Bit32u value, unsigned io_len); BX_NE2K_SMF void page0_write(Bit32u address, Bit32u value, unsigned io_len); BX_NE2K_SMF void page1_write(Bit32u address, Bit32u value, unsigned io_len); BX_NE2K_SMF void page2_write(Bit32u address, Bit32u value, unsigned io_len); BX_NE2K_SMF void page3_write(Bit32u address, Bit32u value, unsigned io_len); static void tx_timer_handler(void *); BX_NE2K_SMF void tx_timer(void); static Bit32u rx_status_handler(void *arg); BX_NE2K_SMF Bit32u rx_status(void); static void rx_handler(void *arg, const void *buf, unsigned len); BX_NE2K_SMF unsigned mcast_index(const void *dst); BX_NE2K_SMF void rx_frame(const void *buf, unsigned io_len); #if BX_SUPPORT_PCI BX_NE2K_SMF bx_bool mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param); BX_NE2K_SMF bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param); #endif static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_NE2K_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif #if BX_DEBUGGER void print_info(int page, int reg, int nodups); #endif }; #endif bochs-2.6/iodev/network/netmod.h0000644000175000017500000001174212020641503016571 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: netmod.h 11342 2012-08-16 11:59:44Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Peter Grehan (grehan@iprg.nokia.com) coded the initial version of the // NE2000/ether stuff. // netmod.h - see eth_null.cc for implementation details #ifndef BX_NETMOD_H #define BX_NETMOD_H // Pseudo device that loads the lowlevel networking module class bx_netmod_ctl_c : public bx_netmod_ctl_stub_c { public: bx_netmod_ctl_c() {} virtual ~bx_netmod_ctl_c() {} virtual void* init_module(bx_list_c *base, void* rxh, void* rxstat, bx_devmodel_c *dev); }; #define BX_PACKET_BUFSIZE 2048 // Enough for an ether frame // device receive status definitions #define BX_NETDEV_RXREADY 0x0001 #define BX_NETDEV_SPEED 0x000e #define BX_NETDEV_10MBIT 0x0002 #define BX_NETDEV_100MBIT 0x0004 #define BX_NETDEV_1GBIT 0x0008 #define TFTP_BUFFER_SIZE 512 typedef void (*eth_rx_handler_t)(void *arg, const void *buf, unsigned len); typedef Bit32u (*eth_rx_status_t)(void *arg); typedef struct { Bit8u host_macaddr[6]; Bit8u guest_macaddr[6]; Bit8u host_ipv4addr[4]; const Bit8u *default_guest_ipv4addr; Bit8u guest_ipv4addr[4]; Bit8u dns_ipv4addr[4]; } dhcp_cfg_t; typedef struct { char filename[BX_PATHNAME_LEN]; char rootdir[BX_PATHNAME_LEN]; bx_bool write; Bit16u tid; } tftp_data_t; static const Bit8u broadcast_macaddr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; int execute_script(bx_devmodel_c *netdev, const char *name, char* arg1); void write_pktlog_txt(FILE *pktlog_txt, const Bit8u *buf, unsigned len, bx_bool host_to_guest); BX_CPP_INLINE Bit16u get_net2(const Bit8u *buf) { return (((Bit16u)*buf) << 8) | ((Bit16u)*(buf+1)); } BX_CPP_INLINE void put_net2(Bit8u *buf,Bit16u data) { *buf = (Bit8u)(data >> 8); *(buf+1) = (Bit8u)(data & 0xff); } BX_CPP_INLINE Bit32u get_net4(const Bit8u *buf) { return (((Bit32u)*buf) << 24) | (((Bit32u)*(buf+1)) << 16) | (((Bit32u)*(buf+2)) << 8) | ((Bit32u)*(buf+3)); } BX_CPP_INLINE void put_net4(Bit8u *buf,Bit32u data) { *buf = (Bit8u)((data >> 24) & 0xff); *(buf+1) = (Bit8u)((data >> 16) & 0xff); *(buf+2) = (Bit8u)((data >> 8) & 0xff); *(buf+3) = (Bit8u)(data & 0xff); } Bit16u ip_checksum(const Bit8u *buf, unsigned buf_len); int process_dhcp(bx_devmodel_c *netdev, const Bit8u *data, unsigned data_len, Bit8u *reply, dhcp_cfg_t *dhcp); int process_tftp(bx_devmodel_c *netdev, const Bit8u *data, unsigned data_len, Bit16u req_tid, Bit8u *reply, tftp_data_t *tftp); // // The eth_pktmover class is used by ethernet chip emulations // to interface to the outside world. An instance of this // would allow frames to be sent to and received from some // entity. An example would be the packet filter on a Unix // system, an NDIS driver in promisc mode on WinNT, or maybe // a simulated network that talks to another process. // class eth_pktmover_c { public: virtual void sendpkt(void *buf, unsigned io_len) = 0; virtual ~eth_pktmover_c () {} protected: bx_devmodel_c *netdev; eth_rx_handler_t rxh; // receive callback eth_rx_status_t rxstat; // receive status callback }; // // The eth_locator class is used by pktmover classes to register // their name. Chip emulations use the static 'create' method // to locate and instantiate a pktmover class. // class eth_locator_c { public: static eth_pktmover_c *create(const char *type, const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); protected: eth_locator_c(const char *type); virtual ~eth_locator_c() {} virtual eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) = 0; private: static eth_locator_c *all; eth_locator_c *next; const char *type; }; #endif bochs-2.6/iodev/network/Makefile.in0000644000175000017500000003173512020641503017203 0ustar guillemguillem# Copyright (C) 2012 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Makefile for the iodev/network component of bochs @SUFFIX_LINE@ prefix = @prefix@ exec_prefix = @exec_prefix@ srcdir = @srcdir@ VPATH = @srcdir@ bindir = @bindir@ libdir = @libdir@ datarootdir = @datarootdir@ mandir = @mandir@ man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 docdir = $(datarootdir)/doc/bochs sharedir = $(datarootdir)/bochs top_builddir = .. top_srcdir = @top_srcdir@ SHELL = @SHELL@ @SET_MAKE@ CXX = @CXX@ CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ PLUGIN_PATH=@libdir@ top_builddir = ../.. LIBTOOL=@LIBTOOL@ WIN32_DLL_IMPORT_LIBRARY=../../dllexports.a NETLOW_OBJS = @NETLOW_OBJS@ BX_INCDIRS = -I.. -I../.. -I$(srcdir)/.. -I$(srcdir)/../.. -I../../@INSTRUMENT_DIR@ -I$(srcdir)/../../@INSTRUMENT_DIR@ LOCAL_CXXFLAGS = $(MCH_CFLAGS) OBJS_THAT_CAN_BE_PLUGINS = \ @NETDEV_OBJS@ \ netmod.o OBJS_THAT_SUPPORT_OTHER_PLUGINS = \ $(NETLOW_OBJS) NONPLUGIN_OBJS = @IODEV_EXT_NON_PLUGIN_OBJS@ PLUGIN_OBJS = @IODEV_EXT_PLUGIN_OBJS@ all: libnetwork.a plugins: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@) libnetwork.a: $(NONPLUGIN_OBJS) @RMCOMMAND@ libnetwork.a @MAKELIB@ $(NONPLUGIN_OBJS) @RANLIB@ libnetwork.a # standard compile rule for C++ files .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@ ##### building plugins with libtool %.lo: %.@CPP_SUFFIX@ $(LIBTOOL) --mode=compile --tag CXX $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@ libbx_%.la: %.lo $(LIBTOOL) --mode=link --tag CXX $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) # special link rules for plugins that require more than one object file libbx_netmod.la: netmod.lo $(NETLOW_OBJS:.o=.lo) $(LIBTOOL) --mode=link --tag CXX $(CXX) -module netmod.lo $(NETLOW_OBJS:.o=.lo) -o libbx_netmod.la -rpath $(PLUGIN_PATH) #### building DLLs for win32 (tested on cygwin only) bx_%.dll: %.o $(CXX) $(CXXFLAGS) -shared -o $@ $< $(WIN32_DLL_IMPORT_LIBRARY) # special link rules for plugins that require more than one object file bx_netmod.dll: netmod.o $(NETLOW_OBJS) $(CXX) $(CXXFLAGS) -shared -o bx_netmod.dll netmod.o $(NETLOW_OBJS) $(WIN32_DLL_IMPORT_LIBRARY) ##### end DLL section clean: @RMCOMMAND@ -rf .libs *.lo *.o *.la *.a *.dll dist-clean: clean @RMCOMMAND@ Makefile ########################################### # dependencies generated by # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | sed -e 's/\.cc/.@CPP_SUFFIX@/g' # gcc -MM -I.. -I../.. -I../../instrument/stubs *.cc | \ # sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g' # # This means that every source file is listed twice, once with a .o rule # and then again with an identical .lo rule. The .lo rules are used when # building plugins. ########################################### e1000.o: e1000.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h ../pci.h netmod.h e1000.h eth_fbsd.o: eth_fbsd.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_linux.o: eth_linux.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_null.o: eth_null.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_slirp.o: eth_slirp.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_tap.o: eth_tap.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_tuntap.o: eth_tuntap.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_vde.o: eth_vde.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_vnet.o: eth_vnet.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_win32.o: eth_win32.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h ne2k.o: ne2k.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h ../pci.h ne2k.h netmod.h netmod.o: netmod.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h pcipnic.o: pcipnic.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h e1000.lo: e1000.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h ../pci.h netmod.h e1000.h eth_fbsd.lo: eth_fbsd.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_linux.lo: eth_linux.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_null.lo: eth_null.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_slirp.lo: eth_slirp.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_tap.lo: eth_tap.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_tuntap.lo: eth_tuntap.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_vde.lo: eth_vde.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_vnet.lo: eth_vnet.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h eth_win32.lo: eth_win32.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h ne2k.lo: ne2k.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h ../pci.h ne2k.h netmod.h netmod.lo: netmod.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h ../../osdep.h \ ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h netmod.h pcipnic.lo: pcipnic.@CPP_SUFFIX@ ../iodev.h ../../bochs.h ../../config.h \ ../../osdep.h ../../bx_debug/debug.h ../../config.h ../../osdep.h \ ../../gui/siminterface.h ../../cpudb.h ../../gui/paramtree.h \ ../../memory/memory.h ../../pc_system.h ../../gui/gui.h \ ../../instrument/stubs/instrument.h ../../plugin.h ../../extplugin.h \ ../../param_names.h bochs-2.6/iodev/network/eth_vnet.cc0000644000175000017500000005337012020641503017260 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_vnet.cc 11343 2012-08-16 12:25:55Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // virtual Ethernet locator // // An implementation of ARP, ping(ICMP-echo), DHCP and read/write TFTP. // Virtual host acts as a DHCP server for guest. // There are no connections between the virtual host and real ethernets. // // Virtual host name: vnet // Virtual host IP: 192.168.10.1 // Guest IP: 192.168.10.2 // Guest netmask: 255.255.255.0 // Guest broadcast: 192.168.10.255 // TFTP server uses ethdev value for the root directory and doesn't overwrite files #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING #define LOG_THIS netdev-> #define BX_ETH_VNET_LOGGING 1 #define BX_ETH_VNET_PCAP_LOGGING 0 #if BX_ETH_VNET_PCAP_LOGGING #include #endif ///////////////////////////////////////////////////////////////////////// // handler to send/receive packets ///////////////////////////////////////////////////////////////////////// static const Bit8u default_host_ipv4addr[4] = {192,168,10,1}; static const Bit8u subnetmask_ipv4addr[4] = {0xff,0xff,0xff,0x00}; static const Bit8u default_guest_ipv4addr[4] = {192,168,10,2}; static const Bit8u broadcast_ipv4addr[3][4] = { { 0, 0, 0, 0}, {255,255,255,255}, {192,168, 10,255}, }; #define ICMP_ECHO_PACKET_MAX 128 #define LAYER4_LISTEN_MAX 128 static Bit8u packet_buffer[BX_PACKET_BUFSIZE]; static unsigned packet_len; typedef void (*layer4_handler_t)( void *this_ptr, const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len ); #define INET_PORT_FTPDATA 20 #define INET_PORT_FTP 21 #define INET_PORT_TIME 37 #define INET_PORT_NAME 42 #define INET_PORT_DOMAIN 53 #define INET_PORT_BOOTP_SERVER 67 #define INET_PORT_BOOTP_CLIENT 68 #define INET_PORT_HTTP 80 #define INET_PORT_NTP 123 // TFTP server support by EaseWay #define INET_PORT_TFTP_SERVER 69 class bx_vnet_pktmover_c : public eth_pktmover_c { public: bx_vnet_pktmover_c(); void pktmover_init( const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: void guest_to_host(const Bit8u *buf, unsigned io_len); void host_to_guest(Bit8u *buf, unsigned io_len); void process_arp(const Bit8u *buf, unsigned io_len); void host_to_guest_arp(Bit8u *buf, unsigned io_len); void process_ipv4(const Bit8u *buf, unsigned io_len); void host_to_guest_ipv4(Bit8u *buf, unsigned io_len); layer4_handler_t get_layer4_handler( unsigned ipprotocol, unsigned port); bx_bool register_layer4_handler( unsigned ipprotocol, unsigned port,layer4_handler_t func); bx_bool unregister_layer4_handler( unsigned ipprotocol, unsigned port); void process_icmpipv4( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len); void process_tcpipv4( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len); void process_udpipv4( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len); void host_to_guest_udpipv4_packet( unsigned target_port, unsigned source_port, const Bit8u *udpdata, unsigned udpdata_len); void process_icmpipv4_echo( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len); static void udpipv4_dhcp_handler( void *this_ptr, const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len); void udpipv4_dhcp_handler_ns( const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len); static void udpipv4_tftp_handler( void *this_ptr, const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len); void udpipv4_tftp_handler_ns( const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len); dhcp_cfg_t dhcp; tftp_data_t tftp; struct { unsigned ipprotocol; unsigned port; layer4_handler_t func; } l4data[LAYER4_LISTEN_MAX]; unsigned l4data_used; static void rx_timer_handler(void *); void rx_timer(void); int rx_timer_index; unsigned netdev_speed; unsigned tx_time; #if BX_ETH_VNET_LOGGING FILE *pktlog_txt; #endif // BX_ETH_VNET_LOGGING #if BX_ETH_VNET_PCAP_LOGGING pcap_t *pcapp; pcap_dumper_t *pktlog_pcap; struct pcap_pkthdr pcaphdr; #endif // BX_ETH_VNET_PCAP_LOGGING }; class bx_vnet_locator_c : public eth_locator_c { public: bx_vnet_locator_c(void) : eth_locator_c("vnet") {} protected: eth_pktmover_c *allocate( const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { bx_vnet_pktmover_c *pktmover; pktmover = new bx_vnet_pktmover_c(); pktmover->pktmover_init(netif, macaddr, rxh, rxstat, dev, script); return pktmover; } } bx_vnet_match; bx_vnet_pktmover_c::bx_vnet_pktmover_c() { } void bx_vnet_pktmover_c::pktmover_init( const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { this->netdev = dev; BX_INFO(("vnet network driver")); this->rxh = rxh; this->rxstat = rxstat; strcpy(this->tftp.rootdir, netif); this->tftp.tid = 0; this->tftp.write = 0; memcpy(&dhcp.host_macaddr[0], macaddr, 6); memcpy(&dhcp.guest_macaddr[0], macaddr, 6); dhcp.host_macaddr[5] ^= 0x03; memcpy(&dhcp.host_ipv4addr[0], &default_host_ipv4addr[0], 4); memcpy(&dhcp.guest_ipv4addr[0], &broadcast_ipv4addr[1][0], 4); dhcp.default_guest_ipv4addr = default_guest_ipv4addr; memcpy(&dhcp.dns_ipv4addr[0], &broadcast_ipv4addr[0][0], 4); l4data_used = 0; register_layer4_handler(0x11,INET_PORT_BOOTP_SERVER,udpipv4_dhcp_handler); register_layer4_handler(0x11,INET_PORT_TFTP_SERVER,udpipv4_tftp_handler); Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED; this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 : (status == BX_NETDEV_100MBIT) ? 100 : 10; this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, 0, 0, "eth_vnet"); #if BX_ETH_VNET_LOGGING pktlog_txt = fopen("ne2k-pktlog.txt", "wb"); if (!pktlog_txt) BX_PANIC(("ne2k-pktlog.txt failed")); fprintf(pktlog_txt, "vnet packetmover readable log file\n"); fprintf(pktlog_txt, "TFTP root = %s\n", netif); fprintf(pktlog_txt, "host MAC address = "); int i; for (i=0; i<6; i++) fprintf(pktlog_txt, "%02x%s", 0xff & dhcp.host_macaddr[i], i<5?":" : "\n"); fprintf(pktlog_txt, "guest MAC address = "); for (i=0; i<6; i++) fprintf(pktlog_txt, "%02x%s", 0xff & dhcp.guest_macaddr[i], i<5?":" : "\n"); fprintf(pktlog_txt, "--\n"); fflush(pktlog_txt); #endif #if BX_ETH_VNET_PCAP_LOGGING pcapp = pcap_open_dead(DLT_EN10MB, BX_PACKET_BUFSIZE); pktlog_pcap = pcap_dump_open(pcapp, "ne2k-pktlog.pcap"); if (pktlog_pcap == NULL) BX_PANIC(("ne2k-pktlog.pcap failed")); #endif } void bx_vnet_pktmover_c::sendpkt(void *buf, unsigned io_len) { guest_to_host((const Bit8u *)buf,io_len); } void bx_vnet_pktmover_c::guest_to_host(const Bit8u *buf, unsigned io_len) { #if BX_ETH_VNET_LOGGING write_pktlog_txt(pktlog_txt, buf, io_len, 0); #endif #if BX_ETH_VNET_PCAP_LOGGING if (pktlog_pcap && !ferror((FILE *)pktlog_pcap)) { Bit64u time = bx_pc_system.time_usec(); pcaphdr.ts.tv_usec = time % 1000000; pcaphdr.ts.tv_sec = time / 1000000; pcaphdr.caplen = io_len; pcaphdr.len = io_len; pcap_dump((u_char *)pktlog_pcap, &pcaphdr, buf); fflush((FILE *)pktlog_pcap); } #endif this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / this->netdev_speed; if ((io_len >= 14) && (!memcmp(&buf[6],&dhcp.guest_macaddr[0],6)) && (!memcmp(&buf[0],&dhcp.host_macaddr[0],6) || !memcmp(&buf[0],&broadcast_macaddr[0],6))) { switch (get_net2(&buf[12])) { case 0x0800: // IPv4. process_ipv4(buf, io_len); break; case 0x0806: // ARP. process_arp(buf, io_len); break; default: // unknown packet type. break; } } } // The receive poll process void bx_vnet_pktmover_c::rx_timer_handler(void *this_ptr) { bx_vnet_pktmover_c *class_ptr = (bx_vnet_pktmover_c *) this_ptr; class_ptr->rx_timer(); } void bx_vnet_pktmover_c::rx_timer(void) { if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, (void *)packet_buffer, packet_len); #if BX_ETH_VNET_LOGGING write_pktlog_txt(pktlog_txt, packet_buffer, packet_len, 1); #endif #if BX_ETH_VNET_PCAP_LOGGING if (pktlog_pcap && !ferror((FILE *)pktlog_pcap)) { Bit64u time = bx_pc_system.time_usec(); pcaphdr.ts.tv_usec = time % 1000000; pcaphdr.ts.tv_sec = time / 1000000; pcaphdr.caplen = packet_len; pcaphdr.len = packet_len; pcap_dump((u_char *)pktlog_pcap, &pcaphdr, packet_buffer); fflush((FILE *)pktlog_pcap); } #endif } else { BX_ERROR(("device not ready to receive data")); } } void bx_vnet_pktmover_c::host_to_guest(Bit8u *buf, unsigned io_len) { Bit8u localbuf[60]; if (io_len < 14) { BX_PANIC(("host_to_guest: io_len < 14!")); return; } if (io_len < 60) { memcpy(&localbuf[0],&buf[0],io_len); memset(&localbuf[io_len],0,60-io_len); buf=localbuf; io_len=60; } packet_len = io_len; memcpy(&packet_buffer, &buf[0], io_len); unsigned rx_time = (64 + 96 + 4 * 8 + io_len * 8) / this->netdev_speed; bx_pc_system.activate_timer(this->rx_timer_index, this->tx_time + rx_time + 100, 0); } ///////////////////////////////////////////////////////////////////////// // ARP ///////////////////////////////////////////////////////////////////////// void bx_vnet_pktmover_c::process_arp(const Bit8u *buf, unsigned io_len) { unsigned opcode; unsigned protocol; Bit8u replybuf[60]; if (io_len < 22) return; if (io_len < (unsigned)(22+buf[18]*2+buf[19]*2)) return; // hardware:Ethernet if (buf[14] != 0x00 || buf[15] != 0x01 || buf[18] != 0x06) return; opcode = get_net2(&buf[20]); protocol = get_net2(&buf[16]); memset(&replybuf[0],0,60); // protocol switch (protocol) { case 0x0800: // IPv4 if (buf[19] == 0x04) { switch (opcode) { case 0x0001: // ARP REQUEST if (!memcmp(&buf[22],&dhcp.guest_macaddr[0],6)) { memcpy(&dhcp.guest_ipv4addr[0],&buf[28],4); if (!memcmp(&buf[38],&dhcp.host_ipv4addr[0],4)) { memcpy(&replybuf[14],&buf[14],6); replybuf[20]=0x00; replybuf[21]=0x02; memcpy(&replybuf[22],&dhcp.host_macaddr[0],6); memcpy(&replybuf[28],&dhcp.host_ipv4addr[0],4); memcpy(&replybuf[32],&dhcp.guest_macaddr[0],6); memcpy(&replybuf[38],&dhcp.guest_ipv4addr[0],4); host_to_guest_arp(replybuf,60); } } break; case 0x0002: // ARP REPLY BX_INFO(("unexpected ARP REPLY")); break; case 0x0003: // RARP REQUEST BX_ERROR(("RARP is not implemented")); break; case 0x0004: // RARP REPLY BX_INFO(("unexpected RARP REPLY")); break; default: BX_INFO(("arp: unknown ARP opcode %04x",opcode)); break; } } else { BX_INFO(("arp: unknown address length %u",(unsigned)buf[19])); } break; default: BX_INFO(("arp: unknown protocol 0x%04x",protocol)); break; } } void bx_vnet_pktmover_c::host_to_guest_arp(Bit8u *buf, unsigned io_len) { memcpy(&buf[0],&dhcp.guest_macaddr[0],6); memcpy(&buf[6],&dhcp.host_macaddr[0],6); buf[12]=0x08; buf[13]=0x06; host_to_guest(buf,io_len); } ///////////////////////////////////////////////////////////////////////// // IPv4 ///////////////////////////////////////////////////////////////////////// void bx_vnet_pktmover_c::process_ipv4(const Bit8u *buf, unsigned io_len) { unsigned total_len; // unsigned packet_id; unsigned fragment_flags; unsigned fragment_offset; unsigned ipproto; unsigned l3header_len; const Bit8u *l4pkt; unsigned l4pkt_len; if (io_len < (14U+20U)) { BX_INFO(("ip packet - too small packet")); return; } if ((buf[14+0] & 0xf0) != 0x40) { BX_INFO(("ipv%u packet - not implemented",((unsigned)buf[14+0] >> 4))); return; } l3header_len = ((unsigned)(buf[14+0] & 0x0f) << 2); if (l3header_len != 20) { BX_ERROR(("ip: option header is not implemented")); return; } if (io_len < (14U+l3header_len)) return; if (ip_checksum(&buf[14],l3header_len) != (Bit16u)0xffff) { BX_INFO(("ip: invalid checksum")); return; } total_len = get_net2(&buf[14+2]); // FIXED By EaseWay // Ignore this check to tolerant some cases //if (io_len > (14U+total_len)) return; if (memcmp(&buf[14+16],dhcp.host_ipv4addr,4) && memcmp(&buf[14+16],broadcast_ipv4addr[0],4) && memcmp(&buf[14+16],broadcast_ipv4addr[1],4) && memcmp(&buf[14+16],broadcast_ipv4addr[2],4)) { BX_INFO(("target IP address %u.%u.%u.%u is unknown", (unsigned)buf[14+16],(unsigned)buf[14+17], (unsigned)buf[14+18],(unsigned)buf[14+19])); return; } // packet_id = get_net2(&buf[14+4]); fragment_flags = (unsigned)buf[14+6] >> 5; fragment_offset = ((unsigned)get_net2(&buf[14+6]) & 0x1fff) << 3; ipproto = buf[14+9]; if ((fragment_flags & 0x1) || (fragment_offset != 0)) { BX_INFO(("ignore fragmented packet!")); return; } else { l4pkt = &buf[14 + l3header_len]; l4pkt_len = total_len - l3header_len; } switch (ipproto) { case 0x01: // ICMP process_icmpipv4(&buf[14],l3header_len,l4pkt,l4pkt_len); break; case 0x06: // TCP process_tcpipv4(&buf[14],l3header_len,l4pkt,l4pkt_len); break; case 0x11: // UDP process_udpipv4(&buf[14],l3header_len,l4pkt,l4pkt_len); break; default: BX_INFO(("unknown IP protocol %02x",ipproto)); break; } } void bx_vnet_pktmover_c::host_to_guest_ipv4(Bit8u *buf, unsigned io_len) { unsigned l3header_len; memcpy(&buf[0],&dhcp.guest_macaddr[0],6); memcpy(&buf[6],&dhcp.host_macaddr[0],6); buf[12]=0x08; buf[13]=0x00; buf[14+0] = (buf[14+0] & 0x0f) | 0x40; l3header_len = ((unsigned)(buf[14+0] & 0x0f) << 2); memcpy(&buf[14+12],&dhcp.host_ipv4addr[0],4); memcpy(&buf[14+16],&dhcp.guest_ipv4addr[0],4); put_net2(&buf[14+10], 0); put_net2(&buf[14+10], ip_checksum(&buf[14],l3header_len) ^ (Bit16u)0xffff); host_to_guest(buf,io_len); } layer4_handler_t bx_vnet_pktmover_c::get_layer4_handler( unsigned ipprotocol, unsigned port) { unsigned n; for (n = 0; n < l4data_used; n++) { if (l4data[n].ipprotocol == ipprotocol && l4data[n].port == port) return l4data[n].func; } return (layer4_handler_t)NULL; } bx_bool bx_vnet_pktmover_c::register_layer4_handler( unsigned ipprotocol, unsigned port,layer4_handler_t func) { if (get_layer4_handler(ipprotocol,port) != (layer4_handler_t)NULL) { BX_INFO(("IP protocol 0x%02x port %u is already in use", ipprotocol,port)); return false; } unsigned n; for (n = 0; n < l4data_used; n++) { if (l4data[n].func == (layer4_handler_t)NULL) { break; } } if (n == l4data_used) { if (n >= LAYER4_LISTEN_MAX) { BX_ERROR(("vnet: LAYER4_LISTEN_MAX is too small")); return false; } l4data_used++; } l4data[n].ipprotocol = ipprotocol; l4data[n].port = port; l4data[n].func = func; return true; } bx_bool bx_vnet_pktmover_c::unregister_layer4_handler( unsigned ipprotocol, unsigned port) { unsigned n; for (n = 0; n < l4data_used; n++) { if (l4data[n].ipprotocol == ipprotocol && l4data[n].port == port) { l4data[n].func = (layer4_handler_t)NULL; return true; } } BX_ERROR(("IP protocol 0x%02x port %u is not registered", ipprotocol,port)); return false; } void bx_vnet_pktmover_c::process_icmpipv4( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len) { unsigned icmptype; unsigned icmpcode; if (l4pkt_len < 8) return; icmptype = l4pkt[0]; icmpcode = l4pkt[1]; if (ip_checksum(l4pkt,l4pkt_len) != (Bit16u)0xffff) { BX_INFO(("icmp: invalid checksum")); return; } switch (icmptype) { case 0x08: // ECHO if (icmpcode == 0) { process_icmpipv4_echo(ipheader,ipheader_len,l4pkt,l4pkt_len); } break; default: BX_INFO(("unhandled icmp packet: type=%u code=%u", icmptype, icmpcode)); break; } } void bx_vnet_pktmover_c::process_tcpipv4( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len) { if (l4pkt_len < 20) return; BX_INFO(("tcp packet - not implemented")); } void bx_vnet_pktmover_c::process_udpipv4( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len) { unsigned udp_targetport; unsigned udp_sourceport; // unsigned udp_len; layer4_handler_t func; if (l4pkt_len < 8) return; udp_sourceport = get_net2(&l4pkt[0]); udp_targetport = get_net2(&l4pkt[2]); // udp_len = get_net2(&l4pkt[4]); func = get_layer4_handler(0x11,udp_targetport); if (func != (layer4_handler_t)NULL) { (*func)((void *)this,ipheader,ipheader_len, udp_sourceport,udp_targetport,&l4pkt[8],l4pkt_len-8); } else { BX_INFO(("udp - unhandled port %u",udp_targetport)); } } void bx_vnet_pktmover_c::host_to_guest_udpipv4_packet( unsigned target_port, unsigned source_port, const Bit8u *udpdata, unsigned udpdata_len) { Bit8u ipbuf[BX_PACKET_BUFSIZE]; if ((udpdata_len + 42U) > BX_PACKET_BUFSIZE) { BX_PANIC(("generated udp data is too long")); return; } // udp pseudo-header ipbuf[34U-12U]=0; ipbuf[34U-11U]=0x11; // UDP put_net2(&ipbuf[34U-10U],8U+udpdata_len); memcpy(&ipbuf[34U-8U],dhcp.host_ipv4addr,4); memcpy(&ipbuf[34U-4U],dhcp.guest_ipv4addr,4); // udp header put_net2(&ipbuf[34U+0],source_port); put_net2(&ipbuf[34U+2],target_port); put_net2(&ipbuf[34U+4],8U+udpdata_len); put_net2(&ipbuf[34U+6],0); memcpy(&ipbuf[42U],udpdata,udpdata_len); put_net2(&ipbuf[34U+6], ip_checksum(&ipbuf[34U-12U],12U+8U+udpdata_len) ^ (Bit16u)0xffff); // ip header memset(&ipbuf[14U],0,20U); ipbuf[14U+0] = 0x45; ipbuf[14U+1] = 0x00; put_net2(&ipbuf[14U+2],20U+8U+udpdata_len); put_net2(&ipbuf[14U+4],1); ipbuf[14U+6] = 0x00; ipbuf[14U+7] = 0x00; ipbuf[14U+8] = 0x07; // TTL ipbuf[14U+9] = 0x11; // UDP host_to_guest_ipv4(ipbuf,udpdata_len + 42U); } ///////////////////////////////////////////////////////////////////////// // ICMP/IPv4 ///////////////////////////////////////////////////////////////////////// void bx_vnet_pktmover_c::process_icmpipv4_echo( const Bit8u *ipheader, unsigned ipheader_len, const Bit8u *l4pkt, unsigned l4pkt_len) { Bit8u replybuf[ICMP_ECHO_PACKET_MAX]; if ((14U+ipheader_len+l4pkt_len) > ICMP_ECHO_PACKET_MAX) { BX_ERROR(("icmp echo: size of an echo packet is too long")); return; } memcpy(&replybuf[14],ipheader,ipheader_len); memcpy(&replybuf[14+ipheader_len],l4pkt,l4pkt_len); replybuf[14+ipheader_len+0] = 0x00; // echo reply put_net2(&replybuf[14+ipheader_len+2],0); put_net2(&replybuf[14+ipheader_len+2], ip_checksum(&replybuf[14+ipheader_len],l4pkt_len) ^ (Bit16u)0xffff); host_to_guest_ipv4(replybuf,14U+ipheader_len+l4pkt_len); } ///////////////////////////////////////////////////////////////////////// // DHCP/UDP/IPv4 ///////////////////////////////////////////////////////////////////////// void bx_vnet_pktmover_c::udpipv4_dhcp_handler( void *this_ptr, const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len) { ((bx_vnet_pktmover_c *)this_ptr)->udpipv4_dhcp_handler_ns( ipheader,ipheader_len,sourceport,targetport,data,data_len); } void bx_vnet_pktmover_c::udpipv4_dhcp_handler_ns( const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len) { Bit8u replybuf[576]; unsigned opts_len; opts_len = process_dhcp(netdev, data, data_len, replybuf, &dhcp); if (opts_len > 0) { host_to_guest_udpipv4_packet(sourceport, targetport, replybuf, opts_len); } } void bx_vnet_pktmover_c::udpipv4_tftp_handler( void *this_ptr, const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len) { ((bx_vnet_pktmover_c *)this_ptr)->udpipv4_tftp_handler_ns( ipheader,ipheader_len,sourceport,targetport,data,data_len); } void bx_vnet_pktmover_c::udpipv4_tftp_handler_ns( const Bit8u *ipheader, unsigned ipheader_len, unsigned sourceport, unsigned targetport, const Bit8u *data, unsigned data_len) { Bit8u replybuf[TFTP_BUFFER_SIZE + 4]; int len; len = process_tftp(netdev, data, data_len, sourceport, replybuf, &tftp); if (len > 0) { host_to_guest_udpipv4_packet(sourceport, targetport, replybuf, len); } } #endif /* if BX_NETWORKING */ bochs-2.6/iodev/network/eth_slirp.cc0000644000175000017500000004427212020641503017436 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_slirp.cc 11342 2012-08-16 11:59:44Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2011 Heikki Lindholm // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // eth_slirp.cc - slirp backend to eth #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING && BX_NETMOD_SLIRP #include #include #include #include #include #include #include #include /* ntohs, htons */ #define LOG_THIS netdev-> #define BX_ETH_SLIRP_LOGGING 0 #if defined(_MSC_VER) #pragma pack(push, 1) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=packed #endif // this should not be smaller than an arp reply with an ethernet header #define MIN_RX_PACKET_LEN 60 #define ETHERNET_MAC_ADDR_LEN 6 #define ETHERNET_TYPE_IPV4 0x0800 #define ETHERNET_TYPE_ARP 0x0806 typedef struct ethernet_header { #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif Bit8u dst_mac_addr[ETHERNET_MAC_ADDR_LEN]; Bit8u src_mac_addr[ETHERNET_MAC_ADDR_LEN]; Bit16u type; } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif ethernet_header_t; #define ARP_OPCODE_REQUEST 1 #define ARP_OPCODE_REPLY 2 typedef struct arp_header { #if defined(_MSC_VER) && (_MSC_VER>=1300) __declspec(align(1)) #endif Bit16u hw_addr_space; Bit16u proto_addr_space; Bit8u hw_addr_len; Bit8u proto_addr_len; Bit16u opcode; /* HW address of sender */ /* Protocol address of sender */ /* HW address of target*/ /* Protocol address of target */ } #if !defined(_MSC_VER) GCC_ATTRIBUTE((packed)) #endif arp_header_t; #if defined(_MSC_VER) #pragma pack(pop) #elif defined(__MWERKS__) && defined(macintosh) #pragma options align=reset #endif const Bit8u default_host_ipv4addr[4] = {10, 0, 2, 2}; const Bit8u default_dns_ipv4addr[4] = {10, 0, 2, 3}; const Bit8u default_guest_ipv4addr[4] = {10, 0, 2, 15}; const Bit8u broadcast_ipv4addr[3][4] = { { 0, 0, 0, 0}, {255,255,255,255}, { 10, 0, 2,255}, }; #define SLIP_END 192 #define SLIP_ESC 219 #define SLIP_ESC_END 220 #define SLIP_ESC_ESC 221 static size_t encode_slip(Bit8u *src, Bit8u *dst, size_t src_len) { Bit8u *dst_start = dst; Bit8u *src_end = src + src_len; while (src < src_end) { switch (*src) { case SLIP_END: *dst++ = SLIP_ESC; *dst++ = SLIP_ESC_END; break; case SLIP_ESC: *dst++ = SLIP_ESC; *dst++ = SLIP_ESC_ESC; break; default: *dst++ = *src; break; } src++; } *dst++ = SLIP_END; return dst - dst_start; } static int decode_slip(Bit8u *src, size_t *src_len, Bit8u *dst, size_t *dst_len) { Bit8u *dst_start = dst; Bit8u *src_start = src; Bit8u *src_end = src + *src_len; int got_packet = 0; if (*src_len == 0) { *dst_len = 0; return 0; } while ((src < (src_end - 1)) && (!got_packet)) { switch (*src) { case SLIP_END: if (dst != dst_start) // discard empty packets got_packet = 1; src++; break; case SLIP_ESC: switch (*++src) { case SLIP_ESC_ESC: *dst++ = SLIP_ESC; src++; break; case SLIP_ESC_END: *dst++ = SLIP_END; src++; break; default: *dst++ = *src++; break; } break; default: *dst++ = *src++; break; } } if ((!got_packet) && (src < src_end)) { switch (*src) { case SLIP_END: got_packet = 1; src++; break; case SLIP_ESC: break; default: *dst++ = *src++; break; } } *src_len = src - src_start; *dst_len = dst - dst_start; return got_packet; } class bx_slirp_pktmover_c : public eth_pktmover_c { public: bx_slirp_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: pid_t slirp_pid; int slirp_pipe_fds[2]; Bit8u slip_output_buffer[4096]; // TODO: reasonable size for these? Bit8u slip_input_buffer[4096]; size_t slip_input_buffer_filled; size_t slip_input_buffer_decoded; Bit8u reply_buffer[1024]; int pending_reply_size; dhcp_cfg_t dhcp; tftp_data_t tftp; int rx_timer_index; unsigned netdev_speed; unsigned tx_time; static void rx_timer_handler(void *); void rx_timer(); bx_bool handle_ipv4(const Bit8u *buf, unsigned len); void handle_arp(void *buf, unsigned len); void prepare_builtin_reply(unsigned type); #if BX_ETH_SLIRP_LOGGING FILE *pktlog_txt; #endif }; class bx_slirp_locator_c : public eth_locator_c { public: bx_slirp_locator_c(void) : eth_locator_c("slirp") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_slirp_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_slirp_match; bx_slirp_pktmover_c::bx_slirp_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { int flags; this->netdev = dev; BX_INFO(("slirp network driver")); if (socketpair(AF_UNIX, SOCK_STREAM, 0, slirp_pipe_fds)) BX_PANIC(("socketpair() failed: %s", strerror(errno))); // mark our end of the pipe non-blocking because of the timer based poll flags = fcntl(slirp_pipe_fds[0], F_GETFL); if (flags == -1) BX_PANIC(("fcntl(,F_GETFL) failed: %s", strerror(errno))); flags |= O_NONBLOCK; if (fcntl (slirp_pipe_fds[0], F_SETFL, flags) != 0) BX_PANIC(("fcntl(,F_SETFL,) failed: %s", strerror(errno))); slirp_pid = fork(); if (slirp_pid == -1) { BX_PANIC(("fork() failed: %s", strerror(errno))); } else if (slirp_pid == 0) { int ret; int nfd; nfd = open("/dev/null", O_RDWR); if (nfd != -1) { dup2(nfd, STDERR_FILENO); } if (dup2(slirp_pipe_fds[1], STDIN_FILENO) == -1) { BX_PANIC(("dup2() failed: %s", strerror(errno))); } /* XXX slirp seems to use stdin bidirectionally * instead of using stdout for SLIP output */ if (dup2(slirp_pipe_fds[1], STDOUT_FILENO) == -1) { BX_PANIC(("dup2() failed: %s", strerror(errno))); } close(slirp_pipe_fds[0]); ret = execlp(script == NULL ? "slirp" : script, script == NULL ? "slirp" : script, /*"-d", "-1", "-S",*/ NULL); if (ret == -1) { BX_PANIC(("execlp() failed: %s", strerror(errno))); } } this->rxh = rxh; this->rxstat = rxstat; strcpy(this->tftp.rootdir, netif); this->tftp.tid = 0; this->tftp.write = 0; Bit32u status = this->rxstat(this->netdev) & BX_NETDEV_SPEED; this->netdev_speed = (status == BX_NETDEV_1GBIT) ? 1000 : (status == BX_NETDEV_100MBIT) ? 100 : 10; this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, 1, 1, "eth_slirp"); memcpy(&dhcp.guest_macaddr[0], macaddr, ETHERNET_MAC_ADDR_LEN); // ensure the slirp host has a different mac address memcpy(&dhcp.host_macaddr[0], macaddr, ETHERNET_MAC_ADDR_LEN); dhcp.host_macaddr[5] ^= 0x03; memcpy(&dhcp.host_ipv4addr[0], &default_host_ipv4addr[0], 4); memcpy(&dhcp.guest_ipv4addr[0], &broadcast_ipv4addr[1][0], 4); dhcp.default_guest_ipv4addr = default_guest_ipv4addr; memcpy(&dhcp.dns_ipv4addr[0], &default_dns_ipv4addr[0], 4); pending_reply_size = 0; slip_input_buffer_filled = slip_input_buffer_decoded = 0; close(slirp_pipe_fds[1]); #if BX_ETH_SLIRP_LOGGING pktlog_txt = fopen("ne2k-pktlog.txt", "wb"); if (!pktlog_txt) BX_PANIC(("ne2k-pktlog.txt failed")); fprintf(pktlog_txt, "slirp packetmover readable log file\n"); fprintf(pktlog_txt, "host MAC address = "); int i; for (i=0; i<6; i++) fprintf(pktlog_txt, "%02x%s", 0xff & host_mac_addr[i], i<5?":" : "\n"); fprintf(pktlog_txt, "guest MAC address = "); for (i=0; i<6; i++) fprintf(pktlog_txt, "%02x%s", 0xff & guest_mac_addr[i], i<5?":" : "\n"); fprintf(pktlog_txt, "--\n"); fflush(pktlog_txt); #endif } void bx_slirp_pktmover_c::handle_arp(void *buf, unsigned len) { arp_header_t *arphdr = (arp_header_t *)((Bit8u *)buf + sizeof(ethernet_header_t)); if (pending_reply_size > 0) return; if ((ntohs(arphdr->hw_addr_space) != 0x0001) || (ntohs(arphdr->proto_addr_space) != 0x0800) || (arphdr->hw_addr_len != ETHERNET_MAC_ADDR_LEN) || (arphdr->proto_addr_len != 4)) { BX_ERROR(("Unhandled ARP message hw: %04x (%d) proto: %04x (%d)\n", ntohs(arphdr->hw_addr_space), arphdr->hw_addr_len, ntohs(arphdr->proto_addr_space), arphdr->proto_addr_len)); return; } arp_header_t *arprhdr = (arp_header_t *)((Bit8u *)reply_buffer + sizeof(ethernet_header_t)); switch(ntohs(arphdr->opcode)) { case ARP_OPCODE_REQUEST: // Slirp uses addresses x.x.x.0 - x.x.x.3 if (((Bit8u *)arphdr)[27] > 3) break; memset(reply_buffer, 0, MIN_RX_PACKET_LEN); arprhdr->hw_addr_space = htons(0x0001); arprhdr->proto_addr_space = htons(0x0800); arprhdr->hw_addr_len = ETHERNET_MAC_ADDR_LEN; arprhdr->proto_addr_len = 4; arprhdr->opcode = htons(ARP_OPCODE_REPLY); memcpy((Bit8u *)arprhdr+8, dhcp.host_macaddr, ETHERNET_MAC_ADDR_LEN); memcpy((Bit8u *)arprhdr+14, (Bit8u *)arphdr+24, 4); memcpy((Bit8u *)arprhdr+18, dhcp.guest_macaddr, ETHERNET_MAC_ADDR_LEN); memcpy((Bit8u *)arprhdr+24, (Bit8u *)arphdr+14, 4); pending_reply_size = MIN_RX_PACKET_LEN; prepare_builtin_reply(ETHERNET_TYPE_ARP); break; case ARP_OPCODE_REPLY: break; default: break; } } // detect and handle DHCP request (partly copy & paste from eth_vnet.cc) bx_bool bx_slirp_pktmover_c::handle_ipv4(const Bit8u *buf, unsigned len) { unsigned total_len; unsigned fragment_flags; unsigned fragment_offset; unsigned ipproto; unsigned l3header_len; const Bit8u *l4pkt; unsigned l4pkt_len; unsigned udp_sourceport; unsigned udp_targetport; unsigned udp_reply_size; // guest-to-host IPv4 if (len < (14U+20U)) { return 0; } if ((buf[14+0] & 0xf0) != 0x40) { return 0; } l3header_len = ((unsigned)(buf[14+0] & 0x0f) << 2); if (l3header_len != 20) { return 0; } if (len < (14U+l3header_len)) return 0; if (ip_checksum(&buf[14],l3header_len) != (Bit16u)0xffff) { return 0; } total_len = get_net2(&buf[14+2]); if (memcmp(&buf[14+16],dhcp.host_ipv4addr, 4) && memcmp(&buf[14+16],broadcast_ipv4addr[0],4) && memcmp(&buf[14+16],broadcast_ipv4addr[1],4) && memcmp(&buf[14+16],broadcast_ipv4addr[2],4)) { return 0; } fragment_flags = (unsigned)buf[14+6] >> 5; fragment_offset = ((unsigned)get_net2(&buf[14+6]) & 0x1fff) << 3; ipproto = buf[14+9]; if ((fragment_flags & 0x1) || (fragment_offset != 0)) { return 0; } else { l4pkt = &buf[14 + l3header_len]; l4pkt_len = total_len - l3header_len; } if (ipproto == 0x11) { // guest-to-host UDP IPv4 if (l4pkt_len < 8) return 0; udp_sourceport = get_net2(&l4pkt[0]); udp_targetport = get_net2(&l4pkt[2]); if ((udp_targetport == 67) || (udp_targetport == 69)) { // BOOTP & TFTP if (udp_targetport == 67) { // BOOTP udp_reply_size = process_dhcp(netdev, &l4pkt[8], l4pkt_len-8, &reply_buffer[42], &dhcp); } else { udp_reply_size = process_tftp(netdev, &l4pkt[8], l4pkt_len-8, udp_sourceport, &reply_buffer[42], &tftp); } if (udp_reply_size > 0) { pending_reply_size = udp_reply_size + 42; // host-to-guest UDP IPv4: pseudo-header reply_buffer[22] = 0; reply_buffer[23] = 0x11; // UDP put_net2(&reply_buffer[24], 8U+udp_reply_size); memcpy(&reply_buffer[26], dhcp.host_ipv4addr, 4); memcpy(&reply_buffer[30], dhcp.guest_ipv4addr, 4); // udp header put_net2(&reply_buffer[34], udp_targetport); put_net2(&reply_buffer[36], udp_sourceport); put_net2(&reply_buffer[38], 8U+udp_reply_size); put_net2(&reply_buffer[40], 0); put_net2(&reply_buffer[40], ip_checksum(&reply_buffer[22], 12U+8U+udp_reply_size) ^ (Bit16u)0xffff); // ip header memset(&reply_buffer[14], 0, 20); reply_buffer[14] = 0x45; reply_buffer[15] = 0x00; put_net2(&reply_buffer[16], 20U+8U+udp_reply_size); put_net2(&reply_buffer[18], 1); reply_buffer[20] = 0x00; reply_buffer[21] = 0x00; reply_buffer[22] = 0x07; // TTL reply_buffer[23] = 0x11; // UDP // host-to-guest IPv4 reply_buffer[14] = (reply_buffer[14] & 0x0f) | 0x40; l3header_len = ((unsigned)(reply_buffer[14] & 0x0f) << 2); memcpy(&reply_buffer[26], &dhcp.host_ipv4addr[0], 4); memcpy(&reply_buffer[30], &dhcp.guest_ipv4addr[0], 4); put_net2(&reply_buffer[24], 0); put_net2(&reply_buffer[24], ip_checksum(&reply_buffer[14], l3header_len) ^ (Bit16u)0xffff); prepare_builtin_reply(ETHERNET_TYPE_IPV4); } // don't forward DHCP / TFTP requests to Slirp return 1; } } return 0; } void bx_slirp_pktmover_c::sendpkt(void *buf, unsigned io_len) { size_t len; ethernet_header_t *ethhdr = (ethernet_header_t *)buf; #if BX_ETH_SLIRP_LOGGING write_pktlog_txt(pktlog_txt, (Bit8u*)buf, io_len, 0); #endif this->tx_time = (64 + 96 + 4 * 8 + io_len * 8) / this->netdev_speed; switch (ntohs(ethhdr->type)) { case ETHERNET_TYPE_IPV4: if (!handle_ipv4((Bit8u*)buf, io_len)) { len = encode_slip((Bit8u *)buf+sizeof(ethernet_header_t), slip_output_buffer, io_len-sizeof(ethernet_header_t)); len = write(slirp_pipe_fds[0], slip_output_buffer, len); } break; case ETHERNET_TYPE_ARP: handle_arp(buf, io_len); break; default: break; } } void bx_slirp_pktmover_c::prepare_builtin_reply(unsigned type) { ethernet_header_t *ethhdr; unsigned rx_time; ethhdr = (ethernet_header_t *)reply_buffer; memcpy(ethhdr->dst_mac_addr, dhcp.guest_macaddr, ETHERNET_MAC_ADDR_LEN); memcpy(ethhdr->src_mac_addr, dhcp.host_macaddr, ETHERNET_MAC_ADDR_LEN); ethhdr->type = htons(type); rx_time = (64 + 96 + 4 * 8 + pending_reply_size * 8) / this->netdev_speed; bx_pc_system.activate_timer(this->rx_timer_index, this->tx_time + rx_time + 100, 0); } void bx_slirp_pktmover_c::rx_timer_handler(void *this_ptr) { bx_slirp_pktmover_c *class_ptr = (bx_slirp_pktmover_c *)this_ptr; class_ptr->rx_timer(); } void bx_slirp_pktmover_c::rx_timer() { Bit8u *packet; Bit8u padded_packet[MIN_RX_PACKET_LEN]; ethernet_header_t *ethhdr; size_t packet_len; if (pending_reply_size > 0) { #if BX_ETH_SLIRP_LOGGING write_pktlog_txt(pktlog_txt, reply_buffer, pending_reply_size, 1); #endif if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, reply_buffer, pending_reply_size); } else { BX_ERROR(("device not ready to receive data")); } pending_reply_size = 0; // restore timer bx_pc_system.activate_timer(this->rx_timer_index, 1000, 1); return; } Bit8u *buf = slip_input_buffer + sizeof(ethernet_header_t); ssize_t n; int got_packet; size_t ilen, olen, pos; if (slip_input_buffer_filled + sizeof(ethernet_header_t) < sizeof(slip_input_buffer)) { n = read(slirp_pipe_fds[0], buf+slip_input_buffer_filled, (sizeof(slip_input_buffer) - sizeof(ethernet_header_t)) - slip_input_buffer_filled); if (n < 1) return; slip_input_buffer_filled += n; } packet = (Bit8u *)slip_input_buffer; ethhdr = (ethernet_header_t *)packet; memcpy(ethhdr->dst_mac_addr, dhcp.guest_macaddr, ETHERNET_MAC_ADDR_LEN); memcpy(ethhdr->src_mac_addr, dhcp.host_macaddr, ETHERNET_MAC_ADDR_LEN); ethhdr->type = htons(ETHERNET_TYPE_IPV4); olen = 0; pos = slip_input_buffer_decoded; do { ilen = slip_input_buffer_filled - slip_input_buffer_decoded; got_packet = decode_slip(buf + pos, &ilen, buf + slip_input_buffer_decoded, &olen); pos += ilen; slip_input_buffer_filled -= ilen; slip_input_buffer_filled += olen; slip_input_buffer_decoded += olen; if (got_packet) { packet_len = sizeof(ethernet_header_t) + slip_input_buffer_decoded; if (packet_len < MIN_RX_PACKET_LEN) { packet = padded_packet; bzero(packet, MIN_RX_PACKET_LEN); memcpy(packet, slip_input_buffer, packet_len); packet_len = MIN_RX_PACKET_LEN; } #if BX_ETH_SLIRP_LOGGING write_pktlog_txt(pktlog_txt, packet, packet_len, 1); #endif (*rxh)(this->netdev, packet, packet_len); slip_input_buffer_filled -= slip_input_buffer_decoded; slip_input_buffer_decoded = 0; } } while (got_packet); if ((slip_input_buffer_filled - slip_input_buffer_decoded) > 0) memmove(slip_input_buffer + slip_input_buffer_decoded, slip_input_buffer + pos, (slip_input_buffer_filled - slip_input_buffer_decoded)); } #endif /* if BX_NETWORKING && BX_NETMOD_SLIRP */ bochs-2.6/iodev/network/pcipnic.h0000644000175000017500000000621012020641503016722 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pcipnic.h 11231 2012-06-24 17:42:24Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2003 Fen Systems Ltd. // http://www.fensystems.co.uk/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_PCIPNIC_H #define BX_IODEV_PCIPNIC_H #include "pnic_api.h" #if BX_USE_PCIPNIC_SMF # define BX_PNIC_SMF static # define BX_PNIC_THIS thePNICDevice-> # define BX_PNIC_THIS_PTR thePNICDevice #else # define BX_PNIC_SMF # define BX_PNIC_THIS this-> # define BX_PNIC_THIS_PTR this #endif #define PNIC_DATA_SIZE 4096 #define PNIC_RECV_RINGS 4 typedef struct { Bit8u macaddr[6]; Bit8u irqEnabled; Bit16u rCmd; // Command register Bit16u rStatus; // Status register Bit16u rLength; // Length register Bit8u rData[PNIC_DATA_SIZE]; // Data register array Bit16u rDataCursor; int recvIndex; int recvQueueLength; Bit8u recvRing[PNIC_RECV_RINGS][PNIC_DATA_SIZE]; // Receive buffer Bit16u recvRingLength[PNIC_RECV_RINGS]; Bit8u devfunc; int statusbar_id; } bx_pnic_t; class bx_pcipnic_c : public bx_devmodel_c, bx_pci_device_stub_c { public: bx_pcipnic_c(); virtual ~bx_pcipnic_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); private: bx_pnic_t s; static void set_irq_level(bx_bool level); static void pnic_timer_handler(void *); void pnic_timer(void); BX_PNIC_SMF bx_bool mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param); BX_PNIC_SMF bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_PCIPNIC_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif eth_pktmover_c *ethdev; static void exec_command(void); static Bit32u rx_status_handler(void *arg); BX_PNIC_SMF Bit32u rx_status(void); static void rx_handler(void *arg, const void *buf, unsigned len); BX_PNIC_SMF void rx_frame(const void *buf, unsigned io_len); }; #endif bochs-2.6/iodev/network/pcipnic.cc0000644000175000017500000004711512020641503017071 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pcipnic.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2003 Fen Systems Ltd. // http://www.fensystems.co.uk/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_PCIPNIC #include "pci.h" #include "netmod.h" #include "pcipnic.h" #define LOG_THIS thePNICDevice-> bx_pcipnic_c* thePNICDevice = NULL; const Bit8u pnic_iomask[16] = {2, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // builtin configuration handling functions void pnic_init_options(void) { bx_param_c *network = SIM->get_param("network"); bx_list_c *menu = new bx_list_c(network, "pcipnic", "PCI Pseudo NIC"); menu->set_options(menu->SHOW_PARENT); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", "Enable Pseudo NIC emulation", "Enables the Pseudo NIC emulation", 0); SIM->init_std_nic_options("Pseudo NIC", menu); enabled->set_dependent_list(menu->clone()); } Bit32s pnic_options_parser(const char *context, int num_params, char *params[]) { int ret, valid = 0; if (!strcmp(params[0], "pcipnic")) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_PNIC); if (!SIM->get_param_bool("enabled", base)->get()) { SIM->get_param_enum("ethmod", base)->set_by_name("null"); } for (int i = 1; i < num_params; i++) { ret = SIM->parse_nic_params(context, params[i], base); if (ret > 0) { valid |= ret; } } if (!SIM->get_param_bool("enabled", base)->get()) { if (valid == 0x04) { SIM->get_param_bool("enabled", base)->set(1); } else if (valid < 0x80) { BX_PANIC(("%s: 'pcipnic' directive incomplete (mac is required)", context)); } } else { if (valid & 0x80) { SIM->get_param_bool("enabled", base)->set(0); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s pnic_options_save(FILE *fp) { SIM->write_pci_nic_options(fp, (bx_list_c*) SIM->get_param(BXPN_PNIC)); return 0; } // device plugin entry points int libpcipnic_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { thePNICDevice = new bx_pcipnic_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePNICDevice, BX_PLUGIN_PCIPNIC); // add new configuration parameter for the config interface pnic_init_options(); // register add-on option for bochsrc and command line SIM->register_addon_option("pcipnic", pnic_options_parser, pnic_options_save); return 0; // Success } void libpcipnic_LTX_plugin_fini(void) { SIM->unregister_addon_option("pcipnic"); bx_list_c *menu = (bx_list_c*)SIM->get_param("network"); menu->remove("pnic"); delete thePNICDevice; } // the device object bx_pcipnic_c::bx_pcipnic_c() { put("pcipnic", "PNIC"); memset(&s, 0, sizeof(bx_pnic_t)); ethdev = NULL; } bx_pcipnic_c::~bx_pcipnic_c() { if (ethdev != NULL) { delete ethdev; } SIM->get_bochs_root()->remove("pcipnic"); BX_DEBUG(("Exit")); } void bx_pcipnic_c::init(void) { bx_list_c *base; const char *bootrom; // Read in values from config interface base = (bx_list_c*) SIM->get_param(BXPN_PNIC); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", base)->get()) { BX_INFO(("PCI Pseudo NIC disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("pcipnic"))->set(0); return; } memcpy(BX_PNIC_THIS s.macaddr, SIM->get_param_string("macaddr", base)->getptr(), 6); BX_PNIC_THIS s.devfunc = 0x00; DEV_register_pci_handlers(this, &BX_PNIC_THIS s.devfunc, BX_PLUGIN_PCIPNIC, "Experimental PCI Pseudo NIC"); for (unsigned i=0; i<256; i++) { BX_PNIC_THIS pci_conf[i] = 0x0; } BX_PNIC_THIS s.statusbar_id = bx_gui->register_statusitem("PNIC", 1); // Attach to the selected ethernet module BX_PNIC_THIS ethdev = DEV_net_init_module(base, rx_handler, rx_status_handler, this); BX_PNIC_THIS pci_base_address[4] = 0; BX_PNIC_THIS pci_rom_address = 0; bootrom = SIM->get_param_string("bootrom", base)->getptr(); if (strlen(bootrom) > 0) { BX_PNIC_THIS load_pci_rom(bootrom); } BX_INFO(("PCI Pseudo NIC initialized")); } void bx_pcipnic_c::reset(unsigned type) { unsigned i; static const struct reset_vals_t { unsigned addr; unsigned char val; } reset_vals[] = { { 0x00, PNIC_PCI_VENDOR & 0xff }, { 0x01, PNIC_PCI_VENDOR >> 8 }, { 0x02, PNIC_PCI_DEVICE & 0xff }, { 0x03, PNIC_PCI_DEVICE >> 8 }, { 0x04, 0x01 }, { 0x05, 0x00 }, // command_io { 0x06, 0x00 }, { 0x07, 0x00 }, // status { 0x08, 0x01 }, // revision number { 0x09, 0x00 }, // interface { 0x0a, 0x00 }, // class_sub { 0x0b, 0x02 }, // class_base Network Controller { 0x0D, 0x20 }, // bus latency { 0x0e, 0x00 }, // header_type_generic // address space 0x20 - 0x23 { 0x20, 0x01 }, { 0x21, 0x00 }, { 0x22, 0x00 }, { 0x23, 0x00 }, { 0x3c, 0x00, }, // IRQ { 0x3d, BX_PCI_INTA }, // INT { 0x6a, 0x01 }, // PNIC clock { 0xc1, 0x20 } // PIRQ enable }; for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { BX_PNIC_THIS pci_conf[reset_vals[i].addr] = reset_vals[i].val; } // Set up initial register values BX_PNIC_THIS s.rCmd = PNIC_CMD_NOOP; BX_PNIC_THIS s.rStatus = PNIC_STATUS_OK; BX_PNIC_THIS s.rLength = 0; BX_PNIC_THIS s.rDataCursor = 0; BX_PNIC_THIS s.recvIndex = 0; BX_PNIC_THIS s.recvQueueLength = 0; BX_PNIC_THIS s.irqEnabled = 0; // Deassert IRQ set_irq_level(0); } void bx_pcipnic_c::register_state(void) { char name[6]; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "pcipnic", "PCI Pseudo NIC State"); new bx_shadow_num_c(list, "irqEnabled", &BX_PNIC_THIS s.irqEnabled); new bx_shadow_num_c(list, "rCmd", &BX_PNIC_THIS s.rCmd); new bx_shadow_num_c(list, "rStatus", &BX_PNIC_THIS s.rStatus); new bx_shadow_num_c(list, "rLength", &BX_PNIC_THIS s.rLength); new bx_shadow_num_c(list, "rDataCursor", &BX_PNIC_THIS s.rDataCursor); new bx_shadow_num_c(list, "recvIndex", &BX_PNIC_THIS s.recvIndex); new bx_shadow_num_c(list, "recvQueueLength", &BX_PNIC_THIS s.recvQueueLength); bx_list_c *recvRL = new bx_list_c(list, "recvRingLength"); for (unsigned i=0; i 0) { if (DEV_pci_set_base_mem(BX_PNIC_THIS_PTR, mem_read_handler, mem_write_handler, &BX_PNIC_THIS pci_rom_address, &BX_PNIC_THIS pci_conf[0x30], BX_PNIC_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_PNIC_THIS pci_rom_address)); } } } void bx_pcipnic_c::set_irq_level(bx_bool level) { DEV_pci_set_irq(BX_PNIC_THIS s.devfunc, BX_PNIC_THIS pci_conf[0x3d], level); } bx_bool bx_pcipnic_c::mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; Bit32u mask = (BX_PNIC_THIS pci_rom_size - 1); #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { if (BX_PNIC_THIS pci_conf[0x30] & 0x01) { *data_ptr = BX_PNIC_THIS pci_rom[addr & mask]; } else { *data_ptr = 0xff; } addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } bx_bool bx_pcipnic_c::mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { BX_INFO(("write to ROM ignored (addr=0x%08x len=%d)", (Bit32u)addr, len)); return 1; } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_pcipnic_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_PCIPNIC_SMF bx_pcipnic_c *class_ptr = (bx_pcipnic_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_pcipnic_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PCIPNIC_SMF Bit32u val = 0x0; Bit8u offset; BX_DEBUG(("register read from address 0x%04x - ", (unsigned) address)); offset = address - BX_PNIC_THIS pci_base_address[4]; switch (offset) { case PNIC_REG_STAT: val = BX_PNIC_THIS s.rStatus; break; case PNIC_REG_LEN: val = BX_PNIC_THIS s.rLength; break; case PNIC_REG_DATA: if (BX_PNIC_THIS s.rDataCursor >= BX_PNIC_THIS s.rLength) BX_PANIC(("PNIC read at %u, beyond end of data register array", BX_PNIC_THIS s.rDataCursor)); val = BX_PNIC_THIS s.rData[BX_PNIC_THIS s.rDataCursor++]; break; default : val = 0; // keep compiler happy BX_PANIC(("unsupported io read from address=0x%04x!", (unsigned) address)); break; } BX_DEBUG(("val = 0x%04x", (Bit16u) val)); return(val); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_pcipnic_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_PCIPNIC_SMF bx_pcipnic_c *class_ptr = (bx_pcipnic_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_pcipnic_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_PCIPNIC_SMF Bit8u offset; BX_DEBUG(("register write to address 0x%04x - ", (unsigned) address)); offset = address - BX_PNIC_THIS pci_base_address[4]; switch (offset) { case PNIC_REG_CMD: BX_PNIC_THIS s.rCmd = value; BX_PNIC_THIS exec_command(); break; case PNIC_REG_LEN: if (value > PNIC_DATA_SIZE) BX_PANIC(("PNIC bad length %u written to length register, max is %u", value, PNIC_DATA_SIZE)); BX_PNIC_THIS s.rLength = value; BX_PNIC_THIS s.rDataCursor = 0; break; case PNIC_REG_DATA: if (BX_PNIC_THIS s.rDataCursor >= BX_PNIC_THIS s.rLength) BX_PANIC(("PNIC write at %u, beyond end of data register array", BX_PNIC_THIS s.rDataCursor)); BX_PNIC_THIS s.rData[BX_PNIC_THIS s.rDataCursor++] = value; break; default: BX_PANIC(("unsupported io write to address=0x%04x!", (unsigned) address)); break; } } void bx_pcipnic_c::pnic_timer_handler(void *this_ptr) { bx_pcipnic_c *class_ptr = (bx_pcipnic_c *) this_ptr; class_ptr->pnic_timer(); } // Called once every 1ms void bx_pcipnic_c::pnic_timer(void) { // Do nothing atm } // pci configuration space read callback handler Bit32u bx_pcipnic_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x10) && (address < 0x20)) || ((address > 0x23) && (address < 0x30))) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_PNIC_THIS pci_conf[address+i]; switch (address+i) { case 0x04: value8 &= 0x01; break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); } break; case 0x20: value8 = (value8 & 0xfc) | 0x01; case 0x21: case 0x22: case 0x23: baseaddr_change = (value8 != oldval); break; case 0x30: case 0x31: case 0x32: case 0x33: if (BX_PNIC_THIS pci_rom_size > 0) { if ((address+i) == 0x30) { value8 &= 0x01; } else if ((address+i) == 0x31) { value8 &= 0xfc; } romaddr_change = 1; break; } default: value8 = oldval; } BX_PNIC_THIS pci_conf[address+i] = value8; } if (baseaddr_change) { if (DEV_pci_set_base_io(BX_PNIC_THIS_PTR, read_handler, write_handler, &BX_PNIC_THIS pci_base_address[4], &BX_PNIC_THIS pci_conf[0x20], 16, &pnic_iomask[0], "PNIC")) { BX_INFO(("new base address: 0x%04x", BX_PNIC_THIS pci_base_address[4])); } } if (romaddr_change) { if (DEV_pci_set_base_mem(BX_PNIC_THIS_PTR, mem_read_handler, mem_write_handler, &BX_PNIC_THIS pci_rom_address, &BX_PNIC_THIS pci_conf[0x30], BX_PNIC_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_PNIC_THIS pci_rom_address)); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } /* * Execute a hardware command. */ void bx_pcipnic_c::exec_command(void) { Bit16u command = BX_PNIC_THIS s.rCmd; Bit16u ilength = BX_PNIC_THIS s.rLength; Bit8u *data = BX_PNIC_THIS s.rData; // Default return values Bit16u status = PNIC_STATUS_UNKNOWN_CMD; Bit16u olength = 0; if (ilength != BX_PNIC_THIS s.rDataCursor) BX_PANIC(("PNIC command issued with incomplete data (should be %u, is %u)", ilength, BX_PNIC_THIS s.rDataCursor)); switch (command) { case PNIC_CMD_NOOP: status = PNIC_STATUS_OK; break; case PNIC_CMD_API_VER: Bit16u api_version; api_version = PNIC_API_VERSION; olength = sizeof(api_version); memcpy (data, &api_version, sizeof(api_version)); status = PNIC_STATUS_OK; break; case PNIC_CMD_READ_MAC: olength = sizeof (BX_PNIC_THIS s.macaddr); memcpy (data, BX_PNIC_THIS s.macaddr, olength); status = PNIC_STATUS_OK; break; case PNIC_CMD_RESET: /* Flush the receive queue */ BX_PNIC_THIS s.recvQueueLength = 0; status = PNIC_STATUS_OK; break; case PNIC_CMD_XMIT: BX_PNIC_THIS ethdev->sendpkt(data, ilength); bx_gui->statusbar_setitem(BX_PNIC_THIS s.statusbar_id, 1, 1); if (BX_PNIC_THIS s.irqEnabled) { set_irq_level(1); } status = PNIC_STATUS_OK; break; case PNIC_CMD_RECV: if (BX_PNIC_THIS s.recvQueueLength > 0) { int idx = (BX_PNIC_THIS s.recvIndex - BX_PNIC_THIS s.recvQueueLength + PNIC_RECV_RINGS) % PNIC_RECV_RINGS; olength = BX_PNIC_THIS s.recvRingLength[idx]; memcpy (data, BX_PNIC_THIS s.recvRing[idx], olength); BX_PNIC_THIS s.recvQueueLength--; } if (! BX_PNIC_THIS s.recvQueueLength) { set_irq_level(0); } status = PNIC_STATUS_OK; break; case PNIC_CMD_RECV_QLEN: Bit16u qlen; qlen = BX_PNIC_THIS s.recvQueueLength; olength = sizeof(qlen); memcpy (data, &qlen, sizeof(qlen)); status = PNIC_STATUS_OK; break; case PNIC_CMD_MASK_IRQ: Bit8u enabled; enabled = *((Bit8u*)data); BX_PNIC_THIS s.irqEnabled = enabled; if (enabled && BX_PNIC_THIS s.recvQueueLength) { set_irq_level(1); } else { set_irq_level(0); } status = PNIC_STATUS_OK; break; case PNIC_CMD_FORCE_IRQ: set_irq_level(1); status = PNIC_STATUS_OK; break; default: BX_ERROR(("Unknown PNIC command %x (data length %u)", command, ilength)); status = PNIC_STATUS_UNKNOWN_CMD; break; } // Set registers BX_PNIC_THIS s.rStatus = status; BX_PNIC_THIS s.rLength = olength; BX_PNIC_THIS s.rDataCursor = 0; } /* * Callback from the eth system driver to check if the device can receive */ Bit32u bx_pcipnic_c::rx_status_handler(void *arg) { bx_pcipnic_c *class_ptr = (bx_pcipnic_c *) arg; return class_ptr->rx_status(); } Bit32u bx_pcipnic_c::rx_status() { Bit32u status = BX_NETDEV_100MBIT; if (BX_PNIC_THIS s.recvQueueLength < PNIC_RECV_RINGS) { status |= BX_NETDEV_RXREADY; } return status; } /* * Callback from the eth system driver when a frame has arrived */ void bx_pcipnic_c::rx_handler(void *arg, const void *buf, unsigned len) { // BX_DEBUG(("rx_handler with length %d", len)); bx_pcipnic_c *class_ptr = (bx_pcipnic_c *) arg; class_ptr->rx_frame(buf, len); } /* * rx_frame() - called by the platform-specific code when an * ethernet frame has been received. The destination address * is tested to see if it should be accepted, and if the * rx ring has enough room, it is copied into it and * the receive process is updated */ void bx_pcipnic_c::rx_frame(const void *buf, unsigned io_len) { // Check packet length if (io_len > PNIC_DATA_SIZE) { BX_PANIC(("PNIC receive: data size %u exceeded buffer size %u", io_len, PNIC_DATA_SIZE)); // Truncate if user continues io_len = PNIC_DATA_SIZE; } // Check receive ring is not full if (BX_PNIC_THIS s.recvQueueLength == PNIC_RECV_RINGS) { BX_ERROR(("PNIC receive: receive ring full, discarding packet")); return; } // Copy data to receive ring and record length memcpy (BX_PNIC_THIS s.recvRing[BX_PNIC_THIS s.recvIndex], buf, io_len); BX_PNIC_THIS s.recvRingLength[BX_PNIC_THIS s.recvIndex] = io_len; // Move to next ring entry BX_PNIC_THIS s.recvIndex = (BX_PNIC_THIS s.recvIndex + 1) % PNIC_RECV_RINGS; BX_PNIC_THIS s.recvQueueLength++; // Generate interrupt if enabled if (BX_PNIC_THIS s.irqEnabled) { set_irq_level(1); } bx_gui->statusbar_setitem(BX_PNIC_THIS s.statusbar_id, 1); } #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIPNIC bochs-2.6/iodev/network/eth_fbsd.cc0000644000175000017500000003025412020641503017216 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_fbsd.cc 11326 2012-08-08 15:38:33Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Peter Grehan (grehan@iprg.nokia.com) coded all of this // NE2000/ether stuff. // eth_fbsd.cc - A FreeBSD packet filter implementation of // an ethernet pktmover. There are some problems and limitations // with FreeBSD: // - the source address of the frame is overwritten by // the hosts's source address. This causes problems with // learning bridges - since they cannot determine where // BOCHS 'is', they broadcast the frame to all ports. // - packets cannot be sent from BOCHS to the host // - TCP performance seems to be abysmal; I think this is // a timing problem somewhere. // - I haven't handled the case where multiple frames arrive // in a single BPF read. // // The /dev/bpf* devices need to be set up with the appropriate // permissions for this to work. // // The config line in .bochsrc should look something like: // // ne2k: ioaddr=0x280, irq=9, mac=00:a:b:c:1:2, ethmod=fbsd, ethdev=fxp0 // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING && BX_NETMOD_FBSD #define LOG_THIS netdev-> #define BX_ETH_FBSD_LOGGING 0 extern "C" { #include #include #include #include #include #include }; #define BX_BPF_POLL 1000 // Poll for a frame every 250 usecs #define BX_BPF_INSNSIZ 8 // number of bpf insns // template filter for a unicast mac address and all // multicast/broadcast frames static const struct bpf_insn macfilter[] = { BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), // A <- P[2:4] BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2), // if A != 0xaaaaaaa GOTO LABEL-1 BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0), // A <- P[0:2] BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0), // if A == 0xaaaa GOTO ACCEPT // LABEL-1 BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), // A <- P[0:1] BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1), // if !(A & 1) GOTO LABEL-REJECT // LABEL-ACCEPT BPF_STMT(BPF_RET, 1514), // Accept packet // LABEL-REJECT BPF_STMT(BPF_RET, 0), // Reject packet }; // template filter for all frames static const struct bpf_insn promiscfilter[] = { BPF_STMT(BPF_RET, 1514) }; // // Define the class. This is private to this module // class bx_fbsd_pktmover_c : public eth_pktmover_c { public: bx_fbsd_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: char *fbsd_macaddr[6]; int bpf_fd; static void rx_timer_handler(void *); void rx_timer(void); int rx_timer_index; struct bpf_insn filter[BX_BPF_INSNSIZ]; FILE *ne2klog, *ne2klog_txt; }; // // Define the static class that registers the derived pktmover class, // and allocates one on request. // class bx_fbsd_locator_c : public eth_locator_c { public: bx_fbsd_locator_c(void) : eth_locator_c("fbsd") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_fbsd_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_fbsd_match; // // Define the methods for the bx_fbsd_pktmover derived class // // the constructor // // Open a bpf file descriptor, and attempt to bind to // the specified netif (Replicates libpcap open code) // bx_fbsd_pktmover_c::bx_fbsd_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { char device[sizeof "/dev/bpf000"]; int tmpfd; int n = 0; struct ifreq ifr; struct bpf_version bv; struct bpf_program bp; u_int v; this->netdev = dev; BX_INFO(("freebsd network driver")); memcpy(fbsd_macaddr, macaddr, 6); do { (void)sprintf(device, "/dev/bpf%d", n++); this->bpf_fd = open(device, O_RDWR); BX_DEBUG(("tried %s, returned %d (%s)",device,this->bpf_fd,strerror(errno))); if(errno == EACCES) break; } while (this->bpf_fd == -1); if (this->bpf_fd == -1) { BX_PANIC(("eth_freebsd: could not open packet filter: %s", strerror(errno))); return; } if (ioctl(this->bpf_fd, BIOCVERSION, (caddr_t)&bv) < 0) { BX_PANIC(("eth_freebsd: could not retrieve bpf version")); close(this->bpf_fd); this->bpf_fd = -1; return; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { BX_PANIC(("eth_freebsd: bpf version mismatch between compilation and runtime")); close(this->bpf_fd); this->bpf_fd = -1; return; } // Set buffer size v = BX_PACKET_BUFSIZE; if (ioctl(this->bpf_fd, BIOCSBLEN, (caddr_t)&v) < 0) { BX_PANIC(("eth_freebsd: could not set buffer size: %s", strerror(errno))); close(this->bpf_fd); this->bpf_fd = -1; return; } (void)strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name)); if (ioctl(this->bpf_fd, BIOCSETIF, (caddr_t)&ifr) < 0) { BX_PANIC(("eth_freebsd: could not enable interface '%s': %s", netif, strerror(errno))); close(this->bpf_fd); this->bpf_fd == -1; } // Verify that the device is an ethernet. if (ioctl(this->bpf_fd, BIOCGDLT, (caddr_t)&v) < 0) { BX_PANIC(("eth_freebsd: could not retrieve datalink type: %s", strerror(errno))); close(this->bpf_fd); this->bpf_fd = -1; return; } if (v != DLT_EN10MB) { BX_PANIC(("eth_freebsd: incorrect datalink type %d, expected 10mb ethernet", v)); close(this->bpf_fd); this->bpf_fd = -1; return; } // Put the device into promisc mode. This could be optimised // to filter on a MAC address, broadcast, and all-multi, // but this will do for now. // if (ioctl(this->bpf_fd, BIOCPROMISC, NULL) < 0) { BX_PANIC(("eth_freebsd: could not enable promisc mode: %s", strerror(errno))); close(this->bpf_fd); this->bpf_fd = -1; return; } v = 1; if (ioctl(this->bpf_fd, BIOCIMMEDIATE, &v) < 0) { BX_PANIC(("eth_freebsd: could not enable immediate mode")); close(this->bpf_fd); this->bpf_fd = -1; return; } // Set up non-blocking i/o v = 1; if (ioctl(this->bpf_fd, FIONBIO, &v) < 0) { BX_PANIC(("eth_freebsd: could not enable non-blocking i/o: %s", strerror(errno))); close(this->bpf_fd); this->bpf_fd = -1; return; } // Install a filter #ifdef notdef memcpy(&this->filter, promiscfilter, sizeof(promiscfilter)); bp.bf_len = 1; #else memcpy(&this->filter, macfilter, sizeof(macfilter)); this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 | (macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff); this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff); bp.bf_len = 8; #endif bp.bf_insns = &this->filter[0]; if (ioctl(this->bpf_fd, BIOCSETF, &bp) < 0) { BX_PANIC(("eth_freebsd: could not set filter: %s", strerror(errno))); close(this->bpf_fd); this->bpf_fd = -1; return; } // Start the rx poll this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, BX_BPF_POLL, 1, 1, "eth_fbsd"); // continuous, active this->rxh = rxh; this->rxstat = rxstat; #if BX_ETH_FBSD_LOGGING // eventually Bryce wants ne2klog to dump in pcap format so that // tcpdump -r FILE can read it and interpret packets. ne2klog = fopen("ne2k.raw", "wb"); if (!ne2klog) BX_PANIC(("open ne2k-tx.log failed")); ne2klog_txt = fopen("ne2k.txt", "wb"); if (!ne2klog_txt) BX_PANIC(("open ne2k-txdump.txt failed")); fprintf(ne2klog_txt, "null packetmover readable log file\n"); fprintf(ne2klog_txt, "net IF = %s\n", netif); fprintf(ne2klog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(ne2klog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(ne2klog_txt, "\n--\n"); fflush(ne2klog_txt); #endif } // the output routine - called with pre-formatted ethernet frame. void bx_fbsd_pktmover_c::sendpkt(void *buf, unsigned io_len) { #if BX_ETH_FBSD_LOGGING BX_DEBUG(("sendpkt length %u", io_len)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. int n = fwrite(buf, io_len, 1, ne2klog); if (n != 1) BX_ERROR(("fwrite to ne2klog failed", io_len)); // dump packet in hex into an ascii log file write_pktlog_txt(ne2klog_txt, (const Bit8u *)buf, io_len, 0); // flush log so that we see the packets as they arrive w/o buffering fflush(ne2klog); #endif int status; if (this->bpf_fd != -1) status = write(this->bpf_fd, buf, io_len); } // The receive poll process void bx_fbsd_pktmover_c::rx_timer_handler(void *this_ptr) { bx_fbsd_pktmover_c *class_ptr = (bx_fbsd_pktmover_c *) this_ptr; class_ptr->rx_timer(); } void bx_fbsd_pktmover_c::rx_timer(void) { int nbytes = 0; unsigned char rxbuf[BX_PACKET_BUFSIZE]; struct bpf_hdr *bhdr; struct bpf_stat bstat; static struct bpf_stat previous_bstat; int counter = 10; #define phdr ((unsigned char*)bhdr) bhdr = (struct bpf_hdr *) rxbuf; nbytes = read(this->bpf_fd, rxbuf, sizeof(rxbuf)); while (phdr < (rxbuf + nbytes)) { if (ioctl(this->bpf_fd, BIOCGSTATS, &bstat) < 0) { BX_PANIC(("eth_freebsd: could not stat filter: %s", strerror(errno))); } if (bstat.bs_drop > previous_bstat.bs_drop) { BX_INFO(("eth_freebsd: %d packets dropped by the kernel.", bstat.bs_drop - previous_bstat.bs_drop)); } previous_bstat = bstat; if (bhdr->bh_caplen < 20 || bhdr->bh_caplen > 1514) { BX_ERROR(("eth_freebsd: received too weird packet length: %d", bhdr->bh_caplen)); } // filter out packets sourced from this node if (memcmp(bhdr + bhdr->bh_hdrlen + 6, this->fbsd_macaddr, 6)) { if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, phdr + bhdr->bh_hdrlen, bhdr->bh_caplen); } else { BX_ERROR(("device not ready to receive data")); } } #if BX_ETH_FBSD_LOGGING BX_DEBUG(("receive packet length %u", nbytes)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. if (1 != fwrite(bhdr, bhdr->bh_caplen, 1, ne2klog)) { BX_PANIC(("fwrite to ne2klog failed: %s", strerror(errno))); } // dump packet in hex into an ascii log file write_pktlog_txt(ne2klog_txt, rxbuf, bhdr->bh_caplen, 1); // flush log so that we see the packets as they arrive w/o buffering fflush (this->ne2klog); #endif // Advance bhdr and phdr pointers to next packet bhdr = (struct bpf_hdr*) ((char*) bhdr + BPF_WORDALIGN(bhdr->bh_hdrlen + bhdr->bh_caplen)); } } #endif /* if BX_NETWORKING && BX_NETMOD_FBSD */ bochs-2.6/iodev/network/e1000.h0000644000175000017500000001265412020641503016033 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: e1000.h 11382 2012-08-30 20:41:25Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Intel(R) 82540EM Gigabit Ethernet support (ported from QEMU) // Software developer's manual: // http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf // // Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. // Copyright (c) 2008 Qumranet // Based on work done by: // Copyright (c) 2007 Dan Aloni // Copyright (c) 2004 Antony T Curtis // // Copyright (C) 2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_E1000_H #define BX_IODEV_E1000_H #if BX_USE_E1000_SMF # define BX_E1000_SMF static # define BX_E1000_THIS theE1000Device-> # define BX_E1000_THIS_PTR theE1000Device #else # define BX_E1000_SMF # define BX_E1000_THIS this-> # define BX_E1000_THIS_PTR this #endif struct e1000_tx_desc { Bit64u buffer_addr; // Address of the descriptor's data buffer union { Bit32u data; struct { Bit16u length; // Data buffer length Bit8u cso; // Checksum offset Bit8u cmd; // Descriptor control } flags; } lower; union { Bit32u data; struct { Bit8u status; // Descriptor status Bit8u css; // Checksum start Bit16u special; } fields; } upper; }; typedef struct { Bit8u header[256]; Bit8u vlan_header[4]; Bit8u *vlan; Bit8u *data; Bit16u size; Bit8u sum_needed; bx_bool vlan_needed; Bit8u ipcss; Bit8u ipcso; Bit16u ipcse; Bit8u tucss; Bit8u tucso; Bit16u tucse; Bit8u hdr_len; Bit16u mss; Bit32u paylen; Bit16u tso_frames; bx_bool tse; bx_bool ip; bx_bool tcp; bx_bool cptse; // current packet tse bit Bit32u int_cause; } e1000_tx; typedef struct { Bit32u *mac_reg; Bit16u phy_reg[0x20]; Bit16u eeprom_data[64]; Bit32u rxbuf_size; Bit32u rxbuf_min_shift; bx_bool check_rxov; e1000_tx tx; struct { Bit32u val_in; // shifted in from guest driver Bit16u bitnum_in; Bit16u bitnum_out; bx_bool reading; Bit32u old_eecd; } eecd_state; int tx_timer_index; int statusbar_id; Bit8u devfunc; } bx_e1000_t; class bx_e1000_c : public bx_devmodel_c, bx_pci_device_stub_c { public: bx_e1000_c(); virtual ~bx_e1000_c(); virtual void init(void); virtual void reset(unsigned type); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); private: bx_e1000_t s; eth_pktmover_c *ethdev; BX_E1000_SMF void set_irq_level(bx_bool level); BX_E1000_SMF void set_interrupt_cause(Bit32u val); BX_E1000_SMF void set_ics(Bit32u value); BX_E1000_SMF int rxbufsize(Bit32u v); BX_E1000_SMF void set_rx_control(Bit32u value); BX_E1000_SMF void set_mdic(Bit32u value); BX_E1000_SMF Bit32u get_eecd(void); BX_E1000_SMF void set_eecd(Bit32u value); BX_E1000_SMF Bit32u flash_eerd_read(void); BX_E1000_SMF void putsum(Bit8u *data, Bit32u n, Bit32u sloc, Bit32u css, Bit32u cse); BX_E1000_SMF bx_bool vlan_enabled(void); BX_E1000_SMF bx_bool vlan_rx_filter_enabled(void); BX_E1000_SMF bx_bool is_vlan_packet(const Bit8u *buf); BX_E1000_SMF bx_bool is_vlan_txd(Bit32u txd_lower); BX_E1000_SMF int fcs_len(void); BX_E1000_SMF void xmit_seg(void); BX_E1000_SMF void process_tx_desc(struct e1000_tx_desc *dp); BX_E1000_SMF Bit32u txdesc_writeback(bx_phy_address base, struct e1000_tx_desc *dp); BX_E1000_SMF Bit64u tx_desc_base(void); BX_E1000_SMF void start_xmit(void); static void tx_timer_handler(void *); void tx_timer(void); BX_E1000_SMF int receive_filter(const Bit8u *buf, int size); BX_E1000_SMF bx_bool e1000_has_rxbufs(size_t total_size); BX_E1000_SMF Bit64u rx_desc_base(void); static Bit32u rx_status_handler(void *arg); BX_E1000_SMF Bit32u rx_status(void); static void rx_handler(void *arg, const void *buf, unsigned len); BX_E1000_SMF void rx_frame(const void *buf, unsigned io_len); BX_E1000_SMF bx_bool mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param); BX_E1000_SMF bx_bool mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_E1000_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif }; #endif bochs-2.6/iodev/network/eth_linux.cc0000644000175000017500000002164112020641503017437 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_linux.cc 10975 2012-01-14 17:03:00Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Peter Grehan (grehan@iprg.nokia.com) coded all of this // NE2000/ether stuff. // eth_linux.cc - A Linux socket filter adaptation of the FreeBSD BPF driver // 21 June 2001 // // Problems and limitations: // - packets cannot be sent from BOCHS to the host // - Linux kernel sometimes gets network watchdog timeouts under emulation // - author doesn't know C++ // // The config line in .bochsrc should look something like: // // ne2k: ioaddr=0x280, irq=10, mac=00:a:b:c:1:2, ethmod=linux, ethdev=eth0 // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING && BX_NETMOD_LINUX #define LOG_THIS netdev-> extern "C" { #include #include #include #include #include #include #include #include #include #include #include }; #define BX_PACKET_POLL 1000 // Poll for a frame every 1000 usecs // template filter for a unicast mac address and all // multicast/broadcast frames static const struct sock_filter macfilter[] = { BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2), BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0), BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1), BPF_STMT(BPF_RET, 1514), BPF_STMT(BPF_RET, 0), }; #define BX_LSF_ICNT 8 // number of lsf instructions in macfilter #if 0 // template filter for all frames static const struct sock_filter promiscfilter[] = { BPF_STMT(BPF_RET, 1514) }; #endif // // Define the class. This is private to this module // class bx_linux_pktmover_c : public eth_pktmover_c { public: bx_linux_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: unsigned char *linux_macaddr[6]; int fd; int ifindex; static void rx_timer_handler(void *); void rx_timer(void); int rx_timer_index; struct sock_filter filter[BX_LSF_ICNT]; }; // // Define the static class that registers the derived pktmover class, // and allocates one on request. // class bx_linux_locator_c : public eth_locator_c { public: bx_linux_locator_c(void) : eth_locator_c("linux") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_linux_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_linux_match; // // Define the methods for the bx_linux_pktmover derived class // // the constructor // bx_linux_pktmover_c::bx_linux_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { struct sockaddr_ll sll; struct packet_mreq mr; struct ifreq ifr; struct sock_fprog fp; this->netdev = dev; memcpy(linux_macaddr, macaddr, 6); // Open packet socket // if ((this->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) { if (errno == EACCES) BX_PANIC(("eth_linux: must be root or have CAP_NET_RAW capability to open socket")); else BX_PANIC(("eth_linux: could not open socket: %s", strerror(errno))); this->fd = -1; return; } // Translate interface name to index // memset(&ifr, 0, sizeof(ifr)); strcpy(ifr.ifr_name, netif); if (ioctl(this->fd, SIOCGIFINDEX, &ifr) == -1) { BX_PANIC(("eth_linux: could not get index for interface '%s'\n", netif)); close(fd); this->fd = -1; return; } this->ifindex = ifr.ifr_ifindex; // Bind to given interface // memset(&sll, 0, sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = this->ifindex; if (bind(fd, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) { BX_PANIC(("eth_linux: could not bind to interface '%s': %s\n", netif, strerror(errno))); close(fd); this->fd = -1; return; } // Put the device into promisc mode. // memset(&mr, 0, sizeof(mr)); mr.mr_ifindex = this->ifindex; mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(this->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&mr, (socklen_t)sizeof(mr)) == -1) { BX_PANIC(("eth_linux: could not enable promisc mode: %s\n", strerror(errno))); close(this->fd); this->fd = -1; return; } // Set up non-blocking i/o if (fcntl(this->fd, F_SETFL, O_NONBLOCK) == -1) { BX_PANIC(("eth_linux: could not set non-blocking i/o on socket")); close(this->fd); this->fd = -1; return; } // Install a filter #ifdef notdef memcpy(&this->filter, promiscfilter, sizeof(promiscfilter)); fp.len = 1; #endif memcpy(&this->filter, macfilter, sizeof(macfilter)); this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 | (macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff); this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff); fp.len = BX_LSF_ICNT; fp.filter = this->filter; BX_INFO(("eth_linux: fp.len=%d fp.filter=%lx", fp.len, (unsigned long) fp.filter)); if (setsockopt(this->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fp, sizeof(fp)) < 0) { BX_PANIC(("eth_linux: could not set socket filter: %s", strerror(errno))); close(this->fd); this->fd = -1; return; } // Start the rx poll this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, BX_PACKET_POLL, 1, 1, "eth_linux"); // continuous, active this->rxh = rxh; this->rxstat = rxstat; BX_INFO(("linux network driver initialized: using interface %s", netif)); } // the output routine - called with pre-formatted ethernet frame. void bx_linux_pktmover_c::sendpkt(void *buf, unsigned io_len) { int status; if (this->fd != -1) { status = write(this->fd, buf, io_len); if (status == -1) BX_INFO(("eth_linux: write failed: %s", strerror(errno))); } } // The receive poll process void bx_linux_pktmover_c::rx_timer_handler(void *this_ptr) { bx_linux_pktmover_c *class_ptr = (bx_linux_pktmover_c *) this_ptr; class_ptr->rx_timer(); } void bx_linux_pktmover_c::rx_timer(void) { int nbytes = 0; Bit8u rxbuf[BX_PACKET_BUFSIZE]; struct sockaddr_ll sll; socklen_t fromlen; if (this->fd == -1) return; fromlen = sizeof(sll); nbytes = recvfrom(this->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&sll, &fromlen); if (nbytes == -1) { if (errno != EAGAIN) BX_INFO(("eth_linux: error receiving packet: %s\n", strerror(errno))); return; } // this should be done with LSF someday // filter out packets sourced by us if (memcmp(sll.sll_addr, this->linux_macaddr, 6) == 0) return; // let through broadcast, multicast, and our mac address // if ((memcmp(rxbuf, broadcast_macaddr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) { BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, rxbuf, nbytes); } else { BX_ERROR(("device not ready to receive data")); } // } } #endif /* if BX_NETWORKING && BX_NETMOD_LINUX */ bochs-2.6/iodev/network/ne2k.cc0000644000175000017500000020511312020641503016275 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ne2k.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Peter Grehan (grehan@iprg.nokia.com) coded the initial version of this // NE2000/ether stuff. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_NE2K #if BX_SUPPORT_PCI #include "pci.h" #endif #include "ne2k.h" #include "netmod.h" //Never completely fill the ne2k ring so that we never // hit the unclear completely full buffer condition. #define BX_NE2K_NEVER_FULL_RING (1) #define LOG_THIS theNE2kDevice-> bx_ne2k_c *theNE2kDevice = NULL; const Bit8u ne2k_iomask[32] = {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; // builtin configuration handling functions void ne2k_init_options(void) { bx_param_c *network = SIM->get_param("network"); bx_list_c *menu = new bx_list_c(network, "ne2k", "NE2000"); menu->set_options(menu->SHOW_PARENT); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", "Enable NE2K NIC emulation", "Enables the NE2K NIC emulation", 0); bx_param_num_c *ioaddr = new bx_param_num_c(menu, "ioaddr", "NE2K I/O Address", "I/O base address of the emulated NE2K device", 0, 0xffff, 0x300); ioaddr->set_base(16); bx_param_num_c *irq = new bx_param_num_c(menu, "irq", "NE2K Interrupt", "IRQ used by the NE2K device", 0, 15, 9); irq->set_options(irq->USE_SPIN_CONTROL); SIM->init_std_nic_options("NE2K", menu); enabled->set_dependent_list(menu->clone()); } Bit32s ne2k_options_parser(const char *context, int num_params, char *params[]) { int ret, valid = 0; if (!strcmp(params[0], "ne2k")) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_NE2K); char tmpdev[80]; if (!SIM->get_param_bool("enabled", base)->get()) { SIM->get_param_enum("ethmod", base)->set_by_name("null"); } if (SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) { for (int slot = 1; slot < 6; slot++) { sprintf(tmpdev, "pci.slot.%d", slot); if (!strcmp(SIM->get_param_string(tmpdev)->getptr(), "ne2k")) { valid |= 0x03; break; } } } for (int i = 1; i < num_params; i++) { if (!strncmp(params[i], "ioaddr=", 7)) { SIM->get_param_num("ioaddr", base)->set(strtoul(¶ms[i][7], NULL, 16)); valid |= 0x01; } else if (!strncmp(params[i], "irq=", 4)) { SIM->get_param_num("irq", base)->set(atol(¶ms[i][4])); valid |= 0x02; } else { ret = SIM->parse_nic_params(context, params[i], base); if (ret > 0) { valid |= ret; } } } if (!SIM->get_param_bool("enabled", base)->get()) { if (valid == 0x07) { SIM->get_param_bool("enabled", base)->set(1); } else if (valid < 0x80) { if ((valid & 0x03) != 0x03) { BX_ERROR(("%s: 'ne2k' directive incomplete (ioaddr and irq are required)", context)); } if ((valid & 0x04) == 0) { BX_ERROR(("%s: 'ne2k' directive incomplete (mac address is required)", context)); } } } else { if (valid & 0x80) { SIM->get_param_bool("enabled", base)->set(0); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s ne2k_options_save(FILE *fp) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_NE2K); fprintf(fp, "ne2k: enabled=%d", SIM->get_param_bool("enabled", base)->get()); if (SIM->get_param_bool("enabled", base)->get()) { char *ptr = SIM->get_param_string("macaddr", base)->getptr(); fprintf(fp, ", ioaddr=0x%x, irq=%d, mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s, bootrom=%s", SIM->get_param_num("ioaddr", base)->get(), SIM->get_param_num("irq", base)->get(), (unsigned int)(0xff & ptr[0]), (unsigned int)(0xff & ptr[1]), (unsigned int)(0xff & ptr[2]), (unsigned int)(0xff & ptr[3]), (unsigned int)(0xff & ptr[4]), (unsigned int)(0xff & ptr[5]), SIM->get_param_enum("ethmod", base)->get_selected(), SIM->get_param_string("ethdev", base)->getptr(), SIM->get_param_string("script", base)->getptr(), SIM->get_param_string("bootrom", base)->getptr()); } fprintf(fp, "\n"); return 0; } // device plugin entry points int libne2k_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theNE2kDevice = new bx_ne2k_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theNE2kDevice, BX_PLUGIN_NE2K); // add new configuration parameter for the config interface ne2k_init_options(); // register add-on option for bochsrc and command line SIM->register_addon_option("ne2k", ne2k_options_parser, ne2k_options_save); return(0); // Success } void libne2k_LTX_plugin_fini(void) { SIM->unregister_addon_option("ne2k"); ((bx_list_c*)SIM->get_param("network"))->remove("ne2k"); delete theNE2kDevice; } // the device object bx_ne2k_c::bx_ne2k_c() { put("NE2K"); memset(&s, 0, sizeof(bx_ne2k_t)); s.tx_timer_index = BX_NULL_TIMER_HANDLE; ethdev = NULL; } bx_ne2k_c::~bx_ne2k_c() { if (ethdev != NULL) { delete ethdev; } SIM->get_bochs_root()->remove("ne2k"); BX_DEBUG(("Exit")); } void bx_ne2k_c::init(void) { char devname[16]; Bit8u macaddr[6]; const char *bootrom; BX_DEBUG(("Init $Id: ne2k.cc 11346 2012-08-19 08:16:20Z vruppert $")); // Read in values from config interface bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_NE2K); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", base)->get()) { BX_INFO(("NE2000 disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("ne2k"))->set(0); return; } memcpy(macaddr, SIM->get_param_string("macaddr", base)->getptr(), 6); BX_NE2K_THIS s.pci_enabled = 0; strcpy(devname, "NE2000 NIC"); #if BX_SUPPORT_PCI if ((SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get()) && (DEV_is_pci_device(BX_PLUGIN_NE2K))) { BX_NE2K_THIS s.pci_enabled = 1; strcpy(devname, "NE2000 PCI NIC"); BX_NE2K_THIS s.devfunc = 0x00; DEV_register_pci_handlers(this, &BX_NE2K_THIS s.devfunc, BX_PLUGIN_NE2K, devname); for (unsigned i=0; i<256; i++) BX_NE2K_THIS pci_conf[i] = 0x0; // readonly registers BX_NE2K_THIS pci_conf[0x00] = 0xec; BX_NE2K_THIS pci_conf[0x01] = 0x10; BX_NE2K_THIS pci_conf[0x02] = 0x29; BX_NE2K_THIS pci_conf[0x03] = 0x80; BX_NE2K_THIS pci_conf[0x04] = 0x01; BX_NE2K_THIS pci_conf[0x0a] = 0x00; BX_NE2K_THIS pci_conf[0x0b] = 0x02; BX_NE2K_THIS pci_conf[0x0e] = 0x00; BX_NE2K_THIS pci_conf[0x10] = 0x01; BX_NE2K_THIS pci_conf[0x3d] = BX_PCI_INTA; BX_NE2K_THIS s.base_address = 0x0; BX_NE2K_THIS pci_rom_address = 0; bootrom = SIM->get_param_string("bootrom", base)->getptr(); if (strlen(bootrom) > 0) { BX_NE2K_THIS load_pci_rom(bootrom); } } #endif if (BX_NE2K_THIS s.tx_timer_index == BX_NULL_TIMER_HANDLE) { BX_NE2K_THIS s.tx_timer_index = bx_pc_system.register_timer(this, tx_timer_handler, 0, 0,0, "ne2k"); // one-shot, inactive } // Register the IRQ and i/o port addresses if (!BX_NE2K_THIS s.pci_enabled) { BX_NE2K_THIS s.base_address = SIM->get_param_num("ioaddr", base)->get(); BX_NE2K_THIS s.base_irq = SIM->get_param_num("irq", base)->get(); DEV_register_irq(BX_NE2K_THIS s.base_irq, "NE2000 ethernet NIC"); DEV_register_ioread_handler_range(BX_NE2K_THIS_PTR, read_handler, BX_NE2K_THIS s.base_address, BX_NE2K_THIS s.base_address + 0x0F, devname, 3); DEV_register_iowrite_handler_range(BX_NE2K_THIS_PTR, write_handler, BX_NE2K_THIS s.base_address, BX_NE2K_THIS s.base_address + 0x0F, devname, 3); DEV_register_ioread_handler(BX_NE2K_THIS_PTR, read_handler, BX_NE2K_THIS s.base_address + 0x10, devname, 3); DEV_register_iowrite_handler(BX_NE2K_THIS_PTR, write_handler, BX_NE2K_THIS s.base_address + 0x10, devname, 3); DEV_register_ioread_handler(BX_NE2K_THIS_PTR, read_handler, BX_NE2K_THIS s.base_address + 0x1F, devname, 1); DEV_register_iowrite_handler(BX_NE2K_THIS_PTR, write_handler, BX_NE2K_THIS s.base_address + 0x1F, devname, 1); bootrom = SIM->get_param_string("bootrom", base)->getptr(); if (strlen(bootrom) > 0) { BX_PANIC(("%s: boot ROM support not present yet", devname)); } BX_INFO(("%s initialized port 0x%x/32 irq %d mac %02x:%02x:%02x:%02x:%02x:%02x", devname, BX_NE2K_THIS s.base_address, BX_NE2K_THIS s.base_irq, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5])); } else { BX_INFO(("%s initialized mac %02x:%02x:%02x:%02x:%02x:%02x", devname, macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5])); } // Initialise the mac address area by doubling the physical address BX_NE2K_THIS s.macaddr[0] = macaddr[0]; BX_NE2K_THIS s.macaddr[1] = macaddr[0]; BX_NE2K_THIS s.macaddr[2] = macaddr[1]; BX_NE2K_THIS s.macaddr[3] = macaddr[1]; BX_NE2K_THIS s.macaddr[4] = macaddr[2]; BX_NE2K_THIS s.macaddr[5] = macaddr[2]; BX_NE2K_THIS s.macaddr[6] = macaddr[3]; BX_NE2K_THIS s.macaddr[7] = macaddr[3]; BX_NE2K_THIS s.macaddr[8] = macaddr[4]; BX_NE2K_THIS s.macaddr[9] = macaddr[4]; BX_NE2K_THIS s.macaddr[10] = macaddr[5]; BX_NE2K_THIS s.macaddr[11] = macaddr[5]; // ne2k signature for (int i = 12; i < 32; i++) BX_NE2K_THIS s.macaddr[i] = 0x57; BX_NE2K_THIS s.statusbar_id = bx_gui->register_statusitem("NE2K", 1); // Attach to the selected ethernet module BX_NE2K_THIS ethdev = DEV_net_init_module(base, rx_handler, rx_status_handler, this); #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("ne2k", this); #endif } // // reset - restore state to power-up, cancelling all i/o // void bx_ne2k_c::reset(unsigned type) { if (type == BX_RESET_HARDWARE) { // Zero out registers and memory memset(&BX_NE2K_THIS s.CR, 0, sizeof(BX_NE2K_THIS s.CR)); memset(&BX_NE2K_THIS s.IMR, 0, sizeof(BX_NE2K_THIS s.IMR)); memset(&BX_NE2K_THIS s.DCR, 0, sizeof(BX_NE2K_THIS s.DCR)); memset(&BX_NE2K_THIS s.TCR, 0, sizeof(BX_NE2K_THIS s.TCR)); memset(&BX_NE2K_THIS s.TSR, 0, sizeof(BX_NE2K_THIS s.TSR)); memset(&BX_NE2K_THIS s.RCR, 0, sizeof(BX_NE2K_THIS s.RCR)); memset(&BX_NE2K_THIS s.RSR, 0, sizeof(BX_NE2K_THIS s.RSR)); BX_NE2K_THIS s.local_dma = 0; BX_NE2K_THIS s.page_start = 0; BX_NE2K_THIS s.page_stop = 0; BX_NE2K_THIS s.bound_ptr = 0; BX_NE2K_THIS s.tx_page_start = 0; BX_NE2K_THIS s.num_coll = 0; BX_NE2K_THIS s.tx_bytes = 0; BX_NE2K_THIS s.fifo = 0; BX_NE2K_THIS s.remote_dma = 0; BX_NE2K_THIS s.remote_start = 0; BX_NE2K_THIS s.remote_bytes = 0; BX_NE2K_THIS s.tallycnt_0 = 0; BX_NE2K_THIS s.tallycnt_1 = 0; BX_NE2K_THIS s.tallycnt_2 = 0; memset(&BX_NE2K_THIS s.physaddr, 0, sizeof(BX_NE2K_THIS s.physaddr)); memset(&BX_NE2K_THIS s.mchash, 0, sizeof(BX_NE2K_THIS s.mchash)); BX_NE2K_THIS s.curr_page = 0; BX_NE2K_THIS s.rempkt_ptr = 0; BX_NE2K_THIS s.localpkt_ptr = 0; BX_NE2K_THIS s.address_cnt = 0; memset(&BX_NE2K_THIS s.mem, 0, sizeof(BX_NE2K_THIS s.mem)); // Set power-up conditions BX_NE2K_THIS s.CR.stop = 1; BX_NE2K_THIS s.CR.rdma_cmd = 4; BX_NE2K_THIS s.DCR.longaddr = 1; set_irq_level(0); } memset(&BX_NE2K_THIS s.ISR, 0, sizeof(BX_NE2K_THIS s.ISR)); BX_NE2K_THIS s.ISR.reset = 1; } void bx_ne2k_c::register_state(void) { unsigned i; char name[6]; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "ne2k", "NE2000 State"); bx_list_c *CR = new bx_list_c(list, "CR"); new bx_shadow_bool_c(CR, "stop", &BX_NE2K_THIS s.CR.stop); new bx_shadow_bool_c(CR, "start", &BX_NE2K_THIS s.CR.start); new bx_shadow_bool_c(CR, "tx_packet", &BX_NE2K_THIS s.CR.tx_packet); new bx_shadow_num_c(CR, "rdma_cmd", &BX_NE2K_THIS s.CR.rdma_cmd); new bx_shadow_num_c(CR, "pgsel", &BX_NE2K_THIS s.CR.pgsel); bx_list_c *ISR = new bx_list_c(list, "ISR"); new bx_shadow_bool_c(ISR, "pkt_rx", &BX_NE2K_THIS s.ISR.pkt_rx); new bx_shadow_bool_c(ISR, "pkt_tx", &BX_NE2K_THIS s.ISR.pkt_tx); new bx_shadow_bool_c(ISR, "rx_err", &BX_NE2K_THIS s.ISR.rx_err); new bx_shadow_bool_c(ISR, "tx_err", &BX_NE2K_THIS s.ISR.tx_err); new bx_shadow_bool_c(ISR, "overwrite", &BX_NE2K_THIS s.ISR.overwrite); new bx_shadow_bool_c(ISR, "cnt_oflow", &BX_NE2K_THIS s.ISR.cnt_oflow); new bx_shadow_bool_c(ISR, "rdma_done", &BX_NE2K_THIS s.ISR.rdma_done); new bx_shadow_bool_c(ISR, "reset", &BX_NE2K_THIS s.ISR.reset); bx_list_c *IMR = new bx_list_c(list, "IMR"); new bx_shadow_bool_c(IMR, "rx_inte", &BX_NE2K_THIS s.IMR.rx_inte); new bx_shadow_bool_c(IMR, "tx_inte", &BX_NE2K_THIS s.IMR.tx_inte); new bx_shadow_bool_c(IMR, "rxerr_inte", &BX_NE2K_THIS s.IMR.rxerr_inte); new bx_shadow_bool_c(IMR, "txerr_inte", &BX_NE2K_THIS s.IMR.txerr_inte); new bx_shadow_bool_c(IMR, "overw_inte", &BX_NE2K_THIS s.IMR.overw_inte); new bx_shadow_bool_c(IMR, "cofl_inte", &BX_NE2K_THIS s.IMR.cofl_inte); new bx_shadow_bool_c(IMR, "rdma_inte", &BX_NE2K_THIS s.IMR.rdma_inte); bx_list_c *DCR = new bx_list_c(list, "DCR"); new bx_shadow_bool_c(DCR, "wdsize", &BX_NE2K_THIS s.DCR.wdsize); new bx_shadow_bool_c(DCR, "endian", &BX_NE2K_THIS s.DCR.endian); new bx_shadow_bool_c(DCR, "longaddr", &BX_NE2K_THIS s.DCR.longaddr); new bx_shadow_bool_c(DCR, "loop", &BX_NE2K_THIS s.DCR.loop); new bx_shadow_bool_c(DCR, "auto_rx", &BX_NE2K_THIS s.DCR.auto_rx); new bx_shadow_num_c(DCR, "fifo_size", &BX_NE2K_THIS s.DCR.fifo_size); bx_list_c *TCR = new bx_list_c(list, "TCR"); new bx_shadow_bool_c(TCR, "crc_disable", &BX_NE2K_THIS s.TCR.crc_disable); new bx_shadow_num_c(TCR, "loop_cntl", &BX_NE2K_THIS s.TCR.loop_cntl); new bx_shadow_bool_c(TCR, "ext_stoptx", &BX_NE2K_THIS s.TCR.ext_stoptx); new bx_shadow_bool_c(TCR, "coll_prio", &BX_NE2K_THIS s.TCR.coll_prio); bx_list_c *TSR = new bx_list_c(list, "TSR"); new bx_shadow_bool_c(TSR, "tx_ok", &BX_NE2K_THIS s.TSR.tx_ok); new bx_shadow_bool_c(TSR, "collided", &BX_NE2K_THIS s.TSR.collided); new bx_shadow_bool_c(TSR, "aborted", &BX_NE2K_THIS s.TSR.aborted); new bx_shadow_bool_c(TSR, "no_carrier", &BX_NE2K_THIS s.TSR.no_carrier); new bx_shadow_bool_c(TSR, "fifo_ur", &BX_NE2K_THIS s.TSR.fifo_ur); new bx_shadow_bool_c(TSR, "cd_hbeat", &BX_NE2K_THIS s.TSR.cd_hbeat); new bx_shadow_bool_c(TSR, "ow_coll", &BX_NE2K_THIS s.TSR.ow_coll); bx_list_c *RCR = new bx_list_c(list, "RCR"); new bx_shadow_bool_c(RCR, "errors_ok", &BX_NE2K_THIS s.RCR.errors_ok); new bx_shadow_bool_c(RCR, "runts_ok", &BX_NE2K_THIS s.RCR.runts_ok); new bx_shadow_bool_c(RCR, "broadcast", &BX_NE2K_THIS s.RCR.broadcast); new bx_shadow_bool_c(RCR, "multicast", &BX_NE2K_THIS s.RCR.multicast); new bx_shadow_bool_c(RCR, "promisc", &BX_NE2K_THIS s.RCR.promisc); new bx_shadow_bool_c(RCR, "monitor", &BX_NE2K_THIS s.RCR.monitor); bx_list_c *RSR = new bx_list_c(list, "RSR"); new bx_shadow_bool_c(RSR, "rx_ok", &BX_NE2K_THIS s.RSR.rx_ok); new bx_shadow_bool_c(RSR, "bad_crc", &BX_NE2K_THIS s.RSR.bad_crc); new bx_shadow_bool_c(RSR, "bad_falign", &BX_NE2K_THIS s.RSR.bad_falign); new bx_shadow_bool_c(RSR, "fifo_or", &BX_NE2K_THIS s.RSR.fifo_or); new bx_shadow_bool_c(RSR, "rx_missed", &BX_NE2K_THIS s.RSR.rx_missed); new bx_shadow_bool_c(RSR, "rx_mbit", &BX_NE2K_THIS s.RSR.rx_mbit); new bx_shadow_bool_c(RSR, "rx_disabled", &BX_NE2K_THIS s.RSR.rx_disabled); new bx_shadow_bool_c(RSR, "deferred", &BX_NE2K_THIS s.RSR.deferred); new bx_shadow_num_c(list, "local_dma", &BX_NE2K_THIS s.local_dma, BASE_HEX); new bx_shadow_num_c(list, "page_start", &BX_NE2K_THIS s.page_start, BASE_HEX); new bx_shadow_num_c(list, "page_stop", &BX_NE2K_THIS s.page_stop, BASE_HEX); new bx_shadow_num_c(list, "bound_ptr", &BX_NE2K_THIS s.bound_ptr, BASE_HEX); new bx_shadow_num_c(list, "tx_page_start", &BX_NE2K_THIS s.tx_page_start, BASE_HEX); new bx_shadow_num_c(list, "num_coll", &BX_NE2K_THIS s.num_coll, BASE_HEX); new bx_shadow_num_c(list, "tx_bytes", &BX_NE2K_THIS s.tx_bytes, BASE_HEX); new bx_shadow_num_c(list, "fifo", &BX_NE2K_THIS s.fifo, BASE_HEX); new bx_shadow_num_c(list, "remote_dma", &BX_NE2K_THIS s.remote_dma, BASE_HEX); new bx_shadow_num_c(list, "remote_start", &BX_NE2K_THIS s.remote_start, BASE_HEX); new bx_shadow_num_c(list, "remote_bytes", &BX_NE2K_THIS s.remote_bytes, BASE_HEX); new bx_shadow_num_c(list, "tallycnt_0", &BX_NE2K_THIS s.tallycnt_0, BASE_HEX); new bx_shadow_num_c(list, "tallycnt_1", &BX_NE2K_THIS s.tallycnt_1, BASE_HEX); new bx_shadow_num_c(list, "tallycnt_2", &BX_NE2K_THIS s.tallycnt_2, BASE_HEX); bx_list_c *paddr = new bx_list_c(list, "physaddr"); for (i=0; i<6; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(paddr, name, &BX_NE2K_THIS s.physaddr[i], BASE_HEX); } new bx_shadow_num_c(list, "curr_page", &BX_NE2K_THIS s.curr_page, BASE_HEX); bx_list_c *mchash = new bx_list_c(list, "mchash"); for (i=0; i<8; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(mchash, name, &BX_NE2K_THIS s.mchash[i], BASE_HEX); } new bx_shadow_num_c(list, "rempkt_ptr", &BX_NE2K_THIS s.rempkt_ptr, BASE_HEX); new bx_shadow_num_c(list, "localpkt_ptr", &BX_NE2K_THIS s.localpkt_ptr, BASE_HEX); new bx_shadow_num_c(list, "address_cnt", &BX_NE2K_THIS s.address_cnt, BASE_HEX); new bx_shadow_data_c(list, "mem", BX_NE2K_THIS s.mem, BX_NE2K_MEMSIZ); new bx_shadow_bool_c(list, "tx_timer_active", &BX_NE2K_THIS s.tx_timer_active); #if BX_SUPPORT_PCI if (BX_NE2K_THIS s.pci_enabled) { register_pci_state(list); } #endif } #if BX_SUPPORT_PCI void bx_ne2k_c::after_restore_state(void) { if (BX_NE2K_THIS s.pci_enabled) { if (DEV_pci_set_base_io(BX_NE2K_THIS_PTR, read_handler, write_handler, &BX_NE2K_THIS s.base_address, &BX_NE2K_THIS pci_conf[0x10], 32, &ne2k_iomask[0], "NE2000 PCI NIC")) { BX_INFO(("new base address: 0x%04x", BX_NE2K_THIS s.base_address)); } if (BX_NE2K_THIS pci_rom_size > 0) { if (DEV_pci_set_base_mem(BX_NE2K_THIS_PTR, mem_read_handler, mem_write_handler, &BX_NE2K_THIS pci_rom_address, &BX_NE2K_THIS pci_conf[0x30], BX_NE2K_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_NE2K_THIS pci_rom_address)); } } } } #endif // // read_cr/write_cr - utility routines for handling reads/writes to // the Command Register // Bit32u bx_ne2k_c::read_cr(void) { Bit32u val = (((BX_NE2K_THIS s.CR.pgsel & 0x03) << 6) | ((BX_NE2K_THIS s.CR.rdma_cmd & 0x07) << 3) | (BX_NE2K_THIS s.CR.tx_packet << 2) | (BX_NE2K_THIS s.CR.start << 1) | (BX_NE2K_THIS s.CR.stop)); BX_DEBUG(("read CR returns 0x%02x", val)); return val; } void bx_ne2k_c::write_cr(Bit32u value) { BX_DEBUG(("wrote 0x%02x to CR", value)); // Validate remote-DMA if ((value & 0x38) == 0x00) { BX_DEBUG(("CR write - invalid rDMA value 0")); value |= 0x20; /* dma_cmd == 4 is a safe default */ } // Check for s/w reset if (value & 0x01) { BX_NE2K_THIS s.ISR.reset = 1; BX_NE2K_THIS s.CR.stop = 1; } else { BX_NE2K_THIS s.CR.stop = 0; } BX_NE2K_THIS s.CR.rdma_cmd = (value & 0x38) >> 3; // If start command issued, the RST bit in the ISR // must be cleared if ((value & 0x02) && !BX_NE2K_THIS s.CR.start) { BX_NE2K_THIS s.ISR.reset = 0; } BX_NE2K_THIS s.CR.start = ((value & 0x02) == 0x02); BX_NE2K_THIS s.CR.pgsel = (value & 0xc0) >> 6; // Check for send-packet command if (BX_NE2K_THIS s.CR.rdma_cmd == 3) { // Set up DMA read from receive ring BX_NE2K_THIS s.remote_start = BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.bound_ptr * 256; BX_NE2K_THIS s.remote_bytes = (Bit16u) chipmem_read(BX_NE2K_THIS s.bound_ptr * 256 + 2, 2); BX_INFO(("Sending buffer #x%x length %d", BX_NE2K_THIS s.remote_start, BX_NE2K_THIS s.remote_bytes)); } // Check for start-tx if ((value & 0x04) && BX_NE2K_THIS s.TCR.loop_cntl) { if (BX_NE2K_THIS s.TCR.loop_cntl != 1) { BX_INFO(("Loop mode %d not supported.", BX_NE2K_THIS s.TCR.loop_cntl)); } else { rx_frame (& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes); } } else if (value & 0x04) { if (BX_NE2K_THIS s.CR.stop || (!BX_NE2K_THIS s.CR.start && !BX_NE2K_THIS s.pci_enabled)) { if (BX_NE2K_THIS s.tx_bytes == 0) /* njh@bandsman.co.uk */ return; /* Solaris9 probe */ BX_PANIC(("CR write - tx start, dev in reset")); } if (BX_NE2K_THIS s.tx_bytes == 0) BX_PANIC(("CR write - tx start, tx bytes == 0")); // Send the packet to the system driver BX_NE2K_THIS s.CR.tx_packet = 1; BX_NE2K_THIS ethdev->sendpkt(& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes); // some more debug if (BX_NE2K_THIS s.tx_timer_active) BX_ERROR(("CR write, tx timer still active")); // Schedule a timer to trigger a tx-complete interrupt // The number of microseconds is the bit-time / 10. // The bit-time is the preamble+sfd (64 bits), the // inter-frame gap (96 bits), the CRC (4 bytes), and the // the number of bits in the frame (s.tx_bytes * 8). // bx_pc_system.activate_timer(BX_NE2K_THIS s.tx_timer_index, (64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10, 0); // not continuous BX_NE2K_THIS s.tx_timer_active = 1; bx_gui->statusbar_setitem(BX_NE2K_THIS s.statusbar_id, 1, 1); } // Linux probes for an interrupt by setting up a remote-DMA read // of 0 bytes with remote-DMA completion interrupts enabled. // Detect this here if (BX_NE2K_THIS s.CR.rdma_cmd == 0x01 && BX_NE2K_THIS s.CR.start && BX_NE2K_THIS s.remote_bytes == 0) { BX_NE2K_THIS s.ISR.rdma_done = 1; if (BX_NE2K_THIS s.IMR.rdma_inte) { set_irq_level(1); } } } // // chipmem_read/chipmem_write - access the 64K private RAM. // The ne2000 memory is accessed through the data port of // the asic (offset 0) after setting up a remote-DMA transfer. // Both byte and word accesses are allowed. // The first 16 bytes contains the MAC address at even locations, // and there is 16K of buffer memory starting at 16K // Bit32u BX_CPP_AttrRegparmN(2) bx_ne2k_c::chipmem_read(Bit32u address, unsigned int io_len) { Bit32u retval = 0; if ((io_len == 2) && (address & 0x1)) BX_PANIC(("unaligned chipmem word read")); // ROM'd MAC address if ((address >=0) && (address <= 31)) { retval = BX_NE2K_THIS s.macaddr[address]; if ((io_len == 2) || (io_len == 4)) { retval |= (BX_NE2K_THIS s.macaddr[address + 1] << 8); } if (io_len == 4) { retval |= (BX_NE2K_THIS s.macaddr[address + 2] << 16); retval |= (BX_NE2K_THIS s.macaddr[address + 3] << 24); } return (retval); } if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) { retval = BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART]; if ((io_len == 2) || (io_len == 4)) { retval |= (BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] << 8); } if (io_len == 4) { retval |= (BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 2] << 16); retval |= (BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 3] << 24); } return (retval); } BX_DEBUG(("out-of-bounds chipmem read, %04X", address)); return (0xff); } void BX_CPP_AttrRegparmN(3) bx_ne2k_c::chipmem_write(Bit32u address, Bit32u value, unsigned io_len) { if ((io_len == 2) && (address & 0x1)) BX_PANIC(("unaligned chipmem word write")); if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) { BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART] = value & 0xff; if ((io_len == 2) || (io_len == 4)) { BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] = value >> 8; } if (io_len == 4) { BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 2] = value >> 16; BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 3] = value >> 24; } } else BX_DEBUG(("out-of-bounds chipmem write, %04X", address)); } // // asic_read/asic_write - This is the high 16 bytes of i/o space // (the lower 16 bytes is for the DS8390). Only two locations // are used: offset 0, which is used for data transfer, and // offset 0xf, which is used to reset the device. // The data transfer port is used to as 'external' DMA to the // DS8390. The chip has to have the DMA registers set up, and // after that, insw/outsw instructions can be used to move // the appropriate number of bytes to/from the device. // Bit32u BX_CPP_AttrRegparmN(2) bx_ne2k_c::asic_read(Bit32u offset, unsigned int io_len) { Bit32u retval = 0; switch (offset) { case 0x0: // Data register // // A read remote-DMA command must have been issued, // and the source-address and length registers must // have been initialised. // if (io_len > BX_NE2K_THIS s.remote_bytes) { BX_ERROR(("ne2K: dma read underrun iolen=%d remote_bytes=%d",io_len,BX_NE2K_THIS s.remote_bytes)); //return 0; } //BX_INFO(("ne2k read DMA: addr=%4x remote_bytes=%d",BX_NE2K_THIS s.remote_dma,BX_NE2K_THIS s.remote_bytes)); retval = chipmem_read(BX_NE2K_THIS s.remote_dma, io_len); // // The 8390 bumps the address and decreases the byte count // by the selected word size after every access, not by // the amount of data requested by the host (io_len). // if (io_len == 4) { BX_NE2K_THIS s.remote_dma += io_len; } else { BX_NE2K_THIS s.remote_dma += (BX_NE2K_THIS s.DCR.wdsize + 1); } if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) { BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8; } // keep s.remote_bytes from underflowing if (BX_NE2K_THIS s.remote_bytes > BX_NE2K_THIS s.DCR.wdsize) if (io_len == 4) { BX_NE2K_THIS s.remote_bytes -= io_len; } else { BX_NE2K_THIS s.remote_bytes -= (BX_NE2K_THIS s.DCR.wdsize + 1); } else BX_NE2K_THIS s.remote_bytes = 0; // If all bytes have been written, signal remote-DMA complete if (BX_NE2K_THIS s.remote_bytes == 0) { BX_NE2K_THIS s.ISR.rdma_done = 1; if (BX_NE2K_THIS s.IMR.rdma_inte) { set_irq_level(1); } } break; case 0xf: // Reset register theNE2kDevice->reset(BX_RESET_SOFTWARE); break; default: BX_INFO(("asic read invalid address %04x", (unsigned) offset)); break; } return (retval); } void bx_ne2k_c::asic_write(Bit32u offset, Bit32u value, unsigned io_len) { BX_DEBUG(("asic write addr=0x%02x, value=0x%04x", (unsigned) offset, (unsigned) value)); switch (offset) { case 0x0: // Data register - see asic_read for a description if ((io_len > 1) && (BX_NE2K_THIS s.DCR.wdsize == 0)) { BX_PANIC(("dma write length %d on byte mode operation", io_len)); break; } if (BX_NE2K_THIS s.remote_bytes == 0) { BX_ERROR(("ne2K: dma write, byte count 0")); } chipmem_write(BX_NE2K_THIS s.remote_dma, value, io_len); if (io_len == 4) { BX_NE2K_THIS s.remote_dma += io_len; } else { BX_NE2K_THIS s.remote_dma += (BX_NE2K_THIS s.DCR.wdsize + 1); } if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) { BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8; } if (io_len == 4) { BX_NE2K_THIS s.remote_bytes -= io_len; } else { BX_NE2K_THIS s.remote_bytes -= (BX_NE2K_THIS s.DCR.wdsize + 1); } if (BX_NE2K_THIS s.remote_bytes > BX_NE2K_MEMSIZ) BX_NE2K_THIS s.remote_bytes = 0; // If all bytes have been written, signal remote-DMA complete if (BX_NE2K_THIS s.remote_bytes == 0) { BX_NE2K_THIS s.ISR.rdma_done = 1; if (BX_NE2K_THIS s.IMR.rdma_inte) { set_irq_level(1); } } break; case 0xf: // Reset register // end of reset pulse break; default: // this is invalid, but happens under win95 device detection BX_INFO(("asic write invalid address %04x, ignoring", (unsigned) offset)); break; } } // // page0_read/page0_write - These routines handle reads/writes to // the 'zeroth' page of the DS8390 register file // Bit32u bx_ne2k_c::page0_read(Bit32u offset, unsigned int io_len) { Bit8u value = 0; if (io_len > 1) { BX_ERROR(("bad length! page 0 read from register 0x%02x, len=%u", offset, io_len)); /* encountered with win98 hardware probe */ return value; } switch (offset) { case 0x1: // CLDA0 value = (BX_NE2K_THIS s.local_dma & 0xff); break; case 0x2: // CLDA1 value = (BX_NE2K_THIS s.local_dma >> 8); break; case 0x3: // BNRY value = BX_NE2K_THIS s.bound_ptr; break; case 0x4: // TSR value = ((BX_NE2K_THIS s.TSR.ow_coll << 7) | (BX_NE2K_THIS s.TSR.cd_hbeat << 6) | (BX_NE2K_THIS s.TSR.fifo_ur << 5) | (BX_NE2K_THIS s.TSR.no_carrier << 4) | (BX_NE2K_THIS s.TSR.aborted << 3) | (BX_NE2K_THIS s.TSR.collided << 2) | (BX_NE2K_THIS s.TSR.tx_ok)); break; case 0x5: // NCR value = BX_NE2K_THIS s.num_coll; break; case 0x6: // FIFO // reading FIFO is only valid in loopback mode BX_ERROR(("reading FIFO not supported yet")); value = BX_NE2K_THIS s.fifo; break; case 0x7: // ISR value = ((BX_NE2K_THIS s.ISR.reset << 7) | (BX_NE2K_THIS s.ISR.rdma_done << 6) | (BX_NE2K_THIS s.ISR.cnt_oflow << 5) | (BX_NE2K_THIS s.ISR.overwrite << 4) | (BX_NE2K_THIS s.ISR.tx_err << 3) | (BX_NE2K_THIS s.ISR.rx_err << 2) | (BX_NE2K_THIS s.ISR.pkt_tx << 1) | (BX_NE2K_THIS s.ISR.pkt_rx)); break; case 0x8: // CRDA0 value = (BX_NE2K_THIS s.remote_dma & 0xff); break; case 0x9: // CRDA1 value = (BX_NE2K_THIS s.remote_dma >> 8); break; case 0xa: // reserved / RTL8029ID0 if (BX_NE2K_THIS s.pci_enabled) { value = 0x50; } else { BX_INFO(("reserved read - page 0, 0xa")); value = 0xff; } break; case 0xb: // reserved / RTL8029ID1 if (BX_NE2K_THIS s.pci_enabled) { value = 0x43; } else { BX_INFO(("reserved read - page 0, 0xb")); value = 0xff; } break; case 0xc: // RSR value = ((BX_NE2K_THIS s.RSR.deferred << 7) | (BX_NE2K_THIS s.RSR.rx_disabled << 6) | (BX_NE2K_THIS s.RSR.rx_mbit << 5) | (BX_NE2K_THIS s.RSR.rx_missed << 4) | (BX_NE2K_THIS s.RSR.fifo_or << 3) | (BX_NE2K_THIS s.RSR.bad_falign << 2) | (BX_NE2K_THIS s.RSR.bad_crc << 1) | (BX_NE2K_THIS s.RSR.rx_ok)); break; case 0xd: // CNTR0 value = BX_NE2K_THIS s.tallycnt_0; break; case 0xe: // CNTR1 value = BX_NE2K_THIS s.tallycnt_1; break; case 0xf: // CNTR2 value = BX_NE2K_THIS s.tallycnt_2; break; default: BX_PANIC(("page 0 register 0x%02x out of range", offset)); } BX_DEBUG(("page 0 read from register 0x%02x, value=0x%02x", offset, value)); return value; } void bx_ne2k_c::page0_write(Bit32u offset, Bit32u value, unsigned io_len) { Bit8u value2; // It appears to be a common practice to use outw on page0 regs... // break up outw into two outb's if (io_len == 2) { page0_write(offset, (value & 0xff), 1); if (offset < 0x0f) { page0_write(offset + 1, ((value >> 8) & 0xff), 1); } return; } BX_DEBUG(("page 0 write to register 0x%02x, value=0x%02x", offset, value)); switch (offset) { case 0x1: // PSTART BX_NE2K_THIS s.page_start = value; break; case 0x2: // PSTOP BX_NE2K_THIS s.page_stop = value; break; case 0x3: // BNRY BX_NE2K_THIS s.bound_ptr = value; break; case 0x4: // TPSR BX_NE2K_THIS s.tx_page_start = value; break; case 0x5: // TBCR0 // Clear out low byte and re-insert BX_NE2K_THIS s.tx_bytes &= 0xff00; BX_NE2K_THIS s.tx_bytes |= (value & 0xff); break; case 0x6: // TBCR1 // Clear out high byte and re-insert BX_NE2K_THIS s.tx_bytes &= 0x00ff; BX_NE2K_THIS s.tx_bytes |= ((value & 0xff) << 8); break; case 0x7: // ISR value &= 0x7f; // clear RST bit - status-only bit // All other values are cleared iff the ISR bit is 1 BX_NE2K_THIS s.ISR.pkt_rx &= ~((bx_bool)((value & 0x01) == 0x01)); BX_NE2K_THIS s.ISR.pkt_tx &= ~((bx_bool)((value & 0x02) == 0x02)); BX_NE2K_THIS s.ISR.rx_err &= ~((bx_bool)((value & 0x04) == 0x04)); BX_NE2K_THIS s.ISR.tx_err &= ~((bx_bool)((value & 0x08) == 0x08)); BX_NE2K_THIS s.ISR.overwrite &= ~((bx_bool)((value & 0x10) == 0x10)); BX_NE2K_THIS s.ISR.cnt_oflow &= ~((bx_bool)((value & 0x20) == 0x20)); BX_NE2K_THIS s.ISR.rdma_done &= ~((bx_bool)((value & 0x40) == 0x40)); value = ((BX_NE2K_THIS s.ISR.rdma_done << 6) | (BX_NE2K_THIS s.ISR.cnt_oflow << 5) | (BX_NE2K_THIS s.ISR.overwrite << 4) | (BX_NE2K_THIS s.ISR.tx_err << 3) | (BX_NE2K_THIS s.ISR.rx_err << 2) | (BX_NE2K_THIS s.ISR.pkt_tx << 1) | (BX_NE2K_THIS s.ISR.pkt_rx)); value &= ((BX_NE2K_THIS s.IMR.rdma_inte << 6) | (BX_NE2K_THIS s.IMR.cofl_inte << 5) | (BX_NE2K_THIS s.IMR.overw_inte << 4) | (BX_NE2K_THIS s.IMR.txerr_inte << 3) | (BX_NE2K_THIS s.IMR.rxerr_inte << 2) | (BX_NE2K_THIS s.IMR.tx_inte << 1) | (BX_NE2K_THIS s.IMR.rx_inte)); if (value == 0) set_irq_level(0); break; case 0x8: // RSAR0 // Clear out low byte and re-insert BX_NE2K_THIS s.remote_start &= 0xff00; BX_NE2K_THIS s.remote_start |= (value & 0xff); BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start; break; case 0x9: // RSAR1 // Clear out high byte and re-insert BX_NE2K_THIS s.remote_start &= 0x00ff; BX_NE2K_THIS s.remote_start |= ((value & 0xff) << 8); BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start; break; case 0xa: // RBCR0 // Clear out low byte and re-insert BX_NE2K_THIS s.remote_bytes &= 0xff00; BX_NE2K_THIS s.remote_bytes |= (value & 0xff); break; case 0xb: // RBCR1 // Clear out high byte and re-insert BX_NE2K_THIS s.remote_bytes &= 0x00ff; BX_NE2K_THIS s.remote_bytes |= ((value & 0xff) << 8); break; case 0xc: // RCR // Check if the reserved bits are set if (value & 0xc0) BX_INFO(("RCR write, reserved bits set")); // Set all other bit-fields BX_NE2K_THIS s.RCR.errors_ok = ((value & 0x01) == 0x01); BX_NE2K_THIS s.RCR.runts_ok = ((value & 0x02) == 0x02); BX_NE2K_THIS s.RCR.broadcast = ((value & 0x04) == 0x04); BX_NE2K_THIS s.RCR.multicast = ((value & 0x08) == 0x08); BX_NE2K_THIS s.RCR.promisc = ((value & 0x10) == 0x10); BX_NE2K_THIS s.RCR.monitor = ((value & 0x20) == 0x20); // Monitor bit is a little suspicious... if (value & 0x20) BX_INFO(("RCR write, monitor bit set!")); break; case 0xd: // TCR // Check reserved bits if (value & 0xe0) BX_ERROR(("TCR write, reserved bits set")); // Test loop mode (not supported) if (value & 0x06) { BX_NE2K_THIS s.TCR.loop_cntl = (value & 0x6) >> 1; BX_INFO(("TCR write, loop mode %d not supported", BX_NE2K_THIS s.TCR.loop_cntl)); } else { BX_NE2K_THIS s.TCR.loop_cntl = 0; } // Inhibit-CRC not supported. if (value & 0x01) BX_PANIC(("TCR write, inhibit-CRC not supported")); // Auto-transmit disable very suspicious if (value & 0x08) BX_PANIC(("TCR write, auto transmit disable not supported")); // Allow collision-offset to be set, although not used BX_NE2K_THIS s.TCR.coll_prio = ((value & 0x08) == 0x08); break; case 0xe: // DCR // the loopback mode is not suppported yet if (!(value & 0x08)) { BX_ERROR(("DCR write, loopback mode selected")); } // It is questionable to set longaddr and auto_rx, since they // aren't supported on the ne2000. Print a warning and continue if (value & 0x04) BX_INFO(("DCR write - LAS set ???")); if (value & 0x10) BX_INFO(("DCR write - AR set ???")); // Set other values. BX_NE2K_THIS s.DCR.wdsize = ((value & 0x01) == 0x01); BX_NE2K_THIS s.DCR.endian = ((value & 0x02) == 0x02); BX_NE2K_THIS s.DCR.longaddr = ((value & 0x04) == 0x04); // illegal ? BX_NE2K_THIS s.DCR.loop = ((value & 0x08) == 0x08); BX_NE2K_THIS s.DCR.auto_rx = ((value & 0x10) == 0x10); // also illegal ? BX_NE2K_THIS s.DCR.fifo_size = (value & 0x50) >> 5; break; case 0xf: // IMR // Check for reserved bit if (value & 0x80) BX_ERROR(("IMR write, reserved bit set")); // Set other values BX_NE2K_THIS s.IMR.rx_inte = ((value & 0x01) == 0x01); BX_NE2K_THIS s.IMR.tx_inte = ((value & 0x02) == 0x02); BX_NE2K_THIS s.IMR.rxerr_inte = ((value & 0x04) == 0x04); BX_NE2K_THIS s.IMR.txerr_inte = ((value & 0x08) == 0x08); BX_NE2K_THIS s.IMR.overw_inte = ((value & 0x10) == 0x10); BX_NE2K_THIS s.IMR.cofl_inte = ((value & 0x20) == 0x20); BX_NE2K_THIS s.IMR.rdma_inte = ((value & 0x40) == 0x40); value2 = ((BX_NE2K_THIS s.ISR.rdma_done << 6) | (BX_NE2K_THIS s.ISR.cnt_oflow << 5) | (BX_NE2K_THIS s.ISR.overwrite << 4) | (BX_NE2K_THIS s.ISR.tx_err << 3) | (BX_NE2K_THIS s.ISR.rx_err << 2) | (BX_NE2K_THIS s.ISR.pkt_tx << 1) | (BX_NE2K_THIS s.ISR.pkt_rx)); if (((value & value2) & 0x7f) == 0) { set_irq_level(0); } else { set_irq_level(1); } break; default: BX_PANIC(("page 0 write, bad register 0x%02x", offset)); } } // // page1_read/page1_write - These routines handle reads/writes to // the first page of the DS8390 register file // Bit32u bx_ne2k_c::page1_read(Bit32u offset, unsigned int io_len) { BX_DEBUG(("page 1 read from register 0x%02x, len=%u", offset, io_len)); if (io_len > 1) BX_PANIC(("bad length! page 1 read from register 0x%02x, len=%u", offset, io_len)); switch (offset) { case 0x1: // PAR0-5 case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: return (BX_NE2K_THIS s.physaddr[offset - 1]); break; case 0x7: // CURR BX_DEBUG(("returning current page: 0x%02x", (BX_NE2K_THIS s.curr_page))); return (BX_NE2K_THIS s.curr_page); case 0x8: // MAR0-7 case 0x9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf: return (BX_NE2K_THIS s.mchash[offset - 8]); break; default: BX_PANIC(("page 1 read register 0x%02x out of range", offset)); } return (0); } void bx_ne2k_c::page1_write(Bit32u offset, Bit32u value, unsigned io_len) { BX_DEBUG(("page 1 write to register 0x%02x, len=%u, value=0x%04x", offset, io_len, value)); switch (offset) { case 0x1: // PAR0-5 case 0x2: case 0x3: case 0x4: case 0x5: case 0x6: BX_NE2K_THIS s.physaddr[offset - 1] = value; if (offset == 6) { BX_INFO(("Physical address set to %02x:%02x:%02x:%02x:%02x:%02x", BX_NE2K_THIS s.physaddr[0], BX_NE2K_THIS s.physaddr[1], BX_NE2K_THIS s.physaddr[2], BX_NE2K_THIS s.physaddr[3], BX_NE2K_THIS s.physaddr[4], BX_NE2K_THIS s.physaddr[5])); } break; case 0x7: // CURR BX_NE2K_THIS s.curr_page = value; break; case 0x8: // MAR0-7 case 0x9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf: BX_NE2K_THIS s.mchash[offset - 8] = value; break; default: BX_PANIC(("page 1 write register 0x%02x out of range", offset)); } } // // page2_read/page2_write - These routines handle reads/writes to // the second page of the DS8390 register file // Bit32u bx_ne2k_c::page2_read(Bit32u offset, unsigned int io_len) { BX_DEBUG(("page 2 read from register 0x%02x, len=%u", offset, io_len)); if (io_len > 1) BX_PANIC(("bad length! page 2 read from register 0x%02x, len=%u", offset, io_len)); switch (offset) { case 0x1: // PSTART return (BX_NE2K_THIS s.page_start); case 0x2: // PSTOP return (BX_NE2K_THIS s.page_stop); case 0x3: // Remote Next-packet pointer return (BX_NE2K_THIS s.rempkt_ptr); case 0x4: // TPSR return (BX_NE2K_THIS s.tx_page_start); case 0x5: // Local Next-packet pointer return (BX_NE2K_THIS s.localpkt_ptr); case 0x6: // Address counter (upper) return (BX_NE2K_THIS s.address_cnt >> 8); case 0x7: // Address counter (lower) return (BX_NE2K_THIS s.address_cnt & 0xff); case 0x8: // Reserved case 0x9: case 0xa: case 0xb: BX_ERROR(("reserved read - page 2, register 0x%02x", offset)); return (0xff); case 0xc: // RCR return ((BX_NE2K_THIS s.RCR.monitor << 5) | (BX_NE2K_THIS s.RCR.promisc << 4) | (BX_NE2K_THIS s.RCR.multicast << 3) | (BX_NE2K_THIS s.RCR.broadcast << 2) | (BX_NE2K_THIS s.RCR.runts_ok << 1) | (BX_NE2K_THIS s.RCR.errors_ok)); case 0xd: // TCR return ((BX_NE2K_THIS s.TCR.coll_prio << 4) | (BX_NE2K_THIS s.TCR.ext_stoptx << 3) | ((BX_NE2K_THIS s.TCR.loop_cntl & 0x3) << 1) | (BX_NE2K_THIS s.TCR.crc_disable)); case 0xe: // DCR return (((BX_NE2K_THIS s.DCR.fifo_size & 0x3) << 5) | (BX_NE2K_THIS s.DCR.auto_rx << 4) | (BX_NE2K_THIS s.DCR.loop << 3) | (BX_NE2K_THIS s.DCR.longaddr << 2) | (BX_NE2K_THIS s.DCR.endian << 1) | (BX_NE2K_THIS s.DCR.wdsize)); case 0xf: // IMR return ((BX_NE2K_THIS s.IMR.rdma_inte << 6) | (BX_NE2K_THIS s.IMR.cofl_inte << 5) | (BX_NE2K_THIS s.IMR.overw_inte << 4) | (BX_NE2K_THIS s.IMR.txerr_inte << 3) | (BX_NE2K_THIS s.IMR.rxerr_inte << 2) | (BX_NE2K_THIS s.IMR.tx_inte << 1) | (BX_NE2K_THIS s.IMR.rx_inte)); default: BX_PANIC(("page 2 register 0x%02x out of range", offset)); } return (0); } void bx_ne2k_c::page2_write(Bit32u offset, Bit32u value, unsigned io_len) { // Maybe all writes here should be BX_PANIC()'d, since they // affect internal operation, but let them through for now // and print a warning. BX_ERROR(("page 2 write to register 0x%02x, len=%u, value=0x%04x", offset, io_len, value)); switch (offset) { case 0x1: // CLDA0 // Clear out low byte and re-insert BX_NE2K_THIS s.local_dma &= 0xff00; BX_NE2K_THIS s.local_dma |= (value & 0xff); break; case 0x2: // CLDA1 // Clear out high byte and re-insert BX_NE2K_THIS s.local_dma &= 0x00ff; BX_NE2K_THIS s.local_dma |= ((value & 0xff) << 8); break; case 0x3: // Remote Next-pkt pointer BX_NE2K_THIS s.rempkt_ptr = value; break; case 0x4: BX_PANIC(("page 2 write to reserved register 0x04")); break; case 0x5: // Local Next-packet pointer BX_NE2K_THIS s.localpkt_ptr = value; break; case 0x6: // Address counter (upper) // Clear out high byte and re-insert BX_NE2K_THIS s.address_cnt &= 0x00ff; BX_NE2K_THIS s.address_cnt |= ((value & 0xff) << 8); break; case 0x7: // Address counter (lower) // Clear out low byte and re-insert BX_NE2K_THIS s.address_cnt &= 0xff00; BX_NE2K_THIS s.address_cnt |= (value & 0xff); break; case 0x8: case 0x9: case 0xa: case 0xb: case 0xc: case 0xd: case 0xe: case 0xf: BX_PANIC(("page 2 write to reserved register 0x%02x", offset)); break; default: BX_PANIC(("page 2 write, illegal register 0x%02x", offset)); break; } } // // page3_read/page3_write - writes to this page are illegal // Bit32u bx_ne2k_c::page3_read(Bit32u offset, unsigned int io_len) { if (BX_NE2K_THIS s.pci_enabled) { switch (offset) { case 0x3: // CONFIG0 return (0); case 0x5: // CONFIG2 return (0x40); case 0x6: // CONFIG3 return (0x40); default: BX_ERROR(("page 3 read register 0x%02x attempted", offset)); return (0); } } else { BX_ERROR(("page 3 read register 0x%02x attempted", offset)); return (0); } } void bx_ne2k_c::page3_write(Bit32u offset, Bit32u value, unsigned io_len) { BX_ERROR(("page 3 write register 0x%02x attempted", offset)); } // // tx_timer_handler/tx_timer // void bx_ne2k_c::tx_timer_handler(void *this_ptr) { bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr; class_ptr->tx_timer(); } void bx_ne2k_c::tx_timer(void) { BX_DEBUG(("tx_timer")); BX_NE2K_THIS s.CR.tx_packet = 0; BX_NE2K_THIS s.TSR.tx_ok = 1; BX_NE2K_THIS s.ISR.pkt_tx = 1; // Generate an interrupt if not masked if (BX_NE2K_THIS s.IMR.tx_inte) { set_irq_level(1); } BX_NE2K_THIS s.tx_timer_active = 0; } #if BX_SUPPORT_PCI bx_bool bx_ne2k_c::mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; Bit32u mask = (BX_NE2K_THIS pci_rom_size - 1); #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { if (BX_NE2K_THIS pci_conf[0x30] & 0x01) { *data_ptr = BX_NE2K_THIS pci_rom[addr & mask]; } else { *data_ptr = 0xff; } addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } bx_bool bx_ne2k_c::mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { BX_INFO(("write to ROM ignored (addr=0x%08x len=%d)", (Bit32u)addr, len)); return 1; } #endif // // read_handler/read - i/o 'catcher' function called from BOCHS // mainline when the CPU attempts a read in the i/o space registered // by this ne2000 instance // Bit32u bx_ne2k_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_NE2K_SMF bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_ne2k_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_NE2K_SMF BX_DEBUG(("read addr %x, len %d", address, io_len)); Bit32u retval = 0; int offset = address - BX_NE2K_THIS s.base_address; if (offset >= 0x10) { retval = asic_read(offset - 0x10, io_len); } else if (offset == 0x00) { retval = read_cr(); } else { switch (BX_NE2K_THIS s.CR.pgsel) { case 0x00: retval = page0_read(offset, io_len); break; case 0x01: retval = page1_read(offset, io_len); break; case 0x02: retval = page2_read(offset, io_len); break; case 0x03: retval = page3_read(offset, io_len); break; default: BX_PANIC(("ne2K: unknown value of pgsel in read - %d", BX_NE2K_THIS s.CR.pgsel)); } } return (retval); } // // write_handler/write - i/o 'catcher' function called from BOCHS // mainline when the CPU attempts a write in the i/o space registered // by this ne2000 instance // void bx_ne2k_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_NE2K_SMF bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_ne2k_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_NE2K_SMF BX_DEBUG(("write addr %x, value %x len %d", address, value, io_len)); int offset = address - BX_NE2K_THIS s.base_address; // // The high 16 bytes of i/o space are for the ne2000 asic - // the low 16 bytes are for the DS8390, with the current // page being selected by the PS0,PS1 registers in the // command register // if (offset >= 0x10) { asic_write(offset - 0x10, value, io_len); } else if (offset == 0x00) { write_cr(value); } else { switch (BX_NE2K_THIS s.CR.pgsel) { case 0x00: page0_write(offset, value, io_len); break; case 0x01: page1_write(offset, value, io_len); break; case 0x02: page2_write(offset, value, io_len); break; case 0x03: page3_write(offset, value, io_len); break; default: BX_PANIC(("ne2K: unknown value of pgsel in write - %d", BX_NE2K_THIS s.CR.pgsel)); } } } /* * mcast_index() - return the 6-bit index into the multicast * table. Stolen unashamedly from FreeBSD's if_ed.c */ unsigned bx_ne2k_c::mcast_index(const void *dst) { #define POLYNOMIAL 0x04c11db6 Bit32u crc = 0xffffffffL; int carry, i, j; unsigned char b; unsigned char *ep = (unsigned char *) dst; for (i = 6; --i >= 0;) { b = *ep++; for (j = 8; --j >= 0;) { carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); crc <<= 1; b >>= 1; if (carry) crc = ((crc ^ POLYNOMIAL) | carry); } } return (crc >> 26); #undef POLYNOMIAL } /* * Callback from the eth system driver to check if the device can receive */ Bit32u bx_ne2k_c::rx_status_handler(void *arg) { bx_ne2k_c *class_ptr = (bx_ne2k_c *) arg; return class_ptr->rx_status(); } Bit32u bx_ne2k_c::rx_status() { Bit32u status = BX_NETDEV_10MBIT; if ((BX_NE2K_THIS s.CR.stop == 0) && (BX_NE2K_THIS s.page_start != 0) && ((BX_NE2K_THIS s.DCR.loop != 0) || (BX_NE2K_THIS s.TCR.loop_cntl == 0))) { status |= BX_NETDEV_RXREADY; } return status; } /* * Callback from the eth system driver when a frame has arrived */ void bx_ne2k_c::rx_handler(void *arg, const void *buf, unsigned len) { // BX_DEBUG(("rx_handler with length %d", len)); bx_ne2k_c *class_ptr = (bx_ne2k_c *) arg; class_ptr->rx_frame(buf, len); } /* * rx_frame() - called by the platform-specific code when an * ethernet frame has been received. The destination address * is tested to see if it should be accepted, and if the * rx ring has enough room, it is copied into it and * the receive process is updated */ void bx_ne2k_c::rx_frame(const void *buf, unsigned io_len) { int pages; int avail; unsigned idx; int wrapped; int nextpage; unsigned char pkthdr[4]; unsigned char *pktbuf = (unsigned char *) buf; unsigned char *startptr; BX_DEBUG(("rx_frame with length %d", io_len)); if ((BX_NE2K_THIS s.CR.stop != 0) || (BX_NE2K_THIS s.page_start == 0) || ((BX_NE2K_THIS s.DCR.loop == 0) && (BX_NE2K_THIS s.TCR.loop_cntl != 0))) { return; } // Add the pkt header + CRC to the length, and work // out how many 256-byte pages the frame would occupy pages = (io_len + 4 + 4 + 255)/256; if (BX_NE2K_THIS s.curr_page < BX_NE2K_THIS s.bound_ptr) { avail = BX_NE2K_THIS s.bound_ptr - BX_NE2K_THIS s.curr_page; } else { avail = (BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start) - (BX_NE2K_THIS s.curr_page - BX_NE2K_THIS s.bound_ptr); wrapped = 1; } // Avoid getting into a buffer overflow condition by not attempting // to do partial receives. The emulation to handle this condition // seems particularly painful. if ((avail < pages) #if BX_NE2K_NEVER_FULL_RING || (avail == pages) #endif ) { return; } if ((io_len < 60) && !BX_NE2K_THIS s.RCR.runts_ok) { BX_DEBUG(("rejected small packet, length %d", io_len)); return; } // Do address filtering if not in promiscuous mode if (! BX_NE2K_THIS s.RCR.promisc) { if (!memcmp(buf, broadcast_macaddr, 6)) { if (!BX_NE2K_THIS s.RCR.broadcast) { return; } } else if (pktbuf[0] & 0x01) { if (! BX_NE2K_THIS s.RCR.multicast) { return; } idx = mcast_index(buf); if (!(BX_NE2K_THIS s.mchash[idx >> 3] & (1 << (idx & 0x7)))) { return; } } else if (0 != memcmp(buf, BX_NE2K_THIS s.physaddr, 6)) { return; } } else { BX_DEBUG(("rx_frame promiscuous receive")); } // BX_INFO(("rx_frame %d to %x:%x:%x:%x:%x:%x from %x:%x:%x:%x:%x:%x", // io_len, // pktbuf[0], pktbuf[1], pktbuf[2], pktbuf[3], pktbuf[4], pktbuf[5], // pktbuf[6], pktbuf[7], pktbuf[8], pktbuf[9], pktbuf[10], pktbuf[11])); nextpage = BX_NE2K_THIS s.curr_page + pages; if (nextpage >= BX_NE2K_THIS s.page_stop) { nextpage -= BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start; } // Setup packet header pkthdr[0] = 0; // rx status - old behavior pkthdr[0] = 1; // Probably better to set it all the time // rather than set it to 0, which is clearly wrong. if (pktbuf[0] & 0x01) { pkthdr[0] |= 0x20; // rx status += multicast packet } pkthdr[1] = nextpage; // ptr to next packet pkthdr[2] = (io_len + 4) & 0xff; // length-low pkthdr[3] = (io_len + 4) >> 8; // length-hi // copy into buffer, update curpage, and signal interrupt if config'd startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.curr_page * 256 - BX_NE2K_MEMSTART]; if ((nextpage > BX_NE2K_THIS s.curr_page) || ((BX_NE2K_THIS s.curr_page + pages) == BX_NE2K_THIS s.page_stop)) { memcpy(startptr, pkthdr, 4); memcpy(startptr + 4, buf, io_len); BX_NE2K_THIS s.curr_page = nextpage; } else { int endbytes = (BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.curr_page) * 256; memcpy(startptr, pkthdr, 4); memcpy(startptr + 4, buf, endbytes - 4); startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.page_start * 256 - BX_NE2K_MEMSTART]; memcpy(startptr, (void *)(pktbuf + endbytes - 4), io_len - endbytes + 8); BX_NE2K_THIS s.curr_page = nextpage; } BX_NE2K_THIS s.RSR.rx_ok = 1; BX_NE2K_THIS s.RSR.rx_mbit = (bx_bool)((pktbuf[0] & 0x01) > 0); BX_NE2K_THIS s.ISR.pkt_rx = 1; if (BX_NE2K_THIS s.IMR.rx_inte) { set_irq_level(1); } bx_gui->statusbar_setitem(BX_NE2K_THIS s.statusbar_id, 1); } void bx_ne2k_c::set_irq_level(bx_bool level) { if (BX_NE2K_THIS s.pci_enabled) { #if BX_SUPPORT_PCI DEV_pci_set_irq(BX_NE2K_THIS s.devfunc, BX_NE2K_THIS pci_conf[0x3d], level); #endif } else { if (level) { DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq); } else { DEV_pic_lower_irq(BX_NE2K_THIS s.base_irq); } } } #if BX_SUPPORT_PCI // pci configuration space read callback handler Bit32u bx_ne2k_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i 0x13) && (address < 0x30)) return; for (unsigned i=0; i> (i*8)) & 0xFF; switch (address+i) { case 0x04: value8 &= 0x01; break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); } break; case 0x10: value8 = (value8 & 0xfc) | 0x01; case 0x11: case 0x12: case 0x13: baseaddr_change |= (value8 != oldval); break; case 0x30: case 0x31: case 0x32: case 0x33: if (BX_NE2K_THIS pci_rom_size > 0) { if ((address+i) == 0x30) { value8 &= 0x01; } else if ((address+i) == 0x31) { value8 &= 0xfc; } romaddr_change = 1; break; } default: value8 = oldval; } BX_NE2K_THIS pci_conf[address+i] = value8; } if (baseaddr_change) { if (DEV_pci_set_base_io(BX_NE2K_THIS_PTR, read_handler, write_handler, &BX_NE2K_THIS s.base_address, &BX_NE2K_THIS pci_conf[0x10], 32, &ne2k_iomask[0], "NE2000 PCI NIC")) { BX_INFO(("new base address: 0x%04x", BX_NE2K_THIS s.base_address)); } } if (romaddr_change) { if (DEV_pci_set_base_mem(BX_NE2K_THIS_PTR, mem_read_handler, mem_write_handler, &BX_NE2K_THIS pci_rom_address, &BX_NE2K_THIS pci_conf[0x30], BX_NE2K_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_NE2K_THIS pci_rom_address)); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } #endif /* BX_SUPPORT_PCI */ #if BX_DEBUGGER void bx_ne2k_c::debug_dump(int argc, char **argv) { int page = -1, reg = -1; for (int arg = 0; arg < argc; arg++) { if (!strncmp(argv[arg], "page=", 5) && isdigit(argv[arg][5])) { page = atoi(&argv[arg][5]); } else if (!strncmp(argv[arg], "reg=", 4) && isdigit(argv[arg][4])) { reg = atoi(&argv[arg][4]); } else { dbg_printf("\nUnknown option: '%s'\n", argv[arg]); return; } } BX_NE2K_THIS print_info(page, reg, 0); } /* * this implements the info device 'ne2k' command in the debugger. * info device 'ne2k' - shows all registers * info device 'ne2k' 'page=N' - shows all registers in a page * info device 'ne2k' 'page=N,reg=M' - shows just one register */ #define SHOW_FIELD(reg,field) do { \ if (n>0 && !(n%5)) dbg_printf ("\n "); \ dbg_printf ("%s=%d ", #field, BX_NE2K_THIS s.reg.field); \ n++; \ } while (0); #define BX_HIGH_BYTE(x) ((0xff00 & (x)) >> 8) #define BX_LOW_BYTE(x) (0x00ff & (x)) #define BX_DUPLICATE(n) if (brief && num!=n) break; void bx_ne2k_c::print_info(int page, int reg, int brief) { int i; int n = 0; if (page < 0) { for (page=0; page<=2; page++) theNE2kDevice->print_info(page, reg, 1); // tell them how to use this command dbg_printf("\nSupported options:\n"); dbg_printf("info device 'ne2k' 'page=N' - show registers in page N\n"); dbg_printf("info device 'ne2k' 'page=N,reg=M' - show just one register\n"); return; } if (page > 2) { dbg_printf("NE2K has only pages 0, 1, and 2. Page %d is out of range.\n", page); return; } if (reg < 0) { dbg_printf("NE2K registers, page %d\n", page); dbg_printf("----------------------\n"); for (reg=0; reg<=15; reg++) theNE2kDevice->print_info(page, reg, 1); dbg_printf("----------------------\n"); return; } if (reg > 15) { dbg_printf("NE2K has only registers 0-15 (0x0-0xf). Register %d is out of range.\n", reg); return; } if (!brief) { dbg_printf("NE2K Info - page %d, register 0x%02x\n", page, reg); dbg_printf("----------------------------------\n"); } int num = page*0x100 + reg; switch (num) { case 0x0000: case 0x0100: case 0x0200: dbg_printf ("CR (Command register):\n "); SHOW_FIELD(CR, stop); SHOW_FIELD(CR, start); SHOW_FIELD(CR, tx_packet); SHOW_FIELD(CR, rdma_cmd); SHOW_FIELD(CR, pgsel); dbg_printf("\n"); break; case 0x0003: dbg_printf("BNRY = Boundary Pointer = 0x%02x\n", BX_NE2K_THIS s.bound_ptr); break; case 0x0004: dbg_printf("TSR (Transmit Status Register), read-only:\n "); SHOW_FIELD(TSR, tx_ok); SHOW_FIELD(TSR, reserved); SHOW_FIELD(TSR, collided); SHOW_FIELD(TSR, aborted); SHOW_FIELD(TSR, no_carrier); SHOW_FIELD(TSR, fifo_ur); SHOW_FIELD(TSR, cd_hbeat); SHOW_FIELD(TSR, ow_coll); dbg_printf("\n"); // fall through into TPSR, no break line. case 0x0204: dbg_printf("TPSR = Transmit Page Start = 0x%02x\n", BX_NE2K_THIS s.tx_page_start); break; case 0x0005: case 0x0006: BX_DUPLICATE(0x0005); dbg_printf("NCR = Number of Collisions Register (read-only) = 0x%02x\n", BX_NE2K_THIS s.num_coll); dbg_printf("TBCR1,TBCR0 = Transmit Byte Count = %02x %02x\n", BX_HIGH_BYTE(BX_NE2K_THIS s.tx_bytes), BX_LOW_BYTE(BX_NE2K_THIS s.tx_bytes)); dbg_printf("FIFO = %02x\n", BX_NE2K_THIS s.fifo); break; case 0x0007: dbg_printf("ISR (Interrupt Status Register):\n "); SHOW_FIELD(ISR, pkt_rx); SHOW_FIELD(ISR, pkt_tx); SHOW_FIELD(ISR, rx_err); SHOW_FIELD(ISR, tx_err); SHOW_FIELD(ISR, overwrite); SHOW_FIELD(ISR, cnt_oflow); SHOW_FIELD(ISR, rdma_done); SHOW_FIELD(ISR, reset); dbg_printf("\n"); break; case 0x0008: case 0x0009: BX_DUPLICATE(0x0008); dbg_printf("CRDA1,0 = Current remote DMA address = %02x %02x\n", BX_HIGH_BYTE(BX_NE2K_THIS s.remote_dma), BX_LOW_BYTE(BX_NE2K_THIS s.remote_dma)); dbg_printf("RSAR1,0 = Remote start address = %02x %02x\n", BX_HIGH_BYTE(s.remote_start), BX_LOW_BYTE(s.remote_start)); break; case 0x000a: case 0x000b: BX_DUPLICATE(0x000a); dbg_printf("RCBR1,0 = Remote byte count = %02x\n", BX_NE2K_THIS s.remote_bytes); break; case 0x000c: dbg_printf("RSR (Receive Status Register), read-only:\n "); SHOW_FIELD(RSR, rx_ok); SHOW_FIELD(RSR, bad_crc); SHOW_FIELD(RSR, bad_falign); SHOW_FIELD(RSR, fifo_or); SHOW_FIELD(RSR, rx_missed); SHOW_FIELD(RSR, rx_mbit); SHOW_FIELD(RSR, rx_disabled); SHOW_FIELD(RSR, deferred); dbg_printf("\n"); // fall through into RCR case 0x020c: dbg_printf("RCR (Receive Configuration Register):\n "); SHOW_FIELD(RCR, errors_ok); SHOW_FIELD(RCR, runts_ok); SHOW_FIELD(RCR, broadcast); SHOW_FIELD(RCR, multicast); SHOW_FIELD(RCR, promisc); SHOW_FIELD(RCR, monitor); SHOW_FIELD(RCR, reserved); dbg_printf("\n"); break; case 0x000d: dbg_printf("CNTR0 = Tally Counter 0 (Frame alignment errors) = %02x\n", BX_NE2K_THIS s.tallycnt_0); // fall through into TCR case 0x020d: dbg_printf("TCR (Transmit Configuration Register):\n "); SHOW_FIELD(TCR, crc_disable); SHOW_FIELD(TCR, loop_cntl); SHOW_FIELD(TCR, ext_stoptx); SHOW_FIELD(TCR, coll_prio); SHOW_FIELD(TCR, reserved); dbg_printf("\n"); break; case 0x000e: dbg_printf("CNTR1 = Tally Counter 1 (CRC Errors) = %02x\n", BX_NE2K_THIS s.tallycnt_1); // fall through into DCR case 0x020e: dbg_printf("DCR (Data Configuration Register):\n "); SHOW_FIELD(DCR, wdsize); SHOW_FIELD(DCR, endian); SHOW_FIELD(DCR, longaddr); SHOW_FIELD(DCR, loop); SHOW_FIELD(DCR, auto_rx); SHOW_FIELD(DCR, fifo_size); dbg_printf("\n"); break; case 0x000f: dbg_printf("CNTR2 = Tally Counter 2 (Missed Packet Errors) = %02x\n", BX_NE2K_THIS s.tallycnt_2); // fall through into IMR case 0x020f: dbg_printf("IMR (Interrupt Mask Register)\n "); SHOW_FIELD(IMR, rx_inte); SHOW_FIELD(IMR, tx_inte); SHOW_FIELD(IMR, rxerr_inte); SHOW_FIELD(IMR, txerr_inte); SHOW_FIELD(IMR, overw_inte); SHOW_FIELD(IMR, cofl_inte); SHOW_FIELD(IMR, rdma_inte); SHOW_FIELD(IMR, reserved); dbg_printf("\n"); break; case 0x0101: case 0x0102: BX_DUPLICATE(0x0101); case 0x0103: BX_DUPLICATE(0x0101); case 0x0104: BX_DUPLICATE(0x0101); case 0x0105: BX_DUPLICATE(0x0101); case 0x0106: BX_DUPLICATE(0x0101); dbg_printf("MAC address registers are located at page 1, registers 1-6.\n"); dbg_printf("The MAC address is "); for (i=0; i<=5; i++) dbg_printf("%02x%c", BX_NE2K_THIS s.physaddr[i], i<5?':' : '\n'); break; case 0x0107: dbg_printf("Current page is 0x%02x\n", BX_NE2K_THIS s.curr_page); break; case 0x0108: case 0x0109: BX_DUPLICATE(0x0108); case 0x010A: BX_DUPLICATE(0x0108); case 0x010B: BX_DUPLICATE(0x0108); case 0x010C: BX_DUPLICATE(0x0108); case 0x010D: BX_DUPLICATE(0x0108); case 0x010E: BX_DUPLICATE(0x0108); case 0x010F: BX_DUPLICATE(0x0108); dbg_printf("MAR0-7 (Multicast address registers 0-7) are set to:\n"); for (i=0; i<8; i++) dbg_printf("%02x ", BX_NE2K_THIS s.mchash[i]); dbg_printf("\nMAR0 is listed first.\n"); break; case 0x0001: case 0x0002: BX_DUPLICATE(0x0001); case 0x0201: BX_DUPLICATE(0x0001); case 0x0202: BX_DUPLICATE(0x0001); dbg_printf("PSTART = Page start register = %02x\n", BX_NE2K_THIS s.page_start); dbg_printf("PSTOP = Page stop register = %02x\n", BX_NE2K_THIS s.page_stop); dbg_printf("Local DMA address = %02x %02x\n", BX_HIGH_BYTE(BX_NE2K_THIS s.local_dma), BX_LOW_BYTE(BX_NE2K_THIS s.local_dma)); break; case 0x0203: dbg_printf("Remote Next Packet Pointer = %02x\n", BX_NE2K_THIS s.rempkt_ptr); break; case 0x0205: dbg_printf("Local Next Packet Pointer = %02x\n", BX_NE2K_THIS s.localpkt_ptr); break; case 0x0206: case 0x0207: BX_DUPLICATE(0x0206); dbg_printf("Address Counter= %02x %02x\n", BX_HIGH_BYTE(BX_NE2K_THIS s.address_cnt), BX_LOW_BYTE(BX_NE2K_THIS s.address_cnt)); break; case 0x0208: case 0x0209: BX_DUPLICATE(0x0208); case 0x020A: BX_DUPLICATE(0x0208); case 0x020B: BX_DUPLICATE(0x0208); if (!brief) dbg_printf ("Reserved\n"); case 0xffff: dbg_printf("IMR (Interrupt Mask Register):\n "); dbg_printf("\n"); break; default: dbg_printf("NE2K info: sorry, page %d register %d cannot be displayed.\n", page, reg); } if (!brief) dbg_printf("\n"); } #endif #endif /* if BX_SUPPORT_NE2K */ bochs-2.6/iodev/network/netmod.cc0000644000175000017500000006256712020641503016742 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: netmod.cc 11342 2012-08-16 11:59:44Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Common networking and helper code to find and create pktmover classes // Peter Grehan (grehan@iprg.nokia.com) coded the initial version of the // NE2000/ether stuff. // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_NETWORKING #include "netmod.h" #define LOG_THIS netdev-> bx_netmod_ctl_c* theNetModCtl = NULL; int libnetmod_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theNetModCtl = new bx_netmod_ctl_c; bx_devices.pluginNetModCtl = theNetModCtl; return 0; // Success } else { return -1; } } void libnetmod_LTX_plugin_fini(void) { delete theNetModCtl; } void* bx_netmod_ctl_c::init_module(bx_list_c *base, void *rxh, void *rxstat, bx_devmodel_c *netdev) { eth_pktmover_c *ethmod; // Attach to the selected ethernet module const char *modname = SIM->get_param_enum("ethmod", base)->get_selected(); ethmod = eth_locator_c::create(modname, SIM->get_param_string("ethdev", base)->getptr(), (const char *) SIM->get_param_string("macaddr", base)->getptr(), (eth_rx_handler_t)rxh, (eth_rx_status_t)rxstat, netdev, SIM->get_param_string("script", base)->getptr()); if (ethmod == NULL) { BX_PANIC(("could not find eth module %s", modname)); // if they continue, use null. BX_INFO(("could not find eth module %s - using null instead", modname)); ethmod = eth_locator_c::create("null", NULL, (const char *) SIM->get_param_string("macaddr", base)->getptr(), (eth_rx_handler_t)rxh, (eth_rx_status_t)rxstat, netdev, ""); if (ethmod == NULL) BX_PANIC(("could not locate null module")); } return ethmod; } eth_locator_c *eth_locator_c::all; // // Each pktmover module has a static locator class that registers // here // eth_locator_c::eth_locator_c(const char *type) { next = all; all = this; this->type = type; } extern class bx_null_locator_c bx_null_match; #if BX_NETMOD_FBSD extern class bx_fbsd_locator_c bx_fbsd_match; #endif #if BX_NETMOD_LINUX extern class bx_linux_locator_c bx_linux_match; #endif #if BX_NETMOD_WIN32 extern class bx_win32_locator_c bx_win32_match; #endif #if BX_NETMOD_TAP extern class bx_tap_locator_c bx_tap_match; #endif #if BX_NETMOD_TUNTAP extern class bx_tuntap_locator_c bx_tuntap_match; #endif #if BX_NETMOD_VDE extern class bx_vde_locator_c bx_vde_match; #endif #if BX_NETMOD_SLIRP extern class bx_slirp_locator_c bx_slirp_match; #endif extern class bx_vnet_locator_c bx_vnet_match; // // Called by ethernet chip emulations to locate and create a pktmover // object // eth_pktmover_c * eth_locator_c::create(const char *type, const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { #ifdef eth_static_constructors for (eth_locator_c *p = all; p != NULL; p = p->next) { if (strcmp(type, p->type) == 0) return (p->allocate(netif, macaddr, rxh, rxstat, dev, script)); } #else eth_locator_c *ptr = 0; if (!strcmp(type, "null")) { ptr = (eth_locator_c *) &bx_null_match; } #if BX_NETMOD_FBSD { if (!strcmp(type, "fbsd")) ptr = (eth_locator_c *) &bx_fbsd_match; } #endif #if BX_NETMOD_LINUX { if (!strcmp(type, "linux")) ptr = (eth_locator_c *) &bx_linux_match; } #endif #if BX_NETMOD_TUNTAP { if (!strcmp(type, "tuntap")) ptr = (eth_locator_c *) &bx_tuntap_match; } #endif #if BX_NETMOD_VDE { if (!strcmp(type, "vde")) ptr = (eth_locator_c *) &bx_vde_match; } #endif #if BX_NETMOD_SLIRP { if (!strcmp(type, "slirp")) ptr = (eth_locator_c *) &bx_slirp_match; } #endif #if BX_NETMOD_TAP { if (!strcmp(type, "tap")) ptr = (eth_locator_c *) &bx_tap_match; } #endif #if BX_NETMOD_WIN32 { if(!strcmp(type, "win32")) ptr = (eth_locator_c *) &bx_win32_match; } #endif if (!strcmp(type, "vnet")) { ptr = (eth_locator_c *) &bx_vnet_match; } if (ptr) { return (ptr->allocate(netif, macaddr, rxh, rxstat, dev, script)); } #endif return (NULL); } #if (BX_NETMOD_TAP==1) || (BX_NETMOD_TUNTAP==1) || (BX_NETMOD_VDE==1) extern "C" { #include }; // This is a utility script used for tuntap or ethertap int execute_script(bx_devmodel_c *netdev, const char* scriptname, char* arg1) { int pid,status; if (!(pid=fork())) { char filename[BX_PATHNAME_LEN]; if (scriptname[0]=='/') { strcpy(filename, scriptname); } else { getcwd(filename, BX_PATHNAME_LEN); strcat(filename, "/"); strcat(filename, scriptname); } // execute the script BX_INFO(("Executing script '%s %s'", filename, arg1)); execle(filename, scriptname, arg1, NULL, NULL); // if we get here there has been a problem exit(-1); } wait (&status); if (!WIFEXITED(status)) { return -1; } return WEXITSTATUS(status); } #endif void write_pktlog_txt(FILE *pktlog_txt, const Bit8u *buf, unsigned len, bx_bool host_to_guest) { Bit8u *charbuf = (Bit8u *)buf; unsigned n; if (!host_to_guest) { fprintf(pktlog_txt, "a packet from guest to host, length %u\n", len); } else { fprintf(pktlog_txt, "a packet from host to guest, length %u\n", len); } for (n = 0; n < len; n++) { if (((n % 16) == 0) && (n > 0)) fprintf(pktlog_txt, "\n"); fprintf(pktlog_txt, "%02x ", (unsigned)charbuf[n]); } fprintf(pktlog_txt, "\n--\n"); fflush(pktlog_txt); } Bit16u ip_checksum(const Bit8u *buf, unsigned buf_len) { Bit32u sum = 0; unsigned n; for (n = 0; n < buf_len; n++) { if (n & 1) { sum += (Bit32u)(*buf++); } else { sum += (Bit32u)(*buf++) << 8; } } while (sum > 0xffff) { sum = (sum >> 16) + (sum & 0xffff); } return (Bit16u)sum; } // DHCP server #define BOOTREQUEST 1 #define BOOTREPLY 2 #define BOOTPOPT_PADDING 0 #define BOOTPOPT_END 255 #define BOOTPOPT_SUBNETMASK 1 #define BOOTPOPT_TIMEOFFSET 2 #define BOOTPOPT_ROUTER_OPTION 3 #define BOOTPOPT_DOMAIN_NAMESERVER 6 #define BOOTPOPT_HOST_NAME 12 #define BOOTPOPT_DOMAIN_NAME 15 #define BOOTPOPT_MAX_DATAGRAM_SIZE 22 #define BOOTPOPT_DEFAULT_IP_TTL 23 #define BOOTPOPT_BROADCAST_ADDRESS 28 #define BOOTPOPT_ARPCACHE_TIMEOUT 35 #define BOOTPOPT_DEFAULT_TCP_TTL 37 #define BOOTPOPT_NTP_SERVER 42 #define BOOTPOPT_NETBIOS_NAMESERVER 44 #define BOOTPOPT_X_FONTSERVER 48 #define BOOTPOPT_REQUESTED_IP_ADDRESS 50 #define BOOTPOPT_IP_ADDRESS_LEASE_TIME 51 #define BOOTPOPT_OPTION_OVRLOAD 52 #define BOOTPOPT_DHCP_MESSAGETYPE 53 #define BOOTPOPT_SERVER_IDENTIFIER 54 #define BOOTPOPT_PARAMETER_REQUEST_LIST 55 #define BOOTPOPT_MAX_DHCP_MESSAGE_SIZE 57 #define BOOTPOPT_RENEWAL_TIME 58 #define BOOTPOPT_REBINDING_TIME 59 #define BOOTPOPT_CLASS_IDENTIFIER 60 #define BOOTPOPT_CLIENT_IDENTIFIER 61 #define DHCPDISCOVER 1 #define DHCPOFFER 2 #define DHCPREQUEST 3 #define DHCPDECLINE 4 #define DHCPACK 5 #define DHCPNAK 6 #define DHCPRELEASE 7 #define DHCPINFORM 8 #define DEFAULT_LEASE_TIME 28800 // TFTP server support by EaseWay #define TFTP_RRQ 1 #define TFTP_WRQ 2 #define TFTP_DATA 3 #define TFTP_ACK 4 #define TFTP_ERROR 5 #define TFTP_OPTACK 6 static const Bit8u subnetmask_ipv4addr[4] = {0xff,0xff,0xff,0x00}; static const Bit8u broadcast_ipv4addr1[4] = {0xff,0xff,0xff,0xff}; int process_dhcp(bx_devmodel_c *netdev, const Bit8u *data, unsigned data_len, Bit8u *reply, dhcp_cfg_t *dhcp) { const Bit8u *opts; unsigned opts_len; unsigned extcode; unsigned extlen; const Bit8u *extdata; unsigned dhcpmsgtype = 0; bx_bool found_serverid = false; bx_bool found_leasetime = false; bx_bool found_guest_ipaddr = false; bx_bool found_host_name = false; Bit32u leasetime = BX_MAX_BIT32U; const Bit8u *dhcpreqparams = NULL; unsigned dhcpreqparams_len = 0; Bit8u dhcpreqparam_default[8]; bx_bool dhcpreqparam_default_validflag = false; unsigned dhcpreqparams_default_len = 0; Bit8u *replyopts; Bit8u replybuf[576]; char *hostname = NULL; unsigned hostname_len = 0; if (data_len < (236U+4U)) return 0; if (data[0] != BOOTREQUEST) return 0; if (data[1] != 1 || data[2] != 6) return 0; if (memcmp(&data[28U], dhcp->guest_macaddr, 6)) return 0; if (data[236] != 0x63 || data[237] != 0x82 || data[238] != 0x53 || data[239] != 0x63) return 0; opts = &data[240]; opts_len = data_len - 240U; while (1) { if (opts_len < 1) { BX_ERROR(("dhcp: invalid request")); return 0; } extcode = *opts++; opts_len--; if (extcode == BOOTPOPT_PADDING) continue; if (extcode == BOOTPOPT_END) break; if (opts_len < 1) { BX_ERROR(("dhcp: invalid request")); return 0; } extlen = *opts++; opts_len--; if (opts_len < extlen) { BX_ERROR(("dhcp: invalid request")); return 0; } extdata = opts; opts += extlen; opts_len -= extlen; switch (extcode) { case BOOTPOPT_DHCP_MESSAGETYPE: if (extlen != 1) break; dhcpmsgtype = *extdata; break; case BOOTPOPT_PARAMETER_REQUEST_LIST: if (extlen < 1) break; dhcpreqparams = extdata; dhcpreqparams_len = extlen; break; case BOOTPOPT_SERVER_IDENTIFIER: if (extlen != 4) break; if (memcmp(extdata, dhcp->host_ipv4addr, 4)) { BX_INFO(("dhcp: request to another server")); return 0; } found_serverid = true; break; case BOOTPOPT_IP_ADDRESS_LEASE_TIME: if (extlen != 4) break; leasetime = get_net4(&extdata[0]); found_leasetime = true; break; case BOOTPOPT_REQUESTED_IP_ADDRESS: if (extlen != 4) break; if (!memcmp(extdata, dhcp->default_guest_ipv4addr,4)) { found_guest_ipaddr = true; memcpy(dhcp->guest_ipv4addr, dhcp->default_guest_ipv4addr, 4); } break; case BOOTPOPT_HOST_NAME: if (extlen < 1) break; hostname = (char*)malloc(extlen); memcpy(hostname, extdata, extlen); hostname_len = extlen; found_host_name = true; break; default: BX_ERROR(("extcode %d not supported yet", extcode)); break; } } memset(&dhcpreqparam_default,0,sizeof(dhcpreqparam_default)); memset(&replybuf[0],0,sizeof(replybuf)); replybuf[0] = BOOTREPLY; replybuf[1] = 1; replybuf[2] = 6; memcpy(&replybuf[4],&data[4],4); memcpy(&replybuf[16], dhcp->default_guest_ipv4addr, 4); memcpy(&replybuf[20], dhcp->host_ipv4addr, 4); memcpy(&replybuf[28],&data[28],6); memcpy(&replybuf[44],"vnet",4); memcpy(&replybuf[108],"pxelinux.0",10); replybuf[236] = 0x63; replybuf[237] = 0x82; replybuf[238] = 0x53; replybuf[239] = 0x63; replyopts = &replybuf[240]; opts_len = sizeof(replybuf)/sizeof(replybuf[0])-240; switch (dhcpmsgtype) { case DHCPDISCOVER: BX_INFO(("dhcp server: DHCPDISCOVER")); // reset guest address; answer must be broadcasted to unconfigured IP memcpy(dhcp->guest_ipv4addr, broadcast_ipv4addr1, 4); *replyopts ++ = BOOTPOPT_DHCP_MESSAGETYPE; *replyopts ++ = 1; *replyopts ++ = DHCPOFFER; opts_len -= 3; dhcpreqparam_default[0] = BOOTPOPT_IP_ADDRESS_LEASE_TIME; dhcpreqparam_default[1] = BOOTPOPT_SERVER_IDENTIFIER; if (found_host_name) { dhcpreqparam_default[2] = BOOTPOPT_HOST_NAME; } dhcpreqparam_default_validflag = true; break; case DHCPREQUEST: BX_INFO(("dhcp server: DHCPREQUEST")); // check ciaddr. if (found_serverid || found_guest_ipaddr || (!memcmp(&data[12], dhcp->default_guest_ipv4addr, 4))) { *replyopts ++ = BOOTPOPT_DHCP_MESSAGETYPE; *replyopts ++ = 1; *replyopts ++ = DHCPACK; opts_len -= 3; dhcpreqparam_default[0] = BOOTPOPT_IP_ADDRESS_LEASE_TIME; if (!found_serverid) { dhcpreqparam_default[1] = BOOTPOPT_SERVER_IDENTIFIER; } dhcpreqparam_default_validflag = true; } else { *replyopts ++ = BOOTPOPT_DHCP_MESSAGETYPE; *replyopts ++ = 1; *replyopts ++ = DHCPNAK; opts_len -= 3; if (found_leasetime) { dhcpreqparam_default[dhcpreqparams_default_len++] = BOOTPOPT_IP_ADDRESS_LEASE_TIME; dhcpreqparam_default_validflag = true; } if (!found_serverid) { dhcpreqparam_default[dhcpreqparams_default_len++] = BOOTPOPT_SERVER_IDENTIFIER; dhcpreqparam_default_validflag = true; } } break; default: BX_ERROR(("dhcp server: unsupported message type %u",dhcpmsgtype)); return 0; } while (1) { while (dhcpreqparams_len-- > 0) { switch (*dhcpreqparams++) { case BOOTPOPT_SUBNETMASK: BX_INFO(("provide BOOTPOPT_SUBNETMASK")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_SUBNETMASK; *replyopts ++ = 4; memcpy(replyopts,subnetmask_ipv4addr,4); replyopts += 4; break; case BOOTPOPT_ROUTER_OPTION: BX_INFO(("provide BOOTPOPT_ROUTER_OPTION")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_ROUTER_OPTION; *replyopts ++ = 4; memcpy(replyopts, dhcp->host_ipv4addr, 4); replyopts += 4; break; case BOOTPOPT_DOMAIN_NAMESERVER: if (dhcp->dns_ipv4addr[0] != 0) { BX_INFO(("provide BOOTPOPT_DOMAIN_NAMESERVER")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_DOMAIN_NAMESERVER; *replyopts ++ = 4; memcpy(replyopts, dhcp->dns_ipv4addr, 4); replyopts += 4; } break; case BOOTPOPT_BROADCAST_ADDRESS: BX_INFO(("provide BOOTPOPT_BROADCAST_ADDRESS")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_BROADCAST_ADDRESS; *replyopts ++ = 4; memcpy(replyopts, dhcp->host_ipv4addr, 3); replyopts += 3; *replyopts ++ = 0xff; break; case BOOTPOPT_IP_ADDRESS_LEASE_TIME: BX_INFO(("provide BOOTPOPT_IP_ADDRESS_LEASE_TIME")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_IP_ADDRESS_LEASE_TIME; *replyopts ++ = 4; if (leasetime < DEFAULT_LEASE_TIME) { put_net4(replyopts, leasetime); } else { put_net4(replyopts, DEFAULT_LEASE_TIME); } replyopts += 4; break; case BOOTPOPT_SERVER_IDENTIFIER: BX_INFO(("provide BOOTPOPT_SERVER_IDENTIFIER")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_SERVER_IDENTIFIER; *replyopts ++ = 4; memcpy(replyopts, dhcp->host_ipv4addr,4); replyopts += 4; break; case BOOTPOPT_RENEWAL_TIME: BX_INFO(("provide BOOTPOPT_RENEWAL_TIME")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_RENEWAL_TIME; *replyopts ++ = 4; put_net4(replyopts, 600); replyopts += 4; break; case BOOTPOPT_REBINDING_TIME: BX_INFO(("provide BOOTPOPT_REBINDING_TIME")); if (opts_len < 6) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 6; *replyopts ++ = BOOTPOPT_REBINDING_TIME; *replyopts ++ = 4; put_net4(replyopts, 1800); replyopts += 4; break; case BOOTPOPT_HOST_NAME: if (hostname != NULL) { BX_INFO(("provide BOOTPOPT_HOST_NAME")); if (opts_len < (hostname_len + 2)) { free(hostname); BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= (hostname_len + 2); *replyopts ++ = BOOTPOPT_HOST_NAME; *replyopts ++ = hostname_len; memcpy(replyopts, hostname, hostname_len); replyopts += hostname_len; free(hostname); hostname = NULL; break; } default: if (*(dhcpreqparams-1) != 0) { BX_ERROR(("dhcp server: requested parameter %u not supported yet",*(dhcpreqparams-1))); } break; } } if (!dhcpreqparam_default_validflag) break; dhcpreqparams = &dhcpreqparam_default[0]; dhcpreqparams_len = sizeof(dhcpreqparam_default); dhcpreqparam_default_validflag = false; } if (opts_len < 1) { BX_ERROR(("option buffer is insufficient")); return 0; } opts_len -= 2; *replyopts ++ = BOOTPOPT_END; opts_len = replyopts - &replybuf[0]; if (opts_len < (236U+64U)) { opts_len = (236U+64U); // BOOTP } if (opts_len < (548U)) { opts_len = 548U; // DHCP } memcpy(reply, replybuf, opts_len); return opts_len; } int tftp_send_error(Bit8u *buffer, unsigned code, const char *msg, tftp_data_t *tftp) { put_net2(buffer, TFTP_ERROR); put_net2(buffer + 2, code); strcpy((char*)buffer + 4, msg); tftp->tid = 0; return (strlen(msg) + 5); } int tftp_send_data(Bit8u *buffer, unsigned block_nr, tftp_data_t *tftp) { char path[BX_PATHNAME_LEN]; char msg[BX_PATHNAME_LEN]; int rd; if (strlen(tftp->filename) == 0) { return tftp_send_error(buffer, 1, "File not found", tftp); } if ((strlen(tftp->rootdir) + strlen(tftp->filename)) > BX_PATHNAME_LEN) { return tftp_send_error(buffer, 1, "Path name too long", tftp); } sprintf(path, "%s/%s", tftp->rootdir, tftp->filename); FILE *fp = fopen(path, "rb"); if (!fp) { sprintf(msg, "File not found: %s", tftp->filename); return tftp_send_error(buffer, 1, msg, tftp); } if (fseek(fp, (block_nr - 1) * TFTP_BUFFER_SIZE, SEEK_SET) < 0) { return tftp_send_error(buffer, 3, "Block not seekable", tftp); } rd = fread(buffer + 4, 1, TFTP_BUFFER_SIZE, fp); fclose(fp); if (rd < 0) { return tftp_send_error(buffer, 3, "Block not readable", tftp); } put_net2(buffer, TFTP_DATA); put_net2(buffer + 2, block_nr); if (rd < TFTP_BUFFER_SIZE) { tftp->tid = 0; } return (rd + 4); } int tftp_send_ack(Bit8u *buffer, unsigned block_nr) { put_net2(buffer, TFTP_ACK); put_net2(buffer + 2, block_nr); return 4; } int tftp_send_optack(Bit8u *buffer, size_t tsize_option, unsigned blksize_option) { Bit8u *p = buffer; put_net2(p, TFTP_OPTACK); p += 2; if (tsize_option > 0) { *p++='t'; *p++='s'; *p++='i'; *p++='z'; *p++='e'; *p++='\0'; sprintf((char *)p, "%lu", (unsigned long)tsize_option); p += strlen((const char *)p) + 1; } if (blksize_option > 0) { *p++='b'; *p++='l'; *p++='k'; *p++='s'; *p++='i'; *p++='z'; *p++='e'; *p++='\0'; sprintf((char *)p, "%d", blksize_option); p += strlen((const char *)p) + 1; } return (p - buffer); } // duplicate the part of tftp_send_data() that constructs the filename // but ignore errors since tftp_send_data() will respond for us static size_t get_file_size(bx_devmodel_c *netdev, const char *tpath, const char *tname) { struct stat stbuf; char path[BX_PATHNAME_LEN]; if (strlen(tname) == 0) return 0; if ((strlen(tpath) + strlen(tname)) > BX_PATHNAME_LEN) return 0; sprintf(path, "%s/%s", tpath, tname); if (stat(path, &stbuf) < 0) return 0; BX_INFO(("tftp filesize: %lu", (unsigned long)stbuf.st_size)); return (size_t)stbuf.st_size; } int process_tftp(bx_devmodel_c *netdev, const Bit8u *data, unsigned data_len, Bit16u req_tid, Bit8u *reply, tftp_data_t *tftp) { char path[BX_PATHNAME_LEN]; FILE *fp; unsigned block_nr; unsigned tftp_len; switch (get_net2(data)) { case TFTP_RRQ: if (tftp->tid == 0) { strncpy((char*)reply, (const char*)data + 2, data_len - 2); reply[data_len - 4] = 0; // options size_t tsize_option = 0; int blksize_option = 0; if (strlen((char*)reply) < data_len - 2) { const char *mode = (const char*)data + 2 + strlen((char*)reply) + 1; int octet_option = 0; while (mode < (const char*)data + data_len) { if (memcmp(mode, "octet\0", 6) == 0) { mode += 6; octet_option = 1; } else if (memcmp(mode, "tsize\0", 6) == 0) { mode += 6; tsize_option = 1; // size needed mode += strlen(mode)+1; } else if (memcmp(mode, "blksize\0", 8) == 0) { mode += 8; blksize_option = atoi(mode); mode += strlen(mode)+1; } else { BX_INFO(("tftp req: unknown option %s", mode)); break; } } if (!octet_option) { return tftp_send_error(reply, 4, "Unsupported transfer mode", tftp); } } strcpy(tftp->filename, (char*)reply); BX_INFO(("tftp req: %s", tftp->filename)); if (tsize_option) { tsize_option = get_file_size(netdev, tftp->rootdir, tftp->filename); if (tsize_option > 0) { // if tsize requested and file exists, send optack and return // optack ack will pick up where we leave off here. // if blksize_option is less than TFTP_BUFFER_SIZE should // probably use blksize_option... return tftp_send_optack(reply, tsize_option, TFTP_BUFFER_SIZE); } } if (blksize_option) { BX_INFO(("tftp req: blksize (val = %d) unused", blksize_option)); } tftp->tid = req_tid; tftp->write = 0; return tftp_send_data(reply, 1, tftp); } else { return tftp_send_error(reply, 4, "Illegal request", tftp); } break; case TFTP_WRQ: if (tftp->tid == 0) { strncpy((char*)reply, (const char*)data + 2, data_len - 2); reply[data_len - 4] = 0; // transfer mode if (strlen((char*)reply) < data_len - 2) { const char *mode = (const char*)data + 2 + strlen((char*)reply) + 1; if (memcmp(mode, "octet\0", 6) != 0) { return tftp_send_error(reply, 4, "Unsupported transfer mode", tftp); } } strcpy(tftp->filename, (char*)reply); sprintf(path, "%s/%s", tftp->rootdir, tftp->filename); fp = fopen(path, "rb"); if (fp) { fclose(fp); return tftp_send_error(reply, 6, "File exists", tftp); } fp = fopen(path, "wb"); if (!fp) { return tftp_send_error(reply, 2, "Access violation", tftp); } fclose(fp); tftp->tid = req_tid; tftp->write = 1; return tftp_send_ack(reply, 0); } else { return tftp_send_error(reply, 4, "Illegal request", tftp); } break; case TFTP_DATA: if ((tftp->tid == req_tid) && (tftp->write == 1)) { block_nr = get_net2(data + 2); strncpy((char*)reply, (const char*)data + 4, data_len - 4); tftp_len = data_len - 4; reply[tftp_len] = 0; if (tftp_len <= 512) { sprintf(path, "%s/%s", tftp->rootdir, tftp->filename); fp = fopen(path, "ab"); if (!fp) { return tftp_send_error(reply, 2, "Access violation", tftp); } if (fseek(fp, (block_nr - 1) * TFTP_BUFFER_SIZE, SEEK_SET) < 0) { return tftp_send_error(reply, 3, "Block not seekable", tftp); } fwrite(reply, 1, tftp_len, fp); fclose(fp); if (tftp_len < 512) { tftp->tid = 0; } return tftp_send_ack(reply, block_nr); } else { return tftp_send_error(reply, 4, "Illegal request", tftp); } } else { return tftp_send_error(reply, 4, "Illegal request", tftp); } break; case TFTP_ACK: return tftp_send_data(reply, get_net2(data + 2) + 1, tftp); case TFTP_ERROR: // silently ignore error packets break; default: BX_ERROR(("TFTP unknown opt %d", get_net2(data))); } return 0; } #endif /* if BX_NETWORKING */ bochs-2.6/iodev/network/eth_win32.cc0000644000175000017500000003116112020641503017240 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_win32.cc 10975 2012-01-14 17:03:00Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // eth_win32.cc - packet mover for win32 // All win32 coding by Don Becker // with patches from various sources // // Various networking docs: // http://www.graphcomp.com/info/rfc/ // rfc0826: arp // rfc0903: rarp // // For ethernet support under win32 to work, you must install WinPCap. // Download it from http://netgroup-serv.polito.it/winpcap // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING && BX_NETMOD_WIN32 // windows.h included by bochs.h #define LOG_THIS netdev-> #define BX_ETH_WIN32_LOGGING 0 #define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 #define Packet_ALIGNMENT sizeof(int) #define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) typedef int bpf_int32; typedef u_int bpf_u_int32; /* * The instruction encondings. */ /* instruction classes */ #define BPF_CLASS(code) ((code) & 0x07) #define BPF_LD 0x00 #define BPF_LDX 0x01 #define BPF_ST 0x02 #define BPF_STX 0x03 #define BPF_ALU 0x04 #define BPF_JMP 0x05 #define BPF_RET 0x06 #define BPF_MISC 0x07 /* ld/ldx fields */ #define BPF_SIZE(code) ((code) & 0x18) #define BPF_W 0x00 #define BPF_H 0x08 #define BPF_B 0x10 #define BPF_MODE(code) ((code) & 0xe0) #define BPF_IMM 0x00 #define BPF_ABS 0x20 #define BPF_IND 0x40 #define BPF_MEM 0x60 #define BPF_LEN 0x80 #define BPF_MSH 0xa0 /* alu/jmp fields */ #define BPF_OP(code) ((code) & 0xf0) #define BPF_ADD 0x00 #define BPF_SUB 0x10 #define BPF_MUL 0x20 #define BPF_DIV 0x30 #define BPF_OR 0x40 #define BPF_AND 0x50 #define BPF_LSH 0x60 #define BPF_RSH 0x70 #define BPF_NEG 0x80 #define BPF_JA 0x00 #define BPF_JEQ 0x10 #define BPF_JGT 0x20 #define BPF_JGE 0x30 #define BPF_JSET 0x40 #define BPF_SRC(code) ((code) & 0x08) #define BPF_K 0x00 #define BPF_X 0x08 /* ret - BPF_K and BPF_X also apply */ #define BPF_RVAL(code) ((code) & 0x18) #define BPF_A 0x10 /* misc */ #define BPF_MISCOP(code) ((code) & 0xf8) #define BPF_TAX 0x00 #define BPF_TXA 0x80 #define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } #define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } /* * The instruction data structure. */ struct bpf_insn { u_short code; u_char jt; u_char jf; bpf_int32 k; }; struct bpf_program { u_int bf_len; struct bpf_insn *bf_insns; }; struct bpf_hdr { struct timeval bh_tstamp; /* time stamp */ UINT bh_caplen; /* length of captured portion */ UINT bh_datalen; /* original length of packet */ USHORT bh_hdrlen; /* length of bpf header (this struct plus alignment padding) */ }; #define MAX_LINK_NAME_LENGTH 64 // Why don't these definitions come from including winpcap.h or something? // -Bryce typedef struct _ADAPTER { HANDLE hFile; TCHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; int NumWrites; HANDLE ReadEvent; UINT ReadTimeOut; // WARNING: maybe invalid before winpcap 2.2 } ADAPTER, *LPADAPTER; typedef struct _PACKET { HANDLE hEvent; OVERLAPPED OverLapped; PVOID Buffer; UINT Length; UINT ulBytesReceived; BOOLEAN bIoComplete; } PACKET, *LPPACKET; HINSTANCE hPacket; LPADAPTER lpAdapter = 0; LPPACKET pkSend; LPPACKET pkRecv; char buffer[256000]; DWORD dwVersion, dwMajorVersion; char AdapterList[10][1024]; char cMacAddr[6]; char NetDev[512]; BOOL IsNT = FALSE; LPADAPTER (*PacketOpenAdapter) (LPTSTR); VOID (*PacketCloseAdapter) (LPADAPTER); BOOLEAN (*PacketSetHwFilter) (LPADAPTER, ULONG); BOOLEAN (*PacketSetBpf) (LPADAPTER, struct bpf_program *); BOOLEAN (*PacketGetAdapterNames) (PTSTR, PULONG); BOOLEAN (*PacketSendPacket) (LPADAPTER, LPPACKET, BOOLEAN); BOOLEAN (*PacketReceivePacket) (LPADAPTER, LPPACKET, BOOLEAN); BOOLEAN (*PacketSetBuff) (LPADAPTER, int); BOOLEAN (*PacketSetReadTimeout) (LPADAPTER, int); LPPACKET (*PacketAllocatePacket) (void); VOID (*PacketInitPacket) (LPPACKET, PVOID, UINT); VOID (*PacketFreePacket) (LPPACKET); // template filter for a unicast mac address and all // multicast/broadcast frames static const struct bpf_insn macfilter[] = { BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2), BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0), BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0), BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1), BPF_STMT(BPF_RET, 1514), BPF_STMT(BPF_RET, 0), }; // // Define the class. This is private to this module // class bx_win32_pktmover_c : public eth_pktmover_c { public: bx_win32_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: struct bpf_insn filter[8]; int rx_timer_index; static void rx_timer_handler(void *); void rx_timer(void); #if BX_ETH_WIN32_LOGGING FILE *pktlog_txt; #endif }; // // Define the static class that registers the derived pktmover class, // and allocates one on request. // class bx_win32_locator_c : public eth_locator_c { public: bx_win32_locator_c(void) : eth_locator_c("win32") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_win32_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_win32_match; // // Define the methods for the bx_win32_pktmover derived class // // the constructor bx_win32_pktmover_c::bx_win32_pktmover_c( const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { this->netdev = dev; BX_INFO(("win32 network driver")); // Open Packet Driver Here. DWORD dwVersion; DWORD dwWindowsMajorVersion; this->rxh = rxh; this->rxstat = rxstat; hPacket = LoadLibrary("PACKET.DLL"); memcpy(cMacAddr, macaddr, 6); if (hPacket) { PacketOpenAdapter = (LPADAPTER (*)(LPTSTR)) GetProcAddress(hPacket, "PacketOpenAdapter"); PacketCloseAdapter = (VOID (*)(LPADAPTER)) GetProcAddress(hPacket, "PacketCloseAdapter"); PacketSetHwFilter = (BOOLEAN (*)(LPADAPTER, ULONG)) GetProcAddress(hPacket, "PacketSetHwFilter"); PacketSetBpf = (BOOLEAN (*)(LPADAPTER, struct bpf_program *)) GetProcAddress(hPacket, "PacketSetBpf"); PacketGetAdapterNames = (BOOLEAN (*)(PTSTR, PULONG)) GetProcAddress(hPacket, "PacketGetAdapterNames"); PacketSendPacket = (BOOLEAN (*)(LPADAPTER, LPPACKET, BOOLEAN)) GetProcAddress(hPacket, "PacketSendPacket"); PacketReceivePacket = (BOOLEAN (*)(LPADAPTER, LPPACKET, BOOLEAN)) GetProcAddress(hPacket, "PacketReceivePacket"); PacketSetBuff = (BOOLEAN (*)(LPADAPTER, int)) GetProcAddress(hPacket, "PacketSetBuff"); PacketSetReadTimeout = (BOOLEAN (*)(LPADAPTER, int)) GetProcAddress(hPacket, "PacketSetReadTimeout"); PacketAllocatePacket = (LPPACKET (*)(void)) GetProcAddress(hPacket, "PacketAllocatePacket"); PacketInitPacket = (VOID (*)(LPPACKET, PVOID, UINT)) GetProcAddress(hPacket, "PacketInitPacket"); PacketFreePacket = (VOID (*)(LPPACKET)) GetProcAddress(hPacket, "PacketFreePacket"); } else { BX_PANIC(("Could not load WPCap Drivers for ethernet support!")); } memset(&NetDev, 0, sizeof(NetDev)); dwVersion=GetVersion(); dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4)) { // Windows NT/2k int nLen = MultiByteToWideChar(CP_ACP, 0, netif, -1, NULL, 0); MultiByteToWideChar(CP_ACP, 0, netif, -1, (WCHAR *)NetDev, nLen); IsNT = TRUE; } else { // Win9x strcpy(NetDev, netif); } lpAdapter = PacketOpenAdapter(NetDev); if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) { BX_PANIC(("Could not open adapter for ethernet reception")); return; } PacketSetHwFilter(lpAdapter, NDIS_PACKET_TYPE_PROMISCUOUS); /* The code below sets a BPF mac address filter that seems to really kill performance, for now im just using code to filter, and it works better */ // memcpy(&this->filter, macfilter, sizeof(macfilter)); // this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 | (macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff); // this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff); // bp.bf_len = 8; // bp.bf_insns = &this->filter[0]; // if (!PacketSetBpf(lpAdapter, &bp)) { // BX_PANIC(("Could not set mac address BPF filter")); // } PacketSetBuff(lpAdapter, 512000); PacketSetReadTimeout(lpAdapter, -1); if ((pkSend = PacketAllocatePacket()) == NULL) { BX_PANIC(("Could not allocate a send packet")); } if ((pkRecv = PacketAllocatePacket()) == NULL) { BX_PANIC(("Could not allocate a recv packet")); } rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 10000, 1, 1, "eth_win32"); #if BX_ETH_WIN32_LOGGING pktlog_txt = fopen("ne2k-pktlog.txt", "wb"); if (!pktlog_txt) BX_PANIC(("ne2k-pktlog.txt failed")); fprintf(pktlog_txt, "win32 packetmover readable log file\n"); fprintf(pktlog_txt, "host adapter = %s\n", netif); fprintf(pktlog_txt, "guest MAC address = "); int i; for (i=0; i<6; i++) fprintf(pktlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "\n"); fprintf(pktlog_txt, "--\n"); fflush(pktlog_txt); #endif } void bx_win32_pktmover_c::sendpkt(void *buf, unsigned io_len) { #if BX_ETH_WIN32_LOGGING write_pktlog_txt(pktlog_txt, (const Bit8u *)buf, io_len, 0); #endif // SendPacket Here. PacketInitPacket(pkSend, (char *)buf, io_len); if (!PacketSendPacket(lpAdapter, pkSend, TRUE)) { fprintf(stderr, "[ETH-WIN32] Error sending packet: %lu\n", GetLastError()); } } void bx_win32_pktmover_c::rx_timer_handler (void *this_ptr) { bx_win32_pktmover_c *class_ptr = (bx_win32_pktmover_c *) this_ptr; class_ptr->rx_timer(); } void bx_win32_pktmover_c::rx_timer(void) { // Recieve Packet ???? char *pBuf; unsigned char *pPacket; unsigned int iOffset = 0; struct bpf_hdr *hdr; int pktlen; PacketInitPacket(pkRecv, (char *)buffer, 256000); if (WaitForSingleObject(lpAdapter->ReadEvent,0) == WAIT_OBJECT_0 || IsNT) { PacketReceivePacket(lpAdapter, pkRecv, TRUE); pBuf = (char *)pkRecv->Buffer; iOffset = 0; while(iOffset < pkRecv->ulBytesReceived) { hdr = (struct bpf_hdr *)(pBuf + iOffset); pPacket = (unsigned char *)(pBuf + iOffset + hdr->bh_hdrlen); if (memcmp(pPacket + 6, cMacAddr, 6) != 0) // src field != ours { if(memcmp(pPacket, cMacAddr, 6) == 0 || memcmp(pPacket, broadcast_macaddr, 6) == 0) { pktlen = hdr->bh_caplen; if (pktlen < 60) pktlen = 60; #if BX_ETH_WIN32_LOGGING write_pktlog_txt(pktlog_txt, pPacket, pktlen, 1); #endif if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, pPacket, pktlen); } else { BX_ERROR(("device not ready to receive data")); } } } iOffset = Packet_WORDALIGN(iOffset + (hdr->bh_hdrlen + hdr->bh_caplen)); } } } #endif /* if BX_NETWORKING && BX_NETMOD_WIN32 */ bochs-2.6/iodev/network/eth_vde.cc0000644000175000017500000002377312020641503017066 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_vde.cc 10975 2012-01-14 17:03:00Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2003 Renzo Davoli // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // eth_vde.cc - Virtual Distributed Ethernet interface by Renzo Davoli // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING && BX_NETMOD_VDE #define LOG_THIS netdev-> #include #include #include #include #include #include #include #if defined(__linux__) #include #include #include #elif BX_HAVE_NET_IF_H #include #endif #include #include #include #include #include #include #include #include #define SWITCH_MAGIC 0xfeedface #define BX_ETH_VDE_LOGGING 0 int vde_alloc(char *dev,int *fdp,struct sockaddr_un *pdataout); // // Define the class. This is private to this module // class bx_vde_pktmover_c : public eth_pktmover_c { public: bx_vde_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: int fd; int rx_timer_index; static void rx_timer_handler(void *); void rx_timer(); FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt; int fddata; struct sockaddr_un dataout; }; // // Define the static class that registers the derived pktmover class, // and allocates one on request. // class bx_vde_locator_c : public eth_locator_c { public: bx_vde_locator_c(void) : eth_locator_c("vde") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_vde_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_vde_match; // // Define the methods for the bx_vde_pktmover derived class // // the constructor bx_vde_pktmover_c::bx_vde_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { int flags; this->netdev = dev; //if (strncmp (netif, "vde", 3) != 0) { // BX_PANIC (("eth_vde: interface name (%s) must be vde", netif)); //} char intname[IFNAMSIZ]; if (netif == NULL || strcmp(netif,"") == 0) strcpy(intname,"/tmp/vde.ctl"); else strcpy(intname,netif); fd=vde_alloc(intname,&fddata,&dataout); if (fd < 0) { BX_PANIC(("open failed on %s: %s", netif, strerror (errno))); return; } /* set O_ASYNC flag so that we can poll with read() */ if ((flags = fcntl(fd, F_GETFL)) < 0) { BX_PANIC(("getflags on vde device: %s", strerror (errno))); } flags |= O_NONBLOCK; if (fcntl(fd, F_SETFL, flags) < 0) { BX_PANIC(("set vde device flags: %s", strerror (errno))); } BX_INFO(("eth_vde: opened %s device", netif)); /* Execute the configuration script */ if((script != NULL) && (strcmp(script, "") != 0) && (strcmp(script, "none") != 0)) { if (execute_script(this->netdev, script, intname) < 0) BX_ERROR(("execute script '%s' on %s failed", script, intname)); } // Start the rx poll this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, 1, 1, "eth_vde"); // continuous, active this->rxh = rxh; this->rxstat = rxstat; #if BX_ETH_VDE_LOGGING // eventually Bryce wants txlog to dump in pcap format so that // tcpdump -r FILE can read it and interpret packets. txlog = fopen("ne2k-tx.log", "wb"); if (!txlog) BX_PANIC(("open ne2k-tx.log failed")); txlog_txt = fopen("ne2k-txdump.txt", "wb"); if (!txlog_txt) BX_PANIC(("open ne2k-txdump.txt failed")); fprintf(txlog_txt, "vde packetmover readable log file\n"); fprintf(txlog_txt, "net IF = %s\n", netif); fprintf(txlog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(txlog_txt, "\n--\n"); fflush(txlog_txt); rxlog = fopen("ne2k-rx.log", "wb"); if (!rxlog) BX_PANIC(("open ne2k-rx.log failed")); rxlog_txt = fopen("ne2k-rxdump.txt", "wb"); if (!rxlog_txt) BX_PANIC(("open ne2k-rxdump.txt failed")); fprintf(rxlog_txt, "vde packetmover readable log file\n"); fprintf(rxlog_txt, "net IF = %s\n", netif); fprintf(rxlog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(rxlog_txt, "\n--\n"); fflush(rxlog_txt); #endif } void bx_vde_pktmover_c::sendpkt(void *buf, unsigned io_len) { unsigned int size; //size = write (fd, buf, io_len); //size=send(fd,buf,io_len,0); size=sendto(fddata,buf,io_len,0,(struct sockaddr *) &dataout, sizeof(struct sockaddr_un)); if (size != io_len) { BX_PANIC(("write on vde device: %s", strerror (errno))); } else { BX_INFO(("wrote %d bytes on vde", io_len)); } #if BX_ETH_VDE_LOGGING BX_DEBUG(("sendpkt length %u", io_len)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. int n = fwrite(buf, io_len, 1, txlog); if (n != 1) BX_ERROR(("fwrite to txlog failed")); // dump packet in hex into an ascii log file write_pktlog_txt(txlog_txt, (const Bit8u *)buf, io_len, 0); // flush log so that we see the packets as they arrive w/o buffering fflush(txlog); #endif } void bx_vde_pktmover_c::rx_timer_handler(void *this_ptr) { bx_vde_pktmover_c *class_ptr = (bx_vde_pktmover_c *) this_ptr; class_ptr->rx_timer(); } void bx_vde_pktmover_c::rx_timer() { int nbytes; Bit8u buf[BX_PACKET_BUFSIZE]; Bit8u *rxbuf; struct sockaddr_un datain; socklen_t datainsize; if (fd<0) return; //nbytes = read (fd, buf, sizeof(buf)); nbytes=recvfrom(fddata,buf,sizeof(buf),MSG_DONTWAIT|MSG_WAITALL,(struct sockaddr *) &datain, &datainsize); rxbuf=buf; if (nbytes>0) BX_INFO(("vde read returned %d bytes", nbytes)); if (nbytes<0) { if (errno != EAGAIN) BX_ERROR(("vde read error: %s", strerror(errno))); return; } #if BX_ETH_VDE_LOGGING if (nbytes > 0) { BX_DEBUG(("receive packet length %u", nbytes)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. int n = fwrite(rxbuf, nbytes, 1, rxlog); if (n != 1) BX_ERROR(("fwrite to rxlog failed")); // dump packet in hex into an ascii log file write_pktlog_txt(rxlog_txt, rxbuf, nbytes, 1); // flush log so that we see the packets as they arrive w/o buffering fflush(rxlog); } #endif BX_DEBUG(("eth_vde: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11])); if (nbytes < 60) { BX_INFO(("packet too short (%d), padding to 60", nbytes)); nbytes = 60; } if (this->rxstat(this->netdev) & BX_NETDEV_RXREADY) { this->rxh(this->netdev, rxbuf, nbytes); } else { BX_ERROR(("device not ready to receive data")); } } //enum request_type { REQ_NEW_CONTROL }; #define REQ_NEW_CONTROL 0 struct request_v3 { Bit32u magic; Bit32u version; //enum request_type type; int type; struct sockaddr_un sock; }; static int send_fd(char *name, int fddata, struct sockaddr_un *datasock, int group) { int pid = getpid(); struct request_v3 req; int fdctl; struct sockaddr_un sock; if((fdctl = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { perror("socket"); return(-1); } sock.sun_family = AF_UNIX; snprintf(sock.sun_path, sizeof(sock.sun_path), "%s", name); if(connect(fdctl, (struct sockaddr *) &sock, sizeof(sock))) { perror("connect"); return(-1); } req.magic=SWITCH_MAGIC; req.version=3; req.type=((int)REQ_NEW_CONTROL)+((group > 0)?((geteuid()<<8) + group) << 8:0); req.sock.sun_family=AF_UNIX; memset(req.sock.sun_path, 0, sizeof(req.sock.sun_path)); sprintf(&req.sock.sun_path[1], "%5d", pid); if(bind(fddata, (struct sockaddr *) &req.sock, sizeof(req.sock)) < 0) { perror("bind"); return(-1); } if (send(fdctl,&req,sizeof(req),0) < 0) { perror("send"); return(-1); } if (recv(fdctl,datasock,sizeof(struct sockaddr_un),0) < 0) { perror("recv"); return(-1); } return fdctl; } int vde_alloc(char *dev, int *fdp, struct sockaddr_un *pdataout) { //struct ifreq ifr; //int err; int fd, fddata; if ((fddata = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) return -1; if ((fd = send_fd(dev, fddata, pdataout, 0)) < 0) return -1; //memset(&ifr, 0, sizeof(ifr)); *fdp=fddata; return fd; } #endif /* if BX_NETWORKING && BX_NETMOD_VDE */ bochs-2.6/iodev/network/eth_null.cc0000644000175000017500000001245312020641503017253 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: eth_null.cc 10975 2012-01-14 17:03:00Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // eth_null.cc - skeleton code for an ethernet pktmover // Various networking docs: // http://www.graphcomp.com/info/rfc/ // rfc0826: arp // rfc0903: rarp // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "netmod.h" #if BX_NETWORKING #define LOG_THIS netdev-> #define BX_ETH_NULL_LOGGING 1 // // Define the class. This is private to this module // class bx_null_pktmover_c : public eth_pktmover_c { public: bx_null_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script); void sendpkt(void *buf, unsigned io_len); private: int rx_timer_index; static void rx_timer_handler(void *); FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt; }; // // Define the static class that registers the derived pktmover class, // and allocates one on request. // class bx_null_locator_c : public eth_locator_c { public: bx_null_locator_c(void) : eth_locator_c("null") {} protected: eth_pktmover_c *allocate(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { return (new bx_null_pktmover_c(netif, macaddr, rxh, rxstat, dev, script)); } } bx_null_match; // // Define the methods for the bx_null_pktmover derived class // // the constructor bx_null_pktmover_c::bx_null_pktmover_c(const char *netif, const char *macaddr, eth_rx_handler_t rxh, eth_rx_status_t rxstat, bx_devmodel_c *dev, const char *script) { this->netdev = dev; BX_INFO(("null network driver")); #if BX_ETH_NULL_LOGGING // Start the rx poll this->rx_timer_index = bx_pc_system.register_timer(this, this->rx_timer_handler, 1000, 1, 1, "eth_null"); // continuous, active this->rxh = rxh; this->rxstat = rxstat; // eventually Bryce wants txlog to dump in pcap format so that // tcpdump -r FILE can read it and interpret packets. txlog = fopen("ne2k-tx.log", "wb"); if (!txlog) BX_PANIC(("open ne2k-tx.log failed")); txlog_txt = fopen("ne2k-txdump.txt", "wb"); if (!txlog_txt) BX_PANIC(("open ne2k-txdump.txt failed")); fprintf(txlog_txt, "null packetmover readable log file\n"); fprintf(txlog_txt, "net IF = %s\n", netif); fprintf(txlog_txt, "MAC address = "); for (int i=0; i<6; i++) fprintf(txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : ""); fprintf(txlog_txt, "\n--\n"); fflush(txlog_txt); #endif } void bx_null_pktmover_c::sendpkt(void *buf, unsigned io_len) { #if BX_ETH_NULL_LOGGING BX_DEBUG (("sendpkt length %u", io_len)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. size_t n = fwrite (buf, io_len, 1, txlog); if (n != 1) BX_ERROR(("fwrite to txlog failed, io_len = %u", io_len)); // dump packet in hex into an ascii log file write_pktlog_txt(txlog_txt, (const Bit8u *)buf, io_len, 0); // flush log so that we see the packets as they arrive w/o buffering fflush(txlog); #endif } void bx_null_pktmover_c::rx_timer_handler (void *this_ptr) { #if BX_ETH_NULL_LOGGING /// hey wait there is no receive data with a NULL ethernet, is there.... int io_len = 0; Bit8u buf[1]; bx_null_pktmover_c *class_ptr = (bx_null_pktmover_c *) this_ptr; bx_devmodel_c *netdev = class_ptr->netdev; if (io_len > 0) { BX_DEBUG(("receive packet length %u", io_len)); // dump raw bytes to a file, eventually dump in pcap format so that // tcpdump -r FILE can interpret them for us. size_t n = fwrite (buf, io_len, 1, class_ptr->rxlog); if (n != 1) BX_ERROR(("fwrite to rxlog failed, io_len = %u", io_len)); // dump packet in hex into an ascii log file write_pktlog_txt(class_ptr->rxlog_txt, buf, io_len, 1); // flush log so that we see the packets as they arrive w/o buffering fflush(class_ptr->rxlog); } #endif } #endif /* if BX_NETWORKING */ bochs-2.6/iodev/network/e1000.cc0000644000175000017500000015767712020641503016210 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: e1000.cc 11382 2012-08-30 20:41:25Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Intel(R) 82540EM Gigabit Ethernet support (ported from QEMU) // Software developer's manual: // http://download.intel.com/design/network/manuals/8254x_GBe_SDM.pdf // // Nir Peleg, Tutis Systems Ltd. for Qumranet Inc. // Copyright (c) 2008 Qumranet // Based on work done by: // Copyright (c) 2007 Dan Aloni // Copyright (c) 2004 Antony T Curtis // // Copyright (C) 2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_E1000 #include "pci.h" #include "netmod.h" #include "e1000.h" #define LOG_THIS theE1000Device-> bx_e1000_c* theE1000Device = NULL; const Bit8u e1000_iomask[64] = {7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7}; #define E1000_CTRL 0x00000 // Device Control - RW #define E1000_STATUS 0x00008 // Device Status - RO #define E1000_EECD 0x00010 // EEPROM/Flash Control - RW #define E1000_EERD 0x00014 // EEPROM Read - RW #define E1000_MDIC 0x00020 // MDI Control - RW #define E1000_VET 0x00038 // VLAN Ether Type - RW #define E1000_ICR 0x000C0 // Interrupt Cause Read - R/clr #define E1000_ICS 0x000C8 // Interrupt Cause Set - WO #define E1000_IMS 0x000D0 // Interrupt Mask Set - RW #define E1000_IMC 0x000D8 // Interrupt Mask Clear - WO #define E1000_RCTL 0x00100 // RX Control - RW #define E1000_TCTL 0x00400 // TX Control - RW #define E1000_LEDCTL 0x00E00 // LED Control - RW #define E1000_PBA 0x01000 // Packet Buffer Allocation - RW #define E1000_RDBAL 0x02800 // RX Descriptor Base Address Low - RW #define E1000_RDBAH 0x02804 // RX Descriptor Base Address High - RW #define E1000_RDLEN 0x02808 // RX Descriptor Length - RW #define E1000_RDH 0x02810 // RX Descriptor Head - RW #define E1000_RDT 0x02818 // RX Descriptor Tail - RW #define E1000_TDBAL 0x03800 // TX Descriptor Base Address Low - RW #define E1000_TDBAH 0x03804 // TX Descriptor Base Address High - RW #define E1000_TDLEN 0x03808 // TX Descriptor Length - RW #define E1000_TDH 0x03810 // TX Descriptor Head - RW #define E1000_TDT 0x03818 // TX Descripotr Tail - RW #define E1000_TXDCTL 0x03828 // TX Descriptor Control - RW #define E1000_CRCERRS 0x04000 // CRC Error Count - R/clr #define E1000_MPC 0x04010 // Missed Packet Count - R/clr #define E1000_GPRC 0x04074 // Good Packets RX Count - R/clr #define E1000_GPTC 0x04080 // Good Packets TX Count - R/clr #define E1000_TORL 0x040C0 // Total Octets RX Low - R/clr #define E1000_TORH 0x040C4 // Total Octets RX High - R/clr #define E1000_TOTL 0x040C8 // Total Octets TX Low - R/clr #define E1000_TOTH 0x040CC // Total Octets TX High - R/clr #define E1000_TPR 0x040D0 // Total Packets RX - R/clr #define E1000_TPT 0x040D4 // Total Packets TX - R/clr #define E1000_MTA 0x05200 // Multicast Table Array - RW Array #define E1000_RA 0x05400 // Receive Address - RW Array #define E1000_VFTA 0x05600 // VLAN Filter Table Array - RW Array #define E1000_WUFC 0x05808 // Wakeup Filter Control - RW #define E1000_MANC 0x05820 // Management Control - RW #define E1000_SWSM 0x05B50 // SW Semaphore #define PHY_CTRL 0x00 // Control Register #define PHY_STATUS 0x01 // Status Regiser #define PHY_ID1 0x02 // Phy Id Reg (word 1) #define PHY_ID2 0x03 // Phy Id Reg (word 2) #define PHY_AUTONEG_ADV 0x04 // Autoneg Advertisement #define PHY_LP_ABILITY 0x05 // Link Partner Ability (Base Page) #define PHY_1000T_CTRL 0x09 // 1000Base-T Control Reg #define PHY_1000T_STATUS 0x0A // 1000Base-T Status Reg #define M88E1000_PHY_SPEC_CTRL 0x10 // PHY Specific Control Register #define M88E1000_PHY_SPEC_STATUS 0x11 // PHY Specific Status Register #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 // Extended PHY Specific Control #define E1000_ICR_TXDW 0x00000001 // Transmit desc written back #define E1000_ICR_TXQE 0x00000002 // Transmit Queue empty #define E1000_ICR_RXDMT0 0x00000010 // rx desc min. threshold (0) #define E1000_ICR_RXO 0x00000040 // rx overrun #define E1000_ICR_RXT0 0x00000080 // rx timer intr (ring 0) #define E1000_ICR_MDAC 0x00000200 // MDIO access complete #define E1000_ICR_INT_ASSERTED 0x80000000 // If this bit asserted, the driver should claim the interrupt #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 // rx desc min. threshold #define E1000_ICS_RXO E1000_ICR_RXO // rx overrun #define E1000_ICS_RXT0 E1000_ICR_RXT0 // rx timer intr #define E1000_ICS_TXQE E1000_ICR_TXQE // Transmit Queue empty #define E1000_RCTL_EN 0x00000002 // enable #define E1000_RCTL_UPE 0x00000008 // unicast promiscuous enable #define E1000_RCTL_MPE 0x00000010 // multicast promiscuous enab #define E1000_RCTL_RDMTS_QUAT 0x00000100 // rx desc min threshold size #define E1000_RCTL_MO_SHIFT 12 // multicast offset shift #define E1000_RCTL_BAM 0x00008000 // broadcast enable // these buffer sizes are valid if E1000_RCTL_BSEX is 0 #define E1000_RCTL_SZ_2048 0x00000000 // rx buffer size 2048 #define E1000_RCTL_SZ_1024 0x00010000 // rx buffer size 1024 #define E1000_RCTL_SZ_512 0x00020000 // rx buffer size 512 #define E1000_RCTL_SZ_256 0x00030000 // rx buffer size 256 // these buffer sizes are valid if E1000_RCTL_BSEX is 1 #define E1000_RCTL_SZ_16384 0x00010000 // rx buffer size 16384 #define E1000_RCTL_SZ_8192 0x00020000 // rx buffer size 8192 #define E1000_RCTL_SZ_4096 0x00030000 // rx buffer size 4096 #define E1000_RCTL_VFE 0x00040000 // vlan filter enable #define E1000_RCTL_BSEX 0x02000000 // Buffer size extension #define E1000_RCTL_SECRC 0x04000000 // Strip Ethernet CRC #define E1000_EEPROM_RW_REG_DATA 16 // Offset to data in EEPROM read/write registers #define E1000_EEPROM_RW_REG_DONE 0x10 // Offset to READ/WRITE done bit #define E1000_EEPROM_RW_REG_START 1 // First bit for telling part to start operation #define E1000_EEPROM_RW_ADDR_SHIFT 8 // Shift to the address bits #define E1000_CTRL_SLU 0x00000040 // Set link up (Force Link) #define E1000_CTRL_SPD_1000 0x00000200 // Force 1Gb #define E1000_CTRL_SWDPIN0 0x00040000 // SWDPIN 0 value #define E1000_CTRL_SWDPIN2 0x00100000 // SWDPIN 2 value #define E1000_CTRL_RST 0x04000000 // Global reset #define E1000_CTRL_VME 0x40000000 // IEEE VLAN mode enable #define E1000_STATUS_FD 0x00000001 // Full duplex.0=half,1=full #define E1000_STATUS_LU 0x00000002 // Link up.0=no,1=link #define E1000_STATUS_SPEED_1000 0x00000080 // Speed 1000Mb/s #define E1000_STATUS_ASDV 0x00000300 // Auto speed detect value #define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 // Status of Master requests #define E1000_STATUS_MTXCKOK 0x00000400 // MTX clock running OK #define E1000_EECD_SK 0x00000001 // EEPROM Clock #define E1000_EECD_CS 0x00000002 // EEPROM Chip Select #define E1000_EECD_DI 0x00000004 // EEPROM Data In #define E1000_EECD_DO 0x00000008 // EEPROM Data Out #define E1000_EECD_FWE_MASK 0x00000030 #define E1000_EECD_REQ 0x00000040 // EEPROM Access Request #define E1000_EECD_GNT 0x00000080 // EEPROM Access Grant #define E1000_EECD_PRES 0x00000100 // EEPROM Present #define E1000_MDIC_DATA_MASK 0x0000FFFF #define E1000_MDIC_REG_MASK 0x001F0000 #define E1000_MDIC_REG_SHIFT 16 #define E1000_MDIC_PHY_MASK 0x03E00000 #define E1000_MDIC_PHY_SHIFT 21 #define E1000_MDIC_OP_WRITE 0x04000000 #define E1000_MDIC_OP_READ 0x08000000 #define E1000_MDIC_READY 0x10000000 #define E1000_MDIC_INT_EN 0x20000000 #define E1000_MDIC_ERROR 0x40000000 #define EEPROM_READ_OPCODE_MICROWIRE 0x6 // EEPROM read opcode #define E1000_TXD_DTYP_D 0x00100000 // Data Descriptor #define E1000_TXD_POPTS_IXSM 0x01 // Insert IP checksum #define E1000_TXD_POPTS_TXSM 0x02 // Insert TCP/UDP checksum #define E1000_TXD_CMD_RS 0x08000000 // Report Status #define E1000_TXD_CMD_RPS 0x10000000 // Report Packet Sent #define E1000_TXD_CMD_VLE 0x40000000 // Add VLAN tag #define E1000_TXD_CMD_DEXT 0x20000000 // Descriptor extension (0 = legacy) #define E1000_TXD_STAT_DD 0x00000001 // Descriptor Done #define E1000_TXD_STAT_EC 0x00000002 // Excess Collisions #define E1000_TXD_STAT_LC 0x00000004 // Late Collisions #define E1000_TXD_STAT_TU 0x00000008 // Transmit underrun #define E1000_TXD_CMD_EOP 0x01000000 // End of Packet #define E1000_TXD_CMD_TCP 0x01000000 // TCP packet #define E1000_TXD_CMD_IP 0x02000000 // IP packet #define E1000_TXD_CMD_TSE 0x04000000 // TCP Seg enable #define E1000_TCTL_EN 0x00000002 // enable tx struct e1000_rx_desc { Bit64u buffer_addr; // Address of the descriptor's data buffer Bit16u length; // Length of data DMAed into data buffer Bit16u csum; // Packet checksum Bit8u status; // Descriptor status Bit8u errors; // Descriptor Errors Bit16u special; }; #define E1000_RXD_STAT_DD 0x01 // Descriptor Done #define E1000_RXD_STAT_EOP 0x02 // End of Packet #define E1000_RXD_STAT_IXSM 0x04 // Ignore checksum #define E1000_RXD_STAT_VP 0x08 // IEEE VLAN Packet #define E1000_RAH_AV 0x80000000 // Receive descriptor valid struct e1000_context_desc { union { Bit32u ip_config; struct { Bit8u ipcss; // IP checksum start */ Bit8u ipcso; // IP checksum offset */ Bit16u ipcse; // IP checksum end */ } ip_fields; } lower_setup; union { Bit32u tcp_config; struct { Bit8u tucss; // TCP checksum start */ Bit8u tucso; // TCP checksum offset */ Bit16u tucse; // TCP checksum end */ } tcp_fields; } upper_setup; Bit32u cmd_and_length; union { Bit32u data; struct { Bit8u status; // Descriptor status */ Bit8u hdr_len; // Header length */ Bit16u mss; // Maximum segment size */ } fields; } tcp_seg_setup; }; #define E1000_MANC_RMCP_EN 0x00000100 // Enable RCMP 026Fh Filtering #define E1000_MANC_0298_EN 0x00000200 // Enable RCMP 0298h Filtering #define E1000_MANC_ARP_EN 0x00002000 // Enable ARP Request Filtering #define E1000_MANC_RCV_TCO_EN 0x00020000 // Receive TCO Packets Enabled #define E1000_MANC_EN_MNG2HOST 0x00200000 // Enable MNG packets to host memory #define EEPROM_CHECKSUM_REG 0x3f #define EEPROM_SUM 0xbaba #define MIN_BUF_SIZE 60 #define defreg(x) x = (E1000_##x>>2) enum { defreg(CTRL), defreg(EECD), defreg(EERD), defreg(GPRC), defreg(GPTC), defreg(ICR), defreg(ICS), defreg(IMC), defreg(IMS), defreg(LEDCTL),defreg(MANC), defreg(MDIC), defreg(MPC), defreg(PBA), defreg(RCTL), defreg(RDBAH), defreg(RDBAL), defreg(RDH), defreg(RDLEN), defreg(RDT), defreg(STATUS),defreg(SWSM), defreg(TCTL), defreg(TDBAH), defreg(TDBAL), defreg(TDH), defreg(TDLEN), defreg(TDT), defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL), defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC), defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA), defreg(VET), }; enum { PHY_R = 1, PHY_W = 2, PHY_RW = PHY_R | PHY_W }; static const char phy_regcap[0x20] = { PHY_RW, PHY_R, PHY_R, PHY_R, PHY_RW, PHY_R, 0, 0, 0, PHY_RW, PHY_R, 0, 0, 0, 0, 0, PHY_RW, PHY_R, 0, 0, PHY_RW, PHY_R, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const Bit16u e1000_eeprom_template[64] = { 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0x0000, 0x0000, 0x0000, 0x3000, 0x1000, 0x6403, 0x100e, 0x8086, 0x100e, 0x8086, 0x3040, 0x0008, 0x2000, 0x7e14, 0x0048, 0x1000, 0x00d8, 0x0000, 0x2700, 0x6cc9, 0x3150, 0x0722, 0x040b, 0x0984, 0x0000, 0xc000, 0x0706, 0x1008, 0x0000, 0x0f04, 0x7fff, 0x4d01, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0100, 0x4000, 0x121c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x0000, }; // builtin configuration handling functions void e1000_init_options(void) { bx_param_c *network = SIM->get_param("network"); bx_list_c *menu = new bx_list_c(network, "e1000", "Intel(R) Gigabit Ethernet"); menu->set_options(menu->SHOW_PARENT); bx_param_bool_c *enabled = new bx_param_bool_c(menu, "enabled", "Enable Intel(R) Gigabit Ethernet emulation", "Enables the Intel(R) Gigabit Ethernet emulation", 0); SIM->init_std_nic_options("Intel(R) Gigabit Ethernet", menu); enabled->set_dependent_list(menu->clone()); } Bit32s e1000_options_parser(const char *context, int num_params, char *params[]) { int ret, valid = 0; if (!strcmp(params[0], "e1000")) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_E1000); if (!SIM->get_param_bool("enabled", base)->get()) { SIM->get_param_enum("ethmod", base)->set_by_name("null"); } for (int i = 1; i < num_params; i++) { ret = SIM->parse_nic_params(context, params[i], base); if (ret > 0) { valid |= ret; } } if (!SIM->get_param_bool("enabled", base)->get()) { if (valid == 0x04) { SIM->get_param_bool("enabled", base)->set(1); } else if (valid < 0x80) { BX_PANIC(("%s: 'e1000' directive incomplete (mac is required)", context)); } } else { if (valid & 0x80) { SIM->get_param_bool("enabled", base)->set(0); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s e1000_options_save(FILE *fp) { SIM->write_pci_nic_options(fp, (bx_list_c*) SIM->get_param(BXPN_E1000)); return 0; } // device plugin entry points int libe1000_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theE1000Device = new bx_e1000_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theE1000Device, BX_PLUGIN_E1000); // add new configuration parameter for the config interface e1000_init_options(); // register add-on option for bochsrc and command line SIM->register_addon_option("e1000", e1000_options_parser, e1000_options_save); return 0; // Success } void libe1000_LTX_plugin_fini(void) { SIM->unregister_addon_option("e1000"); bx_list_c *menu = (bx_list_c*)SIM->get_param("network"); menu->remove("e1000"); delete theE1000Device; } // temporary helper functions // we should use host from/to little endian conversion directly Bit16u cpu_to_le16(Bit16u value) { Bit16u hvalue; WriteHostWordToLittleEndian(&hvalue, value); return hvalue; } Bit32u cpu_to_le32(Bit32u value) { Bit32u hvalue; WriteHostDWordToLittleEndian(&hvalue, value); return hvalue; } Bit64u cpu_to_le64(Bit64u value) { Bit64u hvalue; WriteHostQWordToLittleEndian(&hvalue, value); return hvalue; } #define le16_to_cpu cpu_to_le16 #define le32_to_cpu cpu_to_le32 #define le64_to_cpu cpu_to_le64 Bit32u net_checksum_add(Bit8u *buf, unsigned buf_len) { Bit32u sum = 0; unsigned i; for (i = 0; i < buf_len; i++) { if (i & 1) sum += (Bit32u)buf[i]; else sum += (Bit32u)buf[i] << 8; } return sum; } Bit16u net_checksum_finish(Bit32u sum) { while (sum >> 16) sum = (sum & 0xFFFF) + (sum >> 16); return ~sum; } // the device object bx_e1000_c::bx_e1000_c() { put("E1000"); memset(&s, 0, sizeof(bx_e1000_t)); s.tx_timer_index = BX_NULL_TIMER_HANDLE; ethdev = NULL; } bx_e1000_c::~bx_e1000_c() { if (s.mac_reg != NULL) { delete [] s.mac_reg; } if (s.tx.vlan != NULL) { delete [] s.tx.vlan; } if (ethdev != NULL) { delete ethdev; } SIM->get_bochs_root()->remove("e1000"); BX_DEBUG(("Exit")); } void bx_e1000_c::init(void) { Bit8u macaddr[6]; int i; Bit16u checksum = 0; const char *bootrom; // Read in values from config interface bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_E1000); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", base)->get()) { BX_INFO(("E1000 disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("e1000"))->set(0); return; } memcpy(macaddr, SIM->get_param_string("macaddr", base)->getptr(), 6); memcpy(BX_E1000_THIS s.eeprom_data, e1000_eeprom_template, sizeof(e1000_eeprom_template)); for (i = 0; i < 3; i++) BX_E1000_THIS s.eeprom_data[i] = (macaddr[2*i+1]<<8) | macaddr[2*i]; for (i = 0; i < EEPROM_CHECKSUM_REG; i++) checksum += BX_E1000_THIS s.eeprom_data[i]; checksum = (Bit16u) EEPROM_SUM - checksum; BX_E1000_THIS s.eeprom_data[EEPROM_CHECKSUM_REG] = checksum; BX_E1000_THIS s.mac_reg = new Bit32u[0x8000]; BX_E1000_THIS s.tx.vlan = new Bit8u[0x10004]; BX_E1000_THIS s.tx.data = BX_E1000_THIS s.tx.vlan + 4; BX_E1000_THIS s.devfunc = 0x00; DEV_register_pci_handlers(this, &BX_E1000_THIS s.devfunc, BX_PLUGIN_E1000, "Experimental Intel(R) Gigabit Ethernet"); for (unsigned i=0; i<256; i++) { BX_E1000_THIS pci_conf[i] = 0x0; } BX_E1000_THIS pci_base_address[0] = 0; BX_E1000_THIS pci_base_address[1] = 0; BX_E1000_THIS pci_rom_address = 0; bootrom = SIM->get_param_string("bootrom", base)->getptr(); if (strlen(bootrom) > 0) { BX_E1000_THIS load_pci_rom(bootrom); } if (BX_E1000_THIS s.tx_timer_index == BX_NULL_TIMER_HANDLE) { BX_E1000_THIS s.tx_timer_index = bx_pc_system.register_timer(this, tx_timer_handler, 0, 0, 0, "e1000"); // one-shot, inactive } BX_E1000_THIS s.statusbar_id = bx_gui->register_statusitem("E1000", 1); // Attach to the selected ethernet module BX_E1000_THIS ethdev = DEV_net_init_module(base, rx_handler, rx_status_handler, this); BX_INFO(("E1000 initialized")); } void bx_e1000_c::reset(unsigned type) { unsigned i; Bit8u *saved_ptr; static const struct reset_vals_t { unsigned addr; unsigned char val; } reset_vals[] = { { 0x00, 0x86 }, { 0x01, 0x80 }, { 0x02, 0x0e }, { 0x03, 0x10 }, { 0x04, 0x03 }, { 0x05, 0x00 }, // command io / memory { 0x06, 0x00 }, { 0x07, 0x00 }, // status { 0x08, 0x03 }, // revision number { 0x09, 0x00 }, // interface { 0x0a, 0x00 }, // class_sub { 0x0b, 0x02 }, // class_base Network Controller { 0x0e, 0x00 }, // header type generic // address space 0x10 - 0x13 { 0x10, 0x00 }, { 0x11, 0x00 }, { 0x12, 0x00 }, { 0x13, 0x00 }, // address space 0x14 - 0x17 { 0x14, 0x01 }, { 0x15, 0x00 }, { 0x16, 0x00 }, { 0x17, 0x00 }, { 0x3c, 0x00 }, // IRQ { 0x3d, BX_PCI_INTA }, // INT }; for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { BX_E1000_THIS pci_conf[reset_vals[i].addr] = reset_vals[i].val; } memset(BX_E1000_THIS s.phy_reg, 0, sizeof(BX_E1000_THIS s.phy_reg)); BX_E1000_THIS s.phy_reg[PHY_CTRL] = 0x1140; BX_E1000_THIS s.phy_reg[PHY_STATUS] = 0x796d; // link initially up BX_E1000_THIS s.phy_reg[PHY_ID1] = 0x141; BX_E1000_THIS s.phy_reg[PHY_ID2] = 0xc20; BX_E1000_THIS s.phy_reg[PHY_1000T_CTRL] = 0x0e00; BX_E1000_THIS s.phy_reg[M88E1000_PHY_SPEC_CTRL] = 0x360; BX_E1000_THIS s.phy_reg[M88E1000_EXT_PHY_SPEC_CTRL] = 0x0d60; BX_E1000_THIS s.phy_reg[PHY_AUTONEG_ADV] = 0xde1; BX_E1000_THIS s.phy_reg[PHY_LP_ABILITY] = 0x1e0; BX_E1000_THIS s.phy_reg[PHY_1000T_STATUS] = 0x3c00; BX_E1000_THIS s.phy_reg[M88E1000_PHY_SPEC_STATUS] = 0xac00; memset(BX_E1000_THIS s.mac_reg, 0, 0x20000); BX_E1000_THIS s.mac_reg[PBA] = 0x00100030; BX_E1000_THIS s.mac_reg[LEDCTL] = 0x602; BX_E1000_THIS s.mac_reg[CTRL] = E1000_CTRL_SWDPIN2 | E1000_CTRL_SWDPIN0 | E1000_CTRL_SPD_1000 | E1000_CTRL_SLU; BX_E1000_THIS s.mac_reg[STATUS] = 0x80000000 | E1000_STATUS_GIO_MASTER_ENABLE | E1000_STATUS_ASDV | E1000_STATUS_MTXCKOK | E1000_STATUS_SPEED_1000 | E1000_STATUS_FD | E1000_STATUS_LU; BX_E1000_THIS s.mac_reg[MANC] = E1000_MANC_EN_MNG2HOST | E1000_MANC_RCV_TCO_EN | E1000_MANC_ARP_EN | E1000_MANC_0298_EN | E1000_MANC_RMCP_EN; BX_E1000_THIS s.rxbuf_min_shift = 1; saved_ptr = BX_E1000_THIS s.tx.vlan; memset(&BX_E1000_THIS s.tx, 0, sizeof(BX_E1000_THIS s.tx)); BX_E1000_THIS s.tx.vlan = saved_ptr; BX_E1000_THIS s.tx.data = BX_E1000_THIS s.tx.vlan + 4; // Deassert IRQ set_irq_level(0); } void bx_e1000_c::register_state(void) { unsigned i; char pname[5]; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "e1000", "E1000 State"); new bx_shadow_data_c(list, "mac_reg", (Bit8u*)BX_E1000_THIS s.mac_reg, 0x20000); bx_list_c *phy = new bx_list_c(list, "phy_reg", ""); for (i = 0; i < 32; i++) { sprintf(pname, "0x%02x", i); new bx_shadow_num_c(phy, pname, &BX_E1000_THIS s.phy_reg[i], BASE_HEX); } bx_list_c *eeprom = new bx_list_c(list, "eeprom_data", ""); for (i = 0; i < 64; i++) { sprintf(pname, "0x%02x", i); new bx_shadow_num_c(eeprom, pname, &BX_E1000_THIS s.eeprom_data[i], BASE_HEX); } BXRS_DEC_PARAM_FIELD(list, rxbuf_size, BX_E1000_THIS s.rxbuf_size); BXRS_DEC_PARAM_FIELD(list, rxbuf_min_shift, BX_E1000_THIS s.rxbuf_min_shift); BXRS_PARAM_BOOL(list, check_rxov, BX_E1000_THIS s.check_rxov); bx_list_c *tx = new bx_list_c(list, "tx", ""); bx_list_c *header = new bx_list_c(tx, "header", ""); for (i = 0; i < 256; i++) { sprintf(pname, "0x%02x", i); new bx_shadow_num_c(header, pname, &BX_E1000_THIS s.tx.header[i], BASE_HEX); } bx_list_c *vlh = new bx_list_c(tx, "vlan_header", ""); for (i = 0; i < 4; i++) { sprintf(pname, "0x%02x", i); new bx_shadow_num_c(vlh, pname, &BX_E1000_THIS s.tx.vlan_header[i], BASE_HEX); } new bx_shadow_data_c(list, "tx_vlan_data", BX_E1000_THIS s.tx.vlan, 0x10004); BXRS_DEC_PARAM_FIELD(tx, size, BX_E1000_THIS s.tx.size); BXRS_DEC_PARAM_FIELD(tx, sum_needed, BX_E1000_THIS s.tx.sum_needed); BXRS_PARAM_BOOL(tx, vlan_needed, BX_E1000_THIS s.tx.vlan_needed); BXRS_DEC_PARAM_FIELD(tx, ipcss, BX_E1000_THIS s.tx.ipcss); BXRS_DEC_PARAM_FIELD(tx, ipcso, BX_E1000_THIS s.tx.ipcso); BXRS_DEC_PARAM_FIELD(tx, ipcse, BX_E1000_THIS s.tx.ipcse); BXRS_DEC_PARAM_FIELD(tx, tucss, BX_E1000_THIS s.tx.tucss); BXRS_DEC_PARAM_FIELD(tx, tucso, BX_E1000_THIS s.tx.tucso); BXRS_DEC_PARAM_FIELD(tx, tucse, BX_E1000_THIS s.tx.tucse); BXRS_DEC_PARAM_FIELD(tx, hdr_len, BX_E1000_THIS s.tx.hdr_len); BXRS_DEC_PARAM_FIELD(tx, mss, BX_E1000_THIS s.tx.mss); BXRS_DEC_PARAM_FIELD(tx, paylen, BX_E1000_THIS s.tx.paylen); BXRS_DEC_PARAM_FIELD(tx, tso_frames, BX_E1000_THIS s.tx.tso_frames); BXRS_PARAM_BOOL(tx, tse, BX_E1000_THIS s.tx.tse); BXRS_PARAM_BOOL(tx, ip, BX_E1000_THIS s.tx.ip); BXRS_PARAM_BOOL(tx, tcp, BX_E1000_THIS s.tx.tcp); BXRS_PARAM_BOOL(tx, cptse, BX_E1000_THIS s.tx.cptse); BXRS_HEX_PARAM_FIELD(tx, int_cause, BX_E1000_THIS s.tx.int_cause); bx_list_c *eecds = new bx_list_c(list, "eecd_state", ""); BXRS_DEC_PARAM_FIELD(eecds, val_in, BX_E1000_THIS s.eecd_state.val_in); BXRS_DEC_PARAM_FIELD(eecds, bitnum_in, BX_E1000_THIS s.eecd_state.bitnum_in); BXRS_DEC_PARAM_FIELD(eecds, bitnum_out, BX_E1000_THIS s.eecd_state.bitnum_out); BXRS_PARAM_BOOL(eecds, reading, BX_E1000_THIS s.eecd_state.reading); BXRS_HEX_PARAM_FIELD(eecds, old_eecd, BX_E1000_THIS s.eecd_state.old_eecd); register_pci_state(list); } void bx_e1000_c::after_restore_state(void) { if (DEV_pci_set_base_mem(BX_E1000_THIS_PTR, mem_read_handler, mem_write_handler, &BX_E1000_THIS pci_base_address[0], &BX_E1000_THIS pci_conf[0x10], 0x20000)) { BX_INFO(("new mem base address: 0x%08x", BX_E1000_THIS pci_base_address[0])); } if (DEV_pci_set_base_io(BX_E1000_THIS_PTR, read_handler, write_handler, &BX_E1000_THIS pci_base_address[1], &BX_E1000_THIS pci_conf[0x14], 64, &e1000_iomask[0], "e1000")) { BX_INFO(("new i/o base address: 0x%04x", BX_E1000_THIS pci_base_address[1])); } if (BX_E1000_THIS pci_rom_size > 0) { if (DEV_pci_set_base_mem(BX_E1000_THIS_PTR, mem_read_handler, mem_write_handler, &BX_E1000_THIS pci_rom_address, &BX_E1000_THIS pci_conf[0x30], BX_E1000_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_E1000_THIS pci_rom_address)); } } } bx_bool bx_e1000_c::mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit32u *data_ptr = (Bit32u*) data; Bit8u *data8_ptr; Bit32u offset, value = 0; Bit16u index; if (BX_E1000_THIS pci_rom_size > 0) { Bit32u mask = (BX_E1000_THIS pci_rom_size - 1); if ((addr & ~mask) == BX_E1000_THIS pci_rom_address) { #ifdef BX_LITTLE_ENDIAN data8_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data8_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { if (BX_E1000_THIS pci_conf[0x30] & 0x01) { *data8_ptr = BX_E1000_THIS pci_rom[addr & mask]; } else { *data8_ptr = 0xff; } addr++; #ifdef BX_LITTLE_ENDIAN data8_ptr++; #else // BX_BIG_ENDIAN data8_ptr--; #endif } return 1; } } offset = addr & 0x1ffff; index = (offset >> 2); if (len == 4) { BX_DEBUG(("mem read from offset 0x%08x -", offset)); switch (offset) { case E1000_PBA: case E1000_RCTL: case E1000_TDH: case E1000_TXDCTL: case E1000_WUFC: case E1000_TDT: case E1000_CTRL: case E1000_LEDCTL: case E1000_MANC: case E1000_MDIC: case E1000_SWSM: case E1000_STATUS: case E1000_TORL: case E1000_TOTL: case E1000_IMS: case E1000_TCTL: case E1000_RDH: case E1000_RDT: case E1000_VET: case E1000_ICS: case E1000_TDBAL: case E1000_TDBAH: case E1000_RDBAH: case E1000_RDBAL: case E1000_TDLEN: case E1000_RDLEN: value = BX_E1000_THIS s.mac_reg[index]; break; case E1000_TOTH: case E1000_TORH: value = BX_E1000_THIS s.mac_reg[index]; BX_E1000_THIS s.mac_reg[index] = 0; BX_E1000_THIS s.mac_reg[index - 1] = 0; break; case E1000_GPRC: case E1000_GPTC: case E1000_TPR: case E1000_TPT: value = BX_E1000_THIS s.mac_reg[index]; BX_E1000_THIS s.mac_reg[index] = 0; break; case E1000_ICR: value = BX_E1000_THIS s.mac_reg[index]; BX_DEBUG(("ICR read: %x", value)); set_interrupt_cause(0); break; case E1000_EECD: value = get_eecd(); break; case E1000_EERD: value = flash_eerd_read(); break; default: if (((offset >= E1000_CRCERRS) && (offset <= E1000_MPC)) || ((offset >= E1000_RA) && (offset <= (E1000_RA + 31))) || ((offset >= E1000_MTA) && (offset <= (E1000_MTA + 127))) || ((offset >= E1000_VFTA) && (offset <= (E1000_VFTA + 127)))) { value = BX_E1000_THIS s.mac_reg[index]; } else { BX_DEBUG(("mem read from offset 0x%08x returns 0", offset)); } } } else if ((len == 1) && (offset == E1000_STATUS)) { BX_DEBUG(("mem read from offset 0x%08x with len 1 -", offset)); value = BX_E1000_THIS s.mac_reg[index] & 0xff; } else { BX_DEBUG(("mem read from offset 0x%08x with len %d not implemented", offset, len)); } BX_DEBUG(("val = 0x%08x", value)); *data_ptr = value; return 1; } bx_bool bx_e1000_c::mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit32u value = *(Bit32u*) data; Bit32u offset; Bit16u index; if (BX_E1000_THIS pci_rom_size > 0) { Bit32u mask = (BX_E1000_THIS pci_rom_size - 1); if ((addr & ~mask) == BX_E1000_THIS pci_rom_address) { BX_INFO(("write to ROM ignored (addr=0x%08x len=%d)", (Bit32u)addr, len)); return 1; } } offset = addr & 0x1ffff; index = (offset >> 2); if (len == 4) { BX_DEBUG(("mem write to offset 0x%08x - value = 0x%08x", offset, value)); switch (offset) { case E1000_PBA: case E1000_EERD: case E1000_SWSM: case E1000_WUFC: case E1000_TDBAL: case E1000_TDBAH: case E1000_TXDCTL: case E1000_RDBAH: case E1000_RDBAL: case E1000_LEDCTL: case E1000_VET: BX_E1000_THIS s.mac_reg[index] = value; break; case E1000_TDLEN: case E1000_RDLEN: BX_E1000_THIS s.mac_reg[index] = value & 0xfff80; break; case E1000_TCTL: case E1000_TDT: BX_E1000_THIS s.mac_reg[index] = value; BX_E1000_THIS s.mac_reg[TDT] &= 0xffff; start_xmit(); break; case E1000_MDIC: set_mdic(value); break; case E1000_ICS: set_ics(value); break; case E1000_TDH: case E1000_RDH: BX_E1000_THIS s.mac_reg[index] = value & 0xffff; break; case E1000_RDT: BX_E1000_THIS s.check_rxov = 0; BX_E1000_THIS s.mac_reg[index] = value & 0xffff; break; case E1000_IMC: BX_E1000_THIS s.mac_reg[IMS] &= ~value; set_ics(0); break; case E1000_IMS: BX_E1000_THIS s.mac_reg[IMS] |= value; set_ics(0); break; case E1000_ICR: BX_DEBUG(("set_icr %x", value)); set_interrupt_cause(BX_E1000_THIS s.mac_reg[ICR] & ~value); break; case E1000_EECD: set_eecd(value); break; case E1000_RCTL: set_rx_control(value); break; case E1000_CTRL: // RST is self clearing BX_E1000_THIS s.mac_reg[CTRL] = value & ~E1000_CTRL_RST; break; default: if (((offset >= E1000_RA) && (offset <= (E1000_RA + 31))) || ((offset >= E1000_MTA) && (offset <= (E1000_MTA + 127))) || ((offset >= E1000_VFTA) && (offset <= (E1000_VFTA + 127)))) { BX_E1000_THIS s.mac_reg[index] = value; } else { BX_DEBUG(("mem write to offset 0x%08x ignored - value = 0x%08x", offset, value)); } } } else { BX_DEBUG(("mem write to offset 0x%08x with len %d not implemented", offset, len)); } return 1; } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_e1000_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_E1000_SMF bx_e1000_c *class_ptr = (bx_e1000_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_e1000_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_E1000_SMF Bit8u offset; offset = address - BX_E1000_THIS pci_base_address[1]; BX_ERROR(("register read from offset 0x%02x returns 0", offset)); return 0; } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_e1000_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_E1000_SMF bx_e1000_c *class_ptr = (bx_e1000_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_e1000_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_E1000_SMF Bit8u offset; offset = address - BX_E1000_THIS pci_base_address[1]; BX_ERROR(("register write to offset 0x%02x ignored - value = 0x%08x", offset, value)); } void bx_e1000_c::set_irq_level(bx_bool level) { DEV_pci_set_irq(BX_E1000_THIS s.devfunc, BX_E1000_THIS pci_conf[0x3d], level); } void bx_e1000_c::set_interrupt_cause(Bit32u value) { if (value != 0) value |= E1000_ICR_INT_ASSERTED; BX_E1000_THIS s.mac_reg[ICR] = value; BX_E1000_THIS s.mac_reg[ICS] = value; set_irq_level((BX_E1000_THIS s.mac_reg[IMS] & BX_E1000_THIS s.mac_reg[ICR]) != 0); } void bx_e1000_c::set_ics(Bit32u value) { BX_DEBUG(("set_ics %x, ICR %x, IMR %x", value, BX_E1000_THIS s.mac_reg[ICR], BX_E1000_THIS s.mac_reg[IMS])); set_interrupt_cause(value | BX_E1000_THIS s.mac_reg[ICR]); } int bx_e1000_c::rxbufsize(Bit32u v) { v &= E1000_RCTL_BSEX | E1000_RCTL_SZ_16384 | E1000_RCTL_SZ_8192 | E1000_RCTL_SZ_4096 | E1000_RCTL_SZ_2048 | E1000_RCTL_SZ_1024 | E1000_RCTL_SZ_512 | E1000_RCTL_SZ_256; switch (v) { case E1000_RCTL_BSEX | E1000_RCTL_SZ_16384: return 16384; case E1000_RCTL_BSEX | E1000_RCTL_SZ_8192: return 8192; case E1000_RCTL_BSEX | E1000_RCTL_SZ_4096: return 4096; case E1000_RCTL_SZ_1024: return 1024; case E1000_RCTL_SZ_512: return 512; case E1000_RCTL_SZ_256: return 256; } return 2048; } void bx_e1000_c::set_rx_control(Bit32u value) { BX_E1000_THIS s.mac_reg[RCTL] = value; BX_E1000_THIS s.rxbuf_size = rxbufsize(value); BX_E1000_THIS s.rxbuf_min_shift = ((value / E1000_RCTL_RDMTS_QUAT) & 3) + 1; BX_DEBUG(("RCTL: %d, mac_reg[RCTL] = 0x%x", BX_E1000_THIS s.mac_reg[RDT], BX_E1000_THIS s.mac_reg[RCTL])); } void bx_e1000_c::set_mdic(Bit32u value) { Bit32u data = value & E1000_MDIC_DATA_MASK; Bit32u addr = ((value & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); if ((value & E1000_MDIC_PHY_MASK) >> E1000_MDIC_PHY_SHIFT != 1) { // phy # value = BX_E1000_THIS s.mac_reg[MDIC] | E1000_MDIC_ERROR; } else if (value & E1000_MDIC_OP_READ) { BX_DEBUG(("MDIC read reg 0x%x", addr)); if (!(phy_regcap[addr] & PHY_R)) { BX_DEBUG(("MDIC read reg %x unhandled", addr)); value |= E1000_MDIC_ERROR; } else { value = (value ^ data) | BX_E1000_THIS s.phy_reg[addr]; } } else if (value & E1000_MDIC_OP_WRITE) { BX_DEBUG(("MDIC write reg 0x%x, value 0x%x", addr, data)); if (!(phy_regcap[addr] & PHY_W)) { BX_DEBUG(("MDIC write reg %x unhandled", addr)); value |= E1000_MDIC_ERROR; } else { BX_E1000_THIS s.phy_reg[addr] = data; } } BX_E1000_THIS s.mac_reg[MDIC] = value | E1000_MDIC_READY; set_ics(E1000_ICR_MDAC); } Bit32u bx_e1000_c::get_eecd() { BX_DEBUG(("reading eeprom bit %d (reading %d)", BX_E1000_THIS s.eecd_state.bitnum_out, BX_E1000_THIS s.eecd_state.reading)); Bit32u ret = E1000_EECD_PRES|E1000_EECD_GNT | BX_E1000_THIS s.eecd_state.old_eecd; if (!BX_E1000_THIS s.eecd_state.reading || ((BX_E1000_THIS s.eeprom_data[(BX_E1000_THIS s.eecd_state.bitnum_out >> 4) & 0x3f] >> ((BX_E1000_THIS s.eecd_state.bitnum_out & 0xf) ^ 0xf))) & 1) { ret |= E1000_EECD_DO; } return ret; } void bx_e1000_c::set_eecd(Bit32u value) { Bit32u oldval = BX_E1000_THIS s.eecd_state.old_eecd; BX_E1000_THIS s.eecd_state.old_eecd = value & (E1000_EECD_SK | E1000_EECD_CS | E1000_EECD_DI|E1000_EECD_FWE_MASK|E1000_EECD_REQ); if (!(E1000_EECD_CS & value)) // CS inactive; nothing to do return; if (E1000_EECD_CS & (value ^ oldval)) { // CS rise edge; reset state BX_E1000_THIS s.eecd_state.val_in = 0; BX_E1000_THIS s.eecd_state.bitnum_in = 0; BX_E1000_THIS s.eecd_state.bitnum_out = 0; BX_E1000_THIS s.eecd_state.reading = 0; } if (!(E1000_EECD_SK & (value ^ oldval))) // no clock edge return; if (!(E1000_EECD_SK & value)) { // falling edge BX_E1000_THIS s.eecd_state.bitnum_out++; return; } BX_E1000_THIS s.eecd_state.val_in <<= 1; if (value & E1000_EECD_DI) BX_E1000_THIS s.eecd_state.val_in |= 1; if (++BX_E1000_THIS s.eecd_state.bitnum_in == 9 && !BX_E1000_THIS s.eecd_state.reading) { BX_E1000_THIS s.eecd_state.bitnum_out = ((BX_E1000_THIS s.eecd_state.val_in & 0x3f)<<4)-1; BX_E1000_THIS s.eecd_state.reading = (((BX_E1000_THIS s.eecd_state.val_in >> 6) & 7) == EEPROM_READ_OPCODE_MICROWIRE); } BX_DEBUG(("eeprom bitnum in %d out %d, reading %d", BX_E1000_THIS s.eecd_state.bitnum_in, BX_E1000_THIS s.eecd_state.bitnum_out, BX_E1000_THIS s.eecd_state.reading)); } Bit32u bx_e1000_c::flash_eerd_read() { unsigned int index, r = BX_E1000_THIS s.mac_reg[EERD] & ~E1000_EEPROM_RW_REG_START; if ((BX_E1000_THIS s.mac_reg[EERD] & E1000_EEPROM_RW_REG_START) == 0) return (BX_E1000_THIS s.mac_reg[EERD]); if ((index = r >> E1000_EEPROM_RW_ADDR_SHIFT) > EEPROM_CHECKSUM_REG) return (E1000_EEPROM_RW_REG_DONE | r); return ((BX_E1000_THIS s.eeprom_data[index] << E1000_EEPROM_RW_REG_DATA) | E1000_EEPROM_RW_REG_DONE | r); } void bx_e1000_c::putsum(Bit8u *data, Bit32u n, Bit32u sloc, Bit32u css, Bit32u cse) { Bit32u sum; if (cse && cse < n) n = cse + 1; if (sloc < n-1) { sum = net_checksum_add(data+css, n-css); put_net2(data + sloc, net_checksum_finish(sum)); } } bx_bool bx_e1000_c::vlan_enabled() { return ((BX_E1000_THIS s.mac_reg[CTRL] & E1000_CTRL_VME) != 0); } bx_bool bx_e1000_c::vlan_rx_filter_enabled() { return ((BX_E1000_THIS s.mac_reg[RCTL] & E1000_RCTL_VFE) != 0); } bx_bool bx_e1000_c::is_vlan_packet(const Bit8u *buf) { return (get_net2(buf + 12) == (Bit16u)BX_E1000_THIS s.mac_reg[VET]); } bx_bool bx_e1000_c::is_vlan_txd(Bit32u txd_lower) { return ((txd_lower & E1000_TXD_CMD_VLE) != 0); } int bx_e1000_c::fcs_len() { return (BX_E1000_THIS s.mac_reg[RCTL] & E1000_RCTL_SECRC) ? 0 : 4; } void bx_e1000_c::xmit_seg() { Bit16u len; Bit8u *sp; unsigned int frames = BX_E1000_THIS s.tx.tso_frames, css, sofar, n; e1000_tx *tp = &BX_E1000_THIS s.tx; if (tp->tse && tp->cptse) { css = tp->ipcss; BX_DEBUG(("frames %d size %d ipcss %d", frames, tp->size, css)); if (tp->ip) { // IPv4 put_net2(tp->data+css+2, tp->size - css); put_net2(tp->data+css+4, get_net2(tp->data+css+4+frames)); } else // IPv6 put_net2(tp->data+css+4, tp->size - css); css = tp->tucss; len = tp->size - css; BX_DEBUG(("tcp %d tucss %d len %d", tp->tcp, css, len)); if (tp->tcp) { sofar = frames * tp->mss; put_net4(tp->data+css+4, // seq get_net4(tp->data+css+4+sofar)); if (tp->paylen - sofar > tp->mss) tp->data[css + 13] &= ~9; // PSH, FIN } else // UDP put_net2(tp->data+css+4, len); if (tp->sum_needed & E1000_TXD_POPTS_TXSM) { unsigned int phsum; // add pseudo-header length before checksum calculation sp = tp->data + tp->tucso; phsum = get_net2(sp) + len; phsum = (phsum >> 16) + (phsum & 0xffff); put_net2(sp, phsum); } tp->tso_frames++; } if (tp->sum_needed & E1000_TXD_POPTS_TXSM) putsum(tp->data, tp->size, tp->tucso, tp->tucss, tp->tucse); if (tp->sum_needed & E1000_TXD_POPTS_IXSM) putsum(tp->data, tp->size, tp->ipcso, tp->ipcss, tp->ipcse); if (tp->vlan_needed) { memmove(tp->vlan, tp->data, 4); memmove(tp->data, tp->data + 4, 8); memcpy(tp->data + 8, tp->vlan_header, 4); BX_E1000_THIS ethdev->sendpkt(tp->vlan, tp->size + 4); } else BX_E1000_THIS ethdev->sendpkt(tp->data, tp->size); BX_E1000_THIS s.mac_reg[TPT]++; BX_E1000_THIS s.mac_reg[GPTC]++; n = BX_E1000_THIS s.mac_reg[TOTL]; if ((BX_E1000_THIS s.mac_reg[TOTL] += BX_E1000_THIS s.tx.size) < n) BX_E1000_THIS s.mac_reg[TOTH]++; } void bx_e1000_c::process_tx_desc(struct e1000_tx_desc *dp) { Bit32u txd_lower = le32_to_cpu(dp->lower.data); Bit32u dtype = txd_lower & (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D); unsigned int split_size = txd_lower & 0xffff, bytes, sz, op; unsigned int msh = 0xfffff, hdr = 0; Bit64u addr; struct e1000_context_desc *xp = (struct e1000_context_desc *)dp; e1000_tx *tp = &BX_E1000_THIS s.tx; if (dtype == E1000_TXD_CMD_DEXT) { // context descriptor op = le32_to_cpu(xp->cmd_and_length); tp->ipcss = xp->lower_setup.ip_fields.ipcss; tp->ipcso = xp->lower_setup.ip_fields.ipcso; tp->ipcse = le16_to_cpu(xp->lower_setup.ip_fields.ipcse); tp->tucss = xp->upper_setup.tcp_fields.tucss; tp->tucso = xp->upper_setup.tcp_fields.tucso; tp->tucse = le16_to_cpu(xp->upper_setup.tcp_fields.tucse); tp->paylen = op & 0xfffff; tp->hdr_len = xp->tcp_seg_setup.fields.hdr_len; tp->mss = le16_to_cpu(xp->tcp_seg_setup.fields.mss); tp->ip = (op & E1000_TXD_CMD_IP) ? 1 : 0; tp->tcp = (op & E1000_TXD_CMD_TCP) ? 1 : 0; tp->tse = (op & E1000_TXD_CMD_TSE) ? 1 : 0; tp->tso_frames = 0; if (tp->tucso == 0) { // this is probably wrong BX_DEBUG(("TCP/UDP: cso 0!")); tp->tucso = tp->tucss + (tp->tcp ? 16 : 6); } return; } else if (dtype == (E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D)) { // data descriptor if (tp->size == 0) { tp->sum_needed = le32_to_cpu(dp->upper.data) >> 8; } tp->cptse = ( txd_lower & E1000_TXD_CMD_TSE ) ? 1 : 0; } else { // legacy descriptor tp->cptse = 0; } if (vlan_enabled() && is_vlan_txd(txd_lower) && (tp->cptse || txd_lower & E1000_TXD_CMD_EOP)) { tp->vlan_needed = 1; put_net2(tp->vlan_header, (Bit16u)BX_E1000_THIS s.mac_reg[VET]); put_net2(tp->vlan_header + 2, le16_to_cpu(dp->upper.fields.special)); } addr = le64_to_cpu(dp->buffer_addr); if (tp->tse && tp->cptse) { hdr = tp->hdr_len; msh = hdr + tp->mss; do { bytes = split_size; if (tp->size + bytes > msh) bytes = msh - tp->size; DEV_MEM_READ_PHYSICAL_DMA(addr, bytes, tp->data + tp->size); if ((sz = tp->size + bytes) >= hdr && tp->size < hdr) memmove(tp->header, tp->data, hdr); tp->size = sz; addr += bytes; if (sz == msh) { xmit_seg(); memmove(tp->data, tp->header, hdr); tp->size = hdr; } } while (split_size -= bytes); } else if (!tp->tse && tp->cptse) { // context descriptor TSE is not set, while data descriptor TSE is set BX_DEBUG(("TCP segmentaion Error")); } else { DEV_MEM_READ_PHYSICAL_DMA(addr, split_size, tp->data + tp->size); tp->size += split_size; } if (!(txd_lower & E1000_TXD_CMD_EOP)) return; if (!(tp->tse && tp->cptse && tp->size < hdr)) xmit_seg(); tp->tso_frames = 0; tp->sum_needed = 0; tp->vlan_needed = 0; tp->size = 0; tp->cptse = 0; } Bit32u bx_e1000_c::txdesc_writeback(bx_phy_address base, struct e1000_tx_desc *dp) { Bit32u txd_upper, txd_lower = le32_to_cpu(dp->lower.data); if (!(txd_lower & (E1000_TXD_CMD_RS|E1000_TXD_CMD_RPS))) return 0; txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) & ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU); dp->upper.data = cpu_to_le32(txd_upper); DEV_MEM_WRITE_PHYSICAL_DMA(base + ((char *)&dp->upper - (char *)dp), sizeof(dp->upper), (Bit8u *)&dp->upper); return E1000_ICR_TXDW; } Bit64u bx_e1000_c::tx_desc_base() { Bit64u bah = BX_E1000_THIS s.mac_reg[TDBAH]; Bit64u bal = BX_E1000_THIS s.mac_reg[TDBAL] & ~0xf; return (bah << 32) + bal; } void bx_e1000_c::start_xmit() { bx_phy_address base; struct e1000_tx_desc desc; Bit32u tdh_start = BX_E1000_THIS s.mac_reg[TDH], cause = E1000_ICS_TXQE; if (!(BX_E1000_THIS s.mac_reg[TCTL] & E1000_TCTL_EN)) { BX_DEBUG(("tx disabled")); return; } while (BX_E1000_THIS s.mac_reg[TDH] != BX_E1000_THIS s.mac_reg[TDT]) { base = tx_desc_base() + sizeof(struct e1000_tx_desc) * BX_E1000_THIS s.mac_reg[TDH]; DEV_MEM_READ_PHYSICAL_DMA(base, sizeof(struct e1000_tx_desc), (Bit8u *)&desc); BX_DEBUG(("index %d: %p : %x %x", BX_E1000_THIS s.mac_reg[TDH], (void *)desc.buffer_addr, desc.lower.data, desc.upper.data)); process_tx_desc(&desc); cause |= txdesc_writeback(base, &desc); if (++BX_E1000_THIS s.mac_reg[TDH] * sizeof(desc) >= BX_E1000_THIS s.mac_reg[TDLEN]) BX_E1000_THIS s.mac_reg[TDH] = 0; /* * the following could happen only if guest sw assigns * bogus values to TDT/TDLEN. * there's nothing too intelligent we could do about this. */ if (BX_E1000_THIS s.mac_reg[TDH] == tdh_start) { BX_ERROR(("TDH wraparound @%x, TDT %x, TDLEN %x", tdh_start, BX_E1000_THIS s.mac_reg[TDT], BX_E1000_THIS s.mac_reg[TDLEN])); break; } } BX_E1000_THIS s.tx.int_cause = cause; bx_pc_system.activate_timer(BX_E1000_THIS s.tx_timer_index, 10, 0); // not continuous bx_gui->statusbar_setitem(BX_E1000_THIS s.statusbar_id, 1, 1); } void bx_e1000_c::tx_timer_handler(void *this_ptr) { bx_e1000_c *class_ptr = (bx_e1000_c *) this_ptr; class_ptr->tx_timer(); } void bx_e1000_c::tx_timer(void) { set_ics(BX_E1000_THIS s.tx.int_cause); } int bx_e1000_c::receive_filter(const Bit8u *buf, int size) { static const Bit8u bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; static const int mta_shift[] = {4, 3, 2, 0}; Bit32u f, rctl = BX_E1000_THIS s.mac_reg[RCTL], ra[2], *rp; if (is_vlan_packet(buf) && vlan_rx_filter_enabled()) { Bit16u vid = get_net2(buf + 14); Bit32u vfta = BX_E1000_THIS s.mac_reg[VFTA + ((vid >> 5) & 0x7f)]; if ((vfta & (1 << (vid & 0x1f))) == 0) return 0; } if (rctl & E1000_RCTL_UPE) // promiscuous return 1; if ((buf[0] & 1) && (rctl & E1000_RCTL_MPE)) // promiscuous mcast return 1; if ((rctl & E1000_RCTL_BAM) && !memcmp(buf, bcast, sizeof bcast)) return 1; for (rp = BX_E1000_THIS s.mac_reg + RA; rp < BX_E1000_THIS s.mac_reg + RA + 32; rp += 2) { if (!(rp[1] & E1000_RAH_AV)) continue; ra[0] = cpu_to_le32(rp[0]); ra[1] = cpu_to_le32(rp[1]); if (!memcmp(buf, (Bit8u *)ra, 6)) { BX_DEBUG(("unicast match[%d]: %02x:%02x:%02x:%02x:%02x:%02x", (int)(rp - BX_E1000_THIS s.mac_reg - RA) / 2, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5])); return 1; } } BX_DEBUG(("unicast mismatch: %02x:%02x:%02x:%02x:%02x:%02x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5])); f = mta_shift[(rctl >> E1000_RCTL_MO_SHIFT) & 3]; f = (((buf[5] << 8) | buf[4]) >> f) & 0xfff; if (BX_E1000_THIS s.mac_reg[MTA + (f >> 5)] & (1 << (f & 0x1f))) return 1; BX_DEBUG(("dropping, inexact filter mismatch: %02x:%02x:%02x:%02x:%02x:%02x MO %d MTA[%d] %x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], (rctl >> E1000_RCTL_MO_SHIFT) & 3, f >> 5, BX_E1000_THIS s.mac_reg[MTA + (f >> 5)])); return 0; } bx_bool bx_e1000_c::e1000_has_rxbufs(size_t total_size) { int bufs; // Fast-path short packets if (total_size <= BX_E1000_THIS s.rxbuf_size) { return (BX_E1000_THIS s.mac_reg[RDH] != BX_E1000_THIS s.mac_reg[RDT]) || !BX_E1000_THIS s.check_rxov; } if (BX_E1000_THIS s.mac_reg[RDH] < BX_E1000_THIS s.mac_reg[RDT]) { bufs = BX_E1000_THIS s.mac_reg[RDT] - BX_E1000_THIS s.mac_reg[RDH]; } else if (BX_E1000_THIS s.mac_reg[RDH] > BX_E1000_THIS s.mac_reg[RDT] || !BX_E1000_THIS s.check_rxov) { bufs = BX_E1000_THIS s.mac_reg[RDLEN] / sizeof(struct e1000_rx_desc) + BX_E1000_THIS s.mac_reg[RDT] - BX_E1000_THIS s.mac_reg[RDH]; } else { return 0; } return (total_size <= (bufs * BX_E1000_THIS s.rxbuf_size)); } Bit64u bx_e1000_c::rx_desc_base() { Bit64u bah = BX_E1000_THIS s.mac_reg[RDBAH]; Bit64u bal = BX_E1000_THIS s.mac_reg[RDBAL] & ~0xf; return (bah << 32) + bal; } /* * Callback from the eth system driver to check if the device can receive */ Bit32u bx_e1000_c::rx_status_handler(void *arg) { bx_e1000_c *class_ptr = (bx_e1000_c *) arg; return class_ptr->rx_status(); } Bit32u bx_e1000_c::rx_status() { Bit32u status = BX_NETDEV_1GBIT; if ((BX_E1000_THIS s.mac_reg[RCTL] & E1000_RCTL_EN) && e1000_has_rxbufs(1)) { status |= BX_NETDEV_RXREADY; } return status; } /* * Callback from the eth system driver when a frame has arrived */ void bx_e1000_c::rx_handler(void *arg, const void *buf, unsigned len) { bx_e1000_c *class_ptr = (bx_e1000_c *) arg; class_ptr->rx_frame(buf, len); } void bx_e1000_c::rx_frame(const void *buf, unsigned buf_size) { struct e1000_rx_desc desc; bx_phy_address base; unsigned int n, rdt; Bit32u rdh_start; Bit16u vlan_special = 0; Bit8u vlan_status = 0, vlan_offset = 0; Bit8u min_buf[MIN_BUF_SIZE]; size_t desc_offset; size_t desc_size; size_t total_size; if (!(BX_E1000_THIS s.mac_reg[RCTL] & E1000_RCTL_EN)) return; // Pad to minimum Ethernet frame length if (buf_size < sizeof(min_buf)) { memcpy(min_buf, buf, buf_size); memset(&min_buf[buf_size], 0, sizeof(min_buf) - buf_size); buf = min_buf; buf_size = sizeof(min_buf); } if (!receive_filter((Bit8u *)buf, buf_size)) return; if (vlan_enabled() && is_vlan_packet((Bit8u *)buf)) { vlan_special = cpu_to_le16(get_net2(((Bit8u *)(buf) + 14))); memmove((Bit8u *)buf + 4, buf, 12); vlan_status = E1000_RXD_STAT_VP; vlan_offset = 4; buf_size -= 4; } rdh_start = BX_E1000_THIS s.mac_reg[RDH]; desc_offset = 0; total_size = buf_size + fcs_len(); if (!e1000_has_rxbufs(total_size)) { set_ics(E1000_ICS_RXO); return; } do { desc_size = total_size - desc_offset; if (desc_size > BX_E1000_THIS s.rxbuf_size) { desc_size = BX_E1000_THIS s.rxbuf_size; } base = rx_desc_base() + sizeof(desc) * BX_E1000_THIS s.mac_reg[RDH]; DEV_MEM_READ_PHYSICAL_DMA(base, sizeof(desc), (Bit8u *)&desc); desc.special = vlan_special; desc.status |= (vlan_status | E1000_RXD_STAT_DD); if (desc.buffer_addr) { if (desc_offset < buf_size) { size_t copy_size = buf_size - desc_offset; if (copy_size > BX_E1000_THIS s.rxbuf_size) { copy_size = BX_E1000_THIS s.rxbuf_size; } DEV_MEM_WRITE_PHYSICAL_DMA(le64_to_cpu(desc.buffer_addr), copy_size, (Bit8u *)buf + desc_offset + vlan_offset); } desc_offset += desc_size; desc.length = cpu_to_le16(desc_size); if (desc_offset >= total_size) { desc.status |= E1000_RXD_STAT_EOP | E1000_RXD_STAT_IXSM; } else { /* Guest zeroing out status is not a hardware requirement. Clear EOP in case guest didn't do it. */ desc.status &= ~E1000_RXD_STAT_EOP; } } else { // as per intel docs; skip descriptors with null buf addr BX_ERROR(("Null RX descriptor!!")); } DEV_MEM_WRITE_PHYSICAL_DMA(base, sizeof(desc), (Bit8u *)&desc); if (++BX_E1000_THIS s.mac_reg[RDH] * sizeof(desc) >= BX_E1000_THIS s.mac_reg[RDLEN]) BX_E1000_THIS s.mac_reg[RDH] = 0; BX_E1000_THIS s.check_rxov = 1; /* see comment in start_xmit; same here */ if (BX_E1000_THIS s.mac_reg[RDH] == rdh_start) { BX_DEBUG(("RDH wraparound @%x, RDT %x, RDLEN %x", rdh_start, BX_E1000_THIS s.mac_reg[RDT], BX_E1000_THIS s.mac_reg[RDLEN])); set_ics(E1000_ICS_RXO); return; } } while (desc_offset < total_size); BX_E1000_THIS s.mac_reg[GPRC]++; BX_E1000_THIS s.mac_reg[TPR]++; /* TOR - Total Octets Received: * This register includes bytes received in a packet from the field through the field, inclusively. */ n = BX_E1000_THIS s.mac_reg[TORL] + buf_size + /* Always include FCS length. */ 4; if (n < BX_E1000_THIS s.mac_reg[TORL]) BX_E1000_THIS s.mac_reg[TORH]++; BX_E1000_THIS s.mac_reg[TORL] = n; n = E1000_ICS_RXT0; if ((rdt = BX_E1000_THIS s.mac_reg[RDT]) < BX_E1000_THIS s.mac_reg[RDH]) rdt += BX_E1000_THIS s.mac_reg[RDLEN] / sizeof(desc); if (((rdt - BX_E1000_THIS s.mac_reg[RDH]) * sizeof(desc)) <= BX_E1000_THIS s.mac_reg[RDLEN] >> BX_E1000_THIS s.rxbuf_min_shift) n |= E1000_ICS_RXDMT0; set_ics(n); bx_gui->statusbar_setitem(BX_E1000_THIS s.statusbar_id, 1); } // pci configuration space read callback handler Bit32u bx_e1000_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x18) && (address < 0x30)) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_E1000_THIS pci_conf[address+i]; switch (address+i) { case 0x04: value8 &= 0x07; break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); } break; case 0x10: value8 = (value8 & 0xf0) | (oldval & 0x0f); case 0x11: case 0x12: case 0x13: baseaddr0_change |= (value8 != oldval); break; case 0x14: value8 = (value8 & 0xf0) | (oldval & 0x0f); case 0x15: case 0x16: case 0x17: baseaddr1_change |= (value8 != oldval); break; case 0x30: case 0x31: case 0x32: case 0x33: if (BX_E1000_THIS pci_rom_size > 0) { if ((address+i) == 0x30) { value8 &= 0x01; } else if ((address+i) == 0x31) { value8 &= 0xfc; } romaddr_change = 1; break; } default: value8 = oldval; } BX_E1000_THIS pci_conf[address+i] = value8; } if (baseaddr0_change) { if (DEV_pci_set_base_mem(BX_E1000_THIS_PTR, mem_read_handler, mem_write_handler, &BX_E1000_THIS pci_base_address[0], &BX_E1000_THIS pci_conf[0x10], 0x20000)) { BX_INFO(("new mem base address: 0x%08x", BX_E1000_THIS pci_base_address[0])); } } if (baseaddr1_change) { if (DEV_pci_set_base_io(BX_E1000_THIS_PTR, read_handler, write_handler, &BX_E1000_THIS pci_base_address[1], &BX_E1000_THIS pci_conf[0x14], 64, &e1000_iomask[0], "e1000")) { BX_INFO(("new i/o base address: 0x%04x", BX_E1000_THIS pci_base_address[1])); } } if (romaddr_change) { if (DEV_pci_set_base_mem(BX_E1000_THIS_PTR, mem_read_handler, mem_write_handler, &BX_E1000_THIS pci_rom_address, &BX_E1000_THIS pci_conf[0x30], BX_E1000_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_E1000_THIS pci_rom_address)); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } #endif // BX_SUPPORT_PCI && BX_SUPPORT_E1000 bochs-2.6/iodev/ioapic.h0000644000175000017500000001033712020641505015057 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: ioapic.h 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef BX_DEVICES_IOAPIC_H #define BX_DEVICES_IOAPIC_H #if BX_SUPPORT_APIC typedef Bit32u apic_dest_t; /* same definition in apic.h */ extern int apic_bus_deliver_lowest_priority(Bit8u vector, apic_dest_t dest, bx_bool trig_mode, bx_bool broadcast); extern int apic_bus_deliver_interrupt(Bit8u vector, apic_dest_t dest, Bit8u delivery_mode, bx_bool logical_dest, bx_bool level, bx_bool trig_mode); extern int apic_bus_broadcast_interrupt(Bit8u vector, Bit8u delivery_mode, bx_bool trig_mode, int exclude_cpu); #define BX_IOAPIC_NUM_PINS (0x18) // use the same version as 82093 IOAPIC (0x00170011) #define BX_IOAPIC_VERSION_ID (((BX_IOAPIC_NUM_PINS - 1) << 16) | 0x11) class bx_io_redirect_entry_t { Bit32u hi, lo; public: bx_io_redirect_entry_t(): hi(0), lo(0x10000) {} Bit8u destination() const { return (Bit8u)(hi >> 24); } bx_bool is_masked() const { return (bx_bool)((lo >> 16) & 1); } Bit8u trigger_mode() const { return (Bit8u)((lo >> 15) & 1); } bx_bool remote_irr() const { return (bx_bool)((lo >> 14) & 1); } Bit8u pin_polarity() const { return (Bit8u)((lo >> 13) & 1); } bx_bool delivery_status() const { return (bx_bool)((lo >> 12) & 1); } Bit8u destination_mode() const { return (Bit8u)((lo >> 11) & 1); } Bit8u delivery_mode() const { return (Bit8u)((lo >> 8) & 7); } Bit8u vector() const { return (Bit8u)(lo & 0xff); } void set_delivery_status() { lo |= (1<<12); } void clear_delivery_status() { lo &= ~(1<<12); } void set_remote_irr() { lo |= (1<<14); } void clear_remote_irr() { lo &= ~(1<<14); } Bit32u get_lo_part () const { return lo; } Bit32u get_hi_part () const { return hi; } void set_lo_part (Bit32u val_lo_part) { // keep high 32 bits of value, replace low 32, ignore R/O bits lo = val_lo_part & 0xffffafff; } void set_hi_part (Bit32u val_hi_part) { // keep low 32 bits of value, replace high 32 hi = val_hi_part; } void sprintf_self(char *buf); void register_state(bx_param_c *parent); }; class bx_ioapic_c : public bx_ioapic_stub_c { public: bx_ioapic_c(); virtual ~bx_ioapic_c(); virtual void init(); virtual void reset(unsigned type); virtual void register_state(void); #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv); #endif virtual void receive_eoi(Bit8u vector); virtual void set_irq_level(Bit8u int_in, bx_bool level); Bit32u read_aligned(bx_phy_address address); void write_aligned(bx_phy_address address, Bit32u data); private: bx_phy_address get_base(void) const { return base_addr; } void set_id(Bit32u new_id) { id = new_id; } Bit32u get_id() const { return id; } void service_ioapic(void); bx_phy_address base_addr; Bit32u id; Bit32u ioregsel; // selects between various registers Bit32u intin; // interrupt request bitmask, not visible from the outside. Bits in the // irr are set when trigger_irq is called, and cleared when the interrupt // is delivered to the processor. If an interrupt is masked, the irr // will still be set but delivery will not occur until it is unmasked. // It's not clear if this is how the real device works. Bit32u irr; bx_io_redirect_entry_t ioredtbl[BX_IOAPIC_NUM_PINS]; // table of redirections }; #endif #endif bochs-2.6/iodev/unmapped.cc0000644000175000017500000002052512020641505015562 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: unmapped.cc 10886 2011-12-29 19:51:54Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "unmapped.h" #define LOG_THIS theUnmappedDevice-> bx_unmapped_c *theUnmappedDevice = NULL; int libunmapped_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theUnmappedDevice = new bx_unmapped_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUnmappedDevice, BX_PLUGIN_UNMAPPED); return(0); // Success } void libunmapped_LTX_plugin_fini(void) { delete theUnmappedDevice; } bx_unmapped_c::bx_unmapped_c(void) { put("unmapped", "UNMP"); } bx_unmapped_c::~bx_unmapped_c(void) { BX_DEBUG(("Exit")); } void bx_unmapped_c::init(void) { DEV_register_default_ioread_handler(this, read_handler, "Unmapped", 7); DEV_register_default_iowrite_handler(this, write_handler, "Unmapped", 7); s.port80 = 0x00; s.port8e = 0x00; s.shutdown = 0; s.port_e9_hack = SIM->get_param_bool(BXPN_PORT_E9_HACK)->get(); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_unmapped_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_UM_SMF bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_unmapped_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_UM_SMF UNUSED(io_len); Bit32u retval; // This function gets called for access to any IO ports which // are not mapped to any device handler. Reads return 0 if (address >= 0x02e0 && address <= 0x02ef) { retval = 0; goto return_from_read; } switch (address) { case 0x80: retval = BX_UM_THIS s.port80; break; case 0x8e: retval = BX_UM_THIS s.port8e; break; // Unused port on ISA - this can be used by the emulated code // to detect it is running inside Bochs and that the debugging // features are available (write 0xFF or something on unused // port 0x80, then read from 0xe9, if value is 0xe9, debug // output is available) (see write() for that) -- Andreas and Emmanuel case 0xe9: if (BX_UM_THIS s.port_e9_hack) { retval = 0xe9; } else { retval = 0xffffffff; } break; case 0x03df: retval = 0xffffffff; BX_DEBUG(("unsupported IO read from port %04x (CGA)", address)); break; case 0x023a: case 0x02f8: /* UART */ case 0x02f9: /* UART */ case 0x02fb: /* UART */ case 0x02fc: /* UART */ case 0x02fd: /* UART */ case 0x02ea: case 0x02eb: case 0x03e8: case 0x03e9: case 0x03ea: case 0x03eb: case 0x03ec: case 0x03ed: case 0x03f8: /* UART */ case 0x03f9: /* UART */ case 0x03fb: /* UART */ case 0x03fc: /* UART */ case 0x03fd: /* UART */ case 0x17c6: retval = 0xffffffff; break; default: retval = 0xffffffff; } return_from_read: switch (io_len) { case 1: retval = (Bit8u)retval; BX_DEBUG(("unmapped: 8-bit read from %04x = %02x", address, retval)); break; case 2: retval = (Bit16u)retval; BX_DEBUG(("unmapped: 16-bit read from %04x = %04x", address, retval)); break; case 4: BX_DEBUG(("unmapped: 32-bit read from %04x = %08x", address, retval)); break; default: BX_PANIC(("unmapped: %d-bit read from %04x = %x", io_len * 8, address, retval)); } return retval; } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_unmapped_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_UM_SMF bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_unmapped_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_UM_SMF UNUSED(io_len); // This function gets called for access to any IO ports which // are not mapped to any device handler. Writes to an unmapped // IO port are ignored. if (address >= 0x02e0 && address <= 0x02ef) goto return_from_write; switch (address) { case 0x80: // diagnostic test port to display progress of POST //BX_DEBUG(("Diagnostic port 80h: write = %02xh", (unsigned) value)); BX_UM_THIS s.port80 = value; break; case 0x8e: // ??? BX_UM_THIS s.port8e = value; break; // This port doesn't exist on normal ISA architecture. However, // we define a convention here, to display on the console of the // system running Bochs, anything that is written to it. The // idea is to provide debug output very early when writing // BIOS or OS code for example, without having to bother with // properly setting up a serial port or anything. // // Idea by Andreas Beck (andreas.beck@ggi-project.org) case 0xe9: if (BX_UM_THIS s.port_e9_hack) { putchar(value); fflush(stdout); } break; case 0xed: // Dummy port used as I/O delay break; case 0xee: // ??? break; case 0x2f2: case 0x2f3: case 0x2f4: case 0x2f5: case 0x2f6: case 0x2f7: case 0x3e8: case 0x3e9: case 0x3eb: case 0x3ec: case 0x3ed: // BX_DEBUG(("unsupported IO write to port %04x of %02x", address, value)); break; case 0x8900: // Shutdown port, could be moved in a PM device // or a host <-> guest communication device switch (value) { case 'S': if (BX_UM_THIS s.shutdown == 0) BX_UM_THIS s.shutdown = 1; break; case 'h': if (BX_UM_THIS s.shutdown == 1) BX_UM_THIS s.shutdown = 2; break; case 'u': if (BX_UM_THIS s.shutdown == 2) BX_UM_THIS s.shutdown = 3; break; case 't': if (BX_UM_THIS s.shutdown == 3) BX_UM_THIS s.shutdown = 4; break; case 'd': if (BX_UM_THIS s.shutdown == 4) BX_UM_THIS s.shutdown = 5; break; case 'o': if (BX_UM_THIS s.shutdown == 5) BX_UM_THIS s.shutdown = 6; break; case 'w': if (BX_UM_THIS s.shutdown == 6) BX_UM_THIS s.shutdown = 7; break; case 'n': if (BX_UM_THIS s.shutdown == 7) BX_UM_THIS s.shutdown = 8; break; #if BX_DEBUGGER // Very handy for debugging: // output 'D' to port 8900, and bochs quits to debugger case 'D': bx_debug_break(); break; #endif default : BX_UM_THIS s.shutdown = 0; break; } if (BX_UM_THIS s.shutdown == 8) { bx_user_quit = 1; LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL); BX_PANIC(("Shutdown port: shutdown requested")); } break; /* case 0xfedc: bx_dbg.io_debugger = (value > 0); BX_DEBUG(("DEBUGGER = %u", (unsigned) bx_dbg.io_debugger)); break; */ default: break; } return_from_write: switch (io_len) { case 1: BX_DEBUG(("unmapped: 8-bit write to %04x = %02x", address, value)); break; case 2: BX_DEBUG(("unmapped: 16-bit write to %04x = %04x", address, value)); break; case 4: BX_DEBUG(("unmapped: 32-bit write to %04x = %08x", address, value)); break; default: BX_PANIC(("unmapped: %d-bit write to %04x = %x", io_len * 8, address, value)); break; } } bochs-2.6/iodev/slowdown_timer.cc0000644000175000017500000001233112020641505017021 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: slowdown_timer.cc 10898 2011-12-30 11:13:37Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "param_names.h" #include "slowdown_timer.h" #include #if !defined(_MSC_VER) #include #endif //These need to stay printfs because they are useless in the log file. #define BX_SLOWDOWN_PRINTF_FEEDBACK 0 #define SECINUSEC 1000000 #define usectosec(a) ((a)/SECINUSEC) #define sectousec(a) ((a)*SECINUSEC) #define nsectousec(a) ((a)/1000) #define MSECINUSEC 1000 #define usectomsec(a) ((a)/MSECINUSEC) #define Qval 1000 #define MAXMULT 1.5 #define REALTIME_Q SECINUSEC #define LOG_THIS bx_slowdown_timer. bx_slowdown_timer_c bx_slowdown_timer; bx_slowdown_timer_c::bx_slowdown_timer_c() { put("slowdown_timer", "STIME"); s.start_time=0; s.start_emulated_time=0; s.timer_handle=BX_NULL_TIMER_HANDLE; } void bx_slowdown_timer_c::init(void) { // Return early if slowdown timer not selected if ((SIM->get_param_enum(BXPN_CLOCK_SYNC)->get() != BX_CLOCK_SYNC_SLOWDOWN) && (SIM->get_param_enum(BXPN_CLOCK_SYNC)->get() != BX_CLOCK_SYNC_BOTH)) return; BX_INFO(("using 'slowdown' timer synchronization method")); s.MAXmultiplier=MAXMULT; s.Q=Qval; if(s.MAXmultiplier<1) s.MAXmultiplier=1; s.start_time=sectousec(time(NULL)); s.start_emulated_time = bx_pc_system.time_usec(); s.lasttime=0; if (s.timer_handle == BX_NULL_TIMER_HANDLE) { s.timer_handle=bx_pc_system.register_timer(this, timer_handler, 100 , 1, 1, "slowdown_timer"); } bx_pc_system.deactivate_timer(s.timer_handle); bx_pc_system.activate_timer(s.timer_handle,(Bit32u)s.Q,0); } void bx_slowdown_timer_c::exit(void) { s.timer_handle = BX_NULL_TIMER_HANDLE; } void bx_slowdown_timer_c::after_restore_state(void) { s.start_emulated_time = bx_pc_system.time_usec(); } void bx_slowdown_timer_c::timer_handler(void * this_ptr) { bx_slowdown_timer_c * class_ptr = (bx_slowdown_timer_c *) this_ptr; class_ptr->handle_timer(); } void bx_slowdown_timer_c::handle_timer() { Bit64u total_emu_time = (bx_pc_system.time_usec()) - s.start_emulated_time; Bit64u wanttime = s.lasttime+s.Q; Bit64u totaltime = sectousec(time(NULL)) - s.start_time; Bit64u thistime=(wanttime>totaltime)?wanttime:totaltime; #if BX_SLOWDOWN_PRINTF_FEEDBACK printf("Entering slowdown timer handler.\n"); #endif /* Decide if we're behind. * Set interrupt interval accordingly. */ if(totaltime > total_emu_time) { bx_pc_system.deactivate_timer(s.timer_handle); bx_pc_system.activate_timer(s.timer_handle, (Bit32u)(s.MAXmultiplier * (float)((Bit64s)s.Q)), 0); #if BX_SLOWDOWN_PRINTF_FEEDBACK printf("running at MAX speed\n"); #endif } else { bx_pc_system.deactivate_timer(s.timer_handle); bx_pc_system.activate_timer(s.timer_handle,(Bit32u)s.Q,0); #if BX_SLOWDOWN_PRINTF_FEEDBACK printf("running at NORMAL speed\n"); #endif } /* Make sure we took at least one time quantum. */ /* This is a little strange. I'll try to explain. * We're running bochs one second ahead of real time. * this gives us a very precise division on whether * we're ahead or behind the second line. * Basically, here's how it works: * *****|******************|***********... * Time Time+1sec * <^Bochs doesn't delay. * ^>Bochs delays. * <^Bochs runs at MAX speed. * ^>Bochs runs at normal */ if(wanttime > (totaltime+REALTIME_Q)) { #if BX_HAVE_USLEEP usleep(s.Q); #elif BX_HAVE_MSLEEP msleep(usectomsec((Bit32u)s.Q)); #elif BX_HAVE_SLEEP sleep(usectosec(s.Q)); #else #error do not know have to sleep #endif //delay(wanttime-totaltime); /* alternatively: delay(Q); * This works okay because we share the delay between * two time quantums. */ #if BX_SLOWDOWN_PRINTF_FEEDBACK printf("DELAYING for a quantum\n"); #endif } s.lasttime=thistime; //Diagnostic info: #if 0 if(wanttime > (totaltime+REALTIME_Q)) { if(totaltime > total_emu_time) { printf("Solving OpenBSD problem.\n"); } else { printf("too fast.\n"); } } else { if(totaltime > total_emu_time) { printf("too slow.\n"); } else { printf("sometimes invalid state, normally okay.\n"); } } #endif // Diagnostic info } bochs-2.6/iodev/gameport.cc0000644000175000017500000001565112020641505015573 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: gameport.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2003-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // // Standard PC gameport // // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "gameport.h" #ifdef __linux__ #include #include #include #include #include #elif defined(WIN32) #ifndef JOY_BUTTON1 #define JOY_BUTTON1 1 #define JOY_BUTTON2 2 UINT STDCALL joyGetPos(UINT, LPJOYINFO); #endif #define JOYSTICKID1 0 #endif #define LOG_THIS theGameport-> bx_gameport_c *theGameport = NULL; int libgameport_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theGameport = new bx_gameport_c(); bx_devices.pluginGameport = theGameport; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theGameport, BX_PLUGIN_GAMEPORT); return(0); // Success } void libgameport_LTX_plugin_fini(void) { bx_devices.pluginGameport = &bx_devices.stubGameport; delete theGameport; } bx_gameport_c::bx_gameport_c() { put("gameport", "GAME"); joyfd = -1; } bx_gameport_c::~bx_gameport_c() { if (joyfd >= 0) close(joyfd); SIM->get_bochs_root()->remove("gameport"); BX_DEBUG(("Exit")); } void bx_gameport_c::init(void) { // Allocate the gameport IO address range 0x200..0x207 for (unsigned addr=0x200; addr<0x208; addr++) { DEV_register_ioread_handler(this, read_handler, addr, "Gameport", 1); DEV_register_iowrite_handler(this, write_handler, addr, "Gameport", 1); } // always enabled unless controlled by external device BX_GAMEPORT_THIS enabled = 1; BX_GAMEPORT_THIS port = 0xf0; BX_GAMEPORT_THIS write_usec = 0; BX_GAMEPORT_THIS timer_x = 0; BX_GAMEPORT_THIS timer_y = 0; #ifdef __linux__ BX_GAMEPORT_THIS joyfd = open("/dev/input/js0", O_RDONLY); if (BX_GAMEPORT_THIS joyfd >= 0) { for (unsigned i=0; i<4; i++) poll_joydev(); } #elif defined(WIN32) JOYINFO joypos; if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) { BX_GAMEPORT_THIS joyfd = 1; } else { BX_GAMEPORT_THIS joyfd = -1; } #else BX_GAMEPORT_THIS joyfd = -1; #endif } void bx_gameport_c::reset(unsigned type) { // nothing for now } void bx_gameport_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "gameport", "Gameport State"); BXRS_PARAM_BOOL(list, enabled, BX_GAMEPORT_THIS enabled); BXRS_HEX_PARAM_FIELD(list, port, BX_GAMEPORT_THIS port); BXRS_DEC_PARAM_FIELD(list, delay_x, BX_GAMEPORT_THIS delay_x); BXRS_DEC_PARAM_FIELD(list, delay_y, BX_GAMEPORT_THIS delay_y); BXRS_PARAM_BOOL(list, timer_x, BX_GAMEPORT_THIS timer_x); BXRS_PARAM_BOOL(list, timer_y, BX_GAMEPORT_THIS timer_y); BXRS_DEC_PARAM_FIELD(list, write_usec, BX_GAMEPORT_THIS write_usec); } void bx_gameport_c::poll_joydev(void) { #ifdef __linux__ struct js_event e; fd_set joyfds; struct timeval tv; memset(&tv, 0, sizeof(tv)); FD_ZERO(&joyfds); FD_SET(BX_GAMEPORT_THIS joyfd, &joyfds); e.type = 0; if (select(BX_GAMEPORT_THIS joyfd+1, &joyfds, NULL, NULL, &tv)) { read(BX_GAMEPORT_THIS joyfd, &e, sizeof(struct js_event)); if (e.type & JS_EVENT_BUTTON) { if (e.value == 1) { BX_GAMEPORT_THIS port &= ~(0x10 << e.number); } else { BX_GAMEPORT_THIS port |= (0x10 << e.number); } } if (e.type & JS_EVENT_AXIS) { if (e.number == 0) { BX_GAMEPORT_THIS delay_x = 25 + ((e.value + 0x8000) / 60); } if (e.number == 1) { BX_GAMEPORT_THIS delay_y = 25 + ((e.value + 0x8000) / 62); } } } #elif defined(WIN32) JOYINFO joypos; if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) { if (joypos.wButtons & JOY_BUTTON1) { BX_GAMEPORT_THIS port &= ~0x10; } else { BX_GAMEPORT_THIS port |= 0x10; } if (joypos.wButtons & JOY_BUTTON2) { BX_GAMEPORT_THIS port &= ~0x20; } else { BX_GAMEPORT_THIS port |= 0x20; } BX_GAMEPORT_THIS delay_x = 25 + (joypos.wXpos / 60); BX_GAMEPORT_THIS delay_y = 25 + (joypos.wYpos / 60); } #endif } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_gameport_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_GAMEPORT_SMF bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_gameport_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_GAMEPORT_SMF Bit64u usec; if (BX_GAMEPORT_THIS enabled) { if (BX_GAMEPORT_THIS joyfd >= 0) { poll_joydev(); usec = bx_pc_system.time_usec(); if (BX_GAMEPORT_THIS timer_x) { if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_x) { BX_GAMEPORT_THIS port &= 0xfe; BX_GAMEPORT_THIS timer_x = 0; } } if (BX_GAMEPORT_THIS timer_y) { if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_y) { BX_GAMEPORT_THIS port &= 0xfd; BX_GAMEPORT_THIS timer_y = 0; } } } else { BX_DEBUG(("read: joystick not present")); } return BX_GAMEPORT_THIS port; } else { BX_DEBUG(("read: gameport disabled")); return 0xff; } } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_gameport_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_GAMEPORT_SMF bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_gameport_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_GAMEPORT_SMF if (BX_GAMEPORT_THIS enabled) { BX_GAMEPORT_THIS write_usec = bx_pc_system.time_usec(); BX_GAMEPORT_THIS timer_x = 1; BX_GAMEPORT_THIS timer_y = 1; BX_GAMEPORT_THIS port |= 0x0f; } else { BX_DEBUG(("write: gameport disabled")); } } bochs-2.6/iodev/svga_cirrus.cc0000644000175000017500000034214012020641505016300 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: svga_cirrus.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (c) 2004 Makoto Suzuki (suzu) // Volker Ruppert (vruppert) // Robin Kay (komadori) // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // limited PCI/ISA CLGD5446 support for Bochs // // there are still many unimplemented features: // // - destination write mask support is not complete (bit 5..6) // - BLT mode extension support is not complete (bit 3..4) // - 4bpp modes // // some codes are copied from vga.cc and modified. // some codes are ported from the cirrus emulation in qemu // (http://savannah.nongnu.org/projects/qemu). #define BX_PLUGGABLE #include "iodev.h" #include "vgacore.h" #include "svga_cirrus.h" #include "virt_timer.h" #if BX_SUPPORT_CLGD54XX // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, do nothing. #define SET_TILE_UPDATED(xtile, ytile, value) \ do { \ if (((xtile) < BX_CIRRUS_THIS s.num_x_tiles) && ((ytile) < BX_CIRRUS_THIS s.num_y_tiles)) \ BX_CIRRUS_THIS s.vga_tile_updated[(xtile)+(ytile)*BX_CIRRUS_THIS s.num_x_tiles] = value; \ } while (0) // Only reference the array if the tile numbers are within the bounds // of the array. If out of bounds, return 0. #define GET_TILE_UPDATED(xtile,ytile) \ ((((xtile) < BX_CIRRUS_THIS s.num_x_tiles) && ((ytile) < BX_CIRRUS_THIS s.num_y_tiles))? \ BX_CIRRUS_THIS s.vga_tile_updated[(xtile)+(ytile)*BX_CIRRUS_THIS s.num_x_tiles] \ : 0) #define LOG_THIS BX_CIRRUS_THIS #if BX_USE_CIRRUS_SMF #define VGA_READ(addr,len) bx_vgacore_c::read_handler(theSvga,addr,len) #define VGA_WRITE(addr,val,len) bx_vgacore_c::write_handler(theSvga,addr,val,len) #define SVGA_READ(addr,len) svga_read_handler(theSvga,addr,len) #define SVGA_WRITE(addr,val,len) svga_write_handler(theSvga,addr,val,len) #else #define VGA_READ(addr,len) bx_vgacore_c::read(addr,len) #define VGA_WRITE(addr,val,len) bx_vgacore_c::write(addr,val,len) #define SVGA_READ(addr,len) svga_read(addr,len) #define SVGA_WRITE(addr,val,len) svga_write(addr,val,len) #endif // BX_USE_CIRRUS_SMF #define ID_CLGD5428 (0x26<<2) #define ID_CLGD5430 (0x28<<2) #define ID_CLGD5434 (0x2A<<2) #define ID_CLGD5446 (0x2E<<2) // sequencer 0x07 #define CIRRUS_SR7_BPP_VGA 0x00 #define CIRRUS_SR7_BPP_SVGA 0x01 #define CIRRUS_SR7_BPP_MASK 0x0e #define CIRRUS_SR7_BPP_8 0x00 #define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02 #define CIRRUS_SR7_BPP_24 0x04 #define CIRRUS_SR7_BPP_16 0x06 #define CIRRUS_SR7_BPP_32 0x08 #define CIRRUS_SR7_ISAADDR_MASK 0xe0 // sequencer 0x0f #define CIRRUS_MEMSIZE_512k 0x08 #define CIRRUS_MEMSIZE_1M 0x10 #define CIRRUS_MEMSIZE_2M 0x18 #define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled. // sequencer 0x12 #define CIRRUS_CURSOR_SHOW 0x01 #define CIRRUS_CURSOR_HIDDENPEL 0x02 #define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear // sequencer 0x17 #define CIRRUS_BUSTYPE_VLBFAST 0x10 #define CIRRUS_BUSTYPE_PCI 0x20 #define CIRRUS_BUSTYPE_VLBSLOW 0x30 #define CIRRUS_BUSTYPE_ISA 0x38 #define CIRRUS_MMIO_ENABLE 0x04 #define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared. #define CIRRUS_MEMSIZEEXT_DOUBLE 0x80 // control 0x0b #define CIRRUS_BANKING_DUAL 0x01 #define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k // control 0x30 #define CIRRUS_BLTMODE_BACKWARDS 0x01 #define CIRRUS_BLTMODE_MEMSYSDEST 0x02 #define CIRRUS_BLTMODE_MEMSYSSRC 0x04 #define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 #define CIRRUS_BLTMODE_PATTERNCOPY 0x40 #define CIRRUS_BLTMODE_COLOREXPAND 0x80 #define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 #define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 #define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 #define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 #define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 // control 0x31 #define CIRRUS_BLT_BUSY 0x01 #define CIRRUS_BLT_START 0x02 #define CIRRUS_BLT_RESET 0x04 #define CIRRUS_BLT_FIFOUSED 0x10 #define CIRRUS_BLT_AUTOSTART 0x80 // control 0x32 #define CIRRUS_ROP_0 0x00 #define CIRRUS_ROP_SRC_AND_DST 0x05 #define CIRRUS_ROP_NOP 0x06 #define CIRRUS_ROP_SRC_AND_NOTDST 0x09 #define CIRRUS_ROP_NOTDST 0x0b #define CIRRUS_ROP_SRC 0x0d #define CIRRUS_ROP_1 0x0e #define CIRRUS_ROP_NOTSRC_AND_DST 0x50 #define CIRRUS_ROP_SRC_XOR_DST 0x59 #define CIRRUS_ROP_SRC_OR_DST 0x6d #define CIRRUS_ROP_NOTSRC_AND_NOTDST 0x90 #define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 #define CIRRUS_ROP_SRC_OR_NOTDST 0xad #define CIRRUS_ROP_NOTSRC 0xd0 #define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 #define CIRRUS_ROP_NOTSRC_OR_NOTDST 0xda // control 0x33 #define CIRRUS_BLTMODEEXT_SYNCDISPSWITCH 0x10 // unimplemented #define CIRRUS_BLTMODEEXT_BKGNDONLYCLIP 0x08 // unimplemented #define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 #define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02 #define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 #define CLGD543x_MMIO_BLTBGCOLOR 0x00 // dword #define CLGD543x_MMIO_BLTFGCOLOR 0x04 // dword #define CLGD543x_MMIO_BLTWIDTH 0x08 // word #define CLGD543x_MMIO_BLTHEIGHT 0x0a // word #define CLGD543x_MMIO_BLTDESTPITCH 0x0c // word #define CLGD543x_MMIO_BLTSRCPITCH 0x0e // word #define CLGD543x_MMIO_BLTDESTADDR 0x10 // dword #define CLGD543x_MMIO_BLTSRCADDR 0x14 // dword #define CLGD543x_MMIO_BLTWRITEMASK 0x17 // byte #define CLGD543x_MMIO_BLTMODE 0x18 // byte #define CLGD543x_MMIO_BLTROP 0x1a // byte #define CLGD543x_MMIO_BLTMODEEXT 0x1b // byte #define CLGD543x_MMIO_BLTTRANSPARENTCOLOR 0x1c // word? #define CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word? #define CLGD543x_MMIO_BLTSTATUS 0x40 // byte // PCI 0x00: vendor, 0x02: device #define PCI_VENDOR_CIRRUS 0x1013 #define PCI_DEVICE_CLGD5430 0x00a0 // CLGD5430 or CLGD5440 #define PCI_DEVICE_CLGD5434 0x00a8 #define PCI_DEVICE_CLGD5436 0x00ac #define PCI_DEVICE_CLGD5446 0x00b8 #define PCI_DEVICE_CLGD5462 0x00d0 #define PCI_DEVICE_CLGD5465 0x00d6 // PCI 0x04: command(word), 0x06(word): status #define PCI_COMMAND_IOACCESS 0x0001 #define PCI_COMMAND_MEMACCESS 0x0002 #define PCI_COMMAND_BUSMASTER 0x0004 #define PCI_COMMAND_SPECIALCYCLE 0x0008 #define PCI_COMMAND_MEMWRITEINVALID 0x0010 #define PCI_COMMAND_PALETTESNOOPING 0x0020 #define PCI_COMMAND_PARITYDETECTION 0x0040 #define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080 #define PCI_COMMAND_SERR 0x0100 #define PCI_COMMAND_BACKTOBACKTRANS 0x0200 // PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev) #define PCI_CLASS_BASE_DISPLAY 0x03 // PCI 0x08, 0x00ff0000 #define PCI_CLASS_SUB_VGA 0x00 // PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test) #define PCI_CLASS_HEADERTYPE_00h 0x00 // 0x10-0x3f (headertype 00h) // PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers // 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x) #define PCI_MAP_MEM 0x0 #define PCI_MAP_IO 0x1 #define PCI_MAP_MEM_ADDR_MASK (~0xf) #define PCI_MAP_IO_ADDR_MASK (~0x3) #define PCI_MAP_MEMFLAGS_32BIT 0x0 #define PCI_MAP_MEMFLAGS_32BIT_1M 0x1 #define PCI_MAP_MEMFLAGS_64BIT 0x4 #define PCI_MAP_MEMFLAGS_CACHEABLE 0x8 // PCI 0x28: cardbus CIS pointer // PCI 0x2c: subsystem vendor id, 0x2e: subsystem id // PCI 0x30: expansion ROM base address // PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer // PCI 0x38: reserved // PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat // PCI 0x40-0xff: device dependent fields // default PnP memory and memory-mapped I/O sizes #define CIRRUS_PNPMEM_SIZE CIRRUS_VIDEO_MEMORY_BYTES #define CIRRUS_PNPMMIO_SIZE 0x1000 static bx_svga_cirrus_c *theSvga = NULL; int libsvga_cirrus_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theSvga = new bx_svga_cirrus_c(); bx_devices.pluginVgaDevice = theSvga; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSvga, BX_PLUGIN_CIRRUS); return 0; // Success } else { return -1; } } void libsvga_cirrus_LTX_plugin_fini(void) { delete theSvga; } bx_svga_cirrus_c::bx_svga_cirrus_c() : bx_vgacore_c() { // nothing else to do } bx_svga_cirrus_c::~bx_svga_cirrus_c() { SIM->get_bochs_root()->remove("svga_cirrus"); BX_DEBUG(("Exit")); } void bx_svga_cirrus_c::init_vga_extension(void) { if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) { BX_CIRRUS_THIS put("cirrus", "CLVGA"); // initialize SVGA stuffs. BX_CIRRUS_THIS bx_vgacore_c::init_iohandlers(svga_read_handler, svga_write_handler); BX_CIRRUS_THIS bx_vgacore_c::init_systemtimer(svga_timer_handler, svga_param_handler); BX_CIRRUS_THIS pci_enabled = DEV_is_pci_device("cirrus"); BX_CIRRUS_THIS svga_init_members(); #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { BX_CIRRUS_THIS svga_init_pcihandlers(); BX_INFO(("CL-GD5446 PCI initialized")); } else #endif { BX_INFO(("CL-GD5430 ISA initialized")); } BX_CIRRUS_THIS s.max_xres = 1600; BX_CIRRUS_THIS s.max_yres = 1200; BX_CIRRUS_THIS extension_init = 1; } else { BX_CIRRUS_THIS sequencer.reg[0x07] = 0x00; // Cirrus extension disabled // initialize VGA extension, read/write handlers and timer BX_CIRRUS_THIS bx_vgacore_c::init_vga_extension(); } #if BX_DEBUGGER // register device for the 'info device' command (calls debug_dump()) bx_dbg_register_debug_info("cirrus", this); #endif } void bx_svga_cirrus_c::svga_init_members() { unsigned i; // clear all registers. BX_CIRRUS_THIS sequencer.index = CIRRUS_SEQENCER_MAX + 1; for (i = 0; i <= CIRRUS_SEQENCER_MAX; i++) BX_CIRRUS_THIS sequencer.reg[i] = 0x00; BX_CIRRUS_THIS control.index = CIRRUS_CONTROL_MAX + 1; for (i = 0; i <= CIRRUS_CONTROL_MAX; i++) BX_CIRRUS_THIS control.reg[i] = 0x00; BX_CIRRUS_THIS control.shadow_reg0 = 0x00; BX_CIRRUS_THIS control.shadow_reg1 = 0x00; BX_CIRRUS_THIS crtc.index = CIRRUS_CRTC_MAX + 1; for (i = 0; i <= CIRRUS_CRTC_MAX; i++) BX_CIRRUS_THIS crtc.reg[i] = 0x00; BX_CIRRUS_THIS hidden_dac.lockindex = 0; BX_CIRRUS_THIS hidden_dac.data = 0x00; BX_CIRRUS_THIS svga_unlock_special = 0; BX_CIRRUS_THIS svga_needs_update_tile = 1; BX_CIRRUS_THIS svga_needs_update_dispentire = 1; BX_CIRRUS_THIS svga_needs_update_mode = 0; BX_CIRRUS_THIS svga_xres = 640; BX_CIRRUS_THIS svga_yres = 480; BX_CIRRUS_THIS svga_bpp = 8; BX_CIRRUS_THIS svga_pitch = 640; BX_CIRRUS_THIS bank_base[0] = 0; BX_CIRRUS_THIS bank_base[1] = 0; BX_CIRRUS_THIS bank_limit[0] = 0; BX_CIRRUS_THIS bank_limit[1] = 0; svga_reset_bitblt(); BX_CIRRUS_THIS hw_cursor.x = 0; BX_CIRRUS_THIS hw_cursor.y = 0; BX_CIRRUS_THIS hw_cursor.size = 0; // memory allocation. if (BX_CIRRUS_THIS s.memory == NULL) BX_CIRRUS_THIS s.memory = new Bit8u[CIRRUS_VIDEO_MEMORY_BYTES]; // set some registers. BX_CIRRUS_THIS sequencer.reg[0x06] = 0x0f; BX_CIRRUS_THIS sequencer.reg[0x07] = 0x00; // 0xf0:linearbase(0x00 if disabled) #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { BX_CIRRUS_THIS svga_unlock_special = 1; BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5446; BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x2d; // MemClock BX_CIRRUS_THIS control.reg[0x18] = 0x0f; BX_CIRRUS_THIS sequencer.reg[0x0F] = 0x98; BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_PCI; BX_CIRRUS_THIS sequencer.reg[0x15] = 0x04; // memory size 4MB BX_CIRRUS_THIS s.memsize = (4 << 20); } else #endif { BX_CIRRUS_THIS crtc.reg[0x27] = ID_CLGD5430; BX_CIRRUS_THIS sequencer.reg[0x1F] = 0x22; // MemClock BX_CIRRUS_THIS sequencer.reg[0x0F] = CIRRUS_MEMSIZE_2M; BX_CIRRUS_THIS sequencer.reg[0x17] = CIRRUS_BUSTYPE_ISA; BX_CIRRUS_THIS sequencer.reg[0x15] = 0x03; // memory size 2MB BX_CIRRUS_THIS s.memsize = (2 << 20); } BX_CIRRUS_THIS hidden_dac.lockindex = 5; BX_CIRRUS_THIS hidden_dac.data = 0; memset(BX_CIRRUS_THIS s.memory, 0xff, CIRRUS_VIDEO_MEMORY_BYTES); BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS s.memory; } void bx_svga_cirrus_c::reset(unsigned type) { // reset VGA stuffs. BX_CIRRUS_THIS bx_vgacore_c::reset(type); if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) { // reset SVGA stuffs. BX_CIRRUS_THIS svga_init_members(); } } void bx_svga_cirrus_c::register_state(void) { unsigned i; char name[6]; bx_list_c *reg; if (!strcmp(SIM->get_param_string(BXPN_VGA_EXTENSION)->getptr(), "cirrus")) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "svga_cirrus", "Cirrus SVGA State"); bx_vgacore_c::register_state(list); bx_list_c *crtc = new bx_list_c(list, "crtc"); new bx_shadow_num_c(crtc, "index", &BX_CIRRUS_THIS crtc.index, BASE_HEX); reg = new bx_list_c(crtc, "reg"); for (i=0; i<=CIRRUS_CRTC_MAX; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS crtc.reg[i], BASE_HEX); } bx_list_c *sequ = new bx_list_c(list, "sequencer"); new bx_shadow_num_c(sequ, "index", &BX_CIRRUS_THIS sequencer.index, BASE_HEX); reg = new bx_list_c(sequ, "reg"); for (i=0; i<=CIRRUS_SEQENCER_MAX; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS sequencer.reg[i], BASE_HEX); } bx_list_c *ctrl = new bx_list_c(list, "control"); new bx_shadow_num_c(ctrl, "index", &BX_CIRRUS_THIS control.index, BASE_HEX); reg = new bx_list_c(ctrl, "reg"); for (i=0; i<=CIRRUS_CONTROL_MAX; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS control.reg[i], BASE_HEX); } new bx_shadow_num_c(ctrl, "shadow_reg0", &BX_CIRRUS_THIS control.shadow_reg0, BASE_HEX); new bx_shadow_num_c(ctrl, "shadow_reg1", &BX_CIRRUS_THIS control.shadow_reg1, BASE_HEX); bx_list_c *hdac = new bx_list_c(list, "hidden_dac"); new bx_shadow_num_c(hdac, "lockindex", &BX_CIRRUS_THIS hidden_dac.lockindex, BASE_HEX); new bx_shadow_num_c(hdac, "data", &BX_CIRRUS_THIS hidden_dac.data, BASE_HEX); reg = new bx_list_c(hdac, "palette"); for (i=0; i<48; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(reg, name, &BX_CIRRUS_THIS hidden_dac.palette[i], BASE_HEX); } new bx_shadow_bool_c(list, "svga_unlock_special", &BX_CIRRUS_THIS svga_unlock_special); new bx_shadow_num_c(list, "svga_xres", &BX_CIRRUS_THIS svga_xres); new bx_shadow_num_c(list, "svga_yres", &BX_CIRRUS_THIS svga_yres); new bx_shadow_num_c(list, "svga_pitch", &BX_CIRRUS_THIS svga_pitch); new bx_shadow_num_c(list, "svga_bpp", &BX_CIRRUS_THIS svga_bpp); new bx_shadow_num_c(list, "svga_dispbpp", &BX_CIRRUS_THIS svga_dispbpp); new bx_shadow_num_c(list, "bank_base0", &BX_CIRRUS_THIS bank_base[0], BASE_HEX); new bx_shadow_num_c(list, "bank_base1", &BX_CIRRUS_THIS bank_base[1], BASE_HEX); new bx_shadow_num_c(list, "bank_limit0", &BX_CIRRUS_THIS bank_limit[0], BASE_HEX); new bx_shadow_num_c(list, "bank_limit1", &BX_CIRRUS_THIS bank_limit[1], BASE_HEX); bx_list_c *cursor = new bx_list_c(list, "hw_cursor"); new bx_shadow_num_c(cursor, "x", &BX_CIRRUS_THIS hw_cursor.x, BASE_HEX); new bx_shadow_num_c(cursor, "y", &BX_CIRRUS_THIS hw_cursor.y, BASE_HEX); new bx_shadow_num_c(cursor, "size", &BX_CIRRUS_THIS hw_cursor.size, BASE_HEX); #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { register_pci_state(list); } #endif } } void bx_svga_cirrus_c::after_restore_state(void) { if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { BX_CIRRUS_THIS bx_vgacore_c::after_restore_state(); } else { #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[0], &BX_CIRRUS_THIS pci_conf[0x10], 0x2000000)) { BX_INFO(("new pci_memaddr: 0x%04x", BX_CIRRUS_THIS pci_base_address[0])); } if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[1], &BX_CIRRUS_THIS pci_conf[0x14], CIRRUS_PNPMMIO_SIZE)) { BX_INFO(("new pci_mmioaddr = 0x%08x", BX_CIRRUS_THIS pci_base_address[1])); } if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_rom_address, &BX_CIRRUS_THIS pci_conf[0x30], BX_CIRRUS_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_CIRRUS_THIS pci_rom_address)); } } #endif for (unsigned i=0; i<256; i++) { bx_gui->palette_change(i, BX_CIRRUS_THIS s.pel.data[i].red<<2, BX_CIRRUS_THIS s.pel.data[i].green<<2, BX_CIRRUS_THIS s.pel.data[i].blue<<2); } BX_CIRRUS_THIS svga_needs_update_mode = 1; BX_CIRRUS_THIS svga_update(); } } void bx_svga_cirrus_c::redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height) { unsigned xti, yti, xt0, xt1, yt0, yt1; if ((width == 0) || (height == 0)) { return; } if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { BX_CIRRUS_THIS bx_vgacore_c::redraw_area(x0,y0,width,height); return; } if (BX_CIRRUS_THIS svga_needs_update_mode) { return; } BX_CIRRUS_THIS svga_needs_update_tile = 1; xt0 = x0 / X_TILESIZE; yt0 = y0 / Y_TILESIZE; if (x0 < BX_CIRRUS_THIS svga_xres) { xt1 = (x0 + width - 1) / X_TILESIZE; } else { xt1 = (BX_CIRRUS_THIS svga_xres - 1) / X_TILESIZE; } if (y0 < BX_CIRRUS_THIS svga_yres) { yt1 = (y0 + height - 1) / Y_TILESIZE; } else { yt1 = (BX_CIRRUS_THIS svga_yres - 1) / Y_TILESIZE; } for (yti=yt0; yti<=yt1; yti++) { for (xti=xt0; xti<=xt1; xti++) { SET_TILE_UPDATED (xti, yti, 1); } } } void bx_svga_cirrus_c::mem_write_mode4and5_8bpp(Bit8u mode, Bit32u offset, Bit8u value) { Bit8u val = value; Bit8u *dst; dst = BX_CIRRUS_THIS s.memory + offset; for (int x = 0; x < 8; x++) { if (val & 0x80) { *dst = BX_CIRRUS_THIS control.shadow_reg1; } else if (mode == 5) { *dst = BX_CIRRUS_THIS control.shadow_reg0; } val <<= 1; dst++; } } void bx_svga_cirrus_c::mem_write_mode4and5_16bpp(Bit8u mode, Bit32u offset, Bit8u value) { Bit8u val = value; Bit8u *dst; dst = BX_CIRRUS_THIS s.memory + offset; for (int x = 0; x < 8; x++) { if (val & 0x80) { *dst = BX_CIRRUS_THIS control.shadow_reg1; *(dst + 1) = BX_CIRRUS_THIS control.reg[0x11]; } else if (mode == 5) { *dst = BX_CIRRUS_THIS control.shadow_reg0; *(dst + 1) = BX_CIRRUS_THIS control.reg[0x10]; } val <<= 1; dst += 2; } } #if BX_SUPPORT_PCI bx_bool bx_svga_cirrus_c::cirrus_mem_read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { *data_ptr = BX_CIRRUS_THIS mem_read(addr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } #endif Bit8u bx_svga_cirrus_c::mem_read(bx_phy_address addr) { #if BX_SUPPORT_PCI if ((BX_CIRRUS_THIS pci_enabled) && (BX_CIRRUS_THIS pci_rom_size > 0)) { Bit32u mask = (BX_CIRRUS_THIS pci_rom_size - 1); if ((addr & ~mask) == BX_CIRRUS_THIS pci_rom_address) { if (BX_CIRRUS_THIS pci_conf[0x30] & 0x01) { return BX_CIRRUS_THIS pci_rom[addr & mask]; } else { return 0xff; } } } #endif if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { return BX_CIRRUS_THIS bx_vgacore_c::mem_read(addr); } #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if ((addr >= BX_CIRRUS_THIS pci_base_address[0]) && (addr < (BX_CIRRUS_THIS pci_base_address[0] + CIRRUS_PNPMEM_SIZE))) { Bit8u *ptr; Bit32u offset = addr & (BX_CIRRUS_THIS s.memsize - 1); if ((offset >= (BX_CIRRUS_THIS s.memsize - 256)) && ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x44)) { return svga_mmio_blt_read(offset & 0xff); } // video-to-cpu BLT if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) { BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } if (!svga_asyncbitblt_next()) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } } ptr = BX_CIRRUS_THIS s.memory; if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= (BX_CIRRUS_THIS s.memsize - 1); return *(ptr + offset); } else if ((addr >= BX_CIRRUS_THIS pci_base_address[1]) && (addr < (BX_CIRRUS_THIS pci_base_address[1] + CIRRUS_PNPMMIO_SIZE))) { Bit32u offset = addr & (CIRRUS_PNPMMIO_SIZE - 1); if (offset >= 0x100) { return svga_mmio_blt_read(offset - 0x100); } else { return svga_mmio_vga_read(offset); } } } #endif // BX_SUPPORT_PCI if (addr >= 0xA0000 && addr <= 0xAFFFF) { Bit32u bank; Bit32u offset; Bit8u *ptr; // video-to-cpu BLT if (BX_CIRRUS_THIS bitblt.memdst_needed != 0) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; if (ptr != BX_CIRRUS_THIS bitblt.memdst_endptr) { BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } if (!svga_asyncbitblt_next()) { ptr = BX_CIRRUS_THIS bitblt.memdst_ptr; BX_CIRRUS_THIS bitblt.memdst_ptr ++; return *ptr; } } offset = addr & 0xffff; bank = (offset >> 15); offset &= 0x7fff; if (offset < bank_limit[bank]) { offset += bank_base[bank]; if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= (BX_CIRRUS_THIS s.memsize - 1); return *(BX_CIRRUS_THIS s.memory + offset); } else { return 0xff; } } else if (addr >= 0xB8000 && addr <= 0xB8100) { // memory-mapped I/O. Bit32u offset = (Bit32u) (addr - 0xb8000); if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) return svga_mmio_blt_read(offset); } else { BX_DEBUG(("mem_read 0x%08x", (Bit32u)addr)); } return 0xff; } #if BX_SUPPORT_PCI bx_bool bx_svga_cirrus_c::cirrus_mem_write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit8u *data_ptr; #ifdef BX_LITTLE_ENDIAN data_ptr = (Bit8u *) data; #else // BX_BIG_ENDIAN data_ptr = (Bit8u *) data + (len - 1); #endif for (unsigned i = 0; i < len; i++) { BX_CIRRUS_THIS mem_write(addr, *data_ptr); addr++; #ifdef BX_LITTLE_ENDIAN data_ptr++; #else // BX_BIG_ENDIAN data_ptr--; #endif } return 1; } #endif void bx_svga_cirrus_c::mem_write(bx_phy_address addr, Bit8u value) { if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { BX_CIRRUS_THIS bx_vgacore_c::mem_write(addr,value); return; } #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if ((addr >= BX_CIRRUS_THIS pci_base_address[0]) && (addr < (BX_CIRRUS_THIS pci_base_address[0] + CIRRUS_PNPMEM_SIZE))) { Bit32u offset = addr & (BX_CIRRUS_THIS s.memsize - 1); if ((offset >= (BX_CIRRUS_THIS s.memsize - 256)) && ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x44)) { svga_mmio_blt_write(addr & 0xff, value); return; } // cpu-to-video BLT if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value); if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) { svga_asyncbitblt_next(); } return; } // BX_DEBUG(("write offset 0x%08x,value 0x%02x",offset,value)); if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= (BX_CIRRUS_THIS s.memsize - 1); Bit8u mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07; if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) { *(BX_CIRRUS_THIS s.memory + offset) = value; } else { if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) { mem_write_mode4and5_8bpp(mode, offset, value); } else { mem_write_mode4and5_16bpp(mode, offset, value); } } BX_CIRRUS_THIS svga_needs_update_tile = 1; SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE, (offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1); return; } else if ((addr >= BX_CIRRUS_THIS pci_base_address[1]) && (addr < (BX_CIRRUS_THIS pci_base_address[1] + CIRRUS_PNPMMIO_SIZE))) { // memory-mapped I/O. // BX_DEBUG(("write mmio 0x%08x",addr)); Bit32u offset = addr & (CIRRUS_PNPMMIO_SIZE - 1); if (offset >= 0x100) { svga_mmio_blt_write(offset - 0x100, value); } else { svga_mmio_vga_write(offset,value); } return; } } #endif // BX_SUPPORT_PCI if (addr >= 0xA0000 && addr <= 0xAFFFF) { Bit32u bank, offset; Bit8u mode; // cpu-to-video BLT if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { *(BX_CIRRUS_THIS bitblt.memsrc_ptr)++ = (value); if (BX_CIRRUS_THIS bitblt.memsrc_ptr >= BX_CIRRUS_THIS bitblt.memsrc_endptr) { svga_asyncbitblt_next(); } return; } offset = addr & 0xffff; bank = (offset >> 15); offset &= 0x7fff; if (offset < bank_limit[bank]) { offset += bank_base[bank]; if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) == 0x14) { offset <<= 4; } else if (BX_CIRRUS_THIS control.reg[0x0b] & 0x02) { offset <<= 3; } offset &= (BX_CIRRUS_THIS s.memsize - 1); mode = BX_CIRRUS_THIS control.reg[0x05] & 0x07; if ((mode < 4) || (mode > 5) || ((BX_CIRRUS_THIS control.reg[0x0b] & 0x4) == 0)) { *(BX_CIRRUS_THIS s.memory + offset) = value; } else { if ((BX_CIRRUS_THIS control.reg[0x0b] & 0x14) != 0x14) { mem_write_mode4and5_8bpp(mode, offset, value); } else { mem_write_mode4and5_16bpp(mode, offset, value); } } BX_CIRRUS_THIS svga_needs_update_tile = 1; SET_TILE_UPDATED(((offset % BX_CIRRUS_THIS svga_pitch) / (BX_CIRRUS_THIS svga_bpp / 8)) / X_TILESIZE, (offset / BX_CIRRUS_THIS svga_pitch) / Y_TILESIZE, 1); } } else if (addr >= 0xB8000 && addr < 0xB8100) { // memory-mapped I/O. Bit32u offset = (Bit32u) (addr - 0xb8000); if ((BX_CIRRUS_THIS sequencer.reg[0x17] & 0x44) == 0x04) { svga_mmio_blt_write(offset & 0xff, value); } } else { BX_DEBUG(("mem_write 0x%08x, value 0x%02x", (Bit32u)addr, value)); } } int bx_svga_cirrus_c::get_snapshot_mode() { if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { return BX_CIRRUS_THIS bx_vgacore_c::get_snapshot_mode(); } else { return BX_GUI_SNAPSHOT_GFX; } } void bx_svga_cirrus_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, unsigned *txWidth) { BX_CIRRUS_THIS bx_vgacore_c::get_text_snapshot(text_snapshot,txHeight,txWidth); } Bit32u bx_svga_cirrus_c::get_gfx_snapshot(Bit8u **snapshot_ptr, Bit8u **palette_ptr, unsigned *iHeight, unsigned *iWidth, unsigned *iDepth) { Bit32u len, len1; unsigned i; Bit8u *dst_ptr, *src_ptr; if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) != CIRRUS_SR7_BPP_VGA) { *iHeight = BX_CIRRUS_THIS svga_yres; *iWidth = BX_CIRRUS_THIS svga_xres; *iDepth = BX_CIRRUS_THIS svga_dispbpp; len1 = BX_CIRRUS_THIS svga_xres * (BX_CIRRUS_THIS svga_bpp >> 3); len = len1 * BX_CIRRUS_THIS svga_yres; *snapshot_ptr = (Bit8u*)malloc(len); if (snapshot_ptr == NULL) return 0; src_ptr = BX_CIRRUS_THIS disp_ptr; dst_ptr = *snapshot_ptr; for (i = 0; i < BX_CIRRUS_THIS svga_yres; i++) { memcpy(dst_ptr, src_ptr, len1); src_ptr += BX_CIRRUS_THIS svga_pitch; dst_ptr += len1; } if (*iDepth == 8) { BX_CIRRUS_THIS get_dac_palette(palette_ptr, 2); } return len; } else { return BX_CIRRUS_THIS bx_vgacore_c::get_gfx_snapshot(snapshot_ptr, palette_ptr, iHeight, iWidth, iDepth); } } Bit64s bx_svga_cirrus_c::svga_param_handler(bx_param_c *param, int set, Bit64s val) { Bit32u interval; if (set) { interval = (Bit32u)(1000000 / val); BX_INFO(("Changing timer interval to %d", interval)); BX_CIRRUS_THIS svga_timer_handler(theSvga); bx_virt_timer.activate_timer(BX_CIRRUS_THIS timer_id, interval, 1); if (interval < 300000) { BX_CIRRUS_THIS s.blink_counter = 300000 / (unsigned)interval; } else { BX_CIRRUS_THIS s.blink_counter = 1; } } return val; } Bit32u bx_svga_cirrus_c::svga_read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_CIRRUS_SMF bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr; return class_ptr->svga_read(address, io_len); } Bit32u bx_svga_cirrus_c::svga_read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_CIRRUS_SMF if ((io_len == 2) && ((address & 1) == 0)) { Bit32u value; value = (Bit32u)SVGA_READ(address,1); value |= (Bit32u)SVGA_READ(address+1,1) << 8; return value; } if (io_len != 1) { BX_PANIC(("SVGA read: io_len != 1")); } switch (address) { case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */ case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */ return BX_CIRRUS_THIS crtc.index; case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */ case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */ if (BX_CIRRUS_THIS is_unlocked()) return BX_CIRRUS_THIS svga_read_crtc(address,BX_CIRRUS_THIS crtc.index); break; case 0x03c4: /* VGA: Sequencer Index Register */ if (BX_CIRRUS_THIS is_unlocked()) { Bit32u value = BX_CIRRUS_THIS sequencer.index; if ((value & 0x1e) == 0x10) { /* SR10-F0, SR11-F1 */ if (value & 1) value = ((BX_CIRRUS_THIS hw_cursor.y & 7) << 5) | 0x11; else value = ((BX_CIRRUS_THIS hw_cursor.x & 7) << 5) | 0x10; } return value; } return BX_CIRRUS_THIS sequencer.index; case 0x03c5: /* VGA: Sequencer Registers */ if ((BX_CIRRUS_THIS sequencer.index == 0x06) || (BX_CIRRUS_THIS is_unlocked())) { return BX_CIRRUS_THIS svga_read_sequencer(address,BX_CIRRUS_THIS sequencer.index); } break; case 0x03c6: /* Hidden DAC */ if (BX_CIRRUS_THIS is_unlocked()) { if ((++BX_CIRRUS_THIS hidden_dac.lockindex) == 5) { BX_CIRRUS_THIS hidden_dac.lockindex = 0; return BX_CIRRUS_THIS hidden_dac.data; } } break; case 0x03c8: /* PEL write address */ BX_CIRRUS_THIS hidden_dac.lockindex = 0; break; case 0x03c9: /* PEL Data Register, hiddem pel colors 00..0F */ if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) { Bit8u index = (BX_CIRRUS_THIS s.pel.read_data_register & 0x0f) * 3 + BX_CIRRUS_THIS s.pel.read_data_cycle; Bit8u retval = BX_CIRRUS_THIS hidden_dac.palette[index]; BX_CIRRUS_THIS s.pel.read_data_cycle ++; if (BX_CIRRUS_THIS s.pel.read_data_cycle >= 3) { BX_CIRRUS_THIS s.pel.read_data_cycle = 0; BX_CIRRUS_THIS s.pel.read_data_register++; } return retval; } break; case 0x03ce: /* VGA: Graphics Controller Index Register */ return BX_CIRRUS_THIS control.index; case 0x03cf: /* VGA: Graphics Controller Registers */ if (BX_CIRRUS_THIS is_unlocked()) return BX_CIRRUS_THIS svga_read_control(address,BX_CIRRUS_THIS control.index); break; default: break; } return VGA_READ(address,io_len); } void bx_svga_cirrus_c::svga_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_CIRRUS_SMF bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr; class_ptr->svga_write(address, value, io_len); } void bx_svga_cirrus_c::svga_write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_CIRRUS_SMF if ((io_len == 2) && ((address & 1) == 0)) { SVGA_WRITE(address,value & 0xff,1); SVGA_WRITE(address+1,value >> 8,1); return; } if (io_len != 1) { BX_PANIC(("SVGA write: io_len != 1")); } switch (address) { case 0x03b4: /* VGA: CRTC Index Register (monochrome emulation modes) */ case 0x03d4: /* VGA: CRTC Index Register (color emulation modes) */ BX_CIRRUS_THIS crtc.index = value & 0x7f; break; case 0x03b5: /* VGA: CRTC Registers (monochrome emulation modes) */ case 0x03d5: /* VGA: CRTC Registers (color emulation modes) */ if (BX_CIRRUS_THIS is_unlocked()) { BX_CIRRUS_THIS svga_write_crtc(address,BX_CIRRUS_THIS crtc.index,value); return; } break; case 0x03c4: /* VGA: Sequencer Index Register */ BX_CIRRUS_THIS sequencer.index = value; break; case 0x03c5: /* VGA: Sequencer Registers */ if ((BX_CIRRUS_THIS sequencer.index == 0x06) || (BX_CIRRUS_THIS is_unlocked())) { BX_CIRRUS_THIS svga_write_sequencer(address,BX_CIRRUS_THIS sequencer.index,value); return; } break; case 0x03c6: /* Hidden DAC */ if (BX_CIRRUS_THIS is_unlocked()) { if (BX_CIRRUS_THIS hidden_dac.lockindex == 4) { BX_CIRRUS_THIS hidden_dac.data = value; } BX_CIRRUS_THIS hidden_dac.lockindex = 0; return; } break; case 0x03c9: /* PEL Data Register, hidden pel colors 00..0F */ BX_CIRRUS_THIS svga_needs_update_dispentire = 1; if (BX_CIRRUS_THIS sequencer.reg[0x12] & CIRRUS_CURSOR_HIDDENPEL) { Bit8u index = (BX_CIRRUS_THIS s.pel.write_data_register & 0x0f) * 3 + BX_CIRRUS_THIS s.pel.write_data_cycle; BX_CIRRUS_THIS hidden_dac.palette[index] = value; BX_CIRRUS_THIS s.pel.write_data_cycle ++; if (BX_CIRRUS_THIS s.pel.write_data_cycle >= 3) { BX_CIRRUS_THIS s.pel.write_data_cycle = 0; BX_CIRRUS_THIS s.pel.write_data_register++; } return; } break; case 0x03ce: /* VGA: Graphics Controller Index Register */ BX_CIRRUS_THIS control.index = value; break; case 0x03cf: /* VGA: Graphics Controller Registers */ if (BX_CIRRUS_THIS is_unlocked()) { BX_CIRRUS_THIS svga_write_control(address,BX_CIRRUS_THIS control.index,value); return; } break; default: break; } VGA_WRITE(address,value,io_len); } void bx_svga_cirrus_c::svga_timer_handler(void *this_ptr) { #if !BX_USE_CIRRUS_SMF bx_svga_cirrus_c *class_ptr = (bx_svga_cirrus_c *) this_ptr; class_ptr->svga_timer(); } void bx_svga_cirrus_c::svga_timer(void) { #else // !BX_USE_CIRRUS_SMF UNUSED(this_ptr); #endif // !BX_USE_CIRRUS_SMF BX_CIRRUS_THIS svga_update(); bx_gui->flush(); } void bx_svga_cirrus_c::svga_modeupdate(void) { Bit32u iTopOffset, iWidth, iHeight; Bit8u iBpp, iDispBpp; iTopOffset = (BX_CIRRUS_THIS crtc.reg[0x0c] << 8) + BX_CIRRUS_THIS crtc.reg[0x0d] + ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x01) << 16) + ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x0c) << 15) + ((BX_CIRRUS_THIS crtc.reg[0x1d] & 0x80) << 12); iTopOffset <<= 2; iHeight = 1 + BX_CIRRUS_THIS crtc.reg[0x12] + ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x02) << 7) + ((BX_CIRRUS_THIS crtc.reg[0x07] & 0x40) << 3); if ((BX_CIRRUS_THIS crtc.reg[0x1a] & 0x01) > 0) { iHeight <<= 1; } iWidth = (BX_CIRRUS_THIS crtc.reg[0x01] + 1) * 8; iBpp = 8; iDispBpp = 4; if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x1) == CIRRUS_SR7_BPP_SVGA) { switch (BX_CIRRUS_THIS sequencer.reg[0x07] & CIRRUS_SR7_BPP_MASK) { case CIRRUS_SR7_BPP_8: iBpp = 8; iDispBpp = 8; break; case CIRRUS_SR7_BPP_16_DOUBLEVCLK: case CIRRUS_SR7_BPP_16: iBpp = 16; iDispBpp = (BX_CIRRUS_THIS hidden_dac.data & 0x1) ? 16 : 15; break; case CIRRUS_SR7_BPP_24: iBpp = 24; iDispBpp = 24; break; case CIRRUS_SR7_BPP_32: iBpp = 32; iDispBpp = 32; break; default: BX_PANIC(("unknown bpp - seqencer.reg[0x07] = %02x",BX_CIRRUS_THIS sequencer.reg[0x07])); break; } } if ((iWidth != BX_CIRRUS_THIS svga_xres) || (iHeight != BX_CIRRUS_THIS svga_yres) || (iDispBpp != BX_CIRRUS_THIS svga_dispbpp)) { BX_INFO(("switched to %u x %u x %u", iWidth, iHeight, iDispBpp)); } BX_CIRRUS_THIS svga_xres = iWidth; BX_CIRRUS_THIS svga_yres = iHeight; BX_CIRRUS_THIS svga_bpp = iBpp; BX_CIRRUS_THIS svga_dispbpp = iDispBpp; BX_CIRRUS_THIS disp_ptr = BX_CIRRUS_THIS s.memory + iTopOffset; } void bx_svga_cirrus_c::draw_hardware_cursor(unsigned xc, unsigned yc, bx_svga_tileinfo_t *info) { if (BX_CIRRUS_THIS hw_cursor.size && (xc < (unsigned)(BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size)) && (xc+X_TILESIZE > BX_CIRRUS_THIS hw_cursor.x) && (yc < (unsigned)(BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size)) && (yc+Y_TILESIZE > BX_CIRRUS_THIS hw_cursor.y)) { int i; unsigned w, h, pitch, cx, cy, cx0, cy0, cx1, cy1; Bit8u * tile_ptr, * tile_ptr2; Bit8u * plane0_ptr, *plane0_ptr2; Bit8u * plane1_ptr, *plane1_ptr2; unsigned long fgcol, bgcol; Bit64u plane0, plane1; cx0 = BX_CIRRUS_THIS hw_cursor.x > xc ? BX_CIRRUS_THIS hw_cursor.x : xc; cy0 = BX_CIRRUS_THIS hw_cursor.y > yc ? BX_CIRRUS_THIS hw_cursor.y : yc; cx1 = (unsigned)(BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size) < xc+X_TILESIZE ? BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size : xc+X_TILESIZE; cy1 = (unsigned)(BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size) < yc+Y_TILESIZE ? BX_CIRRUS_THIS hw_cursor.y+BX_CIRRUS_THIS hw_cursor.size : yc+Y_TILESIZE; if (info->bpp == 15) info->bpp = 16; tile_ptr = bx_gui->graphics_tile_get(xc, yc, &w, &h) + info->pitch * (cy0 - yc) + (info->bpp / 8) * (cx0 - xc); plane0_ptr = BX_CIRRUS_THIS s.memory + BX_CIRRUS_THIS s.memsize - 16384; switch (BX_CIRRUS_THIS hw_cursor.size) { case 32: plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3f) * 256; plane1_ptr = plane0_ptr + 128; pitch = 4; break; case 64: plane0_ptr += (BX_CIRRUS_THIS sequencer.reg[0x13] & 0x3c) * 256; plane1_ptr = plane0_ptr + 8; pitch = 16; break; default: BX_ERROR(("unsupported hardware cursor size")); return; break; } if (!info->is_indexed) { fgcol = MAKE_COLOUR( BX_CIRRUS_THIS hidden_dac.palette[45], 6, info->red_shift, info->red_mask, BX_CIRRUS_THIS hidden_dac.palette[46], 6, info->green_shift, info->green_mask, BX_CIRRUS_THIS hidden_dac.palette[47], 6, info->blue_shift, info->blue_mask); bgcol = MAKE_COLOUR( BX_CIRRUS_THIS hidden_dac.palette[0], 6, info->red_shift, info->red_mask, BX_CIRRUS_THIS hidden_dac.palette[1], 6, info->green_shift, info->green_mask, BX_CIRRUS_THIS hidden_dac.palette[2], 6, info->blue_shift, info->blue_mask); } else { // FIXME: this is a hack that works in Windows guests // TODO: compare hidden DAC entries with DAC entries to find nearest match fgcol = 0xff; bgcol = 0x00; } plane0_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y); plane1_ptr += pitch * (cy0 - BX_CIRRUS_THIS hw_cursor.y); for (cy=cy0; cybpp/8) * (cx1 - cx0) - 1; plane0_ptr2 = plane0_ptr; plane1_ptr2 = plane1_ptr; plane0 = plane1 = 0; for (i=0; i>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1; plane1 >>= BX_CIRRUS_THIS hw_cursor.x+BX_CIRRUS_THIS hw_cursor.size - cx1; for (cx=cx0; cxis_little_endian) { for (i=info->bpp-8; i>-8; i-=8) { *(tile_ptr2--) = (Bit8u)(fgcol >> i); } } else { for (i=0; ibpp; i+=8) { *(tile_ptr2--) = (Bit8u)(fgcol >> i); } } } else { for (i=0; ibpp; i+=8) { *(tile_ptr2--) ^= 0xff; } } } else { if (plane1 & 1) { if (info->is_little_endian) { for (i=info->bpp-8; i>-8; i-=8) { *(tile_ptr2--) = (Bit8u)(bgcol >> i); } } else { for (i=0; ibpp; i+=8) { *(tile_ptr2--) = (Bit8u)(bgcol >> i); } } } else { tile_ptr2 -= (info->bpp/8); } } plane0 >>= 1; plane1 >>= 1; } tile_ptr += info->pitch; plane0_ptr += pitch; plane1_ptr += pitch; } } } void bx_svga_cirrus_c::svga_update(void) { unsigned width, height, pitch; /* skip screen update when the sequencer is in reset mode or video is disabled */ if (! BX_CIRRUS_THIS s.sequencer.reset1 || ! BX_CIRRUS_THIS s.sequencer.reset2 || ! BX_CIRRUS_THIS s.attribute_ctrl.video_enabled) { return; } if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_VGA) { if (BX_CIRRUS_THIS svga_needs_update_mode) { BX_CIRRUS_THIS s.vga_mem_updated = 1; BX_CIRRUS_THIS svga_needs_update_mode = 0; } BX_CIRRUS_THIS bx_vgacore_c::update(); return; } else { if (BX_CIRRUS_THIS svga_needs_update_mode) { svga_modeupdate(); } } width = BX_CIRRUS_THIS svga_xres; height = BX_CIRRUS_THIS svga_yres; pitch = BX_CIRRUS_THIS svga_pitch; if (BX_CIRRUS_THIS svga_needs_update_mode) { width = BX_CIRRUS_THIS svga_xres; height = BX_CIRRUS_THIS svga_yres; bx_gui->dimension_update(width, height, 0, 0, BX_CIRRUS_THIS svga_dispbpp); BX_CIRRUS_THIS s.last_bpp = BX_CIRRUS_THIS svga_dispbpp; BX_CIRRUS_THIS svga_needs_update_mode = 0; BX_CIRRUS_THIS svga_needs_update_dispentire = 1; } if (BX_CIRRUS_THIS svga_needs_update_dispentire) { BX_CIRRUS_THIS redraw_area(0,0,width,height); BX_CIRRUS_THIS svga_needs_update_dispentire = 0; } if (!BX_CIRRUS_THIS svga_needs_update_tile) { return; } BX_CIRRUS_THIS svga_needs_update_tile = 0; unsigned xc, yc, xti, yti; unsigned r, c, w, h; int i; Bit8u red, green, blue; Bit32u colour; Bit8u * vid_ptr, * vid_ptr2; Bit8u * tile_ptr, * tile_ptr2; bx_svga_tileinfo_t info; if (bx_gui->graphics_tile_info(&info)) { if (info.is_indexed) { switch (BX_CIRRUS_THIS svga_dispbpp) { case 4: case 15: case 16: case 24: case 32: BX_ERROR(("current guest pixel format is unsupported on indexed colour host displays, svga_dispbpp=%d", BX_CIRRUS_THIS svga_dispbpp)); break; case 8: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; } } else { switch (BX_CIRRUS_THIS svga_dispbpp) { case 4: BX_ERROR(("cannot draw 4bpp SVGA")); break; case 8: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 15: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 16: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 24: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; case 32: for (yc=0, yti = 0; ycgraphics_tile_get(xc, yc, &w, &h); for (r=0; r> i; } } else { for (i=info.bpp-8; i>-8; i-=8) { *(tile_ptr2++) = colour >> i; } } } vid_ptr += pitch; tile_ptr += info.pitch; } draw_hardware_cursor(xc, yc, &info); bx_gui->graphics_tile_update_in_place(xc, yc, w, h); SET_TILE_UPDATED (xti, yti, 0); } } } break; } } } else { BX_PANIC(("cannot get svga tile info")); } } void bx_svga_cirrus_c::update_bank_ptr(Bit8u bank_index) { unsigned offset; unsigned limit; if (BX_CIRRUS_THIS banking_is_dual()) offset = BX_CIRRUS_THIS control.reg[0x09 + bank_index]; else offset = BX_CIRRUS_THIS control.reg[0x09]; if (BX_CIRRUS_THIS banking_granularity_is_16k()) offset <<= 14; else offset <<= 12; if (BX_CIRRUS_THIS s.memsize <= offset) { limit = 0; BX_ERROR(("bank offset %08x is invalid",offset)); } else { limit = BX_CIRRUS_THIS s.memsize - offset; } if (!BX_CIRRUS_THIS banking_is_dual() && (bank_index != 0)) { if (limit > 0x8000) { offset += 0x8000; limit -= 0x8000; } else { limit = 0; } } if (limit > 0) { BX_CIRRUS_THIS bank_base[bank_index] = offset; BX_CIRRUS_THIS bank_limit[bank_index] = limit; } else { BX_CIRRUS_THIS bank_base[bank_index] = 0; BX_CIRRUS_THIS bank_limit[bank_index] = 0; } } Bit8u bx_svga_cirrus_c::svga_read_crtc(Bit32u address, unsigned index) { switch (index) { case 0x00: // VGA case 0x01: // VGA case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x05: // VGA case 0x06: // VGA case 0x07: // VGA case 0x08: // VGA case 0x09: // VGA case 0x0a: // VGA case 0x0b: // VGA case 0x0c: // VGA case 0x0d: // VGA case 0x0e: // VGA case 0x0f: // VGA case 0x10: // VGA case 0x11: // VGA case 0x12: // VGA case 0x13: // VGA case 0x14: // VGA case 0x15: // VGA case 0x16: // VGA case 0x17: // VGA case 0x18: // VGA break; case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x22: case 0x24: case 0x25: case 0x27: break; case 0x26: return (BX_CIRRUS_THIS s.attribute_ctrl.address & 0x3f); default: BX_DEBUG(("CRTC index 0x%02x is unknown(read)", index)); break; } if (index <= VGA_CRTC_MAX) { return VGA_READ(address,1); } if (index <= CIRRUS_CRTC_MAX) { return BX_CIRRUS_THIS crtc.reg[index]; } return 0xff; } void bx_svga_cirrus_c::svga_write_crtc(Bit32u address, unsigned index, Bit8u value) { BX_DEBUG(("crtc: index 0x%02x write 0x%02x", index, (unsigned)value)); bx_bool update_pitch = 0; switch (index) { case 0x00: // VGA case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x05: // VGA case 0x06: // VGA case 0x08: // VGA case 0x0a: // VGA case 0x0b: // VGA case 0x0e: // VGA case 0x0f: // VGA case 0x10: // VGA case 0x11: // VGA case 0x14: // VGA case 0x15: // VGA case 0x16: // VGA case 0x17: // VGA case 0x18: // VGA break; case 0x01: // VGA case 0x07: // VGA case 0x09: // VGA case 0x0c: // VGA (display offset 0x00ff00) case 0x0d: // VGA (display offset 0x0000ff) case 0x12: // VGA case 0x1A: // 0x01: interlaced video mode case 0x1D: // 0x80: offset 0x080000 (>=CLGD5434) BX_CIRRUS_THIS svga_needs_update_mode = 1; break; case 0x13: // VGA case 0x1B: // 0x01: offset 0x010000, 0x0c: offset 0x060000 update_pitch = 1; break; case 0x19: case 0x1C: break; default: BX_DEBUG(("CRTC index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value)); return; } if (index <= CIRRUS_CRTC_MAX) { BX_CIRRUS_THIS crtc.reg[index] = value; } if (index <= VGA_CRTC_MAX) { VGA_WRITE(address,value,1); } if (update_pitch) { BX_CIRRUS_THIS svga_pitch = (BX_CIRRUS_THIS crtc.reg[0x13] << 3) | ((BX_CIRRUS_THIS crtc.reg[0x1b] & 0x10) << 7); BX_CIRRUS_THIS svga_needs_update_mode = 1; } } Bit8u bx_svga_cirrus_c::svga_read_sequencer(Bit32u address, unsigned index) { switch (index) { case 0x00: // VGA case 0x01: // VGA case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA break; case 0x6: // cirrus unlock extensions case 0x7: // cirrus extended sequencer mode case 0xf: // cirrus dram control case 0x12: // graphics cursor attribute case 0x13: // graphics cursor pattern address offset case 0x17: // configuration readback & extended control break; case 0x10: // cursor xpos << 5 (index & 0x3f) case 0x30: case 0x50: case 0x70: case 0x90: case 0xb0: case 0xd0: case 0xf0: return BX_CIRRUS_THIS sequencer.reg[0x10]; case 0x11: // cursor ypos << 5 (index & 0x3f) case 0x31: case 0x51: case 0x71: case 0x91: case 0xb1: case 0xd1: case 0xf1: return BX_CIRRUS_THIS sequencer.reg[0x11]; default: BX_DEBUG(("sequencer index 0x%02x is unknown(read)", index)); break; } if (index <= VGA_SEQENCER_MAX) { return VGA_READ(address,1); } if (index <= CIRRUS_SEQENCER_MAX) { return BX_CIRRUS_THIS sequencer.reg[index]; } return 0xff; } void bx_svga_cirrus_c::svga_write_sequencer(Bit32u address, unsigned index, Bit8u value) { BX_DEBUG(("sequencer: index 0x%02x write 0x%02x", index, (unsigned)value)); bx_bool update_cursor = 0; Bit16u x, y, size; x = BX_CIRRUS_THIS hw_cursor.x; y = BX_CIRRUS_THIS hw_cursor.y; size = BX_CIRRUS_THIS hw_cursor.size; switch (index) { case 0x00: // VGA case 0x02: // VGA case 0x03: // VGA break; case 0x01: // VGA case 0x04: // VGA BX_CIRRUS_THIS svga_needs_update_mode = 1; break; case 0x6: // cirrus unlock extensions value &= 0x17; if (value == 0x12) { BX_CIRRUS_THIS svga_unlock_special = 1; BX_CIRRUS_THIS sequencer.reg[0x6] = 0x12; } else { #if BX_SUPPORT_PCI BX_CIRRUS_THIS svga_unlock_special = 0; #else if (!BX_CIRRUS_THIS pci_enabled) { BX_CIRRUS_THIS svga_unlock_special = 0; } #endif BX_CIRRUS_THIS sequencer.reg[0x6] = 0x0f; } return; case 0x7: // cirrus extended sequencer mode if (value != BX_CIRRUS_THIS sequencer.reg[0x7]) { BX_CIRRUS_THIS svga_needs_update_mode = 1; } break; case 0x08: case 0x09: case 0x0a: // cirrus scratch reg 1 case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x1b: case 0x1c: case 0x1d: case 0x1e: break; case 0x0f: return; case 0x10: // cursor xpos << 5 (index & 0x3f) case 0x30: case 0x50: case 0x70: case 0x90: case 0xb0: case 0xd0: case 0xf0: BX_CIRRUS_THIS sequencer.reg[0x10] = value; x = BX_CIRRUS_THIS hw_cursor.x; BX_CIRRUS_THIS hw_cursor.x = (value << 3) | (index >> 5); update_cursor = 1; break; case 0x11: // cursor ypos << 5 (index & 0x3f) case 0x31: case 0x51: case 0x71: case 0x91: case 0xb1: case 0xd1: case 0xf1: BX_CIRRUS_THIS sequencer.reg[0x11] = value; y = BX_CIRRUS_THIS hw_cursor.y; BX_CIRRUS_THIS hw_cursor.y = (value << 3) | (index >> 5); update_cursor = 1; break; case 0x12: size = BX_CIRRUS_THIS hw_cursor.size; if (value & CIRRUS_CURSOR_SHOW) { if (value & CIRRUS_CURSOR_LARGE) { BX_CIRRUS_THIS hw_cursor.size = 64; } else { BX_CIRRUS_THIS hw_cursor.size = 32; } } else { BX_CIRRUS_THIS hw_cursor.size = 0; } update_cursor = 1; break; case 0x13: update_cursor = 1; break; case 0x17: value = (BX_CIRRUS_THIS sequencer.reg[0x17] & 0x38) | (value & 0xc7); break; default: BX_DEBUG(("sequencer index 0x%02x is unknown(write 0x%02x)", index, (unsigned)value)); break; } if (update_cursor) { BX_CIRRUS_THIS redraw_area(x, y, size, size); BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS hw_cursor.x, BX_CIRRUS_THIS hw_cursor.y, BX_CIRRUS_THIS hw_cursor.size, BX_CIRRUS_THIS hw_cursor.size); } if (index <= CIRRUS_SEQENCER_MAX) { BX_CIRRUS_THIS sequencer.reg[index] = value; } if (index <= VGA_SEQENCER_MAX) { VGA_WRITE(address,value,1); } } Bit8u bx_svga_cirrus_c::svga_read_control(Bit32u address, unsigned index) { switch (index) { case 0x00: // VGA return BX_CIRRUS_THIS control.shadow_reg0; case 0x01: // VGA return BX_CIRRUS_THIS control.shadow_reg1; case 0x05: // VGA return BX_CIRRUS_THIS control.reg[index]; case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x06: // VGA case 0x07: // VGA case 0x08: // VGA break; case 0x09: // bank offset #0 case 0x0A: // bank offset #1 case 0x0B: break; case 0x10: // BGCOLOR 0x0000ff00 case 0x11: // FGCOLOR 0x0000ff00 case 0x12: // BGCOLOR 0x00ff0000 case 0x13: // FGCOLOR 0x00ff0000 case 0x14: // BGCOLOR 0xff000000 case 0x15: // FGCOLOR 0xff000000 break; case 0x20: // BLT WIDTH 0x0000ff case 0x21: // BLT WIDTH 0x001f00 case 0x22: // BLT HEIGHT 0x0000ff case 0x23: // BLT HEIGHT 0x001f00 case 0x24: // BLT DEST PITCH 0x0000ff case 0x25: // BLT DEST PITCH 0x001f00 case 0x26: // BLT SRC PITCH 0x0000ff case 0x27: // BLT SRC PITCH 0x001f00 case 0x28: // BLT DEST ADDR 0x0000ff case 0x29: // BLT DEST ADDR 0x00ff00 case 0x2a: // BLT DEST ADDR 0x3f0000 case 0x2c: // BLT SRC ADDR 0x0000ff case 0x2d: // BLT SRC ADDR 0x00ff00 case 0x2e: // BLT SRC ADDR 0x3f0000 case 0x2f: // BLT WRITE MASK case 0x30: // BLT MODE case 0x31: // BLT STATUS case 0x32: // RASTER OP case 0x33: // BLT MODE EXTENSION case 0x34: // BLT TRANSPARENT COLOR 0x00ff case 0x35: // BLT TRANSPARENT COLOR 0xff00 case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 break; default: BX_DEBUG(("control index 0x%02x is unknown(read)", index)); break; } if (index <= VGA_CONTROL_MAX) { return VGA_READ(address,1); } if (index <= CIRRUS_CONTROL_MAX) { return BX_CIRRUS_THIS control.reg[index]; } return 0xff; } void bx_svga_cirrus_c::svga_write_control(Bit32u address, unsigned index, Bit8u value) { Bit8u old_value = BX_CIRRUS_THIS control.reg[index]; BX_DEBUG(("control: index 0x%02x write 0x%02x", index, (unsigned)value)); switch (index) { case 0x00: // VGA BX_CIRRUS_THIS control.shadow_reg0 = value; break; case 0x01: // VGA BX_CIRRUS_THIS control.shadow_reg1 = value; break; case 0x02: // VGA case 0x03: // VGA case 0x04: // VGA case 0x07: // VGA case 0x08: // VGA break; case 0x05: // VGA case 0x06: // VGA BX_CIRRUS_THIS svga_needs_update_mode = 1; break; case 0x09: // bank offset #0 case 0x0A: // bank offset #1 case 0x0B: BX_CIRRUS_THIS control.reg[index] = value; update_bank_ptr(0); update_bank_ptr(1); break; case 0x10: // BGCOLOR 0x0000ff00 case 0x11: // FGCOLOR 0x0000ff00 case 0x12: // BGCOLOR 0x00ff0000 case 0x13: // FGCOLOR 0x00ff0000 case 0x14: // BGCOLOR 0xff000000 case 0x15: // FGCOLOR 0xff000000 break; case 0x20: // BLT WIDTH 0x0000ff break; case 0x21: // BLT WIDTH 0x001f00 value &= 0x1f; break; case 0x22: // BLT HEIGHT 0x0000ff break; case 0x23: // BLT HEIGHT 0x001f00 value &= 0x1f; break; case 0x24: // BLT DEST PITCH 0x0000ff break; case 0x25: // BLT DEST PITCH 0x001f00 value &= 0x1f; break; case 0x26: // BLT SRC PITCH 0x0000ff break; case 0x27: // BLT SRC PITCH 0x001f00 value &= 0x1f; break; case 0x28: // BLT DEST ADDR 0x0000ff break; case 0x29: // BLT DEST ADDR 0x00ff00 break; case 0x2a: // BLT DEST ADDR 0x3f0000 BX_CIRRUS_THIS control.reg[index] = value & 0x3f; if (BX_CIRRUS_THIS control.reg[0x31] & CIRRUS_BLT_AUTOSTART) { svga_bitblt(); } return; case 0x2b: // BLT DEST ADDR (unused bits) break; case 0x2c: // BLT SRC ADDR 0x0000ff break; case 0x2d: // BLT SRC ADDR 0x00ff00 break; case 0x2e: // BLT SRC ADDR 0x3f0000 value &= 0x3f; break; case 0x2f: // BLT WRITE MASK if (((value ^ old_value) & 0x60) && (value & 0x60)) { BX_ERROR(("BLT WRITE MASK support is not complete (value = 0x%02x)", value)); } break; case 0x30: // BLT MODE break; case 0x31: // BLT STATUS/START BX_CIRRUS_THIS control.reg[0x31] = value; if (((old_value & CIRRUS_BLT_RESET) != 0) && ((value & CIRRUS_BLT_RESET) == 0)) { svga_reset_bitblt(); } else if (((old_value & CIRRUS_BLT_START) == 0) && ((value & CIRRUS_BLT_START) != 0)) { BX_CIRRUS_THIS control.reg[0x31] |= CIRRUS_BLT_BUSY; svga_bitblt(); } return; case 0x32: // RASTER OP break; case 0x33: // BLT MODE EXTENSION #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { if (((value ^ old_value) & 0x18) && (value & 0x18)) { BX_ERROR(("BLT MODE EXTENSION support is not complete (value = 0x%02x)", value & 0x18)); } } else #endif { BX_DEBUG(("BLT MODE EXTENSION not available")); return; } break; case 0x34: // BLT TRANSPARENT COLOR 0x00ff case 0x35: // BLT TRANSPARENT COLOR 0xff00 case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00 default: BX_DEBUG(("control index 0x%02x is unknown (write 0x%02x)", index, (unsigned)value)); break; } if (index <= CIRRUS_CONTROL_MAX) { BX_CIRRUS_THIS control.reg[index] = value; } if (index <= VGA_CONTROL_MAX) { VGA_WRITE(address,value,1); } } Bit8u bx_svga_cirrus_c::svga_mmio_vga_read(Bit32u address) { Bit8u value = 0xff; BX_DEBUG(("MMIO vga read - address 0x%04x, value 0x%02x",address,value)); #if BX_USE_CIRRUS_SMF value = (Bit8u)svga_read_handler(theSvga,0x3c0+address,1); #else // BX_USE_CIRRUS_SMF value = (Bit8u)svga_read(0x3c0+address,1); #endif // BX_USE_CIRRUS_SMF return value; } void bx_svga_cirrus_c::svga_mmio_vga_write(Bit32u address,Bit8u value) { BX_DEBUG(("MMIO vga write - address 0x%04x, value 0x%02x",address,value)); #if BX_USE_CIRRUS_SMF svga_write_handler(theSvga,0x3c0+address,value,1); #else // BX_USE_CIRRUS_SMF svga_write(0x3c0+address,value,1); #endif // BX_USE_CIRRUS_SMF } Bit8u bx_svga_cirrus_c::svga_mmio_blt_read(Bit32u address) { Bit8u value = 0xff; switch (address) { case (CLGD543x_MMIO_BLTBGCOLOR+0): value = BX_CIRRUS_THIS control.shadow_reg0; break; case (CLGD543x_MMIO_BLTBGCOLOR+1): value = svga_read_control(0x3cf,0x10); break; case (CLGD543x_MMIO_BLTBGCOLOR+2): value = svga_read_control(0x3cf,0x12); break; case (CLGD543x_MMIO_BLTBGCOLOR+3): value = svga_read_control(0x3cf,0x14); break; case (CLGD543x_MMIO_BLTFGCOLOR+0): value = BX_CIRRUS_THIS control.shadow_reg1; break; case (CLGD543x_MMIO_BLTFGCOLOR+1): value = svga_read_control(0x3cf,0x11); break; case (CLGD543x_MMIO_BLTFGCOLOR+2): value = svga_read_control(0x3cf,0x13); break; case (CLGD543x_MMIO_BLTFGCOLOR+3): value = svga_read_control(0x3cf,0x15); break; case (CLGD543x_MMIO_BLTWIDTH+0): value = svga_read_control(0x3cf,0x20); break; case (CLGD543x_MMIO_BLTWIDTH+1): value = svga_read_control(0x3cf,0x21); break; case (CLGD543x_MMIO_BLTHEIGHT+0): value = svga_read_control(0x3cf,0x22); break; case (CLGD543x_MMIO_BLTHEIGHT+1): value = svga_read_control(0x3cf,0x23); break; case (CLGD543x_MMIO_BLTDESTPITCH+0): value = svga_read_control(0x3cf,0x24); break; case (CLGD543x_MMIO_BLTDESTPITCH+1): value = svga_read_control(0x3cf,0x25); break; case (CLGD543x_MMIO_BLTSRCPITCH+0): value = svga_read_control(0x3cf,0x26); break; case (CLGD543x_MMIO_BLTSRCPITCH+1): value = svga_read_control(0x3cf,0x27); break; case (CLGD543x_MMIO_BLTDESTADDR+0): value = svga_read_control(0x3cf,0x28); break; case (CLGD543x_MMIO_BLTDESTADDR+1): value = svga_read_control(0x3cf,0x29); break; case (CLGD543x_MMIO_BLTDESTADDR+2): value = svga_read_control(0x3cf,0x2a); break; case (CLGD543x_MMIO_BLTDESTADDR+3): value = svga_read_control(0x3cf,0x2b); break; case (CLGD543x_MMIO_BLTSRCADDR+0): value = svga_read_control(0x3cf,0x2c); break; case (CLGD543x_MMIO_BLTSRCADDR+1): value = svga_read_control(0x3cf,0x2d); break; case (CLGD543x_MMIO_BLTSRCADDR+2): value = svga_read_control(0x3cf,0x2e); break; case CLGD543x_MMIO_BLTWRITEMASK: value = svga_read_control(0x3cf,0x2f); break; case CLGD543x_MMIO_BLTMODE: value = svga_read_control(0x3cf,0x30); break; case CLGD543x_MMIO_BLTROP: value = svga_read_control(0x3cf,0x32); break; case CLGD543x_MMIO_BLTMODEEXT: value = svga_read_control(0x3cf,0x33); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0): value = svga_read_control(0x3cf,0x34); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1): value = svga_read_control(0x3cf,0x35); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0): value = svga_read_control(0x3cf,0x38); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1): value = svga_read_control(0x3cf,0x39); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case CLGD543x_MMIO_BLTSTATUS: value = svga_read_control(0x3cf,0x31); break; default: BX_ERROR(("MMIO blt read - address 0x%04x",address)); break; } BX_DEBUG(("MMIO blt read - address 0x%04x, value 0x%02x",address,value)); return value; } void bx_svga_cirrus_c::svga_mmio_blt_write(Bit32u address,Bit8u value) { BX_DEBUG(("MMIO blt write - address 0x%04x, value 0x%02x",address,value)); switch (address) { case (CLGD543x_MMIO_BLTBGCOLOR+0): BX_CIRRUS_THIS control.shadow_reg0 = value; break; case (CLGD543x_MMIO_BLTBGCOLOR+1): svga_write_control(0x3cf,0x10,value); break; case (CLGD543x_MMIO_BLTBGCOLOR+2): svga_write_control(0x3cf,0x12,value); break; case (CLGD543x_MMIO_BLTBGCOLOR+3): svga_write_control(0x3cf,0x14,value); break; case (CLGD543x_MMIO_BLTFGCOLOR+0): BX_CIRRUS_THIS control.shadow_reg1 = value; break; case (CLGD543x_MMIO_BLTFGCOLOR+1): svga_write_control(0x3cf,0x11,value); break; case (CLGD543x_MMIO_BLTFGCOLOR+2): svga_write_control(0x3cf,0x13,value); break; case (CLGD543x_MMIO_BLTFGCOLOR+3): svga_write_control(0x3cf,0x15,value); break; case (CLGD543x_MMIO_BLTWIDTH+0): svga_write_control(0x3cf,0x20,value); break; case (CLGD543x_MMIO_BLTWIDTH+1): svga_write_control(0x3cf,0x21,value); break; case (CLGD543x_MMIO_BLTHEIGHT+0): svga_write_control(0x3cf,0x22,value); break; case (CLGD543x_MMIO_BLTHEIGHT+1): svga_write_control(0x3cf,0x23,value); break; case (CLGD543x_MMIO_BLTDESTPITCH+0): svga_write_control(0x3cf,0x24,value); break; case (CLGD543x_MMIO_BLTDESTPITCH+1): svga_write_control(0x3cf,0x25,value); break; case (CLGD543x_MMIO_BLTSRCPITCH+0): svga_write_control(0x3cf,0x26,value); break; case (CLGD543x_MMIO_BLTSRCPITCH+1): svga_write_control(0x3cf,0x27,value); break; case (CLGD543x_MMIO_BLTDESTADDR+0): svga_write_control(0x3cf,0x28,value); break; case (CLGD543x_MMIO_BLTDESTADDR+1): svga_write_control(0x3cf,0x29,value); break; case (CLGD543x_MMIO_BLTDESTADDR+2): svga_write_control(0x3cf,0x2a,value); break; case (CLGD543x_MMIO_BLTDESTADDR+3): svga_write_control(0x3cf,0x2b,value); break; case (CLGD543x_MMIO_BLTSRCADDR+0): svga_write_control(0x3cf,0x2c,value); break; case (CLGD543x_MMIO_BLTSRCADDR+1): svga_write_control(0x3cf,0x2d,value); break; case (CLGD543x_MMIO_BLTSRCADDR+2): svga_write_control(0x3cf,0x2e,value); break; case CLGD543x_MMIO_BLTWRITEMASK: svga_write_control(0x3cf,0x2f,value); break; case CLGD543x_MMIO_BLTMODE: svga_write_control(0x3cf,0x30,value); break; case CLGD543x_MMIO_BLTMODE+1: // unused ??? - ignored for now break; case CLGD543x_MMIO_BLTROP: svga_write_control(0x3cf,0x32,value); break; case CLGD543x_MMIO_BLTMODEEXT: svga_write_control(0x3cf,0x33,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+0): svga_write_control(0x3cf,0x34,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+1): svga_write_control(0x3cf,0x35,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLOR+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLOR")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+0): svga_write_control(0x3cf,0x38,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+1): svga_write_control(0x3cf,0x39,value); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+2): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case (CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK+3): BX_ERROR(("CLGD543x_MMIO_BLTTRANSPARENTCOLORMASK")); break; case CLGD543x_MMIO_BLTSTATUS: svga_write_control(0x3cf,0x31,value); break; default: BX_ERROR(("MMIO blt write - address 0x%04x, value 0x%02x",address,value)); break; } } ///////////////////////////////////////////////////////////////////////// // // PCI support // ///////////////////////////////////////////////////////////////////////// #if BX_SUPPORT_PCI void bx_svga_cirrus_c::svga_init_pcihandlers(void) { int i; Bit8u devfunc = 0x00; DEV_register_pci_handlers(BX_CIRRUS_THIS_PTR, &devfunc, "cirrus", "SVGA Cirrus PCI"); for (i=0; i<256; i++) { BX_CIRRUS_THIS pci_conf[i] = 0x0; } WriteHostWordToLittleEndian( &BX_CIRRUS_THIS pci_conf[0x00], PCI_VENDOR_CIRRUS); WriteHostWordToLittleEndian( &BX_CIRRUS_THIS pci_conf[0x02], PCI_DEVICE_CLGD5446); WriteHostWordToLittleEndian( &BX_CIRRUS_THIS pci_conf[0x04], (PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS)); WriteHostDWordToLittleEndian( &BX_CIRRUS_THIS pci_conf[0x10], (PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT | PCI_MAP_MEMFLAGS_CACHEABLE)); WriteHostDWordToLittleEndian( &BX_CIRRUS_THIS pci_conf[0x14], (PCI_MAP_MEM | PCI_MAP_MEMFLAGS_32BIT)); BX_CIRRUS_THIS pci_conf[0x0a] = PCI_CLASS_SUB_VGA; BX_CIRRUS_THIS pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY; BX_CIRRUS_THIS pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h; BX_CIRRUS_THIS pci_base_address[0] = 0; BX_CIRRUS_THIS pci_base_address[1] = 0; BX_CIRRUS_THIS pci_rom_address = 0; BX_CIRRUS_THIS load_pci_rom(SIM->get_param_string(BXPN_VGA_ROM_PATH)->getptr()); } Bit32u bx_svga_cirrus_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u ret = 0; for (unsigned i = 0; i < io_len; i++) { ret |= (Bit32u)(BX_CIRRUS_THIS pci_conf[address + i]) << (i*8); } BX_DEBUG(("pci_read: address 0x%02x, io_len 0x%02x, value 0x%x", (unsigned)address, (unsigned)io_len, (unsigned)ret)); return ret; } void bx_svga_cirrus_c::pci_write_handler(Bit8u address, Bit32u value, unsigned io_len) { unsigned i; unsigned write_addr; Bit8u new_value, old_value; bx_bool baseaddr0_change = 0; bx_bool baseaddr1_change = 0; bx_bool romaddr_change = 0; BX_DEBUG(("pci_write: address 0x%02x, io_len 0x%02x, value 0x%x", (unsigned)address, (unsigned)io_len, (unsigned)value)); if ((address > 0x17) && (address < 0x30)) return; if (address == 0x30) { value = value & 0xfffffc01; romaddr_change = 1; } for (i = 0; i < io_len; i++) { write_addr = address + i; old_value = BX_CIRRUS_THIS pci_conf[write_addr]; new_value = (Bit8u)(value & 0xff); switch (write_addr) { case 0x04: // command bit0-7 new_value &= PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS; new_value |= old_value & ~(PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS); break; case 0x05: // command bit8-15 new_value = old_value; break; case 0x06: // status bit0-7 new_value = old_value & (~new_value); break; case 0x07: // status bit8-15 new_value = old_value & (~new_value); break; case 0x10: // base address #0 new_value = (new_value & 0xf0) | (old_value & 0x0f); case 0x11: case 0x12: case 0x13: baseaddr0_change |= (old_value != new_value); break; case 0x14: // base address #1 new_value = (new_value & 0xf0) | (old_value & 0x0f); case 0x15: case 0x16: case 0x17: baseaddr1_change |= (old_value != new_value); break; // read-only. case 0x00: case 0x01: // vendor case 0x02: case 0x03: // device case 0x08: // revision case 0x09: case 0x0a: case 0x0b: // class case 0x0e: // header type case 0x0f: // built-in self test(unimplemented) new_value = old_value; break; default: break; } BX_CIRRUS_THIS pci_conf[write_addr] = new_value; value >>= 8; } if (baseaddr0_change) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[0], &BX_CIRRUS_THIS pci_conf[0x10], 0x2000000)) { BX_INFO(("new pci_memaddr: 0x%04x", BX_CIRRUS_THIS pci_base_address[0])); } } if (baseaddr1_change) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_base_address[1], &BX_CIRRUS_THIS pci_conf[0x14], CIRRUS_PNPMMIO_SIZE)) { BX_INFO(("new pci_mmioaddr = 0x%08x", BX_CIRRUS_THIS pci_base_address[1])); } } if (romaddr_change) { if (DEV_pci_set_base_mem(BX_CIRRUS_THIS_PTR, cirrus_mem_read_handler, cirrus_mem_write_handler, &BX_CIRRUS_THIS pci_rom_address, &BX_CIRRUS_THIS pci_conf[0x30], BX_CIRRUS_THIS pci_rom_size)) { BX_INFO(("new ROM address: 0x%08x", BX_CIRRUS_THIS pci_rom_address)); } } } #endif // BX_SUPPORT_PCI ///////////////////////////////////////////////////////////////////////// // // Bitblt. // ///////////////////////////////////////////////////////////////////////// void bx_svga_cirrus_c::svga_reset_bitblt(void) { BX_CIRRUS_THIS control.reg[0x31] &= ~(CIRRUS_BLT_START|CIRRUS_BLT_BUSY|CIRRUS_BLT_FIFOUSED); BX_CIRRUS_THIS bitblt.rop_handler = NULL; BX_CIRRUS_THIS bitblt.src = NULL; BX_CIRRUS_THIS bitblt.dst = NULL; BX_CIRRUS_THIS bitblt.memsrc_ptr = NULL; BX_CIRRUS_THIS bitblt.memsrc_endptr = NULL; BX_CIRRUS_THIS bitblt.memsrc_needed = 0; BX_CIRRUS_THIS bitblt.memdst_ptr = NULL; BX_CIRRUS_THIS bitblt.memdst_endptr = NULL; BX_CIRRUS_THIS bitblt.memdst_needed = 0; } void bx_svga_cirrus_c::svga_bitblt() { Bit16u tmp16; Bit32u tmp32; Bit32u dstaddr; Bit32u srcaddr; Bit32u offset; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x20],tmp16); BX_CIRRUS_THIS bitblt.bltwidth = ((int)tmp16 & (int)0x1fff) + 1; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x22],tmp16); BX_CIRRUS_THIS bitblt.bltheight = ((int)tmp16 & (int)0x07ff) + 1; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x24],tmp16); BX_CIRRUS_THIS bitblt.dstpitch = (int)tmp16 & (int)0x1fff; ReadHostWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x26],tmp16); BX_CIRRUS_THIS bitblt.srcpitch = (int)tmp16 & (int)0x1fff; ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x28],tmp32); dstaddr = tmp32 & (BX_CIRRUS_THIS s.memsize - 1); ReadHostDWordFromLittleEndian(&BX_CIRRUS_THIS control.reg[0x2c],tmp32); srcaddr = tmp32 & (BX_CIRRUS_THIS s.memsize - 1); BX_CIRRUS_THIS bitblt.srcaddr = srcaddr; BX_CIRRUS_THIS bitblt.bltmode = BX_CIRRUS_THIS control.reg[0x30]; BX_CIRRUS_THIS bitblt.bltmodeext = BX_CIRRUS_THIS control.reg[0x33]; BX_CIRRUS_THIS bitblt.bltrop = BX_CIRRUS_THIS control.reg[0x32]; offset = dstaddr - (BX_CIRRUS_THIS disp_ptr - BX_CIRRUS_THIS s.memory); BX_CIRRUS_THIS redraw.x = (offset % BX_CIRRUS_THIS bitblt.dstpitch) / (BX_CIRRUS_THIS svga_bpp >> 3); BX_CIRRUS_THIS redraw.y = offset / BX_CIRRUS_THIS bitblt.dstpitch; BX_CIRRUS_THIS redraw.w = BX_CIRRUS_THIS bitblt.bltwidth / (BX_CIRRUS_THIS svga_bpp >> 3); BX_CIRRUS_THIS redraw.h = BX_CIRRUS_THIS bitblt.bltheight; BX_DEBUG(("BLT: src:0x%08x,dst 0x%08x,block %ux%u,mode 0x%02x,ROP 0x%02x", (unsigned)srcaddr,(unsigned)dstaddr, (unsigned)BX_CIRRUS_THIS bitblt.bltwidth,(unsigned)BX_CIRRUS_THIS bitblt.bltheight, (unsigned)BX_CIRRUS_THIS bitblt.bltmode,(unsigned)BX_CIRRUS_THIS bitblt.bltrop)); BX_DEBUG(("BLT: srcpitch:0x%08x,dstpitch 0x%08x,modeext 0x%02x,writemask 0x%02x", (unsigned)BX_CIRRUS_THIS bitblt.srcpitch, (unsigned)BX_CIRRUS_THIS bitblt.dstpitch, (unsigned)BX_CIRRUS_THIS bitblt.bltmodeext, BX_CIRRUS_THIS control.reg[0x2f])); switch (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { case CIRRUS_BLTMODE_PIXELWIDTH8: BX_CIRRUS_THIS bitblt.pixelwidth = 1; break; case CIRRUS_BLTMODE_PIXELWIDTH16: BX_CIRRUS_THIS bitblt.pixelwidth = 2; break; case CIRRUS_BLTMODE_PIXELWIDTH24: BX_CIRRUS_THIS bitblt.pixelwidth = 3; break; case CIRRUS_BLTMODE_PIXELWIDTH32: BX_CIRRUS_THIS bitblt.pixelwidth = 4; break; default: BX_PANIC(("unknown pixel width")); goto ignoreblt; } BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK; if ((BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST)) == (CIRRUS_BLTMODE_MEMSYSSRC|CIRRUS_BLTMODE_MEMSYSDEST)) { BX_ERROR(("BLT: memory-to-memory copy is requested, ROP %02x", (unsigned)BX_CIRRUS_THIS bitblt.bltrop)); goto ignoreblt; } if ((BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && (BX_CIRRUS_THIS bitblt.bltmode & (CIRRUS_BLTMODE_MEMSYSDEST | CIRRUS_BLTMODE_TRANSPARENTCOMP | CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) == (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop); BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr; svga_solidfill(); } else { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_BACKWARDS) { BX_CIRRUS_THIS bitblt.dstpitch = -BX_CIRRUS_THIS bitblt.dstpitch; BX_CIRRUS_THIS bitblt.srcpitch = -BX_CIRRUS_THIS bitblt.srcpitch; BX_CIRRUS_THIS bitblt.rop_handler = svga_get_bkwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop); BX_CIRRUS_THIS redraw.x -= BX_CIRRUS_THIS redraw.w; BX_CIRRUS_THIS redraw.y -= BX_CIRRUS_THIS redraw.h; } else { BX_CIRRUS_THIS bitblt.rop_handler = svga_get_fwd_rop_handler(BX_CIRRUS_THIS bitblt.bltrop); } BX_DEBUG(("BLT redraw: x = %d, y = %d, w = %d, h = %d", BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h)); // setup bitblt engine. if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSSRC) { svga_setup_bitblt_cputovideo(dstaddr,srcaddr); } else if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_MEMSYSDEST) { svga_setup_bitblt_videotocpu(dstaddr,srcaddr); } else { svga_setup_bitblt_videotovideo(dstaddr,srcaddr); } return; } ignoreblt: svga_reset_bitblt(); } void bx_svga_cirrus_c::svga_setup_bitblt_cputovideo(Bit32u dstaddr,Bit32u srcaddr) { Bit16u w; BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSSRC; BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr; BX_CIRRUS_THIS bitblt.src = NULL; BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[0]; BX_CIRRUS_THIS bitblt.memsrc_endptr = &BX_CIRRUS_THIS bitblt.memsrc[0]; if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { BX_CIRRUS_THIS bitblt.srcpitch = 8; } else { BX_CIRRUS_THIS bitblt.srcpitch = 8 * 8 * BX_CIRRUS_THIS bitblt.pixelwidth; } BX_CIRRUS_THIS bitblt.memsrc_needed = BX_CIRRUS_THIS bitblt.srcpitch; BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memsrc_static; } else { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) { BX_CIRRUS_THIS bitblt.srcpitch = (w + 31) >> 5; } else { BX_CIRRUS_THIS bitblt.srcpitch = (w + 7) >> 3; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_colorexpand_transp_memsrc_static; } else { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memsrc_static; } } else { BX_CIRRUS_THIS bitblt.srcpitch = (BX_CIRRUS_THIS bitblt.bltwidth + 3) & (~3); BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memsrc_static; } BX_CIRRUS_THIS bitblt.memsrc_needed = BX_CIRRUS_THIS bitblt.srcpitch * BX_CIRRUS_THIS bitblt.bltheight; } BX_CIRRUS_THIS bitblt.memsrc_endptr += BX_CIRRUS_THIS bitblt.srcpitch; } void bx_svga_cirrus_c::svga_setup_bitblt_videotocpu(Bit32u dstaddr,Bit32u srcaddr) { BX_ERROR(("BLT: MEMSYSDEST is not implemented")); BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_MEMSYSDEST; #if 0 BX_CIRRUS_THIS bitblt.dst = NULL; BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + srcaddr; BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0]; BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[0]; BX_CIRRUS_THIS bitblt.memdst_needed = BX_CIRRUS_THIS bitblt.bltwidth * BX_CIRRUS_THIS bitblt.bltheight; BX_CIRRUS_THIS bitblt.memdst_needed = (BX_CIRRUS_THIS bitblt.memdst_needed + 3) & (~3); if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_memdst_static; } else { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_memdst_static; } #endif } void bx_svga_cirrus_c::svga_setup_bitblt_videotovideo(Bit32u dstaddr,Bit32u srcaddr) { BX_CIRRUS_THIS bitblt.dst = BX_CIRRUS_THIS s.memory + dstaddr; if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_PATTERNCOPY) { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_patterncopy_static; BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + (srcaddr & ~0x07); } else { BX_CIRRUS_THIS bitblt.bitblt_ptr = svga_simplebitblt_static; BX_CIRRUS_THIS bitblt.src = BX_CIRRUS_THIS s.memory + srcaddr; } (*BX_CIRRUS_THIS bitblt.bitblt_ptr)(); svga_reset_bitblt(); BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); } void bx_svga_cirrus_c::svga_colorexpand(Bit8u *dst,const Bit8u *src,int count,int pixelwidth) { BX_DEBUG(("svga_cirrus: COLOR EXPAND")); switch (pixelwidth) { case 1: svga_colorexpand_8(dst,src,count); break; case 2: svga_colorexpand_16(dst,src,count); break; case 3: svga_colorexpand_24(dst,src,count); break; case 4: svga_colorexpand_32(dst,src,count); break; default: BX_PANIC(("COLOREXPAND: unknown pixelwidth %u",(unsigned)pixelwidth)); break; } } #if !BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_colorexpand_8_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_8(dst,src,count); } void bx_svga_cirrus_c::svga_colorexpand_16_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_16(dst,src,count); } void bx_svga_cirrus_c::svga_colorexpand_24_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_24(dst,src,count); } void bx_svga_cirrus_c::svga_colorexpand_32_static(void *this_ptr,Bit8u *dst,const Bit8u *src,int count) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_32(dst,src,count); } #endif // BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_colorexpand_8(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2]; unsigned bits; unsigned bitmask; colors[0] = BX_CIRRUS_THIS control.shadow_reg0; colors[1] = BX_CIRRUS_THIS control.shadow_reg1; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } *dst++ = colors[!!(bits & bitmask)]; bitmask >>= 1; } } void bx_svga_cirrus_c::svga_colorexpand_16(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2][2]; unsigned bits; unsigned bitmask; unsigned index; colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0; colors[0][1] = BX_CIRRUS_THIS control.reg[0x10]; colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1; colors[1][1] = BX_CIRRUS_THIS control.reg[0x11]; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } index = !!(bits & bitmask); *dst++ = colors[index][0]; *dst++ = colors[index][1]; bitmask >>= 1; } } void bx_svga_cirrus_c::svga_colorexpand_24(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2][3]; unsigned bits; unsigned bitmask; unsigned index; colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0; colors[0][1] = BX_CIRRUS_THIS control.reg[0x10]; colors[0][2] = BX_CIRRUS_THIS control.reg[0x12]; colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1; colors[1][1] = BX_CIRRUS_THIS control.reg[0x11]; colors[1][2] = BX_CIRRUS_THIS control.reg[0x13]; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } index = !!(bits & bitmask); *dst++ = colors[index][0]; *dst++ = colors[index][1]; *dst++ = colors[index][2]; bitmask >>= 1; } } void bx_svga_cirrus_c::svga_colorexpand_32(Bit8u *dst,const Bit8u *src,int count) { Bit8u colors[2][4]; unsigned bits; unsigned bitmask; unsigned index; colors[0][0] = BX_CIRRUS_THIS control.shadow_reg0; colors[0][1] = BX_CIRRUS_THIS control.reg[0x10]; colors[0][2] = BX_CIRRUS_THIS control.reg[0x12]; colors[0][3] = BX_CIRRUS_THIS control.reg[0x14]; colors[1][0] = BX_CIRRUS_THIS control.shadow_reg1; colors[1][1] = BX_CIRRUS_THIS control.reg[0x11]; colors[1][2] = BX_CIRRUS_THIS control.reg[0x13]; colors[1][3] = BX_CIRRUS_THIS control.reg[0x15]; bitmask = 0x80; bits = *src++; for (int x = 0; x < count; x++) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++; } index = !!(bits & bitmask); *dst++ = colors[index][0]; *dst++ = colors[index][1]; *dst++ = colors[index][2]; *dst++ = colors[index][3]; bitmask >>= 1; } } #if !BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_patterncopy_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy(); } void bx_svga_cirrus_c::svga_simplebitblt_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt(); } void bx_svga_cirrus_c::svga_solidfill_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_solidfill(); } void bx_svga_cirrus_c::svga_patterncopy_memsrc_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_patterncopy_memsrc(); } void bx_svga_cirrus_c::svga_simplebitblt_memsrc_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_simplebitblt_memsrc(); } void bx_svga_cirrus_c::svga_colorexpand_transp_memsrc_static(void *this_ptr) { ((bx_svga_cirrus_c *)this_ptr)->svga_colorexpand_transp_memsrc(); } #endif // !BX_USE_CIRRUS_SMF void bx_svga_cirrus_c::svga_patterncopy() { Bit8u color[4]; Bit8u work_colorexp[256]; Bit8u *src, *dst; Bit8u *dstc, *srcc, *src2; int x, y, pattern_x, pattern_y, srcskipleft; int patternbytes = 8 * BX_CIRRUS_THIS bitblt.pixelwidth; int pattern_pitch = patternbytes; int bltbytes = BX_CIRRUS_THIS bitblt.bltwidth; unsigned bits, bits_xor, bitmask; if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; srcskipleft = pattern_x / 3; } else { srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07; pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; } else { bits_xor = 0x00; } pattern_y = BX_CIRRUS_THIS bitblt.srcaddr & 0x07; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; bitmask = 0x80 >> srcskipleft; bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor; for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = BX_CIRRUS_THIS bitblt.src[pattern_y] ^ bits_xor; } if (bits & bitmask) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); } dst += BX_CIRRUS_THIS bitblt.pixelwidth; bitmask >>= 1; } pattern_y = (pattern_y + 1) & 7; BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } return; } else { svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src,8*8,BX_CIRRUS_THIS bitblt.pixelwidth); BX_CIRRUS_THIS bitblt.src = work_colorexp; BX_CIRRUS_THIS bitblt.bltmode &= ~CIRRUS_BLTMODE_COLOREXPAND; } } else { if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_pitch = 32; } } if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_PATTERNCOPY) { BX_ERROR(("PATTERNCOPY: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } BX_DEBUG(("svga_cirrus: PATTERN COPY")); dst = BX_CIRRUS_THIS bitblt.dst; pattern_y = BX_CIRRUS_THIS bitblt.srcaddr & 0x07; src = (Bit8u *)BX_CIRRUS_THIS bitblt.src; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { srcc = src + pattern_y * pattern_pitch; dstc = dst + pattern_x; for (x = pattern_x; x < bltbytes; x += BX_CIRRUS_THIS bitblt.pixelwidth) { src2 = srcc + (x % patternbytes); (*BX_CIRRUS_THIS bitblt.rop_handler)( dstc, src2, 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); dstc += BX_CIRRUS_THIS bitblt.pixelwidth; } pattern_y = (pattern_y + 1) & 7; dst += BX_CIRRUS_THIS bitblt.dstpitch; } } void bx_svga_cirrus_c::svga_simplebitblt() { Bit8u color[4]; Bit8u work_colorexp[2048]; Bit16u w, x, y; Bit8u *dst; unsigned bits, bits_xor, bitmask; int pattern_x, srcskipleft; if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; srcskipleft = pattern_x / 3; } else { srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07; pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; } else { bits_xor = 0x00; } for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; bitmask = 0x80 >> srcskipleft; bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor; for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *BX_CIRRUS_THIS bitblt.src++ ^ bits_xor; } if (bits & bitmask) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); } dst += BX_CIRRUS_THIS bitblt.pixelwidth; bitmask >>= 1; } BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } return; } else { w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { svga_colorexpand(work_colorexp,BX_CIRRUS_THIS bitblt.src, w, BX_CIRRUS_THIS bitblt.pixelwidth); dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, work_colorexp + pattern_x, 0, 0, BX_CIRRUS_THIS bitblt.bltwidth - pattern_x, 1); BX_CIRRUS_THIS bitblt.src += ((w + 7) >> 3); BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } return; } } if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_BACKWARDS) { BX_ERROR(("SIMPLE BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } BX_DEBUG(("svga_cirrus: BITBLT")); (*BX_CIRRUS_THIS bitblt.rop_handler)( BX_CIRRUS_THIS bitblt.dst, BX_CIRRUS_THIS bitblt.src, BX_CIRRUS_THIS bitblt.dstpitch, BX_CIRRUS_THIS bitblt.srcpitch, BX_CIRRUS_THIS bitblt.bltwidth, BX_CIRRUS_THIS bitblt.bltheight); } void bx_svga_cirrus_c::svga_solidfill() { Bit8u color[4]; int x, y; Bit8u *dst; BX_DEBUG(("BLT: SOLIDFILL")); color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; for (y = 0; y < BX_CIRRUS_THIS bitblt.bltheight; y++) { dst = BX_CIRRUS_THIS bitblt.dst; for (x = 0; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); dst += BX_CIRRUS_THIS bitblt.pixelwidth; } BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; } BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); } void bx_svga_cirrus_c::svga_patterncopy_memsrc() { BX_INFO(("svga_patterncopy_memsrc() - not tested")); BX_CIRRUS_THIS bitblt.src = &BX_CIRRUS_THIS bitblt.memsrc[0]; svga_patterncopy(); BX_CIRRUS_THIS bitblt.memsrc_needed = 0; BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); } void bx_svga_cirrus_c::svga_simplebitblt_memsrc() { Bit8u *srcptr = &BX_CIRRUS_THIS bitblt.memsrc[0]; Bit8u work_colorexp[2048]; Bit16u w; int pattern_x; BX_DEBUG(("svga_cirrus: BLT, cpu-to-video")); if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; } else { pattern_x = (BX_CIRRUS_THIS control.reg[0x2f] & 0x07) * BX_CIRRUS_THIS bitblt.pixelwidth; } if (BX_CIRRUS_THIS bitblt.bltmode & CIRRUS_BLTMODE_COLOREXPAND) { if (BX_CIRRUS_THIS bitblt.bltmode & ~CIRRUS_BLTMODE_COLOREXPAND) { BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } w = BX_CIRRUS_THIS bitblt.bltwidth / BX_CIRRUS_THIS bitblt.pixelwidth; svga_colorexpand(work_colorexp,srcptr,w,BX_CIRRUS_THIS bitblt.pixelwidth); (*BX_CIRRUS_THIS bitblt.rop_handler)( BX_CIRRUS_THIS bitblt.dst + pattern_x, work_colorexp + pattern_x, 0, 0, BX_CIRRUS_THIS bitblt.bltwidth - pattern_x, 1); } else { if (BX_CIRRUS_THIS bitblt.bltmode != 0) { BX_ERROR(("cpu-to-video BLT: unknown bltmode %02x",BX_CIRRUS_THIS bitblt.bltmode)); return; } (*BX_CIRRUS_THIS bitblt.rop_handler)( BX_CIRRUS_THIS bitblt.dst, srcptr, 0, 0, BX_CIRRUS_THIS bitblt.bltwidth, 1); } } void bx_svga_cirrus_c::svga_colorexpand_transp_memsrc() { Bit8u *src = &BX_CIRRUS_THIS bitblt.memsrc[0]; Bit8u color[4]; int x, pattern_x, srcskipleft; Bit8u *dst; unsigned bits, bits_xor, bitmask; BX_DEBUG(("BLT, cpu-to-video, transparent")); if (BX_CIRRUS_THIS bitblt.pixelwidth == 3) { pattern_x = BX_CIRRUS_THIS control.reg[0x2f] & 0x1f; srcskipleft = pattern_x / 3; } else { srcskipleft = BX_CIRRUS_THIS control.reg[0x2f] & 0x07; pattern_x = srcskipleft * BX_CIRRUS_THIS bitblt.pixelwidth; } color[0] = BX_CIRRUS_THIS control.shadow_reg1; color[1] = BX_CIRRUS_THIS control.reg[0x11]; color[2] = BX_CIRRUS_THIS control.reg[0x13]; color[3] = BX_CIRRUS_THIS control.reg[0x15]; if (BX_CIRRUS_THIS bitblt.bltmodeext & CIRRUS_BLTMODEEXT_COLOREXPINV) { bits_xor = 0xff; } else { bits_xor = 0x00; } dst = BX_CIRRUS_THIS bitblt.dst + pattern_x; bitmask = 0x80 >> srcskipleft; bits = *src++ ^ bits_xor; for (x = pattern_x; x < BX_CIRRUS_THIS bitblt.bltwidth; x+=BX_CIRRUS_THIS bitblt.pixelwidth) { if ((bitmask & 0xff) == 0) { bitmask = 0x80; bits = *src++ ^ bits_xor; } if (bits & bitmask) { (*BX_CIRRUS_THIS bitblt.rop_handler)( dst, &color[0], 0, 0, BX_CIRRUS_THIS bitblt.pixelwidth, 1); } dst += BX_CIRRUS_THIS bitblt.pixelwidth; bitmask >>= 1; } } bx_bool // 1 if finished, 0 otherwise bx_svga_cirrus_c::svga_asyncbitblt_next() { int count; int avail; if (BX_CIRRUS_THIS bitblt.bitblt_ptr == NULL) { BX_PANIC(("svga_asyncbitblt_next: unexpected call")); goto cleanup; } if (BX_CIRRUS_THIS bitblt.memdst_needed > 0) { BX_CIRRUS_THIS bitblt.memdst_needed -= BX_CIRRUS_THIS bitblt.memdst_ptr - &BX_CIRRUS_THIS bitblt.memdst[0]; avail = BX_MIN(CIRRUS_BLT_CACHESIZE, BX_CIRRUS_THIS bitblt.memdst_needed); BX_CIRRUS_THIS bitblt.memdst_ptr = &BX_CIRRUS_THIS bitblt.memdst[0]; BX_CIRRUS_THIS bitblt.memdst_endptr = &BX_CIRRUS_THIS bitblt.memdst[avail]; if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0 && BX_CIRRUS_THIS bitblt.memdst_needed <= 0) { goto cleanup; } } (*BX_CIRRUS_THIS bitblt.bitblt_ptr)(); if (BX_CIRRUS_THIS bitblt.memsrc_needed > 0) { BX_CIRRUS_THIS bitblt.dst += BX_CIRRUS_THIS bitblt.dstpitch; BX_CIRRUS_THIS bitblt.memsrc_needed -= BX_CIRRUS_THIS bitblt.srcpitch; if (BX_CIRRUS_THIS bitblt.memsrc_needed <= 0) { BX_CIRRUS_THIS redraw_area(BX_CIRRUS_THIS redraw.x, BX_CIRRUS_THIS redraw.y, BX_CIRRUS_THIS redraw.w, BX_CIRRUS_THIS redraw.h); if (BX_CIRRUS_THIS bitblt.memdst_needed <= 0) { goto cleanup; } } else { count = BX_CIRRUS_THIS bitblt.memsrc_endptr - BX_CIRRUS_THIS bitblt.memsrc_ptr; memmove(&BX_CIRRUS_THIS bitblt.memsrc[0], BX_CIRRUS_THIS bitblt.memsrc_ptr, count); BX_CIRRUS_THIS bitblt.memsrc_ptr = &BX_CIRRUS_THIS bitblt.memsrc[count]; } } return 0; cleanup: svga_reset_bitblt(); return 1; } ///////////////////////////////////////////////////////////////////////// // // Raster operations. // ///////////////////////////////////////////////////////////////////////// #define IMPLEMENT_FORWARD_BITBLT(name,opline) \ static void bitblt_rop_fwd_##name( \ Bit8u *dst,const Bit8u *src, \ int dstpitch,int srcpitch, \ int bltwidth,int bltheight) \ { \ int x,y; \ dstpitch -= bltwidth; \ srcpitch -= bltwidth; \ for (y = 0; y < bltheight; y++) { \ for (x = 0; x < bltwidth; x++) { \ opline; \ dst++; \ src++; \ } \ dst += dstpitch; \ src += srcpitch; \ } \ } #define IMPLEMENT_BACKWARD_BITBLT(name,opline) \ static void bitblt_rop_bkwd_##name( \ Bit8u *dst,const Bit8u *src, \ int dstpitch,int srcpitch, \ int bltwidth,int bltheight) \ { \ int x,y; \ dstpitch += bltwidth; \ srcpitch += bltwidth; \ for (y = 0; y < bltheight; y++) { \ for (x = 0; x < bltwidth; x++) { \ opline; \ dst--; \ src--; \ } \ dst += dstpitch; \ src += srcpitch; \ } \ } IMPLEMENT_FORWARD_BITBLT(0, *dst = 0) IMPLEMENT_FORWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst)) IMPLEMENT_FORWARD_BITBLT(nop, (void)0) IMPLEMENT_FORWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst))) IMPLEMENT_FORWARD_BITBLT(notdst, *dst = ~(*dst)) IMPLEMENT_FORWARD_BITBLT(src, *dst = *src) IMPLEMENT_FORWARD_BITBLT(1, *dst = 0xff) IMPLEMENT_FORWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst)) IMPLEMENT_FORWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst)) IMPLEMENT_FORWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst)) IMPLEMENT_FORWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst))) IMPLEMENT_FORWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst))) IMPLEMENT_FORWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst))) IMPLEMENT_FORWARD_BITBLT(notsrc, *dst = (~(*src))) IMPLEMENT_FORWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst)) IMPLEMENT_FORWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(0, *dst = 0) IMPLEMENT_BACKWARD_BITBLT(src_and_dst, *dst = (*src) & (*dst)) IMPLEMENT_BACKWARD_BITBLT(nop, (void)0) IMPLEMENT_BACKWARD_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(notdst, *dst = ~(*dst)) IMPLEMENT_BACKWARD_BITBLT(src, *dst = *src) IMPLEMENT_BACKWARD_BITBLT(1, *dst = 0xff) IMPLEMENT_BACKWARD_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst)) IMPLEMENT_BACKWARD_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst)) IMPLEMENT_BACKWARD_BITBLT(src_or_dst, *dst = (*src) | (*dst)) IMPLEMENT_BACKWARD_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst))) IMPLEMENT_BACKWARD_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst))) IMPLEMENT_BACKWARD_BITBLT(notsrc, *dst = (~(*src))) IMPLEMENT_BACKWARD_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst)) IMPLEMENT_BACKWARD_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst))) bx_cirrus_bitblt_rop_t bx_svga_cirrus_c::svga_get_fwd_rop_handler(Bit8u rop) { bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_fwd_nop; switch (rop) { case CIRRUS_ROP_0: rop_handler = bitblt_rop_fwd_0; break; case CIRRUS_ROP_SRC_AND_DST: rop_handler = bitblt_rop_fwd_src_and_dst; break; case CIRRUS_ROP_NOP: rop_handler = bitblt_rop_fwd_nop; break; case CIRRUS_ROP_SRC_AND_NOTDST: rop_handler = bitblt_rop_fwd_src_and_notdst; break; case CIRRUS_ROP_NOTDST: rop_handler = bitblt_rop_fwd_notdst; break; case CIRRUS_ROP_SRC: rop_handler = bitblt_rop_fwd_src; break; case CIRRUS_ROP_1: rop_handler = bitblt_rop_fwd_1; break; case CIRRUS_ROP_NOTSRC_AND_DST: rop_handler = bitblt_rop_fwd_notsrc_and_dst; break; case CIRRUS_ROP_SRC_XOR_DST: rop_handler = bitblt_rop_fwd_src_xor_dst; break; case CIRRUS_ROP_SRC_OR_DST: rop_handler = bitblt_rop_fwd_src_or_dst; break; case CIRRUS_ROP_NOTSRC_OR_NOTDST: rop_handler = bitblt_rop_fwd_notsrc_or_notdst; break; case CIRRUS_ROP_SRC_NOTXOR_DST: rop_handler = bitblt_rop_fwd_src_notxor_dst; break; case CIRRUS_ROP_SRC_OR_NOTDST: rop_handler = bitblt_rop_fwd_src_or_notdst; break; case CIRRUS_ROP_NOTSRC: rop_handler = bitblt_rop_fwd_notsrc; break; case CIRRUS_ROP_NOTSRC_OR_DST: rop_handler = bitblt_rop_fwd_notsrc_or_dst; break; case CIRRUS_ROP_NOTSRC_AND_NOTDST: rop_handler = bitblt_rop_fwd_notsrc_and_notdst; break; default: BX_ERROR(("unknown ROP %02x",rop)); break; } return rop_handler; } bx_cirrus_bitblt_rop_t bx_svga_cirrus_c::svga_get_bkwd_rop_handler(Bit8u rop) { bx_cirrus_bitblt_rop_t rop_handler = bitblt_rop_bkwd_nop; switch (rop) { case CIRRUS_ROP_0: rop_handler = bitblt_rop_bkwd_0; break; case CIRRUS_ROP_SRC_AND_DST: rop_handler = bitblt_rop_bkwd_src_and_dst; break; case CIRRUS_ROP_NOP: rop_handler = bitblt_rop_bkwd_nop; break; case CIRRUS_ROP_SRC_AND_NOTDST: rop_handler = bitblt_rop_bkwd_src_and_notdst; break; case CIRRUS_ROP_NOTDST: rop_handler = bitblt_rop_bkwd_notdst; break; case CIRRUS_ROP_SRC: rop_handler = bitblt_rop_bkwd_src; break; case CIRRUS_ROP_1: rop_handler = bitblt_rop_bkwd_1; break; case CIRRUS_ROP_NOTSRC_AND_DST: rop_handler = bitblt_rop_bkwd_notsrc_and_dst; break; case CIRRUS_ROP_SRC_XOR_DST: rop_handler = bitblt_rop_bkwd_src_xor_dst; break; case CIRRUS_ROP_SRC_OR_DST: rop_handler = bitblt_rop_bkwd_src_or_dst; break; case CIRRUS_ROP_NOTSRC_OR_NOTDST: rop_handler = bitblt_rop_bkwd_notsrc_or_notdst; break; case CIRRUS_ROP_SRC_NOTXOR_DST: rop_handler = bitblt_rop_bkwd_src_notxor_dst; break; case CIRRUS_ROP_SRC_OR_NOTDST: rop_handler = bitblt_rop_bkwd_src_or_notdst; break; case CIRRUS_ROP_NOTSRC: rop_handler = bitblt_rop_bkwd_notsrc; break; case CIRRUS_ROP_NOTSRC_OR_DST: rop_handler = bitblt_rop_bkwd_notsrc_or_dst; break; case CIRRUS_ROP_NOTSRC_AND_NOTDST: rop_handler = bitblt_rop_bkwd_notsrc_and_notdst; break; default: BX_ERROR(("unknown ROP %02x",rop)); break; } return rop_handler; } #if BX_DEBUGGER void bx_svga_cirrus_c::debug_dump(int argc, char **argv) { if ((BX_CIRRUS_THIS sequencer.reg[0x07] & 0x01) == CIRRUS_SR7_BPP_SVGA) { #if BX_SUPPORT_PCI if (BX_CIRRUS_THIS pci_enabled) { dbg_printf("CL-GD5446 PCI\n\n"); } else #endif { dbg_printf("CL-GD5430 ISA\n\n"); } dbg_printf("current mode: %u x %u x %u\n", BX_CIRRUS_THIS svga_xres, BX_CIRRUS_THIS svga_yres, BX_CIRRUS_THIS svga_dispbpp); } else { bx_vgacore_c::debug_dump(); } if (argc > 0) { dbg_printf("\nAdditional options not supported\n"); } } #endif #endif // BX_SUPPORT_CLGD54XX bochs-2.6/iodev/harddrv.cc0000644000175000017500000044570312020641505015414 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: harddrv.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Useful docs: // AT Attachment with Packet Interface // working draft by T13 at www.t13.org // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "harddrv.h" #include "hdimage/hdimage.h" #include "hdimage/cdrom.h" #define LOG_THIS theHardDrive-> #define INDEX_PULSE_CYCLE 10 #define PACKET_SIZE 12 // some packet handling macros #define EXTRACT_FIELD(arr,byte,start,num_bits) (((arr)[(byte)] >> (start)) & ((1 << (num_bits)) - 1)) #define get_packet_field(controller,b,s,n) (EXTRACT_FIELD((controller->buffer),(b),(s),(n))) #define get_packet_byte(controller,b) (controller->buffer[(b)]) #define get_packet_word(controller,b) (((Bit16u)controller->buffer[(b)] << 8) | controller->buffer[(b)+1]) #define BX_CONTROLLER(c,a) (BX_HD_THIS channels[(c)].drives[(a)]).controller #define BX_DRIVE(c,a) (BX_HD_THIS channels[(c)].drives[(a)]) #define BX_DRIVE_IS_PRESENT(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type != IDE_NONE) #define BX_DRIVE_IS_HD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_DISK) #define BX_DRIVE_IS_CD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_CDROM) #define BX_MASTER_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),0) #define BX_SLAVE_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),1) #define BX_ANY_IS_PRESENT(c) (BX_DRIVE_IS_PRESENT((c),0) || BX_DRIVE_IS_PRESENT((c),1)) #define BX_SELECTED_CONTROLLER(c) (BX_CONTROLLER((c),BX_HD_THIS channels[(c)].drive_select)) #define BX_SELECTED_DRIVE(c) (BX_DRIVE((c),BX_HD_THIS channels[(c)].drive_select)) #define BX_MASTER_SELECTED(c) (!BX_HD_THIS channels[(c)].drive_select) #define BX_SLAVE_SELECTED(c) (BX_HD_THIS channels[(c)].drive_select) #define BX_SELECTED_IS_PRESENT(c) (BX_DRIVE_IS_PRESENT((c),BX_SLAVE_SELECTED((c)))) #define BX_SELECTED_IS_HD(c) (BX_DRIVE_IS_HD((c),BX_SLAVE_SELECTED((c)))) #define BX_SELECTED_IS_CD(c) (BX_DRIVE_IS_CD((c),BX_SLAVE_SELECTED((c)))) #define BX_SELECTED_MODEL(c) (BX_HD_THIS channels[(c)].drives[BX_HD_THIS channels[(c)].drive_select].model_no) #define BX_SELECTED_TYPE_STRING(channel) ((BX_SELECTED_IS_CD(channel)) ? "CD-ROM" : "DISK") #define WRITE_FEATURES(c,a) do { Bit8u _a = a; \ BX_CONTROLLER((c),0).hob.feature = BX_CONTROLLER((c),0).features; \ BX_CONTROLLER((c),1).hob.feature = BX_CONTROLLER((c),1).features; \ BX_CONTROLLER((c),0).features = _a; BX_CONTROLLER((c),1).features = _a; } while(0) #define WRITE_SECTOR_COUNT(c,a) do { Bit8u _a = a; \ BX_CONTROLLER((c),0).hob.nsector = BX_CONTROLLER((c),0).sector_count; \ BX_CONTROLLER((c),1).hob.nsector = BX_CONTROLLER((c),1).sector_count; \ BX_CONTROLLER((c),0).sector_count = _a; BX_CONTROLLER((c),1).sector_count = _a; } while(0) #define WRITE_SECTOR_NUMBER(c,a) do { Bit8u _a = a; \ BX_CONTROLLER((c),0).hob.sector = BX_CONTROLLER((c),0).sector_no; \ BX_CONTROLLER((c),1).hob.sector = BX_CONTROLLER((c),1).sector_no; \ BX_CONTROLLER((c),0).sector_no = _a; BX_CONTROLLER((c),1).sector_no = _a; } while(0) #define WRITE_CYLINDER_LOW(c,a) do { Bit8u _a = a; \ BX_CONTROLLER((c),0).hob.lcyl = (Bit8u)(BX_CONTROLLER((c),0).cylinder_no & 0xff); \ BX_CONTROLLER((c),1).hob.lcyl = (Bit8u)(BX_CONTROLLER((c),1).cylinder_no & 0xff); \ BX_CONTROLLER((c),0).cylinder_no = (BX_CONTROLLER((c),0).cylinder_no & 0xff00) | _a; \ BX_CONTROLLER((c),1).cylinder_no = (BX_CONTROLLER((c),1).cylinder_no & 0xff00) | _a; } while(0) #define WRITE_CYLINDER_HIGH(c,a) do { Bit16u _a = a; \ BX_CONTROLLER((c),0).hob.hcyl = (Bit8u)(BX_CONTROLLER((c),0).cylinder_no >> 8); \ BX_CONTROLLER((c),1).hob.hcyl = (Bit8u)(BX_CONTROLLER((c),1).cylinder_no >> 8); \ BX_CONTROLLER((c),0).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),0).cylinder_no & 0xff); \ BX_CONTROLLER((c),1).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),1).cylinder_no & 0xff); } while(0) #define WRITE_HEAD_NO(c,a) do { Bit8u _a = a; BX_CONTROLLER((c),0).head_no = _a; BX_CONTROLLER((c),1).head_no = _a; } while(0) #define WRITE_LBA_MODE(c,a) do { Bit8u _a = a; BX_CONTROLLER((c),0).lba_mode = _a; BX_CONTROLLER((c),1).lba_mode = _a; } while(0) BX_CPP_INLINE Bit16u read_16bit(const Bit8u* buf) { return (buf[0] << 8) | buf[1]; } BX_CPP_INLINE Bit32u read_32bit(const Bit8u* buf) { return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]; } bx_hard_drive_c *theHardDrive = NULL; int libharddrv_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theHardDrive = new bx_hard_drive_c(); bx_devices.pluginHardDrive = theHardDrive; BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theHardDrive, BX_PLUGIN_HARDDRV); return(0); // Success } void libharddrv_LTX_plugin_fini(void) { delete theHardDrive; } bx_hard_drive_c::bx_hard_drive_c() { #if DLL_HD_SUPPORT # error code must be fixed to use DLL_HD_SUPPORT and 4 ata channels #endif put("harddrv", "HD"); for (Bit8u channel=0; channelclose(); delete channels[channel].drives[device].hdimage; channels[channel].drives[device].hdimage = NULL; } #ifdef LOWLEVEL_CDROM if (channels[channel].drives[device].cdrom.cd != NULL) { delete channels[channel].drives[device].cdrom.cd; channels[channel].drives[device].cdrom.cd = NULL; } #endif sprintf(ata_name, "ata.%d.%s", channel, (device==0)?"master":"slave"); base = (bx_list_c*) SIM->get_param(ata_name); SIM->get_param_string("path", base)->set_handler(NULL); SIM->get_param_bool("status", base)->set_handler(NULL); } } SIM->get_bochs_root()->remove("hard_drive"); BX_DEBUG(("Exit")); } void bx_hard_drive_c::init(void) { Bit8u channel, image_mode; char string[5]; char sbtext[8]; char ata_name[20]; bx_list_c *base; BX_DEBUG(("Init $Id: harddrv.cc 11346 2012-08-19 08:16:20Z vruppert $")); for (channel=0; channelget_param(ata_name); if (SIM->get_param_bool("enabled", base)->get() == 1) { BX_HD_THIS channels[channel].ioaddr1 = SIM->get_param_num("ioaddr1", base)->get(); BX_HD_THIS channels[channel].ioaddr2 = SIM->get_param_num("ioaddr2", base)->get(); BX_HD_THIS channels[channel].irq = SIM->get_param_num("irq", base)->get(); // Coherency check if ((BX_HD_THIS channels[channel].ioaddr1 == 0) || (BX_HD_THIS channels[channel].ioaddr2 == 0) || (BX_HD_THIS channels[channel].irq == 0)) { BX_PANIC(("incoherency for ata channel %d: io1=0x%x, io2=%x, irq=%d", channel, BX_HD_THIS channels[channel].ioaddr1, BX_HD_THIS channels[channel].ioaddr2, BX_HD_THIS channels[channel].irq)); } } else { BX_HD_THIS channels[channel].ioaddr1 = 0; BX_HD_THIS channels[channel].ioaddr2 = 0; BX_HD_THIS channels[channel].irq = 0; } } for (channel=0; channelget_param(ata_name); // Initialize controller state, even if device is not present BX_CONTROLLER(channel,device).status.busy = 0; BX_CONTROLLER(channel,device).status.drive_ready = 1; BX_CONTROLLER(channel,device).status.write_fault = 0; BX_CONTROLLER(channel,device).status.seek_complete = 1; BX_CONTROLLER(channel,device).status.drq = 0; BX_CONTROLLER(channel,device).status.corrected_data = 0; BX_CONTROLLER(channel,device).status.index_pulse = 0; BX_CONTROLLER(channel,device).status.index_pulse_count = 0; BX_CONTROLLER(channel,device).status.err = 0; BX_CONTROLLER(channel,device).error_register = 0x01; // diagnostic code: no error BX_CONTROLLER(channel,device).head_no = 0; BX_CONTROLLER(channel,device).sector_count = 1; BX_CONTROLLER(channel,device).sector_no = 1; BX_CONTROLLER(channel,device).cylinder_no = 0; BX_CONTROLLER(channel,device).current_command = 0x00; BX_CONTROLLER(channel,device).buffer_index = 0; BX_CONTROLLER(channel,device).control.reset = 0; BX_CONTROLLER(channel,device).control.disable_irq = 0; BX_CONTROLLER(channel,device).reset_in_progress = 0; BX_CONTROLLER(channel,device).multiple_sectors = 0; BX_CONTROLLER(channel,device).lba_mode = 0; BX_CONTROLLER(channel,device).features = 0; BX_CONTROLLER(channel,device).mdma_mode = 0; BX_CONTROLLER(channel,device).udma_mode = 0; // If not present BX_HD_THIS channels[channel].drives[device].device_type = IDE_NONE; BX_HD_THIS channels[channel].drives[device].statusbar_id = -1; BX_HD_THIS channels[channel].drives[device].identify_set = 0; if (!SIM->get_param_bool("present", base)->get()) continue; // Make model string strncpy((char*)BX_HD_THIS channels[channel].drives[device].model_no, SIM->get_param_string("model", base)->getptr(), 40); while (strlen((char *)BX_HD_THIS channels[channel].drives[device].model_no) < 40) { strcat((char*)BX_HD_THIS channels[channel].drives[device].model_no, " "); } BX_HD_THIS channels[channel].drives[device].model_no[40] = 0; if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_DISK) { BX_DEBUG(("Hard-Disk on target %d/%d",channel,device)); BX_HD_THIS channels[channel].drives[device].device_type = IDE_DISK; sprintf(sbtext, "HD:%d-%s", channel, device?"S":"M"); BX_HD_THIS channels[channel].drives[device].statusbar_id = bx_gui->register_statusitem(sbtext, 1); int cyl = SIM->get_param_num("cylinders", base)->get(); int heads = SIM->get_param_num("heads", base)->get(); int spt = SIM->get_param_num("spt", base)->get(); Bit64u disk_size = (Bit64u)cyl * heads * spt * 512; image_mode = SIM->get_param_enum("mode", base)->get(); channels[channel].drives[device].hdimage = DEV_hdimage_init_image(image_mode, disk_size, SIM->get_param_string("journal", base)->getptr()); if (channels[channel].drives[device].hdimage != NULL) { BX_INFO(("HD on ata%d-%d: '%s', '%s' mode", channel, device, SIM->get_param_string("path", base)->getptr(), hdimage_mode_names[image_mode])); } else { // it's safe to return here on failure return; } BX_HD_THIS channels[channel].drives[device].hdimage->cylinders = cyl; BX_HD_THIS channels[channel].drives[device].hdimage->heads = heads; BX_HD_THIS channels[channel].drives[device].hdimage->spt = spt; /* open hard drive image file */ if ((BX_HD_THIS channels[channel].drives[device].hdimage->open(SIM->get_param_string("path", base)->getptr())) < 0) { BX_PANIC(("ata%d-%d: could not open hard drive image file '%s'", channel, device, SIM->get_param_string("path", base)->getptr())); return; } Bit32u image_caps = BX_HD_THIS channels[channel].drives[device].hdimage->get_capabilities(); if ((image_caps & HDIMAGE_HAS_GEOMETRY) != 0) { // If the image provides a geometry, always use it. cyl = BX_HD_THIS channels[channel].drives[device].hdimage->cylinders; heads = BX_HD_THIS channels[channel].drives[device].hdimage->heads; spt = BX_HD_THIS channels[channel].drives[device].hdimage->spt; BX_INFO(("ata%d-%d: image geometry: CHS=%d/%d/%d", channel, device, cyl, heads, spt)); } else { if ((cyl == 0) && (image_caps & HDIMAGE_AUTO_GEOMETRY)) { // Autodetect number of cylinders if ((heads == 0) || (spt == 0)) { BX_PANIC(("ata%d-%d cannot have zero heads, or sectors/track", channel, device)); } cyl = (int)(BX_HD_THIS channels[channel].drives[device].hdimage->hd_size / (heads * spt * 512)); disk_size = ((Bit64u)cyl * heads * spt * 512); BX_HD_THIS channels[channel].drives[device].hdimage->cylinders = cyl; BX_INFO(("ata%d-%d: autodetect geometry: CHS=%d/%d/%d", channel, device, cyl, heads, spt)); } else { // Default method: use CHS from configuration. if (cyl == 0 || heads == 0 || spt == 0) { BX_PANIC(("ata%d-%d cannot have zero cylinders, heads, or sectors/track", channel, device)); } BX_INFO(("ata%d-%d: using specified geometry: CHS=%d/%d/%d", channel, device, cyl, heads, spt)); } if (disk_size > BX_HD_THIS channels[channel].drives[device].hdimage->hd_size) { BX_PANIC(("ata%d-%d: specified geometry doesn't fit on disk image", channel, device)); } else if (disk_size < BX_HD_THIS channels[channel].drives[device].hdimage->hd_size) { BX_INFO(("ata%d-%d: extra data outside of CHS address range", channel, device)); } } } else if (SIM->get_param_enum("type", base)->get() == BX_ATA_DEVICE_CDROM) { bx_list_c *cdrom_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_CDROM); cdrom_rt->add(base); base->set_options(base->SERIES_ASK | base->USE_BOX_TITLE); base->set_runtime_param(1); SIM->get_param_string("path", base)->set_handler(cdrom_path_handler); SIM->get_param("path", base)->set_runtime_param(1); SIM->get_param_bool("status", base)->set_handler(cdrom_status_handler); SIM->get_param("status", base)->set_runtime_param(1); BX_DEBUG(("CDROM on target %d/%d",channel,device)); BX_HD_THIS channels[channel].drives[device].device_type = IDE_CDROM; BX_HD_THIS channels[channel].drives[device].cdrom.locked = 0; BX_HD_THIS channels[channel].drives[device].sense.sense_key = SENSE_NONE; BX_HD_THIS channels[channel].drives[device].sense.asc = 0; BX_HD_THIS channels[channel].drives[device].sense.ascq = 0; sprintf(sbtext, "CD:%d-%s", channel, device?"S":"M"); BX_HD_THIS channels[channel].drives[device].statusbar_id = bx_gui->register_statusitem(sbtext, 1); BX_HD_THIS cdrom_count++; BX_HD_THIS channels[channel].drives[device].device_num = BX_HD_THIS cdrom_count + 48; // Check bit fields BX_CONTROLLER(channel,device).sector_count = 0; BX_CONTROLLER(channel,device).interrupt_reason.c_d = 1; if (BX_CONTROLLER(channel,device).sector_count != 0x01) BX_PANIC(("interrupt reason bit field error")); BX_CONTROLLER(channel,device).sector_count = 0; BX_CONTROLLER(channel,device).interrupt_reason.i_o = 1; if (BX_CONTROLLER(channel,device).sector_count != 0x02) BX_PANIC(("interrupt reason bit field error")); BX_CONTROLLER(channel,device).sector_count = 0; BX_CONTROLLER(channel,device).interrupt_reason.rel = 1; if (BX_CONTROLLER(channel,device).sector_count != 0x04) BX_PANIC(("interrupt reason bit field error")); BX_CONTROLLER(channel,device).sector_count = 0; BX_CONTROLLER(channel,device).interrupt_reason.tag = 3; if (BX_CONTROLLER(channel,device).sector_count != 0x18) BX_PANIC(("interrupt reason bit field error")); BX_CONTROLLER(channel,device).sector_count = 0; // allocate low level driver #ifdef LOWLEVEL_CDROM BX_HD_THIS channels[channel].drives[device].cdrom.cd = DEV_hdimage_init_cdrom(SIM->get_param_string("path", base)->getptr()); BX_INFO(("CD on ata%d-%d: '%s'",channel, device, SIM->get_param_string("path", base)->getptr())); if (SIM->get_param_bool("status", base)->get()) { if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom()) { BX_INFO(("Media present in CD-ROM drive")); BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1; Bit32u capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity(); BX_HD_THIS channels[channel].drives[device].cdrom.capacity = capacity; BX_INFO(("Capacity is %d sectors (%.2f MB)", capacity, (float)capacity / 512.0)); } else { BX_INFO(("Could not locate CD-ROM, continuing with media not present")); BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; SIM->get_param_bool("status", base)->set(0); } } else #endif { BX_INFO(("Media not present in CD-ROM drive")); BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; } } } } // generate CMOS values for hard drive if not using a CMOS image if (!SIM->get_param_bool(BXPN_CMOSIMAGE_ENABLED)->get()) { DEV_cmos_set_reg(0x12, 0x00); // start out with: no drive 0, no drive 1 if (BX_DRIVE_IS_HD(0,0)) { // Flag drive type as Fh, use extended CMOS location as real type DEV_cmos_set_reg(0x12, (DEV_cmos_get_reg(0x12) & 0x0f) | 0xf0); DEV_cmos_set_reg(0x19, 47); // user definable type // AMI BIOS: 1st hard disk #cyl low byte DEV_cmos_set_reg(0x1b, (BX_DRIVE(0,0).hdimage->cylinders & 0x00ff)); // AMI BIOS: 1st hard disk #cyl high byte DEV_cmos_set_reg(0x1c, (BX_DRIVE(0,0).hdimage->cylinders & 0xff00) >> 8); // AMI BIOS: 1st hard disk #heads DEV_cmos_set_reg(0x1d, BX_DRIVE(0,0).hdimage->heads); // AMI BIOS: 1st hard disk write precompensation cylinder, low byte DEV_cmos_set_reg(0x1e, 0xff); // -1 // AMI BIOS: 1st hard disk write precompensation cylinder, high byte DEV_cmos_set_reg(0x1f, 0xff); // -1 // AMI BIOS: 1st hard disk control byte DEV_cmos_set_reg(0x20, (0xc0 | ((BX_DRIVE(0,0).hdimage->heads > 8) << 3))); // AMI BIOS: 1st hard disk landing zone, low byte DEV_cmos_set_reg(0x21, DEV_cmos_get_reg(0x1b)); // AMI BIOS: 1st hard disk landing zone, high byte DEV_cmos_set_reg(0x22, DEV_cmos_get_reg(0x1c)); // AMI BIOS: 1st hard disk sectors/track DEV_cmos_set_reg(0x23, BX_DRIVE(0,0).hdimage->spt); } //set up cmos for second hard drive if (BX_DRIVE_IS_HD(0,1)) { // fill in lower 4 bits of 0x12 for second HD DEV_cmos_set_reg(0x12, (DEV_cmos_get_reg(0x12) & 0xf0) | 0x0f); DEV_cmos_set_reg(0x1a, 47); // user definable type // AMI BIOS: 2nd hard disk #cyl low byte DEV_cmos_set_reg(0x24, (BX_DRIVE(0,1).hdimage->cylinders & 0x00ff)); // AMI BIOS: 2nd hard disk #cyl high byte DEV_cmos_set_reg(0x25, (BX_DRIVE(0,1).hdimage->cylinders & 0xff00) >> 8); // AMI BIOS: 2nd hard disk #heads DEV_cmos_set_reg(0x26, BX_DRIVE(0,1).hdimage->heads); // AMI BIOS: 2nd hard disk write precompensation cylinder, low byte DEV_cmos_set_reg(0x27, 0xff); // -1 // AMI BIOS: 2nd hard disk write precompensation cylinder, high byte DEV_cmos_set_reg(0x28, 0xff); // -1 // AMI BIOS: 2nd hard disk, 0x80 if heads>8 DEV_cmos_set_reg(0x29, (BX_DRIVE(0,1).hdimage->heads > 8) ? 0x80 : 0x00); // AMI BIOS: 2nd hard disk landing zone, low byte DEV_cmos_set_reg(0x2a, DEV_cmos_get_reg(0x24)); // AMI BIOS: 2nd hard disk landing zone, high byte DEV_cmos_set_reg(0x2b, DEV_cmos_get_reg(0x25)); // AMI BIOS: 2nd hard disk sectors/track DEV_cmos_set_reg(0x2c, BX_DRIVE(0,1).hdimage->spt); } DEV_cmos_set_reg(0x39, 0); DEV_cmos_set_reg(0x3a, 0); for (channel=0; channelget_param(ata_name); if (SIM->get_param_bool("present", base)->get()) { if (BX_DRIVE_IS_HD(channel,device)) { Bit16u cylinders = BX_DRIVE(channel,device).hdimage->cylinders; Bit16u heads = BX_DRIVE(channel,device).hdimage->heads; Bit16u spt = BX_DRIVE(channel,device).hdimage->spt; Bit8u translation = SIM->get_param_enum("translation", base)->get(); Bit8u reg = 0x39 + channel/2; Bit8u bitshift = 2 * (device+(2 * (channel%2))); // Find the right translation if autodetect if (translation == BX_ATA_TRANSLATION_AUTO) { if((cylinders <= 1024) && (heads <= 16) && (spt <= 63)) { translation = BX_ATA_TRANSLATION_NONE; } else if (((Bit32u)cylinders * (Bit32u)heads) <= 131072) { translation = BX_ATA_TRANSLATION_LARGE; } else translation = BX_ATA_TRANSLATION_LBA; BX_INFO(("translation on ata%d-%d set to '%s'",channel, device, translation==BX_ATA_TRANSLATION_NONE?"none": translation==BX_ATA_TRANSLATION_LARGE?"large": "lba")); } // FIXME we should test and warn // - if LBA and spt != 63 // - if RECHS and heads != 16 // - if NONE and size > 1024*16*SPT blocks // - if LARGE and size > 8192*16*SPT blocks // - if RECHS and size > 1024*240*SPT blocks // - if LBA and size > 1024*255*63, not that we can do much about it switch(translation) { case BX_ATA_TRANSLATION_NONE: DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (0 << bitshift)); break; case BX_ATA_TRANSLATION_LBA: DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (1 << bitshift)); break; case BX_ATA_TRANSLATION_LARGE: DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (2 << bitshift)); break; case BX_ATA_TRANSLATION_RECHS: DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (3 << bitshift)); break; } } } } } // Set the "non-extended" boot device. This will default to DISKC if cdrom if (SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() != BX_BOOT_FLOPPYA) { // system boot sequence C:, A: DEV_cmos_set_reg(0x2d, DEV_cmos_get_reg(0x2d) & 0xdf); } else { // 'a' // system boot sequence A:, C: DEV_cmos_set_reg(0x2d, DEV_cmos_get_reg(0x2d) | 0x20); } // Set the "extended" boot sequence, bytes 0x38 and 0x3D (needed for cdrom booting) BX_INFO(("Using boot sequence %s, %s, %s", SIM->get_param_enum(BXPN_BOOTDRIVE1)->get_selected(), SIM->get_param_enum(BXPN_BOOTDRIVE2)->get_selected(), SIM->get_param_enum(BXPN_BOOTDRIVE3)->get_selected())); DEV_cmos_set_reg(0x3d, SIM->get_param_enum(BXPN_BOOTDRIVE1)->get() | (SIM->get_param_enum(BXPN_BOOTDRIVE2)->get() << 4)); // Set the signature check flag in cmos, inverted for compatibility DEV_cmos_set_reg(0x38, SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->get() | (SIM->get_param_enum(BXPN_BOOTDRIVE3)->get() << 4)); BX_INFO(("Floppy boot signature check is %sabled", SIM->get_param_bool(BXPN_FLOPPYSIGCHECK)->get() ? "dis" : "en")); } // register timer for HD/CD seek emulation if (BX_HD_THIS seek_timer_index == BX_NULL_TIMER_HANDLE) { BX_HD_THIS seek_timer_index = DEV_register_timer(this, seek_timer_handler, 100000, 0,0, "HD/CD seek"); // TODO !!! } BX_HD_THIS pci_enabled = SIM->get_param_bool(BXPN_I440FX_SUPPORT)->get(); // register handler for correct cdrom parameter handling after runtime config SIM->register_runtime_config_handler(BX_HD_THIS_PTR, runtime_config_handler); } void bx_hard_drive_c::reset(unsigned type) { for (unsigned channel=0; channelget_bochs_root(), "hard_drive", "Hard Drive State"); for (i=0; iseek_timer(); } void bx_hard_drive_c::seek_timer() { for (unsigned channel=0; channelruntime_config(); } void bx_hard_drive_c::runtime_config(void) { char pname[16]; int handle; bx_bool status; for (Bit8u channel=0; channelget_param(pname); status = SIM->get_param_bool("status", base)->get(); BX_HD_THIS set_cd_media_status(handle, 0); if (status == 1) { BX_HD_THIS set_cd_media_status(handle, status); } BX_HD_THIS channels[channel].drives[device].status_changed = 0; } } } } #define GOTO_RETURN_VALUE if(io_len==4) { \ goto return_value32; \ } \ else if(io_len==2) { \ value16=(Bit16u)value32; \ goto return_value16; \ } \ else { \ value8=(Bit8u)value32; \ goto return_value8; \ } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_hard_drive_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_HD_SMF bx_hard_drive_c *class_ptr = (bx_hard_drive_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_hard_drive_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_HD_SMF Bit8u value8; Bit16u value16; Bit32u value32; Bit8u channel = BX_MAX_ATA_CHANNEL; Bit32u port = 0xff; // undefined for (channel=0; channel 0x03f7)) { BX_PANIC(("read: unable to find ATA channel, ioport=0x%04x", address)); } else { channel = 0; port = address - 0x03e0; } } controller_t *controller = &BX_SELECTED_CONTROLLER(channel); switch (port) { case 0x00: // hard disk data (16bit) 0x1f0 if (controller->status.drq == 0) { BX_ERROR(("IO read(0x%04x) with drq == 0: last command was %02xh", address, (unsigned) controller->current_command)); return(0); } BX_DEBUG(("IO read(0x%04x): current command is %02xh", address, (unsigned) controller->current_command)); switch (controller->current_command) { case 0x20: // READ SECTORS, with retries case 0x21: // READ SECTORS, without retries case 0xC4: // READ MULTIPLE SECTORS case 0x24: // READ SECTORS EXT case 0x29: // READ MULTIPLE EXT if (controller->buffer_index >= controller->buffer_size) BX_PANIC(("IO read(0x%04x): buffer_index >= %d", address, controller->buffer_size)); #if BX_SupportRepeatSpeedups if (DEV_bulk_io_quantum_requested()) { unsigned transferLen, quantumsMax; quantumsMax = (controller->buffer_size - controller->buffer_index) / io_len; if (quantumsMax == 0) BX_PANIC(("IO read(0x%04x): not enough space for read", address)); DEV_bulk_io_quantum_transferred() = DEV_bulk_io_quantum_requested(); if (quantumsMax < DEV_bulk_io_quantum_transferred()) DEV_bulk_io_quantum_transferred() = quantumsMax; transferLen = io_len * DEV_bulk_io_quantum_transferred(); memcpy((Bit8u*) DEV_bulk_io_host_addr(), &controller->buffer[controller->buffer_index], transferLen); DEV_bulk_io_host_addr() += transferLen; controller->buffer_index += transferLen; value32 = 0; // Value returned not important; } else #endif { value32 = 0L; switch(io_len){ case 4: value32 |= (controller->buffer[controller->buffer_index+3] << 24); value32 |= (controller->buffer[controller->buffer_index+2] << 16); case 2: value32 |= (controller->buffer[controller->buffer_index+1] << 8); value32 |= controller->buffer[controller->buffer_index]; } controller->buffer_index += io_len; } // if buffer completely read if (controller->buffer_index >= controller->buffer_size) { // update sector count, sector number, cylinder, // drive, head, status // if there are more sectors, read next one in... // if ((controller->current_command == 0xC4) || (controller->current_command == 0x29)) { if (controller->num_sectors > controller->multiple_sectors) { controller->buffer_size = controller->multiple_sectors * 512; } else { controller->buffer_size = controller->num_sectors * 512; } } controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.seek_complete = 1; controller->status.corrected_data = 0; controller->status.err = 0; if (controller->num_sectors==0) { controller->status.drq = 0; } else { /* read next one into controller buffer */ controller->status.drq = 1; controller->status.seek_complete = 1; if (ide_read_sector(channel, controller->buffer, controller->buffer_size)) { controller->buffer_index = 0; raise_interrupt(channel); } } } GOTO_RETURN_VALUE; break; case 0xec: // IDENTIFY DEVICE case 0xa1: unsigned index; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.seek_complete = 1; controller->status.corrected_data = 0; controller->status.err = 0; index = controller->buffer_index; value32 = controller->buffer[index]; index++; if (io_len >= 2) { value32 |= (controller->buffer[index] << 8); index++; } if (io_len == 4) { value32 |= (controller->buffer[index] << 16); value32 |= (controller->buffer[index+1] << 24); index += 2; } controller->buffer_index = index; if (controller->buffer_index >= 512) { controller->status.drq = 0; BX_DEBUG(("Read all drive ID Bytes ...")); } GOTO_RETURN_VALUE; break; case 0xa0: { unsigned index = controller->buffer_index; unsigned increment = 0; // Load block if necessary if (index >= controller->buffer_size) { if (index > controller->buffer_size) BX_PANIC(("index > %d : %d", controller->buffer_size, index)); switch (BX_SELECTED_DRIVE(channel).atapi.command) { case 0x28: // read (10) case 0xa8: // read (12) case 0xbe: // read cd #ifdef LOWLEVEL_CDROM if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { BX_PANIC(("Read with CDROM not ready")); } /* set status bar conditions for device */ bx_gui->statusbar_setitem(BX_SELECTED_DRIVE(channel).statusbar_id, 1); if (!BX_SELECTED_DRIVE(channel).cdrom.cd->read_block(controller->buffer, BX_SELECTED_DRIVE(channel).cdrom.next_lba, controller->buffer_size)) { BX_PANIC(("CDROM: read block %d failed", BX_SELECTED_DRIVE(channel).cdrom.next_lba)); } BX_SELECTED_DRIVE(channel).cdrom.next_lba++; BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks--; if (!BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks) { BX_DEBUG(("CDROM: last READ block loaded")); } else { BX_DEBUG(("CDROM: READ block loaded (%d remaining)", BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks)); } // one block transfered, start at beginning index = 0; #else BX_PANIC(("Read with no LOWLEVEL_CDROM")); #endif break; default: // no need to load a new block break; } } value32 = controller->buffer[index+increment]; increment++; if (io_len >= 2) { value32 |= (controller->buffer[index+increment] << 8); increment++; } if (io_len == 4) { value32 |= (controller->buffer[index+increment] << 16); value32 |= (controller->buffer[index+increment+1] << 24); increment += 2; } controller->buffer_index = index + increment; controller->drq_index += increment; if (controller->drq_index >= (unsigned)BX_SELECTED_DRIVE(channel).atapi.drq_bytes) { controller->status.drq = 0; controller->drq_index = 0; BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining -= BX_SELECTED_DRIVE(channel).atapi.drq_bytes; if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining > 0) { // one or more blocks remaining (works only for single block commands) BX_DEBUG(("PACKET drq bytes read")); controller->interrupt_reason.i_o = 1; controller->status.busy = 0; controller->status.drq = 1; controller->interrupt_reason.c_d = 0; // set new byte count if last block if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining < controller->byte_count) { controller->byte_count = BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining; } BX_SELECTED_DRIVE(channel).atapi.drq_bytes = controller->byte_count; raise_interrupt(channel); } else { // all bytes read BX_DEBUG(("PACKET all bytes read")); controller->interrupt_reason.i_o = 1; controller->interrupt_reason.c_d = 1; controller->status.drive_ready = 1; controller->interrupt_reason.rel = 0; controller->status.busy = 0; controller->status.drq = 0; controller->status.err = 0; raise_interrupt(channel); } } GOTO_RETURN_VALUE; } break; default: BX_ERROR(("read from 0x%04x: current command is 0x%02x", address, controller->current_command)); } break; case 0x01: // hard disk error register 0x1f1 // -- WARNING : On real hardware the controller registers are shared between drives. // So we must respond even if the select device is not present. Some OS uses this fact // to detect the disks.... minix2 for example value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : controller->error_register; goto return_value8; case 0x02: // hard disk sector count / interrupt reason 0x1f2 value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : controller->sector_count; goto return_value8; case 0x03: // sector number 0x1f3 value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : controller->sector_no; goto return_value8; case 0x04: // cylinder low 0x1f4 value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : (controller->cylinder_no & 0x00ff); goto return_value8; case 0x05: // cylinder high 0x1f5 value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : controller->cylinder_no >> 8; goto return_value8; case 0x06: // hard disk drive and head register 0x1f6 // b7 Extended data field for ECC // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 // Since 512 was always used, bit 6 was taken to mean LBA mode: // b6 1=LBA mode, 0=CHS mode // b5 1 // b4: DRV // b3..0 HD3..HD0 value8 = (1 << 7) | (controller->lba_mode << 6) | (1 << 5) | // 01b = 512 sector size (BX_HD_THIS channels[channel].drive_select << 4) | (controller->head_no << 0); goto return_value8; case 0x07: // Hard Disk Status 0x1f7 case 0x16: // Hard Disk Alternate Status 0x3f6 if (!BX_SELECTED_IS_PRESENT(channel)) { // (mch) Just return zero for these registers value8 = 0; } else { value8 = ( (controller->status.busy << 7) | (controller->status.drive_ready << 6) | (controller->status.write_fault << 5) | (controller->status.seek_complete << 4) | (controller->status.drq << 3) | (controller->status.corrected_data << 2) | (controller->status.index_pulse << 1) | (controller->status.err)); controller->status.index_pulse_count++; controller->status.index_pulse = 0; if (controller->status.index_pulse_count >= INDEX_PULSE_CYCLE) { controller->status.index_pulse = 1; controller->status.index_pulse_count = 0; } } if (port == 0x07) { DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq); } goto return_value8; case 0x17: // Hard Disk Address Register 0x3f7 // Obsolete and unsupported register. Not driven by hard // disk controller. Report all 1's. If floppy controller // is handling this address, it will call this function // set/clear D7 (the only bit it handles), then return // the combined value value8 = 0xff; goto return_value8; default: BX_PANIC(("hard drive: io read to address %x unsupported", (unsigned) address)); } BX_PANIC(("hard drive: shouldnt get here!")); return(0); return_value32: BX_DEBUG(("32-bit read from %04x = %08x {%s}", (unsigned) address, value32, BX_SELECTED_TYPE_STRING(channel))); return value32; return_value16: BX_DEBUG(("16-bit read from %04x = %04x {%s}", (unsigned) address, value16, BX_SELECTED_TYPE_STRING(channel))); return value16; return_value8: BX_DEBUG(("8-bit read from %04x = %02x {%s}", (unsigned) address, value8, BX_SELECTED_TYPE_STRING(channel))); return value8; } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_hard_drive_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_HD_SMF bx_hard_drive_c *class_ptr = (bx_hard_drive_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_hard_drive_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_HD_SMF Bit64s logical_sector; bx_bool prev_control_reset; bx_bool lba48 = 0; Bit8u channel = BX_MAX_ATA_CHANNEL; Bit32u port = 0xff; // undefined int i; for (channel=0; channelcurrent_command) { case 0x30: // WRITE SECTORS case 0xC5: // WRITE MULTIPLE SECTORS case 0x34: // WRITE SECTORS EXT case 0x39: // WRITE MULTIPLE EXT if (controller->buffer_index >= controller->buffer_size) BX_PANIC(("IO write(0x%04x): buffer_index >= %d", address, controller->buffer_size)); #if BX_SupportRepeatSpeedups if (DEV_bulk_io_quantum_requested()) { unsigned transferLen, quantumsMax; quantumsMax = (controller->buffer_size - controller->buffer_index) / io_len; if (quantumsMax == 0) BX_PANIC(("IO write(0x%04x): not enough space for write", address)); DEV_bulk_io_quantum_transferred() = DEV_bulk_io_quantum_requested(); if (quantumsMax < DEV_bulk_io_quantum_transferred()) DEV_bulk_io_quantum_transferred() = quantumsMax; transferLen = io_len * DEV_bulk_io_quantum_transferred(); memcpy(&controller->buffer[controller->buffer_index], (Bit8u*) DEV_bulk_io_host_addr(), transferLen); DEV_bulk_io_host_addr() += transferLen; controller->buffer_index += transferLen; } else #endif { switch(io_len) { case 4: controller->buffer[controller->buffer_index+3] = (Bit8u)(value >> 24); controller->buffer[controller->buffer_index+2] = (Bit8u)(value >> 16); case 2: controller->buffer[controller->buffer_index+1] = (Bit8u)(value >> 8); controller->buffer[controller->buffer_index] = (Bit8u) value; } controller->buffer_index += io_len; } /* if buffer completely writtten */ if (controller->buffer_index >= controller->buffer_size) { if (ide_write_sector(channel, controller->buffer, controller->buffer_size)) { if ((controller->current_command == 0xC5) || (controller->current_command == 0x39)) { if (controller->num_sectors > controller->multiple_sectors) { controller->buffer_size = controller->multiple_sectors * 512; } else { controller->buffer_size = controller->num_sectors * 512; } } controller->buffer_index = 0; /* When the write is complete, controller clears the DRQ bit and * sets the BSY bit. * If at least one more sector is to be written, controller sets DRQ bit, * clears BSY bit, and issues IRQ */ if (controller->num_sectors != 0) { controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.drq = 1; controller->status.corrected_data = 0; controller->status.err = 0; } else { /* no more sectors to write */ controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.drq = 0; controller->status.err = 0; controller->status.corrected_data = 0; } raise_interrupt(channel); } } break; case 0xa0: // PACKET if (controller->buffer_index >= PACKET_SIZE) BX_PANIC(("IO write(0x%04x): buffer_index >= PACKET_SIZE", address)); switch (io_len) { case 4: controller->buffer[controller->buffer_index+3] = (Bit8u)(value >> 24); controller->buffer[controller->buffer_index+2] = (Bit8u)(value >> 16); case 2: controller->buffer[controller->buffer_index+1] = (Bit8u)(value >> 8); controller->buffer[controller->buffer_index] = (Bit8u) value; } controller->buffer_index += io_len; /* if packet completely writtten */ if (controller->buffer_index >= PACKET_SIZE) { // complete command received Bit8u atapi_command = controller->buffer[0]; controller->buffer_size = 2048; BX_DEBUG(("ata%d-%d: ATAPI command 0x%02x started", channel, BX_SLAVE_SELECTED(channel), atapi_command)); switch (atapi_command) { case 0x00: // test unit ready if (BX_SELECTED_DRIVE(channel).cdrom.ready) { atapi_cmd_nop(controller); } else { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 0); } raise_interrupt(channel); break; case 0x03: // request sense { int alloc_length = controller->buffer[4]; init_send_atapi_command(channel, atapi_command, 18, alloc_length); // sense data controller->buffer[0] = 0x70 | (1 << 7); controller->buffer[1] = 0; controller->buffer[2] = BX_SELECTED_DRIVE(channel).sense.sense_key; controller->buffer[3] = BX_SELECTED_DRIVE(channel).sense.information.arr[0]; controller->buffer[4] = BX_SELECTED_DRIVE(channel).sense.information.arr[1]; controller->buffer[5] = BX_SELECTED_DRIVE(channel).sense.information.arr[2]; controller->buffer[6] = BX_SELECTED_DRIVE(channel).sense.information.arr[3]; controller->buffer[7] = 17-7; controller->buffer[8] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[0]; controller->buffer[9] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[1]; controller->buffer[10] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[2]; controller->buffer[11] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[3]; controller->buffer[12] = BX_SELECTED_DRIVE(channel).sense.asc; controller->buffer[13] = BX_SELECTED_DRIVE(channel).sense.ascq; controller->buffer[14] = BX_SELECTED_DRIVE(channel).sense.fruc; controller->buffer[15] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[0]; controller->buffer[16] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[1]; controller->buffer[17] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[2]; if (BX_SELECTED_DRIVE(channel).sense.sense_key == SENSE_UNIT_ATTENTION) { BX_SELECTED_DRIVE(channel).sense.sense_key = SENSE_NONE; } ready_to_send_atapi(channel); } break; case 0x1b: // start stop unit { char ata_name[20]; //bx_bool Immed = (controller->buffer[1] >> 0) & 1; bx_bool LoEj = (controller->buffer[4] >> 1) & 1; bx_bool Start = (controller->buffer[4] >> 0) & 1; if (!LoEj && !Start) { // stop the disc BX_ERROR(("FIXME: Stop disc not implemented")); atapi_cmd_nop(controller); raise_interrupt(channel); } else if (!LoEj && Start) { // start (spin up) the disc #ifdef LOWLEVEL_CDROM BX_SELECTED_DRIVE(channel).cdrom.cd->start_cdrom(); #endif BX_ERROR(("FIXME: ATAPI start disc not reading TOC")); atapi_cmd_nop(controller); raise_interrupt(channel); } else if (LoEj && !Start) { // Eject the disc atapi_cmd_nop(controller); if (BX_SELECTED_DRIVE(channel).cdrom.ready) { #ifdef LOWLEVEL_CDROM BX_SELECTED_DRIVE(channel).cdrom.cd->eject_cdrom(); #endif BX_SELECTED_DRIVE(channel).cdrom.ready = 0; sprintf(ata_name, "ata.%d.%s", channel, BX_SLAVE_SELECTED(channel)?"slave":"master"); bx_list_c *base = (bx_list_c*) SIM->get_param(ata_name); SIM->get_param_bool("status", base)->set(0); bx_gui->update_drive_status_buttons(); } raise_interrupt(channel); } else { // Load the disc // My guess is that this command only closes the tray, that's a no-op for us atapi_cmd_nop(controller); raise_interrupt(channel); } } break; case 0xbd: // mechanism status { Bit16u alloc_length = read_16bit(controller->buffer + 8); if (alloc_length == 0) BX_PANIC(("Zero allocation length to MECHANISM STATUS not impl.")); init_send_atapi_command(channel, atapi_command, 8, alloc_length); controller->buffer[0] = 0; // reserved for non changers controller->buffer[1] = 0; // reserved for non changers controller->buffer[2] = 0; // Current LBA (TODO!) controller->buffer[3] = 0; // Current LBA (TODO!) controller->buffer[4] = 0; // Current LBA (TODO!) controller->buffer[5] = 1; // one slot controller->buffer[6] = 0; // slot table length controller->buffer[7] = 0; // slot table length ready_to_send_atapi(channel); } break; case 0x1a: // mode sense (6) case 0x5a: // mode sense (10) { Bit16u alloc_length; if (atapi_command == 0x5a) { alloc_length = read_16bit(controller->buffer + 7); } else { alloc_length = controller->buffer[4]; } Bit8u PC = controller->buffer[2] >> 6; Bit8u PageCode = controller->buffer[2] & 0x3f; switch (PC) { case 0x0: // current values switch (PageCode) { case 0x01: // error recovery init_send_atapi_command(channel, atapi_command, sizeof(error_recovery_t) + 8, alloc_length); init_mode_sense_single(channel, &BX_SELECTED_DRIVE(channel).cdrom.current.error_recovery, sizeof(error_recovery_t)); ready_to_send_atapi(channel); break; case 0x2a: // CD-ROM capabilities & mech. status init_send_atapi_command(channel, atapi_command, 28, alloc_length); init_mode_sense_single(channel, &controller->buffer[8], 28); controller->buffer[8] = 0x2a; controller->buffer[9] = 0x12; controller->buffer[10] = 0x00; controller->buffer[11] = 0x00; // Multisession, Mode 2 Form 2, Mode 2 Form 1 controller->buffer[12] = 0x70; controller->buffer[13] = (3 << 5); controller->buffer[14] = (unsigned char) (1 | (BX_SELECTED_DRIVE(channel).cdrom.locked ? (1 << 1) : 0) | (1 << 3) | (1 << 5)); controller->buffer[15] = 0x00; controller->buffer[16] = (706 >> 8) & 0xff; controller->buffer[17] = 706 & 0xff; controller->buffer[18] = 0; controller->buffer[19] = 2; controller->buffer[20] = (512 >> 8) & 0xff; controller->buffer[21] = 512 & 0xff; controller->buffer[22] = (706 >> 8) & 0xff; controller->buffer[23] = 706 & 0xff; controller->buffer[24] = 0; controller->buffer[25] = 0; controller->buffer[26] = 0; controller->buffer[27] = 0; ready_to_send_atapi(channel); break; case 0x0d: // CD-ROM case 0x0e: // CD-ROM audio control case 0x3f: // all BX_ERROR(("cdrom: MODE SENSE (curr), code=%x not implemented yet", PageCode)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; default: // not implemeted by this device BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device", PC, PageCode)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; } break; case 0x1: // changeable values switch (PageCode) { case 0x01: // error recovery case 0x0d: // CD-ROM case 0x0e: // CD-ROM audio control case 0x2a: // CD-ROM capabilities & mech. status case 0x3f: // all BX_ERROR(("cdrom: MODE SENSE (chg), code=%x not implemented yet", PageCode)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; default: // not implemeted by this device BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device", PC, PageCode)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; } break; case 0x2: // default values switch (PageCode) { case 0x2a: // CD-ROM capabilities & mech. status, copied from current values init_send_atapi_command(channel, atapi_command, 28, alloc_length); init_mode_sense_single(channel, &controller->buffer[8], 28); controller->buffer[8] = 0x2a; controller->buffer[9] = 0x12; controller->buffer[10] = 0x00; controller->buffer[11] = 0x00; // Multisession, Mode 2 Form 2, Mode 2 Form 1 controller->buffer[12] = 0x70; controller->buffer[13] = (3 << 5); controller->buffer[14] = (unsigned char) (1 | (BX_SELECTED_DRIVE(channel).cdrom.locked ? (1 << 1) : 0) | (1 << 3) | (1 << 5)); controller->buffer[15] = 0x00; controller->buffer[16] = (706 >> 8) & 0xff; controller->buffer[17] = 706 & 0xff; controller->buffer[18] = 0; controller->buffer[19] = 2; controller->buffer[20] = (512 >> 8) & 0xff; controller->buffer[21] = 512 & 0xff; controller->buffer[22] = (706 >> 8) & 0xff; controller->buffer[23] = 706 & 0xff; controller->buffer[24] = 0; controller->buffer[25] = 0; controller->buffer[26] = 0; controller->buffer[27] = 0; ready_to_send_atapi(channel); break; case 0x01: // error recovery case 0x0d: // CD-ROM case 0x0e: // CD-ROM audio control case 0x3f: // all BX_ERROR(("cdrom: MODE SENSE (dflt), code=%x not implemented", PageCode)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; default: // not implemeted by this device BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x, not implemented by device", PC, PageCode)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; } break; case 0x3: // saved values not implemented atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED, 1); raise_interrupt(channel); break; default: BX_PANIC(("Should not get here!")); break; } } break; case 0x12: // inquiry { Bit8u alloc_length = controller->buffer[4]; init_send_atapi_command(channel, atapi_command, 36, alloc_length); controller->buffer[0] = 0x05; // CD-ROM controller->buffer[1] = 0x80; // Removable controller->buffer[2] = 0x00; // ISO, ECMA, ANSI version controller->buffer[3] = 0x21; // ATAPI-2, as specified controller->buffer[4] = 31; // additional length (total 36) controller->buffer[5] = 0x00; // reserved controller->buffer[6] = 0x00; // reserved controller->buffer[7] = 0x00; // reserved // Vendor ID const char* vendor_id = "BOCHS "; for (i = 0; i < 8; i++) controller->buffer[8+i] = vendor_id[i]; // Product ID const char* product_id = "Generic CD-ROM "; for (i = 0; i < 16; i++) controller->buffer[16+i] = product_id[i]; if (BX_HD_THIS cdrom_count > 1) { controller->buffer[31] = BX_SELECTED_DRIVE(channel).device_num; } // Product Revision level const char* rev_level = "1.0 "; for (i = 0; i < 4; i++) controller->buffer[32+i] = rev_level[i]; ready_to_send_atapi(channel); } break; case 0x25: // read cd-rom capacity { // no allocation length??? init_send_atapi_command(channel, atapi_command, 8, 8); if (BX_SELECTED_DRIVE(channel).cdrom.ready) { Bit32u capacity = BX_SELECTED_DRIVE(channel).cdrom.capacity - 1; controller->buffer[0] = (capacity >> 24) & 0xff; controller->buffer[1] = (capacity >> 16) & 0xff; controller->buffer[2] = (capacity >> 8) & 0xff; controller->buffer[3] = (capacity >> 0) & 0xff; controller->buffer[4] = (2048 >> 24) & 0xff; controller->buffer[5] = (2048 >> 16) & 0xff; controller->buffer[6] = (2048 >> 8) & 0xff; controller->buffer[7] = (2048 >> 0) & 0xff; ready_to_send_atapi(channel); } else { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 1); raise_interrupt(channel); } } break; case 0xbe: // read cd { if (BX_SELECTED_DRIVE(channel).cdrom.ready) { Bit32u lba = read_32bit(controller->buffer + 2); Bit32u transfer_length = controller->buffer[8] | (controller->buffer[7] << 8) | (controller->buffer[6] << 16); Bit8u transfer_req = controller->buffer[9]; if (transfer_length == 0) { atapi_cmd_nop(controller); raise_interrupt(channel); break; } switch (transfer_req & 0xf8) { case 0x00: atapi_cmd_nop(controller); raise_interrupt(channel); break; case 0xf8: controller->buffer_size = 2352; case 0x10: init_send_atapi_command(channel, atapi_command, transfer_length * controller->buffer_size, transfer_length * controller->buffer_size, 1); BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks = transfer_length; BX_SELECTED_DRIVE(channel).cdrom.next_lba = lba; ready_to_send_atapi(channel); break; default: BX_ERROR(("Read CD: unknown format")); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); } } else { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 1); raise_interrupt(channel); } } break; case 0x43: // read toc if (BX_SELECTED_DRIVE(channel).cdrom.ready) { #ifdef LOWLEVEL_CDROM bx_bool msf = (controller->buffer[1] >> 1) & 1; Bit8u starting_track = controller->buffer[6]; int toc_length; #endif Bit16u alloc_length = read_16bit(controller->buffer + 7); Bit8u format = (controller->buffer[9] >> 6); // Win32: I just read the TOC using Win32's IOCTRL functions (Ben) #if defined(WIN32) #ifdef LOWLEVEL_CDROM switch (format) { case 2: case 3: case 4: if (msf != 1) BX_ERROR(("READ_TOC_EX: msf not set for format %i", format)); case 0: case 1: case 5: if (!(BX_SELECTED_DRIVE(channel).cdrom.cd->read_toc(controller->buffer, &toc_length, msf, starting_track, format))) { atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); } else { init_send_atapi_command(channel, atapi_command, toc_length, alloc_length); ready_to_send_atapi(channel); } break; default: BX_ERROR(("(READ TOC) format %d not supported", format)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); } #else BX_PANIC(("LOWLEVEL_CDROM not defined")); #endif #else // WIN32 switch (format) { case 0: case 1: case 2: #ifdef LOWLEVEL_CDROM if (!(BX_SELECTED_DRIVE(channel).cdrom.cd->read_toc(controller->buffer, &toc_length, msf, starting_track, format))) { atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); } else { init_send_atapi_command(channel, atapi_command, toc_length, alloc_length); ready_to_send_atapi(channel); } #else BX_PANIC(("LOWLEVEL_CDROM not defined")); #endif break; default: BX_ERROR(("(READ TOC) format %d not supported", format)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; } #endif // WIN32 } else { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 1); raise_interrupt(channel); } break; case 0x28: // read (10) case 0xa8: // read (12) { Bit32s transfer_length; if (atapi_command == 0x28) transfer_length = read_16bit(controller->buffer + 7); else transfer_length = read_32bit(controller->buffer + 6); Bit32u lba = read_32bit(controller->buffer + 2); if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 1); raise_interrupt(channel); break; } if (lba > BX_SELECTED_DRIVE(channel).cdrom.capacity) { atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR, 1); raise_interrupt(channel); break; } // Ben: see comment below if (lba + transfer_length > BX_SELECTED_DRIVE(channel).cdrom.capacity) { transfer_length = (BX_SELECTED_DRIVE(channel).cdrom.capacity - lba); } if (transfer_length <= 0) { atapi_cmd_nop(controller); raise_interrupt(channel); BX_INFO(("READ(%d) with transfer length <= 0, ok (%i)", atapi_command==0x28?10:12, transfer_length)); break; } /* Ben: I commented this out and added the three lines above. I am not sure this is the correct thing to do, but it seems to work. FIXME: I think that if the transfer_length is more than we can transfer, we should return some sort of flag/error/bitrep stating so. I haven't read the atapi specs enough to know what needs to be done though. if (lba + transfer_length > BX_SELECTED_DRIVE(channel).cdrom.capacity) { atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR, 1); raise_interrupt(channel); break; } */ BX_DEBUG(("cdrom: READ (%d) LBA=%d LEN=%d", atapi_command==0x28?10:12, lba, transfer_length)); // handle command init_send_atapi_command(channel, atapi_command, transfer_length * 2048, transfer_length * 2048, 1); BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks = transfer_length; BX_SELECTED_DRIVE(channel).cdrom.next_lba = lba; ready_to_send_atapi(channel); } break; case 0x2b: // seek { Bit32u lba = read_32bit(controller->buffer + 2); if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 1); raise_interrupt(channel); break; } if (lba > BX_SELECTED_DRIVE(channel).cdrom.capacity) { atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR, 1); raise_interrupt(channel); break; } #ifdef LOWLEVEL_CDROM BX_SELECTED_DRIVE(channel).cdrom.cd->seek(lba); #else BX_PANIC(("Seek with no LOWLEVEL_CDROM")); #endif atapi_cmd_nop(controller); raise_interrupt(channel); } break; case 0x1e: // prevent/allow medium removal if (BX_SELECTED_DRIVE(channel).cdrom.ready) { BX_SELECTED_DRIVE(channel).cdrom.locked = controller->buffer[4] & 1; atapi_cmd_nop(controller); } else { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 1); } raise_interrupt(channel); break; case 0x42: // read sub-channel { bx_bool msf = get_packet_field(controller,1, 1, 1); bx_bool sub_q = get_packet_field(controller,2, 6, 1); Bit8u data_format = get_packet_byte(controller, 3); Bit8u track_number = get_packet_byte(controller, 6); Bit16u alloc_length = get_packet_word(controller, 7); int ret_len = 4; // header size UNUSED(msf); UNUSED(track_number); if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT, 1); raise_interrupt(channel); } else { controller->buffer[0] = 0; controller->buffer[1] = 0; // audio not supported controller->buffer[2] = 0; controller->buffer[3] = 0; if (sub_q) { // !sub_q == header only if ((data_format == 2) || (data_format == 3)) { // UPC or ISRC ret_len = 24; controller->buffer[4] = data_format; if (data_format == 3) { controller->buffer[5] = 0x14; controller->buffer[6] = 1; } controller->buffer[8] = 0; // no UPC, no ISRC } else { BX_ERROR(("Read sub-channel with SubQ not implemented (format=%d)", data_format)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; } } init_send_atapi_command(channel, atapi_command, ret_len, alloc_length); ready_to_send_atapi(channel); } } break; case 0x51: // read disc info // no-op to keep the Linux CD-ROM driver happy atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET, 1); raise_interrupt(channel); break; case 0x55: // mode select case 0xa6: // load/unload cd case 0x4b: // pause/resume case 0x45: // play audio case 0x47: // play audio msf case 0xbc: // play cd case 0xb9: // read cd msf case 0x44: // read header case 0xba: // scan case 0xbb: // set cd speed case 0x4e: // stop play/scan case 0x46: // get configuration case 0x4a: // get event status notification BX_DEBUG(("ATAPI command 0x%x not implemented yet", atapi_command)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 0); raise_interrupt(channel); break; default: BX_ERROR(("Unknown ATAPI command 0x%x (%d)", atapi_command, atapi_command)); atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE, 1); raise_interrupt(channel); break; } } break; default: BX_PANIC(("IO write(0x%04x): current command is %02xh", address, (unsigned) controller->current_command)); } break; case 0x01: // hard disk write precompensation 0x1f1 WRITE_FEATURES(channel,value); if (value == 0xff) BX_DEBUG(("no precompensation {%s}", BX_SELECTED_TYPE_STRING(channel))); else BX_DEBUG(("precompensation value %02x {%s}", value, BX_SELECTED_TYPE_STRING(channel))); break; case 0x02: // hard disk sector count 0x1f2 WRITE_SECTOR_COUNT(channel,value); BX_DEBUG(("sector count = %u {%s}", value, BX_SELECTED_TYPE_STRING(channel))); break; case 0x03: // hard disk sector number 0x1f3 WRITE_SECTOR_NUMBER(channel,value); BX_DEBUG(("sector number = %u {%s}", value, BX_SELECTED_TYPE_STRING(channel))); break; case 0x04: // hard disk cylinder low 0x1f4 WRITE_CYLINDER_LOW(channel,value); BX_DEBUG(("cylinder low = %02xh {%s}", value, BX_SELECTED_TYPE_STRING(channel))); break; case 0x05: // hard disk cylinder high 0x1f5 WRITE_CYLINDER_HIGH(channel,value); BX_DEBUG(("cylinder high = %02xh {%s}", value, BX_SELECTED_TYPE_STRING(channel))); break; case 0x06: // hard disk drive and head register 0x1f6 // b7 Extended data field for ECC // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128 // Since 512 was always used, bit 6 was taken to mean LBA mode: // b6 1=LBA mode, 0=CHS mode // b5 1 // b4: DRV // b3..0 HD3..HD0 { if ((value & 0xa0) != 0xa0) // 1x1xxxxx BX_DEBUG(("IO write 0x%04x (%02x): not 1x1xxxxxb", address, (unsigned) value)); Bit32u drvsel = BX_HD_THIS channels[channel].drive_select = (value >> 4) & 0x01; WRITE_HEAD_NO(channel,value & 0xf); if (!controller->lba_mode && ((value >> 6) & 1) == 1) BX_DEBUG(("enabling LBA mode")); WRITE_LBA_MODE(channel,(value >> 6) & 1); if (!BX_SELECTED_IS_PRESENT(channel)) { BX_DEBUG(("ata%d: device set to %d which does not exist", channel, drvsel)); } } break; case 0x07: // hard disk command 0x1f7 // (mch) Writes to the command register with drive_select != 0 // are ignored if no secondary device is present if ((BX_SLAVE_SELECTED(channel)) && (!BX_SLAVE_IS_PRESENT(channel))) break; // Writes to the command register clear the IRQ DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq); if (controller->status.busy) { BX_ERROR(("ata%d: command 0x%02x sent, controller BSY bit set", channel, value)); break; } if ((value & 0xf0) == 0x10) value = 0x10; controller->status.err = 0; switch (value) { case 0x10: // CALIBRATE DRIVE if (!BX_SELECTED_IS_HD(channel)) { BX_INFO(("ata%d-%d: calibrate drive issued to non-disk", channel, BX_SLAVE_SELECTED(channel))); command_aborted(channel, value); break; } if (!BX_SELECTED_IS_PRESENT(channel)) { controller->error_register = 0x02; // Track 0 not found controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.seek_complete = 0; controller->status.drq = 0; controller->status.err = 1; raise_interrupt(channel); BX_INFO(("calibrate drive: disk ata%d-%d not present", channel, BX_SLAVE_SELECTED(channel))); break; } /* move head to cylinder 0, issue IRQ */ controller->error_register = 0; controller->cylinder_no = 0; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.seek_complete = 1; controller->status.drq = 0; raise_interrupt(channel); break; case 0x24: // READ SECTORS EXT case 0x29: // READ MULTIPLE EXT lba48 = 1; case 0x20: // READ SECTORS, with retries case 0x21: // READ SECTORS, without retries case 0xC4: // READ MULTIPLE SECTORS /* update sector_no, always points to current sector * after each sector is read to buffer, DRQ bit set and issue IRQ * if interrupt handler transfers all data words into main memory, * and more sectors to read, then set BSY bit again, clear DRQ and * read next sector into buffer * sector count of 0 means 256 sectors */ if (!BX_SELECTED_IS_HD(channel)) { BX_INFO(("ata%d-%d: read sectors issued to non-disk", channel, BX_SLAVE_SELECTED(channel))); command_aborted(channel, value); break; } // Lose98 accesses 0/0/0 in CHS mode if (!controller->lba_mode && !controller->head_no && !controller->cylinder_no && !controller->sector_no) { BX_INFO(("ata%d-%d: : read from 0/0/0, aborting command", channel, BX_SLAVE_SELECTED(channel))); command_aborted(channel, value); break; } lba48_transform(controller, lba48); if ((value == 0xC4) || (value == 0x29)) { if (controller->multiple_sectors == 0) { command_aborted(channel, value); break; } if (controller->num_sectors > controller->multiple_sectors) { controller->buffer_size = controller->multiple_sectors * 512; } else { controller->buffer_size = controller->num_sectors * 512; } } else { controller->buffer_size = 512; } controller->current_command = value; if (ide_read_sector(channel, controller->buffer, controller->buffer_size)) { controller->error_register = 0; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.seek_complete = 1; controller->status.drq = 1; controller->status.corrected_data = 0; controller->buffer_index = 0; raise_interrupt(channel); } break; case 0x34: // WRITE SECTORS EXT case 0x39: // WRITE MULTIPLE EXT lba48 = 1; case 0x30: // WRITE SECTORS, with retries case 0xC5: // WRITE MULTIPLE SECTORS /* update sector_no, always points to current sector * after each sector is read to buffer, DRQ bit set and issue IRQ * if interrupt handler transfers all data words into main memory, * and more sectors to read, then set BSY bit again, clear DRQ and * read next sector into buffer * sector count of 0 means 256 sectors */ if (!BX_SELECTED_IS_HD(channel)) { BX_INFO(("ata%d-%d: write sectors issued to non-disk", channel, BX_SLAVE_SELECTED(channel))); command_aborted(channel, value); break; } lba48_transform(controller, lba48); if ((value == 0xC5) || (value ==0x39)) { if (controller->multiple_sectors == 0) { command_aborted(channel, value); break; } if (controller->num_sectors > controller->multiple_sectors) { controller->buffer_size = controller->multiple_sectors * 512; } else { controller->buffer_size = controller->num_sectors * 512; } } else { controller->buffer_size = 512; } controller->current_command = value; // implicit seek done :^) controller->error_register = 0; controller->status.busy = 0; // controller->status.drive_ready = 1; controller->status.seek_complete = 1; controller->status.drq = 1; controller->buffer_index = 0; break; case 0x90: // EXECUTE DEVICE DIAGNOSTIC set_signature(channel, BX_SLAVE_SELECTED(channel)); controller->error_register = 0x01; controller->status.drq = 0; raise_interrupt(channel); break; case 0x91: // INITIALIZE DRIVE PARAMETERS if (!BX_SELECTED_IS_HD(channel)) { BX_INFO(("ata%d-%d: initialize drive parameters issued to non-disk", channel, BX_SLAVE_SELECTED(channel))); command_aborted(channel, value); break; } // sets logical geometry of specified drive BX_DEBUG(("ata%d-%d: init drive params: sec=%u, drive sel=%u, head=%u", channel, BX_SLAVE_SELECTED(channel), (unsigned) controller->sector_count, (unsigned) BX_HD_THIS channels[channel].drive_select, (unsigned) controller->head_no)); if (!BX_SELECTED_IS_PRESENT(channel)) { BX_PANIC(("init drive params: disk ata%d-%d not present", channel, BX_SLAVE_SELECTED(channel))); //controller->error_register = 0x12; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.drq = 0; raise_interrupt(channel); break; } if (controller->sector_count != BX_SELECTED_DRIVE(channel).hdimage->spt) { BX_ERROR(("ata%d-%d: init drive params: logical sector count %d not supported", channel, BX_SLAVE_SELECTED(channel), controller->sector_count)); command_aborted(channel, value); break; } if (controller->head_no == 0) { // Linux 2.6.x kernels use this value and don't like aborting here BX_ERROR(("ata%d-%d: init drive params: max. logical head number 0 not supported", channel, BX_SLAVE_SELECTED(channel))); } else if (controller->head_no != (BX_SELECTED_DRIVE(channel).hdimage->heads-1)) { BX_ERROR(("ata%d-%d: init drive params: max. logical head number %d not supported", channel, BX_SLAVE_SELECTED(channel), controller->head_no)); command_aborted(channel, value); break; } controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.drq = 0; raise_interrupt(channel); break; case 0xec: // IDENTIFY DEVICE { BX_DEBUG(("Drive ID Command issued : 0xec ")); if (!BX_SELECTED_IS_PRESENT(channel)) { BX_INFO(("disk ata%d-%d not present, aborting",channel,BX_SLAVE_SELECTED(channel))); command_aborted(channel, value); break; } if (BX_SELECTED_IS_CD(channel)) { set_signature(channel, BX_SLAVE_SELECTED(channel)); command_aborted(channel, 0xec); } else { controller->current_command = value; controller->error_register = 0; // See ATA/ATAPI-4, 8.12 controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.drq = 1; controller->status.seek_complete = 1; controller->status.corrected_data = 0; controller->buffer_index = 0; if (!BX_SELECTED_DRIVE(channel).identify_set) { identify_drive(channel); } // now convert the id_drive array (native 256 word format) to // the controller buffer (512 bytes) for (i=0; i<=255; i++) { Bit16u temp16 = BX_SELECTED_DRIVE(channel).id_drive[i]; controller->buffer[i*2] = temp16 & 0x00ff; controller->buffer[i*2+1] = temp16 >> 8; } raise_interrupt(channel); } } break; case 0xef: // SET FEATURES switch(controller->features) { case 0x03: // Set Transfer Mode { Bit8u type = (controller->sector_count >> 3); Bit8u mode = controller->sector_count & 0x07; switch (type) { case 0x00: // PIO default case 0x01: // PIO mode BX_INFO(("ata%d-%d: set transfer mode to PIO", channel, BX_SLAVE_SELECTED(channel))); controller->mdma_mode = 0x00; controller->udma_mode = 0x00; controller->status.drive_ready = 1; controller->status.seek_complete = 1; raise_interrupt(channel); break; case 0x04: // MDMA mode BX_INFO(("ata%d-%d: set transfer mode to MDMA%d", channel, BX_SLAVE_SELECTED(channel), mode)); controller->mdma_mode = (1 << mode); controller->udma_mode = 0x00; controller->status.drive_ready = 1; controller->status.seek_complete = 1; raise_interrupt(channel); break; case 0x08: // UDMA mode controller->mdma_mode = 0x00; controller->udma_mode = (1 << mode); controller->status.drive_ready = 1; controller->status.seek_complete = 1; raise_interrupt(channel); break; default: BX_ERROR(("ata%d-%d: unknown transfer mode type 0x%02x", channel, BX_SLAVE_SELECTED(channel), type)); command_aborted(channel, value); } BX_SELECTED_DRIVE(channel).identify_set = 0; } break; case 0x02: // Enable and case 0x82: // Disable write cache. case 0xAA: // Enable and case 0x55: // Disable look-ahead cache. case 0xCC: // Enable and case 0x66: // Disable reverting to power-on default BX_INFO(("ata%d-%d: SET FEATURES subcommand 0x%02x not supported, but returning success", channel,BX_SLAVE_SELECTED(channel),(unsigned) controller->features)); controller->status.drive_ready = 1; controller->status.seek_complete = 1; raise_interrupt(channel); break; default: BX_ERROR(("ata%d-%d: SET FEATURES with unknown subcommand: 0x%02x", channel,BX_SLAVE_SELECTED(channel),(unsigned) controller->features)); command_aborted(channel, value); } break; case 0x42: // READ VERIFY SECTORS EXT lba48 = 1; case 0x40: // READ VERIFY SECTORS case 0x41: // READ VERIFY SECTORS NO RETRY if (!BX_SELECTED_IS_HD(channel)) { BX_INFO(("ata%d-%d: read verify issued to non-disk", channel,BX_SLAVE_SELECTED(channel))); command_aborted(channel, value); break; } lba48_transform(controller, lba48); BX_INFO(("ata%d-%d: verify command : 0x%02x !", channel,BX_SLAVE_SELECTED(channel), value)); controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.drq = 0; raise_interrupt(channel); break; case 0xc6: // SET MULTIPLE MODE if (!BX_SELECTED_IS_HD(channel)) { BX_INFO(("set multiple mode issued to non-disk")); command_aborted(channel, value); } else if ((controller->sector_count > MAX_MULTIPLE_SECTORS) || ((controller->sector_count & (controller->sector_count - 1)) != 0) || (controller->sector_count == 0)) { command_aborted(channel, value); } else { BX_DEBUG(("set multiple mode: sectors=%d", controller->sector_count)); controller->multiple_sectors = controller->sector_count; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.drq = 0; raise_interrupt(channel); } break; // ATAPI commands case 0xa1: // IDENTIFY PACKET DEVICE { if (BX_SELECTED_IS_CD(channel)) { controller->current_command = value; controller->error_register = 0; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.drq = 1; controller->status.seek_complete = 1; controller->status.corrected_data = 0; controller->buffer_index = 0; if (!BX_SELECTED_DRIVE(channel).identify_set) { identify_ATAPI_drive(channel); } // now convert the id_drive array (native 256 word format) to // the controller buffer (512 bytes) for (i = 0; i <= 255; i++) { Bit16u temp16 = BX_SELECTED_DRIVE(channel).id_drive[i]; controller->buffer[i*2] = temp16 & 0x00ff; controller->buffer[i*2+1] = temp16 >> 8; } raise_interrupt(channel); } else { command_aborted(channel, 0xa1); } } break; case 0x08: // DEVICE RESET (atapi) if (BX_SELECTED_IS_CD(channel)) { set_signature(channel, BX_SLAVE_SELECTED(channel)); controller->status.busy = 1; controller->error_register &= ~(1 << 7); controller->status.write_fault = 0; controller->status.drq = 0; controller->status.corrected_data = 0; controller->status.busy = 0; } else { BX_DEBUG(("ATAPI Device Reset on non-cd device")); command_aborted(channel, 0x08); } break; case 0xa0: // SEND PACKET (atapi) if (BX_SELECTED_IS_CD(channel)) { // PACKET controller->packet_dma = (controller->features & 1); if (controller->features & (1 << 1)) { BX_ERROR(("PACKET-overlapped not supported")); command_aborted (channel, 0xa0); } else { // We're already ready! controller->sector_count = 1; controller->status.busy = 0; controller->status.write_fault = 0; // serv bit?? controller->status.drq = 1; // NOTE: no interrupt here controller->current_command = value; controller->buffer_index = 0; } } else { command_aborted (channel, 0xa0); } break; case 0xa2: // SERVICE (atapi), optional if (BX_SELECTED_IS_CD(channel)) { BX_PANIC(("ATAPI SERVICE not implemented")); command_aborted(channel, 0xa2); } else { command_aborted(channel, 0xa2); } break; // power management & flush cache stubs case 0xE0: // STANDBY NOW case 0xE1: // IDLE IMMEDIATE case 0xE7: // FLUSH CACHE case 0xEA: // FLUSH CACHE EXT controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.drq = 0; raise_interrupt(channel); break; case 0xe5: // CHECK POWER MODE controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.drq = 0; controller->sector_count = 0xff; // Active or Idle mode raise_interrupt(channel); break; case 0x70: // SEEK (cgs) if (BX_SELECTED_IS_HD(channel)) { BX_DEBUG(("write cmd 0x70 (SEEK) executing")); if (!calculate_logical_address(channel, &logical_sector)) { BX_ERROR(("initial seek to sector %lu out of bounds, aborting", (unsigned long)logical_sector)); command_aborted(channel, value); break; } controller->error_register = 0; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.seek_complete = 1; controller->status.drq = 0; controller->status.corrected_data = 0; controller->buffer_index = 0; BX_DEBUG(("ata%d-%d: SEEK completed (IRQ %sabled)", channel, BX_SLAVE_SELECTED(channel), controller->control.disable_irq?"dis":"en")); raise_interrupt(channel); } else { BX_INFO(("write cmd 0x70 (SEEK) not supported for non-disk")); command_aborted(channel, 0x70); } break; case 0x25: // READ DMA EXT lba48 = 1; case 0xC8: // READ DMA if (BX_SELECTED_IS_HD(channel) && BX_HD_THIS bmdma_present()) { lba48_transform(controller, lba48); controller->status.drive_ready = 1; controller->status.seek_complete = 1; controller->status.drq = 1; controller->current_command = value; } else { BX_ERROR(("write cmd 0x%02x (READ DMA) not supported", value)); command_aborted(channel, value); } break; case 0x35: // WRITE DMA EXT lba48 = 1; case 0xCA: // WRITE DMA if (BX_SELECTED_IS_HD(channel) && BX_HD_THIS bmdma_present()) { lba48_transform(controller, lba48); controller->status.drive_ready = 1; controller->status.seek_complete = 1; controller->status.drq = 1; controller->current_command = value; } else { BX_ERROR(("write cmd 0x%02x (WRITE DMA) not supported", value)); command_aborted(channel, value); } break; case 0x27: // READ NATIVE MAX ADDRESS EXT lba48 = 1; case 0xF8: // READ NATIVE MAX ADDRESS if (BX_SELECTED_IS_HD(channel)) { lba48_transform(controller, lba48); Bit64s max_sector = BX_SELECTED_DRIVE(channel).hdimage->hd_size / 512 - 1; if (controller->lba_mode) { if (!controller->lba48) { controller->head_no = (Bit8u)((max_sector >> 24) & 0xf); controller->cylinder_no = (Bit16u)((max_sector >> 8) & 0xffff); controller->sector_no = (Bit8u)((max_sector) & 0xff); } else { controller->hob.hcyl = (Bit8u)((max_sector >> 40) & 0xff); controller->hob.lcyl = (Bit8u)((max_sector >> 32) & 0xff); controller->hob.sector = (Bit8u)((max_sector >> 24) & 0xff); controller->cylinder_no = (Bit16u)((max_sector >> 8) & 0xffff); controller->sector_no = (Bit8u)((max_sector) & 0xff); } controller->status.drive_ready = 1; controller->status.seek_complete = 1; raise_interrupt(channel); } else { command_aborted(channel, value); } } else { command_aborted(channel, value); } break; // List all the write operations that are defined in the ATA/ATAPI spec // that we don't support. Commands that are listed here will cause a // BX_ERROR, which is non-fatal, and the command will be aborted. case 0x22: BX_ERROR(("write cmd 0x22 (READ LONG) not supported")); command_aborted(channel, 0x22); break; case 0x23: BX_ERROR(("write cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(channel, 0x23); break; case 0x26: BX_ERROR(("write cmd 0x26 (READ DMA QUEUED EXT) not supported"));command_aborted(channel, 0x26); break; case 0x2A: BX_ERROR(("write cmd 0x2A (READ STREAM DMA) not supported"));command_aborted(channel, 0x2A); break; case 0x2B: BX_ERROR(("write cmd 0x2B (READ STREAM PIO) not supported"));command_aborted(channel, 0x2B); break; case 0x2F: BX_ERROR(("write cmd 0x2F (READ LOG EXT) not supported"));command_aborted(channel, 0x2F); break; case 0x31: BX_ERROR(("write cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(channel, 0x31); break; case 0x32: BX_ERROR(("write cmd 0x32 (WRITE LONG) not supported")); command_aborted(channel, 0x32); break; case 0x33: BX_ERROR(("write cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(channel, 0x33); break; case 0x36: BX_ERROR(("write cmd 0x36 (WRITE DMA QUEUED EXT) not supported"));command_aborted(channel, 0x36); break; case 0x37: BX_ERROR(("write cmd 0x37 (SET MAX ADDRESS EXT) not supported"));command_aborted(channel, 0x37); break; case 0x38: BX_ERROR(("write cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported"));command_aborted(channel, 0x38); break; case 0x3A: BX_ERROR(("write cmd 0x3A (WRITE STREAM DMA) not supported"));command_aborted(channel, 0x3A); break; case 0x3B: BX_ERROR(("write cmd 0x3B (WRITE STREAM PIO) not supported"));command_aborted(channel, 0x3B); break; case 0x3F: BX_ERROR(("write cmd 0x3F (WRITE LOG EXT) not supported"));command_aborted(channel, 0x3F); break; case 0x50: BX_ERROR(("write cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(channel, 0x50); break; case 0x51: BX_ERROR(("write cmd 0x51 (CONFIGURE STREAM) not supported"));command_aborted(channel, 0x51); break; case 0x87: BX_ERROR(("write cmd 0x87 (CFA TRANSLATE SECTOR) not supported"));command_aborted(channel, 0x87); break; case 0x92: BX_ERROR(("write cmd 0x92 (DOWNLOAD MICROCODE) not supported"));command_aborted(channel, 0x92); break; case 0x94: BX_ERROR(("write cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0x94); break; case 0x95: BX_ERROR(("write cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0x95); break; case 0x96: BX_ERROR(("write cmd 0x96 (STANDBY) not supported")); command_aborted(channel, 0x96); break; case 0x97: BX_ERROR(("write cmd 0x97 (IDLE) not supported")); command_aborted(channel, 0x97); break; case 0x98: BX_ERROR(("write cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(channel, 0x98); break; case 0x99: BX_ERROR(("write cmd 0x99 (SLEEP) not supported")); command_aborted(channel, 0x99); break; case 0xB0: BX_ERROR(("write cmd 0xB0 (SMART commands) not supported"));command_aborted(channel, 0xB0); break; case 0xB1: BX_ERROR(("write cmd 0xB1 (DEVICE CONFIGURATION commands) not supported"));command_aborted(channel, 0xB1); break; case 0xC0: BX_ERROR(("write cmd 0xC0 (CFA ERASE SECTORS) not supported"));command_aborted(channel, 0xC0); break; case 0xC7: BX_ERROR(("write cmd 0xC7 (READ DMA QUEUED) not supported"));command_aborted(channel, 0xC7); break; case 0xC9: BX_ERROR(("write cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(channel, 0xC9); break; case 0xCC: BX_ERROR(("write cmd 0xCC (WRITE DMA QUEUED) not supported"));command_aborted(channel, 0xCC); break; case 0xCD: BX_ERROR(("write cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported"));command_aborted(channel, 0xCD); break; case 0xD1: BX_ERROR(("write cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported"));command_aborted(channel, 0xD1); break; case 0xDA: BX_ERROR(("write cmd 0xDA (GET MEDIA STATUS) not supported"));command_aborted(channel, 0xDA); break; case 0xDE: BX_ERROR(("write cmd 0xDE (MEDIA LOCK) not supported"));command_aborted(channel, 0xDE); break; case 0xDF: BX_ERROR(("write cmd 0xDF (MEDIA UNLOCK) not supported"));command_aborted(channel, 0xDF); break; case 0xE2: BX_ERROR(("write cmd 0xE2 (STANDBY) not supported"));command_aborted(channel, 0xE2); break; case 0xE3: BX_ERROR(("write cmd 0xE3 (IDLE) not supported"));command_aborted(channel, 0xE3); break; case 0xE4: BX_ERROR(("write cmd 0xE4 (READ BUFFER) not supported"));command_aborted(channel, 0xE4); break; case 0xE6: BX_ERROR(("write cmd 0xE6 (SLEEP) not supported"));command_aborted(channel, 0xE6); break; case 0xE8: BX_ERROR(("write cmd 0xE8 (WRITE BUFFER) not supported"));command_aborted(channel, 0xE8); break; case 0xED: BX_ERROR(("write cmd 0xED (MEDIA EJECT) not supported"));command_aborted(channel, 0xED); break; case 0xF1: BX_ERROR(("write cmd 0xF1 (SECURITY SET PASSWORD) not supported"));command_aborted(channel, 0xF1); break; case 0xF2: BX_ERROR(("write cmd 0xF2 (SECURITY UNLOCK) not supported"));command_aborted(channel, 0xF2); break; case 0xF3: BX_ERROR(("write cmd 0xF3 (SECURITY ERASE PREPARE) not supported"));command_aborted(channel, 0xF3); break; case 0xF4: BX_ERROR(("write cmd 0xF4 (SECURITY ERASE UNIT) not supported"));command_aborted(channel, 0xF4); break; case 0xF5: BX_ERROR(("write cmd 0xF5 (SECURITY FREEZE LOCK) not supported"));command_aborted(channel, 0xF5); break; case 0xF6: BX_ERROR(("write cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported"));command_aborted(channel, 0xF6); break; case 0xF9: BX_ERROR(("write cmd 0xF9 (SET MAX ADDRESS) not supported"));command_aborted(channel, 0xF9); break; default: BX_ERROR(("IO write to 0x%04x: unknown command 0x%02x", address, value)); command_aborted(channel, value); } break; case 0x16: // hard disk adapter control 0x3f6 // (mch) Even if device 1 was selected, a write to this register // goes to device 0 (if device 1 is absent) prev_control_reset = controller->control.reset; BX_HD_THIS channels[channel].drives[0].controller.control.reset = value & 0x04; BX_HD_THIS channels[channel].drives[1].controller.control.reset = value & 0x04; BX_HD_THIS channels[channel].drives[0].controller.control.disable_irq = value & 0x02; BX_HD_THIS channels[channel].drives[1].controller.control.disable_irq = value & 0x02; BX_DEBUG(("ata%d: adapter control reg: reset controller = %d", channel, (unsigned) (controller->control.reset) ? 1 : 0)); BX_DEBUG(("ata%d: adapter control reg: disable irq = %d", channel, (unsigned) (controller->control.disable_irq) ? 1 : 0)); if (!prev_control_reset && controller->control.reset) { // transition from 0 to 1 causes all drives to reset BX_DEBUG(("Enter RESET mode")); // (mch) Set BSY, drive not ready for (int id = 0; id < 2; id++) { BX_CONTROLLER(channel,id).status.busy = 1; BX_CONTROLLER(channel,id).status.drive_ready = 0; BX_CONTROLLER(channel,id).reset_in_progress = 1; BX_CONTROLLER(channel,id).status.write_fault = 0; BX_CONTROLLER(channel,id).status.seek_complete = 1; BX_CONTROLLER(channel,id).status.drq = 0; BX_CONTROLLER(channel,id).status.corrected_data = 0; BX_CONTROLLER(channel,id).status.err = 0; BX_CONTROLLER(channel,id).error_register = 0x01; // diagnostic code: no error BX_CONTROLLER(channel,id).current_command = 0x00; BX_CONTROLLER(channel,id).buffer_index = 0; BX_CONTROLLER(channel,id).multiple_sectors = 0; BX_CONTROLLER(channel,id).lba_mode = 0; BX_CONTROLLER(channel,id).control.disable_irq = 0; DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq); } } else if (controller->reset_in_progress && !controller->control.reset) { // Clear BSY and DRDY BX_DEBUG(("Reset complete {%s}", BX_SELECTED_TYPE_STRING(channel))); for (int id = 0; id < 2; id++) { BX_CONTROLLER(channel,id).status.busy = 0; BX_CONTROLLER(channel,id).status.drive_ready = 1; BX_CONTROLLER(channel,id).reset_in_progress = 0; set_signature(channel, id); } } BX_DEBUG(("ata%d: adapter control reg: disable irq = %d", channel, (unsigned) (controller->control.disable_irq) ? 1 : 0)); break; default: BX_PANIC(("hard drive: io write to address %x = %02x", (unsigned) address, (unsigned) value)); } } bx_bool BX_CPP_AttrRegparmN(2) bx_hard_drive_c::calculate_logical_address(Bit8u channel, Bit64s *sector) { Bit64s logical_sector; controller_t *controller = &BX_SELECTED_CONTROLLER(channel); if (controller->lba_mode) { if (!controller->lba48) { logical_sector = ((Bit32u)controller->head_no) << 24 | ((Bit32u)controller->cylinder_no) << 8 | (Bit32u)controller->sector_no; } else { logical_sector = ((Bit64u)controller->hob.hcyl) << 40 | ((Bit64u)controller->hob.lcyl) << 32 | ((Bit64u)controller->hob.sector) << 24 | ((Bit64u)controller->cylinder_no) << 8 | (Bit64u)controller->sector_no; } } else { logical_sector = ((Bit32u)controller->cylinder_no * BX_SELECTED_DRIVE(channel).hdimage->heads * BX_SELECTED_DRIVE(channel).hdimage->spt) + (Bit32u)(controller->head_no * BX_SELECTED_DRIVE(channel).hdimage->spt) + (controller->sector_no - 1); } Bit64s sector_count = BX_SELECTED_DRIVE(channel).hdimage->hd_size / 512; if (logical_sector >= sector_count) { BX_ERROR (("calc_log_addr: out of bounds ("FMT_LL"d/"FMT_LL"d)", logical_sector, sector_count)); return 0; } *sector = logical_sector; return 1; } void BX_CPP_AttrRegparmN(2) bx_hard_drive_c::increment_address(Bit8u channel, Bit64s *sector) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); controller->sector_count--; controller->num_sectors--; if (controller->lba_mode) { Bit64s logical_sector = *sector; logical_sector++; if (!controller->lba48) { controller->head_no = (Bit8u)((logical_sector >> 24) & 0xf); controller->cylinder_no = (Bit16u)((logical_sector >> 8) & 0xffff); controller->sector_no = (Bit8u)((logical_sector) & 0xff); } else { controller->hob.hcyl = (Bit8u)((logical_sector >> 40) & 0xff); controller->hob.lcyl = (Bit8u)((logical_sector >> 32) & 0xff); controller->hob.sector = (Bit8u)((logical_sector >> 24) & 0xff); controller->cylinder_no = (Bit16u)((logical_sector >> 8) & 0xffff); controller->sector_no = (Bit8u)((logical_sector) & 0xff); } } else { controller->sector_no++; if (controller->sector_no > BX_SELECTED_DRIVE(channel).hdimage->spt) { controller->sector_no = 1; controller->head_no++; if (controller->head_no >= BX_SELECTED_DRIVE(channel).hdimage->heads) { controller->head_no = 0; controller->cylinder_no++; if (controller->cylinder_no >= BX_SELECTED_DRIVE(channel).hdimage->cylinders) controller->cylinder_no = BX_SELECTED_DRIVE(channel).hdimage->cylinders - 1; } } } } void bx_hard_drive_c::identify_ATAPI_drive(Bit8u channel) { unsigned i; char serial_number[21]; memset(&BX_SELECTED_DRIVE(channel).id_drive, 0, 512); BX_SELECTED_DRIVE(channel).id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets for (i = 1; i <= 9; i++) BX_SELECTED_DRIVE(channel).id_drive[i] = 0; strcpy(serial_number, "BXCD00000 "); serial_number[8] = BX_SELECTED_DRIVE(channel).device_num; for (i = 0; i < 10; i++) { BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) | serial_number[i*2 + 1]; } for (i = 20; i <= 22; i++) BX_SELECTED_DRIVE(channel).id_drive[i] = 0; const char* firmware = "ALPHA1 "; for (i = 0; i < strlen(firmware)/2; i++) { BX_SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) | firmware[i*2 + 1]; } BX_ASSERT((23+i) == 27); for (i = 0; i < strlen((char *) BX_SELECTED_MODEL(channel))/2; i++) { BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) | BX_SELECTED_MODEL(channel)[i*2 + 1]; } BX_ASSERT((27+i) == 47); BX_SELECTED_DRIVE(channel).id_drive[47] = 0; BX_SELECTED_DRIVE(channel).id_drive[48] = 1; // 32 bits access if (BX_HD_THIS bmdma_present()) { BX_SELECTED_DRIVE(channel).id_drive[49] = (1<<9) | (1<<8); // LBA and DMA } else { BX_SELECTED_DRIVE(channel).id_drive[49] = (1<<9); // LBA only supported } BX_SELECTED_DRIVE(channel).id_drive[50] = 0; BX_SELECTED_DRIVE(channel).id_drive[51] = 0; BX_SELECTED_DRIVE(channel).id_drive[52] = 0; BX_SELECTED_DRIVE(channel).id_drive[53] = 3; // words 64-70, 54-58 valid for (i = 54; i <= 62; i++) BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // copied from CFA540A BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff) BX_SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO BX_SELECTED_DRIVE(channel).id_drive[65] = 0x00b4; BX_SELECTED_DRIVE(channel).id_drive[66] = 0x00b4; BX_SELECTED_DRIVE(channel).id_drive[67] = 0x012c; BX_SELECTED_DRIVE(channel).id_drive[68] = 0x00b4; BX_SELECTED_DRIVE(channel).id_drive[69] = 0; BX_SELECTED_DRIVE(channel).id_drive[70] = 0; BX_SELECTED_DRIVE(channel).id_drive[71] = 30; // faked BX_SELECTED_DRIVE(channel).id_drive[72] = 30; // faked BX_SELECTED_DRIVE(channel).id_drive[73] = 0; BX_SELECTED_DRIVE(channel).id_drive[74] = 0; BX_SELECTED_DRIVE(channel).id_drive[75] = 0; for (i = 76; i <= 79; i++) BX_SELECTED_DRIVE(channel).id_drive[i] = 0; BX_SELECTED_DRIVE(channel).id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4 BX_SELECTED_DRIVE(channel).id_drive[81] = 0; BX_SELECTED_DRIVE(channel).id_drive[82] = 0; BX_SELECTED_DRIVE(channel).id_drive[83] = 0; BX_SELECTED_DRIVE(channel).id_drive[84] = 0; BX_SELECTED_DRIVE(channel).id_drive[85] = 0; BX_SELECTED_DRIVE(channel).id_drive[86] = 0; BX_SELECTED_DRIVE(channel).id_drive[87] = 0; BX_SELECTED_DRIVE(channel).id_drive[88] = 0; BX_SELECTED_DRIVE(channel).identify_set = 1; } void bx_hard_drive_c::identify_drive(Bit8u channel) { unsigned i; char serial_number[21]; Bit32u temp32; Bit64u num_sects; memset(&BX_SELECTED_DRIVE(channel).id_drive, 0, 512); // Identify Drive command return values definition // // This code is rehashed from some that was donated. // I'm using ANSI X3.221-1994, AT Attachment Interface for Disk Drives // and X3T10 2008D Working Draft for ATA-3 // Word 0: general config bit-significant info // Note: bits 1-5 and 8-14 are now "Vendor specific (obsolete)" // bit 15: 0=ATA device // 1=ATAPI device // bit 14: 1=format speed tolerance gap required // bit 13: 1=track offset option available // bit 12: 1=data strobe offset option available // bit 11: 1=rotational speed tolerance is > 0,5% (typo?) // bit 10: 1=disk transfer rate > 10Mbs // bit 9: 1=disk transfer rate > 5Mbs but <= 10Mbs // bit 8: 1=disk transfer rate <= 5Mbs // bit 7: 1=removable cartridge drive // bit 6: 1=fixed drive // bit 5: 1=spindle motor control option implemented // bit 4: 1=head switch time > 15 usec // bit 3: 1=not MFM encoded // bit 2: 1=soft sectored // bit 1: 1=hard sectored // bit 0: 0=reserved BX_SELECTED_DRIVE(channel).id_drive[0] = 0x0040; // Word 1: number of user-addressable cylinders in // default translation mode. If the value in words 60-61 // exceed 16,515,072, this word shall contain 16,383. if (BX_SELECTED_DRIVE(channel).hdimage->cylinders > 16383) { BX_SELECTED_DRIVE(channel).id_drive[1] = 16383; } else { BX_SELECTED_DRIVE(channel).id_drive[1] = BX_SELECTED_DRIVE(channel).hdimage->cylinders; } // Word 2: reserved // Word 3: number of user-addressable heads in default // translation mode BX_SELECTED_DRIVE(channel).id_drive[3] = BX_SELECTED_DRIVE(channel).hdimage->heads; // Word 4: # unformatted bytes per translated track in default xlate mode // Word 5: # unformatted bytes per sector in default xlated mode // Word 6: # user-addressable sectors per track in default xlate mode // Note: words 4,5 are now "Vendor specific (obsolete)" BX_SELECTED_DRIVE(channel).id_drive[4] = (512 * BX_SELECTED_DRIVE(channel).hdimage->spt); BX_SELECTED_DRIVE(channel).id_drive[5] = 512; BX_SELECTED_DRIVE(channel).id_drive[6] = BX_SELECTED_DRIVE(channel).hdimage->spt; // Word 7-9: Vendor specific // Word 10-19: Serial number (20 ASCII characters, 0000h=not specified) // This field is right justified and padded with spaces (20h). strcpy(serial_number, "BXHD00000 "); serial_number[7] = channel + 49; serial_number[8] = BX_HD_THIS channels[channel].drive_select + 49; for (i = 0; i < 10; i++) { BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) | serial_number[i*2 + 1]; } // Word 20: buffer type // 0000h = not specified // 0001h = single ported single sector buffer which is // not capable of simulataneous data xfers to/from // the host and the disk. // 0002h = dual ported multi-sector buffer capable of // simulatenous data xfers to/from the host and disk. // 0003h = dual ported mutli-sector buffer capable of // simulatenous data xfers with a read caching // capability. // 0004h-ffffh = reserved BX_SELECTED_DRIVE(channel).id_drive[20] = 3; // Word 21: buffer size in 512 byte increments, 0000h = not specified BX_SELECTED_DRIVE(channel).id_drive[21] = 512; // 512 Sectors = 256kB cache // Word 22: # of ECC bytes available on read/write long cmds // 0000h = not specified BX_SELECTED_DRIVE(channel).id_drive[22] = 4; // Word 23..26: Firmware revision (8 ascii chars, 0000h=not specified) // This field is left justified and padded with spaces (20h) for (i=23; i<=26; i++) BX_SELECTED_DRIVE(channel).id_drive[i] = 0; // Word 27..46: Model number (40 ascii chars, 0000h=not specified) // This field is left justified and padded with spaces (20h) for (i=0; i<20; i++) { BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) | BX_SELECTED_MODEL(channel)[i*2 + 1]; } // Word 47: 15-8 Vendor unique // 7-0 00h= read/write multiple commands not implemented // xxh= maximum # of sectors that can be transferred // per interrupt on read and write multiple commands BX_SELECTED_DRIVE(channel).id_drive[47] = MAX_MULTIPLE_SECTORS; // Word 48: 0000h = cannot perform dword IO // 0001h = can perform dword IO BX_SELECTED_DRIVE(channel).id_drive[48] = 1; // Word 49: Capabilities // 15-10: 0 = reserved // 9: 1 = LBA supported // 8: 1 = DMA supported // 7-0: Vendor unique if (BX_HD_THIS bmdma_present()) { BX_SELECTED_DRIVE(channel).id_drive[49] = (1<<9) | (1<<8); } else { BX_SELECTED_DRIVE(channel).id_drive[49] = 1<<9; } // Word 50: Reserved // Word 51: 15-8 PIO data transfer cycle timing mode // 7-0 Vendor unique BX_SELECTED_DRIVE(channel).id_drive[51] = 0x200; // Word 52: 15-8 DMA data transfer cycle timing mode // 7-0 Vendor unique BX_SELECTED_DRIVE(channel).id_drive[52] = 0x200; // Word 53: 15-1 Reserved // 2 1=the fields reported in word 88 are valid // 1 1=the fields reported in words 64-70 are valid // 0 1=the fields reported in words 54-58 are valid BX_SELECTED_DRIVE(channel).id_drive[53] = 0x07; // Word 54: # of user-addressable cylinders in curr xlate mode // Word 55: # of user-addressable heads in curr xlate mode // Word 56: # of user-addressable sectors/track in curr xlate mode if (BX_SELECTED_DRIVE(channel).hdimage->cylinders > 16383) { BX_SELECTED_DRIVE(channel).id_drive[54] = 16383; } else { BX_SELECTED_DRIVE(channel).id_drive[54] = BX_SELECTED_DRIVE(channel).hdimage->cylinders; } BX_SELECTED_DRIVE(channel).id_drive[55] = BX_SELECTED_DRIVE(channel).hdimage->heads; BX_SELECTED_DRIVE(channel).id_drive[56] = BX_SELECTED_DRIVE(channel).hdimage->spt; // Word 57-58: Current capacity in sectors // Excludes all sectors used for device specific purposes. temp32 = BX_SELECTED_DRIVE(channel).hdimage->cylinders * BX_SELECTED_DRIVE(channel).hdimage->heads * BX_SELECTED_DRIVE(channel).hdimage->spt; BX_SELECTED_DRIVE(channel).id_drive[57] = (temp32 & 0xffff); // LSW BX_SELECTED_DRIVE(channel).id_drive[58] = (temp32 >> 16); // MSW // Word 59: 15-9 Reserved // 8 1=multiple sector setting is valid // 7-0 current setting for number of sectors that can be // transferred per interrupt on R/W multiple commands if (BX_SELECTED_CONTROLLER(channel).multiple_sectors > 0) BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0100 | BX_SELECTED_CONTROLLER(channel).multiple_sectors; else BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0000; // Word 60-61: // If drive supports LBA Mode, these words reflect total # of user // addressable sectors. This value does not depend on the current // drive geometry. If the drive does not support LBA mode, these // words shall be set to 0. if (BX_SELECTED_DRIVE(channel).hdimage->hd_size > 0) num_sects = (BX_SELECTED_DRIVE(channel).hdimage->hd_size >> 9); else num_sects = BX_SELECTED_DRIVE(channel).hdimage->cylinders * BX_SELECTED_DRIVE(channel).hdimage->heads * BX_SELECTED_DRIVE(channel).hdimage->spt; BX_SELECTED_DRIVE(channel).id_drive[60] = (Bit16u)(num_sects & 0xffff); // LSW BX_SELECTED_DRIVE(channel).id_drive[61] = (Bit16u)(num_sects >> 16); // MSW // Word 62: 15-8 single word DMA transfer mode active // 7-0 single word DMA transfer modes supported // The low order byte identifies by bit, all the Modes which are // supported e.g., if Mode 0 is supported bit 0 is set. // The high order byte contains a single bit set to indiciate // which mode is active. BX_SELECTED_DRIVE(channel).id_drive[62] = 0x0; // Word 63: 15-8 multiword DMA transfer mode active // 7-0 multiword DMA transfer modes supported // The low order byte identifies by bit, all the Modes which are // supported e.g., if Mode 0 is supported bit 0 is set. // The high order byte contains a single bit set to indiciate // which mode is active. if (BX_HD_THIS bmdma_present()) { BX_SELECTED_DRIVE(channel).id_drive[63] = 0x07 | (BX_SELECTED_CONTROLLER(channel).mdma_mode << 8); } else { BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0; } // Word 64 PIO modes supported BX_SELECTED_DRIVE(channel).id_drive[64] = 0x00; // Word 65-68 PIO/DMA cycle time (nanoseconds) for (i=65; i<=68; i++) BX_SELECTED_DRIVE(channel).id_drive[i] = 120; // Word 69-79 Reserved // Word 80: 15-5 reserved // 6 supports ATA/ATAPI-6 // 5 supports ATA/ATAPI-5 // 4 supports ATA/ATAPI-4 // 3 supports ATA-3 // 2 supports ATA-2 // 1 supports ATA-1 // 0 reserved BX_SELECTED_DRIVE(channel).id_drive[80] = 0x7e; // Word 81: Minor version number BX_SELECTED_DRIVE(channel).id_drive[81] = 0x00; // Word 82: 15 obsolete // 14 NOP command supported // 13 READ BUFFER command supported // 12 WRITE BUFFER command supported // 11 obsolete // 10 Host protected area feature set supported // 9 DEVICE RESET command supported // 8 SERVICE interrupt supported // 7 release interrupt supported // 6 look-ahead supported // 5 write cache supported // 4 supports PACKET command feature set // 3 supports power management feature set // 2 supports removable media feature set // 1 supports securite mode feature set // 0 support SMART feature set BX_SELECTED_DRIVE(channel).id_drive[82] = 1 << 14; // Word 83: 15 shall be ZERO // 14 shall be ONE // 13 FLUSH CACHE EXT command supported // 12 FLUSH CACHE command supported // 11 Device configuration overlay supported // 10 48-bit Address feature set supported // 9 Automatic acoustic management supported // 8 SET MAX security supported // 7 reserved for 1407DT PARTIES // 6 SetF sub-command Power-Up supported // 5 Power-Up in standby feature set supported // 4 Removable media notification supported // 3 APM feature set supported // 2 CFA feature set supported // 1 READ/WRITE DMA QUEUED commands supported // 0 Download MicroCode supported BX_SELECTED_DRIVE(channel).id_drive[83] = (1 << 14) | (1 << 13) | (1 << 12) | (1 << 10); BX_SELECTED_DRIVE(channel).id_drive[84] = 1 << 14; BX_SELECTED_DRIVE(channel).id_drive[85] = 1 << 14; // Word 86: 15 shall be ZERO // 14 shall be ONE // 13 FLUSH CACHE EXT command enabled // 12 FLUSH CACHE command enabled // 11 Device configuration overlay enabled // 10 48-bit Address feature set enabled // 9 Automatic acoustic management enabled // 8 SET MAX security enabled // 7 reserved for 1407DT PARTIES // 6 SetF sub-command Power-Up enabled // 5 Power-Up in standby feature set enabled // 4 Removable media notification enabled // 3 APM feature set enabled // 2 CFA feature set enabled // 1 READ/WRITE DMA QUEUED commands enabled // 0 Download MicroCode enabled BX_SELECTED_DRIVE(channel).id_drive[86] = (1 << 14) | (1 << 13) | (1 << 12) | (1 << 10); BX_SELECTED_DRIVE(channel).id_drive[87] = 1 << 14; if (BX_HD_THIS bmdma_present()) { BX_SELECTED_DRIVE(channel).id_drive[88] = 0x3f | (BX_SELECTED_CONTROLLER(channel).udma_mode << 8); } else { BX_SELECTED_DRIVE(channel).id_drive[88] = 0x0; } BX_SELECTED_DRIVE(channel).id_drive[93] = 1 | (1 << 14) | 0x2000; // Word 100-103: 48-bit total number of sectors BX_SELECTED_DRIVE(channel).id_drive[100] = (Bit16u)(num_sects & 0xffff); BX_SELECTED_DRIVE(channel).id_drive[101] = (Bit16u)(num_sects >> 16); BX_SELECTED_DRIVE(channel).id_drive[102] = (Bit16u)(num_sects >> 32); BX_SELECTED_DRIVE(channel).id_drive[103] = (Bit16u)(num_sects >> 48); // Word 128-159 Vendor unique // Word 160-255 Reserved BX_SELECTED_DRIVE(channel).identify_set = 1; } void bx_hard_drive_c::init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bx_bool lazy) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); // byte_count is a union of cylinder_no; // lazy is used to force a data read in the buffer at the next read. if (controller->byte_count == 0xffff) controller->byte_count = 0xfffe; if ((controller->byte_count & 1) && !(alloc_length <= controller->byte_count)) { BX_INFO(("Odd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%04x", controller->byte_count, command, controller->byte_count - 1)); controller->byte_count--; } if (!controller->packet_dma) { if (controller->byte_count == 0) BX_PANIC(("ATAPI command 0x%02x with zero byte count", command)); } if (alloc_length < 0) BX_PANIC(("Allocation length < 0")); if (alloc_length == 0) alloc_length = controller->byte_count; controller->interrupt_reason.i_o = 1; controller->interrupt_reason.c_d = 0; controller->status.busy = 0; controller->status.drq = 1; controller->status.err = 0; // no bytes transfered yet if (lazy) controller->buffer_index = controller->buffer_size; else controller->buffer_index = 0; controller->drq_index = 0; if (controller->byte_count > req_length) controller->byte_count = req_length; if (controller->byte_count > alloc_length) controller->byte_count = alloc_length; BX_SELECTED_DRIVE(channel).atapi.command = command; BX_SELECTED_DRIVE(channel).atapi.drq_bytes = controller->byte_count; BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length; } void bx_hard_drive_c::atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc, bx_bool show) { if (show) { BX_ERROR(("ata%d-%d: atapi_cmd_error: key=%02x asc=%02x", channel, BX_SLAVE_SELECTED(channel), sense_key, asc)); } else { BX_DEBUG(("ata%d-%d: atapi_cmd_error: key=%02x asc=%02x", channel, BX_SLAVE_SELECTED(channel), sense_key, asc)); } controller_t *controller = &BX_SELECTED_CONTROLLER(channel); controller->error_register = sense_key << 4; controller->interrupt_reason.i_o = 1; controller->interrupt_reason.c_d = 1; controller->interrupt_reason.rel = 0; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.write_fault = 0; controller->status.drq = 0; controller->status.err = 1; BX_SELECTED_DRIVE(channel).sense.sense_key = sense_key; BX_SELECTED_DRIVE(channel).sense.asc = asc; BX_SELECTED_DRIVE(channel).sense.ascq = 0; } void BX_CPP_AttrRegparmN(1) bx_hard_drive_c::atapi_cmd_nop(controller_t *controller) { controller->interrupt_reason.i_o = 1; controller->interrupt_reason.c_d = 1; controller->interrupt_reason.rel = 0; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.drq = 0; controller->status.err = 0; } void bx_hard_drive_c::init_mode_sense_single(Bit8u channel, const void* src, int size) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); // Header controller->buffer[0] = (size+6) >> 8; controller->buffer[1] = (size+6) & 0xff; if (BX_SELECTED_DRIVE(channel).cdrom.ready) controller->buffer[2] = 0x12; // media present 120mm CD-ROM (CD-R) data/audio door closed else controller->buffer[2] = 0x70; // no media present controller->buffer[3] = 0; // reserved controller->buffer[4] = 0; // reserved controller->buffer[5] = 0; // reserved controller->buffer[6] = 0; // reserved controller->buffer[7] = 0; // reserved // Data memcpy(controller->buffer + 8, src, size); } void BX_CPP_AttrRegparmN(1) bx_hard_drive_c::ready_to_send_atapi(Bit8u channel) { if (!BX_SELECTED_CONTROLLER(channel).packet_dma) { raise_interrupt(channel); } } void BX_CPP_AttrRegparmN(1) bx_hard_drive_c::raise_interrupt(Bit8u channel) { if (!BX_SELECTED_CONTROLLER(channel).control.disable_irq) { Bit32u irq = BX_HD_THIS channels[channel].irq; BX_DEBUG(("raising interrupt %d {%s}", irq, BX_SELECTED_TYPE_STRING(channel))); #if BX_SUPPORT_PCI DEV_ide_bmdma_set_irq(channel); #endif DEV_pic_raise_irq(irq); } else { BX_DEBUG(("not raising interrupt {%s}", BX_SELECTED_TYPE_STRING(channel))); } } void bx_hard_drive_c::command_aborted(Bit8u channel, unsigned value) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); BX_DEBUG(("aborting on command 0x%02x {%s}", value, BX_SELECTED_TYPE_STRING(channel))); controller->current_command = 0; controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.err = 1; controller->error_register = 0x04; // command ABORTED controller->status.drq = 0; controller->status.corrected_data = 0; controller->buffer_index = 0; raise_interrupt(channel); } Bit32u bx_hard_drive_c::get_first_cd_handle(void) { for (Bit8u channel=0; channel= BX_MAX_ATA_CHANNEL*2) return 0; Bit8u channel = handle / 2; Bit8u device = handle % 2; return BX_HD_THIS channels[channel].drives[device].cdrom.ready; } bx_bool bx_hard_drive_c::set_cd_media_status(Bit32u handle, bx_bool status) { char ata_name[20]; BX_DEBUG(("set_cd_media_status handle=%d status=%d", handle, status)); if (handle >= BX_MAX_ATA_CHANNEL*2) return 0; Bit8u channel = handle / 2; Bit8u device = handle % 2; sprintf(ata_name, "ata.%d.%s", channel, (device==0)?"master":"slave"); bx_list_c *base = (bx_list_c*) SIM->get_param(ata_name); // if setting to the current value, nothing to do if (status == BX_HD_THIS channels[channel].drives[device].cdrom.ready) return(status); // return 0 if selected drive is not a cdrom if (!BX_DRIVE_IS_CD(channel,device)) return(0); if (status == 0) { // eject cdrom if not locked by guest OS if (BX_HD_THIS channels[channel].drives[device].cdrom.locked) return(1); else { #ifdef LOWLEVEL_CDROM BX_HD_THIS channels[channel].drives[device].cdrom.cd->eject_cdrom(); #endif BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; SIM->get_param_bool("status", base)->set(0); } } else { // insert cdrom #ifdef LOWLEVEL_CDROM if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom(SIM->get_param_string("path", base)->getptr())) { BX_INFO(("Media present in CD-ROM drive")); BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1; Bit32u capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity(); BX_HD_THIS channels[channel].drives[device].cdrom.capacity = capacity; BX_INFO(("Capacity is %d sectors (%.2f MB)", capacity, (float)capacity / 512.0)); SIM->get_param_bool("status", base)->set(1); BX_SELECTED_DRIVE(channel).sense.sense_key = SENSE_UNIT_ATTENTION; BX_SELECTED_DRIVE(channel).sense.asc = ASC_MEDIUM_MAY_HAVE_CHANGED; BX_SELECTED_DRIVE(channel).sense.ascq = 0; raise_interrupt(channel); } else #endif { BX_INFO(("Could not locate CD-ROM, continuing with media not present")); BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0; SIM->get_param_bool("status", base)->set(0); } } return (BX_HD_THIS channels[channel].drives[device].cdrom.ready); } bx_bool bx_hard_drive_c::bmdma_present(void) { #if BX_SUPPORT_PCI if (BX_HD_THIS pci_enabled) { return DEV_ide_bmdma_present(); } #endif return 0; } #if BX_SUPPORT_PCI bx_bool bx_hard_drive_c::bmdma_read_sector(Bit8u channel, Bit8u *buffer, Bit32u *sector_size) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); if ((controller->current_command == 0xC8) || (controller->current_command == 0x25)) { *sector_size = 512; if (!ide_read_sector(channel, buffer, 512)) { return 0; } } else if (controller->current_command == 0xA0) { if (controller->packet_dma) { switch (BX_SELECTED_DRIVE(channel).atapi.command) { case 0x28: // read (10) case 0xa8: // read (12) case 0xbe: // read cd *sector_size = controller->buffer_size; if (!BX_SELECTED_DRIVE(channel).cdrom.ready) { BX_PANIC(("Read with CDROM not ready")); return 0; } /* set status bar conditions for device */ bx_gui->statusbar_setitem(BX_SELECTED_DRIVE(channel).statusbar_id, 1); #ifdef LOWLEVEL_CDROM if (!BX_SELECTED_DRIVE(channel).cdrom.cd->read_block(buffer, BX_SELECTED_DRIVE(channel).cdrom.next_lba, controller->buffer_size)) { BX_PANIC(("CDROM: read block %d failed", BX_SELECTED_DRIVE(channel).cdrom.next_lba)); return 0; } BX_SELECTED_DRIVE(channel).cdrom.next_lba++; BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks--; #else BX_PANIC(("BM-DMA read with no LOWLEVEL_CDROM")); #endif break; default: memcpy(buffer, controller->buffer, *sector_size); break; } } else { BX_ERROR(("PACKET-DMA not active")); command_aborted(channel, controller->current_command); return 0; } } else { BX_ERROR(("DMA read not active")); command_aborted (channel, controller->current_command); return 0; } return 1; } bx_bool bx_hard_drive_c::bmdma_write_sector(Bit8u channel, Bit8u *buffer) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); if ((controller->current_command != 0xCA) && (controller->current_command != 0x35)) { BX_ERROR(("DMA write not active")); command_aborted (channel, controller->current_command); return 0; } if (!ide_write_sector(channel, buffer, 512)) { return 0; } return 1; } void bx_hard_drive_c::bmdma_complete(Bit8u channel) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); controller->status.busy = 0; controller->status.drive_ready = 1; controller->status.drq = 0; controller->status.err = 0; if (BX_SELECTED_IS_CD(channel)) { controller->interrupt_reason.i_o = 1; controller->interrupt_reason.c_d = 1; controller->interrupt_reason.rel = 0; } else { controller->status.write_fault = 0; controller->status.seek_complete = 1; controller->status.corrected_data = 0; } raise_interrupt(channel); } #endif void bx_hard_drive_c::set_signature(Bit8u channel, Bit8u id) { // Device signature BX_CONTROLLER(channel,id).head_no = 0; BX_CONTROLLER(channel,id).sector_count = 1; BX_CONTROLLER(channel,id).sector_no = 1; if (BX_DRIVE_IS_HD(channel,id)) { BX_CONTROLLER(channel,id).cylinder_no = 0; BX_HD_THIS channels[channel].drive_select = 0; } else if (BX_DRIVE_IS_CD(channel,id)) { BX_CONTROLLER(channel,id).cylinder_no = 0xeb14; } else { BX_CONTROLLER(channel,id).cylinder_no = 0xffff; } } bx_bool bx_hard_drive_c::ide_read_sector(Bit8u channel, Bit8u *buffer, Bit32u buffer_size) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); Bit64s logical_sector = 0; Bit64s ret; int sector_count = (buffer_size / 512); Bit8u *bufptr = buffer; do { if (!calculate_logical_address(channel, &logical_sector)) { BX_ERROR(("ide_read_sector() reached invalid sector %lu, aborting", (unsigned long)logical_sector)); command_aborted(channel, controller->current_command); return 0; } ret = BX_SELECTED_DRIVE(channel).hdimage->lseek(logical_sector * 512, SEEK_SET); if (ret < 0) { BX_ERROR(("could not lseek() hard drive image file")); command_aborted(channel, controller->current_command); return 0; } /* set status bar conditions for device */ bx_gui->statusbar_setitem(BX_SELECTED_DRIVE(channel).statusbar_id, 1); ret = BX_SELECTED_DRIVE(channel).hdimage->read((bx_ptr_t)bufptr, 512); if (ret < 512) { BX_ERROR(("could not read() hard drive image file at byte %lu", (unsigned long)logical_sector*512)); command_aborted(channel, controller->current_command); return 0; } increment_address(channel, &logical_sector); bufptr += 512; } while (--sector_count > 0); return 1; } bx_bool bx_hard_drive_c::ide_write_sector(Bit8u channel, Bit8u *buffer, Bit32u buffer_size) { controller_t *controller = &BX_SELECTED_CONTROLLER(channel); Bit64s logical_sector = 0; Bit64s ret; int sector_count = (buffer_size / 512); Bit8u *bufptr = buffer; do { if (!calculate_logical_address(channel, &logical_sector)) { BX_ERROR(("ide_write_sector() reached invalid sector %lu, aborting", (unsigned long)logical_sector)); command_aborted(channel, controller->current_command); return 0; } ret = BX_SELECTED_DRIVE(channel).hdimage->lseek(logical_sector * 512, SEEK_SET); if (ret < 0) { BX_ERROR(("could not lseek() hard drive image file at byte %lu", (unsigned long)logical_sector * 512)); command_aborted(channel, controller->current_command); return 0; } /* set status bar conditions for device */ bx_gui->statusbar_setitem(BX_SELECTED_DRIVE(channel).statusbar_id, 1, 1 /* write */); ret = BX_SELECTED_DRIVE(channel).hdimage->write((bx_ptr_t)bufptr, 512); if (ret < 512) { BX_ERROR(("could not write() hard drive image file at byte %lu", (unsigned long)logical_sector*512)); command_aborted(channel, controller->current_command); return 0; } increment_address(channel, &logical_sector); bufptr += 512; } while (--sector_count > 0); return 1; } void bx_hard_drive_c::lba48_transform(controller_t *controller, bx_bool lba48) { controller->lba48 = lba48; if (!controller->lba48) { if (!controller->sector_count) controller->num_sectors = 256; else controller->num_sectors = controller->sector_count; } else { if (!controller->sector_count && !controller->hob.nsector) controller->num_sectors = 65536; else controller->num_sectors = (controller->hob.nsector << 8) | controller->sector_count; } } error_recovery_t::error_recovery_t() { if (sizeof(error_recovery_t) != 8) { BX_PANIC(("error_recovery_t has size != 8")); } data[0] = 0x01; data[1] = 0x06; data[2] = 0x00; data[3] = 0x05; // Try to recover 5 times data[4] = 0x00; data[5] = 0x00; data[6] = 0x00; data[7] = 0x00; } // cdrom runtime parameter handling // helper function int get_device_handle_from_param(bx_param_c *param) { char pname[BX_PATHNAME_LEN]; bx_list_c *base = (bx_list_c*) param->get_parent(); base->get_param_path(pname, BX_PATHNAME_LEN); if (!strncmp(pname, "ata.", 4)) { int handle = (pname[4] - '0') << 1; if (!strcmp(base->get_name(), "slave")) { handle |= 1; } return handle; } else { return -1; } } Bit64s bx_hard_drive_c::cdrom_status_handler(bx_param_c *param, int set, Bit64s val) { if (set) { int handle = get_device_handle_from_param(param); if (handle >= 0) { if (!strcmp(param->get_name(), "status")) { BX_HD_THIS channels[handle/2].drives[handle%2].status_changed = 1; } } else { BX_PANIC(("cdrom_status_handler called with unexpected parameter '%s'", param->get_name())); } } return val; } const char *bx_hard_drive_c::cdrom_path_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { if (set) { if (strlen(val) < 1) { val = "none"; } int handle = get_device_handle_from_param(param); if (handle >= 0) { if (!strcmp(param->get_name(), "path")) { BX_HD_THIS channels[handle/2].drives[handle%2].status_changed = 1; } } else { BX_PANIC(("cdrom_path_handler called with unexpected parameter '%s'", param->get_name())); } } return val; } bochs-2.6/iodev/iodev.h0000644000175000017500000005204412020641505014722 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: iodev.h 11349 2012-08-20 07:35:30Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2012 The Bochs Project // // I/O port handlers API Copyright (C) 2003 by Frank Cornelis // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #ifndef IODEV_H #define IODEV_H #include "bochs.h" #include "plugin.h" #include "param_names.h" /* number of IRQ lines supported. In an ISA PC there are two PIC chips cascaded together. each has 8 IRQ lines, so there should be 16 IRQ's total */ #define BX_MAX_IRQS 16 /* size of internal buffer for mouse devices */ #define BX_MOUSE_BUFF_SIZE 48 /* maximum size of the ISA DMA buffer */ #define BX_DMA_BUFFER_SIZE 512 typedef Bit32u (*bx_read_handler_t)(void *, Bit32u, unsigned); typedef void (*bx_write_handler_t)(void *, Bit32u, Bit32u, unsigned); typedef bx_bool (*bx_keyb_enq_t)(void *, Bit8u *); typedef void (*bx_mouse_enq_t)(void *, int, int, int, unsigned, bx_bool); typedef void (*bx_mouse_enabled_changed_t)(void *, bx_bool); #if BX_USE_DEV_SMF # define BX_DEV_SMF static # define BX_DEV_THIS bx_devices. #else # define BX_DEV_SMF # define BX_DEV_THIS this-> #endif ////////////////////////////////////////////////////////////////////// // bx_devmodel_c declaration ////////////////////////////////////////////////////////////////////// // This class defines virtual methods that are common to all devices. // Child classes do not need to implement all of them, because in this // definition they are defined as empty, as opposed to being pure // virtual (= 0). class BOCHSAPI bx_devmodel_c : public logfunctions { public: virtual ~bx_devmodel_c() {} virtual void init(void) {} virtual void reset(unsigned type) {} virtual void register_state(void) {} virtual void after_restore_state(void) {} #if BX_DEBUGGER virtual void debug_dump(int argc, char **argv) {} #endif }; ////////////////////////////////////////////////////////////////////// // declare stubs for PCI devices ////////////////////////////////////////////////////////////////////// class bx_list_c; class device_image_t; class LOWLEVEL_CDROM; // the best should be deriving of bx_pci_device_stub_c from bx_devmodel_c // but it make serious problems for cirrus_svga device class BOCHSAPI bx_pci_device_stub_c { public: bx_pci_device_stub_c(): pci_rom(NULL), pci_rom_size(0) {} virtual ~bx_pci_device_stub_c() { if (pci_rom != NULL) delete [] pci_rom; } virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len) { return 0; } virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len) {} void register_pci_state(bx_list_c *list); void load_pci_rom(const char *path); protected: Bit8u pci_conf[256]; Bit32u pci_base_address[6]; Bit8u *pci_rom; Bit32u pci_rom_address; Bit32u pci_rom_size; }; ////////////////////////////////////////////////////////////////////// // declare stubs for devices ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// #define STUBFUNC(dev,method) \ pluginlog->panic("%s called in %s stub. you must not have loaded the %s plugin", #dev, #method, #dev) ////////////////////////////////////////////////////////////////////// class BOCHSAPI bx_keyb_stub_c : public bx_devmodel_c { public: virtual ~bx_keyb_stub_c() {} // stubs for bx_keyb_c methods virtual void gen_scancode(Bit32u key) { STUBFUNC(keyboard, gen_scancode); } virtual void paste_bytes(Bit8u *data, Bit32s length) { STUBFUNC(keyboard, paste_bytes); } }; class BOCHSAPI bx_hard_drive_stub_c : public bx_devmodel_c { public: virtual void init() { STUBFUNC(HD, init); } virtual void reset(unsigned type) { STUBFUNC(HD, reset); } virtual Bit32u get_first_cd_handle(void) { STUBFUNC(HD, get_first_cd_handle); return 0; } virtual unsigned get_cd_media_status(Bit32u handle) { STUBFUNC(HD, get_cd_media_status); return 0; } virtual unsigned set_cd_media_status(Bit32u handle, unsigned status) { STUBFUNC(HD, set_cd_media_status); return 0; } virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len) { STUBFUNC(HD, virt_read_handler); return 0; } virtual void virt_write_handler(Bit32u address, Bit32u value, unsigned io_len) { STUBFUNC(HD, virt_write_handler); } virtual bx_bool bmdma_read_sector(Bit8u channel, Bit8u *buffer, Bit32u *sector_size) { STUBFUNC(HD, bmdma_read_sector); return 0; } virtual bx_bool bmdma_write_sector(Bit8u channel, Bit8u *buffer) { STUBFUNC(HD, bmdma_write_sector); return 0; } virtual void bmdma_complete(Bit8u channel) { STUBFUNC(HD, bmdma_complete); } }; class BOCHSAPI bx_floppy_stub_c : public bx_devmodel_c { public: virtual unsigned set_media_status(unsigned drive, unsigned status) { STUBFUNC(floppy, set_media_status); return 0; } }; class BOCHSAPI bx_cmos_stub_c : public bx_devmodel_c { public: virtual Bit32u get_reg(unsigned reg) { STUBFUNC(cmos, get_reg); return 0; } virtual void set_reg(unsigned reg, Bit32u val) { STUBFUNC(cmos, set_reg); } virtual time_t get_timeval() { return 0; } virtual void checksum_cmos(void) { STUBFUNC(cmos, checksum); } }; class BOCHSAPI bx_dma_stub_c : public bx_devmodel_c { public: virtual unsigned registerDMA8Channel( unsigned channel, Bit16u (* dmaRead)(Bit8u *data_byte, Bit16u maxlen), Bit16u (* dmaWrite)(Bit8u *data_byte, Bit16u maxlen), const char *name) { STUBFUNC(dma, registerDMA8Channel); return 0; } virtual unsigned registerDMA16Channel( unsigned channel, Bit16u (* dmaRead)(Bit16u *data_word, Bit16u maxlen), Bit16u (* dmaWrite)(Bit16u *data_word, Bit16u maxlen), const char *name) { STUBFUNC(dma, registerDMA16Channel); return 0; } virtual unsigned unregisterDMAChannel(unsigned channel) { STUBFUNC(dma, unregisterDMAChannel); return 0; } virtual unsigned get_TC(void) { STUBFUNC(dma, get_TC); return 0; } virtual void set_DRQ(unsigned channel, bx_bool val) { STUBFUNC(dma, set_DRQ); } virtual void raise_HLDA(void) { STUBFUNC(dma, raise_HLDA); } }; class BOCHSAPI bx_pic_stub_c : public bx_devmodel_c { public: virtual void raise_irq(unsigned irq_no) { STUBFUNC(pic, raise_irq); } virtual void lower_irq(unsigned irq_no) { STUBFUNC(pic, lower_irq); } virtual void set_mode(bx_bool ma_sl, Bit8u mode) { STUBFUNC(pic, set_mode); } virtual Bit8u IAC(void) { STUBFUNC(pic, IAC); return 0; } }; class BOCHSAPI bx_vga_stub_c : public bx_devmodel_c { public: virtual void redraw_area(unsigned x0, unsigned y0, unsigned width, unsigned height) { STUBFUNC(vga, redraw_area); } virtual Bit8u mem_read(bx_phy_address addr) { STUBFUNC(vga, mem_read); return 0; } virtual void mem_write(bx_phy_address addr, Bit8u value) { STUBFUNC(vga, mem_write); } virtual int get_snapshot_mode(void) { STUBFUNC(vga, get_snapshot_mode); return 0; } virtual void get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight, unsigned *txWidth) { STUBFUNC(vga, get_text_snapshot); } virtual Bit32u get_gfx_snapshot(Bit8u **snapshot_ptr, Bit8u **palette_ptr, unsigned *iHeight, unsigned *iWidth, unsigned *iDepth) { STUBFUNC(vga, get_gfx_snapshot); return 0; } virtual void set_override(bx_bool enabled) { STUBFUNC(vga, set_override); } virtual void trigger_timer(void *this_ptr) { STUBFUNC(vga, trigger_timer); } }; class BOCHSAPI bx_pci_bridge_stub_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: virtual bx_bool register_pci_handlers(bx_pci_device_stub_c *device, Bit8u *devfunc, const char *name, const char *descr) { STUBFUNC(pci, register_pci_handlers); return 0; } virtual bx_bool is_pci_device(const char *name) { return 0; } virtual bx_bool pci_set_base_mem(void *this_ptr, memory_handler_t f1, memory_handler_t f2, Bit32u *addr, Bit8u *pci_conf, unsigned size) { STUBFUNC(pci, pci_set_base_mem); return 0; } virtual bx_bool pci_set_base_io(void *this_ptr, bx_read_handler_t f1, bx_write_handler_t f2, Bit32u *addr, Bit8u *pci_conf, unsigned size, const Bit8u *iomask, const char *name) { STUBFUNC(pci, pci_set_base_io); return 0; } }; class BOCHSAPI bx_pci2isa_stub_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: virtual void pci_set_irq (Bit8u devfunc, unsigned line, bx_bool level) { STUBFUNC(pci2isa, pci_set_irq); } }; class BOCHSAPI bx_pci_ide_stub_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: virtual bx_bool bmdma_present(void) { return 0; } virtual void bmdma_set_irq(Bit8u channel) {} }; class BOCHSAPI bx_speaker_stub_c : public bx_devmodel_c { public: virtual void beep_on(float frequency) { bx_gui->beep_on(frequency); } virtual void beep_off() { bx_gui->beep_off(); } }; #if BX_SUPPORT_PCI class BOCHSAPI bx_acpi_ctrl_stub_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: virtual void generate_smi(Bit8u value) {} }; #endif #if BX_SUPPORT_IODEBUG class BOCHSAPI bx_iodebug_stub_c : public bx_devmodel_c { public: virtual void mem_write(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {} virtual void mem_read(BX_CPU_C *cpu, bx_phy_address addr, unsigned len, void *data) {} }; #endif #if BX_SUPPORT_APIC class BOCHSAPI bx_ioapic_stub_c : public bx_devmodel_c { public: virtual void receive_eoi(Bit8u vector) {} virtual void set_irq_level(Bit8u int_in, bx_bool level) {} }; #endif #if BX_SUPPORT_GAMEPORT class BOCHSAPI bx_game_stub_c : public bx_devmodel_c { public: virtual void set_enabled(bx_bool val) { STUBFUNC(gameport, set_enabled); } }; #endif #if BX_SUPPORT_PCIUSB class BOCHSAPI bx_usb_devctl_stub_c : public bx_devmodel_c { public: virtual int init_device(bx_list_c *portconf, logfunctions *hub, void **dev, bx_list_c *sr_list) { STUBFUNC(usb_devctl, init_device); return 0; } virtual void usb_send_msg(void *dev, int msg) {} }; #endif class BOCHSAPI bx_hdimage_ctl_stub_c : public bx_devmodel_c { public: virtual device_image_t* init_image(Bit8u image_mode, Bit64u disk_size, const char *journal) { STUBFUNC(hdimage_ctl, init_image); return NULL; } #ifdef LOWLEVEL_CDROM virtual LOWLEVEL_CDROM* init_cdrom(const char *dev) { STUBFUNC(hdimage_ctl, init_cdrom); return NULL; } #endif }; #if BX_SUPPORT_SOUNDLOW class BOCHSAPI bx_soundmod_ctl_stub_c : public bx_devmodel_c { public: virtual void* init_module(const char *type, logfunctions *dev) { STUBFUNC(soundmod_ctl, init_module); return NULL; } virtual bx_bool beep_on(float frequency) { return 0; } virtual bx_bool beep_off() { return 0; } }; #endif #if BX_NETWORKING class BOCHSAPI bx_netmod_ctl_stub_c : public bx_devmodel_c { public: virtual void* init_module(bx_list_c *base, void* rxh, void* rxstat, bx_devmodel_c *dev) { STUBFUNC(netmod_ctl, init_module); return NULL; } }; #endif class BOCHSAPI bx_devices_c : public logfunctions { public: bx_devices_c(); ~bx_devices_c(); // Initialize the device stubs (in constructur and exit()) void init_stubs(void); // Register I/O addresses and IRQ lines. Initialize any internal // structures. init() is called only once, even if the simulator // reboots or is restarted. void init(BX_MEM_C *); // Enter reset state in response to a reset condition. // The types of reset conditions are defined in bochs.h: // power-on, hardware, or software. void reset(unsigned type); // Cleanup the devices when the simulation quits. void exit(void); void register_state(void); void after_restore_state(void); BX_MEM_C *mem; // address space associated with these devices bx_bool register_io_read_handler(void *this_ptr, bx_read_handler_t f, Bit32u addr, const char *name, Bit8u mask); bx_bool unregister_io_read_handler(void *this_ptr, bx_read_handler_t f, Bit32u addr, Bit8u mask); bx_bool register_io_write_handler(void *this_ptr, bx_write_handler_t f, Bit32u addr, const char *name, Bit8u mask); bx_bool unregister_io_write_handler(void *this_ptr, bx_write_handler_t f, Bit32u addr, Bit8u mask); bx_bool register_io_read_handler_range(void *this_ptr, bx_read_handler_t f, Bit32u begin_addr, Bit32u end_addr, const char *name, Bit8u mask); bx_bool register_io_write_handler_range(void *this_ptr, bx_write_handler_t f, Bit32u begin_addr, Bit32u end_addr, const char *name, Bit8u mask); bx_bool unregister_io_read_handler_range(void *this_ptr, bx_read_handler_t f, Bit32u begin, Bit32u end, Bit8u mask); bx_bool unregister_io_write_handler_range(void *this_ptr, bx_write_handler_t f, Bit32u begin, Bit32u end, Bit8u mask); bx_bool register_default_io_read_handler(void *this_ptr, bx_read_handler_t f, const char *name, Bit8u mask); bx_bool register_default_io_write_handler(void *this_ptr, bx_write_handler_t f, const char *name, Bit8u mask); bx_bool register_irq(unsigned irq, const char *name); bx_bool unregister_irq(unsigned irq, const char *name); Bit32u inp(Bit16u addr, unsigned io_len) BX_CPP_AttrRegparmN(2); void outp(Bit16u addr, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3); void register_removable_keyboard(void *dev, bx_keyb_enq_t keyb_enq); void unregister_removable_keyboard(void *dev); void register_default_mouse(void *dev, bx_mouse_enq_t mouse_enq, bx_mouse_enabled_changed_t mouse_enabled_changed); void register_removable_mouse(void *dev, bx_mouse_enq_t mouse_enq, bx_mouse_enabled_changed_t mouse_enabled_changed); void unregister_removable_mouse(void *dev); bx_bool optional_key_enq(Bit8u *scan_code); void mouse_enabled_changed(bx_bool enabled); void mouse_motion(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy); static void timer_handler(void *); void timer(void); bx_pci_bridge_stub_c *pluginPciBridge; bx_pci2isa_stub_c *pluginPci2IsaBridge; bx_pci_ide_stub_c *pluginPciIdeController; #if BX_SUPPORT_PCI bx_acpi_ctrl_stub_c *pluginACPIController; #endif bx_devmodel_c *pluginPitDevice; bx_keyb_stub_c *pluginKeyboard; bx_dma_stub_c *pluginDmaDevice; bx_floppy_stub_c *pluginFloppyDevice; bx_cmos_stub_c *pluginCmosDevice; bx_vga_stub_c *pluginVgaDevice; bx_pic_stub_c *pluginPicDevice; bx_hard_drive_stub_c *pluginHardDrive; bx_hdimage_ctl_stub_c *pluginHDImageCtl; bx_speaker_stub_c *pluginSpeaker; #if BX_SUPPORT_IODEBUG bx_iodebug_stub_c *pluginIODebug; #endif #if BX_SUPPORT_APIC bx_ioapic_stub_c *pluginIOAPIC; #endif #if BX_SUPPORT_GAMEPORT bx_game_stub_c *pluginGameport; #endif #if BX_SUPPORT_PCIUSB bx_usb_devctl_stub_c *pluginUsbDevCtl; #endif #if BX_SUPPORT_SOUNDLOW bx_soundmod_ctl_stub_c *pluginSoundModCtl; #endif #if BX_NETWORKING bx_netmod_ctl_stub_c *pluginNetModCtl; #endif // stub classes that the pointers (above) can point to until a plugin is // loaded bx_cmos_stub_c stubCmos; bx_keyb_stub_c stubKeyboard; bx_hard_drive_stub_c stubHardDrive; bx_hdimage_ctl_stub_c stubHDImage; bx_dma_stub_c stubDma; bx_pic_stub_c stubPic; bx_floppy_stub_c stubFloppy; bx_vga_stub_c stubVga; bx_pci_bridge_stub_c stubPci; bx_pci2isa_stub_c stubPci2Isa; bx_pci_ide_stub_c stubPciIde; bx_speaker_stub_c stubSpeaker; #if BX_SUPPORT_PCI bx_acpi_ctrl_stub_c stubACPIController; #endif #if BX_SUPPORT_IODEBUG bx_iodebug_stub_c stubIODebug; #endif #if BX_SUPPORT_APIC bx_ioapic_stub_c stubIOAPIC; #endif #if BX_SUPPORT_GAMEPORT bx_game_stub_c stubGameport; #endif #if BX_SUPPORT_PCIUSB bx_usb_devctl_stub_c stubUsbDevCtl; #endif #if BX_SUPPORT_SOUNDLOW bx_soundmod_ctl_stub_c stubSoundModCtl; #endif #if BX_NETWORKING bx_netmod_ctl_stub_c stubNetModCtl; #endif // Some info to pass to devices which can handled bulk IO. This allows // the interface to remain the same for IO devices which can't handle // bulk IO. We should probably implement special INPBulk() and OUTBulk() // functions which stick these values in the bx_devices_c class, and // then call the normal functions rather than having gross globals // variables. Bit8u* bulkIOHostAddr; unsigned bulkIOQuantumsRequested; unsigned bulkIOQuantumsTransferred; private: struct io_handler_struct { struct io_handler_struct *next; struct io_handler_struct *prev; void *funct; // C++ type checking is great, but annoying void *this_ptr; char *handler_name; // name of device int usage_count; Bit8u mask; // io_len mask }; struct io_handler_struct io_read_handlers; struct io_handler_struct io_write_handlers; #define PORTS 0x10000 struct io_handler_struct **read_port_to_handler; struct io_handler_struct **write_port_to_handler; // more for informative purposes, the names of the devices which // are use each of the IRQ 0..15 lines are stored here char *irq_handler_name[BX_MAX_IRQS]; static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); BX_DEV_SMF Bit32u port92_read(Bit32u address, unsigned io_len); BX_DEV_SMF void port92_write(Bit32u address, Bit32u value, unsigned io_len); static Bit32u default_read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void default_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); bx_bool mouse_captured; // host mouse capture enabled Bit8u mouse_type; struct { void *dev; bx_mouse_enq_t enq_event; bx_mouse_enabled_changed_t enabled_changed; } bx_mouse[2]; struct { void *dev; bx_keyb_enq_t enq_event; } bx_keyboard; int timer_handle; bx_bool network_enabled; bx_bool sound_enabled; bx_bool usb_enabled; bx_bool is_harddrv_enabled(); bx_bool is_network_enabled(); bx_bool is_sound_enabled(); bx_bool is_usb_enabled(); }; // memory stub has an assumption that there are no memory accesses splitting 4K page BX_CPP_INLINE void DEV_MEM_READ_PHYSICAL(bx_phy_address phy_addr, unsigned len, Bit8u *ptr) { unsigned remainingInPage = 0x1000 - (phy_addr & 0xfff); if (len <= remainingInPage) { BX_MEM(0)->readPhysicalPage(NULL, phy_addr, len, ptr); } else { BX_MEM(0)->readPhysicalPage(NULL, phy_addr, remainingInPage, ptr); ptr += remainingInPage; phy_addr += remainingInPage; len -= remainingInPage; BX_MEM(0)->readPhysicalPage(NULL, phy_addr, len, ptr); } } BX_CPP_INLINE void DEV_MEM_READ_PHYSICAL_DMA(bx_phy_address phy_addr, unsigned len, Bit8u *ptr) { while(len > 0) { unsigned remainingInPage = 0x1000 - (phy_addr & 0xfff); if (len < remainingInPage) remainingInPage = len; BX_MEM(0)->dmaReadPhysicalPage(phy_addr, remainingInPage, ptr); ptr += remainingInPage; phy_addr += remainingInPage; len -= remainingInPage; } } // memory stub has an assumption that there are no memory accesses splitting 4K page BX_CPP_INLINE void DEV_MEM_WRITE_PHYSICAL(bx_phy_address phy_addr, unsigned len, Bit8u *ptr) { unsigned remainingInPage = 0x1000 - (phy_addr & 0xfff); if (len <= remainingInPage) { BX_MEM(0)->writePhysicalPage(NULL, phy_addr, len, ptr); } else { BX_MEM(0)->writePhysicalPage(NULL, phy_addr, remainingInPage, ptr); ptr += remainingInPage; phy_addr += remainingInPage; len -= remainingInPage; BX_MEM(0)->writePhysicalPage(NULL, phy_addr, len, ptr); } } BX_CPP_INLINE void DEV_MEM_WRITE_PHYSICAL_DMA(bx_phy_address phy_addr, unsigned len, Bit8u *ptr) { while(len > 0) { unsigned remainingInPage = 0x1000 - (phy_addr & 0xfff); if (len < remainingInPage) remainingInPage = len; BX_MEM(0)->dmaWritePhysicalPage(phy_addr, remainingInPage, ptr); ptr += remainingInPage; phy_addr += remainingInPage; len -= remainingInPage; } } BOCHSAPI extern bx_devices_c bx_devices; #endif /* IODEV_H */ bochs-2.6/iodev/busmouse.cc0000644000175000017500000002521012020641505015607 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: busmouse.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Initial code by Ben Lunt 'fys frontiernet net' // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #include "busmouse.h" #if BX_SUPPORT_BUSMOUSE #define LOG_THIS theBusMouse-> bx_busm_c *theBusMouse = NULL; int libbusmouse_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { // Create one instance of the busmouse device object. theBusMouse = new bx_busm_c(); // Register this device. BX_REGISTER_DEVICE_DEVMODEL (plugin, type, theBusMouse, BX_PLUGIN_BUSMOUSE); return(0); // Success } void libbusmouse_LTX_plugin_fini(void) { delete theBusMouse; } bx_busm_c::bx_busm_c() { put("busmouse", "BUSM"); } bx_busm_c::~bx_busm_c() { SIM->get_bochs_root()->remove("busmouse"); BX_DEBUG(("Exit")); } void bx_busm_c::init(void) { BX_DEBUG(("Init $Id: busmouse.cc 11346 2012-08-19 08:16:20Z vruppert $")); DEV_register_irq(BUS_MOUSE_IRQ, "Bus Mouse"); // Call our timer routine at 30hz BX_BUSM_THIS timer_index = bx_pc_system.register_timer(this, timer_handler, 33334, 1, 1, "bus mouse timer"); for (int i=0x23C; i<=0x23F; i++) { DEV_register_ioread_handler(this, read_handler, i, "Bus Mouse", 1); DEV_register_iowrite_handler(this, write_handler, i, "Bus Mouse", 1); } DEV_register_default_mouse(this, mouse_enq_static, NULL); BX_BUSM_THIS mouse_delayed_dx = 0; BX_BUSM_THIS mouse_delayed_dy = 0; BX_BUSM_THIS current_x = BX_BUSM_THIS current_y = BX_BUSM_THIS current_b = 0; BX_BUSM_THIS sig_port_sequ = 0; BX_BUSM_THIS interrupts = 0; // interrupts off BX_BUSM_THIS command_val = 0; // command byte BX_BUSM_THIS cur_command = 0; // the control port values BX_BUSM_THIS control_val = BX_BUSM_THIS control.mode_set = BX_BUSM_THIS control.modeA_select = BX_BUSM_THIS control.portA_dir = BX_BUSM_THIS control.portC_upper_dir = BX_BUSM_THIS control.modeBC_select = BX_BUSM_THIS control.portB_dir = BX_BUSM_THIS control.portC_lower_dir = BX_BUSM_THIS control_val = 0; BX_INFO(("Initialized BusMouse")); } void bx_busm_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "busmouse", "Busmouse State"); BXRS_HEX_PARAM_FIELD(list, mouse_delayed_dx, BX_BUSM_THIS mouse_delayed_dx); BXRS_HEX_PARAM_FIELD(list, mouse_delayed_dx, BX_BUSM_THIS mouse_delayed_dy); BXRS_HEX_PARAM_FIELD(list, current_x, BX_BUSM_THIS current_x); BXRS_HEX_PARAM_FIELD(list, current_y, BX_BUSM_THIS current_y); BXRS_HEX_PARAM_FIELD(list, current_b, BX_BUSM_THIS current_b); BXRS_HEX_PARAM_FIELD(list, sig_port_sequ, BX_BUSM_THIS sig_port_sequ); BXRS_HEX_PARAM_FIELD(list, control_val, BX_BUSM_THIS control_val); bx_list_c *ctrl = new bx_list_c(list, "control"); BXRS_PARAM_BOOL(ctrl, mode_set, BX_BUSM_THIS control.mode_set); BXRS_HEX_PARAM_FIELD(ctrl, modeA_select, BX_BUSM_THIS control.modeA_select); BXRS_PARAM_BOOL(ctrl, portA_dir, BX_BUSM_THIS control.portA_dir); BXRS_PARAM_BOOL(ctrl, portC_upper_dir, BX_BUSM_THIS control.portC_upper_dir); BXRS_PARAM_BOOL(ctrl, modeBC_select, BX_BUSM_THIS control.modeBC_select); BXRS_PARAM_BOOL(ctrl, portB_dir, BX_BUSM_THIS control.portB_dir); BXRS_PARAM_BOOL(ctrl, portC_lower_dir, BX_BUSM_THIS control.portC_lower_dir); BXRS_PARAM_BOOL(list, interrupts, BX_BUSM_THIS interrupts); BXRS_PARAM_BOOL(list, packet_update, BX_BUSM_THIS packet_update); BXRS_HEX_PARAM_FIELD(list, cur_command, BX_BUSM_THIS cur_command); BXRS_HEX_PARAM_FIELD(list, command_val, BX_BUSM_THIS command_val); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_busm_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_BUSM_SMF bx_busm_c *class_ptr = (bx_busm_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_busm_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_BUSM_SMF Bit8u value = 0; switch (address) { case 0x023C: value = BX_BUSM_THIS control_val; /* value = (BX_BUSM_THIS control.mode_set ? 1<<7 : 0) * | (BX_BUSM_THIS control.modeA_select <<5) * | (BX_BUSM_THIS control.portA_dir ? 1<<4 : 0) * | (BX_BUSM_THIS control.portC_upper_dir ? 1<<3 : 0) * | (BX_BUSM_THIS control.modeBC_select ? 1<<2 : 0) * | (BX_BUSM_THIS control.portB_dir ? 1<<1 : 0) * | (BX_BUSM_THIS control.portC_lower_dir ? 1<<0 : 0); */ break; case 0x023D: // data switch (BX_BUSM_THIS cur_command) { case 0x00: // read buttons value = BX_BUSM_THIS current_b; break; case 0x01: // read x value = BX_BUSM_THIS current_x; break; case 0x02: // read y value = BX_BUSM_THIS current_y; break; case 0x07: // command mode value = BX_BUSM_THIS command_val; break; default: BX_PANIC(("Unknown command to data port: %x", BX_BUSM_THIS cur_command)); } break; case 0x023E: // sig if (!(BX_BUSM_THIS sig_port_sequ & 1)) value = 0xDE; else value = 0x22; // Manufacture id? BX_BUSM_THIS sig_port_sequ++; break; case 0x023F: BX_PANIC(("Read from port 0x023F")); break; } BX_INFO(("read from address 0x%04x, value = 0x%02x ", address, value)); return value; } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_busm_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_BUSM_SMF bx_busm_c *class_ptr = (bx_busm_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_busm_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_BUSM_SMF BX_INFO(("write to address 0x%04x, value = 0x%02x ", address, value)); switch (address) { case 0x023C: // control BX_BUSM_THIS control.mode_set = (value & 0x80) ? 1 : 0; BX_BUSM_THIS control.modeA_select = (value & 0x60) >> 5; BX_BUSM_THIS control.portA_dir = (value & 0x10) ? 1 : 0; BX_BUSM_THIS control.portC_upper_dir = (value & 0x08) ? 1 : 0; BX_BUSM_THIS control.modeBC_select = (value & 0x04) ? 1 : 0; BX_BUSM_THIS control.portB_dir = (value & 0x02) ? 1 : 0; BX_BUSM_THIS control.portC_lower_dir = (value & 0x01) ? 1 : 0; BX_BUSM_THIS control_val = value; /* switch (value) { case 0x00: // read buttons case 0x01: // read x case 0x02: // read y case 0x07: BX_BUSM_THIS cur_command = (Bit8u) value; break; case 0x80: // reset BX_BUSM_THIS cur_command = 0x00; BX_BUSM_THIS command_val = 0x80; break; default: BX_PANIC(("Unknown command to control port %x", value)); } */ break; case 0x023D: // data port switch (BX_BUSM_THIS cur_command) { case 0x07: // command mode switch (value) { case 0x10: // interrupts off BX_BUSM_THIS interrupts = 0; break; case 0x11: // interrupts on BX_BUSM_THIS interrupts = 1; break; default: BX_BUSM_THIS command_val = value; if ((value & 0x20) == 0) DEV_pic_lower_irq(BUS_MOUSE_IRQ); } break; default: BX_PANIC(("Unknown command written to data port: %x", BX_BUSM_THIS cur_command)); } break; case 0x023E: BX_PANIC(("Write to port 0x023E")); break; case 0x023F: BX_PANIC(("Write to port 0x023F")); break; } } void bx_busm_c::mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state) { ((bx_busm_c*)dev)->mouse_enq(delta_x, delta_y, delta_z, button_state); } void bx_busm_c::mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state) { // scale down the motion if ((delta_x < -1) || (delta_x > 1)) delta_x /= 2; if ((delta_y < -1) || (delta_y > 1)) delta_y /= 2; if(delta_x>127) delta_x=127; if(delta_y>127) delta_y=127; if(delta_x<-128) delta_x=-128; if(delta_y<-128) delta_y=-128; BX_BUSM_THIS mouse_delayed_dx+=delta_x; BX_BUSM_THIS mouse_delayed_dy-=delta_y; if (BX_BUSM_THIS mouse_delayed_dx > 127) { delta_x = 127; BX_BUSM_THIS mouse_delayed_dx -= 127; } else if (BX_BUSM_THIS mouse_delayed_dx < -128) { delta_x = -128; BX_BUSM_THIS mouse_delayed_dx += 128; } else { delta_x = BX_BUSM_THIS mouse_delayed_dx; BX_BUSM_THIS mouse_delayed_dx = 0; } if (BX_BUSM_THIS mouse_delayed_dy > 127) { delta_y = 127; BX_BUSM_THIS mouse_delayed_dy -= 127; } else if (BX_BUSM_THIS mouse_delayed_dy < -128) { delta_y = -128; BX_BUSM_THIS mouse_delayed_dy += 128; } else { delta_y = BX_BUSM_THIS mouse_delayed_dy; BX_BUSM_THIS mouse_delayed_dy = 0; } if ((BX_BUSM_THIS cur_command & 0x20) == 0x00) { BX_BUSM_THIS current_x = (Bit8u) delta_x; BX_BUSM_THIS current_y = (Bit8u) delta_y; BX_BUSM_THIS current_b = (Bit8u) ~(((button_state & 0x01)<<2) | ((button_state & 0x02) >> 1)); } } void bx_busm_c::timer_handler(void *this_ptr) { bx_busm_c *class_ptr = (bx_busm_c *) this_ptr; class_ptr->busm_timer(); } // Called at 30hz void bx_busm_c::busm_timer(void) { // if interrupts are on, fire the interrupt if (BX_BUSM_THIS interrupts) { DEV_pic_raise_irq(BUS_MOUSE_IRQ); } } #endif // BX_SUPPORT_BUSMOUSE bochs-2.6/iodev/usb/0000755000175000017500000000000012020641504014226 5ustar guillemguillembochs-2.6/iodev/usb/usb_printer.cc0000644000175000017500000002315312020641504017075 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_printer.cc 11027 2012-02-12 18:43:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB #include "usb_common.h" #include "usb_printer.h" #define LOG_THIS static const Bit8u bx_printer_dev_descriptor[] = { 0x12, /* u8 bLength; */ 0x01, /* u8 bDescriptorType; Device */ 0x10, 0x01, /* u16 bcdUSB; v1.10 */ 0x00, /* u8 bDeviceClass; */ 0x00, /* u8 bDeviceSubClass; */ 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */ 0x08, /* u8 bMaxPacketSize0; 8 Bytes */ 0xF0, 0x03, /* u16 idVendor; */ 0x04, 0x15, /* u16 idProduct; */ 0x00, 0x01, /* u16 bcdDevice */ 0x01, /* u8 iManufacturer; */ 0x02, /* u8 iProduct; */ 0x03, /* u8 iSerialNumber; */ 0x01 /* u8 bNumConfigurations; */ }; static const Bit8u bx_printer_config_descriptor[] = { /* one configuration */ 0x09, /* u8 bLength; */ 0x02, /* u8 bDescriptorType; Configuration */ 0x20, 0x00, /* u16 wTotalLength; */ 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x00, /* u8 iConfiguration string desc.; */ 0xC0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 0x02, /* u8 MaxPower; */ /* one interface */ 0x09, /* u8 if_bLength; */ 0x04, /* u8 if_bDescriptorType; Interface */ 0x00, /* u8 if_bInterfaceNumber; */ 0x00, /* u8 if_bAlternateSetting; */ 0x02, /* u8 if_bNumEndpoints; */ 0x07, /* u8 if_bInterfaceClass; */ 0x01, /* u8 if_bInterfaceSubClass; */ 0x02, /* u8 if_bInterfaceProtocol; */ 0x00, /* u8 if_iInterface; string desc. */ /* first endpoint */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x02, /* u8 ep_bmAttributes; Bulk */ 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ 0x00, /* u8 ep_bInterval; */ /* second endpoint */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */ 0x02, /* u8 ep_bmAttributes; Bulk */ 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ 0x00, /* u8 ep_bInterval; */ }; // Length word calculated at run time static const Bit8u bx_device_id_string[] = "\0\0" // len field is calculated at run-time "MFG:HEWLETT-PACKARD;" "MDL:DESKJET 920C;" "CMD:MLC,PCL,PML;" "CLASS:PRINTER;" "DESCRIPTION:Hewlett-Packard DeskJet 920C;" "SERN:CN21R1C0BPIS;" "VSTATUS:$HBO,$NCO,ff,DN,IDLE,CUT,K0,C0,SM,NR,KP093,CP097;" "VP:0800,FL,B0;" "VJ: ;"; usb_printer_device_c::usb_printer_device_c(usbdev_type type, const char *filename) { d.type = type; d.maxspeed = USB_SPEED_FULL; d.speed = d.maxspeed; // TODO: d.max_packet_size = ??? memset((void*)&s, 0, sizeof(s)); strcpy(d.devname, "USB Printer"); s.fname = filename; s.fp = NULL; put("usb_printer", "USBPR"); } usb_printer_device_c::~usb_printer_device_c(void) { if (s.fp != NULL) { fclose(s.fp); } } bx_bool usb_printer_device_c::init() { s.fp = fopen(s.fname, "w+b"); if (s.fp == NULL) { BX_ERROR(("Could not create/open %s", s.fname)); return 0; } else { sprintf(s.info_txt, "USB printer: file=%s", s.fname); d.connected = 1; return 1; } } const char* usb_printer_device_c::get_info() { return s.info_txt; } void usb_printer_device_c::register_state_specific(bx_list_c *parent) { bx_list_c *list = new bx_list_c(parent, "s", "USB PRINTER Device State"); new bx_shadow_num_c(list, "printer_status", &s.printer_status); } void usb_printer_device_c::handle_reset() { BX_INFO(("Opened %s for USB HP Deskjet 920C printer emulation.", s.fname)); BX_DEBUG(("Reset")); } int usb_printer_device_c::handle_control(int request, int value, int index, int length, Bit8u *data) { int ret = 0; BX_DEBUG(("Printer: request: 0x%04X value: 0x%04X index: 0x%04X len: %i", request, value, index, length)); switch(request) { case DeviceRequest | USB_REQ_GET_STATUS: if (d.state == USB_STATE_DEFAULT) goto fail; else { data[0] = (1 << USB_DEVICE_SELF_POWERED) | (d.remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; } break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: d.state = USB_STATE_ADDRESS; d.addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, bx_printer_dev_descriptor, sizeof(bx_printer_dev_descriptor)); ret = sizeof(bx_printer_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, bx_printer_config_descriptor, sizeof(bx_printer_config_descriptor)); ret = sizeof(bx_printer_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* vendor description */ ret = set_usb_string(data, "Hewlett-Packard"); break; case 2: /* product description */ ret = set_usb_string(data, "Deskjet 920C"); break; case 3: /* serial number */ ret = set_usb_string(data, "HU18L6P2DNBI"); break; default: BX_ERROR(("USB Printer handle_control: unknown string descriptor 0x%02x", value & 0xff)); goto fail; } break; default: BX_ERROR(("USB Printer handle_control: unknown descriptor type 0x%02x", value >> 8)); goto fail; } break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: data[0] = 1; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: d.state = USB_STATE_CONFIGURED; ret = 0; break; case DeviceRequest | USB_REQ_GET_INTERFACE: data[0] = 0; ret = 1; break; case EndpointOutRequest | USB_REQ_SET_INTERFACE: ret = 0; break; /* printer specific requests */ case InterfaceInClassRequest | 0x00: // 1284 get device id string memcpy(data, bx_device_id_string, sizeof(bx_device_id_string)); ret = sizeof(bx_device_id_string); data[0] = (Bit8u) (ret >> 8); // len word is big endian data[1] = (Bit8u) (ret & 0xFF); // break; case InterfaceInClassRequest | 0x01: // Get Port Status s.printer_status = (0<<5) | (1<<4) | (1<<3); memcpy(data, &s.printer_status, 1); ret = 1; break; case InterfaceOutClassRequest | 0x02: // soft reset // for now, just return ret = 0; break; default: BX_ERROR(("USB PRINTER handle_control: unknown request 0x%04x", request)); fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } int usb_printer_device_c::handle_data(USBPacket *p) { int ret = 0; switch(p->pid) { case USB_TOKEN_IN: if (p->devep == 1) { BX_INFO(("Printer: handle_data: IN: len = %i", p->len)); BX_INFO(("Printer: Ben: We need to find out what this is and send valid status back")); ret = p->len; } else { goto fail; } break; case USB_TOKEN_OUT: if (p->devep == 2) { BX_DEBUG(("Sent %i bytes to the 'usb printer': %s", p->len, s.fname)); usb_dump_packet(p->data, p->len); fwrite(p->data, 1, p->len, s.fp); ret = p->len; } else { goto fail; } break; default: fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB bochs-2.6/iodev/usb/usb_msd.h0000644000175000017500000000547312020641504016044 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_msd.h 11390 2012-09-02 09:37:47Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // USB mass storage device support (ported from QEMU) // // Copyright (c) 2006 CodeSourcery. // Written by Paul Brook // Copyright (C) 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_USB_MSD_H #define BX_IODEV_USB_MSD_H class device_image_t; class LOWLEVEL_CDROM; class scsi_device_t; class usb_msd_device_c : public usb_device_c { public: usb_msd_device_c(usbdev_type type, const char *filename); virtual ~usb_msd_device_c(void); virtual bx_bool init(); virtual bx_bool set_option(const char *option); virtual const char* get_info(); virtual void handle_reset(); virtual int handle_control(int request, int value, int index, int length, Bit8u *data); virtual int handle_data(USBPacket *p); virtual void register_state_specific(bx_list_c *parent); virtual void cancel_packet(USBPacket *p); void set_inserted(bx_bool value); bx_bool get_inserted(); protected: void copy_data(); void send_status(); static void usb_msd_command_complete(void *this_ptr, int reason, Bit32u tag, Bit32u arg); void command_complete(int reason, Bit32u tag, Bit32u arg); private: struct { Bit8u mode; Bit32u scsi_len; Bit8u *scsi_buf; Bit32u usb_len; Bit8u *usb_buf; Bit32u data_len; Bit32u residue; Bit32u tag; int result; Bit8u image_mode; device_image_t *hdimage; #ifdef LOWLEVEL_CDROM LOWLEVEL_CDROM *cdrom; #endif scsi_device_t *scsi_dev; USBPacket *packet; bx_list_c *sr_list; const char *fname; bx_list_c *config; char info_txt[BX_PATHNAME_LEN]; char journal[BX_PATHNAME_LEN]; } s; static const char *cd_param_string_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen); static Bit64s cd_param_handler(bx_param_c *param, int set, Bit64s val); }; #endif bochs-2.6/iodev/usb/usb_xhci.h0000644000175000017500000006050112020641504016205 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_xhci.h 10972 2012-01-14 12:36:32Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2010 Benjamin D Lunt (fys [at] fysnet [dot] net) // 2011-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_USB_XHCI_H #define BX_IODEV_USB_XHCI_H #if BX_USE_USB_XHCI_SMF # define BX_XHCI_THIS theUSB_XHCI-> # define BX_XHCI_THIS_PTR theUSB_XHCI #else # define BX_XHCI_THIS this-> # define BX_XHCI_THIS_PTR this #endif // If in 64bit mode, print 64bits, else only print 32 bit addresses #if BX_PHY_ADDRESS_LONG #define FORMATADDRESS FMT_ADDRX64 #else #define FORMATADDRESS "%08x" #endif /************************************************************************************************ * Actual configuration of the card */ #define IO_SPACE_SIZE 8192 #define OPS_REGS_OFFSET 0x20 // Change this to 0.95, 0.96, or 1.00, according to the desired effects (LINK chain bit, etc) #define VERSION_MAJOR 0 #define VERSION_MINOR 0x96 // HCSPARAMS1 #define INTERRUPTERS 8 #define MAX_SLOTS 32 // (1 based) #define USB_XHCI_PORTS 4 // 2 physical sockets, each supporting USB3 or USB2 // HCSPARAMS2 #define ISO_SECH_THRESHOLD 1 #define MAX_SEG_TBL_SZ_EXP 1 #define SCATCH_PAD_RESTORE 0 // 1 = uses system memory and must be maintained. 0 = uses controller's internal memory #define MAX_SCRATCH_PADS 0 // 0 to 1023 // HCSPARAMS3 #define U1_DEVICE_EXIT_LAT 0 #define U2_DEVICE_EXIT_LAT 0 // HCCPARAMS #define ADDR_CAP_64 1 #define BW_NEGOTIATION 1 #define CONTEXT_SIZE 32 // Size of the CONTEXT blocks (32 or 64) #define PORT_POWER_CTRL 1 #define PORT_INDICATORS 0 #define LIGHT_HC_RESET 0 // Do we support the Light HC Reset function #define FORCED_STOPPED 0 // version 0.96 and below only (MUST BE 1 in v1.00+) #define SEC_DOMAIN_BAND 1 // version 0.96 and below only (MUST BE 1 in v1.00+) #define MAX_PSA_SIZE 0x04 #define EXT_CAPS_OFFSET 0x500 #define EXT_CAPS_SIZE 48 #define PAGE_SIZE 1 // Page size operational register value #define PORT_SET_OFFSET (0x400 + OPS_REGS_OFFSET) #define RUNTIME_OFFSET 0x600 #define DOORBELL_OFFSET 0x800 /************************************************************************************************/ #if (((VERSION_MAJOR == 0) && ((VERSION_MINOR != 0x95) && (VERSION_MINOR != 0x96))) || ((VERSION_MAJOR == 1) && (VERSION_MINOR != 0x00))) # error "Unknown Controller Version number specified." #endif #if (MAX_SCRATCH_PADS > 1023) # error "MAX_SCRATCH_PADS must be 0 to 1023." #endif #if (SCATCH_PAD_RESTORE && (MAX_SCRATCH_PADS == 0)) # error "Must specify amount of scratch pad buffers to use." #endif #if ((MAX_SCRATCH_PADS > 0) && !SCATCH_PAD_RESTORE) # error "Must set SCATCH_PAD_RESTORE to 1 if MAX_SCRATCH_PADS > 0" #endif #if ((FORCED_STOPPED == 0) && (VERSION_MAJOR > 0)) # error "FORCED_STOPPED must be 1 in version 1.0 and above" #endif #if ((SEC_DOMAIN_BAND == 0) && (VERSION_MAJOR > 0)) # error "SEC_DOMAIN_BAND must be 1 in version 1.0 and above" #endif // Each controller supports its own number of ports. We must adhere to that for now. // (The Extended Capabilities register set is hardcoded for this as of now.) // As long as BX_N_USB_XHCI_PORTS was defined as greater than what we have now, then // we are fine. // Note: BX_N_USB_XHCI_PORTS should have been defined as twice the amount of ports wanted. // ie.: Each physical port (socket) has two defined port register sets. One for USB3, one for USB2 // Only one port type may be used at a time. Port0 or Port1, not both. If Port0 is used, then // Port1 must be vacant. #ifndef BX_N_USB_XHCI_PORTS #error "BX_N_USB_XHCI_PORTS was not defined in bochs.h" #else #if (BX_N_USB_XHCI_PORTS < USB_XHCI_PORTS) #error "BX_N_USB_XHCI_PORTS is less than USB_XHCI_PORTS." #endif #endif // xHCI speed values #define SPEED_FULL 1 #define SPEED_LOW 2 #define SPEED_HI 3 #define SPEED_SUPER 4 #define USB2 0 #define USB3 1 // our saved ring members struct RING_MEMBERS { struct { Bit64u dq_pointer; bx_bool rcs; } command_ring; struct { bx_bool rcs; unsigned trb_count; unsigned count; Bit64u cur_trb; struct { Bit64u addr; Bit32u size; Bit32u resv; } entrys[(1<> 8) #define NEC_FW_MINOR(v) (((v) & 0x000000FF) >> 0) #define TRB_GET_STYPE(x) (((x) & (0x1F << 16)) >> 16) #define TRB_SET_STYPE(x) (((x) & 0x1F) << 16) #define TRB_GET_TYPE(x) (((x) & (0x3F << 10)) >> 10) #define TRB_SET_TYPE(x) (((x) & 0x3F) << 10) #define TRB_GET_COMP_CODE(x) (((x) & (0xFF << 24)) >> 24) #define TRB_SET_COMP_CODE(x) (((x) & 0xFF) << 24) #define TRB_GET_SLOT(x) (((x) & (0xFF << 24)) >> 24) #define TRB_SET_SLOT(x) (((x) & 0xFF) << 24) #define TRB_GET_TDSIZE(x) (((x) & (0x1F << 17)) >> 17) #define TRB_SET_TDSIZE(x) (((x) & 0x1F) << 17) #define TRB_GET_EP(x) (((x) & (0x1F << 16)) >> 16) #define TRB_SET_EP(x) (((x) & 0x1F) << 16) #define TRB_GET_TARGET(x) (((x) & (0x3FF << 22)) >> 22) #define TRB_GET_TX_LEN(x) ((x) & 0x1FFFF) #define TRB_GET_TOGGLE(x) (((x) & (1<<1)) >> 1) #define TRB_DC(x) (((x) & (1<<9)) >> 9) #define TRB_IS_IMMED_DATA(x) (((x) & (1<<6)) >> 6) #define TRB_IOC(x) (((x) & (1<<5)) >> 5) #define TRB_CHAIN(x) (((x) & (1<<4)) >> 4) #define TRB_SPD(x) (((x) & (1<<2)) >> 2) #define TRB_TOGGLE(x) (((x) & (1<<1)) >> 1) #define TRB_TX_TYPE(x) (((x) == 2) ? USB_TOKEN_OUT : USB_TOKEN_IN) #define TRB_GET_DIR(x) (((x) & (1<<16)) ? USB_TOKEN_IN : USB_TOKEN_OUT) struct TRB { Bit64u parameter; Bit32u status; Bit32u command; }; typedef struct { struct XHCI_CAP_REGS { Bit32u HcCapLength; Bit32u HcSParams1; Bit32u HcSParams2; Bit32u HcSParams3; Bit32u HcCParams; Bit32u DBOFF; Bit32u RTSOFF; } cap_regs; struct XHCI_OP_REGS { struct { Bit32u RsvdP1; // 20 bit reserved and preserved = 0x000000 RW bx_bool eu3s; // 1 bit Enable U3 MFINDEX Stop = 0b RW bx_bool ewe; // 1 bit Enable Wrap Event = 0b RW bx_bool crs; // 1 bit Controller Restore State = 0b RW bx_bool css; // 1 bit Controller Save State = 0b RW bx_bool lhcrst; // 1 bit Light HC Reset = 0b RW or RO (HCCPARAMS:LHRC) Bit8u RsvdP0; // 1 bit reserved and preserved = 000b RW bx_bool hsee; // 1 bit Host System Error Enable = 0b RW bx_bool inte; // 1 bit Interrupter Enable = 0b RW bx_bool hcrst; // 1 bit HC Reset = 0b RW bx_bool rs; // 1 bit Run Stop = 0b RW } HcCommand; // = 0x00000000 struct { Bit32u RsvdZ1; // 19 bit reserved and zero'd = 0x000000 RW bx_bool hce; // 1 bit Host Controller Error = 0b RO bx_bool cnr; // 1 bit Controller Not Ready = 0b R0 bx_bool sre; // 1 bit Save/Restore Error = 0b RW1C bx_bool rss; // 1 bit Restore State Status = 0b RO bx_bool sss; // 1 bit Save State Status = 0b RO Bit8u RsvdZ0; // 3 bit reserved and zero'd = 0x0 RW bx_bool pcd; // 1 bit Port Change Detect = 0b RW1C bx_bool eint; // 1 bit Event Interrupt = 0b RW1C bx_bool hse; // 1 bit Host System Error = 0b RW1C bx_bool RsvdZ2; // 1 bit reserved and zero'd = 0b RW bx_bool hch; // 1 bit HCHalted = 1b RO } HcStatus; // = 0x00000001 struct { Bit16u Rsvd; // 16 bit reserved = 0x0000 RO Bit16u pagesize; // 16 bit reserved = 0x0001 RO } HcPageSize; // = 0x00000001 struct { Bit16u RsvdP; // 16 bit reserved and presserved = 0x0000 RW bx_bool n15; // 1 bit N15 = 0 RW bx_bool n14; // 1 bit N14 = 0 RW bx_bool n13; // 1 bit N13 = 0 RW bx_bool n12; // 1 bit N12 = 0 RW bx_bool n11; // 1 bit N11 = 0 RW bx_bool n10; // 1 bit N10 = 0 RW bx_bool n9; // 1 bit N9 = 0 RW bx_bool n8; // 1 bit N8 = 0 RW bx_bool n7; // 1 bit N7 = 0 RW bx_bool n6; // 1 bit N6 = 0 RW bx_bool n5; // 1 bit N5 = 0 RW bx_bool n4; // 1 bit N4 = 0 RW bx_bool n3; // 1 bit N3 = 0 RW bx_bool n2; // 1 bit N2 = 0 RW bx_bool n1; // 1 bit N1 = 0 RW bx_bool n0; // 1 bit N0 = 0 RW } HcNotification; // = 0x00000000 struct { Bit64u crc; // 64 bit hi order address = 0x00000000 RW Bit8u RsvdP; // 2 bit reserved and preserved = 00b RW bx_bool crr; // 1 bit Command Ring Running = 0 RO bx_bool ca; // 1 bit Command Abort = 0 RW1S bx_bool cs; // 1 bit Command Stop = 0 RW1S bx_bool rcs; // 1 bit Ring Cycle State = 0 RW } HcCrcr; struct { Bit64u dcbaap; // 64 bit hi order address = 0x00000000 RW Bit8u RsvdZ; // 6 bit reserved and zero'd = 000000b RW } HcDCBAAP; struct { Bit32u RsvdP; // 24 bit reserved and preserved = 0x000000 RW Bit8u MaxSlotsEn; // 8 bit Max Device Slots Enabled = 0x00 RW } HcConfig; } op_regs; struct { // our data usb_device_c *device; // device connected to this port bx_bool is_usb3; // set if usb3 port, cleared if usb2 port. struct { bx_bool wpr; // 1 bit Warm Port Reset = 0b RW or RsvdZ bx_bool dr; // 1 bit Device Removable = 0b RO Bit8u RsvdZ1; // 2 bit Reserved and Zero'd = 00b RW bx_bool woe; // 1 bit Wake on Over Current Enable = 0b RW bx_bool wde; // 1 bit Wake on Disconnect Enable = 0b RW bx_bool wce; // 1 bit Wake on Connect Enable = 0b RW bx_bool cas; // 1 bit Cold Attach Status = 0b RO bx_bool cec; // 1 bit Port Config Error Change = 0b RW1C or RsvdZ bx_bool plc; // 1 bit Port Link State Change = 0b RW1C bx_bool prc; // 1 bit Port Reset Change = 0b RW1C bx_bool occ; // 1 bit Over Current Change = 0b RW1C bx_bool wrc; // 1 bit Warm Port Reset Change = 0b RW1C or RsvdZ bx_bool pec; // 1 bit Port Enabled/Disabled Change= 0b RW1C bx_bool csc; // 1 bit Connect Status Change = 0b RW1C bx_bool lws; // 1 bit Port Link State Write Strobe= 0b RW Bit8u pic; // 2 bit Port Indicator Control = 00b RW bx_bool speed; // 1 bit Port Speed = 0b RO bx_bool pp; // 1 bit Port Power = 0b RW Bit8u pls; // 4 bit Port Link State = 0x00 RW bx_bool pr; // 1 bit Port Reset = 0b RW bx_bool oca; // 1 bit Over Current Active = 0b RO bx_bool RsvdZ0; // 1 bit Reserved and Zero'd = 0b RW bx_bool ped; // 1 bit Port Enabled/Disabled = 0b RW1C bx_bool ccs; // 1 bit Current Connect Status = 0b RO } portsc; union { // if usb3 port struct { struct { Bit16u RsvdP; // 15 bit Reserved and Preserved = 0x0000 RW bx_bool fla; // 1 bit Force Link PM Accept = 0x0000 RW Bit8u u2timeout; // 8 bit U2 Timeout = 0x0000 RW Bit8u u1timeout; // 8 bit U1 Timeout = 0x0000 RW } portpmsc; struct { Bit16u RsvdP; // 16 bit Reserved and Preserved = 0x0000 RW Bit16u lec; // 16 bit Link Error Count = 0x0000 RO } portli; } usb3; // if usb2 port struct { struct { Bit8u tmode; // 4 bit Test Mode = 0x0 RO Bit16u RsvdP; // 11 bit reserved and preseved = 0x000 RW bx_bool hle; // 1 bit hardware LPM enable = 0b RW Bit8u l1dslot; // 8 bit L1 Device Slot = 0x00 RW Bit8u hird; // 4 bit Host Initiated Resume Durat = 0x0 RW bx_bool rwe; // 1 bit Remote Wakeup Enable = 0b RW Bit8u l1s; // 3 bit L1 Status = 000b RO } portpmsc; struct { Bit32u RsvdP; // 32 bit reserved and preseved = 0x00000000 RW } portli; } usb2; }; struct { Bit8u hirdm; // 2 bit host initiated resume duration mode Bit8u l1timeout; // 8 bit L1 timeout Bit8u hirdd; // 4 bit host initiated resume duration deep Bit32u RsvdP; // 18 bit reserved and preseved = 0x00000000 RW } porthlpmc; } usb_port[USB_XHCI_PORTS]; // Extended Caps Registers Bit8u extended_caps[EXT_CAPS_SIZE]; struct XHCI_RUNTIME_REGS { struct { Bit32u RsvdP; // 18 bit reserved and preseved = 0x00000 RW Bit16u index; // 14 bit index = 0x0000 RO } mfindex; struct { struct { Bit32u RsvdP; // 30 bit reserved and preseved = 0x00000000 RW bx_bool ie; // 1 bit Interrupt Enable = 0b RW bx_bool ip; // 1 bit Interrupt Pending = 0b RW1C } iman; struct { Bit16u imodc; // 16 bit Interrupter Mod Counter = 0x0000 RW Bit16u imodi; // 16 bit Interrupter Mod Interval = 0x0000 RW } imod; struct { Bit16u RsvdP; // 16 bit reserved and preseved = 0x0000 RW Bit16u erstabsize; // 16 bit Event Ring Seg Table Size = 0x0000 RW } erstsz; Bit32u RsvdP; // 32 bit reserved and preseved = 0x00000000 RW struct { Bit64u erstabadd; // 64 bit Event Ring Seg Tab Addy = 0x00000000 RW Bit16u RsvdP; // 6 bit reserved and preseved = 0x0000 RW } erstba; struct { Bit64u eventadd; // 64 bit Event Ring Addy hi = 0x00000000 RW bx_bool ehb; // 1 bit Event Handler Busy = 0b RW1C Bit8u desi; // 2 bit Dequeue ERST Seg Index = 00b RW } erdp; } interrupter[INTERRUPTERS]; } runtime_regs; struct HC_SLOT_CONTEXT slots[MAX_SLOTS]; // first one is ignored by controller. struct RING_MEMBERS ring_members; Bit8u devfunc; int statusbar_id; // ID of the status LEDs Bit8u device_change; } bx_usb_xhci_t; class bx_usb_xhci_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: bx_usb_xhci_c(); virtual ~bx_usb_xhci_c(); virtual void init(void); virtual void reset(unsigned); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); static const char *usb_param_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen); private: bx_usb_xhci_t hub; Bit8u *device_buffer; static void reset_hc(); static void reset_port(int); static bx_bool save_hc_state(void); static bx_bool restore_hc_state(void); static void update_irq(unsigned interrupter); static void init_device(Bit8u port, bx_list_c *portconf); static void remove_device(Bit8u port); static void usb_set_connect_status(Bit8u port, int type, bx_bool connected); static int broadcast_packet(USBPacket *p, const int port); //static void usb_frame_handler(void *); //void usb_frame_timer(void); static void process_transfer_ring(const int slot, const int ep); static void process_command_ring(void); static void write_event_TRB(const unsigned interrupter, const Bit64u parameter, const Bit32u status, const Bit32u command, const bx_bool fire_int); static Bit32u NEC_verification(const Bit64u parameter); static void init_event_ring(const unsigned interrupter); static void read_TRB(bx_phy_address addr, struct TRB *trb); static void write_TRB(bx_phy_address addr, const Bit64u parameter, const Bit32u status, const Bit32u command); static void update_slot_context(const int slot); static void update_ep_context(const int slot, const int ep); static void dump_slot_context(const Bit32u *context, const int slot); static void dump_ep_context(const Bit32u *context, const int slot, const int ep); static void copy_slot_from_buffer(struct SLOT_CONTEXT *slot_context, const Bit8u *buffer); static void copy_ep_from_buffer(struct EP_CONTEXT *ep_context, const Bit8u *buffer); static void copy_slot_to_buffer(const Bit8u *buffer, const int slot); static void copy_ep_to_buffer(const Bit8u *buffer, const int slot, const int ep); static bx_bool validate_slot_context(const struct SLOT_CONTEXT *slot_context); static bx_bool validate_ep_context(const struct EP_CONTEXT *ep_context, int speed, int ep_num); static int create_unique_address(const int slot); static int send_set_address(const int addr, const int port_num); static void dump_xhci_core(const int slots, const int eps); #if BX_USE_USB_XHCI_SMF static bx_bool read_handler(bx_phy_address addr, unsigned len, void *data, void *param); static bx_bool write_handler(bx_phy_address addr, unsigned len, void *data, void *param); #else bx_bool read_handler(bx_phy_address addr, unsigned len, void *data, void *param); bx_bool write_handler(bx_phy_address addr, unsigned len, void *data, void *param); #endif static void runtime_config_handler(void *); void runtime_config(void); }; #endif // BX_IODEV_USB_XHCI_H bochs-2.6/iodev/usb/usb_common.cc0000644000175000017500000003052312020641504016701 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_common.cc 11390 2012-09-02 09:37:47Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Generic USB emulation code // // Copyright (c) 2005 Fabrice Bellard // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB #include "usb_common.h" #include "usb_hid.h" #include "usb_hub.h" #include "usb_msd.h" #include "usb_printer.h" #define LOG_THIS bx_usb_devctl_c* theUsbDevCtl = NULL; int libusb_common_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { if (type == PLUGTYPE_CORE) { theUsbDevCtl = new bx_usb_devctl_c; bx_devices.pluginUsbDevCtl = theUsbDevCtl; return 0; // Success } else { return -1; } } void libusb_common_LTX_plugin_fini(void) { delete theUsbDevCtl; } int bx_usb_devctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void **dev, bx_list_c *sr_list) { usbdev_type type = USB_DEV_TYPE_NONE; int ports; usb_device_c **device = (usb_device_c**)dev; const char *devname = NULL; devname = ((bx_param_string_c*)portconf->get_by_name("device"))->getptr(); if (!strcmp(devname, "mouse")) { type = USB_DEV_TYPE_MOUSE; *device = new usb_hid_device_c(type); } else if (!strcmp(devname, "tablet")) { type = USB_DEV_TYPE_TABLET; *device = new usb_hid_device_c(type); } else if (!strcmp(devname, "keypad")) { type = USB_DEV_TYPE_KEYPAD; *device = new usb_hid_device_c(type); } else if (!strncmp(devname, "disk", 4)) { if ((strlen(devname) > 5) && (devname[4] == ':')) { type = USB_DEV_TYPE_DISK; *device = new usb_msd_device_c(type, devname+5); } else { hub->panic("USB device 'disk' needs a filename separated with a colon"); return type; } } else if (!strncmp(devname, "cdrom", 5)) { if ((strlen(devname) > 6) && (devname[5] == ':')) { type = USB_DEV_TYPE_CDROM; *device = new usb_msd_device_c(type, devname+6); } else { hub->panic("USB device 'cdrom' needs a filename separated with a colon"); return type; } } else if (!strncmp(devname, "hub", 3)) { type = USB_DEV_TYPE_HUB; ports = 4; if (strlen(devname) > 3) { if (devname[3] == ':') { ports = atoi(&devname[4]); if ((ports < 2) || (ports > BX_N_USB_HUB_PORTS)) { hub->panic("USB device 'hub': invalid number of ports"); } } else { hub->panic("USB device 'hub' needs the port count separated with a colon"); } } *device = new usb_hub_device_c(ports); } else if (!strncmp(devname, "printer", 7)) { if ((strlen(devname) > 8) && (devname[7] == ':')) { type = USB_DEV_TYPE_PRINTER; *device = new usb_printer_device_c(type, devname+8); } else { hub->panic("USB device 'printer' needs a filename separated with a colon"); return type; } } else { hub->panic("unknown USB device: %s", devname); return type; } if (*device != NULL) { (*device)->register_state(sr_list); parse_port_options(*device, portconf); } return type; } void bx_usb_devctl_c::parse_port_options(usb_device_c *device, bx_list_c *portconf) { const char *raw_options; char *options; unsigned i, string_i; int optc, speed = USB_SPEED_LOW; char *opts[16]; char *ptr; char string[512]; size_t len; memset(opts, 0, sizeof(opts)); optc = 0; raw_options = ((bx_param_string_c*)portconf->get_by_name("options"))->getptr(); len = strlen(raw_options); if (len > 0) { options = new char[len + 1]; strcpy(options, raw_options); ptr = strtok(options, ","); while (ptr) { string_i = 0; for (i=0; iget_maxspeed()) { device->set_speed(speed); } else { BX_ERROR(("unsupported USB device speed: '%s'", opts[i]+6)); } } else if (!device->set_option(opts[i])) { BX_ERROR(("unknown USB device option: '%s'", opts[i])); } } for (i = 1; i < (unsigned)optc; i++) { if (opts[i] != NULL) { free(opts[i]); opts[i] = NULL; } } } void bx_usb_devctl_c::usb_send_msg(void *dev, int msg) { ((usb_device_c*)dev)->usb_send_msg(msg); } // Dumps the contents of a buffer to the log file void usb_device_c::usb_dump_packet(Bit8u *data, unsigned size) { char the_packet[256], str[16]; strcpy(the_packet, "Packet contents (in hex):"); unsigned offset = 0; for (unsigned p=0; p 32) { *q = 0; return 0; } *q++ = 2 * len + 2; *q++ = 3; for(i = 0; i < len; i++) { *q++ = str[i]; *q++ = 0; } return q - buf; } // generic USB packet handler #define SETUP_STATE_IDLE 0 #define SETUP_STATE_DATA 1 #define SETUP_STATE_ACK 2 int usb_device_c::handle_packet(USBPacket *p) { int l, ret = 0; int len = p->len; Bit8u *data = p->data; switch(p->pid) { case USB_MSG_ATTACH: d.state = USB_STATE_ATTACHED; break; case USB_MSG_DETACH: d.state = USB_STATE_NOTATTACHED; break; case USB_MSG_RESET: d.remote_wakeup = 0; d.addr = 0; d.state = USB_STATE_DEFAULT; handle_reset(); break; case USB_TOKEN_SETUP: if (d.state < USB_STATE_DEFAULT || p->devaddr != d.addr) return USB_RET_NODEV; if (len != 8) goto fail; d.stall = 0; memcpy(d.setup_buf, data, 8); d.setup_len = (d.setup_buf[7] << 8) | d.setup_buf[6]; d.setup_index = 0; if (d.setup_buf[0] & USB_DIR_IN) { ret = handle_control((d.setup_buf[0] << 8) | d.setup_buf[1], (d.setup_buf[3] << 8) | d.setup_buf[2], (d.setup_buf[5] << 8) | d.setup_buf[4], d.setup_len, d.data_buf); if (ret < 0) return ret; if (ret < d.setup_len) d.setup_len = ret; d.setup_state = SETUP_STATE_DATA; } else { if (d.setup_len == 0) d.setup_state = SETUP_STATE_ACK; else d.setup_state = SETUP_STATE_DATA; } break; case USB_TOKEN_IN: if (d.state < USB_STATE_DEFAULT || p->devaddr != d.addr) return USB_RET_NODEV; if (d.stall) goto fail; switch(p->devep) { case 0: switch(d.setup_state) { case SETUP_STATE_ACK: if (!(d.setup_buf[0] & USB_DIR_IN)) { d.setup_state = SETUP_STATE_IDLE; ret = handle_control((d.setup_buf[0] << 8) | d.setup_buf[1], (d.setup_buf[3] << 8) | d.setup_buf[2], (d.setup_buf[5] << 8) | d.setup_buf[4], d.setup_len, d.data_buf); if (ret > 0) ret = 0; } else { // return 0 byte } break; case SETUP_STATE_DATA: if (d.setup_buf[0] & USB_DIR_IN) { l = d.setup_len - d.setup_index; if (l > len) l = len; memcpy(data, d.data_buf + d.setup_index, l); d.setup_index += l; if (d.setup_index >= d.setup_len) d.setup_state = SETUP_STATE_ACK; ret = l; } else { d.setup_state = SETUP_STATE_IDLE; goto fail; } break; default: goto fail; } break; default: ret = handle_data(p); break; } break; case USB_TOKEN_OUT: if (d.state < USB_STATE_DEFAULT || p->devaddr != d.addr) return USB_RET_NODEV; if (d.stall) goto fail; switch(p->devep) { case 0: switch(d.setup_state) { case SETUP_STATE_ACK: if (d.setup_buf[0] & USB_DIR_IN) { d.setup_state = SETUP_STATE_IDLE; // transfer OK } else { // ignore additionnal output } break; case SETUP_STATE_DATA: if (!(d.setup_buf[0] & USB_DIR_IN)) { l = d.setup_len - d.setup_index; if (l > len) l = len; memcpy(d.data_buf + d.setup_index, data, l); d.setup_index += l; if (d.setup_index >= d.setup_len) d.setup_state = SETUP_STATE_ACK; ret = l; } else { // it is okay for a host to send an OUT before it reads // all of the expected IN. It is telling the controller // that it doesn't want any more from that particular call. ret = 0; d.setup_state = SETUP_STATE_IDLE; } break; default: goto fail; } break; default: ret = handle_data(p); break; } break; default: fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } void usb_device_c::register_state(bx_list_c *parent) { bx_list_c *list = new bx_list_c(parent, "d", "Common USB Device State"); new bx_shadow_num_c(list, "addr", &d.addr); new bx_shadow_num_c(list, "state", &d.state); new bx_shadow_num_c(list, "remote_wakeup", &d.remote_wakeup); register_state_specific(parent); } // base class for USB devices usb_device_c::usb_device_c(void) { memset((void*)&d, 0, sizeof(d)); } // Send an internal message to a USB device void usb_device_c::usb_send_msg(int msg) { USBPacket p; memset(&p, 0, sizeof(p)); p.pid = msg; handle_packet(&p); } #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB bochs-2.6/iodev/usb/scsi_device.h0000644000175000017500000000647712020641504016675 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: scsi_device.h 11382 2012-08-30 20:41:25Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // SCSI emulation layer (ported from QEMU) // // Copyright (C) 2006 CodeSourcery. // Based on code by Fabrice Bellard // // Written by Paul Brook // // Copyright (C) 2007-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_SCSI_DEVICE_H #define BX_IODEV_SCSI_DEVICE_H typedef void (*scsi_completionfn)(void *opaque, int reason, Bit32u tag, Bit32u arg); class scsi_device_t; class LOWLEVEL_CDROM; enum scsidev_type { SCSIDEV_TYPE_DISK, SCSIDEV_TYPE_CDROM }; enum scsi_reason { SCSI_REASON_DONE, SCSI_REASON_DATA }; #define SENSE_NO_SENSE 0 #define SENSE_NOT_READY 2 #define SENSE_HARDWARE_ERROR 4 #define SENSE_ILLEGAL_REQUEST 5 #define STATUS_GOOD 0 #define STATUS_CHECK_CONDITION 2 #define SCSI_DMA_BUF_SIZE 131072 #define SCSI_MAX_INQUIRY_LEN 256 typedef struct SCSIRequest { scsi_device_t *dev; Bit32u tag; Bit64u sector; Bit32u sector_count; int buf_len; Bit8u dma_buf[SCSI_DMA_BUF_SIZE]; Bit32u status; struct SCSIRequest *next; } SCSIRequest; class scsi_device_t : public logfunctions { public: scsi_device_t(device_image_t *_hdimage, int _tcq, scsi_completionfn _completion, void *_dev); #ifdef LOWLEVEL_CDROM scsi_device_t(LOWLEVEL_CDROM *_cdrom, int _tcq, scsi_completionfn _completion, void *_dev); #endif virtual ~scsi_device_t(void); void register_state(bx_list_c *parent, const char *name); Bit32s scsi_send_command(Bit32u tag, Bit8u *buf, int lun); void scsi_command_complete(SCSIRequest *r, int status, int sense); void scsi_cancel_io(Bit32u tag); void scsi_read_complete(void *req, int ret); void scsi_read_data(Bit32u tag); void scsi_write_complete(void *req, int ret); int scsi_write_data(Bit32u tag); Bit8u* scsi_get_buf(Bit32u tag); const char *get_serial_number() {return drive_serial_str;} void set_inserted(bx_bool value) {inserted = value;} bx_bool get_inserted() {return inserted;} protected: SCSIRequest* scsi_new_request(Bit32u tag); void scsi_remove_request(SCSIRequest *r); SCSIRequest *scsi_find_request(Bit32u tag); private: enum scsidev_type type; device_image_t *hdimage; #ifdef LOWLEVEL_CDROM LOWLEVEL_CDROM *cdrom; #endif SCSIRequest *requests; int cluster_size; Bit64u max_lba; int sense; int tcq; scsi_completionfn completion; void *dev; bx_bool locked; bx_bool inserted; char drive_serial_str[21]; }; #endif bochs-2.6/iodev/usb/usb_ohci.h0000644000175000017500000003251012020641504016173 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_ohci.h 10972 2012-01-14 12:36:32Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_USB_OHCI_H #define BX_IODEV_USB_OHCI_H #if BX_USE_USB_OHCI_SMF # define BX_OHCI_THIS theUSB_OHCI-> # define BX_OHCI_THIS_PTR theUSB_OHCI #else # define BX_OHCI_THIS this-> # define BX_OHCI_THIS_PTR this #endif // number of ports defined in bochs.h #define OHCI_INTR_SO (1<<0) // Scheduling overrun #define OHCI_INTR_WD (1<<1) // HcDoneHead writeback #define OHCI_INTR_SF (1<<2) // Start of frame #define OHCI_INTR_RD (1<<3) // Resume detect #define OHCI_INTR_UE (1<<4) // Unrecoverable error #define OHCI_INTR_FNO (1<<5) // Frame number overflow #define OHCI_INTR_RHSC (1<<6) // Root hub status change #define OHCI_INTR_OC (1<<30) // Ownership change #define OHCI_INTR_MIE (1<<31) // Master Interrupt Enable // Completion Codes enum { NoError = 0, CRC, BitStuffing, DataToggleMismatch, Stall, DeviceNotResponding, PIDCheckFailure, UnexpectedPID, DataOverrun, DataUnderrun, BufferOverrun = 0xC, BufferUnderrun, NotAccessed }; #define ED_GET_MPS(x) (((x)->dword0 & 0x07FF0000) >> 16) #define ED_GET_F(x) (((x)->dword0 & 0x00008000) >> 15) #define ED_GET_K(x) (((x)->dword0 & 0x00004000) >> 14) #define ED_GET_S(x) (((x)->dword0 & 0x00002000) >> 13) #define ED_GET_D(x) (((x)->dword0 & 0x00001800) >> 11) #define ED_GET_EN(x) (((x)->dword0 & 0x00000780) >> 7) #define ED_GET_FA(x) (((x)->dword0 & 0x0000007F) >> 0) #define ED_GET_TAILP(x) ((x)->dword1 & 0xFFFFFFF0) #define ED_GET_HEADP(x) ((x)->dword2 & 0xFFFFFFF0) #define ED_SET_HEADP(x, y) ((x)->dword2 = ((x)->dword2 & 0x0000000F) | ((y) & 0xFFFFFFF0)) #define ED_GET_C(x) (((x)->dword2 & 0x00000002) >> 1) #define ED_SET_C(x,y) ((x)->dword2 = ((x)->dword2 & ~0x00000002) | ((y)<<1)) #define ED_GET_H(x) (((x)->dword2 & 0x00000001) >> 0) #define ED_SET_H(x,y) ((x)->dword2 = ((x)->dword2 & ~0x00000001) | ((y)<<0)) #define ED_GET_NEXTED(x) ((x)->dword3 & 0xFFFFFFF0) struct OHCI_ED { Bit32u dword0; Bit32u dword1; Bit32u dword2; Bit32u dword3; }; #define TD_GET_R(x) (((x)->dword0 & 0x00040000) >> 18) #define TD_GET_DP(x) (((x)->dword0 & 0x00180000) >> 19) #define TD_GET_DI(x) (((x)->dword0 & 0x00E00000) >> 21) #define TD_GET_T(x) (((x)->dword0 & 0x03000000) >> 24) #define TD_SET_T(x,y) ((x)->dword0 = ((x)->dword0 & ~0x03000000) | ((y)<<24)) #define TD_GET_EC(x) (((x)->dword0 & 0x0C000000) >> 26) #define TD_SET_EC(x,y) ((x)->dword0 = ((x)->dword0 & ~0x0C000000) | ((y)<<26)) #define TD_GET_CC(x) (((x)->dword0 & 0xF0000000) >> 28) #define TD_SET_CC(x,y) ((x)->dword0 = ((x)->dword0 & ~0xF0000000) | ((y)<<28)) #define TD_GET_CBP(x) ((x)->dword1) #define TD_SET_CBP(x,y) ((x)->dword1 = y) #define TD_GET_NEXTTD(x) ((x)->dword2 & 0xFFFFFFF0) #define TD_SET_NEXTTD(x,y) ((x)->dword2 = (y & 0xFFFFFFF0)) #define TD_GET_BE(x) ((x)->dword3) struct OHCI_TD { Bit32u dword0; Bit32u dword1; Bit32u dword2; Bit32u dword3; }; #define ISO_TD_GET_CC(x) (((x)->dword0 & 0xF0000000) >> 28) #define ISO_TD_GET_FC(x) (((x)->dword0 & 0x0F000000) >> 24) #define ISO_TD_GET_DI(x) (((x)->dword0 & 0x00E00000) >> 21) #define ISO_TD_GET_SF(x) ((x)->dword0 & 0x0000FFFF) #define ISO_TD_GET_BP0(x) (((x)->dword1 & 0xFFFFF000) >> 12) #define ISO_TD_GET_NEXTTD(x) ((x)->dword2 & 0xFFFFFFF0) #define ISO_TD_GET_BE(x) ((x)->dword3) #define ISO_TD_GET_PSW0(x) ((x)->dword4 & 0x0000FFFF) #define ISO_TD_GET_PSW1(x) (((x)->dword4 & 0xFFFF0000) >> 16) #define ISO_TD_GET_PSW2(x) ((x)->dword5 & 0x0000FFFF) #define ISO_TD_GET_PSW3(x) (((x)->dword5 & 0xFFFF0000) >> 16) #define ISO_TD_GET_PSW4(x) ((x)->dword6 & 0x0000FFFF) #define ISO_TD_GET_PSW5(x) (((x)->dword6 & 0xFFFF0000) >> 16) #define ISO_TD_GET_PSW6(x) ((x)->dword7 & 0x0000FFFF) #define ISO_TD_GET_PSW7(x) (((x)->dword7 & 0xFFFF0000) >> 16) struct OHCI_ISO_TD { Bit32u dword0; Bit32u dword1; Bit32u dword2; Bit32u dword3; Bit32u dword4; Bit32u dword5; Bit32u dword6; Bit32u dword7; }; typedef struct { int frame_timer_index; struct OHCI_OP_REGS { Bit16u HcRevision; struct { Bit32u reserved; // 21 bit reserved = 0x000000 R R bx_bool rwe; // 1 bit RemoteWakeupEnable = 0b RW R bx_bool rwc; // 1 bit RemoteWakeupConnected = 0b RW RW bx_bool ir; // 1 bit InterruptRouting = 0b RW R Bit8u hcfs; // 2 bit HostControllerFuncState = 00b RW RW bx_bool ble; // 1 bit BulkListEnable = 0b RW R bx_bool cle; // 1 bit ControlListEnable = 0b RW R bx_bool ie; // 1 bit IsochronousEnable = 0b RW R bx_bool ple; // 1 bit PeriodicListEnable = 0b RW R Bit8u cbsr; // 2 bit ControlBulkService Ratio = 00b RW R } HcControl; // = 0x00000000 struct { Bit16u reserved0; // 14 bit reserved = 0x000000 R R Bit8u soc; // 2 bit SchedulingOverrunCount = 00b R RW Bit16u reserved1; // 12 bit reserved = 0x000000 R R bx_bool ocr; // 1 bit OwnershipChangeRequest = 0b RW RW bx_bool blf; // 1 bit BulkListFilled = 0b RW RW bx_bool clf; // 1 bit ControlListFilled = 0b RW RW bx_bool hcr; // 1 bit HostControllerReset = 0b RW RW } HcCommandStatus; // = 0x00000000 Bit32u HcInterruptStatus; Bit32u HcInterruptEnable; Bit32u HcHCCA; Bit32u HcPeriodCurrentED; Bit32u HcControlHeadED; Bit32u HcControlCurrentED; Bit32u HcBulkHeadED; Bit32u HcBulkCurrentED; Bit32u HcDoneHead; struct { bx_bool fit; // 1 bit FrameIntervalToggle = 0b RW R Bit16u fsmps; // 15 bit FSLargestDataPacket = TBD (0) RW R Bit8u reserved; // 2 bit reserved = 00b R R Bit16u fi; // 14 bit FrameInterval = 0x2EDF RW R } HcFmInterval; // = 0x00002EDF bx_bool HcFmRemainingToggle; // 1 bit FrameRemainingToggle = 0b R RW Bit32u HcFmNumber; Bit32u HcPeriodicStart; Bit16u HcLSThreshold; struct { Bit8u potpgt; // 8 bit PowerOnToPowerGoodTime = 0x10 RW R Bit16u reserved; // 11 bit reserved = 0x000 R R bx_bool nocp; // 1 bit NoOverCurrentProtection = 0b RW R bx_bool ocpm; // 1 bit OverCurrentProtectionMode = 1b RW R bx_bool dt; // 1 bit DeviceType = 0b R R bx_bool nps; // 1 bit NoPowerSwitching = 0b RW R bx_bool psm; // 1 bit PowerSwitchingMode = 1b RW R Bit8u ndp; // 8 bit NumberDownstreamPorts = NUMPORTS RW R } HcRhDescriptorA; // = 0x100009xx struct { Bit16u ppcm; // 16 bit PortPowerControlMask = 0x0002 RW R Bit16u dr; // 16 bit DeviceRemovable = 0x0000 RW R } HcRhDescriptorB; // = 0x00020000 struct { bx_bool crwe; // 1 bit ClearRemoteWakeupEnable = 0b WC R Bit16u reserved0; // 13 bit reserved = 0x000000 R R bx_bool ocic; // 1 bit OverCurrentIndicatorChange = 0b RW RW bx_bool lpsc; // 1 bit LocalPowerStatusChange(r) = 0b RW R bx_bool drwe; // 1 bit DeviceRemoteWakeupEnable(r) = 0b RW R Bit16u reserved1; // 13 bit reserved = 0x000000 R R bx_bool oci; // 1 bit OverCurrentIndicator = 0b R RW bx_bool lps; // 1 bit LocalPowerStatus(r) = 0b RW R } HcRhStatus; // = 0x00000000 } op_regs; struct { // our data usb_device_c *device; // device connected to this port struct { Bit16u reserved0; // 11 bit reserved = 0x000000 R R bx_bool prsc; // 1 bit PortResetStatusChange = 0b RW RW bx_bool ocic; // 1 bit OverCurrentIndicatorChange = 0b RW RW bx_bool pssc; // 1 bit PortSuspendStatusChange = 0b RW RW bx_bool pesc; // 1 bit PortEnableStatusChange = 0b RW RW bx_bool csc; // 1 bit ConnectStatusChange = 0b RW RW Bit8u reserved1; // 6 bit reserved = 0x00 R R bx_bool lsda; // 1 bit LowSpeedDeviceAttached = 0b RW RW bx_bool pps; // 1 bit PortPowerStatus = 0b RW RW Bit8u reserved2; // 3 bit reserved = 0x0 R R bx_bool prs; // 1 bit PortResetStatus = 0b RW RW bx_bool poci; // 1 bit PortOverCurrentIndicator = 0b RW RW bx_bool pss; // 1 bit PortSuspendStatus = 0b RW RW bx_bool pes; // 1 bit PortEnableStatus = 0b RW RW bx_bool ccs; // 1 bit CurrentConnectStatus = 0b RW RW } HcRhPortStatus; } usb_port[BX_N_USB_OHCI_PORTS]; Bit8u devfunc; unsigned ohci_done_count; bx_bool use_control_head; bx_bool use_bulk_head; Bit64u sof_time; int statusbar_id; // ID of the status LEDs Bit8u device_change; } bx_usb_ohci_t; class bx_usb_ohci_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: bx_usb_ohci_c(); virtual ~bx_usb_ohci_c(); virtual void init(void); virtual void reset(unsigned); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); static const char *usb_param_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen); private: bx_usb_ohci_t hub; Bit8u *device_buffer; USBPacket usb_packet; static void reset_hc(); static void reset_port(int); static void update_irq(); static void set_interrupt(Bit32u value); static void init_device(Bit8u port, bx_list_c *portconf); static void remove_device(Bit8u port); static int broadcast_packet(USBPacket *p); static void usb_set_connect_status(Bit8u port, int type, bx_bool connected); static void usb_frame_handler(void *); void usb_frame_timer(void); static Bit32u get_frame_remaining(void); void process_ed(struct OHCI_ED *, const Bit32u); bx_bool process_td(struct OHCI_TD *, struct OHCI_ED *); #if BX_USE_USB_OHCI_SMF static bx_bool read_handler(bx_phy_address addr, unsigned len, void *data, void *param); static bx_bool write_handler(bx_phy_address addr, unsigned len, void *data, void *param); #else bx_bool read_handler(bx_phy_address addr, unsigned len, void *data, void *param); bx_bool write_handler(bx_phy_address addr, unsigned len, void *data, void *param); #endif static void runtime_config_handler(void *); void runtime_config(void); }; #endif // BX_IODEV_USB_OHCI_H bochs-2.6/iodev/usb/usb_ohci.cc0000644000175000017500000016713312020641504016343 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_ohci.cc 11390 2012-09-02 09:37:47Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Experimental USB OHCI adapter // Notes: See usb_uhci.cc // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_USB_OHCI #include "pci.h" #include "usb_common.h" #include "usb_ohci.h" #define LOG_THIS theUSB_OHCI-> bx_usb_ohci_c* theUSB_OHCI = NULL; const char *usb_ohci_port_name[] = { "HCRevision ", "HCControl ", "HCCommandStatus ", "HCInterruptStatus ", "HCInterruptEnable ", "HCInterruptDisable", "HCHCCA ", "HCPeriodCurrentED ", "HCControlHeadED ", "HCControlCurrentED", "HCBulkHeadED ", "HCBulkCurrentED ", "HCDoneHead ", "HCFmInterval ", "HCFmRemaining ", "HCFmNumber ", "HCPeriodicStart ", "HCLSThreshold ", "HCRhDescriptorA ", "HCRhDescriptorB ", "HCRhStatus ", "HCRhPortStatus0 ", "HCRhPortStatus1 ", "HCRhPortStatus2 ", "HCRhPortStatus3 ", " **unknown** " }; // builtin configuration handling functions Bit32s usb_ohci_options_parser(const char *context, int num_params, char *params[]) { if (!strcmp(params[0], "usb_ohci")) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_USB_OHCI); for (int i = 1; i < num_params; i++) { if (!strncmp(params[i], "enabled=", 8)) { SIM->get_param_bool(BXPN_OHCI_ENABLED)->set(atol(¶ms[i][8])); } else if (!strncmp(params[i], "port", 4)) { if (SIM->parse_usb_port_params(context, 0, params[i], BX_N_USB_OHCI_PORTS, base) < 0) { return -1; } } else if (!strncmp(params[i], "options", 7)) { if (SIM->parse_usb_port_params(context, 1, params[i], BX_N_USB_OHCI_PORTS, base) < 0) { return -1; } } else { BX_ERROR(("%s: unknown parameter '%s' for usb_ohci ignored.", context, params[i])); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s usb_ohci_options_save(FILE *fp) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_USB_OHCI); SIM->write_usb_options(fp, BX_N_USB_OHCI_PORTS, base); return 0; } // device plugin entry points int libusb_ohci_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theUSB_OHCI = new bx_usb_ohci_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUSB_OHCI, BX_PLUGIN_USB_OHCI); // add new configuration parameter for the config interface SIM->init_usb_options("OHCI", "ohci", BX_N_USB_OHCI_PORTS); // register add-on option for bochsrc and command line SIM->register_addon_option("usb_ohci", usb_ohci_options_parser, usb_ohci_options_save); return 0; // Success } void libusb_ohci_LTX_plugin_fini(void) { SIM->unregister_addon_option("usb_ohci"); bx_list_c *menu = (bx_list_c*)SIM->get_param("ports.usb"); delete theUSB_OHCI; menu->remove("ohci"); } // the device object bx_usb_ohci_c::bx_usb_ohci_c() { put("usb_ohci", "OHCI"); memset((void*)&hub, 0, sizeof(bx_usb_ohci_t)); device_buffer = NULL; hub.frame_timer_index = BX_NULL_TIMER_HANDLE; } bx_usb_ohci_c::~bx_usb_ohci_c() { char pname[16]; if (BX_OHCI_THIS device_buffer != NULL) delete [] BX_OHCI_THIS device_buffer; for (int i=0; iget_param_string(pname, SIM->get_param(BXPN_USB_OHCI))->set_handler(NULL); remove_device(i); } SIM->get_bochs_root()->remove("usb_ohci"); BX_DEBUG(("Exit")); } void bx_usb_ohci_c::init(void) { unsigned i; char pname[6]; bx_list_c *ohci, *port; bx_param_string_c *device, *options; // Read in values from config interface ohci = (bx_list_c*) SIM->get_param(BXPN_USB_OHCI); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", ohci)->get()) { BX_INFO(("USB OHCI disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("usb_ohci"))->set(0); return; } BX_OHCI_THIS device_buffer = new Bit8u[65536]; // Call our frame timer routine every 1mS (1,000uS) // Continuous and active BX_OHCI_THIS hub.frame_timer_index = bx_pc_system.register_timer(this, usb_frame_handler, 1000, 1,1, "ohci.frame_timer"); BX_OHCI_THIS hub.devfunc = 0x00; DEV_register_pci_handlers(this, &BX_OHCI_THIS hub.devfunc, BX_PLUGIN_USB_OHCI, "Experimental USB OHCI"); for (i=0; i<256; i++) BX_OHCI_THIS pci_conf[i] = 0x0; BX_OHCI_THIS pci_base_address[0] = 0x0; BX_OHCI_THIS hub.ohci_done_count = 7; BX_OHCI_THIS hub.use_control_head = 0; BX_OHCI_THIS hub.use_bulk_head = 0; BX_OHCI_THIS hub.sof_time = 0; //FIXME: for now, we want a status bar // hub zero, port zero BX_OHCI_THIS hub.statusbar_id = bx_gui->register_statusitem("OHCI", 1); bx_list_c *usb_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_USB); ohci->set_options(ohci->SHOW_PARENT); ohci->set_runtime_param(1); usb_rt->add(ohci); for (i=0; iget_param(pname, ohci); port->set_runtime_param(1); device = (bx_param_string_c*)port->get_by_name("device"); device->set_handler(usb_param_handler); device->set_runtime_param(1); options = (bx_param_string_c*)port->get_by_name("options"); options->set_runtime_param(1); BX_OHCI_THIS hub.usb_port[i].device = NULL; BX_OHCI_THIS hub.usb_port[i].HcRhPortStatus.ccs = 0; BX_OHCI_THIS hub.usb_port[i].HcRhPortStatus.csc = 0; } // register handler for correct device connect handling after runtime config SIM->register_runtime_config_handler(BX_OHCI_THIS_PTR, runtime_config_handler); BX_OHCI_THIS hub.device_change = 0; BX_INFO(("USB OHCI initialized")); } void bx_usb_ohci_c::reset(unsigned type) { unsigned i; if (type == BX_RESET_HARDWARE) { static const struct reset_vals_t { unsigned addr; unsigned char val; } reset_vals[] = { { 0x00, 0xC1 }, { 0x01, 0x11 }, // 0x11C1 = vendor { 0x02, 0x03 }, { 0x03, 0x58 }, // 0x5803 = device { 0x04, 0x06 }, { 0x05, 0x00 }, // command_io { 0x06, 0x10 }, { 0x07, 0x02 }, // status (bit 4 = 1, has capabilities list.) { 0x08, 0x11 }, // revision number { 0x09, 0x10 }, // interface { 0x0a, 0x03 }, // class_sub USB Host Controller { 0x0b, 0x0c }, // class_base Serial Bus Controller { 0x0D, 0x40 }, // bus latency { 0x0e, 0x00 }, // header_type_generic // address space 0x10 - 0x13 { 0x10, 0x00 }, { 0x11, 0x50 }, // { 0x12, 0x00 }, { 0x13, 0xE1 }, // { 0x2C, 0xC1 }, { 0x2D, 0x11 }, // subsystem vendor ID { 0x2E, 0x03 }, { 0x2F, 0x58 }, // subsystem ID { 0x34, 0x50 }, // offset of capabilities list within configuration space { 0x3c, 0x0B }, // IRQ { 0x3d, BX_PCI_INTD }, // INT { 0x3E, 0x03 }, // minimum time bus master needs PCI bus ownership, in 250ns units { 0x3F, 0x56 }, // maximum latency, in 250ns units (bus masters only) (read-only) // capabilities list: { 0x50, 0x01 }, // { 0x51, 0x00 }, // { 0x52, 0x02 }, // { 0x53, 0x76 }, // { 0x54, 0x00 }, // { 0x55, 0x20 }, // { 0x56, 0x00 }, // { 0x57, 0x1F }, // }; for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { BX_OHCI_THIS pci_conf[reset_vals[i].addr] = reset_vals[i].val; } } BX_OHCI_THIS reset_hc(); } void bx_usb_ohci_c::reset_hc() { int i; char pname[6]; // reset locals BX_OHCI_THIS hub.ohci_done_count = 7; // HcRevision BX_OHCI_THIS hub.op_regs.HcRevision = 0x0110; // HcControl BX_OHCI_THIS hub.op_regs.HcControl.reserved = 0; BX_OHCI_THIS hub.op_regs.HcControl.rwe = 0; BX_OHCI_THIS hub.op_regs.HcControl.rwc = 0; BX_OHCI_THIS hub.op_regs.HcControl.ir = 0; BX_OHCI_THIS hub.op_regs.HcControl.hcfs = 0; BX_OHCI_THIS hub.op_regs.HcControl.ble = 0; BX_OHCI_THIS hub.op_regs.HcControl.cle = 0; BX_OHCI_THIS hub.op_regs.HcControl.ie = 0; BX_OHCI_THIS hub.op_regs.HcControl.ple = 0; BX_OHCI_THIS hub.op_regs.HcControl.cbsr = 0; // HcCommandStatus BX_OHCI_THIS hub.op_regs.HcCommandStatus.reserved0 = 0x000000; BX_OHCI_THIS hub.op_regs.HcCommandStatus.soc = 0; BX_OHCI_THIS hub.op_regs.HcCommandStatus.reserved1 = 0x000000; BX_OHCI_THIS hub.op_regs.HcCommandStatus.ocr = 0; BX_OHCI_THIS hub.op_regs.HcCommandStatus.blf = 0; BX_OHCI_THIS hub.op_regs.HcCommandStatus.clf = 0; BX_OHCI_THIS hub.op_regs.HcCommandStatus.hcr = 0; // HcInterruptStatus BX_OHCI_THIS hub.op_regs.HcInterruptStatus = 0x00000000; // HcInterruptEnable BX_OHCI_THIS hub.op_regs.HcInterruptEnable = OHCI_INTR_MIE; // HcHCCA BX_OHCI_THIS hub.op_regs.HcHCCA = 0x00000000; // HcPeriodCurrentED BX_OHCI_THIS hub.op_regs.HcPeriodCurrentED = 0x00000000; // HcControlHeadED BX_OHCI_THIS hub.op_regs.HcControlHeadED = 0x00000000; // HcControlCurrentED BX_OHCI_THIS hub.op_regs.HcControlCurrentED = 0x00000000; // HcBulkHeadED BX_OHCI_THIS hub.op_regs.HcBulkHeadED = 0x00000000; // HcBulkCurrentED BX_OHCI_THIS hub.op_regs.HcBulkCurrentED = 0x00000000; // HcDoneHead BX_OHCI_THIS hub.op_regs.HcDoneHead = 0x00000000; // HcFmInterval BX_OHCI_THIS hub.op_regs.HcFmInterval.fit = 0; BX_OHCI_THIS hub.op_regs.HcFmInterval.fsmps = 0; BX_OHCI_THIS hub.op_regs.HcFmInterval.reserved = 0; BX_OHCI_THIS hub.op_regs.HcFmInterval.fi = 0x2EDF; // HcFmRemaining BX_OHCI_THIS hub.op_regs.HcFmRemainingToggle = 0; // HcFmNumber BX_OHCI_THIS hub.op_regs.HcFmNumber = 0x00000000; // HcPeriodicStart BX_OHCI_THIS hub.op_regs.HcPeriodicStart = 0x00000000; // HcLSThreshold BX_OHCI_THIS hub.op_regs.HcLSThreshold = 0x0628; // HcRhDescriptorA BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.potpgt = 0x10; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.reserved = 0; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nocp = 0; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ocpm = 1; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.dt = 0; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nps = 0; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm = 1; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ndp = BX_N_USB_OHCI_PORTS; // HcRhDescriptorB BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.ppcm = ((1 << BX_N_USB_OHCI_PORTS) - 1) << 1; BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.dr = 0x0000; // HcRhStatus BX_OHCI_THIS hub.op_regs.HcRhStatus.crwe = 0; BX_OHCI_THIS hub.op_regs.HcRhStatus.reserved0 = 0; BX_OHCI_THIS hub.op_regs.HcRhStatus.ocic = 0; BX_OHCI_THIS hub.op_regs.HcRhStatus.lpsc = 0; BX_OHCI_THIS hub.op_regs.HcRhStatus.drwe = 0; BX_OHCI_THIS hub.op_regs.HcRhStatus.reserved1 = 0; BX_OHCI_THIS hub.op_regs.HcRhStatus.oci = 0; BX_OHCI_THIS hub.op_regs.HcRhStatus.lps = 0; // HcRhPortStatus[x] for (i=0; iget_param(pname, SIM->get_param(BXPN_USB_OHCI))); } else { usb_set_connect_status(i, BX_OHCI_THIS hub.usb_port[i].device->get_type(), 1); } } } void bx_usb_ohci_c::reset_port(int p) { BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved0 = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prsc = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ocic = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pssc = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pesc = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved1 = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.lsda = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved2 = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prs = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.poci = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pss = 0; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pes = 0; } void bx_usb_ohci_c::register_state(void) { unsigned i; char portnum[8]; bx_list_c *hub, *port, *reg; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "usb_ohci", "USB OHCI State"); hub = new bx_list_c(list, "hub"); reg = new bx_list_c(hub, "HcControl"); new bx_shadow_bool_c(reg, "rwe", &BX_OHCI_THIS hub.op_regs.HcControl.rwe); new bx_shadow_bool_c(reg, "rwc", &BX_OHCI_THIS hub.op_regs.HcControl.rwc); new bx_shadow_bool_c(reg, "ir", &BX_OHCI_THIS hub.op_regs.HcControl.ir); new bx_shadow_num_c(reg, "hcfs", &BX_OHCI_THIS hub.op_regs.HcControl.hcfs); new bx_shadow_bool_c(reg, "ble", &BX_OHCI_THIS hub.op_regs.HcControl.ble); new bx_shadow_bool_c(reg, "cle", &BX_OHCI_THIS hub.op_regs.HcControl.cle); new bx_shadow_bool_c(reg, "ie", &BX_OHCI_THIS hub.op_regs.HcControl.ie); new bx_shadow_bool_c(reg, "ple", &BX_OHCI_THIS hub.op_regs.HcControl.ple); new bx_shadow_num_c(reg, "cbsr", &BX_OHCI_THIS hub.op_regs.HcControl.cbsr); reg = new bx_list_c(hub, "HcCommandStatus"); new bx_shadow_num_c(reg, "soc", &BX_OHCI_THIS hub.op_regs.HcCommandStatus.soc); new bx_shadow_bool_c(reg, "ocr", &BX_OHCI_THIS hub.op_regs.HcCommandStatus.ocr); new bx_shadow_bool_c(reg, "blf", &BX_OHCI_THIS hub.op_regs.HcCommandStatus.blf); new bx_shadow_bool_c(reg, "clf", &BX_OHCI_THIS hub.op_regs.HcCommandStatus.clf); new bx_shadow_bool_c(reg, "hcr", &BX_OHCI_THIS hub.op_regs.HcCommandStatus.hcr); new bx_shadow_num_c(hub, "HcInterruptStatus", &BX_OHCI_THIS hub.op_regs.HcInterruptStatus, BASE_HEX); new bx_shadow_num_c(hub, "HcInterruptEnable", &BX_OHCI_THIS hub.op_regs.HcInterruptEnable, BASE_HEX); new bx_shadow_num_c(hub, "HcHCCA", &BX_OHCI_THIS hub.op_regs.HcHCCA, BASE_HEX); new bx_shadow_num_c(hub, "HcPeriodCurrentED", &BX_OHCI_THIS hub.op_regs.HcPeriodCurrentED, BASE_HEX); new bx_shadow_num_c(hub, "HcControlHeadED", &BX_OHCI_THIS hub.op_regs.HcControlHeadED, BASE_HEX); new bx_shadow_num_c(hub, "HcControlCurrentED", &BX_OHCI_THIS hub.op_regs.HcControlCurrentED, BASE_HEX); new bx_shadow_num_c(hub, "HcBulkHeadED", &BX_OHCI_THIS hub.op_regs.HcBulkHeadED, BASE_HEX); new bx_shadow_num_c(hub, "HcBulkCurrentED", &BX_OHCI_THIS hub.op_regs.HcBulkCurrentED, BASE_HEX); new bx_shadow_num_c(hub, "HcDoneHead", &BX_OHCI_THIS hub.op_regs.HcDoneHead, BASE_HEX); reg = new bx_list_c(hub, "HcFmInterval"); new bx_shadow_bool_c(reg, "fit", &BX_OHCI_THIS hub.op_regs.HcFmInterval.fit); new bx_shadow_num_c(reg, "fsmps", &BX_OHCI_THIS hub.op_regs.HcFmInterval.fsmps); new bx_shadow_num_c(reg, "fi", &BX_OHCI_THIS hub.op_regs.HcFmInterval.fi, BASE_HEX); new bx_shadow_bool_c(hub, "HcFmRemainingToggle", &BX_OHCI_THIS hub.op_regs.HcFmRemainingToggle); new bx_shadow_num_c(hub, "HcFmNumber", &BX_OHCI_THIS hub.op_regs.HcFmNumber, BASE_HEX); new bx_shadow_num_c(hub, "HcPeriodicStart", &BX_OHCI_THIS hub.op_regs.HcPeriodicStart, BASE_HEX); reg = new bx_list_c(hub, "HcRhDescriptorA"); new bx_shadow_num_c(reg, "potpgt", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.potpgt, BASE_HEX); new bx_shadow_bool_c(reg, "nocp", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nocp); new bx_shadow_bool_c(reg, "ocpm", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ocpm); new bx_shadow_bool_c(reg, "dt", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.dt); new bx_shadow_bool_c(reg, "nps", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nps); new bx_shadow_bool_c(reg, "psm", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm); new bx_shadow_num_c(reg, "ndp", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ndp); reg = new bx_list_c(hub, "HcRhDescriptorB"); new bx_shadow_num_c(reg, "ppcm", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.ppcm, BASE_HEX); new bx_shadow_num_c(reg, "dr", &BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.dr, BASE_HEX); reg = new bx_list_c(hub, "HcRhStatus"); new bx_shadow_bool_c(reg, "crwe", &BX_OHCI_THIS hub.op_regs.HcRhStatus.crwe); new bx_shadow_bool_c(reg, "ocic", &BX_OHCI_THIS hub.op_regs.HcRhStatus.ocic); new bx_shadow_bool_c(reg, "lpsc", &BX_OHCI_THIS hub.op_regs.HcRhStatus.lpsc); new bx_shadow_bool_c(reg, "drwe", &BX_OHCI_THIS hub.op_regs.HcRhStatus.drwe); new bx_shadow_bool_c(reg, "oci", &BX_OHCI_THIS hub.op_regs.HcRhStatus.oci); new bx_shadow_bool_c(reg, "lps", &BX_OHCI_THIS hub.op_regs.HcRhStatus.lps); for (i=0; iafter_restore_state(); } } } void bx_usb_ohci_c::init_device(Bit8u port, bx_list_c *portconf) { usbdev_type type; char pname[BX_PATHNAME_LEN]; const char *devname = NULL; devname = ((bx_param_string_c*)portconf->get_by_name("device"))->getptr(); if (devname == NULL) return; if (!strlen(devname) || !strcmp(devname, "none")) return; if (BX_OHCI_THIS hub.usb_port[port].device != NULL) { BX_ERROR(("init_device(): port%d already in use", port+1)); return; } sprintf(pname, "usb_ohci.hub.port%d.device", port+1); bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root()); type = DEV_usb_init_device(portconf, BX_OHCI_THIS_PTR, &BX_OHCI_THIS hub.usb_port[port].device, sr_list); if (BX_OHCI_THIS hub.usb_port[port].device != NULL) { usb_set_connect_status(port, type, 1); } } void bx_usb_ohci_c::remove_device(Bit8u port) { char pname[BX_PATHNAME_LEN]; if (BX_OHCI_THIS hub.usb_port[port].device != NULL) { delete BX_OHCI_THIS hub.usb_port[port].device; BX_OHCI_THIS hub.usb_port[port].device = NULL; sprintf(pname, "usb_ohci.hub.port%d.device", port+1); bx_list_c *devlist = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root()); devlist->clear(); } } void bx_usb_ohci_c::update_irq() { bx_bool level = 0; if ((BX_OHCI_THIS hub.op_regs.HcInterruptEnable & OHCI_INTR_MIE) && (BX_OHCI_THIS hub.op_regs.HcInterruptStatus & BX_OHCI_THIS hub.op_regs.HcInterruptEnable)) { level = 1; BX_DEBUG(("Interrupt Fired.")); } DEV_pci_set_irq(BX_OHCI_THIS hub.devfunc, BX_OHCI_THIS pci_conf[0x3d], level); } void bx_usb_ohci_c::set_interrupt(Bit32u value) { BX_OHCI_THIS hub.op_regs.HcInterruptStatus |= value; update_irq(); } bx_bool bx_usb_ohci_c::read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit32u val = 0x0; int p = 0; if (len != 4) { BX_INFO(("Read at 0x%08X with len != 4 (%i)", (Bit32u)addr, len)); return 1; } if (addr & 3) { BX_INFO(("Misaligned read at 0x%08X", (Bit32u)addr)); return 1; } Bit32u offset = (Bit32u)(addr - BX_OHCI_THIS pci_base_address[0]); switch (offset) { case 0x00: // HcRevision val = BX_OHCI_THIS hub.op_regs.HcRevision; break; case 0x04: // HcControl val = (BX_OHCI_THIS hub.op_regs.HcControl.reserved << 11) | (BX_OHCI_THIS hub.op_regs.HcControl.rwe ? 1 << 10 : 0) | (BX_OHCI_THIS hub.op_regs.HcControl.rwc ? 1 << 9 : 0) | (BX_OHCI_THIS hub.op_regs.HcControl.ir ? 1 << 8 : 0) | (BX_OHCI_THIS hub.op_regs.HcControl.hcfs << 6) | (BX_OHCI_THIS hub.op_regs.HcControl.ble ? 1 << 5 : 0) | (BX_OHCI_THIS hub.op_regs.HcControl.cle ? 1 << 4 : 0) | (BX_OHCI_THIS hub.op_regs.HcControl.ie ? 1 << 3 : 0) | (BX_OHCI_THIS hub.op_regs.HcControl.ple ? 1 << 2 : 0) | (BX_OHCI_THIS hub.op_regs.HcControl.cbsr << 0); break; case 0x08: // HcCommandStatus val = (BX_OHCI_THIS hub.op_regs.HcCommandStatus.reserved0 << 18) | (BX_OHCI_THIS hub.op_regs.HcCommandStatus.soc << 16) | (BX_OHCI_THIS hub.op_regs.HcCommandStatus.reserved1 << 4) | (BX_OHCI_THIS hub.op_regs.HcCommandStatus.ocr ? 1 << 3 : 0) | (BX_OHCI_THIS hub.op_regs.HcCommandStatus.blf ? 1 << 2 : 0) | (BX_OHCI_THIS hub.op_regs.HcCommandStatus.clf ? 1 << 1 : 0) | (BX_OHCI_THIS hub.op_regs.HcCommandStatus.hcr ? 1 << 0 : 0); break; case 0x0C: // HcInterruptStatus val = BX_OHCI_THIS hub.op_regs.HcInterruptStatus; break; case 0x10: // HcInterruptEnable case 0x14: // HcInterruptDisable (reading this one returns that one) val = BX_OHCI_THIS hub.op_regs.HcInterruptEnable; break; case 0x18: // HcHCCA val = BX_OHCI_THIS hub.op_regs.HcHCCA; break; case 0x1C: // HcPeriodCurrentED val = BX_OHCI_THIS hub.op_regs.HcPeriodCurrentED; break; case 0x20: // HcControlHeadED val = BX_OHCI_THIS hub.op_regs.HcControlHeadED; break; case 0x24: // HcControlCurrentED val = BX_OHCI_THIS hub.op_regs.HcControlCurrentED; break; case 0x28: // HcBulkHeadED val = BX_OHCI_THIS hub.op_regs.HcBulkHeadED; break; case 0x2C: // HcBulkCurrentED val = BX_OHCI_THIS hub.op_regs.HcBulkCurrentED; break; case 0x30: // HcDoneHead val = BX_OHCI_THIS hub.op_regs.HcDoneHead; break; case 0x34: // HcFmInterval val = (BX_OHCI_THIS hub.op_regs.HcFmInterval.fit ? 1 << 31 : 0) | (BX_OHCI_THIS hub.op_regs.HcFmInterval.fsmps << 16) | (BX_OHCI_THIS hub.op_regs.HcFmInterval.reserved << 14) | (BX_OHCI_THIS hub.op_regs.HcFmInterval.fi << 0); break; case 0x38: // HcFmRemaining val = get_frame_remaining(); break; case 0x3C: // HcFmNumber val = BX_OHCI_THIS hub.op_regs.HcFmNumber; break; case 0x40: // HcPeriodicStart val = BX_OHCI_THIS hub.op_regs.HcPeriodicStart; break; case 0x44: // HcLSThreshold val = BX_OHCI_THIS hub.op_regs.HcLSThreshold; break; case 0x48: // HcRhDescriptorA val = (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.potpgt << 24) | (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.reserved << 13) | (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nocp ? 1 << 12 : 0) | (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ocpm ? 1 << 11 : 0) | 0 //BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.dt << 10 | (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nps ? 1 << 9 : 0) | (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm ? 1 << 8 : 0) | (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ndp << 0); break; case 0x4C: // HcRhDescriptorB val = (BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.ppcm << 16) | (BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.dr << 0); break; case 0x50: // HcRhStatus val = (BX_OHCI_THIS hub.op_regs.HcRhStatus.crwe ? 1 << 31 : 0) | (BX_OHCI_THIS hub.op_regs.HcRhStatus.reserved0 << 18) | (BX_OHCI_THIS hub.op_regs.HcRhStatus.ocic ? 1 << 17 : 0) | 0 //BX_OHCI_THIS hub.op_regs.HcRhStatus.lpsc << 16 | (BX_OHCI_THIS hub.op_regs.HcRhStatus.drwe ? 1 << 15 : 0) | (BX_OHCI_THIS hub.op_regs.HcRhStatus.reserved1 << 2) | (BX_OHCI_THIS hub.op_regs.HcRhStatus.oci ? 1 << 1 : 0) | (BX_OHCI_THIS hub.op_regs.HcRhStatus.lps ? 1 << 0 : 0); break; case 0x60: // HcRhPortStatus[3] #if (BX_N_USB_OHCI_PORTS < 4) val = 0; break; #endif case 0x5C: // HcRhPortStatus[2] #if (BX_N_USB_OHCI_PORTS < 3) val = 0; break; #endif case 0x58: // HcRhPortStatus[1] #if (BX_N_USB_OHCI_PORTS < 2) val = 0; break; #endif case 0x54: // HcRhPortStatus[0] p = (offset - 0x54) >> 2; if (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps == 1) { val = (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved0 << 21) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prsc ? (1 << 20) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ocic ? (1 << 19) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pssc ? (1 << 18) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pesc ? (1 << 17) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.csc ? (1 << 16) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved1 << 10) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.lsda ? (1 << 9) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps ? (1 << 8) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.reserved2 << 5) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prs ? (1 << 4) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.poci ? (1 << 3) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pss ? (1 << 2) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pes ? (1 << 1) : 0) | (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ccs ? (1 << 0) : 0); } else val = 0; break; default: BX_ERROR(("unsupported read from address=0x%08X!", (Bit32u)addr)); break; } int name = offset >> 2; if (name > (0x60 >> 2)) name = 25; //BX_INFO(("register read from address 0x%04X (%s): 0x%08X (len=%i)", (unsigned) addr, usb_ohci_port_name[name], (Bit32u) val, len)); *((Bit32u *) data) = val; return 1; } bx_bool bx_usb_ohci_c::write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit32u value = *((Bit32u *) data); Bit32u offset = (Bit32u)addr - BX_OHCI_THIS pci_base_address[0]; int p, org_state; int name = offset >> 2; if (name > (0x60 >> 2)) name = 25; //BX_INFO(("register write to address 0x%04X (%s): 0x%08X (len=%i)", (unsigned) addr, usb_ohci_port_name[name], (unsigned) value, len)); if (len != 4) { BX_INFO(("Write at 0x%08X with len != 4 (%i)", (Bit32u)addr, len)); return 1; } if (addr & 3) { BX_INFO(("Misaligned write at 0x%08X", (Bit32u)addr)); return 1; } switch (offset) { case 0x00: // HcRevision BX_ERROR(("Write to HcRevision ignored")); break; case 0x04: // HcControl if (value & 0xFFFFF800) BX_ERROR(("Write to reserved field in HcControl")); org_state = BX_OHCI_THIS hub.op_regs.HcControl.hcfs; BX_OHCI_THIS hub.op_regs.HcControl.rwe = (value & (1<<10)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcControl.rwc = (value & (1<< 9)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcControl.ir = (value & (1<< 8)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcControl.hcfs = (value & (3<< 6)) >> 6; BX_OHCI_THIS hub.op_regs.HcControl.ble = (value & (1<< 5)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcControl.cle = (value & (1<< 4)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcControl.ie = (value & (1<< 3)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcControl.ple = (value & (1<< 2)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcControl.cbsr = (value & (3<< 0)) >> 0; if (BX_OHCI_THIS hub.op_regs.HcControl.hcfs == 0x02) { BX_OHCI_THIS hub.op_regs.HcFmRemainingToggle = 0; if (org_state != 2) BX_OHCI_THIS hub.use_control_head = BX_OHCI_THIS hub.use_bulk_head = 1; } break; case 0x08: // HcCommandStatus if (value & 0xFFFCFFF0) BX_ERROR(("Write to a reserved field in HcCommandStatus")); if (value & (3<<16)) BX_ERROR(("Write to R/O field: HcCommandStatus.soc")); if (value & (1<< 3)) BX_OHCI_THIS hub.op_regs.HcCommandStatus.ocr = 1; if (value & (1<< 2)) BX_OHCI_THIS hub.op_regs.HcCommandStatus.blf = 1; if (value & (1<< 1)) BX_OHCI_THIS hub.op_regs.HcCommandStatus.clf = 1; if (value & (1<< 0)) { BX_OHCI_THIS hub.op_regs.HcCommandStatus.hcr = 1; BX_OHCI_THIS reset_hc(); BX_OHCI_THIS hub.op_regs.HcControl.hcfs = 3; // suspend state for (unsigned i=0; i> 16; BX_OHCI_THIS hub.op_regs.HcFmInterval.fi = (value & 0x00003FFF) >> 0; break; case 0x38: // HcFmRemaining BX_ERROR(("Write to HcFmRemaining not allowed.")); break; case 0x3C: // HcFmNumber BX_ERROR(("Write to HcFmNumber not allowed.")); break; case 0x40: // HcPeriodicStart if (value & 0xFFFFC000) BX_ERROR(("Write to a reserved field in HcPeriodicStart.")); BX_OHCI_THIS hub.op_regs.HcPeriodicStart = (value & 0x00003FFF); break; case 0x44: // HcLSThreshold BX_ERROR(("Write to HcLSThreshold not allowed.")); break; case 0x48: // HcRhDescriptorA if (value & 0x00FFE000) BX_ERROR(("Write to a reserved field in HcRhDescriptorA.")); if (value & 0x000000FF) BX_ERROR(("Write to HcRhDescriptorA.ndp not allowed.")); if (value & (1<<10)) BX_ERROR(("Write to HcRhDescriptorA.dt not allowed.")); BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.potpgt = (value & 0xFF000000) >> 24; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nocp = (value & (1<<12)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.ocpm = (value & (1<<11)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.nps = (value & (1<< 9)) ? 1 : 0; BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm = (value & (1<< 8)) ? 1 : 0; if (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm == 0) { BX_INFO(("Ben: BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm == 0")); // all ports have power, etc. // BX_USB_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps = 1 // Call a routine to set each ports dword (LS, Connected, etc.) } else { BX_INFO(("Ben: BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm == 1")); // only ports with bit set in rhstatus have power, etc. // Call a routine to set each ports dword (LS, Connected, etc.) } break; case 0x4C: // HcRhDescriptorB BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.ppcm = (value & 0xFFFF0000) >> 16; BX_OHCI_THIS hub.op_regs.HcRhDescriptorB.dr = (value & 0x0000FFFF) >> 0; break; case 0x50: { // HcRhStatus if (value & 0x7FFC7FFC) BX_ERROR(("Write to a reserved field in HcRhStatus.")); if (value & (1<<1)) BX_ERROR(("Write to HcRhStatus.oci not allowed.")); // which one of these two takes presidence? if (value & (1<<31)) BX_OHCI_THIS hub.op_regs.HcRhStatus.drwe = 0; if (value & (1<<15)) BX_OHCI_THIS hub.op_regs.HcRhStatus.drwe = 1; if (value & (1<<17)) BX_OHCI_THIS hub.op_regs.HcRhStatus.ocic = 1; if (value & (1<<16)) { if (BX_OHCI_THIS hub.op_regs.HcRhDescriptorA.psm == 0) { for (p=0; p> 2; if (value & 0xFFE0FCE0) BX_ERROR(("Write to a reserved field in usb_port[%d].HcRhPortStatus", p)); if (value & (1<<0)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pes = 0; if (value & (1<<1)) { if (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ccs == 0) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.csc = 1; else BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pes = 1; } if (value & (1<<2)) { if (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ccs == 0) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.csc = 1; else BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pss = 1; } // if (value & (1<<3)) // if (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pss) // ; // do a resume (or test this in the timer code and do the resume there) if (value & (1<<4)) { if (BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ccs == 0) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.csc = 1; else { reset_port(p); BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps = 1; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pes = 1; BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prsc = 1; // are we are currently connected/disconnected if (BX_OHCI_THIS hub.usb_port[p].device != NULL) { BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.lsda = (BX_OHCI_THIS hub.usb_port[p].device->get_speed() == USB_SPEED_LOW); usb_set_connect_status(p, BX_OHCI_THIS hub.usb_port[p].device->get_type(), 1); DEV_usb_send_msg(BX_OHCI_THIS hub.usb_port[p].device, USB_MSG_RESET); } set_interrupt(OHCI_INTR_RHSC); } } if (value & (1<<8)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps = 1; if (value & (1<<9)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pps = 0; if (value & (1<<16)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.csc = (value & ((1<<4) | (1<<1) | (1<<2))) ? 1 : 0; if (value & (1<<17)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pesc = 0; if (value & (1<<18)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.pssc = 0; if (value & (1<<19)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.ocic = 0; if (value & (1<<20)) BX_OHCI_THIS hub.usb_port[p].HcRhPortStatus.prsc = 0; break; } default: BX_ERROR(("unsupported write to address=0x%08X, val = 0x%08X!", (Bit32u)addr, value)); break; } return 1; } Bit32u bx_usb_ohci_c::get_frame_remaining(void) { Bit16u bit_time, fr; bit_time = (Bit16u)((bx_pc_system.time_usec() - BX_OHCI_THIS hub.sof_time) * 12); if ((BX_OHCI_THIS hub.op_regs.HcControl.hcfs != 2) || (bit_time > BX_OHCI_THIS hub.op_regs.HcFmInterval.fi)) { fr = 0; } else { fr = BX_OHCI_THIS hub.op_regs.HcFmInterval.fi - bit_time; } return (BX_OHCI_THIS hub.op_regs.HcFmRemainingToggle << 31) | fr; } void bx_usb_ohci_c::usb_frame_handler(void *this_ptr) { bx_usb_ohci_c *class_ptr = (bx_usb_ohci_c *) this_ptr; class_ptr->usb_frame_timer(); } // Called once every 1mS void bx_usb_ohci_c::usb_frame_timer(void) { struct OHCI_ED cur_ed; Bit32u address, ed_address; Bit16u zero = 0; if (BX_OHCI_THIS hub.op_regs.HcControl.hcfs == 2) { // set remaining to the interval amount. BX_OHCI_THIS hub.op_regs.HcFmRemainingToggle = BX_OHCI_THIS hub.op_regs.HcFmInterval.fit; BX_OHCI_THIS hub.sof_time = bx_pc_system.time_usec(); // The Frame Number Register is incremented // every time bit 15 is changed (at 0x8000 or 0x0000), fno is fired. BX_OHCI_THIS hub.op_regs.HcFmNumber++; BX_OHCI_THIS hub.op_regs.HcFmNumber &= 0xffff; DEV_MEM_WRITE_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcHCCA + 0x80, 2, (Bit8u *) &BX_OHCI_THIS hub.op_regs.HcFmNumber); DEV_MEM_WRITE_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcHCCA + 0x82, 2, (Bit8u *) &zero); if ((BX_OHCI_THIS hub.op_regs.HcFmNumber == 0x8000) || (BX_OHCI_THIS hub.op_regs.HcFmNumber == 0x0000)) { set_interrupt(OHCI_INTR_FNO); } // set_interrupt(OHCI_INTR_SF); // if interrupt delay (done_count) == 0, and status.wdh == 0, then update the donehead fields. BX_DEBUG(("done_count = %i, status.wdh = %i", BX_OHCI_THIS hub.ohci_done_count, ((BX_OHCI_THIS hub.op_regs.HcInterruptStatus & OHCI_INTR_WD) > 0))); if ((BX_OHCI_THIS hub.ohci_done_count == 0) && ((BX_OHCI_THIS hub.op_regs.HcInterruptStatus & OHCI_INTR_WD) == 0)) { Bit32u temp = BX_OHCI_THIS hub.op_regs.HcDoneHead; if (BX_OHCI_THIS hub.op_regs.HcInterruptStatus & BX_OHCI_THIS hub.op_regs.HcInterruptEnable) temp |= 1; BX_DEBUG(("Updating the hcca.DoneHead field to 0x%08X and setting the wdh flag", temp)); DEV_MEM_WRITE_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcHCCA + 0x84, 4, (Bit8u *) &temp); BX_OHCI_THIS hub.op_regs.HcDoneHead = 0; BX_OHCI_THIS hub.ohci_done_count = 7; set_interrupt(OHCI_INTR_WD); } // if (6 >= done_count > 0) then decrement done_count if ((BX_OHCI_THIS hub.ohci_done_count != 7) && (BX_OHCI_THIS hub.ohci_done_count > 0)) BX_OHCI_THIS hub.ohci_done_count--; // TODO: Rather than just comparing .fr to <8000 here, and <4000 below, see the highlighted // statement on page 45. // if the control list is enabled *and* the control list filled bit is set, do a control list ED if (BX_OHCI_THIS hub.op_regs.HcControl.cle) { if (BX_OHCI_THIS hub.use_control_head) { BX_OHCI_THIS hub.op_regs.HcControlCurrentED = 0; BX_OHCI_THIS hub.use_control_head = 0; } if (!BX_OHCI_THIS hub.op_regs.HcControlCurrentED && BX_OHCI_THIS hub.op_regs.HcCommandStatus.clf) { BX_OHCI_THIS hub.op_regs.HcControlCurrentED = BX_OHCI_THIS hub.op_regs.HcControlHeadED; BX_OHCI_THIS hub.op_regs.HcCommandStatus.clf = 0; } while (BX_OHCI_THIS hub.op_regs.HcControlCurrentED) { DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcControlCurrentED, 4, (Bit8u*) &cur_ed.dword0); DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcControlCurrentED + 4, 4, (Bit8u*) &cur_ed.dword1); DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcControlCurrentED + 8, 4, (Bit8u*) &cur_ed.dword2); DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcControlCurrentED + 12, 4, (Bit8u*) &cur_ed.dword3); process_ed(&cur_ed, BX_OHCI_THIS hub.op_regs.HcControlCurrentED); BX_OHCI_THIS hub.op_regs.HcControlCurrentED = ED_GET_NEXTED(&cur_ed); if (get_frame_remaining() < 8000) goto do_bulk_eds; } } do_bulk_eds: // if the bulk list is enabled *and* the bulk list filled bit is set, do a bulk list ED if (BX_OHCI_THIS hub.op_regs.HcControl.ble) { if (BX_OHCI_THIS hub.use_bulk_head) { BX_OHCI_THIS hub.op_regs.HcBulkCurrentED = 0; BX_OHCI_THIS hub.use_bulk_head = 0; } if (!BX_OHCI_THIS hub.op_regs.HcBulkCurrentED && BX_OHCI_THIS hub.op_regs.HcCommandStatus.blf) { BX_OHCI_THIS hub.op_regs.HcBulkCurrentED = BX_OHCI_THIS hub.op_regs.HcBulkHeadED; BX_OHCI_THIS hub.op_regs.HcCommandStatus.blf = 0; } while (BX_OHCI_THIS hub.op_regs.HcBulkCurrentED) { DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcBulkCurrentED, 4, (Bit8u*) &cur_ed.dword0); DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcBulkCurrentED + 4, 4, (Bit8u*) &cur_ed.dword1); DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcBulkCurrentED + 8, 4, (Bit8u*) &cur_ed.dword2); DEV_MEM_READ_PHYSICAL(BX_OHCI_THIS hub.op_regs.HcBulkCurrentED + 12, 4, (Bit8u*) &cur_ed.dword3); process_ed(&cur_ed, BX_OHCI_THIS hub.op_regs.HcBulkCurrentED); BX_OHCI_THIS hub.op_regs.HcBulkCurrentED = ED_GET_NEXTED(&cur_ed); if (get_frame_remaining() < 4000) goto do_iso_eds; } } do_iso_eds: // do the ED's in the interrupt table if (BX_OHCI_THIS hub.op_regs.HcControl.ple) { address = BX_OHCI_THIS hub.op_regs.HcHCCA + ((BX_OHCI_THIS hub.op_regs.HcFmNumber & 0x1F) * 4); DEV_MEM_READ_PHYSICAL(address, 4, (Bit8u*) &ed_address); while (ed_address) { DEV_MEM_READ_PHYSICAL(ed_address, 4, (Bit8u*) &cur_ed.dword0); DEV_MEM_READ_PHYSICAL(ed_address + 4, 4, (Bit8u*) &cur_ed.dword1); DEV_MEM_READ_PHYSICAL(ed_address + 8, 4, (Bit8u*) &cur_ed.dword2); DEV_MEM_READ_PHYSICAL(ed_address + 12, 4, (Bit8u*) &cur_ed.dword3); process_ed(&cur_ed, ed_address); ed_address = ED_GET_NEXTED(&cur_ed); } } } // end run schedule } void bx_usb_ohci_c::process_ed(struct OHCI_ED *ed, const Bit32u ed_address) { struct OHCI_TD cur_td; if (!ED_GET_H(ed) && !ED_GET_K(ed) && (ED_GET_HEADP(ed) != ED_GET_TAILP(ed))) { // if the isochronous is enabled and ed is a isochronous, do TD if (ED_GET_F(ed)) { if (BX_OHCI_THIS hub.op_regs.HcControl.ie) { // load and do a isochronous TD list BX_DEBUG(("Found a valid ED that points to an isochronous TD")); // we currently ignore ISO TD's } } else { BX_DEBUG(("Found a valid ED that points to an control/bulk/int TD")); while (ED_GET_HEADP(ed) != ED_GET_TAILP(ed)) { DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed), 4, (Bit8u*) &cur_td.dword0); DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed) + 4, 4, (Bit8u*) &cur_td.dword1); DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed) + 8, 4, (Bit8u*) &cur_td.dword2); DEV_MEM_READ_PHYSICAL(ED_GET_HEADP(ed) + 12, 4, (Bit8u*) &cur_td.dword3); BX_DEBUG(("Head: 0x%08X Tail: 0x%08X Next: 0x%08X", ED_GET_HEADP(ed), ED_GET_TAILP(ed), TD_GET_NEXTTD(&cur_td))); if (process_td(&cur_td, ed)) { const Bit32u temp = ED_GET_HEADP(ed); if (TD_GET_CC(&cur_td) < NotAccessed) { ED_SET_HEADP(ed, TD_GET_NEXTTD(&cur_td)); TD_SET_NEXTTD(&cur_td, BX_OHCI_THIS hub.op_regs.HcDoneHead); BX_OHCI_THIS hub.op_regs.HcDoneHead = temp; if (TD_GET_DI(&cur_td) < BX_OHCI_THIS hub.ohci_done_count) BX_OHCI_THIS hub.ohci_done_count = TD_GET_DI(&cur_td); } DEV_MEM_WRITE_PHYSICAL(temp, 4, (Bit8u*) &cur_td.dword0); DEV_MEM_WRITE_PHYSICAL(temp + 4, 4, (Bit8u*) &cur_td.dword1); DEV_MEM_WRITE_PHYSICAL(temp + 8, 4, (Bit8u*) &cur_td.dword2); } else break; } } DEV_MEM_WRITE_PHYSICAL(ed_address + 8, 4, (Bit8u*) &ed->dword2); } } bx_bool bx_usb_ohci_c::process_td(struct OHCI_TD *td, struct OHCI_ED *ed) { unsigned pid = 0, len = 0, len1, len2; int r, ret = 0; char buf_str[1025], temp_str[17]; // The td->cc field should be 111x if it hasn't been processed yet. if (TD_GET_CC(td) < NotAccessed) { BX_ERROR(("Found TD with CC value not 111x")); return 0; } if (ED_GET_D(ed) == 1) pid = USB_TOKEN_OUT; else if (ED_GET_D(ed) == 2) pid = USB_TOKEN_IN; else { if (TD_GET_DP(td) == 0) pid = USB_TOKEN_SETUP; else if (TD_GET_DP(td) == 1) pid = USB_TOKEN_OUT; else if (TD_GET_DP(td) == 2) pid = USB_TOKEN_IN; } // calculate the length of the packet if (TD_GET_CBP(td) && TD_GET_BE(td)) { if ((TD_GET_CBP(td) & 0xFFFFF000) != (TD_GET_BE(td) & 0xFFFFF000)) len = (TD_GET_BE(td) & 0xFFF) + 0x1001 - (TD_GET_CBP(td) & 0xFFF); else { len = (TD_GET_BE(td) - TD_GET_CBP(td)) + 1; if (len < 0) len = 0x1001 + len; } } else len = 0; BX_OHCI_THIS usb_packet.pid = pid; BX_OHCI_THIS usb_packet.devaddr = ED_GET_FA(ed); BX_OHCI_THIS usb_packet.devep = ED_GET_EN(ed); BX_OHCI_THIS usb_packet.data = BX_OHCI_THIS device_buffer; switch (pid) { case USB_TOKEN_SETUP: case USB_TOKEN_OUT: BX_OHCI_THIS usb_packet.len = (len <= ED_GET_MPS(ed)) ? len : ED_GET_MPS(ed); break; case USB_TOKEN_IN: BX_OHCI_THIS usb_packet.len = len; break; } BX_DEBUG((" pid = %s addr = %i endpnt = %i len = %i mps = %i (td->cbp = 0x%08X, td->be = 0x%08X)", (pid == USB_TOKEN_IN)? "IN" : (pid == USB_TOKEN_OUT) ? "OUT" : (pid == USB_TOKEN_SETUP) ? "SETUP" : "UNKNOWN", ED_GET_FA(ed), ED_GET_EN(ed), len, ED_GET_MPS(ed), TD_GET_CBP(td), TD_GET_BE(td))); BX_DEBUG((" td->t = %i ed->c = %i td->di = %i td->r = %i", TD_GET_T(td), ED_GET_C(ed), TD_GET_DI(td), TD_GET_R(td))); /* set status bar conditions for device */ if ((len > 0) && (BX_OHCI_THIS hub.statusbar_id >= 0)) { if (pid == USB_TOKEN_IN) bx_gui->statusbar_setitem(BX_OHCI_THIS hub.statusbar_id, 1); // read else bx_gui->statusbar_setitem(BX_OHCI_THIS hub.statusbar_id, 1, 1); // write } switch (pid) { case USB_TOKEN_SETUP: if (len > 0) DEV_MEM_READ_PHYSICAL_DMA(TD_GET_CBP(td), len, device_buffer); // TODO: This is a hack. dev->handle_packet() should return the amount of bytes // it received, not the amount it anticipates on receiving/sending in the next packet. if ((ret = BX_OHCI_THIS broadcast_packet(&BX_OHCI_THIS usb_packet)) >= 0) ret = 8; break; case USB_TOKEN_OUT: if (len > 0) DEV_MEM_READ_PHYSICAL_DMA(TD_GET_CBP(td), len, device_buffer); ret = BX_OHCI_THIS broadcast_packet(&BX_OHCI_THIS usb_packet); break; case USB_TOKEN_IN: ret = BX_OHCI_THIS broadcast_packet(&BX_OHCI_THIS usb_packet); if (ret > 0) { if (((TD_GET_CBP(td) & 0xfff) + ret) > 0x1000) { len1 = 0x1000 - (TD_GET_CBP(td) & 0xfff); len2 = ret - len1; DEV_MEM_WRITE_PHYSICAL_DMA(TD_GET_CBP(td), len1, device_buffer); DEV_MEM_WRITE_PHYSICAL_DMA((TD_GET_BE(td) & ~0xfff), len2, device_buffer+len1); } else { DEV_MEM_WRITE_PHYSICAL_DMA(TD_GET_CBP(td), ret, device_buffer); } } else ret = 0; break; default: TD_SET_CC(td, UnexpectedPID); TD_SET_EC(td, 3); return 1; } // print the buffer used, to the log file if (ret > 0) { BX_DEBUG(("buffer dump (%i bytes)", ret)); buf_str[0] = 0; for (r=0; r 0) BX_DEBUG(("%s", buf_str)); } if ((ret == (int)len) || ((pid == USB_TOKEN_IN) && (ret >= 0) && TD_GET_R(td)) || ((pid == USB_TOKEN_OUT) && (ret >= 0) && (ret <= (int) ED_GET_MPS(ed)))) { if (ret == (int)len) TD_SET_CBP(td, 0); else { if (((TD_GET_CBP(td) & 0xfff) + ret) >= 0x1000) { TD_SET_CBP(td, (TD_GET_CBP(td) + ret) & 0x0FFF); TD_SET_CBP(td, TD_GET_CBP(td) | (TD_GET_BE(td) & ~0x0FFF)); } else { TD_SET_CBP(td, TD_GET_CBP(td) + ret); } } if (TD_GET_T(td) & 2) { TD_SET_T(td, TD_GET_T(td) ^ 1); ED_SET_C(ed, (TD_GET_T(td) & 1)); } else ED_SET_C(ed, (ED_GET_C(ed) ^ 1)); if ((pid != USB_TOKEN_OUT) || (ret == (int)len)) { TD_SET_CC(td, NoError); TD_SET_EC(td, 0); } } else { if (ret >= 0) TD_SET_CC(td, DataUnderrun); else { switch (ret) { case USB_RET_NODEV: // (-1) TD_SET_CC(td, DeviceNotResponding); break; case USB_RET_NAK: // (-2) TD_SET_CC(td, Stall); break; case USB_RET_STALL: // (-3) TD_SET_CC(td, Stall); break; case USB_RET_BABBLE: // (-4) TD_SET_CC(td, BufferOverrun); break; case USB_RET_ASYNC: // (-5) TD_SET_CC(td, BufferOverrun); break; default: BX_ERROR(("Unknown error returned: %i", ret)); break; } } TD_SET_EC(td, 3); ED_SET_H(ed, 1); } BX_DEBUG((" td->cbp = 0x%08X ret = %i len = %i td->cc = %i td->ec = %i ed->h = %i", TD_GET_CBP(td), ret, len, TD_GET_CC(td), TD_GET_EC(td), ED_GET_H(ed))); BX_DEBUG((" td->t = %i ed->c = %i", TD_GET_T(td), ED_GET_C(ed))); return 1; } int bx_usb_ohci_c::broadcast_packet(USBPacket *p) { int i, ret; ret = USB_RET_NODEV; for (i = 0; i < BX_N_USB_OHCI_PORTS && ret == USB_RET_NODEV; i++) { if ((BX_OHCI_THIS hub.usb_port[i].device != NULL) && (BX_OHCI_THIS hub.usb_port[i].HcRhPortStatus.ccs)) { ret = BX_OHCI_THIS hub.usb_port[i].device->handle_packet(p); } } return ret; } void bx_usb_ohci_c::runtime_config_handler(void *this_ptr) { bx_usb_ohci_c *class_ptr = (bx_usb_ohci_c *) this_ptr; class_ptr->runtime_config(); } void bx_usb_ohci_c::runtime_config(void) { int i; char pname[6]; for (i = 0; i < BX_N_USB_OHCI_PORTS; i++) { // device change support if ((BX_OHCI_THIS hub.device_change & (1 << i)) != 0) { BX_INFO(("USB port #%d: device connect", i+1)); sprintf(pname, "port%d", i + 1); init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_OHCI))); BX_OHCI_THIS hub.device_change &= ~(1 << i); } // forward to connected device if (BX_OHCI_THIS hub.usb_port[i].device != NULL) { BX_OHCI_THIS hub.usb_port[i].device->runtime_config(); } } } // pci configuration space read callback handler Bit32u bx_usb_ohci_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x14) && (address <= 0x34))) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_OHCI_THIS pci_conf[address+i]; switch (address+i) { case 0x04: value8 &= 0x06; // (bit 0 is read only for this card) (we don't allow port IO) BX_OHCI_THIS pci_conf[address+i] = value8; break; case 0x3d: // case 0x3e: // case 0x3f: // case 0x05: // disallowing write to command hi-byte case 0x06: // disallowing write to status lo-byte (is that expected?) break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); BX_OHCI_THIS pci_conf[address+i] = value8; } break; case 0x10: // low 12 bits of BAR are R/O value8 = 0x00; case 0x11: // low 12 bits of BAR are R/O value8 &= 0xF0; case 0x12: case 0x13: baseaddr_change |= (value8 != oldval); default: BX_OHCI_THIS pci_conf[address+i] = value8; } } if (baseaddr_change) { if (DEV_pci_set_base_mem(BX_OHCI_THIS_PTR, read_handler, write_handler, &BX_OHCI_THIS pci_base_address[0], &BX_OHCI_THIS pci_conf[0x10], 4096)) { BX_INFO(("new base address: 0x%04x", BX_OHCI_THIS pci_base_address[0])); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } void bx_usb_ohci_c::usb_set_connect_status(Bit8u port, int type, bx_bool connected) { const bx_bool ccs_org = BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs; const bx_bool pes_org = BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pes; usb_device_c *device = BX_OHCI_THIS hub.usb_port[port].device; if (device != NULL) { if (device->get_type() == type) { if (connected) { BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = (device->get_speed() == USB_SPEED_LOW); BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs = 1; if (!device->get_connected()) { if (!device->init()) { usb_set_connect_status(port, type, 0); BX_ERROR(("port #%d: connect failed", port+1)); } else { BX_INFO(("port #%d: connect: %s", port+1, device->get_info())); } } } else { // not connected BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs = 0; BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pes = 0; BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.lsda = 0; remove_device(port); } } BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.csc |= (ccs_org != BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.ccs); BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pesc |= (pes_org != BX_OHCI_THIS hub.usb_port[port].HcRhPortStatus.pes); // we changed the value of the port, so show it set_interrupt(OHCI_INTR_RHSC); } } // USB runtime parameter handler const char *bx_usb_ohci_c::usb_param_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { usbdev_type type = USB_DEV_TYPE_NONE; int portnum; if (set) { portnum = atoi((param->get_parent())->get_name()+4) - 1; bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none"))); if ((portnum >= 0) && (portnum < BX_N_USB_OHCI_PORTS)) { if (empty && BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.ccs) { BX_INFO(("USB port #%d: device disconnect", portnum+1)); if (BX_OHCI_THIS hub.usb_port[portnum].device != NULL) { type = BX_OHCI_THIS hub.usb_port[portnum].device->get_type(); } usb_set_connect_status(portnum, type, 0); } else if (!empty && !BX_OHCI_THIS hub.usb_port[portnum].HcRhPortStatus.ccs) { BX_OHCI_THIS hub.device_change |= (1 << portnum); } } else { BX_PANIC(("usb_param_handler called with unexpected parameter '%s'", param->get_name())); } } return val; } #endif // BX_SUPPORT_PCI && BX_SUPPORT_USB_OHCI bochs-2.6/iodev/usb/usb_xhci.cc0000644000175000017500000040057012020641504016347 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_xhci.cc 11346 2012-08-19 08:16:20Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2010-2011 Benjamin D Lunt (fys [at] fysnet [dot] net) // 2011-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Experimental USB xHCI adapter // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE /* Notes: * bochsrc.txt line: #usb_xhci: enabled=1, port3=keypad * port1 & 2 are USB3, while port3 & 4 are USB2 * * This code *should* be 64-bit addressing aware (uses: bx_phy_address & ADDR_CAP_64) * * * * This emulation is experimental. It is not completly accorate, though it is * my intention to make it as close as possible. If you find an error or would * like to add to the emulation, please let me know at fys [at] fysnet [dot] net. * * * */ #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_USB_XHCI #include "pci.h" #include "usb_common.h" #include "usb_xhci.h" #define LOG_THIS theUSB_XHCI-> bx_usb_xhci_c* theUSB_XHCI = NULL; Bit8u port_speed_allowed[USB_XHCI_PORTS] = { USB3, USB3, USB2, USB2 }; Bit8u ext_caps[EXT_CAPS_SIZE] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x03, 0x55, 0x53, 0x42, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x55, 0x53, 0x42, 0x20, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Bit8u port_band_width[4][1 + USB_XHCI_PORTS] = { { 0x00, 0x00, 0x00, 0x5A, 0x5A }, // 90% { 0x00, 0x00, 0x00, 0x5A, 0x5A }, // 90% { 0x00, 0x00, 0x00, 0x50, 0x50 }, // 80% { 0x00, 0x5A, 0x5A, 0x00, 0x00 } // 90% }; // builtin configuration handling functions Bit32s usb_xhci_options_parser(const char *context, int num_params, char *params[]) { if (!strcmp(params[0], "usb_xhci")) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_USB_XHCI); for (int i = 1; i < num_params; i++) { if (!strncmp(params[i], "enabled=", 8)) { SIM->get_param_bool(BXPN_XHCI_ENABLED)->set(atol(¶ms[i][8])); } else if (!strncmp(params[i], "port", 4)) { if (SIM->parse_usb_port_params(context, 0, params[i], BX_N_USB_XHCI_PORTS, base) < 0) { return -1; } } else if (!strncmp(params[i], "options", 7)) { if (SIM->parse_usb_port_params(context, 1, params[i], BX_N_USB_XHCI_PORTS, base) < 0) { return -1; } } else { BX_ERROR(("%s: unknown parameter '%s' for usb_xhci ignored.", context, params[i])); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s usb_xhci_options_save(FILE *fp) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_USB_XHCI); SIM->write_usb_options(fp, BX_N_USB_XHCI_PORTS, base); return 0; } // device plugin entry points int libusb_xhci_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theUSB_XHCI = new bx_usb_xhci_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUSB_XHCI, BX_PLUGIN_USB_XHCI); // add new configuration parameter for the config interface SIM->init_usb_options("xHCI", "xhci", BX_N_USB_XHCI_PORTS); // register add-on option for bochsrc and command line SIM->register_addon_option("usb_xhci", usb_xhci_options_parser, usb_xhci_options_save); return 0; // Success } void libusb_xhci_LTX_plugin_fini(void) { SIM->unregister_addon_option("usb_xhci"); bx_list_c *menu = (bx_list_c*)SIM->get_param("ports.usb"); delete theUSB_XHCI; menu->remove("xhci"); } // the device object bx_usb_xhci_c::bx_usb_xhci_c() { put("usb_xhci", "XHCI"); memset((void*)&hub, 0, sizeof(bx_usb_xhci_t)); device_buffer = NULL; //hub.frame_timer_index = BX_NULL_TIMER_HANDLE; } bx_usb_xhci_c::~bx_usb_xhci_c() { char pname[16]; if (BX_XHCI_THIS device_buffer != NULL) delete [] BX_XHCI_THIS device_buffer; for (int i=0; iget_param_string(pname, SIM->get_param(BXPN_USB_XHCI))->set_handler(NULL); remove_device(i); } SIM->get_bochs_root()->remove("usb_xhci"); BX_DEBUG(("Exit")); } void bx_usb_xhci_c::init(void) { unsigned i; char pname[6]; bx_list_c *xhci, *port; bx_param_string_c *device, *options; // Read in values from config interface xhci = (bx_list_c*) SIM->get_param(BXPN_USB_XHCI); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", xhci)->get()) { BX_INFO(("USB xHCI disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("usb_xhci"))->set(0); return; } BX_XHCI_THIS device_buffer = new Bit8u[65536]; // TODO: Use this to decrement the Interrupter:count down value // Call our frame timer routine every 1mS (1,000uS) // Continuous and active // BX_XHCI_THIS hub.frame_timer_index = // bx_pc_system.register_timer(this, usb_frame_handler, 1000, 1,1, "xhci.frame_timer"); BX_XHCI_THIS hub.devfunc = 0x00; DEV_register_pci_handlers(this, &BX_XHCI_THIS hub.devfunc, BX_PLUGIN_USB_XHCI, "Experimental USB xHCI"); for (i=0; i<256; i++) BX_XHCI_THIS pci_conf[i] = 0x0; BX_XHCI_THIS pci_base_address[0] = 0x0; //FIXME: for now, we want a status bar // hub zero, port zero BX_XHCI_THIS hub.statusbar_id = bx_gui->register_statusitem("xHCI", 1); bx_list_c *usb_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_USB); xhci->set_options(xhci->SHOW_PARENT | xhci->USE_BOX_TITLE); xhci->set_runtime_param(1); usb_rt->add(xhci); for (i=0; iget_param(pname, xhci); port->set_runtime_param(1); device = (bx_param_string_c*)port->get_by_name("device"); device->set_handler(usb_param_handler); device->set_runtime_param(1); options = (bx_param_string_c*)port->get_by_name("options"); options->set_runtime_param(1); BX_XHCI_THIS hub.usb_port[i].device = NULL; BX_XHCI_THIS hub.usb_port[i].portsc.ccs = 0; BX_XHCI_THIS hub.usb_port[i].portsc.csc = 0; } // register handler for correct device connect handling after runtime config SIM->register_runtime_config_handler(BX_XHCI_THIS_PTR, runtime_config_handler); BX_XHCI_THIS hub.device_change = 0; BX_INFO(("USB xHCI initialized")); } void bx_usb_xhci_c::reset(unsigned type) { unsigned i; if (type == BX_RESET_HARDWARE) { static const struct reset_vals_t { unsigned addr; unsigned char val; } reset_vals[] = { { 0x00, 0x33 }, { 0x01, 0x10 }, // 0x1033 = vendor // TODO: Change the VendorID and DeviceID to something else ???? { 0x02, 0x94 }, { 0x03, 0x01 }, // 0x0194 = device { 0x04, 0x06 }, { 0x05, 0x01 }, // command_io { 0x06, 0x10 }, { 0x07, 0x00 }, // status (has caps list) { 0x08, 0x03 }, // revision number = 0x03 { 0x09, 0x30 }, // interface { 0x0A, 0x03 }, // class_sub USB Host Controller { 0x0B, 0x0C }, // class_base Serial Bus Controller { 0x0C, 0x10 }, // cache line size { 0x0D, 0x00 }, // bus latency { 0x0E, 0x00 }, // header_type_generic // address space 0x10 - 0x13 { 0x10, 0x04 }, { 0x11, 0x00 }, // { 0x12, 0x50 }, { 0x13, 0xF0 }, // { 0x2C, 0xFF }, { 0x2D, 0xFF }, // subsystem vendor ID { 0x2E, 0xFF }, { 0x2F, 0xFF }, // subsystem ID { 0x34, 0x50 }, // offset of capabilities list within configuration space { 0x3C, 0x0A }, // IRQ { 0x3D, BX_PCI_INTD }, // INT { 0x3E, 0x00 }, // minimum time bus master needs PCI bus ownership, in 250ns units { 0x3F, 0x00 }, // maximum latency, in 250ns units (bus masters only) (read-only) // capabilities list: { 0x50, 0x01 }, // PCI Power Management { 0x51, 0x00 }, // Pointer to next item (0x00 = no more) { 0x52, 0x03 }, { 0x53, 0x48 }, // Capabilities: version = 1.2, self powered, PME# asserted from D0 & D3 { 0x54, 0x08 }, { 0x55, 0x00 }, // Status: Bit 3 = no soft reset { 0x60, 0x30 }, // { 0x61, 0x20 } // }; for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); i++) { BX_XHCI_THIS pci_conf[reset_vals[i].addr] = reset_vals[i].val; } } BX_XHCI_THIS reset_hc(); } void bx_usb_xhci_c::reset_hc() { int i; char pname[6]; // Capability registers BX_XHCI_THIS hub.cap_regs.HcCapLength = (VERSION_MAJOR << 24) | (VERSION_MINOR << 16) | OPS_REGS_OFFSET; BX_XHCI_THIS hub.cap_regs.HcSParams1 = (USB_XHCI_PORTS << 24) | (INTERRUPTERS << 8) | MAX_SLOTS; BX_XHCI_THIS hub.cap_regs.HcSParams2 = // MAX_SCRATCH_PADS 4:0 in bits 31:27 (v1.00) and bits 9:5 in bits 21:25 (v1.01) ((MAX_SCRATCH_PADS >> 5) << 21) | ((MAX_SCRATCH_PADS & 0x1F) << 27) | ((SCATCH_PAD_RESTORE == 1) << 26) | (MAX_SEG_TBL_SZ_EXP << 4) | ISO_SECH_THRESHOLD; BX_XHCI_THIS hub.cap_regs.HcSParams3 = (U2_DEVICE_EXIT_LAT << 16) | U1_DEVICE_EXIT_LAT; BX_XHCI_THIS hub.cap_regs.HcCParams = ((EXT_CAPS_OFFSET >> 2) << 16) | (MAX_PSA_SIZE << 12) | (SEC_DOMAIN_BAND << 9) | (FORCED_STOPPED << 8) | (LIGHT_HC_RESET << 5) | (PORT_INDICATORS << 4) | (PORT_POWER_CTRL << 3) | ((CONTEXT_SIZE >> 6) << 2) | (BW_NEGOTIATION << 1) | ADDR_CAP_64; BX_XHCI_THIS hub.cap_regs.DBOFF = DOORBELL_OFFSET; // at offset DOORBELL_OFFSET from base BX_XHCI_THIS hub.cap_regs.RTSOFF = RUNTIME_OFFSET; // at offset RUNTIME_OFFSET from base BX_DEBUG((" CAPLENGTH: 0x%02X", BX_XHCI_THIS hub.cap_regs.HcCapLength & 0xFF)); BX_DEBUG(("HC VERSION: %X.%02X", ((BX_XHCI_THIS hub.cap_regs.HcCapLength & 0xFF000000) >> 24), ((BX_XHCI_THIS hub.cap_regs.HcCapLength & 0x00FF0000) >> 16))); BX_DEBUG(("HCSPARAMS1: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcSParams1)); BX_DEBUG(("HCSPARAMS2: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcSParams2)); BX_DEBUG(("HCSPARAMS3: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcSParams3)); BX_DEBUG((" HCCPARAMS: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcCParams)); BX_DEBUG((" DBOFF: 0x%08X", BX_XHCI_THIS hub.cap_regs.DBOFF)); BX_DEBUG((" RTSOFF: 0x%08X", BX_XHCI_THIS hub.cap_regs.RTSOFF)); // Command BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP1 = 0; BX_XHCI_THIS hub.op_regs.HcCommand.eu3s = 0; BX_XHCI_THIS hub.op_regs.HcCommand.ewe = 0; BX_XHCI_THIS hub.op_regs.HcCommand.crs = 0; BX_XHCI_THIS hub.op_regs.HcCommand.css = 0; BX_XHCI_THIS hub.op_regs.HcCommand.lhcrst = 0; BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP0 = 0; BX_XHCI_THIS hub.op_regs.HcCommand.hsee = 0; BX_XHCI_THIS hub.op_regs.HcCommand.inte = 0; BX_XHCI_THIS hub.op_regs.HcCommand.hcrst = 0; BX_XHCI_THIS hub.op_regs.HcCommand.rs = 0; // Status BX_XHCI_THIS hub.op_regs.HcStatus.RsvdZ1 = 0; BX_XHCI_THIS hub.op_regs.HcStatus.hce = 0; BX_XHCI_THIS hub.op_regs.HcStatus.cnr = 0; BX_XHCI_THIS hub.op_regs.HcStatus.sre = 0; BX_XHCI_THIS hub.op_regs.HcStatus.rss = 0; BX_XHCI_THIS hub.op_regs.HcStatus.sss = 0; BX_XHCI_THIS hub.op_regs.HcStatus.RsvdZ0 = 0; BX_XHCI_THIS hub.op_regs.HcStatus.pcd = 0; BX_XHCI_THIS hub.op_regs.HcStatus.eint = 0; BX_XHCI_THIS hub.op_regs.HcStatus.hse = 0; BX_XHCI_THIS hub.op_regs.HcStatus.RsvdZ2 = 0; BX_XHCI_THIS hub.op_regs.HcStatus.hch = 1; // Page Size BX_XHCI_THIS hub.op_regs.HcPageSize.pagesize = PAGE_SIZE; // Device Notification Control Register BX_XHCI_THIS hub.op_regs.HcNotification.RsvdP = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n15 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n14 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n13 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n12 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n11 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n10 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n9 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n8 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n7 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n6 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n5 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n4 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n3 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n2 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n1 = 0; BX_XHCI_THIS hub.op_regs.HcNotification.n0 = 0; // Command Ring Control Register BX_XHCI_THIS hub.op_regs.HcCrcr.crc = 0; BX_XHCI_THIS hub.op_regs.HcCrcr.RsvdP = 0; BX_XHCI_THIS hub.op_regs.HcCrcr.crr = 0; BX_XHCI_THIS hub.op_regs.HcCrcr.ca = 0; BX_XHCI_THIS hub.op_regs.HcCrcr.cs = 0; BX_XHCI_THIS hub.op_regs.HcCrcr.rcs = 0; // DCBAAP BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap = 0; // Config BX_XHCI_THIS hub.op_regs.HcConfig.RsvdP = 0; BX_XHCI_THIS hub.op_regs.HcConfig.MaxSlotsEn = 0; // Ports[x] for (i=0; iget_param(pname, SIM->get_param(BXPN_USB_XHCI))); } else { usb_set_connect_status(i, BX_XHCI_THIS hub.usb_port[i].device->get_type(), 1); } } // first half are USB3 ports, second half are USB2 ports for (i=0; i<(USB_XHCI_PORTS / 2); i++) { BX_XHCI_THIS hub.usb_port[i].is_usb3 = 1; BX_XHCI_THIS hub.usb_port[i + (USB_XHCI_PORTS / 2)].is_usb3 = 0; } // Extended Caps for (i=0; iget_bochs_root(), "usb_xhci", "USB xHCI State"); hub = new bx_list_c(list, "hub"); reg_grp = new bx_list_c(hub, "cap_regs"); new bx_shadow_num_c(reg_grp, "HcCapLength", &BX_XHCI_THIS hub.cap_regs.HcCapLength, BASE_HEX); new bx_shadow_num_c(reg_grp, "HcSParams1", &BX_XHCI_THIS hub.cap_regs.HcSParams1, BASE_HEX); new bx_shadow_num_c(reg_grp, "HcSParams2", &BX_XHCI_THIS hub.cap_regs.HcSParams2, BASE_HEX); new bx_shadow_num_c(reg_grp, "HcSParams3", &BX_XHCI_THIS hub.cap_regs.HcSParams3, BASE_HEX); new bx_shadow_num_c(reg_grp, "HcCParams", &BX_XHCI_THIS hub.cap_regs.HcCParams, BASE_HEX); new bx_shadow_num_c(reg_grp, "DBOFF", &BX_XHCI_THIS hub.cap_regs.DBOFF, BASE_HEX); new bx_shadow_num_c(reg_grp, "RTSOFF", &BX_XHCI_THIS hub.cap_regs.RTSOFF, BASE_HEX); reg_grp = new bx_list_c(hub, "op_regs"); reg = new bx_list_c(reg_grp, "HcCommand"); new bx_shadow_bool_c(reg, "eu3s", &BX_XHCI_THIS hub.op_regs.HcCommand.eu3s); new bx_shadow_bool_c(reg, "ewe", &BX_XHCI_THIS hub.op_regs.HcCommand.ewe); new bx_shadow_bool_c(reg, "crs", &BX_XHCI_THIS hub.op_regs.HcCommand.crs); new bx_shadow_bool_c(reg, "css", &BX_XHCI_THIS hub.op_regs.HcCommand.css); new bx_shadow_bool_c(reg, "lhcrst", &BX_XHCI_THIS hub.op_regs.HcCommand.lhcrst); new bx_shadow_bool_c(reg, "hsee", &BX_XHCI_THIS hub.op_regs.HcCommand.hsee); new bx_shadow_bool_c(reg, "inte", &BX_XHCI_THIS hub.op_regs.HcCommand.inte); new bx_shadow_bool_c(reg, "hcrst", &BX_XHCI_THIS hub.op_regs.HcCommand.hcrst); new bx_shadow_bool_c(reg, "rs", &BX_XHCI_THIS hub.op_regs.HcCommand.rs); reg = new bx_list_c(reg_grp, "HcStatus"); new bx_shadow_bool_c(reg, "hce", &BX_XHCI_THIS hub.op_regs.HcStatus.hce); new bx_shadow_bool_c(reg, "cnr", &BX_XHCI_THIS hub.op_regs.HcStatus.cnr); new bx_shadow_bool_c(reg, "sre", &BX_XHCI_THIS hub.op_regs.HcStatus.sre); new bx_shadow_bool_c(reg, "rss", &BX_XHCI_THIS hub.op_regs.HcStatus.rss); new bx_shadow_bool_c(reg, "sss", &BX_XHCI_THIS hub.op_regs.HcStatus.sss); new bx_shadow_bool_c(reg, "pcd", &BX_XHCI_THIS hub.op_regs.HcStatus.pcd); new bx_shadow_bool_c(reg, "eint", &BX_XHCI_THIS hub.op_regs.HcStatus.eint); new bx_shadow_bool_c(reg, "hse", &BX_XHCI_THIS hub.op_regs.HcStatus.hse); new bx_shadow_bool_c(reg, "hch", &BX_XHCI_THIS hub.op_regs.HcStatus.hch); new bx_shadow_num_c(reg_grp, "HcPageSize", &BX_XHCI_THIS hub.op_regs.HcPageSize.pagesize, BASE_HEX); reg = new bx_list_c(reg_grp, "HcNotification"); new bx_shadow_bool_c(reg, "n15", &BX_XHCI_THIS hub.op_regs.HcNotification.n15); new bx_shadow_bool_c(reg, "n14", &BX_XHCI_THIS hub.op_regs.HcNotification.n14); new bx_shadow_bool_c(reg, "n13", &BX_XHCI_THIS hub.op_regs.HcNotification.n13); new bx_shadow_bool_c(reg, "n12", &BX_XHCI_THIS hub.op_regs.HcNotification.n12); new bx_shadow_bool_c(reg, "n11", &BX_XHCI_THIS hub.op_regs.HcNotification.n11); new bx_shadow_bool_c(reg, "n10", &BX_XHCI_THIS hub.op_regs.HcNotification.n10); new bx_shadow_bool_c(reg, "n9", &BX_XHCI_THIS hub.op_regs.HcNotification.n9); new bx_shadow_bool_c(reg, "n8", &BX_XHCI_THIS hub.op_regs.HcNotification.n8); new bx_shadow_bool_c(reg, "n7", &BX_XHCI_THIS hub.op_regs.HcNotification.n7); new bx_shadow_bool_c(reg, "n6", &BX_XHCI_THIS hub.op_regs.HcNotification.n6); new bx_shadow_bool_c(reg, "n5", &BX_XHCI_THIS hub.op_regs.HcNotification.n5); new bx_shadow_bool_c(reg, "n4", &BX_XHCI_THIS hub.op_regs.HcNotification.n4); new bx_shadow_bool_c(reg, "n3", &BX_XHCI_THIS hub.op_regs.HcNotification.n3); new bx_shadow_bool_c(reg, "n2", &BX_XHCI_THIS hub.op_regs.HcNotification.n2); new bx_shadow_bool_c(reg, "n1", &BX_XHCI_THIS hub.op_regs.HcNotification.n1); new bx_shadow_bool_c(reg, "n0", &BX_XHCI_THIS hub.op_regs.HcNotification.n0); reg = new bx_list_c(reg_grp, "HcCrcr"); new bx_shadow_num_c(reg, "crc", &BX_XHCI_THIS hub.op_regs.HcCrcr.crc, BASE_HEX); new bx_shadow_bool_c(reg, "crr", &BX_XHCI_THIS hub.op_regs.HcCrcr.crr); new bx_shadow_bool_c(reg, "ca", &BX_XHCI_THIS hub.op_regs.HcCrcr.ca); new bx_shadow_bool_c(reg, "cs", &BX_XHCI_THIS hub.op_regs.HcCrcr.cs); new bx_shadow_bool_c(reg, "rcs", &BX_XHCI_THIS hub.op_regs.HcCrcr.rcs); new bx_shadow_num_c(reg_grp, "HcDCBAAP", &BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap, BASE_HEX); new bx_shadow_num_c(reg_grp, "HcConfig_MaxSlotsEn", &BX_XHCI_THIS hub.op_regs.HcConfig.MaxSlotsEn, BASE_HEX); reg_grp = new bx_list_c(hub, "runtime_regs"); new bx_shadow_num_c(reg_grp, "mfindex", &BX_XHCI_THIS hub.runtime_regs.mfindex.index, BASE_HEX); for (i = 0; i < INTERRUPTERS; i++) { sprintf(tmpname, "interrupter%d", i+1); reg_grp1 = new bx_list_c(reg_grp, tmpname); reg = new bx_list_c(reg_grp1, "iman"); new bx_shadow_bool_c(reg, "ie", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ie); new bx_shadow_bool_c(reg, "ip", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ip); reg = new bx_list_c(reg_grp1, "imod"); new bx_shadow_num_c(reg, "imodc", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodc, BASE_HEX); new bx_shadow_num_c(reg, "imodi", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodi, BASE_HEX); new bx_shadow_num_c(reg_grp1, "erstabsize", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.erstabsize, BASE_HEX); new bx_shadow_num_c(reg_grp1, "erstabadd", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd, BASE_HEX); reg = new bx_list_c(reg_grp1, "erdp"); new bx_shadow_num_c(reg, "eventadd", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd, BASE_HEX); new bx_shadow_bool_c(reg, "ehb", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.ehb); new bx_shadow_num_c(reg, "desi", &BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.desi, BASE_HEX); } for (i = 0; i < USB_XHCI_PORTS; i++) { sprintf(tmpname, "port%d", i+1); port = new bx_list_c(hub, tmpname); new bx_shadow_bool_c(port, "is_usb3", &BX_XHCI_THIS hub.usb_port[i].is_usb3); reg = new bx_list_c(port, "portsc"); new bx_shadow_bool_c(reg, "wpr", &BX_XHCI_THIS hub.usb_port[i].portsc.wpr); new bx_shadow_bool_c(reg, "dr", &BX_XHCI_THIS hub.usb_port[i].portsc.dr); new bx_shadow_bool_c(reg, "woe", &BX_XHCI_THIS hub.usb_port[i].portsc.woe); new bx_shadow_bool_c(reg, "wde", &BX_XHCI_THIS hub.usb_port[i].portsc.wde); new bx_shadow_bool_c(reg, "wce", &BX_XHCI_THIS hub.usb_port[i].portsc.wce); new bx_shadow_bool_c(reg, "cas", &BX_XHCI_THIS hub.usb_port[i].portsc.cas); new bx_shadow_bool_c(reg, "cec", &BX_XHCI_THIS hub.usb_port[i].portsc.cec); new bx_shadow_bool_c(reg, "plc", &BX_XHCI_THIS hub.usb_port[i].portsc.plc); new bx_shadow_bool_c(reg, "prc", &BX_XHCI_THIS hub.usb_port[i].portsc.prc); new bx_shadow_bool_c(reg, "occ", &BX_XHCI_THIS hub.usb_port[i].portsc.occ); new bx_shadow_bool_c(reg, "wrc", &BX_XHCI_THIS hub.usb_port[i].portsc.wrc); new bx_shadow_bool_c(reg, "pec", &BX_XHCI_THIS hub.usb_port[i].portsc.pec); new bx_shadow_bool_c(reg, "csc", &BX_XHCI_THIS hub.usb_port[i].portsc.csc); new bx_shadow_bool_c(reg, "lws", &BX_XHCI_THIS hub.usb_port[i].portsc.lws); new bx_shadow_num_c(reg, "pic", &BX_XHCI_THIS hub.usb_port[i].portsc.pic, BASE_HEX); new bx_shadow_bool_c(reg, "speed", &BX_XHCI_THIS hub.usb_port[i].portsc.speed); new bx_shadow_bool_c(reg, "pp", &BX_XHCI_THIS hub.usb_port[i].portsc.pp); new bx_shadow_num_c(reg, "pls", &BX_XHCI_THIS hub.usb_port[i].portsc.pls, BASE_HEX); new bx_shadow_bool_c(reg, "pr", &BX_XHCI_THIS hub.usb_port[i].portsc.pr); new bx_shadow_bool_c(reg, "oca", &BX_XHCI_THIS hub.usb_port[i].portsc.oca); new bx_shadow_bool_c(reg, "ped", &BX_XHCI_THIS hub.usb_port[i].portsc.ped); new bx_shadow_bool_c(reg, "ccs", &BX_XHCI_THIS hub.usb_port[i].portsc.ccs); // TODO: handle USB2/USB3 cases reg = new bx_list_c(port, "portpmsc"); new bx_shadow_num_c(port, "portli_lec", &BX_XHCI_THIS hub.usb_port[i].usb3.portli.lec, BASE_HEX); reg = new bx_list_c(port, "porthlpmc"); new bx_shadow_num_c(reg, "hirdm", &BX_XHCI_THIS hub.usb_port[i].porthlpmc.hirdm, BASE_HEX); new bx_shadow_num_c(reg, "l1timeout", &BX_XHCI_THIS hub.usb_port[i].porthlpmc.l1timeout, BASE_HEX); new bx_shadow_num_c(reg, "hirdd", &BX_XHCI_THIS hub.usb_port[i].porthlpmc.hirdd, BASE_HEX); // empty list for USB device state new bx_list_c(port, "device"); } register_pci_state(hub); } void bx_usb_xhci_c::after_restore_state(void) { if (DEV_pci_set_base_mem(BX_XHCI_THIS_PTR, read_handler, write_handler, &BX_XHCI_THIS pci_base_address[0], &BX_XHCI_THIS pci_conf[0x10], 4096)) { BX_INFO(("new base address: 0x%04x", BX_XHCI_THIS pci_base_address[0])); } for (int j=0; jafter_restore_state(); } } } void bx_usb_xhci_c::init_device(Bit8u port, bx_list_c *portconf) { usbdev_type type; char pname[BX_PATHNAME_LEN]; const char *devname = NULL; devname = ((bx_param_string_c*)portconf->get_by_name("device"))->getptr(); if (devname == NULL) return; if (!strlen(devname) || !strcmp(devname, "none")) return; if (BX_XHCI_THIS hub.usb_port[port].device != NULL) { BX_ERROR(("init_device(): port%d already in use", port+1)); return; } sprintf(pname, "usb_xhci.hub.port%d.device", port+1); bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root()); type = DEV_usb_init_device(portconf, BX_XHCI_THIS_PTR, &BX_XHCI_THIS hub.usb_port[port].device, sr_list); if (BX_XHCI_THIS hub.usb_port[port].device != NULL) { usb_set_connect_status(port, type, 1); } } void bx_usb_xhci_c::remove_device(Bit8u port) { char pname[BX_PATHNAME_LEN]; if (BX_XHCI_THIS hub.usb_port[port].device != NULL) { delete BX_XHCI_THIS hub.usb_port[port].device; BX_XHCI_THIS hub.usb_port[port].device = NULL; sprintf(pname, "usb_xhci.hub.port%d.device", port+1); bx_list_c *devlist = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root()); if (devlist) devlist->clear(); } } void bx_usb_xhci_c::update_irq(unsigned interrupter) { bx_bool level = 0; if ((BX_XHCI_THIS hub.op_regs.HcCommand.inte) && (BX_XHCI_THIS hub.runtime_regs.interrupter[interrupter].iman.ie)) { level = 1; BX_DEBUG(("Interrupt Fired.")); } DEV_pci_set_irq(BX_XHCI_THIS hub.devfunc, BX_XHCI_THIS pci_conf[0x3d], level); } bx_bool bx_usb_xhci_c::read_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit32u val = 0, val_hi = 0; Bit64u val64; int i; const Bit32u offset = (Bit32u) (addr - BX_XHCI_THIS pci_base_address[0]); // Even though the controller allows reads other than 32-bits & on odd boundaries, // we are going to ASSUME dword reads and writes unless specified below // RO Capability Registers if (offset < OPS_REGS_OFFSET) { switch (offset) { // Capability Registers case 0x00: // CapLength / version val = BX_XHCI_THIS hub.cap_regs.HcCapLength; break; case 0x01: val = BX_XHCI_THIS hub.cap_regs.HcCapLength >> 8; break; case 0x02: val = BX_XHCI_THIS hub.cap_regs.HcCapLength >> 16; break; case 0x04: // HCSPARAMS1 val = BX_XHCI_THIS hub.cap_regs.HcSParams1; break; case 0x08: // HCSPARAMS2 val = BX_XHCI_THIS hub.cap_regs.HcSParams2; break; case 0x0C: // HCSPARAMS3 val = BX_XHCI_THIS hub.cap_regs.HcSParams3; break; case 0x10: // HCCPARAMS val = BX_XHCI_THIS hub.cap_regs.HcCParams; break; case 0x14: // DBOFF val = BX_XHCI_THIS hub.cap_regs.DBOFF; break; case 0x18: // RTSOFF val = BX_XHCI_THIS hub.cap_regs.RTSOFF; break; case 0x1C: // reserved val = 0; break; } } else // Operational Registers if ((offset >= OPS_REGS_OFFSET) && (offset < (OPS_REGS_OFFSET + 0x40))) { switch (offset - OPS_REGS_OFFSET) { case 0x00: // Command val = (BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP1 << 12) | (BX_XHCI_THIS hub.op_regs.HcCommand.eu3s ? 1 << 11 : 0) | (BX_XHCI_THIS hub.op_regs.HcCommand.ewe ? 1 << 10 : 0) | 0 // BX_XHCI_THIS hub.op_regs.HcCommand.crs | 0 // BX_XHCI_THIS hub.op_regs.HcCommand.css | (BX_XHCI_THIS hub.op_regs.HcCommand.lhcrst ? 1 << 7 : 0) | (BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP0 << 4) | (BX_XHCI_THIS hub.op_regs.HcCommand.hsee ? 1 << 3 : 0) | (BX_XHCI_THIS hub.op_regs.HcCommand.inte ? 1 << 2 : 0) | (BX_XHCI_THIS hub.op_regs.HcCommand.hcrst ? 1 << 1 : 0) | (BX_XHCI_THIS hub.op_regs.HcCommand.rs ? 1 << 0 : 0); break; case 0x04: // Status val = (BX_XHCI_THIS hub.op_regs.HcStatus.hce ? 1 << 12 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.cnr ? 1 << 11 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.sre ? 1 << 10 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.rss ? 1 << 9 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.sss ? 1 << 8 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.pcd ? 1 << 4 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.eint ? 1 << 3 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.hse ? 1 << 2 : 0) | (BX_XHCI_THIS hub.op_regs.HcStatus.hch ? 1 << 0 : 0); break; case 0x08: // Page Size val = BX_XHCI_THIS hub.op_regs.HcPageSize.pagesize; break; case 0x0C: // Reserved and Zero'd case 0x10: // Reserved and Zero'd val = 0; break; case 0x14: // Device Notification Control Register val = (BX_XHCI_THIS hub.op_regs.HcNotification.RsvdP << 16) | (BX_XHCI_THIS hub.op_regs.HcNotification.n15 ? 1 << 15 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n14 ? 1 << 14 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n13 ? 1 << 13 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n12 ? 1 << 12 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n11 ? 1 << 11 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n10 ? 1 << 10 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n9 ? 1 << 9 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n8 ? 1 << 8 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n7 ? 1 << 7 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n6 ? 1 << 6 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n5 ? 1 << 5 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n4 ? 1 << 4 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n3 ? 1 << 3 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n2 ? 1 << 2 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n1 ? 1 << 1 : 0) | (BX_XHCI_THIS hub.op_regs.HcNotification.n0 ? 1 << 0 : 0); break; case 0x18: // Command Ring Control Register (Lo) (most fields always returns zero when read) val = (BX_XHCI_THIS hub.op_regs.HcCrcr.RsvdP << 4) | (BX_XHCI_THIS hub.op_regs.HcCrcr.crr ? 1 << 3 : 0); break; case 0x1C: // Command Ring Control Register (Hi) (always returns zero when read) val = 0; break; case 0x20: // Reserved and Zero'd case 0x24: // Reserved and Zero'd case 0x28: // Reserved and Zero'd case 0x2C: // Reserved and Zero'd val = 0; break; case 0x30: // DCBAAP (Lo) val = (Bit32u) ((Bit32u) BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap & ~0x3F); if (len == 8) #if ADDR_CAP_64 val_hi = (Bit32u) (BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap >> 32); #else val_hi = 0; #endif // ADDR_CAP_64 break; case 0x34: // DCBAAP (Hi) #if ADDR_CAP_64 val = (Bit32u) (BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap >> 32); #else val = 0; #endif // ADDR_CAP_64 break; case 0x38: // Config val = (BX_XHCI_THIS hub.op_regs.HcConfig.RsvdP << 8) | (BX_XHCI_THIS hub.op_regs.HcConfig.MaxSlotsEn << 0); break; } } else // Register Port Sets if ((offset >= PORT_SET_OFFSET) && (offset < (PORT_SET_OFFSET + (USB_XHCI_PORTS * 16)))) { unsigned port = (((offset - PORT_SET_OFFSET) >> 4) & 0x3F); // calculate port number if (BX_XHCI_THIS hub.usb_port[port].portsc.pp) { switch (offset & 0x0000000F) { case 0x00: val = 0 /* BX_XHCI_THIS hub.usb_port[port].portsc.wpr == 0 when read */ | (BX_XHCI_THIS hub.usb_port[port].portsc.dr ? 1 << 30 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.woe ? 1 << 27 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.wde ? 1 << 26 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.wce ? 1 << 25 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.cas ? 1 << 24 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.cec ? 1 << 23 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.plc ? 1 << 22 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.prc ? 1 << 21 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.occ ? 1 << 20 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.wrc ? 1 << 19 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.pec ? 1 << 18 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.csc ? 1 << 17 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.pic << 14) | (BX_XHCI_THIS hub.usb_port[port].portsc.speed << 10) | (BX_XHCI_THIS hub.usb_port[port].portsc.pp ? 1 << 9 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.pls << 5) | (BX_XHCI_THIS hub.usb_port[port].portsc.pr ? 1 << 4 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.oca ? 1 << 3 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.ped ? 1 << 1 : 0) | (BX_XHCI_THIS hub.usb_port[port].portsc.ccs ? 1 << 0 : 0); break; case 0x04: if (BX_XHCI_THIS hub.usb_port[port].is_usb3) { val = (BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.RsvdP << 17) | (BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.fla ? 1 << 16 : 0) | (BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.u2timeout << 8) | (BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.u1timeout << 0); } else { val = (BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.tmode << 28) | (BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.RsvdP << 17) | (BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.hle ? 1 << 16 : 0) | (BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.l1dslot << 8) | (BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.hird << 4) | (BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.rwe ? 1 << 3 : 0) | (BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.l1s << 0); } break; case 0x08: if (BX_XHCI_THIS hub.usb_port[port].is_usb3) { val = (BX_XHCI_THIS hub.usb_port[port].usb3.portli.RsvdP << 16) | (BX_XHCI_THIS hub.usb_port[port].usb3.portli.lec << 0); } else { val = BX_XHCI_THIS hub.usb_port[port].usb2.portli.RsvdP; } break; case 0x0C: #if ((VERSION_MAJOR < 1) || ((VERSION_MAJOR == 1) && (VERSION_MINOR == 0))) BX_ERROR(("Read from Reserved Register in Port Register Set %i", port)); #else val = (BX_XHCI_THIS hub.usb_port[port].porthlpmc.RsvdP << 14) | (BX_XHCI_THIS hub.usb_port[port].porthlpmc.hirdd << 10) | (BX_XHCI_THIS hub.usb_port[port].porthlpmc.l1timeout << 2) | (BX_XHCI_THIS hub.usb_port[port].porthlpmc.hirdm << 0); #endif break; } } else val = 0; } else // Extended Capabilities if ((offset >= EXT_CAPS_OFFSET) && (offset < (EXT_CAPS_OFFSET + EXT_CAPS_SIZE))) { unsigned caps_offset = (offset - EXT_CAPS_OFFSET); switch (len) { case 1: val = BX_XHCI_THIS hub.extended_caps[caps_offset]; break; case 2: ReadHostWordFromLittleEndian(&BX_XHCI_THIS hub.extended_caps[caps_offset], val); break; case 4: ReadHostDWordFromLittleEndian(&BX_XHCI_THIS hub.extended_caps[caps_offset], val); break; case 8: ReadHostQWordFromLittleEndian(&BX_XHCI_THIS hub.extended_caps[caps_offset], val64); val = (Bit32u)val64; val_hi = (Bit32u)(val64 >> 32); break; } } else // Host Controller Runtime Registers if ((offset >= RUNTIME_OFFSET) && (offset < (RUNTIME_OFFSET + 32 + (INTERRUPTERS * 32)))) { if (offset == RUNTIME_OFFSET) { val = (BX_XHCI_THIS hub.runtime_regs.mfindex.RsvdP << 14) | (BX_XHCI_THIS hub.runtime_regs.mfindex.index << 0); } else if (offset < (RUNTIME_OFFSET + 32)) { val = 0; } else { unsigned rt_offset = (offset - RUNTIME_OFFSET - 32); i = (rt_offset >> 5); // interrupter offset switch (rt_offset & 0x1F) { case 0x00: val = (BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.RsvdP << 2) | (BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ie ? 1 << 1 : 0) | (BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ip ? 1 << 0 : 0); break; case 0x04: val = (BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodc << 16) | (BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodi << 0); break; case 0x08: val = (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.RsvdP << 16) | (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.erstabsize << 0); break; case 0x0C: val = BX_XHCI_THIS hub.runtime_regs.interrupter[i].RsvdP; break; case 0x10: val = ((Bit32u) BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd & ~0x3F) | (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.RsvdP << 0); if (len == 8) #if ADDR_CAP_64 val_hi = (Bit32u) (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd >> 32); #else val_hi = 0; #endif // ADDR_CAP_64 break; case 0x14: #if ADDR_CAP_64 val = (Bit32u) (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd >> 32); #else val = 0; #endif // ADDR_CAP_64 break; case 0x18: val = (Bit32u) ((Bit32u) BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd & ~0x0F) | (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.ehb ? 1 << 3 : 0) | (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.desi << 0); if (len == 8) #if ADDR_CAP_64 val_hi = (Bit32u) (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd >> 32); #else val_hi = 0; #endif // ADDR_CAP_64 break; case 0x1C: #if ADDR_CAP_64 val = (Bit32u) (BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd >> 32); #else val = 0; #endif // ADDR_CAP_64 break; } } } else // Doorbell Registers (return zero when read) if ((offset >= DOORBELL_OFFSET) && (offset < (DOORBELL_OFFSET + 4 + (INTERRUPTERS * 4)))) { val = 0; } else BX_ERROR(("register read from unknown offset 0x%08X: 0x%08X%08X (len=%i)", offset, (Bit32u) val_hi, (Bit32u) val, len)); switch (len) { case 1: val &= 0xFF; *((Bit8u *) data) = (Bit8u) val; break; case 2: val &= 0xFFFF; *((Bit16u *) data) = (Bit16u) val; break; case 8: *((Bit32u *) ((Bit8u *) data + 4)) = val_hi; case 4: *((Bit32u *) data) = val; break; } // don't populate the log file if reading from interrupter's IMAN and only INT_ENABLE is set. // (This only works with the first interrupter) if ((offset != 0x620) || (val != 0x02)) BX_DEBUG(("register read from offset 0x%04X: 0x%08X%08X (len=%i)", offset, (Bit32u) val_hi, (Bit32u) val, len)); return 1; } bx_bool bx_usb_xhci_c::write_handler(bx_phy_address addr, unsigned len, void *data, void *param) { Bit32u value = *((Bit32u *) data); Bit32u value_hi = *((Bit32u *) ((Bit8u *) data + 4)); const Bit32u offset = (Bit32u) (addr - BX_XHCI_THIS pci_base_address[0]); Bit32u temp; int i; // modify val and val_hi per len of data to write switch (len) { case 1: value &= 0xFF; value_hi = 0; break; case 2: value &= 0xFFFF; case 4: value_hi = 0; break; } BX_DEBUG(("register write to offset 0x%04X: 0x%08X%08X (len=%i)", offset, (Bit32u) value_hi, (Bit32u) value, len)); // Even though the controller allows reads other than 32-bits & on odd boundaries, // we are going to ASSUME dword reads and writes unless specified below // RO Capability Registers if (offset < OPS_REGS_OFFSET) { switch (offset) { // Capability Registers case 0x00: // CapLength / version case 0x04: // HCSPARAMS1 case 0x08: // HCSPARAMS2 case 0x0C: // HCSPARAMS3 case 0x10: // HCCPARAMS case 0x14: // DBOFF case 0x18: // TRSOFF case 0x1C: // reserved BX_ERROR(("Write to Read Only Host Capability Register (0x%08X)", offset)); break; } } else // Operational Registers if ((offset >= OPS_REGS_OFFSET) && (offset < (OPS_REGS_OFFSET + 0x40))) { switch (offset - OPS_REGS_OFFSET) { case 0x00: // Command temp = BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP1; BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP1 = (value >> 12); if (temp != BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP1) BX_ERROR(("bits 31:12 in command register were not preserved")); BX_XHCI_THIS hub.op_regs.HcCommand.eu3s = (value & (1 << 11)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcCommand.ewe = (value & (1 << 10)) ? 1 : 0; if (value & (1 << 9)) { if (BX_XHCI_THIS hub.op_regs.HcStatus.hch == 1) { BX_XHCI_THIS hub.op_regs.HcStatus.sre = 0; // clear error state BX_XHCI_THIS hub.op_regs.HcStatus.rss = 1; // show that we are restoring the state BX_XHCI_THIS hub.op_regs.HcStatus.sre = BX_XHCI_THIS restore_hc_state(); BX_XHCI_THIS hub.op_regs.HcStatus.rss = 0; } else BX_ERROR(("Restore State when controller not in Halted state.")); } if (value & (1 << 8)) { if (BX_XHCI_THIS hub.op_regs.HcStatus.hch == 1) { BX_XHCI_THIS hub.op_regs.HcStatus.sre = 0; // clear error state BX_XHCI_THIS hub.op_regs.HcStatus.sss = 1; // show that we are saving the state BX_XHCI_THIS hub.op_regs.HcStatus.sre = BX_XHCI_THIS save_hc_state(); BX_XHCI_THIS hub.op_regs.HcStatus.sss = 0; } else BX_ERROR(("Save State when controller not in Halted state.")); } #if LIGHT_HC_RESET BX_XHCI_THIS hub.op_regs.HcCommand.lhcrst = (value & (1 << 7)) ? 1 : 0; // TODO: Do light reset #endif // LIGHT_HC_RESET temp = BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP0; BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP0 = (value & (7 << 4)) >> 4; if (temp != BX_XHCI_THIS hub.op_regs.HcCommand.RsvdP0) BX_ERROR(("bits 6:4 in Command Register were not preserved")); BX_XHCI_THIS hub.op_regs.HcCommand.hsee = (value & (1 << 3)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcCommand.inte = (value & (1 << 2)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcCommand.hcrst = (value & (1 << 1)) ? 1 : 0; if (BX_XHCI_THIS hub.op_regs.HcCommand.hcrst) { BX_XHCI_THIS reset_hc(); BX_XHCI_THIS hub.op_regs.HcCommand.hcrst = 0; } // if run/stop bit cleared, stop command ring BX_XHCI_THIS hub.op_regs.HcCommand.rs = (value & (1 << 0)) ? 1 : 0; if (BX_XHCI_THIS hub.op_regs.HcCommand.rs == 0) { BX_XHCI_THIS hub.op_regs.HcCrcr.crr = 0; BX_XHCI_THIS hub.op_regs.HcStatus.hch = 1; // set the Halted Bit } else BX_XHCI_THIS hub.op_regs.HcStatus.hch = 0; // clear the Halted Bit break; case 0x04: // Status if ((value & 0xFFFFE0E2) != 0) BX_ERROR(("RsvdZ bits in HcStatus not written as zeros")); if (value & ((1<<12) | (1<<11) | (1<<9) | (1<<8) | (1<<0))) BX_ERROR(("Write to one or more Read-only bits in Status Register")); BX_XHCI_THIS hub.op_regs.HcStatus.sre = (value & (1 << 10)) ? 0 : BX_XHCI_THIS hub.op_regs.HcStatus.sre; BX_XHCI_THIS hub.op_regs.HcStatus.pcd = (value & (1 << 4)) ? 0 : BX_XHCI_THIS hub.op_regs.HcStatus.pcd; BX_XHCI_THIS hub.op_regs.HcStatus.eint = (value & (1 << 3)) ? 0 : BX_XHCI_THIS hub.op_regs.HcStatus.eint; BX_XHCI_THIS hub.op_regs.HcStatus.hse = (value & (1 << 2)) ? 0 : BX_XHCI_THIS hub.op_regs.HcStatus.hse; //FIXME: should this line go where system software clears the IP bit, or here when it clears the status:eint bit? if (value & (1 << 3)) // acknowledging the interrupt DEV_pci_set_irq(BX_XHCI_THIS hub.devfunc, BX_XHCI_THIS pci_conf[0x3d], 0); break; case 0x08: // Page Size BX_ERROR(("Write to one or more Read-only bits in Page Size Register")); break; case 0x0C: // Reserved and Zero'd case 0x10: // Reserved and Zero'd if (value != 0) BX_ERROR(("Write non-zero to RsvdZ Register (offset = 0x%08X value = 0x%08X)", offset, value)); break; case 0x14: // Device Notification Control Register temp = BX_XHCI_THIS hub.op_regs.HcNotification.RsvdP; BX_XHCI_THIS hub.op_regs.HcNotification.RsvdP = value >> 16; if (temp != BX_XHCI_THIS hub.op_regs.HcNotification.RsvdP) BX_ERROR(("bits 31:16 in DNCTRL Register were not preserved")); BX_XHCI_THIS hub.op_regs.HcNotification.n15 = (value & (1 << 15)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n14 = (value & (1 << 14)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n13 = (value & (1 << 13)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n12 = (value & (1 << 12)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n11 = (value & (1 << 11)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n10 = (value & (1 << 10)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n9 = (value & (1 << 9)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n8 = (value & (1 << 8)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n7 = (value & (1 << 7)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n6 = (value & (1 << 6)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n5 = (value & (1 << 5)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n4 = (value & (1 << 4)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n3 = (value & (1 << 3)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n2 = (value & (1 << 2)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n1 = (value & (1 << 1)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcNotification.n0 = (value & (1 << 0)) ? 1 : 0; break; case 0x18: // Command Ring Control Register (Lo) if (value & (1<<3)) BX_ERROR(("Write to one or more Read-only bits in CRCR Register")); temp = BX_XHCI_THIS hub.op_regs.HcCrcr.RsvdP; BX_XHCI_THIS hub.op_regs.HcCrcr.RsvdP = (value & (2<<4)) >> 4; if (temp != BX_XHCI_THIS hub.op_regs.HcCrcr.RsvdP) BX_ERROR(("bits 5:4 in CRCR Register were not preserved")); BX_XHCI_THIS hub.op_regs.HcCrcr.ca = (value & (1 << 2)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcCrcr.cs = (value & (1 << 1)) ? 1 : 0; BX_XHCI_THIS hub.op_regs.HcCrcr.rcs = (value & (1 << 0)) ? 1 : 0; // save the new ring pointer #if ADDR_CAP_64 if (len == 8) { BX_XHCI_THIS hub.op_regs.HcCrcr.crc = (Bit64u) (((Bit64u) value_hi << 32) | (value & ~0x3F)); } else { BX_XHCI_THIS hub.op_regs.HcCrcr.crc &= (Bit64u) ~0xFFFFFFFF; BX_XHCI_THIS hub.op_regs.HcCrcr.crc |= (Bit64u) (value & ~0x3F); } #else BX_XHCI_THIS hub.op_regs.HcCrcr.crc = (Bit64u) (value & ~0x3F); #endif BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer = BX_XHCI_THIS hub.op_regs.HcCrcr.crc; BX_XHCI_THIS hub.ring_members.command_ring.rcs = BX_XHCI_THIS hub.op_regs.HcCrcr.rcs; // if command stop or abort, stop command ring if (BX_XHCI_THIS hub.op_regs.HcCrcr.ca || BX_XHCI_THIS hub.op_regs.HcCrcr.cs) BX_XHCI_THIS hub.op_regs.HcCrcr.crr = 0; break; case 0x1C: // Command Ring Control Register (Hi) #if ADDR_CAP_64 BX_XHCI_THIS hub.op_regs.HcCrcr.crc &= (Bit64u) 0xFFFFFFFF; BX_XHCI_THIS hub.op_regs.HcCrcr.crc |= (Bit64u) ((Bit64u) value << 32); BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer = BX_XHCI_THIS hub.op_regs.HcCrcr.crc; #endif break; case 0x20: // Reserved and Zero'd case 0x24: // Reserved and Zero'd case 0x28: // Reserved and Zero'd case 0x2C: // Reserved and Zero'd if (value != 0) BX_ERROR(("Write non-zero to RsvdZ Register (offset = 0x%08X value = 0x%08X)", offset, value)); break; case 0x30: // DCBAAP (Lo) if (value & 0x3F) BX_ERROR(("Write non-zero to RsvdZ member of DCBAAP Register")); #if ADDR_CAP_64 if (len == 8) BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap = (Bit64u) (((Bit64u) value_hi << 32) | (value & ~0x3F)); else { BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap &= (Bit64u) ~0xFFFFFFFF; BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap |= (Bit64u) (value & ~0x3F); } #else BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap = (Bit64u) (value & ~0x3F); #endif break; case 0x34: // DCBAAP (Hi) #if ADDR_CAP_64 BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap &= (Bit64u) 0xFFFFFFFF; BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap |= (Bit64u) ((Bit64u) value << 32); #endif break; case 0x38: // Config temp = BX_XHCI_THIS hub.op_regs.HcConfig.RsvdP; BX_XHCI_THIS hub.op_regs.HcConfig.RsvdP = (value >> 8); if (temp != BX_XHCI_THIS hub.op_regs.HcConfig.RsvdP) BX_ERROR(("bits 31:8 in Config Register were not preserved")); BX_XHCI_THIS hub.op_regs.HcConfig.MaxSlotsEn = (value & 0xFF); break; } } else // Register Port Sets if ((offset >= PORT_SET_OFFSET) && (offset < (PORT_SET_OFFSET + (USB_XHCI_PORTS * 16)))) { unsigned port = (((offset - PORT_SET_OFFSET) >> 4) & 0x3F); // calculate port number switch (offset & 0x0000000F) { case 0x00: if (value & (1<<9)) { // port power if (value & ((1<<30) | (1<<24) | (1<<3) | (1<<0))) BX_ERROR(("Write to one or more Read-only bits in PORTSC[%i] Register (0x%08X)", port, value)); if (value & ((3<<28) | (1<<2))) BX_ERROR(("Write non-zero to a RsvdZ member of PORTSC[%i] Register", port)); if (BX_XHCI_THIS hub.usb_port[port].is_usb3) { BX_XHCI_THIS hub.usb_port[port].portsc.wpr = (value & (1 << 31)) ? 1 : 0; BX_XHCI_THIS hub.usb_port[port].portsc.cec = (value & (1 << 23)) ? 1 : 0; BX_XHCI_THIS hub.usb_port[port].portsc.wrc = (value & (1 << 20)) ? 0 : BX_XHCI_THIS hub.usb_port[port].portsc.wrc; if (value & (1<<18)) BX_ERROR(("Write to USB3 port: bit 18")); } else { BX_XHCI_THIS hub.usb_port[port].portsc.pec = (value & (1 << 18)) ? 0 : BX_XHCI_THIS hub.usb_port[port].portsc.pec; if (value & ((1<<31) | (1<<23) | (1<<19))) BX_ERROR(("Write to USB2 port: RsvdZ bit")); } // The WC1 bits must be before anything that will change these bits below. if (value & (1 << 22)) BX_XHCI_THIS hub.usb_port[port].portsc.plc = 0; if (value & (1 << 21)) BX_XHCI_THIS hub.usb_port[port].portsc.prc = 0; if (value & (1 << 20)) BX_XHCI_THIS hub.usb_port[port].portsc.occ = 0; if (value & (1 << 17)) BX_XHCI_THIS hub.usb_port[port].portsc.csc = 0; if (value & (1 << 1)) BX_XHCI_THIS hub.usb_port[port].portsc.ped = 0; BX_XHCI_THIS hub.usb_port[port].portsc.woe = (value & (1 << 27)) ? 1 : 0; BX_XHCI_THIS hub.usb_port[port].portsc.wde = (value & (1 << 26)) ? 1 : 0; BX_XHCI_THIS hub.usb_port[port].portsc.wce = (value & (1 << 25)) ? 1 : 0; BX_XHCI_THIS hub.usb_port[port].portsc.pic = (value & (0x3 << 14)) >> 14; // if transition from non powered to powered if (BX_XHCI_THIS hub.usb_port[port].portsc.pp == 0) { if (BX_XHCI_THIS hub.usb_port[port].portsc.ccs) BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_POLLING; else BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_RXDETECT; } BX_XHCI_THIS hub.usb_port[port].portsc.pp = 1; if (value & (1<<16)) { // LWS switch ((value & (0xF << 5)) >> 5) { case 0: BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_U0; break; case 2: // USB2 only BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_U2; break; case 3: BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_U3_SUSPENDED; break; case 5: // USB3 only if (BX_XHCI_THIS hub.usb_port[port].portsc.pls == PLS_DISABLED) { BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_RXDETECT; BX_XHCI_THIS hub.usb_port[port].portsc.ped = 0; BX_XHCI_THIS hub.usb_port[port].portsc.pec = 1; } break; case 15: // USB2 only if (BX_XHCI_THIS hub.usb_port[port].portsc.pls == PLS_U3_SUSPENDED) { // port should transition to the U3Exit state... } break; } } // if port reset bit is set, reset the port, then enable the port (if ccs == 1). if (value & (1 << 4)) { BX_DEBUG(("Reset port #%i (PORTSC[%i])", port + 1, port)); BX_XHCI_THIS hub.usb_port[port].portsc.pr = 0; if (BX_XHCI_THIS hub.usb_port[port].portsc.ccs) { BX_XHCI_THIS hub.usb_port[port].portsc.prc = 1; BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_U0; BX_XHCI_THIS hub.usb_port[port].portsc.ped = 1; if (BX_XHCI_THIS hub.usb_port[port].device != NULL) { switch (BX_XHCI_THIS hub.usb_port[port].device->get_speed()) { case USB_SPEED_LOW: BX_XHCI_THIS hub.usb_port[port].portsc.speed = 2; break; case USB_SPEED_FULL: BX_XHCI_THIS hub.usb_port[port].portsc.speed = 1; break; case USB_SPEED_HIGH: BX_XHCI_THIS hub.usb_port[port].portsc.speed = 3; break; case USB_SPEED_SUPER: BX_XHCI_THIS hub.usb_port[port].portsc.speed = 4; break; } DEV_usb_send_msg(BX_XHCI_THIS hub.usb_port[port].device, USB_MSG_RESET); } } else { BX_XHCI_THIS hub.usb_port[port].portsc.pls = PLS_RXDETECT; BX_XHCI_THIS hub.usb_port[port].portsc.ped = 0; BX_XHCI_THIS hub.usb_port[port].portsc.speed = 0; } } } else BX_XHCI_THIS hub.usb_port[port].portsc.pp = 0; break; case 0x04: if (BX_XHCI_THIS hub.usb_port[port].portsc.pp) { if (BX_XHCI_THIS hub.usb_port[port].is_usb3) { temp = BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.RsvdP; BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.RsvdP = value >> 17; if (temp != BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.RsvdP) BX_ERROR(("bits 31:17 in PORTPMSC[%i] Register were not preserved", port)); BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.fla = (value & (1 << 16)) ? 1 : 0; BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.u2timeout = (value & (0xFF << 8)) >> 8; BX_XHCI_THIS hub.usb_port[port].usb3.portpmsc.u1timeout = (value & (0xFF << 0)) >> 0; } else { if (value & (7<<0)) BX_ERROR(("Write to one or more Read-only bits in PORTPMSC[%i] Register", port)); BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.tmode = (value & (0xF << 28)) >> 28; temp = BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.RsvdP; BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.RsvdP = (value & (0x1FFF << 15)) >> 15; if (temp != BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.RsvdP) BX_ERROR(("bits 27:15 in PORTPMSC[%i] Register were not preserved", port)); BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.hle = (value & (1 << 16)) ? 1 : 0; BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.l1dslot = (value & (0xFF << 8)) >> 8; BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.hird = (value & (0xF << 4)) >> 4; BX_XHCI_THIS hub.usb_port[port].usb2.portpmsc.rwe = (value & (1 << 3)) ? 1 : 0; } } break; case 0x08: if (BX_XHCI_THIS hub.usb_port[port].portsc.pp) { if (BX_XHCI_THIS hub.usb_port[port].is_usb3) { if (value & (0xFFFF<<0)) BX_ERROR(("Write to one or more Read-only bits in PORTLI[%i] Register", port)); temp = BX_XHCI_THIS hub.usb_port[port].usb3.portli.RsvdP; BX_XHCI_THIS hub.usb_port[port].usb3.portli.RsvdP = value >> 16; if (temp != BX_XHCI_THIS hub.usb_port[port].usb3.portli.RsvdP) BX_ERROR(("bits 31:16 in PORTLI[%i] Register were not preserved", port)); } else { temp = BX_XHCI_THIS hub.usb_port[port].usb2.portli.RsvdP; BX_XHCI_THIS hub.usb_port[port].usb2.portli.RsvdP = value; if (temp != BX_XHCI_THIS hub.usb_port[port].usb2.portli.RsvdP) BX_ERROR(("bits 31:0 in PORTLI[%i] Register were not preserved", port)); } } break; case 0x0C: #if ((VERSION_MAJOR < 1) || ((VERSION_MAJOR == 1) && (VERSION_MINOR == 0))) BX_ERROR(("Write to Reserved Register in Port Register Set %i", port)); #else temp = BX_XHCI_THIS hub.usb_port[port].porthlpmc.RsvdP; BX_XHCI_THIS hub.usb_port[port].porthlpmc.RsvdP = (value >> 14); if (temp != BX_XHCI_THIS hub.usb_port[port].porthlpmc.RsvdP) BX_ERROR(("bits 31:14 in PORTHLPMC[%i] Register were not preserved", port)); BX_XHCI_THIS hub.usb_port[port].porthlpmc.hirdd = ((value & (0x0F << 10)) >> 10); BX_XHCI_THIS hub.usb_port[port].porthlpmc.l1timeout = ((value & (0xFF << 2)) >> 2); BX_XHCI_THIS hub.usb_port[port].porthlpmc.hirdm = ((value & (0x0F << 0)) >> 0); #endif break; } } else // Extended Capabilities if ((offset >= EXT_CAPS_OFFSET) && (offset < (EXT_CAPS_OFFSET + EXT_CAPS_SIZE))) { unsigned caps_offset = (offset - EXT_CAPS_OFFSET); Bit64u qword = (((Bit64u) value_hi << 32) | value); while (len) { *(Bit8u *) &BX_XHCI_THIS hub.extended_caps[caps_offset] = (Bit8u) (qword & 0xFF); switch (caps_offset) { case 3: if (qword & 1) // clear the BIOS owner bit BX_XHCI_THIS hub.extended_caps[2] &= ~(1<<0); break; default: ; } len--; caps_offset++; qword >>= 8; } } else // Host Controller Runtime Registers if ((offset >= RUNTIME_OFFSET) && (offset < (RUNTIME_OFFSET + 32 + (INTERRUPTERS * 32)))) { if (offset == RUNTIME_OFFSET) { BX_ERROR(("Write to MFINDEX register")); } else if (offset < (RUNTIME_OFFSET + 32)) { BX_ERROR(("Write to Reserved Register in HC Runtime Register set")); } else { unsigned rt_offset = (offset - RUNTIME_OFFSET - 32); i = (rt_offset >> 5); // interrupter offset switch (rt_offset & 0x1F) { case 0x00: temp = BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.RsvdP; BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.RsvdP = (value >> 2); if (temp != BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.RsvdP) BX_ERROR(("bits 31:2 in IMAN Register were not preserved")); BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ie = ((value & (1 << 1)) == (1 << 1)); if (value & (1 << 0)) BX_XHCI_THIS hub.runtime_regs.interrupter[i].iman.ip = 0; break; case 0x04: BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodc = (value >> 16); BX_XHCI_THIS hub.runtime_regs.interrupter[i].imod.imodi = (value & 0xFFFF); break; case 0x08: temp = BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.RsvdP; BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.RsvdP = (value >> 16); if (temp != BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.RsvdP) BX_ERROR(("bits 31:16 in ERSTSZ Register were not preserved")); BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstsz.erstabsize = (value & 0xFFFF); break; case 0x0C: temp = BX_XHCI_THIS hub.runtime_regs.interrupter[i].RsvdP; BX_XHCI_THIS hub.runtime_regs.interrupter[i].RsvdP = value; if (temp != BX_XHCI_THIS hub.runtime_regs.interrupter[i].RsvdP) BX_ERROR(("bits 31:0 in RsvdP (0x0C) Register were not preserved")); break; case 0x10: temp = BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.RsvdP; BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.RsvdP = (value & 0x3F); if (temp != BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.RsvdP) BX_ERROR(("bits 5:0 in ERSTBA Register were not preserved")); #if ADDR_CAP_64 if (len == 8) { BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd = (((Bit64u) value_hi << 32) | (value & ~0x3F)); init_event_ring(i); // initialize event ring members } else { BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd &= (Bit64u) ~0xFFFFFFFF; BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd |= (Bit64u) (value & ~0x3F); } #else BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd = (Bit64u) (value & ~0x3F); init_event_ring(i); // initialize event ring members #endif break; case 0x14: #if ADDR_CAP_64 BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd &= (Bit64u) 0xFFFFFFFF; BX_XHCI_THIS hub.runtime_regs.interrupter[i].erstba.erstabadd |= ((Bit64u) value << 32); init_event_ring(i); // initialize event ring members #endif break; case 0x18: if (value & (1 << 3)) BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.ehb = 0; BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.desi = (value & 0x07); #if ADDR_CAP_64 if (len == 8) BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd = (Bit64u) (((Bit64u) value_hi << 32) | (value & ~0x0F)); else { BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd &= (Bit64u) ~0xFFFFFFFF; BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd |= (Bit64u) (value & ~0x0F); } #else BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd == (Bit64u) (value & ~0x0F); #endif break; case 0x1C: #if ADDR_CAP_64 BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd &= (Bit64u) 0xFFFFFFFF; BX_XHCI_THIS hub.runtime_regs.interrupter[i].erdp.eventadd |= ((Bit64u) value << 32); #endif break; } } } else // Doorbell Registers if ((offset >= DOORBELL_OFFSET) && (offset < (DOORBELL_OFFSET + 4 + (INTERRUPTERS * 4)))) { if (value & (0xFF << 8)) BX_ERROR(("RsvdZ field of Doorbell written as non zero.")); unsigned doorbell = ((offset - DOORBELL_OFFSET) >> 2); if (doorbell == 0) { // Command Doorbell BX_DEBUG(("Command Doorbell Rang")); if (value & (0xFFFF << 16)) BX_ERROR(("DB Stream ID not zero when Command Doorbell rung")); if ((value & 0xFF) != 0) BX_ERROR(("Command Doorbell rang with non zero value: 0x%02X", (value & 0xFF))); // if the run/stop bit is set, the command ring is running if (BX_XHCI_THIS hub.op_regs.HcCommand.rs) BX_XHCI_THIS hub.op_regs.HcCrcr.crr = 1; process_command_ring(); } else { // doorbell = slot to use (1 based) // (value & 0xFF) = ep (1 = control, 2 = ep1 out, 3 = ep1 in, etc); int ep = (value & 0xFF); BX_DEBUG(("Rang Doorbell: slot = %i ep = %i (%s)", doorbell, ep, (ep & 1) ? "IN" : "OUT")); if (ep > 31) BX_ERROR(("Doorbell rang with EP > 31 (ep = %i)", ep)); else process_transfer_ring(doorbell, ep); } } else BX_ERROR(("register write to unknown offset 0x%08X: 0x%08X%08X (len=%i)", offset, (Bit32u) value_hi, (Bit32u) value, len)); return 1; } // This function checks and processes all enqueued TRB's in the EP's transfer ring void bx_usb_xhci_c::process_transfer_ring(const int slot, const int ep) { struct TRB trb; Bit64u address = 0, org_addr; int int_target, td_size, transfer_length; int ret, len; int port_num = BX_XHCI_THIS hub.slots[slot].slot_context.rh_port_num; USBPacket packet; Bit8u cur_direction = (ep & 1) ? USB_TOKEN_IN : USB_TOKEN_OUT; // for NORMAL without SETUP bx_bool is_transfer_trb, is_immed_data, ioc, spd_occurred = 0; bx_bool first_event_trb_encountered = 0; int bytes_transferred = 0, bytes_not_transferred = 0; int trb_count = 0; int comp_code = 0; // if the ep is disabled, return an error event trb. if ((BX_XHCI_THIS hub.slots[slot].slot_context.slot_state == SLOT_STATE_DISABLED_ENABLED) || (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_DISABLED)) { org_addr = BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer; write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(EP_NOT_ENABLED), TRB_SET_SLOT(slot) | TRB_SET_EP(ep) | TRB_SET_TYPE(TRANS_EVENT), 1); return; } // if the ep is in the halted or error state, ignore the doorbell ring. if ((BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_HALTED) || (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_ERROR)) return; // if the ep_context::type::direction field is not correct for the ep type of this ep, then ignore the doorbell if (ep >= 2) { static int endpoint_dir[8] = { -1, EP_DIR_OUT, EP_DIR_OUT, EP_DIR_OUT, -1, EP_DIR_IN, EP_DIR_IN, EP_DIR_IN }; int ep_type = (ep & 1) ? EP_DIR_IN : EP_DIR_OUT; if (endpoint_dir[BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_type] != ep_type) { BX_ERROR(("Endpoint_context::Endpoint_type::direction is not correct for this endpoint number. Ignoring doorbell ring.")); return; } } // If an endpoint is in the Stopped state when the doorbell is rung, it will transition to the Running state (page 126) // The output Context (*slot_addr) should be updated before any other transfer events are made if (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_STOPPED) { BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state = EP_STATE_RUNNING; update_ep_context(slot, ep); } // read in the TRB read_TRB((bx_phy_address) BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer, &trb); BX_DEBUG(("Found TRB: address = 0x" FORMATADDRESS " 0x" FMT_ADDRX64 " 0x%08X 0x%08X %i", (bx_phy_address) BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer, trb.parameter, trb.status, trb.command, BX_XHCI_THIS hub.slots[slot].ep_context[ep].rcs)); while ((trb.command & 1) == BX_XHCI_THIS hub.slots[slot].ep_context[ep].rcs) { org_addr = BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer; BX_DEBUG(("Found TRB: address = 0x" FORMATADDRESS " 0x" FMT_ADDRX64 " 0x%08X 0x%08X %i (SPD occurred = %i)", (bx_phy_address) org_addr, trb.parameter, trb.status, trb.command, BX_XHCI_THIS hub.slots[slot].ep_context[ep].rcs, spd_occurred)); trb_count++; // these are used in some/most items. // If not used, won't hurt to extract bad data. int_target = TRB_GET_TARGET(trb.status); td_size = TRB_GET_TDSIZE(trb.status); transfer_length = TRB_GET_TX_LEN(trb.status); is_transfer_trb = 0; // assume not a transfer ioc = TRB_IOC(trb.command); // if a SPD occurred, we only process the LINK and EVENT TRB's in this TD, until either on of these two or end of TD if (!spd_occurred || (spd_occurred && ((TRB_GET_TYPE(trb.command) == LINK) || (TRB_GET_TYPE(trb.command) == EVENT_DATA)))) { // is the data in trb.parameter? (Immediate data?) is_immed_data = TRB_IS_IMMED_DATA(trb.command); if (is_immed_data) memcpy(BX_XHCI_THIS device_buffer, &trb.parameter, 8); else address = trb.parameter; switch (TRB_GET_TYPE(trb.command)) { // is a LINK trb. case LINK: if (ioc) write_event_TRB(int_target, org_addr, TRB_SET_COMP_CODE(TRB_SUCCESS), TRB_SET_TYPE(LINK), 1); if (TRB_TOGGLE(trb.command)) BX_XHCI_THIS hub.slots[slot].ep_context[ep].rcs ^= 1; BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer = trb.parameter & (Bit64u) ~0xF; BX_DEBUG(("0x" FORMATADDRESS ": Transfer Ring (slot = %i) (ep = %i): LINK TRB: New dq_pointer = 0x" FMT_ADDRX64 " (%i)", (bx_phy_address) org_addr, slot, ep, BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer, BX_XHCI_THIS hub.slots[slot].ep_context[ep].rcs)); #if ((VERSION_MAJOR == 0) && (VERSION_MINOR == 0x95)) // https://patchwork.kernel.org/patch/51191/ if (!TRB_CHAIN(trb.command)) BX_DEBUG(("Chain Bit in Link TRB not set.")); #endif read_TRB((bx_phy_address) BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer, &trb); continue; // Setup Stage TRB case SETUP_STAGE: cur_direction = USB_TOKEN_SETUP; is_transfer_trb = 1; BX_DEBUG(("0x" FORMATADDRESS ": Transfer Ring (slot = %i) (ep = %i) (len = %i): Found SETUP TRB", (bx_phy_address) org_addr, slot, ep, transfer_length)); break; // Data Stage TRB case DATA_STAGE: cur_direction = TRB_GET_DIR(trb.command); is_transfer_trb = 1; BX_DEBUG(("0x" FORMATADDRESS ": Transfer Ring (slot = %i) (ep = %i) (len = %i): Found DATA STAGE TRB", (bx_phy_address) org_addr, slot, ep, transfer_length)); break; // Status Stage TRB case STATUS_STAGE: cur_direction = TRB_GET_DIR(trb.command); is_transfer_trb = 1; transfer_length = 0; BX_DEBUG(("0x" FORMATADDRESS ": Transfer Ring (slot = %i) (ep = %i): Found STATUS STAGE TRB", (bx_phy_address) org_addr, slot, ep)); break; // Normal TRB case NORMAL: is_transfer_trb = 1; BX_DEBUG(("0x" FORMATADDRESS ": Transfer Ring (slot = %i) (ep = %i) (len = %i): Found NORMAL TRB", (bx_phy_address) org_addr, slot, ep, transfer_length)); break; // Event TRB case EVENT_DATA: if (!spd_occurred || (spd_occurred && !first_event_trb_encountered)) { comp_code = (spd_occurred) ? SHORT_PACKET : TRB_SUCCESS; if (spd_occurred && !first_event_trb_encountered) write_event_TRB(int_target, trb.parameter, TRB_SET_COMP_CODE(comp_code) | bytes_transferred, TRB_SET_TYPE(TRANS_EVENT) | (1<<2), ioc); else write_event_TRB(int_target, trb.parameter, TRB_SET_COMP_CODE(comp_code), TRB_SET_TYPE(TRANS_EVENT) | (1<<2), ioc); } if (spd_occurred) first_event_trb_encountered = 1; BX_DEBUG(("0x" FORMATADDRESS ": Transfer Ring (slot = %i) (ep = %i): Found EVENT_DATA TRB: (returning %i)", (bx_phy_address) org_addr, slot, ep, comp_code)); break; // unknown TRB type default: BX_ERROR(("0x" FORMATADDRESS ": Transfer Ring (slot = %i) (ep = %i): Unknown TRB found.", (bx_phy_address) org_addr, slot, ep)); BX_ERROR(("Unknown trb type found: %i(dec) (0x" FMT_ADDRX64 " 0x%08X 0x%08X)", TRB_GET_TYPE(trb.command), trb.parameter, trb.status, trb.command)); } // is there a transfer to be done? if (is_transfer_trb) { // set status bar conditions for device if ((transfer_length > 0) && (BX_XHCI_THIS hub.statusbar_id >= 0)) { if (cur_direction == USB_TOKEN_IN) bx_gui->statusbar_setitem(BX_XHCI_THIS hub.statusbar_id, 1); // read else bx_gui->statusbar_setitem(BX_XHCI_THIS hub.statusbar_id, 1, 1); // write } comp_code = TRB_SUCCESS; // assume good trans event packet.pid = cur_direction; packet.devaddr = BX_XHCI_THIS hub.slots[slot].slot_context.device_address; packet.devep = (ep >> 1); packet.data = BX_XHCI_THIS device_buffer; packet.len = transfer_length; switch (cur_direction) { case USB_TOKEN_OUT: case USB_TOKEN_SETUP: if ((is_immed_data == 0) && (transfer_length > 0)) DEV_MEM_READ_PHYSICAL_DMA((bx_phy_address) address, transfer_length, BX_XHCI_THIS device_buffer); // The XHCI should block all SET_ADDRESS SETUP TOKEN's if ((cur_direction == USB_TOKEN_SETUP) && (BX_XHCI_THIS device_buffer[0] == 0) && // Request type (BX_XHCI_THIS device_buffer[1] == 5) // SET_ADDRESS ) { len = 0; comp_code = TRB_ERROR; BX_ERROR(("SETUP_TOKEN: System Software should not send SET_ADDRESS command on the xHCI.")); } else { ret = BX_XHCI_THIS broadcast_packet(&packet, port_num - 1); len = transfer_length; BX_DEBUG(("OUT: Transferred %i bytes (ret = %i)", len, ret)); } break; case USB_TOKEN_IN: ret = BX_XHCI_THIS broadcast_packet(&packet, port_num - 1); if (ret >= 0) { len = ret; bytes_transferred += len; if (len > 0) DEV_MEM_WRITE_PHYSICAL_DMA((bx_phy_address) address, len, BX_XHCI_THIS device_buffer); BX_DEBUG(("IN: Transferred %i bytes, requested %i bytes", len, transfer_length)); if (len < transfer_length) { bytes_not_transferred = transfer_length - len; spd_occurred = 1; } else bytes_not_transferred = 0; } else { switch (ret) { case USB_RET_STALL: comp_code = STALL_ERROR; break; case USB_RET_BABBLE: comp_code = BABBLE_DETECTION; break; default: comp_code = TRANSACTION_ERROR; } len = 0; } break; } // 4.10.1 paragraph 4 // 4.10.1.1 if (ioc) { if ((comp_code == TRB_SUCCESS) && spd_occurred && TRB_SPD(trb.command)) { comp_code = SHORT_PACKET; BX_DEBUG(("Sending Short Packet Detect Event TRB (%i)", bytes_not_transferred)); } // create a Event TRB write_event_TRB(int_target, org_addr, TRB_SET_COMP_CODE(comp_code) | bytes_not_transferred, TRB_SET_SLOT(slot) | TRB_SET_EP(ep) | TRB_SET_TYPE(TRANS_EVENT), 1); } } } // if the Chain bit is clear, then end of TD if ((trb.command & (1<<4)) == 0) { spd_occurred = 0; bytes_transferred = 0; } // advance the Dequeue pointer and continue; BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer += 16; read_TRB((bx_phy_address) BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer, &trb); } BX_DEBUG(("Process Transfer Ring: Processed %i TRB's", trb_count)); if (trb_count == 0) BX_ERROR(("Process Transfer Ring: Doorbell rang, but no TRB's were enqueued in the ring.")); } // This function call starts at the current position in the Command Ring, // processes that command, then moves to the next one, until CCS != SCS; // BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer = current position in ring // BX_XHCI_THIS hub.op_regs.HcCrcr.rcs = current ring cycle state // BX_XHCI_THIS hub.op_regs.HcCrcr.crr = command ring running void bx_usb_xhci_c::process_command_ring(void) { struct TRB trb; int i, slot, slot_type, ep, comp_code = 0, new_addr = 0, bsr = 0; Bit32u a_flags = 0, d_flags, tmpval1, tmpval2; Bit64u org_addr; Bit8u buffer[CONTEXT_SIZE + 2048]; struct SLOT_CONTEXT slot_context; struct EP_CONTEXT ep_context; if (!BX_XHCI_THIS hub.op_regs.HcCrcr.crr) return; // read in the TRB read_TRB((bx_phy_address) BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer, &trb); BX_DEBUG(("Dump command trb: %i(dec) (0x" FMT_ADDRX64 " 0x%08X 0x%08X) (%i)", TRB_GET_TYPE(trb.command), trb.parameter, trb.status, trb.command, BX_XHCI_THIS hub.ring_members.command_ring.rcs)); while ((trb.command & 1) == BX_XHCI_THIS hub.ring_members.command_ring.rcs) { org_addr = BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer; switch (TRB_GET_TYPE(trb.command)) { // is a LINK trb. case LINK: // Chain bit and Interrupter Target fields are ignored in Command Rings (Page 370) BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer = trb.parameter & (Bit64u) ~0xF; if (TRB_IOC(trb.command)) write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(TRB_SUCCESS), TRB_SET_TYPE(LINK), 1); if (TRB_TOGGLE(trb.command)) BX_XHCI_THIS hub.ring_members.command_ring.rcs ^= 1; BX_INFO(("0x" FORMATADDRESS ": Command Ring: Found LINK TRB: New dq_pointer = 0x" FORMATADDRESS " (%i)", (bx_phy_address) org_addr, (bx_phy_address) BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer, BX_XHCI_THIS hub.ring_members.command_ring.rcs)); read_TRB((bx_phy_address) BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer, &trb); continue; // NEC: Get Firmware version case NEC_TRB_TYPE_GET_FW: write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(1) | 0x3021, TRB_SET_TYPE(NEC_TRB_TYPE_CMD_COMP), 1); BX_INFO(("NEC GET Firmware Version TRB found. Returning 0x3021")); break; case ENABLE_SLOT: comp_code = NO_SLOTS_ERROR; // assume no slots slot = 0; slot_type = TRB_GET_STYPE(trb.command); // currently not used for (i=1; i> 16) - 1; // slot:port_num is 1 based new_addr = create_unique_address(slot); if (send_set_address(new_addr, port_num) == 0) { slot_context.slot_state = SLOT_STATE_ADRESSED; slot_context.device_address = new_addr; ep_context.ep_state = EP_STATE_RUNNING; comp_code = TRB_SUCCESS; } else comp_code = TRANSACTION_ERROR; } else comp_code = CONTEXT_STATE_ERROR; } } else // validate contexts comp_code = CONTEXT_STATE_ERROR; } else comp_code = CONTEXT_STATE_ERROR; // A0 and A1 not set correctly } else comp_code = SLOT_NOT_ENABLED; // if successful, copy to the buffer allocated for this slot if (comp_code == TRB_SUCCESS) { memcpy(&BX_XHCI_THIS hub.slots[slot].slot_context, &slot_context, sizeof(struct SLOT_CONTEXT)); memcpy(&BX_XHCI_THIS hub.slots[slot].ep_context[1].ep_context, &ep_context, sizeof(struct EP_CONTEXT)); // initialize our internal enqueue pointer BX_XHCI_THIS hub.slots[slot].ep_context[1].enqueue_pointer = ep_context.tr_dequeue_pointer; BX_XHCI_THIS hub.slots[slot].ep_context[1].rcs = ep_context.dcs; update_slot_context(slot); update_ep_context(slot, 1); // mark that we have done this once before BX_XHCI_THIS hub.slots[slot].sent_address = 1; } write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(comp_code), TRB_SET_SLOT(slot) | TRB_SET_TYPE(COMMAND_COMPLETION), 1); //BX_INFO(("ADDRESS_DEVICE TRB: 0x" FMT_ADDRX64 " 0x%08X 0x%08X", trb.parameter, trb.status, trb.command)); BX_INFO(("0x" FORMATADDRESS ": Command Ring: SetAddress TRB (bsr = %i) (addr = %i) (slot = %i) (returning %i)", (bx_phy_address) org_addr, bsr, new_addr, slot, comp_code)); break; case EVALUATE_CONTEXT: { slot = TRB_GET_SLOT(trb.command); // slots are 1 based if (BX_XHCI_THIS hub.slots[slot].enabled == 1) { DEV_MEM_READ_PHYSICAL_DMA((bx_phy_address) trb.parameter, (CONTEXT_SIZE + (CONTEXT_SIZE * 32)), buffer); ReadHostDWordFromLittleEndian(&buffer[4], a_flags); // only the Slot context and EP1 (control EP) contexts are evaluated. Section 6.2.3.3 // If the slot is not addresses or configured, then return error // FIXME: XHCI specs 1.0, page 102 says DEFAULT or higher, while page 321 states higher than DEFAULT!!! if (BX_XHCI_THIS hub.slots[slot].slot_context.slot_state >= SLOT_STATE_DEFAULT) { comp_code = TRB_SUCCESS; // assume good completion if (a_flags & (1<<0)) { copy_slot_from_buffer(&slot_context, &buffer[CONTEXT_SIZE]); if (!validate_slot_context(&slot_context)) comp_code = PARAMETER_ERROR; } if (a_flags & (1<<1)) { copy_ep_from_buffer(&ep_context, &buffer[CONTEXT_SIZE + CONTEXT_SIZE]); if (!validate_ep_context(&ep_context, BX_XHCI_THIS hub.slots[slot].slot_context.speed, 1)) comp_code = PARAMETER_ERROR; } } else comp_code = CONTEXT_STATE_ERROR; // if all were good, go ahead and update our contexts if (comp_code == TRB_SUCCESS) { for (i=0; i<32; i++) { if (a_flags & (1<get_max_packet_size(); } else BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.max_packet_size = ep_context.max_packet_size; switch (ep_context.ep_type) { case 4: // control BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.cerr = ep_context.cerr; break; case 2: // Bulk out case 6: // Bulk in BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.max_burst_size = ep_context.max_burst_size; BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.cerr = ep_context.cerr; BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.max_pstreams = 0; // we don't support streams yet break; default: // ISO or interrupt BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.max_burst_size = ep_context.max_burst_size; BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.mult = ep_context.mult; BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.cerr = 3; BX_XHCI_THIS hub.slots[slot].ep_context[i].ep_context.max_pstreams = 0; // we don't support streams yet break; } // update our internal enqueue pointer //BX_XHCI_THIS hub.slots[slot].ep_context[i].enqueue_pointer = ep_context.tr_dequeue_pointer; BX_XHCI_THIS hub.slots[slot].ep_context[i].rcs = ep_context.dcs; // update the DCBAAP slot's ep update_ep_context(slot, i); } } } } } else comp_code = SLOT_NOT_ENABLED; write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(comp_code), TRB_SET_SLOT(slot) | TRB_SET_TYPE(COMMAND_COMPLETION), 1); BX_INFO(("0x" FORMATADDRESS ": Command Ring: Evaluate TRB (slot = %i) (a_flags = 0x%08X) (returning %i)", (bx_phy_address) org_addr, slot, a_flags, comp_code)); } break; case CONFIG_EP: { slot = TRB_GET_SLOT(trb.command); // slots are 1 based bx_bool dc = TRB_DC(trb.command); if (BX_XHCI_THIS hub.slots[slot].enabled) { DEV_MEM_READ_PHYSICAL_DMA((bx_phy_address) trb.parameter, (CONTEXT_SIZE + (CONTEXT_SIZE * 32)), buffer); ReadHostDWordFromLittleEndian(&buffer[0], d_flags); ReadHostDWordFromLittleEndian(&buffer[4], a_flags); copy_slot_from_buffer(&slot_context, &buffer[CONTEXT_SIZE]); // so we get entry_count if (BX_XHCI_THIS hub.slots[slot].slot_context.slot_state == SLOT_STATE_CONFIGURED) { for (i=2; i<32; i++) { if (dc || (d_flags & (1<= SLOT_STATE_ADRESSED)) { comp_code = TRB_SUCCESS; // assume good completion // Check all the input context entries with an a_flag == 1 for (i=2; i<32; i++) { if (a_flags & (1< (int) slot_context.entries) || !validate_ep_context(&ep_context, BX_XHCI_THIS hub.slots[slot].slot_context.speed, i)) { comp_code = PARAMETER_ERROR; break; // no need to check the rest } } } // if all were good, go ahead and update our contexts if (comp_code == TRB_SUCCESS) { for (i=2; i<32; i++) { if (d_flags & (1< EP_STATE_DISABLED) { BX_XHCI_THIS hub.slots[slot].slot_context.slot_state = SLOT_STATE_CONFIGURED; break; } } BX_XHCI_THIS hub.slots[slot].slot_context.entries = slot_context.entries; /////// update_slot_context(slot); } } else comp_code = CONTEXT_STATE_ERROR; } else comp_code = SLOT_NOT_ENABLED; // TODO: Page 101 (change to context entries) write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(comp_code), TRB_SET_SLOT(slot) | TRB_SET_TYPE(COMMAND_COMPLETION), 1); BX_INFO(("0x" FORMATADDRESS ": Command Ring: Found Config_EP TRB (slot = %i) (returning %i)", (bx_phy_address) org_addr, slot, comp_code)); } break; case SET_TR_DEQUEUE: slot = TRB_GET_SLOT(trb.command); // slots are 1 based ep = TRB_GET_EP(trb.command); if (BX_XHCI_THIS hub.slots[slot].enabled == 1) { if ((BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_STOPPED) || (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_ERROR)) { BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.tr_dequeue_pointer = BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer = (trb.parameter & (Bit64u) ~0xF); BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.dcs = BX_XHCI_THIS hub.slots[slot].ep_context[ep].rcs = (bx_bool) (trb.parameter & 1); update_ep_context(slot, ep); comp_code = TRB_SUCCESS; } else comp_code = CONTEXT_STATE_ERROR; } else comp_code = SLOT_NOT_ENABLED; // if the state is in error, move it to stopped if (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_ERROR) BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state = EP_STATE_STOPPED; write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(comp_code), TRB_SET_SLOT(slot) | TRB_SET_TYPE(COMMAND_COMPLETION), 1); BX_INFO(("0x" FORMATADDRESS ": Command Ring: Found Set_tr_Dequeue TRB (slot = %i) (ep = %i) (returning %i)", (bx_phy_address) org_addr, slot, ep, comp_code)); if (comp_code == TRB_SUCCESS) BX_INFO((" New address: 0x" FORMATADDRESS " state = %i", (bx_phy_address) BX_XHCI_THIS hub.slots[slot].ep_context[ep].enqueue_pointer, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.dcs)); break; // case RESET_EP: // May only be sent to EP's in the HALTED state. (page 105) // BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_STOPPED; // break; case STOP_EP: slot = TRB_GET_SLOT(trb.command); // slots are 1 based ep = TRB_GET_EP(trb.command); // A Stop Endpoint Command received while an endpoint is in the Error state shall have no effect and shall // generate a Command Completion Event with the Completion Code set to Context State Error. if (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state == EP_STATE_ERROR) comp_code = CONTEXT_STATE_ERROR; else { BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state = EP_STATE_STOPPED; update_ep_context(slot, ep); comp_code = TRB_SUCCESS; } write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(comp_code), TRB_SET_SLOT(slot) | TRB_SET_TYPE(COMMAND_COMPLETION), 1); BX_INFO(("0x" FORMATADDRESS ": Command Ring: Found Stop EP TRB (slot = %i) (ep = %i) (sp = %i) (returning 1)", (bx_phy_address) org_addr, slot, ep, ((trb.command & (1<<23)) == (1<<23)))); break; // Get Port Bandwidth (only available on version 0.96 or 0.95.) case GET_PORT_BAND: { unsigned hub_id = TRB_GET_SLOT(trb.command); unsigned band_speed = ((trb.command & (0x0F << 16)) >> 16) - 1; if (hub_id == 0) { // root hub if (band_speed < 4) { DEV_MEM_WRITE_PHYSICAL_DMA((bx_phy_address) trb.parameter, 1 + USB_XHCI_PORTS, port_band_width[band_speed]); comp_code = TRB_SUCCESS; } else { comp_code = TRB_ERROR; BX_ERROR(("Get Port Bandwidth with unknown speed of %i", band_speed + 1)); } } else { #if SEC_DOMAIN_BAND // TODO: External HUB support comp_code = TRB_ERROR; BX_ERROR(("Get Secondary Port Bandwidth not implemented yet.")); #else write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(TRB_ERROR), TRB_SET_TYPE(COMMAND_COMPLETION), 1); #endif } write_event_TRB(0, org_addr, TRB_SET_COMP_CODE(comp_code), TRB_SET_TYPE(COMMAND_COMPLETION), 1); BX_INFO(("0x" FORMATADDRESS ": Command Ring: GetPortBandwidth TRB (speed = %i) (hub_id = %i) (returning %i)", (bx_phy_address) org_addr, band_speed, hub_id, comp_code)); } break; // unknown TRB type default: BX_ERROR(("0x" FORMATADDRESS ": Command Ring: Unknown TRB found.", (bx_phy_address) org_addr)); BX_ERROR(("Unknown trb type found: %i(dec) (0x" FMT_ADDRX64 " 0x%08X 0x%08X)", TRB_GET_TYPE(trb.command), trb.parameter, trb.status, trb.command)); write_event_TRB(0, 0x0, TRB_SET_COMP_CODE(TRB_ERROR), TRB_SET_TYPE(COMMAND_COMPLETION), 1); } // advance the Dequeue pointer and continue; BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer += 16; read_TRB((bx_phy_address) BX_XHCI_THIS hub.ring_members.command_ring.dq_pointer, &trb); } } void bx_usb_xhci_c::init_event_ring(const unsigned interrupter) { bx_phy_address addr = (bx_phy_address) BX_XHCI_THIS hub.runtime_regs.interrupter[interrupter].erstba.erstabadd; Bit8u entry[16]; Bit32u val32; Bit64u val64; BX_XHCI_THIS hub.ring_members.event_rings[interrupter].rcs = 1; BX_XHCI_THIS hub.ring_members.event_rings[interrupter].count = 0; DEV_MEM_READ_PHYSICAL_DMA(addr, sizeof(BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys), (Bit8u*) BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys); BX_XHCI_THIS hub.ring_members.event_rings[interrupter].cur_trb = BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys[0].addr; BX_XHCI_THIS hub.ring_members.event_rings[interrupter].trb_count = BX_XHCI_THIS hub.ring_members.event_rings[interrupter].entrys[0].size; // dump the event segment table BX_DEBUG(("Interrupter %02i: Event Ring Table has %i entries:", interrupter, BX_XHCI_THIS hub.runtime_regs.interrupter[interrupter].erstsz.erstabsize)); addr = (bx_phy_address) BX_XHCI_THIS hub.runtime_regs.interrupter[interrupter].erstba.erstabadd; for (int i=0; iparameter); ReadHostDWordFromLittleEndian(&buffer[8], trb->status); ReadHostDWordFromLittleEndian(&buffer[12], trb->command); } void bx_usb_xhci_c::write_TRB(bx_phy_address addr, const Bit64u parameter, const Bit32u status, const Bit32u command) { Bit8u buffer[16]; WriteHostQWordToLittleEndian(&buffer[0], parameter); WriteHostDWordToLittleEndian(&buffer[8], status); WriteHostDWordToLittleEndian(&buffer[12], command); DEV_MEM_WRITE_PHYSICAL_DMA(addr, 16, buffer); } void bx_usb_xhci_c::update_slot_context(const int slot) { Bit8u buffer[64]; memset(buffer, 0, 64); copy_slot_to_buffer(buffer, slot); Bit64u slot_addr = (BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap + (slot * sizeof(Bit64u))); DEV_MEM_READ_PHYSICAL_DMA((bx_phy_address) slot_addr, sizeof(Bit64u), (Bit8u *) &slot_addr); DEV_MEM_WRITE_PHYSICAL_DMA((bx_phy_address) slot_addr, CONTEXT_SIZE, buffer); } void bx_usb_xhci_c::update_ep_context(const int slot, const int ep) { Bit8u buffer[64]; memset(buffer, 0, 64); copy_ep_to_buffer(buffer, slot, ep); Bit64u slot_addr = (BX_XHCI_THIS hub.op_regs.HcDCBAAP.dcbaap + (slot * sizeof(Bit64u))); DEV_MEM_READ_PHYSICAL_DMA((bx_phy_address) slot_addr, sizeof(Bit64u), (Bit8u *) &slot_addr); DEV_MEM_WRITE_PHYSICAL_DMA((bx_phy_address) (slot_addr + (ep * CONTEXT_SIZE)), CONTEXT_SIZE, buffer); } void bx_usb_xhci_c::dump_slot_context(const Bit32u *context, const int slot) { BX_INFO((" -=-=-=-=-=-=-=- Slot Context -=-=-=-=-=-=-=-")); BX_INFO((" Context Entries: %i (%i)", (context[0] & (0x1F<<27)) >> 27, BX_XHCI_THIS hub.slots[slot].slot_context.entries)); BX_INFO((" Hub: %i (%i)", (context[0] & (1 <<26)) >> 26, BX_XHCI_THIS hub.slots[slot].slot_context.hub)); BX_INFO((" MTT: %i (%i)", (context[0] & (1 <<25)) >> 25, BX_XHCI_THIS hub.slots[slot].slot_context.mtt)); BX_INFO((" ReservedZ: %02X", (context[0] & (1 <<24)) >> 24)); BX_INFO((" Speed: %i (%i)", (context[0] & (0x0F<<20)) >> 20, BX_XHCI_THIS hub.slots[slot].slot_context.speed)); BX_INFO((" Route String: %05X (%05X)", (context[0] & 0xFFFFF) >> 0, BX_XHCI_THIS hub.slots[slot].slot_context.route_string)); BX_INFO((" Num Ports: %i (%i)", (context[1] & (0xFF<<24)) >> 24, BX_XHCI_THIS hub.slots[slot].slot_context.num_ports)); BX_INFO((" RH Port Num: %i (%i)", (context[1] & (0xFF<<16)) >> 16, BX_XHCI_THIS hub.slots[slot].slot_context.rh_port_num)); BX_INFO(("Max Exit Latency: %i (%i)", (context[1] & 0xFFFF) >> 0, BX_XHCI_THIS hub.slots[slot].slot_context.max_exit_latency)); BX_INFO((" Int Target: %i (%i)", (context[2] & (0x3F<<22)) >> 22, BX_XHCI_THIS hub.slots[slot].slot_context.int_target)); BX_INFO((" ReservedZ: %02X", (context[2] & (0x0F<<18)) >> 18)); BX_INFO((" TTT: %i (%i)", (context[2] & (0x03<<16)) >> 16, BX_XHCI_THIS hub.slots[slot].slot_context.ttt)); BX_INFO((" TT Port Num: %i (%i)", (context[2] & (0xFF<< 8)) >> 8, BX_XHCI_THIS hub.slots[slot].slot_context.tt_port_num)); BX_INFO((" TT Hub Slot: %i (%i)", (context[2] & 0xFF) >> 0, BX_XHCI_THIS hub.slots[slot].slot_context.tt_hub_slot_id)); BX_INFO((" Slot State: %i (%i)", (context[3] & (0x1F<<27)) >> 27, BX_XHCI_THIS hub.slots[slot].slot_context.slot_state)); BX_INFO((" ReservedZ: %06X", (context[3] & (0x7FFFF<<8)) >> 8)); BX_INFO((" Dev Address: %i (%i)", (context[3] & 0xFF) >> 0, BX_XHCI_THIS hub.slots[slot].slot_context.device_address)); BX_INFO((" ReservedZ: %08X", context[4])); BX_INFO((" ReservedZ: %08X", context[5])); BX_INFO((" ReservedZ: %08X", context[6])); BX_INFO((" ReservedZ: %08X", context[7])); #if (CONTEXT_SIZE == 64) BX_INFO((" ReservedZ: %08x", context[8])); BX_INFO((" ReservedZ: %08x", context[9])); BX_INFO((" ReservedZ: %08x", context[10])); BX_INFO((" ReservedZ: %08x", context[11])); BX_INFO((" ReservedZ: %08x", context[12])); BX_INFO((" ReservedZ: %08x", context[13])); BX_INFO((" ReservedZ: %08x", context[14])); BX_INFO((" ReservedZ: %08x", context[15])); #endif } void bx_usb_xhci_c::dump_ep_context(const Bit32u *context, const int slot, const int ep) { BX_INFO((" -=-=-=-=-=-=-=-=- EP Context -=-=-=-=-=-=-=-")); BX_INFO((" ReservedZ: %02x", (context[0] & (0xFF<<24)) >> 24)); BX_INFO((" Interval: %i (%i)", (context[0] & (0x0F<<20)) >> 20, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.interval)); BX_INFO((" LSA: %i (%i)", (context[0] & (1 <<15)) >> 15, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.lsa)); BX_INFO((" MaxPStreams: %i (%i)", (context[0] & (0x1F<<10)) >> 10, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_pstreams)); BX_INFO((" Mult: %i (%i)", (context[0] & (0x03<< 8)) >> 8, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.mult)); BX_INFO((" ReservedZ: %02x", (context[0] & (0x1F<< 3)) >> 3)); BX_INFO((" EP State: %i (%i)", (context[0] & 0x7) >> 0, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state)); BX_INFO((" Max Packet Size: %i (%i)", (context[1] & (0xFFFF<<16)) >> 16, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_packet_size)); BX_INFO((" Max Burst Size: %i (%i)", (context[1] & (0xFF<< 8)) >> 8, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_burst_size)); BX_INFO((" HID: %i (%i)", (context[1] & (1 << 7)) >> 7, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.hid)); BX_INFO((" ReservedZ: %01x", (context[1] & (1 << 6)) >> 6)); BX_INFO((" EP Type: %i (%i)", (context[1] & (0x07<< 3)) >> 3, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_type)); BX_INFO((" CErr: %i (%i)", (context[1] & (0x03<< 1)) >> 1, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.cerr)); BX_INFO((" ReservedZ: %01x", (context[1] & (1 << 0)) >> 0)); BX_INFO((" TR Dequeue Ptr: " FMT_ADDRX64 " (" FMT_ADDRX64 ")", (*(Bit64u *) &context[2] & (Bit64u) ~0x0F), BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.tr_dequeue_pointer)); BX_INFO((" ReservedZ: %01x", (context[2] & (0x07 << 1)) >> 1)); BX_INFO((" DCS: %i (%i)", (context[2] & (1 << 0)) >> 0, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.dcs)); BX_INFO(("Avg ESIT Payload: %i (%i)", (context[4] & (0xFFFF<<16)) >> 16, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_esit_payload)); BX_INFO((" Avg TRB Length: %i (%i)", (context[4] & (0xFFFF<< 0)) >> 0, BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.average_trb_len)); BX_INFO((" ReservedZ: %08x", context[5])); BX_INFO((" ReservedZ: %08x", context[6])); BX_INFO((" ReservedZ: %08x", context[7])); #if (CONTEXT_SIZE == 64) BX_INFO((" ReservedZ: %08x", context[8])); BX_INFO((" ReservedZ: %08x", context[9])); BX_INFO((" ReservedZ: %08x", context[10])); BX_INFO((" ReservedZ: %08x", context[11])); BX_INFO((" ReservedZ: %08x", context[12])); BX_INFO((" ReservedZ: %08x", context[13])); BX_INFO((" ReservedZ: %08x", context[14])); BX_INFO((" ReservedZ: %08x", context[15])); #endif } void bx_usb_xhci_c::copy_slot_from_buffer(struct SLOT_CONTEXT *slot_context, const Bit8u *buffer) { slot_context->entries = (*(Bit32u *) &buffer[0]) >> 27; slot_context->hub = ((*(Bit32u *) &buffer[0]) & (1<<26)) ? 1 : 0; slot_context->mtt = ((*(Bit32u *) &buffer[0]) & (1<<25)) ? 1 : 0; slot_context->speed = ((*(Bit32u *) &buffer[0]) & (0x0F<<20)) >> 20; slot_context->route_string = ((*(Bit32u *) &buffer[0]) & 0x0007FFFF); slot_context->num_ports = (*(Bit32u *) &buffer[4]) >> 24; slot_context->rh_port_num = ((*(Bit32u *) &buffer[4]) & (0xFF<<16)) >> 16; slot_context->max_exit_latency = (*(Bit32u *) &buffer[4]) & 0xFFFF; slot_context->int_target = (*(Bit32u *) &buffer[8]) >> 22; slot_context->ttt = ((*(Bit32u *) &buffer[8]) & (0x3<<16)) >> 16; slot_context->tt_port_num = ((*(Bit32u *) &buffer[8]) & (0xFF<<8)) >> 8; slot_context->tt_hub_slot_id = (*(Bit32u *) &buffer[8]) & 0xFF; slot_context->slot_state = (*(Bit32u *) &buffer[12]) >> 27; slot_context->device_address = (*(Bit32u *) &buffer[12]) & 0xFF; } void bx_usb_xhci_c::copy_ep_from_buffer(struct EP_CONTEXT *ep_context, const Bit8u *buffer) { ep_context->interval = ((*(Bit32u *) &buffer[0]) & (0xFF<<16)) >> 16; ep_context->lsa = ((*(Bit32u *) &buffer[0]) & (1<<15)) ? 1 : 0; ep_context->max_pstreams = ((*(Bit32u *) &buffer[0]) & (0x1F<<10)) >> 10; ep_context->mult = ((*(Bit32u *) &buffer[0]) & (0x03<<8)) >> 8; ep_context->ep_state = (*(Bit32u *) &buffer[0]) & 0x07; ep_context->max_packet_size = (*(Bit32u *) &buffer[4]) >> 16; ep_context->max_burst_size = ((*(Bit32u *) &buffer[4]) & (0xFF<<8)) >> 8; ep_context->hid = ((*(Bit32u *) &buffer[4]) & (1<<7)) ? 1 : 0; ep_context->ep_type = ((*(Bit32u *) &buffer[4]) & (0x07<<3)) >> 3; ep_context->cerr = ((*(Bit32u *) &buffer[4]) & (0x03<<1)) >> 1; ep_context->tr_dequeue_pointer = (*(Bit64u *) &buffer[8]) & (Bit64u) ~0xF; ep_context->dcs = (*(Bit64u *) &buffer[8]) & (1<<0); ep_context->max_esit_payload = (*(Bit32u *) &buffer[16]) >> 16; ep_context->average_trb_len = (*(Bit32u *) &buffer[16]) & 0xFFFF; } void bx_usb_xhci_c::copy_slot_to_buffer(const Bit8u *buffer, const int slot) { (*(Bit32u *) &buffer[0]) = (BX_XHCI_THIS hub.slots[slot].slot_context.entries << 27) | (BX_XHCI_THIS hub.slots[slot].slot_context.hub << 26) | (BX_XHCI_THIS hub.slots[slot].slot_context.mtt << 25) | (BX_XHCI_THIS hub.slots[slot].slot_context.speed << 20) | BX_XHCI_THIS hub.slots[slot].slot_context.route_string; (*(Bit32u *) &buffer[4]) = (BX_XHCI_THIS hub.slots[slot].slot_context.num_ports << 24) | (BX_XHCI_THIS hub.slots[slot].slot_context.rh_port_num << 16) | BX_XHCI_THIS hub.slots[slot].slot_context.max_exit_latency; (*(Bit32u *) &buffer[8]) = (BX_XHCI_THIS hub.slots[slot].slot_context.int_target << 22) | (BX_XHCI_THIS hub.slots[slot].slot_context.ttt << 16) | (BX_XHCI_THIS hub.slots[slot].slot_context.tt_port_num << 8) | BX_XHCI_THIS hub.slots[slot].slot_context.tt_hub_slot_id; (*(Bit32u *) &buffer[12]) = (BX_XHCI_THIS hub.slots[slot].slot_context.slot_state << 27) | BX_XHCI_THIS hub.slots[slot].slot_context.device_address; } void bx_usb_xhci_c::copy_ep_to_buffer(const Bit8u *buffer, const int slot, const int ep) { (*(Bit32u *) &buffer[0]) = (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.interval << 16) | (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.lsa << 15) | (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_pstreams << 10) | (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.mult << 8) | BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_state; (*(Bit32u *) &buffer[4]) = (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_packet_size << 16) | (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_burst_size << 8) | (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.hid << 7) | (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.ep_type << 3) | (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.cerr << 1); (*(Bit64u *) &buffer[8]) = BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.tr_dequeue_pointer | BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.dcs; (*(Bit32u *) &buffer[16]) = (BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.max_esit_payload << 16) | BX_XHCI_THIS hub.slots[slot].ep_context[ep].ep_context.average_trb_len; } bx_bool bx_usb_xhci_c::validate_slot_context(const struct SLOT_CONTEXT *slot_context) { // specs:6.2.2.3: Only checks the Interrupter Target and Max Latency fields for validity // See also 4.6.7 // only the Interrupter Target and Max Exit Latency are evaluated BX_INFO((" slot_context->int_target = %i, slot_context->max_exit_latency = %i", slot_context->int_target, slot_context->max_exit_latency)); return 1; } bx_bool bx_usb_xhci_c::validate_ep_context(const struct EP_CONTEXT *ep_context, int speed, int ep_num) { // Only the Max_packet Size is evaluated (for an evaluate ep command) ??? // max_packet_size is assumed to be a multiple of 8 BX_INFO((" ep_num = %i, speed = %i, ep_context->max_packet_size = %i", ep_num, speed, ep_context->max_packet_size)); // if speed == -1, don't check the speed if ((ep_num == 1) && (speed != -1)) { return ( ((speed == SPEED_LOW) && (ep_context->max_packet_size == 8)) || ((speed == SPEED_FULL) && (ep_context->max_packet_size <= 64)) || // this may need to retrieve the mps from usb_common.c ((speed == SPEED_HI) && (ep_context->max_packet_size == 64)) || ((speed == SPEED_SUPER) && (ep_context->max_packet_size == 512)) ); } else return 1; } // The Specs say that the address is only unique to the RH Port Number // For now, we simply return the slot number (+1); int bx_usb_xhci_c::create_unique_address(const int slot) { return (slot + 1); // Windows may need the first one to be 2 (though it shouldn't know the difference for xHCI) } int bx_usb_xhci_c::send_set_address(const int addr, const int port_num) { int ret; USBPacket packet; static Bit8u setup_address[8] = { 0, 0x05, 0, 0, 0, 0, 0 }; WriteHostWordToLittleEndian(&setup_address[2], addr); packet.pid = USB_TOKEN_SETUP; packet.devep = 0; packet.devaddr = 0; // default address packet.len = 8; packet.data = setup_address; ret = BX_XHCI_THIS broadcast_packet(&packet, port_num); if (ret == 0) { packet.pid = USB_TOKEN_IN; packet.len = 0; ret = BX_XHCI_THIS broadcast_packet(&packet, port_num); } return ret; } int bx_usb_xhci_c::broadcast_packet(USBPacket *p, const int port) { int ret = USB_RET_NODEV; if (BX_XHCI_THIS hub.usb_port[port].device != NULL) ret = BX_XHCI_THIS hub.usb_port[port].device->handle_packet(p); return ret; } /* void bx_usb_xhci_c::usb_frame_handler(void *this_ptr) { bx_usb_xhci_c *class_ptr = (bx_usb_xhci_c *) this_ptr; class_ptr->usb_frame_timer(); } // Called once every ???? void bx_usb_xhci_c::usb_frame_timer(void) { // Nothing for now } */ void bx_usb_xhci_c::runtime_config_handler(void *this_ptr) { bx_usb_xhci_c *class_ptr = (bx_usb_xhci_c *) this_ptr; class_ptr->runtime_config(); } void bx_usb_xhci_c::runtime_config(void) { int i; char pname[6]; for (i = 0; i < BX_N_USB_XHCI_PORTS; i++) { // device change support if ((BX_XHCI_THIS hub.device_change & (1 << i)) != 0) { BX_INFO(("USB port #%d: device connect", i+1)); sprintf(pname, "port%d", i + 1); init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_XHCI))); BX_XHCI_THIS hub.device_change &= ~(1 << i); } // forward to connected device if (BX_XHCI_THIS hub.usb_port[i].device != NULL) { BX_XHCI_THIS hub.usb_port[i].device->runtime_config(); } } } // pci configuration space read callback handler Bit32u bx_usb_xhci_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x14) && (address <= 0x34))) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_XHCI_THIS pci_conf[address+i]; switch (address+i) { case 0x04: value8 &= 0x06; // (bit 0 is read only for this card) (we don't allow port IO) BX_XHCI_THIS pci_conf[address+i] = value8; break; case 0x3d: // case 0x3e: // case 0x3f: // case 0x05: // disallowing write to command hi-byte case 0x06: // disallowing write to status lo-byte (is that expected?) break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); BX_XHCI_THIS pci_conf[address+i] = value8; } break; case 0x10: // low 12 bits of BAR are R/O value8 = 0x00; case 0x11: // low 12 bits of BAR are R/O value8 &= 0xF0; case 0x12: case 0x13: baseaddr_change |= (value8 != oldval); default: BX_XHCI_THIS pci_conf[address+i] = value8; } } if (baseaddr_change) { if (DEV_pci_set_base_mem(BX_XHCI_THIS_PTR, read_handler, write_handler, &BX_XHCI_THIS pci_base_address[0], &BX_XHCI_THIS pci_conf[0x10], IO_SPACE_SIZE)) { BX_INFO(("new base address: 0x%04x", BX_XHCI_THIS pci_base_address[0])); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } void bx_usb_xhci_c::usb_set_connect_status(Bit8u port, int type, bx_bool connected) { const bx_bool ccs_org = BX_XHCI_THIS hub.usb_port[port].portsc.ccs; const bx_bool ped_org = BX_XHCI_THIS hub.usb_port[port].portsc.ped; usb_device_c *device = BX_XHCI_THIS hub.usb_port[port].device; if (device != NULL) { if (device->get_type() == type) { if (connected) { BX_XHCI_THIS hub.usb_port[port].portsc.speed = (device->get_speed() == USB_SPEED_LOW) ? 2 : 1; BX_XHCI_THIS hub.usb_port[port].portsc.ccs = 1; if (!device->get_connected()) { if (!device->init()) { usb_set_connect_status(port, type, 0); BX_ERROR(("port #%d: connect failed", port+1)); } else { BX_INFO(("port #%d: connect: %s", port+1, device->get_info())); } } } else { // not connected BX_XHCI_THIS hub.usb_port[port].portsc.ccs = 0; BX_XHCI_THIS hub.usb_port[port].portsc.ped = 0; BX_XHCI_THIS hub.usb_port[port].portsc.speed = 0; remove_device(port); } } if (ccs_org != BX_XHCI_THIS hub.usb_port[port].portsc.ccs) BX_XHCI_THIS hub.usb_port[port].portsc.csc = 1; if (ped_org != BX_XHCI_THIS hub.usb_port[port].portsc.ped) BX_XHCI_THIS hub.usb_port[port].portsc.pec = 1; // we changed the value of the port, so show it BX_INFO(("Port Status Change Event.")); write_event_TRB(0, ((port + 1) << 24), TRB_SET_COMP_CODE(1), TRB_SET_TYPE(PORT_STATUS_CHANGE), 1); } } // USB runtime parameter handler const char *bx_usb_xhci_c::usb_param_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { usbdev_type type = USB_DEV_TYPE_NONE; int portnum; if (set) { portnum = atoi((param->get_parent())->get_name()+4) - 1; bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none"))); if ((portnum >= 0) && (portnum < USB_XHCI_PORTS)) { if (empty && BX_XHCI_THIS hub.usb_port[portnum].portsc.ccs) { BX_INFO(("USB port #%d: device disconnect", portnum+1)); if (BX_XHCI_THIS hub.usb_port[portnum].device != NULL) { type = BX_XHCI_THIS hub.usb_port[portnum].device->get_type(); } usb_set_connect_status(portnum, type, 0); } else if (!empty && !BX_XHCI_THIS hub.usb_port[portnum].portsc.ccs) { BX_XHCI_THIS hub.device_change |= (1 << portnum); } } else { BX_PANIC(("usb_param_handler called with unexpected parameter '%s'", param->get_name())); } } return val; } void bx_usb_xhci_c::dump_xhci_core(const int slots, const int eps) { bx_phy_address addr = BX_XHCI_THIS pci_base_address[0]; Bit32u dword; Bit64u qword, slot_addr; int p, i; Bit8u buffer[4096]; // dump the caps registers BX_INFO((" CAPLENGTH: 0x%02X", BX_XHCI_THIS hub.cap_regs.HcCapLength & 0xFF)); BX_INFO(("HC VERSION: %X.%02X", ((BX_XHCI_THIS hub.cap_regs.HcCapLength & 0xFF000000) >> 24), ((BX_XHCI_THIS hub.cap_regs.HcCapLength & 0x00FF0000) >> 16))); BX_INFO(("HCSPARAMS1: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcSParams1)); BX_INFO(("HCSPARAMS2: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcSParams2)); BX_INFO(("HCSPARAMS3: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcSParams3)); BX_INFO((" HCCPARAMS: 0x%08X", BX_XHCI_THIS hub.cap_regs.HcCParams)); BX_INFO((" DBOFF: 0x%08X", BX_XHCI_THIS hub.cap_regs.DBOFF)); BX_INFO((" RTSOFF: 0x%08X", BX_XHCI_THIS hub.cap_regs.RTSOFF)); // dump the operational registers BX_XHCI_THIS read_handler(addr + 0x20, 4, &dword, NULL); BX_INFO((" USB_COMMAND: 0x%08X", dword)); BX_XHCI_THIS read_handler(addr + 0x24, 4, &dword, NULL); BX_INFO((" USB_STATUS: 0x%08X", dword)); BX_XHCI_THIS read_handler(addr + 0x28, 4, &dword, NULL); BX_INFO((" PAGE_SIZE: 0x%08X", dword)); BX_XHCI_THIS read_handler(addr + 0x34, 4, &dword, NULL); BX_INFO((" DNCTRL: 0x%08X", dword)); BX_XHCI_THIS read_handler(addr + 0x38, 8, &qword, NULL); BX_INFO((" CRCR: 0x" FMT_ADDRX64, qword)); BX_XHCI_THIS read_handler(addr + 0x50, 8, &qword, NULL); BX_INFO((" DCBAAP: 0x" FMT_ADDRX64, qword)); BX_XHCI_THIS read_handler(addr + 0x58, 4, &dword, NULL); BX_INFO((" CONFIG: 0x%08X", dword)); for (i=0, p=0; iset_mouse_mode_absxy(1); } else if (d.type == USB_DEV_TYPE_KEYPAD) { strcpy(d.devname, "USB/PS2 Keypad"); DEV_register_removable_keyboard((void*)this, key_enq_static); } d.connected = 1; memset((void*)&s, 0, sizeof(s)); put("usb_hid", "USBHI"); } usb_hid_device_c::~usb_hid_device_c(void) { if ((d.type == USB_DEV_TYPE_MOUSE) || (d.type == USB_DEV_TYPE_TABLET)) { bx_gui->set_mouse_mode_absxy(0); DEV_unregister_removable_mouse((void*)this); } else if (d.type == USB_DEV_TYPE_KEYPAD) { DEV_unregister_removable_keyboard((void*)this); } } void usb_hid_device_c::register_state_specific(bx_list_c *parent) { bx_list_c *key; Bit8u i; char name[6]; bx_list_c *list = new bx_list_c(parent, "s", "USB HID Device State"); new bx_shadow_num_c(list, "mouse_delayed_dx", &s.mouse_delayed_dx); new bx_shadow_num_c(list, "mouse_delayed_dy", &s.mouse_delayed_dy); new bx_shadow_num_c(list, "mouse_delayed_dz", &s.mouse_delayed_dz); new bx_shadow_num_c(list, "mouse_x", &s.mouse_x); new bx_shadow_num_c(list, "mouse_y", &s.mouse_y); new bx_shadow_num_c(list, "mouse_z", &s.mouse_z); new bx_shadow_num_c(list, "b_state", &s.b_state, BASE_HEX); key = new bx_list_c(list, "saved_key"); for (i=0; i<8; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(key, name, &s.saved_key[i], BASE_HEX); } key = new bx_list_c(list, "key_pad_packet"); for (i=0; i<8; i++) { sprintf(name, "0x%02x", i); new bx_shadow_num_c(key, name, &s.key_pad_packet[i], BASE_HEX); } } void usb_hid_device_c::handle_reset() { memset((void*)&s, 0, sizeof(s)); BX_DEBUG(("Reset")); } int usb_hid_device_c::handle_control(int request, int value, int index, int length, Bit8u *data) { int ret = 0; switch(request) { case DeviceRequest | USB_REQ_GET_STATUS: if (d.state == USB_STATE_DEFAULT) goto fail; else { data[0] = (1 << USB_DEVICE_SELF_POWERED) | (d.remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; } break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: d.state = USB_STATE_ADDRESS; d.addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: if ((d.type == USB_DEV_TYPE_MOUSE) || (d.type == USB_DEV_TYPE_TABLET)) { memcpy(data, bx_mouse_dev_descriptor, sizeof(bx_mouse_dev_descriptor)); ret = sizeof(bx_mouse_dev_descriptor); } else if (d.type == USB_DEV_TYPE_KEYPAD) { memcpy(data, bx_keypad_dev_descriptor, sizeof(bx_keypad_dev_descriptor)); ret = sizeof(bx_keypad_dev_descriptor); } else { goto fail; } break; case USB_DT_CONFIG: if (d.type == USB_DEV_TYPE_MOUSE) { memcpy(data, bx_mouse_config_descriptor, sizeof(bx_mouse_config_descriptor)); ret = sizeof(bx_mouse_config_descriptor); } else if (d.type == USB_DEV_TYPE_TABLET) { memcpy(data, bx_tablet_config_descriptor, sizeof(bx_tablet_config_descriptor)); ret = sizeof(bx_tablet_config_descriptor); } else if (d.type == USB_DEV_TYPE_KEYPAD) { memcpy(data, bx_keypad_config_descriptor, sizeof(bx_keypad_config_descriptor)); ret = sizeof(bx_keypad_config_descriptor); } else { goto fail; } break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* serial number */ ret = set_usb_string(data, "1"); break; case 2: /* product description */ if (strlen(d.devname) > 0) { ret = set_usb_string(data, d.devname); } else { goto fail; } break; case 3: /* vendor description */ ret = set_usb_string(data, "BOCHS"); break; case 4: ret = set_usb_string(data, "HID Mouse"); break; case 5: ret = set_usb_string(data, "Endpoint1 Interrupt Pipe"); break; default: BX_ERROR(("USB HID handle_control: unknown string descriptor 0x%02x", value & 0xff)); goto fail; } break; default: BX_ERROR(("USB HID handle_control: unknown descriptor type 0x%02x", value >> 8)); goto fail; } break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: data[0] = 1; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: d.state = USB_STATE_CONFIGURED; ret = 0; break; case DeviceRequest | USB_REQ_GET_INTERFACE: data[0] = 0; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_INTERFACE: ret = 0; break; /* hid specific requests */ case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case 0x21: if (d.type == USB_DEV_TYPE_MOUSE) { memcpy(data, bx_mouse_hid_descriptor, sizeof(bx_mouse_hid_descriptor)); ret = sizeof(bx_mouse_hid_descriptor); } else if (d.type == USB_DEV_TYPE_TABLET) { memcpy(data, bx_tablet_hid_descriptor, sizeof(bx_tablet_hid_descriptor)); ret = sizeof(bx_tablet_hid_descriptor); } else if (d.type == USB_DEV_TYPE_KEYPAD) { memcpy(data, bx_keypad_hid_descriptor, sizeof(bx_keypad_hid_descriptor)); ret = sizeof(bx_keypad_hid_descriptor); } else { goto fail; } break; case 0x22: if (d.type == USB_DEV_TYPE_MOUSE) { memcpy(data, bx_mouse_hid_report_descriptor, sizeof(bx_mouse_hid_report_descriptor)); ret = sizeof(bx_mouse_hid_report_descriptor); } else if (d.type == USB_DEV_TYPE_TABLET) { memcpy(data, bx_tablet_hid_report_descriptor, sizeof(bx_tablet_hid_report_descriptor)); ret = sizeof(bx_tablet_hid_report_descriptor); } else if (d.type == USB_DEV_TYPE_KEYPAD) { if (index == 0) { memcpy(data, bx_keypad_hid_report_descriptor1, sizeof(bx_keypad_hid_report_descriptor1)); ret = sizeof(bx_keypad_hid_report_descriptor1); } else { memcpy(data, bx_keypad_hid_report_descriptor2, sizeof(bx_keypad_hid_report_descriptor2)); ret = sizeof(bx_keypad_hid_report_descriptor2); } } else { goto fail; } break; case 0x23: BX_ERROR(("USB HID handle_control: Host requested the HID Physical Descriptor")); goto fail; default: BX_ERROR(("USB HID handle_control: unknown HID descriptor 0x%02x", value >> 8)); goto fail; } break; case GET_REPORT: if ((d.type == USB_DEV_TYPE_MOUSE) || (d.type == USB_DEV_TYPE_TABLET)) { ret = mouse_poll(data, length); } else if (d.type == USB_DEV_TYPE_KEYPAD) { ret = keypad_poll(data, length); } else { goto fail; } break; case SET_REPORT: if ((d.type == USB_DEV_TYPE_KEYPAD) && (value = 0x200)) { BX_INFO(("keypad NUMLOCK %s", (data[0] & 0x01) ? "on" : "off")); ret = 0; } else { goto fail; } break; case SET_IDLE: case SET_PROTOCOL: ret = 0; break; default: BX_ERROR(("USB HID handle_control: unknown request 0x%04x", request)); fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } int usb_hid_device_c::handle_data(USBPacket *p) { int ret = 0; switch(p->pid) { case USB_TOKEN_IN: if (p->devep == 1) { if ((d.type == USB_DEV_TYPE_MOUSE) || (d.type == USB_DEV_TYPE_TABLET)) { ret = mouse_poll(p->data, p->len); } else if (d.type == USB_DEV_TYPE_KEYPAD) { ret = keypad_poll(p->data, p->len); } else { goto fail; } } else if (p->devep == 2) { if (d.type == USB_DEV_TYPE_KEYPAD) { ret = mouse_poll(p->data, p->len); } else { goto fail; } } else { goto fail; } break; case USB_TOKEN_OUT: BX_ERROR(("USB HID handle_data: unexpected pid TOKEN_OUT")); default: fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } int usb_hid_device_c::mouse_poll(Bit8u *buf, int len) { int l = 0; if ((d.type == USB_DEV_TYPE_MOUSE) || (d.type == USB_DEV_TYPE_KEYPAD)) { if (!s.mouse_x && !s.mouse_y) { // if there's no new movement, handle delayed one mouse_enq(0, 0, s.mouse_z, s.b_state, 0); } buf[0] = (Bit8u) s.b_state; buf[1] = (Bit8s) s.mouse_x; buf[2] = (Bit8s) s.mouse_y; s.mouse_x = 0; s.mouse_y = 0; l = 3; if (len >= 4) { buf[3] = (Bit8s) s.mouse_z; // if wheel mouse s.mouse_z = 0; l = 4; } } else if (d.type == USB_DEV_TYPE_TABLET) { buf[0] = (Bit8u) s.b_state; buf[1] = (Bit8u)(s.mouse_x & 0xff); buf[2] = (Bit8u)(s.mouse_x >> 8); buf[3] = (Bit8u)(s.mouse_y & 0xff); buf[4] = (Bit8u)(s.mouse_y >> 8); buf[5] = (Bit8s) s.mouse_z; s.mouse_z = 0; l = 6; } return l; } void usb_hid_device_c::mouse_enabled_changed(void *dev, bx_bool enabled) { if (enabled) ((usb_hid_device_c*)dev)->handle_reset(); } void usb_hid_device_c::mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy) { ((usb_hid_device_c*)dev)->mouse_enq(delta_x, delta_y, delta_z, button_state, absxy); } void usb_hid_device_c::mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state, bx_bool absxy) { if (d.type == USB_DEV_TYPE_MOUSE) { // scale down the motion if ((delta_x < -1) || (delta_x > 1)) delta_x /= 2; if ((delta_y < -1) || (delta_y > 1)) delta_y /= 2; if (delta_x>127) delta_x=127; if (delta_y>127) delta_y=127; if (delta_x<-128) delta_x=-128; if (delta_y<-128) delta_y=-128; s.mouse_delayed_dx+=delta_x; s.mouse_delayed_dy-=delta_y; if (s.mouse_delayed_dx > 127) { delta_x = 127; s.mouse_delayed_dx -= 127; } else if (s.mouse_delayed_dx < -128) { delta_x = -128; s.mouse_delayed_dx += 128; } else { delta_x = s.mouse_delayed_dx; s.mouse_delayed_dx = 0; } if (s.mouse_delayed_dy > 127) { delta_y = 127; s.mouse_delayed_dy -= 127; } else if (s.mouse_delayed_dy < -128) { delta_y = -128; s.mouse_delayed_dy += 128; } else { delta_y = s.mouse_delayed_dy; s.mouse_delayed_dy = 0; } s.mouse_x = (Bit8s) delta_x; s.mouse_y = (Bit8s) delta_y; } else if (d.type == USB_DEV_TYPE_TABLET) { if (absxy) { s.mouse_x = delta_x; s.mouse_y = delta_y; } else { s.mouse_x += delta_x; s.mouse_y -= delta_y; } if (s.mouse_x < 0) s.mouse_x = 0; if (s.mouse_y < 0) s.mouse_y = 0; } s.mouse_z = (Bit8s) delta_z; s.b_state = (Bit8u) button_state; } int usb_hid_device_c::keypad_poll(Bit8u *buf, int len) { int l = 0; if (d.type == USB_DEV_TYPE_KEYPAD) { memcpy(buf, s.key_pad_packet, len); l = 8; } return l; } bx_bool usb_hid_device_c::key_enq_static(void *dev, Bit8u *scan_code) { return ((usb_hid_device_c*)dev)->key_enq(scan_code); } bx_bool usb_hid_device_c::key_enq(Bit8u *scan_code) { bx_bool is_break_code = 0; Bit8u our_scan_code[8]; memset(our_scan_code, 0, 8); int os = 0; for (int sc=0; sc<8; sc++) { if ((scan_code[sc] == 0xF0) && ((sc == 0) || ((sc == 1) && (scan_code[0] == 0xE0)))) { is_break_code = 1; } else { if (!(our_scan_code[os++] = scan_code[sc])) break; } } // if it is the break code of the saved key, then clear our packet key. if (is_break_code && !memcmp(s.saved_key, our_scan_code, 8)) { memset(s.saved_key, 0, 8); memset(s.key_pad_packet, 0, 8); return 1; // tell the keyboard handler that we used it, and to return with out processing key } bx_bool fnd = 0; for (int m = 0; m < 18; m++) { if (!memcmp(keypad_lookup[m].scan_code, our_scan_code, 8)) { memcpy(s.key_pad_packet, keypad_lookup[m].keypad_packet, 8); fnd = 1; break; } } if (!fnd) { memset(s.key_pad_packet, 0, 8); memset(s.saved_key, 0, 8); } else { memcpy(s.saved_key, our_scan_code, 8); // print a debug line to the log file char bx_debug_code[128] = ""; char value[8]; for (unsigned i=0; ihd_size / 512) - 1; sprintf(drive_serial_str, "%d", serial_number++); put("SCSID"); } #ifdef LOWLEVEL_CDROM scsi_device_t::scsi_device_t(LOWLEVEL_CDROM *_cdrom, int _tcq, scsi_completionfn _completion, void *_dev) { type = SCSIDEV_TYPE_CDROM; cdrom = _cdrom; hdimage = NULL; requests = NULL; sense = 0; tcq = _tcq; completion = _completion; dev = _dev; cluster_size = 4; locked = 0; inserted = 1; max_lba = cdrom->capacity() - 1; sprintf(drive_serial_str, "%d", serial_number++); put("SCSIC"); } #endif scsi_device_t::~scsi_device_t(void) { SCSIRequest *r, *next; if (requests) { r = requests; while (r != NULL) { next = r->next; delete r; r = next; } } if (free_requests) { r = free_requests; while (r != NULL) { next = r->next; delete r; r = next; } free_requests = NULL; } } void scsi_device_t::register_state(bx_list_c *parent, const char *name) { bx_list_c *list = new bx_list_c(parent, name, ""); new bx_shadow_num_c(list, "sense", &sense); // TODO: save/restore for SCSI requests } SCSIRequest* scsi_device_t::scsi_new_request(Bit32u tag) { SCSIRequest *r; if (free_requests) { r = free_requests; free_requests = r->next; } else { r = new SCSIRequest; } r->dev = this; r->tag = tag; r->sector_count = 0; r->buf_len = 0; r->status = 0; r->next = requests; requests = r; return r; } void scsi_device_t::scsi_remove_request(SCSIRequest *r) { SCSIRequest *last; if (requests == r) { requests = r->next; } else { last = requests; while (last != NULL) { if (last->next != r) last = last->next; else break; } if (last) { last->next = r->next; } else { BX_ERROR(("orphaned request")); } } r->next = free_requests; free_requests = r; } SCSIRequest* scsi_device_t::scsi_find_request(Bit32u tag) { SCSIRequest *r = requests; while (r != NULL) { if (r->tag != tag) r = r->next; else break; } return r; } void scsi_device_t::scsi_command_complete(SCSIRequest *r, int status, int _sense) { Bit32u tag; BX_DEBUG(("command complete tag=0x%x status=%d sense=%d", r->tag, status, sense)); sense = _sense; tag = r->tag; scsi_remove_request(r); completion(dev, SCSI_REASON_DONE, tag, status); } void scsi_device_t::scsi_cancel_io(Bit32u tag) { BX_DEBUG(("cancel tag=0x%x", tag)); SCSIRequest *r = scsi_find_request(tag); if (r) { scsi_remove_request(r); } } void scsi_device_t::scsi_read_complete(void *req, int ret) { SCSIRequest *r = (SCSIRequest *)req; if (ret) { BX_ERROR(("IO error")); completion(r, SCSI_REASON_DATA, r->tag, 0); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NO_SENSE); return; } BX_DEBUG(("data ready tag=0x%x len=%d", r->tag, r->buf_len)); completion(dev, SCSI_REASON_DATA, r->tag, r->buf_len); } void scsi_device_t::scsi_read_data(Bit32u tag) { Bit32u n; int ret; SCSIRequest *r = scsi_find_request(tag); if (!r) { BX_ERROR(("bad read tag 0x%x", tag)); // ??? This is the wrong error. scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); return; } if (r->sector_count == (Bit32u)-1) { BX_DEBUG(("read buf_len=%d", r->buf_len)); r->sector_count = 0; completion(dev, SCSI_REASON_DATA, r->tag, r->buf_len); return; } BX_DEBUG(("read sector_count=%d", r->sector_count)); if (r->sector_count == 0) { scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE); return; } n = r->sector_count; if (n > (Bit32u)(SCSI_DMA_BUF_SIZE / (512 * cluster_size))) n = SCSI_DMA_BUF_SIZE / (512 * cluster_size); r->buf_len = n * 512 * cluster_size; if (type == SCSIDEV_TYPE_CDROM) { #ifdef LOWLEVEL_CDROM if (!cdrom->read_block(r->dma_buf, (Bit32u)r->sector, 2048)) { scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); } else { scsi_read_complete((void*)r, 0); } #else scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); #endif } else { ret = (int)hdimage->lseek(r->sector * 512, SEEK_SET); if (ret < 0) { BX_ERROR(("could not lseek() hard drive image file")); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); } ret = hdimage->read((bx_ptr_t)r->dma_buf, r->buf_len); if (ret < r->buf_len) { BX_ERROR(("could not read() hard drive image file")); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); } else { scsi_read_complete((void*)r, 0); } } r->sector += n; r->sector_count -= n; } void scsi_device_t::scsi_write_complete(void *req, int ret) { SCSIRequest *r = (SCSIRequest *)req; Bit32u len; if (ret) { BX_ERROR(("IO error")); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); return; } if (r->sector_count == 0) { scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE); } else { len = r->sector_count * 512; if (len > SCSI_DMA_BUF_SIZE) { len = SCSI_DMA_BUF_SIZE; } r->buf_len = len; BX_DEBUG(("write complete tag=0x%x more=%d", r->tag, len)); completion(dev, SCSI_REASON_DATA, r->tag, len); } } int scsi_device_t::scsi_write_data(Bit32u tag) { SCSIRequest *r; Bit32u n; int ret; BX_DEBUG(("write data tag=0x%x", tag)); r = scsi_find_request(tag); if (!r) { BX_ERROR(("bad write tag 0x%x", tag)); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); return 1; } if (type == SCSIDEV_TYPE_DISK) { n = r->buf_len / 512; if (n) { ret = (int)hdimage->lseek(r->sector * 512, SEEK_SET); if (ret < 0) { BX_ERROR(("could not lseek() hard drive image file")); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); } ret = hdimage->write((bx_ptr_t)r->dma_buf, r->buf_len); r->sector += n; r->sector_count -= n; if (ret < r->buf_len) { BX_ERROR(("could not write() hard drive image file")); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); } else { scsi_write_complete((void*)r, 0); } } else { scsi_write_complete(r, 0); } } else { BX_ERROR(("CD-ROM: write not supported")); scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); } return 0; } Bit8u* scsi_device_t::scsi_get_buf(Bit32u tag) { SCSIRequest *r = scsi_find_request(tag); if (!r) { BX_ERROR(("bad buffer tag 0x%x", tag)); return NULL; } return r->dma_buf; } Bit32s scsi_device_t::scsi_send_command(Bit32u tag, Bit8u *buf, int lun) { Bit64u nb_sectors; Bit64u lba; Bit32s len; int cmdlen; int is_write; Bit8u command; Bit8u *outbuf; SCSIRequest *r; command = buf[0]; r = scsi_find_request(tag); if (r) { BX_ERROR(("tag 0x%x already in use", tag)); scsi_cancel_io(tag); } r = scsi_new_request(tag); outbuf = r->dma_buf; is_write = 0; BX_DEBUG(("command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0])); switch (command >> 5) { case 0: lba = buf[3] | (buf[2] << 8) | ((buf[1] & 0x1f) << 16); len = buf[4]; cmdlen = 6; break; case 1: case 2: lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); len = buf[8] | (buf[7] << 8); cmdlen = 10; break; case 4: lba = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24) | ((Bit64u)buf[5] << 32) | ((Bit64u)buf[4] << 40) | ((Bit64u)buf[3] << 48) | ((Bit64u)buf[2] << 56); len = buf[13] | (buf[12] << 8) | (buf[11] << 16) | (buf[10] << 24); cmdlen = 16; break; case 5: lba = buf[5] | (buf[4] << 8) | (buf[3] << 16) | (buf[2] << 24); len = buf[9] | (buf[8] << 8) | (buf[7] << 16) | (buf[6] << 24); cmdlen = 12; break; default: BX_ERROR(("Unsupported command length, command %x", command)); goto fail; } if (lun || buf[1] >> 5) { BX_ERROR(("unimplemented LUN %d", lun ? lun : buf[1] >> 5)); if ((command != 0x03) && (command != 0x12)) // REQUEST SENSE and INQUIRY goto fail; } switch (command) { case 0x0: BX_DEBUG(("Test Unit Ready")); if (!inserted) goto notready; break; case 0x03: BX_DEBUG(("request Sense (len %d)", len)); if (len < 4) goto fail; memset(outbuf, 0, 4); r->buf_len = 4; if ((sense == SENSE_NOT_READY) && (len >= 18)) { memset(outbuf, 0, 18); r->buf_len = 18; outbuf[7] = 10; /* asc 0x3a, ascq 0: Medium not present */ outbuf[12] = 0x3a; outbuf[13] = 0; } outbuf[0] = 0xf0; outbuf[1] = 0; outbuf[2] = sense; break; case 0x12: BX_DEBUG(("inquiry (len %d)", len)); if (buf[1] & 0x2) { // Command support data - optional, not implemented BX_ERROR(("optional INQUIRY command support request not implemented")); goto fail; } else if (buf[1] & 0x1) { // Vital product data Bit8u page_code = buf[2]; if (len < 4) { BX_ERROR(("Error: Inquiry (EVPD[%02X]) buffer size %d is less than 4", page_code, len)); goto fail; } switch (page_code) { case 0x00: // Supported page codes, mandatory BX_DEBUG(("Inquiry EVPD[Supported pages] buffer size %d", len)); r->buf_len = 0; if (type == SCSIDEV_TYPE_CDROM) { outbuf[r->buf_len++] = 5; } else { outbuf[r->buf_len++] = 0; } outbuf[r->buf_len++] = 0x00; // this page outbuf[r->buf_len++] = 0x00; outbuf[r->buf_len++] = 3; // number of pages outbuf[r->buf_len++] = 0x00; // list of supported pages (this page) outbuf[r->buf_len++] = 0x80; // unit serial number outbuf[r->buf_len++] = 0x83; // device identification break; case 0x80: { int l; // Device serial number, optional if (len < 4) { BX_ERROR(("Error: EVPD[Serial number] Inquiry buffer size %d too small, %d needed", len, 4)); goto fail; } BX_DEBUG(("Inquiry EVPD[Serial number] buffer size %d\n", len)); l = BX_MIN(len, (int)strlen(drive_serial_str)); r->buf_len = 0; // Supported page codes if (type == SCSIDEV_TYPE_CDROM) { outbuf[r->buf_len++] = 5; } else { outbuf[r->buf_len++] = 0; } outbuf[r->buf_len++] = 0x80; // this page outbuf[r->buf_len++] = 0x00; outbuf[r->buf_len++] = l; memcpy(&outbuf[r->buf_len], drive_serial_str, l); r->buf_len += l; } break; case 0x83: { // Device identification page, mandatory int max_len = 255 - 8; int id_len = strlen(DEVICE_NAME); if (id_len > max_len) id_len = max_len; BX_DEBUG(("Inquiry EVPD[Device identification] buffer size %d", len)); r->buf_len = 0; if (type == SCSIDEV_TYPE_CDROM) { outbuf[r->buf_len++] = 5; } else { outbuf[r->buf_len++] = 0; } outbuf[r->buf_len++] = 0x83; // this page outbuf[r->buf_len++] = 0x00; outbuf[r->buf_len++] = 3 + id_len; outbuf[r->buf_len++] = 0x2; // ASCII outbuf[r->buf_len++] = 0; // not officially assigned outbuf[r->buf_len++] = 0; // reserved outbuf[r->buf_len++] = id_len; // length of data following memcpy(&outbuf[r->buf_len], DEVICE_NAME, id_len); r->buf_len += id_len; } break; default: BX_ERROR(("Error: unsupported Inquiry (EVPD[%02X]) buffer size %d", page_code, len)); goto fail; } // done with EVPD break; } else { // Standard INQUIRY data if (buf[2] != 0) { BX_ERROR(("Error: Inquiry (STANDARD) page or code is non-zero [%02X]", buf[2])); goto fail; } // PAGE CODE == 0 if (len < 5) { BX_ERROR(("Error: Inquiry (STANDARD) buffer size %d is less than 5", len)); goto fail; } if (len < 36) { BX_ERROR(("Error: Inquiry (STANDARD) buffer size %d is less than 36 (TODO: only 5 required)", len)); } } if(len > SCSI_MAX_INQUIRY_LEN) len = SCSI_MAX_INQUIRY_LEN; memset(outbuf, 0, len); if (lun || buf[1] >> 5) { outbuf[0] = 0x7f; // LUN not supported } else if (type == SCSIDEV_TYPE_CDROM) { outbuf[0] = 5; outbuf[1] = 0x80; memcpy(&outbuf[16], "BOCHS CD-ROM ", 16); } else { outbuf[0] = 0; memcpy(&outbuf[16], "BOCHS HARDDISK ", 16); } memcpy(&outbuf[8], "BOCHS ", 8); memcpy(&outbuf[32], "1.0", 4); // Identify device as SCSI-3 rev 1. // Some later commands are also implemented. outbuf[2] = 3; outbuf[3] = 2; // Format 2 outbuf[4] = len - 5; // Additional Length = (Len - 1) - 4 // Sync data transfer and TCQ. outbuf[7] = 0x10 | (tcq ? 0x02 : 0); r->buf_len = len; break; case 0x16: BX_INFO(("Reserve(6)")); if (buf[1] & 1) goto fail; break; case 0x17: BX_INFO(("Release(6)")); if (buf[1] & 1) goto fail; break; case 0x1a: case 0x5a: { Bit8u *p; int page; page = buf[2] & 0x3f; BX_DEBUG(("mode sense (page %d, len %d)", page, len)); p = outbuf; memset(p, 0, 4); outbuf[1] = 0; /* Default media type. */ outbuf[3] = 0; /* Block descriptor length. */ if (type == SCSIDEV_TYPE_CDROM) { outbuf[2] = 0x80; /* Readonly. */ } p += 4; if ((page == 4) || (page == 5)) { BX_ERROR(("mode sense: page %d not implemented", page)); } if ((page == 8 || page == 0x3f)) { /* Caching page. */ memset(p, 0, 20); p[0] = 8; p[1] = 0x12; p[2] = 4; /* WCE */ p += 20; } if ((page == 0x3f || page == 0x2a) && (type == SCSIDEV_TYPE_CDROM)) { /* CD Capabilities and Mechanical Status page. */ p[0] = 0x2a; p[1] = 0x14; p[2] = 3; // CD-R & CD-RW read p[3] = 0; // Writing not supported p[4] = 0x7f; /* Audio, composite, digital out, mode 2 form 1&2, multi session */ p[5] = 0xff; /* CD DA, DA accurate, RW supported, RW corrected, C2 errors, ISRC, UPC, Bar code */ p[6] = 0x2d | (locked ? 2 : 0); /* Locking supported, jumper present, eject, tray */ p[7] = 0; /* no volume & mute control, no changer */ p[8] = (50 * 176) >> 8; // 50x read speed p[9] = (50 * 176) & 0xff; p[10] = 0 >> 8; // No volume p[11] = 0 & 0xff; p[12] = 2048 >> 8; // 2M buffer p[13] = 2048 & 0xff; p[14] = (16 * 176) >> 8; // 16x read speed current p[15] = (16 * 176) & 0xff; p[18] = (16 * 176) >> 8; // 16x write speed p[19] = (16 * 176) & 0xff; p[20] = (16 * 176) >> 8; // 16x write speed current p[21] = (16 * 176) & 0xff; p += 22; } r->buf_len = p - outbuf; outbuf[0] = r->buf_len - 4; if (r->buf_len > (int)len) r->buf_len = len; } break; case 0x1b: BX_INFO(("Start Stop Unit")); if (type == SCSIDEV_TYPE_CDROM && (buf[4] & 2)) { if (!(buf[4] & 1)) { // eject medium #ifdef LOWLEVEL_CDROM cdrom->eject_cdrom(); #endif inserted = 0; } } break; case 0x1e: BX_INFO(("Prevent Allow Medium Removal (prevent = %d)", buf[4] & 3)); locked = buf[4] & 1; break; case 0x25: BX_DEBUG(("Read Capacity")); // The normal LEN field for this command is zero memset(outbuf, 0, 8); if (type == SCSIDEV_TYPE_CDROM) { #ifdef LOWLEVEL_CDROM nb_sectors = cdrom->capacity(); #else nb_sectors = 0; #endif } else { nb_sectors = hdimage->hd_size / 512; } /* Returned value is the address of the last sector. */ if (nb_sectors) { nb_sectors--; outbuf[0] = (Bit8u)((nb_sectors >> 24) & 0xff); outbuf[1] = (Bit8u)((nb_sectors >> 16) & 0xff); outbuf[2] = (Bit8u)((nb_sectors >> 8) & 0xff); outbuf[3] = (Bit8u)(nb_sectors & 0xff); outbuf[4] = 0; outbuf[5] = 0; outbuf[6] = cluster_size * 2; outbuf[7] = 0; r->buf_len = 8; } else { notready: scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_NOT_READY); return 0; } break; case 0x08: case 0x28: case 0x88: BX_DEBUG(("Read (sector "FMT_LL"d, count %d)", lba, len)); if (lba > max_lba) goto illegal_lba; r->sector = lba; r->sector_count = len; break; case 0x0a: case 0x2a: case 0x8a: BX_DEBUG(("Write (sector "FMT_LL"d, count %d)", lba, len)); if (lba > max_lba) goto illegal_lba; r->sector = lba; r->sector_count = len; is_write = 1; break; case 0x35: BX_DEBUG(("Syncronise cache (sector "FMT_LL"d, count %d)", lba, len)); // TODO: flush cache break; case 0x43: { int start_track, format, msf, toclen; if (type == SCSIDEV_TYPE_CDROM) { msf = buf[1] & 2; format = buf[2] & 0xf; start_track = buf[6]; BX_DEBUG(("Read TOC (track %d format %d msf %d)", start_track, format, msf >> 1)); #ifdef LOWLEVEL_CDROM cdrom->read_toc(outbuf, &toclen, msf, start_track, format); if (toclen > 0) { if (len > toclen) len = toclen; r->buf_len = len; break; } #endif BX_ERROR(("Read TOC error")); goto fail; } else { goto fail; } } case 0x46: BX_DEBUG(("Get Configuration (rt %d, maxlen %d)", buf[1] & 3, len)); memset(outbuf, 0, 8); /* ??? This shoud probably return much more information. For now just return the basic header indicating the CD-ROM profile. */ outbuf[7] = 8; // CD-ROM r->buf_len = 8; break; case 0x56: BX_INFO(("Reserve(10)")); if (buf[1] & 3) goto fail; break; case 0x57: BX_INFO(("Release(10)")); if (buf[1] & 3) goto fail; break; case 0xa0: BX_INFO(("Report LUNs (len %d)", len)); if (len < 16) goto fail; memset(outbuf, 0, 16); outbuf[3] = 8; r->buf_len = 16; break; case 0x2f: BX_INFO(("Verify")); break; case 0x23: { // USBMASS-UFI10.pdf  rev 1.0  Section 4.10 BX_INFO(("READ FORMAT CAPACITIES (MMC)")); unsigned len = (buf[7]<<8) | buf[8]; #define OUR_LEN 12 // Cap List Header outbuf[0] = 0; outbuf[1] = 0; outbuf[2] = 0; outbuf[3] = OUR_LEN; // Current/Max Cap Header if (type == SCSIDEV_TYPE_CDROM) { #ifdef LOWLEVEL_CDROM nb_sectors = cdrom->capacity(); #else nb_sectors = 0; #endif } else { nb_sectors = (hdimage->hd_size / 512); } /* Returned value is the address of the last sector.  */ outbuf[4] = (Bit8u)((nb_sectors >> 24) & 0xff); outbuf[5] = (Bit8u)((nb_sectors >> 16) & 0xff); outbuf[6] = (Bit8u)((nb_sectors >> 8) & 0xff); outbuf[7] = (Bit8u)(nb_sectors & 0xff); outbuf[8] = 2; // formatted (1 = unformatted) outbuf[9] = 0; outbuf[10] = cluster_size * 2; outbuf[11] = 0; r->buf_len = (len < OUR_LEN) ? len : OUR_LEN; } break; default: BX_ERROR(("Unknown SCSI command (%2.2x)", buf[0])); fail: scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_ILLEGAL_REQUEST); return 0; illegal_lba: scsi_command_complete(r, STATUS_CHECK_CONDITION, SENSE_HARDWARE_ERROR); return 0; } if (r->sector_count == 0 && r->buf_len == 0) { scsi_command_complete(r, STATUS_GOOD, SENSE_NO_SENSE); } len = r->sector_count * 512 * cluster_size + r->buf_len; if (is_write) { return -len; } else { if (!r->sector_count) r->sector_count = (Bit32u) -1; return len; } } #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB bochs-2.6/iodev/usb/usb_uhci.cc0000644000175000017500000013440612020641504016346 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_uhci.cc 11390 2012-09-02 09:37:47Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Experimental USB UHCI adapter /* Notes by Ben Lunt: - My purpose of coding this emulation was/is to learn about the USB. It has been a challenge, but I have learned a lot. - 31 July 2006: I now have a Beagle USB Protocol Analyzer from Total Phase for my research. (http://www.totalphase.com/products/beagle/usb/) With this device, I plan on doing a lot of research and development to get this code to a state where it is actually very useful. I plan on adding support of many "plug-in" type modules so that you can simply add a plug-in for your specific device without having to modify the root code. I hope to have some working code to upload to the CVS as soon as possible. Thanks to Total Phase for their help in my research and the development of this project. */ // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_USB_UHCI #include "pci.h" #include "usb_common.h" #include "usb_uhci.h" #define LOG_THIS theUSB_UHCI-> bx_usb_uhci_c* theUSB_UHCI = NULL; const Bit8u uhci_iomask[32] = {2, 1, 2, 1, 2, 1, 2, 0, 4, 0, 0, 0, 1, 0, 0, 0, 3, 1, 3, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // builtin configuration handling functions Bit32s usb_uhci_options_parser(const char *context, int num_params, char *params[]) { if (!strcmp(params[0], "usb_uhci")) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_USB_UHCI); for (int i = 1; i < num_params; i++) { if (!strncmp(params[i], "enabled=", 8)) { SIM->get_param_bool(BXPN_UHCI_ENABLED)->set(atol(¶ms[i][8])); } else if (!strncmp(params[i], "port", 4)) { if (SIM->parse_usb_port_params(context, 0, params[i], BX_N_USB_UHCI_PORTS, base) < 0) { return -1; } } else if (!strncmp(params[i], "options", 7)) { if (SIM->parse_usb_port_params(context, 1, params[i], BX_N_USB_UHCI_PORTS, base) < 0) { return -1; } } else { BX_ERROR(("%s: unknown parameter '%s' for usb_uhci ignored.", context, params[i])); } } } else { BX_PANIC(("%s: unknown directive '%s'", context, params[0])); } return 0; } Bit32s usb_uhci_options_save(FILE *fp) { bx_list_c *base = (bx_list_c*) SIM->get_param(BXPN_USB_UHCI); SIM->write_usb_options(fp, BX_N_USB_UHCI_PORTS, base); return 0; } // device plugin entry points int libusb_uhci_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]) { theUSB_UHCI = new bx_usb_uhci_c(); BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUSB_UHCI, BX_PLUGIN_USB_UHCI); // add new configuration parameter for the config interface SIM->init_usb_options("UHCI", "uhci", BX_N_USB_UHCI_PORTS); // register add-on option for bochsrc and command line SIM->register_addon_option("usb_uhci", usb_uhci_options_parser, usb_uhci_options_save); return 0; // Success } void libusb_uhci_LTX_plugin_fini(void) { SIM->unregister_addon_option("usb_uhci"); bx_list_c *menu = (bx_list_c*)SIM->get_param("ports.usb"); delete theUSB_UHCI; menu->remove("uhci"); } // the device object bx_usb_uhci_c::bx_usb_uhci_c() { put("usb_uhci", "UHCI"); memset((void*)&hub, 0, sizeof(bx_usb_uhci_t)); device_buffer = NULL; hub.timer_index = BX_NULL_TIMER_HANDLE; } bx_usb_uhci_c::~bx_usb_uhci_c() { char pname[16]; if (BX_UHCI_THIS device_buffer != NULL) delete [] BX_UHCI_THIS device_buffer; for (int i=0; iget_param_string(pname, SIM->get_param(BXPN_USB_UHCI))->set_handler(NULL); remove_device(i); } SIM->get_bochs_root()->remove("usb_uhci"); BX_DEBUG(("Exit")); } void bx_usb_uhci_c::init(void) { unsigned i; char pname[6]; bx_list_c *uhci, *port; bx_param_string_c *device, *options; // Read in values from config interface uhci = (bx_list_c*) SIM->get_param(BXPN_USB_UHCI); // Check if the device is disabled or not configured if (!SIM->get_param_bool("enabled", uhci)->get()) { BX_INFO(("USB UHCI disabled")); // mark unused plugin for removal ((bx_param_bool_c*)((bx_list_c*)SIM->get_param(BXPN_PLUGIN_CTRL))->get_by_name("usb_uhci"))->set(0); return; } BX_UHCI_THIS device_buffer = new Bit8u[65536]; // Call our timer routine every 1mS (1,000uS) // Continuous and active BX_UHCI_THIS hub.timer_index = bx_pc_system.register_timer(this, usb_timer_handler, 1000, 1,1, "usb.timer"); if (DEV_is_pci_device(BX_PLUGIN_USB_UHCI)) { BX_UHCI_THIS hub.devfunc = 0x00; } else { BX_UHCI_THIS hub.devfunc = BX_PCI_DEVICE(1,2); } DEV_register_pci_handlers(this, &BX_UHCI_THIS hub.devfunc, BX_PLUGIN_USB_UHCI, "Experimental USB UHCI"); for (i=0; i<256; i++) { BX_UHCI_THIS pci_conf[i] = 0x0; } BX_UHCI_THIS pci_base_address[4] = 0x0; //FIXME: for now, we want a status bar // hub zero, port zero BX_UHCI_THIS hub.statusbar_id = bx_gui->register_statusitem("UHCI", 1); bx_list_c *usb_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_USB); uhci->set_options(uhci->SHOW_PARENT); uhci->set_runtime_param(1); usb_rt->add(uhci); for (i=0; iget_param(pname, uhci); port->set_runtime_param(1); device = (bx_param_string_c*)port->get_by_name("device"); device->set_handler(usb_param_handler); device->set_runtime_param(1); options = (bx_param_string_c*)port->get_by_name("options"); options->set_runtime_param(1); BX_UHCI_THIS hub.usb_port[i].device = NULL; } // register handler for correct device connect handling after runtime config SIM->register_runtime_config_handler(BX_UHCI_THIS_PTR, runtime_config_handler); BX_UHCI_THIS hub.device_change = 0; BX_INFO(("USB UHCI initialized")); } void bx_usb_uhci_c::reset(unsigned type) { unsigned i, j; char pname[6]; if (type == BX_RESET_HARDWARE) { static const struct reset_vals_t { unsigned addr; unsigned char val; } reset_vals[] = { { 0x00, 0x86 }, { 0x01, 0x80 }, // 0x8086 = vendor { 0x02, 0x20 }, { 0x03, 0x70 }, // 0x7020 = device { 0x04, 0x05 }, { 0x05, 0x00 }, // command_io { 0x06, 0x80 }, { 0x07, 0x02 }, // status { 0x08, 0x01 }, // revision number { 0x09, 0x00 }, // interface { 0x0a, 0x03 }, // class_sub USB Host Controller { 0x0b, 0x0c }, // class_base Serial Bus Controller { 0x0D, 0x20 }, // bus latency { 0x0e, 0x00 }, // header_type_generic // address space 0x20 - 0x23 { 0x20, 0x01 }, { 0x21, 0x00 }, { 0x22, 0x00 }, { 0x23, 0x00 }, { 0x3c, 0x00 }, // IRQ { 0x3d, BX_PCI_INTD }, // INT { 0x60, 0x10 }, // USB revision 1.0 { 0x6a, 0x01 }, // USB clock { 0xc1, 0x20 } // PIRQ enable }; for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) { BX_UHCI_THIS pci_conf[reset_vals[i].addr] = reset_vals[i].val; } } // reset locals BX_UHCI_THIS busy = 0; BX_UHCI_THIS global_reset = 0; // Put the USB registers into their RESET state BX_UHCI_THIS hub.usb_command.max_packet_size = 0; BX_UHCI_THIS hub.usb_command.configured = 0; BX_UHCI_THIS hub.usb_command.debug = 0; BX_UHCI_THIS hub.usb_command.resume = 0; BX_UHCI_THIS hub.usb_command.suspend = 0; BX_UHCI_THIS hub.usb_command.reset = 0; BX_UHCI_THIS hub.usb_command.host_reset = 0; BX_UHCI_THIS hub.usb_command.schedule = 0; BX_UHCI_THIS hub.usb_status.error_interrupt = 0; BX_UHCI_THIS hub.usb_status.host_error = 0; BX_UHCI_THIS hub.usb_status.host_halted = 0; BX_UHCI_THIS hub.usb_status.interrupt = 0; BX_UHCI_THIS hub.usb_status.status2 = 0; BX_UHCI_THIS hub.usb_status.pci_error = 0; BX_UHCI_THIS hub.usb_status.resume = 0; BX_UHCI_THIS hub.usb_enable.short_packet = 0; BX_UHCI_THIS hub.usb_enable.on_complete = 0; BX_UHCI_THIS hub.usb_enable.resume = 0; BX_UHCI_THIS hub.usb_enable.timeout_crc = 0; BX_UHCI_THIS hub.usb_frame_num.frame_num = 0x0000; BX_UHCI_THIS hub.usb_frame_base.frame_base = 0x00000000; BX_UHCI_THIS hub.usb_sof.sof_timing = 0x40; for (j=0; jget_param(pname, SIM->get_param(BXPN_USB_UHCI))); } else { usb_set_connect_status(j, BX_UHCI_THIS hub.usb_port[j].device->get_type(), 1); } } } void bx_usb_uhci_c::register_state(void) { unsigned j; char portnum[8]; bx_list_c *hub, *usb_cmd, *usb_st, *usb_en, *port; bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "usb_uhci", "USB UHCI State"); hub = new bx_list_c(list, "hub"); usb_cmd = new bx_list_c(hub, "usb_command"); new bx_shadow_bool_c(usb_cmd, "max_packet_size", &BX_UHCI_THIS hub.usb_command.max_packet_size); new bx_shadow_bool_c(usb_cmd, "configured", &BX_UHCI_THIS hub.usb_command.configured); new bx_shadow_bool_c(usb_cmd, "debug", &BX_UHCI_THIS hub.usb_command.debug); new bx_shadow_bool_c(usb_cmd, "resume", &BX_UHCI_THIS hub.usb_command.resume); new bx_shadow_bool_c(usb_cmd, "suspend", &BX_UHCI_THIS hub.usb_command.suspend); new bx_shadow_bool_c(usb_cmd, "reset", &BX_UHCI_THIS hub.usb_command.reset); new bx_shadow_bool_c(usb_cmd, "host_reset", &BX_UHCI_THIS hub.usb_command.host_reset); new bx_shadow_bool_c(usb_cmd, "schedule", &BX_UHCI_THIS hub.usb_command.schedule); usb_st = new bx_list_c(hub, "usb_status"); new bx_shadow_bool_c(usb_st, "host_halted", &BX_UHCI_THIS hub.usb_status.host_halted); new bx_shadow_bool_c(usb_st, "host_error", &BX_UHCI_THIS hub.usb_status.host_error); new bx_shadow_bool_c(usb_st, "pci_error", &BX_UHCI_THIS hub.usb_status.pci_error); new bx_shadow_bool_c(usb_st, "resume", &BX_UHCI_THIS hub.usb_status.resume); new bx_shadow_bool_c(usb_st, "error_interrupt", &BX_UHCI_THIS hub.usb_status.error_interrupt); new bx_shadow_bool_c(usb_st, "interrupt", &BX_UHCI_THIS hub.usb_status.interrupt); new bx_shadow_num_c(usb_st, "status2", &BX_UHCI_THIS hub.usb_status.status2, BASE_HEX); usb_en = new bx_list_c(hub, "usb_enable"); new bx_shadow_bool_c(usb_en, "short_packet", &BX_UHCI_THIS hub.usb_enable.short_packet); new bx_shadow_bool_c(usb_en, "on_complete", &BX_UHCI_THIS hub.usb_enable.on_complete); new bx_shadow_bool_c(usb_en, "resume", &BX_UHCI_THIS hub.usb_enable.resume); new bx_shadow_bool_c(usb_en, "timeout_crc", &BX_UHCI_THIS hub.usb_enable.timeout_crc); new bx_shadow_num_c(hub, "frame_num", &BX_UHCI_THIS hub.usb_frame_num.frame_num, BASE_HEX); new bx_shadow_num_c(hub, "frame_base", &BX_UHCI_THIS hub.usb_frame_base.frame_base, BASE_HEX); new bx_shadow_num_c(hub, "sof_timing", &BX_UHCI_THIS hub.usb_sof.sof_timing, BASE_HEX); for (j=0; jafter_restore_state(); } } } void bx_usb_uhci_c::init_device(Bit8u port, bx_list_c *portconf) { usbdev_type type; char pname[BX_PATHNAME_LEN]; const char *devname = NULL; devname = ((bx_param_string_c*)portconf->get_by_name("device"))->getptr(); if (devname == NULL) return; if (!strlen(devname) || !strcmp(devname, "none")) return; if (BX_UHCI_THIS hub.usb_port[port].device != NULL) { BX_ERROR(("init_device(): port%d already in use", port+1)); return; } sprintf(pname, "usb_uhci.hub.port%d.device", port+1); bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root()); type = DEV_usb_init_device(portconf, BX_UHCI_THIS_PTR, &BX_UHCI_THIS hub.usb_port[port].device, sr_list); if (BX_UHCI_THIS hub.usb_port[port].device != NULL) { usb_set_connect_status(port, type, 1); } } void bx_usb_uhci_c::remove_device(Bit8u port) { char pname[BX_PATHNAME_LEN]; if (BX_UHCI_THIS hub.usb_port[port].device != NULL) { delete BX_UHCI_THIS hub.usb_port[port].device; BX_UHCI_THIS hub.usb_port[port].device = NULL; sprintf(pname, "usb_uhci.hub.port%d.device", port+1); bx_list_c *devlist = (bx_list_c*)SIM->get_param(pname, SIM->get_bochs_root()); devlist->clear(); } } void bx_usb_uhci_c::update_irq() { bx_bool level; if (((BX_UHCI_THIS hub.usb_status.status2 & 1) && (BX_UHCI_THIS hub.usb_enable.on_complete)) || ((BX_UHCI_THIS hub.usb_status.status2 & 2) && (BX_UHCI_THIS hub.usb_enable.short_packet)) || ((BX_UHCI_THIS hub.usb_status.error_interrupt) && (BX_UHCI_THIS hub.usb_enable.timeout_crc)) || ((BX_UHCI_THIS hub.usb_status.resume) && (BX_UHCI_THIS hub.usb_enable.resume)) || (BX_UHCI_THIS hub.usb_status.pci_error) || (BX_UHCI_THIS hub.usb_status.host_error)) { level = 1; } else { level = 0; } DEV_pci_set_irq(BX_UHCI_THIS hub.devfunc, BX_UHCI_THIS pci_conf[0x3d], level); } // static IO port read callback handler // redirects to non-static class handler to avoid virtual functions Bit32u bx_usb_uhci_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len) { #if !BX_USE_USB_UHCI_SMF bx_usb_uhci_c *class_ptr = (bx_usb_uhci_c *) this_ptr; return class_ptr->read(address, io_len); } Bit32u bx_usb_uhci_c::read(Bit32u address, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_USB_UHCI_SMF Bit32u val = 0x0; Bit8u offset,port; offset = address - BX_UHCI_THIS pci_base_address[4]; switch (offset) { case 0x00: // command register (16-bit) val = BX_UHCI_THIS hub.usb_command.max_packet_size << 7 | BX_UHCI_THIS hub.usb_command.configured << 6 | BX_UHCI_THIS hub.usb_command.debug << 5 | BX_UHCI_THIS hub.usb_command.resume << 4 | BX_UHCI_THIS hub.usb_command.suspend << 3 | BX_UHCI_THIS hub.usb_command.reset << 2 | BX_UHCI_THIS hub.usb_command.host_reset << 1 | BX_UHCI_THIS hub.usb_command.schedule; break; case 0x02: // status register (16-bit) val = BX_UHCI_THIS hub.usb_status.host_halted << 5 | BX_UHCI_THIS hub.usb_status.host_error << 4 | BX_UHCI_THIS hub.usb_status.pci_error << 3 | BX_UHCI_THIS hub.usb_status.resume << 2 | BX_UHCI_THIS hub.usb_status.error_interrupt << 1 | BX_UHCI_THIS hub.usb_status.interrupt; break; case 0x04: // interrupt enable register (16-bit) val = BX_UHCI_THIS hub.usb_enable.short_packet << 3 | BX_UHCI_THIS hub.usb_enable.on_complete << 2 | BX_UHCI_THIS hub.usb_enable.resume << 1 | BX_UHCI_THIS hub.usb_enable.timeout_crc; break; case 0x06: // frame number register (16-bit) val = BX_UHCI_THIS hub.usb_frame_num.frame_num; break; case 0x08: // frame base register (32-bit) val = BX_UHCI_THIS hub.usb_frame_base.frame_base; break; case 0x0C: // start of Frame Modify register (8-bit) val = BX_UHCI_THIS hub.usb_sof.sof_timing; break; case 0x14: // port #3 non existant, but linux systems check it to see if there are more than 2 BX_ERROR(("read from non existant offset 0x14 (port #3)")); val = 0xFF7F; break; case 0x10: // port #1 case 0x11: case 0x12: // port #2 case 0x13: port = (offset & 0x0F) >> 1; if (port < BX_N_USB_UHCI_PORTS) { val = BX_UHCI_THIS hub.usb_port[port].suspend << 12 | 1 << 10 // some Root Hubs have bit 10 set ????? | BX_UHCI_THIS hub.usb_port[port].reset << 9 | BX_UHCI_THIS hub.usb_port[port].low_speed << 8 | 1 << 7 | BX_UHCI_THIS hub.usb_port[port].resume << 6 | BX_UHCI_THIS hub.usb_port[port].line_dminus << 5 | BX_UHCI_THIS hub.usb_port[port].line_dplus << 4 | BX_UHCI_THIS hub.usb_port[port].able_changed << 3 | BX_UHCI_THIS hub.usb_port[port].enabled << 2 | BX_UHCI_THIS hub.usb_port[port].connect_changed << 1 | BX_UHCI_THIS hub.usb_port[port].status; if (offset & 1) val >>= 8; break; } // else fall through to default default: val = 0xFF7F; // keep compiler happy BX_ERROR(("unsupported io read from address=0x%04x!", (unsigned) address)); break; } BX_DEBUG(("register read from address 0x%04X: 0x%08X (%2i bits)", (unsigned) address, (Bit32u) val, io_len * 8)); return(val); } // static IO port write callback handler // redirects to non-static class handler to avoid virtual functions void bx_usb_uhci_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len) { #if !BX_USE_USB_UHCI_SMF bx_usb_uhci_c *class_ptr = (bx_usb_uhci_c *) this_ptr; class_ptr->write(address, value, io_len); } void bx_usb_uhci_c::write(Bit32u address, Bit32u value, unsigned io_len) { #else UNUSED(this_ptr); #endif // !BX_USE_USB_UHCI_SMF Bit8u offset,port; BX_DEBUG(("register write to address 0x%04X: 0x%08X (%2i bits)", (unsigned) address, (unsigned) value, io_len * 8)); offset = address - BX_UHCI_THIS pci_base_address[4]; switch (offset) { case 0x00: // command register (16-bit) (R/W) if (value & 0xFF00) BX_DEBUG(("write to command register with bits 15:8 not zero: 0x%04x", value)); BX_UHCI_THIS hub.usb_command.max_packet_size = (value & 0x80) ? 1: 0; BX_UHCI_THIS hub.usb_command.configured = (value & 0x40) ? 1: 0; BX_UHCI_THIS hub.usb_command.debug = (value & 0x20) ? 1: 0; BX_UHCI_THIS hub.usb_command.resume = (value & 0x10) ? 1: 0; BX_UHCI_THIS hub.usb_command.suspend = (value & 0x08) ? 1: 0; BX_UHCI_THIS hub.usb_command.reset = (value & 0x04) ? 1: 0; BX_UHCI_THIS hub.usb_command.host_reset = (value & 0x02) ? 1: 0; BX_UHCI_THIS hub.usb_command.schedule = (value & 0x01) ? 1: 0; // HCRESET if (BX_UHCI_THIS hub.usb_command.host_reset) { BX_UHCI_THIS reset(0); for (unsigned i=0; i> 1; if ((port < BX_N_USB_UHCI_PORTS) && (io_len == 2)) { // If the ports reset bit is set, don't allow any writes unless the new write will clear the reset bit if (BX_UHCI_THIS hub.usb_port[port].reset & (value & (1<<9))) break; if (value & ((1<<5) | (1<<4) | (1<<0))) BX_DEBUG(("write to one or more read-only bits in port #%d register: 0x%04x", port+1, value)); if (!(value & (1<<7))) BX_DEBUG(("write to port #%d register bit 7 = 0", port+1)); if (value & (1<<8)) BX_DEBUG(("write to bit 8 in port #%d register ignored", port+1)); if ((value & (1<<12)) && BX_UHCI_THIS hub.usb_command.suspend) BX_DEBUG(("write to port #%d register bit 12 when in Global-Suspend", port+1)); BX_UHCI_THIS hub.usb_port[port].suspend = (value & (1<<12)) ? 1 : 0; BX_UHCI_THIS hub.usb_port[port].reset = (value & (1<<9)) ? 1 : 0; BX_UHCI_THIS hub.usb_port[port].resume = (value & (1<<6)) ? 1 : 0; if (!BX_UHCI_THIS hub.usb_port[port].enabled && (value & (1<<2))) BX_UHCI_THIS hub.usb_port[port].able_changed = 0; else if ((value & (1<<3)) != 0) BX_UHCI_THIS hub.usb_port[port].able_changed = 0; BX_UHCI_THIS hub.usb_port[port].enabled = (value & (1<<2)) ? 1 : 0; if ((value & (1<<1)) != 0) BX_UHCI_THIS hub.usb_port[port].connect_changed = 0; // if port reset, reset function(s) //TODO: only reset items on the downstream... // for now, reset the one and only // TODO: descriptors, etc.... if (BX_UHCI_THIS hub.usb_port[port].reset) { BX_UHCI_THIS hub.usb_port[port].suspend = 0; BX_UHCI_THIS hub.usb_port[port].resume = 0; BX_UHCI_THIS hub.usb_port[port].enabled = 0; // are we are currently connected/disconnected if (BX_UHCI_THIS hub.usb_port[port].status) { if (BX_UHCI_THIS hub.usb_port[port].device != NULL) { BX_UHCI_THIS hub.usb_port[port].low_speed = (BX_UHCI_THIS hub.usb_port[port].device->get_speed() == USB_SPEED_LOW); usb_set_connect_status(port, BX_UHCI_THIS hub.usb_port[port].device->get_type(), 1); DEV_usb_send_msg(BX_UHCI_THIS hub.usb_port[port].device, USB_MSG_RESET); } } BX_INFO(("Port%d: Reset", port+1)); } break; } // else fall through to default default: BX_ERROR(("unsupported io write to address=0x%04x!", (unsigned) address)); break; } } void bx_usb_uhci_c::usb_timer_handler(void *this_ptr) { bx_usb_uhci_c *class_ptr = (bx_usb_uhci_c *) this_ptr; class_ptr->usb_timer(); } // Called once every 1ms #define USB_STACK_SIZE 256 void bx_usb_uhci_c::usb_timer(void) { int i; // If the "global reset" bit was set by software if (BX_UHCI_THIS global_reset) { for (i=0; i -1) { // Linux seems to just loop a few queues together and wait for the 1ms to end. // We will just count the stack and exit when we get to a good point to stop. if (stk >= USB_STACK_SIZE) break; // check to make sure we are not done before continue-ing on if ((stack[stk].d == HC_VERT) && stack[stk].t) { stk--; continue; } if ((stack[stk].d == HC_HORZ) && stack[stk].t) break; if (stack[stk].q) { // is a queue address = stack[stk].next; lastvertaddr = address + 4; // get HORZ slot stk++; DEV_MEM_READ_PHYSICAL(address, 4, (Bit8u*) &item); stack[stk].next = item & ~0xF; stack[stk].d = HC_HORZ; stack[stk].q = (item & 0x0002) ? 1 : 0; stack[stk].t = (item & 0x0001) ? 1 : 0; // get VERT slot stk++; DEV_MEM_READ_PHYSICAL(lastvertaddr, 4, (Bit8u*) &item); stack[stk].next = item & ~0xF; stack[stk].d = HC_VERT; stack[stk].q = (item & 0x0002) ? 1 : 0; stack[stk].t = (item & 0x0001) ? 1 : 0; BX_DEBUG(("Queue %3i: 0x%08X %i %i 0x%08X %i %i", queue_num, stack[stk-1].next, stack[stk-1].q, stack[stk-1].t, stack[stk].next, stack[stk].q, stack[stk].t)); queue_num++; } else { // else is a TD address = stack[stk].next; DEV_MEM_READ_PHYSICAL(address, 4, (Bit8u*) &td.dword0); DEV_MEM_READ_PHYSICAL(address+4, 4, (Bit8u*) &td.dword1); DEV_MEM_READ_PHYSICAL(address+8, 4, (Bit8u*) &td.dword2); DEV_MEM_READ_PHYSICAL(address+12, 4, (Bit8u*) &td.dword3); bx_bool spd = (td.dword1 & (1<<29)) ? 1 : 0; stack[stk].next = td.dword0 & ~0xF; bx_bool depthbreadth = (td.dword0 & 0x0004) ? 1 : 0; // 1 = depth first, 0 = breadth first stack[stk].q = (td.dword0 & 0x0002) ? 1 : 0; stack[stk].t = (td.dword0 & 0x0001) ? 1 : 0; if (td.dword1 & (1<<24)) interrupt = 1; if (td.dword1 & (1<<23)) { // is it an active TD BX_DEBUG(("Frame: %04i (0x%04X)", BX_UHCI_THIS hub.usb_frame_num.frame_num, BX_UHCI_THIS hub.usb_frame_num.frame_num)); if (BX_UHCI_THIS DoTransfer(address, queue_num, &td)) { // issue short packet? Bit16u r_actlen = (((td.dword1 & 0x7FF)+1) & 0x7FF); Bit16u r_maxlen = (((td.dword2>>21)+1) & 0x7FF); BX_DEBUG((" r_actlen = 0x%04X r_maxlen = 0x%04X", r_actlen, r_maxlen)); if (((td.dword2 & 0xFF) == USB_TOKEN_IN) && spd && stk && (r_actlen < r_maxlen) && ((td.dword1 & 0x00FF0000) == 0)) { shortpacket = 1; td.dword1 |= (1<<29); } if (td.dword1 & (1<<22)) stalled = 1; DEV_MEM_WRITE_PHYSICAL(address+4, 4, (Bit8u*) &td.dword1); // write back the status if (shortpacket) { td.dword0 |= 1; stack[stk].t = 1; } // copy pointer for next queue item, in to vert queue head if ((stk > 0) && (stack[stk].d == HC_VERT) && !shortpacket) DEV_MEM_WRITE_PHYSICAL(lastvertaddr, 4, (Bit8u*) &td.dword0); } } if (stk > 0) { // if last TD in HORZ queue pointer, then we are done. if (stack[stk].t && (stack[stk].d == HC_HORZ)) break; // if Breadth first or last item in queue, move to next queue. if (!depthbreadth || stack[stk].t) { if (stack[stk].d == HC_HORZ) queue_num--; // <-- really, this should never happen until we stk--; // support bandwidth reclamation... } if (stk < 1) break; } else { if (stack[stk].t) break; } } } // set the status register bit:0 to 1 if SPD is enabled // and if interrupts not masked via interrupt register, raise irq interrupt. if (shortpacket) BX_UHCI_THIS hub.usb_status.status2 |= 2; if (shortpacket && BX_UHCI_THIS hub.usb_enable.short_packet) { BX_DEBUG((" [SPD] We want it to fire here (Frame: %04i)", BX_UHCI_THIS hub.usb_frame_num.frame_num)); } // if one of the TD's in this frame had the ioc bit set, we need to // raise an interrupt, if interrupts are not masked via interrupt register. // always set the status register if IOC. BX_UHCI_THIS hub.usb_status.status2 |= interrupt; if (interrupt && BX_UHCI_THIS hub.usb_enable.on_complete) { BX_DEBUG((" [IOC] We want it to fire here (Frame: %04i)", BX_UHCI_THIS hub.usb_frame_num.frame_num)); } BX_UHCI_THIS hub.usb_status.error_interrupt |= stalled; if (stalled && BX_UHCI_THIS hub.usb_enable.timeout_crc) { BX_DEBUG((" [stalled] We want it to fire here (Frame: %04i)", BX_UHCI_THIS hub.usb_frame_num.frame_num)); } } // The Frame Number Register is incremented every 1ms BX_UHCI_THIS hub.usb_frame_num.frame_num++; BX_UHCI_THIS hub.usb_frame_num.frame_num &= (1024-1); // The status.interrupt bit should be set regardless of the enable bits if a IOC or SPD is found if (interrupt || shortpacket) { BX_UHCI_THIS hub.usb_status.interrupt = 1; } // if we needed to fire an interrupt now, lets do it *after* we increment the frame_num register update_irq(); BX_UHCI_THIS busy = 0; // ready to do next frame item } // end run schedule // if host turned off the schedule, set the halted bit in the status register // Note: Can not use an else from the if() above since the host can changed this bit // while we are processing a frame. if (BX_UHCI_THIS hub.usb_command.schedule == 0) BX_UHCI_THIS hub.usb_status.host_halted = 1; // TODO: // If in Global_Suspend mode and any of usb_port[i] bits 6,3, or 1 are set, // we need to issue a Global_Resume (set the global resume bit). // However, since we don't do anything, let's not. } bx_bool bx_usb_uhci_c::DoTransfer(Bit32u address, Bit32u queue_num, struct TD *td) { int len = 0, ret = 0; Bit16u maxlen = (td->dword2 >> 21); Bit8u addr = (td->dword2 >> 8) & 0x7F; Bit8u endpt = (td->dword2 >> 15) & 0x0F; Bit8u pid = td->dword2 & 0xFF; BX_DEBUG(("QH%03i:TD found at address: 0x%08X", queue_num, address)); BX_DEBUG((" %08X %08X %08X %08X", td->dword0, td->dword1, td->dword2, td->dword3)); // check TD to make sure it is valid // A max length 0x500 to 0x77E is illegal if ((maxlen >= 0x500) && (maxlen != 0x7FF)) { BX_ERROR(("invalid max. length value 0x%04x", maxlen )); return 0; // error = consistency check failure } // if (td->dword0 & 0x8) return 1; // error = reserved bit in dword0 set // other error checks here // the device should remain in a stall state until the next setup packet is recieved // For some reason, this doesn't work yet. //if (dev && dev->in_stall && (pid != USB_TOKEN_SETUP)) // return FALSE; maxlen++; maxlen &= 0x7FF; /* set status bar conditions for device */ if ((maxlen > 0) && (BX_UHCI_THIS hub.statusbar_id >= 0)) { if (pid == USB_TOKEN_IN) bx_gui->statusbar_setitem(BX_UHCI_THIS hub.statusbar_id, 1); // read else bx_gui->statusbar_setitem(BX_UHCI_THIS hub.statusbar_id, 1, 1); // write } BX_UHCI_THIS usb_packet.pid = pid; BX_UHCI_THIS usb_packet.devaddr = addr; BX_UHCI_THIS usb_packet.devep = endpt; BX_UHCI_THIS usb_packet.data = device_buffer; BX_UHCI_THIS usb_packet.len = maxlen; switch (pid) { case USB_TOKEN_OUT: case USB_TOKEN_SETUP: if (maxlen > 0) { DEV_MEM_READ_PHYSICAL_DMA(td->dword3, maxlen, device_buffer); } ret = BX_UHCI_THIS broadcast_packet(&BX_UHCI_THIS usb_packet); len = maxlen; break; case USB_TOKEN_IN: ret = BX_UHCI_THIS broadcast_packet(&BX_UHCI_THIS usb_packet); if (ret >= 0) { len = ret; if (len > maxlen) { len = maxlen; ret = USB_RET_BABBLE; } if (len > 0) { DEV_MEM_WRITE_PHYSICAL_DMA(td->dword3, len, device_buffer); } } else { len = 0; } break; default: BX_UHCI_THIS hub.usb_status.host_error = 1; update_irq(); return 0; } if (ret >= 0) { BX_UHCI_THIS set_status(td, 0, 0, 0, 0, 0, 0, len-1); } else { BX_UHCI_THIS set_status(td, 1, 0, 0, 0, 0, 0, 0x007); // stalled } return 1; } int bx_usb_uhci_c::broadcast_packet(USBPacket *p) { int i, ret; ret = USB_RET_NODEV; for (i = 0; i < BX_N_USB_UHCI_PORTS && ret == USB_RET_NODEV; i++) { if ((BX_UHCI_THIS hub.usb_port[i].device != NULL) && (BX_UHCI_THIS hub.usb_port[i].enabled)) { ret = BX_UHCI_THIS hub.usb_port[i].device->handle_packet(p); } } return ret; } // If the request fails, set the stall bit ???? void bx_usb_uhci_c::set_status(struct TD *td, bx_bool stalled, bx_bool data_buffer_error, bx_bool babble, bx_bool nak, bx_bool crc_time_out, bx_bool bitstuff_error, Bit16u act_len) { // clear out the bits we can modify and/or want zero td->dword1 &= 0xDF00F800; // now set the bits according to the passed param's td->dword1 |= stalled ? (1<<22) : 0; // stalled td->dword1 |= data_buffer_error ? (1<<21) : 0; // data buffer error td->dword1 |= babble ? (1<<20) : 0; // babble td->dword1 |= nak ? (1<<19) : 0; // nak td->dword1 |= crc_time_out ? (1<<18) : 0; // crc/timeout td->dword1 |= bitstuff_error ? (1<<17) : 0; // bitstuff error td->dword1 |= (act_len & 0x7FF); // actual length if (stalled || data_buffer_error || babble || nak || crc_time_out || bitstuff_error) td->dword1 &= ~((1<<28) | (1<<27)); // clear the c_err field in there was an error } void bx_usb_uhci_c::runtime_config_handler(void *this_ptr) { bx_usb_uhci_c *class_ptr = (bx_usb_uhci_c *) this_ptr; class_ptr->runtime_config(); } void bx_usb_uhci_c::runtime_config(void) { int i; char pname[6]; for (i = 0; i < BX_N_USB_UHCI_PORTS; i++) { // device change support if ((BX_UHCI_THIS hub.device_change & (1 << i)) != 0) { BX_INFO(("USB port #%d: device connect", i+1)); sprintf(pname, "port%d", i + 1); init_device(i, (bx_list_c*)SIM->get_param(pname, SIM->get_param(BXPN_USB_UHCI))); BX_UHCI_THIS hub.device_change &= ~(1 << i); } // forward to connected device if (BX_UHCI_THIS hub.usb_port[i].device != NULL) { BX_UHCI_THIS hub.usb_port[i].device->runtime_config(); } } } // pci configuration space read callback handler Bit32u bx_usb_uhci_c::pci_read_handler(Bit8u address, unsigned io_len) { Bit32u value = 0; for (unsigned i=0; i= 0x10) && (address < 0x20)) || ((address > 0x23) && (address < 0x34))) return; for (unsigned i=0; i> (i*8)) & 0xFF; oldval = BX_UHCI_THIS pci_conf[address+i]; switch (address+i) { case 0x04: value8 &= 0x05; BX_UHCI_THIS pci_conf[address+i] = value8; break; case 0x3d: // case 0x3e: // case 0x3f: // case 0x05: // disallowing write to command hi-byte case 0x06: // disallowing write to status lo-byte (is that expected?) break; case 0x3c: if (value8 != oldval) { BX_INFO(("new irq line = %d", value8)); BX_UHCI_THIS pci_conf[address+i] = value8; } break; case 0x20: value8 = (value8 & 0xfc) | 0x01; case 0x21: case 0x22: case 0x23: baseaddr_change |= (value8 != oldval); default: BX_UHCI_THIS pci_conf[address+i] = value8; } } if (baseaddr_change) { if (DEV_pci_set_base_io(BX_UHCI_THIS_PTR, read_handler, write_handler, &BX_UHCI_THIS pci_base_address[4], &BX_UHCI_THIS pci_conf[0x20], 32, &uhci_iomask[0], "USB UHCI Hub")) { BX_INFO(("new base address: 0x%04x", BX_UHCI_THIS pci_base_address[4])); } } if (io_len == 1) BX_DEBUG(("write PCI register 0x%02x value 0x%02x", address, value)); else if (io_len == 2) BX_DEBUG(("write PCI register 0x%02x value 0x%04x", address, value)); else if (io_len == 4) BX_DEBUG(("write PCI register 0x%02x value 0x%08x", address, value)); } void bx_usb_uhci_c::usb_set_connect_status(Bit8u port, int type, bx_bool connected) { usb_device_c *device = BX_UHCI_THIS hub.usb_port[port].device; if (device != NULL) { if (device->get_type() == type) { if (connected) { BX_UHCI_THIS hub.usb_port[port].low_speed = (device->get_speed() == USB_SPEED_LOW); if (BX_UHCI_THIS hub.usb_port[port].low_speed) { BX_UHCI_THIS hub.usb_port[port].line_dminus = 1; // dminus=1 & dplus=0 = low speed (at idle time) BX_UHCI_THIS hub.usb_port[port].line_dplus = 0; // dminus=0 & dplus=1 = high speed (at idle time) } else { BX_UHCI_THIS hub.usb_port[port].line_dminus = 0; BX_UHCI_THIS hub.usb_port[port].line_dplus = 1; } BX_UHCI_THIS hub.usb_port[port].status = 1; BX_UHCI_THIS hub.usb_port[port].connect_changed = 1; // if in suspend state, signal resume if (BX_UHCI_THIS hub.usb_command.suspend) { BX_UHCI_THIS hub.usb_port[port].resume = 1; BX_UHCI_THIS hub.usb_status.resume = 1; if (BX_UHCI_THIS hub.usb_enable.resume) { BX_UHCI_THIS hub.usb_status.interrupt = 1; } update_irq(); } if (!device->get_connected()) { if (!device->init()) { usb_set_connect_status(port, type, 0); BX_ERROR(("port #%d: connect failed", port+1)); } else { BX_INFO(("port #%d: connect: %s", port+1, device->get_info())); } } } else { BX_UHCI_THIS hub.usb_port[port].status = 0; BX_UHCI_THIS hub.usb_port[port].connect_changed = 1; if (BX_UHCI_THIS hub.usb_port[port].enabled) { BX_UHCI_THIS hub.usb_port[port].able_changed = 1; BX_UHCI_THIS hub.usb_port[port].enabled = 0; } BX_UHCI_THIS hub.usb_port[port].low_speed = 0; BX_UHCI_THIS hub.usb_port[port].line_dminus = 0; BX_UHCI_THIS hub.usb_port[port].line_dplus = 0; remove_device(port); } } } } // USB runtime parameter handler const char *bx_usb_uhci_c::usb_param_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { usbdev_type type = USB_DEV_TYPE_NONE; int portnum; if (set) { portnum = atoi((param->get_parent())->get_name()+4) - 1; bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none"))); if ((portnum >= 0) && (portnum < BX_N_USB_UHCI_PORTS)) { if (empty && BX_UHCI_THIS hub.usb_port[portnum].status) { BX_INFO(("USB port #%d: device disconnect", portnum+1)); if (BX_UHCI_THIS hub.usb_port[portnum].device != NULL) { type = BX_UHCI_THIS hub.usb_port[portnum].device->get_type(); } usb_set_connect_status(portnum, type, 0); } else if (!empty && !BX_UHCI_THIS hub.usb_port[portnum].status) { BX_UHCI_THIS hub.device_change |= (1 << portnum); } } else { BX_PANIC(("usb_param_handler called with unexpected parameter '%s'", param->get_name())); } } return val; } #endif // BX_SUPPORT_PCI && BX_SUPPORT_USB_UHCI bochs-2.6/iodev/usb/usb_common.h0000644000175000017500000001456012020641504016546 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_common.h 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Generic USB emulation code // // Copyright (c) 2005 Fabrice Bellard // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_USB_COMMON_H #define BX_IODEV_USB_COMMON_H #define USB_TOKEN_IN 0x69 #define USB_TOKEN_OUT 0xE1 #define USB_TOKEN_SETUP 0x2D #define USB_MSG_ATTACH 0x100 #define USB_MSG_DETACH 0x101 #define USB_MSG_RESET 0x102 #define USB_RET_NODEV (-1) #define USB_RET_NAK (-2) #define USB_RET_STALL (-3) #define USB_RET_BABBLE (-4) #define USB_RET_ASYNC (-5) #define USB_SPEED_LOW 0 #define USB_SPEED_FULL 1 #define USB_SPEED_HIGH 2 #define USB_SPEED_SUPER 3 #define USB_STATE_NOTATTACHED 0 #define USB_STATE_ATTACHED 1 //#define USB_STATE_POWERED 2 #define USB_STATE_DEFAULT 3 #define USB_STATE_ADDRESS 4 #define USB_STATE_CONFIGURED 5 #define USB_STATE_SUSPENDED 6 #define USB_DIR_OUT 0 #define USB_DIR_IN 0x80 #define USB_TYPE_MASK (0x03 << 5) #define USB_TYPE_STANDARD (0x00 << 5) #define USB_TYPE_CLASS (0x01 << 5) #define USB_TYPE_VENDOR (0x02 << 5) #define USB_TYPE_RESERVED (0x03 << 5) #define USB_RECIP_MASK 0x1f #define USB_RECIP_DEVICE 0x00 #define USB_RECIP_INTERFACE 0x01 #define USB_RECIP_ENDPOINT 0x02 #define USB_RECIP_OTHER 0x03 #define DeviceRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) #define DeviceOutRequest ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) #define InterfaceRequest \ ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) #define InterfaceInClassRequest \ ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) #define InterfaceOutRequest \ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) #define InterfaceOutClassRequest \ ((USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE)<<8) #define EndpointRequest ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) #define EndpointOutRequest \ ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT)<<8) #define USB_REQ_GET_STATUS 0x00 #define USB_REQ_CLEAR_FEATURE 0x01 #define USB_REQ_SET_FEATURE 0x03 #define USB_REQ_SET_ADDRESS 0x05 #define USB_REQ_GET_DESCRIPTOR 0x06 #define USB_REQ_SET_DESCRIPTOR 0x07 #define USB_REQ_GET_CONFIGURATION 0x08 #define USB_REQ_SET_CONFIGURATION 0x09 #define USB_REQ_GET_INTERFACE 0x0A #define USB_REQ_SET_INTERFACE 0x0B #define USB_REQ_SYNCH_FRAME 0x0C #define USB_DEVICE_SELF_POWERED 0 #define USB_DEVICE_REMOTE_WAKEUP 1 // USB 1.1 #define USB_DT_DEVICE 0x01 #define USB_DT_CONFIG 0x02 #define USB_DT_STRING 0x03 #define USB_DT_INTERFACE 0x04 #define USB_DT_ENDPOINT 0x05 // USB 2.0 #define USB_DT_DEVICE_QUALIFIER 0x06 #define USB_DT_OTHER_SPEED_CONFIG 0x07 #define USB_DT_INTERFACE_POWER 0x08 class usb_device_c; struct USBPacket { int pid; Bit8u devaddr; Bit8u devep; Bit8u *data; int len; usb_device_c *dev; }; enum usbdev_type { USB_DEV_TYPE_NONE=0, USB_DEV_TYPE_MOUSE, USB_DEV_TYPE_TABLET, USB_DEV_TYPE_KEYPAD, USB_DEV_TYPE_DISK, USB_DEV_TYPE_CDROM, USB_DEV_TYPE_HUB, USB_DEV_TYPE_PRINTER }; class bx_usb_devctl_c : public bx_usb_devctl_stub_c { public: bx_usb_devctl_c() {} virtual ~bx_usb_devctl_c() {} virtual int init_device(bx_list_c *portconf, logfunctions *hub, void **dev, bx_list_c *sr_list); virtual void usb_send_msg(void *dev, int msg); private: void parse_port_options(usb_device_c *dev, bx_list_c *portconf); }; class usb_device_c : public logfunctions { public: usb_device_c(void); virtual ~usb_device_c() {} virtual bx_bool init() {return 1;} virtual const char* get_info() {return NULL;} virtual int handle_packet(USBPacket *p); virtual void handle_reset() {} virtual int handle_control(int request, int value, int index, int length, Bit8u *data) {return 0;} virtual int handle_data(USBPacket *p) {return 0;} void register_state(bx_list_c *parent); virtual void register_state_specific(bx_list_c *parent) {} virtual void after_restore_state() {} virtual void cancel_packet(USBPacket *p) {} virtual bx_bool set_option(const char *option) {return 0;} virtual void runtime_config() {} bx_bool get_connected() {return d.connected;} usbdev_type get_type() {return d.type;} int get_maxspeed() {return d.maxspeed;} int get_speed() {return d.speed;} void set_speed(int speed) {d.speed = speed;} Bit8u get_address() {return d.addr;} int get_max_packet_size() {return d.max_packet_size;} void usb_send_msg(int msg); protected: struct { enum usbdev_type type; bx_bool connected; int maxspeed; int speed; Bit8u addr; Bit8u config; char devname[32]; int state; Bit8u setup_buf[8]; Bit8u data_buf[1024]; int remote_wakeup; int setup_state; int setup_len; int setup_index; int max_packet_size; bx_bool stall; } d; void usb_dump_packet(Bit8u *data, unsigned size); int set_usb_string(Bit8u *buf, const char *str); }; static BX_CPP_INLINE void usb_defer_packet(USBPacket *p, usb_device_c *dev) { p->dev = dev; } static BX_CPP_INLINE void usb_cancel_packet(USBPacket *p) { p->dev->cancel_packet(p); } #endif bochs-2.6/iodev/usb/usb_printer.h0000644000175000017500000000340512020641504016735 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_printer.h 10972 2012-01-14 12:36:32Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #ifndef BX_IODEV_USB_PRINTER_H #define BX_IODEV_USB_PRINTER_H class usb_printer_device_c : public usb_device_c { public: usb_printer_device_c(usbdev_type type, const char *filename); virtual ~usb_printer_device_c(void); virtual bx_bool init(); virtual const char* get_info(); virtual void handle_reset(); virtual int handle_control(int request, int value, int index, int length, Bit8u *data); virtual int handle_data(USBPacket *p); virtual void register_state_specific(bx_list_c *parent); private: struct { Bit8u printer_status; const char *fname; FILE *fp; char info_txt[BX_PATHNAME_LEN]; } s; }; #endif bochs-2.6/iodev/usb/usb_msd.cc0000644000175000017500000005026012020641504016174 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_msd.cc 11390 2012-09-02 09:37:47Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // USB mass storage device support (ported from QEMU) // // Copyright (c) 2006 CodeSourcery. // Written by Paul Brook // Copyright (C) 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB #include "usb_common.h" #include "hdimage/cdrom.h" #include "hdimage/hdimage.h" #include "scsi_device.h" #include "usb_msd.h" #define LOG_THIS enum USBMSDMode { USB_MSDM_CBW, USB_MSDM_DATAOUT, USB_MSDM_DATAIN, USB_MSDM_CSW }; struct usb_msd_cbw { Bit32u sig; Bit32u tag; Bit32u data_len; Bit8u flags; Bit8u lun; Bit8u cmd_len; Bit8u cmd[16]; }; struct usb_msd_csw { Bit32u sig; Bit32u tag; Bit32u residue; Bit8u status; }; // USB requests #define MassStorageReset 0xff #define GetMaxLun 0xfe static const Bit8u bx_msd_dev_descriptor[] = { 0x12, /* u8 bLength; */ 0x01, /* u8 bDescriptorType; Device */ 0x00, 0x02, /* u16 bcdUSB; v2.0 */ 0x00, /* u8 bDeviceClass; */ 0x00, /* u8 bDeviceSubClass; */ 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */ 0x40, /* u8 bMaxPacketSize0; 64 Bytes */ /* Vendor and product id are arbitrary. */ 0x00, 0x00, /* u16 idVendor; */ 0x00, 0x00, /* u16 idProduct; */ 0x00, 0x01, /* u16 bcdDevice */ 0x01, /* u8 iManufacturer; */ 0x02, /* u8 iProduct; */ 0x03, /* u8 iSerialNumber; */ 0x01 /* u8 bNumConfigurations; */ }; static const Bit8u bx_msd_config_descriptor[] = { /* one configuration */ 0x09, /* u8 bLength; */ 0x02, /* u8 bDescriptorType; Configuration */ 0x20, 0x00, /* u16 wTotalLength; */ 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x00, /* u8 iConfiguration; */ 0xc0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 0x00, /* u8 MaxPower; */ /* one interface */ 0x09, /* u8 if_bLength; */ 0x04, /* u8 if_bDescriptorType; Interface */ 0x00, /* u8 if_bInterfaceNumber; */ 0x00, /* u8 if_bAlternateSetting; */ 0x02, /* u8 if_bNumEndpoints; */ 0x08, /* u8 if_bInterfaceClass; MASS STORAGE */ 0x06, /* u8 if_bInterfaceSubClass; SCSI */ 0x50, /* u8 if_bInterfaceProtocol; Bulk Only */ 0x00, /* u8 if_iInterface; */ /* Bulk-In endpoint */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x02, /* u8 ep_bmAttributes; Bulk */ 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ 0x00, /* u8 ep_bInterval; */ /* Bulk-Out endpoint */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x02, /* u8 ep_bEndpointAddress; OUT Endpoint 2 */ 0x02, /* u8 ep_bmAttributes; Bulk */ 0x40, 0x00, /* u16 ep_wMaxPacketSize; */ 0x00 /* u8 ep_bInterval; */ }; static int cdrom_count = 0; usb_msd_device_c::usb_msd_device_c(usbdev_type type, const char *filename) { char pname[10]; char label[32]; char tmpfname[BX_PATHNAME_LEN]; char *ptr1, *ptr2; bx_param_string_c *path; bx_param_bool_c *status; d.type = type; d.maxspeed = USB_SPEED_FULL; d.speed = d.maxspeed; // TODO: d.max_packet_size = ??? memset((void*)&s, 0, sizeof(s)); if (d.type == USB_DEV_TYPE_DISK) { strcpy(d.devname, "BOCHS USB HARDDRIVE"); strcpy(tmpfname, filename); ptr1 = strtok(tmpfname, ":"); ptr2 = strtok(NULL, ":"); if ((ptr2 == NULL) || (strlen(ptr1) < 2)) { s.image_mode = BX_HDIMAGE_MODE_FLAT; s.fname = filename; } else { s.image_mode = SIM->hdimage_get_mode(ptr1); s.fname = filename+strlen(ptr1)+1; } s.journal[0] = 0; } else if (d.type == USB_DEV_TYPE_CDROM) { strcpy(d.devname, "BOCHS USB CDROM"); s.fname = filename; // config options bx_list_c *usb_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_USB); sprintf(pname, "cdrom%d", ++cdrom_count); sprintf(label, "USB CD-ROM #%d Configuration", cdrom_count); s.config = new bx_list_c(usb_rt, pname, label); s.config->set_options(bx_list_c::SERIES_ASK); s.config->set_runtime_param(1); s.config->set_device_param(this); path = new bx_param_string_c(s.config, "path", "Path", "", "", BX_PATHNAME_LEN); path->set(s.fname); path->set_handler(cd_param_string_handler); path->set_runtime_param(1); status = new bx_param_bool_c(s.config, "status", "Inserted", "", 1); status->set_handler(cd_param_handler); status->set_runtime_param(1); #if BX_WITH_WX bx_list_c *usb = (bx_list_c*)SIM->get_param("ports.usb"); usb->add(s.config); #endif } put("usb_msd", "USBMS"); } usb_msd_device_c::~usb_msd_device_c(void) { if (s.scsi_dev != NULL) delete s.scsi_dev; if (s.hdimage != NULL) { delete s.hdimage; #ifdef LOWLEVEL_CDROM } else if (s.cdrom != NULL) { delete s.cdrom; #if BX_WITH_WX bx_list_c *usb = (bx_list_c*)SIM->get_param("ports.usb"); usb->remove(s.config->get_name()); #endif bx_list_c *usb_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_USB); usb_rt->remove(s.config->get_name()); #endif } } bx_bool usb_msd_device_c::set_option(const char *option) { if (!strncmp(option, "journal:", 8)) { strcpy(s.journal, option+8); return 1; } return 0; } bx_bool usb_msd_device_c::init() { if (d.type == USB_DEV_TYPE_DISK) { s.hdimage = DEV_hdimage_init_image(s.image_mode, 0, s.journal); if (s.hdimage->open(s.fname) < 0) { BX_ERROR(("could not open hard drive image file '%s'", s.fname)); return 0; } else { s.scsi_dev = new scsi_device_t(s.hdimage, 0, usb_msd_command_complete, (void*)this); } sprintf(s.info_txt, "USB HD: path='%s', mode='%s'", s.fname, hdimage_mode_names[s.image_mode]); } else if (d.type == USB_DEV_TYPE_CDROM) { #ifdef LOWLEVEL_CDROM s.cdrom = DEV_hdimage_init_cdrom(s.fname); if (!s.cdrom->insert_cdrom()) { BX_ERROR(("could not open cdrom image file '%s'", s.fname)); return 0; } else { s.scsi_dev = new scsi_device_t(s.cdrom, 0, usb_msd_command_complete, (void*)this); } sprintf(s.info_txt, "USB CD: path='%s'", s.fname); #else BX_PANIC(("missing LOWLEVEL_CDROM support")); return 0; #endif } s.scsi_dev->register_state(s.sr_list, "scsidev"); s.mode = USB_MSDM_CBW; d.connected = 1; return 1; } const char* usb_msd_device_c::get_info() { return s.info_txt; } void usb_msd_device_c::register_state_specific(bx_list_c *parent) { s.sr_list = new bx_list_c(parent, "s", "USB MSD Device State"); new bx_shadow_num_c(s.sr_list, "mode", &s.mode); new bx_shadow_num_c(s.sr_list, "scsi_len", &s.scsi_len); new bx_shadow_num_c(s.sr_list, "usb_len", &s.usb_len); new bx_shadow_num_c(s.sr_list, "data_len", &s.data_len); new bx_shadow_num_c(s.sr_list, "residue", &s.residue); new bx_shadow_num_c(s.sr_list, "tag", &s.tag); new bx_shadow_num_c(s.sr_list, "result", &s.result); } void usb_msd_device_c::handle_reset() { BX_DEBUG(("Reset")); s.mode = USB_MSDM_CBW; } int usb_msd_device_c::handle_control(int request, int value, int index, int length, Bit8u *data) { int ret = 0; switch (request) { case DeviceRequest | USB_REQ_GET_STATUS: case EndpointRequest | USB_REQ_GET_STATUS: data[0] = (1 << USB_DEVICE_SELF_POWERED) | (d.remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 0; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: d.addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, bx_msd_dev_descriptor, sizeof(bx_msd_dev_descriptor)); ret = sizeof(bx_msd_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, bx_msd_config_descriptor, sizeof(bx_msd_config_descriptor)); ret = sizeof(bx_msd_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: // language IDs data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: // vendor description ret = set_usb_string(data, "BOCHS"); break; case 2: // product description if (strlen(d.devname) > 0) { ret = set_usb_string(data, d.devname); } else { goto fail; } break; case 3: // serial number ret = set_usb_string(data, s.scsi_dev->get_serial_number()); break; default: BX_ERROR(("USB MSD handle_control: unknown string descriptor 0x%02x", value & 0xff)); goto fail; } break; case USB_DT_DEVICE_QUALIFIER: // device qualifier data[0] = 10; data[1] = USB_DT_DEVICE_QUALIFIER; memcpy(data+2, bx_msd_dev_descriptor+2, 6); data[8] = 1; data[9] = 0; ret = 10; break; default: BX_ERROR(("USB MSD handle_control: unknown descriptor type 0x%02x", value >> 8)); goto fail; } break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: data[0] = 1; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: ret = 0; break; case DeviceRequest | USB_REQ_GET_INTERFACE: data[0] = 0; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_INTERFACE: case InterfaceOutRequest | USB_REQ_SET_INTERFACE: ret = 0; break; case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: if (value == 0 && index != 0x81) { /* clear ep halt */ goto fail; } ret = 0; break; // Class specific requests case InterfaceOutClassRequest | MassStorageReset: case MassStorageReset: s.mode = USB_MSDM_CBW; ret = 0; break; case InterfaceInClassRequest | GetMaxLun: case GetMaxLun: data[0] = 0; ret = 1; break; default: BX_ERROR(("USB MSD handle_control: unknown request 0x%04x", request)); fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } int usb_msd_device_c::handle_data(USBPacket *p) { struct usb_msd_cbw cbw; int ret = 0; Bit8u devep = p->devep; Bit8u *data = p->data; int len = p->len; switch (p->pid) { case USB_TOKEN_OUT: usb_dump_packet(data, len); if (devep != 2) goto fail; switch (s.mode) { case USB_MSDM_CBW: if (len != 31) { BX_ERROR(("bad CBW len")); goto fail; } memcpy(&cbw, data, 31); if (dtoh32(cbw.sig) != 0x43425355) { BX_ERROR(("bad signature %08x", dtoh32(cbw.sig))); goto fail; } BX_DEBUG(("command on LUN %d", cbw.lun)); s.tag = dtoh32(cbw.tag); s.data_len = dtoh32(cbw.data_len); if (s.data_len == 0) { s.mode = USB_MSDM_CSW; } else if (cbw.flags & 0x80) { s.mode = USB_MSDM_DATAIN; } else { s.mode = USB_MSDM_DATAOUT; } BX_DEBUG(("command tag 0x%x flags %08x len %d data %d", s.tag, cbw.flags, cbw.cmd_len, s.data_len)); s.residue = 0; s.scsi_dev->scsi_send_command(s.tag, cbw.cmd, cbw.lun); if (s.residue == 0) { if (s.mode == USB_MSDM_DATAIN) { s.scsi_dev->scsi_read_data(s.tag); } else if (s.mode == USB_MSDM_DATAOUT) { s.scsi_dev->scsi_write_data(s.tag); } } ret = len; break; case USB_MSDM_DATAOUT: BX_DEBUG(("data out %d/%d", len, s.data_len)); if (len > (int)s.data_len) goto fail; s.usb_buf = data; s.usb_len = len; if (s.scsi_len) { copy_data(); } if (s.residue && s.usb_len) { s.data_len -= s.usb_len; if (s.data_len == 0) s.mode = USB_MSDM_CSW; s.usb_len = 0; } if (s.usb_len) { BX_INFO(("deferring packet %p", p)); usb_defer_packet(p, this); s.packet = p; ret = USB_RET_ASYNC; } else { ret = len; } break; default: BX_ERROR(("USB MSD handle_data: unexpected mode at USB_TOKEN_OUT")); goto fail; } break; case USB_TOKEN_IN: if (devep != 1) goto fail; switch (s.mode) { case USB_MSDM_DATAOUT: if ((s.data_len > 0) && (len == 13)) { s.usb_len = len; s.usb_buf = data; send_status(); ret = 13; break; } if (s.data_len != 0 || len < 13) goto fail; usb_defer_packet(p, this); s.packet = p; ret = USB_RET_ASYNC; break; case USB_MSDM_CSW: BX_DEBUG(("command status %d tag 0x%x, len %d", s.result, s.tag, len)); if (len < 13) return ret; s.usb_len = len; s.usb_buf = data; send_status(); s.mode = USB_MSDM_CBW; ret = 13; break; case USB_MSDM_DATAIN: BX_DEBUG(("data in %d/%d", len, s.data_len)); if (len > (int)s.data_len) len = s.data_len; s.usb_buf = data; s.usb_len = len; if (s.scsi_len) { copy_data(); } if (s.residue && s.usb_len) { s.data_len -= s.usb_len; memset(s.usb_buf, 0, s.usb_len); if (s.data_len == 0) s.mode = USB_MSDM_CSW; s.usb_len = 0; } if (s.usb_len) { BX_INFO(("deferring packet %p", p)); usb_defer_packet(p, this); s.packet = p; ret = USB_RET_ASYNC; } else { ret = len; } break; default: BX_ERROR(("USB MSD handle_data: unexpected mode at USB_TOKEN_IN")); goto fail; } if (ret > 0) usb_dump_packet(data, ret); break; default: BX_ERROR(("USB MSD handle_data: bad token")); fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } void usb_msd_device_c::copy_data() { Bit32u len = s.usb_len; if (len > s.scsi_len) len = s.scsi_len; if (s.mode == USB_MSDM_DATAIN) { memcpy(s.usb_buf, s.scsi_buf, len); } else { memcpy(s.scsi_buf, s.usb_buf, len); } s.usb_len -= len; s.scsi_len -= len; s.usb_buf += len; s.scsi_buf += len; s.data_len -= len; if (s.scsi_len == 0) { if (s.mode == USB_MSDM_DATAIN) { s.scsi_dev->scsi_read_data(s.tag); } else if (s.mode == USB_MSDM_DATAOUT) { s.scsi_dev->scsi_write_data(s.tag); } } } void usb_msd_device_c::send_status() { struct usb_msd_csw csw; csw.sig = htod32(0x53425355); csw.tag = htod32(s.tag); csw.residue = s.residue; csw.status = s.result; memcpy(s.usb_buf, &csw, 13); } void usb_msd_device_c::usb_msd_command_complete(void *this_ptr, int reason, Bit32u tag, Bit32u arg) { usb_msd_device_c *class_ptr = (usb_msd_device_c *) this_ptr; class_ptr->command_complete(reason, tag, arg); } void usb_msd_device_c::command_complete(int reason, Bit32u tag, Bit32u arg) { USBPacket *p = s.packet; if (tag != s.tag) { BX_ERROR(("usb-msd_command_complete: unexpected SCSI tag 0x%x", tag)); } if (reason == SCSI_REASON_DONE) { BX_DEBUG(("command complete %d", arg)); s.residue = s.data_len; s.result = arg != 0; if (s.packet) { if (s.data_len == 0 && s.mode == USB_MSDM_DATAOUT) { send_status(); s.mode = USB_MSDM_CBW; } else { if (s.data_len) { s.data_len -= s.usb_len; if (s.mode == USB_MSDM_DATAIN) memset(s.usb_buf, 0, s.usb_len); s.usb_len = 0; } if (s.data_len == 0) s.mode = USB_MSDM_CSW; } s.packet = NULL; } else if (s.data_len == 0) { s.mode = USB_MSDM_CSW; } return; } s.scsi_len = arg; s.scsi_buf = s.scsi_dev->scsi_get_buf(tag); if (p) { copy_data(); if (s.usb_len == 0) { BX_INFO(("packet complete %p", p)); s.packet = NULL; } } } void usb_msd_device_c::cancel_packet(USBPacket *p) { s.scsi_dev->scsi_cancel_io(s.tag); s.packet = NULL; s.scsi_len = 0; } void usb_msd_device_c::set_inserted(bx_bool value) { #ifdef LOWLEVEL_CDROM const char *path; if (value) { path = SIM->get_param_string("path", s.config)->getptr(); if (!s.cdrom->insert_cdrom(path)) { SIM->get_param_bool("status", s.config)->set(0); return; } } else { s.cdrom->eject_cdrom(); } s.scsi_dev->set_inserted(value); #else SIM->get_param_bool("status", s.config)->set(0); #endif } bx_bool usb_msd_device_c::get_inserted() { return s.scsi_dev->get_inserted(); } #undef LOG_THIS #define LOG_THIS cdrom-> // USB hub runtime parameter handlers const char *usb_msd_device_c::cd_param_string_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { usb_msd_device_c *cdrom; if (set) { cdrom = (usb_msd_device_c*) param->get_parent()->get_device_param(); if (cdrom != NULL) { bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none"))); if (!empty) { if (cdrom->get_inserted()) { BX_ERROR(("direct path change not supported (setting to 'none')")); param->set("none"); } } else { SIM->get_param_bool("status", param->get_parent())->set(0); } } else { BX_PANIC(("cd_param_string_handler: cdrom not found")); } } return val; } Bit64s usb_msd_device_c::cd_param_handler(bx_param_c *param, int set, Bit64s val) { usb_msd_device_c *cdrom; const char *path; if (set) { cdrom = (usb_msd_device_c*) param->get_parent()->get_device_param(); if (cdrom != NULL) { path = SIM->get_param_string("path", param->get_parent())->getptr(); val &= ((strlen(path) > 0) && (strcmp(path, "none"))); if (val != cdrom->get_inserted()) { cdrom->set_inserted((bx_bool)val); } } else { BX_PANIC(("cd_param_string_handler: cdrom not found")); } } return val; } #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB bochs-2.6/iodev/usb/usb_hub.cc0000644000175000017500000005252412020641504016174 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_hub.cc 11384 2012-08-31 12:08:19Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // USB hub emulation support (ported from QEMU) // // Copyright (C) 2005 Fabrice Bellard // Copyright (C) 2009-2012 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. ///////////////////////////////////////////////////////////////////////// // Define BX_PLUGGABLE in files that can be compiled into plugins. For // platforms that require a special tag on exported symbols, BX_PLUGGABLE // is used to know when we are exporting symbols and when we are importing. #define BX_PLUGGABLE #include "iodev.h" #if BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB #include "usb_common.h" #include "usb_hub.h" #define LOG_THIS #define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) #define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) #define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) #define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) #define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) #define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) #define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) #define PORT_STAT_CONNECTION 0x0001 #define PORT_STAT_ENABLE 0x0002 #define PORT_STAT_SUSPEND 0x0004 #define PORT_STAT_OVERCURRENT 0x0008 #define PORT_STAT_RESET 0x0010 #define PORT_STAT_POWER 0x0100 #define PORT_STAT_LOW_SPEED 0x0200 #define PORT_STAT_HIGH_SPEED 0x0400 #define PORT_STAT_TEST 0x0800 #define PORT_STAT_INDICATOR 0x1000 #define PORT_STAT_C_CONNECTION 0x0001 #define PORT_STAT_C_ENABLE 0x0002 #define PORT_STAT_C_SUSPEND 0x0004 #define PORT_STAT_C_OVERCURRENT 0x0008 #define PORT_STAT_C_RESET 0x0010 #define PORT_CONNECTION 0 #define PORT_ENABLE 1 #define PORT_SUSPEND 2 #define PORT_OVERCURRENT 3 #define PORT_RESET 4 #define PORT_POWER 8 #define PORT_LOWSPEED 9 #define PORT_HIGHSPEED 10 #define PORT_C_CONNECTION 16 #define PORT_C_ENABLE 17 #define PORT_C_SUSPEND 18 #define PORT_C_OVERCURRENT 19 #define PORT_C_RESET 20 #define PORT_TEST 21 #define PORT_INDICATOR 22 static Bit32u serial_number = 1234; static const Bit8u bx_hub_dev_descriptor[] = { 0x12, /* u8 bLength; */ 0x01, /* u8 bDescriptorType; Device */ 0x00, 0x02, /* u16 bcdUSB; v2.0 */ 0x09, /* u8 bDeviceClass; HUB_CLASSCODE */ 0x00, /* u8 bDeviceSubClass; */ 0x00, /* u8 bDeviceProtocol; [ low/full speeds only ] */ 0x40, /* u8 bMaxPacketSize0; 64 Bytes */ 0x09, 0x04, /* u16 idVendor; */ 0x5A, 0x00, /* u16 idProduct; */ 0x00, 0x01, /* u16 bcdDevice */ 0x00, /* u8 iManufacturer; */ 0x00, /* u8 iProduct; */ 0x00, /* u8 iSerialNumber; */ 0x01 /* u8 bNumConfigurations; */ }; /* XXX: patch interrupt size */ static const Bit8u bx_hub_config_descriptor[] = { /* one configuration */ 0x09, /* u8 bLength; */ 0x02, /* u8 bDescriptorType; Configuration */ 0x19, 0x00, /* u16 wTotalLength; */ 0x01, /* u8 bNumInterfaces; (1) */ 0x01, /* u8 bConfigurationValue; */ 0x00, /* u8 iConfiguration; */ 0xE0, /* u8 bmAttributes; Bit 7: must be set, 6: Self-powered, 5: Remote wakeup, 4..0: resvd */ 0x32, /* u8 MaxPower; */ /* USB 1.1: * USB 2.0, single TT organization (mandatory): * one interface, protocol 0 * * USB 2.0, multiple TT organization (optional): * two interfaces, protocols 1 (like single TT) * and 2 (multiple TT mode) ... config is * sometimes settable * NOT IMPLEMENTED */ /* one interface */ 0x09, /* u8 if_bLength; */ 0x04, /* u8 if_bDescriptorType; Interface */ 0x00, /* u8 if_bInterfaceNumber; */ 0x00, /* u8 if_bAlternateSetting; */ 0x01, /* u8 if_bNumEndpoints; */ 0x09, /* u8 if_bInterfaceClass; HUB_CLASSCODE */ 0x00, /* u8 if_bInterfaceSubClass; */ 0x00, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ 0x00, /* u8 if_iInterface; */ /* one endpoint (status change endpoint) */ 0x07, /* u8 ep_bLength; */ 0x05, /* u8 ep_bDescriptorType; Endpoint */ 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03, /* u8 ep_bmAttributes; Interrupt */ 0x02, 0x00, /* u16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ 0xff /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ }; static const Bit8u bx_hub_hub_descriptor[] = { 0x00, /* u8 bLength; patched in later */ 0x29, /* u8 bDescriptorType; Hub-descriptor */ 0x00, /* u8 bNbrPorts; (patched later) */ 0xa9, /* u16 wHubCharacteristics; */ 0x00, /* (per-port OC, no power switching) */ 0x32, /* u8 bPwrOn2pwrGood; 2ms */ 0x64 /* u8 bHubContrCurrent; 0 mA */ /* DeviceRemovable and PortPwrCtrlMask patched in later */ }; static int hub_count = 0; usb_hub_device_c::usb_hub_device_c(Bit8u ports) { int i; char pname[10]; char label[32]; bx_list_c *port; bx_param_string_c *device, *options; d.type = USB_DEV_TYPE_HUB; d.maxspeed = USB_SPEED_FULL; d.speed = d.maxspeed; // TODO: d.max_packet_size = ??? strcpy(d.devname, "Bochs USB HUB"); d.connected = 1; memset((void*)&hub, 0, sizeof(hub)); hub.n_ports = ports; sprintf(hub.serial_number, "%d", serial_number++); for(i = 0; i < hub.n_ports; i++) { hub.usb_port[i].PortStatus = PORT_STAT_POWER; hub.usb_port[i].PortChange = 0; } hub.device_change = 0; // config options bx_list_c *usb_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_USB); sprintf(pname, "exthub%d", ++hub_count); sprintf(label, "External Hub #%d Configuration", hub_count); hub.config = new bx_list_c(usb_rt, pname, label); hub.config->set_options(bx_list_c::SHOW_PARENT); hub.config->set_runtime_param(1); hub.config->set_device_param(this); for(i = 0; i < hub.n_ports; i++) { sprintf(pname, "port%d", i+1); sprintf(label, "Port #%d Configuration", i+1); port = new bx_list_c(hub.config, pname, label); port->set_options(port->SERIES_ASK | port->USE_BOX_TITLE); port->set_runtime_param(1); device = new bx_param_string_c(port, "device", "Device", "", "", BX_PATHNAME_LEN); device->set_handler(hub_param_handler); device->set_runtime_param(1); options = new bx_param_string_c(port, "options", "Options", "", "", BX_PATHNAME_LEN); options->set_runtime_param(1); } #if BX_WITH_WX bx_list_c *usb = (bx_list_c*)SIM->get_param("ports.usb"); usb->add(hub.config); #endif put("usb_hub", "USBHB"); } usb_hub_device_c::~usb_hub_device_c(void) { for (int i=0; iget_param("ports.usb"); usb->remove(hub.config->get_name()); #endif bx_list_c *usb_rt = (bx_list_c*)SIM->get_param(BXPN_MENU_RUNTIME_USB); usb_rt->remove(hub.config->get_name()); } void usb_hub_device_c::register_state_specific(bx_list_c *parent) { Bit8u i; char portnum[6]; bx_list_c *port; hub.state = new bx_list_c(parent, "hub", "USB HUB Device State"); for (i=0; iafter_restore_state(); } } } void usb_hub_device_c::handle_reset() { // TODO BX_DEBUG(("Reset")); } int usb_hub_device_c::handle_control(int request, int value, int index, int length, Bit8u *data) { int ret = 0; unsigned int n; switch(request) { case DeviceRequest | USB_REQ_GET_STATUS: if (d.state == USB_STATE_DEFAULT) goto fail; else { data[0] = (1 << USB_DEVICE_SELF_POWERED) | (d.remote_wakeup << USB_DEVICE_REMOTE_WAKEUP); data[1] = 0x00; ret = 2; } break; case DeviceOutRequest | USB_REQ_CLEAR_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 0; } else { goto fail; } ret = 0; break; case EndpointOutRequest | USB_REQ_CLEAR_FEATURE: if (value == 0 && index != 0x81) { /* clear ep halt */ goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_FEATURE: if (value == USB_DEVICE_REMOTE_WAKEUP) { d.remote_wakeup = 1; } else { goto fail; } ret = 0; break; case DeviceOutRequest | USB_REQ_SET_ADDRESS: d.state = USB_STATE_ADDRESS; d.addr = value; ret = 0; break; case DeviceRequest | USB_REQ_GET_DESCRIPTOR: switch(value >> 8) { case USB_DT_DEVICE: memcpy(data, bx_hub_dev_descriptor, sizeof(bx_hub_dev_descriptor)); ret = sizeof(bx_hub_dev_descriptor); break; case USB_DT_CONFIG: memcpy(data, bx_hub_config_descriptor, sizeof(bx_hub_config_descriptor)); /* status change endpoint size based on number * of ports */ data[22] = (hub.n_ports + 1 + 7) / 8; ret = sizeof(bx_hub_config_descriptor); break; case USB_DT_STRING: switch(value & 0xff) { case 0: /* language ids */ data[0] = 4; data[1] = 3; data[2] = 0x09; data[3] = 0x04; ret = 4; break; case 1: /* serial number */ ret = set_usb_string(data, hub.serial_number); break; case 2: /* product description */ ret = set_usb_string(data, "Bochs USB HUB"); break; case 3: /* vendor description */ ret = set_usb_string(data, "Bochs"); break; default: BX_ERROR(("unknown string descriptor type %i", value & 0xff)); goto fail; } break; default: BX_ERROR(("unknown descriptor type: 0x%02x", (value >> 8))); goto fail; } break; case DeviceRequest | USB_REQ_GET_CONFIGURATION: data[0] = 1; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_CONFIGURATION: d.state = USB_STATE_CONFIGURED; ret = 0; break; case DeviceRequest | USB_REQ_GET_INTERFACE: data[0] = 0; ret = 1; break; case DeviceOutRequest | USB_REQ_SET_INTERFACE: ret = 0; break; /* usb specific requests */ case GetHubStatus: if (d.state == USB_STATE_CONFIGURED) { data[0] = 0; data[1] = 0; data[2] = 0; data[3] = 0; ret = 4; } else goto fail; break; case GetPortStatus: n = index - 1; if (n >= hub.n_ports) goto fail; data[0] = (hub.usb_port[n].PortStatus & 0xff); data[1] = (hub.usb_port[n].PortStatus >> 8); data[2] = (hub.usb_port[n].PortChange & 0xff); data[3] = (hub.usb_port[n].PortChange >> 8); ret = 4; break; case SetHubFeature: case ClearHubFeature: if (value == 0 || value == 1) { } else { goto fail; } ret = 0; break; case SetPortFeature: n = index - 1; if (n >= hub.n_ports) goto fail; switch(value) { case PORT_SUSPEND: hub.usb_port[n].PortStatus |= PORT_STAT_SUSPEND; break; case PORT_RESET: if (hub.usb_port[n].device != NULL) { DEV_usb_send_msg(hub.usb_port[n].device, USB_MSG_RESET); hub.usb_port[n].PortChange |= PORT_STAT_C_RESET; /* set enable bit */ hub.usb_port[n].PortStatus |= PORT_STAT_ENABLE; } break; case PORT_POWER: break; default: BX_ERROR(("Unknown SetPortFeature: %i", value)); goto fail; } ret = 0; break; case ClearPortFeature: n = index - 1; if (n >= hub.n_ports) goto fail; switch(value) { case PORT_ENABLE: hub.usb_port[n].PortStatus &= ~PORT_STAT_ENABLE; break; case PORT_C_ENABLE: hub.usb_port[n].PortChange &= ~PORT_STAT_C_ENABLE; break; case PORT_SUSPEND: hub.usb_port[n].PortStatus &= ~PORT_STAT_SUSPEND; break; case PORT_C_SUSPEND: hub.usb_port[n].PortChange &= ~PORT_STAT_C_SUSPEND; break; case PORT_C_CONNECTION: hub.usb_port[n].PortChange &= ~PORT_STAT_C_CONNECTION; break; case PORT_C_OVERCURRENT: hub.usb_port[n].PortChange &= ~PORT_STAT_C_OVERCURRENT; break; case PORT_C_RESET: hub.usb_port[n].PortChange &= ~PORT_STAT_C_RESET; break; default: BX_ERROR(("Unknown ClearPortFeature: %i", value)); goto fail; } ret = 0; break; case GetHubDescriptor: { unsigned int limit, var_hub_size = 0; memcpy(data, bx_hub_hub_descriptor, sizeof(bx_hub_hub_descriptor)); data[2] = hub.n_ports; /* fill DeviceRemovable bits */ limit = ((hub.n_ports + 1 + 7) / 8) + 7; for (n = 7; n < limit; n++) { data[n] = 0x00; var_hub_size++; } /* fill PortPwrCtrlMask bits */ limit = limit + ((hub.n_ports + 7) / 8); for (;n < limit; n++) { data[n] = 0xff; var_hub_size++; } ret = sizeof(bx_hub_hub_descriptor) + var_hub_size; data[0] = ret; break; } default: BX_ERROR(("handle_control: unknown request: 0x%04x", request)); fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } int usb_hub_device_c::handle_data(USBPacket *p) { int ret = 0; switch(p->pid) { case USB_TOKEN_IN: if (p->devep == 1) { unsigned int status; int i, n; n = (hub.n_ports + 1 + 7) / 8; if (p->len == 1) { /* FreeBSD workaround */ n = 1; } else if (n > p->len) { return USB_RET_BABBLE; } status = 0; for(i = 0; i < hub.n_ports; i++) { if (hub.usb_port[i].PortChange) status |= (1 << (i + 1)); } if (status != 0) { for(i = 0; i < n; i++) { p->data[i] = status >> (8 * i); } ret = n; } else { ret = USB_RET_NAK; /* usb11 11.13.1 */ } } else { goto fail; } break; case USB_TOKEN_OUT: default: fail: d.stall = 1; ret = USB_RET_STALL; break; } return ret; } int usb_hub_device_c::broadcast_packet(USBPacket *p) { int i, ret; usb_device_c *dev; for(i = 0; i < hub.n_ports; i++) { dev = hub.usb_port[i].device; if ((dev != NULL) && (hub.usb_port[i].PortStatus & PORT_STAT_ENABLE)) { ret = dev->handle_packet(p); if (ret != USB_RET_NODEV) { return ret; } } } return USB_RET_NODEV; } int usb_hub_device_c::handle_packet(USBPacket *p) { if ((d.state >= USB_STATE_DEFAULT) && (d.addr != 0) && (p->devaddr != d.addr) && ((p->pid == USB_TOKEN_SETUP) || (p->pid == USB_TOKEN_OUT) || (p->pid == USB_TOKEN_IN))) { /* broadcast the packet to the devices */ return broadcast_packet(p); } return usb_device_c::handle_packet(p); } void usb_hub_device_c::init_device(Bit8u port, bx_list_c *portconf) { usbdev_type type; char pname[BX_PATHNAME_LEN]; const char *devname = NULL; devname = ((bx_param_string_c*)portconf->get_by_name("device"))->getptr(); if (devname == NULL) return; if (!strlen(devname) || !strcmp(devname, "none")) return; if (hub.usb_port[port].device != NULL) { BX_ERROR(("init_device(): port%d already in use", port+1)); return; } sprintf(pname, "port%d.device", port+1); bx_list_c *sr_list = (bx_list_c*)SIM->get_param(pname, hub.state); type = DEV_usb_init_device(portconf, this, &hub.usb_port[port].device, sr_list); if (hub.usb_port[port].device != NULL) { usb_set_connect_status(port, type, 1); } } void usb_hub_device_c::remove_device(Bit8u port) { char pname[BX_PATHNAME_LEN]; if (hub.usb_port[port].device != NULL) { delete hub.usb_port[port].device; hub.usb_port[port].device = NULL; sprintf(pname, "port%d.device", port+1); bx_list_c *devlist = (bx_list_c*)SIM->get_param(pname, hub.state); devlist->clear(); } } void usb_hub_device_c::usb_set_connect_status(Bit8u port, int type, bx_bool connected) { usb_device_c *device = hub.usb_port[port].device; if (device != NULL) { if (device->get_type() == type) { if (connected) { hub.usb_port[port].PortStatus |= PORT_STAT_CONNECTION; hub.usb_port[port].PortChange |= PORT_STAT_C_CONNECTION; if (device->get_speed() == USB_SPEED_LOW) hub.usb_port[port].PortStatus |= PORT_STAT_LOW_SPEED; else hub.usb_port[port].PortStatus &= ~PORT_STAT_LOW_SPEED; if (!device->get_connected()) { if (!device->init()) { usb_set_connect_status(port, type, 0); BX_ERROR(("port #%d: connect failed", port+1)); } else { BX_INFO(("port #%d: connect: %s", port+1, device->get_info())); } } } else { hub.usb_port[port].PortStatus &= ~PORT_STAT_CONNECTION; hub.usb_port[port].PortChange |= PORT_STAT_C_CONNECTION; if (hub.usb_port[port].PortStatus & PORT_STAT_ENABLE) { hub.usb_port[port].PortStatus &= ~PORT_STAT_ENABLE; hub.usb_port[port].PortChange |= PORT_STAT_C_ENABLE; } remove_device(port); } } } } void usb_hub_device_c::runtime_config() { int i, hubnum; char pname[6]; for (i = 0; i < hub.n_ports; i++) { // device change support if ((hub.device_change & (1 << i)) != 0) { hubnum = atoi(hub.config->get_name()+6); BX_INFO(("USB hub #%d, port #%d: device connect", hubnum, i+1)); sprintf(pname, "port%d", i + 1); init_device(i, (bx_list_c*)SIM->get_param(pname, hub.config)); hub.device_change &= ~(1 << i); } // forward to connected device if (hub.usb_port[i].device != NULL) { hub.usb_port[i].device->runtime_config(); } } } #undef LOG_THIS #define LOG_THIS hub-> // USB hub runtime parameter handler const char *usb_hub_device_c::hub_param_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen) { usbdev_type type = USB_DEV_TYPE_NONE; int hubnum, portnum; usb_hub_device_c *hub; bx_list_c *port; if (set) { port = (bx_list_c*)param->get_parent(); hub = (usb_hub_device_c*)(port->get_parent()->get_device_param()); if (hub != NULL) { hubnum = atoi(port->get_parent()->get_name()+6); portnum = atoi(port->get_name()+4) - 1; bx_bool empty = ((strlen(val) == 0) || (!strcmp(val, "none"))); if ((portnum >= 0) && (portnum < hub->hub.n_ports)) { if (empty && (hub->hub.usb_port[portnum].PortStatus & PORT_STAT_CONNECTION)) { BX_INFO(("USB hub #%d, port #%d: device disconnect", hubnum, portnum+1)); if (hub->hub.usb_port[portnum].device != NULL) { type = hub->hub.usb_port[portnum].device->get_type(); } hub->usb_set_connect_status(portnum, type, 0); } else if (!empty && !(hub->hub.usb_port[portnum].PortStatus & PORT_STAT_CONNECTION)) { hub->hub.device_change |= (1 << portnum); } } else { BX_PANIC(("usb_param_handler called with unexpected parameter '%s'", param->get_name())); } } else { BX_PANIC(("hub_param_handler: external hub not found")); } } return val; } #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB bochs-2.6/iodev/usb/usb_uhci.h0000644000175000017500000001615512020641504016210 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usb_uhci.h 11220 2012-06-17 07:14:27Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) // 2009-2012 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_IODEV_USB_UHCI_H #define BX_IODEV_USB_UHCI_H #if BX_USE_USB_UHCI_SMF # define BX_UHCI_THIS theUSB_UHCI-> # define BX_UHCI_THIS_PTR theUSB_UHCI #else # define BX_UHCI_THIS this-> # define BX_UHCI_THIS_PTR this #endif // defined in bochs.h: UHCI supports 2 ports per root hub typedef struct { int timer_index; // Registers // Base + 0x00 Command register // Base + 0x02 Status register // Base + 0x04 Interrupt Enable register // Base + 0x06 Frame Number register // Base + 0x08 Frame Base Register (32-bit) // Base + 0x0C Start of Frame Modify register // Base + 0x0D // Base + 0x0E // Base + 0x0F // Base + 0x10 Eight(?) 16-bit ports (one for each port on hub) // Bit reps of registers above // Command Register // Bits 15-8 are reserved // Bit 7 = Maximum packet size // Bit 6 = Host Controller has been configured (set by software) // Bit 5 = software debug mode // Bit 4 = force global resume // Bit 3 = enter global suspend mode // Bit 2 = global reset // Bit 1 = host controller reset // Bit 0 = run/stop schedule struct { bx_bool max_packet_size; //(bit 7) 0 = 32 bytes, 1 = 64 bytes bx_bool configured; //(bit 6) bx_bool debug; //(bit 5) bx_bool resume; //(bit 4) bx_bool suspend; //(bit 3) bx_bool reset; //(bit 2) bx_bool host_reset; //(bit 1) bx_bool schedule; //(bit 0) 0 = Stop, 1 = Run } usb_command; // Status Register // Bits 15-6 are reserved // Bit 5 = Host controller halted // Bit 4 = Host controller process error // Bit 3 = PCI Bus error // Bit 2 = resume received // Bit 1 = USB error interrupt // Bit 0 = USB interrupt struct { bx_bool host_halted; //(bit 5) bx_bool host_error; //(bit 4) bx_bool pci_error; //(bit 3) bx_bool resume; //(bit 2) bx_bool error_interrupt; //(bit 1) bx_bool interrupt; //(bit 0) Bit8u status2; // bit 0 and 1 are used to generate the interrupt } usb_status; // Interrupt Enable Register // Bits 15-4 are reserved // Bit 3 = enable short packet interrupts // Bit 2 = enable interrupt On Complete // Bit 1 = enable resume // Bit 0 = enable timeout/crc struct { bx_bool short_packet; //(bit 3) bx_bool on_complete; //(bit 2) bx_bool resume; //(bit 1) bx_bool timeout_crc; //(bit 0) } usb_enable; // Frame Number Register // Bits 15-11 are reserved // Bits 10-0 Frame List Current Index/Frame Number struct { Bit16u frame_num; } usb_frame_num; // Frame List Base Address Register // Bits 31-12 Base // Bits 11-0 *must* be zeros when written to struct { Bit32u frame_base; } usb_frame_base; // Start of Frame Modify Register // Bit 7 reserved // Bits 6-0 SOF timing value (default 64) // SOF cycle time equals 11936+timing value struct { Bit8u sof_timing; } usb_sof; // Port Register (0-1) // Bits 15-13 are reserved // Bit 12 suspend port // Bit 11-10 are reserved // Bit 9 port in reset state // Bit 8 low-speed device is attached (read-only) // Bit 7 reserved // Bit 6 resume detected (read-only) // Bit 5 line-status D+ (read-only) // Bit 4 line-status D- (read-only) // Bit 3 port enabled/disable status has changed // (write 1 to this bit to clear it) // Bit 2 port is enabled // Bit 1 connect status has changed // (write 1 to this bit to clear it) // Bit 0 current connect status (read-only) // Can only write in WORD sizes (Read in byte sizes???) struct { // our data usb_device_c *device; // device connected to this port // bit reps of actual port bx_bool suspend; bx_bool reset; bx_bool low_speed; bx_bool resume; bx_bool line_dminus; bx_bool line_dplus; bx_bool able_changed; bx_bool enabled; bx_bool connect_changed; bx_bool status; } usb_port[BX_N_USB_UHCI_PORTS]; Bit8u devfunc; int statusbar_id; // ID of the status LEDs Bit8u device_change; } bx_usb_uhci_t; #pragma pack (push, 1) struct TD { Bit32u dword0; Bit32u dword1; Bit32u dword2; Bit32u dword3; Bit32u resv[4]; }; #pragma pack (pop) #define HC_HORZ 0x80 #define HC_VERT 0x81 struct HCSTACK { Bit32u next; Bit8u d; // if queue, denotes VERT or HORZ bx_bool q; bx_bool t; }; class bx_usb_uhci_c : public bx_devmodel_c, public bx_pci_device_stub_c { public: bx_usb_uhci_c(); virtual ~bx_usb_uhci_c(); virtual void init(void); virtual void reset(unsigned); virtual void register_state(void); virtual void after_restore_state(void); virtual Bit32u pci_read_handler(Bit8u address, unsigned io_len); virtual void pci_write_handler(Bit8u address, Bit32u value, unsigned io_len); static const char *usb_param_handler(bx_param_string_c *param, int set, const char *oldval, const char *val, int maxlen); private: bx_usb_uhci_t hub; Bit8u global_reset; bx_bool busy; Bit8u *device_buffer; USBPacket usb_packet; static void update_irq(void); static void init_device(Bit8u port, bx_list_c *portconf); static void remove_device(Bit8u port); static int broadcast_packet(USBPacket *p); static void usb_set_connect_status(Bit8u port, int type, bx_bool connected); static void usb_timer_handler(void *); void usb_timer(void); bx_bool DoTransfer(Bit32u address, Bit32u queue_num, struct TD *); void set_status(struct TD *td, bx_bool stalled, bx_bool data_buffer_error, bx_bool babble, bx_bool nak, bx_bool crc_time_out, bx_bool bitstuff_error, Bit16u act_len); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_USB_UHCI_SMF Bit32u read(Bit32u address, unsigned io_len); void write(Bit32u address, Bit32u value, unsigned io_len); #endif static void runtime_config_handler(void *); void runtime_config(void); }; #endif bochs-2.6/iodev/busmouse.h0000644000175000017500000000677112020641505015464 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: busmouse.h 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2004-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if BX_SUPPORT_BUSMOUSE #ifndef _PCBUSM_H #define _PCBUSM_H // these keywords should only be used in busmouse.cc #if BX_USE_BUSM_SMF # define BX_BUSM_SMF static # define BX_BUSM_THIS theBusMouse-> #else # define BX_BUSM_SMF # define BX_BUSM_THIS #endif #define BUS_MOUSE_IRQ 5 #define PORT_CONTROL 0x023C #define PORT_DATA 0x023D #define PORT_SIGNATURE 0x023E #define PORT_CONFIG 0x023F class bx_busm_c : public bx_devmodel_c { public: bx_busm_c(); virtual ~bx_busm_c(); virtual void init(void); virtual void reset(unsigned type) {} virtual void register_state(void); private: static void timer_handler(void *); void busm_timer(void); static void mouse_enq_static(void *dev, int delta_x, int delta_y, int delta_z, unsigned button_state); void mouse_enq(int delta_x, int delta_y, int delta_z, unsigned button_state); static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len); static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len); #if !BX_USE_BUSM_SMF void write(Bit32u address, Bit32u value, unsigned io_len); Bit32u read(Bit32u address, unsigned io_len); #endif int timer_index; // our timer index int mouse_delayed_dx; int mouse_delayed_dy; Bit8u current_x, current_y, current_b; // signature port Bit8u sig_port_sequ; // bit0: 0 or 1. A register read rotates between two values? 0xDE and Hardware ID? // D7 = Mode set flag (1 = active) // D6,D5 = Mode selection (port A) // 00 = Mode 0 = Basic I/O // 01 = Mode 1 = Strobed I/O // 10 = Mode 2 = Bi-dir bus // D4 = Port A direction (1 = input) // D3 = Port C (upper 4 bits) // direction. (1 = input) // D2 = Mode selection (port B & C) // 0 = Mode 0 = Basic I/O // 1 = Mode 1 = Strobed I/O // D1 = Port B direction (1 = input) // D0 = Port C (lower 4 bits) // direction. (1 = input) Bit8u control_val; struct { bx_bool mode_set; Bit8u modeA_select; bx_bool portA_dir; // 1 = input bx_bool portC_upper_dir; // 1 = input bx_bool modeBC_select; bx_bool portB_dir; // 1 = input bx_bool portC_lower_dir; // 1 = input } control; bx_bool interrupts; // 0 or 1. interrupts off or on. bx_bool packet_update; // 0 or 1. allow the mouse to update the packet? Bit8u cur_command; // current command Bit8u command_val; // current command val }; #endif // #ifndef _PCBUSM_H #endif // BX_SUPPORT_BUSMOUSE bochs-2.6/wxbochs.rc0000644000175000017500000000025512020641507014337 0ustar guillemguillem#include "config.h" icon_bochs ICON build\win32\nsis\bochs.ico #include "wx/msw/wx.rc" #if BX_WITH_WIN32 #include "win32res.rc" #else #include "bxversion.rc" #endif bochs-2.6/.conf.sparc0000755000175000017500000000103312020641507014367 0ustar guillemguillem#!/bin/sh # # These are the steps I typically use to configure and compile Bochs. # # superSPARC w/ Solaris 2.x set echo CC="gcc" CXX="g++" #CFLAGS="-Wall -O2 -mv8 -msupersparc -mno-epilogue" CFLAGS="-Wall -O2 -mv8 -msupersparc" #CFLAGS="-Wall -O2 -g" CXXFLAGS="$CFLAGS" export CC export CXX export CFLAGS export CXXFLAGS ./configure --enable-ne2000 \ --enable-all-optimizations \ --enable-cpu-level=6 \ --enable-x86-64 \ --enable-pci \ --enable-clgd54xx \ --enable-usb unset echo bochs-2.6/bx_debug/0000755000175000017500000000000012020641506014110 5ustar guillemguillembochs-2.6/bx_debug/symbols.cc0000644000175000017500000002426012020641506016113 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: symbols.cc 11161 2012-05-05 18:40:37Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu/cpu.h" #if BX_DEBUGGER #if !((BX_HAVE_MAP || BX_HAVE_MAP_H) && (BX_HAVE_SET || BX_HAVE_SET_H)) static const char BX_HAVE_MAP_ERR[] = "context not implemented because BX_HAVE_MAP=0\n"; const char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base) { static bx_bool first = true; if (first) { dbg_printf(BX_HAVE_MAP_ERR); first = false; } return "unk. ctxt"; } const char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs) { // just prints an error anyway return bx_dbg_symbolic_address (0,0,0); } int bx_dbg_symbol_command(const char* filename, bx_bool global, Bit32u offset) { dbg_printf(BX_HAVE_MAP_ERR); return -1; } void bx_dbg_info_symbols_command(const char *Symbol) { dbg_printf(BX_HAVE_MAP_ERR); } int bx_dbg_lbreakpoint_symbol_command(const char *Symbol) { dbg_printf(BX_HAVE_MAP_ERR); return -1; } Bit32u bx_dbg_get_symbol_value(const char *Symbol) { return 0; } const char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base) { return 0; } #else /* if BX_HAVE_MAP == 1 */ #if BX_HAVE_MAP #include #elif BX_HAVE_MAP_H #include #endif #if BX_HAVE_SET #include #elif BX_HAVE_SET_H #include #endif struct symbol_entry_t { symbol_entry_t (Bit32u _start = 0, const char* _name = 0) { start = _start; name = _name ? strdup(_name) : 0; } ~symbol_entry_t() { if (name) free(name); } void trim_quotes(void); char* name; Bit32u start; private: symbol_entry_t(const symbol_entry_t&); // No definition void operator=(const symbol_entry_t &); // No definition }; struct lt_symbol_entry_t { bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const { return s1->start < s2->start; } }; struct lt_rsymbol_entry_t { bool operator()(const symbol_entry_t* s1, const symbol_entry_t* s2) const { return strcoll(s1->name, s2->name) < 0; } }; struct context_t { typedef std::set sym_set_t; typedef std::set rsym_set_t; typedef std::map map_t; context_t (Bit32u); ~context_t(); static context_t* get_context(Bit32u); symbol_entry_t* get_symbol_entry(Bit32u); symbol_entry_t* get_symbol_entry(const char *Symbol) const; void add_symbol(symbol_entry_t*); const sym_set_t* get_all_symbols() const {return &m_syms;} const rsym_set_t* get_all_rsymbols() const {return &m_rsyms;} friend class context_dtor_t; protected: static map_t s_map; // Forvard references (find name by address) sym_set_t m_syms; // Reverse references (find address by name) rsym_set_t m_rsyms; Bit32u m_id; }; context_t::map_t context_t::s_map; context_t::context_t (Bit32u id) { m_id = id; s_map[m_id] = this; } context_t::~context_t() { while (!m_syms.empty()) { sym_set_t::iterator it = m_syms.begin(); symbol_entry_t *sym = *it; m_syms.erase(it); delete sym; } } context_t* context_t::get_context(Bit32u i) { return s_map[i]; } symbol_entry_t* context_t::get_symbol_entry(Bit32u ip) { symbol_entry_t probe(ip, 0); // find the first symbol whose address is greater than ip. if (m_syms.empty ()) return 0; sym_set_t::iterator iter = m_syms.upper_bound(&probe); if (iter == m_syms.end()) { // No symbol found return 0; } --iter; if(iter == m_syms.end()) return 0; return *iter; } symbol_entry_t* context_t::get_symbol_entry(const char *Symbol) const { if (m_rsyms.empty()) return 0; symbol_entry_t probe(0, Symbol); rsym_set_t::const_iterator iter; iter=m_rsyms.find(&probe); if(iter==m_rsyms.end()) // No symbol found return 0; return *iter; } void context_t::add_symbol(symbol_entry_t* sym) { m_syms.insert(sym); m_rsyms.insert(sym); } void symbol_entry_t::trim_quotes(void) { size_t len = strlen(name); if (name[0] == '\"' && name[len-1] == '\"') { memmove(name, name+1, len); name[len-2] = 0; } } Bit32u bx_dbg_get_symbol_value(const char *Symbol) { context_t* cntx = context_t::get_context(0); if(!cntx) // Context not found return 0; symbol_entry_t s(0, Symbol); s.trim_quotes(); symbol_entry_t* sym=cntx->get_symbol_entry(s.name); if(!sym) // Symbol not found return 0; return sym->start; } const char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base) { static char buf[80]; // Look up this context context_t* cntx = context_t::get_context(context); if (!cntx) { // Try global context cntx = context_t::get_context(0); if (!cntx) { snprintf (buf, 80, "unk. ctxt"); return buf; } } // full linear address not only eip (for nonzero based segments) symbol_entry_t* entr = cntx->get_symbol_entry(base+eip); if (!entr) { snprintf (buf, 80, "no symbol"); return buf; } snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start); return buf; } const char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base) { static char buf[80]; // Try global context context_t* cntx = context_t::get_context(0); if (!cntx) { return 0; } // full linear address not only eip (for nonzero based segments) symbol_entry_t* entr = cntx->get_symbol_entry(base+eip); if (!entr) { return 0; } snprintf (buf, 80, "%s+%x", entr->name, (base+eip) - entr->start); return buf; } const char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs) { // in 16-bit code, the segment selector and offset are combined into a // 20-bit linear address = (segment selector<<4) + offset. eip &= 0xffff; cs &= 0xffff; return bx_dbg_symbolic_address (0, eip+(cs<<4), 0); } int bx_dbg_symbol_command(const char* filename, bx_bool global, Bit32u offset) { symbol_entry_t file(0, filename); file.trim_quotes(); // Install symbols in correct context (page table) // The file format should be // address symbol (example '00002afe _StartLoseNT') Bit32u context_id = (global) ? 0 : (BX_CPU(dbg_cpu)->cr3) >> 12; context_t* cntx = context_t::get_context(context_id); if (!cntx) { cntx = new context_t(context_id); } FILE* fp = fopen(file.name, "rt"); // 't' is need for win32, unixes simply ignore it if (!fp) { dbg_printf ("Could not open symbol file '%s'\n", file.name); return -1; } // C++/C# symbols can be long char buf[512]; int line_num = 1; while (fgets(buf, sizeof(buf), fp)) { // handle end of line (before error messages) int len = strlen(buf); bool whole_line = (buf[len - 1] == '\n'); if (whole_line) buf[len - 1] = 0; // parse char* sym_name; Bit32u addr = strtoul(buf, &sym_name, 16); if (!isspace(*sym_name)) { if (*sym_name == 0) dbg_printf("%s:%d: missing symbol name\n", file.name, line_num); else dbg_printf("%s:%d: syntax error near '%s'\n", file.name, line_num, sym_name); return -1; } ++sym_name; symbol_entry_t* sym = new symbol_entry_t(addr + offset, sym_name); cntx->add_symbol(sym); // skip the rest of long line while (!whole_line) { if (!fgets(buf, sizeof(buf), fp)) break; // actually, last line can end without newline, but then // we'll just break at the next iteration because of EOF whole_line = (buf[strlen(buf)-1] == '\n'); } ++line_num; } return 0; } // check if s1 is prefix of s2 static bool bx_dbg_strprefix(const char *s1, const char *s2) { if(!s1 || !s2) return false; size_t len=strlen(s1); if(len>strlen(s2)) return false; return strncmp(s1, s2, len)==0; } void bx_dbg_info_symbols_command(const char *Symbol) { context_t* cntx = context_t::get_context(0); if(!cntx) { dbg_printf ("Global context not available\n"); return; } if(Symbol) { const context_t::rsym_set_t* rsyms; rsyms=cntx->get_all_rsymbols(); if (rsyms->empty ()) { dbg_printf ("Symbols not loaded\n"); return; } symbol_entry_t probe(0, Symbol); // remove leading and trailing quotas probe.trim_quotes(); context_t::rsym_set_t::const_iterator iter; iter=rsyms->lower_bound(&probe); if(iter==rsyms->end() || !bx_dbg_strprefix(probe.name, (*iter)->name)) dbg_printf ("No symbols found\n"); else { for(;iter!=rsyms->end() && bx_dbg_strprefix(probe.name, (*iter)->name);++iter) { dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name); } } } else { const context_t::sym_set_t* syms; syms=cntx->get_all_symbols(); if (syms->empty ()) { dbg_printf ("Symbols not loaded\n"); return; } context_t::sym_set_t::const_iterator iter; for(iter = syms->begin();iter!=syms->end();++iter) { dbg_printf ("%08x: %s\n", (*iter)->start, (*iter)->name); } } } int bx_dbg_lbreakpoint_symbol_command(const char *symbol) { context_t* cntx = context_t::get_context(0); if(!cntx) { dbg_printf ("Global context not available\n"); return -1; } symbol_entry_t probe(0, symbol); // remove leading and trailing quotes probe.trim_quotes(); const symbol_entry_t* sym=cntx->get_symbol_entry(probe.name); if(sym) return bx_dbg_lbreakpoint_command(bkRegular, sym->start); dbg_printf ("Symbol not found\n"); return -1; } #endif #endif bochs-2.6/bx_debug/parser.h0000644000175000017500000001732312020641506015563 0ustar guillemguillem/* A Bison parser, made by GNU Bison 2.5. */ /* Bison interface for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { BX_TOKEN_8BH_REG = 258, BX_TOKEN_8BL_REG = 259, BX_TOKEN_16B_REG = 260, BX_TOKEN_32B_REG = 261, BX_TOKEN_64B_REG = 262, BX_TOKEN_CS = 263, BX_TOKEN_ES = 264, BX_TOKEN_SS = 265, BX_TOKEN_DS = 266, BX_TOKEN_FS = 267, BX_TOKEN_GS = 268, BX_TOKEN_FLAGS = 269, BX_TOKEN_ON = 270, BX_TOKEN_OFF = 271, BX_TOKEN_CONTINUE = 272, BX_TOKEN_STEPN = 273, BX_TOKEN_STEP_OVER = 274, BX_TOKEN_SET = 275, BX_TOKEN_DEBUGGER = 276, BX_TOKEN_LIST_BREAK = 277, BX_TOKEN_VBREAKPOINT = 278, BX_TOKEN_LBREAKPOINT = 279, BX_TOKEN_PBREAKPOINT = 280, BX_TOKEN_DEL_BREAKPOINT = 281, BX_TOKEN_ENABLE_BREAKPOINT = 282, BX_TOKEN_DISABLE_BREAKPOINT = 283, BX_TOKEN_INFO = 284, BX_TOKEN_QUIT = 285, BX_TOKEN_R = 286, BX_TOKEN_REGS = 287, BX_TOKEN_CPU = 288, BX_TOKEN_FPU = 289, BX_TOKEN_MMX = 290, BX_TOKEN_SSE = 291, BX_TOKEN_AVX = 292, BX_TOKEN_IDT = 293, BX_TOKEN_IVT = 294, BX_TOKEN_GDT = 295, BX_TOKEN_LDT = 296, BX_TOKEN_TSS = 297, BX_TOKEN_TAB = 298, BX_TOKEN_ALL = 299, BX_TOKEN_LINUX = 300, BX_TOKEN_DEBUG_REGS = 301, BX_TOKEN_CONTROL_REGS = 302, BX_TOKEN_SEGMENT_REGS = 303, BX_TOKEN_EXAMINE = 304, BX_TOKEN_XFORMAT = 305, BX_TOKEN_DISFORMAT = 306, BX_TOKEN_RESTORE = 307, BX_TOKEN_WRITEMEM = 308, BX_TOKEN_SETPMEM = 309, BX_TOKEN_SYMBOLNAME = 310, BX_TOKEN_QUERY = 311, BX_TOKEN_PENDING = 312, BX_TOKEN_TAKE = 313, BX_TOKEN_DMA = 314, BX_TOKEN_IRQ = 315, BX_TOKEN_HEX = 316, BX_TOKEN_DISASM = 317, BX_TOKEN_INSTRUMENT = 318, BX_TOKEN_STRING = 319, BX_TOKEN_STOP = 320, BX_TOKEN_DOIT = 321, BX_TOKEN_CRC = 322, BX_TOKEN_TRACE = 323, BX_TOKEN_TRACEREG = 324, BX_TOKEN_TRACEMEM = 325, BX_TOKEN_SWITCH_MODE = 326, BX_TOKEN_SIZE = 327, BX_TOKEN_PTIME = 328, BX_TOKEN_TIMEBP_ABSOLUTE = 329, BX_TOKEN_TIMEBP = 330, BX_TOKEN_MODEBP = 331, BX_TOKEN_VMEXITBP = 332, BX_TOKEN_PRINT_STACK = 333, BX_TOKEN_WATCH = 334, BX_TOKEN_UNWATCH = 335, BX_TOKEN_READ = 336, BX_TOKEN_WRITE = 337, BX_TOKEN_SHOW = 338, BX_TOKEN_LOAD_SYMBOLS = 339, BX_TOKEN_SYMBOLS = 340, BX_TOKEN_LIST_SYMBOLS = 341, BX_TOKEN_GLOBAL = 342, BX_TOKEN_WHERE = 343, BX_TOKEN_PRINT_STRING = 344, BX_TOKEN_NUMERIC = 345, BX_TOKEN_PAGE = 346, BX_TOKEN_HELP = 347, BX_TOKEN_CALC = 348, BX_TOKEN_VGA = 349, BX_TOKEN_DEVICE = 350, BX_TOKEN_COMMAND = 351, BX_TOKEN_GENERIC = 352, BX_TOKEN_RSHIFT = 353, BX_TOKEN_LSHIFT = 354, BX_TOKEN_REG_IP = 355, BX_TOKEN_REG_EIP = 356, BX_TOKEN_REG_RIP = 357, INDIRECT = 358, NEG = 359, NOT = 360 }; #endif /* Tokens. */ #define BX_TOKEN_8BH_REG 258 #define BX_TOKEN_8BL_REG 259 #define BX_TOKEN_16B_REG 260 #define BX_TOKEN_32B_REG 261 #define BX_TOKEN_64B_REG 262 #define BX_TOKEN_CS 263 #define BX_TOKEN_ES 264 #define BX_TOKEN_SS 265 #define BX_TOKEN_DS 266 #define BX_TOKEN_FS 267 #define BX_TOKEN_GS 268 #define BX_TOKEN_FLAGS 269 #define BX_TOKEN_ON 270 #define BX_TOKEN_OFF 271 #define BX_TOKEN_CONTINUE 272 #define BX_TOKEN_STEPN 273 #define BX_TOKEN_STEP_OVER 274 #define BX_TOKEN_SET 275 #define BX_TOKEN_DEBUGGER 276 #define BX_TOKEN_LIST_BREAK 277 #define BX_TOKEN_VBREAKPOINT 278 #define BX_TOKEN_LBREAKPOINT 279 #define BX_TOKEN_PBREAKPOINT 280 #define BX_TOKEN_DEL_BREAKPOINT 281 #define BX_TOKEN_ENABLE_BREAKPOINT 282 #define BX_TOKEN_DISABLE_BREAKPOINT 283 #define BX_TOKEN_INFO 284 #define BX_TOKEN_QUIT 285 #define BX_TOKEN_R 286 #define BX_TOKEN_REGS 287 #define BX_TOKEN_CPU 288 #define BX_TOKEN_FPU 289 #define BX_TOKEN_MMX 290 #define BX_TOKEN_SSE 291 #define BX_TOKEN_AVX 292 #define BX_TOKEN_IDT 293 #define BX_TOKEN_IVT 294 #define BX_TOKEN_GDT 295 #define BX_TOKEN_LDT 296 #define BX_TOKEN_TSS 297 #define BX_TOKEN_TAB 298 #define BX_TOKEN_ALL 299 #define BX_TOKEN_LINUX 300 #define BX_TOKEN_DEBUG_REGS 301 #define BX_TOKEN_CONTROL_REGS 302 #define BX_TOKEN_SEGMENT_REGS 303 #define BX_TOKEN_EXAMINE 304 #define BX_TOKEN_XFORMAT 305 #define BX_TOKEN_DISFORMAT 306 #define BX_TOKEN_RESTORE 307 #define BX_TOKEN_WRITEMEM 308 #define BX_TOKEN_SETPMEM 309 #define BX_TOKEN_SYMBOLNAME 310 #define BX_TOKEN_QUERY 311 #define BX_TOKEN_PENDING 312 #define BX_TOKEN_TAKE 313 #define BX_TOKEN_DMA 314 #define BX_TOKEN_IRQ 315 #define BX_TOKEN_HEX 316 #define BX_TOKEN_DISASM 317 #define BX_TOKEN_INSTRUMENT 318 #define BX_TOKEN_STRING 319 #define BX_TOKEN_STOP 320 #define BX_TOKEN_DOIT 321 #define BX_TOKEN_CRC 322 #define BX_TOKEN_TRACE 323 #define BX_TOKEN_TRACEREG 324 #define BX_TOKEN_TRACEMEM 325 #define BX_TOKEN_SWITCH_MODE 326 #define BX_TOKEN_SIZE 327 #define BX_TOKEN_PTIME 328 #define BX_TOKEN_TIMEBP_ABSOLUTE 329 #define BX_TOKEN_TIMEBP 330 #define BX_TOKEN_MODEBP 331 #define BX_TOKEN_VMEXITBP 332 #define BX_TOKEN_PRINT_STACK 333 #define BX_TOKEN_WATCH 334 #define BX_TOKEN_UNWATCH 335 #define BX_TOKEN_READ 336 #define BX_TOKEN_WRITE 337 #define BX_TOKEN_SHOW 338 #define BX_TOKEN_LOAD_SYMBOLS 339 #define BX_TOKEN_SYMBOLS 340 #define BX_TOKEN_LIST_SYMBOLS 341 #define BX_TOKEN_GLOBAL 342 #define BX_TOKEN_WHERE 343 #define BX_TOKEN_PRINT_STRING 344 #define BX_TOKEN_NUMERIC 345 #define BX_TOKEN_PAGE 346 #define BX_TOKEN_HELP 347 #define BX_TOKEN_CALC 348 #define BX_TOKEN_VGA 349 #define BX_TOKEN_DEVICE 350 #define BX_TOKEN_COMMAND 351 #define BX_TOKEN_GENERIC 352 #define BX_TOKEN_RSHIFT 353 #define BX_TOKEN_LSHIFT 354 #define BX_TOKEN_REG_IP 355 #define BX_TOKEN_REG_EIP 356 #define BX_TOKEN_REG_RIP 357 #define INDIRECT 358 #define NEG 359 #define NOT 360 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 2068 of yacc.c */ #line 13 "parser.y" char *sval; Bit64u uval; bx_bool bval; /* Line 2068 of yacc.c */ #line 268 "y.tab.h" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif extern YYSTYPE bxlval; bochs-2.6/bx_debug/lexer.c0000644000175000017500000034112012020641506015374 0ustar guillemguillem #line 3 "" #define YY_INT_ALIGNED short int /* A lexical scanner generated by flex */ #define yy_create_buffer bx_create_buffer #define yy_delete_buffer bx_delete_buffer #define yy_flex_debug bx_flex_debug #define yy_init_buffer bx_init_buffer #define yy_flush_buffer bx_flush_buffer #define yy_load_buffer_state bx_load_buffer_state #define yy_switch_to_buffer bx_switch_to_buffer #define yyin bxin #define yyleng bxleng #define yylex bxlex #define yylineno bxlineno #define yyout bxout #define yyrestart bxrestart #define yytext bxtext #define yywrap bxwrap #define yyalloc bxalloc #define yyrealloc bxrealloc #define yyfree bxfree #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #define YY_FLEX_SUBMINOR_VERSION 35 #if YY_FLEX_SUBMINOR_VERSION > 0 #define FLEX_BETA #endif /* First, we deal with platform-specific or compiler-specific issues. */ /* begin standard C headers. */ #include #include #include #include /* end standard C headers. */ /* flex integer type definitions */ #ifndef FLEXINT_H #define FLEXINT_H /* C99 systems have . Non-C99 systems may or may not. */ #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, * if you want the limit (max/min) macros for int types. */ #ifndef __STDC_LIMIT_MACROS #define __STDC_LIMIT_MACROS 1 #endif #include typedef int8_t flex_int8_t; typedef uint8_t flex_uint8_t; typedef int16_t flex_int16_t; typedef uint16_t flex_uint16_t; typedef int32_t flex_int32_t; typedef uint32_t flex_uint32_t; #else typedef signed char flex_int8_t; typedef short int flex_int16_t; typedef int flex_int32_t; typedef unsigned char flex_uint8_t; typedef unsigned short int flex_uint16_t; typedef unsigned int flex_uint32_t; #endif /* ! C99 */ /* Limits of integral types. */ #ifndef INT8_MIN #define INT8_MIN (-128) #endif #ifndef INT16_MIN #define INT16_MIN (-32767-1) #endif #ifndef INT32_MIN #define INT32_MIN (-2147483647-1) #endif #ifndef INT8_MAX #define INT8_MAX (127) #endif #ifndef INT16_MAX #define INT16_MAX (32767) #endif #ifndef INT32_MAX #define INT32_MAX (2147483647) #endif #ifndef UINT8_MAX #define UINT8_MAX (255U) #endif #ifndef UINT16_MAX #define UINT16_MAX (65535U) #endif #ifndef UINT32_MAX #define UINT32_MAX (4294967295U) #endif #endif /* ! FLEXINT_H */ #ifdef __cplusplus /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ /* C99 requires __STDC__ to be defined as 1. */ #if defined (__STDC__) #define YY_USE_CONST #endif /* defined (__STDC__) */ #endif /* ! __cplusplus */ #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN (yy_start) = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START (((yy_start) - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE bxrestart(bxin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 #endif /* The state buf must be large enough to hold one state per character in the main buffer. */ #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) #ifndef YY_TYPEDEF_YY_BUFFER_STATE #define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; #endif extern int bxleng; extern FILE *bxin, *bxout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 #define YY_LESS_LINENO(n) /* Return all but the first "n" matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up bxtext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ *yy_cp = (yy_hold_char); \ YY_RESTORE_YY_MORE_OFFSET \ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up bxtext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, (yytext_ptr) ) #ifndef YY_TYPEDEF_YY_SIZE_T #define YY_TYPEDEF_YY_SIZE_T typedef size_t yy_size_t; #endif #ifndef YY_STRUCT_YY_BUFFER_STATE #define YY_STRUCT_YY_BUFFER_STATE struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; int yy_bs_lineno; /**< The line count. */ int yy_bs_column; /**< The column count. */ /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via bxrestart()), so that the user can continue scanning by * just pointing bxin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; #endif /* !YY_STRUCT_YY_BUFFER_STATE */ /* Stack of input buffers. */ static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". * * Returns the top of the stack, or NULL. */ #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ : NULL) /* Same as previous macro, but useful when we know that the buffer stack is not * NULL or when we need an lvalue. For internal use only. */ #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when bxtext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int bxleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 0; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow bxwrap()'s to do buffer switches * instead of setting up a fresh bxin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void bxrestart (FILE *input_file ); void bx_switch_to_buffer (YY_BUFFER_STATE new_buffer ); YY_BUFFER_STATE bx_create_buffer (FILE *file,int size ); void bx_delete_buffer (YY_BUFFER_STATE b ); void bx_flush_buffer (YY_BUFFER_STATE b ); void bxpush_buffer_state (YY_BUFFER_STATE new_buffer ); void bxpop_buffer_state (void ); static void bxensure_buffer_stack (void ); static void bx_load_buffer_state (void ); static void bx_init_buffer (YY_BUFFER_STATE b,FILE *file ); #define YY_FLUSH_BUFFER bx_flush_buffer(YY_CURRENT_BUFFER ) YY_BUFFER_STATE bx_scan_buffer (char *base,yy_size_t size ); YY_BUFFER_STATE bx_scan_string (yyconst char *yy_str ); YY_BUFFER_STATE bx_scan_bytes (yyconst char *bytes,int len ); void *bxalloc (yy_size_t ); void *bxrealloc (void *,yy_size_t ); void bxfree (void * ); #define yy_new_buffer bx_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! YY_CURRENT_BUFFER ){ \ bxensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ bx_create_buffer(bxin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! YY_CURRENT_BUFFER ){\ bxensure_buffer_stack (); \ YY_CURRENT_BUFFER_LVALUE = \ bx_create_buffer(bxin,YY_BUF_SIZE ); \ } \ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) /* Begin user sect3 */ typedef unsigned char YY_CHAR; FILE *bxin = (FILE *) 0, *bxout = (FILE *) 0; typedef int yy_state_type; extern int bxlineno; int bxlineno = 1; extern char *bxtext; #define yytext_ptr bxtext static yy_state_type yy_get_previous_state (void ); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); static int yy_get_next_buffer (void ); static void yy_fatal_error (yyconst char msg[] ); /* Done after the current pattern has been matched and before the * corresponding action - sets up bxtext. */ #define YY_DO_BEFORE_ACTION \ (yytext_ptr) = yy_bp; \ bxleng = (size_t) (yy_cp - yy_bp); \ (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; #define YY_NUM_RULES 201 #define YY_END_OF_BUFFER 202 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info { flex_int32_t yy_verify; flex_int32_t yy_nxt; }; static yyconst flex_int16_t yy_accept[441] = { 0, 0, 0, 0, 0, 0, 0, 202, 199, 1, 197, 184, 199, 198, 199, 181, 199, 186, 187, 177, 175, 176, 178, 192, 192, 196, 199, 199, 170, 185, 195, 183, 193, 18, 6, 43, 193, 193, 193, 169, 193, 193, 193, 193, 12, 193, 13, 48, 26, 10, 193, 59, 193, 79, 49, 193, 182, 200, 1, 200, 196, 200, 1, 0, 189, 0, 198, 194, 0, 188, 0, 193, 191, 192, 0, 180, 179, 195, 193, 107, 91, 111, 108, 92, 117, 193, 112, 193, 109, 93, 193, 193, 21, 162, 113, 193, 110, 116, 94, 193, 193, 23, 165, 114, 193, 193, 193, 193, 193, 193, 163, 193, 193, 29, 166, 193, 193, 167, 193, 193, 193, 159, 193, 193, 16, 193, 193, 193, 193, 193, 193, 3, 193, 18, 193, 193, 193, 193, 195, 151, 152, 193, 193, 193, 193, 193, 193, 193, 71, 193, 193, 115, 193, 118, 193, 164, 193, 193, 193, 193, 193, 193, 193, 15, 193, 193, 193, 193, 193, 193, 50, 193, 172, 173, 174, 194, 190, 90, 193, 45, 44, 98, 193, 193, 193, 33, 5, 193, 42, 193, 96, 193, 57, 193, 193, 127, 133, 128, 129, 132, 130, 193, 160, 131, 134, 193, 193, 29, 36, 193, 193, 61, 34, 193, 193, 58, 35, 193, 193, 37, 193, 32, 193, 193, 4, 193, 193, 193, 193, 193, 193, 193, 153, 154, 155, 156, 157, 158, 99, 135, 119, 100, 136, 120, 143, 150, 144, 145, 148, 146, 193, 27, 193, 161, 147, 149, 72, 2, 193, 95, 193, 193, 97, 193, 30, 193, 193, 193, 193, 39, 193, 193, 38, 193, 193, 88, 193, 193, 193, 193, 31, 193, 193, 171, 7, 22, 193, 193, 193, 64, 24, 193, 47, 193, 193, 169, 20, 193, 193, 193, 193, 193, 11, 87, 193, 193, 193, 193, 193, 46, 101, 137, 121, 102, 138, 122, 103, 139, 123, 104, 140, 124, 105, 141, 125, 106, 142, 126, 78, 193, 27, 193, 193, 80, 69, 193, 25, 9, 63, 193, 193, 56, 193, 193, 193, 193, 193, 193, 193, 14, 17, 193, 193, 193, 193, 193, 168, 193, 193, 193, 81, 40, 193, 193, 193, 193, 70, 54, 193, 193, 193, 83, 193, 193, 65, 193, 193, 193, 76, 85, 79, 193, 41, 89, 60, 84, 193, 16, 73, 19, 193, 193, 193, 193, 193, 193, 193, 193, 193, 15, 193, 193, 193, 193, 55, 193, 193, 51, 53, 193, 82, 193, 193, 77, 193, 193, 8, 193, 193, 193, 193, 193, 193, 74, 52, 193, 193, 193, 28, 193, 67, 66, 62, 193, 193, 193, 75, 193, 68, 86, 0 } ; static yyconst flex_int32_t yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 5, 6, 7, 1, 8, 9, 10, 11, 12, 13, 1, 14, 1, 15, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 1, 25, 26, 1, 27, 28, 29, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 1, 32, 1, 33, 31, 1, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 1, 60, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst flex_int32_t yy_meta[61] = { 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 5, 6, 1, 1, 7, 8, 8, 8, 7, 7, 9, 9, 9, 10, 10, 10, 9, 10, 9, 10, 10, 10, 9, 9, 9, 10, 9, 11, 10, 10, 1 } ; static yyconst flex_int16_t yy_base[455] = { 0, 0, 0, 59, 61, 63, 65, 200, 3062, 197, 3062, 3062, 64, 0, 0, 3062, 61, 3062, 3062, 3062, 3062, 0, 3062, 48, 0, 3062, 170, 168, 3062, 3062, 0, 3062, 92, 136, 83, 156, 180, 40, 127, 185, 198, 199, 217, 214, 92, 234, 241, 250, 289, 309, 110, 281, 334, 341, 344, 351, 3062, 3062, 181, 391, 3062, 0, 180, 68, 3062, 0, 0, 0, 66, 3062, 0, 0, 79, 0, 0, 3062, 3062, 0, 308, 387, 405, 408, 419, 430, 445, 135, 282, 444, 458, 459, 474, 477, 484, 504, 509, 503, 512, 523, 528, 548, 553, 558, 578, 583, 581, 592, 599, 610, 613, 624, 635, 646, 655, 664, 675, 685, 695, 706, 704, 716, 736, 728, 742, 748, 756, 762, 761, 776, 781, 790, 799, 804, 817, 818, 833, 834, 849, 859, 400, 64, 90, 854, 868, 873, 886, 898, 903, 914, 923, 932, 943, 941, 960, 963, 972, 981, 992, 1004, 1013, 1018, 1038, 1043, 1048, 1068, 1073, 1078, 1098, 1103, 1108, 1128, 1133, 1142, 0, 0, 0, 0, 0, 1156, 1162, 1167, 1187, 1192, 1197, 1217, 1222, 1227, 1247, 1252, 1259, 1273, 1279, 1284, 1293, 1304, 1313, 1324, 1333, 1338, 1344, 1358, 1364, 1369, 1378, 1389, 1398, 1403, 1410, 1424, 1430, 1435, 1433, 1444, 1451, 1458, 1476, 1482, 1487, 1496, 1507, 1516, 1521, 1528, 1542, 1548, 1553, 1562, 1573, 1161, 1565, 1572, 1585, 1595, 154, 155, 247, 258, 263, 273, 0, 0, 0, 0, 0, 0, 1603, 1609, 1615, 1623, 1629, 1635, 1628, 1647, 1657, 1666, 1671, 1677, 1691, 1684, 1699, 1710, 1718, 1728, 1738, 1748, 1758, 1753, 1766, 1772, 1784, 1792, 1798, 1804, 1812, 1818, 1824, 1832, 1823, 1837, 1846, 1855, 1864, 1875, 1885, 1896, 1906, 1916, 1926, 1936, 1946, 1956, 1966, 1976, 1986, 1996, 2006, 2016, 2026, 2036, 2046, 2056, 2047, 2076, 2081, 2086, 2106, 2111, 2116, 2136, 2141, 2147, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2167, 2172, 2177, 2197, 2203, 2208, 2217, 2228, 2237, 2242, 2248, 2262, 2268, 2273, 2293, 2298, 2303, 2323, 2139, 2328, 2333, 2353, 2358, 1867, 2363, 2383, 2389, 2394, 2403, 2408, 2417, 2428, 2435, 2442, 2449, 2460, 1888, 2475, 2476, 2491, 2481, 2501, 2509, 2515, 2510, 2524, 2531, 2538, 2549, 2567, 2573, 2578, 2587, 2601, 2607, 2612, 2632, 2637, 2643, 2657, 2663, 2668, 2677, 128, 2688, 2697, 2708, 2722, 2717, 31, 2731, 2736, 2756, 2761, 2766, 2786, 2791, 122, 2796, 2816, 2821, 128, 2826, 133, 127, 2846, 2837, 2844, 2851, 2716, 53, 2866, 103, 96, 98, 2873, 2882, 2892, 90, 79, 2900, 82, 0, 0, 2906, 74, 60, 57, 0, 54, 0, 0, 3062, 2959, 2970, 2981, 2988, 2999, 3008, 3016, 79, 3024, 3033, 75, 3041, 3049, 3050 } ; static yyconst flex_int16_t yy_def[455] = { 0, 440, 1, 441, 441, 441, 441, 440, 440, 440, 440, 440, 442, 443, 444, 440, 445, 440, 440, 440, 440, 446, 440, 447, 448, 440, 440, 440, 440, 440, 449, 440, 450, 450, 33, 33, 33, 33, 33, 33, 33, 33, 40, 40, 40, 40, 40, 40, 46, 46, 46, 40, 46, 46, 40, 40, 440, 440, 440, 440, 440, 451, 440, 442, 440, 442, 443, 452, 445, 440, 445, 446, 447, 448, 453, 440, 440, 449, 40, 40, 33, 33, 33, 33, 33, 46, 46, 33, 33, 33, 40, 40, 46, 46, 46, 40, 40, 33, 33, 46, 46, 46, 46, 46, 33, 33, 33, 33, 33, 33, 33, 33, 46, 46, 46, 46, 46, 46, 33, 46, 46, 46, 46, 46, 46, 46, 40, 33, 40, 33, 33, 33, 33, 33, 40, 40, 40, 46, 449, 449, 449, 33, 33, 33, 33, 46, 33, 33, 46, 46, 46, 33, 33, 33, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 59, 454, 451, 452, 453, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 33, 33, 33, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 40, 40, 40, 40, 46, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 46, 46, 46, 46, 46, 46, 40, 40, 46, 46, 46, 46, 46, 40, 40, 40, 46, 46, 46, 46, 46, 40, 40, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 33, 33, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 46, 46, 46, 46, 46, 46, 46, 46, 46, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 33, 46, 46, 46, 46, 40, 46, 46, 46, 46, 46, 33, 33, 33, 33, 33, 33, 33, 40, 40, 40, 40, 46, 46, 46, 46, 33, 33, 33, 33, 33, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 446, 46, 46, 46, 46, 46, 446, 33, 33, 46, 46, 46, 46, 46, 446, 46, 46, 46, 446, 46, 446, 446, 46, 33, 33, 33, 40, 446, 40, 446, 446, 446, 40, 40, 46, 446, 446, 46, 446, 446, 446, 46, 446, 446, 446, 446, 446, 446, 446, 0, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440 } ; static yyconst flex_int16_t yy_nxt[3123] = { 0, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 26, 27, 28, 29, 30, 30, 8, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 41, 56, 58, 10, 58, 10, 58, 10, 58, 10, 64, 69, 73, 73, 64, 59, 69, 59, 411, 61, 174, 61, 78, 412, 73, 60, 112, 60, 426, 60, 113, 60, 78, 114, 70, 439, 438, 65, 78, 70, 238, 65, 239, 73, 73, 427, 74, 71, 437, 77, 77, 77, 77, 77, 77, 77, 77, 77, 87, 436, 435, 240, 434, 77, 77, 88, 241, 433, 242, 89, 78, 129, 90, 91, 79, 92, 93, 440, 80, 431, 78, 94, 78, 430, 78, 159, 78, 243, 78, 78, 81, 71, 429, 77, 77, 77, 77, 77, 77, 77, 77, 77, 160, 161, 78, 115, 422, 77, 77, 78, 78, 78, 421, 116, 182, 420, 418, 78, 82, 78, 117, 405, 83, 62, 62, 78, 84, 78, 85, 78, 310, 313, 311, 314, 86, 95, 76, 75, 96, 97, 62, 440, 98, 99, 440, 100, 78, 440, 101, 102, 440, 312, 315, 440, 103, 104, 105, 106, 107, 440, 108, 440, 78, 109, 118, 440, 78, 78, 440, 440, 78, 78, 78, 110, 440, 78, 119, 78, 111, 440, 78, 78, 440, 78, 78, 78, 120, 440, 121, 78, 122, 78, 78, 124, 123, 125, 78, 78, 440, 440, 126, 127, 78, 128, 78, 78, 78, 78, 440, 78, 78, 440, 78, 78, 130, 440, 132, 133, 440, 78, 134, 440, 131, 316, 78, 317, 78, 440, 78, 78, 78, 78, 440, 135, 319, 136, 320, 78, 78, 322, 78, 323, 78, 440, 318, 137, 78, 138, 440, 325, 440, 326, 440, 139, 140, 321, 440, 78, 78, 78, 324, 78, 440, 440, 141, 142, 143, 144, 145, 162, 327, 78, 146, 78, 78, 440, 78, 78, 440, 440, 440, 78, 147, 78, 78, 148, 78, 440, 149, 440, 440, 150, 151, 440, 440, 152, 78, 440, 78, 153, 78, 154, 155, 156, 78, 440, 157, 440, 158, 78, 163, 440, 440, 78, 440, 164, 166, 78, 440, 440, 78, 165, 78, 167, 440, 440, 78, 440, 78, 78, 440, 169, 78, 168, 170, 78, 78, 440, 171, 78, 78, 78, 440, 78, 440, 440, 440, 78, 172, 172, 172, 172, 172, 172, 172, 172, 172, 232, 233, 234, 235, 236, 237, 440, 440, 78, 440, 173, 173, 173, 440, 440, 173, 173, 173, 78, 440, 78, 173, 78, 173, 440, 440, 78, 173, 173, 173, 78, 173, 173, 78, 177, 440, 440, 78, 78, 440, 78, 78, 440, 78, 78, 440, 78, 440, 78, 78, 440, 440, 78, 440, 78, 78, 178, 440, 440, 78, 78, 440, 440, 78, 440, 78, 179, 180, 440, 78, 78, 78, 440, 183, 181, 440, 440, 78, 78, 78, 78, 440, 440, 78, 78, 78, 78, 78, 78, 440, 440, 78, 78, 78, 78, 78, 440, 440, 78, 78, 78, 440, 78, 78, 186, 184, 187, 78, 78, 78, 78, 440, 78, 78, 440, 185, 78, 440, 440, 78, 440, 78, 78, 78, 78, 440, 78, 78, 78, 440, 440, 78, 188, 78, 78, 440, 78, 440, 78, 78, 440, 78, 189, 78, 78, 78, 78, 78, 78, 440, 440, 78, 190, 78, 440, 440, 78, 78, 78, 191, 440, 78, 440, 78, 78, 440, 192, 78, 440, 78, 78, 78, 78, 440, 440, 78, 78, 78, 440, 193, 194, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 78, 440, 440, 440, 78, 440, 440, 78, 78, 78, 78, 78, 78, 440, 78, 78, 195, 440, 78, 196, 440, 78, 78, 440, 440, 440, 78, 197, 78, 78, 199, 440, 78, 78, 198, 440, 201, 78, 440, 78, 78, 440, 78, 78, 440, 200, 440, 78, 78, 440, 440, 202, 440, 78, 78, 203, 440, 440, 78, 78, 440, 440, 204, 440, 78, 78, 205, 206, 78, 78, 78, 78, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 207, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 208, 440, 78, 78, 440, 209, 78, 78, 78, 440, 78, 210, 78, 78, 440, 78, 78, 78, 440, 78, 440, 78, 440, 211, 78, 78, 440, 440, 78, 78, 440, 212, 78, 78, 440, 440, 78, 213, 78, 78, 440, 78, 78, 78, 78, 78, 440, 440, 78, 78, 214, 78, 78, 78, 215, 78, 78, 78, 78, 78, 78, 78, 78, 216, 440, 440, 440, 440, 440, 217, 220, 78, 78, 440, 78, 78, 218, 219, 78, 78, 222, 440, 440, 78, 440, 440, 440, 78, 440, 78, 78, 440, 78, 78, 78, 221, 440, 78, 78, 440, 224, 78, 78, 78, 440, 440, 78, 78, 440, 223, 78, 78, 78, 440, 440, 78, 440, 78, 78, 225, 78, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 226, 78, 78, 440, 440, 78, 78, 228, 440, 440, 440, 227, 78, 78, 78, 78, 78, 78, 440, 78, 78, 440, 229, 440, 78, 78, 78, 78, 230, 78, 78, 78, 231, 440, 78, 78, 78, 440, 440, 440, 78, 78, 244, 78, 78, 78, 440, 440, 245, 78, 78, 440, 440, 78, 440, 78, 246, 440, 78, 248, 440, 247, 78, 250, 78, 440, 78, 78, 78, 251, 440, 440, 440, 440, 249, 78, 440, 440, 440, 78, 78, 252, 78, 253, 440, 78, 78, 254, 256, 78, 78, 78, 78, 440, 255, 440, 78, 78, 78, 440, 440, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 257, 259, 440, 440, 440, 78, 258, 78, 440, 78, 440, 78, 440, 78, 440, 260, 78, 261, 440, 78, 78, 78, 78, 262, 78, 263, 78, 78, 440, 78, 78, 78, 78, 440, 264, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 265, 440, 78, 440, 78, 440, 440, 440, 78, 78, 266, 440, 78, 78, 440, 78, 267, 78, 78, 440, 440, 78, 78, 269, 440, 78, 78, 78, 440, 268, 440, 440, 270, 440, 78, 440, 78, 440, 440, 78, 440, 78, 271, 78, 440, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 272, 78, 440, 440, 78, 440, 78, 78, 78, 273, 440, 78, 275, 78, 440, 440, 78, 78, 78, 440, 440, 276, 440, 440, 274, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 278, 78, 78, 440, 440, 78, 440, 440, 78, 279, 277, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 440, 264, 440, 78, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 280, 440, 78, 78, 440, 78, 78, 78, 78, 78, 305, 440, 78, 78, 78, 440, 440, 78, 440, 78, 78, 78, 78, 440, 78, 78, 281, 78, 78, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 282, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 283, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 284, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 285, 78, 78, 440, 440, 286, 78, 440, 78, 440, 440, 78, 440, 78, 440, 78, 78, 440, 78, 78, 78, 78, 78, 287, 440, 78, 288, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 290, 440, 78, 440, 289, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 78, 78, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 78, 78, 78, 78, 78, 440, 440, 78, 291, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 78, 78, 78, 440, 78, 78, 440, 440, 78, 78, 293, 78, 440, 440, 78, 440, 292, 440, 78, 78, 440, 78, 78, 78, 78, 78, 440, 440, 78, 78, 294, 440, 440, 78, 78, 78, 440, 78, 78, 440, 440, 78, 295, 78, 78, 78, 78, 440, 78, 78, 78, 440, 78, 78, 440, 78, 78, 440, 440, 78, 78, 78, 78, 78, 440, 440, 296, 78, 78, 78, 78, 78, 440, 440, 78, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 297, 78, 78, 440, 78, 298, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 78, 78, 78, 440, 78, 78, 440, 299, 78, 78, 440, 78, 440, 440, 78, 440, 78, 300, 78, 78, 440, 78, 301, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 78, 303, 302, 78, 440, 78, 440, 78, 78, 78, 78, 440, 304, 306, 78, 78, 78, 78, 440, 307, 78, 78, 78, 78, 78, 78, 440, 78, 78, 440, 78, 78, 440, 78, 78, 78, 440, 308, 78, 78, 440, 78, 78, 440, 78, 78, 440, 78, 78, 309, 78, 78, 440, 440, 78, 78, 440, 78, 78, 78, 440, 78, 78, 78, 78, 78, 328, 78, 78, 78, 78, 78, 440, 440, 78, 78, 78, 78, 78, 440, 78, 78, 440, 78, 78, 78, 440, 78, 440, 78, 329, 440, 78, 78, 440, 78, 78, 78, 440, 78, 330, 78, 78, 78, 440, 78, 78, 78, 440, 78, 78, 331, 78, 78, 440, 440, 78, 440, 78, 440, 78, 440, 78, 78, 440, 78, 78, 78, 440, 78, 78, 78, 78, 440, 332, 440, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 78, 440, 78, 78, 78, 333, 334, 78, 440, 78, 440, 78, 78, 78, 440, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 335, 78, 78, 78, 440, 440, 78, 440, 336, 78, 78, 78, 78, 78, 440, 440, 78, 440, 440, 78, 78, 78, 337, 78, 78, 440, 78, 78, 78, 78, 78, 78, 440, 78, 440, 338, 440, 78, 78, 340, 440, 78, 78, 78, 440, 339, 78, 78, 440, 440, 78, 440, 78, 78, 440, 78, 341, 78, 78, 78, 342, 440, 78, 78, 440, 78, 78, 78, 440, 78, 78, 78, 343, 78, 440, 78, 78, 78, 78, 78, 440, 440, 344, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 346, 78, 78, 440, 78, 78, 440, 345, 440, 78, 78, 440, 78, 78, 78, 78, 78, 78, 78, 440, 78, 78, 78, 440, 347, 78, 78, 440, 440, 78, 78, 78, 440, 78, 440, 348, 78, 78, 440, 440, 78, 381, 78, 78, 78, 78, 78, 78, 440, 78, 78, 440, 78, 78, 440, 349, 350, 78, 78, 440, 440, 78, 390, 78, 78, 78, 78, 78, 78, 440, 78, 78, 440, 440, 78, 351, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 353, 440, 78, 440, 440, 78, 440, 352, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 354, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 355, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 357, 78, 440, 440, 78, 440, 440, 78, 356, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 359, 78, 440, 440, 78, 440, 440, 358, 78, 78, 78, 78, 78, 440, 78, 440, 78, 78, 78, 78, 440, 440, 360, 440, 361, 440, 440, 78, 440, 78, 78, 362, 440, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 363, 78, 440, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 364, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 365, 78, 78, 440, 440, 366, 78, 78, 440, 440, 78, 378, 78, 78, 440, 78, 78, 440, 78, 78, 78, 78, 440, 78, 440, 78, 440, 78, 440, 78, 367, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 368, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 78, 440, 440, 78, 78, 78, 440, 369, 78, 440, 78, 370, 78, 78, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 78, 78, 371, 78, 78, 440, 440, 78, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 372, 78, 78, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 373, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 374, 78, 78, 440, 440, 78, 376, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 375, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 377, 379, 78, 78, 440, 440, 380, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 382, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 383, 440, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 384, 78, 78, 78, 440, 78, 78, 78, 440, 440, 78, 356, 78, 440, 78, 440, 440, 440, 385, 78, 440, 78, 78, 78, 78, 440, 440, 78, 440, 440, 78, 78, 440, 78, 78, 440, 386, 387, 78, 78, 440, 78, 78, 440, 78, 78, 440, 440, 78, 78, 78, 78, 78, 440, 391, 78, 78, 78, 78, 78, 440, 440, 440, 388, 78, 78, 78, 440, 440, 389, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 78, 78, 78, 440, 78, 440, 440, 78, 78, 78, 78, 78, 78, 78, 440, 78, 78, 78, 440, 392, 78, 78, 440, 78, 78, 78, 440, 78, 78, 78, 397, 78, 394, 440, 78, 78, 395, 393, 78, 78, 78, 440, 440, 440, 78, 78, 78, 78, 440, 440, 78, 78, 78, 78, 396, 440, 440, 78, 78, 398, 78, 78, 440, 440, 78, 78, 78, 78, 78, 440, 440, 440, 78, 78, 78, 78, 440, 440, 399, 78, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 400, 78, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 401, 440, 78, 78, 440, 78, 78, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 402, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 78, 440, 440, 78, 440, 78, 440, 78, 440, 440, 78, 403, 78, 78, 78, 440, 78, 78, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 440, 78, 78, 78, 404, 440, 78, 440, 78, 78, 78, 440, 440, 406, 440, 78, 440, 78, 78, 78, 440, 440, 407, 409, 440, 440, 78, 440, 78, 78, 78, 440, 440, 78, 440, 78, 440, 78, 78, 78, 78, 408, 78, 78, 78, 440, 78, 78, 78, 440, 425, 440, 78, 440, 78, 78, 410, 78, 78, 413, 78, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 78, 78, 440, 78, 414, 440, 78, 78, 78, 78, 440, 440, 415, 78, 78, 440, 440, 416, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 78, 78, 440, 440, 417, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 419, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 78, 78, 440, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 440, 78, 78, 78, 78, 78, 78, 440, 78, 78, 423, 440, 78, 78, 424, 440, 78, 78, 78, 78, 78, 78, 440, 78, 78, 78, 78, 78, 440, 440, 440, 440, 78, 440, 78, 440, 440, 78, 440, 78, 440, 78, 428, 78, 78, 78, 78, 440, 78, 440, 78, 78, 78, 78, 78, 78, 440, 78, 78, 78, 440, 78, 78, 440, 78, 78, 440, 78, 78, 432, 440, 440, 440, 440, 440, 78, 440, 78, 440, 440, 440, 78, 440, 78, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 63, 440, 63, 63, 63, 63, 63, 63, 63, 63, 63, 66, 440, 66, 66, 66, 66, 66, 66, 66, 66, 66, 67, 67, 67, 67, 67, 67, 67, 68, 440, 68, 68, 68, 68, 68, 68, 68, 68, 68, 71, 440, 440, 440, 71, 71, 71, 71, 71, 72, 440, 440, 440, 440, 440, 440, 72, 77, 77, 77, 77, 77, 77, 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 175, 175, 175, 175, 175, 175, 175, 175, 176, 176, 440, 176, 176, 173, 173, 440, 173, 7, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440 } ; static yyconst flex_int16_t yy_chk[3123] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 5, 5, 6, 6, 12, 16, 23, 23, 63, 3, 68, 4, 397, 5, 451, 6, 37, 397, 448, 3, 37, 4, 418, 5, 37, 6, 37, 37, 16, 437, 435, 12, 37, 68, 139, 63, 139, 72, 72, 418, 23, 32, 434, 32, 32, 32, 32, 32, 32, 32, 32, 32, 34, 433, 429, 139, 427, 32, 32, 34, 140, 426, 140, 34, 44, 44, 34, 34, 32, 34, 34, 72, 32, 422, 44, 34, 44, 421, 44, 50, 50, 140, 44, 50, 32, 33, 420, 33, 33, 33, 33, 33, 33, 33, 33, 33, 50, 50, 50, 38, 412, 33, 33, 38, 85, 85, 411, 38, 85, 409, 405, 38, 33, 38, 38, 391, 33, 62, 58, 38, 33, 85, 33, 85, 232, 233, 232, 233, 33, 35, 27, 26, 35, 35, 9, 7, 35, 35, 0, 35, 35, 0, 35, 35, 0, 232, 233, 0, 35, 36, 36, 36, 36, 0, 36, 0, 36, 36, 39, 0, 36, 39, 0, 0, 36, 39, 36, 36, 0, 39, 40, 39, 36, 0, 40, 41, 0, 39, 40, 41, 40, 0, 40, 41, 40, 41, 43, 42, 40, 42, 40, 41, 0, 0, 42, 43, 43, 43, 43, 42, 43, 42, 0, 42, 43, 0, 45, 42, 45, 0, 46, 46, 0, 46, 46, 0, 45, 234, 45, 234, 45, 0, 47, 46, 45, 46, 0, 46, 235, 46, 235, 46, 47, 236, 47, 236, 47, 0, 234, 47, 47, 48, 0, 237, 0, 237, 0, 48, 48, 235, 0, 86, 86, 51, 236, 86, 0, 0, 48, 48, 48, 48, 48, 51, 237, 51, 48, 51, 86, 0, 86, 51, 0, 0, 0, 48, 48, 48, 49, 49, 78, 0, 49, 0, 0, 49, 49, 0, 0, 49, 78, 0, 78, 49, 78, 49, 49, 49, 78, 0, 49, 0, 49, 52, 52, 0, 0, 52, 0, 52, 53, 53, 0, 0, 53, 52, 54, 53, 0, 0, 52, 0, 52, 55, 0, 54, 54, 53, 54, 53, 54, 0, 55, 55, 54, 55, 0, 55, 0, 0, 0, 55, 59, 59, 59, 59, 59, 59, 59, 59, 59, 138, 138, 138, 138, 138, 138, 0, 0, 79, 0, 59, 59, 59, 0, 0, 59, 59, 59, 79, 0, 79, 59, 79, 59, 0, 0, 79, 59, 59, 59, 80, 59, 59, 81, 80, 0, 0, 81, 80, 0, 80, 81, 0, 81, 82, 0, 80, 0, 82, 81, 0, 0, 82, 0, 82, 83, 83, 0, 0, 83, 82, 0, 0, 83, 0, 83, 84, 84, 0, 87, 84, 83, 0, 87, 84, 0, 0, 87, 84, 87, 84, 0, 0, 88, 89, 87, 84, 88, 89, 0, 0, 88, 89, 88, 89, 90, 0, 0, 91, 88, 89, 0, 92, 92, 92, 90, 92, 90, 91, 90, 91, 0, 91, 90, 0, 91, 91, 0, 0, 92, 0, 92, 93, 93, 95, 0, 93, 94, 94, 0, 0, 94, 95, 96, 95, 0, 95, 0, 95, 93, 0, 93, 95, 96, 94, 96, 94, 96, 97, 0, 0, 96, 97, 98, 0, 0, 97, 98, 97, 97, 0, 98, 0, 98, 97, 0, 99, 99, 0, 98, 99, 100, 100, 0, 0, 100, 101, 101, 0, 100, 101, 0, 0, 99, 0, 99, 0, 0, 100, 0, 100, 0, 0, 101, 0, 101, 102, 102, 0, 0, 102, 103, 103, 0, 0, 103, 104, 0, 0, 0, 104, 0, 0, 102, 104, 102, 104, 105, 103, 0, 103, 105, 104, 0, 106, 105, 0, 105, 106, 0, 0, 0, 106, 105, 106, 107, 107, 0, 108, 107, 106, 0, 108, 107, 0, 107, 108, 0, 108, 109, 0, 107, 0, 109, 108, 0, 0, 109, 0, 109, 110, 110, 0, 0, 110, 109, 0, 0, 110, 0, 110, 111, 111, 112, 112, 111, 110, 112, 0, 111, 0, 111, 113, 113, 0, 0, 113, 111, 0, 0, 112, 0, 112, 114, 114, 0, 0, 114, 0, 113, 0, 113, 113, 115, 115, 0, 0, 115, 0, 0, 114, 0, 114, 116, 116, 0, 0, 116, 0, 0, 115, 0, 115, 0, 117, 117, 0, 116, 117, 118, 116, 0, 116, 118, 119, 119, 0, 118, 119, 118, 0, 117, 0, 117, 0, 118, 121, 121, 0, 0, 121, 119, 0, 119, 120, 120, 0, 0, 120, 120, 122, 122, 0, 121, 122, 121, 123, 123, 0, 0, 123, 120, 120, 120, 124, 124, 122, 122, 124, 122, 125, 125, 126, 123, 125, 123, 0, 0, 0, 0, 0, 124, 126, 124, 126, 0, 126, 125, 125, 125, 126, 127, 128, 0, 0, 127, 0, 0, 0, 127, 0, 127, 128, 0, 128, 129, 128, 127, 0, 129, 128, 0, 130, 129, 130, 129, 0, 0, 130, 131, 0, 129, 130, 131, 130, 0, 0, 131, 0, 131, 130, 132, 132, 133, 0, 131, 132, 133, 0, 0, 132, 133, 132, 133, 134, 135, 0, 0, 132, 133, 135, 0, 0, 0, 134, 135, 134, 135, 134, 135, 136, 0, 134, 135, 0, 136, 0, 137, 137, 141, 136, 137, 136, 141, 136, 137, 0, 141, 136, 141, 0, 0, 0, 142, 137, 141, 137, 142, 143, 0, 0, 142, 143, 142, 0, 0, 143, 0, 143, 142, 0, 144, 144, 0, 143, 144, 145, 145, 0, 144, 145, 144, 145, 0, 0, 0, 0, 144, 146, 0, 0, 0, 146, 145, 145, 145, 146, 0, 146, 147, 147, 148, 148, 147, 146, 148, 0, 147, 0, 147, 149, 149, 0, 0, 149, 147, 0, 0, 148, 0, 148, 150, 150, 0, 0, 150, 151, 149, 0, 149, 151, 0, 0, 0, 151, 150, 151, 0, 150, 0, 150, 0, 151, 0, 151, 152, 152, 0, 153, 152, 154, 154, 153, 152, 154, 152, 153, 0, 153, 155, 155, 152, 0, 155, 153, 0, 0, 154, 0, 154, 156, 156, 0, 0, 156, 0, 155, 0, 155, 0, 0, 0, 157, 157, 156, 0, 157, 156, 0, 156, 157, 158, 158, 0, 0, 158, 159, 159, 0, 157, 159, 157, 0, 158, 0, 0, 159, 0, 158, 0, 158, 0, 0, 159, 0, 159, 160, 160, 0, 0, 160, 161, 161, 0, 0, 161, 162, 162, 0, 0, 162, 0, 0, 160, 0, 160, 0, 0, 161, 161, 161, 0, 0, 162, 0, 162, 163, 163, 162, 0, 163, 164, 164, 0, 0, 164, 165, 165, 0, 0, 165, 0, 0, 163, 0, 163, 0, 0, 164, 0, 164, 0, 0, 165, 0, 165, 166, 166, 0, 0, 166, 167, 167, 0, 0, 167, 168, 168, 0, 0, 168, 0, 0, 166, 168, 166, 0, 0, 167, 0, 167, 0, 0, 168, 0, 168, 169, 169, 0, 0, 169, 170, 170, 0, 0, 170, 0, 0, 169, 0, 171, 171, 0, 169, 171, 169, 0, 0, 170, 0, 170, 0, 171, 0, 177, 177, 0, 171, 177, 171, 178, 178, 227, 0, 178, 179, 179, 0, 0, 179, 0, 177, 227, 177, 227, 0, 227, 178, 178, 178, 227, 0, 179, 0, 179, 180, 180, 0, 0, 180, 181, 181, 0, 0, 181, 182, 182, 0, 0, 182, 0, 0, 180, 0, 180, 0, 0, 181, 0, 181, 0, 0, 182, 0, 182, 183, 183, 183, 0, 183, 184, 184, 0, 0, 184, 185, 185, 0, 0, 185, 0, 0, 183, 0, 183, 0, 0, 184, 0, 184, 0, 0, 185, 0, 185, 186, 186, 0, 0, 186, 187, 187, 0, 0, 187, 0, 187, 188, 188, 0, 0, 188, 186, 0, 186, 0, 0, 187, 0, 187, 0, 189, 189, 0, 188, 189, 188, 190, 190, 189, 0, 190, 191, 191, 0, 0, 191, 0, 189, 0, 189, 192, 192, 0, 190, 192, 190, 0, 0, 191, 0, 191, 193, 193, 0, 0, 193, 0, 192, 0, 192, 194, 194, 0, 0, 194, 0, 194, 0, 193, 0, 193, 195, 195, 0, 0, 195, 0, 194, 0, 194, 196, 196, 0, 0, 196, 197, 197, 0, 195, 197, 195, 198, 198, 0, 0, 198, 0, 196, 0, 196, 0, 0, 197, 0, 197, 199, 199, 0, 198, 199, 198, 200, 200, 0, 0, 200, 201, 201, 0, 0, 201, 0, 199, 0, 199, 202, 202, 0, 200, 202, 200, 0, 0, 201, 0, 201, 203, 203, 0, 0, 203, 0, 202, 0, 202, 204, 204, 0, 0, 204, 205, 205, 0, 203, 205, 203, 0, 206, 206, 0, 0, 206, 204, 206, 204, 0, 0, 205, 0, 205, 0, 207, 207, 0, 206, 207, 206, 208, 208, 0, 0, 208, 209, 209, 0, 0, 209, 210, 207, 0, 207, 210, 0, 0, 208, 210, 208, 210, 211, 209, 0, 209, 211, 210, 0, 212, 211, 0, 211, 212, 0, 0, 213, 212, 211, 212, 213, 0, 0, 213, 213, 212, 213, 214, 214, 0, 0, 214, 213, 215, 215, 0, 0, 215, 216, 216, 0, 0, 216, 0, 214, 0, 214, 217, 217, 0, 215, 217, 215, 0, 0, 216, 0, 216, 218, 218, 0, 0, 218, 0, 217, 0, 217, 219, 219, 0, 0, 219, 220, 220, 0, 218, 220, 218, 0, 221, 221, 0, 218, 221, 219, 0, 219, 0, 0, 220, 0, 220, 220, 222, 222, 0, 221, 222, 221, 223, 223, 0, 0, 223, 224, 224, 0, 0, 224, 0, 222, 0, 222, 225, 225, 0, 223, 225, 223, 228, 0, 224, 0, 224, 226, 226, 229, 0, 226, 228, 225, 228, 225, 228, 0, 229, 229, 228, 229, 230, 229, 226, 0, 226, 229, 0, 231, 231, 0, 230, 231, 230, 0, 230, 244, 244, 0, 230, 244, 0, 245, 245, 0, 231, 245, 231, 246, 246, 0, 0, 246, 244, 0, 244, 247, 247, 0, 245, 247, 245, 248, 248, 250, 246, 248, 246, 249, 249, 0, 0, 249, 247, 250, 247, 250, 0, 250, 248, 0, 248, 250, 251, 0, 249, 0, 249, 251, 0, 252, 252, 0, 251, 252, 251, 0, 251, 251, 253, 253, 251, 0, 253, 254, 254, 0, 252, 254, 252, 255, 255, 0, 0, 255, 0, 253, 0, 253, 0, 257, 254, 0, 254, 256, 256, 0, 255, 256, 255, 257, 0, 257, 0, 257, 258, 0, 0, 257, 0, 0, 256, 0, 256, 0, 258, 259, 258, 0, 258, 0, 260, 260, 258, 258, 260, 259, 0, 259, 0, 259, 261, 261, 0, 259, 261, 0, 0, 260, 0, 260, 262, 262, 0, 0, 262, 0, 0, 261, 261, 261, 263, 263, 0, 0, 263, 0, 263, 262, 265, 262, 264, 264, 0, 0, 264, 0, 0, 263, 265, 263, 265, 266, 265, 0, 267, 267, 265, 264, 267, 264, 0, 266, 0, 266, 0, 266, 268, 268, 0, 266, 268, 267, 0, 267, 269, 269, 0, 0, 269, 0, 270, 270, 0, 268, 270, 268, 271, 271, 271, 0, 271, 269, 0, 269, 272, 272, 0, 270, 272, 270, 273, 273, 0, 271, 273, 271, 274, 274, 0, 0, 274, 272, 276, 272, 275, 275, 276, 273, 275, 273, 276, 277, 276, 274, 0, 274, 277, 0, 276, 0, 277, 275, 0, 275, 277, 278, 277, 279, 279, 278, 0, 279, 277, 278, 0, 278, 280, 280, 0, 0, 280, 278, 351, 0, 279, 0, 279, 281, 281, 0, 0, 281, 351, 280, 351, 280, 351, 282, 282, 0, 351, 282, 0, 364, 281, 0, 281, 282, 283, 283, 0, 0, 283, 364, 282, 364, 282, 364, 284, 284, 0, 364, 284, 0, 0, 283, 284, 283, 285, 285, 0, 0, 285, 0, 0, 284, 0, 284, 286, 286, 0, 0, 286, 0, 0, 285, 0, 285, 287, 287, 287, 0, 287, 0, 0, 286, 0, 286, 288, 288, 0, 0, 288, 0, 0, 287, 0, 287, 289, 289, 0, 0, 289, 0, 0, 288, 288, 288, 290, 290, 0, 0, 290, 0, 0, 289, 0, 289, 291, 291, 0, 0, 291, 0, 291, 290, 0, 290, 292, 292, 0, 0, 292, 0, 0, 291, 0, 291, 293, 293, 0, 0, 293, 0, 0, 292, 0, 292, 294, 294, 0, 0, 294, 0, 0, 293, 293, 293, 295, 295, 0, 0, 295, 0, 0, 294, 0, 294, 296, 296, 0, 0, 296, 0, 0, 295, 0, 295, 297, 297, 0, 0, 297, 0, 0, 296, 0, 296, 298, 298, 0, 0, 298, 0, 0, 297, 300, 297, 299, 299, 300, 0, 299, 0, 300, 298, 300, 298, 0, 0, 299, 0, 300, 0, 0, 299, 0, 299, 301, 301, 0, 0, 301, 302, 302, 0, 0, 302, 303, 303, 0, 0, 303, 0, 0, 301, 0, 301, 0, 0, 302, 0, 302, 0, 0, 303, 0, 303, 304, 304, 0, 0, 304, 305, 305, 0, 0, 305, 306, 306, 0, 305, 306, 0, 0, 304, 0, 304, 0, 0, 305, 0, 305, 0, 0, 306, 0, 306, 307, 307, 0, 0, 307, 308, 308, 0, 0, 308, 346, 309, 309, 0, 346, 309, 0, 307, 346, 307, 346, 0, 308, 0, 308, 0, 346, 0, 309, 308, 309, 328, 328, 0, 0, 328, 329, 329, 0, 0, 329, 330, 330, 0, 0, 330, 0, 0, 328, 0, 328, 0, 0, 329, 329, 329, 0, 0, 330, 0, 330, 331, 331, 0, 0, 331, 0, 332, 332, 0, 0, 332, 333, 333, 0, 331, 333, 0, 331, 332, 331, 334, 334, 0, 332, 334, 332, 0, 0, 333, 0, 333, 335, 335, 0, 0, 335, 0, 334, 0, 334, 336, 336, 0, 0, 336, 337, 337, 0, 335, 337, 335, 338, 338, 0, 0, 338, 0, 336, 0, 336, 0, 0, 337, 0, 337, 339, 339, 339, 338, 339, 338, 340, 340, 0, 0, 340, 341, 341, 0, 0, 341, 0, 339, 0, 339, 340, 0, 0, 340, 0, 340, 0, 0, 341, 0, 341, 342, 342, 0, 0, 342, 343, 343, 0, 0, 343, 344, 344, 0, 0, 344, 0, 0, 342, 0, 342, 0, 0, 343, 0, 343, 0, 0, 344, 0, 344, 345, 345, 0, 0, 345, 347, 347, 0, 345, 347, 348, 348, 0, 0, 348, 0, 0, 345, 0, 345, 0, 0, 347, 0, 347, 0, 0, 348, 0, 348, 349, 349, 0, 0, 349, 350, 350, 0, 0, 350, 352, 352, 0, 0, 352, 0, 0, 349, 0, 349, 0, 0, 350, 0, 350, 0, 0, 352, 0, 352, 353, 353, 0, 0, 353, 0, 354, 354, 0, 0, 354, 355, 355, 0, 0, 355, 0, 353, 354, 353, 356, 356, 0, 354, 356, 354, 0, 0, 355, 355, 355, 0, 357, 0, 0, 0, 357, 356, 0, 356, 357, 358, 357, 0, 0, 358, 0, 0, 357, 358, 0, 358, 359, 0, 358, 359, 359, 358, 0, 360, 359, 0, 359, 360, 0, 0, 361, 360, 359, 360, 361, 0, 365, 362, 361, 360, 361, 362, 0, 0, 0, 362, 361, 362, 363, 0, 0, 363, 363, 362, 0, 0, 363, 0, 363, 365, 366, 0, 368, 368, 363, 0, 368, 0, 0, 365, 366, 365, 366, 365, 366, 367, 0, 365, 366, 368, 0, 368, 369, 369, 0, 367, 369, 367, 0, 367, 370, 370, 374, 367, 370, 0, 371, 371, 372, 369, 371, 369, 372, 0, 0, 0, 372, 370, 372, 370, 0, 0, 373, 371, 372, 371, 373, 0, 0, 374, 373, 375, 373, 374, 0, 0, 375, 374, 373, 374, 375, 0, 0, 0, 375, 374, 375, 376, 0, 0, 376, 376, 375, 0, 0, 376, 0, 376, 377, 377, 0, 0, 377, 376, 378, 378, 0, 0, 378, 379, 379, 0, 0, 379, 0, 377, 0, 377, 380, 380, 0, 378, 380, 378, 0, 0, 379, 0, 379, 0, 380, 0, 381, 381, 0, 380, 381, 380, 382, 382, 0, 0, 382, 383, 383, 0, 0, 383, 0, 381, 0, 381, 381, 0, 0, 382, 0, 382, 0, 0, 383, 0, 383, 384, 384, 0, 0, 384, 385, 385, 0, 0, 385, 0, 386, 386, 0, 0, 386, 0, 384, 0, 384, 0, 0, 385, 386, 385, 387, 387, 0, 386, 387, 386, 388, 388, 0, 0, 388, 389, 389, 0, 0, 389, 0, 387, 0, 387, 390, 390, 0, 388, 390, 388, 390, 0, 389, 0, 389, 392, 392, 0, 0, 392, 0, 390, 0, 390, 393, 393, 0, 0, 393, 395, 0, 0, 392, 0, 392, 394, 394, 0, 0, 394, 0, 393, 0, 393, 396, 396, 417, 394, 396, 395, 395, 0, 394, 395, 394, 0, 417, 0, 417, 0, 417, 396, 396, 396, 417, 398, 395, 0, 395, 398, 399, 0, 0, 398, 399, 398, 0, 0, 399, 0, 399, 398, 0, 400, 400, 0, 399, 400, 401, 401, 0, 0, 401, 402, 402, 0, 0, 402, 0, 0, 400, 0, 400, 0, 0, 401, 0, 401, 0, 0, 402, 0, 402, 403, 403, 0, 0, 403, 404, 404, 0, 0, 404, 406, 406, 0, 0, 406, 0, 0, 403, 0, 403, 0, 0, 404, 0, 404, 0, 0, 406, 0, 406, 407, 407, 0, 0, 407, 408, 408, 0, 0, 408, 410, 410, 0, 0, 410, 0, 0, 407, 0, 407, 0, 0, 408, 0, 408, 0, 0, 410, 414, 410, 413, 413, 414, 0, 413, 415, 414, 0, 414, 415, 415, 0, 416, 415, 414, 415, 416, 413, 0, 413, 416, 415, 416, 419, 0, 0, 0, 0, 416, 0, 423, 0, 0, 419, 0, 419, 0, 419, 419, 424, 423, 419, 423, 0, 423, 0, 425, 425, 423, 424, 425, 424, 0, 424, 428, 428, 0, 424, 428, 0, 432, 432, 0, 425, 432, 425, 0, 0, 0, 0, 0, 428, 0, 428, 0, 0, 0, 432, 0, 432, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 441, 442, 0, 442, 442, 442, 442, 442, 442, 442, 442, 442, 443, 0, 443, 443, 443, 443, 443, 443, 443, 443, 443, 444, 444, 444, 444, 444, 444, 444, 445, 0, 445, 445, 445, 445, 445, 445, 445, 445, 445, 446, 0, 0, 0, 446, 446, 446, 446, 446, 447, 0, 0, 0, 0, 0, 0, 447, 449, 449, 449, 449, 449, 449, 449, 449, 450, 450, 450, 450, 450, 450, 450, 450, 450, 452, 452, 452, 452, 452, 452, 452, 452, 453, 453, 0, 453, 453, 454, 454, 0, 454, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440, 440 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; extern int bx_flex_debug; int bx_flex_debug = 0; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *bxtext; #line 1 "lexer.l" #line 2 "lexer.l" ///////////////////////////////////////////////////////////////////////// // $Id: lexer.c 11151 2012-04-24 11:01:59Z sshwarts $ ///////////////////////////////////////////////////////////////////////// #include #include #ifdef WIN32 #include #define YY_NO_UNISTD_H #endif #include "debug.h" #if BX_DEBUGGER #include "parser.h" int bx_yyinput(char *buf, int max_size); #undef YY_INPUT #define YY_INPUT(buf, ret, max_size) (ret = bx_yyinput(buf, max_size)) static char *lex_input_ptr = NULL; static unsigned lex_input_size = 0; #if BX_SUPPORT_X86_64 #define LONG_MODE_8BL_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_8BL_REG); } #define LONG_MODE_16B_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_16B_REG); } #define LONG_MODE_32B_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_32B_REG); } #define LONG_MODE_64B_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_64B_REG); } #else #define LONG_MODE_8BL_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #define LONG_MODE_16B_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #define LONG_MODE_32B_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #define LONG_MODE_64B_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #endif #line 1351 "" #define INITIAL 0 #define EXAMINE 1 #define DISASM 2 #ifndef YY_NO_UNISTD_H /* Special case for "unistd.h", since it is non-ANSI. We include it way * down here because we want the user's section 1 to have been scanned first. * The user has a chance to override it with an option. */ #include #endif #ifndef YY_EXTRA_TYPE #define YY_EXTRA_TYPE void * #endif static int yy_init_globals (void ); /* Accessor methods to globals. These are made visible to non-reentrant scanners for convenience. */ int bxlex_destroy (void ); int bxget_debug (void ); void bxset_debug (int debug_flag ); YY_EXTRA_TYPE bxget_extra (void ); void bxset_extra (YY_EXTRA_TYPE user_defined ); FILE *bxget_in (void ); void bxset_in (FILE * in_str ); FILE *bxget_out (void ); void bxset_out (FILE * out_str ); int bxget_leng (void ); char *bxget_text (void ); int bxget_lineno (void ); void bxset_lineno (int line_number ); /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int bxwrap (void ); #else extern int bxwrap (void ); #endif #endif static void yyunput (int c,char *buf_ptr ); #ifndef yytext_ptr static void yy_flex_strncpy (char *,yyconst char *,int ); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * ); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void ); #else static int input (void ); #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO fwrite( bxtext, bxleng, 1, bxout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ { \ int c = '*'; \ int n; \ for ( n = 0; n < max_size && \ (c = getc( bxin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( bxin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, bxin))==0 && ferror(bxin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(bxin); \ } \ }\ \ #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* end tables serialization structures and prototypes */ /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL_IS_OURS 1 extern int bxlex (void); #define YY_DECL int bxlex (void) #endif /* !YY_DECL */ /* Code executed at the beginning of each rule, after bxtext and bxleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION /** The main scanner function which does all the work. */ YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 51 "lexer.l" #line 1537 "" if ( !(yy_init) ) { (yy_init) = 1; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! (yy_start) ) (yy_start) = 1; /* first start state */ if ( ! bxin ) bxin = stdin; if ( ! bxout ) bxout = stdout; if ( ! YY_CURRENT_BUFFER ) { bxensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = bx_create_buffer(bxin,YY_BUF_SIZE ); } bx_load_buffer_state( ); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = (yy_c_buf_p); /* Support of bxtext. */ *yy_cp = (yy_hold_char); /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = (yy_start); yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 441 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 3062 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = (yy_hold_char); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); goto yy_find_action; case 1: YY_RULE_SETUP #line 52 "lexer.l" ; // eat up whitespace YY_BREAK case 2: YY_RULE_SETUP #line 53 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SET); } YY_BREAK case 3: YY_RULE_SETUP #line 54 "lexer.l" { bxlval.bval = 1; return(BX_TOKEN_ON); } YY_BREAK case 4: YY_RULE_SETUP #line 55 "lexer.l" { bxlval.bval = 0; return(BX_TOKEN_OFF); } YY_BREAK case 5: YY_RULE_SETUP #line 56 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CRC); } YY_BREAK case 6: #line 58 "lexer.l" case 7: #line 59 "lexer.l" case 8: YY_RULE_SETUP #line 59 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CONTINUE); } YY_BREAK case 9: #line 61 "lexer.l" case 10: YY_RULE_SETUP #line 61 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_STEPN); } YY_BREAK case 11: #line 63 "lexer.l" case 12: #line 64 "lexer.l" case 13: YY_RULE_SETUP #line 64 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_STEP_OVER); } YY_BREAK case 14: YY_RULE_SETUP #line 65 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LIST_BREAK); } YY_BREAK case 15: YY_RULE_SETUP #line 66 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_VBREAKPOINT); } YY_BREAK case 16: YY_RULE_SETUP #line 67 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LBREAKPOINT); } YY_BREAK case 17: #line 69 "lexer.l" case 18: #line 70 "lexer.l" case 19: YY_RULE_SETUP #line 70 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PBREAKPOINT); } YY_BREAK case 20: YY_RULE_SETUP #line 71 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_INFO); } YY_BREAK case 21: #line 73 "lexer.l" case 22: YY_RULE_SETUP #line 73 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CONTROL_REGS); } YY_BREAK case 23: #line 75 "lexer.l" case 24: YY_RULE_SETUP #line 75 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DEBUG_REGS); } YY_BREAK case 25: YY_RULE_SETUP #line 76 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SEGMENT_REGS); } YY_BREAK case 26: YY_RULE_SETUP #line 77 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_R); } YY_BREAK case 27: #line 79 "lexer.l" case 28: YY_RULE_SETUP #line 79 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_REGS); } YY_BREAK case 29: YY_RULE_SETUP #line 80 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_FPU); } YY_BREAK case 30: YY_RULE_SETUP #line 81 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SSE); } YY_BREAK case 31: YY_RULE_SETUP #line 82 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_AVX); } YY_BREAK case 32: YY_RULE_SETUP #line 83 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_MMX); } YY_BREAK case 33: YY_RULE_SETUP #line 84 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CPU); } YY_BREAK case 34: YY_RULE_SETUP #line 85 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_IDT); } YY_BREAK case 35: YY_RULE_SETUP #line 86 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_IVT); } YY_BREAK case 36: YY_RULE_SETUP #line 87 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GDT); } YY_BREAK case 37: YY_RULE_SETUP #line 88 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LDT); } YY_BREAK case 38: YY_RULE_SETUP #line 89 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TSS); } YY_BREAK case 39: YY_RULE_SETUP #line 90 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TAB); } YY_BREAK case 40: YY_RULE_SETUP #line 91 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LINUX); } YY_BREAK case 41: #line 93 "lexer.l" case 42: #line 94 "lexer.l" case 43: YY_RULE_SETUP #line 94 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DEL_BREAKPOINT); } YY_BREAK case 44: YY_RULE_SETUP #line 95 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_ENABLE_BREAKPOINT); } YY_BREAK case 45: YY_RULE_SETUP #line 96 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DISABLE_BREAKPOINT); } YY_BREAK case 46: #line 98 "lexer.l" case 47: #line 99 "lexer.l" case 48: YY_RULE_SETUP #line 99 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_QUIT); } YY_BREAK case 49: #line 101 "lexer.l" case 50: YY_RULE_SETUP #line 101 "lexer.l" { BEGIN(EXAMINE); bxlval.sval = strdup(bxtext); return(BX_TOKEN_EXAMINE); } YY_BREAK case 51: YY_RULE_SETUP #line 102 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_RESTORE); } YY_BREAK case 52: YY_RULE_SETUP #line 103 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WRITEMEM); } YY_BREAK case 53: YY_RULE_SETUP #line 104 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SETPMEM); } YY_BREAK case 54: YY_RULE_SETUP #line 105 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_QUERY); } YY_BREAK case 55: YY_RULE_SETUP #line 106 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PENDING); } YY_BREAK case 56: YY_RULE_SETUP #line 107 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TAKE); } YY_BREAK case 57: YY_RULE_SETUP #line 108 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DMA); } YY_BREAK case 58: YY_RULE_SETUP #line 109 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_IRQ); } YY_BREAK case 59: #line 111 "lexer.l" case 60: YY_RULE_SETUP #line 111 "lexer.l" { BEGIN(DISASM); bxlval.sval = strdup(bxtext); return(BX_TOKEN_DISASM); } YY_BREAK case 61: YY_RULE_SETUP #line 112 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_HEX); } YY_BREAK case 62: YY_RULE_SETUP #line 113 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_INSTRUMENT); } YY_BREAK case 63: YY_RULE_SETUP #line 114 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_STOP); } YY_BREAK case 64: YY_RULE_SETUP #line 115 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DOIT); } YY_BREAK case 65: YY_RULE_SETUP #line 116 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACE); } YY_BREAK case 66: YY_RULE_SETUP #line 117 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACEREG); } YY_BREAK case 67: YY_RULE_SETUP #line 118 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACEMEM); } YY_BREAK case 68: YY_RULE_SETUP #line 119 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SWITCH_MODE); } YY_BREAK case 69: YY_RULE_SETUP #line 120 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SIZE); } YY_BREAK case 70: YY_RULE_SETUP #line 121 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PTIME); } YY_BREAK case 71: YY_RULE_SETUP #line 122 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TIMEBP); } YY_BREAK case 72: YY_RULE_SETUP #line 123 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TIMEBP_ABSOLUTE); } YY_BREAK case 73: YY_RULE_SETUP #line 124 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_MODEBP); } YY_BREAK case 74: YY_RULE_SETUP #line 125 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_VMEXITBP); } YY_BREAK case 75: YY_RULE_SETUP #line 126 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PRINT_STACK); } YY_BREAK case 76: YY_RULE_SETUP #line 127 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WATCH); } YY_BREAK case 77: YY_RULE_SETUP #line 128 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_UNWATCH); } YY_BREAK case 78: YY_RULE_SETUP #line 129 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_READ); } YY_BREAK case 79: YY_RULE_SETUP #line 130 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WRITE); } YY_BREAK case 80: YY_RULE_SETUP #line 131 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SHOW); } YY_BREAK case 81: YY_RULE_SETUP #line 132 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LOAD_SYMBOLS); } YY_BREAK case 82: YY_RULE_SETUP #line 133 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SYMBOLS); } YY_BREAK case 83: YY_RULE_SETUP #line 134 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LIST_SYMBOLS); } YY_BREAK case 84: YY_RULE_SETUP #line 135 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GLOBAL); } YY_BREAK case 85: YY_RULE_SETUP #line 136 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WHERE); } YY_BREAK case 86: YY_RULE_SETUP #line 137 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PRINT_STRING); } YY_BREAK case 87: YY_RULE_SETUP #line 138 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PAGE); } YY_BREAK case 88: YY_RULE_SETUP #line 139 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_VGA); } YY_BREAK case 89: YY_RULE_SETUP #line 140 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DEVICE); } YY_BREAK case 90: YY_RULE_SETUP #line 141 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_ALL); } YY_BREAK case 91: YY_RULE_SETUP #line 142 "lexer.l" { bxlval.uval = BX_DBG_REG8L_AL; return(BX_TOKEN_8BL_REG);} YY_BREAK case 92: YY_RULE_SETUP #line 143 "lexer.l" { bxlval.uval = BX_DBG_REG8L_BL; return(BX_TOKEN_8BL_REG);} YY_BREAK case 93: YY_RULE_SETUP #line 144 "lexer.l" { bxlval.uval = BX_DBG_REG8L_CL; return(BX_TOKEN_8BL_REG);} YY_BREAK case 94: YY_RULE_SETUP #line 145 "lexer.l" { bxlval.uval = BX_DBG_REG8L_DL; return(BX_TOKEN_8BL_REG);} YY_BREAK case 95: YY_RULE_SETUP #line 146 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_SIL); } YY_BREAK case 96: YY_RULE_SETUP #line 147 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_DIL); } YY_BREAK case 97: YY_RULE_SETUP #line 148 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_SPL); } YY_BREAK case 98: YY_RULE_SETUP #line 149 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_BPL); } YY_BREAK case 99: YY_RULE_SETUP #line 150 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R8); } YY_BREAK case 100: YY_RULE_SETUP #line 151 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R9); } YY_BREAK case 101: YY_RULE_SETUP #line 152 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R10); } YY_BREAK case 102: YY_RULE_SETUP #line 153 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R11); } YY_BREAK case 103: YY_RULE_SETUP #line 154 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R12); } YY_BREAK case 104: YY_RULE_SETUP #line 155 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R13); } YY_BREAK case 105: YY_RULE_SETUP #line 156 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R14); } YY_BREAK case 106: YY_RULE_SETUP #line 157 "lexer.l" { LONG_MODE_8BL_REG(BX_DBG_REG8L_R15); } YY_BREAK case 107: YY_RULE_SETUP #line 158 "lexer.l" { bxlval.uval = BX_DBG_REG8H_AH; return(BX_TOKEN_8BH_REG);} YY_BREAK case 108: YY_RULE_SETUP #line 159 "lexer.l" { bxlval.uval = BX_DBG_REG8H_BH; return(BX_TOKEN_8BH_REG);} YY_BREAK case 109: YY_RULE_SETUP #line 160 "lexer.l" { bxlval.uval = BX_DBG_REG8H_CH; return(BX_TOKEN_8BH_REG);} YY_BREAK case 110: YY_RULE_SETUP #line 161 "lexer.l" { bxlval.uval = BX_DBG_REG8H_DH; return(BX_TOKEN_8BH_REG);} YY_BREAK case 111: YY_RULE_SETUP #line 162 "lexer.l" { bxlval.uval = BX_DBG_REG16_AX; return(BX_TOKEN_16B_REG);} YY_BREAK case 112: YY_RULE_SETUP #line 163 "lexer.l" { bxlval.uval = BX_DBG_REG16_BX; return(BX_TOKEN_16B_REG);} YY_BREAK case 113: YY_RULE_SETUP #line 164 "lexer.l" { bxlval.uval = BX_DBG_REG16_CX; return(BX_TOKEN_16B_REG);} YY_BREAK case 114: YY_RULE_SETUP #line 165 "lexer.l" { bxlval.uval = BX_DBG_REG16_DX; return(BX_TOKEN_16B_REG);} YY_BREAK case 115: YY_RULE_SETUP #line 166 "lexer.l" { bxlval.uval = BX_DBG_REG16_SI; return(BX_TOKEN_16B_REG);} YY_BREAK case 116: YY_RULE_SETUP #line 167 "lexer.l" { bxlval.uval = BX_DBG_REG16_DI; return(BX_TOKEN_16B_REG);} YY_BREAK case 117: YY_RULE_SETUP #line 168 "lexer.l" { bxlval.uval = BX_DBG_REG16_BP; return(BX_TOKEN_16B_REG);} YY_BREAK case 118: YY_RULE_SETUP #line 169 "lexer.l" { bxlval.uval = BX_DBG_REG16_SP; return(BX_TOKEN_16B_REG);} YY_BREAK case 119: YY_RULE_SETUP #line 170 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R8); } YY_BREAK case 120: YY_RULE_SETUP #line 171 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R9); } YY_BREAK case 121: YY_RULE_SETUP #line 172 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R10); } YY_BREAK case 122: YY_RULE_SETUP #line 173 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R11); } YY_BREAK case 123: YY_RULE_SETUP #line 174 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R12); } YY_BREAK case 124: YY_RULE_SETUP #line 175 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R13); } YY_BREAK case 125: YY_RULE_SETUP #line 176 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R14); } YY_BREAK case 126: YY_RULE_SETUP #line 177 "lexer.l" { LONG_MODE_16B_REG(BX_DBG_REG16_R15); } YY_BREAK case 127: YY_RULE_SETUP #line 178 "lexer.l" { bxlval.uval = BX_DBG_REG32_EAX; return(BX_TOKEN_32B_REG);} YY_BREAK case 128: YY_RULE_SETUP #line 179 "lexer.l" { bxlval.uval = BX_DBG_REG32_EBX; return(BX_TOKEN_32B_REG);} YY_BREAK case 129: YY_RULE_SETUP #line 180 "lexer.l" { bxlval.uval = BX_DBG_REG32_ECX; return(BX_TOKEN_32B_REG);} YY_BREAK case 130: YY_RULE_SETUP #line 181 "lexer.l" { bxlval.uval = BX_DBG_REG32_EDX; return(BX_TOKEN_32B_REG);} YY_BREAK case 131: YY_RULE_SETUP #line 182 "lexer.l" { bxlval.uval = BX_DBG_REG32_ESI; return(BX_TOKEN_32B_REG);} YY_BREAK case 132: YY_RULE_SETUP #line 183 "lexer.l" { bxlval.uval = BX_DBG_REG32_EDI; return(BX_TOKEN_32B_REG);} YY_BREAK case 133: YY_RULE_SETUP #line 184 "lexer.l" { bxlval.uval = BX_DBG_REG32_EBP; return(BX_TOKEN_32B_REG);} YY_BREAK case 134: YY_RULE_SETUP #line 185 "lexer.l" { bxlval.uval = BX_DBG_REG32_ESP; return(BX_TOKEN_32B_REG);} YY_BREAK case 135: YY_RULE_SETUP #line 186 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R8); } YY_BREAK case 136: YY_RULE_SETUP #line 187 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R9); } YY_BREAK case 137: YY_RULE_SETUP #line 188 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R10); } YY_BREAK case 138: YY_RULE_SETUP #line 189 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R11); } YY_BREAK case 139: YY_RULE_SETUP #line 190 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R12); } YY_BREAK case 140: YY_RULE_SETUP #line 191 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R13); } YY_BREAK case 141: YY_RULE_SETUP #line 192 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R14); } YY_BREAK case 142: YY_RULE_SETUP #line 193 "lexer.l" { LONG_MODE_32B_REG(BX_DBG_REG32_R15); } YY_BREAK case 143: YY_RULE_SETUP #line 194 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RAX); } YY_BREAK case 144: YY_RULE_SETUP #line 195 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RBX); } YY_BREAK case 145: YY_RULE_SETUP #line 196 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RCX); } YY_BREAK case 146: YY_RULE_SETUP #line 197 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RDX); } YY_BREAK case 147: YY_RULE_SETUP #line 198 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RSI); } YY_BREAK case 148: YY_RULE_SETUP #line 199 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RDI); } YY_BREAK case 149: YY_RULE_SETUP #line 200 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RSP); } YY_BREAK case 150: YY_RULE_SETUP #line 201 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_RBP); } YY_BREAK case 151: YY_RULE_SETUP #line 202 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R8); } YY_BREAK case 152: YY_RULE_SETUP #line 203 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R9); } YY_BREAK case 153: YY_RULE_SETUP #line 204 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R10); } YY_BREAK case 154: YY_RULE_SETUP #line 205 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R11); } YY_BREAK case 155: YY_RULE_SETUP #line 206 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R12); } YY_BREAK case 156: YY_RULE_SETUP #line 207 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R13); } YY_BREAK case 157: YY_RULE_SETUP #line 208 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R14); } YY_BREAK case 158: YY_RULE_SETUP #line 209 "lexer.l" { LONG_MODE_64B_REG(BX_DBG_REG64_R15); } YY_BREAK case 159: YY_RULE_SETUP #line 210 "lexer.l" { return(BX_TOKEN_REG_IP); } YY_BREAK case 160: YY_RULE_SETUP #line 211 "lexer.l" { return(BX_TOKEN_REG_EIP);} YY_BREAK case 161: YY_RULE_SETUP #line 212 "lexer.l" { return(BX_TOKEN_REG_RIP);} YY_BREAK case 162: YY_RULE_SETUP #line 213 "lexer.l" { bxlval.uval = BX_DBG_SREG_CS; return(BX_TOKEN_CS); } YY_BREAK case 163: YY_RULE_SETUP #line 214 "lexer.l" { bxlval.uval = BX_DBG_SREG_ES; return(BX_TOKEN_ES); } YY_BREAK case 164: YY_RULE_SETUP #line 215 "lexer.l" { bxlval.uval = BX_DBG_SREG_SS; return(BX_TOKEN_SS); } YY_BREAK case 165: YY_RULE_SETUP #line 216 "lexer.l" { bxlval.uval = BX_DBG_SREG_DS; return(BX_TOKEN_DS); } YY_BREAK case 166: YY_RULE_SETUP #line 217 "lexer.l" { bxlval.uval = BX_DBG_SREG_FS; return(BX_TOKEN_FS); } YY_BREAK case 167: YY_RULE_SETUP #line 218 "lexer.l" { bxlval.uval = BX_DBG_SREG_GS; return(BX_TOKEN_GS); } YY_BREAK case 168: YY_RULE_SETUP #line 219 "lexer.l" { bxlval.uval = 0; return (BX_TOKEN_FLAGS); } YY_BREAK case 169: YY_RULE_SETUP #line 220 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_HELP); } YY_BREAK case 170: #line 222 "lexer.l" case 171: YY_RULE_SETUP #line 222 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CALC); } YY_BREAK case 172: YY_RULE_SETUP #line 223 "lexer.l" { BEGIN(INITIAL); bxlval.sval = strdup(bxtext); return(BX_TOKEN_XFORMAT); } YY_BREAK case 173: YY_RULE_SETUP #line 224 "lexer.l" { BEGIN(INITIAL); bxlval.sval = strdup(bxtext); return(BX_TOKEN_XFORMAT); } YY_BREAK case 174: YY_RULE_SETUP #line 225 "lexer.l" { BEGIN(INITIAL); bxlval.sval = strdup(bxtext); return(BX_TOKEN_DISFORMAT); } YY_BREAK case 175: YY_RULE_SETUP #line 226 "lexer.l" { return ('+'); } YY_BREAK case 176: YY_RULE_SETUP #line 227 "lexer.l" { return ('-'); } YY_BREAK case 177: YY_RULE_SETUP #line 228 "lexer.l" { return ('*'); } YY_BREAK case 178: YY_RULE_SETUP #line 229 "lexer.l" { return ('/'); } YY_BREAK case 179: YY_RULE_SETUP #line 230 "lexer.l" { return (BX_TOKEN_RSHIFT); } YY_BREAK case 180: YY_RULE_SETUP #line 231 "lexer.l" { return (BX_TOKEN_LSHIFT); } YY_BREAK case 181: YY_RULE_SETUP #line 232 "lexer.l" { return ('&'); } YY_BREAK case 182: YY_RULE_SETUP #line 233 "lexer.l" { return ('|'); } YY_BREAK case 183: YY_RULE_SETUP #line 234 "lexer.l" { return ('^'); } YY_BREAK case 184: YY_RULE_SETUP #line 235 "lexer.l" { return ('!'); } YY_BREAK case 185: YY_RULE_SETUP #line 236 "lexer.l" { return ('@'); } YY_BREAK case 186: YY_RULE_SETUP #line 237 "lexer.l" { return ('('); } YY_BREAK case 187: YY_RULE_SETUP #line 238 "lexer.l" { return (')'); } YY_BREAK case 188: #line 240 "lexer.l" case 189: YY_RULE_SETUP #line 240 "lexer.l" { bxlval.sval = strdup(bxtext+1); bxlval.sval[strlen(bxlval.sval)-1] = 0; return(BX_TOKEN_STRING); } YY_BREAK case 190: YY_RULE_SETUP #line 241 "lexer.l" { bxlval.uval = strtoull(bxtext, NULL, 16); return(BX_TOKEN_NUMERIC); } YY_BREAK case 191: YY_RULE_SETUP #line 242 "lexer.l" { bxlval.uval = strtoull(bxtext, NULL, 8); return(BX_TOKEN_NUMERIC); } YY_BREAK case 192: YY_RULE_SETUP #line 243 "lexer.l" { bxlval.uval = strtoull(bxtext, NULL, 10); return(BX_TOKEN_NUMERIC); } YY_BREAK case 193: YY_RULE_SETUP #line 244 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_COMMAND); } YY_BREAK case 194: YY_RULE_SETUP #line 245 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SYMBOLNAME); } YY_BREAK case 195: YY_RULE_SETUP #line 246 "lexer.l" { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } YY_BREAK case 196: YY_RULE_SETUP #line 247 "lexer.l" { return ('\n'); } YY_BREAK case 197: /* rule 197 can match eol */ YY_RULE_SETUP #line 248 "lexer.l" { return ('\n'); } YY_BREAK case 198: YY_RULE_SETUP #line 249 "lexer.l" ; // eat up comments '//' YY_BREAK case 199: YY_RULE_SETUP #line 250 "lexer.l" { return(bxtext[0]); } YY_BREAK case 200: YY_RULE_SETUP #line 251 "lexer.l" { BEGIN(INITIAL); unput(*bxtext); } YY_BREAK case 201: YY_RULE_SETUP #line 252 "lexer.l" ECHO; YY_BREAK #line 2572 "" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(EXAMINE): case YY_STATE_EOF(DISASM): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = (yy_hold_char); YY_RESTORE_YY_MORE_OFFSET if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed bxin at a new source and called * bxlex(). If so, then we have to assure * consistency between YY_CURRENT_BUFFER and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; YY_CURRENT_BUFFER_LVALUE->yy_input_file = bxin; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) { /* This was really a NUL. */ yy_state_type yy_next_state; (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = (yytext_ptr) + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++(yy_c_buf_p); yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = (yy_c_buf_p); goto yy_find_action; } } else switch ( yy_get_next_buffer( ) ) { case EOB_ACT_END_OF_FILE: { (yy_did_buffer_switch_on_eof) = 0; if ( bxwrap( ) ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * bxtext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: (yy_c_buf_p) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; yy_current_state = yy_get_previous_state( ); yy_cp = (yy_c_buf_p); yy_bp = (yytext_ptr) + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of bxlex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer (void) { register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; register char *source = (yytext_ptr); register int number_to_move, i; int ret_val; if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; else { int num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = YY_CURRENT_BUFFER; int yy_c_buf_p_offset = (int) ((yy_c_buf_p) - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ bxrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } if ( (yy_n_chars) == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; bxrestart(bxin ); } else { ret_val = EOB_ACT_LAST_MATCH; YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { /* Extend the array by 50%, plus the number we really need. */ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) bxrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); } (yy_n_chars) += number_to_move; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state (void) { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = (yy_start); for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 441 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) { register int yy_is_jam; register char *yy_cp = (yy_c_buf_p); register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { (yy_last_accepting_state) = yy_current_state; (yy_last_accepting_cpos) = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 441 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 440); return yy_is_jam ? 0 : yy_current_state; } static void yyunput (int c, register char * yy_bp ) { register char *yy_cp; yy_cp = (yy_c_buf_p); /* undo effects of setting up bxtext */ *yy_cp = (yy_hold_char); if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = (yy_n_chars) + 2; register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; register char *source = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; (yytext_ptr) = yy_bp; (yy_hold_char) = *yy_cp; (yy_c_buf_p) = yy_cp; } #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput (void) #else static int input (void) #endif { int c; *(yy_c_buf_p) = (yy_hold_char); if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) /* This was really a NUL. */ *(yy_c_buf_p) = '\0'; else { /* need more input */ int offset = (yy_c_buf_p) - (yytext_ptr); ++(yy_c_buf_p); switch ( yy_get_next_buffer( ) ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ bxrestart(bxin ); /*FALLTHROUGH*/ case EOB_ACT_END_OF_FILE: { if ( bxwrap( ) ) return EOF; if ( ! (yy_did_buffer_switch_on_eof) ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: (yy_c_buf_p) = (yytext_ptr) + offset; break; } } } c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ *(yy_c_buf_p) = '\0'; /* preserve bxtext */ (yy_hold_char) = *++(yy_c_buf_p); return c; } #endif /* ifndef YY_NO_INPUT */ /** Immediately switch to a different input stream. * @param input_file A readable stream. * * @note This function does not reset the start condition to @c INITIAL . */ void bxrestart (FILE * input_file ) { if ( ! YY_CURRENT_BUFFER ){ bxensure_buffer_stack (); YY_CURRENT_BUFFER_LVALUE = bx_create_buffer(bxin,YY_BUF_SIZE ); } bx_init_buffer(YY_CURRENT_BUFFER,input_file ); bx_load_buffer_state( ); } /** Switch to a different input buffer. * @param new_buffer The new input buffer. * */ void bx_switch_to_buffer (YY_BUFFER_STATE new_buffer ) { /* TODO. We should be able to replace this entire function body * with * bxpop_buffer_state(); * bxpush_buffer_state(new_buffer); */ bxensure_buffer_stack (); if ( YY_CURRENT_BUFFER == new_buffer ) return; if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } YY_CURRENT_BUFFER_LVALUE = new_buffer; bx_load_buffer_state( ); /* We don't actually know whether we did this switch during * EOF (bxwrap()) processing, but the only time this flag * is looked at is after bxwrap() is called, so it's safe * to go ahead and always set it. */ (yy_did_buffer_switch_on_eof) = 1; } static void bx_load_buffer_state (void) { (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; bxin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; (yy_hold_char) = *(yy_c_buf_p); } /** Allocate and initialize an input buffer state. * @param file A readable stream. * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. * * @return the allocated buffer state. */ YY_BUFFER_STATE bx_create_buffer (FILE * file, int size ) { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) bxalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in bx_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) bxalloc(b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in bx_create_buffer()" ); b->yy_is_our_buffer = 1; bx_init_buffer(b,file ); return b; } /** Destroy the buffer. * @param b a buffer created with bx_create_buffer() * */ void bx_delete_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) bxfree((void *) b->yy_ch_buf ); bxfree((void *) b ); } #ifndef __cplusplus extern int isatty (int ); #endif /* __cplusplus */ /* Initializes or reinitializes a buffer. * This function is sometimes called more than once on the same buffer, * such as during a bxrestart() or at EOF. */ static void bx_init_buffer (YY_BUFFER_STATE b, FILE * file ) { int oerrno = errno; bx_flush_buffer(b ); b->yy_input_file = file; b->yy_fill_buffer = 1; /* If b is the current buffer, then bx_init_buffer was _probably_ * called from bxrestart() or through yy_get_next_buffer. * In that case, we don't want to reset the lineno or column. */ if (b != YY_CURRENT_BUFFER){ b->yy_bs_lineno = 1; b->yy_bs_column = 0; } b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; errno = oerrno; } /** Discard all buffered characters. On the next scan, YY_INPUT will be called. * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. * */ void bx_flush_buffer (YY_BUFFER_STATE b ) { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == YY_CURRENT_BUFFER ) bx_load_buffer_state( ); } /** Pushes the new state onto the stack. The new state becomes * the current state. This function will allocate the stack * if necessary. * @param new_buffer The new state. * */ void bxpush_buffer_state (YY_BUFFER_STATE new_buffer ) { if (new_buffer == NULL) return; bxensure_buffer_stack(); /* This block is copied from bx_switch_to_buffer. */ if ( YY_CURRENT_BUFFER ) { /* Flush out information for old buffer. */ *(yy_c_buf_p) = (yy_hold_char); YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } /* Only push if top exists. Otherwise, replace top. */ if (YY_CURRENT_BUFFER) (yy_buffer_stack_top)++; YY_CURRENT_BUFFER_LVALUE = new_buffer; /* copied from bx_switch_to_buffer. */ bx_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } /** Removes and deletes the top of the stack, if present. * The next element becomes the new top. * */ void bxpop_buffer_state (void) { if (!YY_CURRENT_BUFFER) return; bx_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; if ((yy_buffer_stack_top) > 0) --(yy_buffer_stack_top); if (YY_CURRENT_BUFFER) { bx_load_buffer_state( ); (yy_did_buffer_switch_on_eof) = 1; } } /* Allocates the stack if it does not exist. * Guarantees space for at least one push. */ static void bxensure_buffer_stack (void) { int num_to_alloc; if (!(yy_buffer_stack)) { /* First allocation is just for 2 elements, since we don't know if this * scanner will even need a stack. We use 2 instead of 1 to avoid an * immediate realloc on the next call. */ num_to_alloc = 1; (yy_buffer_stack) = (struct yy_buffer_state**)bxalloc (num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in bxensure_buffer_stack()" ); memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; (yy_buffer_stack_top) = 0; return; } if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ /* Increase the buffer to prepare for a possible push. */ int grow_size = 8 /* arbitrary grow size */; num_to_alloc = (yy_buffer_stack_max) + grow_size; (yy_buffer_stack) = (struct yy_buffer_state**)bxrealloc ((yy_buffer_stack), num_to_alloc * sizeof(struct yy_buffer_state*) ); if ( ! (yy_buffer_stack) ) YY_FATAL_ERROR( "out of dynamic memory in bxensure_buffer_stack()" ); /* zero only the new slots.*/ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); (yy_buffer_stack_max) = num_to_alloc; } } /** Setup the input buffer state to scan directly from a user-specified character buffer. * @param base the character buffer * @param size the size in bytes of the character buffer * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE bx_scan_buffer (char * base, yy_size_t size ) { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) bxalloc(sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in bx_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; bx_switch_to_buffer(b ); return b; } /** Setup the input buffer state to scan a string. The next call to bxlex() will * scan from a @e copy of @a str. * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use * bx_scan_bytes() instead. */ YY_BUFFER_STATE bx_scan_string (yyconst char * yystr ) { return bx_scan_bytes(yystr,strlen(yystr) ); } /** Setup the input buffer state to scan the given bytes. The next call to bxlex() will * scan from a @e copy of @a bytes. * @param bytes the byte buffer to scan * @param len the number of bytes in the buffer pointed to by @a bytes. * * @return the newly allocated buffer state object. */ YY_BUFFER_STATE bx_scan_bytes (yyconst char * yybytes, int _yybytes_len ) { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = _yybytes_len + 2; buf = (char *) bxalloc(n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in bx_scan_bytes()" ); for ( i = 0; i < _yybytes_len; ++i ) buf[i] = yybytes[i]; buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; b = bx_scan_buffer(buf,n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in bx_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif static void yy_fatal_error (yyconst char* msg ) { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up bxtext. */ \ int yyless_macro_arg = (n); \ YY_LESS_LINENO(yyless_macro_arg);\ bxtext[bxleng] = (yy_hold_char); \ (yy_c_buf_p) = bxtext + yyless_macro_arg; \ (yy_hold_char) = *(yy_c_buf_p); \ *(yy_c_buf_p) = '\0'; \ bxleng = yyless_macro_arg; \ } \ while ( 0 ) /* Accessor methods (get/set functions) to struct members. */ /** Get the current line number. * */ int bxget_lineno (void) { return bxlineno; } /** Get the input stream. * */ FILE *bxget_in (void) { return bxin; } /** Get the output stream. * */ FILE *bxget_out (void) { return bxout; } /** Get the length of the current token. * */ int bxget_leng (void) { return bxleng; } /** Get the current token. * */ char *bxget_text (void) { return bxtext; } /** Set the current line number. * @param line_number * */ void bxset_lineno (int line_number ) { bxlineno = line_number; } /** Set the input stream. This does not discard the current * input buffer. * @param in_str A readable stream. * * @see bx_switch_to_buffer */ void bxset_in (FILE * in_str ) { bxin = in_str ; } void bxset_out (FILE * out_str ) { bxout = out_str ; } int bxget_debug (void) { return bx_flex_debug; } void bxset_debug (int bdebug ) { bx_flex_debug = bdebug ; } static int yy_init_globals (void) { /* Initialization is the same as for the non-reentrant scanner. * This function is called from bxlex_destroy(), so don't allocate here. */ (yy_buffer_stack) = 0; (yy_buffer_stack_top) = 0; (yy_buffer_stack_max) = 0; (yy_c_buf_p) = (char *) 0; (yy_init) = 0; (yy_start) = 0; /* Defined in main.c */ #ifdef YY_STDINIT bxin = stdin; bxout = stdout; #else bxin = (FILE *) 0; bxout = (FILE *) 0; #endif /* For future reference: Set errno on error, since we are called by * bxlex_init() */ return 0; } /* bxlex_destroy is for both reentrant and non-reentrant scanners. */ int bxlex_destroy (void) { /* Pop the buffer stack, destroying each element. */ while(YY_CURRENT_BUFFER){ bx_delete_buffer(YY_CURRENT_BUFFER ); YY_CURRENT_BUFFER_LVALUE = NULL; bxpop_buffer_state(); } /* Destroy the stack itself. */ bxfree((yy_buffer_stack) ); (yy_buffer_stack) = NULL; /* Reset the globals. This is important in a non-reentrant scanner so the next time * bxlex() is called, initialization will occur. */ yy_init_globals( ); return 0; } /* * Internal utility routines. */ #ifndef yytext_ptr static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen (yyconst char * s ) { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif void *bxalloc (yy_size_t size ) { return (void *) malloc( size ); } void *bxrealloc (void * ptr, yy_size_t size ) { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } void bxfree (void * ptr ) { free( (char *) ptr ); /* see bxrealloc() for (char *) cast */ } #define YYTABLES_NAME "yytables" #line 252 "lexer.l" int bx_yyinput(char *buf, int max_size) { int len; if (lex_input_size == 0) { fprintf(stderr, "lex: no characters in string input buffer.\n"); exit(1); } len = strlen(lex_input_ptr) + 1; if (len > max_size) len = max_size; memcpy(buf, lex_input_ptr, len); return(len); } void bx_add_lex_input(char *buf) { lex_input_ptr = buf; lex_input_size = strlen(buf); // Since we're parsing from strings, flush out // all current buffer state, so the next read // requests from yyinput bx_flush_buffer( YY_CURRENT_BUFFER ); } #endif /* if BX_DEBUGGER */ bochs-2.6/bx_debug/debug.h0000644000175000017500000003512612020641506015356 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: debug.h 11151 2012-04-24 11:01:59Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2011 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #ifndef BX_DEBUG_H #define BX_DEBUG_H // if including from C parser, need basic types etc #include "config.h" #include "osdep.h" #define BX_DBG_NO_HANDLE 1000 Bit32u crc32(const Bit8u *buf, int len); #if BX_DEBUGGER // some strict C declarations needed by the parser/lexer #ifdef __cplusplus extern "C" { #endif extern Bit32u dbg_cpu; void dbg_printf (const char *fmt, ...); typedef enum { BX_DBG_SREG_ES, BX_DBG_SREG_CS, BX_DBG_SREG_SS, BX_DBG_SREG_DS, BX_DBG_SREG_FS, BX_DBG_SREG_GS } SRegs; #if BX_SUPPORT_X86_64 # define BX_DBG_GEN_REGISTERS 16 #else # define BX_DBG_GEN_REGISTERS 8 #endif typedef enum { BX_DBG_REG8H_AH, BX_DBG_REG8H_CH, BX_DBG_REG8H_DH, BX_DBG_REG8H_BH, } Regs8H; #if BX_SUPPORT_X86_64 typedef enum { BX_DBG_REG8L_AL, BX_DBG_REG8L_CL, BX_DBG_REG8L_DL, BX_DBG_REG8L_BL, BX_DBG_REG8L_SPL, BX_DBG_REG8L_BPL, BX_DBG_REG8L_SIL, BX_DBG_REG8L_DIL, BX_DBG_REG8L_R8, BX_DBG_REG8L_R9, BX_DBG_REG8L_R10, BX_DBG_REG8L_R11, BX_DBG_REG8L_R12, BX_DBG_REG8L_R13, BX_DBG_REG8L_R14, BX_DBG_REG8L_R15 } Regs8L; typedef enum { BX_DBG_REG16_AX, BX_DBG_REG16_CX, BX_DBG_REG16_DX, BX_DBG_REG16_BX, BX_DBG_REG16_SP, BX_DBG_REG16_BP, BX_DBG_REG16_SI, BX_DBG_REG16_DI, BX_DBG_REG16_R8, BX_DBG_REG16_R9, BX_DBG_REG16_R10, BX_DBG_REG16_R11, BX_DBG_REG16_R12, BX_DBG_REG16_R13, BX_DBG_REG16_R14, BX_DBG_REG16_R15 } Regs16; typedef enum { BX_DBG_REG32_EAX, BX_DBG_REG32_ECX, BX_DBG_REG32_EDX, BX_DBG_REG32_EBX, BX_DBG_REG32_ESP, BX_DBG_REG32_EBP, BX_DBG_REG32_ESI, BX_DBG_REG32_EDI, BX_DBG_REG32_R8, BX_DBG_REG32_R9, BX_DBG_REG32_R10, BX_DBG_REG32_R11, BX_DBG_REG32_R12, BX_DBG_REG32_R13, BX_DBG_REG32_R14, BX_DBG_REG32_R15 } Regs32; typedef enum { BX_DBG_REG64_RAX, BX_DBG_REG64_RCX, BX_DBG_REG64_RDX, BX_DBG_REG64_RBX, BX_DBG_REG64_RSP, BX_DBG_REG64_RBP, BX_DBG_REG64_RSI, BX_DBG_REG64_RDI, BX_DBG_REG64_R8, BX_DBG_REG64_R9, BX_DBG_REG64_R10, BX_DBG_REG64_R11, BX_DBG_REG64_R12, BX_DBG_REG64_R13, BX_DBG_REG64_R14, BX_DBG_REG64_R15 } Regs64; #else typedef enum { BX_DBG_REG8L_AL, BX_DBG_REG8L_CL, BX_DBG_REG8L_DL, BX_DBG_REG8L_BL } Regs8L; typedef enum { BX_DBG_REG16_AX, BX_DBG_REG16_CX, BX_DBG_REG16_DX, BX_DBG_REG16_BX, BX_DBG_REG16_SP, BX_DBG_REG16_BP, BX_DBG_REG16_SI, BX_DBG_REG16_DI } Regs16; typedef enum { BX_DBG_REG32_EAX, BX_DBG_REG32_ECX, BX_DBG_REG32_EDX, BX_DBG_REG32_EBX, BX_DBG_REG32_ESP, BX_DBG_REG32_EBP, BX_DBG_REG32_ESI, BX_DBG_REG32_EDI } Regs32; #endif typedef enum { bkRegular, bkAtIP, bkStepOver } BreakpointKind; typedef enum _show_flags { Flag_call = 0x1, Flag_ret = 0x2, Flag_softint = 0x4, Flag_iret = 0x8, Flag_intsig = 0x10, Flag_mode = 0x20, } show_flags_t; // Flex defs extern int bxlex(void); extern char *bxtext; // Using the pointer option rather than array extern int bxwrap(void); void bx_add_lex_input(char *buf); // Yacc defs extern int bxparse(void); extern void bxerror(char *s); // register function for 'info device' command bx_bool bx_dbg_register_debug_info(const char *devname, void *dev); #define EMPTY_ARG (-1) bx_bool bx_dbg_read_linear(unsigned which_cpu, bx_address laddr, unsigned len, Bit8u *buf); Bit16u bx_dbg_get_selector_value(unsigned int seg_no); Bit16u bx_dbg_get_ip (void); Bit32u bx_dbg_get_eip(void); bx_address bx_dbg_get_instruction_pointer(void); Bit8u bx_dbg_get_reg8l_value(unsigned reg); Bit8u bx_dbg_get_reg8h_value(unsigned reg); Bit16u bx_dbg_get_reg16_value(unsigned reg); Bit32u bx_dbg_get_reg32_value(unsigned reg); Bit64u bx_dbg_get_reg64_value(unsigned reg); void bx_dbg_set_reg8l_value(unsigned reg, Bit8u value); void bx_dbg_set_reg8h_value(unsigned reg, Bit8u value); void bx_dbg_set_reg16_value(unsigned reg, Bit16u value); void bx_dbg_set_reg32_value(unsigned reg, Bit32u value); void bx_dbg_set_reg64_value(unsigned reg, Bit64u value); void bx_dbg_load_segreg(unsigned reg, unsigned value); bx_address bx_dbg_get_laddr(Bit16u sel, bx_address ofs); void bx_dbg_step_over_command(void); void bx_dbg_trace_command(bx_bool enable); void bx_dbg_trace_reg_command(bx_bool enable); void bx_dbg_trace_mem_command(bx_bool enable); void bx_dbg_ptime_command(void); void bx_dbg_timebp_command(bx_bool absolute, Bit64u time); #define MAX_CONCURRENT_BPS 5 extern int timebp_timer; extern Bit64u timebp_queue[MAX_CONCURRENT_BPS]; extern int timebp_queue_size; void bx_dbg_modebp_command(void); void bx_dbg_vmexitbp_command(void); void bx_dbg_where_command(void); void bx_dbg_print_string_command(bx_address addr); void bx_dbg_xlate_address(bx_lin_address address); void bx_dbg_show_command(const char*); void bx_dbg_print_stack_command(unsigned nwords); void bx_dbg_print_watchpoints(void); void bx_dbg_watchpoint_continue(bx_bool watch_continue); void bx_dbg_watch(int type, bx_phy_address address, Bit32u len); void bx_dbg_unwatch_all(void); void bx_dbg_unwatch(bx_phy_address handle); void bx_dbg_continue_command(void); void bx_dbg_stepN_command(int cpu, Bit32u count); void bx_dbg_set_auto_disassemble(bx_bool enable); void bx_dbg_disassemble_switch_mode(void); void bx_dbg_disassemble_hex_mode_switch(int mode); void bx_dbg_set_disassemble_size(unsigned size); void bx_dbg_del_breakpoint_command(unsigned handle); void bx_dbg_en_dis_breakpoint_command(unsigned handle, bx_bool enable); bx_bool bx_dbg_en_dis_pbreak(unsigned handle, bx_bool enable); bx_bool bx_dbg_en_dis_lbreak(unsigned handle, bx_bool enable); bx_bool bx_dbg_en_dis_vbreak(unsigned handle, bx_bool enable); bx_bool bx_dbg_del_pbreak(unsigned handle); bx_bool bx_dbg_del_lbreak(unsigned handle); bx_bool bx_dbg_del_vbreak(unsigned handle); int bx_dbg_vbreakpoint_command(BreakpointKind bk, Bit32u cs, bx_address eip); int bx_dbg_lbreakpoint_command(BreakpointKind bk, bx_address laddress); int bx_dbg_pbreakpoint_command(BreakpointKind bk, bx_phy_address paddress); void bx_dbg_info_bpoints_command(void); void bx_dbg_quit_command(void); #define BX_INFO_GENERAL_PURPOSE_REGS 0x01 /* bitmasks - choices for bx_dbg_info_registers_command */ #define BX_INFO_FPU_REGS 0x02 #define BX_INFO_MMX_REGS 0x04 #define BX_INFO_SSE_REGS 0x08 #define BX_INFO_AVX_REGS 0x10 void bx_dbg_info_registers_command(int); void bx_dbg_info_ivt_command(unsigned from, unsigned to); void bx_dbg_info_idt_command(unsigned from, unsigned to); void bx_dbg_info_gdt_command(unsigned from, unsigned to); void bx_dbg_info_ldt_command(unsigned from, unsigned to); void bx_dbg_info_tss_command(void); void bx_dbg_info_debug_regs_command(void); void bx_dbg_info_control_regs_command(void); void bx_dbg_info_segment_regs_command(void); void bx_dbg_info_flags(void); void bx_dbg_info_linux_command(void); void bx_dbg_examine_command(const char *command, const char *format, bx_bool format_passed, bx_address addr, bx_bool addr_passed); Bit32u bx_dbg_lin_indirect(bx_address addr); Bit32u bx_dbg_phy_indirect(bx_phy_address addr); void bx_dbg_writemem_command(const char *filename, bx_address laddr, unsigned len); void bx_dbg_setpmem_command(bx_phy_address addr, unsigned len, Bit32u val); void bx_dbg_query_command(const char *); void bx_dbg_take_command(const char *, unsigned n); void bx_dbg_disassemble_current(const char *); void bx_dbg_disassemble_command(const char *, Bit64u from, Bit64u to); void bx_dbg_instrument_command(const char *); void bx_dbg_doit_command(unsigned); void bx_dbg_crc_command(bx_phy_address addr1, bx_phy_address addr2); void bx_dbg_linux_syscall(unsigned which_cpu); void bx_dbg_info_device(const char *, const char *); void bx_dbg_print_help(void); void bx_dbg_calc_command(Bit64u value); void bx_dbg_dump_table(void); // callbacks from CPU void bx_dbg_exception(unsigned cpu, Bit8u vector, Bit16u error_code); void bx_dbg_interrupt(unsigned cpu, Bit8u vector, Bit16u error_code); void bx_dbg_halt(unsigned cpu); // memory trace callbacks from CPU, len=1,2,4 or 8 void bx_dbg_lin_memory_access(unsigned cpu, bx_address lin, bx_phy_address phy, unsigned len, unsigned pl, unsigned rw, Bit8u *data); void bx_dbg_phy_memory_access(unsigned cpu, bx_phy_address phy, unsigned len, unsigned rw, unsigned attr, Bit8u *data); // check memory access for watchpoints void bx_dbg_check_memory_watchpoints(unsigned cpu, bx_phy_address phy, unsigned len, unsigned rw); // commands that work with Bochs param tree void bx_dbg_restore_command(const char *param_name, const char *path); void bx_dbg_show_param_command(const char *param); int bx_dbg_show_symbolic(void); void bx_dbg_set_symbol_command(const char *symbol, Bit32u val); const char* bx_dbg_symbolic_address(Bit32u context, Bit32u eip, Bit32u base); const char* bx_dbg_symbolic_address_16bit(Bit32u eip, Bit32u cs); int bx_dbg_symbol_command(const char* filename, bx_bool global, Bit32u offset); void bx_dbg_info_symbols_command(const char *Symbol); int bx_dbg_lbreakpoint_symbol_command(const char *Symbol); Bit32u bx_dbg_get_symbol_value(const char *Symbol); const char* bx_dbg_disasm_symbolic_address(Bit32u eip, Bit32u base); #ifdef __cplusplus } #endif // the rest for C++ #ifdef __cplusplus typedef enum { STOP_NO_REASON = 0, STOP_TIME_BREAK_POINT, STOP_READ_WATCH_POINT, STOP_WRITE_WATCH_POINT, STOP_MAGIC_BREAK_POINT, STOP_MODE_BREAK_POINT, STOP_VMEXIT_BREAK_POINT, STOP_CPU_HALTED, } stop_reason_t; typedef enum { BREAK_POINT_MAGIC, BREAK_POINT_READ, BREAK_POINT_WRITE, BREAK_POINT_TIME } break_point_t; #define BX_DBG_REG_EIP 10 #define BX_DBG_REG_EFLAGS 11 #define BX_DBG_REG_CS 20 #define BX_DBG_REG_SS 21 #define BX_DBG_REG_DS 22 #define BX_DBG_REG_ES 23 #define BX_DBG_REG_FS 24 #define BX_DBG_REG_GS 25 #define BX_DBG_REG_CR0 30 #define BX_DBG_REG_CR2 32 #define BX_DBG_REG_CR3 33 #define BX_DBG_REG_CR4 34 #define BX_DBG_PENDING_DMA 1 #define BX_DBG_PENDING_IRQ 2 void bx_debug_break(void); void bx_dbg_exit(int code); #if BX_DBG_EXTENSIONS int bx_dbg_extensions(char *command); #else #define bx_dbg_extensions(command) 0 #endif // // code for guards... // #define BX_DBG_GUARD_IADDR_VIR 0x0001 #define BX_DBG_GUARD_IADDR_LIN 0x0002 #define BX_DBG_GUARD_IADDR_PHY 0x0004 #define BX_DBG_GUARD_IADDR_ALL (BX_DBG_GUARD_IADDR_VIR | \ BX_DBG_GUARD_IADDR_LIN | \ BX_DBG_GUARD_IADDR_PHY) #define BX_DBG_GUARD_ICOUNT 0x0010 typedef struct { unsigned guard_for; // instruction address breakpoints struct { #if (BX_DBG_MAX_VIR_BPOINTS > 0) unsigned num_virtual; struct { Bit32u cs; // only use 16 bits bx_address eip; unsigned bpoint_id; bx_bool enabled; } vir[BX_DBG_MAX_VIR_BPOINTS]; #endif #if (BX_DBG_MAX_LIN_BPOINTS > 0) unsigned num_linear; struct { bx_address addr; unsigned bpoint_id; bx_bool enabled; } lin[BX_DBG_MAX_LIN_BPOINTS]; #endif #if (BX_DBG_MAX_PHY_BPOINTS > 0) unsigned num_physical; struct { bx_phy_address addr; unsigned bpoint_id; bx_bool enabled; } phy[BX_DBG_MAX_PHY_BPOINTS]; #endif } iaddr; // user typed Ctrl-C, requesting simulator stop at next convinient spot volatile bx_bool interrupt_requested; // booleans to control whether simulator should report events // to debug controller struct { bx_bool irq; bx_bool a20; bx_bool io; bx_bool dma; } report; struct { bx_bool irq; // should process IRQs asynchronously bx_bool dma; // should process DMAs asynchronously } async; #define BX_DBG_ASYNC_PENDING_A20 0x01 #define BX_DBG_ASYNC_PENDING_RESET 0x02 #define BX_DBG_ASYNC_PENDING_NMI 0x04 // Asynchronous changes which are pending. These are Q'd by // the debugger, as the master simulator is notified of a pending // async change. At the simulator's next point, where it checks for // such events, it notifies the debugger with acknowlegement. This // field contains a logically or'd list of all events which should // be checked, and ack'd. struct { unsigned which; // logical OR of above constants bx_bool a20; bx_bool reset; bx_bool nmi; } async_changes_pending; } bx_guard_t; // working information for each simulator to update when a guard // is reached (found) typedef struct bx_guard_found_t { unsigned guard_found; Bit64u icount_max; // stop after completing this many instructions unsigned iaddr_index; Bit32u cs; // cs:eip and linear addr of instruction at guard point bx_address eip; bx_address laddr; // 00 - 16 bit, 01 - 32 bit, 10 - 64-bit, 11 - illegal unsigned code_32_64; // CS seg size at guard point } bx_guard_found_t; struct bx_watchpoint { bx_phy_address addr; Bit32u len; }; extern unsigned num_write_watchpoints; extern unsigned num_read_watchpoints; extern bx_watchpoint write_watchpoint[BX_DBG_MAX_WATCHPONTS]; extern bx_watchpoint read_watchpoint[BX_DBG_MAX_WATCHPONTS]; extern bx_guard_t bx_guard; #define IS_CODE_32(code_32_64) ((code_32_64 & 1) != 0) #define IS_CODE_64(code_32_64) ((code_32_64 & 2) != 0) void bx_dbg_init_infile(void); int bx_dbg_set_rcfile(const char *rcfile); int bx_dbg_main(void); void bx_dbg_user_input_loop(void); void bx_dbg_interpret_line(char *cmd); typedef struct { Bit16u sel; Bit32u des_l, des_h, valid; #if BX_SUPPORT_X86_64 Bit32u dword3; #endif } bx_dbg_sreg_t; typedef struct { bx_address base; Bit16u limit; } bx_dbg_global_sreg_t; void bx_dbg_dma_report(bx_phy_address addr, unsigned len, unsigned what, Bit32u val); void bx_dbg_iac_report(unsigned vector, unsigned irq); void bx_dbg_a20_report(unsigned val); void bx_dbg_io_report(Bit32u port, unsigned size, unsigned op, Bit32u val); void bx_dbg_disassemble_current(int which_cpu, int print_time); #endif // #ifdef __cplusplus #endif // #if BX_DEBUGGER #endif bochs-2.6/bx_debug/Makefile.in0000644000175000017500000001065312020641506016162 0ustar guillemguillem# Copyright (C) 2001 The Bochs Project # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ top_builddir = .. top_srcdir = @top_srcdir@ SHELL = @SHELL@ @SET_MAKE@ CC = @CC@ CFLAGS = @CFLAGS@ @GUI_CFLAGS@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ @GUI_CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ # Definitely use flex. Use flex version >= 2.5.4 # Flex version 2.5.2 was reported not to work LEX = flex YACC = yacc # =========================================================== # end of configurable options # =========================================================== BX_OBJS = \ dbg_main.o \ symbols.o \ linux.o \ BX_PARSER_OBJS = \ parser.o \ lexer.o BX_INCLUDES = debug.h BX_INCDIRS = -I.. -I$(srcdir)/.. -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@ -I. -I$(srcdir)/. all: libdebug.a .@CPP_SUFFIX@.o: $(CXX) @DASH@c $(BX_INCDIRS) $(CXXFLAGS) @CXXFP@$< @OFP@$@ .c.o: $(CC) @DASH@c $(BX_INCDIRS) $(CFLAGS) @CFP@$< @OFP@$@ libdebug.a: $(BX_OBJS) $(BX_PARSER_OBJS) @RMCOMMAND@ libdebug.a @MAKELIB@ $(BX_OBJS) $(BX_PARSER_OBJS) $(RANLIB) libdebug.a $(BX_OBJS): $(BX_INCLUDES) clean: @RMCOMMAND@ *.o @RMCOMMAND@ libdebug.a dist-clean: clean @RMCOMMAND@ Makefile parse-clean: @RMCOMMAND@ -f lexer.c @RMCOMMAND@ -f parser.c @RMCOMMAND@ -f parser.h dbg_main.o: debug.h @NO_FLEX_YACC@parser.c: parser.y @NO_FLEX_YACC@ @/bin/rm -f y.tab.c parser.c @NO_FLEX_YACC@ @/bin/rm -f y.tab.h parser.h @NO_FLEX_YACC@ $(YACC) -p bx -d $< @NO_FLEX_YACC@ @/bin/mv -f y.tab.c parser.c @NO_FLEX_YACC@ @/bin/mv -f y.tab.h parser.h @NO_FLEX_YACC@ @echo '#endif /* if BX_DEBUGGER */' >> parser.c @NO_FLEX_YACC@ @echo '/* The #endif is appended by the makefile after running yacc. */' >> parser.c @NO_FLEX_YACC@lexer.c: lexer.l @NO_FLEX_YACC@ $(LEX) -Pbx -t $< > lexer.c ########################################### # dependencies generated by # gcc -MM -I. -I.. -I../instrument/stubs *.c *.cc | sed 's/\.cc/.@CPP_SUFFIX@/g' ########################################### lexer.o: lexer.c debug.h ../config.h ../osdep.h parser.o: parser.c debug.h ../config.h ../osdep.h dbg_main.o: dbg_main.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h \ ../gui/siminterface.h ../gui/paramtree.h ../memory/memory.h \ ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ ../instrument/stubs/instrument.h ../param_names.h ../cpu/cpu.h \ ../cpu/cpuid.h ../cpu/crregs.h ../cpu/descriptor.h \ ../cpu/instr.h ../cpu/ia_opcodes.h ../cpu/lazy_flags.h ../cpu/icache.h \ ../cpu/apic.h ../cpu/i387.h ../fpu/softfloat.h ../fpu/tag_w.h \ ../fpu/status_w.h ../fpu/control_w.h ../cpu/xmm.h ../iodev/iodev.h linux.o: linux.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \ ../config.h ../osdep.h ../gui/siminterface.h \ ../gui/paramtree.h ../memory/memory.h ../pc_system.h ../plugin.h \ ../extplugin.h ../ltdl.h ../gui/gui.h ../instrument/stubs/instrument.h \ ../cpu/cpu.h ../cpu/cpuid.h ../cpu/crregs.h \ ../cpu/descriptor.h ../cpu/instr.h ../cpu/ia_opcodes.h \ ../cpu/lazy_flags.h ../cpu/icache.h ../cpu/apic.h ../cpu/i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ ../cpu/xmm.h symbols.o: symbols.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \ ../bx_debug/debug.h ../config.h ../osdep.h \ ../gui/siminterface.h ../gui/paramtree.h ../memory/memory.h \ ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \ ../instrument/stubs/instrument.h ../cpu/cpu.h ../cpu/cpuid.h \ ../cpu/crregs.h ../cpu/descriptor.h ../cpu/instr.h ../cpu/ia_opcodes.h \ ../cpu/lazy_flags.h ../cpu/icache.h ../cpu/apic.h ../cpu/i387.h \ ../fpu/softfloat.h ../fpu/tag_w.h ../fpu/status_w.h ../fpu/control_w.h \ ../cpu/xmm.h bochs-2.6/bx_debug/lexer.l0000644000175000017500000003426512020641506015416 0ustar guillemguillem%{ ///////////////////////////////////////////////////////////////////////// // $Id: lexer.l 11151 2012-04-24 11:01:59Z sshwarts $ ///////////////////////////////////////////////////////////////////////// #include #include #ifdef WIN32 #include #define YY_NO_UNISTD_H #endif #include "debug.h" #if BX_DEBUGGER #include "parser.h" int bx_yyinput(char *buf, int max_size); #undef YY_INPUT #define YY_INPUT(buf, ret, max_size) (ret = bx_yyinput(buf, max_size)) static char *lex_input_ptr = NULL; static unsigned lex_input_size = 0; #if BX_SUPPORT_X86_64 #define LONG_MODE_8BL_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_8BL_REG); } #define LONG_MODE_16B_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_16B_REG); } #define LONG_MODE_32B_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_32B_REG); } #define LONG_MODE_64B_REG(reg) \ { bxlval.uval = reg; return(BX_TOKEN_64B_REG); } #else #define LONG_MODE_8BL_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #define LONG_MODE_16B_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #define LONG_MODE_32B_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #define LONG_MODE_64B_REG(reg) \ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } #endif %} %x EXAMINE %x DISASM %% <*>[ \t]+ ; // eat up whitespace set { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SET); } on { bxlval.bval = 1; return(BX_TOKEN_ON); } off { bxlval.bval = 0; return(BX_TOKEN_OFF); } crc { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CRC); } c | cont | continue { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CONTINUE); } step | s { bxlval.sval = strdup(bxtext); return(BX_TOKEN_STEPN); } next | n | p { bxlval.sval = strdup(bxtext); return(BX_TOKEN_STEP_OVER); } blist { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LIST_BREAK); } vb|vbreak { bxlval.sval = strdup(bxtext); return(BX_TOKEN_VBREAKPOINT); } lb|lbreak { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LBREAKPOINT); } break | b|pb | pbreak { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PBREAKPOINT); } info { bxlval.sval = strdup(bxtext); return(BX_TOKEN_INFO); } cr | creg { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CONTROL_REGS); } dr | dreg { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DEBUG_REGS); } sreg { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SEGMENT_REGS); } r { bxlval.sval = strdup(bxtext); return(BX_TOKEN_R); } reg|regs | registers { bxlval.sval = strdup(bxtext); return(BX_TOKEN_REGS); } fp|fpu { bxlval.sval = strdup(bxtext); return(BX_TOKEN_FPU); } sse|xmm { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SSE); } ymm { bxlval.sval = strdup(bxtext); return(BX_TOKEN_AVX); } mmx { bxlval.sval = strdup(bxtext); return(BX_TOKEN_MMX); } cpu { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CPU); } idt { bxlval.sval = strdup(bxtext); return(BX_TOKEN_IDT); } ivt { bxlval.sval = strdup(bxtext); return(BX_TOKEN_IVT); } gdt { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GDT); } ldt { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LDT); } tss { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TSS); } tab { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TAB); } linux { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LINUX); } delete | del | d { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DEL_BREAKPOINT); } bpe { bxlval.sval = strdup(bxtext); return(BX_TOKEN_ENABLE_BREAKPOINT); } bpd { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DISABLE_BREAKPOINT); } quit | exit | q { bxlval.sval = strdup(bxtext); return(BX_TOKEN_QUIT); } x | xp { BEGIN(EXAMINE); bxlval.sval = strdup(bxtext); return(BX_TOKEN_EXAMINE); } restore { bxlval.sval = strdup(bxtext); return(BX_TOKEN_RESTORE); } writemem { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WRITEMEM); } setpmem { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SETPMEM); } query { bxlval.sval = strdup(bxtext); return(BX_TOKEN_QUERY); } pending { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PENDING); } take { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TAKE); } dma { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DMA); } irq { bxlval.sval = strdup(bxtext); return(BX_TOKEN_IRQ); } u | disasm { BEGIN(DISASM); bxlval.sval = strdup(bxtext); return(BX_TOKEN_DISASM); } hex { bxlval.sval = strdup(bxtext); return(BX_TOKEN_HEX); } instrument { bxlval.sval = strdup(bxtext); return(BX_TOKEN_INSTRUMENT); } stop { bxlval.sval = strdup(bxtext); return(BX_TOKEN_STOP); } doit { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DOIT); } trace { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACE); } trace-reg { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACEREG); } trace-mem { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TRACEMEM); } switch-mode { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SWITCH_MODE); } size { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SIZE); } ptime { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PTIME); } sb { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TIMEBP); } sba { bxlval.sval = strdup(bxtext); return(BX_TOKEN_TIMEBP_ABSOLUTE); } modebp { bxlval.sval = strdup(bxtext); return(BX_TOKEN_MODEBP); } vmexitbp { bxlval.sval = strdup(bxtext); return(BX_TOKEN_VMEXITBP); } print-stack { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PRINT_STACK); } watch { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WATCH); } unwatch { bxlval.sval = strdup(bxtext); return(BX_TOKEN_UNWATCH); } read { bxlval.sval = strdup(bxtext); return(BX_TOKEN_READ); } w|write { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WRITE); } show { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SHOW); } ldsym { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LOAD_SYMBOLS); } symbols { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SYMBOLS); } slist { bxlval.sval = strdup(bxtext); return(BX_TOKEN_LIST_SYMBOLS); } global { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GLOBAL); } where { bxlval.sval = strdup(bxtext); return(BX_TOKEN_WHERE); } print-string { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PRINT_STRING); } page { bxlval.sval = strdup(bxtext); return(BX_TOKEN_PAGE); } vga { bxlval.sval = strdup(bxtext); return(BX_TOKEN_VGA); } device { bxlval.sval = strdup(bxtext); return(BX_TOKEN_DEVICE); } all { bxlval.sval = strdup(bxtext); return(BX_TOKEN_ALL); } al { bxlval.uval = BX_DBG_REG8L_AL; return(BX_TOKEN_8BL_REG);} bl { bxlval.uval = BX_DBG_REG8L_BL; return(BX_TOKEN_8BL_REG);} cl { bxlval.uval = BX_DBG_REG8L_CL; return(BX_TOKEN_8BL_REG);} dl { bxlval.uval = BX_DBG_REG8L_DL; return(BX_TOKEN_8BL_REG);} sil { LONG_MODE_8BL_REG(BX_DBG_REG8L_SIL); } dil { LONG_MODE_8BL_REG(BX_DBG_REG8L_DIL); } spl { LONG_MODE_8BL_REG(BX_DBG_REG8L_SPL); } bpl { LONG_MODE_8BL_REG(BX_DBG_REG8L_BPL); } r8b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R8); } r9b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R9); } r10b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R10); } r11b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R11); } r12b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R12); } r13b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R13); } r14b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R14); } r15b { LONG_MODE_8BL_REG(BX_DBG_REG8L_R15); } ah { bxlval.uval = BX_DBG_REG8H_AH; return(BX_TOKEN_8BH_REG);} bh { bxlval.uval = BX_DBG_REG8H_BH; return(BX_TOKEN_8BH_REG);} ch { bxlval.uval = BX_DBG_REG8H_CH; return(BX_TOKEN_8BH_REG);} dh { bxlval.uval = BX_DBG_REG8H_DH; return(BX_TOKEN_8BH_REG);} ax { bxlval.uval = BX_DBG_REG16_AX; return(BX_TOKEN_16B_REG);} bx { bxlval.uval = BX_DBG_REG16_BX; return(BX_TOKEN_16B_REG);} cx { bxlval.uval = BX_DBG_REG16_CX; return(BX_TOKEN_16B_REG);} dx { bxlval.uval = BX_DBG_REG16_DX; return(BX_TOKEN_16B_REG);} si { bxlval.uval = BX_DBG_REG16_SI; return(BX_TOKEN_16B_REG);} di { bxlval.uval = BX_DBG_REG16_DI; return(BX_TOKEN_16B_REG);} bp { bxlval.uval = BX_DBG_REG16_BP; return(BX_TOKEN_16B_REG);} sp { bxlval.uval = BX_DBG_REG16_SP; return(BX_TOKEN_16B_REG);} r8w { LONG_MODE_16B_REG(BX_DBG_REG16_R8); } r9w { LONG_MODE_16B_REG(BX_DBG_REG16_R9); } r10w { LONG_MODE_16B_REG(BX_DBG_REG16_R10); } r11w { LONG_MODE_16B_REG(BX_DBG_REG16_R11); } r12w { LONG_MODE_16B_REG(BX_DBG_REG16_R12); } r13w { LONG_MODE_16B_REG(BX_DBG_REG16_R13); } r14w { LONG_MODE_16B_REG(BX_DBG_REG16_R14); } r15w { LONG_MODE_16B_REG(BX_DBG_REG16_R15); } eax { bxlval.uval = BX_DBG_REG32_EAX; return(BX_TOKEN_32B_REG);} ebx { bxlval.uval = BX_DBG_REG32_EBX; return(BX_TOKEN_32B_REG);} ecx { bxlval.uval = BX_DBG_REG32_ECX; return(BX_TOKEN_32B_REG);} edx { bxlval.uval = BX_DBG_REG32_EDX; return(BX_TOKEN_32B_REG);} esi { bxlval.uval = BX_DBG_REG32_ESI; return(BX_TOKEN_32B_REG);} edi { bxlval.uval = BX_DBG_REG32_EDI; return(BX_TOKEN_32B_REG);} ebp { bxlval.uval = BX_DBG_REG32_EBP; return(BX_TOKEN_32B_REG);} esp { bxlval.uval = BX_DBG_REG32_ESP; return(BX_TOKEN_32B_REG);} r8d { LONG_MODE_32B_REG(BX_DBG_REG32_R8); } r9d { LONG_MODE_32B_REG(BX_DBG_REG32_R9); } r10d { LONG_MODE_32B_REG(BX_DBG_REG32_R10); } r11d { LONG_MODE_32B_REG(BX_DBG_REG32_R11); } r12d { LONG_MODE_32B_REG(BX_DBG_REG32_R12); } r13d { LONG_MODE_32B_REG(BX_DBG_REG32_R13); } r14d { LONG_MODE_32B_REG(BX_DBG_REG32_R14); } r15d { LONG_MODE_32B_REG(BX_DBG_REG32_R15); } rax { LONG_MODE_64B_REG(BX_DBG_REG64_RAX); } rbx { LONG_MODE_64B_REG(BX_DBG_REG64_RBX); } rcx { LONG_MODE_64B_REG(BX_DBG_REG64_RCX); } rdx { LONG_MODE_64B_REG(BX_DBG_REG64_RDX); } rsi { LONG_MODE_64B_REG(BX_DBG_REG64_RSI); } rdi { LONG_MODE_64B_REG(BX_DBG_REG64_RDI); } rsp { LONG_MODE_64B_REG(BX_DBG_REG64_RSP); } rbp { LONG_MODE_64B_REG(BX_DBG_REG64_RBP); } r8 { LONG_MODE_64B_REG(BX_DBG_REG64_R8); } r9 { LONG_MODE_64B_REG(BX_DBG_REG64_R9); } r10 { LONG_MODE_64B_REG(BX_DBG_REG64_R10); } r11 { LONG_MODE_64B_REG(BX_DBG_REG64_R11); } r12 { LONG_MODE_64B_REG(BX_DBG_REG64_R12); } r13 { LONG_MODE_64B_REG(BX_DBG_REG64_R13); } r14 { LONG_MODE_64B_REG(BX_DBG_REG64_R14); } r15 { LONG_MODE_64B_REG(BX_DBG_REG64_R15); } ip { return(BX_TOKEN_REG_IP); } eip { return(BX_TOKEN_REG_EIP);} rip { return(BX_TOKEN_REG_RIP);} cs { bxlval.uval = BX_DBG_SREG_CS; return(BX_TOKEN_CS); } es { bxlval.uval = BX_DBG_SREG_ES; return(BX_TOKEN_ES); } ss { bxlval.uval = BX_DBG_SREG_SS; return(BX_TOKEN_SS); } ds { bxlval.uval = BX_DBG_SREG_DS; return(BX_TOKEN_DS); } fs { bxlval.uval = BX_DBG_SREG_FS; return(BX_TOKEN_FS); } gs { bxlval.uval = BX_DBG_SREG_GS; return(BX_TOKEN_GS); } flags|eflags { bxlval.uval = 0; return (BX_TOKEN_FLAGS); } h|help { bxlval.sval = strdup(bxtext); return(BX_TOKEN_HELP); } \? | calc { bxlval.sval = strdup(bxtext); return(BX_TOKEN_CALC); } \/[0-9]+ { BEGIN(INITIAL); bxlval.sval = strdup(bxtext); return(BX_TOKEN_XFORMAT); } \/[0-9]*[mxduotcsibhwg]+ { BEGIN(INITIAL); bxlval.sval = strdup(bxtext); return(BX_TOKEN_XFORMAT); } \/[0-9]+ { BEGIN(INITIAL); bxlval.sval = strdup(bxtext); return(BX_TOKEN_DISFORMAT); } "+" { return ('+'); } "-" { return ('-'); } "*" { return ('*'); } "/" { return ('/'); } ">>" { return (BX_TOKEN_RSHIFT); } "<<" { return (BX_TOKEN_LSHIFT); } "&" { return ('&'); } "|" { return ('|'); } "^" { return ('^'); } "!" { return ('!'); } "@" { return ('@'); } "(" { return ('('); } ")" { return (')'); } \'([^\\\'\n]|(\\.))*\' | /* throw away leading and trailing \" */ \"([^\\\"\n]|(\\.))*\" { bxlval.sval = strdup(bxtext+1); bxlval.sval[strlen(bxlval.sval)-1] = 0; return(BX_TOKEN_STRING); } 0x[0-9a-fA-F]+ { bxlval.uval = strtoull(bxtext, NULL, 16); return(BX_TOKEN_NUMERIC); } 0[0-7]+ { bxlval.uval = strtoull(bxtext, NULL, 8); return(BX_TOKEN_NUMERIC); } [0-9]+ { bxlval.uval = strtoull(bxtext, NULL, 10); return(BX_TOKEN_NUMERIC); } [a-z-]+ { bxlval.sval = strdup(bxtext); return(BX_TOKEN_COMMAND); } $[a-zA-Z_][a-zA-Z0-9_]* { bxlval.sval = strdup(bxtext); return(BX_TOKEN_SYMBOLNAME); } [A-Za-z_][A-Za-z0-9_]* { bxlval.sval = strdup(bxtext); return(BX_TOKEN_GENERIC); } <*>";" { return ('\n'); } <*>\n { return ('\n'); } [#][^\n]* ; // eat up comments '//' . { return(bxtext[0]); } . { BEGIN(INITIAL); unput(*bxtext); } %% int bx_yyinput(char *buf, int max_size) { int len; if (lex_input_size == 0) { fprintf(stderr, "lex: no characters in string input buffer.\n"); exit(1); } len = strlen(lex_input_ptr) + 1; if (len > max_size) len = max_size; memcpy(buf, lex_input_ptr, len); return(len); } void bx_add_lex_input(char *buf) { lex_input_ptr = buf; lex_input_size = strlen(buf); // Since we're parsing from strings, flush out // all current buffer state, so the next read // requests from yyinput bx_flush_buffer( YY_CURRENT_BUFFER ); } #endif /* if BX_DEBUGGER */ bochs-2.6/bx_debug/parser.c0000644000175000017500000043475012020641506015565 0ustar guillemguillem/* A Bison parser, made by GNU Bison 2.5. */ /* Bison implementation for Yacc-like parsers in C Copyright (C) 1984, 1989-1990, 2000-2011 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* As a special exception, you may create a larger work that contains part or all of the Bison parser skeleton and distribute that work under terms of your choice, so long as that work isn't itself a parser generator using the skeleton or a modified version thereof as a parser skeleton. Alternatively, if you modify or redistribute the parser skeleton itself, you may (at your option) remove this special exception, which will cause the skeleton and the resulting Bison output files to be licensed under the GNU General Public License without this special exception. This special exception was added by the Free Software Foundation in version 2.2 of Bison. */ /* C LALR(1) parser skeleton written by Richard Stallman, by simplifying the original so-called "semantic" parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.5" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Push parsers. */ #define YYPUSH 0 /* Pull parsers. */ #define YYPULL 1 /* Using locations. */ #define YYLSP_NEEDED 0 /* Substitute the variable and function names. */ #define yyparse bxparse #define yylex bxlex #define yyerror bxerror #define yylval bxlval #define yychar bxchar #define yydebug bxdebug #define yynerrs bxnerrs /* Copy the first part of user declarations. */ /* Line 268 of yacc.c */ #line 5 "parser.y" #include #include #include "debug.h" #if BX_DEBUGGER /* Line 268 of yacc.c */ #line 88 "y.tab.c" /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { BX_TOKEN_8BH_REG = 258, BX_TOKEN_8BL_REG = 259, BX_TOKEN_16B_REG = 260, BX_TOKEN_32B_REG = 261, BX_TOKEN_64B_REG = 262, BX_TOKEN_CS = 263, BX_TOKEN_ES = 264, BX_TOKEN_SS = 265, BX_TOKEN_DS = 266, BX_TOKEN_FS = 267, BX_TOKEN_GS = 268, BX_TOKEN_FLAGS = 269, BX_TOKEN_ON = 270, BX_TOKEN_OFF = 271, BX_TOKEN_CONTINUE = 272, BX_TOKEN_STEPN = 273, BX_TOKEN_STEP_OVER = 274, BX_TOKEN_SET = 275, BX_TOKEN_DEBUGGER = 276, BX_TOKEN_LIST_BREAK = 277, BX_TOKEN_VBREAKPOINT = 278, BX_TOKEN_LBREAKPOINT = 279, BX_TOKEN_PBREAKPOINT = 280, BX_TOKEN_DEL_BREAKPOINT = 281, BX_TOKEN_ENABLE_BREAKPOINT = 282, BX_TOKEN_DISABLE_BREAKPOINT = 283, BX_TOKEN_INFO = 284, BX_TOKEN_QUIT = 285, BX_TOKEN_R = 286, BX_TOKEN_REGS = 287, BX_TOKEN_CPU = 288, BX_TOKEN_FPU = 289, BX_TOKEN_MMX = 290, BX_TOKEN_SSE = 291, BX_TOKEN_AVX = 292, BX_TOKEN_IDT = 293, BX_TOKEN_IVT = 294, BX_TOKEN_GDT = 295, BX_TOKEN_LDT = 296, BX_TOKEN_TSS = 297, BX_TOKEN_TAB = 298, BX_TOKEN_ALL = 299, BX_TOKEN_LINUX = 300, BX_TOKEN_DEBUG_REGS = 301, BX_TOKEN_CONTROL_REGS = 302, BX_TOKEN_SEGMENT_REGS = 303, BX_TOKEN_EXAMINE = 304, BX_TOKEN_XFORMAT = 305, BX_TOKEN_DISFORMAT = 306, BX_TOKEN_RESTORE = 307, BX_TOKEN_WRITEMEM = 308, BX_TOKEN_SETPMEM = 309, BX_TOKEN_SYMBOLNAME = 310, BX_TOKEN_QUERY = 311, BX_TOKEN_PENDING = 312, BX_TOKEN_TAKE = 313, BX_TOKEN_DMA = 314, BX_TOKEN_IRQ = 315, BX_TOKEN_HEX = 316, BX_TOKEN_DISASM = 317, BX_TOKEN_INSTRUMENT = 318, BX_TOKEN_STRING = 319, BX_TOKEN_STOP = 320, BX_TOKEN_DOIT = 321, BX_TOKEN_CRC = 322, BX_TOKEN_TRACE = 323, BX_TOKEN_TRACEREG = 324, BX_TOKEN_TRACEMEM = 325, BX_TOKEN_SWITCH_MODE = 326, BX_TOKEN_SIZE = 327, BX_TOKEN_PTIME = 328, BX_TOKEN_TIMEBP_ABSOLUTE = 329, BX_TOKEN_TIMEBP = 330, BX_TOKEN_MODEBP = 331, BX_TOKEN_VMEXITBP = 332, BX_TOKEN_PRINT_STACK = 333, BX_TOKEN_WATCH = 334, BX_TOKEN_UNWATCH = 335, BX_TOKEN_READ = 336, BX_TOKEN_WRITE = 337, BX_TOKEN_SHOW = 338, BX_TOKEN_LOAD_SYMBOLS = 339, BX_TOKEN_SYMBOLS = 340, BX_TOKEN_LIST_SYMBOLS = 341, BX_TOKEN_GLOBAL = 342, BX_TOKEN_WHERE = 343, BX_TOKEN_PRINT_STRING = 344, BX_TOKEN_NUMERIC = 345, BX_TOKEN_PAGE = 346, BX_TOKEN_HELP = 347, BX_TOKEN_CALC = 348, BX_TOKEN_VGA = 349, BX_TOKEN_DEVICE = 350, BX_TOKEN_COMMAND = 351, BX_TOKEN_GENERIC = 352, BX_TOKEN_RSHIFT = 353, BX_TOKEN_LSHIFT = 354, BX_TOKEN_REG_IP = 355, BX_TOKEN_REG_EIP = 356, BX_TOKEN_REG_RIP = 357, INDIRECT = 358, NEG = 359, NOT = 360 }; #endif /* Tokens. */ #define BX_TOKEN_8BH_REG 258 #define BX_TOKEN_8BL_REG 259 #define BX_TOKEN_16B_REG 260 #define BX_TOKEN_32B_REG 261 #define BX_TOKEN_64B_REG 262 #define BX_TOKEN_CS 263 #define BX_TOKEN_ES 264 #define BX_TOKEN_SS 265 #define BX_TOKEN_DS 266 #define BX_TOKEN_FS 267 #define BX_TOKEN_GS 268 #define BX_TOKEN_FLAGS 269 #define BX_TOKEN_ON 270 #define BX_TOKEN_OFF 271 #define BX_TOKEN_CONTINUE 272 #define BX_TOKEN_STEPN 273 #define BX_TOKEN_STEP_OVER 274 #define BX_TOKEN_SET 275 #define BX_TOKEN_DEBUGGER 276 #define BX_TOKEN_LIST_BREAK 277 #define BX_TOKEN_VBREAKPOINT 278 #define BX_TOKEN_LBREAKPOINT 279 #define BX_TOKEN_PBREAKPOINT 280 #define BX_TOKEN_DEL_BREAKPOINT 281 #define BX_TOKEN_ENABLE_BREAKPOINT 282 #define BX_TOKEN_DISABLE_BREAKPOINT 283 #define BX_TOKEN_INFO 284 #define BX_TOKEN_QUIT 285 #define BX_TOKEN_R 286 #define BX_TOKEN_REGS 287 #define BX_TOKEN_CPU 288 #define BX_TOKEN_FPU 289 #define BX_TOKEN_MMX 290 #define BX_TOKEN_SSE 291 #define BX_TOKEN_AVX 292 #define BX_TOKEN_IDT 293 #define BX_TOKEN_IVT 294 #define BX_TOKEN_GDT 295 #define BX_TOKEN_LDT 296 #define BX_TOKEN_TSS 297 #define BX_TOKEN_TAB 298 #define BX_TOKEN_ALL 299 #define BX_TOKEN_LINUX 300 #define BX_TOKEN_DEBUG_REGS 301 #define BX_TOKEN_CONTROL_REGS 302 #define BX_TOKEN_SEGMENT_REGS 303 #define BX_TOKEN_EXAMINE 304 #define BX_TOKEN_XFORMAT 305 #define BX_TOKEN_DISFORMAT 306 #define BX_TOKEN_RESTORE 307 #define BX_TOKEN_WRITEMEM 308 #define BX_TOKEN_SETPMEM 309 #define BX_TOKEN_SYMBOLNAME 310 #define BX_TOKEN_QUERY 311 #define BX_TOKEN_PENDING 312 #define BX_TOKEN_TAKE 313 #define BX_TOKEN_DMA 314 #define BX_TOKEN_IRQ 315 #define BX_TOKEN_HEX 316 #define BX_TOKEN_DISASM 317 #define BX_TOKEN_INSTRUMENT 318 #define BX_TOKEN_STRING 319 #define BX_TOKEN_STOP 320 #define BX_TOKEN_DOIT 321 #define BX_TOKEN_CRC 322 #define BX_TOKEN_TRACE 323 #define BX_TOKEN_TRACEREG 324 #define BX_TOKEN_TRACEMEM 325 #define BX_TOKEN_SWITCH_MODE 326 #define BX_TOKEN_SIZE 327 #define BX_TOKEN_PTIME 328 #define BX_TOKEN_TIMEBP_ABSOLUTE 329 #define BX_TOKEN_TIMEBP 330 #define BX_TOKEN_MODEBP 331 #define BX_TOKEN_VMEXITBP 332 #define BX_TOKEN_PRINT_STACK 333 #define BX_TOKEN_WATCH 334 #define BX_TOKEN_UNWATCH 335 #define BX_TOKEN_READ 336 #define BX_TOKEN_WRITE 337 #define BX_TOKEN_SHOW 338 #define BX_TOKEN_LOAD_SYMBOLS 339 #define BX_TOKEN_SYMBOLS 340 #define BX_TOKEN_LIST_SYMBOLS 341 #define BX_TOKEN_GLOBAL 342 #define BX_TOKEN_WHERE 343 #define BX_TOKEN_PRINT_STRING 344 #define BX_TOKEN_NUMERIC 345 #define BX_TOKEN_PAGE 346 #define BX_TOKEN_HELP 347 #define BX_TOKEN_CALC 348 #define BX_TOKEN_VGA 349 #define BX_TOKEN_DEVICE 350 #define BX_TOKEN_COMMAND 351 #define BX_TOKEN_GENERIC 352 #define BX_TOKEN_RSHIFT 353 #define BX_TOKEN_LSHIFT 354 #define BX_TOKEN_REG_IP 355 #define BX_TOKEN_REG_EIP 356 #define BX_TOKEN_REG_RIP 357 #define INDIRECT 358 #define NEG 359 #define NOT 360 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE { /* Line 293 of yacc.c */ #line 13 "parser.y" char *sval; Bit64u uval; bx_bool bval; /* Line 293 of yacc.c */ #line 342 "y.tab.c" } YYSTYPE; # define YYSTYPE_IS_TRIVIAL 1 # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 #endif /* Copy the second part of user declarations. */ /* Line 343 of yacc.c */ #line 354 "y.tab.c" #ifdef short # undef short #endif #ifdef YYTYPE_UINT8 typedef YYTYPE_UINT8 yytype_uint8; #else typedef unsigned char yytype_uint8; #endif #ifdef YYTYPE_INT8 typedef YYTYPE_INT8 yytype_int8; #elif (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) typedef signed char yytype_int8; #else typedef short int yytype_int8; #endif #ifdef YYTYPE_UINT16 typedef YYTYPE_UINT16 yytype_uint16; #else typedef unsigned short int yytype_uint16; #endif #ifdef YYTYPE_INT16 typedef YYTYPE_INT16 yytype_int16; #else typedef short int yytype_int16; #endif #ifndef YYSIZE_T # ifdef __SIZE_TYPE__ # define YYSIZE_T __SIZE_TYPE__ # elif defined size_t # define YYSIZE_T size_t # elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # else # define YYSIZE_T unsigned int # endif #endif #define YYSIZE_MAXIMUM ((YYSIZE_T) -1) #ifndef YY_ # if defined YYENABLE_NLS && YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif /* Suppress unused-variable warnings by "using" E. */ #if ! defined lint || defined __GNUC__ # define YYUSE(e) ((void) (e)) #else # define YYUSE(e) /* empty */ #endif /* Identity function, used to suppress warnings about constant conditions. */ #ifndef lint # define YYID(n) (n) #else #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static int YYID (int yyi) #else static int YYID (yyi) int yyi; #endif { return yyi; } #endif #if ! defined yyoverflow || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # elif defined __BUILTIN_VA_ARG_INCR # include /* INFRINGES ON USER NAME SPACE */ # elif defined _AIX # define YYSTACK_ALLOC __alloca # elif defined _MSC_VER # include /* INFRINGES ON USER NAME SPACE */ # define alloca _alloca # else # define YYSTACK_ALLOC alloca # if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM # endif # if (defined __cplusplus && ! defined EXIT_SUCCESS \ && ! ((defined YYMALLOC || defined malloc) \ && (defined YYFREE || defined free))) # include /* INFRINGES ON USER NAME SPACE */ # ifndef EXIT_SUCCESS # define EXIT_SUCCESS 0 # endif # endif # ifndef YYMALLOC # define YYMALLOC malloc # if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # endif #endif /* ! defined yyoverflow || YYERROR_VERBOSE */ #if (! defined yyoverflow \ && (! defined __cplusplus \ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { yytype_int16 yyss_alloc; YYSTYPE yyvs_alloc; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) # define YYCOPY_NEEDED 1 /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack_alloc, Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ Stack = &yyptr->Stack_alloc; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (YYID (0)) #endif #if defined YYCOPY_NEEDED && YYCOPY_NEEDED /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined __GNUC__ && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (YYID (0)) # endif # endif #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ #define YYFINAL 280 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 1371 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 120 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 55 /* YYNRULES -- Number of rules. */ #define YYNRULES 267 /* YYNRULES -- Number of states. */ #define YYNSTATES 517 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 360 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const yytype_uint8 yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 113, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 116, 2, 2, 2, 2, 109, 2, 117, 118, 107, 103, 2, 104, 2, 108, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 115, 2, 2, 114, 2, 2, 119, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 106, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 105, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 110, 111, 112 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const yytype_uint16 yyprhs[] = { 0, 0, 3, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 101, 103, 105, 107, 109, 111, 113, 115, 117, 119, 121, 123, 127, 131, 134, 137, 141, 145, 149, 152, 156, 159, 163, 167, 171, 174, 178, 182, 186, 189, 194, 199, 204, 210, 216, 222, 225, 229, 233, 238, 243, 249, 252, 256, 259, 262, 266, 271, 276, 279, 284, 290, 296, 302, 308, 314, 320, 326, 329, 335, 338, 342, 346, 349, 353, 358, 361, 364, 368, 372, 376, 382, 388, 394, 400, 404, 408, 412, 416, 420, 425, 429, 434, 440, 441, 443, 446, 449, 452, 455, 458, 461, 464, 467, 471, 475, 479, 482, 487, 491, 495, 498, 503, 509, 515, 519, 523, 528, 532, 535, 539, 544, 548, 553, 559, 563, 568, 574, 578, 582, 586, 591, 595, 599, 603, 607, 611, 615, 619, 623, 627, 631, 635, 639, 643, 647, 651, 655, 659, 663, 667, 671, 675, 679, 683, 687, 691, 695, 699, 703, 707, 711, 715, 719, 723, 727, 731, 735, 739, 743, 747, 751, 755, 759, 763, 767, 771, 774, 778, 780, 782, 784, 786, 788, 790, 792, 794, 796, 798, 800, 804, 808, 812, 816, 820, 824, 828, 832, 836, 839, 842, 846, 848, 850, 852, 854, 856, 858, 860, 862, 864, 866, 868, 872, 876, 880, 884, 888, 892, 896, 900, 904, 908, 911, 914, 917, 920 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { 121, 0, -1, 121, 122, -1, 122, -1, 140, -1, 141, -1, 142, -1, 143, -1, 144, -1, 147, -1, 149, -1, 150, -1, 151, -1, 152, -1, 153, -1, 154, -1, 156, -1, 155, -1, 145, -1, 146, -1, 157, -1, 158, -1, 159, -1, 160, -1, 161, -1, 162, -1, 163, -1, 164, -1, 165, -1, 166, -1, 167, -1, 168, -1, 169, -1, 170, -1, 132, -1, 133, -1, 134, -1, 131, -1, 126, -1, 127, -1, 128, -1, 135, -1, 136, -1, 130, -1, 129, -1, 137, -1, 138, -1, 139, -1, 171, -1, 172, -1, -1, 113, -1, 15, -1, 16, -1, 31, -1, 32, -1, 8, -1, 9, -1, 10, -1, 11, -1, 12, -1, 13, -1, 75, 90, 113, -1, 74, 90, 113, -1, 76, 113, -1, 77, 113, -1, 83, 96, 113, -1, 83, 16, 113, -1, 83, 64, 113, -1, 83, 113, -1, 91, 174, 113, -1, 73, 113, -1, 68, 123, 113, -1, 69, 123, 113, -1, 70, 123, 113, -1, 78, 113, -1, 78, 90, 113, -1, 79, 65, 113, -1, 79, 17, 113, -1, 79, 113, -1, 79, 31, 174, 113, -1, 79, 81, 174, 113, -1, 79, 82, 174, 113, -1, 79, 31, 174, 174, 113, -1, 79, 81, 174, 174, 113, -1, 79, 82, 174, 174, 113, -1, 80, 113, -1, 80, 174, 113, -1, 84, 64, 113, -1, 84, 64, 90, 113, -1, 84, 87, 64, 113, -1, 84, 87, 64, 90, 113, -1, 88, 113, -1, 89, 90, 113, -1, 17, 113, -1, 18, 113, -1, 18, 90, 113, -1, 18, 44, 90, 113, -1, 18, 90, 90, 113, -1, 19, 113, -1, 20, 62, 123, 113, -1, 20, 55, 114, 90, 113, -1, 20, 4, 114, 174, 113, -1, 20, 3, 114, 174, 113, -1, 20, 5, 114, 174, 113, -1, 20, 6, 114, 174, 113, -1, 20, 7, 114, 174, 113, -1, 20, 125, 114, 174, 113, -1, 23, 113, -1, 23, 173, 115, 173, 113, -1, 24, 113, -1, 24, 174, 113, -1, 24, 64, 113, -1, 25, 113, -1, 25, 174, 113, -1, 25, 107, 174, 113, -1, 22, 113, -1, 86, 113, -1, 86, 64, 113, -1, 29, 25, 113, -1, 29, 33, 113, -1, 29, 38, 148, 148, 113, -1, 29, 39, 148, 148, 113, -1, 29, 40, 148, 148, 113, -1, 29, 41, 148, 148, 113, -1, 29, 43, 113, -1, 29, 42, 113, -1, 29, 14, 113, -1, 29, 45, 113, -1, 29, 85, 113, -1, 29, 85, 64, 113, -1, 29, 95, 113, -1, 29, 95, 64, 113, -1, 29, 95, 64, 64, 113, -1, -1, 90, -1, 124, 113, -1, 34, 113, -1, 35, 113, -1, 36, 113, -1, 37, 113, -1, 48, 113, -1, 47, 113, -1, 46, 113, -1, 26, 90, 113, -1, 27, 90, 113, -1, 28, 90, 113, -1, 30, 113, -1, 49, 50, 174, 113, -1, 49, 50, 113, -1, 49, 174, 113, -1, 49, 113, -1, 52, 64, 64, 113, -1, 53, 64, 90, 90, 113, -1, 54, 90, 90, 90, 113, -1, 56, 57, 113, -1, 58, 59, 113, -1, 58, 59, 90, 113, -1, 58, 60, 113, -1, 62, 113, -1, 62, 174, 113, -1, 62, 174, 174, 113, -1, 62, 51, 113, -1, 62, 51, 174, 113, -1, 62, 51, 174, 174, 113, -1, 62, 71, 113, -1, 62, 61, 123, 113, -1, 62, 72, 114, 90, 113, -1, 63, 65, 113, -1, 63, 96, 113, -1, 66, 90, 113, -1, 67, 90, 90, 113, -1, 92, 30, 113, -1, 92, 17, 113, -1, 92, 18, 113, -1, 92, 19, 113, -1, 92, 23, 113, -1, 92, 24, 113, -1, 92, 25, 113, -1, 92, 26, 113, -1, 92, 27, 113, -1, 92, 28, 113, -1, 92, 22, 113, -1, 92, 76, 113, -1, 92, 77, 113, -1, 92, 67, 113, -1, 92, 68, 113, -1, 92, 69, 113, -1, 92, 70, 113, -1, 92, 52, 113, -1, 92, 73, 113, -1, 92, 75, 113, -1, 92, 74, 113, -1, 92, 78, 113, -1, 92, 84, 113, -1, 92, 86, 113, -1, 92, 124, 113, -1, 92, 34, 113, -1, 92, 35, 113, -1, 92, 36, 113, -1, 92, 37, 113, -1, 92, 48, 113, -1, 92, 47, 113, -1, 92, 46, 113, -1, 92, 53, 113, -1, 92, 54, 113, -1, 92, 62, 113, -1, 92, 79, 113, -1, 92, 80, 113, -1, 92, 49, 113, -1, 92, 63, 113, -1, 92, 20, 113, -1, 92, 91, 113, -1, 92, 29, 113, -1, 92, 83, 113, -1, 92, 93, 113, -1, 92, 92, 113, -1, 92, 113, -1, 93, 174, 113, -1, 90, -1, 64, -1, 4, -1, 3, -1, 5, -1, 6, -1, 7, -1, 125, -1, 100, -1, 101, -1, 102, -1, 173, 103, 173, -1, 173, 104, 173, -1, 173, 107, 173, -1, 173, 108, 173, -1, 173, 98, 173, -1, 173, 99, 173, -1, 173, 105, 173, -1, 173, 106, 173, -1, 173, 109, 173, -1, 116, 173, -1, 104, 173, -1, 117, 173, 118, -1, 90, -1, 64, -1, 4, -1, 3, -1, 5, -1, 6, -1, 7, -1, 125, -1, 100, -1, 101, -1, 102, -1, 174, 115, 174, -1, 174, 103, 174, -1, 174, 104, 174, -1, 174, 107, 174, -1, 174, 108, 174, -1, 174, 98, 174, -1, 174, 99, 174, -1, 174, 105, 174, -1, 174, 106, 174, -1, 174, 109, 174, -1, 116, 174, -1, 104, 174, -1, 107, 174, -1, 119, 174, -1, 117, 174, 118, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { 0, 137, 137, 138, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 195, 196, 201, 202, 207, 208, 209, 210, 211, 212, 217, 222, 230, 238, 246, 251, 256, 261, 269, 277, 285, 293, 301, 309, 314, 322, 327, 332, 337, 342, 347, 352, 357, 362, 367, 372, 380, 385, 390, 395, 403, 411, 419, 427, 432, 437, 442, 450, 458, 463, 468, 472, 476, 480, 484, 488, 495, 500, 505, 510, 515, 520, 525, 530, 538, 546, 551, 559, 564, 569, 574, 579, 584, 589, 594, 599, 604, 609, 614, 619, 624, 629, 637, 638, 641, 649, 657, 665, 673, 681, 689, 697, 705, 713, 720, 728, 736, 741, 746, 751, 759, 767, 775, 783, 791, 796, 801, 809, 814, 819, 824, 829, 834, 839, 844, 849, 857, 862, 870, 878, 886, 891, 896, 903, 908, 913, 918, 923, 928, 933, 938, 943, 948, 953, 958, 964, 970, 976, 984, 989, 994, 999, 1004, 1009, 1014, 1019, 1024, 1029, 1034, 1039, 1044, 1049, 1054, 1059, 1064, 1074, 1085, 1091, 1104, 1109, 1119, 1124, 1139, 1151, 1161, 1166, 1174, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "BX_TOKEN_8BH_REG", "BX_TOKEN_8BL_REG", "BX_TOKEN_16B_REG", "BX_TOKEN_32B_REG", "BX_TOKEN_64B_REG", "BX_TOKEN_CS", "BX_TOKEN_ES", "BX_TOKEN_SS", "BX_TOKEN_DS", "BX_TOKEN_FS", "BX_TOKEN_GS", "BX_TOKEN_FLAGS", "BX_TOKEN_ON", "BX_TOKEN_OFF", "BX_TOKEN_CONTINUE", "BX_TOKEN_STEPN", "BX_TOKEN_STEP_OVER", "BX_TOKEN_SET", "BX_TOKEN_DEBUGGER", "BX_TOKEN_LIST_BREAK", "BX_TOKEN_VBREAKPOINT", "BX_TOKEN_LBREAKPOINT", "BX_TOKEN_PBREAKPOINT", "BX_TOKEN_DEL_BREAKPOINT", "BX_TOKEN_ENABLE_BREAKPOINT", "BX_TOKEN_DISABLE_BREAKPOINT", "BX_TOKEN_INFO", "BX_TOKEN_QUIT", "BX_TOKEN_R", "BX_TOKEN_REGS", "BX_TOKEN_CPU", "BX_TOKEN_FPU", "BX_TOKEN_MMX", "BX_TOKEN_SSE", "BX_TOKEN_AVX", "BX_TOKEN_IDT", "BX_TOKEN_IVT", "BX_TOKEN_GDT", "BX_TOKEN_LDT", "BX_TOKEN_TSS", "BX_TOKEN_TAB", "BX_TOKEN_ALL", "BX_TOKEN_LINUX", "BX_TOKEN_DEBUG_REGS", "BX_TOKEN_CONTROL_REGS", "BX_TOKEN_SEGMENT_REGS", "BX_TOKEN_EXAMINE", "BX_TOKEN_XFORMAT", "BX_TOKEN_DISFORMAT", "BX_TOKEN_RESTORE", "BX_TOKEN_WRITEMEM", "BX_TOKEN_SETPMEM", "BX_TOKEN_SYMBOLNAME", "BX_TOKEN_QUERY", "BX_TOKEN_PENDING", "BX_TOKEN_TAKE", "BX_TOKEN_DMA", "BX_TOKEN_IRQ", "BX_TOKEN_HEX", "BX_TOKEN_DISASM", "BX_TOKEN_INSTRUMENT", "BX_TOKEN_STRING", "BX_TOKEN_STOP", "BX_TOKEN_DOIT", "BX_TOKEN_CRC", "BX_TOKEN_TRACE", "BX_TOKEN_TRACEREG", "BX_TOKEN_TRACEMEM", "BX_TOKEN_SWITCH_MODE", "BX_TOKEN_SIZE", "BX_TOKEN_PTIME", "BX_TOKEN_TIMEBP_ABSOLUTE", "BX_TOKEN_TIMEBP", "BX_TOKEN_MODEBP", "BX_TOKEN_VMEXITBP", "BX_TOKEN_PRINT_STACK", "BX_TOKEN_WATCH", "BX_TOKEN_UNWATCH", "BX_TOKEN_READ", "BX_TOKEN_WRITE", "BX_TOKEN_SHOW", "BX_TOKEN_LOAD_SYMBOLS", "BX_TOKEN_SYMBOLS", "BX_TOKEN_LIST_SYMBOLS", "BX_TOKEN_GLOBAL", "BX_TOKEN_WHERE", "BX_TOKEN_PRINT_STRING", "BX_TOKEN_NUMERIC", "BX_TOKEN_PAGE", "BX_TOKEN_HELP", "BX_TOKEN_CALC", "BX_TOKEN_VGA", "BX_TOKEN_DEVICE", "BX_TOKEN_COMMAND", "BX_TOKEN_GENERIC", "BX_TOKEN_RSHIFT", "BX_TOKEN_LSHIFT", "BX_TOKEN_REG_IP", "BX_TOKEN_REG_EIP", "BX_TOKEN_REG_RIP", "'+'", "'-'", "'|'", "'^'", "'*'", "'/'", "'&'", "INDIRECT", "NEG", "NOT", "'\\n'", "'='", "':'", "'!'", "'('", "')'", "'@'", "$accept", "commands", "command", "BX_TOKEN_TOGGLE_ON_OFF", "BX_TOKEN_REGISTERS", "BX_TOKEN_SEGREG", "timebp_command", "modebp_command", "vmexitbp_command", "show_command", "page_command", "ptime_command", "trace_command", "trace_reg_command", "trace_mem_command", "print_stack_command", "watch_point_command", "symbol_command", "where_command", "print_string_command", "continue_command", "stepN_command", "step_over_command", "set_command", "breakpoint_command", "blist_command", "slist_command", "info_command", "optional_numeric", "regs_command", "fpu_regs_command", "mmx_regs_command", "sse_regs_command", "avx_regs_command", "segment_regs_command", "control_regs_command", "debug_regs_command", "delete_command", "bpe_command", "bpd_command", "quit_command", "examine_command", "restore_command", "writemem_command", "setpmem_command", "query_command", "take_command", "disassemble_command", "instrument_command", "doit_command", "crc_command", "help_command", "calc_command", "vexpression", "expression", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const yytype_uint16 yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 43, 45, 124, 94, 42, 47, 38, 358, 359, 360, 10, 61, 58, 33, 40, 41, 64 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint8 yyr1[] = { 0, 120, 121, 121, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, 123, 123, 124, 124, 125, 125, 125, 125, 125, 125, 126, 126, 127, 128, 129, 129, 129, 129, 130, 131, 132, 133, 134, 135, 135, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 137, 137, 137, 137, 138, 139, 140, 141, 141, 141, 141, 142, 143, 143, 143, 143, 143, 143, 143, 143, 144, 144, 144, 144, 144, 144, 144, 144, 145, 146, 146, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 148, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 161, 161, 161, 162, 163, 164, 165, 166, 166, 166, 167, 167, 167, 167, 167, 167, 167, 167, 167, 168, 168, 169, 170, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 172, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const yytype_uint8 yyr2[] = { 0, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 2, 2, 3, 3, 3, 2, 3, 2, 3, 3, 3, 2, 3, 3, 3, 2, 4, 4, 4, 5, 5, 5, 2, 3, 3, 4, 4, 5, 2, 3, 2, 2, 3, 4, 4, 2, 4, 5, 5, 5, 5, 5, 5, 5, 2, 5, 2, 3, 3, 2, 3, 4, 2, 2, 3, 3, 3, 5, 5, 5, 5, 3, 3, 3, 3, 3, 4, 3, 4, 5, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 4, 3, 3, 2, 4, 5, 5, 3, 3, 4, 3, 2, 3, 4, 3, 4, 5, 3, 4, 5, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3 }; /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM. Performed when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const yytype_uint16 yydefact[] = { 50, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 3, 0, 38, 39, 40, 44, 43, 37, 34, 35, 36, 41, 42, 45, 46, 47, 4, 5, 6, 7, 8, 18, 19, 9, 10, 11, 12, 13, 14, 15, 17, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 48, 49, 94, 0, 0, 95, 99, 0, 0, 0, 0, 0, 56, 57, 58, 59, 60, 61, 0, 0, 0, 116, 222, 221, 223, 224, 225, 220, 219, 227, 228, 229, 0, 108, 0, 0, 226, 0, 245, 244, 246, 247, 248, 243, 242, 250, 251, 252, 0, 0, 110, 0, 0, 0, 249, 0, 243, 0, 113, 0, 0, 0, 0, 0, 0, 0, 134, 134, 134, 134, 0, 0, 0, 0, 0, 147, 137, 138, 139, 140, 143, 142, 141, 0, 151, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 159, 0, 0, 0, 0, 0, 52, 53, 0, 0, 0, 71, 0, 0, 64, 65, 0, 75, 0, 0, 0, 0, 0, 79, 86, 0, 0, 0, 0, 69, 0, 0, 0, 117, 92, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 217, 0, 0, 1, 2, 136, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 240, 239, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 264, 265, 263, 0, 266, 0, 0, 0, 0, 0, 0, 0, 0, 0, 111, 0, 265, 114, 144, 145, 146, 127, 119, 120, 135, 134, 134, 134, 134, 126, 125, 128, 0, 129, 0, 131, 149, 0, 150, 0, 0, 0, 155, 0, 156, 158, 162, 0, 0, 165, 0, 0, 0, 160, 0, 168, 169, 170, 0, 72, 73, 74, 63, 62, 76, 78, 0, 77, 0, 0, 87, 67, 68, 66, 0, 88, 0, 118, 93, 70, 173, 174, 175, 211, 182, 176, 177, 178, 179, 180, 181, 213, 172, 197, 198, 199, 200, 203, 202, 201, 209, 189, 204, 205, 206, 210, 185, 186, 187, 188, 190, 192, 191, 183, 184, 193, 207, 208, 214, 194, 195, 212, 216, 215, 196, 218, 97, 98, 0, 0, 0, 0, 0, 0, 100, 0, 241, 234, 235, 230, 231, 236, 237, 232, 233, 238, 0, 267, 258, 259, 254, 255, 260, 261, 256, 257, 262, 253, 115, 0, 0, 0, 0, 130, 0, 132, 148, 152, 0, 0, 157, 163, 0, 166, 0, 255, 256, 161, 171, 80, 0, 81, 0, 82, 0, 89, 0, 90, 103, 102, 104, 105, 106, 101, 107, 109, 121, 122, 123, 124, 133, 153, 154, 164, 167, 83, 84, 85, 91 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { -1, 53, 54, 204, 55, 154, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 333, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 137, 155 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -164 static const yytype_int16 yypact[] = { 1069, -93, -42, -83, 75, -81, 240, 632, 679, -51, -29, -15, 1206, -71, -164, -164, -69, -20, -18, -16, -12, -11, -10, 46, 27, 40, 15, 50, -22, 562, -56, 19, 22, 54, 54, 54, 0, 24, 25, 14, 20, -80, -5, 699, -2, -53, -48, 21, 38, 866, 1149, 866, -164, 989, -164, 26, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, 45, -77, -164, -164, 28, 37, 41, 42, 43, -164, -164, -164, -164, -164, -164, 44, 54, 47, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, 886, -164, 886, 886, -164, 256, -164, -164, -164, -164, -164, 39, -164, -164, -164, -164, 866, 866, -164, 866, 866, 866, -164, 291, -164, 866, -164, 353, 51, 55, 56, 61, 63, 65, 48, 48, 48, 48, 66, 67, 68, -47, -46, -164, -164, -164, -164, -164, -164, -164, -164, 749, -164, 415, 90, 70, 77, 69, -68, 72, 816, 54, 73, 74, -164, 113, 87, 88, 89, 93, -164, -164, 91, 92, 95, -164, 110, 114, -164, -164, 118, -164, 123, 866, 124, 866, 866, -164, -164, 478, 125, 127, 129, -164, -67, 142, 143, -164, -164, 144, 552, 145, 153, 154, 155, 157, 159, 160, 162, 163, 164, 170, 171, 173, 174, 175, 176, 177, 178, 179, 180, 201, 214, 218, 219, 232, 233, 236, 237, 245, 254, 257, 259, 260, 261, 262, 263, 278, 279, 280, 288, 289, 292, 294, 295, -164, 296, 622, -164, -164, -164, 297, 310, -164, 866, 866, 866, 866, 866, 97, 311, 866, -164, -164, 230, 886, 886, 886, 886, 886, 886, 886, 886, 886, 886, -164, 228, 228, 228, 156, 228, 866, 866, 866, 866, 866, 866, 866, 866, 866, -164, 866, -84, -164, -164, -164, -164, -164, -164, -164, -164, 48, 48, 48, 48, -164, -164, -164, 312, -164, -45, -164, -164, 669, -164, 314, 149, 341, -164, 320, -164, -164, -164, 313, 321, -164, 345, 866, 866, -164, 739, -164, -164, -164, 323, -164, -164, -164, -164, -164, -164, -164, 375, -164, 437, 499, -164, -164, -164, -164, 324, -164, -66, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, 806, 838, 856, 1160, 1173, 325, -164, 1191, -164, -164, -164, -35, -35, -35, -35, -164, -164, -164, 1101, -164, 228, 228, -9, -9, -9, -9, 228, 228, 228, 1256, -164, 340, 342, 350, 351, -164, 354, -164, -164, -164, 356, 357, -164, -164, 1204, -164, 358, 126, 228, -164, -164, -164, 1217, -164, 1230, -164, 1243, -164, 359, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { -164, -164, 216, -27, 404, -3, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -163, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -164, -107, -8 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -265 static const yytype_int16 yytable[] = { 159, 120, 103, 136, 334, 335, 336, 205, 206, 198, 212, 226, 214, 284, 222, 185, 228, 340, 342, 472, 102, 197, 351, 382, 494, 294, 215, 295, 296, 466, 106, 323, 121, 213, 227, 221, 285, 190, 191, 160, 199, 232, 175, 279, 176, 352, 383, 495, 104, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 216, 161, 223, 297, 298, 229, 341, 343, 473, 202, 203, 105, 303, 304, 305, 162, 217, 218, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 313, 314, 186, 292, 177, 224, 178, 183, 179, 319, 320, 321, 180, 181, 182, 187, 188, 323, 189, 219, 200, 156, 225, 201, 207, 208, 209, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 210, 231, 136, 118, 136, 136, 211, 230, 283, 144, 119, 332, 282, 308, 309, 286, 310, 311, 312, 145, 146, 147, 324, 148, 287, 307, 149, 347, 288, 289, 290, 291, 184, 348, 293, 151, 152, 326, 153, 356, 349, 327, 328, 467, 468, 469, 470, 329, 345, 330, 156, 331, 337, 338, 339, 350, 366, 355, 353, 357, 441, 358, 362, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 363, 364, 365, 144, 367, 368, 384, 374, 369, 376, 377, 313, 314, 145, 146, 147, 315, 359, 317, 318, 360, 320, 321, 370, -264, -264, 361, 371, 323, 151, 152, 372, 153, -264, -264, -264, 373, 375, 379, 476, 380, 323, 381, 122, 123, 124, 125, 126, 112, 113, 114, 115, 116, 117, 313, 314, 385, 386, 388, 315, 316, 317, 318, 319, 320, 321, 389, 390, 391, 281, 392, 323, 393, 394, 455, 395, 396, 397, 436, 437, 438, 439, 440, 398, 399, 443, 400, 401, 402, 403, 404, 405, 406, 407, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 127, 456, 457, 458, 459, 460, 461, 462, 463, 464, 408, 465, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 409, 297, 298, 128, 410, 411, 299, 300, 301, 302, 303, 304, 305, 129, 130, 131, 323, 132, 412, 413, 480, 444, 414, 415, 483, 484, 133, 297, 298, 134, 135, 416, 299, 300, 301, 302, 303, 304, 305, 488, 417, 490, 492, 418, 306, 419, 420, 421, 422, 423, 156, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 313, 314, 424, 425, 426, 315, 316, 317, 318, 319, 320, 321, 427, 428, 144, 322, 429, 323, 430, 431, 432, 434, 313, 314, 145, 146, 147, 315, 359, 317, 318, 360, 320, 321, 435, 442, 471, 479, 475, 323, 151, 152, 477, 153, 478, 481, 482, 486, 493, 501, 156, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 313, 314, 504, 278, 505, 315, 316, 317, 318, 319, 320, 321, 506, 507, 144, 325, 508, 323, 509, 510, 512, 516, 313, 314, 145, 146, 147, 315, 359, 317, 318, 360, 320, 321, 0, 0, 0, 487, 0, 323, 151, 152, 0, 153, 0, 0, 0, 0, 0, 0, 156, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 313, 314, 0, 0, 0, 315, 316, 317, 318, 319, 320, 321, 0, 0, 144, 346, 0, 323, 0, 0, 0, 0, 313, 314, 145, 146, 147, 315, 359, 317, 318, 360, 320, 321, 0, 0, 0, 489, 0, 323, 151, 152, 0, 153, 0, 0, 0, 0, 0, 0, 156, 0, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 313, 314, 0, 0, 0, 315, 316, 317, 318, 319, 320, 321, 0, 144, 0, 378, 0, 323, 0, 0, 0, 313, 314, 145, 146, 147, 315, 359, 317, 318, 360, 320, 321, 0, 0, 0, 491, 192, 323, 151, 152, 0, 153, 0, 0, 0, 0, 193, 0, 0, 156, 0, 0, 0, 0, 0, 0, 194, 195, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 0, 0, 0, 0, 313, 314, 144, 0, 0, 315, 316, 317, 318, 319, 320, 321, 145, 146, 147, 387, 148, 323, 0, 149, 0, 0, 0, 0, 0, 196, 0, 0, 151, 152, 0, 153, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 0, 0, 0, 143, 0, 0, 0, 0, 0, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 0, 0, 0, 0, 0, 0, 0, 313, 314, 144, 0, 0, 315, 316, 317, 318, 319, 320, 321, 145, 146, 147, 433, 148, 323, 0, 149, 0, 0, 0, 156, 0, 150, 0, 0, 151, 152, 0, 153, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 156, 0, 0, 0, 313, 314, 144, 0, 0, 315, 316, 317, 318, 319, 320, 321, 145, 146, 147, 474, 148, 323, 0, 157, 0, 0, 144, 0, 0, 158, 0, 0, 151, 152, 0, 153, 145, 146, 147, 0, 148, 0, 0, 149, 0, 0, 0, 0, 0, 220, 156, 0, 151, 152, 0, 153, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 0, 0, 0, 0, 0, 0, 0, 313, 314, 144, 0, 0, 315, 316, 317, 318, 319, 320, 321, 145, 146, 147, 485, 148, 323, 0, 149, 0, 0, 0, 0, 0, 344, 0, 0, 151, 152, 0, 153, 138, 139, 140, 141, 142, 112, 113, 114, 115, 116, 117, 156, 0, 0, 0, 0, 0, 0, 0, 0, 122, 123, 124, 125, 126, 112, 113, 114, 115, 116, 117, 0, 0, 0, 0, 313, 314, 144, 0, 0, 315, 316, 317, 318, 319, 320, 321, 145, 146, 147, 496, 148, 323, 0, 149, 0, 0, 0, 0, 0, 354, 156, 0, 151, 152, 0, 153, 313, 314, 0, 0, 0, 315, 316, 317, 318, 319, 320, 321, 0, 0, 127, 497, 0, 323, 313, 314, 144, 0, 0, 315, 316, 317, 318, 319, 320, 321, 145, 146, 147, 498, 148, 323, 0, 149, 0, 0, 128, 0, 0, 0, 0, 0, 151, 152, 0, 153, 129, 130, 131, 280, 132, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 135, 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 0, 0, 24, 25, 26, 0, 27, 0, 28, 0, 0, 0, 29, 30, 0, 0, 31, 32, 33, 34, 35, 0, 0, 36, 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, 45, 0, 46, 0, 47, 48, 0, 49, 50, 51, 0, 0, 0, 1, 2, 3, 4, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 52, 16, 17, 18, 19, 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 0, 0, 24, 25, 26, 0, 27, 0, 28, 0, 0, 0, 29, 30, 0, 0, 31, 32, 33, 34, 35, 0, 0, 36, 37, 38, 39, 40, 41, 42, 43, 0, 0, 44, 45, 0, 46, 0, 47, 48, 0, 49, 50, 51, 0, 0, 0, 233, 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, 243, 244, 245, 14, 15, 52, 246, 247, 248, 249, 0, 0, 0, 0, 0, 0, 0, 0, 250, 251, 252, 253, 297, 298, 254, 255, 256, 299, 300, 301, 302, 303, 304, 305, 257, 258, 0, 503, 0, 259, 260, 261, 262, 163, 0, 263, 264, 265, 266, 267, 268, 269, 270, 0, 164, 271, 272, 0, 273, 0, 0, 0, 165, 274, 275, 276, 0, 166, 167, 168, 169, 170, 171, 0, 172, 0, 0, 0, 0, 0, 0, 313, 314, 0, 0, 277, 315, 316, 317, 318, 319, 320, 321, 0, 313, 314, 499, 0, 323, 315, 316, 317, 318, 319, 320, 321, 0, 0, 0, 500, 0, 323, 313, 314, 173, 0, 0, 315, 316, 317, 318, 319, 320, 321, 174, 313, 314, 502, 0, 323, 315, 316, 317, 318, 319, 320, 321, 0, 313, 314, 511, 0, 323, 315, 316, 317, 318, 319, 320, 321, 0, 313, 314, 513, 0, 323, 315, 316, 317, 318, 319, 320, 321, 0, 313, 314, 514, 0, 323, 315, 316, 317, 318, 319, 320, 321, 0, 313, 314, 515, 0, 323, 315, 316, 317, 318, 319, 320, 321, 0, 0, 0, 0, 0, 323 }; #define yypact_value_is_default(yystate) \ ((yystate) == (-164)) #define yytable_value_is_error(yytable_value) \ YYID (0) static const yytype_int16 yycheck[] = { 8, 4, 44, 6, 167, 168, 169, 34, 35, 65, 90, 64, 17, 90, 16, 23, 64, 64, 64, 64, 113, 29, 90, 90, 90, 132, 31, 134, 135, 113, 113, 115, 113, 113, 87, 43, 113, 59, 60, 90, 96, 49, 113, 51, 113, 113, 113, 113, 90, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 65, 90, 64, 98, 99, 113, 113, 113, 113, 15, 16, 113, 107, 108, 109, 90, 81, 82, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 98, 99, 64, 119, 113, 96, 113, 50, 113, 107, 108, 109, 113, 113, 113, 64, 90, 115, 57, 113, 90, 64, 113, 90, 113, 90, 90, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 113, 90, 132, 55, 134, 135, 113, 113, 90, 90, 62, 90, 113, 148, 149, 114, 151, 152, 153, 100, 101, 102, 157, 104, 114, 113, 107, 64, 114, 114, 114, 114, 113, 90, 114, 116, 117, 113, 119, 193, 90, 113, 113, 333, 334, 335, 336, 113, 183, 113, 64, 113, 113, 113, 113, 113, 90, 192, 113, 113, 90, 114, 197, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 113, 113, 113, 90, 113, 113, 64, 215, 113, 217, 218, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 113, 98, 99, 113, 113, 115, 116, 117, 113, 119, 107, 108, 109, 113, 113, 113, 90, 113, 115, 113, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 98, 99, 113, 113, 113, 103, 104, 105, 106, 107, 108, 109, 113, 113, 113, 53, 113, 115, 113, 113, 118, 113, 113, 113, 286, 287, 288, 289, 290, 113, 113, 293, 113, 113, 113, 113, 113, 113, 113, 113, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 64, 313, 314, 315, 316, 317, 318, 319, 320, 321, 113, 323, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 113, 98, 99, 90, 113, 113, 103, 104, 105, 106, 107, 108, 109, 100, 101, 102, 115, 104, 113, 113, 355, 118, 113, 113, 359, 360, 113, 98, 99, 116, 117, 113, 103, 104, 105, 106, 107, 108, 109, 374, 113, 376, 377, 113, 115, 113, 113, 113, 113, 113, 64, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 98, 99, 113, 113, 113, 103, 104, 105, 106, 107, 108, 109, 113, 113, 90, 113, 113, 115, 113, 113, 113, 113, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 113, 113, 113, 113, 113, 115, 116, 117, 90, 119, 113, 113, 90, 113, 113, 113, 64, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 98, 99, 113, 50, 113, 103, 104, 105, 106, 107, 108, 109, 113, 113, 90, 113, 113, 115, 113, 113, 113, 113, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, -1, -1, -1, 113, -1, 115, 116, 117, -1, 119, -1, -1, -1, -1, -1, -1, 64, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 98, 99, -1, -1, -1, 103, 104, 105, 106, 107, 108, 109, -1, -1, 90, 113, -1, 115, -1, -1, -1, -1, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, -1, -1, -1, 113, -1, 115, 116, 117, -1, 119, -1, -1, -1, -1, -1, -1, 64, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 98, 99, -1, -1, -1, 103, 104, 105, 106, 107, 108, 109, -1, 90, -1, 113, -1, 115, -1, -1, -1, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, -1, -1, -1, 113, 51, 115, 116, 117, -1, 119, -1, -1, -1, -1, 61, -1, -1, 64, -1, -1, -1, -1, -1, -1, 71, 72, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, -1, -1, -1, 98, 99, 90, -1, -1, 103, 104, 105, 106, 107, 108, 109, 100, 101, 102, 113, 104, 115, -1, 107, -1, -1, -1, -1, -1, 113, -1, -1, 116, 117, -1, 119, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, -1, -1, 64, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, 98, 99, 90, -1, -1, 103, 104, 105, 106, 107, 108, 109, 100, 101, 102, 113, 104, 115, -1, 107, -1, -1, -1, 64, -1, 113, -1, -1, 116, 117, -1, 119, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 64, -1, -1, -1, 98, 99, 90, -1, -1, 103, 104, 105, 106, 107, 108, 109, 100, 101, 102, 113, 104, 115, -1, 107, -1, -1, 90, -1, -1, 113, -1, -1, 116, 117, -1, 119, 100, 101, 102, -1, 104, -1, -1, 107, -1, -1, -1, -1, -1, 113, 64, -1, 116, 117, -1, 119, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, -1, -1, -1, -1, -1, -1, 98, 99, 90, -1, -1, 103, 104, 105, 106, 107, 108, 109, 100, 101, 102, 113, 104, 115, -1, 107, -1, -1, -1, -1, -1, 113, -1, -1, 116, 117, -1, 119, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 64, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, -1, -1, -1, -1, 98, 99, 90, -1, -1, 103, 104, 105, 106, 107, 108, 109, 100, 101, 102, 113, 104, 115, -1, 107, -1, -1, -1, -1, -1, 113, 64, -1, 116, 117, -1, 119, 98, 99, -1, -1, -1, 103, 104, 105, 106, 107, 108, 109, -1, -1, 64, 113, -1, 115, 98, 99, 90, -1, -1, 103, 104, 105, 106, 107, 108, 109, 100, 101, 102, 113, 104, 115, -1, 107, -1, -1, 90, -1, -1, -1, -1, -1, 116, 117, -1, 119, 100, 101, 102, 0, 104, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 116, 117, -1, -1, 17, 18, 19, 20, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, 34, 35, 36, 37, -1, -1, -1, -1, -1, -1, -1, -1, 46, 47, 48, 49, -1, -1, 52, 53, 54, -1, 56, -1, 58, -1, -1, -1, 62, 63, -1, -1, 66, 67, 68, 69, 70, -1, -1, 73, 74, 75, 76, 77, 78, 79, 80, -1, -1, 83, 84, -1, 86, -1, 88, 89, -1, 91, 92, 93, -1, -1, -1, 17, 18, 19, 20, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 113, 34, 35, 36, 37, -1, -1, -1, -1, -1, -1, -1, -1, 46, 47, 48, 49, -1, -1, 52, 53, 54, -1, 56, -1, 58, -1, -1, -1, 62, 63, -1, -1, 66, 67, 68, 69, 70, -1, -1, 73, 74, 75, 76, 77, 78, 79, 80, -1, -1, 83, 84, -1, 86, -1, 88, 89, -1, 91, 92, 93, -1, -1, -1, 17, 18, 19, 20, -1, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 113, 34, 35, 36, 37, -1, -1, -1, -1, -1, -1, -1, -1, 46, 47, 48, 49, 98, 99, 52, 53, 54, 103, 104, 105, 106, 107, 108, 109, 62, 63, -1, 113, -1, 67, 68, 69, 70, 14, -1, 73, 74, 75, 76, 77, 78, 79, 80, -1, 25, 83, 84, -1, 86, -1, -1, -1, 33, 91, 92, 93, -1, 38, 39, 40, 41, 42, 43, -1, 45, -1, -1, -1, -1, -1, -1, 98, 99, -1, -1, 113, 103, 104, 105, 106, 107, 108, 109, -1, 98, 99, 113, -1, 115, 103, 104, 105, 106, 107, 108, 109, -1, -1, -1, 113, -1, 115, 98, 99, 85, -1, -1, 103, 104, 105, 106, 107, 108, 109, 95, 98, 99, 113, -1, 115, 103, 104, 105, 106, 107, 108, 109, -1, 98, 99, 113, -1, 115, 103, 104, 105, 106, 107, 108, 109, -1, 98, 99, 113, -1, 115, 103, 104, 105, 106, 107, 108, 109, -1, 98, 99, 113, -1, 115, 103, 104, 105, 106, 107, 108, 109, -1, 98, 99, 113, -1, 115, 103, 104, 105, 106, 107, 108, 109, -1, -1, -1, -1, -1, 115 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint8 yystos[] = { 0, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 34, 35, 36, 37, 46, 47, 48, 49, 52, 53, 54, 56, 58, 62, 63, 66, 67, 68, 69, 70, 73, 74, 75, 76, 77, 78, 79, 80, 83, 84, 86, 88, 89, 91, 92, 93, 113, 121, 122, 124, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 113, 44, 90, 113, 113, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 55, 62, 125, 113, 3, 4, 5, 6, 7, 64, 90, 100, 101, 102, 104, 113, 116, 117, 125, 173, 3, 4, 5, 6, 7, 64, 90, 100, 101, 102, 104, 107, 113, 116, 117, 119, 125, 174, 64, 107, 113, 174, 90, 90, 90, 14, 25, 33, 38, 39, 40, 41, 42, 43, 45, 85, 95, 113, 113, 113, 113, 113, 113, 113, 113, 50, 113, 174, 64, 64, 90, 57, 59, 60, 51, 61, 71, 72, 113, 174, 65, 96, 90, 90, 15, 16, 123, 123, 123, 113, 90, 90, 113, 113, 90, 113, 17, 31, 65, 81, 82, 113, 113, 174, 16, 64, 96, 113, 64, 87, 64, 113, 113, 90, 174, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 34, 35, 36, 37, 46, 47, 48, 49, 52, 53, 54, 62, 63, 67, 68, 69, 70, 73, 74, 75, 76, 77, 78, 79, 80, 83, 84, 86, 91, 92, 93, 113, 124, 174, 0, 122, 113, 90, 90, 113, 114, 114, 114, 114, 114, 114, 123, 114, 173, 173, 173, 98, 99, 103, 104, 105, 106, 107, 108, 109, 115, 113, 174, 174, 174, 174, 174, 98, 99, 103, 104, 105, 106, 107, 108, 109, 113, 115, 174, 113, 113, 113, 113, 113, 113, 113, 90, 148, 148, 148, 148, 113, 113, 113, 64, 113, 64, 113, 113, 174, 113, 64, 90, 90, 113, 90, 113, 113, 113, 174, 123, 113, 114, 104, 107, 113, 174, 113, 113, 113, 90, 113, 113, 113, 113, 113, 113, 113, 174, 113, 174, 174, 113, 113, 113, 113, 90, 113, 64, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 174, 174, 174, 174, 174, 90, 113, 174, 118, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 118, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 113, 148, 148, 148, 148, 113, 64, 113, 113, 113, 90, 90, 113, 113, 174, 113, 90, 174, 174, 113, 113, 113, 174, 113, 174, 113, 174, 113, 90, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113, 113 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. However, YYFAIL appears to be in use. Nevertheless, it is formally deprecated in Bison 2.4.2's NEWS entry, where a plan to phase it out is discussed. */ #define YYFAIL goto yyerrlab #if defined YYFAIL /* This is here to suppress warnings from the GCC cpp's -Wunused-macros. Normally we don't worry about that warning, but some users do, and we want to make it easy for users to remove YYFAIL uses, which will produce warnings from Bison 2.5. */ #endif #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ YYPOPSTACK (1); \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (YYID (0)) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (YYID (N)) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (YYID (0)) #endif /* This macro is provided for backward compatibility. */ #ifndef YY_LOCATION_PRINT # define YY_LOCATION_PRINT(File, Loc) ((void) 0) #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (YYID (0)) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yy_symbol_print (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (YYID (0)) /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_value_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (!yyvaluep) return; # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # else YYUSE (yyoutput); # endif switch (yytype) { default: break; } } /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) #else static void yy_symbol_print (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE const * const yyvaluep; #endif { if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); yy_symbol_value_print (yyoutput, yytype, yyvaluep); YYFPRINTF (yyoutput, ")"); } /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) #else static void yy_stack_print (yybottom, yytop) yytype_int16 *yybottom; yytype_int16 *yytop; #endif { YYFPRINTF (stderr, "Stack now"); for (; yybottom <= yytop; yybottom++) { int yybot = *yybottom; YYFPRINTF (stderr, " %d", yybot); } YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (YYID (0)) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yy_reduce_print (YYSTYPE *yyvsp, int yyrule) #else static void yy_reduce_print (yyvsp, yyrule) YYSTYPE *yyvsp; int yyrule; #endif { int yynrhs = yyr2[yyrule]; int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", yyrule - 1, yylno); /* The symbols being reduced. */ for (yyi = 0; yyi < yynrhs; yyi++) { YYFPRINTF (stderr, " $%d = ", yyi + 1); yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], &(yyvsp[(yyi + 1) - (yynrhs)]) ); YYFPRINTF (stderr, "\n"); } } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (yyvsp, Rule); \ } while (YYID (0)) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined __GLIBC__ && defined _STRING_H # define yystrlen strlen # else /* Return the length of YYSTR. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static YYSIZE_T yystrlen (const char *yystr) #else static YYSIZE_T yystrlen (yystr) const char *yystr; #endif { YYSIZE_T yylen; for (yylen = 0; yystr[yylen]; yylen++) continue; return yylen; } # endif # endif # ifndef yystpcpy # if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static char * yystpcpy (char *yydest, const char *yysrc) #else static char * yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; #endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { YYSIZE_T yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif /* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message about the unexpected token YYTOKEN for the state stack whose top is YYSSP. Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is not large enough to hold the message. In that case, also set *YYMSG_ALLOC to the required number of bytes. Return 2 if the required number of bytes is too large to store. */ static int yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, yytype_int16 *yyssp, int yytoken) { YYSIZE_T yysize0 = yytnamerr (0, yytname[yytoken]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; /* Internationalized format string. */ const char *yyformat = 0; /* Arguments of yyformat. */ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; /* Number of reported tokens (one for the "unexpected", one per "expected"). */ int yycount = 0; /* There are many possibilities here to consider: - Assume YYFAIL is not used. It's too flawed to consider. See for details. YYERROR is fine as it does not invoke this function. - If this state is a consistent state with a default action, then the only way this function was invoked is if the default action is an error action. In that case, don't check for expected tokens because there are none. - The only way there can be no lookahead present (in yychar) is if this state is a consistent state with a default action. Thus, detecting the absence of a lookahead is sufficient to determine that there is no unexpected or expected token to report. In that case, just report a simple "syntax error". - Don't assume there isn't a lookahead just because this state is a consistent state with a default action. There might have been a previous inconsistent state, consistent state with a non-default action, or user semantic action that manipulated yychar. - Of course, the expected token list depends on states to have correct lookahead information, and it depends on the parser not to perform extra reductions after fetching a lookahead from the scanner and before detecting a syntax error. Thus, state merging (from LALR or IELR) and default reductions corrupt the expected token list. However, the list is correct for canonical LR with one exception: it will still contain any token that will not be accepted due to an error action in a later state. */ if (yytoken != YYEMPTY) { int yyn = yypact[*yyssp]; yyarg[yycount++] = yytname[yytoken]; if (!yypact_value_is_default (yyn)) { /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. In other words, skip the first -YYN actions for this state because they are default actions. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn + 1; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yyx; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR && !yytable_value_is_error (yytable[yyx + yyn])) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; } } } switch (yycount) { # define YYCASE_(N, S) \ case N: \ yyformat = S; \ break YYCASE_(0, YY_("syntax error")); YYCASE_(1, YY_("syntax error, unexpected %s")); YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); # undef YYCASE_ } yysize1 = yysize + yystrlen (yyformat); if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) return 2; yysize = yysize1; if (*yymsg_alloc < yysize) { *yymsg_alloc = 2 * yysize; if (! (yysize <= *yymsg_alloc && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; return 1; } /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ { char *yyp = *yymsg; int yyi = 0; while ((*yyp = *yyformat) != '\0') if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyformat += 2; } else { yyp++; yyformat++; } } return 0; } #endif /* YYERROR_VERBOSE */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ /*ARGSUSED*/ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { YYUSE (yyvaluep); if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM #if defined __STDC__ || defined __cplusplus int yyparse (void *YYPARSE_PARAM); #else int yyparse (); #endif #else /* ! YYPARSE_PARAM */ #if defined __STDC__ || defined __cplusplus int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void *YYPARSE_PARAM) #else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; #endif #else /* ! YYPARSE_PARAM */ #if (defined __STDC__ || defined __C99__FUNC__ \ || defined __cplusplus || defined _MSC_VER) int yyparse (void) #else int yyparse () #endif #endif { int yystate; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* The stacks and their tools: `yyss': related to states. `yyvs': related to semantic values. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ yytype_int16 yyssa[YYINITDEPTH]; yytype_int16 *yyss; yytype_int16 *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs; YYSTYPE *yyvsp; YYSIZE_T yystacksize; int yyn; int yyresult; /* Lookahead token as an internal (translated) token number. */ int yytoken; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; #if YYERROR_VERBOSE /* Buffer for error messages, and its allocated size. */ char yymsgbuf[128]; char *yymsg = yymsgbuf; YYSIZE_T yymsg_alloc = sizeof yymsgbuf; #endif #define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) /* The number of symbols on the RHS of the reduced rule. Keep to zero when no symbol should be popped. */ int yylen = 0; yytoken = 0; yyss = yyssa; yyvs = yyvsa; yystacksize = YYINITDEPTH; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. So pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; yytype_int16 *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { yytype_int16 *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss_alloc, yyss); YYSTACK_RELOCATE (yyvs_alloc, yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); if (yystate == YYFINAL) YYACCEPT; goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. Read a lookahead token if we need one and don't already have one. */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yypact_value_is_default (yyn)) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yytable_value_is_error (yyn)) goto yyerrlab; yyn = -yyn; goto yyreduce; } /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; /* Shift the lookahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the shifted token. */ yychar = YYEMPTY; yystate = yyn; *++yyvsp = yylval; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 51: /* Line 1806 of yacc.c */ #line 190 "parser.y" { } break; case 53: /* Line 1806 of yacc.c */ #line 197 "parser.y" { (yyval.bval)=(yyvsp[(1) - (1)].bval); } break; case 55: /* Line 1806 of yacc.c */ #line 203 "parser.y" { (yyval.sval)=(yyvsp[(1) - (1)].sval); } break; case 61: /* Line 1806 of yacc.c */ #line 213 "parser.y" { (yyval.uval)=(yyvsp[(1) - (1)].uval); } break; case 62: /* Line 1806 of yacc.c */ #line 218 "parser.y" { bx_dbg_timebp_command(0, (yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 63: /* Line 1806 of yacc.c */ #line 223 "parser.y" { bx_dbg_timebp_command(1, (yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 64: /* Line 1806 of yacc.c */ #line 231 "parser.y" { bx_dbg_modebp_command(); free((yyvsp[(1) - (2)].sval)); } break; case 65: /* Line 1806 of yacc.c */ #line 239 "parser.y" { bx_dbg_vmexitbp_command(); free((yyvsp[(1) - (2)].sval)); } break; case 66: /* Line 1806 of yacc.c */ #line 247 "parser.y" { bx_dbg_show_command((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 67: /* Line 1806 of yacc.c */ #line 252 "parser.y" { bx_dbg_show_command("off"); free((yyvsp[(1) - (3)].sval)); } break; case 68: /* Line 1806 of yacc.c */ #line 257 "parser.y" { bx_dbg_show_param_command((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 69: /* Line 1806 of yacc.c */ #line 262 "parser.y" { bx_dbg_show_command(0); free((yyvsp[(1) - (2)].sval)); } break; case 70: /* Line 1806 of yacc.c */ #line 270 "parser.y" { bx_dbg_xlate_address((yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 71: /* Line 1806 of yacc.c */ #line 278 "parser.y" { bx_dbg_ptime_command(); free((yyvsp[(1) - (2)].sval)); } break; case 72: /* Line 1806 of yacc.c */ #line 286 "parser.y" { bx_dbg_trace_command((yyvsp[(2) - (3)].bval)); free((yyvsp[(1) - (3)].sval)); } break; case 73: /* Line 1806 of yacc.c */ #line 294 "parser.y" { bx_dbg_trace_reg_command((yyvsp[(2) - (3)].bval)); free((yyvsp[(1) - (3)].sval)); } break; case 74: /* Line 1806 of yacc.c */ #line 302 "parser.y" { bx_dbg_trace_mem_command((yyvsp[(2) - (3)].bval)); free((yyvsp[(1) - (3)].sval)); } break; case 75: /* Line 1806 of yacc.c */ #line 310 "parser.y" { bx_dbg_print_stack_command(16); free((yyvsp[(1) - (2)].sval)); } break; case 76: /* Line 1806 of yacc.c */ #line 315 "parser.y" { bx_dbg_print_stack_command((yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 77: /* Line 1806 of yacc.c */ #line 323 "parser.y" { bx_dbg_watchpoint_continue(0); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 78: /* Line 1806 of yacc.c */ #line 328 "parser.y" { bx_dbg_watchpoint_continue(1); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 79: /* Line 1806 of yacc.c */ #line 333 "parser.y" { bx_dbg_print_watchpoints(); free((yyvsp[(1) - (2)].sval)); } break; case 80: /* Line 1806 of yacc.c */ #line 338 "parser.y" { bx_dbg_watch(0, (yyvsp[(3) - (4)].uval), 1); /* BX_READ */ free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 81: /* Line 1806 of yacc.c */ #line 343 "parser.y" { bx_dbg_watch(0, (yyvsp[(3) - (4)].uval), 1); /* BX_READ */ free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 82: /* Line 1806 of yacc.c */ #line 348 "parser.y" { bx_dbg_watch(1, (yyvsp[(3) - (4)].uval), 1); /* BX_WRITE */ free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 83: /* Line 1806 of yacc.c */ #line 353 "parser.y" { bx_dbg_watch(0, (yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); /* BX_READ */ free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 84: /* Line 1806 of yacc.c */ #line 358 "parser.y" { bx_dbg_watch(0, (yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); /* BX_READ */ free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 85: /* Line 1806 of yacc.c */ #line 363 "parser.y" { bx_dbg_watch(1, (yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); /* BX_WRITE */ free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 86: /* Line 1806 of yacc.c */ #line 368 "parser.y" { bx_dbg_unwatch_all(); free((yyvsp[(1) - (2)].sval)); } break; case 87: /* Line 1806 of yacc.c */ #line 373 "parser.y" { bx_dbg_unwatch((yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 88: /* Line 1806 of yacc.c */ #line 381 "parser.y" { bx_dbg_symbol_command((yyvsp[(2) - (3)].sval), 0, 0); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 89: /* Line 1806 of yacc.c */ #line 386 "parser.y" { bx_dbg_symbol_command((yyvsp[(2) - (4)].sval), 0, (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 90: /* Line 1806 of yacc.c */ #line 391 "parser.y" { bx_dbg_symbol_command((yyvsp[(3) - (4)].sval), 1, 0); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); free((yyvsp[(3) - (4)].sval)); } break; case 91: /* Line 1806 of yacc.c */ #line 396 "parser.y" { bx_dbg_symbol_command((yyvsp[(3) - (5)].sval), 1, (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); free((yyvsp[(3) - (5)].sval)); } break; case 92: /* Line 1806 of yacc.c */ #line 404 "parser.y" { bx_dbg_where_command(); free((yyvsp[(1) - (2)].sval)); } break; case 93: /* Line 1806 of yacc.c */ #line 412 "parser.y" { bx_dbg_print_string_command((yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 94: /* Line 1806 of yacc.c */ #line 420 "parser.y" { bx_dbg_continue_command(); free((yyvsp[(1) - (2)].sval)); } break; case 95: /* Line 1806 of yacc.c */ #line 428 "parser.y" { bx_dbg_stepN_command(dbg_cpu, 1); free((yyvsp[(1) - (2)].sval)); } break; case 96: /* Line 1806 of yacc.c */ #line 433 "parser.y" { bx_dbg_stepN_command(dbg_cpu, (yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 97: /* Line 1806 of yacc.c */ #line 438 "parser.y" { bx_dbg_stepN_command(-1, (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 98: /* Line 1806 of yacc.c */ #line 443 "parser.y" { bx_dbg_stepN_command((yyvsp[(2) - (4)].uval), (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); } break; case 99: /* Line 1806 of yacc.c */ #line 451 "parser.y" { bx_dbg_step_over_command(); free((yyvsp[(1) - (2)].sval)); } break; case 100: /* Line 1806 of yacc.c */ #line 459 "parser.y" { bx_dbg_set_auto_disassemble((yyvsp[(3) - (4)].bval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 101: /* Line 1806 of yacc.c */ #line 464 "parser.y" { bx_dbg_set_symbol_command((yyvsp[(2) - (5)].sval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 102: /* Line 1806 of yacc.c */ #line 469 "parser.y" { bx_dbg_set_reg8l_value((yyvsp[(2) - (5)].uval), (yyvsp[(4) - (5)].uval)); } break; case 103: /* Line 1806 of yacc.c */ #line 473 "parser.y" { bx_dbg_set_reg8h_value((yyvsp[(2) - (5)].uval), (yyvsp[(4) - (5)].uval)); } break; case 104: /* Line 1806 of yacc.c */ #line 477 "parser.y" { bx_dbg_set_reg16_value((yyvsp[(2) - (5)].uval), (yyvsp[(4) - (5)].uval)); } break; case 105: /* Line 1806 of yacc.c */ #line 481 "parser.y" { bx_dbg_set_reg32_value((yyvsp[(2) - (5)].uval), (yyvsp[(4) - (5)].uval)); } break; case 106: /* Line 1806 of yacc.c */ #line 485 "parser.y" { bx_dbg_set_reg64_value((yyvsp[(2) - (5)].uval), (yyvsp[(4) - (5)].uval)); } break; case 107: /* Line 1806 of yacc.c */ #line 489 "parser.y" { bx_dbg_load_segreg((yyvsp[(2) - (5)].uval), (yyvsp[(4) - (5)].uval)); } break; case 108: /* Line 1806 of yacc.c */ #line 496 "parser.y" { bx_dbg_vbreakpoint_command(bkAtIP, 0, 0); free((yyvsp[(1) - (2)].sval)); } break; case 109: /* Line 1806 of yacc.c */ #line 501 "parser.y" { bx_dbg_vbreakpoint_command(bkRegular, (yyvsp[(2) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); } break; case 110: /* Line 1806 of yacc.c */ #line 506 "parser.y" { bx_dbg_lbreakpoint_command(bkAtIP, 0); free((yyvsp[(1) - (2)].sval)); } break; case 111: /* Line 1806 of yacc.c */ #line 511 "parser.y" { bx_dbg_lbreakpoint_command(bkRegular, (yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 112: /* Line 1806 of yacc.c */ #line 516 "parser.y" { bx_dbg_lbreakpoint_symbol_command((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 113: /* Line 1806 of yacc.c */ #line 521 "parser.y" { bx_dbg_pbreakpoint_command(bkAtIP, 0); free((yyvsp[(1) - (2)].sval)); } break; case 114: /* Line 1806 of yacc.c */ #line 526 "parser.y" { bx_dbg_pbreakpoint_command(bkRegular, (yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 115: /* Line 1806 of yacc.c */ #line 531 "parser.y" { bx_dbg_pbreakpoint_command(bkRegular, (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); } break; case 116: /* Line 1806 of yacc.c */ #line 539 "parser.y" { bx_dbg_info_bpoints_command(); free((yyvsp[(1) - (2)].sval)); } break; case 117: /* Line 1806 of yacc.c */ #line 547 "parser.y" { bx_dbg_info_symbols_command(0); free((yyvsp[(1) - (2)].sval)); } break; case 118: /* Line 1806 of yacc.c */ #line 552 "parser.y" { bx_dbg_info_symbols_command((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 119: /* Line 1806 of yacc.c */ #line 560 "parser.y" { bx_dbg_info_bpoints_command(); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 120: /* Line 1806 of yacc.c */ #line 565 "parser.y" { bx_dbg_info_registers_command(-1); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 121: /* Line 1806 of yacc.c */ #line 570 "parser.y" { bx_dbg_info_idt_command((yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 122: /* Line 1806 of yacc.c */ #line 575 "parser.y" { bx_dbg_info_ivt_command((yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 123: /* Line 1806 of yacc.c */ #line 580 "parser.y" { bx_dbg_info_gdt_command((yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 124: /* Line 1806 of yacc.c */ #line 585 "parser.y" { bx_dbg_info_ldt_command((yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 125: /* Line 1806 of yacc.c */ #line 590 "parser.y" { bx_dbg_dump_table(); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 126: /* Line 1806 of yacc.c */ #line 595 "parser.y" { bx_dbg_info_tss_command(); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 127: /* Line 1806 of yacc.c */ #line 600 "parser.y" { bx_dbg_info_flags(); free((yyvsp[(1) - (3)].sval)); } break; case 128: /* Line 1806 of yacc.c */ #line 605 "parser.y" { bx_dbg_info_linux_command(); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 129: /* Line 1806 of yacc.c */ #line 610 "parser.y" { bx_dbg_info_symbols_command(0); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 130: /* Line 1806 of yacc.c */ #line 615 "parser.y" { bx_dbg_info_symbols_command((yyvsp[(3) - (4)].sval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); free((yyvsp[(3) - (4)].sval)); } break; case 131: /* Line 1806 of yacc.c */ #line 620 "parser.y" { bx_dbg_info_device("", ""); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 132: /* Line 1806 of yacc.c */ #line 625 "parser.y" { bx_dbg_info_device((yyvsp[(3) - (4)].sval), ""); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 133: /* Line 1806 of yacc.c */ #line 630 "parser.y" { bx_dbg_info_device((yyvsp[(3) - (5)].sval), (yyvsp[(4) - (5)].sval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 134: /* Line 1806 of yacc.c */ #line 637 "parser.y" { (yyval.uval) = EMPTY_ARG; } break; case 136: /* Line 1806 of yacc.c */ #line 642 "parser.y" { bx_dbg_info_registers_command(BX_INFO_GENERAL_PURPOSE_REGS); free((yyvsp[(1) - (2)].sval)); } break; case 137: /* Line 1806 of yacc.c */ #line 650 "parser.y" { bx_dbg_info_registers_command(BX_INFO_FPU_REGS); free((yyvsp[(1) - (2)].sval)); } break; case 138: /* Line 1806 of yacc.c */ #line 658 "parser.y" { bx_dbg_info_registers_command(BX_INFO_MMX_REGS); free((yyvsp[(1) - (2)].sval)); } break; case 139: /* Line 1806 of yacc.c */ #line 666 "parser.y" { bx_dbg_info_registers_command(BX_INFO_SSE_REGS); free((yyvsp[(1) - (2)].sval)); } break; case 140: /* Line 1806 of yacc.c */ #line 674 "parser.y" { bx_dbg_info_registers_command(BX_INFO_AVX_REGS); free((yyvsp[(1) - (2)].sval)); } break; case 141: /* Line 1806 of yacc.c */ #line 682 "parser.y" { bx_dbg_info_segment_regs_command(); free((yyvsp[(1) - (2)].sval)); } break; case 142: /* Line 1806 of yacc.c */ #line 690 "parser.y" { bx_dbg_info_control_regs_command(); free((yyvsp[(1) - (2)].sval)); } break; case 143: /* Line 1806 of yacc.c */ #line 698 "parser.y" { bx_dbg_info_debug_regs_command(); free((yyvsp[(1) - (2)].sval)); } break; case 144: /* Line 1806 of yacc.c */ #line 706 "parser.y" { bx_dbg_del_breakpoint_command((yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 145: /* Line 1806 of yacc.c */ #line 714 "parser.y" { bx_dbg_en_dis_breakpoint_command((yyvsp[(2) - (3)].uval), 1); free((yyvsp[(1) - (3)].sval)); } break; case 146: /* Line 1806 of yacc.c */ #line 721 "parser.y" { bx_dbg_en_dis_breakpoint_command((yyvsp[(2) - (3)].uval), 0); free((yyvsp[(1) - (3)].sval)); } break; case 147: /* Line 1806 of yacc.c */ #line 729 "parser.y" { bx_dbg_quit_command(); free((yyvsp[(1) - (2)].sval)); } break; case 148: /* Line 1806 of yacc.c */ #line 737 "parser.y" { bx_dbg_examine_command((yyvsp[(1) - (4)].sval), (yyvsp[(2) - (4)].sval),1, (yyvsp[(3) - (4)].uval), 1); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 149: /* Line 1806 of yacc.c */ #line 742 "parser.y" { bx_dbg_examine_command((yyvsp[(1) - (3)].sval), (yyvsp[(2) - (3)].sval),1, 0, 0); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 150: /* Line 1806 of yacc.c */ #line 747 "parser.y" { bx_dbg_examine_command((yyvsp[(1) - (3)].sval), NULL,0, (yyvsp[(2) - (3)].uval), 1); free((yyvsp[(1) - (3)].sval)); } break; case 151: /* Line 1806 of yacc.c */ #line 752 "parser.y" { bx_dbg_examine_command((yyvsp[(1) - (2)].sval), NULL,0, 0, 0); free((yyvsp[(1) - (2)].sval)); } break; case 152: /* Line 1806 of yacc.c */ #line 760 "parser.y" { bx_dbg_restore_command((yyvsp[(2) - (4)].sval), (yyvsp[(3) - (4)].sval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); free((yyvsp[(3) - (4)].sval)); } break; case 153: /* Line 1806 of yacc.c */ #line 768 "parser.y" { bx_dbg_writemem_command((yyvsp[(2) - (5)].sval), (yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 154: /* Line 1806 of yacc.c */ #line 776 "parser.y" { bx_dbg_setpmem_command((yyvsp[(2) - (5)].uval), (yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); } break; case 155: /* Line 1806 of yacc.c */ #line 784 "parser.y" { bx_dbg_query_command((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 156: /* Line 1806 of yacc.c */ #line 792 "parser.y" { bx_dbg_take_command((yyvsp[(2) - (3)].sval), 1); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 157: /* Line 1806 of yacc.c */ #line 797 "parser.y" { bx_dbg_take_command((yyvsp[(2) - (4)].sval), (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 158: /* Line 1806 of yacc.c */ #line 802 "parser.y" { bx_dbg_take_command((yyvsp[(2) - (3)].sval), 1); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 159: /* Line 1806 of yacc.c */ #line 810 "parser.y" { bx_dbg_disassemble_current(NULL); free((yyvsp[(1) - (2)].sval)); } break; case 160: /* Line 1806 of yacc.c */ #line 815 "parser.y" { bx_dbg_disassemble_command(NULL, (yyvsp[(2) - (3)].uval), (yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 161: /* Line 1806 of yacc.c */ #line 820 "parser.y" { bx_dbg_disassemble_command(NULL, (yyvsp[(2) - (4)].uval), (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); } break; case 162: /* Line 1806 of yacc.c */ #line 825 "parser.y" { bx_dbg_disassemble_current((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 163: /* Line 1806 of yacc.c */ #line 830 "parser.y" { bx_dbg_disassemble_command((yyvsp[(2) - (4)].sval), (yyvsp[(3) - (4)].uval), (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 164: /* Line 1806 of yacc.c */ #line 835 "parser.y" { bx_dbg_disassemble_command((yyvsp[(2) - (5)].sval), (yyvsp[(3) - (5)].uval), (yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 165: /* Line 1806 of yacc.c */ #line 840 "parser.y" { bx_dbg_disassemble_switch_mode(); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 166: /* Line 1806 of yacc.c */ #line 845 "parser.y" { bx_dbg_disassemble_hex_mode_switch((yyvsp[(3) - (4)].bval)); free((yyvsp[(1) - (4)].sval)); free((yyvsp[(2) - (4)].sval)); } break; case 167: /* Line 1806 of yacc.c */ #line 850 "parser.y" { bx_dbg_set_disassemble_size((yyvsp[(4) - (5)].uval)); free((yyvsp[(1) - (5)].sval)); free((yyvsp[(2) - (5)].sval)); } break; case 168: /* Line 1806 of yacc.c */ #line 858 "parser.y" { bx_dbg_instrument_command((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 169: /* Line 1806 of yacc.c */ #line 863 "parser.y" { bx_dbg_instrument_command((yyvsp[(2) - (3)].sval)); free((yyvsp[(1) - (3)].sval)); free((yyvsp[(2) - (3)].sval)); } break; case 170: /* Line 1806 of yacc.c */ #line 871 "parser.y" { bx_dbg_doit_command((yyvsp[(2) - (3)].uval)); free((yyvsp[(1) - (3)].sval)); } break; case 171: /* Line 1806 of yacc.c */ #line 879 "parser.y" { bx_dbg_crc_command((yyvsp[(2) - (4)].uval), (yyvsp[(3) - (4)].uval)); free((yyvsp[(1) - (4)].sval)); } break; case 172: /* Line 1806 of yacc.c */ #line 887 "parser.y" { dbg_printf("q|quit|exit - quit debugger and emulator execution\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 173: /* Line 1806 of yacc.c */ #line 892 "parser.y" { dbg_printf("c|cont|continue - continue executing\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 174: /* Line 1806 of yacc.c */ #line 897 "parser.y" { dbg_printf("s|step [count] - execute #count instructions on current processor (default is one instruction)\n"); dbg_printf("s|step [cpu] - execute #count instructions on processor #cpu\n"); dbg_printf("s|step all - execute #count instructions on all the processors\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 175: /* Line 1806 of yacc.c */ #line 904 "parser.y" { dbg_printf("n|next|p - execute instruction stepping over subroutines\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 176: /* Line 1806 of yacc.c */ #line 909 "parser.y" { dbg_printf("vb|vbreak - set a virtual address instruction breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 177: /* Line 1806 of yacc.c */ #line 914 "parser.y" { dbg_printf("lb|lbreak - set a linear address instruction breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 178: /* Line 1806 of yacc.c */ #line 919 "parser.y" { dbg_printf("p|pb|break|pbreak - set a physical address instruction breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 179: /* Line 1806 of yacc.c */ #line 924 "parser.y" { dbg_printf("d|del|delete - delete a breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 180: /* Line 1806 of yacc.c */ #line 929 "parser.y" { dbg_printf("bpe - enable a breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 181: /* Line 1806 of yacc.c */ #line 934 "parser.y" { dbg_printf("bpd - disable a breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 182: /* Line 1806 of yacc.c */ #line 939 "parser.y" { dbg_printf("blist - list all breakpoints (same as 'info break')\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 183: /* Line 1806 of yacc.c */ #line 944 "parser.y" { dbg_printf("modebp - toggles mode switch breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 184: /* Line 1806 of yacc.c */ #line 949 "parser.y" { dbg_printf("vmexitbp - toggles VMEXIT switch breakpoint\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 185: /* Line 1806 of yacc.c */ #line 954 "parser.y" { dbg_printf("crc - show CRC32 for physical memory range addr1..addr2\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 186: /* Line 1806 of yacc.c */ #line 959 "parser.y" { dbg_printf("trace on - print disassembly for every executed instruction\n"); dbg_printf("trace off - disable instruction tracing\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 187: /* Line 1806 of yacc.c */ #line 965 "parser.y" { dbg_printf("trace-reg on - print all registers before every executed instruction\n"); dbg_printf("trace-reg off - disable registers state tracing\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 188: /* Line 1806 of yacc.c */ #line 971 "parser.y" { dbg_printf("trace-mem on - print all memory accesses occured during instruction execution\n"); dbg_printf("trace-mem off - disable memory accesses tracing\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 189: /* Line 1806 of yacc.c */ #line 977 "parser.y" { dbg_printf("restore [path] - restore bochs root param from the file\n"); dbg_printf("for example:\n"); dbg_printf("restore \"cpu0\" - restore CPU #0 from file \"cpu0\" in current directory\n"); dbg_printf("restore \"cpu0\" \"/save\" - restore CPU #0 from file \"cpu0\" located in directory \"/save\"\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 190: /* Line 1806 of yacc.c */ #line 985 "parser.y" { dbg_printf("ptime - print current time (number of ticks since start of simulation)\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 191: /* Line 1806 of yacc.c */ #line 990 "parser.y" { dbg_printf("sb - insert a time breakpoint delta instructions into the future\n"); free((yyvsp[(1) - (3)].sval));free((yyvsp[(2) - (3)].sval)); } break; case 192: /* Line 1806 of yacc.c */ #line 995 "parser.y" { dbg_printf("sba &1 /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case "$host_cpu" in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; irix5* | irix6* | nonstopux*) case $host_os in irix5* | nonstopux*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" ;; *) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" ;; esac lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux*) case $host_cpu in alpha* | hppa* | i*86 | ia64* | m68* | mips* | powerpc* | sparc* | s390* | sh*) lt_cv_deplibs_check_method=pass_all ;; *) # glibc up to 2.1.1 does not perform some relocations on ARM lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; esac lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; nto-qnx*) lt_cv_deplibs_check_method=unknown ;; openbsd*) lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' else lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' fi ;; osf3* | osf4* | osf5*) # this will be overridden with pass_all, but let us keep it just in case lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' lt_cv_file_magic_test_file=/shlib/libc.so lt_cv_deplibs_check_method=pass_all ;; sco3.2v5*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all lt_cv_file_magic_test_file=/lib/libc.so ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown ])# AC_DEPLIBS_CHECK_METHOD # AC_PROG_NM # ---------- # find the pathname to a BSD-compatible name lister AC_DEFUN([AC_PROG_NM], [AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/${ac_tool_prefix}nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac esac fi done IFS="$lt_save_ifs" test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm fi]) NM="$lt_cv_path_NM" ])# AC_PROG_NM # AC_CHECK_LIBM # ------------- # check for math library AC_DEFUN([AC_CHECK_LIBM], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM="-lm") ;; esac ])# AC_CHECK_LIBM # AC_LIBLTDL_CONVENIENCE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl convenience library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL # and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If # DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will # be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with # '${top_srcdir}/' (note the single quotes!). If your package is not # flat and you're not using automake, define top_builddir and # top_srcdir appropriately in the Makefiles. AC_DEFUN([AC_LIBLTDL_CONVENIENCE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl case $enable_ltdl_convenience in no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; "") enable_ltdl_convenience=yes ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; esac LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_CONVENIENCE # AC_LIBLTDL_INSTALLABLE([DIRECTORY]) # ----------------------------------- # sets LIBLTDL to the link flags for the libltdl installable library and # LTDLINCL to the include flags for the libltdl header and adds # --enable-ltdl-install to the configure arguments. Note that LIBLTDL # and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If # DIRECTORY is not provided and an installed libltdl is not found, it is # assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' # and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single # quotes!). If your package is not flat and you're not using automake, # define top_builddir and top_srcdir appropriately in the Makefiles. # In the future, this macro may have to be called after AC_PROG_LIBTOOL. AC_DEFUN([AC_LIBLTDL_INSTALLABLE], [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl AC_CHECK_LIB(ltdl, lt_dlinit, [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], [if test x"$enable_ltdl_install" = xno; then AC_MSG_WARN([libltdl not installed, but installation disabled]) else enable_ltdl_install=yes fi ]) if test x"$enable_ltdl_install" = x"yes"; then ac_configure_args="$ac_configure_args --enable-ltdl-install" LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) else ac_configure_args="$ac_configure_args --enable-ltdl-install=no" LIBLTDL="-lltdl" LTDLINCL= fi # For backwards non-gettext consistent compatibility... INCLTDL="$LTDLINCL" ])# AC_LIBLTDL_INSTALLABLE # AC_LIBTOOL_CXX # -------------- # enable support for C++ libraries AC_DEFUN([AC_LIBTOOL_CXX], [AC_REQUIRE([_LT_AC_LANG_CXX]) ])# AC_LIBTOOL_CXX # _LT_AC_LANG_CXX # --------------- AC_DEFUN([_LT_AC_LANG_CXX], [AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([AC_PROG_CXXCPP]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) ])# _LT_AC_LANG_CXX # AC_LIBTOOL_F77 # -------------- # enable support for Fortran 77 libraries AC_DEFUN([AC_LIBTOOL_F77], [AC_REQUIRE([_LT_AC_LANG_F77]) ])# AC_LIBTOOL_F77 # _LT_AC_LANG_F77 # --------------- AC_DEFUN([_LT_AC_LANG_F77], [AC_REQUIRE([AC_PROG_F77]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) ])# _LT_AC_LANG_F77 # AC_LIBTOOL_GCJ # -------------- # enable support for GCJ libraries AC_DEFUN([AC_LIBTOOL_GCJ], [AC_REQUIRE([_LT_AC_LANG_GCJ]) ])# AC_LIBTOOL_GCJ # _LT_AC_LANG_GCJ # --------------- AC_DEFUN([_LT_AC_LANG_GCJ], [AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) ])# _LT_AC_LANG_GCJ # AC_LIBTOOL_RC # -------------- # enable support for Windows resource files AC_DEFUN([AC_LIBTOOL_RC], [AC_REQUIRE([LT_AC_PROG_RC]) _LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) ])# AC_LIBTOOL_RC # AC_LIBTOOL_LANG_C_CONFIG # ------------------------ # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) AC_DEFUN([_LT_AC_LANG_C_CONFIG], [lt_save_CC="$CC" AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}\n' _LT_AC_SYS_COMPILER # # Check for any special shared library compilation flags. # _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= if test "$GCC" = no; then case $host_os in sco3.2v5*) _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' ;; esac fi if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$]_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[[ ]]" >/dev/null; then : else AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no fi fi # # Check to make sure the static flag actually works. # AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], _LT_AC_TAGVAR(lt_cv_prog_compiler_static_works, $1), $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), [], [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_SYS_LIB_STRIP AC_LIBTOOL_DLOPEN_SELF($1) # Report which librarie types wil actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case "$host_os" in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix4*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; darwin* | rhapsody*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case "$host_os" in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' ;; esac fi ;; esac output_verbose_link_cmd='echo' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes AC_MSG_RESULT([$enable_static]) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC="$lt_save_CC" ])# AC_LIBTOOL_LANG_C_CONFIG # AC_LIBTOOL_LANG_CXX_CONFIG # -------------------------- # Ensure that the configuration vars for the C compiler are # suitably defined. Those variables are subsequently used by # AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], [AC_LANG_PUSH(C++) AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([AC_PROG_CXXCPP]) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_AC_TAGVAR(no_undefined_flag, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Dependencies to place before and after the object being linked: _LT_AC_TAGVAR(predep_objects, $1)= _LT_AC_TAGVAR(postdep_objects, $1)= _LT_AC_TAGVAR(predeps, $1)= _LT_AC_TAGVAR(postdeps, $1)= _LT_AC_TAGVAR(compiler_lib_search_path, $1)= # Source file extension for C++ test sources. ac_ext=cc # Object file extension for compiled C++ test sources. objext=o _LT_AC_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;\n" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_AC_SYS_COMPILER # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} compiler=$CC _LT_AC_TAGVAR(compiler, $1)=$CC cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` # We don't want -fno-exception wen compiling C++ code, so set the # no_builtin_flag separately if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test "$GXX" = yes; then # Set up default GNU C++ configuration AC_PROG_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test "$with_gnu_ld" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='${wl}' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_AC_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GXX" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=yes else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) _LT_AC_TAGVAR(always_export_symbols, $1)=yes # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds it's shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; darwin* | rhapsody*) if test "$GXX" = yes; then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case "$host_os" in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; dgux*) case $cc_basename in ec++) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; ghcx) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd[12]*) # C++ shared libraries reported to be fairly broken before switch to ELF _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | kfreebsd*-gnu) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_AC_TAGVAR(ld_shlibs, $1)=yes ;; gnu*) ;; hpux9*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test $with_gnu_ld = no; then case "$host_cpu" in hppa*64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; *) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; esac fi case "$host_cpu" in hppa*64*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; ia64*) _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; *) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; aCC) case "$host_cpu" in hppa*64*|ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes; then if test $with_gnu_ld = no; then case "$host_cpu" in ia64*|hppa*64*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; irix5* | irix6*) case $cc_basename in CC) # SGI C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' fi fi _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; linux*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc) # Intel C++ with_gnu_ld=yes _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' ;; cxx) # Compaq C++ _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; osf3*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; osf4* | osf5*) case $cc_basename in KCC) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; RCC) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; cxx) _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ $rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' else # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; sco*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case $cc_basename in CC) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; lcc) # Lucid # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The C++ compiler is used as linker so we must use $wl # flag to pass the commands to the underlying system # linker. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx) # Green Hills C++ Compiler _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' if $CC --version | grep -v '^2\.7' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' fi ;; esac ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no _LT_AC_TAGVAR(GCC, $1)="$GXX" _LT_AC_TAGVAR(LD, $1)="$LD" ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... AC_LIBTOOL_POSTDEP_PREDEP($1) AC_LIBTOOL_PROG_COMPILER_PIC($1) AC_LIBTOOL_PROG_CC_C_O($1) AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) AC_LIBTOOL_PROG_LD_SHLIBS($1) AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) AC_LIBTOOL_SYS_LIB_STRIP AC_LIBTOOL_DLOPEN_SELF($1) AC_LIBTOOL_CONFIG($1) AC_LANG_POP CC=$lt_save_CC LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ldcxx=$with_gnu_ld with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld ])# AC_LIBTOOL_LANG_CXX_CONFIG # AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) # ------------------------ # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" ifelse([$1], [], [#! $SHELL # `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 # Free Software Foundation, Inc. # # This file is part of GNU Libtool: # Originally by Gordon Matzigkeit , 1996 # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="$SED -e s/^X//" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi # The names of the tagged configurations supported by this script. available_tags= # ### BEGIN LIBTOOL CONFIG], [# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) # Whether or not to disallow shared libs when runtime libs are static allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # The host system. host_alias=$host_alias host=$host # An echo program that does not interpret backslashes. echo=$lt_echo # The archiver. AR=$lt_AR AR_FLAGS=$lt_AR_FLAGS # A C compiler. LTCC=$lt_LTCC # A language-specific compiler. CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) # Is the compiler the GNU C compiler? with_gcc=$_LT_AC_TAGVAR(GCC, $1) # An ERE matcher. EGREP=$lt_EGREP # The linker used to build libraries. LD=$lt_[]_LT_AC_TAGVAR(LD, $1) # Whether we need hard or soft links. LN_S=$lt_LN_S # A BSD-compatible nm program. NM=$lt_NM # A symbol stripping program STRIP="$STRIP" # Used to examine libraries when file_magic_cmd begins "file" MAGIC_CMD=$MAGIC_CMD # Used on cygwin: DLL creation program. DLLTOOL="$DLLTOOL" # Used on cygwin: object dumper. OBJDUMP="$OBJDUMP" # Used on cygwin: assembler. AS="$AS" # The name of the directory that contains temporary libtool files. objdir=$objdir # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # How to pass a linker flag through the compiler. wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) # Object file suffix (normally "o"). objext="$ac_objext" # Old archive suffix (normally "a"). libext="$libext" # Shared library suffix (normally ".so"). shrext='$shrext' # Executable file suffix (normally ""). exeext="$exeext" # Additional compiler flags for building library objects. pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) pic_mode=$pic_mode # What is the maximum length of a command? max_cmd_len=$lt_cv_sys_max_cmd_len # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) # Must we lock files when doing compilation ? need_locks=$lt_need_locks # Do we need the lib prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Compiler flag to prevent dynamic linking. link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) # Compiler flag to generate thread-safe objects. thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) # Library versioning type. version_type=$version_type # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME. library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Commands used to build and install an old-style archive. RANLIB=$lt_RANLIB old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) # Commands used to build and install a shared archive. archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) postinstall_cmds=$lt_postinstall_cmds postuninstall_cmds=$lt_postuninstall_cmds # Commands used to build a loadable module (assumed same as above if empty) module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # Dependencies to place before the objects being linked to create a # shared library. predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) # Dependencies to place after the objects being linked to create a # shared library. postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) # Dependencies to place before the objects being linked to create a # shared library. predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) # Dependencies to place after the objects being linked to create a # shared library. postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) # The library search path used internally by the compiler when linking # a shared library. compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method == file_magic. file_magic_cmd=$lt_file_magic_cmd # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) # Flag that forces no undefined symbols. no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # Same as above, but a single script fragment to be evaled but not shown. finish_eval=$lt_finish_eval # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # This is the shared library runtime path variable. runpath_var=$runpath_var # This is the shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # How to hardcode a shared library path into an executable. hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist. hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) # If ld is used when linking, flag to hardcode \$libdir into # a binary during linking. This must work even if \$libdir does # not exist. hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) # Whether we need a single -rpath flag with a separated argument. hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) # Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the # resulting binary. hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) # Set to yes if using the -LDIR flag during linking hardcodes DIR into the # resulting binary. hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) # Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into # the resulting binary. hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) # Set to yes if building a shared library automatically hardcodes DIR into the library # and all subsequent libraries and executables linked against it. hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) # Variables whose values should be saved in libtool wrapper scripts and # restored at relink time. variables_saved_for_relink="$variables_saved_for_relink" # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) # Compile-time system search path for libraries sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Fix the shell variable \$srcfile for the compiler. fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" # Set to yes if exported symbols are required. always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) # The commands to list exported symbols. export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) # Symbols that must always be exported. include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) ifelse([$1],[], [# ### END LIBTOOL CONFIG], [# ### END LIBTOOL TAG CONFIG: $tagname]) __EOF__ ifelse([$1],[], [ case $host_os in aix3*) cat <<\EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi EOF ;; esac # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || \ (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ]) else # If there is no Makefile yet, we rely on a make rule to execute # `config.status --recheck' to rerun these tests and create the # libtool script then. test -f Makefile && make "$ltmain" fi ])# AC_LIBTOOL_CONFIG # AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi ])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # --------------------------------- AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_REQUIRE([AC_PROG_NM]) AC_REQUIRE([AC_OBJEXT]) # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Transform the above into a raw symbol and a C symbol. symxfrm='\1 \2\3 \3' # Transform an extracted symbol line into a proper C declaration lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32*) symcode='[[ABCDGISTW]]' ;; hpux*) # Its linker distinguishes data from code symbols if test "$host_cpu" = ia64; then symcode='[[ABCDEGRST]]' fi lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris* | sysv5*) symcode='[[BDRT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac # Try without a prefix undercore, then with it. for ac_symprfx in "" "_"; do # Write the raw and C identifiers. lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if grep ' nm_test_var$' "$nlist" >/dev/null; then if grep ' nm_test_func$' "$nlist" >/dev/null; then cat < conftest.$ac_ext #ifdef __cplusplus extern "C" { #endif EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' cat <> conftest.$ac_ext #if defined (__STDC__) && __STDC__ # define lt_ptr_t void * #else # define lt_ptr_t char * # define const #endif /* The mapping between symbol names and symbols. */ const struct { const char *name; lt_ptr_t address; } lt_preloaded_symbols[[]] = { EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext cat <<\EOF >> conftest.$ac_ext {0, (lt_ptr_t) 0} }; #ifdef __cplusplus } #endif EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_save_LIBS="$LIBS" lt_save_CFLAGS="$CFLAGS" LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS="$lt_save_LIBS" CFLAGS="$lt_save_CFLAGS" else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -f conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi ]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE # AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) # --------------------------------------- AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], [_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)= AC_MSG_CHECKING([for $compiler option to produce PIC]) ifelse([$1],[CXX],[ # C++ specific cases for pic, static, wl, etc. if test "$GXX" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | os2* | pw32*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix4* | aix5*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68) # Green Hills C++ Compiler # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; dgux*) case $cc_basename in ec++) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | kfreebsd*-gnu) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux*) case $cc_basename in KCC) # KAI C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; icpc) # Intel C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; cxx) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd*) ;; osf3* | osf4* | osf5*) case $cc_basename in KCC) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC) # Rational C++ 2.4.1 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx) # Digital/Compaq C++ _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; sco*) case $cc_basename in CC) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; *) ;; esac ;; solaris*) case $cc_basename in CC) # Sun C++ 4.2, 5.x and Centerline C++ _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx) # Green Hills C++ Compiler _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC) # Sun C++ 4.x _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc) # Lucid _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; tandem*) case $cc_basename in NCC) # NonStop-UX NCC 3.20 _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; unixware*) ;; vxworks*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test "$GCC" = yes; then _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; amigaos*) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | pw32* | os2*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case "$host_cpu" in hppa*64*|ia64*) # +Z the default ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; newsos6) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; linux*) case $CC in icc* | ecc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; ccc*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; esac ;; osf3* | osf4* | osf5*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; sco3.2v5*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' ;; solaris*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sunos4*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; uts4*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], _LT_AC_TAGVAR(lt_cv_prog_compiler_pic_works, $1), [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi case "$host_os" in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" ;; esac ]) # AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) # ------------------------------------ # See if the linker supports building shared libraries. AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) ifelse([$1],[CXX],[ _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' case $host_os in aix4* | aix5*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" ;; cygwin* | mingw*) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' ;; *) _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ],[ runpath_var= _LT_AC_TAGVAR(allow_undefined_flag, $1)= _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_AC_TAGVAR(archive_cmds, $1)= _LT_AC_TAGVAR(archive_expsym_cmds, $1)= _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown _LT_AC_TAGVAR(hardcode_automatic, $1)=no _LT_AC_TAGVAR(module_cmds, $1)= _LT_AC_TAGVAR(module_expsym_cmds, $1)= _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_AC_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; openbsd*) with_gnu_ld=no ;; esac _LT_AC_TAGVAR(ld_shlibs, $1)=yes if test "$with_gnu_ld" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # See if GNU ld supports shared libraries. case $host_os in aix3* | aix4* | aix5*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <&2 *** Warning: the GNU linker, at least up to release 2.9.1, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to modify your PATH *** so that a non-GNU linker is found, and then restart. EOF fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Samuel A. Falvo II reports # that the semantics of dynamic libraries on AmigaOS, at least up # to version 4, is to share data among multiple programs linked # with the same dynamic library. Since this doesn't match the # behavior of shared libraries on other platforms, we can't use # them. _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32*) # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=no _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris* | sysv5*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then _LT_AC_TAGVAR(ld_shlibs, $1)=no cat <&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. EOF elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; sunos4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; linux*) if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" supports_anon_versioning=no case `$LD -v 2>/dev/null` in *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac if test $supports_anon_versioning = yes; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ $echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' else _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" fi else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then runpath_var=LD_RUN_PATH _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= fi fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(always_export_symbols, $1)=yes _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes if test "$GCC" = yes && test -z "$link_static_flag"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix4* | aix5*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm if $NM -V 2>&1 | grep 'GNU' > /dev/null; then _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' else _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_AC_TAGVAR(archive_cmds, $1)='' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=yes else # We have old collect2 _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_AC_TAGVAR(always_export_symbols, $1)=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an empty executable. _LT_AC_SYS_LIBPATH_AIX _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' # -bexpall does not export symbols beginning with underscore (_) _LT_AC_TAGVAR(always_export_symbols, $1)=yes # Exported symbols can be pulled into shared objects from archives _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds it's shared libraries. _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # see comment about different semantics on the GNU ld section _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; bsdi4*) _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext=".dll" # FIXME: Setting linknames here is a bad hack. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' fix_srcfile_path='`cygpath -w "$srcfile"`' _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; darwin* | rhapsody*) if test "$GXX" = yes ; then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no case "$host_os" in rhapsody* | darwin1.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' ;; *) # Darwin 1.3 on if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' else case ${MACOSX_DEPLOYMENT_TARGET} in 10.[[012]]) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' ;; 10.*) _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup' ;; esac fi ;; esac lt_int_apple_cc_single_mod=no output_verbose_link_cmd='echo' if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then lt_int_apple_cc_single_mod=yes fi if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' fi _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's if test "X$lt_int_apple_cc_single_mod" = Xyes ; then _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' else _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' fi _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_automatic, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' _LT_AC_TAGVAR(link_all_deplibs, $1)=yes else _LT_AC_TAGVAR(ld_shlibs, $1)=no fi ;; dgux*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; freebsd1*) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | kfreebsd*-gnu) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' ;; hpux10* | hpux11*) if test "$GCC" = yes -a "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*|ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case "$host_cpu" in hppa*64*|ia64*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' ;; esac fi if test "$with_gnu_ld" = no; then case "$host_cpu" in hppa*64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; ia64*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes ;; *) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; netbsd*) if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; openbsd*) _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' else case $host_os in openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' ;; *) _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' ;; esac fi ;; os2*) _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' # Both c and cxx compiler support -rpath directly _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: ;; sco3.2v5*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ;; solaris*) _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_AC_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_AC_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_AC_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4.2uw2*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_direct, $1)=yes _LT_AC_TAGVAR(hardcode_minus_L, $1)=no _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no hardcode_runpath_var=yes runpath_var=LD_RUN_PATH ;; sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' if test "$GCC" = yes; then _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' fi runpath_var='LD_RUN_PATH' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv5*) _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' # $CC -shared without GNU ld will not create a library from C++ # object files and a static libstdc++, better avoid it by now _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' ;; uts4*) _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_AC_TAGVAR(ld_shlibs, $1)=no ;; esac fi ]) AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi # # Do we need to explicitly link libc? # case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $_LT_AC_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_MSG_CHECKING([whether -lc should be explicitly linked in]) $rm conftest* printf "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) _LT_AC_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) then _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no else _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $rm conftest* AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) ;; esac fi ;; esac ])# AC_LIBTOOL_PROG_LD_SHLIBS # _LT_AC_FILE_LTDLL_C # ------------------- # Be careful that the start marker always follows a newline. AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ # /* ltdll.c starts here */ # #define WIN32_LEAN_AND_MEAN # #include # #undef WIN32_LEAN_AND_MEAN # #include # # #ifndef __CYGWIN__ # # ifdef __CYGWIN32__ # # define __CYGWIN__ __CYGWIN32__ # # endif # #endif # # #ifdef __cplusplus # extern "C" { # #endif # BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); # #ifdef __cplusplus # } # #endif # # #ifdef __CYGWIN__ # #include # DECLARE_CYGWIN_DLL( DllMain ); # #endif # HINSTANCE __hDllInstance_base; # # BOOL APIENTRY # DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) # { # __hDllInstance_base = hInst; # return TRUE; # } # /* ltdll.c ends here */ ])# _LT_AC_FILE_LTDLL_C # _LT_AC_TAGVAR(VARNAME, [TAGNAME]) # --------------------------------- AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) # old names AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) # This is just to silence aclocal about the macro not being used ifelse([AC_DISABLE_FAST_INSTALL]) AC_DEFUN([LT_AC_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj, no) test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS) ]) AC_DEFUN([LT_AC_PROG_RC], [AC_CHECK_TOOL(RC, windres, no) ]) ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ # LT_AC_PROG_SED # -------------- # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. AC_DEFUN([LT_AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f $lt_ac_sed && break cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test $lt_ac_count -gt 10 && break lt_ac_count=`expr $lt_ac_count + 1` if test $lt_ac_count -gt $lt_ac_max; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done SED=$lt_cv_path_SED ]) AC_MSG_RESULT([$SED]) ]) ## ltdl.m4 - Configure ltdl for the target system. -*-Autoconf-*- ## Copyright (C) 1999-2000 Free Software Foundation, Inc. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ## ## As a special exception to the GNU General Public License, if you ## distribute this file as part of a program that contains a ## configuration script generated by Autoconf, you may include it under ## the same distribution terms that you use for the rest of that program. # serial 6 AC_LIB_LTDL # Debian $Rev: 42 $ # AC_WITH_LTDL # ------------ # Clients of libltdl can use this macro to allow the installer to # choose between a shipped copy of the ltdl sources or a preinstalled # version of the library. AC_DEFUN([AC_WITH_LTDL], [AC_REQUIRE([AC_LIB_LTDL]) AC_SUBST([LIBLTDL]) AC_SUBST([INCLTDL]) # Unless the user asks us to check, assume no installed ltdl exists. use_installed_libltdl=no AC_ARG_WITH([included_ltdl], [ --with-included-ltdl use the GNU ltdl sources included here]) if test "x$with_included_ltdl" != xyes; then # We are not being forced to use the included libltdl sources, so # decide whether there is a useful installed version we can use. AC_CHECK_HEADER([ltdl.h], [AC_CHECK_LIB([ltdl], [lt_dlcaller_register], [with_included_ltdl=no], [with_included_ltdl=yes]) ]) fi if test "x$enable_ltdl_install" != xyes; then # If the user did not specify an installable libltdl, then default # to a convenience lib. AC_LIBLTDL_CONVENIENCE fi if test "x$with_included_ltdl" = xno; then # If the included ltdl is not to be used. then Use the # preinstalled libltdl we found. AC_DEFINE([HAVE_LTDL], 1, [Define this if a modern libltdl is already installed]) LIBLTDL=-lltdl fi # Report our decision... AC_MSG_CHECKING([whether to use included libltdl]) AC_MSG_RESULT([$with_included_ltdl]) AC_CONFIG_SUBDIRS([libltdl]) ])# AC_WITH_LTDL # AC_LIB_LTDL # ----------- # Perform all the checks necessary for compilation of the ltdl objects # -- including compiler checks and header checks. AC_DEFUN([AC_LIB_LTDL], [AC_PREREQ(2.50) AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_C_CONST]) AC_REQUIRE([AC_HEADER_STDC]) AC_REQUIRE([AC_HEADER_DIRENT]) AC_REQUIRE([_LT_AC_CHECK_DLFCN]) AC_REQUIRE([AC_LTDL_ENABLE_INSTALL]) AC_REQUIRE([AC_LTDL_SHLIBEXT]) AC_REQUIRE([AC_LTDL_SHLIBPATH]) AC_REQUIRE([AC_LTDL_SYSSEARCHPATH]) AC_REQUIRE([AC_LTDL_OBJDIR]) AC_REQUIRE([AC_LTDL_DLPREOPEN]) AC_REQUIRE([AC_LTDL_DLLIB]) AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) AC_REQUIRE([AC_LTDL_DLSYM_USCORE]) AC_REQUIRE([AC_LTDL_SYS_DLOPEN_DEPLIBS]) AC_REQUIRE([AC_LTDL_FUNC_ARGZ]) AC_CHECK_HEADERS([assert.h ctype.h errno.h malloc.h memory.h stdlib.h \ stdio.h unistd.h]) AC_CHECK_HEADERS([dl.h sys/dl.h dld.h mach-o/dyld.h]) AC_CHECK_HEADERS([string.h strings.h], [break]) AC_CHECK_FUNCS([strchr index], [break]) AC_CHECK_FUNCS([strrchr rindex], [break]) AC_CHECK_FUNCS([memcpy bcopy], [break]) AC_CHECK_FUNCS([memmove strcmp]) AC_CHECK_FUNCS([closedir opendir readdir]) ])# AC_LIB_LTDL # AC_LTDL_ENABLE_INSTALL # ---------------------- AC_DEFUN([AC_LTDL_ENABLE_INSTALL], [AC_ARG_ENABLE([ltdl-install], [AC_HELP_STRING([--enable-ltdl-install], [install libltdl])]) if test x"${enable_ltdl_install-no}" != xno; then AC_DEFINE(INSTALL_LTDL) fi if test x"${enable_ltdl_convenience-no}" != xno; then AC_DEFINE(CONVENIENCE_LTDL) fi ])])# AC_LTDL_ENABLE_INSTALL # AC_LTDL_SYS_DLOPEN_DEPLIBS # -------------------------- AC_DEFUN([AC_LTDL_SYS_DLOPEN_DEPLIBS], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_CACHE_CHECK([whether deplibs are loaded by dlopen], [libltdl_cv_sys_dlopen_deplibs], [# PORTME does your system automatically load deplibs for dlopen? # or its logical equivalent (e.g. shl_load for HP-UX < 11) # For now, we just catch OSes we know something about -- in the # future, we'll try test this programmatically. libltdl_cv_sys_dlopen_deplibs=unknown case "$host_os" in aix3*|aix4.1.*|aix4.2.*) # Unknown whether this is true for these versions of AIX, but # we want this `case' here to explicitly catch those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; aix[[45]]*) libltdl_cv_sys_dlopen_deplibs=yes ;; darwin*) # Assuming the user has installed a libdl from somewhere, this is true # If you are looking for one http://www.opendarwin.org/projects/dlcompat libltdl_cv_sys_dlopen_deplibs=yes ;; kfreebsd*-gnu) libltdl_cv_sys_dlopen_deplibs=yes ;; gnu*) libltdl_cv_sys_dlopen_deplibs=yes ;; hpux10*|hpux11*) libltdl_cv_sys_dlopen_deplibs=yes ;; irix[[12345]]*|irix6.[[01]]*) # Catch all versions of IRIX before 6.2, and indicate that we don't # know how it worked for any of those versions. libltdl_cv_sys_dlopen_deplibs=unknown ;; irix*) # The case above catches anything before 6.2, and it's known that # at 6.2 and later dlopen does load deplibs. libltdl_cv_sys_dlopen_deplibs=yes ;; linux*) libltdl_cv_sys_dlopen_deplibs=yes ;; netbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; openbsd*) libltdl_cv_sys_dlopen_deplibs=yes ;; osf[[1234]]*) # dlopen did load deplibs (at least at 4.x), but until the 5.x series, # it did *not* use an RPATH in a shared library to find objects the # library depends on, so we explictly say `no'. libltdl_cv_sys_dlopen_deplibs=no ;; osf5.0|osf5.0a|osf5.1) # dlopen *does* load deplibs and with the right loader patch applied # it even uses RPATH in a shared library to search for shared objects # that the library depends on, but there's no easy way to know if that # patch is installed. Since this is the case, all we can really # say is unknown -- it depends on the patch being installed. If # it is, this changes to `yes'. Without it, it would be `no'. libltdl_cv_sys_dlopen_deplibs=unknown ;; osf*) # the two cases above should catch all versions of osf <= 5.1. Read # the comments above for what we know about them. # At > 5.1, deplibs are loaded *and* any RPATH in a shared library # is used to find them so we can finally say `yes'. libltdl_cv_sys_dlopen_deplibs=yes ;; solaris*) libltdl_cv_sys_dlopen_deplibs=yes ;; esac ]) if test "$libltdl_cv_sys_dlopen_deplibs" != yes; then AC_DEFINE([LTDL_DLOPEN_DEPLIBS], [1], [Define if the OS needs help to load dependent libraries for dlopen().]) fi ])# AC_LTDL_SYS_DLOPEN_DEPLIBS # AC_LTDL_SHLIBEXT # ---------------- AC_DEFUN([AC_LTDL_SHLIBEXT], [AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) AC_CACHE_CHECK([which extension is used for loadable modules], [libltdl_cv_shlibext], [ module=yes eval libltdl_cv_shlibext=$shrext ]) if test -n "$libltdl_cv_shlibext"; then AC_DEFINE_UNQUOTED(LTDL_SHLIB_EXT, "$libltdl_cv_shlibext", [Define to the extension used for shared libraries, say, ".so".]) fi ])# AC_LTDL_SHLIBEXT # AC_LTDL_SHLIBPATH # ----------------- AC_DEFUN([AC_LTDL_SHLIBPATH], [AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) AC_CACHE_CHECK([which variable specifies run-time library path], [libltdl_cv_shlibpath_var], [libltdl_cv_shlibpath_var="$shlibpath_var"]) if test -n "$libltdl_cv_shlibpath_var"; then AC_DEFINE_UNQUOTED(LTDL_SHLIBPATH_VAR, "$libltdl_cv_shlibpath_var", [Define to the name of the environment variable that determines the dynamic library search path.]) fi ])# AC_LTDL_SHLIBPATH # AC_LTDL_SYSSEARCHPATH # --------------------- AC_DEFUN([AC_LTDL_SYSSEARCHPATH], [AC_REQUIRE([AC_LIBTOOL_SYS_DYNAMIC_LINKER]) AC_CACHE_CHECK([for the default library search path], [libltdl_cv_sys_search_path], [libltdl_cv_sys_search_path="$sys_lib_dlsearch_path_spec"]) if test -n "$libltdl_cv_sys_search_path"; then sys_search_path= for dir in $libltdl_cv_sys_search_path; do if test -z "$sys_search_path"; then sys_search_path="$dir" else sys_search_path="$sys_search_path$PATH_SEPARATOR$dir" fi done AC_DEFINE_UNQUOTED(LTDL_SYSSEARCHPATH, "$sys_search_path", [Define to the system default library search path.]) fi ])# AC_LTDL_SYSSEARCHPATH # AC_LTDL_OBJDIR # -------------- AC_DEFUN([AC_LTDL_OBJDIR], [AC_CACHE_CHECK([for objdir], [libltdl_cv_objdir], [libltdl_cv_objdir="$objdir" if test -n "$objdir"; then : else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then libltdl_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. libltdl_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi ]) AC_DEFINE_UNQUOTED(LTDL_OBJDIR, "$libltdl_cv_objdir/", [Define to the sub-directory in which libtool stores uninstalled libraries.]) ])# AC_LTDL_OBJDIR # AC_LTDL_DLPREOPEN # ----------------- AC_DEFUN([AC_LTDL_DLPREOPEN], [AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) AC_CACHE_CHECK([whether libtool supports -dlopen/-dlpreopen], [libltdl_cv_preloaded_symbols], [if test -n "$lt_cv_sys_global_symbol_pipe"; then libltdl_cv_preloaded_symbols=yes else libltdl_cv_preloaded_symbols=no fi ]) if test x"$libltdl_cv_preloaded_symbols" = xyes; then AC_DEFINE(HAVE_PRELOADED_SYMBOLS, 1, [Define if libtool can extract symbol lists from object files.]) fi ])# AC_LTDL_DLPREOPEN # AC_LTDL_DLLIB # ------------- AC_DEFUN([AC_LTDL_DLLIB], [LIBADD_DL= AC_SUBST(LIBADD_DL) AC_LANG_PUSH([C]) AC_CHECK_FUNC([shl_load], [AC_DEFINE([HAVE_SHL_LOAD], [1], [Define if you have the shl_load function.])], [AC_CHECK_LIB([dld], [shl_load], [AC_DEFINE([HAVE_SHL_LOAD], [1], [Define if you have the shl_load function.]) LIBADD_DL="$LIBADD_DL -ldld"], [AC_CHECK_LIB([dl], [dlopen], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) LIBADD_DL="-ldl" libltdl_cv_lib_dl_dlopen="yes"], [AC_TRY_LINK([#if HAVE_DLFCN_H # include #endif ], [dlopen(0, 0);], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) libltdl_cv_func_dlopen="yes"], [AC_CHECK_LIB([svld], [dlopen], [AC_DEFINE([HAVE_LIBDL], [1], [Define if you have the libdl library or equivalent.]) LIBADD_DL="-lsvld" libltdl_cv_func_dlopen="yes"], [AC_CHECK_LIB([dld], [dld_link], [AC_DEFINE([HAVE_DLD], [1], [Define if you have the GNU dld library.]) LIBADD_DL="$LIBADD_DL -ldld"], [AC_CHECK_FUNC([_dyld_func_lookup], [AC_DEFINE([HAVE_DYLD], [1], [Define if you have the _dyld_func_lookup function.])]) ]) ]) ]) ]) ]) ]) if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes then lt_save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" AC_CHECK_FUNCS([dlerror]) LIBS="$lt_save_LIBS" fi AC_LANG_POP ])# AC_LTDL_DLLIB # AC_LTDL_SYMBOL_USCORE # --------------------- # does the compiler prefix global symbols with an underscore? AC_DEFUN([AC_LTDL_SYMBOL_USCORE], [AC_REQUIRE([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE]) AC_CACHE_CHECK([for _ prefix in compiled symbols], [ac_cv_sys_symbol_underscore], [ac_cv_sys_symbol_underscore=no cat > conftest.$ac_ext < $ac_nlist) && test -s "$ac_nlist"; then # See whether the symbols have a leading underscore. if grep '^. _nm_test_func' "$ac_nlist" >/dev/null; then ac_cv_sys_symbol_underscore=yes else if grep '^. nm_test_func ' "$ac_nlist" >/dev/null; then : else echo "configure: cannot find nm_test_func in $ac_nlist" >&AC_FD_CC fi fi else echo "configure: cannot run $lt_cv_sys_global_symbol_pipe" >&AC_FD_CC fi else echo "configure: failed program was:" >&AC_FD_CC cat conftest.c >&AC_FD_CC fi rm -rf conftest* ]) ])# AC_LTDL_SYMBOL_USCORE # AC_LTDL_DLSYM_USCORE # -------------------- AC_DEFUN([AC_LTDL_DLSYM_USCORE], [AC_REQUIRE([AC_LTDL_SYMBOL_USCORE]) if test x"$ac_cv_sys_symbol_underscore" = xyes; then if test x"$libltdl_cv_func_dlopen" = xyes || test x"$libltdl_cv_lib_dl_dlopen" = xyes ; then AC_CACHE_CHECK([whether we have to add an underscore for dlsym], [libltdl_cv_need_uscore], [libltdl_cv_need_uscore=unknown save_LIBS="$LIBS" LIBS="$LIBS $LIBADD_DL" _LT_AC_TRY_DLOPEN_SELF( [libltdl_cv_need_uscore=no], [libltdl_cv_need_uscore=yes], [], [libltdl_cv_need_uscore=cross]) LIBS="$save_LIBS" ]) fi fi if test x"$libltdl_cv_need_uscore" = xyes; then AC_DEFINE(NEED_USCORE, 1, [Define if dlsym() requires a leading underscore in symbol names.]) fi ])# AC_LTDL_DLSYM_USCORE # AC_LTDL_FUNC_ARGZ # ----------------- AC_DEFUN([AC_LTDL_FUNC_ARGZ], [AC_CHECK_HEADERS([argz.h]) AC_CHECK_TYPES([error_t], [], [AC_DEFINE([error_t], [int], [Define to a type to use for `error_t' if it is not otherwise available.])], [#if HAVE_ARGZ_H # include #endif]) AC_CHECK_FUNCS([argz_append argz_create_sep argz_insert argz_next argz_stringify]) ])# AC_LTDL_FUNC_ARGZ # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # # Similar to PKG_CHECK_MODULES, make sure that the first instance of # this or PKG_CHECK_MODULES is called, or make sure to call # PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_ifval([$2], [$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$PKG_CONFIG"; then if test -n "$$1"; then pkg_cv_[]$1="$$1" else PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) fi else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` else $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT ])], [$4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES bochs-2.6/README-wxWidgets0000644000175000017500000003151512020641507015202 0ustar guillemguillemReadme for wxWidgets Interface updated Sat Dec 21 11:09:34 EST 2002 Contributors to wxWidgets port: Don Becker (Psyon) Bryce Denney Dave Poirier Volker Ruppert wxWidgets Configuration Interface The wxWidgets port began in June 2001 around the time of Bochs 1.2.1. Dave Poirier and Bryce Denney started adding a wxWidgets configuration interface. We made some progress, but stopped after a while. Then in March/April 2002 Bryce and Psyon revived the wxWidgets branch and turned it into a usable interface. Psyon did most of the work to get text and graphics working, and Bryce worked on event passing between threads, and keyboard mapping. Starting in August 2002, Bryce added lots of dialog boxes to allow you to set all the bochsrc parameters. At the time of release 2.0, there are still some bugs but it is pretty stable and usable. Bochs should be build with wxWidgets 2.3.3 or later. It will probably not compile with 2.2.x without some work. wxWidgets 2.3.3 includes a patch by Bryce Denney to allow us to get raw keycode data for several OSes. On any UNIX platform with wxWidgets installed, configure with --with-wx to enable the wxWidgets display library. To build in MS VC++: - edit .conf.win32-vcpp and add "--with-wx" to the configure line. If you want different configure options from what you see, change them too. - in cygwin, do "sh .conf.win32-vcpp" to run configure - unzip build/win32/wxworkspace.zip into the main directory. For cygwin: unzip build/win32/wxworkspace.zip or use winzip or whatever else. - open up bochs.dsw, the workspace file - edit project settings so that VC++ can find the wxWidgets include files and libraries on your system. Bryce installed them in d:/wx/wx233/include and d:/wx/wx233/lib. Specifically, edit - Project>Settings>C/C++>Category=Preprocessor: include directories. - Project>Settings>Link>Category=Input: additional library path. - build Note that the project is set up for wxWidgets 2.3.3. To use on other wxwindows versions, you will have to change some of the names of the libraries to include. Use the samples that came with that version of wxwindows for reference. To do: - now that ParamDialog works, I may rewrite some of the other dialogs as subclasses of ParamDialog. This would lead to more compact code, and fewer bugs. - configure time dialog - need to think about dialog layout - setting of IPS (controls how much time the PIT associates with each instruction for purposes of sending timer interrupts). How can we name this? instructions per simulated second. - enable realtime pit, realtime pit settings (?) - enable/disable X windows idle hack - report instructions per wall clock second in real time - decide which settings can be adjusted at runtime, and figure out how to disable the others. Do we need a set_enable() on the parameters themselves? - the power button has always "turned off" the power. Make it also turn ON the power. I think a few little green LEDs are in order. - floppy config screen: on win32, both not present and ejected are selected at first. - log events - Later: allow viewing of current log messages. Maybe this is a dialog that we append to, or maybe it should periodically display the last 1K of the log file (might be faster in high volume situations). - Later: should we allow multiple log files with different settings? for example dump cpu events to cpulog.txt and keyboard events to keyboardlog.txt? - debugger - bug: it's possible to make the GUI stop responding to mouse and keyboard input if you click the continue button in the debugger twice in very close succession. I don't know why yet. - probably the layout will be similar to BFE at first - need to show disassembly of the next instruction to be executed - clean up the biggest memory leaks and init/cleanup code. The gui allows you to kill the simulator and restart, but it doesn't do well after the first time. Valgrind should help with memory leak debugging, though until recently it couldn't run multithreaded programes. - disk change dialogs for floppy and cdrom need work. http://sourceforge.net/tracker/index.php?func=detail&aid=545414&group_id=12580&atid=112580 ------------- ------------------------------------------------------ Random notes follow Added some sketches. I'm thinking that the control panel will be able to basically show one of these screens at a time. When you first start you would see ChooseConfigScreen which chooses between the configurations that you have loaded recently (which it would remember by the pathname of their bochsrc). Whether you choose an existing configuration to be loaded or a new one, when you click Ok you go to the first configuration screen, ConfigDiskScreen. Each of the configuration screens takes up the whole control panel window. We could use tabs on the top and/or "<-Prev" and "Next->" buttons to make it quick to navigate the configuration screens. Each screen should probably have a Prev, Next, Revert to Saved, and Accept button. The menu choices like Disk..., VGA..., etc. just switch directly to that tab. ------------------------------------------------------ Notes: events from gui to sim: - [async] key pressed or released - [async] mouse motion with button state - [sync] query parameter - [sync] change parameter - [async] start, pause, stop, reset simulation. Can be implemented as changing a parameter. - [async] request notification when some param changes events from sim to gui: - [async] log message to be displayed (or not) - [async] ask user how to proceed (like panic: action=ask) - [async] param value changed - make my thread sleep for X microseconds (call wxThread::sleep then return) In a synchronous event, the event object will contain space for the entire response. The sender allocates memory for the event and builds it. The receiver fills in blanks in the event structure (or could overwrite parts) and returns the same event pointer as a response. For async events, probably the sender will allocate and the receiver will have to delete it. implement the floppyA and floppyB change buttons using new event structure. How should it work? vga gui detects a click on floppyA bitmap construct a BxEvent type BX_EVT_ASK_PARAM post the event to the wxwindows gui thread (somehow) and block for response when it arrives in the gui thread, show a modal dialog box get the answer back to the simulator thread right now, this is working ok within the simulator thread using wxMutexGuiEnter/Leave. Still I'm going to change it so that the siminterface.cc code builds an event structure and the gui code fills in the blank in the structure, instead of the stupid notify_get_int_arg stuff. Starting and Killing Threads When a detachable (default) thread finishes (returns from its Entry() function), wxwindows frees the memory associated with that thread. Unless the thread is never going to end, it is potentially dangerous to have a pointer to it at all. Even if you try to "check if it's alive" first, you may be dereferencing the pointer after it has already been deleted, leading to it claiming to be alive when it's not, or a segfault. To solve this, the approach used in the wxwindows threads example is to have code in the thread's OnExit() method remove the thread's pointer from the list of usable threads. In addition, any references or changes to the list of threads is controlled by a critical section to ensure that it stays correct. This post finally explained what I was seeing. +----------------------- | From: Pieter van der Meulen (pgmvdm@yahoo.com) | Subject: Re: Thread Sample program - bug | Newsgroups: comp.soft-sys.wxwindows | Date: 2001-06-28 17:51:35 PST | | | At 06:24 PM 6/28/2001, you wrote: | >Hi, | >I have wxWindows 2.2.7 (wxMSW) installed. | > | >I just found in the thread.cpp sample code this section: | > | > | >void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) ) | >{ | > size_t count = wxGetApp().m_threads.Count(); | > for ( size_t i = 0; i < count; i++ ) | > { | >===> wxGetApp().m_threads[0]->Delete(); <===== | > } | > | > Close(TRUE); | >} | > | >The indecated line should probably rather have a | >m_threads[i] rather than m_threads[0] . | | No, it should not, although it is not immediately obvious. When Delete() is | called, the thread will eventually delete itself, but not before it calls | MyThread::Exit(), which will remove itself from m_threads[] using | wxArray::Remove(this). wxArray::Remove (RemoveAt) will compact the array to | remove the element, it is now size-1. After this wxThread::Delete() returns. | | | >I have have a further question to this: | >Does this mean that a detached thread created with new | >HAS to be deleted manually ? Or is this only in case it might still | >be running? | | Firstly, you must create every detached thread using new since it will | delete itself, literally calling delete this. | Calling wxThread::Delete() is a correct way to terminate a thread, but | manually deleting (using delete) a detached wxThread object is not. | wxThread::Delete() will ask the thread to exit, the thread should check for | this in wxThread::Entry() regularly using wxThread::TestDestroy() and exit | when asked to do so. | | >(In general I have a unsatisfied felling about when delete is | >neccessary and when not -- "I only know, it's not , if the class is | >derived from wxWindows") | | For wxThreads: joinable threads must be deleted (when allocated on the | heap), detached threads may never be deleted. For other classes, consult | the documentation ;) | | | >Thanks for some feedback, | >Sebastian | | Regards, | | Pieter. +----------------------- tracking some kind of deadlock bug in Linux. seems to be in ReadMailcap, src/unix/mimetypes.cpp in wxwindows sources src/unix/mimetype.cpp:2312 SOLUTION: compile with -pthread on every compile and link line. ---------------------------------------------- Suggested solution for putting sizers inside a scrolled window From: Thaddaeus Frogley (codemonkey_uk@users.sourceforge.net) Subject: RE: Using sizers inside of a scrolled window Newsgroups: comp.soft-sys.wxwindows Date: 2001-10-02 02:41:04 PST I have solved that same problem (scrolled windows / sizers) like so: In the constructor for your wxFrame derived class, //create a scrolling window myScrolledWindow = new wxScrolledWindow(this, -1); //in the scolling window, create a panel myMainPanel = new wxPanel(myScrolledWindow, -1); //place controls in the panel, laying them out with sizers //... myMainPanel->SetAutoLayout( TRUE ); myMainPanel->SetSizer( sizer ); sizer->Fit( myMainPanel ); sizer->SetSizeHints( myMainPanel ); //set the scroll bars lengths based on the size of the inner panel wxSize size = myMainPanel->GetBestSize(); myScrolledWindow->SetScrollbars( 1, 1, size.GetWidth(), size.GetHeight() ); //calculate the size of the window, and set it appropriately size.Set(size.GetWidth()+16,size.GetHeight()+16); //Get the physical size of the display in pixels. int displaySizeX,displaySizeY; wxDisplaySize(&displaySizeX,&displaySizeY); //clamp window size to % of screen if (size.GetWidth()>displaySizeX*0.75){ size.SetWidth(displaySizeX*0.75); } if (size.GetHeight()>displaySizeY*0.75){ size.SetHeight(displaySizeY*0.75); } SetClientSize(size); ----------------- How to make wxChoice as wide as the longest string in the choice box? From: Vadim Zeitlin (Vadim.zeitlin@dptmaths.ens-cachan.fr) Subject: Re: wxChoice Newsgroups: comp.soft-sys.wxwindows Date: 2001-09-18 04:41:07 PST On Sat, 15 Sep 2001 15:39:45 +0200 Merlijn Blaauw wrote: MB> Also, I MB> would like the widget's parent window to change size (width) to fit the MB> widget's new content aswell. You'll have to do it manually by calculating the length of the string you add to the control (use wxClientDC(combobox) and set correct font before calling GetTextExtent()!) and resizing the control to be slightly larger (yes, I know it's not nice at all but I don't see any other way to do it). Regards, VZ --------- Hold on, this is even better! From: Yann Rouillard (Y.Rouillard@exeter.ac.uk) Subject: wxChoice and wxADJUST_MINSIZE Newsgroups: comp.soft-sys.wxwindows Date: 2002-07-18 08:28:31 PST I am trying to use a wxChoice widget in a little panel. The text length of the choices in the wxChoice can change so I used the wxADJUST_MINSIZE to have its width correctly set. > the manual for wxSizer::Add() says: Finally, you can also specify wxADJUST_MINSIZE flag to make the minimal size of the control dynamically adjust to the value returned by its GetBestSize() method - this allows, for example, for correct relayouting of a static text control even if its text is changed during run-time. relayouting? sounds like s/size/layout/g gone wrong. Call Add() with wxADJUST_MINSIZE flag! -------------- mno-cygwin guide on mingw webpage http://www.xraylith.wisc.edu/~khan/software/gnu-win32/mno-cygwin-howto.txt www.mingw.org bochs-2.6/TODO0000644000175000017500000002515412020641507013031 0ustar guillemguillemThis is the "roadmap" posted in the mailing list, augmented by comments from the mailing list and the irc chat. Anybody is welcome to work on any of these issues. Some of these items are rather simple and can be implemented by single individuals. Other items are quite complex and development needs to be coordinated. So, if you want to contribute, please drop us a note in the mailing list, so you can get help or exchange ideas. Christophe Bothamy. 0. Donations Source Forge recently set up a donation system for hosted projects. Should we accept donations ? What could we do with the money ? - give to EFF, FSF or other - fund Kevin to continue the work on plex86 so we can use it - bounties for somebody write optimized win9x/NT/XFree/linux/*BSD drivers for our vga/net/ide cards - other ? Status in Bochs 2.5: No decisions about this yet. 1. Speed Speed (well lack of) is one of the biggest criticism made by users who'd like to see Bochs run as fast as Virtual PC. Paths we can explore to get more speed : 1.1 virtualization : plex86 1.2 dynamic translation : qemu Status: Some work has been done for Bochs 2.5 but still long way is ahead. 2 multithreading. Conn Clark wrote : Threading might be nice too, for those of us who have SMP/SMT machines. I have a patch from Mathis (who hangs out on the IRC channel all the time) that puts the video card interface in its own thread. It has troubles though that I have not resolved. It may also be easier to debug a threaded peripheral. I also think that it might be possible to thread a chunk of the CPU emulation to improve performance on a SMP/SMT machine. Specifically write_virtual_dword, write_virtual_word, write_virtual_byte, etc... might just be able to be threaded. I think the threading overhead might be less than the protection and address translation code. We would have to try it to find out. I'm also sure there can be some nasty hurdles to overcome. Status: Third party group started a para-Bochs project exactly to reach above goals, some beta version is already released. The home page of the project: http://grid.hust.edu.cn/cluster/VirtualMachine/main.html 3. Plugin architecture 3.1 The plugin architecture can be reworked if we want to support multiple similar devices like serial, net or vga cards. We currently have two "types" of plugins: "core" and "optional". Maybe we could add "classes" of plugins. The current version of Bochs supports the classes "display_library" and "io_device". New classes can be "config_interface", "net_lowlevel" and "sound_lowlevel" 3.2 Stanislav wrote : Plugin architecture should be rewritten like real plugin architecture s.t. Bochs VGA plugin for example will be real plugin. I mean that replacement of plugin dll in already compiled Bochs will replace Bochs VGA card and the new card will be detected automatically. This will allow for example developing of plugins separately from Bochs. 3.3 Michael Brown wrote : If the configuration interface is to be reworked, could we also make it so that plugins are self-contained, rather than needing to pollute config.cc with code for defining and parsing plugin-specific options Status: Some of the basic work is done now: The config parameter handling has been rewritten to a parameter tree and user-defined bochsrc options are now supported. For most of the optional plugins the config parameter creation and bochsrc parsing has been moved to the plugin code. Unknown bochsrc options are now treated as plugin names and Bochs tries to load them. 4. PCI host<->guest proxy Being able to use a real pci device from inside Bochs would be a great feature of Bochs. It would ease reverse engineering of non documented cards, or one could even use a real spare vga card. Frank Cornellis has done a great job on this subject, and we began integrating his changes. Status: The pcidev device is present in SVN and it has been updated for the new PCI infrastructure, but the new code is untested yet. 5. Subdirectories in iodev The iodev directory contains the various implemented iodevice. With the new pci devices, new harddrives and new net access methods, it could be interesting to add new subdirectories like : iodev/video/... --> for standard vga and new card emulation iodev/disks/... --> for the ata/atapi classes, hd/cd classes and host accesses iodev/net/... --> for ne2k and host net access isa and pci devices would be mixed in the directories, but this should be manageable. Status: Subfolders for disk imaging, sound, network and usb devices were created under the iodev folder. 6. VGA For SVGA emulation we have Bochs VBE and the Cirrus adapter. We should have a look at the voodoo3 (specs http://v3tv.sourceforge.net/docs.php). Status: Not done yet. 7. Random thoughts on disk emulation improvements : 7.1 autodetection of disk size / geometry 7.2 uml cow disk image support 7.3 compressed disk image support 7.4 extend redolog-disk specification to add coherency check of the flat image file, by storing its fstat-mtime field in the redolog. Status: Autodetection now works for all image types created with bximage and vmware3 images. Vmware4 disk images support was added in Bochs 2.3.5 release. Coherency check for 'undoable' mode images added for Bochs 2.6. 8. net 8.1 bootable ethernet rom ? 8.2 user mode networking ? see etherboot, Micheal Brown wrote : This already works; you can build an Etherboot rom image with the pnic driver, specify it as an option ROM in bochsrc and it will boot. I'm using this extensively at the moment in Etherboot development. In the Etherboot project's CVS, in the contrib/bochs directory, you can find a working bochsrc file and an up-to-date README with step-by-step instructions on getting this working. Status: The pnic device is present in SVN, but the status is unknown. PCI boot ROM support has been added for Bochs 2.6. User mode networking currently requires the 'slirp' program and it is not possible on all platforms. The slirp core should be added to the Bochs sources. 9. Bios 9.1 add "jump table placeholder" and log missing function calls in the bios. Check completness with Ralf Brown interrupt list. Status: Not done yet. 9.2 use Coreboot or SeaBios as possible alternatives/extensions to Bochs Bios ROM we have. Status: Starting from Bochs 2.5 SeaBIOS is usable. 10. LGPL VGABios 11.1 Video parameters table There is a very nice parameter table in 3dfx banshee document http://www2.lm-sensors.nu/~lm78/pdfs/Banshee_2d_spec.PDF see also http://www.xyzzy.claranet.de/dos/vgacrt.c Status: Version 0.7a of the LGPL'd VGABIOS has minimal support for the video parameter table. 11. Optimized Guest drivers still needed : VGA, IDE, NET We have a specific VGA driver for winNT/2K, but still lack drivers for other OSes. Status: Not done yet. 12. USB support Ben Lunt has been working on USB support. The USB mouse and keypad code is present in Bochs and almost stable. USB flash disk support has been started and the runtime device change support should be completed. Status: OHCI and UHCI host controller and 7 devices are known to work in Bochs. USB xHCI support is present, but needs more testing. 13. Config file and dynamic menu 13.1 Benjamen R. Meyer wrote : I think we should rework the .bochsrc file to be more standard across all devices. I like how the USB configuration is done in it, and think we should put something similar together for everything else. In other words, create something that can be easily used for everything, and make it easier to configure in the process. From what I can tell right now, most of the configuration lines are randomly thrown together as each gets implemented or added, instead of having something that is based on a standard approach to the configuration. The result should be something that would be able to easily auto-configured by another program (a configuration editor?) with minimal changes necessary when new devices/features are added. 13.2 Franck Cornelis wrote : the config system needs some work... e.g. the main menu is static while it could be generated at run-time... the main menu text lives somewhere in a file... while it should be generated at run-time by iterating the main menu objects Status: The config options handling has been rewritten to a parameter tree. Dynamic menus are now implemented on win32. 14. lowlevel serial support for Windows. Volker has been working on this. Status: Not yet complete (transmit works, receive is losing data). 15. Parallel port Conn Clark wrote : I would like to see better parallel port support so I can use a dongle. This is something I would find very useful as it would mean I wouldn't have to boot back into windows ever again. I also recognize that this may require a kernel module be written, which is beyond my current skills. I know others will find this useful as I have had to tell a few people that their parallel port driven peripherals that require a bidirectional parallel port won't work. Status: Not done yet. 16. Guest-To-Host Communication Try to adapt VirtualBox guest-to-host communication methods into Bochs. Having VirtualBox Shared Folders or VNAT support in Bochs could very simplify its usage. 17. Patches / Bug reports There are dozens of patches floating around. Some are outdated, don't apply cleanly, are obsolete/unneeded. We could try to do some clean-up, and keep only relevant ones. We should also clean up the SF bug tracker. Some bugreports are very old and we asked for more information with no response. Status: There is some progress, but still a lot of work to do. 18. Positions If you want to help without coding, here are available positions : 19.1 Webmaster : update website (Jan Bruun Andersen offered to help) 19.2 patch coordinator : look at incoming patches (sourceforge and mailing list) and upload / update in the SVN patches directory. 19.3 platform maintainers for macos / win32 19.4 disk image maintainer : create and maintain our collection of disk images. Usually, only the configuration file needs to be updated, and old bios files have to be removed. Some packages still contain very old bios files, they should definitely have to be removed. Status: More active developers are needed to do the things described above. 19. Bochs demo cd/dvd With version 2.1, it is now technically possible to use disk images on a read-only media, with a journal files on a read/write media. It would be great to create a demo cd/dvd with executables for supported platforms, configuration files and read-only disk images, the journal files would be written in a temporary directory on the harddisk. Status: Not done yet. 20. Other CPU architectures : arm, ppc This has been asked in the mailing list. I'm not really interested, but other people might be. Should we propose to host the new CPUs code in our source tree, or should we let people fork ? Status: Not done yet. bochs-2.6/pc_system.cc0000644000175000017500000004043012020641507014650 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: pc_system.cc 11058 2012-02-23 17:16:35Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002-2009 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu/cpu.h" #include "iodev/iodev.h" #define LOG_THIS bx_pc_system. #ifdef WIN32 #ifndef __MINGW32__ // #include // +++ #include #endif #endif #if defined(PROVIDE_M_IPS) double m_ips; // Millions of Instructions Per Second #endif // Option for turning off BX_TIMER_DEBUG? // Check out m_ips and ips #define SpewPeriodicTimerInfo 0 #define MinAllowableTimerPeriod 1 const Bit64u bx_pc_system_c::NullTimerInterval = 0xffffffff; // constructor bx_pc_system_c::bx_pc_system_c() { this->put("pc_system", "SYS"); BX_ASSERT(numTimers == 0); // Timer[0] is the null timer. It is initialized as a special // case here. It should never be turned off or modified, and its // duration should always remain the same. ticksTotal = 0; // Reset ticks since emulator started. timer[0].inUse = 1; timer[0].period = NullTimerInterval; timer[0].active = 1; timer[0].continuous = 1; timer[0].funct = nullTimer; timer[0].this_ptr = this; numTimers = 1; // So far, only the nullTimer. } void bx_pc_system_c::initialize(Bit32u ips) { ticksTotal = 0; timer[0].timeToFire = NullTimerInterval; currCountdown = NullTimerInterval; currCountdownPeriod = NullTimerInterval; lastTimeUsec = 0; usecSinceLast = 0; triggeredTimer = 0; HRQ = 0; kill_bochs_request = 0; // parameter 'ips' is the processor speed in Instructions-Per-Second m_ips = double(ips) / 1000000.0L; BX_DEBUG(("ips = %u", (unsigned) ips)); } void bx_pc_system_c::set_HRQ(bx_bool val) { HRQ = val; if (val) BX_CPU(0)->async_event = 1; } void bx_pc_system_c::set_INTR(bx_bool value) { if (bx_dbg.interrupts) BX_INFO(("pc_system: Setting INTR=%d on bootstrap processor %d", (int)value, BX_BOOTSTRAP_PROCESSOR)); BX_CPU(BX_BOOTSTRAP_PROCESSOR)->set_INTR(value); } // // Read from the IO memory address space // Bit32u BX_CPP_AttrRegparmN(2) bx_pc_system_c::inp(Bit16u addr, unsigned io_len) { Bit32u ret = bx_devices.inp(addr, io_len); return ret; } // // Write to the IO memory address space. // void BX_CPP_AttrRegparmN(3) bx_pc_system_c::outp(Bit16u addr, Bit32u value, unsigned io_len) { bx_devices.outp(addr, value, io_len); } void bx_pc_system_c::set_enable_a20(bx_bool value) { #if BX_SUPPORT_A20 bx_bool old_enable_a20 = enable_a20; if (value) { enable_a20 = 1; #if BX_CPU_LEVEL < 2 a20_mask = 0xfffff; #elif BX_CPU_LEVEL == 2 a20_mask = 0xffffff; #elif BX_PHY_ADDRESS_LONG a20_mask = BX_CONST64(0xffffffffffffffff); #else /* 386+ */ a20_mask = 0xffffffff; #endif } else { enable_a20 = 0; /* mask off A20 address line */ #if BX_PHY_ADDRESS_LONG a20_mask = BX_CONST64(0xffffffffffefffff); #else a20_mask = 0xffefffff; #endif } BX_DBG_A20_REPORT(enable_a20); BX_DEBUG(("A20: set() = %u", (unsigned) enable_a20)); // If there has been a transition, we need to notify the CPUs so // they can potentially invalidate certain cache info based on // A20-line-applied physical addresses. if (old_enable_a20 != enable_a20) MemoryMappingChanged(); #else BX_DEBUG(("set_enable_a20: ignoring: BX_SUPPORT_A20 = 0")); #endif } bx_bool bx_pc_system_c::get_enable_a20(void) { #if BX_SUPPORT_A20 BX_DEBUG(("A20: get() = %u", (unsigned) enable_a20)); return enable_a20; #else BX_DEBUG(("get_enable_a20: ignoring: BX_SUPPORT_A20 = 0")); return 1; #endif } void bx_pc_system_c::MemoryMappingChanged(void) { for (unsigned i=0; iTLB_flush(); } void bx_pc_system_c::invlpg(bx_address addr) { for (unsigned i=0; iTLB_invlpg(addr); } int bx_pc_system_c::Reset(unsigned type) { // type is BX_RESET_HARDWARE or BX_RESET_SOFTWARE BX_INFO(("bx_pc_system_c::Reset(%s) called",type==BX_RESET_HARDWARE?"HARDWARE":"SOFTWARE")); set_enable_a20(1); // Always reset cpu for (int i=0; ireset(type); } // Reset devices only on Hardware resets if (type==BX_RESET_HARDWARE) { DEV_reset_devices(type); } return(0); } Bit8u bx_pc_system_c::IAC(void) { return DEV_pic_iac(); } void bx_pc_system_c::exit(void) { // delete all registered timers (exception: null timer and APIC timer) numTimers = 1 + BX_SUPPORT_APIC; bx_devices.exit(); if (bx_gui) { bx_gui->cleanup(); bx_gui->exit(); } } void bx_pc_system_c::register_state(void) { bx_list_c *list = new bx_list_c(SIM->get_bochs_root(), "pc_system", "PC System State"); BXRS_PARAM_BOOL(list, enable_a20, enable_a20); BXRS_HEX_PARAM_SIMPLE(list, a20_mask); BXRS_DEC_PARAM_SIMPLE(list, currCountdown); BXRS_DEC_PARAM_SIMPLE(list, currCountdownPeriod); BXRS_DEC_PARAM_SIMPLE(list, ticksTotal); BXRS_DEC_PARAM_SIMPLE(list, lastTimeUsec); BXRS_DEC_PARAM_SIMPLE(list, usecSinceLast); BXRS_PARAM_BOOL(list, HRQ, HRQ); bx_list_c *timers = new bx_list_c(list, "timer"); for (unsigned i = 0; i < numTimers; i++) { char name[4]; sprintf(name, "%d", i); bx_list_c *bxtimer = new bx_list_c(timers, name); BXRS_PARAM_BOOL(bxtimer, inUse, timer[i].inUse); BXRS_DEC_PARAM_FIELD(bxtimer, period, timer[i].period); BXRS_DEC_PARAM_FIELD(bxtimer, timeToFire, timer[i].timeToFire); BXRS_PARAM_BOOL(bxtimer, active, timer[i].active); BXRS_PARAM_BOOL(bxtimer, continuous, timer[i].continuous); } } // ================================================ // Bochs internal timer delivery framework features // ================================================ int bx_pc_system_c::register_timer(void *this_ptr, void (*funct)(void *), Bit32u useconds, bx_bool continuous, bx_bool active, const char *id) { // Convert useconds to number of ticks. Bit64u ticks = (Bit64u) (double(useconds) * m_ips); return register_timer_ticks(this_ptr, funct, ticks, continuous, active, id); } int bx_pc_system_c::register_timer_ticks(void* this_ptr, bx_timer_handler_t funct, Bit64u ticks, bx_bool continuous, bx_bool active, const char *id) { unsigned i; // If the timer frequency is rediculously low, make it more sane. // This happens when 'ips' is too low. if (ticks < MinAllowableTimerPeriod) { //BX_INFO(("register_timer_ticks: adjusting ticks of %llu to min of %u", // ticks, MinAllowableTimerPeriod)); ticks = MinAllowableTimerPeriod; } // search for new timer for i=1, i=0 is reserved for NullTimer for (i=1; i < numTimers; i++) { if (timer[i].inUse == 0) break; } #if BX_TIMER_DEBUG if (i==0) BX_PANIC(("register_timer: cannot register NullTimer again!")); if (numTimers >= BX_MAX_TIMERS) BX_PANIC(("register_timer: too many registered timers")); if (this_ptr == NULL) BX_PANIC(("register_timer_ticks: this_ptr is NULL!")); if (funct == NULL) BX_PANIC(("register_timer_ticks: funct is NULL!")); #endif timer[i].inUse = 1; timer[i].period = ticks; timer[i].timeToFire = (ticksTotal + Bit64u(currCountdownPeriod-currCountdown)) + ticks; timer[i].active = active; timer[i].continuous = continuous; timer[i].funct = funct; timer[i].this_ptr = this_ptr; strncpy(timer[i].id, id, BxMaxTimerIDLen); timer[i].id[BxMaxTimerIDLen-1] = 0; // Null terminate if not already. if (active) { if (ticks < Bit64u(currCountdown)) { // This new timer needs to fire before the current countdown. // Skew the current countdown and countdown period to be smaller // by the delta. currCountdownPeriod -= (currCountdown - Bit32u(ticks)); currCountdown = Bit32u(ticks); } } BX_DEBUG(("timer id %d registered for '%s'", i, id)); // If we didn't find a free slot, increment the bound, numTimers. if (i==numTimers) numTimers++; // One new timer installed. // Return timer id. return(i); } void bx_pc_system_c::countdownEvent(void) { unsigned i; Bit64u minTimeToFire; bx_bool triggered[BX_MAX_TIMERS]; // The countdown decremented to 0. We need to service all the active // timers, and invoke callbacks from those timers which have fired. #if BX_TIMER_DEBUG if (currCountdown != 0) BX_PANIC(("countdownEvent: ticks!=0")); #endif // Increment global ticks counter by number of ticks which have // elapsed since the last update. ticksTotal += Bit64u(currCountdownPeriod); minTimeToFire = (Bit64u) -1; for (i=0; i < numTimers; i++) { triggered[i] = 0; // Reset triggered flag. if (timer[i].active) { #if BX_TIMER_DEBUG if (ticksTotal > timer[i].timeToFire) BX_PANIC(("countdownEvent: ticksTotal > timeToFire[%u], D " FMT_LL "u", i, timer[i].timeToFire-ticksTotal)); #endif if (ticksTotal == timer[i].timeToFire) { // This timer is ready to fire. triggered[i] = 1; if (timer[i].continuous==0) { // If triggered timer is one-shot, deactive. timer[i].active = 0; } else { // Continuous timer, increment time-to-fire by period. timer[i].timeToFire += timer[i].period; if (timer[i].timeToFire < minTimeToFire) minTimeToFire = timer[i].timeToFire; } } else { // This timer is not ready to fire yet. if (timer[i].timeToFire < minTimeToFire) minTimeToFire = timer[i].timeToFire; } } } // Calculate next countdown period. We need to do this before calling // any of the callbacks, as they may call timer features, which need // to be advanced to the next countdown cycle. currCountdown = currCountdownPeriod = Bit32u(minTimeToFire - ticksTotal); for (i=0; i < numTimers; i++) { // Call requested timer function. It may request a different // timer period or deactivate etc. if (triggered[i]) { triggeredTimer = i; timer[i].funct(timer[i].this_ptr); triggeredTimer = 0; } } } void bx_pc_system_c::nullTimer(void* this_ptr) { // This function is always inserted in timer[0]. It is sort of // a heartbeat timer. It ensures that at least one timer is // always active to make the timer logic more simple, and has // a duration of less than the maximum 32-bit integer, so that // a 32-bit size can be used for the hot countdown timer. The // rest of the timer info can be 64-bits. This is also a good // place for some logic to report actual emulated // instructions-per-second (IPS) data when measured relative to // the host computer's wall clock. UNUSED(this_ptr); #if SpewPeriodicTimerInfo BX_INFO(("===================================")); for (unsigned i=0; i < bx_pc_system.numTimers; i++) { if (bx_pc_system.timer[i].active) { BX_INFO(("BxTimer(%s): period=" FMT_LL "u, continuous=%u", bx_pc_system.timer[i].id, bx_pc_system.timer[i].period, bx_pc_system.timer[i].continuous)); } } #endif } void bx_pc_system_c::benchmarkTimer(void* this_ptr) { bx_pc_system_c *class_ptr = (bx_pc_system_c *) this_ptr; class_ptr->kill_bochs_request = 1; bx_user_quit = 1; } #if BX_DEBUGGER void bx_pc_system_c::timebp_handler(void* this_ptr) { BX_CPU(0)->break_point = BREAK_POINT_TIME; BX_DEBUG(("Time breakpoint triggered")); if (timebp_queue_size > 1) { Bit64s new_diff = timebp_queue[1] - bx_pc_system.time_ticks(); bx_pc_system.activate_timer_ticks(timebp_timer, new_diff, 0); } timebp_queue_size--; for (int i = 0; i < timebp_queue_size; i++) timebp_queue[i] = timebp_queue[i+1]; } #endif // BX_DEBUGGER Bit64u bx_pc_system_c::time_usec_sequential() { Bit64u this_time_usec = time_usec(); if(this_time_usec != lastTimeUsec) { Bit64u diff_usec = this_time_usec-lastTimeUsec; lastTimeUsec = this_time_usec; if(diff_usec >= usecSinceLast) { usecSinceLast = 0; } else { usecSinceLast -= diff_usec; } } usecSinceLast++; return (this_time_usec+usecSinceLast); } Bit64u bx_pc_system_c::time_usec() { return (Bit64u) (((double)(Bit64s)time_ticks()) / m_ips); } void bx_pc_system_c::start_timers(void) { } void bx_pc_system_c::activate_timer_ticks(unsigned i, Bit64u ticks, bx_bool continuous) { #if BX_TIMER_DEBUG if (i >= numTimers) BX_PANIC(("activate_timer_ticks: timer %u OOB", i)); if (i == 0) BX_PANIC(("activate_timer_ticks: timer 0 is the NullTimer!")); if (timer[i].period < MinAllowableTimerPeriod) BX_PANIC(("activate_timer_ticks: timer[%u].period of " FMT_LL "u < min of %u", i, timer[i].period, MinAllowableTimerPeriod)); #endif // If the timer frequency is rediculously low, make it more sane. // This happens when 'ips' is too low. if (ticks < MinAllowableTimerPeriod) { //BX_INFO(("activate_timer_ticks: adjusting ticks of %llu to min of %u", // ticks, MinAllowableTimerPeriod)); ticks = MinAllowableTimerPeriod; } timer[i].period = ticks; timer[i].timeToFire = (ticksTotal + Bit64u(currCountdownPeriod-currCountdown)) + ticks; timer[i].active = 1; timer[i].continuous = continuous; if (ticks < Bit64u(currCountdown)) { // This new timer needs to fire before the current countdown. // Skew the current countdown and countdown period to be smaller // by the delta. currCountdownPeriod -= (currCountdown - Bit32u(ticks)); currCountdown = Bit32u(ticks); } } void bx_pc_system_c::activate_timer(unsigned i, Bit32u useconds, bx_bool continuous) { Bit64u ticks; #if BX_TIMER_DEBUG if (i >= numTimers) BX_PANIC(("activate_timer: timer %u OOB", i)); if (i == 0) BX_PANIC(("activate_timer: timer 0 is the nullTimer!")); #endif // if useconds = 0, use default stored in period field // else set new period from useconds if (useconds==0) { ticks = timer[i].period; } else { // convert useconds to number of ticks ticks = (Bit64u) (double(useconds) * m_ips); // If the timer frequency is rediculously low, make it more sane. // This happens when 'ips' is too low. if (ticks < MinAllowableTimerPeriod) { //BX_INFO(("activate_timer: adjusting ticks of %llu to min of %u", // ticks, MinAllowableTimerPeriod)); ticks = MinAllowableTimerPeriod; } timer[i].period = ticks; } activate_timer_ticks(i, ticks, continuous); } void bx_pc_system_c::deactivate_timer(unsigned i) { #if BX_TIMER_DEBUG if (i >= numTimers) BX_PANIC(("deactivate_timer: timer %u OOB", i)); if (i == 0) BX_PANIC(("deactivate_timer: timer 0 is the nullTimer!")); #endif timer[i].active = 0; } bx_bool bx_pc_system_c::unregisterTimer(unsigned timerIndex) { #if BX_TIMER_DEBUG if (timerIndex >= numTimers) BX_PANIC(("unregisterTimer: timer %u OOB", timerIndex)); if (timerIndex == 0) BX_PANIC(("unregisterTimer: timer 0 is the nullTimer!")); if (timer[timerIndex].inUse == 0) BX_PANIC(("unregisterTimer: timer %u is not in-use!", timerIndex)); #endif if (timer[timerIndex].active) { BX_PANIC(("unregisterTimer: timer '%s' is still active!", timer[timerIndex].id)); return(0); // Fail. } // Reset timer fields for good measure. timer[timerIndex].inUse = 0; // No longer registered. timer[timerIndex].period = BX_MAX_BIT64S; // Max value (invalid) timer[timerIndex].timeToFire = BX_MAX_BIT64S; // Max value (invalid) timer[timerIndex].continuous = 0; timer[timerIndex].funct = NULL; timer[timerIndex].this_ptr = NULL; memset(timer[timerIndex].id, 0, BxMaxTimerIDLen); if (timerIndex == (numTimers-1)) numTimers--; return(1); // OK } bochs-2.6/.bochsrc0000644000175000017500000014505312020641507013766 0ustar guillemguillem# You may now use double quotes around pathnames, in case # your pathname includes spaces. #======================================================================= # PLUGIN_CTRL: # Controls the presence of optional device plugins. These plugins are loaded # directly with this option and some of them install a config option that is # only available when the plugin device is loaded. The value "1" means to load # the plugin and "0" will unload it (if loaded before). # # These plugins will be loaded by default (if present): 'biosdev', 'extfpuirq', # 'gameport', 'iodebug','parallel', 'serial', 'speaker' and 'unmapped'. # # These plugins are also supported, but they are usually loaded directly with # their bochsrc option: 'e1000', 'es1370', 'ne2k', 'pcidev', 'pcipnic', 'sb16', # 'usb_ohci', 'usb_uhci' and 'usb_xhci'. #======================================================================= #plugin_ctrl: unmapped=0, e1000=1 # unload 'unmapped' and load 'e1000' #======================================================================= # CONFIG_INTERFACE # # The configuration interface is a series of menus or dialog boxes that # allows you to change all the settings that control Bochs's behavior. # Depending on the platform there are up to 3 choices of configuration # interface: a text mode version called "textconfig" and two graphical versions # called "win32config" and "wx". The text mode version uses stdin/stdout and # is always compiled in, unless Bochs is compiled for wx only. The choice # "win32config" is only available on win32 and it is the default there. # The choice "wx" is only available when you use "--with-wx" on the configure # command. If you do not write a config_interface line, Bochs will # choose a default for you. # # NOTE: if you use the "wx" configuration interface, you must also use # the "wx" display library. #======================================================================= #config_interface: textconfig #config_interface: win32config #config_interface: wx #======================================================================= # DISPLAY_LIBRARY # # The display library is the code that displays the Bochs VGA screen. Bochs # has a selection of about 10 different display library implementations for # different platforms. If you run configure with multiple --with-* options, # the display_library command lets you choose which one you want to run with. # If you do not write a display_library line, Bochs will choose a default for # you. # # The choices are: # x use X windows interface, cross platform # win32 use native win32 libraries # carbon use Carbon library (for MacOS X) # macintosh use MacOS pre-10 # amigaos use native AmigaOS libraries # sdl use SDL library, cross platform # svga use SVGALIB library for Linux, allows graphics without X11 # term text only, uses curses/ncurses library, cross platform # rfb provides an interface to AT&T's VNC viewer, cross platform # wx use wxWidgets library, cross platform # nogui no display at all # # NOTE: if you use the "wx" configuration interface, you must also use # the "wx" display library. # # Specific options: # Some display libraries now support specific options to control their # behaviour. These options are supported by more than one display library: # # "gui_debug" - use GTK debugger gui (sdl, x) / Win32 debugger gui (sdl, win32) # "hideIPS" - disable IPS output in status bar (rfb, sdl, win32, wx, x) # "nokeyrepeat" - turn off host keyboard repeat (sdl, win32, x) # # See the examples below for other currently supported options. #======================================================================= #display_library: amigaos #display_library: carbon #display_library: macintosh #display_library: nogui #display_library: rfb, options="timeout=60" # time to wait for client #display_library: sdl, options="fullscreen" # startup in fullscreen mode #display_library: term #display_library: win32 #display_library: wx #display_library: x #======================================================================= # ROMIMAGE: # The ROM BIOS controls what the PC does when it first powers on. # Normally, you can use a precompiled BIOS in the source or binary # distribution called BIOS-bochs-latest. The ROM BIOS is usually loaded # starting at address 0xf0000, and it is exactly 64k long. Another option # is 128k BIOS which is loaded at address 0xe0000. # You can also use the environment variable $BXSHARE to specify the # location of the BIOS. # The usage of external large BIOS images (up to 512k) at memory top is # now supported, but we still recommend to use the BIOS distributed with # Bochs. The start address optional, since it can be calculated from image size. #======================================================================= romimage: file=$BXSHARE/BIOS-bochs-latest #romimage: file=bios/seabios-1.6.3.bin #romimage: file=mybios.bin, address=0xfff80000 # 512k at memory top #======================================================================= # CPU: # This defines cpu-related parameters inside Bochs: # # MODEL: # Selects CPU configuration to emulate from pre-defined list of all # supported configurations. When this option is used, the CPUID option # has no effect anymore. # # CPU configurations that can be selected: # ----------------------------------------------------------------- # pentium_mmx Intel Pentium MMX # amd_k6_2_chomper AMD-K6(tm) 3D processor (Chomper) # p2_klamath Intel Pentium II (Klamath) # p3_katmai Intel Pentium III (Katmai) # p4_willamette Intel(R) Pentium(R) 4 (Willamette) # core_duo_t2400_yonah Intel(R) Core(TM) Duo CPU T2400 (Yonah) # atom_n270 Intel(R) Atom(TM) CPU N270 # athlon64_clawhammer AMD Athlon(tm) 64 Processor 2800+ (Clawhammer) # athlon64_venice AMD Athlon(tm) 64 Processor 3000+ (Venice) # turion64_tyler AMD Turion(tm) 64 X2 Mobile TL-60 (Tyler) # phenom_8650_toliman AMD Phenom X3 8650 (Toliman) # p4_prescott_celeron_336 Intel(R) Celeron(R) 336 (Prescott) # core2_penryn_t9600 Intel Mobile Core 2 Duo T9600 (Penryn) # corei5_lynnfield_750 Intel(R) Core(TM) i5 750 (Lynnfield) # corei5_arrandale_m520 Intel(R) Core(TM) i5 M 520 (Arrandale) # corei7_sandy_bridge_2600k Intel(R) Core(TM) i7-2600K (Sandy Bridge) # corei7_ivy_bridge_3770k Intel(R) Core(TM) i7-3770K CPU (Ivy Bridge) # # COUNT: # Set the number of processors:cores per processor:threads per core # when Bochs is compiled for SMP emulation. # Bochs currently supports up to 8 threads running simultaniosly. # If Bochs is compiled without SMP support, it won't accept values # different from 1. # # QUANTUM: # Maximum amount of instructions allowed to execute by processor before # returning control to another cpu. This option exists only in Bochs # binary compiled with SMP support. # # RESET_ON_TRIPLE_FAULT: # Reset the CPU when triple fault occur (highly recommended) rather than # PANIC. Remember that if you trying to continue after triple fault the # simulation will be completely bogus ! # # CPUID_LIMIT_WINNT: # Determine whether to limit maximum CPUID function to 2. This mode is # required to workaround WinNT installation and boot issues. # # MSRS: # Define path to user CPU Model Specific Registers (MSRs) specification. # See example in msrs.def. # # IGNORE_BAD_MSRS: # Ignore MSR references that Bochs does not understand; print a warning # message instead of generating #GP exception. This option is enabled # by default but will not be avaiable if configurable MSRs are enabled. # # MWAIT_IS_NOP: # When this option is enabled MWAIT will not put the CPU into a sleep state. # This option exists only if Bochs compiled with --enable-monitor-mwait. # # IPS: # Emulated Instructions Per Second. This is the number of IPS that bochs # is capable of running on your machine. You can recompile Bochs with # --enable-show-ips option enabled, to find your host's capability. # Measured IPS value will then be logged into your log file or shown # in the status bar (if supported by the gui). # # IPS is used to calibrate many time-dependent events within the bochs # simulation. For example, changing IPS affects the frequency of VGA # updates, the duration of time before a key starts to autorepeat, and # the measurement of BogoMips and other benchmarks. # # Examples: # # Bochs Machine/Compiler Mips # ______________________________________________________________________ # 2.4.6 3.4Ghz Intel Core i7 2600 with Win7x64/g++ 4.5.2 85 to 95 Mips # 2.3.7 3.2Ghz Intel Core 2 Q9770 with WinXP/g++ 3.4 50 to 55 Mips # 2.3.7 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 38 to 43 Mips # 2.2.6 2.6Ghz Intel Core 2 Duo with WinXP/g++ 3.4 21 to 25 Mips # 2.2.6 2.1Ghz Athlon XP with Linux 2.6/g++ 3.4 12 to 15 Mips #======================================================================= cpu: model=core2_penryn_t9600, count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def" cpu: cpuid_limit_winnt=0 #======================================================================= # CPUID: # # This defines features and functionality supported by Bochs emulated CPU. # The option has no offect if CPU model was selected in CPU option. # # MMX: # Select MMX instruction set support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. # # APIC: # Select APIC configuration (LEGACY/XAPIC/XAPIC_EXT/X2APIC). # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 5. # # SEP: # Select SYSENTER/SYSEXIT instruction set support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # SSE: # Select SSE instruction set support. # Any of NONE/SSE/SSE2/SSE3/SSSE3/SSE4_1/SSE4_2 could be selected. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # SSE4A: # Select AMD SSE4A instructions support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # AES: # Select AES instruction set support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # MOVBE: # Select MOVBE Intel(R) Atom instruction support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # ADX: # Select ADCX/ADOX instructions support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # XSAVE: # Select XSAVE extensions support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # XSAVEOPT: # Select XSAVEOPT instruction support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # AVX: # Select AVX/AVX2 instruction set support. # This option exists only if Bochs compiled with --enable-avx option. # # AVX_F16C: # Select AVX float16 convert instructions support. # This option exists only if Bochs compiled with --enable-avx option. # # AVX_FMA: # Select AVX fused multiply add (FMA) instructions support. # This option exists only if Bochs compiled with --enable-avx option. # # BMI: # Select BMI1/BMI2 instructions support. # This option exists only if Bochs compiled with --enable-avx option. # # XOP: # Select AMD XOP instructions support. # This option exists only if Bochs compiled with --enable-avx option. # # FMA4: # Select AMD four operand FMA instructions support. # This option exists only if Bochs compiled with --enable-avx option. # # TBM: # Select AMD Trailing Bit Manipulation (TBM) instructions support. # This option exists only if Bochs compiled with --enable-avx option. # # X86-64: # Enable x86-64 and long mode support. # This option exists only if Bochs compiled with x86-64 support. # # 1G_PAGES: # Enable 1G page size support in long mode. # This option exists only if Bochs compiled with x86-64 support. # # PCID: # Enable Process-Context Identifiers (PCID) support in long mode. # This option exists only if Bochs compiled with x86-64 support. # # FSGSBASE: # Enable GS/GS BASE access instructions support in long mode. # This option exists only if Bochs compiled with x86-64 support. # # SMEP: # Enable Supervisor Mode Execution Protection (SMEP) support. # This option exists only if Bochs compiled with BX_CPU_LEVEL >= 6. # # MWAIT: # Select MONITOR/MWAIT instructions support. # This option exists only if Bochs compiled with --enable-monitor-mwait. # # VMX: # Select VMX extensions emulation support. # This option exists only if Bochs compiled with --enable-vmx option. # # VENDOR_STRING: # Set the CPUID vendor string returned by CPUID(0x0). This should be a # twelve-character ASCII string. # # BRAND_STRING: # Set the CPUID vendor string returned by CPUID(0x80000002 .. 0x80000004). # This should be at most a forty-eight-character ASCII string. # # FAMILY: # Set model information returned by CPUID. Default family value determined # by configure option --enable-cpu-level. # # MODEL: # Set model information returned by CPUID. Default model value is 3. # # STEPPING: # Set stepping information returned by CPUID. Default stepping value is 3. #======================================================================= #cpuid: x86_64=1, mmx=1, sep=1, sse=sse4_2, apic=xapic, aes=1, movbe=1, xsave=1 #cpuid: family=6, model=0x1a, stepping=5 #======================================================================= # MEMORY # Set the amount of physical memory you want to emulate. # # GUEST: # Set amount of guest physical memory to emulate. The default is 32MB, # the maximum amount limited only by physical address space limitations. # # HOST: # Set amount of host memory you want to allocate for guest RAM emulation. # It is possible to allocate less memory than you want to emulate in guest # system. This will fake guest to see the non-existing memory. Once guest # system touches new memory block it will be dynamically taken from the # memory pool. You will be warned (by FATAL PANIC) in case guest already # used all allocated host memory and wants more. # #======================================================================= memory: guest=512, host=256 #======================================================================= # OPTROMIMAGE[1-4]: # You may now load up to 4 optional ROM images. Be sure to use a # read-only area, typically between C8000 and EFFFF. These optional # ROM images should not overwrite the rombios (located at # F0000-FFFFF) and the videobios (located at C0000-C7FFF). # Those ROM images will be initialized by the bios if they contain # the right signature (0x55AA) and a valid checksum. # It can also be a convenient way to upload some arbitrary code/data # in the simulation, that can be retrieved by the boot loader #======================================================================= #optromimage1: file=optionalrom.bin, address=0xd0000 #optromimage2: file=optionalrom.bin, address=0xd1000 #optromimage3: file=optionalrom.bin, address=0xd2000 #optromimage4: file=optionalrom.bin, address=0xd3000 #optramimage1: file=/path/file1.img, address=0x0010000 #optramimage2: file=/path/file2.img, address=0x0020000 #optramimage3: file=/path/file3.img, address=0x0030000 #optramimage4: file=/path/file4.img, address=0x0040000 #======================================================================= # VGAROMIMAGE # You now need to load a VGA ROM BIOS into C0000. #======================================================================= #vgaromimage: file=bios/VGABIOS-elpin-2.40 vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest #vgaromimage: file=bios/VGABIOS-lgpl-latest-cirrus #======================================================================= # VGA: # This defines parameters related to the VGA display # # EXTENSION # Here you can specify the display extension to be used. With the value # 'none' you can use standard VGA with no extension. Other supported # values are 'vbe' for Bochs VBE and 'cirrus' for Cirrus SVGA support. # # UPDATE_FREQ # The VGA update frequency is based on the emulated clock and the default # value is 5. Keep in mind that you must tweak the 'cpu: ips=N' directive # to be as close to the number of emulated instructions-per-second your # workstation can do, for this to be accurate. If the realtime sync is # enabled with the 'clock' option, the value is based on the real time. # This parameter can be changed at runtime. # # Examples: # vga: extension=cirrus, update_freq=10 #======================================================================= #vga: extension=vbe, update_freq=5 #======================================================================= # FLOPPYA: # Point this to pathname of floppy image file or device # This should be of a bootable floppy(image/device) if you're # booting from 'a' (or 'floppy'). # # You can set the initial status of the media to 'ejected' or 'inserted'. # floppya: 2_88=path, status=ejected (2.88M 3.5" media) # floppya: 1_44=path, status=inserted (1.44M 3.5" media) # floppya: 1_2=path, status=ejected (1.2M 5.25" media) # floppya: 720k=path, status=inserted (720K 3.5" media) # floppya: 360k=path, status=inserted (360K 5.25" media) # floppya: 320k=path, status=inserted (320K 5.25" media) # floppya: 180k=path, status=inserted (180K 5.25" media) # floppya: 160k=path, status=inserted (160K 5.25" media) # floppya: image=path, status=inserted (guess media type from image size) # floppya: 1_44=vvfat:path, status=inserted (use directory as VFAT media) # floppya: type=1_44 (1.44M 3.5" floppy drive, no media) # # The path should be the name of a disk image file. On Unix, you can use a raw # device name such as /dev/fd0 on Linux. On win32 platforms, use drive letters # such as a: or b: as the path. The parameter 'image' works with image files # only. In that case the size must match one of the supported types. # The parameter 'type' can be used to enable the floppy drive without media # and status specified. Usually the drive type is set up based on the media type. # The optional parameter 'write_protected' can be used to control the media # write protect switch. By default it is turned off. #======================================================================= floppya: 1_44=/dev/fd0, status=inserted #floppya: image=../1.44, status=inserted #floppya: 1_44=/dev/fd0H1440, status=inserted #floppya: 1_2=../1_2, status=inserted #floppya: 1_44=a:, status=inserted #floppya: 1_44=a.img, status=inserted, write_protected=1 #floppya: 1_44=/dev/rfd0a, status=inserted #======================================================================= # FLOPPYB: # See FLOPPYA above for syntax #======================================================================= #floppyb: 1_44=b:, status=inserted #floppyb: 1_44=b.img, status=inserted #======================================================================= # ATA0, ATA1, ATA2, ATA3 # ATA controller for hard disks and cdroms # # ata[0-3]: enabled=[0|1], ioaddr1=addr, ioaddr2=addr, irq=number # # These options enables up to 4 ata channels. For each channel # the two base io addresses and the irq must be specified. # # ata0 and ata1 are enabled by default with the values shown below # # Examples: # ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 # ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 # ata2: enabled=1, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 # ata3: enabled=1, ioaddr1=0x168, ioaddr2=0x360, irq=9 #======================================================================= ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata2: enabled=0, ioaddr1=0x1e8, ioaddr2=0x3e0, irq=11 ata3: enabled=0, ioaddr1=0x168, ioaddr2=0x360, irq=9 #======================================================================= # ATA[0-3]-MASTER, ATA[0-3]-SLAVE # # This defines the type and characteristics of all attached ata devices: # type= type of attached device [disk|cdrom] # mode= only valid for disks [flat|concat|external|dll|sparse|vmware3] # [vmware4|undoable|growing|volatile|vpc|vvfat] # path= path of the image / directory # cylinders= only valid for disks # heads= only valid for disks # spt= only valid for disks # status= only valid for cdroms [inserted|ejected] # biosdetect= type of biosdetection [none|auto], only for disks on ata0 [cmos] # translation=type of translation of the bios, only for disks [none|lba|large|rechs|auto] # model= string returned by identify device command # journal= optional filename of the redolog for undoable, volatile and vvfat disks # # Point this at a hard disk image file, cdrom iso file, or physical cdrom # device. To create a hard disk image, try running bximage. It will help you # choose the size and then suggest a line that works with it. # # In UNIX it may be possible to use a raw device as a Bochs hard disk, # but WE DON'T RECOMMEND IT. In Windows there is no easy way. # # In windows, the drive letter + colon notation should be used for cdroms. # Depending on versions of windows and drivers, you may only be able to # access the "first" cdrom in the system. On MacOSX, use path="drive" # to access the physical drive. # # The path is mandatory for hard disks. Disk geometry autodetection works with # images created by bximage if CHS is set to 0/0/0 (cylinders are calculated # using heads=16 and spt=63). For other hard disk images and modes the # cylinders, heads, and spt are mandatory. In all cases the disk size reported # from the image must be exactly C*H*S*512. # # Default values are: # mode=flat, biosdetect=auto, translation=auto, model="Generic 1234" # # The biosdetect option has currently no effect on the bios # # Examples: # ata0-master: type=disk, mode=flat, path=10M.sample, cylinders=306, heads=4, spt=17 # ata0-slave: type=disk, mode=flat, path=20M.sample, cylinders=615, heads=4, spt=17 # ata1-master: type=disk, mode=flat, path=30M.sample, cylinders=615, heads=6, spt=17 # ata1-slave: type=disk, mode=flat, path=46M.sample, cylinders=940, heads=6, spt=17 # ata2-master: type=disk, mode=flat, path=62M.sample, cylinders=940, heads=8, spt=17 # ata2-slave: type=disk, mode=flat, path=112M.sample, cylinders=900, heads=15, spt=17 # ata3-master: type=disk, mode=flat, path=483M.sample, cylinders=1024, heads=15, spt=63 # ata3-slave: type=cdrom, path=iso.sample, status=inserted #======================================================================= ata0-master: type=disk, mode=flat, path="30M.sample" #ata0-master: type=disk, mode=flat, path="30M.sample", cylinders=615, heads=6, spt=17 #ata0-master: type=disk, mode=flat, path="c.img", cylinders=0 # autodetect #ata0-slave: type=disk, mode=vvfat, path=/bochs/images/vvfat, journal=vvfat.redolog #ata0-slave: type=cdrom, path=D:, status=inserted #ata0-slave: type=cdrom, path=/dev/cdrom, status=inserted #ata0-slave: type=cdrom, path="drive", status=inserted #ata0-slave: type=cdrom, path=/dev/rcd0d, status=inserted #======================================================================= # BOOT: # This defines the boot sequence. Now you can specify up to 3 boot drives, # which can be 'floppy', 'disk', 'cdrom' or 'network' (boot ROM). # Legacy 'a' and 'c' are also supported. # Examples: # boot: floppy # boot: cdrom, disk # boot: network, disk # boot: cdrom, floppy, disk #======================================================================= #boot: floppy boot: disk #======================================================================= # CLOCK: # This defines the parameters of the clock inside Bochs: # # SYNC: # This defines the method how to synchronize the Bochs internal time # with realtime. With the value 'none' the Bochs time relies on the IPS # value and no host time synchronization is used. The 'slowdown' method # sacrifices performance to preserve reproducibility while allowing host # time correlation. The 'realtime' method sacrifices reproducibility to # preserve performance and host-time correlation. # It is possible to enable both synchronization methods. # # RTC_SYNC: # If this option is enabled together with the realtime synchronization, # the RTC runs at realtime speed. This feature is disabled by default. # # TIME0: # Specifies the start (boot) time of the virtual machine. Use a time # value as returned by the time(2) system call. If no time0 value is # set or if time0 equal to 1 (special case) or if time0 equal 'local', # the simulation will be started at the current local host time. # If time0 equal to 2 (special case) or if time0 equal 'utc', # the simulation will be started at the current utc time. # # Syntax: # clock: sync=[none|slowdown|realtime|both], time0=[timeValue|local|utc] # # Example: # clock: sync=none, time0=local # Now (localtime) # clock: sync=slowdown, time0=315529200 # Tue Jan 1 00:00:00 1980 # clock: sync=none, time0=631148400 # Mon Jan 1 00:00:00 1990 # clock: sync=realtime, time0=938581955 # Wed Sep 29 07:12:35 1999 # clock: sync=realtime, time0=946681200 # Sat Jan 1 00:00:00 2000 # clock: sync=none, time0=1 # Now (localtime) # clock: sync=none, time0=utc # Now (utc/gmt) # # Default value are sync=none, time0=local #======================================================================= #clock: sync=none, time0=local #======================================================================= # FLOPPY_BOOTSIG_CHECK: disabled=[0|1] # Enables or disables the 0xaa55 signature check on boot floppies # Defaults to disabled=0 # Examples: # floppy_bootsig_check: disabled=0 # floppy_bootsig_check: disabled=1 #======================================================================= floppy_bootsig_check: disabled=0 #======================================================================= # LOG: # Give the path of the log file you'd like Bochs debug and misc. verbiage # to be written to. If you don't use this option or set the filename to # '-' the output is written to the console. If you really don't want it, # make it "/dev/null" (Unix) or "nul" (win32). :^( # # Examples: # log: ./bochs.out # log: /dev/tty #======================================================================= #log: /dev/null log: bochsout.txt #======================================================================= # LOGPREFIX: # This handles the format of the string prepended to each log line. # You may use those special tokens : # %t : 11 decimal digits timer tick # %i : 8 hexadecimal digits of cpu current eip (ignored in SMP configuration) # %e : 1 character event type ('i'nfo, 'd'ebug, 'p'anic, 'e'rror) # %d : 5 characters string of the device, between brackets # # Default : %t%e%d # Examples: # logprefix: %t-%e-@%i-%d # logprefix: %i%e%d #======================================================================= #logprefix: %t%e%d #======================================================================= # LOG CONTROLS # # Bochs has four severity levels for event logging. # panic: cannot proceed. If you choose to continue after a panic, # don't be surprised if you get strange behavior or crashes. # error: something went wrong, but it is probably safe to continue the # simulation. # info: interesting or useful messages. # debug: messages useful only when debugging the code. This may # spit out thousands per second. # # For events of each level, you can choose to exit Bochs ('fatal'), 'report' # or 'ignore'. On some guis you have the additional choice 'ask'. A gui dialog # appears asks how to proceed. # # It is also possible to specify the 'action' to do for each Bochs facility # separately (e.g. crash on panics from everything except the cdrom, and only # report those). See the 'log function' module list in the user documentation. # # If you are experiencing many panics, it can be helpful to change # the panic action to report instead of fatal. However, be aware # that anything executed after a panic is uncharted territory and can # cause bochs to become unstable. The panic is a "graceful exit," so # if you disable it you may get a spectacular disaster instead. #======================================================================= panic: action=ask error: action=report info: action=report debug: action=ignore, pci=report # report BX_DEBUG from module 'pci' #======================================================================= # DEBUGGER_LOG: # Give the path of the log file you'd like Bochs to log debugger output. # If you really don't want it, make it /dev/null or '-'. :^( # # Examples: # debugger_log: ./debugger.out #======================================================================= #debugger_log: /dev/null #debugger_log: debugger.out debugger_log: - #======================================================================= # COM1, COM2, COM3, COM4: # This defines a serial port (UART type 16550A). In the 'term' you can specify # a device to use as com1. This can be a real serial line, or a pty. To use # a pty (under X/Unix), create two windows (xterms, usually). One of them will # run bochs, and the other will act as com1. Find out the tty the com1 # window using the `tty' command, and use that as the `dev' parameter. # Then do `sleep 1000000' in the com1 window to keep the shell from # messing with things, and run bochs in the other window. Serial I/O to # com1 (port 0x3f8) will all go to the other window. # In socket* and pipe* (win32 only) modes Bochs becomes either socket/named pipe # client or server. In client mode it connects to an already running server (if # connection fails Bochs treats com port as not connected). In server mode it # opens socket/named pipe and waits until a client application connects to it # before starting simulation. This mode is useful for remote debugging (e.g. # with gdb's "target remote host:port" command or windbg's command line option # -k com:pipe,port=\\.\pipe\pipename). Note: 'socket' is a shorthand for # 'socket-client' and 'pipe' for 'pipe-client'. Socket modes use simple TCP # communication, pipe modes use duplex byte mode pipes. # Other serial modes are 'null' (no input/output), 'file' (output to a file # specified as the 'dev' parameter), 'raw' (use the real serial port - under # construction for win32), 'mouse' (standard serial mouse - requires # mouse option setting 'type=serial', 'type=serial_wheel' or 'type=serial_msys'). # # Examples: # com1: enabled=1, mode=null # com1: enabled=1, mode=mouse # com2: enabled=1, mode=file, dev=serial.out # com3: enabled=1, mode=raw, dev=com1 # com3: enabled=1, mode=socket-client, dev=localhost:8888 # com3: enabled=1, mode=socket-server, dev=localhost:8888 # com4: enabled=1, mode=pipe-client, dev=\\.\pipe\mypipe # com4: enabled=1, mode=pipe-server, dev=\\.\pipe\mypipe #======================================================================= #com1: enabled=1, mode=term, dev=/dev/ttyp9 #======================================================================= # PARPORT1, PARPORT2: # This defines a parallel (printer) port. When turned on and an output file is # defined the emulated printer port sends characters printed by the guest OS # into the output file. On some platforms a device filename can be used to # send the data to the real parallel port (e.g. "/dev/lp0" on Linux, "lpt1" on # win32 platforms). # # Examples: # parport1: enabled=1, file="parport.out" # parport2: enabled=1, file="/dev/lp0" # parport1: enabled=0 #======================================================================= parport1: enabled=1, file="parport.out" #======================================================================= # SB16: # This defines the SB16 sound emulation. It can have several of the # following properties. # All properties are in the format sb16: property=value # enabled: # This optional property controls the presence of the SB16 emulation. # The emulation is turned on unless this property is used and set to 0. # midi: The filename is where the midi data is sent. This can be a # device or just a file if you want to record the midi data. # midimode: # 0=no data # 1=output to device (system dependent. midi denotes the device driver) # 2=SMF file output, including headers # 3=output the midi data stream to the file (no midi headers and no # delta times, just command and data bytes) # wave: This is the device/file where wave output is stored # wavemode: # 0=no data # 1=output to device (system dependent. wave denotes the device driver) # 2=VOC file output, incl. headers # 3=output the raw wave stream to the file # log: The file to write the sb16 emulator messages to. # loglevel: # 0=no log # 1=resource changes, midi program and bank changes # 2=severe errors # 3=all errors # 4=all errors plus all port accesses # 5=all errors and port accesses plus a lot of extra info # dmatimer: # microseconds per second for a DMA cycle. Make it smaller to fix # non-continuous sound. 750000 is usually a good value. This needs a # reasonably correct setting for the IPS parameter of the CPU option. # # Examples for output devices: # sb16: midimode=1, midi="", wavemode=1, wave="" # win32 # sb16: midimode=1, midi=alsa:128:0, wavemode=1, wave=alsa # Linux with ALSA # sb16: wavemode=1, wave=sdl # use SDL audio (if present) for output #======================================================================= #sb16: midimode=1, midi=/dev/midi00, wavemode=1, wave=/dev/dsp, loglevel=2, log=sb16.log, dmatimer=600000 #======================================================================= # ES1370: # This defines the ES1370 sound emulation. The parameter 'enabled' controls the # presence of the device. The 'wavedev' parameter is similar to the 'wave' # parameter of the SB16 soundcard. The emulation supports recording and playback # (except DAC1+DAC2 output at the same time). # # Examples: # es1370: enabled=1, wavedev="" # win32 # es1370: enabled=1, wavedev=alsa # Linux with ALSA # es1370: enabled=1, wavedev=sdl # use SDL audio (if present) for output #======================================================================= #es1370: enabled=1, wavedev=alsa #======================================================================= # KEYBOARD: # This defines parameters related to the emulated keyboard # # TYPE: # Type of keyboard return by a "identify keyboard" command to the # keyboard controller. It must be one of "xt", "at" or "mf". # Defaults to "mf". It should be ok for almost everybody. A known # exception is french macs, that do have a "at"-like keyboard. # # SERIAL_DELAY: # Approximate time in microseconds that it takes one character to # be transferred from the keyboard to controller over the serial path. # # PASTE_DELAY: # Approximate time in microseconds between attempts to paste # characters to the keyboard controller. This leaves time for the # guest os to deal with the flow of characters. The ideal setting # depends on how your operating system processes characters. The # default of 100000 usec (.1 seconds) was chosen because it works # consistently in Windows. # If your OS is losing characters during a paste, increase the paste # delay until it stops losing characters. # # KEYMAP: # This enables a remap of a physical localized keyboard to a # virtualized us keyboard, as the PC architecture expects. # # Examples: # keyboard: type=mf, serial_delay=200, paste_delay=100000 # keyboard: keymap=gui/keymaps/x11-pc-de.map #======================================================================= #keyboard: type=mf, serial_delay=250 #======================================================================= # MOUSE: # This defines parameters for the emulated mouse type, the initial status # of the mouse capture and the runtime method to toggle it. # # TYPE: # With the mouse type option you can select the type of mouse to emulate. # The default value is 'ps2'. The other choices are 'imps2' (wheel mouse # on PS/2), 'serial', 'serial_wheel' and 'serial_msys' (one com port requires # setting 'mode=mouse'). To connect a mouse to an USB port, see the 'usb_uhci', # 'usb_ohci' or 'usb_xhci' options (requires PCI and USB support). # # ENABLED: # The Bochs gui creates mouse "events" unless the 'enabled' option is # set to 0. The hardware emulation itself is not disabled by this. # Unless you have a particular reason for enabling the mouse by default, # it is recommended that you leave it off. You can also toggle the mouse # usage at runtime (RFB, SDL, Win32, wxWidgets and X11 - see below). # # TOGGLE: # The default method to toggle the mouse capture at runtime is to press the # CTRL key and the middle mouse button ('ctrl+mbutton'). This option allows # to change the method to 'ctrl+f10' (like DOSBox), 'ctrl+alt' (like QEMU) # or 'f12' (replaces win32 'legacyF12' option). # # Examples: # mouse: enabled=1 # mouse: type=imps2, enabled=1 # mouse: type=serial, enabled=1 # mouse: enabled=0, toggle=ctrl+f10 #======================================================================= mouse: enabled=0 #======================================================================= # private_colormap: Request that the GUI create and use it's own # non-shared colormap. This colormap will be used # when in the bochs window. If not enabled, a # shared colormap scheme may be used. Not implemented # on all GUI's. # # Examples: # private_colormap: enabled=1 # private_colormap: enabled=0 #======================================================================= private_colormap: enabled=0 #======================================================================= # fullscreen: ONLY IMPLEMENTED ON AMIGA # Request that Bochs occupy the entire screen instead of a # window. # # Examples: # fullscreen: enabled=0 # fullscreen: enabled=1 #======================================================================= #fullscreen: enabled=0 #screenmode: name="sample" #======================================================================= # ne2k: NE2000 compatible ethernet adapter # # Format: # ne2k: enabled=1, ioaddr=IOADDR, irq=IRQ, mac=MACADDR, ethmod=MODULE, # ethdev=DEVICE, script=SCRIPT, bootrom=BOOTROM # # IOADDR, IRQ: You probably won't need to change ioaddr and irq, unless there # are IRQ conflicts. These arguments are ignored when assign the ne2k to a # PCI slot. # # MAC: The MAC address MUST NOT match the address of any machine on the net. # Also, the first byte must be an even number (bit 0 set means a multicast # address), and you cannot use ff:ff:ff:ff:ff:ff because that's the broadcast # address. For the ethertap module, you must use fe:fd:00:00:00:01. There may # be other restrictions too. To be safe, just use the b0:c4... address. # # ETHDEV: The ethdev value is the name of the network interface on your host # platform. On UNIX machines, you can get the name by running ifconfig. On # Windows machines, you must run niclist to get the name of the ethdev. # Niclist source code is in misc/niclist.c and it is included in Windows # binary releases. # # SCRIPT: The script value is optional, and is the name of a script that # is executed after bochs initialize the network interface. You can use # this script to configure this network interface, or enable masquerading. # This is mainly useful for the tun/tap devices that only exist during # Bochs execution. The network interface name is supplied to the script # as first parameter. # # BOOTROM: The bootrom value is optional, and is the name of the ROM image # to load. Note that this feature is only implemented for the PCI version of # the NE2000. # # If you don't want to make connections to any physical networks, # you can use the following 'ethmod's to simulate a virtual network. # null: All packets are discarded, but logged to a few files. # vde: Virtual Distributed Ethernet # vnet: ARP, ICMP-echo(ping), DHCP and read/write TFTP are simulated. # The virtual host uses 192.168.10.1. # DHCP assigns 192.168.10.2 to the guest. # TFTP uses the 'ethdev' value for the root directory and doesn't # overwrite files. # #======================================================================= # ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=fbsd, ethdev=en0 #macosx # ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=fbsd, ethdev=xl0 # ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:00, ethmod=linux, ethdev=eth0 # ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=win32, ethdev=MYCARD # ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0 # ne2k: ioaddr=0x300, irq=9, mac=fe:fd:00:00:00:01, ethmod=tuntap, ethdev=/dev/net/tun0, script=./tunconfig # ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=null, ethdev=eth0 # ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vde, ethdev="/tmp/vde.ctl" # ne2k: ioaddr=0x300, irq=9, mac=b0:c4:20:00:00:01, ethmod=vnet, ethdev="c:/temp" # ne2k: mac=b0:c4:20:00:00:01, ethmod=slirp, script=/usr/local/bin/slirp, bootrom=ne2k_pci.rom #======================================================================= # pcipnic: Bochs/Etherboot pseudo-NIC # # Format: # pcipnic: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT, # bootrom=BOOTROM # # The pseudo-NIC accepts the same syntax (for mac, ethmod, ethdev, script, # bootrom) and supports the same networking modules as the NE2000 adapter. #======================================================================= #pcipnic: enabled=1, mac=b0:c4:20:00:00:00, ethmod=vnet #======================================================================= # e1000: Intel(R) 82540EM Gigabit Ethernet adapter # # Format: # e1000: enabled=1, mac=MACADDR, ethmod=MODULE, ethdev=DEVICE, script=SCRIPT # bootrom=BOOTROM # # The E1000 accepts the same syntax (for mac, ethmod, ethdev, script, bootrom) # and supports the same networking modules as the NE2000 adapter. #======================================================================= #e1000: enabled=1, mac=52:54:00:12:34:56, ethmod=slirp, script=/usr/local/bin/slirp #======================================================================= # USER_SHORTCUT: # This defines the keyboard shortcut to be sent when you press the "user" # button in the headerbar. The shortcut string is a combination of maximum # 3 key names (listed below) separated with a '-' character. # Valid key names: # "alt", "bksl", "bksp", "ctrl", "del", "down", "end", "enter", "esc", # "f1", ... "f12", "home", "ins", "left", "menu", "minus", "pgdwn", "pgup", # "plus", "right", "shift", "space", "tab", "up", "win", "print" and "power". # # Example: # user_shortcut: keys=ctrl-alt-del #======================================================================= #user_shortcut: keys=ctrl-alt-del #======================================================================= # PCI: # This option controls the presence of a PCI chipset in Bochs. Currently it only # supports the i440FX chipset. You can also specify the devices connected to # PCI slots. Up to 5 slots are available. For these combined PCI/ISA devices # assigning to slot is mandatory if you want to emulate the PCI model: cirrus, # ne2k and pcivga. These PCI-only devices are also supported, but they are # auto-assigned if you don't use the slot configuration: e1000, es1370, pcidev, # pcipnic, usb_ohci and usb_xhci. # # Example: # pci: enabled=1, chipset=i440fx, slot1=pcivga, slot2=ne2k #======================================================================= pci: enabled=1, chipset=i440fx #======================================================================= # USB_UHCI: # This option controls the presence of the USB root hub which is a part # of the i440FX PCI chipset. With the portX parameter you can connect devices # to the hub (currently supported: 'mouse', 'tablet', 'keypad', 'disk', 'cdrom' # 'hub' and 'printer'). # # The optionsX parameter can be used to assign specific options to the device # connected to the corresponding USB port. Currently this feature is only used # to set the speed reported by device and by the 'disk' device to specify # an alternative redolog file of some image modes. # # If you connect the mouse or tablet to one of the ports, Bochs forwards the # mouse movement data to the USB device instead of the selected mouse type. # When connecting the keypad to one of the ports, Bochs forwards the input of # the numeric keypad to the USB device instead of the PS/2 keyboard. # # To connect a 'flat' mode image as an USB hardisk you can use the 'disk' device # with the path to the image separated with a colon. To use other disk image modes # similar to ATA disks the syntax 'disk:mode:filename' must be used (see below). # # To emulate an USB cdrom you can use the 'cdrom' device name and the path to # an ISO image or raw device name also separated with a colon. An option to # insert/eject media is available in the runtime configuration. # # The device name 'hub' connects an external hub with max. 8 ports (default: 4) # to the root hub. To specify the number of ports you have to add the value # separated with a colon. Connecting devices to the external hub ports is only # available in the runtime configuration. # # The device 'printer' emulates the HP Deskjet 920C printer. The PCL data is # sent to a file specified in bochsrc.txt. The current code appends the PCL # code to the file if the file already existed. It would probably be nice to # overwrite the file instead, asking user first. #======================================================================= #usb_uhci: enabled=1 #usb_uhci: enabled=1, port1=mouse, port2=disk:usbstick.img #usb_uhci: enabled=1, port1=hub:7, port2=disk:growing:usbdisk.img #usb_uhci: enabled=1, port2=disk:undoable:usbdisk.img, options1=journal:redo.log #usb_uhci: enabled=1, port1=printer:printdata.bin, port2=cdrom:image.iso #======================================================================= # USB_OHCI: # This option controls the presence of the USB OHCI host controller with a # 2-port hub. The portX option accepts the same device types with the same # syntax as the UHCI controller (see above). #======================================================================= #usb_ohci: enabled=1 #usb_ohci: enabled=1, port1=printer:usbprinter.bin #======================================================================= # USB_XHCI: # This option controls the presence of the experimental USB xHCI host controller # with a 4-port hub. The portX option accepts the same device types with the # same syntax as the UHCI controller (see above). #======================================================================= #usb_xhci: enabled=1 #======================================================================= # CMOSIMAGE: # This defines image file that can be loaded into the CMOS RAM at startup. # The rtc_init parameter controls whether initialize the RTC with values stored # in the image. By default the time0 argument given to the clock option is used. # With 'rtc_init=image' the image is the source for the initial time. # # Example: # cmosimage: file=cmos.img, rtc_init=image #======================================================================= #cmosimage: file=cmos.img, rtc_init=time0 #======================================================================= # MAGIC_BREAK: # This enables the "magic breakpoint" feature when using the debugger. # The useless cpu instruction XCHG BX, BX causes Bochs to enter the # debugger mode. This might be useful for software development. # # Example: # magic_break: enabled=1 #======================================================================= #magic_break: enabled=1 #======================================================================= # PORT_E9_HACK: # The 0xE9 port doesn't exists in normal ISA architecture. However, we # define a convention here, to display on the console of the system running # Bochs anything that is written to it. The idea is to provide debug output # very early when writing BIOS or OS code for example, without having to # bother with setting up a serial port or etc. Reading from port 0xE9 will # will return 0xe9 to let you know if the feature is available. # Leave this 0 unless you have a reason to use it. # # Example: # port_e9_hack: enabled=1 #======================================================================= #port_e9_hack: enabled=1 #======================================================================= # DEBUG_SYMBOLS: # This loads symbols from the specified file for use in Bochs' internal # debugger. Symbols are loaded into global context. This is equivalent to # issuing ldsym debugger command at start up. # # Example: # debug_symbols: file="kernel.sym" # debug_symbols: file="kernel.sym", offset=0x80000000 #======================================================================= #debug_symbols: file="kernel.sym" #======================================================================= # other stuff #======================================================================= #load32bitOSImage: os=nullkernel, path=../kernel.img, iolog=../vga_io.log #load32bitOSImage: os=linux, path=../linux.img, iolog=../vga_io.log, initrd=../initrd.img #print_timestamps: enabled=1 #------------------------- # PCI host device mapping #------------------------- #pcidev: vendor=0x1234, device=0x5678 #======================================================================= # GDBSTUB: # Enable GDB stub. See user documentation for details. # Default value is enabled=0. #======================================================================= #gdbstub: enabled=0, port=1234, text_base=0, data_base=0, bss_base=0 #======================================================================= # USER_PLUGIN: # Load user-defined plugin. This option is available only if Bochs is # compiled with plugin support. Maximum 8 different plugins are supported. # See the example in the Bochs sources how to write a plugin device. #======================================================================= #user_plugin: name=testdev #======================================================================= # for Macintosh, use the style of pathnames in the following # examples. # # vgaromimage: :bios:VGABIOS-elpin-2.40 # romimage: file=:bios:BIOS-bochs-latest, address=0xf0000 # floppya: 1_44=[fd:], status=inserted #======================================================================= #======================================================================= # MEGS # Set the number of Megabytes of physical memory you want to emulate. # The default is 32MB, most OS's won't need more than that. # The maximum amount of memory supported is 2048Mb. # The 'MEGS' option is deprecated. Use 'MEMORY' option instead. #======================================================================= #megs: 256 #megs: 128 #megs: 64 #megs: 32 #megs: 16 #megs: 8 bochs-2.6/bios/0000755000175000017500000000000012077504622013276 5ustar guillemguillembochs-2.6/bios/rombios32.c0000644000175000017500000021212112020641455015252 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: rombios32.c 11180 2012-05-13 20:06:51Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // 32 bit Bochs BIOS init code // Copyright (C) 2006 Fabrice Bellard // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include "rombios.h" typedef signed char int8_t; typedef short int16_t; typedef int int32_t; typedef long long int64_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned long long uint64_t; #define cpuid(index, eax, ebx, ecx, edx) \ asm volatile ("cpuid" \ : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) \ : "0" (index)) #define wbinvd() asm volatile("wbinvd") static inline void outl(int addr, int val) { asm volatile ("outl %1, %w0" : : "d" (addr), "a" (val)); } static inline void outw(int addr, int val) { asm volatile ("outw %w1, %w0" : : "d" (addr), "a" (val)); } static inline void outb(int addr, int val) { asm volatile ("outb %b1, %w0" : : "d" (addr), "a" (val)); } static inline uint32_t inl(int addr) { uint32_t val; asm volatile ("inl %w1, %0" : "=a" (val) : "d" (addr)); return val; } static inline uint16_t inw(int addr) { uint16_t val; asm volatile ("inw %w1, %w0" : "=a" (val) : "d" (addr)); return val; } static inline uint8_t inb(int addr) { uint8_t val; asm volatile ("inb %w1, %b0" : "=a" (val) : "d" (addr)); return val; } static inline void writel(void *addr, uint32_t val) { *(volatile uint32_t *)addr = val; } static inline void writew(void *addr, uint16_t val) { *(volatile uint16_t *)addr = val; } static inline void writeb(void *addr, uint8_t val) { *(volatile uint8_t *)addr = val; } static inline uint32_t readl(const void *addr) { return *(volatile const uint32_t *)addr; } static inline uint16_t readw(const void *addr) { return *(volatile const uint16_t *)addr; } static inline uint8_t readb(const void *addr) { return *(volatile const uint8_t *)addr; } static inline void putch(int c) { outb(INFO_PORT, c); } static uint64_t rdmsr(unsigned index) { unsigned long long ret; asm ("rdmsr" : "=A"(ret) : "c"(index)); return ret; } static void wrmsr(unsigned index, uint64_t val) { asm volatile ("wrmsr" : : "c"(index), "A"(val)); } static inline int isdigit(int c) { return c >= '0' && c <= '9'; } void *memset(void *d1, int val, size_t len) { uint8_t *d = d1; while (len--) { *d++ = val; } return d1; } void *memcpy(void *d1, const void *s1, size_t len) { uint8_t *d = d1; const uint8_t *s = s1; while (len--) { *d++ = *s++; } return d1; } void *memmove(void *d1, const void *s1, size_t len) { uint8_t *d = d1; const uint8_t *s = s1; if (d <= s) { while (len--) { *d++ = *s++; } } else { d += len; s += len; while (len--) { *--d = *--s; } } return d1; } int memcmp(const void *s1, const void *s2, size_t len) { const int8_t *p1 = s1; const int8_t *p2 = s2; while (len--) { int r = *p1++ - *p2++; if(r) return r; } return 0; } size_t strlen(const char *s) { const char *s1; for(s1 = s; *s1 != '\0'; s1++); return s1 - s; } /* from BSD ppp sources */ int vsnprintf(char *buf, int buflen, const char *fmt, va_list args) { int c, i, n; int width, prec, fillch; int base, len, neg; unsigned long val = 0; const char *f; char *str, *buf0; char num[32]; static const char hexchars[] = "0123456789abcdef"; buf0 = buf; --buflen; while (buflen > 0) { for (f = fmt; *f != '%' && *f != 0; ++f) ; if (f > fmt) { len = f - fmt; if (len > buflen) len = buflen; memcpy(buf, fmt, len); buf += len; buflen -= len; fmt = f; } if (*fmt == 0) break; c = *++fmt; width = prec = 0; fillch = ' '; if (c == '0') { fillch = '0'; c = *++fmt; } if (c == '*') { width = va_arg(args, int); c = *++fmt; } else { while (isdigit(c)) { width = width * 10 + c - '0'; c = *++fmt; } } if (c == '.') { c = *++fmt; if (c == '*') { prec = va_arg(args, int); c = *++fmt; } else { while (isdigit(c)) { prec = prec * 10 + c - '0'; c = *++fmt; } } } /* modifiers */ switch(c) { case 'l': c = *++fmt; break; default: break; } str = 0; base = 0; neg = 0; ++fmt; switch (c) { case 'd': i = va_arg(args, int); if (i < 0) { neg = 1; val = -i; } else val = i; base = 10; break; case 'o': val = va_arg(args, unsigned int); base = 8; break; case 'x': case 'X': val = va_arg(args, unsigned int); base = 16; break; case 'p': val = (unsigned long) va_arg(args, void *); base = 16; neg = 2; break; case 's': str = va_arg(args, char *); break; case 'c': num[0] = va_arg(args, int); num[1] = 0; str = num; break; default: *buf++ = '%'; if (c != '%') --fmt; /* so %z outputs %z etc. */ --buflen; continue; } if (base != 0) { str = num + sizeof(num); *--str = 0; while (str > num + neg) { *--str = hexchars[val % base]; val = val / base; if (--prec <= 0 && val == 0) break; } switch (neg) { case 1: *--str = '-'; break; case 2: *--str = 'x'; *--str = '0'; break; } len = num + sizeof(num) - 1 - str; } else { len = strlen(str); if (prec > 0 && len > prec) len = prec; } if (width > 0) { if (width > buflen) width = buflen; if ((n = width - len) > 0) { buflen -= n; for (; n > 0; --n) *buf++ = fillch; } } if (len > buflen) len = buflen; memcpy(buf, str, len); buf += len; buflen -= len; } *buf = 0; return buf - buf0; } int snprintf(char * buf, size_t size, const char *fmt, ...) { va_list args; int i; va_start(args, fmt); i = vsnprintf(buf, size, fmt, args); va_end(args); return i; } void bios_printf(int flags, const char *fmt, ...) { va_list ap; char buf[1024]; const char *s; if ((flags & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) outb(PANIC_PORT2, 0x00); va_start(ap, fmt); vsnprintf(buf, sizeof(buf), fmt, ap); s = buf; while (*s) putch(*s++); va_end(ap); } void delay_ms(int n) { int i, j; for(i = 0; i < n; i++) { #ifdef BX_QEMU volatile int k; /* approximative ! */ for(j = 0; j < 1000000; j++) { k++; } #else { int r1, r2; j = 66; r1 = inb(0x61) & 0x10; do { r2 = inb(0x61) & 0x10; if (r1 != r2) { j--; r1 = r2; } } while (j > 0); } #endif } } uint16_t smp_cpus; uint32_t cpuid_signature; uint32_t cpuid_features; uint32_t cpuid_ext_features; unsigned long ram_size; uint64_t ram_end; uint8_t bios_uuid[16]; #ifdef BX_USE_EBDA_TABLES unsigned long ebda_cur_addr; #endif int acpi_enabled; uint32_t pm_io_base, smb_io_base; int pm_sci_int; unsigned long bios_table_cur_addr; unsigned long bios_table_end_addr; void wrmsr_smp(uint32_t index, uint64_t val) { static struct { uint32_t ecx, eax, edx; } *p = (void *)SMP_MSR_ADDR; wrmsr(index, val); p->ecx = index; p->eax = val; p->edx = val >> 32; ++p; p->ecx = 0; } #ifdef BX_QEMU int qemu_cfg_port; void qemu_cfg_select(int f) { outw(QEMU_CFG_CTL_PORT, f); } int qemu_cfg_port_probe() { char *sig = "QEMU"; int i; qemu_cfg_select(QEMU_CFG_SIGNATURE); for (i = 0; i < 4; i++) if (inb(QEMU_CFG_DATA_PORT) != sig[i]) return 0; return 1; } void qemu_cfg_read(uint8_t *buf, int len) { while (len--) *(buf++) = inb(QEMU_CFG_DATA_PORT); } #endif void uuid_probe(void) { #ifdef BX_QEMU if(qemu_cfg_port) { qemu_cfg_select(QEMU_CFG_UUID); qemu_cfg_read(bios_uuid, 16); return; } #endif memset(bios_uuid, 0, 16); } void cpu_probe(void) { uint32_t eax, ebx, ecx, edx; cpuid(1, eax, ebx, ecx, edx); cpuid_signature = eax; cpuid_features = edx; cpuid_ext_features = ecx; } static int cmos_readb(int addr) { outb(0x70, addr); return inb(0x71); } void setup_mtrr(void) { int i, vcnt, fix, wc; uint32_t mtrr_cap; union { uint8_t valb[8]; uint64_t val; } u; *(uint32_t *)SMP_MSR_ADDR = 0; if (!(cpuid_features & CPUID_MTRR)) return; if (!(cpuid_features & CPUID_MSR)) return; mtrr_cap = rdmsr(MSR_MTRRcap); vcnt = mtrr_cap & 0xff; fix = mtrr_cap & 0x100; wc = mtrr_cap & 0x400; if (!vcnt || !fix) return; u.val = 0; for (i = 0; i < 8; ++i) if (ram_size >= 65536 * (i + 1)) u.valb[i] = 6; wrmsr_smp(MSR_MTRRfix64K_00000, u.val); u.val = 0; for (i = 0; i < 8; ++i) if (ram_size >= 65536 * 8 + 16384 * (i + 1)) u.valb[i] = 6; wrmsr_smp(MSR_MTRRfix16K_80000, u.val); wrmsr_smp(MSR_MTRRfix16K_A0000, 0); wrmsr_smp(MSR_MTRRfix4K_C0000, 0); wrmsr_smp(MSR_MTRRfix4K_C8000, 0); wrmsr_smp(MSR_MTRRfix4K_D0000, 0); wrmsr_smp(MSR_MTRRfix4K_D8000, 0); wrmsr_smp(MSR_MTRRfix4K_E0000, 0); wrmsr_smp(MSR_MTRRfix4K_E8000, 0); wrmsr_smp(MSR_MTRRfix4K_F0000, 0); wrmsr_smp(MSR_MTRRfix4K_F8000, 0); /* Mark 3-4GB as UC, anything not specified defaults to WB */ wrmsr_smp(MTRRphysBase_MSR(0), 0xc0000000 | MTRR_MEMTYPE_UC); /* Make sure no reserved bit set to '1 in MTRRphysMask_MSR */ wrmsr_smp(MTRRphysMask_MSR(0), (uint32_t)(~(0x40000000 - 1)) | 0x800); wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB); } void ram_probe(void) { if (cmos_readb(0x34) | cmos_readb(0x35)) ram_size = (cmos_readb(0x34) | (cmos_readb(0x35) << 8)) * 65536 + 16 * 1024 * 1024; else ram_size = (cmos_readb(0x30) | (cmos_readb(0x31) << 8)) * 1024 + 1 * 1024 * 1024; BX_INFO("ram_size=0x%08lx\n", ram_size); if (cmos_readb(0x5b) | cmos_readb(0x5c) | cmos_readb(0x5d)) ram_end = (((uint64_t)cmos_readb(0x5b) << 16) | ((uint64_t)cmos_readb(0x5c) << 24) | ((uint64_t)cmos_readb(0x5d) << 32)) + (1ull << 32); else ram_end = ram_size; BX_INFO("ram_end=%ldMB\n", ram_end >> 20); #ifdef BX_USE_EBDA_TABLES ebda_cur_addr = ((*(uint16_t *)(0x40e)) << 4) + 0x386; BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr); #endif } /****************************************************/ /* SMP probe */ extern uint8_t smp_ap_boot_code_start; extern uint8_t smp_ap_boot_code_end; /* find the number of CPUs by launching a SIPI to them */ void smp_probe(void) { uint32_t val, sipi_vector; writew(&smp_cpus, 1); if (cpuid_features & CPUID_APIC) { /* enable local APIC */ val = readl(APIC_BASE + APIC_SVR); val |= APIC_ENABLED; writel(APIC_BASE + APIC_SVR, val); /* copy AP boot code */ memcpy((void *)AP_BOOT_ADDR, &smp_ap_boot_code_start, &smp_ap_boot_code_end - &smp_ap_boot_code_start); /* broadcast SIPI */ writel(APIC_BASE + APIC_ICR_LOW, 0x000C4500); sipi_vector = AP_BOOT_ADDR >> 12; writel(APIC_BASE + APIC_ICR_LOW, 0x000C4600 | sipi_vector); #ifndef BX_QEMU delay_ms(10); #else while (cmos_readb(0x5f) + 1 != readw(&smp_cpus)) ; #endif } BX_INFO("Found %d cpu(s)\n", readw(&smp_cpus)); } /****************************************************/ /* PCI init */ typedef struct PCIDevice { int bus; int devfn; } PCIDevice; static uint32_t pci_bios_io_addr; static uint32_t pci_bios_mem_addr; static uint32_t pci_bios_rom_start; /* host irqs corresponding to PCI irqs A-D */ static uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; static PCIDevice i440_pcidev = {-1, -1}; static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) { outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); outl(0xcfc, val); } static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) { outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); outw(0xcfc + (addr & 2), val); } static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) { outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); outb(0xcfc + (addr & 3), val); } static uint32_t pci_config_readl(PCIDevice *d, uint32_t addr) { outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); return inl(0xcfc); } static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) { outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); return inw(0xcfc + (addr & 2)); } static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) { outl(0xcf8, 0x80000000 | (d->bus << 16) | (d->devfn << 8) | (addr & 0xfc)); return inb(0xcfc + (addr & 3)); } static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) { uint16_t cmd; uint32_t ofs, old_addr; if ( region_num == PCI_ROM_SLOT ) { ofs = PCI_ROM_ADDRESS; addr |= PCI_ROM_ADDRESS_ENABLE; }else{ ofs = PCI_BASE_ADDRESS_0 + region_num * 4; } old_addr = pci_config_readl(d, ofs); pci_config_writel(d, ofs, addr); BX_INFO("region %d: 0x%08x\n", region_num, addr & ~0x01); /* enable memory mappings */ cmd = pci_config_readw(d, PCI_COMMAND); if ( region_num == PCI_ROM_SLOT ) cmd |= PCI_COMMAND_MEMORY; else if (old_addr & PCI_ADDRESS_SPACE_IO) cmd |= PCI_COMMAND_IO; else cmd |= PCI_COMMAND_MEMORY; pci_config_writew(d, PCI_COMMAND, cmd); } /* return the global irq number corresponding to a given device irq pin. We could also use the bus number to have a more precise mapping. */ static int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) { int slot_addend; slot_addend = (pci_dev->devfn >> 3) - 1; return (irq_num + slot_addend) & 3; } static void find_bios_table_area(void) { unsigned long addr; for(addr = 0xf0000; addr < 0x100000; addr += 16) { if (*(uint32_t *)addr == 0xaafb4442) { bios_table_cur_addr = addr + 8; bios_table_end_addr = bios_table_cur_addr + *(uint32_t *)(addr + 4); BX_INFO("bios_table_addr: 0x%08lx end=0x%08lx\n", bios_table_cur_addr, bios_table_end_addr); return; } } return; } static void bios_shadow_init(PCIDevice *d) { int v; if (bios_table_cur_addr == 0) return; /* remap the BIOS to shadow RAM an keep it read/write while we are writing tables */ v = pci_config_readb(d, 0x59); v &= 0xcf; pci_config_writeb(d, 0x59, v); memcpy((void *)BIOS_TMP_STORAGE, (void *)0x000f0000, 0x10000); v |= 0x30; pci_config_writeb(d, 0x59, v); memcpy((void *)0x000f0000, (void *)BIOS_TMP_STORAGE, 0x10000); i440_pcidev = *d; } static void bios_lock_shadow_ram(void) { PCIDevice *d = &i440_pcidev; int v; wbinvd(); v = pci_config_readb(d, 0x59); v = (v & 0x0f) | (0x10); pci_config_writeb(d, 0x59, v); } static void pci_bios_init_bridges(PCIDevice *d) { uint16_t vendor_id, device_id; vendor_id = pci_config_readw(d, PCI_VENDOR_ID); device_id = pci_config_readw(d, PCI_DEVICE_ID); if (vendor_id == PCI_VENDOR_ID_INTEL && (device_id == PCI_DEVICE_ID_INTEL_82371SB_0 || device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) { int i, irq; uint8_t elcr[2]; /* PIIX3/PIIX4 PCI to ISA bridge */ elcr[0] = 0x00; elcr[1] = 0x00; for(i = 0; i < 4; i++) { irq = pci_irqs[i]; /* set to trigger level */ elcr[irq >> 3] |= (1 << (irq & 7)); /* activate irq remapping in PIIX */ pci_config_writeb(d, 0x60 + i, irq); } outb(0x4d0, elcr[0]); outb(0x4d1, elcr[1]); BX_INFO("PIIX3/PIIX4 init: elcr=%02x %02x\n", elcr[0], elcr[1]); } else if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441) { /* i440 PCI bridge */ bios_shadow_init(d); } } extern uint8_t smm_relocation_start, smm_relocation_end; extern uint8_t smm_code_start, smm_code_end; #ifdef BX_USE_SMM static void smm_init(PCIDevice *d) { uint32_t value; /* check if SMM init is already done */ value = pci_config_readl(d, 0x58); if ((value & (1 << 25)) == 0) { /* enable the SMM memory window */ pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x48); /* save original memory content */ memcpy((void *)0xa8000, (void *)0x38000, 0x8000); /* copy the SMM relocation code */ memcpy((void *)0x38000, &smm_relocation_start, &smm_relocation_end - &smm_relocation_start); /* enable SMI generation when writing to the APMC register */ pci_config_writel(d, 0x58, value | (1 << 25)); /* init APM status port */ outb(0xb3, 0x01); /* raise an SMI interrupt */ outb(0xb2, 0x00); /* wait until SMM code executed */ while (inb(0xb3) != 0x00); /* restore original memory content */ memcpy((void *)0x38000, (void *)0xa8000, 0x8000); /* copy the SMM code */ memcpy((void *)0xa8000, &smm_code_start, &smm_code_end - &smm_code_start); wbinvd(); /* close the SMM memory window and enable normal SMM */ pci_config_writeb(&i440_pcidev, 0x72, 0x02 | 0x08); } } #endif static void piix4_pm_enable(PCIDevice *d) { /* PIIX4 Power Management device (for ACPI) */ pci_config_writel(d, 0x40, PM_IO_BASE | 1); pci_config_writeb(d, 0x80, 0x01); /* enable PM io space */ pci_config_writel(d, 0x90, SMB_IO_BASE | 1); pci_config_writeb(d, 0xd2, 0x09); /* enable SMBus io space */ #ifdef BX_USE_SMM smm_init(d); #endif } static void pci_bios_init_pcirom(PCIDevice *d, uint32_t paddr) { PCIDevice d1, *i440fx = &d1; uint32_t tmpaddr, size; uint8_t reg, v; int copied, shift, tmpsize; i440fx->bus = 0; i440fx->devfn = 0; if (paddr != 0) { size = readb((void *)(paddr + 2)); if (size & 0x03) { size &= 0xfc; size += 0x04; } size <<= 9; if ((pci_bios_rom_start + size) > 0xe0000) return; tmpaddr = pci_bios_rom_start; copied = 0; do { tmpsize = 0x4000 - (tmpaddr & 0x3fff); if ((size - copied) < tmpsize) { tmpsize = size - copied; } reg = 0x5a + (uint8_t)((tmpaddr >> 15) & 0x07); if (tmpaddr & 0x4000) { shift = 4; } else { shift = 0; } v = pci_config_readb(i440fx, reg); v = (v & (~(0x03 << shift))) | (0x02 << shift); pci_config_writeb(i440fx, reg, v); memcpy((void *)tmpaddr, (void *)(paddr + copied), tmpsize); v = (v & (~(0x03 << shift))) | (0x01 << shift); pci_config_writeb(i440fx, reg, v); tmpaddr += tmpsize; copied += tmpsize; } while (copied < size); BX_INFO("PCI ROM copied to 0x%05x (size=0x%05x)\n", pci_bios_rom_start, size); pci_bios_rom_start += size; pci_config_writeb(d, PCI_ROM_ADDRESS, 0x00); } } static void pci_bios_init_device(PCIDevice *d) { PCIDevice d1, *i440fx = &d1; uint16_t class; uint32_t *paddr; int i, pin, pic_irq, vendor_id, device_id; i440fx->bus = 0; i440fx->devfn = 0; class = pci_config_readw(d, PCI_CLASS_DEVICE); vendor_id = pci_config_readw(d, PCI_VENDOR_ID); device_id = pci_config_readw(d, PCI_DEVICE_ID); BX_INFO("PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x class=0x%04x\n", d->bus, d->devfn, vendor_id, device_id, class); switch(class) { case PCI_CLASS_STORAGE_IDE: if (vendor_id == PCI_VENDOR_ID_INTEL && (device_id == PCI_DEVICE_ID_INTEL_82371SB_1 || device_id == PCI_DEVICE_ID_INTEL_82371AB)) { /* PIIX3/PIIX4 IDE */ pci_config_writew(d, 0x40, 0x8000); // enable IDE0 pci_config_writew(d, 0x42, 0x8000); // enable IDE1 goto default_map; } else { /* IDE: we map it as in ISA mode */ pci_set_io_region_addr(d, 0, 0x1f0); pci_set_io_region_addr(d, 1, 0x3f4); pci_set_io_region_addr(d, 2, 0x170); pci_set_io_region_addr(d, 3, 0x374); } break; case PCI_CLASS_SYSTEM_PIC: if (vendor_id == PCI_VENDOR_ID_IBM) { /* IBM */ if (device_id == 0x0046 || device_id == 0xFFFF) { /* MPIC & MPIC2 */ pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000); } } break; case 0xff00: if (vendor_id == PCI_VENDOR_ID_APPLE && (device_id == 0x0017 || device_id == 0x0022)) { /* macio bridge */ pci_set_io_region_addr(d, 0, 0x80800000); } break; default: default_map: /* default memory mappings */ for(i = 0; i < PCI_NUM_REGIONS; i++) { int ofs; uint32_t val, size ; if (i == PCI_ROM_SLOT) { ofs = PCI_ROM_ADDRESS; pci_config_writel(d, ofs, 0xfffffffe); } else { ofs = PCI_BASE_ADDRESS_0 + i * 4; pci_config_writel(d, ofs, 0xffffffff); } val = pci_config_readl(d, ofs); if (val != 0) { size = (~(val & ~0xf)) + 1; if (val & PCI_ADDRESS_SPACE_IO) paddr = &pci_bios_io_addr; else paddr = &pci_bios_mem_addr; *paddr = (*paddr + size - 1) & ~(size - 1); pci_set_io_region_addr(d, i, *paddr); if ((i == PCI_ROM_SLOT) && (class == PCI_CLASS_DISPLAY_VGA)) { pci_bios_init_pcirom(d, *paddr); } *paddr += size; } } break; } /* map the interrupt */ pin = pci_config_readb(d, PCI_INTERRUPT_PIN); if (pin != 0) { pin = pci_slot_get_pirq(d, pin - 1); pic_irq = pci_irqs[pin]; pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq); } if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) { /* PIIX4 Power Management device (for ACPI) */ pm_io_base = PM_IO_BASE; smb_io_base = SMB_IO_BASE; // acpi sci is hardwired to 9 pci_config_writeb(d, PCI_INTERRUPT_LINE, 9); pm_sci_int = pci_config_readb(d, PCI_INTERRUPT_LINE); piix4_pm_enable(d); acpi_enabled = 1; } } static void pci_bios_init_optrom(PCIDevice *d) { uint32_t paddr; uint16_t class; class = pci_config_readw(d, PCI_CLASS_DEVICE); if (class != PCI_CLASS_DISPLAY_VGA) { paddr = pci_config_readl(d, PCI_ROM_ADDRESS) & 0xfffffc00; pci_bios_init_pcirom(d, paddr); } } void pci_for_each_device(void (*init_func)(PCIDevice *d)) { PCIDevice d1, *d = &d1; int bus, devfn; uint16_t vendor_id, device_id; for(bus = 0; bus < 1; bus++) { for(devfn = 0; devfn < 256; devfn++) { d->bus = bus; d->devfn = devfn; vendor_id = pci_config_readw(d, PCI_VENDOR_ID); device_id = pci_config_readw(d, PCI_DEVICE_ID); if (vendor_id != 0xffff || device_id != 0xffff) { init_func(d); } } } } void pci_bios_init(void) { pci_bios_io_addr = 0xc000; pci_bios_mem_addr = 0xc0000000; pci_bios_rom_start = 0xc0000; pci_for_each_device(pci_bios_init_bridges); pci_for_each_device(pci_bios_init_device); pci_for_each_device(pci_bios_init_optrom); } /****************************************************/ /* Multi Processor table init */ static void putb(uint8_t **pp, int val) { uint8_t *q; q = *pp; *q++ = val; *pp = q; } static void putstr(uint8_t **pp, const char *str) { uint8_t *q; q = *pp; while (*str) *q++ = *str++; *pp = q; } static void putle16(uint8_t **pp, int val) { uint8_t *q; q = *pp; *q++ = val; *q++ = val >> 8; *pp = q; } static void putle32(uint8_t **pp, int val) { uint8_t *q; q = *pp; *q++ = val; *q++ = val >> 8; *q++ = val >> 16; *q++ = val >> 24; *pp = q; } static int mpf_checksum(const uint8_t *data, int len) { int sum, i; sum = 0; for(i = 0; i < len; i++) sum += data[i]; return sum & 0xff; } static unsigned long align(unsigned long addr, unsigned long v) { return (addr + v - 1) & ~(v - 1); } static void mptable_init(void) { uint8_t *mp_config_table, *q, *float_pointer_struct; int ioapic_id, i, len; int mp_config_table_size; #ifdef BX_USE_EBDA_TABLES if (ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE < 0x100000) { BX_INFO("Not enough memory for MPC table\n"); return; } mp_config_table = (uint8_t *)(ram_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE); #else bios_table_cur_addr = align(bios_table_cur_addr, 16); mp_config_table = (uint8_t *)bios_table_cur_addr; #endif q = mp_config_table; putstr(&q, "PCMP"); /* "PCMP signature */ putle16(&q, 0); /* table length (patched later) */ putb(&q, 4); /* spec rev */ putb(&q, 0); /* checksum (patched later) */ #ifdef BX_QEMU putstr(&q, "QEMUCPU "); /* OEM id */ #else putstr(&q, "BOCHSCPU"); #endif putstr(&q, "0.1 "); /* vendor id */ putle32(&q, 0); /* OEM table ptr */ putle16(&q, 0); /* OEM table size */ putle16(&q, smp_cpus + 18); /* entry count */ putle32(&q, 0xfee00000); /* local APIC addr */ putle16(&q, 0); /* ext table length */ putb(&q, 0); /* ext table checksum */ putb(&q, 0); /* reserved */ for(i = 0; i < smp_cpus; i++) { putb(&q, 0); /* entry type = processor */ putb(&q, i); /* APIC id */ putb(&q, 0x11); /* local APIC version number */ if (i == 0) putb(&q, 3); /* cpu flags: enabled, bootstrap cpu */ else putb(&q, 1); /* cpu flags: enabled */ if (cpuid_signature) { putle32(&q, cpuid_signature); putle32(&q, cpuid_features); } else { putb(&q, 0); /* cpu signature */ putb(&q, 6); putb(&q, 0); putb(&q, 0); putle16(&q, 0x201); /* feature flags */ putle16(&q, 0); } putle16(&q, 0); /* reserved */ putle16(&q, 0); putle16(&q, 0); putle16(&q, 0); } /* isa bus */ putb(&q, 1); /* entry type = bus */ putb(&q, 0); /* bus ID */ putstr(&q, "ISA "); /* ioapic */ ioapic_id = smp_cpus; putb(&q, 2); /* entry type = I/O APIC */ putb(&q, ioapic_id); /* apic ID */ putb(&q, 0x11); /* I/O APIC version number */ putb(&q, 1); /* enable */ putle32(&q, 0xfec00000); /* I/O APIC addr */ /* irqs */ for(i = 0; i < 16; i++) { /* One entry per ioapic input. Input 2 is covered by irq0->inti2 override (i == 0). irq 2 is unused */ if (i == 2) continue; putb(&q, 3); /* entry type = I/O interrupt */ putb(&q, 0); /* interrupt type = vectored interrupt */ putb(&q, 0); /* flags: po=0, el=0 */ putb(&q, 0); putb(&q, 0); /* source bus ID = ISA */ putb(&q, i); /* source bus IRQ */ putb(&q, ioapic_id); /* dest I/O APIC ID */ putb(&q, i == 0 ? 2 : i); /* dest I/O APIC interrupt in */ } /* patch length */ len = q - mp_config_table; mp_config_table[4] = len; mp_config_table[5] = len >> 8; mp_config_table[7] = -mpf_checksum(mp_config_table, q - mp_config_table); mp_config_table_size = q - mp_config_table; #ifndef BX_USE_EBDA_TABLES bios_table_cur_addr += mp_config_table_size; #endif /* floating pointer structure */ #ifdef BX_USE_EBDA_TABLES ebda_cur_addr = align(ebda_cur_addr, 16); float_pointer_struct = (uint8_t *)ebda_cur_addr; #else bios_table_cur_addr = align(bios_table_cur_addr, 16); float_pointer_struct = (uint8_t *)bios_table_cur_addr; #endif q = float_pointer_struct; putstr(&q, "_MP_"); /* pointer to MP config table */ putle32(&q, (unsigned long)mp_config_table); putb(&q, 1); /* length in 16 byte units */ putb(&q, 4); /* MP spec revision */ putb(&q, 0); /* checksum (patched later) */ putb(&q, 0); /* MP feature byte 1 */ putb(&q, 0); putb(&q, 0); putb(&q, 0); putb(&q, 0); float_pointer_struct[10] = -mpf_checksum(float_pointer_struct, q - float_pointer_struct); #ifdef BX_USE_EBDA_TABLES ebda_cur_addr += (q - float_pointer_struct); #else bios_table_cur_addr += (q - float_pointer_struct); #endif BX_INFO("MP table addr=0x%08lx MPC table addr=0x%08lx size=0x%x\n", (unsigned long)float_pointer_struct, (unsigned long)mp_config_table, mp_config_table_size); } /****************************************************/ /* ACPI tables init */ /* Table structure from Linux kernel (the ACPI tables are under the BSD license) */ /* * All tables must be byte-packed to match the ACPI specification, since * the tables are provided by the system BIOS. */ #define ACPI_TABLE_HEADER_DEF /* ACPI common table header */ \ uint8_t signature [4]; /* ACPI signature (4 ASCII characters) */\ uint32_t length; /* Length of table, in bytes, including header */\ uint8_t revision; /* ACPI Specification minor version # */\ uint8_t checksum; /* To make sum of entire table == 0 */\ uint8_t oem_id [6]; /* OEM identification */\ uint8_t oem_table_id [8]; /* OEM table identification */\ uint32_t oem_revision; /* OEM revision number */\ uint8_t asl_compiler_id [4]; /* ASL compiler vendor ID */\ uint32_t asl_compiler_revision; /* ASL compiler revision number */ struct acpi_table_header /* ACPI common table header */ { ACPI_TABLE_HEADER_DEF } __attribute__((__packed__)); struct rsdp_descriptor /* Root System Descriptor Pointer */ { uint8_t signature [8]; /* ACPI signature, contains "RSD PTR " */ uint8_t checksum; /* To make sum of struct == 0 */ uint8_t oem_id [6]; /* OEM identification */ uint8_t revision; /* Must be 0 for 1.0, 2 for 2.0 */ uint32_t rsdt_physical_address; /* 32-bit physical address of RSDT */ uint32_t length; /* XSDT Length in bytes including hdr */ uint64_t xsdt_physical_address; /* 64-bit physical address of XSDT */ uint8_t extended_checksum; /* Checksum of entire table */ uint8_t reserved [3]; /* Reserved field must be 0 */ } __attribute__((__packed__)); /* * ACPI 1.0 Root System Description Table (RSDT) */ struct rsdt_descriptor_rev1 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ #ifdef BX_QEMU uint32_t table_offset_entry [4]; /* Array of pointers to other */ #else uint32_t table_offset_entry [3]; /* Array of pointers to other */ #endif /* ACPI tables */ } __attribute__((__packed__)); /* * ACPI 1.0 Firmware ACPI Control Structure (FACS) */ struct facs_descriptor_rev1 { uint8_t signature[4]; /* ACPI Signature */ uint32_t length; /* Length of structure, in bytes */ uint32_t hardware_signature; /* Hardware configuration signature */ uint32_t firmware_waking_vector; /* ACPI OS waking vector */ uint32_t global_lock; /* Global Lock */ uint32_t S4bios_f : 1; /* Indicates if S4BIOS support is present */ uint32_t reserved1 : 31; /* Must be 0 */ uint8_t resverved3 [40]; /* Reserved - must be zero */ } __attribute__((__packed__)); /* * ACPI 1.0 Fixed ACPI Description Table (FADT) */ struct fadt_descriptor_rev1 { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ uint32_t firmware_ctrl; /* Physical address of FACS */ uint32_t dsdt; /* Physical address of DSDT */ uint8_t model; /* System Interrupt Model */ uint8_t reserved1; /* Reserved */ uint16_t sci_int; /* System vector of SCI interrupt */ uint32_t smi_cmd; /* Port address of SMI command port */ uint8_t acpi_enable; /* Value to write to smi_cmd to enable ACPI */ uint8_t acpi_disable; /* Value to write to smi_cmd to disable ACPI */ uint8_t S4bios_req; /* Value to write to SMI CMD to enter S4BIOS state */ uint8_t reserved2; /* Reserved - must be zero */ uint32_t pm1a_evt_blk; /* Port address of Power Mgt 1a acpi_event Reg Blk */ uint32_t pm1b_evt_blk; /* Port address of Power Mgt 1b acpi_event Reg Blk */ uint32_t pm1a_cnt_blk; /* Port address of Power Mgt 1a Control Reg Blk */ uint32_t pm1b_cnt_blk; /* Port address of Power Mgt 1b Control Reg Blk */ uint32_t pm2_cnt_blk; /* Port address of Power Mgt 2 Control Reg Blk */ uint32_t pm_tmr_blk; /* Port address of Power Mgt Timer Ctrl Reg Blk */ uint32_t gpe0_blk; /* Port addr of General Purpose acpi_event 0 Reg Blk */ uint32_t gpe1_blk; /* Port addr of General Purpose acpi_event 1 Reg Blk */ uint8_t pm1_evt_len; /* Byte length of ports at pm1_x_evt_blk */ uint8_t pm1_cnt_len; /* Byte length of ports at pm1_x_cnt_blk */ uint8_t pm2_cnt_len; /* Byte Length of ports at pm2_cnt_blk */ uint8_t pm_tmr_len; /* Byte Length of ports at pm_tm_blk */ uint8_t gpe0_blk_len; /* Byte Length of ports at gpe0_blk */ uint8_t gpe1_blk_len; /* Byte Length of ports at gpe1_blk */ uint8_t gpe1_base; /* Offset in gpe model where gpe1 events start */ uint8_t reserved3; /* Reserved */ uint16_t plvl2_lat; /* Worst case HW latency to enter/exit C2 state */ uint16_t plvl3_lat; /* Worst case HW latency to enter/exit C3 state */ uint16_t flush_size; /* Size of area read to flush caches */ uint16_t flush_stride; /* Stride used in flushing caches */ uint8_t duty_offset; /* Bit location of duty cycle field in p_cnt reg */ uint8_t duty_width; /* Bit width of duty cycle field in p_cnt reg */ uint8_t day_alrm; /* Index to day-of-month alarm in RTC CMOS RAM */ uint8_t mon_alrm; /* Index to month-of-year alarm in RTC CMOS RAM */ uint8_t century; /* Index to century in RTC CMOS RAM */ uint8_t reserved4; /* Reserved */ uint8_t reserved4a; /* Reserved */ uint8_t reserved4b; /* Reserved */ #if 0 uint32_t wb_invd : 1; /* The wbinvd instruction works properly */ uint32_t wb_invd_flush : 1; /* The wbinvd flushes but does not invalidate */ uint32_t proc_c1 : 1; /* All processors support C1 state */ uint32_t plvl2_up : 1; /* C2 state works on MP system */ uint32_t pwr_button : 1; /* Power button is handled as a generic feature */ uint32_t sleep_button : 1; /* Sleep button is handled as a generic feature, or not present */ uint32_t fixed_rTC : 1; /* RTC wakeup stat not in fixed register space */ uint32_t rtcs4 : 1; /* RTC wakeup stat not possible from S4 */ uint32_t tmr_val_ext : 1; /* The tmr_val width is 32 bits (0 = 24 bits) */ uint32_t reserved5 : 23; /* Reserved - must be zero */ #else uint32_t flags; #endif } __attribute__((__packed__)); /* * MADT values and structures */ /* Values for MADT PCATCompat */ #define DUAL_PIC 0 #define MULTIPLE_APIC 1 /* Master MADT */ struct multiple_apic_table { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ uint32_t local_apic_address; /* Physical address of local APIC */ #if 0 uint32_t PCATcompat : 1; /* A one indicates system also has dual 8259s */ uint32_t reserved1 : 31; #else uint32_t flags; #endif } __attribute__((__packed__)); /* Values for Type in APIC_HEADER_DEF */ #define APIC_PROCESSOR 0 #define APIC_IO 1 #define APIC_XRUPT_OVERRIDE 2 #define APIC_NMI 3 #define APIC_LOCAL_NMI 4 #define APIC_ADDRESS_OVERRIDE 5 #define APIC_IO_SAPIC 6 #define APIC_LOCAL_SAPIC 7 #define APIC_XRUPT_SOURCE 8 #define APIC_RESERVED 9 /* 9 and greater are reserved */ /* * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) */ #define APIC_HEADER_DEF /* Common APIC sub-structure header */\ uint8_t type; \ uint8_t length; /* Sub-structures for MADT */ struct madt_processor_apic { APIC_HEADER_DEF uint8_t processor_id; /* ACPI processor id */ uint8_t local_apic_id; /* Processor's local APIC id */ #if 0 uint32_t processor_enabled: 1; /* Processor is usable if set */ uint32_t reserved2 : 31; /* Reserved, must be zero */ #else uint32_t flags; #endif } __attribute__((__packed__)); #ifdef BX_QEMU /* * * ACPI 2.0 Generic Address Space definition. * */ struct acpi_20_generic_address { uint8_t address_space_id; uint8_t register_bit_width; uint8_t register_bit_offset; uint8_t reserved; uint64_t address; } __attribute__((__packed__)); /* * * HPET Description Table * */ struct acpi_20_hpet { ACPI_TABLE_HEADER_DEF /* ACPI common table header */ uint32_t timer_block_id; struct acpi_20_generic_address addr; uint8_t hpet_number; uint16_t min_tick; uint8_t page_protect; } __attribute__((__packed__)); #define ACPI_HPET_ADDRESS 0xFED00000UL #endif struct madt_io_apic { APIC_HEADER_DEF uint8_t io_apic_id; /* I/O APIC ID */ uint8_t reserved; /* Reserved - must be zero */ uint32_t address; /* APIC physical address */ uint32_t interrupt; /* Global system interrupt where INTI * lines start */ } __attribute__((__packed__)); struct madt_int_override { APIC_HEADER_DEF uint8_t bus; /* Identifies ISA Bus */ uint8_t source; /* Bus-relative interrupt source */ uint32_t gsi; /* GSI that source will signal */ uint16_t flags; /* MPS INTI flags */ } __attribute__((__packed__)); #include "acpi-dsdt.hex" static inline uint16_t cpu_to_le16(uint16_t x) { return x; } static inline uint32_t cpu_to_le32(uint32_t x) { return x; } static int acpi_checksum(const uint8_t *data, int len) { int sum, i; sum = 0; for(i = 0; i < len; i++) sum += data[i]; return (-sum) & 0xff; } static void acpi_build_table_header(struct acpi_table_header *h, char *sig, int len, uint8_t rev) { memcpy(h->signature, sig, 4); h->length = cpu_to_le32(len); h->revision = rev; #ifdef BX_QEMU memcpy(h->oem_id, "QEMU ", 6); memcpy(h->oem_table_id, "QEMU", 4); #else memcpy(h->oem_id, "BOCHS ", 6); memcpy(h->oem_table_id, "BXPC", 4); #endif memcpy(h->oem_table_id + 4, sig, 4); h->oem_revision = cpu_to_le32(1); #ifdef BX_QEMU memcpy(h->asl_compiler_id, "QEMU", 4); #else memcpy(h->asl_compiler_id, "BXPC", 4); #endif h->asl_compiler_revision = cpu_to_le32(1); h->checksum = acpi_checksum((void *)h, len); } int acpi_build_processor_ssdt(uint8_t *ssdt) { uint8_t *ssdt_ptr = ssdt; int i, length; int acpi_cpus = smp_cpus > 0xff ? 0xff : smp_cpus; ssdt_ptr[9] = 0; // checksum; ssdt_ptr += sizeof(struct acpi_table_header); // caluculate the length of processor block and scope block excluding PkgLength length = 0x0d * acpi_cpus + 4; // build processor scope header *(ssdt_ptr++) = 0x10; // ScopeOp if (length <= 0x3e) { /* Handle 1-4 CPUs with one byte encoding */ *(ssdt_ptr++) = length + 1; } else { /* Handle 5-314 CPUs with two byte encoding */ *(ssdt_ptr++) = 0x40 | ((length + 2) & 0xf); *(ssdt_ptr++) = (length + 2) >> 4; } *(ssdt_ptr++) = '_'; // Name *(ssdt_ptr++) = 'P'; *(ssdt_ptr++) = 'R'; *(ssdt_ptr++) = '_'; // build object for each processor for(i=0;i> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa; else *(ssdt_ptr++) = 'U'; *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa; *(ssdt_ptr++) = i; *(ssdt_ptr++) = 0x10; // Processor block address *(ssdt_ptr++) = 0xb0; *(ssdt_ptr++) = 0; *(ssdt_ptr++) = 0; *(ssdt_ptr++) = 6; // Processor block length } acpi_build_table_header((struct acpi_table_header *)ssdt, "SSDT", ssdt_ptr - ssdt, 1); return ssdt_ptr - ssdt; } /* base_addr must be a multiple of 4KB */ void acpi_bios_init(void) { struct rsdp_descriptor *rsdp; struct rsdt_descriptor_rev1 *rsdt; struct fadt_descriptor_rev1 *fadt; struct facs_descriptor_rev1 *facs; struct multiple_apic_table *madt; uint8_t *dsdt, *ssdt; #ifdef BX_QEMU struct acpi_20_hpet *hpet; uint32_t hpet_addr; #endif uint32_t base_addr, rsdt_addr, fadt_addr, addr, facs_addr, dsdt_addr, ssdt_addr; uint32_t acpi_tables_size, madt_addr, madt_size; int i; if (ram_size - ACPI_DATA_SIZE < 0x100000) { BX_INFO("Not enough memory for ACPI tables\n"); return; } /* reserve memory space for tables */ #ifdef BX_USE_EBDA_TABLES ebda_cur_addr = align(ebda_cur_addr, 16); rsdp = (void *)(ebda_cur_addr); ebda_cur_addr += sizeof(*rsdp); #else bios_table_cur_addr = align(bios_table_cur_addr, 16); rsdp = (void *)(bios_table_cur_addr); bios_table_cur_addr += sizeof(*rsdp); #endif addr = base_addr = ram_size - ACPI_DATA_SIZE; rsdt_addr = addr; rsdt = (void *)(addr); addr += sizeof(*rsdt); fadt_addr = addr; fadt = (void *)(addr); addr += sizeof(*fadt); /* XXX: FACS should be in RAM */ addr = (addr + 63) & ~63; /* 64 byte alignment for FACS */ facs_addr = addr; facs = (void *)(addr); addr += sizeof(*facs); dsdt_addr = addr; dsdt = (void *)(addr); addr += sizeof(AmlCode); ssdt_addr = addr; ssdt = (void *)(addr); addr += acpi_build_processor_ssdt(ssdt); addr = (addr + 7) & ~7; madt_addr = addr; madt_size = sizeof(*madt) + sizeof(struct madt_processor_apic) * smp_cpus + sizeof(struct madt_io_apic) + sizeof(struct madt_int_override); madt = (void *)(addr); addr += madt_size; #ifdef BX_QEMU addr = (addr + 7) & ~7; hpet_addr = addr; hpet = (void *)(addr); addr += sizeof(*hpet); #endif acpi_tables_size = addr - base_addr; BX_INFO("ACPI tables: RSDP addr=0x%08lx ACPI DATA addr=0x%08lx size=0x%x\n", (unsigned long)rsdp, (unsigned long)rsdt, acpi_tables_size); /* RSDP */ memset(rsdp, 0, sizeof(*rsdp)); memcpy(rsdp->signature, "RSD PTR ", 8); #ifdef BX_QEMU memcpy(rsdp->oem_id, "QEMU ", 6); #else memcpy(rsdp->oem_id, "BOCHS ", 6); #endif rsdp->rsdt_physical_address = cpu_to_le32(rsdt_addr); rsdp->checksum = acpi_checksum((void *)rsdp, 20); /* RSDT */ memset(rsdt, 0, sizeof(*rsdt)); rsdt->table_offset_entry[0] = cpu_to_le32(fadt_addr); rsdt->table_offset_entry[1] = cpu_to_le32(madt_addr); rsdt->table_offset_entry[2] = cpu_to_le32(ssdt_addr); #ifdef BX_QEMU rsdt->table_offset_entry[3] = cpu_to_le32(hpet_addr); #endif acpi_build_table_header((struct acpi_table_header *)rsdt, "RSDT", sizeof(*rsdt), 1); /* FADT */ memset(fadt, 0, sizeof(*fadt)); fadt->firmware_ctrl = cpu_to_le32(facs_addr); fadt->dsdt = cpu_to_le32(dsdt_addr); fadt->model = 1; fadt->reserved1 = 0; fadt->sci_int = cpu_to_le16(pm_sci_int); fadt->smi_cmd = cpu_to_le32(SMI_CMD_IO_ADDR); fadt->acpi_enable = 0xf1; fadt->acpi_disable = 0xf0; fadt->pm1a_evt_blk = cpu_to_le32(pm_io_base); fadt->pm1a_cnt_blk = cpu_to_le32(pm_io_base + 0x04); fadt->pm_tmr_blk = cpu_to_le32(pm_io_base + 0x08); fadt->pm1_evt_len = 4; fadt->pm1_cnt_len = 2; fadt->pm_tmr_len = 4; fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported /* WBINVD + PROC_C1 + PWR_BUTTON + SLP_BUTTON + FIX_RTC */ fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 4) | (1 << 5) | (1 << 6)); acpi_build_table_header((struct acpi_table_header *)fadt, "FACP", sizeof(*fadt), 1); /* FACS */ memset(facs, 0, sizeof(*facs)); memcpy(facs->signature, "FACS", 4); facs->length = cpu_to_le32(sizeof(*facs)); BX_INFO("Firmware waking vector %p\n", &facs->firmware_waking_vector); /* DSDT */ memcpy(dsdt, AmlCode, sizeof(AmlCode)); /* MADT */ { struct madt_processor_apic *apic; struct madt_io_apic *io_apic; struct madt_int_override *int_override; memset(madt, 0, madt_size); madt->local_apic_address = cpu_to_le32(0xfee00000); madt->flags = cpu_to_le32(1); apic = (void *)(madt + 1); for(i=0;itype = APIC_PROCESSOR; apic->length = sizeof(*apic); apic->processor_id = i; apic->local_apic_id = i; apic->flags = cpu_to_le32(1); apic++; } io_apic = (void *)apic; io_apic->type = APIC_IO; io_apic->length = sizeof(*io_apic); io_apic->io_apic_id = smp_cpus; io_apic->address = cpu_to_le32(0xfec00000); io_apic->interrupt = cpu_to_le32(0); io_apic++; int_override = (void *)io_apic; int_override->type = APIC_XRUPT_OVERRIDE; int_override->length = sizeof(*int_override); int_override->bus = cpu_to_le32(0); int_override->source = cpu_to_le32(0); int_override->gsi = cpu_to_le32(2); int_override->flags = cpu_to_le32(0); acpi_build_table_header((struct acpi_table_header *)madt, "APIC", madt_size, 1); } #ifdef BX_QEMU /* HPET */ memset(hpet, 0, sizeof(*hpet)); /* Note timer_block_id value must be kept in sync with value advertised by * emulated hpet */ hpet->timer_block_id = cpu_to_le32(0x8086a201); hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS); acpi_build_table_header((struct acpi_table_header *)hpet, "HPET", sizeof(*hpet), 1); #endif } /* SMBIOS entry point -- must be written to a 16-bit aligned address between 0xf0000 and 0xfffff. */ struct smbios_entry_point { char anchor_string[4]; uint8_t checksum; uint8_t length; uint8_t smbios_major_version; uint8_t smbios_minor_version; uint16_t max_structure_size; uint8_t entry_point_revision; uint8_t formatted_area[5]; char intermediate_anchor_string[5]; uint8_t intermediate_checksum; uint16_t structure_table_length; uint32_t structure_table_address; uint16_t number_of_structures; uint8_t smbios_bcd_revision; } __attribute__((__packed__)); /* This goes at the beginning of every SMBIOS structure. */ struct smbios_structure_header { uint8_t type; uint8_t length; uint16_t handle; } __attribute__((__packed__)); /* SMBIOS type 0 - BIOS Information */ struct smbios_type_0 { struct smbios_structure_header header; uint8_t vendor_str; uint8_t bios_version_str; uint16_t bios_starting_address_segment; uint8_t bios_release_date_str; uint8_t bios_rom_size; uint8_t bios_characteristics[8]; uint8_t bios_characteristics_extension_bytes[2]; uint8_t system_bios_major_release; uint8_t system_bios_minor_release; uint8_t embedded_controller_major_release; uint8_t embedded_controller_minor_release; } __attribute__((__packed__)); /* SMBIOS type 1 - System Information */ struct smbios_type_1 { struct smbios_structure_header header; uint8_t manufacturer_str; uint8_t product_name_str; uint8_t version_str; uint8_t serial_number_str; uint8_t uuid[16]; uint8_t wake_up_type; uint8_t sku_number_str; uint8_t family_str; } __attribute__((__packed__)); /* SMBIOS type 3 - System Enclosure (v2.3) */ struct smbios_type_3 { struct smbios_structure_header header; uint8_t manufacturer_str; uint8_t type; uint8_t version_str; uint8_t serial_number_str; uint8_t asset_tag_number_str; uint8_t boot_up_state; uint8_t power_supply_state; uint8_t thermal_state; uint8_t security_status; uint32_t oem_defined; uint8_t height; uint8_t number_of_power_cords; uint8_t contained_element_count; // contained elements follow } __attribute__((__packed__)); /* SMBIOS type 4 - Processor Information (v2.0) */ struct smbios_type_4 { struct smbios_structure_header header; uint8_t socket_designation_str; uint8_t processor_type; uint8_t processor_family; uint8_t processor_manufacturer_str; uint32_t processor_id[2]; uint8_t processor_version_str; uint8_t voltage; uint16_t external_clock; uint16_t max_speed; uint16_t current_speed; uint8_t status; uint8_t processor_upgrade; uint16_t l1_cache_handle; uint16_t l2_cache_handle; uint16_t l3_cache_handle; } __attribute__((__packed__)); /* SMBIOS type 16 - Physical Memory Array * Associated with one type 17 (Memory Device). */ struct smbios_type_16 { struct smbios_structure_header header; uint8_t location; uint8_t use; uint8_t error_correction; uint32_t maximum_capacity; uint16_t memory_error_information_handle; uint16_t number_of_memory_devices; } __attribute__((__packed__)); /* SMBIOS type 17 - Memory Device * Associated with one type 19 */ struct smbios_type_17 { struct smbios_structure_header header; uint16_t physical_memory_array_handle; uint16_t memory_error_information_handle; uint16_t total_width; uint16_t data_width; uint16_t size; uint8_t form_factor; uint8_t device_set; uint8_t device_locator_str; uint8_t bank_locator_str; uint8_t memory_type; uint16_t type_detail; } __attribute__((__packed__)); /* SMBIOS type 19 - Memory Array Mapped Address */ struct smbios_type_19 { struct smbios_structure_header header; uint32_t starting_address; uint32_t ending_address; uint16_t memory_array_handle; uint8_t partition_width; } __attribute__((__packed__)); /* SMBIOS type 20 - Memory Device Mapped Address */ struct smbios_type_20 { struct smbios_structure_header header; uint32_t starting_address; uint32_t ending_address; uint16_t memory_device_handle; uint16_t memory_array_mapped_address_handle; uint8_t partition_row_position; uint8_t interleave_position; uint8_t interleaved_data_depth; } __attribute__((__packed__)); /* SMBIOS type 32 - System Boot Information */ struct smbios_type_32 { struct smbios_structure_header header; uint8_t reserved[6]; uint8_t boot_status; } __attribute__((__packed__)); /* SMBIOS type 127 -- End-of-table */ struct smbios_type_127 { struct smbios_structure_header header; } __attribute__((__packed__)); static void smbios_entry_point_init(void *start, uint16_t max_structure_size, uint16_t structure_table_length, uint32_t structure_table_address, uint16_t number_of_structures) { uint8_t sum; int i; struct smbios_entry_point *ep = (struct smbios_entry_point *)start; memcpy(ep->anchor_string, "_SM_", 4); ep->length = 0x1f; ep->smbios_major_version = 2; ep->smbios_minor_version = 4; ep->max_structure_size = max_structure_size; ep->entry_point_revision = 0; memset(ep->formatted_area, 0, 5); memcpy(ep->intermediate_anchor_string, "_DMI_", 5); ep->structure_table_length = structure_table_length; ep->structure_table_address = structure_table_address; ep->number_of_structures = number_of_structures; ep->smbios_bcd_revision = 0x24; ep->checksum = 0; ep->intermediate_checksum = 0; sum = 0; for (i = 0; i < 0x10; i++) sum += ((int8_t *)start)[i]; ep->checksum = -sum; sum = 0; for (i = 0x10; i < ep->length; i++) sum += ((int8_t *)start)[i]; ep->intermediate_checksum = -sum; } /* Type 0 -- BIOS Information */ #define RELEASE_DATE_STR "01/01/2007" static void * smbios_type_0_init(void *start) { struct smbios_type_0 *p = (struct smbios_type_0 *)start; p->header.type = 0; p->header.length = sizeof(struct smbios_type_0); p->header.handle = 0; p->vendor_str = 1; p->bios_version_str = 2; p->bios_starting_address_segment = 0xe000; p->bios_release_date_str = 3; p->bios_rom_size = 1; /* 128 kB */ memset(p->bios_characteristics, 0, 8); p->bios_characteristics[0] |= 1 << 4; /* Bit 4 - ISA is supported */ #if BX_PCIBIOS p->bios_characteristics[0] |= 1 << 7; /* Bit 7 - PCI is supported */ #endif #if BX_APM p->bios_characteristics[1] |= 1 << 2; /* Bit 10 - APM is supported */ #endif p->bios_characteristics[1] |= 1 << 3; /* Bit 11 - BIOS is Upgradeable (Flash) */ p->bios_characteristics[1] |= 1 << 4; /* Bit 12 - BIOS shadowing is allowed */ #if BX_ELTORITO_BOOT && BX_USE_ATADRV p->bios_characteristics[1] |= 1 << 7; /* Bit 15 - Boot from CD is supported */ p->bios_characteristics[2] |= 1 << 0; /* Bit 16 - Selectable Boot is supported */ #endif #if BX_USE_ATADRV p->bios_characteristics[2] |= 1 << 3; /* Bit 19 - EDD (Enhanced Disk Drive) Specification is supported */ #endif #if BX_SUPPORT_FLOPPY p->bios_characteristics[2] |= 1 << 6; /* Bit 22 - Int 13h - 5.25" / 360 KB Floppy Services are supported */ p->bios_characteristics[2] |= 1 << 7; /* Bit 23 - Int 13h - 5.25" / 1.2 MB Floppy Services are supported */ p->bios_characteristics[3] |= 1 << 0; /* Bit 24 - Int 13h - 3.5" / 720 KB Floppy Services are supported */ p->bios_characteristics[3] |= 1 << 1; /* Bit 25 - Int 13h - 3.5" / 2.88 MB Floppy Services are supported */ #endif p->bios_characteristics[3] |= 1 << 3; /* Bit 27 - Int 9h, 8042 Keyboard services are supported */ p->bios_characteristics[3] |= 1 << 4; /* Bit 28 - Int 14h, Serial Services are supported */ p->bios_characteristics[3] |= 1 << 5; /* Bit 29 - Int 17h, Printer Services are supported */ p->bios_characteristics_extension_bytes[0] = 1; /* Bit 0 - ACPI supported */ p->bios_characteristics_extension_bytes[1] = 0; p->system_bios_major_release = 1; p->system_bios_minor_release = 0; p->embedded_controller_major_release = 0xff; p->embedded_controller_minor_release = 0xff; start += sizeof(struct smbios_type_0); memcpy((char *)start, BX_APPVENDOR, sizeof(BX_APPVENDOR)); start += sizeof(BX_APPVENDOR); memcpy((char *)start, BX_APPNAME, sizeof(BX_APPNAME)); start += sizeof(BX_APPNAME); memcpy((char *)start, RELEASE_DATE_STR, sizeof(RELEASE_DATE_STR)); start += sizeof(RELEASE_DATE_STR); *((uint8_t *)start) = 0; return start+1; } /* Type 1 -- System Information */ static void * smbios_type_1_init(void *start) { struct smbios_type_1 *p = (struct smbios_type_1 *)start; p->header.type = 1; p->header.length = sizeof(struct smbios_type_1); p->header.handle = 0x100; p->manufacturer_str = 0; p->product_name_str = 0; p->version_str = 0; p->serial_number_str = 0; memcpy(p->uuid, bios_uuid, 16); p->wake_up_type = 0x06; /* power switch */ p->sku_number_str = 0; p->family_str = 0; start += sizeof(struct smbios_type_1); *((uint16_t *)start) = 0; return start+2; } /* Type 3 -- System Enclosure */ static void * smbios_type_3_init(void *start) { struct smbios_type_3 *p = (struct smbios_type_3 *)start; p->header.type = 3; p->header.length = sizeof(struct smbios_type_3); p->header.handle = 0x300; p->manufacturer_str = 0; p->type = 0x01; /* other */ p->version_str = 0; p->serial_number_str = 0; p->asset_tag_number_str = 0; p->boot_up_state = 0x03; /* safe */ p->power_supply_state = 0x03; /* safe */ p->thermal_state = 0x03; /* safe */ p->security_status = 0x02; /* unknown */ p->oem_defined = 0; p->height = 0; p->number_of_power_cords = 0; p->contained_element_count = 0; start += sizeof(struct smbios_type_3); *((uint16_t *)start) = 0; return start+2; } /* Type 4 -- Processor Information */ static void * smbios_type_4_init(void *start, unsigned int cpu_number) { struct smbios_type_4 *p = (struct smbios_type_4 *)start; p->header.type = 4; p->header.length = sizeof(struct smbios_type_4); p->header.handle = 0x400 + cpu_number; p->socket_designation_str = 1; p->processor_type = 0x03; /* CPU */ p->processor_family = 0x01; /* other */ p->processor_manufacturer_str = 0; p->processor_id[0] = cpuid_signature; p->processor_id[1] = cpuid_features; p->processor_version_str = 0; p->voltage = 0; p->external_clock = 0; p->max_speed = 0; /* unknown */ p->current_speed = 0; /* unknown */ p->status = 0x41; /* socket populated, CPU enabled */ p->processor_upgrade = 0x01; /* other */ p->l1_cache_handle = 0xffff; /* cache information structure not provided */ p->l2_cache_handle = 0xffff; p->l3_cache_handle = 0xffff; start += sizeof(struct smbios_type_4); memcpy((char *)start, "CPU " "\0" "" "\0" "", 7); ((char *)start)[4] = cpu_number + '0'; return start+7; } /* Type 16 -- Physical Memory Array */ static void * smbios_type_16_init(void *start, uint32_t memsize, int nr_mem_devs) { struct smbios_type_16 *p = (struct smbios_type_16*)start; p->header.type = 16; p->header.length = sizeof(struct smbios_type_16); p->header.handle = 0x1000; p->location = 0x03; /* system board or motherboard */ p->use = 0x03; /* system memory */ p->error_correction = 0x01; /* other */ p->maximum_capacity = memsize * 1024; p->memory_error_information_handle = 0xfffe; /* none provided */ p->number_of_memory_devices = nr_mem_devs; start += sizeof(struct smbios_type_16); *((uint16_t *)start) = 0; return start + 2; } /* Type 17 -- Memory Device */ static void * smbios_type_17_init(void *start, uint32_t memory_size_mb, int instance) { struct smbios_type_17 *p = (struct smbios_type_17 *)start; p->header.type = 17; p->header.length = sizeof(struct smbios_type_17); p->header.handle = 0x1100 + instance; p->physical_memory_array_handle = 0x1000; p->memory_error_information_handle = 0xfffe; /* none provided */ p->total_width = 64; p->data_width = 64; /* TODO: should assert in case something is wrong ASSERT((memory_size_mb & ~0x7fff) == 0); */ p->size = memory_size_mb; p->form_factor = 0x09; /* DIMM */ p->device_set = 0; p->device_locator_str = 1; p->bank_locator_str = 0; p->memory_type = 0x07; /* RAM */ p->type_detail = 0; start += sizeof(struct smbios_type_17); snprintf(start, 8, "DIMM %d", instance); start += strlen(start) + 1; *((uint8_t *)start) = 0; return start+1; } /* Type 19 -- Memory Array Mapped Address */ static void * smbios_type_19_init(void *start, uint32_t memory_size_mb, int instance) { struct smbios_type_19 *p = (struct smbios_type_19 *)start; p->header.type = 19; p->header.length = sizeof(struct smbios_type_19); p->header.handle = 0x1300 + instance; p->starting_address = instance << 24; p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; p->memory_array_handle = 0x1000; p->partition_width = 1; start += sizeof(struct smbios_type_19); *((uint16_t *)start) = 0; return start + 2; } /* Type 20 -- Memory Device Mapped Address */ static void * smbios_type_20_init(void *start, uint32_t memory_size_mb, int instance) { struct smbios_type_20 *p = (struct smbios_type_20 *)start; p->header.type = 20; p->header.length = sizeof(struct smbios_type_20); p->header.handle = 0x1400 + instance; p->starting_address = instance << 24; p->ending_address = p->starting_address + (memory_size_mb << 10) - 1; p->memory_device_handle = 0x1100 + instance; p->memory_array_mapped_address_handle = 0x1300 + instance; p->partition_row_position = 1; p->interleave_position = 0; p->interleaved_data_depth = 0; start += sizeof(struct smbios_type_20); *((uint16_t *)start) = 0; return start+2; } /* Type 32 -- System Boot Information */ static void * smbios_type_32_init(void *start) { struct smbios_type_32 *p = (struct smbios_type_32 *)start; p->header.type = 32; p->header.length = sizeof(struct smbios_type_32); p->header.handle = 0x2000; memset(p->reserved, 0, 6); p->boot_status = 0; /* no errors detected */ start += sizeof(struct smbios_type_32); *((uint16_t *)start) = 0; return start+2; } /* Type 127 -- End of Table */ static void * smbios_type_127_init(void *start) { struct smbios_type_127 *p = (struct smbios_type_127 *)start; p->header.type = 127; p->header.length = sizeof(struct smbios_type_127); p->header.handle = 0x7f00; start += sizeof(struct smbios_type_127); *((uint16_t *)start) = 0; return start + 2; } void smbios_init(void) { unsigned cpu_num, nr_structs = 0, max_struct_size = 0; char *start, *p, *q; int memsize = (ram_end == ram_size) ? ram_size / (1024 * 1024) : (ram_end - (1ull << 32) + ram_size) / (1024 * 1024); int i, nr_mem_devs; bios_table_cur_addr = align(bios_table_cur_addr, 16); start = (void *)(bios_table_cur_addr); p = (char *)start + sizeof(struct smbios_entry_point); #define add_struct(fn) do { \ q = (fn); \ nr_structs++; \ if ((q - p) > max_struct_size) \ max_struct_size = q - p; \ p = q; \ } while (0) add_struct(smbios_type_0_init(p)); add_struct(smbios_type_1_init(p)); add_struct(smbios_type_3_init(p)); for (cpu_num = 1; cpu_num <= smp_cpus; cpu_num++) add_struct(smbios_type_4_init(p, cpu_num)); /* Each 'memory device' covers up to 16GB of address space. */ nr_mem_devs = (memsize + 0x3fff) >> 14; add_struct(smbios_type_16_init(p, memsize, nr_mem_devs)); for ( i = 0; i < nr_mem_devs; i++ ) { uint32_t dev_memsize = ((i == (nr_mem_devs - 1)) ? (((memsize - 1) & 0x3fff) + 1) : 0x4000); add_struct(smbios_type_17_init(p, dev_memsize, i)); add_struct(smbios_type_19_init(p, dev_memsize, i)); add_struct(smbios_type_20_init(p, dev_memsize, i)); } add_struct(smbios_type_32_init(p)); add_struct(smbios_type_127_init(p)); #undef add_struct smbios_entry_point_init( start, max_struct_size, (p - (char *)start) - sizeof(struct smbios_entry_point), (uint32_t)(start + sizeof(struct smbios_entry_point)), nr_structs); bios_table_cur_addr += (p - (char *)start); BX_INFO("SMBIOS table addr=0x%08lx\n", (unsigned long)start); } static uint32_t find_resume_vector(void) { unsigned long addr, start, end; #ifdef BX_USE_EBDA_TABLES start = align(ebda_cur_addr, 16); end = 0xa000 << 4; #else if (bios_table_cur_addr == 0) return 0; start = align(bios_table_cur_addr, 16); end = bios_table_end_addr; #endif for (addr = start; addr < end; addr += 16) { if (!memcmp((void*)addr, "RSD PTR ", 8)) { struct rsdp_descriptor *rsdp = (void*)addr; struct rsdt_descriptor_rev1 *rsdt = (void*)rsdp->rsdt_physical_address; struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[0]; struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl; return facs->firmware_waking_vector; } } return 0; } static void find_440fx(PCIDevice *d) { uint16_t vendor_id, device_id; vendor_id = pci_config_readw(d, PCI_VENDOR_ID); device_id = pci_config_readw(d, PCI_DEVICE_ID); if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82441) i440_pcidev = *d; } static void reinit_piix4_pm(PCIDevice *d) { uint16_t vendor_id, device_id; vendor_id = pci_config_readw(d, PCI_VENDOR_ID); device_id = pci_config_readw(d, PCI_DEVICE_ID); if (vendor_id == PCI_VENDOR_ID_INTEL && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) piix4_pm_enable(d); } void rombios32_init(uint32_t *s3_resume_vector, uint8_t *shutdown_flag) { BX_INFO("Starting rombios32\n"); BX_INFO("Shutdown flag %x\n", *shutdown_flag); #ifdef BX_QEMU qemu_cfg_port = qemu_cfg_port_probe(); #endif ram_probe(); cpu_probe(); setup_mtrr(); smp_probe(); find_bios_table_area(); if (*shutdown_flag == 0xfe) { /* redirect bios read access to RAM */ pci_for_each_device(find_440fx); bios_lock_shadow_ram(); /* bios is already copied */ *s3_resume_vector = find_resume_vector(); if (!*s3_resume_vector) { BX_INFO("This is S3 resume but wakeup vector is NULL\n"); } else { BX_INFO("S3 resume vector %p\n", *s3_resume_vector); pci_for_each_device(reinit_piix4_pm); } return; } pci_bios_init(); #ifndef BX_USE_EBDA_TABLES if (bios_table_cur_addr != 0 && i440_pcidev.bus != -1) { mptable_init(); uuid_probe(); smbios_init(); if (acpi_enabled) acpi_bios_init(); bios_lock_shadow_ram(); } #else mptable_init(); if (bios_table_cur_addr != 0 && i440_pcidev.bus != -1) { uuid_probe(); smbios_init(); } if (acpi_enabled) acpi_bios_init(); BX_INFO("ebda_cur_addr: 0x%08lx\n", ebda_cur_addr); if (ebda_cur_addr > 0xA0000) BX_PANIC("ebda_cur_addr overflow!\n"); #endif BX_INFO("bios_table_cur_addr: 0x%08lx\n", bios_table_cur_addr); if (bios_table_cur_addr > bios_table_end_addr) BX_PANIC("bios_table_end_addr overflow!\n"); } bochs-2.6/bios/rombios32start.S0000644000175000017500000000513712020641455016317 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: rombios32start.S 10213 2011-02-25 15:32:08Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // 32 bit Bochs BIOS init code // Copyright (C) 2006 Fabrice Bellard // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "rombios.h" .globl _start .globl smp_ap_boot_code_start .globl smp_ap_boot_code_end .global smm_relocation_start .global smm_relocation_end .global smm_code_start .global smm_code_end _start: /* clear bss section */ xor %eax, %eax mov $__bss_start, %edi mov $__bss_end, %ecx sub %edi, %ecx rep stosb /* copy data section */ mov $_end, %esi mov $__data_start, %edi mov $__data_end, %ecx sub %edi, %ecx rep movsb jmp rombios32_init .code16 smp_ap_boot_code_start: cli xor %ax, %ax mov %ax, %ds mov $SMP_MSR_ADDR, %ebx 11: mov 0(%ebx), %ecx test %ecx, %ecx jz 12f mov 4(%ebx), %eax mov 8(%ebx), %edx wrmsr add $12, %ebx jmp 11b 12: lock incw smp_cpus 1: hlt jmp 1b smp_ap_boot_code_end: /* code to relocate SMBASE to 0xa0000 */ smm_relocation_start: mov $0x38000 + 0x7efc, %ebx addr32 mov (%ebx), %al /* revision ID to see if x86_64 or x86 */ cmp $0x64, %al je 1f mov $0x38000 + 0x7ef8, %ebx jmp 2f 1: mov $0x38000 + 0x7f00, %ebx 2: movl $0xa0000, %eax addr32 movl %eax, (%ebx) /* indicate to the BIOS that the SMM code was executed */ mov $0x00, %al movw $0xb3, %dx outb %al, %dx rsm smm_relocation_end: /* minimal SMM code to enable or disable ACPI */ smm_code_start: movw $0xb2, %dx inb %dx, %al cmp $0xf0, %al jne 1f /* ACPI disable */ mov $PM_IO_BASE + 0x04, %dx /* PMCNTRL */ inw %dx, %ax andw $~1, %ax outw %ax, %dx jmp 2f 1: cmp $0xf1, %al jne 2f /* ACPI enable */ mov $PM_IO_BASE + 0x04, %dx /* PMCNTRL */ inw %dx, %ax orw $1, %ax outw %ax, %dx 2: rsm smm_code_end: bochs-2.6/bios/notes0000644000175000017500000000343712020641455014352 0ustar guillemguillem#################### # Read Disk Sector # #################### System programming: ------------------- (Int 13h, ah=2) in 1f7 until BSY cleared out 1f2, AL # number of sectors out 1f3, cl (bits 0-5) # starting sector number out 1f4, ch # cylinder number bits 0..7, 0 based out 1f5, cl (bits 6,7) & dh (bits 6,7) # cyl, bits 8..9, 10..11 out 1f6, dh (bits 0..3) --> bits 0..3 # head number dh (bits 4..5) --> ??? # head number dl (bit 0) --> bit 4 # drive number out 1f7, 0x20 # read sectors command normal Drive response: --------------- * drive sets the busy bit in Status Reg to 1 * if command parameters are wrong: > drive sets the aborted-command bit in the Error register and error bit in the Status register to 1. > Drive also sets the busy bit in the Status register to 0. > Drive then generates an interrupt to the system. * else: > drive executes an implied seek to desired track and reads sectors into sector buffer > when sector buffer is filled and the data is ready to be transferred, the drive sets the data-request bit to 1, sets the busy bit to 0, and generates an interrupt. > on a single-sector transfer, after the system has transferred the data, the drive sets the data-request bit and the busy bit to 0. > on a multiple-sector transfer, after the system has transferred the first sector of data, the drive sets the data-request bit to 0, and the busy bit to 1. When each subsequent sector is ready to be transferred, the drive sets the data-request bit to 1, the busy bit to 0, and generates an interrupt. When the system has tranferred the last sector, the drive sets the data-request bit and busy bit to 0. bochs-2.6/bios/usage.cc0000644000175000017500000000517712020641455014715 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: usage.cc 10209 2011-02-24 22:05:47Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include #include #include #include unsigned char bios[65536]; int main(int argc, char *argv[]) { int bios_file; FILE * org_file; unsigned org, last_org, offset; int retval; unsigned int to_read, index; double elements, ratio; if (argc !=3 ) { fprintf(stderr, "Usage: usage bios-file org-file\n"); exit(1); } bios_file = open(argv[1], O_RDONLY); org_file = fopen(argv[2], "r"); if ( (bios_file<0) | (org_file==NULL) ) { fprintf(stderr, "problems opening files.\n"); exit(1); } printf("files opened OK\n"); to_read = 65536; index = 0; while (to_read > 0) { retval = read(bios_file, &bios[index], to_read); if (retval <= 0) { fprintf(stderr, "problem reading bios file\n"); exit(1); } to_read -= retval; index += retval; } printf("bios file read in OK\n"); last_org = 0; while (1) { retval = fscanf(org_file, "0x%x\n", &org); if (retval <= 0) break; printf("%04x .. %04x ", last_org, org-1); for (offset=org-1; offset>last_org; offset--) { if (bios[offset] != 0) break; } if (offset > last_org) { elements = (1.0 + double(offset) - double(last_org)); } else { if (bios[last_org] == 0) elements = 0.0; else elements = 1.0; } ratio = elements / (double(org) - double(last_org)); ratio *= 100.0; printf("%6.2lf\n", ratio); last_org = org; } } bochs-2.6/bios/rombios32.ld0000644000175000017500000000105012020641455015424 0ustar guillemguillemOUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start); SECTIONS { . = 0x000e0000; .text : { *(.text) } .rodata : { *(.rodata*) } _end = . ; .data 0x700 : AT (_end) { __data_start = .; *(.data); __data_end = .;} .bss : { __bss_start = .; *(.bss) *(COMMON); __bss_end = .;} /DISCARD/ : { *(.stab) *(.stabstr) *(.comment) *(.eh_frame) *(.note) } } bochs-2.6/bios/Makefile.in0000644000175000017500000000627112020641455015343 0ustar guillemguillem# Copyright (C) 2001 MandrakeSoft S.A. # # MandrakeSoft S.A. # 43, rue d'Aboukir # 75002 Paris - France # http://www.linux-mandrake.com/ # http://www.mandrakesoft.com/ # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2 of the License, or (at your option) any later version. # # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Makefile for the BIOS component of bochs @SUFFIX_LINE@ srcdir = @srcdir@ VPATH = @srcdir@ SHELL = @SHELL@ @SET_MAKE@ CXX = @CXX@ CXXFLAGS = @CXXFLAGS@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ RANLIB = @RANLIB@ BCC = bcc GCC = gcc GCC32 = gcc -m32 -fno-stack-protector AS86 = as86 BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev LOCAL_CXXFLAGS = BUILDDATE = `date '+%m/%d/%y'` BIOS_BUILD_DATE = "-DBIOS_BUILD_DATE=\"$(BUILDDATE)\"" # # -------- end configurable options -------------------------- # .@CPP_SUFFIX@.o: $(CXX) -c $(BX_INCDIRS) $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@ bios: biossums BIOS-bochs-latest BIOS-bochs-legacy clean: @RMCOMMAND@ *.o *.a *.s _rombios*_.c rombios*.txt rombios*.sym @RMCOMMAND@ usage biossums rombios16.bin @RMCOMMAND@ rombios32.bin rombios32.out dist-clean: clean @RMCOMMAND@ Makefile bios-clean: @RMCOMMAND@ BIOS-bochs-* BIOS-bochs-legacy: rombios.c apmbios.S biossums rombios.h $(GCC32) $(BIOS_BUILD_DATE) -DLEGACY -E -P $< > _rombiosl_.c $(BCC) -o rombiosl.s -C-c -D__i86__ -0 -S _rombiosl_.c sed -e 's/^\.text//' -e 's/^\.data//' rombiosl.s > _rombiosl_.s $(AS86) _rombiosl_.s -b tmpl.bin -u- -w- -g -0 -j -O -l rombiosl.txt -perl ${srcdir}/makesym.perl < rombiosl.txt > rombiosl.sym mv tmpl.bin $@ ./biossums $@ @RMCOMMAND@ _rombiosl_.s rombios16.bin: rombios.c apmbios.S biossums rombios.h $(GCC32) $(BIOS_BUILD_DATE) -E -P $< > _rombios_.c $(BCC) -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s $(AS86) _rombios_.s -b tmp.bin -u- -w- -g -0 -j -O -l rombios.txt -perl ${srcdir}/makesym.perl < rombios.txt > rombios.sym mv tmp.bin rombios16.bin ./biossums rombios16.bin @RMCOMMAND@ _rombios_.s rombios32.bin: rombios32.out rombios.h objcopy -O binary $< $@ ./biossums -pad $@ rombios32.out: rombios32start.o rombios32.o rombios32.ld ld -o $@ -T $(srcdir)/rombios32.ld rombios32start.o rombios32.o rombios32.o: rombios32.c acpi-dsdt.hex rombios.h $(GCC32) -O2 -Wall -c -o $@ $< ifeq ("1", "0") acpi-dsdt.hex: acpi-dsdt.dsl cpp -P $< $<.i iasl -tc -p $@ $<.i rm $<.i sed -i -e's/^unsigned/const unsigned/' $@ endif rombios32start.o: rombios32start.S $(GCC32) -c -o $@ $< BIOS-bochs-latest: rombios16.bin rombios32.bin cat rombios32.bin rombios16.bin > $@ biossums: biossums.o bochs-2.6/bios/rombios.c0000644000175000017500000115557512020641455015131 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: rombios.c 11318 2012-08-06 17:59:54Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2002 MandrakeSoft S.A. // // MandrakeSoft S.A. // 43, rue d'Aboukir // 75002 Paris - France // http://www.linux-mandrake.com/ // http://www.mandrakesoft.com/ // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA // ROM BIOS for use with Bochs/Plex86/QEMU emulation environment // ROM BIOS compatibility entry points: // =================================== // $e05b ; POST Entry Point // $e2c3 ; NMI Handler Entry Point // $e3fe ; INT 13h Fixed Disk Services Entry Point // $e401 ; Fixed Disk Parameter Table // $e6f2 ; INT 19h Boot Load Service Entry Point // $e6f5 ; Configuration Data Table // $e729 ; Baud Rate Generator Table // $e739 ; INT 14h Serial Communications Service Entry Point // $e82e ; INT 16h Keyboard Service Entry Point // $e987 ; INT 09h Keyboard Service Entry Point // $ec59 ; INT 13h Diskette Service Entry Point // $ef57 ; INT 0Eh Diskette Hardware ISR Entry Point // $efc7 ; Diskette Controller Parameter Table // $efd2 ; INT 17h Printer Service Entry Point // $f045 ; INT 10 Functions 0-Fh Entry Point // $f065 ; INT 10h Video Support Service Entry Point // $f0a4 ; MDA/CGA Video Parameter Table (INT 1Dh) // $f841 ; INT 12h Memory Size Service Entry Point // $f84d ; INT 11h Equipment List Service Entry Point // $f859 ; INT 15h System Services Entry Point // $fa6e ; Character Font for 320x200 & 640x200 Graphics (lower 128 characters) // $fe6e ; INT 1Ah Time-of-day Service Entry Point // $fea5 ; INT 08h System Timer ISR Entry Point // $fef3 ; Initial Interrupt Vector Offsets Loaded by POST // $ff53 ; IRET Instruction for Dummy Interrupt Handler // $ff54 ; INT 05h Print Screen Service Entry Point // $fff0 ; Power-up Entry Point // $fff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY // $fffe ; System Model ID // NOTES for ATA/ATAPI driver (cbbochs@free.fr) // Features // - supports up to 4 ATA interfaces // - device/geometry detection // - 16bits/32bits device access // - pchs/lba access // - datain/dataout/packet command support // // NOTES for El-Torito Boot (cbbochs@free.fr) // - CD-ROM booting is only available if ATA/ATAPI Driver is available // - Current code is only able to boot mono-session cds // - Current code can not boot and emulate a hard-disk // the bios will panic otherwise // - Current code also use memory in EBDA segment. // - I used cmos byte 0x3D to store extended information on boot-device // - Code has to be modified modified to handle multiple cdrom drives // - Here are the cdrom boot failure codes: // 1 : no atapi device found // 2 : no atapi cdrom found // 3 : can not read cd - BRVD // 4 : cd is not eltorito (BRVD) // 5 : cd is not eltorito (ISO TAG) // 6 : cd is not eltorito (ELTORITO TAG) // 7 : can not read cd - boot catalog // 8 : boot catalog : bad header // 9 : boot catalog : bad platform // 10 : boot catalog : bad signature // 11 : boot catalog : bootable flag not set // 12 : can not read cd - boot image // // ATA driver // - EBDA segment. // I used memory starting at 0x121 in the segment // - the translation policy is defined in cmos regs 0x39 & 0x3a // // TODO : // // int74 // - needs to be reworked. Uses direct [bp] offsets. (?) // // int13: // - f04 (verify sectors) isn't complete (?) // - f02/03/04 should set current cyl,etc in BDA (?) // - rewrite int13_relocated & clean up int13 entry code // // NOTES: // - NMI access (bit7 of addr written to 70h) // // ATA driver // - should handle the "don't detect" bit (cmos regs 0x3b & 0x3c) // - could send the multiple-sector read/write commands // // El-Torito // - Emulate a Hard-disk (currently only diskette can be emulated) see "FIXME ElTorito Harddisk" // - Implement remaining int13_cdemu functions (as defined by El-Torito specs) // - cdrom drive is hardcoded to ide 0 device 1 in several places. see "FIXME ElTorito Hardcoded" // - int13 Fix DL when emulating a cd. In that case DL is decremented before calling real int13. // This is ok. But DL should be reincremented afterwards. // - Fix all "FIXME ElTorito Various" // - should be able to boot any cdrom instead of the first one // // BCC Bug: find a generic way to handle the bug of #asm after an "if" (fixed in 0.16.7) #include "rombios.h" // Sanity Checks #if BX_CPU<3 # error Only 386+ cpu supported #endif #if BX_USE_ATADRV && !BX_USE_EBDA # error ATA/ATAPI Driver can only be used if EBDA is available #endif #if BX_ELTORITO_BOOT && !BX_USE_ATADRV # error El-Torito Boot can only be use if ATA/ATAPI Driver is available #endif // define this if you want to make PCIBIOS working on a specific bridge only // undef enables PCIBIOS when at least one PCI device is found // i440FX is emulated by Bochs and QEMU #define PCI_FIXED_HOST_BRIDGE 0x12378086 ;; i440FX PCI bridge // #20 is dec 20 // #$20 is hex 20 = 32 // #0x20 is hex 20 = 32 // LDA #$20 // JSR $E820 // LDD .i,S // JSR $C682 // mov al, #$20 // all hex literals should be prefixed with '0x' // grep "#[0-9a-fA-F][0-9a-fA-F]" rombios.c // no mov SEG-REG, #value, must mov register into seg-reg // grep -i "mov[ ]*.s" rombios.c // This is for compiling with gcc2 and gcc3 #define ASM_START #asm #define ASM_END #endasm // Added this to use data_segment based data #define read_byte_DS(offset) *((Bit8u *)(offset)) #define read_word_DS(offset) *((Bit16u *)(offset)) #define read_dword_DS(offset) *((Bit32u *)(offset)) #define write_byte_DS(offset,data) *((Bit8u *)(offset)) = (data) #define write_word_DS(offset,data) *((Bit16u *)(offset)) = (data) #define write_dword_DS(offset,data) *((Bit32u *)(offset)) = (data) ASM_START .rom .org 0x0000 use16 386 MACRO HALT ;; the HALT macro is called with the line number of the HALT call. ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex ;; to print a BX_PANIC message. This will normally halt the simulation ;; with a message such as "BIOS panic at rombios.c, line 4091". ;; However, users can choose to make panics non-fatal and continue. #if BX_VIRTUAL_PORTS mov dx,#PANIC_PORT mov ax,#?1 out dx,ax #else mov dx,#0x80 mov ax,#?1 out dx,al #endif MEND MACRO JMP_AP db 0xea dw ?2 dw ?1 MEND MACRO SET_INT_VECTOR mov ax, ?3 mov ?1*4, ax mov ax, ?2 mov ?1*4+2, ax MEND ASM_END typedef unsigned char Bit8u; typedef unsigned short Bit16u; typedef unsigned short bx_bool; typedef unsigned long Bit32u; void memsetb(value,offset,seg,count); void memcpyb(doffset,dseg,soffset,sseg,count); void memcpyd(doffset,dseg,soffset,sseg,count); // memset of count bytes void memsetb(value,offset,seg,count) Bit16u value; Bit16u offset; Bit16u seg; Bit16u count; { ASM_START push bp mov bp, sp push ax push cx push es push di mov cx, 10[bp] ; count jcxz memsetb_end les di, 6[bp] ; segment & offset mov al, 4[bp] ; value cld rep stosb memsetb_end: pop di pop es pop cx pop ax pop bp ASM_END } // memcpy of count bytes void memcpyb(doffset,dseg,soffset,sseg,count) Bit16u doffset; Bit16u dseg; Bit16u soffset; Bit16u sseg; Bit16u count; { ASM_START push bp mov bp, sp push cx push es push di push ds push si mov cx, 12[bp] ; count jcxz memcpyb_end les di, 4[bp] ; dsegment & doffset lds si, 8[bp] ; ssegment & soffset cld rep movsb memcpyb_end: pop si pop ds pop di pop es pop cx pop bp ASM_END } // memcpy of count dword void memcpyd(doffset,dseg,soffset,sseg,count) Bit16u doffset; Bit16u dseg; Bit16u soffset; Bit16u sseg; Bit16u count; { ASM_START push bp mov bp, sp push cx push es push di push ds push si mov cx, 12[bp] ; count jcxz memcpyd_end les di, 4[bp] ; dsegment & doffset lds si, 8[bp] ; ssegment & soffset cld rep movsd memcpyd_end: pop si pop ds pop di pop es pop cx pop bp ASM_END } // read_dword and write_dword functions static Bit32u read_dword(); static void write_dword(); static Bit32u read_dword_SS(); //static void write_dword_SS(); Bit32u read_dword(offset, seg) Bit16u seg; Bit16u offset; { ASM_START push bp mov bp, sp push bx push ds lds bx, 4[bp] ; segment & offset mov ax, [bx] mov dx, 2[bx] ;; ax = return value (word) ;; dx = return value (word) pop ds pop bx pop bp ASM_END } void write_dword(data, offset, seg) Bit32u data; Bit16u offset; Bit16u seg; { ASM_START push bp mov bp, sp push eax push bx push ds lds bx, 8[bp] ; segment & offset mov eax, 4[bp] ; data dword mov [bx], eax ; write data dword pop ds pop bx pop eax pop bp ASM_END } Bit32u read_dword_SS(offset) Bit16u offset; { ASM_START push bp mov bp, sp mov bp, 4[bp] ; offset mov ax, [bp] mov dx, 2[bp] ;; ax = return value (word) ;; dx = return value (word) pop bp ASM_END } // Not currently used #if 0 void write_dword_SS(data, offset) Bit32u data; Bit16u offset; { ASM_START push bp mov bp, sp push eax mov eax, 4[bp] ; data word mov bp, 8[bp] ; offset mov [bp], eax ; write data dword pop eax pop bp ASM_END } #endif // Bit32u (unsigned long) and long helper functions ASM_START ;; and function landl: landul: SEG SS and ax,[di] SEG SS and bx,2[di] ret ;; add function laddl: laddul: SEG SS add ax,[di] SEG SS adc bx,2[di] ret ;; cmp function lcmpl: lcmpul: and eax, #0x0000FFFF shl ebx, #16 or eax, ebx shr ebx, #16 SEG SS cmp eax, dword ptr [di] ret ;; sub function lsubl: lsubul: SEG SS sub ax,[di] SEG SS sbb bx,2[di] ret ;; mul function lmull: lmulul: and eax, #0x0000FFFF shl ebx, #16 or eax, ebx SEG SS mul eax, dword ptr [di] mov ebx, eax shr ebx, #16 ret ;; dec function ldecl: ldecul: SEG SS dec dword ptr [bx] ret ;; or function lorl: lorul: SEG SS or ax,[di] SEG SS or bx,2[di] ret ;; inc function lincl: lincul: SEG SS inc dword ptr [bx] ret ;; tst function ltstl: ltstul: and eax, #0x0000FFFF shl ebx, #16 or eax, ebx shr ebx, #16 test eax, eax ret ;; sr function lsrul: mov cx,di jcxz lsr_exit and eax, #0x0000FFFF shl ebx, #16 or eax, ebx lsr_loop: shr eax, #1 loop lsr_loop mov ebx, eax shr ebx, #16 lsr_exit: ret ;; sl function lsll: lslul: mov cx,di jcxz lsl_exit and eax, #0x0000FFFF shl ebx, #16 or eax, ebx lsl_loop: shl eax, #1 loop lsl_loop mov ebx, eax shr ebx, #16 lsl_exit: ret idiv_: cwd idiv bx ret idiv_u: xor dx,dx div bx ret ldivul: and eax, #0x0000FFFF shl ebx, #16 or eax, ebx xor edx, edx SEG SS mov bx, 2[di] shl ebx, #16 SEG SS mov bx, [di] div ebx mov ebx, eax shr ebx, #16 ret ASM_END // for access to RAM area which is used by interrupt vectors // and BIOS Data Area typedef struct { unsigned char filler1[0x400]; unsigned char filler2[0x6c]; Bit16u ticks_low; Bit16u ticks_high; Bit8u midnight_flag; } bios_data_t; #define BiosData ((bios_data_t *) 0) #if BX_USE_ATADRV typedef struct { Bit16u heads; // # heads Bit16u cylinders; // # cylinders Bit16u spt; // # sectors / track } chs_t; // DPTE definition typedef struct { Bit16u iobase1; Bit16u iobase2; Bit8u prefix; Bit8u unused; Bit8u irq; Bit8u blkcount; Bit8u dma; Bit8u pio; Bit16u options; Bit16u reserved; Bit8u revision; Bit8u checksum; } dpte_t; typedef struct { Bit8u iface; // ISA or PCI Bit16u iobase1; // IO Base 1 Bit16u iobase2; // IO Base 2 Bit8u irq; // IRQ } ata_channel_t; typedef struct { Bit8u type; // Detected type of ata (ata/atapi/none/unknown) Bit8u device; // Detected type of attached devices (hd/cd/none) Bit8u removable; // Removable device flag Bit8u lock; // Locks for removable devices Bit8u mode; // transfer mode : PIO 16/32 bits - IRQ - ISADMA - PCIDMA Bit16u blksize; // block size Bit8u translation; // type of translation chs_t lchs; // Logical CHS chs_t pchs; // Physical CHS Bit32u sectors_low; // Total sectors count Bit32u sectors_high; } ata_device_t; typedef struct { // ATA channels info ata_channel_t channels[BX_MAX_ATA_INTERFACES]; // ATA devices info ata_device_t devices[BX_MAX_ATA_DEVICES]; // // map between (bios hd id - 0x80) and ata channels Bit8u hdcount, hdidmap[BX_MAX_ATA_DEVICES]; // map between (bios cd id - 0xE0) and ata channels Bit8u cdcount, cdidmap[BX_MAX_ATA_DEVICES]; // Buffer for DPTE table dpte_t dpte; // Count of transferred sectors and bytes Bit16u trsfsectors; Bit32u trsfbytes; } ata_t; #if BX_ELTORITO_BOOT // ElTorito Device Emulation data typedef struct { Bit8u active; Bit8u media; Bit8u emulated_drive; Bit8u controller_index; Bit16u device_spec; Bit32u ilba; Bit16u buffer_segment; Bit16u load_segment; Bit16u sector_count; // Virtual device chs_t vdevice; } cdemu_t; #endif // BX_ELTORITO_BOOT // for access to EBDA area // The EBDA structure should conform to // http://www.frontiernet.net/~fys/rombios.htm document // I made the ata and cdemu structs begin at 0x121 in the EBDA seg // EBDA must be at most 768 bytes; it lives at EBDA_SEG, and the boot // device tables are at IPL_SEG typedef struct { Bit8u size; unsigned char filler0[0x21]; Bit16u mouse_driver_offset; Bit16u mouse_driver_seg; Bit8u mouse_flag1; Bit8u mouse_flag2; Bit8u mouse_data[0x08]; unsigned char filler1[0x0D]; // FDPT - Can be split into data members if needed unsigned char fdpt0[0x10]; unsigned char fdpt1[0x10]; unsigned char filler2[0xC4]; // ATA Driver data ata_t ata; #if BX_ELTORITO_BOOT // El Torito Emulation data cdemu_t cdemu; #endif // BX_ELTORITO_BOOT } ebda_data_t; #define EbdaData ((ebda_data_t *) 0) // for access to the int13ext structure typedef struct { Bit8u size; Bit8u reserved; Bit16u count; Bit16u offset; Bit16u segment; Bit32u lba1; Bit32u lba2; } int13ext_t; #define Int13Ext ((int13ext_t *) 0) // Disk Physical Table definition typedef struct { Bit16u size; Bit16u infos; Bit32u cylinders; Bit32u heads; Bit32u spt; Bit32u sector_count1; Bit32u sector_count2; Bit16u blksize; Bit16u dpte_offset; Bit16u dpte_segment; union { struct { Bit16u key; Bit8u dpi_length; Bit8u reserved1; Bit16u reserved2; Bit8u host_bus[4]; Bit8u iface_type[8]; Bit8u iface_path[8]; Bit8u device_path[8]; Bit8u reserved3; Bit8u checksum; } phoenix; struct { Bit16u key; Bit8u dpi_length; Bit8u reserved1; Bit16u reserved2; Bit8u host_bus[4]; Bit8u iface_type[8]; Bit8u iface_path[8]; Bit8u device_path[16]; Bit8u reserved3; Bit8u checksum; } t13; } dpi; } dpt_t; #define Int13DPT ((dpt_t *) 0) #endif // BX_USE_ATADRV typedef struct { union { struct { Bit16u di, si, bp, sp; Bit16u bx, dx, cx, ax; } r16; struct { Bit16u filler[4]; Bit8u bl, bh, dl, dh, cl, ch, al, ah; } r8; } u; } pusha_regs_t; typedef struct { union { struct { Bit32u edi, esi, ebp, esp; Bit32u ebx, edx, ecx, eax; } r32; struct { Bit16u di, filler1, si, filler2, bp, filler3, sp, filler4; Bit16u bx, filler5, dx, filler6, cx, filler7, ax, filler8; } r16; struct { Bit32u filler[4]; Bit8u bl, bh; Bit16u filler1; Bit8u dl, dh; Bit16u filler2; Bit8u cl, ch; Bit16u filler3; Bit8u al, ah; Bit16u filler4; } r8; } u; } pushad_regs_t; typedef struct { union { struct { Bit16u flags; } r16; struct { Bit8u flagsl; Bit8u flagsh; } r8; } u; } flags_t; #define SetCF(x) x.u.r8.flagsl |= 0x01 #define SetZF(x) x.u.r8.flagsl |= 0x40 #define ClearCF(x) x.u.r8.flagsl &= 0xfe #define ClearZF(x) x.u.r8.flagsl &= 0xbf #define GetCF(x) (x.u.r8.flagsl & 0x01) typedef struct { Bit16u ip; Bit16u cs; flags_t flags; } iret_addr_t; typedef struct { Bit16u type; Bit16u flags; Bit32u vector; Bit32u description; Bit32u reserved; } ipl_entry_t; static Bit8u inb(); static Bit8u inb_cmos(); static void outb(); static void outb_cmos(); static Bit16u inw(); static void outw(); static void init_rtc(); static bx_bool rtc_updating(); static Bit8u read_byte(); static Bit16u read_word(); static void write_byte(); static void write_word(); static Bit8u read_byte_SS(); static Bit16u read_word_SS(); static void write_byte_SS(); static void write_word_SS(); static void bios_printf(); static Bit8u inhibit_mouse_int_and_events(); static void enable_mouse_int_and_events(); static Bit8u send_to_mouse_ctrl(); static Bit8u get_mouse_data(); static void set_kbd_command_byte(); static void int09_function(); static void int13_harddisk(); static void int13_cdrom(); static void int13_cdemu(); static void int13_eltorito(); static void int13_diskette_function(); static void int14_function(); static void int15_function(); static void int16_function(); static void int17_function(); static void int19_function(); static void int1a_function(); static void int70_function(); static void int74_function(); static Bit16u get_CS(); static Bit16u get_SS(); static Bit16u set_DS(); static unsigned int enqueue_key(); static unsigned int dequeue_key(); static void get_hd_geometry(); static void set_diskette_ret_status(); static void set_diskette_current_cyl(); static void determine_floppy_media(); static bx_bool floppy_drive_exists(); static bx_bool floppy_drive_recal(); static bx_bool floppy_media_known(); static bx_bool floppy_media_sense(); static bx_bool set_enable_a20(); static void debugger_on(); static void debugger_off(); static void keyboard_init(); static void keyboard_panic(); static void shutdown_status_panic(); static void nmi_handler_msg(); static void delay_ticks(); static void delay_ticks_and_check_for_keystroke(); static void interactive_bootkey(); static void print_bios_banner(); static void print_boot_device(); static void print_boot_failure(); static void print_cdromboot_failure(); # if BX_USE_ATADRV // ATA / ATAPI driver void ata_init(); void ata_detect(); void ata_reset(); Bit16u ata_cmd_non_data(); Bit16u ata_cmd_data_io(); Bit16u ata_cmd_packet(); Bit16u atapi_get_sense(); Bit16u atapi_is_ready(); Bit16u atapi_is_cdrom(); #endif // BX_USE_ATADRV #if BX_ELTORITO_BOOT void cdemu_init(); Bit8u cdemu_isactive(); Bit8u cdemu_emulated_drive(); Bit16u cdrom_boot(); #endif // BX_ELTORITO_BOOT static char bios_cvs_version_string[] = "$Revision: 11318 $ $Date: 2012-08-06 19:59:54 +0200 (Mo, 06. Aug 2012) $"; #define BIOS_COPYRIGHT_STRING "(c) 2002-2010 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team." #if DEBUG_ATA # define BX_DEBUG_ATA(a...) BX_DEBUG(a) #else # define BX_DEBUG_ATA(a...) #endif #if DEBUG_INT13_HD # define BX_DEBUG_INT13_HD(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT13_HD(a...) #endif #if DEBUG_INT13_CD # define BX_DEBUG_INT13_CD(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT13_CD(a...) #endif #if DEBUG_INT13_ET # define BX_DEBUG_INT13_ET(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT13_ET(a...) #endif #if DEBUG_INT13_FL # define BX_DEBUG_INT13_FL(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT13_FL(a...) #endif #if DEBUG_INT15 # define BX_DEBUG_INT15(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT15(a...) #endif #if DEBUG_INT16 # define BX_DEBUG_INT16(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT16(a...) #endif #if DEBUG_INT1A # define BX_DEBUG_INT1A(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT1A(a...) #endif #if DEBUG_INT74 # define BX_DEBUG_INT74(a...) BX_DEBUG(a) #else # define BX_DEBUG_INT74(a...) #endif #define SET_AL(val8) AX = ((AX & 0xff00) | (val8)) #define SET_BL(val8) BX = ((BX & 0xff00) | (val8)) #define SET_CL(val8) CX = ((CX & 0xff00) | (val8)) #define SET_DL(val8) DX = ((DX & 0xff00) | (val8)) #define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8)) #define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8)) #define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8)) #define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8)) #define GET_AL() ( AX & 0x00ff ) #define GET_BL() ( BX & 0x00ff ) #define GET_CL() ( CX & 0x00ff ) #define GET_DL() ( DX & 0x00ff ) #define GET_AH() ( AX >> 8 ) #define GET_BH() ( BX >> 8 ) #define GET_CH() ( CX >> 8 ) #define GET_DH() ( DX >> 8 ) #define GET_ELDL() ( ELDX & 0x00ff ) #define GET_ELDH() ( ELDX >> 8 ) #define SET_CF() FLAGS |= 0x0001 #define CLEAR_CF() FLAGS &= 0xfffe #define GET_CF() (FLAGS & 0x0001) #define SET_ZF() FLAGS |= 0x0040 #define CLEAR_ZF() FLAGS &= 0xffbf #define GET_ZF() (FLAGS & 0x0040) #define UNSUPPORTED_FUNCTION 0x86 #define none 0 #define MAX_SCAN_CODE 0x58 static struct { Bit16u normal; Bit16u shift; Bit16u control; Bit16u alt; Bit8u lock_flags; } scan_to_scanascii[MAX_SCAN_CODE + 1] = { { none, none, none, none, none }, { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */ { 0x0231, 0x0221, none, 0x7800, none }, /* 1! */ { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */ { 0x0433, 0x0423, none, 0x7a00, none }, /* 3# */ { 0x0534, 0x0524, none, 0x7b00, none }, /* 4$ */ { 0x0635, 0x0625, none, 0x7c00, none }, /* 5% */ { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */ { 0x0837, 0x0826, none, 0x7e00, none }, /* 7& */ { 0x0938, 0x092a, none, 0x7f00, none }, /* 8* */ { 0x0a39, 0x0a28, none, 0x8000, none }, /* 9( */ { 0x0b30, 0x0b29, none, 0x8100, none }, /* 0) */ { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */ { 0x0d3d, 0x0d2b, none, 0x8300, none }, /* =+ */ { 0x0e08, 0x0e08, 0x0e7f, none, none }, /* backspace */ { 0x0f09, 0x0f00, none, none, none }, /* tab */ { 0x1071, 0x1051, 0x1011, 0x1000, 0x40 }, /* Q */ { 0x1177, 0x1157, 0x1117, 0x1100, 0x40 }, /* W */ { 0x1265, 0x1245, 0x1205, 0x1200, 0x40 }, /* E */ { 0x1372, 0x1352, 0x1312, 0x1300, 0x40 }, /* R */ { 0x1474, 0x1454, 0x1414, 0x1400, 0x40 }, /* T */ { 0x1579, 0x1559, 0x1519, 0x1500, 0x40 }, /* Y */ { 0x1675, 0x1655, 0x1615, 0x1600, 0x40 }, /* U */ { 0x1769, 0x1749, 0x1709, 0x1700, 0x40 }, /* I */ { 0x186f, 0x184f, 0x180f, 0x1800, 0x40 }, /* O */ { 0x1970, 0x1950, 0x1910, 0x1900, 0x40 }, /* P */ { 0x1a5b, 0x1a7b, 0x1a1b, none, none }, /* [{ */ { 0x1b5d, 0x1b7d, 0x1b1d, none, none }, /* ]} */ { 0x1c0d, 0x1c0d, 0x1c0a, none, none }, /* Enter */ { none, none, none, none, none }, /* L Ctrl */ { 0x1e61, 0x1e41, 0x1e01, 0x1e00, 0x40 }, /* A */ { 0x1f73, 0x1f53, 0x1f13, 0x1f00, 0x40 }, /* S */ { 0x2064, 0x2044, 0x2004, 0x2000, 0x40 }, /* D */ { 0x2166, 0x2146, 0x2106, 0x2100, 0x40 }, /* F */ { 0x2267, 0x2247, 0x2207, 0x2200, 0x40 }, /* G */ { 0x2368, 0x2348, 0x2308, 0x2300, 0x40 }, /* H */ { 0x246a, 0x244a, 0x240a, 0x2400, 0x40 }, /* J */ { 0x256b, 0x254b, 0x250b, 0x2500, 0x40 }, /* K */ { 0x266c, 0x264c, 0x260c, 0x2600, 0x40 }, /* L */ { 0x273b, 0x273a, none, none, none }, /* ;: */ { 0x2827, 0x2822, none, none, none }, /* '" */ { 0x2960, 0x297e, none, none, none }, /* `~ */ { none, none, none, none, none }, /* L shift */ { 0x2b5c, 0x2b7c, 0x2b1c, none, none }, /* |\ */ { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, 0x40 }, /* Z */ { 0x2d78, 0x2d58, 0x2d18, 0x2d00, 0x40 }, /* X */ { 0x2e63, 0x2e43, 0x2e03, 0x2e00, 0x40 }, /* C */ { 0x2f76, 0x2f56, 0x2f16, 0x2f00, 0x40 }, /* V */ { 0x3062, 0x3042, 0x3002, 0x3000, 0x40 }, /* B */ { 0x316e, 0x314e, 0x310e, 0x3100, 0x40 }, /* N */ { 0x326d, 0x324d, 0x320d, 0x3200, 0x40 }, /* M */ { 0x332c, 0x333c, none, none, none }, /* ,< */ { 0x342e, 0x343e, none, none, none }, /* .> */ { 0x352f, 0x353f, none, none, none }, /* /? */ { none, none, none, none, none }, /* R Shift */ { 0x372a, 0x372a, none, none, none }, /* * */ { none, none, none, none, none }, /* L Alt */ { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */ { none, none, none, none, none }, /* caps lock */ { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */ { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */ { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */ { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */ { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */ { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */ { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */ { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */ { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */ { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */ { none, none, none, none, none }, /* Num Lock */ { none, none, none, none, none }, /* Scroll Lock */ { 0x4700, 0x4737, 0x7700, none, 0x20 }, /* 7 Home */ { 0x4800, 0x4838, none, none, 0x20 }, /* 8 UP */ { 0x4900, 0x4939, 0x8400, none, 0x20 }, /* 9 PgUp */ { 0x4a2d, 0x4a2d, none, none, none }, /* - */ { 0x4b00, 0x4b34, 0x7300, none, 0x20 }, /* 4 Left */ { 0x4c00, 0x4c35, none, none, 0x20 }, /* 5 */ { 0x4d00, 0x4d36, 0x7400, none, 0x20 }, /* 6 Right */ { 0x4e2b, 0x4e2b, none, none, none }, /* + */ { 0x4f00, 0x4f31, 0x7500, none, 0x20 }, /* 1 End */ { 0x5000, 0x5032, none, none, 0x20 }, /* 2 Down */ { 0x5100, 0x5133, 0x7600, none, 0x20 }, /* 3 PgDn */ { 0x5200, 0x5230, none, none, 0x20 }, /* 0 Ins */ { 0x5300, 0x532e, none, none, 0x20 }, /* Del */ { none, none, none, none, none }, { none, none, none, none, none }, { 0x565c, 0x567c, none, none, none }, /* \| */ { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */ { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */ }; Bit8u inb(port) Bit16u port; { ASM_START push bp mov bp, sp push dx mov dx, 4[bp] in al, dx pop dx pop bp ASM_END } #if BX_USE_ATADRV Bit16u inw(port) Bit16u port; { ASM_START push bp mov bp, sp push dx mov dx, 4[bp] in ax, dx pop dx pop bp ASM_END } #endif void outb(port, val) Bit16u port; Bit8u val; { ASM_START push bp mov bp, sp push ax push dx mov dx, 4[bp] mov al, 6[bp] out dx, al pop dx pop ax pop bp ASM_END } #if BX_USE_ATADRV void outw(port, val) Bit16u port; Bit16u val; { ASM_START push bp mov bp, sp push ax push dx mov dx, 4[bp] mov ax, 6[bp] out dx, ax pop dx pop ax pop bp ASM_END } #endif void outb_cmos(cmos_reg, val) Bit8u cmos_reg; Bit8u val; { ASM_START push bp mov bp, sp mov al, 4[bp] ;; cmos_reg out PORT_CMOS_INDEX, al mov al, 6[bp] ;; val out PORT_CMOS_DATA, al pop bp ASM_END } Bit8u inb_cmos(cmos_reg) Bit8u cmos_reg; { ASM_START push bp mov bp, sp mov al, 4[bp] ;; cmos_reg out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA pop bp ASM_END } void init_rtc() { outb_cmos(0x0a, 0x26); outb_cmos(0x0b, 0x02); inb_cmos(0x0c); inb_cmos(0x0d); } bx_bool rtc_updating() { // This function checks to see if the update-in-progress bit // is set in CMOS Status Register A. If not, it returns 0. // If it is set, it tries to wait until there is a transition // to 0, and will return 0 if such a transition occurs. A 1 // is returned only after timing out. The maximum period // that this bit should be set is constrained to 244useconds. // The count I use below guarantees coverage or more than // this time, with any reasonable IPS setting. Bit16u count; count = 25000; while (--count != 0) { if ( (inb_cmos(0x0a) & 0x80) == 0 ) return(0); } return(1); // update-in-progress never transitioned to 0 } Bit8u read_byte(offset, seg) Bit16u offset; Bit16u seg; { ASM_START push bp mov bp, sp push bx push ds lds bx, 4[bp] ; segment & offset mov al, [bx] ;; al = return value (byte) pop ds pop bx pop bp ASM_END } Bit16u read_word(offset, seg) Bit16u offset; Bit16u seg; { ASM_START push bp mov bp, sp push bx push ds lds bx, 4[bp] ; segment & offset mov ax, [bx] ;; ax = return value (word) pop ds pop bx pop bp ASM_END } void write_byte(data, offset, seg) Bit8u data; Bit16u offset; Bit16u seg; { ASM_START push bp mov bp, sp push ax push bx push ds lds bx, 6[bp] ; segment & offset mov al, 4[bp] ; data byte mov [bx], al ; write data byte pop ds pop bx pop ax pop bp ASM_END } void write_word(data, offset, seg) Bit16u data; Bit16u offset; Bit16u seg; { ASM_START push bp mov bp, sp push ax push bx push ds lds bx, 6[bp] ; segment & offset mov ax, 4[bp] ; data word mov [bx], ax ; write data word pop ds pop bx pop ax pop bp ASM_END } Bit8u read_byte_SS(offset) Bit16u offset; { ASM_START push bp mov bp, sp mov bp, 4[bp] ; offset mov al, [bp] ;; al = return value (byte) pop bp ASM_END } Bit16u read_word_SS(offset) Bit16u offset; { ASM_START push bp mov bp, sp mov bp, 4[bp] ; offset mov ax, [bp] ;; ax = return value (word) pop bp ASM_END } void write_byte_SS(data, offset) Bit8u data; Bit16u offset; { ASM_START push bp mov bp, sp push ax mov al, 4[bp] ; data byte mov bp, 6[bp] ; offset mov [bp], al ; write data byte pop ax pop bp ASM_END } void write_word_SS(data, offset) Bit16u data; Bit16u offset; { ASM_START push bp mov bp, sp push ax mov ax, 4[bp] ; data word mov bp, 6[bp] ; offset mov [bp], ax ; write data word pop ax pop bp ASM_END } Bit16u get_CS() { ASM_START mov ax, cs ASM_END } Bit16u get_SS() { ASM_START mov ax, ss ASM_END } // Set data segment base.returns old data segment base. Bit16u set_DS(seg) Bit16u seg; { ASM_START push bp mov bp, sp push ds mov ds, 4[bp] ;; seg pop ax pop bp ASM_END } #if BX_DEBUG_SERIAL /* serial debug port*/ #define BX_DEBUG_PORT 0x03f8 /* data */ #define UART_RBR 0x00 #define UART_THR 0x00 /* control */ #define UART_IER 0x01 #define UART_IIR 0x02 #define UART_FCR 0x02 #define UART_LCR 0x03 #define UART_MCR 0x04 #define UART_DLL 0x00 #define UART_DLM 0x01 /* status */ #define UART_LSR 0x05 #define UART_MSR 0x06 #define UART_SCR 0x07 int uart_can_tx_byte(base_port) Bit16u base_port; { return inb(base_port + UART_LSR) & 0x20; } void uart_wait_to_tx_byte(base_port) Bit16u base_port; { while (!uart_can_tx_byte(base_port)); } void uart_wait_until_sent(base_port) Bit16u base_port; { while (!(inb(base_port + UART_LSR) & 0x40)); } void uart_tx_byte(base_port, data) Bit16u base_port; Bit8u data; { uart_wait_to_tx_byte(base_port); outb(base_port + UART_THR, data); uart_wait_until_sent(base_port); } #endif void wrch(c) Bit8u c; { ASM_START push bp mov bp, sp push bx mov ah, #0x0e mov al, 4[bp] xor bx,bx int #0x10 pop bx pop bp ASM_END } void send(action, c) Bit16u action; Bit8u c; { #if BX_DEBUG_SERIAL if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r'); uart_tx_byte(BX_DEBUG_PORT, c); #endif #if BX_VIRTUAL_PORTS if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c); if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c); #endif if (action & BIOS_PRINTF_SCREEN) { if (c == '\n') wrch('\r'); wrch(c); } } void put_uint(action, val, width, neg) Bit16u action; unsigned short val; short width; bx_bool neg; { unsigned short nval = val / 10; if (nval) put_uint(action, nval, width - 1, neg); else { while (--width > 0) send(action, ' '); if (neg) send(action, '-'); } send(action, val - (nval * 10) + '0'); } void put_luint(action, val, width, neg) Bit16u action; unsigned long val; short width; bx_bool neg; { unsigned long nval = val / 10; if (nval) put_luint(action, nval, width - 1, neg); else { while (--width > 0) send(action, ' '); if (neg) send(action, '-'); } send(action, val - (nval * 10) + '0'); } void put_str(action, segment, offset) Bit16u action; Bit16u segment; Bit16u offset; { Bit8u c; while (c = read_byte(offset, segment)) { send(action, c); offset++; } } void delay_ticks(ticks) Bit16u ticks; { long ticks_to_wait, delta; Bit32u prev_ticks, t; /* * The 0:046c wraps around at 'midnight' according to a 18.2Hz clock. * We also have to be careful about interrupt storms. */ ASM_START pushf push ds push #0x00 pop ds sti ASM_END ticks_to_wait = ticks; prev_ticks = read_dword_DS(0x46c); do { ASM_START hlt ASM_END t = read_dword_DS(0x46c); if (t > prev_ticks) { delta = t - prev_ticks; /* The temp var is required or bcc screws up. */ ticks_to_wait -= delta; } else if (t < prev_ticks) { ticks_to_wait -= t; /* wrapped */ } prev_ticks = t; } while (ticks_to_wait > 0); ASM_START cli pop ds popf ASM_END } Bit8u check_for_keystroke() { ASM_START mov ax, #0x100 int #0x16 jz no_key mov al, #1 jmp done no_key: xor al, al done: ASM_END } Bit8u get_keystroke() { ASM_START mov ax, #0x0 int #0x16 xchg ah, al ASM_END } void delay_ticks_and_check_for_keystroke(ticks, count) Bit16u ticks, count; { Bit16u i; for (i = 1; i <= count; i++) { delay_ticks(ticks); if (check_for_keystroke()) break; } } //-------------------------------------------------------------------------- // bios_printf() // A compact variable argument printf function. // // Supports %[format_width][length]format // where format can be x,X,u,d,s,S,c // and the optional length modifier is l (ell) //-------------------------------------------------------------------------- void bios_printf(action, s) Bit16u action; Bit8u *s; { Bit8u c, format_char; bx_bool in_format; short i; Bit16u *arg_ptr; Bit16u arg, nibble, hibyte, shift_count, format_width; Bit16u old_ds = set_DS(get_CS()); arg_ptr = &s; in_format = 0; format_width = 0; if ((action & BIOS_PRINTF_DEBHALT) == BIOS_PRINTF_DEBHALT) { #if BX_VIRTUAL_PORTS outb(PANIC_PORT2, 0x00); #endif bios_printf (BIOS_PRINTF_SCREEN, "FATAL: "); } while (c = read_byte_DS(s)) { if ( c == '%' ) { in_format = 1; format_width = 0; } else if (in_format) { if ( (c>='0') && (c<='9') ) { format_width = (format_width * 10) + (c - '0'); } else { arg_ptr++; // increment to next arg arg = read_word_SS(arg_ptr); if ((c & 0xdf) == 'X') { if (format_width == 0) format_width = 4; for (i=format_width-1; i>=0; i--) { nibble = (arg >> (4 * i)) & 0x000f; send (action, (nibble<=9)? (nibble+'0') : (nibble+c-33)); } } else if (c == 'u') { put_uint(action, arg, format_width, 0); } else if (c == 'l') { s++; c = read_byte_DS(s); /* is it ld,lx,lu? */ arg_ptr++; /* increment to next arg */ hibyte = read_word_SS(arg_ptr); if (c == 'd') { if (hibyte & 0x8000) put_luint(action, 0L-(((Bit32u) hibyte << 16) | arg), format_width-1, 1); else put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); } else if (c == 'u') { put_luint(action, ((Bit32u) hibyte << 16) | arg, format_width, 0); } else if ((c & 0xdf) == 'X') { if (format_width == 0) format_width = 8; for (i=format_width-1; i>=0; i--) { nibble = ((((Bit32u) hibyte <<16) | arg) >> (4 * i)) & 0x000f; send (action, (nibble<=9)? (nibble+'0') : (nibble+c-33)); } } } else if (c == 'd') { if (arg & 0x8000) put_uint(action, -arg, format_width - 1, 1); else put_uint(action, arg, format_width, 0); } else if (c == 's') { put_str(action, get_CS(), arg); } else if (c == 'S') { hibyte = arg; arg_ptr++; arg = read_word_SS(arg_ptr); put_str(action, hibyte, arg); } else if (c == 'c') { send(action, arg); } else BX_PANIC("bios_printf: unknown format\n"); in_format = 0; } } else { send(action, c); } s ++; } if (action & BIOS_PRINTF_HALT) { // freeze in a busy loop. ASM_START cli halt2_loop: hlt jmp halt2_loop ASM_END } set_DS(old_ds); } //-------------------------------------------------------------------------- // keyboard_init //-------------------------------------------------------------------------- // this file is based on LinuxBIOS implementation of keyboard.c // could convert to #asm to gain space void keyboard_init() { Bit16u max; /* ------------------- Flush buffers ------------------------*/ /* Wait until buffer is empty */ max=0xffff; while ( (inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x00); /* flush incoming keys */ max=0x2000; while (--max > 0) { outb(PORT_DIAG, 0x00); if (inb(PORT_PS2_STATUS) & 0x01) { inb(PORT_PS2_DATA); max = 0x2000; } } // Due to timer issues, and if the IPS setting is > 15000000, // the incoming keys might not be flushed here. That will // cause a panic a few lines below. See sourceforge bug report : // [ 642031 ] FATAL: Keyboard RESET error:993 /* ------------------- controller side ----------------------*/ /* send cmd = 0xAA, self test 8042 */ outb(PORT_PS2_STATUS, 0xaa); /* Wait until buffer is empty */ max=0xffff; while ( (inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x00); if (max==0x0) keyboard_panic(00); /* Wait for data */ max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x01); if (max==0x0) keyboard_panic(01); /* read self-test result, 0x55 should be returned from 0x60 */ if ((inb(PORT_PS2_DATA) != 0x55)){ keyboard_panic(991); } /* send cmd = 0xAB, keyboard interface test */ outb(PORT_PS2_STATUS,0xab); /* Wait until buffer is empty */ max=0xffff; while ((inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x10); if (max==0x0) keyboard_panic(10); /* Wait for data */ max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x11); if (max==0x0) keyboard_panic(11); /* read keyboard interface test result, */ /* 0x00 should be returned form 0x60 */ if ((inb(PORT_PS2_DATA) != 0x00)) { keyboard_panic(992); } /* Enable Keyboard clock */ outb(PORT_PS2_STATUS,0xae); outb(PORT_PS2_STATUS,0xa8); /* ------------------- keyboard side ------------------------*/ /* reset keyboard and self test (keyboard side) */ outb(PORT_PS2_DATA, 0xff); /* Wait until buffer is empty */ max=0xffff; while ((inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x20); if (max==0x0) keyboard_panic(20); /* Wait for data */ max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x21); if (max==0x0) keyboard_panic(21); /* keyboard should return ACK */ if ((inb(PORT_PS2_DATA) != 0xfa)) { keyboard_panic(993); } /* Wait for data */ max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x31); if (max==0x0) keyboard_panic(31); if ((inb(PORT_PS2_DATA) != 0xaa)) { keyboard_panic(994); } /* Disable keyboard */ outb(PORT_PS2_DATA, 0xf5); /* Wait until buffer is empty */ max=0xffff; while ((inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x40); if (max==0x0) keyboard_panic(40); /* Wait for data */ max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x41); if (max==0x0) keyboard_panic(41); /* keyboard should return ACK */ if ((inb(PORT_PS2_DATA) != 0xfa)) { keyboard_panic(995); } /* Write Keyboard Mode */ outb(PORT_PS2_STATUS, 0x60); /* Wait until buffer is empty */ max=0xffff; while ((inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x50); if (max==0x0) keyboard_panic(50); /* send cmd: scan code convert, disable mouse, enable IRQ 1 */ outb(PORT_PS2_DATA, 0x61); /* Wait until buffer is empty */ max=0xffff; while ((inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x60); if (max==0x0) keyboard_panic(60); /* Enable keyboard */ outb(PORT_PS2_DATA, 0xf4); /* Wait until buffer is empty */ max=0xffff; while ((inb(PORT_PS2_STATUS) & 0x02) && (--max>0)) outb(PORT_DIAG, 0x70); if (max==0x0) keyboard_panic(70); /* Wait for data */ max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x71); if (max==0x0) keyboard_panic(70); /* keyboard should return ACK */ if ((inb(PORT_PS2_DATA) != 0xfa)) { keyboard_panic(996); } outb(PORT_DIAG, 0x77); } //-------------------------------------------------------------------------- // keyboard_panic //-------------------------------------------------------------------------- void keyboard_panic(status) Bit16u status; { // If you're getting a 993 keyboard panic here, // please see the comment in keyboard_init BX_PANIC("Keyboard error:%u\n",status); } //-------------------------------------------------------------------------- // shutdown_status_panic // called when the shutdown status is not implemented, displays the status //-------------------------------------------------------------------------- void shutdown_status_panic(status) Bit16u status; { BX_PANIC("Unimplemented shutdown status: %02x\n",(Bit8u)status); } void s3_resume_panic() { BX_PANIC("Returned from s3_resume.\n"); } //-------------------------------------------------------------------------- // print_bios_banner // displays a the bios version //-------------------------------------------------------------------------- void print_bios_banner() { printf(BX_APPNAME" BIOS - build: %s\n%s\nOptions: ", BIOS_BUILD_DATE, bios_cvs_version_string); printf( #if BX_APM "apmbios " #endif #if BX_PCIBIOS "pcibios " #endif #if BX_PNPBIOS "pnpbios " #endif #if BX_ELTORITO_BOOT "eltorito " #endif #if BX_ROMBIOS32 "rombios32 " #endif "\n\n"); } //-------------------------------------------------------------------------- // BIOS Boot Specification 1.0.1 compatibility // // Very basic support for the BIOS Boot Specification, which allows expansion // ROMs to register themselves as boot devices, instead of just stealing the // INT 19h boot vector. // // This is a hack: to do it properly requires a proper PnP BIOS and we aren't // one; we just lie to the option ROMs to make them behave correctly. // We also don't support letting option ROMs register as bootable disk // drives (BCVs), only as bootable devices (BEVs). // // http://www.phoenix.com/en/Customer+Services/White+Papers-Specs/pc+industry+specifications.htm //-------------------------------------------------------------------------- static char drivetypes[][10]={"", "Floppy","Hard Disk","CD-Rom", "Network"}; static void init_boot_vectors() { ipl_entry_t e; Bit16u count = 0; Bit16u ss = get_SS(); ASM_START push ds ASM_END set_DS(IPL_SEG); /* Clear out the IPL table. */ memsetb(0, IPL_TABLE_OFFSET, IPL_SEG, IPL_SIZE); /* User selected device not set */ write_word_DS(IPL_BOOTFIRST_OFFSET, 0xFFFF); /* Floppy drive */ e.type = IPL_TYPE_FLOPPY; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; memcpyb(IPL_TABLE_OFFSET + count * sizeof (e), IPL_SEG, &e, ss, sizeof (e)); count++; /* First HDD */ e.type = IPL_TYPE_HARDDISK; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; memcpyb(IPL_TABLE_OFFSET + count * sizeof (e), IPL_SEG, &e, ss, sizeof (e)); count++; #if BX_ELTORITO_BOOT /* CDROM */ e.type = IPL_TYPE_CDROM; e.flags = 0; e.vector = 0; e.description = 0; e.reserved = 0; memcpyb(IPL_TABLE_OFFSET + count * sizeof (e), IPL_SEG, &e, ss, sizeof (e)); count++; #endif /* Remember how many devices we have */ write_word_DS(IPL_COUNT_OFFSET, count); /* Not tried booting anything yet */ write_word_DS(IPL_SEQUENCE_OFFSET, 0xffff); ASM_START pop ds ASM_END } static Bit8u get_boot_vector(i, e) Bit16u i; ipl_entry_t *e; { Bit16u count; Bit16u ss = get_SS(); /* Get the count of boot devices, and refuse to overrun the array */ count = read_word(IPL_COUNT_OFFSET, IPL_SEG); if (i >= count) return 0; /* OK to read this device */ memcpyb(e, ss, IPL_TABLE_OFFSET + i * sizeof (*e), IPL_SEG, sizeof (*e)); return 1; } #if BX_ELTORITO_BOOT void interactive_bootkey() { ipl_entry_t e; Bit16u count; char description[33]; Bit8u scan_code; Bit8u i; Bit16u ss = get_SS(); Bit16u valid_choice = 0; while (check_for_keystroke()) get_keystroke(); printf("Press F12 for boot menu.\n\n"); delay_ticks_and_check_for_keystroke(11, 5); /* ~3 seconds */ if (check_for_keystroke()) { scan_code = get_keystroke(); if (scan_code == 0x86) /* F12 */ { while (check_for_keystroke()) get_keystroke(); printf("Select boot device:\n\n"); count = read_word(IPL_COUNT_OFFSET, IPL_SEG); for (i = 0; i < count; i++) { memcpyb(&e, ss, IPL_TABLE_OFFSET + i * sizeof (e), IPL_SEG, sizeof (e)); printf("%d. ", i+1); switch(e.type) { case IPL_TYPE_FLOPPY: case IPL_TYPE_HARDDISK: case IPL_TYPE_CDROM: printf("%s\n", drivetypes[e.type]); break; case IPL_TYPE_BEV: printf("%s", drivetypes[4]); if (e.description != 0) { memcpyb(&description, ss, (Bit16u)(e.description & 0xffff), (Bit16u)(e.description >> 16), 32); description[32] = 0; printf(" [%S]", ss, description); } printf("\n"); break; } } count++; while (!valid_choice) { scan_code = get_keystroke(); if (scan_code == 0x01 || scan_code == 0x58) /* ESC or F12 */ { valid_choice = 1; } else if (scan_code <= count) { valid_choice = 1; scan_code -= 1; /* Set user selected device */ write_word(scan_code, IPL_BOOTFIRST_OFFSET, IPL_SEG); } } printf("\n"); } } } #endif // BX_ELTORITO_BOOT //-------------------------------------------------------------------------- // print_boot_device // displays the boot device //-------------------------------------------------------------------------- void print_boot_device(e) ipl_entry_t *e; { Bit16u type; char description[33]; Bit16u ss = get_SS(); type = e->type; /* NIC appears as type 0x80 */ if (type == IPL_TYPE_BEV) type = 0x4; if (type == 0 || type > 0x4) BX_PANIC("Bad drive type\n"); printf("Booting from %s", drivetypes[type]); /* print product string if BEV */ if (type == 4 && e->description != 0) { /* first 32 bytes are significant */ memcpyb(&description, ss, (Bit16u)(e->description & 0xffff), (Bit16u)(e->description >> 16), 32); /* terminate string */ description[32] = 0; printf(" [%S]", ss, description); } printf("...\n"); } //-------------------------------------------------------------------------- // print_boot_failure // displays the reason why boot failed //-------------------------------------------------------------------------- void print_boot_failure(type, reason) Bit16u type; Bit8u reason; { if (type == 0 || type > 0x3) BX_PANIC("Bad drive type\n"); printf("Boot failed"); if (type < 4) { /* Report the reason too */ if (reason==0) printf(": not a bootable disk"); else printf(": could not read the boot disk"); } printf("\n\n"); } //-------------------------------------------------------------------------- // print_cdromboot_failure // displays the reason why boot failed //-------------------------------------------------------------------------- void print_cdromboot_failure( code ) Bit16u code; { bios_printf(BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO, "CDROM boot failure code : %04x\n",code); return; } void nmi_handler_msg() { BX_PANIC("NMI Handler called\n"); } void int18_panic_msg() { BX_PANIC("INT18: BOOT FAILURE\n"); } void log_bios_start() { #if BX_DEBUG_SERIAL outb(BX_DEBUG_PORT+UART_LCR, 0x03); /* setup for serial logging: 8N1 */ #endif BX_INFO("%s\n", bios_cvs_version_string); } bx_bool set_enable_a20(val) bx_bool val; { Bit8u oldval; // Use PS2 System Control port A to set A20 enable // get current setting first oldval = inb(PORT_A20); // change A20 status if (val) outb(PORT_A20, oldval | 0x02); else outb(PORT_A20, oldval & 0xfd); return((oldval & 0x02) != 0); } void debugger_on() { outb(0xfedc, 0x01); } void debugger_off() { outb(0xfedc, 0x00); } int s3_resume() { Bit32u s3_wakeup_vector; Bit8u s3_resume_flag; // // DS has been set to 0 before call // s3_resume_flag = read_byte_DS(0x04b0); s3_wakeup_vector = read_dword_DS(0x04b2); BX_INFO("S3 resume called %x 0x%lx\n", s3_resume_flag, s3_wakeup_vector); if (s3_resume_flag != 0xFE || !s3_wakeup_vector) return 0; write_byte_DS(0x04b0, 0); /* setup wakeup vector */ write_word_DS(0x04b6, (s3_wakeup_vector & 0xF)); /* IP */ write_word_DS(0x04b8, (s3_wakeup_vector >> 4)); /* CS */ BX_INFO("S3 resume jump to %x:%x\n", (s3_wakeup_vector >> 4), (s3_wakeup_vector & 0xF)); ASM_START jmpf [0x04b6] ASM_END return 1; } #if BX_USE_ATADRV // --------------------------------------------------------------------------- // Start of ATA/ATAPI Driver // --------------------------------------------------------------------------- // Global defines -- ATA register and register bits. // command block & control block regs #define ATA_CB_DATA 0 // data reg in/out pio_base_addr1+0 #define ATA_CB_ERR 1 // error in pio_base_addr1+1 #define ATA_CB_FR 1 // feature reg out pio_base_addr1+1 #define ATA_CB_SC 2 // sector count in/out pio_base_addr1+2 #define ATA_CB_SN 3 // sector number in/out pio_base_addr1+3 #define ATA_CB_CL 4 // cylinder low in/out pio_base_addr1+4 #define ATA_CB_CH 5 // cylinder high in/out pio_base_addr1+5 #define ATA_CB_DH 6 // device head in/out pio_base_addr1+6 #define ATA_CB_STAT 7 // primary status in pio_base_addr1+7 #define ATA_CB_CMD 7 // command out pio_base_addr1+7 #define ATA_CB_ASTAT 6 // alternate status in pio_base_addr2+6 #define ATA_CB_DC 6 // device control out pio_base_addr2+6 #define ATA_CB_DA 7 // device address in pio_base_addr2+7 #define ATA_CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC #define ATA_CB_ER_BBK 0x80 // ATA bad block #define ATA_CB_ER_UNC 0x40 // ATA uncorrected error #define ATA_CB_ER_MC 0x20 // ATA media change #define ATA_CB_ER_IDNF 0x10 // ATA id not found #define ATA_CB_ER_MCR 0x08 // ATA media change request #define ATA_CB_ER_ABRT 0x04 // ATA command aborted #define ATA_CB_ER_NTK0 0x02 // ATA track 0 not found #define ATA_CB_ER_NDAM 0x01 // ATA address mark not found #define ATA_CB_ER_P_SNSKEY 0xf0 // ATAPI sense key (mask) #define ATA_CB_ER_P_MCR 0x08 // ATAPI Media Change Request #define ATA_CB_ER_P_ABRT 0x04 // ATAPI command abort #define ATA_CB_ER_P_EOM 0x02 // ATAPI End of Media #define ATA_CB_ER_P_ILI 0x01 // ATAPI Illegal Length Indication // ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC) #define ATA_CB_SC_P_TAG 0xf8 // ATAPI tag (mask) #define ATA_CB_SC_P_REL 0x04 // ATAPI release #define ATA_CB_SC_P_IO 0x02 // ATAPI I/O #define ATA_CB_SC_P_CD 0x01 // ATAPI C/D // bits 7-4 of the device/head (CB_DH) reg #define ATA_CB_DH_DEV0 0xa0 // select device 0 #define ATA_CB_DH_DEV1 0xb0 // select device 1 #define ATA_CB_DH_LBA 0x40 // use LBA // status reg (CB_STAT and CB_ASTAT) bits #define ATA_CB_STAT_BSY 0x80 // busy #define ATA_CB_STAT_RDY 0x40 // ready #define ATA_CB_STAT_DF 0x20 // device fault #define ATA_CB_STAT_WFT 0x20 // write fault (old name) #define ATA_CB_STAT_SKC 0x10 // seek complete #define ATA_CB_STAT_SERV 0x10 // service #define ATA_CB_STAT_DRQ 0x08 // data request #define ATA_CB_STAT_CORR 0x04 // corrected #define ATA_CB_STAT_IDX 0x02 // index #define ATA_CB_STAT_ERR 0x01 // error (ATA) #define ATA_CB_STAT_CHK 0x01 // check (ATAPI) // device control reg (CB_DC) bits #define ATA_CB_DC_HD15 0x08 // bit should always be set to one #define ATA_CB_DC_SRST 0x04 // soft reset #define ATA_CB_DC_NIEN 0x02 // disable interrupts // Most mandatory and optional ATA commands (from ATA-3), #define ATA_CMD_CFA_ERASE_SECTORS 0xC0 #define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03 #define ATA_CMD_CFA_TRANSLATE_SECTOR 0x87 #define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD #define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38 #define ATA_CMD_CHECK_POWER_MODE1 0xE5 #define ATA_CMD_CHECK_POWER_MODE2 0x98 #define ATA_CMD_DEVICE_RESET 0x08 #define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90 #define ATA_CMD_FLUSH_CACHE 0xE7 #define ATA_CMD_FORMAT_TRACK 0x50 #define ATA_CMD_IDENTIFY_DEVICE 0xEC #define ATA_CMD_IDENTIFY_DEVICE_PACKET 0xA1 #define ATA_CMD_IDENTIFY_PACKET_DEVICE 0xA1 #define ATA_CMD_IDLE1 0xE3 #define ATA_CMD_IDLE2 0x97 #define ATA_CMD_IDLE_IMMEDIATE1 0xE1 #define ATA_CMD_IDLE_IMMEDIATE2 0x95 #define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91 #define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91 #define ATA_CMD_NOP 0x00 #define ATA_CMD_PACKET 0xA0 #define ATA_CMD_READ_BUFFER 0xE4 #define ATA_CMD_READ_DMA 0xC8 #define ATA_CMD_READ_DMA_QUEUED 0xC7 #define ATA_CMD_READ_MULTIPLE 0xC4 #define ATA_CMD_READ_SECTORS 0x20 #define ATA_CMD_READ_VERIFY_SECTORS 0x40 #define ATA_CMD_RECALIBRATE 0x10 #define ATA_CMD_REQUEST_SENSE 0x03 #define ATA_CMD_SEEK 0x70 #define ATA_CMD_SET_FEATURES 0xEF #define ATA_CMD_SET_MULTIPLE_MODE 0xC6 #define ATA_CMD_SLEEP1 0xE6 #define ATA_CMD_SLEEP2 0x99 #define ATA_CMD_STANDBY1 0xE2 #define ATA_CMD_STANDBY2 0x96 #define ATA_CMD_STANDBY_IMMEDIATE1 0xE0 #define ATA_CMD_STANDBY_IMMEDIATE2 0x94 #define ATA_CMD_WRITE_BUFFER 0xE8 #define ATA_CMD_WRITE_DMA 0xCA #define ATA_CMD_WRITE_DMA_QUEUED 0xCC #define ATA_CMD_WRITE_MULTIPLE 0xC5 #define ATA_CMD_WRITE_SECTORS 0x30 #define ATA_CMD_WRITE_VERIFY 0x3C #define ATA_IFACE_NONE 0x00 #define ATA_IFACE_ISA 0x00 #define ATA_IFACE_PCI 0x01 #define ATA_TYPE_NONE 0x00 #define ATA_TYPE_UNKNOWN 0x01 #define ATA_TYPE_ATA 0x02 #define ATA_TYPE_ATAPI 0x03 #define ATA_DEVICE_NONE 0x00 #define ATA_DEVICE_HD 0xFF #define ATA_DEVICE_CDROM 0x05 #define ATA_MODE_NONE 0x00 #define ATA_MODE_PIO16 0x00 #define ATA_MODE_PIO32 0x01 #define ATA_MODE_ISADMA 0x02 #define ATA_MODE_PCIDMA 0x03 #define ATA_MODE_USEIRQ 0x10 #define ATA_TRANSLATION_NONE 0 #define ATA_TRANSLATION_LBA 1 #define ATA_TRANSLATION_LARGE 2 #define ATA_TRANSLATION_RECHS 3 #define ATA_DATA_NO 0x00 #define ATA_DATA_IN 0x01 #define ATA_DATA_OUT 0x02 // --------------------------------------------------------------------------- // ATA/ATAPI driver : initialization // --------------------------------------------------------------------------- void ata_init( ) { Bit8u channel, device; // Set DS to EBDA segment. Bit16u old_ds = set_DS(read_word(0x000E,0x0040)); // Channels info init. for (channel=0; channelata.channels[channel].iface,ATA_IFACE_NONE); write_word_DS(&EbdaData->ata.channels[channel].iobase1,0x0); write_word_DS(&EbdaData->ata.channels[channel].iobase2,0x0); write_byte_DS(&EbdaData->ata.channels[channel].irq,0); } // Devices info init. for (device=0; deviceata.devices[device].type,ATA_TYPE_NONE); write_byte_DS(&EbdaData->ata.devices[device].device,ATA_DEVICE_NONE); write_byte_DS(&EbdaData->ata.devices[device].removable,0); write_byte_DS(&EbdaData->ata.devices[device].lock,0); write_byte_DS(&EbdaData->ata.devices[device].mode,ATA_MODE_NONE); write_word_DS(&EbdaData->ata.devices[device].blksize,0); write_byte_DS(&EbdaData->ata.devices[device].translation,ATA_TRANSLATION_NONE); write_word_DS(&EbdaData->ata.devices[device].lchs.heads,0); write_word_DS(&EbdaData->ata.devices[device].lchs.cylinders,0); write_word_DS(&EbdaData->ata.devices[device].lchs.spt,0); write_word_DS(&EbdaData->ata.devices[device].pchs.heads,0); write_word_DS(&EbdaData->ata.devices[device].pchs.cylinders,0); write_word_DS(&EbdaData->ata.devices[device].pchs.spt,0); write_dword_DS(&EbdaData->ata.devices[device].sectors_low,0L); write_dword_DS(&EbdaData->ata.devices[device].sectors_high,0L); } // hdidmap and cdidmap init. for (device=0; deviceata.hdidmap[device],BX_MAX_ATA_DEVICES); write_byte_DS(&EbdaData->ata.cdidmap[device],BX_MAX_ATA_DEVICES); } write_byte_DS(&EbdaData->ata.hdcount,0); write_byte_DS(&EbdaData->ata.cdcount,0); // Restore old DS set_DS(old_ds); } #define TIMEOUT 0 #define BSY 1 #define NOT_BSY 2 #define NOT_BSY_DRQ 3 #define NOT_BSY_NOT_DRQ 4 #define NOT_BSY_RDY 5 #define IDE_TIMEOUT 32000u //32 seconds max for IDE ops int await_ide(); static int await_ide(when_done,base,timeout) Bit8u when_done; Bit16u base; Bit16u timeout; { Bit32u time=0,last=0; Bit16u status; Bit8u result; status = inb(base + ATA_CB_STAT); // for the times you're supposed to throw one away for(;;) { status = inb(base+ATA_CB_STAT); time++; if (when_done == BSY) result = status & ATA_CB_STAT_BSY; else if (when_done == NOT_BSY) result = !(status & ATA_CB_STAT_BSY); else if (when_done == NOT_BSY_DRQ) result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_DRQ); else if (when_done == NOT_BSY_NOT_DRQ) result = !(status & ATA_CB_STAT_BSY) && !(status & ATA_CB_STAT_DRQ); else if (when_done == NOT_BSY_RDY) result = !(status & ATA_CB_STAT_BSY) && (status & ATA_CB_STAT_RDY); else if (when_done == TIMEOUT) result = 0; if (result) return 0; if (time>>16 != last) // mod 2048 each 16 ms { last = time >>16; BX_DEBUG_ATA("await_ide: (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout); } if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("await_ide: ERROR (TIMEOUT,BSY,!BSY,!BSY_DRQ,!BSY_!DRQ,!BSY_RDY) %d time= %ld timeout= %d\n",when_done,time>>11, timeout); return -1; } if ((timeout == 0) || ((time>>11) > timeout)) break; } BX_INFO("IDE time out\n"); return -1; } // --------------------------------------------------------------------------- // ATA/ATAPI driver : device detection // --------------------------------------------------------------------------- void ata_detect( ) { Bit8u hdcount, cdcount, device, type; Bit8u buffer[0x0200]; // Set DS to EBDA segment. Bit16u old_ds = set_DS(read_word(0x000E,0x0040)); #if BX_MAX_ATA_INTERFACES > 0 write_byte_DS(&EbdaData->ata.channels[0].iface,ATA_IFACE_ISA); write_word_DS(&EbdaData->ata.channels[0].iobase1,PORT_ATA1_CMD_BASE); write_word_DS(&EbdaData->ata.channels[0].iobase2,0x3f0); write_byte_DS(&EbdaData->ata.channels[0].irq,14); #endif #if BX_MAX_ATA_INTERFACES > 1 write_byte_DS(&EbdaData->ata.channels[1].iface,ATA_IFACE_ISA); write_word_DS(&EbdaData->ata.channels[1].iobase1,PORT_ATA2_CMD_BASE); write_word_DS(&EbdaData->ata.channels[1].iobase2,0x370); write_byte_DS(&EbdaData->ata.channels[1].irq,15); #endif #if BX_MAX_ATA_INTERFACES > 2 write_byte_DS(&EbdaData->ata.channels[2].iface,ATA_IFACE_ISA); write_word_DS(&EbdaData->ata.channels[2].iobase1,0x1e8); write_word_DS(&EbdaData->ata.channels[2].iobase2,0x3e0); write_byte_DS(&EbdaData->ata.channels[2].irq,12); #endif #if BX_MAX_ATA_INTERFACES > 3 write_byte_DS(&EbdaData->ata.channels[3].iface,ATA_IFACE_ISA); write_word_DS(&EbdaData->ata.channels[3].iobase1,0x168); write_word_DS(&EbdaData->ata.channels[3].iobase2,0x360); write_byte_DS(&EbdaData->ata.channels[3].irq,11); #endif #if BX_MAX_ATA_INTERFACES > 4 #error Please fill the ATA interface informations #endif // Device detection hdcount=cdcount=0; for(device=0; deviceata.channels[channel].iobase1); iobase2 =read_word_DS(&EbdaData->ata.channels[channel].iobase2); // Disable interrupts outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); // Look for device outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); outb(iobase1+ATA_CB_SC, 0x55); outb(iobase1+ATA_CB_SN, 0xaa); outb(iobase1+ATA_CB_SC, 0xaa); outb(iobase1+ATA_CB_SN, 0x55); outb(iobase1+ATA_CB_SC, 0x55); outb(iobase1+ATA_CB_SN, 0xaa); // If we found something sc = inb(iobase1+ATA_CB_SC); sn = inb(iobase1+ATA_CB_SN); if ( (sc == 0x55) && (sn == 0xaa) ) { write_byte_DS(&EbdaData->ata.devices[device].type,ATA_TYPE_UNKNOWN); // reset the channel ata_reset(device); // check for ATA or ATAPI outb(iobase1+ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); sc = inb(iobase1+ATA_CB_SC); sn = inb(iobase1+ATA_CB_SN); if ((sc==0x01) && (sn==0x01)) { cl = inb(iobase1+ATA_CB_CL); ch = inb(iobase1+ATA_CB_CH); st = inb(iobase1+ATA_CB_STAT); if ((cl==0x14) && (ch==0xeb)) { write_byte_DS(&EbdaData->ata.devices[device].type,ATA_TYPE_ATAPI); } else if ((cl==0x00) && (ch==0x00) && (st!=0x00)) { write_byte_DS(&EbdaData->ata.devices[device].type,ATA_TYPE_ATA); } else if ((cl==0xff) && (ch==0xff)) { write_byte_DS(&EbdaData->ata.devices[device].type,ATA_TYPE_NONE); } } } type=read_byte_DS(&EbdaData->ata.devices[device].type); // Now we send a IDENTIFY command to ATA device if(type == ATA_TYPE_ATA) { Bit32u sectors_low, sectors_high; Bit16u cylinders, heads, spt, blksize; Bit8u translation, removable, mode; //Temporary values to do the transfer write_byte_DS(&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); write_byte_DS(&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); if (ata_cmd_data_io(0, device,ATA_CMD_IDENTIFY_DEVICE, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) !=0 ) BX_PANIC("ata-detect: Failed to detect ATA device\n"); removable = (read_byte_SS(buffer+0) & 0x80) >> 7; mode = read_byte_SS(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; blksize = read_word_SS(buffer+10); cylinders = read_word_SS(buffer+(1*2)); // word 1 heads = read_word_SS(buffer+(3*2)); // word 3 spt = read_word_SS(buffer+(6*2)); // word 6 if (read_word_SS(buffer+(83*2)) & (1 << 10)) { // word 83 - lba48 support sectors_low = read_dword_SS(buffer+(100*2)); // word 100 and word 101 sectors_high = read_dword_SS(buffer+(102*2)); // word 102 and word 103 } else { sectors_low = read_dword_SS(buffer+(60*2)); // word 60 and word 61 sectors_high = 0; } write_byte_DS(&EbdaData->ata.devices[device].device,ATA_DEVICE_HD); write_byte_DS(&EbdaData->ata.devices[device].removable, removable); write_byte_DS(&EbdaData->ata.devices[device].mode, mode); write_word_DS(&EbdaData->ata.devices[device].blksize, blksize); write_word_DS(&EbdaData->ata.devices[device].pchs.heads, heads); write_word_DS(&EbdaData->ata.devices[device].pchs.cylinders, cylinders); write_word_DS(&EbdaData->ata.devices[device].pchs.spt, spt); write_dword_DS(&EbdaData->ata.devices[device].sectors_low, sectors_low); write_dword_DS(&EbdaData->ata.devices[device].sectors_high, sectors_high); BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt); translation = inb_cmos(0x39 + channel/2); for (shift=device%4; shift>0; shift--) translation >>= 2; translation &= 0x03; write_byte_DS(&EbdaData->ata.devices[device].translation, translation); switch (translation) { case ATA_TRANSLATION_NONE: BX_INFO("none"); break; case ATA_TRANSLATION_LBA: BX_INFO("lba"); break; case ATA_TRANSLATION_LARGE: BX_INFO("large"); break; case ATA_TRANSLATION_RECHS: BX_INFO("r-echs"); break; } switch (translation) { case ATA_TRANSLATION_NONE: break; case ATA_TRANSLATION_LBA: spt = 63; sectors_low /= 63; heads = sectors_low / 1024; if (heads>128) heads = 255; else if (heads>64) heads = 128; else if (heads>32) heads = 64; else if (heads>16) heads = 32; else heads=16; cylinders = sectors_low / heads; break; case ATA_TRANSLATION_RECHS: // Take care not to overflow if (heads==16) { if(cylinders>61439) cylinders=61439; heads=15; cylinders = (Bit16u)((Bit32u)(cylinders)*16/15); } // then go through the large bitshift process case ATA_TRANSLATION_LARGE: while(cylinders > 1024) { cylinders >>= 1; heads <<= 1; // If we max out the head count if (heads > 127) break; } break; } // clip to 1024 cylinders in lchs if (cylinders > 1024) cylinders=1024; BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt); write_word_DS(&EbdaData->ata.devices[device].lchs.heads, heads); write_word_DS(&EbdaData->ata.devices[device].lchs.cylinders, cylinders); write_word_DS(&EbdaData->ata.devices[device].lchs.spt, spt); // fill hdidmap write_byte_DS(&EbdaData->ata.hdidmap[hdcount], device); hdcount++; } // Now we send a IDENTIFY command to ATAPI device if(type == ATA_TYPE_ATAPI) { Bit8u type, removable, mode; Bit16u blksize; //Temporary values to do the transfer write_byte_DS(&EbdaData->ata.devices[device].device,ATA_DEVICE_CDROM); write_byte_DS(&EbdaData->ata.devices[device].mode, ATA_MODE_PIO16); if (ata_cmd_data_io(0, device,ATA_CMD_IDENTIFY_DEVICE_PACKET, 1, 0, 0, 0, 0L, 0L, get_SS(),buffer) != 0) BX_PANIC("ata-detect: Failed to detect ATAPI device\n"); type = read_byte_SS(buffer+1) & 0x1f; removable = (read_byte_SS(buffer+0) & 0x80) ? 1 : 0; mode = read_byte_SS(buffer+96) ? ATA_MODE_PIO32 : ATA_MODE_PIO16; blksize = 2048; write_byte_DS(&EbdaData->ata.devices[device].device, type); write_byte_DS(&EbdaData->ata.devices[device].removable, removable); write_byte_DS(&EbdaData->ata.devices[device].mode, mode); write_word_DS(&EbdaData->ata.devices[device].blksize, blksize); // fill cdidmap write_byte_DS(&EbdaData->ata.cdidmap[cdcount], device); cdcount++; } { Bit32u sizeinmb; Bit16u ataversion; Bit8u c, i, version, model[41]; switch (type) { case ATA_TYPE_ATA: sizeinmb = (read_dword_DS(&EbdaData->ata.devices[device].sectors_high) << 21) | (read_dword_DS(&EbdaData->ata.devices[device].sectors_low) >> 11); case ATA_TYPE_ATAPI: // Read ATA/ATAPI version ataversion=((Bit16u)(read_byte_SS(buffer+161))<<8)|read_byte_SS(buffer+160); for(version=15;version>0;version--) { if((ataversion&(1<0;i--){ if(read_byte_SS(model+i)==0x20) write_byte_SS(0x00,model+i); else break; } if (i>36) { write_byte_SS(0x00,model+36); for(i=35;i>32;i--){ write_byte_SS(0x2E,model+i); } } break; } switch (type) { case ATA_TYPE_ATA: printf("ata%d %s: ",channel,slave?" slave":"master"); i=0; while(c=read_byte_SS(model+i++)) printf("%c",c); if (sizeinmb < (1UL<<16)) printf(" ATA-%d Hard-Disk (%4u MBytes)\n", version, (Bit16u)sizeinmb); else printf(" ATA-%d Hard-Disk (%4u GBytes)\n", version, (Bit16u)(sizeinmb>>10)); break; case ATA_TYPE_ATAPI: printf("ata%d %s: ",channel,slave?" slave":"master"); i=0; while(c=read_byte_SS(model+i++)) printf("%c",c); if(read_byte_DS(&EbdaData->ata.devices[device].device)==ATA_DEVICE_CDROM) printf(" ATAPI-%d CD-Rom/DVD-Rom\n",version); else printf(" ATAPI-%d Device\n",version); break; case ATA_TYPE_UNKNOWN: printf("ata%d %s: Unknown device\n",channel,slave?" slave":"master"); break; } } } // Store the devices counts write_byte_DS(&EbdaData->ata.hdcount, hdcount); write_byte_DS(&EbdaData->ata.cdcount, cdcount); write_byte(hdcount, 0x75, 0x40); printf("\n"); // FIXME : should use bios=cmos|auto|disable bits // FIXME : should know about translation bits // FIXME : move hard_drive_post here // Restore DS value. set_DS(old_ds); } // --------------------------------------------------------------------------- // ATA/ATAPI driver : software reset // --------------------------------------------------------------------------- // ATA-3 // 8.2.1 Software reset - Device 0 void ata_reset(device) Bit16u device; { Bit16u iobase1, iobase2; Bit8u channel, slave, sn, sc; Bit8u type; Bit16u max; // // DS has been set to EBDA segment before call // channel = device / 2; slave = device % 2; iobase1 = read_word_DS(&EbdaData->ata.channels[channel].iobase1); iobase2 = read_word_DS(&EbdaData->ata.channels[channel].iobase2); // Reset // 8.2.1 (a) -- set SRST in DC outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST); // 8.2.1 (b) -- wait for BSY await_ide(BSY, iobase1, 20); // 8.2.1 (f) -- clear SRST outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); type=read_byte_DS(&EbdaData->ata.devices[device].type); if (type != ATA_TYPE_NONE) { // 8.2.1 (g) -- check for sc==sn==0x01 // select device outb(iobase1+ATA_CB_DH, slave?ATA_CB_DH_DEV1:ATA_CB_DH_DEV0); sc = inb(iobase1+ATA_CB_SC); sn = inb(iobase1+ATA_CB_SN); if ( (sc==0x01) && (sn==0x01) ) { if (type == ATA_TYPE_ATA) //ATA await_ide(NOT_BSY_RDY, iobase1, IDE_TIMEOUT); else //ATAPI await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); } // 8.2.1 (h) -- wait for not BSY await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); } // Enable interrupts outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); } // --------------------------------------------------------------------------- // ATA/ATAPI driver : execute a non data command // --------------------------------------------------------------------------- Bit16u ata_cmd_non_data() {return 0;} // --------------------------------------------------------------------------- // ATA/ATAPI driver : execute a data-in/out command // --------------------------------------------------------------------------- // returns // 0 : no error // 1 : BUSY bit set // 2 : read error // 3 : expected DRQ=1 // 4 : no sectors left to read/verify // 5 : more sectors to read/verify // 6 : no sectors left to write // 7 : more sectors to write Bit16u ata_cmd_data_io(ioflag, device, command, count, cylinder, head, sector, lba_low, lba_high, segment, offset) Bit16u ioflag, device, command, count, cylinder, head, sector, segment, offset; Bit32u lba_low, lba_high; { Bit16u iobase1, iobase2, blksize; Bit8u channel, slave; Bit8u status, current, mode; // // DS has been set to EBDA segment before call // channel = device / 2; slave = device % 2; iobase1 = read_word_DS(&EbdaData->ata.channels[channel].iobase1); iobase2 = read_word_DS(&EbdaData->ata.channels[channel].iobase2); mode = read_byte_DS(&EbdaData->ata.devices[device].mode); blksize = 0x200; // was = read_word_DS(&EbdaData->ata.devices[device].blksize); if (mode == ATA_MODE_PIO32) blksize>>=2; else blksize>>=1; // Reset count of transferred data write_word_DS(&EbdaData->ata.trsfsectors,0); write_dword_DS(&EbdaData->ata.trsfbytes,0L); current = 0; status = inb(iobase1 + ATA_CB_STAT); if (status & ATA_CB_STAT_BSY) return 1; outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); // sector will be 0 only on lba access. Convert to lba-chs if (sector == 0) { if ((count >= 1 << 8) || lba_high || (lba_low >= ((1UL << 28) - count))) { outb(iobase1 + ATA_CB_FR, 0x00); outb(iobase1 + ATA_CB_SC, (count >> 8) & 0xff); outb(iobase1 + ATA_CB_SN, lba_low >> 24); outb(iobase1 + ATA_CB_CL, lba_high & 0xff); outb(iobase1 + ATA_CB_CH, lba_high >> 8); command |= 0x04; count &= (1UL << 8) - 1; lba_low &= (1UL << 24) - 1; } sector = (Bit16u) (lba_low & 0x000000ffL); cylinder = (Bit16u) ((lba_low>>8) & 0x0000ffffL); head = ((Bit16u) ((lba_low>>24) & 0x0000000fL)) | ATA_CB_DH_LBA; } outb(iobase1 + ATA_CB_FR, 0x00); outb(iobase1 + ATA_CB_SC, count); outb(iobase1 + ATA_CB_SN, sector); outb(iobase1 + ATA_CB_CL, cylinder & 0x00ff); outb(iobase1 + ATA_CB_CH, cylinder >> 8); outb(iobase1 + ATA_CB_DH, (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0) | (Bit8u) head ); outb(iobase1 + ATA_CB_CMD, command); await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); status = inb(iobase1 + ATA_CB_STAT); if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_data_io : read error\n"); return 2; } else if ( !(status & ATA_CB_STAT_DRQ) ) { BX_DEBUG_ATA("ata_cmd_data_io : DRQ not set (status %02x)\n", (unsigned) status); return 3; } // FIXME : move seg/off translation here ASM_START sti ;; enable higher priority interrupts ASM_END while (1) { if(ioflag == 0) { ASM_START push bp mov bp, sp mov di, _ata_cmd_data_io.offset + 2[bp] mov ax, _ata_cmd_data_io.segment + 2[bp] mov cx, _ata_cmd_data_io.blksize + 2[bp] ;; adjust if there will be an overrun. 2K max sector size cmp di, #0xf800 ;; jbe ata_in_no_adjust ata_in_adjust: sub di, #0x0800 ;; sub 2 kbytes from offset add ax, #0x0080 ;; add 2 Kbytes to segment ata_in_no_adjust: mov es, ax ;; segment in es mov dx, _ata_cmd_data_io.iobase1 + 2[bp] ;; ATA data read port mov ah, _ata_cmd_data_io.mode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_in_32 ata_in_16: rep insw ;; CX words transferred from port(DX) to ES:[DI] jmp ata_in_done ata_in_32: rep insd ;; CX dwords transferred from port(DX) to ES:[DI] ata_in_done: mov _ata_cmd_data_io.offset + 2[bp], di mov _ata_cmd_data_io.segment + 2[bp], es pop bp ASM_END } else { ASM_START push bp mov bp, sp mov si, _ata_cmd_data_io.offset + 2[bp] mov ax, _ata_cmd_data_io.segment + 2[bp] mov cx, _ata_cmd_data_io.blksize + 2[bp] ;; adjust if there will be an overrun. 2K max sector size cmp si, #0xf800 ;; jbe ata_out_no_adjust ata_out_adjust: sub si, #0x0800 ;; sub 2 kbytes from offset add ax, #0x0080 ;; add 2 Kbytes to segment ata_out_no_adjust: mov es, ax ;; segment in es mov dx, _ata_cmd_data_io.iobase1 + 2[bp] ;; ATA data write port mov ah, _ata_cmd_data_io.mode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_out_32 ata_out_16: seg ES rep outsw ;; CX words transferred from port(DX) to ES:[SI] jmp ata_out_done ata_out_32: seg ES rep outsd ;; CX dwords transferred from port(DX) to ES:[SI] ata_out_done: mov _ata_cmd_data_io.offset + 2[bp], si mov _ata_cmd_data_io.segment + 2[bp], es pop bp ASM_END } current++; write_word_DS(&EbdaData->ata.trsfsectors,current); count--; if(ioflag == 0) await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); status = inb(iobase1 + ATA_CB_STAT); if(ioflag == 0) { if (count == 0) { if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != ATA_CB_STAT_RDY ) { BX_DEBUG_ATA("ata_cmd_data_io : no sectors left (status %02x)\n", (unsigned) status); return 4; } break; } else { if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { BX_DEBUG_ATA("ata_cmd_data_io : more sectors left (status %02x)\n", (unsigned) status); return 5; } continue; } } else { if (count == 0) { if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != ATA_CB_STAT_RDY ) { BX_DEBUG_ATA("ata_cmd_data_io : no sectors left (status %02x)\n", (unsigned) status); return 6; } break; } else { if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != (ATA_CB_STAT_RDY | ATA_CB_STAT_DRQ) ) { BX_DEBUG_ATA("ata_cmd_data_io : more sectors left (status %02x)\n", (unsigned) status); return 7; } continue; } } } // Enable interrupts outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); return 0; } // --------------------------------------------------------------------------- // ATA/ATAPI driver : execute a packet command // --------------------------------------------------------------------------- // returns // 0 : no error // 1 : error in parameters // 2 : BUSY bit set // 3 : error // 4 : not ready Bit16u ata_cmd_packet(device, cmdlen, cmdseg, cmdoff, header, length, inout, bufseg, bufoff) Bit8u cmdlen,inout; Bit16u device,cmdseg, cmdoff, bufseg, bufoff; Bit16u header; Bit32u length; { Bit16u ebda_seg=read_word(0x000E,0x0040), old_ds; Bit16u iobase1, iobase2; Bit16u lcount, lbefore, lafter, count; Bit8u channel, slave; Bit8u status, mode, lmode; Bit32u total, transfer; channel = device / 2; slave = device % 2; // Data out is not supported yet if (inout == ATA_DATA_OUT) { BX_INFO("ata_cmd_packet: DATA_OUT not supported yet\n"); return 1; } // The header length must be even if (header & 1) { BX_DEBUG_ATA("ata_cmd_packet : header must be even (%04x)\n",header); return 1; } // Set DS to EBDA segment. old_ds = set_DS(ebda_seg); iobase1 = read_word_DS(&EbdaData->ata.channels[channel].iobase1); iobase2 = read_word_DS(&EbdaData->ata.channels[channel].iobase2); mode = read_byte_DS(&EbdaData->ata.devices[device].mode); transfer= 0L; if (cmdlen < 12) cmdlen=12; if (cmdlen > 12) cmdlen=16; cmdlen>>=1; // Reset count of transferred data write_word_DS(&EbdaData->ata.trsfsectors,0); write_dword_DS(&EbdaData->ata.trsfbytes,0L); // Restore old DS set_DS(old_ds); status = inb(iobase1 + ATA_CB_STAT); if (status & ATA_CB_STAT_BSY) return 2; outb(iobase2 + ATA_CB_DC, ATA_CB_DC_HD15 | ATA_CB_DC_NIEN); outb(iobase1 + ATA_CB_FR, 0x00); outb(iobase1 + ATA_CB_SC, 0x00); outb(iobase1 + ATA_CB_SN, 0x00); outb(iobase1 + ATA_CB_CL, 0xfff0 & 0x00ff); outb(iobase1 + ATA_CB_CH, 0xfff0 >> 8); outb(iobase1 + ATA_CB_DH, slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0); outb(iobase1 + ATA_CB_CMD, ATA_CMD_PACKET); // Device should ok to receive command await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); status = inb(iobase1 + ATA_CB_STAT); if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_packet : error, status is %02x\n",status); return 3; } else if ( !(status & ATA_CB_STAT_DRQ) ) { BX_DEBUG_ATA("ata_cmd_packet : DRQ not set (status %02x)\n", (unsigned) status); return 4; } // Normalize address cmdseg += (cmdoff / 16); cmdoff %= 16; // Send command to device ASM_START sti ;; enable higher priority interrupts push bp mov bp, sp mov si, _ata_cmd_packet.cmdoff + 2[bp] mov ax, _ata_cmd_packet.cmdseg + 2[bp] mov cx, _ata_cmd_packet.cmdlen + 2[bp] mov es, ax ;; segment in es mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data write port seg ES rep outsw ;; CX words transferred from port(DX) to ES:[SI] pop bp ASM_END if (inout == ATA_DATA_NO) { await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); status = inb(iobase1 + ATA_CB_STAT); } else { Bit16u loops = 0; Bit8u sc; while (1) { if (loops == 0) {//first time through status = inb(iobase2 + ATA_CB_ASTAT); await_ide(NOT_BSY_DRQ, iobase1, IDE_TIMEOUT); } else await_ide(NOT_BSY, iobase1, IDE_TIMEOUT); loops++; status = inb(iobase1 + ATA_CB_STAT); sc = inb(iobase1 + ATA_CB_SC); // Check if command completed if(((inb(iobase1 + ATA_CB_SC)&0x7)==0x3) && ((status & (ATA_CB_STAT_RDY | ATA_CB_STAT_ERR)) == ATA_CB_STAT_RDY)) break; if (status & ATA_CB_STAT_ERR) { BX_DEBUG_ATA("ata_cmd_packet : error (status %02x)\n",status); return 3; } // Normalize address bufseg += (bufoff / 16); bufoff %= 16; // Get the byte count lcount = ((Bit16u)(inb(iobase1 + ATA_CB_CH))<<8)+inb(iobase1 + ATA_CB_CL); // adjust to read what we want if(header>lcount) { lbefore=lcount; header-=lcount; lcount=0; } else { lbefore=header; header=0; lcount-=lbefore; } if(lcount>length) { lafter=lcount-length; lcount=length; length=0; } else { lafter=0; length-=lcount; } // Save byte count count = lcount; BX_DEBUG_ATA("Trying to read %04x bytes (%04x %04x %04x) ",lbefore+lcount+lafter,lbefore,lcount,lafter); BX_DEBUG_ATA("to 0x%04x:0x%04x\n",bufseg,bufoff); // If counts not dividable by 4, use 16bits mode lmode = mode; if (lbefore & 0x03) lmode=ATA_MODE_PIO16; if (lcount & 0x03) lmode=ATA_MODE_PIO16; if (lafter & 0x03) lmode=ATA_MODE_PIO16; // adds an extra byte if count are odd. before is always even if (lcount & 0x01) { lcount+=1; if ((lafter > 0) && (lafter & 0x01)) { lafter-=1; } } if (lmode == ATA_MODE_PIO32) { lcount>>=2; lbefore>>=2; lafter>>=2; } else { lcount>>=1; lbefore>>=1; lafter>>=1; } ; // FIXME bcc bug ASM_START push bp mov bp, sp mov dx, _ata_cmd_packet.iobase1 + 2[bp] ;; ATA data read port mov cx, _ata_cmd_packet.lbefore + 2[bp] jcxz ata_packet_no_before mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_before_32 ata_packet_in_before_16: in ax, dx loop ata_packet_in_before_16 jmp ata_packet_no_before ata_packet_in_before_32: push eax ata_packet_in_before_32_loop: in eax, dx loop ata_packet_in_before_32_loop pop eax ata_packet_no_before: mov cx, _ata_cmd_packet.lcount + 2[bp] jcxz ata_packet_after mov di, _ata_cmd_packet.bufoff + 2[bp] mov ax, _ata_cmd_packet.bufseg + 2[bp] mov es, ax mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_32 ata_packet_in_16: rep insw ;; CX words transferred to port(DX) to ES:[DI] jmp ata_packet_after ata_packet_in_32: rep insd ;; CX dwords transferred to port(DX) to ES:[DI] ata_packet_after: mov cx, _ata_cmd_packet.lafter + 2[bp] jcxz ata_packet_done mov ah, _ata_cmd_packet.lmode + 2[bp] cmp ah, #ATA_MODE_PIO32 je ata_packet_in_after_32 ata_packet_in_after_16: in ax, dx loop ata_packet_in_after_16 jmp ata_packet_done ata_packet_in_after_32: push eax ata_packet_in_after_32_loop: in eax, dx loop ata_packet_in_after_32_loop pop eax ata_packet_done: pop bp ASM_END // Compute new buffer address bufoff += count; // Save transferred bytes count transfer += count; write_dword(transfer, &EbdaData->ata.trsfbytes, ebda_seg); } } // Final check, device must be ready if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR) ) != ATA_CB_STAT_RDY ) { BX_DEBUG_ATA("ata_cmd_packet : not ready (status %02x)\n", (unsigned) status); return 4; } // Enable interrupts outb(iobase2+ATA_CB_DC, ATA_CB_DC_HD15); return 0; } // --------------------------------------------------------------------------- // End of ATA/ATAPI Driver // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // Start of ATA/ATAPI generic functions // --------------------------------------------------------------------------- Bit16u atapi_get_sense(device, seg, asc, ascq) Bit16u device; { Bit8u atacmd[12]; Bit8u buffer[18]; Bit8u i; memsetb(0,atacmd,get_SS(),12); // Request SENSE atacmd[0]=ATA_CMD_REQUEST_SENSE; atacmd[4]=sizeof(buffer); if (ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 18L, ATA_DATA_IN, get_SS(), buffer) != 0) return 0x0002; write_byte(buffer[12],asc,seg); write_byte(buffer[13],ascq,seg); return 0; } Bit16u atapi_is_ready(device) Bit16u device; { Bit8u packet[12]; Bit8u buf[8]; Bit32u block_len; Bit32u sectors; Bit32u timeout; //measured in ms Bit32u time; Bit8u asc, ascq; Bit8u in_progress; Bit16u ebda_seg = read_word(0x000E,0x0040); if (read_byte(&EbdaData->ata.devices[device].type,ebda_seg) != ATA_TYPE_ATAPI) { printf("not implemented for non-ATAPI device\n"); return -1; } BX_DEBUG_ATA("ata_detect_medium: begin\n"); memsetb(0, packet,get_SS(), sizeof packet); packet[0] = 0x25; /* READ CAPACITY */ /* Retry READ CAPACITY 50 times unless MEDIUM NOT PRESENT * is reported by the device. If the device reports "IN PROGRESS", * 30 seconds is added. */ timeout = 5000; time = 0; in_progress = 0; while (time < timeout) { if (ata_cmd_packet(device, sizeof(packet), get_SS(), packet, 0, 8L, ATA_DATA_IN, get_SS(), buf) == 0) goto ok; if (atapi_get_sense(device, get_SS(), &asc, &ascq) == 0) { if (asc == 0x3a) { /* MEDIUM NOT PRESENT */ BX_DEBUG_ATA("Device reports MEDIUM NOT PRESENT\n"); return -1; } if (asc == 0x04 && ascq == 0x01 && !in_progress) { /* IN PROGRESS OF BECOMING READY */ printf("Waiting for device to detect medium... "); /* Allow 30 seconds more */ timeout = 30000; in_progress = 1; } } time += 100; } BX_DEBUG_ATA("read capacity failed\n"); return -1; ok: block_len = (Bit32u) buf[4] << 24 | (Bit32u) buf[5] << 16 | (Bit32u) buf[6] << 8 | (Bit32u) buf[7] << 0; BX_DEBUG_ATA("block_len=%u\n", block_len); if (block_len!= 2048 && block_len!= 512) { printf("Unsupported sector size %u\n", block_len); return -1; } write_dword(block_len,&EbdaData->ata.devices[device].blksize,ebda_seg); sectors = (Bit32u) buf[0] << 24 | (Bit32u) buf[1] << 16 | (Bit32u) buf[2] << 8 | (Bit32u) buf[3] << 0; BX_DEBUG_ATA("sectors=%u\n", sectors); if (block_len == 2048) sectors <<= 2; /* # of sectors in 512-byte "soft" sector */ if (sectors != read_dword(&EbdaData->ata.devices[device].sectors_low,ebda_seg)) printf("%dMB medium detected\n", sectors>>(20-9)); write_dword(sectors,&EbdaData->ata.devices[device].sectors_low,ebda_seg); return 0; } Bit16u atapi_is_cdrom(device) Bit8u device; { Bit16u ebda_seg=read_word(0x000E,0x0040); if (device >= BX_MAX_ATA_DEVICES) return 0; if (read_byte(&EbdaData->ata.devices[device].type,ebda_seg) != ATA_TYPE_ATAPI) return 0; if (read_byte(&EbdaData->ata.devices[device].device,ebda_seg) != ATA_DEVICE_CDROM) return 0; return 1; } // --------------------------------------------------------------------------- // End of ATA/ATAPI generic functions // --------------------------------------------------------------------------- #endif // BX_USE_ATADRV #if BX_ELTORITO_BOOT // --------------------------------------------------------------------------- // Start of El-Torito boot functions // --------------------------------------------------------------------------- void cdemu_init() { Bit16u ebda_seg=read_word(0x000E,0x0040); // the only important data is this one for now write_byte(0x00,&EbdaData->cdemu.active,ebda_seg); } Bit8u cdemu_isactive() { Bit16u ebda_seg=read_word(0x000E,0x0040); return(read_byte(&EbdaData->cdemu.active,ebda_seg)); } Bit8u cdemu_emulated_drive() { Bit16u ebda_seg=read_word(0x000E,0x0040); return(read_byte(&EbdaData->cdemu.emulated_drive,ebda_seg)); } static char isotag[6]="CD001"; static char eltorito[24]="EL TORITO SPECIFICATION"; // // Returns ah: emulated drive, al: error code // Bit16u cdrom_boot() { Bit16u ebda_seg=read_word(0x000E,0x0040), old_ds; Bit8u atacmd[12], buffer[2048]; Bit32u lba; Bit16u boot_segment, nbsectors, i, error; Bit8u device; // Find out the first cdrom for (device=0; device= BX_MAX_ATA_DEVICES) return 2; if(error = atapi_is_ready(device) != 0) BX_INFO("ata_is_ready returned %d\n",error); // Read the Boot Record Volume Descriptor memsetb(0,atacmd,get_SS(),12); atacmd[0]=0x28; // READ command atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors atacmd[8]=(0x01 & 0x00ff); // Sectors atacmd[2]=(0x11 & 0xff000000) >> 24; // LBA atacmd[3]=(0x11 & 0x00ff0000) >> 16; atacmd[4]=(0x11 & 0x0000ff00) >> 8; atacmd[5]=(0x11 & 0x000000ff); if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) return 3; // Validity checks if(buffer[0]!=0) return 4; for(i=0;i<5;i++){ if(buffer[1+i]!=read_byte(&isotag[i],0xf000)) return 5; } for(i=0;i<23;i++) if(buffer[7+i]!=read_byte(&eltorito[i],0xf000)) return 6; // ok, now we calculate the Boot catalog address lba=*((Bit32u *)&buffer[0x47]); // And we read the Boot Catalog memsetb(0,atacmd,get_SS(),12); atacmd[0]=0x28; // READ command atacmd[7]=(0x01 & 0xff00) >> 8; // Sectors atacmd[8]=(0x01 & 0x00ff); // Sectors atacmd[2]=(lba & 0xff000000) >> 24; // LBA atacmd[3]=(lba & 0x00ff0000) >> 16; atacmd[4]=(lba & 0x0000ff00) >> 8; atacmd[5]=(lba & 0x000000ff); if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, 2048L, ATA_DATA_IN, get_SS(), buffer)) != 0) return 7; // Validation entry if(buffer[0x00]!=0x01)return 8; // Header if(buffer[0x01]!=0x00)return 9; // Platform if(buffer[0x1E]!=0x55)return 10; // key 1 if(buffer[0x1F]!=0xAA)return 10; // key 2 // Initial/Default Entry if(buffer[0x20]!=0x88)return 11; // Bootable // Set DS to EBDA segment old_ds = set_DS(ebda_seg); write_byte_DS(&EbdaData->cdemu.media,buffer[0x21]); if(buffer[0x21]==0){ // FIXME ElTorito Hardcoded. cdrom is hardcoded as device 0xE0. // Win2000 cd boot needs to know it booted from cd write_byte_DS(&EbdaData->cdemu.emulated_drive,0xE0); } else if(buffer[0x21]<4) write_byte_DS(&EbdaData->cdemu.emulated_drive,0x00); else write_byte_DS(&EbdaData->cdemu.emulated_drive,0x80); write_byte_DS(&EbdaData->cdemu.controller_index,device/2); write_byte_DS(&EbdaData->cdemu.device_spec,device%2); boot_segment=*((Bit16u *)&buffer[0x22]); if(boot_segment==0x0000)boot_segment=0x07C0; write_word_DS(&EbdaData->cdemu.load_segment,boot_segment); write_word_DS(&EbdaData->cdemu.buffer_segment,0x0000); nbsectors=*((Bit16u *)&buffer[0x26]); write_word_DS(&EbdaData->cdemu.sector_count,nbsectors); lba=*((Bit32u *)&buffer[0x28]); write_dword_DS(&EbdaData->cdemu.ilba,lba); // And we read the image in memory memsetb(0,atacmd,get_SS(),12); atacmd[0]=0x28; // READ command atacmd[7]=((1+(nbsectors-1)/4) & 0xff00) >> 8; // Sectors atacmd[8]=((1+(nbsectors-1)/4) & 0x00ff); // Sectors atacmd[2]=(lba & 0xff000000) >> 24; // LBA atacmd[3]=(lba & 0x00ff0000) >> 16; atacmd[4]=(lba & 0x0000ff00) >> 8; atacmd[5]=(lba & 0x000000ff); if((error = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, nbsectors*512L, ATA_DATA_IN, boot_segment,0)) != 0) { // Restore old DS value before return. set_DS(old_ds); return 12; } // Remember the media type switch(read_byte_DS(&EbdaData->cdemu.media)) { case 0x01: // 1.2M floppy write_word_DS(&EbdaData->cdemu.vdevice.spt,15); write_word_DS(&EbdaData->cdemu.vdevice.cylinders,80); write_word_DS(&EbdaData->cdemu.vdevice.heads,2); break; case 0x02: // 1.44M floppy write_word_DS(&EbdaData->cdemu.vdevice.spt,18); write_word_DS(&EbdaData->cdemu.vdevice.cylinders,80); write_word_DS(&EbdaData->cdemu.vdevice.heads,2); break; case 0x03: // 2.88M floppy write_word_DS(&EbdaData->cdemu.vdevice.spt,36); write_word_DS(&EbdaData->cdemu.vdevice.cylinders,80); write_word_DS(&EbdaData->cdemu.vdevice.heads,2); break; case 0x04: // Harddrive write_word_DS(&EbdaData->cdemu.vdevice.spt,read_byte(446+6,boot_segment)&0x3f); write_word_DS(&EbdaData->cdemu.vdevice.cylinders, (read_byte(446+6,boot_segment)<<2) + read_byte(446+7,boot_segment) + 1); write_word_DS(&EbdaData->cdemu.vdevice.heads,read_byte(446+5,boot_segment) + 1); break; } if(read_byte_DS(&EbdaData->cdemu.media)!=0) { // Increase bios installed hardware number of devices if(read_byte_DS(&EbdaData->cdemu.emulated_drive)==0x00) write_byte(read_byte(0x10,0x40)|0x41,0x10,0x40); else write_byte_DS(&EbdaData->ata.hdcount, read_byte_DS(&EbdaData->ata.hdcount) + 1); } // everything is ok, so from now on, the emulation is active if(read_byte_DS(&EbdaData->cdemu.media)!=0) write_byte_DS(&EbdaData->cdemu.active,0x01); // Set return value to boot drive + no error i = (read_byte_DS(&EbdaData->cdemu.emulated_drive)*0x100)+0; // Restore old DS value before return. set_DS(old_ds); // return the boot drive + no error return i; } // --------------------------------------------------------------------------- // End of El-Torito boot functions // --------------------------------------------------------------------------- #endif // BX_ELTORITO_BOOT void int14_function(regs, ds, iret_addr) pusha_regs_t regs; // regs pushed from PUSHA instruction Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call { Bit16u addr,timer,val16; Bit8u counter; ASM_START sti ASM_END addr = read_word_DS(0x400 + (regs.u.r16.dx << 1)); counter = read_byte_DS(0x047C + regs.u.r16.dx); if ((regs.u.r16.dx < 4) && (addr > 0)) { switch (regs.u.r8.ah) { case 0: outb(addr+3, inb(addr+3) | 0x80); if (regs.u.r8.al & 0xE0 == 0) { outb(addr, 0x17); outb(addr+1, 0x04); } else { val16 = 0x600 >> ((regs.u.r8.al & 0xE0) >> 5); outb(addr, val16 & 0xFF); outb(addr+1, val16 >> 8); } outb(addr+3, regs.u.r8.al & 0x1F); regs.u.r8.ah = inb(addr+5); regs.u.r8.al = inb(addr+6); ClearCF(iret_addr.flags); break; case 1: timer = read_word_DS(0x046C); while (((inb(addr+5) & 0x60) != 0x60) && (counter)) { val16 = read_word_DS(0x046C); if (val16 != timer) { timer = val16; counter--; } } if (counter > 0) { outb(addr, regs.u.r8.al); regs.u.r8.ah = inb(addr+5); } else { regs.u.r8.ah = 0x80; } ClearCF(iret_addr.flags); break; case 2: timer = read_word_DS(0x046C); while (((inb(addr+5) & 0x01) == 0) && (counter)) { val16 = read_word_DS(0x046C); if (val16 != timer) { timer = val16; counter--; } } if (counter > 0) { regs.u.r8.ah = inb(addr+5); regs.u.r8.al = inb(addr); } else { regs.u.r8.ah = 0x80; } ClearCF(iret_addr.flags); break; case 3: regs.u.r8.ah = inb(addr+5); regs.u.r8.al = inb(addr+6); ClearCF(iret_addr.flags); break; default: SetCF(iret_addr.flags); // Unsupported } } else { SetCF(iret_addr.flags); // Unsupported } } void int15_function(regs, ES, DS, FLAGS) pusha_regs_t regs; // REGS pushed via pusha Bit16u ES, DS, FLAGS; { Bit16u ebda_seg=read_word(0x000E,0x0040); bx_bool prev_a20_enable; Bit16u base15_00; Bit8u base23_16; Bit16u ss; Bit16u BX,CX,DX; Bit16u bRegister; Bit8u irqDisable; BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); switch (regs.u.r8.ah) { case 0x24: /* A20 Control */ switch (regs.u.r8.al) { case 0x00: case 0x01: set_enable_a20(regs.u.r8.al); CLEAR_CF(); regs.u.r8.ah = 0; break; case 0x02: regs.u.r8.al = (inb(PORT_A20) >> 1) & 0x01; CLEAR_CF(); regs.u.r8.ah = 0; break; case 0x03: CLEAR_CF(); regs.u.r8.ah = 0; regs.u.r16.bx = 3; break; default: BX_INFO("int15: Func 24h, subfunc %02xh, A20 gate control not supported\n", (unsigned) regs.u.r8.al); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } break; case 0x41: SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; case 0x4f: /* keyboard intercept */ // nop SET_CF(); break; case 0x52: // removable media eject CLEAR_CF(); regs.u.r8.ah = 0; // "ok ejection may proceed" break; case 0x80: /* Device open */ case 0x81: /* Device close */ case 0x82: /* Program termination */ case 0x90: /* Device busy interrupt. Called by Int 16h when no key available */ case 0x91: /* Interrupt complete. Called by IRQ handlers */ CLEAR_CF(); regs.u.r8.ah = 0; // "operation success" break; case 0x83: { // Set DS to 0x40 set_DS(0x40); if( regs.u.r8.al == 0 ) { // Set Interval requested. if( ( read_byte_DS( 0xA0 ) & 1 ) == 0 ) { // Interval not already set. write_byte_DS( 0xA0, 1 ); // Set status byte. write_word_DS( 0x98, ES ); // Byte location, segment write_word_DS( 0x9A, regs.u.r16.bx ); // Byte location, offset write_word_DS( 0x9C, regs.u.r16.dx ); // Low word, delay write_word_DS( 0x9E, regs.u.r16.cx ); // High word, delay. CLEAR_CF( ); irqDisable = inb( PORT_PIC2_DATA ); outb( PORT_PIC2_DATA, irqDisable & 0xFE ); bRegister = inb_cmos( 0xB ); // Unmask IRQ8 so INT70 will get through. outb_cmos( 0xB, bRegister | 0x40 ); // Turn on the Periodic Interrupt timer } else { // Interval already set. BX_DEBUG_INT15("int15: Func 83h, failed, already waiting.\n" ); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } } else if( regs.u.r8.al == 1 ) { // Clear Interval requested write_byte_DS( 0xA0, 0 ); // Clear status byte CLEAR_CF( ); bRegister = inb_cmos( 0xB ); outb_cmos( 0xB, bRegister & ~0x40 ); // Turn off the Periodic Interrupt timer } else { BX_DEBUG_INT15("int15: Func 83h, failed.\n" ); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; regs.u.r8.al--; } break; } case 0x87: // +++ should probably have descriptor checks // +++ should have exception handlers // turn off interrupts ASM_START cli ASM_END prev_a20_enable = set_enable_a20(1); // enable A20 line // 128K max of transfer on 386+ ??? // source == destination ??? // ES:SI points to descriptor table // offset use initially comments // ============================================== // 00..07 Unused zeros Null descriptor // 08..0f GDT zeros filled in by BIOS // 10..17 source ssssssss source of data // 18..1f dest dddddddd destination of data // 20..27 CS zeros filled in by BIOS // 28..2f SS zeros filled in by BIOS //es:si //eeee0 //0ssss //----- // check for access rights of source & dest here // Initialize GDT descriptor base15_00 = (ES << 4) + regs.u.r16.si; base23_16 = ES >> 12; if (base15_00 < (ES<<4)) base23_16++; // Set DS to ES value set_DS(ES); write_word_DS(regs.u.r16.si+0x08+0, 47); // limit 15:00 = 6 * 8bytes/descriptor write_word_DS(regs.u.r16.si+0x08+2, base15_00);// base 15:00 write_byte_DS(regs.u.r16.si+0x08+4, base23_16);// base 23:16 write_byte_DS(regs.u.r16.si+0x08+5, 0x93); // access write_word_DS(regs.u.r16.si+0x08+6, 0x0000); // base 31:24/reserved/limit 19:16 // Initialize CS descriptor write_word_DS(regs.u.r16.si+0x20+0, 0xffff);// limit 15:00 = normal 64K limit write_word_DS(regs.u.r16.si+0x20+2, 0x0000);// base 15:00 write_byte_DS(regs.u.r16.si+0x20+4, 0x000f);// base 23:16 write_byte_DS(regs.u.r16.si+0x20+5, 0x9b); // access write_word_DS(regs.u.r16.si+0x20+6, 0x0000);// base 31:24/reserved/limit 19:16 // Initialize SS descriptor ss = get_SS(); base15_00 = ss << 4; base23_16 = ss >> 12; write_word_DS(regs.u.r16.si+0x28+0, 0xffff); // limit 15:00 = normal 64K limit write_word_DS(regs.u.r16.si+0x28+2, base15_00);// base 15:00 write_byte_DS(regs.u.r16.si+0x28+4, base23_16);// base 23:16 write_byte_DS(regs.u.r16.si+0x28+5, 0x93); // access write_word_DS(regs.u.r16.si+0x28+6, 0x0000); // base 31:24/reserved/limit 19:16 CX = regs.u.r16.cx; ASM_START // Compile generates locals offset info relative to SP. // Get CX (word count) from stack. mov bx, sp SEG SS mov cx, _int15_function.CX [bx] // since we need to set SS:SP, save them to the BDA // for future restore push eax xor eax, eax mov ds, ax mov 0x0469, ss mov 0x0467, sp SEG ES lgdt [si + 0x08] SEG CS lidt [pmode_IDT_info] ;; perhaps do something with IDT here ;; set PE bit in CR0 mov eax, cr0 or al, #0x01 mov cr0, eax ;; far jump to flush CPU queue after transition to protected mode JMP_AP(0x0020, protected_mode) protected_mode: ;; GDT points to valid descriptor table, now load SS, DS, ES mov ax, #0x28 ;; 101 000 = 5th descriptor in table, TI=GDT, RPL=00 mov ss, ax mov ax, #0x10 ;; 010 000 = 2nd descriptor in table, TI=GDT, RPL=00 mov ds, ax mov ax, #0x18 ;; 011 000 = 3rd descriptor in table, TI=GDT, RPL=00 mov es, ax xor si, si xor di, di cld rep movsw ;; move CX words from DS:SI to ES:DI ;; make sure DS and ES limits are 64KB mov ax, #0x28 mov ds, ax mov es, ax ;; reset PG bit in CR0 ??? mov eax, cr0 and al, #0xFE mov cr0, eax ;; far jump to flush CPU queue after transition to real mode JMP_AP(0xf000, real_mode) real_mode: ;; restore IDT to normal real-mode defaults SEG CS lidt [rmode_IDT_info] // restore SS:SP from the BDA xor ax, ax mov ds, ax mov ss, 0x0469 mov sp, 0x0467 pop eax ASM_END set_enable_a20(prev_a20_enable); // turn back on interrupts ASM_START sti ASM_END regs.u.r8.ah = 0; CLEAR_CF(); break; case 0x88: // Get the amount of extended memory (above 1M) regs.u.r8.al = inb_cmos(0x30); regs.u.r8.ah = inb_cmos(0x31); // According to Ralf Brown's interrupt the limit should be 15M, // but real machines mostly return max. 63M. if(regs.u.r16.ax > 0xffc0) regs.u.r16.ax = 0xffc0; CLEAR_CF(); break; case 0x89: // Switch to Protected Mode. // ES:DI points to user-supplied GDT // BH/BL contains starting interrupt numbers for PIC0/PIC1 // This subfunction does not return! // turn off interrupts ASM_START cli ASM_END set_enable_a20(1); // enable A20 line; we're supposed to fail if that fails // Initialize CS descriptor for BIOS // Set DS to ES value set_DS(ES); write_word_DS(regs.u.r16.si+0x38+0, 0xffff);// limit 15:00 = normal 64K limit write_word_DS(regs.u.r16.si+0x38+2, 0x0000);// base 15:00 write_byte_DS(regs.u.r16.si+0x38+4, 0x000f);// base 23:16 (hardcoded to f000:0000) write_byte_DS(regs.u.r16.si+0x38+5, 0x9b); // access write_word_DS(regs.u.r16.si+0x38+6, 0x0000);// base 31:24/reserved/limit 19:16 BX = regs.u.r16.bx; ASM_START // Compiler generates locals offset info relative to SP. // Get BX (PIC offsets) from stack. mov bx, sp SEG SS mov bx, _int15_function.BX [bx] // Program PICs mov al, #0x11 ; send initialisation commands out PORT_PIC1_CMD, al out PORT_PIC2_CMD, al mov al, bh out PORT_PIC1_DATA, al mov al, bl out PORT_PIC2_DATA, al mov al, #0x04 out PORT_PIC1_DATA, al mov al, #0x02 out PORT_PIC2_DATA, al mov al, #0x01 out PORT_PIC1_DATA, al out PORT_PIC2_DATA, al mov al, #0xff ; mask all IRQs, user must re-enable out PORT_PIC1_DATA, al out PORT_PIC2_DATA, al // Load GDT and IDT from supplied data SEG ES lgdt [si + 0x08] SEG ES lidt [si + 0x10] // set PE bit in CR0 mov eax, cr0 or al, #0x01 mov cr0, eax // far jump to flush CPU queue after transition to protected mode JMP_AP(0x0038, protmode_switch) protmode_switch: ;; GDT points to valid descriptor table, now load SS, DS, ES mov ax, #0x28 mov ss, ax mov ax, #0x18 mov ds, ax mov ax, #0x20 mov es, ax // unwind the stack - this will break if calling sequence changes! mov sp,bp add sp,#4 ; skip return address popa ; restore regs pop ax ; skip saved es pop ax ; skip saved ds pop ax ; skip saved flags // return to caller - note that we do not use IRET because // we cannot enable interrupts pop cx ; get return offset pop ax ; skip return segment pop ax ; skip flags mov ax, #0x30 ; ah must be 0 on successful exit push ax push cx ; re-create modified ret address on stack retf ASM_END break; case 0xbf: BX_INFO("*** int 15h function AH=bf not yet supported!\n"); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; case 0xC0: #if 0 SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; #endif CLEAR_CF(); regs.u.r8.ah = 0; regs.u.r16.bx = BIOS_CONFIG_TABLE; ES = 0xF000; break; case 0xc1: ES = ebda_seg; CLEAR_CF(); break; case 0xd8: bios_printf(BIOS_PRINTF_DEBUG, "EISA BIOS not present\n"); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; default: BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; } } #if BX_USE_PS2_MOUSE void int15_function_mouse(regs, ES, DS, FLAGS) pusha_regs_t regs; // REGS pushed via pusha Bit16u ES, DS, FLAGS; { Bit16u ebda_seg=read_word(0x000E,0x0040); Bit8u mouse_flags_1, mouse_flags_2; Bit16u mouse_driver_seg; Bit16u mouse_driver_offset; Bit8u comm_byte, prev_command_byte; Bit8u ret, mouse_data1, mouse_data2, mouse_data3; BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); switch (regs.u.r8.ah) { case 0xC2: // Return Codes status in AH // ========================= // 00: success // 01: invalid subfunction (AL > 7) // 02: invalid input value (out of allowable range) // 03: interface error // 04: resend command received from mouse controller, // device driver should attempt command again // 05: cannot enable mouse, since no far call has been installed // 80/86: mouse service not implemented switch (regs.u.r8.al) { case 0: // Disable/Enable Mouse BX_DEBUG_INT15("case 0:\n"); switch (regs.u.r8.bh) { case 0: // Disable Mouse BX_DEBUG_INT15("case 0: disable mouse\n"); inhibit_mouse_int_and_events(); // disable IRQ12 and packets ret = send_to_mouse_ctrl(0xF5); // disable mouse command if (ret == 0) { ret = get_mouse_data(&mouse_data1); if ( (ret == 0) || (mouse_data1 == 0xFA) ) { CLEAR_CF(); regs.u.r8.ah = 0; return; } } // error SET_CF(); regs.u.r8.ah = ret; return; break; case 1: // Enable Mouse BX_DEBUG_INT15("case 1: enable mouse\n"); mouse_flags_2 = read_byte(&EbdaData->mouse_flag2, ebda_seg); if ( (mouse_flags_2 & 0x80) == 0 ) { BX_DEBUG_INT15("INT 15h C2 Enable Mouse, no far call handler\n"); SET_CF(); // error regs.u.r8.ah = 5; // no far call installed return; } inhibit_mouse_int_and_events(); // disable IRQ12 and packets ret = send_to_mouse_ctrl(0xF4); // enable mouse command if (ret == 0) { ret = get_mouse_data(&mouse_data1); if ( (ret == 0) && (mouse_data1 == 0xFA) ) { enable_mouse_int_and_events(); // turn IRQ12 and packet generation on CLEAR_CF(); regs.u.r8.ah = 0; return; } } SET_CF(); regs.u.r8.ah = ret; return; default: // invalid subfunction BX_DEBUG_INT15("INT 15h C2 AL=0, BH=%02x\n", (unsigned) regs.u.r8.bh); SET_CF(); // error regs.u.r8.ah = 1; // invalid subfunction return; } break; case 1: // Reset Mouse case 5: // Initialize Mouse BX_DEBUG_INT15("case 1 or 5:\n"); if (regs.u.r8.al == 5) { if (regs.u.r8.bh != 3) { SET_CF(); regs.u.r8.ah = 0x02; // invalid input return; } mouse_flags_2 = read_byte(&EbdaData->mouse_flag2, ebda_seg); mouse_flags_2 = (mouse_flags_2 & 0xF8) | regs.u.r8.bh - 1; mouse_flags_1 = 0x00; write_byte(mouse_flags_1, &EbdaData->mouse_flag1, ebda_seg); write_byte(mouse_flags_2, &EbdaData->mouse_flag2, ebda_seg); } inhibit_mouse_int_and_events(); // disable IRQ12 and packets ret = send_to_mouse_ctrl(0xFF); // reset mouse command if (ret == 0) { ret = get_mouse_data(&mouse_data3); // if no mouse attached, it will return RESEND if (mouse_data3 == 0xfe) { SET_CF(); return; } if (mouse_data3 != 0xfa) BX_PANIC("Mouse reset returned %02x (should be ack)\n", (unsigned)mouse_data3); if ( ret == 0 ) { ret = get_mouse_data(&mouse_data1); if ( ret == 0 ) { ret = get_mouse_data(&mouse_data2); if ( ret == 0 ) { // turn IRQ12 and packet generation on enable_mouse_int_and_events(); CLEAR_CF(); regs.u.r8.ah = 0; regs.u.r8.bl = mouse_data1; regs.u.r8.bh = mouse_data2; return; } } } } // error SET_CF(); regs.u.r8.ah = ret; return; case 2: // Set Sample Rate BX_DEBUG_INT15("case 2:\n"); switch (regs.u.r8.bh) { case 0: mouse_data1 = 10; break; // 10 reports/sec case 1: mouse_data1 = 20; break; // 20 reports/sec case 2: mouse_data1 = 40; break; // 40 reports/sec case 3: mouse_data1 = 60; break; // 60 reports/sec case 4: mouse_data1 = 80; break; // 80 reports/sec case 5: mouse_data1 = 100; break; // 100 reports/sec (default) case 6: mouse_data1 = 200; break; // 200 reports/sec default: mouse_data1 = 0; } if (mouse_data1 > 0) { ret = send_to_mouse_ctrl(0xF3); // set sample rate command if (ret == 0) { ret = get_mouse_data(&mouse_data2); ret = send_to_mouse_ctrl(mouse_data1); ret = get_mouse_data(&mouse_data2); CLEAR_CF(); regs.u.r8.ah = 0; } else { // error SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } } else { // error SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } break; case 3: // Set Resolution BX_DEBUG_INT15("case 3:\n"); // BH: // 0 = 25 dpi, 1 count per millimeter // 1 = 50 dpi, 2 counts per millimeter // 2 = 100 dpi, 4 counts per millimeter // 3 = 200 dpi, 8 counts per millimeter comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets if (regs.u.r8.bh < 4) { ret = send_to_mouse_ctrl(0xE8); // set resolution command if (ret == 0) { ret = get_mouse_data(&mouse_data1); if (mouse_data1 != 0xfa) BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); ret = send_to_mouse_ctrl(regs.u.r8.bh); ret = get_mouse_data(&mouse_data1); if (mouse_data1 != 0xfa) BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); CLEAR_CF(); regs.u.r8.ah = 0; } else { // error SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } } else { // error SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable break; case 4: // Get Device ID BX_DEBUG_INT15("case 4:\n"); inhibit_mouse_int_and_events(); // disable IRQ12 and packets ret = send_to_mouse_ctrl(0xF2); // get mouse ID command if (ret == 0) { ret = get_mouse_data(&mouse_data1); ret = get_mouse_data(&mouse_data2); CLEAR_CF(); regs.u.r8.ah = 0; regs.u.r8.bh = mouse_data2; } else { // error SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } break; case 6: // Return Status & Set Scaling Factor... BX_DEBUG_INT15("case 6:\n"); switch (regs.u.r8.bh) { case 0: // Return Status comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets ret = send_to_mouse_ctrl(0xE9); // get mouse info command if (ret == 0) { ret = get_mouse_data(&mouse_data1); if (mouse_data1 != 0xfa) BX_PANIC("Mouse status returned %02x (should be ack)\n", (unsigned)mouse_data1); if (ret == 0) { ret = get_mouse_data(&mouse_data1); if (ret == 0) { ret = get_mouse_data(&mouse_data2); if (ret == 0) { ret = get_mouse_data(&mouse_data3); if (ret == 0) { CLEAR_CF(); regs.u.r8.ah = 0; regs.u.r8.bl = mouse_data1; regs.u.r8.cl = mouse_data2; regs.u.r8.dl = mouse_data3; set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable return; } } } } } // error SET_CF(); regs.u.r8.ah = ret; set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable return; case 1: // Set Scaling Factor to 1:1 case 2: // Set Scaling Factor to 2:1 comm_byte = inhibit_mouse_int_and_events(); // disable IRQ12 and packets if (regs.u.r8.bh == 1) { ret = send_to_mouse_ctrl(0xE6); } else { ret = send_to_mouse_ctrl(0xE7); } if (ret == 0) { get_mouse_data(&mouse_data1); ret = (mouse_data1 != 0xFA); } if (ret == 0) { CLEAR_CF(); regs.u.r8.ah = 0; } else { // error SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; } set_kbd_command_byte(comm_byte); // restore IRQ12 and serial enable break; default: BX_PANIC("INT 15h C2 AL=6, BH=%02x\n", (unsigned) regs.u.r8.bh); } break; case 7: // Set Mouse Handler Address BX_DEBUG_INT15("case 7:\n"); mouse_driver_seg = ES; mouse_driver_offset = regs.u.r16.bx; write_word(mouse_driver_offset, &EbdaData->mouse_driver_offset, ebda_seg); write_word(mouse_driver_seg, &EbdaData->mouse_driver_seg, ebda_seg); mouse_flags_2 = read_byte(&EbdaData->mouse_flag2, ebda_seg); if (mouse_driver_offset == 0 && mouse_driver_seg == 0) { /* remove handler */ if ( (mouse_flags_2 & 0x80) != 0 ) { mouse_flags_2 &= ~0x80; inhibit_mouse_int_and_events(); // disable IRQ12 and packets } } else { /* install handler */ mouse_flags_2 |= 0x80; } write_byte(mouse_flags_2, &EbdaData->mouse_flag2, ebda_seg); CLEAR_CF(); regs.u.r8.ah = 0; break; default: BX_DEBUG_INT15("case default:\n"); regs.u.r8.ah = 1; // invalid function SET_CF(); } break; default: BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; } } #endif // BX_USE_PS2_MOUSE void set_e820_range(ES, DI, start, end, extra_start, extra_end, type) Bit16u ES; Bit16u DI; Bit32u start; Bit32u end; Bit8u extra_start; Bit8u extra_end; Bit16u type; { Bit16u old_ds = set_DS(ES); write_dword_DS(DI, start); write_word_DS(DI+4, extra_start); write_word_DS(DI+6, 0x00); end -= start; extra_end -= extra_start; write_dword_DS(DI+8, end); write_word_DS(DI+12, extra_end); write_word_DS(DI+14, 0x0000); write_word_DS(DI+16, type); write_word_DS(DI+18, 0x0); set_DS(old_ds); } void int15_function32(regs, ES, DS, FLAGS) pushad_regs_t regs; // REGS pushed via pushad Bit16u ES, DS, FLAGS; { Bit32u extended_memory_size=0; // 64bits long Bit32u extra_lowbits_memory_size=0; Bit16u CX,DX; Bit8u extra_highbits_memory_size=0; BX_DEBUG_INT15("int15 AX=%04x\n",regs.u.r16.ax); switch (regs.u.r8.ah) { case 0x86: // Wait for CX:DX microseconds. currently using the // refresh request port 0x61 bit4, toggling every 15usec CX = regs.u.r16.cx; DX = regs.u.r16.dx; ASM_START sti ;; Get the count in eax mov bx, sp SEG SS mov ax, _int15_function32.CX [bx] shl eax, #16 SEG SS mov ax, _int15_function32.DX [bx] ;; convert to numbers of 15usec ticks mov ebx, #15 xor edx, edx div eax, ebx mov ecx, eax ;; wait for ecx number of refresh requests in al, PORT_PS2_CTRLB and al,#0x10 mov ah, al or ecx, ecx je int1586_tick_end int1586_tick: in al, PORT_PS2_CTRLB and al,#0x10 cmp al, ah je int1586_tick mov ah, al dec ecx jnz int1586_tick int1586_tick_end: ASM_END break; case 0xe8: switch(regs.u.r8.al) { case 0x20: // coded by osmaker aka K.J. if(regs.u.r32.edx == 0x534D4150) { extended_memory_size = inb_cmos(0x35); extended_memory_size <<= 8; extended_memory_size |= inb_cmos(0x34); extended_memory_size *= 64; if(extended_memory_size > 0x2fc000) { extended_memory_size = 0x2fc000; // everything after this is reserved memory until we get to 0x100000000 } extended_memory_size *= 1024; extended_memory_size += (16L * 1024 * 1024); if(extended_memory_size <= (16L * 1024 * 1024)) { extended_memory_size = inb_cmos(0x31); extended_memory_size <<= 8; extended_memory_size |= inb_cmos(0x30); extended_memory_size *= 1024; extended_memory_size += (1L * 1024 * 1024); } extra_lowbits_memory_size = inb_cmos(0x5c); extra_lowbits_memory_size <<= 8; extra_lowbits_memory_size |= inb_cmos(0x5b); extra_lowbits_memory_size *= 64; extra_lowbits_memory_size *= 1024; extra_highbits_memory_size = inb_cmos(0x5d); switch(regs.u.r16.bx) { case 0: set_e820_range(ES, regs.u.r16.di, 0x0000000L, 0x0009f000L, 0, 0, E820_RAM); regs.u.r32.ebx = 1; break; case 1: set_e820_range(ES, regs.u.r16.di, 0x0009f000L, 0x000a0000L, 0, 0, E820_RESERVED); regs.u.r32.ebx = 2; break; case 2: set_e820_range(ES, regs.u.r16.di, 0x000e8000L, 0x00100000L, 0, 0, E820_RESERVED); if (extended_memory_size <= 0x100000) regs.u.r32.ebx = 6; else regs.u.r32.ebx = 3; break; case 3: #if BX_ROMBIOS32 #ifdef BX_USE_EBDA_TABLES set_e820_range(ES, regs.u.r16.di, 0x00100000L, extended_memory_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE, 0, 0, E820_RAM); regs.u.r32.ebx = 4; #else set_e820_range(ES, regs.u.r16.di, 0x00100000L, extended_memory_size - ACPI_DATA_SIZE, 0, 0, E820_RAM); regs.u.r32.ebx = 5; #endif #else set_e820_range(ES, regs.u.r16.di, 0x00100000L, extended_memory_size, 0, 0, E820_RAM); regs.u.r32.ebx = 6; #endif break; case 4: set_e820_range(ES, regs.u.r16.di, extended_memory_size - ACPI_DATA_SIZE - MPTABLE_MAX_SIZE, extended_memory_size - ACPI_DATA_SIZE, 0, 0, E820_RESERVED); regs.u.r32.ebx = 5; break; case 5: set_e820_range(ES, regs.u.r16.di, extended_memory_size - ACPI_DATA_SIZE, extended_memory_size, 0, 0, E820_ACPI); regs.u.r32.ebx = 6; break; case 6: /* 256KB BIOS area at the end of 4 GB */ set_e820_range(ES, regs.u.r16.di, 0xfffc0000L, 0x00000000L, 0, 0, E820_RESERVED); if (extra_highbits_memory_size || extra_lowbits_memory_size) regs.u.r32.ebx = 7; else regs.u.r32.ebx = 0; break; case 7: /* Mapping of memory above 4 GB */ set_e820_range(ES, regs.u.r16.di, 0x00000000L, extra_lowbits_memory_size, 1, extra_highbits_memory_size + 1, E820_RAM); regs.u.r32.ebx = 0; break; default: /* AX=E820, DX=534D4150, BX unrecognized */ goto int15_unimplemented; break; } regs.u.r32.eax = 0x534D4150; regs.u.r32.ecx = 0x14; CLEAR_CF(); } else { // if DX != 0x534D4150) goto int15_unimplemented; } break; case 0x01: // do we have any reason to fail here ? CLEAR_CF(); // my real system sets ax and bx to 0 // this is confirmed by Ralph Brown list // but syslinux v1.48 is known to behave // strangely if ax is set to 0 // regs.u.r16.ax = 0; // regs.u.r16.bx = 0; // Get the amount of extended memory (above 1M) regs.u.r8.cl = inb_cmos(0x30); regs.u.r8.ch = inb_cmos(0x31); // limit to 15M if(regs.u.r16.cx > 0x3c00) { regs.u.r16.cx = 0x3c00; } // Get the amount of extended memory above 16M in 64k blocs regs.u.r8.dl = inb_cmos(0x34); regs.u.r8.dh = inb_cmos(0x35); // Set configured memory equal to extended memory regs.u.r16.ax = regs.u.r16.cx; regs.u.r16.bx = regs.u.r16.dx; break; default: /* AH=0xE8?? but not implemented */ goto int15_unimplemented; } break; int15_unimplemented: // fall into the default default: BX_INFO("*** int 15h function AX=%04x, BX=%04x not yet supported!\n", (unsigned) regs.u.r16.ax, (unsigned) regs.u.r16.bx); SET_CF(); regs.u.r8.ah = UNSUPPORTED_FUNCTION; break; } } void int16_function(DI, SI, BP, SP, BX, DX, CX, AX, FLAGS) Bit16u DI, SI, BP, SP, BX, DX, CX, AX, FLAGS; { Bit8u scan_code, ascii_code, shift_flags, led_flags, count; Bit16u kbd_code, max; // // DS has been set to 0x40 before call // BX_DEBUG_INT16("int16: AX=%04x BX=%04x CX=%04x DX=%04x \n", AX, BX, CX, DX); shift_flags = read_byte_DS(0x17); led_flags = read_byte_DS(0x97); if ((((shift_flags >> 4) & 0x07) ^ (led_flags & 0x07)) != 0) { ASM_START cli ASM_END outb(PORT_PS2_DATA, 0xed); while ((inb(PORT_PS2_STATUS) & 0x01) == 0) outb(PORT_DIAG, 0x21); if ((inb(PORT_PS2_DATA) == 0xfa)) { led_flags &= 0xf8; led_flags |= ((shift_flags >> 4) & 0x07); outb(PORT_PS2_DATA, led_flags & 0x07); while ((inb(PORT_PS2_STATUS) & 0x01) == 0) outb(PORT_DIAG, 0x21); inb(PORT_PS2_DATA); write_byte_DS(0x97, led_flags); } ASM_START sti ASM_END } switch (GET_AH()) { case 0x00: /* read keyboard input */ if ( !dequeue_key(&scan_code, &ascii_code, 1) ) { BX_PANIC("KBD: int16h: out of keyboard input\n"); } if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; else if (ascii_code == 0xE0) ascii_code = 0; AX = (scan_code << 8) | ascii_code; break; case 0x01: /* check keyboard status */ if ( !dequeue_key(&scan_code, &ascii_code, 0) ) { SET_ZF(); return; } if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; else if (ascii_code == 0xE0) ascii_code = 0; AX = (scan_code << 8) | ascii_code; CLEAR_ZF(); break; case 0x02: /* get shift flag status */ shift_flags = read_byte_DS(0x17); SET_AL(shift_flags); break; case 0x05: /* store key-stroke into buffer */ if ( !enqueue_key(GET_CH(), GET_CL()) ) { SET_AL(1); } else { SET_AL(0); } break; case 0x09: /* GET KEYBOARD FUNCTIONALITY */ // bit Bochs Description // 7 0 reserved // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support) // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support) // 4 1 INT 16/AH=0Ah supported // 3 0 INT 16/AX=0306h supported // 2 0 INT 16/AX=0305h supported // 1 0 INT 16/AX=0304h supported // 0 0 INT 16/AX=0300h supported // SET_AL(0x30); break; case 0x0A: /* GET KEYBOARD ID */ count = 2; kbd_code = 0x0; outb(PORT_PS2_DATA, 0xf2); /* Wait for data */ max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x00); if (max>0x0) { if ((inb(PORT_PS2_DATA) == 0xfa)) { do { max=0xffff; while ( ((inb(PORT_PS2_STATUS) & 0x01) == 0) && (--max>0) ) outb(PORT_DIAG, 0x00); if (max>0x0) { kbd_code >>= 8; kbd_code |= (inb(PORT_PS2_DATA) << 8); } } while (--count>0); } } BX=kbd_code; break; case 0x10: /* read MF-II keyboard input */ if ( !dequeue_key(&scan_code, &ascii_code, 1) ) { BX_PANIC("KBD: int16h: out of keyboard input\n"); } if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; AX = (scan_code << 8) | ascii_code; break; case 0x11: /* check MF-II keyboard status */ if ( !dequeue_key(&scan_code, &ascii_code, 0) ) { SET_ZF(); return; } if (scan_code !=0 && ascii_code == 0xF0) ascii_code = 0; AX = (scan_code << 8) | ascii_code; CLEAR_ZF(); break; case 0x12: /* get extended keyboard status */ shift_flags = read_byte_DS(0x17); SET_AL(shift_flags); shift_flags = read_byte_DS(0x18) & 0x73; shift_flags |= read_byte_DS(0x96) & 0x0c; SET_AH(shift_flags); BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX); break; case 0x92: /* keyboard capability check called by DOS 5.0+ keyb */ SET_AH(0x80); // function int16 ah=0x10-0x12 supported break; case 0xA2: /* 122 keys capability check called by DOS 5.0+ keyb */ // don't change AH : function int16 ah=0x20-0x22 NOT supported break; case 0x6F: if (GET_AL() == 0x08) SET_AH(0x02); // unsupported, aka normal keyboard default: BX_INFO("KBD: unsupported int 16h function %02x\n", GET_AH()); } } unsigned int dequeue_key(scan_code, ascii_code, incr) Bit8u *scan_code; Bit8u *ascii_code; unsigned int incr; { Bit16u buffer_start, buffer_end, buffer_head, buffer_tail; Bit8u acode, scode; // DS is already set to 0x40 at int16 handler buffer_start = read_word_DS(0x0080); buffer_end = read_word_DS(0x0082); buffer_head = read_word_DS(0x001a); buffer_tail = read_word_DS(0x001c); if (buffer_head != buffer_tail) { acode = read_byte_DS(buffer_head); scode = read_byte_DS(buffer_head+1); write_byte_SS(acode, ascii_code); write_byte_SS(scode, scan_code); if (incr) { buffer_head += 2; if (buffer_head >= buffer_end) buffer_head = buffer_start; write_word_DS(0x001a, buffer_head); } return(1); } else { return(0); } } static char panic_msg_keyb_buffer_full[] = "%s: keyboard input buffer full\n"; Bit8u inhibit_mouse_int_and_events() { Bit8u command_byte, prev_command_byte; // Turn off IRQ generation and aux data line if ( inb(PORT_PS2_STATUS) & 0x02 ) BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse"); outb(PORT_PS2_STATUS, 0x20); // get command byte while ( (inb(PORT_PS2_STATUS) & 0x01) != 0x01 ); prev_command_byte = inb(PORT_PS2_DATA); command_byte = prev_command_byte; //while ( (inb(PORT_PS2_STATUS) & 0x02) ); if ( inb(PORT_PS2_STATUS) & 0x02 ) BX_PANIC(panic_msg_keyb_buffer_full,"inhibmouse"); command_byte &= 0xfd; // turn off IRQ 12 generation command_byte |= 0x20; // disable mouse serial clock line outb(PORT_PS2_STATUS, 0x60); // write command byte outb(PORT_PS2_DATA, command_byte); return(prev_command_byte); } void enable_mouse_int_and_events() { Bit8u command_byte; // Turn on IRQ generation and aux data line if ( inb(PORT_PS2_STATUS) & 0x02 ) BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse"); outb(PORT_PS2_STATUS, 0x20); // get command byte while ( (inb(PORT_PS2_STATUS) & 0x01) != 0x01 ); command_byte = inb(PORT_PS2_DATA); //while ( (inb(PORT_PS2_STATUS) & 0x02) ); if ( inb(PORT_PS2_STATUS) & 0x02 ) BX_PANIC(panic_msg_keyb_buffer_full,"enabmouse"); command_byte |= 0x02; // turn on IRQ 12 generation command_byte &= 0xdf; // enable mouse serial clock line outb(PORT_PS2_STATUS, 0x60); // write command byte outb(PORT_PS2_DATA, command_byte); } Bit8u send_to_mouse_ctrl(sendbyte) Bit8u sendbyte; { Bit8u response; // wait for chance to write to ctrl if ( inb(PORT_PS2_STATUS) & 0x02 ) BX_PANIC(panic_msg_keyb_buffer_full,"sendmouse"); outb(PORT_PS2_STATUS, 0xD4); outb(PORT_PS2_DATA, sendbyte); return(0); } Bit8u get_mouse_data(data) Bit8u *data; { Bit8u response; while ((inb(PORT_PS2_STATUS) & 0x21) != 0x21) { } response = inb(PORT_PS2_DATA); write_byte_SS(response, data); return(0); } void set_kbd_command_byte(command_byte) Bit8u command_byte; { if ( inb(PORT_PS2_STATUS) & 0x02 ) BX_PANIC(panic_msg_keyb_buffer_full,"setkbdcomm"); outb(PORT_PS2_STATUS, 0xD4); outb(PORT_PS2_STATUS, 0x60); // write command byte outb(PORT_PS2_DATA, command_byte); } void int09_function(DI, SI, BP, SP, BX, DX, CX, AX) Bit16u DI, SI, BP, SP, BX, DX, CX, AX; { Bit8u scancode, asciicode, shift_flags; Bit8u mf2_flags, mf2_state; // // DS has been set to 0x40 before call // scancode = GET_AL(); if (scancode == 0) { BX_INFO("KBD: int09 handler: AL=0\n"); return; } shift_flags = read_byte_DS(0x17); mf2_flags = read_byte_DS(0x18); mf2_state = read_byte_DS(0x96); asciicode = 0; switch (scancode) { case 0x3a: /* Caps Lock press */ shift_flags ^= 0x40; write_byte_DS(0x17, shift_flags); mf2_flags |= 0x40; write_byte_DS(0x18, mf2_flags); break; case 0xba: /* Caps Lock release */ mf2_flags &= ~0x40; write_byte_DS(0x18, mf2_flags); break; case 0x2a: /* L Shift press */ shift_flags |= 0x02; write_byte_DS(0x17, shift_flags); break; case 0xaa: /* L Shift release */ shift_flags &= ~0x02; write_byte_DS(0x17, shift_flags); break; case 0x36: /* R Shift press */ shift_flags |= 0x01; write_byte_DS(0x17, shift_flags); break; case 0xb6: /* R Shift release */ shift_flags &= ~0x01; write_byte_DS(0x17, shift_flags); break; case 0x1d: /* Ctrl press */ if ((mf2_state & 0x01) == 0) { shift_flags |= 0x04; write_byte_DS(0x17, shift_flags); if (mf2_state & 0x02) { mf2_state |= 0x04; write_byte_DS(0x96, mf2_state); } else { mf2_flags |= 0x01; write_byte_DS(0x18, mf2_flags); } } break; case 0x9d: /* Ctrl release */ if ((mf2_state & 0x01) == 0) { shift_flags &= ~0x04; write_byte_DS(0x17, shift_flags); if (mf2_state & 0x02) { mf2_state &= ~0x04; write_byte_DS(0x96, mf2_state); } else { mf2_flags &= ~0x01; write_byte_DS(0x18, mf2_flags); } } break; case 0x38: /* Alt press */ shift_flags |= 0x08; write_byte_DS(0x17, shift_flags); if (mf2_state & 0x02) { mf2_state |= 0x08; write_byte_DS(0x96, mf2_state); } else { mf2_flags |= 0x02; write_byte_DS(0x18, mf2_flags); } break; case 0xb8: /* Alt release */ shift_flags &= ~0x08; write_byte_DS(0x17, shift_flags); if (mf2_state & 0x02) { mf2_state &= ~0x08; write_byte_DS(0x96, mf2_state); } else { mf2_flags &= ~0x02; write_byte_DS(0x18, mf2_flags); } break; case 0x45: /* Num Lock press */ if ((mf2_state & 0x03) == 0) { mf2_flags |= 0x20; write_byte_DS(0x18, mf2_flags); shift_flags ^= 0x20; write_byte_DS(0x17, shift_flags); } break; case 0xc5: /* Num Lock release */ if ((mf2_state & 0x03) == 0) { mf2_flags &= ~0x20; write_byte_DS(0x18, mf2_flags); } break; case 0x46: /* Scroll Lock or Ctrl-Break press */ if ((mf2_state & 0x02) || (!(mf2_state & 0x10) && (shift_flags & 0x04))) { /* Ctrl-Break press */ mf2_state &= ~0x02; write_byte_DS(0x96, mf2_state); write_byte_DS(0x71, 0x80); write_word_DS(0x001C, read_word_DS(0x001A)); ASM_START int #0x1B ASM_END enqueue_key(0, 0); } else { /* Scroll Lock press */ mf2_flags |= 0x10; write_byte_DS(0x18, mf2_flags); shift_flags ^= 0x10; write_byte_DS(0x17, shift_flags); } break; case 0xc6: /* Scroll Lock or Ctrl-Break release */ if ((mf2_state & 0x02) || (!(mf2_state & 0x10) && (shift_flags & 0x04))) { /* Ctrl-Break release */ /* nothing to do */ } else { /* Scroll Lock release */ mf2_flags &= ~0x10; write_byte_DS(0x18, mf2_flags); } break; default: if (scancode & 0x80) { break; /* toss key releases ... */ } if (scancode > MAX_SCAN_CODE) { BX_INFO("KBD: int09h_handler(): unknown scancode read: 0x%02x!\n", scancode); return; } if (scancode == 0x53) { /* DEL */ if ((shift_flags & 0x0f) == 0x0c) { /* CTRL+ALT */ write_word_DS(0x0072, 0x1234); ASM_START jmp 0xf000:post; ASM_END } } // // Set DS to CS here to get ascii code & scan code // set_DS(get_CS()); if (shift_flags & 0x08) { /* ALT */ asciicode = scan_to_scanascii[scancode].alt; scancode = scan_to_scanascii[scancode].alt >> 8; } else if (shift_flags & 0x04) { /* CONTROL */ asciicode = scan_to_scanascii[scancode].control; scancode = scan_to_scanascii[scancode].control >> 8; } else if (((mf2_state & 0x02) > 0) && ((scancode >= 0x47) && (scancode <= 0x53))) { /* extended keys handling */ asciicode = 0xe0; scancode = scan_to_scanascii[scancode].normal >> 8; } else if (shift_flags & 0x03) { /* LSHIFT + RSHIFT */ /* check if lock state should be ignored * because a SHIFT key are pressed */ if (shift_flags & scan_to_scanascii[scancode].lock_flags) { asciicode = scan_to_scanascii[scancode].normal; scancode = scan_to_scanascii[scancode].normal >> 8; } else { asciicode = scan_to_scanascii[scancode].shift; scancode = scan_to_scanascii[scancode].shift >> 8; } } else { /* check if lock is on */ if (shift_flags & scan_to_scanascii[scancode].lock_flags) { asciicode = scan_to_scanascii[scancode].shift; scancode = scan_to_scanascii[scancode].shift >> 8; } else { asciicode = scan_to_scanascii[scancode].normal; scancode = scan_to_scanascii[scancode].normal >> 8; } } // // Set DS back to 0x40 // set_DS(0x40); if (scancode==0 && asciicode==0) { BX_INFO("KBD: int09h_handler(): scancode & asciicode are zero?\n"); } enqueue_key(scancode, asciicode); break; } if ((scancode & 0x7f) != 0x1d) { mf2_state &= ~0x01; } mf2_state &= ~0x02; write_byte_DS(0x96, mf2_state); } unsigned int enqueue_key(scan_code, ascii_code) Bit8u scan_code, ascii_code; { Bit16u buffer_start, buffer_end, buffer_head, buffer_tail, temp_tail, old_ds; // Set DS to 0x40 old_ds = set_DS(0x40); buffer_start = read_word_DS(0x0080); buffer_end = read_word_DS(0x0082); buffer_head = read_word_DS(0x001A); buffer_tail = read_word_DS(0x001C); temp_tail = buffer_tail; buffer_tail += 2; if (buffer_tail >= buffer_end) buffer_tail = buffer_start; if (buffer_tail == buffer_head) { set_DS(old_ds); return(0); } write_byte_DS(temp_tail, ascii_code); write_byte_DS(temp_tail+1, scan_code); write_word_DS(0x001C, buffer_tail); set_DS(old_ds); return(1); } void int74_function(make_farcall, Z, Y, X, status) Bit16u make_farcall, Z, Y, X, status; { Bit8u in_byte, index, package_count; Bit8u mouse_flags_1, mouse_flags_2; // // DS has been set to EBDA segment before call // BX_DEBUG_INT74("entering int74_function\n"); make_farcall = 0; in_byte = inb(PORT_PS2_STATUS); if ((in_byte & 0x21) != 0x21) { return; } in_byte = inb(PORT_PS2_DATA); BX_DEBUG_INT74("int74: read byte %02x\n", in_byte); mouse_flags_1 = read_byte_DS(&EbdaData->mouse_flag1); mouse_flags_2 = read_byte_DS(&EbdaData->mouse_flag2); if ((mouse_flags_2 & 0x80) != 0x80) { return; } package_count = mouse_flags_2 & 0x07; index = mouse_flags_1 & 0x07; write_byte_DS(&EbdaData->mouse_data[index], in_byte); if (index >= package_count) { BX_DEBUG_INT74("int74_function: make_farcall=1\n"); status = read_byte_DS(&EbdaData->mouse_data[0]); X = read_byte_DS(&EbdaData->mouse_data[1]); Y = read_byte_DS(&EbdaData->mouse_data[2]); Z = 0; mouse_flags_1 = 0; // check if far call handler installed if (mouse_flags_2 & 0x80) make_farcall = 1; } else { mouse_flags_1++; } write_byte_DS(&EbdaData->mouse_flag1, mouse_flags_1); } #define SET_DISK_RET_STATUS(status) write_byte(status, 0x0074, 0x0040) #if BX_USE_ATADRV int int13_edd(DS, SI, device) Bit16u DS, SI; Bit8u device; { Bit32u lba_low, lba_high; Bit16u npc, nph, npspt, size, t13; Bit16u ebda_seg=read_word(0x000E,0x0040); // // DS has been set to EBDA segment before call // Bit8u type=read_byte_DS(&EbdaData->ata.devices[device].type); size=read_word(SI+(Bit16u)&Int13DPT->size,DS); t13 = size == 74; // Buffer is too small if(size < 26) return 1; // EDD 1.x if(size >= 26) { Bit16u blksize, infos; write_word(26, SI+(Bit16u)&Int13DPT->size, DS); blksize = read_word_DS(&EbdaData->ata.devices[device].blksize); if (type == ATA_TYPE_ATA) { npc = read_word_DS(&EbdaData->ata.devices[device].pchs.cylinders); nph = read_word_DS(&EbdaData->ata.devices[device].pchs.heads); npspt = read_word_DS(&EbdaData->ata.devices[device].pchs.spt); lba_low = read_dword_DS(&EbdaData->ata.devices[device].sectors_low); lba_high = read_dword_DS(&EbdaData->ata.devices[device].sectors_high); if (lba_high || (lba_low/npspt)/nph > 0x3fff) { infos = 0 << 1; // geometry is invalid npc = 0x3fff; } else { infos = 1 << 1; // geometry is valid } } if (type == ATA_TYPE_ATAPI) { npc = 0xffffffff; nph = 0xffffffff; npspt = 0xffffffff; lba_low = 0xffffffff; lba_high = 0xffffffff; infos = 1 << 2 /* removable */ | 1 << 4 /* media change */ | 1 << 5 /* lockable */ | 1 << 6; /* max values */ } write_word(infos, SI+(Bit16u)&Int13DPT->infos, DS); write_dword((Bit32u)npc, SI+(Bit16u)&Int13DPT->cylinders, DS); write_dword((Bit32u)nph, SI+(Bit16u)&Int13DPT->heads, DS); write_dword((Bit32u)npspt, SI+(Bit16u)&Int13DPT->spt, DS); write_dword(lba_low, SI+(Bit16u)&Int13DPT->sector_count1, DS); write_dword(lba_high, SI+(Bit16u)&Int13DPT->sector_count2, DS); write_word(blksize, SI+(Bit16u)&Int13DPT->blksize, DS); } // EDD 2.x if(size >= 30) { Bit8u channel, dev, irq, mode, checksum, i, translation; Bit16u iobase1, iobase2, options; write_word(30, SI+(Bit16u)&Int13DPT->size, DS); write_word(ebda_seg, SI+(Bit16u)&Int13DPT->dpte_segment, DS); write_word(&EbdaData->ata.dpte, SI+(Bit16u)&Int13DPT->dpte_offset, DS); // Fill in dpte channel = device / 2; iobase1 = read_word_DS(&EbdaData->ata.channels[channel].iobase1); iobase2 = read_word_DS(&EbdaData->ata.channels[channel].iobase2); irq = read_byte_DS(&EbdaData->ata.channels[channel].irq); mode = read_byte_DS(&EbdaData->ata.devices[device].mode); translation = read_byte_DS(&EbdaData->ata.devices[device].translation); options = (1<<4); // lba translation options |= (mode==ATA_MODE_PIO32?1:0)<<7; if (type == ATA_TYPE_ATA) { options |= (translation==ATA_TRANSLATION_NONE?0:1)<<3; // chs translation options |= (translation==ATA_TRANSLATION_LBA?1:0)<<9; options |= (translation==ATA_TRANSLATION_RECHS?3:0)<<9; } if (type == ATA_TYPE_ATAPI) { options |= (1<<5); // removable device options |= (1<<6); // atapi device } write_word_DS(&EbdaData->ata.dpte.iobase1, iobase1); write_word_DS(&EbdaData->ata.dpte.iobase2, iobase2 + ATA_CB_DC); write_byte_DS(&EbdaData->ata.dpte.prefix, (0xe | (device % 2))<<4 ); write_byte_DS(&EbdaData->ata.dpte.unused, 0xcb ); write_byte_DS(&EbdaData->ata.dpte.irq, irq ); write_byte_DS(&EbdaData->ata.dpte.blkcount, 1 ); write_byte_DS(&EbdaData->ata.dpte.dma, 0 ); write_byte_DS(&EbdaData->ata.dpte.pio, 0 ); write_word_DS(&EbdaData->ata.dpte.options, options); write_word_DS(&EbdaData->ata.dpte.reserved, 0); write_byte_DS(&EbdaData->ata.dpte.revision, 0x11); checksum=0; for (i=0; i<15; i++) checksum+=read_byte_DS(((Bit8u*)(&EbdaData->ata.dpte)) + i); checksum = -checksum; write_byte_DS(&EbdaData->ata.dpte.checksum, checksum); } // EDD 3.x if(size >= 66) { Bit8u channel, iface, checksum, i; Bit16u iobase1; channel = device / 2; iface = read_byte_DS(&EbdaData->ata.channels[channel].iface); iobase1 = read_word_DS(&EbdaData->ata.channels[channel].iobase1); // Set DS to original DS register value set_DS(DS); write_word_DS(SI+(Bit16u)&Int13DPT->dpi.t13.key, 0xbedd); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.dpi_length, t13 ? 44 : 36); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.reserved1, 0); write_word_DS(SI+(Bit16u)&Int13DPT->dpi.t13.reserved2, 0); if (iface==ATA_IFACE_ISA) { write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.host_bus[0], 'I'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.host_bus[1], 'S'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.host_bus[2], 'A'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.host_bus[3], ' '); } else { // FIXME PCI } if (type == ATA_TYPE_ATA) { write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[0], 'A'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[1], 'T'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[2], 'A'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[3], ' '); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[4], ' '); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[5], ' '); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[6], ' '); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[7], ' '); } else if (type == ATA_TYPE_ATAPI) { write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[0], 'A'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[1], 'T'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[2], 'A'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[3], 'P'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[4], 'I'); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[5], ' '); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[6], ' '); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_type[7], ' '); } if (iface==ATA_IFACE_ISA) { write_word_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_path[0], iobase1); write_word_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_path[2], 0); write_dword_DS(SI+(Bit16u)&Int13DPT->dpi.t13.iface_path[4], 0L); } else { // FIXME PCI } write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.device_path[0], device%2); write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.device_path[1], 0); write_word_DS(SI+(Bit16u)&Int13DPT->dpi.t13.device_path[2], 0); write_dword_DS(SI+(Bit16u)&Int13DPT->dpi.t13.device_path[4], 0L); if (t13) { write_dword_DS(SI+(Bit16u)&Int13DPT->dpi.t13.device_path[8], 0L); write_dword_DS(SI+(Bit16u)&Int13DPT->dpi.t13.device_path[12], 0L); } if (t13) write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.reserved3, 0); else write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.phoenix.reserved3, 0); checksum = 0; for (i = 30; i < (t13 ? 73 : 65); i++) checksum += read_byte_DS(SI + i); checksum = -checksum; if (t13) write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.t13.checksum, checksum); else write_byte_DS(SI+(Bit16u)&Int13DPT->dpi.phoenix.checksum, checksum); } return 0; } void int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; { Bit32u lba_low, lba_high; Bit16u cylinder, head, sector; Bit16u segment, offset; Bit16u npc, nph, npspt, nlc, nlh, nlspt; Bit16u size, count; Bit8u device, status; // // DS has been set to EBDA segment before call // BX_DEBUG_INT13_HD("int13_harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); write_byte(0, 0x008e, 0x0040); // clear completion flag // basic check : device has to be defined if ( (GET_ELDL() < 0x80) || (GET_ELDL() >= 0x80 + BX_MAX_ATA_DEVICES) ) { BX_INFO("int13_harddisk: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL()); goto int13_fail; } // Get the ata channel device=read_byte_DS(&EbdaData->ata.hdidmap[GET_ELDL()-0x80]); // basic check : device has to be valid if (device >= BX_MAX_ATA_DEVICES) { BX_INFO("int13_harddisk: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); goto int13_fail; } switch (GET_AH()) { case 0x00: /* disk controller reset */ ata_reset (device); goto int13_success; break; case 0x01: /* read disk status */ status = read_byte(0x0074, 0x0040); SET_AH(status); SET_DISK_RET_STATUS(0); /* set CF if error status read */ if (status) goto int13_fail_nostatus; else goto int13_success_noah; break; case 0x02: // read disk sectors case 0x03: // write disk sectors case 0x04: // verify disk sectors count = GET_AL(); cylinder = GET_CH(); cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300; sector = (GET_CL() & 0x3f); head = GET_DH(); segment = ES; offset = BX; if ((count > 128) || (count == 0) || (sector == 0)) { BX_INFO("int13_harddisk: function %02x, parameter out of range!\n",GET_AH()); goto int13_fail; } nlc = read_word_DS(&EbdaData->ata.devices[device].lchs.cylinders); nlh = read_word_DS(&EbdaData->ata.devices[device].lchs.heads); nlspt = read_word_DS(&EbdaData->ata.devices[device].lchs.spt); // sanity check on cyl heads, sec if( (cylinder >= nlc) || (head >= nlh) || (sector > nlspt) ) { BX_INFO("int13_harddisk: function %02x, parameters out of range %04x/%04x/%04x!\n", GET_AH(), cylinder, head, sector); goto int13_fail; } // FIXME verify if (GET_AH() == 0x04) goto int13_success; nph = read_word_DS(&EbdaData->ata.devices[device].pchs.heads); npspt = read_word_DS(&EbdaData->ata.devices[device].pchs.spt); // if needed, translate lchs to lba, and execute command if ( (nph != nlh) || (npspt != nlspt)) { lba_low = ((((Bit32u)cylinder * (Bit32u)nlh) + (Bit32u)head) * (Bit32u)nlspt) + (Bit32u)sector - 1; lba_high = 0; sector = 0; // this forces the command to be lba } if (GET_AH() == 0x02) status=ata_cmd_data_io(0, device, ATA_CMD_READ_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset); else status=ata_cmd_data_io(1, device, ATA_CMD_WRITE_SECTORS, count, cylinder, head, sector, lba_low, lba_high, segment, offset); // Set nb of sector transferred SET_AL(read_word_DS(&EbdaData->ata.trsfsectors)); if (status != 0) { BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status); SET_AH(0x0c); goto int13_fail_noah; } goto int13_success; break; case 0x05: /* format disk track */ BX_INFO("format disk track called\n"); goto int13_success; return; break; case 0x08: /* read disk drive parameters */ // Get logical geometry from table nlc = read_word_DS(&EbdaData->ata.devices[device].lchs.cylinders); nlh = read_word_DS(&EbdaData->ata.devices[device].lchs.heads); nlspt = read_word_DS(&EbdaData->ata.devices[device].lchs.spt); count = read_byte_DS(&EbdaData->ata.hdcount); nlc = nlc - 1; /* 0 based */ SET_AL(0); SET_CH(nlc & 0xff); SET_CL(((nlc >> 2) & 0xc0) | (nlspt & 0x3f)); SET_DH(nlh - 1); SET_DL(count); /* FIXME returns 0, 1, or n hard drives */ // FIXME should set ES & DI goto int13_success; break; case 0x10: /* check drive ready */ // should look at 40:8E also??? // Read the status from controller status = inb(read_word_DS(&EbdaData->ata.channels[device/2].iobase1) + ATA_CB_STAT); if ( (status & (ATA_CB_STAT_BSY | ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY ) { goto int13_success; } else { SET_AH(0xAA); goto int13_fail_noah; } break; case 0x15: /* read disk drive size */ // Get logical geometry from table nlc = read_word_DS(&EbdaData->ata.devices[device].lchs.cylinders); nlh = read_word_DS(&EbdaData->ata.devices[device].lchs.heads); nlspt = read_word_DS(&EbdaData->ata.devices[device].lchs.spt); // Compute sector count seen by int13 lba_low = (Bit32u)(nlc - 1) * (Bit32u)nlh * (Bit32u)nlspt; CX = lba_low >> 16; DX = lba_low & 0xffff; SET_AH(3); // hard disk accessible goto int13_success_noah; break; case 0x41: // IBM/MS installation check BX=0xaa55; // install check SET_AH(0x30); // EDD 3.0 CX=0x0007; // ext disk access and edd, removable supported goto int13_success_noah; break; case 0x42: // IBM/MS extended read case 0x43: // IBM/MS extended write case 0x44: // IBM/MS verify case 0x47: // IBM/MS extended seek count=read_word(SI+(Bit16u)&Int13Ext->count, DS); segment=read_word(SI+(Bit16u)&Int13Ext->segment, DS); offset=read_word(SI+(Bit16u)&Int13Ext->offset, DS); // Get 32 msb lba and check lba_high=read_dword(SI+(Bit16u)&Int13Ext->lba2, DS); if (lba_high > read_dword_DS(&EbdaData->ata.devices[device].sectors_high) ) { BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH()); goto int13_fail; } // Get 32 lsb lba and check lba_low=read_dword(SI+(Bit16u)&Int13Ext->lba1, DS); if (lba_high == read_dword_DS(&EbdaData->ata.devices[device].sectors_high) && lba_low >= read_dword_DS(&EbdaData->ata.devices[device].sectors_low) ) { BX_INFO("int13_harddisk: function %02x. LBA out of range\n",GET_AH()); goto int13_fail; } // If verify or seek if (( GET_AH() == 0x44 ) || ( GET_AH() == 0x47 )) goto int13_success; // Execute the command if (GET_AH() == 0x42) status=ata_cmd_data_io(0, device, ATA_CMD_READ_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset); else status=ata_cmd_data_io(1, device, ATA_CMD_WRITE_SECTORS, count, 0, 0, 0, lba_low, lba_high, segment, offset); count=read_word_DS(&EbdaData->ata.trsfsectors); write_word(count, SI+(Bit16u)&Int13Ext->count, DS); if (status != 0) { BX_INFO("int13_harddisk: function %02x, error %02x !\n",GET_AH(),status); SET_AH(0x0c); goto int13_fail_noah; } goto int13_success; break; case 0x45: // IBM/MS lock/unlock drive case 0x49: // IBM/MS extended media change goto int13_success; // Always success for HD break; case 0x46: // IBM/MS eject media SET_AH(0xb2); // Volume Not Removable goto int13_fail_noah; // Always fail for HD break; case 0x48: // IBM/MS get drive parameters if (int13_edd(DS, SI, device)) goto int13_fail; goto int13_success; break; case 0x4e: // // IBM/MS set hardware configuration // DMA, prefetch, PIO maximum not supported switch (GET_AL()) { case 0x01: case 0x03: case 0x04: case 0x06: goto int13_success; break; default: goto int13_fail; } break; case 0x09: /* initialize drive parameters */ case 0x0c: /* seek to specified cylinder */ case 0x0d: /* alternate disk reset */ case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ BX_INFO("int13_harddisk: function %02xh unimplemented, returns success\n", GET_AH()); goto int13_success; break; case 0x0a: /* read disk sectors with ECC */ case 0x0b: /* write disk sectors with ECC */ case 0x18: // set media type for format case 0x50: // IBM/MS send packet command default: BX_INFO("int13_harddisk: function %02xh unsupported, returns fail\n", GET_AH()); goto int13_fail; break; } int13_fail: SET_AH(0x01); // defaults to invalid function in AH or invalid parameter int13_fail_noah: SET_DISK_RET_STATUS(GET_AH()); int13_fail_nostatus: SET_CF(); // error occurred return; int13_success: SET_AH(0x00); // no error int13_success_noah: SET_DISK_RET_STATUS(0x00); CLEAR_CF(); // no error } // --------------------------------------------------------------------------- // Start of int13 for cdrom // --------------------------------------------------------------------------- void int13_cdrom(EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u EHBX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; { Bit8u device, status, locks; Bit8u atacmd[12]; Bit32u lba; Bit16u count, segment, offset, i, size; // // DS has been set to EBDA segment before call // BX_DEBUG_INT13_CD("int13_cdrom: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); SET_DISK_RET_STATUS(0x00); /* basic check : device should be 0xE0+ */ if( (GET_ELDL() < 0xE0) || (GET_ELDL() >= 0xE0+BX_MAX_ATA_DEVICES) ) { BX_INFO("int13_cdrom: function %02x, ELDL out of range %02x\n", GET_AH(), GET_ELDL()); goto int13_fail; } // Get the ata channel device=read_byte_DS(&EbdaData->ata.cdidmap[GET_ELDL()-0xE0]); /* basic check : device has to be valid */ if (device >= BX_MAX_ATA_DEVICES) { BX_INFO("int13_cdrom: function %02x, unmapped device for ELDL=%02x\n", GET_AH(), GET_ELDL()); goto int13_fail; } switch (GET_AH()) { // all those functions return SUCCESS case 0x00: /* disk controller reset */ case 0x09: /* initialize drive parameters */ case 0x0c: /* seek to specified cylinder */ case 0x0d: /* alternate disk reset */ case 0x10: /* check drive ready */ case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ case 0x16: /* detect disk change */ goto int13_success; break; // all those functions return disk write-protected case 0x03: /* write disk sectors */ case 0x05: /* format disk track */ case 0x43: // IBM/MS extended write SET_AH(0x03); goto int13_fail_noah; break; case 0x01: /* read disk status */ status = read_byte(0x0074, 0x0040); SET_AH(status); SET_DISK_RET_STATUS(0); /* set CF if error status read */ if (status) goto int13_fail_nostatus; else goto int13_success_noah; break; case 0x15: /* read disk drive size */ SET_AH(0x02); goto int13_fail_noah; break; case 0x41: // IBM/MS installation check BX=0xaa55; // install check SET_AH(0x30); // EDD 2.1 CX=0x0007; // ext disk access, removable and edd goto int13_success_noah; break; case 0x42: // IBM/MS extended read case 0x44: // IBM/MS verify sectors case 0x47: // IBM/MS extended seek count=read_word(SI+(Bit16u)&Int13Ext->count, DS); segment=read_word(SI+(Bit16u)&Int13Ext->segment, DS); offset=read_word(SI+(Bit16u)&Int13Ext->offset, DS); // Can't use 64 bits lba lba=read_dword(SI+(Bit16u)&Int13Ext->lba2, DS); if (lba != 0L) { BX_PANIC("int13_cdrom: function %02x. Can't use 64bits lba\n",GET_AH()); goto int13_fail; } // Get 32 bits lba lba=read_dword(SI+(Bit16u)&Int13Ext->lba1, DS); // If verify or seek if ((GET_AH() == 0x44) || (GET_AH() == 0x47)) goto int13_success; memsetb(0,atacmd,get_SS(),12); atacmd[0]=0x28; // READ command atacmd[7]=(count & 0xff00) >> 8; // Sectors atacmd[8]=(count & 0x00ff); // Sectors atacmd[2]=(lba & 0xff000000) >> 24; // LBA atacmd[3]=(lba & 0x00ff0000) >> 16; atacmd[4]=(lba & 0x0000ff00) >> 8; atacmd[5]=(lba & 0x000000ff); status = ata_cmd_packet(device, 12, get_SS(), atacmd, 0, count*2048L, ATA_DATA_IN, segment,offset); count = (Bit16u)(read_dword_DS(&EbdaData->ata.trsfbytes) >> 11); write_word(count, SI+(Bit16u)&Int13Ext->count, DS); if (status != 0) { BX_INFO("int13_cdrom: function %02x, status %02x !\n",GET_AH(),status); SET_AH(0x0c); goto int13_fail_noah; } goto int13_success; break; case 0x45: // IBM/MS lock/unlock drive if (GET_AL() > 2) goto int13_fail; locks = read_byte_DS(&EbdaData->ata.devices[device].lock); switch (GET_AL()) { case 0 : // lock if (locks == 0xff) { SET_AH(0xb4); SET_AL(1); goto int13_fail_noah; } write_byte_DS(&EbdaData->ata.devices[device].lock, ++locks); SET_AL(1); break; case 1 : // unlock if (locks == 0x00) { SET_AH(0xb0); SET_AL(0); goto int13_fail_noah; } write_byte_DS(&EbdaData->ata.devices[device].lock, --locks); SET_AL(locks==0?0:1); break; case 2 : // status SET_AL(locks==0?0:1); break; } goto int13_success; break; case 0x46: // IBM/MS eject media locks = read_byte_DS(&EbdaData->ata.devices[device].lock); if (locks != 0) { SET_AH(0xb1); // media locked goto int13_fail_noah; } // FIXME should handle 0x31 no media in device // FIXME should handle 0xb5 valid request failed // Call removable media eject ASM_START push bp mov bp, sp mov ah, #0x52 int #0x15 mov _int13_cdrom.status + 2[bp], ah jnc int13_cdrom_rme_end mov _int13_cdrom.status, #1 int13_cdrom_rme_end: pop bp ASM_END if (status != 0) { SET_AH(0xb1); // media locked goto int13_fail_noah; } goto int13_success; break; case 0x48: // IBM/MS get drive parameters if (int13_edd(DS, SI, device)) goto int13_fail; goto int13_success; break; case 0x49: // IBM/MS extended media change // always send changed ?? SET_AH(06); goto int13_fail_nostatus; break; case 0x4e: // // IBM/MS set hardware configuration // DMA, prefetch, PIO maximum not supported switch (GET_AL()) { case 0x01: case 0x03: case 0x04: case 0x06: goto int13_success; break; default: goto int13_fail; } break; // all those functions return unimplemented case 0x02: /* read sectors */ case 0x04: /* verify sectors */ case 0x08: /* read disk drive parameters */ case 0x0a: /* read disk sectors with ECC */ case 0x0b: /* write disk sectors with ECC */ case 0x18: /* set media type for format */ case 0x50: // ? - send packet command default: BX_INFO("int13_cdrom: unsupported AH=%02x\n", GET_AH()); goto int13_fail; break; } int13_fail: SET_AH(0x01); // defaults to invalid function in AH or invalid parameter int13_fail_noah: SET_DISK_RET_STATUS(GET_AH()); int13_fail_nostatus: SET_CF(); // error occurred return; int13_success: SET_AH(0x00); // no error int13_success_noah: SET_DISK_RET_STATUS(0x00); CLEAR_CF(); // no error } // --------------------------------------------------------------------------- // End of int13 for cdrom // --------------------------------------------------------------------------- #if BX_ELTORITO_BOOT // --------------------------------------------------------------------------- // Start of int13 for eltorito functions // --------------------------------------------------------------------------- void int13_eltorito(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS; { Bit16u ebda_seg=read_word(0x000E,0x0040); BX_DEBUG_INT13_ET("int13_eltorito: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); // BX_DEBUG_INT13_ET("int13_eltorito: SS=%04x DS=%04x ES=%04x DI=%04x SI=%04x\n",get_SS(), DS, ES, DI, SI); switch (GET_AH()) { // FIXME ElTorito Various. Should be implemented case 0x4a: // ElTorito - Initiate disk emu case 0x4c: // ElTorito - Initiate disk emu and boot case 0x4d: // ElTorito - Return Boot catalog BX_PANIC("Int13 eltorito call with AX=%04x. Please report\n",AX); goto int13_fail; break; case 0x4b: // ElTorito - Terminate disk emu // FIXME ElTorito Hardcoded write_byte_DS(SI+0x00,0x13); write_byte_DS(SI+0x01,read_byte(&EbdaData->cdemu.media,ebda_seg)); write_byte_DS(SI+0x02,read_byte(&EbdaData->cdemu.emulated_drive,ebda_seg)); write_byte_DS(SI+0x03,read_byte(&EbdaData->cdemu.controller_index,ebda_seg)); write_dword_DS(SI+0x04,read_dword(&EbdaData->cdemu.ilba,ebda_seg)); write_word_DS(SI+0x08,read_word(&EbdaData->cdemu.device_spec,ebda_seg)); write_word_DS(SI+0x0a,read_word(&EbdaData->cdemu.buffer_segment,ebda_seg)); write_word_DS(SI+0x0c,read_word(&EbdaData->cdemu.load_segment,ebda_seg)); write_word_DS(SI+0x0e,read_word(&EbdaData->cdemu.sector_count,ebda_seg)); write_byte_DS(SI+0x10,read_byte(&EbdaData->cdemu.vdevice.cylinders,ebda_seg)); write_byte_DS(SI+0x11,read_byte(&EbdaData->cdemu.vdevice.spt,ebda_seg)); write_byte_DS(SI+0x12,read_byte(&EbdaData->cdemu.vdevice.heads,ebda_seg)); // If we have to terminate emulation if(GET_AL() == 0x00) { // FIXME ElTorito Various. Should be handled accordingly to spec write_byte(0x00,&EbdaData->cdemu.active,ebda_seg); // bye bye } goto int13_success; break; default: BX_INFO("int13_eltorito: unsupported AH=%02x\n", GET_AH()); goto int13_fail; break; } int13_fail: SET_AH(0x01); // defaults to invalid function in AH or invalid parameter SET_DISK_RET_STATUS(GET_AH()); SET_CF(); // error occurred return; int13_success: SET_AH(0x00); // no error SET_DISK_RET_STATUS(0x00); CLEAR_CF(); // no error } // --------------------------------------------------------------------------- // End of int13 for eltorito functions // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- // Start of int13 when emulating a device from the cd // --------------------------------------------------------------------------- void int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS; { Bit8u device, status; Bit16u vheads, vspt, vcylinders; Bit16u head, sector, cylinder, nbsectors; Bit32u vlba, ilba, slba, elba; Bit16u before, segment, offset; Bit8u atacmd[12]; // // DS has been set to EBDA segment before call // BX_DEBUG_INT13_ET("int13_cdemu: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); /* at this point, we are emulating a floppy/harddisk */ // Recompute the device number device = read_byte_DS(&EbdaData->cdemu.controller_index) * 2; device += read_byte_DS(&EbdaData->cdemu.device_spec); SET_DISK_RET_STATUS(0x00); /* basic checks : emulation should be active, dl should equal the emulated drive */ if( (read_byte_DS(&EbdaData->cdemu.active) ==0) || (read_byte_DS(&EbdaData->cdemu.emulated_drive ) != GET_DL())) { BX_INFO("int13_cdemu: function %02x, emulation not active for DL= %02x\n", GET_AH(), GET_DL()); goto int13_fail; } switch (GET_AH()) { // all those functions return SUCCESS case 0x00: /* disk controller reset */ case 0x09: /* initialize drive parameters */ case 0x0c: /* seek to specified cylinder */ case 0x0d: /* alternate disk reset */ // FIXME ElTorito Various. should really reset ? case 0x10: /* check drive ready */ // FIXME ElTorito Various. should check if ready ? case 0x11: /* recalibrate */ case 0x14: /* controller internal diagnostic */ case 0x16: /* detect disk change */ goto int13_success; break; // all those functions return disk write-protected case 0x03: /* write disk sectors */ case 0x05: /* format disk track */ SET_AH(0x03); goto int13_fail_noah; break; case 0x01: /* read disk status */ status=read_byte(0x0074, 0x0040); SET_AH(status); SET_DISK_RET_STATUS(0); /* set CF if error status read */ if (status) goto int13_fail_nostatus; else goto int13_success_noah; break; case 0x02: // read disk sectors case 0x04: // verify disk sectors vspt = read_word_DS(&EbdaData->cdemu.vdevice.spt); vcylinders = read_word_DS(&EbdaData->cdemu.vdevice.cylinders); vheads = read_word_DS(&EbdaData->cdemu.vdevice.heads); ilba = read_dword_DS(&EbdaData->cdemu.ilba); sector = GET_CL() & 0x003f; cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH(); head = GET_DH(); nbsectors = GET_AL(); segment = ES; offset = BX; // no sector to read ? if(nbsectors==0) goto int13_success; // sanity checks sco openserver needs this! if ((sector > vspt) || (cylinder >= vcylinders) || (head >= vheads)) { goto int13_fail; } // After controls, verify do nothing if (GET_AH() == 0x04) goto int13_success; segment = ES+(BX / 16); offset = BX % 16; // calculate the virtual lba inside the image vlba=((((Bit32u)cylinder*(Bit32u)vheads)+(Bit32u)head)*(Bit32u)vspt)+((Bit32u)(sector-1)); // In advance so we don't loose the count SET_AL(nbsectors); // start lba on cd slba = (Bit32u)vlba/4; before= (Bit16u)vlba%4; // end lba on cd elba = (Bit32u)(vlba+nbsectors-1)/4; memsetb(0,atacmd,get_SS(),12); atacmd[0]=0x28; // READ command atacmd[7]=((Bit16u)(elba-slba+1) & 0xff00) >> 8; // Sectors atacmd[8]=((Bit16u)(elba-slba+1) & 0x00ff); // Sectors atacmd[2]=(ilba+slba & 0xff000000) >> 24; // LBA atacmd[3]=(ilba+slba & 0x00ff0000) >> 16; atacmd[4]=(ilba+slba & 0x0000ff00) >> 8; atacmd[5]=(ilba+slba & 0x000000ff); if((status = ata_cmd_packet(device, 12, get_SS(), atacmd, before*512, nbsectors*512L, ATA_DATA_IN, segment,offset)) != 0) { BX_INFO("int13_cdemu: function %02x, error %02x !\n",GET_AH(),status); SET_AH(0x02); SET_AL(0); goto int13_fail_noah; } goto int13_success; break; case 0x08: /* read disk drive parameters */ vspt=read_word_DS(&EbdaData->cdemu.vdevice.spt); vcylinders=read_word_DS(&EbdaData->cdemu.vdevice.cylinders) - 1; vheads=read_word_DS(&EbdaData->cdemu.vdevice.heads) - 1; SET_AL(0x00); SET_BL(0x00); SET_CH(vcylinders & 0xff); SET_CL(((vcylinders >> 2) & 0xc0) | (vspt & 0x3f)); SET_DH(vheads); SET_DL(0x02); // FIXME ElTorito Various. should send the real count of drives 1 or 2 // FIXME ElTorito Harddisk. should send the HD count switch(read_byte_DS(&EbdaData->cdemu.media)) { case 0x01: SET_BL( 0x02 ); break; case 0x02: SET_BL( 0x04 ); break; case 0x03: SET_BL( 0x06 ); break; } ASM_START push bp mov bp, sp mov ax, #diskette_param_table2 mov _int13_cdemu.DI+2[bp], ax mov _int13_cdemu.ES+2[bp], cs pop bp ASM_END goto int13_success; break; case 0x15: /* read disk drive size */ // FIXME ElTorito Harddisk. What geometry to send ? SET_AH(0x03); goto int13_success_noah; break; // all those functions return unimplemented case 0x0a: /* read disk sectors with ECC */ case 0x0b: /* write disk sectors with ECC */ case 0x18: /* set media type for format */ case 0x41: // IBM/MS installation check // FIXME ElTorito Harddisk. Darwin would like to use EDD case 0x42: // IBM/MS extended read case 0x43: // IBM/MS extended write case 0x44: // IBM/MS verify sectors case 0x45: // IBM/MS lock/unlock drive case 0x46: // IBM/MS eject media case 0x47: // IBM/MS extended seek case 0x48: // IBM/MS get drive parameters case 0x49: // IBM/MS extended media change case 0x4e: // ? - set hardware configuration case 0x50: // ? - send packet command default: BX_INFO("int13_cdemu function AH=%02x unsupported, returns fail\n", GET_AH()); goto int13_fail; break; } int13_fail: SET_AH(0x01); // defaults to invalid function in AH or invalid parameter int13_fail_noah: SET_DISK_RET_STATUS(GET_AH()); int13_fail_nostatus: SET_CF(); // error occurred return; int13_success: SET_AH(0x00); // no error int13_success_noah: SET_DISK_RET_STATUS(0x00); CLEAR_CF(); // no error } // --------------------------------------------------------------------------- // End of int13 when emulating a device from the cd // --------------------------------------------------------------------------- #endif // BX_ELTORITO_BOOT #else //BX_USE_ATADRV void outLBA(cylinder,hd_heads,head,hd_sectors,sector,dl) Bit16u cylinder; Bit16u hd_heads; Bit16u head; Bit16u hd_sectors; Bit16u sector; Bit16u dl; { ASM_START push bp mov bp, sp push eax push ebx push edx xor eax,eax mov ax,4[bp] // cylinder xor ebx,ebx mov bl,6[bp] // hd_heads imul ebx mov bl,8[bp] // head add eax,ebx mov bl,10[bp] // hd_sectors imul ebx mov bl,12[bp] // sector add eax,ebx dec eax mov dx,#0x1f3 out dx,al mov dx,#0x1f4 mov al,ah out dx,al shr eax,#16 mov dx,#0x1f5 out dx,al and ah,#0xf mov bl,14[bp] // dl and bl,#1 shl bl,#4 or ah,bl or ah,#0xe0 mov al,ah mov dx,#0x01f6 out dx,al pop edx pop ebx pop eax pop bp ASM_END } void int13_harddisk(EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u EHAX, DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; { Bit8u drive, num_sectors, sector, head, status, mod; Bit8u drive_map; Bit8u n_drives; Bit16u cyl_mod, ax; Bit16u max_cylinder, cylinder, total_sectors; Bit16u hd_cylinders; Bit8u hd_heads, hd_sectors; Bit16u val16; Bit8u sector_count; unsigned int i; Bit16u tempbx; Bit16u dpsize; Bit16u count, segment, offset; Bit32u lba; Bit16u error; BX_DEBUG_INT13_HD("int13 harddisk: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); write_byte(0, 0x008e, 0x0040); // clear completion flag /* at this point, DL is >= 0x80 to be passed from the floppy int13h handler code */ /* check how many disks first (cmos reg 0x12), return an error if drive not present */ drive_map = inb_cmos(0x12); drive_map = (((drive_map & 0xf0)==0) ? 0 : 1) | (((drive_map & 0x0f)==0) ? 0 : 2); n_drives = (drive_map==0) ? 0 : ((drive_map==3) ? 2 : 1); if (!(drive_map & (1<<(GET_ELDL()&0x7f)))) { /* allow 0, 1, or 2 disks */ SET_AH(0x01); SET_DISK_RET_STATUS(0x01); SET_CF(); /* error occurred */ return; } switch (GET_AH()) { case 0x00: /* disk controller reset */ BX_DEBUG_INT13_HD("int13_f00\n"); SET_AH(0); SET_DISK_RET_STATUS(0); set_diskette_ret_status(0); set_diskette_current_cyl(0, 0); /* current cylinder, diskette 1 */ set_diskette_current_cyl(1, 0); /* current cylinder, diskette 2 */ CLEAR_CF(); /* successful */ return; break; case 0x01: /* read disk status */ BX_DEBUG_INT13_HD("int13_f01\n"); status = read_byte(0x0074, 0x0040); SET_AH(status); SET_DISK_RET_STATUS(0); /* set CF if error status read */ if (status) SET_CF(); else CLEAR_CF(); return; break; case 0x04: // verify disk sectors case 0x02: // read disk sectors drive = GET_ELDL(); get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); num_sectors = GET_AL(); cylinder = (GET_CL() & 0x00c0) << 2 | GET_CH(); sector = (GET_CL() & 0x3f); head = GET_DH(); if (hd_cylinders > 1024) { if (hd_cylinders <= 2048) { cylinder <<= 1; } else if (hd_cylinders <= 4096) { cylinder <<= 2; } else if (hd_cylinders <= 8192) { cylinder <<= 3; } else { // hd_cylinders <= 16384 cylinder <<= 4; } ax = head / hd_heads; cyl_mod = ax & 0xff; head = ax >> 8; cylinder |= cyl_mod; } if ( (cylinder >= hd_cylinders) || (sector > hd_sectors) || (head >= hd_heads) ) { SET_AH(1); SET_DISK_RET_STATUS(1); SET_CF(); /* error occurred */ return; } if ( (num_sectors > 128) || (num_sectors == 0) ) BX_PANIC("int13_harddisk: num_sectors out of range!\n"); if (head > 15) BX_PANIC("hard drive BIOS:(read/verify) head > 15\n"); if ( GET_AH() == 0x04 ) { SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); return; } status = inb(PORT_ATA1_CMD_BASE + 7); if (status & 0x80) { BX_PANIC("hard drive BIOS:(read/verify) BUSY bit set\n"); } outb(PORT_ATA1_CMD_BASE + 2, num_sectors); /* activate LBA? (tomv) */ if (hd_heads > 16) { BX_DEBUG_INT13_HD("CHS: %x %x %x\n", cylinder, head, sector); outLBA(cylinder,hd_heads,head,hd_sectors,sector,drive); } else { outb(PORT_ATA1_CMD_BASE + 3, sector); outb(PORT_ATA1_CMD_BASE + 4, cylinder & 0x00ff); outb(PORT_ATA1_CMD_BASE + 5, cylinder >> 8); outb(PORT_ATA1_CMD_BASE + 6, 0xa0 | ((drive & 0x01)<<4) | (head & 0x0f)); } outb(PORT_ATA1_CMD_BASE + 7, 0x20); while (1) { status = inb(PORT_ATA1_CMD_BASE + 7); if (!(status & 0x80)) break; } if (status & 0x01) { BX_PANIC("hard drive BIOS:(read/verify) read error\n"); } else if (!(status & 0x08)) { BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status); BX_PANIC("hard drive BIOS:(read/verify) expected DRQ=1\n"); } sector_count = 0; tempbx = BX; ASM_START sti ;; enable higher priority interrupts ASM_END while (1) { ASM_START ;; store temp bx in real DI register push bp mov bp, sp mov di, _int13_harddisk.tempbx + 2 [bp] pop bp ;; adjust if there will be an overrun cmp di, #0xfe00 jbe i13_f02_no_adjust i13_f02_adjust: sub di, #0x0200 ; sub 512 bytes from offset mov ax, es add ax, #0x0020 ; add 512 to segment mov es, ax i13_f02_no_adjust: mov cx, #0x0100 ;; counter (256 words = 512b) mov dx, #0x01f0 ;; AT data read port rep insw ;; CX words transferred from port(DX) to ES:[DI] i13_f02_done: ;; store real DI register back to temp bx push bp mov bp, sp mov _int13_harddisk.tempbx + 2 [bp], di pop bp ASM_END sector_count++; num_sectors--; if (num_sectors == 0) { status = inb(PORT_ATA1_CMD_BASE + 7); if ((status & 0xc9) != 0x40) BX_PANIC("no sectors left to read/verify, status is %02x\n", (unsigned) status); break; } else { status = inb(PORT_ATA1_CMD_BASE + 7); if ((status & 0xc9) != 0x48) BX_PANIC("more sectors left to read/verify, status is %02x\n", (unsigned) status); continue; } } SET_AH(0); SET_DISK_RET_STATUS(0); SET_AL(sector_count); CLEAR_CF(); /* successful */ return; break; case 0x03: /* write disk sectors */ BX_DEBUG_INT13_HD("int13_f03\n"); drive = GET_ELDL (); get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); num_sectors = GET_AL(); cylinder = GET_CH(); cylinder |= ( ((Bit16u) GET_CL()) << 2) & 0x300; sector = (GET_CL() & 0x3f); head = GET_DH(); if (hd_cylinders > 1024) { if (hd_cylinders <= 2048) { cylinder <<= 1; } else if (hd_cylinders <= 4096) { cylinder <<= 2; } else if (hd_cylinders <= 8192) { cylinder <<= 3; } else { // hd_cylinders <= 16384 cylinder <<= 4; } ax = head / hd_heads; cyl_mod = ax & 0xff; head = ax >> 8; cylinder |= cyl_mod; } if ( (cylinder >= hd_cylinders) || (sector > hd_sectors) || (head >= hd_heads) ) { SET_AH(1); SET_DISK_RET_STATUS(1); SET_CF(); /* error occurred */ return; } if ( (num_sectors > 128) || (num_sectors == 0) ) BX_PANIC("int13_harddisk: num_sectors out of range!\n"); if (head > 15) BX_PANIC("hard drive BIOS:(read) head > 15\n"); status = inb(PORT_ATA1_CMD_BASE + 7); if (status & 0x80) { BX_PANIC("hard drive BIOS:(read) BUSY bit set\n"); } // should check for Drive Ready Bit also in status reg outb(PORT_ATA1_CMD_BASE + 2, num_sectors); /* activate LBA? (tomv) */ if (hd_heads > 16) { BX_DEBUG_INT13_HD("CHS (write): %x %x %x\n", cylinder, head, sector); outLBA(cylinder,hd_heads,head,hd_sectors,sector,GET_ELDL()); } else { outb(PORT_ATA1_CMD_BASE + 3, sector); outb(PORT_ATA1_CMD_BASE + 4, cylinder & 0x00ff); outb(PORT_ATA1_CMD_BASE + 5, cylinder >> 8); outb(PORT_ATA1_CMD_BASE + 6, 0xa0 | ((GET_ELDL() & 0x01)<<4) | (head & 0x0f)); } outb(PORT_ATA1_CMD_BASE + 7, 0x30); // wait for busy bit to turn off after seeking while (1) { status = inb(PORT_ATA1_CMD_BASE + 7); if (!(status & 0x80)) break; } if (!(status & 0x08)) { BX_DEBUG_INT13_HD("status was %02x\n", (unsigned) status); BX_PANIC("hard drive BIOS:(write) data-request bit not set\n"); } sector_count = 0; tempbx = BX; ASM_START sti ;; enable higher priority interrupts ASM_END while (1) { ASM_START ;; store temp bx in real SI register push bp mov bp, sp mov si, _int13_harddisk.tempbx + 2 [bp] pop bp ;; adjust if there will be an overrun cmp si, #0xfe00 jbe i13_f03_no_adjust i13_f03_adjust: sub si, #0x0200 ; sub 512 bytes from offset mov ax, es add ax, #0x0020 ; add 512 to segment mov es, ax i13_f03_no_adjust: mov cx, #0x0100 ;; counter (256 words = 512b) mov dx, #0x01f0 ;; AT data read port seg ES rep outsw ;; CX words tranferred from ES:[SI] to port(DX) ;; store real SI register back to temp bx push bp mov bp, sp mov _int13_harddisk.tempbx + 2 [bp], si pop bp ASM_END sector_count++; num_sectors--; if (num_sectors == 0) { status = inb(PORT_ATA1_CMD_BASE + 7); if ((status & 0xe9) != 0x40) BX_PANIC("no sectors left to write, status is %02x\n", (unsigned) status); break; } else { status = inb(PORT_ATA1_CMD_BASE + 7); if ((status & 0xc9) != 0x48) BX_PANIC("more sectors left to write, status is %02x\n", (unsigned) status); continue; } } SET_AH(0); SET_DISK_RET_STATUS(0); SET_AL(sector_count); CLEAR_CF(); /* successful */ return; break; case 0x05: /* format disk track */ BX_DEBUG_INT13_HD("int13_f05\n"); BX_PANIC("format disk track called\n"); /* nop */ SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); /* successful */ return; break; case 0x08: /* read disk drive parameters */ BX_DEBUG_INT13_HD("int13_f08\n"); drive = GET_ELDL (); get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); // translate CHS // if (hd_cylinders <= 1024) { // hd_cylinders >>= 0; // hd_heads <<= 0; } else if (hd_cylinders <= 2048) { hd_cylinders >>= 1; hd_heads <<= 1; } else if (hd_cylinders <= 4096) { hd_cylinders >>= 2; hd_heads <<= 2; } else if (hd_cylinders <= 8192) { hd_cylinders >>= 3; hd_heads <<= 3; } else { // hd_cylinders <= 16384 hd_cylinders >>= 4; hd_heads <<= 4; } max_cylinder = hd_cylinders - 1; /* 0 based */ SET_AL(0); SET_CH(max_cylinder & 0xff); SET_CL(((max_cylinder >> 2) & 0xc0) | (hd_sectors & 0x3f)); SET_DH(hd_heads - 1); SET_DL(n_drives); /* returns 0, 1, or 2 hard drives */ SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); /* successful */ return; break; case 0x09: /* initialize drive parameters */ BX_DEBUG_INT13_HD("int13_f09\n"); SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); /* successful */ return; break; case 0x0a: /* read disk sectors with ECC */ BX_DEBUG_INT13_HD("int13_f0a\n"); case 0x0b: /* write disk sectors with ECC */ BX_DEBUG_INT13_HD("int13_f0b\n"); BX_PANIC("int13h Functions 0Ah & 0Bh not implemented!\n"); return; break; case 0x0c: /* seek to specified cylinder */ BX_DEBUG_INT13_HD("int13_f0c\n"); BX_INFO("int13h function 0ch (seek) not implemented!\n"); SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); /* successful */ return; break; case 0x0d: /* alternate disk reset */ BX_DEBUG_INT13_HD("int13_f0d\n"); SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); /* successful */ return; break; case 0x10: /* check drive ready */ BX_DEBUG_INT13_HD("int13_f10\n"); //SET_AH(0); //SET_DISK_RET_STATUS(0); //CLEAR_CF(); /* successful */ //return; //break; // should look at 40:8E also??? status = inb(PORT_ATA1_CMD_BASE + 7); if ((status & 0xc0) == 0x40) { SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); // drive ready return; } else { SET_AH(0xAA); SET_DISK_RET_STATUS(0xAA); SET_CF(); // not ready return; } break; case 0x11: /* recalibrate */ BX_DEBUG_INT13_HD("int13_f11\n"); SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); /* successful */ return; break; case 0x14: /* controller internal diagnostic */ BX_DEBUG_INT13_HD("int13_f14\n"); SET_AH(0); SET_DISK_RET_STATUS(0); CLEAR_CF(); /* successful */ SET_AL(0); return; break; case 0x15: /* read disk drive size */ drive = GET_ELDL(); get_hd_geometry(drive, &hd_cylinders, &hd_heads, &hd_sectors); ASM_START push bp mov bp, sp mov al, _int13_harddisk.hd_heads + 2 [bp] mov ah, _int13_harddisk.hd_sectors + 2 [bp] mul al, ah ;; ax = heads * sectors mov bx, _int13_harddisk.hd_cylinders + 2 [bp] dec bx ;; use (cylinders - 1) ??? mul ax, bx ;; dx:ax = (cylinders -1) * (heads * sectors) ;; now we need to move the 32bit result dx:ax to what the ;; BIOS wants which is cx:dx. ;; and then into CX:DX on the stack mov _int13_harddisk.CX + 2 [bp], dx mov _int13_harddisk.DX + 2 [bp], ax pop bp ASM_END SET_AH(3); // hard disk accessible SET_DISK_RET_STATUS(0); // ??? should this be 0 CLEAR_CF(); // successful return; break; case 0x18: // set media type for format case 0x41: // IBM/MS case 0x42: // IBM/MS case 0x43: // IBM/MS case 0x44: // IBM/MS case 0x45: // IBM/MS lock/unlock drive case 0x46: // IBM/MS eject media case 0x47: // IBM/MS extended seek case 0x49: // IBM/MS extended media change case 0x50: // IBM/MS send packet command default: BX_INFO("int13_harddisk: unsupported AH=%02x\n", GET_AH()); SET_AH(1); // code=invalid function in AH or invalid parameter SET_DISK_RET_STATUS(1); SET_CF(); /* unsuccessful */ return; } } static char panic_msg_reg12h[] = "HD%d cmos reg 12h not type F\n"; static char panic_msg_reg19h[] = "HD%d cmos reg %02xh not user definable type 47\n"; void get_hd_geometry(drive, hd_cylinders, hd_heads, hd_sectors) Bit8u drive; Bit16u *hd_cylinders; Bit8u *hd_heads; Bit8u *hd_sectors; { Bit8u hd_type; Bit16u cylinders; Bit8u iobase; if (drive == 0x80) { hd_type = inb_cmos(0x12) & 0xf0; if (hd_type != 0xf0) BX_INFO(panic_msg_reg12h,0); hd_type = inb_cmos(0x19); // HD0: extended type if (hd_type != 47) BX_INFO(panic_msg_reg19h,0,0x19); iobase = 0x1b; } else { hd_type = inb_cmos(0x12) & 0x0f; if (hd_type != 0x0f) BX_INFO(panic_msg_reg12h,1); hd_type = inb_cmos(0x1a); // HD1: extended type if (hd_type != 47) BX_INFO(panic_msg_reg19h,0,0x1a); iobase = 0x24; } // cylinders cylinders = inb_cmos(iobase) | (inb_cmos(iobase+1) << 8); write_word_SS(cylinders, hd_cylinders); // heads write_byte_SS(inb_cmos(iobase+2), hd_heads); // sectors per track write_byte_SS(inb_cmos(iobase+8), hd_sectors); } #endif //else BX_USE_ATADRV #if BX_SUPPORT_FLOPPY ////////////////////// // FLOPPY functions // ////////////////////// void floppy_reset_controller() { Bit8u val8; // Reset controller val8 = inb(PORT_FD_DOR); outb(PORT_FD_DOR, val8 & ~0x04); outb(PORT_FD_DOR, val8 | 0x04); // Wait for controller to come out of reset do { val8 = inb(PORT_FD_STATUS); } while ((val8 & 0xc0) != 0x80); } void floppy_prepare_controller(drive) Bit16u drive; { Bit8u val8, dor, prev_reset; // // DS has been set to 0x40 before call // // set 40:3e bit 7 to 0 val8 = read_byte_DS(0x003e); val8 &= 0x7f; write_byte_DS(0x003e, val8); // turn on motor of selected drive, DMA & int enabled, normal operation prev_reset = inb(PORT_FD_DOR) & 0x04; if (drive) dor = 0x20; else dor = 0x10; dor |= 0x0c; dor |= drive; outb(PORT_FD_DOR, dor); // reset the disk motor timeout value of INT 08 write_byte_DS(0x40, BX_FLOPPY_ON_CNT); // wait for drive readiness do { val8 = inb(PORT_FD_STATUS); } while ( (val8 & 0xc0) != 0x80 ); if (prev_reset == 0) { // turn on interrupts ASM_START sti ASM_END // wait on 40:3e bit 7 to become 1 do { val8 = read_byte_DS(0x003e); } while ( (val8 & 0x80) == 0 ); val8 &= 0x7f; ASM_START cli ASM_END write_byte_DS(0x003e, val8); } } bx_bool floppy_media_known(drive) Bit16u drive; { Bit8u val8; Bit16u media_state_offset; // // DS has been set to 0x40 before call // val8 = read_byte_DS(0x003e); // diskette recal status if (drive) val8 >>= 1; val8 &= 0x01; if (val8 == 0) return(0); media_state_offset = 0x0090; if (drive) media_state_offset += 1; val8 = read_byte_DS(media_state_offset); val8 = (val8 >> 4) & 0x01; if (val8 == 0) return(0); // check pass, return KNOWN return(1); } bx_bool floppy_media_sense(drive) Bit16u drive; { bx_bool retval; Bit16u media_state_offset; Bit8u drive_type, config_data, media_state; // // DS has been set to 0x40 before call // if (floppy_drive_recal(drive) == 0) { return(0); } // for now cheat and get drive type from CMOS, // assume media is same as drive type // ** config_data ** // Bitfields for diskette media control: // Bit(s) Description (Table M0028) // 7-6 last data rate set by controller // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps // 5-4 last diskette drive step rate selected // 00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah // 3-2 {data rate at start of operation} // 1-0 reserved // ** media_state ** // Bitfields for diskette drive media state: // Bit(s) Description (Table M0030) // 7-6 data rate // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps // 5 double stepping required (e.g. 360kB in 1.2MB) // 4 media type established // 3 drive capable of supporting 4MB media // 2-0 on exit from BIOS, contains // 000 trying 360kB in 360kB // 001 trying 360kB in 1.2MB // 010 trying 1.2MB in 1.2MB // 011 360kB in 360kB established // 100 360kB in 1.2MB established // 101 1.2MB in 1.2MB established // 110 reserved // 111 all other formats/drives drive_type = inb_cmos(0x10); if (drive == 0) drive_type >>= 4; else drive_type &= 0x0f; switch(drive_type) { case 1: // 360K 5.25" drive case 2: // 1.2 MB 5.25" drive config_data = 0x00; // 0000 0000 /* 1.2 MB 5.25" drive: media_state - need double stepping??? (bit 5) */ media_state = 0x25; // 0010 0101 retval = 1; break; case 3: // 720K 3.5" drive /* config_data - 0000 0000 ??? */ case 4: // 1.44 MB 3.5" drive config_data = 0x00; // 0000 0000 media_state = 0x17; // 0001 0111 retval = 1; break; case 5: // 2.88 MB 3.5" drive config_data = 0xCC; // 1100 1100 media_state = 0xD7; // 1101 0111 retval = 1; break; /* Extended floppy size uses special cmos setting */ case 6: // 160k 5.25" drive case 7: // 180k 5.25" drive case 8: // 320k 5.25" drive config_data = 0x00; // 0000 0000 media_state = 0x27; // 0010 0111 retval = 1; break; default: // not recognized config_data = 0x00; // 0000 0000 media_state = 0x00; // 0000 0000 retval = 0; break; } if (drive == 0) media_state_offset = 0x90; else media_state_offset = 0x91; write_byte_DS(0x008B, config_data); write_byte_DS(media_state_offset, media_state); return(retval); } bx_bool floppy_drive_recal(drive) Bit16u drive; { Bit8u val8; Bit16u curr_cyl_offset; // // DS has been set to 0x40 before call // floppy_prepare_controller(drive); // send Recalibrate command (2 bytes) to controller outb(PORT_FD_DATA, 0x07); // 07: Recalibrate outb(PORT_FD_DATA, drive); // 0=drive0, 1=drive1 // turn on interrupts ASM_START sti ASM_END // wait on 40:3e bit 7 to become 1 do { val8 = (read_byte_DS(0x003e) & 0x80); } while ( val8 == 0 ); val8 = 0; // separate asm from while() loop // turn off interrupts ASM_START cli ASM_END // set 40:3e bit 7 to 0, and calibrated bit val8 = read_byte_DS(0x003e); val8 &= 0x7f; if (drive) { val8 |= 0x02; // Drive 1 calibrated curr_cyl_offset = 0x0095; } else { val8 |= 0x01; // Drive 0 calibrated curr_cyl_offset = 0x0094; } write_byte_DS(0x003e, val8); write_byte_DS(curr_cyl_offset, 0); // current cylinder is 0 return(1); } bx_bool floppy_drive_exists(drive) Bit16u drive; { Bit8u drive_type; // check CMOS to see if drive exists drive_type = inb_cmos(0x10); if (drive == 0) drive_type >>= 4; else drive_type &= 0x0f; if ( drive_type == 0 ) return(0); else return(1); } void int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; { Bit8u drive, num_sectors, track, sector, head, status; Bit16u base_address, base_count, base_es; Bit8u page, mode_register, val8, dor; Bit8u return_status[7]; Bit8u drive_type, num_floppies, ah, spt; Bit16u es, last_addr, maxCyl; // // DS has been set to 0x40 before call // BX_DEBUG_INT13_FL("int13_diskette: AX=%04x BX=%04x CX=%04x DX=%04x ES=%04x\n", AX, BX, CX, DX, ES); ah = GET_AH(); switch ( ah ) { case 0x00: // diskette controller reset BX_DEBUG_INT13_FL("floppy f00\n"); drive = GET_ELDL(); if (drive > 1) { SET_AH(1); // invalid param set_diskette_ret_status(1); SET_CF(); return; } drive_type = inb_cmos(0x10); if (drive == 0) drive_type >>= 4; else drive_type &= 0x0f; if (drive_type == 0) { SET_AH(0x80); // drive not responding set_diskette_ret_status(0x80); SET_CF(); return; } SET_AH(0); set_diskette_ret_status(0); CLEAR_CF(); // successful set_diskette_current_cyl(drive, 0); // current cylinder return; case 0x01: // Read Diskette Status CLEAR_CF(); val8 = read_byte_DS(0x0041); SET_AH(val8); if (val8) { SET_CF(); } return; case 0x02: // Read Diskette Sectors case 0x03: // Write Diskette Sectors case 0x04: // Verify Diskette Sectors num_sectors = GET_AL(); track = GET_CH(); sector = GET_CL(); head = GET_DH(); drive = GET_ELDL(); if ((drive > 1) || (head > 1) || (sector == 0) || (num_sectors == 0) || (num_sectors > 72)) { BX_INFO("int13_diskette: read/write/verify: parameter out of range\n"); SET_AH(1); set_diskette_ret_status(1); SET_AL(0); // no sectors read SET_CF(); // error occurred return; } // see if drive exists if (floppy_drive_exists(drive) == 0) { SET_AH(0x80); // not responding set_diskette_ret_status(0x80); SET_AL(0); // no sectors read SET_CF(); // error occurred return; } // see if media in drive, and type is known if (floppy_media_known(drive) == 0) { if (floppy_media_sense(drive) == 0) { SET_AH(0x0C); // Media type not found set_diskette_ret_status(0x0C); SET_AL(0); // no sectors read SET_CF(); // error occurred return; } } if(ah == 0x04) { // Verify Diskette Sectors goto floppy_return_success; } //----------------------------------- // set up DMA controller for transfer //----------------------------------- // es:bx = pointer to where to place information from diskette // port 04: DMA-1 base and current address, channel 2 // port 05: DMA-1 base and current count, channel 2 page = (ES >> 12); // upper 4 bits base_es = (ES << 4); // lower 16bits contributed by ES base_address = base_es + BX; // lower 16 bits of address // contributed by ES:BX if ( base_address < base_es ) { // in case of carry, adjust page by 1 page++; } base_count = (num_sectors * 512) - 1; // check for 64K boundary overrun last_addr = base_address + base_count; if (last_addr < base_address) { SET_AH(0x09); set_diskette_ret_status(0x09); SET_AL(0); // no sectors read SET_CF(); // error occurred return; } BX_DEBUG_INT13_FL("masking DMA-1 c2\n"); outb(PORT_DMA1_MASK_REG, 0x06); BX_DEBUG_INT13_FL("clear flip-flop\n"); outb(PORT_DMA1_CLEAR_FF_REG, 0x00); // clear flip-flop outb(PORT_DMA_ADDR_2, base_address); outb(PORT_DMA_ADDR_2, base_address>>8); BX_DEBUG_INT13_FL("clear flip-flop\n"); outb(PORT_DMA1_CLEAR_FF_REG, 0x00); // clear flip-flop outb(PORT_DMA_CNT_2, base_count); outb(PORT_DMA_CNT_2, base_count>>8); if (ah == 0x02) { // Read Diskette Sectors // port 0b: DMA-1 Mode Register mode_register = 0x46; // single mode, increment, autoinit disable, // transfer type=write, channel 2 BX_DEBUG_INT13_FL("setting mode register\n"); outb(PORT_DMA1_MODE_REG, mode_register); BX_DEBUG_INT13_FL("setting page register\n"); // port 81: DMA-1 Page Register, channel 2 outb(PORT_DMA_PAGE_2, page); BX_DEBUG_INT13_FL("unmask chan 2\n"); outb(PORT_DMA1_MASK_REG, 0x02); // unmask channel 2 BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n"); outb(PORT_DMA1_MASK_REG, 0x02); //-------------------------------------- // set up floppy controller for transfer //-------------------------------------- floppy_prepare_controller(drive); // send read-normal-data command (9 bytes) to controller outb(PORT_FD_DATA, 0xe6); // e6: read normal data } else { // if (ah == 0x03) // Write Diskette Sectors // port 0b: DMA-1 Mode Register mode_register = 0x4a; // single mode, increment, autoinit disable, // transfer type=read, channel 2 outb(PORT_DMA1_MODE_REG, mode_register); // port 81: DMA-1 Page Register, channel 2 outb(PORT_DMA_PAGE_2, page); BX_DEBUG_INT13_FL("unmasking DMA-1 c2\n"); outb(PORT_DMA1_MASK_REG, 0x02); //-------------------------------------- // set up floppy controller for transfer //-------------------------------------- floppy_prepare_controller(drive); // send write-normal-data command (9 bytes) to controller outb(PORT_FD_DATA, 0xc5); // c5: write normal data } outb(PORT_FD_DATA, (head << 2) | drive); // HD DR1 DR2 outb(PORT_FD_DATA, track); outb(PORT_FD_DATA, head); outb(PORT_FD_DATA, sector); outb(PORT_FD_DATA, 2); // 512 byte sector size outb(PORT_FD_DATA, sector + num_sectors - 1); // last sector to read/write on track outb(PORT_FD_DATA, 0); // Gap length outb(PORT_FD_DATA, 0xff); // Gap length // turn on interrupts ASM_START sti ASM_END // wait on 40:3e bit 7 to become 1 do { val8 = read_byte_DS(0x0040); if (val8 == 0) { floppy_reset_controller(); SET_AH(0x80); // drive not ready (timeout) set_diskette_ret_status(0x80); SET_AL(0); // no sectors read / write SET_CF(); // error occurred return; } val8 = (read_byte_DS(0x003e) & 0x80); } while ( val8 == 0 ); val8 = 0; // separate asm from while() loop // turn off interrupts ASM_START cli ASM_END // set 40:3e bit 7 to 0 val8 = read_byte_DS(0x003e); val8 &= 0x7f; write_byte_DS(0x003e, val8); // check port 3f4 for accessibility to status bytes val8 = inb(PORT_FD_STATUS); if ( (val8 & 0xc0) != 0xc0 ) BX_PANIC("int13_diskette: ctrl not ready\n"); // read 7 return status bytes from controller // using loop index broken, have to unroll... return_status[0] = inb(PORT_FD_DATA); return_status[1] = inb(PORT_FD_DATA); return_status[2] = inb(PORT_FD_DATA); return_status[3] = inb(PORT_FD_DATA); return_status[4] = inb(PORT_FD_DATA); return_status[5] = inb(PORT_FD_DATA); return_status[6] = inb(PORT_FD_DATA); // record in BIOS Data Area memcpyb(0x0042, 0x0040, return_status, get_SS(), 7); if ( (return_status[0] & 0xc0) != 0 ) { if (ah == 0x02) { SET_AH(0x20); set_diskette_ret_status(0x20); SET_AL(0); // no sectors read SET_CF(); // error occurred return; } else { // if (ah == 0x03) if ( (return_status[1] & 0x02) != 0 ) { // diskette not writable. // AH=status code=0x03 (tried to write on write-protected disk) // AL=number of sectors written=0 AX = 0x0300; SET_CF(); return; } else { BX_PANIC("int13_diskette_function: read error\n"); } } } floppy_return_success: // ??? should track be new val from return_status[3] ? set_diskette_current_cyl(drive, track); // AL = number of sectors read (same value as passed) SET_AH(0x00); // success CLEAR_CF(); // success break; case 0x05: // format diskette track BX_DEBUG_INT13_FL("floppy f05\n"); num_sectors = GET_AL(); track = GET_CH(); head = GET_DH(); drive = GET_ELDL(); if ((drive > 1) || (head > 1) || (track > 79) || (num_sectors == 0) || (num_sectors > 18)) { SET_AH(1); set_diskette_ret_status(1); SET_CF(); // error occurred } // see if drive exists if (floppy_drive_exists(drive) == 0) { SET_AH(0x80); // drive not responding set_diskette_ret_status(0x80); SET_CF(); // error occurred return; } // see if media in drive, and type is known if (floppy_media_known(drive) == 0) { if (floppy_media_sense(drive) == 0) { SET_AH(0x0C); // Media type not found set_diskette_ret_status(0x0C); SET_AL(0); // no sectors read SET_CF(); // error occurred return; } } // set up DMA controller for transfer page = (ES >> 12); // upper 4 bits base_es = (ES << 4); // lower 16bits contributed by ES base_address = base_es + BX; // lower 16 bits of address // contributed by ES:BX if ( base_address < base_es ) { // in case of carry, adjust page by 1 page++; } base_count = (num_sectors * 4) - 1; // check for 64K boundary overrun last_addr = base_address + base_count; if (last_addr < base_address) { SET_AH(0x09); set_diskette_ret_status(0x09); SET_AL(0); // no sectors read SET_CF(); // error occurred return; } outb(PORT_DMA1_MASK_REG, 0x06); outb(PORT_DMA1_CLEAR_FF_REG, 0x00); // clear flip-flop outb(PORT_DMA_ADDR_2, base_address); outb(PORT_DMA_ADDR_2, base_address>>8); outb(PORT_DMA1_CLEAR_FF_REG, 0x00); // clear flip-flop outb(PORT_DMA_CNT_2, base_count); outb(PORT_DMA_CNT_2, base_count>>8); mode_register = 0x4a; // single mode, increment, autoinit disable, // transfer type=read, channel 2 outb(PORT_DMA1_MODE_REG, mode_register); // port 81: DMA-1 Page Register, channel 2 outb(PORT_DMA_PAGE_2, page); outb(PORT_DMA1_MASK_REG, 0x02); // set up floppy controller for transfer floppy_prepare_controller(drive); // send format-track command (6 bytes) to controller outb(PORT_FD_DATA, 0x4d); // 4d: format track outb(PORT_FD_DATA, (head << 2) | drive); // HD DR1 DR2 outb(PORT_FD_DATA, 2); // 512 byte sector size outb(PORT_FD_DATA, num_sectors); // number of sectors per track outb(PORT_FD_DATA, 0); // Gap length outb(PORT_FD_DATA, 0xf6); // Fill byte // turn on interrupts ASM_START sti ASM_END // wait on 40:3e bit 7 to become 1 do { val8 = read_byte_DS(0x0040); if (val8 == 0) { floppy_reset_controller(); SET_AH(0x80); // drive not ready (timeout) set_diskette_ret_status(0x80); SET_CF(); // error occurred return; } val8 = (read_byte_DS(0x003e) & 0x80); } while ( val8 == 0 ); val8 = 0; // separate asm from while() loop // turn off interrupts ASM_START cli ASM_END // set 40:3e bit 7 to 0 val8 = read_byte_DS(0x003e); val8 &= 0x7f; write_byte_DS(0x003e, val8); // check port 3f4 for accessibility to status bytes val8 = inb(PORT_FD_STATUS); if ( (val8 & 0xc0) != 0xc0 ) BX_PANIC("int13_diskette: ctrl not ready\n"); // read 7 return status bytes from controller // using loop index broken, have to unroll... return_status[0] = inb(PORT_FD_DATA); return_status[1] = inb(PORT_FD_DATA); return_status[2] = inb(PORT_FD_DATA); return_status[3] = inb(PORT_FD_DATA); return_status[4] = inb(PORT_FD_DATA); return_status[5] = inb(PORT_FD_DATA); return_status[6] = inb(PORT_FD_DATA); // record in BIOS Data Area memcpyb(0x0042, 0x0040, return_status, get_SS(), 7); if ( (return_status[0] & 0xc0) != 0 ) { if ( (return_status[1] & 0x02) != 0 ) { // diskette not writable. // AH=status code=0x03 (tried to write on write-protected disk) // AL=number of sectors written=0 AX = 0x0300; SET_CF(); return; } else { BX_PANIC("int13_diskette_function: write error\n"); } } SET_AH(0); set_diskette_ret_status(0); set_diskette_current_cyl(drive, 0); CLEAR_CF(); // successful return; case 0x08: // read diskette drive parameters BX_DEBUG_INT13_FL("floppy f08\n"); drive = GET_ELDL(); if (drive > 1) { AX = 0; BX = 0; CX = 0; DX = 0; ES = 0; DI = 0; SET_DL(num_floppies); SET_CF(); return; } drive_type = inb_cmos(0x10); num_floppies = 0; if (drive_type & 0xf0) num_floppies++; if (drive_type & 0x0f) num_floppies++; if (drive == 0) drive_type >>= 4; else drive_type &= 0x0f; SET_BH(0); SET_BL(drive_type); SET_AH(0); SET_AL(0); SET_DL(num_floppies); switch (drive_type) { case 0: // none CX = 0; SET_DH(0); // max head # break; case 1: // 360KB, 5.25" CX = 0x2709; // 40 tracks, 9 sectors SET_DH(1); // max head # break; case 2: // 1.2MB, 5.25" CX = 0x4f0f; // 80 tracks, 15 sectors SET_DH(1); // max head # break; case 3: // 720KB, 3.5" CX = 0x4f09; // 80 tracks, 9 sectors SET_DH(1); // max head # break; case 4: // 1.44MB, 3.5" CX = 0x4f12; // 80 tracks, 18 sectors SET_DH(1); // max head # break; case 5: // 2.88MB, 3.5" CX = 0x4f24; // 80 tracks, 36 sectors SET_DH(1); // max head # break; case 6: // 160k, 5.25" CX = 0x2708; // 40 tracks, 8 sectors SET_DH(0); // max head # break; case 7: // 180k, 5.25" CX = 0x2709; // 40 tracks, 9 sectors SET_DH(0); // max head # break; case 8: // 320k, 5.25" CX = 0x2708; // 40 tracks, 8 sectors SET_DH(1); // max head # break; default: // ? BX_PANIC("floppy: int13: bad floppy type\n"); } /* set es & di to point to 11 byte diskette param table in ROM */ ASM_START push bp mov bp, sp mov ax, #diskette_param_table2 mov _int13_diskette_function.DI+2[bp], ax mov _int13_diskette_function.ES+2[bp], cs pop bp ASM_END CLEAR_CF(); // success /* disk status not changed upon success */ return; case 0x15: // read diskette drive type BX_DEBUG_INT13_FL("floppy f15\n"); drive = GET_ELDL(); if (drive > 1) { SET_AH(0); // only 2 drives supported // set_diskette_ret_status here ??? SET_CF(); return; } drive_type = inb_cmos(0x10); if (drive == 0) drive_type >>= 4; else drive_type &= 0x0f; CLEAR_CF(); // successful, not present if (drive_type==0) { SET_AH(0); // drive not present } else { SET_AH(1); // drive present, does not support change line } return; case 0x16: // get diskette change line status BX_DEBUG_INT13_FL("floppy f16\n"); drive = GET_ELDL(); if (drive > 1) { SET_AH(0x01); // invalid drive set_diskette_ret_status(0x01); SET_CF(); return; } SET_AH(0x06); // change line not supported set_diskette_ret_status(0x06); SET_CF(); return; case 0x17: // set diskette type for format(old) BX_DEBUG_INT13_FL("floppy f17\n"); // NOTE: 1.44M diskette not supported by this function, // should use Int13 al=0x18 instead. // Intr Reference: http://www.ctyme.com/intr // // ** media state byte ** // Bitfields for diskette drive media state byte that we might // change in this function: // Bit(s) Description (Table M0030) // 7-6 data rate // 00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps // 5 double stepping required (e.g. 360kB in 1.2MB) // 4 media type established // Drive number (0 or 1) values allowed drive = GET_ELDL(); // Drive type (AL) // 00 - NOT USED // 01 - DISKETTE 320/360K IN 360K DRIVE // 02 - DISKETTE 360K IN 1.2M DRIVE // 03 - DISKETTE 1.2M IN 1.2M DRIVE // 04 - DISKETTE 720K IN 720K DRIVE drive_type = GET_AL(); if (drive > 1) { SET_AH(0x01); // invalid drive set_diskette_ret_status(1); // bad parameter SET_CF(); return; } // see if drive exists if (floppy_drive_exists(drive) == 0) { SET_AH(0x80); // not responding/time out set_diskette_ret_status(0x80); SET_CF(); return; } // Get current drive status into 'status'. Set 'base_address' to media status offset address base_address = (drive) ? 0x0091 : 0x0090; status = read_byte_DS(base_address); // Mask out (clear) bits 4-7 (4:media type established, 5:double stepping, 6-7:data rate), val8 = status & 0x0f; switch(drive_type) { case 1: // 320/360K media in 360K drive val8 |= 0x90; // 1001 0000 (media type established, data rate=250) break; case 2: // 360K media in 1.2M drive val8 |= 0x70; // 0111 0000 (media type established, double stepping, data rate=300) break; case 3: // 1.2M media in 1.2M drive val8 |= 0x10; // 0001 0000 (media type established, data rate=500) break; case 4: // 720K media in 720K drive if (((status >> 4) & 0x01) && ((status >> 1) & 0x01)) { // Media type already determined, and multiple format capable, so assume a higher data rate. val8 |= 0x50; // 0101 0000 (media type established, data rate=300) } else { // Media type not yet determined, or not multiple format capable, assume a lower data rate. val8 |= 0x90; // 1001 0000 (media type established, data rate=250) } break; default: // bad parameter SET_AH(0x01); // invalid drive set_diskette_ret_status(1); // bad parameter SET_CF(); return; } BX_DEBUG_INT13_FL("floppy f17 - media status set to: %02x\n", val8); // Update media status write_byte_DS(base_address, val8); // return success! SET_AH(0); set_diskette_ret_status(0); CLEAR_CF(); return; case 0x18: // set diskette type for format(new) BX_DEBUG_INT13_FL("floppy f18\n"); // Set Media Type for Format verifies that the device supports a specific geometry. // Unlike Int13 al=0x17 entry point, this version supports higher capacity // drives like 1.44M and even 2.88M. // Drive number (0 or 1) values allowed drive = GET_ELDL(); val8 = GET_CL(); spt = val8 & 0x3f; // sectors per track maxCyl = ((val8 >> 6) << 8) + GET_CH(); // max cylinder number (max cylinders - 1) BX_DEBUG_INT13_FL("floppy f18 - drive: %d, max cylinder number: %d, sectors-per-tracks: %d\n", drive, maxCyl, spt); if (drive > 1) { SET_AH(0x01); // invalid drive set_diskette_ret_status(1); // bad parameter SET_CF(); return; } // see if drive exists if (floppy_drive_exists(drive) == 0) { SET_AH(0x80); // not responding/time out set_diskette_ret_status(0x80); SET_CF(); return; } // see if media in drive, and type is known if (floppy_media_known(drive) == 0) { if (floppy_media_sense(drive) == 0) { SET_AH(0x0C); // drive type unknown set_diskette_ret_status(0x0C); SET_CF(); return; } } // get current drive type drive_type = inb_cmos(0x10); if (drive == 0) drive_type >>= 4; else drive_type &= 0x0f; // Get current drive status into 'status'. Set 'base_address' to media status offset address base_address = (drive) ? 0x0091 : 0x0090; status = read_byte_DS(base_address); // Mask out (clear) bits 4-7 (4:media type established, 5:double stepping, 6-7:data rate), val8 = status & 0x0f; SET_AH(0x0C); // Assume error - unsupported combination of drive-type/max-cylinders/sectors-per-track switch (drive_type) { case 0: // none break; case 1: // 360KB, 5.25" case 6: // 160k, 5.25" case 7: // 180k, 5.25" case 8: // 320k, 5.25" if (maxCyl == 39 && (spt == 8 || spt == 9)) { val8 |= 0x90; // 1001 0000 (media type established, data rate=250) SET_AH(0); } break; case 2: // 1.2MB, 5.25" if (maxCyl == 39 && (spt == 8 || spt == 9)) { // 320K/360K disk in 1.2M drive val8 |= 0x70; // 0111 0000 (media type established, double stepping, data rate=300) SET_AH(0); } else if (maxCyl == 79 && spt == 15) { // 1.2M disk in 1.2M drive val8 |= 0x10; // 0001 0000 (media type established, data rate=500) SET_AH(0); } break; case 3: // 720KB, 3.5" if (maxCyl == 79 && spt == 9) { val8 |= 0x90; // 1001 0000 (media type established, data rate=250) SET_AH(0); } break; case 4: // 1.44MB, 3.5" if (maxCyl == 79) { if (spt == 9) { // 720K disk in 1.44M drive val8 |= 0x90; // 1001 0000 (media type established, data rate=250) SET_AH(0); } else if (spt == 18) { // 1.44M disk in 1.44M drive val8 |= 0x10; // 0001 0000 (media type established, data rate=500) SET_AH(0); } } break; case 5: // 2.88MB, 3.5" if (maxCyl == 79) { if (spt == 9) { // 720K disk in 2.88M drive val8 |= 0x90; // 1001 0000 (media type established, data rate=250) SET_AH(0); } else if (spt == 18) { // 1.44M disk in 2.88M drive val8 |= 0x10; // 0001 0000 (media type established, data rate=500) SET_AH(0); } else if (spt == 36) { // 2.88M disk in 2.88M drive val8 |= 0xD0; // 1101 0000 (media type established, data rate=1mb/s) SET_AH(0); } } break; default: break; } if (0 != GET_AH()) { // Error - assume requested max-cylinder/sectors-per-track not supported // for current drive type - or drive type is unknown! set_diskette_ret_status(GET_AH()); SET_CF(); return; } BX_DEBUG_INT13_FL("floppy f18 - media status set to: %02x\n", val8); // Update media status write_byte_DS(base_address, val8); // set es & di to point to 11 byte diskette param table in ROM // Note that we do not update the table, as I don't see it being used anywhere... ASM_START push bp mov bp, sp mov ax, #diskette_param_table2 mov _int13_diskette_function.DI+2[bp], ax mov _int13_diskette_function.ES+2[bp], cs pop bp ASM_END // return success! set_diskette_ret_status(0); CLEAR_CF(); return; default: BX_INFO("int13_diskette: unsupported AH=%02x\n", GET_AH()); // if ((ah==0x20) || ((ah>=0x41) && (ah<=0x49)) || (ah==0x4e)) { SET_AH(0x01); // ??? set_diskette_ret_status(1); SET_CF(); return; // } } } #else // #if BX_SUPPORT_FLOPPY void int13_diskette_function(DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS) Bit16u DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS; { Bit8u val8; switch (GET_AH()) { case 0x01: // Read Diskette Status CLEAR_CF(); val8 = read_byte_DS(0x0041); SET_AH(val8); if (val8) { SET_CF(); } return; default: SET_CF(); write_byte_DS(0x0041, 0x01); SET_AH(0x01); } } #endif // #if BX_SUPPORT_FLOPPY void set_diskette_ret_status(value) Bit8u value; { write_byte(value, 0x0041, 0x0040); } void set_diskette_current_cyl(drive, cyl) Bit8u drive; Bit8u cyl; { if (drive > 1) BX_PANIC("set_diskette_current_cyl(): drive > 1\n"); write_byte(cyl, 0x0094+drive, 0x0040); } void determine_floppy_media(drive) Bit16u drive; { #if 0 Bit8u val8, DOR, ctrl_info; ctrl_info = read_byte(0x008F, 0x0040); if (drive==1) ctrl_info >>= 4; else ctrl_info &= 0x0f; #if 0 if (drive == 0) { DOR = 0x1c; // DOR: drive0 motor on, DMA&int enabled, normal op, drive select 0 } else { DOR = 0x2d; // DOR: drive1 motor on, DMA&int enabled, normal op, drive select 1 } #endif if ((ctrl_info & 0x04) != 0x04) { // Drive not determined means no drive exists, done. return; } #if 0 // check Main Status Register for readiness val8 = inb(PORT_FD_STATUS) & 0x80; // Main Status Register if (val8 != 0x80) BX_PANIC("d_f_m: MRQ bit not set\n"); // change line // existing BDA values // turn on drive motor outb(PORT_FD_DOR, DOR); // Digital Output Register // #endif BX_PANIC("d_f_m: OK so far\n"); #endif } void int17_function(regs, ds, iret_addr) pusha_regs_t regs; // regs pushed from PUSHA instruction Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call { Bit16u addr,timeout; Bit8u val8; ASM_START sti ASM_END addr = read_word_DS(0x0400 + (regs.u.r16.dx << 1) + 8); if ((regs.u.r8.ah < 3) && (regs.u.r16.dx < 3) && (addr > 0)) { timeout = read_byte_DS(0x0478 + regs.u.r16.dx) << 8; if (regs.u.r8.ah == 0) { outb(addr, regs.u.r8.al); val8 = inb(addr+2); outb(addr+2, val8 | 0x01); // send strobe ASM_START nop ASM_END outb(addr+2, val8 & ~0x01); while (((inb(addr+1) & 0x40) == 0x40) && (timeout)) { timeout--; } } if (regs.u.r8.ah == 1) { val8 = inb(addr+2); outb(addr+2, val8 & ~0x04); // send init ASM_START nop ASM_END outb(addr+2, val8 | 0x04); } val8 = inb(addr+1); regs.u.r8.ah = (val8 ^ 0x48); if (!timeout) regs.u.r8.ah |= 0x01; ClearCF(iret_addr.flags); } else { SetCF(iret_addr.flags); // Unsupported } } void int19_function(seq_nr) Bit16u seq_nr; { // // DS has been set to 0 before call // Bit16u ebda_seg=read_word_DS(0x040E); Bit16u bootdev; Bit8u bootdrv; Bit8u bootchk; Bit16u bootseg; Bit16u bootip; Bit16u status; Bit16u bootfirst; ipl_entry_t e; // if BX_ELTORITO_BOOT is not defined, old behavior // check bit 5 in CMOS reg 0x2d. load either 0x00 or 0x80 into DL // in preparation for the initial INT 13h (0=floppy A:, 0x80=C:) // 0: system boot sequence, first drive C: then A: // 1: system boot sequence, first drive A: then C: // else BX_ELTORITO_BOOT is defined // CMOS regs 0x3D and 0x38 contain the boot sequence: // CMOS reg 0x3D & 0x0f : 1st boot device // CMOS reg 0x3D & 0xf0 : 2nd boot device // CMOS reg 0x38 & 0xf0 : 3rd boot device // boot device codes: // 0x00 : not defined // 0x01 : first floppy // 0x02 : first harddrive // 0x03 : first cdrom // 0x04 - 0x0f : PnP expansion ROMs (e.g. Etherboot) // else : boot failure // Get the boot sequence #if BX_ELTORITO_BOOT bootdev = inb_cmos(0x3d); bootdev |= ((inb_cmos(0x38) & 0xf0) << 4); bootdev >>= 4 * seq_nr; bootdev &= 0xf; /* Read user selected device */ bootfirst = read_word(IPL_BOOTFIRST_OFFSET, IPL_SEG); if (bootfirst != 0xFFFF) { bootdev = bootfirst; /* User selected device not set */ write_word(0xFFFF, IPL_BOOTFIRST_OFFSET, IPL_SEG); /* Reset boot sequence */ write_word(0xFFFF, IPL_SEQUENCE_OFFSET, IPL_SEG); } else if (bootdev == 0) BX_PANIC("No bootable device.\n"); /* Translate from CMOS runes to an IPL table offset by subtracting 1 */ bootdev -= 1; #else if (seq_nr ==2) BX_PANIC("No more boot devices."); if (!!(inb_cmos(0x2d) & 0x20) ^ (seq_nr == 1)) /* Boot from floppy if the bit is set or it's the second boot */ bootdev = 0x00; else bootdev = 0x01; #endif /* Read the boot device from the IPL table */ if (get_boot_vector(bootdev, &e) == 0) { BX_INFO("Invalid boot device (0x%x)\n", bootdev); return; } /* Do the loading, and set up vector as a far pointer to the boot * address, and bootdrv as the boot drive */ print_boot_device(&e); switch(e.type) { case IPL_TYPE_FLOPPY: /* FDD */ case IPL_TYPE_HARDDISK: /* HDD */ bootdrv = (e.type == IPL_TYPE_HARDDISK) ? 0x80 : 0x00; bootseg = 0x07c0; status = 0; ASM_START push bp mov bp, sp push ax push bx push cx push dx mov dl, _int19_function.bootdrv + 2[bp] mov ax, _int19_function.bootseg + 2[bp] mov es, ax ;; segment xor bx, bx ;; offset mov ah, #0x02 ;; function 2, read diskette sector mov al, #0x01 ;; read 1 sector mov ch, #0x00 ;; track 0 mov cl, #0x01 ;; sector 1 mov dh, #0x00 ;; head 0 int #0x13 ;; read sector jnc int19_load_done mov ax, #0x0001 mov _int19_function.status + 2[bp], ax int19_load_done: pop dx pop cx pop bx pop ax pop bp ASM_END if (status != 0) { print_boot_failure(e.type, 1); return; } /* Always check the signature on a HDD boot sector; on FDD, only do * the check if the CMOS doesn't tell us to skip it */ if ((e.type != IPL_TYPE_FLOPPY) || !((inb_cmos(0x38) & 0x01))) { if (read_word(0x1fe,bootseg) != 0xaa55) { print_boot_failure(e.type, 0); return; } } /* Canonicalize bootseg:bootip */ bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; break; #if BX_ELTORITO_BOOT case IPL_TYPE_CDROM: /* CD-ROM */ status = cdrom_boot(); // If failure if ( (status & 0x00ff) !=0 ) { print_cdromboot_failure(status); print_boot_failure(e.type, 1); return; } bootdrv = (Bit8u)(status>>8); bootseg = read_word(&EbdaData->cdemu.load_segment,ebda_seg); bootip = 0; break; #endif case IPL_TYPE_BEV: /* Expansion ROM with a Bootstrap Entry Vector (a far pointer) */ bootseg = e.vector >> 16; bootip = e.vector & 0xffff; break; default: return; } /* Debugging info */ BX_INFO("Booting from %x:%x\n", bootseg, bootip); /* Jump to the boot vector */ ASM_START mov bp, sp push cs push #int18_handler ;; Build an iret stack frame that will take us to the boot vector. ;; iret pops ip, then cs, then flags, so push them in the opposite order. pushf mov ax, _int19_function.bootseg + 0[bp] push ax mov ax, _int19_function.bootip + 0[bp] push ax ;; Set the magic number in ax and the boot drive in dl. mov ax, #0xaa55 mov dl, _int19_function.bootdrv + 0[bp] ;; Zero some of the other registers. xor bx, bx mov ds, bx mov es, bx mov bp, bx ;; Go! iret ASM_END } void int1a_function(regs, ds, iret_addr) pusha_regs_t regs; // regs pushed from PUSHA instruction Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call { Bit8u val8; BX_DEBUG_INT1A("int1a: AX=%04x BX=%04x CX=%04x DX=%04x DS=%04x\n", regs.u.r16.ax, regs.u.r16.bx, regs.u.r16.cx, regs.u.r16.dx, ds); ASM_START sti ASM_END switch (regs.u.r8.ah) { case 0: // get current clock count ASM_START cli ASM_END regs.u.r16.cx = BiosData->ticks_high; regs.u.r16.dx = BiosData->ticks_low; regs.u.r8.al = BiosData->midnight_flag; BiosData->midnight_flag = 0; // reset flag ASM_START sti ASM_END // AH already 0 ClearCF(iret_addr.flags); // OK break; case 1: // Set Current Clock Count ASM_START cli ASM_END BiosData->ticks_high = regs.u.r16.cx; BiosData->ticks_low = regs.u.r16.dx; BiosData->midnight_flag = 0; // reset flag ASM_START sti ASM_END regs.u.r8.ah = 0; ClearCF(iret_addr.flags); // OK break; case 2: // Read CMOS Time if (rtc_updating()) { SetCF(iret_addr.flags); break; } regs.u.r8.dh = inb_cmos(0x00); // Seconds regs.u.r8.cl = inb_cmos(0x02); // Minutes regs.u.r8.ch = inb_cmos(0x04); // Hours regs.u.r8.dl = inb_cmos(0x0b) & 0x01; // Stat Reg B regs.u.r8.ah = 0; regs.u.r8.al = regs.u.r8.ch; ClearCF(iret_addr.flags); // OK break; case 3: // Set CMOS Time // Using a debugger, I notice the following masking/setting // of bits in Status Register B, by setting Reg B to // a few values and getting its value after INT 1A was called. // // try#1 try#2 try#3 // before 1111 1101 0111 1101 0000 0000 // after 0110 0010 0110 0010 0000 0010 // // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = ((RegB & 01100000b) | 00000010b) if (rtc_updating()) { init_rtc(); // fall through as if an update were not in progress } outb_cmos(0x00, regs.u.r8.dh); // Seconds outb_cmos(0x02, regs.u.r8.cl); // Minutes outb_cmos(0x04, regs.u.r8.ch); // Hours // Set Daylight Savings time enabled bit to requested value val8 = (inb_cmos(0x0b) & 0x60) | 0x02 | (regs.u.r8.dl & 0x01); // (reg B already selected) outb_cmos(0x0b, val8); regs.u.r8.ah = 0; regs.u.r8.al = val8; // val last written to Reg B ClearCF(iret_addr.flags); // OK break; case 4: // Read CMOS Date regs.u.r8.ah = 0; if (rtc_updating()) { SetCF(iret_addr.flags); break; } regs.u.r8.cl = inb_cmos(0x09); // Year regs.u.r8.dh = inb_cmos(0x08); // Month regs.u.r8.dl = inb_cmos(0x07); // Day of Month regs.u.r8.ch = inb_cmos(0x32); // Century regs.u.r8.al = regs.u.r8.ch; ClearCF(iret_addr.flags); // OK break; case 5: // Set CMOS Date // Using a debugger, I notice the following masking/setting // of bits in Status Register B, by setting Reg B to // a few values and getting its value after INT 1A was called. // // try#1 try#2 try#3 try#4 // before 1111 1101 0111 1101 0000 0010 0000 0000 // after 0110 1101 0111 1101 0000 0010 0000 0000 // // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = (RegB & 01111111b) if (rtc_updating()) { init_rtc(); SetCF(iret_addr.flags); break; } outb_cmos(0x09, regs.u.r8.cl); // Year outb_cmos(0x08, regs.u.r8.dh); // Month outb_cmos(0x07, regs.u.r8.dl); // Day of Month outb_cmos(0x32, regs.u.r8.ch); // Century val8 = inb_cmos(0x0b) & 0x7f; // clear halt-clock bit outb_cmos(0x0b, val8); regs.u.r8.ah = 0; regs.u.r8.al = val8; // AL = val last written to Reg B ClearCF(iret_addr.flags); // OK break; case 6: // Set Alarm Time in CMOS // Using a debugger, I notice the following masking/setting // of bits in Status Register B, by setting Reg B to // a few values and getting its value after INT 1A was called. // // try#1 try#2 try#3 // before 1101 1111 0101 1111 0000 0000 // after 0110 1111 0111 1111 0010 0000 // // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = ((RegB & 01111111b) | 00100000b) val8 = inb_cmos(0x0b); // Get Status Reg B regs.u.r16.ax = 0; if (val8 & 0x20) { // Alarm interrupt enabled already SetCF(iret_addr.flags); // Error: alarm in use break; } if (rtc_updating()) { init_rtc(); // fall through as if an update were not in progress } outb_cmos(0x01, regs.u.r8.dh); // Seconds alarm outb_cmos(0x03, regs.u.r8.cl); // Minutes alarm outb_cmos(0x05, regs.u.r8.ch); // Hours alarm outb(PORT_PIC2_DATA, inb(PORT_PIC2_DATA) & 0xfe); // enable IRQ 8 // enable Status Reg B alarm bit, clear halt clock bit outb_cmos(0x0b, (val8 & 0x7f) | 0x20); ClearCF(iret_addr.flags); // OK break; case 7: // Turn off Alarm // Using a debugger, I notice the following masking/setting // of bits in Status Register B, by setting Reg B to // a few values and getting its value after INT 1A was called. // // try#1 try#2 try#3 try#4 // before 1111 1101 0111 1101 0010 0000 0010 0010 // after 0100 0101 0101 0101 0000 0000 0000 0010 // // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1 // My assumption: RegB = (RegB & 01010111b) val8 = inb_cmos(0x0b); // Get Status Reg B // clear clock-halt bit, disable alarm bit outb_cmos(0x0b, val8 & 0x57); // disable alarm bit regs.u.r8.ah = 0; regs.u.r8.al = val8; // val last written to Reg B ClearCF(iret_addr.flags); // OK break; #if BX_PCIBIOS case 0xb1: // real mode PCI BIOS functions now handled in assembler code // this C code handles the error code for information only if (regs.u.r8.bl == 0xff) { BX_INFO("PCI BIOS: PCI not present\n"); } else if (regs.u.r8.bl == 0x81) { BX_INFO("unsupported PCI BIOS function 0x%02x\n", regs.u.r8.al); } else if (regs.u.r8.bl == 0x83) { BX_INFO("bad PCI vendor ID %04x\n", regs.u.r16.dx); } else if (regs.u.r8.bl == 0x86) { if (regs.u.r8.al == 0x02) { BX_INFO("PCI device %04x:%04x not found at index %d\n", regs.u.r16.dx, regs.u.r16.cx, regs.u.r16.si); } else { BX_INFO("no PCI device with class code 0x%02x%04x found at index %d\n", regs.u.r8.cl, regs.u.r16.dx, regs.u.r16.si); } } regs.u.r8.ah = regs.u.r8.bl; SetCF(iret_addr.flags); break; #endif default: SetCF(iret_addr.flags); // Unsupported } } void int70_function(regs, ds, iret_addr) pusha_regs_t regs; // regs pushed from PUSHA instruction Bit16u ds; // previous DS:, DS set to 0x0000 by asm wrapper iret_addr_t iret_addr; // CS,IP,Flags pushed from original INT call { // INT 70h: IRQ 8 - CMOS RTC interrupt from periodic or alarm modes Bit8u registerB = 0, registerC = 0; // Check which modes are enabled and have occurred. registerB = inb_cmos( 0xB ); registerC = inb_cmos( 0xC ); if( ( registerB & 0x60 ) != 0 ) { if( ( registerC & 0x20 ) != 0 ) { // Handle Alarm Interrupt. ASM_START sti int #0x4a cli ASM_END } if( ( registerC & 0x40 ) != 0 ) { // Handle Periodic Interrupt. if( read_byte_DS( 0x4A0 ) != 0 ) { // Wait Interval (Int 15, AH=83) active. Bit32u time, toggle; time = read_dword_DS( 0x49C ); // Time left in microseconds. if( time < 0x3D1 ) { // Done waiting. Bit16u segment, offset; segment = read_word_DS( 0x498 ); offset = read_word_DS( 0x49A ); write_byte_DS( 0x4A0, 0 ); // Turn of status byte. outb_cmos( 0xB, registerB & 0x37 ); // Clear the Periodic Interrupt. write_byte(read_byte(offset, segment) | 0x80, offset, segment); // Write to specified flag byte. } else { // Continue waiting. time -= 0x3D1; write_dword_DS( 0x49C, time ); } } } } ASM_START call eoi_both_pics ASM_END } ASM_START ;------------------------------------------ ;- INT74h : PS/2 mouse hardware interrupt - ;------------------------------------------ int74_handler: sti pusha push ds ;; save DS push #0x00 pop ds push 0x040E ;; push 0000:040E (opcodes 0xff, 0x36, 0x0E, 0x04) pop ds push #0x00 ;; placeholder for status push #0x00 ;; placeholder for X push #0x00 ;; placeholder for Y push #0x00 ;; placeholder for Z push #0x00 ;; placeholder for make_far_call boolean call _int74_function pop cx ;; remove make_far_call from stack jcxz int74_done ;; make far call to EBDA:0022 //CALL_EP(0x0022) ;; call far routine (call_Ep DS:0022 :opcodes 0xff, 0x1e, 0x22, 0x00) call far ptr[0x22] int74_done: cli call eoi_both_pics add sp, #8 ;; pop status, x, y, z pop ds ;; restore DS popa iret ;; This will perform an IRET, but will retain value of current CF ;; by altering flags on stack. Better than RETF #02. iret_modify_cf: jc carry_set push bp mov bp, sp and BYTE [bp + 0x06], #0xfe pop bp iret carry_set: push bp mov bp, sp or BYTE [bp + 0x06], #0x01 pop bp iret ;---------------------- ;- INT13h (relocated) - ;---------------------- ; ; int13_relocated is a little bit messed up since I played with it ; I have to rewrite it: ; - call a function that detect which function to call ; - make all called C function get the same parameters list ; int13_relocated: #if BX_ELTORITO_BOOT ;; check for an eltorito function cmp ah,#0x4a jb int13_not_eltorito cmp ah,#0x4d ja int13_not_eltorito pusha push es push ds push #int13_out jmp _int13_eltorito ;; ELDX not used int13_not_eltorito: push ax push bx push cx push dx ;; check if emulation active call _cdemu_isactive cmp al,#0x00 je int13_cdemu_inactive ;; check if access to the emulated drive call _cdemu_emulated_drive pop dx push dx cmp al,dl ;; int13 on emulated drive jne int13_nocdemu pop dx pop cx pop bx pop ax pusha push es push ds push #0x40 pop ds push 0x000E pop ds ;; Set DS to EBDA segment push #int13_out jmp _int13_cdemu ;; ELDX not used int13_nocdemu: and dl,#0xE0 ;; mask to get device class, including cdroms cmp al,dl ;; al is 0x00 or 0x80 jne int13_cdemu_inactive ;; inactive for device class pop dx pop cx pop bx pop ax push ax push cx push dx push bx dec dl ;; real drive is dl - 1 jmp int13_legacy int13_cdemu_inactive: pop dx pop cx pop bx pop ax #endif // BX_ELTORITO_BOOT int13_noeltorito: push ax push cx push dx push bx int13_legacy: push dx ;; push eltorito value of dx instead of sp push bp push si push di push es push ds push #0x40 pop ds ;; Set DS to 0x40 ;; now the 16-bit registers can be restored with: ;; pop ds; pop es; popa; iret ;; arguments passed to functions should be ;; DS, ES, DI, SI, BP, ELDX, BX, DX, CX, AX, IP, CS, FLAGS test dl, #0x80 jnz int13_notfloppy push #int13_out jmp _int13_diskette_function int13_notfloppy: #if BX_USE_ATADRV push 0x000E pop ds ;; Set DS to EBDA segment cmp dl, #0xE0 jb int13_notcdrom // ebx is modified: BSD 5.2.1 boot loader problem // someone should figure out which 32 bit register that actually are used shr ebx, #16 push bx call _int13_cdrom pop bx shl ebx, #16 jmp int13_out int13_notcdrom: #endif int13_disk: ;; int13_harddisk modifies high word of EAX shr eax, #16 push ax call _int13_harddisk pop ax shl eax, #16 int13_out: pop ds pop es popa iret ;---------- ;- INT18h - ;---------- int18_handler: ;; Boot Failure recovery: try the next device. ;; Reset SP and SS mov ax, #0xfffe mov sp, ax xor ax, ax mov ss, ax ;; Get the boot sequence number out of the IPL memory mov bx, #IPL_SEG mov ds, bx ;; Set segment mov bx, IPL_SEQUENCE_OFFSET ;; BX is now the sequence number inc bx ;; ++ mov IPL_SEQUENCE_OFFSET, bx ;; Write it back mov ds, ax ;; and reset the segment to zero. ;; Carry on in the INT 19h handler, using the new sequence number push bx jmp int19_next_boot ;---------- ;- INT19h - ;---------- int19_relocated: ;; Boot function, relocated ;; int19 was beginning to be really complex, so now it ;; just calls a C function that does the work push bp mov bp, sp ;; Reset SS and SP mov ax, #0xfffe mov sp, ax xor ax, ax mov ss, ax ;; Start from the first boot device (0, in AX) mov bx, #IPL_SEG mov ds, bx ;; Set segment to write to the IPL memory mov IPL_SEQUENCE_OFFSET, ax ;; Save the sequence number mov ds, ax ;; and reset the segment. push ax int19_next_boot: ;; Call the C code for the next boot device call _int19_function ;; Boot failed: invoke the boot recovery function int #0x18 ;---------------------- ;- POST: Floppy Drive - ;---------------------- floppy_drive_post: xor ax, ax mov ds, ax mov al, #0x00 mov 0x043e, al ;; drive 0 & 1 uncalibrated, no interrupt has occurred mov 0x043f, al ;; diskette motor status: read op, drive0, motors off mov 0x0440, al ;; diskette motor timeout counter: not active mov 0x0441, al ;; diskette controller status return code mov 0x0442, al ;; disk & diskette controller status register 0 mov 0x0443, al ;; diskette controller status register 1 mov 0x0444, al ;; diskette controller status register 2 mov 0x0445, al ;; diskette controller cylinder number mov 0x0446, al ;; diskette controller head number mov 0x0447, al ;; diskette controller sector number mov 0x0448, al ;; diskette controller bytes written mov 0x048b, al ;; diskette configuration data ;; ----------------------------------------------------------------- ;; (048F) diskette controller information ;; mov al, #0x10 ;; get CMOS diskette drive type out PORT_CMOS_INDEX, AL in AL, PORT_CMOS_DATA mov ah, al ;; save byte to AH look_drive0: shr al, #4 ;; look at top 4 bits for drive 0 jz f0_missing ;; jump if no drive0 mov bl, #0x07 ;; drive0 determined, multi-rate, has changed line jmp look_drive1 f0_missing: mov bl, #0x00 ;; no drive0 look_drive1: mov al, ah ;; restore from AH and al, #0x0f ;; look at bottom 4 bits for drive 1 jz f1_missing ;; jump if no drive1 or bl, #0x70 ;; drive1 determined, multi-rate, has changed line f1_missing: ;; leave high bits in BL zerod mov 0x048f, bl ;; put new val in BDA (diskette controller information) ;; ----------------------------------------------------------------- mov al, #0x00 mov 0x0490, al ;; diskette 0 media state mov 0x0491, al ;; diskette 1 media state ;; diskette 0,1 operational starting state ;; drive type has not been determined, ;; has no changed detection line mov 0x0492, al mov 0x0493, al mov 0x0494, al ;; diskette 0 current cylinder mov 0x0495, al ;; diskette 1 current cylinder mov al, #0x02 out PORT_DMA1_MASK_REG, al ;; clear DMA-1 channel 2 mask bit SET_INT_VECTOR(0x1E, #0xF000, #diskette_param_table2) SET_INT_VECTOR(0x40, #0xF000, #int13_diskette) SET_INT_VECTOR(0x0E, #0xF000, #int0e_handler) ;; IRQ 6 ret ;-------------------- ;- POST: HARD DRIVE - ;-------------------- ; relocated here because the primary POST area isnt big enough. hard_drive_post: // IRQ 14 = INT 76h // INT 76h calls INT 15h function ax=9100 mov al, #0x0a ; 0000 1010 = reserved, disable IRQ 14 mov dx, #0x03f6 out dx, al xor ax, ax mov ds, ax mov 0x0474, al /* hard disk status of last operation */ mov 0x0477, al /* hard disk port offset (XT only ???) */ mov 0x048c, al /* hard disk status register */ mov 0x048d, al /* hard disk error register */ mov 0x048e, al /* hard disk task complete flag */ mov al, #0x01 mov 0x0475, al /* hard disk number attached */ mov al, #0xc0 mov 0x0476, al /* hard disk control byte */ SET_INT_VECTOR(0x13, #0xF000, #int13_handler) SET_INT_VECTOR(0x76, #0xF000, #int76_handler) ;; INT 41h: hard disk 0 configuration pointer ;; INT 46h: hard disk 1 configuration pointer SET_INT_VECTOR(0x41, #EBDA_SEG, #0x003D) SET_INT_VECTOR(0x46, #EBDA_SEG, #0x004D) ;; move disk geometry data from CMOS to EBDA disk parameter table(s) mov al, #0x12 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA and al, #0xf0 cmp al, #0xf0 je post_d0_extended jmp check_for_hd1 post_d0_extended: mov al, #0x19 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA cmp al, #47 ;; decimal 47 - user definable je post_d0_type47 HALT(__LINE__) post_d0_type47: ;; CMOS purpose param table offset ;; 1b cylinders low 0 ;; 1c cylinders high 1 ;; 1d heads 2 ;; 1e write pre-comp low 5 ;; 1f write pre-comp high 6 ;; 20 retries/bad map/heads>8 8 ;; 21 landing zone low C ;; 22 landing zone high D ;; 23 sectors/track E mov ax, #EBDA_SEG mov ds, ax ;;; Filling EBDA table for hard disk 0. mov al, #0x1f out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov ah, al mov al, #0x1e out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov (0x003d + 0x05), ax ;; write precomp word mov al, #0x20 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov (0x003d + 0x08), al ;; drive control byte mov al, #0x22 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov ah, al mov al, #0x21 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov (0x003d + 0x0C), ax ;; landing zone word mov al, #0x1c ;; get cylinders word in AX out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA ;; high byte mov ah, al mov al, #0x1b out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA ;; low byte mov bx, ax ;; BX = cylinders mov al, #0x1d out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov cl, al ;; CL = heads mov al, #0x23 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov dl, al ;; DL = sectors cmp bx, #1024 jnbe hd0_post_logical_chs ;; if cylinders > 1024, use translated style CHS hd0_post_physical_chs: ;; no logical CHS mapping used, just physical CHS ;; use Standard Fixed Disk Parameter Table (FDPT) mov (0x003d + 0x00), bx ;; number of physical cylinders mov (0x003d + 0x02), cl ;; number of physical heads mov (0x003d + 0x0E), dl ;; number of physical sectors jmp check_for_hd1 hd0_post_logical_chs: ;; complies with Phoenix style Translated Fixed Disk Parameter Table (FDPT) mov (0x003d + 0x09), bx ;; number of physical cylinders mov (0x003d + 0x0b), cl ;; number of physical heads mov (0x003d + 0x04), dl ;; number of physical sectors mov (0x003d + 0x0e), dl ;; number of logical sectors (same) mov al, #0xa0 mov (0x003d + 0x03), al ;; A0h signature, indicates translated table cmp bx, #2048 jnbe hd0_post_above_2048 ;; 1024 < c <= 2048 cylinders shr bx, #0x01 shl cl, #0x01 jmp hd0_post_store_logical hd0_post_above_2048: cmp bx, #4096 jnbe hd0_post_above_4096 ;; 2048 < c <= 4096 cylinders shr bx, #0x02 shl cl, #0x02 jmp hd0_post_store_logical hd0_post_above_4096: cmp bx, #8192 jnbe hd0_post_above_8192 ;; 4096 < c <= 8192 cylinders shr bx, #0x03 shl cl, #0x03 jmp hd0_post_store_logical hd0_post_above_8192: ;; 8192 < c <= 16384 cylinders shr bx, #0x04 shl cl, #0x04 hd0_post_store_logical: mov (0x003d + 0x00), bx ;; number of physical cylinders mov (0x003d + 0x02), cl ;; number of physical heads ;; checksum mov cl, #0x0f ;; repeat count mov si, #0x003d ;; offset to disk0 FDPT mov al, #0x00 ;; sum hd0_post_checksum_loop: add al, [si] inc si dec cl jnz hd0_post_checksum_loop not al ;; now take 2s complement inc al mov [si], al ;;; Done filling EBDA table for hard disk 0. check_for_hd1: ;; is there really a second hard disk? if not, return now mov al, #0x12 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA and al, #0x0f jnz post_d1_exists ret post_d1_exists: ;; check that the hd type is really 0x0f. cmp al, #0x0f jz post_d1_extended HALT(__LINE__) post_d1_extended: ;; check that the extended type is 47 - user definable mov al, #0x1a out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA cmp al, #47 ;; decimal 47 - user definable je post_d1_type47 HALT(__LINE__) post_d1_type47: ;; Table for disk1. ;; CMOS purpose param table offset ;; 0x24 cylinders low 0 ;; 0x25 cylinders high 1 ;; 0x26 heads 2 ;; 0x27 write pre-comp low 5 ;; 0x28 write pre-comp high 6 ;; 0x29 heads>8 8 ;; 0x2a landing zone low C ;; 0x2b landing zone high D ;; 0x2c sectors/track E ;;; Fill EBDA table for hard disk 1. mov ax, #EBDA_SEG mov ds, ax mov al, #0x28 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov ah, al mov al, #0x27 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov (0x004d + 0x05), ax ;; write precomp word mov al, #0x29 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov (0x004d + 0x08), al ;; drive control byte mov al, #0x2b out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov ah, al mov al, #0x2a out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov (0x004d + 0x0C), ax ;; landing zone word mov al, #0x25 ;; get cylinders word in AX out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA ;; high byte mov ah, al mov al, #0x24 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA ;; low byte mov bx, ax ;; BX = cylinders mov al, #0x26 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov cl, al ;; CL = heads mov al, #0x2c out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov dl, al ;; DL = sectors cmp bx, #1024 jnbe hd1_post_logical_chs ;; if cylinders > 1024, use translated style CHS hd1_post_physical_chs: ;; no logical CHS mapping used, just physical CHS ;; use Standard Fixed Disk Parameter Table (FDPT) mov (0x004d + 0x00), bx ;; number of physical cylinders mov (0x004d + 0x02), cl ;; number of physical heads mov (0x004d + 0x0E), dl ;; number of physical sectors ret hd1_post_logical_chs: ;; complies with Phoenix style Translated Fixed Disk Parameter Table (FDPT) mov (0x004d + 0x09), bx ;; number of physical cylinders mov (0x004d + 0x0b), cl ;; number of physical heads mov (0x004d + 0x04), dl ;; number of physical sectors mov (0x004d + 0x0e), dl ;; number of logical sectors (same) mov al, #0xa0 mov (0x004d + 0x03), al ;; A0h signature, indicates translated table cmp bx, #2048 jnbe hd1_post_above_2048 ;; 1024 < c <= 2048 cylinders shr bx, #0x01 shl cl, #0x01 jmp hd1_post_store_logical hd1_post_above_2048: cmp bx, #4096 jnbe hd1_post_above_4096 ;; 2048 < c <= 4096 cylinders shr bx, #0x02 shl cl, #0x02 jmp hd1_post_store_logical hd1_post_above_4096: cmp bx, #8192 jnbe hd1_post_above_8192 ;; 4096 < c <= 8192 cylinders shr bx, #0x03 shl cl, #0x03 jmp hd1_post_store_logical hd1_post_above_8192: ;; 8192 < c <= 16384 cylinders shr bx, #0x04 shl cl, #0x04 hd1_post_store_logical: mov (0x004d + 0x00), bx ;; number of physical cylinders mov (0x004d + 0x02), cl ;; number of physical heads ;; checksum mov cl, #0x0f ;; repeat count mov si, #0x004d ;; offset to disk0 FDPT mov al, #0x00 ;; sum hd1_post_checksum_loop: add al, [si] inc si dec cl jnz hd1_post_checksum_loop not al ;; now take 2s complement inc al mov [si], al ;;; Done filling EBDA table for hard disk 1. ret ;-------------------- ;- POST: EBDA segment ;-------------------- ; relocated here because the primary POST area isnt big enough. ebda_post: #if BX_USE_EBDA mov ax, #EBDA_SEG mov ds, ax mov byte ptr [0x0], #EBDA_SIZE #endif xor ax, ax ; mov EBDA seg into 0x40E mov ds, ax mov word ptr [0x40E], #EBDA_SEG ret;; ;-------------------- ;- POST: EOI + jmp via [0x40:67) ;-------------------- ; relocated here because the primary POST area isnt big enough. eoi_jmp_post: mov al, #0x11 ; send initialisation commands out PORT_PIC1_CMD, al out PORT_PIC2_CMD, al mov al, #0x08 out PORT_PIC1_DATA, al mov al, #0x70 out PORT_PIC2_DATA, al mov al, #0x04 out PORT_PIC1_DATA, al mov al, #0x02 out PORT_PIC2_DATA, al mov al, #0x01 out PORT_PIC1_DATA, al out PORT_PIC2_DATA, al mov al, #0xb8 out PORT_PIC1_DATA, AL ;master pic: unmask IRQ 0, 1, 2, 6 #if BX_USE_PS2_MOUSE mov al, #0x8f #else mov al, #0x9f #endif out PORT_PIC2_DATA, AL ;slave pic: unmask IRQ 12, 13, 14 mov al, #0x20 out PORT_PIC2_CMD, al ;; slave PIC EOI mov al, #0x20 out PORT_PIC1_CMD, al ;; master PIC EOI jmp_post_0x467: xor ax, ax mov ds, ax jmp far ptr [0x467] iret_post_0x467: xor ax, ax mov ds, ax mov sp, [0x467] mov ss, [0x469] iret retf_post_0x467: xor ax, ax mov ds, ax mov sp, [0x467] mov ss, [0x469] retf s3_post: mov sp, #0xffe #if BX_ROMBIOS32 call rombios32_init #endif call _s3_resume mov bl, #0x00 and ax, ax jz normal_post call _s3_resume_panic ;-------------------- eoi_both_pics: mov al, #0x20 out PORT_PIC2_CMD, al ;; slave PIC EOI eoi_master_pic: mov al, #0x20 out PORT_PIC1_CMD, al ;; master PIC EOI ret ;-------------------- BcdToBin: ;; in: AL in BCD format ;; out: AL in binary format, AH will always be 0 ;; trashes BX mov bl, al and bl, #0x0f ;; bl has low digit shr al, #4 ;; al has high digit mov bh, #10 mul al, bh ;; multiply high digit by 10 (result in AX) add al, bl ;; then add low digit ret ;-------------------- timer_tick_post: ;; Setup the Timer Ticks Count (0x46C:dword) and ;; Timer Ticks Roller Flag (0x470:byte) ;; The Timer Ticks Count needs to be set according to ;; the current CMOS time, as if ticks have been occurring ;; at 18.2hz since midnight up to this point. Calculating ;; this is a little complicated. Here are the factors I gather ;; regarding this. 14,318,180 hz was the original clock speed, ;; chosen so it could be divided by either 3 to drive the 5Mhz CPU ;; at the time, or 4 to drive the CGA video adapter. The div3 ;; source was divided again by 4 to feed a 1.193Mhz signal to ;; the timer. With a maximum 16bit timer count, this is again ;; divided down by 65536 to 18.2hz. ;; ;; 14,318,180 Hz clock ;; /3 = 4,772,726 Hz fed to original 5Mhz CPU ;; /4 = 1,193,181 Hz fed to timer ;; /65536 (maximum timer count) = 18.20650736 ticks/second ;; 1 second = 18.20650736 ticks ;; 1 minute = 1092.390442 ticks ;; 1 hour = 65543.42651 ticks ;; ;; Given the values in the CMOS clock, one could calculate ;; the number of ticks by the following: ;; ticks = (BcdToBin(seconds) * 18.206507) + ;; (BcdToBin(minutes) * 1092.3904) ;; (BcdToBin(hours) * 65543.427) ;; To get a little more accuracy, since Im using integer ;; arithmetic, I use: ;; ticks = (((BcdToBin(hours) * 60 + BcdToBin(minutes)) * 60 + BcdToBin(seconds)) * (18 * 4294967296 + 886942379)) / 4294967296 ;; assuming DS=0000 ;; get CMOS hours xor eax, eax ;; clear EAX mov al, #0x04 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA ;; AL has CMOS hours in BCD call BcdToBin ;; EAX now has hours in binary imul eax, #60 mov edx, eax ;; get CMOS minutes xor eax, eax ;; clear EAX mov al, #0x02 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA ;; AL has CMOS minutes in BCD call BcdToBin ;; EAX now has minutes in binary add eax, edx imul eax, #60 mov edx, eax ;; get CMOS seconds xor eax, eax ;; clear EAX mov al, #0x00 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA ;; AL has CMOS seconds in BCD call BcdToBin ;; EAX now has seconds in binary add eax, edx ;; multiplying 18.2065073649 mov ecx, eax imul ecx, #18 mov edx, #886942379 mul edx add ecx, edx mov 0x46C, ecx ;; Timer Ticks Count xor al, al mov 0x470, al ;; Timer Ticks Rollover Flag ret ;-------------------- int76_handler: ;; record completion in BIOS task complete flag push ax push ds mov ax, #0x0040 mov ds, ax mov BYTE 0x008E, #0xff call eoi_both_pics ;; Notify fixed disk interrupt complete w/ int 15h, function AX=9100 mov ax, #0x9100 int 0x15 pop ds pop ax iret ;-------------------- #if BX_APM use32 386 #define APM_PROT32 #include "apmbios.S" use16 386 #define APM_PROT16 #include "apmbios.S" #define APM_REAL #include "apmbios.S" #endif ;-------------------- #if BX_PCIBIOS use32 386 .align 16 bios32_structure: db 0x5f, 0x33, 0x32, 0x5f ;; "_32_" signature dw bios32_entry_point, 0xf ;; 32 bit physical address db 0 ;; revision level ;; length in paragraphs and checksum stored in a word to prevent errors dw (~(((bios32_entry_point >> 8) + (bios32_entry_point & 0xff) + 0x32) \ & 0xff) << 8) + 0x01 db 0,0,0,0,0 ;; reserved .align 16 bios32_entry_point: pushfd cmp eax, #0x49435024 ;; "$PCI" jne unknown_service mov eax, #0x80000000 mov dx, #0x0cf8 out dx, eax mov dx, #0x0cfc in eax, dx #ifdef PCI_FIXED_HOST_BRIDGE cmp eax, #PCI_FIXED_HOST_BRIDGE jne unknown_service #else ;; say ok if a device is present cmp eax, #0xffffffff je unknown_service #endif mov ebx, #0x000f0000 mov ecx, #0x10000 mov edx, #pcibios_protected xor al, al jmp bios32_end unknown_service: mov al, #0x80 bios32_end: #ifdef BX_QEMU and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu #endif popfd retf .align 16 pcibios_protected: pushfd cli push esi push edi cmp al, #0x01 ;; installation check jne pci_pro_f02 mov bx, #0x0210 mov cx, #0 mov edx, #0x20494350 ;; "PCI " mov al, #0x01 jmp pci_pro_ok pci_pro_f02: ;; find pci device cmp al, #0x02 jne pci_pro_f03 shl ecx, #16 mov cx, dx xor bx, bx mov di, #0x00 pci_pro_devloop: call pci_pro_select_reg mov dx, #0x0cfc in eax, dx cmp eax, ecx jne pci_pro_nextdev cmp si, #0 je pci_pro_ok dec si pci_pro_nextdev: inc bx cmp bx, #0x0100 jne pci_pro_devloop mov ah, #0x86 jmp pci_pro_fail pci_pro_f03: ;; find class code cmp al, #0x03 jne pci_pro_f08 xor bx, bx mov di, #0x08 pci_pro_devloop2: call pci_pro_select_reg mov dx, #0x0cfc in eax, dx shr eax, #8 cmp eax, ecx jne pci_pro_nextdev2 cmp si, #0 je pci_pro_ok dec si pci_pro_nextdev2: inc bx cmp bx, #0x0100 jne pci_pro_devloop2 mov ah, #0x86 jmp pci_pro_fail pci_pro_f08: ;; read configuration byte cmp al, #0x08 jne pci_pro_f09 call pci_pro_select_reg push edx mov dx, di and dx, #0x03 add dx, #0x0cfc in al, dx pop edx mov cl, al jmp pci_pro_ok pci_pro_f09: ;; read configuration word cmp al, #0x09 jne pci_pro_f0a call pci_pro_select_reg push edx mov dx, di and dx, #0x02 add dx, #0x0cfc in ax, dx pop edx mov cx, ax jmp pci_pro_ok pci_pro_f0a: ;; read configuration dword cmp al, #0x0a jne pci_pro_f0b call pci_pro_select_reg push edx mov dx, #0x0cfc in eax, dx pop edx mov ecx, eax jmp pci_pro_ok pci_pro_f0b: ;; write configuration byte cmp al, #0x0b jne pci_pro_f0c call pci_pro_select_reg push edx mov dx, di and dx, #0x03 add dx, #0x0cfc mov al, cl out dx, al pop edx jmp pci_pro_ok pci_pro_f0c: ;; write configuration word cmp al, #0x0c jne pci_pro_f0d call pci_pro_select_reg push edx mov dx, di and dx, #0x02 add dx, #0x0cfc mov ax, cx out dx, ax pop edx jmp pci_pro_ok pci_pro_f0d: ;; write configuration dword cmp al, #0x0d jne pci_pro_unknown call pci_pro_select_reg push edx mov dx, #0x0cfc mov eax, ecx out dx, eax pop edx jmp pci_pro_ok pci_pro_unknown: mov ah, #0x81 pci_pro_fail: pop edi pop esi #ifdef BX_QEMU and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu #endif popfd stc retf pci_pro_ok: xor ah, ah pop edi pop esi #ifdef BX_QEMU and dword ptr[esp+8],0xfffffffc ;; reset CS.RPL for kqemu #endif popfd clc retf pci_pro_select_reg: push edx mov eax, #0x800000 mov ax, bx shl eax, #8 and di, #0xff or ax, di and al, #0xfc mov dx, #0x0cf8 out dx, eax pop edx ret use16 386 pcibios_real: push eax push dx mov eax, #0x80000000 mov dx, #0x0cf8 out dx, eax mov dx, #0x0cfc in eax, dx #ifdef PCI_FIXED_HOST_BRIDGE cmp eax, #PCI_FIXED_HOST_BRIDGE je pci_present #else ;; say ok if a device is present cmp eax, #0xffffffff jne pci_present #endif pop dx pop eax mov ah, #0xff stc ret pci_present: pop dx pop eax cmp al, #0x01 ;; installation check jne pci_real_f02 mov ax, #0x0001 mov bx, #0x0210 mov cx, #0 mov edx, #0x20494350 ;; "PCI " mov edi, #0xf0000 mov di, #pcibios_protected clc ret pci_real_f02: ;; find pci device push esi push edi cmp al, #0x02 jne pci_real_f03 shl ecx, #16 mov cx, dx xor bx, bx mov di, #0x00 pci_real_devloop: call pci_real_select_reg mov dx, #0x0cfc in eax, dx cmp eax, ecx jne pci_real_nextdev cmp si, #0 je pci_real_ok dec si pci_real_nextdev: inc bx cmp bx, #0x0100 jne pci_real_devloop mov dx, cx shr ecx, #16 mov ax, #0x8602 jmp pci_real_fail pci_real_f03: ;; find class code cmp al, #0x03 jne pci_real_f08 xor bx, bx mov di, #0x08 pci_real_devloop2: call pci_real_select_reg mov dx, #0x0cfc in eax, dx shr eax, #8 cmp eax, ecx jne pci_real_nextdev2 cmp si, #0 je pci_real_ok dec si pci_real_nextdev2: inc bx cmp bx, #0x0100 jne pci_real_devloop2 mov dx, cx shr ecx, #16 mov ax, #0x8603 jmp pci_real_fail pci_real_f08: ;; read configuration byte cmp al, #0x08 jne pci_real_f09 call pci_real_select_reg push dx mov dx, di and dx, #0x03 add dx, #0x0cfc in al, dx pop dx mov cl, al jmp pci_real_ok pci_real_f09: ;; read configuration word cmp al, #0x09 jne pci_real_f0a call pci_real_select_reg push dx mov dx, di and dx, #0x02 add dx, #0x0cfc in ax, dx pop dx mov cx, ax jmp pci_real_ok pci_real_f0a: ;; read configuration dword cmp al, #0x0a jne pci_real_f0b call pci_real_select_reg push dx mov dx, #0x0cfc in eax, dx pop dx mov ecx, eax jmp pci_real_ok pci_real_f0b: ;; write configuration byte cmp al, #0x0b jne pci_real_f0c call pci_real_select_reg push dx mov dx, di and dx, #0x03 add dx, #0x0cfc mov al, cl out dx, al pop dx jmp pci_real_ok pci_real_f0c: ;; write configuration word cmp al, #0x0c jne pci_real_f0d call pci_real_select_reg push dx mov dx, di and dx, #0x02 add dx, #0x0cfc mov ax, cx out dx, ax pop dx jmp pci_real_ok pci_real_f0d: ;; write configuration dword cmp al, #0x0d jne pci_real_f0e call pci_real_select_reg push dx mov dx, #0x0cfc mov eax, ecx out dx, eax pop dx jmp pci_real_ok pci_real_f0e: ;; get irq routing options cmp al, #0x0e jne pci_real_unknown push ax mov ax, #pci_routing_table_structure_end - pci_routing_table_structure_start SEG ES cmp word ptr [di], ax jb pci_real_too_small stosw pushf push es push cx cld mov si, #pci_routing_table_structure_start push cs pop ds SEG ES les di, [di+2] mov cx, ax rep movsb pop cx pop es popf pop ax mov bx, #(1 << 9) | (1 << 11) ;; irq 9 and 11 are used jmp pci_real_ok pci_real_too_small: stosw pop ax mov ah, #0x89 jmp pci_real_fail pci_real_unknown: mov ah, #0x81 pci_real_fail: pop edi pop esi stc ret pci_real_ok: xor ah, ah pop edi pop esi clc ret pci_real_select_reg: push dx mov eax, #0x800000 mov ax, bx shl eax, #8 and di, #0xff or ax, di and al, #0xfc mov dx, #0x0cf8 out dx, eax pop dx ret .align 16 pci_routing_table_structure: db 0x24, 0x50, 0x49, 0x52 ;; "$PIR" signature db 0, 1 ;; version dw 32 + (6 * 16) ;; table size db 0 ;; PCI interrupt router bus db 0x08 ;; PCI interrupt router DevFunc dw 0x0000 ;; PCI exclusive IRQs dw 0x8086 ;; compatible PCI interrupt router vendor ID dw 0x122e ;; compatible PCI interrupt router device ID dw 0,0 ;; Miniport data db 0,0,0,0,0,0,0,0,0,0,0 ;; reserved db 0x37 ;; checksum pci_routing_table_structure_start: ;; first slot entry PCI-to-ISA (embedded) db 0 ;; pci bus number db 0x08 ;; pci device number (bit 7-3) db 0x60 ;; link value INTA#: pointer into PCI2ISA config space dw 0xdef8 ;; IRQ bitmap INTA# db 0x61 ;; link value INTB# dw 0xdef8 ;; IRQ bitmap INTB# db 0x62 ;; link value INTC# dw 0xdef8 ;; IRQ bitmap INTC# db 0x63 ;; link value INTD# dw 0xdef8 ;; IRQ bitmap INTD# db 0 ;; physical slot (0 = embedded) db 0 ;; reserved ;; second slot entry: 1st PCI slot db 0 ;; pci bus number db 0x10 ;; pci device number (bit 7-3) db 0x61 ;; link value INTA# dw 0xdef8 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# dw 0xdef8 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# dw 0xdef8 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# dw 0xdef8 ;; IRQ bitmap INTD# db 1 ;; physical slot (0 = embedded) db 0 ;; reserved ;; third slot entry: 2nd PCI slot db 0 ;; pci bus number db 0x18 ;; pci device number (bit 7-3) db 0x62 ;; link value INTA# dw 0xdef8 ;; IRQ bitmap INTA# db 0x63 ;; link value INTB# dw 0xdef8 ;; IRQ bitmap INTB# db 0x60 ;; link value INTC# dw 0xdef8 ;; IRQ bitmap INTC# db 0x61 ;; link value INTD# dw 0xdef8 ;; IRQ bitmap INTD# db 2 ;; physical slot (0 = embedded) db 0 ;; reserved ;; 4th slot entry: 3rd PCI slot db 0 ;; pci bus number db 0x20 ;; pci device number (bit 7-3) db 0x63 ;; link value INTA# dw 0xdef8 ;; IRQ bitmap INTA# db 0x60 ;; link value INTB# dw 0xdef8 ;; IRQ bitmap INTB# db 0x61 ;; link value INTC# dw 0xdef8 ;; IRQ bitmap INTC# db 0x62 ;; link value INTD# dw 0xdef8 ;; IRQ bitmap INTD# db 3 ;; physical slot (0 = embedded) db 0 ;; reserved ;; 5th slot entry: 4rd PCI slot db 0 ;; pci bus number db 0x28 ;; pci device number (bit 7-3) db 0x60 ;; link value INTA# dw 0xdef8 ;; IRQ bitmap INTA# db 0x61 ;; link value INTB# dw 0xdef8 ;; IRQ bitmap INTB# db 0x62 ;; link value INTC# dw 0xdef8 ;; IRQ bitmap INTC# db 0x63 ;; link value INTD# dw 0xdef8 ;; IRQ bitmap INTD# db 4 ;; physical slot (0 = embedded) db 0 ;; reserved ;; 6th slot entry: 5rd PCI slot db 0 ;; pci bus number db 0x30 ;; pci device number (bit 7-3) db 0x61 ;; link value INTA# dw 0xdef8 ;; IRQ bitmap INTA# db 0x62 ;; link value INTB# dw 0xdef8 ;; IRQ bitmap INTB# db 0x63 ;; link value INTC# dw 0xdef8 ;; IRQ bitmap INTC# db 0x60 ;; link value INTD# dw 0xdef8 ;; IRQ bitmap INTD# db 5 ;; physical slot (0 = embedded) db 0 ;; reserved pci_routing_table_structure_end: #if !BX_ROMBIOS32 pci_irq_list: db 11, 10, 9, 5; pcibios_init_sel_reg: push eax mov eax, #0x800000 mov ax, bx shl eax, #8 and dl, #0xfc or al, dl mov dx, #0x0cf8 out dx, eax pop eax ret pcibios_init_iomem_bases: push bp mov bp, sp mov eax, #0xc0000000 ;; base for memory init push eax mov ax, #0xc000 ;; base for i/o init push ax mov ax, #0x0010 ;; start at base address #0 push ax mov bx, #0x0008 pci_init_io_loop1: mov dl, #0x00 call pcibios_init_sel_reg mov dx, #0x0cfc in ax, dx cmp ax, #0xffff jz next_pci_dev mov dl, #0x04 ;; disable i/o and memory space access call pcibios_init_sel_reg mov dx, #0x0cfc in al, dx and al, #0xfc out dx, al pci_init_io_loop2: mov dl, [bp-8] call pcibios_init_sel_reg mov dx, #0x0cfc in eax, dx test al, #0x01 jnz init_io_base mov ecx, eax mov eax, #0xffffffff out dx, eax in eax, dx cmp eax, ecx je next_pci_base not eax mov ecx, eax mov eax, [bp-4] out dx, eax add eax, ecx ;; calculate next free mem base add eax, #0x01000000 and eax, #0xff000000 mov [bp-4], eax jmp next_pci_base init_io_base: mov cx, ax mov ax, #0xffff out dx, ax in ax, dx cmp ax, cx je next_pci_base xor ax, #0xfffe mov cx, ax mov ax, [bp-6] out dx, ax add ax, cx ;; calculate next free i/o base add ax, #0x0100 and ax, #0xff00 mov [bp-6], ax next_pci_base: mov al, [bp-8] add al, #0x04 cmp al, #0x28 je enable_iomem_space mov byte ptr[bp-8], al jmp pci_init_io_loop2 enable_iomem_space: mov dl, #0x04 ;; enable i/o and memory space access if available call pcibios_init_sel_reg mov dx, #0x0cfc in al, dx or al, #0x07 out dx, al next_pci_dev: mov byte ptr[bp-8], #0x10 inc bx cmp bx, #0x0100 jne pci_init_io_loop1 leave ret pcibios_init_set_elcr: push ax push cx mov dx, #0x04d0 test al, #0x08 jz is_master_pic inc dx and al, #0x07 is_master_pic: mov cl, al mov bl, #0x01 shl bl, cl in al, dx or al, bl out dx, al pop cx pop ax ret pcibios_init_irqs: push ds push bp push cs pop ds mov dx, #0x04d0 ;; reset ELCR1 + ELCR2 mov al, #0x00 out dx, al inc dx out dx, al mov si, #pci_routing_table_structure mov bh, [si+8] mov bl, [si+9] mov dl, #0x00 call pcibios_init_sel_reg mov dx, #0x0cfc in ax, dx cmp ax, [si+12] ;; check irq router jne pci_init_end mov dl, [si+34] call pcibios_init_sel_reg push bx ;; save irq router bus + devfunc mov dx, #0x0cfc mov ax, #0x8080 out dx, ax ;; reset PIRQ route control add dx, #2 out dx, ax mov ax, [si+6] sub ax, #0x20 shr ax, #4 mov cx, ax add si, #0x20 ;; set pointer to 1st entry mov bp, sp push #pci_irq_list push #0x00 pci_init_irq_loop1: mov bh, [si] mov bl, [si+1] pci_init_irq_loop2: mov dl, #0x00 call pcibios_init_sel_reg mov dx, #0x0cfc in ax, dx cmp ax, #0xffff jnz pci_test_int_pin test bl, #0x07 jz next_pir_entry jmp next_pci_func pci_test_int_pin: mov dl, #0x3c call pcibios_init_sel_reg mov dx, #0x0cfd in al, dx and al, #0x07 jz next_pci_func dec al ;; determine pirq reg mov dl, #0x03 mul al, dl add al, #0x02 xor ah, ah mov bx, ax mov al, [si+bx] mov dl, al mov bx, [bp] call pcibios_init_sel_reg mov dx, #0x0cfc and al, #0x03 add dl, al in al, dx cmp al, #0x80 jb pirq_found mov bx, [bp-2] ;; pci irq list pointer mov al, [bx] out dx, al inc bx mov [bp-2], bx call pcibios_init_set_elcr pirq_found: mov bh, [si] mov bl, [si+1] add bl, [bp-3] ;; pci function number mov dl, #0x3c call pcibios_init_sel_reg mov dx, #0x0cfc out dx, al next_pci_func: inc byte ptr[bp-3] inc bl test bl, #0x07 jnz pci_init_irq_loop2 next_pir_entry: add si, #0x10 mov byte ptr[bp-3], #0x00 loop pci_init_irq_loop1 mov sp, bp pop bx pci_init_end: pop bp pop ds ret #endif // !BX_ROMBIOS32 #endif // BX_PCIBIOS #if BX_ROMBIOS32 rombios32_init: ;; save a20 and enable it in al, PORT_A20 push ax or al, #0x02 out PORT_A20, al ;; save SS:SP to the BDA xor ax, ax mov ds, ax mov 0x0469, ss mov 0x0467, sp SEG CS lidt [pmode_IDT_info] SEG CS lgdt [rombios32_gdt_48] ;; set PE bit in CR0 mov eax, cr0 or al, #0x01 mov cr0, eax ;; start protected mode code: ljmpl 0x10:rombios32_init1 db 0x66, 0xea dw rombios32_05 dw 0x000f ;; high 16 bit address dw 0x0010 use32 386 rombios32_05: ;; init data segments mov eax, #0x18 mov ds, ax mov es, ax mov ss, ax xor eax, eax mov fs, ax mov gs, ax cld ;; init the stack pointer to point below EBDA mov ax, [0x040e] shl eax, #4 mov esp, #-0x10 add esp, eax ;; pass pointer to s3_resume_flag and s3_resume_vector to rombios32 push #0x04b0 push #0x04b2 ;; call rombios32 code mov eax, #0x000e0000 call eax ;; return to 16 bit protected mode first db 0xea dd rombios32_10 dw 0x20 use16 386 rombios32_10: ;; restore data segment limits to 0xffff mov ax, #0x28 mov ds, ax mov es, ax mov ss, ax mov fs, ax mov gs, ax ;; reset PE bit in CR0 mov eax, cr0 and al, #0xFE mov cr0, eax ;; far jump to flush CPU queue after transition to real mode JMP_AP(0xf000, rombios32_real_mode) rombios32_real_mode: ;; restore IDT to normal real-mode defaults SEG CS lidt [rmode_IDT_info] xor ax, ax mov ds, ax mov es, ax mov fs, ax mov gs, ax ;; restore SS:SP from the BDA mov ss, 0x0469 xor esp, esp mov sp, 0x0467 ;; restore a20 pop ax out PORT_A20, al ret rombios32_gdt_48: dw 0x30 dw rombios32_gdt dw 0x000f rombios32_gdt: dw 0, 0, 0, 0 dw 0, 0, 0, 0 dw 0xffff, 0, 0x9b00, 0x00cf ; 32 bit flat code segment (0x10) dw 0xffff, 0, 0x9300, 0x00cf ; 32 bit flat data segment (0x18) dw 0xffff, 0, 0x9b0f, 0x0000 ; 16 bit code segment base=0xf0000 limit=0xffff dw 0xffff, 0, 0x9300, 0x0000 ; 16 bit data segment base=0x0 limit=0xffff #endif // BX_ROMBIOS32 ; parallel port detection: base address in DX, index in BX, timeout in CL detect_parport: push dx add dx, #2 in al, dx and al, #0xdf ; clear input mode out dx, al pop dx mov al, #0xaa out dx, al in al, dx cmp al, #0xaa jne no_parport push bx shl bx, #1 mov [bx+0x408], dx ; Parallel I/O address pop bx mov [bx+0x478], cl ; Parallel printer timeout inc bx no_parport: ret ; serial port detection: base address in DX, index in BX, timeout in CL detect_serial: push dx inc dx mov al, #0x02 out dx, al in al, dx cmp al, #0x02 jne no_serial inc dx in al, dx cmp al, #0x02 jne no_serial dec dx xor al, al out dx, al pop dx push bx shl bx, #1 mov [bx+0x400], dx ; Serial I/O address pop bx mov [bx+0x47c], cl ; Serial timeout inc bx ret no_serial: pop dx ret rom_checksum: pusha push ds xor ax, ax xor bx, bx xor cx, cx xor dx, dx mov ch, [2] shl cx, #1 jnc checksum_loop jz checksum_loop xchg dx, cx dec cx checksum_loop: add al, [bx] inc bx loop checksum_loop test dx, dx je checksum_out add al, [bx] mov cx, dx mov dx, ds add dh, #0x10 mov ds, dx xor dx, dx xor bx, bx jmp checksum_loop checksum_out: and al, #0xff pop ds popa ret .align 16 #if !BX_PNPBIOS ;; Make sure the pnpbios structure is *not* aligned, so OSes will not see it if ;; they scan. db 0 #endif pnpbios_structure: .ascii "$PnP" db 0x10 ;; version db 0x21 ;; length dw 0x0 ;; control field db 0xd1 ;; checksum dd 0xf0000 ;; event notification flag address dw pnpbios_real ;; real mode 16 bit offset dw 0xf000 ;; real mode 16 bit segment dw pnpbios_prot ;; 16 bit protected mode offset dd 0xf0000 ;; 16 bit protected mode segment base dd 0x0 ;; OEM device identifier dw 0xf000 ;; real mode 16 bit data segment dd 0xf0000 ;; 16 bit protected mode segment base pnpbios_prot: push ebp mov ebp, esp jmp pnpbios_code pnpbios_real: push ebp movzx ebp, sp pnpbios_code: mov ax, 8[ebp] cmp ax, #0x60 ;; Get Version and Installation Check jnz pnpbios_fail push es push di les di, 10[bp] mov ax, #0x0101 stosw pop di pop es xor ax, ax ;; SUCCESS jmp pnpbios_exit pnpbios_fail: mov ax, #0x82 ;; FUNCTION_NOT_SUPPORTED pnpbios_exit: pop ebp retf rom_scan: ;; Scan for existence of valid expansion ROMS. ;; Video ROM: from 0xC0000..0xC7FFF in 2k increments ;; General ROM: from 0xC8000..0xDFFFF in 2k increments ;; System ROM: only 0xE0000 ;; ;; Header: ;; Offset Value ;; 0 0x55 ;; 1 0xAA ;; 2 ROM length in 512-byte blocks ;; 3 ROM initialization entry point (FAR CALL) rom_scan_loop: push ax ;; Save AX mov ds, cx mov ax, #0x0004 ;; start with increment of 4 (512-byte) blocks = 2k cmp [0], #0xAA55 ;; look for signature jne rom_scan_increment call rom_checksum jnz rom_scan_increment mov al, [2] ;; change increment to ROM length in 512-byte blocks ;; We want our increment in 512-byte quantities, rounded to ;; the nearest 2k quantity, since we only scan at 2k intervals. test al, #0x03 jz block_count_rounded and al, #0xfc ;; needs rounding up add al, #0x04 block_count_rounded: xor bx, bx ;; Restore DS back to 0000: mov ds, bx push ax ;; Save AX push di ;; Save DI ;; Push addr of ROM entry point push cx ;; Push seg push #0x0003 ;; Push offset ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS. ;; That should stop it grabbing INT 19h; we will use its BEV instead. mov ax, #0xf000 mov es, ax lea di, pnpbios_structure mov bp, sp ;; Call ROM init routine using seg:off on stack db 0xff ;; call_far ss:[bp+0] db 0x5e db 0 cli ;; In case expansion ROM BIOS turns IF on add sp, #2 ;; Pop offset value pop cx ;; Pop seg value (restore CX) ;; Look at the ROM's PnP Expansion header. Properly, we're supposed ;; to init all the ROMs and then go back and build an IPL table of ;; all the bootable devices, but we can get away with one pass. mov ds, cx ;; ROM base mov bx, 0x001a ;; 0x1A is the offset into ROM header that contains... mov ax, [bx] ;; the offset of PnP expansion header, where... cmp ax, #0x5024 ;; we look for signature "$PnP" jne no_bev mov ax, 2[bx] cmp ax, #0x506e jne no_bev mov ax, 0x16[bx] ;; 0x16 is the offset of Boot Connection Vector cmp ax, #0x0000 je no_bcv ;; Option ROM has BCV. Run it now. push cx ;; Push seg push ax ;; Push offset ;; Point ES:DI at "$PnP", which tells the ROM that we are a PnP BIOS. mov bx, #0xf000 mov es, bx lea di, pnpbios_structure /* jump to BCV function entry pointer */ mov bp, sp ;; Call ROM BCV routine using seg:off on stack db 0xff ;; call_far ss:[bp+0] db 0x5e db 0 cli ;; In case expansion ROM BIOS turns IF on add sp, #2 ;; Pop offset value pop cx ;; Pop seg value (restore CX) jmp no_bev no_bcv: mov ax, 0x1a[bx] ;; 0x1A is also the offset into the expansion header of... cmp ax, #0x0000 ;; the Bootstrap Entry Vector, or zero if there is none. je no_bev ;; Found a device that thinks it can boot the system. Record its BEV and product name string. mov di, 0x10[bx] ;; Pointer to the product name string or zero if none mov bx, #IPL_SEG ;; Go to the segment where the IPL table lives mov ds, bx mov bx, IPL_COUNT_OFFSET ;; Read the number of entries so far cmp bx, #IPL_TABLE_ENTRIES je no_bev ;; Get out if the table is full shl bx, #0x4 ;; Turn count into offset (entries are 16 bytes) mov 0[bx], #IPL_TYPE_BEV ;; This entry is a BEV device mov 6[bx], cx ;; Build a far pointer from the segment... mov 4[bx], ax ;; and the offset cmp di, #0x0000 je no_prod_str mov 0xA[bx], cx ;; Build a far pointer from the segment... mov 8[bx], di ;; and the offset no_prod_str: shr bx, #0x4 ;; Turn the offset back into a count inc bx ;; We have one more entry now mov IPL_COUNT_OFFSET, bx ;; Remember that. no_bev: pop di ;; Restore DI pop ax ;; Restore AX rom_scan_increment: shl ax, #5 ;; convert 512-bytes blocks to 16-byte increments ;; because the segment selector is shifted left 4 bits. add cx, ax pop ax ;; Restore AX cmp cx, ax jbe rom_scan_loop xor ax, ax ;; Restore DS back to 0000: mov ds, ax ret post_init_pic: mov al, #0x11 ; send initialisation commands out PORT_PIC1_CMD, al out PORT_PIC2_CMD, al mov al, #0x08 out PORT_PIC1_DATA, al mov al, #0x70 out PORT_PIC2_DATA, al mov al, #0x04 out PORT_PIC1_DATA, al mov al, #0x02 out PORT_PIC2_DATA, al mov al, #0x01 out PORT_PIC1_DATA, al out PORT_PIC2_DATA, al mov al, #0xb8 out PORT_PIC1_DATA, AL ;master pic: unmask IRQ 0, 1, 2, 6 #if BX_USE_PS2_MOUSE mov al, #0x8f #else mov al, #0x9f #endif out PORT_PIC2_DATA, AL ;slave pic: unmask IRQ 12, 13, 14 ret post_init_ivt: ;; set all interrupts to default handler xor bx, bx ;; offset index mov cx, #0x0100 ;; counter (256 interrupts) mov ax, #dummy_iret_handler mov dx, #0xF000 post_default_ints: mov [bx], ax mov 2[bx], dx add bx, #4 loop post_default_ints ;; Master PIC vector mov bx, #0x0020 mov cl, #0x08 mov ax, #dummy_master_pic_irq_handler post_default_master_pic_ints: mov [bx], ax add bx, #4 loop post_default_master_pic_ints ;; Slave PIC vector add bx, #0x0180 mov cl, #0x08 mov ax, #dummy_slave_pic_irq_handler post_default_slave_pic_ints: mov [bx], ax add bx, #4 loop post_default_slave_pic_ints ;; Printer Services vector SET_INT_VECTOR(0x17, #0xF000, #int17_handler) ;; Bootstrap failure vector SET_INT_VECTOR(0x18, #0xF000, #int18_handler) ;; Bootstrap Loader vector SET_INT_VECTOR(0x19, #0xF000, #int19_handler) ;; Memory Size Check vector SET_INT_VECTOR(0x12, #0xF000, #int12_handler) ;; Equipment Configuration Check vector SET_INT_VECTOR(0x11, #0xF000, #int11_handler) ;; System Services SET_INT_VECTOR(0x15, #0xF000, #int15_handler) ;; set vectors 0x60 - 0x67h to zero (0:180..0:19f) xor ax, ax mov cx, #0x0010 ;; 16 words mov di, #0x0180 cld rep stosw ;; set vector 0x79 to zero ;; this is used by 'guardian angel' protection system SET_INT_VECTOR(0x79, #0, #0) ret ;; the following area can be used to write dynamically generated tables .align 16 bios_table_area_start: dd 0xaafb4442 dd bios_table_area_end - bios_table_area_start - 8; ;-------- ;- POST - ;-------- .org 0xe05b ; POST Entry Point post: xor ax, ax ;; first reset the DMA controllers out PORT_DMA1_MASTER_CLEAR,al out PORT_DMA2_MASTER_CLEAR,al ;; then initialize the DMA controllers mov al, #0xC0 out PORT_DMA2_MODE_REG, al ; cascade mode of channel 4 enabled mov al, #0x00 out PORT_DMA2_MASK_REG, al ; unmask channel 4 ;; Examine CMOS shutdown status. mov AL, #0x0f out PORT_CMOS_INDEX, AL in AL, PORT_CMOS_DATA ;; backup status mov bl, al ;; Reset CMOS shutdown status. mov AL, #0x0f out PORT_CMOS_INDEX, AL ; select CMOS register Fh mov AL, #0x00 out PORT_CMOS_DATA, AL ; set shutdown action to normal ;; Examine CMOS shutdown status. mov al, bl ;; 0x00, 0x0D+ = normal startup cmp AL, #0x00 jz normal_post cmp AL, #0x0d jae normal_post ;; 0x05 = eoi + jmp via [0x40:0x67] jump cmp al, #0x05 je eoi_jmp_post ;; 0x0A = jmp via [0x40:0x67] jump cmp al, #0x0a je jmp_post_0x467 ;; 0x0B = iret via [0x40:0x67] cmp al, #0x0b je iret_post_0x467 ;; 0x0C = retf via [0x40:0x67] cmp al, #0x0c je retf_post_0x467 ;; Examine CMOS shutdown status. ;; 0x01,0x02,0x03,0x04,0x06,0x07,0x08,0x09 = Unimplemented shutdown status. push bx call _shutdown_status_panic #if 0 HALT(__LINE__) ; ;#if 0 ; 0xb0, 0x20, /* mov al, #0x20 */ ; 0xe6, 0x20, /* out PORT_PIC1_CMD, al ;send EOI to PIC */ ;#endif ; pop es pop ds popa iret #endif normal_post: ; case 0: normal startup cli mov ax, #0xfffe mov sp, ax xor ax, ax mov ds, ax mov ss, ax ;; Save shutdown status mov 0x04b0, bl cmp bl, #0xfe jz s3_post ;; zero out BIOS data area (40:00..40:ff) mov es, ax mov cx, #0x0080 ;; 128 words mov di, #0x0400 cld rep stosw call _log_bios_start call post_init_ivt ;; base memory in K 40:13 (word) mov ax, #BASE_MEM_IN_K mov 0x0413, ax ;; Manufacturing Test 40:12 ;; zerod out above ;; Warm Boot Flag 0040:0072 ;; value of 1234h = skip memory checks ;; zerod out above ;; EBDA setup call ebda_post ;; PIT setup SET_INT_VECTOR(0x08, #0xF000, #int08_handler) ;; int 1C already points at dummy_iret_handler (above) mov al, #0x34 ; timer0: binary count, 16bit count, mode 2 out PORT_PIT_MODE, al mov al, #0x00 ; maximum count of 0000H = 18.2Hz out PORT_PIT_COUNTER0, al out PORT_PIT_COUNTER0, al ;; Keyboard SET_INT_VECTOR(0x09, #0xF000, #int09_handler) SET_INT_VECTOR(0x16, #0xF000, #int16_handler) xor ax, ax mov ds, ax mov 0x0417, al /* keyboard shift flags, set 1 */ mov 0x0418, al /* keyboard shift flags, set 2 */ mov 0x0419, al /* keyboard alt-numpad work area */ mov 0x0471, al /* keyboard ctrl-break flag */ mov 0x0497, al /* keyboard status flags 4 */ mov al, #0x10 mov 0x0496, al /* keyboard status flags 3 */ /* keyboard head of buffer pointer */ mov bx, #0x001E mov 0x041A, bx /* keyboard end of buffer pointer */ mov 0x041C, bx /* keyboard pointer to start of buffer */ mov bx, #0x001E mov 0x0480, bx /* keyboard pointer to end of buffer */ mov bx, #0x003E mov 0x0482, bx /* init the keyboard */ call _keyboard_init ;; mov CMOS Equipment Byte to BDA Equipment Word mov ax, 0x0410 mov al, #0x14 out PORT_CMOS_INDEX, al in al, PORT_CMOS_DATA mov 0x0410, ax ;; Parallel setup xor ax, ax mov ds, ax xor bx, bx mov cl, #0x14 ; timeout value mov dx, #0x378 ; Parallel I/O address, port 1 call detect_parport mov dx, #0x278 ; Parallel I/O address, port 2 call detect_parport shl bx, #0x0e mov ax, 0x410 ; Equipment word bits 14..15 determine # parallel ports and ax, #0x3fff or ax, bx ; set number of parallel ports mov 0x410, ax ;; Serial setup SET_INT_VECTOR(0x14, #0xF000, #int14_handler) xor bx, bx mov cl, #0x0a ; timeout value mov dx, #0x03f8 ; Serial I/O address, port 1 call detect_serial mov dx, #0x02f8 ; Serial I/O address, port 2 call detect_serial mov dx, #0x03e8 ; Serial I/O address, port 3 call detect_serial mov dx, #0x02e8 ; Serial I/O address, port 4 call detect_serial shl bx, #0x09 mov ax, 0x410 ; Equipment word bits 9..11 determine # serial ports and ax, #0xf1ff or ax, bx ; set number of serial port mov 0x410, ax ;; CMOS RTC SET_INT_VECTOR(0x1A, #0xF000, #int1a_handler) SET_INT_VECTOR(0x4A, #0xF000, #dummy_iret_handler) SET_INT_VECTOR(0x70, #0xF000, #int70_handler) ;; BIOS DATA AREA 0x4CE ??? call timer_tick_post ;; IRQ9 (IRQ2 redirect) setup SET_INT_VECTOR(0x71, #0xF000, #int71_handler) ;; PS/2 mouse setup SET_INT_VECTOR(0x74, #0xF000, #int74_handler) ;; IRQ13 (FPU exception) setup SET_INT_VECTOR(0x75, #0xF000, #int75_handler) ;; Video setup SET_INT_VECTOR(0x10, #0xF000, #int10_handler) ;; PIC call post_init_pic #if BX_ROMBIOS32 call rombios32_init #else #if BX_PCIBIOS call pcibios_init_iomem_bases call pcibios_init_irqs #endif //BX_PCIBIOS #endif mov cx, #0xc000 ;; init vga bios mov ax, #0xc780 call rom_scan call _print_bios_banner ;; ;; Floppy setup ;; call floppy_drive_post ;; ;; Hard Drive setup ;; call hard_drive_post #if BX_USE_ATADRV ;; ;; ATA/ATAPI driver setup ;; call _ata_init call _ata_detect ;; #endif // BX_USE_ATADRV #if BX_ELTORITO_BOOT ;; ;; eltorito floppy/harddisk emulation from cd ;; call _cdemu_init ;; #endif // BX_ELTORITO_BOOT call _init_boot_vectors mov cx, #0xc800 ;; init option roms mov ax, #0xe000 call rom_scan #if BX_ELTORITO_BOOT call _interactive_bootkey #endif // BX_ELTORITO_BOOT sti ;; enable interrupts int #0x19 .org 0xe2c3 ; NMI Handler Entry Point nmi: ;; FIXME the NMI handler should not panic ;; but iret when called from int75 (fpu exception) call _nmi_handler_msg iret int75_handler: out 0xf0, al // clear irq13 call eoi_both_pics // clear interrupt int 2 // legacy nmi call iret ;------------------------------------------- ;- INT 13h Fixed Disk Services Entry Point - ;------------------------------------------- .org 0xe3fe ; INT 13h Fixed Disk Services Entry Point int13_handler: //JMPL(int13_relocated) jmp int13_relocated .org 0xe401 ; Fixed Disk Parameter Table ;---------- ;- INT19h - ;---------- .org 0xe6f2 ; INT 19h Boot Load Service Entry Point int19_handler: jmp int19_relocated ;------------------------------------------- ;- System BIOS Configuration Data Table ;------------------------------------------- .org BIOS_CONFIG_TABLE db 0x08 ; Table size (bytes) -Lo db 0x00 ; Table size (bytes) -Hi db SYS_MODEL_ID db SYS_SUBMODEL_ID db BIOS_REVISION ; Feature byte 1 ; b7: 1=DMA channel 3 used by hard disk ; b6: 1=2 interrupt controllers present ; b5: 1=RTC present ; b4: 1=BIOS calls int 15h/4Fh every key ; b3: 1=wait for extern event supported (Int 15h/41h) ; b2: 1=extended BIOS data area used ; b1: 0=AT or ESDI bus, 1=MicroChannel ; b0: 1=Dual bus (MicroChannel + ISA) db (0 << 7) | \ (1 << 6) | \ (1 << 5) | \ (BX_CALL_INT15_4F << 4) | \ (0 << 3) | \ (BX_USE_EBDA << 2) | \ (0 << 1) | \ (0 << 0) ; Feature byte 2 ; b7: 1=32-bit DMA supported ; b6: 1=int16h, function 9 supported ; b5: 1=int15h/C6h (get POS data) supported ; b4: 1=int15h/C7h (get mem map info) supported ; b3: 1=int15h/C8h (en/dis CPU) supported ; b2: 1=non-8042 kb controller ; b1: 1=data streaming supported ; b0: reserved db (0 << 7) | \ (1 << 6) | \ (0 << 5) | \ (0 << 4) | \ (0 << 3) | \ (0 << 2) | \ (0 << 1) | \ (0 << 0) ; Feature byte 3 ; b7: not used ; b6: reserved ; b5: reserved ; b4: POST supports ROM-to-RAM enable/disable ; b3: SCSI on system board ; b2: info panel installed ; b1: Initial Machine Load (IML) system - BIOS on disk ; b0: SCSI supported in IML db 0x00 ; Feature byte 4 ; b7: IBM private ; b6: EEPROM present ; b5-3: ABIOS presence (011 = not supported) ; b2: private ; b1: memory split above 16Mb supported ; b0: POSTEXT directly supported by POST db 0x00 ; Feature byte 5 (IBM) ; b1: enhanced mouse ; b0: flash EPROM db 0x00 .org 0xe729 ; Baud Rate Generator Table ;---------- ;- INT14h - ;---------- .org 0xe739 ; INT 14h Serial Communications Service Entry Point int14_handler: push ds pusha xor ax, ax mov ds, ax call _int14_function popa pop ds iret ;---------------------------------------- ;- INT 16h Keyboard Service Entry Point - ;---------------------------------------- .org 0xe82e int16_handler: sti push ds pushf pusha // Set DS to BDA push #0x40 pop ds cmp ah, #0x00 je int16_F00 cmp ah, #0x10 je int16_F00 call _int16_function popa popf pop ds jz int16_zero_set int16_zero_clear: push bp mov bp, sp //SEG SS and BYTE [bp + 0x06], #0xbf pop bp iret int16_zero_set: push bp mov bp, sp //SEG SS or BYTE [bp + 0x06], #0x40 pop bp iret int16_F00: cli mov ax, 0x001a cmp ax, 0x001c jne int16_key_found sti ;; no key yet, call int 15h, function AX=9002 mov ax, #0x9002 int #0x15 int16_wait_for_key: cli mov ax, 0x001a cmp ax, 0x001c jne int16_key_found sti jmp int16_wait_for_key int16_key_found: call _int16_function popa popf pop ds iret ;------------------------------------------------- ;- INT09h : Keyboard Hardware Service Entry Point - ;------------------------------------------------- .org 0xe987 int09_handler: cli push ax mov al, #0xAD ;;disable keyboard out PORT_PS2_STATUS, al mov al, #0x0B out PORT_PIC1_CMD, al in al, PORT_PIC1_CMD and al, #0x02 jz int09_finish in al, PORT_PS2_DATA ;;read key from keyboard controller sti push ds pusha #ifdef BX_CALL_INT15_4F mov ah, #0x4f ;; allow for keyboard intercept stc int #0x15 jnc int09_done #endif ;; check for extended key push #0x40 pop ds cmp al, #0xe0 jne int09_check_pause mov al, BYTE [0x96] ;; mf2_state |= 0x02 or al, #0x02 mov BYTE [0x96], al jmp int09_done int09_check_pause: ;; check for pause key cmp al, #0xe1 jne int09_process_key mov al, BYTE [0x96] ;; mf2_state |= 0x01 or al, #0x01 mov BYTE [0x96], al jmp int09_done int09_process_key: call _int09_function int09_done: popa pop ds cli call eoi_master_pic ;; Notify keyboard interrupt complete w/ int 15h, function AX=9102 mov ax, #0x9102 int #0x15 int09_finish: mov al, #0xAE ;;enable keyboard out PORT_PS2_STATUS, al pop ax iret ; IRQ9 handler(Redirect to IRQ2) ;-------------------- int71_handler: push ax mov al, #0x20 out PORT_PIC2_CMD, al pop ax int #0x0A iret ;-------------------- dummy_master_pic_irq_handler: push ax call eoi_master_pic pop ax iret ;-------------------- dummy_slave_pic_irq_handler: push ax call eoi_both_pics pop ax iret ;---------------------------------------- ;- INT 13h Diskette Service Entry Point - ;---------------------------------------- .org 0xec59 int13_diskette: jmp int13_noeltorito ;--------------------------------------------- ;- INT 0Eh Diskette Hardware ISR Entry Point - ;--------------------------------------------- .org 0xef57 ; INT 0Eh Diskette Hardware ISR Entry Point int0e_handler: push ax push dx mov dx, #0x03f4 in al, dx and al, #0xc0 cmp al, #0xc0 je int0e_normal mov dx, #0x03f5 mov al, #0x08 ; sense interrupt status out dx, al int0e_loop1: mov dx, #0x03f4 in al, dx and al, #0xc0 cmp al, #0xc0 jne int0e_loop1 int0e_loop2: mov dx, #0x03f5 in al, dx mov dx, #0x03f4 in al, dx and al, #0xc0 cmp al, #0xc0 je int0e_loop2 int0e_normal: push ds xor ax, ax ;; segment 0000 mov ds, ax call eoi_master_pic mov al, 0x043e or al, #0x80 ;; diskette interrupt has occurred mov 0x043e, al pop ds ;; Notify diskette interrupt complete w/ int 15h, function AX=9101 mov ax, #0x9101 int #0x15 pop dx pop ax iret .org 0xefc7 ; Diskette Controller Parameter Table diskette_param_table: ;; Since no provisions are made for multiple drive types, most ;; values in this table are ignored. I set parameters for 1.44M ;; floppy here db 0xAF db 0x02 ;; head load time 0000001, DMA used db 0x25 db 0x02 db 18 db 0x1B db 0xFF db 0x6C db 0xF6 db 0x0F db 0x08 ;---------------------------------------- ;- INT17h : Printer Service Entry Point - ;---------------------------------------- .org 0xefd2 int17_handler: push ds pusha xor ax, ax mov ds, ax call _int17_function popa pop ds iret diskette_param_table2: ;; New diskette parameter table adding 3 parameters from IBM ;; Since no provisions are made for multiple drive types, most ;; values in this table are ignored. I set parameters for 1.44M ;; floppy here db 0xAF db 0x02 ;; head load time 0000001, DMA used db 0x25 db 0x02 db 18 db 0x1B db 0xFF db 0x6C db 0xF6 db 0x0F db 0x08 db 79 ;; maximum track db 0 ;; data transfer rate db 4 ;; drive type in cmos .org 0xf045 ; INT 10 Functions 0-Fh Entry Point HALT(__LINE__) iret ;---------- ;- INT10h - ;---------- .org 0xf065 ; INT 10h Video Support Service Entry Point int10_handler: ;; dont do anything, since the VGA BIOS handles int10h requests iret .org 0xf0a4 ; MDA/CGA Video Parameter Table (INT 1Dh) ;---------- ;- INT12h - ;---------- .org 0xf841 ; INT 12h Memory Size Service Entry Point ; ??? different for Pentium (machine check)? int12_handler: push ds mov ax, #0x0040 mov ds, ax mov ax, 0x0013 pop ds iret ;---------- ;- INT11h - ;---------- .org 0xf84d ; INT 11h Equipment List Service Entry Point int11_handler: push ds mov ax, #0x0040 mov ds, ax mov ax, 0x0010 pop ds iret ;---------- ;- INT15h - ;---------- .org 0xf859 ; INT 15h System Services Entry Point int15_handler: pushf #if BX_APM cmp ah, #0x53 je apm_call #endif push ds push es cmp ah, #0x86 je int15_handler32 cmp ah, #0xE8 je int15_handler32 pusha #if BX_USE_PS2_MOUSE cmp ah, #0xC2 je int15_handler_mouse #endif call _int15_function int15_handler_mouse_ret: popa int15_handler32_ret: pop es pop ds popf jmp iret_modify_cf #if BX_APM apm_call: jmp _apmreal_entry #endif #if BX_USE_PS2_MOUSE int15_handler_mouse: call _int15_function_mouse jmp int15_handler_mouse_ret #endif int15_handler32: pushad call _int15_function32 popad jmp int15_handler32_ret ;; Protected mode IDT descriptor ;; ;; I just make the limit 0, so the machine will shutdown ;; if an exception occurs during protected mode memory ;; transfers. ;; ;; Set base to f0000 to correspond to beginning of BIOS, ;; in case I actually define an IDT later ;; Set limit to 0 pmode_IDT_info: dw 0x0000 ;; limit 15:00 dw 0x0000 ;; base 15:00 db 0x0f ;; base 23:16 db 0x00 ;; base 31:24 ;; Real mode IDT descriptor ;; ;; Set to typical real-mode values. ;; base = 000000 ;; limit = 03ff rmode_IDT_info: dw 0x03ff ;; limit 15:00 dw 0x0000 ;; base 15:00 db 0x00 ;; base 23:16 db 0x00 ;; base 31:24 ;---------- ;- INT1Ah - ;---------- .org 0xfe6e ; INT 1Ah Time-of-day Service Entry Point int1a_handler: #if BX_PCIBIOS cmp ah, #0xb1 jne int1a_normal call pcibios_real jc pcibios_error retf 2 pcibios_error: mov bl, ah mov ah, #0xb1 push ds pusha mov ax, ss ; set readable descriptor to ds, for calling pcibios mov ds, ax ; on 16bit protected mode. jmp int1a_callfunction int1a_normal: #endif push ds pusha xor ax, ax mov ds, ax int1a_callfunction: call _int1a_function popa pop ds iret ;; ;; int70h: IRQ8 - CMOS RTC ;; int70_handler: push ds pushad xor ax, ax mov ds, ax call _int70_function popad pop ds iret ;--------- ;- INT08 - ;--------- .org 0xfea5 ; INT 08h System Timer ISR Entry Point int08_handler: sti push eax push ds xor ax, ax mov ds, ax ;; time to turn off drive(s)? mov al,0x0440 or al,al jz int08_floppy_off dec al mov 0x0440,al jnz int08_floppy_off ;; turn motor(s) off push dx mov dx,#0x03f2 in al,dx and al,#0xcf out dx,al pop dx int08_floppy_off: mov eax, 0x046c ;; get ticks dword inc eax ;; compare eax to one days worth of timer ticks at 18.2 hz cmp eax, #0x001800B0 jb int08_store_ticks ;; there has been a midnight rollover at this point xor eax, eax ;; zero out counter inc BYTE 0x0470 ;; increment rollover flag int08_store_ticks: mov 0x046c, eax ;; store new ticks dword ;; chain to user timer tick INT #0x1c //pushf //;; call_ep [ds:loc] //CALL_EP( 0x1c << 2 ) int #0x1c cli call eoi_master_pic pop ds pop eax iret .org 0xfef3 ; Initial Interrupt Vector Offsets Loaded by POST .org 0xff00 .ascii BIOS_COPYRIGHT_STRING ;------------------------------------------------ ;- IRET Instruction for Dummy Interrupt Handler - ;------------------------------------------------ .org 0xff53 ; IRET Instruction for Dummy Interrupt Handler dummy_iret_handler: iret .org 0xff54 ; INT 05h Print Screen Service Entry Point HALT(__LINE__) iret .org 0xfff0 ; Power-up Entry Point jmp 0xf000:post .org 0xfff5 ; ASCII Date ROM was built - 8 characters in MM/DD/YY .ascii BIOS_BUILD_DATE .org 0xfffe ; System Model ID db SYS_MODEL_ID db 0x00 ; filler .org 0xfa6e ;; Character Font for 320x200 & 640x200 Graphics (lower 128 characters) ASM_END /* * This font comes from the fntcol16.zip package (c) by Joseph Gil * found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip * This font is public domain */ static Bit8u vgafont8[128*8]= { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c, 0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0, 0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99, 0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00, 0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00, 0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00, 0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00, 0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00, 0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00, 0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00, 0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00, 0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00, 0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60, 0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, 0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00, 0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00, 0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00, 0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00, 0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00, 0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00, 0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00, 0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00, 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00, 0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00, 0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00, 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00, 0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, }; ASM_START .org 0xcc00 bios_table_area_end: // bcc-generated data will be placed here ASM_END bochs-2.6/bios/acpi-dsdt.dsl0000644000175000017500000004535012020641455015653 0ustar guillemguillem/* * Bochs/QEMU ACPI DSDT ASL definition * * Copyright (c) 2006 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ DefinitionBlock ( "acpi-dsdt.aml", // Output Filename "DSDT", // Signature 0x01, // DSDT Compliance Revision "BXPC", // OEMID "BXDSDT", // TABLE ID 0x1 // OEM Revision ) { Scope (\) { /* Debug Output */ OperationRegion (DBG, SystemIO, 0xb044, 0x04) Field (DBG, DWordAcc, NoLock, Preserve) { DBGL, 32, } } /* PCI Bus definition */ Scope(\_SB) { Device(PCI0) { Name (_HID, EisaId ("PNP0A03")) Name (_ADR, 0x00) Name (_UID, 1) Name(_PRT, Package() { /* PCI IRQ routing table, example from ACPI 2.0a specification, section 6.2.8.1 */ /* Note: we provide the same info as the PCI routing table of the Bochs BIOS */ // PCI Slot 0 Package() {0x0000ffff, 0, LNKD, 0}, Package() {0x0000ffff, 1, LNKA, 0}, Package() {0x0000ffff, 2, LNKB, 0}, Package() {0x0000ffff, 3, LNKC, 0}, // PCI Slot 1 Package() {0x0001ffff, 0, LNKA, 0}, Package() {0x0001ffff, 1, LNKB, 0}, Package() {0x0001ffff, 2, LNKC, 0}, Package() {0x0001ffff, 3, LNKD, 0}, // PCI Slot 2 Package() {0x0002ffff, 0, LNKB, 0}, Package() {0x0002ffff, 1, LNKC, 0}, Package() {0x0002ffff, 2, LNKD, 0}, Package() {0x0002ffff, 3, LNKA, 0}, // PCI Slot 3 Package() {0x0003ffff, 0, LNKC, 0}, Package() {0x0003ffff, 1, LNKD, 0}, Package() {0x0003ffff, 2, LNKA, 0}, Package() {0x0003ffff, 3, LNKB, 0}, // PCI Slot 4 Package() {0x0004ffff, 0, LNKD, 0}, Package() {0x0004ffff, 1, LNKA, 0}, Package() {0x0004ffff, 2, LNKB, 0}, Package() {0x0004ffff, 3, LNKC, 0}, // PCI Slot 5 Package() {0x0005ffff, 0, LNKA, 0}, Package() {0x0005ffff, 1, LNKB, 0}, Package() {0x0005ffff, 2, LNKC, 0}, Package() {0x0005ffff, 3, LNKD, 0}, }) Name (_CRS, ResourceTemplate () { WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode, 0x0000, // Address Space Granularity 0x0000, // Address Range Minimum 0x00FF, // Address Range Maximum 0x0000, // Address Translation Offset 0x0100, // Address Length ,, ) IO (Decode16, 0x0CF8, // Address Range Minimum 0x0CF8, // Address Range Maximum 0x01, // Address Alignment 0x08, // Address Length ) WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, 0x0000, // Address Space Granularity 0x0000, // Address Range Minimum 0x0CF7, // Address Range Maximum 0x0000, // Address Translation Offset 0x0CF8, // Address Length ,, , TypeStatic) WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange, 0x0000, // Address Space Granularity 0x0D00, // Address Range Minimum 0xFFFF, // Address Range Maximum 0x0000, // Address Translation Offset 0xF300, // Address Length ,, , TypeStatic) DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite, 0x00000000, // Address Space Granularity 0x000A0000, // Address Range Minimum 0x000BFFFF, // Address Range Maximum 0x00000000, // Address Translation Offset 0x00020000, // Address Length ,, , AddressRangeMemory, TypeStatic) DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, 0x00000000, // Address Space Granularity 0xC0000000, // Address Range Minimum 0xFEBFFFFF, // Address Range Maximum 0x00000000, // Address Translation Offset 0x3EC00000, // Address Length ,, , AddressRangeMemory, TypeStatic) }) } #ifdef BX_QEMU Device(HPET) { Name(_HID, EISAID("PNP0103")) Name(_UID, 0) Method (_STA, 0, NotSerialized) { Return(0x0F) } Name(_CRS, ResourceTemplate() { DWordMemory( ResourceConsumer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite, 0x00000000, 0xFED00000, 0xFED003FF, 0x00000000, 0x00000400 /* 1K memory: FED00000 - FED003FF */ ) }) } #endif } Scope(\_SB.PCI0) { Device (VGA) { Name (_ADR, 0x00020000) Method (_S1D, 0, NotSerialized) { Return (0x00) } Method (_S2D, 0, NotSerialized) { Return (0x00) } Method (_S3D, 0, NotSerialized) { Return (0x00) } } /* PIIX3 ISA bridge */ Device (ISA) { Name (_ADR, 0x00010000) /* PIIX PCI to ISA irq remapping */ OperationRegion (P40C, PCI_Config, 0x60, 0x04) /* Real-time clock */ Device (RTC) { Name (_HID, EisaId ("PNP0B00")) Name (_CRS, ResourceTemplate () { IO (Decode16, 0x0070, 0x0070, 0x10, 0x02) IRQNoFlags () {8} IO (Decode16, 0x0072, 0x0072, 0x02, 0x06) }) } /* Keyboard seems to be important for WinXP install */ Device (KBD) { Name (_HID, EisaId ("PNP0303")) Method (_STA, 0, NotSerialized) { Return (0x0f) } Method (_CRS, 0, NotSerialized) { Name (TMP, ResourceTemplate () { IO (Decode16, 0x0060, // Address Range Minimum 0x0060, // Address Range Maximum 0x01, // Address Alignment 0x01, // Address Length ) IO (Decode16, 0x0064, // Address Range Minimum 0x0064, // Address Range Maximum 0x01, // Address Alignment 0x01, // Address Length ) IRQNoFlags () {1} }) Return (TMP) } } /* PS/2 mouse */ Device (MOU) { Name (_HID, EisaId ("PNP0F13")) Method (_STA, 0, NotSerialized) { Return (0x0f) } Method (_CRS, 0, NotSerialized) { Name (TMP, ResourceTemplate () { IRQNoFlags () {12} }) Return (TMP) } } /* PS/2 floppy controller */ Device (FDC0) { Name (_HID, EisaId ("PNP0700")) Method (_STA, 0, NotSerialized) { Return (0x0F) } Method (_CRS, 0, NotSerialized) { Name (BUF0, ResourceTemplate () { IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04) IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01) IRQNoFlags () {6} DMA (Compatibility, NotBusMaster, Transfer8) {2} }) Return (BUF0) } } /* Parallel port */ Device (LPT) { Name (_HID, EisaId ("PNP0400")) Method (_STA, 0, NotSerialized) { Store (\_SB.PCI0.PX13.DRSA, Local0) And (Local0, 0x80000000, Local0) If (LEqual (Local0, 0)) { Return (0x00) } Else { Return (0x0F) } } Method (_CRS, 0, NotSerialized) { Name (BUF0, ResourceTemplate () { IO (Decode16, 0x0378, 0x0378, 0x08, 0x08) IRQNoFlags () {7} }) Return (BUF0) } } /* Serial Ports */ Device (COM1) { Name (_HID, EisaId ("PNP0501")) Name (_UID, 0x01) Method (_STA, 0, NotSerialized) { Store (\_SB.PCI0.PX13.DRSC, Local0) And (Local0, 0x08000000, Local0) If (LEqual (Local0, 0)) { Return (0x00) } Else { Return (0x0F) } } Method (_CRS, 0, NotSerialized) { Name (BUF0, ResourceTemplate () { IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08) IRQNoFlags () {4} }) Return (BUF0) } } Device (COM2) { Name (_HID, EisaId ("PNP0501")) Name (_UID, 0x02) Method (_STA, 0, NotSerialized) { Store (\_SB.PCI0.PX13.DRSC, Local0) And (Local0, 0x80000000, Local0) If (LEqual (Local0, 0)) { Return (0x00) } Else { Return (0x0F) } } Method (_CRS, 0, NotSerialized) { Name (BUF0, ResourceTemplate () { IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08) IRQNoFlags () {3} }) Return (BUF0) } } } /* PIIX4 PM */ Device (PX13) { Name (_ADR, 0x00010003) OperationRegion (P13C, PCI_Config, 0x5c, 0x24) Field (P13C, DWordAcc, NoLock, Preserve) { DRSA, 32, DRSB, 32, DRSC, 32, DRSE, 32, DRSF, 32, DRSG, 32, DRSH, 32, DRSI, 32, DRSJ, 32 } } } /* PCI IRQs */ Scope(\_SB) { Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve) { PRQ0, 8, PRQ1, 8, PRQ2, 8, PRQ3, 8 } Device(LNKA){ Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link Name(_UID, 1) Name(_PRS, ResourceTemplate(){ IRQ (Level, ActiveLow, Shared) {3,4,5,6,7,9,10,11,12} }) Method (_STA, 0, NotSerialized) { Store (0x0B, Local0) If (And (0x80, PRQ0, Local1)) { Store (0x09, Local0) } Return (Local0) } Method (_DIS, 0, NotSerialized) { Or (PRQ0, 0x80, PRQ0) } Method (_CRS, 0, NotSerialized) { Name (PRR0, ResourceTemplate () { IRQ (Level, ActiveLow, Shared) {1} }) CreateWordField (PRR0, 0x01, TMP) Store (PRQ0, Local0) If (LLess (Local0, 0x80)) { ShiftLeft (One, Local0, TMP) } Else { Store (Zero, TMP) } Return (PRR0) } Method (_SRS, 1, NotSerialized) { CreateWordField (Arg0, 0x01, TMP) FindSetRightBit (TMP, Local0) Decrement (Local0) Store (Local0, PRQ0) } } Device(LNKB){ Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link Name(_UID, 2) Name(_PRS, ResourceTemplate(){ IRQ (Level, ActiveLow, Shared) {3,4,5,6,7,9,10,11,12} }) Method (_STA, 0, NotSerialized) { Store (0x0B, Local0) If (And (0x80, PRQ1, Local1)) { Store (0x09, Local0) } Return (Local0) } Method (_DIS, 0, NotSerialized) { Or (PRQ1, 0x80, PRQ1) } Method (_CRS, 0, NotSerialized) { Name (PRR0, ResourceTemplate () { IRQ (Level, ActiveLow, Shared) {1} }) CreateWordField (PRR0, 0x01, TMP) Store (PRQ1, Local0) If (LLess (Local0, 0x80)) { ShiftLeft (One, Local0, TMP) } Else { Store (Zero, TMP) } Return (PRR0) } Method (_SRS, 1, NotSerialized) { CreateWordField (Arg0, 0x01, TMP) FindSetRightBit (TMP, Local0) Decrement (Local0) Store (Local0, PRQ1) } } Device(LNKC){ Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link Name(_UID, 3) Name(_PRS, ResourceTemplate(){ IRQ (Level, ActiveLow, Shared) {3,4,5,6,7,9,10,11,12} }) Method (_STA, 0, NotSerialized) { Store (0x0B, Local0) If (And (0x80, PRQ2, Local1)) { Store (0x09, Local0) } Return (Local0) } Method (_DIS, 0, NotSerialized) { Or (PRQ2, 0x80, PRQ2) } Method (_CRS, 0, NotSerialized) { Name (PRR0, ResourceTemplate () { IRQ (Level, ActiveLow, Shared) {1} }) CreateWordField (PRR0, 0x01, TMP) Store (PRQ2, Local0) If (LLess (Local0, 0x80)) { ShiftLeft (One, Local0, TMP) } Else { Store (Zero, TMP) } Return (PRR0) } Method (_SRS, 1, NotSerialized) { CreateWordField (Arg0, 0x01, TMP) FindSetRightBit (TMP, Local0) Decrement (Local0) Store (Local0, PRQ2) } } Device(LNKD){ Name(_HID, EISAID("PNP0C0F")) // PCI interrupt link Name(_UID, 4) Name(_PRS, ResourceTemplate(){ IRQ (Level, ActiveLow, Shared) {3,4,5,6,7,9,10,11,12} }) Method (_STA, 0, NotSerialized) { Store (0x0B, Local0) If (And (0x80, PRQ3, Local1)) { Store (0x09, Local0) } Return (Local0) } Method (_DIS, 0, NotSerialized) { Or (PRQ3, 0x80, PRQ3) } Method (_CRS, 0, NotSerialized) { Name (PRR0, ResourceTemplate () { IRQ (Level, ActiveLow, Shared) {1} }) CreateWordField (PRR0, 0x01, TMP) Store (PRQ3, Local0) If (LLess (Local0, 0x80)) { ShiftLeft (One, Local0, TMP) } Else { Store (Zero, TMP) } Return (PRR0) } Method (_SRS, 1, NotSerialized) { CreateWordField (Arg0, 0x01, TMP) FindSetRightBit (TMP, Local0) Decrement (Local0) Store (Local0, PRQ3) } } } /* * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes: * must match piix4 emulation. */ Name (\_S3, Package (0x04) { 0x01, /* PM1a_CNT.SLP_TYP */ 0x01, /* PM1b_CNT.SLP_TYP */ Zero, /* reserved */ Zero /* reserved */ }) Name (\_S4, Package (0x04) { Zero, /* PM1a_CNT.SLP_TYP */ Zero, /* PM1b_CNT.SLP_TYP */ Zero, /* reserved */ Zero /* reserved */ }) Name (\_S5, Package (0x04) { Zero, /* PM1a_CNT.SLP_TYP */ Zero, /* PM1b_CNT.SLP_TYP */ Zero, /* reserved */ Zero /* reserved */ }) } bochs-2.6/bios/bios_usage0000644000175000017500000000023512020641455015333 0ustar guillemguillem#!/bin/csh -f gcc -E rombios.c | grep "^\.org" | sed -e 's/\.org //' | sed -e 's/ .*//' | sort >! temp.usage usage rombios.bin temp.usage /bin/rm temp.usage bochs-2.6/bios/rombios.h0000644000175000017500000002071412020641455015117 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: rombios.h 10842 2011-12-20 19:34:05Z vruppert $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2006 Volker Ruppert // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA /* define it to include QEMU specific code */ //#define BX_QEMU #ifndef LEGACY # define BX_ROMBIOS32 1 #else # define BX_ROMBIOS32 0 #endif #define DEBUG_ROMBIOS 0 #define DEBUG_ATA 0 #define DEBUG_INT13_HD 0 #define DEBUG_INT13_CD 0 #define DEBUG_INT13_ET 0 #define DEBUG_INT13_FL 0 #define DEBUG_INT15 0 #define DEBUG_INT16 0 #define DEBUG_INT1A 0 #define DEBUG_INT74 0 #define DEBUG_APM 0 #define PANIC_PORT 0x400 #define PANIC_PORT2 0x401 #define INFO_PORT 0x402 #define DEBUG_PORT 0x403 #define BIOS_PRINTF_HALT 1 #define BIOS_PRINTF_SCREEN 2 #define BIOS_PRINTF_INFO 4 #define BIOS_PRINTF_DEBUG 8 #define BIOS_PRINTF_ALL (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO) #define BIOS_PRINTF_DEBHALT (BIOS_PRINTF_SCREEN | BIOS_PRINTF_INFO | BIOS_PRINTF_HALT) #define printf(format, p...) bios_printf(BIOS_PRINTF_SCREEN, format, ##p) // Defines the output macros. // BX_DEBUG goes to INFO port until we can easily choose debug info on a // per-device basis. Debug info are sent only in debug mode #if DEBUG_ROMBIOS # define BX_DEBUG(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p) #else # define BX_DEBUG(format, p...) #endif #define BX_INFO(format, p...) bios_printf(BIOS_PRINTF_INFO, format, ##p) #define BX_PANIC(format, p...) bios_printf(BIOS_PRINTF_DEBHALT, format, ##p) /* put the MP float table and ACPI RSDP in EBDA and the MP and ACPI tables in high memory. Linux kernels < 2.6.30 might not work with this configuration */ //#define BX_USE_EBDA_TABLES #define ACPI_DATA_SIZE 0x00010000L #define MPTABLE_MAX_SIZE 0x00002000 #define PM_IO_BASE 0xb000 #define SMB_IO_BASE 0xb100 #define SMP_MSR_ADDR 0x0510 // Define the application NAME #if defined(BX_QEMU) # define BX_APPNAME "QEMU" # define BX_APPVENDOR "QEMU" #else # define BX_APPNAME "Bochs" # define BX_APPVENDOR "The Bochs Project" #endif #define E820_RAM 1 #define E820_RESERVED 2 #define E820_ACPI 3 #define E820_NVS 4 #define E820_UNUSABLE 5 #define BX_CPU 3 #define BX_USE_PS2_MOUSE 1 #define BX_CALL_INT15_4F 1 #define BX_USE_EBDA 1 #define BX_SUPPORT_FLOPPY 1 #define BX_FLOPPY_ON_CNT 37 /* 2 seconds */ #define BX_PCIBIOS 1 #define BX_APM 1 #define BX_PNPBIOS 1 /* define it if the (emulated) hardware supports SMM mode */ #define BX_USE_SMM #define BX_USE_ATADRV 1 #define BX_ELTORITO_BOOT 1 #define BX_MAX_ATA_INTERFACES 4 #define BX_MAX_ATA_DEVICES (BX_MAX_ATA_INTERFACES*2) #define BX_VIRTUAL_PORTS 1 /* normal output to Bochs ports */ #define BX_DEBUG_SERIAL 0 /* output to COM1 */ /* model byte 0xFC = AT */ #define SYS_MODEL_ID 0xFC #define SYS_SUBMODEL_ID 0x00 #define BIOS_REVISION 1 #define BIOS_CONFIG_TABLE 0xe6f5 #ifndef BIOS_BUILD_DATE # define BIOS_BUILD_DATE "06/23/99" #endif // 1K of base memory used for Extended Bios Data Area (EBDA) // EBDA is used for PS/2 mouse support, and IDE BIOS, etc. #define EBDA_SEG 0x9FC0 #define EBDA_SIZE 1 // In KiB #define BASE_MEM_IN_K (640 - EBDA_SIZE) /* IPL_SIZE bytes at 0x9ff00 are used for the IPL boot table. */ #define IPL_SEG 0x9ff0 #define IPL_TABLE_OFFSET 0x0000 #define IPL_TABLE_ENTRIES 8 #define IPL_COUNT_OFFSET 0x0080 /* u16: number of valid table entries */ #define IPL_SEQUENCE_OFFSET 0x0082 /* u16: next boot device */ #define IPL_BOOTFIRST_OFFSET 0x0084 /* u16: user selected device */ #define IPL_SIZE 0x86 #define IPL_TYPE_FLOPPY 0x01 #define IPL_TYPE_HARDDISK 0x02 #define IPL_TYPE_CDROM 0x03 #define IPL_TYPE_BEV 0x80 /* Ports */ #define PORT_DMA_ADDR_2 0x0004 #define PORT_DMA_CNT_2 0x0005 #define PORT_DMA1_MASK_REG 0x000a #define PORT_DMA1_MODE_REG 0x000b #define PORT_DMA1_CLEAR_FF_REG 0x000c #define PORT_DMA1_MASTER_CLEAR 0x000d #define PORT_PIC1_CMD 0x0020 #define PORT_PIC1_DATA 0x0021 #define PORT_PIT_COUNTER0 0x0040 #define PORT_PIT_MODE 0x0043 #define PORT_PS2_DATA 0x0060 #define PORT_PS2_CTRLB 0x0061 #define PORT_PS2_STATUS 0x0064 #define PORT_CMOS_INDEX 0x0070 #define PORT_CMOS_DATA 0x0071 #define PORT_DIAG 0x0080 #define PORT_DMA_PAGE_2 0x0081 #define PORT_A20 0x0092 #define PORT_PIC2_CMD 0x00a0 #define PORT_PIC2_DATA 0x00a1 #define PORT_DMA2_MASK_REG 0x00d4 #define PORT_DMA2_MODE_REG 0x00d6 #define PORT_DMA2_MASTER_CLEAR 0x00da #define PORT_ATA2_CMD_BASE 0x0170 #define PORT_ATA1_CMD_BASE 0x01f0 #define PORT_FD_DOR 0x03f2 #define PORT_FD_STATUS 0x03f4 #define PORT_FD_DATA 0x03f5 #define CPUID_MSR (1 << 5) #define CPUID_APIC (1 << 9) #define CPUID_MTRR (1 << 12) #define APIC_BASE ((uint8_t *)0xfee00000) #define APIC_ICR_LOW 0x300 #define APIC_SVR 0x0F0 #define APIC_ID 0x020 #define APIC_LVT3 0x370 #define APIC_ENABLED 0x0100 #define AP_BOOT_ADDR 0x9f000 #define SMI_CMD_IO_ADDR 0xb2 #define BIOS_TMP_STORAGE 0x00030000 /* 64 KB used to copy the BIOS to shadow RAM */ #define MSR_MTRRcap 0x000000fe #define MSR_MTRRfix64K_00000 0x00000250 #define MSR_MTRRfix16K_80000 0x00000258 #define MSR_MTRRfix16K_A0000 0x00000259 #define MSR_MTRRfix4K_C0000 0x00000268 #define MSR_MTRRfix4K_C8000 0x00000269 #define MSR_MTRRfix4K_D0000 0x0000026a #define MSR_MTRRfix4K_D8000 0x0000026b #define MSR_MTRRfix4K_E0000 0x0000026c #define MSR_MTRRfix4K_E8000 0x0000026d #define MSR_MTRRfix4K_F0000 0x0000026e #define MSR_MTRRfix4K_F8000 0x0000026f #define MSR_MTRRdefType 0x000002ff #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) #define MTRR_MEMTYPE_UC 0 #define MTRR_MEMTYPE_WC 1 #define MTRR_MEMTYPE_WT 4 #define MTRR_MEMTYPE_WP 5 #define MTRR_MEMTYPE_WB 6 #define QEMU_CFG_CTL_PORT 0x510 #define QEMU_CFG_DATA_PORT 0x511 #define QEMU_CFG_SIGNATURE 0x00 #define QEMU_CFG_ID 0x01 #define QEMU_CFG_UUID 0x02 #define PCI_ADDRESS_SPACE_MEM 0x00 #define PCI_ADDRESS_SPACE_IO 0x01 #define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08 #define PCI_ROM_SLOT 6 #define PCI_NUM_REGIONS 7 #define PCI_DEVICES_MAX 64 #define PCI_CLASS_STORAGE_IDE 0x0101 #define PCI_CLASS_DISPLAY_VGA 0x0300 #define PCI_CLASS_SYSTEM_PIC 0x0800 #define PCI_VENDOR_ID 0x00 /* 16 bits */ #define PCI_DEVICE_ID 0x02 /* 16 bits */ #define PCI_COMMAND 0x04 /* 16 bits */ #define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ #define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ #define PCI_CLASS_DEVICE 0x0a /* Device class */ #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ #define PCI_MIN_GNT 0x3e /* 8 bits */ #define PCI_MAX_LAT 0x3f /* 8 bits */ #define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ #define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ #define PCI_ROM_ADDRESS_ENABLE 0x01 #define PCI_VENDOR_ID_INTEL 0x8086 #define PCI_DEVICE_ID_INTEL_82441 0x1237 #define PCI_DEVICE_ID_INTEL_82371SB_0 0x7000 #define PCI_DEVICE_ID_INTEL_82371SB_1 0x7010 #define PCI_DEVICE_ID_INTEL_82371AB_0 0x7110 #define PCI_DEVICE_ID_INTEL_82371AB 0x7111 #define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113 #define PCI_VENDOR_ID_IBM 0x1014 #define PCI_VENDOR_ID_APPLE 0x106b bochs-2.6/bios/apmbios.S0000644000175000017500000001462212020641455015053 0ustar guillemguillem// APM BIOS support for the Bochs BIOS // Copyright (C) 2004 Fabrice Bellard // // Debugging extensions, 16-bit interface and extended power options // Copyright (C) 2005 Struan Bartlett // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #if defined(APM_REAL) #define APMSYM(s) apmreal_ ## s #elif defined(APM_PROT16) #define APMSYM(s) apm16_ ## s #elif defined(APM_PROT32) #define APMSYM(s) apm32_ ## s #else #error unsupported APM mode #endif APMSYM(out_str): push eax push ebx mov ebx, eax APMSYM(out_str1): SEG CS mov al, byte ptr [bx] cmp al, #0 je APMSYM(out_str2) outb dx, al inc ebx jmp APMSYM(out_str1) APMSYM(out_str2): pop ebx pop eax ret APMSYM(07_poweroff_str): .ascii "Shutdown" db 0 APMSYM(07_suspend_str): .ascii "Suspend" db 0 APMSYM(07_standby_str): .ascii "Standby" db 0 #if DEBUG_APM APMSYM(put_str): push edx mov dx, #INFO_PORT call APMSYM(out_str) pop edx ret ; print the hex number in eax APMSYM(put_num): push eax push ebx push ecx push edx mov ecx, eax mov bx, #8 mov dx, #INFO_PORT APMSYM(put_num1): mov eax, ecx shr eax, #28 add al, #0x30 cmp al, #0x39 jbe APMSYM(put_num2) add al, #0x27 APMSYM(put_num2): outb dx, al shl ecx, #4 dec bx jne APMSYM(put_num1) pop edx pop ecx pop ebx pop eax ret APMSYM(put_reg): outb dx, al shr eax, #8 outb dx, al shr eax, #8 outb dx, al shr eax, #8 outb dx, al mov eax,ebx call APMSYM(put_num) mov al, #0x3b outb dx,al mov al, #0x20 outb dx,al ret APMSYM(put_regs): push eax push edx push ebx mov dx, #INFO_PORT mov ebx, eax mov eax, #0x3d584145 // 'EAX=' call APMSYM(put_reg) pop ebx push ebx mov eax, #0x3d584245 // 'EBX=' call APMSYM(put_reg) mov ebx, ecx mov eax, #0x3d584345 // 'ECX=' call APMSYM(put_reg) mov ebx, edx mov eax, #0x3d584445 // 'EDX=' call APMSYM(put_reg) mov ebx, esi mov eax, #0x3d495345 // 'ESI=' call APMSYM(put_reg) mov ebx, edi mov eax, #0x3d494445 // 'EDI=' call APMSYM(put_reg) mov al, #0x0a outb dx, al pop ebx pop edx pop eax ret #endif #if defined(APM_PROT32) _apm32_entry: #endif #if defined(APM_PROT16) _apm16_entry: #endif pushf #if defined(APM_REAL) _apmreal_entry: #endif #if DEBUG_APM call APMSYM(put_regs) #endif #if defined(APM_REAL) ;----------------- ; APM installation check APMSYM(00): cmp al, #0x00 jne APMSYM(01) mov ah, #1 // APM major version mov al, #2 // APM minor version mov bh, #0x50 // 'P' mov bl, #0x4d // 'M' // bit 0 : 16 bit interface supported // bit 1 : 32 bit interface supported mov cx, #0x3 jmp APMSYM(ok) ;----------------- ; APM real mode interface connect APMSYM(01): cmp al, #0x01 jne APMSYM(02) jmp APMSYM(ok) ;----------------- ; APM 16 bit protected mode interface connect APMSYM(02): cmp al, #0x02 jne APMSYM(03) mov bx, #_apm16_entry mov ax, #0xf000 // 16 bit code segment base mov si, #0xfff0 // 16 bit code segment size mov cx, #0xf000 // data segment address mov di, #0xfff0 // data segment length jmp APMSYM(ok) ;----------------- ; APM 32 bit protected mode interface connect APMSYM(03): cmp al, #0x03 jne APMSYM(04) mov ax, #0xf000 // 32 bit code segment base mov ebx, #_apm32_entry mov cx, #0xf000 // 16 bit code segment base // 32 bit code segment size (low 16 bits) // 16 bit code segment size (high 16 bits) mov esi, #0xfff0fff0 mov dx, #0xf000 // data segment address mov di, #0xfff0 // data segment length jmp APMSYM(ok) #endif ;----------------- ; APM interface disconnect APMSYM(04): cmp al, #0x04 jne APMSYM(05) jmp APMSYM(ok) ;----------------- ; APM cpu idle APMSYM(05): cmp al, #0x05 jne APMSYM(07) sti hlt jmp APMSYM(ok) ;----------------- ; APM Set Power State APMSYM(07): cmp al, #0x07 jne APMSYM(08) cmp bx, #1 jne APMSYM(ok) cmp cx, #3 je APMSYM(07_poweroff) cmp cx, #2 je APMSYM(07_suspend) cmp cx, #1 je APMSYM(07_standby) jne APMSYM(ok) APMSYM(07_poweroff): // send power off event to emulator cli mov dx, #0x8900 mov ax, #APMSYM(07_poweroff_str) call APMSYM(out_str) APMSYM(07_1): hlt jmp APMSYM(07_1) APMSYM(07_suspend): push edx mov dx, #0x8900 mov ax, #APMSYM(07_suspend_str) call APMSYM(out_str) pop edx jmp APMSYM(ok) APMSYM(07_standby): push edx mov dx, #0x8900 mov ax, #APMSYM(07_standby_str) call APMSYM(out_str) pop edx jmp APMSYM(ok) ;----------------- ; APM Enable / Disable APMSYM(08): cmp al, #0x08 jne APMSYM(0a) jmp APMSYM(ok) ;----------------- ; Get Power Status APMSYM(0a): cmp al, #0x0a jne APMSYM(0b) mov bh, #0x01 // on line // mov bh, #0x02 // battery mov bl, #0xff // unknown battery status // mov bl, #0x03 // charging mov ch, #0x80 // no system battery // mov ch, #0x8 // charging mov cl, #0xff // unknown remaining time // mov cl, #50 mov dx, #0xffff // unknown remaining time mov si, #0 // zero battery // mov si, #1 // one battery jmp APMSYM(ok) ;----------------- ; Get PM Event APMSYM(0b): cmp al, #0x0b jne APMSYM(0e) mov ah, #0x80 // no event pending jmp APMSYM(error) ;----------------- ; APM Driver Version APMSYM(0e): cmp al, #0x0e jne APMSYM(0f) mov ah, #1 mov al, #2 jmp APMSYM(ok) ;----------------- ; APM Engage / Disengage APMSYM(0f): cmp al, #0x0f jne APMSYM(10) jmp APMSYM(ok) ;----------------- ; APM Get Capabilities APMSYM(10): cmp al, #0x10 jne APMSYM(unimplemented) mov bl, #0 mov cx, #0 jmp APMSYM(ok) ;----------------- APMSYM(ok): popf clc #if defined(APM_REAL) jmp iret_modify_cf #else retf #endif APMSYM(unimplemented): APMSYM(error): popf stc #if defined(APM_REAL) jmp iret_modify_cf #else retf #endif #undef APM_PROT32 #undef APM_PROT16 #undef APM_REAL #undef APMSYM bochs-2.6/bios/makesym.perl0000755000175000017500000000163112020641455015626 0ustar guillemguillem#!/usr/bin/perl # # $Id: makesym.perl,v 1.3 2009-12-30 20:28:23 sshwarts Exp $ # # Read output file from as86 (e.g. rombios.txt) and write out a symbol # table suitable for the Bochs debugger. # use strict; use warnings; my $WHERE_BEFORE_SYM_TABLE = 0; my $WHERE_IN_SYM_TABLE = 1; my $WHERE_AFTER_SYM_TABLE = 2; my $where = $WHERE_BEFORE_SYM_TABLE; while () { chop; if ($where == $WHERE_BEFORE_SYM_TABLE && /^Symbols:/) { $where = $WHERE_IN_SYM_TABLE; } elsif ($where == $WHERE_IN_SYM_TABLE && /^$/) { $where = $WHERE_AFTER_SYM_TABLE; } if ($where == $WHERE_IN_SYM_TABLE) { my $name; my $junk; foreach my $f (split(/\s+/)) { if ($f =~ /^[[:xdigit:]]{4,}$/) { if (defined($name)) { print '000f', lc($f), ' ', $name, "\n"; undef($name); undef($junk); next; } } $name = $junk if (defined($junk)); $junk = $f; } } } exit(0); bochs-2.6/bios/biossums.c0000644000175000017500000003646112020641455015312 0ustar guillemguillem/* * $Id: biossums.c 10209 2011-02-24 22:05:47Z sshwarts $ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* biossums.c --- written by Eike W. for the Bochs BIOS */ #include #include #include typedef unsigned char byte; void check( int value, char* message ); #define LEN_BIOS_DATA 0x10000 #define MAX_OFFSET (LEN_BIOS_DATA - 1) #define BIOS_OFFSET 0xFFFF long chksum_bios_get_offset( byte* data, long offset ); byte chksum_bios_calc_value( byte* data, long offset ); byte chksum_bios_get_value( byte* data, long offset ); void chksum_bios_set_value( byte* data, long offset, byte value ); #define _32__LEN 9 #define _32__CHKSUM 10 #define _32__MINHDR 16 long chksum__32__get_offset( byte* data, long offset ); byte chksum__32__calc_value( byte* data, long offset ); byte chksum__32__get_value( byte* data, long offset ); void chksum__32__set_value( byte* data, long offset, byte value ); #define _MP__LEN 8 #define _MP__CHKSUM 10 #define _MP__MINHDR 16 long chksum__mp__get_offset( byte* data, long offset ); byte chksum__mp__calc_value( byte* data, long offset ); byte chksum__mp__get_value( byte* data, long offset ); void chksum__mp__set_value( byte* data, long offset, byte value ); #define PCMP_BASELEN 4 #define PCMP_CHKSUM 7 #define PCMP_EXT_LEN 40 #define PCMP_EXT_CHKSUM 42 #define PCMP_MINHDR 42 long chksum_pcmp_get_offset( byte* data, long offset ); byte chksum_pcmp_calc_value( byte* data, long offset ); byte chksum_pcmp_get_value( byte* data, long offset ); void chksum_pcmp_set_value( byte* data, long offset, byte value ); #define _PIR_LEN 6 #define _PIR_CHKSUM 31 #define _PIR_MINHDR 32 long chksum__pir_get_offset( byte *data, long offset ); byte chksum__pir_calc_value( byte* data, long offset ); byte chksum__pir_get_value( byte* data, long offset ); void chksum__pir_set_value( byte* data, long offset, byte value ); #define _PNP_LEN 5 #define _PNP_CHKSUM 8 #define _PNP_MINHDR 32 long chksum__pnp_get_offset( byte *data, long offset ); byte chksum__pnp_calc_value( byte* data, long offset ); byte chksum__pnp_get_value( byte* data, long offset ); void chksum__pnp_set_value( byte* data, long offset, byte value ); byte bios_data[LEN_BIOS_DATA]; long bios_len; int main(int argc, char* argv[]) { FILE* stream; long offset, tmp_offset; byte cur_val = 0, new_val = 0; int arg = 1, hits, pad = 0; if ((argc == 3) && (!strcmp(argv[1], "-pad"))) { pad = 1; arg = 2; } else if (argc != 2) { printf("Error. Need a file-name as an argument.\n"); exit(EXIT_FAILURE); } memset(bios_data, 0xff, LEN_BIOS_DATA); if ((stream = fopen(argv[arg], "rb")) == NULL) { printf("Error opening %s for reading.\n", argv[arg]); exit(EXIT_FAILURE); } bios_len = fread(bios_data, 1, LEN_BIOS_DATA, stream); if ((bios_len < LEN_BIOS_DATA) && (pad == 0)) { printf("Error reading 64KBytes from %s.\n", argv[arg]); fclose(stream); exit(EXIT_FAILURE); } fclose(stream); if (pad == 1) goto write_bios; hits = 0; offset = 0L; while( (tmp_offset = chksum__32__get_offset( bios_data, offset )) != -1L ) { offset = tmp_offset; cur_val = chksum__32__get_value( bios_data, offset ); new_val = chksum__32__calc_value( bios_data, offset ); printf( "\n\nPCI-Bios header at: 0x%4lX\n", offset ); printf( "Current checksum: 0x%02X\n", cur_val ); printf( "Calculated checksum: 0x%02X ", new_val ); hits++; } if( hits == 1 && cur_val != new_val ) { printf( "Setting checksum." ); chksum__32__set_value( bios_data, offset, new_val ); } if( hits >= 2 ) { printf( "Multiple PCI headers! No checksum set." ); } if( hits ) { printf( "\n" ); } hits = 0; offset = 0L; while( (tmp_offset = chksum__mp__get_offset( bios_data, offset )) != -1L ) { offset = tmp_offset; cur_val = chksum__mp__get_value( bios_data, offset ); new_val = chksum__mp__calc_value( bios_data, offset ); printf( "\n\nMP header at: 0x%4lX\n", offset ); printf( "Current checksum: 0x%02X\n", cur_val ); printf( "Calculated checksum: 0x%02X ", new_val ); hits++; } if( hits == 1 && cur_val != new_val ) { printf( "Setting checksum." ); chksum__mp__set_value( bios_data, offset, new_val ); } if( hits >= 2 ) { printf( "Warning! Multiple MP headers. No checksum set." ); } if( hits ) { printf( "\n" ); } hits = 0; offset = 0L; while( (tmp_offset = chksum_pcmp_get_offset( bios_data, offset )) != -1L ) { offset = tmp_offset; cur_val = chksum_pcmp_get_value( bios_data, offset ); new_val = chksum_pcmp_calc_value( bios_data, offset ); printf( "\n\nPCMP header at: 0x%4lX\n", offset ); printf( "Current checksum: 0x%02X\n", cur_val ); printf( "Calculated checksum: 0x%02X ", new_val ); hits++; } if( hits == 1 && cur_val != new_val ) { printf( "Setting checksum." ); chksum_pcmp_set_value( bios_data, offset, new_val ); } if( hits >= 2 ) { printf( "Warning! Multiple PCMP headers. No checksum set." ); } if( hits ) { printf( "\n" ); } hits = 0; offset = 0L; while( (tmp_offset = chksum__pir_get_offset( bios_data, offset )) != -1L ) { offset = tmp_offset; cur_val = chksum__pir_get_value( bios_data, offset ); new_val = chksum__pir_calc_value( bios_data, offset ); printf( "\n\n$PIR header at: 0x%4lX\n", offset ); printf( "Current checksum: 0x%02X\n", cur_val ); printf( "Calculated checksum: 0x%02X\n ", new_val ); hits++; } if( hits == 1 && cur_val != new_val ) { printf( "Setting checksum." ); chksum__pir_set_value( bios_data, offset, new_val ); } if( hits >= 2 ) { printf( "Warning! Multiple $PIR headers. No checksum set." ); } if( hits ) { printf( "\n" ); } hits = 0; offset = 0L; while( (tmp_offset = chksum__pnp_get_offset( bios_data, offset )) != -1L ) { offset = tmp_offset; cur_val = chksum__pnp_get_value( bios_data, offset ); new_val = chksum__pnp_calc_value( bios_data, offset ); printf( "\n\n$PnP header at: 0x%4lX\n", offset ); printf( "Current checksum: 0x%02X\n", cur_val ); printf( "Calculated checksum: 0x%02X\n ", new_val ); hits++; } if( hits == 1 && cur_val != new_val ) { printf( "Setting checksum." ); chksum__pnp_set_value( bios_data, offset, new_val ); } if( hits >= 2 ) { printf( "Warning! Multiple $PnP headers. No checksum set." ); } if( hits ) { printf( "\n" ); } offset = 0L; offset = chksum_bios_get_offset( bios_data, offset ); cur_val = chksum_bios_get_value( bios_data, offset ); new_val = chksum_bios_calc_value( bios_data, offset ); printf( "\n\nBios checksum at: 0x%4lX\n", offset ); printf( "Current checksum: 0x%02X\n", cur_val ); printf( "Calculated checksum: 0x%02X ", new_val ); if( cur_val != new_val ) { printf( "Setting checksum." ); chksum_bios_set_value( bios_data, offset, new_val ); } printf( "\n" ); write_bios: if ((stream = fopen(argv[arg], "wb")) == NULL) { printf("Error opening %s for writing.\n", argv[arg]); exit(EXIT_FAILURE); } if (fwrite(bios_data, 1, LEN_BIOS_DATA, stream) < LEN_BIOS_DATA) { printf("Error writing 64KBytes to %s.\n", argv[arg]); fclose(stream); exit(EXIT_FAILURE); } fclose(stream); return(EXIT_SUCCESS); } void check(int okay, char* message) { if (!okay) { printf("\n\nError. %s.\n", message); exit(EXIT_FAILURE); } } long chksum_bios_get_offset( byte* data, long offset ) { return( BIOS_OFFSET ); } byte chksum_bios_calc_value( byte* data, long offset ) { int i; byte sum; sum = 0; for( i = 0; i < MAX_OFFSET; i++ ) { sum = sum + *( data + i ); } sum = -sum; /* iso ensures -s + s == 0 on unsigned types */ return( sum ); } byte chksum_bios_get_value( byte* data, long offset ) { return( *( data + BIOS_OFFSET ) ); } void chksum_bios_set_value( byte* data, long offset, byte value ) { *( data + BIOS_OFFSET ) = value; } byte chksum__32__calc_value( byte* data, long offset ) { int i; int len; byte sum; check( offset + _32__MINHDR <= MAX_OFFSET, "_32_ header out of bounds" ); len = *( data + offset + _32__LEN ) << 4; check( offset + len <= MAX_OFFSET, "_32_ header-length out of bounds" ); sum = 0; for( i = 0; i < len; i++ ) { if( i != _32__CHKSUM ) { sum = sum + *( data + offset + i ); } } sum = -sum; return( sum ); } long chksum__32__get_offset( byte* data, long offset ) { long result = -1L; offset = offset + 0x0F; offset = offset & ~( 0x0F ); while( offset + 16 < MAX_OFFSET ) { offset = offset + 16; if( *( data + offset + 0 ) == '_' && \ *( data + offset + 1 ) == '3' && \ *( data + offset + 2 ) == '2' && \ *( data + offset + 3 ) == '_' ) { result = offset; break; } } return( result ); } byte chksum__32__get_value( byte* data, long offset ) { check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" ); return( *( data + offset + _32__CHKSUM ) ); } void chksum__32__set_value( byte* data, long offset, byte value ) { check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" ); *( data + offset + _32__CHKSUM ) = value; } byte chksum__mp__calc_value( byte* data, long offset ) { int i; int len; byte sum; check( offset + _MP__MINHDR <= MAX_OFFSET, "_MP_ header out of bounds" ); len = *( data + offset + _MP__LEN ) << 4; check( offset + len <= MAX_OFFSET, "_MP_ header-length out of bounds" ); sum = 0; for( i = 0; i < len; i++ ) { if( i != _MP__CHKSUM ) { sum = sum + *( data + offset + i ); } } sum = -sum; return( sum ); } long chksum__mp__get_offset( byte* data, long offset ) { long result = -1L; offset = offset + 0x0F; offset = offset & ~( 0x0F ); while( offset + 16 < MAX_OFFSET ) { offset = offset + 16; if( *( data + offset + 0 ) == '_' && \ *( data + offset + 1 ) == 'M' && \ *( data + offset + 2 ) == 'P' && \ *( data + offset + 3 ) == '_' ) { result = offset; break; } } return( result ); } byte chksum__mp__get_value( byte* data, long offset ) { check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" ); return( *( data + offset + _MP__CHKSUM ) ); } void chksum__mp__set_value( byte* data, long offset, byte value ) { check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" ); *( data + offset + _MP__CHKSUM ) = value; } byte chksum_pcmp_calc_value( byte* data, long offset ) { int i; int len; byte sum; check( offset + PCMP_MINHDR <= MAX_OFFSET, "PCMP header out of bounds" ); len = *( data + offset + PCMP_BASELEN ) + \ ( *( data + offset + PCMP_BASELEN + 1 ) << 8 ); check( offset + len <= MAX_OFFSET, "PCMP header-length out of bounds" ); if( *( data + offset + PCMP_EXT_LEN ) | \ *( data + offset + PCMP_EXT_LEN + 1 ) | \ *( data + offset + PCMP_EXT_CHKSUM ) ) { check( 0, "PCMP header indicates extended tables (unsupported)" ); } sum = 0; for( i = 0; i < len; i++ ) { if( i != PCMP_CHKSUM ) { sum = sum + *( data + offset + i ); } } sum = -sum; return( sum ); } long chksum_pcmp_get_offset( byte* data, long offset ) { long result = -1L; offset = offset + 0x0F; offset = offset & ~( 0x0F ); while( offset + 16 < MAX_OFFSET ) { offset = offset + 16; if( *( data + offset + 0 ) == 'P' && \ *( data + offset + 1 ) == 'C' && \ *( data + offset + 2 ) == 'M' && \ *( data + offset + 3 ) == 'P' ) { result = offset; break; } } return( result ); } byte chksum_pcmp_get_value( byte* data, long offset ) { check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" ); return( *( data + offset + PCMP_CHKSUM ) ); } void chksum_pcmp_set_value( byte* data, long offset, byte value ) { check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" ); *( data + offset + PCMP_CHKSUM ) = value; } byte chksum__pir_calc_value( byte* data, long offset ) { int i; int len; byte sum; check( offset + _PIR_MINHDR <= MAX_OFFSET, "$PIR header out of bounds" ); len = *( data + offset + _PIR_LEN ) + \ ( *( data + offset + _PIR_LEN + 1 ) << 8 ); check( offset + len <= MAX_OFFSET, "$PIR header-length out of bounds" ); sum = 0; for( i = 0; i < len; i++ ) { if( i != _PIR_CHKSUM ) { sum = sum + *( data + offset + i ); } } sum = -sum; return( sum ); } long chksum__pir_get_offset( byte* data, long offset ) { long result = -1L; offset = offset + 0x0F; offset = offset & ~( 0x0F ); while( offset + 16 < MAX_OFFSET ) { offset = offset + 16; if( *( data + offset + 0 ) == '$' && \ *( data + offset + 1 ) == 'P' && \ *( data + offset + 2 ) == 'I' && \ *( data + offset + 3 ) == 'R' ) { result = offset; break; } } return( result ); } byte chksum__pir_get_value( byte* data, long offset ) { check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" ); return( *( data + offset + _PIR_CHKSUM ) ); } void chksum__pir_set_value( byte* data, long offset, byte value ) { check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" ); *( data + offset + _PIR_CHKSUM ) = value; } byte chksum__pnp_calc_value( byte* data, long offset ) { int i; int len; byte sum; check( offset + _PNP_MINHDR <= MAX_OFFSET, "$PnP header out of bounds" ); len = *( data + offset + _PNP_LEN ); check( offset + len <= MAX_OFFSET, "$PnP header-length out of bounds" ); sum = 0; for( i = 0; i < len; i++ ) { if( i != _PNP_CHKSUM ) { sum = sum + *( data + offset + i ); } } sum = -sum; return( sum ); } long chksum__pnp_get_offset( byte* data, long offset ) { long result = -1L; offset = offset + 0x0F; offset = offset & ~( 0x0F ); while( offset + 16 < MAX_OFFSET ) { offset = offset + 16; if( *( data + offset + 0 ) == '$' && \ *( data + offset + 1 ) == 'P' && \ *( data + offset + 2 ) == 'n' && \ *( data + offset + 3 ) == 'P' ) { result = offset; break; } } return( result ); } byte chksum__pnp_get_value( byte* data, long offset ) { check( offset + _PNP_CHKSUM <= MAX_OFFSET, "$PnP checksum out of bounds" ); return( *( data + offset + _PNP_CHKSUM ) ); } void chksum__pnp_set_value( byte* data, long offset, byte value ) { check( offset + _PNP_CHKSUM <= MAX_OFFSET, "$PnP checksum out of bounds" ); *( data + offset + _PNP_CHKSUM ) = value; } bochs-2.6/PARAM_TREE.txt0000644000175000017500000000667012020641507014563 0ustar guillemguillem$Id: PARAM_TREE.txt 11276 2012-07-12 14:51:54Z sshwarts $ Starting from Bochs 2.3 the parameters are organized in a tree structure instead of a huge flat list. The parameter tree was required for implementing the save/restore feature, and it gives access to the device state from within the debugger. -Volker Current organization of parameters in the tree general config_interface start_mode benchmark restore restore_path debug_running cpu n_processors n_cores n_threads model ips quantum reset_on_triple_fault msrs cpuid_limit_winnt mwait_is_nop cpuid family model stepping vendor_string brand_string mmx sep sse sse4a aes movbe adx xsave xsaveopt svm vmx avx avx_f16c avx_fma bmi xop tbm fma4 apic x86_64 1g_pages pcid fsgsbase smep mwait memory standard ram size rom path address vgarom path optrom 0 path addr 1 path addr 2 path addr 3 path addr optram 0 path addr 1 path addr 2 path addr 3 path addr clock_cmos clock_sync time0 cmosimage enabled path rtc_init pci i440fx_support slot 1 2 3 4 5 pcidev vendor device display display_library displaylib_options private_colormap fullscreen screenmode vga_extension vga_update_interval keyboard_mouse keyboard type serial_delay paste_delay use_mapping keymap user_shortcut mouse type enabled boot_params boot_drive1 boot_drive2 boot_drive3 floppy_sig_check load32bitos which path iolog initrd floppy 0 devtype path type readonly status 1 devtype path type readonly status ata 0 resources enabled ioaddr1 ioaddr2 irq master present type path mode journal cylinders heads spt status model biosdetect translation slave (same options as master) 1 (same options as ata.0) 2 (same options as ata.0) 3 (same options as ata.0) ports serial 1 enabled mode dev 2 (same options as ports.serial.1) 3 (same options as ports.serial.1) 4 (same options as ports.serial.1) parallel 1 enabled outfile 2 (same options as ports.parallel.1) usb uhci enabled port1 device options port2 device options ohci (same options as ports.usb.uhci) xhci (same options as ports.usb.uhci) network ne2k enabled ioaddr irq macaddr ethmod ethdev script bootrom pnic enabled macaddr ethmod ethdev script bootrom e1000 enabled macaddr ethmod ethdev script bootrom sound sb16 enabled midifile wavefile logfile midimode wavemode loglevel dmatimer es1370 enabled wavedev misc port_e9_hack gdbstub port text_base data_base bss_base user_plugin 1 ... 8 log filename prefix debugger_filename menu disk disk_win32 memory runtime cdrom usb misc bochs (subtree containing Bochs state) wxdebug (special subtree for wxBochs debugger) user (subtree for user-defined options) bochs-2.6/logio.cc0000644000175000017500000003601612020641507013760 0ustar guillemguillem///////////////////////////////////////////////////////////////////////// // $Id: logio.cc 11116 2012-03-27 21:30:34Z sshwarts $ ///////////////////////////////////////////////////////////////////////// // // Copyright (C) 2001-2010 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // ///////////////////////////////////////////////////////////////////////// #include "bochs.h" #include "cpu/cpu.h" #include "iodev/iodev.h" #include #if BX_WITH_CARBON #include #endif // Just for the iofunctions static int Allocio=0; const char* iofunctions::getlevel(int i) const { static const char *loglevel[N_LOGLEV] = { "DEBUG", "INFO", "ERROR", "PANIC" }; if (i>=0 && i=ACT_IGNORE && iput("logio", "IO"); log->ldebug("Init(log file: '%s').",logfn); } void iofunctions::add_logfn(logfunc_t *fn) { assert(n_logfn < MAX_LOGFNS); logfn_list[n_logfn++] = fn; } void iofunctions::remove_logfn(logfunc_t *fn) { assert(n_logfn > 0); int i = 0; while ((fn != logfn_list[i]) && (i < n_logfn)) { i++; }; if (i < n_logfn) { for (int j=i; jsetonoff(loglevel, action); } void iofunctions::init_log(const char *fn) { assert(magic==MAGIC_LOGNUM); // use newfd/newfn so that we can log the message to the OLD log // file descriptor. FILE *newfd = stderr; const char *newfn = "/dev/stderr"; if(strcmp(fn, "-") != 0) { newfd = fopen(fn, "w"); if(newfd != NULL) { newfn = strdup(fn); log->ldebug("Opened log file '%s'.", fn); } else { // in constructor, genlog might not exist yet, so do it the safe way. log->error("Couldn't open log file: %s, using stderr instead", fn); newfd = stderr; } } logfd = newfd; logfn = newfn; } void iofunctions::init_log(FILE *fs) { assert(magic==MAGIC_LOGNUM); logfd = fs; if(fs == stderr) { logfn = "/dev/stderr"; } else if(fs == stdout) { logfn = "/dev/stdout"; } else { logfn = "(unknown)"; } } void iofunctions::init_log(int fd) { assert(magic==MAGIC_LOGNUM); FILE *tmpfd; if((tmpfd = fdopen(fd,"w")) == NULL) { log->panic("Couldn't open fd %d as a stream for writing", fd); return; } init_log(tmpfd); }; void iofunctions::exit_log() { flush(); if (logfd != stderr) { fclose(logfd); logfd = stderr; free((char *)logfn); logfn = "/dev/stderr"; } } // all other functions may use genlog safely. #define LOG_THIS genlog-> // This converts the option string to a printf style string with the following args: // 1. timer, 2. event, 3. cpu0 eip, 4. device void iofunctions::set_log_prefix(const char* prefix) { strcpy(logprefix, prefix); } // iofunctions::out(level, prefix, fmt, ap) // DO NOT nest out() from ::info() and the like. // fmt and ap retained for direct printinf from iofunctions only! void iofunctions::out(int level, const char *prefix, const char *fmt, va_list ap) { char c=' ', *s; assert(magic==MAGIC_LOGNUM); assert(this != NULL); assert(logfd != NULL); switch (level) { case LOGLEV_INFO: c='i'; break; case LOGLEV_PANIC: c='p'; break; case LOGLEV_ERROR: c='e'; break; case LOGLEV_DEBUG: c='d'; break; default: break; } s=logprefix; while(*s) { switch(*s) { case '%': if(*(s+1)) s++; else break; switch(*s) { case 'd': fprintf(logfd, "%s", prefix==NULL?"":prefix); break; case 't': fprintf(logfd, FMT_TICK, bx_pc_system.time_ticks()); break; case 'i': #if BX_SUPPORT_SMP == 0 fprintf(logfd, "%08x", BX_CPU(0)->get_eip()); #endif break; case 'e': fprintf(logfd, "%c", c); break; case '%': fprintf(logfd,"%%"); break; default: fprintf(logfd,"%%%c",*s); } break; default : fprintf(logfd,"%c",*s); } s++; } fprintf(logfd," "); if(level==LOGLEV_PANIC) fprintf(logfd, ">>PANIC<< "); vfprintf(logfd, fmt, ap); fprintf(logfd, "\n"); fflush(logfd); } iofunctions::iofunctions(FILE *fs) { init(); init_log(fs); } iofunctions::iofunctions(const char *fn) { init(); init_log(fn); } iofunctions::iofunctions(int fd) { init(); init_log(fd); } iofunctions::iofunctions() { init(); } iofunctions::~iofunctions(void) { // flush before erasing magic number, or flush does nothing. flush(); magic=0; } #define LOG_THIS genlog-> int logfunctions::default_onoff[N_LOGLEV] = { ACT_IGNORE, // ignore debug ACT_REPORT, // report info ACT_REPORT, // report error #if BX_WITH_WX || BX_WITH_WIN32 || BX_WITH_X11 ACT_ASK // on panic, ask user what to do #else ACT_FATAL // on panic, quit #endif }; logfunctions::logfunctions(void) { name = NULL; prefix = NULL; put("?", " "); if (io == NULL && Allocio == 0) { Allocio = 1; io = new iofunc_t(stderr); } setio(io); // BUG: unfortunately this can be called before the bochsrc is read, // which means that the bochsrc has no effect on the actions. for (int i=0; iremove_logfn(this); if (name) free(name); if (prefix) free(prefix); } void logfunctions::setio(iofunc_t *i) { // add pointer to iofunction object to use logio = i; // give iofunction a pointer to me i->add_logfn(this); } void logfunctions::put(const char *p) { const char *n = p; put(n, p); } void logfunctions::put(const char *n, const char *p) { char *tmpbuf=strdup("[ ]"); // if we ever have more than 32 chars, // we need to rethink this if (tmpbuf == NULL) return; // allocation not successful if (name != NULL) { free(name); // free previously allocated memory name = NULL; } name = strdup(n); if (prefix != NULL) { free(prefix); // free previously allocated memory prefix = NULL; } size_t len=strlen(p); if (len > (strlen(tmpbuf) - 2)) { len = strlen(tmpbuf) - 2; } for(size_t i=1;i <= len;i++) { tmpbuf[i]=p[i-1]; } prefix = tmpbuf; } void logfunctions::info(const char *fmt, ...) { va_list ap; assert(logio != NULL); if(!onoff[LOGLEV_INFO]) return; va_start(ap, fmt); logio->out(LOGLEV_INFO, prefix, fmt, ap); if (onoff[LOGLEV_INFO] == ACT_ASK) ask(LOGLEV_INFO, prefix, fmt, ap); if (onoff[LOGLEV_INFO] == ACT_FATAL) fatal(prefix, fmt, ap, 1); va_end(ap); } void logfunctions::error(const char *fmt, ...) { va_list ap; assert(logio != NULL); if(!onoff[LOGLEV_ERROR]) return; va_start(ap, fmt); logio->out(LOGLEV_ERROR, prefix, fmt, ap); if (onoff[LOGLEV_ERROR] == ACT_ASK) ask(LOGLEV_ERROR, prefix, fmt, ap); if (onoff[LOGLEV_ERROR] == ACT_FATAL) fatal(prefix, fmt, ap, 1); va_end(ap); } void logfunctions::panic(const char *fmt, ...) { va_list ap; assert(logio != NULL); // Special case for panics since they are so important. Always print // the panic to the log, no matter what the log action says. //if(!onoff[LOGLEV_PANIC]) return; va_start(ap, fmt); logio->out(LOGLEV_PANIC, prefix, fmt, ap); // This fixes a funny bug on linuxppc where va_list is no pointer but a struct va_end(ap); va_start(ap, fmt); if (onoff[LOGLEV_PANIC] == ACT_ASK) ask(LOGLEV_PANIC, prefix, fmt, ap); if (onoff[LOGLEV_PANIC] == ACT_FATAL) fatal(prefix, fmt, ap, 1); va_end(ap); } void logfunctions::ldebug(const char *fmt, ...) { va_list ap; assert(logio != NULL); if(!onoff[LOGLEV_DEBUG]) return; va_start(ap, fmt); logio->out(LOGLEV_DEBUG, prefix, fmt, ap); if (onoff[LOGLEV_DEBUG] == ACT_ASK) ask(LOGLEV_DEBUG, prefix, fmt, ap); if (onoff[LOGLEV_DEBUG] == ACT_FATAL) fatal(prefix, fmt, ap, 1); va_end(ap); } void logfunctions::ask(int level, const char *prefix, const char *fmt, va_list ap) { // Guard against reentry on ask() function. The danger is that some // function that's called within ask() could trigger another // BX_PANIC that could call ask() again, leading to infinite // recursion and infinite asks. static char in_ask_already = 0; char buf1[1024]; if (in_ask_already) { fprintf(stderr, "logfunctions::ask() should not reenter!!\n"); return; } in_ask_already = 1; vsnprintf(buf1, sizeof(buf1), fmt, ap); // FIXME: facility set to 0 because it's unknown. // update vga screen. This is useful because sometimes useful messages // are printed on the screen just before a panic. It's also potentially // dangerous if this function calls ask again... That's why I added // the reentry check above. if (SIM->get_init_done()) DEV_vga_refresh(); // ensure the text screen is showing SIM->set_display_mode(DISP_MODE_CONFIG); int val = SIM->log_msg(prefix, level, buf1); switch(val) { case BX_LOG_ASK_CHOICE_CONTINUE: break; case BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS: // user said continue, and don't "ask" for this facility again. setonoff(level, ACT_REPORT); break; case BX_LOG_ASK_CHOICE_DIE: case BX_LOG_NOTIFY_FAILED: bx_user_quit = (val==BX_LOG_ASK_CHOICE_DIE)?1:0; in_ask_already = 0; // because fatal will longjmp out fatal(prefix, buf1, ap, 1); // should never get here BX_PANIC(("in ask(), fatal() should never return!")); break; case BX_LOG_ASK_CHOICE_DUMP_CORE: fprintf(stderr, "User chose to dump core...\n"); #if BX_HAVE_ABORT abort(); #else // do something highly illegal that should kill the process. // Hey, this is fun! { char *crashptr = (char *)0; char c = *crashptr; } fprintf(stderr, "Sorry, I couldn't find your abort() function. Exiting."); exit(0); #endif #if BX_DEBUGGER case BX_LOG_ASK_CHOICE_ENTER_DEBUG: // user chose debugger. To "drop into the debugger" we just set the // interrupt_requested bit and continue execution. Before the next // instruction, it should notice the user interrupt and return to // the debugger. bx_debug_break(); break; #elif BX_GDBSTUB case BX_LOG_ASK_CHOICE_ENTER_DEBUG: bx_gdbstub_break(); break; #endif default: // this happens if panics happen before the callback is initialized // in gui/control.cc. fprintf(stderr, "WARNING: log_msg returned unexpected value %d\n", val); } // return to simulation mode SIM->set_display_mode(DISP_MODE_SIM); in_ask_already = 0; } #if BX_WITH_CARBON /* Panic button to display fatal errors. Completely self contained, can't rely on carbon.cc being available */ static void carbonFatalDialog(const char *error, const char *exposition) { DialogRef alertDialog; CFStringRef cfError; CFStringRef cfExposition; DialogItemIndex index; AlertStdCFStringAlertParamRec alertParam = {0}; // Init libraries InitCursor(); // Assemble dialog cfError = CFStringCreateWithCString(NULL, error, kCFStringEncodingASCII); if(exposition != NULL) { cfExposition = CFStringCreateWithCString(NULL, exposition, kCFStringEncodingASCII); } else { cfExposition = NULL; } alertParam.version = kStdCFStringAlertVersionOne; alertParam.defaultText = CFSTR("Quit"); alertParam.position = kWindowDefaultPosition; alertParam.defaultButton = kAlertStdAlertOKButton; // Display Dialog CreateStandardAlert( kAlertStopAlert, cfError, cfExposition, /* can be NULL */ &alertParam, /* can be NULL */ &alertDialog); RunStandardAlert(alertDialog, NULL, &index); // Cleanup CFRelease(cfError); if(cfExposition != NULL) { CFRelease(cfExposition); } } #endif void logfunctions::fatal(const char *prefix, const char *fmt, va_list ap, int exit_status) { #if !BX_WITH_WX // store prefix and message in 'exit_msg' before unloading device plugins char tmpbuf[1024]; char exit_msg[1024]; vsprintf(tmpbuf, fmt, ap); sprintf(exit_msg, "%s %s", prefix, tmpbuf); #endif #if !BX_DEBUGGER bx_atexit(); #endif #if BX_WITH_CARBON if(!isatty(STDIN_FILENO) && !SIM->get_init_done()) { char buf1[1024]; char buf2[1024]; vsnprintf(buf1, sizeof(buf1), fmt, ap); snprintf(buf2, sizeof(buf2), "Bochs startup error\n%s", buf1); carbonFatalDialog(buf2, "For more information, try running Bochs within Terminal by clicking on \"bochs.scpt\"."); } #endif #if !BX_WITH_WX static const char *divider = "========================================================================"; fprintf(stderr, "%s\n", divider); fprintf(stderr, "Bochs is exiting with the following message:\n"); fprintf(stderr, "%s", exit_msg); fprintf(stderr, "\n%s\n", divider); #endif #if !BX_DEBUGGER BX_EXIT(exit_status); #else static bx_bool dbg_exit_called = 0; if (dbg_exit_called == 0) { dbg_exit_called = 1; bx_dbg_exit(exit_status); } #endif // not safe to use BX_* log functions in here. fprintf(stderr, "fatal() should never return, but it just did\n"); } iofunc_t *io = NULL; logfunc_t *genlog = NULL; void bx_center_print(FILE *file, const char *line, unsigned maxwidth) { size_t len = strlen(line); if (len > maxwidth) BX_PANIC(("bx_center_print: line is too long: '%s'", line)); size_t imax = (maxwidth - len) >> 1; for (size_t i=0; iquit_sim (x) #else // provide the real main and the usual exit. #define BX_EXIT(x) ::exit(x) #endif // if simulating Linux, this provides a few more debugging options // such as tracing all system calls. #define BX_DEBUG_LINUX 0 // adds support for the GNU readline library in the debugger command // prompt. #define HAVE_LIBREADLINE 0 #define HAVE_READLINE_HISTORY_H 0 // Define to 1 if you have #define HAVE_LOCALE_H 0 // I rebuilt the code which provides timers to IO devices. // Setting this to 1 will introduce a little code which // will panic out if cases which shouldn't happen occur. // Set this to 0 for optimal performance. #define BX_TIMER_DEBUG 0 // Settable A20 line. For efficiency, you can disable // having a settable A20 line, eliminating conditional // code for every physical memory access. You'll have // to tell your software not to mess with the A20 line, // and accept it as always being on if you change this. // 1 = use settable A20 line. (normal) // 0 = A20 is like the rest of the address lines #define BX_SUPPORT_A20 1 // Processor Instructions Per Second // To find out what value to use for the 'ips' directive // in your '.bochsrc' file, set BX_SHOW_IPS to 1, and // run the software in bochs you plan to use most. Bochs // will print out periodic IPS ratings. This will change // based on the processor mode at the time, and various // other factors. You'll get a reasonable estimate though. // When you're done, reset BX_SHOW_IPS to 0, do a // 'make all-clean', then 'make' again. #define BX_SHOW_IPS 0 #if (BX_SHOW_IPS) && (defined(__MINGW32__) || defined(_MSC_VER)) #define SIGALRM 14 #endif // Compile in support for DMA & FLOPPY IO. You'll need this // if you plan to use the floppy drive emulation. But if // you're environment doesn't require it, you can change // it to 0. #define BX_DMA_FLOPPY_IO 1 // Default number of Megs of memory to emulate. The // 'megs:' directive in the '.bochsrc' file overrides this, // allowing per-run settings. #define BX_DEFAULT_MEM_MEGS 32 // CPU level emulation. Default level is set in the configure script. // BX_CPU_LEVEL defines the CPU level to emulate. #define BX_CPU_LEVEL 0 // emulate x86-64 instruction set? #define BX_SUPPORT_X86_64 0 // emulate long physical address (>32 bit) #define BX_PHY_ADDRESS_LONG 0 #define BX_HAVE_SLEEP 0 #define BX_HAVE_MSLEEP 0 #define BX_HAVE_USLEEP 0 #define BX_HAVE_NANOSLEEP 0 #define BX_HAVE_ABORT 0 #define BX_HAVE_SOCKLEN_T 0 #define BX_HAVE_SOCKADDR_IN_SIN_LEN 0 #define BX_HAVE_GETTIMEOFDAY 0 #if defined(WIN32) #define BX_HAVE_REALTIME_USEC 1 #else #define BX_HAVE_REALTIME_USEC (BX_HAVE_GETTIMEOFDAY) #endif #define BX_HAVE_MKSTEMP 0 #define BX_HAVE_SYS_MMAN_H 0 #define BX_HAVE_XPM_H 0 #define BX_HAVE_TIMELOCAL 0 #define BX_HAVE_GMTIME 0 #define BX_HAVE_MKTIME 0 #define BX_HAVE_TMPFILE64 0 #define BX_HAVE_FSEEK64 0 #define BX_HAVE_FSEEKO64 0 #define BX_HAVE_NET_IF_H 0 #define BX_HAVE___BUILTIN_BSWAP32 0 #define BX_HAVE___BUILTIN_BSWAP64 0 // This turns on Roland Mainz's idle hack. Presently it is specific to the X11 // and term gui. If people try to enable it elsewhere, give a compile error // after the gui definition so that they don't waste their time trying. #define BX_USE_IDLE_HACK 0 // Minimum Emulated IPS. // This is used in the realtime PIT as well as for checking the // IPS value set in the config file. #define BX_MIN_IPS 1000000 // Minimum and maximum values for SMP quantum variable. Defines // how many instructions each CPU could execute in one // shot (one cpu_loop call) #define BX_SMP_QUANTUM_MIN 1 #define BX_SMP_QUANTUM_MAX 32 // Use Static Member Funtions to eliminate 'this' pointer passing // If you want the efficiency of 'C', you can make all the // members of the C++ CPU class to be static. // This defaults to 1 since it should improve performance, but when // SMP mode is enabled, it will be turned off by configure. #define BX_USE_CPU_SMF 1 #define BX_USE_MEM_SMF 1 // Use static member functions in IO DEVice emulation modules. // For efficiency, use C like functions for IO handling, // and declare a device instance at compile time, // instead of using 'new' and storing the pointer. This // eliminates some overhead, especially for high-use IO // devices like the disk drive. // 1 = Use static member efficiency (normal) // 0 = Use nonstatic member functions (use only if you need // multiple instances of a device class #define BX_USE_HD_SMF 1 // Hard drive #define BX_USE_BIOS_SMF 1 // BIOS #define BX_USE_CMOS_SMF 1 // CMOS #define BX_USE_DMA_SMF 1 // DMA #define BX_USE_FD_SMF 1 // Floppy #define BX_USE_KEY_SMF 1 // Keyboard #define BX_USE_PAR_SMF 1 // Parallel #define BX_USE_PIC_SMF 1 // PIC #define BX_USE_PIT_SMF 1 // PIT #define BX_USE_SER_SMF 1 // Serial #define BX_USE_UM_SMF 1 // Unmapped #define BX_USE_VGA_SMF 1 // VGA #define BX_USE_SB16_SMF 1 // SB 16 soundcard #define BX_USE_ES1370_SMF 1 // ES1370 soundcard #define BX_USE_DEV_SMF 1 // System Devices (port92) #define BX_USE_PCI_SMF 1 // PCI #define BX_USE_P2I_SMF 1 // PCI-to-ISA bridge #define BX_USE_PIDE_SMF 1 // PCI-IDE #define BX_USE_PCIDEV_SMF 1 // PCI-DEV #define BX_USE_USB_UHCI_SMF 1 // USB UHCI hub #define BX_USE_USB_OHCI_SMF 1 // USB OHCI hub #define BX_USE_USB_XHCI_SMF 1 // USB xHCI hub #define BX_USE_PCIPNIC_SMF 1 // PCI pseudo NIC #define BX_USE_E1000_SMF 1 // Intel(R) Gigabit Ethernet #define BX_USE_NE2K_SMF 1 // NE2K #define BX_USE_EFI_SMF 1 // External FPU IRQ #define BX_USE_GAMEPORT_SMF 1 // Gameport #define BX_USE_CIRRUS_SMF 1 // SVGA Cirrus #define BX_USE_BUSM_SMF 1 // Bus Mouse #define BX_USE_ACPI_SMF 1 // ACPI #define BX_PLUGINS 0 #define BX_HAVE_LTDL 0 #define BX_HAVE_DLFCN_H 0 #if BX_PLUGINS && \ ( !BX_USE_HD_SMF || !BX_USE_BIOS_SMF || !BX_USE_CMOS_SMF \ || !BX_USE_DMA_SMF || !BX_USE_FD_SMF || !BX_USE_KEY_SMF \ || !BX_USE_PAR_SMF || !BX_USE_PIC_SMF || !BX_USE_PIT_SMF \ || !BX_USE_SER_SMF || !BX_USE_UM_SMF || !BX_USE_VGA_SMF \ || !BX_USE_SB16_SMF || !BX_USE_ES1370_SMF || !BX_USE_DEV_SMF \ || !BX_USE_PCI_SMF || !BX_USE_P2I_SMF \ || !BX_USE_USB_UHCI_SMF || !BX_USE_USB_OHCI_SMF || !BX_USE_USB_XHCI_SMF \ || !BX_USE_PCIPNIC_SMF || !BX_USE_PIDE_SMF || !BX_USE_ACPI_SMF \ || !BX_USE_NE2K_SMF || !BX_USE_EFI_SMF || !BX_USE_GAMEPORT_SMF \ || !BX_USE_E1000_SMF || !BX_USE_PCIDEV_SMF || !BX_USE_CIRRUS_SMF) #error You must use SMF to have plugins #endif #define USE_RAW_SERIAL 0 // This option enables RAM file backing for large guest memory with a smaller // amount host memory, without causing a panic when host memory is exhausted. #define BX_LARGE_RAMFILE 0 // This option defines the number of supported ATA channels. // There are up to two drives per ATA channel. #define BX_MAX_ATA_CHANNEL 4 #if (BX_MAX_ATA_CHANNEL>4 || BX_MAX_ATA_CHANNEL<1) #error "BX_MAX_ATA_CHANNEL should be between 1 and 4" #endif // ================================================================= // BEGIN: OPTIONAL DEBUGGER SECTION // // These options are only used if you compile in support for the // native command line debugging environment. Typically, the debugger // is not used, and this section can be ignored. // ================================================================= // Compile in support for virtual/linear/physical breakpoints. // Enable only those you need. Recommend using only linear // breakpoints, unless you need others. Less supported means // slightly faster execution time. #define BX_DBG_MAX_VIR_BPOINTS 16 #define BX_DBG_MAX_LIN_BPOINTS 16 #define BX_DBG_MAX_PHY_BPOINTS 16 #define BX_DBG_MAX_WATCHPONTS 16 // max file pathname size for debugger commands #define BX_MAX_PATH 256 // max nesting level for debug scripts including other scripts #define BX_INFILE_DEPTH 10 // use this command to include (nest) debug scripts #define BX_INCLUDE_CMD "source" // Make a call to command line debugger extensions. If set to 1, // a call is made. An external routine has a chance to process // the command. If it does, than the debugger ignores the command. #define BX_DBG_EXTENSIONS 0 // ================================================================= // END: OPTIONAL DEBUGGER SECTION // ================================================================= ////////////////////////////////////////////////////////////////////// // END OF USER CONFIGURABLE OPTIONS : DON'T EDIT ANYTHING BELOW !!! // // THIS IS GENERATED BY THE ./configure SCRIPT // ////////////////////////////////////////////////////////////////////// #define BX_WITH_X11 0 #define BX_WITH_WIN32 0 #define BX_WITH_MACOS 0 #define BX_WITH_CARBON 0 #define BX_WITH_NOGUI 0 #define BX_WITH_TERM 0 #define BX_WITH_RFB 0 #define BX_WITH_AMIGAOS 0 #define BX_WITH_SDL 0 #define BX_WITH_SVGA 0 #define BX_WITH_WX 0 // BX_USE_TEXTCONFIG should be set to 1 unless Bochs is compiled // for wxWidgets only. #define BX_USE_TEXTCONFIG 1 // A certain functions must NOT be fastcall even if compiled with fastcall // option, and those are callbacks from Windows which are defined either // as cdecl or stdcall. The entry point main() also has to remain cdecl. #ifndef CDECL #if defined(_MSC_VER) #define CDECL __cdecl #else #define CDECL #endif #endif // add special export symbols for win32 DLL building. The main code must // have __declspec(dllexport) on variables, functions, or classes that the // plugins can access. The plugins should #define PLUGGABLE which will // activate the __declspec(dllimport) instead. #if defined(WIN32) || defined(__CYGWIN__) # if BX_PLUGINS && defined(BX_PLUGGABLE) // #warning I will import DLL symbols from Bochs main program. # define BOCHSAPI __declspec(dllimport) # elif BX_PLUGINS // #warning I will export DLL symbols. # define BOCHSAPI __declspec(dllexport) # endif #endif #ifndef BOCHSAPI # define BOCHSAPI #endif #if defined(__CYGWIN__) // Make BOCHSAPI_CYGONLY exactly the same as BOCHSAPI. This symbol // will be used for any cases where Cygwin requires a special tag // but VC++ does not. #define BOCHSAPI_CYGONLY BOCHSAPI #else // define the symbol to be empty #define BOCHSAPI_CYGONLY /*empty*/ #endif #if defined(_MSC_VER) // Make BOCHSAPI_MSVCONLY exactly the same as BOCHSAPI. This symbol // will be used for any cases where VC++ requires a special tag // but Cygwin does not. #define BOCHSAPI_MSVCONLY BOCHSAPI #else // define the symbol to be empty #define BOCHSAPI_MSVCONLY /*empty*/ #endif #define BX_DEFAULT_CONFIG_INTERFACE "defined_by_configure" #define BX_DEFAULT_DISPLAY_LIBRARY "defined_by_configure" // Roland Mainz's idle hack is presently specific to X11. If people try to // enable it elsewhere, give a compile error so that they don't waste their // time trying. #if (BX_USE_IDLE_HACK && !BX_WITH_X11 && !BX_WITH_TERM) # error IDLE_HACK will only work with the X11 or term gui. Correct configure args and retry. #endif #define WORDS_BIGENDIAN 0 #define SIZEOF_UNSIGNED_CHAR 0 #define SIZEOF_UNSIGNED_SHORT 0 #define SIZEOF_UNSIGNED_INT 0 #define SIZEOF_UNSIGNED_LONG 0 #define SIZEOF_UNSIGNED_LONG_LONG 0 #define SIZEOF_INT_P 0 #define BX_64BIT_CONSTANTS_USE_LL 1 #if BX_64BIT_CONSTANTS_USE_LL // doesn't work on Microsoft Visual C++, maybe others #define BX_CONST64(x) (x##LL) #elif defined(_MSC_VER) #define BX_CONST64(x) (x##I64) #else #define BX_CONST64(x) (x) #endif #if defined(WIN32) typedef unsigned char Bit8u; typedef signed char Bit8s; typedef unsigned short Bit16u; typedef signed short Bit16s; typedef unsigned int Bit32u; typedef signed int Bit32s; #ifdef __GNUC__ typedef unsigned long long Bit64u; typedef signed long long Bit64s; #include #include #else typedef unsigned __int64 Bit64u; typedef signed __int64 Bit64s; #endif #elif BX_WITH_MACOS typedef unsigned char Bit8u; typedef signed char Bit8s; typedef unsigned short Bit16u; typedef signed short Bit16s; typedef unsigned int Bit32u; typedef signed int Bit32s; typedef unsigned long long Bit64u; typedef signed long long Bit64s; #else // Unix like platforms #if SIZEOF_UNSIGNED_CHAR != 1 # error "sizeof (unsigned char) != 1" #else typedef unsigned char Bit8u; typedef signed char Bit8s; #endif #if SIZEOF_UNSIGNED_SHORT != 2 # error "sizeof (unsigned short) != 2" #else typedef unsigned short Bit16u; typedef signed short Bit16s; #endif #if SIZEOF_UNSIGNED_INT == 4 typedef unsigned int Bit32u; typedef signed int Bit32s; #elif SIZEOF_UNSIGNED_LONG == 4 typedef unsigned long Bit32u; typedef signed long Bit32s; #else # error "can't find sizeof(type) of 4 bytes!" #endif #if SIZEOF_UNSIGNED_LONG == 8 typedef unsigned long Bit64u; typedef signed long Bit64s; #elif SIZEOF_UNSIGNED_LONG_LONG == 8 typedef unsigned long long Bit64u; typedef signed long long Bit64s; #else # error "can't find data type of 8 bytes" #endif #endif #define GET32L(val64) ((Bit32u)(((Bit64u)(val64)) & 0xFFFFFFFF)) #define GET32H(val64) ((Bit32u)(((Bit64u)(val64)) >> 32)) // now that Bit32u and Bit64u exist, defined bx_address #if BX_SUPPORT_X86_64 typedef Bit64u bx_address; #else typedef Bit32u bx_address; #endif // define physical and linear address types typedef bx_address bx_lin_address; #if BX_SUPPORT_X86_64 #define BX_LIN_ADDRESS_WIDTH 48 #else #define BX_LIN_ADDRESS_WIDTH 32 #endif #if BX_PHY_ADDRESS_LONG typedef Bit64u bx_phy_address; #if BX_CPU_LEVEL == 5 #define BX_PHY_ADDRESS_WIDTH 36 #else #define BX_PHY_ADDRESS_WIDTH 40 #endif #else typedef Bit32u bx_phy_address; #define BX_PHY_ADDRESS_WIDTH 32 #endif // small sanity check #if BX_PHY_ADDRESS_LONG #if (BX_PHY_ADDRESS_WIDTH <= 32) #error "BX_PHY_ADDRESS_LONG implies emulated physical address width > 32 bit" #endif #endif #define BX_PHY_ADDRESS_MASK ((((Bit64u)(1)) << BX_PHY_ADDRESS_WIDTH) - 1) #define BX_PHY_ADDRESS_RESERVED_BITS (~BX_PHY_ADDRESS_MASK) // technically, in an 8 bit signed the real minimum is -128, not -127. // But if you decide to negate -128 you tend to get -128 again, so it's // better not to use the absolute maximum in the signed range. #define BX_MAX_BIT64U ( (Bit64u) -1 ) #define BX_MIN_BIT64U ( 0 ) #define BX_MAX_BIT64S ( ((Bit64u) -1) >> 1 ) #define BX_MIN_BIT64S ( (Bit64s)-(((Bit64u) -1) >> 1) ) #define BX_MAX_BIT32U ( (Bit32u) -1 ) #define BX_MIN_BIT32U ( 0 ) #define BX_MAX_BIT32S ( ((Bit32u) -1) >> 1 ) #define BX_MIN_BIT32S ( (Bit32s)-(((Bit32u) -1) >> 1) ) #define BX_MAX_BIT16U ( (Bit16u) -1 ) #define BX_MIN_BIT16U ( 0 ) #define BX_MAX_BIT16S ( ((Bit16u) -1) >> 1 ) #define BX_MIN_BIT16S ( (Bit16s)-(((Bit16u) -1) >> 1) ) #define BX_MAX_BIT8U ( (Bit8u) -1 ) #define BX_MIN_BIT8U ( 0 ) #define BX_MAX_BIT8S ( ((Bit8u) -1) >> 1 ) #define BX_MIN_BIT8S ( (Bit8s)-(((Bit8u) -1) >> 1) ) // create an unsigned integer type that is the same size as a pointer. // You can typecast a pointer to a bx_pr_equiv_t without losing any // bits (and without getting the compiler excited). #if SIZEOF_INT_P == 4 typedef Bit32u bx_ptr_equiv_t; #elif SIZEOF_INT_P == 8 typedef Bit64u bx_ptr_equiv_t; #else # error "could not define bx_ptr_equiv_t to size of int*" #endif // Use a boolean type that will not conflict with the builtin type // on any system. typedef Bit32u bx_bool; #if BX_WITH_MACOS # define bx_ptr_t char * #else # define bx_ptr_t void * #endif #if defined(WIN32) # define BX_LITTLE_ENDIAN #elif BX_WITH_MACOS # define BX_BIG_ENDIAN #else #if WORDS_BIGENDIAN # define BX_BIG_ENDIAN #else # define BX_LITTLE_ENDIAN #endif #endif // defined(WIN32) #if BX_SUPPORT_X86_64 #ifdef BX_LITTLE_ENDIAN typedef struct { Bit64u lo; Bit64u hi; } Bit128u; typedef struct { Bit64u lo; Bit64s hi; } Bit128s; #else // must be Big Endian typedef struct { Bit64u hi; Bit64u lo; } Bit128u; typedef struct { Bit64s hi; Bit64u lo; } Bit128s; #endif #endif // #if BX_SUPPORT_X86_64 // for now only term.cc requires a GUI sighandler. #define BX_GUI_SIGHANDLER (BX_WITH_TERM) #define HAVE_SIGACTION 1 // configure will change the definition of "inline" to the value // that the C compiler allows. It tests the following keywords to // see if any is permitted: inline, __inline__, __inline. If none // is permitted, it defines inline to be empty. #define inline inline // Use BX_CPP_INLINE for all C++ inline functions. Note that the // word "inline" itself may now be redefined by the above #define. #define BX_CPP_INLINE inline #ifdef __GNUC__ // Some helpful compiler hints for compilers that allow them; GCC for now. // // BX_CPP_AlignN(n): // Align a construct on an n-byte boundary. // // BX_CPP_AttrPrintf(formatArg, firstArg): // This function takes printf-like arguments, so the compiler can check // the consistency of the format string and the matching arguments. // 'formatArg' is the parameter number (starting from 1) of the format // string argument. 'firstArg' is the parameter number of the 1st argument // to check against the string argument. NOTE: For non-static member // functions, the this-ptr is argument number 1 but is invisible on // the function prototype declaration - but you still have to count it. // // BX_CPP_AttrNoReturn(): // This function never returns. The compiler can optimize-out following // code accordingly. #define BX_CPP_AlignN(n) __attribute__ ((aligned (n))) #define BX_CPP_AttrPrintf(formatArg, firstArg) \ __attribute__ ((format (printf, formatArg, firstArg))) #define BX_CPP_AttrNoReturn() __attribute__ ((noreturn)) #else #define BX_CPP_AlignN(n) /* Not supported. */ #define BX_CPP_AttrPrintf(formatArg, firstArg) /* Not supported. */ #define BX_CPP_AttrNoReturn() /* Not supported. */ #endif #define BX_GDBSTUB 0 #define BX_DEBUGGER 0 #define BX_DISASM 0 #define BX_DEBUGGER_GUI 0 #if (BX_DEBUGGER == 1) && (BX_DISASM == 0) #error Dissembler is required for BX_DEBUGGER ! #endif #define BX_INSTRUMENTATION 0 // enable BX_DEBUG/BX_ERROR/BX_INFO messages #define BX_NO_LOGGING 0 // enable BX_ASSERT checks #define BX_ASSERT_ENABLE 0 // limited i440FX PCI support #define BX_SUPPORT_PCI 0 // CLGD54XX emulation #define BX_SUPPORT_CLGD54XX 0 // Experimental host PCI device mapping #define BX_SUPPORT_PCIDEV 0 #if (BX_SUPPORT_PCIDEV && !BX_SUPPORT_PCI) #error To enable PCI host device mapping, you must also enable PCI #endif // USB host controllers #define BX_SUPPORT_USB_UHCI 0 #define BX_SUPPORT_USB_OHCI 0 #define BX_SUPPORT_USB_XHCI 0 #define BX_SUPPORT_PCIUSB (BX_SUPPORT_USB_UHCI || BX_SUPPORT_USB_OHCI || BX_SUPPORT_USB_XHCI) #if (BX_SUPPORT_PCIUSB && !BX_SUPPORT_PCI) #error To enable USB, you must also enable PCI #endif // Experimental bus mouse support #define BX_SUPPORT_BUSMOUSE 0 #define BX_SUPPORT_ALIGNMENT_CHECK 0 #define BX_SUPPORT_FPU 0 #define BX_SUPPORT_3DNOW 0 #define BX_SUPPORT_MISALIGNED_SSE 0 #define BX_SUPPORT_MONITOR_MWAIT 0 #define BX_SUPPORT_SVM 0 #define BX_SUPPORT_VMX 0 #define BX_SUPPORT_AVX 0 #if BX_SUPPORT_SVM && BX_SUPPORT_X86_64 == 0 #error "SVM require x86-64 support" #endif #if BX_SUPPORT_VMX >= 2 && BX_SUPPORT_X86_64 == 0 #error "VMXx2 require x86-64 support" #endif #if BX_SUPPORT_AVX && BX_SUPPORT_X86_64 == 0 #error "AVX require x86-64 support" #endif #define BX_SUPPORT_REPEAT_SPEEDUPS 0 #define BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS 0 #if (BX_DEBUGGER || BX_GDBSTUB) && BX_SUPPORT_HANDLERS_CHAINING_SPEEDUPS #error "Handler-chaining-speedups are not supported together with internal debugger or gdb-stub!" #endif #if BX_SUPPORT_3DNOW #define BX_CPU_VENDOR_INTEL 0 #else #define BX_CPU_VENDOR_INTEL 1 #endif // Maximum CPUID vendor and brand string lengths #define BX_CPUID_VENDOR_LEN 12 #define BX_CPUID_BRAND_LEN 48 #define BX_CONFIGURE_MSRS 0 #if (BX_SUPPORT_ALIGNMENT_CHECK && BX_CPU_LEVEL < 4) #error Alignment exception check is not supported in i386 ! #endif #if (BX_CONFIGURE_MSRS && BX_CPU_LEVEL < 5) #error MSRs are supported only with CPU level >= 5 ! #endif #if (!BX_SUPPORT_FPU && BX_CPU_LEVEL > 4) #error With CPU level > 4, you must enable FPU support ! #endif #if (BX_SUPPORT_FPU && BX_CPU_LEVEL < 3) #error "FPU cannot be compiled without cpu level >= 3 !" #endif #if (BX_CPU_LEVEL<6 && BX_SUPPORT_VMX) #error "VMX only supported with CPU_LEVEL >= 6 !" #endif #if BX_SUPPORT_X86_64 // Sanity checks to ensure that you cannot accidently use conflicting options. #if BX_CPU_LEVEL < 6 #error "X86-64 requires cpu level 6 or greater !" #endif #endif // We have tested the following combinations: // * processors=1, bootstrap=0, ioapic_id=1 (uniprocessor system) // * processors=2, bootstrap=0, ioapic_id=2 // * processors=4, bootstrap=0, ioapic_id=4 // * processors=8, bootstrap=0, ioapic_id=8 #define BX_SUPPORT_SMP 0 #define BX_BOOTSTRAP_PROCESSOR 0 // For P6 and Pentium family processors the local APIC ID feild is 4 bits // APIC_MAX_ID indicate broadcast so it can't be used as valid APIC ID #define BX_MAX_SMP_THREADS_SUPPORTED 0xfe /* leave APIC ID for I/O APIC */ // include in APIC models, required for a multiprocessor system. #if BX_SUPPORT_SMP || BX_CPU_LEVEL >= 5 #define BX_SUPPORT_APIC 1 #else #define BX_SUPPORT_APIC 0 #endif #define BX_HAVE_GETENV 0 #define BX_HAVE_SETENV 0 #define BX_HAVE_SELECT 0 #define BX_HAVE_SNPRINTF 0 #define BX_HAVE_VSNPRINTF 0 #define BX_HAVE_STRTOULL 0 #define BX_HAVE_STRTOUQ 0 #define BX_HAVE_STRDUP 0 #define BX_HAVE_STRREV 0 #define BX_HAVE_STRICMP 0 #define BX_HAVE_STRCASECMP 0 // used in term gui #define BX_HAVE_COLOR_SET 0 #define BX_HAVE_MVHLINE 0 #define BX_HAVE_MVVLINE 0 // set if your compiler does not understand __attribute__ after a struct #define BX_NO_ATTRIBUTES 0 #if BX_NO_ATTRIBUTES #define GCC_ATTRIBUTE(x) /* attribute not supported */ #else #define GCC_ATTRIBUTE __attribute__ #endif // set to use fast function calls #define BX_FAST_FUNC_CALL 0 // On gcc2.95+ x86 only #if BX_FAST_FUNC_CALL && defined(__i386__) && defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)) #if BX_USE_CPU_SMF == 1 # define BX_CPP_AttrRegparmN(X) __attribute__((regparm(X))) #else // FIXME: BX_FAST_FUNC_CALL doesn't work with BX_USE_CPU_SMF = 0 # define BX_CPP_AttrRegparmN(X) /* Not defined */ #endif #else # define BX_CPP_AttrRegparmN(X) /* Not defined */ #endif // set if you do have , used in bx_debug/dbg_main.c #define BX_HAVE_SET 0 // set if you do have , used in bx_debug/dbg_main.c #define BX_HAVE_SET_H 0 // set if you do have , used in bx_debug/dbg_main.c #define BX_HAVE_MAP 0 // set if you do have , used in bx_debug/dbg_main.c #define BX_HAVE_MAP_H 0 // Support x86 hardware debugger registers and facilities. // These are the debug facilities offered by the x86 architecture, // not the optional built-in debugger. #define BX_X86_DEBUGGER 0 #define BX_SUPPORT_CDROM 0 #if BX_SUPPORT_CDROM // This is the C++ class name to use if we are supporting // low-level CDROM. # define LOWLEVEL_CDROM cdrom_interface #endif // NE2K network emulation #define BX_SUPPORT_NE2K 0 // Pseudo PCI NIC #define BX_SUPPORT_PCIPNIC 0 #if (BX_SUPPORT_PCIPNIC && !BX_SUPPORT_PCI) #error To enable the PCI pseudo NIC, you must also enable PCI #endif // Intel(R) Gigabit Ethernet #define BX_SUPPORT_E1000 0 #if (BX_SUPPORT_E1000 && !BX_SUPPORT_PCI) #error To enable the E1000 NIC, you must also enable PCI #endif // this enables the lowlevel stuff below if one of the NICs is present #define BX_NETWORKING 0 // which networking modules will be enabled // determined by configure script #define BX_NETMOD_FBSD 0 #define BX_NETMOD_LINUX 0 #define BX_NETMOD_WIN32 0 #define BX_NETMOD_TAP 0 #define BX_NETMOD_TUNTAP 0 #define BX_NETMOD_VDE 0 #define BX_NETMOD_SLIRP 0 // Soundcard and gameport support #define BX_SUPPORT_SB16 0 #define BX_SUPPORT_ES1370 0 #define BX_SUPPORT_GAMEPORT 0 #define BX_SUPPORT_SOUNDLOW 0 #if BX_SUPPORT_SOUNDLOW // Determines which sound lowlevel class is to be used. // Currently the following are available: // bx_sound_linux_c Output for Linux, to /dev/dsp and /dev/midi00 // or ALSA PCM and sequencer interface // bx_sound_windows_c Output for Windows midi and wave mappers // bx_sound_osx_c Output for MacOSX midi and wave device // bx_sound_lowlevel_c Dummy functions, no output #define BX_SOUND_LOWLEVEL_C bx_sound_lowlevel_c // Use ALSA sound interface on Linux #define BX_HAVE_ALSASOUND 0 #endif #if (BX_SUPPORT_ES1370 && !BX_SUPPORT_PCI) #error To enable the ES1370 soundcard, you must also enable PCI #endif // I/O Interface to debugger #define BX_SUPPORT_IODEBUG 0 #ifdef WIN32 #define BX_FLOPPY0_NAME "Floppy Disk A:" #define BX_FLOPPY1_NAME "Floppy Disk B:" #else #define BX_FLOPPY0_NAME "Floppy Disk 0" #define BX_FLOPPY1_NAME "Floppy Disk 1" #endif #if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ == 0) #error "gcc 4.0.0 is known to produce incorrect code which breaks Bochs emulation" #endif #endif // _BX_CONFIG_H